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