/*++ Copyright (c) 1996 Microsoft Corporation Module Name: sceclnt.cpp Abstract: SCE Client APIs Author: Jin Huang (jinhuang) 23-Jun-1997 created Revision History: jinhuang 23-Jan-1998 split to client-server model --*/ #include "headers.h" #include "scerpc.h" #include "sceutil.h" #include "clntutil.h" #include "infp.h" #include "scedllrc.h" #include #include #pragma hdrstop extern PVOID theCallBack; extern HWND hCallbackWnd; extern DWORD CallbackType; extern HINSTANCE MyModuleHandle; PVOID theBrowseCallBack = NULL; #define SCE_REGISTER_REGVALUE_SECTION TEXT("Register Registry Values") typedef BOOL (WINAPI *PFNREFRESHPOLICY)( BOOL ); SCESTATUS ScepMergeBuffer( IN OUT PSCE_PROFILE_INFO pOldBuf, IN PSCE_PROFILE_INFO pNewBuf, IN AREA_INFORMATION Area ); SCESTATUS ScepConvertServices( IN OUT PVOID *ppServices, IN BOOL bSRForm ); SCESTATUS ScepFreeConvertedServices( IN PVOID pServices, IN BOOL bSRForm ); DWORD ScepMakeSelfRelativeSD( IN PSECURITY_DESCRIPTOR pInSD, OUT PSECURITY_DESCRIPTOR *pOutSD, OUT PULONG pnLen ); // // exported APIs in secedit.h (for secedit UI to use) // SCESTATUS WINAPI SceGetSecurityProfileInfo( IN PVOID hProfile OPTIONAL, IN SCETYPE ProfileType, IN AREA_INFORMATION Area, IN OUT PSCE_PROFILE_INFO *ppInfoBuffer, OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL ) /* Routine Description: SceGetSecurityProfileInfo will return the following type based on the SCETYPE parameter and profile handle: Profile Handle SCETYPE USAGE type field in SCE_PROFILE_INFO --------------------------------------------------------------------------------------------------------------------------------------------------------- JET SCE_ENGINE_SCP SCE_ENGINE_SCP JET SCE_ENGINE_SAP SCE_ENGINE_SAP JET SCE_ENGINE_SMP SCE_ENGINE_SMP JET all other SCETYPEs INVALID PARAMETER INF SCE_ENGINE_SCP SCE_STRUCT_INF INF all other SCETYPEs INVALID PARAMETER Arguments: hProfile - the Inf or SCE databas handle ProfileType - the profile type Area - the Area to read info for ppInfoBuffer- the output buffer Errlog - the error log buffer if there is any Retuen Value: SCE status */ { SCESTATUS rc; if ( !ppInfoBuffer || 0 == Area ) { return(SCESTATUS_INVALID_PARAMETER); } if ( !hProfile && ProfileType != SCE_ENGINE_SYSTEM ) { return(SCESTATUS_INVALID_PARAMETER); } BYTE dType; if ( hProfile ) { dType = *((BYTE *)hProfile); } else { dType = 0; } // // the first component in both INF and JET handle structures // is the ProfileFormat field - DWORD // switch ( dType ) { case SCE_INF_FORMAT: // // Inf format is only available to SCP type // if ( ProfileType != SCE_ENGINE_SCP ) { return(SCESTATUS_INVALID_PARAMETER); } // // initialize the error log buffer // if ( Errlog ) { *Errlog = NULL; } rc = SceInfpGetSecurityProfileInfo( ((PSCE_HINF)hProfile)->hInf, Area, ppInfoBuffer, Errlog ); break; default: if ( ProfileType != SCE_ENGINE_SCP && ProfileType != SCE_ENGINE_SMP && ProfileType != SCE_ENGINE_SAP && ProfileType != SCE_ENGINE_SYSTEM && ProfileType != SCE_ENGINE_GPO ) { return(SCESTATUS_INVALID_PARAMETER); } // // initialize the error log buffer // if ( Errlog ) { *Errlog = NULL; } PSCE_PROFILE_INFO pWkBuffer=NULL; PSCE_ERROR_LOG_INFO pErrTmp=NULL; // // handle Rpc exceptions // RpcTryExcept { if ( ProfileType == SCE_ENGINE_SYSTEM ) { Area &= (AREA_SECURITY_POLICY | AREA_PRIVILEGES); if ( hProfile ) { // // the local policy database can be opened // rc = SceRpcGetSystemSecurityFromHandle( (SCEPR_CONTEXT)hProfile, (AREAPR)Area, 0, (PSCEPR_PROFILE_INFO *)&pWkBuffer, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); } else { // // just get system settings // for normal user, the local policy database // can't be opened. // // // RPC bind to the server // handle_t binding_h; NTSTATUS NtStatus = ScepBindSecureRpc( NULL, L"scerpc", 0, &binding_h ); if (NT_SUCCESS(NtStatus)){ RpcTryExcept { rc = SceRpcGetSystemSecurity( binding_h, (AREAPR)Area, 0, (PSCEPR_PROFILE_INFO *)&pWkBuffer, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } } } else { rc = SceRpcGetDatabaseInfo( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (AREAPR)Area, (PSCEPR_PROFILE_INFO *)&pWkBuffer, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); } if ( pWkBuffer ) { if ( ProfileType != SCE_ENGINE_SYSTEM ) { // // convert the service list first // for ( PSCE_SERVICES ps=pWkBuffer->pServices; ps != NULL; ps = ps->Next ) { if ( ps->General.pSecurityDescriptor ) { // // this is really the SCEPR_SR_SECURITY_DESCRIPTOR * // PSCEPR_SR_SECURITY_DESCRIPTOR pWrap; pWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)(ps->General.pSecurityDescriptor); ps->General.pSecurityDescriptor = (PSECURITY_DESCRIPTOR)(pWrap->SecurityDescriptor); ScepFree(pWrap); } } } // // information is loaded ok, now merge them into ppInfoBuffer // if ( *ppInfoBuffer ) { if ( AREA_ALL != Area ) { // // merge new data into this buffer // ScepMergeBuffer(*ppInfoBuffer, pWkBuffer, Area); } else { PSCE_PROFILE_INFO pTemp=*ppInfoBuffer; *ppInfoBuffer = pWkBuffer; pWkBuffer = pTemp; } // // free the work buffer // SceFreeProfileMemory(pWkBuffer); } else { // // just assign it to the output buffer // *ppInfoBuffer = pWkBuffer; } } // // assign the error log // if ( Errlog ) { *Errlog = pErrTmp; pErrTmp = NULL; } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; if ( pErrTmp ) { // // free this tmp buffer // ScepFreeErrorLog(pErrTmp); } break; } return(rc); } SCESTATUS ScepMergeBuffer( IN OUT PSCE_PROFILE_INFO pOldBuf, IN PSCE_PROFILE_INFO pNewBuf, IN AREA_INFORMATION Area ) /* Routine Description: Merge information for the area(s) from new buffer into old buffer. Arguments: Return Value: */ { if ( !pOldBuf || !pNewBuf || !Area ) { return(SCESTATUS_INVALID_PARAMETER); } __try { if ( Area & AREA_SECURITY_POLICY ) { // // copy system access section, // note: free existing memory first // if ( pOldBuf->NewAdministratorName ) { ScepFree(pOldBuf->NewAdministratorName); } if ( pOldBuf->NewGuestName ) { ScepFree(pOldBuf->NewGuestName); } size_t nStart = offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordAge); size_t nEnd = offsetof(struct _SCE_PROFILE_INFO, ClearTextPassword)+sizeof(DWORD); memcpy((PBYTE)pOldBuf+nStart, (PBYTE)pNewBuf+nStart, nEnd-nStart); // // set NULL to memory directly assigned to the old buffer // pNewBuf->NewAdministratorName = NULL; pNewBuf->NewGuestName = NULL; // // copy kerberos policy and local policy // free exist memory used by the old buffer // if ( pOldBuf->pKerberosInfo ) { ScepFree(pOldBuf->pKerberosInfo); } nStart = offsetof(struct _SCE_PROFILE_INFO, pKerberosInfo ); nEnd = offsetof(struct _SCE_PROFILE_INFO, CrashOnAuditFull)+sizeof(DWORD); memcpy((PBYTE)pOldBuf+nStart, (PBYTE)pNewBuf+nStart, nEnd-nStart); // // set NULL to memory directly assigned to the old buffer // pNewBuf->pKerberosInfo = NULL; // // copy registry values info // if ( pOldBuf->aRegValues ) { ScepFreeRegistryValues(&(pOldBuf->aRegValues), pOldBuf->RegValueCount); } pOldBuf->RegValueCount = pNewBuf->RegValueCount; pOldBuf->aRegValues = pNewBuf->aRegValues; pNewBuf->aRegValues = NULL; } // // do not care user settings // if ( Area & AREA_PRIVILEGES ) { // // privilege section // SceFreeMemory(pOldBuf, AREA_PRIVILEGES); pOldBuf->OtherInfo.smp.pPrivilegeAssignedTo = pNewBuf->OtherInfo.smp.pPrivilegeAssignedTo; pNewBuf->OtherInfo.smp.pPrivilegeAssignedTo = NULL; } if ( Area & AREA_GROUP_MEMBERSHIP ) { // // group membership area // if ( pOldBuf->pGroupMembership ) { ScepFreeGroupMembership(pOldBuf->pGroupMembership); } pOldBuf->pGroupMembership = pNewBuf->pGroupMembership; pNewBuf->pGroupMembership = NULL; } if ( Area & AREA_REGISTRY_SECURITY ) { // // registry keys // if ( pOldBuf->pRegistryKeys.pOneLevel ) { ScepFreeObjectList( pOldBuf->pRegistryKeys.pOneLevel ); } pOldBuf->pRegistryKeys.pOneLevel = pNewBuf->pRegistryKeys.pOneLevel; pNewBuf->pRegistryKeys.pOneLevel = NULL; } if ( Area & AREA_FILE_SECURITY ) { // // file security // if ( pOldBuf->pFiles.pOneLevel ) { ScepFreeObjectList( pOldBuf->pFiles.pOneLevel ); } pOldBuf->pFiles.pOneLevel = pNewBuf->pFiles.pOneLevel; pNewBuf->pFiles.pOneLevel = NULL; } #if 0 if ( Area & AREA_DS_OBJECTS ) { // // ds objects // if ( pOldBuf->pDsObjects.pOneLevel ) { ScepFreeObjectList( pOldBuf->pDsObjects.pOneLevel ); } pOldBuf->pDsObjects.pOneLevel = pNewBuf->pDsObjects.pOneLevel; pNewBuf->pDsObjects.pOneLevel = NULL; } #endif if ( Area & AREA_SYSTEM_SERVICE ) { // // system services // if ( pOldBuf->pServices ) { SceFreePSCE_SERVICES( pOldBuf->pServices); } pOldBuf->pServices = pNewBuf->pServices; pNewBuf->pServices = NULL; } } __except (EXCEPTION_EXECUTE_HANDLER) { return (SCESTATUS_OTHER_ERROR); } return(SCESTATUS_SUCCESS); } SCESTATUS WINAPI SceGetObjectChildren( IN PVOID hProfile, IN SCETYPE ProfileType, IN AREA_INFORMATION Area, IN PWSTR ObjectPrefix, OUT PSCE_OBJECT_CHILDREN *Buffer, OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL ) /* Routine Description: Routine to get one level of children from the SCE database for the object named in ObjectPrefix. Arguments: hProfile - the database context handle ProfileType - the database type Area - the area to request (files, registry, ds objects, ..) ObjectPrefix - the parent object name Buffer - the output buffer for object list Errlog - the error log buffer Return Value: SCE status of this operation */ { SCESTATUS rc; if ( hProfile == NULL || Buffer == NULL || ObjectPrefix == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( SCE_INF_FORMAT == *((BYTE *)hProfile) ) { return(SCESTATUS_INVALID_PARAMETER); } if ( ProfileType != SCE_ENGINE_SCP && ProfileType != SCE_ENGINE_SMP && ProfileType != SCE_ENGINE_SAP ) { return(SCESTATUS_INVALID_PARAMETER); } // // initialize the error log buffer // if ( Errlog ) { *Errlog = NULL; } // // call RPC interface // PSCE_ERROR_LOG_INFO pErrTmp=NULL; RpcTryExcept { // // structure types must be casted for RPC data marshelling // rc = SceRpcGetObjectChildren( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (AREAPR)Area, (wchar_t *)ObjectPrefix, (PSCEPR_OBJECT_CHILDREN *)Buffer, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); if ( Errlog ) { *Errlog = pErrTmp; } else if ( pErrTmp ) { ScepFreeErrorLog(pErrTmp); } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceOpenProfile( IN PCWSTR ProfileName OPTIONAL, // for the system database IN SCE_FORMAT_TYPE ProfileFormat, OUT PVOID *hProfile ) /* Routine Description: Arguments: ProfileName - the profile name to open, use UNC name for remote ProfileFormat - the format of the profile SCE_INF_FORMAT, SCE_JET_FORMAT, SCE_JET_ANALYSIS_REQUIRED hProfile - the profile handle returned Return Value: SCE status of this operation */ { SCESTATUS rc; LPTSTR DefProfile=NULL; SCEPR_CONTEXT pContext = NULL; if ( hProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } BOOL bEmptyName=FALSE; if ( ProfileName == NULL || wcslen(ProfileName) == 0 ) { bEmptyName = TRUE; } switch (ProfileFormat ) { case SCE_INF_FORMAT: if ( bEmptyName ) { return(SCESTATUS_INVALID_PARAMETER); } // // Inf format // *hProfile = ScepAlloc( LMEM_ZEROINIT, sizeof(SCE_HINF) ); if ( *hProfile == NULL ) { return(SCESTATUS_NOT_ENOUGH_RESOURCE); } ((PSCE_HINF)(*hProfile))->Type = (BYTE)SCE_INF_FORMAT; rc = SceInfpOpenProfile( ProfileName, &(((PSCE_HINF)(*hProfile))->hInf) ); if ( rc != SCESTATUS_SUCCESS ) { // // free memory // ScepFree( *hProfile ); *hProfile = NULL; } break; case SCE_JET_ANALYSIS_REQUIRED: case SCE_JET_FORMAT: BOOL bAnalysis; if ( SCE_JET_FORMAT == ProfileFormat ) { bAnalysis = FALSE; if ( bEmptyName ) { // // looking for the system database // rc = ScepGetProfileSetting( L"DefaultProfile", TRUE, // in order to get system db name. Access will be checked when opening the database &DefProfile ); if ( rc != ERROR_SUCCESS || DefProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } } } else { bAnalysis = TRUE; // // jet database name is required // if ( bEmptyName ) { return(SCESTATUS_ACCESS_DENIED); } } // // system database can't be opened for SCM mode // if ( bAnalysis && SceIsSystemDatabase(ProfileName) ) { return(SCESTATUS_ACCESS_DENIED); } handle_t binding_h; NTSTATUS NtStatus; // // RPC bind to the server // NtStatus = ScepBindSecureRpc( NULL, // should use the system name embedded within the database name L"scerpc", 0, &binding_h ); if (NT_SUCCESS(NtStatus)){ RpcTryExcept { rc = SceRpcOpenDatabase( binding_h, bEmptyName ? (wchar_t *)DefProfile : (wchar_t *)ProfileName, bAnalysis ? SCE_OPEN_OPTION_REQUIRE_ANALYSIS : 0, &pContext ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } if ( SCESTATUS_SUCCESS == rc ) { // // database is opened // *hProfile = (PVOID)pContext; } else { *hProfile = NULL; } break; default: rc = SCESTATUS_INVALID_PARAMETER; break; } if ( DefProfile ) { ScepFree(DefProfile); } return(rc); } SCESTATUS WINAPI SceCloseProfile( IN PVOID *hProfile ) /* Routine Description: Close the profile handle Arguments: hProfile - the address of a profile handle Return Value: SCE status of this operation */ { if ( hProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( *hProfile == NULL ) { return(SCESTATUS_SUCCESS); } SCESTATUS rc = SCESTATUS_SUCCESS; switch(*((BYTE *)(*hProfile)) ) { case SCE_INF_FORMAT: // // close the inf handle // SceInfpCloseProfile(((PSCE_HINF)(*hProfile))->hInf); ScepFree(*hProfile); *hProfile = NULL; break; default: // // jet database, call rpc to close it // RpcTryExcept { rc = SceRpcCloseDatabase((SCEPR_CONTEXT *)hProfile); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; break; } return(rc); } SCESTATUS WINAPI SceGetScpProfileDescription( IN PVOID hProfile, OUT PWSTR *Description ) /* Routine Descripton: Get profile description from the profile handle Arguments: hProfile - the profile handle Description - the description output buffer Return Value: SCE status */ { SCESTATUS rc; if ( hProfile == NULL || Description == NULL ) { return(SCESTATUS_SUCCESS); } switch( *((BYTE *)hProfile) ) { case SCE_INF_FORMAT: // // inf format of profile // rc = SceInfpGetDescription( ((PSCE_HINF)hProfile)->hInf, Description ); break; default: // // jet database, call rpc interface // RpcTryExcept { rc = SceRpcGetDatabaseDescription( (SCEPR_CONTEXT)hProfile, (wchar_t **)Description ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; break; } return(rc); } SCESTATUS WINAPI SceGetTimeStamp( IN PVOID hProfile, OUT PWSTR *ConfigTimeStamp OPTIONAL, OUT PWSTR *AnalyzeTimeStamp OPTIONAL ) /* Routine Descripton: Get SCE database last config and last analysis time stamp Arguments: hProfile - the profile handle ConfigTimeStamp - the time stamp for last config AnalyzeTimeStamp - the time stamp for last analysis Return Value: SCE status */ { SCESTATUS rc; LARGE_INTEGER TimeStamp1; LARGE_INTEGER TimeStamp2; LARGE_INTEGER ConfigTime; LARGE_INTEGER AnalyzeTime; TIME_FIELDS TimeFields; if ( hProfile == NULL || ( ConfigTimeStamp == NULL && AnalyzeTimeStamp == NULL) ) { return(SCESTATUS_INVALID_PARAMETER); } // // call RPC interface // RpcTryExcept { rc = SceRpcGetDBTimeStamp( (SCEPR_CONTEXT)hProfile, &ConfigTime, &AnalyzeTime ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; if ( rc == SCESTATUS_SUCCESS ) { if ( ConfigTimeStamp ) { *ConfigTimeStamp = NULL; if ( ConfigTime.HighPart != 0 || ConfigTime.LowPart != 0 ) { // // convert the config time stamp from LARGE_INTEGER to // string format // RtlSystemTimeToLocalTime(&ConfigTime, &TimeStamp1); if ( TimeStamp1.LowPart != 0 || TimeStamp1.HighPart != 0) { memset(&TimeFields, 0, sizeof(TIME_FIELDS)); RtlTimeToTimeFields ( &TimeStamp1, &TimeFields ); if ( TimeFields.Month > 0 && TimeFields.Month <= 12 && TimeFields.Day > 0 && TimeFields.Day <= 31 && TimeFields.Year > 1600 ) { *ConfigTimeStamp = (PWSTR)ScepAlloc(0, 60); //60 bytes swprintf(*ConfigTimeStamp, L"%02d/%02d/%04d %02d:%02d:%02d", TimeFields.Month, TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second); } else { *ConfigTimeStamp = (PWSTR)ScepAlloc(0, 40); //40 bytes swprintf(*ConfigTimeStamp, L"%08x%08x", TimeStamp1.HighPart, TimeStamp1.LowPart); } } } } if ( AnalyzeTimeStamp ) { *AnalyzeTimeStamp = NULL; if ( AnalyzeTime.HighPart != 0 || AnalyzeTime.LowPart != 0 ) { // // convert the analysis time stamp from LARGE_INTEGER // to string format // RtlSystemTimeToLocalTime(&AnalyzeTime, &TimeStamp2); if ( TimeStamp2.LowPart != 0 || TimeStamp2.HighPart != 0) { memset(&TimeFields, 0, sizeof(TIME_FIELDS)); RtlTimeToTimeFields ( &TimeStamp2, &TimeFields ); if ( TimeFields.Month > 0 && TimeFields.Month <= 12 && TimeFields.Day > 0 && TimeFields.Day <= 31 && TimeFields.Year > 1600 ) { *AnalyzeTimeStamp = (PWSTR)ScepAlloc(0, 60); //40 bytes swprintf(*AnalyzeTimeStamp, L"%02d/%02d/%04d %02d:%02d:%02d", TimeFields.Month, TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second); } else { *AnalyzeTimeStamp = (PWSTR)ScepAlloc(0, 40); //40 bytes swprintf(*AnalyzeTimeStamp, L"%08x%08x", TimeStamp2.HighPart, TimeStamp2.LowPart); } } } } } return(rc); } SCESTATUS WINAPI SceGetDbTime( IN PVOID hProfile, OUT SYSTEMTIME *ConfigDateTime, OUT SYSTEMTIME *AnalyzeDateTime ) /* Routine Descripton: Get SCE database last config and last analysis time (in SYSTEMTIME structure) Arguments: hProfile - the profile handle ConfigDateTime - the system time for last configuration AnalyzeDateTime - the system time for last analysis Return Value: SCE status */ { SCESTATUS rc; LARGE_INTEGER TimeStamp; LARGE_INTEGER ConfigTimeStamp; LARGE_INTEGER AnalyzeTimeStamp; FILETIME ft; if ( hProfile == NULL || ( ConfigDateTime == NULL && AnalyzeDateTime == NULL) ) { return(SCESTATUS_INVALID_PARAMETER); } // // call RPC interface // RpcTryExcept { rc = SceRpcGetDBTimeStamp( (SCEPR_CONTEXT)hProfile, &ConfigTimeStamp, &AnalyzeTimeStamp ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; if ( rc == SCESTATUS_SUCCESS ) { if ( ConfigDateTime ) { memset(ConfigDateTime, '\0', sizeof(SYSTEMTIME)); if ( ConfigTimeStamp.HighPart != 0 || ConfigTimeStamp.LowPart != 0 ) { // // convert the config time stamp from LARGE_INTEGER to // string format // RtlSystemTimeToLocalTime(&ConfigTimeStamp, &TimeStamp); if ( TimeStamp.LowPart != 0 || TimeStamp.HighPart != 0) { ft.dwLowDateTime = TimeStamp.LowPart; ft.dwHighDateTime = TimeStamp.HighPart; if ( !FileTimeToSystemTime(&ft, ConfigDateTime) ) { rc = ScepDosErrorToSceStatus(GetLastError()); } } } } if ( AnalyzeDateTime && (SCESTATUS_SUCCESS == rc) ) { memset(AnalyzeDateTime, '\0', sizeof(SYSTEMTIME)); if ( AnalyzeTimeStamp.HighPart != 0 || AnalyzeTimeStamp.LowPart != 0 ) { // // convert the analysis time stamp from LARGE_INTEGER // to string format // RtlSystemTimeToLocalTime(&AnalyzeTimeStamp, &TimeStamp); if ( TimeStamp.LowPart != 0 || TimeStamp.HighPart != 0) { ft.dwLowDateTime = TimeStamp.LowPart; ft.dwHighDateTime = TimeStamp.HighPart; if ( !FileTimeToSystemTime(&ft, AnalyzeDateTime) ) { rc = ScepDosErrorToSceStatus(GetLastError()); } } } } } return(rc); } SCESTATUS WINAPI SceGetObjectSecurity( IN PVOID hProfile, IN SCETYPE ProfileType, IN AREA_INFORMATION Area, IN PWSTR ObjectName, OUT PSCE_OBJECT_SECURITY *ObjSecurity ) /* Routine Descripton: Get security setting for an object from the SCE database Arguments: hProfile - the profile handle ProfileType - the database type Area - the security area to get info (file, registry, ..) ObjectName - the object's name (full path) ObjSecurity - the security settings (flag, SDDL) Return Value: SCE status */ { SCESTATUS rc; if ( hProfile == NULL || ObjectName == NULL || ObjSecurity == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( ProfileType != SCE_ENGINE_SCP && ProfileType != SCE_ENGINE_SMP && ProfileType != SCE_ENGINE_SAP ) { return(SCESTATUS_INVALID_PARAMETER); } // // call rpc interface // RpcTryExcept { rc = SceRpcGetObjectSecurity( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (AREAPR)Area, (wchar_t *)ObjectName, (PSCEPR_OBJECT_SECURITY *)ObjSecurity ); // // convert the security descriptor // if ( *ObjSecurity && (*ObjSecurity)->pSecurityDescriptor ) { // // this is really the SCEPR_SR_SECURITY_DESCRIPTOR * // PSCEPR_SR_SECURITY_DESCRIPTOR pWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)((*ObjSecurity)->pSecurityDescriptor); (*ObjSecurity)->pSecurityDescriptor = (PSECURITY_DESCRIPTOR)(pWrap->SecurityDescriptor); ScepFree(pWrap); } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceGetAnalysisAreaSummary( IN PVOID hProfile, IN AREA_INFORMATION Area, OUT PDWORD pCount ) /* Routine Descripton: Get summary information for the security area from SCE database. Arguments: hProfile - the profile handle Area - the security area to get info pCount - the total object count Return Value: SCE status */ { if ( hProfile == NULL || pCount == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } // // call RPC interface // SCESTATUS rc; RpcTryExcept { rc = SceRpcGetAnalysisSummary( (SCEPR_CONTEXT)hProfile, (AREAPR)Area, pCount ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceCopyBaseProfile( IN PVOID hProfile, IN SCETYPE ProfileType, IN PWSTR InfFileName, IN AREA_INFORMATION Area, OUT PSCE_ERROR_LOG_INFO *pErrlog OPTIONAL ) /* ++ Routine Description: Copy the base profile from Jet database into a inf profile. Arguments: hProfile - the database handle InfFileName - the inf template name to generate Area - the area to generate pErrlog - the error log buffer Return Value: SCE status -- */ { SCESTATUS rc; PWSTR Description=NULL; PSCE_PROFILE_INFO pSmpInfo=NULL; SCE_PROFILE_INFO scpInfo; AREA_INFORMATION Area2; PSCE_ERROR_LOG_INFO pErrTmp=NULL; PSCE_ERROR_LOG_INFO errTmp; if ( hProfile == NULL || InfFileName == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( ProfileType != SCE_ENGINE_SCP && ProfileType != SCE_ENGINE_SMP ) { return(SCESTATUS_INVALID_PARAMETER); } // // make RPC calls to query information // RpcTryExcept { // // read profile description, if fails here, continue // rc = SceRpcGetDatabaseDescription( (SCEPR_CONTEXT)hProfile, (wchar_t **)&Description ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // create a new inf profile with [Version] section and make it unicode // if ( !SetupINFAsUCS2(InfFileName) ) { // //if error continues // rc = ScepDosErrorToSceStatus(GetLastError()); } if ( !WritePrivateProfileSection( L"Version", L"signature=\"$CHICAGO$\"\0Revision=1\0\0", (LPCTSTR)InfFileName) ) { rc = ScepDosErrorToSceStatus(GetLastError()); goto Cleanup; } // // create [description], if error, continue // if ( Description ) { // // empty the description section first. // WritePrivateProfileSection( L"Profile Description", NULL, (LPCTSTR)InfFileName); WritePrivateProfileString( L"Profile Description", L"Description", Description, (LPCTSTR)InfFileName); } // // info for the following areas can be retrieved together // Area2 = Area & ( AREA_SECURITY_POLICY | AREA_GROUP_MEMBERSHIP | AREA_PRIVILEGES ); rc = SCESTATUS_SUCCESS; // // initialize the error log buffer // if ( pErrlog ) { *pErrlog = NULL; } if ( Area2 != 0 ) { // // read base profile information // rc = SceGetSecurityProfileInfo( hProfile, ProfileType, // SCE_ENGINE_SMP, Area2, &pSmpInfo, &pErrTmp ); if ( pErrlog ) { *pErrlog = pErrTmp; } else if ( pErrTmp ) { ScepFreeErrorLog(pErrTmp); } pErrTmp = NULL; if ( rc == SCESTATUS_SUCCESS && pSmpInfo != NULL ) { // // use a new error buffer if pErrlog is not NULL // because SceWriteSecurityProfileInfo reset the errlog buffer to NULL // at beginning // rc = SceWriteSecurityProfileInfo( InfFileName, Area2, pSmpInfo, &pErrTmp ); if ( pErrlog && pErrTmp ) { // // link the new error buffer to the end of pErrlog // if ( *pErrlog ) { // // find the end of the buffer // for ( errTmp=*pErrlog; errTmp && errTmp->next; errTmp=errTmp->next); // // when this loop is done, errTmp->next must be NULL // if(errTmp) { errTmp->next = pErrTmp; } } else { *pErrlog = pErrTmp; } pErrTmp = NULL; } } if ( rc != SCESTATUS_SUCCESS ) { goto Cleanup; } } // // copy privileges area // if ( Area & AREA_PRIVILEGES && pSmpInfo != NULL ) { // // write [Privileges] section // a new error buffer is used because the api below reset the error buffer // scpInfo.OtherInfo.scp.u.pInfPrivilegeAssignedTo = pSmpInfo->OtherInfo.smp.pPrivilegeAssignedTo; rc = SceWriteSecurityProfileInfo( InfFileName, AREA_PRIVILEGES, &scpInfo, &pErrTmp ); if ( pErrlog && pErrTmp ) { // // link the new error buffer to the end of pErrlog // if ( *pErrlog ) { // // find the end of the buffer // for ( errTmp=*pErrlog; errTmp && errTmp->next; errTmp=errTmp->next); // // when this loop is done, errTmp->next must be NULL // errTmp->next = pErrTmp; } else { *pErrlog = pErrTmp; } pErrTmp = NULL; } if ( rc != SCESTATUS_SUCCESS ) goto Cleanup; } // // copy objects // Area2 = Area & ( AREA_REGISTRY_SECURITY | AREA_FILE_SECURITY | // AREA_DS_OBJECTS | AREA_SYSTEM_SERVICE | AREA_SECURITY_POLICY | AREA_ATTACHMENTS); if ( Area2 ) { // // write objects section (szRegistryKeys, szFileSecurity, // szDSSecurity, szServiceGeneral) // RpcTryExcept { rc = SceRpcCopyObjects( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (wchar_t *)InfFileName, (AREAPR)Area2, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); if ( pErrlog && pErrTmp ) { // // link the new error buffer to the end of pErrlog // if ( *pErrlog ) { // // find the end of the buffer // for ( errTmp=*pErrlog; errTmp && errTmp->next; errTmp=errTmp->next); // // when this loop is done, errTmp->next must be NULL // errTmp->next = pErrTmp; } else { *pErrlog = pErrTmp; } pErrTmp = NULL; } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; } Cleanup: if ( Description != NULL ) { ScepFree(Description); } if ( pSmpInfo != NULL ) { Area2 = Area & ( AREA_SECURITY_POLICY | AREA_GROUP_MEMBERSHIP | AREA_PRIVILEGES ); SceFreeProfileMemory(pSmpInfo); } if ( pErrTmp ) { ScepFreeErrorLog(pErrTmp); } return(rc); } SCESTATUS WINAPI SceConfigureSystem( IN LPTSTR SystemName OPTIONAL, IN PCWSTR InfFileName OPTIONAL, IN PCWSTR DatabaseName, IN PCWSTR LogFileName OPTIONAL, IN DWORD ConfigOptions, IN AREA_INFORMATION Area, IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL, IN HANDLE hCallbackWnd OPTIONAL, OUT PDWORD pdWarning OPTIONAL ) // see ScepConfigSystem { AREA_INFORMATION Area2=Area; if ( DatabaseName == NULL || SceIsSystemDatabase(DatabaseName) ) { // // detect if this is system database (admin logon) // no configuration is allowed. // if ( DatabaseName == NULL ) { BOOL bAdminLogon=FALSE; ScepIsAdminLoggedOn(&bAdminLogon, FALSE); if ( bAdminLogon ) { return(SCESTATUS_ACCESS_DENIED); } } else return(SCESTATUS_ACCESS_DENIED); } SCESTATUS rc; DWORD dOptions; ScepSetCallback((PVOID)pCallback, hCallbackWnd, SCE_AREA_CALLBACK); // // filter out invalid options from clients // filter out areas other than security policy and user rights // dOptions = ConfigOptions & 0xFFL; rc = ScepConfigSystem( SystemName, InfFileName, DatabaseName, LogFileName, dOptions, Area2, pCallback, hCallbackWnd, pdWarning ); ScepSetCallback(NULL, NULL, 0); if ( DatabaseName != NULL && !SceIsSystemDatabase(DatabaseName) && !(ConfigOptions & SCE_NO_CONFIG) && (Area2 & AREA_SECURITY_POLICY) ) { // // private database, should trigger policy propagation // delete the last configuration time // HKEY hKey=NULL; if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, 0, KEY_READ | KEY_WRITE, &hKey ) == ERROR_SUCCESS ) { RegDeleteValue(hKey, TEXT("LastWinlogonConfig")); RegCloseKey( hKey ); } HINSTANCE hLoadDll = LoadLibrary(TEXT("userenv.dll")); if ( hLoadDll) { PFNREFRESHPOLICY pfnRefreshPolicy = (PFNREFRESHPOLICY)GetProcAddress( hLoadDll, "RefreshPolicy"); if ( pfnRefreshPolicy ) { (*pfnRefreshPolicy )( TRUE ); } FreeLibrary(hLoadDll); } } return(rc); } SCESTATUS ScepConfigSystem( IN LPTSTR SystemName OPTIONAL, IN PCWSTR InfFileName OPTIONAL, IN PCWSTR DatabaseName OPTIONAL, IN PCWSTR LogFileName OPTIONAL, IN DWORD ConfigOptions, IN AREA_INFORMATION Area, IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL, IN HANDLE hCallbackWnd OPTIONAL, OUT PDWORD pdWarning OPTIONAL ) /* ++ Routine Description: Routine to configure a system or local system if SystemName is NULL. If DatabaseName is NULL, the default databae on the system is used. if InfFileName is provided, depending on the ConfigOptions, info in the InfFileName is either appended to the database (if exist), or used to create/overwrite the database. ConfigOptions can contain flags such as verbose log, no log, and overwrite /update database. When overwrite is specified, existing database info is overwritten by the inf template, and all analysis information is cleaned up. Callback pointers to the client can be registered as the arguments for progress indication. A warning code is also returned if there is any warning occurs during the operation while the SCESTATUS return code is SCESTATUS_SUCCESS. Examples such as ERROR_FILE_NOT_FOUND, or ERROR_ACCESS_DENIED when configuring the system won't be counted as error of this operation because the current user context may not have proper access to some of the resources specified in the template. Arguments: SystemName - the system name where this operation will run, NULL for local system InfFileName - optional inf template name, if NULL, existing info in the SCe database is used to configure. DatabaseName - the SCE database name. if NULL, the default is used. LogFileName - optional log file name for the operation ConfigOptions - the options to configure SCE_OVERWRITE_DB SCE_UPDATE_DB SCE_VERBOSE_LOG SCE_DISABLE_LOG Area - Area to configure pCallback - optional client callback routine hCallbackWnd - a callback window handle pdWarning - the warning code Return Value: SCE status -- */ { SCESTATUS rc; handle_t binding_h; NTSTATUS NtStatus; DWORD dOptions; dOptions = ConfigOptions & ~(SCE_CALLBACK_DELTA | SCE_CALLBACK_TOTAL | SCE_POLBIND_NO_AUTH); if ( pCallback ) { dOptions |= SCE_CALLBACK_TOTAL; } // // check the input arguments // LPCTSTR NewInf = NULL; LPCTSTR NewDb = NULL; LPCTSTR NewLog = NULL; __try { if ( InfFileName && wcslen(InfFileName) > 0 ) { NewInf = InfFileName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } __try { if ( DatabaseName && wcslen(DatabaseName) > 0 ) { NewDb = DatabaseName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } __try { if ( LogFileName && wcslen(LogFileName) > 0 ) { NewLog = LogFileName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } /* // // ANZ hotfix: // move the "drop SAM notifications" event-reset into scesrv // just before configuring the SAM during policy propagation // to reduce the "dropping notifications" window // if ( (ConfigOptions & SCE_POLICY_TEMPLATE) && !(ConfigOptions & SCE_NO_CONFIG) && (Area & AREA_SECURITY_POLICY) ) { // // turn off policy filter for SAM notification // ScepRegSetIntValue(HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, TEXT("PolicyFilterOffSAM"), 1 ); } */ // // RPC bind to the server // if ( ConfigOptions & SCE_POLBIND_NO_AUTH ) { NtStatus = ScepBindRpc( SystemName, L"scerpc", L"security=impersonation dynamic false", &binding_h ); } else { NtStatus = ScepBindSecureRpc( SystemName, L"scerpc", L"security=impersonation dynamic false", &binding_h ); } if (NT_SUCCESS(NtStatus)){ LPVOID pebClient = GetEnvironmentStrings(); DWORD ebSize = ScepGetEnvStringSize(pebClient); RpcTryExcept { DWORD dWarn=0; rc = SceRpcConfigureSystem( binding_h, (wchar_t *)NewInf, (wchar_t *)NewDb, (wchar_t *)NewLog, dOptions, (AREAPR)Area, ebSize, (UCHAR *)pebClient, &dWarn ); if ( pdWarning ) { *pdWarning = dWarn; } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); if(pebClient) { FreeEnvironmentStrings((LPTSTR)pebClient); } } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } /* // // ANZ hotfix: // move the "enable SAM notifications" event-set into scesrv // just after configuring the SAM in policy propagation // to reduce the "dropping notifications" window // if ( (ConfigOptions & SCE_POLICY_TEMPLATE) && !(ConfigOptions & SCE_NO_CONFIG) && (Area & AREA_SECURITY_POLICY) ) { // // delete the value // dOptions = ScepRegDeleteValue(HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, TEXT("PolicyFilterOffSAM") ); if ( dOptions != ERROR_SUCCESS && dOptions != ERROR_FILE_NOT_FOUND && dOptions != ERROR_PATH_NOT_FOUND ) { ScepRegSetIntValue(HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, TEXT("PolicyFilterOffSAM"), 0 ); } } */ return(rc); } SCESTATUS WINAPI SceAnalyzeSystem( IN LPTSTR SystemName OPTIONAL, IN PCWSTR InfFileName OPTIONAL, IN PCWSTR DatabaseName, IN PCWSTR LogFileName OPTIONAL, IN DWORD AnalyzeOptions, IN AREA_INFORMATION Area, IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL, IN HANDLE hCallbackWnd OPTIONAL, OUT PDWORD pdWarning OPTIONAL ) /* ++ Routine Description: Routine to analyze a system or local system if SystemName is NULL. If DatabaseName is NULL, the default databae on the system is used. if InfFileName is provided with OVERWRITE flag in AnalyzeOptions, the database must NOT exist, otherwise, the Inf template is ignored and the system is analyzed based on the info in the database. When APPEND is specified in the flag, the InfFileName is appended to the database (if exist), or used to create the database, then overall information in the database is used to analyze the system. AnalyzeOptions can contain flags such as verbose log, no log, and overwrite /update database. Callback pointers to the client can be registered as the arguments for progress indication. A warning code is also returned if there is any warning occurs during the operation while the SCESTATUS return code is SCESTATUS_SUCCESS. Examples such as ERROR_FILE_NOT_FOUND, or ERROR_ACCESS_DENIED when configuring the system won't be counted as error of this operation because the current user context may not have proper access to some of the resources specified in the template. Arguments: SystemName - the system name where this operation will run, NULL for local system InfFileName - optional inf template name, if NULL, existing info in the SCe database is used to configure. DatabaseName - the SCE database name. if NULL, the default is used. LogFileName - optional log file name for the operation AnalzyeOptions - the options to configure SCE_OVERWRITE_DB SCE_UPDATE_DB SCE_VERBOSE_LOG SCE_DISABLE_LOG Area - reserved pCallback - optional client callback routine hCallbackWnd - a callback window handle pdWarning - the warning code Return Value: SCE status -- */ { if ( DatabaseName == NULL || SceIsSystemDatabase(DatabaseName) ) { // // detect if this is system database (admin logon) // no configuration is allowed. // if ( DatabaseName == NULL ) { BOOL bAdminLogon=FALSE; ScepIsAdminLoggedOn(&bAdminLogon, FALSE); if ( bAdminLogon ) { return(SCESTATUS_ACCESS_DENIED); } } else return(SCESTATUS_ACCESS_DENIED); } SCESTATUS rc; handle_t binding_h; NTSTATUS NtStatus; DWORD dOptions; ScepSetCallback((PVOID)pCallback, hCallbackWnd, SCE_AREA_CALLBACK); // // filter out invalid options // dOptions = AnalyzeOptions & 0xFFL; dOptions = dOptions & ~(SCE_CALLBACK_DELTA | SCE_CALLBACK_TOTAL); if ( pCallback ) { dOptions |= SCE_CALLBACK_TOTAL; } // // check the input arguments // LPCTSTR NewInf = NULL; LPCTSTR NewDb = NULL; LPCTSTR NewLog = NULL; __try { if ( InfFileName && wcslen(InfFileName) > 0 ) { NewInf = InfFileName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } __try { if ( DatabaseName && wcslen(DatabaseName) > 0 ) { NewDb = DatabaseName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } __try { if ( LogFileName && wcslen(LogFileName) > 0 ) { NewLog = LogFileName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } // // RPC bind to the server // NtStatus = ScepBindSecureRpc( SystemName, L"scerpc", L"security=impersonation dynamic false", &binding_h ); if (NT_SUCCESS(NtStatus)){ LPVOID pebClient = GetEnvironmentStrings(); DWORD ebSize = ScepGetEnvStringSize(pebClient); RpcTryExcept { DWORD dwWarn=0; rc = SceRpcAnalyzeSystem( binding_h, (wchar_t *)NewInf, (wchar_t *)NewDb, (wchar_t *)NewLog, (AREAPR)Area, dOptions, ebSize, (UCHAR *)pebClient, &dwWarn ); if ( pdWarning ) { *pdWarning = dwWarn; } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); if(pebClient) { FreeEnvironmentStrings((LPTSTR)pebClient); } } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } ScepSetCallback(NULL, NULL, 0); return(rc); } SCESTATUS WINAPI SceGenerateRollback( IN LPTSTR SystemName OPTIONAL, IN PCWSTR InfFileName, IN PCWSTR InfRollback, IN PCWSTR LogFileName OPTIONAL, IN DWORD Options, IN AREA_INFORMATION Area, OUT PDWORD pdWarning OPTIONAL ) /* ++ Routine Description: Routine to generate a rollback template based on the input configuration template. Must be called by admins. System database is used to analyze system settings with the confgiuration template and mismatches are saved to the rollback template on top of the configuration. Options can contain flags such as verbose log and no log A warning code is also returned if there is any warning occurs during the operation while the SCESTATUS return code is SCESTATUS_SUCCESS. Examples such as ERROR_FILE_NOT_FOUND, or ERROR_ACCESS_DENIED when querying the system won't be counted as error of this operation Arguments: SystemName - the system name where this operation will run, NULL for local system InfFileName - optional inf template name, if NULL, existing info in the SCe database is used to configure. InfRollback - the rollback template name LogFileName - optional log file name for the operation Options - the options to configure SCE_VERBOSE_LOG SCE_DISABLE_LOG Area - reserved pdWarning - the warning code Return Value: SCE status -- */ { if ( InfFileName == NULL || InfRollback == NULL ) return (SCESTATUS_INVALID_PARAMETER); SCESTATUS rc; handle_t binding_h; NTSTATUS NtStatus; DWORD dOptions; // // filter out invalid options // dOptions = Options & 0xFFL; // // check the input arguments // LPCTSTR NewLog = NULL; if ( InfFileName[0] == L'\0' || InfRollback[0] == L'\0' ) { return(SCESTATUS_INVALID_PARAMETER); } __try { if ( LogFileName && wcslen(LogFileName) > 0 ) { NewLog = LogFileName; } } __except (EXCEPTION_EXECUTE_HANDLER) { } // // RPC bind to the server // NtStatus = ScepBindSecureRpc( SystemName, L"scerpc", L"security=impersonation dynamic false", &binding_h ); if (NT_SUCCESS(NtStatus)){ LPVOID pebClient = GetEnvironmentStrings(); DWORD ebSize = ScepGetEnvStringSize(pebClient); RpcTryExcept { DWORD dwWarn=0; rc = SceRpcAnalyzeSystem( binding_h, (wchar_t *)InfFileName, (wchar_t *)InfRollback, (wchar_t *)NewLog, (AREAPR)Area, dOptions | SCE_GENERATE_ROLLBACK, ebSize, (UCHAR *)pebClient, &dwWarn ); if ( pdWarning ) { *pdWarning = dwWarn; } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); if(pebClient) { FreeEnvironmentStrings((LPTSTR)pebClient); } } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } return(rc); } SCESTATUS WINAPI SceUpdateSecurityProfile( IN PVOID cxtProfile OPTIONAL, IN AREA_INFORMATION Area, IN PSCE_PROFILE_INFO pInfo, IN DWORD dwMode ) /* Routine Description: See description in SceRpcUpdateDatabaseInfo */ { if ( !pInfo ) { return(SCESTATUS_INVALID_PARAMETER); } if ( !cxtProfile && !(dwMode & SCE_UPDATE_SYSTEM ) ) { // // if it's not update for system, profile context can't be NULL. // return(SCESTATUS_INVALID_PARAMETER); } if ( ( dwMode & (SCE_UPDATE_LOCAL_POLICY | SCE_UPDATE_SYSTEM) ) && ( Area & ~(AREA_SECURITY_POLICY | AREA_PRIVILEGES) ) ) { // // local policy mode can only take security policy area and // privileges area // return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc=SCESTATUS_SUCCESS; PSCE_SERVICES pOldServices=NULL; if ( pInfo && pInfo->pServices ) { // // save the old service structure // pOldServices = pInfo->pServices; } if ( Area & AREA_SYSTEM_SERVICE ) { // // now convert the security descriptor (within PSCE_SERVICES) to self // relative format and to the RPC structure. // rc = ScepConvertServices( (PVOID *)&(pInfo->pServices), FALSE ); } else { // // if don't care service area, don't bother to convert the structures // pInfo->pServices = NULL; } if ( SCESTATUS_SUCCESS == rc ) { RpcTryExcept { if ( dwMode & SCE_UPDATE_SYSTEM ) { PSCE_ERROR_LOG_INFO pErrTmp=NULL; if ( cxtProfile ) { rc = SceRpcSetSystemSecurityFromHandle( (SCEPR_CONTEXT)cxtProfile, (AREAPR)Area, 0, (PSCEPR_PROFILE_INFO)pInfo, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); } else { // // set system settings // for normal user, the local policy database can't be opened. // // RPC bind to the server // handle_t binding_h; NTSTATUS NtStatus = ScepBindSecureRpc( NULL, L"scerpc", 0, &binding_h ); if (NT_SUCCESS(NtStatus)){ RpcTryExcept { rc = SceRpcSetSystemSecurity( binding_h, (AREAPR)Area, 0, (PSCEPR_PROFILE_INFO)pInfo, (PSCEPR_ERROR_LOG_INFO *)&pErrTmp ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } } if ( pErrTmp ) { // // free this tmp buffer // ScepFreeErrorLog(pErrTmp); } } else { rc = SceRpcUpdateDatabaseInfo( (SCEPR_CONTEXT)cxtProfile, (SCEPR_TYPE)(pInfo->Type), (AREAPR)Area, (PSCEPR_PROFILE_INFO)pInfo, dwMode ); } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; } // // should free the new service security descriptor buffer // ScepFreeConvertedServices( (PVOID)(pInfo->pServices), TRUE ); // // restore the old buffer // pInfo->pServices = pOldServices; return(rc); } SCESTATUS WINAPI SceUpdateObjectInfo( IN PVOID cxtProfile, IN AREA_INFORMATION Area, IN PWSTR ObjectName, IN DWORD NameLen, // number of characters IN BYTE ConfigStatus, IN BOOL IsContainer, IN PSECURITY_DESCRIPTOR pSD, IN SECURITY_INFORMATION SeInfo, OUT PBYTE pAnalysisStatus ) /* Routine Description: See description in SceRpcUpdateObjectInfo */ { if ( !cxtProfile || !ObjectName || 0 == Area ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc=SCESTATUS_SUCCESS; // // handle RPC exceptions // PSCEPR_SR_SECURITY_DESCRIPTOR pNewWrap=NULL; PSECURITY_DESCRIPTOR pNewSrSD=NULL; // // there is a security descriptor, must be self relative // if the SD is not self relative, should convert it // if ( pSD ) { if ( !RtlValidSid (pSD) ) { return(SCESTATUS_INVALID_PARAMETER); } SECURITY_DESCRIPTOR_CONTROL ControlBits=0; ULONG Revision; ULONG nLen=0; RtlGetControlSecurityDescriptor ( pSD, &ControlBits, &Revision); if ( !(ControlBits & SE_SELF_RELATIVE) ) { // // if it's absolute format, convert it // rc = ScepDosErrorToSceStatus( ScepMakeSelfRelativeSD( pSD, &pNewSrSD, &nLen ) ); if ( SCESTATUS_SUCCESS != rc ) { return(rc); } } else { // // already self relative, just use it // nLen = RtlLengthSecurityDescriptor (pSD); } if ( nLen > 0 ) { // // create a wrapper node to contain the security descriptor // pNewWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)ScepAlloc(0, sizeof(SCEPR_SR_SECURITY_DESCRIPTOR)); if ( pNewWrap ) { // // assign the wrap to the structure // if ( ControlBits & SE_SELF_RELATIVE ) { pNewWrap->SecurityDescriptor = (UCHAR *)pSD; } else { pNewWrap->SecurityDescriptor = (UCHAR *)pNewSrSD; } pNewWrap->Length = nLen; } else { // // no memory is available, but still continue to parse all nodes // rc = SCESTATUS_NOT_ENOUGH_RESOURCE; } } else { // // something is wrong with the SD // rc = SCESTATUS_INVALID_PARAMETER; } if ( SCESTATUS_SUCCESS != rc ) { if ( pNewSrSD ) { ScepFree(pNewSrSD); } return(rc); } } RpcTryExcept { rc = SceRpcUpdateObjectInfo( (SCEPR_CONTEXT)cxtProfile, (AREAPR)Area, (wchar_t *)ObjectName, NameLen, ConfigStatus, IsContainer, (SCEPR_SR_SECURITY_DESCRIPTOR *)pNewWrap, SeInfo, pAnalysisStatus ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; if ( pNewSrSD ) { ScepFree(pNewSrSD); } return(rc); } SCESTATUS WINAPI SceStartTransaction( IN PVOID cxtProfile ) { if ( cxtProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc; RpcTryExcept { rc = SceRpcStartTransaction((SCEPR_CONTEXT)cxtProfile); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceCommitTransaction( IN PVOID cxtProfile ) { if ( cxtProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc; RpcTryExcept { rc = SceRpcCommitTransaction((SCEPR_CONTEXT)cxtProfile); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceRollbackTransaction( IN PVOID cxtProfile ) { if ( cxtProfile == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc; RpcTryExcept { rc = SceRpcRollbackTransaction((SCEPR_CONTEXT)cxtProfile); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceGetServerProductType( IN LPTSTR SystemName OPTIONAL, OUT PSCE_SERVER_TYPE pServerType ) /* Routine Description: Query product type and NT version of the server where SCE server is running on See description of SceRpcGetServerProductType */ { if ( !SystemName ) { // // the local call // return(ScepGetProductType(pServerType)); } handle_t binding_h; NTSTATUS NtStatus; SCESTATUS rc; // // RPC bind to the server // NtStatus = ScepBindSecureRpc( SystemName, L"scerpc", 0, &binding_h ); if (NT_SUCCESS(NtStatus)){ // // handle RPC exceptions // RpcTryExcept { rc = SceRpcGetServerProductType( binding_h, (PSCEPR_SERVER_TYPE)pServerType ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; // // Free the binding handle // RpcpUnbindRpc( binding_h ); } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } return(rc); } SCESTATUS WINAPI SceSvcUpdateInfo( IN PVOID hProfile, IN PCWSTR ServiceName, IN PSCESVC_CONFIGURATION_INFO Info ) /* Routine Description: Load service's engine dll and pass the Info buffer to service engine's update API (SceSvcAttachmentUpdate). Currently security manager engine is not doing any processing for the service data. This routine triggers the update of configuration database and/or analysis information by the service engine. Info may contain the modifications only, or the whole configuratio data for the service, or partial configuration data, depending on the agreement between service extension and service engine. This routine does not really write info to security manager database directly, instead, it passes the info buffer to the service engine's update interface and service engine will determine what and when to write inot the database. Arguments: hProfile - the security database handle (returned from SCE server) ServiceName - The service's name as used by service control manager Info - The information modified */ { if ( hProfile == NULL || ServiceName == NULL || Info == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } SCESTATUS rc; RpcTryExcept { // // call the RPC interface to update info. // the RPC interface loads service engine dll on the server site // and passes the info buffer to service engine to process // rc = SceSvcRpcUpdateInfo( (SCEPR_CONTEXT)hProfile, (wchar_t *)ServiceName, (PSCEPR_SVCINFO)Info ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) and convert it into SCESTATUS // rc = ScepDosErrorToSceStatus( RpcExceptionCode()); } RpcEndExcept; return(rc); } DWORD WINAPI SceRegisterRegValues( IN LPTSTR InfFileName ) /* Routine Description: Register the registry values from the inf file into reg values location under SecEdit key This routine can be called from DllRegisterServer, or from the command line tool /register Arguments: InfFileName - the inf file which contains the register values to register Return Value: Win32 error code */ { if ( !InfFileName ) { return(ERROR_INVALID_PARAMETER); } SCESTATUS rc; HINF hInf; DWORD Win32rc; rc = SceInfpOpenProfile( InfFileName, &hInf ); if ( SCESTATUS_SUCCESS == rc ) { INFCONTEXT InfLine; HKEY hKeyRoot; DWORD dwDisp; if(SetupFindFirstLine(hInf,SCE_REGISTER_REGVALUE_SECTION,NULL,&InfLine)) { // // create the root key first // Win32rc = RegCreateKeyEx (HKEY_LOCAL_MACHINE, SCE_ROOT_REGVALUE_PATH, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKeyRoot, &dwDisp); if ( ERROR_SUCCESS == Win32rc || ERROR_ALREADY_EXISTS == Win32rc ) { DWORD dSize; PWSTR RegKeyName, DisplayName; DWORD dType; HKEY hKey; do { // // Get key names, value type, diaply name, and display type. // if(SetupGetStringField(&InfLine,1,NULL,0,&dSize) && dSize > 0) { RegKeyName = (PWSTR)ScepAlloc( 0, (dSize+1)*sizeof(WCHAR)); if( RegKeyName == NULL ) { Win32rc = ERROR_NOT_ENOUGH_MEMORY; } else { RegKeyName[dSize] = L'\0'; if(SetupGetStringField(&InfLine,1,RegKeyName,dSize, NULL)) { // // make sure not \\ is specified, if there is // change it to / // ScepConvertMultiSzToDelim(RegKeyName, dSize, L'\\', L'/'); // // get the filed count // if count is 1, this key should be deleted // dwDisp = SetupGetFieldCount( &InfLine ); if ( dwDisp <= 1 ) { // // delete this key, don't care error // RegDeleteKey ( hKeyRoot, RegKeyName ); Win32rc = ERROR_SUCCESS; } else { Win32rc = RegCreateKeyEx (hKeyRoot, RegKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); } if ( (dwDisp > 1) && ERROR_SUCCESS == Win32rc || ERROR_ALREADY_EXISTS == Win32rc ) { // // get registry value type // dType = REG_DWORD; SetupGetIntField( &InfLine, 2, (INT *)&dType ); RegSetValueEx (hKey, SCE_REG_VALUE_TYPE, 0, REG_DWORD, (LPBYTE)&dType, sizeof(DWORD)); // // get registry value display type // dType = SCE_REG_DISPLAY_ENABLE; SetupGetIntField( &InfLine, 4, (INT *)&dType ); RegSetValueEx (hKey, SCE_REG_DISPLAY_TYPE, 0, REG_DWORD, (LPBYTE)&dType, sizeof(DWORD)); // // get registry display name // if(SetupGetStringField(&InfLine,3,NULL,0,&dSize) && dSize > 0) { DisplayName = (PWSTR)ScepAlloc( 0, (dSize+1)*sizeof(WCHAR)); if( DisplayName == NULL ) { Win32rc = ERROR_NOT_ENOUGH_MEMORY; } else { DisplayName[dSize] = L'\0'; if(SetupGetStringField(&InfLine,3,DisplayName,dSize, NULL)) { RegSetValueEx (hKey, SCE_REG_DISPLAY_NAME, 0, REG_SZ, (LPBYTE)DisplayName, dSize*sizeof(TCHAR)); } ScepFree(DisplayName); DisplayName = NULL; } } // // get registry display unit (optional) // if ( dType == SCE_REG_DISPLAY_NUMBER || dType == SCE_REG_DISPLAY_CHOICE || dType == SCE_REG_DISPLAY_FLAGS ) { if ( SetupGetMultiSzField(&InfLine,5,NULL,0,&dSize) && dSize > 0) { DisplayName = (PWSTR)ScepAlloc( 0, (dSize+1)*sizeof(WCHAR)); if( DisplayName == NULL ) { Win32rc = ERROR_NOT_ENOUGH_MEMORY; } else { DisplayName[dSize] = L'\0'; if(SetupGetMultiSzField(&InfLine,5,DisplayName,dSize, NULL)) { if ( dType == SCE_REG_DISPLAY_NUMBER ) { dSize = wcslen(DisplayName); } switch (dType) { case SCE_REG_DISPLAY_NUMBER: RegSetValueEx (hKey, SCE_REG_DISPLAY_UNIT, 0, REG_SZ, (LPBYTE)DisplayName, dSize*sizeof(TCHAR)); break; case SCE_REG_DISPLAY_CHOICE: RegSetValueEx (hKey, SCE_REG_DISPLAY_CHOICES, 0, REG_MULTI_SZ, (LPBYTE)DisplayName, dSize*sizeof(TCHAR)); break; case SCE_REG_DISPLAY_FLAGS: RegSetValueEx (hKey, SCE_REG_DISPLAY_FLAGLIST, 0, REG_MULTI_SZ, (LPBYTE)DisplayName, dSize*sizeof(TCHAR)); break; default: break; } } ScepFree(DisplayName); DisplayName = NULL; } } } RegCloseKey(hKey); hKey = NULL; } } else { Win32rc = GetLastError(); } ScepFree(RegKeyName); RegKeyName = NULL; } } else { Win32rc = GetLastError(); } if ( ERROR_SUCCESS != Win32rc ) { break; } } while (SetupFindNextLine(&InfLine,&InfLine)); RegCloseKey(hKeyRoot); } } else { Win32rc = GetLastError(); } SceInfpCloseProfile(hInf); } else { Win32rc = ScepSceStatusToDosError(rc); } return(Win32rc); } // // the RPC callback // SCEPR_STATUS SceClientBrowseCallback( IN LONG GpoID, IN wchar_t *KeyName OPTIONAL, IN wchar_t *GpoName OPTIONAL, IN SCEPR_SR_SECURITY_DESCRIPTOR *Value OPTIONAL ) /* Routine Description: The RPC client callback routine which is called from the server when the callback flag is set. This routine is registered in scerpc.idl. The callbacks are registered to SCE as arguments when calling from the browse API Arguments: Return Value: SCEPR_STATUS */ { // // the static variables holding callback pointer to client // if ( theBrowseCallBack != NULL ) { // // callback to browse progress // PSCE_BROWSE_CALLBACK_ROUTINE pcb; pcb = (PSCE_BROWSE_CALLBACK_ROUTINE)theBrowseCallBack; __try { // // callback // if ( !((*pcb)(GpoID, KeyName, GpoName, ((Value && Value->Length) ? (PWSTR)(Value->SecurityDescriptor) : NULL), Value ? (Value->Length)/sizeof(WCHAR) : 0 )) ) { return SCESTATUS_SERVICE_NOT_SUPPORT; } } __except(EXCEPTION_EXECUTE_HANDLER) { return(SCESTATUS_INVALID_PARAMETER); } } return(SCESTATUS_SUCCESS); } SCESTATUS SceBrowseDatabaseTable( IN PWSTR DatabaseName OPTIONAL, IN SCETYPE ProfileType, IN AREA_INFORMATION Area, IN BOOL bDomainPolicyOnly, IN PSCE_BROWSE_CALLBACK_ROUTINE pCallback OPTIONAL ) { if ( bDomainPolicyOnly && (ProfileType != SCE_ENGINE_SCP) && (ProfileType != SCE_ENGINE_SAP) ) { return(SCESTATUS_INVALID_PARAMETER); } if ( bDomainPolicyOnly && (ProfileType == SCE_ENGINE_SAP) ) { /* // No, should allow any database for debugging // // should only work for the system database // if ( DatabaseName != NULL && !SceIsSystemDatabase(DatabaseName) ) { return(SCESTATUS_INVALID_PARAMETER); } */ if ( DatabaseName == NULL ) { // // if it's a normal user logon, should return invalid // BOOL bAdmin=FALSE; if ( ERROR_SUCCESS != ScepIsAdminLoggedOn(&bAdmin, FALSE) || !bAdmin ) return(SCESTATUS_INVALID_PARAMETER); } } if ( ProfileType != SCE_ENGINE_SCP && ProfileType != SCE_ENGINE_SMP && ProfileType != SCE_ENGINE_SAP ) { return(SCESTATUS_INVALID_PARAMETER); } NTSTATUS NtStatus; SCESTATUS rc; handle_t binding_h; // // RPC bind to the server // NtStatus = ScepBindSecureRpc( NULL, L"scerpc", 0, &binding_h ); if (NT_SUCCESS(NtStatus)){ theBrowseCallBack = (PVOID)pCallback; RpcTryExcept { rc = SceRpcBrowseDatabaseTable( binding_h, (wchar_t *)DatabaseName, (SCEPR_TYPE)ProfileType, (AREAPR)Area, bDomainPolicyOnly ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; theBrowseCallBack = NULL; // // Free the binding handle // RpcpUnbindRpc( binding_h ); } else { rc = ScepDosErrorToSceStatus( RtlNtStatusToDosError( NtStatus )); } return(rc); } SCESTATUS ScepConvertServices( IN OUT PVOID *ppServices, IN BOOL bSRForm ) { if ( !ppServices ) { return(SCESTATUS_INVALID_PARAMETER); } PSCE_SERVICES pTemp = (PSCE_SERVICES)(*ppServices); SCESTATUS rc=SCESTATUS_SUCCESS; PSCE_SERVICES pNewNode; PSCE_SERVICES pNewServices=NULL; while ( pTemp ) { pNewNode = (PSCE_SERVICES)ScepAlloc(0,sizeof(SCE_SERVICES)); if ( pNewNode ) { pNewNode->ServiceName = pTemp->ServiceName; pNewNode->DisplayName = pTemp->DisplayName; pNewNode->Status = pTemp->Status; pNewNode->Startup = pTemp->Startup; pNewNode->SeInfo = pTemp->SeInfo; pNewNode->General.pSecurityDescriptor = NULL; pNewNode->Next = pNewServices; pNewServices = pNewNode; if ( bSRForm ) { // // Service node is in SCEPR_SERVICES structure // convert it to SCE_SERVICES structure // in this case, just use the self relative security descriptor // if ( pTemp->General.pSecurityDescriptor) { pNewNode->General.pSecurityDescriptor = ((PSCEPR_SERVICES)pTemp)->pSecurityDescriptor->SecurityDescriptor; } } else { // // Service node is in SCE_SERVICES strucutre // convert it to SCEPR_SERVICES structure // // make the SD to self relative format and PSCEPR_SR_SECURITY_DESCRIPTOR // if ( pTemp->General.pSecurityDescriptor ) { if ( !RtlValidSid ( pTemp->General.pSecurityDescriptor ) ) { rc = SCESTATUS_INVALID_PARAMETER; break; } DWORD nLen = 0; PSECURITY_DESCRIPTOR pSD=NULL; rc = ScepDosErrorToSceStatus( ScepMakeSelfRelativeSD( pTemp->General.pSecurityDescriptor, &pSD, &nLen )); if ( SCESTATUS_SUCCESS == rc ) { // // create a wrapper node to contain the security descriptor // PSCEPR_SR_SECURITY_DESCRIPTOR pNewWrap; pNewWrap = (PSCEPR_SR_SECURITY_DESCRIPTOR)ScepAlloc(0, sizeof(SCEPR_SR_SECURITY_DESCRIPTOR)); if ( pNewWrap ) { // // assign the wrap to the structure // pNewWrap->SecurityDescriptor = (UCHAR *)pSD; pNewWrap->Length = nLen; } else { rc = SCESTATUS_NOT_ENOUGH_RESOURCE; ScepFree(pSD); break; } // // now link the SR_SD to the list // ((PSCEPR_SERVICES)pNewNode)->pSecurityDescriptor = pNewWrap; } else { break; } } } } else { // // all allocated buffer are in the list of pNewServices // rc = SCESTATUS_NOT_ENOUGH_RESOURCE; break; } pTemp = pTemp->Next; } if ( SCESTATUS_SUCCESS != rc ) { // // free pNewServices // ScepFreeConvertedServices( (PVOID)pNewServices, !bSRForm ); pNewServices = NULL; } *ppServices = (PVOID)pNewServices; return(rc); } SCESTATUS ScepFreeConvertedServices( IN PVOID pServices, IN BOOL bSRForm ) { if ( pServices == NULL ) { return(SCESTATUS_SUCCESS); } PSCEPR_SERVICES pNewNode = (PSCEPR_SERVICES)pServices; PSCEPR_SERVICES pTempNode; while ( pNewNode ) { if ( bSRForm && pNewNode->pSecurityDescriptor ) { // // free this allocated buffer (PSCEPR_SR_SECURITY_DESCRIPTOR) // if ( pNewNode->pSecurityDescriptor->SecurityDescriptor ) { ScepFree( pNewNode->pSecurityDescriptor->SecurityDescriptor); } ScepFree(pNewNode->pSecurityDescriptor); } // // also free the PSCEPR_SERVICE node (but not the names referenced by this node) // pTempNode = pNewNode; pNewNode = pNewNode->Next; ScepFree(pTempNode); } return(SCESTATUS_SUCCESS); } DWORD ScepMakeSelfRelativeSD( IN PSECURITY_DESCRIPTOR pInSD, OUT PSECURITY_DESCRIPTOR *pOutSD, OUT PULONG pnLen ) { if ( pInSD == NULL || pOutSD == NULL || pnLen == NULL ) { return(ERROR_INVALID_PARAMETER); } // // get the length // RtlMakeSelfRelativeSD( pInSD, NULL, pnLen ); if ( *pnLen > 0 ) { *pOutSD = (PSECURITY_DESCRIPTOR)ScepAlloc(LMEM_ZEROINIT, *pnLen); if ( !(*pOutSD) ) { return(ERROR_NOT_ENOUGH_MEMORY); } DWORD NewLen=*pnLen; DWORD rc = RtlNtStatusToDosError( RtlMakeSelfRelativeSD( pInSD, *pOutSD, &NewLen ) ); if ( rc != ERROR_SUCCESS ) { ScepFree(*pOutSD); *pOutSD = NULL; *pnLen = 0; return(rc); } } else { // // something is wrong with the SD // return(ERROR_INVALID_PARAMETER); } return(ERROR_SUCCESS); } SCESTATUS WINAPI SceGetDatabaseSetting( IN PVOID hProfile, IN SCETYPE ProfileType, IN PWSTR SectionName, IN PWSTR KeyName, OUT PWSTR *Value, OUT DWORD *pnBytes OPTIONAL ) /* Routine Descripton: Get database setting (from SMP table) for the given key Arguments: hProfile - the profile handle ProfileType - the database type SectionName - the section to query data from KeyName - the key name Value - output buffer for the setting ValueLen - the nubmer of bytes to output Return Value: SCE status */ { SCESTATUS rc; if ( hProfile == NULL || KeyName == NULL || SectionName == NULL || Value == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( ProfileType != SCE_ENGINE_SMP ) { return(SCESTATUS_INVALID_PARAMETER); } // // call rpc interface // PSCEPR_VALUEINFO ValueInfo=NULL; RpcTryExcept { rc = SceRpcGetDatabaseSetting( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (wchar_t *)SectionName, (wchar_t *)KeyName, &ValueInfo ); if ( ValueInfo && ValueInfo->Value ) { // // output the data // *Value = (PWSTR)ValueInfo->Value; if ( pnBytes ) *pnBytes = ValueInfo->ValueLen; ValueInfo->Value = NULL; } // // free buffer if ( ValueInfo ) { if ( ValueInfo->Value ) ScepFree(ValueInfo->Value); ScepFree(ValueInfo); } } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } SCESTATUS WINAPI SceSetDatabaseSetting( IN PVOID hProfile, IN SCETYPE ProfileType, IN PWSTR SectionName, IN PWSTR KeyName, IN PWSTR Value OPTIONAL, IN DWORD nBytes ) /* Routine Descripton: Set a setting to the database (SMP table) for the given key Arguments: hProfile - the profile handle ProfileType - the database type SectionName - the section name to write to KeyName - the key name to write to or delete Value - the value to write. If NULL, delete the key nBytes - the number of bytes of the input Value buffer Return Value: SCE status */ { SCESTATUS rc; if ( hProfile == NULL || SectionName == NULL || KeyName == NULL ) { return(SCESTATUS_INVALID_PARAMETER); } if ( ProfileType != SCE_ENGINE_SMP ) { return(SCESTATUS_INVALID_PARAMETER); } // // call rpc interface // RpcTryExcept { SCEPR_VALUEINFO ValueInfo; ValueInfo.Value = (byte *)Value; ValueInfo.ValueLen = nBytes; rc = SceRpcSetDatabaseSetting( (SCEPR_CONTEXT)hProfile, (SCEPR_TYPE)ProfileType, (wchar_t *)SectionName, (wchar_t *)KeyName, Value ? &ValueInfo : NULL ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = ScepDosErrorToSceStatus(RpcExceptionCode()); } RpcEndExcept; return(rc); } DWORD ScepControlNotificationQProcess( IN PWSTR szLogFileName, IN BOOL bThisIsDC, IN DWORD ControlFlag ) /* Description: To suspend or resume policy notification queue processing on DCs This routine is used to make sure that the latest group policy is being processed in policy proapgation (copied to the cache) */ { if ( !bThisIsDC ) return ERROR_SUCCESS; handle_t binding_h; NTSTATUS NtStatus; DWORD rc; NtStatus = ScepBindRpc( NULL, L"scerpc", L"security=impersonation dynamic false", &binding_h ); rc = RtlNtStatusToDosError( NtStatus ); if (NT_SUCCESS(NtStatus)){ RpcTryExcept { rc = SceRpcControlNotificationQProcess( binding_h, ControlFlag ); } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) { // // get exception code (DWORD) // rc = RpcExceptionCode(); } RpcEndExcept; } // // Free the binding handle // RpcpUnbindRpc( binding_h ); // // log the operation // if ( szLogFileName ) { LogEventAndReport(MyModuleHandle, szLogFileName, 1, 0, IDS_CONTROL_QUEUE, rc, ControlFlag ); } return rc; }