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)
8 * 09-05-2001 CSH Created
13 #include <wine/debug.h>
14 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
16 /* From rtl/actctx.c and must match! */
19 DWORD kind
; // Activation context type
20 WCHAR
*name
; // Class name
21 WCHAR
*clsid
; // Not supported yet but needed for menu name.
26 WCHAR
*name
; // Dll name
36 LPCWSTR
*plpLibFileName
,
41 UNICODE_STRING SectionName
;
42 WCHAR SeactionNameBuf
[256] = {0};
43 ACTCTX_SECTION_KEYED_DATA KeyedData
= { sizeof(KeyedData
) };
45 if (IS_ATOM(lpszClass
))
47 SectionName
.Buffer
= (LPWSTR
)&SeactionNameBuf
;
48 SectionName
.MaximumLength
= sizeof(SeactionNameBuf
);
49 if(!NtUserGetAtomName(LOWORD((DWORD_PTR
)lpszClass
), &SectionName
))
58 RtlCreateUnicodeStringFromAsciiz(&SectionName
, (LPSTR
)lpszClass
);
62 RtlInitUnicodeString(&SectionName
, lpszClass
);
65 Status
= RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
,
67 ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION
,
71 if (NT_SUCCESS(Status
) && KeyedData
.ulDataFormatVersion
== 1)
73 struct dll_redirect
*dll
= KeyedData
.lpSectionBase
;
75 if (plpLibFileName
) *plpLibFileName
= dll
->name
;
83 struct entity
*entity
= KeyedData
.lpData
;
85 FIXME("actctx: Needs to support menu name from redirected class!");
89 mnubuf
= entity
->clsid
;
92 mnuNameA
= (LPSTR
)lpszMenuName
;
93 RtlUnicodeToMultiByteN( mnuNameA
, 255, (PULONG
)&len
, mnubuf
, strlenW(mnubuf
) * sizeof(WCHAR
) );
98 mnuNameW
= (LPWSTR
)lpszMenuName
;
99 len
= strlenW(mnubuf
) * sizeof(WCHAR
);
100 RtlCopyMemory((void *)mnuNameW
, mnubuf
, len
);
105 if (pContext
) *pContext
= KeyedData
.hActCtx
;
108 if (!IS_ATOM(lpszClass
) && bAnsi
)
109 RtlFreeUnicodeString(&SectionName
);
110 if (KeyedData
.hActCtx
)
111 RtlReleaseActivationContext(KeyedData
.hActCtx
);
118 VersionRegisterClass(
120 LPCWSTR lpLibFileName
,
122 HMODULE
* phLibModule
)
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 };
131 RtlActivateActivationContextUnsafeFast(&Frame
, Contex
);
138 hLibModule
= LoadLibraryW(lpLibFileName
);
141 if ((pRegisterClassNameW
= (void*) GetProcAddress(hLibModule
, "RegisterClassNameW")))
143 if (IS_ATOM(pszClass
))
145 ClassName
.Buffer
= (LPWSTR
)&ClassNameBuf
;
146 ClassName
.MaximumLength
= sizeof(ClassNameBuf
);
147 if (!NtUserGetAtomName(LOWORD((DWORD_PTR
)pszClass
), &ClassName
))
149 _SEH2_YIELD(goto Error_Exit
);
151 pszClass
= (PCWSTR
)&ClassNameBuf
;
153 Ret
= pRegisterClassNameW(pszClass
);
157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
163 if ( Ret
|| !hLibModule
)
165 if ( phLibModule
) *phLibModule
= hLibModule
;
169 DWORD save_error
= GetLastError();
170 FreeLibrary(hLibModule
);
171 SetLastError(save_error
);
187 UNICODE_STRING ClassName
= {0};
191 TRACE("%p class/atom: %s/%04x %p\n", hInstance
,
192 IS_ATOM(lpszClass
) ? NULL
: lpszClass
,
193 IS_ATOM(lpszClass
) ? lpszClass
: 0,
198 SetLastError( ERROR_NOACCESS
);
202 if (hInstance
== User32Instance
)
207 if (lpszClass
== NULL
)
209 SetLastError(ERROR_INVALID_PARAMETER
);
213 if (IS_ATOM(lpszClass
))
215 ClassName
.Buffer
= (PWSTR
)((ULONG_PTR
)lpszClass
);
219 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName
,
222 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
227 if (!RegisterDefaultClasses
)
229 ERR("GetClassInfoExA RegisterSystemControls\n");
230 RegisterSystemControls();
233 Ret
= NtUserGetClassInfo(hInstance
,
235 (LPWNDCLASSEXW
)lpwcx
,
236 (LPWSTR
*)&pszMenuName
,
240 lpwcx
->lpszClassName
= lpszClass
;
241 // lpwcx->lpszMenuName = pszMenuName;
244 if (!IS_ATOM(lpszClass
))
246 RtlFreeUnicodeString(&ClassName
);
263 UNICODE_STRING ClassName
= {0};
267 TRACE("%p class/atom: %S/%04x %p\n", hInstance
,
268 IS_ATOM(lpszClass
) ? NULL
: lpszClass
,
269 IS_ATOM(lpszClass
) ? lpszClass
: 0,
272 /* From wine, for speed only, ReactOS supports the correct return in
273 * Win32k. cbSize is ignored.
277 SetLastError( ERROR_NOACCESS
);
281 if (hInstance
== User32Instance
)
286 if (lpszClass
== NULL
)
288 SetLastError(ERROR_INVALID_PARAMETER
);
292 if (IS_ATOM(lpszClass
))
294 ClassName
.Buffer
= (PWSTR
)((ULONG_PTR
)lpszClass
);
298 RtlInitUnicodeString(&ClassName
,
302 if (!RegisterDefaultClasses
)
304 ERR("GetClassInfoExW RegisterSystemControls\n");
305 RegisterSystemControls();
308 Ret
= NtUserGetClassInfo( hInstance
,
315 lpwcx
->lpszClassName
= lpszClass
;
316 // lpwcx->lpszMenuName = pszMenuName;
330 LPWNDCLASSA lpWndClass
)
335 retval
= GetClassInfoExA(hInstance
, lpClassName
, &wcex
);
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
;
361 LPWNDCLASSW lpWndClass
)
366 retval
= GetClassInfoExW(hInstance
, lpClassName
, &wcex
);
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
;
384 // Based on find_winproc... Fixes many whine tests......
387 IntGetClsWndProc(PWND pWnd
, PCLS Class
, BOOL Ansi
)
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
++)
396 if (GETPFNSERVER(i
) == Class
->lpfnWndProc
)
399 Ret
= (ULONG_PTR
)GETPFNCLIENTA(i
);
401 Ret
= (ULONG_PTR
)GETPFNCLIENTW(i
);
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
)
412 { // If match return the right proc by type.
413 if (GETPFNCLIENTW(Class
->fnid
) == Class
->lpfnWndProc
)
414 Ret
= (ULONG_PTR
)GETPFNCLIENTA(Class
->fnid
);
418 if (GETPFNCLIENTA(Class
->fnid
) == Class
->lpfnWndProc
)
419 Ret
= (ULONG_PTR
)GETPFNCLIENTW(Class
->fnid
);
422 // Return on change or Ansi/Unicode proc equal.
423 if ( Ret
!= (ULONG_PTR
)Class
->lpfnWndProc
||
424 Ansi
== !!(Class
->CSF_flags
& CSF_ANSIPROC
) )
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
,
433 return (gcpd
? gcpd
: Ret
);
437 // Based on IntGetClsWndProc
440 IntGetWndProc(PWND pWnd
, BOOL Ansi
)
443 WNDPROC gcpd
, Ret
= 0;
444 PCLS Class
= DesktopPtrToUser(pWnd
->pcls
);
446 if (!Class
) return Ret
;
448 if (pWnd
->state
& WNDS_SERVERSIDEWINDOWPROC
)
450 for ( i
= FNID_FIRST
; i
<= FNID_SWITCH
; i
++)
452 if (GETPFNSERVER(i
) == pWnd
->lpfnWndProc
)
455 Ret
= GETPFNCLIENTA(i
);
457 Ret
= GETPFNCLIENTW(i
);
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.
468 if (Class
->fnid
== FNID_EDIT
)
469 Ret
= pWnd
->lpfnWndProc
;
473 Ret
= pWnd
->lpfnWndProc
;
475 if (Class
->fnid
<= FNID_GHOST
&& Class
->fnid
>= FNID_BUTTON
)
479 if (GETPFNCLIENTW(Class
->fnid
) == pWnd
->lpfnWndProc
)
480 Ret
= GETPFNCLIENTA(Class
->fnid
);
484 if (GETPFNCLIENTA(Class
->fnid
) == pWnd
->lpfnWndProc
)
485 Ret
= GETPFNCLIENTW(Class
->fnid
);
488 // Return on the change.
489 if ( Ret
!= pWnd
->lpfnWndProc
)
493 if ( Ansi
== !!(pWnd
->state
& WNDS_ANSIWINDOWPROC
) )
496 gcpd
= (WNDPROC
)NtUserGetCPD( UserHMGetHandle(pWnd
),
497 (Ansi
? UserGetCPDA2U
: UserGetCPDU2A
)|UserGetCPDWindow
,
500 return (gcpd
? gcpd
: Ret
);
503 static ULONG_PTR FASTCALL
504 IntGetClassLongA(PWND Wnd
, PCLS Class
, int nIndex
)
510 if (nIndex
+ sizeof(ULONG_PTR
) < nIndex
||
511 nIndex
+ sizeof(ULONG_PTR
) > Class
->cbclsExtra
)
513 SetLastError(ERROR_INVALID_PARAMETER
);
516 Ret
= *(PULONG_PTR
)((ULONG_PTR
)(Class
+ 1) + nIndex
);
523 Ret
= (ULONG_PTR
)Class
->cbwndExtra
;
527 Ret
= (ULONG_PTR
)Class
->cbclsExtra
;
530 case GCL_HBRBACKGROUND
:
531 Ret
= (ULONG_PTR
)Class
->hbrBackground
;
532 if (Ret
!= 0 && Ret
< 0x4000)
533 Ret
= (ULONG_PTR
)GetSysColorBrush((ULONG
)Ret
- 1);
537 //ERR("Cls 0x%x GCL_HMODULE 0x%x\n", Wnd->pcls, Class->hModule);
538 Ret
= (ULONG_PTR
)Class
->hModule
;
542 Ret
= (ULONG_PTR
)Class
->lpszClientAnsiMenuName
;
546 Ret
= (ULONG_PTR
)Class
->style
;
550 Ret
= (ULONG_PTR
)Class
->atomClassName
;
554 /* FIXME - get handle from pointer to CURSOR object */
555 Ret
= (ULONG_PTR
)Class
->hCursor
;
559 /* FIXME - get handle from pointer to ICON object */
560 Ret
= (ULONG_PTR
)Class
->hIcon
;
564 /* FIXME - get handle from pointer to ICON object */
565 Ret
= (ULONG_PTR
)(Class
->hIconSm
? Class
->hIconSm
: Class
->hIconSmIntern
);
569 Ret
= IntGetClsWndProc(Wnd
, Class
, TRUE
);
573 SetLastError(ERROR_INVALID_INDEX
);
581 static ULONG_PTR FASTCALL
582 IntGetClassLongW (PWND Wnd
, PCLS Class
, int nIndex
)
588 if (nIndex
+ sizeof(ULONG_PTR
) < nIndex
||
589 nIndex
+ sizeof(ULONG_PTR
) > Class
->cbclsExtra
)
591 SetLastError(ERROR_INVALID_PARAMETER
);
594 Ret
= *(PULONG_PTR
)((ULONG_PTR
)(Class
+ 1) + nIndex
);
601 Ret
= (ULONG_PTR
)Class
->cbwndExtra
;
605 Ret
= (ULONG_PTR
)Class
->cbclsExtra
;
608 case GCLP_HBRBACKGROUND
:
609 Ret
= (ULONG_PTR
)Class
->hbrBackground
;
610 if (Ret
!= 0 && Ret
< 0x4000)
611 Ret
= (ULONG_PTR
)GetSysColorBrush((ULONG
)Ret
- 1);
615 Ret
= (ULONG_PTR
)Class
->hModule
;
619 Ret
= (ULONG_PTR
)Class
->lpszClientUnicodeMenuName
;
623 Ret
= (ULONG_PTR
)Class
->style
;
627 Ret
= (ULONG_PTR
)Class
->atomClassName
;
631 /* FIXME - get handle from pointer to CURSOR object */
632 Ret
= (ULONG_PTR
)Class
->hCursor
;
636 /* FIXME - get handle from pointer to ICON object */
637 Ret
= (ULONG_PTR
)Class
->hIcon
;
641 /* FIXME - get handle from pointer to ICON object */
642 Ret
= (ULONG_PTR
)(Class
->hIconSm
? Class
->hIconSm
: Class
->hIconSmIntern
);
646 Ret
= IntGetClsWndProc(Wnd
, Class
, FALSE
);
650 SetLastError(ERROR_INVALID_INDEX
);
662 GetClassLongA(HWND hWnd
, int nIndex
)
668 TRACE("%p %d\n", hWnd
, nIndex
);
670 Wnd
= ValidateHwnd(hWnd
);
676 Class
= DesktopPtrToUser(Wnd
->pcls
);
682 case GCLP_HBRBACKGROUND
:
689 SetLastError(ERROR_INVALID_INDEX
);
693 Ret
= IntGetClassLongA(Wnd
, Class
, nIndex
);
697 Ret
= IntGetClassLongA(Wnd
, Class
, nIndex
);
702 WARN("Invalid class for hwnd 0x%p!\n", hWnd
);
705 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
718 GetClassLongW ( HWND hWnd
, int nIndex
)
724 TRACE("%p %d\n", hWnd
, nIndex
);
726 Wnd
= ValidateHwnd(hWnd
);
732 Class
= DesktopPtrToUser(Wnd
->pcls
);
738 case GCLP_HBRBACKGROUND
:
745 SetLastError(ERROR_INVALID_INDEX
);
749 Ret
= IntGetClassLongW(Wnd
, Class
, nIndex
);
753 Ret
= IntGetClassLongW(Wnd
, Class
, nIndex
);
758 WARN("Invalid class for hwnd 0x%p!\n", hWnd
);
761 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
776 GetClassLongPtrA(HWND hWnd
,
783 TRACE("%p %d\n", hWnd
, nIndex
);
785 Wnd
= ValidateHwnd(hWnd
);
791 Class
= DesktopPtrToUser(Wnd
->pcls
);
794 Ret
= IntGetClassLongA(Wnd
, Class
, nIndex
);
798 WARN("Invalid class for hwnd 0x%p!\n", hWnd
);
801 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
815 GetClassLongPtrW(HWND hWnd
,
822 TRACE("%p %d\n", hWnd
, nIndex
);
824 Wnd
= ValidateHwnd(hWnd
);
830 Class
= DesktopPtrToUser(Wnd
->pcls
);
833 Ret
= IntGetClassLongW(Wnd
, Class
, nIndex
);
837 WARN("Invalid class for hwnd 0x%p!\n", hWnd
);
840 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
860 WCHAR tmpbuf
[MAX_ATOM_LEN
+ 1];
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;
868 TRACE("%p class/atom: %s/%04x %x\n", hWnd
,
869 IS_ATOM(lpClassName
) ? NULL
: lpClassName
,
870 IS_ATOM(lpClassName
) ? lpClassName
: 0,
887 UNICODE_STRING ClassName
;
890 ClassName
.MaximumLength
= nMaxCount
* sizeof(WCHAR
);
891 ClassName
.Buffer
= lpClassName
;
893 Result
= NtUserGetClassName(hWnd
,
897 TRACE("%p class/atom: %S/%04x %x\n", hWnd
,
898 IS_ATOM(lpClassName
) ? NULL
: lpClassName
,
899 IS_ATOM(lpClassName
) ? lpClassName
: 0,
919 if (offset
< 0) return GetClassLongA( hwnd
, offset
);
921 Wnd
= ValidateHwnd(hwnd
);
925 class = DesktopPtrToUser(Wnd
->pcls
);
926 if (class == NULL
) return 0;
928 if (offset
<= class->cbclsExtra
- sizeof(WORD
))
929 memcpy( &retvalue
, (char *)(class + 1) + offset
, sizeof(retvalue
) );
931 SetLastError( ERROR_INVALID_INDEX
);
937 LONG_PTR
IntGetWindowLong( HWND hwnd
, INT offset
, UINT size
, BOOL unicode
)
939 LONG_PTR retvalue
= 0;
942 if (offset
== GWLP_HWNDPARENT
)
944 HWND parent
= GetAncestor( hwnd
, GA_PARENT
);
945 if (parent
== GetDesktopWindow()) parent
= GetWindow( hwnd
, GW_OWNER
);
946 return (ULONG_PTR
)parent
;
949 if (!(wndPtr
= ValidateHwnd( hwnd
)))
951 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
957 if (offset
> (int)(wndPtr
->cbwndExtra
- size
))
959 WARN("Invalid offset %d\n", offset
);
960 SetLastError( ERROR_INVALID_INDEX
);
963 retvalue
= *((LONG_PTR
*)((PCHAR
)(wndPtr
+ 1) + offset
));
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 );
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;
980 if (!TestWindowProcess(wndPtr
))
982 SetLastError(ERROR_ACCESS_DENIED
);
985 retvalue
= (ULONG_PTR
)IntGetWndProc(wndPtr
, !unicode
);
989 WARN("Unknown offset %d\n", offset
);
990 SetLastError( ERROR_INVALID_INDEX
);
1001 GetWindowLongA ( HWND hWnd
, int nIndex
)
1003 return IntGetWindowLong( hWnd
, nIndex
, sizeof(LONG
), FALSE
);
1011 GetWindowLongW(HWND hWnd
, int nIndex
)
1013 return IntGetWindowLong( hWnd
, nIndex
, sizeof(LONG
), TRUE
);
1022 GetWindowLongPtrA(HWND hWnd
,
1025 return IntGetWindowLong( hWnd
, nIndex
, sizeof(LONG_PTR
), FALSE
);
1033 GetWindowLongPtrW(HWND hWnd
,
1036 return IntGetWindowLong( hWnd
, nIndex
, sizeof(LONG_PTR
), TRUE
);
1046 GetWindowWord(HWND hWnd
, int nIndex
)
1051 case GWLP_HINSTANCE
:
1052 case GWLP_HWNDPARENT
:
1057 WARN("Invalid offset %d\n", nIndex
);
1058 SetLastError( ERROR_INVALID_INDEX
);
1063 return IntGetWindowLong( hWnd
, nIndex
, sizeof(WORD
), FALSE
);
1071 RealGetWindowClassW(
1076 UNICODE_STRING ClassName
;
1077 ClassName
.MaximumLength
= cchType
* sizeof(WCHAR
);
1078 ClassName
.Buffer
= (PWSTR
)pszType
;
1080 return NtUserGetClassName(hwnd
,TRUE
,&ClassName
);
1089 RealGetWindowClassA(
1094 WCHAR tmpbuf
[MAX_ATOM_LEN
+ 1];
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
) );
1105 * Create a small icon based on a standard icon
1107 #if 0 // Keep vintage code from revision 18764 by GvG!
1109 CreateSmallIcon(HICON StdIcon
)
1111 HICON SmallIcon
= NULL
;
1114 int SmallIconHeight
;
1115 BITMAP StdBitmapInfo
;
1116 HDC hSourceDc
= NULL
;
1119 HBITMAP OldSourceBitmap
= NULL
;
1120 HBITMAP OldDestBitmap
= NULL
;
1122 SmallInfo
.hbmColor
= NULL
;
1123 SmallInfo
.hbmMask
= NULL
;
1125 /* We need something to work with... */
1126 if (NULL
== StdIcon
)
1131 SmallIconWidth
= GetSystemMetrics(SM_CXSMICON
);
1132 SmallIconHeight
= GetSystemMetrics(SM_CYSMICON
);
1133 if (! GetIconInfo(StdIcon
, &StdInfo
))
1135 ERR("Failed to get icon info for icon 0x%x\n", StdIcon
);
1138 if (! GetObjectW(StdInfo
.hbmMask
, sizeof(BITMAP
), &StdBitmapInfo
))
1140 ERR("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
1141 StdIcon
, StdInfo
.hbmColor
);
1144 if (StdBitmapInfo
.bmWidth
== SmallIconWidth
&&
1145 StdBitmapInfo
.bmHeight
== SmallIconHeight
)
1147 /* Icon already has the correct dimensions */
1151 hSourceDc
= CreateCompatibleDC(NULL
);
1152 if (NULL
== hSourceDc
)
1154 ERR("Failed to create source DC\n");
1157 hDestDc
= CreateCompatibleDC(NULL
);
1158 if (NULL
== hDestDc
)
1160 ERR("Failed to create dest DC\n");
1164 OldSourceBitmap
= SelectObject(hSourceDc
, StdInfo
.hbmColor
);
1165 if (NULL
== OldSourceBitmap
)
1167 ERR("Failed to select source color bitmap\n");
1170 SmallInfo
.hbmColor
= CreateCompatibleBitmap(hSourceDc
, SmallIconWidth
,
1172 if (NULL
== SmallInfo
.hbmColor
)
1174 ERR("Failed to create color bitmap\n");
1177 OldDestBitmap
= SelectObject(hDestDc
, SmallInfo
.hbmColor
);
1178 if (NULL
== OldDestBitmap
)
1180 ERR("Failed to select dest color bitmap\n");
1183 if (! StretchBlt(hDestDc
, 0, 0, SmallIconWidth
, SmallIconHeight
,
1184 hSourceDc
, 0, 0, StdBitmapInfo
.bmWidth
,
1185 StdBitmapInfo
.bmHeight
, SRCCOPY
))
1187 ERR("Failed to stretch color bitmap\n");
1191 if (NULL
== SelectObject(hSourceDc
, StdInfo
.hbmMask
))
1193 ERR("Failed to select source mask bitmap\n");
1196 SmallInfo
.hbmMask
= CreateCompatibleBitmap(hSourceDc
, SmallIconWidth
, SmallIconHeight
);
1197 if (NULL
== SmallInfo
.hbmMask
)
1199 ERR("Failed to create mask bitmap\n");
1202 if (NULL
== SelectObject(hDestDc
, SmallInfo
.hbmMask
))
1204 ERR("Failed to select dest mask bitmap\n");
1207 if (! StretchBlt(hDestDc
, 0, 0, SmallIconWidth
, SmallIconHeight
,
1208 hSourceDc
, 0, 0, StdBitmapInfo
.bmWidth
,
1209 StdBitmapInfo
.bmHeight
, SRCCOPY
))
1211 ERR("Failed to stretch mask bitmap\n");
1215 SmallInfo
.fIcon
= TRUE
;
1216 SmallInfo
.xHotspot
= SmallIconWidth
/ 2;
1217 SmallInfo
.yHotspot
= SmallIconHeight
/ 2;
1218 SmallIcon
= CreateIconIndirect(&SmallInfo
);
1219 if (NULL
== SmallIcon
)
1221 ERR("Failed to create icon\n");
1226 if (NULL
!= SmallInfo
.hbmMask
)
1228 DeleteObject(SmallInfo
.hbmMask
);
1230 if (NULL
!= OldDestBitmap
)
1232 SelectObject(hDestDc
, OldDestBitmap
);
1234 if (NULL
!= SmallInfo
.hbmColor
)
1236 DeleteObject(SmallInfo
.hbmColor
);
1238 if (NULL
!= hDestDc
)
1242 if (NULL
!= OldSourceBitmap
)
1244 SelectObject(hSourceDc
, OldSourceBitmap
);
1246 if (NULL
!= hSourceDc
)
1248 DeleteDC(hSourceDc
);
1256 RegisterClassExWOWW(WNDCLASSEXW
*lpwcx
,
1263 WNDCLASSEXW WndClass
;
1264 UNICODE_STRING ClassName
;
1265 UNICODE_STRING MenuName
= {0};
1266 CLSMENUNAME clsMenuName
;
1267 ANSI_STRING AnsiMenuName
;
1269 if (lpwcx
== NULL
|| lpwcx
->cbSize
!= sizeof(WNDCLASSEXW
) ||
1270 lpwcx
->cbClsExtra
< 0 || lpwcx
->cbWndExtra
< 0 ||
1271 lpwcx
->lpszClassName
== NULL
)
1273 TRACE("RegisterClassExWOWW Invalid Parameter Error!\n");
1274 SetLastError(ERROR_INVALID_PARAMETER
);
1280 if (!RegisterDefaultClasses
) RegisterSystemControls();
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.
1290 GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400)
1292 if (lpwcx
->hInstance
== User32Instance
)
1294 TRACE("RegisterClassExWOWW User32Instance!\n");
1295 SetLastError(ERROR_INVALID_PARAMETER
);
1298 /* Yes, this is correct. We should modify the passed structure. */
1299 if (lpwcx
->hInstance
== NULL
)
1300 ((WNDCLASSEXW
*)lpwcx
)->hInstance
= GetModuleHandleW(NULL
);
1302 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXW
));
1304 if (NULL == WndClass.hIconSm)
1306 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
1309 if (WndClass
.lpszMenuName
!= NULL
)
1311 if (!IS_INTRESOURCE(WndClass
.lpszMenuName
))
1313 if (WndClass
.lpszMenuName
[0])
1315 RtlInitUnicodeString(&MenuName
, WndClass
.lpszMenuName
);
1316 RtlUnicodeStringToAnsiString( &AnsiMenuName
, &MenuName
, TRUE
);
1321 MenuName
.Buffer
= (LPWSTR
)WndClass
.lpszMenuName
;
1322 AnsiMenuName
.Buffer
= (PCHAR
)WndClass
.lpszMenuName
;
1326 if (IS_ATOM(WndClass
.lpszClassName
))
1329 ClassName
.MaximumLength
= 0;
1330 ClassName
.Buffer
= (LPWSTR
)WndClass
.lpszClassName
;
1334 RtlInitUnicodeString(&ClassName
, WndClass
.lpszClassName
);
1337 clsMenuName
.pszClientAnsiMenuName
= AnsiMenuName
.Buffer
;
1338 clsMenuName
.pwszClientUnicodeMenuName
= MenuName
.Buffer
;
1339 clsMenuName
.pusMenuName
= &MenuName
;
1341 Atom
= NtUserRegisterClassExWOW( &WndClass
,
1343 NULL
, //PUNICODE_STRING ClsNVersion,
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
);
1360 RegisterClassExA(CONST WNDCLASSEXA
*lpwcx
)
1363 WNDCLASSEXW WndClass
;
1364 WCHAR mname
[MAX_BUFFER_LEN
];
1365 WCHAR cname
[MAX_BUFFER_LEN
];
1367 RtlCopyMemory(&WndClass
, lpwcx
, sizeof(WNDCLASSEXA
));
1369 if (WndClass
.lpszMenuName
!= NULL
)
1371 if (!IS_INTRESOURCE(WndClass
.lpszMenuName
))
1373 if (WndClass
.lpszMenuName
[0])
1375 if (!MultiByteToWideChar( CP_ACP
, 0, lpwcx
->lpszMenuName
, -1, mname
, MAX_ATOM_LEN
+ 1 )) return 0;
1377 WndClass
.lpszMenuName
= mname
;
1382 if (!IS_ATOM(WndClass
.lpszClassName
))
1384 if (!MultiByteToWideChar( CP_ACP
, 0, lpwcx
->lpszClassName
, -1, cname
, MAX_ATOM_LEN
+ 1 )) return 0;
1386 WndClass
.lpszClassName
= cname
;
1389 Atom
= RegisterClassExWOWW( &WndClass
,
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
);
1406 RegisterClassExW(CONST WNDCLASSEXW
*lpwcx
)
1410 Atom
= RegisterClassExWOWW( (WNDCLASSEXW
*)lpwcx
, 0, 0, 0, TRUE
);
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
);
1423 RegisterClassA(CONST WNDCLASSA
*lpWndClass
)
1427 if (lpWndClass
== NULL
)
1430 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSA
));
1431 Class
.cbSize
= sizeof(WNDCLASSEXA
);
1432 Class
.hIconSm
= NULL
;
1434 return RegisterClassExA(&Class
);
1441 RegisterClassW(CONST WNDCLASSW
*lpWndClass
)
1445 if (lpWndClass
== NULL
)
1448 RtlCopyMemory(&Class
.style
, lpWndClass
, sizeof(WNDCLASSW
));
1449 Class
.cbSize
= sizeof(WNDCLASSEXW
);
1450 Class
.hIconSm
= NULL
;
1452 return RegisterClassExW(&Class
);
1460 SetClassLongA (HWND hWnd
,
1464 PSTR lpStr
= (PSTR
)(ULONG_PTR
)dwNewLong
;
1465 UNICODE_STRING Value
= {0};
1466 BOOL Allocated
= FALSE
;
1469 /* FIXME - portability!!!! */
1471 if (nIndex
== GCL_MENUNAME
&& lpStr
!= NULL
)
1473 if (!IS_INTRESOURCE(lpStr
))
1475 if (!RtlCreateUnicodeStringFromAsciiz(&Value
,
1478 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1485 Value
.Buffer
= (PWSTR
)lpStr
;
1487 dwNewLong
= (LONG_PTR
)&Value
;
1489 else if (nIndex
== GCW_ATOM
&& lpStr
!= NULL
)
1491 if (!IS_ATOM(lpStr
))
1493 if (!RtlCreateUnicodeStringFromAsciiz(&Value
,
1496 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1503 Value
.Buffer
= (PWSTR
)lpStr
;
1505 dwNewLong
= (LONG_PTR
)&Value
;
1508 Ret
= (DWORD
)NtUserSetClassLong(hWnd
,
1515 RtlFreeUnicodeString(&Value
);
1527 SetClassLongW(HWND hWnd
,
1531 PWSTR lpStr
= (PWSTR
)(ULONG_PTR
)dwNewLong
;
1532 UNICODE_STRING Value
= {0};
1534 TRACE("%p %d %lx\n", hWnd
, nIndex
, dwNewLong
);
1536 /* FIXME - portability!!!! */
1538 if (nIndex
== GCL_MENUNAME
&& lpStr
!= NULL
)
1540 if (!IS_INTRESOURCE(lpStr
))
1542 RtlInitUnicodeString(&Value
,
1546 Value
.Buffer
= lpStr
;
1548 dwNewLong
= (LONG_PTR
)&Value
;
1550 else if (nIndex
== GCW_ATOM
&& lpStr
!= NULL
)
1552 if (!IS_ATOM(lpStr
))
1554 RtlInitUnicodeString(&Value
,
1558 Value
.Buffer
= lpStr
;
1560 dwNewLong
= (LONG_PTR
)&Value
;
1563 return (DWORD
)NtUserSetClassLong(hWnd
,
1575 SetClassLongPtrA(HWND hWnd
,
1588 SetClassLongPtrW(HWND hWnd
,
1607 * NOTE: Obsoleted in 32-bit windows
1610 if ((nIndex
< 0) && (nIndex
!= GCW_ATOM
))
1613 return (WORD
) SetClassLongW ( hWnd
, nIndex
, wNewWord
);
1621 SetWindowWord ( HWND hWnd
,int nIndex
,WORD wNewWord
)
1626 case GWLP_HINSTANCE
:
1627 case GWLP_HWNDPARENT
:
1632 WARN("Invalid offset %d\n", nIndex
);
1633 SetLastError( ERROR_INVALID_INDEX
);
1638 return NtUserSetWindowLong( hWnd
, nIndex
, wNewWord
, FALSE
);
1651 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, TRUE
);
1664 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, FALSE
);
1673 SetWindowLongPtrA(HWND hWnd
,
1677 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, FALSE
);
1685 SetWindowLongPtrW(HWND hWnd
,
1689 return NtUserSetWindowLong(hWnd
, nIndex
, dwNewLong
, FALSE
);
1700 HINSTANCE hInstance
)
1702 UNICODE_STRING ClassName
= {0};
1705 TRACE("class/atom: %s/%04x %p\n",
1706 IS_ATOM(lpClassName
) ? NULL
: lpClassName
,
1707 IS_ATOM(lpClassName
) ? lpClassName
: 0,
1710 if (!IS_ATOM(lpClassName
))
1712 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName
,
1715 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1720 ClassName
.Buffer
= (PWSTR
)((ULONG_PTR
)lpClassName
);
1722 Ret
= NtUserUnregisterClass(&ClassName
,
1726 if (!IS_ATOM(lpClassName
))
1727 RtlFreeUnicodeString(&ClassName
);
1739 LPCWSTR lpClassName
,
1740 HINSTANCE hInstance
)
1742 UNICODE_STRING ClassName
= {0};
1744 TRACE("class/atom: %S/%04x %p\n",
1745 IS_ATOM(lpClassName
) ? NULL
: lpClassName
,
1746 IS_ATOM(lpClassName
) ? lpClassName
: 0,
1749 if (!IS_ATOM(lpClassName
))
1751 RtlInitUnicodeString(&ClassName
,
1755 ClassName
.Buffer
= (PWSTR
)((ULONG_PTR
)lpClassName
);
1757 return NtUserUnregisterClass(&ClassName
,