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 51 CShellCommandDir::CShellCommandDir(CRegistryTree& rTree):m_rTree(rTree) 52 { 53 } 54 55 CShellCommandDir::~CShellCommandDir() 56 { 57 } 58 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 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 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 293 const TCHAR * CShellCommandDir::GetHelpShortDescriptionString() 294 { 295 return DIR_CMD_SHORT_DESC; 296 } 297