/* * genthunk - Generic thunks */ #ifndef WIN32 #include "tweakui.h" const char CODESEG szKernel32[] = "KERNEL32"; /***************************************************************************** * * hwnd32Hwnd converts a 16-bit hwnd to a 32-bit hwnd. Note that we * extend with 0xFFFF to be compatible with NT. * *****************************************************************************/ #define hwnd32Hwnd(hwnd) MAKELONG(hwnd, 0xFFFF) /***************************************************************************** * * CallProcEx32W (a.k.a. ThunkMeHarder) * * Generic wrapper for thunking. * * lpszDll -> ASCIIZ DLL name * lpszProc -> ASCIIZ procedure name * c = number of arguments * dwMask = bitmask; if argument N is a pointer, then bit c-N is set. * Yes, it's backwards. * arg0, arg1, arg2, ... = arguments * * Returns whatever the procedure returns, or 0 on error. * * To aid in building dwMask, the macro ARGPTR(k,n) builds the * appropriate bitmask that indicates that argument k of n is * a pointer. k is zero-based, of course. * * This is pretty gross evil code that is Intel x86-specific. * But hey, it's Win16. That's to be expected. * * CallProc32W is insane. It's a variadic function that uses * the pascal calling convention. (It probably makes more sense * when you're stoned.) * *****************************************************************************/ DWORD PASCAL GetProcAddressEx32W(DWORD hinst, LPCSTR lpsz); DWORD WINAPI LoadLibraryEx32W(LPCSTR lpszLib, DWORD dw1, DWORD dw2); DWORD WINAPI GetProcAddress32W(DWORD hinst, LPCSTR lpsz); DWORD WINAPI FreeLibrary32W(DWORD hinst); DWORD WINAPI CallProc32W(DWORD pfn, DWORD dwMask, DWORD c); #define CallProcEx32W ThunkMeHarder #define ARGPTR(k,n) (1<<(n-k-1)) DWORD _cdecl ThunkMeHarder(LPCSTR lpszDll, LPCSTR lpszProc, UINT c, DWORD dwMask, ...) { DWORD dwRc = 0; DWORD hdll, pfn; if (SELECTOROF(lpszDll) ? (HIWORD(hdll = LoadLibraryEx32W(lpszDll, 0, 0)) && HIWORD(pfn = GetProcAddressEx32W(hdll, lpszProc))) : (hdll = 0, pfn = (DWORD)lpszProc, 1)) { _asm { mov cx, c /* cx = number of arguments */ xor si, si /* si = number of bytes pushed */ jcxz PushesDone PushHarder: _emit 0x66 /* 32-bit override */ push word ptr dwMask[4+si] add si, 4 loop PushHarder PushesDone: } dwRc = CallProc32W(pfn, dwMask, c); } if (HIWORD(hdll)) FreeLibrary32W(hdll); return dwRc; } /***************************************************************************** * * GetProcAddressEx32W * * The same as GetProcAddress32W, except it also understands ordinals. * * Yes, this is a rather close relationship we have with ThunkMeHarder, * * * (The Shell VxD does a very similar thing) * *****************************************************************************/ const char CODESEG szGetProcAddress[] = "GetProcAddress"; DWORD PASCAL GetProcAddressEx32W(DWORD hinst, LPCSTR lpsz) { if (SELECTOROF(lpsz)) { /* Optimization */ return GetProcAddress32W(hinst, lpsz); } else { return ThunkMeHarder(szKernel32, szGetProcAddress, 2, 0, hinst, lpsz); } } /***************************************************************************** * * CopyFile * *****************************************************************************/ const char CODESEG szCopyFileA[] = "CopyFileA"; BOOL PASCAL CopyFile(LPCSTR lpszSrc, LPCSTR lpszDst, BOOL fFailExists) { return CallProcEx32W(szKernel32, szCopyFileA, 3, ARGPTR(0,3)|ARGPTR(1,3), lpszSrc, lpszDst, (DWORD)fFailExists) != 0; } /***************************************************************************** * * SHChangeNotify * * Actually, we are slimy because we *know* that uFlags is always * SHCNF_PIDL, so no parameters need to be thunked. * *****************************************************************************/ const char CODESEG szSHChangeNotify[] = "SHChangeNotify"; void PASCAL SHChangeNotify(LONG wEventId, UINT uFlags, const void FAR *dwItem1, const void FAR *dwItem2) { CallProcEx32W(szShell32, szSHChangeNotify, 4, 0, wEventId, (DWORD)uFlags, dwItem1, dwItem2); } /***************************************************************************** * * SHGetSpecialFolderLocation * * Ignore the return value; just check the pidl. * *****************************************************************************/ const char CODESEG szSHGetSpecialFolderLocation[] = "SHGetSpecialFolderLocation"; void PASCAL SHGetSpecialFolderLocation(HWND hwnd, int nFolder, PIDL FAR *ppidl) { CallProcEx32W(szShell32, szSHGetSpecialFolderLocation, 3, ARGPTR(2,3), hwnd32Hwnd(hwnd), (LONG)nFolder, (LPVOID)ppidl); } /***************************************************************************** * * SHGetPathFromIDList * * Ignore the return value; just check the pidl. * *****************************************************************************/ const char CODESEG szSHGetPathFromIDList[] = "SHGetPathFromIDList"; void PASCAL SHGetPathFromIDList(PIDL pidl, LPSTR pszBuf) { CallProcEx32W(szShell32, szSHGetPathFromIDList, 2, ARGPTR(1,2), pidl, pszBuf); } /***************************************************************************** * * ILFree * * This is exported by ordinal. * *****************************************************************************/ void WINAPI ILFree(PIDL pidl) { CallProcEx32W(szShell32, MAKEINTRESOURCE(155), 1, 0, pidl); } /***************************************************************************** * * Shell_GetImageLists * * This is exported by ordinal. * *****************************************************************************/ BOOL PASCAL Shell_GetImageLists(HIMAGELIST FAR *phiml, HIMAGELIST FAR *phimlSmall) { return (BOOL)CallProcEx32W(szShell32, MAKEINTRESOURCE(71), 2, ARGPTR(0,2)|ARGPTR(1,2), phiml, phimlSmall); } /***************************************************************************** * * ExtractIconEx * *****************************************************************************/ const char CODESEG szExtractIconExA[] = "ExtractIconExA"; int PASCAL ExtractIconEx(LPCSTR pszFile, int iIcon, HICON FAR *phiconLarge, HICON FAR *phiconSmall, int nIcons) { return (int)CallProcEx32W(szShell32, szExtractIconExA, 5, ARGPTR(0,5)|ARGPTR(2,5)|ARGPTR(3,5), pszFile, (LONG)iIcon, phiconLarge, phiconSmall, (LONG)nIcons); } #endif /* !WIN32 */