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