📄 shellpath.c
字号:
if (PathFileExistsW(szBuildPath)) goto end;
/* not existing but we are not allowed to create it. The return value
* is verified against shell32 version 6.0.
*/
if (!(nFolder & CSIDL_FLAG_CREATE))
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
goto end;
}
/* create directory/directories */
ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
if (ret && ret != ERROR_ALREADY_EXISTS)
{
ERR("Failed to create directory '%s'.\n", debugstr_w(szBuildPath));
hr = E_FAIL;
goto end;
}
TRACE("Created missing system directory '%s'\n", debugstr_w(szBuildPath));
end:
TRACE("returning 0x%08lx (final path is %s)\n", hr, debugstr_w(szBuildPath));
return hr;
}
/*************************************************************************
* SHGetFolderPathA [SHELL32.@]
*
* See SHGetFolderPathW.
*/
HRESULT WINAPI SHGetFolderPathA(
HWND hwndOwner,
int nFolder,
HANDLE hToken,
DWORD dwFlags,
LPSTR pszPath)
{
WCHAR szTemp[MAX_PATH];
HRESULT hr;
TRACE("%p,%p,nFolder=0x%04x\n",hwndOwner,pszPath,nFolder);
if (pszPath)
*pszPath = '\0';
hr = SHGetFolderPathW(hwndOwner, nFolder, hToken, dwFlags, szTemp);
if (SUCCEEDED(hr) && pszPath)
WideCharToMultiByte(CP_ACP, 0, szTemp, -1, pszPath, MAX_PATH, NULL,
NULL);
return hr;
}
/* For each folder in folders, if its value has not been set in the registry,
* calls _SHGetUserProfilePath or _SHGetAllUsersProfilePath (depending on the
* folder's type) to get the unexpanded value first.
* Writes the unexpanded value to User Shell Folders, and queries it with
* SHGetFolderPathW to force the creation of the directory if it doesn't
* already exist. SHGetFolderPathW also returns the expanded value, which
* this then writes to Shell Folders.
*/
static HRESULT _SHRegisterFolders(HKEY hRootKey, HANDLE hToken,
LPCWSTR szUserShellFolderPath, LPCWSTR szShellFolderPath, const UINT folders[],
UINT foldersLen)
{
UINT i;
WCHAR path[MAX_PATH];
HRESULT hr = S_OK;
HKEY hUserKey = NULL, hKey = NULL;
DWORD dwDisp, dwType, dwPathLen;
LONG ret;
TRACE("%p,%p,%s,%p,%u\n", hRootKey, hToken,
debugstr_w(szUserShellFolderPath), folders, foldersLen);
ret = RegCreateKeyExW(hRootKey, szUserShellFolderPath, 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &hUserKey, &dwDisp);
if (ret)
hr = HRESULT_FROM_WIN32(ret);
else
{
ret = RegCreateKeyExW(hRootKey, szShellFolderPath, 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
if (ret)
hr = HRESULT_FROM_WIN32(ret);
}
for (i = 0; SUCCEEDED(hr) && i < foldersLen; i++)
{
dwPathLen = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueExW(hUserKey, CSIDL_Data[folders[i]].szValueName, NULL,
&dwType, (LPBYTE)path, &dwPathLen) || (dwType != REG_SZ &&
dwType != REG_EXPAND_SZ))
{
*path = '\0';
if (CSIDL_Data[folders[i]].type == CSIDL_Type_User)
_SHGetUserProfilePath(hToken, SHGFP_TYPE_DEFAULT, folders[i],
path);
else if (CSIDL_Data[folders[i]].type == CSIDL_Type_AllUsers)
_SHGetAllUsersProfilePath(SHGFP_TYPE_DEFAULT, folders[i], path);
else if (CSIDL_Data[folders[i]].type == CSIDL_Type_CurrVer)
_SHGetDefaultValue(folders[i], path);
else
hr = E_FAIL;
if (*path)
{
ret = RegSetValueExW(hUserKey,
CSIDL_Data[folders[i]].szValueName, 0, REG_EXPAND_SZ,
(LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
if (ret)
hr = HRESULT_FROM_WIN32(ret);
else
{
hr = SHGetFolderPathW(NULL, folders[i] | CSIDL_FLAG_CREATE,
hToken, SHGFP_TYPE_DEFAULT, path);
ret = RegSetValueExW(hKey,
CSIDL_Data[folders[i]].szValueName, 0, REG_SZ,
(LPBYTE)path, (strlenW(path) + 1) * sizeof(WCHAR));
if (ret)
hr = HRESULT_FROM_WIN32(ret);
}
}
}
}
if (hUserKey)
RegCloseKey(hUserKey);
if (hKey)
RegCloseKey(hKey);
TRACE("returning 0x%08lx\n", hr);
return hr;
}
static HRESULT _SHRegisterUserShellFolders(BOOL bDefault)
{
static const UINT folders[] = {
CSIDL_PROGRAMS,
CSIDL_PERSONAL,
CSIDL_FAVORITES,
CSIDL_APPDATA,
CSIDL_STARTUP,
CSIDL_RECENT,
CSIDL_SENDTO,
CSIDL_STARTMENU,
CSIDL_MYMUSIC,
CSIDL_MYVIDEO,
CSIDL_DESKTOPDIRECTORY,
CSIDL_NETHOOD,
CSIDL_TEMPLATES,
CSIDL_PRINTHOOD,
CSIDL_LOCAL_APPDATA,
CSIDL_INTERNET_CACHE,
CSIDL_COOKIES,
CSIDL_HISTORY,
CSIDL_MYPICTURES,
CSIDL_ADMINTOOLS
};
WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
LPCWSTR pUserShellFolderPath, pShellFolderPath;
HRESULT hr = S_OK;
HKEY hRootKey;
HANDLE hToken;
TRACE("%s\n", bDefault ? "TRUE" : "FALSE");
if (bDefault)
{
hToken = (HANDLE)-1;
hRootKey = HKEY_USERS;
strcpyW(userShellFolderPath, DefaultW);
PathAddBackslashW(userShellFolderPath);
strcatW(userShellFolderPath, szSHUserFolders);
pUserShellFolderPath = userShellFolderPath;
strcpyW(shellFolderPath, DefaultW);
PathAddBackslashW(shellFolderPath);
strcatW(shellFolderPath, szSHFolders);
pShellFolderPath = shellFolderPath;
}
else
{
hToken = NULL;
hRootKey = HKEY_CURRENT_USER;
pUserShellFolderPath = szSHUserFolders;
pShellFolderPath = szSHFolders;
}
hr = _SHRegisterFolders(hRootKey, hToken, pUserShellFolderPath,
pShellFolderPath, folders, sizeof(folders) / sizeof(folders[0]));
TRACE("returning 0x%08lx\n", hr);
return hr;
}
static HRESULT _SHRegisterCommonShellFolders(void)
{
static const UINT folders[] = {
CSIDL_COMMON_STARTMENU,
CSIDL_COMMON_PROGRAMS,
CSIDL_COMMON_STARTUP,
CSIDL_COMMON_DESKTOPDIRECTORY,
CSIDL_COMMON_FAVORITES,
CSIDL_COMMON_APPDATA,
CSIDL_COMMON_TEMPLATES,
CSIDL_COMMON_DOCUMENTS,
};
HRESULT hr;
TRACE("\n");
hr = _SHRegisterFolders(HKEY_LOCAL_MACHINE, NULL, szSHUserFolders,
szSHFolders, folders, sizeof(folders) / sizeof(folders[0]));
TRACE("returning 0x%08lx\n", hr);
return hr;
}
static HRESULT _SHRegisterSetupShellFolders(void)
{
static const UINT folders[] = {
CSIDL_PROGRAM_FILES_COMMON,
CSIDL_PROGRAM_FILES,
};
HRESULT hr;
TRACE("\n");
hr = _SHRegisterFolders(HKEY_LOCAL_MACHINE, NULL, szSHSetupFolders,
szSHSetupFolders, folders, sizeof(folders) / sizeof(folders[0]));
TRACE("returning 0x%08lx\n", hr);
return hr;
}
/* Register the default values in the registry, as some apps seem to depend
* on their presence. The set registered was taken from Windows XP.
*/
HRESULT SHELL_RegisterShellFolders(void)
{
HRESULT hr = _SHRegisterUserShellFolders(TRUE);
if (SUCCEEDED(hr))
hr = _SHRegisterUserShellFolders(FALSE);
if (SUCCEEDED(hr))
hr = _SHRegisterCommonShellFolders();
if (SUCCEEDED(hr))
hr = _SHRegisterSetupShellFolders();
return hr;
}
/*************************************************************************
* SHGetSpecialFolderPathA [SHELL32.@]
*/
BOOL WINAPI SHGetSpecialFolderPathA (
HWND hwndOwner,
LPSTR szPath,
int nFolder,
BOOL bCreate)
{
return (SHGetFolderPathA(
hwndOwner,
nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
NULL,
0,
szPath)) == S_OK ? TRUE : FALSE;
}
/*************************************************************************
* SHGetSpecialFolderPathW
*/
BOOL WINAPI SHGetSpecialFolderPathW (
HWND hwndOwner,
LPWSTR szPath,
int nFolder,
BOOL bCreate)
{
return (SHGetFolderPathW(
hwndOwner,
nFolder + (bCreate ? CSIDL_FLAG_CREATE : 0),
NULL,
0,
szPath)) == S_OK ? TRUE : FALSE;
}
/*************************************************************************
* SHGetSpecialFolderPath (SHELL32.175)
*/
BOOL WINAPI SHGetSpecialFolderPathAW (
HWND hwndOwner,
LPVOID szPath,
int nFolder,
BOOL bCreate)
{
if (SHELL_OsIsUnicode())
return SHGetSpecialFolderPathW (hwndOwner, szPath, nFolder, bCreate);
return SHGetSpecialFolderPathA (hwndOwner, szPath, nFolder, bCreate);
}
/*************************************************************************
* SHGetFolderLocation [SHELL32.@]
*
* Gets the folder locations from the registry and creates a pidl.
*
* PARAMS
* hwndOwner [I]
* nFolder [I] CSIDL_xxxxx
* hToken [I] token representing user, or NULL for current user, or -1 for
* default user
* dwReserved [I] must be zero
* ppidl [O] PIDL of a special folder
*
* RETURNS
* Success: S_OK
* Failure: Standard OLE-defined error result, S_FALSE or E_INVALIDARG
*
* NOTES
* Creates missing reg keys and directories.
* Mostly forwards to SHGetFolderPathW, but a few values of nFolder return
* virtual folders that are handled here.
*/
HRESULT WINAPI SHGetFolderLocation(
HWND hwndOwner,
int nFolder,
HANDLE hToken,
DWORD dwReserved,
LPITEMIDLIST *ppidl)
{
HRESULT hr = E_INVALIDARG;
TRACE("%p 0x%08x %p 0x%08lx %p\n",
hwndOwner, nFolder, hToken, dwReserved, ppidl);
if (!ppidl)
return E_INVALIDARG;
if (dwReserved)
return E_INVALIDARG;
/* The virtual folders' locations are not user-dependent */
*ppidl = NULL;
switch (nFolder)
{
case CSIDL_DESKTOP:
*ppidl = _ILCreateDesktop();
break;
case CSIDL_INTERNET:
*ppidl = _ILCreateIExplore();
break;
case CSIDL_CONTROLS:
*ppidl = _ILCreateControlPanel();
break;
case CSIDL_PRINTERS:
*ppidl = _ILCreatePrinters();
break;
case CSIDL_FONTS:
FIXME("virtual font folder");
break;
case CSIDL_BITBUCKET:
*ppidl = _ILCreateBitBucket();
break;
case CSIDL_DRIVES:
*ppidl = _ILCreateMyComputer();
break;
case CSIDL_NETWORK:
*ppidl = _ILCreateNetwork();
break;
default:
{
WCHAR szPath[MAX_PATH];
hr = SHGetFolderPathW(hwndOwner, nFolder, hToken,
SHGFP_TYPE_CURRENT, szPath);
if (SUCCEEDED(hr))
{
DWORD attributes=0;
TRACE("Value=%s\n", debugstr_w(szPath));
hr = SHILCreateFromPathW(szPath, ppidl, &attributes);
}
else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
{
/* unlike SHGetFolderPath, SHGetFolderLocation in shell32
* version 6.0 returns E_FAIL for nonexistent paths
*/
hr = E_FAIL;
}
}
}
if(*ppidl)
hr = NOERROR;
TRACE("-- (new pidl %p)\n",*ppidl);
return hr;
}
/*************************************************************************
* SHGetSpecialFolderLocation [SHELL32.@]
*
* NOTES
* In NT5, SHGetSpecialFolderLocation needs the <winntdir>/Recent
* directory.
*/
HRESULT WINAPI SHGetSpecialFolderLocation(
HWND hwndOwner,
INT nFolder,
LPITEMIDLIST * ppidl)
{
HRESULT hr = E_INVALIDARG;
TRACE("(%p,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
if (!ppidl)
return E_INVALIDARG;
hr = SHGetFolderLocation(hwndOwner, nFolder, NULL, 0, ppidl);
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -