(Re)move USER32 headers from include/user32.
[reactos.git] / reactos / lib / user32 / windows / class.c
1 /* $Id$
2 *
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)
8 * UPDATE HISTORY:
9 * 09-05-2001 CSH Created
10 */
11
12 #include "user32.h"
13 #include <string.h>
14 #include <stdlib.h>
15 #include <debug.h>
16 #include <window.h>
17 #include <strpool.h>
18
19
20 static BOOL GetClassInfoExCommon(
21 HINSTANCE hInst,
22 LPCWSTR lpszClass,
23 LPWNDCLASSEXW lpwcx,
24 BOOL unicode)
25 {
26 LPWSTR str;
27 UNICODE_STRING str2, str3;
28 WNDCLASSEXW w;
29 BOOL retval;
30 NTSTATUS Status;
31
32 if ( !lpszClass || !lpwcx )
33 {
34 SetLastError(ERROR_INVALID_PARAMETER);
35 return FALSE;
36 }
37
38 if(IS_ATOM(lpszClass))
39 str = (LPWSTR)lpszClass;
40 else
41 {
42 extern BOOL ControlsInitialized;
43
44 if (unicode)
45 {
46 str = HEAP_strdupW ( lpszClass, wcslen(lpszClass) );
47
48 if ( !str )
49 {
50 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
51 return FALSE;
52 }
53 }
54
55 else
56 {
57 Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL);
58
59 if (! NT_SUCCESS(Status))
60 {
61 SetLastError(RtlNtStatusToDosError(Status));
62 return FALSE;
63 }
64 }
65
66 /* Register built-in controls if not already done */
67 if ( !ControlsInitialized )
68 {
69 ControlsInitialized = ControlsInit(str);
70 }
71 }
72
73 str2.Length = str3.Length = 0;
74 str2.MaximumLength = str3.MaximumLength = 255;
75 str2.Buffer = (PWSTR)HEAP_alloc ( str2.MaximumLength * sizeof(WCHAR) );
76 if ( !str2.Buffer )
77 {
78 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
79 if ( !IS_ATOM(str) )
80 HEAP_free ( str );
81 return FALSE;
82 }
83
84 str3.Buffer = (PWSTR)HEAP_alloc ( str3.MaximumLength * sizeof(WCHAR) );
85 if ( !str3.Buffer )
86 {
87 SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY));
88 HEAP_free ( str2.Buffer );
89 if ( !IS_ATOM(str) )
90 HEAP_free ( str );
91 return FALSE;
92 }
93
94 w.lpszMenuName = (LPCWSTR)&str2;
95 w.lpszClassName = (LPCWSTR)&str3;
96 retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0);
97 if ( !IS_ATOM(str) )
98 HEAP_free(str);
99
100 RtlCopyMemory ( lpwcx, &w, sizeof(WNDCLASSEXW) );
101
102 if ( !IS_INTRESOURCE(w.lpszMenuName) && w.lpszMenuName )
103 {
104 if (unicode)
105 lpwcx->lpszMenuName = heap_string_poolW ( str2.Buffer, str2.Length );
106 else
107 ((LPWNDCLASSEXA) lpwcx)->lpszMenuName = heap_string_poolA ( str2.Buffer, str2.Length );
108 }
109
110 if ( !IS_ATOM(w.lpszClassName) && w.lpszClassName )
111 {
112 if (unicode)
113 lpwcx->lpszClassName = heap_string_poolW ( str3.Buffer, str3.Length );
114 else
115 ((LPWNDCLASSEXA) lpwcx)->lpszClassName = heap_string_poolA ( str3.Buffer, str3.Length );
116 }
117
118 HEAP_free ( str2.Buffer );
119 HEAP_free ( str3.Buffer );
120
121 return retval;
122 }
123
124
125 /*
126 * @implemented
127 */
128 BOOL
129 STDCALL
130 GetClassInfoExA(
131 HINSTANCE hinst,
132 LPCSTR lpszClass,
133 LPWNDCLASSEXA lpwcx)
134 {
135 return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE);
136 }
137
138
139 /*
140 * @implemented
141 */
142 BOOL
143 STDCALL
144 GetClassInfoExW(
145 HINSTANCE hinst,
146 LPCWSTR lpszClass,
147 LPWNDCLASSEXW lpwcx)
148 {
149 return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE);
150 }
151
152
153 /*
154 * @implemented
155 */
156 BOOL
157 STDCALL
158 GetClassInfoA(
159 HINSTANCE hInstance,
160 LPCSTR lpClassName,
161 LPWNDCLASSA lpWndClass)
162 {
163 WNDCLASSEXA w;
164 BOOL retval;
165
166 if ( !lpClassName || !lpWndClass )
167 {
168 SetLastError(ERROR_INVALID_PARAMETER);
169 return FALSE;
170 }
171
172 retval = GetClassInfoExA(hInstance,lpClassName,&w);
173 if (retval)
174 {
175 RtlCopyMemory ( lpWndClass, &w.style, sizeof(WNDCLASSA) );
176 }
177 return retval;
178 }
179
180 /*
181 * @implemented
182 */
183 BOOL
184 STDCALL
185 GetClassInfoW(
186 HINSTANCE hInstance,
187 LPCWSTR lpClassName,
188 LPWNDCLASSW lpWndClass)
189 {
190 WNDCLASSEXW w;
191 BOOL retval;
192
193 if(!lpClassName || !lpWndClass)
194 {
195 SetLastError(ERROR_INVALID_PARAMETER);
196 return FALSE;
197 }
198
199 retval = GetClassInfoExW(hInstance,lpClassName,&w);
200 RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
201 return retval;
202 }
203
204
205 /*
206 * @implemented
207 */
208 DWORD STDCALL
209 GetClassLongA(HWND hWnd, int nIndex)
210 {
211 switch (nIndex)
212 {
213 case GCL_HBRBACKGROUND:
214 {
215 DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
216 if (hBrush != 0 && hBrush < 0x4000)
217 hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
218 return hBrush;
219 }
220
221 case GCL_MENUNAME:
222 {
223 PUNICODE_STRING Name;
224 Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, TRUE);
225 if (IS_INTRESOURCE(Name))
226 return (DWORD)Name;
227 else
228 return (DWORD)heap_string_poolA(Name->Buffer, Name->Length);
229 }
230
231 default:
232 return NtUserGetClassLong(hWnd, nIndex, TRUE);
233 }
234 }
235
236 /*
237 * @implemented
238 */
239 DWORD STDCALL
240 GetClassLongW ( HWND hWnd, int nIndex )
241 {
242 switch (nIndex)
243 {
244 case GCL_HBRBACKGROUND:
245 {
246 DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
247 if (hBrush != 0 && hBrush < 0x4000)
248 hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
249 return hBrush;
250 }
251
252 case GCL_MENUNAME:
253 {
254 PUNICODE_STRING Name;
255 Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, FALSE);
256 if (IS_INTRESOURCE(Name))
257 return (DWORD)Name;
258 else
259 return (DWORD)heap_string_poolW(Name->Buffer, Name->Length);
260 }
261
262 default:
263 return NtUserGetClassLong(hWnd, nIndex, FALSE);
264 }
265 }
266
267
268 /*
269 * @implemented
270 */
271 int STDCALL
272 GetClassNameA(
273 HWND hWnd,
274 LPSTR lpClassName,
275 int nMaxCount)
276 {
277 int result;
278 LPWSTR ClassNameW;
279 NTSTATUS Status;
280
281 if(!lpClassName)
282 return 0;
283
284 ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) );
285
286 result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
287
288 Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result );
289
290 HEAP_free ( ClassNameW );
291
292 if ( !NT_SUCCESS(Status) )
293 return 0;
294
295 return result;
296 }
297
298
299 /*
300 * @implemented
301 */
302 int
303 STDCALL
304 GetClassNameW(
305 HWND hWnd,
306 LPWSTR lpClassName,
307 int nMaxCount)
308 {
309 return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
310 }
311
312
313 /*
314 * @implemented
315 */
316 WORD
317 STDCALL
318 GetClassWord(
319 HWND hWnd,
320 int nIndex)
321 /*
322 * NOTE: Obsoleted in 32-bit windows
323 */
324 {
325 if ((nIndex < 0) && (nIndex != GCW_ATOM))
326 return 0;
327
328 return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
329 }
330
331
332 /*
333 * @implemented
334 */
335 LONG
336 STDCALL
337 GetWindowLongA ( HWND hWnd, int nIndex )
338 {
339 return NtUserGetWindowLong(hWnd, nIndex, TRUE);
340 }
341
342
343 /*
344 * @implemented
345 */
346 LONG
347 STDCALL
348 GetWindowLongW(HWND hWnd, int nIndex)
349 {
350 return NtUserGetWindowLong(hWnd, nIndex, FALSE);
351 }
352
353 /*
354 * @implemented
355 */
356 WORD
357 STDCALL
358 GetWindowWord(HWND hWnd, int nIndex)
359 {
360 return (WORD)NtUserGetWindowLong(hWnd, nIndex, TRUE);
361 }
362
363 /*
364 * @implemented
365 */
366 WORD
367 STDCALL
368 SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
369 {
370 return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
371 }
372
373 /*
374 * @implemented
375 */
376 UINT
377 STDCALL
378 RealGetWindowClassW(
379 HWND hwnd,
380 LPWSTR pszType,
381 UINT cchType)
382 {
383 /* FIXME: Implement correct functionality of RealGetWindowClass */
384 return GetClassNameW(hwnd,pszType,cchType);
385 }
386
387
388 /*
389 * @implemented
390 */
391 UINT
392 STDCALL
393 RealGetWindowClassA(
394 HWND hwnd,
395 LPSTR pszType,
396 UINT cchType)
397 {
398 /* FIXME: Implement correct functionality of RealGetWindowClass */
399 return GetClassNameA(hwnd,pszType,cchType);
400 }
401
402 /*
403 * @implemented
404 */
405 ATOM STDCALL
406 RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
407 {
408 RTL_ATOM Atom;
409 WNDCLASSEXA WndClass;
410 UNICODE_STRING ClassName;
411 UNICODE_STRING MenuName;
412
413 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
414 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
415 lpwcx->lpszClassName == NULL)
416 {
417 SetLastError(ERROR_INVALID_PARAMETER);
418 return 0;
419 }
420
421 /*
422 * On real Windows this looks more like:
423 * if (lpwcx->hInstance == User32Instance &&
424 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
425 * But since I have no idea what the magic field in the
426 * TEB structure means, I rather decided to omit that.
427 * -- Filip Navara
428 */
429 if (lpwcx->hInstance == User32Instance)
430 {
431 SetLastError(ERROR_INVALID_PARAMETER);
432 return 0;
433 }
434
435 /* Yes, this is correct. We should modify the passed structure. */
436 if (lpwcx->hInstance == NULL)
437 ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
438
439 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
440
441 if (IS_ATOM(lpwcx->lpszMenuName) || lpwcx->lpszMenuName == 0)
442 {
443 MenuName.Length =
444 MenuName.MaximumLength = 0;
445 MenuName.Buffer = (LPWSTR)lpwcx->lpszMenuName;
446 } else
447 {
448 RtlCreateUnicodeStringFromAsciiz(&MenuName, lpwcx->lpszMenuName);
449 }
450
451 if (IS_ATOM(lpwcx->lpszClassName))
452 {
453 ClassName.Length =
454 ClassName.MaximumLength = 0;
455 ClassName.Buffer = (LPWSTR)lpwcx->lpszClassName;
456 } else
457 {
458 RtlCreateUnicodeStringFromAsciiz(&ClassName, lpwcx->lpszClassName);
459 }
460
461 Atom = NtUserRegisterClassExWOW(
462 (WNDCLASSEXW*)&WndClass,
463 &ClassName,
464 &ClassName,
465 &MenuName,
466 NULL,
467 REGISTERCLASS_ANSI,
468 0);
469
470 if (!IS_ATOM(lpwcx->lpszMenuName))
471 RtlFreeUnicodeString(&MenuName);
472 if (!IS_ATOM(lpwcx->lpszClassName))
473 RtlFreeUnicodeString(&ClassName);
474
475 return (ATOM)Atom;
476 }
477
478 /*
479 * @implemented
480 */
481 ATOM STDCALL
482 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
483 {
484 WNDCLASSEXW WndClass;
485 UNICODE_STRING ClassName;
486 UNICODE_STRING MenuName;
487
488 if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
489 lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
490 lpwcx->lpszClassName == NULL)
491 {
492 SetLastError(ERROR_INVALID_PARAMETER);
493 return 0;
494 }
495
496 /*
497 * On real Windows this looks more like:
498 * if (lpwcx->hInstance == User32Instance &&
499 * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
500 * But since I have no idea what the magic field in the
501 * TEB structure means, I rather decided to omit that.
502 * -- Filip Navara
503 */
504 if (lpwcx->hInstance == User32Instance)
505 {
506 SetLastError(ERROR_INVALID_PARAMETER);
507 return 0;
508 }
509
510 /* Yes, this is correct. We should modify the passed structure. */
511 if (lpwcx->hInstance == NULL)
512 ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
513
514 RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
515
516 if (IS_ATOM(lpwcx->lpszMenuName))
517 {
518 MenuName.Length =
519 MenuName.MaximumLength = 0;
520 MenuName.Buffer = (LPWSTR)lpwcx->lpszMenuName;
521 } else
522 {
523 RtlInitUnicodeString(&MenuName, lpwcx->lpszMenuName);
524 }
525
526 if (IS_ATOM(lpwcx->lpszClassName))
527 {
528 ClassName.Length =
529 ClassName.MaximumLength = 0;
530 ClassName.Buffer = (LPWSTR)lpwcx->lpszClassName;
531 } else
532 {
533 RtlInitUnicodeString(&ClassName, lpwcx->lpszClassName);
534 }
535
536 return (ATOM)NtUserRegisterClassExWOW(
537 &WndClass,
538 &ClassName,
539 &ClassName,
540 &MenuName,
541 NULL,
542 0,
543 0);
544 }
545
546 /*
547 * @implemented
548 */
549 ATOM STDCALL
550 RegisterClassA(CONST WNDCLASSA *lpWndClass)
551 {
552 WNDCLASSEXA Class;
553
554 if (lpWndClass == NULL)
555 return 0;
556
557 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
558 Class.cbSize = sizeof(WNDCLASSEXA);
559 Class.hIconSm = NULL;
560
561 return RegisterClassExA(&Class);
562 }
563
564 /*
565 * @implemented
566 */
567 ATOM STDCALL
568 RegisterClassW(CONST WNDCLASSW *lpWndClass)
569 {
570 WNDCLASSEXW Class;
571
572 if (lpWndClass == NULL)
573 return 0;
574
575 RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
576 Class.cbSize = sizeof(WNDCLASSEXW);
577 Class.hIconSm = NULL;
578
579 return RegisterClassExW(&Class);
580 }
581
582 /*
583 * @implemented
584 */
585 DWORD
586 STDCALL
587 SetClassLongA (
588 HWND hWnd,
589 int nIndex,
590 LONG dwNewLong)
591 {
592 UNICODE_STRING str2buf;
593 PUNICODE_STRING str;
594 PUNICODE_STRING str2 = &str2buf;
595
596 if ( nIndex != GCL_MENUNAME )
597 {
598 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
599 }
600 if ( IS_INTRESOURCE(dwNewLong) )
601 {
602 str2 = (PUNICODE_STRING)dwNewLong;
603 }
604 else
605 {
606 RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong );
607 }
608
609 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
610
611 if ( !IS_INTRESOURCE(dwNewLong) )
612 {
613 RtlFreeUnicodeString ( str2 );
614 }
615 if ( IS_INTRESOURCE(str) )
616 {
617 return (DWORD)str;
618 }
619 else
620 {
621 return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
622 }
623 }
624
625
626 /*
627 * @implemented
628 */
629 DWORD
630 STDCALL
631 SetClassLongW(
632 HWND hWnd,
633 int nIndex,
634 LONG dwNewLong)
635 {
636 UNICODE_STRING str2buf;
637 PUNICODE_STRING str;
638 PUNICODE_STRING str2 = &str2buf;
639
640 if (nIndex != GCL_MENUNAME )
641 {
642 return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
643 }
644 if ( IS_INTRESOURCE(dwNewLong) )
645 {
646 str2 = (PUNICODE_STRING)dwNewLong;
647 }
648 else
649 {
650 RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong );
651 }
652
653 str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
654
655 if ( !IS_INTRESOURCE(dwNewLong) )
656 {
657 RtlFreeUnicodeString(str2);
658 }
659 if ( IS_INTRESOURCE(str) )
660 {
661 return (DWORD)str;
662 }
663 else
664 {
665 return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
666 }
667 }
668
669
670 /*
671 * @implemented
672 */
673 WORD
674 STDCALL
675 SetClassWord(
676 HWND hWnd,
677 int nIndex,
678 WORD wNewWord)
679 /*
680 * NOTE: Obsoleted in 32-bit windows
681 */
682 {
683 if ((nIndex < 0) && (nIndex != GCW_ATOM))
684 return 0;
685
686 return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
687 }
688
689
690 /*
691 * @implemented
692 */
693 LONG
694 STDCALL
695 SetWindowLongA(
696 HWND hWnd,
697 int nIndex,
698 LONG dwNewLong)
699 {
700 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
701 }
702
703
704 /*
705 * @implemented
706 */
707 LONG
708 STDCALL
709 SetWindowLongW(
710 HWND hWnd,
711 int nIndex,
712 LONG dwNewLong)
713 {
714 return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
715 }
716
717
718 /*
719 * @implemented
720 */
721 BOOL
722 STDCALL
723 UnregisterClassA(
724 LPCSTR lpClassName,
725 HINSTANCE hInstance)
726 {
727 LPWSTR ClassName;
728 NTSTATUS Status;
729 BOOL Result;
730
731 if(!IS_ATOM(lpClassName))
732 {
733 Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
734 if(!NT_SUCCESS(Status))
735 {
736 SetLastError(RtlNtStatusToDosError(Status));
737 return FALSE;
738 }
739 }
740 else
741 ClassName = (LPWSTR)lpClassName;
742
743 Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
744
745 if(ClassName && !IS_ATOM(lpClassName))
746 HEAP_free(ClassName);
747
748 return Result;
749 }
750
751
752 /*
753 * @implemented
754 */
755 BOOL
756 STDCALL
757 UnregisterClassW(
758 LPCWSTR lpClassName,
759 HINSTANCE hInstance)
760 {
761 return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
762 }
763
764 /* EOF */