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