|
|
/*
* 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 */
|