/*++ 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 #include #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; ipRegistryKeys.pAllNodes->Count; i++) { if ( InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i] == NULL ) continue; for ( j=0; jpRegistryKeys.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; ipFiles.pAllNodes->Count; i++) { if ( InfoBuffer->pFiles.pAllNodes->pObjectArray[i] == NULL ) continue; for ( j=0; jpFiles.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; iNewAdministratorName; 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; iNext) { // // 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; iCount; 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 : ,"" // *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; iName, 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 : ,"" // *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; iServiceName, 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 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; jName, 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; jDisallowPasswordChange != 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 0 ) { rc = SceInfpWriteInfSection( ProfileName, szKerberosPolicy, TotalSize+1, EachLine, &EachSize[0], 0, j-1, Errlog ); } else { WritePrivateProfileSection( szKerberosPolicy, NULL, ProfileName); } } Done: for ( i=0; i. 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; iCount; 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; iCount; 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); }