|
|
/**************************************************************************\
* Module Name: client.c * * Client/Server call related routines. * * Copyright (c) 1985 - 1999, Microsoft Corporation * * History: * 04-Dec-1990 SMeans Created. \**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "kbd.h"
#include "ntsend.h"
#include "vdm.h"
/*
* NOTE -- this table must match the FNID list in user.h. It provides a WOWCLASS for each FNID. */
int aiClassWow[] = { WOWCLASS_SCROLLBAR, WOWCLASS_ICONTITLE, WOWCLASS_MENU, WOWCLASS_DESKTOP, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_SWITCHWND, WOWCLASS_BUTTON, WOWCLASS_COMBOBOX, WOWCLASS_COMBOLBOX, WOWCLASS_DIALOG, WOWCLASS_EDIT, WOWCLASS_LISTBOX, WOWCLASS_MDICLIENT, WOWCLASS_STATIC, WOWCLASS_WIN16, // 2A9
WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, // 2B1
WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16, WOWCLASS_WIN16 };
HBITMAP WOWLoadBitmapA(HINSTANCE hmod, LPCSTR lpName, LPBYTE pResData, DWORD cbResData); HMENU WowServerLoadCreateMenu(HANDLE hMod, LPTSTR lpName, CONST LPMENUTEMPLATE pmt, DWORD cb, BOOL fCallClient); DWORD GetFullUserHandle(WORD wHandle);
UINT GetClipboardCodePage(LCID, LCTYPE);
extern HANDLE WOWFindResourceExWCover(HANDLE hmod, LPCWSTR rt, LPCWSTR lpUniName, WORD LangId);
extern BOOL APIENTRY EnableEUDC();
CONST WCHAR szKLKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Keyboard Layouts\\"; CONST WCHAR szKLFile[] = L"Layout File"; CONST WCHAR szKLAttributes[] = L"Attributes"; CONST WCHAR szKLId[] = L"Layout ID"; #define NSZKLKEY (sizeof szKLKey + 16)
CONST LPWSTR pwszKLLibSafety = L"kbdus.dll"; CONST UINT wKbdLocaleSafety = 0x04090409; CONST LPWSTR pwszKLLibSafetyJPN = L"kbdjpn.dll"; CONST UINT wKbdLocaleSafetyJPN = 0x04110411; CONST LPWSTR pwszKLLibSafetyKOR = L"kbdkor.dll"; CONST UINT wKbdLocaleSafetyKOR = 0x04120412;
#define CCH_KL_LIBNAME 256
#define CCH_KL_ID 16
UNICODE_STRING strRootDirectory;
VOID CheckValidLayoutName(LPWSTR lpszName);
BOOL WOWModuleUnload(HANDLE hModule) { return (BOOL)NtUserCallOneParam((ULONG_PTR)hModule, SFI__WOWMODULEUNLOAD); }
BOOL WOWCleanup(HANDLE hInstance, DWORD hTaskWow) { return (BOOL)NtUserCallTwoParam((ULONG_PTR)hInstance, (ULONG_PTR)hTaskWow, SFI__WOWCLEANUP); } /***************************************************************************\
* BringWindowToTop (API) * * * History: * 11-Jul-1991 DarrinM Ported from Win 3.1 sources. \***************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, BringWindowToTop, HWND, hwnd) BOOL BringWindowToTop( HWND hwnd) { return NtUserSetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); }
FUNCLOG2(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, ChildWindowFromPoint, HWND, hwndParent, POINT, point) HWND ChildWindowFromPoint( HWND hwndParent, POINT point) { /*
* Cool Hack Alert... Corel Ventura 5.0 * Dies after it calls ChildWindowFromPoint, and * the combobox doesn't have its edit window at 1,1... */ if ((point.x == 1) && (point.y == 1)) { PCBOX pcCombo; PWND pwnd;
pwnd = ValidateHwnd(hwndParent); if (pwnd == NULL) return NULL;
if (!TestWF(pwnd, WFWIN40COMPAT) && GETFNID(pwnd) == FNID_COMBOBOX && TestWindowProcess(pwnd) && ((pcCombo = ((PCOMBOWND)pwnd)->pcbox) != NULL) && !(pcCombo->fNoEdit)) {
RIPMSG0(RIP_WARNING, "ChildWindowFromPoint: Combobox @1,1. Returning spwndEdit"); return HWq(pcCombo->spwndEdit); }
}
return NtUserChildWindowFromPointEx(hwndParent, point, 0); }
FUNCLOG1(LOG_GENERAL, HICON, DUMMYCALLINGTYPE, CopyIcon, HICON, hicon) HICON CopyIcon( HICON hicon) { HICON hIconT = NULL; ICONINFO ii;
if (GetIconInfo(hicon, &ii)) { hIconT = CreateIconIndirect(&ii);
DeleteObject(ii.hbmMask);
if (ii.hbmColor != NULL) DeleteObject(ii.hbmColor); }
return hIconT; }
/***************************************************************************\
* AdjustWindowRect (API) * * History: * 01-Jul-1991 MikeKe Created. \***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, WINAPI, AdjustWindowRect, LPRECT, lprc, DWORD, style, BOOL, fMenu) BOOL WINAPI AdjustWindowRect( LPRECT lprc, DWORD style, BOOL fMenu) { ConnectIfNecessary(0);
return _AdjustWindowRectEx(lprc, style, fMenu, 0L); }
/***************************************************************************\
* TranslateAcceleratorA/W * * Put here so we can check for NULL on client side, and before validation * for both DOS and NT cases. * * 05-29-91 ScottLu Created. * 01-05-93 IanJa Unicode/ANSI. \***************************************************************************/
FUNCLOG3(LOG_GENERAL, int, WINAPI, TranslateAcceleratorW, HWND, hwnd, HACCEL, hAccel, LPMSG, lpMsg) int WINAPI TranslateAcceleratorW( HWND hwnd, HACCEL hAccel, LPMSG lpMsg) { /*
* NULL pwnd is a valid case - since this is called from the center * of main loops, pwnd == NULL happens all the time, and we shouldn't * generate a warning because of it. */ if (hwnd == NULL) return FALSE;
/*
* We only need to pass key-down messages to the server, * everything else ends up returning 0/FALSE from this function. */ switch (lpMsg->message) {
case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_CHAR: case WM_SYSCHAR: return NtUserTranslateAccelerator(hwnd, hAccel, lpMsg);
default: return 0; } }
FUNCLOG3(LOG_GENERAL, int, WINAPI, TranslateAcceleratorA, HWND, hwnd, HACCEL, hAccel, LPMSG, lpMsg) int WINAPI TranslateAcceleratorA( HWND hwnd, HACCEL hAccel, LPMSG lpMsg) { WPARAM wParamT; int iT;
/*
* NULL pwnd is a valid case - since this is called from the center * of main loops, pwnd == NULL happens all the time, and we shouldn't * generate a warning because of it. */ if (hwnd == NULL) return FALSE;
/*
* We only need to pass key-down messages to the server, * everything else ends up returning 0/FALSE from this function. */ switch (lpMsg->message) {
case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_CHAR: case WM_SYSCHAR: wParamT = lpMsg->wParam; RtlMBMessageWParamCharToWCS(lpMsg->message, &(lpMsg->wParam)); iT = NtUserTranslateAccelerator(hwnd, hAccel, lpMsg); lpMsg->wParam = wParamT; return iT;
default: return 0; } }
/***************************************************************************\
* Clipboard functions * * 11-Oct-1991 mikeke Created. \***************************************************************************/
typedef struct _HANDLENODE { struct _HANDLENODE *pnext; UINT fmt; HANDLE handleServer; HANDLE handleClient; BOOL fGlobalHandle; } HANDLENODE; typedef HANDLENODE *PHANDLENODE;
PHANDLENODE gphn = NULL;
/***************************************************************************\
* DeleteClientClipboardHandle * * 11-Oct-1991 MikeKe Created. \***************************************************************************/
BOOL DeleteClientClipboardHandle( PHANDLENODE phn) { LPMETAFILEPICT lpMFP;
UserAssert(phn->handleClient != (HANDLE)0);
switch (phn->fmt) { case CF_BITMAP: case CF_DSPBITMAP: case CF_PALETTE: // Does nothing (should remove).
//
//GdiDeleteLocalObject((ULONG)hobjDelete);
break;
case CF_METAFILEPICT: case CF_DSPMETAFILEPICT: USERGLOBALLOCK(phn->handleClient, lpMFP); if (lpMFP) { DeleteMetaFile(lpMFP->hMF); USERGLOBALUNLOCK(phn->handleClient); UserGlobalFree(phn->handleClient); } else { RIPMSGF1(RIP_ERROR, "Can't lock client handle 0x%p", phn->handleClient); return FALSE; } break;
case CF_ENHMETAFILE: case CF_DSPENHMETAFILE: DeleteEnhMetaFile((HENHMETAFILE)phn->handleClient); break;
default: //case CF_TEXT:
//case CF_OEMTEXT:
//case CF_UNICODETEXT:
//case CF_LOCALE:
//case CF_DSPTEXT:
//case CF_DIB:
//case CF_DIBV5:
if (phn->fGlobalHandle) { if (UserGlobalFree(phn->handleClient)) { RIPMSGF1(RIP_WARNING, "UserGlobalFree(0x%p) failed", phn->handleClient); return FALSE; } } else { UserAssert(GlobalFlags(phn->handleClient) == GMEM_INVALID_HANDLE); } break; }
/*
* Deleted successfully */ return TRUE;
}
/***************************************************************************\
* ClientEmptyClipboard * * Empties the client side clipboard list. * * 01-15-93 ScottLu Created. \***************************************************************************/
void ClientEmptyClipboard(void) { PHANDLENODE phnNext; PHANDLENODE phnT;
RtlEnterCriticalSection(&gcsClipboard);
phnT = gphn; while (phnT != NULL) { phnNext = phnT->pnext;
if (phnT->handleClient != (HANDLE)0) { DeleteClientClipboardHandle(phnT); }
UserLocalFree(phnT);
phnT = phnNext; } gphn = NULL;
/*
* Tell wow to cleanup it's clipboard stuff */ if (pfnWowEmptyClipBoard) { pfnWowEmptyClipBoard(); }
RtlLeaveCriticalSection(&gcsClipboard); }
/***************************************************************************\
* GetClipboardData * * 11-Oct-1991 mikeke Created. \***************************************************************************/
FUNCLOG1(LOG_GENERAL, HANDLE, WINAPI, GetClipboardData, UINT, uFmt) HANDLE WINAPI GetClipboardData( UINT uFmt) { HANDLE handleClient; HANDLE handleServer; PHANDLENODE phn; PHANDLENODE phnNew; GETCLIPBDATA gcd;
/*
* Get the Server's Data; return if there is no data. */ if (!(handleServer = NtUserGetClipboardData(uFmt, &gcd))) return (HANDLE)NULL;
/*
* Handle any translation that must be done for text items. The * format returned will only differ for text items. Metafile and * Enhanced-Metafiles are handled through GDI for their converstions. * And Bitmap color space convertion also nessesary for CF_BITMAP, * CF_DIB and CF_DIBV5 with color space. */ if (uFmt != gcd.uFmtRet) {
LPBYTE lpSrceData = NULL; LPBYTE lpDestData = NULL; LPBYTE lptData = NULL; LPDWORD lpLocale; DWORD uLocale; int iSrce; int iDest; UINT uCPage; SETCLIPBDATA scd; UINT cbNULL = 0;
/*
* Make sure handleServer is server-side memory handle */ if ((gcd.uFmtRet == CF_TEXT) || (gcd.uFmtRet == CF_OEMTEXT) || (gcd.uFmtRet == CF_UNICODETEXT) || (gcd.uFmtRet == CF_DIB) || (gcd.uFmtRet == CF_DIBV5)) {
if ((lpSrceData = CreateLocalMemHandle(handleServer)) == NULL) { goto AbortDummyHandle; }
/*
* Allocate space for the converted TEXT data. */ if (!(iSrce = (UINT)GlobalSize(lpSrceData))) { goto AbortDummyHandle; }
/*
* Only CF_xxxTEXT may have locale information. */ if ((gcd.uFmtRet == CF_TEXT) || (gcd.uFmtRet == CF_OEMTEXT) || (gcd.uFmtRet == CF_UNICODETEXT)) {
/*
* Get the locale out of the parameter-struct. We will * use this to get the codepage for text-translation. */ if (lpLocale = (LPDWORD)CreateLocalMemHandle(gcd.hLocale)) {
uLocale = *lpLocale; GlobalFree(lpLocale); } else { uLocale = 0; }
/*
* And also, pre-allocate translated buffer in same size as source. */ if ((lpDestData = GlobalAlloc(LPTR, iSrce)) == NULL) { goto AbortDummyHandle; } }
switch (uFmt) { case CF_TEXT: cbNULL = 1; if (gcd.uFmtRet == CF_OEMTEXT) {
/*
* CF_OEMTEXT --> CF_TEXT conversion */ OemToAnsi((LPSTR)lpSrceData, (LPSTR)lpDestData); } else {
uCPage = GetClipboardCodePage(uLocale, LOCALE_IDEFAULTANSICODEPAGE);
/*
* CF_UNICODETEXT --> CF_TEXT conversion */ iDest = 0; if ((iDest = WideCharToMultiByte(uCPage, (DWORD)0, (LPWSTR)lpSrceData, (int)(iSrce / sizeof(WCHAR)), (LPSTR)NULL, (int)iDest, (LPSTR)NULL, (LPBOOL)NULL)) == 0) { AbortGetClipData: UserGlobalFree(lpDestData); AbortDummyHandle: if (lpSrceData) { UserGlobalFree(lpSrceData); } return NULL; }
if (!(lptData = GlobalReAlloc(lpDestData, iDest, LPTR | LMEM_MOVEABLE))) goto AbortGetClipData;
lpDestData = lptData;
if (WideCharToMultiByte(uCPage, (DWORD)0, (LPWSTR)lpSrceData, (int)(iSrce / sizeof(WCHAR)), (LPSTR)lpDestData, (int)iDest, (LPSTR)NULL, (LPBOOL)NULL) == 0) goto AbortGetClipData; } break;
case CF_OEMTEXT: cbNULL = 1; if (gcd.uFmtRet == CF_TEXT) {
/*
* CF_TEXT --> CF_OEMTEXT conversion */ AnsiToOem((LPSTR)lpSrceData, (LPSTR)lpDestData); } else {
uCPage = GetClipboardCodePage(uLocale, LOCALE_IDEFAULTCODEPAGE);
/*
* CF_UNICODETEXT --> CF_OEMTEXT conversion */ iDest = 0; if ((iDest = WideCharToMultiByte(uCPage, (DWORD)0, (LPWSTR)lpSrceData, (int)(iSrce / sizeof(WCHAR)), (LPSTR)NULL, (int)iDest, (LPSTR)NULL, (LPBOOL)NULL)) == 0) goto AbortGetClipData;
if (!(lptData = GlobalReAlloc(lpDestData, iDest, LPTR | LMEM_MOVEABLE))) goto AbortGetClipData;
lpDestData = lptData;
if (WideCharToMultiByte(uCPage, (DWORD)0, (LPWSTR)lpSrceData, (int)(iSrce / sizeof(WCHAR)), (LPSTR)lpDestData, (int)iDest, (LPSTR)NULL, (LPBOOL)NULL) == 0) goto AbortGetClipData; } break;
case CF_UNICODETEXT: cbNULL = 2; if (gcd.uFmtRet == CF_TEXT) {
uCPage = GetClipboardCodePage(uLocale, LOCALE_IDEFAULTANSICODEPAGE);
/*
* CF_TEXT --> CF_UNICODETEXT conversion */ iDest = 0; if ((iDest = MultiByteToWideChar(uCPage, (DWORD)MB_PRECOMPOSED, (LPSTR)lpSrceData, (int)iSrce, (LPWSTR)NULL, (int)iDest)) == 0) goto AbortGetClipData;
if (!(lptData = GlobalReAlloc(lpDestData, iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE))) goto AbortGetClipData;
lpDestData = lptData;
if (MultiByteToWideChar(uCPage, (DWORD)MB_PRECOMPOSED, (LPSTR)lpSrceData, (int)iSrce, (LPWSTR)lpDestData, (int)iDest) == 0) goto AbortGetClipData;
} else {
uCPage = GetClipboardCodePage(uLocale, LOCALE_IDEFAULTCODEPAGE);
/*
* CF_OEMTEXT --> CF_UNICDOETEXT conversion */ iDest = 0; if ((iDest = MultiByteToWideChar(uCPage, (DWORD)MB_PRECOMPOSED, (LPSTR)lpSrceData, (int)iSrce, (LPWSTR)NULL, (int)iDest)) == 0) goto AbortGetClipData;
if (!(lptData = GlobalReAlloc(lpDestData, iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE))) goto AbortGetClipData;
lpDestData = lptData;
if (MultiByteToWideChar(uCPage, (DWORD)MB_PRECOMPOSED, (LPSTR)lpSrceData, (int)iSrce, (LPWSTR)lpDestData, (int)iDest) == 0) goto AbortGetClipData; } break;
case CF_BITMAP: if (gcd.uFmtRet == CF_DIBV5) {
/*
* CF_DIBV5 --> CF_BITMAP (sRGB) * * The GDI bitmap handle will be returned in handleServer. */ if ((handleServer = GdiConvertBitmapV5(lpSrceData,iSrce, gcd.hPalette,CF_BITMAP)) == NULL) {
/*
* GDI failed to convert. */ RIPMSG0(RIP_ERROR, "GetClipboardData: Failed CF_DIBV5 -> CF_BITMAP"); goto AbortDummyHandle; } } else { RIPMSG0(RIP_ERROR, "GetClipboardData: bad conversion request"); goto AbortDummyHandle; } break;
case CF_DIB: if (gcd.uFmtRet == CF_DIBV5) {
/*
* CF_DIBV5 --> CF_DIB (sRGB) * * The local memory handle will be returned in lpDestData. */ if ((lpDestData = (LPBYTE) GdiConvertBitmapV5(lpSrceData,iSrce, gcd.hPalette,CF_DIB)) == NULL) {
/*
* GDI failed to convert. */ RIPMSG0(RIP_ERROR, "GetClipboardData: Failed CF_DIBV5 -> CF_DIB"); goto AbortDummyHandle; } } else {
RIPMSG0(RIP_ERROR, "GetClipboardData: bad conversion request"); goto AbortDummyHandle; } break; } }
if (lpDestData) { /*
* Replace the dummy user-mode memory handle with the actual handle. */ handleServer = ConvertMemHandle(lpDestData, cbNULL); if (handleServer == NULL) goto AbortGetClipData; }
/*
* Update the server. If that is successfull update the client */ RtlEnterCriticalSection(&gcsClipboard); scd.fGlobalHandle = gcd.fGlobalHandle; scd.fIncSerialNumber = FALSE; if (!NtUserSetClipboardData(uFmt, handleServer, &scd)) { handleServer = NULL; } RtlLeaveCriticalSection(&gcsClipboard);
if (lpDestData) UserGlobalFree(lpDestData); if (lpSrceData) UserGlobalFree(lpSrceData);
if (handleServer == NULL) return NULL; }
/*
* See if we already have a client side handle; validate the format * as well because some server objects, metafile for example, are dual mode * and yield two kinds of client objects enhanced and regular metafiles */ handleClient = NULL; RtlEnterCriticalSection(&gcsClipboard);
phn = gphn; while (phn) { if ((phn->handleServer == handleServer) && (phn->fmt == uFmt)) { handleClient = phn->handleClient; goto Exit; } phn = phn->pnext; }
/*
* We don't have a handle cached so we'll create one. */ phnNew = (PHANDLENODE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(HANDLENODE)); if (phnNew == NULL) { goto Exit; }
phnNew->handleServer = handleServer; phnNew->fmt = gcd.uFmtRet; phnNew->fGlobalHandle = gcd.fGlobalHandle;
switch (uFmt) {
/*
* Misc GDI Handles */ case CF_BITMAP: case CF_DSPBITMAP: case CF_PALETTE: phnNew->handleClient = handleServer; break;
case CF_METAFILEPICT: case CF_DSPMETAFILEPICT: phnNew->handleClient = GdiCreateLocalMetaFilePict(handleServer); break;
case CF_ENHMETAFILE: case CF_DSPENHMETAFILE: phnNew->handleClient = GdiCreateLocalEnhMetaFile(handleServer); break;
/*
* GlobalHandle Cases */ case CF_TEXT: case CF_OEMTEXT: case CF_UNICODETEXT: case CF_LOCALE: case CF_DSPTEXT: case CF_DIB: case CF_DIBV5: phnNew->handleClient = CreateLocalMemHandle(handleServer); phnNew->fGlobalHandle = TRUE; break;
default: /*
* Private Data Format; If this is global data, create a copy of that * data here on the client. If it isn't global data, it is just a dword * in which case we just return a dword. If it is global data and * the server fails to give us that memory, return NULL. If it isn't * global data, handleClient is just a dword. */ if (phnNew->fGlobalHandle) { phnNew->handleClient = CreateLocalMemHandle(handleServer); } else { phnNew->handleClient = handleServer; } break; }
if (phnNew->handleClient == NULL) { /*
* Something bad happened; GDI didn't give us back a handle. Since * GDI has logged the error, we'll just clean up and return an error. */ RIPMSGF1(RIP_WARNING, "Unable to convert server handle 0x%p to client handle", handleServer);
UserLocalFree(phnNew); goto Exit; }
#if DBG
/*
* If handleClient came from a GlobalAlloc, then fGlobalHandle must be TRUE. * Some formats are acutally global handles but require special cleanup. */ switch (phnNew->fmt) { case CF_METAFILEPICT: case CF_DSPMETAFILEPICT: break;
default: UserAssert(phnNew->fGlobalHandle ^ (GlobalFlags(phnNew->handleClient) == GMEM_INVALID_HANDLE)); break; } #endif
/*
* Cache the new handle by linking it into our list */ phnNew->pnext = gphn; gphn = phnNew; handleClient = phnNew->handleClient;
Exit: RtlLeaveCriticalSection(&gcsClipboard); return handleClient; }
/***************************************************************************\
* GetClipboardCodePage (internal) * * This routine returns the code-page associated with the given locale. * * 24-Aug-1995 ChrisWil Created. \***************************************************************************/
#define GETCCP_SIZE 8
UINT GetClipboardCodePage( LCID uLocale, LCTYPE uLocaleType) { WCHAR wszCodePage[GETCCP_SIZE]; DWORD uCPage;
if (GetLocaleInfoW(uLocale, uLocaleType, wszCodePage, GETCCP_SIZE)) {
uCPage = (UINT)wcstol(wszCodePage, NULL, 10);
} else {
switch(uLocaleType) {
case LOCALE_IDEFAULTCODEPAGE: uCPage = CP_OEMCP; break;
case LOCALE_IDEFAULTANSICODEPAGE: uCPage = CP_ACP; break;
default: uCPage = CP_MACCP; break; } }
return uCPage; }
/***************************************************************************\
* SetClipboardData * * Stub routine needs to exist on the client side so any global data gets * allocated DDESHARE. * * 05-20-91 ScottLu Created. \***************************************************************************/
FUNCLOG2(LOG_GENERAL, HANDLE, WINAPI, SetClipboardData, UINT, wFmt, HANDLE, hMem) HANDLE WINAPI SetClipboardData( UINT wFmt, HANDLE hMem) { PHANDLENODE phnNew; HANDLE hServer = NULL; SETCLIPBDATA scd; BOOL fGlobalHandle = FALSE;
if (hMem != NULL) {
switch(wFmt) {
case CF_BITMAP: case CF_DSPBITMAP: case CF_PALETTE: hServer = hMem; break;
case CF_METAFILEPICT: case CF_DSPMETAFILEPICT: hServer = GdiConvertMetaFilePict(hMem); break;
case CF_ENHMETAFILE: case CF_DSPENHMETAFILE: hServer = GdiConvertEnhMetaFile(hMem); break;
/*
* Must have a valid hMem (GlobalHandle) */ case CF_TEXT: case CF_OEMTEXT: case CF_LOCALE: case CF_DSPTEXT: hServer = ConvertMemHandle(hMem, 1); fGlobalHandle = TRUE; break;
case CF_UNICODETEXT: hServer = ConvertMemHandle(hMem, 2); fGlobalHandle = TRUE; break;
case CF_DIB: case CF_DIBV5: hServer = ConvertMemHandle(hMem, 0); fGlobalHandle = TRUE; break;
/*
* hMem should have been NULL but Write sends non-null when told * to render */ case CF_OWNERDISPLAY: // Fall Through;
/*
* May have an hMem (GlobalHandle) or may be private handle\info */ default: if (GlobalFlags(hMem) == GMEM_INVALID_HANDLE) { hServer = hMem; // No server equivalent; private data
goto SCD_AFTERNULLCHECK; } else { fGlobalHandle = TRUE; hServer = ConvertMemHandle(hMem, 0); } break; }
if (hServer == NULL) { /*
* Something bad happened, gdi didn't give us back a handle. * Since gdi has logged the error, we'll just clean up and * return an error. */ RIPMSG0(RIP_WARNING, "SetClipboardData: bad handle"); return NULL; } }
SCD_AFTERNULLCHECK:
RtlEnterCriticalSection(&gcsClipboard);
/*
* Update the server if that is successfull update the client */ scd.fGlobalHandle = fGlobalHandle; scd.fIncSerialNumber = TRUE;
if (!NtUserSetClipboardData(wFmt, hServer, &scd)) { RtlLeaveCriticalSection(&gcsClipboard); return NULL; }
/*
* See if we already have a client handle of this type. If so * delete it. */ phnNew = gphn; while (phnNew) { if (phnNew->fmt == wFmt) { if (phnNew->handleClient != NULL) { DeleteClientClipboardHandle(phnNew); /*
* Notify WOW to clear its associated cached h16 for this format * so that OLE32 thunked calls, which bypass the WOW cache will work. */ if (pfnWowCBStoreHandle) { pfnWowCBStoreHandle((WORD)wFmt, 0); } } break; }
phnNew = phnNew->pnext; }
/*
* If we aren't re-using an old client cache entry alloc a new one */ if (!phnNew) { phnNew = (PHANDLENODE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(HANDLENODE));
if (phnNew == NULL) { RIPMSG0(RIP_WARNING, "SetClipboardData: not enough memory");
RtlLeaveCriticalSection(&gcsClipboard); return NULL; }
/*
* Link in the newly allocated cache entry */ phnNew->pnext = gphn; gphn = phnNew; }
phnNew->handleServer = hServer; phnNew->handleClient = hMem; phnNew->fmt = wFmt; phnNew->fGlobalHandle = fGlobalHandle;
RtlLeaveCriticalSection(&gcsClipboard);
return hMem; }
/**************************************************************************\
* SetDeskWallpaper * * 22-Jul-1991 mikeke Created * 01-Mar-1992 GregoryW Modified to call SystemParametersInfo. \**************************************************************************/
BOOL SetDeskWallpaper( IN LPCSTR pString OPTIONAL) { return SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, (PVOID)pString, TRUE); }
/***************************************************************************\
* ReleaseDC (API) * * A complete Thank cannot be generated for ReleaseDC because its first * parameter (hwnd) unnecessary and should be discarded before calling the * server-side routine _ReleaseDC. * * History: * 03-28-91 SMeans Created. * 06-17-91 ChuckWh Added support for local DCs. \***************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, ReleaseDC, HWND, hwnd, HDC, hdc) BOOL WINAPI ReleaseDC( HWND hwnd, HDC hdc) {
/*
* NOTE: This is a smart stub that calls _ReleaseDC so there is * no need for a separate ReleaseDC layer or client-server stub. * _ReleaseDC has simpler layer and client-server stubs since the * hwnd can be ignored. */
UNREFERENCED_PARAMETER(hwnd);
/*
* Translate the handle. */ if (hdc == NULL) return FALSE;
/*
* call GDI to release user mode DC resources */
GdiReleaseDC(hdc);
return (BOOL)NtUserCallOneParam((ULONG_PTR)hdc, SFI__RELEASEDC); }
int WINAPI ToAscii( UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT wFlags ) { WCHAR UnicodeChar[2]; int cch, retval;
retval = ToUnicode(wVirtKey, wScanCode, lpKeyState, UnicodeChar,2, wFlags); cch = (retval < 0) ? -retval : retval; if (cch != 0) { if (!NT_SUCCESS(RtlUnicodeToMultiByteN( (LPSTR)lpChar, (ULONG) sizeof(*lpChar), (PULONG)&cch, UnicodeChar, cch * sizeof(WCHAR)))) { return 0; } } return (retval < 0) ? -cch : cch; }
static UINT uCachedCP = 0; static HKL hCachedHKL = 0;
int WINAPI ToAsciiEx( UINT wVirtKey, UINT wScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT wFlags, HKL hkl ) { WCHAR UnicodeChar[2]; int cch, retval; BOOL fUsedDefaultChar;
retval = ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, UnicodeChar,2, wFlags, hkl); cch = (retval < 0) ? -retval : retval; if (cch != 0) { if (hkl != hCachedHKL) { DWORD dwCodePage; if (!GetLocaleInfoW( HandleToUlong(hkl) & 0xffff, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (LPWSTR)&dwCodePage, sizeof(dwCodePage) / sizeof(WCHAR) )) { return 0; } uCachedCP = dwCodePage; hCachedHKL = hkl; } if (!WideCharToMultiByte( uCachedCP, 0, UnicodeChar, cch, (LPSTR)lpChar, sizeof(*lpChar), NULL, &fUsedDefaultChar)) { return 0; } } return (retval < 0) ? -cch : cch; }
/**************************************************************************\
* ScrollDC * * DrawIcon * * ExcludeUpdateRgn * * ValidateRgn * * DrawFocusRect * * FrameRect * * ReleaseDC * * GetUpdateRgn * * * * These USER entry points all need handles translated before the call is * * passed to the server side handler. * * * * History: * * Mon 17-Jun-1991 22:51:45 -by- Charles Whitmer [chuckwh] * * Wrote the stubs. The final form of these routines depends strongly on * * what direction the user stubs take in general. * \**************************************************************************/
BOOL WINAPI ScrollDC( HDC hDC, int dx, int dy, CONST RECT *lprcScroll, CONST RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate) { if (hDC == NULL) return FALSE;
/*
* If we're not scrolling, just empty the update region and return. */ if (dx == 0 && dy == 0) { if (hrgnUpdate) SetRectRgn(hrgnUpdate, 0, 0, 0, 0); if (lprcUpdate) SetRectEmpty(lprcUpdate); return TRUE; }
return NtUserScrollDC(hDC, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate); }
FUNCLOG4(LOG_GENERAL, BOOL, WINAPI, DrawIcon, HDC, hdc, int, x, int, y, HICON, hicon) BOOL WINAPI DrawIcon(HDC hdc,int x,int y,HICON hicon) { return DrawIconEx(hdc, x, y, hicon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE ); }
FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawIconEx, HDC, hdc, int, x, int, y, HICON, hIcon, int, cx, int, cy, UINT, istepIfAniCur, HBRUSH, hbrFlickerFreeDraw, UINT, diFlags) BOOL DrawIconEx( HDC hdc, int x, int y, HICON hIcon, int cx, int cy, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { DRAWICONEXDATA did; HBITMAP hbmT; BOOL retval = FALSE; HDC hdcr; BOOL fAlpha = FALSE; LONG rop = (diFlags & DI_NOMIRROR) ? NOMIRRORBITMAP : 0;
if (diFlags & ~DI_VALID) { RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); return(FALSE); }
if (diFlags & DI_DEFAULTSIZE) { cx = 0; cy = 0; }
if (!IsMetaFile(hdc)) { hdcr = GdiConvertAndCheckDC(hdc); if (hdcr == (HDC)0) return FALSE;
return NtUserDrawIconEx(hdcr, x, y, hIcon, cx, cy, istepIfAniCur, hbrFlickerFreeDraw, diFlags, FALSE, &did); }
if (!NtUserDrawIconEx(NULL, 0, 0, hIcon, cx, cy, 0, NULL, 0, TRUE, &did)) { return FALSE; }
if ((diFlags & ~DI_NOMIRROR) == 0) return TRUE;
RtlEnterCriticalSection(&gcsHdc);
/*
* We really want to draw an alpha icon if we can. But we need to * respect the user's request to draw only the image or only the * mask. We decide if we are, or are not, going to draw the icon * with alpha information here. */ if (did.hbmUserAlpha != NULL && ((diFlags & DI_NORMAL) == DI_NORMAL)) { fAlpha = TRUE; }
RIPMSG5(RIP_WARNING, "Drawing to metafile! fAlpha=%d, did.cx=%d, did.cy=%d, cx=%d, cy=%d", fAlpha, did.cx, did.cy, cx, cy); /*
* Setup the attributes */ if (!cx) cx = did.cx; if (!cy) cy = did.cy / 2;
SetTextColor(hdc, 0x00000000L); SetBkColor(hdc, 0x00FFFFFFL);
if (fAlpha) { BLENDFUNCTION bf;
hbmT = SelectObject(ghdcBits2, did.hbmUserAlpha);
bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = AC_MIRRORBITMAP; bf.SourceConstantAlpha = 0xFF; bf.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(hdc, x, y, cx, cy, ghdcBits2, 0, 0, did.cx, did.cy / 2, bf); SelectObject(ghdcBits2,hbmT); retval = TRUE; } else { if (diFlags & DI_MASK) {
if (did.hbmMask) {
hbmT = SelectObject(ghdcBits2, did.hbmMask); StretchBlt(hdc, x, y, cx, cy, ghdcBits2, 0, 0, did.cx, did.cy / 2, rop | SRCAND); SelectObject(ghdcBits2,hbmT); retval = TRUE; } }
if (diFlags & DI_IMAGE) {
if (did.hbmColor != NULL) { hbmT = SelectObject(ghdcBits2, did.hbmColor); StretchBlt(hdc, x, y, cx, cy, ghdcBits2, 0, 0, did.cx, did.cy / 2, rop | SRCINVERT); SelectObject(ghdcBits2, hbmT); retval = TRUE; } else { if (did.hbmMask) { hbmT = SelectObject(ghdcBits2, did.hbmMask); StretchBlt(hdc, x, y, cx, cy, ghdcBits2, 0, did.cy / 2, did.cx, did.cy / 2, rop | SRCINVERT); SelectObject(ghdcBits2, hbmT); retval = TRUE; } } } }
RtlLeaveCriticalSection(&gcsHdc);
return retval; }
FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, ValidateRgn, HWND, hWnd, HRGN, hRgn) BOOL WINAPI ValidateRgn(HWND hWnd,HRGN hRgn) { return (BOOL)NtUserCallHwndParamLock(hWnd, (ULONG_PTR)hRgn, SFI_XXXVALIDATERGN); }
FUNCLOG3(LOG_GENERAL, int, WINAPI, GetUpdateRgn, HWND, hWnd, HRGN, hRgn, BOOL, bErase) int WINAPI GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase) { PWND pwnd;
if (hRgn == NULL) { RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid region %#p", hRgn); return ERROR; }
if ((pwnd = ValidateHwnd(hWnd)) == NULL) { return ERROR; }
/*
* Check for the simple case where nothing needs to be done. */ if (pwnd->hrgnUpdate == NULL && !TestWF(pwnd, WFSENDERASEBKGND) && !TestWF(pwnd, WFSENDNCPAINT) && !TestWF(pwnd, WFUPDATEDIRTY) && !TestWF(pwnd, WFPAINTNOTPROCESSED)) { SetRectRgn(hRgn, 0, 0, 0, 0); return NULLREGION; }
return NtUserGetUpdateRgn(hWnd, hRgn, bErase); }
FUNCLOG3(LOG_GENERAL, int, WINAPI, GetUpdateRect, HWND, hWnd, LPRECT, lprc, BOOL, bErase) int WINAPI GetUpdateRect(HWND hWnd, LPRECT lprc, BOOL bErase) { PWND pwnd;
if ((pwnd = ValidateHwnd(hWnd)) == NULL) { return FALSE; }
/*
* Check for the simple case where nothing needs to be done. */ if (pwnd->hrgnUpdate == NULL && !TestWF(pwnd, WFSENDERASEBKGND) && !TestWF(pwnd, WFSENDNCPAINT) && !TestWF(pwnd, WFUPDATEDIRTY) && !TestWF(pwnd, WFPAINTNOTPROCESSED)) { if (lprc) SetRectEmpty(lprc); return FALSE; }
return NtUserGetUpdateRect(hWnd, lprc, bErase); }
/***************************************************************************\
* ScrollWindow (API) * * * History: * 18-Jul-1991 DarrinM Ported from Win 3.1 sources. \***************************************************************************/
#define SW_FLAG_RC (SW_SCROLLWINDOW | SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN)
#define SW_FLAG_NRC (SW_SCROLLWINDOW | SW_INVALIDATE | SW_ERASE)
BOOL WINAPI ScrollWindow( HWND hwnd, int dx, int dy, CONST RECT *prcScroll, CONST RECT *prcClip) { return NtUserScrollWindowEx( hwnd, dx, dy, prcScroll, prcClip, NULL, NULL, !IS_PTR(prcScroll) ? SW_FLAG_RC : SW_FLAG_NRC) != ERROR; }
/***************************************************************************\
* SwitchToThisWindow \***************************************************************************/ FUNCLOGVOID2(LOG_GENERAL, WINAPI, SwitchToThisWindow, HWND, hwnd, BOOL, fAltTab) VOID WINAPI SwitchToThisWindow( HWND hwnd, BOOL fAltTab) { (VOID)NtUserCallHwndParamLock(hwnd, fAltTab, SFI_XXXSWITCHTOTHISWINDOW); }
/***************************************************************************\
* WaitForInputIdle * * Waits for a given process to go idle. * * 09-18-91 ScottLu Created. \***************************************************************************/
FUNCLOG2(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, WaitForInputIdle, HANDLE, hProcess, DWORD, dwMilliseconds) DWORD WaitForInputIdle( HANDLE hProcess, DWORD dwMilliseconds) { PROCESS_BASIC_INFORMATION processinfo; ULONG_PTR idProcess; NTSTATUS Status;
/*
* First get the process id from the hProcess. */ Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &processinfo, sizeof(processinfo), NULL); if (!NT_SUCCESS(Status)) { if (Status == STATUS_OBJECT_TYPE_MISMATCH) { if ((ULONG_PTR)hProcess & 0x2) { /*
* WOW Process handles are really semaphore handles. * CreateProcess ORs in a 0x2 (the low 2 bits of handles * are not used) so we can identify it more clearly. */ idProcess = ((ULONG_PTR)hProcess & ~0x03); return NtUserWaitForInputIdle(idProcess, dwMilliseconds, TRUE); }
/*
* VDM (DOS) Process handles are really semaphore handles. * CreateProcess ORs in a 0x1 (the low 2 bits of handles * are not used) so we can identify and return immidiately. */ if ((ULONG_PTR)hProcess & 0x1) { return 0; } }
RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "WaitForInputIdle invalid process 0x%p", hProcess); return WAIT_FAILED; }
idProcess = processinfo.UniqueProcessId; return NtUserWaitForInputIdle(idProcess, dwMilliseconds, FALSE); }
DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, CONST HANDLE *pHandles, BOOL fWaitAll, DWORD dwMilliseconds, DWORD dwWakeMask) { return MsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, fWaitAll?MWMO_WAITALL:0); }
DWORD WINAPI MsgWaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE *pHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags) #ifdef MESSAGE_PUMP_HOOK
{ DWORD dwResult;
BEGIN_MESSAGEPUMPHOOK() if (fInsideHook) { dwResult = gmph.pfnMsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags); } else { dwResult = RealMsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags); } END_MESSAGEPUMPHOOK()
return dwResult; }
DWORD WINAPI RealMsgWaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE *pHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags) #endif
{ HANDLE hEventInput; PHANDLE ph; DWORD dwIndex; BOOL ReenterWowScheduler; PCLIENTINFO pci; HANDLE rgHandles[ 8 + 1 ]; BOOL fWaitAll = ((dwFlags & MWMO_WAITALL) != 0); BOOL fAlertable = ((dwFlags & MWMO_ALERTABLE) != 0); CLIENTTHREADINFO *pcti;
if (dwFlags & ~MWMO_VALID) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "MsgWaitForMultipleObjectsEx, invalid flags 0x%x", dwFlags); return WAIT_FAILED; }
pci = GetClientInfo(); pcti = GETCLIENTTHREADINFO(); if (pcti && (!fWaitAll || !nCount)) { if (GetInputBits(pcti, LOWORD(dwWakeMask), (dwFlags & MWMO_INPUTAVAILABLE))) { return nCount; } }
/*
* Note -- the wake mask is a WORD, and only 3 flags are defined, so * they can be combined for the call. */
hEventInput = (HANDLE)NtUserCallOneParam(MAKELONG(dwWakeMask, dwFlags), SFI_XXXGETINPUTEVENT);
if (hEventInput == NULL) { RIPMSG0(RIP_WARNING, "MsgWaitForMultipleObjectsEx, GetInputEvent failed"); return WAIT_FAILED; }
/*
* If needed, allocate a new array of handles that will include the * input event handle. */ ph = rgHandles; if (pHandles) { if (nCount > 8) { ph = (PHANDLE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(HANDLE) * (nCount + 1)); if (ph == NULL) { NtUserCallNoParam(SFI_CLEARWAKEMASK); return WAIT_FAILED; } }
RtlCopyMemory((PVOID)ph, pHandles, sizeof(HANDLE) * nCount); } else { /*
* If this isn't zero, the function parameters are invalid. */ nCount = 0; }
ph[nCount] = hEventInput;
/*
* WowApps must exit the Wow scheduler otherwise other tasks in this * Wow scheduler can't run. The only exception is if the timeout is * Zero. We pass HEVENT_REMOVEME as the handle so we will go into the * sleeptask AND return without going to sleep but letting other apps * run. */ if ((pci->dwTIFlags & TIF_16BIT) && dwMilliseconds) { ReenterWowScheduler = TRUE; NtUserWaitForMsgAndEvent(HEVENT_REMOVEME); /*
* If our wait condition is satisfied, make sure we won't wait. * We must have a pcti now since we just went to the kernel. */ pcti = GETCLIENTTHREADINFO(); if (GetInputBits(pcti, LOWORD(dwWakeMask), (dwFlags & MWMO_INPUTAVAILABLE))) { SetEvent(hEventInput); } } else { ReenterWowScheduler = FALSE; }
dwIndex = WaitForMultipleObjectsEx(nCount + 1, ph, fWaitAll, dwMilliseconds, fAlertable);
/*
* Clear the wake mask since we're done waiting on these events. */ NtUserCallNoParam(SFI_CLEARWAKEMASK);
/*
* If needed reenter the wow scheduler. */ if (ReenterWowScheduler) { NtUserCallOneParam(DY_OLDYIELD, SFI_XXXDIRECTEDYIELD); }
if (ph != rgHandles) { UserLocalFree(ph); }
return dwIndex; }
/***************************************************************************\
* GrayString * * GrayStingA used to convert the string and call GrayStringW but that * did not work in a number of special cases such as the app passing in * a pointer to a zero length string. Eventually GrayStringA had almost as * much code as GrayStringW so now they are one. * * History: * 06-11-91 JimA Created. * 06-17-91 ChuckWh Added GDI handle conversion. * 02-12-92 mikeke Made it completely client side \***************************************************************************/
BOOL InnerGrayStringAorW( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC lpfnPrint, LPARAM lParam, int cch, int x, int y, int cx, int cy, BOOL bAnsi) { HBITMAP hbm; HBITMAP hbmOld; BOOL fResult; HFONT hFontSave = NULL; BOOL fReturn = FALSE; DWORD dwOldLayout = GDI_ERROR;
/*
* Win 3.1 tries to calc the size even if we don't know if it is a string. */ if (cch == 0) {
try {
cch = bAnsi ? strlen((LPSTR)lParam) : wcslen((LPWSTR)lParam);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) { fReturn = TRUE; }
if (fReturn) return FALSE; }
if (cx == 0 || cy == 0) {
SIZE size;
/*
* We use the caller supplied hdc (instead of hdcBits) since we may be * graying a font which is different than the system font and we want to * get the proper text extents. */ try { if (bAnsi) { GetTextExtentPointA(hdc, (LPSTR)lParam, cch, &size); } else { GetTextExtentPointW(hdc, (LPWSTR)lParam, cch, &size); }
cx = size.cx; cy = size.cy;
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) { fReturn = TRUE; }
if (fReturn) return FALSE; }
UserAssert (ghdcGray != NULL);
RtlEnterCriticalSection(&gcsHdc);
if (gcxGray < cx || gcyGray < cy) {
if ((hbm = CreateBitmap(cx, cy, 1, 1, 0L)) != NULL) {
hbmOld = SelectObject(ghdcGray, hbm); DeleteObject(hbmOld);
gcxGray = cx; gcyGray = cy;
} else { cx = gcxGray; cy = gcyGray; } }
/*
* If the caller hdc is mirrored then mirror ghdcGray. */ if (MIRRORED_HDC(hdc)) { dwOldLayout = SetLayoutWidth(ghdcGray, cx, LAYOUT_RTL); }
/*
* Force the ghdcGray font to be the same as hDC; ghdcGray is always * the system font */ hFontSave = SelectObject(hdc, ghFontSys);
if (hFontSave != ghFontSys) { SelectObject(hdc, hFontSave); hFontSave = SelectObject(ghdcGray, hFontSave); }
if (lpfnPrint != NULL) { PatBlt(ghdcGray, 0, 0, cx, cy, WHITENESS); fResult = (*lpfnPrint)(ghdcGray, lParam, cch); } else {
if (bAnsi) { fResult = TextOutA(ghdcGray, 0, 0, (LPSTR)lParam, cch); } else { fResult = TextOutW(ghdcGray, 0, 0, (LPWSTR)lParam, cch); } }
if (fResult) PatBlt(ghdcGray, 0, 0, cx, cy, DESTINATION | PATTERN);
if (fResult || cch == -1) {
HBRUSH hbrSave; DWORD textColorSave; DWORD bkColorSave;
textColorSave = SetTextColor(hdc, 0x00000000L); bkColorSave = SetBkColor(hdc, 0x00FFFFFFL);
hbrSave = SelectObject(hdc, hbr ? hbr : ghbrWindowText);
BitBlt(hdc, x, y, cx, cy, ghdcGray, 0, 0, (((PATTERN ^ DESTINATION) & SOURCE) ^ PATTERN));
SelectObject(hdc, hbrSave);
/*
* Restore saved colors */ SetTextColor(hdc, textColorSave); SetBkColor(hdc, bkColorSave); }
SelectObject(ghdcGray, hFontSave);
/*
* Restore ghdcGray layout state. */ if (dwOldLayout != GDI_ERROR) { SetLayoutWidth(ghdcGray, cx, dwOldLayout); }
RtlLeaveCriticalSection(&gcsHdc);
return fResult; }
FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GrayStringA, HDC, hdc, HBRUSH, hbr, GRAYSTRINGPROC, lpfnPrint, LPARAM, lParam, int, cch, int, x, int, y, int, cx, int, cy) BOOL GrayStringA( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC lpfnPrint, LPARAM lParam, int cch, int x, int y, int cx, int cy) { return (InnerGrayStringAorW(hdc, hbr, lpfnPrint, lParam, cch, x, y, cx, cy, TRUE)); }
FUNCLOG9(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GrayStringW, HDC, hdc, HBRUSH, hbr, GRAYSTRINGPROC, lpfnPrint, LPARAM, lParam, int, cch, int, x, int, y, int, cx, int, cy) BOOL GrayStringW( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC lpfnPrint, LPARAM lParam, int cch, int x, int y, int cx, int cy) { return (InnerGrayStringAorW(hdc, hbr, lpfnPrint, lParam, cch, x, y, cx, cy, FALSE)); }
/***************************************************************************\
* GetUserObjectSecurity (API) * * Gets the security descriptor of an object * * History: * 07-01-91 JimA Created. \***************************************************************************/ FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetUserObjectSecurity, HANDLE, hObject, PSECURITY_INFORMATION, pRequestedInformation, PSECURITY_DESCRIPTOR, pSecurityDescriptor, DWORD, nLength, LPDWORD, lpnLengthRequired) BOOL GetUserObjectSecurity( HANDLE hObject, PSECURITY_INFORMATION pRequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthRequired) { NTSTATUS Status;
Status = NtQuerySecurityObject(hObject, *pRequestedInformation, pSecurityDescriptor, nLength, lpnLengthRequired); if (!NT_SUCCESS(Status)) { RIPNTERR0(Status, RIP_VERBOSE, ""); return FALSE; }
return TRUE; }
/***************************************************************************\
* SetUserObjectSecurity (API) * * Sets the security descriptor of an object * * History: * 07-01-91 JimA Created. \***************************************************************************/
FUNCLOG3(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetUserObjectSecurity, HANDLE, hObject, PSECURITY_INFORMATION, pRequestedInformation, PSECURITY_DESCRIPTOR, pSecurityDescriptor) BOOL SetUserObjectSecurity( HANDLE hObject, PSECURITY_INFORMATION pRequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { NTSTATUS Status;
Status = NtSetSecurityObject(hObject, *pRequestedInformation, pSecurityDescriptor); if (!NT_SUCCESS(Status)) { RIPNTERR0(Status, RIP_VERBOSE, ""); return FALSE; } return TRUE; }
/***************************************************************************\
* GetUserObjectInformation (API) * * Gets information about an object * * History: \***************************************************************************/
FUNCLOG5(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetUserObjectInformationA, HANDLE, hObject, int, nIndex, PVOID, pvInfo, DWORD, nLength, LPDWORD, pnLengthNeeded) BOOL GetUserObjectInformationA( HANDLE hObject, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD pnLengthNeeded) { PVOID pvInfoW; DWORD nLengthW; BOOL fSuccess;
if (nIndex == UOI_NAME || nIndex == UOI_TYPE) { nLengthW = nLength * sizeof(WCHAR); pvInfoW = UserLocalAlloc(HEAP_ZERO_MEMORY, nLengthW); fSuccess = NtUserGetObjectInformation(hObject, nIndex, pvInfoW, nLengthW, pnLengthNeeded); if (fSuccess) { if (pnLengthNeeded != NULL) { *pnLengthNeeded /= sizeof(WCHAR); } WCSToMB(pvInfoW, -1, &(PCHAR)pvInfo, nLength, FALSE); } UserLocalFree(pvInfoW); return fSuccess; } else { return NtUserGetObjectInformation(hObject, nIndex, pvInfo, nLength, pnLengthNeeded); } }
BOOL GetWinStationInfo( WSINFO* pWsInfo) { return (BOOL)NtUserCallOneParam((ULONG_PTR)pWsInfo, SFI__GETWINSTATIONINFO); }
/***************************************************************************\
* GetServerIMEKeyboardLayout * * This routine finds HKL matches the IME module name sent from the Hydra * client at its session startup. * Hydra server tries to load the same IME module in the client, rather * than to use the same HKL: that's because, on FE machines, * the same IME might have different HKL dependent to each system. * * If the same IME name is found in registry, then it returns the HKL. * If it cannot find, return value is 0. * * History: \***************************************************************************/ ULONG GetServerIMEKeyboardLayout( LPTSTR pszImeFileName) { BOOL fFound = FALSE; ULONG wLayoutId; UNICODE_STRING UnicodeStringKLKey; UNICODE_STRING UnicodeStringSubKLKey; UNICODE_STRING UnicodeStringIME; OBJECT_ATTRIBUTES OA; HANDLE hKey; ULONG Index; WCHAR awchKLRegKey[NSZKLKEY]; LPWSTR lpszKLRegKey = awchKLRegKey; NTSTATUS Status;
RtlInitUnicodeString(&UnicodeStringKLKey, szKLKey); InitializeObjectAttributes(&OA, &UnicodeStringKLKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) {
for (Index = 0; TRUE; Index++) {
BYTE KeyBuffer[sizeof(KEY_BASIC_INFORMATION) + KL_NAMELENGTH * sizeof(WCHAR)]; PKEY_BASIC_INFORMATION pKeyInfo; ULONG ResultLength;
pKeyInfo = (PKEY_BASIC_INFORMATION)KeyBuffer; Status = NtEnumerateKey(hKey, Index, KeyBasicInformation, pKeyInfo, sizeof(KeyBuffer), &ResultLength);
if (NT_SUCCESS(Status)) { UnicodeStringSubKLKey.Buffer = (PWSTR)&(pKeyInfo->Name[0]); UnicodeStringSubKLKey.Length = (USHORT)pKeyInfo->NameLength; UnicodeStringSubKLKey.MaximumLength = (USHORT)pKeyInfo->NameLength; RtlUnicodeStringToInteger(&UnicodeStringSubKLKey, 16, &wLayoutId);
if (IS_IME_KBDLAYOUT(wLayoutId)) {
HANDLE hSubKey;
wcscpy(lpszKLRegKey, szKLKey); wcsncat(lpszKLRegKey, UnicodeStringSubKLKey.Buffer, UnicodeStringSubKLKey.Length / sizeof(WCHAR)); RtlInitUnicodeString(&UnicodeStringKLKey, lpszKLRegKey); InitializeObjectAttributes(&OA, &UnicodeStringKLKey, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (NT_SUCCESS(NtOpenKey(&hSubKey, KEY_READ, &OA))) { /*
* GetIME file name from "HKLM\...\<Index>\IME File" */ static CONST WCHAR szIMEfile[] = L"IME file"; struct { KEY_VALUE_PARTIAL_INFORMATION KeyInfo; WCHAR awchImeName[CCH_KL_LIBNAME]; } IMEfile; LPWSTR pwszIME; DWORD cbSize;
RtlInitUnicodeString(&UnicodeStringIME, szIMEfile);
Status = NtQueryValueKey(hSubKey, &UnicodeStringIME, KeyValuePartialInformation, &IMEfile, sizeof IMEfile, &cbSize); NtClose(hSubKey);
if (NT_SUCCESS(Status)) { pwszIME = (LPWSTR)IMEfile.KeyInfo.Data; pwszIME[CCH_KL_LIBNAME - 1] = L'\0'; if (!lstrcmpi(pwszIME, pszImeFileName)) { /*
* IME file name match !! */ fFound = TRUE; break; } } } } } else { break; } } NtClose(hKey); }
if (fFound) return wLayoutId;
return 0; }
/***************************************************************************\
* GetRemoteKeyboardLayout * * Returns TRUE if the client winstation specified a keyboard layout. * If TRUE, the LayoutBuf contains the name of the keyboard layout. * History: \***************************************************************************/
extern ULONG GetRemoteKeyboardLayoutFromConfigData(VOID); extern BOOL GetRemoteInputLanguage(LANGID*, PWCHAR);
BOOL GetRemoteKeyboardLayout( PWCHAR pwszKLName, LANGID* pLangId) { ULONG KeyboardLayout; BOOL fLangDataOK; WCHAR wszImeFileName[FIELD_SIZE(WINSTATIONCLIENTW, imeFileName) / sizeof(WCHAR)];
/*
* Skip if this is the main session */ if (!ISREMOTESESSION()) { return FALSE; }
KeyboardLayout = GetRemoteKeyboardLayoutFromConfigData();
fLangDataOK = GetRemoteInputLanguage(pLangId, wszImeFileName);
if (IS_IME_ENABLED()) { if (!fLangDataOK) { /*
* To preserve the W2k/XP behavior, * if ClientData was not retrieved * and if the machine is IME enabled, * bail out here. */ return FALSE; }
if (IS_IME_KBDLAYOUT(KeyboardLayout)) { KeyboardLayout = GetServerIMEKeyboardLayout(wszImeFileName); } }
if (KeyboardLayout != 0) { wsprintfW(pwszKLName, L"%8.8lx", KeyboardLayout); return TRUE; }
return FALSE; }
ULONG GetRemoteKeyboardLayoutFromConfigData(VOID) { WINSTATIONCONFIG ConfigData; ULONG Length;
if (!ISREMOTESESSION()) { RIPMSGF0(RIP_WARNING, "This is not a remote session!"); }
/*
* Fetch the WinStation's basic information */ if (!WinStationQueryInformationW(SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationConfiguration, &ConfigData, sizeof(ConfigData), &Length)) {
RIPMSGF0(RIP_WARNING, "Failed to get remote client ConfigData."); return 0; }
RIPMSGF1(RIP_WARNING, "The keyboard layout is %08x", ConfigData.User.KeyboardLayout);
return ConfigData.User.KeyboardLayout; }
BOOL GetRemoteInputLanguage(LANGID* pLangId, PWCHAR pwszImeFileName) { WINSTATIONCLIENTW ClientData; ULONG Length;
if (!ISREMOTESESSION()) { RIPMSGF0(RIP_WARNING, "This is not a remote session!"); }
/*
* Fetch the more remote client information. * N.b. this and above functions are departed from GetRemoteKeyboardLayout() * to reduce the stack consumption. */ if (!WinStationQueryInformationW(SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationClient, &ClientData, sizeof(ClientData), &Length)) { RIPMSGF0(RIP_WARNING, "Failed to get the remote ClientData -> no info about the langid"); *pLangId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); return FALSE; }
*pLangId = LOWORD(ClientData.ActiveInputLocale); TAGMSGF1(DBGTAG_KBD, "remote InputLocale is %08x", (DWORD)*pLangId); RtlCopyMemory(pwszImeFileName, ClientData.imeFileName, sizeof ClientData.imeFileName); return TRUE; }
/***************************************************************************\
* CommonCreateWindowStation (API) * * Creates a windowstation object * * History: \***************************************************************************/
HWINSTA CommonCreateWindowStation( PUNICODE_STRING pstrName, ACCESS_MASK amRequest, DWORD dwFlags, PSECURITY_ATTRIBUTES lpsa) { OBJECT_ATTRIBUTES Obja; HANDLE hRootDirectory; HWINSTA hwinstaNew = NULL; WCHAR wszKLName[KL_NAMELENGTH]; HANDLE hKeyboardFile = NULL; DWORD offTable; UNICODE_STRING strKLID; UINT uKbdInputLocale, uFlags; NTSTATUS Status;
/*
* Load initial keyboard layout. Continue even if * this fails (esp. important with KLF_INITTIME set) */ ULONG KeyboardLayout = 0;
KBDTABLE_MULTI_INTERNAL kbdTableMulti;
extern BOOL CtxInitUser32(VOID);
TAGMSGF0(DBGTAG_KBD, "entering");
hKeyboardFile = NULL;
/*
* Get winstation info */ if (ISREMOTESESSION()) { LANGID langidKbd;
if (GetRemoteKeyboardLayout(wszKLName, &langidKbd)) { // will we make the short-cut version?
uFlags = KLF_ACTIVATE | KLF_INITTIME; hKeyboardFile = OpenKeyboardLayoutFile(wszKLName, langidKbd, &uFlags, &offTable, &uKbdInputLocale, &kbdTableMulti); if (hKeyboardFile == NULL) { RIPMSGF0(RIP_WARNING, "OpenKeyboardLayoutFile() failed for the remote layout, will use the fallback."); } } }
if (hKeyboardFile == NULL) {
GetActiveKeyboardName(wszKLName); retry: uFlags = KLF_ACTIVATE | KLF_INITTIME; hKeyboardFile = OpenKeyboardLayoutFile(wszKLName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), &uFlags, &offTable, &uKbdInputLocale, &kbdTableMulti); if (hKeyboardFile == NULL) { if (wcscmp(wszKLName, L"00000409")) { wcscpy(wszKLName, L"00000409"); RIPMSG0(RIP_WARNING, "OpendKeyboardLayoutFile() failed: will use the fallback keyboard layout."); goto retry; } uKbdInputLocale = 0x04090409; } }
/*
* Finish the rest of the DLL initialization for WinStations. * Until this point we had no video driver. * * clupu: We have to prevent this for NOIO windowstations !!! */ if (ISTS()) { if (!CtxInitUser32()) { RIPMSG0(RIP_WARNING, "CtxInitUser32 failed"); goto Exit; } }
RtlInitUnicodeString(&strKLID, wszKLName);
/*
* If a name was specified, open the parent directory. Be sure * to test the length rather than the buffer because for NULL * string RtlCreateUnicodeStringFromAsciiz will allocate a * buffer pointing to an empty string. */ if (pstrName->Length != 0) { InitializeObjectAttributes(&Obja, (PUNICODE_STRING)&strRootDirectory, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenDirectoryObject(&hRootDirectory, DIRECTORY_CREATE_OBJECT, &Obja); if (!NT_SUCCESS(Status)) { RIPNTERR0(Status, RIP_VERBOSE, ""); goto Exit; } } else { pstrName = NULL; hRootDirectory = NULL; }
InitializeObjectAttributes(&Obja, pstrName, OBJ_CASE_INSENSITIVE | ((dwFlags & CWF_CREATE_ONLY) ? 0 : OBJ_OPENIF) | ((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0), hRootDirectory, lpsa ? lpsa->lpSecurityDescriptor : NULL);
/*
* NULL hKeyboardFile will let the kernel to utilize * the kbdnull layout which is a built in as a fallback layout * in Win32k.sys. */ hwinstaNew = NtUserCreateWindowStation( &Obja, amRequest, hKeyboardFile, offTable, &kbdTableMulti, &strKLID, uKbdInputLocale);
if (hRootDirectory != NULL) NtClose(hRootDirectory); Exit: if (hKeyboardFile) { NtClose(hKeyboardFile); } return hwinstaNew; }
FUNCLOG4(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, CreateWindowStationA, LPCSTR, pwinsta, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa) HWINSTA CreateWindowStationA( LPCSTR pwinsta, DWORD dwFlags, ACCESS_MASK amRequest, PSECURITY_ATTRIBUTES lpsa) { UNICODE_STRING UnicodeString; HWINSTA hwinsta;
if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pwinsta)) return NULL;
hwinsta = CommonCreateWindowStation(&UnicodeString, amRequest, dwFlags, lpsa);
RtlFreeUnicodeString(&UnicodeString);
return hwinsta; }
FUNCLOG4(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, CreateWindowStationW, LPCWSTR, pwinsta, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa) HWINSTA CreateWindowStationW( LPCWSTR pwinsta, DWORD dwFlags, ACCESS_MASK amRequest, PSECURITY_ATTRIBUTES lpsa) { UNICODE_STRING strWinSta;
RtlInitUnicodeString(&strWinSta, pwinsta);
return CommonCreateWindowStation(&strWinSta, amRequest, dwFlags, lpsa); }
/***************************************************************************\
* OpenWindowStation (API) * * Opens a windowstation object * * History: \***************************************************************************/
HWINSTA CommonOpenWindowStation( CONST UNICODE_STRING *pstrName, BOOL fInherit, ACCESS_MASK amRequest) { WCHAR awchName[sizeof(WINSTA_NAME) / sizeof(WCHAR)]; UNICODE_STRING strDefaultName; OBJECT_ATTRIBUTES ObjA; HANDLE hRootDirectory; HWINSTA hwinsta; NTSTATUS Status;
InitializeObjectAttributes(&ObjA, (PUNICODE_STRING)&strRootDirectory, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenDirectoryObject(&hRootDirectory, DIRECTORY_TRAVERSE, &ObjA); if (!NT_SUCCESS(Status)) { RIPNTERR0(Status, RIP_VERBOSE, ""); return NULL; }
if (pstrName->Length == 0) { RtlCopyMemory(awchName, WINSTA_NAME, sizeof(WINSTA_NAME)); RtlInitUnicodeString(&strDefaultName, awchName); pstrName = &strDefaultName; }
InitializeObjectAttributes(&ObjA, (PUNICODE_STRING)pstrName, OBJ_CASE_INSENSITIVE, hRootDirectory, NULL); if (fInherit) ObjA.Attributes |= OBJ_INHERIT;
hwinsta = NtUserOpenWindowStation(&ObjA, amRequest);
NtClose(hRootDirectory);
return hwinsta; }
FUNCLOG3(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, OpenWindowStationA, LPCSTR, pwinsta, BOOL, fInherit, ACCESS_MASK, amRequest) HWINSTA OpenWindowStationA( LPCSTR pwinsta, BOOL fInherit, ACCESS_MASK amRequest) { UNICODE_STRING UnicodeString; HWINSTA hwinsta;
if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pwinsta)) return NULL;
hwinsta = CommonOpenWindowStation(&UnicodeString, fInherit, amRequest);
RtlFreeUnicodeString(&UnicodeString);
return hwinsta; }
FUNCLOG3(LOG_GENERAL, HWINSTA, DUMMYCALLINGTYPE, OpenWindowStationW, LPCWSTR, pwinsta, BOOL, fInherit, ACCESS_MASK, amRequest) HWINSTA OpenWindowStationW( LPCWSTR pwinsta, BOOL fInherit, ACCESS_MASK amRequest) { UNICODE_STRING strWinSta;
RtlInitUnicodeString(&strWinSta, pwinsta);
return CommonOpenWindowStation(&strWinSta, fInherit, amRequest); }
/***************************************************************************\
* CommonCreateDesktop (API) * * Creates a desktop object * * History: \***************************************************************************/
HDESK CommonCreateDesktop( PUNICODE_STRING pstrDesktop, PUNICODE_STRING pstrDevice, LPDEVMODEW pDevmode, DWORD dwFlags, ACCESS_MASK amRequest, PSECURITY_ATTRIBUTES lpsa) { OBJECT_ATTRIBUTES Obja; HDESK hdesk = NULL;
InitializeObjectAttributes(&Obja, pstrDesktop, OBJ_CASE_INSENSITIVE | OBJ_OPENIF | ((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0), NtUserGetProcessWindowStation(), lpsa ? lpsa->lpSecurityDescriptor : NULL);
hdesk = NtUserCreateDesktop(&Obja, pstrDevice, pDevmode, dwFlags, amRequest);
return hdesk; }
/***************************************************************************\
* CreateDesktopA (API) * * Creates a desktop object * * History: \***************************************************************************/
FUNCLOG6(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, CreateDesktopA, LPCSTR, pDesktop, LPCSTR, pDevice, LPDEVMODEA, pDevmode, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa) HDESK CreateDesktopA( LPCSTR pDesktop, LPCSTR pDevice, LPDEVMODEA pDevmode, DWORD dwFlags, ACCESS_MASK amRequest, PSECURITY_ATTRIBUTES lpsa) { NTSTATUS Status; ANSI_STRING AnsiString; UNICODE_STRING UnicodeDesktop; UNICODE_STRING UnicodeDevice; PUNICODE_STRING pUnicodeDevice = NULL; LPDEVMODEW lpDevModeW = NULL; HDESK hdesk;
RtlInitAnsiString(&AnsiString, pDesktop); Status = RtlAnsiStringToUnicodeString(&UnicodeDesktop, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) { RIPNTERR1(Status, RIP_WARNING, "CreateDesktop fails with Status = 0x%x", Status); return NULL; }
if (pDevice) { pUnicodeDevice = &UnicodeDevice; RtlInitAnsiString(&AnsiString, pDevice); Status = RtlAnsiStringToUnicodeString(&UnicodeDevice, &AnsiString, TRUE);
if (!NT_SUCCESS(Status)) { RIPNTERR0(Status, RIP_VERBOSE, ""); RtlFreeUnicodeString(&UnicodeDesktop); return NULL; } }
if (pDevmode) { lpDevModeW = GdiConvertToDevmodeW(pDevmode); }
hdesk = CommonCreateDesktop(&UnicodeDesktop, pUnicodeDevice, lpDevModeW, dwFlags, amRequest, lpsa);
RtlFreeUnicodeString(&UnicodeDesktop); if (pDevice) { RtlFreeUnicodeString(&UnicodeDevice); }
if (lpDevModeW) { RtlFreeHeap(RtlProcessHeap(), 0, lpDevModeW); }
return hdesk; }
/***************************************************************************\
* CreateDesktopW (API) * * Creates a desktop object * * History: \***************************************************************************/
FUNCLOG6(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, CreateDesktopW, LPCWSTR, pDesktop, LPCWSTR, pDevice, LPDEVMODEW, pDevmode, DWORD, dwFlags, ACCESS_MASK, amRequest, PSECURITY_ATTRIBUTES, lpsa) HDESK CreateDesktopW( LPCWSTR pDesktop, LPCWSTR pDevice, LPDEVMODEW pDevmode, DWORD dwFlags, ACCESS_MASK amRequest, PSECURITY_ATTRIBUTES lpsa) { UNICODE_STRING strDesktop; UNICODE_STRING strDevice;
RtlInitUnicodeString(&strDesktop, pDesktop); RtlInitUnicodeString(&strDevice, pDevice);
return CommonCreateDesktop(&strDesktop, pDevice ? &strDevice : NULL, pDevmode, dwFlags, amRequest, lpsa); }
/***************************************************************************\
* OpenDesktop (API) * * Opens a desktop object * * History: \***************************************************************************/
HDESK CommonOpenDesktop( PUNICODE_STRING pstrDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK amRequest) { OBJECT_ATTRIBUTES ObjA;
InitializeObjectAttributes(&ObjA, pstrDesktop, OBJ_CASE_INSENSITIVE, NtUserGetProcessWindowStation(), NULL); if (fInherit) { ObjA.Attributes |= OBJ_INHERIT; }
return NtUserOpenDesktop(&ObjA, dwFlags, amRequest); }
FUNCLOG4(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, OpenDesktopA, LPCSTR, pdesktop, DWORD, dwFlags, BOOL, fInherit, ACCESS_MASK, amRequest) HDESK OpenDesktopA( LPCSTR pdesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK amRequest) { UNICODE_STRING UnicodeString; HDESK hdesk;
if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pdesktop)) return NULL;
hdesk = CommonOpenDesktop(&UnicodeString, dwFlags, fInherit, amRequest);
RtlFreeUnicodeString(&UnicodeString);
return hdesk; }
FUNCLOG4(LOG_GENERAL, HDESK, DUMMYCALLINGTYPE, OpenDesktopW, LPCWSTR, pdesktop, DWORD, dwFlags, BOOL, fInherit, ACCESS_MASK, amRequest) HDESK OpenDesktopW( LPCWSTR pdesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK amRequest) { UNICODE_STRING strDesktop;
RtlInitUnicodeString(&strDesktop, pdesktop);
return CommonOpenDesktop(&strDesktop, dwFlags, fInherit, amRequest); }
/***************************************************************************\
* RegisterClassWOW(API) * * History: * 28-Jul-1992 ChandanC Created. \***************************************************************************/ ATOM WINAPI RegisterClassWOWA( WNDCLASSA *lpWndClass, LPDWORD pdwWOWstuff) { WNDCLASSEXA wc;
/*
* On 64-bit plaforms we'll have 32 bits of padding between style and * lpfnWndProc in WNDCLASS, so start the copy from the first 64-bit * aligned field and hand copy the rest. */ RtlCopyMemory(&(wc.lpfnWndProc), &(lpWndClass->lpfnWndProc), sizeof(WNDCLASSA) - FIELD_OFFSET(WNDCLASSA, lpfnWndProc)); wc.style = lpWndClass->style; wc.hIconSm = NULL; wc.cbSize = sizeof(WNDCLASSEXA);
return RegisterClassExWOWA(&wc, pdwWOWstuff, 0, 0); }
/**************************************************************************\
* WowGetDefWindowProcBits - Fills in bit array for WOW * * 22-Jul-1991 mikeke Created \**************************************************************************/
WORD WowGetDefWindowProcBits( PBYTE pDefWindowProcBits, WORD cbDefWindowProcBits) { WORD wMaxMsg; KPBYTE pbSrc; PBYTE pbDst, pbDstEnd;
UNREFERENCED_PARAMETER(cbDefWindowProcBits);
/*
* Merge the bits from gpsi->gabDefWindowMsgs and * gpsi->gabDefWindowSpecMsgs into WOW's DefWindowProcBits. These two * indicate which messages must go directly to the server and which * can be handled with some special code in DefWindowProcWorker. * Bitwise OR'ing the two gives a bit array with 1 in the bit field * for each message that must go to user32's DefWindowProc, and 0 * for those that can be returned back to the client immediately. * * For speed we assume WOW has zeroed the buffer, in fact it's in * USER.EXE's code segment and is zeroed in the image. */
wMaxMsg = max(gSharedInfo.DefWindowMsgs.maxMsgs, gSharedInfo.DefWindowSpecMsgs.maxMsgs);
UserAssert((wMaxMsg / 8 + 1) <= cbDefWindowProcBits);
//
// If the above assertion fires, the size of the DWPBits array in
// \nt\private\mvdm\wow16\user\user.asm needs to be increased.
//
/* First copy the bits from DefWindowMsgs */
RtlCopyMemory( pDefWindowProcBits, gSharedInfo.DefWindowMsgs.abMsgs, gSharedInfo.DefWindowMsgs.maxMsgs / 8 + 1 );
/* Next OR in the bits from DefWindowSpecMsgs */
pbSrc = gSharedInfo.DefWindowSpecMsgs.abMsgs; pbDst = pDefWindowProcBits; pbDstEnd = pbDst + (gSharedInfo.DefWindowSpecMsgs.maxMsgs / 8 + 1);
while (pbDst < pbDstEnd) { *pbDst++ |= *pbSrc++; }
return wMaxMsg; }
FUNCLOG2(LOG_GENERAL, ULONG_PTR, DUMMYCALLINGTYPE, UserRegisterWowHandlers, APFNWOWHANDLERSIN, apfnWowIn, APFNWOWHANDLERSOUT, apfnWowOut) ULONG_PTR UserRegisterWowHandlers( APFNWOWHANDLERSIN apfnWowIn, APFNWOWHANDLERSOUT apfnWowOut) { VDM_QUERY_VDM_PROCESS_DATA QueryVdmProcessData; NTSTATUS Status;
//
// Check the Target Process to see if this is a Wx86 process
//
QueryVdmProcessData.IsVdmProcess = FALSE;
QueryVdmProcessData.ProcessHandle = NtCurrentProcess();
Status = NtVdmControl(VdmQueryVdmProcess, &QueryVdmProcessData);
if (!NT_SUCCESS(Status) || QueryVdmProcessData.IsVdmProcess == FALSE) {
return STATUS_ACCESS_DENIED; }
// In'ees
pfnLocalAlloc = apfnWowIn->pfnLocalAlloc; pfnLocalReAlloc = apfnWowIn->pfnLocalReAlloc; pfnLocalLock = apfnWowIn->pfnLocalLock; pfnLocalUnlock = apfnWowIn->pfnLocalUnlock; pfnLocalSize = apfnWowIn->pfnLocalSize; pfnLocalFree = apfnWowIn->pfnLocalFree; pfnGetExpWinVer = apfnWowIn->pfnGetExpWinVer; pfn16GlobalAlloc = apfnWowIn->pfn16GlobalAlloc; pfn16GlobalFree = apfnWowIn->pfn16GlobalFree; pfnWowEmptyClipBoard = apfnWowIn->pfnEmptyCB; pfnWowEditNextWord = apfnWowIn->pfnWowEditNextWord; pfnWowCBStoreHandle = apfnWowIn->pfnWowCBStoreHandle; pfnFindResourceExA = apfnWowIn->pfnFindResourceEx; pfnLoadResource = apfnWowIn->pfnLoadResource; pfnLockResource = apfnWowIn->pfnLockResource; pfnUnlockResource = apfnWowIn->pfnUnlockResource; pfnFreeResource = apfnWowIn->pfnFreeResource; pfnSizeofResource = apfnWowIn->pfnSizeofResource; pfnFindResourceExW = WOWFindResourceExWCover; pfnWowDlgProcEx = apfnWowIn->pfnWowDlgProcEx; pfnWowWndProcEx = apfnWowIn->pfnWowWndProcEx; pfnWowGetProcModule = apfnWowIn->pfnGetProcModule16; pfnWowTask16SchedNotify = apfnWowIn->pfnWowTask16SchedNotify; pfnWOWTellWOWThehDlg = apfnWowIn->pfnWOWTellWOWThehDlg; pfnWowMsgBoxIndirectCallback = apfnWowIn->pfnWowMsgBoxIndirectCallback; pfnWowIlstrcmp = apfnWowIn->pfnWowIlstrsmp;
// Out'ees
#if DBG
apfnWowOut->dwBldInfo = (WINVER << 16) | 0x80000000; #else
apfnWowOut->dwBldInfo = (WINVER << 16); #endif
apfnWowOut->pfnCsCreateWindowEx = _CreateWindowEx; apfnWowOut->pfnDirectedYield = DirectedYield; apfnWowOut->pfnFreeDDEData = FreeDDEData; apfnWowOut->pfnGetClassWOWWords = GetClassWOWWords; apfnWowOut->pfnInitTask = InitTask; apfnWowOut->pfnRegisterClassWOWA = RegisterClassWOWA; apfnWowOut->pfnRegisterUserHungAppHandlers = RegisterUserHungAppHandlers; apfnWowOut->pfnServerCreateDialog = InternalCreateDialog; apfnWowOut->pfnServerLoadCreateCursorIcon = WowServerLoadCreateCursorIcon; apfnWowOut->pfnServerLoadCreateMenu = WowServerLoadCreateMenu; apfnWowOut->pfnWOWCleanup = WOWCleanup; apfnWowOut->pfnWOWModuleUnload = WOWModuleUnload; apfnWowOut->pfnWOWFindWindow = WOWFindWindow; apfnWowOut->pfnWOWLoadBitmapA = WOWLoadBitmapA; apfnWowOut->pfnWowWaitForMsgAndEvent = NtUserWaitForMsgAndEvent; apfnWowOut->pfnYieldTask = NtUserYieldTask; apfnWowOut->pfnGetFullUserHandle = GetFullUserHandle; apfnWowOut->pfnGetMenuIndex = NtUserGetMenuIndex; apfnWowOut->pfnWowGetDefWindowProcBits = WowGetDefWindowProcBits; apfnWowOut->pfnFillWindow = FillWindow; apfnWowOut->aiWowClass = aiClassWow; return (ULONG_PTR)&gSharedInfo; }
/***************************************************************************\
* GetEditDS * * This is a callback to WOW used to allocate a segment for DS_LOCALEDIT * edit controls. The segment is disguised to look like a WOW hInstance. * * 06-19-92 sanfords Created \***************************************************************************/ HANDLE GetEditDS() { UserAssert(pfn16GlobalAlloc != NULL);
return((HANDLE)((*pfn16GlobalAlloc)(GHND | GMEM_SHARE, 256))); }
/***************************************************************************\
* ReleaseEditDS * * This is a callback to WOW used to free a segment for DS_LOCALEDIT * edit controls. * * 06-19-92 sanfords Created \***************************************************************************/ VOID ReleaseEditDS( HANDLE h) { UserAssert(pfn16GlobalFree != NULL);
(*pfn16GlobalFree)(LOWORD(HandleToUlong(h))); }
/***************************************************************************\
* TellWOWThehDlg * * This is a callback to WOW used to inform WOW of the hDlg of a newly * created dialog window. * * 08-31-97 cmjones Created \***************************************************************************/ VOID TellWOWThehDlg( HWND hDlg) { UserAssert(pfnWOWTellWOWThehDlg != NULL);
(*pfnWOWTellWOWThehDlg)(hDlg); }
/***************************************************************************\
* DispatchClientMessage * * pwnd is threadlocked in the kernel and thus always valid. * * 19-Aug-1992 mikeke created \***************************************************************************/ LRESULT DispatchClientMessage( PWND pwnd, UINT message, WPARAM wParam, LPARAM lParam, ULONG_PTR pfn) { PCLIENTINFO pci = GetClientInfo(); HWND hwnd = KHWND_TO_HWND(pci->CallbackWnd.hwnd); PACTIVATION_CONTEXT pActCtx = pci->CallbackWnd.pActCtx; LRESULT lRet = 0;
/*
* Assert that the header comment is legit (it must be). For WM_TIMER * messages not associated with a window, pwnd can be NULL. So don't * rip validating the handle. */ UserAssert(pwnd == ValidateHwndNoRip(hwnd));
/*
* Add assert to catch dispatching messages to a thread not associated * with a desktop. */ UserAssert(GetClientInfo()->ulClientDelta != 0);
if (message == WM_TIMER && lParam != 0) { /*
* Console windows use WM_TIMER for the caret. However, they don't * use a timer callback, so if this is CSRSS and there's a WM_TIMER * for us, the only way lParam would be non-zero is if someone's trying * to make us fault. No, this isn't a nice thing to do, but there * are bad, bad people out there. Windows Bug #361246. */ if (!gfServerProcess) { /*
* We can't really trust what's in lParam, so make sure we * handle any exceptions that occur during this call. */ try { lRet = UserCallWinProcCheckWow(pActCtx, (WNDPROC)pfn, hwnd, message, wParam, NtGetTickCount(), &(pwnd->state), TRUE); } except ((GetAppCompatFlags2(VER40) & GACF2_NO_TRYEXCEPT_CALLWNDPROC) ? EXCEPTION_CONTINUE_SEARCH : W32ExceptionHandler(FALSE, RIP_WARNING)) { /*
* Windows NT Bug #359866. * Some applications like Hagaki Studio 2000 need to handle * the exception in WndProc in their handler, even though it * skips the API calls. For those apps, we have to honor the * behavior of NT4, with no protection. */ } } } else { lRet = UserCallWinProcCheckWow(pActCtx, (WNDPROC)pfn, hwnd, message, wParam, lParam, &(pwnd->state), TRUE); }
return lRet; }
/**************************************************************************\
* ArrangeIconicWindows * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, ArrangeIconicWindows, HWND, hwnd) UINT ArrangeIconicWindows( HWND hwnd) { return (UINT)NtUserCallHwndLock(hwnd, SFI_XXXARRANGEICONICWINDOWS); }
/**************************************************************************\
* BeginDeferWindowPos * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, HANDLE, DUMMYCALLINGTYPE, BeginDeferWindowPos, int, nNumWindows) HANDLE BeginDeferWindowPos( int nNumWindows) { if (nNumWindows < 0) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid parameter \"nNumWindows\" (%ld) to BeginDeferWindowPos", nNumWindows);
return 0; }
return (HANDLE)NtUserCallOneParam(nNumWindows, SFI__BEGINDEFERWINDOWPOS); }
/**************************************************************************\
* EndDeferWindowPos * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EndDeferWindowPos, HDWP, hWinPosInfo) BOOL EndDeferWindowPos( HDWP hWinPosInfo) { return NtUserEndDeferWindowPosEx(hWinPosInfo, FALSE); }
/**************************************************************************\
* CascadeChildWindows * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CascadeChildWindows, HWND, hwndParent, UINT, nCode) BOOL CascadeChildWindows( HWND hwndParent, UINT nCode) { return (BOOL) CascadeWindows(hwndParent, nCode, NULL, 0, NULL); }
/**************************************************************************\
* CloseWindow * * 22-Jul-1991 mikeke Created * 17-Feb-1998 MCostea Use xxxShowWindow instead of xxxCloseWindow \**************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, CloseWindow, HWND, hwnd) BOOL CloseWindow( HWND hwnd) { PWND pwnd;
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return FALSE; } if (!TestWF(pwnd, WFMINIMIZED)) { NtUserShowWindow(hwnd, SW_SHOWMINIMIZED); } return TRUE; }
/**************************************************************************\
* CreateMenu * * 22-Jul-1991 mikeke Created \**************************************************************************/
HMENU CreateMenu() { return (HMENU)NtUserCallNoParam(SFI__CREATEMENU); }
/**************************************************************************\
* CreatePopupMenu * * 22-Jul-1991 mikeke Created \**************************************************************************/
HMENU CreatePopupMenu() { return (HMENU)NtUserCallNoParam(SFI__CREATEPOPUPMENU); }
/**************************************************************************\
* CurrentTaskLock * * 21-Apr-1992 jonpa Created \**************************************************************************/ #if 0 /* WOW is not using this but they might some day */
DWORD CurrentTaskLock( DWORD hlck) { return (DWORD)NtUserCallOneParam(hlck, SFI_CURRENTTASKLOCK); } #endif
/**************************************************************************\
* DestroyCaret * * 22-Jul-1991 mikeke Created \**************************************************************************/
BOOL DestroyCaret() { return (BOOL)NtUserCallNoParam(SFI_ZZZDESTROYCARET); }
/**************************************************************************\
* DirectedYield * * 22-Jul-1991 mikeke Created \**************************************************************************/
void DirectedYield( DWORD dwThreadId) { NtUserCallOneParam(dwThreadId, SFI_XXXDIRECTEDYIELD); }
/**************************************************************************\
* DrawMenuBar * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DrawMenuBar, HWND, hwnd) BOOL DrawMenuBar( HWND hwnd) { return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXDRAWMENUBAR); }
/**************************************************************************\
* EnableWindow * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EnableWindow, HWND, hwnd, BOOL, bEnable) BOOL EnableWindow( HWND hwnd, BOOL bEnable) { return (BOOL)NtUserCallHwndParamLock(hwnd, bEnable, SFI_XXXENABLEWINDOW); }
/**************************************************************************\
* EnumClipboardFormats * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, EnumClipboardFormats, UINT, fmt) UINT EnumClipboardFormats( UINT fmt) { /*
* So apps can tell if the API failed or just ran out of formats * we "clear" the last error. */ UserSetLastError(ERROR_SUCCESS);
return (UINT)NtUserCallOneParam(fmt, SFI__ENUMCLIPBOARDFORMATS); }
/**************************************************************************\
* FlashWindow * * 22-Jul-1991 mikeke Created * 08-Aug-1997 Gerardob Added FlashWindowEx. * 16-Nov-1997 MCostea Make it use NtUserFlashWindowEx \**************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, FlashWindow, HWND, hwnd, BOOL, bInvert) BOOL FlashWindow( HWND hwnd, BOOL bInvert) { FLASHWINFO fwi = { sizeof(FLASHWINFO), // cbSize
hwnd, // hwnd
bInvert ? (FLASHW_CAPTION | FLASHW_TRAY) : 0, // flags
1, // uCount
0 // dwTimeout
}; return (BOOL)NtUserFlashWindowEx(&fwi); }
/**************************************************************************\
* GetDialogBaseUnits * * 22-Jul-1991 mikeke Created \**************************************************************************/ LONG GetDialogBaseUnits( VOID) { return MAKELONG(gpsi->cxSysFontChar, gpsi->cySysFontChar); }
/**************************************************************************\
* GetInputDesktop * * 22-Jul-1991 mikeke Created \**************************************************************************/ HDESK GetInputDesktop( VOID) { return (HDESK)NtUserCallNoParam(SFI__GETINPUTDESKTOP); }
/***************************************************************************\
* GetClientKeyboardType * * This routine returns the keyboard type sent from the Hydra client. * Hydra client sends keyboard types at session startup. * * Returns the client winstation specified a keyboard type. * History: \***************************************************************************/ BOOL GetClientKeyboardType( PCLIENTKEYBOARDTYPE KeyboardType) { ULONG Length; WINSTATIONCLIENTW ClientData; static CLIENTKEYBOARDTYPE ClientKeyboard = { (ULONG)-1, (ULONG)-1, (ULONG)-1 };
//
// Should be called only if this is a HYDRA remote session.
//
if (!ISREMOTESESSION()) { RIPMSGF0(RIP_WARNING, "This is not a remote session!"); }
// Skip if this is the console
if (!ISREMOTESESSION()) { return FALSE; }
if (ClientKeyboard.Type == (ULONG)-1) {
// Fetch the WinStation's basic information
if (!WinStationQueryInformationW(SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationClient, &ClientData, sizeof(ClientData), &Length)) { return FALSE; }
ClientKeyboard.Type = ClientData.KeyboardType; ClientKeyboard.SubType = ClientData.KeyboardSubType; ClientKeyboard.FunctionKey = ClientData.KeyboardFunctionKey;
}
*KeyboardType = ClientKeyboard;
return TRUE; }
/**************************************************************************\
* GetKeyboardType * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetKeyboardType, int, nTypeFlags) int GetKeyboardType( int nTypeFlags) { if (ISREMOTESESSION()) { //
// Get keyboard type from Hydra client if this is not the console
//
CLIENTKEYBOARDTYPE KeyboardType;
if (GetClientKeyboardType(&KeyboardType)) { switch (nTypeFlags) { case 0: return KeyboardType.Type; case 1: if (KeyboardType.Type == 7) { /* 7 is a Japanese */ // Because HIWORD has been using private value
// for Japanese keyboard layout.
return LOWORD(KeyboardType.SubType); } else return KeyboardType.SubType; case 2: return KeyboardType.FunctionKey; default: break; } } return 0; } return (int)NtUserCallOneParam(nTypeFlags, SFI__GETKEYBOARDTYPE); }
/**************************************************************************\
* GetMessagePos * * 22-Jul-1991 mikeke Created \**************************************************************************/
DWORD GetMessagePos() { return (DWORD)NtUserCallNoParam(SFI__GETMESSAGEPOS); }
/**************************************************************************\
* GetQueueStatus * * 22-Jul-1991 mikeke Created * 14-Dec-2000 JStall Converted to WMH \**************************************************************************/
FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetQueueStatus, UINT, flags) DWORD GetQueueStatus( UINT flags) #ifdef MESSAGE_PUMP_HOOK
{ DWORD dwResult;
BEGIN_MESSAGEPUMPHOOK() if (fInsideHook) { dwResult = gmph.pfnGetQueueStatus(flags); } else { dwResult = RealGetQueueStatus(flags); } END_MESSAGEPUMPHOOK()
return dwResult; }
DWORD RealGetQueueStatus( UINT flags) #endif
{ if (flags & ~QS_VALID) { RIPERR2(ERROR_INVALID_FLAGS, RIP_WARNING, "Invalid flags %x & ~%x != 0", flags, QS_VALID); return 0; }
return (DWORD)NtUserCallOneParam(flags, SFI__GETQUEUESTATUS); }
/**************************************************************************\
* KillSystemTimer * * 7-Jul-1992 mikehar Created \**************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, KillSystemTimer, HWND, hwnd, UINT, nIDEvent) BOOL KillSystemTimer( HWND hwnd, UINT nIDEvent) { return (BOOL)NtUserCallHwndParam(hwnd, nIDEvent, SFI__KILLSYSTEMTIMER); }
/**************************************************************************\
* LoadRemoteFonts * 02-Dec-1993 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
void LoadRemoteFonts(void) { NtUserCallOneParam(TRUE,SFI_XXXLW_LOADFONTS);
/*
* After load remote fonts, let eudc enabled. */ EnableEUDC(TRUE); }
/**************************************************************************\
* LoadLocalFonts * 31-Mar-1994 -by- Bodin Dresevic [gerritv] * Wrote it. \**************************************************************************/
void LoadLocalFonts(void) { NtUserCallOneParam(FALSE,SFI_XXXLW_LOADFONTS); }
/**************************************************************************\
* MessageBeep * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, MessageBeep, UINT, wType) BOOL MessageBeep( UINT wType) { return (BOOL)NtUserCallOneParam(wType, SFI_XXXMESSAGEBEEP); }
/**************************************************************************\
* OpenIcon * * 22-Jul-1991 mikeke Created * 17-Feb-1998 MCostea Use xxxShowWindow instead of xxxCloseWindow \**************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, OpenIcon, HWND, hwnd) BOOL OpenIcon( HWND hwnd) { PWND pwnd;
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return FALSE; } if (TestWF(pwnd, WFMINIMIZED)) { NtUserShowWindow(hwnd, SW_NORMAL); } return TRUE; }
HWND GetShellWindow(void) { PCLIENTINFO pci; PWND pwnd;
ConnectIfNecessary(0);
pci = GetClientInfo(); pwnd = pci->pDeskInfo->spwndShell; if (pwnd != NULL) { pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta); return HWq(pwnd); } return NULL; }
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetShellWindow, HWND, hwnd) BOOL SetShellWindow(HWND hwnd) { return (BOOL)NtUserSetShellWindowEx(hwnd, hwnd); }
HWND GetProgmanWindow(void) { PCLIENTINFO pci; PWND pwnd;
ConnectIfNecessary(0);
pci = GetClientInfo(); pwnd = pci->pDeskInfo->spwndProgman; if (pwnd != NULL) { pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta); return HWq(pwnd); } return NULL; }
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetProgmanWindow, HWND, hwnd) BOOL SetProgmanWindow( HWND hwnd) { return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETPROGMANWINDOW); }
HWND GetTaskmanWindow(void) { PCLIENTINFO pci; PWND pwnd;
ConnectIfNecessary(0);
pci = GetClientInfo(); pwnd = pci->pDeskInfo->spwndTaskman; if (pwnd != NULL) { pwnd = (PWND)((KERNEL_ULONG_PTR)pwnd - pci->ulClientDelta); return HWq(pwnd); } return NULL; }
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetTaskmanWindow, HWND, hwnd) BOOL SetTaskmanWindow( HWND hwnd) { return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETTASKMANWINDOW); }
/**************************************************************************\
* SetWindowContextHelpId * * 22-Jul-1991 mikeke Created \**************************************************************************/
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetWindowContextHelpId, HWND, hwnd, DWORD, id) BOOL SetWindowContextHelpId( HWND hwnd, DWORD id) { return (BOOL)NtUserCallHwndParam(hwnd, id, SFI__SETWINDOWCONTEXTHELPID); }
/**************************************************************************\
* GetWindowContextHelpId * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, DWORD, DUMMYCALLINGTYPE, GetWindowContextHelpId, HWND, hwnd) DWORD GetWindowContextHelpId( HWND hwnd) { return (BOOL)NtUserCallHwnd(hwnd, SFI__GETWINDOWCONTEXTHELPID); }
VOID SetWindowState( PWND pwnd, UINT flags) { if (TestWF(pwnd, flags) != LOBYTE(flags)) { NtUserCallHwndParam(HWq(pwnd), flags, SFI_SETWINDOWSTATE); } }
VOID ClearWindowState( PWND pwnd, UINT flags) { if (TestWF(pwnd, flags)) { NtUserCallHwndParam(HWq(pwnd), flags, SFI_CLEARWINDOWSTATE); } }
/**************************************************************************\
* PostQuitMessage * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, PostQuitMessage, int, nExitCode) VOID PostQuitMessage( int nExitCode) { NtUserCallOneParam(nExitCode, SFI__POSTQUITMESSAGE); }
/**************************************************************************\
* REGISTERUSERHUNAPPHANDLERS * * 01-Apr-1992 jonpa Created \**************************************************************************/ BOOL RegisterUserHungAppHandlers( PFNW32ET pfnW32EndTask, HANDLE hEventWowExec) { return (BOOL)NtUserCallTwoParam((ULONG_PTR)pfnW32EndTask, (ULONG_PTR)hEventWowExec, SFI_XXXREGISTERUSERHUNGAPPHANDLERS); }
/**************************************************************************\
* ReleaseCapture * * 22-Jul-1991 mikeke Created \**************************************************************************/ BOOL ReleaseCapture( VOID) { return (BOOL)NtUserCallNoParam(SFI_XXXRELEASECAPTURE); }
/**************************************************************************\
* ReplyMessage * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ReplyMessage, LRESULT, pp1) BOOL ReplyMessage( LRESULT pp1) { return (BOOL)NtUserCallOneParam(pp1, SFI__REPLYMESSAGE); }
/**************************************************************************\
* RegisterSystemThread * * 21-Jun-1994 johnc Created \**************************************************************************/ FUNCLOGVOID2(LOG_GENERAL, DUMMYCALLINGTYPE, RegisterSystemThread, DWORD, dwFlags, DWORD, dwReserved) VOID RegisterSystemThread( DWORD dwFlags, DWORD dwReserved) { NtUserCallTwoParam(dwFlags, dwReserved, SFI_ZZZREGISTERSYSTEMTHREAD); }
/**************************************************************************\
* SetCaretBlinkTime * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCaretBlinkTime, UINT, wMSeconds) BOOL SetCaretBlinkTime( UINT wMSeconds) { return (BOOL)NtUserCallOneParam(wMSeconds, SFI__SETCARETBLINKTIME); }
/**************************************************************************\
* SetCaretPos * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCaretPos, int, X, int, Y) BOOL SetCaretPos( int X, int Y) { return (BOOL)NtUserCallTwoParam(X, Y, SFI_ZZZSETCARETPOS); }
/**************************************************************************\
* SetCursorPos * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetCursorPos, int, X, int, Y) BOOL SetCursorPos( int X, int Y) { return (BOOL)NtUserCallTwoParam(X, Y, SFI_ZZZSETCURSORPOS); }
/**************************************************************************\
* SetDoubleClickTime * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetDoubleClickTime, UINT, cms) BOOL SetDoubleClickTime( UINT cms) { return (BOOL)NtUserCallOneParam(cms, SFI__SETDOUBLECLICKTIME); }
/**************************************************************************\
* SetForegroundWindow * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetForegroundWindow, HWND, hwnd) BOOL SetForegroundWindow( HWND hwnd) { return NtUserSetForegroundWindow(hwnd); }
/**************************************************************************\
* AllowSetForegroundWindow * * 28-Jan-1998 GerardoB Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, AllowSetForegroundWindow, DWORD, dwProcessId) BOOL AllowSetForegroundWindow( DWORD dwProcessId) { return (BOOL)NtUserCallOneParam(dwProcessId, SFI_XXXALLOWSETFOREGROUNDWINDOW); }
/**************************************************************************\
* LockSetForegroundWindow * * 07-Apr-1998 GerardoB Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, LockSetForegroundWindow, UINT, uLockCode) BOOL LockSetForegroundWindow( UINT uLockCode) { return (BOOL)NtUserCallOneParam(uLockCode, SFI__LOCKSETFOREGROUNDWINDOW); }
/**************************************************************************\
* ShowCursor * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, int, DUMMYCALLINGTYPE, ShowCursor, BOOL, bShow) int ShowCursor( BOOL bShow) { return (int)NtUserCallOneParam(bShow, SFI_ZZZSHOWCURSOR); }
/**************************************************************************\
* ShowOwnedPopups * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, ShowOwnedPopups, HWND, hwnd, BOOL, fShow) BOOL ShowOwnedPopups( HWND hwnd, BOOL fShow) { return (BOOL)NtUserCallHwndParamLock(hwnd, fShow, SFI_XXXSHOWOWNEDPOPUPS); }
/**************************************************************************\
* ShowStartGlass * * 10-Sep-1992 scottlu Created \**************************************************************************/ FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, ShowStartGlass, DWORD, dwTimeout) VOID ShowStartGlass( DWORD dwTimeout) { NtUserCallOneParam(dwTimeout, SFI_ZZZSHOWSTARTGLASS); }
/**************************************************************************\
* SwapMouseButton * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SwapMouseButton, BOOL, fSwap) BOOL SwapMouseButton( BOOL fSwap) { return (BOOL)NtUserCallOneParam(fSwap, SFI__SWAPMOUSEBUTTON); }
/**************************************************************************\
* TileChildWindows * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, TileChildWindows, HWND, hwndParent, UINT, flags) BOOL TileChildWindows( HWND hwndParent, UINT flags) { return (BOOL)TileWindows(hwndParent, flags, NULL, 0, NULL); }
/**************************************************************************\
* UnhookWindowsHook * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, UnhookWindowsHook, int, nCode, HOOKPROC, pfnFilterProc) BOOL UnhookWindowsHook( int nCode, HOOKPROC pfnFilterProc) { return (BOOL)NtUserCallTwoParam(nCode, (ULONG_PTR)pfnFilterProc, SFI_ZZZUNHOOKWINDOWSHOOK); }
/**************************************************************************\
* UpdateWindow * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, UpdateWindow, HWND, hwnd) BOOL UpdateWindow( HWND hwnd) { PWND pwnd;
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return FALSE; }
/*
* Don't need to do anything if this window does not need any painting * and it has no child windows */ if (!NEEDSPAINT(pwnd) && (pwnd->spwndChild == NULL)) { return TRUE; }
return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXUPDATEWINDOW); }
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, RegisterShellHookWindow, HWND, hwnd) BOOL RegisterShellHookWindow( HWND hwnd) { return (BOOL)NtUserCallHwnd(hwnd, SFI__REGISTERSHELLHOOKWINDOW); }
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DeregisterShellHookWindow, HWND, hwnd) BOOL DeregisterShellHookWindow( HWND hwnd) { return (BOOL)NtUserCallHwnd(hwnd, SFI__DEREGISTERSHELLHOOKWINDOW); }
/**************************************************************************\
* UserRealizePalette * * 13-Nov-1992 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, UserRealizePalette, HDC, hdc) UINT UserRealizePalette( HDC hdc) { return (UINT)NtUserCallOneParam((ULONG_PTR)hdc, SFI_XXXREALIZEPALETTE); }
/**************************************************************************\
* WindowFromDC * * 22-Jul-1991 mikeke Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, HWND, DUMMYCALLINGTYPE, WindowFromDC, HDC, hdc) HWND WindowFromDC( HDC hdc) { return (HWND)NtUserCallOneParam((ULONG_PTR)hdc, SFI__WINDOWFROMDC); }
/***************************************************************************\
* GetWindowRgn * * Parameters: * hwnd -- Window handle * hrgn -- Region to copy window region into * * Returns: * Region complexity code * * Comments: * hrgn gets returned in window rect coordinates (not client rect) * * 30-JUl-1994 ScottLu Created. \***************************************************************************/ FUNCLOG2(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetWindowRgn, HWND, hwnd, HRGN, hrgn) int GetWindowRgn( HWND hwnd, HRGN hrgn) { int code; PWND pwnd;
if (hrgn == NULL) { return ERROR; }
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return ERROR; }
/*
* If there is no region selected into this window, then return error */ if (pwnd->hrgnClip == NULL || TestWF(pwnd, WFMAXFAKEREGIONAL)) { return ERROR; }
code = CombineRgn(hrgn, KHRGN_TO_HRGN(pwnd->hrgnClip), NULL, RGN_COPY); if (code == ERROR) { return ERROR; }
/*
* Offset it to window rect coordinates (not client rect coordinates) */ if (GETFNID(pwnd) != FNID_DESKTOP) { code = OffsetRgn(hrgn, -pwnd->rcWindow.left, -pwnd->rcWindow.top); }
if (TestWF(pwnd, WEFLAYOUTRTL)) { MirrorRgn(HW(pwnd), hrgn); }
return code; }
/***************************************************************************\
* GetWindowRgnBox * * Parameters: * hwnd -- Window handle * lprc -- Rectangle for bounding box * * Returns: * Region complexity code * * Comments: * This function is designed after GetWindowRgn(), but does not require * an HRGN to be passed in since it only returns the complexity code. * * 06-JUN-2000 JStall Created. \***************************************************************************/ FUNCLOG2(LOG_GENERAL, int, DUMMYCALLINGTYPE, GetWindowRgnBox, HWND, hwnd, LPRECT, lprc) int GetWindowRgnBox( HWND hwnd, LPRECT lprc) { int code; PWND pwnd;
if (lprc == NULL) { return ERROR; }
if ((pwnd = ValidateHwnd(hwnd)) == NULL) { return ERROR; }
/*
* If there is no region selected into this window, then return error */ if (pwnd->hrgnClip == NULL || TestWF(pwnd, WFMAXFAKEREGIONAL)) { return ERROR; }
code = GetRgnBox(KHRGN_TO_HRGN(pwnd->hrgnClip), lprc); if (code == ERROR) { return ERROR; }
/*
* Offset it to window rect coordinates (not client rect coordinates) */ if (GETFNID(pwnd) != FNID_DESKTOP) { OffsetRect(lprc, -pwnd->rcWindow.left, -pwnd->rcWindow.top); }
if (TestWF(pwnd, WEFLAYOUTRTL)) { MirrorWindowRect(pwnd, lprc); }
return code; }
/***************************************************************************\
* GetActiveKeyboardName * * Retrieves the active keyboard layout ID from the registry. * * 01-11-95 JimA Created. * 03-06-95 GregoryW Modified to use new registry layout \***************************************************************************/ VOID GetActiveKeyboardName( LPWSTR lpszName) { LPTSTR szKbdActive = TEXT("Active"); LPTSTR szKbdLayout = TEXT("Keyboard Layout"); LPTSTR szKbdLayoutPreload = TEXT("Keyboard Layout\\Preload"); NTSTATUS rc; DWORD cbSize; HANDLE UserKeyHandle, hKey, hKeyPreload; OBJECT_ATTRIBUTES ObjA; UNICODE_STRING UnicodeString; ULONG CreateDisposition; struct { KEY_VALUE_PARTIAL_INFORMATION KeyInfo; WCHAR KeyLayoutId[KL_NAMELENGTH]; } KeyValueId;
/*
* Load initial keyboard name ( HKEY_CURRENT_USER\Keyboard Layout\Preload\1 ) */ rc = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserKeyHandle); if (!NT_SUCCESS(rc)) { RIPMSGF1(RIP_WARNING, "Could NOT open HKEY_CURRENT_USER (%lx).", rc); wcscpy(lpszName, L"00000409"); return; }
RtlInitUnicodeString(&UnicodeString, szKbdLayoutPreload); InitializeObjectAttributes(&ObjA, &UnicodeString, OBJ_CASE_INSENSITIVE, UserKeyHandle, NULL ); rc = NtOpenKey(&hKey, KEY_ALL_ACCESS, &ObjA ); if (NT_SUCCESS(rc)) { /*
* Query the value from the registry. */ RtlInitUnicodeString(&UnicodeString, L"1");
rc = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyValueId, sizeof(KeyValueId), &cbSize );
if (rc == STATUS_BUFFER_OVERFLOW) { RIPMSGF0(RIP_WARNING, "Buffer overflow."); rc = STATUS_SUCCESS; } if (NT_SUCCESS(rc)) { wcsncpycch(lpszName, (LPWSTR)KeyValueId.KeyInfo.Data, KL_NAMELENGTH - 1); lpszName[KL_NAMELENGTH - 1] = L'\0'; } else { /*
* Error reading value...use default */ wcscpy(lpszName, L"00000409"); }
NtClose(hKey); NtClose(UserKeyHandle); if (IS_IME_ENABLED()) { CheckValidLayoutName(lpszName); } return; }
/*
* NOTE: The code below is only executed the first time a user logs * on after an upgrade from NT3.x to NT4.0. * * The Preload key does not exist in the registry. Try reading the * old registry entry "Keyboard Layout\Active". If it exists, we * convert it to the new style Preload key. */ RtlInitUnicodeString(&UnicodeString, szKbdLayout); InitializeObjectAttributes(&ObjA, &UnicodeString, OBJ_CASE_INSENSITIVE, UserKeyHandle, NULL ); rc = NtOpenKey(&hKey, KEY_ALL_ACCESS, &ObjA);
NtClose(UserKeyHandle);
if (!NT_SUCCESS(rc)) { RIPMSGF1(RIP_WARNING, "Could not determine active keyboard layout 0x%x.", rc); wcscpy(lpszName, L"00000409"); return; }
/*
* Query the value from the registry. */ RtlInitUnicodeString(&UnicodeString, szKbdActive);
rc = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyValueId, sizeof(KeyValueId), &cbSize );
if (rc == STATUS_BUFFER_OVERFLOW) { RIPMSGF0(RIP_WARNING, "Buffer overflow."); rc = STATUS_SUCCESS; } if (NT_SUCCESS(rc)) { wcsncpycch(lpszName, (LPWSTR)KeyValueId.KeyInfo.Data, KL_NAMELENGTH - 1); lpszName[KL_NAMELENGTH - 1] = L'\0'; } else { /*
* Error reading value...use default */ RIPMSGF1(RIP_WARNING, "Could not query active keyboard layout 0x%x.", rc); wcscpy(lpszName, L"00000409"); NtClose(hKey); return; }
/*
* if 'Active' keyboard layout is for Japanese/Korean layout. just put * IME prefix, because user prefer to have keyboard layout with IME as * default. */ if (IS_IME_ENABLED()) { UINT wLanguageId = (UINT)wcstoul(lpszName, NULL, 16);
/*
* Default keyboard layout values. * * [LATER, if needed] * * The hard-codeed default value might be wanted * come from registry or somewhere... */ CONST LPWSTR lpszJapaneseDefaultLayout = L"E0010411"; CONST LPWSTR lpszKoreanDefaultLayout = L"E0010412";
/*
* Need to mask off hi-word to look up locale ID, because * NEC PC-9800 Series version of Windows NT 3.5 contains * bogus value in hi-word. */ wLanguageId &= 0x0000FFFF;
if (PRIMARYLANGID(wLanguageId) == LANG_JAPANESE) {
/*
* Set Japanese default layout Id. */ wcscpy(lpszName,lpszJapaneseDefaultLayout);
} else if (PRIMARYLANGID(wLanguageId) == LANG_KOREAN) {
/*
* Set Korean default layout Id. */ wcscpy(lpszName,lpszKoreanDefaultLayout); } }
/*
* We have the Active value. Now create the Preload key. */ RtlInitUnicodeString(&UnicodeString, L"Preload"); InitializeObjectAttributes(&ObjA, &UnicodeString, OBJ_CASE_INSENSITIVE, hKey, NULL ); rc = NtCreateKey(&hKeyPreload, STANDARD_RIGHTS_WRITE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | KEY_CREATE_SUB_KEY, &ObjA, 0, NULL, 0, &CreateDisposition );
if (!NT_SUCCESS(rc)) { RIPMSGF1(RIP_WARNING, "Could NOT create Preload key (0x%x).", rc); NtClose(hKey); return; }
/*
* Set the new value entry. */ RtlInitUnicodeString(&UnicodeString, L"1"); rc = NtSetValueKey(hKeyPreload, &UnicodeString, 0, REG_SZ, lpszName, (wcslen(lpszName) + 1) * sizeof(WCHAR));
if (!NT_SUCCESS(rc)) { RIPMSGF1(RIP_WARNING, "Could NOT create value entry 1 for Preload key (0x%x).", rc); NtClose(hKey); NtClose(hKeyPreload); return; }
/*
* Success: attempt to delete the Active value key. */ RtlInitUnicodeString(&UnicodeString, szKbdActive); rc = NtDeleteValueKey(hKey, &UnicodeString);
if (!NT_SUCCESS(rc)) { RIPMSGF1(RIP_WARNING, "Could NOT delete value key 'Active'.", rc); }
NtClose(hKey); NtClose(hKeyPreload); }
/***************************************************************************\
* LoadPreloadKeyboardLayouts * * Loads the keyboard layouts stored under the Preload key in the user's * registry. The first layout, the default, was already loaded. * * 03-06-95 GregoryW Created. \***************************************************************************/
// size allows up to 999 preloaded!!!!!
#define NSIZEPRELOAD (4)
VOID LoadPreloadKeyboardLayouts( VOID) { UINT i; WCHAR szPreLoadee[NSIZEPRELOAD]; WCHAR lpszName[KL_NAMELENGTH];
if (!ISREMOTESESSION()) { /*
* Console doesn't have a client layout, so start from 2. */ i = 2; } else { /*
* Client might have specified a keyboard layout, if this * is so, then Preload\1 was not loaded, so start from 1. */ i = 1; }
for (; i < 1000; i++) { wsprintf(szPreLoadee, L"%d", i ); if ((GetPrivateProfileStringW( L"Preload", szPreLoadee, L"", lpszName, KL_NAMELENGTH, L"keyboardlayout.ini") == -1 ) || (*lpszName == L'\0')) { break; } LoadKeyboardLayoutW(lpszName, KLF_REPLACELANG |KLF_SUBSTITUTE_OK |KLF_NOTELLSHELL); } }
LPWSTR GetKeyboardDllName( LPWSTR pwszLibIn, LPWSTR pszKLName, LANGID langid, PUINT puFlags, PUINT pKbdInputLocale) { NTSTATUS Status; WCHAR awchKL[KL_NAMELENGTH]; WCHAR awchKLRegKey[NSZKLKEY]; LPWSTR lpszKLRegKey = &awchKLRegKey[0]; LPWSTR pwszLib; LPWSTR pwszId; UINT wLayoutId; UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES OA; HANDLE hKey; DWORD cbSize; struct { KEY_VALUE_PARTIAL_INFORMATION KeyInfo; WCHAR awchLibName[CCH_KL_LIBNAME]; } KeyFile; struct { KEY_VALUE_PARTIAL_INFORMATION KeyInfo; WCHAR awchId[CCH_KL_ID]; } KeyId; struct { KEY_VALUE_PARTIAL_INFORMATION KeyInfo; DWORD Attributes; } KeyAttributes;
if (pszKLName == NULL) { return NULL; }
if (langid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)) { langid = (UINT)wcstoul(pszKLName, NULL, 16); TAGMSGF1(DBGTAG_KBD, "langid is acquired from pszKLName: %04x", langid); } else { TAGMSGF1(DBGTAG_KBD, "langid is passed in: %04x", langid); }
/*
* Substitute Layout if required. */ if (*puFlags & KLF_SUBSTITUTE_OK) { GetPrivateProfileStringW(L"Substitutes", pszKLName, pszKLName, awchKL, ARRAY_SIZE(awchKL), L"keyboardlayout.ini"); /*
* #273562 : Flush the registry cache, because the cpanel applet * destroys and recreates the Substitutes section a lot, which * would otherwise leave us with STATUS_KEY_DELETED. */ WritePrivateProfileStringW(NULL, NULL, NULL, NULL);
awchKL[KL_NAMELENGTH - 1] = L'\0'; wcscpy(pszKLName, awchKL); }
wLayoutId = (UINT)wcstoul(pszKLName, NULL, 16);
/*
* Get DLL name from the registry, load it, and get the entry point. */ pwszLib = NULL; wcscpy(lpszKLRegKey, szKLKey); wcscat(lpszKLRegKey, pszKLName); RtlInitUnicodeString(&UnicodeString, lpszKLRegKey); InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) { /*
* Read the "Layout File" value. */ RtlInitUnicodeString(&UnicodeString, szKLFile);
Status = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyFile, sizeof(KeyFile), &cbSize); if (Status == STATUS_BUFFER_OVERFLOW) { RIPMSGF0(RIP_WARNING, "(Layout File) - Buffer overflow."); Status = STATUS_SUCCESS; } if (NT_SUCCESS(Status)) { pwszLib = (LPWSTR)KeyFile.KeyInfo.Data; pwszLib[CCH_KL_LIBNAME - 1] = L'\0'; } else { RIPMSGF1(RIP_WARNING, "Failed to get the DLL name for %ws", pszKLName); }
RtlInitUnicodeString(&UnicodeString, szKLAttributes); Status = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyAttributes, sizeof(KeyAttributes), &cbSize); if (NT_SUCCESS(Status)) { if ((*((PDWORD)KeyAttributes.KeyInfo.Data) & ~KLF_ATTRMASK) != 0) { RIPMSGF1(RIP_WARNING, "Unexpected attributes %lx", *((PDWORD)KeyAttributes.KeyInfo.Data)); }
*puFlags |= (*(PDWORD)KeyAttributes.KeyInfo.Data & KLF_ATTRMASK); }
/*
* If the high word of wLayoutId is 0xE??? then this is an IME based * keyboard layout. */ if (IS_IME_KBDLAYOUT(wLayoutId)) { wLayoutId = (UINT)HIWORD(wLayoutId); } else if (HIWORD(wLayoutId)) { /*
* If the high word of wLayoutId is non-null then read the * "Layout ID" value. Layout IDs start at 1, increase * sequentially and are unique. */ RtlInitUnicodeString(&UnicodeString, szKLId);
Status = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyId, sizeof(KeyId), &cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) { RIPMSGF0(RIP_WARNING, "Buffer overflow."); Status = STATUS_SUCCESS; } if (NT_SUCCESS(Status)) { pwszId = (LPWSTR)KeyId.KeyInfo.Data; pwszId[CCH_KL_ID - 1] = L'\0'; wLayoutId = (wcstol(pwszId, NULL, 16) & 0x0fff) | 0xf000; } else { wLayoutId = (UINT)0xfffe ; // error in layout ID, load separately
} } NtClose(hKey); } else { /*
* Get DLL name from the registry, load it, and get the entry point. */ pwszLib = NULL; RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Keyboard Layout"); InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) { RtlInitUnicodeString(&UnicodeString, pszKLName);
Status = NtQueryValueKey(hKey, &UnicodeString, KeyValuePartialInformation, &KeyFile, sizeof(KeyFile), &cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) { RIPMSGF0(RIP_WARNING, "Buffer overflow."); Status = STATUS_SUCCESS; } if (NT_SUCCESS(Status)) { pwszLib = (LPWSTR)KeyFile.KeyInfo.Data; pwszLib[CCH_KL_LIBNAME - 1] = L'\0'; }
NtClose(hKey); }
if (pwszLib == NULL) { RIPMSGF1(RIP_WARNING, "Failed to get the library name for %ws", pszKLName); } }
*pKbdInputLocale = (UINT)MAKELONG(LOWORD(langid),LOWORD(wLayoutId));
if (pwszLib == NULL) { if (ISREMOTESESSION() && IS_IME_KBDLAYOUT(wLayoutId)) { /*
* -- port from HYDRA -- * Could not find the keyboard KL for FE, so give them some reasonable one. * If the high word of wLayoutId is 0xE??? then this is an IME based * keyboard layout. * And, the safe KL name is KBDJPN.DLL for Japanese. * or KBDKOR.DLL for Korean * or KBDUS.DLL for other Far East */ if (PRIMARYLANGID(langid) == LANG_JAPANESE) { pwszLib = pwszKLLibSafetyJPN; *pKbdInputLocale = wKbdLocaleSafetyJPN; } else if (PRIMARYLANGID(langid) == LANG_KOREAN) { pwszLib = pwszKLLibSafetyKOR; *pKbdInputLocale = wKbdLocaleSafetyKOR; } else { pwszLib = pwszKLLibSafety; *pKbdInputLocale = MAKELONG(LOWORD(langid), LOWORD(langid)); } } else if (*puFlags & KLF_INITTIME) { pwszLib = pwszKLLibSafety; *pKbdInputLocale = wKbdLocaleSafety; } else { RIPMSG1(RIP_WARNING, "no DLL name for %ws", pszKLName); /*
* We're going to use the fallback layout... * This could happen when IMM32 is trying to unload the IME, * by making any non IME keyboard layout tentatively active. */ pwszLib = pwszKLLibSafety; *pKbdInputLocale = wKbdLocaleSafety; } }
if (pwszLib) { wcscpy(pwszLibIn, pwszLib); pwszLib = pwszLibIn; }
return pwszLib; }
/***************************************************************************\
* OpenKeyboardLayoutFile * * Opens a layout file and computes the table offset. * * 01-11-95 JimA Moved LoadLibrary code from server. \***************************************************************************/ HANDLE OpenKeyboardLayoutFileWorker( LPWSTR pwszLib, LPWSTR lpszKLName, CONST UINT* puFlags, PUINT poffTable, OUT OPTIONAL PKBDTABLE_MULTI_INTERNAL pKbdTableMultiIn) { WCHAR awchRealLayoutFile[MAX_PATH]; HANDLE hLibModule, hLibMulti = NULL; WCHAR awchModName[MAX_PATH];
PKBDTABLES (*pfn)(void); // @1
PKBDNLSTABLES (* pfnNls)(void); // @2
BOOL (*pfnLayerNT4)(LPWSTR); // @3
BOOL (*pfnLayer)(HKL, LPWSTR, PCLIENTKEYBOARDTYPE, LPVOID); // @5
BOOL (*pfnMulti)(PKBDTABLE_MULTI); // @6
TAGMSGF1(DBGTAG_KBD, "opening '%S'", pwszLib);
RetryLoad: hLibModule = LoadLibraryW(pwszLib);
if (hLibModule == NULL) { RIPMSG1(RIP_WARNING, "Keyboard Layout: cannot load %ws", pwszLib);
/*
* It is OK to fail to load DLL here. If this ever happens, the * fallback keyboard layout built in win32k.sys shall be used. */ return NULL; }
if (pwszLib != pwszKLLibSafety) { /*
* if the layout driver is not "REAL" layout driver, the driver has * "3" or "5" entry point, then we call this to get real layout driver.. * This is neccesary for Japanese and Korean systems. because their * keyboard layout driver is "KBDJPN.DLL" or "KBDKOR.DLL", but its * "REAL" driver becomes different depending their keyboard hardware. */
/*
* Get the entrypoints. */ pfnLayerNT4 = (BOOL(*)(LPWSTR))GetProcAddress(hLibModule, (LPCSTR)3); pfnLayer = (BOOL(*)(HKL, LPWSTR, PCLIENTKEYBOARDTYPE, LPVOID))GetProcAddress(hLibModule, (LPCSTR)5);
if (pKbdTableMultiIn && !ISREMOTESESSION()) { pfnMulti = (BOOL(*)(PKBDTABLE_MULTI))GetProcAddress(hLibModule, (LPCSTR)6); } else { pfnMulti = NULL; }
/*
* Firstly check if multiple layout is included. * This needs to be done before the dll name is redirected to * the real one (if layered). */ if (pfnMulti) { UserAssert(pKbdTableMultiIn); UserAssert(!ISREMOTESESSION());
if (pfnMulti(&pKbdTableMultiIn->multi)) { UINT i;
/*
* Do multi layout stuff only if the layout dll returns * a legitimate result. */ if (pKbdTableMultiIn->multi.nTables < KBDTABLE_MULTI_MAX) { for (i = 0; i < pKbdTableMultiIn->multi.nTables; ++i) { UINT uiOffset;
TAGMSGF2(DBGTAG_KBD | RIP_THERESMORE, "opening %d, %S", i, pKbdTableMultiIn->multi.aKbdTables[i].wszDllName);
UserAssert(i < KBDTABLE_MULTI_MAX);
pKbdTableMultiIn->files[i].hFile = OpenKeyboardLayoutFileWorker(pKbdTableMultiIn->multi.aKbdTables[i].wszDllName, NULL, puFlags, &uiOffset, NULL); TAGMSG1(DBGTAG_KBD, "hFile = %p", pKbdTableMultiIn->files[i].hFile); if (pKbdTableMultiIn->files[i].hFile) { pKbdTableMultiIn->files[i].wTable = LOWORD(uiOffset); pKbdTableMultiIn->files[i].wNls = HIWORD(uiOffset); } } } else { pKbdTableMultiIn->multi.nTables = 0; RIPMSGF2(RIP_ERROR, "KL=%S returned bogus nTables=%x", lpszKLName, pKbdTableMultiIn->multi.nTables); } } }
/*
* If there are private entries, call them. */ if (pfnLayer || pfnLayerNT4) { HKL hkl; UNICODE_STRING UnicodeString; CLIENTKEYBOARDTYPE clientKbdType; PCLIENTKEYBOARDTYPE pClientKbdType = NULL;
UserAssert(lpszKLName);
RtlInitUnicodeString(&UnicodeString, lpszKLName); RtlUnicodeStringToInteger(&UnicodeString, 0x10, (PULONG)&hkl);
/*
* When we reach here, the layout DLL may have KBDNLSTABLE * even if we fail from now on. Our temporary layout * dll should have the fallback tables for just in case. */
if (ISREMOTESESSION() && GetClientKeyboardType(&clientKbdType)) { pClientKbdType = &clientKbdType; }
/*
* Call the entry. * a. NT5 / Hydra (oridinal=5) * b. NT4 compatible (3) */ if ((pfnLayer && pfnLayer(hkl, awchRealLayoutFile, pClientKbdType, NULL)) || (pfnLayerNT4 && pfnLayerNT4(awchRealLayoutFile))) {
HANDLE hLibModuleNew; /*
* Try to load "REAL" keyboard layout file. */ TAGMSG1(DBGTAG_KBD, "awchRealLayoutFile='%S'", awchRealLayoutFile); if (hLibModuleNew = LoadLibraryW(awchRealLayoutFile)) { /*
* Set "REAL" layout file name. */ pwszLib = awchRealLayoutFile; /*
* Unload temporary layout driver. */ FreeLibrary(hLibModule); /*
* Updates it. */ hLibModule = hLibModuleNew; } } } }
/*
* HACK Part 1! Get the pointer to the layout table and * change it to a virtual offset. The server will then * use this offset when poking through the file header to * locate the table within the file. */ pfn = (PKBDTABLES(*)(void))GetProcAddress(hLibModule, (LPCSTR)1); if (pfn == NULL) { RIPMSGF0(RIP_ERROR, "cannot get proc addr of '1'"); if (pKbdTableMultiIn) { /*
* Main load somehow failed. Need to clean up * the dynamic layout switching stuff. */ UINT i;
RIPMSGF0(RIP_WARNING, "multi table exists, cleaning up");
for (i = 0; i < pKbdTableMultiIn->multi.nTables && i < KBDTABLE_MULTI_MAX; ++i) { if (pKbdTableMultiIn->files[i].hFile) { NtClose(pKbdTableMultiIn->files[i].hFile); pKbdTableMultiIn->files[i].hFile = NULL; } } pKbdTableMultiIn->multi.nTables = 0; } if ((*puFlags & KLF_INITTIME) && (pwszLib != pwszKLLibSafety)) { pwszLib = pwszKLLibSafety; goto RetryLoad; } return NULL; } *poffTable = (UINT)((PBYTE)pfn() - (PBYTE)hLibModule);
if (pKbdTableMultiIn) { /*
* Save the toplevel Dll name */ lstrcpyn(pKbdTableMultiIn->wszDllName, pwszLib, ARRAY_SIZE(pKbdTableMultiIn->wszDllName)); pKbdTableMultiIn->wszDllName[ARRAY_SIZE(pKbdTableMultiIn->wszDllName) - 1] = 0; TAGMSGF1(DBGTAG_KBD, " real DllName is '%ls'", pKbdTableMultiIn->wszDllName); }
pfnNls = (PKBDNLSTABLES(*)(void))GetProcAddress(hLibModule, (LPCSTR)2); if (pfnNls != NULL) { UINT offNlsTable;
offNlsTable = (UINT)((PBYTE)pfnNls() - (PBYTE)hLibModule);
TAGMSGF2(DBGTAG_KBD | RIP_THERESMORE, "Offset to KBDTABLES = %d (%x)", *poffTable, *poffTable); TAGMSGF2(DBGTAG_KBD, "Offset to KBDNLSTABLES = %d (%x)", offNlsTable, offNlsTable);
/*
* Combine these offsets... * * LOWORD(*poffTable) = Offset to KBDTABLES. * HIWORD(*poffTable) = Offset to KBDNLSTABLES. */ *poffTable |= (offNlsTable << 16); }
/*
* Open the dll for read access. */ GetModuleFileName(hLibModule, awchModName, ARRAY_SIZE(awchModName)); FreeLibrary(hLibModule);
return CreateFileW(awchModName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); }
HANDLE OpenKeyboardLayoutFile( LPWSTR lpszKLName, LANGID langid, PUINT puFlags, PUINT poffTable, PUINT pKbdInputLocale, OUT OPTIONAL PKBDTABLE_MULTI_INTERNAL pKbdTableMultiIn) { LPWSTR pwszLib; WCHAR awchModName[MAX_PATH];
if (pKbdTableMultiIn) { RtlZeroMemory(pKbdTableMultiIn, sizeof(*pKbdTableMultiIn)); }
pwszLib = GetKeyboardDllName(awchModName, lpszKLName, langid, puFlags, pKbdInputLocale); if (pwszLib == NULL) { return NULL; }
TAGMSG0(DBGTAG_KBD, "================="); TAGMSGF1(DBGTAG_KBD, "loading '%S'", lpszKLName); TAGMSGF1(DBGTAG_KBD, "input locale is %08x", *pKbdInputLocale);
return OpenKeyboardLayoutFileWorker(pwszLib, lpszKLName, puFlags, poffTable, pKbdTableMultiIn); }
/***************************************************************************\
* LoadKeyboardLayoutEx * * Loads a keyboard translation table from a dll, replacing the layout associated * with hkl. This routine is needed to provide Win95 compatibility. * * 10-27-95 GregoryW Created. \***************************************************************************/ HKL LoadKeyboardLayoutWorker( HKL hkl, LPCWSTR lpszKLName, LANGID langid, UINT uFlags, BOOL fFailSafe) { UINT offTable; KBDTABLE_MULTI_INTERNAL kbdTableMulti; UINT i; UINT KbdInputLocale; HANDLE hFile; HKL hKbdLayout; WCHAR awchKL[KL_NAMELENGTH];
TAGMSGF1(DBGTAG_KBD, "called with KLNAME=%S", lpszKLName);
/*
* If there is a substitute keyboard layout OpenKeyboardLayoutFile returns * the substitute keyboard layout name to load. */ wcsncpy(awchKL, lpszKLName, KL_NAMELENGTH - 1); awchKL[KL_NAMELENGTH - 1] = L'\0';
/*
* "langid" is non-zero to propagate the client side * input locale. This should be zero for the console * session. */ UserAssert(langid == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) || ISREMOTESESSION());
/*
* Open the layout file */ hFile = OpenKeyboardLayoutFile(awchKL, langid, &uFlags, &offTable, &KbdInputLocale, &kbdTableMulti); if (hFile == NULL) { RIPMSGF1(RIP_WARNING, "Couldn't open layout file for '%ws'", awchKL); if (!fFailSafe && (uFlags & KLF_FAILSAFE) == 0) { // If not fail safe mode, just bail to fail.
return NULL; } uFlags &= ~KLF_SUBSTITUTE_OK;
/*
* If the first attempt fails, we should not try to setup the * dynamic switching. */ kbdTableMulti.multi.nTables = 0; if (wcscmp(awchKL, L"00000409")) { wcscpy(awchKL, L"00000409"); hFile = OpenKeyboardLayoutFile(awchKL, langid, &uFlags, &offTable, &KbdInputLocale, NULL); } }
/*
* Call the server to read the keyboard tables. Note that the server * will close the file handle when it is done. */ hKbdLayout = _LoadKeyboardLayoutEx(hFile, offTable, &kbdTableMulti, hkl, awchKL, KbdInputLocale, uFlags); NtClose(hFile);
/*
* Free opened files for dynamic layout switching. */ for (i = 0; i < kbdTableMulti.multi.nTables && i < KBDTABLE_MULTI_MAX; ++i) { if (kbdTableMulti.files[i].hFile) { NtClose(kbdTableMulti.files[i].hFile); } }
CliImmInitializeHotKeys(ISHK_ADD, UlongToHandle(KbdInputLocale));
return hKbdLayout; }
FUNCLOG3(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutEx, HKL, hkl, LPCWSTR, lpszKLName, UINT, uFlags) HKL LoadKeyboardLayoutEx( HKL hkl, LPCWSTR lpszKLName, UINT uFlags) { /*
* NULL hkl is not allowed. */ if (hkl == (HKL)NULL) { return NULL; }
return LoadKeyboardLayoutWorker(hkl, lpszKLName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), uFlags, FALSE); }
/***************************************************************************\
* LoadKeyboardLayout * * Loads a keyboard translation table from a dll. * * 01-09-95 JimA Moved LoadLibrary code from server. \***************************************************************************/ FUNCLOG2(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutW, LPCWSTR, lpszKLName, UINT, uFlags) HKL LoadKeyboardLayoutW( LPCWSTR lpszKLName, UINT uFlags) { return LoadKeyboardLayoutWorker(NULL, lpszKLName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), uFlags, FALSE); }
FUNCLOG2(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, LoadKeyboardLayoutA, LPCSTR, lpszKLName, UINT, uFlags) HKL LoadKeyboardLayoutA( LPCSTR lpszKLName, UINT uFlags) { WCHAR awchKLName[MAX_PATH]; LPWSTR lpBuffer = awchKLName;
if (!MBToWCS(lpszKLName, -1, &lpBuffer, sizeof(awchKLName), FALSE)) { return (HKL)NULL; }
return LoadKeyboardLayoutW(awchKLName, uFlags); }
BOOL UnloadKeyboardLayout( IN HKL hkl) { BOOL fRet = NtUserUnloadKeyboardLayout(hkl);
if (fRet) { CliImmInitializeHotKeys(ISHK_REMOVE, hkl); return TRUE; }
return FALSE; }
/**************************************************************************\
* GetKeyboardLayout * * 01-17-95 GregoryW Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, HKL, DUMMYCALLINGTYPE, GetKeyboardLayout, DWORD, idThread) HKL GetKeyboardLayout( DWORD idThread) { return (HKL)NtUserCallOneParam(idThread, SFI__GETKEYBOARDLAYOUT); }
FUNCLOGVOID1(LOG_GENERAL, DUMMYCALLINGTYPE, SetDebugErrorLevel, DWORD, dwLevel) VOID SetDebugErrorLevel( DWORD dwLevel) { UNREFERENCED_PARAMETER(dwLevel); }
VOID CheckValidLayoutName( LPWSTR lpszKLName) { UINT wLayoutId; WCHAR awchKLRegKey[NSZKLKEY]; LPWSTR lpszKLRegKey = &awchKLRegKey[0]; OBJECT_ATTRIBUTES OA; HANDLE hKey; UNICODE_STRING UnicodeString;
UserAssert(IS_IME_ENABLED());
wLayoutId = (UINT)wcstoul(lpszKLName, NULL, 16);
if (IS_IME_KBDLAYOUT(wLayoutId)) { /*
* If it's an IME layout, we need to check if the layout name exists * in the HKEY_LOCAL_MACHINE. If we've upgraded from NT 3.51 the * corresponding entry might be lost because those process-type IMEs * that are supported on NT 3.51 are not supported in NT 4.0. */ wcscpy(lpszKLRegKey, szKLKey); wcscat(lpszKLRegKey, lpszKLName); RtlInitUnicodeString(&UnicodeString, lpszKLRegKey); InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
if (NT_SUCCESS(NtOpenKey(&hKey, KEY_READ, &OA))) { NtClose(hKey); } else { /*
* Quick and dirty way to make the fallback name... */ lpszKLName[0] = lpszKLName[1] = lpszKLName[2] = lpszKLName[3] = L'0'; } } }
/**************************************************************************\
* GetProcessDefaultLayout * * 22-Jan-1998 SamerA Created \**************************************************************************/ BOOL WINAPI GetProcessDefaultLayout( DWORD *pdwDefaultLayout) { return (BOOL)NtUserCallOneParam((ULONG_PTR)pdwDefaultLayout, SFI__GETPROCESSDEFAULTLAYOUT); }
/**************************************************************************\
* SetProcessDefaultLayout * * 22-Jan-1998 SamerA Created \**************************************************************************/ FUNCLOG1(LOG_GENERAL, BOOL, WINAPI, SetProcessDefaultLayout, DWORD, dwDefaultLayout) BOOL WINAPI SetProcessDefaultLayout( DWORD dwDefaultLayout) { return (BOOL)NtUserCallOneParam(dwDefaultLayout, SFI__SETPROCESSDEFAULTLAYOUT); }
/***************************************************************************\
* IsWinEventHookInstalled * * History: * Jul-18-2000 DwayneN Created \***************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, IsWinEventHookInstalled, DWORD, event) BOOL IsWinEventHookInstalled( DWORD event) { /*
* We need to ensure that we are a GUI thread. If we fail to convert * to a GUI thread, we have to return TRUE to indicate that there might * be a hook installed for the event - since we can't check it for sure. * In reality, any future calls to User APIs like NotifyWinEvent will * probably fail as well, so this is probably a dead-end anyway. */ ConnectIfNecessary(TRUE);
return(FEVENTHOOKED(event)); };
HWND VerNtUserCreateWindowEx( IN DWORD dwExStyle, IN PLARGE_STRING pstrClassName, IN PLARGE_STRING pstrWindowName OPTIONAL, IN DWORD dwStyle, IN int x, IN int y, IN int nWidth, IN int nHeight, IN HWND hwndParent, IN HMENU hmenu, IN HANDLE hModule, IN LPVOID pParam, IN DWORD dwFlags) { HWND hwnd = NULL; PACTIVATION_CONTEXT pActCtx = NULL; LARGE_IN_STRING strClassNameVer; PLARGE_STRING pstrClassNameVer = pstrClassName; NTSTATUS Status; WCHAR ClassNameVer[MAX_ATOM_LEN]; LPWSTR lpClassNameVer; #ifdef LAME_BUTTON
PWND pwnd; #endif
LPWSTR lpDllName = NULL; HMODULE hDllMod = NULL; PREGISTERCLASSNAMEW pRegisterClassNameW = NULL; BOOL bRegistered = FALSE; PACTIVATION_CONTEXT lpActivationContext = NULL;
strClassNameVer.fAllocated = FALSE;
if (GetClientInfo()->dwTIFlags & TIF_16BIT) { /*
* No Fusion redirection for 16BIT apps */ if (!(GetAppCompatFlags2(VERMAX) & GACF2_FORCEFUSION)) { dwFlags &= ~CW_FLAGS_VERSIONCLASS; } }
#ifdef LAZY_CLASS_INIT
LazyInitClasses(); #endif
if (dwFlags & CW_FLAGS_VERSIONCLASS) { /*
* Get the current active App context to be activated whenever we call * the user WndProc. * Be aware that RtlGetActiveActivationContext will increment the pActCtx * ref count for that reason we have to release it in fnNCDESTROY. */ ACTIVATION_CONTEXT_BASIC_INFORMATION ActivationContextInfo = {0}; const ACTIVATIONCONTEXTINFOCLASS ActivationContextInfoClass = ActivationContextBasicInformation; Status = RtlQueryInformationActiveActivationContext( ActivationContextInfoClass, &ActivationContextInfo, sizeof(ActivationContextInfo), NULL ); UserAssert (NT_SUCCESS(Status)); if ((ActivationContextInfo.Flags & ACTIVATION_CONTEXT_FLAG_NO_INHERIT) == 0) { pActCtx = ActivationContextInfo.ActivationContext; } else { RtlReleaseActivationContext(ActivationContextInfo.ActivationContext); }
/*
* Now convert the class name to class name+version. */ if (IS_PTR(pstrClassName)) { lpClassNameVer = ClassNameToVersion((LPWSTR)pstrClassName->Buffer, ClassNameVer, &lpDllName, &lpActivationContext, FALSE); } else { lpClassNameVer = ClassNameToVersion((LPWSTR)pstrClassName, ClassNameVer, &lpDllName, &lpActivationContext, FALSE); } if (lpClassNameVer == NULL) { RIPMSG0(RIP_WARNING, "CreateWindowEx: Couldn't resolve the class name"); return NULL; }
if (IS_PTR(lpClassNameVer)) { RtlInitLargeUnicodeString( (PLARGE_UNICODE_STRING)&strClassNameVer.strCapture, lpClassNameVer, (UINT)-1); pstrClassNameVer = (PLARGE_STRING)&strClassNameVer.strCapture; } else { pstrClassNameVer = (PLARGE_STRING)lpClassNameVer; } }
TryAgain:
hwnd = NtUserCreateWindowEx(dwExStyle, pstrClassName, pstrClassNameVer, pstrWindowName, dwStyle, x, y, nWidth, nHeight, hwndParent, hmenu, hModule, pParam, dwFlags, pActCtx);
/*
* Did we fail to create the window due to the class not being * registered? */ if (hwnd == NULL && (dwFlags & CW_FLAGS_VERSIONCLASS) && lpDllName != NULL && !bRegistered && GetLastError() == ERROR_CANNOT_FIND_WND_CLASS) { /*
* Then try to register it by loading its DLL. Notice that this DLL * will never get unloaded unless we failed to create the window. * But once we created a window by loading this DLL we'll never free it. */ bRegistered = VersionRegisterClass(IS_PTR(pstrClassName) ? pstrClassName->Buffer : pstrClassName, lpDllName, lpActivationContext, &hDllMod); if (bRegistered) { goto TryAgain; } }
if (hwnd == NULL && hDllMod != NULL) { FREE_LIBRARY_SAVE_ERROR(hDllMod); hDllMod = NULL; }
if (lpActivationContext != NULL) { RtlReleaseActivationContext(lpActivationContext); lpActivationContext = NULL; }
#ifdef LAME_BUTTON
pwnd = ValidateHwnd(hwnd); if (pwnd != NULL && TestWF(pwnd, WEFLAMEBUTTON)) { ULONG nCallers; PVOID stack[16]; PVOID pStackTrace = NULL;
/*
* Get a stack trace and store it for use when the button is * pressed. */ nCallers = RtlWalkFrameChain(stack, ARRAY_SIZE(stack), 0); if (nCallers > 0) { pStackTrace = UserLocalAlloc(HEAP_ZERO_MEMORY, (nCallers + 1) * sizeof(PVOID)); if (pStackTrace != NULL) { RtlCopyMemory(pStackTrace, stack, nCallers * sizeof(PVOID));
/*
* NULL terminate the array so we know where it ends. */ ((PVOID*)pStackTrace)[nCallers] = NULL; } }
SetProp(hwnd, MAKEINTATOM(gatomLameButton), pStackTrace); } #endif
CLEANUPLPSTRW(strClassNameVer);
return hwnd; }
/**************************************************************************\
* AllowForegroundActivation * * 26-Apr-2001 clupu Created \**************************************************************************/ VOID AllowForegroundActivation( VOID) { NtUserCallNoParam(SFI__ALLOWFOREGROUNDACTIVATION); }
/**************************************************************************\
* DisableProcessWindowGhosting * * 31-May-2001 msadek Created \**************************************************************************/ VOID DisableProcessWindowsGhosting( VOID) { NtUserCallNoParam(SFI__DISABLEPROCESSWINDOWSGHOSTING); }
/**************************************************************************\
* IsProcess16Bit * * This is a private function for the GDI guys. Exporting this function is * more expendient than fixing the headers such that they can include what * they need to do this themselves. Longterm, this function should be removed * and the headers properly munged. * * 15-Oct-2001 JasonSch Created \**************************************************************************/ BOOL IsProcess16Bit( VOID) { return (GetClientInfo()->CI_flags & CI_16BIT) != 0; }
|