[SHLWAPI][SDK] Support PathUnExpandEnvStringsForUserA/W (#9041)

Implementing missing features...
JIRA issue: CORE-19278
- Implement PathUnExpandEnvStringsForUserA and
  PathUnExpandEnvStringsForUserW functions.
- Modify shlwapi.spec.
- Add prototypes into <shlwapi_undoc.h>.
This commit is contained in:
Katayama Hirofumi MZ
2026-05-25 19:22:40 +09:00
committed by GitHub
parent b60f66cbbf
commit 8823853f77
3 changed files with 193 additions and 2 deletions
+2 -2
View File
@@ -462,8 +462,8 @@
462 stdcall -noname UrlFixupW(wstr wstr long)
463 stdcall -noname SHExpandEnvironmentStringsForUserA(ptr str ptr long) userenv.ExpandEnvironmentStringsForUserA
464 stdcall -noname SHExpandEnvironmentStringsForUserW(ptr wstr ptr long) userenv.ExpandEnvironmentStringsForUserW
465 stub -noname PathUnExpandEnvStringsForUserA
466 stdcall -stub -noname PathUnExpandEnvStringsForUserW(ptr wstr ptr long)
465 stdcall -noname PathUnExpandEnvStringsForUserA(ptr str ptr long)
466 stdcall -noname PathUnExpandEnvStringsForUserW(ptr wstr ptr long)
467 stdcall -ordinal SHRunIndirectRegClientCommand(ptr wstr) # Exported by name in Vista+
468 stdcall -noname RunIndirectRegCommand(ptr ptr wstr wstr)
469 stdcall -noname RunRegCommand(ptr ptr wstr)
+177
View File
@@ -19,6 +19,7 @@
#include <shlwapi.h>
#include <shlobj_undoc.h>
#include <shlguid_undoc.h>
#include <userenv.h>
#include <atlstr.h>
#include <shlwapi_undoc.h>
@@ -41,6 +42,182 @@ GetVersionMajorMinor()
return MAKEWORD(HIBYTE(version), LOBYTE(version));
}
static BOOL
UnExpandEnvironmentStringForUserA(
_In_ HANDLE hUserToken,
_In_ PCSTR lpString,
_In_ PCSTR lpSrc,
_Out_ PSTR pszDest,
_In_ INT cchDest)
{
CHAR szBuff[MAX_PATH];
INT cchExpanded;
if (hUserToken)
{
if (ExpandEnvironmentStringsForUserA(hUserToken, lpSrc, szBuff, _countof(szBuff)))
cchExpanded = lstrlenA(szBuff) + 1;
else
cchExpanded = 0;
}
else
{
cchExpanded = ExpandEnvironmentStringsA(lpSrc, szBuff, _countof(szBuff));
}
if (!cchExpanded || cchExpanded > cchDest)
return FALSE;
INT cchEnvPath = cchExpanded - 1;
if (CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szBuff, cchEnvPath, lpString, cchEnvPath) != CSTR_EQUAL)
{
return FALSE;
}
INT cchSuffix = lstrlenA(lpString) - cchEnvPath;
if (lstrlenA(lpSrc) + cchSuffix >= cchDest)
return FALSE;
StringCchCopyA(pszDest, cchDest, lpSrc);
StringCchCatA(pszDest, cchDest, &lpString[cchEnvPath]);
return TRUE;
}
static BOOL
UnExpandEnvironmentStringForUserW(
_In_ HANDLE hUserToken,
_In_ PCWSTR lpString,
_In_ PCWSTR lpSrc,
_Out_ PWSTR pszDest,
_In_ INT cchDest)
{
WCHAR szBuff[MAX_PATH];
INT cchExpanded;
if (hUserToken)
{
if (ExpandEnvironmentStringsForUserW(hUserToken, lpSrc, szBuff, _countof(szBuff)))
cchExpanded = lstrlenW(szBuff) + 1;
else
cchExpanded = 0;
}
else
{
cchExpanded = ExpandEnvironmentStringsW(lpSrc, szBuff, _countof(szBuff));
}
if (!cchExpanded || cchExpanded > cchDest)
return FALSE;
INT cchEnvPath = cchExpanded - 1;
if (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
szBuff, cchEnvPath, lpString, cchEnvPath) != CSTR_EQUAL)
{
return FALSE;
}
INT cchSuffix = lstrlenW(lpString) - cchEnvPath;
if (lstrlenW(lpSrc) + cchSuffix >= cchDest)
return FALSE;
StringCchCopyW(pszDest, cchDest, lpSrc);
StringCchCatW(pszDest, cchDest, &lpString[cchEnvPath]);
return TRUE;
}
/*************************************************************************
* PathUnExpandEnvStringsForUserA [SHLWAPI.465]
*
* See PathUnExpandEnvStringsForUserW.
*/
EXTERN_C
BOOL WINAPI
PathUnExpandEnvStringsForUserA(
_In_ HANDLE hUserToken,
_In_ PCSTR pszPath,
_Out_writes_(cchBuff) PSTR pszBuff,
_In_ INT cchBuff)
{
static const PCSTR c_varsA[] =
{
"%APPDATA%",
"%USERPROFILE%",
"%ALLUSERSPROFILE%",
"%ProgramFiles%",
"%SystemRoot%",
"%SystemDrive%",
};
if (!pszPath)
{
if (pszBuff && cchBuff)
*pszBuff = ANSI_NULL;
return FALSE;
}
if (!pszBuff)
return FALSE;
for (size_t iVar = 0; iVar < _countof(c_varsA); ++iVar)
{
if (UnExpandEnvironmentStringForUserA(hUserToken, pszPath, c_varsA[iVar],
pszBuff, cchBuff))
{
return TRUE;
}
}
return FALSE;
}
/*************************************************************************
* PathUnExpandEnvStringsForUserW [SHLWAPI.466]
*
* https://undoc.airesoft.co.uk/shlwapi.dll/PathUnExpandEnvStringsForUserW.php
*/
EXTERN_C
BOOL WINAPI
PathUnExpandEnvStringsForUserW(
_In_ HANDLE hUserToken,
_In_ PCWSTR pwszPath,
_Out_writes_(cchBuff) PWSTR pszBuff,
_In_ INT cchBuff)
{
static const PCWSTR c_varsW[] =
{
L"%APPDATA%",
L"%USERPROFILE%",
L"%ALLUSERSPROFILE%",
L"%ProgramFiles%",
L"%SystemRoot%",
L"%SystemDrive%",
};
if (!pwszPath)
{
if (pszBuff && cchBuff)
*pszBuff = UNICODE_NULL;
return FALSE;
}
if (!pszBuff)
return FALSE;
for (size_t iVar = 0; iVar < _countof(c_varsW); ++iVar)
{
if (UnExpandEnvironmentStringForUserW(hUserToken, pwszPath, c_varsW[iVar],
pszBuff, cchBuff))
{
return TRUE;
}
}
return FALSE;
}
static BOOL CharLowerNoDBCSAWorker(PSTR lpString, INT cchMax, BOOL bUppercase)
{
CHAR szBuff[MAX_PATH];
+14
View File
@@ -388,6 +388,20 @@ PathFileExistsDefExtAndAttributesW(
_In_ DWORD dwWhich,
_Out_opt_ LPDWORD pdwFileAttributes);
BOOL WINAPI
PathUnExpandEnvStringsForUserA(
_In_ HANDLE hUserToken,
_In_ PCSTR pszPath,
_Out_writes_(cchBuff) PSTR pszBuff,
_In_ INT cchBuff);
BOOL WINAPI
PathUnExpandEnvStringsForUserW(
_In_ HANDLE hUserToken,
_In_ PCWSTR pwszPath,
_Out_writes_(cchBuff) PWSTR pszBuff,
_In_ INT cchBuff);
BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs, DWORD dwWhich);
VOID WINAPI FixSlashesAndColonA(_Inout_ LPSTR lpstr);
VOID WINAPI FixSlashesAndColonW(_Inout_ LPWSTR lpwstr);