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