1 /* $Id: RegistryExplorer.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
3 * regexpl - Console Registry Explorer
5 * Copyright (C) 2000 Nedko Arnaoudov <nedkohome@atia.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 // Registry Explorer.cpp : Defines the entry point for the console application.
27 #include "RegistryExplorer.h"
29 #include "RegistryKey.h"
30 #include "RegistryTree.h"
31 #include "SecurityDescriptor.h"
32 #include "ArgumentParser.h"
33 #include "ShellCommandsLinkedList.h"
34 #include "ShellCommandExit.h"
35 #include "ShellCommandVersion.h"
36 #include "ShellCommandHelp.h"
37 #include "ShellCommandDir.h"
38 #include "ShellCommandChangeKey.h"
39 #include "ShellCommandValue.h"
40 #include "ShellCommandOwner.h"
41 #include "ShellCommandDACL.h"
42 #include "ShellCommandSACL.h"
43 #include "ShellCommandDOKA.h"
44 #include "ShellCommandConnect.h"
45 #include "ShellCommandNewKey.h"
46 #include "ShellCommandDeleteKey.h"
47 #include "ShellCommandSetValue.h"
48 #include "ShellCommandDeleteValue.h"
50 TCHAR pchCurrentKey
[PROMPT_BUFFER_SIZE
];
52 CRegistryTree
Tree(PROMPT_BUFFER_SIZE
+1);
55 const TCHAR
* ppchRootKeys
[7] =
57 _T("HKEY_CLASSES_ROOT"),
58 _T("HKEY_CURRENT_USER"),
59 _T("HKEY_LOCAL_MACHINE"),
61 _T("HKEY_PERFORMANCE_DATA"),
62 _T("HKEY_CURRENT_CONFIG"),
63 _T("HKEY_DYN_DATA") //win9x only?
66 BOOL g_blnCompletionCycle
= TRUE
;
68 const TCHAR
* CompletionCallback(unsigned __int64
& rnIndex
, const BOOL
*pblnForward
, const TCHAR
*pchContext
, const TCHAR
*pchBegin
)
70 #define COMPLETION_BUFFER_SIZE 4096
71 static TCHAR pchBuffer
[COMPLETION_BUFFER_SIZE
];
72 CRegistryKey
*pKey
= NULL
;
73 CRegistryTree
*pTree
= NULL
;
74 unsigned __int64 nTotalKeys
= 0;
75 unsigned __int64 nTotalValues
= 0;
76 unsigned __int64 nTotalItems
= 0;
80 CompletionMatch(const TCHAR
*pchText
, CompletionMatch
**pNext
)
82 BOOL b
= _tcschr(pchText
,_T(' ')) != NULL
;
83 size_t s
= _tcslen(pchText
);
84 m_pchText
= new TCHAR
[s
+(b
?3:1)];
87 m_pchText
[0] = _T('\"');
88 _tcscpy(m_pchText
+1,pchText
);
89 m_pchText
[s
+1] = _T('\"');
94 _tcscpy(m_pchText
,pchText
);
109 const TCHAR
*GetText(unsigned __int64 dwReverseIndex
)
114 return m_pNext
->GetText(dwReverseIndex
-1);
122 CompletionMatch
*m_pNext
;
124 CompletionMatch
*pRootMatch
= NULL
;
126 BOOL blnCompletionOnKeys
= TRUE
;
127 BOOL blnCompletionOnValues
= TRUE
;
129 while(*pchContext
&& _istspace(*pchContext
))
134 /* if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
135 (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
136 (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
137 (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
138 (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
140 blnCompletionOnValues = FALSE;
142 // else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
144 // blnCompletionOnKeys = FALSE;
147 const TCHAR
*pchKey
= _tcsrchr(pchBegin
,_T('\\'));
148 DWORD nBufferOffset
= 0;
151 nBufferOffset
= pchKey
-pchBegin
+1;
152 if (nBufferOffset
>= COMPLETION_BUFFER_SIZE
-1)
154 if (pRootMatch
) delete pRootMatch
;
157 return _T("internal error");
159 _tcsncpy(pchBuffer
,pchBegin
,nBufferOffset
);
160 pchBuffer
[nBufferOffset
] = 0;
162 pTree
= new CRegistryTree(Tree
);
163 if ((_tcscmp(pTree
->GetCurrentPath(),Tree
.GetCurrentPath()) != 0)||(!pTree
->ChangeCurrentKey(pchBuffer
)))
171 pKey
= pTree
->GetCurrentKey();
176 pKey
= Tree
.GetCurrentKey();
181 for(unsigned int i
= 0 ; i
< sizeof(ppchRootKeys
)/sizeof(TCHAR
*) ; i
++)
185 CompletionMatch
*p
= new CompletionMatch(ppchRootKeys
[i
],&pRootMatch
);
186 if (!p
|| !p
->GetText(0))
188 if (pRootMatch
) delete pRootMatch
;
191 return _T("Out of memory");
199 if (blnCompletionOnKeys
)
201 /* if (_tcslen(pchBegin) == 0)
203 p = new CompletionMatch(_T(".."),&pRootMatch);
204 if (!p || !p->GetText(0))
206 if (pRootMatch) delete pRootMatch;
209 return _T("Out of memory");
215 pKey
->InitSubKeyEnumeration();
216 TCHAR
*pchSubKeyName
;
217 while ((pchSubKeyName
= pKey
->GetSubKeyName(dwError
)) != NULL
)
219 if (_tcsnicmp(pchSubKeyName
,pchBegin
,_tcslen(pchBegin
)) == 0)
223 p
= new CompletionMatch(pchSubKeyName
,&pRootMatch
);
224 if (!p
|| !p
->GetText(0))
226 if (pRootMatch
) delete pRootMatch
;
229 return _T("Out of memory");
233 if ((dwError
!= ERROR_SUCCESS
)&&(dwError
!= ERROR_NO_MORE_ITEMS
))
235 if (pRootMatch
) delete pRootMatch
;
242 if (blnCompletionOnValues
)
244 pKey
->InitValueEnumeration();
246 DWORD dwValueNameLength
, dwMaxValueNameLength
;
247 dwError
= pKey
->GetMaxValueNameLength(dwMaxValueNameLength
);
248 if (dwError
!= ERROR_SUCCESS
)
250 if (pRootMatch
) delete pRootMatch
;
256 dwMaxValueNameLength
++;
257 pchValueName
= new TCHAR
[dwMaxValueNameLength
];
260 if (pRootMatch
) delete pRootMatch
;
263 return _T("Out of memory");
267 dwValueNameLength
= dwMaxValueNameLength
;
268 //dwValueSize = dwMaxValueSize;
269 dwError
= pKey
->GetNextValue(pchValueName
,dwValueNameLength
,NULL
,NULL
,NULL
);
270 if (dwError
== ERROR_NO_MORE_ITEMS
) break;
271 if (dwError
!= ERROR_SUCCESS
)
273 if (pRootMatch
) delete pRootMatch
;
279 if (((dwValueNameLength
== 0) && (_tcslen(pchBegin
) == 0))||
280 (_tcsnicmp(pchValueName
,pchBegin
,_tcslen(pchBegin
)) == 0))
284 p
= new CompletionMatch((dwValueNameLength
== 0)?_T("(Default)"):pchValueName
,&pRootMatch
);
285 if (!p
|| !p
->GetText(0))
287 if (pRootMatch
) delete pRootMatch
;
290 return _T("Out of memory");
294 delete [] pchValueName
;
297 if (rnIndex
>= nTotalItems
)
298 rnIndex
= nTotalItems
-1;
304 if (rnIndex
>= nTotalItems
)
306 if (g_blnCompletionCycle
)
316 else if (g_blnCompletionCycle
)
317 rnIndex
= nTotalItems
-1;
321 const TCHAR
*pchName
;
322 if (nTotalItems
== 0)
330 ASSERT(rnIndex
< nTotalItems
);
331 pchName
= pRootMatch
->GetText(nTotalItems
-rnIndex
-1);
338 return _T("internal error");
340 DWORD dwBufferFull
= _tcslen(pchName
);
341 if (dwBufferFull
>= COMPLETION_BUFFER_SIZE
-nBufferOffset
)
343 dwBufferFull
= COMPLETION_BUFFER_SIZE
-1-nBufferOffset
;
345 _tcsncpy(pchBuffer
+nBufferOffset
,pchName
,dwBufferFull
);
346 if ((dwBufferFull
< COMPLETION_BUFFER_SIZE
-1)&&(rnIndex
< nTotalKeys
))
347 pchBuffer
[nBufferOffset
+dwBufferFull
++] = _T('\\');
348 pchBuffer
[nBufferOffset
+dwBufferFull
] = 0;
356 BOOL blnCommandExecutionInProgress
= FALSE
;
358 BOOL WINAPI
HandlerRoutine(DWORD dwCtrlType
)
363 case CTRL_BREAK_EVENT
:
364 if (blnCommandExecutionInProgress
)
375 Console
.Write(_T("\n"));
376 Console
.DisableWrite();
384 //int _tmain(/*int argc, TCHAR* argv[], TCHAR* envp[]*/)
387 CShellCommandsLinkedList
CommandsList(Console
);
389 CShellCommandExit ExitCommand
;
390 CommandsList
.AddCommand(&ExitCommand
);
392 CShellCommandVersion VersionCommand
;
393 CommandsList
.AddCommand(&VersionCommand
);
395 CShellCommandHelp
HelpCommand(CommandsList
);
396 CommandsList
.AddCommand(&HelpCommand
);
398 CShellCommandDir
DirCommand(Tree
);
399 CommandsList
.AddCommand(&DirCommand
);
401 CShellCommandChangeKey
ChangeKeyCommand(Tree
);
402 CommandsList
.AddCommand(&ChangeKeyCommand
);
404 CShellCommandValue
ValueCommand(Tree
);
405 CommandsList
.AddCommand(&ValueCommand
);
407 CShellCommandOwner
OwnerCommand(Tree
);
408 CommandsList
.AddCommand(&OwnerCommand
);
410 CShellCommandDACL
DACLCommand(Tree
);
411 CommandsList
.AddCommand(&DACLCommand
);
413 CShellCommandSACL
SACLCommand(Tree
);
414 CommandsList
.AddCommand(&SACLCommand
);
416 CShellCommandDOKA
DOKACommand(Tree
);
417 CommandsList
.AddCommand(&DOKACommand
);
419 CShellCommandConnect
ConnectCommand(Tree
);
420 CommandsList
.AddCommand(&ConnectCommand
);
422 CShellCommandNewKey
NewKeyCommand(Tree
);
423 CommandsList
.AddCommand(&NewKeyCommand
);
425 CShellCommandDeleteKey
DeleteKeyCommand(Tree
);
426 CommandsList
.AddCommand(&DeleteKeyCommand
);
428 CShellCommandSetValue
SetValueCommand(Tree
);
429 CommandsList
.AddCommand(&SetValueCommand
);
431 CShellCommandDeleteValue
DeleteValueCommand(Tree
);
432 CommandsList
.AddCommand(&DeleteValueCommand
);
434 CArgumentParser Parser
;
438 // input buffer size in chars
439 #define INPUT_BUFFER_SIZE 1024
440 //#define INPUT_BUFFER_SIZE 128
441 //#define INPUT_BUFFER_SIZE 10
445 pchCommand
= Console
.Init(INPUT_BUFFER_SIZE
,10);
446 if (pchCommand
== NULL
)
448 _ftprintf(stderr
,_T("Cannot initialize console.\n"));
452 Console
.SetReplaceCompletionCallback(CompletionCallback
);
454 WORD wOldConsoleAttribute
;
455 if (!Console
.GetTextAttribute(wOldConsoleAttribute
)) goto Abort
;
457 Console
.SetTitle(_T("Registry Explorer"));
458 Console
.SetTextAttribute(FOREGROUND_BLUE
|FOREGROUND_GREEN
|FOREGROUND_RED
|FOREGROUND_INTENSITY
);
460 VERIFY(SetConsoleCtrlHandler((PHANDLER_ROUTINE
)HandlerRoutine
,TRUE
));
462 if (!Console
.Write(HELLO_MSG
463 //(_L(__TIMESTAMP__))
466 Tree
.SetDesiredOpenKeyAccess(KEY_READ
);
470 // TODO: make prompt user-customizable
471 Console
.EnableWrite();
472 _tcscpy(pchCurrentKey
,Tree
.GetCurrentPath());
473 Console
.Write(pchCurrentKey
);
474 Console
.Write(_T("\n# "));
475 Console
.FlushInputBuffer();
477 blnCommandExecutionInProgress
= FALSE
;
479 // Set command line color
480 // Console.SetTextAttribute(/*FOREGROUND_BLUE|*/FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
481 if (!Console
.ReadLine()) goto Abort
;
484 // Console.SetTextAttribute(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
486 Console
.BeginScrollingOperation();
487 blnCommandExecutionInProgress
= TRUE
;
490 // Parse command line (1st step - convert to multi sz)
491 Parser
.SetArgumentList(pchCommand
);
493 int nCommandReturnValue
;
494 switch(CommandsList
.Execute(Parser
,nCommandReturnValue
))
496 case -1: // not recognized command
498 Parser
.ResetArgumentIteration();
499 TCHAR
*pchCommandItself
= Parser
.GetNextArgument();
500 size_t cmdlen
= _tcslen(pchCommandItself
);
502 (pchCommandItself
[cmdlen
-1] != _T('\\'))||
503 (Parser
.GetNextArgument())||
504 (!Tree
.ChangeCurrentKey(pchCommandItself
)))
506 Console
.Write(_T("Unknown command \""));
507 Console
.Write(pchCommandItself
);
508 Console
.Write(_T("\"\n"));
511 case -2: // empty line
513 case 0: // exit command
515 Console
.SetTextAttribute(wOldConsoleAttribute
);
518 Console
.Write(_T("\n"));
523 _ftprintf(stderr
,_T("Abnormal program termination.\nPlease report bugs to ") EMAIL
_T("\n"));