diff --git a/reactos/dll/win32/shell32/CDefaultContextMenu.cpp b/reactos/dll/win32/shell32/CDefaultContextMenu.cpp index d6b8ba936ce..7f8efa07deb 100644 --- a/reactos/dll/win32/shell32/CDefaultContextMenu.cpp +++ b/reactos/dll/win32/shell32/CDefaultContextMenu.cpp @@ -61,6 +61,8 @@ class CDefaultContextMenu : private: CComPtr m_site; CComPtr m_psf; + CComPtr m_pmcb; + LPFNDFMCALLBACK m_pfnmcb; UINT m_cidl; PCUITEMID_CHILD_ARRAY m_apidl; CComPtr m_pDataObj; @@ -75,6 +77,7 @@ class CDefaultContextMenu : UINT m_iIdSCMFirst; /* first static used id */ UINT m_iIdSCMLast; /* last static used id */ + HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam); void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb); void AddStaticEntriesForKey(HKEY hKey); BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid); @@ -93,7 +96,6 @@ class CDefaultContextMenu : HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy); HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi); - HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici); HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); @@ -106,7 +108,7 @@ class CDefaultContextMenu : public: CDefaultContextMenu(); ~CDefaultContextMenu(); - HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm); + HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn); // IContextMenu virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); @@ -133,6 +135,8 @@ class CDefaultContextMenu : CDefaultContextMenu::CDefaultContextMenu() : m_psf(NULL), + m_pmcb(NULL), + m_pfnmcb(NULL), m_cidl(0), m_apidl(NULL), m_pDataObj(NULL), @@ -180,7 +184,7 @@ CDefaultContextMenu::~CDefaultContextMenu() _ILFreeaPidl(const_cast(m_apidl), m_cidl); } -HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm) +HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn) { TRACE("cidl %u\n", pdcm->cidl); @@ -189,6 +193,8 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm) if (m_cidl && !m_apidl) return E_OUTOFMEMORY; m_psf = pdcm->psf; + m_pmcb = pdcm->pcmcb; + m_pfnmcb = lpfn; m_cKeys = pdcm->cKeys; if (pdcm->cKeys) @@ -219,6 +225,20 @@ HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm) return S_OK; } +HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam) +{ + if (m_pmcb) + { + return m_pmcb->CallBack(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam); + } + else if(m_pfnmcb) + { + return m_pfnmcb(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam); + } + + return S_OK; +} + void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb) { PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL; @@ -712,23 +732,15 @@ CDefaultContextMenu::BuildShellItemContextMenu( IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast); TRACE("IndexMenu %d\n", IndexMenu); - if (_ILIsDrive(m_apidl[0])) - { - char szDrive[8] = {0}; - DWORD dwFlags; - - _ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)); - if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0)) - { - /* Disable format if read only */ - if (!(dwFlags & FILE_READ_ONLY_VOLUME)) - { - _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED); - bAddSep = TRUE; - } - } - } + /* Now let the callback add its own items */ + QCMINFO qcminfo; + qcminfo.hmenu = hMenu; + qcminfo.indexMenu = IndexMenu; + qcminfo.idCmdFirst = iIdCmdFirst; + qcminfo.idCmdLast = iIdCmdLast; + qcminfo.pIdMap = NULL; + _DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo); + IndexMenu = GetMenuItemCount(hMenu); BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM)); if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData) @@ -971,105 +983,8 @@ HRESULT CDefaultContextMenu::DoProperties( LPCMINVOKECOMMANDINFO lpcmi) { - HRESULT hr = S_OK; - const ITEMIDLIST *pidlParent = m_pidlFolder, *pidlChild; + _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL); - if (!pidlParent) - { - CComPtr pf; - - /* pidlFolder is optional */ - if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf)))) - { - pf->GetCurFolder((_ITEMIDLIST**)&pidlParent); - } - } - - if (m_cidl > 0) - pidlChild = m_apidl[0]; - else - { - /* Set pidlChild to last pidl of current folder */ - if (pidlParent == m_pidlFolder) - pidlParent = (ITEMIDLIST*)ILClone(pidlParent); - - pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent)); - ILRemoveLastID((ITEMIDLIST*)pidlParent); - } - - if (_ILIsMyComputer(pidlChild)) - { - if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL)) - hr = E_FAIL; - } - else if (_ILIsDesktop(pidlChild)) - { - if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL)) - hr = E_FAIL; - } - else if (_ILIsDrive(pidlChild)) - { - WCHAR wszBuf[MAX_PATH]; - ILGetDisplayName(pidlChild, wszBuf); - if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild)) - hr = E_FAIL; - } - else if (_ILIsNetHood(pidlChild)) - { - // FIXME path! - if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe", - L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", - NULL, SW_SHOWDEFAULT)) - hr = E_FAIL; - } - else if (_ILIsBitBucket(pidlChild)) - { - /* FIXME: detect the drive path of bitbucket if appropiate */ - if (!SH_ShowRecycleBinProperties(L'C')) - hr = E_FAIL; - } - else - { - if (m_cidl > 1) - WARN("SHMultiFileProperties is not yet implemented\n"); - - STRRET strFile; - hr = m_psf->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strFile); - if (SUCCEEDED(hr)) - { - WCHAR wszBuf[MAX_PATH]; - hr = StrRetToBufW(&strFile, pidlChild, wszBuf, _countof(wszBuf)); - if (SUCCEEDED(hr)) - hr = SH_ShowPropertiesDialog(wszBuf, pidlParent, &pidlChild); - else - ERR("StrRetToBufW failed\n"); - } - else - ERR("IShellFolder_GetDisplayNameOf failed for apidl\n"); - } - - /* Free allocated PIDLs */ - if (pidlParent != m_pidlFolder) - ILFree((ITEMIDLIST*)pidlParent); - if (m_cidl < 1 || pidlChild != m_apidl[0]) - ILFree((ITEMIDLIST*)pidlChild); - - return hr; -} - -HRESULT -CDefaultContextMenu::DoFormat( - LPCMINVOKECOMMANDINFO lpcmi) -{ - char szDrive[8] = {0}; - - if (!_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive))) - { - ERR("pidl is not a drive\n"); - return E_FAIL; - } - - SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0); return S_OK; } @@ -1411,13 +1326,13 @@ CDefaultContextMenu::InvokeCommand( case FCIDM_SHVIEW_PROPERTIES: Result = DoProperties(&LocalInvokeInfo); break; - case 0x7ABC: - Result = DoFormat(&LocalInvokeInfo); - break; case FCIDM_SHVIEW_NEWFOLDER: Result = DoCreateNewFolder(&LocalInvokeInfo); break; default: + + _DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL); + Result = E_UNEXPECTED; break; } @@ -1561,9 +1476,9 @@ CDefaultContextMenu::GetSite(REFIID riid, void **ppvSite) static HRESULT -CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv) +CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn, REFIID riid, void **ppv) { - return ShellObjectCreatorInit(pdcm, riid, ppv); + return ShellObjectCreatorInit(pdcm, lpfn, riid, ppv); } /************************************************************************* @@ -1575,7 +1490,7 @@ HRESULT WINAPI SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv) { - HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, riid, ppv); + HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, NULL, riid, ppv); if (FAILED_UNEXPECTEDLY(hr)) return hr; @@ -1600,18 +1515,18 @@ CDefFolderMenu_Create2( const HKEY *ahkeyClsKeys, IContextMenu **ppcm) { - DEFCONTEXTMENU pdcm; - pdcm.hwnd = hwnd; - pdcm.pcmcb = NULL; - pdcm.pidlFolder = pidlFolder; - pdcm.psf = psf; - pdcm.cidl = cidl; - pdcm.apidl = apidl; - pdcm.punkAssociationInfo = NULL; - pdcm.cKeys = nKeys; - pdcm.aKeys = ahkeyClsKeys; + DEFCONTEXTMENU dcm; + dcm.hwnd = hwnd; + dcm.pcmcb = NULL; + dcm.pidlFolder = pidlFolder; + dcm.psf = psf; + dcm.cidl = cidl; + dcm.apidl = apidl; + dcm.punkAssociationInfo = NULL; + dcm.cKeys = nKeys; + dcm.aKeys = ahkeyClsKeys; - HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm)); + HRESULT hr = CDefaultContextMenu_CreateInstance(&dcm, lpfn, IID_PPV_ARG(IContextMenu, ppcm)); if (FAILED_UNEXPECTEDLY(hr)) return hr; diff --git a/reactos/dll/win32/shell32/dialogs/drive.cpp b/reactos/dll/win32/shell32/dialogs/drive.cpp index 692bea9770a..2f59094251f 100644 --- a/reactos/dll/win32/shell32/dialogs/drive.cpp +++ b/reactos/dll/win32/shell32/dialogs/drive.cpp @@ -123,7 +123,7 @@ typedef struct _DRIVE_PROP_PAGE } DRIVE_PROP_PAGE; BOOL -SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl) +SH_ShowDriveProperties(WCHAR *pwszDrive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl) { HPSXA hpsx = NULL; HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE]; diff --git a/reactos/dll/win32/shell32/dialogs/fprop.cpp b/reactos/dll/win32/shell32/dialogs/fprop.cpp index a2b6ac2ef62..ede236fa853 100644 --- a/reactos/dll/win32/shell32/dialogs/fprop.cpp +++ b/reactos/dll/win32/shell32/dialogs/fprop.cpp @@ -95,7 +95,7 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPage */ BOOL -SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl) +SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl) { HPSXA hpsxa[3] = {NULL, NULL, NULL}; CComObject *pFileDefExt = NULL; diff --git a/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp b/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp index e9dba76f543..6a0a79dfc01 100644 --- a/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp @@ -133,8 +133,8 @@ HRESULT CCPLExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, R CComPtr initIcon; HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); - if (FAILED(hr)) - return NULL; + if (FAILED_UNEXPECTEDLY(hr)) + return hr; initIcon->SetNormalIcon(pData->szName, (int)pData->iconIdx != -1 ? pData->iconIdx : 0); diff --git a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp index d2008c69b95..9262f5fed73 100644 --- a/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -39,6 +39,69 @@ CDrivesFolderEnum is only responsible for returning the physical items. * IShellFolder implementation */ +HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf, + HWND hwnd, + IDataObject *pdtobj, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + if (uMsg != DFM_MERGECONTEXTMENU && uMsg != DFM_INVOKECOMMAND) + return S_OK; + + PIDLIST_ABSOLUTE pidlFolder; + PUITEMID_CHILD *apidl; + UINT cidl; + HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + char szDrive[8] = {0}; + if (!_ILGetDrive(apidl[0], szDrive, sizeof(szDrive))) + { + ERR("pidl is not a drive\n"); + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + return E_FAIL; + } + + if (uMsg == DFM_MERGECONTEXTMENU) + { + QCMINFO *pqcminfo = (QCMINFO *)lParam; + DWORD dwFlags; + + if (GetVolumeInformationA(szDrive, NULL, 0, NULL, NULL, &dwFlags, NULL, 0)) + { + /* Disable format if read only */ + if (!(dwFlags & FILE_READ_ONLY_VOLUME) && GetDriveTypeA(szDrive) != DRIVE_REMOTE) + { + _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED); + } + } + } + else if (uMsg == DFM_INVOKECOMMAND) + { + if(wParam == 0x7ABC) + { + SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0); + } + else if (wParam == DFM_CMD_PROPERTIES) + { + WCHAR wszBuf[4]; + wcscpy(wszBuf, L"A:\\"); + wszBuf[0] = (WCHAR)szDrive[0]; + if (!SH_ShowDriveProperties(wszBuf, pidlFolder, apidl)) + hr = E_FAIL; + } + } + + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + + return hr; +} + HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl, @@ -51,16 +114,15 @@ HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, AddClassKeyToArray(L"Drive", hKeys, &cKeys); AddClassKeyToArray(L"Folder", hKeys, &cKeys); - /* TODO: also pass a callback here */ - return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm); + return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, DrivesContextMenuCallback, cKeys, hKeys, ppcm); } HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut) { CComPtr initIcon; HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); - if (FAILED(hr)) - return NULL; + if (FAILED_UNEXPECTEDLY(hr)) + return hr; CHAR* pszDrive = _ILGetDataPointer(pidl)->u.drive.szDriveName; WCHAR wTemp[MAX_PATH]; diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.cpp b/reactos/dll/win32/shell32/folders/CFSFolder.cpp index 19a2d7466ba..40c72b1e640 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CFSFolder.cpp @@ -489,12 +489,21 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1)) { - IContextMenu * pCm = NULL; HKEY hKeys[16]; UINT cKeys = 0; AddFSClassKeysToArray(apidl[0], hKeys, &cKeys); - hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast(this), NULL, cKeys, hKeys, &pCm); - pObj = pCm; + + DEFCONTEXTMENU dcm; + dcm.hwnd = hwndOwner; + dcm.pcmcb = this; + dcm.pidlFolder = pidlRoot; + dcm.psf = this; + dcm.cidl = cidl; + dcm.apidl = apidl; + dcm.cKeys = cKeys; + dcm.aKeys = hKeys; + dcm.punkAssociationInfo = NULL; + hr = SHCreateDefaultContextMenu (&dcm, riid, &pObj); } else if (IsEqualIID (riid, IID_IDataObject)) { @@ -1088,4 +1097,38 @@ HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandler(const CLSID *pclsid, LPC return hr; } return hr; -} \ No newline at end of file +} + +HRESULT WINAPI CFSFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES) + return S_OK; + + PIDLIST_ABSOLUTE pidlFolder; + PUITEMID_CHILD *apidl; + UINT cidl; + HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (cidl > 1) + ERR("SHMultiFileProperties is not yet implemented\n"); + + STRRET strFile; + hr = GetDisplayNameOf(apidl[0], SHGDN_FORPARSING, &strFile); + if (SUCCEEDED(hr)) + { + hr = SH_ShowPropertiesDialog(strFile.pOleStr, pidlFolder, apidl); + if (FAILED(hr)) + ERR("SH_ShowPropertiesDialog failed\n"); + } + else + { + ERR("Failed to get display name\n"); + } + + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + + return hr; +} diff --git a/reactos/dll/win32/shell32/folders/CFSFolder.h b/reactos/dll/win32/shell32/folders/CFSFolder.h index f76c7246553..40d54d31f2e 100644 --- a/reactos/dll/win32/shell32/folders/CFSFolder.h +++ b/reactos/dll/win32/shell32/folders/CFSFolder.h @@ -27,7 +27,8 @@ class CFSFolder : public CComCoClass, public CComObjectRootEx, public IShellFolder2, - public IPersistFolder3 + public IPersistFolder3, + public IContextMenuCB { private: CLSID *pclsid; @@ -80,6 +81,9 @@ class CFSFolder : virtual HRESULT WINAPI InitializeEx(IBindCtx *pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO *ppfti); virtual HRESULT WINAPI GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO *ppfti); + // IContextMenuCB + virtual HRESULT WINAPI CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam); + DECLARE_REGISTRY_RESOURCEID(IDR_SHELLFSFOLDER) DECLARE_NOT_AGGREGATABLE(CFSFolder) diff --git a/reactos/dll/win32/shell32/folders/CNetFolder.cpp b/reactos/dll/win32/shell32/folders/CNetFolder.cpp index 0644eed5b33..92843311872 100644 --- a/reactos/dll/win32/shell32/folders/CNetFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CNetFolder.cpp @@ -53,8 +53,8 @@ HRESULT CNetFolderExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LP { CComPtr initIcon; HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); - if (FAILED(hr)) - return NULL; + if (FAILED_UNEXPECTEDLY(hr)) + return hr; initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_NETWORK_FOLDER); diff --git a/reactos/dll/win32/shell32/folders/CRecycleBin.cpp b/reactos/dll/win32/shell32/folders/CRecycleBin.cpp index 03b1e002dd4..ba80e3b9ff9 100644 --- a/reactos/dll/win32/shell32/folders/CRecycleBin.cpp +++ b/reactos/dll/win32/shell32/folders/CRecycleBin.cpp @@ -67,8 +67,8 @@ HRESULT CRecyclerExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID riid, LPV { CComPtr initIcon; HRESULT hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit, &initIcon)); - if (FAILED(hr)) - return NULL; + if (FAILED_UNEXPECTEDLY(hr)) + return hr; /* FIXME: This is completely unimplemented */ initIcon->SetNormalIcon(swShell32Name, 0); diff --git a/reactos/dll/win32/shell32/folders/CRegFolder.cpp b/reactos/dll/win32/shell32/folders/CRegFolder.cpp index e595d375865..55d4fa84f5e 100644 --- a/reactos/dll/win32/shell32/folders/CRegFolder.cpp +++ b/reactos/dll/win32/shell32/folders/CRegFolder.cpp @@ -22,6 +22,54 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell); +HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, + HWND hwnd, + IDataObject *pdtobj, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + if (uMsg != DFM_INVOKECOMMAND || wParam != DFM_CMD_PROPERTIES) + return S_OK; + + PIDLIST_ABSOLUTE pidlFolder; + PUITEMID_CHILD *apidl; + UINT cidl; + HRESULT hr = SH_GetApidlFromDataObject(pdtobj, &pidlFolder, &apidl, &cidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (_ILIsMyComputer(apidl[0])) + { + if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL)) + hr = E_FAIL; + } + else if (_ILIsDesktop(apidl[0])) + { + if (32 >= (UINT)ShellExecuteW(hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL)) + hr = E_FAIL; + } + else if (_ILIsNetHood(apidl[0])) + { + // FIXME path! + if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe", + L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", + NULL, SW_SHOWDEFAULT)) + hr = E_FAIL; + } + else if (_ILIsBitBucket(apidl[0])) + { + /* FIXME: detect the drive path of bitbucket if appropiate */ + if (!SH_ShowRecycleBinProperties(L'C')) + hr = E_FAIL; + } + + SHFree(pidlFolder); + _ILFreeaPidl(apidl, cidl); + + return hr; +} + HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl, @@ -48,7 +96,7 @@ HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder, } AddClassKeyToArray(L"Folder", hKeys, &cKeys); - return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm); + return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, RegFolderContextMenuCallback, cKeys, hKeys, ppcm); } HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut) @@ -398,6 +446,10 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast(this), (IContextMenu**)&pObj); } + else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1)) + { + hr = IDataObject_Constructor (hwndOwner, m_pidlRoot, apidl, cidl, (IDataObject **)&pObj); + } else { hr = E_NOINTERFACE; diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index bc373af0cfa..799e96b5525 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -63,6 +63,8 @@ BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey); void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys); +HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl); + static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) { return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", diff --git a/reactos/dll/win32/shell32/shlfolder.cpp b/reactos/dll/win32/shell32/shlfolder.cpp index 114504f815b..00538a239dd 100644 --- a/reactos/dll/win32/shell32/shlfolder.cpp +++ b/reactos/dll/win32/shell32/shlfolder.cpp @@ -547,6 +547,49 @@ void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys) } } +HRESULT SH_GetApidlFromDataObject(IDataObject *pDataObject, PIDLIST_ABSOLUTE* ppidlfolder, PUITEMID_CHILD **apidlItems, UINT *pcidl) +{ + UINT cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); + if (!cfShellIDList) + return E_FAIL; + + FORMATETC fmt; + InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL); + + HRESULT hr = pDataObject->QueryGetData(&fmt); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + STGMEDIUM medium; + hr = pDataObject->GetData(&fmt, &medium); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + /* lock the handle */ + LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal); + if (!lpcida) + { + ReleaseStgMedium(&medium); + return E_FAIL; + } + + /* convert the data into pidl */ + LPITEMIDLIST pidl; + LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + if (!apidl) + { + ReleaseStgMedium(&medium); + return E_OUTOFMEMORY; + } + + *ppidlfolder = pidl; + *apidlItems = apidl; + *pcidl = lpcida->cidl; + + ReleaseStgMedium(&medium); + return S_OK; +} + /*********************************************************************** * SHCreateLinks * diff --git a/reactos/dll/win32/shell32/wine/shell32_main.h b/reactos/dll/win32/shell32/wine/shell32_main.h index 1a74cba6a56..127a5661593 100644 --- a/reactos/dll/win32/shell32/wine/shell32_main.h +++ b/reactos/dll/win32/shell32/wine/shell32_main.h @@ -189,10 +189,9 @@ 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, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl); +BOOL SH_ShowDriveProperties(WCHAR *drive, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl); BOOL SH_ShowRecycleBinProperties(WCHAR sDrive); -BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl); -BOOL SH_ShowFolderProperties(LPWSTR pwszFolder, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST *apidl); +BOOL SH_ShowPropertiesDialog(LPCWSTR pwszPath, LPCITEMIDLIST pidlFolder, PCUITEMID_CHILD_ARRAY apidl); LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT cchBuf); HRESULT WINAPI DoRegisterServer(void);