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 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 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 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 PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] = 207 { 208 User32CallWindowProcFromKernel, 209 User32CallSendAsyncProcForKernel, 210 User32LoadSysMenuTemplateForKernel, 211 User32SetupDefaultCursors, 212 User32CallHookProcFromKernel, 213 User32CallEventProcFromKernel, 214 User32CallLoadMenuFromKernel, 215 User32CallClientThreadSetupFromKernel, 216 User32CallClientLoadLibraryFromKernel, 217 User32CallGetCharsetInfo, 218 User32CallCopyImageFromKernel, 219 User32CallSetWndIconsFromKernel, 220 User32DeliverUserAPC, 221 User32CallDDEPostFromKernel, 222 User32CallDDEGetFromKernel, 223 User32CallOBMFromKernel, 224 User32CallLPKFromKernel, 225 User32CallUMPDFromKernel, 226 User32CallImmProcessKeyFromKernel, 227 User32CallImmLoadLayoutFromKernel, 228 }; 229 230 231 VOID 232 WINAPI 233 GdiProcessSetup(VOID); 234 235 BOOL 236 WINAPI 237 ClientThreadSetupHelper(BOOL IsCallback) 238 { 239 /* 240 * Normally we are called by win32k so the win32 thread pointers 241 * should be valid as they are set in win32k::InitThreadCallback. 242 */ 243 PCLIENTINFO ClientInfo = GetWin32ClientInfo(); 244 BOOLEAN IsFirstThread = _InterlockedExchange8((PCHAR)&gfFirstThread, FALSE); 245 246 TRACE("In ClientThreadSetup(IsCallback == %s, gfServerProcess = %s, IsFirstThread = %s)\n", 247 IsCallback ? "TRUE" : "FALSE", gfServerProcess ? "TRUE" : "FALSE", IsFirstThread ? "TRUE" : "FALSE"); 248 249 if (IsFirstThread) 250 GdiProcessSetup(); 251 252 /* Check for already initialized thread, and bail out if so */ 253 if (ClientInfo->CI_flags & CI_INITTHREAD) 254 { 255 ERR("ClientThreadSetup: Thread already initialized.\n"); 256 return FALSE; 257 } 258 259 /* 260 * CSRSS couldn't use user32::DllMain CSR server-to-server call to connect 261 * to win32k. So it is delayed to a manually-call to ClientThreadSetup. 262 * Also this needs to be done only for the first thread (since the connection 263 * is per-process). 264 */ 265 if (gfServerProcess && IsFirstThread) 266 { 267 NTSTATUS Status; 268 USERCONNECT UserCon; 269 270 RtlZeroMemory(&UserCon, sizeof(UserCon)); 271 272 /* Minimal setup of the connect info structure */ 273 UserCon.ulVersion = USER_VERSION; 274 // UserCon.dwDispatchCount; 275 276 /* Connect to win32k */ 277 Status = NtUserProcessConnect(NtCurrentProcess(), 278 &UserCon, 279 sizeof(UserCon)); 280 if (!NT_SUCCESS(Status)) return FALSE; 281 282 /* Retrieve data */ 283 g_ppi = ClientInfo->ppi; // Snapshot PI, used as pointer only! 284 gSharedInfo = UserCon.siClient; 285 gpsi = gSharedInfo.psi; 286 gHandleTable = gSharedInfo.aheList; 287 /* ReactOS-Specific! */ gHandleEntries = SharedPtrToUser(gHandleTable->handles); 288 289 // ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", 290 // gSharedInfo.psi, gSharedInfo.aheList, gSharedInfo.ulSharedDelta); 291 } 292 293 TRACE("Checkpoint (register PFN)\n"); 294 if (!RegisterClientPFN()) 295 { 296 ERR("RegisterClientPFN failed\n"); 297 return FALSE; 298 } 299 300 /* Mark this thread as initialized */ 301 ClientInfo->CI_flags |= CI_INITTHREAD; 302 303 /* Initialization that should be done once per process */ 304 if (IsFirstThread) 305 { 306 TRACE("Checkpoint (Allocating TLS)\n"); 307 308 /* Allocate an index for user32 thread local data */ 309 User32TlsIndex = TlsAlloc(); 310 if (User32TlsIndex == TLS_OUT_OF_INDEXES) 311 return FALSE; 312 313 // HAAAAAAAAAACK!!!!!! 314 // ASSERT(gpsi); 315 if (!gpsi) ERR("AAAAAAAAAAAHHHHHHHHHHHHHH!!!!!!!! gpsi == NULL !!!!\n"); 316 if (gpsi) 317 { 318 TRACE("Checkpoint (MessageInit)\n"); 319 320 if (MessageInit()) 321 { 322 TRACE("Checkpoint (MenuInit)\n"); 323 if (MenuInit()) 324 { 325 TRACE("Checkpoint initialization done OK\n"); 326 InitializeCriticalSection(&U32AccelCacheLock); 327 LoadAppInitDlls(); 328 return TRUE; 329 } 330 MessageCleanup(); 331 } 332 333 TlsFree(User32TlsIndex); 334 return FALSE; 335 } 336 } 337 338 return TRUE; 339 } 340 341 /* 342 * @implemented 343 */ 344 BOOL 345 WINAPI 346 ClientThreadSetup(VOID) 347 { 348 // 349 // This routine, in Windows, does a lot of what Init does, but in a radically 350 // different way. 351 // 352 // In Windows, because CSRSS's threads have TIF_CSRSSTHREAD set (we have this 353 // flag in ROS but not sure if we use it), the xxxClientThreadSetup callback 354 // isn't made when CSRSS first loads WINSRV.DLL (which loads USER32.DLL). 355 // 356 // However, all the other calls are made as normal, and WINSRV.DLL loads 357 // USER32.dll, the DllMain runs, and eventually the first NtUser system call is 358 // made which initializes Win32k (and initializes the thread, but as mentioned 359 // above, the thread is marked as TIF_CSRSSTHREAD). 360 // 361 // In the DllMain of User32, there is also a CsrClientConnectToServer call to 362 // server 2 (winsrv). When this is done from CSRSS, the "InServer" flag is set, 363 // so user32 will remember that it's running inside of CSRSS. Also, another 364 // flag, called "FirstThread" is manually set by DllMain. 365 // 366 // Then, WINSRV finishes loading, and CSRSRV starts the API thread/loop. This 367 // code then calls CsrConnectToUser, which calls... ClientThreadStartup. Now 368 // this routine detects that it's in the server process, which means it's CSRSS 369 // and that the callback never happened. It does some first-time-Win32k connection 370 // initialization and caches a bunch of things -- if it's the first thread. It also 371 // acquires a critical section to initialize GDI -- and then resets the first thread 372 // flag. 373 // 374 // For now, we'll do none of this, but to support Windows' CSRSRV.DLL which calls 375 // CsrConnectToUser, we'll pretend we "did something" here. Then the rest will 376 // continue as normal. 377 // 378 379 // FIXME: Disabling this call is a HACK!! See also User32CallClientThreadSetupFromKernel... 380 // return ClientThreadSetupHelper(FALSE); 381 TRACE("ClientThreadSetup is not implemented\n"); 382 return TRUE; 383 } 384 385 BOOL 386 Init(PUSERCONNECT UserCon /*PUSERSRV_API_CONNECTINFO*/) 387 { 388 NTSTATUS Status = STATUS_SUCCESS; 389 390 TRACE("user32::Init(0x%p) -->\n", UserCon); 391 392 RtlInitializeCriticalSection(&gcsUserApiHook); 393 394 /* Initialize callback table in PEB data */ 395 NtCurrentPeb()->KernelCallbackTable = apfnDispatch; 396 NtCurrentPeb()->PostProcessInitRoutine = NULL; 397 398 // This is a HACK!! // 399 gfServerProcess = FALSE; 400 gfFirstThread = TRUE; 401 //// End of HACK!! /// 402 403 /* 404 * Retrieve data from the connect info structure if the initializing 405 * process is not CSRSS. In case it is, this will be done from inside 406 * ClientThreadSetup. 407 */ 408 if (!gfServerProcess) 409 { 410 // FIXME: HACK!! We should fixup for the NtUserProcessConnect fixups 411 // because it was made in the context of CSRSS process and not ours!! 412 // So... as long as we don't fix that, we need to redo again a call 413 // to NtUserProcessConnect... How perverse is that?! 414 // 415 // HACK(2): This call is necessary since we disabled 416 // the CSR call in DllMain... 417 { 418 RtlZeroMemory(UserCon, sizeof(*UserCon)); 419 420 /* Minimal setup of the connect info structure */ 421 UserCon->ulVersion = USER_VERSION; 422 // UserCon->dwDispatchCount; 423 424 TRACE("HACK: Hackish NtUserProcessConnect call!!\n"); 425 /* Connect to win32k */ 426 Status = NtUserProcessConnect(NtCurrentProcess(), 427 UserCon, 428 sizeof(*UserCon)); 429 if (!NT_SUCCESS(Status)) return FALSE; 430 } 431 432 // 433 // We continue as we should do normally... 434 // 435 436 /* Retrieve data */ 437 g_ppi = GetWin32ClientInfo()->ppi; // Snapshot PI, used as pointer only! 438 gSharedInfo = UserCon->siClient; 439 gpsi = gSharedInfo.psi; 440 gHandleTable = gSharedInfo.aheList; 441 /* ReactOS-Specific! */ gHandleEntries = SharedPtrToUser(gHandleTable->handles); 442 } 443 444 // FIXME: Yet another hack... This call should normally not be done here, but 445 // instead in ClientThreadSetup, and in User32CallClientThreadSetupFromKernel as well. 446 TRACE("HACK: Using Init-ClientThreadSetupHelper hack!!\n"); 447 if (!ClientThreadSetupHelper(FALSE)) 448 { 449 TRACE("Init-ClientThreadSetupHelper hack failed!\n"); 450 return FALSE; 451 } 452 453 TRACE("<-- user32::Init()\n"); 454 455 return NT_SUCCESS(Status); 456 } 457 458 VOID 459 Cleanup(VOID) 460 { 461 UnloadAppInitDlls(); 462 DeleteCriticalSection(&U32AccelCacheLock); 463 MenuCleanup(); 464 MessageCleanup(); 465 TlsFree(User32TlsIndex); 466 DeleteFrameBrushes(); 467 } 468 469 // UserClientDllInitialize 470 BOOL 471 WINAPI 472 DllMain( 473 _In_ HANDLE hDll, 474 _In_ ULONG dwReason, 475 _In_opt_ PVOID pReserved) 476 { 477 switch (dwReason) 478 { 479 case DLL_PROCESS_ATTACH: 480 { 481 482 #define WIN_OBJ_DIR L"\\Windows" 483 #define SESSION_DIR L"\\Sessions" 484 485 USERSRV_API_CONNECTINFO ConnectInfo; // USERCONNECT 486 487 #if 0 // Disabling this code is a BIG HACK!! 488 489 NTSTATUS Status; 490 ULONG ConnectInfoSize = sizeof(ConnectInfo); 491 WCHAR SessionDir[256]; 492 493 /* Cache the PEB and Session ID */ 494 PPEB Peb = NtCurrentPeb(); 495 ULONG SessionId = Peb->SessionId; // gSessionId 496 497 TRACE("user32::DllMain\n"); 498 499 /* Don't bother us for each thread */ 500 DisableThreadLibraryCalls(hDll); 501 502 RtlZeroMemory(&ConnectInfo, sizeof(ConnectInfo)); 503 504 /* Minimal setup of the connect info structure */ 505 ConnectInfo.ulVersion = USER_VERSION; 506 507 /* Setup the Object Directory path */ 508 if (!SessionId) 509 { 510 /* Use the raw path */ 511 wcscpy(SessionDir, WIN_OBJ_DIR); 512 } 513 else 514 { 515 /* Use the session path */ 516 swprintf(SessionDir, 517 L"%ws\\%ld%ws", 518 SESSION_DIR, 519 SessionId, 520 WIN_OBJ_DIR); 521 } 522 523 TRACE("Checkpoint (call CSR)\n"); 524 525 /* Connect to the USER Server */ 526 Status = CsrClientConnectToServer(SessionDir, 527 USERSRV_SERVERDLL_INDEX, 528 &ConnectInfo, 529 &ConnectInfoSize, 530 &gfServerProcess); 531 if (!NT_SUCCESS(Status)) 532 { 533 ERR("Failed to connect to CSR (Status %lx)\n", Status); 534 return FALSE; 535 } 536 537 TRACE("Checkpoint (CSR called)\n"); 538 539 #endif 540 541 User32Instance = hDll; 542 543 /* Finish initialization */ 544 TRACE("Checkpoint (call Init)\n"); 545 if (!Init(&ConnectInfo)) 546 return FALSE; 547 548 if (!gfServerProcess) 549 { 550 HINSTANCE hImm32 = NULL; 551 552 if (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32)) 553 { 554 WCHAR szImmFile[MAX_PATH]; 555 InitializeImmEntryTable(); 556 User32GetImmFileName(szImmFile, _countof(szImmFile)); 557 hImm32 = GetModuleHandleW(szImmFile); 558 } 559 560 if (!IMM_FN(ImmRegisterClient)(&gSharedInfo, hImm32)) 561 return FALSE; 562 } 563 break; 564 } 565 566 case DLL_PROCESS_DETACH: 567 { 568 if (ghImm32) 569 FreeLibrary(ghImm32); 570 571 Cleanup(); 572 break; 573 } 574 } 575 576 /* Finally, initialize GDI */ 577 return GdiDllInitialize(hDll, dwReason, pReserved); 578 } 579 580 NTSTATUS 581 WINAPI 582 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength) 583 { 584 TRACE("User32CallClientThreadSetupFromKernel -->\n"); 585 // FIXME: Disabling this call is a HACK!! See also ClientThreadSetup... 586 // ClientThreadSetupHelper(TRUE); 587 TRACE("<-- User32CallClientThreadSetupFromKernel\n"); 588 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS); 589 } 590 591 NTSTATUS 592 WINAPI 593 User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength) 594 { 595 BOOL Ret; 596 PGET_CHARSET_INFO pgci = (PGET_CHARSET_INFO)Arguments; 597 598 TRACE("GetCharsetInfo\n"); 599 600 Ret = TranslateCharsetInfo((DWORD *)(ULONG_PTR)pgci->Locale, &pgci->Cs, TCI_SRCLOCALE); 601 602 return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); 603 } 604 605 NTSTATUS 606 WINAPI 607 User32CallSetWndIconsFromKernel(PVOID Arguments, ULONG ArgumentLength) 608 { 609 PSETWNDICONS_CALLBACK_ARGUMENTS Common = Arguments; 610 611 if (!gpsi->hIconSmWindows) 612 { 613 Common->hIconSample = LoadImageW(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 614 Common->hIconHand = LoadImageW(0, IDI_HAND, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 615 Common->hIconQuestion = LoadImageW(0, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 616 Common->hIconBang = LoadImageW(0, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 617 Common->hIconNote = LoadImageW(0, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 618 Common->hIconWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 619 Common->hIconSmWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); 620 hIconWindows = Common->hIconWindows; 621 hIconSmWindows = Common->hIconSmWindows; 622 } 623 ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows,hIconWindows); 624 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); 625 } 626 627 NTSTATUS 628 WINAPI 629 User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength) 630 { 631 return ZwCallbackReturn(0, 0, STATUS_SUCCESS); 632 } 633 634 NTSTATUS 635 WINAPI 636 User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength) 637 { 638 BITMAP bmp; 639 PSETOBM_CALLBACK_ARGUMENTS Common = Arguments; 640 641 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)), sizeof(bmp), &bmp); 642 Common->oembmi[OBI_CLOSE].cx = bmp.bmWidth; 643 Common->oembmi[OBI_CLOSE].cy = bmp.bmHeight; 644 645 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)), sizeof(bmp), &bmp); 646 Common->oembmi[OBI_MNARROW].cx = bmp.bmWidth; 647 Common->oembmi[OBI_MNARROW].cy = bmp.bmHeight; 648 649 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROW)), sizeof(bmp), &bmp); 650 Common->oembmi[OBI_DNARROW].cx = bmp.bmWidth; 651 Common->oembmi[OBI_DNARROW].cy = bmp.bmHeight; 652 653 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROWI)), sizeof(bmp), &bmp); 654 Common->oembmi[OBI_DNARROWI].cx = bmp.bmWidth; 655 Common->oembmi[OBI_DNARROWI].cy = bmp.bmHeight; 656 657 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROW)), sizeof(bmp), &bmp); 658 Common->oembmi[OBI_UPARROW].cx = bmp.bmWidth; 659 Common->oembmi[OBI_UPARROW].cy = bmp.bmHeight; 660 661 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROWI)), sizeof(bmp), &bmp); 662 Common->oembmi[OBI_UPARROWI].cx = bmp.bmWidth; 663 Common->oembmi[OBI_UPARROWI].cy = bmp.bmHeight; 664 665 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); 666 } 667 668 NTSTATUS WINAPI User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength) 669 { 670 BOOL bResult; 671 PLPK_CALLBACK_ARGUMENTS Argument; 672 673 Argument = (PLPK_CALLBACK_ARGUMENTS)Arguments; 674 675 Argument->lpString = (LPWSTR)((ULONG_PTR)Argument->lpString + (ULONG_PTR)Argument); 676 677 bResult = ExtTextOutW(Argument->hdc, 678 Argument->x, 679 Argument->y, 680 Argument->flags, 681 (Argument->bRect) ? &Argument->rect : NULL, 682 Argument->lpString, 683 Argument->count, 684 NULL); 685 686 return ZwCallbackReturn(&bResult, sizeof(BOOL), STATUS_SUCCESS); 687 } 688 689 NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength) 690 { 691 DWORD Buffer[MAX_USER_MODE_DRV_BUFFER]; 692 INT cbSize = 0; 693 NTSTATUS Status = STATUS_SUCCESS; 694 PUMPDPKTHEAD pkt, pktOut = NULL; 695 696 pkt = (PUMPDPKTHEAD)Arguments; 697 698 if ( pkt->RetSize <= sizeof(Buffer) ) 699 { 700 pktOut = (PUMPDPKTHEAD)Buffer; 701 702 if ( (GdiPrinterThunk( pkt, pktOut, pkt->RetSize ) == GDI_ERROR) ) 703 { 704 pktOut = NULL; 705 Status = STATUS_UNSUCCESSFUL; 706 } 707 else 708 { 709 cbSize = pkt->RetSize; 710 } 711 } 712 else 713 { 714 Status = STATUS_NO_MEMORY; 715 } 716 return ZwCallbackReturn( pktOut, cbSize, Status ); 717 } 718 719 NTSTATUS WINAPI 720 User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength) 721 { 722 PIMMPROCESSKEY_CALLBACK_ARGUMENTS Common = Arguments; 723 DWORD Result = IMM_FN(ImmProcessKey)(Common->hWnd, 724 Common->hKL, 725 Common->vKey, 726 Common->lParam, 727 Common->dwHotKeyID); 728 729 return ZwCallbackReturn(&Result, sizeof(DWORD), STATUS_SUCCESS); 730 } 731 732 NTSTATUS WINAPI 733 User32CallImmLoadLayoutFromKernel(PVOID Arguments, ULONG ArgumentLength) 734 { 735 PIMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = Arguments; 736 IMMLOADLAYOUT_CALLBACK_OUTPUT Result; 737 Result.ret = IMM_FN(ImmLoadLayout)(Common->hKL, &Result.iiex); 738 return ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS); 739 } 740