1 /*
2 * regexpl - Console Registry Explorer
3 *
4 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22 // ShellCommandDir.cpp: implementation of the CShellCommandDir class.
23 //
24 //////////////////////////////////////////////////////////////////////
25
26 #include "ph.h"
27 #include "RegistryExplorer.h"
28 #include "ShellCommandDir.h"
29 #include "RegistryTree.h"
30 #include "RegistryKey.h"
31 #include "Pattern.h"
32
33 // *** THIS SHOULD GO IN A MINGW/ROS HEADER (tchar.h ???) - Begin
34 #if 1 // #ifndef _ui64tot ???
35 #ifdef _UNICODE
36 #define _ui64tot _ui64tow
37 #else
38 #define _ui64tot _ui64toa
39 #endif
40 #endif
41 // *** THIS SHOULD GO IN A MINGW/ROS HEADER - End
42
43 #define DIR_CMD _T("DIR")
44 #define DIR_CMD_LENGTH COMMAND_LENGTH(DIR_CMD)
45 #define DIR_CMD_SHORT_DESC DIR_CMD _T(" command lists keys and values of any key.\n")
46
47 //////////////////////////////////////////////////////////////////////
48 // Construction/Destruction
49 //////////////////////////////////////////////////////////////////////
50
CShellCommandDir(CRegistryTree & rTree)51 CShellCommandDir::CShellCommandDir(CRegistryTree& rTree):m_rTree(rTree)
52 {
53 }
54
~CShellCommandDir()55 CShellCommandDir::~CShellCommandDir()
56 {
57 }
58
Match(const TCHAR * pchCommand)59 BOOL CShellCommandDir::Match(const TCHAR *pchCommand)
60 {
61 if (_tcsicmp(pchCommand,DIR_CMD) == 0)
62 return TRUE;
63 if (_tcsnicmp(pchCommand,DIR_CMD _T(".."),DIR_CMD_LENGTH+2*sizeof(TCHAR)) == 0)
64 return TRUE;
65 if (_tcsnicmp(pchCommand,DIR_CMD _T("/"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
66 return TRUE;
67 if (_tcsnicmp(pchCommand,DIR_CMD _T("\\"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
68 return TRUE;
69 return FALSE;
70 }
71
Execute(CConsole & rConsole,CArgumentParser & rArguments)72 int CShellCommandDir::Execute(CConsole &rConsole, CArgumentParser& rArguments)
73 {
74 rArguments.ResetArgumentIteration();
75
76 BOOL blnDo = TRUE,blnBadParameter, blnHelp = FALSE;
77 TCHAR *pszParameter;
78 TCHAR *pszCommandItself = rArguments.GetNextArgument();
79 TCHAR *pszKey = NULL;
80
81 if ((_tcsnicmp(pszCommandItself,DIR_CMD _T(".."),DIR_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
82 (_tcsnicmp(pszCommandItself,DIR_CMD _T("\\"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
83 {
84 pszKey = pszCommandItself + DIR_CMD_LENGTH;
85 }
86 else if (_tcsnicmp(pszCommandItself,DIR_CMD _T("/"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
87 {
88 pszParameter = pszCommandItself + DIR_CMD_LENGTH;
89 goto CheckDirArgument;
90 }
91
92 while((pszParameter = rArguments.GetNextArgument()) != NULL)
93 {
94 CheckDirArgument:
95 blnBadParameter = FALSE;
96 if ((_tcsicmp(pszParameter,_T("/?")) == 0)
97 ||(_tcsicmp(pszParameter,_T("-?")) == 0))
98 {
99 blnHelp = TRUE;
100 blnDo = pszKey != NULL;
101 }
102 else if (!pszKey)
103 {
104 pszKey = pszParameter;
105 blnDo = TRUE;
106 }
107 else
108 {
109 blnBadParameter = TRUE;
110 }
111 if (blnBadParameter)
112 {
113 rConsole.Write(_T("Bad parameter: "));
114 rConsole.Write(pszParameter);
115 rConsole.Write(_T("\n"));
116 }
117 }
118
119 const TCHAR *pszPattern = PATTERN_MATCH_ALL;
120 const TCHAR *pszPath = _T(".");
121
122 if (pszKey)
123 {
124 pszPath = pszKey;
125
126 TCHAR *pch = pszKey;
127 while(*pch) // search end of string
128 pch++;
129
130 if (pch > pszKey) // last non-null char
131 pch--;
132
133 if (*pch != _T('\\'))
134 {
135 while ((pch > pszKey) && (*pch != _T('\\')))
136 pch--;
137
138 if (*pch == _T('\\'))
139 {
140 pszPattern = pch+1;
141
142 if (pch > pszKey)
143 {
144 ASSERT(*pch == _T('\\'));
145 *pch = 0;
146 }
147 else if (*pch == _T('\\'))
148 {
149 pszPath = _T("\\");
150 }
151 }
152 else
153 {
154 pszPattern = pszKey;
155 pszPath = _T(".");
156 }
157 }
158 }
159
160 CRegistryKey Key;
161
162 if (!m_rTree.GetKey(pszPath,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,Key))
163 {
164 const TCHAR *pszErrorMsg = m_rTree.GetLastErrorDescription();
165 rConsole.Write(pszErrorMsg);
166 blnDo = FALSE;
167 }
168
169 if (blnHelp)
170 {
171 rConsole.Write(GetHelpString());
172 }
173
174 LONG nError;
175
176 if (!blnDo)
177 return 0;
178
179 rConsole.Write(_T("\n Key is "));
180 rConsole.Write(Key.GetKeyName());
181
182 if (!Key.IsRoot())
183 {
184 rConsole.Write(_T("\n Last modify time is "));
185 rConsole.Write(Key.GetLastWriteTime());
186 }
187
188 rConsole.Write(_T("\n\n"));
189 unsigned __int64 nTotalItems = 0;
190
191 try
192 {
193 ASSERT(nTotalItems == 0);
194 rConsole.Write(_T("\t(KEY)\t\t\t\t..\\\n")); // parent key abstraction
195 nTotalItems = 1;
196
197 DWORD dwMaxSubkeyNameLength;
198 nError = Key.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
199 if (nError != ERROR_SUCCESS)
200 throw nError;
201
202 TCHAR *pszSubkeyNameBuffer = new (std::nothrow) TCHAR[dwMaxSubkeyNameLength];
203 if (!pszSubkeyNameBuffer)
204 throw ERROR_OUTOFMEMORY;
205
206 Key.InitSubkeyEnumeration(pszSubkeyNameBuffer,dwMaxSubkeyNameLength);
207 while ((nError = Key.GetNextSubkeyName()) == ERROR_SUCCESS)
208 {
209 if (PatternMatch(pszPattern,pszSubkeyNameBuffer))
210 {
211 rConsole.Write(_T("\t(KEY)\t\t\t\t"));
212 rConsole.Write(pszSubkeyNameBuffer);
213 rConsole.Write(_T("\\\n"));
214 nTotalItems++;
215 }
216 }
217
218 delete[] pszSubkeyNameBuffer;
219
220 if (nError != ERROR_NO_MORE_ITEMS)
221 throw nError;
222
223 DWORD dwMaxValueNameBufferSize;
224 nError = Key.GetMaxValueNameLength(dwMaxValueNameBufferSize);
225 if (nError != ERROR_SUCCESS)
226 throw nError;
227
228 TCHAR *pchValueNameBuffer = new (std::nothrow) TCHAR[dwMaxValueNameBufferSize];
229 if (!pchValueNameBuffer)
230 throw ERROR_OUTOFMEMORY;
231
232
233 DWORD Type;
234 Key.InitValueEnumeration(pchValueNameBuffer,
235 dwMaxValueNameBufferSize,
236 NULL,
237 0,
238 &Type);
239
240 DWORD dwValueNameActualLength;
241 const TCHAR *pszValueTypeName;
242 unsigned int nTabSize = rConsole.GetTabWidth();
243 unsigned int nTabs;
244 while((nError = Key.GetNextValue(&dwValueNameActualLength)) == ERROR_SUCCESS)
245 {
246 if (PatternMatch(pszPattern,pchValueNameBuffer))
247 {
248 rConsole.Write(_T("\t"));
249 pszValueTypeName = CRegistryKey::GetValueTypeName(Type);
250 nTabs = _tcslen(pszValueTypeName)/nTabSize;
251 nTabs = (nTabs < 4)?(4-nTabs):1;
252 rConsole.Write(pszValueTypeName);
253 while(nTabs--)
254 rConsole.Write(_T("\t"));
255 rConsole.Write((dwValueNameActualLength == 0)?_T("(Default)"):pchValueNameBuffer);
256 rConsole.Write(_T("\n"));
257 nTotalItems++;
258 }
259 }
260
261 delete[] pchValueNameBuffer;
262
263 if (nError != ERROR_NO_MORE_ITEMS)
264 throw nError;
265
266 } // try
267 catch (LONG nError)
268 {
269 rConsole.Write(_T("Error "));
270 TCHAR Buffer[256];
271 rConsole.Write(_itoa(nError,Buffer,10));
272 rConsole.Write(_T("\n"));
273 }
274
275 rConsole.Write(_T("\n Total: "));
276 TCHAR Buffer[256];
277 rConsole.Write(_ui64tot(nTotalItems,Buffer,10));
278 rConsole.Write(_T(" item(s) listed.\n"));
279
280 return 0;
281 }
282
GetHelpString()283 const TCHAR * CShellCommandDir::GetHelpString()
284 {
285 return DIR_CMD_SHORT_DESC
286 _T("Syntax: ") DIR_CMD _T(" [<PATH>\\][<PATTERN>] [/?]\n\n")
287 _T(" <PATH> - Optional relative path to the key on which command will be executed\n")
288 _T(" <PATTERN> - Optional pattern. Default is the all matching pattern.")
289 _T(" /? - This help.\n\n")
290 _T("Without parameters, command lists keys and values of current key.\n");
291 }
292
GetHelpShortDescriptionString()293 const TCHAR * CShellCommandDir::GetHelpShortDescriptionString()
294 {
295 return DIR_CMD_SHORT_DESC;
296 }
297