5529 lines
145 KiB
C++
5529 lines
145 KiB
C++
/*++
|
||
|
||
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,
|
||
FALSE,
|
||
&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];
|
||
DWORD EachSize[25];
|
||
DWORD Len;
|
||
|
||
|
||
if (ProfileName == NULL || pSCEinfo == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
for ( i=0, j=0; i<cAccess; i++) {
|
||
|
||
EachLine[i] = NULL;
|
||
EachSize[i] = 0;
|
||
|
||
//
|
||
// 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 ( ScepLookupNameTable(pGroupMembers->GroupName, &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
|
||
//
|
||
swprintf(Keyname+Len, L"%s", 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)+3 + 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\"", pService->ServiceName,
|
||
pService->Startup, SDspec);
|
||
} else {
|
||
//
|
||
// loop through the fields
|
||
//
|
||
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 {
|
||
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 ( ScepLookupNameTable(pName->Name, &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);
|
||
}
|
||
swprintf(*Buffer, L"%s", 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];
|
||
DWORD EachSize[10];
|
||
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++) {
|
||
|
||
EachLine[i] = NULL;
|
||
EachSize[i] = 0;
|
||
|
||
//
|
||
// 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) )
|
||
|
||
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;
|
||
|
||
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 ( 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',') ) {
|
||
//
|
||
// 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);
|
||
|
||
}
|
||
|