Listing 2 Implementing SetCurrentDirectoryW() for SharedCU, Redefine and DLL models
#ifdef WDN_SHAREDCU
# define SetCurrentDirectoryW_impl SetCurrentDirectoryW
. . .
#endif /* WDN_SHAREDCU */
. . .
/* Loads KERNEL32.DLL and returns its instance handle. There's no
* release, but that's ok with KERNEL32.DLL, since every process
* must be statically linked to it in order to be able to call
* LoadLibrary() in the first place! Hacky, but valid.
*/
static HINSTANCE GetInstance_Kernel32();
static BOOL WINAPI SetCurrentDirectoryW_impl_9x(LPCWSTR lpPathName)
{
size_t len = lstrlenW(lpPathName);
char *pathName = (char*)_alloca(1 + len);
WideCharToMultiByte(CP_ACP, 0, lpPathName, 1 + len, pathName, 1 + len, NULL, NULL);
return SetCurrentDirectoryA(pathName);
}
static BOOL WINAPI SetCurrentDirectoryW_impl_NT(LPCWSTR lpPathName)
{
#ifdef WDN_SHAREDCU
/* In this mode, SetCurrentDirectoryW_impl is #defined to be SetCurrentDirectoryW,
* so linking to SetCurrentDirectoryW would just result in infinite recursion
* and stack exhaustion. It's unlikely that that process would result in the
* desired directory change.
*
* Hence, we need to load SetCurrentDirectoryW from KERNEL32.DLL, and call it
* in that way.
*/
typedef BOOL (WINAPI *PFnSetCurrentDirectoryW)(LPCWSTR lpFileName);
PFnSetCurrentDirectoryW pfn = (PFnSetCurrentDirectoryW)GetProcAddress(GetInstance_Kernel32(), "SetCurrentDirectoryW");
return (NULL == pfn) ? FALSE : pfn(lpPathName);
#else
/* Otherwise just link to the function directly. */
return SetCurrentDirectoryW(lpPathName);
#endif /* WDN_SHAREDCU */
}
#ifdef WDN_SHAREDCU
# pragma warning(disable : 4273)
#endif /* WDN_SHAREDCU */
#ifdef WDN_DLL
extern __declspec(dllexport)
#endif /* WDN_DLL */
BOOL WINAPI SetCurrentDirectoryW_impl(LPCWSTR lpPathName)
{
if(IsWinNT())
{
debug_printf("SetCurrentDirectoryW_impl(): calling NT's SetCurrentDirectoryW()\n");
return SetCurrentDirectoryW_impl_NT(lpPathName);
}
else
{
debug_printf("SetCurrentDirectoryW_impl(): calling SetCurrentDirectoryW_impl_9x()\n");
return SetCurrentDirectoryW_impl_9x(lpPathName);
}
}
#ifdef WDN_SHAREDCU
# pragma warning(default : 4273)
#endif /* WDN_SHAREDCU */