https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b582d6ff459e49a5b0c84…
commit b582d6ff459e49a5b0c8459c10fedbae02fb3239
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Dec 2 04:06:20 2019 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Dec 2 04:06:20 2019 +0900
[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
---
dll/win32/shell32/CSendToMenu.cpp | 159 +++++++++++++++++++++++++++++++++++++
dll/win32/shell32/CSendToMenu.h | 3 +
dll/win32/shell32/wine/shellpath.c | 128 -----------------------------
3 files changed, 162 insertions(+), 128 deletions(-)
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<IShellLinkW> 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<IPersistFile> 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<ITEMIDLIST_ABSOLUTE> 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)