mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3915 lines
96 KiB
3915 lines
96 KiB
/*++
|
|
|
|
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 <ntrpcp.h>
|
|
|
|
#include <rpcasync.h>
|
|
|
|
#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
|
|
//
|
|
|
|
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);
|
|
|
|
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) {
|
|
|
|
}
|
|
/*
|
|
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
|
!(ConfigOptions & SCE_NO_CONFIG) &&
|
|
(Area & (AREA_SECURITY_POLICY | AREA_PRIVILEGES)) ) {
|
|
|
|
//
|
|
// turn off policy filter
|
|
//
|
|
ScepRegSetIntValue(HKEY_LOCAL_MACHINE,
|
|
SCE_ROOT_PATH,
|
|
TEXT("PolicyFilterOff"),
|
|
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 );
|
|
|
|
} else {
|
|
|
|
rc = ScepDosErrorToSceStatus(
|
|
RtlNtStatusToDosError( NtStatus ));
|
|
}
|
|
|
|
/*
|
|
if ( (ConfigOptions & SCE_POLICY_TEMPLATE) &&
|
|
!(ConfigOptions & SCE_NO_CONFIG) &&
|
|
(Area & (AREA_SECURITY_POLICY | AREA_PRIVILEGES)) ) {
|
|
|
|
//
|
|
// delete the value
|
|
//
|
|
dOptions = ScepRegDeleteValue(HKEY_LOCAL_MACHINE,
|
|
SCE_ROOT_PATH,
|
|
TEXT("PolicyFilterOff")
|
|
);
|
|
|
|
if ( dOptions != ERROR_SUCCESS &&
|
|
dOptions != ERROR_FILE_NOT_FOUND &&
|
|
dOptions != ERROR_PATH_NOT_FOUND ) {
|
|
|
|
ScepRegSetIntValue(HKEY_LOCAL_MACHINE,
|
|
SCE_ROOT_PATH,
|
|
TEXT("PolicyFilterOff"),
|
|
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);
|
|
|
|
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 );
|
|
|
|
} 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 );
|
|
|
|
} 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) || !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;
|
|
|
|
}
|
|
|
|
|