Visual C++ backend for rbuild (for now just a hacked mingw backend) and related compi...
[reactos.git] / dll / win32 / user32 / windows / class.c
1 /*
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)
7 * UPDATE HISTORY:
8 * 09-05-2001 CSH Created
9 */
10
11 #include <user32.h>
12
13 #include <wine/debug.h>
14 WINE_DEFAULT_DEBUG_CHANNEL(user32);
15
16 /*
17 * @implemented
18 */
19 BOOL
20 STDCALL
21 GetClassInfoExA(
22 HINSTANCE hInstance,
23 LPCSTR lpszClass,
24 LPWNDCLASSEXA lpwcx)
25 {
26 UNICODE_STRING ClassName = {0};
27 BOOL Ret;
28
29 TRACE("%p class/atom: %s/%04x %p\n", hInstance,
30 IS_ATOM(lpszClass) ? NULL : lpszClass,
31 IS_ATOM(lpszClass) ? lpszClass : 0,
32 lpwcx);
33
34 //HACKHACK: This is ROS-specific and should go away
35 lpwcx->cbSize = sizeof(*lpwcx);
36
37 if (hInstance == User32Instance)
38 {
39 hInstance = NULL;
40 }
41
42 if (lpszClass == NULL)
43 {
44 SetLastError(ERROR_INVALID_PARAMETER);
45 return FALSE;
46 }
47
48 if (IS_ATOM(lpszClass))
49 {
50 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
51 }
52 else
53 {
54 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
55 lpszClass))
56 {
57 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
58 return FALSE;
59 }
60 }
61
62 Ret = NtUserGetClassInfo(hInstance,
63 &ClassName,
64 (LPWNDCLASSEXW)lpwcx,
65 NULL,
66 TRUE);
67
68 if (!IS_ATOM(lpszClass))
69 {
70 RtlFreeUnicodeString(&ClassName);
71 }
72
73 return Ret;
74 }
75
76
77 /*
78 * @implemented
79 */
80 BOOL
81 STDCALL
82 GetClassInfoExW(
83 HINSTANCE hInstance,
84 LPCWSTR lpszClass,
85 LPWNDCLASSEXW lpwcx)
86 {
87 UNICODE_STRING ClassName = {0};
88
89 TRACE("%p class/atom: %S/%04x %p\n", hInstance,
90 IS_ATOM(lpszClass) ? NULL : lpszClass,
91 IS_ATOM(lpszClass) ? lpszClass : 0,
92 lpwcx);
93
94 //HACKHACK: This is ROS-specific and should go away
95 lpwcx->cbSize = sizeof(*lpwcx);
96
97 if (hInstance == User32Instance)
98 {
99 hInstance = NULL;
100 }
101
102 if (lpszClass == NULL)
103 {
104 SetLastError(ERROR_INVALID_PARAMETER);
105 return FALSE;
106 }
107
108 if (IS_ATOM(lpszClass))
109 {
110 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
111 }
112 else
113 {
114 RtlInitUnicodeString(&ClassName,
115 lpszClass);
116 }
117
118 return NtUserGetClassInfo(hInstance,
119 &ClassName,
120 lpwcx,
121 NULL,
122 FALSE);
123 }
124
125
126 /*
127 * @implemented
128 */
129 BOOL
130 STDCALL
131 GetClassInfoA(
132 HINSTANCE hInstance,
133 LPCSTR lpClassName,
134 LPWNDCLASSA lpWndClass)
135 {
136 WNDCLASSEXA wcex;
137 BOOL retval;
138
139 retval = GetClassInfoExA(hInstance, lpClassName, &wcex);
140 if (retval)
141 {
142 lpWndClass->style = wcex.style;
143 lpWndClass->lpfnWndProc = wcex.lpfnWndProc;
144 lpWndClass->cbClsExtra = wcex.cbClsExtra;
145 lpWndClass->cbWndExtra = wcex.cbWndExtra;
146 lpWndClass->hInstance = wcex.hInstance;
147 lpWndClass->hIcon = wcex.hIcon;
148 lpWndClass->hCursor = wcex.hCursor;
149 lpWndClass->hbrBackground = wcex.hbrBackground;
150 lpWndClass->lpszMenuName = wcex.lpszMenuName;
151 lpWndClass->lpszClassName = wcex.lpszClassName;
152 }
153
154 return retval;
155 }
156
157 /*
158 * @implemented
159 */
160 BOOL
161 STDCALL
162 GetClassInfoW(
163 HINSTANCE hInstance,
164 LPCWSTR lpClassName,
165 LPWNDCLASSW lpWndClass)
166 {
167 WNDCLASSEXW wcex;
168 BOOL retval;
169
170 retval = GetClassInfoExW(hInstance, lpClassName, &wcex);
171 if (retval)
172 {
173 lpWndClass->style = wcex.style;
174 lpWndClass->lpfnWndProc = wcex.lpfnWndProc;
175 lpWndClass->cbClsExtra = wcex.cbClsExtra;
176 lpWndClass->cbWndExtra = wcex.cbWndExtra;
177 lpWndClass->hInstance = wcex.hInstance;
178 lpWndClass->hIcon = wcex.hIcon;
179 lpWndClass->hCursor = wcex.hCursor;
180 lpWndClass->hbrBackground = wcex.hbrBackground;
181 lpWndClass->lpszMenuName = wcex.lpszMenuName;
182 lpWndClass->lpszClassName = wcex.lpszClassName;
183 }
184 return retval;
185 }
186
187 /*
188 * @implemented
189 */
190 DWORD STDCALL
191 GetClassLongA(HWND hWnd, int nIndex)
192 {
193 PWINDOW Wnd;
194 PWINDOWCLASS Class;
195 ULONG_PTR Ret = 0;
196
197 TRACE("%p %d\n", hWnd, nIndex);
198
199 Wnd = ValidateHwnd(hWnd);
200 if (!Wnd)
201 return 0;
202
203 _SEH_TRY
204 {
205 Class = DesktopPtrToUser(Wnd->Class);
206 if (Class != NULL)
207 {
208 if (nIndex >= 0)
209 {
210 if (nIndex + sizeof(ULONG_PTR) < nIndex ||
211 nIndex + sizeof(ULONG_PTR) > Class->ClsExtra)
212 {
213 SetLastError(ERROR_INVALID_PARAMETER);
214 }
215 else
216 Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex);
217 }
218 else
219 {
220 switch (nIndex)
221 {
222 case GCL_CBWNDEXTRA:
223 Ret = (ULONG_PTR)Class->WndExtra;
224 break;
225
226 case GCL_CBCLSEXTRA:
227 Ret = (ULONG_PTR)Class->ClsExtra;
228 break;
229
230 case GCL_HBRBACKGROUND:
231 Ret = (ULONG_PTR)Class->hbrBackground;
232 if (Ret != 0 && Ret < 0x4000)
233 Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1);
234 break;
235
236 case GCL_HMODULE:
237 Ret = (ULONG_PTR)Class->hInstance;
238 break;
239
240 case GCL_MENUNAME:
241 Ret = (ULONG_PTR)Class->AnsiMenuName;
242 break;
243
244 case GCL_STYLE:
245 Ret = (ULONG_PTR)Class->Style;
246 break;
247
248 case GCW_ATOM:
249 Ret = (ULONG_PTR)Class->Atom;
250 break;
251
252 case GCLP_HCURSOR:
253 /* FIXME - get handle from pointer to CURSOR object */
254 Ret = (ULONG_PTR)Class->hCursor;
255 break;
256
257 case GCLP_HICON:
258 /* FIXME - get handle from pointer to ICON object */
259 Ret = (ULONG_PTR)Class->hIcon;
260 break;
261
262 case GCLP_HICONSM:
263 /* FIXME - get handle from pointer to ICON object */
264 Ret = (ULONG_PTR)Class->hIconSm;
265 break;
266
267 case GCLP_WNDPROC:
268 /* We need to make a call to win32k as it may be required to
269 create a callproc handle */
270 Wnd = NULL;
271 break;
272
273 default:
274 SetLastError(ERROR_INVALID_INDEX);
275 break;
276 }
277 }
278 }
279 else
280 {
281 /* This is a race condition! Call win32k to make sure we're getting
282 the correct result */
283 Wnd = NULL; /* Make sure we call NtUserGetClassLong */
284
285 WARN("Invalid class for hwnd 0x%p!\n", hWnd);
286 }
287 }
288 _SEH_HANDLE
289 {
290 Wnd = NULL; /* Make sure we call NtUserGetClassLong */
291 }
292 _SEH_END;
293
294 if (Wnd == NULL)
295 Ret = NtUserGetClassLong(hWnd, nIndex, TRUE);
296
297 return Ret;
298 }
299
300 /*
301 * @implemented
302 */
303 DWORD STDCALL
304 GetClassLongW ( HWND hWnd, int nIndex )
305 {
306 PWINDOW Wnd;
307 PWINDOWCLASS Class;
308 ULONG_PTR Ret = 0;
309
310 TRACE("%p %d\n", hWnd, nIndex);
311
312 Wnd = ValidateHwnd(hWnd);
313 if (!Wnd)
314 return 0;
315
316 _SEH_TRY
317 {
318 Class = DesktopPtrToUser(Wnd->Class);
319 if (Class != NULL)
320 {
321 if (nIndex >= 0)
322 {
323 if (nIndex + sizeof(ULONG_PTR) < nIndex ||
324 nIndex + sizeof(ULONG_PTR) > Class->ClsExtra)
325 {
326 SetLastError(ERROR_INVALID_PARAMETER);
327 }
328 else
329 Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex);
330 }
331 else
332 {
333 switch (nIndex)
334 {
335 case GCL_CBWNDEXTRA:
336 Ret = (ULONG_PTR)Class->WndExtra;
337 break;
338
339 case GCL_CBCLSEXTRA:
340 Ret = (ULONG_PTR)Class->ClsExtra;
341 break;
342
343 case GCL_HBRBACKGROUND:
344 Ret = (ULONG_PTR)Class->hbrBackground;
345 if (Ret != 0 && Ret < 0x4000)
346 Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1);
347 break;
348
349 case GCL_HMODULE:
350 Ret = (ULONG_PTR)Class->hInstance;
351 break;
352
353 case GCL_MENUNAME:
354 Ret = (ULONG_PTR)Class->MenuName;
355 break;
356
357 case GCL_STYLE:
358 Ret = (ULONG_PTR)Class->Style;
359 break;
360
361 case GCW_ATOM:
362 Ret = (ULONG_PTR)Class->Atom;
363 break;
364
365 case GCLP_HCURSOR:
366 /* FIXME - get handle from pointer to CURSOR object */
367 Ret = (ULONG_PTR)Class->hCursor;
368 break;
369
370 case GCLP_HICON:
371 /* FIXME - get handle from pointer to ICON object */
372 Ret = (ULONG_PTR)Class->hIcon;
373 break;
374
375 case GCLP_HICONSM:
376 /* FIXME - get handle from pointer to ICON object */
377 Ret = (ULONG_PTR)Class->hIconSm;
378 break;
379
380 case GCLP_WNDPROC:
381 /* We need to make a call to win32k as it may be required to
382 create a callproc handle */
383 Wnd = NULL;
384 break;
385
386 default:
387 SetLastError(ERROR_INVALID_INDEX);
388 break;
389 }
390 }
391 }
392 else
393 {
394 /* This is a race condition! Call win32k to make sure we're getting
395 the correct result */
396 Wnd = NULL; /* Make sure we call NtUserGetClassLong */
397
398 WARN("Invalid class for hwnd 0x%p!\n", hWnd);
399 }
400 }
401 _SEH_HANDLE
402 {
403 Wnd = NULL; /* Make sure we call NtUserGetClassLong */
404 }
405 _SEH_END;
406
407 if (Wnd == NULL)
408 Ret = NtUserGetClassLong(hWnd, nIndex, FALSE);
409
410 return Ret;
411 }
412
413
414 /*
415 * @implemented
416 */
417 int STDCALL
418 GetClassNameA(
419 HWND hWnd,
420 LPSTR lpClassName,
421 int nMaxCount)
422 {
423 ANSI_STRING ClassName;
424 int Result;
425
426 ClassName.MaximumLength = nMaxCount;
427 ClassName.Buffer = lpClassName;
428
429 Result = NtUserGetClassName(hWnd,
430 (PUNICODE_STRING)&ClassName,
431 TRUE);
432
433 TRACE("%p class/atom: %s/%04x %x\n", hWnd,
434 IS_ATOM(lpClassName) ? NULL : lpClassName,
435 IS_ATOM(lpClassName) ? lpClassName : 0,
436 nMaxCount);
437
438 return Result;
439 }
440
441
442 /*
443 * @implemented
444 */
445 int
446 STDCALL
447 GetClassNameW(
448 HWND hWnd,
449 LPWSTR lpClassName,
450 int nMaxCount)
451 {
452 UNICODE_STRING ClassName;
453 int Result;
454
455 ClassName.MaximumLength = nMaxCount * sizeof(WCHAR);
456 ClassName.Buffer = lpClassName;
457
458 Result = NtUserGetClassName(hWnd,
459 &ClassName,
460 FALSE);
461
462 TRACE("%p class/atom: %S/%04x %x\n", hWnd,
463 IS_ATOM(lpClassName) ? NULL : lpClassName,
464 IS_ATOM(lpClassName) ? lpClassName : 0,
465 nMaxCount);
466
467 return Result;
468 }
469
470
471 /*
472 * @implemented
473 */
474 WORD
475 STDCALL
476 GetClassWord(
477 HWND hWnd,
478 int nIndex)
479 /*
480 * NOTE: Obsoleted in 32-bit windows
481 */
482 {
483 TRACE("%p %x\n", hWnd, nIndex);
484
485 if ((nIndex < 0) && (nIndex != GCW_ATOM))
486 return 0;
487
488 return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
489 }
490
491
492 /*
493 * @implemented
494 */
495 LONG
496 STDCALL
497 GetWindowLongA ( HWND hWnd, int nIndex )
498 {
499 PWINDOW Wnd;
500
501 Wnd = ValidateHwnd(hWnd);
502 if (Wnd == NULL)
503 return 0;
504
505 if (nIndex >= 0)
506 {
507 if ((DWORD)nIndex + sizeof(LONG) > Wnd->ExtraDataSize)
508 {
509 SetLastError(ERROR_INVALID_PARAMETER);
510 return 0;
511 }
512
513 return *((LONG *)((PCHAR)(Wnd + 1) + nIndex));
514 }
515 else
516 {
517 switch (nIndex)
518 {
519 case GWL_EXSTYLE:
520 return Wnd->ExStyle;
521 case GWL_STYLE:
522 return Wnd->Style;
523 case GWL_HINSTANCE:
524 return (LONG)Wnd->Instance;
525 case GWL_ID:
526 return Wnd->IDMenu;
527 case GWL_USERDATA:
528 return Wnd->UserData;
529
530 case GWL_HWNDPARENT:
531 {
532 HWND parent = GetAncestor( hWnd, GA_PARENT );
533 if (parent == GetDesktopWindow()) parent = GetWindow( hWnd, GW_OWNER );
534 return (LONG)parent;
535 }
536 case GWL_WNDPROC:
537 /* Call win32k for this as a callproc handle may need
538 to be created */
539 return NtUserGetWindowLong(hWnd, nIndex, TRUE);
540
541 default:
542 SetLastError(ERROR_INVALID_PARAMETER);
543 return 0;
544 }
545 }
546 }
547
548
549 /*
550 * @implemented
551 */
552 LONG
553 STDCALL
554 GetWindowLongW(HWND hWnd, int nIndex)
555 {
556 PWINDOW Wnd;
557
558 Wnd = ValidateHwnd(hWnd);
559 if (Wnd == NULL)
560 return 0;
561
562 if (nIndex >= 0)
563 {
564 if ((DWORD)nIndex + sizeof(LONG) > Wnd->ExtraDataSize)
565 {
566 SetLastError(ERROR_INVALID_PARAMETER);
567 return 0;
568 }
569
570 return *((LONG *)((PCHAR)(Wnd + 1) + nIndex));
571 }
572 else
573 {
574 switch (nIndex)
575 {
576 case GWL_EXSTYLE:
577 return Wnd->ExStyle;
578 case GWL_STYLE:
579 return Wnd->Style;
580 case GWL_HINSTANCE:
581 return (LONG)Wnd->Instance;
582 case GWL_ID:
583 return Wnd->IDMenu;
584 case GWL_USERDATA:
585 return Wnd->UserData;
586
587 case GWL_HWNDPARENT:
588 {
589 HWND parent = GetAncestor( hWnd, GA_PARENT );
590 if (parent == GetDesktopWindow()) parent = GetWindow( hWnd, GW_OWNER );
591 return (LONG)parent;
592 }
593 case GWL_WNDPROC:
594 /* Call win32k for this as a callproc handle may need
595 to be created */
596 return NtUserGetWindowLong(hWnd, nIndex, FALSE);
597
598 default:
599 SetLastError(ERROR_INVALID_PARAMETER);
600 return 0;
601 }
602 }
603 }
604
605 /*
606 * @implemented
607 */
608 WORD
609 STDCALL
610 GetWindowWord(HWND hWnd, int nIndex)
611 {
612 return (WORD)GetWindowLongW(hWnd, nIndex);
613 }
614
615 /*
616 * @implemented
617 */
618 WORD
619 STDCALL
620 SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
621 {
622 return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
623 }
624
625 /*
626 * @implemented
627 */
628 UINT
629 STDCALL
630 RealGetWindowClassW(
631 HWND hwnd,
632 LPWSTR pszType,
633 UINT cchType)
634 {
635 /* FIXME: Implement correct functionality of RealGetWindowClass */
636 return GetClassNameW(hwnd,pszType,cchType);
637 }
638
639
640 /*
641 * @implemented
642 */
643 UINT
644 STDCALL
645 RealGetWindowClassA(
646 HWND hwnd,
647 LPSTR pszType,
648 UINT cchType)
649 {
650 /* FIXME: Implement correct functionality of RealGetWindowClass */
651 return GetClassNameA(hwnd,pszType,cchType);
652 }
653
654 /*
655 * Create a small icon based on a standard icon
656 */
657 static HICON
658 CreateSmallIcon(HICON StdIcon)
659 {
660 HICON SmallIcon = NULL;
661 ICONINFO StdInfo;
662 int SmallIconWidth;
663 int SmallIconHeight;
664 BITMAP StdBitmapInfo;
665 HDC hInfoDc = NULL;
666 HDC hSourceDc = NULL;
667 HDC hDestDc = NULL;
668 ICONINFO SmallInfo;
669 HBITMAP OldSourceBitmap = NULL;
670 HBITMAP OldDestBitmap = NULL;
671
672 SmallInfo.hbmColor = NULL;
673 SmallInfo.hbmMask = NULL;
674
675 /* We need something to work with... */
676 if (NULL == StdIcon)
677 {
678 goto cleanup;
679 }
680
681 SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
682 SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
683 if (! GetIconInfo(StdIcon, &StdInfo))
684 {
685 ERR("Failed to get icon info for icon 0x%x\n", StdIcon);
686 goto cleanup;
687 }
688 if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
689 {
690 ERR("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
691 StdIcon, StdInfo.hbmColor);
692 goto cleanup;
693 }
694 if (StdBitmapInfo.bmWidth == SmallIconWidth &&
695 StdBitmapInfo.bmHeight == SmallIconHeight)
696 {
697 /* Icon already has the correct dimensions */
698 return StdIcon;
699 }
700
701 /* Get a handle to a info DC and handles to DCs which can be used to
702 select a bitmap into. This is done to avoid triggering a switch to
703 graphics mode (if we're currently in text/blue screen mode) */
704 hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
705 if (NULL == hInfoDc)
706 {
707 ERR("Failed to create info DC\n");
708 goto cleanup;
709 }
710 hSourceDc = CreateCompatibleDC(NULL);
711 if (NULL == hSourceDc)
712 {
713 ERR("Failed to create source DC\n");
714 goto cleanup;
715 }
716 hDestDc = CreateCompatibleDC(NULL);
717 if (NULL == hDestDc)
718 {
719 ERR("Failed to create dest DC\n");
720 goto cleanup;
721 }
722
723 OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
724 if (NULL == OldSourceBitmap)
725 {
726 ERR("Failed to select source color bitmap\n");
727 goto cleanup;
728 }
729 SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
730 SmallIconHeight);
731 if (NULL == SmallInfo.hbmColor)
732 {
733 ERR("Failed to create color bitmap\n");
734 goto cleanup;
735 }
736 OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
737 if (NULL == OldDestBitmap)
738 {
739 ERR("Failed to select dest color bitmap\n");
740 goto cleanup;
741 }
742 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
743 hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
744 StdBitmapInfo.bmHeight, SRCCOPY))
745 {
746 ERR("Failed to stretch color bitmap\n");
747 goto cleanup;
748 }
749
750 if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
751 {
752 ERR("Failed to select source mask bitmap\n");
753 goto cleanup;
754 }
755 SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
756 NULL);
757 if (NULL == SmallInfo.hbmMask)
758 {
759 ERR("Failed to create mask bitmap\n");
760 goto cleanup;
761 }
762 if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
763 {
764 ERR("Failed to select dest mask bitmap\n");
765 goto cleanup;
766 }
767 if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
768 hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
769 StdBitmapInfo.bmHeight, SRCCOPY))
770 {
771 ERR("Failed to stretch mask bitmap\n");
772 goto cleanup;
773 }
774
775 SmallInfo.fIcon = TRUE;
776 SmallInfo.xHotspot = SmallIconWidth / 2;
777 SmallInfo.yHotspot = SmallIconHeight / 2;
778 SmallIcon = CreateIconIndirect(&SmallInfo);
779 if (NULL == SmallIcon)
780 {
781 ERR("Failed to create icon\n");
782 goto cleanup;
783 }
784
785 cleanup:
786 if (NULL != SmallInfo.hbmMask)
787 {
788 DeleteObject(SmallInfo.hbmMask);
789 }
790 if (NULL != OldDestBitmap)
791 {
792 SelectObject(hDestDc, OldDestBitmap);
793 }
794 if (NULL != SmallInfo.hbmColor)
795 {
796 DeleteObject(SmallInfo.hbmColor);
797 }
798 if (NULL != hDestDc)
799 {
800 DeleteDC(hDestDc);
801 }
802 if (NULL != OldSourceBitmap)
803 {
804 SelectObject(hSourceDc, OldSourceBitmap);
805 }
806 if (NULL != hSourceDc)
807 {
808 DeleteDC(hSourceDc);
809 }
810 if (NULL != hInfoDc)
811 {
812 DeleteDC(hInfoDc);
813 }
814
815 return SmallIcon;
816 }
817
818
819 ATOM STDCALL
820 RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
821 LPDWORD pdwWowData,
822 WORD fnID,
823 DWORD dwFlags)
824 {
825 RTL_ATOM Atom = 0;
826 return (ATOM)Atom;
827 }
828
829 /*
830 * @implemented
831 */
832 ATOM STDCALL
833 RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
834 {
835 RTL_ATOM Atom;
836 WNDCLASSEXA WndClass;
837 UNICODE_STRING ClassName;
838 UNICODE_STRING MenuName = {0};
839 HMENU hMenu = NULL;
840
841 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) ||
842 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
843 lpwcx->lpszClassName == NULL)
844 {
845 SetLastError(ERROR_INVALID_PARAMETER);
846 return 0;
847 }
848
849 /*
850 * On real Windows this looks more like:
851 * if (lpwcx->hInstance == User32Instance &&
852 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
853 * But since I have no idea what the magic field in the
854 * TEB structure means, I rather decided to omit that.
855 * -- Filip Navara
856 */
857 if (lpwcx->hInstance == User32Instance)
858 {
859 SetLastError(ERROR_INVALID_PARAMETER);
860 return 0;
861 }
862
863 /* Yes, this is correct. We should modify the passed structure. */
864 if (lpwcx->hInstance == NULL)
865 ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
866
867 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
868
869 if (NULL == WndClass.hIconSm)
870 {
871 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
872 }
873
874 if (WndClass.lpszMenuName != NULL)
875 {
876 if (!IS_INTRESOURCE(WndClass.lpszMenuName))
877 {
878 if (WndClass.lpszMenuName[0])
879 {
880 RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName);
881 }
882 }
883 else
884 {
885 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
886 }
887
888 if (MenuName.Buffer != NULL)
889 hMenu = LoadMenuA(WndClass.hInstance, WndClass.lpszMenuName);
890 }
891
892 if (IS_ATOM(WndClass.lpszClassName))
893 {
894 ClassName.Length =
895 ClassName.MaximumLength = 0;
896 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
897 }
898 else
899 {
900 RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName);
901 }
902
903 Atom = NtUserRegisterClassEx((WNDCLASSEXW*)&WndClass,
904 &ClassName,
905 &MenuName,
906 NULL,
907 REGISTERCLASS_ANSI,
908 hMenu);
909
910 TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
911 Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
912 lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
913
914 if (!IS_INTRESOURCE(WndClass.lpszMenuName))
915 RtlFreeUnicodeString(&MenuName);
916 if (!IS_ATOM(WndClass.lpszClassName))
917 RtlFreeUnicodeString(&ClassName);
918
919 return (ATOM)Atom;
920 }
921
922 /*
923 * @implemented
924 */
925 ATOM STDCALL
926 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
927 {
928 ATOM Atom;
929 WNDCLASSEXW WndClass;
930 UNICODE_STRING ClassName;
931 UNICODE_STRING MenuName = {0};
932 HMENU hMenu = NULL;
933
934 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
935 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
936 lpwcx->lpszClassName == NULL)
937 {
938 SetLastError(ERROR_INVALID_PARAMETER);
939 return 0;
940 }
941
942 /*
943 * On real Windows this looks more like:
944 * if (lpwcx->hInstance == User32Instance &&
945 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
946 * But since I have no idea what the magic field in the
947 * TEB structure means, I rather decided to omit that.
948 * -- Filip Navara
949 */
950 if (lpwcx->hInstance == User32Instance)
951 {
952 SetLastError(ERROR_INVALID_PARAMETER);
953 return 0;
954 }
955
956 /* Yes, this is correct. We should modify the passed structure. */
957 if (lpwcx->hInstance == NULL)
958 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
959
960 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
961
962 if (NULL == WndClass.hIconSm)
963 {
964 WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
965 }
966
967 if (WndClass.lpszMenuName != NULL)
968 {
969 if (!IS_INTRESOURCE(WndClass.lpszMenuName))
970 {
971 if (WndClass.lpszMenuName[0])
972 {
973 RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
974 }
975 }
976 else
977 {
978 MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
979 }
980
981 if (MenuName.Buffer != NULL)
982 hMenu = LoadMenuW(WndClass.hInstance, WndClass.lpszMenuName);
983 }
984
985 if (IS_ATOM(WndClass.lpszClassName))
986 {
987 ClassName.Length =
988 ClassName.MaximumLength = 0;
989 ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
990 }
991 else
992 {
993 RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
994 }
995
996 Atom = (ATOM)NtUserRegisterClassEx(&WndClass,
997 &ClassName,
998 &MenuName,
999 NULL,
1000 0,
1001 hMenu);
1002
1003 TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
1004 Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
1005 lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
1006
1007 return Atom;
1008 }
1009
1010 /*
1011 * @implemented
1012 */
1013 ATOM STDCALL
1014 RegisterClassA(CONST WNDCLASSA *lpWndClass)
1015 {
1016 WNDCLASSEXA Class;
1017
1018 if (lpWndClass == NULL)
1019 return 0;
1020
1021 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
1022 Class.cbSize = sizeof(WNDCLASSEXA);
1023 Class.hIconSm = NULL;
1024
1025 return RegisterClassExA(&Class);
1026 }
1027
1028 /*
1029 * @implemented
1030 */
1031 ATOM STDCALL
1032 RegisterClassW(CONST WNDCLASSW *lpWndClass)
1033 {
1034 WNDCLASSEXW Class;
1035
1036 if (lpWndClass == NULL)
1037 return 0;
1038
1039 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
1040 Class.cbSize = sizeof(WNDCLASSEXW);
1041 Class.hIconSm = NULL;
1042
1043 return RegisterClassExW(&Class);
1044 }
1045
1046 /*
1047 * @implemented
1048 */
1049 DWORD
1050 STDCALL
1051 SetClassLongA (HWND hWnd,
1052 int nIndex,
1053 LONG dwNewLong)
1054 {
1055 PSTR lpStr = (PSTR)dwNewLong;
1056 UNICODE_STRING Value = {0};
1057 BOOL Allocated = FALSE;
1058 DWORD Ret;
1059
1060 TRACE("%p %d %lx\n", hWnd, nIndex, dwNewLong);
1061
1062 /* FIXME - portability!!!! */
1063
1064 if (nIndex == GCL_MENUNAME && lpStr != NULL)
1065 {
1066 if (!IS_INTRESOURCE(lpStr))
1067 {
1068 if (!RtlCreateUnicodeStringFromAsciiz(&Value,
1069 lpStr))
1070 {
1071 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1072 return 0;
1073 }
1074
1075 Allocated = TRUE;
1076 }
1077 else
1078 Value.Buffer = (PWSTR)lpStr;
1079
1080 dwNewLong = (LONG)&Value;
1081 }
1082 else if (nIndex == GCW_ATOM && lpStr != NULL)
1083 {
1084 if (!IS_ATOM(lpStr))
1085 {
1086 if (!RtlCreateUnicodeStringFromAsciiz(&Value,
1087 lpStr))
1088 {
1089 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1090 return 0;
1091 }
1092
1093 Allocated = TRUE;
1094 }
1095 else
1096 Value.Buffer = (PWSTR)lpStr;
1097
1098 dwNewLong = (LONG)&Value;
1099 }
1100
1101 Ret = (DWORD)NtUserSetClassLong(hWnd,
1102 nIndex,
1103 dwNewLong,
1104 TRUE);
1105
1106 if (Allocated)
1107 {
1108 RtlFreeUnicodeString(&Value);
1109 }
1110
1111 return Ret;
1112 }
1113
1114
1115 /*
1116 * @implemented
1117 */
1118 DWORD
1119 STDCALL
1120 SetClassLongW(HWND hWnd,
1121 int nIndex,
1122 LONG dwNewLong)
1123 {
1124 PWSTR lpStr = (PWSTR)dwNewLong;
1125 UNICODE_STRING Value = {0};
1126
1127 TRACE("%p %d %lx\n", hWnd, nIndex, dwNewLong);
1128
1129 /* FIXME - portability!!!! */
1130
1131 if (nIndex == GCL_MENUNAME && lpStr != NULL)
1132 {
1133 if (!IS_INTRESOURCE(lpStr))
1134 {
1135 RtlInitUnicodeString(&Value,
1136 lpStr);
1137 }
1138 else
1139 Value.Buffer = lpStr;
1140
1141 dwNewLong = (LONG)&Value;
1142 }
1143 else if (nIndex == GCW_ATOM && lpStr != NULL)
1144 {
1145 if (!IS_ATOM(lpStr))
1146 {
1147 RtlInitUnicodeString(&Value,
1148 lpStr);
1149 }
1150 else
1151 Value.Buffer = lpStr;
1152
1153 dwNewLong = (LONG)&Value;
1154 }
1155
1156 return (DWORD)NtUserSetClassLong(hWnd,
1157 nIndex,
1158 dwNewLong,
1159 FALSE);
1160 }
1161
1162
1163 /*
1164 * @implemented
1165 */
1166 WORD
1167 STDCALL
1168 SetClassWord(
1169 HWND hWnd,
1170 int nIndex,
1171 WORD wNewWord)
1172 /*
1173 * NOTE: Obsoleted in 32-bit windows
1174 */
1175 {
1176 if ((nIndex < 0) && (nIndex != GCW_ATOM))
1177 return 0;
1178
1179 return (WORD) SetClassLongW ( hWnd, nIndex, wNewWord );
1180 }
1181
1182
1183 /*
1184 * @implemented
1185 */
1186 LONG
1187 STDCALL
1188 SetWindowLongA(
1189 HWND hWnd,
1190 int nIndex,
1191 LONG dwNewLong)
1192 {
1193 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
1194 }
1195
1196
1197 /*
1198 * @implemented
1199 */
1200 LONG
1201 STDCALL
1202 SetWindowLongW(
1203 HWND hWnd,
1204 int nIndex,
1205 LONG dwNewLong)
1206 {
1207 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
1208 }
1209
1210
1211 /*
1212 * @implemented
1213 */
1214 BOOL
1215 STDCALL
1216 UnregisterClassA(
1217 LPCSTR lpClassName,
1218 HINSTANCE hInstance)
1219 {
1220 UNICODE_STRING ClassName = {0};
1221 BOOL Ret;
1222
1223 TRACE("class/atom: %s/%04x %p\n",
1224 IS_ATOM(lpClassName) ? NULL : lpClassName,
1225 IS_ATOM(lpClassName) ? lpClassName : 0,
1226 hInstance);
1227
1228 if (!IS_ATOM(lpClassName))
1229 {
1230 if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
1231 lpClassName))
1232 {
1233 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1234 return 0;
1235 }
1236 }
1237 else
1238 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
1239
1240 Ret = NtUserUnregisterClass(&ClassName,
1241 hInstance,
1242 0);
1243
1244 if (!IS_ATOM(lpClassName))
1245 RtlFreeUnicodeString(&ClassName);
1246
1247 return Ret;
1248 }
1249
1250
1251 /*
1252 * @implemented
1253 */
1254 BOOL
1255 STDCALL
1256 UnregisterClassW(
1257 LPCWSTR lpClassName,
1258 HINSTANCE hInstance)
1259 {
1260 UNICODE_STRING ClassName = {0};
1261
1262 TRACE("class/atom: %S/%04x %p\n",
1263 IS_ATOM(lpClassName) ? NULL : lpClassName,
1264 IS_ATOM(lpClassName) ? lpClassName : 0,
1265 hInstance);
1266
1267 if (!IS_ATOM(lpClassName))
1268 {
1269 RtlInitUnicodeString(&ClassName,
1270 lpClassName);
1271 }
1272 else
1273 ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
1274
1275 return NtUserUnregisterClass(&ClassName,
1276 hInstance,
1277 0);
1278 }
1279
1280 /* EOF */