/*++ Copyright (c) 1996 Microsoft Corporation Module Name: secedit.c Abstract: Command line tool "secedit" to configure/analyze security Author: Jin Huang (jinhuang) 7-Nov-1996 --*/ // // System header files // #include #include #include #include #include #include // // CRT header files // #include #include #include #include #include #include #include #include "secedit.h" #include "scesetup.h" #include "stringid.h" //#include #include #include "userenv.h" #include #define GPT_EFS_NEW_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}") #define GPT_SCEDLL_NEW_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\{827D319E-6EAC-11D2-A4EA-00C04F79F83A}") #define SECEDITP_MAX_STRING_LENGTH 50 #define SCE_ENGINE_GENERATE 1 #define SCE_ENGINE_COMPILE 2 #define SCE_ENGINE_REGISTER 3 #define SCE_ENGINE_REFRESH 4 #define SCE_ENGINE_BROWSE 5 #define SECEDIT_DETAIL_HELP 1 #define SECEDIT_AREA_HELP 2 #define SECEDIT_OVERWRITE_HELP 4 #define SeceditpArgumentConfigure TEXT("/configure") #define SeceditpArgumentAnalyze TEXT("/analyze") #define SeceditpArgumentGenerate TEXT("/export") #define SeceditpArgumentScpPath TEXT("/CFG") #define SeceditpArgumentSadPath TEXT("/DB") #define SeceditpArgumentArea TEXT("/areas") #define SeceditpArgumentLog TEXT("/log") #define SeceditpArgumentVerbose TEXT("/verbose") #define SeceditpArgumentQuiet TEXT("/quiet") #define SeceditpArgumentAppend TEXT("/overwrite") #define SeceditpArgumentCompile TEXT("/validate") #define SeceditpArgumentRegister TEXT("/register") #define SeceditpArgumentRefresh TEXT("/RefreshPolicy") #define SeceditpArgumentMerge TEXT("/MergedPolicy") #define SeceditpArgumentEnforce TEXT("/Enforce") #define SeceditpAreaPolicy TEXT("SECURITYPOLICY") #define SeceditpAreaUser TEXT("USER_MGMT") #define SeceditpAreaGroup TEXT("GROUP_MGMT") #define SeceditpAreaRight TEXT("USER_RIGHTS") #define SeceditpAreaDsObject TEXT("DSOBJECTS") #define SeceditpAreaRegistry TEXT("REGKEYS") #define SeceditpAreaFile TEXT("FILESTORE") #define SeceditpAreaService TEXT("SERVICES") #define SCE_LOCAL_FREE(ptr) if (ptr != NULL) LocalFree(ptr) HMODULE hMod=NULL; static DWORD dOptions=0; static HANDLE hCmdToolLogFile=INVALID_HANDLE_VALUE; static PWSTR LogFile=NULL; VOID ScepPrintHelp(DWORD nLevel); WCHAR * SecEditPConvertToFullPath( WCHAR *UserFilename, DWORD *retCode ); BOOL ScepCmdToolLogInit( PWSTR logname ); VOID ScepCmdToolLogWrite( PWSTR pErrString ); SCESTATUS ScepCmdToolLogClose( ); SCESTATUS SeceditpErrOut( IN DWORD rc, IN LPTSTR buf OPTIONAL ); DWORD SeceditpSceStatusToDosError( IN SCESTATUS SceStatus ); BOOL CALLBACK SceCmdVerboseCallback( IN HANDLE CallbackHandle, IN AREA_INFORMATION Area, IN DWORD TotalTicks, IN DWORD CurrentTicks ); DWORD pProgressRoutine( IN PWSTR StringUpdate ); BOOL ScepPrintConfigureWarning(); BOOL CALLBACK pBrowseCallback( IN LONG ID, IN PWSTR KeyName OPTIONAL, IN PWSTR GpoName OPTIONAL, IN PWSTR Value OPTIONAL, IN DWORD Len ); #define SECEDIT_OPTION_DEBUG 0x01L #define SECEDIT_OPTION_VERBOSE 0x02L #define SECEDIT_OPTION_QUIET 0x04L #define SECEDIT_OPTION_OVERWRITE 0x08L #define SECEDIT_OPTION_MACHINE 0x10L #define SECEDIT_OPTION_MERGE 0x20L #define SECEDIT_OPTION_APPEND 0x40L #define SECEDIT_OPTION_ENFORCE 0x80L int __cdecl My_wprintf( const wchar_t *format, ... ); int __cdecl My_fwprintf( FILE *str, const wchar_t *format, ... ); int __cdecl My_vfwprintf( FILE *str, const wchar_t *format, va_list argptr ); int __cdecl My_printf( const char *format, ... ); int __cdecl wmain(int argc, WCHAR * argv[]) { PWSTR InfFile=NULL; // PWSTR LogFile=NULL; PWSTR SadFile=NULL; PWSTR pTemp=NULL; AREA_INFORMATION Area=AREA_ALL; SCESTATUS rc; int rCode=0; DWORD EngineType=0; LONG i; DWORD j; DWORD Len, TotalLen; BOOL bTest=FALSE; BOOL bVerbose=TRUE; BOOL bQuiet=FALSE; BOOL bAppend=TRUE; PVOID hProfile=NULL; PSCE_PROFILE_INFO ProfileInfo=NULL; PSCE_ERROR_LOG_INFO ErrBuf=NULL; PSCE_ERROR_LOG_INFO pErr; DWORD dWarning=0; WCHAR LineString[256]; WCHAR WarningStr[256]; BOOL bMachine=FALSE, bMerge=FALSE, bEnforce=FALSE; UINT rId=0; HKEY hKey=NULL, hKey1=NULL; UINT ConsoleCP; char szConsoleCP[6]; // check for /quiet and LogFile if any - set relevant flags (need this info immediately to log errors) for ( i=1; inext ) { if ( pErr->buffer != NULL ) { SeceditpErrOut( pErr->rc, pErr->buffer ); } } SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO); ErrBuf = NULL; if ( ProfileInfo != NULL ) { SceFreeMemory((PVOID)ProfileInfo, Area); LocalFree(ProfileInfo); } SceCloseProfile(&hProfile); } else { if (SCESTATUS_OTHER_ERROR == rc) { LoadString( hMod, SECEDITP_FILE_MAY_CORRUPTED, LineString, 256 ); } else { LoadString( hMod, SECEDITP_CANNOT_FIND_TEMPLATE, LineString, 256 ); } SeceditpErrOut(SeceditpSceStatusToDosError(rc), LineString); } if (SCESTATUS_NOT_ENOUGH_RESOURCE == rc || SCESTATUS_ALREADY_RUNNING == rc ) { rCode = 2; } else if ( rc ) { rCode = 1; } } else { rCode = 1; ScepPrintHelp(EngineType); goto Done; } if ( SCESTATUS_SUCCESS == rc && InfFile) { LoadString( hMod, SECEDITP_COMPILE_OK, LineString, 256 ); My_wprintf(LineString, InfFile); } break; case SCE_ENGINE_REGISTER: rc = 0; if ( InfFile != NULL ) { rc = SceRegisterRegValues(InfFile); if (ERROR_NOT_ENOUGH_MEMORY == rc ) { rCode = 2; } else if ( rc ) { rCode = 1; } } else { rCode = 1; ScepPrintHelp(EngineType); goto Done; } if ( SCESTATUS_SUCCESS == rc && InfFile) { LoadString( hMod, SECEDITP_REGISTER_OK, LineString, 256 ); My_wprintf(LineString, InfFile); } break; case SCE_ENGINE_REFRESH: break; default: rc = 0; rCode = 1; ScepPrintHelp(EngineType); break; } SetConsoleCtrlHandler(NULL, FALSE); if ( EngineType == SCE_ENGINE_SCP || EngineType == SCE_ENGINE_SAP || EngineType == SCE_ENGINE_GENERATE || EngineType == SCE_ENGINE_BROWSE ) { My_wprintf(L" \n"); if ( SCESTATUS_SUCCESS == rc ) { if ( ERROR_SUCCESS == dWarning ) { rId = SECEDITP_TASK_COMPLETE_NO_ERROR; } else { // SeceditpErrOut( dWarning, NULL); rId = SECEDITP_TASK_COMPLETE_WARNING; } } else { SeceditpErrOut( SeceditpSceStatusToDosError(rc), NULL); rId = SECEDITP_TASK_COMPLETE_ERROR; } LoadString( hMod, rId, LineString, 256 ); if ( rId == SECEDITP_TASK_COMPLETE_WARNING ) { // // explain the warnings // WarningStr[0] = L'\0'; switch ( dWarning ) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: LoadString( hMod, SECEDITP_WARNING_NOT_FOUND, WarningStr, 256 ); break; case ERROR_SHARING_VIOLATION: LoadString( hMod, SECEDITP_WARNING_IN_USE, WarningStr, 256 ); break; default: LoadString( hMod, SECEDITP_WARNING_OTHER_WARNING, WarningStr, 256 ); break; } My_wprintf(LineString, WarningStr); } else { My_wprintf(LineString); } if (bQuiet == FALSE) { if ( LogFile ) { LoadString( hMod, SECEDITP_TASK_SEE_LOG, LineString, 256 ); My_wprintf(LineString, LogFile); } else { LoadString( hMod, SECEDITP_TASK_SEE_DEF_LOG, LineString, 256 ); My_wprintf(L"%s", LineString); } } } Done: if ( dOptions & SCE_DISABLE_LOG ){ ScepCmdToolLogClose(); } SCE_LOCAL_FREE(InfFile); SCE_LOCAL_FREE(SadFile); SCE_LOCAL_FREE(LogFile); SCE_LOCAL_FREE(pTemp); FreeLibrary( hMod ); if ( rCode ) return rCode; else if ( rc ) { if (SCESTATUS_NOT_ENOUGH_RESOURCE == rc || SCESTATUS_ALREADY_RUNNING == rc ) return 2; else return 1; } else if ( dWarning ) { return 3; } else return 0; } VOID ScepPrintHelp(DWORD nLevel) { PROCESS_INFORMATION ProcInfo; STARTUPINFOA StartInfo; BOOL fOk; RtlZeroMemory(&StartInfo,sizeof(StartInfo)); StartInfo.cb = sizeof(StartInfo); StartInfo.dwFlags = STARTF_USESHOWWINDOW; StartInfo.wShowWindow = (WORD)SW_SHOWNORMAL; fOk = CreateProcessA(NULL, "hh secedit.chm", NULL, NULL, FALSE, 0, NULL, NULL, &StartInfo, &ProcInfo ); if ( fOk ) { CloseHandle(ProcInfo.hProcess); CloseHandle(ProcInfo.hThread); } } SCESTATUS SeceditpErrOut( IN DWORD rc, IN LPTSTR buf OPTIONAL ) { LPVOID lpMsgBuf=NULL; if ( rc != NO_ERROR ) { // // get error description of rc // FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL ); } // // Display to screen // if ( buf ) { if (lpMsgBuf != NULL ) My_fwprintf( stdout, L"%s %s\n", (PWSTR)lpMsgBuf, buf ); else My_fwprintf( stdout, L"%s\n", buf ); } else { if (lpMsgBuf != NULL ) My_fwprintf( stdout, L"%s\n", (PWSTR)lpMsgBuf); } SCE_LOCAL_FREE(lpMsgBuf); return(SCESTATUS_SUCCESS); } DWORD SeceditpSceStatusToDosError( IN SCESTATUS SceStatus ) // converts SCESTATUS error code to dos error defined in winerror.h { switch(SceStatus) { case SCESTATUS_SUCCESS: return(NO_ERROR); case SCESTATUS_OTHER_ERROR: return(ERROR_EXTENDED_ERROR); case SCESTATUS_INVALID_PARAMETER: return(ERROR_INVALID_PARAMETER); case SCESTATUS_RECORD_NOT_FOUND: return(ERROR_NO_MORE_ITEMS); case SCESTATUS_NO_MAPPING: return(ERROR_NONE_MAPPED); case SCESTATUS_TRUST_FAIL: return(ERROR_TRUSTED_DOMAIN_FAILURE); case SCESTATUS_INVALID_DATA: return(ERROR_INVALID_DATA); case SCESTATUS_OBJECT_EXIST: return(ERROR_FILE_EXISTS); case SCESTATUS_BUFFER_TOO_SMALL: return(ERROR_INSUFFICIENT_BUFFER); case SCESTATUS_PROFILE_NOT_FOUND: return(ERROR_FILE_NOT_FOUND); case SCESTATUS_BAD_FORMAT: return(ERROR_BAD_FORMAT); case SCESTATUS_NOT_ENOUGH_RESOURCE: return(ERROR_NOT_ENOUGH_MEMORY); case SCESTATUS_ACCESS_DENIED: return(ERROR_ACCESS_DENIED); case SCESTATUS_CANT_DELETE: return(ERROR_CURRENT_DIRECTORY); case SCESTATUS_PREFIX_OVERFLOW: return(ERROR_BUFFER_OVERFLOW); case SCESTATUS_ALREADY_RUNNING: return(ERROR_SERVICE_ALREADY_RUNNING); case SCESTATUS_SERVICE_NOT_SUPPORT: return(ERROR_NOT_SUPPORTED); case SCESTATUS_MOD_NOT_FOUND: return(ERROR_MOD_NOT_FOUND); case SCESTATUS_EXCEPTION_IN_SERVER: return(ERROR_EXCEPTION_IN_SERVICE); case SCESTATUS_JET_DATABASE_ERROR: return(ERROR_DATABASE_FAILURE); case SCESTATUS_TIMEOUT: return(ERROR_TIMEOUT); case SCESTATUS_PENDING_IGNORE: return(ERROR_IO_PENDING); case SCESTATUS_SPECIAL_ACCOUNT: return(ERROR_SPECIAL_ACCOUNT); default: return(ERROR_EXTENDED_ERROR); } } BOOL CALLBACK SceCmdVerboseCallback( IN HANDLE CallbackHandle, IN AREA_INFORMATION Area, IN DWORD TotalTicks, IN DWORD CurrentTicks ) { LPCTSTR SectionName; DWORD nProg; WCHAR LineString[256]; switch ( Area ) { case AREA_SECURITY_POLICY: SectionName = NULL; break; case AREA_PRIVILEGES: SectionName = szPrivilegeRights; break; case AREA_GROUP_MEMBERSHIP: SectionName = szGroupMembership; break; case AREA_FILE_SECURITY: SectionName = szFileSecurity; break; case AREA_REGISTRY_SECURITY: SectionName = szRegistryKeys; break; case AREA_DS_OBJECTS: SectionName = szDSSecurity; break; case AREA_SYSTEM_SERVICE: SectionName = NULL; break; default: SectionName = NULL; break; } if ( TotalTicks ) { nProg = (CurrentTicks+1)*100/TotalTicks; if ( nProg > 100 ) { nProg = 100; } } else { nProg = 0; } if ( SectionName ) { LoadString( hMod, SECEDITP_WITH_SECTIONNAME, LineString, 256 ); My_wprintf(LineString, nProg, CurrentTicks, TotalTicks, SectionName); } else if ( Area == AREA_SECURITY_POLICY ) { LoadString( hMod, SECEDITP_SICURITY_POLICY, LineString, 256 ); My_wprintf(LineString, nProg, CurrentTicks, TotalTicks); } else if ( Area == AREA_SYSTEM_SERVICE ) { LoadString( hMod, SECEDITP_SYSTEM_SERVICE, LineString, 256 ); My_wprintf(LineString, nProg, CurrentTicks, TotalTicks); } else { LoadString( hMod, SECEDITP_NO_SECTIONNAME, LineString, 256 ); My_wprintf(LineString, nProg, CurrentTicks, TotalTicks); } return TRUE; } DWORD pProgressRoutine( IN PWSTR StringUpdate ) { if ( StringUpdate ) { My_wprintf(L"Process %s\n", StringUpdate); } return 0; } BOOL ScepPrintConfigureWarning() { WCHAR LineString[256]; WCHAR wch; LoadString( hMod, SECEDITP_CONFIG_WARNING_LINE1, LineString, 256 ); My_wprintf(LineString); LoadString( hMod, SECEDITP_CONFIG_WARNING_LINE2, LineString, 256 ); My_wprintf(LineString); LoadString( hMod, SECEDITP_CONFIG_WARNING_LINE3, LineString, 256 ); My_wprintf(LineString); // // get user input // LoadString( hMod, SECEDITP_CONFIG_WARNING_CONFIRM, LineString, 256 ); My_wprintf(LineString); wch = getwc(stdin); getwc(stdin); // // load string for Yes // LineString[0] = L'\0'; LoadString( hMod, SECEDITP_IDS_YES, LineString, 256 ); if ( towlower(wch) == towlower(LineString[0]) ) { return(TRUE); } else { return(FALSE); } } BOOL CALLBACK pBrowseCallback( IN LONG ID, IN PWSTR KeyName OPTIONAL, IN PWSTR GpoName OPTIONAL, IN PWSTR Value OPTIONAL, IN DWORD Len ) { BYTE *pb=NULL; My_wprintf(L"\n"); if ( ID > 0 ) { My_printf("%d\t", ID); } if (GpoName ) { My_wprintf(L"%s ", GpoName); } if ( KeyName ) { My_wprintf(L"%s", KeyName); if ( Value && Len > 0 ) { if ( Len > 30 ) { My_wprintf(L"\n"); } else { My_wprintf(L"\t"); } if ( iswprint(Value[0]) ) { My_wprintf(L"%c%s\n", Value[0], (Len>1) ? Value+1 : L""); } else { pb = (BYTE *)Value; My_wprintf(L"%d %d ", pb[1], pb[0]); /* if ( isprint( pc[0] ) ) { My_printf("%c ", pc[0] ); } else { My_printf("%d ", (int)(pc[0]) ); } if ( isprint( pc[1] ) ) { My_printf("%c ", pc[1] ); } else { My_printf("%d ", (int)pc[1] ); } */ if ( Len > 1 && Value[1] != L'\0' ) { My_wprintf(L"%s\n", Value+1); } else { My_wprintf(L"No value\n"); } } } else { My_wprintf(L"\n"); } } else { My_wprintf(L"\n"); } return(TRUE); } /*** * My_wprintf(format) - print formatted data * * Prints Unicode formatted string to console window using WriteConsoleW. * Note: This My_wprintf() is used to workaround the problem in c-runtime * which looks up LC_CTYPE even for Unicode string. * */ int __cdecl My_wprintf( const wchar_t *format, ... ) { DWORD cchWChar = 0; DWORD dwBytesWritten; va_list args; va_start( args, format ); cchWChar = My_vfwprintf(stdout, format, args); va_end(args); return cchWChar; } /*** * My_fwprintf(stream, format) - print formatted data * * Prints Unicode formatted string to console window using WriteConsoleW. * Note: This My_fwprintf() is used to workaround the problem in c-runtime * which looks up LC_CTYPE even for Unicode string. * */ int __cdecl My_fwprintf( FILE *str, const wchar_t *format, ... ) { DWORD cchWChar = 0; va_list args; va_start( args, format ); cchWChar = My_vfwprintf(str, format, args); va_end(args); return cchWChar; } int __cdecl My_vfwprintf( FILE *str, const wchar_t *format, va_list argptr ) { HANDLE hOut; // if the /quiet option is specified, suppress printing to stdout // and instead print to the logfile. If logfile not specified // don't print at all if (dOptions & SCE_DISABLE_LOG){ DWORD cchWChar = 0; LPTSTR szBufferMessage = (LPTSTR) LocalAlloc (LPTR, 2048 * sizeof(TCHAR)); if (szBufferMessage) { vswprintf( szBufferMessage, format, argptr ); cchWChar = wcslen(szBufferMessage); // remove trailing LFs if (szBufferMessage[cchWChar-1] == L'\n') szBufferMessage[cchWChar-1] = L'\0'; // remove leading LFs if (szBufferMessage[0] == L'\n') szBufferMessage[0] = L' '; ScepCmdToolLogWrite(szBufferMessage); SCE_LOCAL_FREE(szBufferMessage); } return cchWChar; } if (str == stderr) { hOut = GetStdHandle(STD_ERROR_HANDLE); } else { hOut = GetStdHandle(STD_OUTPUT_HANDLE); } if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) { DWORD cchWChar; WCHAR szBufferMessage[1024]; vswprintf( szBufferMessage, format, argptr ); cchWChar = wcslen(szBufferMessage); WriteConsoleW(hOut, szBufferMessage, cchWChar, &cchWChar, NULL); return cchWChar; } return fwprintf(str, format, argptr); } /////////////////////////////////////////////////////////////////////////////// // This function is to suppress printf if the /quiet option is specified /////////////////////////////////////////////////////////////////////////////// int __cdecl My_printf( const char *format, ... ) { int cchChar = 0; va_list argptr; va_start( argptr, format ); cchChar = printf(format, argptr); va_end(argptr); return cchChar; } /////////////////////////////////////////////////////////////////////////////// // This function takes the user string that is supplied at the command line // and converts it into full path names for eg. it takes ..\%windir%\hisecws.inf // and converts it to C:\winnt\security\templates\hisecws.inf /////////////////////////////////////////////////////////////////////////////// WCHAR * SecEditPConvertToFullPath( WCHAR *pUserFilename, DWORD *pRetCode ) { BOOL NeedCurrDirFlag = TRUE; SCESTATUS rc; DWORD Len; DWORD LenCurrDir; PWSTR pCurrentDir = NULL; PWSTR pAbsolutePath = NULL; PWSTR pAbsolutePathDirOnly = NULL; PWSTR pToMerge = NULL; PWSTR pLastSlash = NULL; WCHAR FirstThree[4]; WCHAR LineString[256]; if (pUserFilename == NULL) { *pRetCode = 2; goto ScePathConvertFuncError; } // PathIsRoot() works only if exact strings // such as C:\ are passed - so need to extract wcsncpy(FirstThree, pUserFilename, 3); FirstThree[3] = L'\0'; // if pUserFilename C:\ etc. then we do not need the current directory - // Note: extraction hack not needed if PathIsRoot() worked as published NeedCurrDirFlag = !PathIsRoot(FirstThree); if (NeedCurrDirFlag){ LenCurrDir = GetCurrentDirectory(0, NULL); pCurrentDir = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (LenCurrDir+1)*sizeof(WCHAR)); if ( pCurrentDir == NULL ) { rc = GetLastError(); LoadString( hMod, SECEDITP_OUT_OF_MEMORY, LineString, 256 ); SeceditpErrOut(rc, LineString ); *pRetCode = 2; goto ScePathConvertFuncError; } GetCurrentDirectory(LenCurrDir, pCurrentDir); if (pCurrentDir[LenCurrDir - 2] != L'\\') wcscat(pCurrentDir, L"\\"); } // allocate space for string that holds the to-be-expanded string Len = wcslen(pUserFilename); if (NeedCurrDirFlag) Len += LenCurrDir; pToMerge = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR)); if ( pToMerge == NULL ) { rc = GetLastError(); LoadString( hMod, SECEDITP_OUT_OF_MEMORY, LineString, 256 ); SeceditpErrOut(rc, LineString ); *pRetCode = 2; goto ScePathConvertFuncError; } if (NeedCurrDirFlag) wcscat(pToMerge, pCurrentDir); wcscat(pToMerge, pUserFilename); // allocate space for string that holds the final full path - can't be > wcslen(pToMerge) #ifdef DBG // shlwapi is lame on chk builds and verifies that the dest buffer is MAX_PATH pAbsolutePath = (PWSTR)LocalAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR)); #else pAbsolutePath = (PWSTR)LocalAlloc(LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR)); #endif if ( pAbsolutePath == NULL ) { rc = GetLastError(); LoadString( hMod, SECEDITP_OUT_OF_MEMORY, LineString, 256 ); SeceditpErrOut(rc, LineString ); *pRetCode = 2; goto ScePathConvertFuncError; } // canonicalize pToMerge i.e. collapse all ..\, .\ and merge if (PathCanonicalize(pAbsolutePath, pToMerge) == FALSE){ LoadString( hMod, SECEDITP_PATH_NOT_CANONICALIZABLE, LineString, 256 ); My_wprintf(LineString); SCE_LOCAL_FREE(pAbsolutePath); *pRetCode = 2; goto ScePathConvertFuncError; } // allocate string to verify validity of directory pAbsolutePathDirOnly = (PWSTR)LocalAlloc(LMEM_ZEROINIT, ((wcslen(pAbsolutePath)+1)*sizeof(WCHAR))); if ( pAbsolutePathDirOnly == NULL ) { rc = GetLastError(); LoadString( hMod, SECEDITP_OUT_OF_MEMORY, LineString, 256 ); SeceditpErrOut(rc, LineString ); SCE_LOCAL_FREE(pAbsolutePath); *pRetCode = 2; goto ScePathConvertFuncError; } // prepare pAbsolutePathDirOnly to have directory part only wcscpy(pAbsolutePathDirOnly, pAbsolutePath); pLastSlash = wcsrchr(pAbsolutePathDirOnly, L'\\'); if (pLastSlash) *pLastSlash = L'\0'; if (PathIsDirectory(pAbsolutePathDirOnly) == FALSE){ LoadString( hMod, SECEDITP_PATH_NOT_VALID, LineString, 256 ); My_wprintf(L"\n%s - %s\n", LineString, pAbsolutePathDirOnly); SCE_LOCAL_FREE(pAbsolutePath); *pRetCode = 2; goto ScePathConvertFuncError; } ScePathConvertFuncError: SCE_LOCAL_FREE(pCurrentDir); SCE_LOCAL_FREE(pToMerge); SCE_LOCAL_FREE(pAbsolutePathDirOnly); return pAbsolutePath; } /////////////////////////////////////////////////////////////////////////////// // This function opens the log file specified and saves the name and its handle // in global variables /////////////////////////////////////////////////////////////////////////////// BOOL ScepCmdToolLogInit( PWSTR logname ) { DWORD rc=NO_ERROR; if ( logname && wcslen(logname) > 3 ) { hCmdToolLogFile = CreateFile(logname, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) { DWORD dwBytesWritten; CHAR TmpBuf[3]; SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_BEGIN); TmpBuf[0] = (CHAR)0xFF; TmpBuf[1] = (CHAR)0xFE; TmpBuf[2] = '\0'; WriteFile (hCmdToolLogFile, (LPCVOID)TmpBuf, 2, &dwBytesWritten, NULL); SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END); } } else { hCmdToolLogFile = INVALID_HANDLE_VALUE; } if ( hCmdToolLogFile == INVALID_HANDLE_VALUE && (logname != NULL ) ) { rc = ERROR_INVALID_NAME; } if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) { CloseHandle( hCmdToolLogFile ); } hCmdToolLogFile = INVALID_HANDLE_VALUE; return(rc); } VOID ScepCmdToolLogWrite( PWSTR pErrString ) { DWORD cchWChar; const TCHAR c_szCRLF[] = TEXT("\r\n"); if ( LogFile && wcslen(LogFile) > 3 ) { hCmdToolLogFile = CreateFile(LogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) { SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END); cchWChar = wcslen( pErrString ); WriteFile(hCmdToolLogFile, (LPCVOID)pErrString, sizeof(WCHAR) * cchWChar, &cchWChar, NULL); WriteFile (hCmdToolLogFile, (LPCVOID) c_szCRLF, 2 * sizeof(WCHAR), &cchWChar, NULL); // SetFilePointer (hCmdToolLogFile, 0, NULL, FILE_END); CloseHandle( hCmdToolLogFile ); hCmdToolLogFile = INVALID_HANDLE_VALUE; return; } } } /////////////////////////////////////////////////////////////////////////////// // This function closes the log file if there is one opened and // clears the log variables /////////////////////////////////////////////////////////////////////////////// SCESTATUS ScepCmdToolLogClose() { if ( INVALID_HANDLE_VALUE != hCmdToolLogFile ) { CloseHandle( hCmdToolLogFile ); } hCmdToolLogFile = INVALID_HANDLE_VALUE; return(SCESTATUS_SUCCESS); }