windows-nt/Source/XPSP1/NT/base/fs/utils/reg/reg.c
2020-09-26 16:20:57 +08:00

1160 lines
29 KiB
C

//-----------------------------------------------------------------------//
//
// File: Reg.cpp
// Created: Jan 1997
// By: Martin Holladay (a-martih)
// Purpose: Command-line registry manipulation (query, add, update, etc)
// Modification History:
// Created - Jan 1997 (a-martih)
// Oct 1997 (martinho)
// Fixed up help on Add and Update to display REG_MULTI_SZ examples.
// Oct 1997 (martinho)
// Changed /F to /FORCE under usage for delete
// April 1999 Zeyong Xu: re-design, revision -> version 2.0
//
//-----------------------------------------------------------------------//
#include "stdafx.h"
#include "reg.h"
TCHAR g_NoName[100];
VOID
InitGlobalStrings(
VOID
)
{
LoadString(
NULL,
IDS_NONAME,
g_NoName,
sizeof(g_NoName)/sizeof(TCHAR));
}
//------------------------------------------------------------------------//
//
// main()
//
//------------------------------------------------------------------------//
int __cdecl wmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
APPVARS AppVars; // Used for all operation
APPVARS DstVars; // Used for COPY/COMPARE operation
UINT nResult;
// set the appropriate thread codepage
SetThreadUILanguage0( 0);
InitAppVars(&AppVars);
InitAppVars(&DstVars);
InitGlobalStrings();
//
// Determine the opertion - and pass control to the *deserving* function
//
nResult = ParseRegCmdLine(&AppVars, argc, argv);
if(nResult == REG_STATUS_BADOPERATION)
{
TCHAR szString[LENGTH_MESSAGE] = {0};
LoadString(NULL,
IDS_ERROR_BADOPERATION,
szString,
LENGTH_MESSAGE);
MyTPrintf(stderr,_T("%s"), szString);
}
else if(nResult == REG_STATUS_HELP)
{
Banner();
Usage(AppVars);
}
else if(nResult == ERROR_SUCCESS)
{
//
// At this point we have a valid operation
//
switch(AppVars.nOperation)
{
case REG_QUERY:
nResult = QueryRegistry(&AppVars, argc, argv);
break;
case REG_DELETE:
nResult = DeleteRegistry(&AppVars, argc, argv);
break;
case REG_ADD:
nResult = AddRegistry(&AppVars, argc, argv);
break;
case REG_COPY:
nResult = CopyRegistry(&AppVars, &DstVars, argc, argv);
break;
case REG_SAVE:
nResult = SaveHive(&AppVars, argc, argv);
break;
case REG_RESTORE:
nResult = RestoreHive(&AppVars, argc, argv);
break;
case REG_LOAD:
nResult = LoadHive(&AppVars, argc, argv);
break;
case REG_UNLOAD:
nResult = UnLoadHive(&AppVars, argc, argv);
break;
case REG_COMPARE:
nResult = CompareRegistry(&AppVars, &DstVars, argc, argv);
break;
case REG_EXPORT:
nResult = ExportRegFile(&AppVars, argc, argv);
break;
case REG_IMPORT:
nResult = ImportRegFile(&AppVars, argc, argv);
break;
default:
nResult = REG_STATUS_INVALIDPARAMS;
break;
}
}
if(nResult != ERROR_SUCCESS &&
nResult != REG_STATUS_BADOPERATION &&
nResult != REG_STATUS_HELP)
{
ErrorMessage(nResult);
}
else if(nResult == ERROR_SUCCESS &&
AppVars.nOperation != REG_QUERY)
{
//
// Print "The operation completed successfully" message
//
TCHAR szString[LENGTH_MESSAGE] = {0};
LoadString(NULL,
IDS_SUCCESS,
szString,
LENGTH_MESSAGE);
MyTPrintf(stdout,_T("%s"), szString);
}
FreeAppVars(&AppVars);
FreeAppVars(&DstVars);
if(nResult == REG_STATUS_HELP)
nResult = ERROR_SUCCESS;
nResult = !(!nResult); // cast to 0 or 1
if(AppVars.nOperation == REG_COMPARE)
{
if( nResult == 0 && // no error
AppVars.bHasDifference)
{
nResult = 2; // has difference
}
}
return nResult;
}
//------------------------------------------------------------------------//
//
// ParseRegCmdLine()
// Find out the operation - each operation parses it's own cmd-line
//
//------------------------------------------------------------------------//
REG_STATUS ParseRegCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
REG_STATUS nResult = ERROR_SUCCESS;
// Set default operation
pAppVars->nOperation = REG_NOOPERATION;
//
// Do we have any cmd-line params
//
if(argc == 1)
{
return REG_STATUS_HELP;
}
//
// If we fell through - we need to get the operation
// MUST be the first parameter
//
if(_tcsicmp(argv[1], STR_QUERY) == 0)
{
pAppVars->nOperation = REG_QUERY;
}
else if(_tcsicmp(argv[1], STR_ADD) == 0)
{
pAppVars->nOperation = REG_ADD;
}
else if(_tcsicmp(argv[1], STR_DELETE) == 0)
{
pAppVars->nOperation = REG_DELETE;
}
else if(_tcsicmp(argv[1], STR_COPY) == 0)
{
pAppVars->nOperation = REG_COPY;
}
else if(_tcsicmp(argv[1], STR_SAVE) == 0)
{
pAppVars->nOperation = REG_SAVE;
}
else if(_tcsicmp(argv[1], STR_RESTORE) == 0)
{
pAppVars->nOperation = REG_RESTORE;
}
else if(_tcsicmp(argv[1], STR_LOAD) == 0)
{
pAppVars->nOperation = REG_LOAD;
}
else if(_tcsicmp(argv[1], STR_UNLOAD) == 0)
{
pAppVars->nOperation = REG_UNLOAD;
}
else if(_tcsicmp(argv[1], STR_COMPARE) == 0)
{
pAppVars->nOperation = REG_COMPARE;
}
else if(_tcsicmp(argv[1], STR_EXPORT) == 0)
{
pAppVars->nOperation = REG_EXPORT;
}
else if(_tcsicmp(argv[1], STR_IMPORT) == 0)
{
pAppVars->nOperation = REG_IMPORT;
}
else if((_tcsicmp(argv[1], _T("-?")) == 0) ||
(_tcsicmp(argv[1], _T("/?")) == 0) ||
(_tcsicmp(argv[1], _T("-h")) == 0) ||
(_tcsicmp(argv[1], _T("/h")) == 0))
{
nResult = REG_STATUS_HELP;
}
else
{
nResult = REG_STATUS_BADOPERATION;
}
if(nResult == ERROR_SUCCESS && argc == 3)
{
if((_tcsicmp(argv[2], _T("-?")) == 0) ||
(_tcsicmp(argv[2], _T("/?")) == 0) ||
(_tcsicmp(argv[2], _T("-h")) == 0) ||
(_tcsicmp(argv[2], _T("/h")) == 0))
{
nResult = REG_STATUS_HELP;
}
}
return nResult;
}
//------------------------------------------------------------------------//
//
// AllocAppVars() - Allocate memory for the AppVars
//
//------------------------------------------------------------------------//
void InitAppVars(PAPPVARS pAppVars)
{
// initialize
pAppVars->nOperation = REG_NOOPERATION;
pAppVars->hRootKey = HKEY_LOCAL_MACHINE;
pAppVars->dwRegDataType = REG_SZ;
pAppVars->bUseRemoteMachine = FALSE;
pAppVars->bCleanRemoteRootKey = FALSE;
pAppVars->bRecurseSubKeys = FALSE;
pAppVars->bForce = FALSE;
pAppVars->bAllValues = FALSE;
pAppVars->bNT4RegFile = FALSE;
pAppVars->bHasDifference = FALSE;
pAppVars->nOutputType = OUTPUTTYPE_DIFF;
pAppVars->szMachineName = NULL;
pAppVars->szFullKey = NULL;
pAppVars->szSubKey = NULL;
pAppVars->szValueName = NULL;
pAppVars->szValue = NULL;
_tcscpy(pAppVars->szSeparator, _T("\\0"));
}
//------------------------------------------------------------------------//
//
// FreeAppVars()
//
//------------------------------------------------------------------------//
void FreeAppVars(PAPPVARS pAppVars)
{
if(pAppVars->szMachineName)
free(pAppVars->szMachineName);
if(pAppVars->szFullKey)
free(pAppVars->szFullKey);
if(pAppVars->szSubKey)
free(pAppVars->szSubKey);
if(pAppVars->szValueName)
free(pAppVars->szValueName);
if(pAppVars->szValue)
free(pAppVars->szValue);
if(pAppVars->bCleanRemoteRootKey)
{
RegCloseKey(pAppVars->hRootKey);
}
}
//------------------------------------------------------------------------//
//
// ErrorMessage() - Displays error string
//
//------------------------------------------------------------------------//
void ErrorMessage(UINT nErr)
{
TCHAR szString[LENGTH_MESSAGE] = {0};
// First check for OUR Errors
switch(nErr)
{
case REG_STATUS_TOMANYPARAMS:
LoadString(NULL,
IDS_ERROR_TOMANYPARAMS,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_TOFEWPARAMS:
LoadString(NULL,
IDS_ERROR_TOFEWPARAMS,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_INVALIDPARAMS:
LoadString(NULL,
IDS_ERROR_INVALIDPARAMS,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_NONREMOTABLEROOT:
LoadString(NULL,
IDS_ERROR_NONREMOTABLEROOT,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_NONLOADABLEROOT:
LoadString(NULL,
IDS_ERROR_NONLOADABLEROOT,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_COPYTOSELF:
LoadString(NULL,
IDS_ERROR_COPYTOSELF,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_COMPARESELF:
LoadString(NULL,
IDS_ERROR_COMPARESELF,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_BADKEYNAME:
case REG_STATUS_NOKEYNAME:
LoadString(NULL,
IDS_ERROR_BADKEYNAME,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_BADFILEFORMAT:
LoadString(NULL,
IDS_ERROR_BADFILEFORMAT,
szString,
LENGTH_MESSAGE);
break;
case REG_STATUS_NONREMOTABLE:
LoadString(NULL,
IDS_ERROR_NONREMOTABLE,
szString,
LENGTH_MESSAGE);
break;
//
// Deal with these two Win32 Error Values - I don't like the
// text strings displayed
//
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
LoadString(NULL,
IDS_ERROR_PATHNOTFOUND,
szString,
LENGTH_MESSAGE);
break;
//
// Must be a Win32 Error number
//
default:
{
TCHAR* szMessage;
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nErr,
0,
(LPTSTR) &szMessage,
0,
NULL))
{
wsprintf(szString, _T("\r\nError: %s"), szMessage);
LocalFree(szMessage);
}
else
{
wsprintf(szString,
_T("\r\nError: Unknown Return Code %d\r\n"),
nErr);
}
break;
}
}
// print the error message
MyTPrintf(stderr, _T("%s"), szString);
}
//------------------------------------------------------------------------//
//
// Prompt() - Answer Y/N question if bForce == FALSE
//
//------------------------------------------------------------------------//
BOOL Prompt(LPCTSTR szFormat, LPCTSTR szStr, BOOL bForce)
{
TCHAR ch;
if(bForce == TRUE)
{
return TRUE;
}
MyTPrintf(stdout,szFormat, szStr);
ch = (TCHAR)_gettchar();
if(ch == _T( 'y' ) || ch == _T( 'Y' ) )
{
return TRUE;
}
return FALSE;
}
// break down [\\MachineName\]keyName
REG_STATUS BreakDownKeyString(TCHAR *szStr, PAPPVARS pAppVars)
{
REG_STATUS nResult = ERROR_SUCCESS;
TCHAR* pTemp;
TCHAR* szTempStr;
szTempStr = (TCHAR*) calloc(_tcslen(szStr) + 1, sizeof(TCHAR));
if (!szTempStr) {
return ERROR_NOT_ENOUGH_MEMORY;
}
_tcscpy(szTempStr, szStr);
//
// figure out machine name
//
pTemp = szTempStr;
// machine name
if( szTempStr[0] == _T('\\') &&
szTempStr[1] == _T('\\') )
{
pTemp = _tcschr(szTempStr + 2, _T('\\'));
if(pTemp)
{
*pTemp = 0;
pTemp += 1;
}
nResult = ParseMachineName(szTempStr, pAppVars);
}
// parse key name
if( nResult == ERROR_SUCCESS)
{
if(pTemp && _tcslen(pTemp) > 0)
{
nResult = ParseKeyName(pTemp, pAppVars);
}
else
{
nResult = REG_STATUS_NOKEYNAME;
}
}
if(szTempStr)
free(szTempStr);
return nResult;
}
//------------------------------------------------------------------------//
//
// FindAndAdjustKeyName()
//
// null out the cmdline based on what we think the end of the argument is
//
// we do this because users might not quote out the cmdline properly.
//
//------------------------------------------------------------------------//
PTCHAR
AdjustKeyName(
PTCHAR szStr
)
{
PTCHAR p;
p = _tcschr(szStr, _T('\"'));
if (p != NULL) {
*p = 0;
}
p = _tcschr(szStr, _T('/'));
if (p != NULL) {
*p = 0;
}
return szStr;
}
//------------------------------------------------------------------------//
//
// ParseKeyName()
//
// Pass the full registry path in szStr
//
// Based on input - Sets AppMember fields:
//
// hRootKey
// szKey
// szValueName
// szValue
//
//------------------------------------------------------------------------//
REG_STATUS ParseKeyName(TCHAR *szStr, PAPPVARS pAppVars)
{
REG_STATUS nResult = ERROR_SUCCESS;
TCHAR* pTemp;
TCHAR* szRootKey;
//
// figure out what root key was specified
//
pTemp = _tcschr(szStr, _T('\\'));
if (pTemp != NULL)
{
*pTemp = 0;
pTemp += 1;
}
if (*szStr == '\"') {
szStr += 1;
}
//
// Check the ROOT has been entered
//
szRootKey = (TCHAR*) calloc(_tcslen(STR_HKEY_CURRENT_CONFIG) + 1,
sizeof(TCHAR));
if (!szRootKey) {
return ERROR_NOT_ENOUGH_MEMORY;
}
if (_tcsicmp(szStr, STR_HKEY_CURRENT_USER) == 0 ||
_tcsicmp(szStr, STR_HKCU) == 0)
{
pAppVars->hRootKey = HKEY_CURRENT_USER;
_tcscpy(szRootKey, STR_HKEY_CURRENT_USER);
// check remotable and loadable
if(pAppVars->bUseRemoteMachine)
nResult = REG_STATUS_NONREMOTABLEROOT;
else if( pAppVars->nOperation == REG_LOAD ||
pAppVars->nOperation == REG_UNLOAD )
nResult = REG_STATUS_NONLOADABLEROOT;
}
else if (_tcsicmp(szStr, STR_HKEY_CLASSES_ROOT) == 0 ||
_tcsicmp(szStr, STR_HKCR) == 0)
{
pAppVars->hRootKey = HKEY_CLASSES_ROOT;
_tcscpy(szRootKey, STR_HKEY_CLASSES_ROOT);
// check remotable and loadable
if(pAppVars->bUseRemoteMachine)
nResult = REG_STATUS_NONREMOTABLEROOT;
else if( pAppVars->nOperation == REG_LOAD ||
pAppVars->nOperation == REG_UNLOAD )
nResult = REG_STATUS_NONLOADABLEROOT;
}
else if (_tcsicmp(szStr, STR_HKEY_CURRENT_CONFIG) == 0 ||
_tcsicmp(szStr, STR_HKCC) == 0)
{
pAppVars->hRootKey = HKEY_CURRENT_CONFIG;
_tcscpy(szRootKey, STR_HKEY_CURRENT_CONFIG);
// check remotable and loadable
if(pAppVars->bUseRemoteMachine)
nResult = REG_STATUS_NONREMOTABLEROOT;
else if( pAppVars->nOperation == REG_LOAD ||
pAppVars->nOperation == REG_UNLOAD )
nResult = REG_STATUS_NONLOADABLEROOT;
}
else if (_tcsicmp(szStr, STR_HKEY_LOCAL_MACHINE) == 0 ||
_tcsicmp(szStr, STR_HKLM) == 0)
{
pAppVars->hRootKey = HKEY_LOCAL_MACHINE;
_tcscpy(szRootKey, STR_HKEY_LOCAL_MACHINE);
}
else if (_tcsicmp(szStr, STR_HKEY_USERS) == 0 ||
_tcsicmp(szStr, STR_HKU) == 0)
{
pAppVars->hRootKey = HKEY_USERS;
_tcscpy(szRootKey, STR_HKEY_USERS);
}
else
{
nResult = REG_STATUS_BADKEYNAME;
}
if(nResult == ERROR_SUCCESS)
{
//
// parse the subkey
//
if (pTemp == NULL)
{
// only root key, subkey is empty
pAppVars->szSubKey = (TCHAR*) calloc(1,
sizeof(TCHAR));
if (!pAppVars->szSubKey) {
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
pAppVars->szFullKey = (TCHAR*) calloc(_tcslen(szRootKey) + 1,
sizeof(TCHAR));
if (!pAppVars->szFullKey) {
free (pAppVars->szSubKey);
pAppVars->szSubKey = NULL;
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
_tcscpy(pAppVars->szFullKey, szRootKey);
}
else
{
//
// figure out what root key was specified
//
pTemp = AdjustKeyName(pTemp);
// get subkey
pAppVars->szSubKey = (TCHAR*) calloc(_tcslen(pTemp) + 1,
sizeof(TCHAR));
if (!pAppVars->szSubKey) {
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
_tcscpy(pAppVars->szSubKey, pTemp);
// get fullkey
pAppVars->szFullKey = (TCHAR*) calloc(_tcslen(szRootKey) +
_tcslen(pAppVars->szSubKey) +
2,
sizeof(TCHAR));
if (!pAppVars->szFullKey) {
free (pAppVars->szSubKey);
pAppVars->szSubKey = NULL;
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
_tcscpy(pAppVars->szFullKey, szRootKey);
_tcscat(pAppVars->szFullKey, _T("\\"));
_tcscat(pAppVars->szFullKey, pAppVars->szSubKey);
}
}
Cleanup:
if(szRootKey)
free(szRootKey);
return nResult;
}
//------------------------------------------------------------------------//
//
// IsRegDataType()
//
//------------------------------------------------------------------------//
DWORD IsRegDataType(TCHAR *szStr)
{
DWORD nResult = (DWORD)-1;
if(_tcsicmp(szStr, STR_REG_SZ) == 0)
{
nResult = REG_SZ;
}
else if(_tcsicmp(szStr, STR_REG_EXPAND_SZ) == 0)
{
nResult = REG_EXPAND_SZ;
}
else if(_tcsicmp(szStr, STR_REG_MULTI_SZ) == 0)
{
nResult = REG_MULTI_SZ;
}
else if(_tcsicmp(szStr, STR_REG_BINARY) == 0)
{
nResult = REG_BINARY;
}
else if(_tcsicmp(szStr, STR_REG_DWORD) == 0)
{
nResult = REG_DWORD;
}
else if(_tcsicmp(szStr, STR_REG_DWORD_LITTLE_ENDIAN) == 0)
{
nResult = REG_DWORD_LITTLE_ENDIAN;
}
else if(_tcsicmp(szStr, STR_REG_DWORD_BIG_ENDIAN) == 0)
{
nResult = REG_DWORD_BIG_ENDIAN;
}
else if(_tcsicmp(szStr, STR_REG_NONE) == 0)
{
nResult = REG_NONE;
}
return nResult;
}
//------------------------------------------------------------------------//
//
// Banner()
//
//------------------------------------------------------------------------//
void Banner()
{
TCHAR szCopyRight[LENGTH_MESSAGE] = {0};
LONG rc = 0;
rc = LoadString( NULL,
IDS_REG_BANNER,
szCopyRight,
LENGTH_MESSAGE);
if( rc ) {
MyTPrintf( stdout,_T("\r\n%s\r\n"), szCopyRight );
}
rc = LoadString( NULL,
IDS_COPYRIGHT,
szCopyRight,
LENGTH_MESSAGE);
if( rc ) {
MyTPrintf( stdout,_T("%s\r\n"), szCopyRight );
}
}
//------------------------------------------------------------------------//
//
// Usage() - Display Usage Information
//
//------------------------------------------------------------------------//
void Usage(APPVARS AppVars)
{
TCHAR szUsage1[LENGTH_USAGE] = {0};
TCHAR szUsage2[LENGTH_USAGE] = {0};
switch(AppVars.nOperation)
{
case REG_QUERY:
LoadString(NULL,
IDS_USAGE_QUERY,
szUsage1,
LENGTH_USAGE);
break;
case REG_ADD:
LoadString(NULL,
IDS_USAGE_ADD1,
szUsage1,
LENGTH_USAGE);
LoadString(NULL,
IDS_USAGE_ADD2,
szUsage2,
LENGTH_USAGE);
break;
case REG_DELETE:
LoadString(NULL,
IDS_USAGE_DELETE,
szUsage1,
LENGTH_USAGE);
break;
case REG_COPY:
LoadString(NULL,
IDS_USAGE_COPY,
szUsage1,
LENGTH_USAGE);
break;
case REG_SAVE:
LoadString(NULL,
IDS_USAGE_SAVE,
szUsage1,
LENGTH_USAGE);
break;
case REG_RESTORE:
LoadString(NULL,
IDS_USAGE_RESTORE,
szUsage1,
LENGTH_USAGE);
break;
case REG_LOAD:
LoadString(NULL,
IDS_USAGE_LOAD,
szUsage1,
LENGTH_USAGE);
break;
case REG_UNLOAD:
LoadString(NULL,
IDS_USAGE_UNLOAD,
szUsage1,
LENGTH_USAGE);
break;
case REG_COMPARE:
LoadString(NULL,
IDS_USAGE_COMPARE1,
szUsage1,
LENGTH_USAGE);
LoadString(NULL,
IDS_USAGE_COMPARE2,
szUsage2,
LENGTH_USAGE);
break;
case REG_EXPORT:
LoadString(NULL,
IDS_USAGE_EXPORT,
szUsage1,
LENGTH_USAGE);
break;
case REG_IMPORT:
LoadString(NULL,
IDS_USAGE_IMPORT,
szUsage1,
LENGTH_USAGE);
break;
default:
LoadString(NULL,
IDS_USAGE_REG,
szUsage1,
LENGTH_USAGE);
break;
}
MyTPrintf(stdout,_T("%s%s"), szUsage1, szUsage2);
}
//------------------------------------------------------------------------//
//
// IsMachineName()
//
//------------------------------------------------------------------------//
REG_STATUS ParseMachineName(TCHAR* szStr, PAPPVARS pAppVars)
{
//
// copy string
//
if(!_tcsicmp(szStr, _T("\\\\"))) // need a machine name
return REG_STATUS_BADKEYNAME;
else if(!_tcsicmp(szStr, _T("\\\\."))) // current machine
return ERROR_SUCCESS;
pAppVars->szMachineName = (TCHAR*) calloc(_tcslen(szStr) + 1,
sizeof(TCHAR));
if (!pAppVars->szMachineName) {
return ERROR_NOT_ENOUGH_MEMORY;
}
_tcscpy(pAppVars->szMachineName, szStr);
pAppVars->bUseRemoteMachine = TRUE;
return ERROR_SUCCESS;
}
LONG RegConnectMachine(PAPPVARS pAppVars)
{
HKEY hKeyConnect;
LONG nResult = ERROR_SUCCESS;
if (pAppVars->bUseRemoteMachine)
{
// close the remote key
if(pAppVars->bCleanRemoteRootKey)
RegCloseKey(pAppVars->hRootKey);
// connect to remote key
nResult = RegConnectRegistry(pAppVars->szMachineName,
pAppVars->hRootKey,
&hKeyConnect);
if (nResult == ERROR_SUCCESS)
{
pAppVars->hRootKey = hKeyConnect;
pAppVars->bCleanRemoteRootKey = TRUE;
}
}
return nResult;
}
//
// BOOL
// IsConsoleHandle(
// IN HANDLE ConsoleHandle
// );
//
#define IsConsoleHandle( h ) \
((( DWORD_PTR )( h )) & 1 )
TCHAR ReallyBigBuffer[4096];
CHAR ReallyBigBufferAnsi[4096];
int __cdecl
MyTPrintf(
FILE* fp,
LPCTSTR FormatString,
...
)
/*++
Routine Description:
This is a function that does what tprintf should really do for console
applications.
tprintf converts strings for the terminal to ansi codepage instead of
oem codepage. This doesn't work for localized apps where the ansi codepage
conversions do not match the oem codepage conversions.
This routine uses WriteConsole() api instead, which does the correct
thing for console apps, but only if the app is writing to the console. if
it's not writing to the console, WriteConsole will fail, so we have to do
something different. So the output unicode text is converted to and saved
in ansi codepage format. This means you can look at the output text with
"notepad.exe" but not with the "type" command for instance.
Arguments:
FormatString - format string
Return Value:
Number of characters written to stdout.
--*/
{
va_list arglist;
HANDLE Handle;
DWORD CharsIn, CharsOut;
PSTR pBuffer;
BOOL Success;
va_start(arglist,FormatString);
CharsIn = _vsntprintf( ReallyBigBuffer, sizeof(ReallyBigBuffer)/sizeof(TCHAR), FormatString, arglist );
//
// If the standard output handle is a console handle, write the string
// via console api
//
Handle = GetStdHandle( fp == stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE );
if ( IsConsoleHandle( Handle )) {
Success = WriteConsole(
Handle,
ReallyBigBuffer,
CharsIn,
&CharsOut,
NULL
);
} else {
#ifdef UNICODE
//
// convert to ansi codepage and write to stdout
//
int rc;
rc = WideCharToMultiByte(
CP_ACP,
0,
ReallyBigBuffer,
CharsIn,
ReallyBigBufferAnsi,
sizeof( ReallyBigBufferAnsi ),
NULL,
NULL
);
if ( rc == 0 ) {
Success = FALSE;
goto exit;
}
pBuffer = ReallyBigBufferAnsi;
#else
pBuffer = ReallyBigBuffer;
#endif
Success = WriteFile(
Handle,
pBuffer,
CharsIn,
&CharsOut,
NULL
);
}
exit:
va_end(arglist);
//
// Return the number of characters written.
//
if ( Success ) {
return CharsOut;
} else {
return 0;
}
}
// ***************************************************************************
// Routine Description:
//
// Complex scripts cannot be rendered in the console, so we
// force the English (US) resource.
//
// Arguments:
// [ in ] dwReserved => must be zero
//
// Return Value:
// TRUE / FALSE
//
// ***************************************************************************
BOOL SetThreadUILanguage0( DWORD dwReserved )
{
// local variables
HMODULE hKernel32Lib = NULL;
const CHAR cstrFunctionName[] = "SetThreadUILanguage";
typedef BOOLEAN (WINAPI * FUNC_SetThreadUILanguage)( DWORD dwReserved );
FUNC_SetThreadUILanguage pfnSetThreadUILanguage = NULL;
// try loading the kernel32 dynamic link library
hKernel32Lib = LoadLibrary( _T( "kernel32.dll" ) );
if ( hKernel32Lib != NULL )
{
// library loaded successfully ... now load the addresses of functions
pfnSetThreadUILanguage = (FUNC_SetThreadUILanguage) GetProcAddress( hKernel32Lib, cstrFunctionName );
// we will keep the library loaded in memory only if all the functions were loaded successfully
if ( pfnSetThreadUILanguage == NULL )
{
// some (or) all of the functions were not loaded ... unload the library
FreeLibrary( hKernel32Lib );
hKernel32Lib = NULL;
pfnSetThreadUILanguage = NULL;
return FALSE;
}
else
{
// call the function
((FUNC_SetThreadUILanguage) pfnSetThreadUILanguage)( dwReserved );
}
}
// unload the library and return success
FreeLibrary( hKernel32Lib );
hKernel32Lib = NULL;
pfnSetThreadUILanguage = NULL;
return TRUE;
}