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