489 lines
14 KiB
C
489 lines
14 KiB
C
#include "priv.h"
|
|
|
|
// no wrappers are needed on non-x86 since this is only for win9x interop
|
|
#ifdef _X86_
|
|
|
|
#include <mluisupp.h>
|
|
|
|
//============================================================================
|
|
// 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_
|