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