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