/*++ Copyright (c) 1996 Microsoft Corporation Module Name: pfset.cpp Abstract: Routines to set info to the jet database. Author: Jin Huang (jinhuang) 28-Oct-1996 Revision History: --*/ #include "headers.h" #include "serverp.h" #include "pfp.h" #include "regvalue.h" #pragma hdrstop //#define SCE_DBG 1 SCESTATUS ScepOpenPrevPolicyContext( IN PSCECONTEXT hProfile, OUT PSCECONTEXT *phPrevProfile ); SCESTATUS ScepClosePrevPolicyContext( IN OUT PSCECONTEXT *phProfile ); SCESTATUS ScepStartANewSection( IN PSCECONTEXT hProfile, IN OUT PSCESECTION *hSection, IN SCEJET_TABLE_TYPE ProfileType, IN PCWSTR SectionName ) /* ++ Routine Description: This routine open a JET section by Name. If the section exists, it is opened, else it is created. Arguments: hProfile - The JET database handle hSection - the JET section handle to return ProfileType - the table to open SectionName - the JET section name Return Value: SCESTATUS_SUCCESS SCESTATUS returned from SceJetCloseSection, SceJetAddSection, SceJetOpenSection -- */ { SCESTATUS rc=SCESTATUS_SUCCESS; DOUBLE SectionID; if ( *hSection != NULL ) { // // free the previous used section // rc = SceJetCloseSection( hSection, FALSE ); } if ( rc == SCESTATUS_SUCCESS ) { // // SceJetAddSection will seek for the section name first. // if a match is found, the section id is returned, else add it. // this is good for SAP profile. // rc = SceJetAddSection( hProfile, SectionName, &SectionID ); if ( rc == SCESTATUS_SUCCESS ) { rc = SceJetOpenSection( hProfile, SectionID, ProfileType, hSection ); } } return( rc ); } SCESTATUS ScepCompareAndSaveIntValue( IN PSCESECTION hSection, IN PWSTR Name, IN BOOL bReplaceExistOnly, IN DWORD BaseValue, IN DWORD CurrentValue ) /* ++ Routine Description: This routine compares DWORD value system settings with the baseline profile settings. If there is mismatch or unknown, the entry is saved in the SAP profile. Arguments: hSection - The JET section context Name - The entry name BaseLine- The baseline profile value to compare with CurrentValue - The current system setting (DWORD value) Return Value: SCESTATUS_SUCCESS SCESTATUS_INVALID_PARAMETER SCESTATUS returned from SceJetSetLine -- */ { SCESTATUS rc; TCHAR StrValue[12]; if ( Name == NULL ) return(SCESTATUS_INVALID_PARAMETER); if ( CurrentValue == SCE_NO_VALUE ) { return(SCESTATUS_SUCCESS); } if ( ( CurrentValue == BaseValue) && ( BaseValue != SCE_NO_VALUE) && ( BaseValue != SCE_SNAPSHOT_VALUE) ) { return(SCESTATUS_SUCCESS); } if ( bReplaceExistOnly && (BaseValue == SCE_NO_VALUE) ) { return(SCESTATUS_SUCCESS); } memset(StrValue, '\0', 24); // // either mismatched/unknown // Save this entry // swprintf(StrValue, L"%d", CurrentValue); rc = SceJetSetLine( hSection, Name, FALSE, StrValue, wcslen(StrValue)*2, 0); switch ( BaseValue ) { case SCE_SNAPSHOT_VALUE: ScepLogOutput2(2, 0, StrValue); break; case SCE_NO_VALUE: if ( CurrentValue == SCE_ERROR_VALUE ) { ScepLogOutput3(2, 0, SCEDLL_STATUS_ERROR, Name); } else { ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name); } break; default: ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name); break; } #ifdef SCE_DBG wprintf(L"rc=%d, Section: %d, %s=%d\n", rc, (DWORD)(hSection->SectionID), Name, CurrentValue); #endif return(rc); } SCESTATUS ScepCompareAndSaveStringValue( IN PSCESECTION hSection, IN PWSTR Name, IN PWSTR BaseValue, IN PWSTR CurrentValue, IN DWORD CurrentLen ) /* ++ Routine Description: This routine compares system settings in string with the baseline profile settings. If there is mismatch or unknown, the entry is saved in the SAP profile. Arguments: hSection - The section handle Name - The entry name BaseLine- The baseline profile value to compare with CurrentValue - The current system setting CurrentLen - The length of the current setting Return Value: SCESTATUS_SUCCESS SCESTATUS_INVALID_PARAMETER SCESTATUS returned from SceJetSetLine -- */ { SCESTATUS rc; if ( Name == NULL ) return(SCESTATUS_INVALID_PARAMETER); if ( CurrentValue == NULL ) return(SCESTATUS_SUCCESS); rc = SceJetSetLine( hSection, Name, FALSE, CurrentValue, CurrentLen, 0); if ( BaseValue ) { if ( (ULONG_PTR)BaseValue == SCE_SNAPSHOT_VALUE ) { ScepLogOutput2(2, 0, CurrentValue); } else { ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name); } } else { ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name); } #ifdef SCE_DBG wprintf(L"rc=%d, Section: %d, %s=%s\n", rc, (DWORD)(hSection->SectionID), Name, CurrentValue); #endif return(rc); } SCESTATUS ScepSaveObjectString( IN PSCESECTION hSection, IN PWSTR Name, IN BOOL IsContainer, IN BYTE Flag, IN PWSTR Value OPTIONAL, IN DWORD ValueLen ) /* ++ Routine Description: This routine writes registry/file settings to the JET section. Registry/ file setting includes a flag (mismatch/unknown) and the security descriptor in text format. The object setting is saved in the format of 1 byte flag followed by the Value. Arguments: hSection - the JET section handle Name - The entry name IsContainer - TRUE = The object is a container FALSE = The object is not a container Flag - the flag for object's setting 1 - Mismatch 0 - Unknown Value - The security descriptor in text ValueLen - the length of the text security descriptor Return Value: SCESTATUS_SUCCESS SCESTATUS_INVALID_PARAMETER SCESTATUS returned from SceJetSetLine -- */ { SCESTATUS rc; DWORD Len; PWSTR ValueToSet=NULL; if ( hSection == NULL || Name == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( Value != NULL ) Len = ( ValueLen+1)*sizeof(WCHAR); else Len = sizeof(WCHAR); ValueToSet = (PWSTR)ScepAlloc( (UINT)0, Len+sizeof(WCHAR) ); if ( ValueToSet == NULL ) return(SCESTATUS_NOT_ENOUGH_RESOURCE); // // The first byte is the flag, the second byte is IsContainer (1,0) // *((BYTE *)ValueToSet) = Flag; *((CHAR *)ValueToSet+1) = IsContainer ? '1' : '0'; if ( Value != NULL ) { wcscpy(ValueToSet+1, Value); ValueToSet[ValueLen+1] = L'\0'; //terminate this string } else { ValueToSet[1] = L'\0'; } rc = SceJetSetLine( hSection, Name, FALSE, ValueToSet, Len, 0); switch ( Flag ) { case SCE_STATUS_CHILDREN_CONFIGURED: case SCE_STATUS_NOT_CONFIGURED: ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name); break; case SCE_STATUS_ERROR_NOT_AVAILABLE: ScepLogOutput3(2, 0, SCEDLL_STATUS_ERROR, Name); break; case SCE_STATUS_GOOD: ScepLogOutput3(2, 0, SCEDLL_STATUS_MATCH, Name); break; case SCE_STATUS_NEW_SERVICE: ScepLogOutput3(2, 0, SCEDLL_STATUS_NEW, Name); break; case SCE_STATUS_NO_ACL_SUPPORT: ScepLogOutput3(2, 0, SCEDLL_STATUS_NOACL, Name); break; default: ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name); break; } #ifdef SCE_DBG wprintf(L"rc=%d, Section: %d, %s=%s\n", rc, (DWORD)(hSection->SectionID), Name, ValueToSet); #endif ScepFree( ValueToSet ); return( rc ); } SCESTATUS ScepWriteNameListValue( IN LSA_HANDLE LsaPolicy OPTIONAL, IN PSCESECTION hSection, IN PWSTR Name, IN PSCE_NAME_LIST NameList, IN DWORD dwWriteOption, IN INT Status ) /* ++ Routine Description: This routine writes a key with a list of value to the JET section. The list of values is saved in a MULTI-SZ format which is separated by a NULL char and terminated by 2 NULLs. If the list is NULL, nothing is saved unless SaveEmptyList is set to TRUE, where a NULL value is saved with the key. Arguments: hSection - the JET hsection handle Name - The key name NameList - the list of values SaveEmptyList - TRUE = save NULL value if the list is empty FALSE = DO NOT save if the list is empty Return Value: SCESTATUS_SUCCESS SCESTATUS_NOT_ENOUGH_RESOURCE SCESTATUS returned from SceJetSetLine -- */ { SCESTATUS rc=SCESTATUS_SUCCESS; DWORD TotalSize=0; PWSTR Value=NULL; PSCE_NAME_LIST pName; PWSTR pTemp=NULL; DWORD Len; DWORD i=0,j; DWORD cntAllocated=0; SCE_TEMP_NODE *tmpArray=NULL, *pa=NULL; PWSTR SidString = NULL; for ( pName=NameList; pName != NULL; pName = pName->Next ) { if ( pName->Name == NULL ) { continue; } if ( dwWriteOption & SCE_WRITE_CONVERT ) { if ( i >= cntAllocated ) { // // array is not enough, reallocate // tmpArray = (SCE_TEMP_NODE *)ScepAlloc(LPTR, (cntAllocated+16)*sizeof(SCE_TEMP_NODE)); if ( tmpArray ) { // // move pointers from the old array to the new array // if ( pa ) { for ( j=0; jName, L'\\') ) { // // check if the name has a '\' in it, it should be translated to // *SID // pTemp = NULL; ScepConvertNameToSidString(LsaPolicy, pName->Name, FALSE, &pTemp, &Len); if ( pTemp ) { pa[i].Name = pTemp; pa[i].bFree = TRUE; } else { pa[i].Name = pName->Name; pa[i].bFree = FALSE; Len= wcslen(pName->Name); } } else if (dwWriteOption & SCE_WRITE_LOCAL_TABLE && ScepLookupWellKnownName( pName->Name, LsaPolicy, &SidString ) ) { pa[i].Name = SidString; pa[i].bFree = TRUE; Len = wcslen(SidString); } else { pa[i].Name = pName->Name; pa[i].bFree = FALSE; Len = wcslen(pName->Name); } pa[i].Len = Len; TotalSize += Len + 1; i++; } else { TotalSize += wcslen(pName->Name)+1; } } TotalSize ++; if ( SCESTATUS_SUCCESS == rc ) { if ( TotalSize > 1 ) { Value = (PWSTR)ScepAlloc( 0, (TotalSize+1)*sizeof(WCHAR)); if ( Value == NULL ) rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } if ( SCESTATUS_SUCCESS == rc ) { if ( TotalSize > 1 ) { pTemp = Value; if ( dwWriteOption & SCE_WRITE_CONVERT ) { for (j=0; jNext ) { if ( pName->Name == NULL ) { continue; } if ( Status == 3 ) { ScepLogOutput2(2, 0, pName->Name); } Len = wcslen(pName->Name); wcsncpy(pTemp, pName->Name, Len); pTemp += Len; *pTemp = L'\0'; pTemp++; } } *pTemp = L'\0'; } else TotalSize = 0; if ( TotalSize > 0 || (dwWriteOption & SCE_WRITE_EMPTY_LIST) ) { rc = SceJetSetLine( hSection, Name, FALSE, Value, TotalSize*sizeof(WCHAR), 0 ); switch ( Status ) { case 1: ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name); break; case 3: // no analyze, already printed break; case 2: ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name); break; } #ifdef SCE_DBG if ( Value != NULL ) wprintf(L"rc=%d, Section: %d, %s=%s\n", rc, (DWORD)(hSection->SectionID), Name, Value); else wprintf(L"rc=%d, Section: %d, %s=", rc, (DWORD)(hSection->SectionID), Name); #endif } if ( Value != NULL ) ScepFree(Value); } if ( pa ) { for ( j=0; jNext ) { // // Privilege value is stored in 2 bytes // TotalSize += 2; if ( pName->Name != NULL) TotalSize += wcslen(pName->Name); TotalSize ++; } TotalSize ++; if ( TotalSize > 1 ) { Value = (PWSTR)ScepAlloc( 0, (TotalSize+1)*sizeof(WCHAR)); if ( Value == NULL ) return(SCESTATUS_NOT_ENOUGH_RESOURCE); pTemp = Value; for ( pName=NameList; pName != NULL; pName = pName->Next ) { swprintf(pTemp, L"%02d", pName->Status); pTemp += 2; if ( pName->Name != NULL ) { Len = wcslen(pName->Name); wcsncpy(pTemp, pName->Name, Len); pTemp += Len; } *pTemp = L'\0'; pTemp++; } *pTemp = L'\0'; } else TotalSize = 0; if ( TotalSize > 0 || SaveEmptyList ) { rc = SceJetSetLine( hSection, Name, FALSE, Value, TotalSize*sizeof(WCHAR), 0 ); if ( Status == 1 ) ScepLogOutput3(2, 0, SCEDLL_STATUS_MISMATCH, Name); else if ( Status == 2 ) { ScepLogOutput3(2, 0, SCEDLL_STATUS_NC, Name); } #ifdef SCE_DBG wprintf(L"rc=%d, Section: %d, %s=%s\n", rc, (DWORD)(hSection->SectionID), Name, Value); #endif if ( Value != NULL ) ScepFree(Value); } return(rc); } SCESTATUS ScepWriteSecurityDescriptorValue( IN PSCESECTION hSection, IN PWSTR Name, IN PSECURITY_DESCRIPTOR pSD, IN SECURITY_INFORMATION SeInfo ) /* ++ Routine Description: This routine writes a key with security descriptor value to the JET section. The security descriptor is converted into text format based on the secrurity information passed in. Arguments: hSection - the JET hsection handle Name - The key name pSD - The security descriptor SeInfo - the part of the security information to save Return Value: SCESTATUS_SUCCESS SCESTATUS_NOT_ENOUGH_RESOURCE SCESTATUS returned from SceJetSetLine -- */ { SCESTATUS rc=SCESTATUS_SUCCESS; PWSTR SDspec=NULL; ULONG SDsize = 0; if ( hSection == NULL || Name == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( pSD != NULL && SeInfo != 0 ) { rc = ConvertSecurityDescriptorToText ( pSD, SeInfo, &SDspec, &SDsize ); if ( rc == NO_ERROR ) { rc = ScepCompareAndSaveStringValue( hSection, Name, NULL, SDspec, SDsize*sizeof(WCHAR) ); ScepFree(SDspec); } } #ifdef SCE_DBG wprintf(L"SD==>rc=%d, Section: %d, %s\n", rc, (DWORD)(hSection->SectionID), Name); #endif return(rc); } SCESTATUS ScepDuplicateTable( IN PSCECONTEXT hProfile, IN SCEJET_TABLE_TYPE TableType, IN LPSTR DupTableName, OUT PSCE_ERROR_LOG_INFO *pErrlog ) /* ++ Routine Description: This routine copies table structure and data from a SCP/SMP/SAP table to a table specified by DupTableName. This is used for the SAP table backup. Arguments: hProfile - the JET database handle TableType - the table type -SCEJET_TABLE_SCP SCEJET_TABLE_SAP SCEJET_TABLE_SMP DupTableName - The new table's name pErrlog - the error list Return Value: SCESTATUS_SUCCESS -- */ { JET_ERR JetErr; SCESTATUS rc; SCECONTEXT hProfile2; PSCESECTION hSection1=NULL; PSCESECTION hSection2=NULL; DOUBLE SectionID=0, SaveID=0; DWORD Actual; PWSTR KeyName=NULL; PWSTR Value=NULL; DWORD KeyLen=0; DWORD ValueLen=0; if ( hProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } // // Create a SCP section handle. the section ID is a dummy one // rc = SceJetOpenSection( hProfile, (DOUBLE)1, TableType, &hSection1 ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc), pErrlog, SCEERR_OPEN, L"SectionID 1"); return(rc); } memset(&hProfile2, '\0', sizeof(SCECONTEXT)); hProfile2.JetSessionID = hProfile->JetSessionID; hProfile2.JetDbID = hProfile->JetDbID; // // Delete the dup table then create it // SceJetDeleteTable( &hProfile2, DupTableName, TableType ); rc = SceJetCreateTable( &hProfile2, DupTableName, TableType, SCEJET_CREATE_IN_BUFFER, NULL, NULL ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc), pErrlog, SCEERR_CREATE, L"backup table"); goto Cleanup; } // // Move to the first line of the SCP table // JetErr = JetMove(hSection1->JetSessionID, hSection1->JetTableID, JET_MoveFirst, 0); while (JetErr == SCESTATUS_SUCCESS ) { // // get section ID // JetErr = JetRetrieveColumn( hSection1->JetSessionID, hSection1->JetTableID, hSection1->JetColumnSectionID, (void *)&SectionID, 8, &Actual, 0, NULL ); if ( JetErr != JET_errSuccess ) { ScepBuildErrorLogInfo( ERROR_READ_FAULT, pErrlog, SCEERR_QUERY_INFO, L"sectionID"); rc = SceJetJetErrorToSceStatus(JetErr); break; } #ifdef SCE_DBG printf("SectionID=%d, JetErr=%d\n", (DWORD)SectionID, JetErr); #endif // // Prepare this Scep section // if ( SectionID != SaveID ) { SaveID = SectionID; // // Prepare this section // rc = SceJetOpenSection( &hProfile2, SectionID, TableType, &hSection2 ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc), pErrlog, SCEERR_OPEN_ID, (DWORD)SectionID); break; } } // // get buffer size for key and value // rc = SceJetGetValue( hSection1, SCEJET_CURRENT, NULL, NULL, 0, &KeyLen, NULL, 0, &ValueLen); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_QUERY_VALUE, L"current row"); break; } // // allocate memory // if ( KeyLen > 0 ) { KeyName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, KeyLen+2); if ( KeyName == NULL ) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; break; } } if ( ValueLen > 0 ) { Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2); if ( Value == NULL ) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; break; } } // // get key and value // rc = SceJetGetValue( hSection1, SCEJET_CURRENT, NULL, KeyName, KeyLen, &KeyLen, Value, ValueLen, &ValueLen); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_QUERY_VALUE, L"current row"); break; } #ifdef SCE_DBG wprintf(L"\t%s=%s, rc=%d\n", KeyName, Value, rc); #endif // // set this line to the dup table // rc = SceJetSetLine( hSection2, KeyName, TRUE, Value, ValueLen, 0 ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_WRITE_INFO, KeyName); break; } ScepFree(KeyName); KeyName = NULL; ScepFree(Value); Value = NULL; // // Move to next line in the SCP table // JetErr = JetMove(hSection1->JetSessionID, hSection1->JetTableID, JET_MoveNext, 0); } Cleanup: if ( rc != SCESTATUS_SUCCESS ) { // // error occurs. Clean up the dup table // #ifdef SCE_DBG printf("Error occurs. delete the dup table.\n"); #endif SceJetDeleteTable( &hProfile2, DupTableName, TableType ); } if ( KeyName != NULL ) ScepFree(KeyName); if ( Value != NULL ) ScepFree(Value); SceJetCloseSection(&hSection1, TRUE); SceJetCloseSection(&hSection2, TRUE); return(rc); } SCESTATUS ScepAddToPrivList( IN PSCE_NAME_STATUS_LIST *pPrivList, IN DWORD Rights, IN PWSTR Name, IN DWORD Len ) /* ++ Routine Description: This routine adds a privilege with optional group name to the list of privilege assignments Arguments: pPrivList - the privilege list to add to. The structure of this list is Status -- The privilege value Name -- The group's name where the priv is assigned if Name is NULL, the privilege is directly assigned Rights - The privilege(s) assigned through group Name Name - The group's name Len - The group's name length Return Value: SCESTATUS_SUCCESS SCESTATUS_INVALID_PARAMETER SCESTATUS_NOT_ENOUGH_RESOURCE -- */ { PSCE_NAME_STATUS_LIST pTemp; LONG i; if ( pPrivList == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } for ( i=31; i>=0; i-- ) if ( Rights & (1 << i) ) { for ( pTemp=*pPrivList; pTemp != NULL; pTemp = pTemp->Next ) { if ( (DWORD)i == pTemp->Status ) break; } if ( pTemp == NULL ) { // // add this one // pTemp = (PSCE_NAME_STATUS_LIST)ScepAlloc( LMEM_ZEROINIT, sizeof(SCE_NAME_STATUS_LIST)); if ( pTemp == NULL ) return(SCESTATUS_NOT_ENOUGH_RESOURCE); if ( Name != NULL && Len > 0 ) { pTemp->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR)); if ( pTemp->Name == NULL) { ScepFree(pTemp); return(SCESTATUS_NOT_ENOUGH_RESOURCE); } wcsncpy(pTemp->Name, Name, Len); } #ifdef SCE_DBG wprintf(L"Add %d %s to privilege list\n", i, pTemp->Name); #endif pTemp->Status = i; pTemp->Next = *pPrivList; *pPrivList = pTemp; pTemp = NULL; } } return(SCESTATUS_SUCCESS); } SCESTATUS ScepOpenPrevPolicyContext( IN PSCECONTEXT hProfile, OUT PSCECONTEXT *phPrevProfile ) { if ( hProfile == NULL || phPrevProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } *phPrevProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT)); if ( *phPrevProfile == NULL ) { return(SCESTATUS_NOT_ENOUGH_RESOURCE); } memcpy( *phPrevProfile, hProfile, sizeof(SCECONTEXT)); DWORD ScpType = hProfile->Type; (*phPrevProfile)->Type &= ~(SCEJET_MERGE_TABLE_2 | SCEJET_MERGE_TABLE_1); SCESTATUS rc; // // now open the previous policy table // if ( ( ScpType & SCEJET_MERGE_TABLE_2 ) ) { // // the second table is the current one // so the first table is the previous one // rc = SceJetOpenTable( *phPrevProfile, "SmTblScp", SCEJET_TABLE_SCP, SCEJET_OPEN_READ_ONLY, NULL ); (*phPrevProfile)->Type |= SCEJET_MERGE_TABLE_1; } else { rc = SceJetOpenTable( *phPrevProfile, "SmTblScp2", SCEJET_TABLE_SCP, SCEJET_OPEN_READ_ONLY, NULL ); (*phPrevProfile)->Type |= SCEJET_MERGE_TABLE_2; } /* if ( SCESTATUS_SUCCESS == rc ) { JET_COLUMNID ColGpoID = (JET_COLUMNID)JET_tableidNil; JET_ERR JetErr; JET_COLUMNDEF ColumnGpoIDDef; JetErr = JetGetTableColumnInfo( (*phPrevProfile)->JetSessionID, (*phPrevProfile)->JetScpID, "GpoID", (VOID *)&ColumnGpoIDDef, sizeof(JET_COLUMNDEF), JET_ColInfo ); if ( JET_errSuccess == JetErr ) { ColGpoID = ColumnGpoIDDef.columnid; } // else ignore error // temp storage for the column ID (*phPrevProfile)->JetSapValueID = ColGpoID; } */ if ( rc != SCESTATUS_SUCCESS ) { LocalFree(*phPrevProfile); *phPrevProfile = NULL; } return(rc); } SCESTATUS ScepClosePrevPolicyContext( IN OUT PSCECONTEXT *phProfile ) { if ( phProfile && *phProfile ) { // // just free the table because all other info are copied from the // current policy context and will be freed there // if ( (*phProfile)->JetScpID != JET_tableidNil ) { if ( (*phProfile)->JetScpID != (*phProfile)->JetSmpID ) { JetCloseTable( (*phProfile)->JetSessionID, (*phProfile)->JetScpID ); } } LocalFree(*phProfile); *phProfile = NULL; } return(SCESTATUS_SUCCESS); } SCESTATUS ScepCopyLocalToMergeTable( IN PSCECONTEXT hProfile, IN DWORD Options, IN DWORD CopyOptions, OUT PSCE_ERROR_LOG_INFO *pErrlog ) /* ++ Routine Description: This routine populate data from SCP table into SMP table. All data except those in the account profiles section(s) in SCP table will be copied over to SMP table. Account profiles section is converted into User List section format. Arguments: hProfile - the JET database handle Return Value: SCESTATUS_SUCCESS -- */ { JET_ERR JetErr; SCESTATUS rc; PSCESECTION hSectionScp=NULL; PSCESECTION hSectionSmp=NULL; PSCESECTION hSectionPrevScp=NULL; PSCECONTEXT hPrevProfile=NULL; DOUBLE SectionID=0, SavedID=0; DWORD Actual; BOOL bCopyIt=FALSE; BOOL bCopyThisLine; BOOL bConvert=FALSE; // to convert privilege accounts PWSTR KeyName=NULL; PWSTR Value=NULL; DWORD KeyLen=0; DWORD ValueLen=0; WCHAR SectionName[256]; if ( hProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( hProfile->JetScpID == hProfile->JetSmpID ) { // if it's the same table, return - shouldn't happen return(SCESTATUS_SUCCESS); } if ( hProfile->JetSapID == JET_tableidNil ) { // tattoo table doesn't exist, return - shouldn't happen return(SCESTATUS_SUCCESS); } // // get previous policy propagation info (if any) // if ( !(CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { rc = ScepOpenPrevPolicyContext(hProfile, &hPrevProfile); if ( SCESTATUS_RECORD_NOT_FOUND == rc || SCESTATUS_PROFILE_NOT_FOUND == rc ) { // // the table doesn't exist - no previous policy prop // do not need to copy anything, just quit // return(SCESTATUS_SUCCESS); } } // // Create a SMP section handle. the section ID is a dummy one // rc = SceJetOpenSection( hProfile, (DOUBLE)1, (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ? SCEJET_TABLE_SMP : SCEJET_TABLE_TATTOO, &hSectionSmp ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc), pErrlog, SCEERR_OPEN, (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ? L"SMP" : L"TATTOO"); if (hPrevProfile) ScepClosePrevPolicyContext(&hPrevProfile); return(rc); } LSA_HANDLE LsaPolicy=NULL; PWSTR pszNewValue=NULL; DWORD NewLen=0; // // Move to the first line of the SCP table // JetErr = JetMove(hSectionSmp->JetSessionID, hSectionSmp->JetTableID, JET_MoveFirst, 0); while (JetErr == SCESTATUS_SUCCESS ) { // // get section ID // JetErr = JetRetrieveColumn( hSectionSmp->JetSessionID, hSectionSmp->JetTableID, hSectionSmp->JetColumnSectionID, (void *)&SectionID, 8, &Actual, 0, NULL ); if ( JetErr != JET_errSuccess ) { ScepBuildErrorLogInfo( ERROR_READ_FAULT, pErrlog, SCEERR_QUERY_INFO, L"sectionID"); rc = SceJetJetErrorToSceStatus(JetErr); break; } #ifdef SCE_DBG printf("SectionID=%d, JetErr=%d\n", (DWORD)SectionID, JetErr); #endif if ( SectionID != SavedID ) { // // a new section. Look for the section's name to see if this section // is to be converted // SavedID = SectionID; Actual = 510; memset(SectionName, '\0', 512); rc = SceJetGetSectionNameByID( hProfile, SectionID, SectionName, &Actual ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ERROR_BAD_FORMAT, pErrlog, SCEERR_CANT_FIND_SECTION, (DWORD)SectionID ); break; } if ( Actual > 0 ) SectionName[Actual/sizeof(TCHAR)] = L'\0'; #ifdef SCE_DBG wprintf(L"SectionName=%s\n", SectionName); #endif // // Compare section name with domain sections to convert // bCopyIt = TRUE; bConvert = FALSE; if ( (CopyOptions & SCE_LOCAL_POLICY_DC) ) { // // do not copy user rights if it's on a domain controller // if ( _wcsicmp(szPrivilegeRights, SectionName) == 0 || _wcsicmp(szSystemAccess, SectionName) == 0 || _wcsicmp(szKerberosPolicy, SectionName) == 0 || _wcsicmp(szAuditEvent, SectionName) == 0 || _wcsicmp(szGroupMembership, SectionName) == 0 ) { bCopyIt = FALSE; } else if ( (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { // // migrate registry values only // if ( _wcsicmp(szRegistryValues, SectionName) != 0 ) bCopyIt = FALSE; } } else if ( (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { // // non DCs, should migrate all local policies // if ( _wcsicmp(szPrivilegeRights, SectionName) == 0 ) { bConvert = TRUE; } else if ( (_wcsicmp(szSystemAccess, SectionName) != 0) && (_wcsicmp(szKerberosPolicy, SectionName) != 0) && (_wcsicmp(szRegistryValues, SectionName) != 0) && (_wcsicmp(szAuditEvent, SectionName) != 0) ) { bCopyIt = FALSE; } } /* if ( ( Options & SCE_NOCOPY_DOMAIN_POLICY) && ( (_wcsicmp(szSystemAccess, SectionName) == 0) || (_wcsicmp(szKerberosPolicy, SectionName) == 0) ) ) { bCopyIt = FALSE; } else if ( (_wcsicmp(szGroupMembership, SectionName) == 0) || (_wcsicmp(szRegistryKeys, SectionName) == 0) || (_wcsicmp(szFileSecurity, SectionName) == 0) || (_wcsicmp(szServiceGeneral, SectionName) == 0) || (_wcsicmp(szAuditApplicationLog, SectionName) == 0) || (_wcsicmp(szAuditSecurityLog, SectionName) == 0) || (_wcsicmp(szAuditSystemLog, SectionName) == 0) || (_wcsicmp(szAttachments, SectionName) == 0) || (_wcsicmp(szDSSecurity, SectionName) == 0) ) { // do not copy areas other than account policy and local policy bCopyIt = FALSE; } else { bCopyIt = TRUE; */ if ( bCopyIt ) { // // Prepare this Scep section // rc = SceJetOpenSection( hProfile, SectionID, (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ? SCEJET_TABLE_TATTOO : SCEJET_TABLE_SCP, &hSectionScp ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc), pErrlog, SCEERR_OPEN_ID, (DWORD)SectionID); break; } if ( (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { // // open current policy propagation table // do not care error here // SceJetOpenSection( hProfile, SectionID, SCEJET_TABLE_SCP, &hSectionPrevScp ); /* // should always copy tattoo value to the merged table // even if the setting doesn't exist in previous policy prop // this is to handle the dependent settings such as // retention perild and retention days } else if ( hPrevProfile ) { // // open previous policy propagation table // do not care error here // SceJetOpenSection( hPrevProfile, SectionID, SCEJET_TABLE_SCP, &hSectionPrevScp ); */ } } } if ( bCopyIt ) { // // get buffer size for key and value // rc = SceJetGetValue( hSectionSmp, SCEJET_CURRENT, NULL, NULL, 0, &KeyLen, NULL, 0, &ValueLen); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_QUERY_VALUE, L"current row"); break; } // // allocate memory // if ( KeyLen > 0 ) { KeyName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, KeyLen+2); if ( KeyName == NULL ) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; break; } } if ( ValueLen > 0 ) { Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2); if ( Value == NULL ) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; break; } } // // get key and value // rc = SceJetGetValue( hSectionSmp, SCEJET_CURRENT, NULL, KeyName, KeyLen, &KeyLen, Value, ValueLen, &ValueLen); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_QUERY_VALUE, L"current row"); break; } #ifdef SCE_DBG wprintf(L"\t%s=%s, rc=%d\n", KeyName, Value, rc); #endif bCopyThisLine = TRUE; // // check if this key exist in the previous prop // if ( hSectionPrevScp ) { rc = SceJetSeek( hSectionPrevScp, KeyName, KeyLen, SCEJET_SEEK_EQ_NO_CASE ); if ( SCESTATUS_RECORD_NOT_FOUND == rc || (hSectionPrevScp->JetColumnGpoID == 0) ) { bCopyThisLine = FALSE; } else if ( SCESTATUS_SUCCESS == rc && (CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { // // found. Let's check if this setting was from a GPO // if in migration (build tattoo), a setting was not // defined in GPO doesn't need a tattoo value // // for policy prop case, there may be undo settings in // previous policy prop and they weren't reset successfully // in previous prop. In this case, we still want to continue // reset these settings. So these settings should be copied // from the tattoo table to this policy table regardless if // there is a domain setting defined for it in the previous // policy propagation. // LONG GpoID = 0; (void)JetRetrieveColumn( hSectionPrevScp->JetSessionID, hSectionPrevScp->JetTableID, hSectionPrevScp->JetColumnGpoID, (void *)&GpoID, 4, &Actual, 0, NULL ); if ( GpoID == 0 ) { // // this is not a setting from a GPO // bCopyThisLine = FALSE; } } rc = SCESTATUS_SUCCESS; } if ( bCopyThisLine ) { // Ignore tattoo memberof entries, but leave an empty // value so that group membership processing code can detect // there is an entry in tattoo table. if(NULL != Value && _wcsicmp(szGroupMembership, SectionName) == 0 && ScepWcstrr(KeyName, szMemberof) && !(CopyOptions & SCE_LOCAL_POLICY_MIGRATE)) { *Value = L'\0'; ValueLen = sizeof(WCHAR); } if ( bConvert ) { rc = ScepConvertFreeTextAccountToSid( &LsaPolicy, Value, ValueLen/sizeof(WCHAR), &pszNewValue, &NewLen ); if ( rc == SCESTATUS_SUCCESS && pszNewValue ) { ScepFree(Value); Value = pszNewValue; ValueLen = NewLen*sizeof(WCHAR); pszNewValue = NULL; } // if failed to convert, just use the name format } // // Process group membership section and restore any relative SIDs "#-RSID" to // "*S-domain SID-RSID". Do not apply during upgrade. // if ( _wcsicmp(szGroupMembership, SectionName) == 0 && !(CopyOptions & SCE_LOCAL_POLICY_MIGRATE) ) { rc = ScepConvertRelativeSidAccountToSid( &LsaPolicy, Value, ValueLen/sizeof(WCHAR), &pszNewValue, &NewLen ); if ( rc == SCESTATUS_SUCCESS && pszNewValue ) { ScepFree(Value); Value = pszNewValue; ValueLen = NewLen*sizeof(WCHAR); pszNewValue = NULL; } } // // set this line to the SCP table // rc = SceJetSetLine( hSectionScp, KeyName, TRUE, Value, ValueLen, 0 ); if ( rc != SCESTATUS_SUCCESS ) { ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc), pErrlog, SCEERR_WRITE_INFO, KeyName); break; } } ScepFree(KeyName); KeyName = NULL; ScepFree(Value); Value = NULL; } // // Move to next line in the SCP table // JetErr = JetMove(hSectionSmp->JetSessionID, hSectionSmp->JetTableID, JET_MoveNext, 0); } if ( KeyName != NULL ) ScepFree(KeyName); if ( Value != NULL ) ScepFree(Value); SceJetCloseSection(&hSectionScp, TRUE); SceJetCloseSection(&hSectionSmp, TRUE); if ( hSectionPrevScp ) { SceJetCloseSection(&hSectionPrevScp, TRUE); } if (hPrevProfile) ScepClosePrevPolicyContext(&hPrevProfile); if ( LsaPolicy ) { LsaClose(LsaPolicy); } return(rc); } SCESTATUS ScepWriteObjectSecurity( IN PSCECONTEXT hProfile, IN SCETYPE ProfileType, IN AREA_INFORMATION Area, IN PSCE_OBJECT_SECURITY ObjSecurity ) /* Get security for a single object */ { SCESTATUS rc; PCWSTR SectionName=NULL; PSCESECTION hSection=NULL; DWORD SDsize, Win32Rc; PWSTR SDspec=NULL; if ( hProfile == NULL || ObjSecurity == NULL || ObjSecurity->Name == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } switch (Area) { case AREA_REGISTRY_SECURITY: SectionName = szRegistryKeys; break; case AREA_FILE_SECURITY: SectionName = szFileSecurity; break; #if 0 case AREA_DS_OBJECTS: SectionName = szDSSecurity; break; #endif default: return(SCESTATUS_INVALID_PARAMETER); } rc = ScepOpenSectionForName( hProfile, ProfileType, SectionName, &hSection ); if ( rc == SCESTATUS_SUCCESS ) { // // convert security descriptor // Win32Rc = ConvertSecurityDescriptorToText ( ObjSecurity->pSecurityDescriptor, ObjSecurity->SeInfo, &SDspec, &SDsize ); if ( Win32Rc == NO_ERROR ) { if ( Area == AREA_DS_OBJECTS ) { // // ds needs to convert name // rc = ScepDosErrorToSceStatus( ScepSaveDsStatusToSection( ObjSecurity->Name, ObjSecurity->IsContainer, ObjSecurity->Status, SDspec, SDsize ) ); } else { rc = ScepSaveObjectString( hSection, ObjSecurity->Name, ObjSecurity->IsContainer, ObjSecurity->Status, SDspec, SDsize ); } } else rc = ScepDosErrorToSceStatus(Win32Rc); } SceJetCloseSection( &hSection, TRUE); if (SDspec) ScepFree(SDspec); return(rc); } SCESTATUS ScepTattooCheckAndUpdateArray( IN OUT SCE_TATTOO_KEYS *pTattooKeys, IN OUT DWORD *pcTattooKeys, IN PWSTR KeyName, IN DWORD ConfigOptions, IN DWORD dwValue ) /* Description: Add a new entry into the array which holds system (tatto) values for the settings The input/output buffer pTattooKeys is allocated outside this routine. */ { if ( pTattooKeys == NULL || pcTattooKeys == NULL || KeyName == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( !(ConfigOptions & SCE_POLICY_TEMPLATE) ) { return(SCESTATUS_SUCCESS); } pTattooKeys[*pcTattooKeys].KeyName = KeyName; pTattooKeys[*pcTattooKeys].KeyLen = wcslen(KeyName); pTattooKeys[*pcTattooKeys].DataType = 'D'; pTattooKeys[*pcTattooKeys].SaveValue = dwValue; pTattooKeys[*pcTattooKeys].Value = NULL; // ScepLogOutput3(3,0, SCESRV_POLICY_TATTOO_ADD, KeyName, *pcTattooKeys); (*pcTattooKeys)++; return(SCESTATUS_SUCCESS); } SCESTATUS ScepTattooOpenPolicySections( IN PSCECONTEXT hProfile, IN PCWSTR SectionName, OUT PSCESECTION *phSectionDomain, OUT PSCESECTION *phSectionTattoo ) /* Open the table/sections for the merged policy and the undo settings */ { if ( hProfile == NULL || SectionName == NULL || phSectionDomain == NULL || phSectionTattoo == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rCode; DOUBLE SectionID; *phSectionDomain = NULL; *phSectionTattoo = NULL; // // open the section for both tattoo table and effective policy table // get section id first // rCode = SceJetGetSectionIDByName( hProfile, SectionName, &SectionID ); if ( rCode == SCESTATUS_SUCCESS ) { // open effective policy table rCode = SceJetOpenSection( hProfile, SectionID, SCEJET_TABLE_SCP, phSectionDomain ); if ( rCode == SCESTATUS_SUCCESS ) { // open tattoo table rCode = SceJetOpenSection( hProfile, SectionID, SCEJET_TABLE_TATTOO, phSectionTattoo ); if ( rCode != SCESTATUS_SUCCESS ) { SceJetCloseSection(phSectionDomain, TRUE); *phSectionDomain = NULL; } } } // // log tattoo process // if ( rCode != 0 ) ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_PREPARE, ScepSceStatusToDosError(rCode), SectionName); return(rCode); } SCESTATUS ScepTattooManageOneStringValue( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR KeyName, IN DWORD KeyLen OPTIONAL, IN PWSTR Value, IN DWORD ValueLen, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || KeyName == NULL || Value == NULL ) return(SCESTATUS_INVALID_PARAMETER); PWSTR pNewValue=NULL; DWORD NewLen=ValueLen; SCESTATUS rCode; if (Value && (ValueLen == 0) ) NewLen = wcslen(Value); if ( NewLen ) { // // the buffer passed may not be NULL terminated // pNewValue = (PWSTR)ScepAlloc(LPTR,(NewLen+1)*sizeof(WCHAR)); if ( pNewValue == NULL ) return(SCESTATUS_NOT_ENOUGH_RESOURCE); wcsncpy(pNewValue, Value, NewLen); } SCE_TATTOO_KEYS theKey; theKey.KeyName = KeyName; theKey.KeyLen = (KeyLen == 0) ? wcslen(KeyName) : KeyLen; theKey.Value = pNewValue; theKey.SaveValue = NewLen; theKey.DataType = 'S'; rCode = ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc); if ( pNewValue ) ScepFree(pNewValue); return(rCode); } SCESTATUS ScepTattooManageOneIntValue( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR KeyName, IN DWORD KeyLen OPTIONAL, IN DWORD Value, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || KeyName == NULL ) return(SCESTATUS_INVALID_PARAMETER); SCE_TATTOO_KEYS theKey; theKey.KeyName = KeyName; theKey.KeyLen = (KeyLen == 0) ? wcslen(KeyName) : KeyLen; theKey.SaveValue = Value; theKey.DataType = 'D'; theKey.Value = NULL; return(ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc)); } SCESTATUS ScepTattooManageOneIntValueWithDependency( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR DependentKeyName, IN DWORD DependentKeyLen OPTIONAL, IN PWSTR SaveKeyName, IN DWORD Value, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || SaveKeyName == NULL || DependentKeyName == NULL) return(SCESTATUS_INVALID_PARAMETER); SCE_TATTOO_KEYS theKey; theKey.KeyName = DependentKeyName; theKey.KeyLen = (DependentKeyLen == 0) ? wcslen(DependentKeyName) : DependentKeyLen; theKey.SaveValue = Value; theKey.DataType = 'L'; theKey.Value = SaveKeyName; return(ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc)); } SCESTATUS ScepTattooManageOneRegistryValue( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR KeyName, IN DWORD KeyLen OPTIONAL, IN PSCE_REGISTRY_VALUE_INFO pOneRegValue, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || KeyName == NULL || pOneRegValue == NULL ) return(SCESTATUS_INVALID_PARAMETER); SCESTATUS rCode; SCE_TATTOO_KEYS theKey; theKey.KeyName = KeyName; theKey.KeyLen = (KeyLen == 0) ? wcslen(KeyName) : KeyLen; theKey.Value = (PWSTR)pOneRegValue; theKey.SaveValue = 0; theKey.DataType = 'R'; rCode = ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc); return(rCode); } SCESTATUS ScepTattooManageOneMemberListValue( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR GroupName, IN DWORD GroupLen OPTIONAL, IN PSCE_NAME_LIST pNameList, IN BOOL bDeleteOnly, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || GroupName == NULL ) return(SCESTATUS_INVALID_PARAMETER); SCESTATUS rCode; SCE_TATTOO_KEYS theKey; DWORD Len=GroupLen; if ( Len == 0 ) Len = wcslen(GroupName); Len += wcslen(szMembers); PWSTR KeyString = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR)); if ( KeyString != NULL ) { swprintf(KeyString, L"%s%s", GroupName, szMembers); theKey.KeyName = KeyString; theKey.KeyLen = Len; theKey.Value = (PWSTR)pNameList; theKey.SaveValue = bDeleteOnly ? 1 : 0; theKey.DataType = 'M'; rCode = ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc); ScepFree(KeyString); } else { rCode = SCESTATUS_NOT_ENOUGH_RESOURCE; } return(rCode); } SCESTATUS ScepTattooReadOneMemberOfListValue( IN PSCESECTION hSectionTattoo, IN PSID pGroupSid, OUT PSCE_NAME_LIST *ppTattooList ) { SCESTATUS rc = SCESTATUS_SUCCESS; PWSTR pszGroupSid = NULL; PWSTR pszKeyName = NULL; DWORD dwValueLen = 0; PWSTR pszValue = NULL; PWSTR pszTemp; // Build the key name in format "*SID_memberof" rc = ScepDosErrorToSceStatus( ScepConvertSidToPrefixStringSid( pGroupSid, &pszGroupSid)); if(SCESTATUS_SUCCESS == rc) { pszKeyName = (PWSTR)ScepAlloc(0, (wcslen(pszGroupSid)+wcslen(szMemberof)+1)*sizeof(WCHAR)); if(!pszKeyName) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } if(SCESTATUS_SUCCESS == rc) { wcscpy(pszKeyName, pszGroupSid); wcscat(pszKeyName, szMemberof); } // retrieve memberof data from tattoo table rc = SceJetGetValue( hSectionTattoo, SCEJET_EXACT_MATCH_NO_CASE, pszKeyName, NULL, 0, NULL, NULL, 0, &dwValueLen); if(SCESTATUS_SUCCESS == rc) { pszValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT, dwValueLen+2); if(!pszValue) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } if(SCESTATUS_SUCCESS == rc) { rc = SceJetGetValue( hSectionTattoo, SCEJET_EXACT_MATCH_NO_CASE, pszKeyName, NULL, 0, NULL, pszValue, dwValueLen, &dwValueLen); } // build the memberof name list if(SCESTATUS_SUCCESS == rc) { pszTemp = pszValue; while(pszTemp && pszTemp[0]) { rc = ScepAddToNameList(ppTattooList, pszTemp, 0); if(STATUS_SUCCESS != rc) { rc = ScepDosErrorToSceStatus(rc); break; } pszTemp += wcslen(pszTemp)+1; } if(SCESTATUS_SUCCESS == rc) { pszTemp = pszValue; while(pszTemp && *pszTemp != L'\0') { DWORD dwLen = wcslen(pszTemp); *(pszTemp+dwLen) = L','; pszTemp = pszTemp+dwLen+1; } ScepLogOutput3(1, 0, SCEDLL_SCP_OLDTATTOO, pszValue); } } if(pszGroupSid) { ScepFree(pszGroupSid); } if(pszKeyName) { ScepFree(pszKeyName); } if(pszValue) { ScepFree(pszValue); } return rc; } SCESTATUS ScepTattooWriteOneMemberOfListValue( IN PSCESECTION hSectionTattoo, IN PSID pGroupSid, IN PSCE_NAME_LIST pNameList ) { SCESTATUS rc = SCESTATUS_SUCCESS; PWSTR pszGroupSid = NULL; PWSTR pszKeyName = NULL; PWSTR pszValue = NULL; PWSTR pszTemp; DWORD dwValueLen; PSCE_NAME_LIST pName; // Build the key name in format "*SID_memberof" rc = ScepDosErrorToSceStatus( ScepConvertSidToPrefixStringSid( pGroupSid, &pszGroupSid)); if(SCESTATUS_SUCCESS == rc) { pszKeyName = (PWSTR)ScepAlloc(0, (wcslen(pszGroupSid)+wcslen(szMemberof)+1)*sizeof(WCHAR)); if(!pszKeyName) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } if(SCESTATUS_SUCCESS == rc) { wcscpy(pszKeyName, pszGroupSid); wcscat(pszKeyName, szMemberof); } // if list is empty, delete entry from tattoo table if(!pNameList) { rc = SceJetDelete( hSectionTattoo, pszKeyName, FALSE, SCEJET_DELETE_LINE_NO_CASE); if(SCESTATUS_SUCCESS == rc) { ScepLogOutput3(1, 0, SCEDLL_SCP_DELETETATTOO); } // entry might not be there if(SCESTATUS_RECORD_NOT_FOUND == rc) { rc = SCESTATUS_SUCCESS; } } else // list is not empty, write new entry to tattoo table { // calculate value size if(SCESTATUS_SUCCESS == rc) { dwValueLen = sizeof(WCHAR); for(pName = pNameList; pName; pName = pName->Next) { dwValueLen += (wcslen(pName->Name)+1)*sizeof(WCHAR); } } // allocate value if(SCESTATUS_SUCCESS == rc) { pszValue = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwValueLen); if(!pszValue) { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } // build value from list if(SCESTATUS_SUCCESS == rc) { pszTemp = pszValue; for(pName = pNameList; pName; pName = pName->Next) { wcscpy(pszTemp, pName->Name); pszTemp += wcslen(pName->Name)+1; } *pszTemp = L'\0'; } if(SCESTATUS_SUCCESS == rc) { rc = SceJetSetLine( hSectionTattoo, pszKeyName, FALSE, // lowercase pszValue, dwValueLen, 0); // no GPOID } // if successfull, convert multisz to comma separated and write to log if(SCESTATUS_SUCCESS == rc) { pszTemp = pszValue; while(pszTemp && *pszTemp != L'\0') { DWORD dwLen = wcslen(pszTemp); *(pszTemp+dwLen) = L','; pszTemp = pszTemp+dwLen+1; } ScepLogOutput3(1, 0, SCEDLL_SCP_NEWTATTOO, pszValue); } if(pszValue) { ScepFree(pszValue); } } if(pszGroupSid) { ScepFree(pszGroupSid); } if(pszKeyName) { ScepFree(pszKeyName); } return(rc); } SCESTATUS ScepTattooManageOneServiceValue( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR ServiceName, IN DWORD ServiceLen OPTIONAL, IN PSCE_SERVICES pServiceNode, IN DWORD rc ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || ServiceName == NULL ) return(SCESTATUS_INVALID_PARAMETER); SCESTATUS rCode; SCE_TATTOO_KEYS theKey; theKey.KeyName = ServiceName; theKey.KeyLen = (ServiceLen == 0) ? wcslen(ServiceName) : ServiceLen; theKey.Value = (PWSTR)pServiceNode; theKey.SaveValue = 0; theKey.DataType = 'V'; rCode = ScepTattooManageValues(hSectionDomain, hSectionTattoo, &theKey, 1, rc); return(rCode); } SCESTATUS ScepTattooManageValues( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN SCE_TATTOO_KEYS *pTattooKeys, IN DWORD cTattooKeys, IN DWORD rc ) /* Description: For each setting in the array, do the following: 1) Check if the setting come from domain 2) Check if there is a tattoo value already exist 3) Save the new value from the array to the tattoo table if it doesn't exist 4) Delete the tattoo value if the setting didn't come from domain and it has been reset successfully */ { if ( hSectionDomain == NULL || hSectionTattoo == NULL || pTattooKeys == NULL || cTattooKeys == 0 ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rCode=SCESTATUS_SUCCESS; SCESTATUS rc2; BOOL bTattooExist,bDomainExist; PWSTR KeyString=NULL; PWSTR pTempKey; for ( DWORD i=0; iJetColumnGpoID > 0 ) { // // check if GpoID > 0 // LONG GpoID = 0; DWORD Actual; JET_ERR JetErr; JetErr = JetRetrieveColumn( hSectionDomain->JetSessionID, hSectionDomain->JetTableID, hSectionDomain->JetColumnGpoID, (void *)&GpoID, 4, &Actual, 0, NULL ); if ( JET_errSuccess != JetErr ) { // // if the column is nil (no value), it will return warning // but the buffer pGpoID is trashed // GpoID = 0; } if ( GpoID > 0 ) { bDomainExist = TRUE; } } } // // check if we need to save the tatto value or delete the tattoo value // if ( bDomainExist ) { pTempKey = pTattooKeys[i].KeyName; BOOL bSave = FALSE; if ( pTattooKeys[i].DataType == 'M' && pTattooKeys[i].SaveValue == 1 ) { // // delete only for group membership, don't do anything in this case // } else if ( !bTattooExist ) { // // domain setting is defined (the first time) // save the tattoo value // switch ( pTattooKeys[i].DataType ) { case 'D': if ( pTattooKeys[i].SaveValue != SCE_NO_VALUE ) { rc2 = ScepCompareAndSaveIntValue(hSectionTattoo, pTattooKeys[i].KeyName, FALSE, SCE_SNAPSHOT_VALUE, pTattooKeys[i].SaveValue ); bSave = TRUE; } break; case 'L': // dependency DWORD type pTempKey = pTattooKeys[i].Value; if ( pTattooKeys[i].SaveValue != SCE_NO_VALUE ) { rc2 = ScepCompareAndSaveIntValue(hSectionTattoo, pTattooKeys[i].Value, FALSE, SCE_SNAPSHOT_VALUE, pTattooKeys[i].SaveValue ); bSave = TRUE; } break; case 'S': if ( pTattooKeys[i].Value ) { rc2 = ScepCompareAndSaveStringValue(hSectionTattoo, pTattooKeys[i].KeyName, (PWSTR)(ULONG_PTR)SCE_SNAPSHOT_VALUE, pTattooKeys[i].Value, pTattooKeys[i].SaveValue*sizeof(WCHAR) ); bSave = TRUE; } break; case 'R': // registry values if ( ((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->Value ) { if ( REG_DWORD == ((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->ValueType ) { DWORD RegData = _wtol(((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->Value); rc2 = ScepSaveRegistryValue(hSectionTattoo, pTattooKeys[i].KeyName, REG_DWORD, (PWSTR)&RegData, sizeof(DWORD), 0 ); } else { rc2 = ScepSaveRegistryValue(hSectionTattoo, pTattooKeys[i].KeyName, ((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->ValueType, ((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->Value, wcslen(((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->Value)*sizeof(WCHAR), 0 ); } bSave = TRUE; } break; case 'M': // group member list // allow empty member list to be saved rc2 = ScepWriteNameListValue( NULL, hSectionTattoo, pTattooKeys[i].KeyName, (PSCE_NAME_LIST)(pTattooKeys[i].Value), SCE_WRITE_EMPTY_LIST, 3 ); bSave = TRUE; break; case 'V': // service if ( pTattooKeys[i].Value ) { rc2 = ScepSetSingleServiceSetting( hSectionTattoo, (PSCE_SERVICES)(pTattooKeys[i].Value) ); bSave = TRUE; } else { rc2 = SCESTATUS_INVALID_PARAMETER; } break; default: rc2 = SCESTATUS_INVALID_PARAMETER; break; } if ( rc2 != SCESTATUS_SUCCESS ) { ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_SETTING, ScepSceStatusToDosError(rc2), pTempKey); rCode = rc2; } else if ( bSave ) { ScepLogOutput3(2, 0, SCESRV_POLICY_TATTOO_CHECK, pTempKey); } } else { // // check if there is any value to save // switch ( pTattooKeys[i].DataType ) { case 'D': case 'L': if ( pTattooKeys[i].SaveValue != SCE_NO_VALUE ) bSave = TRUE; break; case 'S': case 'V': if ( pTattooKeys[i].Value ) bSave = TRUE; break; case 'R': if ( ((PSCE_REGISTRY_VALUE_INFO)(pTattooKeys[i].Value))->Value ) bSave = TRUE; break; } if ( bSave ) ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_EXIST, pTempKey); } } else { pTempKey = (pTattooKeys[i].DataType == 'L') ? pTattooKeys[i].Value : pTattooKeys[i].KeyName; if ( bTattooExist && ERROR_SUCCESS == rc ) { // // no domain setting defined // tattoo setting has been reset, delete the tattoo value // for dependency type, delete the right key // rc2 = SceJetDelete(hSectionTattoo, pTempKey, FALSE, SCEJET_DELETE_LINE_NO_CASE); if ( rc2 == SCESTATUS_RECORD_NOT_FOUND) rc2 = SCESTATUS_SUCCESS; if ( rc2 != SCESTATUS_SUCCESS ) { ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_REMOVE, ScepSceStatusToDosError(rc2), pTempKey); rCode = rc2; } else { ScepLogOutput3(2, 0, SCESRV_POLICY_TATTOO_REMOVE_SETTING, pTempKey); } } else if ( bTattooExist ) { // // undo value wan't reset properly // ScepLogOutput3(1, 0, SCESRV_POLICY_TATTOO_ERROR_RESET, pTempKey, rc ); } else { // // there is no undo value // // ScepLogOutput3(3, 0, SCESRV_POLICY_TATTOO_NONEXIST, pTempKey ); } } } return(rCode); } BOOL ScepTattooIfQueryNeeded( IN PSCESECTION hSectionDomain, IN PSCESECTION hSectionTattoo, IN PWSTR KeyName, IN DWORD Len, OUT BOOL *pbDomainExist, OUT BOOL *pbTattooExist ) { if ( hSectionDomain == NULL || hSectionTattoo == NULL || KeyName == NULL || Len == 0 ) { return FALSE; } // // check if this setting exists in the tattoo table // BOOL bTattooExist = FALSE; if ( SCESTATUS_SUCCESS == SceJetSeek( hSectionTattoo, KeyName, Len*sizeof(WCHAR), SCEJET_SEEK_EQ_NO_CASE ) ) { bTattooExist = TRUE; } // // check if the setting exists in the effective table // BOOL bDomainExist = FALSE; if ( SCESTATUS_SUCCESS == SceJetSeek( hSectionDomain, KeyName, Len*sizeof(WCHAR), SCEJET_SEEK_EQ_NO_CASE ) ) { if ( !bTattooExist ) { // // if there is no tattoo value but there is a setting in domain table // this setting must come from domain // bDomainExist = TRUE; } else if ( hSectionDomain->JetColumnGpoID > 0 ) { // // check if GpoID > 0 // LONG GpoID = 0; DWORD Actual; JET_ERR JetErr; JetErr = JetRetrieveColumn( hSectionDomain->JetSessionID, hSectionDomain->JetTableID, hSectionDomain->JetColumnGpoID, (void *)&GpoID, 4, &Actual, 0, NULL ); if ( JET_errSuccess != JetErr ) { // // if the column is nil (no value), it will return warning // but the buffer pGpoID is trashed // GpoID = 0; } if ( GpoID > 0 ) { bDomainExist = TRUE; } } } // // check if we need to save the tatto value or delete the tattoo value // if ( pbDomainExist ) *pbDomainExist = bDomainExist; if ( pbTattooExist ) *pbTattooExist = bTattooExist; if ( bDomainExist && !bTattooExist ) return TRUE; return FALSE; } SCESTATUS ScepDeleteOneSection( IN PSCECONTEXT hProfile, IN SCETYPE tblType, IN PCWSTR SectionName ) { PSCESECTION hSection=NULL; SCESTATUS rc; rc = ScepOpenSectionForName( hProfile, tblType, SectionName, &hSection ); if ( rc == SCESTATUS_SUCCESS ) { rc = SceJetDelete( hSection, NULL, FALSE,SCEJET_DELETE_SECTION ); SceJetCloseSection(&hSection, TRUE ); } if ( rc == SCESTATUS_RECORD_NOT_FOUND ) rc = SCESTATUS_SUCCESS; return(rc); }