xref: /reactos/win32ss/user/user32/misc/misc.c (revision 595b846d)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS user32.dll
4  * FILE:            win32ss/user/user32/misc/misc.c
5  * PURPOSE:         Misc
6  * PROGRAMMER:      Thomas Weidenmueller (w3seek@users.sourceforge.net)
7  */
8 
9 #include <user32.h>
10 
11 VOID
12 WINAPI
13 UserSetLastError(IN DWORD dwErrCode)
14 {
15     /*
16      * Equivalent of SetLastError in kernel32, but without breaking
17      * into the debugger nor checking whether the last old error is
18      * the same as the one we are going to set.
19      */
20     NtCurrentTeb()->LastErrorValue = dwErrCode;
21 }
22 
23 VOID
24 WINAPI
25 UserSetLastNTError(IN NTSTATUS Status)
26 {
27     /*
28      * Equivalent of BaseSetLastNTError in kernel32, but using
29      * UserSetLastError: convert from NT to Win32, then set.
30      */
31     UserSetLastError(RtlNtStatusToDosError(Status));
32 }
33 
34 
35 PTHREADINFO
36 GetW32ThreadInfo(VOID)
37 {
38     PTHREADINFO ti;
39 
40     ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
41     if (ti == NULL)
42     {
43         /* create the THREADINFO structure */
44         NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
45         ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
46     }
47 
48     return ti;
49 }
50 
51 
52 /*
53  * GetUserObjectSecurity
54  *
55  * Retrieves security information for user object specified
56  * with handle 'hObject'. Descriptor returned in self-relative
57  * format.
58  *
59  * Arguments:
60  *  1) hObject - handle to an object to retrieve information for
61  *  2) pSecurityInfo - type of information to retrieve
62  *  3) pSecurityDescriptor - buffer which receives descriptor
63  *  4) dwLength - size, in bytes, of buffer 'pSecurityDescriptor'
64  *  5) pdwLengthNeeded - reseives actual size of descriptor
65  *
66  * Return Vaules:
67  *  TRUE on success
68  *  FALSE on failure, call GetLastError() for more information
69  */
70 /*
71  * @implemented
72  */
73 BOOL
74 WINAPI
75 GetUserObjectSecurity(
76     IN HANDLE hObject,
77     IN PSECURITY_INFORMATION pSecurityInfo,
78     OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
79     IN DWORD dwLength,
80     OUT PDWORD pdwLengthNeeded
81 )
82 {
83 DWORD dwWin32Error;
84 NTSTATUS Status;
85 
86 
87     Status = NtQuerySecurityObject(
88         hObject,            // Object Handle
89         *pSecurityInfo,     // Security Information
90         pSecurityDescriptor,// Security Descriptor
91         dwLength,           // Buffer Length
92         pdwLengthNeeded     // Actual Length
93     );
94 
95     if ( ! NT_SUCCESS( Status ) ) {
96         dwWin32Error = RtlNtStatusToDosError( Status );
97         NtCurrentTeb()->LastErrorValue = dwWin32Error;
98         return FALSE;
99     }
100 
101     return TRUE;
102 }
103 
104 
105 /*
106  * SetUserObjectSecurity
107  *
108  * Sets new security descriptor to user object specified by
109  * handle 'hObject'. Descriptor must be in self-relative format.
110  *
111  * Arguments:
112  *  1) hObject - handle to an object to set information for
113  *  2) pSecurityInfo - type of information to apply
114  *  3) pSecurityDescriptor - buffer which descriptor to set
115  *
116  * Return Vaules:
117  *  TRUE on success
118  *  FALSE on failure, call GetLastError() for more information
119  */
120 /*
121  * @implemented
122  */
123 BOOL
124 WINAPI
125 SetUserObjectSecurity(
126     IN HANDLE hObject,
127     IN PSECURITY_INFORMATION pSecurityInfo,
128     IN PSECURITY_DESCRIPTOR pSecurityDescriptor
129 )
130 {
131 DWORD dwWin32Error;
132 NTSTATUS Status;
133 
134 
135     Status = NtSetSecurityObject(
136         hObject,            // Object Handle
137         *pSecurityInfo,     // Security Information
138         pSecurityDescriptor // Security Descriptor
139     );
140 
141     if ( ! NT_SUCCESS( Status ) ) {
142         dwWin32Error = RtlNtStatusToDosError( Status );
143         NtCurrentTeb()->LastErrorValue = dwWin32Error;
144         return FALSE;
145     }
146 
147     return TRUE;
148 }
149 
150 /*
151  * @implemented
152  */
153 BOOL
154 WINAPI
155 IsGUIThread(
156     BOOL bConvert)
157 {
158   PTHREADINFO ti = (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo;
159   if (ti == NULL)
160   {
161     if(bConvert)
162     {
163       NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
164       if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo) return TRUE;
165       else
166          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
167     }
168     return FALSE;
169   }
170   else
171     return TRUE;
172 }
173 
174 BOOL
175 FASTCALL
176 TestWindowProcess(PWND Wnd)
177 {
178    if (Wnd->head.pti == (PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo)
179       return TRUE;
180    else
181       return (NtUserQueryWindow(Wnd->head.h, QUERY_WINDOW_UNIQUE_PROCESS_ID) ==
182               (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess );
183 }
184 
185 BOOL
186 FASTCALL
187 TestState(PWND pWnd, UINT Flag)
188 {
189     UINT bit;
190     bit = 1 << LOWORD(Flag);
191     switch(HIWORD(Flag))
192     {
193        case 0:
194           return (pWnd->state & bit);
195        case 1:
196           return (pWnd->state2 & bit);
197        case 2:
198           return (pWnd->ExStyle2 & bit);
199     }
200     return FALSE;
201 }
202 
203 PUSER_HANDLE_ENTRY
204 FASTCALL
205 GetUser32Handle(HANDLE handle)
206 {
207     INT Index;
208     USHORT generation;
209 
210     if (!handle) return NULL;
211 
212     Index = (((UINT_PTR)handle & 0xffff) - FIRST_USER_HANDLE) >> 1;
213 
214     if (Index < 0 || Index >= gHandleTable->nb_handles)
215         return NULL;
216 
217     if (!gHandleEntries[Index].type || !gHandleEntries[Index].ptr)
218         return NULL;
219 
220     generation = (UINT_PTR)handle >> 16;
221 
222     if (generation == gHandleEntries[Index].generation || !generation || generation == 0xffff)
223         return &gHandleEntries[Index];
224 
225     return NULL;
226 }
227 
228 /*
229  * Decide whether an object is located on the desktop or shared heap
230  */
231 static const BOOL g_ObjectHeapTypeShared[TYPE_CTYPES] =
232 {
233     FALSE, /* TYPE_FREE (not used) */
234     FALSE, /* TYPE_WINDOW */
235     FALSE, /* TYPE_MENU */
236     TRUE,  /* TYPE_CURSOR */
237     TRUE,  /* TYPE_SETWINDOWPOS */
238     FALSE, /* TYPE_HOOK */
239     TRUE,  /* TYPE_CLIPDATA */
240     FALSE, /* TYPE_CALLPROC */
241     TRUE,  /* TYPE_ACCELTABLE */
242     FALSE, /* TYPE_DDEACCESS */
243     FALSE, /* TYPE_DDECONV */
244     FALSE, /* TYPE_DDEXACT */
245     TRUE,  /* TYPE_MONITOR */
246     TRUE,  /* TYPE_KBDLAYOUT */
247     TRUE,  /* TYPE_KBDFILE */
248     TRUE,  /* TYPE_WINEVENTHOOK */
249     TRUE,  /* TYPE_TIMER */
250     FALSE, /* TYPE_INPUTCONTEXT */
251     FALSE, /* TYPE_HIDDATA */
252     FALSE, /* TYPE_DEVICEINFO */
253     FALSE, /* TYPE_TOUCHINPUTINFO */
254     FALSE, /* TYPE_GESTUREINFOOBJ */
255 };
256 
257 //
258 // Validate Handle and return the pointer to the object.
259 //
260 PVOID
261 FASTCALL
262 ValidateHandle(HANDLE handle, UINT uType)
263 {
264   PVOID ret;
265   PUSER_HANDLE_ENTRY pEntry;
266 
267   ASSERT(uType < TYPE_CTYPES);
268 
269   pEntry = GetUser32Handle(handle);
270 
271   if (pEntry && uType == 0)
272       uType = pEntry->type;
273 
274 // Must have an entry and must be the same type!
275   if ( (!pEntry) ||
276         (pEntry->type != uType) ||
277         !pEntry->ptr ||
278         (pEntry->flags & HANDLEENTRY_DESTROY) || (pEntry->flags & HANDLEENTRY_INDESTROY) )
279   {
280      switch ( uType )
281      {  // Test (with wine too) confirms these results!
282         case TYPE_WINDOW:
283           SetLastError(ERROR_INVALID_WINDOW_HANDLE);
284           break;
285         case TYPE_MENU:
286           SetLastError(ERROR_INVALID_MENU_HANDLE);
287           break;
288         case TYPE_CURSOR:
289           SetLastError(ERROR_INVALID_CURSOR_HANDLE);
290           break;
291         case TYPE_SETWINDOWPOS:
292           SetLastError(ERROR_INVALID_DWP_HANDLE);
293           break;
294         case TYPE_HOOK:
295           SetLastError(ERROR_INVALID_HOOK_HANDLE);
296           break;
297         case TYPE_ACCELTABLE:
298           SetLastError(ERROR_INVALID_ACCEL_HANDLE);
299           break;
300         default:
301           SetLastError(ERROR_INVALID_HANDLE);
302           break;
303     }
304     return NULL;
305   }
306 
307   if (g_ObjectHeapTypeShared[uType])
308     ret = SharedPtrToUser(pEntry->ptr);
309   else
310     ret = DesktopPtrToUser(pEntry->ptr);
311 
312   return ret;
313 }
314 
315 //
316 // Validate Handle and return the pointer to the object.
317 //
318 PVOID
319 FASTCALL
320 ValidateHandleNoErr(HANDLE handle, UINT uType)
321 {
322   PVOID ret;
323   PUSER_HANDLE_ENTRY pEntry;
324 
325   ASSERT(uType < TYPE_CTYPES);
326 
327   pEntry = GetUser32Handle(handle);
328 
329   if (pEntry && uType == 0)
330       uType = pEntry->type;
331 
332 // Must have an entry and must be the same type!
333   if ( (!pEntry) || (pEntry->type != uType) || !pEntry->ptr )
334     return NULL;
335 
336   if (g_ObjectHeapTypeShared[uType])
337     ret = SharedPtrToUser(pEntry->ptr);
338   else
339     ret = DesktopPtrToUser(pEntry->ptr);
340 
341   return ret;
342 }
343 
344 //
345 // Validate a callproc handle and return the pointer to the object.
346 //
347 PCALLPROCDATA
348 FASTCALL
349 ValidateCallProc(HANDLE hCallProc)
350 {
351   PUSER_HANDLE_ENTRY pEntry;
352 
353   PCALLPROCDATA CallProc = ValidateHandle(hCallProc, TYPE_CALLPROC);
354 
355   pEntry = GetUser32Handle(hCallProc);
356 
357   if (CallProc != NULL && pEntry->ppi == g_ppi)
358      return CallProc;
359 
360   return NULL;
361 }
362 
363 
364 //
365 // Validate a window handle and return the pointer to the object.
366 //
367 PWND
368 FASTCALL
369 ValidateHwnd(HWND hwnd)
370 {
371     PCLIENTINFO ClientInfo = GetWin32ClientInfo();
372     ASSERT(ClientInfo != NULL);
373 
374     /* See if the window is cached */
375     if (hwnd && hwnd == ClientInfo->CallbackWnd.hWnd)
376         return ClientInfo->CallbackWnd.pWnd;
377 
378     return ValidateHandle((HANDLE)hwnd, TYPE_WINDOW);
379 }
380 
381 //
382 // Validate a window handle and return the pointer to the object.
383 //
384 PWND
385 FASTCALL
386 ValidateHwndNoErr(HWND hwnd)
387 {
388     PWND Wnd;
389     PCLIENTINFO ClientInfo = GetWin32ClientInfo();
390     ASSERT(ClientInfo != NULL);
391 
392     /* See if the window is cached */
393     if (hwnd == ClientInfo->CallbackWnd.hWnd)
394         return ClientInfo->CallbackWnd.pWnd;
395 
396     Wnd = ValidateHandleNoErr((HANDLE)hwnd, TYPE_WINDOW);
397     if (Wnd != NULL)
398     {
399         return Wnd;
400     }
401 
402     return NULL;
403 }
404 
405 PWND
406 FASTCALL
407 GetThreadDesktopWnd(VOID)
408 {
409     PWND Wnd = GetThreadDesktopInfo()->spwnd;
410     if (Wnd != NULL)
411         Wnd = DesktopPtrToUser(Wnd);
412     return Wnd;
413 }
414 
415 //
416 // Validate a window handle and return the pointer to the object.
417 //
418 PWND
419 FASTCALL
420 ValidateHwndOrDesk(HWND hwnd)
421 {
422     if (hwnd == HWND_DESKTOP)
423         return GetThreadDesktopWnd();
424 
425     return ValidateHwnd(hwnd);
426 }
427 
428 /*
429  * @implemented
430  */
431 DWORD WINAPI WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR *MBString,LONG MBSize,BOOL Allocate)
432 {
433 	DWORD Size;
434 	if (UnicodeSize == -1)
435 	{
436 		UnicodeSize = wcslen(UnicodeString)+1;
437 	}
438 	if (MBSize == -1)
439 	{
440 		if (!Allocate)
441 		{
442 			return 0;
443 		}
444 		MBSize = UnicodeSize * 2;
445 	}
446 	if (Allocate)
447 	{
448 		LPSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, MBSize);
449         if (SafeString == NULL)
450             return 0;
451         *MBString = SafeString;
452 	}
453 	if (CodePage == 0)
454 	{
455 		RtlUnicodeToMultiByteN(*MBString,MBSize,&Size,UnicodeString,UnicodeSize);
456 	}
457 	else
458 	{
459 		WideCharToMultiByte(CodePage,0,UnicodeString,UnicodeSize,*MBString,MBSize,0,0);
460 	}
461 	return UnicodeSize;
462 }
463 
464 /*
465  * @implemented
466  */
467 DWORD WINAPI MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR *UnicodeString,LONG UnicodeSize,BOOL Allocate)
468 {
469 	DWORD Size;
470 	if (MBSize == -1)
471 	{
472 		MBSize = strlen(MBString)+1;
473 	}
474 	if (UnicodeSize == -1)
475 	{
476 		if (!Allocate)
477 		{
478 			return 0;
479 		}
480 		UnicodeSize = MBSize;
481 	}
482 	if (Allocate)
483 	{
484 		LPWSTR SafeString = RtlAllocateHeap(GetProcessHeap(), 0, UnicodeSize);
485         if (SafeString == NULL)
486             return 0;
487         *UnicodeString = SafeString;
488 	}
489 	UnicodeSize *= sizeof(WCHAR);
490 	if (CodePage == 0)
491 	{
492 		RtlMultiByteToUnicodeN(*UnicodeString,UnicodeSize,&Size,MBString,MBSize);
493 	}
494 	else
495 	{
496 		Size = MultiByteToWideChar(CodePage,0,MBString,MBSize,*UnicodeString,UnicodeSize);
497 	}
498 	return Size;
499 }
500