- Fix gdb2 and regexpl warnings under gcc 4.4.0
[reactos.git] / rosapps / applications / sysutils / regexpl / ShellCommandValue.cpp
1 /* $Id$
2 *
3 * regexpl - Console Registry Explorer
4 *
5 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
6 *
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.
11 *
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.
16 *
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.
21 */
22
23 // ShellCommandValue.cpp: implementation of the CShellCommandValue class.
24 //
25 //////////////////////////////////////////////////////////////////////
26
27 #include "ph.h"
28 #include "RegistryExplorer.h"
29 #include "ShellCommandValue.h"
30 #include "RegistryTree.h"
31 #include "RegistryKey.h"
32
33 #define VALUE_CMD _T("VV")
34 #define VALUE_CMD_LENGTH COMMAND_LENGTH(VALUE_CMD)
35 #define VALUE_CMD_SHORT_DESC VALUE_CMD _T(" command is used to view value.\n")
36
37 //////////////////////////////////////////////////////////////////////
38 // Construction/Destruction
39 //////////////////////////////////////////////////////////////////////
40
41 CShellCommandValue::CShellCommandValue(CRegistryTree& rTree):m_rTree(rTree)
42 {
43 }
44
45 CShellCommandValue::~CShellCommandValue()
46 {
47 }
48
49 BOOL CShellCommandValue::Match(const TCHAR *pchCommand)
50 {
51 if (_tcsicmp(pchCommand,VALUE_CMD) == 0)
52 return TRUE;
53 if (_tcsnicmp(pchCommand,VALUE_CMD _T(".."),VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)
54 return TRUE;
55 if (_tcsnicmp(pchCommand,VALUE_CMD _T("/"),VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
56 return TRUE;
57 if (_tcsnicmp(pchCommand,VALUE_CMD _T("\\"),VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
58 return TRUE;
59 return FALSE;
60 }
61
62 int CShellCommandValue::Execute(CConsole &rConsole, CArgumentParser& rArguments)
63 {
64 rArguments.ResetArgumentIteration();
65 TCHAR *pchCommandItself = rArguments.GetNextArgument();
66
67 TCHAR *pchParameter;
68 TCHAR *pchValueFull = NULL;
69 BOOL blnUnicodeDump = FALSE;
70 BOOL blnBadParameter = FALSE;
71 BOOL blnHelp = FALSE;
72 LONG nError;
73 DWORD dwValueSize;
74 DWORD dwType = REG_NONE;
75 BYTE *pDataBuffer = NULL;
76 TCHAR *pchFilename = NULL;
77
78 if ((_tcsnicmp(pchCommandItself,VALUE_CMD _T(".."),VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
79 (_tcsnicmp(pchCommandItself,VALUE_CMD _T("\\"),VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
80 {
81 pchValueFull = pchCommandItself + VALUE_CMD_LENGTH;
82 }
83 else if (_tcsnicmp(pchCommandItself,VALUE_CMD _T("/"),VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
84 {
85 pchParameter = pchCommandItself + VALUE_CMD_LENGTH;
86 goto CheckValueArgument;
87 }
88
89 while((pchParameter = rArguments.GetNextArgument()) != NULL)
90 {
91 CheckValueArgument:
92 blnBadParameter = FALSE;
93 if ((_tcsicmp(pchParameter,_T("/?")) == 0)
94 ||(_tcsicmp(pchParameter,_T("-?")) == 0))
95 {
96 blnHelp = TRUE;
97 break;
98 }
99 else if (_tcsicmp(pchParameter,_T("/u")) == 0)
100 {
101 blnUnicodeDump = TRUE;
102 }
103 else if ((*pchParameter == _T('/'))&&(*(pchParameter+1) == _T('f')))
104 {
105 pchFilename = pchParameter+2;
106 }
107 else if (!pchValueFull)
108 {
109 pchValueFull = pchParameter;
110 }
111 else
112 {
113 blnBadParameter = TRUE;
114 }
115 if (blnBadParameter)
116 {
117 rConsole.Write(_T("Bad parameter: "));
118 rConsole.Write(pchParameter);
119 rConsole.Write(_T("\n"));
120 }
121 }
122
123 CRegistryKey Key;
124 TCHAR *pchValueName;
125 const TCHAR *pszEmpty = _T("");
126 const TCHAR *pszPath;
127
128 if (blnHelp)
129 {
130 rConsole.Write(GetHelpString());
131
132 if (pDataBuffer)
133 delete pDataBuffer;
134
135 return 0;
136 }
137
138 if (pchValueFull)
139 {
140 if (_tcscmp(pchValueFull,_T("\\")) == 0)
141 goto ValueCommandNAonRoot;
142
143 TCHAR *pchSep = _tcsrchr(pchValueFull,_T('\\'));
144 pchValueName = pchSep?(pchSep+1):(pchValueFull);
145 pszPath = pchSep?pchValueFull:_T(".");
146
147 //if (_tcsrchr(pchValueName,_T('.')))
148 //{
149 // pchValueName = _T("");
150 // pchPath = pchValueFull;
151 //}
152 //else
153 if (pchSep)
154 *pchSep = 0;
155 }
156 else
157 {
158 pchValueName = (TCHAR*)pszEmpty;
159 pszPath = _T(".");
160 }
161
162 if (!m_rTree.GetKey(pszPath,KEY_READ,Key))
163 {
164 rConsole.Write(m_rTree.GetLastErrorDescription());
165 goto SkipValueCommand;
166 }
167
168 if (Key.IsRoot())
169 goto ValueCommandNAonRoot;
170
171 {
172 rConsole.Write(_T("Value name : \""));
173 rConsole.Write(_T("\\"));
174 rConsole.Write(Key.GetKeyName());
175 size_t l = _tcslen(pchValueName);
176 if (l&&
177 (*pchValueName == _T('\"'))&&
178 (pchValueName[l-1] == _T('\"')))
179 {
180 pchValueName[l-1] = 0;
181 pchValueName++;
182 }
183 rConsole.Write(pchValueName);
184 rConsole.Write(_T("\"\n"));
185
186 nError = Key.GetValue(pchValueName,NULL,NULL,&dwValueSize);
187 if (nError == ERROR_SUCCESS)
188 {
189 pDataBuffer = new BYTE [dwValueSize];
190 Key.GetValue(pchValueName,&dwType,pDataBuffer,&dwValueSize);
191 rConsole.Write(_T("Value type : "));
192 rConsole.Write(CRegistryKey::GetValueTypeName(dwType));
193 rConsole.Write(_T("\nValue data : "));
194 switch(dwType)
195 {
196 case REG_DWORD_LITTLE_ENDIAN:
197 {
198 TCHAR Buffer[3];
199 rConsole.Write(_T("0x"));
200 for (unsigned int i = 0 ; i < dwValueSize ; i++)
201 {
202 _stprintf(Buffer,_T("%02X"),*(pDataBuffer+((dwValueSize-1)-i)));
203 rConsole.Write(Buffer);
204 }
205 }
206 rConsole.Write(_T("\n"));
207 break;
208 case REG_DWORD_BIG_ENDIAN:
209 {
210 TCHAR Buffer[3];
211 rConsole.Write(_T("0x"));
212 for (unsigned int i = 0 ; i < dwValueSize ; i++)
213 {
214 _stprintf(Buffer,_T("%02X"),*(pDataBuffer+i));
215 rConsole.Write(Buffer);
216 }
217 }
218 rConsole.Write(_T("\n"));
219 break;
220 case REG_LINK:
221 break;
222 case REG_MULTI_SZ:
223 {
224 TCHAR *pchCurrentString = (TCHAR *)pDataBuffer;
225 rConsole.Write(_T("\n"));
226 while(*pchCurrentString)
227 {
228 rConsole.Write(_T("\""));
229 rConsole.Write(pchCurrentString);
230 rConsole.Write(_T("\"\n"));
231 pchCurrentString += _tcslen(pchCurrentString)+1;
232 }
233 }
234 break;
235 case REG_RESOURCE_LIST:
236 break;
237 case REG_SZ:
238 case REG_EXPAND_SZ:
239 rConsole.Write(_T("\""));
240 rConsole.Write((TCHAR *)pDataBuffer);
241 rConsole.Write(_T("\"\n"));
242 break;
243 case REG_BINARY:
244 default:
245 {
246 TCHAR Buffer[256];
247 DWORD i, j;
248 for (i = 0 ; i < dwValueSize ; i++)
249 {
250 if (i%16 == 0)
251 { // ok this is begining of line
252 rConsole.Write(_T("\n"));
253 // print offset
254 _stprintf(Buffer,_T("0x%08X "),(unsigned int)i);
255 rConsole.Write(Buffer);
256 }
257 else if (i%8 == 0)
258 { // this is the additional space between 7th and 8th byte in current line
259 rConsole.Write(_T(" "));
260 }
261
262 // print current byte
263 unsigned int n = *(pDataBuffer+i);
264 _stprintf(Buffer,_T("%02X "),n);
265 rConsole.Write(Buffer);
266
267 if (i && (i%16 == 15))
268 { // if this is the last byte in line
269 // Dump text representation
270 for (j = i-15; j <= i; j += blnUnicodeDump?2:1)\
271 {
272 if ((j%8 == 0)&&(j%16 != 0))
273 { // this is the additional space between 7th and 8th byte in current line
274 rConsole.Write(_T(" "));
275 }
276 ASSERT(i-j < 16);
277 // write current char representation
278 if (blnUnicodeDump)
279 {
280 ASSERT(j%2 == 0);
281 wchar_t ch = *(TCHAR *)(pDataBuffer+j);
282
283 _stprintf(Buffer,
284 #ifdef _UNICODE
285 _T("%c"),
286 #else
287 // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
288 // %C in format string is a Microsoft extension.
289 _T("%C"),
290 #endif
291 iswprint(ch)?ch:L'.');
292 }
293 else
294 {
295 unsigned char ch = *(pDataBuffer+j);
296
297 _stprintf(Buffer,
298 #ifdef _UNICODE
299 // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
300 // %C in format string is a Microsoft extension.
301 _T("%C"),
302 #else
303 _T("%c"),
304 #endif
305 isprint(ch)?ch:'.');
306 }
307 rConsole.Write(Buffer);
308 } // for
309 } // if
310 } // for
311
312 // print text representation of last line if it is not full (it have less than 16 bytes)
313 // k is pseudo offset
314 for (DWORD k = i; k%16 != 0; k++)
315 {
316 if (k%8 == 0)
317 { // this is the additional space between 7th and 8th byte in current line
318 rConsole.Write(_T(" "));
319 }
320 _tcscpy(Buffer,_T(" ")); // the replacement of two digit of current byte + spacing
321 rConsole.Write(Buffer);
322 if (k && (k%16 == 15))
323 { // if this is the last byte in line
324 ASSERT((k-15)%16 == 0); // k-15 must point at begin of last line
325 for (j = k-15; j < i; j += blnUnicodeDump?2:1)
326 {
327 if (blnUnicodeDump&&(j+1 >= i))
328 { // ok, buffer size is odd number, so we don't display last byte.
329 ASSERT(j+1 == i);
330 break;
331 }
332 if ((j%8 == 0)&&(j%16 != 0))
333 { // this is the additional space between 7th and 8th byte in current line
334 rConsole.Write(_T(" "));
335 }
336
337 // write current char representation
338 if (blnUnicodeDump)
339 {
340 ASSERT(j%2 == 0);
341 wchar_t ch = *(TCHAR *)(pDataBuffer+j);
342
343 _stprintf(Buffer,
344 #ifdef _UNICODE
345 _T("%c"),
346 #else
347 // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
348 // %C in format string is a Microsoft extension.
349 _T("%C"),
350 #endif
351 iswprint(ch)?ch:L'.');
352 }
353 else
354 {
355 unsigned char ch = *(pDataBuffer+j);
356
357 _stprintf(Buffer,
358 #ifdef _UNICODE
359 // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
360 // %C in format string is a Microsoft extension.
361 _T("%C"),
362 #else
363 _T("%c"),
364 #endif
365 isprint(ch)?ch:'.');
366 }
367 rConsole.Write(Buffer);
368 } // for
369 } // if
370 } // for
371 } // default:
372 rConsole.Write(_T("\n"));
373 } // switch
374 rConsole.Write(_T("\n"));
375
376 if (pchFilename)
377 {
378 rConsole.Write(_T("Exporting value data to "));
379 rConsole.Write(pchFilename);
380 rConsole.Write(_T(" ...\n"));
381
382 HANDLE hFile = CreateFile(pchFilename,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
383 if (hFile == INVALID_HANDLE_VALUE)
384 {
385 rConsole.Write(_T("Cannot create new file "));
386 rConsole.Write(pchFilename);
387 rConsole.Write(_T("\n"));
388 goto SkipValueCommand;
389 }
390
391 DWORD dwBytesWritten;
392 if (!WriteFile(hFile,pDataBuffer,dwValueSize,&dwBytesWritten,NULL))
393 {
394 rConsole.Write(_T("Error writting file.\n"));
395 VERIFY(CloseHandle(hFile));
396 goto SkipValueCommand;
397 }
398
399 ASSERT(dwBytesWritten == dwValueSize);
400 VERIFY(CloseHandle(hFile));
401 }
402 }
403 else
404 {
405 rConsole.Write(_T("Error "));
406 TCHAR Buffer[256];
407 rConsole.Write(_itoa(nError,Buffer,10));
408 rConsole.Write(_T("\n"));
409 if (nError == ERROR_FILE_NOT_FOUND)
410 {
411 rConsole.Write(_T("(System cannot find the value specified)\n"));
412 }
413 }
414 }
415
416 SkipValueCommand:
417 if (pDataBuffer)
418 delete pDataBuffer;
419 return 0;
420 ValueCommandNAonRoot:
421 rConsole.Write(VALUE_CMD COMMAND_NA_ON_ROOT);
422 return 0;
423 }
424
425 const TCHAR * CShellCommandValue::GetHelpString()
426 {
427 return VALUE_CMD_SHORT_DESC
428 _T("Syntax: ") VALUE_CMD _T(" [<PATH>][<VALUE_NAME>] [/u] [/?]\n\n")
429 _T(" <PATH> - Optional relative path of key which value will be processed.\n")
430 _T(" <VALUE_NAME> - Name of key's value. Default is key's default value.\n")
431 _T(" /u - On binary dump view as Unicode.\n")
432 _T(" /fFILE - Export value data to FILE.\n")
433 _T(" /? - This help.\n\n")
434 _T("Without parameters, command displays default value of current key.\n");
435 }
436
437 const TCHAR * CShellCommandValue::GetHelpShortDescriptionString()
438 {
439 return VALUE_CMD_SHORT_DESC;
440 }