Synthesize a small icon if none given
[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
578 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
579 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
580 lpwcx->lpszClassName == NULL)
581 {
582 SetLastError(ERROR_INVALID_PARAMETER);
583 return 0;
584 }
585
586 /*
587 * On real Windows this looks more like:
588 * if (lpwcx->hInstance == User32Instance &&
589 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
590 * But since I have no idea what the magic field in the
591 * TEB structure means, I rather decided to omit that.
592 * -- Filip Navara
593 */
594 if (lpwcx->hInstance == User32Instance)
595 {
596 SetLastError(ERROR_INVALID_PARAMETER);
597 return 0;
598 }
599
600 /* Yes, this is correct. We should modify the passed structure. */
601 if (lpwcx->hInstance == NULL)
602 ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
603
604 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
605
606 if (NULL == WndClass.hIconSm)
607 {
608 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
609 }
610
611 if (IS_ATOM(lpwcx->lpszMenuName) || lpwcx->lpszMenuName == 0)
612 {
613 MenuName.Length =
614 MenuName.MaximumLength = 0;
615 MenuName.Buffer = (LPWSTR)lpwcx->lpszMenuName;
616 } else
617 {
618 RtlCreateUnicodeStringFromAsciiz(&MenuName, lpwcx->lpszMenuName);
619 }
620
621 if (IS_ATOM(lpwcx->lpszClassName))
622 {
623 ClassName.Length =
624 ClassName.MaximumLength = 0;
625 ClassName.Buffer = (LPWSTR)lpwcx->lpszClassName;
626 } else
627 {
628 RtlCreateUnicodeStringFromAsciiz(&ClassName, lpwcx->lpszClassName);
629 }
630
631 Atom = NtUserRegisterClassExWOW(
632 (WNDCLASSEXW*)&WndClass,
633 &ClassName,
634 &ClassName,
635 &MenuName,
636 NULL,
637 REGISTERCLASS_ANSI,
638 0);
639
640 if (!IS_ATOM(lpwcx->lpszMenuName))
641 RtlFreeUnicodeString(&MenuName);
642 if (!IS_ATOM(lpwcx->lpszClassName))
643 RtlFreeUnicodeString(&ClassName);
644
645 return (ATOM)Atom;
646 }
647
648 /*
649 * @implemented
650 */
651 ATOM STDCALL
652 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
653 {
654 WNDCLASSEXW WndClass;
655 UNICODE_STRING ClassName;
656 UNICODE_STRING MenuName;
657
658 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
659 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
660 lpwcx->lpszClassName == NULL)
661 {
662 SetLastError(ERROR_INVALID_PARAMETER);
663 return 0;
664 }
665
666 /*
667 * On real Windows this looks more like:
668 * if (lpwcx->hInstance == User32Instance &&
669 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
670 * But since I have no idea what the magic field in the
671 * TEB structure means, I rather decided to omit that.
672 * -- Filip Navara
673 */
674 if (lpwcx->hInstance == User32Instance)
675 {
676 SetLastError(ERROR_INVALID_PARAMETER);
677 return 0;
678 }
679
680 /* Yes, this is correct. We should modify the passed structure. */
681 if (lpwcx->hInstance == NULL)
682 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
683
684 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
685
686 if (NULL == WndClass.hIconSm)
687 {
688 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
689 }
690
691 if (IS_ATOM(lpwcx->lpszMenuName))
692 {
693 MenuName.Length =
694 MenuName.MaximumLength = 0;
695 MenuName.Buffer = (LPWSTR)lpwcx->lpszMenuName;
696 } else
697 {
698 RtlInitUnicodeString(&MenuName, lpwcx->lpszMenuName);
699 }
700
701 if (IS_ATOM(lpwcx->lpszClassName))
702 {
703 ClassName.Length =
704 ClassName.MaximumLength = 0;
705 ClassName.Buffer = (LPWSTR)lpwcx->lpszClassName;
706 } else
707 {
708 RtlInitUnicodeString(&ClassName, lpwcx->lpszClassName);
709 }
710
711 return (ATOM)NtUserRegisterClassExWOW(
712 &WndClass,
713 &ClassName,
714 &ClassName,
715 &MenuName,
716 NULL,
717 0,
718 0);
719 }
720
721 /*
722 * @implemented
723 */
724 ATOM STDCALL
725 RegisterClassA(CONST WNDCLASSA *lpWndClass)
726 {
727 WNDCLASSEXA Class;
728
729 if (lpWndClass == NULL)
730 return 0;
731
732 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
733 Class.cbSize = sizeof(WNDCLASSEXA);
734 Class.hIconSm = NULL;
735
736 return RegisterClassExA(&Class);
737 }
738
739 /*
740 * @implemented
741 */
742 ATOM STDCALL
743 RegisterClassW(CONST WNDCLASSW *lpWndClass)
744 {
745 WNDCLASSEXW Class;
746
747 if (lpWndClass == NULL)
748 return 0;
749
750 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
751 Class.cbSize = sizeof(WNDCLASSEXW);
752 Class.hIconSm = NULL;
753
754 return RegisterClassExW(&Class);
755 }
756
757 /*
758 * @implemented
759 */
760 DWORD
761 STDCALL
762 SetClassLongA (
763 HWND hWnd,
764 int nIndex,
765 LONG dwNewLong)
766 {
767 UNICODE_STRING str2buf;
768 PUNICODE_STRING str;
769 PUNICODE_STRING str2 = &str2buf;
770
771 if ( nIndex != GCL_MENUNAME )
772 {
773 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
774 }
775 if ( IS_INTRESOURCE(dwNewLong) )
776 {
777 str2 = (PUNICODE_STRING)dwNewLong;
778 }
779 else
780 {
781 RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong );
782 }
783
784 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
785
786 if ( !IS_INTRESOURCE(dwNewLong) )
787 {
788 RtlFreeUnicodeString ( str2 );
789 }
790 if ( IS_INTRESOURCE(str) )
791 {
792 return (DWORD)str;
793 }
794 else
795 {
796 return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
797 }
798 }
799
800
801 /*
802 * @implemented
803 */
804 DWORD
805 STDCALL
806 SetClassLongW(
807 HWND hWnd,
808 int nIndex,
809 LONG dwNewLong)
810 {
811 UNICODE_STRING str2buf;
812 PUNICODE_STRING str;
813 PUNICODE_STRING str2 = &str2buf;
814
815 if (nIndex != GCL_MENUNAME )
816 {
817 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
818 }
819 if ( IS_INTRESOURCE(dwNewLong) )
820 {
821 str2 = (PUNICODE_STRING)dwNewLong;
822 }
823 else
824 {
825 RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong );
826 }
827
828 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
829
830 if ( !IS_INTRESOURCE(dwNewLong) )
831 {
832 RtlFreeUnicodeString(str2);
833 }
834 if ( IS_INTRESOURCE(str) )
835 {
836 return (DWORD)str;
837 }
838 else
839 {
840 return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
841 }
842 }
843
844
845 /*
846 * @implemented
847 */
848 WORD
849 STDCALL
850 SetClassWord(
851 HWND hWnd,
852 int nIndex,
853 WORD wNewWord)
854 /*
855 * NOTE: Obsoleted in 32-bit windows
856 */
857 {
858 if ((nIndex < 0) && (nIndex != GCW_ATOM))
859 return 0;
860
861 return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
862 }
863
864
865 /*
866 * @implemented
867 */
868 LONG
869 STDCALL
870 SetWindowLongA(
871 HWND hWnd,
872 int nIndex,
873 LONG dwNewLong)
874 {
875 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
876 }
877
878
879 /*
880 * @implemented
881 */
882 LONG
883 STDCALL
884 SetWindowLongW(
885 HWND hWnd,
886 int nIndex,
887 LONG dwNewLong)
888 {
889 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
890 }
891
892
893 /*
894 * @implemented
895 */
896 BOOL
897 STDCALL
898 UnregisterClassA(
899 LPCSTR lpClassName,
900 HINSTANCE hInstance)
901 {
902 LPWSTR ClassName;
903 NTSTATUS Status;
904 BOOL Result;
905
906 if(!IS_ATOM(lpClassName))
907 {
908 Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
909 if(!NT_SUCCESS(Status))
910 {
911 SetLastError(RtlNtStatusToDosError(Status));
912 return FALSE;
913 }
914 }
915 else
916 ClassName = (LPWSTR)lpClassName;
917
918 Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
919
920 if(ClassName && !IS_ATOM(lpClassName))
921 HEAP_free(ClassName);
922
923 return Result;
924 }
925
926
927 /*
928 * @implemented
929 */
930 BOOL
931 STDCALL
932 UnregisterClassW(
933 LPCWSTR lpClassName,
934 HINSTANCE hInstance)
935 {
936 return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
937 }
938
939 /* EOF */