/*++ Copyright (c) 1996 Microsoft Corporation Module Name: misc.cpp Abstract: SCE Engine miscellaneous APIs Author: Jin Huang (jinhuang) 23-Jun-1997 created --*/ #include "headers.h" #include "serverp.h" #include #include #include #include #pragma hdrstop extern "C" { #include "dumpnt.h" } //#define SCE_DBG 1 NTSTATUS ScepGetLsaDomainInfo( PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo, PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo ); DWORD ScepGetEnvVarsFromProfile( IN PWSTR UserProfileName, IN PCWSTR VarName1, IN PCWSTR VarName2 OPTIONAL, OUT PWSTR *StrValue ); NTSTATUS ScepOpenSamDomain( IN ACCESS_MASK ServerAccess, IN ACCESS_MASK DomainAccess, OUT PSAM_HANDLE pServerHandle, OUT PSAM_HANDLE pDomainHandle, OUT PSID *DomainSid, OUT PSAM_HANDLE pBuiltinDomainHandle OPTIONAL, OUT PSID *BuiltinDomainSid OPTIONAL ) /* Routine Description This routine opens the local SAM server for account domain and builtin domain. The domain handles and their SIDs are returned. */ { NTSTATUS NtStatus; PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo=NULL; PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo=NULL; UNICODE_STRING AccountDomainName; OBJECT_ATTRIBUTES ObjectAttributes; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; if ( !pServerHandle || !pDomainHandle || !DomainSid ) { return(SCESTATUS_INVALID_PARAMETER); } // // initialize output buffers // *pServerHandle = NULL; *pDomainHandle = NULL; *DomainSid = NULL; if ( pBuiltinDomainHandle ) { *pBuiltinDomainHandle = NULL; } if ( BuiltinDomainSid ) { *BuiltinDomainSid = NULL; } // // Get information for the account domain // NtStatus = ScepGetLsaDomainInfo( &PolicyAccountDomainInfo, &PolicyPrimaryDomainInfo ); if (!NT_SUCCESS(NtStatus)) { return( NtStatus ); } AccountDomainName = PolicyAccountDomainInfo->DomainName; // // Connect to the local SAM server // InitializeObjectAttributes( &ObjectAttributes, NULL, 0, 0, NULL ); NtStatus = SamConnect( NULL, // ServerName (Local machine) pServerHandle, ServerAccess, &ObjectAttributes ); if ( NT_SUCCESS(NtStatus) ) { // // Lookup the DomainSid for AccountDomainName // NtStatus = SamLookupDomainInSamServer( *pServerHandle, &AccountDomainName, DomainSid ); if ( NT_SUCCESS(NtStatus) ) { // // open the account domain // NtStatus = SamOpenDomain( *pServerHandle, DomainAccess, *DomainSid, pDomainHandle ); if ( NT_SUCCESS(NtStatus) && BuiltinDomainSid != NULL ) { // // build the builtin domain sid // NtStatus = RtlAllocateAndInitializeSid( &NtAuthority, 1, SECURITY_BUILTIN_DOMAIN_RID, 0, 0, 0, 0, 0, 0, 0, BuiltinDomainSid ); if ( NT_SUCCESS(NtStatus) && pBuiltinDomainHandle != NULL ) { // // open the builtin domain // NtStatus = SamOpenDomain( *pServerHandle, DomainAccess, *BuiltinDomainSid, pBuiltinDomainHandle ); } } } } // // free memory and clean up // if ( PolicyAccountDomainInfo != NULL ) { LsaFreeMemory( PolicyAccountDomainInfo ); } if ( PolicyPrimaryDomainInfo != NULL ) { LsaFreeMemory( PolicyPrimaryDomainInfo ); } if ( !NT_SUCCESS(NtStatus)) { SamCloseHandle( *pDomainHandle ); *pDomainHandle = NULL; if ( pBuiltinDomainHandle ) { SamCloseHandle( *pBuiltinDomainHandle ); *pBuiltinDomainHandle = NULL; } SamCloseHandle( *pServerHandle ); *pServerHandle = NULL; SamFreeMemory(*DomainSid); *DomainSid = NULL; if ( BuiltinDomainSid ) { SamFreeMemory(*BuiltinDomainSid); *BuiltinDomainSid = NULL; } } return(NtStatus); } NTSTATUS ScepLookupNamesInDomain( IN SAM_HANDLE DomainHandle, IN PSCE_NAME_LIST NameList, OUT PUNICODE_STRING *Names, OUT PULONG *RIDs, OUT PSID_NAME_USE *Use, OUT PULONG CountOfName ) /* ++ Routine Description: This routine looks up one or more names in the SAM account domain and returns the relative IDs for each name in the list. The name list may be user list, group list, or alias list. Arguments: DomainHandle - SAM handle to the account domain NameList -- The list of names Names - Translated UNICODE_STRING names. The name list must be freed by RIDs -- List of relative IDs for each name Use -- List of type for each name CoutnOfName - The number of names in the list Return value: NTSTATUS -- */ { PSCE_NAME_LIST pUser; ULONG cnt; NTSTATUS NtStatus=ERROR_SUCCESS; PUNICODE_STRING pUnicodeName=NULL; UNICODE_STRING uName; LPTSTR pTemp; // // Count how many names in the list // for (pUser=NameList, cnt=0; pUser != NULL; pUser = pUser->Next) { if ( pUser->Name == NULL ) { continue; } // // note, this may be bigger than supposed to // cnt++; } if ( cnt > 0 ) { // // Allocate memory for UNICODE_STRING names // pUnicodeName = (PUNICODE_STRING)RtlAllocateHeap( RtlProcessHeap(), 0, cnt * sizeof (UNICODE_STRING) ); if ( pUnicodeName == NULL ) { NtStatus = STATUS_NO_MEMORY; cnt = 0; goto Done; } // // Initialize each UNICODE_STRING // for (pUser=NameList, cnt=0; pUser != NULL; pUser = pUser->Next) { if ( pUser->Name == NULL ) { continue; } pTemp = wcschr(pUser->Name, L'\\'); if ( pTemp ) { uName.Buffer = pUser->Name; uName.Length = ((USHORT)(pTemp-pUser->Name))*sizeof(TCHAR); if ( !ScepIsDomainLocal(&uName) ) { ScepLogOutput3(1, 0, SCEDLL_NO_MAPPINGS, pUser->Name); continue; } pTemp++; } else { pTemp = pUser->Name; } RtlInitUnicodeString(&(pUnicodeName[cnt]), pTemp); cnt++; } // lookup NtStatus = SamLookupNamesInDomain( DomainHandle, cnt, pUnicodeName, RIDs, Use ); if ( !NT_SUCCESS(NtStatus) ) { RtlFreeHeap(RtlProcessHeap(), 0, pUnicodeName); pUnicodeName = NULL; } } Done: *CountOfName = cnt; *Names = pUnicodeName; return(NtStatus); } NTSTATUS ScepGetLsaDomainInfo( PPOLICY_ACCOUNT_DOMAIN_INFO *PolicyAccountDomainInfo, PPOLICY_PRIMARY_DOMAIN_INFO *PolicyPrimaryDomainInfo ) /*++ Routine Description: This routine retrieves ACCOUNT domain information from the LSA policy database. Arguments: PolicyAccountDomainInfo - Receives a pointer to a POLICY_ACCOUNT_DOMAIN_INFO structure containing the account domain info. PolicyPrimaryDomainInfo - Receives a pointer to a POLICY_PRIMARY_DOMAIN_INFO structure containing the Primary domain info. Return Value: STATUS_SUCCESS - Succeeded. Other status values that may be returned from: LsaOpenPolicy() LsaQueryInformationPolicy() --*/ { NTSTATUS Status, IgnoreStatus; LSA_HANDLE PolicyHandle; OBJECT_ATTRIBUTES PolicyObjectAttributes; // // Open the policy database // InitializeObjectAttributes( &PolicyObjectAttributes, NULL, // Name 0, // Attributes NULL, // Root NULL ); // Security Descriptor Status = LsaOpenPolicy( NULL, &PolicyObjectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle ); if ( NT_SUCCESS(Status) ) { // // Query the account domain information // Status = LsaQueryInformationPolicy( PolicyHandle, PolicyAccountDomainInformation, (PVOID *)PolicyAccountDomainInfo ); if ( NT_SUCCESS(Status) ) { // // Query the Primary domain information // Status = LsaQueryInformationPolicy( PolicyHandle, PolicyPrimaryDomainInformation, (PVOID *)PolicyPrimaryDomainInfo ); } IgnoreStatus = LsaClose( PolicyHandle ); ASSERT(NT_SUCCESS(IgnoreStatus)); } return(Status); } VOID ScepConvertLogonHours( IN PSCE_LOGON_HOUR pLogonHours, OUT PUCHAR LogonHourBitMask ) /* ++ Routine Description: This routine converted the logon hour range in hours (for example, 7-20) to logon hour bit mask (for example, 0001 1111 1111 1111 1000 0000, for one day). Arguments: pLogonHours - The logon hour range (in hours) LogonHourBitMask - The converted logon hour bit mask. Each bit represents an hour. There are total 21 bytes (21*8 bits in this argument, which represents a week (7 * 24 = 21 * 8). Return value: None -- */ { PSCE_LOGON_HOUR pTemp; CHAR BitMask[3]={0,0,0}; ULONG j; for ( pTemp=pLogonHours; pTemp != NULL; pTemp=pTemp->Next ) { for (j=pTemp->Start; jEnd; j++) BitMask[j / 8] |= 1 << (j % 8); } for ( j=0; j<7; j++ ) strncpy((CHAR *)&(LogonHourBitMask[j*3]), BitMask,3); } DWORD ScepConvertToSceLogonHour( IN PUCHAR LogonHourBitMask, OUT PSCE_LOGON_HOUR *pLogonHours ) /* ++ Routine Description: This routine converted the logon hour bit mask (for example, 0001 1111 1111 1111 1000 0000 for one day) to SCE_LOGON_HOUR type, which stores the logon hour range (start, end). Arguments: LogonHourBitMask - The logon hour bit mask to convert. Each bit represents an hour. There are total 21 bytes (21*8 bits in this argument, which represents a week (7 * 24 = 21 * 8). pLogonHours - The logon hour range (in hours) Return value: None -- */ { BOOL findStart = TRUE; DWORD i, j, rc=NO_ERROR; DWORD start=0, end=0; LONG value; PSCE_LOGON_HOUR pLogon=NULL; if (pLogonHours == NULL ) return(ERROR_INVALID_PARAMETER); for ( i=3; i<6; i++) for ( j=0; j<8; j++) { if ( findStart ) value = 1; else value = 0; if ( (LogonHourBitMask[i] & (1 << j)) == value ) { if ( findStart ) { start = (i-3)*8 + j; findStart = FALSE; } else { end = (i-3)*8 + j; findStart = TRUE; } if ( findStart ) { // // find a pair // pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR)); if ( pLogon == NULL ) { rc = ERROR_NOT_ENOUGH_MEMORY; return(rc); } pLogon->Start = start; pLogon->End = end; pLogon->Next = *pLogonHours; *pLogonHours = pLogon; pLogon = NULL; } } } if ( findStart == FALSE ) { // find start but not end, which means end=24 end = 24; pLogon = (PSCE_LOGON_HOUR)ScepAlloc( (UINT)0, sizeof(SCE_LOGON_HOUR)); if ( pLogon == NULL ) { rc = ERROR_NOT_ENOUGH_MEMORY; return(rc); } pLogon->Start = start; pLogon->End = end; pLogon->Next = *pLogonHours; *pLogonHours = pLogon; pLogon = NULL; } return(rc); } NTSTATUS ScepGetGroupsForAccount( IN SAM_HANDLE DomainHandle, IN SAM_HANDLE BuiltinDomainHandle, IN SAM_HANDLE UserHandle, IN PSID AccountSid, OUT PSCE_NAME_LIST *GroupList ) /* ++ Routine Description: This routine queries the user's group membership. Arguments: DomainHandle - The SAM handle of the SAM account domain BuiltindomainHandle - The SAM builtin domain handle UserHandle - The SAM account handle for the user AccountSid - The SID for the user GroupList - The list of groups the user belongs to Return value: NTSTATUS -- */ { NTSTATUS NtStatus=ERROR_SUCCESS; ULONG GroupCount=0, AliasCount=0; PULONG Aliases=NULL; PGROUP_MEMBERSHIP GroupAttributes=NULL; PULONG GroupIds=NULL; PUNICODE_STRING Names=NULL; PSID_NAME_USE Use=NULL; DWORD i; NtStatus = SamGetGroupsForUser( UserHandle, &GroupAttributes, &GroupCount ); if ( GroupCount == 0 ) NtStatus = ERROR_SUCCESS; if ( !NT_SUCCESS(NtStatus) ) goto Done; // // See what local groups the account belongs to. // account domain // NtStatus = SamGetAliasMembership( DomainHandle, 1, &AccountSid, &AliasCount, &Aliases ); if ( !NT_SUCCESS(NtStatus) ) goto Done; if ( AliasCount != 0 || GroupCount != 0 ) { // // process each group's name in account domain // GroupIds = (PULONG)ScepAlloc((UINT)0, (GroupCount+AliasCount)*sizeof(ULONG)); if ( GroupIds == NULL ) { NtStatus = STATUS_NO_MEMORY; goto Done; } for ( i=0; i 0 ) { NtStatus = SamLookupIdsInDomain( BuiltinDomainHandle, AliasCount, Aliases, &Names, &Use ); if ( !NT_SUCCESS(NtStatus) ) goto Done; } for ( i=0; iAceCount; i++) { NtStatus = RtlGetAce( pAcl, i, &pAce ); if ( !NT_SUCCESS( NtStatus ) ) break; access = 0; pSid = NULL; switch ( ((PACE_HEADER)pAce)->AceType ) { case ACCESS_ALLOWED_ACE_TYPE: pSid = (PSID)&((PACCESS_ALLOWED_ACE)pAce)->SidStart; access = ((PACCESS_ALLOWED_ACE)pAce)->Mask; if ( EqualSid( AccountSid, pSid ) ) *pUserAccess = &(((PACCESS_ALLOWED_ACE)pAce)->Mask); else if ( EqualSid( EveryoneSid, pSid) ) *pEveryone = &(((PACCESS_ALLOWED_ACE)pAce)->Mask); break; case ACCESS_DENIED_ACE_TYPE: // do not look for denied ace type because it is not used here // pSid = (PSID)&((PACCESS_DENIED_ACE)pAce)->SidStart; // access = ((PACCESS_DENIED_ACE)pAce)->Mask; break; default: break; } if ( *pUserAccess != NULL && *pEveryone != NULL ) // stop the loop because both are found break; } } } // // free EveryoneSid // if (EveryoneSid) { RtlFreeSid(EveryoneSid); EveryoneSid = NULL; } return(NtStatus); } BOOL ScepLastBackSlash( IN PWSTR Name ) { if (Name == NULL ) return(FALSE); if ( Name[wcslen(Name)-1] == L'\\') return(TRUE); else return(FALSE); } DWORD ScepGetUsersHomeDirectory( IN UNICODE_STRING AssignedHomeDir, IN PWSTR UserProfileName, OUT PWSTR *UserHomeDir ) /*++ Routine Description: This routine gets user's default home directory. The home directory is determined 1) if it is assigned in the user's object (user profile), 2) if there is a HomePath environment variable defined for the user, and 3). Harcoded. Arguments: AssignedHomeDir - The home directory explicitly assigned in the user's object. UserProfileName - The user's environment profile name UserHomeDir - The returned home directory for the user Return Value: Win32 error code. --*/ { DWORD Win32rc=NO_ERROR; PWSTR StrValue=NULL; PWSTR SystemRoot=NULL; DWORD DirSize=0; *UserHomeDir = NULL; // // if there is a home directory assigned in the user profile, use it. // if ( AssignedHomeDir.Length > 0 && AssignedHomeDir.Buffer != NULL ) { *UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, AssignedHomeDir.Length+2); if ( *UserHomeDir == NULL ) return(ERROR_NOT_ENOUGH_MEMORY); wcsncpy(*UserHomeDir, AssignedHomeDir.Buffer, AssignedHomeDir.Length/2); return(NO_ERROR); } // // Home directory is NULL in user profile, the HomePath environment // is searched. // Win32rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR ); if ( Win32rc != NO_ERROR ) { ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%"); return(Win32rc); } Win32rc = ScepGetEnvVarsFromProfile( UserProfileName, L"HomePath", NULL, &StrValue ); if ( Win32rc == NO_ERROR && StrValue != NULL ) { *UserHomeDir = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (wcslen(StrValue)+3)*sizeof(WCHAR)); if ( *UserHomeDir == NULL ) Win32rc = ERROR_NOT_ENOUGH_MEMORY; else { swprintf(*UserHomeDir+1, L":%s", StrValue); **UserHomeDir = SystemRoot[0]; } } else Win32rc = NO_ERROR; // do not care if can't get environment variable's value if ( SystemRoot != NULL ) ScepFree(SystemRoot); if ( StrValue != NULL ) ScepFree( StrValue ); return(Win32rc); } DWORD ScepGetEnvVarsFromProfile( IN PWSTR UserProfileName, IN PCWSTR VarName1, IN PCWSTR VarName2 OPTIONAL, OUT PWSTR *StrValue ) { DWORD rc; DWORD RegType; rc = SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, NULL); if ( rc == ERROR_SUCCESS ) { rc = RegLoadKey(HKEY_USERS, L"TEMP", UserProfileName); if ( rc == ERROR_SUCCESS ) { rc = ScepRegQueryValue( HKEY_USERS, L"TEMP\\Environment", VarName1, (PVOID *)StrValue, &RegType ); if ( rc != ERROR_SUCCESS && VarName2 != NULL ) { rc = ScepRegQueryValue( HKEY_USERS, L"TEMP\\Environment", VarName2, (PVOID *)StrValue, &RegType ); } RegUnLoadKey(HKEY_USERS, L"TEMP"); } else { //if ( rc == ERROR_ALREADY_IN_USE) { // // this profile already in use. Open the one in HKEY_CURRENT_USER // rc = ScepRegQueryValue( HKEY_CURRENT_USER, L"Environment", VarName1, (PVOID *)StrValue, &RegType ); if ( rc != ERROR_SUCCESS && VarName2 != NULL ) { rc = ScepRegQueryValue( HKEY_CURRENT_USER, L"Environment", VarName2, (PVOID *)StrValue, &RegType ); } } SceAdjustPrivilege(SE_RESTORE_PRIVILEGE, FALSE, NULL); } return(rc); } DWORD ScepGetUsersTempDirectory( IN PWSTR UserProfileName, OUT PWSTR *UserTempDir ) /*++ Routine Description: This routine returns the user's temp directory. Temp directory for a user is determined 1) environment variable "TEMP" or "TMP" defined in the user's environment profile, or 2) Harcoded to %systemDrive%\TEMP Arguments: UserProfileName - The user's environment profile name UserTempDir - The returned temp directory for the user Return Value: Win32 error code --*/ { DWORD rc=NO_ERROR; PWSTR StrValue=NULL; PWSTR SystemRoot=NULL; DWORD DirSize=0; // // query the TEMP/TMP environment variable(s) // if ( UserProfileName != NULL ) { ScepGetEnvVarsFromProfile( UserProfileName, L"TEMP", L"TMP", &StrValue ); } if ( StrValue != NULL ) { // // find the setting for temp dir // if ( wcsstr(_wcsupr(StrValue), L"%") != NULL ) { rc = ScepTranslateFileDirName( StrValue, UserTempDir ); } if ( rc == NO_ERROR ) { ScepFree(StrValue); } else *UserTempDir = StrValue; StrValue = NULL; } else { // // hardcoded to %SystemDrive%\TEMP // rc = ScepGetNTDirectory( &SystemRoot, &DirSize, SCE_FLAG_WINDOWS_DIR ); if ( rc != NO_ERROR ) { ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_INFO, L"%WinDir%"); return(rc); } *UserTempDir = (PWSTR)ScepAlloc( 0, 8*sizeof(WCHAR)); if ( *UserTempDir == NULL ) rc = ERROR_NOT_ENOUGH_MEMORY; else { swprintf(*UserTempDir+1, L":\\TEMP"); **UserTempDir = SystemRoot[0]; } } if (SystemRoot != NULL ) ScepFree(SystemRoot); return(rc); } SCESTATUS ScepGetRegKeyCase( IN PWSTR ObjName, IN DWORD BufOffset, IN DWORD BufLen ) { DWORD Win32rc; HKEY hKey=NULL; PWSTR Buffer=NULL; TCHAR Buffer1[MAX_PATH]; DWORD BufSize, index; FILETIME LastWriteTime; if ( BufOffset <= 0 || BufLen <= 0 ) { _wcsupr(ObjName); return(SCESTATUS_SUCCESS); } Buffer = (PWSTR)ScepAlloc(LMEM_ZEROINIT, BufOffset*sizeof(WCHAR)); if ( Buffer != NULL ) { wcsncpy(Buffer, ObjName, BufOffset-1); Win32rc = ScepOpenRegistryObject( SE_REGISTRY_KEY, Buffer, KEY_READ, &hKey ); if ( Win32rc == NO_ERROR ) { index = 0; // // enumerate all subkeys of the key // do { memset(Buffer1, '\0', MAX_PATH*sizeof(WCHAR)); BufSize = MAX_PATH; Win32rc = RegEnumKeyEx(hKey, index, Buffer1, &BufSize, NULL, NULL, NULL, &LastWriteTime); if ( Win32rc == ERROR_SUCCESS ) { index++; // // find if the subkey matches the object name // if ( _wcsicmp(ObjName+BufOffset, Buffer1) == 0 ) break; } } while ( Win32rc != ERROR_NO_MORE_ITEMS ); RegCloseKey(hKey); if ( Win32rc == ERROR_SUCCESS ) { // // find it // if ( BufSize > BufLen ) BufSize = BufLen; wcsncpy(ObjName+BufOffset, Buffer1, BufSize); *(ObjName+BufOffset+BufSize) = L'\0'; } else if ( Win32rc == ERROR_NO_MORE_ITEMS) { // // does not find it // Win32rc = ERROR_FILE_NOT_FOUND; } } ScepFree(Buffer); } else Win32rc = ERROR_NOT_ENOUGH_MEMORY; if ( Win32rc != NO_ERROR ) { // // convert everything to uppercase // _wcsupr(ObjName+BufOffset); } return(ScepDosErrorToSceStatus(Win32rc)); } SCESTATUS ScepGetFileCase( IN PWSTR ObjName, IN DWORD BufOffset, IN DWORD BufLen ) { intptr_t hFile; struct _wfinddata_t FileInfo; hFile = _wfindfirst(ObjName, &FileInfo); if ( hFile != -1 ) { wcsncpy(ObjName+BufOffset, FileInfo.name, BufLen); _findclose(hFile); } else return(ScepDosErrorToSceStatus(GetLastError())); return(SCESTATUS_SUCCESS); } SCESTATUS ScepGetGroupCase( IN OUT PWSTR GroupName, IN DWORD Length ) { NTSTATUS NtStatus; SAM_HANDLE ServerHandle=NULL, DomainHandle=NULL, BuiltinDomainHandle=NULL, ThisDomain=NULL, GroupHandle=NULL; PSID DomainSid=NULL, BuiltinDomainSid=NULL; UNICODE_STRING Name; PULONG GrpId=NULL; PSID_NAME_USE GrpUse=NULL; PVOID pNameInfo=NULL; NtStatus = ScepOpenSamDomain( SAM_SERVER_READ | SAM_SERVER_EXECUTE, DOMAIN_READ | DOMAIN_EXECUTE, &ServerHandle, &DomainHandle, &DomainSid, &BuiltinDomainHandle, &BuiltinDomainSid ); if ( NT_SUCCESS(NtStatus) ) { RtlInitUnicodeString(&Name, GroupName); NtStatus = SamLookupNamesInDomain( DomainHandle, 1, &Name, &GrpId, &GrpUse ); ThisDomain = DomainHandle; if ( NtStatus == STATUS_NONE_MAPPED ) { // // not found in account domain. Lookup in the builtin domain // NtStatus = SamLookupNamesInDomain( BuiltinDomainHandle, 1, &Name, &GrpId, &GrpUse ); ThisDomain=BuiltinDomainHandle; } if ( NT_SUCCESS(NtStatus) ) { switch ( GrpUse[0] ) { case SidTypeGroup: NtStatus = SamOpenGroup( ThisDomain, GROUP_READ | GROUP_EXECUTE, GrpId[0], &GroupHandle ); if ( NT_SUCCESS(NtStatus) ) { NtStatus = SamQueryInformationGroup( GroupHandle, GroupNameInformation, &pNameInfo ); } break; case SidTypeAlias: NtStatus = SamOpenAlias( ThisDomain, ALIAS_READ | ALIAS_EXECUTE, GrpId[0], &GroupHandle ); if ( NT_SUCCESS(NtStatus) ) { NtStatus = SamQueryInformationAlias( GroupHandle, AliasNameInformation, &pNameInfo ); } break; default: NtStatus = STATUS_NONE_MAPPED; break; } if ( NT_SUCCESS(NtStatus) ) { // // get name information // if ( ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer != NULL && ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length > 0 ) { if ( Length > (DWORD)(((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2) ) { wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Length/2); } else { wcsncpy(GroupName, ((PGROUP_NAME_INFORMATION)pNameInfo)->Name.Buffer, Length); } } else NtStatus = STATUS_NONE_MAPPED; SamFreeMemory(pNameInfo); } if (GroupHandle) SamCloseHandle(GroupHandle); SamFreeMemory(GrpId); SamFreeMemory(GrpUse); } SamCloseHandle( DomainHandle ); SamCloseHandle( BuiltinDomainHandle ); SamCloseHandle( ServerHandle ); SamFreeMemory(DomainSid); RtlFreeSid(BuiltinDomainSid); } return(ScepDosErrorToSceStatus( RtlNtStatusToDosError(NtStatus) )); } VOID ScepPrintSecurityDescriptor( IN PSECURITY_DESCRIPTOR pSecurityDescriptor, IN BOOL ToDumpSD ) { if (pSecurityDescriptor != NULL) { if ( ToDumpSD ) DumpSECURITY_DESCRIPTOR(pSecurityDescriptor); else printf("Security Descriptor\n"); } }