* added _DISABLE_TIDENTS macro to disable any ANSI/UNICODE ambiguous elements from...
[reactos.git] / reactos / subsys / win32k / ntuser / class.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: class.c,v 1.24 2003/08/07 04:03:25 royce Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * REVISION HISTORY:
27 * 06-06-2001 CSH Created
28 */
29 /* INCLUDES ******************************************************************/
30
31 #include <ddk/ntddk.h>
32 #include <win32k/win32k.h>
33 #include <napi/win32.h>
34 #include <include/class.h>
35 #include <include/error.h>
36 #include <include/winsta.h>
37 #include <include/object.h>
38 #include <include/guicheck.h>
39 #include <include/window.h>
40
41 #define NDEBUG
42 #include <debug.h>
43
44 /* FUNCTIONS *****************************************************************/
45
46 NTSTATUS FASTCALL
47 InitClassImpl(VOID)
48 {
49 return(STATUS_SUCCESS);
50 }
51
52 NTSTATUS FASTCALL
53 CleanupClassImpl(VOID)
54 {
55 return(STATUS_SUCCESS);
56 }
57
58
59 NTSTATUS FASTCALL
60 ClassReferenceClassByAtom(PWNDCLASS_OBJECT* Class,
61 RTL_ATOM Atom)
62 {
63 PWNDCLASS_OBJECT Current;
64 PLIST_ENTRY CurrentEntry;
65 PW32PROCESS Process = PsGetWin32Process();
66
67 ExAcquireFastMutexUnsafe (&Process->ClassListLock);
68 CurrentEntry = Process->ClassListHead.Flink;
69 while (CurrentEntry != &Process->ClassListHead)
70 {
71 Current = CONTAINING_RECORD(CurrentEntry, WNDCLASS_OBJECT, ListEntry);
72
73 if (Current->lpszClassName == (PUNICODE_STRING)(ULONG)Atom)
74 {
75 *Class = Current;
76 ObmReferenceObject(Current);
77 ExReleaseFastMutexUnsafe (&Process->ClassListLock);
78 return(STATUS_SUCCESS);
79 }
80
81 CurrentEntry = CurrentEntry->Flink;
82 }
83 ExReleaseFastMutexUnsafe (&Process->ClassListLock);
84
85 return(STATUS_NOT_FOUND);
86 }
87
88 NTSTATUS STDCALL
89 ClassReferenceClassByName(PWNDCLASS_OBJECT *Class,
90 PWSTR ClassName)
91 {
92 PWINSTATION_OBJECT WinStaObject;
93 NTSTATUS Status;
94 RTL_ATOM ClassAtom;
95
96 if (!ClassName)
97 {
98 return(STATUS_INVALID_PARAMETER);
99 }
100
101 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
102 KernelMode,
103 0,
104 &WinStaObject);
105 if (!NT_SUCCESS(Status))
106 {
107 DPRINT("Validation of window station handle (0x%X) failed\n",
108 PROCESS_WINDOW_STATION());
109 return(STATUS_UNSUCCESSFUL);
110 }
111
112 Status = RtlLookupAtomInAtomTable(WinStaObject->AtomTable,
113 ClassName,
114 &ClassAtom);
115
116 if (!NT_SUCCESS(Status))
117 {
118 ObDereferenceObject(WinStaObject);
119 return(Status);
120 }
121 Status = ClassReferenceClassByAtom(Class,
122 ClassAtom);
123
124 ObDereferenceObject(WinStaObject);
125 return(Status);
126 }
127
128 NTSTATUS FASTCALL
129 ClassReferenceClassByNameOrAtom(PWNDCLASS_OBJECT *Class,
130 LPWSTR ClassNameOrAtom)
131 {
132 NTSTATUS Status;
133
134 if (IS_ATOM(ClassNameOrAtom))
135 {
136 Status = ClassReferenceClassByAtom(Class,
137 (RTL_ATOM)((ULONG_PTR)ClassNameOrAtom));
138 }
139 else
140 {
141 Status = ClassReferenceClassByName(Class,
142 ClassNameOrAtom);
143 }
144
145 if (!NT_SUCCESS(Status))
146 {
147 SetLastNtError(Status);
148 }
149
150 return(Status);
151 }
152
153 DWORD STDCALL
154 NtUserGetClassInfo(IN LPWSTR ClassName,
155 IN ULONG InfoClass,
156 OUT PVOID Info,
157 IN ULONG InfoLength,
158 OUT PULONG ReturnedLength)
159 {
160 UNIMPLEMENTED;
161
162 return(0);
163 }
164
165 ULONG FASTCALL
166 W32kGetClassName(struct _WINDOW_OBJECT *WindowObject,
167 LPWSTR lpClassName,
168 int nMaxCount)
169 {
170 int length;
171 LPCWSTR name;
172 if (IS_ATOM(WindowObject->Class->lpszClassName))
173 {
174 /* FIXME find the string from the atom */
175 name = L"\0";
176 length = wcslen(name);
177 }
178 else
179 {
180 name = WindowObject->Class->lpszClassName->Buffer;
181 length = WindowObject->Class->lpszClassName->Length / sizeof(WCHAR);
182 }
183 if (length > nMaxCount)
184 {
185 length = nMaxCount;
186 }
187 *(lpClassName+length) = 0;
188 wcsncpy(lpClassName,name,length);
189 return length;
190 }
191
192 DWORD STDCALL
193 NtUserGetClassName(HWND hWnd,
194 LPWSTR lpClassName,
195 int nMaxCount)
196 {
197 PWINDOW_OBJECT WindowObject;
198 LONG Ret;
199
200 WindowObject = W32kGetWindowObject(hWnd);
201 if (WindowObject == NULL)
202 {
203 return(0);
204 }
205 Ret = W32kGetClassName(WindowObject, lpClassName, nMaxCount);
206 W32kReleaseWindowObject(WindowObject);
207 return(Ret);
208 }
209
210 DWORD STDCALL
211 NtUserGetWOWClass(DWORD Unknown0,
212 DWORD Unknown1)
213 {
214 UNIMPLEMENTED;
215
216 return(0);
217 }
218
219 PWNDCLASS_OBJECT FASTCALL
220 W32kCreateClass(CONST WNDCLASSEXW *lpwcx,
221 BOOL bUnicodeClass,
222 RTL_ATOM Atom)
223 {
224 PWNDCLASS_OBJECT ClassObject;
225 WORD objectSize;
226 objectSize = sizeof(WNDCLASS_OBJECT);
227 ClassObject = ObmCreateObject(NULL, NULL, otClass, objectSize);
228 if (ClassObject == 0)
229 {
230 return(NULL);
231 }
232
233 ClassObject->cbSize = lpwcx->cbSize;
234 ClassObject->style = lpwcx->style;
235 ClassObject->cbClsExtra = lpwcx->cbClsExtra;
236 ClassObject->cbWndExtra = lpwcx->cbWndExtra;
237 ClassObject->hInstance = lpwcx->hInstance;
238 ClassObject->hIcon = lpwcx->hIcon;
239 ClassObject->hCursor = lpwcx->hCursor;
240 ClassObject->hbrBackground = lpwcx->hbrBackground;
241 ClassObject->Unicode = bUnicodeClass;
242 ClassObject->hIconSm = lpwcx->hIconSm;
243 ClassObject->lpszClassName = (PUNICODE_STRING)(ULONG)Atom;
244 if (bUnicodeClass)
245 {
246 ClassObject->lpfnWndProcW = lpwcx->lpfnWndProc;
247 ClassObject->lpfnWndProcA = (WNDPROC)0xCCCCCCCC;
248 }
249 else
250 {
251 ClassObject->lpfnWndProcA = lpwcx->lpfnWndProc;
252 ClassObject->lpfnWndProcW = (WNDPROC)0xCCCCCCCC;
253 }
254 if (HIWORD(lpwcx->lpszMenuName) == 0)
255 {
256 ClassObject->lpszMenuName = (PUNICODE_STRING)lpwcx->lpszMenuName;
257 }
258 else
259 {
260 RtlCreateUnicodeString(ClassObject->lpszMenuName,(LPWSTR)lpwcx->lpszMenuName);
261 }
262 return(ClassObject);
263 }
264
265 RTL_ATOM STDCALL
266 NtUserRegisterClassExWOW(
267 CONST WNDCLASSEXW *lpwcx,
268 BOOL bUnicodeClass,
269 DWORD Unknown3,
270 DWORD Unknown4,
271 DWORD Unknown5)
272
273 /*
274 * FUNCTION:
275 * Registers a new class with the window manager
276 * ARGUMENTS:
277 * lpwcx = Win32 extended window class structure
278 * bUnicodeClass = Whether to send ANSI or unicode strings
279 * to window procedures
280 * RETURNS:
281 * Atom identifying the new class
282 */
283 {
284 PWINSTATION_OBJECT WinStaObject;
285 PWNDCLASS_OBJECT ClassObject;
286 NTSTATUS Status;
287 RTL_ATOM Atom;
288 DPRINT("About to open window station handle (0x%X)\n",
289 PROCESS_WINDOW_STATION());
290 Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(),
291 KernelMode,
292 0,
293 &WinStaObject);
294 if (!NT_SUCCESS(Status))
295 {
296 DPRINT("Validation of window station handle (0x%X) failed\n",
297 PROCESS_WINDOW_STATION());
298 return((RTL_ATOM)0);
299 }
300 if (!IS_ATOM(lpwcx->lpszClassName))
301 {
302 Status = RtlAddAtomToAtomTable(WinStaObject->AtomTable,
303 (LPWSTR)lpwcx->lpszClassName,
304 &Atom);
305 if (!NT_SUCCESS(Status))
306 {
307 ObDereferenceObject(WinStaObject);
308 DPRINT("Failed adding class name (%wS) to atom table\n",
309 lpwcx->lpszClassName);
310 SetLastNtError(Status);
311 return((RTL_ATOM)0);
312 }
313 }
314 else
315 {
316 Atom = (RTL_ATOM)(ULONG)lpwcx->lpszClassName;
317 }
318 ClassObject = W32kCreateClass(lpwcx, bUnicodeClass, Atom);
319 if (ClassObject == NULL)
320 {
321 if (!IS_ATOM(lpwcx->lpszClassName))
322 {
323 RtlDeleteAtomFromAtomTable(WinStaObject->AtomTable, Atom);
324 }
325 ObDereferenceObject(WinStaObject);
326 DPRINT("Failed creating window class object\n");
327 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
328 return((RTL_ATOM)0);
329 }
330 ExAcquireFastMutex(&PsGetWin32Process()->ClassListLock);
331 InsertTailList(&PsGetWin32Process()->ClassListHead, &ClassObject->ListEntry);
332 ExReleaseFastMutex(&PsGetWin32Process()->ClassListLock);
333 ObDereferenceObject(WinStaObject);
334 return(Atom);
335 }
336
337 ULONG FASTCALL
338 W32kGetClassLong(struct _WINDOW_OBJECT *WindowObject, ULONG Offset, BOOL Ansi)
339 {
340 LONG Ret;
341 switch (Offset)
342 {
343 case GCL_CBWNDEXTRA:
344 Ret = WindowObject->Class->cbWndExtra;
345 break;
346 case GCL_CBCLSEXTRA:
347 Ret = WindowObject->Class->cbClsExtra;
348 break;
349 case GCL_HBRBACKGROUND:
350 Ret = (ULONG)WindowObject->Class->hbrBackground;
351 break;
352 case GCL_HCURSOR:
353 Ret = (ULONG)WindowObject->Class->hCursor;
354 break;
355 case GCL_HICON:
356 Ret = (ULONG)WindowObject->Class->hIcon;
357 break;
358 case GCL_HICONSM:
359 Ret = (ULONG)WindowObject->Class->hIconSm;
360 break;
361 case GCL_HMODULE:
362 Ret = (ULONG)WindowObject->Class->hInstance;
363 break;
364 /*case GCL_MENUNAME:
365 if (Ansi)
366 {
367 Ret = (ULONG)WindowObject->Class->ClassA.lpszMenuName;
368 }
369 else
370 {
371 Ret = (ULONG)WindowObject->Class->ClassW.lpszMenuName;
372 }
373 break;*/
374 case GCL_STYLE:
375 Ret = WindowObject->Class->style;
376 break;
377 case GCL_WNDPROC:
378 if (WindowObject->Unicode)
379 {
380 Ret = (ULONG)WindowObject->Class->lpfnWndProcW;
381 }
382 else
383 {
384 Ret = (ULONG)WindowObject->Class->lpfnWndProcA;
385 }
386 break;
387 default:
388 Ret = 0;
389 break;
390 }
391 return(Ret);
392 }
393
394 DWORD STDCALL
395 NtUserGetClassLong(HWND hWnd, DWORD Offset, BOOL Ansi)
396 {
397 PWINDOW_OBJECT WindowObject;
398 LONG Ret;
399
400 WindowObject = W32kGetWindowObject(hWnd);
401 if (WindowObject == NULL)
402 {
403 return(0);
404 }
405 Ret = W32kGetClassLong(WindowObject, Offset, Ansi);
406 W32kReleaseWindowObject(WindowObject);
407 return(Ret);
408 }
409
410 void FASTCALL
411 W32kSetClassLong(PWINDOW_OBJECT WindowObject, ULONG Offset, LONG dwNewLong, BOOL Ansi)
412 {
413 switch (Offset)
414 {
415 case GCL_CBWNDEXTRA:
416 WindowObject->Class->cbWndExtra = dwNewLong;
417 break;
418 case GCL_CBCLSEXTRA:
419 WindowObject->Class->cbClsExtra = dwNewLong;
420 break;
421 case GCL_HBRBACKGROUND:
422 WindowObject->Class->hbrBackground = (HBRUSH)dwNewLong;
423 break;
424 case GCL_HCURSOR:
425 WindowObject->Class->hCursor = (HCURSOR)dwNewLong;
426 break;
427 case GCL_HICON:
428 WindowObject->Class->hIcon = (HICON)dwNewLong;
429 break;
430 case GCL_HICONSM:
431 WindowObject->Class->hIconSm = (HICON)dwNewLong;
432 break;
433 case GCL_HMODULE:
434 WindowObject->Class->hInstance = (HINSTANCE)dwNewLong;
435 break;
436 /*case GCL_MENUNAME:
437 WindowObject->Class->Class.lpszMenuName = (LPCWSTR)dwNewLong;
438 break;*/
439 case GCL_STYLE:
440 WindowObject->Class->style = dwNewLong;
441 break;
442 /*case GCL_WNDPROC:
443 WindowObject->Class->Class.lpfnWndProc = (WNDPROC)dwNewLong;
444 break;*/
445 }
446 }
447
448 DWORD STDCALL
449 NtUserSetClassLong(HWND hWnd,
450 DWORD Offset,
451 LONG dwNewLong,
452 BOOL Ansi)
453 {
454 PWINDOW_OBJECT WindowObject;
455 LONG Ret;
456
457 WindowObject = W32kGetWindowObject(hWnd);
458 if (WindowObject == NULL)
459 {
460 return(0);
461 }
462 Ret = W32kGetClassLong(WindowObject, Offset, Ansi);
463 W32kSetClassLong(WindowObject, Offset, dwNewLong, Ansi);
464 W32kReleaseWindowObject(WindowObject);
465 return(Ret);
466 }
467
468 DWORD STDCALL
469 NtUserSetClassWord(DWORD Unknown0,
470 DWORD Unknown1,
471 DWORD Unknown2)
472 {
473 UNIMPLEMENTED;
474
475 return(0);
476 }
477
478 DWORD STDCALL
479 NtUserUnregisterClass(DWORD Unknown0,
480 DWORD Unknown1,
481 DWORD Unknown2)
482 {
483 UNIMPLEMENTED;
484
485 return(0);
486 }
487
488 /* EOF */