[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
This commit is contained in:
Katayama Hirofumi MZ 2019-12-02 04:06:20 +09:00 committed by GitHub
parent 92c3c814bb
commit b582d6ff45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 162 additions and 128 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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)