windows-nt/Source/XPSP1/NT/shell/ext/hnw/wizard/shlwapiwrap.cpp
2020-09-26 16:20:57 +08:00

767 lines
20 KiB
C++

// shlwapi wrappers
//
// Since the HNW needs to run on win98 and W98 shipped with IE4 shlwapi.dll we need to created wrappers
// for the IE5 shlwapi functions that aren't implemented in IE4 shlwapi.
//
#include "stdafx.h"
#include "cstrinout.h"
//
// Globals
//
DWORD g_dwShlwapiVersion = 0;
//
// Version helper function.
//
DWORD GetShlwapiVersion()
{
DWORD dwVersion = 0;
HMODULE hShlwapi = LoadLibrary(L"shlwapi.dll");
if (hShlwapi)
{
HRESULT (*DllGetVersion)(DLLVERSIONINFO* pdvi) = (HRESULT (*)(DLLVERSIONINFO*))GetProcAddress(hShlwapi, "DllGetVersion");
if (DllGetVersion)
{
DLLVERSIONINFO dvi;
dvi.cbSize = sizeof(dvi);
DllGetVersion(&dvi);
dwVersion = dvi.dwMajorVersion;
}
else
{
dwVersion = 3;
}
FreeLibrary(hShlwapi);
}
return dwVersion;
}
//
// wrappers
//
// SHChangeNotify
#undef SHChangeNotify
SHSTDAPI_(void) SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2);
#define SHCNF_HAS_WSTR_PARAMS(f) ((f & SHCNF_TYPE) == SHCNF_PATHW || \
(f & SHCNF_TYPE) == SHCNF_PRINTERW || \
(f & SHCNF_TYPE) == SHCNF_PRINTJOBW )
void SHChangeNotify_HNWWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
if (g_dwShlwapiVersion >= 5)
{
_SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2); // delayloaded shlwapi version.
}
else
{
if (SHCNF_HAS_WSTR_PARAMS(uFlags))
{
CStrIn striItem1((LPWSTR)dwItem1);
CStrIn striItem2((LPWSTR)dwItem2);
if ((uFlags & SHCNF_TYPE) == SHCNF_PATHW)
{
uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PATHA;
}
else if ((uFlags & SHCNF_TYPE) == SHCNF_PRINTERW)
{
uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PRINTERA;
}
else
{
uFlags = (uFlags & ~SHCNF_TYPE) | SHCNF_PRINTJOBA;
}
SHChangeNotify(wEventId, uFlags, (void*)(LPSTR)striItem1, (void*)(LPSTR)striItem2); // shell32 version.
}
else
{
SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2); // shell32 version.
}
}
return;
}
// wsprintf functions.
#undef wvnsprintfW
int wvnsprintfW_HNWWrap(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, va_list arglist)
{
int iRet;
if (g_dwShlwapiVersion >= 5)
{
iRet = _wvnsprintfW(lpOut, cchLimitIn, lpFmt, arglist); // shlwapi delayloaded version.
}
else
{
// Change all %s to %S in the format buffer.
// Note: this doesn't take into account format modifiers like %-30s!
char szFmtA[1024];
SHUnicodeToAnsi_HNWWrap(lpFmt, szFmtA, ARRAYSIZE(szFmtA));
for (char* psz = szFmtA; *psz != '\0'; psz++)
{
if ('%' == psz[0] && 's' == psz[1])
psz[1] = 'S';
}
CStrOut strOut(lpOut, cchLimitIn);
// use unbounded version.
iRet = wvsprintfA(strOut, szFmtA, arglist); // user32 version.
}
return iRet;
}
int __cdecl wnsprintfW_HNWWrap(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
{
int iRet;
va_list arglist;
va_start(arglist, lpFmt);
iRet = wvnsprintfW_HNWWrap(lpOut, cchLimitIn, lpFmt, arglist);
va_end(arglist);
return iRet;
}
// SHSetWindowBits.
void SHSetWindowBits_HNWWrap(HWND hWnd, int iWhich, DWORD dwBits, DWORD dwValue)
{
if (g_dwShlwapiVersion >= 5)
{
_SHSetWindowBits(hWnd, iWhich, dwBits, dwValue);
}
else
{
DWORD dwStyle = GetWindowLong(hWnd, iWhich);
DWORD dwNewStyle = (dwStyle & ~dwBits) | (dwValue & dwBits);
if (dwStyle != dwNewStyle)
{
SetWindowLong(hWnd, iWhich, dwNewStyle);
}
}
return;
}
// SHAnsiToUnicode
int SHAnsiToUnicode_HNWWrap(LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf)
{
int iRet;
if (g_dwShlwapiVersion >= 5)
{
iRet = _SHAnsiToUnicode(pszSrc, pwszDst, cwchBuf);
}
else
{
iRet = MultiByteToWideChar(CP_ACP, 0, pszSrc, -1, pwszDst, cwchBuf);
}
return iRet;
}
// SHUnicodeToAnsi
int SHUnicodeToAnsi_HNWWrap(LPCWSTR pwszSrc, LPSTR pszDst, int cchBuf)
{
int iRet;
if (g_dwShlwapiVersion >= 5)
{
iRet = _SHUnicodeToAnsi(pwszSrc, pszDst, cchBuf);
}
else
{
iRet = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, cchBuf, NULL, NULL);
}
return iRet;
}
// GUIDFromStringA
#undef CLSIDFromString
WINOLEAPI CLSIDFromString(IN LPOLESTR lpsz, OUT LPCLSID pclsid);
BOOL GUIDFromStringA_HNWWrap(LPCSTR psz, GUID* pguid)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _GUIDFromStringA(psz, pguid);
}
else
{
CStrInW str(psz);
fRet = (S_OK == CLSIDFromString(str, pguid));
}
return fRet;
}
// WritePrivateProfileString
BOOL WINAPI WritePrivateProfileStringW_HNWWrap(LPCWSTR pwzAppName, LPCWSTR pwzKeyName, LPCWSTR pwzString, LPCWSTR pwzFileName)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _WritePrivateProfileStringWrapW(pwzAppName, pwzKeyName, pwzString, pwzFileName);
}
else
{
CStrIn strTextAppName(pwzAppName);
CStrIn strTextKeyName(pwzKeyName);
CStrIn strTextString(pwzString);
CStrIn strTextFileName(pwzFileName);
fRet = WritePrivateProfileStringA(strTextAppName, strTextKeyName, strTextString, strTextFileName);
}
return fRet;
}
// ExtTextOutW
#undef ExtTextOutW
LWSTDAPI_(BOOL) ExtTextOutW(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx);
BOOL ExtTextOutWrapW_HNWWrap(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _ExtTextOutWrapW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
}
else
{
fRet = ExtTextOutW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
}
return fRet;
}
// LoadLibraryW
HINSTANCE LoadLibraryW_HNWWrap(LPCWSTR pwzLibFileName)
{
HINSTANCE hinst;
if (g_dwShlwapiVersion >= 5)
{
hinst = _LoadLibraryWrapW(pwzLibFileName);
}
else
{
CStrIn strFileName(pwzLibFileName);
hinst = LoadLibraryA(strFileName);
}
return hinst;
}
// SHGetPathFromIDListW
BOOL SHGetPathFromIDListW_HNWWrap(LPCITEMIDLIST pidl, LPWSTR pwzPath)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _SHGetPathFromIDListWrapW(pidl, pwzPath);
}
else
{
CStrOut strPathOut(pwzPath, MAX_PATH);
fRet = SHGetPathFromIDListA(pidl, strPathOut);
if (fRet)
{
strPathOut.ConvertIncludingNul();
}
}
return fRet;
}
// SetFileAttributesW
BOOL SetFileAttributesW_HNWWrap(LPCWSTR pwzFile, DWORD dwFileAttributes)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _SetFileAttributesWrapW(pwzFile, dwFileAttributes);
}
else
{
CStrIn str(pwzFile);
fRet = SetFileAttributesA(str, dwFileAttributes);
}
return fRet;
}
// MessageBoxW
int MessageBoxW_HNWWrap(HWND hwnd, LPCWSTR pwzText, LPCWSTR pwzCaption, UINT uType)
{
int iRet;
if (g_dwShlwapiVersion >= 5)
{
iRet = _MessageBoxWrapW(hwnd, pwzText, pwzCaption, uType);
}
else
{
CStrIn strCaption(pwzCaption);
CStrIn strText(pwzText);
iRet = MessageBoxA(hwnd, strText, strCaption, uType);
}
return iRet;
}
// CreateProcessW
BOOL CreateProcessW_HNWWrap(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags,
LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation)
{
BOOL fRet;
if (g_dwShlwapiVersion >= 5)
{
fRet = _CreateProcessWrapW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory,
lpStartupInfo, lpProcessInformation);
}
else
{
CStrIn striApplicationName(lpApplicationName);
CStrIn striCommandLine(lpCommandLine);
CStrIn striCurrentDirectory(lpCurrentDirectory);
if (NULL == lpStartupInfo)
{
fRet = CreateProcessA(striApplicationName, striCommandLine,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpEnvironment, striCurrentDirectory,
NULL, lpProcessInformation);
}
else
{
STARTUPINFOA si = *(STARTUPINFOA*)lpStartupInfo;
CStrIn striReserved(lpStartupInfo->lpReserved);
CStrIn striDesktop(lpStartupInfo->lpDesktop);
CStrIn striTitle(lpStartupInfo->lpTitle);
si.lpReserved = striReserved;
si.lpDesktop = striDesktop;
si.lpTitle = striTitle;
fRet = CreateProcessA(striApplicationName, striCommandLine,
lpProcessAttributes, lpThreadAttributes,
bInheritHandles, dwCreationFlags,
lpEnvironment, striCurrentDirectory,
&si, lpProcessInformation);
}
}
return fRet;
}
// FormatMessageW
DWORD FormatMessageW_HNWWrap(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId,
LPWSTR lpBuffer, DWORD nSize, va_list* Arguments)
{
DWORD dwRet;
if (g_dwShlwapiVersion >= 5)
{
dwRet = _FormatMessageWrapW(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer,
nSize, Arguments);
}
else
{
if (FORMAT_MESSAGE_FROM_STRING == dwFlags)
{
CStrIn strSource((LPWSTR)lpSource);
CStrOut strBuffer(lpBuffer, nSize);
dwRet = FormatMessageA(dwFlags, strSource, dwMessageId, dwLanguageId, strBuffer,
strBuffer.BufSize(), Arguments);
if (dwRet)
{
dwRet = strBuffer.ConvertExcludingNul();
}
}
else
{
ASSERT(0);
dwRet = 0;
}
}
return dwRet;
}
// SHAnsiToUnicodeCP
int SHAnsiToUnicodeCP_HNWWrap(UINT uiCP, LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf)
{
int iRet;
if (g_dwShlwapiVersion >= 5)
{
iRet = _SHAnsiToUnicodeCP(uiCP, pszSrc, pwszDst, cwchBuf);
}
else
{
iRet = 0; /* Assume failure */
int cchSrc = lstrlenA(pszSrc) + 1;
iRet = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc, pwszDst, cwchBuf);
if (iRet) {
/*
* The output buffer was big enough; no double-buffering
* needed.
*/
} else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
/*
* The output buffer wasn't big enough. Need to double-buffer.
*/
int cwchNeeded = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc,
NULL, 0);
ASSERT(iRet == 0); /* In case we fail later */
if (cwchNeeded) {
LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED,
cwchNeeded * SIZEOF(WCHAR));
if (pwsz) {
iRet = MultiByteToWideChar(uiCP, 0, pszSrc, cchSrc,
pwsz, cwchNeeded);
if (iRet) {
StrCpyNW(pwszDst, pwsz, cwchBuf);
iRet = cwchBuf;
}
LocalFree(pwsz);
}
}
} else {
/* Possibly unsupported code page */
ASSERT(!"Unexpected error in MultiByteToWideChar");
}
}
return iRet;
}
// StrRetToBufW
HRESULT StrRetToBufW_HNWWrap(STRRET* psr, LPCITEMIDLIST pidl, LPWSTR pszBuf, UINT cchBuf)
{
HRESULT hr = E_FAIL;
switch (psr->uType)
{
case STRRET_WSTR:
{
LPWSTR pwszTmp = psr->pOleStr;
if (pwszTmp)
{
StrCpyNW(pszBuf, pwszTmp, cchBuf);
CoTaskMemFree(pwszTmp);
// Make sure no one thinks things are allocated still
psr->uType = STRRET_CSTR;
psr->cStr[0] = 0;
hr = S_OK;
}
}
break;
case STRRET_CSTR:
SHAnsiToUnicode_HNWWrap(psr->cStr, pszBuf, cchBuf);
hr = S_OK;
break;
case STRRET_OFFSET:
if (pidl)
{
SHAnsiToUnicode_HNWWrap(STRRET_OFFPTR(pidl, psr), pszBuf, cchBuf);
hr = S_OK;
}
break;
}
if (FAILED(hr) && cchBuf)
*pszBuf = 0;
return hr;
}
// WhichPlatform
UINT WhichPlatform_HNWWrap(void)
{
UINT uiRet;
if (g_dwShlwapiVersion >= 5)
{
uiRet = _WhichPlatform();
}
else
{
uiRet = PLATFORM_UNKNOWN;
if (uiRet != PLATFORM_UNKNOWN)
return uiRet;
// Not all callers are linked to SHELL32.DLL, so we must use LoadLibrary.
HINSTANCE hinst = LoadLibraryA("SHELL32.DLL");
if (hinst)
{
DWORD fValue;
DWORD cbSize = sizeof(fValue);
HKEY hKey;
LONG lRes;
// NOTE: GetProcAddress always takes ANSI strings!
DLLGETVERSIONPROC pfnGetVersion =
(DLLGETVERSIONPROC)GetProcAddress(hinst, "DllGetVersion");
uiRet = (NULL != pfnGetVersion) ? PLATFORM_INTEGRATED : PLATFORM_BROWSERONLY;
// check that the registry reflects the right value... (this is so iexplore can check efficiently)
lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Internet Explorer"),
0, KEY_READ | KEY_WRITE, &hKey);
if (lRes == ERROR_SUCCESS)
{
lRes = RegQueryValueEx(hKey, L"IntegratedBrowser",
NULL, NULL,
(LPBYTE) &fValue, &cbSize);
if (lRes == ERROR_SUCCESS && uiRet == PLATFORM_BROWSERONLY)
{
// remove the value, we are now Browser only release
RegDeleteValue(hKey, L"IntegratedBrowser");
}
else if (lRes != ERROR_SUCCESS && uiRet == PLATFORM_INTEGRATED)
{
// install the RegValue, we are integrated browser mode...
fValue = TRUE;
cbSize = sizeof(fValue);
RegSetValueEx(hKey, L"IntegratedBrowser",
(DWORD) NULL, REG_DWORD,
(LPBYTE) &fValue, cbSize);
// ignore the failure, if the key is not present, shdocvw will be loaded and this
// function called anyway....
}
RegCloseKey(hKey);
}
FreeLibrary(hinst);
}
}
return uiRet;
}
//
// Static libs are linked to various shlwapi exports. Some of the exports aren't implemented in
// IE4 shlwapi. Define the exports here so that that linker fixes up the static lib imports
// to these functions.
//
#undef LoadLibraryWrapW
STDAPI_(HINSTANCE) LoadLibraryWrapW(LPCWSTR pwzLibFileName)
{
return LoadLibraryW_HNWWrap(pwzLibFileName);
}
#undef SHAnsiToUnicodeCP
STDAPI_(int) SHAnsiToUnicodeCP(UINT uiCP, LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf)
{
return SHAnsiToUnicodeCP_HNWWrap(uiCP, pszSrc, pwszDst, cwchBuf);
}
#undef SHUnicodeToAnsi
STDAPI_(int) SHUnicodeToAnsi(LPCWSTR pwszSrc, LPSTR pszDst, int cchBuf)
{
return SHUnicodeToAnsi_HNWWrap(pwszSrc, pszDst, cchBuf);
}
#undef GetModuleHandleWrapW
STDAPI_(HMODULE) GetModuleHandleWrapW(LPCWSTR lpModuleName)
{
return GetModuleHandleW(lpModuleName);
}
#undef GetWindowsDirectoryWrapW
STDAPI_(UINT) GetWindowsDirectoryWrapW(LPWSTR lpWinPath, UINT cch)
{
return GetWindowsDirectoryW(lpWinPath, cch);
}
#undef GetModuleFileNameWrapW
STDAPI_(DWORD) GetModuleFileNameWrapW(HINSTANCE hModule, LPWSTR pwszFilename, DWORD nSize)
{
return GetModuleFileNameW(hModule, pwszFilename, nSize);
}
#undef CreateWindowExWrapW
STDAPI_(HWND) CreateWindowExWrapW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X,
int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
LPVOID lpParam)
{
return CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu,
hInstance, lpParam);
}
#undef CreateDialogIndirectParamWrapW
STDAPI_(HWND) CreateDialogIndirectParamWrapW(HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent,
DLGPROC lpDialogFunc, LPARAM dwInitParam)
{
return CreateDialogIndirectParamW(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
}
#undef CreateDialogParamWrapW
STDAPI_(HWND) CreateDialogParamWrapW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc,
LPARAM dwInitParam)
{
return CreateDialogParamW(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);
}
#undef DialogBoxIndirectParamWrapW
STDAPI_(INT_PTR) DialogBoxIndirectParamWrapW(HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, HWND hWndParent,
DLGPROC lpDialogFunc, LPARAM dwInitParam)
{
return DialogBoxIndirectParamW(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
}
#undef DialogBoxParamWrapW
STDAPI_(INT_PTR) DialogBoxParamWrapW(HINSTANCE hInstance, LPCWSTR lpszTemplate, HWND hWndParent, DLGPROC lpDialogFunc,
LPARAM dwInitParam)
{
return DialogBoxParamW(hInstance, lpszTemplate, hWndParent, lpDialogFunc, dwInitParam);
}
#undef RegisterClassWrapW
STDAPI_(ATOM) RegisterClassWrapW(CONST WNDCLASSW* lpWndClass)
{
return RegisterClassW(lpWndClass);
}
#undef RegisterClassExWrapW
STDAPI_(ATOM) RegisterClassExWrapW(CONST WNDCLASSEXW* pwcx)
{
return RegisterClassExW(pwcx);
}
#undef GetClassInfoWrapW
STDAPI_(BOOL) GetClassInfoWrapW(HINSTANCE hModule, LPCWSTR lpClassName, LPWNDCLASSW lpWndClassW)
{
return GetClassInfoW(hModule, lpClassName, lpWndClassW);
}
#undef GetClassInfoExWrapW
STDAPI_(BOOL) GetClassInfoExWrapW(HINSTANCE hinst, LPCWSTR pwzClass, LPWNDCLASSEXW lpwcx)
{
return GetClassInfoExW(hinst, pwzClass, lpwcx);
}
#undef CreateFileWrapW
STDAPI_(HANDLE) CreateFileWrapW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
#undef SetFileAttributesWrapW
STDAPI_(BOOL) SetFileAttributesWrapW(LPCWSTR pwzFile, DWORD dwFileAttributes)
{
return SetFileAttributesW(pwzFile, dwFileAttributes);
}
#undef WhichPlatform
STDAPI_(UINT) WhichPlatform(void)
{
return WhichPlatform_HNWWrap();
}