Sync to trunk head (r42241)
[reactos.git] / reactos / dll / win32 / user32 / misc / misc.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 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 /*
20 * PROJECT: ReactOS user32.dll
21 * FILE: lib/user32/misc/misc.c
22 * PURPOSE: Misc
23 * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 19-11-2003 Created
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <user32.h>
31
32 #include <wine/debug.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(user32);
35
36 /* FUNCTIONS *****************************************************************/
37
38 /*
39 * Private calls for CSRSS
40 */
41 VOID
42 WINAPI
43 PrivateCsrssManualGuiCheck(LONG Check)
44 {
45 NtUserCallOneParam(Check, ONEPARAM_ROUTINE_CSRSS_GUICHECK);
46 }
47
48 VOID
49 WINAPI
50 PrivateCsrssInitialized(VOID)
51 {
52 NtUserCallNoParam(NOPARAM_ROUTINE_CSRSS_INITIALIZED);
53 }
54
55
56 /*
57 * @implemented
58 */
59 BOOL
60 WINAPI
61 RegisterLogonProcess(DWORD dwProcessId, BOOL bRegister)
62 {
63 return NtUserCallTwoParam(dwProcessId,
64 (DWORD_PTR)bRegister,
65 TWOPARAM_ROUTINE_REGISTERLOGONPROC);
66 }
67
68 /*
69 * @implemented
70 */
71 BOOL
72 WINAPI
73 SetLogonNotifyWindow (HWND Wnd, HWINSTA WinSta)
74 {
75 /* Maybe we should call NtUserSetLogonNotifyWindow and let that one inform CSRSS??? */
76 CSR_API_MESSAGE Request;
77 ULONG CsrRequest;
78 NTSTATUS Status;
79
80 CsrRequest = MAKE_CSR_API(SET_LOGON_NOTIFY_WINDOW, CSR_GUI);
81 Request.Data.SetLogonNotifyWindowRequest.LogonNotifyWindow = Wnd;
82
83 Status = CsrClientCallServer(&Request,
84 NULL,
85 CsrRequest,
86 sizeof(CSR_API_MESSAGE));
87 if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
88 {
89 SetLastError(RtlNtStatusToDosError(Status));
90 return(FALSE);
91 }
92
93 return(TRUE);
94 }
95
96 /*
97 * @implemented
98 */
99 BOOL WINAPI
100 UpdatePerUserSystemParameters(
101 DWORD dwReserved,
102 BOOL bEnable)
103 {
104 return NtUserUpdatePerUserSystemParameters(dwReserved, bEnable);
105 }
106
107 PW32THREADINFO
108 GetW32ThreadInfo(VOID)
109 {
110 PW32THREADINFO ti;
111
112 ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo;
113 if (ti == NULL)
114 {
115 /* create the W32THREADINFO structure */
116 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
117 ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo;
118 }
119
120 return ti;
121 }
122
123
124 /*
125 * GetUserObjectSecurity
126 *
127 * Retrieves security information for user object specified
128 * with handle 'hObject'. Descriptor returned in self-relative
129 * format.
130 *
131 * Arguments:
132 * 1) hObject - handle to an object to retrieve information for
133 * 2) pSecurityInfo - type of information to retrieve
134 * 3) pSecurityDescriptor - buffer which receives descriptor
135 * 4) dwLength - size, in bytes, of buffer 'pSecurityDescriptor'
136 * 5) pdwLengthNeeded - reseives actual size of descriptor
137 *
138 * Return Vaules:
139 * TRUE on success
140 * FALSE on failure, call GetLastError() for more information
141 */
142 /*
143 * @implemented
144 */
145 BOOL
146 WINAPI
147 GetUserObjectSecurity(
148 IN HANDLE hObject,
149 IN PSECURITY_INFORMATION pSecurityInfo,
150 OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
151 IN DWORD dwLength,
152 OUT PDWORD pdwLengthNeeded
153 )
154 {
155 DWORD dwWin32Error;
156 NTSTATUS Status;
157
158
159 Status = NtQuerySecurityObject(
160 hObject, // Object Handle
161 *pSecurityInfo, // Security Information
162 pSecurityDescriptor,// Security Descriptor
163 dwLength, // Buffer Length
164 pdwLengthNeeded // Actual Length
165 );
166
167 if ( ! NT_SUCCESS( Status ) ) {
168 dwWin32Error = RtlNtStatusToDosError( Status );
169 NtCurrentTeb()->LastErrorValue = dwWin32Error;
170 return FALSE;
171 }
172
173 return TRUE;
174 }
175
176
177 /*
178 * SetUserObjectSecurity
179 *
180 * Sets new security descriptor to user object specified by
181 * handle 'hObject'. Descriptor must be in self-relative format.
182 *
183 * Arguments:
184 * 1) hObject - handle to an object to set information for
185 * 2) pSecurityInfo - type of information to apply
186 * 3) pSecurityDescriptor - buffer which descriptor to set
187 *
188 * Return Vaules:
189 * TRUE on success
190 * FALSE on failure, call GetLastError() for more information
191 */
192 /*
193 * @implemented
194 */
195 BOOL
196 WINAPI
197 SetUserObjectSecurity(
198 IN HANDLE hObject,
199 IN PSECURITY_INFORMATION pSecurityInfo,
200 IN PSECURITY_DESCRIPTOR pSecurityDescriptor
201 )
202 {
203 DWORD dwWin32Error;
204 NTSTATUS Status;
205
206
207 Status = NtSetSecurityObject(
208 hObject, // Object Handle
209 *pSecurityInfo, // Security Information
210 pSecurityDescriptor // Security Descriptor
211 );
212
213 if ( ! NT_SUCCESS( Status ) ) {
214 dwWin32Error = RtlNtStatusToDosError( Status );
215 NtCurrentTeb()->LastErrorValue = dwWin32Error;
216 return FALSE;
217 }
218
219 return TRUE;
220 }
221
222 /*
223 * @implemented
224 */
225 BOOL
226 WINAPI
227 EndTask(
228 HWND hWnd,
229 BOOL fShutDown,
230 BOOL fForce)
231 {
232 SendMessageW(hWnd, WM_CLOSE, 0, 0);
233
234 if (IsWindow(hWnd))
235 {
236 if (fForce)
237 return DestroyWindow(hWnd);
238 else
239 return FALSE;
240 }
241
242 return TRUE;
243 }
244
245 /*
246 * @implemented
247 */
248 BOOL
249 WINAPI
250 IsGUIThread(
251 BOOL bConvert)
252 {
253 PW32THREADINFO ti = (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo;
254 if (ti == NULL)
255 {
256 if(bConvert)
257 {
258 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
259 if ((PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo) return TRUE;
260 else
261 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
262 }
263 return FALSE;
264 }
265 else
266 return TRUE;
267 }
268
269 BOOL
270 FASTCALL
271 TestWindowProcess(PWND Wnd)
272 {
273 if (Wnd->head.pti == (PW32THREADINFO)NtCurrentTeb()->Win32ThreadInfo)
274 return TRUE;
275 else
276 return (NtUserQueryWindow(Wnd->head.h, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
277 (DWORD)NtCurrentTeb()->ClientId.UniqueProcess );
278 }
279
280 BOOL
281 FASTCALL
282 IsMetaFile(HDC hDc)
283 {
284 DWORD Type = GetObjectType((HGDIOBJ) hDc);
285 switch(Type)
286 {
287 case OBJ_METADC:
288 case OBJ_METAFILE:
289 case OBJ_ENHMETADC:
290 case OBJ_ENHMETAFILE:
291 return TRUE;
292 }
293 return FALSE;
294 }
295
296 PUSER_HANDLE_ENTRY
297 FASTCALL
298 GetUser32Handle(HANDLE handle)
299 {
300 INT Index;
301 USHORT generation;
302
303 Index = (((UINT)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
304
305 if (Index < 0 || Index >= gHandleTable->nb_handles)
306 return NULL;
307
308 if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr)
309 return NULL;
310
311 generation = (UINT)handle >> 16;
312
313 if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff)
314 return &gHandleEntries[Index];
315
316 return NULL;
317 }
318
319 /*
320 * Decide whether an object is located on the desktop or shared heap
321 */
322 static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_EVENT + 1] =
323 {
324 FALSE, /* VALIDATE_TYPE_FREE (not used) */
325 TRUE, /* VALIDATE_TYPE_WIN */ /* FIXME: FALSE once WINDOW_OBJECT is deleted! */
326 TRUE, /* VALIDATE_TYPE_MENU */
327 TRUE, /* VALIDATE_TYPE_CURSOR */
328 TRUE, /* VALIDATE_TYPE_MWPOS */
329 TRUE, /* VALIDATE_TYPE_HOOK */
330 FALSE, /* (not used) */
331 TRUE, /* VALIDATE_TYPE_CALLPROC */
332 TRUE, /* VALIDATE_TYPE_ACCEL */
333 FALSE, /* (not used) */
334 FALSE, /* (not used) */
335 FALSE, /* (not used) */
336 TRUE, /* VALIDATE_TYPE_MONITOR */
337 FALSE, /* (not used) */
338 FALSE, /* (not used) */
339 TRUE /* VALIDATE_TYPE_EVENT */
340 };
341
342 //
343 // Validate Handle and return the pointer to the object.
344 //
345 PVOID
346 FASTCALL
347 ValidateHandle(HANDLE handle, UINT uType)
348 {
349 PVOID ret;
350 PUSER_HANDLE_ENTRY pEntry;
351
352 ASSERT(uType <= VALIDATE_TYPE_EVENT);
353
354 pEntry = GetUser32Handle(handle);
355
356 if (pEntry && uType == 0)
357 uType = pEntry->type;
358
359 // Must have an entry and must be the same type!
360 if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
361 {
362 switch ( uType )
363 { // Test (with wine too) confirms these results!
364 case VALIDATE_TYPE_WIN:
365 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
366 break;
367 case VALIDATE_TYPE_MENU:
368 SetLastError(ERROR_INVALID_MENU_HANDLE);
369 break;
370 case VALIDATE_TYPE_CURSOR:
371 SetLastError(ERROR_INVALID_CURSOR_HANDLE);
372 break;
373 case VALIDATE_TYPE_MWPOS:
374 SetLastError(ERROR_INVALID_DWP_HANDLE);
375 break;
376 case VALIDATE_TYPE_HOOK:
377 SetLastError(ERROR_INVALID_HOOK_HANDLE);
378 break;
379 case VALIDATE_TYPE_ACCEL:
380 SetLastError(ERROR_INVALID_ACCEL_HANDLE);
381 break;
382 default:
383 SetLastError(ERROR_INVALID_HANDLE);
384 break;
385 }
386 return NULL;
387 }
388
389 if (g_ObjectHeapTypeShared[uType])
390 ret = SharedPtrToUser(pEntry->ptr);
391 else
392 ret = DesktopPtrToUser(pEntry->ptr);
393
394 return ret;
395 }
396
397 //
398 // Validate Handle and return the pointer to the object.
399 //
400 PVOID
401 FASTCALL
402 ValidateHandleNoErr(HANDLE handle, UINT uType)
403 {
404 PVOID ret;
405 PUSER_HANDLE_ENTRY pEntry;
406
407 ASSERT(uType <= VALIDATE_TYPE_EVENT);
408
409 pEntry = GetUser32Handle(handle);
410
411 if (pEntry && uType == 0)
412 uType = pEntry->type;
413
414 // Must have an entry and must be the same type!
415 if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
416 return NULL;
417
418 if (g_ObjectHeapTypeShared[uType])
419 ret = SharedPtrToUser(pEntry->ptr);
420 else
421 ret = DesktopPtrToUser(pEntry->ptr);
422
423 return ret;
424 }
425
426 //
427 // Validate a callproc handle and return the pointer to the object.
428 //
429 PCALLPROCDATA
430 FASTCALL
431 ValidateCallProc(HANDLE hCallProc)
432 {
433 PUSER_HANDLE_ENTRY pEntry;
434
435 PCALLPROCDATA CallProc = ValidateHandle(hCallProc, VALIDATE_TYPE_CALLPROC);
436
437 pEntry = GetUser32Handle(hCallProc);
438
439 if (CallProc != NULL && pEntry->ppi == g_ppi)
440 return CallProc;
441
442 return NULL;
443 }
444
445 //
446 // Validate a window handle and return the pointer to the object.
447 //
448 PWND
449 FASTCALL
450 ValidateHwnd(HWND hwnd)
451 {
452 PWND Wnd;
453 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
454 ASSERT(ClientInfo != NULL);
455
456 /* See if the window is cached */
457 if (hwnd == ClientInfo->CallbackWnd.hWnd)
458 return ClientInfo->CallbackWnd.pvWnd;
459
460 Wnd = ValidateHandle((HANDLE)hwnd, VALIDATE_TYPE_WIN);
461 if (Wnd != NULL)
462 {
463 /* FIXME: Check if handle table entry is marked as deleting and
464 return NULL in this case! */
465
466 #if 0
467 return Wnd;
468 #else
469 /* HACK HACK HACK! This needs to be done until WINDOW_OBJECT is completely
470 superseded by the WINDOW structure. We *ASSUME* a pointer to the WINDOW
471 structure to be at the beginning of the WINDOW_OBJECT structure!!!
472
473 !!! REMOVE AS SOON AS WINDOW_OBJECT NO LONGER EXISTS !!!
474 */
475
476 if (*((PVOID*)Wnd) != NULL)
477 return DesktopPtrToUser(*((PVOID*)Wnd));
478 #endif
479 }
480
481 return NULL;
482 }
483
484 //
485 // Validate a window handle and return the pointer to the object.
486 //
487 PWND
488 FASTCALL
489 ValidateHwndNoErr(HWND hwnd)
490 {
491 PWND Wnd;
492 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
493 ASSERT(ClientInfo != NULL);
494
495 /* See if the window is cached */
496 if (hwnd == ClientInfo->CallbackWnd.hWnd)
497 return ClientInfo->CallbackWnd.pvWnd;
498
499 Wnd = ValidateHandleNoErr((HANDLE)hwnd, VALIDATE_TYPE_WIN);
500 if (Wnd != NULL)
501 {
502 /* FIXME: Check if handle table entry is marked as deleting and
503 return NULL in this case! */
504
505 #if 0
506 return Wnd;
507 #else
508 /* HACK HACK HACK! This needs to be done until WINDOW_OBJECT is completely
509 superseded by the WINDOW structure. We *ASSUME* a pointer to the WINDOW
510 structure to be at the beginning of the WINDOW_OBJECT structure!!!
511
512 !!! REMOVE AS SOON AS WINDOW_OBJECT NO LONGER EXISTS !!!
513 */
514
515 if (*((PVOID*)Wnd) != NULL)
516 return DesktopPtrToUser(*((PVOID*)Wnd));
517 #endif
518 }
519
520 return NULL;
521 }
522
523 PWND
524 FASTCALL
525 GetThreadDesktopWnd(VOID)
526 {
527 PWND Wnd = GetThreadDesktopInfo()->Wnd;
528 if (Wnd != NULL)
529 Wnd = DesktopPtrToUser(Wnd);
530 return Wnd;
531 }
532
533 //
534 // Validate a window handle and return the pointer to the object.
535 //
536 PWND
537 FASTCALL
538 ValidateHwndOrDesk(HWND hwnd)
539 {
540 if (hwnd == HWND_DESKTOP)
541 return GetThreadDesktopWnd();
542
543 return ValidateHwnd(hwnd);
544 }
545
546 /*
547 * @implemented
548 */
549 DWORD WINAPI WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR *MBString,LONG MBSize,BOOL Allocate)
550 {
551 DWORD Size;
552 if (UnicodeSize == -1)
553 {
554 UnicodeSize = wcslen(UnicodeString)+1;
555 }
556 if (MBSize == -1)
557 {
558 if (!Allocate)
559 {
560 return 0;
561 }
562 MBSize = UnicodeSize * 2;
563 }
564 if (Allocate)
565 {
566 LPSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, MBSize);
567 if (SafeString == NULL)
568 return 0;
569 *MBString = SafeString;
570 }
571 if (CodePage == 0)
572 {
573 RtlUnicodeToMultiByteN(*MBString,MBSize,&Size,UnicodeString,UnicodeSize);
574 }
575 else
576 {
577 WideCharToMultiByte(CodePage,0,UnicodeString,UnicodeSize,*MBString,MBSize,0,0);
578 }
579 return UnicodeSize;
580 }
581
582 /*
583 * @implemented
584 */
585 DWORD WINAPI MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR *UnicodeString,LONG UnicodeSize,BOOL Allocate)
586 {
587 DWORD Size;
588 if (MBSize == -1)
589 {
590 MBSize = strlen(MBString)+1;
591 }
592 if (UnicodeSize == -1)
593 {
594 if (!Allocate)
595 {
596 return 0;
597 }
598 UnicodeSize = MBSize;
599 }
600 if (Allocate)
601 {
602 LPWSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, UnicodeSize);
603 if (SafeString == NULL)
604 return 0;
605 *UnicodeString = SafeString;
606 }
607 UnicodeSize *= sizeof(WCHAR);
608 if (CodePage == 0)
609 {
610 RtlMultiByteToUnicodeN(*UnicodeString,UnicodeSize,&Size,MBString,MBSize);
611 }
612 else
613 {
614 Size = MultiByteToWideChar(CodePage,0,MBString,MBSize,*UnicodeString,UnicodeSize);
615 }
616 return Size;
617 }