1 #include <user32.h>
2 #include <ndk/cmfuncs.h>
3 #include <strsafe.h>
4
5 #define MAX_USER_MODE_DRV_BUFFER 526
6
7 //
8 // UMPD Packet Header should match win32ss/include/ntumpd.h
9 //
10 typedef struct _UMPDPKTHEAD
11 {
12 INT Size;
13 INT Index;
14 INT RetSize;
15 DWORD Reserved;
16 HUMPD humpd;
17 ULONG_PTR Buffer[];
18 } UMPDPKTHEAD, *PUMPDPKTHEAD;
19
20 INT WINAPI GdiPrinterThunk(PUMPDPKTHEAD,PVOID,INT);
21
22 WINE_DEFAULT_DEBUG_CHANNEL(user32);
23
24 #define KEY_LENGTH 1024
25
26 static ULONG User32TlsIndex;
27 HINSTANCE User32Instance;
28
29 PPROCESSINFO g_ppi = NULL;
30 SHAREDINFO gSharedInfo = {0};
31 PSERVERINFO gpsi = NULL;
32 PUSER_HANDLE_TABLE gHandleTable = NULL;
33 PUSER_HANDLE_ENTRY gHandleEntries = NULL;
34 BOOLEAN gfLogonProcess = FALSE;
35 BOOLEAN gfServerProcess = FALSE;
36 BOOLEAN gfFirstThread = TRUE;
37 HICON hIconSmWindows = NULL, hIconWindows = NULL;
38
39 WCHAR szAppInit[KEY_LENGTH];
40
41 BOOL
GetDllList(VOID)42 GetDllList(VOID)
43 {
44 NTSTATUS Status;
45 OBJECT_ATTRIBUTES Attributes;
46 BOOL bRet = FALSE;
47 BOOL bLoad;
48 HANDLE hKey = NULL;
49 DWORD dwSize;
50 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = NULL;
51
52 UNICODE_STRING szKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
53 UNICODE_STRING szLoadName = RTL_CONSTANT_STRING(L"LoadAppInit_DLLs");
54 UNICODE_STRING szDllsName = RTL_CONSTANT_STRING(L"AppInit_DLLs");
55
56 InitializeObjectAttributes(&Attributes, &szKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
57 Status = NtOpenKey(&hKey, KEY_READ, &Attributes);
58 if (NT_SUCCESS(Status))
59 {
60 dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD);
61 kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
62 if (!kvpInfo)
63 goto end;
64
65 Status = NtQueryValueKey(hKey,
66 &szLoadName,
67 KeyValuePartialInformation,
68 kvpInfo,
69 dwSize,
70 &dwSize);
71 if (!NT_SUCCESS(Status))
72 goto end;
73
74 RtlMoveMemory(&bLoad,
75 kvpInfo->Data,
76 kvpInfo->DataLength);
77
78 HeapFree(GetProcessHeap(), 0, kvpInfo);
79 kvpInfo = NULL;
80
81 if (bLoad)
82 {
83 Status = NtQueryValueKey(hKey,
84 &szDllsName,
85 KeyValuePartialInformation,
86 NULL,
87 0,
88 &dwSize);
89 if (Status != STATUS_BUFFER_TOO_SMALL)
90 goto end;
91
92 kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
93 if (!kvpInfo)
94 goto end;
95
96 Status = NtQueryValueKey(hKey,
97 &szDllsName,
98 KeyValuePartialInformation,
99 kvpInfo,
100 dwSize,
101 &dwSize);
102 if (NT_SUCCESS(Status))
103 {
104 LPWSTR lpBuffer = (LPWSTR)kvpInfo->Data;
105 if (*lpBuffer != UNICODE_NULL)
106 {
107 INT bytesToCopy, nullPos;
108
109 bytesToCopy = min(kvpInfo->DataLength, KEY_LENGTH * sizeof(WCHAR));
110
111 if (bytesToCopy != 0)
112 {
113 RtlMoveMemory(szAppInit,
114 kvpInfo->Data,
115 bytesToCopy);
116
117 nullPos = (bytesToCopy / sizeof(WCHAR)) - 1;
118
119 /* ensure string is terminated */
120 szAppInit[nullPos] = UNICODE_NULL;
121
122 bRet = TRUE;
123 }
124 }
125 }
126 }
127 }
128
129 end:
130 if (hKey)
131 NtClose(hKey);
132
133 if (kvpInfo)
134 HeapFree(GetProcessHeap(), 0, kvpInfo);
135
136 return bRet;
137 }
138
139
140 VOID
LoadAppInitDlls(VOID)141 LoadAppInitDlls(VOID)
142 {
143 szAppInit[0] = UNICODE_NULL;
144
145 if (GetDllList())
146 {
147 WCHAR buffer[KEY_LENGTH];
148 LPWSTR ptr;
149 size_t i;
150
151 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH * sizeof(WCHAR) );
152
153 for (i = 0; i < KEY_LENGTH; ++ i)
154 {
155 if(buffer[i] == L' ' || buffer[i] == L',')
156 buffer[i] = 0;
157 }
158
159 for (i = 0; i < KEY_LENGTH; )
160 {
161 if(buffer[i] == 0)
162 ++ i;
163 else
164 {
165 ptr = buffer + i;
166 i += wcslen(ptr);
167 LoadLibraryW(ptr);
168 }
169 }
170 }
171 }
172
173 VOID
UnloadAppInitDlls(VOID)174 UnloadAppInitDlls(VOID)
175 {
176 if (szAppInit[0] != UNICODE_NULL)
177 {
178 WCHAR buffer[KEY_LENGTH];
179 HMODULE hModule;
180 LPWSTR ptr;
181 size_t i;
182
183 RtlCopyMemory(buffer, szAppInit, KEY_LENGTH * sizeof(WCHAR));
184
185 for (i = 0; i < KEY_LENGTH; ++ i)
186 {
187 if(buffer[i] == L' ' || buffer[i] == L',')
188 buffer[i] = 0;
189 }
190
191 for (i = 0; i < KEY_LENGTH; )
192 {
193 if(buffer[i] == 0)
194 ++ i;
195 else
196 {
197 ptr = buffer + i;
198 i += wcslen(ptr);
199 hModule = GetModuleHandleW(ptr);
200 FreeLibrary(hModule);
201 }
202 }
203 }
204 }
205
206 #define DEFINE_USER32_CALLBACK(id, value, fn) fn,
207
208 PVOID apfnDispatch[USER32_CALLBACK_COUNT] =
209 {
210 #include "u32cb.h"
211 };
212
213 #undef DEFINE_USER32_CALLBACK
214
215 VOID
216 WINAPI
217 GdiProcessSetup(VOID);
218
219 BOOL
220 WINAPI
ClientThreadSetupHelper(BOOL IsCallback)221 ClientThreadSetupHelper(BOOL IsCallback)
222 {
223 /*
224 * Normally we are called by win32k so the win32 thread pointers
225 * should be valid as they are set in win32k::InitThreadCallback.
226 */
227 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
228 BOOLEAN IsFirstThread = _InterlockedExchange8((PCHAR)&gfFirstThread, FALSE);
229
230 TRACE("In ClientThreadSetup(IsCallback == %s, gfServerProcess = %s, IsFirstThread = %s)\n",
231 IsCallback ? "TRUE" : "FALSE", gfServerProcess ? "TRUE" : "FALSE", IsFirstThread ? "TRUE" : "FALSE");
232
233 if (IsFirstThread)
234 GdiProcessSetup();
235
236 /* Check for already initialized thread, and bail out if so */
237 if (ClientInfo->CI_flags & CI_INITTHREAD)
238 {
239 ERR("ClientThreadSetup: Thread already initialized.\n");
240 return FALSE;
241 }
242
243 /*
244 * CSRSS couldn't use user32::DllMain CSR server-to-server call to connect
245 * to win32k. So it is delayed to a manually-call to ClientThreadSetup.
246 * Also this needs to be done only for the first thread (since the connection
247 * is per-process).
248 */
249 if (gfServerProcess && IsFirstThread)
250 {
251 NTSTATUS Status;
252 USERCONNECT UserCon;
253
254 RtlZeroMemory(&UserCon, sizeof(UserCon));
255
256 /* Minimal setup of the connect info structure */
257 UserCon.ulVersion = USER_VERSION;
258 // UserCon.dwDispatchCount;
259
260 /* Connect to win32k */
261 Status = NtUserProcessConnect(NtCurrentProcess(),
262 &UserCon,
263 sizeof(UserCon));
264 if (!NT_SUCCESS(Status)) return FALSE;
265
266 /* Retrieve data */
267 g_ppi = ClientInfo->ppi; // Snapshot PI, used as pointer only!
268 gSharedInfo = UserCon.siClient;
269 gpsi = gSharedInfo.psi;
270 gHandleTable = gSharedInfo.aheList;
271 /* ReactOS-Specific! */ gHandleEntries = SharedPtrToUser(gHandleTable->handles);
272
273 // ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n",
274 // gSharedInfo.psi, gSharedInfo.aheList, gSharedInfo.ulSharedDelta);
275 }
276
277 TRACE("Checkpoint (register PFN)\n");
278 if (!RegisterClientPFN())
279 {
280 ERR("RegisterClientPFN failed\n");
281 return FALSE;
282 }
283
284 /* Mark this thread as initialized */
285 ClientInfo->CI_flags |= CI_INITTHREAD;
286
287 /* Initialization that should be done once per process */
288 if (IsFirstThread)
289 {
290 TRACE("Checkpoint (Allocating TLS)\n");
291
292 /* Allocate an index for user32 thread local data */
293 User32TlsIndex = TlsAlloc();
294 if (User32TlsIndex == TLS_OUT_OF_INDEXES)
295 return FALSE;
296
297 // HAAAAAAAAAACK!!!!!!
298 // ASSERT(gpsi);
299 if (!gpsi) ERR("AAAAAAAAAAAHHHHHHHHHHHHHH!!!!!!!! gpsi == NULL !!!!\n");
300 if (gpsi)
301 {
302 TRACE("Checkpoint (MessageInit)\n");
303
304 if (MessageInit())
305 {
306 TRACE("Checkpoint (MenuInit)\n");
307 if (MenuInit())
308 {
309 TRACE("Checkpoint initialization done OK\n");
310 InitializeCriticalSection(&U32AccelCacheLock);
311 LoadAppInitDlls();
312 return TRUE;
313 }
314 MessageCleanup();
315 }
316
317 TlsFree(User32TlsIndex);
318 return FALSE;
319 }
320 }
321
322 return TRUE;
323 }
324
325 /*
326 * @implemented
327 */
328 BOOL
329 WINAPI
ClientThreadSetup(VOID)330 ClientThreadSetup(VOID)
331 {
332 //
333 // This routine, in Windows, does a lot of what Init does, but in a radically
334 // different way.
335 //
336 // In Windows, because CSRSS's threads have TIF_CSRSSTHREAD set (we have this
337 // flag in ROS but not sure if we use it), the xxxClientThreadSetup callback
338 // isn't made when CSRSS first loads WINSRV.DLL (which loads USER32.DLL).
339 //
340 // However, all the other calls are made as normal, and WINSRV.DLL loads
341 // USER32.dll, the DllMain runs, and eventually the first NtUser system call is
342 // made which initializes Win32k (and initializes the thread, but as mentioned
343 // above, the thread is marked as TIF_CSRSSTHREAD).
344 //
345 // In the DllMain of User32, there is also a CsrClientConnectToServer call to
346 // server 2 (winsrv). When this is done from CSRSS, the "InServer" flag is set,
347 // so user32 will remember that it's running inside of CSRSS. Also, another
348 // flag, called "FirstThread" is manually set by DllMain.
349 //
350 // Then, WINSRV finishes loading, and CSRSRV starts the API thread/loop. This
351 // code then calls CsrConnectToUser, which calls... ClientThreadStartup. Now
352 // this routine detects that it's in the server process, which means it's CSRSS
353 // and that the callback never happened. It does some first-time-Win32k connection
354 // initialization and caches a bunch of things -- if it's the first thread. It also
355 // acquires a critical section to initialize GDI -- and then resets the first thread
356 // flag.
357 //
358 // For now, we'll do none of this, but to support Windows' CSRSRV.DLL which calls
359 // CsrConnectToUser, we'll pretend we "did something" here. Then the rest will
360 // continue as normal.
361 //
362
363 // FIXME: Disabling this call is a HACK!! See also User32CallClientThreadSetupFromKernel...
364 // return ClientThreadSetupHelper(FALSE);
365 TRACE("ClientThreadSetup is not implemented\n");
366 return TRUE;
367 }
368
369 BOOL
Init(PUSERCONNECT UserCon)370 Init(PUSERCONNECT UserCon /*PUSERSRV_API_CONNECTINFO*/)
371 {
372 NTSTATUS Status = STATUS_SUCCESS;
373
374 TRACE("user32::Init(0x%p) -->\n", UserCon);
375
376 RtlInitializeCriticalSection(&gcsUserApiHook);
377
378 /* Initialize callback table in PEB data */
379 NtCurrentPeb()->KernelCallbackTable = apfnDispatch;
380 NtCurrentPeb()->PostProcessInitRoutine = NULL;
381
382 // This is a HACK!! //
383 gfServerProcess = FALSE;
384 gfFirstThread = TRUE;
385 //// End of HACK!! ///
386
387 /*
388 * Retrieve data from the connect info structure if the initializing
389 * process is not CSRSS. In case it is, this will be done from inside
390 * ClientThreadSetup.
391 */
392 if (!gfServerProcess)
393 {
394 // FIXME: HACK!! We should fixup for the NtUserProcessConnect fixups
395 // because it was made in the context of CSRSS process and not ours!!
396 // So... as long as we don't fix that, we need to redo again a call
397 // to NtUserProcessConnect... How perverse is that?!
398 //
399 // HACK(2): This call is necessary since we disabled
400 // the CSR call in DllMain...
401 {
402 RtlZeroMemory(UserCon, sizeof(*UserCon));
403
404 /* Minimal setup of the connect info structure */
405 UserCon->ulVersion = USER_VERSION;
406 // UserCon->dwDispatchCount;
407
408 TRACE("HACK: Hackish NtUserProcessConnect call!!\n");
409 /* Connect to win32k */
410 Status = NtUserProcessConnect(NtCurrentProcess(),
411 UserCon,
412 sizeof(*UserCon));
413 if (!NT_SUCCESS(Status)) return FALSE;
414 }
415
416 //
417 // We continue as we should do normally...
418 //
419
420 /* Retrieve data */
421 g_ppi = GetWin32ClientInfo()->ppi; // Snapshot PI, used as pointer only!
422 gSharedInfo = UserCon->siClient;
423 gpsi = gSharedInfo.psi;
424 gHandleTable = gSharedInfo.aheList;
425 /* ReactOS-Specific! */ gHandleEntries = SharedPtrToUser(gHandleTable->handles);
426 }
427
428 // FIXME: Yet another hack... This call should normally not be done here, but
429 // instead in ClientThreadSetup, and in User32CallClientThreadSetupFromKernel as well.
430 TRACE("HACK: Using Init-ClientThreadSetupHelper hack!!\n");
431 if (!ClientThreadSetupHelper(FALSE))
432 {
433 TRACE("Init-ClientThreadSetupHelper hack failed!\n");
434 return FALSE;
435 }
436
437 TRACE("<-- user32::Init()\n");
438
439 return NT_SUCCESS(Status);
440 }
441
442 VOID
Cleanup(VOID)443 Cleanup(VOID)
444 {
445 UnloadAppInitDlls();
446 DeleteCriticalSection(&U32AccelCacheLock);
447 MenuCleanup();
448 MessageCleanup();
449 TlsFree(User32TlsIndex);
450 DeleteFrameBrushes();
451 }
452
453 // UserClientDllInitialize
454 BOOL
455 WINAPI
DllMain(_In_ HANDLE hDll,_In_ ULONG dwReason,_In_opt_ PVOID pReserved)456 DllMain(
457 _In_ HANDLE hDll,
458 _In_ ULONG dwReason,
459 _In_opt_ PVOID pReserved)
460 {
461 switch (dwReason)
462 {
463 case DLL_PROCESS_ATTACH:
464 {
465
466 #define WIN_OBJ_DIR L"\\Windows"
467 #define SESSION_DIR L"\\Sessions"
468
469 USERSRV_API_CONNECTINFO ConnectInfo; // USERCONNECT
470
471 #if 0 // Disabling this code is a BIG HACK!!
472
473 NTSTATUS Status;
474 ULONG ConnectInfoSize = sizeof(ConnectInfo);
475 WCHAR SessionDir[256];
476
477 /* Cache the PEB and Session ID */
478 PPEB Peb = NtCurrentPeb();
479 ULONG SessionId = Peb->SessionId; // gSessionId
480
481 TRACE("user32::DllMain\n");
482
483 /* Don't bother us for each thread */
484 DisableThreadLibraryCalls(hDll);
485
486 RtlZeroMemory(&ConnectInfo, sizeof(ConnectInfo));
487
488 /* Minimal setup of the connect info structure */
489 ConnectInfo.ulVersion = USER_VERSION;
490
491 /* Setup the Object Directory path */
492 if (!SessionId)
493 {
494 /* Use the raw path */
495 wcscpy(SessionDir, WIN_OBJ_DIR);
496 }
497 else
498 {
499 /* Use the session path */
500 swprintf(SessionDir,
501 L"%ws\\%ld%ws",
502 SESSION_DIR,
503 SessionId,
504 WIN_OBJ_DIR);
505 }
506
507 TRACE("Checkpoint (call CSR)\n");
508
509 /* Connect to the USER Server */
510 Status = CsrClientConnectToServer(SessionDir,
511 USERSRV_SERVERDLL_INDEX,
512 &ConnectInfo,
513 &ConnectInfoSize,
514 &gfServerProcess);
515 if (!NT_SUCCESS(Status))
516 {
517 ERR("Failed to connect to CSR (Status %lx)\n", Status);
518 return FALSE;
519 }
520
521 TRACE("Checkpoint (CSR called)\n");
522
523 #endif
524
525 User32Instance = hDll;
526
527 /* Finish initialization */
528 TRACE("Checkpoint (call Init)\n");
529 if (!Init(&ConnectInfo))
530 return FALSE;
531
532 if (!gfServerProcess)
533 {
534 HINSTANCE hImm32 = NULL;
535
536 if (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32))
537 {
538 WCHAR szImmFile[MAX_PATH];
539 InitializeImmEntryTable();
540 User32GetImmFileName(szImmFile, _countof(szImmFile));
541 hImm32 = GetModuleHandleW(szImmFile);
542 }
543
544 if (!IMM_FN(ImmRegisterClient)(&gSharedInfo, hImm32))
545 return FALSE;
546 }
547 break;
548 }
549
550 case DLL_PROCESS_DETACH:
551 {
552 if (ghImm32)
553 FreeLibrary(ghImm32);
554
555 Cleanup();
556 break;
557 }
558 }
559
560 /* Finally, initialize GDI */
561 return GdiDllInitialize(hDll, dwReason, pReserved);
562 }
563
564 NTSTATUS
565 WINAPI
User32CallClientThreadSetupFromKernel(PVOID Arguments,ULONG ArgumentLength)566 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength)
567 {
568 TRACE("User32CallClientThreadSetupFromKernel -->\n");
569 // FIXME: Disabling this call is a HACK!! See also ClientThreadSetup...
570 // ClientThreadSetupHelper(TRUE);
571 TRACE("<-- User32CallClientThreadSetupFromKernel\n");
572 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
573 }
574
575 NTSTATUS
576 WINAPI
User32CallGetCharsetInfo(PVOID Arguments,ULONG ArgumentLength)577 User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength)
578 {
579 BOOL Ret;
580 PGET_CHARSET_INFO pgci = (PGET_CHARSET_INFO)Arguments;
581
582 TRACE("GetCharsetInfo\n");
583
584 Ret = TranslateCharsetInfo((DWORD *)(ULONG_PTR)pgci->Locale, &pgci->Cs, TCI_SRCLOCALE);
585
586 return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
587 }
588
589 NTSTATUS
590 WINAPI
User32CallSetWndIconsFromKernel(PVOID Arguments,ULONG ArgumentLength)591 User32CallSetWndIconsFromKernel(PVOID Arguments, ULONG ArgumentLength)
592 {
593 PSETWNDICONS_CALLBACK_ARGUMENTS Common = Arguments;
594
595 if (!gpsi->hIconSmWindows)
596 {
597 Common->hIconSample = LoadImageW(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
598 Common->hIconHand = LoadImageW(0, IDI_HAND, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
599 Common->hIconQuestion = LoadImageW(0, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
600 Common->hIconBang = LoadImageW(0, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
601 Common->hIconNote = LoadImageW(0, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
602 Common->hIconWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
603 Common->hIconSmWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
604 hIconWindows = Common->hIconWindows;
605 hIconSmWindows = Common->hIconSmWindows;
606 }
607 ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows,hIconWindows);
608 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
609 }
610
611 NTSTATUS
612 WINAPI
User32DeliverUserAPC(PVOID Arguments,ULONG ArgumentLength)613 User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength)
614 {
615 return ZwCallbackReturn(0, 0, STATUS_SUCCESS);
616 }
617
618 NTSTATUS
619 WINAPI
User32CallOBMFromKernel(PVOID Arguments,ULONG ArgumentLength)620 User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength)
621 {
622 BITMAP bmp;
623 PSETOBM_CALLBACK_ARGUMENTS Common = Arguments;
624
625 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)), sizeof(bmp), &bmp);
626 Common->oembmi[OBI_CLOSE].cx = bmp.bmWidth;
627 Common->oembmi[OBI_CLOSE].cy = bmp.bmHeight;
628
629 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)), sizeof(bmp), &bmp);
630 Common->oembmi[OBI_MNARROW].cx = bmp.bmWidth;
631 Common->oembmi[OBI_MNARROW].cy = bmp.bmHeight;
632
633 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROW)), sizeof(bmp), &bmp);
634 Common->oembmi[OBI_DNARROW].cx = bmp.bmWidth;
635 Common->oembmi[OBI_DNARROW].cy = bmp.bmHeight;
636
637 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROWI)), sizeof(bmp), &bmp);
638 Common->oembmi[OBI_DNARROWI].cx = bmp.bmWidth;
639 Common->oembmi[OBI_DNARROWI].cy = bmp.bmHeight;
640
641 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROW)), sizeof(bmp), &bmp);
642 Common->oembmi[OBI_UPARROW].cx = bmp.bmWidth;
643 Common->oembmi[OBI_UPARROW].cy = bmp.bmHeight;
644
645 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROWI)), sizeof(bmp), &bmp);
646 Common->oembmi[OBI_UPARROWI].cx = bmp.bmWidth;
647 Common->oembmi[OBI_UPARROWI].cy = bmp.bmHeight;
648
649 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
650 }
651
User32CallLPKFromKernel(PVOID Arguments,ULONG ArgumentLength)652 NTSTATUS WINAPI User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength)
653 {
654 BOOL bResult;
655 PLPK_CALLBACK_ARGUMENTS Argument;
656
657 Argument = (PLPK_CALLBACK_ARGUMENTS)Arguments;
658
659 Argument->lpString = (LPWSTR)((ULONG_PTR)Argument->lpString + (ULONG_PTR)Argument);
660
661 bResult = ExtTextOutW(Argument->hdc,
662 Argument->x,
663 Argument->y,
664 Argument->flags,
665 (Argument->bRect) ? &Argument->rect : NULL,
666 Argument->lpString,
667 Argument->count,
668 NULL);
669
670 return ZwCallbackReturn(&bResult, sizeof(BOOL), STATUS_SUCCESS);
671 }
672
User32CallUMPDFromKernel(PVOID Arguments,ULONG ArgumentLength)673 NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength)
674 {
675 DWORD Buffer[MAX_USER_MODE_DRV_BUFFER];
676 INT cbSize = 0;
677 NTSTATUS Status = STATUS_SUCCESS;
678 PUMPDPKTHEAD pkt, pktOut = NULL;
679
680 pkt = (PUMPDPKTHEAD)Arguments;
681
682 if ( pkt->RetSize <= sizeof(Buffer) )
683 {
684 pktOut = (PUMPDPKTHEAD)Buffer;
685
686 if ( (GdiPrinterThunk( pkt, pktOut, pkt->RetSize ) == GDI_ERROR) )
687 {
688 pktOut = NULL;
689 Status = STATUS_UNSUCCESSFUL;
690 }
691 else
692 {
693 cbSize = pkt->RetSize;
694 }
695 }
696 else
697 {
698 Status = STATUS_NO_MEMORY;
699 }
700 return ZwCallbackReturn( pktOut, cbSize, Status );
701 }
702
703 NTSTATUS WINAPI
User32CallImmProcessKeyFromKernel(PVOID Arguments,ULONG ArgumentLength)704 User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength)
705 {
706 PIMMPROCESSKEY_CALLBACK_ARGUMENTS Common = Arguments;
707 DWORD Result = IMM_FN(ImmProcessKey)(Common->hWnd,
708 Common->hKL,
709 Common->vKey,
710 Common->lParam,
711 Common->dwHotKeyID);
712
713 return ZwCallbackReturn(&Result, sizeof(DWORD), STATUS_SUCCESS);
714 }
715
716 NTSTATUS WINAPI
User32CallImmLoadLayoutFromKernel(PVOID Arguments,ULONG ArgumentLength)717 User32CallImmLoadLayoutFromKernel(PVOID Arguments, ULONG ArgumentLength)
718 {
719 PIMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = Arguments;
720 IMMLOADLAYOUT_CALLBACK_OUTPUT Result;
721 Result.ret = IMM_FN(ImmLoadLayout)(Common->hKL, &Result.iiex);
722 return ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS);
723 }
724