mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-18 23:11:19 +03:00
642 lines
21 KiB
C
Executable File
642 lines
21 KiB
C
Executable File
/*
|
|
* KernelEx Thunking Unicode Layer
|
|
*
|
|
* Copyright (C) 2009-2010, Tihiy
|
|
*
|
|
* This file is part of KernelEx source code.
|
|
*
|
|
* KernelEx is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published
|
|
* by the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* KernelEx is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include "k32ord.h"
|
|
#include "thuni_thunk.h"
|
|
#include "thuni_layer.h"
|
|
#include "thuni_macro.h"
|
|
|
|
static GCQ_API GetCurrentThreadQueue;
|
|
static HTOP_API HWNDtoPWND;
|
|
|
|
static LPCRITICAL_SECTION pWin16Mutex;
|
|
static CRITICAL_SECTION wndproc_cs;
|
|
|
|
static HMODULE g_hUser32;
|
|
|
|
#define SetWinCreateEvent(proc) SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, g_hUser32, \
|
|
(WINEVENTPROC)(proc), GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT)
|
|
|
|
BOOL InitUniThunkLayer()
|
|
{
|
|
g_hUser32 = GetModuleHandleA("user32");
|
|
/* Returns current thread hQueue 32-bit pointer */
|
|
GetCurrentThreadQueue = (GCQ_API) RELTOABS( (DWORD)GetMessageExtraInfo + 7 );
|
|
/* IsWindow returns PWND */
|
|
HWNDtoPWND = (HTOP_API)IsWindow;
|
|
|
|
_GetpWin16Lock( &pWin16Mutex );
|
|
InitializeCriticalSection( &wndproc_cs );
|
|
MakeCriticalSectionGlobal( &wndproc_cs );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void GrabWin16Lock()
|
|
{
|
|
_EnterSysLevel(pWin16Mutex);
|
|
}
|
|
|
|
void ReleaseWin16Lock()
|
|
{
|
|
_LeaveSysLevel(pWin16Mutex);
|
|
}
|
|
|
|
static WNDPROC WINAPI _GetWindowProc32(PWND pwnd)
|
|
{
|
|
if ( !pwnd ) return NULL;
|
|
if ( !IS32BITWIN(pwnd) ) return NULL;
|
|
PTHUNK16 proc32 = (PTHUNK16)MapSL( (DWORD)pwnd->lpfnWndProc );
|
|
if ( !proc32 ) return NULL;
|
|
if ( proc32->push1 != pushl16_code ) return NULL; //NOT 16-bit pushl?
|
|
return proc32->proc;
|
|
}
|
|
|
|
static PMSGQUEUE _GetWindowQueue(PWND pwnd)
|
|
{
|
|
return pwnd ? (PMSGQUEUE)MapSL( (DWORD)pwnd->hQueue << 16 ) : NULL;
|
|
}
|
|
|
|
static void _SetWindowUnicode(PWND pwnd, BOOL bUnicode)
|
|
{
|
|
if ( pwnd )
|
|
{
|
|
if (bUnicode)
|
|
pwnd->ExStyle |= WS_EX_UNICODE;
|
|
else
|
|
pwnd->ExStyle &= ~WS_EX_UNICODE;
|
|
}
|
|
}
|
|
|
|
BOOL IsWindowReallyUnicode(HWND hwnd)
|
|
{
|
|
/* window is really unicode if it has unicode procedure */
|
|
PWND pwnd = HWNDtoPWND(hwnd);
|
|
if ( pwnd && IS32BITWIN(pwnd) )
|
|
{
|
|
THUNKPROC proc = (THUNKPROC)_GetWindowProc32( pwnd );
|
|
if ( proc && proc->sign == wtoa_code && IsValidThunk(proc) ) return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
#endif
|
|
__declspec(dllexport)
|
|
void SetWindowUnicode(HWND hWnd, BOOL bUnicode)
|
|
{
|
|
GrabWin16Lock();
|
|
_SetWindowUnicode( HWNDtoPWND(hWnd), bUnicode );
|
|
ReleaseWin16Lock();
|
|
}
|
|
|
|
/* MAKE_EXPORT GetWindowLongA_NEW=GetWindowLongA */
|
|
LONG WINAPI GetWindowLongA_NEW(HWND hWnd, int nIndex)
|
|
{
|
|
LONG ret = GetWindowLongA( hWnd, nIndex );
|
|
if (nIndex == GWL_EXSTYLE) ret = ret & ~WS_EX_UNICODE; //mask out our flag
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT IsWindowUnicode_NEW=IsWindowUnicode */
|
|
BOOL WINAPI IsWindowUnicode_NEW( HWND hWnd )
|
|
{
|
|
return GetWindowLongA(hWnd, GWL_EXSTYLE) & WS_EX_UNICODE ? TRUE : FALSE;
|
|
}
|
|
|
|
/* MAKE_EXPORT SetWindowLongA_NEW=SetWindowLongA */
|
|
LONG WINAPI SetWindowLongA_NEW(HWND hWnd, int nIndex, LONG dwNewLong)
|
|
{
|
|
BOOL WasUnicode = FALSE;
|
|
LONG ret;
|
|
if ( nIndex == GWL_EXSTYLE )
|
|
{
|
|
WasUnicode = IsWindowUnicode_NEW( hWnd );
|
|
dwNewLong &= ~WS_EX_UNICODE; //don't let reset nor see unicode flag!!!
|
|
}
|
|
ret = SetWindowLongA( hWnd, nIndex, dwNewLong );
|
|
if ( WasUnicode )
|
|
SetWindowUnicode( hWnd, TRUE ); //restore unicode flag if someone changed ExStyle
|
|
if ( nIndex == GWL_WNDPROC && ret )
|
|
SetWindowUnicode( hWnd, FALSE ); //remove 'Unicode' flag
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* allocate a thunk, AtoW / WtoA
|
|
*/
|
|
static WNDPROC AllocWndProc( PROCESS_THUNKS thunks, WNDPROC oldproc, BOOL AtoW )
|
|
{
|
|
int thunk_number = thunks->count;
|
|
if (thunk_number == CHUNK_THUNKS) //if chunk is full, grow chunk list (thunks points to last chunk)
|
|
{
|
|
thunks = GrowProcessThunks(thunks);
|
|
DBGPRINTF(("Thunks array has grown (new chunk %p)\n",thunks));
|
|
if (!thunks) return oldproc;
|
|
thunk_number = 0;
|
|
}
|
|
DWORD thunkfunc = AtoW ? (DWORD)CallProcAnsiWithUnicode : (DWORD)CallProcUnicodeWithAnsi; //logic is inverted!!! AtoW=Unicode2Ansi, vice versa
|
|
thunks->array[thunk_number].sign = AtoW ? atow_code : wtoa_code;
|
|
thunks->array[thunk_number].pop_eax = pop_eax_code;
|
|
thunks->array[thunk_number].push_func = push_func_code;
|
|
thunks->array[thunk_number].proc = oldproc;
|
|
thunks->array[thunk_number].push_eax = push_eax_code;
|
|
thunks->array[thunk_number].jmp_func = jmp_func_code;
|
|
thunks->array[thunk_number].relay_offset = thunkfunc - (DWORD)&thunks->array[thunk_number].relay_offset - sizeof(DWORD);
|
|
thunks->count++;
|
|
|
|
return (WNDPROC)&thunks->array[thunk_number];
|
|
}
|
|
|
|
/* Window procedure conversions */
|
|
|
|
/* ConvertWndProc W<->A are using per-process
|
|
* growable array of executable code thunks.
|
|
* The rules are simple:
|
|
* WToA(procW) = procA, AToW(procA) = procW
|
|
* WToA(procA) or AToW(procW) are invalid,
|
|
* but we fix this case too.
|
|
*/
|
|
|
|
static WNDPROC ConvertWndProcWToA( WNDPROC ProcW )
|
|
{
|
|
int i;
|
|
WNDPROC ret = NULL;
|
|
THUNKPROC thunk = (THUNKPROC)ProcW;
|
|
if ( !HIWORD(ProcW) ) return ProcW;
|
|
if ( thunk->sign == atow_code && IsValidThunk(thunk) ) return thunk->proc;
|
|
if ( thunk->sign == wtoa_code && IsValidThunk(thunk) ) return ProcW; //invalid
|
|
if ( ProcW == DefWindowProcW_NEW ) return DefWindowProcA;
|
|
if ( ProcW == DefDlgProcW_NEW ) return DefDlgProcA;
|
|
if ( ProcW == DefMDIChildProcW_NEW ) return DefMDIChildProcA;
|
|
EnterCriticalSection( &wndproc_cs );
|
|
PROCESS_THUNKS procthunks = GetProcessThunks();
|
|
while (true)
|
|
{
|
|
for ( i=0; i<procthunks->count; i++)
|
|
{
|
|
if ( procthunks->array[i].proc == ProcW && procthunks->array[i].sign == wtoa_code )
|
|
{
|
|
//we have an WtoA thunk already
|
|
ret = (WNDPROC)&procthunks->array[i];
|
|
break;
|
|
}
|
|
}
|
|
if (ret || !procthunks->nextChunk) break;
|
|
procthunks = procthunks->nextChunk;
|
|
}
|
|
if ( !ret ) ret = AllocWndProc( procthunks, ProcW, FALSE );
|
|
LeaveCriticalSection( &wndproc_cs );
|
|
return ret;
|
|
}
|
|
|
|
static WNDPROC ConvertWndProcAToW( WNDPROC ProcA )
|
|
{
|
|
int i;
|
|
WNDPROC ret = NULL;
|
|
THUNKPROC thunk = (THUNKPROC)ProcA;
|
|
if ( !HIWORD(ProcA) ) return ProcA;
|
|
if ( thunk->sign == wtoa_code && IsValidThunk(thunk) ) return thunk->proc;
|
|
if ( thunk->sign == atow_code && IsValidThunk(thunk) ) return ProcA; //invalid
|
|
if ( ProcA == DefWindowProcA ) return DefWindowProcW_NEW;
|
|
if ( ProcA == DefDlgProcA ) return DefDlgProcW_NEW;
|
|
if ( ProcA == DefMDIChildProcA ) return DefMDIChildProcW_NEW;
|
|
EnterCriticalSection( &wndproc_cs );
|
|
PROCESS_THUNKS procthunks = GetProcessThunks();
|
|
while (true)
|
|
{
|
|
for ( i=0; i<procthunks->count; i++)
|
|
{
|
|
if ( procthunks->array[i].proc == ProcA && procthunks->array[i].sign == atow_code )
|
|
{
|
|
//we have an WtoA thunk already
|
|
ret = (WNDPROC)&procthunks->array[i];
|
|
break;
|
|
}
|
|
}
|
|
if (ret || !procthunks->nextChunk) break;
|
|
procthunks = procthunks->nextChunk;
|
|
}
|
|
if ( !ret ) ret = AllocWndProc( procthunks, ProcA, TRUE );
|
|
LeaveCriticalSection( &wndproc_cs );
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT GetWindowLongW_NEW=GetWindowLongW */
|
|
LONG WINAPI GetWindowLongW_NEW(HWND hWnd, int nIndex)
|
|
{
|
|
LONG ret = GetWindowLongA_NEW(hWnd, nIndex);
|
|
if ( nIndex == GWL_WNDPROC )
|
|
{
|
|
if ( !ISOURPROCESSHWND(hWnd) )
|
|
{
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
return 0L;
|
|
}
|
|
ret = (LONG)ConvertWndProcAToW( (WNDPROC)ret );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT SetWindowLongW_NEW=SetWindowLongW */
|
|
LONG WINAPI SetWindowLongW_NEW(HWND hWnd, int nIndex, LONG dwNewLong)
|
|
{
|
|
LONG ret;
|
|
if ( nIndex == GWL_WNDPROC )
|
|
{
|
|
if ( !ISOURPROCESSHWND(hWnd) )
|
|
{
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
return 0L;
|
|
}
|
|
dwNewLong = (LONG)ConvertWndProcWToA( (WNDPROC)dwNewLong );
|
|
}
|
|
|
|
ret = SetWindowLongA_NEW( hWnd, nIndex, dwNewLong );
|
|
|
|
if ( nIndex == GWL_WNDPROC && ret ) //oh, you're unicode subclassed!
|
|
{
|
|
SetWindowUnicode( hWnd, TRUE );
|
|
ret = (LONG)ConvertWndProcAToW( (WNDPROC)ret );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* Class manipulation functions*/
|
|
|
|
/* MAKE_EXPORT GetClassLongW_NEW=GetClassLongW */
|
|
DWORD WINAPI GetClassLongW_NEW(HWND hWnd, int nIndex)
|
|
{
|
|
DWORD ret = GetClassLongA(hWnd, nIndex);
|
|
if ( nIndex == GCL_WNDPROC )
|
|
{
|
|
if ( !ISOURPROCESSHWND(hWnd) )
|
|
{
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
return 0L;
|
|
}
|
|
ret = (DWORD)ConvertWndProcAToW( (WNDPROC)ret );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT SetClassLongW_NEW=SetClassLongW */
|
|
DWORD WINAPI SetClassLongW_NEW(HWND hWnd, int nIndex, LONG dwNewLong)
|
|
{
|
|
DWORD ret;
|
|
if ( nIndex == GCL_WNDPROC )
|
|
{
|
|
if ( !ISOURPROCESSHWND(hWnd) )
|
|
{
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
return 0L;
|
|
}
|
|
dwNewLong = (DWORD)ConvertWndProcWToA( (WNDPROC)dwNewLong );
|
|
}
|
|
ret = SetClassLongA( hWnd, nIndex, dwNewLong );
|
|
if ( nIndex == GCL_WNDPROC && ret )
|
|
ret = (DWORD)ConvertWndProcAToW( (WNDPROC)ret );
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT RegisterClassExW_NEW=RegisterClassExW */
|
|
ATOM WINAPI RegisterClassExW_NEW( CONST WNDCLASSEXW *lpwcx )
|
|
{
|
|
WNDCLASSEXA wnda;
|
|
if ( !lpwcx || !HIWORD(lpwcx->lpfnWndProc) ) return FALSE;
|
|
CopyMemory( &wnda, lpwcx, sizeof(WNDCLASSEXA));
|
|
STACK_WtoA(lpwcx->lpszClassName, wnda.lpszClassName);
|
|
STACK_WtoA(lpwcx->lpszMenuName, wnda.lpszMenuName);
|
|
wnda.lpfnWndProc = ConvertWndProcWToA( wnda.lpfnWndProc );
|
|
return RegisterClassExA(&wnda);
|
|
}
|
|
|
|
/* MAKE_EXPORT RegisterClassW_NEW=RegisterClassW */
|
|
ATOM WINAPI RegisterClassW_NEW( CONST WNDCLASSW *lpwcx )
|
|
{
|
|
WNDCLASSEXW wndw;
|
|
wndw.cbSize = sizeof(WNDCLASSEXW);
|
|
wndw.style = lpwcx->style;
|
|
wndw.lpfnWndProc = lpwcx->lpfnWndProc;
|
|
wndw.cbClsExtra = lpwcx->cbClsExtra;
|
|
wndw.cbWndExtra = lpwcx->cbWndExtra;
|
|
wndw.hInstance = lpwcx->hInstance;
|
|
wndw.hIcon = lpwcx->hIcon;
|
|
wndw.hCursor = lpwcx->hCursor;
|
|
wndw.hbrBackground = lpwcx->hbrBackground;
|
|
wndw.lpszMenuName = lpwcx->lpszMenuName;
|
|
wndw.lpszClassName = lpwcx->lpszClassName;
|
|
wndw.hIconSm = NULL;
|
|
return RegisterClassExW_NEW( &wndw );
|
|
}
|
|
|
|
//Those two are both ATOMs
|
|
/* MAKE_EXPORT GetClassInfoExW_NEW=GetClassInfoExW */
|
|
ATOM WINAPI GetClassInfoExW_NEW(HINSTANCE hinst, LPCWSTR lpszClass, WNDCLASSEXW *lpwcx)
|
|
{
|
|
LPSTR lpszClassA;
|
|
STACK_WtoA(lpszClass, lpszClassA);
|
|
ATOM ret = GetClassInfoExA( hinst, lpszClassA, (WNDCLASSEXA*)lpwcx );
|
|
if ( ret )
|
|
{
|
|
lpwcx->lpfnWndProc = ConvertWndProcAToW( lpwcx->lpfnWndProc );
|
|
//lpwcx->lpszClassName = lpszClass;
|
|
/* BUGBUG this is not correct behavior. lpszClassName/lpszMenuName have to be
|
|
* permanent pointers! Maybe it can be solved with static buffer like MSLU does.
|
|
*/
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT GetClassInfoW_NEW=GetClassInfoW */
|
|
ATOM WINAPI GetClassInfoW_NEW(HINSTANCE hinst, LPCWSTR lpszClass, WNDCLASSW *wc)
|
|
{
|
|
WNDCLASSEXW wcex;
|
|
wcex.cbSize = sizeof(WNDCLASS);
|
|
ATOM ret = GetClassInfoExW_NEW( hinst, lpszClass, &wcex );
|
|
if (ret && wc)
|
|
{
|
|
wc->style = wcex.style;
|
|
wc->lpfnWndProc = wcex.lpfnWndProc;
|
|
wc->cbClsExtra = wcex.cbClsExtra;
|
|
wc->cbWndExtra = wcex.cbWndExtra;
|
|
wc->hInstance = wcex.hInstance;
|
|
wc->hIcon = wcex.hIcon;
|
|
wc->hCursor = wcex.hCursor;
|
|
wc->hbrBackground = wcex.hbrBackground;
|
|
wc->lpszMenuName = wcex.lpszMenuName;
|
|
wc->lpszClassName = wcex.lpszClassName;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/* Unicode flagging */
|
|
static void CALLBACK UnicodeEvent( HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime )
|
|
{
|
|
if ( idObject != OBJID_WINDOW ) return;
|
|
//NOTE: we don't grab Win16Lock!! we touch windows only belonging to current thread.
|
|
BOOL isUnicode = FALSE;
|
|
PWND pwnd = HWNDtoPWND(hwnd);
|
|
if ( !pwnd ) return; //wtf
|
|
if ( !IS32BITWIN(pwnd) )
|
|
isUnicode = TRUE; //16-bit window, will be Unicode
|
|
else
|
|
{
|
|
THUNKPROC proc = (THUNKPROC)_GetWindowProc32( pwnd );
|
|
if ( IS_SHARED(proc) || (proc && proc->sign == wtoa_code && IsValidThunk(proc)) ) //shared control or Unicode thunk
|
|
isUnicode = TRUE;
|
|
}
|
|
if ( isUnicode ) _SetWindowUnicode( pwnd, TRUE );
|
|
if ( isUnicode ) SendMessage( hwnd, CCM_SETUNICODEFORMAT, TRUE, 0 );
|
|
}
|
|
|
|
/* Window creation functions */
|
|
|
|
/* MAKE_EXPORT CreateWindowExW_NEW=CreateWindowExW */
|
|
HWND WINAPI CreateWindowExW_NEW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
|
{
|
|
LPSTR lpClassNameA;
|
|
LPSTR lpWindowNameA;
|
|
HWINEVENTHOOK uniEvent;
|
|
HWND ret;
|
|
|
|
STACK_WtoA(lpClassName, lpClassNameA);
|
|
STACK_WtoA(lpWindowName, lpWindowNameA);
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = CreateWindowExA(dwExStyle,lpClassNameA,lpWindowNameA,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam);
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT CreateWindowW_NEW=CreateWindowW */
|
|
HWND WINAPI CreateWindowW_NEW( LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
|
{
|
|
return CreateWindowExW_NEW(0, lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam);
|
|
}
|
|
|
|
/* MAKE_EXPORT CreateMDIWindowW_NEW=CreateMDIWindowW */
|
|
HWND WINAPI CreateMDIWindowW_NEW( LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
|
|
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HINSTANCE hInstance, LPARAM lParam)
|
|
{
|
|
LPSTR lpClassNameA;
|
|
LPSTR lpWindowNameA;
|
|
HWINEVENTHOOK uniEvent;
|
|
HWND ret;
|
|
|
|
STACK_WtoA(lpClassName, lpClassNameA);
|
|
STACK_WtoA(lpWindowName, lpWindowNameA);
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = CreateMDIWindowA(lpClassNameA,lpWindowNameA,dwStyle,X,Y,nWidth,nHeight,hWndParent,hInstance,lParam);
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT CreateDialogParamW_NEW=CreateDialogParamW */
|
|
HWND WINAPI CreateDialogParamW_NEW( HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
|
|
{
|
|
LPSTR lpTemplateNameA;
|
|
HWINEVENTHOOK uniEvent;
|
|
HWND ret;
|
|
|
|
STACK_WtoA(lpTemplateName, lpTemplateNameA);
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = CreateDialogParamA( hInstance, lpTemplateNameA, hWndParent, lpDialogFunc, dwInitParam );
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT CreateDialogIndirectParamW_NEW=CreateDialogIndirectParamW */
|
|
HWND WINAPI CreateDialogIndirectParamW_NEW( HINSTANCE hInstance, LPCDLGTEMPLATE lpTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM lParamInit)
|
|
{
|
|
HWINEVENTHOOK uniEvent;
|
|
HWND ret;
|
|
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = CreateDialogIndirectParamA( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit );
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT DialogBoxParamW_NEW=DialogBoxParamW */
|
|
INT_PTR WINAPI DialogBoxParamW_NEW( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
|
|
{
|
|
LPSTR lpTemplateNameA;
|
|
HWINEVENTHOOK uniEvent;
|
|
INT_PTR ret;
|
|
|
|
STACK_WtoA( lpTemplateName, lpTemplateNameA );
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = DialogBoxParamA( hInstance, lpTemplateNameA, hWndParent, lpDialogFunc, dwInitParam );
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
/* MAKE_EXPORT DialogBoxIndirectParamW_NEW=DialogBoxIndirectParamW */
|
|
INT_PTR WINAPI DialogBoxIndirectParamW_NEW( HINSTANCE hInstance, LPCDLGTEMPLATE hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
|
|
{
|
|
HWINEVENTHOOK uniEvent;
|
|
INT_PTR ret;
|
|
|
|
|
|
uniEvent = SetWinCreateEvent(UnicodeEvent);
|
|
ret = DialogBoxIndirectParamA( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam );
|
|
UnhookWinEvent(uniEvent);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/* MAKE_EXPORT SendMessageW_NEW=SendMessageW */
|
|
LRESULT WINAPI SendMessageW_NEW( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if ( hWnd && LOWORD(hWnd)!=0xFFFF ) //broadcasts won't work
|
|
{
|
|
/* If window is in the same thread, sent message directly
|
|
* BUGBUG: take global message filter (Spy++) into account somehow
|
|
*/
|
|
WNDPROC procW = NULL;
|
|
GrabWin16Lock();
|
|
PWND pwnd = HWNDtoPWND(hWnd);
|
|
if ( pwnd )
|
|
{
|
|
PMSGQUEUE msgq = _GetWindowQueue(pwnd);
|
|
PMSGQUEUE ourmsgq = GetCurrentThreadQueue();
|
|
if ( ourmsgq == msgq && !msgq->block1 && !msgq->block2 ) //hooray! we're in the same queue and can be 32-bit!
|
|
procW = ConvertWndProcAToW( _GetWindowProc32(pwnd) );
|
|
}
|
|
ReleaseWin16Lock();
|
|
if ( procW )
|
|
{
|
|
//DBGPRINTF(("SendMessageW [DIRECT]: %p, %p, %p, %p\n",hWnd, Msg, wParam, lParam));
|
|
return CallWindowProc_stdcall( procW, hWnd, Msg, wParam, lParam );
|
|
}
|
|
}
|
|
//DBGPRINTF(("SendMessageW [THUNK]: %p, %p, %p, %p\n",hWnd, Msg, wParam, lParam));
|
|
return CallProcAnsiWithUnicode( (WNDPROC)SendMessageA_fix, hWnd, Msg, wParam, lParam );
|
|
}
|
|
|
|
/* MAKE_EXPORT DefWindowProcW_NEW=DefWindowProcW */
|
|
LRESULT WINAPI DefWindowProcW_NEW( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
return CallProcAnsiWithUnicode( DefWindowProcA, hWnd, Msg, wParam, lParam );
|
|
}
|
|
|
|
/* MAKE_EXPORT SetWindowTextW_NEW=SetWindowTextW */
|
|
BOOL WINAPI SetWindowTextW_NEW( HWND hWnd, LPCWSTR lpString)
|
|
{
|
|
if ( !hWnd || !lpString ) return FALSE;
|
|
if ( ISOURPROCESSHWND(hWnd) )
|
|
return SendMessageW_NEW( hWnd, WM_SETTEXT, 0, (LPARAM)lpString );
|
|
else
|
|
return DefWindowProcW_NEW( hWnd, WM_SETTEXT, 0, (LPARAM)lpString );
|
|
|
|
}
|
|
|
|
/* MAKE_EXPORT SetDlgItemTextW_NEW=SetDlgItemTextW */
|
|
BOOL WINAPI SetDlgItemTextW_NEW( HWND hDlg, int nIDDlgItem, LPCWSTR lpString )
|
|
{
|
|
return SetWindowTextW_NEW( GetDlgItem(hDlg, nIDDlgItem), lpString );
|
|
}
|
|
|
|
/* MAKE_EXPORT SendDlgItemMessageW_NEW=SendDlgItemMessageW */
|
|
LRESULT WINAPI SendDlgItemMessageW_NEW( HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HWND hCtl = GetDlgItem(hDlg, nIDDlgItem);
|
|
if ( hCtl )
|
|
return SendMessageW_NEW( hCtl, Msg, wParam, lParam );
|
|
return 0L;
|
|
}
|
|
|
|
/* MAKE_EXPORT GetWindowTextW_NEW=GetWindowTextW */
|
|
int WINAPI GetWindowTextW_NEW( HWND hWnd, LPWSTR lpString, int nMaxCount)
|
|
{
|
|
if ( !lpString || nMaxCount<=0 ) return 0; //NT does not set error here
|
|
if ( !IsWindow(hWnd) )
|
|
{
|
|
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
|
|
return 0;
|
|
}
|
|
if ( ISOURPROCESSHWND(hWnd) )
|
|
return SendMessageW_NEW( hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
|
|
else
|
|
return DefWindowProcW_NEW( hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
|
|
}
|
|
|
|
/* MAKE_EXPORT GetDlgItemTextW_NEW=GetDlgItemTextW */
|
|
int WINAPI GetDlgItemTextW_NEW( HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
|
|
{
|
|
hDlg = GetDlgItem(hDlg, nIDDlgItem);
|
|
if (hDlg)
|
|
return GetWindowTextW_NEW( hDlg , lpString, nMaxCount );
|
|
//NULL in fail case
|
|
*lpString = WCHAR(0);
|
|
return 0;
|
|
}
|
|
|
|
/* MAKE_EXPORT GetWindowTextLengthW_NEW=GetWindowTextLengthW */
|
|
int WINAPI GetWindowTextLengthW_NEW( HWND hWnd )
|
|
{
|
|
return GetWindowTextLengthA(hWnd); //BUGBUG looks like i care about DBCS?
|
|
}
|
|
|
|
/* MAKE_EXPORT UnregisterClassW_NEW=UnregisterClassW */
|
|
BOOL WINAPI UnregisterClassW_NEW( LPCWSTR lpClassName, HINSTANCE hInstance)
|
|
{
|
|
LPCSTR lpClassNameA;
|
|
STACK_WtoA(lpClassName, lpClassNameA);
|
|
return UnregisterClassA( lpClassNameA, hInstance );
|
|
}
|
|
|
|
/* Those functions were born ugly */
|
|
|
|
/* MAKE_EXPORT SendMessageCallbackW_NEW=SendMessageCallbackW */
|
|
BOOL WINAPI SendMessageCallbackW_NEW( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, SENDASYNCPROC lpCallBack, DWORD dwData)
|
|
{
|
|
//TODO: add WM_CHAR and alike conversion?
|
|
return SendMessageCallbackA( hWnd, Msg, wParam, lParam, lpCallBack, dwData);
|
|
}
|
|
|
|
LRESULT WINAPI SendMessageTimeoutW_Helper( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PSMTIMEOUT_THUNK psm = (PSMTIMEOUT_THUNK)GetMessageExtraInfo();
|
|
return SendMessageTimeoutA(hWnd,Msg,wParam,lParam,psm->fuFlags,psm->uTimeout,psm->lpdwResult);
|
|
}
|
|
|
|
/* MAKE_EXPORT SendMessageTimeoutW_NEW=SendMessageTimeoutW */
|
|
LRESULT WINAPI SendMessageTimeoutW_NEW( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, LPDWORD lpdwResult)
|
|
{
|
|
LONG saveExtraInfo = GetMessageExtraInfo();
|
|
SMTIMEOUT_THUNK smt;
|
|
smt.fuFlags = fuFlags;
|
|
smt.lpdwResult = lpdwResult;
|
|
smt.uTimeout = uTimeout;
|
|
SetMessageExtraInfo((LONG)&smt);
|
|
LRESULT ret = CallProcAnsiWithUnicode(SendMessageTimeoutW_Helper,hWnd,Msg,wParam,lParam);
|
|
SetMessageExtraInfo(saveExtraInfo);
|
|
return ret;
|
|
}
|
|
|