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 INT WINAPI 470 DllMain( 471 IN PVOID hInstanceDll, 472 IN ULONG dwReason, 473 IN PVOID reserved) 474 { 475 switch (dwReason) 476 { 477 case DLL_PROCESS_ATTACH: 478 { 479 480 #define WIN_OBJ_DIR L"\\Windows" 481 #define SESSION_DIR L"\\Sessions" 482 483 USERSRV_API_CONNECTINFO ConnectInfo; // USERCONNECT 484 485 #if 0 // Disabling this code is a BIG HACK!! 486 487 NTSTATUS Status; 488 ULONG ConnectInfoSize = sizeof(ConnectInfo); 489 WCHAR SessionDir[256]; 490 491 /* Cache the PEB and Session ID */ 492 PPEB Peb = NtCurrentPeb(); 493 ULONG SessionId = Peb->SessionId; // gSessionId 494 495 TRACE("user32::DllMain\n"); 496 497 /* Don't bother us for each thread */ 498 DisableThreadLibraryCalls(hInstanceDll); 499 500 RtlZeroMemory(&ConnectInfo, sizeof(ConnectInfo)); 501 502 /* Minimal setup of the connect info structure */ 503 ConnectInfo.ulVersion = USER_VERSION; 504 505 /* Setup the Object Directory path */ 506 if (!SessionId) 507 { 508 /* Use the raw path */ 509 wcscpy(SessionDir, WIN_OBJ_DIR); 510 } 511 else 512 { 513 /* Use the session path */ 514 swprintf(SessionDir, 515 L"%ws\\%ld%ws", 516 SESSION_DIR, 517 SessionId, 518 WIN_OBJ_DIR); 519 } 520 521 TRACE("Checkpoint (call CSR)\n"); 522 523 /* Connect to the USER Server */ 524 Status = CsrClientConnectToServer(SessionDir, 525 USERSRV_SERVERDLL_INDEX, 526 &ConnectInfo, 527 &ConnectInfoSize, 528 &gfServerProcess); 529 if (!NT_SUCCESS(Status)) 530 { 531 ERR("Failed to connect to CSR (Status %lx)\n", Status); 532 return FALSE; 533 } 534 535 TRACE("Checkpoint (CSR called)\n"); 536 537 #endif 538 539 User32Instance = hInstanceDll; 540 541 /* Finish initialization */ 542 TRACE("Checkpoint (call Init)\n"); 543 if (!Init(&ConnectInfo)) 544 return FALSE; 545 546 if (!gfServerProcess) 547 { 548 HINSTANCE hImm32 = NULL; 549 550 if (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32)) 551 { 552 WCHAR szImmFile[MAX_PATH]; 553 InitializeImmEntryTable(); 554 User32GetImmFileName(szImmFile, _countof(szImmFile)); 555 hImm32 = GetModuleHandleW(szImmFile); 556 } 557 558 if (!IMM_FN(ImmRegisterClient)(&gSharedInfo, hImm32)) 559 return FALSE; 560 } 561 break; 562 } 563 564 case DLL_PROCESS_DETACH: 565 { 566 if (ghImm32) 567 FreeLibrary(ghImm32); 568 569 Cleanup(); 570 break; 571 } 572 } 573 574 /* Finally, initialize GDI */ 575 return GdiDllInitialize(hInstanceDll, dwReason, reserved); 576 } 577 578 NTSTATUS 579 WINAPI 580 User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength) 581 { 582 TRACE("User32CallClientThreadSetupFromKernel -->\n"); 583 // FIXME: Disabling this call is a HACK!! See also ClientThreadSetup... 584 // ClientThreadSetupHelper(TRUE); 585 TRACE("<-- User32CallClientThreadSetupFromKernel\n"); 586 return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS); 587 } 588 589 NTSTATUS 590 WINAPI 591 User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength) 592 { 593 BOOL Ret; 594 PGET_CHARSET_INFO pgci = (PGET_CHARSET_INFO)Arguments; 595 596 TRACE("GetCharsetInfo\n"); 597 598 Ret = TranslateCharsetInfo((DWORD *)(ULONG_PTR)pgci->Locale, &pgci->Cs, TCI_SRCLOCALE); 599 600 return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); 601 } 602 603 NTSTATUS 604 WINAPI 605 User32CallSetWndIconsFromKernel(PVOID Arguments, ULONG ArgumentLength) 606 { 607 PSETWNDICONS_CALLBACK_ARGUMENTS Common = Arguments; 608 609 if (!gpsi->hIconSmWindows) 610 { 611 Common->hIconSample = LoadImageW(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 612 Common->hIconHand = LoadImageW(0, IDI_HAND, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 613 Common->hIconQuestion = LoadImageW(0, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 614 Common->hIconBang = LoadImageW(0, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 615 Common->hIconNote = LoadImageW(0, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 616 Common->hIconWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); 617 Common->hIconSmWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); 618 hIconWindows = Common->hIconWindows; 619 hIconSmWindows = Common->hIconSmWindows; 620 } 621 ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows,hIconWindows); 622 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); 623 } 624 625 NTSTATUS 626 WINAPI 627 User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength) 628 { 629 return ZwCallbackReturn(0, 0, STATUS_SUCCESS); 630 } 631 632 NTSTATUS 633 WINAPI 634 User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength) 635 { 636 BITMAP bmp; 637 PSETOBM_CALLBACK_ARGUMENTS Common = Arguments; 638 639 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)), sizeof(bmp), &bmp); 640 Common->oembmi[OBI_CLOSE].cx = bmp.bmWidth; 641 Common->oembmi[OBI_CLOSE].cy = bmp.bmHeight; 642 643 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_MNARROW)), sizeof(bmp), &bmp); 644 Common->oembmi[OBI_MNARROW].cx = bmp.bmWidth; 645 Common->oembmi[OBI_MNARROW].cy = bmp.bmHeight; 646 647 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROW)), sizeof(bmp), &bmp); 648 Common->oembmi[OBI_DNARROW].cx = bmp.bmWidth; 649 Common->oembmi[OBI_DNARROW].cy = bmp.bmHeight; 650 651 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_DNARROWI)), sizeof(bmp), &bmp); 652 Common->oembmi[OBI_DNARROWI].cx = bmp.bmWidth; 653 Common->oembmi[OBI_DNARROWI].cy = bmp.bmHeight; 654 655 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROW)), sizeof(bmp), &bmp); 656 Common->oembmi[OBI_UPARROW].cx = bmp.bmWidth; 657 Common->oembmi[OBI_UPARROW].cy = bmp.bmHeight; 658 659 GetObjectW(LoadBitmapW(0, MAKEINTRESOURCEW(OBM_UPARROWI)), sizeof(bmp), &bmp); 660 Common->oembmi[OBI_UPARROWI].cx = bmp.bmWidth; 661 Common->oembmi[OBI_UPARROWI].cy = bmp.bmHeight; 662 663 return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS); 664 } 665 666 NTSTATUS WINAPI User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength) 667 { 668 BOOL bResult; 669 PLPK_CALLBACK_ARGUMENTS Argument; 670 671 Argument = (PLPK_CALLBACK_ARGUMENTS)Arguments; 672 673 Argument->lpString = (LPWSTR)((ULONG_PTR)Argument->lpString + (ULONG_PTR)Argument); 674 675 bResult = ExtTextOutW(Argument->hdc, 676 Argument->x, 677 Argument->y, 678 Argument->flags, 679 (Argument->bRect) ? &Argument->rect : NULL, 680 Argument->lpString, 681 Argument->count, 682 NULL); 683 684 return ZwCallbackReturn(&bResult, sizeof(BOOL), STATUS_SUCCESS); 685 } 686 687 NTSTATUS WINAPI User32CallUMPDFromKernel(PVOID Arguments, ULONG ArgumentLength) 688 { 689 DWORD Buffer[MAX_USER_MODE_DRV_BUFFER]; 690 INT cbSize = 0; 691 NTSTATUS Status = STATUS_SUCCESS; 692 PUMPDPKTHEAD pkt, pktOut = NULL; 693 694 pkt = (PUMPDPKTHEAD)Arguments; 695 696 if ( pkt->RetSize <= sizeof(Buffer) ) 697 { 698 pktOut = (PUMPDPKTHEAD)Buffer; 699 700 if ( (GdiPrinterThunk( pkt, pktOut, pkt->RetSize ) == GDI_ERROR) ) 701 { 702 pktOut = NULL; 703 Status = STATUS_UNSUCCESSFUL; 704 } 705 else 706 { 707 cbSize = pkt->RetSize; 708 } 709 } 710 else 711 { 712 Status = STATUS_NO_MEMORY; 713 } 714 return ZwCallbackReturn( pktOut, cbSize, Status ); 715 } 716 717 NTSTATUS WINAPI 718 User32CallImmProcessKeyFromKernel(PVOID Arguments, ULONG ArgumentLength) 719 { 720 PIMMPROCESSKEY_CALLBACK_ARGUMENTS Common = Arguments; 721 DWORD Result = IMM_FN(ImmProcessKey)(Common->hWnd, 722 Common->hKL, 723 Common->vKey, 724 Common->lParam, 725 Common->dwHotKeyID); 726 727 return ZwCallbackReturn(&Result, sizeof(DWORD), STATUS_SUCCESS); 728 } 729 730 NTSTATUS WINAPI 731 User32CallImmLoadLayoutFromKernel(PVOID Arguments, ULONG ArgumentLength) 732 { 733 PIMMLOADLAYOUT_CALLBACK_ARGUMENTS Common = Arguments; 734 IMMLOADLAYOUT_CALLBACK_OUTPUT Result; 735 Result.ret = IMM_FN(ImmLoadLayout)(Common->hKL, &Result.iiex); 736 return ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS); 737 } 738