mirror of
https://github.com/reactos/reactos.git
synced 2024-12-03 00:13:32 +08:00
[SHELL32] Implement and use SHOpenPropSheet (#7432)
- Implement SHOpenPropSheetW. - Reuse already opened propertysheets and format dialogs by finding the existing unique stub window. - Default .lnk property dialog to the shortcut tab.
This commit is contained in:
parent
53f498c968
commit
2aadf2eb26
@ -46,14 +46,18 @@ HRESULT STDMETHODCALLTYPE CFolderOptions::AddPages(LPFNSVADDPROPSHEETPAGE pfnAdd
|
||||
HPROPSHEETPAGE hPage;
|
||||
LPARAM sheetparam = (LPARAM)static_cast<CFolderOptions*>(this);
|
||||
|
||||
hPage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, sheetparam, NULL);
|
||||
if (hPage == NULL)
|
||||
hPage = SH_CreatePropertySheetPageEx(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg,
|
||||
sheetparam, NULL, &PropSheetPageLifetimeCallback<CFolderOptions>);
|
||||
HRESULT hr = AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
ERR("Failed to create property sheet page FolderOptionsGeneral\n");
|
||||
return E_FAIL;
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRef(); // For PropSheetPageLifetimeCallback
|
||||
}
|
||||
if (!pfnAddPage(hPage, lParam))
|
||||
return E_FAIL;
|
||||
|
||||
hPage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, sheetparam, NULL);
|
||||
if (hPage == NULL)
|
||||
|
@ -31,7 +31,7 @@ list(APPEND SOURCE
|
||||
dialogs/filedefext.cpp
|
||||
dialogs/filetypes.cpp
|
||||
dialogs/folder_options.cpp
|
||||
dialogs/fprop.cpp
|
||||
dialogs/item_prop.cpp
|
||||
dialogs/general.cpp
|
||||
dialogs/recycler_prop.cpp
|
||||
dialogs/view.cpp
|
||||
@ -40,6 +40,7 @@ list(APPEND SOURCE
|
||||
CExtractIcon.cpp
|
||||
folders.cpp
|
||||
iconcache.cpp
|
||||
propsheet.cpp
|
||||
shell32.cpp
|
||||
utils.cpp
|
||||
CShellItem.cpp
|
||||
|
@ -2903,10 +2903,13 @@ BOOL CShellLink::OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
|
||||
ASSERT(FAILED(hr) || !(path[0] == ':' && path[1] == ':' && path[2] == '{'));
|
||||
}
|
||||
}
|
||||
EnableWindow(GetDlgItem(hwndDlg, IDC_SHORTCUT_TARGET_TEXT), !disablecontrols);
|
||||
|
||||
HWND hWndTarget = GetDlgItem(hwndDlg, IDC_SHORTCUT_TARGET_TEXT);
|
||||
EnableWindow(hWndTarget, !disablecontrols);
|
||||
PostMessage(hWndTarget, EM_SETSEL, 0, -1); // Fix caret bug when first opening the tab
|
||||
|
||||
/* auto-completion */
|
||||
SHAutoComplete(GetDlgItem(hwndDlg, IDC_SHORTCUT_TARGET_TEXT), SHACF_DEFAULT);
|
||||
SHAutoComplete(hWndTarget, SHACF_DEFAULT);
|
||||
SHAutoComplete(GetDlgItem(hwndDlg, IDC_SHORTCUT_START_IN_EDIT), SHACF_DEFAULT);
|
||||
|
||||
m_bInInit = FALSE;
|
||||
@ -3095,17 +3098,15 @@ CShellLink::SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM l
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CShellLink::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
HPROPSHEETPAGE hPage = SH_CreatePropertySheetPage(IDD_SHORTCUT_PROPERTIES, SH_ShellLinkDlgProc, (LPARAM)this, NULL);
|
||||
if (hPage == NULL)
|
||||
{
|
||||
ERR("failed to create property sheet page\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (!pfnAddPage(hPage, lParam))
|
||||
return E_FAIL;
|
||||
|
||||
return S_OK;
|
||||
HPROPSHEETPAGE hPage = SH_CreatePropertySheetPageEx(IDD_SHORTCUT_PROPERTIES, SH_ShellLinkDlgProc,
|
||||
(LPARAM)this, NULL, &PropSheetPageLifetimeCallback<CShellLink>);
|
||||
HRESULT hr = AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
else
|
||||
AddRef(); // For PropSheetPageLifetimeCallback
|
||||
enum { CShellLink_PageIndex_Shortcut = 0 };
|
||||
return 1 + CShellLink_PageIndex_Shortcut; // Make this page the default (one-based)
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CShellLink::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
|
||||
|
@ -32,9 +32,6 @@ typedef struct
|
||||
BOOL bFormattingNow;
|
||||
} FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;
|
||||
|
||||
EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
|
||||
HPROPSHEETPAGE SH_CreatePropertySheetPage(LPCSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle);
|
||||
|
||||
/*
|
||||
* TODO: In Windows the Shell doesn't know by itself if a drive is
|
||||
* a system one or not but rather a packet message is being sent by
|
||||
@ -159,125 +156,6 @@ GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNum
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _DRIVE_PROP_PAGE
|
||||
{
|
||||
LPCSTR resname;
|
||||
DLGPROC dlgproc;
|
||||
UINT DriveType;
|
||||
} DRIVE_PROP_PAGE;
|
||||
|
||||
struct DRIVE_PROP_DATA
|
||||
{
|
||||
PWSTR pwszDrive;
|
||||
IStream *pStream;
|
||||
};
|
||||
|
||||
static DWORD WINAPI
|
||||
ShowDrivePropThreadProc(LPVOID pParam)
|
||||
{
|
||||
CHeapPtr<DRIVE_PROP_DATA, CComAllocator> pPropData((DRIVE_PROP_DATA *)pParam);
|
||||
CHeapPtr<WCHAR, CComAllocator> pwszDrive(pPropData->pwszDrive);
|
||||
|
||||
// Unmarshall IDataObject from IStream
|
||||
CComPtr<IDataObject> pDataObj;
|
||||
CoGetInterfaceAndReleaseStream(pPropData->pStream, IID_PPV_ARG(IDataObject, &pDataObj));
|
||||
|
||||
HPSXA hpsx = NULL;
|
||||
HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE];
|
||||
CComObject<CDrvDefExt> *pDrvDefExt = NULL;
|
||||
|
||||
CDataObjectHIDA cida(pDataObj);
|
||||
if (FAILED_UNEXPECTEDLY(cida.hr()))
|
||||
return FAILED(cida.hr());
|
||||
|
||||
RECT rcPosition = {CW_USEDEFAULT, CW_USEDEFAULT, 0, 0};
|
||||
POINT pt;
|
||||
if (SUCCEEDED(DataObject_GetOffset(pDataObj, &pt)))
|
||||
{
|
||||
rcPosition.left = pt.x;
|
||||
rcPosition.top = pt.y;
|
||||
}
|
||||
|
||||
DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
|
||||
DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
|
||||
CStubWindow32 stub;
|
||||
if (!stub.Create(NULL, rcPosition, NULL, style, exstyle))
|
||||
{
|
||||
ERR("StubWindow32 creation failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PROPSHEETHEADERW psh = {sizeof(PROPSHEETHEADERW)};
|
||||
psh.dwFlags = PSH_PROPTITLE;
|
||||
psh.pszCaption = pwszDrive;
|
||||
psh.hwndParent = stub;
|
||||
psh.nStartPage = 0;
|
||||
psh.phpage = hpsp;
|
||||
|
||||
HRESULT hr = CComObject<CDrvDefExt>::CreateInstance(&pDrvDefExt);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pDrvDefExt->AddRef(); // CreateInstance returns object with 0 ref count
|
||||
hr = pDrvDefExt->Initialize(HIDA_GetPIDLFolder(cida), pDataObj, NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pDrvDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
|
||||
if (FAILED(hr))
|
||||
ERR("AddPages failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Initialize failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE, pDataObj);
|
||||
if (hpsx)
|
||||
SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageCallback, (LPARAM)&psh);
|
||||
|
||||
INT_PTR ret = PropertySheetW(&psh);
|
||||
|
||||
if (hpsx)
|
||||
SHDestroyPropSheetExtArray(hpsx);
|
||||
if (pDrvDefExt)
|
||||
pDrvDefExt->Release();
|
||||
|
||||
stub.DestroyWindow();
|
||||
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
BOOL
|
||||
SH_ShowDriveProperties(WCHAR *pwszDrive, IDataObject *pDataObj)
|
||||
{
|
||||
HRESULT hr = SHStrDupW(pwszDrive, &pwszDrive);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return FALSE;
|
||||
|
||||
// Prepare data for thread
|
||||
DRIVE_PROP_DATA *pData = (DRIVE_PROP_DATA *)SHAlloc(sizeof(*pData));
|
||||
if (!pData)
|
||||
{
|
||||
SHFree(pwszDrive);
|
||||
return FALSE;
|
||||
}
|
||||
pData->pwszDrive = pwszDrive;
|
||||
|
||||
// Marshall IDataObject to IStream
|
||||
hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObj, &pData->pStream);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Run a property sheet in another thread
|
||||
if (SHCreateThread(ShowDrivePropThreadProc, pData, CTF_COINIT, NULL))
|
||||
return TRUE; // Success
|
||||
|
||||
pData->pStream->Release();
|
||||
}
|
||||
SHFree(pData);
|
||||
SHFree(pwszDrive);
|
||||
return FALSE; // Failed
|
||||
}
|
||||
|
||||
static VOID
|
||||
InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
|
||||
{
|
||||
|
@ -750,12 +750,13 @@ CDrvDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
HPROPSHEETPAGE hPage;
|
||||
|
||||
hPage = SH_CreatePropertySheetPage(IDD_DRIVE_PROPERTIES,
|
||||
GeneralPageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
hPage = SH_CreatePropertySheetPageEx(IDD_DRIVE_PROPERTIES, GeneralPageProc, (LPARAM)this,
|
||||
NULL, &PropSheetPageLifetimeCallback<CDrvDefExt>);
|
||||
HRESULT hr = AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
else
|
||||
AddRef(); // For PropSheetPageLifetimeCallback
|
||||
|
||||
if (GetDriveTypeW(m_wszDrive) == DRIVE_FIXED)
|
||||
{
|
||||
|
@ -290,34 +290,6 @@ SH_FormatFileSizeWithBytes(const PULARGE_INTEGER lpQwSize, LPWSTR pwszResult, UI
|
||||
return pwszResult;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* SH_CreatePropertySheetPage [Internal]
|
||||
*
|
||||
* creates a property sheet page from a resource id
|
||||
*
|
||||
*/
|
||||
|
||||
HPROPSHEETPAGE
|
||||
SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle)
|
||||
{
|
||||
PROPSHEETPAGEW Page;
|
||||
|
||||
memset(&Page, 0x0, sizeof(PROPSHEETPAGEW));
|
||||
Page.dwSize = sizeof(PROPSHEETPAGEW);
|
||||
Page.dwFlags = PSP_DEFAULT;
|
||||
Page.hInstance = shell32_hInstance;
|
||||
Page.pszTemplate = MAKEINTRESOURCE(wDialogId);
|
||||
Page.pfnDlgProc = pfnDlgProc;
|
||||
Page.lParam = lParam;
|
||||
Page.pszTitle = pwszTitle;
|
||||
|
||||
if (pwszTitle)
|
||||
Page.dwFlags |= PSP_USETITLE;
|
||||
|
||||
return CreatePropertySheetPageW(&Page);
|
||||
}
|
||||
|
||||
VOID
|
||||
CFileDefExt::InitOpensWithField(HWND hwndDlg)
|
||||
{
|
||||
@ -1321,12 +1293,13 @@ CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
HPROPSHEETPAGE hPage;
|
||||
WORD wResId = m_bDir ? IDD_FOLDER_PROPERTIES : IDD_FILE_PROPERTIES;
|
||||
|
||||
hPage = SH_CreatePropertySheetPage(wResId,
|
||||
GeneralPageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
hPage = SH_CreatePropertySheetPageEx(wResId, GeneralPageProc, (LPARAM)this, NULL,
|
||||
&PropSheetPageLifetimeCallback<CFileDefExt>);
|
||||
HRESULT hr = AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
else
|
||||
AddRef(); // For PropSheetPageLifetimeCallback
|
||||
|
||||
if (!m_bDir && GetFileVersionInfoSizeW(m_wszPath, NULL))
|
||||
{
|
||||
@ -1334,8 +1307,7 @@ CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
VersionPageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
}
|
||||
|
||||
if (m_bDir)
|
||||
@ -1344,8 +1316,7 @@ CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
FolderCustomizePageProc,
|
||||
(LPARAM)this,
|
||||
NULL);
|
||||
if (hPage)
|
||||
pfnAddPage(hPage, lParam);
|
||||
AddPropSheetPage(hPage, pfnAddPage, lParam);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Shell Library Functions
|
||||
*
|
||||
* Copyright 2005 Johannes Anderwald
|
||||
* Copyright 2012 Rafal Harabien
|
||||
* Copyright 2017-2018 Katayama Hirofumi MZ
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
|
||||
|
||||
static UINT
|
||||
LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPages, HPSXA *phpsxa, IDataObject *pDataObj)
|
||||
{
|
||||
WCHAR wszBuf[MAX_PATH];
|
||||
UINT cPages = 0, i = 0;
|
||||
|
||||
LPWSTR pwszFilename = PathFindFileNameW(pwszPath);
|
||||
BOOL bDir = PathIsDirectoryW(pwszPath);
|
||||
|
||||
if (bDir)
|
||||
{
|
||||
phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Folder", cMaxPages - cPages, pDataObj);
|
||||
cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
|
||||
|
||||
phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Directory", cMaxPages - cPages, pDataObj);
|
||||
cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load property sheet handlers from ext key */
|
||||
LPWSTR pwszExt = PathFindExtensionW(pwszFilename);
|
||||
phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, pwszExt, cMaxPages - cPages, pDataObj);
|
||||
cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
|
||||
|
||||
/* Load property sheet handlers from prog id key */
|
||||
DWORD cbBuf = sizeof(wszBuf);
|
||||
if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &cbBuf) == ERROR_SUCCESS)
|
||||
{
|
||||
TRACE("EnumPropSheetExt wszBuf %s, pwszExt %s\n", debugstr_w(wszBuf), debugstr_w(pwszExt));
|
||||
phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszBuf, cMaxPages - cPages, pDataObj);
|
||||
cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
|
||||
}
|
||||
|
||||
/* Add property sheet handlers from "*" key */
|
||||
phpsxa[i] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"*", cMaxPages - cPages, pDataObj);
|
||||
cPages += SHAddFromPropSheetExtArray(phpsxa[i++], AddPropSheetPageCallback, (LPARAM)pHeader);
|
||||
}
|
||||
|
||||
return cPages;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* SH_ShowPropertiesDialog
|
||||
*
|
||||
* called from ShellExecuteExW32
|
||||
*
|
||||
* pwszPath contains path of folder/file
|
||||
*
|
||||
* TODO: provide button change application type if file has registered type
|
||||
* make filename field editable and apply changes to filename on close
|
||||
*/
|
||||
|
||||
BOOL
|
||||
SH_ShowPropertiesDialog(LPCWSTR pwszPath, IDataObject *pDataObj)
|
||||
{
|
||||
HPSXA hpsxa[3] = {NULL, NULL, NULL};
|
||||
CComObject<CFileDefExt> *pFileDefExt = NULL;
|
||||
|
||||
TRACE("SH_ShowPropertiesDialog entered filename %s\n", debugstr_w(pwszPath));
|
||||
|
||||
if (pwszPath == NULL || !wcslen(pwszPath))
|
||||
return FALSE;
|
||||
|
||||
HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
|
||||
memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
|
||||
|
||||
/* Make a copy of path */
|
||||
WCHAR wszPath[MAX_PATH];
|
||||
StringCbCopyW(wszPath, sizeof(wszPath), pwszPath);
|
||||
|
||||
/* remove trailing \\ at the end of path */
|
||||
PathRemoveBackslashW(wszPath);
|
||||
|
||||
CDataObjectHIDA cida(pDataObj);
|
||||
if (FAILED_UNEXPECTEDLY(cida.hr()))
|
||||
return FALSE;
|
||||
|
||||
if (cida->cidl == 0)
|
||||
{
|
||||
ERR("Empty HIDA\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Handle drives */
|
||||
if (_ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
|
||||
return SH_ShowDriveProperties(wszPath, pDataObj);
|
||||
|
||||
|
||||
RECT rcPosition = {CW_USEDEFAULT, CW_USEDEFAULT, 0, 0};
|
||||
POINT pt;
|
||||
if (SUCCEEDED(DataObject_GetOffset(pDataObj, &pt)))
|
||||
{
|
||||
rcPosition.left = pt.x;
|
||||
rcPosition.top = pt.y;
|
||||
}
|
||||
|
||||
DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
|
||||
DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
|
||||
CStubWindow32 stub;
|
||||
if (!stub.Create(NULL, rcPosition, NULL, style, exstyle))
|
||||
{
|
||||
ERR("StubWindow32 creation failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Handle files and folders */
|
||||
PROPSHEETHEADERW Header;
|
||||
memset(&Header, 0x0, sizeof(PROPSHEETHEADERW));
|
||||
Header.dwSize = sizeof(PROPSHEETHEADERW);
|
||||
Header.hwndParent = stub;
|
||||
Header.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
|
||||
Header.phpage = hppages;
|
||||
Header.pszCaption = PathFindFileNameW(wszPath);
|
||||
|
||||
HRESULT hr = CComObject<CFileDefExt>::CreateInstance(&pFileDefExt);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pFileDefExt->AddRef(); // CreateInstance returns object with 0 ref count
|
||||
hr = pFileDefExt->Initialize(HIDA_GetPIDLFolder(cida), pDataObj, NULL);
|
||||
if (!FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
hr = pFileDefExt->AddPages(AddPropSheetPageCallback, (LPARAM)&Header);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
ERR("AddPages failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Initialize failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
LoadPropSheetHandlers(wszPath, &Header, MAX_PROPERTY_SHEET_PAGE - 1, hpsxa, pDataObj);
|
||||
|
||||
INT_PTR Result = PropertySheetW(&Header);
|
||||
|
||||
for (UINT i = 0; i < 3; ++i)
|
||||
if (hpsxa[i])
|
||||
SHDestroyPropSheetExtArray(hpsxa[i]);
|
||||
if (pFileDefExt)
|
||||
pFileDefExt->Release();
|
||||
|
||||
stub.DestroyWindow();
|
||||
|
||||
return (Result != -1);
|
||||
}
|
||||
|
||||
/*EOF */
|
179
dll/win32/shell32/dialogs/item_prop.cpp
Normal file
179
dll/win32/shell32/dialogs/item_prop.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* PROJECT: shell32
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: FileSystem PropertySheet implementation
|
||||
* COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
static HRESULT
|
||||
SHELL_GetCaptionFromDataObject(IDataObject *pDO, LPWSTR Buf, UINT cchBuf)
|
||||
{
|
||||
HRESULT hr = E_INVALIDARG;
|
||||
if (PIDLIST_ABSOLUTE pidl = SHELL_DataObject_ILCloneFullItem(pDO, 0))
|
||||
{
|
||||
hr = SHGetNameAndFlagsW(pidl, SHGDN_INFOLDER, Buf, cchBuf, NULL);
|
||||
ILFree(pidl);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
struct ShellPropSheetDialog
|
||||
{
|
||||
typedef void (CALLBACK*PFNINITIALIZE)(LPCWSTR InitString, IDataObject *pDO,
|
||||
HKEY *hKeys, UINT *cKeys);
|
||||
|
||||
static HRESULT Show(const CLSID *pClsidDefault, IDataObject *pDO,
|
||||
PFNINITIALIZE InitFunc, LPCWSTR InitString)
|
||||
{
|
||||
HRESULT hr;
|
||||
CRegKeyHandleArray keys;
|
||||
if (InitFunc)
|
||||
InitFunc(InitString, pDO, keys, keys);
|
||||
WCHAR szCaption[MAX_PATH], *pszCaption = NULL;
|
||||
if (SUCCEEDED(SHELL_GetCaptionFromDataObject(pDO, szCaption, _countof(szCaption))))
|
||||
pszCaption = szCaption;
|
||||
hr = SHOpenPropSheetW(pszCaption, keys, keys, pClsidDefault, pDO, NULL, NULL) ? S_OK : E_FAIL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
struct DATA
|
||||
{
|
||||
PFNINITIALIZE InitFunc;
|
||||
LPWSTR InitString;
|
||||
CLSID ClsidDefault;
|
||||
const CLSID *pClsidDefault;
|
||||
IStream *pObjStream;
|
||||
};
|
||||
|
||||
static void FreeData(DATA *pData)
|
||||
{
|
||||
if (pData->InitString)
|
||||
SHFree(pData->InitString);
|
||||
SHFree(pData);
|
||||
}
|
||||
|
||||
static HRESULT ShowAsync(const CLSID *pClsidDefault, IDataObject *pDO,
|
||||
PFNINITIALIZE InitFunc, LPCWSTR InitString)
|
||||
{
|
||||
DATA *pData = (DATA*)SHAlloc(sizeof(*pData));
|
||||
if (!pData)
|
||||
return E_OUTOFMEMORY;
|
||||
ZeroMemory(pData, sizeof(*pData));
|
||||
pData->InitFunc = InitFunc;
|
||||
if (InitString && FAILED(SHStrDupW(InitString, &pData->InitString)))
|
||||
{
|
||||
FreeData(pData);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (pClsidDefault)
|
||||
{
|
||||
pData->ClsidDefault = *pClsidDefault;
|
||||
pData->pClsidDefault = &pData->ClsidDefault;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (pDO)
|
||||
hr = CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDO, &pData->pObjStream);
|
||||
|
||||
const UINT flags = CTF_COINIT | CTF_PROCESS_REF | CTF_INSIST;
|
||||
if (SUCCEEDED(hr) && !SHCreateThread(ShowPropertiesThread, pData, flags, NULL))
|
||||
{
|
||||
if (pData->pObjStream)
|
||||
pData->pObjStream->Release();
|
||||
hr = E_FAIL;
|
||||
}
|
||||
if (FAILED(hr))
|
||||
FreeData(pData);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static DWORD CALLBACK ShowPropertiesThread(LPVOID Param)
|
||||
{
|
||||
DATA *pData = (DATA*)Param;
|
||||
CComPtr<IDataObject> pDO;
|
||||
if (pData->pObjStream)
|
||||
CoGetInterfaceAndReleaseStream(pData->pObjStream, IID_PPV_ARG(IDataObject, &pDO));
|
||||
Show(pData->pClsidDefault, pDO, pData->InitFunc, pData->InitString);
|
||||
FreeData(pData);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
static void CALLBACK
|
||||
FSFolderItemPropDialogInitCallback(LPCWSTR InitString, IDataObject *pDO, HKEY *hKeys, UINT *cKeys)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(InitString);
|
||||
CDataObjectHIDA cida(pDO);
|
||||
if (SUCCEEDED(cida.hr()) && cida->cidl)
|
||||
{
|
||||
PCUITEMID_CHILD pidl = HIDA_GetPIDLItem(cida, 0);
|
||||
AddFSClassKeysToArray(1, &pidl, hKeys, cKeys); // Add file-type specific pages
|
||||
}
|
||||
}
|
||||
|
||||
static void CALLBACK
|
||||
ClassPropDialogInitCallback(LPCWSTR InitString, IDataObject *pDO, HKEY *hKeys, UINT *cKeys)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pDO);
|
||||
AddClassKeyToArray(InitString, hKeys, cKeys); // Add pages from HKCR\%ProgId% (with shellex\PropertySheetHandlers appended later)
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL32_ShowFilesystemItemPropertiesDialogAsync(IDataObject *pDO)
|
||||
{
|
||||
CDataObjectHIDA cida(pDO);
|
||||
HRESULT hr = cida.hr();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
const CLSID *pClsid = NULL;
|
||||
ShellPropSheetDialog::PFNINITIALIZE InitFunc = NULL;
|
||||
LPCWSTR InitString = NULL;
|
||||
|
||||
if (_ILIsDrive(HIDA_GetPIDLItem(cida, 0)))
|
||||
{
|
||||
pClsid = &CLSID_ShellDrvDefExt;
|
||||
InitFunc = ClassPropDialogInitCallback;
|
||||
InitString = L"Drive";
|
||||
}
|
||||
else
|
||||
{
|
||||
pClsid = &CLSID_ShellFileDefExt;
|
||||
InitFunc = FSFolderItemPropDialogInitCallback;
|
||||
}
|
||||
ShellPropSheetDialog Dialog;
|
||||
return Dialog.ShowAsync(pClsid, pDO, InitFunc, InitString);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL32_ShowShellExtensionProperties(const CLSID *pClsid, IDataObject *pDO)
|
||||
{
|
||||
WCHAR ClassBuf[6 + 38 + 1] = L"CLSID\\";
|
||||
StringFromGUID2(*pClsid, ClassBuf + 6, 38 + 1);
|
||||
ShellPropSheetDialog Dialog;
|
||||
return Dialog.ShowAsync(NULL, pDO, ClassPropDialogInitCallback, ClassBuf);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_ShowItemIDListProperties(LPCITEMIDLIST pidl)
|
||||
{
|
||||
assert(pidl);
|
||||
|
||||
CComHeapPtr<ITEMIDLIST> alloc;
|
||||
if (IS_INTRESOURCE(pidl))
|
||||
{
|
||||
HRESULT hr = SHGetSpecialFolderLocation(NULL, LOWORD(pidl), const_cast<LPITEMIDLIST*>(&pidl));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
alloc.Attach(const_cast<LPITEMIDLIST>(pidl));
|
||||
}
|
||||
SHELLEXECUTEINFOA sei = {
|
||||
sizeof(sei), SEE_MASK_INVOKEIDLIST | SEE_MASK_ASYNCOK, NULL, "properties",
|
||||
NULL, NULL, NULL, SW_SHOWNORMAL, NULL, const_cast<LPITEMIDLIST>(pidl)
|
||||
};
|
||||
return ShellExecuteExA(&sei) ? S_OK : HResultFromWin32(GetLastError());
|
||||
}
|
@ -401,30 +401,8 @@ RecycleBinDlg(
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SH_ShowRecycleBinProperties(WCHAR sDrive)
|
||||
HRESULT RecycleBin_AddPropSheetPages(LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
HPROPSHEETPAGE hpsp[1];
|
||||
PROPSHEETHEADERW psh;
|
||||
HPROPSHEETPAGE hprop;
|
||||
INT_PTR ret;
|
||||
|
||||
ZeroMemory(&psh, sizeof(psh));
|
||||
psh.dwSize = sizeof(psh);
|
||||
psh.dwFlags = PSP_DEFAULT | PSH_PROPTITLE;
|
||||
psh.pszCaption = MAKEINTRESOURCEW(IDS_RECYCLEBIN_FOLDER_NAME);
|
||||
psh.hwndParent = NULL;
|
||||
psh.phpage = hpsp;
|
||||
psh.hInstance = shell32_hInstance;
|
||||
|
||||
hprop = SH_CreatePropertySheetPage(IDD_RECYCLE_BIN_PROPERTIES, RecycleBinDlg, (LPARAM)sDrive, NULL);
|
||||
if (!hprop)
|
||||
{
|
||||
ERR("Failed to create property sheet\n");
|
||||
return FALSE;
|
||||
}
|
||||
hpsp[psh.nPages] = hprop;
|
||||
psh.nPages++;
|
||||
|
||||
ret = PropertySheetW(&psh);
|
||||
return (ret >= 0);
|
||||
HPROPSHEETPAGE hpsp = SH_CreatePropertySheetPage(IDD_RECYCLE_BIN_PROPERTIES, RecycleBinDlg, 0, NULL);
|
||||
return AddPropSheetPage(hpsp, pfnAddPage, lParam);
|
||||
}
|
||||
|
@ -186,117 +186,22 @@ static BOOL DoEjectDrive(const WCHAR *physical, UINT nDriveType, INT *pnStringID
|
||||
return bResult;
|
||||
}
|
||||
|
||||
// A callback function for finding the stub windows.
|
||||
static BOOL CALLBACK
|
||||
EnumStubProc(HWND hwnd, LPARAM lParam)
|
||||
static DWORD CALLBACK DoFormatDriveThread(LPVOID args)
|
||||
{
|
||||
CSimpleArray<HWND> *pStubs = reinterpret_cast<CSimpleArray<HWND> *>(lParam);
|
||||
|
||||
WCHAR szClass[64];
|
||||
GetClassNameW(hwnd, szClass, _countof(szClass));
|
||||
|
||||
if (lstrcmpiW(szClass, L"StubWindow32") == 0)
|
||||
{
|
||||
pStubs->Add(hwnd);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Another callback function to find the owned window of the stub window.
|
||||
static BOOL CALLBACK
|
||||
EnumStubProc2(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
HWND *phwnd = reinterpret_cast<HWND *>(lParam);
|
||||
|
||||
if (phwnd[0] == GetWindow(hwnd, GW_OWNER))
|
||||
{
|
||||
phwnd[1] = hwnd;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Parameters for format_drive_thread function below.
|
||||
struct THREAD_PARAMS
|
||||
{
|
||||
UINT nDriveNumber;
|
||||
};
|
||||
|
||||
static unsigned __stdcall format_drive_thread(void *args)
|
||||
{
|
||||
THREAD_PARAMS *params = (THREAD_PARAMS *)args;
|
||||
UINT nDriveNumber = params->nDriveNumber;
|
||||
LONG_PTR nProp = nDriveNumber | 0x7F00;
|
||||
|
||||
// Search the stub windows that already exist.
|
||||
CSimpleArray<HWND> old_stubs;
|
||||
EnumWindows(EnumStubProc, (LPARAM)&old_stubs);
|
||||
|
||||
for (INT n = 0; n < old_stubs.GetSize(); ++n)
|
||||
{
|
||||
HWND hwndStub = old_stubs[n];
|
||||
|
||||
// The target stub window has the prop.
|
||||
if (GetPropW(hwndStub, L"DriveNumber") == (HANDLE)nProp)
|
||||
{
|
||||
// Found.
|
||||
HWND ahwnd[2];
|
||||
ahwnd[0] = hwndStub;
|
||||
ahwnd[1] = NULL;
|
||||
EnumWindows(EnumStubProc2, (LPARAM)ahwnd);
|
||||
|
||||
// Activate.
|
||||
BringWindowToTop(ahwnd[1]);
|
||||
|
||||
delete params;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a stub window.
|
||||
DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
|
||||
DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
|
||||
UINT nDrive = PtrToUlong(args);
|
||||
WCHAR szPath[] = { LOWORD(L'A' + nDrive), L'\0' }; // Arbitrary, just needs to include nDrive
|
||||
CStubWindow32 stub;
|
||||
if (!stub.Create(NULL, NULL, NULL, style, exstyle))
|
||||
{
|
||||
ERR("StubWindow32 creation failed\n");
|
||||
delete params;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add prop to the target stub window.
|
||||
SetPropW(stub, L"DriveNumber", (HANDLE)nProp);
|
||||
|
||||
// Do format.
|
||||
SHFormatDrive(stub, nDriveNumber, SHFMT_ID_DEFAULT, 0);
|
||||
|
||||
// Clean up.
|
||||
RemovePropW(stub, L"DriveNumber");
|
||||
stub.DestroyWindow();
|
||||
delete params;
|
||||
|
||||
return 0;
|
||||
HRESULT hr = stub.CreateStub(CStubWindow32::TYPE_FORMATDRIVE, szPath, NULL);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
SHFormatDrive(stub, nDrive, SHFMT_ID_DEFAULT, 0);
|
||||
return stub.DestroyWindow();
|
||||
}
|
||||
|
||||
static HRESULT DoFormatDrive(HWND hwnd, UINT nDriveNumber)
|
||||
static HRESULT DoFormatDriveAsync(HWND hwnd, UINT nDrive)
|
||||
{
|
||||
THREAD_PARAMS *params = new THREAD_PARAMS;
|
||||
params->nDriveNumber = nDriveNumber;
|
||||
|
||||
// Create thread to avoid locked.
|
||||
unsigned tid;
|
||||
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, format_drive_thread, params, 0, &tid);
|
||||
if (hThread == NULL)
|
||||
{
|
||||
delete params;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CloseHandle(hThread);
|
||||
|
||||
return S_OK;
|
||||
BOOL succ = SHCreateThread(DoFormatDriveThread, UlongToPtr(nDrive), CTF_PROCESS_REF, NULL);
|
||||
return succ ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
|
||||
@ -388,20 +293,15 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf,
|
||||
|
||||
if (wParam == DFM_CMD_PROPERTIES)
|
||||
{
|
||||
// pdtobj should be valid at this point!
|
||||
ATLASSERT(pdtobj);
|
||||
hr = SH_ShowDriveProperties(wszBuf, pdtobj) ? S_OK : E_UNEXPECTED;
|
||||
if (FAILED(hr))
|
||||
{
|
||||
dwError = ERROR_CAN_NOT_COMPLETE;
|
||||
nStringID = IDS_CANTSHOWPROPERTIES;
|
||||
}
|
||||
hr = SHELL32_ShowFilesystemItemPropertiesDialogAsync(pdtobj);
|
||||
// Not setting nStringID because SHOpenPropSheet already displayed an error box
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wParam == CMDID_FORMAT)
|
||||
{
|
||||
hr = DoFormatDrive(hwnd, szDrive[0] - 'A');
|
||||
hr = DoFormatDriveAsync(hwnd, szDrive[0] - 'A');
|
||||
}
|
||||
else if (wParam == CMDID_EJECT)
|
||||
{
|
||||
|
@ -1959,25 +1959,7 @@ HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObjec
|
||||
{
|
||||
if (uMsg == DFM_INVOKECOMMAND && wParam == IDC_PROPERTIES)
|
||||
{
|
||||
// Create an data object
|
||||
CComHeapPtr<ITEMID_CHILD> pidlChild(ILClone(ILFindLastID(m_pidlRoot)));
|
||||
CComHeapPtr<ITEMIDLIST> pidlParent(ILClone(m_pidlRoot));
|
||||
ILRemoveLastID(pidlParent);
|
||||
|
||||
CComPtr<IDataObject> pDataObj;
|
||||
HRESULT hr = SHCreateDataObject(pidlParent, 1, &pidlChild.m_pData, NULL, IID_PPV_ARG(IDataObject, &pDataObj));
|
||||
if (!FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
// Ask for a title to display
|
||||
CComHeapPtr<WCHAR> wszName;
|
||||
if (!FAILED_UNEXPECTEDLY(SHGetNameFromIDList(m_pidlRoot, SIGDN_PARENTRELATIVEPARSING, &wszName)))
|
||||
{
|
||||
BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObj);
|
||||
if (!bSuccess)
|
||||
ERR("SH_ShowPropertiesDialog failed\n");
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
return SHELL_ShowItemIDListProperties(m_pidlRoot);
|
||||
}
|
||||
else if (uMsg == DFM_MERGECONTEXTMENU)
|
||||
{
|
||||
|
@ -919,9 +919,8 @@ HRESULT WINAPI CRecycleBin::GetCommandString(UINT_PTR idCommand, UINT uFlags, UI
|
||||
|
||||
HRESULT WINAPI CRecycleBin::AddPages(LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
FIXME("%p %p %lu\n", this, pfnAddPage, lParam);
|
||||
|
||||
return E_NOTIMPL;
|
||||
extern HRESULT RecycleBin_AddPropSheetPages(LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
|
||||
return RecycleBin_AddPropSheetPages(pfnAddPage, lParam);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRecycleBin::ReplacePage(EXPPS uPageID, LPFNSVADDPROPSHEETPAGE pfnReplaceWith, LPARAM lParam)
|
||||
|
@ -881,6 +881,7 @@ static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwn
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
const CLSID* pCLSID;
|
||||
CRegFolder *pRegFolder = static_cast<CRegFolder*>(psf);
|
||||
const REQUIREDREGITEM* pRequired = pRegFolder->IsRequiredItem(apidl[0]);
|
||||
if (pRequired && pRequired->pszCpl)
|
||||
@ -895,10 +896,17 @@ static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwn
|
||||
hr = SHELL_ExecuteControlPanelCPL(hwnd, L"desk.cpl") ? S_OK : E_FAIL;
|
||||
}
|
||||
#endif
|
||||
else if (_ILIsDesktop(pidlFolder) && _ILIsBitBucket(apidl[0]))
|
||||
else if ((pCLSID = pRegFolder->IsRegItem(apidl[0])) != NULL)
|
||||
{
|
||||
FIXME("Use SHOpenPropSheet on Recyclers PropertySheetHandlers from the registry\n");
|
||||
hr = SH_ShowRecycleBinProperties(L'C') ? S_OK : E_FAIL;
|
||||
if (CLSID_MyDocuments != *pCLSID)
|
||||
{
|
||||
hr = SHELL32_ShowShellExtensionProperties(pCLSID, pdtobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("ROS MyDocs must implement IShellPropSheetExt\n");
|
||||
hr = S_FALSE; // Just display the filesystem properties
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -126,10 +126,10 @@ extern const GUID CLSID_UnixDosFolder;
|
||||
extern const GUID SHELL32_AdvtShortcutProduct;
|
||||
extern const GUID SHELL32_AdvtShortcutComponent;
|
||||
|
||||
#define MAX_PROPERTY_SHEET_PAGE 32
|
||||
|
||||
#define VERBKEY_CCHMAX 64 // Note: 63+\0 seems to be the limit on XP
|
||||
|
||||
#define MAX_PROPERTY_SHEET_PAGE 32
|
||||
|
||||
extern inline
|
||||
BOOL
|
||||
CALLBACK
|
||||
@ -146,8 +146,36 @@ AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
AddPropSheetPage(HPROPSHEETPAGE hPage, LPFNSVADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
|
||||
{
|
||||
if (!hPage)
|
||||
return E_FAIL;
|
||||
if (pfnAddPage(hPage, lParam))
|
||||
return S_OK;
|
||||
DestroyPropertySheetPage(hPage);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
template<class T> static UINT CALLBACK
|
||||
PropSheetPageLifetimeCallback(HWND hWnd, UINT uMsg, PROPSHEETPAGEW *pPSP)
|
||||
{
|
||||
if (uMsg == PSPCB_RELEASE)
|
||||
((T*)(pPSP->lParam))->Release();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EXTERN_C HRESULT WINAPI
|
||||
SHMultiFileProperties(IDataObject *pDataObject, DWORD dwFlags);
|
||||
HRESULT
|
||||
SHELL32_ShowPropertiesDialog(IDataObject *pdtobj);
|
||||
HRESULT
|
||||
SHELL32_ShowFilesystemItemPropertiesDialogAsync(IDataObject *pDO);
|
||||
HRESULT
|
||||
SHELL32_ShowShellExtensionProperties(const CLSID *pClsid, IDataObject *pDO);
|
||||
HRESULT
|
||||
SHELL_ShowItemIDListProperties(LPCITEMIDLIST pidl);
|
||||
|
||||
HRESULT
|
||||
SHELL32_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdo, UINT msg);
|
||||
UINT
|
||||
@ -167,12 +195,29 @@ static inline UINT SeeFlagsToCmicFlags(UINT flags)
|
||||
|
||||
// CStubWindow32 --- The owner window of file property sheets.
|
||||
// This window hides taskbar button of property sheet.
|
||||
#define CSTUBWINDOW32_CLASSNAME _T("StubWindow32")
|
||||
class CStubWindow32 : public CWindowImpl<CStubWindow32>
|
||||
{
|
||||
static HWND FindStubWindow(UINT Type, LPCWSTR Path);
|
||||
public:
|
||||
DECLARE_WND_CLASS_EX(_T("StubWindow32"), 0, COLOR_WINDOWTEXT)
|
||||
DECLARE_WND_CLASS_EX(CSTUBWINDOW32_CLASSNAME, 0, COLOR_WINDOWTEXT)
|
||||
enum {
|
||||
TYPE_FORMATDRIVE = 1,
|
||||
TYPE_PROPERTYSHEET,
|
||||
};
|
||||
static LPCWSTR GetTypePropName() { return L"StubType"; }
|
||||
HRESULT CreateStub(UINT Type, LPCWSTR Path, const POINT *pPt);
|
||||
|
||||
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
||||
{
|
||||
if (HICON hIco = (HICON)SendMessage(WM_SETICON, ICON_BIG, NULL))
|
||||
DestroyIcon(hIco);
|
||||
::RemovePropW(m_hWnd, GetTypePropName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
BEGIN_MSG_MAP(CStubWindow32)
|
||||
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
|
||||
END_MSG_MAP()
|
||||
};
|
||||
|
||||
|
211
dll/win32/shell32/propsheet.cpp
Normal file
211
dll/win32/shell32/propsheet.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* PROJECT: shell32
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: SHOpenPropSheetW implementation
|
||||
* COPYRIGHT: Copyright 2024 Whindmar Saksit <whindsaks@proton.me>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
static HRESULT
|
||||
SHELL_GetShellExtensionRegCLSID(HKEY hKey, LPCWSTR KeyName, CLSID &clsid)
|
||||
{
|
||||
// First try the key name
|
||||
if (SUCCEEDED(SHCLSIDFromStringW(KeyName, &clsid)))
|
||||
return S_OK;
|
||||
WCHAR buf[42];
|
||||
DWORD cb = sizeof(buf);
|
||||
// and then the default value
|
||||
DWORD err = RegGetValueW(hKey, KeyName, NULL, RRF_RT_REG_SZ, NULL, buf, &cb);
|
||||
return !err ? SHCLSIDFromStringW(buf, &clsid) : HRESULT_FROM_WIN32(err);
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHELL_InitializeExtension(REFCLSID clsid, PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pDO, HKEY hkeyProgID, REFIID riid, void **ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
IUnknown *pUnk;
|
||||
HRESULT hr = SHCoCreateInstance(NULL, &clsid, NULL, riid, (void**)&pUnk);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
CComPtr<IShellExtInit> Init;
|
||||
hr = pUnk->QueryInterface(IID_PPV_ARG(IShellExtInit, &Init));
|
||||
if (SUCCEEDED(hr))
|
||||
hr = Init->Initialize(pidlFolder, pDO, hkeyProgID);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
*ppv = (void*)pUnk;
|
||||
else
|
||||
pUnk->Release();
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
AddPropSheetHandlerPages(REFCLSID clsid, IDataObject *pDO, HKEY hkeyProgID, PROPSHEETHEADERW &psh)
|
||||
{
|
||||
CComPtr<IShellPropSheetExt> SheetExt;
|
||||
HRESULT hr = SHELL_InitializeExtension(clsid, NULL, pDO, hkeyProgID, IID_PPV_ARG(IShellPropSheetExt, &SheetExt));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT OldCount = psh.nPages;
|
||||
hr = SheetExt->AddPages(AddPropSheetPageCallback, (LPARAM)&psh);
|
||||
// The returned index is one-based (relative to this extension).
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellpropsheetext-addpages
|
||||
if (hr > 0)
|
||||
{
|
||||
hr += OldCount;
|
||||
psh.nStartPage = hr - 1;
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHELL_CreatePropSheetStubWindow(CStubWindow32 &stub, PCIDLIST_ABSOLUTE pidl, const POINT *pPt)
|
||||
{
|
||||
PWSTR Path;
|
||||
if (!pidl || FAILED(SHGetNameFromIDList(pidl, SIGDN_DESKTOPABSOLUTEPARSING, &Path)))
|
||||
Path = NULL; // If we can't get a path, we simply will not be able to reuse this window
|
||||
|
||||
HRESULT hr = stub.CreateStub(CStubWindow32::TYPE_PROPERTYSHEET, Path, pPt);
|
||||
SHFree(Path);
|
||||
UINT flags = SHGFI_ICON | SHGFI_ADDOVERLAYS;
|
||||
SHFILEINFO sfi;
|
||||
if (SUCCEEDED(hr) && SHGetFileInfoW((LPWSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | flags))
|
||||
stub.SendMessage(WM_SETICON, ICON_BIG, (LPARAM)sfi.hIcon);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHELL32_PropertySheet [INTERNAL]
|
||||
* PropertySheetW with stub window.
|
||||
*/
|
||||
static INT_PTR
|
||||
SHELL32_PropertySheet(LPPROPSHEETHEADERW ppsh, IDataObject *pDO)
|
||||
{
|
||||
CStubWindow32 stub;
|
||||
POINT pt, *ppt = NULL;
|
||||
if (pDO && SUCCEEDED(DataObject_GetOffset(pDO, &pt)))
|
||||
ppt = &pt;
|
||||
PIDLIST_ABSOLUTE pidl = SHELL_DataObject_ILCloneFullItem(pDO, 0);
|
||||
HRESULT hr = SHELL_CreatePropSheetStubWindow(stub, pidl, ppt);
|
||||
ILFree(pidl);
|
||||
if (FAILED(hr))
|
||||
return hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) ? 0 : -1;
|
||||
|
||||
INT_PTR Result = -1;
|
||||
ppsh->hwndParent = stub;
|
||||
if (ppsh->nPages)
|
||||
{
|
||||
Result = PropertySheetW(ppsh);
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR szFormat[128], szMessage[_countof(szFormat) + 42];
|
||||
LoadStringW(shell32_hInstance, IDS_CANTSHOWPROPERTIES, szFormat, _countof(szFormat));
|
||||
wsprintfW(szMessage, szFormat, ERROR_CAN_NOT_COMPLETE);
|
||||
MessageBoxW(NULL, szMessage, NULL, MB_ICONERROR);
|
||||
}
|
||||
stub.DestroyWindow();
|
||||
return Result;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHELL32_OpenPropSheet [INTERNAL]
|
||||
* The real implementation of SHOpenPropSheetW.
|
||||
*/
|
||||
static BOOL
|
||||
SHELL32_OpenPropSheet(LPCWSTR pszCaption, HKEY *ahKeys, UINT cKeys,
|
||||
const CLSID *pclsidDefault, IDataObject *pDO, LPCWSTR pStartPage)
|
||||
{
|
||||
HKEY hKeyProgID = cKeys ? ahKeys[cKeys - 1] : NULL; // Windows uses the last key for some reason
|
||||
HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
|
||||
PROPSHEETHEADERW psh = { sizeof(psh), PSH_PROPTITLE };
|
||||
psh.phpage = hppages;
|
||||
psh.hInstance = shell32_hInstance;
|
||||
psh.pszCaption = pszCaption;
|
||||
psh.pStartPage = pStartPage;
|
||||
|
||||
if (pclsidDefault)
|
||||
AddPropSheetHandlerPages(*pclsidDefault, pDO, hKeyProgID, psh);
|
||||
|
||||
for (UINT i = 0; i < cKeys; ++i)
|
||||
{
|
||||
// Note: We can't use SHCreatePropSheetExtArrayEx because we need the AddPages() return value (see AddPropSheetHandlerPages).
|
||||
HKEY hKey;
|
||||
if (RegOpenKeyExW(ahKeys[i], L"shellex\\PropertySheetHandlers", 0, KEY_ENUMERATE_SUB_KEYS, &hKey))
|
||||
continue;
|
||||
for (UINT index = 0;; ++index)
|
||||
{
|
||||
WCHAR KeyName[MAX_PATH];
|
||||
LRESULT err = RegEnumKeyW(hKey, index, KeyName, _countof(KeyName));
|
||||
KeyName[_countof(KeyName)-1] = UNICODE_NULL;
|
||||
if (err == ERROR_MORE_DATA)
|
||||
continue;
|
||||
if (err)
|
||||
break;
|
||||
CLSID clsid;
|
||||
if (SUCCEEDED(SHELL_GetShellExtensionRegCLSID(hKey, KeyName, clsid)))
|
||||
AddPropSheetHandlerPages(clsid, pDO, hKeyProgID, psh);
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
if (pStartPage == psh.pStartPage && pStartPage)
|
||||
psh.dwFlags |= PSH_USEPSTARTPAGE;
|
||||
INT_PTR Result = SHELL32_PropertySheet(&psh, pDO);
|
||||
return (Result != -1);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHOpenPropSheetW [SHELL32.80]
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj/nf-shlobj-shopenpropsheetw
|
||||
*/
|
||||
EXTERN_C BOOL WINAPI
|
||||
SHOpenPropSheetW(
|
||||
_In_opt_ LPCWSTR pszCaption,
|
||||
_In_opt_ HKEY *ahKeys,
|
||||
_In_ UINT cKeys,
|
||||
_In_ const CLSID *pclsidDefault,
|
||||
_In_ IDataObject *pDataObject,
|
||||
_In_opt_ IShellBrowser *pShellBrowser,
|
||||
_In_opt_ LPCWSTR pszStartPage)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pShellBrowser); /* MSDN says "Not used". */
|
||||
return SHELL32_OpenPropSheet(pszCaption, ahKeys, cKeys, pclsidDefault, pDataObject, pszStartPage);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SH_CreatePropertySheetPage [Internal]
|
||||
*
|
||||
* creates a property sheet page from a resource id
|
||||
*/
|
||||
HPROPSHEETPAGE
|
||||
SH_CreatePropertySheetPageEx(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam,
|
||||
LPCWSTR pwszTitle, LPFNPSPCALLBACK Callback)
|
||||
{
|
||||
PROPSHEETPAGEW Page = { sizeof(Page), PSP_DEFAULT, shell32_hInstance };
|
||||
Page.pszTemplate = MAKEINTRESOURCEW(wDialogId);
|
||||
Page.pfnDlgProc = pfnDlgProc;
|
||||
Page.lParam = lParam;
|
||||
Page.pszTitle = pwszTitle;
|
||||
Page.pfnCallback = Callback;
|
||||
|
||||
if (pwszTitle)
|
||||
Page.dwFlags |= PSP_USETITLE;
|
||||
|
||||
if (Callback)
|
||||
Page.dwFlags |= PSP_USECALLBACK;
|
||||
|
||||
return CreatePropertySheetPageW(&Page);
|
||||
}
|
||||
|
||||
HPROPSHEETPAGE
|
||||
SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle)
|
||||
{
|
||||
return SH_CreatePropertySheetPageEx(wDialogId, pfnDlgProc, lParam, pwszTitle, NULL);
|
||||
}
|
@ -275,6 +275,8 @@ BEGIN_OBJECT_MAP(ObjectMap)
|
||||
OBJECT_ENTRY(CLSID_ShellFSFolder, CFSFolder)
|
||||
OBJECT_ENTRY(CLSID_MyComputer, CDrivesFolder)
|
||||
OBJECT_ENTRY(CLSID_ShellDesktop, CDesktopFolder)
|
||||
OBJECT_ENTRY(CLSID_ShellFileDefExt, CFileDefExt)
|
||||
OBJECT_ENTRY(CLSID_ShellDrvDefExt, CDrvDefExt)
|
||||
OBJECT_ENTRY(CLSID_ShellItem, CShellItem)
|
||||
OBJECT_ENTRY(CLSID_ShellLink, CShellLink)
|
||||
OBJECT_ENTRY(CLSID_Shell, CShellDispatch)
|
||||
|
@ -126,8 +126,6 @@ HRESULT SHELL32_BindToSF (LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* pp
|
||||
extern "C"
|
||||
BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
|
||||
|
||||
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys);
|
||||
|
||||
HRESULT CDefViewBckgrndMenu_CreateInstance(IShellFolder* psf, REFIID riid, void **ppv);
|
||||
|
||||
HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl);
|
||||
@ -156,11 +154,26 @@ static __inline int SHELL32_GUIDToStringW (REFGUID guid, LPWSTR str)
|
||||
void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags);
|
||||
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
||||
|
||||
void CloseRegKeyArray(HKEY* array, UINT cKeys);
|
||||
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
||||
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys);
|
||||
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
struct CRegKeyHandleArray
|
||||
{
|
||||
HKEY hKeys[16];
|
||||
UINT cKeys;
|
||||
|
||||
CRegKeyHandleArray() : cKeys(0) {}
|
||||
~CRegKeyHandleArray() { CloseRegKeyArray(hKeys, cKeys); }
|
||||
operator HKEY*() { return hKeys; }
|
||||
operator UINT*() { return &cKeys; }
|
||||
operator UINT() { return cKeys; }
|
||||
HKEY& operator [](SIZE_T i) { return hKeys[i]; }
|
||||
};
|
||||
|
||||
HRESULT inline SHSetStrRet(LPSTRRET pStrRet, DWORD resId)
|
||||
{
|
||||
return SHSetStrRet(pStrRet, shell32_hInstance, resId);
|
||||
|
@ -106,6 +106,8 @@ PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index)
|
||||
|
||||
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index)
|
||||
{
|
||||
if (!pDO)
|
||||
return NULL;
|
||||
CDataObjectHIDA cida(pDO);
|
||||
return SUCCEEDED(cida.hr()) ? SHELL_CIDA_ILCloneFull(cida, Index) : NULL;
|
||||
}
|
||||
|
@ -302,6 +302,12 @@ HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST
|
||||
return MAKE_COMPARE_HRESULT(ret);
|
||||
}
|
||||
|
||||
void CloseRegKeyArray(HKEY* array, UINT cKeys)
|
||||
{
|
||||
for (UINT i = 0; i < cKeys; ++i)
|
||||
RegCloseKey(array[i]);
|
||||
}
|
||||
|
||||
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys)
|
||||
{
|
||||
if (*cKeys >= 16)
|
||||
@ -495,36 +501,6 @@ SHOpenFolderAndSelectItems(PCIDLIST_ABSOLUTE pidlFolder,
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static
|
||||
DWORD WINAPI
|
||||
_ShowPropertiesDialogThread(LPVOID lpParameter)
|
||||
{
|
||||
CComPtr<IDataObject> pDataObject;
|
||||
pDataObject.Attach((IDataObject*)lpParameter);
|
||||
|
||||
CDataObjectHIDA cida(pDataObject);
|
||||
|
||||
if (FAILED_UNEXPECTEDLY(cida.hr()))
|
||||
return cida.hr();
|
||||
|
||||
if (cida->cidl > 1)
|
||||
{
|
||||
ERR("SHMultiFileProperties is not yet implemented\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CComHeapPtr<ITEMIDLIST> completePidl(ILCombine(HIDA_GetPIDLFolder(cida), HIDA_GetPIDLItem(cida, 0)));
|
||||
CComHeapPtr<WCHAR> wszName;
|
||||
if (FAILED_UNEXPECTEDLY(SHGetNameFromIDList(completePidl, SIGDN_PARENTRELATIVEPARSING, &wszName)))
|
||||
return 0;
|
||||
|
||||
BOOL bSuccess = SH_ShowPropertiesDialog(wszName, pDataObject);
|
||||
if (!bSuccess)
|
||||
ERR("SH_ShowPropertiesDialog failed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* for internal use
|
||||
*/
|
||||
@ -534,16 +510,15 @@ SHELL32_ShowPropertiesDialog(IDataObject *pdtobj)
|
||||
if (!pdtobj)
|
||||
return E_INVALIDARG;
|
||||
|
||||
pdtobj->AddRef();
|
||||
if (!SHCreateThread(_ShowPropertiesDialogThread, pdtobj, CTF_INSIST | CTF_COINIT | CTF_PROCESS_REF, NULL))
|
||||
CDataObjectHIDA cida(pdtobj);
|
||||
if (FAILED_UNEXPECTEDLY(cida.hr()))
|
||||
return cida.hr();
|
||||
if (cida->cidl > 1)
|
||||
{
|
||||
pdtobj->Release();
|
||||
return HResultFromWin32(GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
ERR("SHMultiFileProperties is not yet implemented\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
return SHELL32_ShowFilesystemItemPropertiesDialogAsync(pdtobj);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
@ -210,25 +210,6 @@ SHGetSetFolderCustomSettingsA(LPSHFOLDERCUSTOMSETTINGSA pfcs,
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHOpenPropSheetW [SHELL32.80]
|
||||
*
|
||||
* @see https://learn.microsoft.com/en-us/windows/win32/api/shlobj/nf-shlobj-shopenpropsheetw
|
||||
*/
|
||||
BOOL WINAPI
|
||||
SHOpenPropSheetW(
|
||||
_In_opt_ LPCWSTR pszCaption,
|
||||
_In_opt_ HKEY *ahKeys,
|
||||
_In_ UINT cKeys,
|
||||
_In_ const CLSID *pclsidDefault,
|
||||
_In_ IDataObject *pDataObject,
|
||||
_In_opt_ IShellBrowser *pShellBrowser,
|
||||
_In_opt_ LPCWSTR pszStartPage)
|
||||
{
|
||||
FIXME("SHOpenPropSheetW() stub\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unimplemented
|
||||
*/
|
||||
|
@ -9,6 +9,39 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
HWND
|
||||
CStubWindow32::FindStubWindow(UINT Type, LPCWSTR Path)
|
||||
{
|
||||
for (HWND hWnd, hWndAfter = NULL;;)
|
||||
{
|
||||
hWnd = hWndAfter = FindWindowExW(NULL, hWndAfter, CSTUBWINDOW32_CLASSNAME, Path);
|
||||
if (!hWnd || !Path)
|
||||
return NULL;
|
||||
if (GetPropW(hWnd, GetTypePropName()) == ULongToHandle(Type))
|
||||
return hWnd;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CStubWindow32::CreateStub(UINT Type, LPCWSTR Path, const POINT *pPt)
|
||||
{
|
||||
if (HWND hWnd = FindStubWindow(Type, Path))
|
||||
{
|
||||
::SwitchToThisWindow(::GetLastActivePopup(hWnd), TRUE);
|
||||
return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
||||
}
|
||||
RECT rcPosition = { pPt ? pPt->x : CW_USEDEFAULT, pPt ? pPt->y : CW_USEDEFAULT, 0, 0 };
|
||||
DWORD Style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION;
|
||||
DWORD ExStyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW;
|
||||
if (!Create(NULL, rcPosition, Path, Style, ExStyle))
|
||||
{
|
||||
ERR("StubWindow32 creation failed\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
::SetPropW(*this, GetTypePropName(), ULongToHandle(Type));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHILClone(
|
||||
_In_opt_ LPCITEMIDLIST pidl,
|
||||
|
@ -198,12 +198,9 @@ HRESULT SHELL_RegisterShellFolders(void) DECLSPEC_HIDDEN;
|
||||
/* Detect Shell Links */
|
||||
BOOL SHELL_IsShortcut(LPCITEMIDLIST) DECLSPEC_HIDDEN;
|
||||
|
||||
INT_PTR CALLBACK SH_FileGeneralDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
INT_PTR CALLBACK SH_FileVersionDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
HPROPSHEETPAGE SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle);
|
||||
BOOL SH_ShowDriveProperties(WCHAR *drive, IDataObject *pDataObj);
|
||||
BOOL SH_ShowRecycleBinProperties(WCHAR sDrive);
|
||||
BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, IDataObject *pDataObj);
|
||||
HPROPSHEETPAGE SH_CreatePropertySheetPageEx(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam,
|
||||
LPCWSTR pwszTitle, LPFNPSPCALLBACK Callback);
|
||||
LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf);
|
||||
|
||||
HRESULT WINAPI DoRegisterServer(void);
|
||||
|
Loading…
Reference in New Issue
Block a user