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)
9 * 09-05-2001 CSH Created
14 static BOOL
GetClassInfoExCommon(
21 UNICODE_STRING str2
, str3
;
26 if ( !lpszClass
|| !lpwcx
)
28 SetLastError(ERROR_INVALID_PARAMETER
);
32 if(IS_ATOM(lpszClass
))
33 str
= (LPWSTR
)lpszClass
;
36 extern BOOL ControlsInitialized
;
40 str
= HEAP_strdupW ( lpszClass
, wcslen(lpszClass
) );
44 SetLastError (ERROR_OUTOFMEMORY
);
51 Status
= HEAP_strdupAtoW(&str
, (LPCSTR
)lpszClass
, NULL
);
53 if (! NT_SUCCESS(Status
))
55 SetLastError(RtlNtStatusToDosError(Status
));
60 /* Register built-in controls if not already done */
61 if ( !ControlsInitialized
)
63 ControlsInitialized
= ControlsInit(str
);
67 str2
.Length
= str3
.Length
= 0;
68 str2
.MaximumLength
= str3
.MaximumLength
= 255;
69 str2
.Buffer
= (PWSTR
)HEAP_alloc ( str2
.MaximumLength
* sizeof(WCHAR
) );
72 SetLastError (ERROR_OUTOFMEMORY
);
78 str3
.Buffer
= (PWSTR
)HEAP_alloc ( str3
.MaximumLength
* sizeof(WCHAR
) );
81 SetLastError (ERROR_OUTOFMEMORY
);
82 HEAP_free ( str2
.Buffer
);
88 w
.lpszMenuName
= (LPCWSTR
)&str2
;
89 w
.lpszClassName
= (LPCWSTR
)&str3
;
91 /* get info about system classes? */
92 if (!hInst
) hInst
= User32Instance
;
94 retval
= (BOOL
)NtUserGetClassInfo(hInst
, str
, &w
, TRUE
, 0);
96 w
.hInstance
= (hInst
== User32Instance
) ? 0 : hInst
;
101 RtlCopyMemory ( lpwcx
, &w
, sizeof(WNDCLASSEXW
) );
103 if ( !IS_INTRESOURCE(w
.lpszMenuName
) && w
.lpszMenuName
)
106 lpwcx
->lpszMenuName
= heap_string_poolW ( str2
.Buffer
, str2
.Length
);
108 ((LPWNDCLASSEXA
) lpwcx
)->lpszMenuName
= heap_string_poolA ( str2
.Buffer
, str2
.Length
);
111 if ( !IS_ATOM(w
.lpszClassName
) && w
.lpszClassName
)
114 lpwcx
->lpszClassName
= heap_string_poolW ( str3
.Buffer
, str3
.Length
);
116 ((LPWNDCLASSEXA
) lpwcx
)->lpszClassName
= heap_string_poolA ( str3
.Buffer
, str3
.Length
);
119 HEAP_free ( str2
.Buffer
);
120 HEAP_free ( str3
.Buffer
);
136 return GetClassInfoExCommon(hinst
, (LPWSTR
)lpszClass
, (LPWNDCLASSEXW
)lpwcx
, FALSE
);
150 return GetClassInfoExCommon(hinst
, lpszClass
, lpwcx
, TRUE
);
162 LPWNDCLASSA lpWndClass
)
167 if ( !lpClassName
|| !lpWndClass
)
169 SetLastError(ERROR_INVALID_PARAMETER
);
173 retval
= GetClassInfoExA(hInstance
,lpClassName
,&w
);
176 RtlCopyMemory ( lpWndClass
, &w
.style
, sizeof(WNDCLASSA
) );
189 LPWNDCLASSW lpWndClass
)
194 if(!lpClassName
|| !lpWndClass
)
196 SetLastError(ERROR_INVALID_PARAMETER
);
200 retval
= GetClassInfoExW(hInstance
,lpClassName
,&w
);
201 RtlCopyMemory (lpWndClass
,&w
.style
,sizeof(WNDCLASSW
));
210 GetClassLongA(HWND hWnd
, int nIndex
)
214 case GCL_HBRBACKGROUND
:
216 DWORD hBrush
= NtUserGetClassLong(hWnd
, GCL_HBRBACKGROUND
, TRUE
);
217 if (hBrush
!= 0 && hBrush
< 0x4000)
218 hBrush
= (DWORD
)GetSysColorBrush((ULONG
)hBrush
- 1);
224 PUNICODE_STRING Name
;
225 Name
= (PUNICODE_STRING
)NtUserGetClassLong(hWnd
, nIndex
, TRUE
);
226 if (IS_INTRESOURCE(Name
))
229 return (DWORD
)heap_string_poolA(Name
->Buffer
, Name
->Length
);
233 return NtUserGetClassLong(hWnd
, nIndex
, TRUE
);
241 GetClassLongW ( HWND hWnd
, int nIndex
)
245 case GCL_HBRBACKGROUND
:
247 DWORD hBrush
= NtUserGetClassLong(hWnd
, GCL_HBRBACKGROUND
, TRUE
);
248 if (hBrush
!= 0 && hBrush
< 0x4000)
249 hBrush
= (DWORD
)GetSysColorBrush((ULONG
)hBrush
- 1);
255 PUNICODE_STRING Name
;
256 Name
= (PUNICODE_STRING
)NtUserGetClassLong(hWnd
, nIndex
, FALSE
);
257 if (IS_INTRESOURCE(Name
))
260 return (DWORD
)heap_string_poolW(Name
->Buffer
, Name
->Length
);
264 return NtUserGetClassLong(hWnd
, nIndex
, FALSE
);
285 ClassNameW
= HEAP_alloc ( (nMaxCount
+1)*sizeof(WCHAR
) );
287 result
= NtUserGetClassName ( hWnd
, ClassNameW
, nMaxCount
);
289 Status
= HEAP_strcpyWtoA ( lpClassName
, ClassNameW
, result
);
291 HEAP_free ( ClassNameW
);
293 if ( !NT_SUCCESS(Status
) )
310 return NtUserGetClassName(hWnd
, lpClassName
, nMaxCount
);
323 * NOTE: Obsoleted in 32-bit windows
326 if ((nIndex
< 0) && (nIndex
!= GCW_ATOM
))
329 return (WORD
) NtUserGetClassLong ( hWnd
, nIndex
, TRUE
);
338 GetWindowLongA ( HWND hWnd
, int nIndex
)
340 return NtUserGetWindowLong(hWnd
, nIndex
, TRUE
);
349 GetWindowLongW(HWND hWnd
, int nIndex
)
351 return NtUserGetWindowLong(hWnd
, nIndex
, FALSE
);
359 GetWindowWord(HWND hWnd
, int nIndex
)
361 return (WORD
)NtUserGetWindowLong(hWnd
, nIndex
, TRUE
);
369 SetWindowWord ( HWND hWnd
,int nIndex
,WORD wNewWord
)
371 return (WORD
)NtUserSetWindowLong ( hWnd
, nIndex
, (LONG
)wNewWord
, TRUE
);
384 /* FIXME: Implement correct functionality of RealGetWindowClass */
385 return GetClassNameW(hwnd
,pszType
,cchType
);
399 /* FIXME: Implement correct functionality of RealGetWindowClass */
400 return GetClassNameA(hwnd
,pszType
,cchType
);
404 * Create a small icon based on a standard icon
407 CreateSmallIcon(HICON StdIcon
)
409 HICON SmallIcon
= NULL
;
413 BITMAP StdBitmapInfo
;
415 HDC hSourceDc
= NULL
;
418 HBITMAP OldSourceBitmap
= NULL
;
419 HBITMAP OldDestBitmap
= NULL
;
421 SmallInfo
.hbmColor
= NULL
;
422 SmallInfo
.hbmMask
= NULL
;
424 /* We need something to work with... */
430 SmallIconWidth
= GetSystemMetrics(SM_CXSMICON
);
431 SmallIconHeight
= GetSystemMetrics(SM_CYSMICON
);
432 if (! GetIconInfo(StdIcon
, &StdInfo
))
434 DPRINT1("Failed to get icon info for icon 0x%x\n", StdIcon
);
437 if (! GetObjectW(StdInfo
.hbmMask
, sizeof(BITMAP
), &StdBitmapInfo
))
439 DPRINT1("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
440 StdIcon
, StdInfo
.hbmColor
);
443 if (StdBitmapInfo
.bmWidth
== SmallIconWidth
&&
444 StdBitmapInfo
.bmHeight
== SmallIconHeight
)
446 /* Icon already has the correct dimensions */
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
);
456 DPRINT1("Failed to create info DC\n");
459 hSourceDc
= CreateCompatibleDC(NULL
);
460 if (NULL
== hSourceDc
)
462 DPRINT1("Failed to create source DC\n");
465 hDestDc
= CreateCompatibleDC(NULL
);
468 DPRINT1("Failed to create dest DC\n");
472 OldSourceBitmap
= SelectObject(hSourceDc
, StdInfo
.hbmColor
);
473 if (NULL
== OldSourceBitmap
)
475 DPRINT1("Failed to select source color bitmap\n");
478 SmallInfo
.hbmColor
= CreateCompatibleBitmap(hInfoDc
, SmallIconWidth
,
480 if (NULL
== SmallInfo
.hbmColor
)
482 DPRINT1("Failed to create color bitmap\n");
485 OldDestBitmap
= SelectObject(hDestDc
, SmallInfo
.hbmColor
);
486 if (NULL
== OldDestBitmap
)
488 DPRINT1("Failed to select dest color bitmap\n");
491 if (! StretchBlt(hDestDc
, 0, 0, SmallIconWidth
, SmallIconHeight
,
492 hSourceDc
, 0, 0, StdBitmapInfo
.bmWidth
,
493 StdBitmapInfo
.bmHeight
, SRCCOPY
))
495 DPRINT1("Failed to stretch color bitmap\n");
499 if (NULL
== SelectObject(hSourceDc
, StdInfo
.hbmMask
))
501 DPRINT1("Failed to select source mask bitmap\n");
504 SmallInfo
.hbmMask
= CreateBitmap(SmallIconWidth
, SmallIconHeight
, 1, 1,
506 if (NULL
== SmallInfo
.hbmMask
)
508 DPRINT1("Failed to create mask bitmap\n");
511 if (NULL
== SelectObject(hDestDc
, SmallInfo
.hbmMask
))
513 DPRINT1("Failed to select dest mask bitmap\n");
516 if (! StretchBlt(hDestDc
, 0, 0, SmallIconWidth
, SmallIconHeight
,
517 hSourceDc
, 0, 0, StdBitmapInfo
.bmWidth
,
518 StdBitmapInfo
.bmHeight
, SRCCOPY
))
520 DPRINT1("Failed to stretch mask bitmap\n");
524 SmallInfo
.fIcon
= TRUE
;
525 SmallInfo
.xHotspot
= SmallIconWidth
/ 2;
526 SmallInfo
.yHotspot
= SmallIconHeight
/ 2;
527 SmallIcon
= CreateIconIndirect(&SmallInfo
);
528 if (NULL
== SmallIcon
)
530 DPRINT1("Failed to create icon\n");
535 if (NULL
!= SmallInfo
.hbmMask
)
537 DeleteObject(SmallInfo
.hbmMask
);
539 if (NULL
!= OldDestBitmap
)
541 SelectObject(hDestDc
, OldDestBitmap
);
543 if (NULL
!= SmallInfo
.hbmColor
)
545 DeleteObject(SmallInfo
.hbmColor
);
551 if (NULL
!= OldSourceBitmap
)
553 SelectObject(hSourceDc
, OldSourceBitmap
);
555 if (NULL
!= hSourceDc
)
571 RegisterClassExA(CONST WNDCLASSEXA
*lpwcx
)
574 WNDCLASSEXA WndClass
;
575 UNICODE_STRING ClassName
;
576 UNICODE_STRING MenuName
;
579 if (lpwcx
== NULL
|| lpwcx
->cbSize
!= sizeof(WNDCLASSEXA
) ||
580 lpwcx
->cbClsExtra
< 0 || lpwcx
->cbWndExtra
< 0 ||
581 lpwcx
->lpszClassName
== NULL
)
583 SetLastError(ERROR_INVALID_PARAMETER
);
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.
595 if (lpwcx
->hInstance
== User32Instance
)
597 SetLastError(ERROR_INVALID_PARAMETER
);
601 /* Yes, this is correct. We should modify the passed structure. */
602 if (lpwcx
->hInstance
== NULL
)
603 ((WNDCLASSEXA
*)lpwcx
)->hInstance
= GetModuleHandleW(NULL
);
605 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXA
));
607 if (NULL
== WndClass
.hIconSm
)
609 WndClass
.hIconSm
= CreateSmallIcon(WndClass
.hIcon
);
612 if HIWORD(lpwcx
->lpszMenuName
)
615 RtlCreateUnicodeStringFromAsciiz(&MenuName
, WndClass
.lpszMenuName
);
620 MenuName
.MaximumLength
= 0;
621 MenuName
.Buffer
= (LPWSTR
)WndClass
.lpszMenuName
;
622 hMenu
= LoadMenuA(WndClass
.hInstance
, lpwcx
->lpszMenuName
);
625 if (IS_ATOM(WndClass
.lpszClassName
))
628 ClassName
.MaximumLength
= 0;
629 ClassName
.Buffer
= (LPWSTR
)WndClass
.lpszClassName
;
632 RtlCreateUnicodeStringFromAsciiz(&ClassName
, WndClass
.lpszClassName
);
635 Atom
= NtUserRegisterClassExWOW(
636 (WNDCLASSEXW
*)&WndClass
,
645 if (!IS_ATOM(WndClass
.lpszMenuName
))
646 RtlFreeUnicodeString(&MenuName
);
647 if (!IS_ATOM(WndClass
.lpszClassName
))
648 RtlFreeUnicodeString(&ClassName
);
657 RegisterClassExW(CONST WNDCLASSEXW
*lpwcx
)
659 WNDCLASSEXW WndClass
;
660 UNICODE_STRING ClassName
;
661 UNICODE_STRING MenuName
;
664 if (lpwcx
== NULL
|| lpwcx
->cbSize
!= sizeof(WNDCLASSEXW
) ||
665 lpwcx
->cbClsExtra
< 0 || lpwcx
->cbWndExtra
< 0 ||
666 lpwcx
->lpszClassName
== NULL
)
668 SetLastError(ERROR_INVALID_PARAMETER
);
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.
680 if (lpwcx
->hInstance
== User32Instance
)
682 SetLastError(ERROR_INVALID_PARAMETER
);
686 /* Yes, this is correct. We should modify the passed structure. */
687 if (lpwcx
->hInstance
== NULL
)
688 ((WNDCLASSEXW
*)lpwcx
)->hInstance
= GetModuleHandleW(NULL
);
690 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXW
));
692 if (NULL
== WndClass
.hIconSm
)
694 WndClass
.hIconSm
= CreateSmallIcon(WndClass
.hIcon
);
697 if HIWORD(lpwcx
->lpszMenuName
)
700 RtlInitUnicodeString(&MenuName
, WndClass
.lpszMenuName
);
705 MenuName
.MaximumLength
= 0;
706 MenuName
.Buffer
= (LPWSTR
)WndClass
.lpszMenuName
;
707 hMenu
= LoadMenuW(WndClass
.hInstance
, lpwcx
->lpszMenuName
);
710 if (IS_ATOM(WndClass
.lpszClassName
))
713 ClassName
.MaximumLength
= 0;
714 ClassName
.Buffer
= (LPWSTR
)WndClass
.lpszClassName
;
717 RtlInitUnicodeString(&ClassName
, WndClass
.lpszClassName
);
720 return (ATOM
)NtUserRegisterClassExWOW(
735 RegisterClassA(CONST WNDCLASSA
*lpWndClass
)
739 if (lpWndClass
== NULL
)
742 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSA
));
743 Class
.cbSize
= sizeof(WNDCLASSEXA
);
744 Class
.hIconSm
= NULL
;
746 return RegisterClassExA(&Class
);
753 RegisterClassW(CONST WNDCLASSW
*lpWndClass
)
757 if (lpWndClass
== NULL
)
760 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSW
));
761 Class
.cbSize
= sizeof(WNDCLASSEXW
);
762 Class
.hIconSm
= NULL
;
764 return RegisterClassExW(&Class
);
777 UNICODE_STRING str2buf
;
779 PUNICODE_STRING str2
= &str2buf
;
781 if ( nIndex
!= GCL_MENUNAME
)
783 return NtUserSetClassLong ( hWnd
, nIndex
, dwNewLong
, TRUE
);
785 if ( IS_INTRESOURCE(dwNewLong
) )
787 str2
= (PUNICODE_STRING
)dwNewLong
;
791 RtlCreateUnicodeStringFromAsciiz ( &str2buf
,(LPSTR
)dwNewLong
);
794 str
= (PUNICODE_STRING
)NtUserSetClassLong(hWnd
, nIndex
, (DWORD
)str2
, TRUE
);
796 if ( !IS_INTRESOURCE(dwNewLong
) )
798 RtlFreeUnicodeString ( str2
);
800 if ( IS_INTRESOURCE(str
) )
806 return (DWORD
)heap_string_poolA ( str
->Buffer
, str
->Length
);
821 UNICODE_STRING str2buf
;
823 PUNICODE_STRING str2
= &str2buf
;
825 if (nIndex
!= GCL_MENUNAME
)
827 return NtUserSetClassLong ( hWnd
, nIndex
, dwNewLong
, FALSE
);
829 if ( IS_INTRESOURCE(dwNewLong
) )
831 str2
= (PUNICODE_STRING
)dwNewLong
;
835 RtlCreateUnicodeString ( &str2buf
, (LPWSTR
)dwNewLong
);
838 str
= (PUNICODE_STRING
)NtUserSetClassLong(hWnd
, nIndex
, (DWORD
)str2
, TRUE
);
840 if ( !IS_INTRESOURCE(dwNewLong
) )
842 RtlFreeUnicodeString(str2
);
844 if ( IS_INTRESOURCE(str
) )
850 return (DWORD
)heap_string_poolW ( str
->Buffer
, str
->Length
);
865 * NOTE: Obsoleted in 32-bit windows
868 if ((nIndex
< 0) && (nIndex
!= GCW_ATOM
))
871 return (WORD
) NtUserSetClassLong ( hWnd
, nIndex
, wNewWord
, TRUE
);
885 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, TRUE
);
899 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, FALSE
);
916 if(!IS_ATOM(lpClassName
))
918 Status
= HEAP_strdupAtoW(&ClassName
, lpClassName
, NULL
);
919 if(!NT_SUCCESS(Status
))
921 SetLastError(RtlNtStatusToDosError(Status
));
926 ClassName
= (LPWSTR
)lpClassName
;
928 Result
= (BOOL
)NtUserUnregisterClass((LPCWSTR
)ClassName
, hInstance
, 0);
930 if(ClassName
&& !IS_ATOM(lpClassName
))
931 HEAP_free(ClassName
);
946 return (BOOL
)NtUserUnregisterClass(lpClassName
, hInstance
, 0);