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
UserSetLastError(IN DWORD dwErrCode)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
UserSetLastNTError(IN NTSTATUS Status)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
GetW32ThreadInfo(VOID)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
GetUserObjectSecurity(IN HANDLE hObject,IN PSECURITY_INFORMATION pSecurityInfo,OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,IN DWORD dwLength,OUT PDWORD pdwLengthNeeded)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
SetUserObjectSecurity(IN HANDLE hObject,IN PSECURITY_INFORMATION pSecurityInfo,IN PSECURITY_DESCRIPTOR pSecurityDescriptor)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
IsGUIThread(BOOL bConvert)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
TestWindowProcess(PWND Wnd)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
TestState(PWND pWnd,UINT Flag)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
GetUser32Handle(HANDLE handle)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
ValidateHandle(HANDLE handle,UINT uType)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
ValidateHandleNoErr(HANDLE handle,UINT uType)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
ValidateCallProc(HANDLE hCallProc)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
ValidateHwnd(HWND hwnd)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
ValidateHwndNoErr(HWND hwnd)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
GetThreadDesktopWnd(VOID)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
ValidateHwndOrDesk(HWND hwnd)410 ValidateHwndOrDesk(HWND hwnd)
411 {
412 if (hwnd == HWND_DESKTOP)
413 return GetThreadDesktopWnd();
414
415 return ValidateHwnd(hwnd);
416 }
417
418 /*
419 * @implemented
420 */
WCSToMBEx(WORD CodePage,LPWSTR UnicodeString,LONG UnicodeSize,LPSTR * MBString,LONG MBSize,BOOL Allocate)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 */
MBToWCSEx(WORD CodePage,LPSTR MBString,LONG MBSize,LPWSTR * UnicodeString,LONG UnicodeSize,BOOL Allocate)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