Merge trunk r45185
[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 PTHREADINFO
108 GetW32ThreadInfo(VOID)
109 {
110 PTHREADINFO ti;
111
112 ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
113 if (ti == NULL)
114 {
115 /* create the THREADINFO structure */
116 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
117 ti = (PTHREADINFO)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 PTHREADINFO ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
254 if (ti == NULL)
255 {
256 if(bConvert)
257 {
258 NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
259 if ((PTHREADINFO)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 == (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
274 return TRUE;
275 else
276 return (NtUserQueryWindow(Wnd->head.h, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
277 (DWORD_PTR)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_PTR)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_PTR)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 FALSE */
326 TRUE, /* VALIDATE_TYPE_MENU FALSE */
327 TRUE, /* VALIDATE_TYPE_CURSOR */
328 TRUE, /* VALIDATE_TYPE_MWPOS */
329 TRUE, /* VALIDATE_TYPE_HOOK FALSE */
330 FALSE, /* (not used) */
331 TRUE, /* VALIDATE_TYPE_CALLPROC FALSE */
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) ||
361 (pEntry->type != uType) ||
362 !pEntry->ptr ||
363 (pEntry->flags & HANDLEENTRY_INDESTROY) )
364 {
365 switch ( uType )
366 { // Test (with wine too) confirms these results!
367 case VALIDATE_TYPE_WIN:
368 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
369 break;
370 case VALIDATE_TYPE_MENU:
371 SetLastError(ERROR_INVALID_MENU_HANDLE);
372 break;
373 case VALIDATE_TYPE_CURSOR:
374 SetLastError(ERROR_INVALID_CURSOR_HANDLE);
375 break;
376 case VALIDATE_TYPE_MWPOS:
377 SetLastError(ERROR_INVALID_DWP_HANDLE);
378 break;
379 case VALIDATE_TYPE_HOOK:
380 SetLastError(ERROR_INVALID_HOOK_HANDLE);
381 break;
382 case VALIDATE_TYPE_ACCEL:
383 SetLastError(ERROR_INVALID_ACCEL_HANDLE);
384 break;
385 default:
386 SetLastError(ERROR_INVALID_HANDLE);
387 break;
388 }
389 return NULL;
390 }
391
392 if (g_ObjectHeapTypeShared[uType])
393 ret = SharedPtrToUser(pEntry->ptr);
394 else
395 ret = DesktopPtrToUser(pEntry->ptr);
396
397 return ret;
398 }
399
400 //
401 // Validate Handle and return the pointer to the object.
402 //
403 PVOID
404 FASTCALL
405 ValidateHandleNoErr(HANDLE handle, UINT uType)
406 {
407 PVOID ret;
408 PUSER_HANDLE_ENTRY pEntry;
409
410 ASSERT(uType <= VALIDATE_TYPE_EVENT);
411
412 pEntry = GetUser32Handle(handle);
413
414 if (pEntry && uType == 0)
415 uType = pEntry->type;
416
417 // Must have an entry and must be the same type!
418 if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
419 return NULL;
420
421 if (g_ObjectHeapTypeShared[uType])
422 ret = SharedPtrToUser(pEntry->ptr);
423 else
424 ret = DesktopPtrToUser(pEntry->ptr);
425
426 return ret;
427 }
428
429 //
430 // Validate a callproc handle and return the pointer to the object.
431 //
432 PCALLPROCDATA
433 FASTCALL
434 ValidateCallProc(HANDLE hCallProc)
435 {
436 PUSER_HANDLE_ENTRY pEntry;
437
438 PCALLPROCDATA CallProc = ValidateHandle(hCallProc, VALIDATE_TYPE_CALLPROC);
439
440 pEntry = GetUser32Handle(hCallProc);
441
442 if (CallProc != NULL && pEntry->ppi == g_ppi)
443 return CallProc;
444
445 return NULL;
446 }
447
448 // HACK HACK HACK!
449 typedef struct _WNDX
450 {
451 THRDESKHEAD head;
452 PWND pWnd;
453 } WNDX, *PWNDX;
454
455 //
456 // Validate a window handle and return the pointer to the object.
457 //
458 PWND
459 FASTCALL
460 ValidateHwnd(HWND hwnd)
461 {
462 PWND Wnd;
463 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
464 ASSERT(ClientInfo != NULL);
465
466 /* See if the window is cached */
467 if (hwnd == ClientInfo->CallbackWnd.hWnd)
468 return ClientInfo->CallbackWnd.pvWnd;
469
470 Wnd = ValidateHandle((HANDLE)hwnd, VALIDATE_TYPE_WIN);
471 if (Wnd != NULL)
472 {
473 #if 0
474 return Wnd;
475 #else
476 /* HACK HACK HACK! This needs to be done until WINDOW_OBJECT is completely
477 superseded by the WINDOW structure. We *ASSUME* a pointer to the WINDOW
478 structure to be at the beginning of the WINDOW_OBJECT structure!!!
479
480 !!! REMOVE AS SOON AS WINDOW_OBJECT NO LONGER EXISTS !!!
481 */
482
483 if ( ((PWNDX)Wnd)->pWnd != NULL)
484 return DesktopPtrToUser( ((PWNDX)Wnd)->pWnd );
485 #endif
486 }
487
488 return NULL;
489 }
490
491 //
492 // Validate a window handle and return the pointer to the object.
493 //
494 PWND
495 FASTCALL
496 ValidateHwndNoErr(HWND hwnd)
497 {
498 PWND Wnd;
499 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
500 ASSERT(ClientInfo != NULL);
501
502 /* See if the window is cached */
503 if (hwnd == ClientInfo->CallbackWnd.hWnd)
504 return ClientInfo->CallbackWnd.pvWnd;
505
506 Wnd = ValidateHandleNoErr((HANDLE)hwnd, VALIDATE_TYPE_WIN);
507 if (Wnd != NULL)
508 {
509 #if 0
510 return Wnd;
511 #else
512 /* HACK HACK HACK! This needs to be done until WINDOW_OBJECT is completely
513 superseded by the WINDOW structure. We *ASSUME* a pointer to the WINDOW
514 structure to be at the beginning of the WINDOW_OBJECT structure!!!
515
516 !!! REMOVE AS SOON AS WINDOW_OBJECT NO LONGER EXISTS !!!
517 */
518
519 if ( ((PWNDX)Wnd)->pWnd != NULL)
520 return DesktopPtrToUser( ((PWNDX)Wnd)->pWnd );
521 #endif
522 }
523
524 return NULL;
525 }
526
527 PWND
528 FASTCALL
529 GetThreadDesktopWnd(VOID)
530 {
531 PWND Wnd = GetThreadDesktopInfo()->spwnd;
532 if (Wnd != NULL)
533 Wnd = DesktopPtrToUser(Wnd);
534 return Wnd;
535 }
536
537 //
538 // Validate a window handle and return the pointer to the object.
539 //
540 PWND
541 FASTCALL
542 ValidateHwndOrDesk(HWND hwnd)
543 {
544 if (hwnd == HWND_DESKTOP)
545 return GetThreadDesktopWnd();
546
547 return ValidateHwnd(hwnd);
548 }
549
550 /*
551 * @implemented
552 */
553 DWORD WINAPI WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR *MBString,LONG MBSize,BOOL Allocate)
554 {
555 DWORD Size;
556 if (UnicodeSize == -1)
557 {
558 UnicodeSize = wcslen(UnicodeString)+1;
559 }
560 if (MBSize == -1)
561 {
562 if (!Allocate)
563 {
564 return 0;
565 }
566 MBSize = UnicodeSize * 2;
567 }
568 if (Allocate)
569 {
570 LPSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, MBSize);
571 if (SafeString == NULL)
572 return 0;
573 *MBString = SafeString;
574 }
575 if (CodePage == 0)
576 {
577 RtlUnicodeToMultiByteN(*MBString,MBSize,&Size,UnicodeString,UnicodeSize);
578 }
579 else
580 {
581 WideCharToMultiByte(CodePage,0,UnicodeString,UnicodeSize,*MBString,MBSize,0,0);
582 }
583 return UnicodeSize;
584 }
585
586 /*
587 * @implemented
588 */
589 DWORD WINAPI MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR *UnicodeString,LONG UnicodeSize,BOOL Allocate)
590 {
591 DWORD Size;
592 if (MBSize == -1)
593 {
594 MBSize = strlen(MBString)+1;
595 }
596 if (UnicodeSize == -1)
597 {
598 if (!Allocate)
599 {
600 return 0;
601 }
602 UnicodeSize = MBSize;
603 }
604 if (Allocate)
605 {
606 LPWSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, UnicodeSize);
607 if (SafeString == NULL)
608 return 0;
609 *UnicodeString = SafeString;
610 }
611 UnicodeSize *= sizeof(WCHAR);
612 if (CodePage == 0)
613 {
614 RtlMultiByteToUnicodeN(*UnicodeString,UnicodeSize,&Size,MBString,MBSize);
615 }
616 else
617 {
618 Size = MultiByteToWideChar(CodePage,0,MBString,MBSize,*UnicodeString,UnicodeSize);
619 }
620 return Size;
621 }