update for HEAD-2003091401
[reactos.git] / 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 #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  * @implemented
376  */
377 WORD
378 STDCALL
379 GetClassWord(
380   HWND hWnd,
381   int nIndex)
382 /*
383  * NOTE: Obsoleted in 32-bit windows
384  */
385 {
386     if ((nIndex < 0) && (nIndex != GCW_ATOM))
387         return 0;
388
389     return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
390 }
391
392
393 /*
394  * @implemented
395  */
396 LONG
397 STDCALL
398 GetWindowLongA ( HWND hWnd, int nIndex )
399 {
400   return NtUserGetWindowLong(hWnd, nIndex, TRUE);
401 }
402
403
404 /*
405  * @implemented
406  */
407 LONG
408 STDCALL
409 GetWindowLongW(HWND hWnd, int nIndex)
410 {
411   return NtUserGetWindowLong(hWnd, nIndex, FALSE);
412 }
413
414 /*
415  * @implemented
416  */
417 WORD
418 STDCALL
419 GetWindowWord(HWND hWnd, int nIndex)
420 {
421   return (WORD)NtUserGetWindowLong(hWnd, nIndex,  TRUE);
422 }
423
424 /*
425  * @implemented
426  */
427 WORD
428 STDCALL
429 SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
430 {
431   return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
432 }
433
434 /*
435  * @implemented
436  */
437 UINT
438 STDCALL
439 RealGetWindowClassW(
440   HWND  hwnd,
441   LPWSTR pszType,
442   UINT  cchType)
443 {
444         /* FIXME: Implement correct functionality of RealGetWindowClass */
445         return GetClassNameW(hwnd,pszType,cchType);
446 }
447
448
449 /*
450  * @implemented
451  */
452 UINT
453 STDCALL
454 RealGetWindowClassA(
455   HWND  hwnd,
456   LPSTR pszType,
457   UINT  cchType)
458 {
459         /* FIXME: Implement correct functionality of RealGetWindowClass */
460         return GetClassNameA(hwnd,pszType,cchType);
461 }
462
463 /*
464  * @implemented
465  */
466 ATOM
467 STDCALL
468 RegisterClassA(CONST WNDCLASSA *lpWndClass)
469 {
470   WNDCLASSEXA Class;
471
472   if ( !lpWndClass )
473     return 0;
474
475   RtlCopyMemory ( &Class.style, lpWndClass, sizeof(WNDCLASSA) );
476
477   Class.cbSize = sizeof(WNDCLASSEXA);
478   Class.hIconSm = INVALID_HANDLE_VALUE;
479
480   return RegisterClassExA ( &Class );
481 }
482
483 /*
484  * @implemented
485  */
486 ATOM STDCALL
487 RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
488 {
489   RTL_ATOM Atom;
490   WNDCLASSEXW wndclass;
491   NTSTATUS Status;
492   LPWSTR ClassName = NULL;
493   LPWSTR MenuName = NULL;
494
495   if ( !lpwcx || (lpwcx->cbSize != sizeof(WNDCLASSEXA)) )
496     return 0;
497
498   if ( !lpwcx->lpszClassName )
499     return 0;
500
501   RtlCopyMemory ( &wndclass, lpwcx, sizeof(WNDCLASSEXW) );
502
503   if ( !IS_ATOM(lpwcx->lpszClassName) )
504   {
505     Status = HEAP_strdupAtoW ( &ClassName, (LPCSTR)lpwcx->lpszClassName, NULL );
506     if ( !NT_SUCCESS (Status) )
507     {
508       SetLastError (RtlNtStatusToDosError(Status));
509       return 0;
510     }
511     wndclass.lpszClassName = ClassName;
512   }
513
514   if ( !IS_INTRESOURCE(lpwcx->lpszMenuName) )
515   {
516     Status = HEAP_strdupAtoW ( &MenuName, (LPCSTR)lpwcx->lpszMenuName, NULL );
517     if ( !NT_SUCCESS (Status) )
518     {
519       if ( ClassName )
520         HEAP_free ( ClassName );
521       SetLastError (RtlNtStatusToDosError(Status));
522       return 0;
523     }
524     wndclass.lpszMenuName = MenuName;
525   }
526
527   Atom = NtUserRegisterClassExWOW ( &wndclass, FALSE, 0, 0, 0 );
528
529   /* free strings if neccessary */
530   if ( MenuName  ) HEAP_free ( MenuName );
531   if ( ClassName ) HEAP_free ( ClassName );
532
533   return (ATOM)Atom;
534 }
535
536
537
538 /*
539  * @implemented
540  */
541 ATOM STDCALL
542 RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
543 {
544   RTL_ATOM Atom;
545   HANDLE hHeap;
546   WNDCLASSEXW wndclass;
547   LPWSTR ClassName = NULL;
548   LPWSTR MenuName = NULL;
549
550   if ( !lpwcx || (lpwcx->cbSize != sizeof(WNDCLASSEXA)) )
551     return 0;
552
553   if ( !lpwcx->lpszClassName )
554     return 0;
555
556   hHeap = RtlGetProcessHeap();
557   RtlCopyMemory ( &wndclass, lpwcx, sizeof(WNDCLASSEXW) );
558
559   /* copy strings if needed */
560
561   if ( !IS_ATOM(lpwcx->lpszClassName) )
562   {
563     ClassName = HEAP_strdupW ( lpwcx->lpszClassName, lstrlenW(lpwcx->lpszClassName) );
564     if ( !ClassName )
565     {
566       SetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
567       return 0;
568     }
569     wndclass.lpszClassName = ClassName;
570   }
571
572   if ( !IS_INTRESOURCE(lpwcx->lpszMenuName) )
573   {
574     MenuName = HEAP_strdupW ( lpwcx->lpszMenuName, lstrlenW(lpwcx->lpszMenuName) );
575     if ( !MenuName )
576     {
577       if ( ClassName )
578         HEAP_free ( MenuName );
579       SetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
580       return 0;
581     }
582     wndclass.lpszMenuName = MenuName;
583   }
584
585   Atom = NtUserRegisterClassExWOW ( &wndclass, TRUE, 0, 0, 0 );
586
587   /* free strings if neccessary */
588   if ( MenuName  ) HEAP_free ( MenuName  );
589   if ( ClassName ) HEAP_free ( ClassName );
590
591   return (ATOM)Atom;
592 }
593
594 /*
595  * @implemented
596  */
597 ATOM STDCALL
598 RegisterClassW(CONST WNDCLASSW *lpWndClass)
599 {
600   WNDCLASSEXW Class;
601
602   if ( !lpWndClass )
603     return 0;
604
605   RtlCopyMemory ( &Class.style, lpWndClass, sizeof(WNDCLASSW) );
606
607   Class.cbSize = sizeof(WNDCLASSEXW);
608   Class.hIconSm = INVALID_HANDLE_VALUE;
609
610   return RegisterClassExW ( &Class );
611 }
612
613 /*
614  * @implemented
615  */
616 DWORD
617 STDCALL
618 SetClassLongA (
619   HWND hWnd,
620   int nIndex,
621   LONG dwNewLong)
622 {
623   PUNICODE_STRING str;
624   PUNICODE_STRING str2;
625
626   if ( nIndex != GCL_MENUNAME )
627   {
628     return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
629   }
630   if ( IS_INTRESOURCE(dwNewLong) )
631   {
632     str2 = (PUNICODE_STRING)dwNewLong;
633   }
634   else
635   {
636     RtlCreateUnicodeString ( str2, (LPWSTR)dwNewLong );
637   }
638
639   str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
640
641   if ( !IS_INTRESOURCE(dwNewLong) )
642   {
643     RtlFreeUnicodeString ( str2 );
644   }
645   if ( IS_INTRESOURCE(str) )
646   {
647     return (DWORD)str;
648   }
649   else
650   {
651     return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
652   }
653 }
654
655
656 /*
657  * @implemented
658  */
659 DWORD
660 STDCALL
661 SetClassLongW(
662   HWND hWnd,
663   int nIndex,
664   LONG dwNewLong)
665 {
666   PUNICODE_STRING str;
667   PUNICODE_STRING str2;
668
669   if (nIndex != GCL_MENUNAME )
670   {
671     return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
672   }
673   if ( IS_INTRESOURCE(dwNewLong) )
674   {
675     str2 = (PUNICODE_STRING)dwNewLong;
676   }
677   else
678   {
679     RtlCreateUnicodeStringFromAsciiz ( str2,(LPSTR)dwNewLong );
680   }
681
682   str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
683
684   if ( !IS_INTRESOURCE(dwNewLong) )
685   {
686     RtlFreeUnicodeString(str2);
687   }
688   if ( IS_INTRESOURCE(str) )
689   {
690     return (DWORD)str;
691   }
692   else
693   {
694     return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
695   }
696 }
697
698
699 /*
700  * @implemented
701  */
702 WORD
703 STDCALL
704 SetClassWord(
705   HWND hWnd,
706   int nIndex,
707   WORD wNewWord)
708 /*
709  * NOTE: Obsoleted in 32-bit windows
710  */
711 {
712     if ((nIndex < 0) && (nIndex != GCW_ATOM))
713         return 0;
714
715     return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
716 }
717
718
719 /*
720  * @implemented
721  */
722 LONG
723 STDCALL
724 SetWindowLongA(
725   HWND hWnd,
726   int nIndex,
727   LONG dwNewLong)
728 {
729   return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
730 }
731
732
733 /*
734  * @implemented
735  */
736 LONG
737 STDCALL
738 SetWindowLongW(
739   HWND hWnd,
740   int nIndex,
741   LONG dwNewLong)
742 {
743   return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
744 }
745
746
747 /*
748  * @unimplemented
749  */
750 WINBOOL
751 STDCALL
752 UnregisterClassA(
753   LPCSTR lpClassName,
754   HINSTANCE hInstance)
755 {
756   UNIMPLEMENTED;
757   return FALSE;
758 }
759
760
761 /*
762  * @unimplemented
763  */
764 WINBOOL
765 STDCALL
766 UnregisterClassW(
767   LPCWSTR lpClassName,
768   HINSTANCE hInstance)
769 {
770   UNIMPLEMENTED;
771   return FALSE;
772 }
773
774 /* EOF */