From e577021a2b347867c8685cecb79b6b34ca655899 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Wed, 20 Aug 2008 13:47:47 +0000 Subject: [PATCH] - Do not pass SHGDN_INFOLDER flag - Implement IPersistFolder2 for control panel shell folder - Replace _InsertMenuItem with unicode - Pass the pidl of shellfolder and selected drive to SH_ShowDriveProperties to construct a valid IDataObject which is passed to drive PropertySheet handlers - Release HPSX array only if it was constructed - Optimize AddShellPropSheetExCallback for file property dialog - Pass the pidl of the parent shell folder and selected item to SH_ShowPropertiesDialog and construct a IDataObject from it - Check for success for created IDataObject and HPSX array - Add a lot of buffer checks for the OpenNew shell extension - Pass the full filename of the item from Admin Tools shellfolder when IShellFolder_GetDisplayNameOf is called with SHGDN_FORPARSING - Implement initializing the AdminTools folder - Implement IShellFolder_SetNameOf for the desktop shell folder to support renaming desktop items and sub folders - Implement ISFHelper interface for desktop shell folder to support deleting with backspace key and fixes the new item shell service for items and directories - Implement hiding (deleting) shell extensions from desktop - Display a messagebox if shell extensions should be really deleted - Fix the IShellFolder_GetAttributesOf for the Mycomputer shell folder - Implement changing drive name with rename verb using IShellFolder_SetNameOf (MyComputer) - Implement Initializing the MyComputer shell folder properly - Fix Shellfolder attributes for MyDocuments shell folder - Fix Shellfolder attributes for Netplaces shell folder - Implement Initializing the Netplaces shell folder properly - Remove the 'properties' and 'open' verb from recycle bin shell folder, these verbs are statically generated - Directories cannot have the link attribute - Implement IShellExtInit interface for the new item shell service - Implement the default context menu based on the existing item context menu and background context menu and delete old implementation - Implement copy&paste of files and directories - Implement creating links to files - Check if a dynamic shell extension has already been loaded - Free static / dynamic shell extensions on release svn path=/trunk/; revision=35476 --- reactos/dll/win32/shell32/autocomplete.c | 2 +- reactos/dll/win32/shell32/cpanelfolder.c | 25 +- reactos/dll/win32/shell32/dialogs.c | 1 + reactos/dll/win32/shell32/drive.c | 33 +- reactos/dll/win32/shell32/folder_options.c | 84 +- reactos/dll/win32/shell32/fprop.c | 91 +- reactos/dll/win32/shell32/pidl.c | 16 + reactos/dll/win32/shell32/she_ocmenu.c | 65 +- reactos/dll/win32/shell32/shell32.rbuild | 3 +- reactos/dll/win32/shell32/shell32_main.h | 8 +- reactos/dll/win32/shell32/shfldr_admintools.c | 34 +- reactos/dll/win32/shell32/shfldr_desktop.c | 313 ++- reactos/dll/win32/shell32/shfldr_fonts.c | 34 +- reactos/dll/win32/shell32/shfldr_mycomp.c | 34 +- .../dll/win32/shell32/shfldr_mydocuments.c | 4 +- reactos/dll/win32/shell32/shfldr_netplaces.c | 19 +- reactos/dll/win32/shell32/shfldr_printers.c | 7 +- reactos/dll/win32/shell32/shfldr_recyclebin.c | 85 +- reactos/dll/win32/shell32/shlexec.c | 6 +- reactos/dll/win32/shell32/shlfileop.c | 2 +- reactos/dll/win32/shell32/shlfolder.c | 5 +- reactos/dll/win32/shell32/shlmenu.c | 16 +- reactos/dll/win32/shell32/shlview.c | 29 +- reactos/dll/win32/shell32/shv_bg_cmenu.c | 500 ----- reactos/dll/win32/shell32/shv_def_cmenu.c | 1726 +++++++++++++++++ reactos/dll/win32/shell32/shv_item_cmenu.c | 1373 ------------- reactos/dll/win32/shell32/shv_item_new.c | 108 +- reactos/dll/win32/shell32/undocshell.h | 4 +- 28 files changed, 2459 insertions(+), 2168 deletions(-) delete mode 100644 reactos/dll/win32/shell32/shv_bg_cmenu.c create mode 100644 reactos/dll/win32/shell32/shv_def_cmenu.c delete mode 100644 reactos/dll/win32/shell32/shv_item_cmenu.c diff --git a/reactos/dll/win32/shell32/autocomplete.c b/reactos/dll/win32/shell32/autocomplete.c index 0e3663fa9db..b25d7449b28 100644 --- a/reactos/dll/win32/shell32/autocomplete.c +++ b/reactos/dll/win32/shell32/autocomplete.c @@ -78,7 +78,7 @@ typedef struct static const IAutoCompleteVtbl acvt; static const IAutoComplete2Vtbl ac2vt; -static inline IAutoCompleteImpl *impl_from_IAutoComplete2( IAutoComplete2 *iface ) +static IAutoCompleteImpl * impl_from_IAutoComplete2( IAutoComplete2 *iface ) { return (IAutoCompleteImpl *)((char*)iface - FIELD_OFFSET(IAutoCompleteImpl, lpvtblAutoComplete2)); } diff --git a/reactos/dll/win32/shell32/cpanelfolder.c b/reactos/dll/win32/shell32/cpanelfolder.c index 36aadb03a06..b00467838d2 100644 --- a/reactos/dll/win32/shell32/cpanelfolder.c +++ b/reactos/dll/win32/shell32/cpanelfolder.c @@ -703,7 +703,7 @@ static HRESULT WINAPI ISF_ControlPanel_fnGetDisplayNameOf(IShellFolder2 * iface, len = lstrlenW(wszPath); if (!SUCCEEDED - (SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_INFOLDER, wszPath + len, MAX_PATH + 1 - len))) + (SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, wszPath + len, MAX_PATH + 1 - len))) return E_OUTOFMEMORY; if (!WideCharToMultiByte(CP_ACP, 0, wszPath, -1, szPath, MAX_PATH, NULL, NULL)) wszPath[0] = '\0'; @@ -907,8 +907,11 @@ static HRESULT WINAPI ICPanel_PersistFolder2_GetClassID(IPersistFolder2 * iface, static HRESULT WINAPI ICPanel_PersistFolder2_Initialize(IPersistFolder2 * iface, LPCITEMIDLIST pidl) { ICPanelImpl *This = impl_from_IPersistFolder2(iface); - TRACE("(%p)->(%p)\n", This, pidl); - return E_NOTIMPL; + if (This->pidlRoot) + SHFree((LPVOID)This->pidlRoot); + + This->pidlRoot = ILClone(pidl); + return S_OK; } /************************************************************************** @@ -1222,7 +1225,7 @@ static HRESULT WINAPI ICPanel_IContextMenu2_QueryContextMenu( UINT idCmdLast, UINT uFlags) { - char szBuffer[30] = {0}; + WCHAR szBuffer[30] = {0}; ULONG Count = 1; ICPanelImpl *This = impl_from_IContextMenu(iface); @@ -1230,22 +1233,22 @@ static HRESULT WINAPI ICPanel_IContextMenu2_QueryContextMenu( TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - if (LoadStringA(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); Count++; } - if (LoadStringA(shell32_hInstance, IDS_CREATELINK, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_CREATELINK, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { if (Count) { - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_SEPARATOR, NULL, MFS_ENABLED); } - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); Count++; } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count); diff --git a/reactos/dll/win32/shell32/dialogs.c b/reactos/dll/win32/shell32/dialogs.c index 05e962c8479..528037b5be3 100644 --- a/reactos/dll/win32/shell32/dialogs.c +++ b/reactos/dll/win32/shell32/dialogs.c @@ -244,6 +244,7 @@ INT_PTR CALLBACK PickIconProc(HWND hwndDlg, DI_NORMAL); break; } + break; } return FALSE; diff --git a/reactos/dll/win32/shell32/drive.c b/reactos/dll/win32/shell32/drive.c index 8f963fc65ab..32de6a50194 100644 --- a/reactos/dll/win32/shell32/drive.c +++ b/reactos/dll/win32/shell32/drive.c @@ -31,6 +31,7 @@ #define NTOS_MODE_USER #define UNICODE #define _UNICODE +#define COBJMACROS #include #include @@ -121,7 +122,7 @@ typedef struct BOOL InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext); BOOL GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes); - +HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj); HWND WINAPI DeviceCreateHardwarePageEx(HWND hWndParent, LPGUID lpGuids, @@ -667,7 +668,7 @@ struct { "DRIVE_HARDWARE_DLG", DriveHardwareDlg }, }; -BOOL +HRESULT CALLBACK AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam) { @@ -681,15 +682,16 @@ AddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam) } BOOL -SH_ShowDriveProperties(WCHAR * drive) +SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl) { - HPSXA hpsx; + HPSXA hpsx = NULL; HPROPSHEETPAGE hpsp[MAX_PROPERTY_SHEET_PAGE]; PROPSHEETHEADERW psh; BOOL ret; UINT i; WCHAR szName[MAX_PATH]; DWORD dwMaxComponent, dwFileSysFlags; + IDataObject * pDataObj = NULL; ZeroMemory(&psh, sizeof(PROPSHEETHEADERW)); psh.dwSize = sizeof(PROPSHEETHEADERW); @@ -721,7 +723,6 @@ SH_ShowDriveProperties(WCHAR * drive) } } - for (i = 0; i < DRIVE_PROPERTY_PAGES; i++) { HPROPSHEETPAGE hprop = SH_CreatePropertySheetPage(PropPages[i].resname, PropPages[i].dlgproc, (LPARAM)drive, NULL); @@ -731,16 +732,22 @@ SH_ShowDriveProperties(WCHAR * drive) psh.nPages++; } } - - hpsx = SHCreatePropSheetExtArray(HKEY_CLASSES_ROOT, - L"Drive", - MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES); - - SHAddFromPropSheetExtArray(hpsx, - (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc, - (LPARAM)&psh); + if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK) + { + hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Drive", MAX_PROPERTY_SHEET_PAGE-DRIVE_PROPERTY_PAGES, pDataObj); + if (hpsx) + { + SHAddFromPropSheetExtArray(hpsx, (LPFNADDPROPSHEETPAGE)AddPropSheetPageProc, (LPARAM)&psh); + } + } ret = PropertySheetW(&psh); + if (pDataObj) + IDataObject_Release(pDataObj); + + if (hpsx) + SHDestroyPropSheetExtArray(hpsx); + if (ret < 0) return FALSE; else diff --git a/reactos/dll/win32/shell32/folder_options.c b/reactos/dll/win32/shell32/folder_options.c index f7fb6c239e0..6b86636ed47 100644 --- a/reactos/dll/win32/shell32/folder_options.c +++ b/reactos/dll/win32/shell32/folder_options.c @@ -60,6 +60,48 @@ typedef struct WCHAR szFolderPath[MAX_PATH]; }FOLDER_PROPERTIES_CONTEXT, *PFOLDER_PROPERTIES_CONTEXT; +typedef struct +{ + LPCWSTR szKeyName; + UINT ResourceID; +}FOLDER_VIEW_ENTRY, PFOLDER_VIEW_ENTRY; +/* +static FOLDER_VIEW_ENTRY s_Options[] = +{ + { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS }, + { L"AutoCheckSelect", -1 }, + { L"ClassicViewState", -1 }, + { L"DontPrettyPath", -1 }, + { L"Filter", -1 }, + { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP }, + { L"FriendlyTree", -1 }, + { L"Hidden", -1, }, + { L"HideFileExt", IDS_HIDEFILEEXT }, + { L"HideIcons", -1}, + { L"IconsOnly", -1}, + { L"ListviewAlphaSelect", -1}, + { L"ListviewShadow", -1}, + { L"ListviewWatermark", -1}, + { L"MapNetDrvBtn", -1}, + { L"PersistBrowsers", -1}, + { L"SeperateProcess", IDS_SEPERATEPROCESS}, + { L"ServerAdminUI", -1}, + { L"SharingWizardOn", IDS_USESHAREWIZARD}, + { L"ShowCompColor", IDS_COMPCOLOR}, + { L"ShowInfoTip", IDS_SHOWINFOTIP}, + { L"ShowPreviewHandlers", -1}, + { L"ShowSuperHidden", IDS_HIDEOSFILES}, + { L"ShowTypeOverlay", -1}, + { L"Start_ShowMyGames", -1}, + { L"StartMenuInit", -1}, + { L"SuperHidden", -1}, + { L"TypeAhead", -1}, + { L"Webview", -1}, + { NULL, -1} + +}; +*/ + INT_PTR CALLBACK @@ -76,6 +118,35 @@ FolderOptionsGeneralDlg( return FALSE; } +static +VOID +InitializeFolderOptionsListCtrl(HWND hwndDlg) +{ + RECT clientRect; + LVCOLUMNW col; + WCHAR szName[50]; + HWND hDlgCtrl; + + hDlgCtrl = GetDlgItem(hwndDlg, 14003); + + if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR))) + szName[0] = 0; + szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0; + + GetClientRect(hDlgCtrl, &clientRect); + ZeroMemory(&col, sizeof(LV_COLUMN)); + col.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT; + col.iSubItem = 0; + col.pszText = szName; + col.fmt = LVCFMT_LEFT; + col.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL); + (void)ListView_InsertColumnW(hDlgCtrl, 0, &col); + + + +} + + INT_PTR CALLBACK FolderOptionsViewDlg( @@ -85,10 +156,15 @@ FolderOptionsViewDlg( LPARAM lParam ) { - - + switch(uMsg) + { + case WM_INITDIALOG: + InitializeFolderOptionsListCtrl(hwndDlg); + return TRUE; + } return FALSE; + } VOID @@ -173,12 +249,9 @@ InitializeFileTypesListCtrl(HWND hwndDlg) DWORD dwName; INT iItem = 0; - hDlgCtrl = GetDlgItem(hwndDlg, 14000); InitializeFileTypesListCtrlColumns(hDlgCtrl); - - dwName = sizeof(szName) / sizeof(WCHAR); while(RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) @@ -206,7 +279,6 @@ FolderOptionsFileTypesDlg( return TRUE; } - return FALSE; } diff --git a/reactos/dll/win32/shell32/fprop.c b/reactos/dll/win32/shell32/fprop.c index 6cb44310181..2a72394649f 100644 --- a/reactos/dll/win32/shell32/fprop.c +++ b/reactos/dll/win32/shell32/fprop.c @@ -650,24 +650,19 @@ SH_FileGeneralDlgProc( BOOL CALLBACK AddShellPropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam) { - UINT iIndex; - HPROPSHEETPAGE * hppages = (HPROPSHEETPAGE *)lParam; + PROPSHEETHEADERW *pinfo = (PROPSHEETHEADERW *)lParam; - TRACE("AddShellPropSheetExCallback called\n"); - for(iIndex = 0; iIndex < MAX_PROPERTY_SHEET_PAGE; iIndex++) + if (pinfo->nPages < MAX_PROPERTY_SHEET_PAGE) { - if (hppages[iIndex] == NULL) - { - hppages[iIndex] = hPage; - return TRUE; - } + pinfo->u3.phpage[pinfo->nPages++] = hPage; + return TRUE; } return FALSE; } int -EnumPropSheetExt(LPWSTR wFileName, HPROPSHEETPAGE * hppages, int NumPages, HPSXA * hpsxa, IDataObject *pDataObj) +EnumPropSheetExt(LPWSTR wFileName, PROPSHEETHEADERW *pinfo, int NumPages, HPSXA * hpsxa, IDataObject *pDataObj) { WCHAR szName[100]; WCHAR * pOffset; @@ -702,7 +697,7 @@ EnumPropSheetExt(LPWSTR wFileName, HPROPSHEETPAGE * hppages, int NumPages, HPSXA } TRACE("EnumPropSheetExt szName %s\n", debugstr_w(szName)); hpsxa[0] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, szName, NumPages, pDataObj); - Pages = SHAddFromPropSheetExtArray(hpsxa[0], AddShellPropSheetExCallback, (LPARAM)hppages); + Pages = SHAddFromPropSheetExtArray(hpsxa[0], AddShellPropSheetExCallback, (LPARAM)pinfo); if (pOffset) @@ -714,7 +709,7 @@ EnumPropSheetExt(LPWSTR wFileName, HPROPSHEETPAGE * hppages, int NumPages, HPSXA TRACE("EnumPropSheetExt szName %s, pOffset %s\n", debugstr_w(szName), debugstr_w(pOffset)); szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0'; hpsxa[1] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, szName, NumPages - Pages, pDataObj); - Pages +=SHAddFromPropSheetExtArray(hpsxa[1], AddShellPropSheetExCallback, (LPARAM)hppages); + Pages +=SHAddFromPropSheetExtArray(hpsxa[1], AddShellPropSheetExCallback, (LPARAM)pinfo); } } return Pages; @@ -735,19 +730,15 @@ EnumPropSheetExt(LPWSTR wFileName, HPROPSHEETPAGE * hppages, int NumPages, HPSXA */ BOOL -SH_ShowPropertiesDialog(PCWSTR lpf) +SH_ShowPropertiesDialog(WCHAR * lpf, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl) { PROPSHEETHEADERW pinfo; HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE]; - HPROPSHEETPAGE hpage; WCHAR wFileName[MAX_PATH]; - UINT num_pages = 0; DWORD dwHandle = 0; WCHAR * pFileName; HPSXA hpsxa[2]; INT_PTR res; - LPITEMIDLIST pidlChild, pidlFolder; - WCHAR szTemp[MAX_PATH]; IDataObject* pDataObj = NULL; HRESULT hResult; @@ -783,45 +774,9 @@ SH_ShowPropertiesDialog(PCWSTR lpf) if (wcslen(wFileName) == 3) { - return SH_ShowDriveProperties(wFileName); + return SH_ShowDriveProperties(wFileName, pidlFolder, apidl); } - wcscpy(szTemp, wFileName); - pFileName = wcsrchr(szTemp, '\\'); - if (pFileName) - { - pFileName[0] = L'\0'; - pFileName++; - pidlChild = ILCreateFromPathW(pFileName); - pidlFolder = ILCreateFromPathW(szTemp); - if (pidlChild && pidlFolder) - { - hResult = SHCreateDataObject(pidlFolder, 1, (LPCITEMIDLIST*)&pidlChild, NULL, &IID_IDataObject, (LPVOID*)&pDataObj); - ILFree(pidlChild); - ILFree(pidlFolder); - if (hResult != S_OK) - pDataObj = NULL; - } - } - - - hpage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, (LPARAM)wFileName, NULL); - - if (hpage == NULL) - return FALSE; - - hppages[num_pages] = hpage; - num_pages++; - num_pages += EnumPropSheetExt(wFileName, hppages, MAX_PROPERTY_SHEET_PAGE-1, hpsxa, pDataObj); - - if ( GetFileVersionInfoSizeW(lpf, &dwHandle) && num_pages) - { - if ( (hpage = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",SH_FileVersionDlgProc, (LPARAM)wFileName, NULL))!= NULL) - { - hppages[num_pages] = hpage; - num_pages++; - } - } pFileName = wcsrchr(wFileName, '\\'); if (!pFileName) @@ -833,17 +788,35 @@ SH_ShowPropertiesDialog(PCWSTR lpf) memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW)); pinfo.dwSize = sizeof(PROPSHEETHEADERW); pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE; - pinfo.nPages = num_pages; pinfo.u3.phpage = hppages; pinfo.pszCaption = pFileName; - TRACE("SH_ShowPropertiesDialog pages %u\n", num_pages); + hppages[pinfo.nPages] = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, (LPARAM)wFileName, NULL); + if (hppages[pinfo.nPages]) + pinfo.nPages++; + + + hResult = SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (LPVOID*)&pDataObj); + if (hResult == S_OK) + { + EnumPropSheetExt(wFileName, &pinfo, MAX_PROPERTY_SHEET_PAGE-1, hpsxa, pDataObj); + } + + if ( GetFileVersionInfoSizeW(lpf, &dwHandle)) + { + hppages[pinfo.nPages] = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",SH_FileVersionDlgProc, (LPARAM)wFileName, NULL); + if (hppages[pinfo.nPages]) + pinfo.nPages++; + } + res = PropertySheetW(&pinfo); - SHDestroyPropSheetExtArray(hpsxa[0]); - SHDestroyPropSheetExtArray(hpsxa[1]); - if (pDataObj) + if (hResult == S_OK) + { + SHDestroyPropSheetExtArray(hpsxa[0]); + SHDestroyPropSheetExtArray(hpsxa[1]); IDataObject_Release(pDataObj); + } return (res != -1); } diff --git a/reactos/dll/win32/shell32/pidl.c b/reactos/dll/win32/shell32/pidl.c index 452e85695e7..fd009716d96 100644 --- a/reactos/dll/win32/shell32/pidl.c +++ b/reactos/dll/win32/shell32/pidl.c @@ -1382,6 +1382,22 @@ LPITEMIDLIST _ILCreateIExplore(void) LPITEMIDLIST _ILCreateControlPanel(void) { + TRACE("()\n"); + LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, &CLSID_MyComputer), ret = NULL; + + if (parent) + { + LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, &CLSID_ControlPanel); + + if (printers) + { + ret = ILCombine(parent, printers); + SHFree(printers); + } + SHFree(parent); + } + return ret; + return _ILCreateGuid(PT_SHELLEXT, &CLSID_ControlPanel); } diff --git a/reactos/dll/win32/shell32/she_ocmenu.c b/reactos/dll/win32/shell32/she_ocmenu.c index ec57da1ba77..671d0afd031 100644 --- a/reactos/dll/win32/shell32/she_ocmenu.c +++ b/reactos/dll/win32/shell32/she_ocmenu.c @@ -143,8 +143,8 @@ HRESULT WINAPI SHEOW_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppv) SHEOWImpl * ow; HRESULT res; - ow = LocalAlloc(LMEM_ZEROINIT, sizeof(SHEOWImpl)); - if (!ow) + ow = LocalAlloc(LMEM_ZEROINIT, sizeof(SHEOWImpl)); + if (!ow) { return E_OUTOFMEMORY; } @@ -241,6 +241,8 @@ AddItem(HMENU hMenu, UINT idCmdFirst) if (!LoadStringW(shell32_hInstance, IDS_OPEN_WITH_CHOOSE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR))) wcscpy(szBuffer, szChoose); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; mii.fType = MFT_STRING; mii.fState = MFS_ENABLED; @@ -279,6 +281,7 @@ LoadOWItems(POPEN_WITH_CONTEXT pContext, WCHAR * szName) szPath[0] = 0; if (RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, szPath, &dwPath) == ERROR_SUCCESS) { + szPath[(sizeof(szPath)/sizeof(WCHAR))-1] = L'\0'; LoadItemFromHKCR(pContext, szPath); } } @@ -294,17 +297,18 @@ static HRESULT WINAPI SHEOWCm_fnQueryContextMenu( UINT uFlags) { MENUITEMINFOW mii; - WCHAR szBuffer[100]; + WCHAR szBuffer[100] = {0}; INT pos; HMENU hSubMenu = NULL; OPEN_WITH_CONTEXT Context; SHEOWImpl *This = impl_from_IContextMenu(iface); - if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, szBuffer, 100) < 0) + if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)) < 0) { TRACE("failed to load string\n"); return E_FAIL; } + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; hSubMenu = CreatePopupMenu(); @@ -383,12 +387,16 @@ FreeListItems(HWND hwndDlg) BOOL HideApplicationFromList(WCHAR * pFileName) { - WCHAR szBuffer[100]; + WCHAR szBuffer[100] = {'A','p','p','l','i','c','a','t','i','o','n','s','\\',0}; DWORD dwSize = 0; LONG result; - wcscpy(szBuffer, L"Applications\\"); - wcscat(szBuffer, pFileName); + if (wcslen(pFileName) > (sizeof(szBuffer)/sizeof(WCHAR)) - 14) + { + ERR("insufficient buffer\n"); + return FALSE; + } + wcscpy(&szBuffer[13], pFileName); result = RegGetValueW(HKEY_CLASSES_ROOT, szBuffer, L"NoOpenWith", RRF_RT_REG_SZ, NULL, NULL, &dwSize); @@ -405,11 +413,17 @@ WriteStaticShellExtensionKey(HKEY hRootKey, WCHAR * pVerb, WCHAR *pFullPath) { HKEY hShell; LONG result; - WCHAR szBuffer[MAX_PATH+10]; + WCHAR szBuffer[MAX_PATH+10] = {'s','h','e','l','l','\\', 0 }; + + if (wcslen(pVerb) > (sizeof(szBuffer)/sizeof(WCHAR)) - 15 || + wcslen(pFullPath) > (sizeof(szBuffer)/sizeof(WCHAR)) - 4) + { + ERR("insufficient buffer\n"); + return; + } /* construct verb reg path */ - wcscpy(szBuffer, L"shell\\"); - wcscat(szBuffer, pVerb); + wcscpy(&szBuffer[6], pVerb); wcscat(szBuffer, L"\\command"); /* create verb reg key */ @@ -427,7 +441,7 @@ WriteStaticShellExtensionKey(HKEY hRootKey, WCHAR * pVerb, WCHAR *pFullPath) VOID StoreNewSettings(WCHAR * szFileName, WCHAR *szAppName) { - WCHAR szBuffer[100]; + WCHAR szBuffer[100] = { L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\"}; WCHAR * pFileExt; HKEY hKey; LONG result; @@ -435,9 +449,12 @@ StoreNewSettings(WCHAR * szFileName, WCHAR *szAppName) /* get file extension */ pFileExt = wcsrchr(szFileName, L'.'); - wcscpy(szBuffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\"); - wcscat(szBuffer, pFileExt); - + if (wcslen(pFileExt) > (sizeof(szBuffer)/sizeof(WCHAR)) - 60) + { + ERR("insufficient buffer\n"); + return; + } + wcscpy(&szBuffer[60], pFileExt); /* open base key for this file extension */ if (RegCreateKeyExW(HKEY_CURRENT_USER, szBuffer, 0, NULL, 0, KEY_WRITE | KEY_READ, NULL, &hKey, NULL) != ERROR_SUCCESS) return; @@ -464,7 +481,7 @@ VOID SetProgrammAsDefaultHandler(WCHAR * szFileName, WCHAR * szAppName) { HKEY hKey; - HKEY hAppKey; + HKEY hAppKey; DWORD dwDisposition; WCHAR szBuffer[100]; DWORD dwSize; @@ -541,18 +558,17 @@ SetProgrammAsDefaultHandler(WCHAR * szFileName, WCHAR * szAppName) void BrowseForApplication(HWND hwndDlg) { - WCHAR szBuffer[30]; - WCHAR szFilter[30]; + WCHAR szBuffer[30] = {0}; + WCHAR szFilter[30] = {0}; WCHAR szPath[MAX_PATH]; OPENFILENAMEW ofn; OPEN_WITH_CONTEXT Context; INT count; /* load resource open with */ - szBuffer[0] = 0; if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH, szBuffer, sizeof(szBuffer) / sizeof(WCHAR))) { - szBuffer[99] = 0; + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; ofn.lpstrTitle = szBuffer; ofn.nMaxFileTitle = strlenW(szBuffer); } @@ -565,10 +581,9 @@ BrowseForApplication(HWND hwndDlg) ofn.lpstrFile = szPath; /* load the filter resource string */ - szFilter[0] = 0; if (LoadStringW(shell32_hInstance, IDS_OPEN_WITH_FILTER, szFilter, sizeof(szFilter) / sizeof(WCHAR))) { - szFilter[99] = 0; + szFilter[(sizeof(szFilter)/sizeof(WCHAR))-1] = 0; ofn.lpstrFilter = szFilter; } ZeroMemory(szPath, sizeof(szPath)); @@ -658,12 +673,16 @@ static BOOL CALLBACK OpenWithProgrammDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, { szBuffer[0] = L'\0'; SendDlgItemMessageA(hwndDlg, 14001, WM_GETTEXT, sizeof(szBuffer), (LPARAM)szBuffer); - strcat((char*)szBuffer, poainfo->pcszFile); + index = strlen((char*)szBuffer); + if (index + strlen(poainfo->pcszFile) + 1 < sizeof(szBuffer)) + strcat((char*)szBuffer, poainfo->pcszFile); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; SendDlgItemMessageA(hwndDlg, 14001, WM_SETTEXT, 0, (LPARAM)szBuffer); } if (MultiByteToWideChar(CP_ACP, 0,poainfo->pcszFile, -1, szBuffer, MAX_PATH)) { OPEN_WITH_CONTEXT Context; + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; ZeroMemory(&Context, sizeof(OPEN_WITH_CONTEXT)); Context.hDlgCtrl = GetDlgItem(hwndDlg, 14002); LoadOWItems(&Context, szBuffer); @@ -1231,7 +1250,7 @@ SHEOW_LoadOpenWithItems(SHEOWImpl *This, IDataObject *pdtobj) return E_OUTOFMEMORY; } if (_ILIsDesktop(pidl_child) || _ILIsMyDocuments(pidl_child) || _ILIsControlPanel(pidl_child) || _ILIsNetHood(pidl_child) || - _ILIsBitBucket(pidl_child) || _ILIsDrive(pidl_child) || _ILIsCPanelStruct(pidl_child) || _ILIsFolder(pidl_child)) + _ILIsBitBucket(pidl_child) || _ILIsDrive(pidl_child) || _ILIsCPanelStruct(pidl_child) || _ILIsFolder(pidl_child) || _ILIsControlPanel(pidl_folder)) { TRACE("pidl is a folder\n"); SHFree((void*)pidl); diff --git a/reactos/dll/win32/shell32/shell32.rbuild b/reactos/dll/win32/shell32/shell32.rbuild index 991848772af..630d995f15c 100644 --- a/reactos/dll/win32/shell32/shell32.rbuild +++ b/reactos/dll/win32/shell32/shell32.rbuild @@ -65,8 +65,7 @@ shlmenu.c shlview.c shpolicy.c - shv_bg_cmenu.c - shv_item_cmenu.c + shv_def_cmenu.c startmenu.c ros-systray.c shell32.rc diff --git a/reactos/dll/win32/shell32/shell32_main.h b/reactos/dll/win32/shell32/shell32_main.h index ec01b3b5a69..14b1915b3ef 100644 --- a/reactos/dll/win32/shell32/shell32_main.h +++ b/reactos/dll/win32/shell32/shell32_main.h @@ -176,8 +176,8 @@ HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16,LPCSTR,UINT16,WORD); BOOL16 WINAPI ShellAbout16(HWND16,LPCSTR,LPCSTR,HICON16); BOOL16 WINAPI AboutDlgProc16(HWND16,UINT16,WPARAM16,LPARAM); -void WINAPI _InsertMenuItem (HMENU hmenu, UINT indexMenu, BOOL fByPosition, - UINT wID, UINT fType, LPCSTR dwTypeData, UINT fState); +void WINAPI _InsertMenuItemW (HMENU hmenu, UINT indexMenu, BOOL fByPosition, + UINT wID, UINT fType, LPCWSTR dwTypeData, UINT fState); static inline BOOL SHELL_OsIsUnicode(void) { @@ -246,8 +246,8 @@ BOOL SHELL_IsShortcut(LPCITEMIDLIST); 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(LPSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle); -BOOL SH_ShowDriveProperties(WCHAR * drive); +BOOL SH_ShowDriveProperties(WCHAR * drive, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl); BOOL SH_ShowRecycleBinProperties(WCHAR sDrive); -BOOL SH_ShowPropertiesDialog(PCWSTR lpf); +BOOL SH_ShowPropertiesDialog(LPWSTR lpf, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl); BOOL SH_ShowFolderProperties(LPWSTR pwszFolder); #endif diff --git a/reactos/dll/win32/shell32/shfldr_admintools.c b/reactos/dll/win32/shell32/shfldr_admintools.c index bc67dd2b020..959c76a98ec 100644 --- a/reactos/dll/win32/shell32/shfldr_admintools.c +++ b/reactos/dll/win32/shell32/shfldr_admintools.c @@ -163,7 +163,8 @@ static ULONG WINAPI ISF_AdminTools_fnRelease (IShellFolder2 * iface) TRACE ("-- destroying IShellFolder(%p)\n", This); if (This->pidlRoot) SHFree (This->pidlRoot); - LocalFree ((HLOCAL) This); + HeapFree(GetProcessHeap(), 0, This->szTarget); + HeapFree(GetProcessHeap(), 0, This); return 0; } return refCount; @@ -187,6 +188,8 @@ static HRESULT WINAPI ISF_AdminTools_fnParseDisplayName (IShellFolder2 * iface, if (pchEaten) *pchEaten = 0; + MessageBoxW(NULL, lpszDisplayName, L"ParseDisplayName", MB_OK); + return E_NOTIMPL; } @@ -433,7 +436,8 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, { IGenericSFImpl *This = (IGenericSFImpl *)iface; HRESULT hr = S_OK; - LPWSTR pszPath; + LPWSTR pszPath, pOffset; + TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet); pdump (pidl); @@ -457,7 +461,19 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, } else if (_ILIsPidlSimple(pidl)) { - _ILSimpleGetTextW(pidl, pszPath, MAX_PATH); + if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) && + (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) && + This->szTarget) + { + wcscpy(pszPath, This->szTarget); + pOffset = PathAddBackslashW(pszPath); + if (pOffset) + _ILSimpleGetTextW(pidl, pOffset, MAX_PATH + 1 - (pOffset - pszPath)); + } + else + { + _ILSimpleGetTextW(pidl, pszPath, MAX_PATH + 1); + } } else if (_ILIsSpecialFolder(pidl)) { @@ -467,10 +483,6 @@ static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface, { _ILSimpleGetTextW(pidl, pszPath, MAX_PATH); } - else - { - FIXME("special pidl\n"); - } if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { @@ -709,8 +721,11 @@ static HRESULT WINAPI IPF_AdminTools_Initialize ( IPersistFolder2 * iface, LPCITEMIDLIST pidl) { _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - FIXME ("(%p)->(%p): stub\n", This, pidl); - return E_NOTIMPL; + if (This->pidlRoot) + SHFree((LPVOID)This->pidlRoot); + + This->pidlRoot = ILClone(pidl); + return S_OK; } /************************************************************************** @@ -765,6 +780,7 @@ HRESULT WINAPI ISF_AdminTools_Constructor ( { HeapFree(GetProcessHeap(), 0, sf->szTarget); HeapFree(GetProcessHeap(), 0, sf); + return E_FAIL; } sf->ref = 1; diff --git a/reactos/dll/win32/shell32/shfldr_desktop.c b/reactos/dll/win32/shell32/shfldr_desktop.c index 15c09cb7a3d..bbe8e6844da 100644 --- a/reactos/dll/win32/shell32/shfldr_desktop.c +++ b/reactos/dll/win32/shell32/shfldr_desktop.c @@ -62,6 +62,7 @@ WINE_DEFAULT_DEBUG_CHANNEL (shell); typedef struct { const IShellFolder2Vtbl *lpVtbl; const IPersistFolder2Vtbl *lpPF2; + const ISFHelperVtbl *lpvtblSFHelper; LONG ref; /* both paths are parsible from the desktop */ @@ -72,6 +73,9 @@ typedef struct { BOOL fAcceptFmt; /* flag for pending Drop */ } IGenericSFImpl; +WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls); +int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll); + #define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl) #define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl) @@ -110,6 +114,10 @@ static HRESULT WINAPI ISF_Desktop_fnQueryInterface( { *ppvObj = &This->lpPF2; } + else if (IsEqualIID(riid, &IID_ISFHelper)) + { + *ppvObj = &This->lpvtblSFHelper; + } if (*ppvObj) { IUnknown_AddRef ((IUnknown *) (*ppvObj)); @@ -120,6 +128,11 @@ static HRESULT WINAPI ISF_Desktop_fnQueryInterface( return E_NOINTERFACE; } +static inline IGenericSFImpl *impl_from_ISFHelper( ISFHelper *iface ) +{ + return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblSFHelper)); +} + static ULONG WINAPI ISF_Desktop_fnAddRef (IShellFolder2 * iface) { return 2; /* non-heap based object */ @@ -246,7 +259,7 @@ static const WCHAR ClassicStartMenuW[] = {'S','O','F','T','W','A','R','E','\\', 'C','l','a','s','s','i','c','S','t','a','r','t','M','e','n','u','\0' }; INT -HideNamespaceExtension(WCHAR *iid) +IsNamespaceExtensionHidden(WCHAR *iid) { DWORD Result, dwResult; dwResult = sizeof(DWORD); @@ -265,6 +278,19 @@ HideNamespaceExtension(WCHAR *iid) return Result; } +static +VOID +SetNamespaceExtensionVisibleStatus(WCHAR * iid, DWORD dwStatus) +{ + HKEY hKey; + + if (RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) + { + RegSetValueExW(hKey, iid, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD)); + RegCloseKey(hKey); + } +} + /************************************************************************** @@ -280,6 +306,7 @@ static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) { BOOL ret = TRUE; WCHAR szPath[MAX_PATH]; + static WCHAR MyDocumentsClassString[] = L"{450D8FBA-AD25-11D0-98A8-0800361B1103}"; @@ -293,7 +320,7 @@ static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) DWORD dwResult; /* create the pidl for This item */ - if (HideNamespaceExtension(MyDocumentsClassString) < 1) + if (IsNamespaceExtensionHidden(MyDocumentsClassString) < 1) { ret = AddToEnumList(list, _ILCreateMyDocuments()); } @@ -321,7 +348,7 @@ static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) r = RegEnumKeyExW(hkey, i, iid, &size, 0, NULL, NULL, NULL); if (ERROR_SUCCESS == r) { - if (HideNamespaceExtension(iid) < 1) + if (IsNamespaceExtensionHidden(iid) < 1) { pidl = _ILCreateGuidFromStrW(iid); if (!HasItemWithCLSID(list, pidl)) @@ -388,7 +415,7 @@ static BOOL CreateDesktopEnumList(IEnumIDList *list, DWORD dwFlags) } /* enumerate the elements in %windir%\desktop */ - SHGetSpecialFolderPathW(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); + ret = ret && SHGetSpecialFolderPathW(0, szPath, CSIDL_DESKTOPDIRECTORY, FALSE); ret = ret && CreateFolderEnumList(list, szPath, dwFlags); return ret; @@ -741,7 +768,6 @@ static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf (IShellFolder2 * iface, } _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen); - if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags); } @@ -796,13 +822,63 @@ static HRESULT WINAPI ISF_Desktop_fnSetNameOf (IShellFolder2 * iface, LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut) { IGenericSFImpl *This = (IGenericSFImpl *)iface; + IShellFolder2 * psf; + HRESULT hr; + WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1]; + LPWSTR ptr; + BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); - FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This, hwndOwner, pidl, + TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); + if (_ILGetGUIDPointer(pidl)) + { + if (SUCCEEDED(IShellFolder2_BindToObject(iface, pidl, NULL, &IID_IShellFolder2, (LPVOID*)&psf))) + { + hr = IShellFolder2_SetNameOf(psf, hwndOwner, pidl, lpName, dwFlags, pPidlOut); + IShellFolder2_Release(psf); + return hr; + } + } + + /* build source path */ + lstrcpynW(szSrc, This->sPathTarget, MAX_PATH); + ptr = PathAddBackslashW (szSrc); + if (ptr) + _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc)); + + /* build destination path */ + if (dwFlags == SHGDN_NORMAL || dwFlags & SHGDN_INFOLDER) { + lstrcpynW(szDest, This->sPathTarget, MAX_PATH); + ptr = PathAddBackslashW (szDest); + if (ptr) + lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest)); + } else + lstrcpynW(szDest, lpName, MAX_PATH); + + if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) { + WCHAR *ext = PathFindExtensionW(szSrc); + if(*ext != '\0') { + INT len = strlenW(szDest); + lstrcpynW(szDest + len, ext, MAX_PATH - len); + } + } + + TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest)); + if (MoveFileW (szSrc, szDest)) + { + hr = S_OK; + + if (pPidlOut) + hr = _ILCreateFromPathW(szDest, pPidlOut); + + SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, + SHCNF_PATHW, szSrc, szDest); + + return hr; + } return E_FAIL; } - static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(IShellFolder2 *iface, GUID * pguid) { @@ -1024,6 +1100,228 @@ static const IPersistFolder2Vtbl vt_FSFldr_PersistFolder2 = ISF_Desktop_PersistFolder2_fnGetCurFolder, }; +static HRESULT WINAPI +ISF_Desktop_ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + + TRACE ("(%p)->(count=%u)\n", This, This->ref); + + return ISF_Desktop_fnQueryInterface ((IShellFolder2*)This, riid, ppvObj); +} + +static ULONG WINAPI +ISF_Desktop_ISFHelper_fnAddRef (ISFHelper * iface) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + + TRACE ("(%p)->(count=%u)\n", This, This->ref); + + return ISF_Desktop_fnAddRef((IShellFolder2*)This); +} + +static ULONG WINAPI +ISF_Desktop_ISFHelper_fnRelease (ISFHelper * iface) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + + TRACE ("(%p)\n", This); + + return ISF_Desktop_fnRelease ((IShellFolder2*)This); +} + +static HRESULT WINAPI +ISF_Desktop_ISFHelper_fnGetUniqueName (ISFHelper * iface, LPWSTR pwszName, UINT uLen) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + IEnumIDList *penum; + HRESULT hr; + WCHAR wszText[MAX_PATH]; + WCHAR wszNewFolder[25]; + const WCHAR wszFormat[] = {'%','s',' ','%','d',0 }; + + LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, sizeof(wszNewFolder)/sizeof(WCHAR)); + + TRACE ("(%p)(%p %u)\n", This, pwszName, uLen); + + if (uLen < sizeof(wszNewFolder)/sizeof(WCHAR) + 3) + return E_POINTER; + + lstrcpynW (pwszName, wszNewFolder, uLen); + + hr = IShellFolder_EnumObjects ((IShellFolder2*)This, 0, + SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); + if (penum) { + LPITEMIDLIST pidl; + DWORD dwFetched; + int i = 1; + +next: + IEnumIDList_Reset (penum); + while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && + dwFetched) { + _ILSimpleGetTextW (pidl, wszText, MAX_PATH); + if (0 == lstrcmpiW (wszText, pwszName)) { + snprintfW (pwszName, uLen, wszFormat, wszNewFolder, i++); + if (i > 99) { + hr = E_FAIL; + break; + } + goto next; + } + } + + IEnumIDList_Release (penum); + } + return hr; +} + +static HRESULT WINAPI +ISF_Desktop_ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCWSTR pwszName, + LPITEMIDLIST * ppidlOut) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + WCHAR wszNewDir[MAX_PATH]; + DWORD bRes; + HRESULT hres = E_FAIL; + + TRACE ("(%p)(%s %p)\n", This, debugstr_w(pwszName), ppidlOut); + + wszNewDir[0] = 0; + if (This->sPathTarget) + lstrcpynW(wszNewDir, This->sPathTarget, MAX_PATH); + PathAppendW(wszNewDir, pwszName); + bRes = CreateDirectoryW (wszNewDir, NULL); + if (bRes) + { + SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL); + hres = S_OK; + if (ppidlOut) + hres = _ILCreateFromPathW(wszNewDir, ppidlOut); + } + + return hres; +} +static HRESULT WINAPI +ISF_Desktop_ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + UINT i; + SHFILEOPSTRUCTW op; + WCHAR wszPath[MAX_PATH]; + WCHAR wszCaption[50]; + WCHAR *wszPathsList; + HRESULT ret; + WCHAR *wszCurrentPath; + UINT bRestoreWithDeskCpl = FALSE; + int res; + + TRACE ("(%p)(%u %p)\n", This, cidl, apidl); + if (cidl==0) return S_OK; + + for(i = 0; i < cidl; i++) + { + if (_ILIsMyComputer(apidl[i])) + bRestoreWithDeskCpl++; + else if (_ILIsNetHood(apidl[i])) + bRestoreWithDeskCpl++; + else if (_ILIsMyDocuments(apidl[i])) + bRestoreWithDeskCpl++; + } + + if (bRestoreWithDeskCpl) + { + /* FIXME use FormatMessage + * use a similar message resource as in windows + */ + LoadStringW(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, wszPath, sizeof(wszPath)/sizeof(WCHAR)); + wszPath[(sizeof(wszPath)/sizeof(WCHAR))-1] = 0; + + LoadStringW(shell32_hInstance, IDS_DELETEITEM_CAPTION, wszCaption, sizeof(wszCaption)/sizeof(WCHAR)); + wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0; + + res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1); + if (res == IDD_YESTOALL || res == IDYES) + { + for(i = 0; i < cidl; i++) + { + if (_ILIsMyComputer(apidl[i])) + SetNamespaceExtensionVisibleStatus(L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1); + else if (_ILIsNetHood(apidl[i])) + SetNamespaceExtensionVisibleStatus(L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1); + else if (_ILIsMyDocuments(apidl[i])) + SetNamespaceExtensionVisibleStatus(L"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1); + } + } + } + if (This->sPathTarget) + lstrcpynW(wszPath, This->sPathTarget, MAX_PATH); + else + wszPath[0] = '\0'; + + PathAddBackslashW(wszPath); + wszPathsList = build_paths_list(wszPath, cidl, apidl); + + ZeroMemory(&op, sizeof(op)); + op.hwnd = GetActiveWindow(); + op.wFunc = FO_DELETE; + op.pFrom = wszPathsList; + op.fFlags = FOF_ALLOWUNDO; + if (SHFileOperationW(&op)) + { + WARN("SHFileOperation failed\n"); + ret = E_FAIL; + } + else + ret = S_OK; + + /* we currently need to manually send the notifies */ + wszCurrentPath = wszPathsList; + for (i = 0; i < cidl; i++) + { + LONG wEventId; + + if (_ILIsFolder(apidl[i])) + wEventId = SHCNE_RMDIR; + else if (_ILIsValue(apidl[i])) + wEventId = SHCNE_DELETE; + else + continue; + + /* check if file exists */ + if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES) + { + LPITEMIDLIST pidl = ILCombine(This->pidlRoot, apidl[i]); + SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL); + SHFree(pidl); + } + + wszCurrentPath += lstrlenW(wszCurrentPath)+1; + } + HeapFree(GetProcessHeap(), 0, wszPathsList); + return ret; +} + +static HRESULT WINAPI +ISF_Desktop_ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl) +{ + IGenericSFImpl *This = impl_from_ISFHelper(iface); + + TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl); + return E_NOTIMPL; +} + +static const ISFHelperVtbl vt_FSFldr_ISFHelper = +{ + ISF_Desktop_ISFHelper_fnQueryInterface, + ISF_Desktop_ISFHelper_fnAddRef, + ISF_Desktop_ISFHelper_fnRelease, + ISF_Desktop_ISFHelper_fnGetUniqueName, + ISF_Desktop_ISFHelper_fnAddFolder, + ISF_Desktop_ISFHelper_fnDeleteItems, + ISF_Desktop_ISFHelper_fnCopyItems +}; + /************************************************************************** * ISF_Desktop_Constructor @@ -1055,6 +1353,7 @@ HRESULT WINAPI ISF_Desktop_Constructor ( sf->ref = 1; sf->lpVtbl = &vt_MCFldr_ShellFolder2; sf->lpPF2 = &vt_FSFldr_PersistFolder2; + sf->lpvtblSFHelper = &vt_FSFldr_ISFHelper; sf->pidlRoot = _ILCreateDesktop(); /* my qualified pidl */ sf->sPathTarget = SHAlloc( (lstrlenW(szMyPath) + 1)*sizeof(WCHAR) ); lstrcpyW( sf->sPathTarget, szMyPath ); diff --git a/reactos/dll/win32/shell32/shfldr_fonts.c b/reactos/dll/win32/shell32/shfldr_fonts.c index 10b0595e107..4ed7e7acc03 100644 --- a/reactos/dll/win32/shell32/shfldr_fonts.c +++ b/reactos/dll/win32/shell32/shfldr_fonts.c @@ -918,7 +918,7 @@ static HRESULT WINAPI ISF_Fonts_IContextMenu2_QueryContextMenu( UINT idCmdLast, UINT uFlags) { - char szBuffer[30] = {0}; + WCHAR szBuffer[30] = {0}; ULONG Count = 1; _ICOM_THIS_From_IContextMenu2FontItem(IGenericSFImpl, iface); @@ -926,38 +926,38 @@ static HRESULT WINAPI ISF_Fonts_IContextMenu2_QueryContextMenu( TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - if (LoadStringA(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); Count++; } - if (LoadStringA(shell32_hInstance, IDS_PRINT_VERB, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_PRINT_VERB, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); } - if (LoadStringA(shell32_hInstance, IDS_COPY, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_COPY, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); } - if (LoadStringA(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); } - if (LoadStringA(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count); diff --git a/reactos/dll/win32/shell32/shfldr_mycomp.c b/reactos/dll/win32/shell32/shfldr_mycomp.c index b54e7d2e9ee..7c2bc90fb49 100644 --- a/reactos/dll/win32/shell32/shfldr_mycomp.c +++ b/reactos/dll/win32/shell32/shfldr_mycomp.c @@ -451,6 +451,9 @@ static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, { IGenericSFImpl *This = (IGenericSFImpl *)iface; HRESULT hr = S_OK; + static const DWORD dwComputerAttributes = + SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_CANCOPY | + SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); @@ -463,15 +466,8 @@ static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf (IShellFolder2 * iface, if (*rgfInOut == 0) *rgfInOut = ~0; - if(cidl == 0){ - IShellFolder *psfParent = NULL; - LPCITEMIDLIST rpidl = NULL; - - hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&rpidl); - if(SUCCEEDED(hr)) { - SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut); - IShellFolder_Release(psfParent); - } + if(cidl == 0) { + *rgfInOut &= dwComputerAttributes; } else { while (cidl > 0 && *apidl) { pdump (*apidl); @@ -778,10 +774,23 @@ static HRESULT WINAPI ISF_MyComputer_fnSetNameOf ( LPWSTR sName; HKEY hKey; UINT length; + WCHAR szName[30]; TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut); + if (_ILIsDrive(pidl)) + { + if (_ILSimpleGetTextW(pidl, szName, sizeof(szName)/sizeof(WCHAR))) + { + SetVolumeLabelW(szName, lpName); + } + if (pPidlOut) + *pPidlOut = _ILCreateDrive(szName); + return S_OK; + } + + if (pPidlOut != NULL) { *pPidlOut = _ILCreateMyComputer(); @@ -1021,7 +1030,12 @@ static HRESULT WINAPI IMCFldr_PersistFolder2_Initialize ( { IGenericSFImpl *This = impl_from_IPersistFolder2(iface); TRACE ("(%p)->(%p)\n", This, pidl); - return E_NOTIMPL; + + if (This->pidlRoot) + SHFree((LPVOID)This->pidlRoot); + + This->pidlRoot = ILClone(pidl); + return S_OK; } /************************************************************************** diff --git a/reactos/dll/win32/shell32/shfldr_mydocuments.c b/reactos/dll/win32/shell32/shfldr_mydocuments.c index 94a680b5a6c..143c4b74e83 100644 --- a/reactos/dll/win32/shell32/shfldr_mydocuments.c +++ b/reactos/dll/win32/shell32/shfldr_mydocuments.c @@ -368,8 +368,8 @@ static HRESULT WINAPI ISF_MyDocuments_fnGetAttributesOf (IShellFolder2 * iface, IGenericSFImpl *This = (IGenericSFImpl *)iface; HRESULT hr = S_OK; static const DWORD dwMyDocumentsAttributes = - SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | - SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER; + SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_CANCOPY | + SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0); diff --git a/reactos/dll/win32/shell32/shfldr_netplaces.c b/reactos/dll/win32/shell32/shfldr_netplaces.c index adf27f33fb6..361496bebac 100644 --- a/reactos/dll/win32/shell32/shfldr_netplaces.c +++ b/reactos/dll/win32/shell32/shfldr_netplaces.c @@ -317,6 +317,9 @@ static HRESULT WINAPI ISF_NetworkPlaces_fnGetAttributesOf (IShellFolder2 * iface UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut) { IGenericSFImpl *This = (IGenericSFImpl *)iface; + static const DWORD dwNethoodAttributes = + SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | + SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE; HRESULT hr = S_OK; TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This, @@ -330,17 +333,8 @@ static HRESULT WINAPI ISF_NetworkPlaces_fnGetAttributesOf (IShellFolder2 * iface if (*rgfInOut == 0) *rgfInOut = ~0; - if (cidl == 0) - { - IShellFolder *psfParent = NULL; - LPCITEMIDLIST rpidl = NULL; - - hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&rpidl); - if(SUCCEEDED(hr)) - { - SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut); - IShellFolder_Release(psfParent); - } + if(cidl == 0) { + *rgfInOut = dwNethoodAttributes; } else { @@ -392,8 +386,7 @@ static HRESULT WINAPI ISF_NetworkPlaces_fnGetUIObjectOf (IShellFolder2 * iface, if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) { - pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl); - hr = S_OK; + hr = CDefFolderMenu_Create2(This->pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)iface, NULL, 0, NULL, (IContextMenu**)&pObj); } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) { diff --git a/reactos/dll/win32/shell32/shfldr_printers.c b/reactos/dll/win32/shell32/shfldr_printers.c index 9e31aa2abee..c61d37241ff 100644 --- a/reactos/dll/win32/shell32/shfldr_printers.c +++ b/reactos/dll/win32/shell32/shfldr_printers.c @@ -923,8 +923,11 @@ static HRESULT WINAPI IPF_Printers_Initialize ( IPersistFolder2 * iface, LPCITEMIDLIST pidl) { _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface); - FIXME ("(%p)->(%p): stub\n", This, pidl); - return E_NOTIMPL; + if (This->pidlRoot) + SHFree((LPVOID)This->pidlRoot); + + This->pidlRoot = ILClone(pidl); + return S_OK; } /************************************************************************** diff --git a/reactos/dll/win32/shell32/shfldr_recyclebin.c b/reactos/dll/win32/shell32/shfldr_recyclebin.c index aae4772cdf5..f6996107ba6 100644 --- a/reactos/dll/win32/shell32/shfldr_recyclebin.c +++ b/reactos/dll/win32/shell32/shfldr_recyclebin.c @@ -88,11 +88,7 @@ typedef struct tagRecycleBin const IContextMenu2Vtbl *lpContextMenu2; const IShellExtInitVtbl *lpSEI; LONG refCount; - - INT iIdOpen; INT iIdEmpty; - INT iIdProperties; - LPITEMIDLIST pidl; LPCITEMIDLIST apidl; } RecycleBin; @@ -180,12 +176,12 @@ static HRESULT WINAPI RecycleBin_QueryInterface(IShellFolder2 *iface, REFIID rii || IsEqualGUID(riid, &IID_IPersistFolder2)) *ppvObject = &This->lpPersistFolderVtbl; - if (IsEqualIID(riid, &IID_IContextMenu) || IsEqualGUID(riid, &IID_IContextMenu2)) + else if (IsEqualIID(riid, &IID_IContextMenu) || IsEqualGUID(riid, &IID_IContextMenu2)) { This->lpContextMenu2 = &recycleBincmVtblFolder; *ppvObject = &This->lpContextMenu2; } - if(IsEqualIID(riid, &IID_IShellExtInit)) + else if(IsEqualIID(riid, &IID_IShellExtInit)) { *ppvObject = &(This->lpSEI); } @@ -533,10 +529,12 @@ static HRESULT WINAPI RecycleBin_GetDisplayNameOf(IShellFolder2 *This, LPCITEMID { WCHAR pszPath[100]; - HCR_GetClassNameW(&CLSID_RecycleBin, pszPath, MAX_PATH); - pName->uType = STRRET_WSTR; - pName->u.pOleStr = StrDupW(pszPath); - return S_OK; + if (HCR_GetClassNameW(&CLSID_RecycleBin, pszPath, MAX_PATH)) + { + pName->uType = STRRET_WSTR; + pName->u.pOleStr = StrDupW(pszPath); + return S_OK; + } } pFileDetails = _ILGetRecycleStruct(pidl); @@ -747,6 +745,7 @@ static HRESULT WINAPI RecycleBin_IPersistFolder2_Initialize(IPersistFolder2 *ifa RecycleBin *This = impl_from_IPersistFolder(iface); TRACE("(%p, %p)\n", This, pidl); + SHFree((LPVOID)This->pidl); This->pidl = ILClone(pidl); if (This->pidl == NULL) return E_OUTOFMEMORY; @@ -874,31 +873,19 @@ RecycleBin_IContextMenu2Folder_QueryContextMenu( IContextMenu2* iface, HMENU hme memset( &mii, 0, sizeof(mii) ); mii.cbSize = sizeof(mii); mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; - szBuffer[0] = L'\0'; - LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)); - szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; - mii.dwTypeData = (LPWSTR)szBuffer; - mii.cch = strlenW( mii.dwTypeData ); - mii.wID = idCmdFirst + id++; - mii.fState = MFS_ENABLED; - mii.fType = MFT_STRING; - - if (!InsertMenuItemW( hmenu, indexMenu, TRUE, &mii )) - return E_FAIL; - This->iIdOpen = 1; - mii.fState = MFS_ENABLED; szBuffer[0] = L'\0'; LoadStringW(shell32_hInstance, IDS_EMPTY_BITBUCKET, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)); szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + mii.dwTypeData = szBuffer; mii.cch = strlenW( mii.dwTypeData ); mii.wID = idCmdFirst + id++; - if (!InsertMenuItemW( hmenu, idCmdLast, TRUE, &mii )) - { - TRACE("RecycleBin_IContextMenu2Folder_QueryContextMenu failed to insert item properties"); + mii.fType = MFT_STRING; + This->iIdEmpty = 1; + + if (!InsertMenuItemW( hmenu, indexMenu, TRUE, &mii )) return E_FAIL; - } - This->iIdEmpty = 2; + return MAKE_HRESULT( SEVERITY_SUCCESS, 0, id ); } @@ -908,7 +895,6 @@ RecycleBin_IContextMenu2Folder_InvokeCommand( IContextMenu2* iface, LPCMINVOKECO HRESULT hr; LPSHELLBROWSER lpSB; LPSHELLVIEW lpSV = NULL; - RecycleBin * This = impl_from_IContextMenu2(iface); TRACE("%p %p verb %p\n", This, lpici, lpici->lpVerb); @@ -932,15 +918,6 @@ RecycleBin_IContextMenu2Folder_InvokeCommand( IContextMenu2* iface, LPCMINVOKECO } } } - - - if ( LOWORD(lpici->lpVerb) == This->iIdProperties) - { - WCHAR szDrive = 'C'; - SH_ShowRecycleBinProperties(szDrive); - return S_OK; - } - return S_OK; } @@ -1036,7 +1013,7 @@ static HRESULT WINAPI RecycleBin_IContextMenu2Item_QueryContextMenu( UINT idCmdLast, UINT uFlags) { - char szBuffer[30] = {0}; + WCHAR szBuffer[30] = {0}; ULONG Count = 1; RecycleBin * This = impl_from_IContextMenu2(iface); @@ -1044,32 +1021,32 @@ static HRESULT WINAPI RecycleBin_IContextMenu2Item_QueryContextMenu( TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - if (LoadStringA(shell32_hInstance, IDS_RESTORE, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_RESTORE, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED); Count++; } - if (LoadStringA(shell32_hInstance, IDS_CUT, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_CUT, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); } - if (LoadStringA(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer)/sizeof(char))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED); } - if (LoadStringA(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer)/sizeof(char))) + if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer)/sizeof(WCHAR))) { - szBuffer[(sizeof(szBuffer)/sizeof(char))-1] = L'\0'; - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); + szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0'; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT); } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count); diff --git a/reactos/dll/win32/shell32/shlexec.c b/reactos/dll/win32/shell32/shlexec.c index ce88e563607..72735d72d51 100644 --- a/reactos/dll/win32/shell32/shlexec.c +++ b/reactos/dll/win32/shell32/shlexec.c @@ -1298,7 +1298,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) static const WCHAR wFile[] = {'f','i','l','e',0}; static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0}; static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0}; - static const WCHAR wProperties[] = { 'p','r','o','p','e','r','t','i','e','s',0 }; + //static const WCHAR wProperties[] = { 'p','r','o','p','e','r','t','i','e','s',0 }; static const DWORD unsupportedFlags = SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY | SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | @@ -1403,14 +1403,14 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) HeapFree(GetProcessHeap(), 0, wszApplicationName); return TRUE; } - +#if 0 if (sei_tmp.lpVerb && !wcscmp(sei_tmp.lpVerb, wProperties)) { SH_ShowPropertiesDialog(sei_tmp.lpFile); sei->hInstApp = (HINSTANCE) 33; return TRUE; } - +#endif if (sei_tmp.fMask & SEE_MASK_CLASSALL) { /* launch a document by fileclass like 'WordPad.Document.1' */ diff --git a/reactos/dll/win32/shell32/shlfileop.c b/reactos/dll/win32/shell32/shlfileop.c index 6f99819e690..6eccbb18f58 100644 --- a/reactos/dll/win32/shell32/shlfileop.c +++ b/reactos/dll/win32/shell32/shlfileop.c @@ -190,7 +190,7 @@ static INT_PTR CALLBACK ConfirmMsgBoxProc(HWND hDlg, UINT uMsg, WPARAM wParam, L return FALSE; } -static int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll) +int SHELL_ConfirmMsgBox(HWND hWnd, LPWSTR lpszText, LPWSTR lpszCaption, HICON hIcon, BOOL bYesToAll) { static const WCHAR wszTemplate[] = {'S','H','E','L','L','_','Y','E','S','T','O','A','L','L','_','M','S','G','B','O','X',0}; struct confirm_msg_info info; diff --git a/reactos/dll/win32/shell32/shlfolder.c b/reactos/dll/win32/shell32/shlfolder.c index 71351113725..44d5150d38f 100644 --- a/reactos/dll/win32/shell32/shlfolder.c +++ b/reactos/dll/win32/shell32/shlfolder.c @@ -418,7 +418,7 @@ HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWO if (_ILIsDrive (pidl)) { *pdwAttributes &= SFGAO_HASSUBFOLDER|SFGAO_FILESYSTEM|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR| - SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANLINK|SFGAO_CANRENAME; + SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME; } else if (has_guid && HCR_GetFolderAttributes(pidl, &dwAttributes)) { *pdwAttributes = dwAttributes; } else if (_ILGetDataPointer (pidl)) { @@ -446,7 +446,10 @@ HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWO SFGAO_CANRENAME | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANCOPY; if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) + { *pdwAttributes |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); + *pdwAttributes &= ~SFGAO_CANLINK; + } else *pdwAttributes &= ~(SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR); diff --git a/reactos/dll/win32/shell32/shlmenu.c b/reactos/dll/win32/shell32/shlmenu.c index cdd08c9fcc4..87b2ac7ea12 100644 --- a/reactos/dll/win32/shell32/shlmenu.c +++ b/reactos/dll/win32/shell32/shlmenu.c @@ -907,6 +907,7 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI if (!GetMenuItemInfoW(hmSrc, nItem, TRUE, &miiSrc)) { +MessageBoxW(NULL, L"GetMenuItemInfoW failed", NULL, MB_OK); continue; } @@ -916,8 +917,10 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI { /* This is a separator; don't put two of them in a row */ if (bAlreadySeparated) + { +MessageBoxW(NULL, L"bAlreadySeparated failed", NULL, MB_OK); continue; - + } bAlreadySeparated = TRUE; } else if (miiSrc.hSubMenu) @@ -926,9 +929,10 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI { miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ - if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ + if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ + {MessageBoxW(NULL, L"uIDAdjustMax 111 failed", NULL, MB_OK); continue; - + } if (uIDMax <= miiSrc.wID) /* remember the highest ID */ uIDMax = miiSrc.wID + 1; } @@ -953,9 +957,10 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI { miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */ - if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */ + if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */{ +MessageBoxW(NULL, L"uIDAdjustMax max 222 failed", NULL, MB_OK); continue; - + } if (uIDMax <= miiSrc.wID) /* remember the highest ID */ uIDMax = miiSrc.wID + 1; @@ -966,6 +971,7 @@ HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uI */ if (!InsertMenuItemW(hmDst, uInsert, TRUE, &miiSrc)) { +MessageBoxW(NULL, L"InsertMenuItemW failed", NULL, MB_OK); return(uIDMax); } } diff --git a/reactos/dll/win32/shell32/shlview.c b/reactos/dll/win32/shell32/shlview.c index 9c03d8a7271..1a2b6d7fa53 100644 --- a/reactos/dll/win32/shell32/shlview.c +++ b/reactos/dll/win32/shell32/shlview.c @@ -774,8 +774,8 @@ static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu) if(hSubMenu) { /*insert This item at the beginning of the menu */ - _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); - _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"dummy45", MFS_ENABLED); } TRACE("--\n"); @@ -791,18 +791,18 @@ static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu) if(hSubMenu) { /*add a separator at the correct position in the menu*/ - MENUITEMINFOA mii; - static char view[] = "View"; + MENUITEMINFOW mii; + static WCHAR view[] = L"View"; - _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); + _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA; mii.fType = MFT_STRING; mii.dwTypeData = view; - mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001"); - InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); + mii.hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001"); + InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); } } @@ -841,6 +841,8 @@ static UINT ShellView_GetSelections(IShellViewImpl * This) { This->apidl[i] = (LPITEMIDLIST)lvItem.lParam; i++; + if (i == This->cidl) + break; TRACE("-- selected Item found\n"); } lvItem.iItem++; @@ -1030,7 +1032,7 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL { hMenu = CreatePopupMenu(); - This->pCM = ISvBgCm_Constructor(This->pSFParent, FALSE); + CDefFolderMenu_Create2(NULL, NULL, This->cidl, (LPCITEMIDLIST*)This->apidl, This->pSFParent, NULL, 0, NULL, (IContextMenu**)&This->pCM); IContextMenu2_QueryContextMenu(This->pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL); @@ -2063,6 +2065,7 @@ static HRESULT WINAPI IShellView_fnSelectItem( static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut) { + HRESULT hr = E_FAIL; IShellViewImpl *This = (IShellViewImpl *)iface; TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut); @@ -2072,19 +2075,19 @@ static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, switch(uItem) { case SVGIO_BACKGROUND: - *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE); + //*ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE); + CDefFolderMenu_Create2(NULL, NULL, This->cidl, (LPCITEMIDLIST*)This->apidl, This->pSFParent, NULL, 0, NULL, (IContextMenu**)ppvOut); + if (!ppvOut) hr = E_OUTOFMEMORY; break; case SVGIO_SELECTION: ShellView_GetSelections(This); - IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut); + hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut); break; } TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut); - if(!*ppvOut) return E_OUTOFMEMORY; - - return S_OK; + return hr; } static const IShellViewVtbl svvt = diff --git a/reactos/dll/win32/shell32/shv_bg_cmenu.c b/reactos/dll/win32/shell32/shv_bg_cmenu.c deleted file mode 100644 index d5a4ff8afd7..00000000000 --- a/reactos/dll/win32/shell32/shv_bg_cmenu.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * IContextMenu - * ShellView Background Context Menu (shv_bg_cm) - * - * Copyright 1999 Juergen Schmied - * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA - */ -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "wine/debug.h" - -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "shlobj.h" -#include "shtypes.h" -#include "shell32_main.h" -#include "shellfolder.h" -#include "undocshell.h" -#include "shlwapi.h" -#include "stdio.h" -#include "winuser.h" - -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/************************************************************************** -* IContextMenu Implementation -*/ -typedef struct -{ - const IContextMenu2Vtbl *lpVtbl; - IShellFolder* pSFParent; - LONG ref; - BOOL bDesktop; - IContextMenu2 * icm_new; -} BgCmImpl; - -static const IContextMenu2Vtbl cmvt; - -BOOL -HasClipboardData() -{ - BOOL ret = FALSE; - IDataObject * pda; - - if(SUCCEEDED(OleGetClipboard(&pda))) - { - STGMEDIUM medium; - FORMATETC formatetc; - - TRACE("pda=%p\n", pda); - - /* Set the FORMATETC structure*/ - InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); - if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) - { - ret = TRUE; - } - - IDataObject_Release(pda); - ReleaseStgMedium(&medium); - } - - return ret; -} - - -/************************************************************************** -* ISVBgCm_Constructor() -*/ -IContextMenu2 *ISvBgCm_Constructor(IShellFolder* pSFParent, BOOL bDesktop) -{ - BgCmImpl* cm; - - cm = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(BgCmImpl)); - cm->lpVtbl = &cmvt; - cm->ref = 1; - cm->pSFParent = pSFParent; - cm->bDesktop = bDesktop; - if(pSFParent) IShellFolder_AddRef(pSFParent); - - TRACE("(%p)->()\n",cm); - return (IContextMenu2*)cm; -} - -/************************************************************************** -* ISVBgCm_fnQueryInterface -*/ -static HRESULT WINAPI ISVBgCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IContextMenu) || - IsEqualIID(riid, &IID_IContextMenu2)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ - { - FIXME("-- LPSHELLEXTINIT pointer requested\n"); - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* ISVBgCm_fnAddRef -*/ -static ULONG WINAPI ISVBgCm_fnAddRef(IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(count=%u)\n", This, refCount - 1); - - return refCount; -} - -/************************************************************************** -* ISVBgCm_fnRelease -*/ -static ULONG WINAPI ISVBgCm_fnRelease(IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(count=%i)\n", This, refCount + 1); - - if (!refCount) - { - TRACE(" destroying IContextMenu(%p)\n",This); - - if(This->pSFParent) - IShellFolder_Release(This->pSFParent); - - HeapFree(GetProcessHeap(),0,This); - } - return refCount; -} - -/************************************************************************** -* ISVBgCm_fnQueryContextMenu() -*/ - -VOID INewItem_SetParent(LPSHELLFOLDER pSFParent); /* FIXME: remove that, shouldn't be needed */ - -static HRESULT WINAPI ISVBgCm_fnQueryContextMenu( - IContextMenu2 *iface, - HMENU hMenu, - UINT indexMenu, - UINT idCmdFirst, - UINT idCmdLast, - UINT uFlags) -{ - HMENU hMyMenu; - UINT idMax; - MENUITEMINFOW mii; - HRESULT hr; - - IContextMenu2 * icm; - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n", - This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - - - hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002"); - if (uFlags & CMF_DEFAULTONLY) - { - HMENU ourMenu = GetSubMenu(hMyMenu,0); - UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED); - UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED); - if (newDef != oldDef) - SetMenuDefaultItem(hMenu,newDef,TRUE); - if (newDef!=0xFFFFFFFF) - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1); - else - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); - } - else - { - idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu, - idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); - hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst+1); - } - DestroyMenu(hMyMenu); - - if (!HasClipboardData()) - { - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = MFS_DISABLED; - mii.fType = 0; - SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERT, FALSE, &mii); - SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERTLINK, FALSE, &mii); - } - - /* - * FIXME - * load other shell extensions - */ - if (SUCCEEDED(INewItem_Constructor(NULL, &IID_IContextMenu2, (LPVOID*)&icm))) - { - if (SUCCEEDED(IContextMenu_QueryContextMenu(icm, hMenu, 10, idCmdFirst, idCmdLast, uFlags))) - { - This->icm_new = icm; - _InsertMenuItem(hMenu, 11, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED); - } - else - { - This->icm_new = NULL; - } - } - - /* Prepare 'New item' shell extension */ - /* FIXME: shouldn't be needed... */ - INewItem_SetParent(This->pSFParent); - - if (This->bDesktop) - { - /* desktop menu has no view option */ - DeleteMenu(hMenu, 0, MF_BYPOSITION); - DeleteMenu(hMenu, 0, MF_BYPOSITION); - } - TRACE("(%p)->returning 0x%x\n",This,hr); - return hr; -} - - -/************************************************************************** -* DoPaste -*/ -static BOOL DoPaste( - IContextMenu2 *iface) -{ - BgCmImpl *This = (BgCmImpl *)iface; - BOOL bSuccess = FALSE; - IDataObject * pda; - - TRACE("\n"); - - if(SUCCEEDED(OleGetClipboard(&pda))) - { - STGMEDIUM medium; - FORMATETC formatetc; - - TRACE("pda=%p\n", pda); - - /* Set the FORMATETC structure*/ - InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); - - /* Get the pidls from IDataObject */ - if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) - { - LPITEMIDLIST * apidl; - LPITEMIDLIST pidl; - IShellFolder *psfFrom = NULL, *psfDesktop; - - LPIDA lpcida = GlobalLock(medium.u.hGlobal); - TRACE("cida=%p\n", lpcida); - - apidl = _ILCopyCidaToaPidl(&pidl, lpcida); - - /* bind to the source shellfolder */ - SHGetDesktopFolder(&psfDesktop); - if(psfDesktop) - { - IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); - IShellFolder_Release(psfDesktop); - } - - if (psfFrom) - { - /* get source and destination shellfolder */ - ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); - IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc); - - /* do the copy/move */ - if (psfhlpdst && psfhlpsrc) - { - ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); - /* FIXME handle move - ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); - */ - } - if(psfhlpdst) ISFHelper_Release(psfhlpdst); - if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); - IShellFolder_Release(psfFrom); - } - - _ILFreeaPidl(apidl, lpcida->cidl); - SHFree(pidl); - - /* release the medium*/ - ReleaseStgMedium(&medium); - } - IDataObject_Release(pda); - } -#if 0 - HGLOBAL hMem; - - OpenClipboard(NULL); - hMem = GetClipboardData(CF_HDROP); - - if(hMem) - { - char * pDropFiles = (char *)GlobalLock(hMem); - if(pDropFiles) - { - int len, offset = sizeof(DROPFILESTRUCT); - - while( pDropFiles[offset] != 0) - { - len = strlen(pDropFiles + offset); - TRACE("%s\n", pDropFiles + offset); - offset += len+1; - } - } - GlobalUnlock(hMem); - } - CloseClipboard(); -#endif - return bSuccess; -} - -/************************************************************************** -* ISVBgCm_fnInvokeCommand() -*/ -static HRESULT WINAPI ISVBgCm_fnInvokeCommand( - IContextMenu2 *iface, - LPCMINVOKECOMMANDINFO lpcmi) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV = NULL; - HWND hWndSV = 0; - - TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); - - /* get the active IShellView */ - if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - IShellView_GetWindow(lpSV, &hWndSV); - } - } - - if(HIWORD(lpcmi->lpVerb)) - { - TRACE("%s\n",lpcmi->lpVerb); - - if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWLISTA)) - { - if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW,0),0 ); - } - else if (! strcmp(lpcmi->lpVerb,CMDSTR_VIEWDETAILSA)) - { - if(hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 ); - } - else - { - FIXME("please report: unknown verb %s\n",lpcmi->lpVerb); - } - } - else - { - switch(LOWORD(lpcmi->lpVerb)) - { - case FCIDM_SHVIEW_REFRESH: - if (lpSV) IShellView_Refresh(lpSV); - break; - case FCIDM_SHVIEW_INSERT: - DoPaste(iface); - break; - - case FCIDM_SHVIEW_PROPERTIES: - if (This->bDesktop) { - ShellExecuteA(lpcmi->hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL); - } else { - FIXME("launch item properties dialog\n"); - } - break; - - default: - - if (This->icm_new && SUCCEEDED(IContextMenu2_InvokeCommand(This->icm_new, lpcmi))) - return S_OK; - - /* if it's an id just pass it to the parent shv */ - if (hWndSV) SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 ); - break; - } - } - - if (lpSV) - IShellView_Release(lpSV); /* QueryActiveShellView does AddRef */ - - return NOERROR; -} - -/************************************************************************** - * ISVBgCm_fnGetCommandString() - * - */ -static HRESULT WINAPI ISVBgCm_fnGetCommandString( - IContextMenu2 *iface, - UINT_PTR idCommand, - UINT uFlags, - UINT* lpReserved, - LPSTR lpszName, - UINT uMaxNameLen) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); - - /* test the existence of the menu items, the file dialog enables - the buttons according to this */ - if (uFlags == GCS_VALIDATEA) - { - if(HIWORD(idCommand)) - { - if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) || - !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA)) - { - return NOERROR; - } - } - } - - FIXME("unknown command string\n"); - return E_FAIL; -} - -/************************************************************************** -* ISVBgCm_fnHandleMenuMsg() -*/ -static HRESULT WINAPI ISVBgCm_fnHandleMenuMsg( - IContextMenu2 *iface, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - BgCmImpl *This = (BgCmImpl *)iface; - - TRACE("ISVBgCm_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); - - if (This->icm_new) - { - IContextMenu2_HandleMenuMsg(This->icm_new, uMsg, wParam, lParam); - } - - return E_NOTIMPL; -} - -/************************************************************************** -* IContextMenu2 VTable -* -*/ -static const IContextMenu2Vtbl cmvt = -{ - ISVBgCm_fnQueryInterface, - ISVBgCm_fnAddRef, - ISVBgCm_fnRelease, - ISVBgCm_fnQueryContextMenu, - ISVBgCm_fnInvokeCommand, - ISVBgCm_fnGetCommandString, - ISVBgCm_fnHandleMenuMsg -}; diff --git a/reactos/dll/win32/shell32/shv_def_cmenu.c b/reactos/dll/win32/shell32/shv_def_cmenu.c new file mode 100644 index 00000000000..445b5747cbc --- /dev/null +++ b/reactos/dll/win32/shell32/shv_def_cmenu.c @@ -0,0 +1,1726 @@ +/* + * PROJECT: shell32 + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/win32/shell32/shv_item_new.c + * PURPOSE: provides default context menu implementation + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ + +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#define YDEBUG +#include "winerror.h" +#include "wine/debug.h" + +#include "windef.h" +#include "wingdi.h" +#include "pidl.h" +#include "undocshell.h" +#include "shlobj.h" +#include "objbase.h" + +#include "shlwapi.h" +#include "shell32_main.h" +#include "shellfolder.h" +#include "debughlp.h" +#include "shresdef.h" +#include "shlguid.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dmenu); + +typedef struct _DynamicShellEntry_ +{ + UINT iIdCmdFirst; + UINT NumIds; + CLSID ClassID; + IContextMenu * CMenu; + struct _DynamicShellEntry_ * Next; +}DynamicShellEntry, *PDynamicShellEntry; + +typedef struct _StaticShellEntry_ +{ + LPWSTR szVerb; + LPWSTR szClass; + struct _StaticShellEntry_ * Next; +}StaticShellEntry, *PStaticShellEntry; + + +typedef struct +{ + const IContextMenu2Vtbl *lpVtbl; + LONG ref; + DEFCONTEXTMENU dcm; + IDataObject * pDataObj; + DWORD bGroupPolicyActive; + PDynamicShellEntry dhead; /* first dynamic shell extension entry */ + UINT iIdSHEFirst; /* first used id */ + UINT iIdSHELast; /* last used id */ + PStaticShellEntry shead; /* first static shell extension entry */ + UINT iIdSCMFirst; /* first static used id */ + UINT iIdSCMLast; /* last static used id */ +}IDefaultContextMenuImpl; + +static inline IDefaultContextMenuImpl *impl_from_IContextMenu( IContextMenu2 *iface ) +{ + return (IDefaultContextMenuImpl *)((char*)iface - FIELD_OFFSET(IDefaultContextMenuImpl, lpVtbl)); +} + +VOID INewItem_SetCurrentShellFolder(IShellFolder * psfParent); // HACK + + +static +HRESULT +WINAPI +IDefaultContextMenu_fnQueryInterface( + IContextMenu2 *iface, + REFIID riid, + LPVOID *ppvObj) +{ + IDefaultContextMenuImpl *This = (IDefaultContextMenuImpl *)iface; + + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IContextMenu) || + IsEqualIID(riid, &IID_IContextMenu2)) + { + *ppvObj = This; + } + + if(*ppvObj) + { + IUnknown_AddRef((IUnknown*)*ppvObj); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + TRACE("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + + +static +ULONG +WINAPI +IDefaultContextMenu_fnAddRef( + IContextMenu2 *iface) +{ + IDefaultContextMenuImpl *This = (IDefaultContextMenuImpl *)iface; + ULONG refCount = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(count=%u)\n", This, refCount - 1); + + return refCount; +} + +static +ULONG +WINAPI +IDefaultContextMenu_fnRelease( + IContextMenu2 *iface) +{ + PDynamicShellEntry dEntry, dNext; + PStaticShellEntry sEntry, sNext; + IDefaultContextMenuImpl *This = (IDefaultContextMenuImpl *)iface; + ULONG refCount = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(count=%u)\n", This, refCount + 1); + if (!refCount) + { + /* free dynamic shell extension entries */ + dEntry = This->dhead; + while(dEntry) + { + dNext = dEntry->Next; + IContextMenu_Release(dEntry->CMenu); + HeapFree(GetProcessHeap(), 0, dEntry); + dEntry = dNext; + } + /* free static shell extension entries */ + sEntry = This->shead; + while(sEntry) + { + sNext = sEntry->Next; + HeapFree(GetProcessHeap(), 0, sEntry->szClass); + HeapFree(GetProcessHeap(), 0, sEntry->szVerb); + HeapFree(GetProcessHeap(), 0, sEntry); + sEntry = sNext; + } + HeapFree(GetProcessHeap(),0,This); + } + + return refCount; +} + +static +void +SH_AddStaticEntry(IDefaultContextMenuImpl * This, WCHAR *szVerb, WCHAR * szClass) +{ + PStaticShellEntry curEntry; + PStaticShellEntry lastEntry = NULL; + + curEntry = This->shead; + while(curEntry) + { + if (!wcsicmp(curEntry->szVerb, szVerb)) + { + /* entry already exists */ + return; + } + lastEntry = curEntry; + curEntry = curEntry->Next; + } + + TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass)); + + curEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry)); + if (curEntry) + { + curEntry->Next = NULL; + curEntry->szVerb = HeapAlloc(GetProcessHeap(), 0, (wcslen(szVerb)+1) * sizeof(WCHAR)); + if (curEntry->szVerb) + wcscpy(curEntry->szVerb, szVerb); + curEntry->szClass = HeapAlloc(GetProcessHeap(), 0, (wcslen(szClass)+1) * sizeof(WCHAR)); + if (curEntry->szClass) + wcscpy(curEntry->szClass, szClass); + } + + if (lastEntry) + { + lastEntry->Next = curEntry; + } + else + { + This->shead = curEntry; + } +} + +static +void +SH_AddStaticEntryForKey(IDefaultContextMenuImpl * This, HKEY hKey, WCHAR * szClass) +{ + LONG result; + DWORD dwIndex; + WCHAR szName[40]; + DWORD dwName; + + dwIndex = 0; + do + { + szName[0] = 0; + dwName = sizeof(szName) / sizeof(WCHAR); + result = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL); + szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0; + if (result == ERROR_SUCCESS) + { + SH_AddStaticEntry(This, szName, szClass); + } + dwIndex++; + }while(result == ERROR_SUCCESS); +} + +static +void +SH_AddStaticEntryForFileClass(IDefaultContextMenuImpl * This, WCHAR * szExt) +{ + WCHAR szBuffer[100]; + HKEY hKey; + LONG result; + DWORD dwBuffer; + UINT Length; + static WCHAR szShell[] = L"\\shell"; + static WCHAR szShellAssoc[] = L"SystemFileAssociations\\"; + + TRACE("SH_AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt)); + + Length = wcslen(szExt); + if (Length + (sizeof(szShell)/sizeof(WCHAR)) + 1 < sizeof(szBuffer)/sizeof(WCHAR)) + { + wcscpy(szBuffer, szExt); + wcscpy(&szBuffer[Length], szShell); + result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); + if (result == ERROR_SUCCESS) + { + szBuffer[Length] = 0; + SH_AddStaticEntryForKey(This, hKey, szExt); + RegCloseKey(hKey); + } + } + + dwBuffer = sizeof(szBuffer); + result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer); + if (result == ERROR_SUCCESS) + { + Length = strlenW(szBuffer); + if (Length + (sizeof(szShell)/sizeof(WCHAR)) + 1 < sizeof(szBuffer)/sizeof(WCHAR)) + { + wcscpy(&szBuffer[Length], szShell); + TRACE("szBuffer %s\n", debugstr_w(szBuffer)); + + result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); + if (result == ERROR_SUCCESS) + { + szBuffer[Length] = 0; + SH_AddStaticEntryForKey(This, hKey, szBuffer); + RegCloseKey(hKey); + } + } + } + + wcscpy(szBuffer, szShellAssoc); + dwBuffer = sizeof(szBuffer) - sizeof(szShellAssoc) - sizeof(WCHAR); + result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[(sizeof(szShellAssoc)/sizeof(WCHAR))], &dwBuffer); + if (result == ERROR_SUCCESS) + { + Length = strlenW(&szBuffer[(sizeof(szShellAssoc)/sizeof(WCHAR))]) + (sizeof(szShellAssoc)/sizeof(WCHAR)); + wcscat(&szBuffer[(sizeof(szShellAssoc)/sizeof(WCHAR))], szShell); + TRACE("szBuffer %s\n", debugstr_w(szBuffer)); + + result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); + if (result == ERROR_SUCCESS) + { + szBuffer[Length] = 0; + SH_AddStaticEntryForKey(This, hKey, szBuffer); + RegCloseKey(hKey); + } + } + RegCloseKey(hKey); +} + +static +BOOL +HasClipboardData() +{ + BOOL ret = FALSE; + IDataObject * pda; + + if(SUCCEEDED(OleGetClipboard(&pda))) + { + STGMEDIUM medium; + FORMATETC formatetc; + + TRACE("pda=%p\n", pda); + + /* Set the FORMATETC structure*/ + InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); + if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium))) + { + ret = TRUE; + } + + IDataObject_Release(pda); + ReleaseStgMedium(&medium); + } + + return ret; +} + +VOID +DisablePasteOptions(HMENU hMenu) +{ + MENUITEMINFOW mii; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DISABLED; + + TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERT, FALSE, &mii)); + TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERTLINK, FALSE, &mii)); +} + +BOOL +IsShellExtensionAlreadyLoaded(IDefaultContextMenuImpl * This, const CLSID * szClass) +{ + PDynamicShellEntry curEntry = This->dhead; + + while(curEntry) + { + if (!memcmp(&curEntry->ClassID, szClass, sizeof(CLSID))) + return TRUE; + curEntry = curEntry->Next; + } + return FALSE; +} + + +static +HRESULT +SH_LoadDynamicContextMenuHandler(IDefaultContextMenuImpl * This, HKEY hKey, const CLSID * szClass, BOOL bExternalInit) +{ + HRESULT hr; + IContextMenu * cmobj; + IShellExtInit *shext; + PDynamicShellEntry curEntry; + //WCHAR szTemp[100]; + LPOLESTR pstr; + + StringFromCLSID(szClass, &pstr); + + TRACE("SH_LoadDynamicContextMenuHandler entered with This %p hKey %p szClass %s bExternalInit %u\n",This, hKey, wine_dbgstr_guid(szClass), bExternalInit); + //swprintf(szTemp, L"This %p hKey %p szClass %s bExternalInit %u", This, hKey, pstr, bExternalInit); + //MessageBoxW(NULL, szTemp, NULL, MB_OK); + + if (IsShellExtensionAlreadyLoaded(This, szClass)) + return S_OK; + + hr = SHCoCreateInstance(NULL, szClass, NULL, &IID_IContextMenu, (void**)&cmobj); + if (hr != S_OK) + { + TRACE("SHCoCreateInstance failed %x\n", GetLastError()); + return hr; + } + + if (bExternalInit) + { + hr = IContextMenu_QueryInterface(cmobj, &IID_IShellExtInit, (void**)&shext); + if (hr != S_OK) + { + TRACE("Failed to query for interface IID_IShellExtInit\n"); + IContextMenu_Release(cmobj); + return FALSE; + } + hr = IShellExtInit_Initialize(shext, NULL, This->pDataObj, hKey); + IShellExtInit_Release(shext); + if (hr != S_OK) + { + TRACE("Failed to initialize shell extension error %x\n", hr); + IContextMenu_Release(cmobj); + return hr; + } + } + + curEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry)); + if(!curEntry) + { + IContextMenu_Release(cmobj); + return E_OUTOFMEMORY; + } + + curEntry->iIdCmdFirst = 0; + curEntry->Next = NULL; + curEntry->NumIds = 0; + curEntry->CMenu = cmobj; + memcpy(&curEntry->ClassID, szClass, sizeof(CLSID)); + + if (This->dhead) + { + PDynamicShellEntry pEntry = This->dhead; + + while(pEntry->Next) + { + pEntry = pEntry->Next; + } + + pEntry->Next = curEntry; + } + else + { + This->dhead = curEntry; + } + + + if (!memcmp(szClass, &CLSID_NewMenu, sizeof(CLSID))) + { + /* A REAL UGLY HACK */ + INewItem_SetCurrentShellFolder(This->dcm.psf); + } + + + return hr; +} + +static +UINT +EnumerateDynamicContextHandlerForKey(IDefaultContextMenuImpl *This, HKEY hRootKey) +{ + WCHAR szKey[MAX_PATH] = {0}; + WCHAR szName[MAX_PATH] = {0}; + DWORD dwIndex, dwName; + LONG res; + HRESULT hResult; + UINT index; + CLSID clsid; + HKEY hKey; + + static const WCHAR szShellEx[] = { 's','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 }; + + if (RegOpenKeyExW(hRootKey, szShellEx, 0, KEY_READ, &hKey) != ERROR_SUCCESS) + { + TRACE("RegOpenKeyExW failed for key %s\n", debugstr_w(szKey)); + return 0; + } + + dwIndex = 0; + index = 0; + do + { + dwName = MAX_PATH; + res = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL); + if (res == ERROR_SUCCESS) + { + hResult = CLSIDFromString(szName, &clsid); + if (hResult != S_OK) + { + dwName = MAX_PATH; + if (RegGetValueW(hKey, szName, NULL, RRF_RT_REG_SZ, NULL, szKey, &dwName) == ERROR_SUCCESS) + { + hResult = CLSIDFromString(szKey, &clsid); + } + } + if (SUCCEEDED(hResult)) + { + if (This->bGroupPolicyActive) + { + if (RegGetValueW(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", + szKey, + RRF_RT_REG_SZ, + NULL, + NULL, + &dwName) == ERROR_SUCCESS) + { + SH_LoadDynamicContextMenuHandler(This, hKey, &clsid, TRUE); + } + } + else + { + SH_LoadDynamicContextMenuHandler(This, hKey, &clsid, TRUE); + } + } + } + dwIndex++; + }while(res == ERROR_SUCCESS); + + RegCloseKey(hKey); + return index; +} + + +static +UINT +InsertMenuItemsOfDynamicContextMenuExtension(IDefaultContextMenuImpl * This, HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast) +{ + PDynamicShellEntry curEntry; + HRESULT hResult; + + if (!This->dhead) + { + This->iIdSHEFirst = 0; + This->iIdSHELast = 0; + return indexMenu; + } + + curEntry = This->dhead; + idCmdFirst = 0x5000; + idCmdLast = 0x6000; + This->iIdSHEFirst = idCmdFirst; + do + { + hResult = IContextMenu_QueryContextMenu(curEntry->CMenu, hMenu, indexMenu++, idCmdFirst, idCmdLast, CMF_NORMAL); + if (SUCCEEDED(hResult)) + { + curEntry->iIdCmdFirst = idCmdFirst; + curEntry->NumIds = LOWORD(hResult); + indexMenu += curEntry->NumIds; + idCmdFirst += curEntry->NumIds + 0x10; + } + TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n", curEntry, hResult, curEntry->CMenu, curEntry->iIdCmdFirst, curEntry->NumIds); + curEntry = curEntry->Next; + }while(curEntry); + + This->iIdSHELast = idCmdFirst; + TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast); + return indexMenu; +} + +UINT +BuildBackgroundContextMenu( + IDefaultContextMenuImpl * This, + HMENU hMenu, + UINT iIdCmdFirst, + UINT iIdCmdLast, + UINT uFlags) +{ + MENUITEMINFOW mii; + WCHAR szBuffer[MAX_PATH]; + UINT indexMenu = 0; + HMENU hSubMenu; + HKEY hKey; + + ZeroMemory(&mii, sizeof(mii)); + + TRACE("BuildBackgroundContextMenu entered\n"); + + if (!_ILIsDesktop(This->dcm.pidlFolder)) + { + /* view option is only available in browsing mode */ + hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001"); + if (hSubMenu) + { + szBuffer[0] = 0; + LoadStringW(shell32_hInstance, FCIDM_SHVIEW_VIEW, szBuffer, MAX_PATH); + szBuffer[MAX_PATH-1] = 0; + + TRACE("szBuffer %s\n", debugstr_w(szBuffer)); + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID; + mii.fType = MFT_STRING; + mii.wID = iIdCmdFirst++; + mii.dwTypeData = szBuffer; + mii.cch = strlenW( mii.dwTypeData ); + mii.fState = MFS_ENABLED; + mii.hSubMenu = hSubMenu; + InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii); + DestroyMenu(hSubMenu); + } + } + hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_002"); + if (hSubMenu) + { + /* merge general background context menu in */ + iIdCmdFirst = Shell_MergeMenus(hMenu, GetSubMenu(hSubMenu, 0), indexMenu, 0, 0xFFFF, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS) + 1; + DestroyMenu(hSubMenu); + } + + if (!HasClipboardData()) + { + TRACE("disabling paste options\n"); + DisablePasteOptions(hMenu); + } + /* load extensions from HKCR\* key */ + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"*", + 0, + KEY_READ, + &hKey) == ERROR_SUCCESS) + { + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + + /* load create new shell extension */ + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, + L"CLSID\\{D969A300-E7FF-11d0-A93B-00A0C90F2719}", + 0, + KEY_READ, + &hKey) == ERROR_SUCCESS) + { + SH_LoadDynamicContextMenuHandler(This, hKey, &CLSID_NewMenu, TRUE); + RegCloseKey(hKey); + } + + if (InsertMenuItemsOfDynamicContextMenuExtension(This, hMenu, GetMenuItemCount(hMenu)-1, iIdCmdFirst, iIdCmdLast)) + { + /* seperate dynamic context menu items */ + _InsertMenuItemW(hMenu, GetMenuItemCount(hMenu)-1, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED); + } + + return iIdCmdLast; +} + +static +UINT +AddStaticContextMenusToMenu( + HMENU hMenu, + UINT indexMenu, + IDefaultContextMenuImpl * This) +{ + MENUITEMINFOW mii; + UINT idResource; + PStaticShellEntry curEntry; + WCHAR szVerb[40]; + WCHAR szTemp[50]; + DWORD dwSize; + UINT fState; + UINT Length; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; + mii.fType = MFT_STRING; + mii.fState = MFS_ENABLED | MFS_DEFAULT; + mii.wID = 0x4000; + This->iIdSCMFirst = mii.wID; + + curEntry = This->shead; + + while(curEntry) + { + fState = MFS_ENABLED; + if (!wcsicmp(curEntry->szVerb, L"open")) + { + fState |= MFS_DEFAULT; + idResource = IDS_OPEN_VERB; + } + else if (!wcsicmp(curEntry->szVerb, L"runas")) + idResource = IDS_RUNAS_VERB; + else if (!wcsicmp(curEntry->szVerb, L"edit")) + idResource = IDS_EDIT_VERB; + else if (!wcsicmp(curEntry->szVerb, L"find")) + idResource = IDS_FIND_VERB; + else if (!wcsicmp(curEntry->szVerb, L"print")) + idResource = IDS_PRINT_VERB; + else if (!wcsicmp(curEntry->szVerb, L"play")) + idResource = IDS_PLAY_VERB; + else if (!wcsicmp(curEntry->szVerb, L"preview")) + idResource = IDS_PREVIEW_VERB; + else + idResource = 0; + + if (idResource > 0) + { + if (LoadStringW(shell32_hInstance, idResource, szVerb, sizeof(szVerb)/sizeof(WCHAR))) + { + /* use translated verb */ + szVerb[(sizeof(szVerb)/sizeof(WCHAR))-1] = L'\0'; + mii.dwTypeData = szVerb; + } + } + else + { + Length = wcslen(curEntry->szClass) + wcslen(curEntry->szVerb) + 8; + if (Length < sizeof(szTemp)/sizeof(WCHAR)) + { + wcscpy(szTemp, curEntry->szClass); + wcscat(szTemp, L"\\shell\\"); + wcscat(szTemp, curEntry->szVerb); + dwSize = sizeof(szVerb); + + if (RegGetValueW(HKEY_CLASSES_ROOT, szTemp, NULL, RRF_RT_REG_SZ, NULL, szVerb, &dwSize) == ERROR_SUCCESS) + { + /* use description for the menu entry */ + mii.dwTypeData = szVerb; + } + else + { + /* use verb for the menu entry */ + mii.dwTypeData = curEntry->szVerb; + } + } + + } + + mii.cch = strlenW(mii.dwTypeData); + InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii); + mii.fState = fState; + mii.wID++; + curEntry = curEntry->Next; + } + This->iIdSCMLast = mii.wID - 1; + return indexMenu; +} + +void WINAPI _InsertMenuItemW ( + HMENU hmenu, + UINT indexMenu, + BOOL fByPosition, + UINT wID, + UINT fType, + LPCWSTR dwTypeData, + UINT fState) +{ + MENUITEMINFOW mii; + WCHAR szText[100]; + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + if (fType == MFT_SEPARATOR) + { + mii.fMask = MIIM_ID | MIIM_TYPE; + } + else if (fType == MFT_STRING) + { + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0) + { + if (LoadStringW(shell32_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText)/sizeof(WCHAR))) + { + szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0; + mii.dwTypeData = szText; + } + else + { + TRACE("failed to load string %p\n", dwTypeData); + return; + } + } + else + { + mii.dwTypeData = (LPWSTR) dwTypeData; + } + mii.fState = fState; + } + + mii.wID = wID; + mii.fType = fType; + InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii); +} + +UINT +BuildShellItemContextMenu( + IDefaultContextMenuImpl * This, + HMENU hMenu, + UINT iIdCmdFirst, + UINT iIdCmdLast, + UINT uFlags) +{ + WCHAR szPath[MAX_PATH]; + WCHAR szTemp[40]; + HKEY hKey; + UINT indexMenu; + SFGAOF rfg; + HRESULT hr; + BOOL bAddSep; + GUID * guid; + BOOL bClipboardData; + STRRET strFile; + LPWSTR pOffset; + DWORD dwSize; + + TRACE("BuildShellItemContextMenu entered\n"); + + if (IShellFolder2_GetDisplayNameOf(This->dcm.psf, This->dcm.apidl[0], SHGDN_FORPARSING, &strFile) == S_OK) + { + if (StrRetToBufW(&strFile, This->dcm.apidl[0], szPath, MAX_PATH) == S_OK) + { + pOffset = wcsrchr(szPath, L'.'); + if (pOffset) + { + /* enumerate dynamic/static for a given file class */ + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pOffset, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* add static verbs */ + SH_AddStaticEntryForFileClass(This, pOffset); + /* load dynamic extensions from file extension key */ + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + dwSize = sizeof(szTemp); + if (RegGetValueW(HKEY_CLASSES_ROOT, pOffset, NULL, RRF_RT_REG_SZ, NULL, szTemp, &dwSize) == ERROR_SUCCESS) + { + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* add static verbs from progid key */ + SH_AddStaticEntryForFileClass(This, szTemp); + /* load dynamic extensions from progid key */ + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + } + } + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"*", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* load default extensions */ + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + } + } + + guid = _ILGetGUIDPointer(This->dcm.apidl[0]); + if (guid) + { + LPOLESTR pwszCLSID; + WCHAR buffer[60]; + + wcscpy(buffer, L"CLSID\\"); + hr = StringFromCLSID(guid, &pwszCLSID); + if (hr == S_OK) + { + wcscpy(&buffer[6], pwszCLSID); + TRACE("buffer %s\n", debugstr_w(buffer)); + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + EnumerateDynamicContextHandlerForKey(This, hKey); + SH_AddStaticEntryForFileClass(This, buffer); + RegCloseKey(hKey); + } + CoTaskMemFree(pwszCLSID); + } + } + + + if (_ILIsDrive(This->dcm.apidl[0])) + { + SH_AddStaticEntryForFileClass(This, L"Drive"); + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Drive", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + + } + + /* add static actions */ + rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER; + hr = IShellFolder_GetAttributesOf(This->dcm.psf, This->dcm.cidl, This->dcm.apidl, &rfg); + if (!SUCCEEDED(hr)) + rfg = 0; + + if (rfg & SFGAO_FOLDER) + { + /* add the default verbs open / explore */ + SH_AddStaticEntryForFileClass(This, L"Folder"); + SH_AddStaticEntryForFileClass(This, L"Directory"); + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + } + + + if (rfg & SFGAO_FILESYSTEM) + { + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"AllFilesystemObjects", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* sendto service is registered here */ + EnumerateDynamicContextHandlerForKey(This, hKey); + RegCloseKey(hKey); + } + } + + /* add static context menu handlers */ + indexMenu = AddStaticContextMenusToMenu(hMenu, 0, This); + /* now process dynamic context menu handlers */ + indexMenu = InsertMenuItemsOfDynamicContextMenuExtension(This, hMenu, indexMenu, iIdCmdFirst, iIdCmdLast); + TRACE("indexMenu %d\n", indexMenu); + + if (_ILIsDrive(This->dcm.apidl[0])) + { + /* The 'Format' option must be always available, + * thus it is not registered as a static shell extension + */ + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED); + bAddSep = TRUE; + } + + bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM)); + if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData) + { + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + if (rfg & SFGAO_CANMOVE) + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, MAKEINTRESOURCEW(IDS_CUT), MFS_ENABLED); + if (rfg & SFGAO_CANCOPY) + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, MAKEINTRESOURCEW(IDS_COPY), MFS_ENABLED); + if (bClipboardData) + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_INSERT, MFT_STRING, MAKEINTRESOURCEW(IDS_INSERT), MFS_ENABLED); + + bAddSep = TRUE; + } + + + if (rfg & SFGAO_CANLINK) + { + bAddSep = FALSE; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED); + } + + + if (rfg & SFGAO_CANDELETE) + { + if (bAddSep) + { + bAddSep = FALSE; + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + } + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_DELETE), MFS_ENABLED); + } + + if (rfg & SFGAO_CANRENAME) + { + if (bAddSep) + { + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + } + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_RENAME), MFS_ENABLED); + bAddSep = TRUE; + } + + if (rfg & SFGAO_HASPROPSHEET) + { + _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); + _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED); + } + + return iIdCmdLast; +} + +static +HRESULT +WINAPI +IDefaultContextMenu_fnQueryContextMenu( + IContextMenu2 *iface, + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + IDefaultContextMenuImpl * This = impl_from_IContextMenu(iface); + if (This->dcm.cidl) + { + idCmdFirst = BuildShellItemContextMenu(This, hmenu, idCmdFirst, idCmdLast, uFlags); + } + else + { + idCmdFirst = BuildBackgroundContextMenu(This, hmenu, idCmdFirst, idCmdLast, uFlags); + } + + return S_OK; +} + +static +HRESULT +NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh) +{ + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV = NULL; + HWND hwndSV = NULL; + + if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) + { + if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) + { + IShellView_GetWindow(lpSV, &hwndSV); + } + } + + if (LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_REFRESH || bRefresh) + { + if (lpSV) + IShellView_Refresh(lpSV); + + return S_OK; + } + + SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0); + + return S_OK; +} + +static +HRESULT +DoPaste( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + IDataObject * pda; + STGMEDIUM medium; + FORMATETC formatetc; + LPITEMIDLIST * apidl; + LPITEMIDLIST pidl; + IShellFolder *psfFrom = NULL, *psfDesktop, *psfTarget = NULL; + LPIDA lpcida; + ISFHelper *psfhlpdst, *psfhlpsrc; + HRESULT hr; + + if (OleGetClipboard(&pda) != S_OK) + return E_FAIL; + + InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); + hr = IDataObject_GetData(pda,&formatetc,&medium); + + if (FAILED(hr)) + { + IDataObject_Release(pda); + return E_FAIL; + } + + /* lock the handle */ + lpcida = GlobalLock(medium.u.hGlobal); + if (!lpcida) + { + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + return E_FAIL; + } + + /* convert the data into pidl */ + apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + + if (!apidl) + return E_FAIL; + + if (FAILED(SHGetDesktopFolder(&psfDesktop))) + { + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + return E_FAIL; + } + + if (FAILED(IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom))) + { + ERR("no IShellFolder\n"); + + IShellFolder_Release(psfDesktop); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + + return E_FAIL; + } + + IShellFolder_Release(psfDesktop); + + if (FAILED(IShellFolder_BindToObject(This->dcm.psf, This->dcm.apidl[0], NULL, &IID_IShellFolder, (LPVOID*)&psfTarget))) + { + ERR("no IShellFolder\n"); + + IShellFolder_Release(psfFrom); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + + return E_FAIL; + } + + + /* get source and destination shellfolder */ + if (FAILED(IShellFolder_QueryInterface(psfTarget, &IID_ISFHelper, (LPVOID*)&psfhlpdst))) + { + ERR("no IID_ISFHelper for destination\n"); + + IShellFolder_Release(psfFrom); + IShellFolder_Release(psfTarget); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + + return E_FAIL; + } + + if (FAILED(IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc))) + { + ERR("no IID_ISFHelper for source\n"); + + ISFHelper_Release(psfhlpdst); + IShellFolder_Release(psfFrom); + IShellFolder_Release(psfTarget); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + return E_FAIL; + } + + /* FIXXME + * do we want to perform a copy or move ??? + */ + hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); + + ISFHelper_Release(psfhlpdst); + ISFHelper_Release(psfhlpsrc); + IShellFolder_Release(psfFrom); + IShellFolder_Release(psfTarget); + SHFree(pidl); + _ILFreeaPidl(apidl, lpcida->cidl); + ReleaseStgMedium(&medium); + IDataObject_Release(pda); + return S_OK; +} + +static +HRESULT +DoOpenOrExplore( + IDefaultContextMenuImpl *iface, + LPCMINVOKECOMMANDINFO lpcmi) +{ + + + return E_FAIL; +} + +BOOL +GetUniqueFileName(LPWSTR szBasePath, LPWSTR szExt, LPWSTR szTarget, BOOL bShortcut) +{ + UINT RetryCount = 0, Length; + WCHAR szLnk[40]; + HANDLE hFile; + + if (!bShortcut) + { + Length = LoadStringW(shell32_hInstance, IDS_LNK_FILE, szLnk, sizeof(szLnk)/sizeof(WCHAR)); + } + + do + { + if (!bShortcut) + { + if (RetryCount) + swprintf(szTarget, L"%s%s(%u).%s", szLnk, szBasePath, RetryCount, szExt); + else + swprintf(szTarget, L"%s%s.%s", szLnk, szBasePath, szExt); + } + else + { + if (RetryCount) + swprintf(szTarget, L"%s(%u).%s", szBasePath, RetryCount, szExt); + else + swprintf(szTarget, L"%s.%s", szBasePath, szExt); + } + + hFile = CreateFileW(szTarget, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + return TRUE; + } + + }while(RetryCount++ < 100); + + return FALSE; + +} + +static +HRESULT +DoCreateLink( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + WCHAR szPath[MAX_PATH]; + WCHAR szTarget[MAX_PATH] = {0}; + STRRET strFile; + LPWSTR pszExt; + HRESULT hr; + IShellLinkW * nLink; + IPersistFile * ipf; + static WCHAR szLnk[] = L"lnk"; + + if (IShellFolder2_GetDisplayNameOf(This->dcm.psf, This->dcm.apidl[0], SHGDN_FORPARSING, &strFile) != S_OK) + { + ERR("IShellFolder_GetDisplayNameOf failed for apidl\n"); + return E_FAIL; + } + + if (StrRetToBufW(&strFile, This->dcm.apidl[0], szPath, MAX_PATH) != S_OK) + return E_FAIL; + + + pszExt = wcsrchr(szPath, L'.'); + pszExt[0] = 0; + + if (!wcsicmp(pszExt + 1, szLnk)) + { + if (!GetUniqueFileName(szPath, pszExt + 1, szTarget, TRUE)) + return E_FAIL; + + hr = IShellLink_ConstructFromFile(NULL, &IID_IPersistFile, This->dcm.apidl[0], (LPVOID*)&ipf); + if (hr != S_OK) + { + return hr; + } + hr = IPersistFile_Save(ipf, szTarget, FALSE); + IPersistFile_Release(ipf); + NotifyShellViewWindow(lpcmi, TRUE); + return hr; + } + else + { + if (!GetUniqueFileName(szPath, szLnk, szTarget, TRUE)) + return E_FAIL; + + hr = IShellLink_Constructor(NULL, &IID_IShellLinkW, (LPVOID*)&nLink); + if (hr != S_OK) + { + return E_FAIL; + } + pszExt[0] = '.'; + if (SUCCEEDED(IShellLinkW_SetPath(nLink, szPath))) + { + if (SUCCEEDED(IShellLinkW_QueryInterface(nLink, &IID_IPersistFile, (LPVOID*)&ipf))) + { + hr = IPersistFile_Save(ipf, szTarget, TRUE); + IPersistFile_Release(ipf); + } + } + IShellLinkW_Release(nLink); + NotifyShellViewWindow(lpcmi, TRUE); + return hr; + } +} + +static +HRESULT +DoDelete( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + HRESULT hr; + STRRET strTemp; + WCHAR szPath[MAX_PATH]; + SHFILEOPSTRUCTW op; + int ret; + LPSHELLBROWSER lpSB; + HWND hwnd; + + + hr = IShellFolder2_GetDisplayNameOf(This->dcm.psf, This->dcm.apidl[0], SHGDN_FORPARSING, &strTemp); + if(hr != S_OK) + { + ERR("IShellFolder_GetDisplayNameOf failed with %x\n", hr); + return hr; + } + ZeroMemory(szPath, sizeof(szPath)); + hr = StrRetToBufW(&strTemp, This->dcm.apidl[0], szPath, MAX_PATH); + if (hr != S_OK) + { + ERR("StrRetToBufW failed with %x\n", hr); + return hr; + } + /* FIXME + * implement deletion with multiple files + */ + + ZeroMemory(&op, sizeof(op)); + op.hwnd = GetActiveWindow(); + op.wFunc = FO_DELETE; + op.pFrom = szPath; + op.fFlags = FOF_ALLOWUNDO; + ret = SHFileOperationW(&op); + + if (ret) + { + TRACE("SHFileOperation failed with %0x%x", GetLastError()); + return S_OK; + } + + /* get the active IShellView */ + if ((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) + { + /* is the treeview focused */ + if (SUCCEEDED(IShellBrowser_GetControlWindow(lpSB, FCW_TREE, &hwnd))) + { + HTREEITEM hItem = TreeView_GetSelection(hwnd); + if (hItem) + { + (void)TreeView_DeleteItem(hwnd, hItem); + } + return S_OK; + } + } + NotifyShellViewWindow(lpcmi, TRUE); + + return S_OK; + +} + +static +HRESULT +DoCopyOrCut( + IDefaultContextMenuImpl *iface, + LPCMINVOKECOMMANDINFO lpcmi, + BOOL bCopy) +{ + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV; + LPDATAOBJECT lpDo; + HRESULT hr; + + lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0); + if (!lpSB) + { + TRACE("failed to get shellbrowser\n"); + return E_FAIL; + } + + hr = IShellBrowser_QueryActiveShellView(lpSB, &lpSV); + if (FAILED(hr)) + { + TRACE("failed to query the active shellview\n"); + return hr; + } + + hr = IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo); + if (FAILED(hr)) + { + TRACE("failed to get item object\n"); + return hr; + } + + hr = OleSetClipboard(lpDo); + if (FAILED(hr)) + { + WARN("OleSetClipboard failed"); + } + IDataObject_Release(lpDo); + IShellView_Release(lpSV); + return S_OK; +} + +static +HRESULT +DoRename( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + LPSHELLBROWSER lpSB; + LPSHELLVIEW lpSV; + HWND hwnd; + + /* get the active IShellView */ + if ((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER,0,0))) + { + /* is the treeview focused */ + if (SUCCEEDED(IShellBrowser_GetControlWindow(lpSB, FCW_TREE, &hwnd))) + { + HTREEITEM hItem = TreeView_GetSelection(hwnd); + if (hItem) + { + (void)TreeView_EditLabel(hwnd, hItem); + } + } + + if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) + { + IShellView_SelectItem(lpSV, This->dcm.apidl[0], + SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT); + IShellView_Release(lpSV); + return S_OK; + } + } + return E_FAIL; +} + +static +HRESULT +DoProperties( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + WCHAR szDrive[MAX_PATH]; + STRRET strFile; + + if (_ILIsMyComputer(This->dcm.apidl[0])) + { + ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL); + return S_OK; + } + else if (_ILIsDesktop(This->dcm.apidl[0])) + { + ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL); + return S_OK; + } + else if (_ILIsDrive(This->dcm.apidl[0])) + { + ILGetDisplayName(This->dcm.apidl[0], szDrive); + SH_ShowDriveProperties(szDrive, This->dcm.pidlFolder, This->dcm.apidl); + return S_OK; + } + else if (_ILIsNetHood(This->dcm.apidl[0])) + { + /* FIXME + * implement nethood properties + */ + FIXME("implement network connection shell folder\n"); + return S_OK; + } + else if (_ILIsBitBucket(This->dcm.apidl[0])) + { + /* FIXME + * detect the drive path of bitbucket if appropiate + */ + + SH_ShowRecycleBinProperties(L'C'); + return S_OK; + } + + if (This->dcm.cidl > 1) + WARN("SHMultiFileProperties is not yet implemented\n"); + + if (IShellFolder2_GetDisplayNameOf(This->dcm.psf, This->dcm.apidl[0], SHGDN_FORPARSING, &strFile) != S_OK) + { + ERR("IShellFolder_GetDisplayNameOf failed for apidl\n"); + return E_FAIL; + } + + if (StrRetToBufW(&strFile, This->dcm.apidl[0], szDrive, MAX_PATH) != S_OK) + return E_FAIL; + + return SH_ShowPropertiesDialog(szDrive, This->dcm.pidlFolder, This->dcm.apidl); +} + +static +HRESULT +DoFormat( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + char sDrive[5] = {0}; + + if (!_ILGetDrive(This->dcm.apidl[0], sDrive, sizeof(sDrive))) + { + ERR("pidl is not a drive\n"); + return E_FAIL; + } + + SHFormatDrive(lpcmi->hwnd, sDrive[0] - 'A', SHFMT_ID_DEFAULT, 0); + return S_OK; +} + +static +HRESULT +DoDynamicShellExtensions( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + UINT verb = LOWORD(lpcmi->lpVerb); + PDynamicShellEntry pCurrent = This->dhead; + + TRACE("verb %p first %x last %x", lpcmi->lpVerb, This->iIdSHEFirst, This->iIdSHELast); + + while(pCurrent && verb > pCurrent->iIdCmdFirst + pCurrent->NumIds) + pCurrent = pCurrent->Next; + + if (!pCurrent) + return E_FAIL; + + if (verb >= pCurrent->iIdCmdFirst && verb <= pCurrent->iIdCmdFirst + pCurrent->NumIds) + { + /* invoke the dynamic context menu */ + lpcmi->lpVerb = MAKEINTRESOURCE(verb - pCurrent->iIdCmdFirst); + return IContextMenu_InvokeCommand(pCurrent->CMenu, lpcmi); + } + + return E_FAIL; +} + + +static +HRESULT +DoStaticShellExtensions( + IDefaultContextMenuImpl *This, + LPCMINVOKECOMMANDINFO lpcmi) +{ + SHELLEXECUTEINFOW sei; + PStaticShellEntry pCurrent = This->shead; + int verb = LOWORD(lpcmi->lpVerb) - This->iIdSCMFirst; + + + while(pCurrent && verb-- > 0) + pCurrent = pCurrent->Next; + + if (verb > 0) + return E_FAIL; + + + ZeroMemory(&sei, sizeof(sei)); + sei.cbSize = sizeof(sei); + sei.fMask = SEE_MASK_CLASSNAME | SEE_MASK_IDLIST; + sei.lpClass = pCurrent->szClass; + sei.hwnd = lpcmi->hwnd; + sei.nShow = SW_SHOWNORMAL; + sei.lpVerb = pCurrent->szVerb; + sei.lpIDList = ILCombine(This->dcm.pidlFolder, This->dcm.apidl[0]); + ShellExecuteExW(&sei); + SHFree(sei.lpIDList); + return S_OK; + +} + +static +HRESULT +WINAPI +IDefaultContextMenu_fnInvokeCommand( + IContextMenu2 *iface, + LPCMINVOKECOMMANDINFO lpcmi) +{ + IDefaultContextMenuImpl * This = impl_from_IContextMenu(iface); + + switch(LOWORD(lpcmi->lpVerb)) + { + case FCIDM_SHVIEW_BIGICON: + case FCIDM_SHVIEW_SMALLICON: + case FCIDM_SHVIEW_LISTVIEW: + case FCIDM_SHVIEW_REPORTVIEW: + case 0x30: /* FIX IDS in resource files */ + case 0x31: + case 0x32: + case 0x33: + case FCIDM_SHVIEW_AUTOARRANGE: + case FCIDM_SHVIEW_SNAPTOGRID: + case FCIDM_SHVIEW_REFRESH: + return NotifyShellViewWindow(lpcmi, FALSE); + case FCIDM_SHVIEW_INSERT: + case FCIDM_SHVIEW_INSERTLINK: + return DoPaste(This, lpcmi); + case FCIDM_SHVIEW_OPEN: + case FCIDM_SHVIEW_EXPLORE: + return DoOpenOrExplore(This, lpcmi); + case FCIDM_SHVIEW_COPY: + case FCIDM_SHVIEW_CUT: + return DoCopyOrCut(This, lpcmi, LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_COPY); + case FCIDM_SHVIEW_CREATELINK: + return DoCreateLink(This, lpcmi); + case FCIDM_SHVIEW_DELETE: + return DoDelete(This, lpcmi); + case FCIDM_SHVIEW_RENAME: + return DoRename(This, lpcmi); + case FCIDM_SHVIEW_PROPERTIES: + return DoProperties(This, lpcmi); + case 0x7ABC: + return DoFormat(This, lpcmi); + } + + if (This->iIdSHEFirst && This->iIdSHELast) + { + if (LOWORD(lpcmi->lpVerb) >= This->iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSHELast) + { + return DoDynamicShellExtensions(This, lpcmi); + } + } + + if (This->iIdSCMFirst && This->iIdSCMLast) + { + if (LOWORD(lpcmi->lpVerb) >= This->iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSCMLast) + { + return DoStaticShellExtensions(This, lpcmi); + } + } + + FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb)); + return E_UNEXPECTED; +} + +static +HRESULT +WINAPI +IDefaultContextMenu_fnGetCommandString( + IContextMenu2 *iface, + UINT_PTR idCommand, + UINT uFlags, + UINT* lpReserved, + LPSTR lpszName, + UINT uMaxNameLen) +{ + + return S_OK; +} + +static +HRESULT +WINAPI +IDefaultContextMenu_fnHandleMenuMsg( + IContextMenu2 *iface, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + + return S_OK; +} + +static const IContextMenu2Vtbl cmvt = +{ + IDefaultContextMenu_fnQueryInterface, + IDefaultContextMenu_fnAddRef, + IDefaultContextMenu_fnRelease, + IDefaultContextMenu_fnQueryContextMenu, + IDefaultContextMenu_fnInvokeCommand, + IDefaultContextMenu_fnGetCommandString, + IDefaultContextMenu_fnHandleMenuMsg +}; +static +HRESULT +IDefaultContextMenu_Constructor( + const DEFCONTEXTMENU *pdcm, + REFIID riid, + void **ppv) +{ + IDefaultContextMenuImpl * This; + HRESULT hr = E_FAIL; + IDataObject * pDataObj; + + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDefaultContextMenuImpl)); + if (This) + { + This->lpVtbl = &cmvt; + This->ref = 1; + TRACE("cidl %u\n", This->dcm.cidl); + if (SUCCEEDED(SHCreateDataObject(pdcm->pidlFolder, pdcm->cidl, pdcm->apidl, NULL, &IID_IDataObject, (void**)&pDataObj))) + { + This->pDataObj = pDataObj; + } + CopyMemory(&This->dcm, pdcm, sizeof(DEFCONTEXTMENU)); + hr = IDefaultContextMenu_fnQueryInterface((IContextMenu2*)This, riid, ppv); + if (SUCCEEDED(hr)) + IContextMenu_Release((IContextMenu2*)This); + } + + TRACE("This(%p)(%x) cidl %u\n",This, hr, This->dcm.cidl); + return hr; +} + +/************************************************************************* + * SHCreateDefaultContextMenu [SHELL32.325] Vista API + * + */ + +HRESULT +WINAPI +SHCreateDefaultContextMenu( + const DEFCONTEXTMENU *pdcm, + REFIID riid, + void **ppv) +{ + HRESULT hr = E_FAIL; + + *ppv = NULL; + hr = IDefaultContextMenu_Constructor( pdcm, riid, ppv ); + + TRACE("pcm %p hr %x\n", pdcm, hr); + return hr; +} + +/************************************************************************* + * CDefFolderMenu_Create2 [SHELL32.701] + * + */ + +INT +WINAPI +CDefFolderMenu_Create2( + LPCITEMIDLIST pidlFolder, + HWND hwnd, + UINT cidl, + LPCITEMIDLIST *apidl, + IShellFolder *psf, + LPFNDFMCALLBACK lpfn, + UINT nKeys, + HKEY *ahkeyClsKeys, + IContextMenu **ppcm) +{ + DEFCONTEXTMENU pdcm; + HRESULT hr; + + 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; + + hr = SHCreateDefaultContextMenu(&pdcm, &IID_IContextMenu, (void**)ppcm); + return hr; +} + diff --git a/reactos/dll/win32/shell32/shv_item_cmenu.c b/reactos/dll/win32/shell32/shv_item_cmenu.c deleted file mode 100644 index 257f89152db..00000000000 --- a/reactos/dll/win32/shell32/shv_item_cmenu.c +++ /dev/null @@ -1,1373 +0,0 @@ -/* - * IContextMenu for items in the shellview - * - * Copyright 1998, 2000 Juergen Schmied - * - * 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 St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT -#include "winerror.h" -#include "wine/debug.h" - -#include "windef.h" -#include "wingdi.h" -#include "pidl.h" -#include "undocshell.h" -#include "shlobj.h" -#include "objbase.h" - -#include "shlwapi.h" -#include "shell32_main.h" -#include "shellfolder.h" -#include "debughlp.h" -#include "shresdef.h" -WINE_DEFAULT_DEBUG_CHANNEL(shell); - -/* ugly hack for cut&paste files */ -BOOL fileMoving = FALSE; - -typedef struct _StaticShellEntry_ -{ - LPWSTR szVerb; - LPWSTR szClass; - struct _StaticShellEntry_ * Next; -}StaticShellEntry, *PStaticShellEntry; - -typedef struct _DynamicShellEntry_ -{ - UINT iIdCmdFirst; - UINT NumIds; - IContextMenu * CMenu; - struct _DynamicShellEntry_ * Next; -}DynamicShellEntry, *PDynamicShellEntry; - -/************************************************************************** -* IContextMenu Implementation -*/ - -typedef struct -{ const IContextMenu2Vtbl *lpVtbl; - LONG ref; - IShellFolder* pSFParent; - LPITEMIDLIST pidl; /* root pidl */ - LPITEMIDLIST *apidl; /* array of child pidls */ - UINT cidl; - BOOL bAllValues; - PDynamicShellEntry dhead; - PStaticShellEntry head; - UINT iIdSCMFirst; - UINT iIdSCMLast; - UINT iIdSHEFirst; - UINT iIdSHELast; - SFGAOF rfg; -} ItemCmImpl; - -UINT -SH_EnumerateDynamicContextHandlerForKey(LPWSTR szFileClass, ItemCmImpl *This, IDataObject * pDataObj, DWORD bGroupPolicyActive); -WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls); -WCHAR *strdupW(LPWSTR str); -static const IContextMenu2Vtbl cmvt; - -/************************************************************************** -* ISvItemCm_CanRenameItems() -*/ -static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This) -{ UINT i; - DWORD dwAttributes; - - TRACE("(%p)->()\n",This); - - if(This->apidl) - { - for(i = 0; i < This->cidl; i++){} - if(i > 1) return FALSE; /* can't rename more than one item at a time*/ - dwAttributes = SFGAO_CANRENAME; - IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)This->apidl, &dwAttributes); - return dwAttributes & SFGAO_CANRENAME; - } - return FALSE; -} - -/************************************************************************** -* ISvItemCm_Constructor() -*/ -IContextMenu2 *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl) -{ ItemCmImpl* cm; - UINT u; - - cm = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl)); - cm->lpVtbl = &cmvt; - cm->ref = 1; - cm->pidl = ILClone(pidl); - cm->pSFParent = pSFParent; - - if(pSFParent) - { - HRESULT hr; - IShellFolder_AddRef(pSFParent); - cm->rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET; - hr = IShellFolder_GetAttributesOf(pSFParent, cidl, (LPCITEMIDLIST *)apidl, &cm->rfg); - if (!SUCCEEDED(hr)) - cm->rfg = 0; /* No action available */ - } - - cm->apidl = _ILCopyaPidl(apidl, cidl); - cm->cidl = cidl; - - cm->bAllValues = 1; - for(u = 0; u < cidl; u++) - { - cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0); - } - - TRACE("(%p)->()\n",cm); - - return (IContextMenu2*)cm; -} - -/************************************************************************** -* ISvItemCm_fnQueryInterface -*/ -static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - - *ppvObj = NULL; - - if(IsEqualIID(riid, &IID_IUnknown) || - IsEqualIID(riid, &IID_IContextMenu) || - IsEqualIID(riid, &IID_IContextMenu2)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/ - { - FIXME("-- LPSHELLEXTINIT pointer requested\n"); - } - - if(*ppvObj) - { - IUnknown_AddRef((IUnknown*)*ppvObj); - TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); - return S_OK; - } - TRACE("-- Interface: E_NOINTERFACE\n"); - return E_NOINTERFACE; -} - -/************************************************************************** -* ISvItemCm_fnAddRef -*/ -static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu2 *iface) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(count=%u)\n", This, refCount - 1); - - return refCount; -} - -/************************************************************************** -* ISvItemCm_fnRelease -*/ -static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu2 *iface) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->ref); - PStaticShellEntry curEntry; - PStaticShellEntry nextEntry; - - - TRACE("(%p)->(count=%i)\n", This, refCount + 1); - - if (!refCount) - { - TRACE(" destroying IContextMenu(%p)\n",This); - - curEntry = nextEntry = This->head; - while(nextEntry) - { - nextEntry = nextEntry->Next; - free(curEntry->szVerb); - free(curEntry->szClass); - free(curEntry); - curEntry = nextEntry; - } - - if(This->pSFParent) - IShellFolder_Release(This->pSFParent); - - SHFree(This->pidl); - - /*make sure the pidl is freed*/ - _ILFreeaPidl(This->apidl, This->cidl); - - HeapFree(GetProcessHeap(),0,This); - } - return refCount; -} - -/************************************************************************** -* ICM_InsertItem() -*/ -void WINAPI _InsertMenuItem ( - HMENU hmenu, - UINT indexMenu, - BOOL fByPosition, - UINT wID, - UINT fType, - LPCSTR dwTypeData, - UINT fState) -{ - MENUITEMINFOA mii; - - ZeroMemory(&mii, sizeof(mii)); - mii.cbSize = sizeof(mii); - if (fType == MFT_SEPARATOR) - { - mii.fMask = MIIM_ID | MIIM_TYPE; - } - else - { - mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; - mii.dwTypeData = (LPSTR) dwTypeData; - mii.fState = fState; - } - mii.wID = wID; - mii.fType = fType; - InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii); -} - -HRESULT -DoCustomItemAction(ItemCmImpl *This, LPARAM lParam, UINT uMsg) -{ - IContextMenu2 * cmenu; - MEASUREITEMSTRUCT * lpmis = (MEASUREITEMSTRUCT *)lParam; - HRESULT hResult; - UINT i; - PDynamicShellEntry curEntry; - - TRACE("DoCustomItemAction entered with uMsg %x lParam %p\n", uMsg, lParam); - - curEntry = This->dhead; - i = This->iIdSHEFirst; - - - while(curEntry) - { - if (i == lpmis->itemID) - break; - - i++; - curEntry = curEntry->Next; - } - - if (!curEntry) - return E_FAIL; - - hResult = IContextMenu_QueryInterface(curEntry->CMenu, &IID_IContextMenu2, (void**)&cmenu); - if (hResult != S_OK) - { - ERR("failed to get IID_IContextMenu2 interface\n"); - return hResult; - } - - hResult = IContextMenu2_HandleMenuMsg(cmenu, uMsg, (WPARAM)0, lParam); - IContextMenu2_Release(cmenu); - - TRACE("returning hResult %x\n", hResult); - return hResult; -} - -UINT -SH_LoadContextMenuHandlers(ItemCmImpl *This, IDataObject * pDataObj, HMENU hMenu, UINT indexMenu ) -{ - UINT i; - WCHAR buffer[111]; - WCHAR szProgKey[20]; - char ebuf[10]; - HRESULT hr; - HRESULT hResult; - UINT idCmdFirst = 0x6000; - UINT idCmdLast = 0xFFF0; - PDynamicShellEntry curEntry; - DWORD bGroupPolicyActive = FALSE; - DWORD dwSize; - static WCHAR szAny[] = { '*',0}; - - dwSize = sizeof(DWORD); - RegGetValueW(HKEY_CURRENT_USER, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", - L"EnforceShellExtensionSecurity", - RRF_RT_DWORD, - NULL, - &bGroupPolicyActive, - &dwSize); - - SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj, bGroupPolicyActive); - - for (i = 0; i < This->cidl; i++) - { - GUID * guid = _ILGetGUIDPointer(This->apidl[i]); - if (guid) - { - LPOLESTR pwszCLSID; - static const WCHAR CLSID[] = { 'C','L','S','I','D','\\',0 }; - wcscpy(buffer, CLSID); - hr = StringFromCLSID(guid, &pwszCLSID); - if (hr == S_OK) - { - wcscpy(&buffer[6], pwszCLSID); - TRACE("buffer %s\n", debugstr_w(buffer)); - SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj, bGroupPolicyActive); - } - } - - if (_ILGetExtension(This->apidl[i], &ebuf[1], sizeof(ebuf) / sizeof(char))) - { - ebuf[0] = L'.'; - buffer[0] = L'\0'; - if (MultiByteToWideChar(CP_ACP, 0, ebuf, -1, buffer, 111)) - { - SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj, bGroupPolicyActive); - dwSize = sizeof(szProgKey); - if (RegGetValueW(HKEY_CLASSES_ROOT, buffer, NULL, RRF_RT_REG_SZ, NULL, szProgKey, &dwSize) == ERROR_SUCCESS) - { - szProgKey[(sizeof(szProgKey)/sizeof(WCHAR))-1] = L'\0'; - SH_EnumerateDynamicContextHandlerForKey(szProgKey, This, pDataObj, bGroupPolicyActive); - } - } - } - } - TRACE("-- done loading\n"); - if (!This->dhead) - { - This->iIdSHEFirst = 0; - This->iIdSHELast = 0; - return indexMenu; - } - - curEntry = This->dhead; - This->iIdSHEFirst = idCmdFirst; - do - { - - hResult = IContextMenu_QueryContextMenu(curEntry->CMenu, hMenu, indexMenu, idCmdFirst, idCmdLast, CMF_NORMAL); - if (SUCCEEDED(hResult)) - { - curEntry->iIdCmdFirst = idCmdFirst; - curEntry->NumIds = LOWORD(hResult); - indexMenu += curEntry->NumIds; - idCmdFirst += curEntry->NumIds + 0x10; - } - TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n", curEntry, hResult, curEntry->CMenu, curEntry->iIdCmdFirst, curEntry->NumIds); - curEntry = curEntry->Next; - }while(curEntry); - - This->iIdSHELast = idCmdFirst; - TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast); - return indexMenu; -} - -void -SH_AddStaticEntry(ItemCmImpl * This, HKEY hKey, WCHAR *szVerb, WCHAR * szClass) -{ - PStaticShellEntry curEntry; - PStaticShellEntry lastEntry = NULL; - - curEntry = This->head; - - while(curEntry) - { - if (!wcsicmp(curEntry->szVerb, szVerb)) - { - /* entry already exists */ - return; - } - lastEntry = curEntry; - curEntry = curEntry->Next; - } - - TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass)); - - curEntry = malloc(sizeof(StaticShellEntry)); - if (curEntry) - { - curEntry->Next = NULL; - curEntry->szVerb = wcsdup(szVerb); - curEntry->szClass = wcsdup(szClass); - } - - if (lastEntry) - { - lastEntry->Next = curEntry; - } - else - { - This->head = curEntry; - } -} - -void -SH_AddStaticEntryForKey(ItemCmImpl * This, HKEY hKey, WCHAR * szClass) -{ - LONG result; - DWORD dwIndex; - WCHAR szName[40]; - DWORD dwName; - - dwIndex = 0; - do - { - szName[0] = 0; - dwName = sizeof(szName) / sizeof(WCHAR); - result = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL); - szName[39] = 0; - if (result == ERROR_SUCCESS) - { - SH_AddStaticEntry(This, hKey, szName, szClass); - } - dwIndex++; - }while(result == ERROR_SUCCESS); -} - -void -SH_AddStaticEntryForFileClass(ItemCmImpl * This, WCHAR * szExt) -{ - WCHAR szBuffer[100]; - HKEY hKey; - LONG result; - DWORD dwBuffer; - - TRACE("SH_AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt)); - - wcscpy(szBuffer, szExt); - wcscat(szBuffer, L"\\shell"); - result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); - if (result == ERROR_SUCCESS) - { - SH_AddStaticEntryForKey(This, hKey, szExt); - RegCloseKey(hKey); - } - - dwBuffer = sizeof(szBuffer); - result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer); - if (result == ERROR_SUCCESS) - { - UINT length = strlenW(szBuffer); - wcscat(szBuffer, L"\\shell"); - TRACE("szBuffer %s\n", debugstr_w(szBuffer)); - - result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); - if (result == ERROR_SUCCESS) - { - szBuffer[length] = 0; - SH_AddStaticEntryForKey(This, hKey, szBuffer); - RegCloseKey(hKey); - } - } - - strcpyW(szBuffer, "SystemFileAssociations\\"); - dwBuffer = sizeof(szBuffer) - strlenW(szBuffer) * sizeof(WCHAR); - result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[23], &dwBuffer); - if (result == ERROR_SUCCESS) - { - UINT length = strlenW(szBuffer); - wcscat(szBuffer, L"\\shell"); - TRACE("szBuffer %s\n", debugstr_w(szBuffer)); - - result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey); - if (result == ERROR_SUCCESS) - { - szBuffer[length] = 0; - SH_AddStaticEntryForKey(This, hKey, szBuffer); - RegCloseKey(hKey); - } - } - RegCloseKey(hKey); -} - -void -SH_AddStaticEntrySpecial(ItemCmImpl * This) -{ - if (_ILIsFolder(This->apidl[0])) // && (This->rfg & SFGAO_BROWSABLE)) - { - SH_AddStaticEntryForFileClass(This, L"Folder"); - } - else if (_ILIsDrive(This->apidl[0])) - { - SH_AddStaticEntryForFileClass(This, L"Drive"); - } -} - - -UINT -SH_AddStaticEntryToMenu(HMENU hMenu, UINT indexMenu, ItemCmImpl * This) -{ - MENUITEMINFOW mii; - PStaticShellEntry curEntry; - WCHAR szVerb[20]; - UINT idResource; - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA; - mii.fType = MFT_STRING; - mii.fState = MFS_ENABLED | MFS_DEFAULT; - mii.wID = 0x4000; - This->iIdSCMFirst = mii.wID; - - curEntry = This->head; - - while(curEntry) - { - if (!wcsicmp(curEntry->szVerb, L"open")) - idResource = IDS_OPEN_VERB; - else if (!wcsicmp(curEntry->szVerb, L"runas")) - idResource = IDS_RUNAS_VERB; - else if (!wcsicmp(curEntry->szVerb, L"edit")) - idResource = IDS_EDIT_VERB; - else if (!wcsicmp(curEntry->szVerb, L"find")) - idResource = IDS_FIND_VERB; - else if (!wcsicmp(curEntry->szVerb, L"print")) - idResource = IDS_PRINT_VERB; - else if (!wcsicmp(curEntry->szVerb, L"play")) - idResource = IDS_PLAY_VERB; - else if (!wcsicmp(curEntry->szVerb, L"preview")) - idResource = IDS_PREVIEW_VERB; - else if (!wcsicmp(curEntry->szVerb, L"cplopen")) - idResource = IDS_OPEN_VERB; - - else - idResource = 0; - - if (idResource > 0) - { - if (LoadStringW(shell32_hInstance, idResource, szVerb, sizeof(szVerb)/sizeof(WCHAR))) - { - szVerb[(sizeof(szVerb)/sizeof(WCHAR))-1] = L'\0'; - mii.dwTypeData = szVerb; - } - else - { - WARN("unknown verb %s\n", debugstr_w(curEntry->szVerb)); - mii.dwTypeData = curEntry->szVerb; - } - } - else - { - WARN("unknown verb %s\n", debugstr_w(curEntry->szVerb)); - mii.dwTypeData = curEntry->szVerb; - } - - mii.cch = strlenW(mii.dwTypeData); - InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii); - mii.fState = MFS_ENABLED; - mii.wID++; - curEntry = curEntry->Next; - } - This->iIdSCMLast = mii.wID - 1; - return indexMenu; -} - -const char * GetLocalizedString(HMENU hMenu, UINT wID, const char * sDefault, char * sResult) -{ - MENUITEMINFOA mii; - if (!hMenu) - { - return sDefault; - } - - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_TYPE; - mii.fType = MFT_STRING; - mii.dwTypeData = sResult; - mii.cch = 100; - - if (GetMenuItemInfoA(hMenu, wID, FALSE, &mii)) - { - return sResult; - } - else - { - return sDefault; - } -} - -/************************************************************************** -* ISvItemCm_fnQueryContextMenu() -* FIXME: load menu MENU_SHV_FILE out of resources instead if creating -* each menu item by calling _InsertMenuItem() -*/ -static HRESULT WINAPI ISvItemCm_fnQueryContextMenu( - IContextMenu2 *iface, - HMENU hmenu, - UINT indexMenu, - UINT idCmdFirst, - UINT idCmdLast, - UINT uFlags) -{ - IDataObject * pDataObj; - ItemCmImpl *This = (ItemCmImpl *)iface; - USHORT lastindex = 0; - HMENU hLocalMenu; - char sBuffer[100]; - WCHAR szExt[10]; - - static const char sCopy[] = { '&','C','o','p','y',0 }; - static const char sCut[] = { '&','C','u','t',0 }; - static const char sDelete[] = { '&','D','e','l','e','t','e',0 }; - static const char sRename[] = { '&','R','e','n','a','m','e',0 }; - static const char sProperties[] = { '&','P','r','o','p','e','r','t','i','e','s',0 }; - static const WCHAR szSHVFile[] = { 'M','E','N','U','_','S','H','V','_','F','I','L','E',0 }; - - - TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); - - hLocalMenu = LoadMenuW(shell32_hInstance, szSHVFile); - - if (_ILGetExtension(This->apidl[0], &sBuffer[1], sizeof(sBuffer)-1)) - { - sBuffer[0] = '.'; - MultiByteToWideChar( CP_ACP, 0, sBuffer, -1, (LPWSTR)szExt, 10); - SH_AddStaticEntryForFileClass(This, szExt); - } - else - { - SH_AddStaticEntrySpecial(This); - - } - indexMenu = SH_AddStaticEntryToMenu(hmenu, indexMenu, This); - - SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); - pDataObj = IDataObject_Constructor(NULL, This->pidl, (LPCITEMIDLIST *)This->apidl, This->cidl); - if (pDataObj) - { - indexMenu = SH_LoadContextMenuHandlers(This, pDataObj, hmenu, indexMenu); - IDataObject_Release(pDataObj); - } - - if(!(CMF_DEFAULTONLY & uFlags) && This->cidl>0) - { - if(!(uFlags & CMF_EXPLORE)) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_OPEN, MFT_STRING, "&Select", MFS_ENABLED); - - TRACE("rfg %x\n", This->rfg); - - - if (This->rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE)) - { - _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - if (This->rfg & SFGAO_CANCOPY) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_COPY, sCopy, sBuffer), MFS_ENABLED); - if (This->rfg & SFGAO_CANMOVE) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_CUT, sCut, sBuffer), MFS_ENABLED); - } - - if (This->rfg & SFGAO_CANDELETE) - { - _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_DELETE, sDelete, sBuffer), MFS_ENABLED); - } - - if ((uFlags & CMF_CANRENAME) && (This->rfg & SFGAO_CANRENAME)) - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_RENAME, sRename, sBuffer), ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED); - - if (This->rfg & SFGAO_HASPROPSHEET) - { - _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0); - _InsertMenuItem(hmenu, indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, GetLocalizedString(hLocalMenu, FCIDM_SHVIEW_PROPERTIES, sProperties, sBuffer), MFS_ENABLED); - } - - lastindex = FCIDM_SHVIEWLAST; - } - - if (hLocalMenu) - { - DestroyMenu(hLocalMenu); - } - - return MAKE_HRESULT(SEVERITY_SUCCESS, 0, lastindex); -} - -/************************************************************************** -* DoRename -*/ -static void DoRename( - IContextMenu2 *iface, - HWND hwnd) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV; - - TRACE("(%p)->(wnd=%p)\n",This, hwnd); - - /* get the active IShellView */ - if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - TRACE("(sv=%p)\n",lpSV); - IShellView_SelectItem(lpSV, This->apidl[0], - SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT); - IShellView_Release(lpSV); - } - } -} - -/************************************************************************** - * DoDelete - * - * deletes the currently selected items - */ -static void DoDelete(IContextMenu2 *iface, HWND hwnd) -{ - WCHAR szPath[MAX_PATH]; - WCHAR * szTarget; - SHFILEOPSTRUCTW op; - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV; - IPersistFolder2 * psf; - LPITEMIDLIST pidl; - STRRET strTemp; - ItemCmImpl *This = (ItemCmImpl *)iface; - - if (IShellFolder2_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&psf) != S_OK) - { - ERR("Failed to get interface IID_IPersistFolder2\n"); - return; - } - - if (IPersistFolder2_GetCurFolder(psf, &pidl) != S_OK) - { - ERR("IPersistFolder2_GetCurFolder failed\n"); - IPersistFolder2_Release(psf); - return; - } - - if (IShellFolder2_GetDisplayNameOf(This->pSFParent, pidl, SHGDN_FORPARSING, &strTemp) != S_OK) - { - ERR("IShellFolder_GetDisplayNameOf failed\n"); - IPersistFolder2_Release(psf); - return; - } - szPath[MAX_PATH-1] = 0; - StrRetToBufW(&strTemp, pidl, szPath, MAX_PATH); - PathAddBackslashW(szPath); - IPersistFolder2_Release(psf); - - szTarget = build_paths_list(szPath, This->cidl, (LPCITEMIDLIST *)This->apidl); - - if (pidl) - { - if (SHGetPathFromIDListW(pidl, szPath)) - { - ZeroMemory(&op, sizeof(op)); - op.hwnd = GetActiveWindow(); - op.wFunc = FO_DELETE; - op.pFrom = szTarget; - op.fFlags = FOF_ALLOWUNDO; - SHFileOperationW(&op); - } - ILFree(pidl); - } - - if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - IShellView_Refresh(lpSV); - } - } -} - -/************************************************************************** - * DoCopyOrCut - * - * copies the currently selected items into the clipboard - */ -static BOOL DoCopyOrCut( - IContextMenu2 *iface, - HWND hwnd, - BOOL bCut) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - LPSHELLBROWSER lpSB; - LPSHELLVIEW lpSV; - LPDATAOBJECT lpDo; - - TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut); - - /* get the active IShellView */ - if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0))) - { - if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV))) - { - if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo))) - { - OleSetClipboard(lpDo); - IDataObject_Release(lpDo); - } - IShellView_Release(lpSV); - } - } - return TRUE; -} -static void DoProperties( - IContextMenu2 *iface, - HWND hwnd) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - LPITEMIDLIST pidlFQ = NULL; - SHELLEXECUTEINFOA sei; - - /* - * FIXXME - * - * The IShellFolder interface GetUIObject should create the specific item and then query if it has an IContextMenu interface - * If yes return interface to it. - */ - - if (_ILIsMyComputer(This->apidl[0])) - { - ShellExecuteA(hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL); - return; - } - else if (_ILIsDesktop(This->apidl[0])) - { - ShellExecuteA(hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL); - return; - } - else if (_ILIsDrive(This->apidl[0])) - { - WCHAR buffer[111]; - ILGetDisplayName(This->apidl[0], buffer); - SH_ShowDriveProperties(buffer); - return; - } - else if (_ILIsNetHood(This->apidl[0])) - { - /* FIXME - * implement nethood properties - */ - FIXME("implement nethood property dialog\n"); - return; - } - else if (_ILIsBitBucket(This->apidl[0])) - { - ///FIXME - WCHAR szDrive = 'C'; - SH_ShowRecycleBinProperties(szDrive); - } - else - { - pidlFQ = ILCombine(This->pidl, This->apidl[0]); - } - - ZeroMemory(&sei, sizeof(sei)); - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_INVOKEIDLIST; - sei.lpIDList = pidlFQ; - sei.hwnd = hwnd; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = "properties"; - - TRACE("DoProperties before ShellExecuteEx\n"); - ShellExecuteExA(&sei); - TRACE("DoProperties after ShellExecuteEx\n"); - - if (pidlFQ) - { - SHFree(pidlFQ); - } -} -HRESULT -DoStaticShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi) -{ - UINT i; - PStaticShellEntry curEntry; - LPITEMIDLIST pidl; - UINT bFolderFound = FALSE; - SHELLEXECUTEINFOW sei; - - TRACE("DoStaticShellExtensions entered with lpVerb %x first %x last %x\n", LOWORD(lpcmi->lpVerb), This->iIdSCMFirst, This->iIdSCMLast); - - i = This->iIdSCMFirst; - curEntry = This->head; - - while(curEntry) - { - if (i == LOWORD(lpcmi->lpVerb)) - break; - - i++; - curEntry = curEntry->Next; - } - - if (!curEntry) - { - ERR("unexpected\n"); - return E_UNEXPECTED; - } - - for(i = 0; icidl; i++) - { - if(!_ILIsValue(This->apidl[i])) - { - bFolderFound = TRUE; - break; - } - } - - if (bFolderFound && wcsicmp(curEntry->szClass, L"Folder")) - { - /* when there is a folder with item selected - * do nothing - */ - return S_OK; - } - - TRACE("curEntry %p verb %s szClass %s\n", curEntry, debugstr_w(curEntry->szVerb), debugstr_w(curEntry->szClass)); - - pidl = ILCombine(This->pidl, This->apidl[0]); - - ZeroMemory(&sei, sizeof(sei)); - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_CLASSNAME | SEE_MASK_IDLIST; - sei.lpIDList = pidl; - sei.lpClass = curEntry->szClass; - sei.hwnd = lpcmi->hwnd; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = curEntry->szVerb; - ShellExecuteExW(&sei); - SHFree(pidl); - return S_OK; -} - -HRESULT -DoDynamicShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi) -{ - HRESULT hResult = NOERROR; - PDynamicShellEntry curEntry; - UINT id; - - curEntry = This->dhead; - id = LOWORD(lpcmi->lpVerb); - - while(curEntry) - { - if (curEntry->iIdCmdFirst <= id && curEntry->iIdCmdFirst + curEntry->NumIds >= id) - break; - - curEntry = curEntry->Next; - } - - if (!curEntry) - return E_FAIL; - - lpcmi->lpVerb -= curEntry->iIdCmdFirst; - - hResult = IContextMenu_InvokeCommand(curEntry->CMenu, lpcmi); - - TRACE("DoDynamicShellExtensions hResult %x verb %x first %x\n", hResult, lpcmi->lpVerb, curEntry->iIdCmdFirst); - return hResult; -} - - -/************************************************************************** -* ISvItemCm_fnInvokeCommand() -*/ -static HRESULT WINAPI ISvItemCm_fnInvokeCommand( - IContextMenu2 *iface, - LPCMINVOKECOMMANDINFO lpcmi) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO)) - FIXME("Is an EX structure\n"); - - TRACE("ISvItemCm_fnInvokeCommand (%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd); - - if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST) - { - TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb)); - return E_INVALIDARG; - } - - if (HIWORD(lpcmi->lpVerb) == 0) - { - switch(LOWORD(lpcmi->lpVerb)) - { - case FCIDM_SHVIEW_RENAME: - TRACE("Verb FCIDM_SHVIEW_RENAME\n"); - DoRename(iface, lpcmi->hwnd); - break; - case FCIDM_SHVIEW_DELETE: - TRACE("Verb FCIDM_SHVIEW_DELETE\n"); - DoDelete(iface, lpcmi->hwnd); - break; - case FCIDM_SHVIEW_COPY: - TRACE("Verb FCIDM_SHVIEW_COPY\n"); - DoCopyOrCut(iface, lpcmi->hwnd, FALSE); - break; - case FCIDM_SHVIEW_CUT: - TRACE("Verb FCIDM_SHVIEW_CUT\n"); - DoCopyOrCut(iface, lpcmi->hwnd, TRUE); - break; - case FCIDM_SHVIEW_PROPERTIES: - TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n"); - DoProperties(iface, lpcmi->hwnd); - break; - default: - TRACE("iIdSHEFirst %x iIdSHELast %x iIdSCMFirst %x iIdSCMLast %x\n", This->iIdSHEFirst, This->iIdSHELast, This->iIdSCMFirst, This->iIdSCMLast); - if (This->iIdSHEFirst && This->iIdSHELast) - { - if (LOWORD(lpcmi->lpVerb) >= This->iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSHELast) - { - return DoDynamicShellExtensions(This, lpcmi); - } - } - if (This->iIdSCMFirst && This->iIdSCMLast) - { - if (LOWORD(lpcmi->lpVerb) >= This->iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSCMLast) - { - return DoStaticShellExtensions(This, lpcmi); - } - } - FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb)); - } - } - else - { - TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb)); - if (strcmp(lpcmi->lpVerb,"delete")==0) - DoDelete(iface, lpcmi->hwnd); - else - FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb)); - } - return NOERROR; -} - -/************************************************************************** -* ISvItemCm_fnGetCommandString() -*/ -static HRESULT WINAPI ISvItemCm_fnGetCommandString( - IContextMenu2 *iface, - UINT_PTR idCommand, - UINT uFlags, - UINT* lpReserved, - LPSTR lpszName, - UINT uMaxNameLen) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - - HRESULT hr = E_INVALIDARG; - - TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen); - - switch(uFlags) - { - case GCS_HELPTEXTA: - case GCS_HELPTEXTW: - hr = E_NOTIMPL; - break; - - case GCS_VERBA: - switch(idCommand) - { - case FCIDM_SHVIEW_RENAME: - strcpy((LPSTR)lpszName, "rename"); - hr = NOERROR; - break; - } - break; - - /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This - case, you need to do the lstrcpyW to the pointer passed.*/ - case GCS_VERBW: - switch(idCommand) - { case FCIDM_SHVIEW_RENAME: - MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen ); - hr = NOERROR; - break; - } - break; - - case GCS_VALIDATEA: - case GCS_VALIDATEW: - hr = NOERROR; - break; - } - TRACE("-- (%p)->(name=%s)\n",This, lpszName); - return hr; -} - -/************************************************************************** -* ISvItemCm_fnHandleMenuMsg() -* NOTES -* should be only in IContextMenu2 and IContextMenu3 -* is nevertheless called from word95 -*/ -static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg( - IContextMenu2 *iface, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - ItemCmImpl *This = (ItemCmImpl *)iface; - LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT) lParam; - TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); - - switch(uMsg) - { - case WM_MEASUREITEM: - case WM_DRAWITEM: - if (lpmis->itemID >= This->iIdSHEFirst && lpmis->itemID <= This->iIdSHELast) - return DoCustomItemAction(This, lParam, uMsg); - break; - - } - - return E_NOTIMPL; -} - -static const IContextMenu2Vtbl cmvt = -{ - ISvItemCm_fnQueryInterface, - ISvItemCm_fnAddRef, - ISvItemCm_fnRelease, - ISvItemCm_fnQueryContextMenu, - ISvItemCm_fnInvokeCommand, - ISvItemCm_fnGetCommandString, - ISvItemCm_fnHandleMenuMsg -}; - -HRESULT -SH_LoadDynamicContextMenuHandler(HKEY hKey, const CLSID * szClass, ItemCmImpl *This, IDataObject * pDataObj) -{ - HRESULT hr; - IContextMenu * cmobj; - IShellExtInit *shext; - PDynamicShellEntry curEntry; - TRACE("SH_LoadDynamicContextMenuHandler entered with %s\n",wine_dbgstr_guid(szClass)); - - hr = SHCoCreateInstance(NULL, szClass, NULL, &IID_IContextMenu, (void**)&cmobj); - if (hr != S_OK) - { - TRACE("SHCoCreateInstance failed %x\n", GetLastError()); - return hr; - } - hr = cmobj->lpVtbl->QueryInterface(cmobj, &IID_IShellExtInit, (void**)&shext); - if (hr != S_OK) - { - TRACE("Failed to query for interface IID_IShellExtInit\n"); - cmobj->lpVtbl->Release(cmobj); - return FALSE; - } - hr = shext->lpVtbl->Initialize(shext, NULL, pDataObj, hKey); - if (hr != S_OK) - { - TRACE("Failed to initialize shell extension error %x\n", hr); - shext->lpVtbl->Release(shext); - cmobj->lpVtbl->Release(cmobj); - return hr; - } - curEntry = malloc(sizeof(DynamicShellEntry)); - if(!curEntry) - { - return E_OUTOFMEMORY; - } - - curEntry->iIdCmdFirst = 0; - curEntry->Next = NULL; - curEntry->NumIds = 0; - curEntry->CMenu = cmobj; - - if (This->dhead) - { - PDynamicShellEntry pEntry = This->dhead; - - while(pEntry->Next) - { - pEntry = pEntry->Next; - } - - pEntry->Next = curEntry; - } - else - { - This->dhead = curEntry; - } - - return hr; -} - -UINT -SH_EnumerateDynamicContextHandlerForKey(const LPWSTR szFileClass, ItemCmImpl *This, IDataObject * pDataObj, DWORD bGroupPolicyActive) -{ - HKEY hKey; - WCHAR szKey[MAX_PATH] = {0}; - WCHAR szName[MAX_PATH] = {0}; - DWORD dwIndex, dwName; - LONG res; - HRESULT hResult; - UINT index; - CLSID clsid; - static const WCHAR szShellEx[] = { '\\','s','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 }; - - wcscpy(szKey, szFileClass); - wcscat(szKey, szShellEx); - - TRACE("SH_EnumerateDynamicContextHandlerForKey key %s\n", debugstr_w(szFileClass)); - - if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) - { - TRACE("RegOpenKeyExW failed for key %s\n", debugstr_w(szKey)); - return 0; - } - - dwIndex = 0; - index = 0; - do - { - dwName = MAX_PATH; - res = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL); - if (res == ERROR_SUCCESS) - { - hResult = CLSIDFromString(szName, &clsid); - if (hResult != S_OK) - { - dwName = MAX_PATH; - if (RegGetValueW(hKey, szName, NULL, RRF_RT_REG_SZ, NULL, szKey, &dwName) == ERROR_SUCCESS) - { - if (CLSIDFromString(szKey, &clsid) == S_OK) - { - if (bGroupPolicyActive) - { - if (RegGetValueW(HKEY_LOCAL_MACHINE, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", - szKey, - RRF_RT_REG_SZ, - NULL, - NULL, - &dwName) == ERROR_SUCCESS) - { - SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj); - } - - } - else - { - SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj); - } - } - } - } - if (hResult == S_OK) - { - if (bGroupPolicyActive) - { - if (RegGetValueW(HKEY_LOCAL_MACHINE, - L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", - szKey, - RRF_RT_REG_SZ, - NULL, - NULL, - &dwName) == ERROR_SUCCESS) - { - SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj); - } - } - else - { - SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj); - } - } - } - dwIndex++; - }while(res == ERROR_SUCCESS); - - RegCloseKey(hKey); - return index; -} - -/************************************************************************* - * SHCreateDefaultContextMenu [SHELL32.325] Vista API - * - */ - -HRESULT WINAPI SHCreateDefaultContextMenu( - const DEFCONTEXTMENU *pdcm, - REFIID riid, - void **ppv) -{ - HRESULT hr; - IContextMenu2 * pcm; - - if (pdcm->cidl > 0) - pcm = ISvItemCm_Constructor( pdcm->psf, pdcm->pidlFolder, pdcm->apidl, pdcm->cidl ); - else - pcm = ISvBgCm_Constructor( pdcm->psf, TRUE ); - - hr = S_OK; - *ppv = pcm; - - return hr; -} - -/************************************************************************* - * CDefFolderMenu_Create2 [SHELL32.701] - * - */ - -INT -WINAPI -CDefFolderMenu_Create2( - LPCITEMIDLIST pidlFolder, - HWND hwnd, - UINT cidl, - LPCITEMIDLIST *apidl, - IShellFolder *psf, - LPFNDFMCALLBACK lpfn, - UINT nKeys, - HKEY *ahkeyClsKeys, - IContextMenu **ppcm) -{ - DEFCONTEXTMENU pdcm; - HRESULT hr; - - pdcm.hwnd = hwnd; - pdcm.pcmcb = NULL; //FIXME - pdcm.pidlFolder = pidlFolder; - pdcm.psf = psf; - pdcm.cidl = cidl; - pdcm.apidl = apidl; - pdcm.punkAssociationInfo = NULL; - pdcm.cKeys = nKeys; - pdcm.aKeys = ahkeyClsKeys; - - hr = SHCreateDefaultContextMenu(&pdcm, &IID_IContextMenu, (void**)ppcm); - return hr; -} diff --git a/reactos/dll/win32/shell32/shv_item_new.c b/reactos/dll/win32/shell32/shv_item_new.c index f8f52c057f3..24454c9fac7 100644 --- a/reactos/dll/win32/shell32/shv_item_new.c +++ b/reactos/dll/win32/shell32/shv_item_new.c @@ -50,11 +50,14 @@ typedef struct __SHELLNEW_ITEM__ typedef struct { const IContextMenu2Vtbl *lpVtblContextMenu; - LPSHELLFOLDER pSFParent; + const IShellExtInitVtbl *lpvtblShellExtInit; + LPWSTR szPath; + IShellFolder *pSFParent; PSHELLNEW_ITEM s_SnHead; }INewMenuImpl; static const IContextMenu2Vtbl cmvt; +static const IShellExtInitVtbl sei; static WCHAR szNew[MAX_PATH]; @@ -552,15 +555,20 @@ static void DoNewFolder( if (psfhlp) { LPITEMIDLIST pidl; - ISFHelper_GetUniqueName(psfhlp, wszName, MAX_PATH); - ISFHelper_AddFolder(psfhlp, 0, wszName, &pidl); + + if (ISFHelper_GetUniqueName(psfhlp, wszName, MAX_PATH) != S_OK) + return; + if (ISFHelper_AddFolder(psfhlp, 0, wszName, &pidl) != S_OK) + return; if(psv) { + IShellView_Refresh(psv); /* if we are in a shellview do labeledit */ IShellView_SelectItem(psv, pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |SVSI_FOCUSED|SVSI_SELECT)); + IShellView_Refresh(psv); } SHFree(pidl); @@ -569,12 +577,10 @@ static void DoNewFolder( } -#if 0 static inline INewMenuImpl *impl_from_IShellExtInit( IShellExtInit *iface ) { return (INewMenuImpl *)((char*)iface - FIELD_OFFSET(INewMenuImpl, lpvtblShellExtInit)); } -#endif static __inline INewMenuImpl * impl_from_IContextMenu( IContextMenu2 *iface ) { @@ -583,22 +589,21 @@ static __inline INewMenuImpl * impl_from_IContextMenu( IContextMenu2 *iface ) static HRESULT WINAPI INewItem_fnQueryInterface(INewMenuImpl * This, REFIID riid, LPVOID *ppvObj) { - TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); + TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj); - *ppvObj = NULL; + *ppvObj = NULL; if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IContextMenu) || IsEqualIID(riid, &IID_IContextMenu2)) - { - *ppvObj = &This->lpVtblContextMenu; - } -#if 0 - else if(IsEqualIID(riid, &IID_IShellExtInit)) - { - *ppvObj = &This->lpvtblShellExtInit; - } -#endif + { + *ppvObj = &This->lpVtblContextMenu; + } + else if(IsEqualIID(riid, &IID_IShellExtInit)) + { + *ppvObj = &This->lpvtblShellExtInit; + } + if(*ppvObj) { @@ -757,12 +762,12 @@ INewItem_IContextMenu_fnHandleMenuMsg(IContextMenu2 *iface, LPARAM lParam) { INewMenuImpl *This = impl_from_IContextMenu(iface); - //DRAWITEMSTRUCT * lpids = (DRAWITEMSTRUCT*) lParam; - //MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) lParam; + DRAWITEMSTRUCT * lpids = (DRAWITEMSTRUCT*) lParam; + MEASUREITEMSTRUCT *lpmis = (MEASUREITEMSTRUCT*) lParam; + + TRACE("INewItem_IContextMenu_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); - TRACE("INewItem_IContextMenu_fnHandleMenuMsg (%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam); -#if 0 switch(uMsg) { case WM_MEASUREITEM: @@ -772,9 +777,7 @@ INewItem_IContextMenu_fnHandleMenuMsg(IContextMenu2 *iface, return DoDrawItem(This, (HWND)wParam, lpids); break; } -#else return S_OK; -#endif return E_UNEXPECTED; } @@ -790,7 +793,48 @@ static const IContextMenu2Vtbl cmvt = INewItem_IContextMenu_fnHandleMenuMsg }; -static INewMenuImpl *cached_ow; +static HRESULT WINAPI +INewItem_ExtInit_fnQueryInterface( IShellExtInit* iface, REFIID riid, void** ppvObject ) +{ + return INewItem_fnQueryInterface(impl_from_IShellExtInit(iface), riid, ppvObject); +} + +static ULONG WINAPI +INewItem_ExtInit_AddRef( IShellExtInit* iface ) +{ + return INewItem_fnAddRef(impl_from_IShellExtInit(iface)); +} + +static ULONG WINAPI +INewItem_ExtInit_Release( IShellExtInit* iface ) +{ + return INewItem_fnRelease(impl_from_IShellExtInit(iface)); +} + +static HRESULT WINAPI +INewItem_ExtInit_Initialize( IShellExtInit* iface, LPCITEMIDLIST pidlFolder, + IDataObject *pdtobj, HKEY hkeyProgID ) +{ + + return S_OK; +} + +static const IShellExtInitVtbl sei = +{ + INewItem_ExtInit_fnQueryInterface, + INewItem_ExtInit_AddRef, + INewItem_ExtInit_Release, + INewItem_ExtInit_Initialize +}; +static INewMenuImpl *cached_ow = NULL; + +VOID +INewItem_SetCurrentShellFolder(IShellFolder * psfParent) +{ + if (cached_ow) + cached_ow->pSFParent = psfParent; +} + HRESULT WINAPI INewItem_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *ppv) { INewMenuImpl * ow; @@ -798,14 +842,16 @@ HRESULT WINAPI INewItem_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *p if (!cached_ow) { - ow = LocalAlloc(LMEM_ZEROINIT, sizeof(INewMenuImpl)); - if (!ow) + ow = LocalAlloc(LMEM_ZEROINIT, sizeof(INewMenuImpl)); + if (!ow) { return E_OUTOFMEMORY; } ow->lpVtblContextMenu = &cmvt; + ow->lpvtblShellExtInit = &sei; ow->s_SnHead = NULL; + ow->szPath = NULL; if (InterlockedCompareExchangePointer((void *)&cached_ow, ow, NULL) != NULL) { @@ -814,18 +860,6 @@ HRESULT WINAPI INewItem_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID *p } } - TRACE("(%p)->()\n",cached_ow); - res = INewItem_fnQueryInterface( cached_ow, riid, ppv ); return res; } - -VOID INewItem_SetParent(LPSHELLFOLDER pSFParent) -{ - if (cached_ow->pSFParent) - { - IShellFolder_Release(cached_ow->pSFParent); - } - cached_ow->pSFParent = pSFParent; - IShellFolder_AddRef(pSFParent); -} diff --git a/reactos/dll/win32/shell32/undocshell.h b/reactos/dll/win32/shell32/undocshell.h index d4ebf03c1cd..2d2600f98a8 100644 --- a/reactos/dll/win32/shell32/undocshell.h +++ b/reactos/dll/win32/shell32/undocshell.h @@ -178,8 +178,8 @@ typedef struct int WINAPI Shell_GetCachedImageIndex( LPCSTR lpszFileName, - UINT nIconIndex, - BOOL bSimulateDoc); + int nIconIndex, + UINT bSimulateDoc); BOOL WINAPI Shell_GetImageLists( HIMAGELIST *lphimlLarge,