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.
6510 lines
195 KiB
6510 lines
195 KiB
/*++
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pfget.cpp
|
|
|
|
Abstract:
|
|
|
|
Routines to get information from jet database (configuration/analysis
|
|
info).
|
|
|
|
Author:
|
|
|
|
Jin Huang (jinhuang) 28-Oct-1996
|
|
|
|
Revision History:
|
|
|
|
jinhuang 26-Jan-1998 splitted to client-server
|
|
|
|
--*/
|
|
|
|
#include "serverp.h"
|
|
#include <io.h>
|
|
#include "pfp.h"
|
|
#include "kerberos.h"
|
|
#include "regvalue.h"
|
|
#include <sddl.h>
|
|
#pragma hdrstop
|
|
|
|
//#define SCE_DBG 1
|
|
#define SCE_INTERNAL_NP 0x80
|
|
#define SCE_ALLOC_MAX_NODE 10
|
|
|
|
typedef struct _SCE_BROWSE_CALLBACK_VALUE {
|
|
|
|
DWORD Len;
|
|
UCHAR *Value;
|
|
|
|
} SCE_BROWSE_CALLBACK_VALUE;
|
|
|
|
|
|
//
|
|
// Forward references
|
|
//
|
|
|
|
SCESTATUS
|
|
ScepGetSystemAccess(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_PROFILE_INFO pProfileInfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetVariableValue(
|
|
IN PSCESECTION hSection,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR KeyName,
|
|
OUT PWSTR *Value,
|
|
OUT PDWORD ValueLen
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepAddToPrivilegeList(
|
|
OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
|
|
IN PWSTR Name,
|
|
IN DWORD Len,
|
|
IN DWORD PrivValue
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetGroupMembership(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetGroupMembershipFromOneTable(
|
|
IN LSA_HANDLE LsaPolicy,
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetObjectList(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
SCESTATUS
|
|
ScepGetDsRoot(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepBuildDsTree(
|
|
OUT PSCE_OBJECT_CHILD_LIST *TreeRoot,
|
|
IN ULONG Level,
|
|
IN WCHAR Delim,
|
|
IN PCWSTR ObjectFullName
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetObjectFromOneTable(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetObjectChildrenFromOneTable(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectPrefix,
|
|
IN SCE_SUBOBJECT_TYPE Option,
|
|
OUT PVOID *Buffer,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
BYTE
|
|
ScepGetObjectStatusFlag(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectPrefix,
|
|
IN BOOL bLookForParent
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetAuditing(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_PROFILE_INFO pProfileInfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetPrivilegesFromOneTable(
|
|
IN LSA_HANDLE LsaPolicy,
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN DWORD dwAccountFormat,
|
|
OUT PVOID *pPrivileges,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepGetSystemServices(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_SERVICES *pServiceList,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
BOOL
|
|
ScepSearchItemInChildren(
|
|
IN PWSTR ItemName,
|
|
IN DWORD NameLen,
|
|
IN PSCE_OBJECT_CHILDREN_NODE *pArrObject,
|
|
IN DWORD arrCount,
|
|
OUT LONG *pFindIndex
|
|
);
|
|
|
|
|
|
DWORD
|
|
ScepAddItemToChildren(
|
|
IN PSCE_OBJECT_CHILDREN_NODE ThisNode OPTIONAL,
|
|
IN PWSTR ItemName,
|
|
IN DWORD NameLen,
|
|
IN BOOL IsContainer,
|
|
IN BYTE Status,
|
|
IN DWORD ChildCount,
|
|
IN OUT PSCE_OBJECT_CHILDREN_NODE **ppArrObject,
|
|
IN OUT DWORD *pArrCount,
|
|
IN OUT DWORD *pMaxCount,
|
|
IN OUT LONG *pFindIndex
|
|
);
|
|
|
|
PWSTR
|
|
ScepSpecialCaseRegkeyCcs(
|
|
IN OUT PWSTR ObjectName
|
|
);
|
|
|
|
|
|
//
|
|
// function definitions
|
|
//
|
|
|
|
SCESTATUS
|
|
ScepGetDatabaseInfo(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN DWORD dwAccountFormat,
|
|
OUT PSCE_PROFILE_INFO *ppInfoBuffer,
|
|
IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/**++
|
|
|
|
Function Description:
|
|
|
|
This function reads all or part of information from a SCP/SAP/SMP profile
|
|
depending on the ProfileType, into the InfoBuffer. ProfileType is saved in
|
|
the ppInfoBuffer's Type field.
|
|
|
|
A handle to the profile (Jet database) is passed into the routine every
|
|
time this routine is called. Area specifies one or more pre-defined security
|
|
areas to get information. One area's information may be saved in multiple
|
|
sections in the profile.
|
|
|
|
The memory related to the area(s) will be reset/freed before loading
|
|
information from the profile. If the return code is SCESTATUS_SUCCESS, then
|
|
the output InfoBuffer contains the requested information. Otherwise,
|
|
InfoBuffer contains nothing for the area(s) specified.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The handle to the profile to read from.
|
|
|
|
ProfileType - value to indicate engine type.
|
|
SCE_ENGINE_SCP
|
|
SCE_ENGINE_SAP
|
|
SCE_ENGINE_SMP
|
|
|
|
Area - area(s) for which to get information from
|
|
AREA_SECURITY_POLICY
|
|
AREA_PRIVILEGES
|
|
AREA_GROUP_MEMBERSHIP
|
|
AREA_REGISTRY_SECURITY
|
|
AREA_SYSTEM_SERVICE
|
|
AREA_FILE_SECURITY
|
|
|
|
ppInfoBuffer - The address of SCP/SAP/SMP buffers. If it is NULL, a buffer
|
|
will be created which must be freed by LocalFree. The
|
|
output is the information requested if successful, or
|
|
nothing if fail.
|
|
|
|
Errlog - A buffer to hold all error codes/text encountered when
|
|
parsing the INF file. If Errlog is NULL, no further error
|
|
information is returned except the return DWORD
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
-- **/
|
|
{
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD Len;
|
|
BOOL bBufAlloc=FALSE;
|
|
NT_PRODUCT_TYPE theType;
|
|
|
|
//
|
|
// if the JET database is not opened then return
|
|
//
|
|
|
|
if ( hProfile == NULL ) {
|
|
|
|
return( SCESTATUS_INVALID_PARAMETER );
|
|
}
|
|
|
|
//
|
|
// address for InfoBuffer cannot be NULL
|
|
//
|
|
if ( ppInfoBuffer == NULL ) {
|
|
return( SCESTATUS_INVALID_PARAMETER );
|
|
}
|
|
|
|
//
|
|
// check scetype
|
|
//
|
|
if ( ProfileType > SCE_ENGINE_SMP ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// check to see if there is a SMP or SCP table
|
|
//
|
|
if ( hProfile->JetSmpID == JET_tableidNil ||
|
|
hProfile->JetScpID == JET_tableidNil ) {
|
|
return(SCESTATUS_PROFILE_NOT_FOUND);
|
|
}
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO &&
|
|
hProfile->JetScpID == hProfile->JetSmpID ) {
|
|
//
|
|
// there is no domain GPO policy
|
|
//
|
|
return(SCESTATUS_PROFILE_NOT_FOUND);
|
|
}
|
|
//
|
|
// design on this part is changed.
|
|
// if there is no SAP table which means the system has not been
|
|
// analyzed based on the template in SMP, return error and UI
|
|
// will display "no analysis is performed"
|
|
//
|
|
if ( ProfileType == SCE_ENGINE_SAP &&
|
|
hProfile->JetSapID == JET_tableidNil) {
|
|
|
|
return(SCESTATUS_PROFILE_NOT_FOUND);
|
|
}
|
|
|
|
//
|
|
// create buffer if it is NULL
|
|
//
|
|
if ( *ppInfoBuffer == NULL) {
|
|
//
|
|
// allocate memory
|
|
//
|
|
Len = sizeof(SCE_PROFILE_INFO);
|
|
*ppInfoBuffer = (PSCE_PROFILE_INFO)ScepAlloc( (UINT)0, Len);
|
|
if ( *ppInfoBuffer == NULL ) {
|
|
|
|
return( SCESTATUS_NOT_ENOUGH_RESOURCE );
|
|
}
|
|
memset(*ppInfoBuffer, '\0', Len);
|
|
bBufAlloc = TRUE;
|
|
|
|
(*ppInfoBuffer)->Type = ( ProfileType==SCE_ENGINE_GPO) ? SCE_ENGINE_SCP : ProfileType;
|
|
|
|
}
|
|
|
|
/*
|
|
// Design changed. Checking is moved above creating the buffer.
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP &&
|
|
hProfile->JetSapID == JET_tableidNil) {
|
|
//
|
|
// if no SAP table is there, which means configuration is done
|
|
// but analysis is not done, we treat it as everything is fine
|
|
// reset the buffer to SCE_NO_VALUE
|
|
//
|
|
ScepResetSecurityPolicyArea(*ppInfoBuffer);
|
|
|
|
// return(SCESTATUS_PROFILE_NOT_FOUND);
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
*/
|
|
//
|
|
// Free related memory and reset the buffer before parsing
|
|
// there is a problem here for now. it clears the handle and
|
|
// filename too. So comment it out.
|
|
|
|
SceFreeMemory( (PVOID)(*ppInfoBuffer), (DWORD)Area );
|
|
|
|
//
|
|
// system access
|
|
//
|
|
|
|
if ( Area & AREA_SECURITY_POLICY ) {
|
|
|
|
rc = ScepGetSystemAccess(
|
|
hProfile,
|
|
ProfileType,
|
|
*ppInfoBuffer,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// system auditing
|
|
//
|
|
rc = ScepGetAuditing(hProfile,
|
|
ProfileType,
|
|
*ppInfoBuffer,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
#if _WIN32_WINNT>=0x0500
|
|
if ( RtlGetNtProductType(&theType) ) {
|
|
|
|
if ( theType == NtProductLanManNt ) {
|
|
|
|
rc = ScepGetKerberosPolicy(
|
|
hProfile,
|
|
ProfileType,
|
|
&((*ppInfoBuffer)->pKerberosInfo),
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// registry values
|
|
//
|
|
rc = ScepGetRegistryValues(
|
|
hProfile,
|
|
ProfileType,
|
|
&((*ppInfoBuffer)->aRegValues),
|
|
&((*ppInfoBuffer)->RegValueCount),
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// privilege/rights
|
|
//
|
|
|
|
if ( Area & AREA_PRIVILEGES ) {
|
|
//
|
|
// SCP/SMP/SAP privilegeAssignedTo are all in the same address in the
|
|
// SCE_PROFILE_INFO structure.
|
|
//
|
|
rc = ScepGetPrivileges(
|
|
hProfile,
|
|
ProfileType,
|
|
dwAccountFormat,
|
|
(PVOID *)&( (*ppInfoBuffer)->OtherInfo.scp.u.pPrivilegeAssignedTo ),
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
|
|
//
|
|
// group memberships
|
|
//
|
|
|
|
if ( (Area & AREA_GROUP_MEMBERSHIP) &&
|
|
(ProfileType != SCE_ENGINE_GPO) ) {
|
|
|
|
rc = ScepGetGroupMembership(
|
|
hProfile,
|
|
ProfileType,
|
|
&((*ppInfoBuffer)->pGroupMembership),
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// registry keys security
|
|
//
|
|
|
|
if ( (Area & AREA_REGISTRY_SECURITY) &&
|
|
(ProfileType != SCE_ENGINE_GPO) ) {
|
|
|
|
rc = ScepGetObjectList(
|
|
hProfile,
|
|
ProfileType,
|
|
szRegistryKeys,
|
|
&((*ppInfoBuffer)->pRegistryKeys.pOneLevel),
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
}
|
|
|
|
//
|
|
// file security
|
|
//
|
|
|
|
if ( (Area & AREA_FILE_SECURITY) &&
|
|
(ProfileType != SCE_ENGINE_GPO) ) {
|
|
|
|
rc = ScepGetObjectList(
|
|
hProfile,
|
|
ProfileType,
|
|
szFileSecurity,
|
|
&((*ppInfoBuffer)->pFiles.pOneLevel),
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// DS object security
|
|
//
|
|
#if 0
|
|
|
|
#if _WIN32_WINNT>=0x0500
|
|
if ( (Area & AREA_DS_OBJECTS) &&
|
|
(ProfileType != SCE_ENGINE_GPO) &&
|
|
RtlGetNtProductType(&theType) ) {
|
|
|
|
if ( theType == NtProductLanManNt ) {
|
|
rc = ScepGetDsRoot(
|
|
hProfile,
|
|
ProfileType,
|
|
szDSSecurity,
|
|
&((*ppInfoBuffer)->pDsObjects.pOneLevel),
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
if ( (Area & AREA_SYSTEM_SERVICE) &&
|
|
(ProfileType != SCE_ENGINE_GPO) ) {
|
|
|
|
rc = ScepGetSystemServices(
|
|
hProfile,
|
|
ProfileType,
|
|
&((*ppInfoBuffer)->pServices),
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// need free memory because some fatal error happened
|
|
//
|
|
|
|
if ( bBufAlloc ) {
|
|
SceFreeProfileMemory(*ppInfoBuffer);
|
|
*ppInfoBuffer = NULL;
|
|
} else
|
|
SceFreeMemory( (PVOID)(*ppInfoBuffer), (DWORD)Area );
|
|
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetSystemAccess(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_PROFILE_INFO pProfileInfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine retrieves system access area information from the Jet database
|
|
and stores in the output buffer pProfileInfo. System access information
|
|
includes information in [System Access] sections.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The profile handle context
|
|
|
|
pProfileinfo - the output buffer to hold profile info (SCP or SAP).
|
|
|
|
Errlog - A buffer to hold all error codes/text encountered when
|
|
parsing the INF file. If Errlog is NULL, no further error
|
|
information is returned except the return DWORD
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
--*/
|
|
|
|
{
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
|
|
SCE_KEY_LOOKUP AccessKeys[] = {
|
|
{(PWSTR)TEXT("MinimumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordAge), 'D'},
|
|
{(PWSTR)TEXT("MaximumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MaximumPasswordAge), 'D'},
|
|
{(PWSTR)TEXT("MinimumPasswordLength"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordLength), 'D'},
|
|
{(PWSTR)TEXT("PasswordComplexity"), offsetof(struct _SCE_PROFILE_INFO, PasswordComplexity), 'D'},
|
|
{(PWSTR)TEXT("PasswordHistorySize"), offsetof(struct _SCE_PROFILE_INFO, PasswordHistorySize), 'D'},
|
|
{(PWSTR)TEXT("LockoutBadCount"), offsetof(struct _SCE_PROFILE_INFO, LockoutBadCount), 'D'},
|
|
{(PWSTR)TEXT("ResetLockoutCount"), offsetof(struct _SCE_PROFILE_INFO, ResetLockoutCount), 'D'},
|
|
{(PWSTR)TEXT("LockoutDuration"), offsetof(struct _SCE_PROFILE_INFO, LockoutDuration), 'D'},
|
|
{(PWSTR)TEXT("RequireLogonToChangePassword"),offsetof(struct _SCE_PROFILE_INFO, RequireLogonToChangePassword),'D'},
|
|
{(PWSTR)TEXT("ForceLogoffWhenHourExpire"),offsetof(struct _SCE_PROFILE_INFO, ForceLogoffWhenHourExpire),'D'},
|
|
{(PWSTR)TEXT("ClearTextPassword"), offsetof(struct _SCE_PROFILE_INFO, ClearTextPassword), 'D'},
|
|
{(PWSTR)TEXT("LSAAnonymousNameLookup"), offsetof(struct _SCE_PROFILE_INFO, LSAAnonymousNameLookup), 'D'},
|
|
{(PWSTR)TEXT("EnableAdminAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableAdminAccount), 'D'},
|
|
{(PWSTR)TEXT("EnableGuestAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableGuestAccount), 'D'}
|
|
};
|
|
|
|
DWORD cKeys = sizeof(AccessKeys) / sizeof(SCE_KEY_LOOKUP);
|
|
|
|
DWORD DataSize=0;
|
|
PWSTR Strvalue=NULL;
|
|
DWORD SDsize=0;
|
|
PSECURITY_DESCRIPTOR pTempSD=NULL;
|
|
|
|
|
|
if ( pProfileInfo == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
rc = ScepGetFixValueSection(
|
|
hProfile,
|
|
szSystemAccess,
|
|
AccessKeys,
|
|
cKeys,
|
|
ProfileType,
|
|
(PVOID)pProfileInfo,
|
|
&hSection,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
//
|
|
// get new administrator for SCP and SMP types
|
|
//
|
|
rc = ScepGetVariableValue(
|
|
hSection,
|
|
ProfileType,
|
|
L"NewAdministratorName",
|
|
&Strvalue,
|
|
&DataSize
|
|
);
|
|
if ( rc != SCESTATUS_RECORD_NOT_FOUND &&
|
|
rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog, SCEERR_QUERY_VALUE,
|
|
L"NewAdministratorName"
|
|
);
|
|
goto Done;
|
|
}
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( Strvalue ) {
|
|
if ( Strvalue[0] != L'\0') {
|
|
pProfileInfo->NewAdministratorName = Strvalue;
|
|
} else {
|
|
pProfileInfo->NewAdministratorName = NULL;
|
|
ScepFree(Strvalue);
|
|
}
|
|
Strvalue = NULL;
|
|
}
|
|
|
|
//
|
|
// NewGuestName
|
|
//
|
|
|
|
rc = ScepGetVariableValue(
|
|
hSection,
|
|
ProfileType,
|
|
L"NewGuestName",
|
|
&Strvalue,
|
|
&DataSize
|
|
);
|
|
if ( rc != SCESTATUS_RECORD_NOT_FOUND &&
|
|
rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog, SCEERR_QUERY_VALUE,
|
|
L"NewGuestName"
|
|
);
|
|
goto Done;
|
|
}
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( Strvalue ) {
|
|
if ( Strvalue[0] != L'\0') {
|
|
pProfileInfo->NewGuestName = Strvalue;
|
|
} else {
|
|
pProfileInfo->NewGuestName = NULL;
|
|
ScepFree(Strvalue);
|
|
}
|
|
Strvalue = NULL;
|
|
}
|
|
|
|
Done:
|
|
|
|
SceJetCloseSection(&hSection, TRUE);
|
|
|
|
if ( pTempSD != NULL )
|
|
ScepFree(pTempSD);
|
|
|
|
if ( Strvalue != NULL )
|
|
ScepFree( Strvalue );
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetFixValueSection(
|
|
IN PSCECONTEXT hProfile,
|
|
IN PCWSTR SectionName,
|
|
IN SCE_KEY_LOOKUP *Keys,
|
|
IN DWORD cKeys,
|
|
IN SCETYPE ProfileType,
|
|
OUT PVOID pInfo,
|
|
OUT PSCESECTION *phSection,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD i;
|
|
TCHAR Value[25];
|
|
DWORD RetValueLen;
|
|
LONG Keyvalue;
|
|
|
|
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
(ProfileType==SCE_ENGINE_GPO)? SCE_ENGINE_SCP : ProfileType,
|
|
SectionName,
|
|
phSection
|
|
);
|
|
if ( SCESTATUS_SUCCESS != rc ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog, SCEERR_OPEN,
|
|
SectionName
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
JET_COLUMNID ColGpoID = 0;
|
|
JET_ERR JetErr;
|
|
LONG GpoID=0;
|
|
DWORD Actual;
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO ) {
|
|
JET_COLUMNDEF ColumnGpoIDDef;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
(*phSection)->JetSessionID,
|
|
(*phSection)->JetTableID,
|
|
"GpoID",
|
|
(VOID *)&ColumnGpoIDDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
if ( JET_errSuccess == JetErr ) {
|
|
ColGpoID = ColumnGpoIDDef.columnid;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get each key in the access array
|
|
//
|
|
for ( i=0; i<cKeys; i++ ) {
|
|
|
|
memset(Value, '\0', 50);
|
|
RetValueLen = 0;
|
|
|
|
rc = SceJetGetValue(
|
|
*phSection,
|
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|
(PWSTR)(Keys[i].KeyString),
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
Value,
|
|
48,
|
|
&RetValueLen
|
|
);
|
|
|
|
if ( RetValueLen > 0 )
|
|
Value[RetValueLen/2] = L'\0';
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
GpoID = 1;
|
|
if ( ProfileType == SCE_ENGINE_GPO ) {
|
|
|
|
//
|
|
// query if the setting comes from a GPO
|
|
// get GPO ID field from the current line
|
|
//
|
|
GpoID = 0;
|
|
|
|
if ( ColGpoID > 0 ) {
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
(*phSection)->JetSessionID,
|
|
(*phSection)->JetTableID,
|
|
ColGpoID,
|
|
(void *)&GpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( GpoID > 0 && RetValueLen > 0 && Value[0] != L'\0' )
|
|
Keyvalue = _wtol(Value);
|
|
else
|
|
Keyvalue = SCE_NO_VALUE;
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
rc = SCESTATUS_SUCCESS; // it is OK not find a record
|
|
Keyvalue = SCE_NO_VALUE;
|
|
} else {
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_QUERY_VALUE,
|
|
Keys[i].KeyString
|
|
);
|
|
goto Done;
|
|
}
|
|
#ifdef SCE_DBG
|
|
printf("Get info %s (%d) for ", Value, Keyvalue);
|
|
wprintf(L"%s. rc=%d, Return Length=%d\n",
|
|
Keys[i].KeyString, rc, RetValueLen);
|
|
#endif
|
|
|
|
switch (Keys[i].BufferType ) {
|
|
case 'B':
|
|
*((BOOL *)((CHAR *)pInfo+Keys[i].Offset)) = (Keyvalue == 1) ? TRUE : FALSE;
|
|
break;
|
|
case 'D':
|
|
*((DWORD *)((CHAR *)pInfo+Keys[i].Offset)) = Keyvalue;
|
|
break;
|
|
default:
|
|
rc = SCESTATUS_INVALID_DATA;
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_CANT_FIND_DATATYPE,
|
|
Keys[i].KeyString
|
|
);
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
Done:
|
|
//
|
|
// close the section
|
|
//
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
SceJetCloseSection(phSection, TRUE);
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetVariableValue(
|
|
IN PSCESECTION hSection,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR KeyName,
|
|
OUT PWSTR *Value,
|
|
OUT PDWORD ValueLen
|
|
)
|
|
/* ++
|
|
-- */
|
|
{
|
|
|
|
SCESTATUS rc;
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|
(PWSTR)KeyName,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
ValueLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS && *ValueLen > 0 ) {
|
|
|
|
LONG GpoID=1;
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO ) {
|
|
|
|
JET_COLUMNDEF ColumnGpoIDDef;
|
|
JET_COLUMNID ColGpoID = 0;
|
|
JET_ERR JetErr;
|
|
DWORD Actual;
|
|
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
"GpoID",
|
|
(VOID *)&ColumnGpoIDDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
|
|
GpoID = 0;
|
|
|
|
if ( JET_errSuccess == JetErr ) {
|
|
ColGpoID = ColumnGpoIDDef.columnid;
|
|
//
|
|
// query if the setting comes from a GPO
|
|
// get GPO ID field from the current line
|
|
//
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
ColGpoID,
|
|
(void *)&GpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
if ( GpoID > 0 ) {
|
|
|
|
//
|
|
// if DataSize = 0 then the security descriptor is NULL also
|
|
//
|
|
*Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, *ValueLen+2);
|
|
|
|
if( *Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
} else {
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
(PWSTR)KeyName,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
*Value,
|
|
*ValueLen,
|
|
ValueLen
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
}
|
|
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetPrivileges(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN DWORD dwAccountFormat,
|
|
OUT PVOID *pPrivileges,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
|
|
LSA_HANDLE LsaHandle=NULL;
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepOpenLsaPolicy(
|
|
MAXIMUM_ALLOWED,
|
|
&LsaHandle,
|
|
TRUE
|
|
));
|
|
|
|
if ( ERROR_SUCCESS != rc ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEDLL_LSA_POLICY
|
|
);
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
}
|
|
|
|
PSCE_PRIVILEGE_ASSIGNMENT pTempList=NULL, pNode, pPriv, pParent, pTemp;
|
|
|
|
rc = ScepGetPrivilegesFromOneTable(
|
|
LsaHandle,
|
|
hProfile,
|
|
ProfileType,
|
|
dwAccountFormat,
|
|
pPrivileges,
|
|
Errlog
|
|
);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc && SCE_ENGINE_SAP == ProfileType ) {
|
|
//
|
|
// get the remaining stuff from SMP
|
|
//
|
|
rc = ScepGetPrivilegesFromOneTable(
|
|
LsaHandle,
|
|
hProfile,
|
|
SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
|
|
dwAccountFormat,
|
|
(PVOID *)&pTempList,
|
|
Errlog
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// add non-exist nodes to pPrivileges
|
|
//
|
|
pNode=pTempList;
|
|
pParent=NULL;
|
|
|
|
while ( pNode ) {
|
|
//
|
|
// if this node does not exist in the SAP
|
|
// this node is analyzed with "match" status
|
|
// if it already exists in SAP, it is a "mismatched" item
|
|
// duplication is prevented by the last argument TRUE
|
|
//
|
|
for ( pPriv=(PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
|
|
pPriv != NULL; pPriv=pPriv->Next ) {
|
|
if ( pPriv->Status & SCE_INTERNAL_NP &&
|
|
_wcsicmp( pPriv->Name, pNode->Name) == 0 )
|
|
break;
|
|
}
|
|
if ( pPriv ) {
|
|
//
|
|
// find the entry in SAP, mismatched item
|
|
//
|
|
if ( pPriv->Status & SCE_STATUS_ERROR_NOT_AVAILABLE ) {
|
|
pPriv->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
|
|
} else {
|
|
pPriv->Status = SCE_STATUS_MISMATCH;
|
|
}
|
|
|
|
pParent = pNode;
|
|
pNode = pNode->Next;
|
|
|
|
} else {
|
|
//
|
|
// does not exist in SAP.
|
|
// just move this node to SAP, with status SCE_STATUS_GOOD
|
|
//
|
|
if ( pParent )
|
|
pParent->Next = pNode->Next;
|
|
else
|
|
pTempList = pNode->Next;
|
|
|
|
pTemp = pNode;
|
|
pNode=pNode->Next;
|
|
|
|
pTemp->Next = (PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
|
|
*((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges) = pTemp;
|
|
}
|
|
}
|
|
//
|
|
// priv exist in analysis but not in template
|
|
//
|
|
for ( pPriv=(PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
|
|
pPriv != NULL; pPriv=pPriv->Next ) {
|
|
if ( pPriv->Status & SCE_INTERNAL_NP )
|
|
pPriv->Status = SCE_STATUS_NOT_CONFIGURED;
|
|
}
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else {
|
|
//
|
|
// pPrivileges will be freed outside
|
|
//
|
|
}
|
|
|
|
if ( pTempList )
|
|
ScepFreePrivilege(pTempList);
|
|
}
|
|
|
|
if ( LsaHandle ) {
|
|
LsaClose(LsaHandle);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetPrivilegesFromOneTable(
|
|
IN LSA_HANDLE LsaPolicy,
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN DWORD dwAccountFormat,
|
|
OUT PVOID *pPrivileges,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
WCHAR KeyName[36];
|
|
PWSTR Value=NULL;
|
|
|
|
PSCE_PRIVILEGE_ASSIGNMENT pPrivilegeAssigned=NULL;
|
|
PSCE_PRIVILEGE_VALUE_LIST pPrivilegeList=NULL;
|
|
|
|
DWORD KeyLen=0;
|
|
DWORD ValueLen;
|
|
DWORD Len;
|
|
PWSTR pTemp;
|
|
DWORD PrivValue;
|
|
|
|
|
|
if ( pPrivileges == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
(ProfileType==SCE_ENGINE_GPO)? SCE_ENGINE_SCP : ProfileType,
|
|
szPrivilegeRights,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog, SCEERR_OPEN,
|
|
szPrivilegeRights
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
JET_COLUMNID ColGpoID = 0;
|
|
JET_ERR JetErr;
|
|
LONG GpoID;
|
|
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO ) {
|
|
|
|
JET_COLUMNDEF ColumnGpoIDDef;
|
|
|
|
JetErr = JetGetTableColumnInfo(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
"GpoID",
|
|
(VOID *)&ColumnGpoIDDef,
|
|
sizeof(JET_COLUMNDEF),
|
|
JET_ColInfo
|
|
);
|
|
if ( JET_errSuccess == JetErr ) {
|
|
ColGpoID = ColumnGpoIDDef.columnid;
|
|
}
|
|
}
|
|
|
|
//
|
|
// goto the first line of this section
|
|
//
|
|
// memset(KeyName, '\0', 72); KeyName will be manually terminated later
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH,
|
|
NULL,
|
|
KeyName,
|
|
70,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
while ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
|
|
//
|
|
// terminate the string
|
|
//
|
|
KeyName[KeyLen/2] = L'\0';
|
|
|
|
//
|
|
// lookup privilege's value
|
|
// ignore unknown privileges
|
|
//
|
|
if ( ( PrivValue = ScepLookupPrivByName(KeyName) ) == -1 ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_INVALID_PRIVILEGE,
|
|
KeyName
|
|
);
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
KeyName,
|
|
70,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
continue;
|
|
// rc = SCESTATUS_INVALID_DATA;
|
|
// goto Done;
|
|
}
|
|
|
|
GpoID = 1;
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO ) {
|
|
|
|
GpoID = 0;
|
|
|
|
if ( ColGpoID > 0 ) {
|
|
|
|
DWORD Actual;
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
ColGpoID,
|
|
(void *)&GpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ProfileType == SCE_ENGINE_GPO &&
|
|
GpoID <= 0 ) {
|
|
//
|
|
// not domain GPO settings
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
KeyName,
|
|
70,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// allocate memory for the group name and value string
|
|
//
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
|
|
if ( Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
//
|
|
// Get the group and its value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// create a node for this privilege
|
|
//
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
//
|
|
// a sce_privilege_assignment structure. allocate buffer
|
|
//
|
|
pPrivilegeAssigned = (PSCE_PRIVILEGE_ASSIGNMENT)ScepAlloc( LMEM_ZEROINIT,
|
|
sizeof(SCE_PRIVILEGE_ASSIGNMENT) );
|
|
if ( pPrivilegeAssigned == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
pPrivilegeAssigned->Name = (PWSTR)ScepAlloc( (UINT)0, (wcslen(KeyName)+1)*sizeof(WCHAR));
|
|
if ( pPrivilegeAssigned->Name == NULL ) {
|
|
ScepFree(pPrivilegeAssigned);
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
|
|
wcscpy(pPrivilegeAssigned->Name, KeyName);
|
|
pPrivilegeAssigned->Value = PrivValue;
|
|
|
|
if ( SCE_ENGINE_SAP == ProfileType )
|
|
pPrivilegeAssigned->Status = SCE_INTERNAL_NP;
|
|
else
|
|
pPrivilegeAssigned->Status = SCE_STATUS_GOOD;
|
|
}
|
|
|
|
//
|
|
// add the multi-sz value string to the node, depending on the value type
|
|
//
|
|
PSID pSid=NULL;
|
|
BOOL bBufferUsed;
|
|
|
|
pTemp = Value;
|
|
if (pTemp != NULL && pTemp[0] == L'\0' && ValueLen > 1) {
|
|
pTemp ++;
|
|
}
|
|
|
|
while ( rc == SCESTATUS_SUCCESS && pTemp != NULL && pTemp[0]) {
|
|
Len = wcslen(pTemp);
|
|
|
|
if ( (ProfileType == SCE_ENGINE_SAP) &&
|
|
(_wcsicmp( SCE_ERROR_STRING, pTemp) == 0) ) {
|
|
//
|
|
// this is an errored item
|
|
//
|
|
pPrivilegeAssigned->Status |= SCE_STATUS_ERROR_NOT_AVAILABLE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// convert pTemp (may be a name, or *SID format) to the right
|
|
// format (SID_STRING, Name, or ACCOUNT_SID)
|
|
//
|
|
switch ( dwAccountFormat ) {
|
|
case SCE_ACCOUNT_SID:
|
|
|
|
if ( pTemp[0] == L'*' ) {
|
|
//
|
|
// this is the *SID format, convert to SID
|
|
//
|
|
if ( !ConvertStringSidToSid( pTemp+1, &pSid) ) {
|
|
//
|
|
// if failed to convert from sid string to sid,
|
|
// treat it as any name
|
|
//
|
|
rc = GetLastError();
|
|
}
|
|
} else {
|
|
//
|
|
// lookup name for a sid
|
|
//
|
|
rc = RtlNtStatusToDosError(
|
|
ScepConvertNameToSid(
|
|
LsaPolicy,
|
|
pTemp,
|
|
&pSid
|
|
));
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc && pSid ) {
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
rc = ScepAddSidToNameList(
|
|
&(pPrivilegeAssigned->AssignedTo),
|
|
pSid,
|
|
TRUE, // reuse the buffer
|
|
&bBufferUsed
|
|
);
|
|
|
|
} else {
|
|
//
|
|
// add to privilege list (as Sid)
|
|
//
|
|
rc = ScepAddSidToPrivilegeList(
|
|
&pPrivilegeList,
|
|
pSid,
|
|
TRUE, // reuse the buffer
|
|
PrivValue,
|
|
&bBufferUsed
|
|
);
|
|
}
|
|
|
|
if ( rc == ERROR_SUCCESS && bBufferUsed ) {
|
|
pSid = NULL;
|
|
}
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
} else {
|
|
//
|
|
// add as name format
|
|
//
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
rc = ScepAddToNameList(&(pPrivilegeAssigned->AssignedTo), pTemp, Len );
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
} else {
|
|
//
|
|
// pPrivilegeList is a privilege_value list for each user/group.
|
|
// the LowValue and HighValue fields are combination of all privileges assigned to the user
|
|
//
|
|
rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
|
|
}
|
|
}
|
|
|
|
if ( pSid ) {
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if ( (dwAccountFormat != SCE_ACCOUNT_SID_STRING) &&
|
|
(pTemp[0] == L'*') ) {
|
|
//
|
|
// this is a *SID format, must be converted into Domain\Account format
|
|
//
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
rc = ScepLookupSidStringAndAddToNameList(
|
|
LsaPolicy,
|
|
&(pPrivilegeAssigned->AssignedTo),
|
|
pTemp, // +1,
|
|
Len // -1
|
|
);
|
|
} else {
|
|
//
|
|
// add to privilege value list
|
|
//
|
|
PWSTR strName=NULL;
|
|
DWORD strLen=0;
|
|
|
|
if ( ConvertStringSidToSid( pTemp+1, &pSid) ) {
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepConvertSidToName(
|
|
LsaPolicy,
|
|
pSid,
|
|
TRUE, // want domain\account format
|
|
&strName,
|
|
&strLen
|
|
));
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
//
|
|
// add the name to the privilege list
|
|
//
|
|
rc = ScepAddToPrivilegeList(&pPrivilegeList, strName, strLen, PrivValue);
|
|
} else {
|
|
//
|
|
// if couldn't lookup for the name, add *SID to the list
|
|
//
|
|
rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
|
|
}
|
|
|
|
if ( strName ) {
|
|
ScepFree(strName);
|
|
strName = NULL;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
rc = ScepDosErrorToSceStatus(
|
|
ScepAddToNameList(&(pPrivilegeAssigned->AssignedTo),
|
|
pTemp,
|
|
Len ));
|
|
|
|
} else {
|
|
//
|
|
// pPrivilegeList is a privilege_value list for each user/group.
|
|
// the LowValue and HighValue fields are combination of all privileges assigned to the user
|
|
//
|
|
rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
|
|
#ifdef SCE_DBG
|
|
wprintf(L"\tAdd Priv %d for %s (%d bytes)\n", PrivValue, pTemp, Len);
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
pTemp += Len +1;
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_WRITE_FAULT,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
KeyName
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free memory
|
|
//
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
if ( pPrivilegeAssigned != NULL )
|
|
ScepFreePrivilege(pPrivilegeAssigned);
|
|
|
|
if ( pPrivilegeList != NULL )
|
|
ScepFreePrivilegeValueList(pPrivilegeList);
|
|
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// link this to the PSCE_PRIVILEGE_ASSIGNMENT list in pPrivileges
|
|
//
|
|
if ( ProfileType == SCE_ENGINE_SAP ||
|
|
ProfileType == SCE_ENGINE_SMP ||
|
|
ProfileType == SCE_ENGINE_GPO ||
|
|
ProfileType == SCE_ENGINE_SCP ) {
|
|
|
|
pPrivilegeAssigned->Next = *((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges);
|
|
*((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges) = pPrivilegeAssigned;
|
|
pPrivilegeAssigned = NULL;
|
|
|
|
}
|
|
|
|
ScepFree(Value);
|
|
Value = NULL;
|
|
|
|
//
|
|
// read next line
|
|
//
|
|
// memset(KeyName, '\0', 72); KeyName will be manually terminated
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
KeyName,
|
|
70,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( ProfileType == SCE_ENGINE_SCP_INTERNAL ||
|
|
ProfileType == SCE_ENGINE_SMP_INTERNAL )
|
|
*((PSCE_PRIVILEGE_VALUE_LIST *)pPrivileges) = pPrivilegeList;
|
|
|
|
}
|
|
|
|
Done:
|
|
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( Value != NULL )
|
|
ScepFree(Value);
|
|
|
|
//
|
|
// close the section
|
|
//
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepAddToPrivilegeList(
|
|
OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
|
|
IN PWSTR Name,
|
|
IN DWORD Len,
|
|
IN DWORD PrivValue
|
|
)
|
|
{
|
|
PSCE_PRIVILEGE_VALUE_LIST pPriv,
|
|
LastOne=NULL;
|
|
|
|
|
|
if ( pPrivilegeList == NULL || Name == NULL || Len == 0 )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
for ( pPriv = *pPrivilegeList;
|
|
pPriv != NULL;
|
|
LastOne=pPriv, pPriv = pPriv->Next ) {
|
|
|
|
if ( ( wcslen(pPriv->Name) == Len ) &&
|
|
( _wcsnicmp( pPriv->Name, Name, Len ) == 0 ) ) {
|
|
if ( PrivValue < 32 ) {
|
|
|
|
pPriv->PrivLowPart |= (1 << PrivValue);
|
|
} else {
|
|
pPriv->PrivHighPart |= (1 << (PrivValue-32) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if ( pPriv == NULL ) {
|
|
//
|
|
// Create a new one
|
|
//
|
|
pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
|
|
sizeof(SCE_PRIVILEGE_VALUE_LIST));
|
|
if ( pPriv == NULL )
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
|
|
pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
|
|
if ( pPriv->Name == NULL ) {
|
|
ScepFree(pPriv);
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
wcsncpy(pPriv->Name, Name, Len);
|
|
|
|
if ( PrivValue < 32 ) {
|
|
|
|
pPriv->PrivLowPart |= (1 << PrivValue);
|
|
} else {
|
|
pPriv->PrivHighPart |= (1 << (PrivValue-32) );
|
|
}
|
|
|
|
//
|
|
// link to the list
|
|
//
|
|
if ( LastOne != NULL )
|
|
LastOne->Next = pPriv;
|
|
else
|
|
*pPrivilegeList = pPriv;
|
|
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepAddSidToPrivilegeList(
|
|
OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
|
|
IN PSID pSid,
|
|
IN BOOL bReuseBuffer,
|
|
IN DWORD PrivValue,
|
|
OUT BOOL *pbBufferUsed
|
|
)
|
|
{
|
|
|
|
if ( pPrivilegeList == NULL || pbBufferUsed == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
*pbBufferUsed = FALSE;
|
|
|
|
if ( pSid == NULL ) {
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
if ( !ScepValidSid(pSid) ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
PSCE_PRIVILEGE_VALUE_LIST pPriv,
|
|
LastOne=NULL;
|
|
|
|
//
|
|
// check if the sid is already in the list
|
|
//
|
|
for ( pPriv = *pPrivilegeList;
|
|
pPriv != NULL;
|
|
LastOne=pPriv, pPriv = pPriv->Next ) {
|
|
|
|
if ( pPriv->Name == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
if ( ScepValidSid( (PSID)(pPriv->Name) ) &&
|
|
RtlEqualSid( (PSID)(pPriv->Name), pSid ) ) {
|
|
|
|
if ( PrivValue < 32 ) {
|
|
|
|
pPriv->PrivLowPart |= (1 << PrivValue);
|
|
} else {
|
|
pPriv->PrivHighPart |= (1 << (PrivValue-32) );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( pPriv == NULL ) {
|
|
//
|
|
// Create a new one
|
|
//
|
|
pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
|
|
sizeof(SCE_PRIVILEGE_VALUE_LIST));
|
|
if ( pPriv == NULL )
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
|
|
if ( bReuseBuffer ) {
|
|
|
|
pPriv->Name = (PWSTR)pSid;
|
|
*pbBufferUsed = TRUE;
|
|
|
|
} else {
|
|
|
|
DWORD Length = RtlLengthSid ( pSid );
|
|
|
|
pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
|
|
if ( pPriv->Name == NULL ) {
|
|
ScepFree(pPriv);
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
|
|
RtlCopySid( Length, (PSID)(pPriv->Name), pSid );
|
|
|
|
}
|
|
|
|
if ( PrivValue < 32 ) {
|
|
|
|
pPriv->PrivLowPart |= (1 << PrivValue);
|
|
} else {
|
|
pPriv->PrivHighPart |= (1 << (PrivValue-32) );
|
|
}
|
|
|
|
//
|
|
// link to the list
|
|
//
|
|
if ( LastOne != NULL )
|
|
LastOne->Next = pPriv;
|
|
else
|
|
*pPrivilegeList = pPriv;
|
|
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetGroupMembership(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD OneStatus;
|
|
|
|
PSCE_GROUP_MEMBERSHIP pTempList=NULL, pNode, pGroup2,
|
|
pParent, pTemp;
|
|
|
|
LSA_HANDLE LsaHandle=NULL;
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepOpenLsaPolicy(
|
|
MAXIMUM_ALLOWED,
|
|
&LsaHandle,
|
|
TRUE
|
|
));
|
|
|
|
if ( ERROR_SUCCESS != rc ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEDLL_LSA_POLICY
|
|
);
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
}
|
|
|
|
//
|
|
// get groups from the requested table first
|
|
//
|
|
rc = ScepGetGroupMembershipFromOneTable(
|
|
LsaHandle,
|
|
hProfile,
|
|
ProfileType,
|
|
pGroupMembership,
|
|
Errlog
|
|
);
|
|
//
|
|
// return all groups if it is requested for SAP entry
|
|
//
|
|
if ( SCESTATUS_SUCCESS == rc && SCE_ENGINE_SAP == ProfileType ) {
|
|
//
|
|
// get the remaining stuff from SMP
|
|
//
|
|
rc = ScepGetGroupMembershipFromOneTable(
|
|
LsaHandle,
|
|
hProfile,
|
|
SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
|
|
&pTempList,
|
|
Errlog
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// add non-exist nodes to pObjectRoots
|
|
//
|
|
pNode=pTempList;
|
|
pParent=NULL;
|
|
|
|
while ( pNode ) {
|
|
//
|
|
// if this node does not exist in the SAP
|
|
// this node is analyzed with "match" status
|
|
// if it already exists in SAP, it is a "mismatched" item
|
|
// duplication is prevented by the last argument TRUE
|
|
//
|
|
for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
|
|
if ( (pGroup2->Status & SCE_INTERNAL_NP) &&
|
|
_wcsicmp( pGroup2->GroupName, pNode->GroupName) == 0 )
|
|
break;
|
|
}
|
|
if ( pGroup2 ) {
|
|
//
|
|
// find the entry in SAP, mismatched item
|
|
// maybe pMembers, or pMemberOf
|
|
// or not analyzed item, or error items
|
|
//
|
|
OneStatus = pGroup2->Status;
|
|
pGroup2->Status = 0;
|
|
|
|
if ( (OneStatus & SCE_GROUP_STATUS_NOT_ANALYZED) ) {
|
|
// this item is added after last inspection
|
|
pGroup2->Status = SCE_GROUP_STATUS_NOT_ANALYZED;
|
|
|
|
} else if ( (OneStatus & SCE_GROUP_STATUS_ERROR_ANALYZED) ) {
|
|
|
|
// this item errored when analyzing
|
|
pGroup2->Status = SCE_GROUP_STATUS_ERROR_ANALYZED;
|
|
|
|
} else {
|
|
if ( pNode->Status & SCE_GROUP_STATUS_NC_MEMBERS ) {
|
|
pGroup2->Status |= SCE_GROUP_STATUS_NC_MEMBERS;
|
|
} else {
|
|
if ( !(OneStatus & SCE_GROUP_STATUS_NC_MEMBERS) ) {
|
|
pGroup2->Status |= SCE_GROUP_STATUS_MEMBERS_MISMATCH;
|
|
} else {
|
|
// a matched members, pGroup2->pMembers should be NULL;
|
|
if ( pGroup2->pMembers ) {
|
|
ScepFreeNameList(pGroup2->pMembers);
|
|
}
|
|
pGroup2->pMembers = pNode->pMembers;
|
|
pNode->pMembers = NULL;
|
|
}
|
|
}
|
|
|
|
if ( pNode->Status & SCE_GROUP_STATUS_NC_MEMBEROF ) {
|
|
pGroup2->Status |= SCE_GROUP_STATUS_NC_MEMBEROF;
|
|
} else {
|
|
if ( !(OneStatus & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
|
|
pGroup2->Status |= SCE_GROUP_STATUS_MEMBEROF_MISMATCH;
|
|
} else {
|
|
// a matched memberof, pGroup2->pMemberOf should be NULL;
|
|
if ( pGroup2->pMemberOf ) {
|
|
ScepFreeNameList(pGroup2->pMemberOf);
|
|
}
|
|
pGroup2->pMemberOf = pNode->pMemberOf;
|
|
pNode->pMemberOf = NULL;
|
|
}
|
|
}
|
|
}
|
|
pParent = pNode;
|
|
pNode = pNode->Next;
|
|
|
|
} else {
|
|
//
|
|
// does not exist in SAP.
|
|
// this is a matched item on pMembers, and/or pMemberOf
|
|
// just move this node to SAP, with status NC_MEMBERS, or NC_MEMBEROF, or 0
|
|
//
|
|
if ( pParent )
|
|
pParent->Next = pNode->Next;
|
|
else
|
|
pTempList = pNode->Next;
|
|
|
|
pTemp = pNode;
|
|
pNode=pNode->Next;
|
|
|
|
pTemp->Next = *pGroupMembership;
|
|
*pGroupMembership = pTemp;
|
|
}
|
|
}
|
|
//
|
|
// group exist in analysis but not in template
|
|
//
|
|
for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
|
|
if ( pGroup2->Status & SCE_INTERNAL_NP )
|
|
pGroup2->Status = SCE_GROUP_STATUS_NC_MEMBERS | SCE_GROUP_STATUS_NC_MEMBEROF;
|
|
}
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else {
|
|
//
|
|
// pGroupMembership will be freed outside
|
|
//
|
|
}
|
|
|
|
if ( pTempList ) {
|
|
ScepFreeGroupMembership(pTempList);
|
|
}
|
|
}
|
|
|
|
//
|
|
// now the group name may be in *SID format, conver it now to name
|
|
//
|
|
if ( SCESTATUS_SUCCESS == rc && *pGroupMembership ) {
|
|
|
|
for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
|
|
if ( pGroup2->GroupName == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
if ( pGroup2->GroupName[0] == L'*' ) {
|
|
//
|
|
// *SID format, convert it
|
|
//
|
|
PSID pSid=NULL;
|
|
|
|
if ( ConvertStringSidToSid( (pGroup2->GroupName)+1, &pSid) ) {
|
|
|
|
PWSTR strName=NULL;
|
|
DWORD strLen=0;
|
|
|
|
if (NT_SUCCESS( ScepConvertSidToName(
|
|
LsaHandle,
|
|
pSid,
|
|
TRUE, // want domain\account format
|
|
&strName,
|
|
&strLen
|
|
)) && strName ) {
|
|
|
|
ScepFree(pGroup2->GroupName);
|
|
pGroup2->GroupName = strName;
|
|
strName = NULL;
|
|
}
|
|
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( LsaHandle ) {
|
|
LsaClose(LsaHandle);
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetGroupMembershipFromOneTable(
|
|
IN LSA_HANDLE LsaPolicy,
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieves group membership information from the Jet databasae
|
|
and stores in the output buffer pGroupMembership. Group membership information
|
|
is in [Group Membership] section.
|
|
|
|
Arguments:
|
|
|
|
hProfile - the profile handle context
|
|
|
|
ProfileType - Type of the Profile
|
|
SCE_ENGINE_SAP
|
|
SCE_ENGINE_SMP
|
|
SCE_ENGINE_SCP
|
|
|
|
pGroupMembership - the output buffer to hold group membership info.
|
|
|
|
Errlog - the error list for errors encountered in this routine.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
PSCE_GROUP_MEMBERSHIP pGroup=NULL;
|
|
DWORD GroupLen, ValueLen;
|
|
PWSTR GroupName=NULL;
|
|
PWSTR Value=NULL;
|
|
DWORD ValueType;
|
|
ULONG Len;
|
|
PWSTR pTemp;
|
|
|
|
|
|
if ( pGroupMembership == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
szGroupMembership,
|
|
&hSection
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
szGroupMembership
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// goto the first line of this section
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&GroupLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
while ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// allocate memory for the group name and value string
|
|
//
|
|
GroupName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, GroupLen+2);
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
|
|
if ( GroupName == NULL || Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
//
|
|
// Get the group and its value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
GroupName,
|
|
GroupLen,
|
|
&GroupLen,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
GroupName[GroupLen/2] = L'\0';
|
|
Value[ValueLen/2] = L'\0';
|
|
|
|
#ifdef SCE_DBG
|
|
wprintf(L"rc=%d, group membership: %s=%s\n", rc, GroupName, Value);
|
|
#endif
|
|
|
|
if (pTemp = ScepWcstrr(GroupName, szMembers) )
|
|
ValueType = 0;
|
|
else if (pTemp = ScepWcstrr(GroupName, szMemberof) )
|
|
ValueType = 1;
|
|
else if (pTemp = ScepWcstrr(GroupName, szPrivileges) )
|
|
ValueType = 2;
|
|
|
|
if ( pTemp == NULL ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_CANT_FIND_KEYWORD,
|
|
GroupName
|
|
);
|
|
rc = SCESTATUS_INVALID_DATA;
|
|
goto NextLine; //Done;
|
|
}
|
|
|
|
Len = (DWORD)(pTemp - GroupName);
|
|
|
|
//
|
|
// if this is the first group, or a different group, create another node
|
|
// Note, the group name may be in SID string format now.
|
|
// Will be converted later (in the calling function) because we don't want
|
|
// to lookup for the same group name several times (each group may have
|
|
// multiple records).
|
|
//
|
|
if ( *pGroupMembership == NULL ||
|
|
_wcsnicmp((*pGroupMembership)->GroupName, GroupName, Len) != 0 ||
|
|
(*pGroupMembership)->GroupName[Len] != L'\0' ) {
|
|
//
|
|
// a new group. allocate buffer
|
|
//
|
|
pGroup = (PSCE_GROUP_MEMBERSHIP)ScepAlloc( LMEM_ZEROINIT, sizeof(SCE_GROUP_MEMBERSHIP) );
|
|
if ( pGroup == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
pGroup->GroupName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
|
|
if ( pGroup->GroupName == NULL ) {
|
|
ScepFree(pGroup);
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
//
|
|
// get right case for group name
|
|
//
|
|
wcsncpy(pGroup->GroupName, GroupName, Len);
|
|
|
|
// do not care return codes
|
|
ScepGetGroupCase(pGroup->GroupName, Len);
|
|
|
|
pGroup->Next = *pGroupMembership;
|
|
|
|
// if ( SCE_ENGINE_SAP == ProfileType )
|
|
pGroup->Status = SCE_GROUP_STATUS_NC_MEMBERS | SCE_GROUP_STATUS_NC_MEMBEROF;
|
|
// else
|
|
// pGroup->Status = 0;
|
|
if ( SCE_ENGINE_SAP == ProfileType )
|
|
pGroup->Status |= SCE_INTERNAL_NP;
|
|
|
|
}
|
|
|
|
//
|
|
// add the multi-sz value string to the group node, depending on the value type
|
|
//
|
|
pTemp = Value;
|
|
while ( rc == SCESTATUS_SUCCESS && pTemp != NULL && pTemp[0] ) {
|
|
while ( *pTemp && L' ' == *pTemp ) {
|
|
pTemp++;
|
|
}
|
|
|
|
if ( SCE_ENGINE_SAP == ProfileType ) {
|
|
if ( !(*pTemp) ) {
|
|
// this is an not analyzed item
|
|
pGroup->Status = SCE_GROUP_STATUS_NOT_ANALYZED |
|
|
SCE_INTERNAL_NP;
|
|
|
|
break;
|
|
} else if ( _wcsicmp(SCE_ERROR_STRING, pTemp) == 0 ) {
|
|
// this is error item
|
|
pGroup->Status = SCE_GROUP_STATUS_ERROR_ANALYZED |
|
|
SCE_INTERNAL_NP;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !(*pTemp) ) {
|
|
// empty string is not allowed
|
|
break;
|
|
}
|
|
|
|
Len = wcslen(pTemp);
|
|
|
|
if ( ValueType != 0 && ValueType != 1 ) {
|
|
#if 0
|
|
//
|
|
// privilege with optional via group name
|
|
//
|
|
Status = (*((CHAR *)pTemp)-'0')*10 + ((*((CHAR *)pTemp+1)) - '0');
|
|
|
|
PWSTR strName=NULL;
|
|
DWORD strLen=0;
|
|
|
|
if ( pTemp[1] == L'*' ) {
|
|
//
|
|
// convert the SID string into name format
|
|
//
|
|
PSID pSid=NULL;
|
|
|
|
if ( ConvertStringSidToSid( pTemp+2, &pSid) ) {
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepConvertSidToName(
|
|
LsaPolicy,
|
|
pSid,
|
|
TRUE, // want domain\account format
|
|
&strName,
|
|
&strLen
|
|
));
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc && strName ) {
|
|
rc = ScepAddToNameStatusList(&(pGroup->pPrivilegesHeld),
|
|
strName,
|
|
strLen,
|
|
Status);
|
|
} else {
|
|
//
|
|
// if failed to convert, or it's a name format already
|
|
// just add it to the list
|
|
//
|
|
rc = ScepAddToNameStatusList(&(pGroup->pPrivilegesHeld),
|
|
pTemp+1, Len-1, Status);
|
|
}
|
|
|
|
if ( strName ) {
|
|
ScepFree(strName);
|
|
strName = NULL;
|
|
}
|
|
#endif
|
|
} else {
|
|
//
|
|
// members (0) of memberof (1)
|
|
//
|
|
if ( pTemp[0] == L'*' ) {
|
|
//
|
|
// *SID format, convert to name, and add to the list
|
|
//
|
|
rc = ScepLookupSidStringAndAddToNameList(LsaPolicy,
|
|
(ValueType == 0) ?
|
|
&(pGroup->pMembers):
|
|
&(pGroup->pMemberOf),
|
|
pTemp, // +1,
|
|
Len // -1
|
|
);
|
|
|
|
} else {
|
|
|
|
rc = ScepAddToNameList((ValueType == 0) ?
|
|
&(pGroup->pMembers):
|
|
&(pGroup->pMemberOf),
|
|
pTemp,
|
|
Len );
|
|
}
|
|
}
|
|
|
|
#ifdef SCE_DBG
|
|
wprintf(L"Add %s to group list\n", pTemp);
|
|
#endif
|
|
pTemp += Len +1;
|
|
}
|
|
|
|
//
|
|
// Free memory
|
|
//
|
|
if ( rc != SCESTATUS_SUCCESS && pGroup != *pGroupMembership ) {
|
|
|
|
pGroup->Next = NULL;
|
|
ScepFreeGroupMembership( pGroup );
|
|
goto Done;
|
|
}
|
|
|
|
switch ( ValueType ) {
|
|
case 0: // members
|
|
pGroup->Status &= ~SCE_GROUP_STATUS_NC_MEMBERS;
|
|
break;
|
|
case 1:
|
|
pGroup->Status &= ~SCE_GROUP_STATUS_NC_MEMBEROF;
|
|
break;
|
|
}
|
|
*pGroupMembership = pGroup;
|
|
|
|
NextLine:
|
|
|
|
ScepFree(GroupName);
|
|
GroupName = NULL;
|
|
|
|
ScepFree(Value);
|
|
Value = NULL;
|
|
|
|
//
|
|
// read next line
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&GroupLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
Done:
|
|
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( GroupName != NULL )
|
|
ScepFree(GroupName);
|
|
|
|
if ( Value != NULL )
|
|
ScepFree(Value);
|
|
|
|
//
|
|
// close the section
|
|
//
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepOpenSectionForName(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCESECTION *phSection
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
DOUBLE SectionID;
|
|
SCEJET_TABLE_TYPE tblType;
|
|
|
|
//
|
|
// table type
|
|
//
|
|
switch ( ProfileType ) {
|
|
case SCE_ENGINE_SCP:
|
|
case SCE_ENGINE_SCP_INTERNAL:
|
|
tblType = SCEJET_TABLE_SCP;
|
|
break;
|
|
|
|
case SCE_ENGINE_SMP:
|
|
case SCE_ENGINE_SMP_INTERNAL:
|
|
tblType = SCEJET_TABLE_SMP;
|
|
break;
|
|
|
|
case SCE_ENGINE_SAP:
|
|
tblType = SCEJET_TABLE_SAP;
|
|
break;
|
|
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// get section id
|
|
//
|
|
rc = SceJetGetSectionIDByName(
|
|
hProfile,
|
|
SectionName,
|
|
&SectionID
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
rc = SceJetOpenSection(
|
|
hProfile,
|
|
SectionID,
|
|
tblType,
|
|
phSection
|
|
);
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetDsRoot(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*
|
|
DS object root has only one entry, which is the DS domain name
|
|
So the list contains only one entry.
|
|
The format of the DS domain name is dc=<domain>,dc=<domain1>,...o=internet,
|
|
which is the DNS name of the DS domain in LDAP format
|
|
|
|
*/
|
|
{
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
PSCE_OBJECT_LIST pDsRoot=NULL;
|
|
PWSTR JetName=NULL;
|
|
BOOL IsContainer, LastOne;
|
|
DWORD Count, ValueLen;
|
|
BYTE Status;
|
|
WCHAR StatusFlag=L'\0';
|
|
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
SectionName
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
rc = ScepLdapOpen(NULL);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
rc = ScepEnumerateDsObjectRoots(
|
|
NULL,
|
|
&pDsRoot
|
|
);
|
|
ScepLdapClose(NULL);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( pDsRoot == NULL ) {
|
|
rc = SCESTATUS_PROFILE_NOT_FOUND;
|
|
|
|
} else {
|
|
//
|
|
// Convert domain root
|
|
//
|
|
rc = ScepConvertLdapToJetIndexName(
|
|
pDsRoot->Name,
|
|
&JetName
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// goto the line matching the domain root
|
|
//
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
JetName,
|
|
wcslen(JetName)*sizeof(WCHAR),
|
|
SCEJET_SEEK_GE
|
|
);
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP ) {
|
|
//
|
|
// the domain is not in the table, try another one
|
|
//
|
|
SceJetCloseSection(&hSection, FALSE);
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// get count under the domain
|
|
//
|
|
Count = 0;
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
JetName,
|
|
FALSE,
|
|
&Count);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
if ( rc == SCESTATUS_SUCCESS )
|
|
pDsRoot->Status = SCE_STATUS_CHECK;
|
|
else
|
|
pDsRoot->Status = SCE_STATUS_NOT_CONFIGURED;
|
|
pDsRoot->IsContainer = TRUE;
|
|
pDsRoot->Count = Count;
|
|
|
|
*pObjectRoots = pDsRoot;
|
|
pDsRoot = NULL;
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
}
|
|
}
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// something of the domain exist, get value and count of the domain
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_EXACT_MATCH,
|
|
JetName,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
(PWSTR)&StatusFlag, // two bytes buffer
|
|
2,
|
|
&ValueLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL ||
|
|
rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
if ( rc != SCESTATUS_RECORD_NOT_FOUND ) {
|
|
LastOne = TRUE;
|
|
Status = *((BYTE *)&StatusFlag);
|
|
IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
|
|
|
|
} else {
|
|
LastOne = FALSE;
|
|
IsContainer = TRUE;
|
|
if ( ProfileType == SCE_ENGINE_SAP )
|
|
Status = SCE_STATUS_GOOD;
|
|
else
|
|
Status = SCE_STATUS_CHECK;
|
|
}
|
|
//
|
|
// get count under the domain
|
|
//
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
JetName,
|
|
FALSE,
|
|
&Count);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( LastOne )
|
|
Count--;
|
|
|
|
if ( !IsContainer && Count > 0 ) {
|
|
IsContainer = TRUE;
|
|
}
|
|
|
|
//
|
|
// the proper domain name is in pDsRoot
|
|
//
|
|
pDsRoot->Status = Status;
|
|
pDsRoot->IsContainer = IsContainer;
|
|
pDsRoot->Count = Count;
|
|
|
|
*pObjectRoots = pDsRoot;
|
|
pDsRoot = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc),
|
|
Errlog, SCEERR_QUERY_INFO,
|
|
L"SCP/SMP");
|
|
}
|
|
|
|
if ( JetName != NULL ) {
|
|
ScepFree(JetName);
|
|
}
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc),
|
|
Errlog, SCEERR_QUERY_INFO,
|
|
SectionName);
|
|
}
|
|
|
|
ScepFreeObjectList(pDsRoot);
|
|
|
|
SceJetCloseSection(&hSection, TRUE);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetObjectList(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieves registry or files security information from the JET
|
|
database for the root only. To get detail under a root object, call
|
|
ScepGetChildrentObject.
|
|
|
|
For Profiletype "SCE_ENGINE_SAP" (analysis info), a combination of SMP and SAP
|
|
are returned for a complete set of "analyzed" objects.
|
|
|
|
Arguments:
|
|
|
|
hProfile - the profile handle context
|
|
|
|
ProfileType - value to indicate engine type.
|
|
SCE_ENGINE_SCP
|
|
SCE_ENGINE_SAP
|
|
SCE_ENGINE_SMP
|
|
|
|
SectionName - The section name for the objects to retrieve.
|
|
|
|
pObjectRoots - The output list of object roots
|
|
|
|
Errlog - the cummulative error list to hold errors encountered in this routine.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
|
|
{
|
|
SCESTATUS rc;
|
|
PSCE_OBJECT_LIST pTempList=NULL,
|
|
pNode;
|
|
|
|
//
|
|
// get roots from the first table first
|
|
//
|
|
rc = ScepGetObjectFromOneTable(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
pObjectRoots,
|
|
Errlog
|
|
);
|
|
//
|
|
// Ds objects only return the domain name, no need to search SMP
|
|
//
|
|
if ( rc == SCESTATUS_SUCCESS && ProfileType == SCE_ENGINE_SAP ) {
|
|
//
|
|
// get the stuff from SMP
|
|
//
|
|
rc = ScepGetObjectFromOneTable(
|
|
hProfile,
|
|
SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
|
|
SectionName,
|
|
&pTempList,
|
|
Errlog
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// add non-exist nodes to pObjectRoots
|
|
//
|
|
for ( pNode=pTempList; pNode != NULL; pNode = pNode->Next ) {
|
|
|
|
//
|
|
// if this node does not exist in the SAP
|
|
// this node is analyzed with "match" status and
|
|
// no bad children under the node
|
|
// duplication is prevented by the last argument
|
|
//
|
|
rc = ScepAddToObjectList(pObjectRoots, pNode->Name, 0,
|
|
pNode->IsContainer, SCE_STATUS_GOOD, 0, SCE_CHECK_DUP);
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
pNode->Name
|
|
);
|
|
//
|
|
// only the following two errors could be returned
|
|
//
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
} else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else {
|
|
//
|
|
// pObjectRoots will be freed outside
|
|
//
|
|
}
|
|
|
|
if ( pTempList ) {
|
|
ScepFreeObjectList(pTempList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetObjectFromOneTable(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
OUT PSCE_OBJECT_LIST *pObjectRoots,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieves registry or files security information from the JET
|
|
database for the root only. To get detail under a root object, call
|
|
ScepGetChildrentObject.
|
|
|
|
Arguments:
|
|
|
|
hProfile - the profile handle context
|
|
|
|
ProfileType - value to indicate engine type.
|
|
SCE_ENGINE_SCP
|
|
SCE_ENGINE_SAP
|
|
SCE_ENGINE_SMP
|
|
|
|
SectionName - The section name for the objects to retrieve.
|
|
|
|
pObjectRoots - The output list of object roots
|
|
|
|
Errlog - the cummulative error list to hold errors encountered in this routine.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
DWORD ObjectLen=0;
|
|
WCHAR ObjectName[21];
|
|
WCHAR StatusFlag=L'\0';
|
|
BYTE Status=0;
|
|
BOOL IsContainer=TRUE;
|
|
DWORD Len, Count;
|
|
WCHAR Buffer[21];
|
|
BOOL LastOne;
|
|
DWORD ValueLen=0;
|
|
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
SectionName
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// goto the first line of this section
|
|
//
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
NULL,
|
|
0,
|
|
SCEJET_SEEK_GE
|
|
);
|
|
|
|
while ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
|
|
memset(ObjectName, '\0', 21*sizeof(WCHAR));
|
|
memset(Buffer, '\0', 21*sizeof(WCHAR));
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
ObjectName,
|
|
20*sizeof(WCHAR),
|
|
&ObjectLen,
|
|
(PWSTR)&StatusFlag, // two bytes buffer
|
|
2,
|
|
&ValueLen
|
|
);
|
|
#ifdef SCE_DBG
|
|
wprintf(L"ObjectLen=%d, StatusFlag=%x, ValueLen=%d, rc=%d, ObjectName=%s \n",
|
|
ObjectLen, StatusFlag, ValueLen, rc, ObjectName);
|
|
#endif
|
|
if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_BUFFER_TOO_SMALL ) {
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_QUERY_VALUE,
|
|
SectionName
|
|
);
|
|
break;
|
|
}
|
|
//
|
|
// get first component of the object
|
|
//
|
|
if ( ObjectLen <= 40 )
|
|
ObjectName[ObjectLen/sizeof(WCHAR)] = L'\0';
|
|
|
|
rc = ScepGetNameInLevel(
|
|
ObjectName,
|
|
1,
|
|
L'\\',
|
|
Buffer,
|
|
&LastOne
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
Len = wcslen(Buffer);
|
|
|
|
if ( LastOne ) {
|
|
|
|
Status = *((BYTE *)&StatusFlag);
|
|
IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
|
|
|
|
} else {
|
|
IsContainer = TRUE;
|
|
if ( ProfileType == SCE_ENGINE_SAP )
|
|
Status = SCE_STATUS_GOOD;
|
|
else
|
|
Status = SCE_STATUS_CHECK;
|
|
}
|
|
|
|
#ifdef SCE_DBG
|
|
printf("\nStatus=%d, StatusFlag=%x, Len=%d, Buffer=%ws\n", Status, StatusFlag, Len, Buffer);
|
|
#endif
|
|
//
|
|
// get count of this object
|
|
//
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
Buffer,
|
|
FALSE,
|
|
&Count);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
if ( LastOne )
|
|
Count--;
|
|
|
|
if ( !IsContainer && Count > 0 ) {
|
|
IsContainer = TRUE;
|
|
}
|
|
|
|
//
|
|
// the root of registry and file are always upper cased
|
|
//
|
|
_wcsupr(Buffer);
|
|
|
|
rc = ScepAddToObjectList(pObjectRoots, Buffer, Len,
|
|
IsContainer, Status, Count, 0);
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
Buffer
|
|
);
|
|
// only the following two errors could be returned
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY )
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// seek to the next one
|
|
//
|
|
Buffer[Len-1] = (WCHAR)( Buffer[Len-1] + 1);
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
Buffer,
|
|
Len*sizeof(TCHAR),
|
|
SCEJET_SEEK_GT_NO_CASE
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND )
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_QUERY_VALUE,
|
|
SectionName
|
|
);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
//
|
|
// close the section
|
|
//
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetAuditing(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_PROFILE_INFO pProfileInfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieves system auditing information from the JET database
|
|
and stores in the output buffer pProfileInfo. The auditing information
|
|
is stored in [System Log], [Security Log], [Application Log], [Audit Event],
|
|
[Audit Registry], and [Audit File] sections.
|
|
|
|
Arguments:
|
|
|
|
hProfile - the profile handle context
|
|
|
|
pProfileInfo - the output buffer to hold profile info.
|
|
|
|
Errlog - The cummulative error list to hold errors encountered in this routine.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
|
|
SCESTATUS rc;
|
|
SCE_KEY_LOOKUP LogKeys[]={
|
|
{(PWSTR)TEXT("MaximumLogSize"), offsetof(struct _SCE_PROFILE_INFO, MaximumLogSize), 'D'},
|
|
{(PWSTR)TEXT("AuditLogRetentionPeriod"),offsetof(struct _SCE_PROFILE_INFO, AuditLogRetentionPeriod), 'D'},
|
|
{(PWSTR)TEXT("RetentionDays"), offsetof(struct _SCE_PROFILE_INFO, RetentionDays), 'D'},
|
|
{(PWSTR)TEXT("RestrictGuestAccess"), offsetof(struct _SCE_PROFILE_INFO, RestrictGuestAccess), 'D'}
|
|
};
|
|
|
|
SCE_KEY_LOOKUP EventKeys[]={
|
|
{(PWSTR)TEXT("AuditSystemEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditSystemEvents), 'D'},
|
|
{(PWSTR)TEXT("AuditLogonEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditLogonEvents), 'D'},
|
|
{(PWSTR)TEXT("AuditObjectAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditObjectAccess), 'D'},
|
|
{(PWSTR)TEXT("AuditPrivilegeUse"), offsetof(struct _SCE_PROFILE_INFO, AuditPrivilegeUse), 'D'},
|
|
{(PWSTR)TEXT("AuditPolicyChange"), offsetof(struct _SCE_PROFILE_INFO, AuditPolicyChange), 'D'},
|
|
{(PWSTR)TEXT("AuditAccountManage"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountManage), 'D'},
|
|
{(PWSTR)TEXT("AuditProcessTracking"),offsetof(struct _SCE_PROFILE_INFO, AuditProcessTracking),'D'},
|
|
{(PWSTR)TEXT("AuditDSAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditDSAccess), 'D'},
|
|
{(PWSTR)TEXT("AuditAccountLogon"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountLogon), 'D'}};
|
|
|
|
DWORD cKeys = sizeof(EventKeys) / sizeof(SCE_KEY_LOOKUP);
|
|
|
|
PCWSTR szAuditLog;
|
|
DWORD i, j;
|
|
PSCESECTION hSection=NULL;
|
|
|
|
|
|
if ( hProfile == NULL ||
|
|
pProfileInfo == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
|
|
for ( i=0; i<3; i++) {
|
|
|
|
//
|
|
// Get Event Log setting for system log, security log and application log
|
|
//
|
|
|
|
switch (i) {
|
|
case 0:
|
|
szAuditLog = szAuditSystemLog;
|
|
break;
|
|
case 1:
|
|
szAuditLog = szAuditSecurityLog;
|
|
break;
|
|
default:
|
|
szAuditLog = szAuditApplicationLog;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// get DWORD values for the section
|
|
//
|
|
rc = ScepGetFixValueSection(
|
|
hProfile,
|
|
szAuditLog,
|
|
LogKeys,
|
|
4,
|
|
ProfileType,
|
|
(PVOID)pProfileInfo,
|
|
&hSection,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
// close the section
|
|
SceJetCloseSection( &hSection, FALSE );
|
|
|
|
//
|
|
// update the Offset for next section
|
|
//
|
|
for ( j=0; j<4; j++ )
|
|
LogKeys[j].Offset += sizeof(DWORD);
|
|
}
|
|
|
|
//
|
|
// Get Audit Event info
|
|
//
|
|
//
|
|
// get DWORD values for the section
|
|
//
|
|
rc = ScepGetFixValueSection(
|
|
hProfile,
|
|
szAuditEvent,
|
|
EventKeys,
|
|
cKeys,
|
|
ProfileType,
|
|
(PVOID)pProfileInfo,
|
|
&hSection,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
// close the section
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
Done:
|
|
|
|
// close the section
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
return(rc);
|
|
}
|
|
|
|
//////////////////////////////
|
|
// helper APIs
|
|
//////////////////////////////
|
|
|
|
SCESTATUS
|
|
ScepGetUserSection(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PWSTR Name,
|
|
OUT PVOID *ppInfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Function Description:
|
|
|
|
This routine get a dynamic section's information for a security area.
|
|
Dynamic sections are those created dynamically, based on other sections'
|
|
related information. Dynamic sections in a profile include User Security
|
|
Profiles for SCP and User Settings for SAP/SMP. Name contains the section's
|
|
identifier, either the section's name, or a partial name (e.g., a user
|
|
name) for the section. The output must be casted to different structure,
|
|
depending on the ProfileType and Area.
|
|
|
|
The output buffer contains one instance of the requested information,
|
|
e.g., one user security profile or one user's setting. To get all dynamic
|
|
sections, this routine must be called repeatly. The output buffer must
|
|
be freed by LocalFree after its use.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The handle of the profile
|
|
|
|
ProfileType - The type of the profile to read
|
|
|
|
Name - The dynamic section's identifier
|
|
|
|
ppInfo - Output buffer (PSCE_USER_PROFILE or PSCE_USER_SETTING)
|
|
|
|
Errlog - The error log buffer
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
-- */
|
|
|
|
{
|
|
//
|
|
// not support area
|
|
// if need this area later, refer to usersav directory for archived code
|
|
//
|
|
return(SCESTATUS_SERVICE_NOT_SUPPORT);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetObjectChildren(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectPrefix,
|
|
IN SCE_SUBOBJECT_TYPE Option,
|
|
OUT PVOID *Buffer,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*
|
|
Routine Description
|
|
|
|
This routine is the same as ScepGetObjectChildrenFromOneTable, except when
|
|
ProfileType is SCE_ENGINE_SAP, in which case, object children in SMP is also
|
|
looked up and returned so the returned list contains the complete set of
|
|
the objects analyzed.
|
|
|
|
Arguments:
|
|
|
|
See ScepGetObjectChildrenFromOneTable
|
|
|
|
Return Value:
|
|
|
|
See ScepGetObjectChildrenFromOneTable
|
|
*/
|
|
{
|
|
SCESTATUS rc;
|
|
|
|
rc = ScepGetObjectChildrenFromOneTable(
|
|
hProfile,
|
|
ProfileType,
|
|
Area,
|
|
ObjectPrefix,
|
|
Option,
|
|
Buffer,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SERVICE_NOT_SUPPORT &&
|
|
ProfileType == SCE_ENGINE_SAP &&
|
|
Option == SCE_IMMEDIATE_CHILDREN ) {
|
|
|
|
return( SCESTATUS_RECORD_NOT_FOUND); // no acl support, do not allow children
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS &&
|
|
ProfileType == SCE_ENGINE_SAP &&
|
|
Option == SCE_IMMEDIATE_CHILDREN ) {
|
|
|
|
PSCE_OBJECT_CHILDREN pTempList=NULL;
|
|
PSCE_OBJECT_CHILDREN_NODE *pArrObject=NULL;
|
|
DWORD arrCount=0, MaxCount=0;
|
|
LONG FindIndex;
|
|
|
|
if ( *Buffer ) {
|
|
arrCount = ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount;
|
|
MaxCount = ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount;
|
|
pArrObject = &(((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject);
|
|
}
|
|
|
|
//
|
|
// get object children from SMP table too
|
|
//
|
|
rc = ScepGetObjectChildrenFromOneTable(
|
|
hProfile,
|
|
SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
|
|
Area,
|
|
ObjectPrefix,
|
|
Option,
|
|
(PVOID *)(&pTempList),
|
|
Errlog
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS && pTempList ) {
|
|
//
|
|
// add non-exist nodes to Buffer
|
|
//
|
|
DWORD i;
|
|
PSCE_OBJECT_CHILDREN_NODE *pTmpObject= &(pTempList->arrObject);
|
|
|
|
for ( i=0; i<pTempList->nCount; i++ ) {
|
|
|
|
//
|
|
// if this node does not exist in the SAP
|
|
// this node is analyzed with "match" status and
|
|
// no bad children under the node
|
|
// duplication is prevented by the last argument
|
|
//
|
|
if ( pTmpObject[i] == NULL ||
|
|
pTmpObject[i]->Name == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
FindIndex = -1;
|
|
pTmpObject[i]->Status = SCE_STATUS_GOOD;
|
|
|
|
rc = ScepAddItemToChildren(
|
|
pTmpObject[i],
|
|
pTmpObject[i]->Name,
|
|
0,
|
|
pTmpObject[i]->IsContainer,
|
|
pTmpObject[i]->Status,
|
|
pTmpObject[i]->Count,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
//
|
|
// successfully added
|
|
//
|
|
pTmpObject[i] = NULL;
|
|
} else if ( rc == ERROR_DUP_NAME ) {
|
|
//
|
|
// node already exist, ignore the error
|
|
//
|
|
rc = ERROR_SUCCESS;
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
pTmpObject[i]->Name
|
|
);
|
|
//
|
|
// only the following two errors could be returned
|
|
//
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
} else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
if ( pTempList ) {
|
|
ScepFreeObjectChildren(pTempList);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// detect if status of this container or any of its "immediate" parent
|
|
// is in "auto-inherit" status. If so, query from the system to
|
|
// get good items.
|
|
//
|
|
|
|
BYTE ParentStatus = ScepGetObjectStatusFlag(
|
|
hProfile,
|
|
SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
|
|
Area,
|
|
ObjectPrefix,
|
|
TRUE);
|
|
|
|
BYTE AnalysisStatus = ScepGetObjectStatusFlag(
|
|
hProfile,
|
|
SCE_ENGINE_SAP,
|
|
Area,
|
|
ObjectPrefix,
|
|
FALSE);
|
|
//
|
|
// compute the status to be used for all enumerated objects
|
|
//
|
|
BYTE NewStatus;
|
|
|
|
if ( AnalysisStatus == SCE_STATUS_ERROR_NOT_AVAILABLE ||
|
|
AnalysisStatus == SCE_STATUS_NOT_ANALYZED ) {
|
|
|
|
NewStatus = SCE_STATUS_NOT_ANALYZED;
|
|
|
|
} else if ( ParentStatus == SCE_STATUS_OVERWRITE ) {
|
|
|
|
NewStatus = SCE_STATUS_GOOD;
|
|
} else {
|
|
NewStatus = SCE_STATUS_NOT_CONFIGURED;
|
|
}
|
|
|
|
//
|
|
// even though there is no parent in SMP, still return all objects
|
|
//
|
|
// if ( (BYTE)-1 != ParentStatus ) {
|
|
|
|
// if any child is found for this level
|
|
// get the remaining "good" status nodes from system
|
|
//
|
|
|
|
PWSTR WildCard=NULL;
|
|
DWORD BufSize;
|
|
|
|
switch ( Area ) {
|
|
case AREA_FILE_SECURITY:
|
|
|
|
struct _wfinddata_t FileInfo;
|
|
intptr_t hFile;
|
|
BOOL BackSlashExist;
|
|
|
|
BufSize = wcslen(ObjectPrefix)+4;
|
|
WildCard = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
|
|
if ( !WildCard ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
}
|
|
BackSlashExist = ScepLastBackSlash(ObjectPrefix);
|
|
if ( BackSlashExist )
|
|
swprintf(WildCard, L"%s*.*", ObjectPrefix);
|
|
else
|
|
swprintf(WildCard, L"%s\\*.*", ObjectPrefix);
|
|
|
|
hFile = _wfindfirst(WildCard, &FileInfo);
|
|
|
|
ScepFree(WildCard);
|
|
WildCard = NULL;
|
|
|
|
if ( hFile != -1 &&
|
|
( 0 == ( GetFileAttributes(ObjectPrefix) & // bug 635098: don't propagate permissions
|
|
FILE_ATTRIBUTE_REPARSE_POINT ))) // across junction points
|
|
{
|
|
do {
|
|
if ( wcscmp(L"..", FileInfo.name) == 0 ||
|
|
wcscmp(L".", FileInfo.name) == 0 )
|
|
continue;
|
|
|
|
FindIndex = -1;
|
|
|
|
rc = ScepAddItemToChildren(
|
|
NULL,
|
|
FileInfo.name,
|
|
0,
|
|
(FileInfo.attrib & _A_SUBDIR) ? TRUE : FALSE,
|
|
NewStatus,
|
|
0,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc == ERROR_DUP_NAME ) {
|
|
rc = ERROR_SUCCESS;
|
|
} else if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
FileInfo.name
|
|
);
|
|
//
|
|
// only the following two errors could be returned
|
|
//
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
} else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
} while ( _wfindnext(hFile, &FileInfo) == 0 );
|
|
|
|
_findclose(hFile);
|
|
}
|
|
|
|
break;
|
|
case AREA_REGISTRY_SECURITY:
|
|
|
|
HKEY hKey;
|
|
DWORD index;
|
|
DWORD EnumRc;
|
|
//
|
|
// open the key (on a 64-bit platform, 64-bit
|
|
// registry only will be done if SCE_ENGINE_SAP)
|
|
//
|
|
rc = ScepOpenRegistryObject(
|
|
SE_REGISTRY_KEY,
|
|
ObjectPrefix,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
index = 0;
|
|
//
|
|
// enumerate all subkeys of the key
|
|
//
|
|
do {
|
|
WildCard = (PWSTR)ScepAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR));
|
|
if ( WildCard == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
}
|
|
BufSize = MAX_PATH;
|
|
|
|
EnumRc = RegEnumKeyEx(hKey,
|
|
index,
|
|
WildCard,
|
|
&BufSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if ( EnumRc == ERROR_SUCCESS ) {
|
|
index++;
|
|
//
|
|
// add the name to the object list
|
|
//
|
|
FindIndex = -1;
|
|
rc = ScepAddItemToChildren(
|
|
NULL,
|
|
WildCard,
|
|
BufSize,
|
|
TRUE,
|
|
NewStatus,
|
|
0,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc == ERROR_DUP_NAME ) {
|
|
rc = ERROR_SUCCESS;
|
|
} else if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
WildCard
|
|
);
|
|
//
|
|
// only the following two errors could be returned
|
|
//
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
} else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
ScepFree(WildCard);
|
|
WildCard = NULL;
|
|
|
|
} while ( EnumRc != ERROR_NO_MORE_ITEMS );
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
} else {
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
}
|
|
|
|
break;
|
|
#if 0
|
|
case AREA_DS_OBJECTS:
|
|
|
|
PSCE_NAME_LIST pTemp, pList=NULL;
|
|
|
|
rc = ScepLdapOpen(NULL);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// detect if the Ds object exist
|
|
//
|
|
rc = ScepDsObjectExist(ObjectPrefix);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
rc = ScepEnumerateDsOneLevel(ObjectPrefix, &pList);
|
|
//
|
|
// add each one to the object list
|
|
//
|
|
for (pTemp=pList; pTemp != NULL; pTemp = pTemp->Next ) {
|
|
//
|
|
// look for the first ldap component
|
|
//
|
|
WildCard = wcschr(pTemp->Name, L',');
|
|
if ( WildCard ) {
|
|
BufSize = (DWORD)(WildCard - pTemp->Name);
|
|
} else {
|
|
BufSize = 0;
|
|
}
|
|
|
|
rc = ScepAddItemToChildren(
|
|
NULL,
|
|
pTemp->Name,
|
|
BufSize,
|
|
TRUE,
|
|
NewStatus,
|
|
0,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
pTemp->Name
|
|
);
|
|
//
|
|
// only the following two errors could be returned
|
|
//
|
|
if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
break;
|
|
} else
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
if ( pList ) {
|
|
//
|
|
// free the list
|
|
//
|
|
ScepFreeNameList(pList);
|
|
}
|
|
}
|
|
ScepLdapClose(NULL);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
}
|
|
//
|
|
// ignore other errors except out of memory
|
|
//
|
|
if ( rc != SCESTATUS_NOT_ENOUGH_RESOURCE ) {
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
// }
|
|
|
|
}
|
|
/*
|
|
if ( *Buffer ) {
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject = pArrObject;
|
|
}
|
|
*/
|
|
if ( pArrObject ) {
|
|
*Buffer = (PVOID)((PBYTE)pArrObject - 2*sizeof(DWORD));
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// free Buffer
|
|
//
|
|
ScepFreeObjectChildren((PSCE_OBJECT_CHILDREN)(*Buffer));
|
|
*Buffer = NULL;
|
|
}
|
|
}
|
|
|
|
if ( (SCESTATUS_SUCCESS == rc) &&
|
|
(*Buffer == NULL) ) {
|
|
//
|
|
// get nothing
|
|
//
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BYTE
|
|
ScepGetObjectStatusFlag(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectPrefix,
|
|
IN BOOL bLookForParent
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
To find the status for the closest parent node (immediate/non immediate)
|
|
for the Object in the table.
|
|
|
|
Arguments:
|
|
|
|
hProfile - the databaes handle
|
|
|
|
ProfileType - the table type
|
|
|
|
Area - the area information
|
|
|
|
ObjectPrefix - the object's full name
|
|
|
|
Return Value:
|
|
|
|
Byte - the status flag for the nearest parent if one is found
|
|
|
|
*/
|
|
{
|
|
LPCTSTR SectionName;
|
|
PSCESECTION hSection=NULL;
|
|
WCHAR Delim;
|
|
BYTE Status=(BYTE)-1;
|
|
|
|
SCESTATUS rc;
|
|
PWSTR JetName=NULL;
|
|
|
|
|
|
switch ( Area) {
|
|
case AREA_FILE_SECURITY:
|
|
SectionName = szFileSecurity;
|
|
JetName = ObjectPrefix;
|
|
Delim = L'\\';
|
|
break;
|
|
case AREA_REGISTRY_SECURITY:
|
|
SectionName = szRegistryKeys;
|
|
JetName = ObjectPrefix;
|
|
Delim = L'\\';
|
|
break;
|
|
#if 0
|
|
case AREA_DS_OBJECTS:
|
|
SectionName = szDSSecurity;
|
|
Delim = L',';
|
|
rc = ScepConvertLdapToJetIndexName(
|
|
ObjectPrefix,
|
|
&JetName
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return (BYTE)-1;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
return (BYTE)-1;
|
|
}
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
Status = ScepGetObjectAnalysisStatus(hSection,
|
|
JetName,
|
|
bLookForParent
|
|
);
|
|
}
|
|
|
|
SceJetCloseSection(&hSection, TRUE);
|
|
|
|
if ( JetName != ObjectPrefix ) {
|
|
ScepFree(JetName);
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
return Status;
|
|
}
|
|
|
|
return (BYTE)-1;
|
|
}
|
|
|
|
SCESTATUS
|
|
ScepGetObjectChildrenFromOneTable(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectPrefix,
|
|
IN SCE_SUBOBJECT_TYPE Option,
|
|
OUT PVOID *Buffer,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine is used for Registry and File Security ONLY.
|
|
|
|
This routine takes a object prefix ( e.g., a parent node’s full path name)
|
|
and outputs all files and sub directories under the object, or the immediate
|
|
children under the object, based on Option. When all files and sub
|
|
directories are outputted, the output information is in a n-tree structure
|
|
(SCE_OBJECT_TREE). If only the immediate children are outputted, the
|
|
output information is in a list structure (SCE_OBJECT_CHILDREN). The output buffer
|
|
must be freed by LocalFree after its use.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The handle to the profile
|
|
|
|
ProifleType - The type of the profile to read
|
|
|
|
Area - The security area to read info
|
|
AREA_REGISTRY_SECURITY
|
|
AREA_FILE_SECURITY
|
|
|
|
ObjectPrefix- The parent node’s full path name (e.g., c:\winnt)
|
|
|
|
Option - The option for output information. Valid values are
|
|
SCE_ALL_CHILDREN
|
|
SCE_IMMEDIATE_CHILDREN
|
|
|
|
Buffer - The output buffer.
|
|
|
|
Errlog - The error log buffer.
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
SCESTATUS rc = SCESTATUS_SUCCESS;
|
|
PCWSTR SectionName=NULL;
|
|
PWSTR JetName;
|
|
WCHAR Delim=L'\\';
|
|
|
|
|
|
if ( ObjectPrefix == NULL || ObjectPrefix[0] == L'\0' )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( Option == SCE_ALL_CHILDREN &&
|
|
ProfileType == SCE_ENGINE_SAP )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
|
|
switch (Area) {
|
|
case AREA_REGISTRY_SECURITY:
|
|
SectionName = szRegistryKeys;
|
|
JetName = ObjectPrefix;
|
|
break;
|
|
|
|
case AREA_FILE_SECURITY:
|
|
SectionName = szFileSecurity;
|
|
JetName = ObjectPrefix;
|
|
|
|
break;
|
|
#if 0
|
|
case AREA_DS_OBJECTS:
|
|
SectionName = szDSSecurity;
|
|
Delim = L',';
|
|
|
|
rc = ScepConvertLdapToJetIndexName(
|
|
ObjectPrefix,
|
|
&JetName
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
*Buffer = NULL;
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
DWORD PrefixLen;
|
|
PWSTR NewPrefix;
|
|
PWSTR ObjectName=NULL;
|
|
PWSTR Value=NULL;
|
|
DWORD ObjectLen, ValueLen;
|
|
PWSTR Buffer1=NULL;
|
|
|
|
//
|
|
// make a new prefix to force a Delim at the end
|
|
//
|
|
PrefixLen = wcslen(JetName);
|
|
|
|
if ( Option != SCE_ALL_CHILDREN ) {
|
|
|
|
if ( JetName[PrefixLen-1] != Delim )
|
|
PrefixLen++;
|
|
|
|
NewPrefix = (PWSTR)ScepAlloc(0, (PrefixLen+1)*sizeof(WCHAR));
|
|
|
|
if ( NewPrefix == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
} else {
|
|
wcscpy(NewPrefix, JetName);
|
|
NewPrefix[PrefixLen-1] = Delim;
|
|
NewPrefix[PrefixLen] = L'\0';
|
|
}
|
|
} else
|
|
NewPrefix = JetName;
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
if ( Area == AREA_DS_OBJECTS )
|
|
ScepFree(JetName);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
PSCESECTION hSection=NULL;
|
|
DWORD i;
|
|
PSCE_OBJECT_CHILDREN_NODE *pArrObject=NULL;
|
|
DWORD arrCount=0;
|
|
DWORD MaxCount=0;
|
|
LONG LastIndex=-1;
|
|
LONG FindIndex=-1;
|
|
|
|
//
|
|
// open the section
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP &&
|
|
Option != SCE_ALL_CHILDREN &&
|
|
PrefixLen > 2 ) {
|
|
|
|
//
|
|
// find if this drive support ACL
|
|
//
|
|
WCHAR StatusFlag=L'\0';
|
|
WCHAR SaveChr = NewPrefix[3];
|
|
|
|
NewPrefix[3] = L'\0';
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|
NewPrefix,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
(PWSTR)&StatusFlag, // two bytes buffer
|
|
2,
|
|
&i
|
|
);
|
|
|
|
NewPrefix[3] = SaveChr;
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ||
|
|
SCESTATUS_BUFFER_TOO_SMALL == rc ) {
|
|
|
|
i = *((BYTE *)&StatusFlag);
|
|
|
|
if ( i == (BYTE)SCE_STATUS_NO_ACL_SUPPORT ||
|
|
i == (DWORD)SCE_STATUS_NO_ACL_SUPPORT ) {
|
|
|
|
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
|
} else {
|
|
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
} else {
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_HANDLE,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
SectionName
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
DWORD Level;
|
|
PWSTR pTemp;
|
|
DWORD SDsize=0;
|
|
|
|
pTemp = wcschr(JetName, Delim);
|
|
Level=1;
|
|
while ( pTemp ) {
|
|
pTemp++;
|
|
if ( pTemp[0] != 0 )
|
|
Level++;
|
|
pTemp = wcschr(pTemp, Delim);
|
|
}
|
|
Level++;
|
|
|
|
|
|
if ( Option == SCE_ALL_CHILDREN ) {
|
|
//
|
|
// find the first record in the section
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH_NO_CASE,
|
|
JetName,
|
|
NULL,
|
|
0,
|
|
&SDsize, // temp use for ObjectLen,
|
|
NULL,
|
|
0,
|
|
&i // temp use for ValueLen
|
|
);
|
|
} else {
|
|
//
|
|
// find the first record matching prefix in the section
|
|
//
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
NewPrefix,
|
|
PrefixLen*sizeof(TCHAR),
|
|
SCEJET_SEEK_GE_NO_CASE
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// start the Ldap server
|
|
//
|
|
if ( Area == AREA_DS_OBJECTS) {
|
|
|
|
rc = ScepLdapOpen(NULL);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( 0,
|
|
Errlog,
|
|
SCEERR_CONVERT_LDAP,
|
|
L""
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&SDsize, // temp use for ObjectLen,
|
|
NULL,
|
|
0,
|
|
&i // temp use for ValueLen
|
|
);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
DWORD Count=0;
|
|
BYTE Status;
|
|
BOOL IsContainer;
|
|
SCEJET_FIND_TYPE FindFlag;
|
|
|
|
while ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// allocate memory for the group name and value string
|
|
//
|
|
ObjectName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, SDsize+2); // ObjectLen
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, i+2); //ValueLen
|
|
|
|
if ( ObjectName == NULL || Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
//
|
|
// Get the group and its value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
ObjectName,
|
|
SDsize,
|
|
&ObjectLen,
|
|
Value,
|
|
i,
|
|
&ValueLen
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_QUERY_VALUE,
|
|
SectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// teminate the string
|
|
//
|
|
if ( ObjectLen > SDsize )
|
|
ObjectLen = SDsize;
|
|
if ( ValueLen > i )
|
|
ValueLen = i;
|
|
|
|
ObjectName[ObjectLen/2] = L'\0';
|
|
Value[ValueLen/2] = L'\0';
|
|
|
|
if ( Option == SCE_ALL_CHILDREN ) {
|
|
//
|
|
// add this object to the object tree
|
|
//
|
|
|
|
PSECURITY_DESCRIPTOR pTempSD=NULL;
|
|
SECURITY_INFORMATION SeInfo;
|
|
|
|
//
|
|
// use i temperatorily
|
|
//
|
|
i = ConvertTextSecurityDescriptor(
|
|
Value+1,
|
|
&pTempSD,
|
|
&SDsize,
|
|
&SeInfo
|
|
);
|
|
|
|
if ( i == NO_ERROR ) {
|
|
|
|
if ( Area != AREA_DS_OBJECTS ) {
|
|
ScepChangeAclRevision(pTempSD, ACL_REVISION);
|
|
}
|
|
|
|
Status = *((BYTE *)Value);
|
|
IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
|
|
|
|
if ( Area == AREA_DS_OBJECTS && *Buffer == NULL ) {
|
|
//
|
|
// build the first node separately because the first node
|
|
// is always the domain name with its DNS name as full name
|
|
//
|
|
rc = ScepBuildDsTree(
|
|
(PSCE_OBJECT_CHILD_LIST *)Buffer,
|
|
Level-1,
|
|
Delim,
|
|
JetName
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
if ( _wcsicmp(ObjectName, JetName) == 0 ) {
|
|
//
|
|
// exact match
|
|
//
|
|
(*((PSCE_OBJECT_TREE *)Buffer))->IsContainer = IsContainer;
|
|
(*((PSCE_OBJECT_TREE *)Buffer))->Status = Status;
|
|
(*((PSCE_OBJECT_TREE *)Buffer))->pSecurityDescriptor = pTempSD;
|
|
(*((PSCE_OBJECT_TREE *)Buffer))->SeInfo = SeInfo;
|
|
|
|
} else {
|
|
|
|
rc = ScepBuildObjectTree(
|
|
NULL,
|
|
(PSCE_OBJECT_CHILD_LIST *)Buffer,
|
|
Level-1,
|
|
Delim,
|
|
ObjectName,
|
|
IsContainer,
|
|
Status,
|
|
pTempSD,
|
|
SeInfo
|
|
);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = ScepBuildObjectTree(
|
|
NULL,
|
|
(PSCE_OBJECT_CHILD_LIST *)Buffer,
|
|
(Area == AREA_DS_OBJECTS) ? Level : 1,
|
|
Delim,
|
|
ObjectName,
|
|
IsContainer,
|
|
Status,
|
|
pTempSD,
|
|
SeInfo
|
|
);
|
|
}
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_BUILD_OBJECT
|
|
);
|
|
ScepFree(pTempSD);
|
|
}
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo( i,
|
|
Errlog,
|
|
SCEERR_BUILD_SD,
|
|
ObjectName // Value+1
|
|
);
|
|
rc = ScepDosErrorToSceStatus(i);
|
|
}
|
|
FindFlag = SCEJET_NEXT_LINE;
|
|
|
|
} else {
|
|
|
|
INT CompFlag;
|
|
DWORD ListHeadLen;
|
|
|
|
// verify it is within the right range
|
|
CompFlag = _wcsnicmp(ObjectName, NewPrefix, PrefixLen);
|
|
|
|
if ( pArrObject != NULL && LastIndex >= 0 && LastIndex < (LONG)arrCount ) {
|
|
ListHeadLen = wcslen(pArrObject[LastIndex]->Name);
|
|
|
|
} else
|
|
ListHeadLen = 0;
|
|
|
|
if ( (CompFlag == 0 && PrefixLen == ObjectLen/2) ||
|
|
CompFlag < 0 ) {
|
|
// CompFlag < 0 should be impossible!!!
|
|
// if it is the exact match with ObjectPrefix, ignore
|
|
//
|
|
// Every next level node is returned in the ObjectList
|
|
// with either
|
|
// Count=0 ( no sub children ), or
|
|
// Count > 0 && Status=SCE_STATUS_GOOD (this one is good)
|
|
// Status=mismatch/unknown/ignore/check
|
|
// should not count the object itself
|
|
//
|
|
rc = SceJetMoveNext(hSection);
|
|
|
|
} else if (CompFlag > 0 ) {
|
|
|
|
rc = SCESTATUS_RECORD_NOT_FOUND;
|
|
|
|
} else if (pArrObject != NULL && LastIndex >= 0 && LastIndex < (LONG)arrCount &&
|
|
PrefixLen+ListHeadLen < ObjectLen/2 &&
|
|
ObjectName[PrefixLen+ListHeadLen] == Delim &&
|
|
_wcsnicmp( pArrObject[LastIndex]->Name, ObjectName+PrefixLen,
|
|
ListHeadLen ) == 0 ) {
|
|
//
|
|
// if the list is not NULL, check the list head (new added item)
|
|
// to see if the ObjectName is already in. If yes, skip
|
|
//
|
|
Buffer1 = (PWSTR)ScepAlloc(0, (ListHeadLen+PrefixLen+2)*sizeof(WCHAR));
|
|
|
|
if ( Buffer1 == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
} else {
|
|
|
|
swprintf(Buffer1, L"%s%s", NewPrefix, pArrObject[LastIndex]->Name);
|
|
Buffer1[PrefixLen+ListHeadLen] = (WCHAR) (Delim + 1);
|
|
Buffer1[PrefixLen+ListHeadLen+1] = L'\0';
|
|
//
|
|
// skip the block
|
|
//
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
Buffer1,
|
|
(PrefixLen+ListHeadLen+1)*sizeof(TCHAR),
|
|
SCEJET_SEEK_GE_DONT_CARE //SCEJET_SEEK_GE_NO_CASE
|
|
);
|
|
|
|
ScepFree(Buffer1);
|
|
Buffer1 = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DWORD Len;
|
|
BOOL LastOne;
|
|
|
|
//
|
|
// searching for the right level component
|
|
//
|
|
PWSTR pStart = ObjectName;
|
|
|
|
for ( i=0; i<Level; i++) {
|
|
|
|
pTemp = wcschr(pStart, Delim);
|
|
|
|
if ( i == Level-1 ) {
|
|
//
|
|
// find the right level
|
|
//
|
|
if ( pTemp == NULL ) {
|
|
LastOne = TRUE;
|
|
Len = ObjectLen/2; // wcslen(pStart); from begining
|
|
} else {
|
|
Len = (DWORD)(pTemp - ObjectName); // pStart; from begining
|
|
if ( *(pTemp+1) == L'\0' )
|
|
LastOne = TRUE;
|
|
else
|
|
LastOne = FALSE;
|
|
}
|
|
SDsize = (DWORD)(pStart - ObjectName);
|
|
} else {
|
|
if ( pTemp == NULL ) {
|
|
rc = SCESTATUS_INVALID_PARAMETER;
|
|
break;
|
|
} else
|
|
pStart = pTemp + 1;
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS && Len > SDsize ) {
|
|
|
|
Buffer1 = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( Buffer1 == NULL )
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
else {
|
|
// wcsncpy(Buffer1, pStart, Len );
|
|
wcsncpy(Buffer1, ObjectName, Len);
|
|
|
|
Count = 1;
|
|
|
|
if ( LastOne ) {
|
|
|
|
Count = 0;
|
|
|
|
Status = *((BYTE *)Value);
|
|
IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
|
|
|
|
} else {
|
|
IsContainer = TRUE;
|
|
|
|
if ( ProfileType == SCE_ENGINE_SAP )
|
|
Status = SCE_STATUS_GOOD;
|
|
else
|
|
Status = SCE_STATUS_CHECK;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_PROCESS_OBJECT,
|
|
ObjectName
|
|
);
|
|
} else if ( Buffer1 != NULL) {
|
|
//
|
|
// check to see if Buffer1 is already in the list
|
|
//
|
|
|
|
i=0; // temp. use of i for skip flag
|
|
if ( pArrObject && LastIndex >= 0 && LastIndex < (LONG)arrCount ) {
|
|
|
|
if ( ScepSearchItemInChildren(Buffer1+SDsize,
|
|
Len-SDsize,
|
|
pArrObject,
|
|
arrCount,
|
|
&FindIndex
|
|
)
|
|
) {
|
|
|
|
//
|
|
// Buffer1 is already in the list, skip the block
|
|
// use pStart temporarily
|
|
//
|
|
|
|
pStart = (PWSTR)ScepAlloc(0, (Len+2)*sizeof(WCHAR));
|
|
if ( pStart == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
} else {
|
|
//
|
|
// skip the block
|
|
//
|
|
|
|
wcscpy(pStart, Buffer1);
|
|
pStart[Len] = (WCHAR) ( Delim+1);
|
|
pStart[Len+1] = L'\0';
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
pStart,
|
|
(Len+1)*sizeof(TCHAR),
|
|
SCEJET_SEEK_GE_DONT_CARE //cannot use GT cause it will skip the section
|
|
);
|
|
|
|
ScepFree(pStart);
|
|
pStart = NULL;
|
|
|
|
i=1;
|
|
LastIndex = FindIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( 0 == i && SCESTATUS_SUCCESS == rc ) {
|
|
|
|
//
|
|
// get count
|
|
//
|
|
pStart = (PWSTR)ScepAlloc(0, (Len+2)*sizeof(WCHAR));
|
|
if ( pStart == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
} else {
|
|
|
|
wcscpy(pStart, Buffer1);
|
|
pStart[Len] = Delim;
|
|
pStart[Len+1] = L'\0';
|
|
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
pStart,
|
|
FALSE,
|
|
&Count);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ||
|
|
rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
|
|
if ( !IsContainer && Count > 0 ) {
|
|
IsContainer = TRUE;
|
|
}
|
|
|
|
//
|
|
// make buffer1 approprate case
|
|
//
|
|
switch (Area) {
|
|
case AREA_REGISTRY_SECURITY:
|
|
rc = ScepGetRegKeyCase(Buffer1, SDsize, Len-SDsize);
|
|
break;
|
|
case AREA_FILE_SECURITY:
|
|
rc = ScepGetFileCase(Buffer1, SDsize, Len-SDsize);
|
|
break;
|
|
case AREA_DS_OBJECTS:
|
|
//
|
|
// need convert name first from o=,dc=,cn= to cn=,dc=,o=
|
|
//
|
|
pTemp=NULL;
|
|
rc = ScepConvertJetNameToLdapCase(
|
|
Buffer1,
|
|
TRUE, // Last component only
|
|
SCE_CASE_PREFERED, // right case
|
|
&pTemp
|
|
);
|
|
|
|
if ( rc != ERROR_FILE_NOT_FOUND && pTemp != NULL ) {
|
|
|
|
rc = ScepAddItemToChildren(NULL,
|
|
pTemp,
|
|
wcslen(pTemp),
|
|
IsContainer,
|
|
Status,
|
|
Count,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
pTemp
|
|
);
|
|
} else {
|
|
LastIndex = FindIndex;
|
|
}
|
|
|
|
ScepFree(pTemp);
|
|
pTemp = NULL;
|
|
}
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
break;
|
|
}
|
|
/*
|
|
if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
|
|
//
|
|
// if the object does not exist, do not add
|
|
//
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else if ( Area != AREA_DS_OBJECTS ) {
|
|
*/
|
|
if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
|
|
Area != AREA_DS_OBJECTS ) {
|
|
|
|
rc = ScepAddItemToChildren(NULL,
|
|
Buffer1+SDsize,
|
|
Len-SDsize,
|
|
IsContainer,
|
|
Status,
|
|
Count,
|
|
&pArrObject,
|
|
&arrCount,
|
|
&MaxCount,
|
|
&FindIndex
|
|
);
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
Buffer1
|
|
);
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
} else {
|
|
LastIndex = FindIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// seek to the original one
|
|
//
|
|
// Buffer1[Len-1] = (WCHAR) (Buffer1[Len-1] + 1);
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
Buffer1,
|
|
Len*sizeof(TCHAR),
|
|
SCEJET_SEEK_GE_NO_CASE
|
|
);
|
|
//
|
|
// should be success, move to next line
|
|
//
|
|
rc = SceJetMoveNext(hSection);
|
|
|
|
} else if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
|
|
|
|
pStart[Len] = (WCHAR) ( Delim+1);
|
|
pStart[Len+1] = L'\0';
|
|
|
|
rc = SceJetSeek(
|
|
hSection,
|
|
pStart,
|
|
(Len+1)*sizeof(TCHAR),
|
|
SCEJET_SEEK_GE_DONT_CARE //cannot use GT cause it will skip the section
|
|
);
|
|
|
|
}
|
|
|
|
ScepFree(pStart);
|
|
pStart = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
ScepFree(Buffer1);
|
|
Buffer1 = NULL;
|
|
|
|
} else
|
|
rc = SceJetMoveNext(hSection);
|
|
}
|
|
FindFlag = SCEJET_CURRENT;
|
|
}
|
|
|
|
ScepFree(ObjectName);
|
|
ObjectName = NULL;
|
|
|
|
ScepFree(Value);
|
|
Value = NULL;
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
break;
|
|
|
|
//
|
|
// read next line
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
FindFlag,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&SDsize, // temp use for ObjectLen
|
|
NULL,
|
|
0,
|
|
&i // temp use for ValueLen
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( Area == AREA_DS_OBJECTS ) {
|
|
|
|
if ( Area == AREA_DS_OBJECTS ) {
|
|
if ( JetName != NULL )
|
|
ScepFree(JetName);
|
|
}
|
|
|
|
ScepLdapClose(NULL);
|
|
}
|
|
|
|
if ( Option != SCE_ALL_CHILDREN ) {
|
|
ScepFree(NewPrefix);
|
|
}
|
|
|
|
if ( Buffer1 != NULL )
|
|
ScepFree(Buffer1);
|
|
|
|
if ( ObjectName != NULL )
|
|
ScepFree(ObjectName);
|
|
|
|
if ( Value != NULL )
|
|
ScepFree(Value);
|
|
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( ( rc == SCESTATUS_SUCCESS ) &&
|
|
( Option != SCE_ALL_CHILDREN ) ) {
|
|
|
|
if ( pArrObject ) {
|
|
*Buffer = (PVOID)((PBYTE)pArrObject-sizeof(DWORD)*2);
|
|
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
|
|
} else {
|
|
*Buffer = NULL;
|
|
}
|
|
/*
|
|
*Buffer = ScepAlloc(0, sizeof(SCE_OBJECT_CHILDREN));
|
|
|
|
if ( *Buffer ) {
|
|
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
|
|
((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject = pArrObject;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
*/
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// free (PVOID *)Buffer
|
|
//
|
|
if ( Option == SCE_ALL_CHILDREN ) {
|
|
// OBJECT_CHILD_LIST structure
|
|
ScepFreeObject2Security((PSCE_OBJECT_CHILD_LIST)(*Buffer), FALSE);
|
|
} else if ( pArrObject ) {
|
|
// OBJECT_CHILDREN structure
|
|
ScepFreeObjectChildren((PSCE_OBJECT_CHILDREN)((PBYTE)pArrObject-sizeof(DWORD)*2));
|
|
}
|
|
*Buffer = NULL;
|
|
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepBuildDsTree(
|
|
OUT PSCE_OBJECT_CHILD_LIST *TreeRoot,
|
|
IN ULONG Level,
|
|
IN WCHAR Delim,
|
|
IN PCWSTR ObjectFullName
|
|
)
|
|
{
|
|
TCHAR Buffer[MAX_PATH];
|
|
BOOL LastOne=FALSE;
|
|
SCESTATUS rc;
|
|
|
|
if ( TreeRoot == NULL || ObjectFullName == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
memset(Buffer, '\0', MAX_PATH*sizeof(TCHAR));
|
|
|
|
rc = ScepGetNameInLevel(ObjectFullName,
|
|
Level,
|
|
Delim,
|
|
Buffer,
|
|
&LastOne);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
*TreeRoot = (PSCE_OBJECT_CHILD_LIST)ScepAlloc(LPTR, sizeof(SCE_OBJECT_CHILD_LIST));
|
|
if ( *TreeRoot == NULL )
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
|
|
PSCE_OBJECT_TREE Node;
|
|
|
|
//
|
|
// allocate buffer for the node
|
|
//
|
|
Node = (PSCE_OBJECT_TREE)ScepAlloc((UINT)0, sizeof(SCE_OBJECT_TREE));
|
|
if ( Node == NULL ) {
|
|
ScepFree(*TreeRoot);
|
|
*TreeRoot = NULL;
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
|
|
//
|
|
// allocate buffer for the object name
|
|
//
|
|
Node->Name = (PWSTR)ScepAlloc((UINT)0,
|
|
(wcslen(Buffer)+1) * sizeof(TCHAR));
|
|
if ( Node->Name != NULL ) {
|
|
|
|
Node->ObjectFullName = (PWSTR)ScepAlloc( 0, (wcslen(ObjectFullName)+1)*sizeof(TCHAR));
|
|
|
|
if ( Node->ObjectFullName != NULL ) {
|
|
//
|
|
// initialize
|
|
//
|
|
wcscpy(Node->Name, Buffer);
|
|
wcscpy(Node->ObjectFullName, ObjectFullName);
|
|
|
|
Node->ChildList = NULL;
|
|
Node->Parent = NULL;
|
|
Node->pApplySecurityDescriptor = NULL;
|
|
|
|
Node->pSecurityDescriptor = NULL;
|
|
Node->SeInfo = 0;
|
|
Node->IsContainer = TRUE;
|
|
Node->Status = SCE_STATUS_CHECK;
|
|
|
|
(*TreeRoot)->Node = Node;
|
|
|
|
} else {
|
|
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree( Node->Name );
|
|
ScepFree( Node );
|
|
ScepFree( *TreeRoot );
|
|
*TreeRoot = NULL;
|
|
}
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree( Node );
|
|
ScepFree( *TreeRoot );
|
|
*TreeRoot = NULL;
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetObjectSecurity(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN AREA_INFORMATION Area,
|
|
IN PWSTR ObjectName,
|
|
OUT PSCE_OBJECT_SECURITY *ObjSecurity
|
|
)
|
|
/*
|
|
Get security for a single object
|
|
*/
|
|
{
|
|
SCESTATUS rc;
|
|
PCWSTR SectionName=NULL;
|
|
PSCESECTION hSection=NULL;
|
|
PWSTR Value=NULL;
|
|
DWORD ValueLen;
|
|
PSECURITY_DESCRIPTOR pTempSD=NULL;
|
|
SECURITY_INFORMATION SeInfo;
|
|
DWORD SDsize, Win32Rc;
|
|
|
|
|
|
if ( hProfile == NULL || ObjectName == NULL ||
|
|
ObjSecurity == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
switch (Area) {
|
|
case AREA_REGISTRY_SECURITY:
|
|
SectionName = szRegistryKeys;
|
|
break;
|
|
case AREA_FILE_SECURITY:
|
|
SectionName = szFileSecurity;
|
|
break;
|
|
#if 0
|
|
case AREA_DS_OBJECTS:
|
|
SectionName = szDSSecurity;
|
|
break;
|
|
#endif
|
|
default:
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|
ObjectName,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// allocate memory for value string
|
|
//
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
|
|
if ( Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
//
|
|
// Get the value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// convert security descriptor
|
|
//
|
|
|
|
Win32Rc = ConvertTextSecurityDescriptor(
|
|
Value+1,
|
|
&pTempSD,
|
|
&SDsize,
|
|
&SeInfo
|
|
);
|
|
if ( Win32Rc == NO_ERROR ) {
|
|
|
|
if ( Area != AREA_DS_OBJECTS ) {
|
|
ScepChangeAclRevision(pTempSD, ACL_REVISION);
|
|
}
|
|
//
|
|
// allocate output buffer (SCE_OBJECT_SECURITY)
|
|
//
|
|
*ObjSecurity = (PSCE_OBJECT_SECURITY)ScepAlloc(0, sizeof(SCE_OBJECT_SECURITY));
|
|
if ( *ObjSecurity == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
(*ObjSecurity)->Name = (PWSTR)ScepAlloc(0, (wcslen(ObjectName)+1)*sizeof(TCHAR));
|
|
if ( (*ObjSecurity)->Name == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree(*ObjSecurity);
|
|
*ObjSecurity = NULL;
|
|
goto Done;
|
|
}
|
|
/*
|
|
(*ObjSecurity)->SDspec = (PWSTR)ScepAlloc(0, ValueLen);
|
|
if ( (*ObjSecurity)->SDspec == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree((*ObjSecurity)->Name);
|
|
ScepFree(*ObjSecurity);
|
|
*ObjSecurity = NULL;
|
|
goto Done;
|
|
}
|
|
*/
|
|
//
|
|
// build the structure
|
|
//
|
|
(*ObjSecurity)->Status = *((BYTE *)Value);
|
|
(*ObjSecurity)->IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
|
|
|
|
wcscpy( (*ObjSecurity)->Name, ObjectName);
|
|
(*ObjSecurity)->pSecurityDescriptor = pTempSD;
|
|
pTempSD = NULL;
|
|
(*ObjSecurity)->SeInfo = SeInfo;
|
|
// wcscpy( (*ObjSecurity)->SDspec, Value+1);
|
|
// (*ObjSecurity)->SDsize = ValueLen/2-1;
|
|
|
|
} else
|
|
rc = ScepDosErrorToSceStatus(Win32Rc);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( pTempSD )
|
|
ScepFree(pTempSD);
|
|
if ( Value )
|
|
ScepFree(Value);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetSystemServices(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
OUT PSCE_SERVICES *pServiceList,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Read all services defined in the Jet table into the service list
|
|
|
|
Arguments:
|
|
|
|
hProfile - the jet profile handle
|
|
|
|
ProfileType - The table to read from
|
|
SCE_ENGINE_SCP
|
|
SCE_ENGINE_SAP
|
|
SCE_ENGINE_SMP
|
|
|
|
pServiceList - The service list to output
|
|
|
|
Errlog - the error messages to output
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS error codes
|
|
|
|
*/
|
|
{
|
|
SCESTATUS rc;
|
|
DWORD Win32Rc;
|
|
PSCESECTION hSection=NULL;
|
|
DWORD ServiceLen=0, ValueLen=0;
|
|
PWSTR ServiceName=NULL,
|
|
Value=NULL;
|
|
PSECURITY_DESCRIPTOR pTempSD=NULL;
|
|
SECURITY_INFORMATION SeInfo;
|
|
DWORD SDsize;
|
|
PSCE_SERVICES ServiceNode;
|
|
PSCE_SERVICES pServices=NULL, pNode, pParent;
|
|
|
|
|
|
if ( hProfile == NULL ||
|
|
pServiceList == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
//
|
|
// open the section
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
szServiceGeneral,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
szServiceGeneral
|
|
);
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// enumerate all service names from the system.
|
|
// do not care the error code
|
|
//
|
|
SceEnumerateServices(&pServices, TRUE);
|
|
|
|
//
|
|
// goto the first line of this section
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ServiceLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
while ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// allocate memory for the service name and value string
|
|
//
|
|
ServiceName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ServiceLen+2);
|
|
if ( ServiceName != NULL ) {
|
|
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
if ( Value != NULL ) {
|
|
//
|
|
// Get the service and its value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
ServiceName,
|
|
ServiceLen,
|
|
&ServiceLen,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
ServiceName[ServiceLen/2] = L'\0';
|
|
Value[ValueLen/2] = L'\0';
|
|
|
|
#ifdef SCE_DBG
|
|
wprintf(L"rc=%d, service: %s=%s\n", rc, ServiceName, Value);
|
|
#endif
|
|
//
|
|
// convert to security descriptor
|
|
//
|
|
Win32Rc = ConvertTextSecurityDescriptor(
|
|
Value+1,
|
|
&pTempSD,
|
|
&SDsize,
|
|
&SeInfo
|
|
);
|
|
if ( Win32Rc == NO_ERROR ) {
|
|
|
|
ScepChangeAclRevision(pTempSD, ACL_REVISION);
|
|
//
|
|
// create this service node
|
|
//
|
|
ServiceNode = (PSCE_SERVICES)ScepAlloc( LMEM_FIXED, sizeof(SCE_SERVICES) );
|
|
|
|
if ( ServiceNode != NULL ) {
|
|
//
|
|
// find the right name for the service
|
|
//
|
|
for ( pNode=pServices, pParent=NULL; pNode != NULL;
|
|
pParent=pNode, pNode=pNode->Next ) {
|
|
|
|
if ( _wcsicmp(pNode->ServiceName, ServiceName) == 0 ) {
|
|
break;
|
|
}
|
|
}
|
|
if ( pNode != NULL ) {
|
|
//
|
|
// got it
|
|
//
|
|
ServiceNode->ServiceName = pNode->ServiceName;
|
|
ServiceNode->DisplayName = pNode->DisplayName;
|
|
//
|
|
// free the node
|
|
//
|
|
if ( pParent != NULL ) {
|
|
pParent->Next = pNode->Next;
|
|
} else {
|
|
pServices = pNode->Next;
|
|
}
|
|
// General is NULL becuase the enumerate call asks only for names
|
|
ScepFree(pNode);
|
|
pNode = NULL;
|
|
|
|
} else {
|
|
//
|
|
// did not find it
|
|
//
|
|
ServiceNode->ServiceName = ServiceName;
|
|
ServiceNode->DisplayName = NULL;
|
|
|
|
ServiceName = NULL;
|
|
}
|
|
|
|
ServiceNode->Status = *((BYTE *)Value);
|
|
ServiceNode->Startup = *((BYTE *)Value+1);
|
|
ServiceNode->General.pSecurityDescriptor = pTempSD;
|
|
ServiceNode->SeInfo = SeInfo;
|
|
ServiceNode->Next = *pServiceList;
|
|
|
|
*pServiceList = ServiceNode;
|
|
|
|
//
|
|
// DO NOT free the following buffers
|
|
//
|
|
pTempSD = NULL;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree(pTempSD);
|
|
}
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo( Win32Rc,
|
|
Errlog,
|
|
SCEERR_BUILD_SD,
|
|
ServiceName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(Win32Rc);
|
|
}
|
|
}
|
|
ScepFree(Value);
|
|
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
//
|
|
// ServiceName could be used in the service node
|
|
//
|
|
if ( ServiceName )
|
|
ScepFree(ServiceName);
|
|
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// read next line
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ServiceLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// close the section
|
|
//
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
//
|
|
// free the service list
|
|
//
|
|
SceFreePSCE_SERVICES(*pServiceList);
|
|
*pServiceList = NULL;
|
|
}
|
|
|
|
SceFreePSCE_SERVICES(pServices);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
ScepCopyObjects(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PWSTR InfFile,
|
|
IN PCWSTR SectionName,
|
|
IN AREA_INFORMATION Area,
|
|
IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine copies registry/file/ds/service object in SMP table to the specified
|
|
inf template.
|
|
|
|
Arguments:
|
|
|
|
hProfile - The handle to the profile
|
|
|
|
InfFile - The INF template name
|
|
|
|
SectionName - the section name where data is stored
|
|
|
|
Area - The security area to read info
|
|
AREA_REGISTRY_SECURITY
|
|
AREA_FILE_SECURITY
|
|
AREA_DS_OBJECTS
|
|
|
|
Errlog - The error log buffer.
|
|
|
|
Return Value:
|
|
|
|
SCESTATUS_SUCCESS
|
|
SCESTATUS_PROFILE_NOT_FOUND
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
SCESTATUS rc = SCESTATUS_SUCCESS;
|
|
PSCESECTION hSection=NULL;
|
|
|
|
PWSTR ObjectName=NULL;
|
|
PWSTR Value=NULL;
|
|
DWORD ObjectLen, ValueLen;
|
|
|
|
BYTE Status;
|
|
PWSTR NewValue=NULL;
|
|
|
|
DWORD Count=0;
|
|
WCHAR KeyName[10];
|
|
|
|
|
|
if ( InfFile == NULL || hProfile == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
//
|
|
// open the section
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// empty the section first.
|
|
//
|
|
WritePrivateProfileSection(
|
|
SectionName,
|
|
NULL,
|
|
(LPCTSTR)InfFile);
|
|
//
|
|
// find the first record in the section
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ObjectLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
|
|
while ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
Count++;
|
|
//
|
|
// allocate memory for the group name and value string
|
|
//
|
|
|
|
|
|
ObjectName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ObjectLen+2);
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
|
|
if ( ObjectName == NULL || Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
//
|
|
// Get the group and its value
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
ObjectName,
|
|
ObjectLen,
|
|
&ObjectLen,
|
|
Value,
|
|
ValueLen,
|
|
&ValueLen
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo( ERROR_READ_FAULT,
|
|
Errlog,
|
|
SCEERR_QUERY_VALUE,
|
|
SectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
|
|
|
|
#ifdef SCE_DBG
|
|
wprintf(L"Addr: %x %x, %s=%s\n", ObjectName, Value, ObjectName, Value+1);
|
|
#endif
|
|
|
|
if ( Area == AREA_SYSTEM_SERVICE )
|
|
Status = *((BYTE *)Value+1);
|
|
else
|
|
Status = *((BYTE *)Value);
|
|
|
|
if (0 == _wcsicmp(SectionName, szRegistryKeys) &&
|
|
Status != 1 &&
|
|
0 == _wcsnicmp(L"machine\\system\\controlset",
|
|
ObjectName,
|
|
wcslen(L"machine\\system\\controlset"))) {
|
|
|
|
ObjectName = ScepSpecialCaseRegkeyCcs( ObjectName );
|
|
|
|
if ( ObjectName == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
NewValue = (PWSTR)ScepAlloc(0, ObjectLen+ValueLen+40);
|
|
|
|
if ( NewValue == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// to represent "not configured"
|
|
// 0 is used in the database
|
|
// "" is used in the inf template
|
|
// so just generate "" instead of "0"
|
|
//
|
|
|
|
if ( Area == AREA_SYSTEM_SERVICE && Status == 0 ){
|
|
swprintf(NewValue, L"\"%s\",, \"%s\"\0", ObjectName, Value+1);
|
|
}
|
|
else {
|
|
swprintf(NewValue, L"\"%s\", %d, \"%s\"\0", ObjectName, Status, Value+1);
|
|
}
|
|
swprintf(KeyName, L"%x\0", Count);
|
|
|
|
//
|
|
// write this line to the inf file
|
|
//
|
|
if ( !WritePrivateProfileString(
|
|
SectionName,
|
|
KeyName,
|
|
NewValue,
|
|
InfFile
|
|
) ) {
|
|
ScepBuildErrorLogInfo( GetLastError(),
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
ObjectName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(GetLastError());
|
|
}
|
|
|
|
ScepFree(ObjectName);
|
|
ObjectName = NULL;
|
|
|
|
ScepFree(Value);
|
|
Value = NULL;
|
|
|
|
ScepFree(NewValue);
|
|
NewValue = NULL;
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
break;
|
|
|
|
//
|
|
// read next line
|
|
//
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&ObjectLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
} else
|
|
ScepBuildErrorLogInfo( ERROR_INVALID_HANDLE,
|
|
Errlog,
|
|
SCEERR_OPEN,
|
|
SectionName
|
|
);
|
|
|
|
Done:
|
|
|
|
if ( ObjectName != NULL )
|
|
ScepFree(ObjectName);
|
|
|
|
if ( Value != NULL )
|
|
ScepFree(Value);
|
|
|
|
if ( NewValue != NULL )
|
|
ScepFree(NewValue);
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
PWSTR
|
|
ScepSpecialCaseRegkeyCcs(
|
|
IN OUT PWSTR ObjectName
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
When Status != 1 convert all currentcontrolsetxxx's to currentcontrolset
|
|
|
|
Arguments:
|
|
|
|
ObjectName - name of registry key to modify
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
-- */
|
|
{
|
|
PWSTR pszNewObjectName = NULL;
|
|
DWORD dwCcsLen = wcslen(L"machine\\system\\controlset");
|
|
|
|
if (0 == _wcsnicmp(L"machine\\system\\controlset",
|
|
ObjectName,
|
|
dwCcsLen)) {
|
|
|
|
pszNewObjectName = (PWSTR)ScepAlloc(0,
|
|
(wcslen(ObjectName) + wcslen(L"current") + 3) * sizeof(WCHAR));
|
|
|
|
if (NULL == pszNewObjectName) {
|
|
goto Done;
|
|
}
|
|
|
|
pszNewObjectName[0] = L'\0';
|
|
|
|
wcscat(pszNewObjectName, L"machine\\system\\currentcontrolset");
|
|
|
|
wchar_t *pSlash = NULL;
|
|
|
|
pSlash = wcsstr(ObjectName + dwCcsLen, L"\\");
|
|
|
|
if (pSlash != NULL) {
|
|
wcscat(pszNewObjectName, pSlash);
|
|
}
|
|
|
|
}
|
|
|
|
Done:
|
|
|
|
ScepFree(ObjectName);
|
|
|
|
return pszNewObjectName;
|
|
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
ScepGetAnalysisSummary(
|
|
IN PSCECONTEXT Context,
|
|
IN AREA_INFORMATION Area,
|
|
OUT PDWORD pCount
|
|
)
|
|
{
|
|
SCESTATUS rc=SCESTATUS_INVALID_PARAMETER;
|
|
DWORD count;
|
|
DWORD total=0;
|
|
PSCESECTION hSection=NULL;
|
|
|
|
if ( Context == NULL || pCount == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
*pCount = 0;
|
|
|
|
if ( Area & AREA_SECURITY_POLICY ) {
|
|
//
|
|
// system access
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szSystemAccess,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
|
|
//
|
|
// System Log
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szAuditSystemLog,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
//
|
|
// Security Log
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szAuditSecurityLog,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
//
|
|
// Application Log
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szAuditApplicationLog,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
//
|
|
// Event Audit
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szAuditEvent,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
|
|
if ( Area & AREA_PRIVILEGES ) {
|
|
//
|
|
// Privileges
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szPrivilegeRights,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
|
|
if ( Area & AREA_GROUP_MEMBERSHIP) {
|
|
//
|
|
// Group Membership
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szGroupMembership,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
|
|
if ( Area & AREA_SYSTEM_SERVICE ) {
|
|
//
|
|
// system service
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szServiceGeneral,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
|
|
if ( Area & AREA_REGISTRY_SECURITY ) {
|
|
//
|
|
// Registry security
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szRegistryKeys,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
if ( Area & AREA_FILE_SECURITY ) {
|
|
//
|
|
// File Security
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szFileSecurity,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
|
|
#if 0
|
|
#if _WIN32_WINNT>=0x0500
|
|
if ( Area & AREA_DS_OBJECTS &&
|
|
RtlGetNtProductType(&theType) ) {
|
|
|
|
if ( theType == NtProductLanManNt ) {
|
|
//
|
|
// DS object security
|
|
//
|
|
rc = ScepOpenSectionForName(
|
|
Context,
|
|
SCE_ENGINE_SAP,
|
|
szDSSecurity,
|
|
&hSection
|
|
);
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
rc = SceJetGetLineCount(
|
|
hSection,
|
|
NULL,
|
|
FALSE,
|
|
&count
|
|
);
|
|
}
|
|
SceJetCloseSection( &hSection, TRUE);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
|
|
total += count;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
*pCount = total;
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepBrowseTableSection(
|
|
IN PSCECONTEXT hProfile,
|
|
IN SCETYPE ProfileType,
|
|
IN PCWSTR SectionName,
|
|
IN DWORD Options
|
|
)
|
|
{
|
|
SCESTATUS rc;
|
|
PSCESECTION hSection=NULL;
|
|
|
|
SceClientBrowseCallback(
|
|
0,
|
|
(PWSTR)SectionName,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
rc = ScepOpenSectionForName(
|
|
hProfile,
|
|
ProfileType,
|
|
SectionName,
|
|
&hSection
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
return(rc);
|
|
}
|
|
|
|
JET_ERR JetErr;
|
|
|
|
//
|
|
// goto the first line of this section
|
|
//
|
|
DWORD KeyLen, ValueLen, Actual;
|
|
LONG GpoID=0;
|
|
PWSTR KeyName=NULL;
|
|
PWSTR Value=NULL;
|
|
TCHAR GpoName[MAX_PATH];
|
|
|
|
SCE_BROWSE_CALLBACK_VALUE ValBuf;
|
|
ValBuf.Len = 0;
|
|
ValBuf.Value = NULL;
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_PREFIX_MATCH,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
|
|
while ( rc == SCESTATUS_SUCCESS ) {
|
|
|
|
//
|
|
// get GPO ID field from the current line
|
|
//
|
|
GpoID = 0;
|
|
|
|
if ( hSection->JetColumnGpoID > 0 ) {
|
|
|
|
JetErr = JetRetrieveColumn(
|
|
hSection->JetSessionID,
|
|
hSection->JetTableID,
|
|
hSection->JetColumnGpoID,
|
|
(void *)&GpoID,
|
|
4,
|
|
&Actual,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
|
|
if ( (Options & SCEBROWSE_DOMAIN_POLICY) &&
|
|
(GpoID <= 0) ) {
|
|
//
|
|
// do not need this line, continue to next line
|
|
//
|
|
} else {
|
|
|
|
KeyName = (PWSTR)ScepAlloc(LMEM_ZEROINIT, KeyLen+2);
|
|
|
|
//
|
|
// allocate memory for the group name and value string
|
|
//
|
|
Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
|
|
|
|
if ( KeyName == NULL || Value == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
|
|
}
|
|
|
|
//
|
|
// Get the key and value
|
|
//
|
|
DWORD NewKeyLen, NewValueLen;
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CURRENT,
|
|
NULL,
|
|
KeyName,
|
|
KeyLen,
|
|
&NewKeyLen,
|
|
Value,
|
|
ValueLen,
|
|
&NewValueLen
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// terminate the string
|
|
//
|
|
KeyName[KeyLen/2] = L'\0';
|
|
|
|
Value[ValueLen/2] = L'\0';
|
|
|
|
GpoName[0] = L'\0';
|
|
|
|
if ( hSection->JetColumnGpoID > 0 && GpoID > 0 ) {
|
|
|
|
Actual = MAX_PATH;
|
|
SceJetGetGpoNameByID(
|
|
hProfile,
|
|
GpoID,
|
|
GpoName,
|
|
&Actual,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if ( Value && Value[0] != L'\0' &&
|
|
( Options & SCEBROWSE_MULTI_SZ) ) {
|
|
|
|
if (0 == _wcsicmp( KeyName, szLegalNoticeTextKeyName) ) {
|
|
|
|
//
|
|
// check for commas and escape them with ","
|
|
// k=7,a",",b,c
|
|
// pValueStr will be a,\0b\0c\0\0 which we should make
|
|
// a","\0b\0c\0\0
|
|
//
|
|
|
|
DWORD dwCommaCount = 0;
|
|
|
|
for ( DWORD dwIndex = 1; dwIndex < ValueLen/2 ; dwIndex++) {
|
|
if ( Value[dwIndex] == L',' )
|
|
dwCommaCount++;
|
|
}
|
|
|
|
if ( dwCommaCount > 0 ) {
|
|
|
|
//
|
|
// in this case we have to escape commas
|
|
//
|
|
|
|
PWSTR pszValueEscaped;
|
|
DWORD dwBytes = (ValueLen/2 + 1 + (dwCommaCount*2))*sizeof(WCHAR);
|
|
|
|
pszValueEscaped = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwBytes);
|
|
|
|
if (pszValueEscaped) {
|
|
|
|
memset(pszValueEscaped, '\0', dwBytes);
|
|
ValueLen = 2 * ScepEscapeString(Value,
|
|
ValueLen/2,
|
|
L',',
|
|
L'"',
|
|
pszValueEscaped
|
|
);
|
|
|
|
ScepFree(Value);
|
|
|
|
Value = pszValueEscaped;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
ScepConvertMultiSzToDelim(Value+1, ValueLen/2-1, L'\0', L',');
|
|
|
|
}
|
|
|
|
__try {
|
|
|
|
ValBuf.Len = Value ? (ValueLen+2) : 0 ;
|
|
ValBuf.Value = (UCHAR *)Value;
|
|
|
|
SceClientBrowseCallback(
|
|
GpoID,
|
|
KeyName,
|
|
GpoName,
|
|
(SCEPR_SR_SECURITY_DESCRIPTOR *)&ValBuf
|
|
);
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
}
|
|
|
|
ScepFree(Value);
|
|
Value = NULL;
|
|
|
|
ScepFree(KeyName);
|
|
KeyName = NULL;
|
|
}
|
|
|
|
//
|
|
// read next line
|
|
//
|
|
|
|
rc = SceJetGetValue(
|
|
hSection,
|
|
SCEJET_NEXT_LINE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
&KeyLen,
|
|
NULL,
|
|
0,
|
|
&ValueLen
|
|
);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
Done:
|
|
|
|
//
|
|
// close the find index range
|
|
//
|
|
SceJetGetValue(
|
|
hSection,
|
|
SCEJET_CLOSE_VALUE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
|
|
if ( Value != NULL )
|
|
ScepFree(Value);
|
|
|
|
if ( KeyName != NULL )
|
|
ScepFree(KeyName);
|
|
|
|
//
|
|
// close the section
|
|
//
|
|
SceJetCloseSection( &hSection, TRUE );
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
BOOL
|
|
ScepSearchItemInChildren(
|
|
IN PWSTR ItemName,
|
|
IN DWORD NameLen,
|
|
IN PSCE_OBJECT_CHILDREN_NODE *pArrObject,
|
|
IN DWORD arrCount,
|
|
OUT LONG *pFindIndex
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Search the item name in the array specified. If found, the index to the
|
|
array is returned in pFindIndex.
|
|
|
|
Return Value:
|
|
|
|
TRUE - find it
|
|
FALSE - doesn't find it
|
|
*/
|
|
{
|
|
if ( pFindIndex == NULL ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// note pFindIndex stores the closest node, not necessary mean
|
|
// the index is the match.
|
|
//
|
|
*pFindIndex = -1;
|
|
|
|
if ( ItemName == NULL ||
|
|
pArrObject == NULL ||
|
|
arrCount == 0 ) {
|
|
return(FALSE);
|
|
}
|
|
|
|
DWORD idxStart=0;
|
|
DWORD idxEnd=arrCount-1;
|
|
|
|
DWORD theIndex;
|
|
INT CompFlag=-1;
|
|
|
|
do {
|
|
|
|
//
|
|
// choose the middle
|
|
//
|
|
theIndex = (idxStart + idxEnd)/2;
|
|
|
|
if ( pArrObject[theIndex] == NULL ||
|
|
pArrObject[theIndex]->Name == NULL ) {
|
|
//
|
|
// this is a bad node, check the start node
|
|
//
|
|
while ( (pArrObject[idxStart] == NULL ||
|
|
pArrObject[idxStart]->Name == NULL) &&
|
|
idxStart <= idxEnd ) {
|
|
|
|
idxStart++;
|
|
}
|
|
|
|
if ( idxStart <= idxEnd ) {
|
|
|
|
//
|
|
// check the start node
|
|
//
|
|
CompFlag = _wcsicmp(ItemName, pArrObject[idxStart]->Name);
|
|
*pFindIndex = idxStart;
|
|
|
|
if ( CompFlag == 0 ) {
|
|
// find it
|
|
break;
|
|
|
|
} else if ( CompFlag < 0 ) {
|
|
//
|
|
// the item is less than idxStart - no match
|
|
//
|
|
break;
|
|
|
|
} else {
|
|
//
|
|
// the item is between theStart and idxEnd
|
|
//
|
|
if ( idxStart == idxEnd ) {
|
|
// empty now. quit
|
|
break;
|
|
} else {
|
|
idxStart++;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
CompFlag = _wcsicmp(ItemName, pArrObject[theIndex]->Name);
|
|
*pFindIndex = theIndex;
|
|
|
|
if ( CompFlag == 0 ) {
|
|
// find it
|
|
break;
|
|
|
|
} else if ( CompFlag < 0 ) {
|
|
//
|
|
// the item is between index idxStart and theIndex
|
|
//
|
|
if ( theIndex == idxStart ) {
|
|
// empty now. quit
|
|
break;
|
|
} else {
|
|
idxEnd = theIndex-1;
|
|
}
|
|
} else {
|
|
//
|
|
// the item is between theIndex and idxEnd
|
|
//
|
|
if ( theIndex == idxEnd ) {
|
|
// empty now. quit
|
|
break;
|
|
} else {
|
|
idxStart = theIndex+1;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
} while ( idxStart <= idxEnd );
|
|
|
|
if ( CompFlag == 0 ) {
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepAddItemToChildren(
|
|
IN PSCE_OBJECT_CHILDREN_NODE ThisNode OPTIONAL,
|
|
IN PWSTR ItemName,
|
|
IN DWORD NameLen,
|
|
IN BOOL IsContainer,
|
|
IN BYTE Status,
|
|
IN DWORD ChildCount,
|
|
IN OUT PSCE_OBJECT_CHILDREN_NODE **ppArrObject,
|
|
IN OUT DWORD *pArrCount,
|
|
IN OUT DWORD *pMaxCount,
|
|
IN OUT LONG *pFindIndex
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Add a node to the children array. If the node is allocated, the pointer
|
|
will be added to the array; otherwise, a new allocation is made for the
|
|
new node.
|
|
|
|
The node's name will be first checked in the array for duplicate. If
|
|
pFindIndex is specified (not -1), the index will be first used to locate
|
|
the node. If the new node's name is found in the array, it won't be
|
|
added.
|
|
|
|
Return Value:
|
|
|
|
ERROR_DUP_NAME duplicate node name is found, node is not added to the array
|
|
ERROR_SUCCESS succeed
|
|
other errors
|
|
*/
|
|
{
|
|
|
|
if ( ItemName == NULL ||
|
|
ppArrObject == NULL ||
|
|
pArrCount == NULL ||
|
|
pMaxCount == NULL ||
|
|
pFindIndex == NULL ) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
DWORD rc=ERROR_SUCCESS;
|
|
|
|
if ( *ppArrObject == NULL ||
|
|
*pArrCount == 0 ) {
|
|
|
|
*pArrCount = 0;
|
|
*pMaxCount = 0;
|
|
*pFindIndex = -1;
|
|
|
|
} else if ( ( *pFindIndex < 0 ) ||
|
|
( *pFindIndex >= (LONG)(*pArrCount) ) ||
|
|
( (*ppArrObject)[*pFindIndex] == NULL ) ||
|
|
( (*ppArrObject)[*pFindIndex]->Name == NULL) ) {
|
|
|
|
//
|
|
// should search for the closest node
|
|
//
|
|
if ( ScepSearchItemInChildren(
|
|
ItemName,
|
|
NameLen,
|
|
*ppArrObject,
|
|
*pArrCount,
|
|
pFindIndex
|
|
) ) {
|
|
|
|
return(ERROR_DUP_NAME);
|
|
}
|
|
}
|
|
|
|
INT CompFlag=-1;
|
|
|
|
if ( *pFindIndex >= 0 ) {
|
|
|
|
//
|
|
// check if the closest node matches the new node
|
|
//
|
|
CompFlag = _wcsicmp( ItemName, (*ppArrObject)[*pFindIndex]->Name );
|
|
|
|
if ( CompFlag == 0 ) {
|
|
return(ERROR_DUP_NAME);
|
|
}
|
|
}
|
|
|
|
PSCE_OBJECT_CHILDREN_NODE pNodeToAdd;
|
|
|
|
if ( ThisNode == NULL ) {
|
|
//
|
|
// allocate a new node
|
|
//
|
|
pNodeToAdd = (PSCE_OBJECT_CHILDREN_NODE)ScepAlloc(0, sizeof(SCE_OBJECT_CHILDREN_NODE));
|
|
|
|
if ( NameLen == 0 ) {
|
|
NameLen = wcslen(ItemName);
|
|
}
|
|
|
|
if ( pNodeToAdd ) {
|
|
pNodeToAdd->Name = (PWSTR)ScepAlloc(0, (NameLen+1)*sizeof(WCHAR));
|
|
|
|
if ( pNodeToAdd->Name ) {
|
|
wcscpy(pNodeToAdd->Name, ItemName);
|
|
pNodeToAdd->IsContainer = IsContainer;
|
|
pNodeToAdd->Status = Status;
|
|
pNodeToAdd->Count = ChildCount;
|
|
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
ScepFree(pNodeToAdd);
|
|
pNodeToAdd = NULL;
|
|
}
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
|
|
pNodeToAdd = ThisNode;
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
LONG idxAdd, i;
|
|
|
|
if ( *pFindIndex >= 0 ) {
|
|
|
|
if ( CompFlag < 0 ) {
|
|
//
|
|
// add the new node before pFindIndex
|
|
//
|
|
idxAdd = *pFindIndex;
|
|
|
|
} else {
|
|
//
|
|
// add the new node after pFindIndex
|
|
//
|
|
idxAdd = *pFindIndex+1;
|
|
}
|
|
|
|
} else {
|
|
idxAdd = 0;
|
|
}
|
|
|
|
if ( *pArrCount >= *pMaxCount ) {
|
|
//
|
|
// there is not enough array nodes to hold the new node
|
|
//
|
|
PSCE_OBJECT_CHILDREN_NODE *pNewArray;
|
|
PBYTE pTmpBuffer;
|
|
|
|
pTmpBuffer = (PBYTE)ScepAlloc(0, 2*sizeof(DWORD)+(*pMaxCount+SCE_ALLOC_MAX_NODE)*sizeof(PSCE_OBJECT_CHILDREN_NODE));
|
|
|
|
if ( pTmpBuffer == NULL ) {
|
|
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
} else {
|
|
|
|
//
|
|
// need to shift two DWORDs for the array start
|
|
//
|
|
pNewArray = (PSCE_OBJECT_CHILDREN_NODE *)(pTmpBuffer + 2*sizeof(DWORD));
|
|
|
|
LONG idxStart1, idxEnd1, idxStart2, idxEnd2;
|
|
|
|
if ( *pFindIndex >= 0 ) {
|
|
|
|
if ( CompFlag < 0 ) {
|
|
//
|
|
// add the new node before pFindIndex
|
|
//
|
|
idxEnd1 = *pFindIndex-1;
|
|
idxStart2 = *pFindIndex;
|
|
|
|
} else {
|
|
//
|
|
// add the new node after pFindIndex
|
|
//
|
|
|
|
idxEnd1 = *pFindIndex;
|
|
idxStart2 = *pFindIndex+1;
|
|
}
|
|
|
|
idxStart1 = 0;
|
|
idxEnd2 = *pArrCount-1;
|
|
|
|
} else {
|
|
idxStart1 = -1;
|
|
idxEnd1 = -1;
|
|
idxStart2 = 0;
|
|
idxEnd2 = *pArrCount-1;
|
|
}
|
|
|
|
//
|
|
// make the copy
|
|
//
|
|
LONG j=0;
|
|
for ( i=idxStart1; i<=idxEnd1 && i>=0; i++ ) {
|
|
pNewArray[j++] = (*ppArrObject)[i];
|
|
}
|
|
|
|
pNewArray[idxAdd] = pNodeToAdd;
|
|
j = idxAdd+1;
|
|
|
|
for ( i=idxStart2; i<=idxEnd2 && i>=0; i++ ) {
|
|
pNewArray[j++] = (*ppArrObject)[i];
|
|
}
|
|
|
|
(*pMaxCount) += SCE_ALLOC_MAX_NODE;
|
|
(*pArrCount)++;
|
|
|
|
//
|
|
// free the old list
|
|
//
|
|
if ( *ppArrObject ) {
|
|
ScepFree((PBYTE)(*ppArrObject)-2*sizeof(DWORD));
|
|
}
|
|
*ppArrObject = pNewArray;
|
|
|
|
*pFindIndex = idxAdd;
|
|
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// the buffer is big enough, just add the node to the buffer
|
|
//
|
|
|
|
//
|
|
// make the copy
|
|
//
|
|
for ( i=*pArrCount-1; i>=idxAdd && i>=0; i-- ) {
|
|
(*ppArrObject)[i+1] = (*ppArrObject)[i];
|
|
}
|
|
|
|
(*ppArrObject)[idxAdd] = pNodeToAdd;
|
|
|
|
(*pArrCount)++;
|
|
|
|
*pFindIndex = idxAdd;
|
|
}
|
|
}
|
|
|
|
//
|
|
// release memory if it fails
|
|
//
|
|
if ( ERROR_SUCCESS != rc &&
|
|
pNodeToAdd &&
|
|
pNodeToAdd != ThisNode ) {
|
|
|
|
ScepFree(pNodeToAdd->Name);
|
|
ScepFree(pNodeToAdd);
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|