Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3222 lines
95 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
inftojet.c
Abstract:
Routines to convert security profiles in INF format to JET format.
Author:
Jin Huang (jinhuang) 23-Jan-1997
Revision History:
--*/
#include "serverp.h"
#include "infp.h"
#include "pfp.h"
#include "regvalue.h"
#pragma hdrstop
//#define SCE_DBG 1
#define SCE_PRIV_ADD TEXT("Add:")
#define SCE_PRIV_REMOVE TEXT("Remove:")
#define SCE_REG_ADD SCE_PRIV_ADD
#define SCE_REG_REMOVE SCE_PRIV_REMOVE
#define SCE_REG_ADD_REMOVE_VALUE 8
#define SCE_OBJECT_FLAG_OBJECTS 1
#define SCE_OBJECT_FLAG_OLDSDDL 2
#define SCE_OBJECT_FLAG_UNKNOWN_VERSION 4
//
// Forward references
//
SCEINF_STATUS
SceInfpGetOneObject(
IN PINFCONTEXT pInfLine,
IN DWORD ObjectFlag,
OUT PWSTR *Name,
OUT PWSTR *Value,
OUT PDWORD ValueLen
);
#define SCE_CONVERT_INF_MULTISZ 0x01
#define SCE_CONVERT_INF_PRIV 0x02
#define SCE_CONVERT_INF_GROUP 0x04
#define SCE_CONVERT_INF_NEWVERSION 0x08
#define SCE_CONVERT_INF_REGVALUE 0x10
SCESTATUS
SceConvertpInfKeyValue(
IN PCWSTR InfSectionName,
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN DWORD dwConvertOption,
IN LONG GpoID,
IN OPTIONAL PCWSTR pcwszKey,
OUT PSCE_NAME_LIST *pKeyList
);
SCESTATUS
SceConvertpInfObject(
IN PCWSTR InfSectionName,
IN UINT ObjectType,
IN DWORD ObjectFlag,
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID
);
SCESTATUS
SceConvertpInfDescription(
IN HINF hInf,
IN PSCECONTEXT hProfile
);
SCESTATUS
SceConvertpAttachmentSections(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID,
IN SCE_ATTACHMENT_TYPE aType
);
SCESTATUS
SceConvertpWMIAttachmentSections(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID
);
SCESTATUS
SceConvertpOneAttachmentSection(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN PWSTR SectionName,
IN DWORD dwTableOption,
IN LONG GpoID
);
SCESTATUS
ScepBuildNewPrivilegeList(
IN LSA_HANDLE *pPolicyHandle,
IN PWSTR PrivName,
IN PWSTR mszUsers,
IN ULONG dwBuildOption,
OUT PWSTR *pmszNewUsers,
OUT DWORD *pNewLen
);
SCESTATUS
ScepAddToPrivilegeList(
OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
IN PWSTR Name,
IN DWORD Len,
IN DWORD PrivValue
);
SCESTATUS
ScepBuildNewMultiSzRegValue(
IN PWSTR pszKeyName,
IN PWSTR pszStrValue,
IN DWORD dwValueLen,
OUT PWSTR* ppszNewValue,
OUT PDWORD pdwNewLen
);
SCESTATUS
ScepBuildRegMultiSzValue(
IN PWSTR pszKeyName,
IN PWSTR pszAddList OPTIONAL,
IN DWORD dwAddLen,
IN PWSTR pszRemoveList OPTIONAL,
IN DWORD dwRemoveLen,
IN PWSTR pszPrefix,
OUT PWSTR* ppszNewValue,
OUT PDWORD pdwNewValueLen
);
//
// Function definitions
//
SCESTATUS
SceJetConvertInfToJet(
IN PCWSTR InfFile,
IN LPSTR JetDbName,
IN SCEJET_CREATE_TYPE Flags,
IN DWORD Options,
IN AREA_INFORMATION Area
)
/**++
Function Description:
This function converts a SCP profile in INF format to a Jet database format
for the area provided. The SCP profile information is converted into the
local policy table (SMP) in the Jet database.
If the Jet database already exists, Flags is used to decide either overwrite,
reuse, or just error out. All possible errors occur inside the routine are
saved in the optional Errlog if Errlog is not NULL
Arguments:
InfFile - The Inf file name to convert from
JetDbName - the SCP profile in Jet format to convert into
Flags - Used when there is a duplicated Jet database
SCEJET_OVERWRITE
SCEJET_OPEN
0
Options - the conversion options
Area - the area to convert
Return Value:
-- **/
{
PSCECONTEXT hProfile=NULL;
SCESTATUS rc;
PSCE_NAME_LIST pProfileList=NULL,
pProfile=NULL;
DWORD Count;
PSECURITY_DESCRIPTOR pSD=NULL;
SECURITY_INFORMATION SeInfo;
HINF hInf=NULL;
RPC_STATUS RpcStatus=RPC_S_OK;
INT Revision = 0;
DWORD ObjectFlag=0;
INFCONTEXT InfLine;
DWORD dwConvertOption=0;
if ( InfFile == NULL ||
JetDbName == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
//
// open the inf profile
//
rc = SceInfpOpenProfile(
InfFile,
&hInf
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_OPEN,
(PWSTR)InfFile);
return(rc);
}
LONG GpoID=0;
//
// create/open the Jet database
//
DWORD dwNewOption = 0;
// MREGE_POLICY option allows opening the temp merge policy table to build new policy
// TATTOO option allows creating/opening the tattoo table into SAP context
if ( Options & SCE_POLICY_TEMPLATE )
dwNewOption |= SCE_TABLE_OPTION_MERGE_POLICY | SCE_TABLE_OPTION_TATTOO;
// this check handles setup case (to create/open tattoo table)
else {
if ( (Options & SCE_SYSTEM_DB) )
dwNewOption |= SCE_TABLE_OPTION_TATTOO;
// dc demote should reset account policy and user rights at reboot (from tattoo table)
if ( Options & SCE_DC_DEMOTE )
dwNewOption |= SCE_TABLE_OPTION_DEMOTE_TATTOO;
}
rc = SceJetCreateFile(JetDbName,
Flags,
dwNewOption,
&hProfile);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CREATE, L"database");
goto CleanUp;
}
if ( Options & SCE_SYSTEM_DB ) {
//
// set Admin F, CO F to the database (protected)
//
rc = ConvertTextSecurityDescriptor (
L"D:P(A;;GA;;;CO)(A;;GA;;;BA)(A;;GA;;;SY)",
&pSD,
&Count, // temp var for SDsize
&SeInfo
);
if ( rc == NO_ERROR ) {
ScepChangeAclRevision(pSD, ACL_REVISION);
//
// use current token as the owner (because this database is
// to be created
//
HANDLE Token=NULL;
if (!OpenThreadToken( GetCurrentThread(),
TOKEN_QUERY,
TRUE,
&Token)) {
if(ERROR_NO_TOKEN == GetLastError()){
if(!OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY,
&Token)) {
ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
}
} else {
ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
}
}
if ( Token ) {
PSECURITY_DESCRIPTOR pNewSD=NULL;
//
// RtlNewSecurityObjectEx must be called on the process context (system)
// because it will try to get process information inside the api.
//
RpcRevertToSelf();
rc = RtlNtStatusToDosError(
RtlNewSecurityObjectEx(
NULL,
pSD,
&pNewSD,
NULL, // GUID
FALSE,
SEF_DACL_AUTO_INHERIT |
SEF_AVOID_OWNER_CHECK |
SEF_AVOID_PRIVILEGE_CHECK,
Token,
&FileGenericMapping
));
RpcStatus = RpcImpersonateClient( NULL );
if ( RpcStatus == RPC_S_OK ) {
if ( rc == NO_ERROR ) {
if ( !SetFileSecurityA (
JetDbName,
SeInfo,
pNewSD
) ) {
rc = GetLastError();
ScepLogOutput3(1, rc,
SCEDLL_ERROR_SET_SECURITY, L"database");
}
ScepFree(pNewSD);
} else {
ScepLogOutput3(1, rc,
SCEDLL_ERROR_BUILD_SD, L"database");
}
} else {
if ( rc == NO_ERROR ) {
ScepFree(pNewSD);
}
ScepLogOutput3(1, I_RpcMapWin32Status(RpcStatus),
SCEDLL_ERROR_BUILD_SD, L"database");
}
CloseHandle(Token);
}
ScepFree(pSD);
} else
ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, L"database");
}
if ( RpcStatus != RPC_S_OK ) {
goto CleanUp;
}
if ( !(Options & SCE_POLICY_TEMPLATE) ) {
//
// if not in the middle of policy propagation, use Jet transaction
// otherwise, use the temp table concept.
//
SceJetStartTransaction( hProfile );
//
//If it is in demote or snapshot mode delete local policy.
//
if ( (Options & SCE_DC_DEMOTE) &&
(Options & SCE_SYSTEM_DB) ) {
ScepDeleteInfoForAreas(
hProfile,
SCE_ENGINE_SMP,
AREA_ALL
);
ScepDeleteInfoForAreas(
hProfile,
SCE_ENGINE_SAP, // tattoo
AREA_ALL
);
} else if ( Options & SCE_GENERATE_ROLLBACK ) {
ScepDeleteInfoForAreas(
hProfile,
SCE_ENGINE_SMP,
AREA_ALL
);
}
} else if ( Options & SCE_POLICY_FIRST ) {
//
// The ENGINE_SCP table points to the new merge table
// instead of the existing one.
//
// delete everything in SCP then
// copy Tattoo to SCP
//
rc = ScepDeleteInfoForAreas(
hProfile,
SCE_ENGINE_SCP,
AREA_ALL
);
if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_DELETE, L"SCP");
goto CleanUp;
}
//
// delete GPO table to start over
//
SceJetDeleteAll( hProfile,
"SmTblGpo",
SCEJET_TABLE_GPO
);
PSCE_ERROR_LOG_INFO Errlog=NULL;
ScepLogOutput3(2, rc, SCEDLL_COPY_LOCAL);
// copy from tattoo table to effective policy table
rc = ScepCopyLocalToMergeTable( hProfile,
Options,
(ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0,
&Errlog );
ScepLogWriteError( Errlog,1 );
ScepFreeErrorLog( Errlog );
Errlog = NULL;
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_COPY);
goto CleanUp;
}
//
// now, migrate database if tattoo table doesn't exist (in existing database)
// this could happen if someone manually copied a database to the system
// database location, or if the database failed to be migrated in setup
//
if ( hProfile->JetSapID == JET_tableidNil ) {
SceJetCreateTable(
hProfile,
"SmTblTattoo",
SCEJET_TABLE_TATTOO,
SCEJET_CREATE_IN_BUFFER,
NULL,
NULL
);
}
}
TCHAR szGpoName[MAX_PATH];
szGpoName[0] = L'\0';
szGpoName[1] = L'\0';
szGpoName[2] = L'\0';
if ( Options & SCE_POLICY_TEMPLATE ) {
//
// get the GPO path and GPOID
//
GetPrivateProfileString(TEXT("Version"),
TEXT("GPOPath"),
TEXT(""),
szGpoName,
MAX_PATH,
InfFile
);
if ( szGpoName[0] != L'\0' ) {
PWSTR pTemp = wcschr(szGpoName, L'\\');
if ( pTemp ) {
*pTemp = L'\0';
}
GpoID = SceJetGetGpoIDByName(hProfile,
szGpoName,
TRUE // add if it's not there
);
//
// if GpoID is -1, an error occurred
//
if ( GpoID < 0 ) {
rc = GetLastError();
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3( 1, ScepDosErrorToSceStatus(rc),
SCEDLL_ERROR_CONVERT, (PWSTR)szGpoName);
goto CleanUp;
}
}
}
}
//
// query the version # to determine if the SDDL string should be migrated
//
if ( SetupFindFirstLine(hInf,L"Version",L"Revision",&InfLine) ) {
if ( !SetupGetIntField(&InfLine, 1, (INT *)&Revision) ) {
Revision = 0;
}
}
if ( Revision == 0 ) ObjectFlag = SCE_OBJECT_FLAG_OLDSDDL;
if ( Revision > SCE_TEMPLATE_MAX_SUPPORTED_VERSION ) {
dwConvertOption = SCE_CONVERT_INF_NEWVERSION;
ObjectFlag |= SCE_OBJECT_FLAG_UNKNOWN_VERSION;
}
//
// process each area
//
if ( Area & AREA_SECURITY_POLICY ) {
if ( !( Options & SCE_NO_DOMAIN_POLICY) ) {
// System Access section
rc = SceConvertpInfKeyValue(
szSystemAccess,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szSystemAccess);
goto CleanUp;
}
}
rc = SceConvertpInfKeyValue(
szSystemAccess,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
L"LSAAnonymousNameLookup",
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, L"LSAAnonymousNameLookup");
goto CleanUp;
}
//
// configure event log settings in setup too
// since local policy table is not used in policy prop anymore
//
// if ( !(Options & SCE_SYSTEM_DB) ||
// (Options & SCE_POLICY_TEMPLATE) ) {
// System Log section
rc = SceConvertpInfKeyValue(
szAuditSystemLog,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSystemLog);
goto CleanUp;
}
// Security Log section
rc = SceConvertpInfKeyValue(
szAuditSecurityLog,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSecurityLog);
goto CleanUp;
}
// Application Log section
rc = SceConvertpInfKeyValue(
szAuditApplicationLog,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditApplicationLog);
goto CleanUp;
}
// }
// Audit Event section
rc = SceConvertpInfKeyValue(
szAuditEvent,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditEvent);
goto CleanUp;
}
if ( !( Options & SCE_NO_DOMAIN_POLICY) &&
(ProductType == NtProductLanManNt) &&
!( Options & SCE_DC_DEMOTE) ) {
// Kerberos section
rc = SceConvertpInfKeyValue(
szKerberosPolicy,
hInf,
hProfile,
dwNewOption,
dwConvertOption,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szKerberosPolicy);
goto CleanUp;
}
}
// registry values
rc = SceConvertpInfKeyValue(
szRegistryValues,
hInf,
hProfile,
dwNewOption,
dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_REGVALUE,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryValues);
goto CleanUp;
}
rc = SceConvertpAttachmentSections(hInf,
hProfile,
(Options & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
GpoID,
SCE_ATTACHMENT_POLICY);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_SAP_ERROR_ENUMERATE, L"policy attachments.");
goto CleanUp;
}
}
if ( Area & AREA_REGISTRY_SECURITY ) {
//
// Object type - Registry
//
rc = SceConvertpInfObject(
szRegistryKeys,
1,
ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
hInf,
hProfile,
dwNewOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryKeys);
goto CleanUp;
}
}
if ( Area & AREA_FILE_SECURITY ) {
// File security
rc = SceConvertpInfObject(
szFileSecurity,
2,
ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
hInf,
hProfile,
dwNewOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szFileSecurity);
goto CleanUp;
}
}
#if 0
//
// DS object security
//
rc = SceConvertpInfObject(
szDSSecurity,
3,
ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
hInf,
hProfile,
dwNewOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szDSSecurity);
goto CleanUp;
}
#endif
if ( Area & AREA_SYSTEM_SERVICE ) {
//
// Service General Settings
//
rc = SceConvertpInfObject(
szServiceGeneral,
0,
ObjectFlag,
hInf,
hProfile,
dwNewOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szServiceGeneral);
goto CleanUp;
}
//
// each service's specific settings
//
rc = SceConvertpAttachmentSections(hInf,
hProfile,
dwNewOption,
GpoID,
SCE_ATTACHMENT_SERVICE);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_SAP_ERROR_ENUMERATE, L"service attachments.");
goto CleanUp;
}
}
if ( (Area & AREA_ATTACHMENTS) ) {
//
// each service's specific settings
//
rc = SceConvertpWMIAttachmentSections(hInf,
hProfile,
dwNewOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
goto CleanUp;
}
}
if ( Area & AREA_PRIVILEGES ) {
//
// Multi-Sz type - privilege/rights
//
rc = SceConvertpInfKeyValue(
szPrivilegeRights,
hInf,
hProfile,
dwNewOption,
dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_PRIV,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szPrivilegeRights);
goto CleanUp;
}
}
if ( Area & AREA_GROUP_MEMBERSHIP ) {
// group membership
rc = SceConvertpInfKeyValue(
szGroupMembership,
hInf,
hProfile,
dwNewOption,
dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_GROUP,
GpoID,
NULL,
NULL
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szGroupMembership);
goto CleanUp;
}
}
//
// if there is a description, convert it.
//
SceConvertpInfDescription(
hInf,
hProfile);
if ( !(Options & SCE_POLICY_TEMPLATE) ) {
//
// Commit changes
//
SceJetCommitTransaction( hProfile, 0 );
} else if ( Options & SCE_POLICY_LAST ) {
//
// update the LastUsedMergeTable field
//
DWORD dwThisTable = hProfile->Type & 0xF0L;
if ( SCEJET_MERGE_TABLE_1 == dwThisTable ||
SCEJET_MERGE_TABLE_2 == dwThisTable ) {
rc = SceJetSetValueInVersion(
hProfile,
"SmTblVersion",
"LastUsedMergeTable",
(PWSTR)&dwThisTable,
4,
JET_prepReplace
);
}
}
CleanUp:
//
// close the inf profile
//
SceInfpCloseProfile(hInf);
if ( pProfileList != NULL ) {
ScepFreeNameList(pProfileList);
}
//
// Rollback
//
if ( !(Options & SCE_POLICY_TEMPLATE) &&
(RpcStatus == RPC_S_OK) &&
(rc != SCESTATUS_SUCCESS) ) {
SceJetRollback( hProfile, 0 );
}
//
// Close the JET database
//
SceJetCloseFile( hProfile, TRUE, FALSE );
if ( RpcStatus != RPC_S_OK ) {
rc = I_RpcMapWin32Status(RpcStatus);
}
return(rc);
}
SCESTATUS
SceConvertpAttachmentSections(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID,
IN SCE_ATTACHMENT_TYPE aType
)
{
SCESTATUS rc;
PSCE_SERVICES pServiceList=NULL, pNode;
rc = ScepEnumServiceEngines( &pServiceList, aType );
if ( rc == SCESTATUS_SUCCESS ) {
for ( pNode=pServiceList; pNode != NULL; pNode=pNode->Next) {
rc = SceConvertpOneAttachmentSection(hInf,
hProfile,
pNode->ServiceName,
dwTableOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, pNode->ServiceName );
break;
}
}
SceFreePSCE_SERVICES(pServiceList);
} else if ( rc == SCESTATUS_PROFILE_NOT_FOUND ||
rc == SCESTATUS_RECORD_NOT_FOUND ) {
// if no service exist, just ignore
rc = SCESTATUS_SUCCESS;
}
return(rc);
}
SCESTATUS
SceConvertpWMIAttachmentSections(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID
)
{
SCESTATUS rc=SCESTATUS_SUCCESS;
INFCONTEXT InfLine;
WCHAR SectionName[513];
DWORD DataSize=0;
if ( SetupFindFirstLine(hInf, szAttachments,NULL,&InfLine) ) {
do {
memset(SectionName, '\0', 513*sizeof(WCHAR));
// get each attachment section name
if(SetupGetStringField(&InfLine, 0, SectionName, 512, &DataSize) ) {
rc = SceConvertpOneAttachmentSection(hInf,
hProfile,
SectionName,
dwTableOption,
GpoID
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT_SECTION, SectionName );
break;
}
} else {
rc = ScepDosErrorToSceStatus(GetLastError());
}
} while ( rc == SCESTATUS_SUCCESS &&
SetupFindNextLine(&InfLine, &InfLine));
}
return(rc);
}
SCESTATUS
SceConvertpOneAttachmentSection(
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN PWSTR SectionName,
IN DWORD dwTableOption,
IN LONG GpoID
)
{
SCESTATUS rc;
PSCESVC_CONFIGURATION_INFO pServiceInfo=NULL;
//
// read inf info for the service
//
rc = SceSvcpGetInformationTemplate(
hInf,
SectionName,
NULL, // not a single key
&pServiceInfo
);
if ( rc == SCESTATUS_SUCCESS && pServiceInfo != NULL ) {
//
// write the information to SCP or SMP table
//
if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
rc = SceSvcpSetInfo(
hProfile,
SceSvcInternalUse,
SectionName,
NULL,
TRUE, // to support incremental template, DO NOT overwrite the whole section
GpoID,
pServiceInfo
);
} else {
rc = SceSvcpSetInfo(
hProfile,
SceSvcConfigurationInfo,
SectionName,
NULL,
TRUE, // to support incremental template, DO NOT overwrite the whole section
0,
pServiceInfo
);
}
//
// free buffer
//
SceSvcpFreeMemory(pServiceInfo);
pServiceInfo = NULL;
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
rc = SCESTATUS_SUCCESS;
}
return(rc);
}
SCESTATUS
SceConvertpInfKeyValue(
IN PCWSTR InfSectionName,
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN DWORD dwConvertOption,
IN LONG GpoID,
IN OPTIONAL PCWSTR pcwszKey,
OUT PSCE_NAME_LIST *pKeyList OPTIONAL
)
/* ++
Routine Description:
This routine converts INF sections which are in a key=value format. Value
could be in MultiSz format (dwConvertOption & SCE_CONVERT_INF_MULTISZ).
The optional pKeyList is a list of all keys in the section. This option
is used when dynamic sections are converted.
Arguments:
InfSectionName - the INF section name to convert
hInf - the Inf file handle
hprofile - the Jet database context
dwTableOption - SCE_TABLE_OPTION_MERGE_POLICY = within policy propagation
SCE_TABLE_OPTION_TATTOO - system db (in setup)
dwConvertOption - SCE_CONVERT_INF_MULTISZ - MultiSz type value
SCE_CONVERT_INF_PRIV - user right section
SCE_CONVERT_INF_GROUP - group membership section
GpoID - the group policy ID for this item
pKeyList - a list of all keys in the section.
Return Value:
-- */
{
SCESTATUS rc;
DOUBLE SectionID;
PSCESECTION hSection=NULL;
PSCESECTION hSectionTattoo=NULL;
INFCONTEXT InfLine;
WCHAR Keyname[SCE_KEY_MAX_LENGTH];
PWSTR pSidStr=NULL;
PWSTR pKeyStr=NULL;
PWSTR StrValue=NULL;
DWORD ValueLen=0;
LSA_HANDLE LsaPolicy=NULL;
DWORD Len=0;
if ( InfSectionName == NULL ||
hInf == INVALID_HANDLE_VALUE ||
hProfile == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
//
// get section's ID. if the section does not exist, add it to the section table
//
rc = SceJetGetSectionIDByName(
hProfile,
InfSectionName,
&SectionID
);
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
rc = SceJetAddSection(
hProfile,
InfSectionName,
&SectionID
);
}
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_QUERY_INFO, (PWSTR)InfSectionName );
return(rc);
}
if ( SetupFindFirstLine(hInf,InfSectionName,pcwszKey,&InfLine) ) {
if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
//
// open the SCP section
//
rc = SceJetOpenSection(
hProfile,
SectionID,
SCEJET_TABLE_SCP,
&hSection
);
} else {
//
// open SMP table
//
rc = SceJetOpenSection(
hProfile,
SectionID,
SCEJET_TABLE_SMP,
&hSection
);
//
// open the tattoo (in order to update tattoo value in setup)
// do not care error
//
if ( dwTableOption & SCE_TABLE_OPTION_TATTOO )
SceJetOpenSection(hProfile, SectionID,
SCEJET_TABLE_TATTOO,
&hSectionTattoo);
}
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
if (hSection != NULL )
SceJetCloseSection( &hSection, TRUE);
if (hSectionTattoo != NULL )
SceJetCloseSection( &hSectionTattoo, TRUE);
return(rc);
}
//
// Open LSA policy handle for group name lookup, if any
// if policy handle can't be opened, import name format
//
if ( dwConvertOption & SCE_CONVERT_INF_GROUP ) {
ScepOpenLsaPolicy(
MAXIMUM_ALLOWED,
&LsaPolicy,
TRUE
);
}
//
// process each line in the section and save to the scp table.
// Each INF line has a key and a value.
//
do {
memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(TCHAR));
rc = SCESTATUS_BAD_FORMAT;
if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
//
// check if newer version (keys) are passed
//
if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
if ( dwConvertOption & SCE_CONVERT_INF_PRIV ) {
//
// user rights from new version
// filter out all unknown rights
//
if ( -1 == ScepLookupPrivByName(Keyname) ) {
rc = SCESTATUS_SUCCESS;
goto NextLine;
}
} else if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
//
// convert registry values, should check number of fields
//
if ( SetupGetFieldCount( &InfLine ) < 2 ) {
rc = SCESTATUS_SUCCESS;
goto NextLine;
}
}
}
if ( (dwConvertOption & SCE_CONVERT_INF_GROUP) &&
( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ||
(Keyname[0] != L'*') ) ) {
//
// this is a group in name format
//
PWSTR pTemp = (PWSTR)Keyname;
//
// search for the suffix (szMembers or szMemberof or szPrivileges)
//
while ( pTemp = wcsstr(pTemp, szMembers) ) {
if ( *(pTemp+wcslen(szMembers)) != L'\0') {
pTemp++;
ValueLen = 0;
} else {
break;
}
}
if ( pTemp == NULL ) {
pTemp = (PWSTR)Keyname;
while ( pTemp = wcsstr(pTemp, szMemberof) ) {
if ( *(pTemp+wcslen(szMemberof)) != L'\0') {
pTemp++;
ValueLen = 1;
} else {
break;
}
}
if ( pTemp == NULL ) {
pTemp = (PWSTR)Keyname;
while ( pTemp = wcsstr(pTemp, szPrivileges) ) {
if ( *(pTemp+wcslen(szPrivileges)) != L'\0') {
pTemp++;
ValueLen = 2;
} else {
break;
}
}
}
}
if ( pTemp == NULL ) {
//
// this is an unknown group format, just import the keyname
// for supported version; for new version template, ignore
// this line
//
if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
rc = SCESTATUS_SUCCESS;
goto NextLine;
}
} else if ( Keyname[0] != L'*' ) {
*pTemp = L'\0';
Len=0;
if ( LsaPolicy ) {
//
// convert group name (domain\account) into *SID format
//
ScepConvertNameToSidString(
LsaPolicy,
Keyname,
FALSE,
&pSidStr,
&Len
);
} else {
if ( ScepLookupWellKnownName(
Keyname,
NULL,
&pSidStr ) ) {
Len = wcslen(pSidStr);
}
}
//
// restore the "_"
//
*pTemp = L'_';
if ( pSidStr ) {
//
// add the suffix
//
pKeyStr = (PWSTR)ScepAlloc(0, (Len+wcslen(pTemp)+1)*sizeof(WCHAR));
if ( pKeyStr ) {
wcscpy(pKeyStr, pSidStr);
wcscat(pKeyStr, pTemp);
} else {
//
// use the name instead - out of memory will be caught later
//
}
ScepFree(pSidStr);
pSidStr = NULL;
}
}
}
if ( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
SetupGetMultiSzField(&InfLine, 1, NULL, 0, &ValueLen)) ||
(!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
SetupGetStringField(&InfLine, 1, NULL, 0, &ValueLen)) ) {
if ( ValueLen > 1 ) {
StrValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
(ValueLen+1)*sizeof(TCHAR));
if( StrValue == NULL ) {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
} else if( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
SetupGetMultiSzField(&InfLine, 1, StrValue, ValueLen, NULL)) ||
(!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
SetupGetStringField(&InfLine,1,StrValue,ValueLen,NULL)) ) {
//
// if dealing with registry values only, do the following:
// compress regtype into one CHAR instead of many WCHARS
// (can canonicalize REG_QWORD value later by arithmetic padding etc.- doesn't
// make sense now since registry api's treat REG_QWORD as a string anyway)
// Also, resolve the Add/Remove format
//
rc = SCESTATUS_SUCCESS;
if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
DWORD LenStrValue = wcslen(StrValue);
PWSTR NewRegValue = NULL;
DWORD NewValueLen = 0;
if (LenStrValue > 1) {
*((CHAR *)StrValue) = (CHAR) (_wtol(StrValue) + '0');
memmove( StrValue+1,
StrValue + LenStrValue,
sizeof(WCHAR) * (ValueLen - LenStrValue));
ValueLen -= (LenStrValue - 1);
}
//
// if the reg value is of the type add/remove format in the template,
// then we need to resolve the add/remove instructions to generate
// the exact value to save in the DB
//
if(SCE_REG_ADD_REMOVE_VALUE == *((CHAR *)StrValue) - '0'){
rc = ScepBuildNewMultiSzRegValue(Keyname,
StrValue,
ValueLen,
&NewRegValue,
&NewValueLen
);
if(SCESTATUS_SUCCESS == rc){
ScepFree(StrValue);
StrValue = NewRegValue;
ValueLen = NewValueLen;
//
// if we have no buffer to set, then just go
// to the next line
// This happens only if the reg key/value does not
// exist on the system and we don't have an
// "add" instruction in the inf line
//
if(!StrValue || 0 == NewValueLen){
goto NextLine;
}
//
// now change the reg value type to multisz since
// the add/remove is now resolved.
//
*((CHAR *)StrValue) = (CHAR) (REG_MULTI_SZ + '0');
}
else{
ScepFree(StrValue);
StrValue = NULL;
}
}
}
} else {
ScepFree(StrValue);
StrValue = NULL;
}
} else {
rc = SCESTATUS_SUCCESS;
ValueLen = 0;
}
PWSTR NewValue=NULL;
DWORD NewLen=0;
if ( rc == SCESTATUS_SUCCESS ) {
if ( (dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
StrValue != NULL &&
(dwConvertOption & SCE_CONVERT_INF_PRIV) &&
( _wcsicmp(SCE_PRIV_ADD, StrValue) == 0 ||
_wcsicmp(SCE_PRIV_REMOVE, StrValue) == 0) ) {
//
// another format for user rights (ADD: REMOVE:...)
//
rc = ScepBuildNewPrivilegeList(&LsaPolicy,
Keyname,
StrValue,
SCE_BUILD_ENUMERATE_PRIV,
&NewValue,
&NewLen);
if ( rc == SCESTATUS_SUCCESS ) {
ScepFree(StrValue);
StrValue = NewValue;
ValueLen = NewLen;
}
}
}
if ( ( rc == SCESTATUS_SUCCESS) &&
!(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
StrValue &&
( (dwConvertOption & SCE_CONVERT_INF_PRIV) ||
(dwConvertOption & SCE_CONVERT_INF_GROUP)) ) {
//
// convert any free text format accounts from account domain
// to sid format if it's resolvable.
//
NewValue = NULL;
NewLen = 0;
rc = ScepConvertFreeTextAccountToSid(&LsaPolicy,
StrValue,
ValueLen,
&NewValue,
&NewLen);
if ( ( rc == SCESTATUS_SUCCESS) &&
NewValue ) {
ScepFree(StrValue);
StrValue = NewValue;
ValueLen = NewLen;
}
}
if ( rc == SCESTATUS_SUCCESS ) {
//
// write this line to JET database
// within policy propagation, write the GPOID too
//
rc = SceJetSetLine(
hSection,
pKeyStr ? pKeyStr : Keyname,
FALSE,
StrValue,
ValueLen*sizeof(TCHAR),
(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
);
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_WRITE_INFO, Keyname);
}
//
// if this is not policy propagation and it's the system db,
// check if the tattoo value exists and if so, update it
// but if this is in dc demotion, always import them into the
// tattoo table so at reboot when policy propagates, it would
// reset the system settings to a standalone server
//
if ( !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
(dwTableOption & SCE_TABLE_OPTION_TATTOO) &&
hSectionTattoo ) {
if ( pKeyStr )
Len = wcslen(pKeyStr);
else
Len = wcslen(Keyname);
if ( (dwTableOption & SCE_TABLE_OPTION_DEMOTE_TATTOO) ||
(SCESTATUS_SUCCESS == SceJetSeek(
hSectionTattoo,
pKeyStr ? pKeyStr : Keyname,
Len*sizeof(WCHAR),
SCEJET_SEEK_EQ_NO_CASE)) ) {
SceJetSetLine(
hSectionTattoo,
pKeyStr ? pKeyStr : Keyname,
FALSE,
StrValue,
ValueLen*sizeof(TCHAR),
0
);
}
}
ScepFree(StrValue);
StrValue = NULL;
if (pKeyList != NULL) {
if ( (rc=ScepAddToNameList(pKeyList, Keyname,0)) != NO_ERROR ) {
ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_ADD, Keyname);
rc = ScepDosErrorToSceStatus(rc);
ScepFreeNameList(*pKeyList);
}
}
}
}
if ( pKeyStr ) {
ScepFree(pKeyStr);
pKeyStr = NULL;
}
NextLine:
if (rc != SCESTATUS_SUCCESS)
ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT, Keyname);
}
} while( rc == SCESTATUS_SUCCESS && SetupFindNextLine(&InfLine, &InfLine));
SceJetCloseSection( &hSection, TRUE);
if ( hSectionTattoo )
SceJetCloseSection( &hSectionTattoo, TRUE);
}
if ( LsaPolicy ) {
LsaClose(LsaPolicy);
}
return(rc);
}
SCESTATUS
ScepBuildNewPrivilegeList(
IN OUT LSA_HANDLE *pPolicyHandle,
IN PWSTR PrivName,
IN PWSTR mszUsers,
IN ULONG dwBuildOption,
OUT PWSTR *pmszNewUsers,
OUT DWORD *pNewLen
)
{
if ( pPolicyHandle == NULL ||
PrivName == NULL || mszUsers == NULL ||
pmszNewUsers == NULL || pNewLen == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
*pNewLen = 0;
*pmszNewUsers = NULL;
//
// lookup the priv first
//
DWORD PrivValue = ScepLookupPrivByName(PrivName);
if ( PrivValue == -1 || PrivValue >= 64 ) {
return(SCESTATUS_INVALID_DATA);
}
NTSTATUS NtStatus=STATUS_SUCCESS;
if ( *pPolicyHandle == NULL ) {
NtStatus = ScepOpenLsaPolicy(
MAXIMUM_ALLOWED, //GENERIC_ALL,
pPolicyHandle,
TRUE
);
if ( !NT_SUCCESS(NtStatus) ) {
return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
}
}
PSCE_PRIVILEGE_VALUE_LIST pAccountList=NULL;
if ( dwBuildOption & SCE_BUILD_ENUMERATE_PRIV ) {
NtStatus = ScepBuildAccountsToRemove(
*pPolicyHandle,
(PrivValue < 32) ? (1 << PrivValue) : 0,
(PrivValue >= 32) ? (1 << (PrivValue-32)) : 0,
SCE_BUILD_IGNORE_UNKNOWN | SCE_BUILD_ACCOUNT_SID_STRING,
NULL,
0,
NULL,
&pAccountList
);
}
SCESTATUS rc=SCESTATUS_SUCCESS;
if ( NT_SUCCESS(NtStatus) ) {
//
// pAccountList can be NULL (no users are assigned of this privilege)
//
PWSTR pCurr = mszUsers;
BOOL bMode = FALSE; // add
DWORD Len;
DWORD SidStrLen;
PWSTR CurrSidString=NULL;
PSCE_PRIVILEGE_VALUE_LIST pTemp, pParent;
BOOL bFreeCurrSidString = FALSE;
while ( pCurr && *pCurr != L'\0' ) {
Len = wcslen(pCurr);
if ( _wcsicmp(SCE_PRIV_ADD, pCurr) == 0 ) {
bMode = FALSE; // add
} else if ( _wcsicmp(SCE_PRIV_REMOVE, pCurr) == 0 ) {
bMode = TRUE; // remove
} else {
//
// get SID string for the account if it's a name
//
if (*pCurr == L'*') {
CurrSidString = pCurr;
SidStrLen = Len;
}
else if (SCESTATUS_SUCCESS == ScepConvertNameToSidString(
*pPolicyHandle,
pCurr,
FALSE,
&CurrSidString,
&SidStrLen
)) {
bFreeCurrSidString = TRUE;
}
else {
CurrSidString = pCurr;
SidStrLen = Len;
}
for ( pTemp=pAccountList, pParent=NULL; pTemp != NULL;
pParent=pTemp, pTemp = pTemp->Next ) {
if ( _wcsicmp(pTemp->Name, CurrSidString) == 0 ) {
break;
}
}
if ( bMode == FALSE ) {
if ( pTemp == NULL ) {
// add this one in
rc = ScepAddToPrivilegeList(&pAccountList, CurrSidString, SidStrLen, 0);
}
} else {
if ( pTemp ) {
// remove this one out
if ( pParent ) {
pParent->Next = pTemp->Next;
} else {
pAccountList = pTemp->Next;
}
// free this one
pTemp->Next = NULL;
ScepFreePrivilegeValueList(pTemp);
pTemp = NULL;
}
}
}
//
// free CurrSidString if it's allocated
// (BVT: have to be careful here - MULTI_SZ potentially being freed many times)
//
if ( bFreeCurrSidString ) {
LocalFree(CurrSidString);
CurrSidString = NULL;
bFreeCurrSidString = FALSE;
}
SidStrLen = 0;
if ( SCESTATUS_SUCCESS != rc ) {
break;
}
// move to next element
pCurr += Len + 1;
}
if ( SCESTATUS_SUCCESS == rc ) {
DWORD TotalLen = 0;
for ( pTemp=pAccountList; pTemp != NULL; pTemp = pTemp->Next ) {
pTemp->PrivLowPart = wcslen(pTemp->Name);
TotalLen += pTemp->PrivLowPart+1;
}
*pmszNewUsers = (PWSTR)ScepAlloc(0, (TotalLen+1)*sizeof(WCHAR));
if (*pmszNewUsers ) {
*pNewLen = TotalLen;
TotalLen = 0;
for ( pTemp=pAccountList; pTemp != NULL && TotalLen <= *pNewLen;
pTemp = pTemp->Next ) {
wcscpy(*pmszNewUsers+TotalLen, pTemp->Name);
TotalLen += pTemp->PrivLowPart;
*(*pmszNewUsers+TotalLen) = L'\0';
TotalLen++;
}
*(*pmszNewUsers+TotalLen) = L'\0';
} else {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
}
} else {
rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus));
}
return(rc);
}
SCESTATUS
ScepBuildNewMultiSzRegValue(
IN PWSTR pszKeyName,
IN PWSTR pszStrValue,
IN DWORD dwValueLen,
OUT PWSTR* ppszNewValue,
OUT PDWORD pdwNewLen
)
/* ++
Routine Description:
This routine resolves a multisz reg value in add/remove format to
the exact multisz value
Arguments:
pszKeyName [in] - Reg key and value path
pszStrValue [in] - the multisz value in add/remove
format including the reg type
dwValueLen [in] - Number of chars of the value
ppszNewValue [out] - the resolved value
pdwNewLen [out] - number of chars for the resolved value
Return Value:
SCESTATUS value
-- */
{
PWSTR pszAddList = NULL;
PWSTR pszRemoveList = NULL;
PWSTR pCur = NULL;
PWSTR pAddCur = NULL;
PWSTR pRemoveCur = NULL;
DWORD dwAddListSize = 0;
DWORD dwRemoveListSize = 0;
BOOL bRemove = FALSE;
DWORD dwLen = 0;
SCESTATUS rc = SCESTATUS_SUCCESS;
//
// validate parameters
//
if(!pszKeyName || !pszStrValue ||
!ppszNewValue || !pdwNewLen){
return SCESTATUS_INVALID_PARAMETER;
}
//
// Clear return buffers
//
*ppszNewValue = NULL;
*pdwNewLen = 0;
//
// initialize the cursor to skip the reg type
// which is the first item in the multisz string
//
pCur = pszStrValue + wcslen(pszStrValue) + 1;
//
// Build the add/remove value into an "add" buffer and
// "remove" buffer
//
while( ( (DWORD)(pCur - pszStrValue) < dwValueLen) &&
(*pCur != L'\0') ){
dwLen = wcslen(pCur);
//
// Set mode that next item is an "add" item
// or "remove" item
//
if(0 == _wcsicmp(SCE_REG_ADD, pCur)){
bRemove = FALSE;
pCur += dwLen + 1;
continue;
}
else if(0 == _wcsicmp(SCE_REG_REMOVE, pCur)){
bRemove = TRUE;
pCur += dwLen + 1;
continue;
}
//
// add to "add" buffer if an "add" item
//
if(!bRemove){
//
// only allocate the "add list" buffer if we hit an add item
// and only allocate once
//
if(!pszAddList){
pszAddList = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwValueLen*sizeof(WCHAR));
if(!pszAddList){
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
goto ExitHandler;
}
pAddCur = pszAddList;
}
wcscpy(pAddCur, pCur);
pAddCur += dwLen + 1;
}
//
// add to "remove" buffer if an "remove" item
//
else{
//
// only allocate the "remove list" buffer if we hit a remove item
// and only allocate once
//
if(!pszRemoveList){
pszRemoveList = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwValueLen*sizeof(WCHAR));
if(!pszRemoveList){
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
goto ExitHandler;
}
pRemoveCur = pszRemoveList;
}
wcscpy(pRemoveCur, pCur);
pRemoveCur += dwLen + 1;
}
pCur += dwLen + 1;
}
//
// calculate the buffers sizes
//
if(pszAddList){
dwAddListSize = (pAddCur - pszAddList + 1) * sizeof(WCHAR);
}
if(pszRemoveList){
dwRemoveListSize = (pRemoveCur - pszRemoveList + 1) * sizeof(WCHAR);
}
//
// Create the new resolved buffer
//
rc = ScepBuildRegMultiSzValue(pszKeyName,
pszAddList,
dwAddListSize,
pszRemoveList,
dwRemoveListSize,
pszStrValue,
ppszNewValue,
pdwNewLen
);
if(SCESTATUS_SUCCESS != rc){
goto ExitHandler;
}
ExitHandler:
//
// clean up.
//
if(pszAddList){
ScepFree(pszAddList);
}
if(pszRemoveList){
ScepFree(pszRemoveList);
}
if(SCESTATUS_SUCCESS != rc){
if(*ppszNewValue){
ScepFree(*ppszNewValue);
*ppszNewValue = NULL;
}
*pdwNewLen = 0;
}
return rc;
}
SCESTATUS
ScepBuildRegMultiSzValue(
IN PWSTR pszKeyName,
IN PWSTR pszAddList OPTIONAL,
IN DWORD dwAddSize,
IN PWSTR pszRemoveList OPTIONAL,
IN DWORD dwRemoveSize,
IN PWSTR pszPrefix,
OUT PWSTR* ppszNewValue,
OUT PDWORD pdwNewValueLen
)
/* ++
Routine Description:
This routine resolves a multisz reg value for a given "add" buffer
and "remove" buffer
Arguments:
pszKeyName [in] - Reg key and value path.
pszAddList [in][optional] - "add" buffer.
dwAddSize [in] - the "add" buffer size in bytes.
pszRemoveList [in][optional] - the "remove" buffer.
dwRemoveSize [in] - the "remove" buffer size in bytes.
pszPrefix [in] - prefix reg value to be prepended to the
returned value.
ppszNewValue [out] - the resolved value.
pdwNewLen [out] - number of chars for the resolved value.
Return Value:
SCESTATUS value
-- */
{
HKEY hKeyRoot = NULL;
PWSTR pStart = NULL;
PWSTR pValue = NULL;
PWSTR pTemp = NULL;
DWORD rc = ERROR_SUCCESS;
BOOL bRestoreValue = FALSE;
PWSTR pszData = NULL;
DWORD dwDataSize = 0;
PWSTR pszNewData = NULL;
DWORD dwNewDataSize = 0;
DWORD dwRegType = 0;
DWORD dwPrefixLen = 0;
//
// validate parameters
//
if(!pszKeyName || !ppszNewValue ||
!pdwNewValueLen || !pszPrefix){
return SCESTATUS_INVALID_PARAMETER;
}
//
// we have to have either an add list or a remove list
//
if(!pszAddList && !pszRemoveList){
return SCESTATUS_INVALID_PARAMETER;
}
//
// Clear the return buffers
//
*ppszNewValue = NULL;
*pdwNewValueLen = 0;
//
// find the prefix len
//
dwPrefixLen = wcslen(pszPrefix);
//
// obtain the registry key name
//
pStart = wcschr(pszKeyName, L'\\');
if ( (7 == pStart-pszKeyName) &&
(0 == _wcsnicmp(L"MACHINE", pszKeyName, 7)) ) {
hKeyRoot = HKEY_LOCAL_MACHINE;
} else if ( (5 == pStart-pszKeyName) &&
(0 == _wcsnicmp(L"USERS", pszKeyName, 5)) ) {
hKeyRoot = HKEY_USERS;
} else if ( (12 == pStart-pszKeyName) &&
(0 == _wcsnicmp(L"CLASSES_ROOT", pszKeyName, 12)) ) {
hKeyRoot = HKEY_CLASSES_ROOT;
} else {
rc = ERROR_INVALID_DATA;
goto ExitHandler;
}
//
// find the value name
//
pValue = pStart+1;
do {
pTemp = wcschr(pValue, L'\\');
if ( pTemp ) {
pValue = pTemp+1;
}
} while ( pTemp );
if ( pValue == pStart+1 ) {
rc = ERROR_INVALID_DATA;
goto ExitHandler;
}
//
// terminate the subkey for now
//
*(pValue-1) = L'\0';
bRestoreValue = TRUE;
rc = ScepRegQueryValue(hKeyRoot,
pStart+1,
pValue,
(PVOID*)&pszData,
&dwRegType,
&dwDataSize
);
//
// if the key or the value is not found or the value is empty,
// then the new value is the "add" buffer.
//
if((ERROR_FILE_NOT_FOUND == rc) ||
(sizeof(WCHAR) >= dwDataSize)){
if(pszAddList){
*ppszNewValue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwAddSize + (dwPrefixLen+1)*sizeof(WCHAR));
if(!*ppszNewValue){
rc = ERROR_NOT_ENOUGH_MEMORY;
goto ExitHandler;
}
wcsncpy(*ppszNewValue, pszPrefix, dwPrefixLen);
CopyMemory(*ppszNewValue + dwPrefixLen + 1, pszAddList, dwAddSize);
*pdwNewValueLen = (dwAddSize / sizeof(WCHAR)) + dwPrefixLen + 1;
}
rc = ERROR_SUCCESS;
}
else{
if(ERROR_SUCCESS != rc){
goto ExitHandler;
}
if(REG_MULTI_SZ != dwRegType){
rc = ERROR_INVALID_PARAMETER;
goto ExitHandler;
}
//
// if we have a "remove" buffer, then remove the items from
// the queried value
//
if(pszRemoveList){
rc = ScepRemoveMultiSzItems(pszData,
dwDataSize,
pszRemoveList,
dwRemoveSize,
&pszNewData,
&dwNewDataSize
);
if(ERROR_SUCCESS != rc){
goto ExitHandler;
}
}
//
// if we have an "add" buffer, then add the items to the
// value
//
if(pszAddList){
if(pszData && pszNewData){
ScepFree(pszData);
pszData = pszNewData;
dwDataSize = dwNewDataSize;
pszNewData = NULL;
dwNewDataSize = 0;
}
rc = ScepAddMultiSzItems(pszData,
dwDataSize,
pszAddList,
dwAddSize,
&pszNewData,
&dwNewDataSize
);
if(ERROR_SUCCESS != rc){
goto ExitHandler;
}
}
*ppszNewValue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwNewDataSize + (dwPrefixLen+1)*sizeof(WCHAR));
if(!*ppszNewValue){
rc = ERROR_NOT_ENOUGH_MEMORY;
goto ExitHandler;
}
wcsncpy(*ppszNewValue, pszPrefix, dwPrefixLen);
CopyMemory(*ppszNewValue + dwPrefixLen + 1, pszNewData, dwNewDataSize);
*pdwNewValueLen = (dwNewDataSize / sizeof(WCHAR)) + dwPrefixLen + 1;
}
ExitHandler:
//
// clean up.
//
if(bRestoreValue){
*(pValue-1) = L'\\';
}
if(pszData){
ScepFree(pszData);
}
if(pszNewData){
ScepFree(pszNewData);
}
if(ERROR_SUCCESS != rc){
if(*ppszNewValue){
ScepFree(*ppszNewValue);
*ppszNewValue = NULL;
}
*pdwNewValueLen = 0;
}
return ScepDosErrorToSceStatus(rc);
}
SCESTATUS
SceConvertpInfObject(
IN PCWSTR InfSectionName,
IN UINT ObjectType,
IN DWORD ObjectFlag,
IN HINF hInf,
IN PSCECONTEXT hProfile,
IN DWORD dwTableOption,
IN LONG GpoID
)
/* ++
Routine Description:
This routine converts INF sections which are in object-security format,
for example, Registry Keys and File Security sections. These sections
must have 3 fields on each line. The first field is the object's name,
the second field is a status flag, and the third field is the security
descriptor text. The infomration saved in the Jet database for each
object is the object's name as the key, and the text format security
descriptor plus 1 byte status flag as the value.
Arguments:
InfSectionName - the INF section name to convert
ObjectType - The object's type
1 = Registry
2 = File
3 = DS object
hInf - the Inf file handle
hprofile - the Jet database context
Return Value:
-- */
{
SCESTATUS rc;
DOUBLE SectionID;
PSCESECTION hSection=NULL;
PSCESECTION hSectionTattoo=NULL;
INFCONTEXT InfLine;
PWSTR TempName=NULL;
PWSTR Name=NULL;
PWSTR Value=NULL;
DWORD ValueLen;
SCEINF_STATUS InfErr;
TCHAR ObjName[MAX_PATH];
if ( InfSectionName == NULL ||
hInf == INVALID_HANDLE_VALUE ||
hProfile == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
//
// get section's ID. if the section does not exist, add it to the section table
//
rc = SceJetGetSectionIDByName(
hProfile,
InfSectionName,
&SectionID
);
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
rc = SceJetAddSection(
hProfile,
InfSectionName,
&SectionID
);
}
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_SCP_ERROR_ADD, (PWSTR)InfSectionName);
return(rc);
}
if ( SetupFindFirstLine(hInf,InfSectionName,NULL,&InfLine) ) {
//
// open the section
//
if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
rc = SceJetOpenSection(
hProfile,
SectionID,
SCEJET_TABLE_SCP,
&hSection
);
} else {
//
// SMP exists, also open the SMP section
//
rc = SceJetOpenSection(
hProfile,
SectionID,
SCEJET_TABLE_SMP,
&hSection
);
if ( dwTableOption & SCE_TABLE_OPTION_TATTOO ) {
//
// if it's in setup, should check if tattoo table needs to be updated
// do not care error
//
SceJetOpenSection(
hProfile,
SectionID,
SCEJET_TABLE_TATTOO,
&hSectionTattoo
);
}
}
if ( rc != SCESTATUS_SUCCESS ) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
if ( hSection )
SceJetCloseSection( &hSection, TRUE);
if ( hSectionTattoo )
SceJetCloseSection( &hSectionTattoo, TRUE);
return(rc);
}
//
// process each line in the section and save to the scp table.
//
BOOL bIgnore;
do {
//
// Get string fields. Don't care the key name or if it exist.
// Must have at least 3 fields each line.
//
bIgnore = FALSE;
InfErr = SceInfpGetOneObject(&InfLine,
ObjectFlag,
&TempName,
&Value,
&ValueLen
);
rc = ScepDosErrorToSceStatus(InfErr);
if ( rc == SCESTATUS_SUCCESS && TempName != NULL ) {
//
// check to see if the object name needs translated
//
if ( ObjectType == 3 ) {
//
// DS object
//
rc = ScepConvertLdapToJetIndexName(TempName, &Name);
} else if ( ObjectType == 2 && TempName[0] == L'\\' ) {
//
// do not support UNC name format
//
rc = SCESTATUS_INVALID_DATA;
} else if ( ObjectType == 2 && wcschr(TempName, L'%') != NULL ) {
//
// translate the name
//
rc = ScepTranslateFileDirName( TempName, &Name);
if ( rc == ERROR_PATH_NOT_FOUND ) {
if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION )
bIgnore = TRUE;
rc = SCESTATUS_INVALID_DATA;
} else if ( rc != NO_ERROR )
rc = ScepDosErrorToSceStatus(rc);
} else {
Name = TempName;
TempName = NULL;
}
//
// write this line to JET database
//
if ( rc == SCESTATUS_SUCCESS ) {
//
// convert to lowercase
//
Name = _wcslwr(Name);
//
// within policy propagation, write the GPOID too
//
rc = SceJetSetLine(
hSection,
Name,
TRUE,
Value,
ValueLen*sizeof(TCHAR),
(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
);
if ( hSectionTattoo &&
!(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
(dwTableOption & SCE_TABLE_OPTION_TATTOO ) ) {
//
// if it's in setup (not policy prop) and tattoo table exists
// check if tattoo value exists for this one and if so, update it
// do not care error
//
if ( SCESTATUS_SUCCESS == SceJetSeek(
hSectionTattoo,
Name,
wcslen(Name)*sizeof(WCHAR),
SCEJET_SEEK_EQ_NO_CASE) ) {
SceJetSetLine(
hSectionTattoo,
Name,
TRUE,
Value,
ValueLen*sizeof(TCHAR),
0
);
}
}
}
if ( rc != SCESTATUS_SUCCESS) {
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT, TempName );
}
ScepFree(Value);
Value = NULL;
ScepFree(TempName);
TempName = NULL;
ScepFree(Name);
Name = NULL;
} else if ( (ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION) &&
rc == SCESTATUS_SUCCESS && TempName == NULL ) {
//
// this one is ignored because it came from a newer version
// of template.
//
} else {
ObjName[0] = L'\0';
SetupGetStringField(&InfLine,1,ObjName,MAX_PATH,&ValueLen);
ScepLogOutput3(1, ScepSceStatusToDosError(rc),
SCEDLL_ERROR_CONVERT, ObjName );
}
//
// for a newer version template, if a env variable can't be resolved
// it will be ignored.
//
if ( bIgnore ) rc = SCESTATUS_SUCCESS;
if ( SCESTATUS_INVALID_DATA == rc ) {
//
// if a environment variable or other invalid data is found
// in the template, will continue to process other areas/items
// but the error will be eventually returned to the caller
//
gbInvalidData = TRUE;
rc = SCESTATUS_SUCCESS;
}
if ( rc != SCESTATUS_SUCCESS )
break; // do..while loop
} while( SetupFindNextLine(&InfLine,&InfLine) );
SceJetCloseSection( &hSection, TRUE);
if ( hSectionTattoo ) SceJetCloseSection( &hSectionTattoo, TRUE);
}
return(rc);
}
SCEINF_STATUS
SceInfpGetOneObject(
IN PINFCONTEXT pInfLine,
IN DWORD ObjectFlag,
OUT PWSTR *Name,
OUT PWSTR *Value,
OUT PDWORD ValueLen
)
/* ++
Routine Description:
This routine retrieves security setting for one object (a registry key,
or a file) from the INF file (SCP type). Each object in these sections
is represented by one line. Each object has 3 fields, a name, status flag,
and a security setting.
Arguments:
pInfLine - Current line context from the INF file for one object
Name - The object name
Value - The status flag ( 1 byte) plus the security descriptor in text
ValueLen - the length of the value
Return value:
SCESTATUS - SCEINF_SUCCESS
SCEINF_WARNING
SCEINF_NOT_ENOUGH_MEMORY
SCEINF_INVALID_PARAMETER
SCEINF_CORRUPT_PROFILE
SCEINF_INVALID_DATA
-- */
{
SCEINF_STATUS rc=ERROR_BAD_FORMAT;
DWORD cFields;
INT Keyvalue1=0;
DWORD Keyvalue2=0;
DWORD DataSize;
PWSTR SDspec=NULL;
DWORD Len=0;
//
// The Registry/File INF layout must have 3 fields for each line.
// The first field is the key/file name, the 2nd field is the security descriptor index
// for workstations, and the 3rd field is the security descriptor index for servers
//
if ( Name == NULL || Value == NULL ) {
return(ERROR_INVALID_PARAMETER);
}
*Name = NULL;
*Value = NULL;
*ValueLen = 0;
cFields = SetupGetFieldCount( pInfLine );
if ( cFields < 3 ) {
if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION ) {
return(ERROR_SUCCESS);
} else {
return(ERROR_INVALID_DATA);
}
} else if(SetupGetStringField(pInfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
*Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
(DataSize+1)*sizeof(TCHAR) );
if( *Name == NULL ) {
return(ERROR_NOT_ENOUGH_MEMORY);
} else {
//
// the first field is the key/file name. the status is ERROR_BAD_FORMAT now
//
if(SetupGetStringField(pInfLine,1,*Name,DataSize,NULL)) {
#ifdef SCE_DBG
ScepLogOutput2(0,0, L"Read %s", *Name );
#endif
//
// The 2nd field is the status
// The 3rd field (and all fields after) is the security descriptor text
//
if ( SetupGetIntField(pInfLine, 2, (INT *)&Keyvalue1) &&
// SetupGetStringField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
SetupGetMultiSzField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
*Value = (PWSTR)ScepAlloc( 0, (Keyvalue2+2)*sizeof(WCHAR));
//
// add this object
//
if ( *Value == NULL ) {
rc = ERROR_NOT_ENOUGH_MEMORY;
// } else if ( SetupGetStringField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
} else if ( SetupGetMultiSzField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
if ( ObjectFlag & SCE_OBJECT_FLAG_OBJECTS ) {
if ( Keyvalue1 > SCE_STATUS_NO_AUTO_INHERIT ||
Keyvalue1 < SCE_STATUS_CHECK ) {
Keyvalue1 = SCE_STATUS_CHECK;
}
*((BYTE *)(*Value)) = (BYTE)Keyvalue1;
*((CHAR *)(*Value)+1) = '1'; //always treat as container
} else {
//
// services
//
if ( Keyvalue1 > SCE_STARTUP_DISABLED ||
Keyvalue1 < SCE_STARTUP_BOOT ) {
//
// default
//
Keyvalue1 = SCE_STARTUP_MANUAL;
}
*((BYTE *)(*Value)) = 0; // always set status to 0
*((BYTE *)(*Value)+1) = (BYTE)Keyvalue1;
}
//
// convert the multi-sz delimiter to space, if there is any
//
if ( cFields > 3 ) {
ScepConvertMultiSzToDelim( (*Value+1), Keyvalue2, L'\0', L' ');
}
if ( ObjectFlag & SCE_OBJECT_FLAG_OLDSDDL ) {
//
// convert old SDDL string to new one
//
ScepConvertToSDDLFormat( (*Value+1), Keyvalue2 );
}
*ValueLen = Keyvalue2+1;
rc = ERROR_SUCCESS;
} else {
ScepFree(*Value);
*Value = NULL;
rc = ERROR_INVALID_DATA;
}
}
}
// if error, free the memory allocated
if ( rc != ERROR_SUCCESS ) {
ScepFree(*Name);
*Name = NULL;
}
}
}
if ( rc == ERROR_SUCCESS) {
//
// conver the object name to upper case
//
// _wcsupr(*Name); should not do this..
}
return(rc);
}
SCESTATUS
SceConvertpInfDescription(
IN HINF hInf,
IN PSCECONTEXT hProfile
)
{
INFCONTEXT InfLine;
SCESTATUS rc=SCESTATUS_SUCCESS;
WCHAR Description[513];
DWORD Len=0;
DWORD DataSize=0;
DWORD i, cFields;
if ( hInf == INVALID_HANDLE_VALUE ||
hProfile == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
if ( SetupFindFirstLine(hInf,szDescription,NULL,&InfLine) ) {
memset(Description, '\0', 513*sizeof(WCHAR));
// get description from Inf
do {
cFields = SetupGetFieldCount( &InfLine );
for ( i=0; i<cFields && rc==SCESTATUS_SUCCESS; i++) {
if(SetupGetStringField(&InfLine, i+1, Description+Len, 512-Len, &DataSize) ) {
Len += DataSize;
if ( Len >= 512 ) {
Len = 512;
Description[512] = L'\0';
break;
}
if ( i == cFields-1 )
Description[Len-1] = L' ';
else
Description[Len-1] = L',';
} else
rc = SCESTATUS_INVALID_DATA;
}
if ( Len >= 512 )
break;
} while ( rc == SCESTATUS_SUCCESS &&
SetupFindNextLine(&InfLine, &InfLine));
if ( rc == SCESTATUS_SUCCESS && Description[0] ) {
//
// save description to Jet
// NOTE: Jet requires long value update must be done in a transaction
//
rc = SceJetStartTransaction( hProfile );
if ( SCESTATUS_SUCCESS == rc ) {
Description[Len] = L'\0';
rc = SceJetSetValueInVersion(
hProfile,
"SmTblVersion",
"ProfileDescription",
(PWSTR)Description,
Len*sizeof(WCHAR),
JET_prepReplace
);
if ( SCESTATUS_SUCCESS == rc ) {
SceJetCommitTransaction( hProfile, 0 );
} else {
SceJetRollback( hProfile, 0 );
}
}
}
}
return(rc);
}
SCESTATUS
ScepConvertRelativeSidToSidString(
IN PWSTR pwszRelSid,
OUT PWSTR *ppwszSid)
/*
Routine Description:
Given a relative SID string "#-RSID", convert to full SID "*S-domain SID-RSID"
relative to primary domain
Arguments:
pwszRelSid - relative SID
ppwszSid - output SID
Return Value:
WIN32 error code
*/
{
NTSTATUS NtStatus;
DWORD rc = ERROR_SUCCESS;
PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo=NULL;
PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo=NULL;
ULONG ulRid;
DWORD dwSize;
PWSTR pwszDomainSid = NULL;
//
// get primary domain SID
//
NtStatus = ScepGetLsaDomainInfo(
&AccountDomainInfo,
&PrimaryDomainInfo
);
rc = RtlNtStatusToDosError(NtStatus);
if ( ERROR_SUCCESS == rc )
{
rc = ScepConvertSidToPrefixStringSid(
PrimaryDomainInfo->Sid,
&pwszDomainSid);
}
if ( ERROR_SUCCESS == rc ) {
*ppwszSid = (LPWSTR) ScepAlloc(LMEM_ZEROINIT,
(wcslen(pwszDomainSid) + wcslen(&pwszRelSid[1]) + 1) * sizeof(WCHAR));
if(!*ppwszSid)
rc = ERROR_NOT_ENOUGH_MEMORY;
}
//
// build full SID from domain SID and #-RSID, skipping the #
//
if ( ERROR_SUCCESS == rc ) {
wcscpy(*ppwszSid, pwszDomainSid);
wcscat(*ppwszSid, &pwszRelSid[1]);
}
if(AccountDomainInfo != NULL) {
LsaFreeMemory(AccountDomainInfo);
}
if(PrimaryDomainInfo != NULL) {
LsaFreeMemory(PrimaryDomainInfo);
}
return(ScepDosErrorToSceStatus(rc));
}
SCESTATUS
ScepConvertSpecialAccountToSid(
IN OUT LSA_HANDLE *pPolicyHandle,
IN PWSTR mszAccounts,
IN ULONG dwLen,
bool fFreeTextAccount,
OUT PWSTR *pmszNewAccounts,
OUT DWORD *pNewLen
)
{
if ( pPolicyHandle == NULL ||
pmszNewAccounts == NULL || pNewLen == NULL ) {
return(SCESTATUS_INVALID_PARAMETER);
}
*pNewLen = 0;
*pmszNewAccounts = NULL;
PWSTR pCurr = mszAccounts;
DWORD cnt=0;
//
// count how many entries in the list
//
while ( pCurr && *pCurr != L'\0' ) {
cnt++;
pCurr += wcslen(pCurr)+1;
}
if ( cnt == 0 ) {
return(SCESTATUS_SUCCESS);
}
NTSTATUS NtStatus=STATUS_SUCCESS;
if ( *pPolicyHandle == NULL ) {
NtStatus = ScepOpenLsaPolicy(
MAXIMUM_ALLOWED, //GENERIC_ALL,
pPolicyHandle,
TRUE
);
if ( !NT_SUCCESS(NtStatus) ) {
return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
}
}
//
// allocate temp buffer for the sid string pointers
//
PWSTR *pSidStrs = (PWSTR *)ScepAlloc(LPTR, cnt*sizeof(PWSTR));
if ( pSidStrs == NULL ) {
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
}
DWORD *pSidLen = (DWORD *)ScepAlloc(LPTR, cnt*sizeof(DWORD));
if ( pSidLen == NULL ) {
ScepFree(pSidStrs);
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
}
BOOL *pSidFree = (BOOL *)ScepAlloc(LPTR, cnt*sizeof(BOOL));
if ( pSidFree == NULL ) {
ScepFree(pSidStrs);
ScepFree(pSidLen);
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
}
pCurr = mszAccounts;
DWORD i = 0;
BOOL bConvert=FALSE;
PWSTR SidString, pTemp;
DWORD StrLen;
SCESTATUS rc;
while ( pCurr && *pCurr != L'\0' &&
( i < cnt ) ) {
pSidStrs[i] = pCurr;
pSidFree[i] = FALSE;
pSidLen[i] = wcslen(pCurr);
pTemp = pCurr + pSidLen[i] + 1;
if ( fFreeTextAccount && *pCurr != L'*' && wcschr(pCurr, L'\\') == 0 ) {
//
// this is a name format and it's an isolated name
// let's resolve it to a SID string
//
SidString = NULL;
StrLen = 0;
rc = ScepConvertNameToSidString( *pPolicyHandle,
pCurr,
FALSE, //TRUE,
&SidString,
&StrLen
);
if ( rc == SCESTATUS_SUCCESS &&
SidString ) {
//
// got a sid string
//
pSidStrs[i] = SidString;
pSidLen[i] = StrLen;
pSidFree[i] = TRUE;
bConvert = TRUE;
}
}
else if ( !fFreeTextAccount && *pCurr == RELATIVE_SID_PREFIX ) {
// this is a relative SID in format "#-512", convert to "*S-current domain SID-512"
rc = ScepConvertRelativeSidToSidString(pCurr, &SidString);
if( SCESTATUS_SUCCESS == rc) {
pSidStrs[i] = SidString;
pSidLen[i] = wcslen(SidString);
pSidFree[i] = TRUE;
bConvert = TRUE;
}
}
i ++;
pCurr = pTemp;
}
//
// now we need to build the new string
//
rc = SCESTATUS_SUCCESS;
if ( bConvert ) {
DWORD dwTotal=0;
for ( i=0; i<cnt; i++ ) {
dwTotal += pSidLen[i];
dwTotal ++; // for the NULL terminator
}
if ( dwTotal ) {
dwTotal ++; // for the last NULL terminator
*pmszNewAccounts = (PWSTR)ScepAlloc(LPTR, dwTotal*sizeof(WCHAR));
if ( *pmszNewAccounts ) {
pCurr = *pmszNewAccounts;
for ( i=0; i<cnt; i++ ) {
wcsncpy(pCurr, pSidStrs[i], pSidLen[i]);
pCurr += pSidLen[i];
*pCurr = L'\0';
pCurr++;
}
*pNewLen = dwTotal;
} else {
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
}
}
}
for ( i=0; i<cnt; i++ ) {
if ( pSidFree[i] && pSidStrs[i] ) {
ScepFree(pSidStrs[i]);
}
}
ScepFree(pSidStrs);
ScepFree(pSidLen);
ScepFree(pSidFree);
return(rc);
}
SCESTATUS
ScepConvertFreeTextAccountToSid(
IN OUT LSA_HANDLE *pPolicyHandle,
IN PWSTR mszAccounts,
IN ULONG dwLen,
OUT PWSTR *pmszNewAccounts,
OUT DWORD *pNewLen
)
{
return ScepConvertSpecialAccountToSid(
pPolicyHandle,
mszAccounts,
dwLen,
true,
pmszNewAccounts,
pNewLen);
}
SCESTATUS
ScepConvertRelativeSidAccountToSid(
IN OUT LSA_HANDLE *pPolicyHandle,
IN PWSTR mszAccounts,
IN ULONG dwLen,
OUT PWSTR *pmszNewAccounts,
OUT DWORD *pNewLen
)
{
return ScepConvertSpecialAccountToSid(
pPolicyHandle,
mszAccounts,
dwLen,
false,
pmszNewAccounts,
pNewLen);
}