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