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.
5569 lines
152 KiB
5569 lines
152 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
infwrite.c
|
|
|
|
Abstract:
|
|
|
|
Routines to set information into security profiles (INF layout).
|
|
|
|
Author:
|
|
|
|
Jin Huang (jinhuang) 07-Dec-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "headers.h"
|
|
#include "scedllrc.h"
|
|
#include "infp.h"
|
|
#include "sceutil.h"
|
|
#include "splay.h"
|
|
#include <io.h>
|
|
#include <sddl.h>
|
|
#pragma hdrstop
|
|
|
|
const TCHAR c_szCRLF[] = TEXT("\r\n");
|
|
//
|
|
// Forward references
|
|
//
|
|
SCESTATUS
|
|
SceInfpWriteSystemAccess(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWritePrivileges(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PRIVILEGE_ASSIGNMENT pPrivileges,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteUserSettings(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_NAME_LIST pProfiles,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteGroupMembership(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteServices(
|
|
IN PCWSTR ProfileName,
|
|
IN PCWSTR SectionName,
|
|
IN PSCE_SERVICES pServices,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
SceInfpWriteOneService(
|
|
IN PSCE_SERVICES pService,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteObjects(
|
|
IN PCWSTR ProfileName,
|
|
IN PCWSTR SectionName,
|
|
IN PSCE_OBJECT_ARRAY pObjects,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
SceInfpWriteOneObject(
|
|
IN PSCE_OBJECT_SECURITY pObject,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteAuditing(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpAppendAuditing(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepWriteOneIntValueToProfile(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN PWSTR KeyName,
|
|
IN DWORD Value
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteAuditLogSetting(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD LogSize,
|
|
IN DWORD Periods,
|
|
IN DWORD RetentionDays,
|
|
IN DWORD RestrictGuest,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteInfSection(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD TotalSize,
|
|
IN PWSTR *EachLineStr,
|
|
IN DWORD *EachLineSize,
|
|
IN DWORD StartIndex,
|
|
IN DWORD EndIndex,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
#define SCEINF_ADD_EQUAL_SIGN 1
|
|
#define SCEINF_APPEND_SECTION 2
|
|
|
|
DWORD
|
|
SceInfpWriteListSection(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD TotalSize,
|
|
IN PSCE_NAME_LIST ListLines,
|
|
IN DWORD Option,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
LONG
|
|
SceInfpConvertNameListToString(
|
|
IN LSA_HANDLE LsaHandle,
|
|
IN PCWSTR KeyText,
|
|
IN PSCE_NAME_LIST Fields,
|
|
IN BOOL bOverwrite,
|
|
OUT PWSTR *Strvalue,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
LONG
|
|
SceInfpConvertMultiSZToString(
|
|
IN PCWSTR KeyText,
|
|
IN UNICODE_STRING Fields,
|
|
OUT PWSTR *Strvalue,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepAllocateAndCopy(
|
|
OUT PWSTR *Buffer,
|
|
OUT PDWORD BufSize,
|
|
IN DWORD MaxSize,
|
|
IN PWSTR SrcBuf
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpBreakTextIntoMultiFields(
|
|
IN PWSTR szText,
|
|
IN DWORD dLen,
|
|
OUT LPDWORD pnFields,
|
|
OUT LPDWORD *arrOffset
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteKerberosPolicy(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_KERBEROS_TICKET_INFO pKerberosInfo,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
SCESTATUS
|
|
SceInfpWriteRegistryValues(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_REGISTRY_VALUE_INFO pRegValues,
|
|
IN DWORD ValueCount,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
SceInfpWriteOneValue(
|
|
IN PCWSTR ProfileName,
|
|
IN SCE_REGISTRY_VALUE_INFO RegValue,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize
|
|
);
|
|
|
|
SCESTATUS
|
|
ScepWriteSecurityProfile(
|
|
IN PCWSTR InfProfileName,
|
|
IN AREA_INFORMATION Area,
|
|
IN PSCE_PROFILE_INFO InfoBuffer,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
);
|
|
|
|
DWORD
|
|
ScepCreateTempFiles(
|
|
IN PWSTR InfProfileName,
|
|
OUT PWSTR *ppszTempFileName,
|
|
OUT PWSTR *ppszTargetTempName
|
|
);
|
|
|
|
DWORD
|
|
ScepWritePrivateProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPTSTR pData,
|
|
IN LPCWSTR FileName,
|
|
IN BOOL bOverwrite
|
|
);
|
|
|
|
DWORD
|
|
ScepAppendProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPCWSTR FileName,
|
|
IN LPTSTR pData
|
|
);
|
|
|
|
#define SCEP_PROFILE_WRITE_SECTIONNAME 0x1
|
|
#define SCEP_PROFILE_GENERATE_KEYS 0x2
|
|
#define SCEP_PROFILE_CHECK_DUP 0x4
|
|
|
|
DWORD
|
|
ScepOverwriteProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPCWSTR FileName,
|
|
IN LPTSTR pData,
|
|
IN DWORD dwFlags,
|
|
IN OUT PSCEP_SPLAY_TREE pKeys
|
|
);
|
|
|
|
DWORD
|
|
ScepWriteStrings(
|
|
IN HANDLE hFile,
|
|
IN BOOL bUnicode,
|
|
IN PWSTR szPrefix,
|
|
IN DWORD dwPrefixLen,
|
|
IN PWSTR szString,
|
|
IN DWORD dwStrLen,
|
|
IN PWSTR szSuffix,
|
|
IN DWORD dwSuffixLen,
|
|
IN BOOL bCRLF
|
|
);
|
|
|
|
|
|
SCESTATUS
|
|
WINAPI
|
|
SceWriteSecurityProfileInfo(
|
|
IN PCWSTR InfProfileName,
|
|
IN AREA_INFORMATION Area,
|
|
IN PSCE_PROFILE_INFO InfoBuffer,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
// see comments in ScepWriteSecurityProfile
|
|
{
|
|
return( ScepWriteSecurityProfile( InfProfileName,
|
|
Area,
|
|
InfoBuffer,
|
|
TRUE, // overwrite the section(s)
|
|
Errlog
|
|
) );
|
|
}
|
|
|
|
SCESTATUS
|
|
WINAPI
|
|
SceAppendSecurityProfileInfo(
|
|
IN PCWSTR InfProfileName,
|
|
IN AREA_INFORMATION Area,
|
|
IN PSCE_PROFILE_INFO InfoBuffer,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
// see comments in ScepWriteSecurityProfile
|
|
{
|
|
if ( InfoBuffer == NULL ) return SCESTATUS_SUCCESS;
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
/*
|
|
AREA_INFORMATION Area2=0;
|
|
HINF hInf=NULL;
|
|
PSCE_PROFILE_INFO pOldBuffer=NULL;
|
|
PSCE_OBJECT_ARRAY pNewKeys=NULL, pNewFiles=NULL;
|
|
PSCE_OBJECT_ARRAY pOldKeys=NULL, pOldFiles=NULL;
|
|
|
|
|
|
if ( (Area & AREA_REGISTRY_SECURITY) &&
|
|
(InfoBuffer->pRegistryKeys.pAllNodes != NULL) &&
|
|
(InfoBuffer->pRegistryKeys.pAllNodes->Count > 0) ) {
|
|
|
|
Area2 |= AREA_REGISTRY_SECURITY;
|
|
}
|
|
|
|
if ( (Area & AREA_FILE_SECURITY) &&
|
|
(InfoBuffer->pFiles.pAllNodes != NULL ) &&
|
|
(InfoBuffer->pFiles.pAllNodes->Count > 0 ) ) {
|
|
|
|
Area2 |= AREA_FILE_SECURITY;
|
|
}
|
|
|
|
if ( Area2 > 0 ) {
|
|
|
|
//
|
|
// query existing info from the template and check for duplicate
|
|
// because these two sections do not support INF key name
|
|
// any error occured in duplicate checking is ignored
|
|
//
|
|
rc = SceInfpOpenProfile(
|
|
InfProfileName,
|
|
&hInf
|
|
);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
rc = SceInfpGetSecurityProfileInfo(
|
|
hInf,
|
|
Area2,
|
|
&pOldBuffer,
|
|
NULL
|
|
);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
//
|
|
// files/keys in the template are queried
|
|
// now check if there is any existing files/keys
|
|
//
|
|
DWORD i,j,idxNew;
|
|
|
|
if ( (Area2 & AREA_REGISTRY_SECURITY) &&
|
|
(pOldBuffer->pRegistryKeys.pAllNodes != NULL) &&
|
|
(pOldBuffer->pRegistryKeys.pAllNodes->Count > 0) ) {
|
|
|
|
//
|
|
// there are existing keys
|
|
// now create a new buffer
|
|
//
|
|
pNewKeys = (PSCE_OBJECT_ARRAY)ScepAlloc(0,sizeof(SCE_OBJECT_ARRAY));
|
|
|
|
if ( pNewKeys ) {
|
|
|
|
pNewKeys->Count = 0;
|
|
pNewKeys->pObjectArray = (PSCE_OBJECT_SECURITY *)ScepAlloc(LPTR, (pOldBuffer->pRegistryKeys.pAllNodes->Count)*sizeof(PSCE_OBJECT_SECURITY));
|
|
|
|
if ( pNewKeys->pObjectArray ) {
|
|
//
|
|
// checking duplicate now
|
|
//
|
|
idxNew=0;
|
|
|
|
for ( i=0; i<InfoBuffer->pRegistryKeys.pAllNodes->Count; i++) {
|
|
|
|
if ( InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i] == NULL )
|
|
continue;
|
|
|
|
for ( j=0; j<pOldBuffer->pRegistryKeys.pAllNodes->Count; j++) {
|
|
|
|
if ( pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j] == NULL )
|
|
continue;
|
|
|
|
// check if this one has been checked
|
|
if ( pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Status == 255 )
|
|
continue;
|
|
|
|
if ( _wcsicmp(InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i]->Name,
|
|
pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Name) == 0 ) {
|
|
//
|
|
// found it
|
|
//
|
|
pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Status = 255;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( j >= pOldBuffer->pRegistryKeys.pAllNodes->Count ) {
|
|
//
|
|
// did not find it, now link it to the new buffer
|
|
//
|
|
pNewKeys->pObjectArray[idxNew] = InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i];
|
|
idxNew++;
|
|
}
|
|
}
|
|
|
|
pNewKeys->Count = idxNew;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree(pNewKeys);
|
|
pNewKeys = NULL;
|
|
}
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
}
|
|
|
|
if ( (Area2 & AREA_FILE_SECURITY) &&
|
|
(pOldBuffer->pFiles.pAllNodes != NULL ) &&
|
|
(pOldBuffer->pFiles.pAllNodes->Count > 0 ) ) {
|
|
|
|
//
|
|
// there are existing files
|
|
// now create a new buffer
|
|
//
|
|
pNewFiles = (PSCE_OBJECT_ARRAY)ScepAlloc(0,sizeof(SCE_OBJECT_ARRAY));
|
|
|
|
if ( pNewFiles ) {
|
|
|
|
pNewFiles->Count = 0;
|
|
pNewFiles->pObjectArray = (PSCE_OBJECT_SECURITY *)ScepAlloc(LPTR, (pOldBuffer->pFiles.pAllNodes->Count)*sizeof(PSCE_OBJECT_SECURITY));
|
|
|
|
if ( pNewFiles->pObjectArray ) {
|
|
//
|
|
// checking duplicate now
|
|
//
|
|
idxNew=0;
|
|
|
|
for ( i=0; i<InfoBuffer->pFiles.pAllNodes->Count; i++) {
|
|
|
|
if ( InfoBuffer->pFiles.pAllNodes->pObjectArray[i] == NULL )
|
|
continue;
|
|
|
|
for ( j=0; j<pOldBuffer->pFiles.pAllNodes->Count; j++) {
|
|
|
|
if ( pOldBuffer->pFiles.pAllNodes->pObjectArray[j] == NULL )
|
|
continue;
|
|
|
|
// check if this one has been checked
|
|
if ( pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Status == 255 )
|
|
continue;
|
|
|
|
if ( _wcsicmp(InfoBuffer->pFiles.pAllNodes->pObjectArray[i]->Name,
|
|
pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Name) == 0 ) {
|
|
//
|
|
// found it
|
|
//
|
|
pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Status = 255;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( j >= pOldBuffer->pFiles.pAllNodes->Count ) {
|
|
//
|
|
// did not find it, now link it to the new buffer
|
|
//
|
|
pNewFiles->pObjectArray[idxNew] = InfoBuffer->pFiles.pAllNodes->pObjectArray[i];
|
|
idxNew++;
|
|
}
|
|
}
|
|
|
|
pNewFiles->Count = idxNew;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
ScepFree(pNewFiles);
|
|
pNewFiles = NULL;
|
|
}
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
SceInfpCloseProfile(hInf);
|
|
|
|
SceFreeProfileMemory(pOldBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
if ( pNewKeys != NULL ) {
|
|
//
|
|
// use the purged buffer and save the old one
|
|
//
|
|
pOldKeys = InfoBuffer->pRegistryKeys.pAllNodes;
|
|
InfoBuffer->pRegistryKeys.pAllNodes = pNewKeys;
|
|
}
|
|
|
|
if ( pNewFiles != NULL ) {
|
|
|
|
//
|
|
// use the purged buffer and save the old one
|
|
//
|
|
pOldFiles = InfoBuffer->pFiles.pAllNodes;
|
|
InfoBuffer->pFiles.pAllNodes = pNewFiles;
|
|
}
|
|
*/
|
|
rc = ScepWriteSecurityProfile( InfProfileName,
|
|
Area,
|
|
InfoBuffer,
|
|
FALSE, // append to the section(s)
|
|
Errlog
|
|
);
|
|
/*
|
|
if ( pNewKeys != NULL ) {
|
|
//
|
|
// reset the old pointer and free the new buffer
|
|
//
|
|
InfoBuffer->pRegistryKeys.pAllNodes = pOldKeys;
|
|
|
|
ScepFree(pNewKeys->pObjectArray);
|
|
ScepFree(pNewKeys);
|
|
}
|
|
|
|
if ( pNewFiles != NULL ) {
|
|
|
|
//
|
|
// use the purged buffer and save the old one
|
|
//
|
|
InfoBuffer->pFiles.pAllNodes = pOldFiles;
|
|
|
|
ScepFree(pNewFiles->pObjectArray);
|
|
ScepFree(pNewFiles);
|
|
}
|
|
*/
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
DWORD
|
|
ScepCreateTempFiles(
|
|
IN PWSTR InfProfileName,
|
|
OUT PWSTR *ppszTempFileName,
|
|
OUT PWSTR *ppszTargetTempName
|
|
)
|
|
/*
|
|
Description:
|
|
|
|
This function is to get a temporary file name for system context (in system
|
|
directory) as well as for normal user context (in user profile), and copy the
|
|
input template data to the temporary file.
|
|
|
|
Arguments:
|
|
|
|
InfProfileName - the template file to copy from
|
|
|
|
ppszTempFileName - the name of the temporary file to work on
|
|
|
|
ppszTargetTempName - the backup copy of the template file in sysvol
|
|
*/
|
|
{
|
|
if ( InfProfileName == NULL || ppszTempFileName == NULL ||
|
|
ppszTargetTempName == NULL) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
HANDLE Token=NULL;
|
|
BOOL bSystem=FALSE;
|
|
|
|
LONG Len=0, nSize=0, nRequired=0;
|
|
PWSTR pTempName=NULL;
|
|
DWORD rc=0;
|
|
|
|
PWSTR pTemp=NULL;
|
|
|
|
*ppszTempFileName = NULL;
|
|
*ppszTargetTempName = NULL;
|
|
|
|
//
|
|
// check if we should have temp file on the target too.
|
|
// only do this if the target file is in sysvol
|
|
//
|
|
if ((0xFFFFFFFF != GetFileAttributes(InfProfileName)) &&
|
|
InfProfileName[0] == L'\\' && InfProfileName[1] == L'\\' &&
|
|
(pTemp=wcschr(InfProfileName+2, L'\\')) ) {
|
|
|
|
if ( _wcsnicmp(pTemp, L"\\sysvol\\", 8) == 0 ) {
|
|
//
|
|
// this is a file on sysvol
|
|
//
|
|
Len = wcslen(InfProfileName);
|
|
|
|
*ppszTargetTempName = (PWSTR)LocalAlloc(LPTR, (Len+1)*sizeof(WCHAR));
|
|
|
|
if ( *ppszTargetTempName ) {
|
|
|
|
wcsncpy(*ppszTargetTempName, InfProfileName, Len-4);
|
|
wcscat(*ppszTargetTempName, L".tmp");
|
|
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// determine if the current thread/process is system context
|
|
// if this function fails, it's treated a regular user and the temp
|
|
// file will be created in user profile location.
|
|
//
|
|
|
|
if (!OpenThreadToken( GetCurrentThread(),
|
|
TOKEN_QUERY,
|
|
TRUE,
|
|
&Token)) {
|
|
|
|
if (!OpenProcessToken( GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&Token))
|
|
|
|
Token = NULL;
|
|
}
|
|
|
|
if ( Token != NULL ) {
|
|
|
|
ScepIsSystemContext(Token, &bSystem);
|
|
CloseHandle(Token);
|
|
|
|
}
|
|
|
|
//
|
|
// get a temp file name.
|
|
//
|
|
if ( bSystem ) {
|
|
|
|
Len = lstrlen(TEXT("\\security\\sce00000.tmp"));
|
|
nRequired = GetSystemWindowsDirectory(NULL, 0);
|
|
|
|
} else {
|
|
|
|
//
|
|
// get the temp file name from user's temp directory
|
|
// the environment variable "TMP" is used here because this write API
|
|
// is always called in user's process (except called from system context)
|
|
//
|
|
Len = lstrlen(TEXT("\\sce00000.tmp"));
|
|
nRequired = GetEnvironmentVariable( L"TMP", NULL, 0 );
|
|
}
|
|
|
|
if ( nRequired > 0 ) {
|
|
//
|
|
// allocate buffer big enough for the temp file name
|
|
//
|
|
pTempName = (LPTSTR)LocalAlloc(0, (nRequired+2+Len)*sizeof(TCHAR));
|
|
|
|
if ( pTempName ) {
|
|
|
|
if ( bSystem ) {
|
|
|
|
nSize = GetSystemWindowsDirectory(pTempName, nRequired);
|
|
} else {
|
|
|
|
nSize = GetEnvironmentVariable(L"TMP", pTempName, nRequired );
|
|
|
|
}
|
|
|
|
if ( nSize > 0 ) {
|
|
|
|
pTempName[nSize] = L'\0';
|
|
|
|
} else {
|
|
|
|
//
|
|
// if failed to query the information, should fail
|
|
//
|
|
rc = GetLastError();
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_ERROR, "Error %d to query temporary file path\n", rc);
|
|
#endif
|
|
LocalFree(pTempName);
|
|
pTempName = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_ERROR, "Error %d to query temporary file path\n", rc);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// check if the temp file name is already used.
|
|
//
|
|
if ( ERROR_SUCCESS == rc && pTempName &&
|
|
nSize <= nRequired ) {
|
|
|
|
ULONG seed=GetTickCount();
|
|
ULONG ranNum=0;
|
|
|
|
ranNum = RtlRandomEx(&seed);
|
|
//
|
|
// make sure that it's not over 5 digits (99999)
|
|
//
|
|
if ( ranNum > 99999 )
|
|
ranNum = ranNum % 99999;
|
|
|
|
swprintf(pTempName+nSize,
|
|
bSystem ? L"\\security\\sce%05d.tmp\0" : L"\\sce%05d.tmp\0",
|
|
ranNum);
|
|
|
|
DWORD index=0;
|
|
while ( 0xFFFFFFFF != GetFileAttributes(pTempName) &&
|
|
index <= 99999) {
|
|
|
|
ranNum = RtlRandomEx(&seed);
|
|
//
|
|
// make sure that it's not over 5 digits (99999)
|
|
//
|
|
if ( ranNum > 99999 )
|
|
ranNum = ranNum % 99999;
|
|
|
|
index++;
|
|
swprintf(pTempName+nSize,
|
|
bSystem ? L"\\security\\sce%05d.tmp\0" : L"\\sce%05d.tmp\0",
|
|
ranNum);
|
|
}
|
|
|
|
if ( index >= 100000 ) {
|
|
//
|
|
// can't get a temp file name
|
|
//
|
|
rc = ERROR_DUP_NAME;
|
|
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_ERROR, "Can't get an unique temporary file name\n", rc);
|
|
#endif
|
|
|
|
}
|
|
|
|
} else if ( ERROR_SUCCESS == rc ) {
|
|
|
|
rc = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// make a copy of the temp file
|
|
//
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
//
|
|
// detect if the profile exist and if it does, make a local copy
|
|
//
|
|
DWORD dwAttr = GetFileAttributes(InfProfileName);
|
|
if ( 0xFFFFFFFF != dwAttr ) {
|
|
|
|
if ( FALSE == CopyFile( InfProfileName, pTempName, FALSE ) ) {
|
|
|
|
rc = GetLastError();
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_ERROR, "CopyFile to temp failed with %d\n", rc);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
*ppszTempFileName = pTempName;
|
|
|
|
} else {
|
|
|
|
if ( pTempName ) {
|
|
|
|
//
|
|
// make usre the file is not left over
|
|
//
|
|
DeleteFile(pTempName);
|
|
LocalFree(pTempName);
|
|
}
|
|
|
|
if ( *ppszTargetTempName ) {
|
|
LocalFree(*ppszTargetTempName);
|
|
*ppszTargetTempName = NULL;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
//
|
|
// function definitions
|
|
//
|
|
SCESTATUS
|
|
ScepWriteSecurityProfile(
|
|
IN PCWSTR szInfProfileName,
|
|
IN AREA_INFORMATION Area,
|
|
IN PSCE_PROFILE_INFO InfoBuffer,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/**++
|
|
|
|
Function Description:
|
|
|
|
This function writes all or part of information into a SCP profile in
|
|
INF format.
|
|
|
|
Arguments:
|
|
|
|
ProfileName - The INF file name to write to
|
|
|
|
Area - area(s) for which to get information from
|
|
AREA_SECURITY_POLICY
|
|
AREA_PRIVILEGES
|
|
AREA_USER_SETTINGS
|
|
AREA_GROUP_MEMBERSHIP
|
|
AREA_REGISTRY_SECURITY
|
|
AREA_SYSTEM_SERVICE
|
|
AREA_FILE_SECURITY
|
|
|
|
InfoBuffer - Information to write. The Header of InfoBuffer contains
|
|
SCP/SAP file name or file handle.
|
|
|
|
bOverwrite - TRUE = overwrite the section(s) with InfoBuffer
|
|
FALSE = append InfoBuffer to the section(s)
|
|
|
|
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_CORRUPT_PROFILE
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
-- **/
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD Win32rc;
|
|
DWORD SDsize;
|
|
PSCE_PROFILE_INFO pNewBuffer=NULL;
|
|
AREA_INFORMATION Area2=0;
|
|
|
|
PWSTR InfProfileName=NULL;
|
|
PWSTR TargetTempName=NULL;
|
|
|
|
|
|
if ( szInfProfileName == NULL || InfoBuffer == NULL ||
|
|
Area == 0 ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// get a temp file name
|
|
// if this is system context, the temp file is under %windir%\security\scexxxxx.tmp
|
|
// else the temp file will be in the user profile location.
|
|
//
|
|
// temp file name must be unique to handle simultaneous changes to different templates (GPOs)
|
|
// temp file created under system context will be cleaned up when system booted up.
|
|
//
|
|
Win32rc = ScepCreateTempFiles((PWSTR)szInfProfileName, &InfProfileName, &TargetTempName);
|
|
|
|
if ( Win32rc != ERROR_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
Win32rc,
|
|
Errlog,
|
|
SCEERR_ERROR_CREATE,
|
|
TEXT("Temp")
|
|
);
|
|
return(ScepDosErrorToSceStatus(Win32rc));
|
|
}
|
|
|
|
//
|
|
// initialize the error log buffer
|
|
//
|
|
if ( Errlog ) {
|
|
*Errlog = NULL;
|
|
}
|
|
|
|
//
|
|
// get Revision of this template
|
|
//
|
|
|
|
INT Revision = GetPrivateProfileInt( L"Version",
|
|
L"Revision",
|
|
0,
|
|
InfProfileName
|
|
);
|
|
if ( Revision == 0 ) {
|
|
//
|
|
// maybe a old version of inf file, or
|
|
// it's a brand new file
|
|
//
|
|
TCHAR szBuf[20];
|
|
szBuf[0] = L'\0';
|
|
|
|
SDsize = GetPrivateProfileString(TEXT("Version"),
|
|
TEXT("signature"),
|
|
TEXT(""),
|
|
szBuf,
|
|
20,
|
|
InfProfileName
|
|
);
|
|
|
|
if ( SDsize == 0 ) {
|
|
//
|
|
// this is a new inf file
|
|
//
|
|
Revision = SCE_TEMPLATE_MAX_SUPPORTED_VERSION;
|
|
//
|
|
// make it unicode file, if error continues to use ansi
|
|
//
|
|
SetupINFAsUCS2(InfProfileName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// system access
|
|
//
|
|
|
|
if ( Area & AREA_SECURITY_POLICY ) {
|
|
|
|
rc = SceInfpWriteSystemAccess(
|
|
InfProfileName,
|
|
InfoBuffer,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// system auditing
|
|
//
|
|
if ( bOverwrite ) {
|
|
|
|
rc = SceInfpWriteAuditing(
|
|
InfProfileName,
|
|
InfoBuffer,
|
|
Errlog
|
|
);
|
|
} else {
|
|
|
|
rc = SceInfpAppendAuditing(
|
|
InfProfileName,
|
|
InfoBuffer,
|
|
Errlog
|
|
);
|
|
}
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// kerberos policy
|
|
//
|
|
rc = SceInfpWriteKerberosPolicy(
|
|
InfProfileName,
|
|
InfoBuffer->pKerberosInfo,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
//
|
|
// regsitry values
|
|
//
|
|
rc = SceInfpWriteRegistryValues(
|
|
InfProfileName,
|
|
InfoBuffer->aRegValues,
|
|
InfoBuffer->RegValueCount,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// privilege/rights
|
|
//
|
|
if ( Area & AREA_PRIVILEGES ) {
|
|
|
|
rc = SceInfpWritePrivileges(
|
|
InfProfileName,
|
|
InfoBuffer->OtherInfo.scp.u.pInfPrivilegeAssignedTo,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
//
|
|
// privilege/rights and account profiles for each user
|
|
//
|
|
#if 0
|
|
if ( Area & AREA_USER_SETTINGS ) {
|
|
|
|
rc = SceInfpWriteUserSettings(
|
|
InfProfileName,
|
|
InfoBuffer->OtherInfo.scp.pAccountProfiles,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// group memberships
|
|
//
|
|
|
|
if ( Area & AREA_GROUP_MEMBERSHIP ) {
|
|
rc = SceInfpWriteGroupMembership(
|
|
InfProfileName,
|
|
InfoBuffer->pGroupMembership,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
if ( Revision == 0 ) {
|
|
//
|
|
// old SDDL format, convert it
|
|
//
|
|
Area2 = ~Area & (AREA_REGISTRY_SECURITY |
|
|
AREA_FILE_SECURITY |
|
|
AREA_DS_OBJECTS |
|
|
AREA_SYSTEM_SERVICE
|
|
);
|
|
|
|
if ( Area2 > 0 ) {
|
|
|
|
HINF hInf;
|
|
|
|
rc = SceInfpOpenProfile(
|
|
InfProfileName,
|
|
&hInf
|
|
);
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
|
|
rc = SceInfpGetSecurityProfileInfo(
|
|
hInf,
|
|
Area2,
|
|
&pNewBuffer,
|
|
NULL
|
|
);
|
|
|
|
SceInfpCloseProfile(hInf);
|
|
|
|
if ( SCESTATUS_SUCCESS != rc ) {
|
|
goto Done;
|
|
}
|
|
} else {
|
|
//
|
|
// the template can't be opened (new profile)
|
|
// ignore the error
|
|
//
|
|
rc = SCESTATUS_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// registry keys security
|
|
//
|
|
|
|
if ( Area & AREA_REGISTRY_SECURITY ) {
|
|
|
|
if ( !bOverwrite && pNewBuffer ) {
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szRegistryKeys,
|
|
pNewBuffer->pRegistryKeys.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szRegistryKeys,
|
|
InfoBuffer->pRegistryKeys.pAllNodes,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
} else if ( pNewBuffer ) {
|
|
|
|
//
|
|
// should convert this section to new SDDL format
|
|
//
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szRegistryKeys,
|
|
pNewBuffer->pRegistryKeys.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
}
|
|
|
|
//
|
|
// file security
|
|
//
|
|
|
|
if ( Area & AREA_FILE_SECURITY ) {
|
|
|
|
if ( !bOverwrite && pNewBuffer ) {
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szFileSecurity,
|
|
pNewBuffer->pFiles.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szFileSecurity,
|
|
InfoBuffer->pFiles.pAllNodes,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
} else if ( pNewBuffer ) {
|
|
|
|
//
|
|
// should convert this section to new SDDL format
|
|
//
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szFileSecurity,
|
|
pNewBuffer->pFiles.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// DS security
|
|
//
|
|
|
|
if ( Area & AREA_DS_OBJECTS ) {
|
|
|
|
if ( !bOverwrite && pNewBuffer ) {
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szDSSecurity,
|
|
pNewBuffer->pDsObjects.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szDSSecurity,
|
|
InfoBuffer->pDsObjects.pAllNodes,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
} else if ( pNewBuffer ) {
|
|
|
|
//
|
|
// should convert this section to new SDDL format
|
|
//
|
|
|
|
rc = SceInfpWriteObjects(
|
|
InfProfileName,
|
|
szDSSecurity,
|
|
pNewBuffer->pDsObjects.pAllNodes,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
#endif
|
|
|
|
if ( Area & AREA_SYSTEM_SERVICE ) {
|
|
|
|
if ( !bOverwrite && pNewBuffer ) {
|
|
|
|
rc = SceInfpWriteServices(
|
|
InfProfileName,
|
|
szServiceGeneral,
|
|
pNewBuffer->pServices,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
rc = SceInfpWriteServices(
|
|
InfProfileName,
|
|
szServiceGeneral,
|
|
InfoBuffer->pServices,
|
|
bOverwrite,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
} else if ( pNewBuffer ) {
|
|
|
|
//
|
|
// should convert this section to new SDDL format
|
|
//
|
|
|
|
rc = SceInfpWriteServices(
|
|
InfProfileName,
|
|
szServiceGeneral,
|
|
pNewBuffer->pServices,
|
|
TRUE,
|
|
Errlog
|
|
);
|
|
|
|
if( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// always write [Version] section.
|
|
//
|
|
WCHAR tmp[64];
|
|
memset(tmp, 0, 64*2);
|
|
wcscpy(tmp, L"signature=\"$CHICAGO$\"");
|
|
swprintf(tmp+wcslen(tmp)+1,L"Revision=%d\0\0",
|
|
SCE_TEMPLATE_MAX_SUPPORTED_VERSION);
|
|
|
|
WritePrivateProfileSection(
|
|
L"Version",
|
|
tmp,
|
|
InfProfileName);
|
|
|
|
//
|
|
// all data are successfully written
|
|
//
|
|
if ( TargetTempName &&
|
|
(0xFFFFFFFF != GetFileAttributes(szInfProfileName)) ) {
|
|
//
|
|
// now make a copy of the sysvol file first on the target directory
|
|
//
|
|
if ( FALSE == CopyFile( szInfProfileName, TargetTempName, FALSE ) ) {
|
|
|
|
Win32rc = GetLastError();
|
|
ScepBuildErrorLogInfo(
|
|
Win32rc,
|
|
Errlog,
|
|
IDS_ERROR_COPY_TEMPLATE,
|
|
Win32rc,
|
|
TargetTempName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(Win32rc);
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_ERROR, "CopyFile to backup fails with %d\n", Win32rc);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|
//
|
|
// now copy the temp file to the real sysvol file
|
|
// make several attempts
|
|
//
|
|
int indx=0;
|
|
while (indx < 5 ) {
|
|
|
|
indx++;
|
|
Win32rc = ERROR_SUCCESS;
|
|
rc = SCESTATUS_SUCCESS;
|
|
|
|
if ( FALSE == CopyFile( InfProfileName,
|
|
szInfProfileName, FALSE ) ) {
|
|
|
|
Win32rc = GetLastError();
|
|
ScepBuildErrorLogInfo(
|
|
Win32rc,
|
|
Errlog,
|
|
IDS_ERROR_COPY_TEMPLATE,
|
|
Win32rc,
|
|
szInfProfileName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(Win32rc);
|
|
#if DBG == 1
|
|
SceDebugPrint(DEB_WARN, "%d attempt of CopyFile fails with %d\n", indx, Win32rc);
|
|
#endif
|
|
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
Sleep(100);
|
|
}
|
|
|
|
ASSERT(ERROR_SUCCESS == Win32rc);
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// delete the temp file for both success and failure case
|
|
//
|
|
DeleteFile(InfProfileName);
|
|
LocalFree(InfProfileName);
|
|
|
|
if ( TargetTempName ) {
|
|
|
|
//
|
|
// leave the file there if copy fails.
|
|
//
|
|
if ( rc == SCESTATUS_SUCCESS )
|
|
DeleteFile(TargetTempName);
|
|
|
|
LocalFree(TargetTempName);
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteSystemAccess(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine writes system access area information to the INF file
|
|
in section [System Access].
|
|
|
|
Arguments:
|
|
|
|
ProfileName - The profile to write to
|
|
|
|
pSCEinfo - the profile info (SCP) to write.
|
|
|
|
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_CORRUPT_PROFILE
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
--*/
|
|
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD Value;
|
|
PWSTR Strvalue=NULL;
|
|
DWORD TotalSize=0;
|
|
|
|
SCE_KEY_LOOKUP AccessSCPLookup[] = {
|
|
{(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("NewAdministratorName"), 0, 'A'},
|
|
{(PWSTR)TEXT("NewGuestName"), 0, 'G'},
|
|
{(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 cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
|
|
|
|
DWORD i, j;
|
|
UINT Offset;
|
|
PWSTR EachLine[25] = {0};
|
|
DWORD EachSize[25] = {0};
|
|
DWORD Len;
|
|
|
|
|
|
if (ProfileName == NULL || pSCEinfo == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
for ( i=0, j=0; i<cAccess; i++) {
|
|
|
|
//
|
|
// get settings in AccessLookup table
|
|
//
|
|
|
|
Offset = AccessSCPLookup[i].Offset;
|
|
|
|
Value = 0;
|
|
Strvalue = NULL;
|
|
Len = wcslen(AccessSCPLookup[i].KeyString);
|
|
|
|
switch ( AccessSCPLookup[i].BufferType ) {
|
|
case 'B':
|
|
|
|
//
|
|
// Int Field
|
|
//
|
|
Value = *((BOOL *)((CHAR *)pSCEinfo+Offset)) ? 1 : 0;
|
|
EachSize[j] = Len+5;
|
|
break;
|
|
case 'D':
|
|
|
|
//
|
|
// Int Field
|
|
//
|
|
Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
|
|
if ( Value != SCE_NO_VALUE )
|
|
EachSize[j] = Len+15;
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// String Field
|
|
//
|
|
switch( AccessSCPLookup[i].BufferType ) {
|
|
case 'A':
|
|
Strvalue = pSCEinfo->NewAdministratorName;
|
|
break;
|
|
case 'G':
|
|
Strvalue = pSCEinfo->NewGuestName;
|
|
break;
|
|
default:
|
|
Strvalue = *((PWSTR *)((CHAR *)pSCEinfo+Offset));
|
|
break;
|
|
}
|
|
if ( Strvalue != NULL ) {
|
|
EachSize[j] = Len+5+wcslen(Strvalue);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( EachSize[j] <= 0 )
|
|
continue;
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
Len=(EachSize[j]+1)*sizeof(WCHAR);
|
|
|
|
EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
|
|
if ( EachLine[j] == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
|
|
if (AccessSCPLookup[i].BufferType != 'B' &&
|
|
AccessSCPLookup[i].BufferType != 'D') {
|
|
|
|
swprintf(EachLine[j], L"%s = \"%s\"", AccessSCPLookup[i].KeyString, Strvalue);
|
|
|
|
} else {
|
|
swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// in append mode, we have to write each line separately
|
|
//
|
|
|
|
if (AccessSCPLookup[i].BufferType == 'B' ||
|
|
AccessSCPLookup[i].BufferType == 'D') {
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szSystemAccess,
|
|
AccessSCPLookup[i].KeyString,
|
|
Value
|
|
);
|
|
|
|
} else if ( Strvalue ) {
|
|
|
|
WritePrivateProfileString (szSystemAccess,
|
|
AccessSCPLookup[i].KeyString,
|
|
Strvalue,
|
|
ProfileName);
|
|
}
|
|
}
|
|
|
|
TotalSize += EachSize[j]+1;
|
|
j++;
|
|
|
|
}
|
|
|
|
//
|
|
// writes the profile section
|
|
//
|
|
if ( bOverwrite ) {
|
|
|
|
if ( j > 0 ) {
|
|
|
|
rc = SceInfpWriteInfSection(
|
|
ProfileName,
|
|
szSystemAccess,
|
|
TotalSize+1,
|
|
EachLine,
|
|
&EachSize[0],
|
|
0,
|
|
j-1,
|
|
Errlog
|
|
);
|
|
} else {
|
|
|
|
WritePrivateProfileSection(
|
|
szSystemAccess,
|
|
NULL,
|
|
ProfileName);
|
|
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
for ( i=0; i<cAccess; i++ ) {
|
|
|
|
if ( EachLine[i] != NULL ) {
|
|
ScepFree(EachLine[i]);
|
|
}
|
|
|
|
EachLine[i] = NULL;
|
|
EachSize[i] = 0;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
SCESTATUS
|
|
SceInfpWritePrivileges(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PRIVILEGE_ASSIGNMENT pPrivileges,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes privilege assignments info from the SCP buffer
|
|
into the INF file in section [Privilege Rights].
|
|
|
|
Arguments:
|
|
|
|
ProfileName - the inf profile name
|
|
|
|
pPrivileges - the privilege assignment buffer.
|
|
|
|
Errlog - The error list encountered inside inf processing.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
-- */
|
|
{
|
|
SCESTATUS rc;
|
|
PSCE_PRIVILEGE_ASSIGNMENT pCurRight=NULL;
|
|
PSCE_NAME_LIST pNameList=NULL;
|
|
LONG Keysize;
|
|
PWSTR Strvalue=NULL;
|
|
DWORD TotalSize;
|
|
|
|
//
|
|
// [Privilege Rights] section
|
|
//
|
|
|
|
if (ProfileName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( pPrivileges == NULL ) {
|
|
//
|
|
// the buffer doesn't contain any privileges
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
szPrivilegeRights,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// open lsa policy handle for sid/name lookup
|
|
//
|
|
LSA_HANDLE LsaHandle=NULL;
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepOpenLsaPolicy(
|
|
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
|
|
&LsaHandle,
|
|
TRUE
|
|
));
|
|
|
|
if ( ERROR_SUCCESS != rc ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
TEXT("LSA")
|
|
);
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
}
|
|
|
|
for (pCurRight=pPrivileges, TotalSize=0;
|
|
pCurRight != NULL;
|
|
pCurRight = pCurRight->Next) {
|
|
//
|
|
// Each privilege assignment contains the privilege's name and a list
|
|
// of user/groups to assign to.
|
|
//
|
|
Keysize = SceInfpConvertNameListToString(
|
|
LsaHandle,
|
|
pCurRight->Name,
|
|
pCurRight->AssignedTo,
|
|
bOverwrite,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize >= 0 && Strvalue ) {
|
|
|
|
if ( bOverwrite ) {
|
|
rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
|
|
if ( rc != SCESTATUS_SUCCESS ) { //win32 error code
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
pCurRight->Name
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += Keysize + 1;
|
|
|
|
} else {
|
|
//
|
|
// in append mode, write one line at a time
|
|
//
|
|
WritePrivateProfileString( szPrivilegeRights,
|
|
pCurRight->Name,
|
|
Strvalue,
|
|
ProfileName
|
|
);
|
|
}
|
|
|
|
} else if ( Keysize == -1 ) {
|
|
rc = ERROR_EXTENDED_ERROR;
|
|
goto Done;
|
|
}
|
|
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
}
|
|
|
|
//
|
|
// writes the profile section
|
|
//
|
|
if ( bOverwrite ) {
|
|
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
szPrivilegeRights,
|
|
TotalSize+1,
|
|
pNameList,
|
|
0, // do not overwrite section, do not add equal sign
|
|
Errlog
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( Strvalue != NULL )
|
|
ScepFree(Strvalue);
|
|
|
|
ScepFreeNameList(pNameList);
|
|
|
|
if ( LsaHandle ) {
|
|
LsaClose(LsaHandle);
|
|
}
|
|
|
|
return( ScepDosErrorToSceStatus(rc) );
|
|
}
|
|
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteUserSettings(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_NAME_LIST pProfiles,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes user settings information from the SCP buffer
|
|
into the INF file in section [Account Profiles].
|
|
|
|
Arguments:
|
|
|
|
ProfileName - the inf profile name
|
|
|
|
pProfiles - a list of profiles to write to the section.
|
|
|
|
Errlog - The error list encountered inside inf processing.
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_OTHER_ERROR
|
|
|
|
-- */
|
|
{
|
|
DWORD rc;
|
|
PSCE_NAME_LIST pCurProfile;
|
|
DWORD TotalSize;
|
|
|
|
if (ProfileName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( pProfiles == NULL )
|
|
return(SCESTATUS_SUCCESS);
|
|
|
|
for (pCurProfile=pProfiles, TotalSize=0;
|
|
pCurProfile != NULL;
|
|
pCurProfile = pCurProfile->Next) {
|
|
|
|
TotalSize += wcslen(pCurProfile->Name) + 3; // " ="
|
|
}
|
|
|
|
//
|
|
// write the accountProfile section
|
|
//
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
szAccountProfiles,
|
|
TotalSize+1,
|
|
pProfiles,
|
|
SCEINF_ADD_EQUAL_SIGN,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != NO_ERROR ) {
|
|
ScepBuildErrorLogInfo(rc, Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
szAccountProfiles
|
|
);
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
|
|
} else
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteGroupMembership(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes group membership information to the SCP INF file in
|
|
[Group Membership] section.
|
|
|
|
Arguments:
|
|
|
|
ProfileName - the INF profile name
|
|
|
|
pGroupMembership - the 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
|
|
-- */
|
|
{
|
|
PSCE_GROUP_MEMBERSHIP pGroupMembers=NULL;
|
|
PWSTR Strvalue=NULL;
|
|
LONG Keysize;
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD TotalSize;
|
|
PSCE_NAME_LIST pNameList=NULL;
|
|
PWSTR Keyname=NULL;
|
|
DWORD Len;
|
|
PWSTR SidString=NULL;
|
|
|
|
if (ProfileName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( pGroupMembership == NULL ) {
|
|
//
|
|
// the buffer doesn't contain any groups
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
szGroupMembership,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// open lsa policy handle for sid/name lookup
|
|
//
|
|
LSA_HANDLE LsaHandle=NULL;
|
|
|
|
rc = RtlNtStatusToDosError(
|
|
ScepOpenLsaPolicy(
|
|
POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
|
|
&LsaHandle,
|
|
TRUE
|
|
));
|
|
|
|
if ( ERROR_SUCCESS != rc ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
TEXT("LSA")
|
|
);
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
}
|
|
|
|
//
|
|
// process each group in the list
|
|
//
|
|
|
|
for ( pGroupMembers=pGroupMembership, TotalSize=0;
|
|
pGroupMembers != NULL;
|
|
pGroupMembers = pGroupMembers->Next ) {
|
|
|
|
if ( (pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) &&
|
|
(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( SidString ) {
|
|
LocalFree(SidString);
|
|
SidString = NULL;
|
|
}
|
|
|
|
Len = 0;
|
|
|
|
if ( wcschr(pGroupMembers->GroupName, L'\\') ) {
|
|
//
|
|
// convert group name into *SID format
|
|
//
|
|
|
|
ScepConvertNameToSidString(
|
|
LsaHandle,
|
|
pGroupMembers->GroupName,
|
|
FALSE,
|
|
&SidString,
|
|
&Len
|
|
);
|
|
}
|
|
else {
|
|
if ( ScepLookupWellKnownName(
|
|
pGroupMembers->GroupName,
|
|
LsaHandle,
|
|
&SidString) ) {
|
|
Len = wcslen(SidString);
|
|
}
|
|
}
|
|
|
|
if ( SidString == NULL ) {
|
|
Len = wcslen(pGroupMembers->GroupName);
|
|
}
|
|
|
|
Keyname = (PWSTR)ScepAlloc( 0, (Len+15)*sizeof(WCHAR));
|
|
if ( Keyname == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
|
|
if ( SidString ) {
|
|
wcsncpy(Keyname, SidString, Len);
|
|
} else {
|
|
wcsncpy(Keyname, pGroupMembers->GroupName, Len);
|
|
}
|
|
|
|
if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) {
|
|
|
|
wcscpy(Keyname+Len, szMembers);
|
|
|
|
Keyname[Len+9] = L'\0';
|
|
|
|
//
|
|
// convert the member list into a string
|
|
//
|
|
Keysize = SceInfpConvertNameListToString(
|
|
LsaHandle,
|
|
Keyname,
|
|
pGroupMembers->pMembers,
|
|
bOverwrite,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize >= 0 && Strvalue ) {
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD_MEMBERS,
|
|
pGroupMembers->GroupName
|
|
);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
goto Done;
|
|
}
|
|
} else {
|
|
//
|
|
// append mode, write one line at a time
|
|
//
|
|
WritePrivateProfileString( szGroupMembership,
|
|
Keyname,
|
|
Strvalue,
|
|
ProfileName
|
|
);
|
|
}
|
|
TotalSize += Keysize + 1;
|
|
|
|
} else if ( Keysize == -1 ) {
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
goto Done;
|
|
}
|
|
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
|
|
}
|
|
|
|
if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
|
|
|
|
//
|
|
// convert the memberof list into a string
|
|
//
|
|
wcscpy(Keyname+Len, szMemberof);
|
|
Keyname[Len+10] = L'\0';
|
|
|
|
Keysize = SceInfpConvertNameListToString(
|
|
LsaHandle,
|
|
Keyname,
|
|
pGroupMembers->pMemberOf,
|
|
bOverwrite,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize >= 0 && Strvalue ) {
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD_MEMBEROF,
|
|
pGroupMembers->GroupName
|
|
);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
goto Done;
|
|
}
|
|
} else {
|
|
//
|
|
// in append mode, write one line at a time
|
|
//
|
|
WritePrivateProfileString( szGroupMembership,
|
|
Keyname,
|
|
Strvalue,
|
|
ProfileName
|
|
);
|
|
}
|
|
TotalSize += Keysize + 1;
|
|
|
|
} else if ( Keysize == -1 ) {
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
goto Done;
|
|
}
|
|
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// write to this profile's section
|
|
//
|
|
|
|
if ( bOverwrite ) {
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
szGroupMembership,
|
|
TotalSize+1,
|
|
pNameList,
|
|
0,
|
|
Errlog
|
|
);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( Keyname != NULL )
|
|
ScepFree(Keyname);
|
|
|
|
if ( Strvalue != NULL )
|
|
ScepFree(Strvalue);
|
|
|
|
if ( SidString ) {
|
|
LocalFree(SidString);
|
|
}
|
|
|
|
ScepFreeNameList(pNameList);
|
|
|
|
if ( LsaHandle ) {
|
|
LsaClose(LsaHandle);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteObjects(
|
|
IN PCWSTR ProfileName,
|
|
IN PCWSTR SectionName,
|
|
IN PSCE_OBJECT_ARRAY pObjects,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes registry or files security information (names and
|
|
security descriptors) into the INF SCP file in the section provided.
|
|
|
|
Arguments:
|
|
|
|
ProfileName - the SCP INF file name
|
|
|
|
SectionName - a individual section name to retrieve. NULL = all sections for
|
|
the area.
|
|
|
|
pObjects - the buffer of objects to write.
|
|
|
|
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=SCESTATUS_SUCCESS;
|
|
PSCE_NAME_LIST pNameList=NULL;
|
|
DWORD TotalSize=0;
|
|
DWORD i, ObjectSize;
|
|
|
|
|
|
if (ProfileName == NULL || SectionName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( pObjects == NULL || pObjects->Count == 0 ) {
|
|
//
|
|
// the buffer doesn't contain any objects
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
SectionName,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
for ( i=0; i<pObjects->Count; i++) {
|
|
|
|
//
|
|
// Get string fields. Don't care the key name or if it exist.
|
|
// Must have 3 fields each line.
|
|
//
|
|
rc = SceInfpWriteOneObject(
|
|
pObjects->pObjectArray[i],
|
|
&pNameList,
|
|
&ObjectSize,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
pObjects->pObjectArray[i]->Name
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += ObjectSize + 1;
|
|
}
|
|
|
|
//
|
|
// write to this profile's section
|
|
//
|
|
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
SectionName,
|
|
TotalSize+1,
|
|
pNameList,
|
|
bOverwrite ? 0 : SCEINF_APPEND_SECTION,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
SectionName
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
ScepFreeNameList(pNameList);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteServices(
|
|
IN PCWSTR ProfileName,
|
|
IN PCWSTR SectionName,
|
|
IN PSCE_SERVICES pServices,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes system services general settings (startup and
|
|
security descriptors) into the INF SCP file in the section provided.
|
|
|
|
Arguments:
|
|
|
|
ProfileName - the SCP INF file name
|
|
|
|
SectionName - a individual section name to retrieve. NULL = all sections for
|
|
the area.
|
|
|
|
pServices - the buffer of services to write.
|
|
|
|
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=SCESTATUS_SUCCESS;
|
|
PSCE_NAME_LIST pNameList=NULL;
|
|
PSCE_SERVICES pNode;
|
|
DWORD TotalSize=0;
|
|
DWORD ObjectSize;
|
|
|
|
|
|
if (ProfileName == NULL || SectionName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( pServices == NULL ) {
|
|
//
|
|
// the buffer doesn't contain any services
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
SectionName,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
for ( pNode=pServices; pNode != NULL; pNode = pNode->Next) {
|
|
|
|
//
|
|
// write string fields.
|
|
//
|
|
rc = SceInfpWriteOneService(
|
|
pNode,
|
|
&pNameList,
|
|
&ObjectSize,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
pNode->ServiceName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += ObjectSize + 1;
|
|
}
|
|
|
|
//
|
|
// write to this profile's section
|
|
//
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
SectionName,
|
|
TotalSize+1,
|
|
pNameList,
|
|
bOverwrite ? 0 : SCEINF_APPEND_SECTION,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
SectionName
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
ScepFreeNameList(pNameList);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
SceInfpWriteOneObject(
|
|
IN PSCE_OBJECT_SECURITY pObject,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine builds security descriptor text for one object (a registry key,
|
|
or a file) into the name list. Each object represents one line in the INF file.
|
|
|
|
Arguments:
|
|
|
|
pObject - The object's security settings
|
|
|
|
pNameList - The output string list.
|
|
|
|
TotalSize - the total size of the list
|
|
|
|
Errlog - The cummulative 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
|
|
-- */
|
|
{
|
|
DWORD rc;
|
|
PWSTR Strvalue=NULL;
|
|
PWSTR SDspec=NULL;
|
|
DWORD SDsize=0;
|
|
DWORD nFields;
|
|
DWORD *aFieldOffset=NULL;
|
|
DWORD i;
|
|
|
|
|
|
*ObjectSize = 0;
|
|
if ( pObject == NULL )
|
|
return(ERROR_SUCCESS);
|
|
|
|
if ( pObject->pSecurityDescriptor != NULL ) {
|
|
|
|
//
|
|
// convert security to text
|
|
//
|
|
rc = ConvertSecurityDescriptorToText(
|
|
pObject->pSecurityDescriptor,
|
|
pObject->SeInfo,
|
|
&SDspec,
|
|
&SDsize
|
|
);
|
|
if ( rc != NO_ERROR ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_BUILD_SD,
|
|
pObject->Name
|
|
);
|
|
return(rc);
|
|
}
|
|
}
|
|
|
|
//
|
|
// The Registry/File INF layout must have more than 3 fields for each line.
|
|
// The first field is the key/file name, the 2nd field is the status
|
|
// flag, and the 3rd field and after is the security descriptor in text
|
|
//
|
|
//
|
|
// security descriptor in text is broken into multiple fields if the length
|
|
// is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
|
|
// is at the following characters: ) ( ; " or space
|
|
//
|
|
rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
|
|
|
|
if ( SCESTATUS_SUCCESS != rc ) {
|
|
|
|
rc = ScepSceStatusToDosError(rc);
|
|
goto Done;
|
|
}
|
|
//
|
|
// each extra field will use 3 more chars : ,"<field>"
|
|
//
|
|
*ObjectSize = wcslen(pObject->Name)+5 + SDsize;
|
|
if ( nFields ) {
|
|
*ObjectSize += 3*nFields;
|
|
} else {
|
|
*ObjectSize += 2;
|
|
}
|
|
//
|
|
// allocate the output buffer
|
|
//
|
|
Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
|
|
|
|
if ( Strvalue == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Done;
|
|
}
|
|
//
|
|
// copy data into the buffer
|
|
//
|
|
if ( SDspec != NULL ) {
|
|
|
|
if ( nFields == 0 || !aFieldOffset ) {
|
|
swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pObject->Name, pObject->Status, SDspec);
|
|
} else {
|
|
//
|
|
// loop through the fields
|
|
//
|
|
swprintf(Strvalue, L"\"%s\",%1d\0", pObject->Name, pObject->Status);
|
|
|
|
for ( i=0; i<nFields; i++ ) {
|
|
|
|
if ( aFieldOffset[i] < SDsize ) {
|
|
|
|
wcscat(Strvalue, L",\"");
|
|
if ( i == nFields-1 ) {
|
|
//
|
|
// the last field
|
|
//
|
|
wcscat(Strvalue, SDspec+aFieldOffset[i]);
|
|
} else {
|
|
|
|
wcsncat(Strvalue, SDspec+aFieldOffset[i],
|
|
aFieldOffset[i+1]-aFieldOffset[i]);
|
|
}
|
|
wcscat(Strvalue, L"\"");
|
|
}
|
|
}
|
|
}
|
|
|
|
} else
|
|
swprintf(Strvalue, L"\"%s\",%1d,\"\"", pObject->Name, pObject->Status);
|
|
|
|
rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
|
|
|
|
ScepFree(Strvalue);
|
|
|
|
Done:
|
|
|
|
if ( aFieldOffset ) {
|
|
ScepFree(aFieldOffset);
|
|
}
|
|
|
|
if ( SDspec != NULL )
|
|
ScepFree(SDspec);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
SceInfpWriteOneService(
|
|
IN PSCE_SERVICES pService,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine builds security descriptor text for one object (a registry key,
|
|
or a file) into the name list. Each object represents one line in the INF file.
|
|
|
|
Arguments:
|
|
|
|
pService - The service's general setting
|
|
|
|
pNameList - The output string list.
|
|
|
|
TotalSize - the total size of the list
|
|
|
|
Errlog - The cummulative error list for errors encountered in this routine
|
|
|
|
Return value:
|
|
|
|
Win32 error
|
|
|
|
-- */
|
|
{
|
|
DWORD rc;
|
|
PWSTR Strvalue=NULL;
|
|
PWSTR SDspec=NULL;
|
|
DWORD SDsize=0;
|
|
DWORD nFields;
|
|
DWORD *aFieldOffset=NULL;
|
|
DWORD i;
|
|
|
|
|
|
*ObjectSize = 0;
|
|
if ( pService == NULL )
|
|
return(ERROR_SUCCESS);
|
|
|
|
if ( pService->General.pSecurityDescriptor != NULL ) {
|
|
|
|
//
|
|
// convert security to text
|
|
//
|
|
rc = ConvertSecurityDescriptorToText(
|
|
pService->General.pSecurityDescriptor,
|
|
pService->SeInfo,
|
|
&SDspec,
|
|
&SDsize
|
|
);
|
|
if ( rc != NO_ERROR ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_BUILD_SD,
|
|
pService->ServiceName
|
|
);
|
|
return(rc);
|
|
}
|
|
}
|
|
|
|
//
|
|
// The service INF layout must have 3 or more fields for each line.
|
|
// The first field is the service name, the 2nd field is the startup
|
|
// flag, and the 3rd field and after is the security descriptor in text
|
|
//
|
|
//
|
|
// security descriptor in text is broken into multiple fields if the length
|
|
// is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
|
|
// is at the following characters: ) ( ; " or space
|
|
//
|
|
rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
|
|
|
|
if ( SCESTATUS_SUCCESS != rc ) {
|
|
rc = ScepSceStatusToDosError(rc);
|
|
goto Done;
|
|
}
|
|
//
|
|
// each extra field will use 3 more chars : ,"<field>"
|
|
//
|
|
*ObjectSize = wcslen(pService->ServiceName)+5 + SDsize;
|
|
if ( nFields ) {
|
|
*ObjectSize += 3*nFields;
|
|
} else {
|
|
*ObjectSize += 2;
|
|
}
|
|
//
|
|
// allocate the output buffer
|
|
//
|
|
Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
|
|
|
|
if ( Strvalue == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Done;
|
|
}
|
|
//
|
|
// copy data into the buffer
|
|
//
|
|
|
|
if ( SDspec != NULL ) {
|
|
|
|
if ( nFields == 0 || !aFieldOffset ) {
|
|
|
|
//
|
|
// to represent "not configured"
|
|
// 0 is used in the database
|
|
// "" is used in the inf template
|
|
// so just generate "" instead of "0" for startup type
|
|
//
|
|
|
|
if (pService->Startup == 0) {
|
|
swprintf(Strvalue, L"\"%s\",,\"%s\"", pService->ServiceName, SDspec);
|
|
}
|
|
else {
|
|
swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pService->ServiceName,
|
|
pService->Startup, SDspec);
|
|
}
|
|
} else {
|
|
//
|
|
// loop through the fields
|
|
//
|
|
if (pService->Startup == 0) {
|
|
swprintf(Strvalue, L"\"%s\",\0", pService->ServiceName);
|
|
}
|
|
else {
|
|
swprintf(Strvalue, L"\"%s\",%1d\0", pService->ServiceName, pService->Startup);
|
|
}
|
|
|
|
for ( i=0; i<nFields; i++ ) {
|
|
|
|
if ( aFieldOffset[i] < SDsize ) {
|
|
|
|
wcscat(Strvalue, L",\"");
|
|
if ( i == nFields-1 ) {
|
|
//
|
|
// the last field
|
|
//
|
|
wcscat(Strvalue, SDspec+aFieldOffset[i]);
|
|
} else {
|
|
|
|
wcsncat(Strvalue, SDspec+aFieldOffset[i],
|
|
aFieldOffset[i+1]-aFieldOffset[i]);
|
|
}
|
|
wcscat(Strvalue, L"\"");
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (pService->Startup == 0) {
|
|
swprintf(Strvalue, L"\"%s\",,\"\"", pService->ServiceName);
|
|
}
|
|
else {
|
|
swprintf(Strvalue, L"\"%s\",%1d,\"\"", pService->ServiceName, pService->Startup);
|
|
}
|
|
|
|
}
|
|
|
|
rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
|
|
|
|
ScepFree(Strvalue);
|
|
|
|
Done:
|
|
|
|
if ( aFieldOffset ) {
|
|
ScepFree(aFieldOffset);
|
|
}
|
|
|
|
if ( SDspec != NULL )
|
|
ScepFree(SDspec);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteAuditing(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes system auditing information into the SCP INF file
|
|
in [System Log], [Security Log], [Application Log], [Event Audit],
|
|
[Registry Audit], and [File Audit] sections.
|
|
|
|
Arguments:
|
|
|
|
ProfileName - The INF profile's name
|
|
|
|
pSCEinfo - the info buffer to write.
|
|
|
|
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;
|
|
|
|
DWORD LogSize;
|
|
DWORD Periods;
|
|
DWORD RetentionDays;
|
|
DWORD RestrictGuest;
|
|
|
|
PCWSTR szAuditLog;
|
|
DWORD i, j;
|
|
PWSTR EachLine[10];
|
|
DWORD EachSize[10];
|
|
DWORD TotalSize=0;
|
|
|
|
|
|
if (ProfileName == NULL || pSCEinfo == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
//
|
|
// Writes Log setting for system log, security log and application log
|
|
//
|
|
for ( i=0; i<3; i++) {
|
|
|
|
// get the section name
|
|
switch (i) {
|
|
case 0:
|
|
szAuditLog = szAuditSystemLog;
|
|
break;
|
|
case 1:
|
|
szAuditLog = szAuditSecurityLog;
|
|
break;
|
|
default:
|
|
szAuditLog = szAuditApplicationLog;
|
|
break;
|
|
}
|
|
|
|
// set audit log setting
|
|
LogSize = pSCEinfo->MaximumLogSize[i];
|
|
Periods = pSCEinfo->AuditLogRetentionPeriod[i];
|
|
RetentionDays = pSCEinfo->RetentionDays[i];
|
|
RestrictGuest = pSCEinfo->RestrictGuestAccess[i];
|
|
|
|
//
|
|
// writes the setting to the section
|
|
//
|
|
rc = SceInfpWriteAuditLogSetting(
|
|
ProfileName,
|
|
szAuditLog,
|
|
LogSize,
|
|
Periods,
|
|
RetentionDays,
|
|
RestrictGuest,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// fill the array
|
|
//
|
|
for (i=0; i<10; i++) {
|
|
EachLine[i] = NULL;
|
|
EachSize[i] = 25;
|
|
}
|
|
j = 0;
|
|
|
|
//
|
|
// process each attribute for event auditing
|
|
//
|
|
// AuditSystemEvents
|
|
//
|
|
if ( pSCEinfo->AuditSystemEvents != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditSystemEvents = %d\0", pSCEinfo->AuditSystemEvents);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditLogonEvents
|
|
if ( pSCEinfo->AuditLogonEvents != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditLogonEvents = %d\0", pSCEinfo->AuditLogonEvents);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditObjectAccess
|
|
if ( pSCEinfo->AuditObjectAccess != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditObjectAccess = %d\0", pSCEinfo->AuditObjectAccess);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditPrivilegeUse
|
|
if ( pSCEinfo->AuditPrivilegeUse != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditPrivilegeUse = %d\0", pSCEinfo->AuditPrivilegeUse);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditPolicyChange
|
|
if ( pSCEinfo->AuditPolicyChange != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditPolicyChange = %d\0", pSCEinfo->AuditPolicyChange);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditAccountManage
|
|
if ( pSCEinfo->AuditAccountManage != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditAccountManage = %d\0", pSCEinfo->AuditAccountManage);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditprocessTracking
|
|
if ( pSCEinfo->AuditProcessTracking != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditProcessTracking = %d\0", pSCEinfo->AuditProcessTracking);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditDSAccess
|
|
if ( pSCEinfo->AuditDSAccess != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditDSAccess = %d\0", pSCEinfo->AuditDSAccess);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
// AuditAccountLogon
|
|
if ( pSCEinfo->AuditAccountLogon != SCE_NO_VALUE ) {
|
|
EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
|
|
|
|
if ( EachLine[j] != NULL ) {
|
|
swprintf(EachLine[j], L"AuditAccountLogon = %d\0", pSCEinfo->AuditAccountLogon);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
TotalSize += EachSize[j] + 1;
|
|
j++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Writes the section
|
|
//
|
|
|
|
if ( j > 0 ) {
|
|
rc = SceInfpWriteInfSection(
|
|
ProfileName,
|
|
szAuditEvent,
|
|
TotalSize+1,
|
|
EachLine,
|
|
&EachSize[0],
|
|
0,
|
|
j-1,
|
|
Errlog
|
|
);
|
|
} else {
|
|
|
|
WritePrivateProfileSection(
|
|
szAuditEvent,
|
|
NULL,
|
|
ProfileName);
|
|
}
|
|
|
|
Done:
|
|
|
|
for ( i=0; i<10; i++ )
|
|
if ( EachLine[i] != NULL ) {
|
|
ScepFree(EachLine[i]);
|
|
}
|
|
return(rc);
|
|
}
|
|
|
|
SCESTATUS
|
|
SceInfpAppendAuditing(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_PROFILE_INFO pSCEinfo,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
{
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD Value;
|
|
|
|
SCE_KEY_LOOKUP AuditSCPLookup[] = {
|
|
{(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 cAudit = sizeof(AuditSCPLookup) / sizeof(SCE_KEY_LOOKUP);
|
|
PCWSTR szAuditLog;
|
|
DWORD i;
|
|
UINT Offset;
|
|
|
|
|
|
if (ProfileName == NULL || pSCEinfo == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
for ( i=0; i<3; i++) {
|
|
|
|
// get the section name
|
|
switch (i) {
|
|
case 0:
|
|
szAuditLog = szAuditSystemLog;
|
|
break;
|
|
case 1:
|
|
szAuditLog = szAuditSecurityLog;
|
|
break;
|
|
default:
|
|
szAuditLog = szAuditApplicationLog;
|
|
break;
|
|
}
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szAuditLog,
|
|
L"MaximumLogSize",
|
|
pSCEinfo->MaximumLogSize[i]
|
|
);
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szAuditLog,
|
|
L"AuditLogRetentionPeriod",
|
|
pSCEinfo->AuditLogRetentionPeriod[i]
|
|
);
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szAuditLog,
|
|
L"RetentionDays",
|
|
pSCEinfo->RetentionDays[i]
|
|
);
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szAuditLog,
|
|
L"RestrictGuestAccess",
|
|
pSCEinfo->RestrictGuestAccess[i]
|
|
);
|
|
|
|
}
|
|
|
|
for ( i=0; i<cAudit; i++) {
|
|
|
|
//
|
|
// get settings in AuditLookup table
|
|
//
|
|
|
|
Offset = AuditSCPLookup[i].Offset;
|
|
|
|
switch ( AuditSCPLookup[i].BufferType ) {
|
|
case 'D':
|
|
|
|
//
|
|
// Int Field
|
|
//
|
|
Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szAuditEvent,
|
|
AuditSCPLookup[i].KeyString,
|
|
Value
|
|
);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
SCESTATUS
|
|
ScepWriteOneIntValueToProfile(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN PWSTR KeyName,
|
|
IN DWORD Value
|
|
)
|
|
{
|
|
WCHAR TmpBuf[15];
|
|
|
|
if ( Value == SCE_NO_VALUE ) {
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
swprintf(TmpBuf, L"%d\0", Value);
|
|
|
|
WritePrivateProfileString( InfSectionName,
|
|
KeyName,
|
|
TmpBuf,
|
|
InfFileName
|
|
);
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteAuditLogSetting(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD LogSize,
|
|
IN DWORD Periods,
|
|
IN DWORD RetentionDays,
|
|
IN DWORD RestrictGuest,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine retrieves audit log setting from the INF file (SCP and SAP)
|
|
based on the SectionName passed in. The audit log settings include MaximumSize,
|
|
RetentionPeriod and RetentionDays. There are 3 different logs (system,
|
|
security, and application) which all have the same setting. The information
|
|
returned in in LogSize, Periods, RetentionDays. These 3 output arguments will
|
|
be reset at the begining of the routine. So if error occurs after the reset,
|
|
the original values won't be set back.
|
|
|
|
Arguments:
|
|
|
|
InfFileName - The INF file name to write to
|
|
|
|
InfSectionName - Log section name (SAdtSystemLog, SAdtSecurityLog, SAdtApplicationLog)
|
|
|
|
LogSize - The maximum size of the log
|
|
|
|
Periods - The retention period of the log
|
|
|
|
RetentionDays - The number of days for log retention
|
|
|
|
Errlog - The error list
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
PWSTR EachLine[4];
|
|
DWORD EachSize[4];
|
|
DWORD TotalSize=0;
|
|
DWORD i;
|
|
|
|
|
|
if (InfFileName == NULL || InfSectionName == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
//
|
|
// initialize and fill the array
|
|
//
|
|
|
|
for ( i=0; i<4; i++ ) {
|
|
EachLine[i] = NULL;
|
|
EachSize[i] = 37;
|
|
}
|
|
i = 0;
|
|
|
|
if ( LogSize != (DWORD)SCE_NO_VALUE ) {
|
|
|
|
EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"MaximumLogSize = %d", LogSize);
|
|
EachSize[i] = wcslen(EachLine[i]);
|
|
TotalSize += EachSize[i] + 1;
|
|
i++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( Periods != (DWORD)SCE_NO_VALUE ) {
|
|
EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"AuditLogRetentionPeriod = %d", Periods);
|
|
EachSize[i] = wcslen(EachLine[i]);
|
|
TotalSize += EachSize[i] + 1;
|
|
i++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( RetentionDays != (DWORD)SCE_NO_VALUE ) {
|
|
EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"RetentionDays = %d", RetentionDays);
|
|
EachSize[i] = wcslen(EachLine[i]);
|
|
TotalSize += EachSize[i] + 1;
|
|
i++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
if ( RestrictGuest != (DWORD)SCE_NO_VALUE ) {
|
|
EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"RestrictGuestAccess = %d", RestrictGuest);
|
|
EachSize[i] = wcslen(EachLine[i]);
|
|
TotalSize += EachSize[i] + 1;
|
|
i++;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
}
|
|
//
|
|
// write this section
|
|
//
|
|
|
|
if ( i == 0 ) {
|
|
//
|
|
// all settings are not configured
|
|
// delete the section
|
|
//
|
|
WritePrivateProfileString(
|
|
InfSectionName,
|
|
NULL,
|
|
NULL,
|
|
InfFileName
|
|
);
|
|
} else {
|
|
rc = SceInfpWriteInfSection(
|
|
InfFileName,
|
|
InfSectionName,
|
|
TotalSize+1,
|
|
EachLine,
|
|
&EachSize[0],
|
|
0,
|
|
i-1,
|
|
Errlog
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
InfSectionName
|
|
);
|
|
}
|
|
//
|
|
// free memory
|
|
//
|
|
for ( i=0; i<4; i++ ) {
|
|
if ( EachLine[i] != NULL )
|
|
ScepFree(EachLine[i]);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteInfSection(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD TotalSize,
|
|
IN PWSTR *EachLineStr,
|
|
IN DWORD *EachLineSize,
|
|
IN DWORD StartIndex,
|
|
IN DWORD EndIndex,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes information in a array (each element in the array
|
|
represents a line in the section) to the section specified by
|
|
InfSectionName in the file specified by InfFileName. TotalSize is used
|
|
to allocate a block of memory for writing.
|
|
|
|
Arguments:
|
|
|
|
InfFileName - the INF file name
|
|
|
|
InfSectionName - the section into which to write information
|
|
|
|
TotalSize - The size of the buffer required to write
|
|
|
|
EachLineStr - a array of strings (each element represents a line )
|
|
|
|
EachLineSize - a array of numbers (each number is the size of the corresponding
|
|
element in EachLineStr).
|
|
|
|
StartIndex - The first index of the array
|
|
|
|
EndIndex - The last index of the array
|
|
|
|
Errlog - The list of errors
|
|
|
|
Return value:
|
|
|
|
Win32 error code
|
|
|
|
-- */
|
|
{
|
|
PWSTR SectionString=NULL;
|
|
PWSTR pTemp;
|
|
DWORD i;
|
|
BOOL status;
|
|
DWORD rc = NO_ERROR;
|
|
|
|
|
|
if (InfFileName == NULL || InfSectionName == NULL ||
|
|
EachLineStr == NULL || EachLineSize == NULL )
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
|
|
if ( TotalSize > 1 ) {
|
|
SectionString = (PWSTR)ScepAlloc( (UINT)0, (TotalSize+1)*sizeof(WCHAR));
|
|
if ( SectionString == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
return(rc);
|
|
}
|
|
|
|
pTemp = SectionString;
|
|
for ( i=StartIndex; i<=EndIndex; i++) {
|
|
if ( EachLineStr[i] != NULL && EachLineSize[i] > 0 ) {
|
|
wcsncpy(pTemp, EachLineStr[i], EachLineSize[i]);
|
|
pTemp += EachLineSize[i];
|
|
*pTemp = L'\0';
|
|
pTemp++;
|
|
}
|
|
}
|
|
*pTemp = L'\0';
|
|
|
|
//
|
|
// writes the profile section, the following call should empty the section then
|
|
// add all keys in SectionString to the section.
|
|
//
|
|
|
|
status = WritePrivateProfileSection(
|
|
InfSectionName,
|
|
SectionString,
|
|
InfFileName
|
|
);
|
|
if ( status == FALSE ) {
|
|
rc = GetLastError();
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
InfSectionName
|
|
);
|
|
}
|
|
|
|
ScepFree(SectionString);
|
|
SectionString = NULL;
|
|
|
|
}
|
|
|
|
return(ScepDosErrorToSceStatus(rc));
|
|
}
|
|
|
|
|
|
DWORD
|
|
SceInfpWriteListSection(
|
|
IN PCWSTR InfFileName,
|
|
IN PCWSTR InfSectionName,
|
|
IN DWORD TotalSize,
|
|
IN PSCE_NAME_LIST ListLines,
|
|
IN DWORD Option,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine writes information in a PSCE_NAME_LIST type list (each node
|
|
in the list represents a line in the section) to the section specified
|
|
by InfSectionName in the file specified by InfFileName. TotalSize is used
|
|
to allocate a block of memory for writing.
|
|
|
|
Arguments:
|
|
|
|
InfFileName - the INF file name
|
|
|
|
InfSectionName - the section into which to write information
|
|
|
|
TotalSize - The size of the buffer required to write
|
|
|
|
ListLines - The list of each line's text
|
|
|
|
Errlog - The list of errors
|
|
|
|
Return value:
|
|
|
|
Win32 error code
|
|
|
|
-- */
|
|
{
|
|
PWSTR SectionString=NULL;
|
|
PWSTR pTemp;
|
|
PSCE_NAME_LIST pName;
|
|
BOOL status;
|
|
DWORD rc=NO_ERROR;
|
|
DWORD Len;
|
|
|
|
|
|
if ( TotalSize > 1 ) {
|
|
SectionString = (PWSTR)ScepAlloc( (UINT)0, TotalSize*sizeof(WCHAR));
|
|
if ( SectionString == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
return(rc);
|
|
}
|
|
|
|
pTemp = SectionString;
|
|
for ( pName=ListLines; pName != NULL; pName = pName->Next ) {
|
|
Len = wcslen(pName->Name);
|
|
wcsncpy(pTemp, pName->Name, Len);
|
|
pTemp += Len;
|
|
if ( Option & SCEINF_ADD_EQUAL_SIGN ) {
|
|
*pTemp++ = L' ';
|
|
*pTemp++ = L'=';
|
|
}
|
|
*pTemp++ = L'\0';
|
|
}
|
|
*pTemp = L'\0';
|
|
|
|
/*
|
|
if ( !( Option & SCEINF_APPEND_SECTION ) ) {
|
|
|
|
//
|
|
// empty the section first
|
|
//
|
|
WritePrivateProfileString(
|
|
InfSectionName,
|
|
NULL,
|
|
NULL,
|
|
InfFileName
|
|
);
|
|
}
|
|
|
|
//
|
|
// write the section
|
|
//
|
|
status = WritePrivateProfileSection(
|
|
InfSectionName,
|
|
SectionString,
|
|
InfFileName
|
|
);
|
|
*/
|
|
//
|
|
// write the section
|
|
//
|
|
rc = ScepWritePrivateProfileSection(
|
|
InfSectionName,
|
|
SectionString,
|
|
InfFileName,
|
|
( Option & SCEINF_APPEND_SECTION ) ? FALSE : TRUE
|
|
);
|
|
ScepFree(SectionString);
|
|
SectionString = NULL;
|
|
|
|
// if ( status == FALSE ) {
|
|
// rc = GetLastError();
|
|
if ( ERROR_SUCCESS != rc ) {
|
|
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
InfSectionName
|
|
);
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
LONG
|
|
SceInfpConvertNameListToString(
|
|
IN LSA_HANDLE LsaPolicy,
|
|
IN PCWSTR KeyText,
|
|
IN PSCE_NAME_LIST Fields,
|
|
IN BOOL bOverwrite,
|
|
OUT PWSTR *Strvalue,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine converts names in a name list to comma delimited string.
|
|
The format of the returned string is KeyText = f1,f2,f3,f4... where
|
|
f1..fn are names in the name list.
|
|
|
|
Arguments:
|
|
|
|
KeyText - a string represents the key (left side of the = sign)
|
|
|
|
Fields - The name list
|
|
|
|
Strvalue - The output string
|
|
|
|
Errlog - The error list
|
|
|
|
Return value:
|
|
|
|
Length of the output string if successful. -1 if error.
|
|
|
|
-- */
|
|
{
|
|
DWORD TotalSize;
|
|
DWORD Strsize;
|
|
PWSTR pTemp = NULL;
|
|
PSCE_NAME_LIST pName;
|
|
SCE_TEMP_NODE *tmpArray=NULL, *pa=NULL;
|
|
DWORD i=0,j;
|
|
DWORD cntAllocated=0;
|
|
DWORD rc=ERROR_SUCCESS;
|
|
|
|
//
|
|
// count the total size of all fields
|
|
//
|
|
|
|
for ( pName=Fields, TotalSize=0; pName != NULL; pName = pName->Next ) {
|
|
|
|
if (pName->Name[0] == L'\0') {
|
|
continue;
|
|
}
|
|
|
|
if ( i >= cntAllocated ) {
|
|
//
|
|
// array is not enough, reallocate
|
|
//
|
|
tmpArray = (SCE_TEMP_NODE *)ScepAlloc(LPTR, (cntAllocated+16)*sizeof(SCE_TEMP_NODE));
|
|
|
|
if ( tmpArray ) {
|
|
|
|
//
|
|
// move pointers from the old array to the new array
|
|
//
|
|
|
|
if ( pa ) {
|
|
for ( j=0; j<cntAllocated; j++ ) {
|
|
tmpArray[j].Name = pa[j].Name;
|
|
tmpArray[j].Len = pa[j].Len;
|
|
tmpArray[j].bFree = pa[j].bFree;
|
|
}
|
|
ScepFree(pa);
|
|
}
|
|
pa = tmpArray;
|
|
tmpArray = NULL;
|
|
|
|
|
|
cntAllocated += 16;
|
|
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pTemp = NULL;
|
|
if ( wcschr(pName->Name, L'\\') &&
|
|
LsaPolicy ) {
|
|
|
|
//
|
|
// check if the name has a '\' in it, it should be translated to
|
|
// *SID
|
|
//
|
|
ScepConvertNameToSidString(LsaPolicy, pName->Name, FALSE, &pTemp, &Strsize);
|
|
|
|
if ( pTemp ) {
|
|
pa[i].Name = pTemp;
|
|
pa[i].bFree = TRUE;
|
|
} else {
|
|
pa[i].Name = pName->Name;
|
|
pa[i].bFree = FALSE;
|
|
Strsize = wcslen(pName->Name);
|
|
}
|
|
} else {
|
|
if ( ScepLookupWellKnownName(
|
|
pName->Name,
|
|
LsaPolicy,
|
|
&pTemp) ) {
|
|
pa[i].Name = pTemp;
|
|
pa[i].bFree = TRUE;
|
|
Strsize = wcslen(pTemp);
|
|
}
|
|
else {
|
|
pa[i].Name = pName->Name;
|
|
pa[i].bFree = FALSE;
|
|
Strsize = wcslen(pName->Name);
|
|
}
|
|
}
|
|
pa[i].Len = Strsize;
|
|
|
|
TotalSize += Strsize + 1;
|
|
i++;
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
//
|
|
// The format of the string is
|
|
// KeyText = f1,f2,f3,....
|
|
//
|
|
|
|
if ( bOverwrite ) {
|
|
Strsize = 3 + wcslen(KeyText);
|
|
if ( TotalSize > 0 )
|
|
TotalSize += Strsize;
|
|
else
|
|
TotalSize = Strsize;
|
|
} else {
|
|
Strsize = 0;
|
|
}
|
|
|
|
*Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
|
|
if ( *Strvalue == NULL ) {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
|
|
if ( bOverwrite ) {
|
|
swprintf(*Strvalue, L"%s = ", KeyText);
|
|
}
|
|
pTemp = *Strvalue + Strsize;
|
|
|
|
for (j=0; j<i; j++) {
|
|
if ( pa[j].Name ) {
|
|
wcscpy(pTemp, pa[j].Name);
|
|
pTemp += pa[j].Len;
|
|
*pTemp = L',';
|
|
pTemp++;
|
|
}
|
|
}
|
|
if ( pTemp != (*Strvalue+Strsize) ) {
|
|
*(pTemp-1) = L'\0';
|
|
}
|
|
*pTemp = L'\0';
|
|
|
|
}
|
|
}
|
|
|
|
if ( pa ) {
|
|
|
|
for ( j=0; j<i; j++ ) {
|
|
if ( pa[j].Name && pa[j].bFree ) {
|
|
ScepFree(pa[j].Name);
|
|
}
|
|
}
|
|
ScepFree(pa);
|
|
}
|
|
|
|
if ( rc != ERROR_SUCCESS ) {
|
|
return(-1);
|
|
} else if ( TotalSize == 0 ) {
|
|
return(TotalSize);
|
|
} else {
|
|
return(TotalSize-1);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
|
|
SCESTATUS
|
|
WINAPI
|
|
SceWriteUserSection(
|
|
IN PCWSTR InfProfileName,
|
|
IN PWSTR Name,
|
|
IN PSCE_USER_PROFILE pProfile,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
-- */
|
|
{
|
|
PWSTR InfSectionName=NULL;
|
|
SCESTATUS rc;
|
|
PWSTR EachLine[12];
|
|
DWORD EachSize[12];
|
|
DWORD TotalSize;
|
|
TCHAR Keyname[SCE_KEY_MAX_LENGTH];
|
|
DWORD Value;
|
|
LONG Keysize, i;
|
|
PSCE_LOGON_HOUR pLogonHour=NULL;
|
|
PWSTR Strvalue=NULL;
|
|
|
|
|
|
if ( InfProfileName == NULL ||
|
|
Name == NULL ||
|
|
pProfile == NULL ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// process each detail profile section
|
|
//
|
|
|
|
for ( i=0; i<12; i++ ) {
|
|
EachLine[i] = NULL;
|
|
EachSize[i] = 0;
|
|
}
|
|
|
|
TotalSize=0;
|
|
memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
|
|
i = 0;
|
|
|
|
InfSectionName = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (wcslen(Name)+12)*sizeof(WCHAR));
|
|
if ( InfSectionName == NULL )
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
swprintf(InfSectionName, L"UserProfile %s", Name);
|
|
|
|
//
|
|
// initialize the error log buffer
|
|
//
|
|
if ( Errlog ) {
|
|
*Errlog = NULL;
|
|
}
|
|
if ( pProfile->DisallowPasswordChange != SCE_NO_VALUE ) {
|
|
|
|
// DisallowPasswordChange
|
|
Value = pProfile->DisallowPasswordChange == 0 ? 0 : 1;
|
|
swprintf(Keyname, L"DisallowPasswordChange = %d", Value);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"DisallowPasswordChange",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
if ( pProfile->NeverExpirePassword != SCE_NO_VALUE ||
|
|
pProfile->ForcePasswordChange != SCE_NO_VALUE ) {
|
|
|
|
// PasswordChangeStyle
|
|
if ( pProfile->NeverExpirePassword != SCE_NO_VALUE &&
|
|
pProfile->NeverExpirePassword != 0 )
|
|
Value = 1;
|
|
else {
|
|
if ( pProfile->ForcePasswordChange != SCE_NO_VALUE &&
|
|
pProfile->ForcePasswordChange != 0 )
|
|
Value = 2;
|
|
else
|
|
Value = 0;
|
|
}
|
|
swprintf(Keyname, L"PasswordChangeStyle = %d", Value);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"PasswordChangeStyle",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->AccountDisabled != SCE_NO_VALUE ) {
|
|
// AccountDisabled
|
|
Value = pProfile->AccountDisabled == 0 ? 0 : 1;
|
|
swprintf(Keyname, L"AccountDisabled = %d", Value);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"AccountDisabled",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->UserProfile != NULL ) {
|
|
// UserProfile
|
|
swprintf(Keyname, L"UserProfile = %s", pProfile->UserProfile);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"UserProfile",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->LogonScript != NULL ) {
|
|
// LogonScript
|
|
swprintf(Keyname, L"LogonScript = %s", pProfile->LogonScript);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"LogonScript",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->HomeDir != NULL ) {
|
|
// HomeDir
|
|
swprintf(Keyname, L"HomeDir = %s", pProfile->HomeDir);
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"HomeDir",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->pLogonHours != NULL ) {
|
|
// LogonHours
|
|
|
|
swprintf(Keyname, L"LogonHours = ");
|
|
Keysize = wcslen(Keyname);
|
|
|
|
for ( pLogonHour=pProfile->pLogonHours;
|
|
pLogonHour != NULL;
|
|
pLogonHour = pLogonHour->Next) {
|
|
|
|
swprintf(&Keyname[Keysize], L"%d,%d,",pLogonHour->Start,
|
|
pLogonHour->End);
|
|
Keysize += ((pLogonHour->Start < 9) ? 2 : 3) +
|
|
((pLogonHour->End < 9 ) ? 2 : 3);
|
|
}
|
|
// turn off the last comma
|
|
Keyname[Keysize-1] = L'\0';
|
|
|
|
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], Keysize+5, Keyname );
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"LogonHours",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->pWorkstations.Buffer != NULL ) {
|
|
// Workstations
|
|
|
|
Keysize = SceInfpConvertMultiSZToString(
|
|
L"Workstations",
|
|
pProfile->pWorkstations,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize > 0 ) {
|
|
EachLine[i] = Strvalue;
|
|
EachSize[i] = Keysize;
|
|
Strvalue = NULL;
|
|
} else {
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
goto Done;
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"WorkstationRestricitons",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->pGroupsBelongsTo != NULL ) {
|
|
// GroupsBelongsTo
|
|
|
|
Keysize = SceInfpConvertNameListToString(
|
|
NULL,
|
|
L"GroupsBelongsTo",
|
|
pProfile->pGroupsBelongsTo,
|
|
TRUE,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize > 0 ) {
|
|
EachLine[i] = Strvalue;
|
|
EachSize[i] = Keysize;
|
|
Strvalue = NULL;
|
|
} else {
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
goto Done;
|
|
}
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"GroupsBelongsTo",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
}
|
|
|
|
if ( pProfile->pAssignToUsers != NULL ) {
|
|
// AssignToUsers
|
|
|
|
Keysize = SceInfpConvertNameListToString(
|
|
NULL,
|
|
L"AssignToUsers",
|
|
pProfile->pAssignToUsers,
|
|
TRUE,
|
|
&Strvalue,
|
|
Errlog
|
|
);
|
|
if ( Keysize > 0 ) {
|
|
EachLine[i] = Strvalue;
|
|
EachSize[i] = Keysize;
|
|
Strvalue = NULL;
|
|
} else {
|
|
rc = SCESTATUS_OTHER_ERROR;
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
goto Done;
|
|
}
|
|
} else {
|
|
swprintf(Keyname, L"AssignToUsers = ");
|
|
rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
|
|
}
|
|
|
|
if ( rc != SCESTATUS_SUCCESS) {
|
|
ScepBuildErrorLogInfo(
|
|
ScepSceStatusToDosError(rc),
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"AssignToUsers",
|
|
InfSectionName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
|
|
if ( pProfile->pHomeDirSecurity != NULL ) {
|
|
|
|
// HomeDirSecurity
|
|
rc = ConvertSecurityDescriptorToText(
|
|
pProfile->pHomeDirSecurity,
|
|
pProfile->HomeSeInfo,
|
|
&Strvalue,
|
|
(PULONG)&Keysize
|
|
);
|
|
if ( rc == NO_ERROR ) {
|
|
EachSize[i] = Keysize + 21;
|
|
EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"HomeDirSecurity = \"%s\"", Strvalue);
|
|
EachLine[i][EachSize[i]-1] = L'\0';
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADD,
|
|
L"HomeDirSecurity",
|
|
InfSectionName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
}
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( pProfile->pTempDirSecurity != NULL ) {
|
|
|
|
// TempDirSecurity
|
|
rc = ConvertSecurityDescriptorToText(
|
|
pProfile->pTempDirSecurity,
|
|
pProfile->TempSeInfo,
|
|
&Strvalue,
|
|
(PULONG)&Keysize
|
|
);
|
|
if ( rc == NO_ERROR ) {
|
|
EachSize[i] = Keysize + 21;
|
|
EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
|
|
if ( EachLine[i] != NULL ) {
|
|
swprintf(EachLine[i], L"TempDirSecurity = \"%s\"", Strvalue);
|
|
EachLine[i][EachSize[i]-1] = L'\0';
|
|
} else
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
|
|
ScepFree(Strvalue);
|
|
Strvalue = NULL;
|
|
|
|
} else {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_ADDTO,
|
|
L"TempDirSecurity",
|
|
InfSectionName
|
|
);
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
}
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
TotalSize += EachSize[i]+1;
|
|
i++;
|
|
|
|
}
|
|
|
|
//
|
|
// write to this profile's section
|
|
//
|
|
|
|
rc = SceInfpWriteInfSection(
|
|
InfProfileName,
|
|
InfSectionName,
|
|
TotalSize+1,
|
|
EachLine,
|
|
&EachSize[0],
|
|
0,
|
|
i-1,
|
|
Errlog
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
goto Done;
|
|
|
|
Done:
|
|
|
|
if ( InfSectionName != NULL )
|
|
ScepFree(InfSectionName);
|
|
|
|
if ( Strvalue != NULL )
|
|
ScepFree(Strvalue);
|
|
|
|
for ( i=0; i<12; i++ )
|
|
if ( EachLine[i] != NULL )
|
|
ScepFree(EachLine[i]);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
LONG
|
|
SceInfpConvertMultiSZToString(
|
|
IN PCWSTR KeyText,
|
|
IN UNICODE_STRING Fields,
|
|
OUT PWSTR *Strvalue,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine converts names in a unicode string in Multi-SZ format
|
|
(separated by NULLs) to comma delimited string. The format of the
|
|
returned string is KeyText = f1,f2,f3,f4... where f1..fn are names
|
|
in the unicode string.
|
|
|
|
Arguments:
|
|
|
|
KeyText - a string represents the key (left side of the = sign)
|
|
|
|
Fields - The Multi-SZ string
|
|
|
|
Strvalue - The output string
|
|
|
|
Errlog - The error list
|
|
|
|
Return value:
|
|
|
|
Length of the output string if successful. -1 if error.
|
|
|
|
-- */
|
|
{
|
|
DWORD TotalSize;
|
|
DWORD Strsize;
|
|
PWSTR pTemp = NULL;
|
|
PWSTR pField=NULL;
|
|
|
|
//
|
|
// The format of the string is
|
|
// KeyText = f1,f2,f3,....
|
|
//
|
|
|
|
Strsize = 3 + wcslen(KeyText);
|
|
TotalSize = Fields.Length/2 + Strsize;
|
|
|
|
*Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
|
|
if ( *Strvalue == NULL ) {
|
|
return(-1);
|
|
}
|
|
|
|
swprintf(*Strvalue, L"%s = ", KeyText);
|
|
pTemp = *Strvalue + Strsize;
|
|
pField = Fields.Buffer;
|
|
|
|
while ( pField != NULL && pField[0] ) {
|
|
wcscpy(pTemp, pField);
|
|
Strsize = wcslen(pField);
|
|
pField += Strsize+1;
|
|
pTemp += Strsize;
|
|
*pTemp = L',';
|
|
pTemp++;
|
|
}
|
|
*(pTemp-1) = L'\0';
|
|
*pTemp = L'\0';
|
|
|
|
return(TotalSize-1);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
ScepAllocateAndCopy(
|
|
OUT PWSTR *Buffer,
|
|
OUT PDWORD BufSize,
|
|
IN DWORD MaxSize,
|
|
IN PWSTR SrcBuf
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return value:
|
|
|
|
-- */
|
|
{
|
|
*BufSize = 0;
|
|
|
|
*Buffer = (PWSTR)ScepAlloc( (UINT)0, MaxSize*sizeof(WCHAR));
|
|
if ( *Buffer == NULL ) {
|
|
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
|
}
|
|
wcscpy(*Buffer, SrcBuf);
|
|
*BufSize = wcslen(*Buffer);
|
|
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpBreakTextIntoMultiFields(
|
|
IN PWSTR szText,
|
|
IN DWORD dLen,
|
|
OUT LPDWORD pnFields,
|
|
OUT LPDWORD *arrOffset
|
|
)
|
|
/*
|
|
If the text length is greater than MAX_STRING_LENGTH-1, this routine will
|
|
find out how many "blocks" the text can be break into (each block is less
|
|
than MAX_STRING_LENGTH-1), and the starting offsets of each block.
|
|
|
|
Setupapi has string length limit of MAX_STRING_LENGTH per field in a inf
|
|
file. SCE use setupapi to parse security templates which contain security
|
|
descriptors in text format which can have unlimited aces. So when SCE saves
|
|
text format of security descriptors into a inf file, it will break the text
|
|
into multiple fields if the length is over limit. Setupapi does not have
|
|
limit on number of fields per line.
|
|
|
|
The break point occurs when the following characters are encountered in the
|
|
text: ) ( ; " or space
|
|
|
|
*/
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
DWORD nFields;
|
|
DWORD nProc;
|
|
DWORD * newBuffer=NULL;
|
|
DWORD i;
|
|
|
|
if ( !pnFields || !arrOffset ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
*pnFields = 0;
|
|
*arrOffset = NULL;
|
|
|
|
if ( !szText || dLen == 0 ) {
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
//
|
|
// initialize one field always
|
|
//
|
|
nFields = 1;
|
|
*arrOffset = (DWORD *)ScepAlloc(0, nFields*sizeof(DWORD));
|
|
|
|
if ( *arrOffset ) {
|
|
(*arrOffset)[0] = 0;
|
|
|
|
if ( dLen > MAX_STRING_LENGTH-1 ) {
|
|
//
|
|
// loop through the text
|
|
//
|
|
nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
|
|
|
|
while ( SCESTATUS_SUCCESS == rc && nProc < dLen ) {
|
|
|
|
while ( nProc > (*arrOffset)[nFields-1] ) {
|
|
//
|
|
// looking for the break point
|
|
//
|
|
if ( L')' == *(szText+nProc) ||
|
|
L'(' == *(szText+nProc) ||
|
|
L';' == *(szText+nProc) ||
|
|
L' ' == *(szText+nProc) ||
|
|
L'\"' == *(szText+nProc) ) {
|
|
|
|
break;
|
|
} else {
|
|
nProc--;
|
|
}
|
|
}
|
|
if ( nProc <= (*arrOffset)[nFields-1] ) {
|
|
//
|
|
// no break point found, then just use MAX_STRING_LENGTH-2
|
|
//
|
|
nProc = (*arrOffset)[nFields-1]+MAX_STRING_LENGTH-2;
|
|
|
|
} else {
|
|
//
|
|
// else find a break poin at offset nProc, the next block
|
|
// starts at nProc+1
|
|
//
|
|
nProc++;
|
|
}
|
|
|
|
nFields++;
|
|
newBuffer = (DWORD *)ScepAlloc( 0, nFields*sizeof(DWORD));
|
|
|
|
if ( newBuffer ) {
|
|
|
|
for ( i=0; i<nFields-1; i++ ) {
|
|
newBuffer[i] = (*arrOffset)[i];
|
|
}
|
|
ScepFree(*arrOffset);
|
|
//
|
|
// set the offset to the last element
|
|
//
|
|
newBuffer[nFields-1] = nProc;
|
|
*arrOffset = newBuffer;
|
|
|
|
nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
}
|
|
|
|
}
|
|
*pnFields = nFields;
|
|
|
|
} else {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS != rc ) {
|
|
//
|
|
// if error occurs, free memory and clear the output buffer
|
|
//
|
|
*pnFields = 0;
|
|
if ( *arrOffset ) {
|
|
ScepFree(*arrOffset);
|
|
}
|
|
*arrOffset = NULL;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteKerberosPolicy(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_KERBEROS_TICKET_INFO pKerberosInfo,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine writes kerberos policy settings information to the INF file
|
|
in section [Kerberos Policy].
|
|
|
|
Arguments:
|
|
|
|
ProfileName - The profile to write to
|
|
|
|
pKerberosInfo - the Kerberos policy info (SCP) to write.
|
|
|
|
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_CORRUPT_PROFILE
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
--*/
|
|
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
|
|
SCE_KEY_LOOKUP AccessSCPLookup[] = {
|
|
{(PWSTR)TEXT("MaxTicketAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxTicketAge), 'D'},
|
|
{(PWSTR)TEXT("MaxRenewAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxRenewAge), 'D'},
|
|
{(PWSTR)TEXT("MaxServiceAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxServiceAge), 'D'},
|
|
{(PWSTR)TEXT("MaxClockSkew"),offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxClockSkew), 'D'},
|
|
{(PWSTR)TEXT("TicketValidateClient"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, TicketValidateClient), 'D'}
|
|
};
|
|
|
|
DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
|
|
|
|
DWORD i, j;
|
|
PWSTR EachLine[10] = {0};
|
|
DWORD EachSize[10] = {0};
|
|
UINT Offset;
|
|
DWORD Len;
|
|
DWORD Value;
|
|
DWORD TotalSize=0;
|
|
|
|
|
|
if (!ProfileName ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( !pKerberosInfo ) {
|
|
//
|
|
// if no kerberos information to write, just return success
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
szKerberosPolicy,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
for ( i=0, j=0; i<cAccess; i++) {
|
|
|
|
//
|
|
// get settings in AccessLookup table
|
|
//
|
|
|
|
Offset = AccessSCPLookup[i].Offset;
|
|
|
|
Value = 0;
|
|
Len = wcslen(AccessSCPLookup[i].KeyString);
|
|
|
|
switch ( AccessSCPLookup[i].BufferType ) {
|
|
case 'D':
|
|
|
|
//
|
|
// Int Field
|
|
//
|
|
Value = *((DWORD *)((CHAR *)pKerberosInfo+Offset));
|
|
if ( Value != SCE_NO_VALUE ) {
|
|
EachSize[j] = Len+15;
|
|
}
|
|
break;
|
|
default:
|
|
//
|
|
// should not occur
|
|
//
|
|
break;
|
|
}
|
|
|
|
if ( EachSize[j] <= 0 )
|
|
continue;
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
Len=(EachSize[j]+1)*sizeof(WCHAR);
|
|
|
|
EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
|
|
if ( EachLine[j] == NULL ) {
|
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|
goto Done;
|
|
}
|
|
|
|
if ( AccessSCPLookup[i].BufferType == 'D' ) {
|
|
swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
|
|
EachSize[j] = wcslen(EachLine[j]);
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// in append mode, write one string at a time
|
|
//
|
|
|
|
ScepWriteOneIntValueToProfile(
|
|
ProfileName,
|
|
szKerberosPolicy,
|
|
AccessSCPLookup[i].KeyString,
|
|
Value
|
|
);
|
|
}
|
|
|
|
TotalSize += EachSize[j]+1;
|
|
j++;
|
|
|
|
}
|
|
|
|
//
|
|
// writes the profile section
|
|
//
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
if ( j > 0 ) {
|
|
|
|
rc = SceInfpWriteInfSection(
|
|
ProfileName,
|
|
szKerberosPolicy,
|
|
TotalSize+1,
|
|
EachLine,
|
|
&EachSize[0],
|
|
0,
|
|
j-1,
|
|
Errlog
|
|
);
|
|
} else {
|
|
|
|
WritePrivateProfileSection(
|
|
szKerberosPolicy,
|
|
NULL,
|
|
ProfileName);
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
for ( i=0; i<cAccess; i++ ) {
|
|
|
|
if ( EachLine[i] != NULL ) {
|
|
ScepFree(EachLine[i]);
|
|
}
|
|
|
|
EachLine[i] = NULL;
|
|
EachSize[i] = 0;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
SceInfpWriteRegistryValues(
|
|
IN PCWSTR ProfileName,
|
|
IN PSCE_REGISTRY_VALUE_INFO pRegValues,
|
|
IN DWORD ValueCount,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine writes registry values to the INF file in section
|
|
[Registry Values].
|
|
|
|
Arguments:
|
|
|
|
ProfileName - The profile to write to
|
|
|
|
pRegValues - the registry values to write (in the format of ValueName=Value)
|
|
|
|
ValueCount - the number of values to write
|
|
|
|
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_CORRUPT_PROFILE
|
|
SCESTATUS_INVALID_DATA
|
|
|
|
--*/
|
|
|
|
{
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
PSCE_NAME_LIST pNameList=NULL;
|
|
DWORD TotalSize=0;
|
|
DWORD i, ObjectSize;
|
|
|
|
|
|
if (!ProfileName ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ( !pRegValues || 0 == ValueCount ) {
|
|
//
|
|
// if no value to write, just return success
|
|
// empty the section in the file
|
|
//
|
|
if ( bOverwrite ) {
|
|
WritePrivateProfileString(
|
|
szRegistryValues,
|
|
NULL,
|
|
NULL,
|
|
ProfileName
|
|
);
|
|
}
|
|
return(SCESTATUS_SUCCESS);
|
|
}
|
|
|
|
for ( i=0; i<ValueCount; i++) {
|
|
|
|
//
|
|
// Get string fields. Don't care the key name or if it exist.
|
|
// Must have 3 fields each line.
|
|
//
|
|
rc = SceInfpWriteOneValue(
|
|
ProfileName,
|
|
pRegValues[i],
|
|
bOverwrite,
|
|
&pNameList,
|
|
&ObjectSize
|
|
);
|
|
if ( rc != SCESTATUS_SUCCESS ) {
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
pRegValues[i].FullValueName
|
|
);
|
|
goto Done;
|
|
}
|
|
TotalSize += ObjectSize + 1;
|
|
}
|
|
|
|
//
|
|
// write to this profile's section
|
|
//
|
|
|
|
if ( bOverwrite ) {
|
|
rc = SceInfpWriteListSection(
|
|
ProfileName,
|
|
szRegistryValues,
|
|
TotalSize+1,
|
|
pNameList,
|
|
0,
|
|
Errlog
|
|
);
|
|
|
|
if ( rc != SCESTATUS_SUCCESS )
|
|
ScepBuildErrorLogInfo(
|
|
rc,
|
|
Errlog,
|
|
SCEERR_WRITE_INFO,
|
|
szRegistryValues
|
|
);
|
|
}
|
|
|
|
Done:
|
|
|
|
ScepFreeNameList(pNameList);
|
|
|
|
rc = ScepDosErrorToSceStatus(rc);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
SceInfpWriteOneValue(
|
|
IN PCWSTR ProfileName,
|
|
IN SCE_REGISTRY_VALUE_INFO RegValue,
|
|
IN BOOL bOverwrite,
|
|
OUT PSCE_NAME_LIST *pNameList,
|
|
OUT PDWORD ObjectSize
|
|
)
|
|
/* ++
|
|
Routine Description:
|
|
|
|
This routine builds registry valueName=value for one registry value
|
|
into the name list. Each value represents one line in the INF file.
|
|
|
|
Arguments:
|
|
|
|
RegValue - The registry value name and the value
|
|
|
|
pNameList - The output string list.
|
|
|
|
ObjectSize - size of this line
|
|
|
|
Return value:
|
|
|
|
SCESTATUS - SCESTATUS_SUCCESS
|
|
SCESTATUS_NOT_ENOUGH_RESOURCE
|
|
SCESTATUS_INVALID_PARAMETER
|
|
SCESTATUS_BAD_FORMAT
|
|
SCESTATUS_INVALID_DATA
|
|
-- */
|
|
{
|
|
DWORD rc=ERROR_SUCCESS;
|
|
PWSTR OneLine;
|
|
|
|
|
|
if ( !pNameList || !ObjectSize ) {
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
*ObjectSize = 0;
|
|
|
|
if ( RegValue.FullValueName && RegValue.Value ) {
|
|
|
|
if ( bOverwrite ) {
|
|
*ObjectSize = wcslen(RegValue.FullValueName);
|
|
}
|
|
|
|
if ( RegValue.ValueType == REG_SZ ||
|
|
RegValue.ValueType == REG_EXPAND_SZ ) {
|
|
// need to add "" around the string
|
|
*ObjectSize += (5+wcslen(RegValue.Value));
|
|
} else {
|
|
//
|
|
// to be safe, add more spaces to the buffer
|
|
// because ValueType can be "-1" now
|
|
//
|
|
*ObjectSize += (6+wcslen(RegValue.Value));
|
|
}
|
|
|
|
OneLine = (PWSTR)ScepAlloc(0, (*ObjectSize+1)*sizeof(WCHAR));
|
|
|
|
if ( OneLine ) {
|
|
|
|
if ( bOverwrite ) {
|
|
if ( RegValue.ValueType == REG_SZ ||
|
|
RegValue.ValueType == REG_EXPAND_SZ ) {
|
|
swprintf(OneLine, L"%s=%1d,\"%s\"\0", RegValue.FullValueName,
|
|
RegValue.ValueType, RegValue.Value);
|
|
} else {
|
|
swprintf(OneLine, L"%s=%1d,%s\0", RegValue.FullValueName,
|
|
RegValue.ValueType, RegValue.Value);
|
|
}
|
|
} else {
|
|
|
|
if ( RegValue.ValueType == REG_SZ ||
|
|
RegValue.ValueType == REG_EXPAND_SZ ) {
|
|
swprintf(OneLine, L"%1d,\"%s\"\0", RegValue.ValueType, RegValue.Value);
|
|
} else {
|
|
swprintf(OneLine, L"%1d,%s\0", RegValue.ValueType, RegValue.Value);
|
|
}
|
|
}
|
|
OneLine[*ObjectSize] = L'\0';
|
|
|
|
if ( bOverwrite ) {
|
|
|
|
rc = ScepAddToNameList(pNameList, OneLine, *ObjectSize);
|
|
|
|
} else {
|
|
//
|
|
// append mode, write one value at a time
|
|
//
|
|
WritePrivateProfileString( szRegistryValues,
|
|
RegValue.FullValueName,
|
|
OneLine,
|
|
ProfileName
|
|
);
|
|
}
|
|
|
|
ScepFree(OneLine);
|
|
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
|
|
SCESTATUS
|
|
WINAPI
|
|
SceSvcSetInformationTemplate(
|
|
IN PCWSTR TemplateName,
|
|
IN PCWSTR ServiceName,
|
|
IN BOOL bExact,
|
|
IN PSCESVC_CONFIGURATION_INFO ServiceInfo
|
|
)
|
|
/*
|
|
Routine Description:
|
|
|
|
Writes information to the template in section <ServiceName>. The information is
|
|
stored in ServiceInfo in the format of Key and Value. If bExact is set, only
|
|
exact matched keys are overwritten, else all section is overwritten by the info
|
|
in ServiceInfo.
|
|
|
|
When ServiceInfo is NULL and bExact is set, delete the entire section
|
|
|
|
Arguments:
|
|
|
|
TemplateName - the inf template name to write to
|
|
|
|
ServiceName - the section name to write to
|
|
|
|
bExact - TRUE = all existing information in the section is erased
|
|
|
|
ServiceInfo - the information to write
|
|
|
|
Return Value:
|
|
|
|
SCE status of this operation
|
|
*/
|
|
{
|
|
if ( TemplateName == NULL || ServiceName == NULL ||
|
|
(ServiceInfo == NULL && !bExact ) ) {
|
|
return(SCESTATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
DWORD i;
|
|
|
|
if ( ServiceInfo != NULL ) {
|
|
|
|
for ( i=0; i<ServiceInfo->Count; i++ ) {
|
|
if ( ServiceInfo->Lines[i].Key == NULL ) {
|
|
|
|
return(SCESTATUS_INVALID_DATA);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// always write [Version] section.
|
|
//
|
|
WCHAR tmp[64];
|
|
memset(tmp, 0, 64*2);
|
|
wcscpy(tmp, L"signature=\"$CHICAGO$\"");
|
|
swprintf(tmp+wcslen(tmp)+1,L"Revision=%d\0\0",
|
|
SCE_TEMPLATE_MAX_SUPPORTED_VERSION);
|
|
|
|
WritePrivateProfileSection(
|
|
L"Version",
|
|
tmp,
|
|
TemplateName);
|
|
|
|
SCESTATUS rc=SCESTATUS_SUCCESS;
|
|
|
|
if ( (bExact && ServiceInfo == NULL) || !bExact ) {
|
|
//
|
|
// delete the entire section
|
|
//
|
|
if ( !WritePrivateProfileString(ServiceName, NULL, NULL, TemplateName) ) {
|
|
rc = ScepDosErrorToSceStatus(GetLastError());
|
|
}
|
|
}
|
|
|
|
if ( ServiceInfo == NULL ) {
|
|
return(rc);
|
|
}
|
|
|
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|
//
|
|
// process each key/value in ServiceInfo
|
|
//
|
|
for ( i=0; i<ServiceInfo->Count; i++ ) {
|
|
if ( !WritePrivateProfileString(ServiceName,
|
|
ServiceInfo->Lines[i].Key,
|
|
ServiceInfo->Lines[i].Value,
|
|
TemplateName
|
|
) ) {
|
|
|
|
rc = ScepDosErrorToSceStatus(GetLastError());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// need to recover the crash - WMI
|
|
//
|
|
return(rc);
|
|
|
|
}
|
|
|
|
DWORD
|
|
ScepWritePrivateProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPTSTR pData,
|
|
IN LPCWSTR FileName,
|
|
IN BOOL bOverwrite)
|
|
/*
|
|
Description:
|
|
|
|
This function is to provide the same function as WritePrivateProfileSection
|
|
and exceed the 32K limit of that function.
|
|
|
|
If the file doesn't exist, the file is always created in UNICODE.
|
|
|
|
If the file does exist and it's in UNICODE format (the first two bytes are
|
|
0xFF, 0xFE), the data will be saved to the file in UNICODE.
|
|
|
|
If the file does exist and it's in ANSI format, the data will be saved to
|
|
the file in ANSI format.
|
|
|
|
Note, this function assumes that the file is exclusively accessed. It's not
|
|
an atomic operation as WritePrivateProfileSection. But since this is a
|
|
private function implemented for SCE only and SCE always uses temporary
|
|
files (exclusive for each client), there is no problem doing this way.
|
|
|
|
Note 2, new data section is always added to the end of the file. Existing
|
|
data in the section will be moved to the end of the file as well.
|
|
|
|
Arguments:
|
|
|
|
SectionName - the section name to write data to
|
|
|
|
FileName - the full path file name to write data to
|
|
|
|
pData - data in MULTI-SZ format (with no size limit)
|
|
|
|
bOverwrite - TRUE=data will overwrite entire section in the file
|
|
|
|
*/
|
|
{
|
|
if ( SectionName == NULL || FileName == NULL ) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
DWORD rc=ERROR_SUCCESS;
|
|
|
|
//
|
|
// check to see if the file exist
|
|
//
|
|
if ( 0xFFFFFFFF != GetFileAttributes(FileName) ) {
|
|
|
|
//
|
|
// file eixsts.
|
|
//
|
|
if ( !bOverwrite && pData != NULL ) {
|
|
//
|
|
// Need to check if the same section exists and if so
|
|
// append the data
|
|
//
|
|
rc = ScepAppendProfileSection(SectionName, FileName, pData);
|
|
|
|
} else {
|
|
|
|
//
|
|
// the existint data, if any, is not interesting. delete it
|
|
// if the section does not exist at all, the next call won't fail
|
|
//
|
|
if ( !WritePrivateProfileSection(
|
|
SectionName,
|
|
NULL,
|
|
FileName
|
|
) ) {
|
|
rc = GetLastError();
|
|
|
|
} else if ( pData ) {
|
|
//
|
|
// now write the new data in
|
|
//
|
|
rc = ScepOverwriteProfileSection(SectionName,
|
|
FileName,
|
|
pData,
|
|
SCEP_PROFILE_WRITE_SECTIONNAME,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
} else if ( pData ) {
|
|
|
|
//
|
|
// the file does not exist, no need to empty existing data
|
|
//
|
|
rc = ScepOverwriteProfileSection(SectionName,
|
|
FileName,
|
|
pData,
|
|
SCEP_PROFILE_WRITE_SECTIONNAME,
|
|
NULL);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
DWORD
|
|
ScepAppendProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPCWSTR FileName,
|
|
IN LPTSTR pData
|
|
)
|
|
/*
|
|
Description:
|
|
|
|
Append the data to the section if the section exists, otherwise, create
|
|
the section and add data to it.
|
|
|
|
Arguments:
|
|
|
|
SectionName - the section name
|
|
|
|
FileName - the file name
|
|
|
|
pData - the data to append
|
|
|
|
*/
|
|
{
|
|
|
|
DWORD rc=ERROR_SUCCESS;
|
|
DWORD dwSize;
|
|
PWSTR lpExisting = NULL;
|
|
WCHAR szBuffer[256];
|
|
DWORD nSize=256;
|
|
BOOL bSection=TRUE;
|
|
|
|
lpExisting = szBuffer;
|
|
szBuffer[0] = L'\0';
|
|
szBuffer[1] = L'\0';
|
|
|
|
PSCEP_SPLAY_TREE pKeys=NULL;
|
|
|
|
do {
|
|
//
|
|
// check if the section already exist
|
|
//
|
|
dwSize = GetPrivateProfileSection(SectionName, lpExisting, nSize, FileName );
|
|
|
|
if ( dwSize == 0 ) {
|
|
//
|
|
// either failed or the section does not exist
|
|
//
|
|
rc = GetLastError();
|
|
|
|
if ( ERROR_FILE_NOT_FOUND == rc ) {
|
|
//
|
|
// the file or section does not exist
|
|
//
|
|
rc = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
} else if ( dwSize < nSize - 2 ) {
|
|
//
|
|
// data get copied ok because the whole buffer is filled
|
|
//
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// buffer is not big enough, reallocate heap
|
|
//
|
|
if ( lpExisting && lpExisting != szBuffer ) {
|
|
LocalFree(lpExisting);
|
|
}
|
|
|
|
nSize += 256;
|
|
lpExisting = (PWSTR)LocalAlloc(LPTR, nSize*sizeof(TCHAR));
|
|
|
|
if ( lpExisting == NULL ) {
|
|
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
} while ( rc == ERROR_SUCCESS );
|
|
|
|
|
|
if ( ERROR_SUCCESS == rc && lpExisting[0] != L'\0') {
|
|
|
|
//
|
|
// now delete the existing section (to make sure the section will
|
|
// always be at the end)
|
|
//
|
|
|
|
if ( !WritePrivateProfileSection(
|
|
SectionName,
|
|
NULL,
|
|
FileName
|
|
) ) {
|
|
//
|
|
// fail to delete the section
|
|
//
|
|
rc = GetLastError();
|
|
|
|
} else {
|
|
|
|
//
|
|
// save the new data first
|
|
//
|
|
pKeys = ScepSplayInitialize(SplayNodeStringType);
|
|
|
|
rc = ScepOverwriteProfileSection(SectionName,
|
|
FileName,
|
|
pData,
|
|
SCEP_PROFILE_WRITE_SECTIONNAME |
|
|
SCEP_PROFILE_GENERATE_KEYS,
|
|
pKeys
|
|
);
|
|
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
//
|
|
// now append the old data and check for duplicate
|
|
//
|
|
rc = ScepOverwriteProfileSection(SectionName,
|
|
FileName,
|
|
lpExisting,
|
|
SCEP_PROFILE_CHECK_DUP,
|
|
pKeys
|
|
);
|
|
}
|
|
|
|
if ( pKeys ) {
|
|
|
|
ScepSplayFreeTree( &pKeys, TRUE );
|
|
}
|
|
|
|
}
|
|
|
|
} else if ( ERROR_SUCCESS == rc ) {
|
|
|
|
//
|
|
// now write the new data
|
|
//
|
|
rc = ScepOverwriteProfileSection(SectionName,
|
|
FileName,
|
|
pData,
|
|
SCEP_PROFILE_WRITE_SECTIONNAME,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
//
|
|
// free existing data buffer
|
|
//
|
|
if ( lpExisting && (lpExisting != szBuffer) ) {
|
|
LocalFree(lpExisting);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepOverwriteProfileSection(
|
|
IN LPCWSTR SectionName,
|
|
IN LPCWSTR FileName,
|
|
IN LPTSTR pData,
|
|
IN DWORD dwFlags,
|
|
IN OUT PSCEP_SPLAY_TREE pKeys OPTIONAL
|
|
)
|
|
/*
|
|
Description:
|
|
|
|
Writes data to the section. Old data in the section will be overwritten.
|
|
|
|
Arguments:
|
|
|
|
SectionName - section name to write to
|
|
|
|
FileName - file name
|
|
|
|
pData - data to write
|
|
|
|
dwFlags - flags (write section name, generate keys, check duplicate)
|
|
|
|
pKeys - the keys to generate or check duplicate
|
|
*/
|
|
{
|
|
|
|
DWORD rc=ERROR_SUCCESS;
|
|
HANDLE hFile=INVALID_HANDLE_VALUE;
|
|
BOOL bUnicode;
|
|
DWORD dwBytesWritten;
|
|
|
|
//
|
|
// try create the new file
|
|
//
|
|
hFile = CreateFile(FileName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
//
|
|
// this is a new file, created successfully.
|
|
// now make it UNICODE
|
|
//
|
|
BYTE tmpBuf[3];
|
|
tmpBuf[0] = 0xFF;
|
|
tmpBuf[1] = 0xFE;
|
|
tmpBuf[2] = 0;
|
|
|
|
if ( !WriteFile (hFile, (LPCVOID)tmpBuf, 2,
|
|
&dwBytesWritten,
|
|
NULL) )
|
|
{
|
|
CloseHandle (hFile);
|
|
return GetLastError();
|
|
}
|
|
|
|
bUnicode = TRUE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// open the file exclusively
|
|
//
|
|
|
|
hFile = CreateFile(FileName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
|
|
SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
|
|
|
|
//
|
|
// check the first byte of the file to see if it's UNICODE
|
|
//
|
|
BYTE tmpBytes[3];
|
|
tmpBytes[0] = 0;
|
|
tmpBytes[1] = 0;
|
|
|
|
if ( ReadFile(hFile, (LPVOID)tmpBytes, 2, &dwBytesWritten, NULL ) &&
|
|
dwBytesWritten == 2 ) {
|
|
|
|
if ( tmpBytes[0] == 0xFF && tmpBytes[1] == 0xFE ) {
|
|
bUnicode = TRUE;
|
|
} else {
|
|
bUnicode = FALSE;
|
|
}
|
|
} else {
|
|
//
|
|
// if fails to verify the file, assume it's UNICODE
|
|
//
|
|
bUnicode = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
PWSTR pKeyStr=NULL;
|
|
BOOL bSkipGenKey = FALSE;
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
|
|
SetFilePointer (hFile, 0, NULL, FILE_END);
|
|
|
|
if ( dwFlags & SCEP_PROFILE_WRITE_SECTIONNAME ) {
|
|
//
|
|
// save the section name first
|
|
//
|
|
rc = ScepWriteStrings(hFile, bUnicode, L"[", 1, (PWSTR)SectionName, 0, L"]", 1, TRUE);
|
|
}
|
|
|
|
if(( 0 == wcscmp(SectionName, szFileSecurity)) ||
|
|
( 0 == wcscmp(SectionName, szRegistryKeys)) ||
|
|
( 0 == wcscmp(SectionName, szServiceGeneral)) ){
|
|
|
|
bSkipGenKey = TRUE;
|
|
|
|
}
|
|
|
|
if ( ERROR_SUCCESS == rc ) {
|
|
|
|
LPTSTR pTemp=pData;
|
|
LPTSTR pTemp1=pData;
|
|
BOOL bExists, bKeyCopied;
|
|
DWORD rc1;
|
|
DWORD Len;
|
|
|
|
//
|
|
// write each string in the MULTI-SZ string separately, with a \r\n
|
|
//
|
|
while ( *pTemp1 ) {
|
|
|
|
//
|
|
// count to the \0
|
|
//
|
|
bKeyCopied = FALSE;
|
|
if ( pKeyStr ) {
|
|
LocalFree(pKeyStr);
|
|
pKeyStr = NULL;
|
|
}
|
|
|
|
while (*pTemp) {
|
|
if ( pKeys &&
|
|
( (dwFlags & SCEP_PROFILE_GENERATE_KEYS) ||
|
|
(dwFlags & SCEP_PROFILE_CHECK_DUP) ) &&
|
|
!bKeyCopied &&
|
|
(*pTemp == L'=' || *pTemp == L',') ) {
|
|
|
|
if(bSkipGenKey && *pTemp == L'='){
|
|
|
|
pTemp1 = ++pTemp;
|
|
continue;
|
|
|
|
}
|
|
//
|
|
// there is a key to remember
|
|
//
|
|
Len = (DWORD)(pTemp-pTemp1);
|
|
|
|
pKeyStr = (PWSTR)ScepAlloc(LPTR, (Len+1)*sizeof(WCHAR));
|
|
if ( pKeyStr ) {
|
|
wcsncpy(pKeyStr, pTemp1, pTemp-pTemp1);
|
|
bKeyCopied = TRUE;
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
pTemp++;
|
|
}
|
|
|
|
if ( ERROR_SUCCESS != rc )
|
|
break;
|
|
|
|
if ( bKeyCopied ) {
|
|
|
|
if ( dwFlags & SCEP_PROFILE_GENERATE_KEYS ) {
|
|
//
|
|
// add it to the splay list
|
|
//
|
|
|
|
rc1 = ScepSplayInsert( (PVOID)pKeyStr, pKeys, &bExists );
|
|
|
|
} else if ( dwFlags & SCEP_PROFILE_CHECK_DUP ) {
|
|
//
|
|
// check if the key already exists in the splay list
|
|
//
|
|
if ( ScepSplayValueExist( (PVOID)pKeyStr, pKeys) ) {
|
|
//
|
|
// this is a duplicate entry, continue
|
|
//
|
|
pTemp++;
|
|
pTemp1 = pTemp;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Len = (DWORD)(pTemp-pTemp1);
|
|
|
|
rc = ScepWriteStrings(hFile,
|
|
bUnicode, // write it in UNICODE or ANSI
|
|
NULL, // no prefix
|
|
0,
|
|
pTemp1, // the string
|
|
Len,
|
|
NULL, // no suffix
|
|
0,
|
|
TRUE // add \r\n
|
|
);
|
|
|
|
if ( ERROR_SUCCESS != rc )
|
|
break;
|
|
|
|
pTemp++;
|
|
pTemp1 = pTemp;
|
|
}
|
|
}
|
|
|
|
CloseHandle (hFile);
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
}
|
|
|
|
if ( pKeyStr ) {
|
|
LocalFree(pKeyStr);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ScepWriteStrings(
|
|
IN HANDLE hFile,
|
|
IN BOOL bUnicode,
|
|
IN PWSTR szPrefix OPTIONAL,
|
|
IN DWORD dwPrefixLen,
|
|
IN PWSTR szString,
|
|
IN DWORD dwStrLen,
|
|
IN PWSTR szSuffix OPTIONAL,
|
|
IN DWORD dwSuffixLen,
|
|
IN BOOL bCRLF
|
|
)
|
|
/*
|
|
Description:
|
|
|
|
Write data to the file. Data can have prefix and/or suffix, and followed
|
|
by a \r\n optionally.
|
|
|
|
Data will be write in UNICODE or ANSI format based on the input paramter
|
|
bUnicode. If ANSI format is desired, the wide chars are converted to
|
|
multi-byte buffers then write to the file.
|
|
|
|
Arguments:
|
|
|
|
hFile - file handle
|
|
|
|
bUnicode - the file format (UNICODE=TRUE or ANSI=FALSE)
|
|
|
|
szPrefix - the optional prefix string
|
|
|
|
dwPrefixLen - the optional prefix string length (in wchars)
|
|
|
|
szString - the string to write
|
|
|
|
dwStrLen - the string length
|
|
|
|
szSuffix - the optional suffix string
|
|
|
|
dwSuffixLen - the optional suffix string length (in wchars)
|
|
|
|
bCRLF - if \r\n should be added
|
|
|
|
*/
|
|
{
|
|
DWORD rc=ERROR_SUCCESS;
|
|
PWSTR pwBuffer=NULL;
|
|
DWORD dwTotal=0;
|
|
PVOID pBuf=NULL;
|
|
PCHAR pStr=NULL;
|
|
DWORD dwBytes=0;
|
|
|
|
//
|
|
// validate parameters
|
|
//
|
|
if ( hFile == NULL || szString == NULL ) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ( szPrefix && dwPrefixLen == 0 ) {
|
|
dwPrefixLen = wcslen(szPrefix);
|
|
}
|
|
|
|
if ( szSuffix && dwSuffixLen == 0 ) {
|
|
dwSuffixLen = wcslen(szSuffix);
|
|
}
|
|
|
|
if ( dwStrLen == 0 ) {
|
|
dwStrLen = wcslen(szString);
|
|
}
|
|
|
|
//
|
|
// get total length
|
|
//
|
|
dwTotal = dwPrefixLen + dwStrLen + dwSuffixLen;
|
|
|
|
if ( dwTotal == 0 && !bCRLF ) {
|
|
//
|
|
// nothing to write
|
|
//
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
if ( bCRLF ) {
|
|
//
|
|
// add \r\n
|
|
//
|
|
dwTotal += 2;
|
|
}
|
|
|
|
//
|
|
// allocate buffer
|
|
//
|
|
pwBuffer = (PWSTR)LocalAlloc(LPTR, (dwTotal+1)*sizeof(TCHAR));
|
|
|
|
if ( pwBuffer == NULL ) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// copy all data to the buffer
|
|
//
|
|
if ( szPrefix ) {
|
|
wcsncpy(pwBuffer, szPrefix, dwPrefixLen);
|
|
}
|
|
|
|
wcsncat(pwBuffer, szString, dwStrLen);
|
|
|
|
if ( szSuffix ) {
|
|
wcsncat(pwBuffer, szSuffix, dwSuffixLen);
|
|
}
|
|
|
|
if ( bCRLF ) {
|
|
wcscat(pwBuffer, c_szCRLF);
|
|
}
|
|
|
|
if ( !bUnicode ) {
|
|
|
|
//
|
|
// convert WCHAR into ANSI
|
|
//
|
|
dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
|
|
0,
|
|
pwBuffer,
|
|
dwTotal,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if ( dwBytes > 0 ) {
|
|
|
|
//
|
|
// allocate buffer
|
|
//
|
|
pStr = (PCHAR)LocalAlloc(LPTR, dwBytes+1);
|
|
|
|
if ( pStr == NULL ) {
|
|
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
} else {
|
|
|
|
dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
|
|
0,
|
|
pwBuffer,
|
|
dwTotal,
|
|
pStr,
|
|
dwBytes,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if ( dwBytes > 0 ) {
|
|
|
|
pBuf = (PVOID)pStr;
|
|
|
|
} else {
|
|
|
|
rc = GetLastError();
|
|
}
|
|
}
|
|
|
|
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// write in UNICODE, use the existing buffer
|
|
//
|
|
pBuf = (PVOID)pwBuffer;
|
|
dwBytes = dwTotal*sizeof(WCHAR);
|
|
}
|
|
|
|
//
|
|
// write to the file
|
|
//
|
|
DWORD dwBytesWritten=0;
|
|
|
|
if ( pBuf ) {
|
|
|
|
if ( WriteFile (hFile, (LPCVOID)pBuf, dwBytes,
|
|
&dwBytesWritten,
|
|
NULL) ) {
|
|
|
|
if ( dwBytesWritten != dwBytes ) {
|
|
//
|
|
// not all data is written
|
|
//
|
|
rc = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
}
|
|
|
|
if ( pStr ) {
|
|
LocalFree(pStr);
|
|
}
|
|
|
|
//
|
|
// free buffer
|
|
//
|
|
LocalFree(pwBuffer);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|