Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

security.c

Go to the documentation of this file.
00001 /**************************** Module Header ********************************\ 00002 * Module Name: security.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * Securable Object Routines 00007 * 00008 * History: 00009 * 12-31-90 JimA Created. 00010 * 04-14-92 RichardW Changed ACE_HEADER 00011 \***************************************************************************/ 00012 00013 #define _SECURITY 1 00014 #include "precomp.h" 00015 #pragma hdrstop 00016 00017 #pragma alloc_text(INIT, InitSecurity) 00018 00019 /* 00020 * General security stuff 00021 */ 00022 PSECURITY_DESCRIPTOR gpsdInitWinSta; 00023 00024 PRIVILEGE_SET psTcb = { 1, PRIVILEGE_SET_ALL_NECESSARY, 00025 { SE_TCB_PRIVILEGE, 0 } 00026 }; 00027 00028 /***************************************************************************\ 00029 * AllocAce 00030 * 00031 * Allocates and initializes an ACE list. 00032 * 00033 * History: 00034 * 04-25-91 JimA Created. 00035 \***************************************************************************/ 00036 00037 PACCESS_ALLOWED_ACE AllocAce( 00038 PACCESS_ALLOWED_ACE pace, 00039 BYTE bType, 00040 BYTE bFlags, 00041 ACCESS_MASK am, 00042 PSID psid, 00043 LPDWORD lpdwLength) 00044 { 00045 PACCESS_ALLOWED_ACE paceNew; 00046 DWORD iEnd; 00047 DWORD dwLength, dwLengthSid; 00048 00049 /* 00050 * Allocate space for the ACE. 00051 */ 00052 dwLengthSid = RtlLengthSid(psid); 00053 dwLength = dwLengthSid + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK); 00054 if (pace == NULL) { 00055 iEnd = 0; 00056 pace = UserAllocPoolWithQuota(dwLength, TAG_SECURITY); 00057 if (pace == NULL) 00058 return NULL; 00059 } else { 00060 iEnd = *lpdwLength; 00061 paceNew = UserAllocPoolWithQuota(iEnd + dwLength, TAG_SECURITY); 00062 if (paceNew == NULL) 00063 return NULL; 00064 RtlCopyMemory(paceNew, pace, iEnd); 00065 UserFreePool(pace); 00066 pace = paceNew; 00067 } 00068 *lpdwLength = dwLength + iEnd; 00069 00070 /* 00071 * Insert the new ACE. 00072 */ 00073 paceNew = (PACCESS_ALLOWED_ACE)((PBYTE)pace + iEnd); 00074 paceNew->Header.AceType = bType; 00075 paceNew->Header.AceSize = (USHORT)dwLength; 00076 paceNew->Header.AceFlags = bFlags; 00077 paceNew->Mask = am; 00078 RtlCopySid(dwLengthSid, &paceNew->SidStart, psid); 00079 return pace; 00080 } 00081 00082 /***************************************************************************\ 00083 * CreateSecurityDescriptor 00084 * 00085 * Allocates and initializes a security descriptor. 00086 * 00087 * History: 00088 * 04-25-91 JimA Created. 00089 \***************************************************************************/ 00090 00091 PSECURITY_DESCRIPTOR CreateSecurityDescriptor( 00092 PACCESS_ALLOWED_ACE paceList, 00093 DWORD cbAce, 00094 BOOLEAN fDaclDefaulted) 00095 { 00096 PSECURITY_DESCRIPTOR psd; 00097 PACL pacl; 00098 NTSTATUS Status; 00099 00100 /* 00101 * Allocate the security descriptor 00102 */ 00103 psd = (PSECURITY_DESCRIPTOR)UserAllocPoolWithQuota( 00104 cbAce + sizeof(ACL) + SECURITY_DESCRIPTOR_MIN_LENGTH, 00105 TAG_SECURITY); 00106 if (psd == NULL) 00107 return NULL; 00108 RtlCreateSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION); 00109 00110 /* 00111 * Initialize the ACL 00112 */ 00113 pacl = (PACL)((PBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH); 00114 Status = RtlCreateAcl(pacl, sizeof(ACL) + cbAce, ACL_REVISION); 00115 if (NT_SUCCESS(Status)) { 00116 00117 /* 00118 * Add the ACEs to the ACL. 00119 */ 00120 Status = RtlAddAce(pacl, ACL_REVISION, MAXULONG, paceList, cbAce); 00121 if (NT_SUCCESS(Status)) { 00122 00123 /* 00124 * Initialize the SD 00125 */ 00126 Status = RtlSetDaclSecurityDescriptor(psd, (BOOLEAN)TRUE, 00127 pacl, fDaclDefaulted); 00128 RtlSetSaclSecurityDescriptor(psd, (BOOLEAN)FALSE, NULL, 00129 (BOOLEAN)FALSE); 00130 RtlSetOwnerSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE); 00131 RtlSetGroupSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE); 00132 } 00133 } 00134 00135 if (!NT_SUCCESS(Status)) { 00136 UserFreePool(psd); 00137 return NULL; 00138 } 00139 00140 return psd; 00141 } 00142 00143 /***************************************************************************\ 00144 * InitSecurity 00145 * 00146 * Initialize global security information. 00147 * 00148 * History: 00149 * 01-29-91 JimA Created. 00150 \***************************************************************************/ 00151 00152 BOOL InitSecurity( 00153 VOID) 00154 { 00155 PACCESS_ALLOWED_ACE paceList = NULL, pace; 00156 DWORD dwLength; 00157 00158 /* 00159 * Get access to exported constants 00160 */ 00161 SeEnableAccessToExports(); 00162 00163 /* 00164 * Create ACE list. 00165 */ 00166 paceList = AllocAce(NULL, 00167 ACCESS_ALLOWED_ACE_TYPE, 00168 CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE, 00169 WinStaMapping.GenericAll, 00170 SeExports->SeWorldSid, 00171 &dwLength); 00172 if (paceList == NULL) 00173 return FALSE; 00174 00175 pace = AllocAce(paceList, 00176 ACCESS_ALLOWED_ACE_TYPE, 00177 CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE, 00178 WinStaMapping.GenericAll, 00179 SeExports->SeRestrictedSid, 00180 &dwLength); 00181 if (pace == NULL) { 00182 UserFreePool(paceList); 00183 return FALSE; 00184 } 00185 paceList = pace; 00186 00187 pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE, 00188 OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE, 00189 GENERIC_ALL, SeExports->SeWorldSid, &dwLength); 00190 if (pace == NULL) { 00191 UserFreePool(paceList); 00192 return FALSE; 00193 } 00194 paceList = pace; 00195 00196 pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE, 00197 OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE, 00198 GENERIC_ALL, SeExports->SeRestrictedSid, &dwLength); 00199 if (pace == NULL) { 00200 UserFreePool(paceList); 00201 return FALSE; 00202 } 00203 paceList = pace; 00204 00205 pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE, 00206 0, DIRECTORY_QUERY | DIRECTORY_CREATE_OBJECT, 00207 SeExports->SeAliasAdminsSid, &dwLength); 00208 if (pace == NULL) { 00209 UserFreePool(paceList); 00210 return FALSE; 00211 } 00212 paceList = pace; 00213 00214 pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE, 00215 0, DIRECTORY_TRAVERSE, SeExports->SeWorldSid, &dwLength); 00216 if (pace == NULL) { 00217 UserFreePool(paceList); 00218 return FALSE; 00219 } 00220 paceList = pace; 00221 00222 pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE, 00223 0, DIRECTORY_TRAVERSE, SeExports->SeRestrictedSid, &dwLength); 00224 if (pace == NULL) { 00225 UserFreePool(paceList); 00226 return FALSE; 00227 } 00228 paceList = pace; 00229 00230 /* 00231 * Create the SD 00232 */ 00233 gpsdInitWinSta = CreateSecurityDescriptor(paceList, dwLength, FALSE); 00234 UserFreePool(paceList); 00235 00236 if (gpsdInitWinSta == NULL) { 00237 RIPMSG0(RIP_WARNING, "Initial windowstation security was not created!"); 00238 } 00239 00240 return (BOOL)(gpsdInitWinSta != NULL); 00241 } 00242 00243 00244 /***************************************************************************\ 00245 * TestForInteractiveUser 00246 * 00247 * Returns STATUS_SUCCESS if the LUID passed represents an 00248 * interactiveUser user logged on by winlogon, otherwise FALSE 00249 * 00250 * History: 00251 * 03-08-95 JimA Created. 00252 \***************************************************************************/ 00253 00254 NTSTATUS 00255 TestForInteractiveUser( 00256 PLUID pluidCaller 00257 ) 00258 { 00259 PWINDOWSTATION pwinsta; 00260 00261 UserAssert(grpWinStaList != NULL); 00262 00263 /* 00264 * !!! 00265 * 00266 * This relies on the fact that there is only ONE interactive 00267 * windowstation and that it is the first one in the list. 00268 * If multiple windowstations are ever supported 00269 * a lookup will have to be done here. 00270 */ 00271 pwinsta = grpWinStaList; 00272 00273 /* 00274 * Compare it with the id of the logged on user. 00275 */ 00276 if (RtlEqualLuid(pluidCaller, &pwinsta->luidUser)) 00277 return STATUS_SUCCESS; 00278 else 00279 return STATUS_ACCESS_DENIED; 00280 } 00281 00282 00283 00284 /***************************************************************************\ 00285 * _UserTestForWinStaAccess 00286 * 00287 * Returns STATUS_SUCCESS if the current user has GENERIC_EXECUTE access on 00288 * WindowStation pstrWinSta 00289 * 00290 * 00291 * History: 00292 * 06-05-96 Created SalimC 00293 \***************************************************************************/ 00294 NTSTATUS 00295 _UserTestForWinStaAccess( 00296 PUNICODE_STRING pstrWinSta, 00297 BOOL fInherit 00298 ) 00299 { 00300 PTOKEN_STATISTICS pStats; 00301 ULONG BytesRequired; 00302 PWINDOWSTATION pwinsta; 00303 HWINSTA hwsta = NULL; 00304 OBJECT_ATTRIBUTES ObjAttr; 00305 POBJECT_ATTRIBUTES pObjAttr = NULL; 00306 PUNICODE_STRING pstrStatic; 00307 NTSTATUS Status = STATUS_SUCCESS; 00308 SIZE_T cbObjA; 00309 UNICODE_STRING strDefWinSta; 00310 HANDLE htoken; 00311 00312 CheckCritIn(); 00313 00314 UserAssert(NtCurrentTeb()); 00315 UserAssert(pstrWinSta->Buffer == NtCurrentTeb()->StaticUnicodeBuffer); 00316 00317 /* 00318 * If we are testing against Default WindowStation (WinSta0) retreive 00319 * pwinsta from the top of the grpwinstaList instead of doing an 00320 * OpenWindowStation() 00321 * 00322 * !!! 00323 * 00324 * This relies on the fact that there is only ONE interactive 00325 * windowstation and that it is the first one in the list. 00326 * If multiple windowstations are ever supported 00327 * a lookup will have to be done instead. 00328 */ 00329 RtlInitUnicodeString(&strDefWinSta, DEFAULT_WINSTA); 00330 if (RtlEqualUnicodeString(pstrWinSta, &strDefWinSta, TRUE)) { 00331 00332 00333 if (!NT_SUCCESS(Status = OpenEffectiveToken(&htoken))) { 00334 return Status; 00335 } 00336 00337 Status = ZwQueryInformationToken( 00338 htoken, // Handle 00339 TokenStatistics, // TokenInformationClass 00340 NULL, // TokenInformation 00341 0, // TokenInformationLength 00342 &BytesRequired // ReturnLength 00343 ); 00344 00345 if (Status != STATUS_BUFFER_TOO_SMALL) { 00346 ZwClose(htoken); 00347 return Status; 00348 } 00349 00350 // 00351 // Allocate space for the user info 00352 // 00353 00354 pStats = (PTOKEN_STATISTICS)UserAllocPoolWithQuota(BytesRequired, TAG_SECURITY); 00355 if (pStats == NULL) { 00356 Status = STATUS_NO_MEMORY; 00357 ZwClose(htoken); 00358 return Status; 00359 } 00360 00361 // 00362 // Read in the user info 00363 // 00364 00365 if (!NT_SUCCESS(Status = ZwQueryInformationToken( 00366 htoken, // Handle 00367 TokenStatistics, // TokenInformationClass 00368 pStats, // TokenInformation 00369 BytesRequired, // TokenInformationLength 00370 &BytesRequired // ReturnLength 00371 ))) { 00372 ZwClose(htoken); 00373 UserFreePool(pStats); 00374 return Status; 00375 } 00376 00377 /* 00378 * Make sure that current process has access to this window station 00379 */ 00380 Status = STATUS_ACCESS_DENIED; 00381 00382 if (grpWinStaList != NULL) { 00383 00384 /* 00385 * !!! 00386 * 00387 * This relies on the fact that there is only ONE interactive 00388 * windowstation and that it is the first one in the list. 00389 * If multiple windowstations are ever supported 00390 * a lookup will have to be done here. 00391 */ 00392 pwinsta = grpWinStaList; 00393 00394 /* 00395 * For now we will just do the user luid test till we figure out 00396 * what fInherit means for a Multi-User system 00397 */ 00398 if (fInherit) { 00399 if ( (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) || 00400 (RtlEqualLuid(&pStats->AuthenticationId, &luidSystem)) || 00401 (AccessCheckObject(pwinsta, GENERIC_EXECUTE, (KPROCESSOR_MODE)(gbSecureDesktop ? UserMode : KernelMode), &WinStaMapping)) ) { 00402 Status = STATUS_SUCCESS; 00403 } 00404 } else { 00405 /* Bug 42905. Service Controller clears the flag 00406 * ScStartupInfo.dwFlags &= (~STARTF_DESKTOPINHERIT) to make services 00407 * running under the context of system non-interactive. Hence if fInherit 00408 * is false don't do the SystemLuid and AccessCheckObject tests. 00409 */ 00410 00411 if (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) { 00412 Status = STATUS_SUCCESS; 00413 } 00414 } 00415 } 00416 00417 ZwClose(htoken); 00418 UserFreePool(pStats); 00419 return Status; 00420 } 00421 00422 if (gbSecureDesktop) { 00423 /* 00424 * Since we don't have a pointer to the WindowStation Object we will do 00425 * a OpenWindowStation() to make sure we have the desired access. 00426 */ 00427 cbObjA = sizeof(*pObjAttr) + sizeof(*pstrStatic); 00428 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 00429 &pObjAttr, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE); 00430 pstrStatic = (PUNICODE_STRING)((PBYTE)pObjAttr + sizeof(*pObjAttr)); 00431 00432 if (NT_SUCCESS(Status)) { 00433 00434 /* 00435 * Note -- the string must be in client-space or the 00436 * address validation in OpenWindowStation will fail. 00437 * 00438 * This code is called from xxxResolveDesktop and the buffer of the passed-in string 00439 * is in the teb already. 00440 */ 00441 try { 00442 *pstrStatic = *pstrWinSta; 00443 InitializeObjectAttributes( pObjAttr, 00444 pstrStatic, 00445 OBJ_CASE_INSENSITIVE, 00446 NULL, 00447 NULL 00448 ); 00449 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00450 Status = GetExceptionCode(); 00451 } 00452 00453 if (NT_SUCCESS(Status)) { 00454 hwsta = _OpenWindowStation(pObjAttr, GENERIC_EXECUTE, UserMode); 00455 } 00456 } else { 00457 return Status; 00458 } 00459 00460 if (pObjAttr != NULL) { 00461 ZwFreeVirtualMemory(NtCurrentProcess(), &pObjAttr, &cbObjA, 00462 MEM_RELEASE); 00463 } 00464 } else { 00465 InitializeObjectAttributes( &ObjAttr, 00466 pstrWinSta, 00467 OBJ_CASE_INSENSITIVE, 00468 NULL, 00469 NULL 00470 ); 00471 hwsta = _OpenWindowStation(&ObjAttr, GENERIC_EXECUTE, KernelMode); 00472 } 00473 00474 if (!hwsta) { 00475 return STATUS_ACCESS_DENIED; 00476 } 00477 00478 Status = ZwClose(hwsta); 00479 00480 UserAssert(NT_SUCCESS(Status)); 00481 return Status; 00482 } 00483 /***************************************************************************\ 00484 * CheckGrantedAccess 00485 * 00486 * Confirms all requested accesses are granted and sets error status. 00487 * 00488 * History: 00489 * 06-26-95 JimA Created. 00490 \***************************************************************************/ 00491 00492 BOOL CheckGrantedAccess( 00493 ACCESS_MASK amGranted, 00494 ACCESS_MASK amRequest) 00495 { 00496 00497 /* 00498 * Check the granted access. 00499 */ 00500 if (!RtlAreAllAccessesGranted(amGranted, amRequest)) { 00501 RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, ""); 00502 return FALSE; 00503 } 00504 return TRUE; 00505 } 00506 00507 /***************************************************************************\ 00508 * CheckWinstaWriteAttributesAccess 00509 * 00510 * Checks if the current process has WINSTA_WRITEATTRIBUTES access 00511 * to its windowstation, and whether that windowstation is an 00512 * interactive windowstation. 00513 * 00514 * History: 00515 * 06-Jun-1996 adams Created. 00516 \***************************************************************************/ 00517 00518 BOOL CheckWinstaWriteAttributesAccess(void) 00519 { 00520 PPROCESSINFO ppiCurrent = PpiCurrent(); 00521 00522 /* 00523 * winlogon has rights to all windowstations. 00524 */ 00525 if (PsGetCurrentProcess()->UniqueProcessId == gpidLogon) 00526 return TRUE; 00527 00528 if (!(ppiCurrent->W32PF_Flags & W32PF_IOWINSTA)) { 00529 RIPERR0(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION, 00530 RIP_WARNING, 00531 "Operation invalid on a non-interactive WindowStation."); 00532 00533 return FALSE; 00534 } 00535 00536 if (!RtlAreAllAccessesGranted(ppiCurrent->amwinsta, WINSTA_WRITEATTRIBUTES)) { 00537 RIPERR0(ERROR_ACCESS_DENIED, 00538 RIP_WARNING, 00539 "WINSTA_WRITEATTRIBUTES access to WindowStation denied."); 00540 00541 return FALSE; 00542 } 00543 return TRUE; 00544 } 00545 00546 /***************************************************************************\ 00547 * AccessCheckObject 00548 * 00549 * Performs an access check on an object 00550 * 00551 * History: 00552 * 12-31-90 JimA Created. 00553 \***************************************************************************/ 00554 00555 BOOL AccessCheckObject( 00556 PVOID pobj, 00557 ACCESS_MASK amRequest, 00558 KPROCESSOR_MODE AccessMode, 00559 CONST GENERIC_MAPPING *pGenericMapping) 00560 { 00561 NTSTATUS Status; 00562 ACCESS_STATE AccessState; 00563 BOOLEAN fAccessGranted; 00564 AUX_ACCESS_DATA AuxData; 00565 BOOLEAN bMutexLocked = (pGenericMapping == (&KeyMapping)); 00566 /* 00567 * Due to a resource problem in the object manager, we must pass in a TRUE 00568 * when checking access for registry keys, even if we do not explicitly have 00569 * the object type mutex. If we do not, we can get into a deadlock situation with this mutex 00570 * and the CmpRegistry lock. 00571 */ 00572 00573 SeCreateAccessState(&AccessState, &AuxData, amRequest, (PGENERIC_MAPPING)pGenericMapping); 00574 fAccessGranted = ObCheckObjectAccess( 00575 pobj, 00576 &AccessState, 00577 bMutexLocked, 00578 AccessMode, 00579 &Status); 00580 SeDeleteAccessState(&AccessState); 00581 return (BOOL)(fAccessGranted == TRUE); 00582 } 00583 00584 /***************************************************************************\ 00585 * IsPrivileged 00586 * 00587 * Check to see if the client has the specified privileges 00588 * 00589 * History: 00590 * 01-02-91 JimA Created. 00591 \***************************************************************************/ 00592 00593 BOOL IsPrivileged( 00594 PPRIVILEGE_SET ppSet) 00595 { 00596 SECURITY_SUBJECT_CONTEXT Context; 00597 BOOLEAN bHeld; 00598 00599 SeCaptureSubjectContext(&Context); 00600 SeLockSubjectContext(&Context); 00601 00602 bHeld = SePrivilegeCheck(ppSet, &Context, UserMode); 00603 SePrivilegeObjectAuditAlarm(NULL, &Context, 0, ppSet, bHeld, UserMode); 00604 00605 SeUnlockSubjectContext(&Context); 00606 SeReleaseSubjectContext(&Context); 00607 00608 if (!bHeld) 00609 RIPERR0(ERROR_PRIVILEGE_NOT_HELD, RIP_VERBOSE, ""); 00610 00611 /* 00612 * Return result of privilege check 00613 */ 00614 return (BOOL)bHeld; 00615 } 00616 00617 /***************************************************************************\ 00618 * _GetUserObjectInformation (API) 00619 * 00620 * Gets information about a secure USER object 00621 * 00622 * History: 00623 * 04-25-94 JimA Created. 00624 \***************************************************************************/ 00625 00626 BOOL _GetUserObjectInformation( 00627 HANDLE h, 00628 int nIndex, 00629 PVOID ccxpvInfo, 00630 DWORD nLength, 00631 LPDWORD lpnLengthNeeded) 00632 { 00633 PUSEROBJECTFLAGS puof; 00634 BOOL fSuccess = TRUE; 00635 PVOID pObject; 00636 POBJECT_HEADER pHead; 00637 DWORD dwLengthNeeded = 0; 00638 OBJECT_HANDLE_INFORMATION ohi; 00639 PUNICODE_STRING pstrInfo; 00640 PWINDOWSTATION pwinsta; 00641 NTSTATUS Status; 00642 00643 /* 00644 * Validate the object 00645 */ 00646 Status = ObReferenceObjectByHandle( 00647 h, 00648 0, 00649 NULL, 00650 UserMode, // this is always called from the client side 00651 &pObject, 00652 &ohi); 00653 if (!NT_SUCCESS(Status)) { 00654 RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed"); 00655 return FALSE; 00656 } 00657 00658 pHead = OBJECT_TO_OBJECT_HEADER(pObject); 00659 if (pHead->Type != *ExWindowStationObjectType && 00660 pHead->Type != *ExDesktopObjectType) { 00661 RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object"); 00662 ObDereferenceObject(pObject); 00663 return FALSE; 00664 } 00665 00666 #ifdef LOGDESKTOPLOCKS 00667 if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) { 00668 LogDesktop(pObject, LD_REF_FN_GETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrentShared()); 00669 } 00670 #endif 00671 00672 try { 00673 switch (nIndex) { 00674 case UOI_FLAGS: 00675 dwLengthNeeded = sizeof(USEROBJECTFLAGS); 00676 if (nLength < sizeof(USEROBJECTFLAGS)) { 00677 RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, ""); 00678 fSuccess = FALSE; 00679 break; 00680 } 00681 puof = ccxpvInfo; 00682 puof->fInherit = (ohi.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE; 00683 puof->fReserved = 0; 00684 puof->dwFlags = 0; 00685 if (pHead->Type == *ExDesktopObjectType) { 00686 if (CheckHandleFlag(h, HF_DESKTOPHOOK)) 00687 puof->dwFlags |= DF_ALLOWOTHERACCOUNTHOOK; 00688 } else { 00689 if (!(((PWINDOWSTATION)pObject)->dwWSF_Flags & WSF_NOIO)) 00690 puof->dwFlags |= WSF_VISIBLE; 00691 } 00692 break; 00693 00694 case UOI_NAME: 00695 pstrInfo = POBJECT_NAME(pObject); 00696 goto docopy; 00697 00698 case UOI_TYPE: 00699 pstrInfo = &pHead->Type->Name; 00700 docopy: 00701 if (pstrInfo) { 00702 dwLengthNeeded = pstrInfo->Length + sizeof(WCHAR); 00703 if (dwLengthNeeded > nLength) { 00704 RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, ""); 00705 fSuccess = FALSE; 00706 break; 00707 } 00708 RtlCopyMemory(ccxpvInfo, pstrInfo->Buffer, pstrInfo->Length); 00709 *(PWCHAR)((PBYTE)ccxpvInfo + pstrInfo->Length) = 0; 00710 } else { 00711 dwLengthNeeded = 0; 00712 } 00713 break; 00714 00715 case UOI_USER_SID: 00716 if (pHead->Type == *ExWindowStationObjectType) 00717 pwinsta = pObject; 00718 else 00719 pwinsta = ((PDESKTOP)pObject)->rpwinstaParent; 00720 if (pwinsta->psidUser == NULL) { 00721 dwLengthNeeded = 0; 00722 } else { 00723 dwLengthNeeded = RtlLengthSid(pwinsta->psidUser); 00724 if (dwLengthNeeded > nLength) { 00725 RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, ""); 00726 fSuccess = FALSE; 00727 break; 00728 } 00729 RtlCopyMemory(ccxpvInfo, pwinsta->psidUser, dwLengthNeeded); 00730 } 00731 break; 00732 00733 default: 00734 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00735 fSuccess = FALSE; 00736 break; 00737 } 00738 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 00739 fSuccess = FALSE; 00740 } 00741 00742 *lpnLengthNeeded = dwLengthNeeded; 00743 00744 #ifdef LOGDESKTOPLOCKS 00745 if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) { 00746 LogDesktop(pObject, LD_DEREF_FN_GETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrentShared()); 00747 } 00748 #endif 00749 00750 ObDereferenceObject(pObject); 00751 00752 return fSuccess; 00753 } 00754 00755 /***************************************************************************\ 00756 * _SetUserObjectInformation (API) 00757 * 00758 * Sets information about a secure USER object 00759 * 00760 * History: 00761 * 04-25-94 JimA Created. 00762 \***************************************************************************/ 00763 00764 BOOL _SetUserObjectInformation( 00765 HANDLE h, 00766 int nIndex, 00767 PVOID ccxpvInfo, 00768 DWORD nLength) 00769 { 00770 PUSEROBJECTFLAGS puof; 00771 BOOL fSuccess = TRUE; 00772 PVOID pObject; 00773 POBJECT_HEADER pHead; 00774 DWORD dwLengthNeeded = 0; 00775 OBJECT_HANDLE_INFORMATION ohi; 00776 OBJECT_HANDLE_FLAG_INFORMATION ofi; 00777 NTSTATUS Status; 00778 00779 /* 00780 * Validate the object 00781 */ 00782 Status = ObReferenceObjectByHandle( 00783 h, 00784 0, 00785 NULL, 00786 UserMode, // this is always called from the client side 00787 &pObject, 00788 &ohi); 00789 if (!NT_SUCCESS(Status)) { 00790 RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed"); 00791 return FALSE; 00792 } 00793 00794 pHead = OBJECT_TO_OBJECT_HEADER(pObject); 00795 if (pHead->Type != *ExWindowStationObjectType && 00796 pHead->Type != *ExDesktopObjectType) { 00797 RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object"); 00798 ObDereferenceObject(pObject); 00799 return FALSE; 00800 } 00801 00802 #ifdef LOGDESKTOPLOCKS 00803 if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) { 00804 LogDesktop(pObject, LD_REF_FN_SETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrent()); 00805 } 00806 #endif 00807 00808 try { 00809 switch (nIndex) { 00810 case UOI_FLAGS: 00811 if (nLength < sizeof(USEROBJECTFLAGS)) { 00812 RIPERR0(ERROR_INVALID_DATA, RIP_VERBOSE, ""); 00813 fSuccess = FALSE; 00814 break; 00815 } 00816 puof = ccxpvInfo; 00817 ZwQueryObject(h, ObjectHandleFlagInformation, 00818 &ofi, sizeof(ofi), NULL); 00819 ofi.Inherit = (puof->fInherit != FALSE); 00820 ZwSetInformationObject(h, ObjectHandleFlagInformation, 00821 &ofi, sizeof(ofi)); 00822 if (pHead->Type == *ExDesktopObjectType) { 00823 SetHandleFlag(h, HF_DESKTOPHOOK, 00824 puof->dwFlags & DF_ALLOWOTHERACCOUNTHOOK); 00825 } 00826 break; 00827 default: 00828 RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, ""); 00829 fSuccess = FALSE; 00830 break; 00831 } 00832 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 00833 fSuccess = FALSE; 00834 } 00835 00836 #ifdef LOGDESKTOPLOCKS 00837 if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) { 00838 LogDesktop(pObject, LD_DEREF_FN_SETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrent()); 00839 } 00840 #endif 00841 00842 ObDereferenceObject(pObject); 00843 00844 return fSuccess; 00845 } 00846 00847 /***************************************************************************\ 00848 * UserScreenAccessCheck 00849 * 00850 * Called from the engine to determine if the thread's desktop is 00851 * active and the process has WINSTA_READSCREEN access. 00852 * 00853 * Note that we may or may not be in USER's critical section when this 00854 * is called. This is OK as long as we don't reference thing belonging 00855 * to other threads. If we did try to enter the critical section here, 00856 * a deadlock may occur between the engine and user. 00857 * 00858 * History: 00859 * 05-20-93 JimA Created. 00860 * 11-22-96 BradG Brought back to life. 00861 \***************************************************************************/ 00862 00863 BOOL FASTCALL UserScreenAccessCheck(VOID) 00864 { 00865 UserAssert(PtiCurrentShared() != NULL); 00866 00867 return ( 00868 PtiCurrentShared() != NULL && PtiCurrentShared()->rpdesk == grpdeskRitInput && 00869 (W32GetCurrentProcess()->W32PF_Flags & (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)) == 00870 (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)); 00871 }

Generated on Sat May 15 19:41:45 2004 for test by doxygen 1.3.7