From: Katayama Hirofumi MZ Date: Sun, 1 Dec 2019 19:06:20 +0000 (+0900) Subject: [SHELL32] Improve and fix SendTo (#2122) X-Git-Tag: 0.4.14-RC~1019 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=b582d6ff459e49a5b0c8459c10fedbae02fb3239 [SHELL32] Improve and fix SendTo (#2122) Because of timing of SendTo folder initialization, SendTo My Documents didn't work well. Now My Documents item is working well. CORE-12562 --- diff --git a/dll/win32/shell32/CSendToMenu.cpp b/dll/win32/shell32/CSendToMenu.cpp index 9e9fbe8afeb..8a7e1bc0bd8 100644 --- a/dll/win32/shell32/CSendToMenu.cpp +++ b/dll/win32/shell32/CSendToMenu.cpp @@ -156,10 +156,169 @@ void CSendToMenu::UnloadAllItems() } } +BOOL CSendToMenu::FolderHasAnyItems() const +{ + WCHAR szPath[MAX_PATH]; + SHGetSpecialFolderPathW(NULL, szPath, CSIDL_SENDTO, FALSE); + + PathAppendW(szPath, L"*"); + + WIN32_FIND_DATAW find; + HANDLE hFind = FindFirstFileW(szPath, &find); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + + BOOL bFound = FALSE; + do + { + if (wcscmp(find.cFileName, L".") == 0 || + wcscmp(find.cFileName, L"..") == 0 || + _wcsicmp(find.cFileName, L"desktop.ini") == 0) + { + continue; + } + + bFound = TRUE; + break; + } while (FindNextFileW(hFind, &find)); + + FindClose(hFind); + return bFound; +} + +static BOOL CreateEmptyFile(LPCWSTR pszFile) +{ + HANDLE hFile; + hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + CloseHandle(hFile); + return hFile != INVALID_HANDLE_VALUE; +} + +static HRESULT +CreateShellLink( + LPCWSTR pszLinkPath, + LPCWSTR pszTargetPath OPTIONAL, + LPCITEMIDLIST pidlTarget OPTIONAL, + LPCWSTR pszArg OPTIONAL, + LPCWSTR pszDir OPTIONAL, + LPCWSTR pszIconPath OPTIONAL, + INT iIconNr OPTIONAL, + LPCWSTR pszComment OPTIONAL) +{ + CComPtr psl; + HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, + CLSCTX_INPROC_SERVER, + IID_PPV_ARG(IShellLinkW, &psl)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (pszTargetPath) + { + hr = psl->SetPath(pszTargetPath); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + else if (pidlTarget) + { + hr = psl->SetIDList(pidlTarget); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + } + else + { + ERR("invalid argument\n"); + return E_INVALIDARG; + } + + if (pszArg) + hr = psl->SetArguments(pszArg); + + if (pszDir) + hr = psl->SetWorkingDirectory(pszDir); + + if (pszIconPath) + hr = psl->SetIconLocation(pszIconPath, iIconNr); + + if (pszComment) + hr = psl->SetDescription(pszComment); + + CComPtr ppf; + hr = psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = ppf->Save(pszLinkPath, TRUE); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return hr; +} + +HRESULT CSendToMenu::CreateSendToFiles(LPCWSTR pszSendTo) +{ + WCHAR szTarget[MAX_PATH]; + WCHAR szSendToFile[MAX_PATH]; + WCHAR szShell32[MAX_PATH]; + HRESULT hr; + + /* create my documents */ + SHGetSpecialFolderPathW(NULL, szTarget, CSIDL_MYDOCUMENTS, FALSE); + + StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); + PathAppendW(szSendToFile, PathFindFileNameW(szTarget)); + StringCbCatW(szSendToFile, sizeof(szSendToFile), L".lnk"); + + GetSystemDirectoryW(szShell32, ARRAY_SIZE(szShell32)); + PathAppendW(szShell32, L"shell32.dll"); + hr = CreateShellLink(szSendToFile, szTarget, NULL, NULL, NULL, + szShell32, -IDI_SHELL_MY_DOCUMENTS, NULL); + if (FAILED_UNEXPECTEDLY(hr)) + ; + + /* create desklink */ + StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); + LoadStringW(shell32_hInstance, IDS_DESKLINK, szTarget, _countof(szTarget)); + StringCbCatW(szTarget, sizeof(szTarget), L".DeskLink"); + PathAppendW(szSendToFile, szTarget); + if (!CreateEmptyFile(szSendToFile)) + { + ERR("CreateEmptyFile\n"); + } + + /* create zipped compressed folder */ + HINSTANCE hZipFldr = + LoadLibraryExW(L"zipfldr.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); + if (hZipFldr) + { +#define IDS_FRIENDLYNAME 10195 + LoadStringW(hZipFldr, IDS_FRIENDLYNAME, szTarget, _countof(szTarget)); +#undef IDS_FRIENDLYNAME + FreeLibrary(hZipFldr); + + StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); + PathAppendW(szSendToFile, szTarget); + StringCbCatW(szSendToFile, sizeof(szSendToFile), L".ZFSendToTarget"); + if (!CreateEmptyFile(szSendToFile)) + { + ERR("CreateEmptyFile\n"); + } + } + + return S_OK; +} + HRESULT CSendToMenu::LoadAllItems(HWND hwnd) { UnloadAllItems(); + if (!FolderHasAnyItems()) + { + WCHAR szPath[MAX_PATH]; + SHGetSpecialFolderPathW(NULL, szPath, CSIDL_SENDTO, FALSE); + CreateSendToFiles(szPath); + } + CComHeapPtr pidlSendTo; m_pSendTo.Release(); diff --git a/dll/win32/shell32/CSendToMenu.h b/dll/win32/shell32/CSendToMenu.h index 2f59319921e..2156f1ee75e 100644 --- a/dll/win32/shell32/CSendToMenu.h +++ b/dll/win32/shell32/CSendToMenu.h @@ -69,6 +69,9 @@ private: HRESULT LoadAllItems(HWND hwnd); void UnloadAllItems(); + BOOL FolderHasAnyItems() const; + HRESULT CreateSendToFiles(LPCWSTR pszSendTo); + UINT InsertSendToItems(HMENU hMenu, UINT idFirst, UINT idMenu); SENDTO_ITEM *FindItemFromIdOffset(UINT IdOffset); diff --git a/dll/win32/shell32/wine/shellpath.c b/dll/win32/shell32/wine/shellpath.c index 984116f8a38..9ca628f4bbe 100644 --- a/dll/win32/shell32/wine/shellpath.c +++ b/dll/win32/shell32/wine/shellpath.c @@ -2146,129 +2146,6 @@ cleanup: return hr; } -static HRESULT -CreateShellLink( - LPCWSTR pszLinkPath, - LPCWSTR pszCmd, - LPCWSTR pszArg OPTIONAL, - LPCWSTR pszDir OPTIONAL, - LPCWSTR pszIconPath OPTIONAL, - INT iIconNr OPTIONAL, - LPCWSTR pszComment OPTIONAL) -{ - IShellLinkW *psl; - IPersistFile *ppf; - - HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - hr = IShellLinkW_SetPath(psl, pszCmd); - if (FAILED_UNEXPECTEDLY(hr)) - { - IShellLinkW_Release(psl); - return hr; - } - - if (pszArg) - hr = IShellLinkW_SetArguments(psl, pszArg); - - if (pszDir) - hr = IShellLinkW_SetWorkingDirectory(psl, pszDir); - - if (pszIconPath) - hr = IShellLinkW_SetIconLocation(psl, pszIconPath, iIconNr); - - if (pszComment) - hr = IShellLinkW_SetDescription(psl, pszComment); - - hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf); - - if (SUCCEEDED(hr)) - { - hr = IPersistFile_Save(ppf, pszLinkPath, TRUE); - IPersistFile_Release(ppf); - } - - IShellLinkW_Release(psl); - - return hr; -} - -static HRESULT -CreateShellLinkCoInit( - LPCWSTR pszLinkPath, - LPCWSTR pszCmd, - LPCWSTR pszArg OPTIONAL, - LPCWSTR pszDir OPTIONAL, - LPCWSTR pszIconPath OPTIONAL, - INT iIconNr OPTIONAL, - LPCWSTR pszComment OPTIONAL) -{ - HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); - BOOL bCoInit = (hr == S_OK); - - hr = CreateShellLink(pszLinkPath, pszCmd, pszArg, pszDir, - pszIconPath, iIconNr, pszComment); - - if (bCoInit) - CoUninitialize(); - - return hr; -} - -HRESULT DoCreateSendToFiles(LPCWSTR pszSendTo) -{ - WCHAR szTarget[MAX_PATH]; - WCHAR szSendToFile[MAX_PATH]; - WCHAR szShell32[MAX_PATH]; - HRESULT hr; - HANDLE hFile; - HINSTANCE hZipFldr; - - /* create my documents */ - SHGetSpecialFolderPathW(NULL, szTarget, CSIDL_MYDOCUMENTS, TRUE); - - StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); - PathAppendW(szSendToFile, PathFindFileNameW(szTarget)); - StringCbCatW(szSendToFile, sizeof(szSendToFile), L".lnk"); - - GetSystemDirectoryW(szShell32, ARRAY_SIZE(szShell32)); - PathAppendW(szShell32, L"shell32.dll"); - hr = CreateShellLinkCoInit(szSendToFile, szTarget, NULL, NULL, - szShell32, -IDI_SHELL_MY_DOCUMENTS, NULL); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - /* create desklink */ - StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); - LoadStringW(shell32_hInstance, IDS_DESKLINK, szTarget, _countof(szTarget)); - StringCbCatW(szTarget, sizeof(szTarget), L".DeskLink"); - PathAppendW(szSendToFile, szTarget); - hFile = CreateFileW(szSendToFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - CloseHandle(hFile); - - /* create zipped compressed folder */ - hZipFldr = LoadLibraryW(L"zipfldr.dll"); - if (hZipFldr) - { -#define IDS_FRIENDLYNAME 10195 - LoadStringW(hZipFldr, IDS_FRIENDLYNAME, szTarget, _countof(szTarget)); -#undef IDS_FRIENDLYNAME - FreeLibrary(hZipFldr); - - StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo); - PathAppendW(szSendToFile, szTarget); - StringCbCatW(szSendToFile, sizeof(szSendToFile), L".ZFSendToTarget"); - hFile = CreateFileW(szSendToFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - CloseHandle(hFile); - } - - return S_OK; -} - /************************************************************************* * SHGetFolderPathAndSubDirW [SHELL32.@] */ @@ -2408,11 +2285,6 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW( TRACE("Created missing system directory %s\n", debugstr_w(szBuildPath)); end: - if ((nFolder & CSIDL_FLAG_CREATE) && folder == CSIDL_SENDTO) - { - DoCreateSendToFiles(szBuildPath); - } - /* create desktop.ini for custom icon */ if ((nFolder & CSIDL_FLAG_CREATE) && CSIDL_Data[folder].nShell32IconIndex)