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