a473e79e1ce7cf9ecbceabf14d3eff703fded1c6
[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 if (!handle) return NULL;
308
309 Index = (((UINT_PTR)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
310
311 if (Index < 0 || Index >= gHandleTable->nb_handles)
312 return NULL;
313
314 if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr)
315 return NULL;
316
317 generation = (UINT_PTR)handle >> 16;
318
319 if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff)
320 return &gHandleEntries[Index];
321
322 return NULL;
323 }
324
325 /*
326 * Decide whether an object is located on the desktop or shared heap
327 */
328 static const BOOL g_ObjectHeapTypeShared[otEvent + 1] =
329 {
330 FALSE, /* otFree (not used) */
331 FALSE, /* otWindow */
332 TRUE, /* otMenu FALSE */
333 TRUE, /* otCursorIcon */
334 TRUE, /* otSMWP */
335 FALSE, /* otHook */
336 FALSE, /* (not used) */
337 FALSE, /* otCallProc */
338 TRUE, /* otAccel */
339 FALSE, /* (not used) */
340 FALSE, /* (not used) */
341 FALSE, /* (not used) */
342 TRUE, /* otMonitor */
343 FALSE, /* (not used) */
344 FALSE, /* (not used) */
345 TRUE /* otEvent */
346 };
347
348 //
349 // Validate Handle and return the pointer to the object.
350 //
351 PVOID
352 FASTCALL
353 ValidateHandle(HANDLE handle, UINT uType)
354 {
355 PVOID ret;
356 PUSER_HANDLE_ENTRY pEntry;
357
358 ASSERT(uType <= otEvent);
359
360 pEntry = GetUser32Handle(handle);
361
362 if (pEntry && uType == 0)
363 uType = pEntry->type;
364
365 // Must have an entry and must be the same type!
366 if ( (!pEntry) ||
367 (pEntry->type != uType) ||
368 !pEntry->ptr ||
369 (pEntry->flags & HANDLEENTRY_INDESTROY) )
370 {
371 switch ( uType )
372 { // Test (with wine too) confirms these results!
373 case otWindow:
374 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
375 break;
376 case otMenu:
377 SetLastError(ERROR_INVALID_MENU_HANDLE);
378 break;
379 case otCursorIcon:
380 SetLastError(ERROR_INVALID_CURSOR_HANDLE);
381 break;
382 case otSMWP:
383 SetLastError(ERROR_INVALID_DWP_HANDLE);
384 break;
385 case otHook:
386 SetLastError(ERROR_INVALID_HOOK_HANDLE);
387 break;
388 case otAccel:
389 SetLastError(ERROR_INVALID_ACCEL_HANDLE);
390 break;
391 default:
392 SetLastError(ERROR_INVALID_HANDLE);
393 break;
394 }
395 return NULL;
396 }
397
398 if (g_ObjectHeapTypeShared[uType])
399 ret = SharedPtrToUser(pEntry->ptr);
400 else
401 ret = DesktopPtrToUser(pEntry->ptr);
402
403 return ret;
404 }
405
406 //
407 // Validate Handle and return the pointer to the object.
408 //
409 PVOID
410 FASTCALL
411 ValidateHandleNoErr(HANDLE handle, UINT uType)
412 {
413 PVOID ret;
414 PUSER_HANDLE_ENTRY pEntry;
415
416 ASSERT(uType <= otEvent);
417
418 pEntry = GetUser32Handle(handle);
419
420 if (pEntry && uType == 0)
421 uType = pEntry->type;
422
423 // Must have an entry and must be the same type!
424 if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
425 return NULL;
426
427 if (g_ObjectHeapTypeShared[uType])
428 ret = SharedPtrToUser(pEntry->ptr);
429 else
430 ret = DesktopPtrToUser(pEntry->ptr);
431
432 return ret;
433 }
434
435 //
436 // Validate a callproc handle and return the pointer to the object.
437 //
438 PCALLPROCDATA
439 FASTCALL
440 ValidateCallProc(HANDLE hCallProc)
441 {
442 PUSER_HANDLE_ENTRY pEntry;
443
444 PCALLPROCDATA CallProc = ValidateHandle(hCallProc, otCallProc);
445
446 pEntry = GetUser32Handle(hCallProc);
447
448 if (CallProc != NULL && pEntry->ppi == g_ppi)
449 return CallProc;
450
451 return NULL;
452 }
453
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 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
463 ASSERT(ClientInfo != NULL);
464
465 /* See if the window is cached */
466 if (hwnd && hwnd == ClientInfo->CallbackWnd.hWnd)
467 return ClientInfo->CallbackWnd.pWnd;
468
469 return ValidateHandle((HANDLE)hwnd, otWindow);
470 }
471
472 //
473 // Validate a window handle and return the pointer to the object.
474 //
475 PWND
476 FASTCALL
477 ValidateHwndNoErr(HWND hwnd)
478 {
479 PWND Wnd;
480 PCLIENTINFO ClientInfo = GetWin32ClientInfo();
481 ASSERT(ClientInfo != NULL);
482
483 /* See if the window is cached */
484 if (hwnd == ClientInfo->CallbackWnd.hWnd)
485 return ClientInfo->CallbackWnd.pWnd;
486
487 Wnd = ValidateHandleNoErr((HANDLE)hwnd, otWindow);
488 if (Wnd != NULL)
489 {
490 return Wnd;
491 }
492
493 return NULL;
494 }
495
496 PWND
497 FASTCALL
498 GetThreadDesktopWnd(VOID)
499 {
500 PWND Wnd = GetThreadDesktopInfo()->spwnd;
501 if (Wnd != NULL)
502 Wnd = DesktopPtrToUser(Wnd);
503 return Wnd;
504 }
505
506 //
507 // Validate a window handle and return the pointer to the object.
508 //
509 PWND
510 FASTCALL
511 ValidateHwndOrDesk(HWND hwnd)
512 {
513 if (hwnd == HWND_DESKTOP)
514 return GetThreadDesktopWnd();
515
516 return ValidateHwnd(hwnd);
517 }
518
519 /*
520 * @implemented
521 */
522 DWORD WINAPI WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR *MBString,LONG MBSize,BOOL Allocate)
523 {
524 DWORD Size;
525 if (UnicodeSize == -1)
526 {
527 UnicodeSize = wcslen(UnicodeString)+1;
528 }
529 if (MBSize == -1)
530 {
531 if (!Allocate)
532 {
533 return 0;
534 }
535 MBSize = UnicodeSize * 2;
536 }
537 if (Allocate)
538 {
539 LPSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, MBSize);
540 if (SafeString == NULL)
541 return 0;
542 *MBString = SafeString;
543 }
544 if (CodePage == 0)
545 {
546 RtlUnicodeToMultiByteN(*MBString,MBSize,&Size,UnicodeString,UnicodeSize);
547 }
548 else
549 {
550 WideCharToMultiByte(CodePage,0,UnicodeString,UnicodeSize,*MBString,MBSize,0,0);
551 }
552 return UnicodeSize;
553 }
554
555 /*
556 * @implemented
557 */
558 DWORD WINAPI MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR *UnicodeString,LONG UnicodeSize,BOOL Allocate)
559 {
560 DWORD Size;
561 if (MBSize == -1)
562 {
563 MBSize = strlen(MBString)+1;
564 }
565 if (UnicodeSize == -1)
566 {
567 if (!Allocate)
568 {
569 return 0;
570 }
571 UnicodeSize = MBSize;
572 }
573 if (Allocate)
574 {
575 LPWSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, UnicodeSize);
576 if (SafeString == NULL)
577 return 0;
578 *UnicodeString = SafeString;
579 }
580 UnicodeSize *= sizeof(WCHAR);
581 if (CodePage == 0)
582 {
583 RtlMultiByteToUnicodeN(*UnicodeString,UnicodeSize,&Size,MBString,MBSize);
584 }
585 else
586 {
587 Size = MultiByteToWideChar(CodePage,0,MBString,MBSize,*UnicodeString,UnicodeSize);
588 }
589 return Size;
590 }