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