#include "stock.h" #pragma hdrstop #define SHFUSION_IMPL #include "shfusion.h" #include "delaycc.h" #ifdef FUSION_DOWNLEVEL #include #endif typedef BOOL (__stdcall *PFNACTCTX)(HANDLE, ULONG_PTR *); typedef BOOL (__stdcall *PFNDEACTCTX)(DWORD, ULONG_PTR ); typedef HANDLE (__stdcall *PFNCREATECTX)(ACTCTX*); typedef void (__stdcall *PFNRELCTX)(HANDLE); typedef UINT (__stdcall *PFNGSWD)(PTSTR psz, int cch); HMODULE g_hmodKernel = NULL; static PFNACTCTX s_pfnAct = (PFNACTCTX)-1; static PFNDEACTCTX s_pfnDeact = (PFNDEACTCTX)-1; static PFNCREATECTX s_pfnCreateact = (PFNCREATECTX)-1; static PFNRELCTX s_pfnReleaseact = (PFNRELCTX)-1; static PFNGSWD s_pfnGetSysWinDir = (PFNGSWD)-1; HANDLE NT5_CreateActCtx(ACTCTX* p) { if (s_pfnCreateact == (PFNCREATECTX)-1) { g_hmodKernel = GetModuleHandle(TEXT("Kernel32")); if (g_hmodKernel) { #ifdef _UNICODE s_pfnCreateact = (PFNCREATECTX)GetProcAddress(g_hmodKernel, "CreateActCtxW"); #else s_pfnCreateact = (PFNCREATECTX)GetProcAddress(g_hmodKernel, "CreateActCtxA"); #endif // _UNICODE } else s_pfnCreateact = NULL; } if (s_pfnCreateact) return s_pfnCreateact(p); return NULL; } void NT5_ReleaseActCtx(HANDLE h) { if (s_pfnReleaseact == (PFNRELCTX)-1) { g_hmodKernel = GetModuleHandle(TEXT("Kernel32")); if (g_hmodKernel) { s_pfnReleaseact = (PFNRELCTX)GetProcAddress(g_hmodKernel, "ReleaseActCtx"); } else s_pfnReleaseact = NULL; } if (s_pfnReleaseact) s_pfnReleaseact(h); } BOOL NT5_ActivateActCtx(HANDLE h, ULONG_PTR* p) { if (s_pfnAct == (PFNACTCTX)-1) { g_hmodKernel = GetModuleHandle(TEXT("Kernel32")); if (g_hmodKernel) { s_pfnAct = (PFNACTCTX)GetProcAddress(g_hmodKernel, "ActivateActCtx"); } else { s_pfnAct = NULL; } } *p = 0; if (s_pfnAct) { return s_pfnAct(h, p); } return TRUE; } BOOL NT5_DeactivateActCtx(ULONG_PTR p) { if (s_pfnDeact == (PFNDEACTCTX)-1) { g_hmodKernel = GetModuleHandle(TEXT("Kernel32")); if (g_hmodKernel) { s_pfnDeact = (PFNDEACTCTX)GetProcAddress(g_hmodKernel, "DeactivateActCtx"); } else s_pfnDeact = NULL; } if (s_pfnDeact) return s_pfnDeact(0, p); return TRUE; } BOOL SHActivateContext(ULONG_PTR* pulCookie) { *pulCookie = 0; if (g_hActCtx != INVALID_HANDLE_VALUE) { return NT5_ActivateActCtx(g_hActCtx, pulCookie); } // Default to success in activation for down level. return TRUE; } void SHDeactivateContext(ULONG_PTR ulCookie) { if (ulCookie != 0) { NT5_DeactivateActCtx(ulCookie); } } #define ENTERCONTEXT(fail) \ ULONG_PTR ulCookie = 0;\ if (!SHActivateContext(&ulCookie)) \ return fail;\ __try { #define LEAVECONTEXT \ } __finally {SHDeactivateContext(ulCookie);} EXTERN_C HINSTANCE g_hinst; HANDLE g_hActCtx = INVALID_HANDLE_VALUE; UINT NT5_GetSystemWindowsDirectory(PTSTR psz, int cch) { if (s_pfnGetSysWinDir == (PFNGSWD)-1) { g_hmodKernel = GetModuleHandle(TEXT("Kernel32")); if (g_hmodKernel) { #ifdef _UNICODE s_pfnGetSysWinDir = (PFNGSWD)GetProcAddress(g_hmodKernel, "GetSystemWindowsDirectoryW"); #else s_pfnGetSysWinDir = (PFNGSWD)GetProcAddress(g_hmodKernel, "GetSystemWindowsDirectoryA"); #endif // _UNICODE } else s_pfnGetSysWinDir = NULL; } if (s_pfnGetSysWinDir) return s_pfnGetSysWinDir(psz, cch); else return GetWindowsDirectory(psz, cch); } void SHGetManifest(PTSTR pszManifest, int cch) { int cchWindir = NT5_GetSystemWindowsDirectory(pszManifest, cch); // We want to use StrCatBuff but we cannot assume that the caller // is using shlwapi so we do it manually. Note that it's okay to use // lstrcpynW even though Win9x doesn't support it, because Win9x doesn't // support manifests anyway! if (cch > cchWindir) { lstrcpyn(pszManifest + cchWindir, TEXT("\\WindowsShell.Manifest"), cch - cchWindir); } } void VerifyComctl32Loaded() { #ifndef NOCOMCTL32 DelayLoadCC(); #endif } BOOL SHFusionInitializeIDCC(PTSTR pszPath, int id, BOOL fLoadCC) { TCHAR szPath[MAX_PATH]; ACTCTX act = {0}; if (pszPath == NULL) { SHGetManifest(szPath, ARRAYSIZE(szPath)); pszPath = szPath; } else { act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID; act.lpResourceName = MAKEINTRESOURCE(id); } if (g_hActCtx == INVALID_HANDLE_VALUE) { act.cbSize = sizeof(act); act.lpSource = pszPath; g_hActCtx = NT5_CreateActCtx(&act); } #ifndef NOCOMCTL32 if (fLoadCC) DelayLoadCC(); #endif return g_hActCtx != INVALID_HANDLE_VALUE; } BOOL SHFusionInitializeID(PTSTR pszPath, int id) { return SHFusionInitializeIDCC(pszPath, id, TRUE); } BOOL SHFusionInitialize(PTSTR pszPath) { return SHFusionInitializeID(pszPath, 123); } BOOL SHFusionInitializeFromModuleID(HMODULE hMod, int id) { TCHAR szPath[MAX_PATH]; GetModuleFileName(hMod, szPath, ARRAYSIZE(szPath)); return SHFusionInitializeIDCC(szPath, id, TRUE); } BOOL SHFusionInitializeFromModuleIDCC(HMODULE hMod, int id, BOOL fLoadCC) { TCHAR szPath[MAX_PATH]; GetModuleFileName(hMod, szPath, ARRAYSIZE(szPath)); return SHFusionInitializeIDCC(szPath, id, fLoadCC); } BOOL __stdcall SHFusionInitializeFromModuleIDNoCC(HMODULE hMod, int id) { TCHAR szPath[MAX_PATH]; GetModuleFileName(hMod, szPath, ARRAYSIZE(szPath)); return SHFusionInitializeIDCC(szPath, id, FALSE); } BOOL SHFusionInitializeFromModule(HMODULE hMod) { TCHAR szPath[MAX_PATH]; GetModuleFileName(hMod, szPath, ARRAYSIZE(szPath)); return SHFusionInitialize(szPath); } void SHFusionUninitialize() { if (g_hActCtx != INVALID_HANDLE_VALUE) { NT5_ReleaseActCtx(g_hActCtx); g_hActCtx = INVALID_HANDLE_VALUE; } } HMODULE SHFusionLoadLibrary(LPCTSTR lpLibFileName) { HMODULE hmod; ENTERCONTEXT(NULL) hmod = LoadLibrary(lpLibFileName); LEAVECONTEXT return hmod; } HWND SHFusionCreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { HWND hwnd; ENTERCONTEXT(NULL) VerifyComctl32Loaded(); hwnd = CreateWindow(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); LEAVECONTEXT return hwnd; } HWND SHFusionCreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { HWND hwnd; ENTERCONTEXT(NULL) VerifyComctl32Loaded(); hwnd = CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); LEAVECONTEXT return hwnd; } HWND SHNoFusionCreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { // DO NOT ACTIVATE A MANIFEST. HWND hwnd; VerifyComctl32Loaded(); hwnd = CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); return hwnd; } HWND SHFusionCreateDialogIndirect(HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc) { HWND hwnd; ENTERCONTEXT(NULL) VerifyComctl32Loaded(); hwnd = CreateDialogIndirect(hInstance, lpTemplate, hWndParent, lpDialogFunc); LEAVECONTEXT return hwnd; } HWND SHFusionCreateDialogParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { HWND hwnd; ENTERCONTEXT(NULL) VerifyComctl32Loaded(); hwnd = CreateDialogParam(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); LEAVECONTEXT return hwnd; } HWND SHFusionCreateDialogIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit) { HWND hwnd; ENTERCONTEXT(NULL) VerifyComctl32Loaded(); hwnd = CreateDialogIndirectParam(hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit); LEAVECONTEXT return hwnd; } HWND SHNoFusionCreateDialogIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit) { HWND hwnd; VerifyComctl32Loaded(); hwnd = CreateDialogIndirectParam(hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit); return hwnd; } INT_PTR SHFusionDialogBoxIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATE hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { INT_PTR i; ENTERCONTEXT(0) VerifyComctl32Loaded(); i = DialogBoxIndirectParam(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam); LEAVECONTEXT return i; } INT_PTR SHFusionDialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { INT_PTR i; ENTERCONTEXT(0) VerifyComctl32Loaded(); i = DialogBoxParam(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); LEAVECONTEXT return i; } ATOM SHFusionRegisterClass(CONST WNDCLASS *lpWndClass) { ATOM a; ENTERCONTEXT(0) a = RegisterClass(lpWndClass); LEAVECONTEXT return a; } ATOM SHFusionRegisterClassEx(CONST WNDCLASSEX *lpwcx) { ATOM a; ENTERCONTEXT(0) a = RegisterClassEx(lpwcx); LEAVECONTEXT return a; } BOOL SHFusionGetClassInfo(HINSTANCE hInstance, LPCTSTR lpClassName, LPWNDCLASS lpWndClass) { BOOL f; ENTERCONTEXT(FALSE) f = GetClassInfo(hInstance, lpClassName, lpWndClass); LEAVECONTEXT return f; } BOOL SHFusionGetClassInfoEx(HINSTANCE hinst, LPCTSTR lpszClass, LPWNDCLASSEX lpwcx) { BOOL f; ENTERCONTEXT(FALSE) f = GetClassInfoEx(hinst, lpszClass, lpwcx); LEAVECONTEXT return f; } STDAPI SHSquirtManifest(HINSTANCE hInst, UINT uIdManifest, LPTSTR pszPath) { HRESULT hr = E_FAIL; char szManifest[2048]; // Comctl32 has a long manifest. if (LoadStringA(hInst, uIdManifest, szManifest, ARRAYSIZE(szManifest))) { HANDLE hFile; SetFileAttributes(pszPath, FILE_ATTRIBUTE_NORMAL); hFile = CreateFile(pszPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY, NULL); if (hFile != INVALID_HANDLE_VALUE) { DWORD dw = lstrlenA(szManifest) * sizeof(char); if (WriteFile(hFile, szManifest, dw, &dw, NULL)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } CloseHandle(hFile); } } return hr; }