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