fix bug 838 (Sol.exe is missing it's menubar)
[reactos.git] / reactos / lib / user32 / windows / class.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/class.c
6 * PURPOSE: Window classes
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * 09-05-2001 CSH Created
10 */
11
12 #include <user32.h>
13
14 static BOOL GetClassInfoExCommon(
15 HINSTANCE hInst,
16 LPCWSTR lpszClass,
17 LPWNDCLASSEXW lpwcx,
18 BOOL unicode)
19 {
20 LPWSTR str;
21 UNICODE_STRING str2, str3;
22 WNDCLASSEXW w;
23 BOOL retval;
24 NTSTATUS Status;
25
26 if ( !lpszClass || !lpwcx )
27 {
28 SetLastError(ERROR_INVALID_PARAMETER);
29 return FALSE;
30 }
31
32 if(IS_ATOM(lpszClass))
33 str = (LPWSTR)lpszClass;
34 else
35 {
36 extern BOOL ControlsInitialized;
37
38 if (unicode)
39 {
40 str = HEAP_strdupW ( lpszClass, wcslen(lpszClass) );
41
42 if ( !str )
43 {
44 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
45 return FALSE;
46 }
47 }
48
49 else
50 {
51 Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL);
52
53 if (! NT_SUCCESS(Status))
54 {
55 SetLastError(RtlNtStatusToDosError(Status));
56 return FALSE;
57 }
58 }
59
60 /* Register built-in controls if not already done */
61 if ( !ControlsInitialized )
62 {
63 ControlsInitialized = ControlsInit(str);
64 }
65 }
66
67 str2.Length = str3.Length = 0;
68 str2.MaximumLength = str3.MaximumLength = 255;
69 str2.Buffer = (PWSTR)HEAP_alloc ( str2.MaximumLength * sizeof(WCHAR) );
70 if ( !str2.Buffer )
71 {
72 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
73 if ( !IS_ATOM(str) )
74 HEAP_free ( str );
75 return FALSE;
76 }
77
78 str3.Buffer = (PWSTR)HEAP_alloc ( str3.MaximumLength * sizeof(WCHAR) );
79 if ( !str3.Buffer )
80 {
81 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
82 HEAP_free ( str2.Buffer );
83 if ( !IS_ATOM(str) )
84 HEAP_free ( str );
85 return FALSE;
86 }
87
88 w.lpszMenuName = (LPCWSTR)&str2;
89 w.lpszClassName = (LPCWSTR)&str3;
90
91 /* get info about system classes? */
92 if (!hInst) hInst = User32Instance;
93
94 retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0);
95
96 w.hInstance = (hInst == User32Instance) ? 0 : hInst;
97
98 if ( !IS_ATOM(str) )
99 HEAP_free(str);
100
101 RtlCopyMemory ( lpwcx, &w, sizeof(WNDCLASSEXW) );
102
103 if ( !IS_INTRESOURCE(w.lpszMenuName) && w.lpszMenuName )
104 {
105 if (unicode)
106 lpwcx->lpszMenuName = heap_string_poolW ( str2.Buffer, str2.Length );
107 else
108 ((LPWNDCLASSEXA) lpwcx)->lpszMenuName = heap_string_poolA ( str2.Buffer, str2.Length );
109 }
110
111 if ( !IS_ATOM(w.lpszClassName) && w.lpszClassName )
112 {
113 if (unicode)
114 lpwcx->lpszClassName = heap_string_poolW ( str3.Buffer, str3.Length );
115 else
116 ((LPWNDCLASSEXA) lpwcx)->lpszClassName = heap_string_poolA ( str3.Buffer, str3.Length );
117 }
118
119 HEAP_free ( str2.Buffer );
120 HEAP_free ( str3.Buffer );
121
122 return retval;
123 }
124
125
126 /*
127 * @implemented
128 */
129 BOOL
130 STDCALL
131 GetClassInfoExA(
132 HINSTANCE hinst,
133 LPCSTR lpszClass,
134 LPWNDCLASSEXA lpwcx)
135 {
136 return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE);
137 }
138
139
140 /*
141 * @implemented
142 */
143 BOOL
144 STDCALL
145 GetClassInfoExW(
146 HINSTANCE hinst,
147 LPCWSTR lpszClass,
148 LPWNDCLASSEXW lpwcx)
149 {
150 return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE);
151 }
152
153
154 /*
155 * @implemented
156 */
157 BOOL
158 STDCALL
159 GetClassInfoA(
160 HINSTANCE hInstance,
161 LPCSTR lpClassName,
162 LPWNDCLASSA lpWndClass)
163 {
164 WNDCLASSEXA w;
165 BOOL retval;
166
167 if ( !lpClassName || !lpWndClass )
168 {
169 SetLastError(ERROR_INVALID_PARAMETER);
170 return FALSE;
171 }
172
173 retval = GetClassInfoExA(hInstance,lpClassName,&w);
174 if (retval)
175 {
176 RtlCopyMemory ( lpWndClass, &w.style, sizeof(WNDCLASSA) );
177 }
178 return retval;
179 }
180
181 /*
182 * @implemented
183 */
184 BOOL
185 STDCALL
186 GetClassInfoW(
187 HINSTANCE hInstance,
188 LPCWSTR lpClassName,
189 LPWNDCLASSW lpWndClass)
190 {
191 WNDCLASSEXW w;
192 BOOL retval;
193
194 if(!lpClassName || !lpWndClass)
195 {
196 SetLastError(ERROR_INVALID_PARAMETER);
197 return FALSE;
198 }
199
200 retval = GetClassInfoExW(hInstance,lpClassName,&w);
201 RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
202 return retval;
203 }
204
205
206 /*
207 * @implemented
208 */
209 DWORD STDCALL
210 GetClassLongA(HWND hWnd, int nIndex)
211 {
212 switch (nIndex)
213 {
214 case GCL_HBRBACKGROUND:
215 {
216 DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
217 if (hBrush != 0 && hBrush < 0x4000)
218 hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
219 return hBrush;
220 }
221
222 case GCL_MENUNAME:
223 {
224 PUNICODE_STRING Name;
225 Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, TRUE);
226 if (IS_INTRESOURCE(Name))
227 return (DWORD)Name;
228 else
229 return (DWORD)heap_string_poolA(Name->Buffer, Name->Length);
230 }
231
232 default:
233 return NtUserGetClassLong(hWnd, nIndex, TRUE);
234 }
235 }
236
237 /*
238 * @implemented
239 */
240 DWORD STDCALL
241 GetClassLongW ( HWND hWnd, int nIndex )
242 {
243 switch (nIndex)
244 {
245 case GCL_HBRBACKGROUND:
246 {
247 DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
248 if (hBrush != 0 && hBrush < 0x4000)
249 hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
250 return hBrush;
251 }
252
253 case GCL_MENUNAME:
254 {
255 PUNICODE_STRING Name;
256 Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, FALSE);
257 if (IS_INTRESOURCE(Name))
258 return (DWORD)Name;
259 else
260 return (DWORD)heap_string_poolW(Name->Buffer, Name->Length);
261 }
262
263 default:
264 return NtUserGetClassLong(hWnd, nIndex, FALSE);
265 }
266 }
267
268
269 /*
270 * @implemented
271 */
272 int STDCALL
273 GetClassNameA(
274 HWND hWnd,
275 LPSTR lpClassName,
276 int nMaxCount)
277 {
278 int result;
279 LPWSTR ClassNameW;
280 NTSTATUS Status;
281
282 if(!lpClassName)
283 return 0;
284
285 ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) );
286
287 result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
288
289 Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result );
290
291 HEAP_free ( ClassNameW );
292
293 if ( !NT_SUCCESS(Status) )
294 return 0;
295
296 return result;
297 }
298
299
300 /*
301 * @implemented
302 */
303 int
304 STDCALL
305 GetClassNameW(
306 HWND hWnd,
307 LPWSTR lpClassName,
308 int nMaxCount)
309 {
310 return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
311 }
312
313
314 /*
315 * @implemented
316 */
317 WORD
318 STDCALL
319 GetClassWord(
320 HWND hWnd,
321 int nIndex)
322 /*
323 * NOTE: Obsoleted in 32-bit windows
324 */
325 {
326 if ((nIndex < 0) && (nIndex != GCW_ATOM))
327 return 0;
328
329 return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
330 }
331
332
333 /*
334 * @implemented
335 */
336 LONG
337 STDCALL
338 GetWindowLongA ( HWND hWnd, int nIndex )
339 {
340 return NtUserGetWindowLong(hWnd, nIndex, TRUE);
341 }
342
343
344 /*
345 * @implemented
346 */
347 LONG
348 STDCALL
349 GetWindowLongW(HWND hWnd, int nIndex)
350 {
351 return NtUserGetWindowLong(hWnd, nIndex, FALSE);
352 }
353
354 /*
355 * @implemented
356 */
357 WORD
358 STDCALL
359 GetWindowWord(HWND hWnd, int nIndex)
360 {
361 return (WORD)NtUserGetWindowLong(hWnd, nIndex, TRUE);
362 }
363
364 /*
365 * @implemented
366 */
367 WORD
368 STDCALL
369 SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
370 {
371 return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
372 }
373
374 /*
375 * @implemented
376 */
377 UINT
378 STDCALL
379 RealGetWindowClassW(
380 HWND hwnd,
381 LPWSTR pszType,
382 UINT cchType)
383 {
384 /* FIXME: Implement correct functionality of RealGetWindowClass */
385 return GetClassNameW(hwnd,pszType,cchType);
386 }
387
388
389 /*
390 * @implemented
391 */
392 UINT
393 STDCALL
394 RealGetWindowClassA(
395 HWND hwnd,
396 LPSTR pszType,
397 UINT cchType)
398 {
399 /* FIXME: Implement correct functionality of RealGetWindowClass */
400 return GetClassNameA(hwnd,pszType,cchType);
401 }
402
403 /*
404 * Create a small icon based on a standard icon
405 */
406 static HICON
407 CreateSmallIcon(HICON StdIcon)
408 {
409 HICON SmallIcon = NULL;
410 ICONINFO StdInfo;
411 int SmallIconWidth;
412 int SmallIconHeight;
413 BITMAP StdBitmapInfo;
414 HDC hInfoDc = NULL;
415 HDC hSourceDc = NULL;
416 HDC hDestDc = NULL;
417 ICONINFO SmallInfo;
418 HBITMAP OldSourceBitmap = NULL;
419 HBITMAP OldDestBitmap = NULL;
420
421 SmallInfo.hbmColor = NULL;
422 SmallInfo.hbmMask = NULL;
423
424 /* We need something to work with... */
425 if (NULL == StdIcon)
426 {
427 goto cleanup;
428 }
429
430 SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
431 SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
432 if (! GetIconInfo(StdIcon, &StdInfo))
433 {
434 DPRINT1("Failed to get icon info for icon 0x%x\n", StdIcon);
435 goto cleanup;
436 }
437 if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
438 {
439 DPRINT1("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
440 StdIcon, StdInfo.hbmColor);
441 goto cleanup;
442 }
443 if (StdBitmapInfo.bmWidth == SmallIconWidth &&
444 StdBitmapInfo.bmHeight == SmallIconHeight)
445 {
446 /* Icon already has the correct dimensions */
447 return StdIcon;
448 }
449
450 /* Get a handle to a info DC and handles to DCs which can be used to
451 select a bitmap into. This is done to avoid triggering a switch to
452 graphics mode (if we're currently in text/blue screen mode) */
453 hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
454 if (NULL == hInfoDc)
455 {
456 DPRINT1("Failed to create info DC\n");
457 goto cleanup;
458 }
459 hSourceDc = CreateCompatibleDC(NULL);
460 if (NULL == hSourceDc)
461 {
462 DPRINT1("Failed to create source DC\n");
463 goto cleanup;
464 }
465 hDestDc = CreateCompatibleDC(NULL);
466 if (NULL == hDestDc)
467 {
468 DPRINT1("Failed to create dest DC\n");
469 goto cleanup;
470 }
471
472 OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
473 if (NULL == OldSourceBitmap)
474 {
475 DPRINT1("Failed to select source color bitmap\n");
476 goto cleanup;
477 }
478 SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
479 SmallIconHeight);
480 if (NULL == SmallInfo.hbmColor)
481 {
482 DPRINT1("Failed to create color bitmap\n");
483 goto cleanup;
484 }
485 OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
486 if (NULL == OldDestBitmap)
487 {
488 DPRINT1("Failed to select dest color bitmap\n");
489 goto cleanup;
490 }
491 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
492 hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
493 StdBitmapInfo.bmHeight, SRCCOPY))
494 {
495 DPRINT1("Failed to stretch color bitmap\n");
496 goto cleanup;
497 }
498
499 if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
500 {
501 DPRINT1("Failed to select source mask bitmap\n");
502 goto cleanup;
503 }
504 SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
505 NULL);
506 if (NULL == SmallInfo.hbmMask)
507 {
508 DPRINT1("Failed to create mask bitmap\n");
509 goto cleanup;
510 }
511 if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
512 {
513 DPRINT1("Failed to select dest mask bitmap\n");
514 goto cleanup;
515 }
516 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
517 hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
518 StdBitmapInfo.bmHeight, SRCCOPY))
519 {
520 DPRINT1("Failed to stretch mask bitmap\n");
521 goto cleanup;
522 }
523
524 SmallInfo.fIcon = TRUE;
525 SmallInfo.xHotspot = SmallIconWidth / 2;
526 SmallInfo.yHotspot = SmallIconHeight / 2;
527 SmallIcon = CreateIconIndirect(&SmallInfo);
528 if (NULL == SmallIcon)
529 {
530 DPRINT1("Failed to create icon\n");
531 goto cleanup;
532 }
533
534 cleanup:
535 if (NULL != SmallInfo.hbmMask)
536 {
537 DeleteObject(SmallInfo.hbmMask);
538 }
539 if (NULL != OldDestBitmap)
540 {
541 SelectObject(hDestDc, OldDestBitmap);
542 }
543 if (NULL != SmallInfo.hbmColor)
544 {
545 DeleteObject(SmallInfo.hbmColor);
546 }
547 if (NULL != hDestDc)
548 {
549 DeleteDC(hDestDc);
550 }
551 if (NULL != OldSourceBitmap)
552 {
553 SelectObject(hSourceDc, OldSourceBitmap);
554 }
555 if (NULL != hSourceDc)
556 {
557 DeleteDC(hSourceDc);
558 }
559 if (NULL != hInfoDc)
560 {
561 DeleteDC(hInfoDc);
562 }
563
564 return SmallIcon;
565 }
566
567 /*
568 * @implemented
569 */
570 ATOM STDCALL
571 RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
572 {
573 RTL_ATOM Atom;
574 WNDCLASSEXA WndClass;
575 UNICODE_STRING ClassName;
576 UNICODE_STRING MenuName;
577 HMENU hMenu;
578
579 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) ||
580 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
581 lpwcx->lpszClassName == NULL)
582 {
583 SetLastError(ERROR_INVALID_PARAMETER);
584 return 0;
585 }
586
587 /*
588 * On real Windows this looks more like:
589 * if (lpwcx->hInstance == User32Instance &&
590 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
591 * But since I have no idea what the magic field in the
592 * TEB structure means, I rather decided to omit that.
593 * -- Filip Navara
594 */
595 if (lpwcx->hInstance == User32Instance)
596 {
597 SetLastError(ERROR_INVALID_PARAMETER);
598 return 0;
599 }
600
601 /* Yes, this is correct. We should modify the passed structure. */
602 if (lpwcx->hInstance == NULL)
603 ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
604
605 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
606
607 if (NULL == WndClass.hIconSm)
608 {
609 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
610 }
611
612 if HIWORD(lpwcx->lpszMenuName)
613 {
614 hMenu = 0;
615 RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName);
616 }
617 else
618 {
619 MenuName.Length =
620 MenuName.MaximumLength = 0;
621 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
622 hMenu = LoadMenuA(WndClass.hInstance, lpwcx->lpszMenuName);
623 }
624
625 if (IS_ATOM(WndClass.lpszClassName))
626 {
627 ClassName.Length =
628 ClassName.MaximumLength = 0;
629 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
630 } else
631 {
632 RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName);
633 }
634
635 Atom = NtUserRegisterClassExWOW(
636 (WNDCLASSEXW*)&WndClass,
637 &ClassName,
638 &ClassName,
639 &MenuName,
640 NULL,
641 REGISTERCLASS_ANSI,
642 0,
643 hMenu);
644
645 if (!IS_ATOM(WndClass.lpszMenuName))
646 RtlFreeUnicodeString(&MenuName);
647 if (!IS_ATOM(WndClass.lpszClassName))
648 RtlFreeUnicodeString(&ClassName);
649
650 return (ATOM)Atom;
651 }
652
653 /*
654 * @implemented
655 */
656 ATOM STDCALL
657 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
658 {
659 WNDCLASSEXW WndClass;
660 UNICODE_STRING ClassName;
661 UNICODE_STRING MenuName;
662 HMENU hMenu;
663
664 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
665 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
666 lpwcx->lpszClassName == NULL)
667 {
668 SetLastError(ERROR_INVALID_PARAMETER);
669 return 0;
670 }
671
672 /*
673 * On real Windows this looks more like:
674 * if (lpwcx->hInstance == User32Instance &&
675 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
676 * But since I have no idea what the magic field in the
677 * TEB structure means, I rather decided to omit that.
678 * -- Filip Navara
679 */
680 if (lpwcx->hInstance == User32Instance)
681 {
682 SetLastError(ERROR_INVALID_PARAMETER);
683 return 0;
684 }
685
686 /* Yes, this is correct. We should modify the passed structure. */
687 if (lpwcx->hInstance == NULL)
688 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
689
690 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
691
692 if (NULL == WndClass.hIconSm)
693 {
694 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
695 }
696
697 if HIWORD(lpwcx->lpszMenuName)
698 {
699 hMenu = 0;
700 RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
701 }
702 else
703 {
704 MenuName.Length =
705 MenuName.MaximumLength = 0;
706 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
707 hMenu = LoadMenuW(WndClass.hInstance, lpwcx->lpszMenuName);
708 }
709
710 if (IS_ATOM(WndClass.lpszClassName))
711 {
712 ClassName.Length =
713 ClassName.MaximumLength = 0;
714 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
715 } else
716 {
717 RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
718 }
719
720 return (ATOM)NtUserRegisterClassExWOW(
721 &WndClass,
722 &ClassName,
723 &ClassName,
724 &MenuName,
725 NULL,
726 0,
727 0,
728 hMenu);
729 }
730
731 /*
732 * @implemented
733 */
734 ATOM STDCALL
735 RegisterClassA(CONST WNDCLASSA *lpWndClass)
736 {
737 WNDCLASSEXA Class;
738
739 if (lpWndClass == NULL)
740 return 0;
741
742 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
743 Class.cbSize = sizeof(WNDCLASSEXA);
744 Class.hIconSm = NULL;
745
746 return RegisterClassExA(&Class);
747 }
748
749 /*
750 * @implemented
751 */
752 ATOM STDCALL
753 RegisterClassW(CONST WNDCLASSW *lpWndClass)
754 {
755 WNDCLASSEXW Class;
756
757 if (lpWndClass == NULL)
758 return 0;
759
760 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
761 Class.cbSize = sizeof(WNDCLASSEXW);
762 Class.hIconSm = NULL;
763
764 return RegisterClassExW(&Class);
765 }
766
767 /*
768 * @implemented
769 */
770 DWORD
771 STDCALL
772 SetClassLongA (
773 HWND hWnd,
774 int nIndex,
775 LONG dwNewLong)
776 {
777 UNICODE_STRING str2buf;
778 PUNICODE_STRING str;
779 PUNICODE_STRING str2 = &str2buf;
780
781 if ( nIndex != GCL_MENUNAME )
782 {
783 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
784 }
785 if ( IS_INTRESOURCE(dwNewLong) )
786 {
787 str2 = (PUNICODE_STRING)dwNewLong;
788 }
789 else
790 {
791 RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong );
792 }
793
794 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
795
796 if ( !IS_INTRESOURCE(dwNewLong) )
797 {
798 RtlFreeUnicodeString ( str2 );
799 }
800 if ( IS_INTRESOURCE(str) )
801 {
802 return (DWORD)str;
803 }
804 else
805 {
806 return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
807 }
808 }
809
810
811 /*
812 * @implemented
813 */
814 DWORD
815 STDCALL
816 SetClassLongW(
817 HWND hWnd,
818 int nIndex,
819 LONG dwNewLong)
820 {
821 UNICODE_STRING str2buf;
822 PUNICODE_STRING str;
823 PUNICODE_STRING str2 = &str2buf;
824
825 if (nIndex != GCL_MENUNAME )
826 {
827 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
828 }
829 if ( IS_INTRESOURCE(dwNewLong) )
830 {
831 str2 = (PUNICODE_STRING)dwNewLong;
832 }
833 else
834 {
835 RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong );
836 }
837
838 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
839
840 if ( !IS_INTRESOURCE(dwNewLong) )
841 {
842 RtlFreeUnicodeString(str2);
843 }
844 if ( IS_INTRESOURCE(str) )
845 {
846 return (DWORD)str;
847 }
848 else
849 {
850 return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
851 }
852 }
853
854
855 /*
856 * @implemented
857 */
858 WORD
859 STDCALL
860 SetClassWord(
861 HWND hWnd,
862 int nIndex,
863 WORD wNewWord)
864 /*
865 * NOTE: Obsoleted in 32-bit windows
866 */
867 {
868 if ((nIndex < 0) && (nIndex != GCW_ATOM))
869 return 0;
870
871 return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
872 }
873
874
875 /*
876 * @implemented
877 */
878 LONG
879 STDCALL
880 SetWindowLongA(
881 HWND hWnd,
882 int nIndex,
883 LONG dwNewLong)
884 {
885 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
886 }
887
888
889 /*
890 * @implemented
891 */
892 LONG
893 STDCALL
894 SetWindowLongW(
895 HWND hWnd,
896 int nIndex,
897 LONG dwNewLong)
898 {
899 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
900 }
901
902
903 /*
904 * @implemented
905 */
906 BOOL
907 STDCALL
908 UnregisterClassA(
909 LPCSTR lpClassName,
910 HINSTANCE hInstance)
911 {
912 LPWSTR ClassName;
913 NTSTATUS Status;
914 BOOL Result;
915
916 if(!IS_ATOM(lpClassName))
917 {
918 Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
919 if(!NT_SUCCESS(Status))
920 {
921 SetLastError(RtlNtStatusToDosError(Status));
922 return FALSE;
923 }
924 }
925 else
926 ClassName = (LPWSTR)lpClassName;
927
928 Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
929
930 if(ClassName && !IS_ATOM(lpClassName))
931 HEAP_free(ClassName);
932
933 return Result;
934 }
935
936
937 /*
938 * @implemented
939 */
940 BOOL
941 STDCALL
942 UnregisterClassW(
943 LPCWSTR lpClassName,
944 HINSTANCE hInstance)
945 {
946 return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
947 }
948
949 /* EOF */