#include "priv.h" // no wrappers are needed on non-x86 since this is only for win9x interop #ifdef _X86_ #include //============================================================================ // This file contains a bunch of Unicode/Ansi thunks to handle calling // some internal functions that on Windows 95 the strings are Ansi, // whereas the string on NT are unicode //============================================================================ // First undefine everything that we are intercepting as to not forward back to us... #undef ILCreateFromPath #undef PathCleanupSpec #undef PathQualify #undef PathProcessCommand #undef SHCLSIDFromString #undef SHGetSpecialFolderPath #undef SHILCreateFromPath #undef SHSimpleIDListFromPath #undef ShellMessageBox #undef GetFileNameFromBrowse #undef OpenRegStream #undef Win32DeleteFile #undef PathYetAnotherMakeUniqueName #undef PathResolve #undef IsLFNDrive #undef Shell_GetCachedImageIndex #undef SHRunControlPanel #undef PickIconDlg #undef SHCreateDirectory #if 0 #define TF_THUNK TF_CUSTOM1 #else #define TF_THUNK 0 #endif #define THUNKMSG(psz) TraceMsg(TF_THUNK, "shdv THUNK::%s", psz) // FEATURE:: need to properly handle not having ILGetdisplaynameex... typedef BOOL (*PFNILGETDISPLAYNAMEEX)(LPSHELLFOLDER psfRoot, LPCITEMIDLIST pidl, LPTSTR pszName, int fType); #ifndef ANSI_SHELL32_ON_UNIX #define UseUnicodeShell32() (g_fRunningOnNT) #else #define UseUnicodeShell32() (FALSE) #endif //================================================================================= // Now the thunks... int _AorW_SHRunControlPanel(LPCTSTR pszOrig_cmdline, HWND errwnd) { CHAR szPath[MAX_PATH]; if (!UseUnicodeShell32()) { UnicodeToAnsi(pszOrig_cmdline, szPath, ARRAYSIZE(szPath)); pszOrig_cmdline = (LPCTSTR)szPath; // overload the pointer to pass through... } return SHRunControlPanel(pszOrig_cmdline, errwnd); } int _AorW_Shell_GetCachedImageIndex(LPCTSTR pszIconPath, int iIconIndex, UINT uIconFlags) { CHAR szPath[MAX_PATH]; if (!UseUnicodeShell32()) { UnicodeToAnsi(pszIconPath, szPath, ARRAYSIZE(szPath)); pszIconPath = (LPCTSTR)szPath; // overload the pointer to pass through... } return Shell_GetCachedImageIndex(pszIconPath, iIconIndex, uIconFlags); } // the reverse, do it for wide strings also.. int _WorA_Shell_GetCachedImageIndex(LPCWSTR pszIconPath, int iIconIndex, UINT uIconFlags) { CHAR szPath[MAX_PATH]; if (!UseUnicodeShell32()) { UnicodeToAnsi(pszIconPath, szPath, ARRAYSIZE(szPath)); pszIconPath = (LPCWSTR)szPath; // overload the pointer to pass through... } return Shell_GetCachedImageIndex( (LPCTSTR) pszIconPath, iIconIndex, uIconFlags); } // Explicit prototype because only the A/W prototypes exist in the headers WINSHELLAPI LPITEMIDLIST WINAPI ILCreateFromPath(LPCTSTR pszPath); LPITEMIDLIST _AorW_ILCreateFromPath(LPCTSTR pszPath) { CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("ILCreateFromPath")); if (!UseUnicodeShell32()) { UnicodeToAnsi(pszPath, szPath, ARRAYSIZE(szPath)); pszPath = (LPCTSTR)szPath; // overload the pointer to pass through... } return ILCreateFromPath(pszPath); } int _AorW_PathCleanupSpec(LPCTSTR pszDir, LPTSTR pszSpec) { THUNKMSG(TEXT("PathCleanupSpec")); if (!UseUnicodeShell32()) { CHAR szDir[MAX_PATH]; CHAR szSpec[MAX_PATH]; LPSTR pszDir2 = szDir; int iRet; if (pszDir) { UnicodeToAnsi(pszDir, szDir, ARRAYSIZE(szDir)); } else { pszDir2 = NULL; } UnicodeToAnsi(pszSpec, szSpec, ARRAYSIZE(szSpec)); iRet = PathCleanupSpec((LPTSTR)pszDir2, (LPTSTR)szSpec); AnsiToUnicode(szSpec, pszSpec, MAX_PATH); return iRet; } else return PathCleanupSpec(pszDir, pszSpec); } void _AorW_PathQualify(LPTSTR pszDir) { THUNKMSG(TEXT("PathQualify")); if (!UseUnicodeShell32()) { CHAR szDir[MAX_PATH]; UnicodeToAnsi(pszDir, szDir, ARRAYSIZE(szDir)); PathQualify((LPTSTR)szDir); AnsiToUnicode(szDir, pszDir, MAX_PATH); } else PathQualify(pszDir); } LONG WINAPI _AorW_PathProcessCommand(LPCTSTR lpSrc, LPTSTR lpDest, int iDestMax, DWORD dwFlags) { LONG lReturnValue; THUNKMSG(TEXT("PathProcessCommand")); if (!UseUnicodeShell32()) { CHAR szSrc[MAX_PATH]; CHAR szDest[MAX_PATH]; UnicodeToAnsi(lpSrc, szSrc, ARRAYSIZE(szSrc)); lReturnValue = PathProcessCommand((LPTSTR)szSrc, (LPTSTR)szDest, iDestMax, dwFlags); AnsiToUnicode(szDest, lpDest, iDestMax); } else lReturnValue = PathProcessCommand(lpSrc, lpDest, iDestMax, dwFlags); return(lReturnValue); } HRESULT _AorW_SHCLSIDFromString(LPCTSTR lpsz, LPCLSID lpclsid) { CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("SHCLSIDFromString")); if (!UseUnicodeShell32()) { UnicodeToAnsi(lpsz, szPath, ARRAYSIZE(szPath)); lpsz = (LPCTSTR)szPath; // overload the pointer to pass through... } return SHCLSIDFromString(lpsz, lpclsid); } #ifndef UNIX // Explicit prototype because only the A/W prototypes exist in the headers WINSHELLAPI BOOL WINAPI SHGetSpecialFolderPath(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate); #else #ifdef UNICODE #define SHGetSpecialFolderPath SHGetSpecialFolderPathW #else #define SHGetSpecialFolderPath SHGetSpecialFolderPathA #endif #endif BOOL _AorW_SHGetSpecialFolderPath(HWND hwndOwner, LPTSTR pszPath, int nFolder, BOOL fCreate) { THUNKMSG(TEXT("SHGetSpecialFolderPath")); if (!UseUnicodeShell32()) { CHAR szPath[MAX_PATH]; BOOL fRet = SHGetSpecialFolderPath(hwndOwner, (LPTSTR)szPath, nFolder, fCreate); if (fRet) AnsiToUnicode(szPath, pszPath, MAX_PATH); return fRet; } else return SHGetSpecialFolderPath(hwndOwner, pszPath, nFolder, fCreate); } HRESULT _AorW_SHILCreateFromPath(LPCTSTR pszPath, LPITEMIDLIST *ppidl, DWORD *rgfInOut) { WCHAR wszPath[MAX_PATH]; CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("SHILCreateFromPath")); if (pszPath) { // // Shell32 will blindly copy pszPath into a MAX_PATH buffer. This // results in a exploitable buffer overrun. Do not pass more than // MAX_PATH characters. // if (!UseUnicodeShell32()) { UnicodeToAnsi(pszPath, szPath, ARRAYSIZE(szPath)); pszPath = (LPCTSTR)szPath; // overload the pointer to pass through... } else if (lstrlenW(pszPath) >= MAX_PATH) { StrCpyN(wszPath, pszPath, ARRAYSIZE(wszPath)); pszPath = wszPath; // overload the pointer to pass through... } } return SHILCreateFromPath(pszPath, ppidl, rgfInOut); } LPITEMIDLIST _AorW_SHSimpleIDListFromPath(LPCTSTR pszPath) { CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("SHSimpleIDListFromPath")); if (!UseUnicodeShell32() && pszPath) { UnicodeToAnsi(pszPath, szPath, ARRAYSIZE(szPath)); pszPath = (LPCTSTR)szPath; // overload the pointer to pass through... } return SHSimpleIDListFromPath(pszPath); } #define TEMP_SMALL_BUF_SZ 256 BOOL WINAPI _AorW_GetFileNameFromBrowse(HWND hwnd, LPTSTR pszFilePath, UINT cchFilePath, LPCTSTR pszWorkingDir, LPCTSTR pszDefExt, LPCTSTR pszFilters, LPCTSTR pszTitle) { CHAR szPath[MAX_PATH]; CHAR szDir[MAX_PATH]; CHAR szExt[TEMP_SMALL_BUF_SZ]; CHAR szFilters[TEMP_SMALL_BUF_SZ*2]; CHAR szTitle[TEMP_SMALL_BUF_SZ]; LPTSTR pszPath = pszFilePath; BOOL bResult; THUNKMSG(TEXT("GetFileNameFromBrowse")); // thunk strings to ansi if (!UseUnicodeShell32()) { // always move szFilePath stuff to wszPath buffer. Should never be a resourceid. UnicodeToAnsi((LPCTSTR)pszFilePath, szPath, ARRAYSIZE(szPath)); pszPath = (LPTSTR)szPath; if (!IS_INTRESOURCE(pszWorkingDir)) //not a resource { UnicodeToAnsi((LPCTSTR)pszWorkingDir, szDir, ARRAYSIZE(szDir)); pszWorkingDir = (LPCTSTR)szDir; } if (!IS_INTRESOURCE(pszDefExt)) //not a resource { UnicodeToAnsi((LPCTSTR)pszDefExt, szExt, ARRAYSIZE(szExt)); pszDefExt = (LPCTSTR)szExt; } if (!IS_INTRESOURCE(pszFilters)) //not a resource { int l=1; while (*(pszFilters+l) != 0 || *(pszFilters+l-1) != 0) l++; WideCharToMultiByte(CP_ACP, 0, (LPCTSTR)pszFilters, l+1, szFilters, ARRAYSIZE(szFilters), NULL, NULL); pszFilters = (LPCTSTR)szFilters; } if (!IS_INTRESOURCE(pszTitle)) //not a resource { UnicodeToAnsi((LPCTSTR)pszTitle, szTitle, ARRAYSIZE(szTitle)); pszTitle = (LPCTSTR)szTitle; } } bResult = GetFileNameFromBrowse(hwnd, pszPath, cchFilePath, pszWorkingDir, pszDefExt, pszFilters, pszTitle); if (!UseUnicodeShell32()) { AnsiToUnicode(szPath, pszFilePath, cchFilePath); } return (bResult); } IStream * _AorW_OpenRegStream(HKEY hkey, LPCTSTR pszSubkey, LPCTSTR pszValue, DWORD grfMode) { CHAR szSubkey[MAX_PATH]; // large enough to hold most any name... CHAR szValue[MAX_PATH]; // dito. if (!UseUnicodeShell32()) { UnicodeToAnsi(pszSubkey, szSubkey, ARRAYSIZE(szSubkey)); pszSubkey = (LPCTSTR)szSubkey; if (pszValue) { UnicodeToAnsi(pszValue, szValue, ARRAYSIZE(szValue)); pszValue = (LPCTSTR)szValue; } } return OpenRegStream(hkey, pszSubkey, pszValue, grfMode); } BOOL _AorW_Win32DeleteFile(LPCTSTR lpszFileName) { CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("Win32DeleteFile")); if (!UseUnicodeShell32()) { UnicodeToAnsi(lpszFileName, szPath, ARRAYSIZE(szPath)); lpszFileName = (LPCTSTR)szPath; // overload the pointer to pass through... } return Win32DeleteFile(lpszFileName); } BOOL _AorW_PathYetAnotherMakeUniqueName(LPTSTR pszUniqueName, LPCTSTR pszPath, LPCTSTR pszShort, LPCTSTR pszFileSpec) { CHAR szUniqueName[MAX_PATH]; CHAR szPath[MAX_PATH]; CHAR szShort[32]; CHAR szFileSpec[MAX_PATH]; BOOL fRet; THUNKMSG(TEXT("PathYetAnotherMakeUniqueName")); if (!UseUnicodeShell32()) { UnicodeToAnsi(pszPath, szPath, ARRAYSIZE(szPath)); pszPath = (LPCTSTR)szPath; // overload the pointer to pass through... if (pszShort) { UnicodeToAnsi(pszShort, szShort, ARRAYSIZE(szShort)); pszShort = (LPCTSTR)szShort; // overload the pointer to pass through... } if (pszFileSpec) { UnicodeToAnsi(pszFileSpec, szFileSpec, ARRAYSIZE(szFileSpec)); pszFileSpec = (LPCTSTR)szFileSpec; // overload the pointer to pass through... } fRet = PathYetAnotherMakeUniqueName((LPTSTR)szUniqueName, pszPath, pszShort, pszFileSpec); if (fRet) AnsiToUnicode(szUniqueName, pszUniqueName, MAX_PATH); return fRet; } else return PathYetAnotherMakeUniqueName(pszUniqueName, pszPath, pszShort, pszFileSpec); } BOOL _AorW_PathResolve(LPTSTR lpszPath, LPCTSTR rgpszDirs[], UINT fFlags) { CHAR szPath[MAX_PATH]; CHAR szDir[MAX_PATH]; BOOL fRet; THUNKMSG(TEXT("PathResolve")); if (!UseUnicodeShell32()) { // WARNING!!! // Super Hack, we assume dirs has only one element since it's the only case // this is called in SHDOCVW. UnicodeToAnsi(lpszPath, szPath, ARRAYSIZE(szPath)); if (rgpszDirs && rgpszDirs[0]) { UnicodeToAnsi(rgpszDirs[0], szDir, ARRAYSIZE(szDir)); rgpszDirs[0] = (LPCTSTR)szDir; // overload the pointer to pass through... if (rgpszDirs[1]) { AssertMsg(0, TEXT("PathResolve thunk needs to be fixed to handle more than one dirs.")); rgpszDirs[1] = NULL; } } fRet = PathResolve((LPTSTR)szPath, rgpszDirs, fFlags); if (fRet) AnsiToUnicode(szPath, lpszPath, MAX_PATH); return fRet; } else return PathResolve(lpszPath, rgpszDirs, fFlags); } // Explicit prototype because only the A/W prototypes exist in the headers // For UNIX, the old prototype should be defined, because there is no export // by ordinal there and IsLFNDrive is exported from shell32 just this way. #ifndef UNIX BOOL IsLFNDrive(LPCTSTR pszPath); #else # ifdef UNICODE # define IsLFNDrive IsLFNDriveW # else # define IsLFNDrive IsLFNDriveA # endif #endif BOOL _AorW_IsLFNDrive(LPTSTR lpszPath) { CHAR szPath[MAX_PATH]; THUNKMSG(TEXT("IsLFNDrive")); if (!UseUnicodeShell32()) { UnicodeToAnsi(lpszPath, szPath, ARRAYSIZE(szPath)); return IsLFNDrive((LPCTSTR)szPath); } return IsLFNDrive((LPCTSTR)lpszPath); } int _AorW_PickIconDlg( IN HWND hwnd, IN OUT LPTSTR pszIconPath, IN UINT cchIconPath, IN OUT int * piIconIndex) { int nRet; if (UseUnicodeShell32()) { nRet = PickIconDlg(hwnd, pszIconPath, cchIconPath, piIconIndex); } else { CHAR szPath[MAX_PATH]; UINT cch = ARRAYSIZE(szPath); UnicodeToAnsi(pszIconPath, szPath, cch); nRet = PickIconDlg(hwnd, (LPTSTR)szPath, cch, piIconIndex); AnsiToUnicode(szPath, pszIconPath, cchIconPath); } return nRet; } STDAPI_(int) _AorW_SHCreateDirectory(HWND hwnd, LPCTSTR pszPath) { if (UseUnicodeShell32()) { WCHAR wsz[MAX_PATH]; SHTCharToUnicode(pszPath, wsz, ARRAYSIZE(wsz)); return SHCreateDirectory(hwnd, (LPCTSTR)wsz); } else { CHAR sz[MAX_PATH]; SHTCharToAnsi(pszPath, sz, ARRAYSIZE(sz)); return SHCreateDirectory(hwnd, (LPCTSTR)sz); } } #endif // _X86_