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 (RtlNtStatusToDosError(STATUS_NO_MEMORY
));
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 (RtlNtStatusToDosError(STATUS_NO_MEMORY
));
78 str3
.Buffer
= (PWSTR
)HEAP_alloc ( str3
.MaximumLength
* sizeof(WCHAR
) );
81 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY
));
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
;
578 if (lpwcx
== NULL
|| lpwcx
->cbSize
!= sizeof(WNDCLASSEXW
) ||
579 lpwcx
->cbClsExtra
< 0 || lpwcx
->cbWndExtra
< 0 ||
580 lpwcx
->lpszClassName
== NULL
)
582 SetLastError(ERROR_INVALID_PARAMETER
);
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.
594 if (lpwcx
->hInstance
== User32Instance
)
596 SetLastError(ERROR_INVALID_PARAMETER
);
600 /* Yes, this is correct. We should modify the passed structure. */
601 if (lpwcx
->hInstance
== NULL
)
602 ((WNDCLASSEXA
*)lpwcx
)->hInstance
= GetModuleHandleW(NULL
);
604 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXW
));
606 if (NULL
== WndClass
.hIconSm
)
608 WndClass
.hIconSm
= CreateSmallIcon(WndClass
.hIcon
);
611 if (IS_ATOM(lpwcx
->lpszMenuName
) || lpwcx
->lpszMenuName
== 0)
614 MenuName
.MaximumLength
= 0;
615 MenuName
.Buffer
= (LPWSTR
)lpwcx
->lpszMenuName
;
618 RtlCreateUnicodeStringFromAsciiz(&MenuName
, lpwcx
->lpszMenuName
);
621 if (IS_ATOM(lpwcx
->lpszClassName
))
624 ClassName
.MaximumLength
= 0;
625 ClassName
.Buffer
= (LPWSTR
)lpwcx
->lpszClassName
;
628 RtlCreateUnicodeStringFromAsciiz(&ClassName
, lpwcx
->lpszClassName
);
631 Atom
= NtUserRegisterClassExWOW(
632 (WNDCLASSEXW
*)&WndClass
,
640 if (!IS_ATOM(lpwcx
->lpszMenuName
))
641 RtlFreeUnicodeString(&MenuName
);
642 if (!IS_ATOM(lpwcx
->lpszClassName
))
643 RtlFreeUnicodeString(&ClassName
);
652 RegisterClassExW(CONST WNDCLASSEXW
*lpwcx
)
654 WNDCLASSEXW WndClass
;
655 UNICODE_STRING ClassName
;
656 UNICODE_STRING MenuName
;
658 if (lpwcx
== NULL
|| lpwcx
->cbSize
!= sizeof(WNDCLASSEXW
) ||
659 lpwcx
->cbClsExtra
< 0 || lpwcx
->cbWndExtra
< 0 ||
660 lpwcx
->lpszClassName
== NULL
)
662 SetLastError(ERROR_INVALID_PARAMETER
);
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.
674 if (lpwcx
->hInstance
== User32Instance
)
676 SetLastError(ERROR_INVALID_PARAMETER
);
680 /* Yes, this is correct. We should modify the passed structure. */
681 if (lpwcx
->hInstance
== NULL
)
682 ((WNDCLASSEXW
*)lpwcx
)->hInstance
= GetModuleHandleW(NULL
);
684 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXW
));
686 if (NULL
== WndClass
.hIconSm
)
688 WndClass
.hIconSm
= CreateSmallIcon(WndClass
.hIcon
);
691 if (IS_ATOM(lpwcx
->lpszMenuName
))
694 MenuName
.MaximumLength
= 0;
695 MenuName
.Buffer
= (LPWSTR
)lpwcx
->lpszMenuName
;
698 RtlInitUnicodeString(&MenuName
, lpwcx
->lpszMenuName
);
701 if (IS_ATOM(lpwcx
->lpszClassName
))
704 ClassName
.MaximumLength
= 0;
705 ClassName
.Buffer
= (LPWSTR
)lpwcx
->lpszClassName
;
708 RtlInitUnicodeString(&ClassName
, lpwcx
->lpszClassName
);
711 return (ATOM
)NtUserRegisterClassExWOW(
725 RegisterClassA(CONST WNDCLASSA
*lpWndClass
)
729 if (lpWndClass
== NULL
)
732 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSA
));
733 Class
.cbSize
= sizeof(WNDCLASSEXA
);
734 Class
.hIconSm
= NULL
;
736 return RegisterClassExA(&Class
);
743 RegisterClassW(CONST WNDCLASSW
*lpWndClass
)
747 if (lpWndClass
== NULL
)
750 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSW
));
751 Class
.cbSize
= sizeof(WNDCLASSEXW
);
752 Class
.hIconSm
= NULL
;
754 return RegisterClassExW(&Class
);
767 UNICODE_STRING str2buf
;
769 PUNICODE_STRING str2
= &str2buf
;
771 if ( nIndex
!= GCL_MENUNAME
)
773 return NtUserSetClassLong ( hWnd
, nIndex
, dwNewLong
, TRUE
);
775 if ( IS_INTRESOURCE(dwNewLong
) )
777 str2
= (PUNICODE_STRING
)dwNewLong
;
781 RtlCreateUnicodeStringFromAsciiz ( &str2buf
,(LPSTR
)dwNewLong
);
784 str
= (PUNICODE_STRING
)NtUserSetClassLong(hWnd
, nIndex
, (DWORD
)str2
, TRUE
);
786 if ( !IS_INTRESOURCE(dwNewLong
) )
788 RtlFreeUnicodeString ( str2
);
790 if ( IS_INTRESOURCE(str
) )
796 return (DWORD
)heap_string_poolA ( str
->Buffer
, str
->Length
);
811 UNICODE_STRING str2buf
;
813 PUNICODE_STRING str2
= &str2buf
;
815 if (nIndex
!= GCL_MENUNAME
)
817 return NtUserSetClassLong ( hWnd
, nIndex
, dwNewLong
, FALSE
);
819 if ( IS_INTRESOURCE(dwNewLong
) )
821 str2
= (PUNICODE_STRING
)dwNewLong
;
825 RtlCreateUnicodeString ( &str2buf
, (LPWSTR
)dwNewLong
);
828 str
= (PUNICODE_STRING
)NtUserSetClassLong(hWnd
, nIndex
, (DWORD
)str2
, TRUE
);
830 if ( !IS_INTRESOURCE(dwNewLong
) )
832 RtlFreeUnicodeString(str2
);
834 if ( IS_INTRESOURCE(str
) )
840 return (DWORD
)heap_string_poolW ( str
->Buffer
, str
->Length
);
855 * NOTE: Obsoleted in 32-bit windows
858 if ((nIndex
< 0) && (nIndex
!= GCW_ATOM
))
861 return (WORD
) NtUserSetClassLong ( hWnd
, nIndex
, wNewWord
, TRUE
);
875 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, TRUE
);
889 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, FALSE
);
906 if(!IS_ATOM(lpClassName
))
908 Status
= HEAP_strdupAtoW(&ClassName
, lpClassName
, NULL
);
909 if(!NT_SUCCESS(Status
))
911 SetLastError(RtlNtStatusToDosError(Status
));
916 ClassName
= (LPWSTR
)lpClassName
;
918 Result
= (BOOL
)NtUserUnregisterClass((LPCWSTR
)ClassName
, hInstance
, 0);
920 if(ClassName
&& !IS_ATOM(lpClassName
))
921 HEAP_free(ClassName
);
936 return (BOOL
)NtUserUnregisterClass(lpClassName
, hInstance
, 0);