Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1929 lines
50 KiB

/*++
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 <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <string.h>
#include <shlwapi.h>
//
// CRT header files
//
#include <process.h>
#include <wchar.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <limits.h>
#include "secedit.h"
#include "scesetup.h"
#include "stringid.h"
//#include <aclapi.h>
#include <io.h>
#include "userenv.h"
#include <locale.h>
#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; i<argc; i++ ){
if ( _wcsicmp(argv[i], SeceditpArgumentLog ) == 0 ) {
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
LogFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
if (rCode == 2) {
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
if ( _wcsicmp(argv[i], SeceditpArgumentQuiet ) == 0 ) {
bQuiet = TRUE;
dOptions |= SCE_DISABLE_LOG;
}
}
if ( rCode == 0 )
ScepCmdToolLogInit(LogFile);
ConsoleCP = GetConsoleOutputCP();
// szConsoleCP[0] = '.';
// itoa(ConsoleCP, &szConsoleCP[1], 10);
sprintf(szConsoleCP, ".%d", ConsoleCP);
// setlocale(LC_ALL, ".OCP");
setlocale(LC_ALL, szConsoleCP);
hMod = GetModuleHandle(NULL);
if ( hMod == NULL ) {
My_wprintf(L"Cannot find the module handle\n");
return 2; // system error
}
for ( i=1; i<argc; i++ )
if ( _wcsicmp(argv[i], L"/?") == 0 ) {
ScepPrintHelp(0);
goto Done;
}
if ( argc < 2 ) {
ScepPrintHelp(0);
return 1;
} else {
for ( i=1; i<argc; i++ ) {
SCE_LOCAL_FREE(pTemp);
Len = wcslen(argv[i]);
pTemp = (PWSTR)LocalAlloc( 0, (Len+1)*sizeof(WCHAR));
if ( pTemp == NULL ) {
My_wprintf(L"Not enough memory\n");
rCode=2; //system error
goto Done;
}
wcscpy(pTemp, argv[i]);
//
// configure engine type ?
//
if ( _wcsicmp(pTemp, SeceditpArgumentConfigure) == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1; // invalid parameter
goto Done;
}
EngineType = SCE_ENGINE_SCP;
continue;
}
//
// analyze engine type ?
//
if ( _wcsicmp(pTemp, SeceditpArgumentAnalyze) == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1; //invalid parameter
goto Done;
}
EngineType = SCE_ENGINE_SAP;
continue;
}
//
// generate template ?
//
if ( _wcsicmp(pTemp, SeceditpArgumentGenerate) == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
EngineType = SCE_ENGINE_GENERATE;
continue;
}
//
// compile a template ?
//
if ( _wcsicmp(pTemp, SeceditpArgumentCompile) == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
EngineType = SCE_ENGINE_COMPILE;
//
// compile requires a INF template name
//
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
if (rCode == 2) {
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
//
// register a template for registry values ?
//
if ( _wcsicmp(pTemp, SeceditpArgumentRegister) == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
EngineType = SCE_ENGINE_REGISTER;
//
// register requires a INF template name
//
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
if (rCode == 2) {
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
//
// refresh policy
//
if ( _wcsicmp(pTemp, SeceditpArgumentRefresh) == 0 ) {
//
// do not support refresh policy because it's supported by refgp.exe
//
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
/*
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
EngineType = SCE_ENGINE_REFRESH;
//
// next argument is the policy area
//
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
if ( 0 == _wcsicmp(argv[i+1], L"MACHINE_POLICY") ) {
bMachine = TRUE;
} else if ( 0 == _wcsicmp(argv[i+1], L"USER_POLICY") ) {
bMachine = FALSE;
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
*/
}
if ( _wcsicmp(pTemp, L"/browse") == 0 ) {
if ( EngineType != 0 ) {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
EngineType = SCE_ENGINE_BROWSE;
//
// next argument is the table
//
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
if ( 0 == _wcsicmp(argv[i+1], L"scp") ) {
dWarning = SCE_ENGINE_SCP;
} else if ( 0 == _wcsicmp(argv[i+1], L"smp") ) {
dWarning = SCE_ENGINE_SMP;
} else if ( 0 == _wcsicmp(argv[i+1], L"sap") ) {
dWarning = SCE_ENGINE_SAP;
} else if ( 0 == _wcsicmp(argv[i+1], L"tattoo") ) {
dWarning = SCE_ENGINE_SAP;
bMerge = TRUE;
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
if ( _wcsicmp(pTemp, L"/debug") == 0 ) {
bTest = TRUE;
continue;
}
if ( _wcsicmp(pTemp, SeceditpArgumentVerbose ) == 0 ) {
bVerbose = TRUE;
continue;
}
if ( _wcsicmp(pTemp, SeceditpArgumentQuiet ) == 0 ) {
bQuiet = TRUE;
continue;
}
if ( _wcsicmp(pTemp, SeceditpArgumentAppend ) == 0 ) {
bAppend = FALSE;
continue;
}
if ( _wcsicmp(pTemp, SeceditpArgumentMerge ) == 0 ) {
bMerge = TRUE;
continue;
}
if ( _wcsicmp(pTemp, SeceditpArgumentEnforce ) == 0 ) {
bEnforce = TRUE;
continue;
}
//
// scp profile name, it may be empty "/scppath"
//
if ( _wcsicmp(pTemp, SeceditpArgumentScpPath) == 0 ) {
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
InfFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
if (rCode == 2) {
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
//
// sad database name, it may be empty
//
if ( _wcsicmp(pTemp, SeceditpArgumentSadPath) == 0 ) {
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
SadFile = SecEditPConvertToFullPath(argv[i+1], &rCode);
if (rCode == 2) {
goto Done;
}
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
//
// area(s)
//
if ( _wcsicmp(pTemp, SeceditpArgumentArea ) == 0 ) {
//
//
for ( j=(DWORD)i, Area=0; j+1 < (DWORD)argc && argv[j+1][0] != L'/'; j++ ) {
SCE_LOCAL_FREE(pTemp);
Len = wcslen(argv[j+1]);
pTemp = (PWSTR)LocalAlloc( 0, (Len+1)*sizeof(WCHAR));
if ( pTemp == NULL ) {
My_wprintf(L"Not enough memory\n");
rCode = 2;
goto Done;
}
wcscpy(pTemp, argv[j+1]);
//
// Process all arguments for Areas
//
if ( _wcsicmp( pTemp, SeceditpAreaPolicy) == 0 ) {
// security policy
Area |= AREA_SECURITY_POLICY;
continue;
}
/*
if ( _wcsicmp( pTemp, SeceditpAreaUser) == 0 ) {
// user
Area |= AREA_USER_SETTINGS;
continue;
}
*/
if ( _wcsicmp( pTemp, SeceditpAreaGroup) == 0 ) {
// group
Area |= AREA_GROUP_MEMBERSHIP;
continue;
}
if ( _wcsicmp( pTemp, SeceditpAreaRight) == 0 ) {
// privilege rights
Area |= AREA_PRIVILEGES;
continue;
}
#if 0
if ( _wcsicmp( pTemp, SeceditpAreaDsObject) == 0 ) {
// ds objects
Area |= AREA_DS_OBJECTS;
continue;
}
#endif
if ( _wcsicmp( pTemp, SeceditpAreaRegistry) == 0 ) {
// Registry
Area |= AREA_REGISTRY_SECURITY;
continue;
}
if ( _wcsicmp( pTemp, SeceditpAreaFile) == 0 ) {
// file
Area |= AREA_FILE_SECURITY;
continue;
}
if ( _wcsicmp( pTemp, SeceditpAreaService) == 0 ) {
// services
Area |= AREA_SYSTEM_SERVICE;
continue;
}
//
// unrecognized parameter
//
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i = (LONG)j;
continue;
}
//
// ignore if "/log filename" since already processed at the beginning
//
if ( _wcsicmp(pTemp, SeceditpArgumentLog ) == 0 ) {
if ( i+1 < argc && argv[i+1][0] != L'/' ) {
} else {
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
i++;
continue;
}
//
// unrecognized argument
//
ScepPrintHelp(EngineType);
rCode = 1;
goto Done;
}
}
if ( EngineType == 0 ) {
ScepPrintHelp(0);
rCode = 1;
goto Done;
}
SetConsoleCtrlHandler(NULL, TRUE);
//
// Initialize
//
if ( bTest ) {
dOptions |= SCE_DEBUG_LOG;
} else if ( bVerbose ) {
dOptions |= SCE_VERBOSE_LOG;
}
switch ( EngineType ) {
case SCE_ENGINE_SCP:
//
// configure the system
//
if ( (SadFile == NULL) ||
SceIsSystemDatabase(SadFile) ) {
rc = SCESTATUS_INVALID_PARAMETER;
LoadString( hMod,
SECEDITP_CONFIG_NOT_ALLOWED_1,
LineString,
256
);
My_wprintf(LineString);
LoadString( hMod,
SECEDITP_CONFIG_NOT_ALLOWED_2,
LineString,
256
);
My_wprintf(LineString);
EngineType = 0;
} else {
bMachine = TRUE;
if ( bAppend && InfFile != NULL ) {
dOptions |= SCE_UPDATE_DB;
} else {
dOptions |= SCE_OVERWRITE_DB;
if ( FALSE == bAppend && InfFile != NULL && !bQuiet ) {
//
// will overwrite the database with the new inf file.
// warn users for this serious problem.
// If this is a normal user logon, the operation will fail
// by the server site.
//
bMachine = ScepPrintConfigureWarning(); // temp. use of bMachine
}
}
if ( bMachine ) {
rc = SceConfigureSystem(
NULL,
InfFile,
SadFile,
LogFile,
dOptions,
Area,
(bVerbose || bTest ) ?
(PSCE_AREA_CALLBACK_ROUTINE)SceCmdVerboseCallback : NULL,
NULL,
&dWarning
);
} else {
rc = SCESTATUS_SUCCESS;
dWarning = ERROR_REQUEST_ABORTED;
goto Done;
}
}
break;
case SCE_ENGINE_SAP:
//
// analyze the system
//
if ( !bTest )
Area = AREA_ALL;
// if ( bAppend && InfFile != NULL ) {
// dOptions |= SCE_UPDATE_DB;
// } else {
// dOptions |= SCE_OVERWRITE_DB;
// }
dOptions |= SCE_OVERWRITE_DB;
// if ( InfFile == NULL || SadFile != NULL ) {
if ( (SadFile != NULL) &&
!SceIsSystemDatabase(SadFile) ) {
rc = SceAnalyzeSystem(
NULL,
InfFile,
SadFile,
LogFile,
dOptions,
Area,
(bVerbose || bTest ) ?
(PSCE_AREA_CALLBACK_ROUTINE)SceCmdVerboseCallback : NULL,
NULL,
&dWarning
);
} else {
rc = SCESTATUS_INVALID_PARAMETER;
LoadString( hMod,
SECEDITP_ANALYSIS_NOT_ALLOWED_1,
LineString,
256
);
My_wprintf(LineString);
LoadString( hMod,
SECEDITP_ANALYSIS_NOT_ALLOWED_2,
LineString,
256
);
My_wprintf(LineString);
EngineType = 0;
}
break;
case SCE_ENGINE_GENERATE:
if ( InfFile != NULL ) {
//
// must have a inf file name
//
rc = SceSetupGenerateTemplate(NULL,
SadFile,
bMerge,
InfFile,
LogFile,
Area);
if (ERROR_NOT_ENOUGH_MEMORY == rc ||
ERROR_SERVICE_ALREADY_RUNNING == rc ) {
rCode = 2;
} else if ( rc ) {
rCode = 1;
}
} else {
rCode = 1;
ScepPrintHelp(EngineType);
goto Done;
}
break;
case SCE_ENGINE_BROWSE:
//
// must have a inf file name
//
if ( Area == 0 ) {
Area = AREA_ALL;
}
rc = SceBrowseDatabaseTable(SadFile,
(SCETYPE)dWarning,
Area,
bMerge,
(PSCE_BROWSE_CALLBACK_ROUTINE)pBrowseCallback
);
dWarning = 0; // reset the value
if (ERROR_NOT_ENOUGH_MEMORY == rc ||
ERROR_SERVICE_ALREADY_RUNNING == rc ) {
rCode = 2;
} else if ( rc ) {
rCode = 1;
}
break;
case SCE_ENGINE_COMPILE:
rc = 0;
if ( InfFile != NULL ) {
//
// must have a inf file name
//
rc = SceOpenProfile(InfFile,
SCE_INF_FORMAT,
&hProfile);
if ( rc == SCESTATUS_SUCCESS && hProfile ) {
//
// get profile info will parse the template first
//
rc = SceGetSecurityProfileInfo(hProfile,
SCE_ENGINE_SCP,
AREA_ALL,
&ProfileInfo,
&ErrBuf);
if ( SCESTATUS_SUCCESS == rc && ErrBuf ) {
//
// this is a new version template
//
LoadString( hMod,
SECEDITP_TEMPLATE_NEWVERSION,
LineString,
256
);
SeceditpErrOut(0, LineString);
rc = SCESTATUS_INVALID_DATA;
}
for ( pErr=ErrBuf; pErr != NULL; pErr = pErr->next ) {
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);
}