1 /* 2 * PROJECT: ReactOS user32.dll 3 * COPYRIGHT: GPL - See COPYING in the top level directory 4 * FILE: win32ss/user/user32/windows/class.c 5 * PURPOSE: Window classes 6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * UPDATE HISTORY: 8 * 09-05-2001 CSH Created 9 */ 10 11 #include <user32.h> 12 13 WINE_DEFAULT_DEBUG_CHANNEL(user32); 14 15 #define USE_VERSIONED_CLASSES 16 17 /* From rtl/actctx.c and must match! */ 18 struct strsection_header 19 { 20 DWORD magic; 21 ULONG size; 22 DWORD unk1[3]; 23 ULONG count; 24 ULONG index_offset; 25 DWORD unk2[2]; 26 ULONG global_offset; 27 ULONG global_len; 28 }; 29 30 struct wndclass_redirect_data 31 { 32 ULONG size; 33 DWORD res; 34 ULONG name_len; 35 ULONG name_offset; /* versioned name offset */ 36 ULONG module_len; 37 ULONG module_offset;/* container name offset */ 38 }; 39 40 // 41 // Use wine hack to process extended context classes. 42 // 43 /*********************************************************************** 44 * is_comctl32_class 45 */ 46 LPCWSTR is_comctl32_class( const WCHAR *name ) 47 { 48 static const WCHAR classesW[][20] = 49 { 50 {'C','o','m','b','o','B','o','x','E','x','3','2',0}, 51 {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0}, 52 {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0}, 53 {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0}, 54 {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0}, 55 {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0}, 56 {'N','a','t','i','v','e','F','o','n','t','C','t','l',0}, 57 {'R','e','B','a','r','W','i','n','d','o','w','3','2',0}, 58 {'S','y','s','A','n','i','m','a','t','e','3','2',0}, 59 {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0}, 60 {'S','y','s','H','e','a','d','e','r','3','2',0}, 61 {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0}, 62 {'S','y','s','L','i','s','t','V','i','e','w','3','2',0}, 63 {'S','y','s','M','o','n','t','h','C','a','l','3','2',0}, 64 {'S','y','s','P','a','g','e','r',0}, 65 {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0}, 66 {'S','y','s','T','r','e','e','V','i','e','w','3','2',0}, 67 {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0}, 68 {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0}, 69 }; 70 71 int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1; 72 73 while (min <= max) 74 { 75 int res, pos = (min + max) / 2; 76 if (!(res = strcmpiW( name, classesW[pos] ))) return classesW[pos]; 77 if (res < 0) max = pos - 1; 78 else min = pos + 1; 79 } 80 return NULL; 81 } 82 83 LPCWSTR 84 FASTCALL 85 ClassNameToVersion( 86 const void* lpszClass, 87 LPCWSTR lpszMenuName, 88 LPCWSTR *plpLibFileName, 89 HANDLE *pContext, 90 BOOL bAnsi) 91 { 92 LPCWSTR VersionedClass = NULL; 93 NTSTATUS Status; 94 UNICODE_STRING SectionName; 95 WCHAR SectionNameBuf[MAX_PATH] = {0}; 96 ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) }; 97 98 if(!lpszClass) 99 { 100 ERR("Null class given !\n"); 101 return NULL; 102 } 103 104 if (IS_ATOM(lpszClass)) 105 { 106 RtlInitEmptyUnicodeString(&SectionName, SectionNameBuf, sizeof(SectionNameBuf)); 107 if(!NtUserGetAtomName(LOWORD((DWORD_PTR)lpszClass), &SectionName)) 108 { 109 ERR("Couldn't get atom name for atom %x !\n", LOWORD((DWORD_PTR)lpszClass)); 110 return NULL; 111 } 112 SectionName.Length = wcslen(SectionNameBuf) * sizeof(WCHAR); 113 TRACE("ClassNameToVersion got name %wZ from atom\n", &SectionName); 114 } 115 else 116 { 117 if (bAnsi) 118 { 119 ANSI_STRING AnsiString; 120 RtlInitAnsiString(&AnsiString, lpszClass); 121 RtlInitEmptyUnicodeString(&SectionName, SectionNameBuf, sizeof(SectionNameBuf)); 122 RtlAnsiStringToUnicodeString(&SectionName, &AnsiString, FALSE); 123 } 124 else 125 { 126 RtlInitUnicodeString(&SectionName, lpszClass); 127 } 128 } 129 Status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, 130 NULL, 131 ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, 132 &SectionName, 133 &KeyedData ); 134 135 #ifdef USE_VERSIONED_CLASSES 136 if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1) 137 { 138 struct strsection_header *SectionHeader = KeyedData.lpSectionBase; 139 140 /* Find activation context */ 141 if(SectionHeader && SectionHeader->count > 0) 142 { 143 struct wndclass_redirect_data *WindowRedirectionData = KeyedData.lpData; 144 if(WindowRedirectionData && WindowRedirectionData->module_len) 145 { 146 LPCWSTR lpLibFileName; 147 148 VersionedClass = (WCHAR*)((BYTE*)WindowRedirectionData + WindowRedirectionData->name_offset); 149 lpLibFileName = (WCHAR*)((BYTE*)KeyedData.lpSectionBase + WindowRedirectionData->module_offset); 150 TRACE("Returning VersionedClass=%S, plpLibFileName=%S for class %S\n", VersionedClass, lpLibFileName, SectionName.Buffer); 151 152 if (pContext) *pContext = KeyedData.hActCtx; 153 if (plpLibFileName) *plpLibFileName = lpLibFileName; 154 155 } 156 } 157 } 158 159 if (KeyedData.hActCtx) 160 RtlReleaseActivationContext(KeyedData.hActCtx); 161 #endif 162 163 #ifndef DEFAULT_ACTIVATION_CONTEXTS_SUPPORTED 164 /* This block is a hack! */ 165 if (!VersionedClass) 166 { 167 /* 168 * In windows the default activation context always contains comctl32v5 169 * In reactos we don't have a default activation context so we 170 * mimic wine here. 171 */ 172 VersionedClass = is_comctl32_class(SectionName.Buffer); 173 if (VersionedClass) 174 { 175 if (pContext) *pContext = 0; 176 if (plpLibFileName) *plpLibFileName = L"comctl32"; 177 } 178 } 179 #endif 180 181 /* 182 * The returned strings are pointers in the activation context and 183 * will get freed when the activation context gets freed 184 */ 185 return VersionedClass; 186 } 187 188 // 189 // Ref: http://yvs-it.blogspot.com/2010/04/initcommoncontrolsex.html 190 // 191 BOOL 192 FASTCALL 193 VersionRegisterClass( 194 PCWSTR pszClass, 195 LPCWSTR lpLibFileName, 196 HANDLE Contex, 197 HMODULE * phLibModule) 198 { 199 BOOL Ret = FALSE; 200 HMODULE hLibModule = NULL; 201 PREGISTERCLASSNAMEW pRegisterClassNameW; 202 UNICODE_STRING ClassName; 203 WCHAR ClassNameBuf[MAX_PATH] = {0}; 204 RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame = { sizeof(Frame), 1 }; 205 206 ERR("VersionRegisterClass: Attempting to call RegisterClassNameW in %S\n.", lpLibFileName); 207 208 RtlActivateActivationContextUnsafeFast(&Frame, Contex); 209 210 _SEH2_TRY 211 { 212 hLibModule = LoadLibraryW(lpLibFileName); 213 if (hLibModule) 214 { 215 if ((pRegisterClassNameW = (void*)GetProcAddress(hLibModule, "RegisterClassNameW"))) 216 { 217 if (IS_ATOM(pszClass)) 218 { 219 RtlInitEmptyUnicodeString(&ClassName, ClassNameBuf, sizeof(ClassNameBuf)); 220 if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName)) 221 { 222 ERR("Error while verifying ATOM\n"); 223 _SEH2_YIELD(goto Error_Exit); 224 } 225 pszClass = ClassName.Buffer; 226 } 227 Ret = pRegisterClassNameW(pszClass); 228 } 229 else 230 { 231 WARN("No RegisterClassNameW PROC\n"); 232 } 233 } 234 } 235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 236 { 237 ERR("Got exception while trying to call RegisterClassNameW!\n"); 238 } 239 _SEH2_END 240 241 Error_Exit: 242 if (Ret || !hLibModule) 243 { 244 if (phLibModule) *phLibModule = hLibModule; 245 } 246 else 247 { 248 DWORD dwLastError = GetLastError(); 249 FreeLibrary(hLibModule); 250 SetLastError(dwLastError); 251 } 252 253 RtlDeactivateActivationContextUnsafeFast(&Frame); 254 return Ret; 255 } 256 257 /* 258 * @implemented 259 */ 260 BOOL 261 WINAPI 262 GetClassInfoExA( 263 HINSTANCE hInstance, 264 LPCSTR lpszClass, 265 LPWNDCLASSEXA lpwcx) 266 { 267 UNICODE_STRING ClassName = {0}; 268 LPCSTR pszMenuName; 269 HMODULE hLibModule = NULL; 270 DWORD dwLastError; 271 BOOL Ret, ClassFound = FALSE, ConvertedString = FALSE; 272 LPCWSTR lpszClsVersion; 273 HANDLE pCtx = NULL; 274 LPCWSTR lpLibFileName = NULL; 275 276 TRACE("%p class/atom: %s/%04x %p\n", hInstance, 277 IS_ATOM(lpszClass) ? NULL : lpszClass, 278 IS_ATOM(lpszClass) ? lpszClass : 0, 279 lpwcx); 280 281 if (!lpwcx) 282 { 283 SetLastError(ERROR_NOACCESS); 284 return FALSE; 285 } 286 287 if (hInstance == User32Instance) 288 { 289 hInstance = NULL; 290 } 291 292 if (lpszClass == NULL) 293 { 294 SetLastError(ERROR_INVALID_PARAMETER); 295 return FALSE; 296 } 297 298 lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, TRUE); 299 if (lpszClsVersion) 300 { 301 RtlInitUnicodeString(&ClassName, lpszClsVersion); 302 } 303 else if (IS_ATOM(lpszClass)) 304 { 305 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); 306 } 307 else 308 { 309 ConvertedString = TRUE; 310 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpszClass)) 311 { 312 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 313 return FALSE; 314 } 315 } 316 317 if (!RegisterDefaultClasses) 318 { 319 TRACE("RegisterSystemControls\n"); 320 RegisterSystemControls(); 321 } 322 323 for(;;) 324 { 325 Ret = NtUserGetClassInfo(hInstance, 326 &ClassName, 327 (LPWNDCLASSEXW)lpwcx, 328 (LPWSTR *)&pszMenuName, 329 TRUE); 330 if (Ret) break; 331 if (!lpLibFileName) break; 332 if (!ClassFound) 333 { 334 dwLastError = GetLastError(); 335 if ( dwLastError == ERROR_CANNOT_FIND_WND_CLASS || 336 dwLastError == ERROR_CLASS_DOES_NOT_EXIST ) 337 { 338 ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule); 339 if (ClassFound) continue; 340 } 341 } 342 if (hLibModule) 343 { 344 dwLastError = GetLastError(); 345 FreeLibrary(hLibModule); 346 SetLastError(dwLastError); 347 hLibModule = 0; 348 } 349 break; 350 } 351 352 if (Ret) 353 { 354 lpwcx->lpszClassName = lpszClass; 355 // lpwcx->lpszMenuName = pszMenuName; 356 } 357 358 if (ConvertedString) 359 { 360 RtlFreeUnicodeString(&ClassName); 361 } 362 363 return Ret; 364 } 365 366 367 /* 368 * @implemented 369 */ 370 BOOL 371 WINAPI 372 GetClassInfoExW( 373 HINSTANCE hInstance, 374 LPCWSTR lpszClass, 375 LPWNDCLASSEXW lpwcx) 376 { 377 UNICODE_STRING ClassName = {0}; 378 LPWSTR pszMenuName; 379 HMODULE hLibModule = NULL; 380 DWORD dwLastError; 381 BOOL Ret, ClassFound = FALSE; 382 LPCWSTR lpszClsVersion; 383 HANDLE pCtx = NULL; 384 LPCWSTR lpLibFileName = NULL; 385 386 TRACE("%p class/atom: %S/%04x %p\n", hInstance, 387 IS_ATOM(lpszClass) ? NULL : lpszClass, 388 IS_ATOM(lpszClass) ? lpszClass : 0, 389 lpwcx); 390 391 /* From wine, for speed only, ReactOS supports the correct return in 392 * Win32k. cbSize is ignored. 393 */ 394 if (!lpwcx) 395 { 396 SetLastError( ERROR_NOACCESS ); 397 return FALSE; 398 } 399 400 if (hInstance == User32Instance) 401 { 402 hInstance = NULL; 403 } 404 405 if (lpszClass == NULL) 406 { 407 SetLastError(ERROR_INVALID_PARAMETER); 408 return FALSE; 409 } 410 411 lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, FALSE); 412 if (lpszClsVersion) 413 { 414 RtlInitUnicodeString(&ClassName, lpszClsVersion); 415 } 416 else if (IS_ATOM(lpszClass)) 417 { 418 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); 419 } 420 else 421 { 422 RtlInitUnicodeString(&ClassName, lpszClass); 423 } 424 425 if (!RegisterDefaultClasses) 426 { 427 TRACE("RegisterSystemControls\n"); 428 RegisterSystemControls(); 429 } 430 431 for(;;) 432 { 433 Ret = NtUserGetClassInfo( hInstance, 434 &ClassName, 435 lpwcx, 436 &pszMenuName, 437 FALSE); 438 if (Ret) break; 439 if (!lpLibFileName) break; 440 if (!ClassFound) 441 { 442 dwLastError = GetLastError(); 443 if ( dwLastError == ERROR_CANNOT_FIND_WND_CLASS || 444 dwLastError == ERROR_CLASS_DOES_NOT_EXIST ) 445 { 446 ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule); 447 if (ClassFound) continue; 448 } 449 } 450 if (hLibModule) 451 { 452 dwLastError = GetLastError(); 453 FreeLibrary(hLibModule); 454 SetLastError(dwLastError); 455 hLibModule = 0; 456 } 457 break; 458 } 459 460 if (Ret) 461 { 462 lpwcx->lpszClassName = lpszClass; 463 // lpwcx->lpszMenuName = pszMenuName; 464 } 465 return Ret; 466 } 467 468 469 /* 470 * @implemented 471 */ 472 BOOL 473 WINAPI 474 GetClassInfoA( 475 HINSTANCE hInstance, 476 LPCSTR lpClassName, 477 LPWNDCLASSA lpWndClass) 478 { 479 WNDCLASSEXA wcex; 480 BOOL retval; 481 482 retval = GetClassInfoExA(hInstance, lpClassName, &wcex); 483 if (retval) 484 { 485 lpWndClass->style = wcex.style; 486 lpWndClass->lpfnWndProc = wcex.lpfnWndProc; 487 lpWndClass->cbClsExtra = wcex.cbClsExtra; 488 lpWndClass->cbWndExtra = wcex.cbWndExtra; 489 lpWndClass->hInstance = wcex.hInstance; 490 lpWndClass->hIcon = wcex.hIcon; 491 lpWndClass->hCursor = wcex.hCursor; 492 lpWndClass->hbrBackground = wcex.hbrBackground; 493 lpWndClass->lpszMenuName = wcex.lpszMenuName; 494 lpWndClass->lpszClassName = wcex.lpszClassName; 495 } 496 497 return retval; 498 } 499 500 /* 501 * @implemented 502 */ 503 BOOL 504 WINAPI 505 GetClassInfoW( 506 HINSTANCE hInstance, 507 LPCWSTR lpClassName, 508 LPWNDCLASSW lpWndClass) 509 { 510 WNDCLASSEXW wcex; 511 BOOL retval; 512 513 retval = GetClassInfoExW(hInstance, lpClassName, &wcex); 514 if (retval) 515 { 516 lpWndClass->style = wcex.style; 517 lpWndClass->lpfnWndProc = wcex.lpfnWndProc; 518 lpWndClass->cbClsExtra = wcex.cbClsExtra; 519 lpWndClass->cbWndExtra = wcex.cbWndExtra; 520 lpWndClass->hInstance = wcex.hInstance; 521 lpWndClass->hIcon = wcex.hIcon; 522 lpWndClass->hCursor = wcex.hCursor; 523 lpWndClass->hbrBackground = wcex.hbrBackground; 524 lpWndClass->lpszMenuName = wcex.lpszMenuName; 525 lpWndClass->lpszClassName = wcex.lpszClassName; 526 } 527 return retval; 528 } 529 530 // 531 // Based on find_winproc... Fixes many whine tests...... 532 // 533 ULONG_PTR FASTCALL 534 IntGetClsWndProc(PWND pWnd, PCLS Class, BOOL Ansi) 535 { 536 INT i; 537 ULONG_PTR gcpd, Ret = 0; 538 // If server side, sweep through proc list and return the client side proc. 539 if (Class->CSF_flags & CSF_SERVERSIDEPROC) 540 { // Always scan through the list due to wine class "deftest". 541 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) 542 { 543 if (GETPFNSERVER(i) == Class->lpfnWndProc) 544 { 545 if (Ansi) 546 Ret = (ULONG_PTR)GETPFNCLIENTA(i); 547 else 548 Ret = (ULONG_PTR)GETPFNCLIENTW(i); 549 } 550 } 551 return Ret; 552 } 553 // Set return proc. 554 Ret = (ULONG_PTR)Class->lpfnWndProc; 555 // Return the proc if one of the FnId default class type. 556 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) 557 { 558 if (Ansi) 559 { // If match return the right proc by type. 560 if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc) 561 Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid); 562 } 563 else 564 { 565 if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc) 566 Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid); 567 } 568 } 569 // Return on change or Ansi/Unicode proc equal. 570 if ( Ret != (ULONG_PTR)Class->lpfnWndProc || 571 Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) ) 572 return Ret; 573 574 /* We have an Ansi and Unicode swap! If Ansi create Unicode proc handle. 575 This will force CallWindowProc to deal with it. */ 576 gcpd = NtUserGetCPD( UserHMGetHandle(pWnd), 577 (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWndtoCls, 578 Ret); 579 580 return (gcpd ? gcpd : Ret); 581 } 582 583 // 584 // Based on IntGetClsWndProc 585 // 586 WNDPROC FASTCALL 587 IntGetWndProc(PWND pWnd, BOOL Ansi) 588 { 589 INT i; 590 WNDPROC gcpd, Ret = 0; 591 PCLS Class = DesktopPtrToUser(pWnd->pcls); 592 593 if (!Class) return Ret; 594 595 if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC) 596 { 597 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++) 598 { 599 if (GETPFNSERVER(i) == pWnd->lpfnWndProc) 600 { 601 if (Ansi) 602 Ret = GETPFNCLIENTA(i); 603 else 604 Ret = GETPFNCLIENTW(i); 605 } 606 } 607 return Ret; 608 } 609 // Wine Class tests: 610 /* Edit controls are special - they return a wndproc handle when 611 GetWindowLongPtr is called with a different A/W. 612 On the other hand there is no W->A->W conversion so this control 613 is treated specially. 614 */ 615 if (Class->fnid == FNID_EDIT) 616 Ret = pWnd->lpfnWndProc; 617 else 618 { 619 // Set return proc. 620 Ret = pWnd->lpfnWndProc; 621 622 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON) 623 { 624 if (Ansi) 625 { 626 if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc) 627 Ret = GETPFNCLIENTA(Class->fnid); 628 } 629 else 630 { 631 if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc) 632 Ret = GETPFNCLIENTW(Class->fnid); 633 } 634 } 635 // Return on the change. 636 if ( Ret != pWnd->lpfnWndProc) 637 return Ret; 638 } 639 640 if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) ) 641 return Ret; 642 643 gcpd = (WNDPROC)NtUserGetCPD( UserHMGetHandle(pWnd), 644 (Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow, 645 (ULONG_PTR)Ret); 646 647 return (gcpd ? gcpd : Ret); 648 } 649 650 static ULONG_PTR FASTCALL 651 IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex) 652 { 653 ULONG_PTR Ret = 0; 654 655 if (nIndex >= 0) 656 { 657 if (nIndex + sizeof(ULONG_PTR) < nIndex || 658 nIndex + sizeof(ULONG_PTR) > Class->cbclsExtra) 659 { 660 SetLastError(ERROR_INVALID_PARAMETER); 661 } 662 else 663 Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex); 664 } 665 else 666 { 667 switch (nIndex) 668 { 669 case GCL_CBWNDEXTRA: 670 Ret = (ULONG_PTR)Class->cbwndExtra; 671 break; 672 673 case GCL_CBCLSEXTRA: 674 Ret = (ULONG_PTR)Class->cbclsExtra; 675 break; 676 677 case GCL_HBRBACKGROUND: 678 Ret = (ULONG_PTR)Class->hbrBackground; 679 if (Ret != 0 && Ret < 0x4000) 680 Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1); 681 break; 682 683 case GCL_HMODULE: 684 //ERR("Cls 0x%x GCL_HMODULE 0x%x\n", Wnd->pcls, Class->hModule); 685 Ret = (ULONG_PTR)Class->hModule; 686 break; 687 688 case GCL_MENUNAME: 689 Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName; 690 break; 691 692 case GCL_STYLE: 693 Ret = (ULONG_PTR)Class->style; 694 break; 695 696 case GCW_ATOM: 697 Ret = (ULONG_PTR)Class->atomNVClassName; 698 break; 699 700 case GCLP_HCURSOR: 701 Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0; 702 break; 703 704 case GCLP_HICON: 705 Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0; 706 break; 707 708 case GCLP_HICONSM: 709 Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0; 710 break; 711 712 case GCLP_WNDPROC: 713 Ret = IntGetClsWndProc(Wnd, Class, TRUE); 714 break; 715 716 default: 717 SetLastError(ERROR_INVALID_INDEX); 718 break; 719 } 720 } 721 722 return Ret; 723 } 724 725 static ULONG_PTR FASTCALL 726 IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex) 727 { 728 ULONG_PTR Ret = 0; 729 730 if (nIndex >= 0) 731 { 732 if (nIndex + sizeof(ULONG_PTR) < nIndex || 733 nIndex + sizeof(ULONG_PTR) > Class->cbclsExtra) 734 { 735 SetLastError(ERROR_INVALID_PARAMETER); 736 } 737 else 738 Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex); 739 } 740 else 741 { 742 switch (nIndex) 743 { 744 case GCL_CBWNDEXTRA: 745 Ret = (ULONG_PTR)Class->cbwndExtra; 746 break; 747 748 case GCL_CBCLSEXTRA: 749 Ret = (ULONG_PTR)Class->cbclsExtra; 750 break; 751 752 case GCLP_HBRBACKGROUND: 753 Ret = (ULONG_PTR)Class->hbrBackground; 754 if (Ret != 0 && Ret < 0x4000) 755 Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1); 756 break; 757 758 case GCL_HMODULE: 759 Ret = (ULONG_PTR)Class->hModule; 760 break; 761 762 case GCLP_MENUNAME: 763 Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName; 764 break; 765 766 case GCL_STYLE: 767 Ret = (ULONG_PTR)Class->style; 768 break; 769 770 case GCW_ATOM: 771 Ret = (ULONG_PTR)Class->atomNVClassName; 772 break; 773 774 case GCLP_HCURSOR: 775 Ret = Class->spcur ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spcur))->h : 0; 776 break; 777 778 case GCLP_HICON: 779 Ret = Class->spicn ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicn))->h : 0; 780 break; 781 782 case GCLP_HICONSM: 783 Ret = Class->spicnSm ? (ULONG_PTR)((PPROCMARKHEAD)SharedPtrToUser(Class->spicnSm))->h : 0; 784 break; 785 786 case GCLP_WNDPROC: 787 Ret = IntGetClsWndProc(Wnd, Class, FALSE); 788 break; 789 790 default: 791 SetLastError(ERROR_INVALID_INDEX); 792 break; 793 } 794 } 795 796 return Ret; 797 } 798 799 /* 800 * @implemented 801 */ 802 DWORD WINAPI 803 GetClassLongA(HWND hWnd, int nIndex) 804 { 805 PWND Wnd; 806 PCLS Class; 807 ULONG_PTR Ret = 0; 808 809 TRACE("%p %d\n", hWnd, nIndex); 810 811 Wnd = ValidateHwnd(hWnd); 812 if (!Wnd) 813 return 0; 814 815 _SEH2_TRY 816 { 817 Class = DesktopPtrToUser(Wnd->pcls); 818 if (Class != NULL) 819 { 820 #ifdef _WIN64 821 switch (nIndex) 822 { 823 case GCLP_HBRBACKGROUND: 824 case GCLP_HCURSOR: 825 case GCLP_HICON: 826 case GCLP_HICONSM: 827 case GCLP_HMODULE: 828 case GCLP_MENUNAME: 829 case GCLP_WNDPROC: 830 SetLastError(ERROR_INVALID_INDEX); 831 break; 832 833 default: 834 Ret = IntGetClassLongA(Wnd, Class, nIndex); 835 break; 836 } 837 #else 838 Ret = IntGetClassLongA(Wnd, Class, nIndex); 839 #endif 840 } 841 else 842 { 843 WARN("Invalid class for hwnd 0x%p!\n", hWnd); 844 } 845 } 846 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 847 { 848 Ret = 0; 849 } 850 _SEH2_END; 851 852 return (DWORD)Ret; 853 } 854 855 /* 856 * @implemented 857 */ 858 DWORD WINAPI 859 GetClassLongW ( HWND hWnd, int nIndex ) 860 { 861 PWND Wnd; 862 PCLS Class; 863 ULONG_PTR Ret = 0; 864 865 TRACE("%p %d\n", hWnd, nIndex); 866 867 Wnd = ValidateHwnd(hWnd); 868 if (!Wnd) 869 return 0; 870 871 _SEH2_TRY 872 { 873 Class = DesktopPtrToUser(Wnd->pcls); 874 if (Class != NULL) 875 { 876 #ifdef _WIN64 877 switch (nIndex) 878 { 879 case GCLP_HBRBACKGROUND: 880 case GCLP_HCURSOR: 881 case GCLP_HICON: 882 case GCLP_HICONSM: 883 case GCLP_HMODULE: 884 case GCLP_MENUNAME: 885 case GCLP_WNDPROC: 886 SetLastError(ERROR_INVALID_INDEX); 887 break; 888 889 default: 890 Ret = IntGetClassLongW(Wnd, Class, nIndex); 891 break; 892 } 893 #else 894 Ret = IntGetClassLongW(Wnd, Class, nIndex); 895 #endif 896 } 897 else 898 { 899 WARN("Invalid class for hwnd 0x%p!\n", hWnd); 900 } 901 } 902 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 903 { 904 Ret = 0; 905 } 906 _SEH2_END; 907 908 return (DWORD)Ret; 909 } 910 911 #ifdef _WIN64 912 /* 913 * @implemented 914 */ 915 ULONG_PTR 916 WINAPI 917 GetClassLongPtrA(HWND hWnd, 918 INT nIndex) 919 { 920 PWND Wnd; 921 PCLS Class; 922 ULONG_PTR Ret = 0; 923 924 TRACE("%p %d\n", hWnd, nIndex); 925 926 Wnd = ValidateHwnd(hWnd); 927 if (!Wnd) 928 return 0; 929 930 _SEH2_TRY 931 { 932 Class = DesktopPtrToUser(Wnd->pcls); 933 if (Class != NULL) 934 { 935 Ret = IntGetClassLongA(Wnd, Class, nIndex); 936 } 937 else 938 { 939 WARN("Invalid class for hwnd 0x%p!\n", hWnd); 940 } 941 } 942 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 943 { 944 Ret = 0; 945 } 946 _SEH2_END; 947 948 return Ret; 949 } 950 951 /* 952 * @implemented 953 */ 954 ULONG_PTR 955 WINAPI 956 GetClassLongPtrW(HWND hWnd, 957 INT nIndex) 958 { 959 PWND Wnd; 960 PCLS Class; 961 ULONG_PTR Ret = 0; 962 963 TRACE("%p %d\n", hWnd, nIndex); 964 965 Wnd = ValidateHwnd(hWnd); 966 if (!Wnd) 967 return 0; 968 969 _SEH2_TRY 970 { 971 Class = DesktopPtrToUser(Wnd->pcls); 972 if (Class != NULL) 973 { 974 Ret = IntGetClassLongW(Wnd, Class, nIndex); 975 } 976 else 977 { 978 WARN("Invalid class for hwnd 0x%p!\n", hWnd); 979 } 980 } 981 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 982 { 983 Ret = 0; 984 } 985 _SEH2_END; 986 987 return Ret; 988 } 989 #endif 990 991 992 /* 993 * @implemented 994 */ 995 int WINAPI 996 GetClassNameA( 997 HWND hWnd, 998 LPSTR lpClassName, 999 int nMaxCount) 1000 { 1001 WCHAR tmpbuf[MAX_ATOM_LEN + 1]; 1002 int len; 1003 1004 if (nMaxCount <= 0) return 0; 1005 if (!GetClassNameW( hWnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0; 1006 RtlUnicodeToMultiByteN( lpClassName, nMaxCount - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) ); 1007 lpClassName[len] = 0; 1008 1009 TRACE("%p class/atom: %s/%04x %x\n", hWnd, 1010 IS_ATOM(lpClassName) ? NULL : lpClassName, 1011 IS_ATOM(lpClassName) ? lpClassName : 0, 1012 nMaxCount); 1013 1014 return len; 1015 } 1016 1017 1018 /* 1019 * @implemented 1020 */ 1021 int 1022 WINAPI 1023 GetClassNameW( 1024 HWND hWnd, 1025 LPWSTR lpClassName, 1026 int nMaxCount) 1027 { 1028 UNICODE_STRING ClassName; 1029 int Result; 1030 1031 RtlInitEmptyUnicodeString(&ClassName, 1032 lpClassName, 1033 nMaxCount * sizeof(WCHAR)); 1034 1035 Result = NtUserGetClassName(hWnd, 1036 FALSE, 1037 &ClassName); 1038 1039 TRACE("%p class/atom: %S/%04x %x\n", hWnd, 1040 IS_ATOM(lpClassName) ? NULL : lpClassName, 1041 IS_ATOM(lpClassName) ? lpClassName : 0, 1042 nMaxCount); 1043 1044 return Result; 1045 } 1046 1047 1048 /* 1049 * @implemented 1050 */ 1051 WORD 1052 WINAPI 1053 GetClassWord( 1054 HWND hwnd, 1055 int offset) 1056 { 1057 PWND Wnd; 1058 PCLS class; 1059 WORD retvalue = 0; 1060 1061 if (offset < 0) return GetClassLongA( hwnd, offset ); 1062 1063 Wnd = ValidateHwnd(hwnd); 1064 if (!Wnd) 1065 return 0; 1066 1067 class = DesktopPtrToUser(Wnd->pcls); 1068 if (class == NULL) return 0; 1069 1070 if (offset <= class->cbclsExtra - sizeof(WORD)) 1071 memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) ); 1072 else 1073 SetLastError( ERROR_INVALID_INDEX ); 1074 1075 return retvalue; 1076 } 1077 1078 1079 LONG_PTR IntGetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode ) 1080 { 1081 LONG_PTR retvalue = 0; 1082 WND *wndPtr; 1083 1084 if (offset == GWLP_HWNDPARENT) 1085 { 1086 HWND parent = GetAncestor( hwnd, GA_PARENT ); 1087 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER ); 1088 return (ULONG_PTR)parent; 1089 } 1090 1091 if (!(wndPtr = ValidateHwnd( hwnd ))) 1092 { 1093 SetLastError( ERROR_INVALID_WINDOW_HANDLE ); 1094 return 0; 1095 } 1096 1097 if (offset >= 0 && wndPtr->fnid != FNID_DESKTOP) 1098 { 1099 if (offset > (int)(wndPtr->cbwndExtra - size)) 1100 { 1101 WARN("Invalid offset %d\n", offset ); 1102 SetLastError( ERROR_INVALID_INDEX ); 1103 return 0; 1104 } 1105 retvalue = *((LONG_PTR *)((PCHAR)(wndPtr + 1) + offset)); 1106 1107 /* WINE: special case for dialog window procedure */ 1108 //if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG)) 1109 // retvalue = (LONG_PTR)IntGetWndProc( (WNDPROC)retvalue, unicode ); 1110 return retvalue; 1111 } 1112 1113 switch(offset) 1114 { 1115 case GWLP_USERDATA: retvalue = wndPtr->dwUserData; break; 1116 case GWL_STYLE: retvalue = wndPtr->style; break; 1117 case GWL_EXSTYLE: retvalue = wndPtr->ExStyle; break; 1118 case GWLP_ID: retvalue = wndPtr->IDMenu; break; 1119 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hModule; break; 1120 #if 0 1121 /* -1 is an undocumented case which returns WW* */ 1122 /* source: http://www.geoffchappell.com/studies/windows/win32/user32/structs/wnd/index.htm*/ 1123 case -1: retvalue = (ULONG_PTR)&wndPtr->ww; break; 1124 #else 1125 /* We don't have a WW but WND already contains the same fields in the right order, */ 1126 /* so we can return a pointer to its first field */ 1127 case -1: retvalue = (ULONG_PTR)&wndPtr->state; break; 1128 #endif 1129 case GWLP_WNDPROC: 1130 { 1131 if (!TestWindowProcess(wndPtr)) 1132 { 1133 SetLastError(ERROR_ACCESS_DENIED); 1134 retvalue = 0; 1135 } 1136 retvalue = (ULONG_PTR)IntGetWndProc(wndPtr, !unicode); 1137 break; 1138 } 1139 default: 1140 WARN("Unknown offset %d\n", offset ); 1141 SetLastError( ERROR_INVALID_INDEX ); 1142 break; 1143 } 1144 return retvalue; 1145 1146 } 1147 /* 1148 * @implemented 1149 */ 1150 LONG 1151 WINAPI 1152 GetWindowLongA ( HWND hWnd, int nIndex ) 1153 { 1154 return IntGetWindowLong( hWnd, nIndex, sizeof(LONG), FALSE ); 1155 } 1156 1157 /* 1158 * @implemented 1159 */ 1160 LONG 1161 WINAPI 1162 GetWindowLongW(HWND hWnd, int nIndex) 1163 { 1164 return IntGetWindowLong( hWnd, nIndex, sizeof(LONG), TRUE ); 1165 } 1166 1167 #ifdef _WIN64 1168 /* 1169 * @implemented 1170 */ 1171 LONG_PTR 1172 WINAPI 1173 GetWindowLongPtrA(HWND hWnd, 1174 INT nIndex) 1175 { 1176 return IntGetWindowLong( hWnd, nIndex, sizeof(LONG_PTR), FALSE ); 1177 } 1178 1179 /* 1180 * @implemented 1181 */ 1182 LONG_PTR 1183 WINAPI 1184 GetWindowLongPtrW(HWND hWnd, 1185 INT nIndex) 1186 { 1187 return IntGetWindowLong( hWnd, nIndex, sizeof(LONG_PTR), TRUE ); 1188 1189 } 1190 #endif // _WIN64 1191 1192 /* 1193 * @implemented 1194 */ 1195 WORD 1196 WINAPI 1197 GetWindowWord(HWND hWnd, int nIndex) 1198 { 1199 switch(nIndex) 1200 { 1201 case GWLP_ID: 1202 case GWLP_HINSTANCE: 1203 case GWLP_HWNDPARENT: 1204 break; 1205 default: 1206 if (nIndex < 0) 1207 { 1208 WARN("Invalid offset %d\n", nIndex ); 1209 SetLastError( ERROR_INVALID_INDEX ); 1210 return 0; 1211 } 1212 break; 1213 } 1214 return IntGetWindowLong( hWnd, nIndex, sizeof(WORD), FALSE ); 1215 } 1216 1217 /* 1218 * @implemented 1219 */ 1220 UINT 1221 WINAPI 1222 RealGetWindowClassW( 1223 HWND hwnd, 1224 LPWSTR pszType, 1225 UINT cchType) 1226 { 1227 UNICODE_STRING ClassName; 1228 1229 RtlInitEmptyUnicodeString(&ClassName, 1230 pszType, 1231 cchType * sizeof(WCHAR)); 1232 1233 return NtUserGetClassName(hwnd,TRUE,&ClassName); 1234 } 1235 1236 1237 /* 1238 * @implemented 1239 */ 1240 UINT 1241 WINAPI 1242 RealGetWindowClassA( 1243 HWND hwnd, 1244 LPSTR pszType, 1245 UINT cchType) 1246 { 1247 WCHAR tmpbuf[MAX_ATOM_LEN + 1]; 1248 UINT len; 1249 1250 if ((INT)cchType <= 0) return 0; 1251 if (!RealGetWindowClassW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0; 1252 RtlUnicodeToMultiByteN( pszType, cchType - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) ); 1253 pszType[len] = 0; 1254 return len; 1255 } 1256 1257 /* 1258 * Create a small icon based on a standard icon 1259 */ 1260 #if 0 // Keep vintage code from revision 18764 by GvG! 1261 static HICON 1262 CreateSmallIcon(HICON StdIcon) 1263 { 1264 HICON SmallIcon = NULL; 1265 ICONINFO StdInfo; 1266 int SmallIconWidth; 1267 int SmallIconHeight; 1268 BITMAP StdBitmapInfo; 1269 HDC hSourceDc = NULL; 1270 HDC hDestDc = NULL; 1271 ICONINFO SmallInfo; 1272 HBITMAP OldSourceBitmap = NULL; 1273 HBITMAP OldDestBitmap = NULL; 1274 1275 SmallInfo.hbmColor = NULL; 1276 SmallInfo.hbmMask = NULL; 1277 1278 /* We need something to work with... */ 1279 if (NULL == StdIcon) 1280 { 1281 goto cleanup; 1282 } 1283 1284 SmallIconWidth = GetSystemMetrics(SM_CXSMICON); 1285 SmallIconHeight = GetSystemMetrics(SM_CYSMICON); 1286 if (! GetIconInfo(StdIcon, &StdInfo)) 1287 { 1288 ERR("Failed to get icon info for icon 0x%x\n", StdIcon); 1289 goto cleanup; 1290 } 1291 if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo)) 1292 { 1293 ERR("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n", 1294 StdIcon, StdInfo.hbmColor); 1295 goto cleanup; 1296 } 1297 if (StdBitmapInfo.bmWidth == SmallIconWidth && 1298 StdBitmapInfo.bmHeight == SmallIconHeight) 1299 { 1300 /* Icon already has the correct dimensions */ 1301 return StdIcon; 1302 } 1303 1304 hSourceDc = CreateCompatibleDC(NULL); 1305 if (NULL == hSourceDc) 1306 { 1307 ERR("Failed to create source DC\n"); 1308 goto cleanup; 1309 } 1310 hDestDc = CreateCompatibleDC(NULL); 1311 if (NULL == hDestDc) 1312 { 1313 ERR("Failed to create dest DC\n"); 1314 goto cleanup; 1315 } 1316 1317 OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor); 1318 if (NULL == OldSourceBitmap) 1319 { 1320 ERR("Failed to select source color bitmap\n"); 1321 goto cleanup; 1322 } 1323 SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, 1324 SmallIconHeight); 1325 if (NULL == SmallInfo.hbmColor) 1326 { 1327 ERR("Failed to create color bitmap\n"); 1328 goto cleanup; 1329 } 1330 OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor); 1331 if (NULL == OldDestBitmap) 1332 { 1333 ERR("Failed to select dest color bitmap\n"); 1334 goto cleanup; 1335 } 1336 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight, 1337 hSourceDc, 0, 0, StdBitmapInfo.bmWidth, 1338 StdBitmapInfo.bmHeight, SRCCOPY)) 1339 { 1340 ERR("Failed to stretch color bitmap\n"); 1341 goto cleanup; 1342 } 1343 1344 if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask)) 1345 { 1346 ERR("Failed to select source mask bitmap\n"); 1347 goto cleanup; 1348 } 1349 SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight); 1350 if (NULL == SmallInfo.hbmMask) 1351 { 1352 ERR("Failed to create mask bitmap\n"); 1353 goto cleanup; 1354 } 1355 if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask)) 1356 { 1357 ERR("Failed to select dest mask bitmap\n"); 1358 goto cleanup; 1359 } 1360 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight, 1361 hSourceDc, 0, 0, StdBitmapInfo.bmWidth, 1362 StdBitmapInfo.bmHeight, SRCCOPY)) 1363 { 1364 ERR("Failed to stretch mask bitmap\n"); 1365 goto cleanup; 1366 } 1367 1368 SmallInfo.fIcon = TRUE; 1369 SmallInfo.xHotspot = SmallIconWidth / 2; 1370 SmallInfo.yHotspot = SmallIconHeight / 2; 1371 SmallIcon = CreateIconIndirect(&SmallInfo); 1372 if (NULL == SmallIcon) 1373 { 1374 ERR("Failed to create icon\n"); 1375 goto cleanup; 1376 } 1377 1378 cleanup: 1379 if (NULL != SmallInfo.hbmMask) 1380 { 1381 DeleteObject(SmallInfo.hbmMask); 1382 } 1383 if (NULL != OldDestBitmap) 1384 { 1385 SelectObject(hDestDc, OldDestBitmap); 1386 } 1387 if (NULL != SmallInfo.hbmColor) 1388 { 1389 DeleteObject(SmallInfo.hbmColor); 1390 } 1391 if (NULL != hDestDc) 1392 { 1393 DeleteDC(hDestDc); 1394 } 1395 if (NULL != OldSourceBitmap) 1396 { 1397 SelectObject(hSourceDc, OldSourceBitmap); 1398 } 1399 if (NULL != hSourceDc) 1400 { 1401 DeleteDC(hSourceDc); 1402 } 1403 1404 return SmallIcon; 1405 } 1406 #endif 1407 1408 ATOM WINAPI 1409 RegisterClassExWOWW(WNDCLASSEXW *lpwcx, 1410 LPDWORD pdwWowData, 1411 WORD fnID, 1412 DWORD dwFlags, 1413 BOOL ChkRegCls) 1414 { 1415 ATOM Atom; 1416 WNDCLASSEXW WndClass; 1417 UNICODE_STRING ClassName; 1418 UNICODE_STRING ClassVersion; 1419 UNICODE_STRING MenuName = {0}; 1420 CLSMENUNAME clsMenuName; 1421 ANSI_STRING AnsiMenuName; 1422 LPCWSTR lpszClsVersion; 1423 1424 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || 1425 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || 1426 lpwcx->lpszClassName == NULL) 1427 { 1428 TRACE("RegisterClassExWOWW Invalid Parameter Error!\n"); 1429 SetLastError(ERROR_INVALID_PARAMETER); 1430 return 0; 1431 } 1432 1433 if (ChkRegCls) 1434 { 1435 if (!RegisterDefaultClasses) RegisterSystemControls(); 1436 } 1437 /* 1438 * On real Windows this looks more like: 1439 * if (lpwcx->hInstance == User32Instance && 1440 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400) 1441 * But since I have no idea what the magic field in the 1442 * TEB structure means, I rather decided to omit that. 1443 * -- Filip Navara 1444 1445 GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400) 1446 */ 1447 if (lpwcx->hInstance == User32Instance) 1448 { 1449 TRACE("RegisterClassExWOWW User32Instance!\n"); 1450 SetLastError(ERROR_INVALID_PARAMETER); 1451 return 0; 1452 } 1453 /* Yes, this is correct. We should modify the passed structure. */ 1454 if (lpwcx->hInstance == NULL) 1455 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL); 1456 1457 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW)); 1458 /* 1459 if (NULL == WndClass.hIconSm) 1460 { 1461 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon); 1462 } 1463 */ 1464 RtlInitEmptyAnsiString(&AnsiMenuName, NULL, 0); 1465 if (WndClass.lpszMenuName != NULL) 1466 { 1467 if (!IS_INTRESOURCE(WndClass.lpszMenuName)) 1468 { 1469 if (WndClass.lpszMenuName[0]) 1470 { 1471 RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName); 1472 RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE); 1473 } 1474 } 1475 else 1476 { 1477 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName; 1478 AnsiMenuName.Buffer = (PCHAR)WndClass.lpszMenuName; 1479 } 1480 } 1481 1482 if (IS_ATOM(WndClass.lpszClassName)) 1483 { 1484 ClassName.Length = 1485 ClassName.MaximumLength = 0; 1486 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName; 1487 } 1488 else 1489 { 1490 RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); 1491 } 1492 1493 ClassVersion = ClassName; 1494 if (fnID == 0) 1495 { 1496 lpszClsVersion = ClassNameToVersion(lpwcx->lpszClassName, NULL, NULL, NULL, FALSE); 1497 if (lpszClsVersion) 1498 { 1499 RtlInitUnicodeString(&ClassVersion, lpszClsVersion); 1500 } 1501 } 1502 1503 clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer; 1504 clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; 1505 clsMenuName.pusMenuName = &MenuName; 1506 1507 Atom = NtUserRegisterClassExWOW( &WndClass, 1508 &ClassName, 1509 &ClassVersion, 1510 &clsMenuName, 1511 fnID, 1512 dwFlags, 1513 pdwWowData); 1514 1515 TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", 1516 Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, 1517 lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass); 1518 1519 return Atom; 1520 } 1521 1522 /* 1523 * @implemented 1524 */ 1525 ATOM WINAPI 1526 RegisterClassExA(CONST WNDCLASSEXA *lpwcx) 1527 { 1528 RTL_ATOM Atom; 1529 WNDCLASSEXW WndClass; 1530 WCHAR mname[MAX_BUFFER_LEN]; 1531 WCHAR cname[MAX_BUFFER_LEN]; 1532 1533 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA)); 1534 1535 if (WndClass.lpszMenuName != NULL) 1536 { 1537 if (!IS_INTRESOURCE(WndClass.lpszMenuName)) 1538 { 1539 if (WndClass.lpszMenuName[0]) 1540 { 1541 if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszMenuName, -1, mname, MAX_ATOM_LEN + 1 )) return 0; 1542 1543 WndClass.lpszMenuName = mname; 1544 } 1545 } 1546 } 1547 1548 if (!IS_ATOM(WndClass.lpszClassName)) 1549 { 1550 if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszClassName, -1, cname, MAX_ATOM_LEN + 1 )) return 0; 1551 1552 WndClass.lpszClassName = cname; 1553 } 1554 1555 Atom = RegisterClassExWOWW( &WndClass, 1556 0, 1557 0, 1558 CSF_ANSIPROC, 1559 TRUE); 1560 1561 TRACE("A atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", 1562 Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, 1563 lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass); 1564 1565 return (ATOM)Atom; 1566 } 1567 1568 /* 1569 * @implemented 1570 */ 1571 ATOM WINAPI 1572 RegisterClassExW(CONST WNDCLASSEXW *lpwcx) 1573 { 1574 ATOM Atom; 1575 1576 Atom = RegisterClassExWOWW( (WNDCLASSEXW *)lpwcx, 0, 0, 0, TRUE); 1577 1578 TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d\n", 1579 Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, 1580 lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra); 1581 1582 return Atom; 1583 } 1584 1585 /* 1586 * @implemented 1587 */ 1588 ATOM WINAPI 1589 RegisterClassA(CONST WNDCLASSA *lpWndClass) 1590 { 1591 WNDCLASSEXA Class; 1592 1593 if (lpWndClass == NULL) 1594 return 0; 1595 1596 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA)); 1597 Class.cbSize = sizeof(WNDCLASSEXA); 1598 Class.hIconSm = NULL; 1599 1600 return RegisterClassExA(&Class); 1601 } 1602 1603 /* 1604 * @implemented 1605 */ 1606 ATOM WINAPI 1607 RegisterClassW(CONST WNDCLASSW *lpWndClass) 1608 { 1609 WNDCLASSEXW Class; 1610 1611 if (lpWndClass == NULL) 1612 return 0; 1613 1614 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW)); 1615 Class.cbSize = sizeof(WNDCLASSEXW); 1616 Class.hIconSm = NULL; 1617 1618 return RegisterClassExW(&Class); 1619 } 1620 1621 /* 1622 * @implemented 1623 */ 1624 DWORD 1625 WINAPI 1626 SetClassLongA (HWND hWnd, 1627 int nIndex, 1628 LONG dwNewLong) 1629 { 1630 PSTR lpStr = (PSTR)(ULONG_PTR)dwNewLong; 1631 UNICODE_STRING Value = {0}; 1632 BOOL Allocated = FALSE; 1633 DWORD Ret; 1634 1635 /* FIXME - portability!!!! */ 1636 1637 if (nIndex == GCL_MENUNAME && lpStr != NULL) 1638 { 1639 if (!IS_INTRESOURCE(lpStr)) 1640 { 1641 if (!RtlCreateUnicodeStringFromAsciiz(&Value, 1642 lpStr)) 1643 { 1644 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1645 return 0; 1646 } 1647 1648 Allocated = TRUE; 1649 } 1650 else 1651 Value.Buffer = (PWSTR)lpStr; 1652 1653 dwNewLong = (LONG_PTR)&Value; 1654 } 1655 else if (nIndex == GCW_ATOM && lpStr != NULL) 1656 { 1657 if (!IS_ATOM(lpStr)) 1658 { 1659 if (!RtlCreateUnicodeStringFromAsciiz(&Value, 1660 lpStr)) 1661 { 1662 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1663 return 0; 1664 } 1665 1666 Allocated = TRUE; 1667 } 1668 else 1669 Value.Buffer = (PWSTR)lpStr; 1670 1671 dwNewLong = (LONG_PTR)&Value; 1672 } 1673 1674 Ret = (DWORD)NtUserSetClassLong(hWnd, 1675 nIndex, 1676 dwNewLong, 1677 TRUE); 1678 1679 if (Allocated) 1680 { 1681 RtlFreeUnicodeString(&Value); 1682 } 1683 1684 return Ret; 1685 } 1686 1687 1688 /* 1689 * @implemented 1690 */ 1691 DWORD 1692 WINAPI 1693 SetClassLongW(HWND hWnd, 1694 int nIndex, 1695 LONG dwNewLong) 1696 { 1697 PWSTR lpStr = (PWSTR)(ULONG_PTR)dwNewLong; 1698 UNICODE_STRING Value = {0}; 1699 1700 TRACE("%p %d %lx\n", hWnd, nIndex, dwNewLong); 1701 1702 /* FIXME - portability!!!! */ 1703 1704 if (nIndex == GCL_MENUNAME && lpStr != NULL) 1705 { 1706 if (!IS_INTRESOURCE(lpStr)) 1707 { 1708 RtlInitUnicodeString(&Value, 1709 lpStr); 1710 } 1711 else 1712 Value.Buffer = lpStr; 1713 1714 dwNewLong = (LONG_PTR)&Value; 1715 } 1716 else if (nIndex == GCW_ATOM && lpStr != NULL) 1717 { 1718 if (!IS_ATOM(lpStr)) 1719 { 1720 RtlInitUnicodeString(&Value, 1721 lpStr); 1722 } 1723 else 1724 Value.Buffer = lpStr; 1725 1726 dwNewLong = (LONG_PTR)&Value; 1727 } 1728 1729 return (DWORD)NtUserSetClassLong(hWnd, 1730 nIndex, 1731 dwNewLong, 1732 FALSE); 1733 } 1734 1735 #ifdef _WIN64 1736 /* 1737 * @unimplemented 1738 */ 1739 ULONG_PTR 1740 WINAPI 1741 SetClassLongPtrA(HWND hWnd, 1742 INT nIndex, 1743 LONG_PTR dwNewLong) 1744 { 1745 UNIMPLEMENTED; 1746 return 0; 1747 } 1748 1749 /* 1750 * @unimplemented 1751 */ 1752 ULONG_PTR 1753 WINAPI 1754 SetClassLongPtrW(HWND hWnd, 1755 INT nIndex, 1756 LONG_PTR dwNewLong) 1757 { 1758 UNIMPLEMENTED; 1759 return 0; 1760 } 1761 #endif // _WIN64 1762 1763 /* 1764 * @implemented 1765 */ 1766 WORD 1767 WINAPI 1768 SetClassWord( 1769 HWND hWnd, 1770 int nIndex, 1771 WORD wNewWord) 1772 /* 1773 * NOTE: Obsoleted in 32-bit windows 1774 */ 1775 { 1776 if ((nIndex < 0) && (nIndex != GCW_ATOM)) 1777 return 0; 1778 1779 return (WORD) SetClassLongW ( hWnd, nIndex, wNewWord ); 1780 } 1781 1782 /* 1783 * @implemented 1784 */ 1785 WORD 1786 WINAPI 1787 SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord ) 1788 { 1789 switch(nIndex) 1790 { 1791 case GWLP_ID: 1792 case GWLP_HINSTANCE: 1793 case GWLP_HWNDPARENT: 1794 break; 1795 default: 1796 if (nIndex < 0) 1797 { 1798 WARN("Invalid offset %d\n", nIndex ); 1799 SetLastError( ERROR_INVALID_INDEX ); 1800 return 0; 1801 } 1802 break; 1803 } 1804 return NtUserSetWindowLong( hWnd, nIndex, wNewWord, FALSE ); 1805 } 1806 1807 /* 1808 * @implemented 1809 */ 1810 LONG 1811 WINAPI 1812 DECLSPEC_HOTPATCH 1813 SetWindowLongA( 1814 HWND hWnd, 1815 int nIndex, 1816 LONG dwNewLong) 1817 { 1818 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE); 1819 } 1820 1821 /* 1822 * @implemented 1823 */ 1824 LONG 1825 WINAPI 1826 SetWindowLongW( 1827 HWND hWnd, 1828 int nIndex, 1829 LONG dwNewLong) 1830 { 1831 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE); 1832 } 1833 1834 #ifdef _WIN64 1835 /* 1836 * @implemented 1837 */ 1838 LONG_PTR 1839 WINAPI 1840 SetWindowLongPtrA(HWND hWnd, 1841 INT nIndex, 1842 LONG_PTR dwNewLong) 1843 { 1844 return NtUserSetWindowLongPtr(hWnd, nIndex, dwNewLong, TRUE); 1845 } 1846 1847 /* 1848 * @implemented 1849 */ 1850 LONG_PTR 1851 WINAPI 1852 SetWindowLongPtrW(HWND hWnd, 1853 INT nIndex, 1854 LONG_PTR dwNewLong) 1855 { 1856 return NtUserSetWindowLongPtr(hWnd, nIndex, dwNewLong, FALSE); 1857 } 1858 #endif 1859 1860 /* 1861 * @implemented 1862 */ 1863 BOOL 1864 WINAPI 1865 UnregisterClassA( 1866 LPCSTR lpClassName, 1867 HINSTANCE hInstance) 1868 { 1869 UNICODE_STRING ClassName = {0}; 1870 BOOL Ret; 1871 LPCWSTR lpszClsVersion; 1872 BOOL ConvertedString = FALSE; 1873 1874 TRACE("class/atom: %s/%04x %p\n", 1875 IS_ATOM(lpClassName) ? NULL : lpClassName, 1876 IS_ATOM(lpClassName) ? lpClassName : 0, 1877 hInstance); 1878 1879 lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, TRUE); 1880 if (lpszClsVersion) 1881 { 1882 RtlInitUnicodeString(&ClassName, lpszClsVersion); 1883 } 1884 else if (!IS_ATOM(lpClassName)) 1885 { 1886 ConvertedString = TRUE; 1887 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpClassName)) 1888 { 1889 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1890 return 0; 1891 } 1892 } 1893 else 1894 { 1895 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); 1896 } 1897 1898 Ret = NtUserUnregisterClass(&ClassName, hInstance, 0); 1899 1900 if (ConvertedString) 1901 RtlFreeUnicodeString(&ClassName); 1902 1903 return Ret; 1904 } 1905 1906 1907 /* 1908 * @implemented 1909 */ 1910 BOOL 1911 WINAPI 1912 UnregisterClassW( 1913 LPCWSTR lpClassName, 1914 HINSTANCE hInstance) 1915 { 1916 UNICODE_STRING ClassName = {0}; 1917 LPCWSTR lpszClsVersion; 1918 1919 TRACE("class/atom: %S/%04x %p\n", 1920 IS_ATOM(lpClassName) ? NULL : lpClassName, 1921 IS_ATOM(lpClassName) ? lpClassName : 0, 1922 hInstance); 1923 1924 lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, FALSE); 1925 if (lpszClsVersion) 1926 { 1927 RtlInitUnicodeString(&ClassName, lpszClsVersion); 1928 } 1929 else if (!IS_ATOM(lpClassName)) 1930 { 1931 RtlInitUnicodeString(&ClassName, lpClassName); 1932 } 1933 else 1934 { 1935 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); 1936 } 1937 1938 return NtUserUnregisterClass(&ClassName, hInstance, 0); 1939 } 1940 1941 /* EOF */ 1942