Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3750 lines
102 KiB

/**************************************************************************\
* Module Name: client.c
*
* Client/Server call related routines.
*
* Copyright (c) 1985-1995, Microsoft Corporation
*
* History:
* 04-Dec-1990 SMeans Created.
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
int WOWGetIdFromDirectory(PBYTE presbits, UINT rt);
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);
CONST LPWSTR pwszKLLibSafety = L"kbdus.dll";
CONST UINT wKbdLocaleSafety = 0x04090409;
#define CCH_KL_LIBNAME 256
#define CCH_KL_ID 16
BOOL gfLogonProcess = FALSE;
/***************************************************************************\
* BringWindowToTop (API)
*
*
* History:
* 11-Jul-1991 DarrinM Ported from Win 3.1 sources.
\***************************************************************************/
BOOL BringWindowToTop(
HWND hwnd)
{
return NtUserSetWindowPos(hwnd,
HWND_TOP,
0,
0,
0,
0,
SWP_NOSIZE | SWP_NOMOVE);
}
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);
}
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.
\***************************************************************************/
BOOL WINAPI AdjustWindowRect(
LPRECT lprc,
DWORD style,
BOOL fMenu)
{
ConnectIfNecessary();
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.
\***************************************************************************/
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;
}
}
int WINAPI TranslateAcceleratorA(
HWND hwnd,
HACCEL hAccel,
LPMSG lpMsg)
{
DWORD 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, (DWORD *)&(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(
HANDLE hobjDelete,
DWORD dwFormat)
{
LPMETAFILEPICT lpMFP;
UserAssert(hobjDelete != (HANDLE)0);
switch (dwFormat) {
case CF_BITMAP:
case CF_DSPBITMAP:
case CF_PALETTE:
// Does nothing (should remove).
//
//GdiDeleteLocalObject((ULONG)hobjDelete);
break;
case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
USERGLOBALLOCK(hobjDelete, lpMFP);
if (lpMFP) {
DeleteMetaFile(lpMFP->hMF);
USERGLOBALUNLOCK(hobjDelete);
UserGlobalFree(hobjDelete);
} else {
UserAssert(0);
return FALSE;
}
break;
case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
DeleteEnhMetaFile((HENHMETAFILE)hobjDelete);
break;
default:
//case CF_TEXT:
//case CF_OEMTEXT:
//case CF_UNICODETEXT:
//case CF_LOCALE:
//case CF_DSPTEXT:
//case CF_DIB:
if (UserGlobalFree(hobjDelete)) {
RIPMSG1(RIP_WARNING, "CloseClipboard UserGlobalFree(%lX) Failed\n", hobjDelete);
return FALSE;
}
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->handleClient, phnT->fmt);
LocalFree(phnT);
phnT = phnNext;
}
gphn = NULL;
/*
* Tell wow to cleanup it's clipboard stuff
*/
if (pfnWowEmptyClipBoard) {
pfnWowEmptyClipBoard();
}
RtlLeaveCriticalSection(&gcsClipboard);
}
/***************************************************************************\
* GetClipboardData
*
* 11-Oct-1991 mikeke Created.
\***************************************************************************/
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.
*/
if (uFmt != gcd.uFmtRet) {
LPBYTE lpSrceData;
LPBYTE lpDestData;
LPDWORD lpLocale;
DWORD uLocale;
int iSrce;
int iDest;
UINT uCPage;
SETCLIPBDATA scd;
UINT cbNULL = 0;
lpSrceData = CreateLocalMemHandle(handleServer);
/*
* Allocate space for the converted TEXT data.
*/
if (!(iSrce = GlobalSize(lpSrceData)))
goto AbortDummyHandle;
if ((lpDestData = GlobalAlloc(LPTR, iSrce)) == NULL) {
goto AbortDummyHandle;
}
/*
* 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;
}
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:
UserGlobalFree(lpSrceData);
return NULL;
}
if (!(lpDestData = GlobalReAlloc( lpDestData, iDest, LPTR | LMEM_MOVEABLE)))
goto AbortGetClipData;
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 (!(lpDestData = GlobalReAlloc( lpDestData, iDest, LPTR | LMEM_MOVEABLE)))
goto AbortGetClipData;
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 (!(lpDestData = GlobalReAlloc(lpDestData,
iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE)))
goto AbortGetClipData;
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 (!(lpDestData = GlobalReAlloc(lpDestData,
iDest * sizeof(WCHAR), LPTR | LMEM_MOVEABLE)))
goto AbortGetClipData;
if (MultiByteToWideChar(uCPage,
(DWORD)MB_PRECOMPOSED,
(LPSTR)lpSrceData,
(int)iSrce,
(LPWSTR)lpDestData,
(int)iDest) == 0)
goto AbortGetClipData;
}
break;
}
/*
* Replace the dummy text 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);
UserGlobalFree(lpDestData);
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)LocalAlloc(LPTR, 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:
FIXUP_HANDLE(handleServer);
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:
phnNew->handleClient = CreateLocalMemHandle(handleServer);
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.
*/
#ifdef DEBUG
RIPMSG1(RIP_WARNING, "GetClipboardData unable to convert server handle 0x%lX to client handle\n", handleServer);
#endif
LocalFree(phnNew);
goto Exit;
}
/*
* 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.
\***************************************************************************/
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:
FIXUP_HANDLE(hMem);
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);
break;
case CF_UNICODETEXT:
hServer = ConvertMemHandle(hMem, 2);
break;
case CF_DIB:
hServer = ConvertMemHandle(hMem, 0);
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.
*/
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->handleClient, phnNew->fmt);
/*
* 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)LocalAlloc(LPTR, sizeof(HANDLENODE));
if (phnNew == NULL) {
RIPMSG0(RIP_WARNING, "SetClipboardData: not enough memory\n");
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.
\***************************************************************************/
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.
*/
FIXUP_HANDLE(hdc);
if (hdc == NULL)
return FALSE;
return NtUserCallOneParam((DWORD)hdc, SFI__RELEASEDC);
}
int WINAPI
ToAscii(
UINT wVirtKey,
UINT wScanCode,
PBYTE 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,
PBYTE 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(
(DWORD)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 *
* InvalidateRgn *
* ValidateRgn *
* DrawFocusRect *
* FrameRect *
* ReleaseDC *
* CreateCaret *
* 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 (hrgnUpdate != NULL) {
FIXUP_HANDLE(hrgnUpdate);
if (hrgnUpdate == NULL)
return FALSE;
}
FIXUP_HANDLE(hDC);
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);
}
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 );
}
BOOL DrawIconEx( HDC hdc, int x, int y, HICON hIcon,
int cx, int cy, UINT istepIfAniCur,
HBRUSH hbrFlickerFreeDraw, UINT diFlags)
{
DRAWICONEXDATA did;
HBITMAP hbmT;
HBITMAP hbmMask;
HBITMAP hbmColor;
BOOL retval = FALSE;
HDC hdcr;
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;
if (hbrFlickerFreeDraw) {
FIXUP_HANDLE( hbrFlickerFreeDraw );
if (!hbrFlickerFreeDraw)
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 == 0)
return TRUE;
RtlEnterCriticalSection(&gcsHdc);
/*
* Setup the attributes
*/
if (!cx)
cx = did.cx;
if (!cy)
cy = did.cy / 2;
SetTextColor(hdc, 0x00000000L);
SetBkColor(hdc, 0x00FFFFFFL);
if ((diFlags & DI_MASK) || (did.hbmColor == NULL)) {
hbmMask = did.hbmMask;
FIXUP_HANDLE(hbmMask);
}
if ((diFlags & DI_IMAGE) && (did.hbmColor != NULL)) {
hbmColor = did.hbmColor;
FIXUP_HANDLE(hbmColor);
}
if (diFlags & DI_MASK) {
if (hbmMask) {
hbmT = SelectObject(ghdcBits2, hbmMask);
StretchBlt(hdc,
x,
y,
cx,
cy,
ghdcBits2,
0,
0,
did.cx,
did.cy / 2,
SRCAND);
SelectObject(ghdcBits2,hbmT);
retval = TRUE;
}
}
if (diFlags & DI_IMAGE) {
if (did.hbmColor != NULL) {
if (hbmColor) {
hbmT = SelectObject(ghdcBits2, hbmColor);
StretchBlt(hdc,
x,
y,
cx,
cy,
ghdcBits2,
0,
0,
did.cx,
did.cy / 2,
SRCINVERT);
SelectObject(ghdcBits2, hbmT);
retval = TRUE;
}
} else {
if (hbmMask) {
hbmT = SelectObject(ghdcBits2, hbmMask);
StretchBlt(hdc,
x,
y,
cx,
cy,
ghdcBits2,
0,
did.cy / 2,
did.cx,
did.cy / 2,
SRCINVERT);
SelectObject(ghdcBits2, hbmT);
retval = TRUE;
}
}
}
RtlLeaveCriticalSection(&gcsHdc);
return retval;
}
int WINAPI ExcludeUpdateRgn(HDC hDC,HWND hWnd)
{
FIXUP_HANDLE (hDC);
if (hDC == NULL)
return 0;
return (NtUserExcludeUpdateRgn(hDC,hWnd));
}
BOOL WINAPI InvalidateRgn(HWND hWnd,HRGN hRgn,BOOL bErase)
{
if (hRgn != NULL) {
FIXUP_HANDLE(hRgn);
if (hRgn == NULL)
return FALSE;
}
return NtUserInvalidateRgn(hWnd, hRgn, bErase);
}
BOOL WINAPI ValidateRgn(HWND hWnd,HRGN hRgn)
{
if (hRgn != NULL) {
FIXUP_HANDLE(hRgn);
if (hRgn == NULL)
return FALSE;
}
return (BOOL)NtUserCallHwndParamLock(hWnd, (DWORD)hRgn,
SFI_XXXVALIDATERGN);
}
BOOL WINAPI CreateCaret(HWND hWnd,HBITMAP hBitmap,int nWidth,int nHeight)
{
/*
* NULL is solid; 1 is Gray
*/
if ((DWORD)hBitmap >= 2) {
FIXUP_HANDLE(hBitmap);
if (hBitmap == NULL) {
RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid bitmap %lX", hBitmap);
return FALSE;
}
}
return NtUserCreateCaret(hWnd, hBitmap, nWidth, nHeight);
}
int WINAPI GetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
{
PWND pwnd;
FIXUP_HANDLE(hRgn);
if (hRgn == NULL) {
RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "Invalid region %#lx", 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);
}
HDC WINAPI GetDCEx(
HWND hwnd,
HRGN hrgnClip,
DWORD flags)
{
FIXUP_HANDLEZ(hrgnClip);
return NtUserGetDCEx(
hwnd,
hrgnClip,
flags);
}
/***************************************************************************\
* 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,
HIWORD(prcScroll) == 0 ? SW_FLAG_RC : SW_FLAG_NRC) != ERROR;
}
/***************************************************************************\
*
* SwitchToThisWindow()
*
\***************************************************************************/
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.
\***************************************************************************/
DWORD WaitForInputIdle(
HANDLE hProcess,
DWORD dwMilliseconds)
{
PROCESS_BASIC_INFORMATION processinfo;
DWORD 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 ((DWORD)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 = ((DWORD)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 ((DWORD)hProcess & 0x1) {
return 0;
}
}
RIPERR1(ERROR_INVALID_HANDLE, RIP_WARNING, "WaitForInputIdle invalid process", hProcess);
return (DWORD)-1;
}
idProcess = processinfo.UniqueProcessId;
return NtUserWaitForInputIdle(idProcess, dwMilliseconds, FALSE);
}
DWORD WINAPI MsgWaitForMultipleObjects(
DWORD nCount,
LPHANDLE pHandles,
BOOL fWaitAll,
DWORD dwMilliseconds,
DWORD dwWakeMask)
{
return MsgWaitForMultipleObjectsEx(nCount, pHandles,
dwMilliseconds, dwWakeMask, fWaitAll?MWMO_WAITALL:0);
}
DWORD WINAPI MsgWaitForMultipleObjectsEx(
DWORD nCount,
LPHANDLE pHandles,
DWORD dwMilliseconds,
DWORD dwWakeMask,
DWORD dwFlags)
{
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);
if (dwFlags & ~MWMO_VALID) {
RIPERR1(ERROR_INVALID_PARAMETER, RIP_ERROR, "MsgWaitForMultipleObjectsEx, invalid flags 0x%08lx\n", dwFlags);
return (DWORD)-1;
}
pci = GetClientInfo();
if (pci == NULL)
return (DWORD)-1;
/*
* Need to call the server to get the input event.
*/
hEventInput = NtUserGetInputEvent(dwWakeMask);
/*
* If GetInputEvent() returned NULL the DuplicateHandle() call
* failed and we are hosed. If it returned -1 that means the
* wake mask is already satisfied and we can simply return
* the index for our input event handle if that's all we're
* waiting for.
*/
if (hEventInput == NULL) {
RIPMSG0(RIP_WARNING, "MsgWaitForMultipleObjectsEx, GetInputEvent failed\n");
return (DWORD)-1;
} else if (hEventInput == (HANDLE)-1) {
if (!fWaitAll || !nCount) {
return nCount;
}
hEventInput = pci->hEventQueueClient;
}
/*
* If needed, allocate a new array of handles that will include
* the input event handle.
*/
ph = rgHandles;
if (pHandles) {
if (nCount > 8) {
ph = (PHANDLE)LocalAlloc(LPTR, sizeof(HANDLE) * (nCount + 1));
if (ph == NULL)
return (DWORD)-1;
}
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 -1 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((HANDLE)0xffffffff);
if (NtUserGetThreadState(UserThreadStateChangeBits) & (UINT)dwWakeMask) {
SetEvent(hEventInput);
}
} else {
ReenterWowScheduler = FALSE;
}
dwIndex = WaitForMultipleObjectsEx(nCount + 1, ph, fWaitAll, dwMilliseconds, fAlertable);
/*
* If needed reenter the wow scheduler
*/
if (ReenterWowScheduler) {
NtUserCallOneParam(DY_OLDYIELD, SFI_XXXDIRECTEDYIELD);
}
if (ph != rgHandles) {
LocalFree(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;
/*
* 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 (EXCEPTION_EXECUTE_HANDLER) {
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 (EXCEPTION_EXECUTE_HANDLER) {
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;
}
}
/*
* 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);
RtlLeaveCriticalSection(&gcsHdc);
return fResult;
}
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));
}
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.
\***************************************************************************/
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.
\***************************************************************************/
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:
\***************************************************************************/
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 = LocalAlloc(LPTR, nLengthW);
fSuccess = NtUserGetObjectInformation(hObject, nIndex, pvInfoW,
nLengthW, pnLengthNeeded);
if (fSuccess) {
if (pnLengthNeeded != NULL)
*pnLengthNeeded /= sizeof(WCHAR);
WCSToMB(pvInfoW, -1, &(PCHAR)pvInfo, nLength, FALSE);
}
LocalFree(pvInfoW);
return fSuccess;
} else {
return NtUserGetObjectInformation(hObject, nIndex, pvInfo,
nLength, pnLengthNeeded);
}
}
/***************************************************************************\
* CreateWindowStation (API)
*
* Creates a windowstation object
*
* History:
\***************************************************************************/
HWINSTA CommonCreateWindowStation(
PUNICODE_STRING pstrName,
DWORD dwReserved,
ACCESS_MASK amRequest,
PSECURITY_ATTRIBUTES lpsa)
{
OBJECT_ATTRIBUTES Obja;
HANDLE hRootDirectory;
UNICODE_STRING strRootDirectory;
HWINSTA hwinstaNew;
WCHAR pwszKLID[KL_NAMELENGTH];
HANDLE hKeyboardFile;
DWORD offTable;
UNICODE_STRING strKLID;
UINT uKbdInputLocale;
NTSTATUS Status;
/*
* Load initial keyboard layout. Continue even if
* this fails (esp. important with KLF_INITTIME set)
*/
GetActiveKeyboardName(pwszKLID);
hKeyboardFile = OpenKeyboardLayoutFile(pwszKLID,
KLF_ACTIVATE | KLF_INITTIME, &offTable, &uKbdInputLocale);
if (hKeyboardFile == NULL) {
return FALSE;
}
RtlInitUnicodeString(&strKLID, pwszKLID);
/*
* 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) {
RtlInitUnicodeString(&strRootDirectory, WINSTA_DIR);
InitializeObjectAttributes(&Obja, &strRootDirectory,
OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenDirectoryObject(&hRootDirectory,
DIRECTORY_CREATE_OBJECT, &Obja);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status, RIP_VERBOSE, "");
NtClose(hKeyboardFile);
return NULL;
}
} else {
pstrName = NULL;
hRootDirectory = NULL;
}
InitializeObjectAttributes(&Obja, pstrName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0),
hRootDirectory, lpsa ? lpsa->lpSecurityDescriptor : NULL);
hwinstaNew = NtUserCreateWindowStation(&Obja, dwReserved, amRequest,
hKeyboardFile, offTable, &strKLID, uKbdInputLocale);
if (hRootDirectory != NULL)
NtClose(hRootDirectory);
NtClose(hKeyboardFile);
return hwinstaNew;
}
HWINSTA CreateWindowStationA(
LPSTR pwinsta,
DWORD dwReserved,
ACCESS_MASK amRequest,
PSECURITY_ATTRIBUTES lpsa)
{
UNICODE_STRING UnicodeString;
HWINSTA hwinsta;
if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, pwinsta))
return NULL;
hwinsta = CommonCreateWindowStation(&UnicodeString, dwReserved, amRequest, lpsa);
RtlFreeUnicodeString(&UnicodeString);
return hwinsta;
}
HWINSTA CreateWindowStationW(
LPWSTR pwinsta,
DWORD dwReserved,
ACCESS_MASK amRequest,
PSECURITY_ATTRIBUTES lpsa)
{
UNICODE_STRING strWinSta;
RtlInitUnicodeString(&strWinSta, pwinsta);
return CommonCreateWindowStation(&strWinSta, dwReserved, amRequest, lpsa);
}
/***************************************************************************\
* OpenWindowStation (API)
*
* Opens a windowstation object
*
* History:
\***************************************************************************/
HWINSTA CommonOpenWindowStation(
PUNICODE_STRING pstrName,
BOOL fInherit,
ACCESS_MASK amRequest)
{
OBJECT_ATTRIBUTES ObjA;
HANDLE hRootDirectory;
UNICODE_STRING strRootDirectory;
UNICODE_STRING strDefaultName;
HWINSTA hwinsta;
NTSTATUS Status;
WCHAR awchName[sizeof(L"Service-0x0000-0000$") / sizeof(WCHAR)];
RtlInitUnicodeString(&strRootDirectory, WINSTA_DIR);
InitializeObjectAttributes(&ObjA,
&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) {
wsprintfW(awchName, L"Service-0x0000-0000$");
RtlInitUnicodeString(&strDefaultName, awchName);
pstrName = &strDefaultName;
}
InitializeObjectAttributes( &ObjA,
pstrName,
OBJ_CASE_INSENSITIVE,
hRootDirectory,
NULL
);
if (fInherit)
ObjA.Attributes |= OBJ_INHERIT;
hwinsta = NtUserOpenWindowStation(&ObjA, amRequest);
NtClose(hRootDirectory);
return hwinsta;
}
HWINSTA OpenWindowStationA(
LPSTR 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;
}
HWINSTA OpenWindowStationW(
LPWSTR pwinsta,
BOOL fInherit,
ACCESS_MASK amRequest)
{
UNICODE_STRING strWinSta;
RtlInitUnicodeString(&strWinSta, pwinsta);
return CommonOpenWindowStation(&strWinSta, fInherit, amRequest);
}
/***************************************************************************\
* CreateDesktop (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;
UNICODE_STRING strNtDeviceName;
LPDEVMODEW mappedDevmode = pDevmode;
NTSTATUS status;
/*
* Convert the Dos file name into an Nt file name
*/
status = MapDeviceName(
(LPCWSTR)pstrDevice->Buffer,
&strNtDeviceName,
FALSE);
if (!NT_SUCCESS(status)) {
RIPNTERR0(status, RIP_VERBOSE, "");
return NULL;
}
InitializeObjectAttributes(&Obja,
pstrDesktop,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
((lpsa && lpsa->bInheritHandle) ? OBJ_INHERIT : 0),
NtUserGetProcessWindowStation(),
lpsa ? lpsa->lpSecurityDescriptor : NULL);
hdesk = NtUserCreateDesktop(&Obja,
&strNtDeviceName,
mappedDevmode,
dwFlags,
amRequest);
/*
* Clean up device name
*/
RtlFreeHeap(RtlProcessHeap(), 0, strNtDeviceName.Buffer);
return hdesk;
}
HDESK CreateDesktopA(
LPSTR pDesktop,
LPSTR pDevice,
LPDEVMODEA pDevmode,
DWORD dwFlags,
ACCESS_MASK amRequest,
PSECURITY_ATTRIBUTES lpsa)
{
NTSTATUS Status;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeDesktop;
UNICODE_STRING UnicodeDevice;
LPDEVMODEW lpDevModeW = NULL;
HDESK hdesk;
RtlInitAnsiString(&AnsiString, pDesktop);
Status = RtlAnsiStringToUnicodeString( &UnicodeDesktop, &AnsiString, TRUE );
if ( !NT_SUCCESS(Status) ) {
RIPNTERR0(Status, RIP_VERBOSE, "");
return NULL;
}
if (pDevice) {
RtlInitAnsiString(&AnsiString, pDevice);
Status = RtlAnsiStringToUnicodeString( &UnicodeDevice, &AnsiString, TRUE );
if ( !NT_SUCCESS(Status) ) {
RIPNTERR0(Status, RIP_VERBOSE, "");
RtlFreeUnicodeString(&UnicodeDesktop);
return NULL;
}
} else {
RtlInitUnicodeString(&UnicodeDevice, NULL);
}
if (pDevmode) {
lpDevModeW = GdiConvertToDevmodeW(pDevmode);
}
hdesk = CommonCreateDesktop(&UnicodeDesktop,
&UnicodeDevice,
lpDevModeW,
dwFlags,
amRequest,
lpsa);
RtlFreeUnicodeString(&UnicodeDesktop);
if (pDevice) {
RtlFreeUnicodeString(&UnicodeDevice);
}
if (lpDevModeW) {
LocalFree(lpDevModeW);
}
return hdesk;
}
HDESK CreateDesktopW(
LPWSTR pDesktop,
LPWSTR 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,
&strDevice,
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);
}
HDESK OpenDesktopA(
LPSTR 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;
}
HDESK OpenDesktopW(
LPWSTR 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;
memcpy(&(wc.style), lpWndClass, sizeof(WNDCLASSA));
wc.hIconSm = NULL;
wc.cbSize = sizeof(WNDCLASSEXA);
return RegisterClassExWOWA(&wc, pdwWOWstuff, NULL, 0);
}
/**************************************************************************\
* WowGetDefWindowProcBits - Fills in bit array for WOW
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
WORD WowGetDefWindowProcBits(
PBYTE pDefWindowProcBits,
WORD cbDefWindowProcBits)
{
WORD wMaxMsg;
PBYTE pbSrc, pbDst, pbDstEnd;
/*
* 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;
}
DWORD UserRegisterWowHandlers(
APFNWOWHANDLERSIN apfnWowIn,
APFNWOWHANDLERSOUT apfnWowOut)
{
// In'ees
pfnLocalAlloc = apfnWowIn->pfnLocalAlloc;
pfnLocalReAlloc = apfnWowIn->pfnLocalReAlloc;
pfnLocalLock = apfnWowIn->pfnLocalLock;
pfnLocalUnlock = apfnWowIn->pfnLocalUnlock;
pfnLocalSize = apfnWowIn->pfnLocalSize;
pfnLocalFree = apfnWowIn->pfnLocalFree;
pfnGetExpWinVer = apfnWowIn->pfnGetExpWinVer;
pfnInitDlgCallback = apfnWowIn->pfnInitDlgCb;
pfn16GlobalAlloc = apfnWowIn->pfn16GlobalAlloc;
pfn16GlobalFree = apfnWowIn->pfn16GlobalFree;
pfnWowEmptyClipBoard = apfnWowIn->pfnEmptyCB;
pfnWowEditNextWord = apfnWowIn->pfnWowEditNextWord;
pfnWowCBStoreHandle = apfnWowIn->pfnWowCBStoreHandle;
prescalls->pfnFindResourceExA = apfnWowIn->pfnFindResourceEx;
prescalls->pfnLoadResource = apfnWowIn->pfnLoadResource;
prescalls->pfnLockResource = apfnWowIn->pfnLockResource;
prescalls->pfnUnlockResource = apfnWowIn->pfnUnlockResource;
prescalls->pfnFreeResource = apfnWowIn->pfnFreeResource;
prescalls->pfnSizeofResource = apfnWowIn->pfnSizeofResource;
prescalls->pfnFindResourceExW = WOWFindResourceExWCover;
pfnWowWndProcEx = apfnWowIn->pfnWowWndProcEx;
pfnWowSetFakeDialogClass = apfnWowIn->pfnWowSetFakeDialogClass;
// Out'ees
#ifdef DEBUG
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 = NtUserWOWCleanup;
apfnWowOut->pfnWOWFindWindow = WOWFindWindow;
apfnWowOut->pfnWOWGetIdFromDirectory = WOWGetIdFromDirectory;
apfnWowOut->pfnWOWLoadBitmapA = WOWLoadBitmapA;
apfnWowOut->pfnWowWaitForMsgAndEvent = NtUserWaitForMsgAndEvent;
apfnWowOut->pfnYieldTask = NtUserYieldTask;
apfnWowOut->pfnGetFullUserHandle = GetFullUserHandle;
apfnWowOut->pfnGetMenuIndex = NtUserGetMenuIndex;
apfnWowOut->pfnWowGetDefWindowProcBits = WowGetDefWindowProcBits;
apfnWowOut->pfnFillWindow = FillWindow;
return (DWORD)&gSharedInfo;
}
/***************************************************************************\
* WOWDlgInit
*
* This is a callback to WOW used at the begining of dialog creation to allow
* it to associate the lParam of the WM_INITDIALOG messasge with the window
* prior to actually recieving the message.
*
* 06-19-92 sanfords Created
\***************************************************************************/
DWORD WOWDlgInit(
HWND hwndDlg,
LONG lParam)
{
UserAssert(pfnInitDlgCallback != NULL);
return (*pfnInitDlgCallback)(hwndDlg, lParam);
}
/***************************************************************************\
* 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(h));
}
/***************************************************************************\
* DispatchMessage
*
* !!! Warning if this function becomes more complicated then look at the
* server code for WrapCallProc
*
* pwnd is threadlocked in the kernel and thus always valid.
*
* 19-Aug-1992 mikeke created
\***************************************************************************/
LONG DispatchClientMessage(
PWND pwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
DWORD pfn)
{
/*
* Add assert to catch dispatching messages to a thread not associated
* with a desktop.
*/
UserAssert(GetClientInfo()->ulClientDelta != 0);
/*
* More complicate then regular CALLPROC_WOWCHECK() we want to get the
* PWW so wow doesn't have to
*/
if (WNDPROC_WOW & (DWORD)pfn) {
return (*pfnWowWndProcEx)(HW(pwnd), message, wParam, lParam, (DWORD)pfn, pwnd->adwWOW);
} else {
return ((WNDPROC)pfn)(HW(pwnd), message, wParam, lParam);
}
}
/**************************************************************************\
* ArrangeIconicWindows
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
UINT ArrangeIconicWindows(
HWND hwnd)
{
return (UINT)NtUserCallHwndLock(hwnd, SFI_XXXARRANGEICONICWINDOWS);
}
/**************************************************************************\
* BeginDeferWindowPos
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
HANDLE BeginDeferWindowPos(
int nNumWindows)
{
if (nNumWindows < 0) {
RIPERR1(ERROR_INVALID_PARAMETER,
RIP_WARNING,
"Invalid parameter \"nNumWindows\" (%ld) to BeginDeferWindowPos",
nNumWindows);
return 0;
}
return (HANDLE)NtUserCallOneParamTranslate(nNumWindows,
SFI__BEGINDEFERWINDOWPOS);
}
/**************************************************************************\
* EndDeferWindowPos
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL EndDeferWindowPos(
HDWP hWinPosInfo)
{
return NtUserEndDeferWindowPosEx(hWinPosInfo, FALSE);
}
/**************************************************************************\
* CascadeChildWindows
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL CascadeChildWindows(
HWND hwndParent,
UINT nCode)
{
return (BOOL) CascadeWindows(hwndParent, nCode, NULL, 0, NULL);
}
/**************************************************************************\
* CloseClipboard
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL CloseClipboard(VOID)
{
return (BOOL)NtUserCallOneParam((DWORD)NULL, SFI_XXXCLOSECLIPBOARD);
}
/**************************************************************************\
* CloseWindow
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL CloseWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXCLOSEWINDOW);
}
/**************************************************************************\
* CreateMenu
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
HMENU CreateMenu()
{
return (HMENU)NtUserCallNoParamTranslate(SFI__CREATEMENU);
}
/**************************************************************************\
* CreatePopupMenu
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
HMENU CreatePopupMenu()
{
return (HMENU)NtUserCallNoParamTranslate(SFI__CREATEPOPUPMENU);
}
/**************************************************************************\
* CurrentTaskLock
*
* 21-Apr-1992 jonpa Created
\**************************************************************************/
DWORD CurrentTaskLock(
DWORD hlck)
{
return (DWORD)NtUserCallOneParam(hlck, SFI_CURRENTTASKLOCK);
}
/**************************************************************************\
* DestroyCaret
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL DestroyCaret()
{
return (BOOL)NtUserCallNoParam(SFI__DESTROYCARET);
}
/**************************************************************************\
* DirectedYield
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
void DirectedYield(
DWORD dwThreadId)
{
NtUserCallOneParam(dwThreadId, SFI_XXXDIRECTEDYIELD);
}
/**************************************************************************\
* DrawMenuBar
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL DrawMenuBar(
HWND hwnd)
{
return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXDRAWMENUBAR);
}
/**************************************************************************\
* EmptyClipboard
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL EmptyClipboard()
{
return (BOOL)NtUserCallOneParam((DWORD)NULL, SFI_XXXEMPTYCLIPBOARD);
}
/**************************************************************************\
* EnableWindow
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL EnableWindow(
HWND hwnd,
BOOL bEnable)
{
return (BOOL)NtUserCallHwndParamLock(hwnd, bEnable,
SFI_XXXENABLEWINDOW);
}
/**************************************************************************\
* EnumClipboardFormats
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
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
\**************************************************************************/
BOOL FlashWindow(
HWND hwnd,
BOOL bInvert)
{
return (BOOL)NtUserCallHwndParamLock(hwnd, bInvert,
SFI_XXXFLASHWINDOW);
}
/**************************************************************************\
* GetDialogBaseUnits
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
long GetDialogBaseUnits()
{
return MAKELONG(gpsi->cxSysFontChar, gpsi->cySysFontChar);
}
/**************************************************************************\
* GetInputDesktop
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
HDESK GetInputDesktop()
{
return (HDESK)NtUserCallNoParam(SFI_XXXGETINPUTDESKTOP);
}
/**************************************************************************\
* GetKeyboardType
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
int GetKeyboardType(
int nTypeFlags)
{
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
\**************************************************************************/
DWORD GetQueueStatus(
UINT flags)
{
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
\**************************************************************************/
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);
}
/**************************************************************************\
* LoadLocalFonts
* 31-Mar-1994 -by- Bodin Dresevic [gerritv]
* Wrote it.
\**************************************************************************/
void LoadLocalFonts(void)
{
NtUserCallOneParam(FALSE,SFI_XXXLW_LOADFONTS);
}
/**************************************************************************\
* MessageBeep
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL MessageBeep(
UINT wType)
{
return (BOOL)NtUserCallOneParam(wType, SFI_XXXMESSAGEBEEP);
}
/**************************************************************************\
* OpenIcon
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL OpenIcon(
HWND hwnd)
{
return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXOPENICON);
}
HWND GetShellWindow(void) {
PCLIENTINFO pci;
PWND pwnd;
ConnectIfNecessary();
pci = GetClientInfo();
pwnd = pci->pDeskInfo->spwndShell;
if (pwnd != NULL) {
pwnd = (PWND)((PBYTE)pwnd - pci->ulClientDelta);
return HWq(pwnd);
}
return NULL;
}
BOOL SetShellWindow(HWND hwnd) {
return (BOOL)NtUserSetShellWindowEx(hwnd, hwnd);
}
HWND GetProgmanWindow(void) {
PCLIENTINFO pci;
PWND pwnd;
ConnectIfNecessary();
pci = GetClientInfo();
pwnd = pci->pDeskInfo->spwndProgman;
if (pwnd != NULL) {
pwnd = (PWND)((PBYTE)pwnd - pci->ulClientDelta);
return HWq(pwnd);
}
return NULL;
}
BOOL SetProgmanWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETPROGMANWINDOW);
}
HWND GetTaskmanWindow(void) {
PCLIENTINFO pci;
PWND pwnd;
ConnectIfNecessary();
pci = GetClientInfo();
pwnd = pci->pDeskInfo->spwndTaskman;
if (pwnd != NULL) {
pwnd = (PWND)((PBYTE)pwnd - pci->ulClientDelta);
return HWq(pwnd);
}
return NULL;
}
BOOL SetTaskmanWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwndOpt(hwnd, SFI__SETTASKMANWINDOW);
}
/**************************************************************************\
* SetWindowContextHelpId
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetWindowContextHelpId(
HWND hwnd,
DWORD id)
{
return (BOOL)NtUserCallHwndParam(hwnd, id, SFI__SETWINDOWCONTEXTHELPID);
}
/**************************************************************************\
* GetWindowContextHelpId
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
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
\**************************************************************************/
VOID PostQuitMessage(
int nExitCode)
{
NtUserCallOneParam(nExitCode, SFI__POSTQUITMESSAGE);
}
/**************************************************************************\
* REGISTERUSERHUNAPPHANDLERS
*
* 01-Apr-1992 jonpa Created
\**************************************************************************/
BOOL RegisterUserHungAppHandlers(
PFNW32ET pfnW32EndTask,
HANDLE hEventWowExec)
{
return (BOOL)NtUserCallTwoParam((DWORD)pfnW32EndTask,
(DWORD)hEventWowExec,
SFI_XXXREGISTERUSERHUNGAPPHANDLERS);
}
/**************************************************************************\
* ReleaseCapture
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL ReleaseCapture()
{
return (BOOL)NtUserCallNoParam(SFI_XXXRELEASECAPTURE);
}
/**************************************************************************\
* ReplyMessage
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL ReplyMessage(
LONG pp1)
{
return (BOOL)NtUserCallOneParam(pp1, SFI__REPLYMESSAGE);
}
/**************************************************************************\
* RegisterSystemThread
*
* 21-Jun-1994 johnc Created
\**************************************************************************/
VOID RegisterSystemThread(
DWORD dwFlags, DWORD dwReserved)
{
NtUserCallTwoParam(dwFlags, dwReserved, SFI__REGISTERSYSTEMTHREAD);
}
/**************************************************************************\
* SetCaretBlinkTime
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetCaretBlinkTime(
UINT wMSeconds)
{
return (BOOL)NtUserCallOneParam(wMSeconds, SFI__SETCARETBLINKTIME);
}
/**************************************************************************\
* SetCaretPos
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetCaretPos(
int X,
int Y)
{
return (BOOL)NtUserCallTwoParam(X, Y, SFI__SETCARETPOS);
}
/**************************************************************************\
* SetCursorPos
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetCursorPos(
int X,
int Y)
{
return (BOOL)NtUserCallTwoParam(X, Y, SFI__SETCURSORPOS);
}
/**************************************************************************\
* SetDoubleClickTime
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetDoubleClickTime(
UINT cms)
{
return (BOOL)NtUserCallOneParam(cms, SFI__SETDOUBLECLICKTIME);
}
/**************************************************************************\
* SetForegroundWindow
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SetForegroundWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwndLock(hwnd, SFI_XXXSETFOREGROUNDWINDOW);
}
/**************************************************************************\
* ShowCursor
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
int ShowCursor(
BOOL bShow)
{
return (int)NtUserCallOneParam(bShow, SFI__SHOWCURSOR);
}
/**************************************************************************\
* ShowOwnedPopups
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL ShowOwnedPopups(
HWND hwnd,
BOOL fShow)
{
return (BOOL)NtUserCallHwndParamLock(hwnd, fShow,
SFI_XXXSHOWOWNEDPOPUPS);
}
/**************************************************************************\
* ShowStartGlass
*
* 10-Sep-1992 scottlu Created
\**************************************************************************/
void ShowStartGlass(
DWORD dwTimeout)
{
NtUserCallOneParam(dwTimeout, SFI__SHOWSTARTGLASS);
}
/**************************************************************************\
* SwapMouseButton
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL SwapMouseButton(
BOOL fSwap)
{
return (BOOL)NtUserCallOneParam(fSwap, SFI__SWAPMOUSEBUTTON);
}
/**************************************************************************\
* TileChildWindows
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL TileChildWindows(
HWND hwndParent,
UINT flags)
{
return (BOOL)TileWindows(hwndParent, flags, NULL, 0, NULL);
}
/**************************************************************************\
* UnhookWindowsHook
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
BOOL UnhookWindowsHook(
int nCode,
HOOKPROC pfnFilterProc)
{
return (BOOL)NtUserCallTwoParam(nCode, (DWORD)pfnFilterProc,
SFI__UNHOOKWINDOWSHOOK);
}
/**************************************************************************\
* UpdateWindow
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
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);
}
BOOL RegisterShellHookWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwnd(hwnd, SFI__REGISTERSHELLHOOKWINDOW);
}
BOOL DeregisterShellHookWindow(
HWND hwnd)
{
return (BOOL)NtUserCallHwnd(hwnd, SFI__DEREGISTERSHELLHOOKWINDOW);
}
/**************************************************************************\
* UserRealizePalette
*
* 13-Nov-1992 mikeke Created
\**************************************************************************/
UINT UserRealizePalette(
HDC hdc)
{
return (UINT)NtUserCallOneParam((DWORD)hdc, SFI_XXXREALIZEPALETTE);
}
/**************************************************************************\
* WindowFromDC
*
* 22-Jul-1991 mikeke Created
\**************************************************************************/
HWND WindowFromDC(
HDC hdc)
{
FIXUP_HANDLE(hdc);
return (HWND)NtUserCallOneParamTranslate((DWORD)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.
\***************************************************************************/
int GetWindowRgn(HWND hwnd, HRGN hrgn)
{
int code;
PWND pwnd;
HRGN hrgnClipClient;
if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
return ERROR;
}
FIXUP_HANDLE(hrgn);
if (hrgn == NULL)
return ERROR;
/*
* If there is no region selected into this window, then return error
*/
if (pwnd->hrgnClip == NULL)
return ERROR;
/*
* Get a copy of the window clipping region - create a local
* region representing the server region, then destroy it after.
*/
hrgnClipClient = pwnd->hrgnClip;
FIXUP_HANDLE(hrgnClipClient);
if (hrgnClipClient == NULL)
return ERROR;
code = CombineRgn(hrgn, hrgnClipClient, (HRGN)0, RGN_COPY);
if (code == ERROR)
return ERROR;
/*
* Offset it to window rect coordinates (not client rect coordinates)
*/
code = OffsetRgn(hrgn, -pwnd->rcWindow.left, -pwnd->rcWindow.top);
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 ))
{
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could NOT open HKEY_CURRENT_USER (%lx).\n", 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 ) {
RIPMSG0(RIP_WARNING, "GetActiveKeyboardName - 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 );
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 ))
{
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could not determine active keyboard layout (%lx).\n", 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 ) {
RIPMSG0(RIP_WARNING, "GetActiveKeyboardName - 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
*/
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could not query active keyboard layout (%lx).\n", rc );
wcscpy( lpszName, L"00000409" );
NtClose( hKey );
return;
}
/*
* 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 ))
{
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could NOT create Preload key (%lx).\n", 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 ))
{
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could NOT create value entry 1 for Preload key (%lx).\n", 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 ))
{
RIPMSG1( RIP_WARNING, "GetActiveKeyboardName - Could NOT delete value key 'Active'.\n", 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. Start with #2.
*
* 03-06-95 GregoryW Created.
\***************************************************************************/
CONST WCHAR szPreLoadSeq[] = L"%d";
// size allows up to 999 preloaded!!!!!
#define NSIZEPRELOAD (4*sizeof(WCHAR))
VOID LoadPreloadKeyboardLayouts(void)
{
UINT i;
WCHAR szPreLoadee[NSIZEPRELOAD];
WCHAR lpszName[KL_NAMELENGTH];
for ( i=2; i; i++) {
wsprintf( szPreLoadee, szPreLoadSeq, i );
if ((GetPrivateProfileStringW(
L"Preload",
szPreLoadee,
L"", // default = NULL
lpszName, // output buffer
KL_NAMELENGTH,
L"keyboardlayout.ini") == -1 ) || (*lpszName == L'\0')) {
break;
}
LoadKeyboardLayoutW(lpszName, KLF_REPLACELANG |KLF_SUBSTITUTE_OK |KLF_NOTELLSHELL);
}
}
/***************************************************************************\
* OpenKeyboardLayoutFile
*
* Opens a layout file and computes the table offset.
*
* 01-11-95 JimA Moved LoadLibrary code from server.
\***************************************************************************/
CONST WCHAR szKLKey[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Keyboard Layouts\\";
CONST WCHAR szKLFile[] = L"Layout File";
CONST WCHAR szKLId[] = L"Layout ID";
#define NSZKLKEY sizeof(szKLKey)+16
HANDLE OpenKeyboardLayoutFile(
LPWSTR lpszKLName,
UINT uFlags,
PUINT poffTable,
PUINT pKbdInputLocale)
{
WCHAR awchKL[KL_NAMELENGTH];
WCHAR awchKLRegKey[NSZKLKEY];
LPWSTR lpszKLRegKey = &awchKLRegKey[0];
PKBDTABLES (*pfn)();
LPWSTR pwszLib;
LPWSTR pwszId;
HANDLE hLibModule;
WCHAR awchModName[MAX_PATH];
UNICODE_STRING UnicodeString;
UINT wLayoutId;
UINT wLanguageId;
NTSTATUS Status;
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;
wLanguageId = (UINT)wcstoul(lpszKLName, NULL, 16);
/*
* Substitute Layout if required.
*/
if (uFlags & KLF_SUBSTITUTE_OK) {
GetPrivateProfileStringW(
L"Substitutes",
lpszKLName,
lpszKLName, // default == no change (no substitute found)
awchKL,
sizeof(awchKL)/sizeof(WCHAR),
L"keyboardlayout.ini");
awchKL[KL_NAMELENGTH - 1] = L'\0';
wcscpy(lpszKLName, awchKL);
}
wLayoutId = (UINT)wcstoul(lpszKLName, NULL, 16);
/*
* Get DLL name from the registry, load it, and get the entry point.
*/
pwszLib = NULL;
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))) {
/*
* Read the "Layout File" value.
*/
RtlInitUnicodeString(&UnicodeString, szKLFile);
Status = NtQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
&KeyFile,
sizeof(KeyFile),
&cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) {
RIPMSG0(RIP_WARNING, "OpenKeyboardLayoutFile - Buffer overflow.");
Status = STATUS_SUCCESS;
}
if (NT_SUCCESS(Status)) {
pwszLib = (LPWSTR)KeyFile.KeyInfo.Data;
pwszLib[CCH_KL_LIBNAME - 1] = L'\0';
}
#ifdef FE_IME
/*
* 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
#endif
/*
* 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.
*/
if (HIWORD(wLayoutId)) {
RtlInitUnicodeString(&UnicodeString, szKLId);
Status = NtQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
&KeyId,
sizeof(KeyId),
&cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) {
RIPMSG0(RIP_WARNING, "OpenKeyboardLayoutFile - 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 {
/*
* This is a temporary case to allow booting the new multilingual user on top of a
* Daytona registry.
*/
/*
* 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, lpszKLName);
Status = NtQueryValueKey(hKey,
&UnicodeString,
KeyValuePartialInformation,
&KeyFile,
sizeof(KeyFile),
&cbSize);
if (Status == STATUS_BUFFER_OVERFLOW) {
RIPMSG0(RIP_WARNING, "OpenKeyboardLayoutFile - Buffer overflow.");
Status = STATUS_SUCCESS;
}
if (NT_SUCCESS(Status)) {
pwszLib = (LPWSTR)KeyFile.KeyInfo.Data;
pwszLib[CCH_KL_LIBNAME - 1] = L'\0';
}
NtClose(hKey);
}
}
*pKbdInputLocale = (UINT)MAKELONG(LOWORD(wLanguageId),LOWORD(wLayoutId));
if (pwszLib == NULL) {
if (uFlags & KLF_INITTIME) {
pwszLib = pwszKLLibSafety;
*pKbdInputLocale = wKbdLocaleSafety;
} else {
RIPMSG1(RIP_WARNING, "no DLL name for %ws", lpszKLName);
return NULL;
}
}
RetryLoad:
hLibModule = LoadLibraryW(pwszLib);
if (hLibModule == NULL) {
RIPMSG1(RIP_WARNING, "Keyboard Layout: cannot load %ws\n", pwszLib);
return NULL;
}
/*
* 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(*)())GetProcAddress(hLibModule, (LPCSTR)1);
if (pfn == NULL) {
RIPMSG0(RIP_ERROR, "Keyboard Layout: cannot get proc addr");
if ((uFlags & KLF_INITTIME) && (pwszLib != pwszKLLibSafety)) {
pwszLib = pwszKLLibSafety;
goto RetryLoad;
}
return NULL;
}
*poffTable = (UINT)((PBYTE)pfn() - (PBYTE)hLibModule);
/*
* Open the dll for read access.
*/
GetModuleFileName(hLibModule, awchModName, sizeof(awchModName));
FreeLibrary(hLibModule);
return CreateFileW(
awchModName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
}
/***************************************************************************\
* 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 LoadKeyboardLayoutEx(
HKL hkl,
LPCWSTR lpszKLName,
UINT uFlags)
{
UINT offTable;
UINT KbdInputLocale;
HANDLE hFile;
HKL hKbdLayout;
WCHAR awchKL[KL_NAMELENGTH];
/*
* NULL hkl is not allowed.
*/
if (hkl == (HKL)NULL) {
return NULL;
}
/*
* 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';
/*
* Open the layout file
*/
hFile = OpenKeyboardLayoutFile(awchKL, uFlags, &offTable, &KbdInputLocale);
if (hFile == NULL)
return 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, hkl, awchKL, KbdInputLocale, uFlags);
NtClose(hFile);
return hKbdLayout;
}
/***************************************************************************\
* LoadKeyboardLayout
*
* Loads a keyboard translation table from a dll.
*
* 01-09-95 JimA Moved LoadLibrary code from server.
\***************************************************************************/
HKL LoadKeyboardLayoutW(
LPCWSTR lpszKLName,
UINT uFlags)
{
UINT offTable;
UINT KbdInputLocale;
HANDLE hFile;
HKL hKbdLayout;
WCHAR awchKL[KL_NAMELENGTH];
/*
* 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';
/*
* Open the layout file
*/
hFile = OpenKeyboardLayoutFile(awchKL, uFlags, &offTable, &KbdInputLocale);
if (hFile == NULL)
return 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, (HKL)NULL, awchKL, KbdInputLocale, uFlags);
NtClose(hFile);
return hKbdLayout;
}
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);
}
/**************************************************************************\
* GetKeyboardLayout()
*
* 01-17-95 GregoryW Created
\**************************************************************************/
HKL GetKeyboardLayout(
DWORD idThread)
{
return (HKL)NtUserCallOneParam(idThread, SFI__GETKEYBOARDLAYOUT);
}
BOOL RegisterLogonProcess(
DWORD dwProcessId,
BOOL fSecure)
{
gfLogonProcess = NtUserCallTwoParam(dwProcessId, fSecure,
SFI__REGISTERLOGONPROCESS);
return gfLogonProcess;
}
void PrivateKDBreakPoint(void) {
NtUserBreak();
}