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