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 #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 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 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 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 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 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 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 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 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 613 User32DeliverUserAPC(PVOID Arguments, ULONG ArgumentLength) 614 { 615 return ZwCallbackReturn(0, 0, STATUS_SUCCESS); 616 } 617 618 NTSTATUS 619 WINAPI 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 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 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 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 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