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