// 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(); }