reactos/rosapps/sysutils/regnav.c

636 lines
12 KiB
C
Raw Normal View History

/* $Id: regnav.c,v 1.4 2000/09/11 20:17:02 ea Exp $
*
* regnav.c
*
* Copyright (c) 1998-2000 Emanuele Aliberti
*
* --------------------------------------------------------------------
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this software; see the file COPYING.LIB. If
* not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*
* --------------------------------------------------------------------
* ReactOS system registry console navigation tool.
*/
//#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <assert.h>
#include "win32err.h"
#define INPUT_BUFFER_SIZE 512
#define COMMAND_NOT_FOUND NULL
#define CURRENT_PATH_SIZE 1024
LPCTSTR STR_HKEY_CLASSES_ROOT = _TEXT("HKEY_CLASSES_ROOT");
LPCTSTR STR_HKEY_CURRENT_USER = _TEXT("HKEY_CURRENT_USER");
LPCTSTR STR_HKEY_LOCAL_MACHINE = _TEXT("HKEY_LOCAL_MACHINE");
LPCTSTR STR_HKEY_USERS = _TEXT("HKEY_USERS");
LPCTSTR STR_HKEY_CURRENT_CONFIG = _TEXT("HKEY_CURRENT_CONFIG");
LPCTSTR STR_HKEY_PERFORMANCE_DATA = _TEXT("HKEY_PERFORMANCE_DATA");
LPTSTR app_name = _TEXT("regnav");
LPCTSTR app_ver = _TEXT("1.0.5");
HANDLE CurrentWorkingKey = INVALID_HANDLE_VALUE; /* \ */
TCHAR CurrentPath [CURRENT_PATH_SIZE] = _TEXT("\\");
BOOL Done = FALSE;
INT LastExitCode = 0;
/* === COMMANDS === */
#define CMDPROTOIF (int argc,LPTSTR argv[])
typedef int (*CommandFunction) CMDPROTOIF;
#define CMDPROTO(n) int n CMDPROTOIF
typedef
struct _COMMAND_DESCRIPTOR
{
LPCTSTR Name;
LPCTSTR ShortDescription;
LPCTSTR Usage;
CommandFunction Command;
int MinArgc;
int MaxArgc;
} COMMAND_DESCRIPTOR, * PCOMMAND_DESCRIPTOR;
CMDPROTO(cmd_ck);
CMDPROTO(cmd_exit);
CMDPROTO(cmd_help);
CMDPROTO(cmd_ls);
CMDPROTO(cmd_pwk);
CMDPROTO(cmd_ver);
COMMAND_DESCRIPTOR
CommandsTable [] =
{
{
_TEXT("ck"),
_TEXT("Change the working key."),
_TEXT("CK key\n\nChange the working key."),
cmd_ck,
1,
2
},
{
_TEXT("exit"),
_TEXT("Terminate the application."),
_TEXT("EXIT\n\nTerminate the application."),
cmd_exit,
1,
1
},
{
_TEXT("help"),
_TEXT("Print this commands summary, or a command's synopsis."),
_TEXT("HELP [command]\n\nPrint commands summary, or a command's synopsis."),
cmd_help,
1,
2
},
{
_TEXT("ls"),
_TEXT("List a key's values and subkeys."),
_TEXT("LS [key]\n\nList a key's values and subkeys."),
cmd_ls,
1,
2
},
{
_TEXT("pwk"),
_TEXT("Print the current working key."),
_TEXT("PWK\n\nPrint the current working key."),
cmd_pwk,
1,
1
},
{
_TEXT("ver"),
_TEXT("Print version information."),
_TEXT("VER\n\nPrint version information."),
cmd_ver,
1,
1
},
/* End of array marker */
{ NULL }
};
/* === CMD MANAGER === */
PCOMMAND_DESCRIPTOR
DecodeVerb( LPCTSTR Name )
{
register int i;
for ( i = 0;
CommandsTable[i].Name;
++i
)
{
if (0 == lstrcmpi(CommandsTable[i].Name,Name))
{
return & CommandsTable[i];
}
}
return COMMAND_NOT_FOUND;
}
/* === Visual key name manager */
typedef
struct _SPLIT_KEY_NAME
{
TCHAR Host [32];
HANDLE Hive;
TCHAR SubKey [_MAX_PATH];
} SPLIT_KEY_NAME, * PSPLIT_KEY_NAME;
PSPLIT_KEY_NAME
ParseKeyName(
LPTSTR KeyName,
PSPLIT_KEY_NAME k
)
{
TCHAR *r = KeyName;
TCHAR *w = NULL;
TCHAR SystemKey [64];
assert(r && k);
ZeroMemory( k, sizeof (SPLIT_KEY_NAME) );
k->Hive = INVALID_HANDLE_VALUE;
/* HOST */
if (r[0] == _TEXT('\\') && r[1] == _TEXT('\\'))
{
for ( r += 2, w = k->Host;
(*r && (*r != _TEXT('\\')));
++r
) {
*w++ = *r;
}
if (w) *w = _TEXT('\0');
}
/* SYSTEM KEY */
if (*r == _TEXT('\\')) ++r;
for ( w = SystemKey;
(*r && (*r != _TEXT('\\')));
++r
) {
*w++ = *r;
}
if (w) *w = _TEXT('\0');
if (0 == lstrcmpi(STR_HKEY_CLASSES_ROOT, SystemKey))
{
k->Hive = HKEY_CLASSES_ROOT;
}
else if (0 == lstrcmpi(STR_HKEY_CURRENT_USER, SystemKey))
{
k->Hive = HKEY_CURRENT_USER;
}
else if (0 == lstrcmpi(STR_HKEY_LOCAL_MACHINE, SystemKey))
{
k->Hive = HKEY_LOCAL_MACHINE;
}
else if (0 == lstrcmpi(STR_HKEY_USERS, SystemKey))
{
k->Hive = HKEY_USERS;
}
else if (0 == lstrcmpi(STR_HKEY_CURRENT_CONFIG, SystemKey))
{
k->Hive = HKEY_CURRENT_CONFIG;
}
else if (0 == lstrcmpi(STR_HKEY_PERFORMANCE_DATA, SystemKey))
{
k->Hive = HKEY_PERFORMANCE_DATA;
}
/* SUBKEY */
if (*r == _TEXT('\\')) ++r;
for ( w = k->SubKey;
(*r);
++r
) {
*w++ = *r;
}
if (w) *w = _TEXT('\0');
/* OK */
return k;
}
/* === COMMANDS === */
/**********************************************************************
* ck
*
* DESCRIPTION
* Change the current working key.
*/
CMDPROTO(cmd_ck)
{
LONG rv;
SPLIT_KEY_NAME k;
if (0 == lstrcmp(argv[1], _TEXT("..")))
{
_tprintf( _TEXT("Change to parent not implemented yet.\n") );
return EXIT_FAILURE;
}
if (INVALID_HANDLE_VALUE != CurrentWorkingKey)
{
RegCloseKey(CurrentWorkingKey);
CurrentWorkingKey = INVALID_HANDLE_VALUE;
}
if (NULL == ParseKeyName(argv[1], &k))
{
return EXIT_FAILURE;
}
rv = RegOpenKeyEx(
k.Hive, /* handle of open key */
k.SubKey, /* address of name of subkey to open */
0, /* reserved */
(REGSAM) KEY_ENUMERATE_SUB_KEYS,/* security access mask */
& CurrentWorkingKey /* address of handle of open key */
);
if (ERROR_SUCCESS != rv)
{
PrintWin32Error(L"RegOpenKeyEx",GetLastError());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/**********************************************************************
* exit
*
* DESCRIPTION
* Terminate.
*/
CMDPROTO(cmd_exit)
{
Done = TRUE;
_tprintf( _TEXT("Quitting...\n") );
return EXIT_SUCCESS;
}
/**********************************************************************
* help
*
* DESCRIPTION
* Print help.
*/
CMDPROTO(cmd_help)
{
PCOMMAND_DESCRIPTOR cd = NULL;
if (1 == argc)
{
int CommandIndex;
for ( CommandIndex = 0;
(CommandsTable[CommandIndex].Name);
CommandIndex++
)
{
_tprintf(
_TEXT("%s\t%s\n"),
CommandsTable[CommandIndex].Name,
CommandsTable[CommandIndex].ShortDescription
);
}
return EXIT_SUCCESS;
}
if ((cd = DecodeVerb(argv[1])))
{
_tprintf(
_TEXT("%s\n"),
cd->Usage
);
return EXIT_SUCCESS;
}
_tprintf(
_TEXT("Unknown help item \"%s\".\n"),
argv[1]
);
return EXIT_FAILURE;
}
/**********************************************************************
* ls
*
* DESCRIPTION
* List a key.
*/
CMDPROTO(cmd_ls)
{
LONG rv;
DWORD dwIndexK = 0;
DWORD dwIndexV = 0;
UCHAR Name [256];
DWORD cbName;
UCHAR Class [256];
DWORD cbClass;
UCHAR Data [1024];
DWORD cbData;
DWORD Type;
FILETIME ft;
SYSTEMTIME st;
/* _self is always present */
_tprintf( _TEXT(".\\\n") );
/* _root directory? */
if (INVALID_HANDLE_VALUE == CurrentWorkingKey)
{
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_CLASSES_ROOT
);
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_CURRENT_USER
);
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_LOCAL_MACHINE
);
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_USERS
);
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_CURRENT_CONFIG
);
_tprintf(
_TEXT("%s\\\n"),
STR_HKEY_PERFORMANCE_DATA
);
return EXIT_SUCCESS;
}
/* _parent is present only if _self != _root
* (FIXME: change it when RegConnect... available)
*/
_tprintf( _TEXT("..\\\n") );
/* Enumerate subkeys of the current key. */
do {
cbName = sizeof(Name);
cbClass = sizeof(Class);
rv = RegEnumKeyEx(
CurrentWorkingKey, /* handle of key to enumerate */
dwIndexK, /* index of subkey to enumerate */
Name, /* address of buffer for subkey name */
& cbName, /* address for size of subkey buffer */
NULL, /* reserved */
Class, /* address of buffer for class string */
& cbClass, /* address for size of class buffer */
& ft /* address for time key last written to */
);
if (ERROR_SUCCESS == rv)
{
FileTimeToSystemTime( & ft, & st );
if (cbClass)
_tprintf(
_TEXT("%-32s\\ %4d-%02d-%02d %02d:%02d [%s]\n"),
Name,
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute,
Class
);
else
_tprintf(
_TEXT("%-32s\\ %4d-%02d-%02d %02d:%02d\n"),
Name,
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute
);
++dwIndexK;
}
} while (ERROR_SUCCESS == rv);
/* Enumerate key's values */
do {
cbName = sizeof(Name);
cbData = sizeof(Data);
rv = RegEnumValue(
CurrentWorkingKey, /* handle of key to query */
dwIndexV, /* index of value to query */
Name, /* address of buffer for value string */
& cbName, /* address for size of value buffer */
NULL, /* reserved */
& Type, /* address of buffer for type code */
Data, /* address of buffer for value data */
& cbData /* address for size of data buffer */
);
if (ERROR_SUCCESS == rv)
{
switch (Type)
{
case REG_DWORD:
_tprintf(
_TEXT("%s = *REG_DWORD*\n"),
Name
);
break;
case REG_EXPAND_SZ:
/* expand env vars */
break;
case REG_LINK:
/* reparse! */
break;
case REG_SZ:
_tprintf(
_TEXT("%s = \"%s\"\n"),
Name,
Data
);
break;
}
++dwIndexV;
}
} while (ERROR_SUCCESS == rv);
return (UINT) dwIndexK + (UINT) dwIndexV;
}
/**********************************************************************
* pwk
*
* DESCRIPTION
* Print the current working key.
*/
CMDPROTO(cmd_pwk)
{
if (INVALID_HANDLE_VALUE == CurrentWorkingKey)
{
_tprintf( _TEXT("[\\]\n") );
return EXIT_SUCCESS;
}
_tprintf(
_TEXT("[%s]\n"),
CurrentPath
);
return EXIT_SUCCESS;
}
/**********************************************************************
* ver
*
* DESCRIPTION
* Print version information.
*/
CMDPROTO(cmd_ver)
{
_tprintf(
_TEXT("\
%s version %s (compiled on %s, at %s)\n\
ReactOS Console Registry Navigator\n\
Copyright (c) 1998-2000 Emanuele Aliberti\n\n"),
app_name,
app_ver,
_TEXT(__DATE__),
_TEXT(__TIME__)
);
return EXIT_SUCCESS;
}
/* === UTILITIES === */
#define ARGV_SIZE 32
INT
ParseCommandLine(
LPTSTR InputBuffer,
LPTSTR argv[]
)
{
register INT n = 0;
register TCHAR *c = InputBuffer;
assert(InputBuffer);
do
{
for ( ;
( *c
&& ( (*c == _TEXT(' '))
|| (*c == _TEXT('\t'))
|| (*c == _TEXT('\n'))
)
);
++c
);
argv[n++] = c;
if (*c)
{
for ( ;
( *c
&& (*c != _TEXT(' '))
&& (*c != _TEXT('\t'))
&& (*c != _TEXT('\n'))
);
++c
);
*c++ = _TEXT('\0');
}
} while ( *c );
return n;
}
VOID
DisplayPrompt(VOID)
{
_tprintf(
_TEXT("[%s] "),
CurrentPath
);
}
/* === MAIN === */
int
main(
int argc,
char * argv []
)
{
TCHAR InputBuffer [INPUT_BUFFER_SIZE];
PCOMMAND_DESCRIPTOR cd;
INT LocalArgc;
LPTSTR LocalArgv [ARGV_SIZE];
while (!Done)
{
DisplayPrompt();
_fgetts(
InputBuffer,
(sizeof InputBuffer / sizeof (TCHAR)),
stdin
);
if (0 == lstrlen(InputBuffer)) continue;
LocalArgc = ParseCommandLine(InputBuffer, LocalArgv);
if (LocalArgc && (cd = DecodeVerb(LocalArgv[0])))
{
if (LocalArgc < cd->MinArgc)
{
_tprintf(
_TEXT("Too few arguments. Type \"HELP %s\".\n"),
LocalArgv[0]
);
continue;
}
if (LocalArgc > cd->MaxArgc)
{
_tprintf(
_TEXT("Too many arguments. Type \"HELP %s\".\n"),
LocalArgv[0]
);
continue;
}
LastExitCode = cd->Command(
LocalArgc,
LocalArgv
);
continue;
}
_tprintf(
_TEXT("Unknown command (\"%s\").\n"),
LocalArgv[0]
);
}
return EXIT_SUCCESS;
}
/* EOF */