no message
authorNedko Arnaudov <nedko@users.sourceforge.net>
Wed, 10 Jan 2001 01:25:29 +0000 (01:25 +0000)
committerNedko Arnaudov <nedko@users.sourceforge.net>
Wed, 10 Jan 2001 01:25:29 +0000 (01:25 +0000)
svn path=/trunk/; revision=1500

29 files changed:
rosapps/sysutils/regexpl/ArgumentParser.cpp
rosapps/sysutils/regexpl/Completion.cpp [new file with mode: 0644]
rosapps/sysutils/regexpl/Completion.h [new file with mode: 0644]
rosapps/sysutils/regexpl/Console.cpp
rosapps/sysutils/regexpl/Console.h
rosapps/sysutils/regexpl/Makefile
rosapps/sysutils/regexpl/Pattern.cpp [new file with mode: 0644]
rosapps/sysutils/regexpl/Pattern.h [new file with mode: 0644]
rosapps/sysutils/regexpl/RegistryExplorer.cpp
rosapps/sysutils/regexpl/RegistryExplorer.h
rosapps/sysutils/regexpl/RegistryKey.cpp
rosapps/sysutils/regexpl/RegistryKey.h
rosapps/sysutils/regexpl/RegistryTree.cpp
rosapps/sysutils/regexpl/RegistryTree.h
rosapps/sysutils/regexpl/SecurityDescriptor.cpp
rosapps/sysutils/regexpl/SecurityDescriptor.h
rosapps/sysutils/regexpl/ShellCommandChangeKey.cpp
rosapps/sysutils/regexpl/ShellCommandConnect.cpp
rosapps/sysutils/regexpl/ShellCommandDACL.cpp
rosapps/sysutils/regexpl/ShellCommandDeleteKey.cpp
rosapps/sysutils/regexpl/ShellCommandDeleteValue.cpp
rosapps/sysutils/regexpl/ShellCommandDir.cpp
rosapps/sysutils/regexpl/ShellCommandHelp.cpp
rosapps/sysutils/regexpl/ShellCommandNewKey.cpp
rosapps/sysutils/regexpl/ShellCommandOwner.cpp
rosapps/sysutils/regexpl/ShellCommandSACL.cpp
rosapps/sysutils/regexpl/ShellCommandSetValue.cpp
rosapps/sysutils/regexpl/ShellCommandValue.cpp
rosapps/sysutils/regexpl/ph.h

index d857c1b..95a024a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ArgumentParser.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ArgumentParser.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -44,29 +44,29 @@ CArgumentParser::~CArgumentParser()
 
 void CArgumentParser::SetArgumentList(TCHAR *pchArguments)
 {
-       TCHAR *pch = m_pchArgumentList = pchArguments;
-       m_pchArgumentListEnd = pchArguments + _tcslen(pchArguments);
-
      BOOL blnLongArg = FALSE;
      while (*pch)
      {
-               switch(*pch)
-               {
-               case L'\"':
-                       if (blnLongArg) blnLongArg = FALSE;
-                       else blnLongArg = TRUE;
-                       break;
-               case L' ':
-               case L'\t':
-               case L'\r':
-               case L'\n':
-                       if (!blnLongArg) *pch = 0;
-                       break;
-               }
-               pch++;
      }
-
      ResetArgumentIteration();
+TCHAR *pch = m_pchArgumentList = pchArguments;
+m_pchArgumentListEnd = pchArguments + _tcslen(pchArguments);
+ BOOL blnLongArg = FALSE;
+ while (*pch)
+ {
+   switch(*pch)
+   {
+   case _T('\"'):
+    blnLongArg = !blnLongArg;
+               break;
+   case _T(' '):
+   case _T('\t'):
+   case _T('\r'):
+   case _T('\n'):
+     if (!blnLongArg)
+       *pch = 0;
+     break;
+   }
+   pch++;
+ }
+ ResetArgumentIteration();
 }
 
 TCHAR * CArgumentParser::GetNextArgument()
@@ -76,7 +76,8 @@ TCHAR * CArgumentParser::GetNextArgument()
        ASSERT(m_pchArgumentListEnd >= m_pchArgumentList);
 
        // if this is begin of iteration
-       if (!m_pchArgument) m_pchArgument = m_pchArgumentList;
+       if (!m_pchArgument)
+    m_pchArgument = m_pchArgumentList;
 
        while(m_pchArgument)
        {
diff --git a/rosapps/sysutils/regexpl/Completion.cpp b/rosapps/sysutils/regexpl/Completion.cpp
new file mode 100644 (file)
index 0000000..2d38961
--- /dev/null
@@ -0,0 +1,505 @@
+/* $Id: Completion.cpp,v 1.1 2001/01/10 01:25:29 narnaoud Exp $
+ *
+ * regexpl - Console Registry Explorer
+ *
+ * Copyright (C) 2000 Nedko Arnaoudov <nedkohome@atia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+// Completion.cpp : Defines the completion related functions.
+#include "ph.h"
+#include "RegistryKey.h"
+#include "RegistryTree.h"
+
+#define COMPLETION_BUFFER_SIZE 4096
+
+extern CRegistryTree Tree;
+
+BOOL g_blnCompletionCycle = TRUE;
+
+class CCompletionMatch
+{
+public:
+  CCompletionMatch()
+  {
+    m_pNext = m_pPrev = NULL;
+    m_pszText = NULL;
+  };
+
+  BOOL Init(const TCHAR *pszText)
+  {
+    // find the offset to "unique" part
+    const TCHAR *pszUnique = _tcsrchr(pszText,_T('\\'));
+    pszUnique = pszUnique?(pszUnique+1):pszText;
+    BOOL b = _tcschr(pszUnique,_T(' ')) != NULL; // has it spaces in it ???
+    size_t s = _tcslen(pszText);
+    
+    if (m_pszText)
+      delete m_pszText;
+    
+    m_pszText = new TCHAR [s+(b?3:1)]; // if we have spaces in unique part, we need 2 addtional chars for "
+    
+    if (!m_pszText)
+      return FALSE;
+
+    ASSERT(pszText <= pszUnique);
+    s = pszUnique - pszText; // calculate offset of the unique part
+    if (s)
+      _tcsncpy(m_pszText,pszText,s);
+
+    if (b)
+      m_pszText[s++] = _T('\"');
+    
+    _tcscpy(m_pszText+s,pszUnique);
+
+    if (b)
+      _tcscat(m_pszText,_T("\""));
+    
+    return TRUE;
+  }
+  
+  ~CCompletionMatch()
+  {
+    if (m_pszText)
+      delete m_pszText;
+  }
+  
+private:
+  TCHAR *m_pszText;
+  BOOL m_blnIsKey;
+  CCompletionMatch *m_pNext;
+  CCompletionMatch *m_pPrev;
+  friend class CCompletionList;
+};
+
+class CCompletionList
+{
+public:
+  CCompletionList();
+  ~CCompletionList();
+
+  BOOL IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL& rblnNew);
+  BOOL Add(const TCHAR *pszText, BOOL blnIsKey);
+  const TCHAR *Get(unsigned __int64 nIndex, BOOL& rblnIsKey);
+  unsigned __int64 GetCount();
+  const TCHAR * GetContext();
+  const TCHAR * GetBegin();
+  void DeleteList();
+  void Invalidate();
+    
+private:
+  CCompletionMatch *m_pHead; // head of completions linked list
+  CCompletionMatch *m_pTail; // tail of completions linked list
+  CCompletionMatch *m_pLastSearched;
+  unsigned int m_nLastSearched;
+  TCHAR *m_pszContext;
+  TCHAR *m_pszBegin;
+  TCHAR *m_pszCurrentKey;
+  unsigned __int64 m_nCount;
+} g_Completion;
+
+// --- begin of CCompletionList implementation ---
+CCompletionList::CCompletionList()
+{
+  m_pHead = NULL;
+  m_pTail = NULL;
+  m_nCount = 0;
+  m_pLastSearched = NULL;
+  m_pszContext = NULL;
+  m_pszBegin = NULL;
+  m_pszCurrentKey = NULL;
+}
+
+CCompletionList::~CCompletionList()
+{
+  DeleteList();
+    
+  if (m_pszContext)
+    delete m_pszContext;
+    
+  if (m_pszBegin)
+    delete m_pszBegin;
+
+  if (m_pszCurrentKey)
+    delete m_pszCurrentKey;
+}
+
+void CCompletionList::Invalidate()
+{
+  if (m_pszCurrentKey)
+  {
+    delete m_pszCurrentKey;
+    m_pszCurrentKey = NULL;
+  }
+}
+
+BOOL CCompletionList::IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL& rblnNew)
+{
+  const TCHAR *pszCurrentKey = Tree.GetCurrentPath();
+  if (!m_pszContext ||
+      !m_pszBegin ||
+      !m_pszCurrentKey ||
+      (_tcscmp(m_pszContext,pszContext) != 0) ||
+      (_tcscmp(m_pszBegin,pszBegin) != 0) ||
+      (_tcscmp(m_pszCurrentKey,pszCurrentKey)))
+  { // new completion
+    DeleteList();
+    rblnNew = TRUE;
+    if (m_pszContext)
+    {
+      delete m_pszContext;
+      m_pszContext = NULL;
+    }
+
+    if (m_pszBegin)
+    {
+      delete m_pszBegin;
+      m_pszBegin = NULL;
+    }
+
+    if (m_pszCurrentKey)
+    {
+      delete m_pszCurrentKey;
+      m_pszCurrentKey = NULL;
+    }
+      
+    size_t s = _tcslen(pszContext);
+    m_pszContext = new TCHAR[s+1];
+    if (!m_pszContext)
+      return FALSE;
+    _tcscpy(m_pszContext,pszContext);
+
+    s = _tcslen(pszBegin);
+    m_pszBegin = new TCHAR[s+1];
+    if (!m_pszBegin)
+      return FALSE;
+    _tcscpy(m_pszBegin,pszBegin);
+      
+    s = _tcslen(pszCurrentKey);
+    m_pszCurrentKey = new TCHAR[s+1];
+    if (!m_pszCurrentKey)
+      return FALSE;
+    _tcscpy(m_pszCurrentKey,pszCurrentKey);
+      
+    return TRUE;
+  }
+
+  rblnNew = FALSE;
+  return TRUE;
+}
+  
+BOOL CCompletionList::Add(const TCHAR *pszText, BOOL blnIsKey)
+{
+  if (_tcsnicmp(pszText,m_pszBegin,_tcslen(m_pszBegin)) != 0)
+    return TRUE;
+  CCompletionMatch *pNode = new CCompletionMatch;
+  if (!pNode)
+    return FALSE;
+  if (!pNode->Init(pszText))
+    return FALSE;
+
+  ASSERT(pNode->m_pszText);
+  ASSERT(pNode->m_pNext == NULL);
+
+  // add new node to tail
+  pNode->m_blnIsKey = blnIsKey;
+  if (m_pTail)
+  {
+    pNode->m_pPrev = m_pTail;
+    ASSERT(m_pTail->m_pNext == NULL);
+    m_pTail->m_pNext = pNode;
+    m_pTail = pNode;
+  }
+  else
+  {
+    ASSERT(m_pHead == NULL);
+    m_pHead = m_pTail = pNode;
+  }
+
+  m_nCount++;
+
+  m_pLastSearched = NULL;
+    
+  return TRUE;
+}
+  
+const TCHAR * CCompletionList::Get(unsigned __int64 nIndex, BOOL& rblnIsKey)
+{
+  ASSERT(nIndex < m_nCount);
+  BOOL blnForward;
+  CCompletionMatch *pNode = NULL;
+
+  unsigned __int64 nRelativeIndex;
+
+  if (m_pLastSearched)
+  {
+    pNode = m_pLastSearched;
+    blnForward = nIndex > m_nLastSearched;
+    nRelativeIndex = blnForward?(nIndex-m_nLastSearched):(m_nLastSearched-nIndex);
+    if ((nRelativeIndex > nIndex)||(nRelativeIndex > m_nCount-nIndex-1))
+      pNode = NULL; // seraching from tail or from head is more effective
+  }
+    
+  if (!pNode && (nIndex <= m_nCount/2))
+  { // search from head
+    pNode = m_pHead;
+    blnForward = TRUE;
+    nRelativeIndex = nIndex;
+  }
+    
+  if (!pNode)
+  { // search from tail
+    pNode = m_pTail;
+    blnForward = FALSE;
+    nRelativeIndex = m_nCount-nIndex-1;
+  }
+
+  while(pNode)
+  {
+    if (nRelativeIndex == 0)
+    {
+      m_nLastSearched = nIndex;
+      m_pLastSearched = pNode;
+      rblnIsKey = pNode->m_blnIsKey;
+      if (!pNode->m_pszText)
+        ASSERT(FALSE);
+      return pNode->m_pszText;
+    }
+      
+    nRelativeIndex--;
+      
+    pNode = blnForward?(pNode->m_pNext):(pNode->m_pPrev);
+  }
+
+  ASSERT(FALSE);
+  return NULL;
+}
+
+unsigned __int64 CCompletionList::GetCount()
+{
+  return m_nCount;
+}
+
+const TCHAR * CCompletionList::GetContext()
+{
+  return m_pszContext;
+}
+
+const TCHAR * CCompletionList::GetBegin()
+{
+  return m_pszBegin;
+}
+  
+void CCompletionList::DeleteList()
+{
+  CCompletionMatch *pNode;
+  while(m_pHead)
+  {
+    pNode = m_pHead;
+    m_pHead = m_pHead->m_pNext;
+    delete pNode;
+  }
+  m_pTail = NULL;
+  ASSERT(m_pHead == NULL);
+  m_nCount = 0;
+}
+
+// --- end of CCompletionList implementation ---
+
+BOOL FillCompletion(const TCHAR *pszKey)
+{
+  g_Completion.DeleteList();
+  LONG nError;
+  CRegistryKey Key;
+  TCHAR *pszSubkeyName = NULL;
+  DWORD dwMaxSubkeyNameLength;
+  TCHAR *pszValueName = NULL;
+  DWORD dwMaxValueNameSize;
+
+  if (!Tree.GetKey(pszKey?pszKey:_T("."),KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,Key))
+    return FALSE;
+  
+  BOOL blnCompletionOnKeys = TRUE;
+  BOOL blnCompletionOnValues = TRUE;
+
+/*     if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
+               (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
+               (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
+               (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
+               (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
+       {
+               blnCompletionOnValues = FALSE;
+       }*/
+//     else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
+//     {
+//             blnCompletionOnKeys = FALSE;
+//     }
+
+  size_t nKeyNameSize = 0;
+  if (pszKey)
+  {
+    nKeyNameSize = _tcslen(pszKey);
+    if (_tcscmp(pszKey,_T("\\")))
+      nKeyNameSize++;
+  } 
+  
+  if (blnCompletionOnKeys)
+  {
+    nError = Key.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
+    if (nError != ERROR_SUCCESS)
+      return FALSE;
+
+    pszSubkeyName = new TCHAR[nKeyNameSize+dwMaxSubkeyNameLength+1];
+    if (!pszSubkeyName)
+      goto Abort;
+
+    if (pszKey)
+      _stprintf(pszSubkeyName,_tcscmp(pszKey,_T("\\"))?_T("%s\\"):_T("%s"),pszKey);
+      
+    Key.InitSubkeyEnumeration(pszSubkeyName+nKeyNameSize,dwMaxSubkeyNameLength);
+    while ((nError = Key.GetNextSubkeyName()) == ERROR_SUCCESS)
+      if (!g_Completion.Add(pszSubkeyName,TRUE))
+      {
+        ASSERT(FALSE);
+        goto Abort;
+      }
+    if ((nError != ERROR_SUCCESS)&&(nError != ERROR_NO_MORE_ITEMS))
+    {
+      ASSERT(FALSE);
+      goto Abort;
+    }
+  }
+
+  if (blnCompletionOnValues)
+  {
+    nError = Key.GetMaxValueNameLength(dwMaxValueNameSize);
+    if (nError != ERROR_SUCCESS)
+    {
+      ASSERT(FALSE);
+      goto Abort;
+    }
+
+    pszValueName = new TCHAR[nKeyNameSize+dwMaxValueNameSize+1];
+    if (!pszValueName)
+      goto Abort;
+      
+    if (pszKey)
+      _stprintf(pszValueName,_tcscmp(pszKey,_T("\\"))?_T("%s\\"):_T("%s"),pszKey);
+      
+    Key.InitValueEnumeration(pszValueName+nKeyNameSize,dwMaxValueNameSize,NULL,0,NULL);
+    while((nError = Key.GetNextValue()) == ERROR_SUCCESS)
+      if (!g_Completion.Add(pszValueName,FALSE))
+      {
+        ASSERT(FALSE);
+        goto Abort;
+      }
+    if ((nError != ERROR_SUCCESS)&&(nError != ERROR_NO_MORE_ITEMS))
+    {
+      ASSERT(FALSE);
+      goto Abort;
+    }
+  }
+
+  if (pszValueName)
+    delete pszValueName;
+  if (pszSubkeyName)
+    delete pszSubkeyName;
+  return TRUE;
+Abort:
+  if (pszValueName)
+    delete pszValueName;
+  if (pszSubkeyName)
+    delete pszSubkeyName;
+  return FALSE;
+}
+
+const TCHAR * CompletionCallback(unsigned __int64 & rnIndex,
+                                 const BOOL *pblnForward,
+                                 const TCHAR *pszContext,
+                                 const TCHAR *pszBegin)
+{
+  static TCHAR pszBuffer[COMPLETION_BUFFER_SIZE];
+  
+  // Find first non-white space in context
+  while(*pszContext && _istspace(*pszContext))
+    pszContext++;
+
+  BOOL blnNewCompletion = TRUE;
+  if (!g_Completion.IsNewCompletion(pszContext,pszBegin,blnNewCompletion))
+  {
+    ASSERT(FALSE);
+    return NULL;
+  }
+
+  if (blnNewCompletion)
+  {
+    _tcsncpy(pszBuffer,pszBegin,COMPLETION_BUFFER_SIZE-1);
+    pszBuffer[COMPLETION_BUFFER_SIZE-1] = 0;
+    TCHAR *pszSeparator = pszBuffer; // set it to aby non null value
+    if (_tcscmp(pszBuffer,_T("\\")))
+    {
+      pszSeparator = _tcsrchr(pszBuffer,_T('\\'));
+      if (pszSeparator)
+        *pszSeparator = 0;
+    }
+    
+    if (!FillCompletion(pszSeparator?pszBuffer:NULL))
+      return NULL;
+  }
+  
+  unsigned __int64 nTotalItems = g_Completion.GetCount();
+  if (nTotalItems == 0)
+    return NULL;
+
+  if (rnIndex >= nTotalItems)
+    rnIndex = nTotalItems-1;
+  
+  if (pblnForward)
+  {
+    if (*pblnForward)
+    {
+      rnIndex++;
+      if (rnIndex >= nTotalItems)
+      {
+        if (g_blnCompletionCycle)
+          rnIndex = 0;
+        else
+          rnIndex--;
+      }
+    }
+    else
+    {
+      if (rnIndex)
+        rnIndex--;
+      else if (g_blnCompletionCycle)
+        rnIndex = nTotalItems-1;
+    }
+  }
+  BOOL blnIsKey = FALSE;
+  const TCHAR *pszName = g_Completion.Get(rnIndex,blnIsKey);
+
+  ASSERT(pszName);
+
+  _sntprintf(pszBuffer,COMPLETION_BUFFER_SIZE-1,_T("%s%s"),pszName,(blnIsKey?_T("\\"):_T("")));
+  pszBuffer[COMPLETION_BUFFER_SIZE-1] = 0;
+  return pszBuffer;
+}
+
+void InvalidateCompletion()
+{
+  g_Completion.Invalidate();
+}
diff --git a/rosapps/sysutils/regexpl/Completion.h b/rosapps/sysutils/regexpl/Completion.h
new file mode 100644 (file)
index 0000000..b5a08ba
--- /dev/null
@@ -0,0 +1,17 @@
+/* $Id: Completion.h,v 1.1 2001/01/10 01:25:29 narnaoud Exp $ */
+
+// Completion.h - declaration for completion related functions
+
+#if !defined(PATTERN_H__INCLUDED_)
+#define PATTERN_H__INCLUDED_
+
+typedef const TCHAR * (*ReplaceCompletionCallback)(unsigned __int64& rnIndex, const BOOL *pblnForward,
+                                                                                                  const TCHAR *pchContext, const TCHAR *pchBegin);
+
+extern const TCHAR * CompletionCallback(unsigned __int64 & rnIndex,
+                                        const BOOL *pblnForward,
+                                        const TCHAR *pchContext,
+                                        const TCHAR *pchBegin);
+
+extern void InvalidateCompletion();
+#endif
index 73758bc..5724ad2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: Console.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: Console.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -27,6 +27,7 @@
 #include "ph.h"
 #include "Console.h"
 
+#define TAB_WIDTH         8
 #define MORE_STRING                    _T("-- Press space to view more. Press q or Ctrl+break to cancel.--")
 #define MORE_EMPTY_STRING      _T("                                                               ")
 
@@ -118,7 +119,7 @@ BOOL CConsole::Write(const TCHAR *p, DWORD dwChars)
                        {
                                if (!Write(_T(" "))) return FALSE;
                        }
-                       while ((m_CursorPosition.X % 8) && (!m_blnDisableWrite));
+                       while ((m_CursorPosition.X % TAB_WIDTH) && (!m_blnDisableWrite));
                        dwCharsWrittenAdd++;
                        dwCharsToWrite--;
                        continue;
@@ -214,6 +215,11 @@ BOOL CConsole::Write(const TCHAR *p, DWORD dwChars)
        return ret;
 }
 
+unsigned int CConsole::GetTabWidth()
+{
+  return TAB_WIDTH;
+}
+
 BOOL CConsole::SetTitle(TCHAR *p)
 {
        return SetConsoleTitle(p);
@@ -674,85 +680,99 @@ Paste:
                        }
                }
                else if (ch == _T('\t'))
-               {
-                       if (!blnCompletionMode)
+               { // Tab
+      
+                       if (!blnCompletionMode) // If tab was pressed after non-tab. We enter in completion mode.
                        {
-                               if (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
-//                                     nCompletionIndex = 0xFFFFFFFFFFFFFFFF;
-                                       nCompletionIndex = (unsigned long long) -1;
+        // Initialize completion index
+                               if (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)  // If shift was pressed
+                                       nCompletionIndex = (unsigned long long) -1; // Last completion
                                else
-                                       nCompletionIndex = 0;
+                                       nCompletionIndex = 0; // First completion
+
+        // Find completion offset. It points at char after first non-quoted whitespace.
                                dwCompletionOffset = dwCurrentCharOffset;
-                               BOOL b = FALSE;
+                               BOOL blnQuotedParameter = FALSE;
                                while(dwCompletionOffset)
                                {
                                        dwCompletionOffset--;
                                        if (m_pchBuffer[dwCompletionOffset] == _T('\"'))
                                        {
-                                               b = !b;
+                                               blnQuotedParameter = !blnQuotedParameter; 
                                        }
-                                       else if (!b && _istspace(m_pchBuffer[dwCompletionOffset]))
-                                       {
-                                               dwCompletionOffset++;
+                                       else if (!blnQuotedParameter && _istspace(m_pchBuffer[dwCompletionOffset]))
+                                       { // Found ! We are not inside quored parameter and we are on whitespace.
+                                               dwCompletionOffset++; // dwCompletionOffset must point at char AFTER first non-quoted whitespace.
                                                break;
                                        }
                                }
+        
                                ASSERT(dwCompletionOffset <= dwCurrentCharOffset);
+
+        // Save not changing part (context) of completion in m_pchBuffer1
                                _tcsncpy(m_pchBuffer1,m_pchBuffer,dwCompletionOffset);
                                m_pchBuffer1[dwCompletionOffset] = 0;
+
+        // Size of changing part
                                dwCompletionStringSize = dwCurrentCharOffset-dwCompletionOffset;
+
+        // Save intial changing part of completion in m_pchBuffer2
                                if (dwCompletionStringSize)
                                        _tcsncpy(m_pchBuffer2,m_pchBuffer+dwCompletionOffset,dwCompletionStringSize);
                                m_pchBuffer2[dwCompletionStringSize] = 0;
+
+        // Calculate cursor position of point between changing and not changing ports
                                CompletionPosition.X = X_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
                                CompletionPosition.Y = Y_CURSOR_POSITION_FROM_OFFSET(dwCompletionOffset);
-//                             Beep(1000,500);
-                       }
-                       else
-                       {
-//                             Beep(1000,50);
-//                             Beep(2000,50);
-//                             Beep(3000,50);
-//                             Beep(4000,50);
-//                             Beep(3000,50);
-//                             Beep(2000,50);
-//                             Beep(1000,50);
-                       }
+                       } // if first time tab
+
                        const TCHAR *pchCompletion = NULL;
+
+      // Direction
                        BOOL blnForward = !(InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED);
-                       if (m_pfReplaceCompletionCallback)
+
+                       if (m_pfReplaceCompletionCallback)  // If we are using replace completion callback
                                pchCompletion = m_pfReplaceCompletionCallback(nCompletionIndex,
-                               blnCompletionMode?&blnForward:NULL,
-                               m_pchBuffer1,m_pchBuffer2);
-                       if (pchCompletion)
+                                                      blnCompletionMode?&blnForward:NULL, // If this is first time we call the completion callback, do not change completion index
+                                                      m_pchBuffer1,m_pchBuffer2);
+      
+                       if (pchCompletion) // If completion found
                        {
-                               // Set cursor position
+                               // Set cursor position to compeltion position
                                m_CursorPosition = CompletionPosition;
-                               if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition)) return FALSE;
+                               if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition))
+          return FALSE;
 
                                // Calculate buffer free space
                                ASSERT(m_dwBufferSize > dwCompletionOffset);
                                DWORD dwFree = m_dwBufferSize - dwCompletionOffset - 1;
 
+        // Save old completion string size
                                DWORD dwOldCompletionStringSize = dwCompletionStringSize;
 
                                // Write completion string to buffer
                                dwCompletionStringSize = _tcslen(pchCompletion);
 
+        // If there is not enough space in buffer, so we truncate the completion
                                if (dwCompletionStringSize > dwFree)
                                        dwCompletionStringSize = dwFree;
+
                                if (dwCompletionStringSize)
                                {
+          // Copy competion into main buffer
                                        _tcsncpy(m_pchBuffer+dwCompletionOffset,pchCompletion,dwCompletionStringSize);
-//                                     m_pchBuffer[dwCompletionOffset+dwCompletionStringSize] = 0;
                                        
                                        // Write completion string to console
-                                       if (!Write(m_pchBuffer+dwCompletionOffset,dwCompletionStringSize)) return FALSE;
+                                       if (!Write(m_pchBuffer+dwCompletionOffset,dwCompletionStringSize))
+            return FALSE;
+
+          // Set new offsets
                                        dwCurrentCharOffset = dwLastCharOffset = dwCompletionOffset + dwCompletionStringSize;
+          
                                        ASSERT(dwLastCharOffset < m_dwBufferSize);
                                }
 
-                               // Erase rest from previous completion string
+                               // Erase rest from previous completion string, if the new completion is shorter than old
                                if (dwOldCompletionStringSize > dwCompletionStringSize)
                                {
                                        _tcsnset(m_pchBuffer+dwCompletionOffset+dwCompletionStringSize,_T(' '),
@@ -767,22 +787,12 @@ Paste:
 
                                        // Set cursor position
                                        m_CursorPosition = pos;
-                                       if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition)) return FALSE;
+                                       if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition))
+            return FALSE;
                                }
+                       } // If completion found
 
-                       }
-                       else
-                       {
-/*                             if (InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED)
-                               {
-                                        nCompletionIndex++;
-                               }
-                               else
-                               {
-                                       if (nCompletionIndex)
-                                               nCompletionIndex--;
-                               }*/
-                       }
+      // Ok, we are in completion mode
                        blnCompletionMode = TRUE;
                }
                else if (_istprint(ch))
@@ -854,14 +864,19 @@ TCHAR * CConsole::Init(DWORD dwBufferSize, DWORD dwMaxHistoryLines)
        if (m_hStdIn != INVALID_HANDLE_VALUE) VERIFY(CloseHandle(m_hStdIn));
        if (m_hStdOut != INVALID_HANDLE_VALUE) VERIFY(CloseHandle(m_hStdOut));
 
-       m_hStdIn = GetStdHandle(STD_INPUT_HANDLE);
-       if (m_hStdIn == INVALID_HANDLE_VALUE) goto Abort;
+  m_hStdIn = CreateFile("CONIN$",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+  //m_hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+       if (m_hStdIn == INVALID_HANDLE_VALUE)
+    goto Abort;
 
-       m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
-       if (m_hStdOut == INVALID_HANDLE_VALUE) goto Abort;
+  m_hStdOut = CreateFile("CONOUT$",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
+       //m_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+       if (m_hStdOut == INVALID_HANDLE_VALUE)
+    goto Abort;
 
        CONSOLE_SCREEN_BUFFER_INFO info;
-       if (!GetConsoleScreenBufferInfo(m_hStdOut,&info)) goto Abort;
+       if (!GetConsoleScreenBufferInfo(m_hStdOut,&info))
+    goto Abort;
        m_wAttributes = info.wAttributes;
        
        if (!m_blnOldInputModeSaved)
index cd766d4..4157cd2 100644 (file)
@@ -6,9 +6,7 @@
 #define CONSOLE_H__FEF419EC_6EB6_11D3_907D_204C4F4F5020__INCLUDED_
 
 #include "TextHistory.h"
-
-typedef const TCHAR * (*ReplaceCompletionCallback)(unsigned __int64& rnIndex, const BOOL *pblnForward,
-                                                                                                  const TCHAR *pchContext, const TCHAR *pchBegin);
+#include "Completion.h"
 
 class CConsole  
 {
@@ -29,6 +27,7 @@ public:
        BOOL Write(const TCHAR *p, DWORD dwChars = 0);
        CConsole();
        virtual ~CConsole();
+  unsigned int GetTabWidth();
 private:
        HANDLE m_hStdOut;
        HANDLE m_hStdIn;
index ef0f980..7f726cf 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 2000/10/24 20:17:41 narnaoud Exp $
+# $Id: Makefile,v 1.4 2001/01/10 01:25:29 narnaoud Exp $
 #
 #  ReactOS makefile for RegExpl
 #
@@ -36,7 +36,6 @@ OBJECTS = \
        ShellCommandChangeKey.o         \
        ShellCommandConnect.o           \
        ShellCommandDACL.o              \
-       ShellCommandDOKA.o              \
        ShellCommandDeleteKey.o         \
        ShellCommandDeleteValue.o       \
        ShellCommandDir.o               \
@@ -51,6 +50,8 @@ OBJECTS = \
        ShellCommandsLinkedList.o       \
        CrtSupplement.c                 \
        TextHistory.o                   \
+       Completion.o                    \
+       Pattern.o                       \
        $(TARGET_NAME).coff
 
 CLEAN_FILES = \
diff --git a/rosapps/sysutils/regexpl/Pattern.cpp b/rosapps/sysutils/regexpl/Pattern.cpp
new file mode 100644 (file)
index 0000000..58e79d3
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id: Pattern.cpp,v 1.1 2001/01/10 01:25:29 narnaoud Exp $
+ *
+ * regexpl - Console Registry Explorer
+ *
+ * Copyright (C) 2000 Nedko Arnaoudov <nedkohome@atia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+// Pattern.cpp: implementation of pattern functions
+
+#include "ph.h"
+
+// based on wstrcmpjoki() by Jason Filby (jasonfilby@yahoo.com)
+// reactos kernel, services/fs/vfat/string.c
+BOOL PatternMatch(const TCHAR *pszPattern, const TCHAR *pszTry)
+{
+  while ((*pszPattern == _T('?'))||((_totlower(*pszTry)) == (_totlower(*pszPattern))))
+  {
+    if (((*pszTry) == 0) && ((*pszPattern) == 0))
+      return TRUE;
+    pszTry++;
+    pszPattern++;      
+  }
+   
+  if(*pszPattern == _T('*'))
+  {
+    pszPattern++;
+    while (*pszTry)
+    {
+      if (PatternMatch(pszPattern,pszTry))
+        return TRUE;
+      else
+        pszTry++;
+    }
+  }
+   
+  if (((*pszTry) == 0) && ((*pszPattern) == 0))
+    return TRUE;
+   
+  return FALSE;
+}
diff --git a/rosapps/sysutils/regexpl/Pattern.h b/rosapps/sysutils/regexpl/Pattern.h
new file mode 100644 (file)
index 0000000..2aaa0d1
--- /dev/null
@@ -0,0 +1,12 @@
+/* $Id: Pattern.h,v 1.1 2001/01/10 01:25:29 narnaoud Exp $ */
+
+// Pattern.h: decalration for pattern functions
+
+#if !defined(PATTERN_H__INCLUDED_)
+#define PATTERN_H__INCLUDED_
+
+#define PATTERN_MATCH_ALL  _T("*")
+
+BOOL PatternMatch(const TCHAR *pszPattern, const TCHAR *pszTry);
+
+#endif
index 4700bc2..c376592 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: RegistryExplorer.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: RegistryExplorer.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -40,7 +40,7 @@
 #include "ShellCommandOwner.h"
 #include "ShellCommandDACL.h"
 #include "ShellCommandSACL.h"
-#include "ShellCommandDOKA.h"
+//#include "ShellCommandDOKA.h"
 #include "ShellCommandConnect.h"
 #include "ShellCommandNewKey.h"
 #include "ShellCommandDeleteKey.h"
 
 TCHAR pchCurrentKey[PROMPT_BUFFER_SIZE];
 
-CRegistryTree Tree(PROMPT_BUFFER_SIZE+1);
+CRegistryTree Tree;
 CConsole Console;
 
-const TCHAR * ppchRootKeys[7] = 
-{
-       _T("HKEY_CLASSES_ROOT"),
-       _T("HKEY_CURRENT_USER"),
-       _T("HKEY_LOCAL_MACHINE"),
-       _T("HKEY_USERS"),
-       _T("HKEY_PERFORMANCE_DATA"),
-       _T("HKEY_CURRENT_CONFIG"),
-       _T("HKEY_DYN_DATA")             //win9x only?
-};
-
-BOOL g_blnCompletionCycle = TRUE;
-
-const TCHAR * CompletionCallback(unsigned __int64 & rnIndex, const BOOL *pblnForward, const TCHAR *pchContext, const TCHAR *pchBegin)
-{
-#define COMPLETION_BUFFER_SIZE 4096
-       static TCHAR pchBuffer[COMPLETION_BUFFER_SIZE];
-       CRegistryKey *pKey = NULL;
-       CRegistryTree *pTree = NULL;
-       unsigned __int64 nTotalKeys = 0;
-       unsigned __int64 nTotalValues = 0;
-       unsigned __int64 nTotalItems = 0;
-       class CompletionMatch
-       {
-       public:
-               CompletionMatch(const TCHAR *pchText, CompletionMatch **pNext)
-               {
-                       BOOL b = _tcschr(pchText,_T(' ')) != NULL;
-                       size_t s = _tcslen(pchText);
-                       m_pchText = new TCHAR [s+(b?3:1)];
-                       if (b)
-                       {
-                               m_pchText[0] = _T('\"');
-                               _tcscpy(m_pchText+1,pchText);
-                               m_pchText[s+1] = _T('\"');
-                               m_pchText[s+2] = 0;
-                       }
-                       else
-                       {
-                               _tcscpy(m_pchText,pchText);
-                       }
-                       if (m_pchText)
-                       {
-                               m_pNext = *pNext;
-                               *pNext = this;
-                       }
-               }
-               ~CompletionMatch()
-               {
-                       if (m_pchText)
-                               delete m_pchText;
-                       if (m_pNext)
-                               delete m_pNext;
-               }
-               const TCHAR *GetText(unsigned __int64 dwReverseIndex)
-               {
-                       if (dwReverseIndex)
-                       {
-                               if (m_pNext)
-                                       return m_pNext->GetText(dwReverseIndex-1);
-                               else
-                                       return NULL;
-                       }
-                       return m_pchText;
-               }
-       private:
-               TCHAR *m_pchText;
-               CompletionMatch *m_pNext;
-       };
-       CompletionMatch *pRootMatch = NULL;
-
-       BOOL blnCompletionOnKeys = TRUE;
-       BOOL blnCompletionOnValues = TRUE;
-
-       while(*pchContext && _istspace(*pchContext))
-       {
-               pchContext++;
-       }
-
-/*     if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
-               (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
-               (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
-               (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
-               (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
-       {
-               blnCompletionOnValues = FALSE;
-       }*/
-//     else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
-//     {
-//             blnCompletionOnKeys = FALSE;
-//     }
-
-       const TCHAR *pchKey = _tcsrchr(pchBegin,_T('\\'));
-       DWORD nBufferOffset = 0;
-       if (pchKey)
-       {
-               nBufferOffset = pchKey-pchBegin+1;
-               if (nBufferOffset >= COMPLETION_BUFFER_SIZE-1)
-               {
-                       if (pRootMatch) delete pRootMatch;
-                       if (pTree)
-                               delete pTree;
-                       return _T("internal error");
-               }
-               _tcsncpy(pchBuffer,pchBegin,nBufferOffset);
-               pchBuffer[nBufferOffset] = 0;
-               pchBegin = pchKey+1;
-               pTree = new CRegistryTree(Tree);
-               if ((_tcscmp(pTree->GetCurrentPath(),Tree.GetCurrentPath()) != 0)||(!pTree->ChangeCurrentKey(pchBuffer)))
-               {
-                       if (pTree)
-                               delete pTree;
-                       return NULL;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = Tree.GetCurrentKey();
-       }
-
-       if (!pKey)
-       {
-               for(unsigned int i = 0 ; i < sizeof(ppchRootKeys)/sizeof(TCHAR *) ; i++)
-               {
-                       nTotalKeys++;
-                       nTotalItems++;
-                       CompletionMatch *p = new CompletionMatch(ppchRootKeys[i],&pRootMatch);
-                       if (!p || !p->GetText(0))
-                       {
-                               if (pRootMatch) delete pRootMatch;
-                               if (pTree)
-                                       delete pTree;
-                               return _T("Out of memory");
-                       }
-               }
-       }
-       else
-       {
-               CompletionMatch *p;
-               DWORD dwError;
-               if (blnCompletionOnKeys)
-               {
-/*                     if (_tcslen(pchBegin) == 0)
-                       {
-                               p = new CompletionMatch(_T(".."),&pRootMatch);
-                               if (!p || !p->GetText(0))
-                               {
-                                       if (pRootMatch) delete pRootMatch;
-                                       if (pTree)
-                                               delete pTree;
-                                       return _T("Out of memory");
-                               }
-                               nTotalKeys++;
-                               nTotalItems++;
-                       }
-*/                     
-                       pKey->InitSubKeyEnumeration();
-                       TCHAR *pchSubKeyName;
-                       while ((pchSubKeyName = pKey->GetSubKeyName(dwError)) != NULL)
-                       {
-                               if (_tcsnicmp(pchSubKeyName,pchBegin,_tcslen(pchBegin)) == 0)
-                               {
-                                       nTotalKeys++;
-                                       nTotalItems++;
-                                       p = new CompletionMatch(pchSubKeyName,&pRootMatch);
-                                       if (!p || !p->GetText(0))
-                                       {
-                                               if (pRootMatch) delete pRootMatch;
-                                               if (pTree)
-                                                       delete pTree;
-                                               return _T("Out of memory");
-                                       }
-                               }
-                       }
-                       if ((dwError != ERROR_SUCCESS)&&(dwError != ERROR_NO_MORE_ITEMS))
-                       {
-                               if (pRootMatch) delete pRootMatch;
-                               if (pTree)
-                                       delete pTree;
-                               return _T("error");
-                       }
-               }
-               
-               if (blnCompletionOnValues)
-               {
-                       pKey->InitValueEnumeration();
-                       TCHAR *pchValueName;
-                       DWORD dwValueNameLength, dwMaxValueNameLength;
-                       dwError = pKey->GetMaxValueNameLength(dwMaxValueNameLength);
-                       if (dwError != ERROR_SUCCESS)
-                       {
-                               if (pRootMatch) delete pRootMatch;
-                               if (pTree)
-                                       delete pTree;
-                               return _T("error");
-                       }
-                       
-                       dwMaxValueNameLength++;
-                       pchValueName = new TCHAR [dwMaxValueNameLength];
-                       if (!pchValueName)
-                       {
-                               if (pRootMatch) delete pRootMatch;
-                               if (pTree)
-                                       delete pTree;
-                               return _T("Out of memory");
-                       }
-                       for(;;)
-                       {
-                               dwValueNameLength = dwMaxValueNameLength;
-                               //dwValueSize = dwMaxValueSize;
-                               dwError = pKey->GetNextValue(pchValueName,dwValueNameLength,NULL,NULL,NULL);
-                               if (dwError == ERROR_NO_MORE_ITEMS) break;
-                               if (dwError != ERROR_SUCCESS)
-                               {
-                                       if (pRootMatch) delete pRootMatch;
-                                       if (pTree)
-                                               delete pTree;
-                                       return _T("error");
-                               }
-                               
-                               if (((dwValueNameLength == 0) && (_tcslen(pchBegin) == 0))||
-                                       (_tcsnicmp(pchValueName,pchBegin,_tcslen(pchBegin)) == 0))
-                               {
-                                       nTotalValues++;
-                                       nTotalItems++;
-                                       p = new CompletionMatch((dwValueNameLength == 0)?_T("(Default)"):pchValueName,&pRootMatch);
-                                       if (!p || !p->GetText(0))
-                                       {
-                                               if (pRootMatch) delete pRootMatch;
-                                               if (pTree)
-                                                       delete pTree;
-                                               return _T("Out of memory");
-                                       }
-                               }
-                       }       // for
-                       delete [] pchValueName;
-               }
-       }
-       if (rnIndex >= nTotalItems)
-               rnIndex = nTotalItems-1;
-       if (pblnForward)
-       {
-               if (*pblnForward)
-               {
-                       rnIndex++;
-                       if (rnIndex >= nTotalItems)
-                       {
-                               if (g_blnCompletionCycle)
-                                       rnIndex = 0;
-                               else
-                                       rnIndex--;
-                       }
-               }
-               else
-               {
-                       if (rnIndex)
-                               rnIndex--;
-                       else if (g_blnCompletionCycle)
-                               rnIndex = nTotalItems-1;
-               }
-       }
-       
-       const TCHAR *pchName;
-       if (nTotalItems == 0)
-       {
-               if (pRootMatch)
-                       delete pRootMatch;
-               if (pTree)
-                       delete pTree;
-               return NULL;
-       }
-       ASSERT(rnIndex < nTotalItems);
-       pchName = pRootMatch->GetText(nTotalItems-rnIndex-1);
-       if (pchName == NULL)
-       {
-               if (pRootMatch)
-                       delete pRootMatch;
-               if (pTree)
-                       delete pTree;
-               return _T("internal error");
-       }
-       DWORD dwBufferFull = _tcslen(pchName);
-       if (dwBufferFull >= COMPLETION_BUFFER_SIZE-nBufferOffset)
-       {
-               dwBufferFull = COMPLETION_BUFFER_SIZE-1-nBufferOffset;
-       }
-       _tcsncpy(pchBuffer+nBufferOffset,pchName,dwBufferFull);
-       if ((dwBufferFull < COMPLETION_BUFFER_SIZE-1)&&(rnIndex < nTotalKeys))
-               pchBuffer[nBufferOffset+dwBufferFull++] = _T('\\');
-       pchBuffer[nBufferOffset+dwBufferFull] = 0;
-       if (pTree)
-               delete pTree;
-       if (pRootMatch)
-               delete pRootMatch;
-       return pchBuffer;
-}
-
 BOOL blnCommandExecutionInProgress = FALSE;
 
 BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
@@ -413,8 +112,8 @@ int main ()
        CShellCommandSACL SACLCommand(Tree);
        CommandsList.AddCommand(&SACLCommand);
 
-       CShellCommandDOKA DOKACommand(Tree);
-       CommandsList.AddCommand(&DOKACommand);
+       //CShellCommandDOKA DOKACommand(Tree);
+       //CommandsList.AddCommand(&DOKACommand);
 
        CShellCommandConnect ConnectCommand(Tree);
        CommandsList.AddCommand(&ConnectCommand);
@@ -463,14 +162,15 @@ int main ()
        //(_L(__TIMESTAMP__))
        )) goto Abort;
 
-       Tree.SetDesiredOpenKeyAccess(KEY_READ);
+  //Tree.SetDesiredOpenKeyAccess(KEY_READ);
 
+  const TCHAR *pszCurrentPath;
 GetCommand:
        // prompt
        // TODO: make prompt user-customizable
        Console.EnableWrite();
-       _tcscpy(pchCurrentKey,Tree.GetCurrentPath());
-       Console.Write(pchCurrentKey);
+  pszCurrentPath = Tree.GetCurrentPath();
+       Console.Write(pszCurrentPath?pszCurrentPath:_T("NULL (Internal Error)"));
        Console.Write(_T("\n# "));
        Console.FlushInputBuffer();
 
@@ -478,7 +178,8 @@ GetCommand:
 
        // Set command line color
 //     Console.SetTextAttribute(/*FOREGROUND_BLUE|*/FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
-       if (!Console.ReadLine()) goto Abort;
+       if (!Console.ReadLine())
+    goto Abort;
 
        // Set normal color
 //     Console.SetTextAttribute(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY);
@@ -486,7 +187,6 @@ GetCommand:
        Console.BeginScrollingOperation();
        blnCommandExecutionInProgress = TRUE;
 
-
        // Parse command line (1st step - convert to multi sz)
        Parser.SetArgumentList(pchCommand);
 
index e733aaa..7d6a1a0 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _REGISTRY_EXPLORER_H__INCLUDED
 #define _REGISTRY_EXPLORER_H__INCLUDED
 
-#define CURRENT_VERSION                _T("0.10+")
+#define CURRENT_VERSION                _T("0.20")
 #define EMAIL                          _T("registryexplorer@yahoo.com")
 
 //#define __L(x)      L ## x
 
 #define GOODBYE_MSG                    _T("\nThank you for using Registry Explorer !!!\n")
 
-#define COMMAND_NA_ON_ROOT     _T(" command is not applicable to root key.\n")
-
 //#define COMMAND_LENGTH(cmd)  (sizeof(DIR_CMD)-sizeof(TCHAR))/sizeof(TCHAR)
 #define COMMAND_LENGTH(cmd)    _tcslen(cmd)
 
 #define PROMPT_BUFFER_SIZE     1024
 
+#define COMMAND_NA_ON_ROOT     _T(" is not applicable to root key.\n")
+
 #endif //#ifndef _REGISTRY_EXPLORER_H__INCLUDED
index 36579fe..5429022 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: RegistryKey.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: RegistryKey.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
 #include "ph.h"
 #include "RegistryKey.h"
 
+static TCHAR *g_ppszHiveNames[] =
+{
+  _T("HKEY_CLASSES_ROOT"),
+  _T("HKEY_CURRENT_USER"),
+  _T("HKEY_LOCAL_MACHINE"),
+  _T("HKEY_USERS"),
+  _T("HKEY_PERFORMANCE_DATA"),
+  _T("HKEY_CURRENT_CONFIG"),
+  _T("HKEY_DYN_DATA")
+};
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-CRegistryKey::CRegistryKey(const TCHAR *pchKeyName, class CRegistryKey *pParent)
-{
-//     RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-//             &m_dwValueNameBufferSize,&m_dwMaxValueSize,&m_dwSecurityDescriptorSize,&m_ftLastWriteTime);
-//     m_pchValueName = NULL;
-       ASSERT(pParent != NULL);
-       m_pParent = pParent;
-       m_pChild = NULL;
-       m_hKey = NULL;  // Open key with Open() member function
-       ASSERT(pchKeyName != NULL);
-       m_pchKeyName[MAX_PATH] = 0;
-       *m_pszMachineName = 0;
-       if (*pchKeyName == _T('\"'))
-       {
-               _tcsncpy(m_pchKeyName,pchKeyName+1,MAX_PATH);
-               TCHAR *pch = _tcschr(m_pchKeyName,_T('\"'));
-               if (pch)
-               {
-                       *pch = 0;
-               }
-               else
-               {
-                       ASSERT(FALSE);
-               }
-       }
-       else
-       {
-               _tcsncpy(m_pchKeyName,pchKeyName,MAX_PATH);
-       }
-}
-
-CRegistryKey::~CRegistryKey()
-{
-//     if (m_pchValueName) delete [] m_pchValueName;
-       if((m_hKey != HKEY_CLASSES_ROOT)&&(m_hKey != HKEY_CURRENT_USER)&&
-               (m_hKey != HKEY_LOCAL_MACHINE)&&(m_hKey != HKEY_USERS)
-               &&(m_hKey != HKEY_PERFORMANCE_DATA)&&(m_hKey != HKEY_CURRENT_CONFIG)
-               &&(m_hKey != HKEY_DYN_DATA)&&(m_hKey != NULL))
-       {
-               RegCloseKey(m_hKey);
-       }
-}
+CRegistryKey::CRegistryKey()
+{
+  m_pszKeyName = NULL;
+  m_pszMachineName = NULL;
+       m_CurrentAccess = 0;
+       m_hKey = NULL;
+}
+
+HRESULT CRegistryKey::InitRoot(const TCHAR *pszMachineName = NULL)
+{
+  if ((pszMachineName)&&
+      ((_tcslen(pszMachineName) < 3)||
+       (pszMachineName[0] != _T('\\'))||
+       (pszMachineName[1] != _T('\\'))
+      )
+    )
+  {
+    return E_INVALIDARG;
+  }
+    
+  HRESULT hr = Uninit();
+  if (FAILED(hr))
+    return hr;
+
+  if (pszMachineName)
+  { // copy machine name
+    size_t size = _tcslen(pszMachineName);
+
+    m_pszMachineName = new TCHAR [size+2];
+    if (!m_pszMachineName)
+      return E_OUTOFMEMORY;
+    _tcscpy(m_pszMachineName,pszMachineName);
+    m_pszMachineName[size] = _T('\\');
+    m_pszMachineName[size+1] = 0;
+  }
+  else
+  {
+    m_pszMachineName = NULL; // local registry
+  }
+  
+  ASSERT(m_pszKeyName == NULL);
+       m_CurrentAccess = 0;
+       ASSERT(m_hKey == NULL);
+
+  return S_OK;
+}
+
+HRESULT CRegistryKey::Init(HKEY hKey, const TCHAR *pszPath, const TCHAR *pszKeyName, REGSAM CurrentAccess)
+{
+  HRESULT hr = Uninit();
+  if (FAILED(hr))
+    return hr;
+
+  if (!pszKeyName || !hKey)
+    return E_INVALIDARG;
+  
+  // copy key name name
+  size_t size = _tcslen(pszKeyName);
+  if (pszPath)
+    size += _tcslen(pszPath);
+  
+  m_pszKeyName = new TCHAR [size+2];
+  if (!m_pszKeyName)
+    return E_OUTOFMEMORY;
+  _stprintf(m_pszKeyName,_T("%s%s\\"),pszPath?pszPath:_T(""),pszKeyName);
+
+       m_CurrentAccess = CurrentAccess;
+       m_hKey = hKey;
+  ASSERT(m_hKey);
 
-TCHAR * CRegistryKey::GetKeyName()
-{
-       return m_pchKeyName;
+  return S_OK;
 }
 
-class CRegistryKey * CRegistryKey::GetChild()
+HRESULT CRegistryKey::Uninit()
 {
-       return m_pChild;
-}
+       if (m_pszKeyName)
+  {
+    delete [] m_pszKeyName;
+    m_pszKeyName = NULL;
+  }
 
-CRegistryKey * CRegistryKey::GetParent()
-{
-       return m_pParent;
-}
+       if (m_pszMachineName)
+  {
+    delete [] m_pszMachineName;
+    m_pszMachineName = NULL;
+  }
 
-CRegistryKey * CRegistryKey::UpOneLevel()
-{
-       CRegistryKey *pParent = m_pParent;
-       ASSERT(m_pChild == NULL);
-       if (pParent)
-       {
-               ASSERT(pParent->m_pChild == this);
-               pParent->m_pChild = NULL;
-       }
-       delete this;
-       return pParent;
+  LONG nError = ERROR_SUCCESS;
+       if((m_hKey != NULL)&&(!IsHive(m_hKey)))
+               nError = RegCloseKey(m_hKey);
+     
+  m_hKey = NULL;
+  
+  return (nError == ERROR_SUCCESS)?S_OK:E_FAIL;
 }
 
-void CRegistryKey::InitSubKeyEnumeration()
+BOOL CRegistryKey::IsHive(HKEY hKey)
 {
-       m_dwCurrentSubKeyIndex = 0;
+       return ((hKey == HKEY_CLASSES_ROOT)||
+          (hKey == HKEY_CURRENT_USER)||
+          (hKey == HKEY_LOCAL_MACHINE)||
+          (hKey == HKEY_USERS)||
+          (hKey == HKEY_PERFORMANCE_DATA)||
+          (hKey == HKEY_CURRENT_CONFIG)||
+          (hKey == HKEY_DYN_DATA));
 }
 
-TCHAR * CRegistryKey::GetSubKeyName(DWORD& dwError)
+CRegistryKey::~CRegistryKey()
 {
-       static TCHAR m_pchSubName[MAX_PATH+1];
-       dwError = RegEnumKey(m_hKey,m_dwCurrentSubKeyIndex,m_pchSubName,MAX_PATH + 1);
+  Uninit();
+}
+
+const TCHAR * CRegistryKey::GetKeyName()
+{
+       return m_pszKeyName?m_pszKeyName:(m_pszMachineName?m_pszMachineName:_T("\\"));
+}
+
+BOOL CRegistryKey::IsRoot()
+{
+  return m_hKey == NULL;
+}
+
+LONG CRegistryKey::OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, HKEY &rhKey)
+{
+       if (m_hKey == NULL)
+  { // subkey of root key is hive root key.
+    if ((_tcsicmp(pszSubkeyName,_T("HKCR")) == 0)||
+                               (_tcsicmp(pszSubkeyName,_T("HKEY_CLASSES_ROOT")) == 0))
+    {
+      rhKey = HKEY_CLASSES_ROOT;
+      
+      if (m_pszMachineName)
+        return ERROR_FILE_NOT_FOUND;
+            
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKCU")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_CURRENT_USER")) == 0))
+    {
+      rhKey = HKEY_CURRENT_USER;
+      
+      if (m_pszMachineName)
+        return ERROR_FILE_NOT_FOUND;
+            
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKLM")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_LOCAL_MACHINE")) == 0))
+    {
+      rhKey = HKEY_LOCAL_MACHINE;
+      
+      if (m_pszMachineName)
+        return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
+      
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKU")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_USERS")) == 0))
+    {
+      rhKey = HKEY_USERS;
+      
+      if (m_pszMachineName)
+        return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
+      
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKPD")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_PERFORMANCE_DATA")) == 0))
+    {
+      rhKey = HKEY_PERFORMANCE_DATA;
+      
+      if (m_pszMachineName)
+        return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
+      
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKDD")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_DYN_DATA")) == 0))
+    {
+      rhKey = HKEY_DYN_DATA;
+      
+      if (m_pszMachineName)
+        return RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
+      
+      return ERROR_SUCCESS;
+    }
+    else if ((_tcsicmp(pszSubkeyName,_T("HKCC")) == 0)||
+             (_tcsicmp(pszSubkeyName,_T("HKEY_CURRENT_CONFIG")) == 0))
+    {
+      rhKey = HKEY_CURRENT_CONFIG;
+      
+      if (m_pszMachineName)
+      {
+        TCHAR *pch = m_pszMachineName;
+        while (*pch)
+          pch++;
+        pch--;
+        
+        ASSERT(*pch == _T('\\'));
+        if (*pch != _T('\\'))
+          return ERROR_INTERNAL_ERROR;
+
+        *pch = 0;
+        
+        LONG nError = RegConnectRegistry(m_pszMachineName,rhKey,&rhKey);
+
+        *pch = _T('\\');
+        
+        return nError;
+      }
+      
+      return ERROR_SUCCESS;
+    }
+    else
+    {
+      return ERROR_FILE_NOT_FOUND;
+    }
+  }
+  
+       return RegOpenKeyEx(m_hKey,pszSubkeyName,0,samDesired,&rhKey);
+}
+
+LONG CRegistryKey::OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, CRegistryKey &rKey)
+{
+  HKEY hKey;
+  LONG nError = OpenSubkey(samDesired, pszSubkeyName, hKey);
+  
+  if (nError == ERROR_SUCCESS)
+  {
+    const TCHAR *pszKeyName = GetKeyName();
+    size_t size = _tcslen(pszKeyName) + _tcslen(pszSubkeyName) + 1;
+    TCHAR *pszSubkeyFullName = new TCHAR [size];
+    if (!pszSubkeyFullName)
+    {
+      nError = RegCloseKey(hKey);
+      ASSERT(nError == ERROR_SUCCESS);
+      return ERROR_OUTOFMEMORY;
+    }
+    _tcscpy(pszSubkeyFullName,pszKeyName);
+    _tcscat(pszSubkeyFullName,pszSubkeyName);
+    HRESULT hr = rKey.Init(hKey,GetKeyName(),pszSubkeyName,samDesired);
+    delete pszSubkeyName;
+    if (FAILED(hr))
+    {
+      nError = RegCloseKey(hKey);
+      ASSERT(nError == ERROR_SUCCESS);
+      if (hr == (HRESULT)E_OUTOFMEMORY)
+        return ERROR_OUTOFMEMORY;
+      else
+        return ERROR_INTERNAL_ERROR;
+    }
+  }
+
+  return nError;
+}
+
+LONG CRegistryKey::GetSubkeyNameMaxLength(DWORD &rdwMaxSubkeyNameLength)
+{
+  if (m_hKey == NULL)
+  { // root key
+    rdwMaxSubkeyNameLength = 0;
+    for(int i = 0; i < 7 ; i++)
+    {
+      size_t l = _tcslen(g_ppszHiveNames[i]);
+      if (rdwMaxSubkeyNameLength < l)
+        rdwMaxSubkeyNameLength = l;
+    }
+    
+    rdwMaxSubkeyNameLength++; // terminating null
+    
+    return ERROR_SUCCESS;
+  }
+  
+  LONG nRet;
+
+  nRet = RegQueryInfoKey(m_hKey,NULL,NULL,NULL,NULL,&rdwMaxSubkeyNameLength,NULL,NULL,NULL,NULL,NULL,NULL);
+
+  rdwMaxSubkeyNameLength = (nRet == ERROR_SUCCESS)?(rdwMaxSubkeyNameLength+1):0;
+  
+  return nRet;
+}
+
+void CRegistryKey::InitSubkeyEnumeration(TCHAR *pszSubkeyNameBuffer, DWORD dwBufferSize)
+{
+  m_pchSubkeyNameBuffer = pszSubkeyNameBuffer;
+  m_dwSubkeyNameBufferSize = dwBufferSize;
+  m_dwCurrentSubKeyIndex = 0;
+}
+
+LONG CRegistryKey::GetNextSubkeyName(DWORD *pdwActualSize)
+{
+  LONG nError;
+  
+  if (m_hKey == NULL)
+  {
+    if (m_dwCurrentSubKeyIndex < (DWORD)(m_pszMachineName?5:7))
+    {
+      DWORD dwIndex = m_pszMachineName?m_dwCurrentSubKeyIndex+2:m_dwCurrentSubKeyIndex;
+      _tcsncpy(m_pchSubkeyNameBuffer,g_ppszHiveNames[dwIndex],m_dwSubkeyNameBufferSize);
+      nError = ERROR_SUCCESS;
+      if (pdwActualSize)
+        *pdwActualSize = strlen(m_pchSubkeyNameBuffer);
+    }
+    else
+    {
+      nError = ERROR_NO_MORE_ITEMS;
+    }
+  }
+  else
+  {
+    DWORD dwActualSize = m_dwSubkeyNameBufferSize;
+    FILETIME ft;
+    nError = RegEnumKeyEx(m_hKey,
+                          m_dwCurrentSubKeyIndex,
+                          m_pchSubkeyNameBuffer,
+                          &dwActualSize,
+                          NULL,
+                          NULL,
+                          NULL,
+                          &ft);
+    if (pdwActualSize)
+      *pdwActualSize = dwActualSize;
+  }
+  
        m_dwCurrentSubKeyIndex++;
-       switch (dwError)
-       {
-       case ERROR_SUCCESS:
-               return m_pchSubName;
-       case ERROR_NO_MORE_ITEMS:
-               return NULL;
-       default:
-               return NULL;
-       }
-}
 
-void CRegistryKey::UpdateKeyNameCase()
-{
-       m_pParent->InitSubKeyEnumeration();
-       TCHAR *pchSubKeyName;
-       DWORD dwError;
-       while ((pchSubKeyName = m_pParent->GetSubKeyName(dwError)) != NULL)
-       {
-               if (dwError != ERROR_SUCCESS)
-               {
-                       return;
-               }
-               if (_tcsicmp(pchSubKeyName,m_pchKeyName) == 0)
-               {
-                       _tcscpy(m_pchKeyName,pchSubKeyName);
-                       return;
-               }
-       }
+  if (pdwActualSize)
+    *pdwActualSize = strlen(m_pchSubkeyNameBuffer);
+  return nError;
 }
 
-void CRegistryKey::InitValueEnumeration()
+LONG CRegistryKey::GetSubkeyCount(DWORD &rdwSubkeyCount)
 {
-       m_dwCurrentValueIndex = 0;
+       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,&rdwSubkeyCount,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 }
 
-
-// On input dwValueNameSize is size in characters of buffer pointed by pchValueNameBuffer
-// On output dwValueNameSize contains number of characters stored in buffer
-DWORD CRegistryKey::GetNextValue(TCHAR *pchValueNameBuffer,DWORD& dwValueNameSize, 
-                                                        DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize)
+LONG CRegistryKey::GetMaxValueDataSize(DWORD& rdwMaxValueDataBuferSize)
 {
-       DWORD dwRet = RegEnumValue(m_hKey,m_dwCurrentValueIndex,pchValueNameBuffer,&dwValueNameSize,NULL,
-               pdwType,lpValueDataBuffer,pdwValueDataSize);
-       m_dwCurrentValueIndex++;
-       return dwRet;
+       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&rdwMaxValueDataBuferSize,NULL,NULL);
 }
 
-void CRegistryKey::GetLastWriteTime(SYSTEMTIME &st)
+LONG CRegistryKey::GetMaxValueNameLength(DWORD& rdwMaxValueNameBuferSize)
 {
-       FILETIME ftLocal,ft;
-       RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-               &ft);
-       FileTimeToLocalFileTime(&ft,&ftLocal);
-       FileTimeToSystemTime(&ftLocal,&st);
-}
+  if (!m_hKey)
+    return 0; // the root key abstraction has only subkeys (hives)
+  
+       LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&rdwMaxValueNameBuferSize,NULL,NULL,NULL);
 
-TCHAR * CRegistryKey::GetLastWriteTime()
-{
-       SYSTEMTIME st;
-       GetLastWriteTime(st);
-       static TCHAR Buffer[256];
-       _stprintf(Buffer,_T("%d.%d.%d %02d:%02d:%02d"),st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond);
-       return Buffer;
+  rdwMaxValueNameBuferSize++;
+  return nError;
 }
 
-// Returns ErrorCode (ERROR_SUCCESS on success)
-// dwMaxValueDataBuferSize receives the length, in bytes, 
-// of the longest data component among the key's values.
-DWORD CRegistryKey::GetMaxValueDataSize(DWORD& dwMaxValueDataBuferSize)
+void CRegistryKey::InitValueEnumeration(TCHAR *pszValueNameBuffer,
+                                        DWORD dwValueNameBufferSize,
+                                        BYTE *pbValueDataBuffer,
+                                        DWORD dwValueDataBufferSize,
+                                        DWORD *pdwType)
 {
-       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-               NULL,&dwMaxValueDataBuferSize,NULL,NULL);
-}
-
-// Returns ErrorCode (ERROR_SUCCESS on success)
-// dwMaxValueNameBuferSize receives the length, in characters, 
-// of the key's longest value name.
-// The count returned does not include the terminating null character.
-DWORD CRegistryKey::GetMaxValueNameLength(DWORD& dwMaxValueNameBuferSize)
-{
-       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-               &dwMaxValueNameBuferSize,NULL,NULL,NULL);
+  m_pszValueNameBuffer = pszValueNameBuffer;
+  m_dwValueNameBufferSize = dwValueNameBufferSize;
+  m_pbValueDataBuffer = pbValueDataBuffer;
+  m_dwValueDataBufferSize = dwValueDataBufferSize;
+  m_pdwType = pdwType;
+  
+       m_dwCurrentValueIndex = 0;
 }
 
-DWORD CRegistryKey::Open(REGSAM samDesired)
-{
-       if (IsPredefined())
-               return ERROR_SUCCESS;
 
-       DWORD dwRet;
-       HKEY hKey = NULL;
-       if (*m_pszMachineName)
-       {
-               ASSERT(ERROR_SUCCESS == 0);
-               dwRet = RegConnectRegistry(m_pszMachineName,m_hKey,&m_hKey);
-       }
-       else
-       {
-               ASSERT((m_hKey != HKEY_CLASSES_ROOT)&&(m_hKey != HKEY_CURRENT_USER)&&
-                       (m_hKey != HKEY_LOCAL_MACHINE)&&(m_hKey != HKEY_USERS)
-                       &&(m_hKey != HKEY_PERFORMANCE_DATA)&&(m_hKey != HKEY_CURRENT_CONFIG)
-                       &&(m_hKey != HKEY_DYN_DATA));
-               if (m_hKey)
-               {
-                       RegCloseKey(m_hKey);
-               }
-               dwRet = RegOpenKeyEx(*m_pParent,m_pchKeyName,0,samDesired,&hKey);
-       }
-       if (dwRet == ERROR_SUCCESS)
-       {
-               m_hKey = hKey;
-               UpdateKeyNameCase();
-       }
-       return dwRet;
+// On input dwValueNameSize is size in characters of buffer pointed by pchValueNameBuffer
+// On output dwValueNameSize contains number of characters stored in buffer
+LONG CRegistryKey::GetNextValue(DWORD *pdwNameActualSize, DWORD *pdwDataActualSize)
+{
+  if (!m_hKey)
+    return ERROR_NO_MORE_ITEMS; // the root key abstraction has only subkeys (hives)
+  
+       DWORD dwValueNameBufferSize = m_dwValueNameBufferSize;
+       DWORD dwValueDataBufferSize = m_dwValueDataBufferSize;
+  LONG nError = RegEnumValue(m_hKey,
+                            m_dwCurrentValueIndex,
+                            m_pszValueNameBuffer,
+                            &dwValueNameBufferSize,
+                            NULL,
+                            m_pdwType,
+                            m_pbValueDataBuffer,
+                            &dwValueDataBufferSize);
+
+  if (pdwNameActualSize)
+    *pdwNameActualSize = dwValueNameBufferSize;
+  
+  if (pdwDataActualSize)
+    *pdwDataActualSize = dwValueDataBufferSize;
+  
+       m_dwCurrentValueIndex++;
+       return nError;
 }
 
-CRegistryKey::CRegistryKey(HKEY hKey, LPCTSTR pszMachineName)
+LONG CRegistryKey::GetValueCount(DWORD& rdwValueCount)
 {
-       TCHAR *pchKeyName = NULL;
-       ASSERT((hKey == HKEY_CLASSES_ROOT)||(hKey == HKEY_CURRENT_USER)||
-               (hKey == HKEY_LOCAL_MACHINE)||(hKey == HKEY_USERS)
-               ||(hKey == HKEY_PERFORMANCE_DATA)||(hKey == HKEY_CURRENT_CONFIG)
-               ||(hKey == HKEY_DYN_DATA));
-       if(hKey == HKEY_CLASSES_ROOT)
-       {
-               pchKeyName = _T("HKEY_CLASSES_ROOT");
-       }
-       else if(hKey == HKEY_CURRENT_USER)
-       {
-               pchKeyName = _T("HKEY_CURRENT_USER");
-       }
-       else if (hKey == HKEY_LOCAL_MACHINE)
-       {
-               pchKeyName = _T("HKEY_LOCAL_MACHINE");
-       }
-       else if (hKey == HKEY_USERS)
-       {
-               pchKeyName = _T("HKEY_USERS");
-       }
-       else if (hKey == HKEY_PERFORMANCE_DATA)
-       {
-               pchKeyName = _T("HKEY_PERFORMANCE_DATA");
-       }
-       else if (hKey == HKEY_CURRENT_CONFIG)
-       {
-               pchKeyName = _T("HKEY_CURRENT_CONFIG");
-       }
-       else if (hKey == HKEY_DYN_DATA)
-       {
-               pchKeyName = _T("HKEY_DYN_DATA");
-       }
-       else
-       {
-               ASSERT(FALSE);
-               return;
-       }
-
-       m_hKey = hKey;
-
-       m_pParent = NULL;
-       m_pChild = NULL;
-       ASSERT(pchKeyName != NULL);
-       m_pchKeyName[MAX_PATH] = 0;
-       _tcsncpy(m_pchKeyName,pchKeyName,MAX_PATH);
-       _tcsncpy(m_pszMachineName,pszMachineName?pszMachineName:_T(""),MAX_PATH);
+  if (!m_hKey)
+    return 0; // the root key abstraction has only subkeys (hives)
+  
+  return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,&rdwValueCount,NULL,NULL,NULL,NULL);
 }
 
-BOOL CRegistryKey::IsPredefined()
+LONG CRegistryKey::GetDefaultValue(DWORD *pdwType,
+                                   BYTE *pbValueDataBuffer,
+                                   DWORD dwValueDataBufferSize,
+                                   DWORD *pdwValueDataActualSize)
 {
-       return ((m_hKey == HKEY_CLASSES_ROOT)||(m_hKey == HKEY_CURRENT_USER)||
-               (m_hKey == HKEY_LOCAL_MACHINE)||(m_hKey == HKEY_USERS)
-               ||(m_hKey == HKEY_PERFORMANCE_DATA)||(m_hKey == HKEY_CURRENT_CONFIG)
-               ||(m_hKey == HKEY_DYN_DATA));
-}
+  DWORD dwBufferSize = dwValueDataBufferSize;
+  
+       LONG nError = RegQueryValueEx(m_hKey,NULL,NULL,pdwType,pbValueDataBuffer,&dwBufferSize);
 
-DWORD CRegistryKey::GetDefaultValue(DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize)
-{
-       return RegQueryValueEx(m_hKey,NULL,NULL,pdwType,lpValueDataBuffer,pdwValueDataSize);
-}
+  if (pdwValueDataActualSize && (nError == ERROR_SUCCESS))
+    *pdwValueDataActualSize = dwBufferSize;
 
-void CRegistryKey::LinkParent()
-{
-       m_pParent->m_pChild = this;     // self link
+  return nError;
 }
 
 const TCHAR * CRegistryKey::GetValueTypeName(DWORD dwType)
@@ -302,29 +466,29 @@ const TCHAR * CRegistryKey::GetValueTypeName(DWORD dwType)
        switch(dwType)
        {
        case REG_NONE:
-               return _T("REG_NONE\t\t");
+               return _T("REG_NONE");
        case REG_SZ:
-               return _T("REG_SZ\t\t\t");
+               return _T("REG_SZ");
        case REG_EXPAND_SZ:
-               return _T("REG_EXPAND_SZ\t\t");
+               return _T("REG_EXPAND_SZ");
        case REG_BINARY:
-               return _T("REG_BINARY\t\t");
+               return _T("REG_BINARY");
        case REG_DWORD_LITTLE_ENDIAN:
-               return _T("REG_DWORD_LITTLE_ENDIAN\t");
+               return _T("REG_DWORD_LITTLE_ENDIAN");
        case REG_DWORD_BIG_ENDIAN:
-               return _T("REG_DWORD_BIG_ENDIAN\t");
+               return _T("REG_DWORD_BIG_ENDIAN");
        case REG_LINK:
-               return _T("REG_LINK\t\t");
+               return _T("REG_LINK");
        case REG_MULTI_SZ:
-               return _T("REG_MULTI_SZ\t\t");
+               return _T("REG_MULTI_SZ");
        case REG_RESOURCE_LIST:
-               return _T("REG_RESOURCE_LIST\t");
+               return _T("REG_RESOURCE_LIST");
        case REG_FULL_RESOURCE_DESCRIPTOR:
                return _T("REG_FULL_RESOURCE_DESCRIPTOR");
        case REG_RESOURCE_REQUIREMENTS_LIST:
                return _T("REG_RESOURCE_REQUIREMENTS_LIST");
        default:
-               return _T("Unkown Type\t");
+               return _T("Unkown Type");
        }
 }
 
@@ -333,126 +497,78 @@ DWORD CRegistryKey::GetValue(TCHAR *pchValueName, DWORD *pdwType, LPBYTE lpValue
        return RegQueryValueEx(m_hKey,pchValueName,NULL,pdwType,lpValueDataBuffer,pdwValueDataSize);
 }
 
-DWORD CRegistryKey::GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor)
+LONG CRegistryKey::CreateSubkey(REGSAM samDesired,
+                                const TCHAR *pszSubkeyName,
+                                HKEY &rhKey,
+                                BOOL *pblnOpened,
+                                BOOL blnVolatile)
 {
-       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-               NULL,NULL,pdwSecurityDescriptor,NULL);
-}
+  DWORD dwDisposition;
+  
+       LONG nError = RegCreateKeyEx(
+      m_hKey,
+      pszSubkeyName,
+      0,
+      NULL,
+      blnVolatile?REG_OPTION_VOLATILE:REG_OPTION_NON_VOLATILE,
+      samDesired,
+      NULL,
+      &rhKey,
+      &dwDisposition);
 
-LONG CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
-{
-       return RegGetKeySecurity(m_hKey,SecurityInformation,pSecurityDescriptor,lpcbSecurityDescriptor);
+  if ((nError == ERROR_SUCCESS)&&(pblnOpened))
+    *pblnOpened = dwDisposition == REG_OPENED_EXISTING_KEY;
+  
+       return nError;
 }
 
-DWORD CRegistryKey::GetSubKeyCount()
+LONG CRegistryKey::GetLastWriteTime(SYSTEMTIME &st)
 {
-       DWORD nCount;
-       DWORD nRet = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,&nCount,NULL,NULL,NULL,
-               NULL,NULL,NULL,NULL);
-       if (nRet)
-               return 0;
-       return nCount;
-}
+       FILETIME ftLocal,ft;
+       LONG nError = RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&ft);
 
-DWORD CRegistryKey::GetValuesCount()
-{
-       DWORD nCount;
-       if (RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,
-               &nCount,NULL,NULL,NULL,NULL)) return 0;
-       return nCount;
+  if (nError == ERROR_SUCCESS)
+  {
+    FileTimeToLocalFileTime(&ft,&ftLocal);
+    FileTimeToSystemTime(&ftLocal,&st);
+  }
+
+  return nError;
 }
 
-TCHAR * CRegistryKey::GetSubKeyNameByIndex(DWORD dwIndex)
+const TCHAR * CRegistryKey::GetLastWriteTime()
 {
-       DWORD dwError;
-       static TCHAR m_pchSubName[MAX_PATH+1];
-       dwError = RegEnumKey(m_hKey,dwIndex,m_pchSubName,MAX_PATH + 1);
-       switch (dwError)
-       {
-       case ERROR_SUCCESS:
-               return m_pchSubName;
-       case ERROR_NO_MORE_ITEMS:
-               return NULL;
-       default:
-               return NULL;
-       }
+       SYSTEMTIME st;
+       if (GetLastWriteTime(st) != ERROR_SUCCESS)
+    return _T("(Cannot get time last write time)");
+  
+       static TCHAR Buffer[256];
+       _stprintf(Buffer,_T("%d.%d.%d %02d:%02d:%02d"),st.wDay,st.wMonth,st.wYear,st.wHour,st.wMinute,st.wSecond);
+       return Buffer;
 }
 
-DWORD CRegistryKey::Create(REGSAM samDesired, DWORD *pdwDisposition, BOOL blnVolatile)
+LONG CRegistryKey::GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor)
 {
-       ASSERT((m_hKey != HKEY_CLASSES_ROOT)&&(m_hKey != HKEY_CURRENT_USER)&&
-               (m_hKey != HKEY_LOCAL_MACHINE)&&(m_hKey != HKEY_USERS)
-               &&(m_hKey != HKEY_PERFORMANCE_DATA)&&(m_hKey != HKEY_CURRENT_CONFIG)
-               &&(m_hKey != HKEY_DYN_DATA));
-       if (m_hKey)
-       {
-               RegCloseKey(m_hKey);
-       }
-
-       HKEY hKey;
-
-       DWORD dwRet = RegCreateKeyEx(*m_pParent,m_pchKeyName,0,NULL,
-               blnVolatile?REG_OPTION_VOLATILE:REG_OPTION_NON_VOLATILE,
-               samDesired,
-               NULL,
-               &hKey,
-               pdwDisposition);
-       if (dwRet == ERROR_SUCCESS)
-       {
-               m_hKey = hKey;
-               UpdateKeyNameCase();
-       }
-       return dwRet;
+       return RegQueryInfoKeyW(m_hKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+               NULL,NULL,pdwSecurityDescriptor,NULL);
 }
 
-DWORD CRegistryKey::DeleteSubkey(LPCTSTR pszSubKey, BOOL blnRecursive)
+LONG CRegistryKey::GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
 {
-       CRegistryKey *pKey = new CRegistryKey(pszSubKey,this);
-       if (!pKey)
-               return ERROR_NOT_ENOUGH_MEMORY;
-
-       DWORD dwRet = pKey->Open(KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE);
-
-       if (!dwRet)
-               dwRet = pKey->Delete(blnRecursive);
-
-       delete pKey;
-
-       return dwRet;
+       return RegGetKeySecurity(m_hKey,SecurityInformation,pSecurityDescriptor,lpcbSecurityDescriptor);
 }
 
-DWORD CRegistryKey::Delete(BOOL blnRecursive)
+LONG CRegistryKey::DeleteSubkey(const TCHAR *pszSubkeyName)
 {
-       DWORD dwRet;
-       if (blnRecursive)
-       {
-               // Delete childs
-               while(GetSubKeyCount())
-               {
-                       TCHAR *pchKeyName = GetSubKeyNameByIndex(0);
-                       CRegistryKey *pKey = new CRegistryKey(pchKeyName,this);
-                       if (!pKey)
-                               return ERROR_NOT_ENOUGH_MEMORY;
-
-                       dwRet = pKey->Open(KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE);
-
-                       if (!dwRet)
-                               dwRet = pKey->Delete(blnRecursive);
-
-                       delete pKey;
-               }
-       }
-
-       // Delete yourself
-       return RegDeleteKey(m_pParent->m_hKey,m_pchKeyName);
+  return RegDeleteKey(m_hKey,pszSubkeyName);
 }
 
-DWORD CRegistryKey::SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize)
+LONG CRegistryKey::SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize)
 {
        return RegSetValueEx(m_hKey,pszValueName,0,dwType,lpData,dwDataSize);
 }
 
-DWORD CRegistryKey::DeleteValue(LPCTSTR pszValueName)
+LONG CRegistryKey::DeleteValue(const TCHAR *pszValueName)
 {
        return RegDeleteValue(m_hKey,pszValueName);
 }
index 38363e5..2de780c 100644 (file)
 class CRegistryKey  
 {
 public:
-       DWORD DeleteValue(LPCTSTR pszValueName);
-       DWORD SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize);
-       DWORD Delete(BOOL blnRecursive);
-       DWORD DeleteSubkey(LPCTSTR pszSubKey, BOOL blnRecursive = FALSE);
-       DWORD Create(REGSAM samDesired, DWORD *pdwDisposition = NULL, BOOL blnVolatile = FALSE);
+  // Constructor. Call InitXXX methods to make real construct.
+  CRegistryKey();
+  
+  // Call this key to init root key.
+  //
+  // Parameters:
+  //   pszMachineName - pointer to buffer containing machine name. NULL means local machine.
+  //
+  // Return value:
+  //   S_OK - All ok.
+  //   E_XXX - Error.
+       HRESULT InitRoot(const TCHAR *pszMachineName = NULL);
+
+  // Call this method to init normal key.
+  //
+  // Parameters:
+  //   hKey - handle to opened key.
+  //   pszPath - optional path string. NULL if pszKeyName is the needed name.
+  //   pszKeyName - pointer to buffer conatining name of key.
+  //   CurrentAccess - Access of hKey.
+  //
+  // Remarks:
+  //   Constructs key object from handle.
+  //   The constructed object hold the handle and closes it on destruction. Do not close handle outside.
+  //   If pszPath is not NULL, it is concatenated with pszKeyName.
+  //
+  // Return value:
+  //   S_OK - All ok.
+  //   E_XXX - Error.
+  HRESULT Init(HKEY hKey, const TCHAR *pszPath, const TCHAR *pszKeyName, REGSAM CurrentAccess);
+
+  // Call this method to uninitialize the object.
+  //
+  // Return value:
+  //   S_OK - All ok.
+  //   E_XXX - Error.
+  HRESULT Uninit();
+  
+  // Destructor
+       virtual ~CRegistryKey();
+
+  // Call ths function to check if handle to key is handle to hive root.
+  //
+  // Parameters:
+  //   hKey - handle to check.
+  //
+  // Return value:
+  //   TRUE - hKey is handle to hive root.
+  //   FALSE - hKey is not handle to hive root.
+  static BOOL IsHive(HKEY hKey);
+
+  // Call this method to get name of key represented by  this object.
+  //
+  // Return value:
+  //   Pointer to buffer containing key name. Return value is valid until next call to this object method.
+       const TCHAR * GetKeyName();
+
+  BOOL IsRoot();
+
+  // Call this method to open existing subkey of this key.
+  //
+  // Parameters:
+  //   samDesired - deisred access.
+  //   pszSubkeyName - pointer to bufer containing name of key to open.
+  //   rhKey - reference to variable that receives handle of opened key. If method fails, variable value is unchanged.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, HKEY &rhKey);
+  
+  // Call this method to open existing subkey of this key.
+  //
+  // Parameters:
+  //   samDesired - deisred access.
+  //   pszSubkeyName - pointer to bufer containing name of key to open.
+  //   rKey - reference to CRegistryKey object. If method succeeds, rKey is initialized with newly opened key.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG OpenSubkey(REGSAM samDesired, const TCHAR *pszSubkeyName, CRegistryKey &rKey);
+
+  // Call this method to get the length in TCHARs of longest subkey name, including terminating null.
+  //
+  // Parameters:
+  //   rdwMaxSubkeyNameLength, reference to variable that receives size in TCHARs of longest subkey name.
+  //
+  // Return value.
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetSubkeyNameMaxLength(DWORD &rdwMaxSubkeyNameLength);
+
+  // Call this method to init subkey enumeration. I.e. before first call to GetSubkeyName()
+  //
+  // Parameters:
+  //   pchSubkeyNameBuffer - pointer to buffer receiving subkey name.
+  //   dwBufferSize - size, in TCHARs of buffer pointed by pchSubkeyNameBuffer.
+  //
+       void InitSubkeyEnumeration(TCHAR *pchSubkeyNameBuffer, DWORD dwBufferSize);
+
+  // Call this method to get next subkey name. Name is stored in buffer specified in call to InitSubKeyEnumeration.
+  //
+  // Parameters:
+  //   pdwActualSize - optional pointer to variable receiving actual size, in TCHARs, of key name. The count returned does not include the terminating null.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+  //   If no more items available, return error is ERROR_NO_MORE_ITEMS.
+       LONG GetNextSubkeyName(DWORD *pdwActualSize = NULL);
+
+  // Call this method to get count of subkeys.
+  //
+  // Parameters:
+  //   rdwSubkeyCount - reference to variable that receives subkey count.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetSubkeyCount(DWORD &rdwSubkeyCount);
+
+  // Call this method to get the length in TCHARs of longest value name, including terminating null.
+  //
+  // Parameters:
+  //   rdwMaxValueNameBufferSize receives the length, in TCHARs, of the key's longest value name.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetMaxValueNameLength(DWORD& rdwMaxValueNameBufferSize);
+
+  // Call this method to get the size of larges value data.
+  //
+  // Parameters:
+  //   rdwMaxValueDataBufferSize receives the length, in bytes, of the longest data component among the key's values.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetMaxValueDataSize(DWORD& rdwMaxValueDataBufferSize);
+
+  // Call this method to init subkey enumeration. I.e. before first call to GetSubkeyName()
+  //
+  // Parameters:
+  //   pszValueNameBuffer - pointer to buffer receiving value name. If NULL, value name in not received upon iteration.
+  //   dwValueNameBufferSize - size, in TCHARs of buffer pointed by pszValueNameBuffer. If pszValueNameBuffer is NULL, parameter is ignored.
+  //   pbValueDataBuffer - pointer to buffer receiving value name. If NULL, value data is not received upon iteration.
+  //   dwValueDataBufferSize - size, in bytes of buffer pointed by pbValueDataBuffer. If pbValueDataBuffer is NULL, parameter is ignored.
+  //   pdwType - pointer to variable receiving value type. If NULL, value type is not received upon iteration.
+       void InitValueEnumeration(TCHAR *pszValueNameBuffer,
+                            DWORD dwValueNameBufferSize,
+                            BYTE *pbValueDataBuffer,
+                            DWORD dwValueDataBufferSize,
+                            DWORD *pdwType);
+  
+  // Call this method to get next value  name/data/type. Name/data/type is/are stored in buffer(s) specified in call to InitValueEnumeration.
+  //
+  // Parameters:
+  //   pdwNameActualSize - optional pointer to variable receiving actual size, in TCHARs, of value name. The count returned includes the terminating null.
+  //   pdwActualSize - optional pointer to variable receiving actual size, in bytes, of key name. The count returned does not include the terminating null.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+  //   If no more items available, return error is ERROR_NO_MORE_ITEMS.
+       LONG GetNextValue(DWORD *pdwNameActualSize = NULL, DWORD *pdwDataActualSize = NULL);
+  
+  // Call this method to get count of values.
+  //
+  // Parameters:
+  //   rdwValueCount - reference to variable that receives value count.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetValueCount(DWORD& rdwValueCount);
+
+  // Call this method to get data and/or type of default value.
+  //
+  // Parameters:
+  //   pdwType - optional pointer to variable receiving default value type. NULL if not requred.
+  //   pbValueDataBuffer - optional pointer to buffer receiving default value data. NULL if not requred.
+  //   dwValueDataBufferSize - size of buffer pointer by pbValueDataBuffer. Ignored if pbValueDataBuffer is NULL.
+  //   pdwValueDataActualSize - optional pointer to variable receiving size, in bytes, of data stored into buffer. If pbValueDataBuffer is NULL, returned value is size of default value data, in bytes.
+  // 
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG GetDefaultValue(DWORD *pdwType, BYTE *pbValueDataBuffer, DWORD dwValueDataBufferSize, DWORD *pdwValueDataActualSize);
+
+  // Call this function to get text representation of value type.
+  //
+  // Parameters:
+  //   dwType - type to get text representation from.
+  //
+  // Return value:
+  //   text representation od value type.
+       static const TCHAR * GetValueTypeName(DWORD dwType);
+  
+       DWORD GetValue(TCHAR *pchValueName, DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize);
+
+  // Call this method to create subkey of this key.
+  //
+  // Parameters:
+  //   samDesired - deisred access.
+  //   pszKeyName - pointer to bufer containing name of key to create.
+  //   rhKey - reference to variable that receives handle of opened key. If method fails, variable value is unchanged.
+  //   pblnOpened - optional pointer to variable that receives create/open status. If subkey is opened value is TRUE. If key is created value is FALSE.
+  //   blnVolatile - opitional parameter specifining if created key is volatile.
+  //
+  // Return value:
+  //   If the method succeeds, the return value is ERROR_SUCCESS.
+  //   If the method fails, the return value is a nonzero error code defined in winerror.h.
+       LONG CreateSubkey(REGSAM samDesired, const TCHAR *pszKeyName, HKEY &rhKey, BOOL *pblnOpened = NULL, BOOL blnVolatile = FALSE);
+  
+       LONG GetLastWriteTime(SYSTEMTIME& st);
+       const TCHAR * GetLastWriteTime();
+  
+       LONG DeleteValue(const TCHAR *pszValueName);
+       LONG DeleteSubkey(const TCHAR *pszPatternSubkeyName);
+  
+       LONG SetValue(LPCTSTR pszValueName, DWORD dwType, BYTE *lpData, DWORD dwDataSize);
        TCHAR * GetSubKeyNameByIndex(DWORD dwIndex);
-       DWORD GetValuesCount();
-       DWORD GetSubKeyCount();
        LONG GetSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor);
-       DWORD GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor);
-       DWORD GetValue(TCHAR *pchValueName, DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize);
-       static const TCHAR * GetValueTypeName(DWORD dwType);
-       void LinkParent();
-       DWORD GetDefaultValue(DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize);
+       LONG GetSecurityDescriptorLength(DWORD *pdwSecurityDescriptor);
        BOOL IsPredefined();
-       DWORD Open(REGSAM samDesired);
-       DWORD GetMaxValueNameLength(DWORD& dwMaxValueNameBuferSize);
-       DWORD GetMaxValueDataSize(DWORD& dwMaxValueDataBuferSize);
-       TCHAR * GetLastWriteTime();
-       void GetLastWriteTime(SYSTEMTIME& st);
-       DWORD GetNextValue(TCHAR *pchValueNameBuffer,DWORD& dwValueNameSize, DWORD *pdwType, LPBYTE lpValueDataBuffer, DWORD *pdwValueDataSize);
-       void InitValueEnumeration();
-       void UpdateKeyNameCase();
-       TCHAR * GetSubKeyName(DWORD& dwError);
-       void InitSubKeyEnumeration();
-       CRegistryKey * UpOneLevel();
        operator HKEY(){return m_hKey;};
-       CRegistryKey * GetParent();
-       class CRegistryKey * GetChild();
-       TCHAR * GetKeyName();
-       CRegistryKey(const TCHAR *pchKeyName, class CRegistryKey *pParent);
-       CRegistryKey(HKEY hKey, LPCTSTR pszMachineName = NULL);
-       virtual ~CRegistryKey();
 private:
        DWORD m_dwCurrentSubKeyIndex;
+  TCHAR *m_pchSubkeyNameBuffer;
+  DWORD m_dwSubkeyNameBufferSize;
+  
        DWORD m_dwCurrentValueIndex;
+  TCHAR *m_pszValueNameBuffer;
+  DWORD m_dwValueNameBufferSize;
+  BYTE *m_pbValueDataBuffer;
+  DWORD m_dwValueDataBufferSize;
+  DWORD *m_pdwType;
+  
        HKEY m_hKey;
-       class CRegistryKey *m_pChild;
-       class CRegistryKey *m_pParent;
-       TCHAR m_pchKeyName[MAX_PATH+1];
-//     TCHAR *m_pchValueName;
-       TCHAR m_pszMachineName[MAX_PATH+1];
+       TCHAR *m_pszKeyName;
+       TCHAR *m_pszMachineName;
+       REGSAM m_CurrentAccess;
 };
 
 #endif // !defined(REGISTRYKEY_H__FEF419ED_6EB6_11D3_907D_204C4F4F5020__INCLUDED_)
index b1f26d5..4d38cd8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: RegistryTree.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: RegistryTree.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
  */
 
 // RegistryTree.cpp: implementation of the CRegistryTree class.
-//
-//////////////////////////////////////////////////////////////////////
 
 #include "ph.h"
 #include "RegistryTree.h"
+#include "Pattern.h"
+#include "RegistryExplorer.h"
 
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-CRegistryTree::CRegistryTree(unsigned int nMaxPathSize)
+CRegistryTree::CRegistryTree()
 {
        m_pszMachineName = NULL;
-       m_samDesiredOpenKeyAccess = 0;
-       m_pCurrentKey = m_pRoot = NULL;
+  VERIFY(SUCCEEDED(m_Root.m_Key.InitRoot()));
+  m_Root.m_pUp = NULL;
+       m_pCurrentKey = &m_Root;
+  ASSERT(m_pCurrentKey->m_Key.IsRoot());
        m_ErrorMsg[ERROR_MSG_BUFFER_SIZE] = 0;
-       m_ChangeKeyBuffer = new TCHAR[nMaxPathSize];
-//#ifdef _DEBUG
-       m_nMaxPathSize = nMaxPathSize;
-//#endif
 }
 
 CRegistryTree::CRegistryTree(const CRegistryTree& Tree)
 {
        m_pszMachineName = NULL;
-       m_samDesiredOpenKeyAccess = Tree.GetDesiredOpenKeyAccess();
-       m_pCurrentKey = m_pRoot = NULL;
-       m_ErrorMsg[ERROR_MSG_BUFFER_SIZE] = 0;
-       m_ChangeKeyBuffer = new TCHAR[m_nMaxPathSize = Tree.m_nMaxPathSize];
-       _tcscpy(m_ChangeKeyBuffer,Tree.GetCurrentPath());
-       ChangeCurrentKey(m_ChangeKeyBuffer);
+  VERIFY(SUCCEEDED(m_Root.m_Key.InitRoot()));
+  m_Root.m_pUp = NULL;
+       m_pCurrentKey = &m_Root;
+  ASSERT(m_pCurrentKey->m_Key.IsRoot());
+
+  const TCHAR *pszPath = Tree.GetCurrentPath();
+  if ((pszPath[0] == _T('\\')) && (pszPath[1] == _T('\\')))
+  { // path has machine name
+    pszPath += 2;
+    while (*pszPath && (*pszPath != _T('\\')))
+      pszPath++;
+    
+    ASSERT(*pszPath == _T('\\')); // if path begins with \\ it must be followed by machine name
+  }
+
+  if (Tree.m_pszMachineName)
+    SetMachineName(Tree.m_pszMachineName);
+  
+  VERIFY(ChangeCurrentKey(pszPath));
 }
 
 CRegistryTree::~CRegistryTree()
@@ -59,388 +66,574 @@ CRegistryTree::~CRegistryTree()
        if (m_pszMachineName)
                delete m_pszMachineName;
 
-       CRegistryKey *pNode;
-       while(m_pRoot)
+       CNode *pNode;
+       while(m_pCurrentKey->m_pUp)
        {
-               pNode = m_pRoot;
-               m_pRoot = m_pRoot->GetChild();
+               pNode = m_pCurrentKey;
+               m_pCurrentKey = m_pCurrentKey->m_pUp;
                delete pNode;
        }
 
-       delete [] m_ChangeKeyBuffer;
+  // We are on root
+  ASSERT(m_pCurrentKey->m_Key.IsRoot());
+  ASSERT(m_pCurrentKey == &m_Root);
 }
 
 const TCHAR * CRegistryTree::GetCurrentPath() const
 {
-       ASSERT(m_nMaxPathSize > 0);
-       unsigned int nBufferSize = m_nMaxPathSize;
-       CRegistryKey *pNode = m_pRoot;
-
-       nBufferSize--;
-       m_ChangeKeyBuffer[nBufferSize] = 0;
-
-       TCHAR *pchCurrentOffset = m_ChangeKeyBuffer;
-
-       if (m_pszMachineName)
-       {
-               size_t m = _tcslen(m_pszMachineName+2);
-               if (m > nBufferSize)
-               {       // No enough space in buffer to store machine name
-                       ASSERT(FALSE);
-               }
-               else
-               {
-                       _tcscpy(pchCurrentOffset,m_pszMachineName+2);
-                       pchCurrentOffset += m;
-                       nBufferSize -= m;
-               }
-       }
-
-       if (2 > nBufferSize)
-       {       // No enough space in buffer to store '\\'
-               ASSERT(FALSE);
-       }
-       else
-       {
-               *pchCurrentOffset = _T('\\');
-               pchCurrentOffset++;
-               nBufferSize--;
-       }
-
-       while(pNode)
-       {
-               TCHAR *pchKeyName = pNode->GetKeyName();
-               unsigned int nKeyNameLength = _tcslen(pchKeyName);
-               if ((nKeyNameLength+1) > nBufferSize)
-               {       // No enough space in buffer to store key name + '\\'
-                       ASSERT(FALSE);
-                       break;
-               }
-               _tcscpy(pchCurrentOffset,pchKeyName);
-               pchCurrentOffset[nKeyNameLength] = '\\';
-               pchCurrentOffset += nKeyNameLength+1;
-               nBufferSize -= nKeyNameLength+1;
-               pNode = pNode->GetChild();
-       }
-       *pchCurrentOffset = 0;
-       return m_ChangeKeyBuffer;
+  return m_pCurrentKey->m_Key.GetKeyName();
 }
 
 BOOL CRegistryTree::IsCurrentRoot()
 {
-       return m_pRoot == NULL;
+       return m_pCurrentKey->m_Key.IsRoot();
 }
 
-// returns TRUE on success and FALSE on fail
-// on fail, extended information can be received  by calling GetLastErrorDescription();
-BOOL CRegistryTree::ChangeCurrentKey(const TCHAR *pchRelativePath)
+BOOL CRegistryTree::ChangeCurrentKey(const TCHAR *pszRelativePath)
 {
-       if (*pchRelativePath == _T('\\'))
+  if (*pszRelativePath == _T('\\'))
+    GotoRoot();  // This is full absolute path.
+
+  // split path to key names.
+       TCHAR *pszSeps = _T("\\");
+
+  // Make buffer and copy relative path into it.
+  TCHAR *pszBuffer = new TCHAR[_tcslen(pszRelativePath)+1];
+  if (!pszBuffer)
+  {
+    SetError(ERROR_OUTOFMEMORY);
+    return FALSE;
+  }
+
+       _tcscpy(pszBuffer,pszRelativePath);
+
+  // We accept names in form "\"blablabla\\blab  labla\"\\"
+  size_t size = _tcslen(pszBuffer);
+  if (size)
+  {
+    if (pszBuffer[size-1] == _T('\\'))
+      pszBuffer[--size] = 0;
+      
+    if ((*pszBuffer == _T('\"'))&&(pszBuffer[size-1] == _T('\"')))
+    {
+      size--;
+      pszBuffer[size] = 0;     LONG ConnectRegistry(HKEY hKey);
+
+      pszBuffer++;
+    }
+  }
+
+       TCHAR *pszNewKey = _tcstok(pszBuffer,pszSeps);
+
+       if ((!pszNewKey)&&((*pszRelativePath != _T('\\'))||(*(pszRelativePath+1) != 0)))
        {
-               CRegistryKey *pNode;
-               while(m_pRoot)
-               {
-                       pNode = m_pRoot;
-                       m_pRoot = m_pRoot->GetChild();
-                       delete pNode;
-               }
-               m_pCurrentKey = NULL;
-       }
-       TCHAR *pchSeps = _T("\\");
-
-       ASSERT(_tcslen(pchRelativePath) <= m_nMaxPathSize);
-       _tcscpy(m_ChangeKeyBuffer,pchRelativePath);
-
-       TCHAR *pchNewKey = _tcstok(m_ChangeKeyBuffer,pchSeps);
-
-       if ((!pchNewKey)&&((*pchRelativePath != _T('\\'))||(*(pchRelativePath+1) != 0)))
-       {
-               _tcscpy(m_ErrorMsg,_T("Invalid key name"));
-               return FALSE;
+               SetError(_T("Invalid key name"));
+               goto Abort;
        };
-       while (pchNewKey)
+
+  // change keys
+       while (pszNewKey)
        {
-               HKEY hNewKey;
-               if (m_pRoot == NULL)
-               {       // if this is the root key there are limations
-                       if ((_tcsicmp(pchNewKey,_T("HKCR")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_CLASSES_ROOT")) == 0))
-                       {
-                               hNewKey = HKEY_CLASSES_ROOT;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKCU")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_CURRENT_USER")) == 0))
-                       {
-                               hNewKey = HKEY_CURRENT_USER;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKLM")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_LOCAL_MACHINE")) == 0))
-                       {
-                               hNewKey = HKEY_LOCAL_MACHINE;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKU")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_USERS")) == 0))
-                       {
-                               hNewKey = HKEY_USERS;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKPD")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_PERFORMANCE_DATA")) == 0))
-                       {
-                               hNewKey = HKEY_PERFORMANCE_DATA;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKDD")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_DYN_DATA")) == 0))
-                       {
-                               hNewKey = HKEY_DYN_DATA;
-                       }
-                       else if ((_tcsicmp(pchNewKey,_T("HKCC")) == 0)||
-                               (_tcsicmp(pchNewKey,_T("HKEY_CURRENT_CONFIG")) == 0))
-                       {
-                               hNewKey = HKEY_CURRENT_CONFIG;
-                       }
-                       else
-                       {
-                               _tcscpy(m_ErrorMsg,_T("Invalid key name."));
-                               return FALSE;
-                       }
-                       // Ok. Key to open is in hNewKey
-
-                       int nErr = ConnectRegistry(hNewKey);
-                       if (nErr)
-                       {
-                               _stprintf(m_ErrorMsg,_T("Cannot connect registry. Error is %d"),nErr);
-                               return FALSE;
-                       }
-               }       // if (m_pRoot == NULL)
-               else
-               {       // current key is not root key
-                       if (_tcsicmp(pchNewKey,_T("..")) == 0)
-                       {
-                               m_pCurrentKey = m_pCurrentKey->UpOneLevel();
-                               if (m_pCurrentKey == NULL)
-                               {
-                                       m_pRoot = NULL;
-                               }
-                       }
-                       else
-                       {       // Normal key name
-                               CRegistryKey *pNewKey = new CRegistryKey(pchNewKey,m_pCurrentKey);
-                               //RegOpenKeyExW(*m_pCurrentKey,pchNewKey,0,KEY_EXECUTE,&hNewKey)
-                               DWORD dwError = pNewKey->Open(m_samDesiredOpenKeyAccess);
-                               if (dwError != ERROR_SUCCESS)
-                               {
-                                       TCHAR *pchPreErrorMsg = _T("Cannot open key : "), *pchCurrentOffset = m_ErrorMsg;
-                                       _tcscpy(pchCurrentOffset,pchPreErrorMsg);
-                                       pchCurrentOffset += _tcslen(pchPreErrorMsg);
-
-                                       _tcscpy(pchCurrentOffset,pchNewKey);
-                                       pchCurrentOffset += _tcslen(pchNewKey);
-
-                                       TCHAR *pchMsg = _T("\nError ");
-                                       _tcscpy(pchCurrentOffset,pchMsg);
-                                       pchCurrentOffset += _tcslen(pchMsg);
-
-                                       TCHAR Buffer[256];
-                                       _tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
-                                       pchCurrentOffset += _tcslen(Buffer);
-
-                                       pchMsg = _T("\n");
-                                       _tcscpy(pchCurrentOffset,pchMsg);
-                                       pchCurrentOffset += _tcslen(pchMsg);
-                                       switch(dwError)
-                                       {
-                                       case 5:
-                                               pchMsg = _T("(Access denied)");
-                                               break;
-                                       case 2:
-                                               pchMsg = _T("(The system cannot find the key specified)");
-                                               break;
-                                       }
-
-                                       _tcscpy(pchCurrentOffset,pchMsg);
-                                       pchCurrentOffset += _tcslen(pchMsg);
-
-                                       delete pNewKey;
-
-                                       return FALSE;
-                               }
-                               pNewKey->LinkParent();
-                               m_pCurrentKey = pNewKey;
-                       }
-               }
+    if (!InternalChangeCurrentKey(pszNewKey,KEY_READ))
+      goto Abort;  // InternalChangeCurrentKey sets last error description
+
                // Get next key name
-               pchNewKey = _tcstok(NULL,pchSeps);
+               pszNewKey = _tcstok(NULL,pszSeps);
        }
+  
        return TRUE;
-}
 
-TCHAR * CRegistryTree::GetLastErrorDescription()
-{
-       return m_ErrorMsg;
+Abort:
+  delete pszBuffer;
+  return FALSE;
 }
 
-CRegistryKey * CRegistryTree::GetCurrentKey()
+const TCHAR * CRegistryTree::GetLastErrorDescription()
 {
-       return m_pCurrentKey;
+       return m_ErrorMsg;
 }
 
-void CRegistryTree::SetDesiredOpenKeyAccess(REGSAM samDesired)
+void CRegistryTree::GotoRoot()
 {
-       m_samDesiredOpenKeyAccess = samDesired;
+  // Delete current tree
+  CNode *pNode;
+  while(m_pCurrentKey->m_pUp)
+  {
+    pNode = m_pCurrentKey;
+    m_pCurrentKey = m_pCurrentKey->m_pUp;
+    delete pNode;
+  }
+
+  // We are on root
+  ASSERT(m_pCurrentKey->m_Key.IsRoot());
+  ASSERT(m_pCurrentKey == &m_Root);
 }
 
-REGSAM CRegistryTree::GetDesiredOpenKeyAccess() const
+BOOL CRegistryTree::SetMachineName(LPCTSTR pszMachineName)
 {
-       return m_samDesiredOpenKeyAccess;
+  GotoRoot();
+  
+  // If we are going to local machine...
+  if (pszMachineName == NULL)
+  {
+    // Delete previous machine name buffer if allocated.
+    if (m_pszMachineName)
+      delete m_pszMachineName;
+    
+    m_pszMachineName = NULL;
+    m_Root.m_Key.InitRoot();
+    return TRUE;
+  }
+
+  // Skip leading backslashes if any.
+  while ((*pszMachineName)&&(*pszMachineName == _T('\\')))
+    pszMachineName++;
+
+  ASSERT(*pszMachineName);      // No machine name.
+
+  TCHAR *pszNewMachineName = new TCHAR[_tcslen(pszMachineName)+3]; // two leading backslashes + terminating null
+
+  if (!pszMachineName)
+  {
+    SetError(ERROR_OUTOFMEMORY);
+    return FALSE;
+  }
+    
+  // Delete previous machine name buffer if allocated.
+  if (m_pszMachineName)
+    delete m_pszMachineName;
+  
+  m_pszMachineName = pszNewMachineName;
+  
+  _tcscpy(m_pszMachineName,_T("\\\\")); // leading backslashes
+  _tcscpy(m_pszMachineName+2,pszMachineName); // machine name itself
+  _tcsupr(m_pszMachineName+2);  // upercase it
+  
+  VERIFY(SUCCEEDED(m_Root.m_Key.InitRoot(m_pszMachineName)));
+  return TRUE;
 }
 
-int CRegistryTree::ConnectRegistry(HKEY hKey)
+BOOL CRegistryTree::NewKey(const TCHAR *pszKeyName, const TCHAR *pszPath, BOOL blnVolatile)
 {
-       CRegistryKey *pKey = new CRegistryKey(hKey,m_pszMachineName);
-       int ret = pKey->Open(m_samDesiredOpenKeyAccess);
-
-       if (ret == 0)
+  if (!m_pCurrentKey)
+  {
+    SetErrorCommandNAOnRoot(_T("Creating new key "));
+    return FALSE;
+  }
+
+  CRegistryTree Tree(*this);
+       if (!Tree.ChangeCurrentKey(pszPath))
+  {
+    SetError(Tree.GetLastErrorDescription());
+    return FALSE;
+  }
+  
+       BOOL blnOpened;
+  HKEY hKey;
+  
+       LONG nError = Tree.m_pCurrentKey->m_Key.CreateSubkey(KEY_READ,
+                                                       pszKeyName,
+                                                       hKey,
+                                                       &blnOpened,
+                                                       blnVolatile);
+  if (nError == ERROR_SUCCESS)
+  {
+    LONG nError = RegCloseKey(hKey);
+    ASSERT(nError == ERROR_SUCCESS);
+  }
+  
+       if ((nError == ERROR_SUCCESS) && blnOpened)
        {
-               CRegistryKey *pNode;
-               while(m_pRoot)
-               {
-                       pNode = m_pRoot;
-                       m_pRoot = m_pRoot->GetChild();
-                       delete pNode;
-               }
-               m_pCurrentKey = NULL;
-               m_pRoot = m_pCurrentKey = pKey;
+               SetError(_T("A key \"%s\" already exists."),pszKeyName);
+    return FALSE;
        }
-       else
+  
+       if (nError != ERROR_SUCCESS)
        {
-               delete pKey;
+               SetError(_T("Cannot create key : %s%s\nError %d (%s)\n"),
+             GetCurrentPath(),pszKeyName,nError,GetErrorDescription(nError));
+    
+    return FALSE;
        }
 
-       return ret;
+       return TRUE;
 }
 
-void CRegistryTree::SetMachineName(LPCTSTR pszMachineName)
+BOOL CRegistryTree::DeleteSubkeys(const TCHAR *pszKeyPattern, const TCHAR *pszPath, BOOL blnRecursive)
 {
-       if (m_pszMachineName)
-               delete m_pszMachineName;
+  CRegistryKey Key;
+  if (!GetKey(pszPath,KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS|DELETE,Key))
+    return FALSE;
+  
+  return DeleteSubkeys(Key, pszKeyPattern, blnRecursive);
+}
 
-       if (pszMachineName == NULL)
-       {
-               m_pszMachineName = NULL;
-               return;
-       }
+BOOL CRegistryTree::DeleteSubkeys(CRegistryKey& rKey, const TCHAR *pszKeyPattern, BOOL blnRecursive)
+{
+  LONG nError;
+
+  // enumerate subkeys
+  DWORD dwMaxSubkeyNameLength;
+  nError = rKey.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
+  if (nError != ERROR_SUCCESS)
+  {
+    SetError(_T("Cannot delete subkeys(s) of key %s.\nRequesting info about key failed.\nError %d (%s)\n"),
+             rKey.GetKeyName(),nError,GetErrorDescription(nError));
+    return FALSE;
+  }
+
+  TCHAR *pszSubkeyName = new TCHAR [dwMaxSubkeyNameLength];
+  rKey.InitSubkeyEnumeration(pszSubkeyName, dwMaxSubkeyNameLength);
+  BOOL blnKeyDeleted = FALSE;
+  while ((nError = rKey.GetNextSubkeyName()) == ERROR_SUCCESS)
+  {
+    if (blnRecursive)
+    { // deltion is recursive, delete subkey subkeys
+      CRegistryKey Subkey;
+      // open subkey
+      nError = rKey.OpenSubkey(DELETE,pszSubkeyName,Subkey);
+      // delete subkey subkeys
+      if (DeleteSubkeys(Subkey, PATTERN_MATCH_ALL, TRUE))
+      {
+        AddErrorDescription(_T("Cannot delete subkey(s) of key %s. Subkey deletion failed.\n"),Subkey.GetKeyName());
+        return FALSE;
+      }
+    }
+
+    if (PatternMatch(pszKeyPattern,pszSubkeyName))
+    {
+      nError = rKey.DeleteSubkey(pszSubkeyName);
+      if (nError != ERROR_SUCCESS)
+      {
+        SetError(_T("Cannot delete the %s subkey of key %s.\nError %d (%s)\n"),
+                 pszSubkeyName,rKey.GetKeyName(),nError,GetErrorDescription(nError));
+    
+        return FALSE;
+      }
+      blnKeyDeleted = TRUE;
+    }
+  }
+
+  ASSERT(nError != ERROR_SUCCESS);
+  if (nError != ERROR_NO_MORE_ITEMS)
+  {
+    SetError(_T("Cannot delete subkeys(s) of key %s.\nSubkey enumeration failed.\nError %d (%s)\n"),
+             rKey.GetKeyName(),nError,GetErrorDescription(nError));
+    return FALSE;
+  }
+
+  if (!blnKeyDeleted)
+    SetError(_T("The key %s has no subkeys that match %s pattern.\n"),rKey.GetKeyName(),pszKeyPattern);
+
+  return blnKeyDeleted;
+}
 
-       while ((*pszMachineName)&&(*pszMachineName == _T('\\')))
-               pszMachineName++;
+const TCHAR * CRegistryTree::GetErrorDescription(LONG nError)
+{
+  switch(nError)
+  {
+  case ERROR_ACCESS_DENIED:
+    return _T("Access denied");
+  case ERROR_FILE_NOT_FOUND:
+    return _T("The system cannot find the key specified");
+  case ERROR_INTERNAL_ERROR:
+    return _T("Internal error");
+  case ERROR_OUTOFMEMORY:
+    return _T("Out of memory");
+  default:
+    return _T("Unknown error");
+  }
+}
 
-       if (*pszMachineName == 0)
-       {
-               ASSERT(FALSE);
-       }
+void CRegistryTree::SetError(LONG nError)
+{
+  SetError(_T("Error %u (%s)"),nError,GetErrorDescription(nError));
+}
 
-       m_pszMachineName = new TCHAR[_tcslen(pszMachineName)+3];
-       _tcscpy(m_pszMachineName,_T("\\\\"));
-       _tcscpy(m_pszMachineName+2,pszMachineName);
-       _tcsupr(m_pszMachineName+2);
+void CRegistryTree::SetError(const TCHAR *pszFormat, ...)
+{
+  va_list args;
+  va_start(args,pszFormat);
+  if (_vsntprintf(m_ErrorMsg,ERROR_MSG_BUFFER_SIZE,pszFormat,args) < 0)
+    m_ErrorMsg[ERROR_MSG_BUFFER_SIZE] = 0;
+  va_end(args);
 }
 
-BOOL CRegistryTree::NewKey(const TCHAR *pchKeyName, BOOL blnVolatile)
+void CRegistryTree::SetInternalError()
 {
-       CRegistryKey *pNewKey = new CRegistryKey(pchKeyName,m_pCurrentKey);
-       DWORD dwDisposition;
-       DWORD dwError = pNewKey->Create(0,&dwDisposition,blnVolatile);
-       switch (dwDisposition)
-       {
-       case REG_OPENED_EXISTING_KEY:
-               _sntprintf(m_ErrorMsg,ERROR_MSG_BUFFER_SIZE,_T("A key \"%s\" already exists."),pchKeyName);
-               delete pNewKey;
-               return FALSE;
-       case REG_CREATED_NEW_KEY:
-               break;
-       default:
-               ASSERT(FALSE);
-       }
-       if (dwError != ERROR_SUCCESS)
-       {
-               TCHAR *pchCurrentOffset = m_ErrorMsg;
-               TCHAR *pchPreErrorMsg = _T("Cannot create key : ");
-               _tcscpy(pchCurrentOffset,pchPreErrorMsg);
-               pchCurrentOffset += _tcslen(pchPreErrorMsg);
-
-               _tcscpy(pchCurrentOffset,pchKeyName);
-               pchCurrentOffset += _tcslen(pchKeyName);
-
-               TCHAR *pchMsg = _T("\nError ");
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-
-               TCHAR Buffer[256];
-               _tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
-               pchCurrentOffset += _tcslen(Buffer);
-
-               pchMsg = _T("\n");
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-               switch(dwError)
-               {
-               case 5:
-                       pchMsg = _T("(Access denied)");
-                       break;
-               case 2:
-                       pchMsg = _T("(The system cannot find the key specified)");
-                       break;
-               }
-
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-
-               delete pNewKey;
-
-               return FALSE;
-       }
+  SetError(_T("Internal Error"));
+}
 
-       delete pNewKey;
+void CRegistryTree::AddErrorDescription(const TCHAR *pszFormat, ...)
+{
+  size_t size = _tcslen(m_ErrorMsg);
+  if (size < ERROR_MSG_BUFFER_SIZE)
+  {
+    TCHAR *pszAdd = m_ErrorMsg+size;
+    va_list args;
+    va_start(args,pszFormat);
+    size = ERROR_MSG_BUFFER_SIZE-size;
+    if (_vsntprintf(pszAdd,size,pszFormat,args) < 0)
+      m_ErrorMsg[size] = 0;
+    va_end(args);
+  }
+}
 
-       return TRUE;
+void CRegistryTree::SetErrorCommandNAOnRoot(const TCHAR *pszCommand)
+{
+  ASSERT(pszCommand);
+  if (pszCommand)
+    SetError(_T("%s") COMMAND_NA_ON_ROOT,pszCommand);
+  else
+    SetInternalError();
 }
 
-BOOL CRegistryTree::DeleteKey(const TCHAR *pchKeyName, BOOL blnRecursive)
+BOOL CRegistryTree::InternalChangeCurrentKey(const TCHAR *pszSubkeyName, REGSAM DesiredAccess)
 {
-       DWORD dwError = m_pCurrentKey->DeleteSubkey(pchKeyName,blnRecursive);
-       if (dwError != ERROR_SUCCESS)
-       {
-               TCHAR *pchPreErrorMsg = _T("Cannot open key : "), *pchCurrentOffset = m_ErrorMsg;
-               _tcscpy(pchCurrentOffset,pchPreErrorMsg);
-               pchCurrentOffset += _tcslen(pchPreErrorMsg);
-
-               _tcscpy(pchCurrentOffset,pchKeyName);
-               pchCurrentOffset += _tcslen(pchKeyName);
-
-               TCHAR *pchMsg = _T("\nError ");
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-
-               TCHAR Buffer[256];
-               _tcscpy(pchCurrentOffset,_itot(dwError,Buffer,10));
-               pchCurrentOffset += _tcslen(Buffer);
-
-               pchMsg = _T("\n");
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-               switch(dwError)
-               {
-               case 5:
-                       pchMsg = _T("(Access denied)");
-                       break;
-               case 2:
-                       pchMsg = _T("(The system cannot find the key specified)");
-                       break;
-               }
-
-               _tcscpy(pchCurrentOffset,pchMsg);
-               pchCurrentOffset += _tcslen(pchMsg);
-
-               return FALSE;
-       }
-       return TRUE;
+  size_t size = _tcslen(pszSubkeyName);
+  TCHAR *pszSubkeyNameBuffer = new TCHAR[size+3];
+  if (!pszSubkeyNameBuffer)
+  {
+    SetError(_T("Cannot open key : %s%s\nError %d (%s)\n"),
+             GetCurrentPath(),pszSubkeyName,ERROR_OUTOFMEMORY,GetErrorDescription(ERROR_OUTOFMEMORY));
+  }
+
+  _tcscpy(pszSubkeyNameBuffer,pszSubkeyName);
+  if (size && (pszSubkeyName[0] == _T('\"')) && (pszSubkeyName[size-1] == _T('\"')))
+  {
+    pszSubkeyNameBuffer[size-1] = 0;
+    pszSubkeyName = pszSubkeyNameBuffer+1;
+  }
+  
+  if (_tcscmp(pszSubkeyName,_T(".")) == 0)
+  {
+    delete pszSubkeyNameBuffer;
+    return TRUE;
+  }
+
+  if (_tcscmp(pszSubkeyName,_T("..")) == 0)
+  {
+    // Up level abstraction
+    if (m_pCurrentKey->m_Key.IsRoot())
+    {
+      // We are on root
+      ASSERT(m_pCurrentKey->m_pUp == NULL);
+      SetError(_T("Cannot open key. The root is not child.\n"));
+      delete pszSubkeyNameBuffer;
+      return FALSE;
+    }
+      
+    ASSERT(m_pCurrentKey->m_pUp);
+    if (!m_pCurrentKey->m_pUp)
+    {
+      SetInternalError();
+      delete pszSubkeyNameBuffer;
+      return FALSE;
+    }
+    CNode *pNode = m_pCurrentKey;
+    m_pCurrentKey = m_pCurrentKey->m_pUp;
+    delete pNode;
+    delete pszSubkeyNameBuffer;
+    return TRUE;
+  }
+
+  CNode *pNewKey = new CNode;
+  if (!pNewKey)
+  {
+    SetError(_T("Cannot open key : %s%s\nError %d (%s)\n"),
+             GetCurrentPath(),pszSubkeyName,ERROR_OUTOFMEMORY,GetErrorDescription(ERROR_OUTOFMEMORY));
+    delete pszSubkeyNameBuffer;
+    return FALSE;
+  }
+
+  if (!InternalGetSubkey(pszSubkeyName,DesiredAccess,pNewKey->m_Key))
+  {
+    delete pNewKey;
+    delete pszSubkeyNameBuffer;
+    return FALSE;
+  }
+  pNewKey->m_pUp = m_pCurrentKey;
+  m_pCurrentKey = pNewKey;
+  
+  delete pszSubkeyNameBuffer;
+  return TRUE;
 }
+
+BOOL CRegistryTree::InternalGetSubkey(const TCHAR *pszSubkeyName, REGSAM DesiredAccess, CRegistryKey& rKey)
+{
+  LONG nError;
+  HKEY hNewKey = NULL;
+  TCHAR *pszSubkeyNameCaseUpdated = NULL;
+
+  nError = m_pCurrentKey->m_Key.OpenSubkey(DesiredAccess,pszSubkeyName,hNewKey);
+
+  if (nError != ERROR_SUCCESS)
+  {
+               SetError(_T("Cannot open key : %s%s\nError %u (%s)\n"),
+             GetCurrentPath(),pszSubkeyName,nError,GetErrorDescription(nError));
+
+    return FALSE;
+  }
+
+  // enum subkeys to find the subkey and get its name in stored case.
+  DWORD dwMaxSubkeyNameLength;
+       nError = m_pCurrentKey->m_Key.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
+  if (nError != ERROR_SUCCESS)
+    goto SkipCaseUpdate;
+  
+  pszSubkeyNameCaseUpdated = new TCHAR [dwMaxSubkeyNameLength];
+  m_pCurrentKey->m_Key.InitSubkeyEnumeration(pszSubkeyNameCaseUpdated, dwMaxSubkeyNameLength);
+  while ((nError = m_pCurrentKey->m_Key.GetNextSubkeyName()) == ERROR_SUCCESS)
+    if (_tcsicmp(pszSubkeyNameCaseUpdated, pszSubkeyName) == 0)
+      break;
+
+  if (nError != ERROR_SUCCESS)
+  {
+    delete pszSubkeyNameCaseUpdated;
+    pszSubkeyNameCaseUpdated = NULL;
+  }
+
+SkipCaseUpdate:
+
+  HRESULT hr;
+  ASSERT(hNewKey);
+  if (pszSubkeyNameCaseUpdated)
+  {
+    hr = rKey.Init(hNewKey,GetCurrentPath(),pszSubkeyNameCaseUpdated,DesiredAccess);
+    if (FAILED(hr))
+    {
+      if (hr == (HRESULT)E_OUTOFMEMORY)
+        SetError(_T("Cannot open key : %s%s\nError %d (%s)\n"),
+                 GetCurrentPath(),pszSubkeyName,ERROR_OUTOFMEMORY,GetErrorDescription(ERROR_OUTOFMEMORY));
+      else
+        SetError(_T("Cannot open key : %s%s\nUnknown error\n"), GetCurrentPath(), pszSubkeyName);
+
+      goto Abort;
+    }
+    
+    delete pszSubkeyNameCaseUpdated;
+  }
+  else
+  {
+    hr = rKey.Init(hNewKey,GetCurrentPath(),pszSubkeyName,DesiredAccess);
+    if (FAILED(hr))
+    {
+      if (hr == (HRESULT)E_OUTOFMEMORY)
+        SetError(_T("Cannot open key : %s%s\nError %d (%s)\n"),
+                 GetCurrentPath(),pszSubkeyName,ERROR_OUTOFMEMORY,GetErrorDescription(ERROR_OUTOFMEMORY));
+      else
+        SetError(_T("Cannot open key : %s%s\nUnknown error \n"),
+                 GetCurrentPath(),
+                 pszSubkeyName);
+      
+      goto Abort;
+    }
+  }
+  
+  return TRUE;
+Abort:
+  if (pszSubkeyNameCaseUpdated)
+    delete pszSubkeyNameCaseUpdated;
+
+  if (hNewKey)
+  {
+    LONG nError = RegCloseKey(hNewKey);
+    ASSERT(nError == ERROR_SUCCESS);
+  }
+  
+  return FALSE;
+}
+
+BOOL CRegistryTree::GetKey(const TCHAR *pszRelativePath, REGSAM DesiredAccess, CRegistryKey& rKey)
+{
+  CRegistryTree Tree(*this);
+
+  if (!Tree.ChangeCurrentKey(pszRelativePath))
+  {
+    SetError(Tree.GetLastErrorDescription());
+    return FALSE;
+  }
+
+  if (Tree.m_pCurrentKey->m_Key.IsRoot())
+  {
+    HRESULT hr = rKey.InitRoot(m_pszMachineName);
+    if (FAILED(hr))
+    {
+      if (hr == (HRESULT)E_OUTOFMEMORY)
+        SetError(_T("\nError %d (%s)\n"),
+                 ERROR_OUTOFMEMORY,GetErrorDescription(ERROR_OUTOFMEMORY));
+      else
+        SetInternalError();
+      return FALSE;
+    }
+    
+    return TRUE;
+  }
+
+  // open key with desired access
+  
+  // may be call to DuplicateHandle() is better.
+  // registry key handles returned by the RegConnectRegistry function cannot be used in a call to DuplicateHandle.
+
+  // Get short key name now...
+  const TCHAR *pszKeyName = Tree.m_pCurrentKey->m_Key.GetKeyName();
+  if (pszKeyName == NULL)
+  {
+    SetInternalError();
+    return FALSE;
+  }
+  
+  size_t size = _tcslen(pszKeyName);
+  ASSERT(size);
+  if (!size)
+  {
+    SetInternalError();
+    return FALSE;
+  }
+  
+  const TCHAR *pszShortKeyName_ = pszKeyName + size-1;
+  pszShortKeyName_--; // skip ending backslash
+  size = 0;
+  while (pszShortKeyName_ >= pszKeyName)
+  {
+    if (*pszShortKeyName_ == _T('\\'))
+      break;
+    pszShortKeyName_--;
+    size++;
+  }
+  
+  if (!size || (*pszShortKeyName_ != _T('\\')))
+  {
+    ASSERT(FALSE);
+    SetInternalError();
+    return FALSE;
+  }
+
+  TCHAR *pszShortKeyName = new TCHAR [size+1];
+  if (!pszShortKeyName)
+  {
+    SetError(ERROR_OUTOFMEMORY);
+    return FALSE;
+  }
+
+  memcpy(pszShortKeyName,pszShortKeyName_+1,size*sizeof(TCHAR));
+  pszShortKeyName[size] = 0;
+
+  // change to parent key
+       if (!Tree.InternalChangeCurrentKey(_T(".."),READ_CONTROL))
+  {
+    ASSERT(FALSE);
+    SetInternalError();
+    return FALSE;
+  }
+  
+  // change back to target key
+       if (!Tree.InternalGetSubkey(pszShortKeyName,DesiredAccess,rKey))
+  {
+    SetError(Tree.GetLastErrorDescription());
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
index c0a94e9..83471c7 100644 (file)
@@ -1,3 +1,5 @@
+/* $Id: RegistryTree.h,v 1.2 2001/01/10 01:25:29 narnaoud Exp $ */
+
 // RegistryTree.h: interface for the CRegistryTree class.
 //
 //////////////////////////////////////////////////////////////////////
 
 #include "RegistryKey.h"
 
+// Max size of error description.
 #define ERROR_MSG_BUFFER_SIZE  1024
 
 class CRegistryTree  
 {
 public:
-       BOOL DeleteKey(const TCHAR *pchKeyName, BOOL blnRecursive = FALSE);
-       BOOL NewKey(const TCHAR *pchKeyName, BOOL blnVolatile = FALSE);
-       void SetMachineName(LPCTSTR pszMachineName);
-       int ConnectRegistry(HKEY hKey);
-       REGSAM GetDesiredOpenKeyAccess() const;
-       void SetDesiredOpenKeyAccess(REGSAM samDesired);
-       CRegistryKey * GetCurrentKey();
-       TCHAR * GetLastErrorDescription();
-       BOOL ChangeCurrentKey(const TCHAR *pchRelativePath);
-       BOOL IsCurrentRoot();
-       const TCHAR * GetCurrentPath() const;
-
        // Constructor
+  //
        // Parameters:
        //              nMaxPathSize - size in characters of longest path including terminating NULL char
-       CRegistryTree(unsigned int nMaxPathSize);
-       CRegistryTree(const CRegistryTree& Tree);
+       CRegistryTree();
 
+  // Destructor
        virtual ~CRegistryTree();
+
+  // Call this function after fail of this class method.
+  //
+  // Return value:
+  //   Pointer to buffer containing description of last error.
+  //   return value is valid until next method of this class is called.
+       const TCHAR * GetLastErrorDescription();
+
+  // Call this function to get string representation (path) of current key.
+  //
+  // Return value:
+  //   Pointer to buffer containing current key path. The pointer is valid until next call to this objet method.
+       const TCHAR * GetCurrentPath() const;
+
+  // Call this function to check if current key is the root key.
+  //
+  // Return value:
+  //   FALSE - current key is not the root key.
+  //   TRUE - current key is the root key.
+       BOOL IsCurrentRoot();
+
+  // Call this function to change the current key.
+  //
+  // Parameters:
+  //   pchRelativePath - relative path to target key.
+  //
+  // Return value:
+  //   TRUE - current key changed successfully.
+  //   FALSE - failed to change current key. Call GetLastErrorDescription() to get error description.
+       BOOL ChangeCurrentKey(const TCHAR *pchRelativePath);
+
+  // Call this function to obtain key at relative path and opened with desired access.
+  //
+  // Parametes:
+  //   pchRelativePath - path to key to be opened.
+  //   DesiredAccess - desired access to key.
+  //   rKey - reference to variable that receives pointer to key. Caller must free object with delete operator, when object is not longer needed.
+  //
+  // Return value:
+  //   TRUE - key opened successfully.
+  //   FALSE - failed to open desired key path size. Call GetLastErrorDescription() to get error description.
+  BOOL GetKey(const TCHAR *pchRelativePath, REGSAM DesiredAccess, CRegistryKey& rKey);
+
+  // Call this function to delete key subkeys.
+  //
+  // Parameters:
+  //   pszKeyPattern - pattern to specifying which subkeys to delete.
+  //   pszPath - path to key which subkeys will be deleted.
+  //   blnRecursive - if FALSE and particular subkey has subkeys, it will not be deleted.
+  //
+  // Return value:
+  //   TRUE - key opened successfully.
+  //   FALSE - error. Call GetLastErrorDescription() to get error description.
+       BOOL DeleteSubkeys(const TCHAR *pszKeyPattern, const TCHAR *pszPath, BOOL blnRecursive = FALSE);
+  
+       BOOL NewKey(const TCHAR *pszKeyName, const TCHAR *pszPath, BOOL blnVolatile = FALSE);
+  
+       BOOL SetMachineName(LPCTSTR pszMachineName);
+
+// Internal methods
+private:
+       CRegistryTree(const CRegistryTree& Tree);
+
+  // returns description of error value returned by RegXXXX functions in advapi32.
+  const TCHAR *GetErrorDescription(LONG nError);
+
+  void SetError(LONG nError);
+  void SetError(const TCHAR *pszFormat, ...);
+  void SetErrorCommandNAOnRoot(const TCHAR *pszCommand);
+  void SetInternalError();
+  void AddErrorDescription(const TCHAR *pszFormat, ...);
+
+  BOOL InternalChangeCurrentKey(const TCHAR *pszSubkeyName, REGSAM DesiredAccess);
+  BOOL InternalGetSubkey(const TCHAR *pszSubkeyName, REGSAM DesiredAccess, CRegistryKey& rKey);
+  void GotoRoot();
+  BOOL DeleteSubkeys(CRegistryKey& rKey, const TCHAR *pszKeyPattern, BOOL blnRecursive);
+  
 private:
-       unsigned int m_nMaxPathSize;
-       TCHAR *m_ChangeKeyBuffer;
-       CRegistryKey *m_pRoot, *m_pCurrentKey;
-       TCHAR m_ErrorMsg[ERROR_MSG_BUFFER_SIZE+1];
-       REGSAM m_samDesiredOpenKeyAccess;
-       LPTSTR m_pszMachineName;
+  class CNode
+  {
+  public:
+    CNode *m_pUp;
+    CRegistryKey m_Key;
+  } m_Root;
+  
+       CNode *m_pCurrentKey;              // The current key.
+       TCHAR m_ErrorMsg[ERROR_MSG_BUFFER_SIZE+1];   // Last error description buffer.
+       LPTSTR m_pszMachineName;                     // Pointer to buffer containing machine name with leading backslashes. NULL if local.
 };
 
 #endif // !defined(REGISTRYTREE_H__239A6461_70F2_11D3_9085_204C4F4F5020__INCLUDED_)
index d29789a..d19289d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: SecurityDescriptor.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: SecurityDescriptor.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -322,4 +322,8 @@ void CSecurityDescriptor::GetCurrentACE_AccessMask(DWORD& dwMask)
        }
 }
 
-
+void CSecurityDescriptor::GetCurrentACE_Flags(BYTE& bFlags)
+{
+       ASSERT(m_pCurrentACEHeader != NULL);
+  bFlags = m_pCurrentACEHeader->AceFlags;
+}
index 898ad89..9cec227 100644 (file)
@@ -16,6 +16,7 @@ const TCHAR * GetSidTypeName(SID_NAME_USE Use);
 class CSecurityDescriptor  
 {
 public:
+       void GetCurrentACE_Flags(BYTE& bFlags);
        void GetCurrentACE_AccessMask(DWORD& dwMask);
        PSID GetCurrentACE_SID();
        enum ACEntryType
index 701a7a2..3618196 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandChangeKey.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandChangeKey.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -73,7 +73,9 @@ int CShellCommandChangeKey::Execute(CConsole &rConsole, CArgumentParser& rArgume
 
        if ((!blnHelp)&&(pchPath != NULL)&&(!rArguments.GetNextArgument()))
        {
-               ASSERT(_tcslen(pchPath) <= PROMPT_BUFFER_SIZE);
+    size_t size = _tcslen(pchPath);
+               ASSERT(size <= PROMPT_BUFFER_SIZE);
+    
                if (!m_rTree.ChangeCurrentKey(pchPath))
                {
                        rConsole.Write(m_rTree.GetLastErrorDescription());
index d81b740..cde1b7c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandConnect.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandConnect.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -75,7 +75,12 @@ int CShellCommandConnect::Execute(CConsole &rConsole, CArgumentParser& rArgument
        if (blnHelp)
                rConsole.Write(GetHelpString());
 
-       m_rTree.SetMachineName(pchMachine);
+       if (!m_rTree.SetMachineName(pchMachine))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    rConsole.Write(_T("\n"));
+  }
+  
        return 0;
 }
 
index 4c1b50e..62496a4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandDACL.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandDACL.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -64,18 +64,18 @@ int CShellCommandDACL::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
        rArguments.ResetArgumentIteration();
 
-       const TCHAR *pchKey = NULL;
+       const TCHAR *pszKey = NULL;
        BOOL blnDo = TRUE;
        BOOL blnBadParameter = FALSE;
        BOOL blnHelp = FALSE;
        const TCHAR *pchParameter;
        const TCHAR *pchCommandItself = rArguments.GetNextArgument();
-       DWORD dwError;
+       LONG nError;
 
        if ((_tcsnicmp(pchCommandItself,DACL_CMD _T(".."),DACL_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
                (_tcsnicmp(pchCommandItself,DACL_CMD _T("\\"),DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
        {
-               pchKey = pchCommandItself + DACL_CMD_LENGTH;
+               pszKey = pchCommandItself + DACL_CMD_LENGTH;
        }
        else if (_tcsnicmp(pchCommandItself,DACL_CMD _T("/"),DACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
        {
@@ -91,11 +91,11 @@ CheckDACLArgument:
                        ||(_tcsicmp(pchParameter,_T("-?")) == 0))
                {
                        blnHelp = TRUE;
-                       blnDo = pchKey != NULL;
+                       blnDo = pszKey != NULL;
                }
-               else if (!pchKey)
+               else if (!pszKey)
                {
-                       pchKey = pchParameter;
+                       pszKey = pchParameter;
                        blnDo = TRUE;
                }
                else
@@ -110,28 +110,13 @@ CheckDACLArgument:
                }
        }
 
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
-       if (pchKey)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)||(!pTree->ChangeCurrentKey(pchKey)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchKey);
-                       rConsole.Write(_T("\n"));
-                       //blnHelp = TRUE;
-                       blnDo = FALSE;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
+       CRegistryKey Key;
+  
+  if (!m_rTree.GetKey(pszKey?pszKey:_T("."),KEY_QUERY_VALUE|READ_CONTROL,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    blnDo = FALSE;
+  }
 
        if (blnHelp)
        {
@@ -140,221 +125,245 @@ CheckDACLArgument:
 
        if (blnDo&&blnHelp) rConsole.Write(_T("\n"));
 
-       if (blnDo)
-       {
-               if (pKey == NULL)
-               {       // root key
-                       rConsole.Write(DACL_CMD COMMAND_NA_ON_ROOT);
-               }
-               else
-               {
-                       DWORD dwSecurityDescriptorLength;
-                       rConsole.Write(_T("Key : "));
-                       rConsole.Write(_T("\\"));
-                       rConsole.Write(pTree?pTree->GetCurrentPath():m_rTree.GetCurrentPath());
-                       rConsole.Write(_T("\n"));
-                       PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
-                       TCHAR *pchName = NULL, *pchDomainName = NULL;
-                       try
-                       {
-                               dwError = pKey->GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
-                               if (dwError != ERROR_SUCCESS) throw dwError;
+       if (!blnDo)
+    return 0;
+  
+  if (Key.IsRoot())
+       {       // root key
+    rConsole.Write(DACL_CMD COMMAND_NA_ON_ROOT);
+    return 0;
+  }
+  
+  DWORD dwSecurityDescriptorLength;
+  rConsole.Write(_T("Key : "));
+  rConsole.Write(_T("\\"));
+  rConsole.Write(Key.GetKeyName());
+  rConsole.Write(_T("\n"));
+  PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
+  TCHAR *pchName = NULL, *pchDomainName = NULL;
+  try
+  {
+    nError = Key.GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
+    if (nError != ERROR_SUCCESS)
+      throw nError;
                                
-                               pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
-                               DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
-                               dwError = pKey->GetSecurityDescriptor((SECURITY_INFORMATION)DACL_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
-                               if (dwError != ERROR_SUCCESS) throw dwError;
-                               CSecurityDescriptor sd;
-                               sd.AssociateDescriptor(pSecurityDescriptor);
+    pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
+    DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
+    nError = Key.GetSecurityDescriptor((SECURITY_INFORMATION)DACL_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
+    if (nError != ERROR_SUCCESS)
+      throw nError;
+    CSecurityDescriptor sd;
+    sd.AssociateDescriptor(pSecurityDescriptor);
                                
-                               sd.BeginDACLInteration();
-                               ASSERT(sd.DescriptorContainsDACL());
-                               if (sd.HasNULLDACL())
-                               {
-                                       rConsole.Write(_T("Key has not DACL.\n(This allows all access)\n"));
-                               }
-                               else
-                               {
-                                       if (!sd.HasValidDACL())
-                                       {
-                                               rConsole.Write(_T("Invalid DACL.\n"));
-                                       }
-                                       else
-                                       {
-                                               DWORD nACECount = sd.GetDACLEntriesCount();
-                                               rConsole.Write(_T("DACL has "));
-                                               TCHAR Buffer[256];
-                                               rConsole.Write(_itot(nACECount,Buffer,10));
-                                               rConsole.Write(_T(" ACEs.\n"));
-                                               if (nACECount == 0)
-                                               {
-                                                       rConsole.Write(_T("(This denies all access)\n"));
-                                               }
-                                               else
-                                               {
-                                                       for (DWORD i = 0 ; i < nACECount ; i++)
-                                                       {
-                                                               rConsole.Write(_T("\n"));
-                                                               rConsole.Write(_T("\tACE Index: "));
-                                                               rConsole.Write(_itot(i,Buffer,10));
-                                                               rConsole.Write(_T("\n"));
-                                                               rConsole.Write(_T("\tACE Type: "));
-                                                               switch (sd.GetDACLEntry(i))
-                                                               {
-                                                               case CSecurityDescriptor::AccessAlowed:
-                                                                       rConsole.Write(_T("Access-allowed\n"));
-                                                                       break;
-                                                               case CSecurityDescriptor::AccessDenied:
-                                                                       rConsole.Write(_T("Access-denied\n"));
-                                                                       break;
-                                                               default:
-                                                                       rConsole.Write(_T("Unknown.\nCannot continue dumping of the ACE list.\n"));
-                                                                       goto AbortDumpDACL;
-                                                               }
-                                                               PSID pSID = sd.GetCurrentACE_SID();
-                                                               if ((pSID == NULL)||(!IsValidSid(pSID)))
-                                                               {
-                                                                       rConsole.Write(_T("\tInvalid SID.\n"));
-                                                               }
-                                                               else
-                                                               {
-                                                                       DWORD dwSIDStringSize = 0;
-                                                                       BOOL blnRet = GetTextualSid(pSID,NULL,&dwSIDStringSize);
-                                                                       ASSERT(!blnRet);
-                                                                       ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
-                                                                       TCHAR *pchSID = new TCHAR[dwSIDStringSize];
-                                                                       if(!GetTextualSid(pSID,pchSID,&dwSIDStringSize))
-                                                                       {
-                                                                               dwError = GetLastError();
-                                                                               ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
-                                                                               rConsole.Write(_T("Error "));
-                                                                               TCHAR Buffer[256];
-                                                                               rConsole.Write(_itot(dwError,Buffer,10));
-                                                                               rConsole.Write(_T("\nGetting string representation of SID\n"));
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               rConsole.Write(_T("\tSID: "));
-                                                                               rConsole.Write(pchSID);
-                                                                               rConsole.Write(_T("\n"));
-                                                                       }
-                                                                       delete pchSID;
-                                                                       DWORD dwNameBufferLength, dwDomainNameBufferLength;
-                                                                       dwNameBufferLength = 1024;
-                                                                       dwDomainNameBufferLength = 1024;
-                                                                       pchName = new TCHAR [dwNameBufferLength];
-                                                                       pchDomainName = new TCHAR [dwDomainNameBufferLength];
-                                                                       DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
-                                                                       SID_NAME_USE Use;
-                                                                       if (!LookupAccountSid(NULL,pSID,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
-                                                                       {
-                                                                               rConsole.Write(_T("Error "));
-                                                                               TCHAR Buffer[256];
-                                                                               rConsole.Write(_itot(GetLastError(),Buffer,10));
-                                                                               rConsole.Write(_T("\n"));
-                                                                       }
-                                                                       else
-                                                                       {
-                                                                               rConsole.Write(_T("\tTrustee Domain: "));
-                                                                               rConsole.Write(pchDomainName);
-                                                                               rConsole.Write(_T("\n"));
-                                                                               rConsole.Write(_T("\tTrustee Name: "));
-                                                                               rConsole.Write(pchName);
-                                                                               rConsole.Write(_T("\n\tSID type: "));
-                                                                               rConsole.Write(GetSidTypeName(Use));
-                                                                               rConsole.Write(_T("\n"));
-                                                                       }
-                                                                       delete [] pchName;
-                                                                       pchName = NULL;
-                                                                       delete [] pchDomainName;
-                                                                       pchDomainName = NULL;
-                                                               }
-                                                               DWORD dwAccessMask;
-                                                               sd.GetCurrentACE_AccessMask(dwAccessMask);
-                                                               wsprintf(Buffer,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask);
-                                                               rConsole.Write(Buffer);
-                                                               if (dwAccessMask & GENERIC_READ)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tGENERIC_READ\n"));
-                                                               }
-                                                               if (dwAccessMask & GENERIC_WRITE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tGENERIC_WRITE\n"));
-                                                               }
-                                                               if (dwAccessMask & GENERIC_EXECUTE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tGENERIC_EXECUTE\n"));
-                                                               }
-                                                               if (dwAccessMask & GENERIC_ALL)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tGENERIC_ALL\n"));
-                                                               }
-                                                               if (dwAccessMask & SYNCHRONIZE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tSYNCHRONIZE\n"));
-                                                               }
-                                                               if (dwAccessMask & WRITE_OWNER)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tWRITE_OWNER\n"));
-                                                               }
-                                                               if (dwAccessMask & WRITE_DAC)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tWRITE_DAC\n"));
-                                                               }
-                                                               if (dwAccessMask & READ_CONTROL)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tREAD_CONTROL\n"));
-                                                               }
-                                                               if (dwAccessMask & DELETE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tDELETE\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_CREATE_LINK)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_CREATE_LINK\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_NOTIFY)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_NOTIFY\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_ENUMERATE_SUB_KEYS)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_CREATE_SUB_KEY)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_CREATE_SUB_KEY\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_SET_VALUE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_SET_VALUE\n"));
-                                                               }
-                                                               if (dwAccessMask & KEY_QUERY_VALUE)
-                                                               {
-                                                                       rConsole.Write(_T("\t\tKEY_QUERY_VALUE\n"));
-                                                               }
-                                                       } // for
-                                               } // else (nACECount == 0)
-                                       } // else (!sd.HasValidDACL())
-                               } // else (sd.HasNULLDACL())
-AbortDumpDACL:
-                               delete [] pSecurityDescriptor;
-                       }  // try
-                       catch (DWORD dwError)
-                       {
-                               rConsole.Write(_T("Error "));
-                               TCHAR Buffer[256];
-                               rConsole.Write(_itot(dwError,Buffer,10));
-                               rConsole.Write(_T("\n"));
-                               if (pchName) delete [] pchName;
-                               if (pchDomainName) delete [] pchDomainName;
-                               if (pSecurityDescriptor) delete [] pSecurityDescriptor;
-                       }
-               } // else (pKey == NULL)
-       } // if (blnDo)
+    sd.BeginDACLInteration();
+    ASSERT(sd.DescriptorContainsDACL());
+    if (sd.HasNULLDACL())
+    {
+      rConsole.Write(_T("Key has not DACL.\n(This allows all access)\n"));
+    }
+    else
+    {
+      if (!sd.HasValidDACL())
+      {
+        rConsole.Write(_T("Invalid DACL.\n"));
+      }
+      else
+      {
+        DWORD nACECount = sd.GetDACLEntriesCount();
+        rConsole.Write(_T("DACL has "));
+        TCHAR Buffer[256];
+        rConsole.Write(_itot(nACECount,Buffer,10));
+        rConsole.Write(_T(" ACEs.\n"));
+        if (nACECount == 0)
+        {
+          rConsole.Write(_T("(This denies all access)\n"));
+        }
+        else
+        {
+          for (DWORD i = 0 ; i < nACECount ; i++)
+          {
+            rConsole.Write(_T("\n"));
+            rConsole.Write(_T("\tACE Index: "));
+            rConsole.Write(_itot(i,Buffer,10));
+            rConsole.Write(_T("\n"));
+            rConsole.Write(_T("\tACE Type: "));
+            switch (sd.GetDACLEntry(i))
+            {
+            case CSecurityDescriptor::AccessAlowed:
+              rConsole.Write(_T("Access-allowed\n"));
+              break;
+            case CSecurityDescriptor::AccessDenied:
+              rConsole.Write(_T("Access-denied\n"));
+              break;
+            default:
+              rConsole.Write(_T("Unknown.\nCannot continue dumping of the ACE list.\n"));
+              goto AbortDumpDACL;
+            }
+            PSID pSID = sd.GetCurrentACE_SID();
+            if ((pSID == NULL)||(!IsValidSid(pSID)))
+            {
+              rConsole.Write(_T("\tInvalid SID.\n"));
+            }
+            else
+            {
+              DWORD dwSIDStringSize = 0;
+              BOOL blnRet = GetTextualSid(pSID,NULL,&dwSIDStringSize);
+              ASSERT(!blnRet);
+              ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+              TCHAR *pchSID = new TCHAR[dwSIDStringSize];
+              if(!GetTextualSid(pSID,pchSID,&dwSIDStringSize))
+              {
+                DWORD dwError = GetLastError();
+                ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
+                rConsole.Write(_T("Error "));
+                TCHAR Buffer[256];
+                rConsole.Write(_itot(dwError,Buffer,10));
+                rConsole.Write(_T("\nGetting string representation of SID\n"));
+              }
+              else
+              {
+                rConsole.Write(_T("\tSID: "));
+                rConsole.Write(pchSID);
+                rConsole.Write(_T("\n"));
+              }
+              delete pchSID;
+              DWORD dwNameBufferLength, dwDomainNameBufferLength;
+              dwNameBufferLength = 1024;
+              dwDomainNameBufferLength = 1024;
+              pchName = new TCHAR [dwNameBufferLength];
+              pchDomainName = new TCHAR [dwDomainNameBufferLength];
+              DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
+              SID_NAME_USE Use;
+              if (!LookupAccountSid(NULL,pSID,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
+              {
+                rConsole.Write(_T("Error "));
+                TCHAR Buffer[256];
+                rConsole.Write(_itot(GetLastError(),Buffer,10));
+                rConsole.Write(_T("\n"));
+              }
+              else
+              {
+                rConsole.Write(_T("\tTrustee Domain: "));
+                rConsole.Write(pchDomainName);
+                rConsole.Write(_T("\n"));
+                rConsole.Write(_T("\tTrustee Name: "));
+                rConsole.Write(pchName);
+                rConsole.Write(_T("\n\tSID type: "));
+                rConsole.Write(GetSidTypeName(Use));
+                rConsole.Write(_T("\n"));
+              }
+              delete [] pchName;
+              pchName = NULL;
+              delete [] pchDomainName;
+              pchDomainName = NULL;
+            }
 
-       if (pTree)
-               delete pTree;
+            BYTE bFlags;
+            sd.GetCurrentACE_Flags(bFlags);
+            wsprintf(Buffer,_T("\tFlags: 0x%02lX\n"),bFlags);
+            rConsole.Write(Buffer);
+            if (bFlags & CONTAINER_INHERIT_ACE)
+            {
+              rConsole.Write(_T("\t\tCONTAINER_INHERIT_ACE\n"));
+            }
+            if (bFlags & INHERIT_ONLY_ACE)
+            {
+              rConsole.Write(_T("\t\tINHERIT_ONLY_ACE\n"));
+            }
+            if (bFlags & INHERITED_ACE)
+            {
+              rConsole.Write(_T("\t\tINHERITED_ACE\n"));
+            }
+            if (bFlags & NO_PROPAGATE_INHERIT_ACE)
+            {
+              rConsole.Write(_T("\t\tNO_PROPAGATE_INHERIT_ACE\n"));
+            }
+            if (bFlags & OBJECT_INHERIT_ACE)
+            {
+              rConsole.Write(_T("\t\tOBJECT_INHERIT_ACE\n"));
+            }
+
+            DWORD dwAccessMask;
+            sd.GetCurrentACE_AccessMask(dwAccessMask);
+            wsprintf(Buffer,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask);
+            rConsole.Write(Buffer);
+            if (dwAccessMask & GENERIC_READ)
+            {
+              rConsole.Write(_T("\t\tGENERIC_READ\n"));
+            }
+            if (dwAccessMask & GENERIC_WRITE)
+            {
+              rConsole.Write(_T("\t\tGENERIC_WRITE\n"));
+            }
+            if (dwAccessMask & GENERIC_EXECUTE)
+            {
+              rConsole.Write(_T("\t\tGENERIC_EXECUTE\n"));
+            }
+            if (dwAccessMask & GENERIC_ALL)
+            {
+              rConsole.Write(_T("\t\tGENERIC_ALL\n"));
+            }
+            if (dwAccessMask & SYNCHRONIZE)
+            {
+              rConsole.Write(_T("\t\tSYNCHRONIZE\n"));
+            }
+            if (dwAccessMask & WRITE_OWNER)
+            {
+              rConsole.Write(_T("\t\tWRITE_OWNER\n"));
+            }
+            if (dwAccessMask & WRITE_DAC)
+            {
+              rConsole.Write(_T("\t\tWRITE_DAC\n"));
+            }
+            if (dwAccessMask & READ_CONTROL)
+            {
+              rConsole.Write(_T("\t\tREAD_CONTROL\n"));
+            }
+            if (dwAccessMask & DELETE)
+            {
+              rConsole.Write(_T("\t\tDELETE\n"));
+            }
+            if (dwAccessMask & KEY_CREATE_LINK)
+            {
+              rConsole.Write(_T("\t\tKEY_CREATE_LINK\n"));
+            }
+            if (dwAccessMask & KEY_NOTIFY)
+            {
+              rConsole.Write(_T("\t\tKEY_NOTIFY\n"));
+            }
+            if (dwAccessMask & KEY_ENUMERATE_SUB_KEYS)
+            {
+              rConsole.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n"));
+            }
+            if (dwAccessMask & KEY_CREATE_SUB_KEY)
+            {
+              rConsole.Write(_T("\t\tKEY_CREATE_SUB_KEY\n"));
+            }
+            if (dwAccessMask & KEY_SET_VALUE)
+            {
+              rConsole.Write(_T("\t\tKEY_SET_VALUE\n"));
+            }
+            if (dwAccessMask & KEY_QUERY_VALUE)
+            {
+              rConsole.Write(_T("\t\tKEY_QUERY_VALUE\n"));
+            }
+          } // for
+        } // else (nACECount == 0)
+      } // else (!sd.HasValidDACL())
+    } // else (sd.HasNULLDACL())
+AbortDumpDACL:
+    delete [] pSecurityDescriptor;
+  }  // try
+  catch (DWORD dwError)
+  {
+    rConsole.Write(_T("Error "));
+    TCHAR Buffer[256];
+    rConsole.Write(_itot(dwError,Buffer,10));
+    rConsole.Write(_T("\n"));
+    if (pchName) delete [] pchName;
+    if (pchDomainName) delete [] pchDomainName;
+    if (pSecurityDescriptor) delete [] pSecurityDescriptor;
+  }
 
        return 0;
 }
index 71756a1..a580489 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandDeleteKey.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandDeleteKey.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -50,7 +50,7 @@ BOOL CShellCommandDeleteKey::Match(const TCHAR *pchCommand)
 
 int CShellCommandDeleteKey::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
-       const TCHAR *pchKey = NULL, *pchArg;
+       TCHAR *pchKey = NULL, *pchArg;
 
        BOOL blnHelp = FALSE;
        BOOL blnExitAfterHelp = FALSE;
@@ -99,20 +99,72 @@ int CShellCommandDeleteKey::Execute(CConsole &rConsole, CArgumentParser& rArgume
                rConsole.Write(_T("\n"));
        }
 
-       if (!m_rTree.DeleteKey(pchKey,blnRecursive))
+  // search for last key name token
+  TCHAR *pch = pchKey;
+  while(*pch)
+    pch++;
+
+  if (pch > pchKey)
+    pch--;
+
+  while(*pch == _T('\\'))
+    *pch = 0;
+
+  while((pch > pchKey)&&(*pch != _T('\\')))
+    pch--;
+
+  ASSERT(pch >= pchKey);
+
+  const TCHAR *pszPath;
+  TCHAR *pszPattern = pch+1;
+  if (pch == pchKey)
+  {
+    pszPath = _T(".");
+  }
+  else
+  {
+    if (pch-1 == pchKey)
+    {
+      rConsole.Write(DK_CMD COMMAND_NA_ON_ROOT);
+      return 0;
+    }
+    else
+    {
+      *pch = 0;
+      pszPath = pchKey;
+    }
+  }
+  
+  {
+    size_t s = _tcslen(pszPattern);
+    if (s && (pszPattern[0] == _T('\"'))&&(pszPattern[s-1] == _T('\"')))
+    {
+      pszPattern[s-1] = 0;
+      pszPattern++;
+    }
+  }
+  
+       if (!m_rTree.DeleteSubkeys(pszPattern,pszPath,blnRecursive))
        {
-               rConsole.Write(_T("Cannot delete key.\n"));
+               rConsole.Write(_T("Cannot delete key(s).\n"));
                rConsole.Write(m_rTree.GetLastErrorDescription());
        }
+  else
+  {
+    InvalidateCompletion();
+  }
+  
        return 0;
 }
 
 const TCHAR * CShellCommandDeleteKey::GetHelpString()
 {
        return DK_CMD_SHORT_DESC
-                       _T("Syntax: ") DK_CMD _T(" [/s] [/?] Key_Name\n\n")
-                       _T("    /? - This help.\n\n")
-                       _T("    /s - Delete key and all subkeys.\n");
+                       _T("Syntax: ") DK_CMD _T(" [/s] [/?] [PATH]KEY_NAME\n\n")
+      _T("    PATH     - optional path to key which subkey(s) will be deleted. Default is current key.")
+      _T("    KEY_NAME - name of key to be deleted. Wildcards can be used.")
+                       _T("    /?       - This help.\n\n")
+                       _T("    /s       - Delete key and all subkeys.\n");
 }
 
 const TCHAR * CShellCommandDeleteKey::GetHelpShortDescriptionString()
index a03a1bd..fdc28ee 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandDeleteValue.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandDeleteValue.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -44,57 +44,56 @@ CShellCommandDeleteValue::~CShellCommandDeleteValue()
 {
 }
 
-BOOL CShellCommandDeleteValue::Match(const TCHAR *pchCommand)
+BOOL CShellCommandDeleteValue::Match(const TCHAR *pszCommand)
 {
-       return _tcsicmp(pchCommand,DV_CMD) == 0;
+       return _tcsicmp(pszCommand,DV_CMD) == 0;
 }
 
 int CShellCommandDeleteValue::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
        rArguments.ResetArgumentIteration();
-       TCHAR *pchCommandItself = rArguments.GetNextArgument();
+       TCHAR *pszCommandItself = rArguments.GetNextArgument();
 
-       TCHAR *pchParameter;
-       TCHAR *pchValueFull = NULL;
+       TCHAR *pszParameter;
+       TCHAR *pszValueFull = NULL;
        BOOL blnHelp = FALSE;
 //     DWORD dwError;
 
-       if ((_tcsnicmp(pchCommandItself,DV_CMD _T(".."),DV_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
-               (_tcsnicmp(pchCommandItself,DV_CMD _T("\\"),DV_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
+       if ((_tcsnicmp(pszCommandItself,DV_CMD _T(".."),DV_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
+               (_tcsnicmp(pszCommandItself,DV_CMD _T("\\"),DV_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
        {
-               pchValueFull = pchCommandItself + DV_CMD_LENGTH;
+               pszValueFull = pszCommandItself + DV_CMD_LENGTH;
        }
-       else if (_tcsnicmp(pchCommandItself,DV_CMD _T("/"),DV_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+       else if (_tcsnicmp(pszCommandItself,DV_CMD _T("/"),DV_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
        {
-               pchParameter = pchCommandItself + DV_CMD_LENGTH;
+               pszParameter = pszCommandItself + DV_CMD_LENGTH;
                goto CheckValueArgument;
        }
 
-       while((pchParameter = rArguments.GetNextArgument()) != NULL)
+       while((pszParameter = rArguments.GetNextArgument()) != NULL)
        {
 CheckValueArgument:
-               if ((_tcsicmp(pchParameter,_T("/?")) == 0)
-                       ||(_tcsicmp(pchParameter,_T("-?")) == 0))
+               if ((_tcsicmp(pszParameter,_T("/?")) == 0)
+                       ||(_tcsicmp(pszParameter,_T("-?")) == 0))
                {
                        blnHelp = TRUE;
                        break;
                }
-               else if (!pchValueFull)
+               else if (!pszValueFull)
                {
-                       pchValueFull = pchParameter;
+                       pszValueFull = pszParameter;
                }
                else
                {
                        rConsole.Write(_T("Bad parameter: "));
-                       rConsole.Write(pchParameter);
+                       rConsole.Write(pszParameter);
                        rConsole.Write(_T("\n"));
                }
        }
        
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
-       TCHAR *pchValueName;
-       TCHAR *pchPath;
+       CRegistryKey Key;
+       TCHAR *pszValueName;
+       const TCHAR *pszPath;
        
        if (blnHelp)
        {
@@ -102,19 +101,19 @@ CheckValueArgument:
                return 0;
        }
 
-       if (pchValueFull)
+       if (pszValueFull)
        {
-               if (_tcscmp(pchValueFull,_T("\\")) == 0)
+               if (_tcscmp(pszValueFull,_T("\\")) == 0)
                        goto CommandNAonRoot;
 
-               TCHAR *pchSep = _tcsrchr(pchValueFull,_T('\\'));
-               pchValueName = pchSep?(pchSep+1):(pchValueFull);
-               pchPath = pchSep?pchValueFull:NULL;
+               TCHAR *pchSep = _tcsrchr(pszValueFull,_T('\\'));
+               pszValueName = pchSep?(pchSep+1):(pszValueFull);
+               pszPath = pchSep?pszValueFull:_T(".");
                                
-               //if (_tcsrchr(pchValueName,_T('.')))
+               //if (_tcsrchr(pszValueName,_T('.')))
                //{
-               //      pchValueName = _T("");
-               //      pchPath = pchValueFull;
+               //      pszValueName = _T("");
+               //      pszPath = pszValueFull;
                //}
                //else
                if (pchSep)
@@ -122,35 +121,38 @@ CheckValueArgument:
        }
        else
        {
-               pchValueName = _T("");
-               pchPath = NULL;
+               pszValueName = _T("");
+               pszPath = _T(".");
        }
-               
-       if (pchPath)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)
-                       ||(!pTree->ChangeCurrentKey(pchPath)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchPath);
-                       rConsole.Write(_T("\n"));
-                       goto SkipCommand;
-               }
-               else
+  
+  {
+    size_t s = _tcslen(pszValueName);
+    if (s && (pszValueName[0] == _T('\"'))&&(pszValueName[s-1] == _T('\"')))
+    {
+      pszValueName[s-1] = 0;
+      pszValueName++;
+    }
+  }
+
+  if (!m_rTree.GetKey(pszPath,KEY_SET_VALUE,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    goto SkipCommand;
+  }
+
+       if (!Key.IsRoot())
+       {       // not root key ???
+               LONG nError = Key.DeleteValue(pszValueName);
+               if (nError != ERROR_SUCCESS)
                {
-                       pKey = pTree->GetCurrentKey();
+                       char Buffer[254];
+                       _stprintf(Buffer,_T("Cannot delete value. Error is %u\n"),(unsigned int)nError);
+                       rConsole.Write(Buffer);
                }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
-       
-       if (pKey)
-       {       // not root key ???
-               if (pKey->DeleteValue(pchValueName) != ERROR_SUCCESS)
-                       rConsole.Write(_T("Cannot set value\n"));
+    else
+    {
+      InvalidateCompletion();
+    }
        } // if (pKey)
        else
        {
@@ -159,8 +161,8 @@ CommandNAonRoot:
        }
 
 SkipCommand:
-       if (pTree)
-               delete pTree;
+  //   if (pTree)
+  //           delete pTree;
        return 0;
 }
 
index f74eab5..fa405da 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandDir.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandDir.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -73,35 +73,35 @@ int CShellCommandDir::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
        rArguments.ResetArgumentIteration();
 
-       const TCHAR *pchKey = NULL;
        BOOL blnDo = TRUE,blnBadParameter, blnHelp = FALSE;
-       const TCHAR *pchParameter;
-       const TCHAR *pchCommandItself = rArguments.GetNextArgument();
+       const TCHAR *pszParameter;
+       const TCHAR *pszCommandItself = rArguments.GetNextArgument();
+  const TCHAR *pszKey = NULL;
 
-       if ((_tcsnicmp(pchCommandItself,DIR_CMD _T(".."),DIR_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
-               (_tcsnicmp(pchCommandItself,DIR_CMD _T("\\"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
+       if ((_tcsnicmp(pszCommandItself,DIR_CMD _T(".."),DIR_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
+               (_tcsnicmp(pszCommandItself,DIR_CMD _T("\\"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
        {
-               pchKey = pchCommandItself + DIR_CMD_LENGTH;
+               pszKey = pszCommandItself + DIR_CMD_LENGTH;
        }
-       else if (_tcsnicmp(pchCommandItself,DIR_CMD _T("/"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+       else if (_tcsnicmp(pszCommandItself,DIR_CMD _T("/"),DIR_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
        {
-               pchParameter = pchCommandItself + DIR_CMD_LENGTH;
+               pszParameter = pszCommandItself + DIR_CMD_LENGTH;
                goto CheckDirArgument;
        }
 
-       while((pchParameter = rArguments.GetNextArgument()) != NULL)
+       while((pszParameter = rArguments.GetNextArgument()) != NULL)
        {
 CheckDirArgument:
                blnBadParameter = FALSE;
-               if ((_tcsicmp(pchParameter,_T("/?")) == 0)
-                       ||(_tcsicmp(pchParameter,_T("-?")) == 0))
+               if ((_tcsicmp(pszParameter,_T("/?")) == 0)
+                       ||(_tcsicmp(pszParameter,_T("-?")) == 0))
                {
                        blnHelp = TRUE;
-                       blnDo = pchKey != NULL;
+                       blnDo = pszKey != NULL;
                }
-               else if (!pchKey)
+               else if (!pszKey)
                {
-                       pchKey = pchParameter;
+                       pszKey = pszParameter;
                        blnDo = TRUE;
                }
                else
@@ -111,133 +111,124 @@ CheckDirArgument:
                if (blnBadParameter)
                {
                        rConsole.Write(_T("Bad parameter: "));
-                       rConsole.Write(pchParameter);
+                       rConsole.Write(pszParameter);
                        rConsole.Write(_T("\n"));
                }
        }
        
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
-       if (pchKey)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)||
-                       (!pTree->ChangeCurrentKey(pchKey)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchKey);
-                       rConsole.Write(_T("\n"));
-                       //blnHelp = TRUE;
-                       blnDo = FALSE;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
-       
+       CRegistryKey Key;
+
+  if (!m_rTree.GetKey(pszKey?pszKey:_T("."),KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,Key))
+  {
+    const TCHAR *pszErrorMsg = m_rTree.GetLastErrorDescription();
+    rConsole.Write(pszErrorMsg);
+    blnDo = FALSE;
+  }
+
        if (blnHelp)
        {
                rConsole.Write(GetHelpString());
        }
 
-       DWORD dwError;
+       LONG nError;
        
-       if (blnDo)
-       {
-               rConsole.Write(_T("\n Key is "));
-//             rConsole.Write(_T("\\"));
-               rConsole.Write(pTree?pTree->GetCurrentPath():m_rTree.GetCurrentPath());
-               if (pKey)
-               {
-                       rConsole.Write(_T("\n Last modify time is "));
-                       rConsole.Write(pKey->GetLastWriteTime());
-               }
-               rConsole.Write(_T("\n\n"));
-               unsigned __int64 nTotalItems = 0;
-               if (!pKey)
-               {
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_CLASSES_ROOT\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_CURRENT_USER\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_LOCAL_MACHINE\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_USERS\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_PERFORMANCE_DATA\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_CURRENT_CONFIG\\\n"));
-                       rConsole.Write(_T("\t(KEY)\t\t\t\tHKEY_DYN_DATA\\\n"));
-                       nTotalItems = 7;
-               }
-               else
-               {
-                       dwError = ERROR_SUCCESS;
-                       try
-                       {
-                               if (!pKey->IsPredefined())
-                               {
-                                       dwError = pKey->Open(KEY_QUERY_VALUE|KEY_READ);
-                                       if (dwError != ERROR_SUCCESS) throw dwError;
-                               }
-                               
-                               ASSERT(nTotalItems == 0);
-                               rConsole.Write(_T("\t(KEY)\t\t\t\t..\\\n"));    // parent key abstraction
-                               nTotalItems = 1;
-                               
-                               pKey->InitSubKeyEnumeration();
-                               TCHAR *pchSubKeyName;
-                               while ((pchSubKeyName = pKey->GetSubKeyName(dwError)) != NULL)
-                               {
-                                       rConsole.Write(_T("\t(KEY)\t\t\t\t"));
-                                       rConsole.Write(pchSubKeyName);
-                                       rConsole.Write(_T("\\\n"));
-                                       nTotalItems++;
-                               }
-                               if ((dwError != ERROR_SUCCESS)&&(dwError != ERROR_NO_MORE_ITEMS)) throw dwError;
+       if (!blnDo)
+    return 0;
+  
+  rConsole.Write(_T("\n Key is "));
+  rConsole.Write(Key.GetKeyName());
+
+  if (!Key.IsRoot())
+  {
+    rConsole.Write(_T("\n Last modify time is "));
+    rConsole.Write(Key.GetLastWriteTime());
+  }
+  
+  rConsole.Write(_T("\n\n"));
+  unsigned __int64 nTotalItems = 0;
+  
+  try
+  {
+    ASSERT(nTotalItems == 0);
+    rConsole.Write(_T("\t(KEY)\t\t\t\t..\\\n"));       // parent key abstraction
+    nTotalItems = 1;
                                
-                               pKey->InitValueEnumeration();
-                               TCHAR *pchValueName;
-                               DWORD dwValueNameLength, dwMaxValueNameLength;
-                               dwError = pKey->GetMaxValueNameLength(dwMaxValueNameLength);
-                               if (dwError != ERROR_SUCCESS) throw dwError;
-                               dwMaxValueNameLength++;
-                               pchValueName = new TCHAR [dwMaxValueNameLength];
-                               DWORD Type;
-                               for(;;)
-                               {
-                                       dwValueNameLength = dwMaxValueNameLength;
-                                       //dwValueSize = dwMaxValueSize;
-                                       dwError = pKey->GetNextValue(pchValueName,dwValueNameLength,&Type,
-                                               NULL,//pDataBuffer
-                                               NULL//&dwValueSize
-                                               );
-                                       if (dwError == ERROR_NO_MORE_ITEMS) break;
-                                       if (dwError != ERROR_SUCCESS) throw dwError;
-                                       rConsole.Write(_T("\t"));
-                                       rConsole.Write(CRegistryKey::GetValueTypeName(Type));
-                                       rConsole.Write(_T("\t"));
-                                       rConsole.Write((dwValueNameLength == 0)?_T("(Default)"):pchValueName);
-                                       rConsole.Write(_T("\n"));
-                                       nTotalItems++;
-                               }       // for
-                               delete [] pchValueName;
-                       }       // try
-                       catch (DWORD dwError)
-                       {
-                               rConsole.Write(_T("Error "));
-                               TCHAR Buffer[256];
-                               rConsole.Write(_itot(dwError,Buffer,10));
-                               rConsole.Write(_T("\n"));
-                       }
-               }       // else (Tree.IsCurrentRoot())
+    DWORD dwMaxSubkeyNameLength;
+    nError = Key.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
+    if (nError != ERROR_SUCCESS)
+      throw nError;
+
+    TCHAR *pszSubkeyNameBuffer = new TCHAR[dwMaxSubkeyNameLength];
+    if (!pszSubkeyNameBuffer)
+      throw ERROR_OUTOFMEMORY;
+    
+    Key.InitSubkeyEnumeration(pszSubkeyNameBuffer,dwMaxSubkeyNameLength);
+    while ((nError = Key.GetNextSubkeyName()) == ERROR_SUCCESS)
+    {
+      rConsole.Write(_T("\t(KEY)\t\t\t\t"));
+      rConsole.Write(pszSubkeyNameBuffer);
+      rConsole.Write(_T("\\\n"));
+      nTotalItems++;
+    }
+
+    delete pszSubkeyNameBuffer;
+    
+    if (nError != ERROR_NO_MORE_ITEMS)
+      throw nError;
+
+    DWORD dwMaxValueNameBufferSize;
+    nError = Key.GetMaxValueNameLength(dwMaxValueNameBufferSize);
+    if (nError != ERROR_SUCCESS)
+      throw nError;
+    
+    TCHAR *pchValueNameBuffer = new TCHAR[dwMaxValueNameBufferSize];
+    if (!pchValueNameBuffer)
+      throw ERROR_OUTOFMEMORY;
+    
+
+    DWORD Type;
+    Key.InitValueEnumeration(pchValueNameBuffer,
+                             dwMaxValueNameBufferSize,
+                             NULL,
+                             0,
+                             &Type);
+
+    DWORD dwValueNameActualLength;
+    const TCHAR *pszValueTypeName;
+    unsigned int nTabSize = rConsole.GetTabWidth();
+    unsigned int nTabs;
+    while((nError = Key.GetNextValue(&dwValueNameActualLength)) == ERROR_SUCCESS)
+    {
+      rConsole.Write(_T("\t"));
+      pszValueTypeName = CRegistryKey::GetValueTypeName(Type);
+      nTabs = _tcslen(pszValueTypeName)/nTabSize;
+      nTabs = (nTabs < 4)?(4-nTabs):1;
+      rConsole.Write(pszValueTypeName);
+      while(nTabs--)
+        rConsole.Write(_T("\t"));
+      rConsole.Write((dwValueNameActualLength == 0)?_T("(Default)"):pchValueNameBuffer);
+      rConsole.Write(_T("\n"));
+      nTotalItems++;
+    }
+    
+    delete pchValueNameBuffer;
+    
+    if (nError != ERROR_NO_MORE_ITEMS)
+      throw nError;
+    
+  }    // try
+  catch (LONG nError)
+  {
+    rConsole.Write(_T("Error "));
+    TCHAR Buffer[256];
+    rConsole.Write(_itot(nError,Buffer,10));
+    rConsole.Write(_T("\n"));
+  }
                
-               rConsole.Write(_T("\n Total: "));
-               TCHAR Buffer[256];
-               rConsole.Write(_ui64tot(nTotalItems,Buffer,10));
-               rConsole.Write(_T(" item(s) listed.\n"));
-               if (pTree) delete pTree;
-       }       // if (blnDo)
+  rConsole.Write(_T("\n Total: "));
+  TCHAR Buffer[256];
+  rConsole.Write(_ui64tot(nTotalItems,Buffer,10));
+  rConsole.Write(_T(" item(s) listed.\n"));
 
        return 0;
 }
index 57254c1..c0b68be 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandHelp.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandHelp.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -123,7 +123,7 @@ int CShellCommandHelp::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 const TCHAR * CShellCommandHelp::GetHelpString()
 {
        return HELP_CMD_SHORT_DESC
-                       _T("Syntax: ") HELP_CMD _T("[<COMMAND>] [/?]\n")
+                       _T("Syntax: ") HELP_CMD _T(" [<COMMAND>] [/?]\n")
                        _T("    COMMAND    - Command for which help will be displayed.\n")
                        _T("    /?    - This help.\n\n")
                        _T("Without parameters, command lists available commands.\n");
index 94c8cf5..3ba509f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandNewKey.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandNewKey.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -50,41 +50,41 @@ BOOL CShellCommandNewKey::Match(const TCHAR *pchCommand)
 
 int CShellCommandNewKey::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
-       const TCHAR *pchNewKey = NULL, *pchArg;
+       TCHAR *pszNewKey = NULL, *pszArg;
 
        BOOL blnHelp = FALSE;
        BOOL blnExitAfterHelp = FALSE;
        BOOL blnVolatile = FALSE;
        
-       while((pchArg = rArguments.GetNextArgument()) != NULL)
+       while((pszArg = rArguments.GetNextArgument()) != NULL)
        {
-               if ((_tcsicmp(pchArg,_T("/?")) == 0)
-                       ||(_tcsicmp(pchArg,_T("-?")) == 0))
+               if ((_tcsicmp(pszArg,_T("/?")) == 0)
+                       ||(_tcsicmp(pszArg,_T("-?")) == 0))
                {
                        blnHelp = TRUE;
                }
-               else if ((_tcsicmp(pchArg,_T("/v")) == 0)
-                       ||(_tcsicmp(pchArg,_T("-v")) == 0))
+               else if ((_tcsicmp(pszArg,_T("/v")) == 0)
+                       ||(_tcsicmp(pszArg,_T("-v")) == 0))
                {
                        blnVolatile = TRUE;
                }
                else
                {
-                       if (pchNewKey)
+                       if (pszNewKey)
                        {
                                rConsole.Write(_T("Wrong parameter : \""));
-                               rConsole.Write(pchArg);
+                               rConsole.Write(pszArg);
                                rConsole.Write(_T("\"\n\n"));
                                blnHelp = TRUE;
                        }
                        else
                        {
-                               pchNewKey = pchArg;
+                               pszNewKey = pszArg;
                        }
                }
        }
 
-       if ((!blnHelp) && (!pchNewKey))
+       if (!pszNewKey)
        {
                rConsole.Write(_T("Key name not specified !\n\n"));
                blnExitAfterHelp = TRUE;
@@ -96,28 +96,74 @@ int CShellCommandNewKey::Execute(CConsole &rConsole, CArgumentParser& rArguments
                if (blnExitAfterHelp)
                        return 0;
                else
-               rConsole.Write(_T("\n"));
+      rConsole.Write(_T("\n"));
        }
 
-       if (m_rTree.IsCurrentRoot())
-       {       // root key
-               rConsole.Write(NK_CMD COMMAND_NA_ON_ROOT);
-               return 0;
-       }
+  // search for last key name token
+  TCHAR *pch = pszNewKey;
+  while(*pch) // search end of string
+    pch++;
+
+  if (pch > pszNewKey) // last non-null char
+    pch--;
+
+  while(*pch == _T('\\')) // ignore ending backslashes
+    *pch = 0;
+
+  while((pch > pszNewKey)&&(*pch != _T('\\')))
+    pch--;
+
+  ASSERT(pch >= pszNewKey);
+
+  const TCHAR *pszPath;
+  TCHAR *pszSubkeyName = pch+1;
+  if (pch == pszNewKey)
+  {
+    pszPath = _T(".");
+  }
+  else
+  {
+    if (pch-1 == pszNewKey)
+    {
+      rConsole.Write(NK_CMD COMMAND_NA_ON_ROOT);
+      return 0;
+    }
+    else
+    {
+      *pch = 0;
+      pszPath = pszNewKey;
+    }
+  }
+  
+  {
+    size_t s = _tcslen(pszSubkeyName);
+    if (s && (pszSubkeyName[0] == _T('\"')) && (pszSubkeyName[s-1] == _T('\"')))
+    {
+      pszSubkeyName[s-1] = 0;
+      pszSubkeyName++;
+    }
+  }
 
-       if (!m_rTree.NewKey(pchNewKey,blnVolatile))
+       if (!m_rTree.NewKey(pszSubkeyName,pszPath,blnVolatile))
        {
                rConsole.Write(_T("Cannot create key.\n"));
                rConsole.Write(m_rTree.GetLastErrorDescription());
        }
+  else
+  {
+    InvalidateCompletion();
+  }
+  
        return 0;
 }
 
 const TCHAR * CShellCommandNewKey::GetHelpString()
 {
        return NK_CMD_SHORT_DESC
-                       _T("Syntax: ") NK_CMD _T(" [/v] [/?] Key_Name\n\n")
-                       _T("    /? - This help.\n\n")
+                       _T("Syntax: ") NK_CMD _T(" [/v] [/?] [PATH]KEY_NAME\n\n")
+      _T("    PATH     - optional path to key which subkey will be created. Default is current key.\n")
+      _T("    KEY_NAME - name of subkey to be created.\n")
+                       _T("    /? - This help.\n")
                        _T("    /v - Create volatile key. The information is stored in memory and is not\n")
                        _T("         preserved when the corresponding registry hive is unloaded.\n");
 }
index ff79764..11c0d97 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandOwner.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandOwner.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -108,30 +108,14 @@ CheckOwnerArgument:
                }
        }
 
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
+       CRegistryKey Key;
+  
+  if (!m_rTree.GetKey(pchKey?pchKey:_T("."),KEY_QUERY_VALUE|READ_CONTROL,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    blnDo = FALSE;
+  }
 
-       if (pchKey)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)||(!pTree->ChangeCurrentKey(pchKey)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchKey);
-                       rConsole.Write(_T("\n"));
-                       //blnHelp = TRUE;
-                       blnDo = FALSE;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
-       
        if (blnHelp)
        {
                rConsole.Write(GetHelpString());
@@ -139,116 +123,112 @@ CheckOwnerArgument:
 
        if (blnDo&&blnHelp) rConsole.Write(_T("\n"));
 
-       if (blnDo)
-       {
-               if (pKey == NULL)
-               {       // root key
-                       rConsole.Write(OWNER_CMD COMMAND_NA_ON_ROOT);
-               }
-               else
-               {
-                       PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
-                       TCHAR *pchName = NULL, *pchDomainName = NULL;
-                       try
-                       {
-                               DWORD dwSecurityDescriptorLength;
-                               rConsole.Write(_T("Key : "));
-                               rConsole.Write(_T("\\"));
-                               rConsole.Write(pTree?pTree->GetCurrentPath():m_rTree.GetCurrentPath());
-                               rConsole.Write(_T("\n"));
-                               dwError = pKey->GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
-                               if (dwError != ERROR_SUCCESS) throw dwError;
+       if (!blnDo)
+    return 0;
+  
+  if (Key.IsRoot())
+  {    // root key
+    rConsole.Write(OWNER_CMD COMMAND_NA_ON_ROOT);
+    return 0;
+  }
+  
+  PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
+  TCHAR *pchName = NULL, *pchDomainName = NULL;
+  try
+  {
+    DWORD dwSecurityDescriptorLength;
+    rConsole.Write(_T("Key : "));
+    rConsole.Write(_T("\\"));
+    rConsole.Write(Key.GetKeyName());
+    rConsole.Write(_T("\n"));
+    dwError = Key.GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
+    if (dwError != ERROR_SUCCESS) throw dwError;
                                
-                               pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
-                               DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
-                               dwError = pKey->GetSecurityDescriptor((SECURITY_INFORMATION)OWNER_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
-                               if (dwError != ERROR_SUCCESS) throw dwError;
-                               PSID psidOwner;
-                               BOOL blnOwnerDefaulted;
-                               if (!GetSecurityDescriptorOwner(pSecurityDescriptor,&psidOwner,&blnOwnerDefaulted))
-                                       throw GetLastError();
-                               if (psidOwner == NULL)
-                               {
-                                       rConsole.Write(_T("Key has no owner."));
-                               }
-                               else
-                               {
-                                       if (!IsValidSid(psidOwner))
-                                       {
-                                               rConsole.Write(_T("Key has invalid owner SID."));
-                                       }
-                                       else
-                                       {
-                                               rConsole.Write(_T("Key Owner: \n"));
-                                               DWORD dwSIDStringSize = 0;
-                                               BOOL blnRet = GetTextualSid(psidOwner,NULL,&dwSIDStringSize);
-                                               ASSERT(!blnRet);
-                                               ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
-                                               TCHAR *pchSID = new TCHAR[dwSIDStringSize];
-                                               if(!GetTextualSid(psidOwner,pchSID,&dwSIDStringSize))
-                                               {
-                                                       dwError = GetLastError();
-                                                       ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
-                                                       rConsole.Write(_T("Error "));
-                                                       TCHAR Buffer[256];
-                                                       rConsole.Write(_itot(dwError,Buffer,10));
-                                                       rConsole.Write(_T("\nGetting string representation of SID\n"));
-                                               }
-                                               else
-                                               {
-                                                       rConsole.Write(_T("\tSID: "));
-                                                       rConsole.Write(pchSID);
-                                                       rConsole.Write(_T("\n"));
-                                               }
-                                               delete [] pchSID;
-                                               DWORD dwNameBufferLength, dwDomainNameBufferLength;
-                                               dwNameBufferLength = 1024;
-                                               dwDomainNameBufferLength = 1024;
-                                               pchName = new TCHAR [dwNameBufferLength];
-                                               pchDomainName = new TCHAR [dwDomainNameBufferLength];
-                                               DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
-                                               SID_NAME_USE Use;
-                                               if (!LookupAccountSid(NULL,psidOwner,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
-                                                       throw GetLastError();
-                                               else
-                                               {
-                                                       rConsole.Write(_T("\tOwner Domain: "));
-                                                       rConsole.Write(pchDomainName);
-                                                       rConsole.Write(_T("\n"));
-                                                       rConsole.Write(_T("\tOwner Name: "));
-                                                       rConsole.Write(pchName);
-                                                       rConsole.Write(_T("\n\tSID type: "));
-                                                       rConsole.Write(GetSidTypeName(Use));
-                                                       rConsole.Write(_T("\n"));
-                                                       rConsole.Write(_T("\tOwner defaulted: "));
-                                                       rConsole.Write(blnOwnerDefaulted?_T("Yes"):_T("No"));
-                                                       rConsole.Write(_T("\n"));
-                                               }
-                                               delete [] pchName;
-                                               pchName = NULL;
-                                               delete [] pchDomainName;
-                                               pchDomainName = NULL;
+    pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
+    DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
+    dwError = Key.GetSecurityDescriptor((SECURITY_INFORMATION)OWNER_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
+    if (dwError != ERROR_SUCCESS) throw dwError;
+    PSID psidOwner;
+    BOOL blnOwnerDefaulted;
+    if (!GetSecurityDescriptorOwner(pSecurityDescriptor,&psidOwner,&blnOwnerDefaulted))
+      throw GetLastError();
+    if (psidOwner == NULL)
+    {
+      rConsole.Write(_T("Key has no owner."));
+    }
+    else
+    {
+      if (!IsValidSid(psidOwner))
+      {
+        rConsole.Write(_T("Key has invalid owner SID."));
+      }
+      else
+      {
+        rConsole.Write(_T("Key Owner: \n"));
+        DWORD dwSIDStringSize = 0;
+        BOOL blnRet = GetTextualSid(psidOwner,NULL,&dwSIDStringSize);
+        ASSERT(!blnRet);
+        ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+        TCHAR *pchSID = new TCHAR[dwSIDStringSize];
+        if(!GetTextualSid(psidOwner,pchSID,&dwSIDStringSize))
+        {
+          dwError = GetLastError();
+          ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
+          rConsole.Write(_T("Error "));
+          TCHAR Buffer[256];
+          rConsole.Write(_itot(dwError,Buffer,10));
+          rConsole.Write(_T("\nGetting string representation of SID\n"));
+        }
+        else
+        {
+          rConsole.Write(_T("\tSID: "));
+          rConsole.Write(pchSID);
+          rConsole.Write(_T("\n"));
+        }
+        delete [] pchSID;
+        DWORD dwNameBufferLength, dwDomainNameBufferLength;
+        dwNameBufferLength = 1024;
+        dwDomainNameBufferLength = 1024;
+        pchName = new TCHAR [dwNameBufferLength];
+        pchDomainName = new TCHAR [dwDomainNameBufferLength];
+        DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
+        SID_NAME_USE Use;
+        if (!LookupAccountSid(NULL,psidOwner,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
+          throw GetLastError();
+        else
+        {
+          rConsole.Write(_T("\tOwner Domain: "));
+          rConsole.Write(pchDomainName);
+          rConsole.Write(_T("\n"));
+          rConsole.Write(_T("\tOwner Name: "));
+          rConsole.Write(pchName);
+          rConsole.Write(_T("\n\tSID type: "));
+          rConsole.Write(GetSidTypeName(Use));
+          rConsole.Write(_T("\n"));
+          rConsole.Write(_T("\tOwner defaulted: "));
+          rConsole.Write(blnOwnerDefaulted?_T("Yes"):_T("No"));
+          rConsole.Write(_T("\n"));
+        }
+        delete [] pchName;
+        pchName = NULL;
+        delete [] pchDomainName;
+        pchDomainName = NULL;
                                                
-                                       }
-                               }
-                               delete [] pSecurityDescriptor;
-                       }
-                       catch (DWORD dwError)
-                       {
-                               rConsole.Write(_T("Error "));
-                               TCHAR Buffer[256];
-                               rConsole.Write(_itot(dwError,Buffer,10));
-                               rConsole.Write(_T("\n"));
-                               if (pchName) delete [] pchName;
-                               if (pchDomainName) delete [] pchDomainName;
-                               if (pSecurityDescriptor) delete [] pSecurityDescriptor;
-                       }
-               } // else (pKey == NULL)
-       } // if (blnDo)
-
-       if (pTree)
-               delete pTree;
-
+      }
+    }
+    delete [] pSecurityDescriptor;
+  }
+  catch (DWORD dwError)
+  {
+    rConsole.Write(_T("Error "));
+    TCHAR Buffer[256];
+    rConsole.Write(_itot(dwError,Buffer,10));
+    rConsole.Write(_T("\n"));
+    if (pchName) delete [] pchName;
+    if (pchDomainName) delete [] pchDomainName;
+    if (pSecurityDescriptor) delete [] pSecurityDescriptor;
+  }
+  
        return 0;
 }
 
index 0665e8e..929be09 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandSACL.cpp,v 1.2 2000/10/24 20:17:41 narnaoud Exp $
+/* $Id: ShellCommandSACL.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -62,341 +62,382 @@ BOOL CShellCommandSACL::Match(const TCHAR *pchCommand)
 
 int CShellCommandSACL::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
-       TCHAR err_msg[1024];
+#define ERROR_MSG_BUFFER_SIZE 1024
+  TCHAR pszError_msg[ERROR_MSG_BUFFER_SIZE];
+  pszError_msg[ERROR_MSG_BUFFER_SIZE-1] = 0;
+  
+  rArguments.ResetArgumentIteration();
 
-       rArguments.ResetArgumentIteration();
-
-       const TCHAR *pchKey = NULL;
-       BOOL blnDo = TRUE;
-       BOOL blnBadParameter = FALSE;
-       BOOL blnHelp = FALSE;
-       const TCHAR *pchParameter;
-       const TCHAR *pchCommandItself = rArguments.GetNextArgument();
-       DWORD dwError;
+  const TCHAR *pszKey = NULL;
+  BOOL blnDo = TRUE;
+  BOOL blnBadParameter = FALSE;
+  BOOL blnHelp = FALSE;
+  const TCHAR *pszParameter;
+  const TCHAR *pszCommandItself = rArguments.GetNextArgument();
+  DWORD dwError;
+  PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
+  CSecurityDescriptor sd;
+  HANDLE hThreadToken = INVALID_HANDLE_VALUE;
+  
+  if ((_tcsnicmp(pszCommandItself,SACL_CMD _T(".."),SACL_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
+      (_tcsnicmp(pszCommandItself,SACL_CMD _T("\\"),SACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
+  {
+    pszKey = pszCommandItself + SACL_CMD_LENGTH;
+  }
+  else if (_tcsnicmp(pszCommandItself,SACL_CMD _T("/"),SACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+  {
+    pszParameter = pszCommandItself + SACL_CMD_LENGTH;
+    goto CheckSACLArgument;
+  }
+  
+  while((pszParameter = rArguments.GetNextArgument()) != NULL)
+  {
+CheckSACLArgument:
+    blnBadParameter = FALSE;
+    if ((_tcsicmp(pszParameter,_T("/?")) == 0)||
+        (_tcsicmp(pszParameter,_T("-?")) == 0))
+    {
+      blnHelp = TRUE;
+      blnDo = pszKey != NULL;
+    }
+    else if (!pszKey)
+    {
+      pszKey = pszParameter;
+      blnDo = TRUE;
+    }
+    else
+    {
+      blnBadParameter = TRUE;
+    }
+    if (blnBadParameter)
+    {
+      rConsole.Write(_T("Bad parameter: "));
+      rConsole.Write(pszParameter);
+      rConsole.Write(_T("\n"));
+    }
+  }
 
-       if ((_tcsnicmp(pchCommandItself,SACL_CMD _T(".."),SACL_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
-               (_tcsnicmp(pchCommandItself,SACL_CMD _T("\\"),SACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
-       {
-               pchKey = pchCommandItself + SACL_CMD_LENGTH;
-       }
-       else if (_tcsnicmp(pchCommandItself,SACL_CMD _T("/"),SACL_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
-       {
-               pchParameter = pchCommandItself + SACL_CMD_LENGTH;
-               goto CheckSACLArgument;
-       }
+  CRegistryKey Key;
 
-       while((pchParameter = rArguments.GetNextArgument()) != NULL)
-       {
-CheckSACLArgument:
-               blnBadParameter = FALSE;
-//                     Console.Write(_T("Processing parameter: \")");
-//                     Console.Write(pchParameter);
-//                     Console.Write(_T("\")\n");
-               if ((_tcsicmp(pchParameter,_T("/?")) == 0)
-                       ||(_tcsicmp(pchParameter,_T("-?")) == 0))
-               {
-                       blnHelp = TRUE;
-                       blnDo = pchKey != NULL;
-               }
-               else if (!pchKey)
-               {
-                       pchKey = pchParameter;
-                       blnDo = TRUE;
-               }
-               else
-               {
-                       blnBadParameter = TRUE;
-               }
-               if (blnBadParameter)
-               {
-                       rConsole.Write(_T("Bad parameter: "));
-                       rConsole.Write(pchParameter);
-                       rConsole.Write(_T("\n"));
-               }
-       }
+  ASSERT(hThreadToken == INVALID_HANDLE_VALUE);
+  
+  // Open thread token
+  if (!OpenThreadToken(GetCurrentThread(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,FALSE,&hThreadToken))
+  {    // OpenThreadToken failed
+    dwError = GetLastError();
+    if (dwError != ERROR_NO_TOKEN)
+    {
+      _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot open thread token.\nOpenThreadToken fails with error: %u\n"),(unsigned int)dwError);
+      goto Error;
+    }
+    
+    // If the thread does not have an access token, we'll examine the
+    // access token associated with the process.
+    if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hThreadToken))
+    {
+      _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot open process token.\nOpenProcessToken fails with error: %u\n"),(unsigned int)GetLastError());
+      goto Error;
+    }
+  }
+  
+  ASSERT(hThreadToken != INVALID_HANDLE_VALUE);
 
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
-       if (pchKey)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)||(!pTree->ChangeCurrentKey(pchKey)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchKey);
-                       rConsole.Write(_T("\n"));
-                       //blnHelp = TRUE;
-                       blnDo = FALSE;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
+  // enable SeSecurityPrivilege privilege
+  TOKEN_PRIVILEGES priv;
+  priv.PrivilegeCount = 1;
+  priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+  if (!LookupPrivilegeValue(
+      NULL,                                                    // lookup privilege on local system
+      SE_SECURITY_NAME,                                // privilege to lookup 
+      &(priv.Privileges[0].Luid)))     // receives LUID of privilege
+  {
+    _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot retrieve the locally unique identifier for %s privilege.\nLookupPrivilegeValue error: %u\n"),SE_SECURITY_NAME,(unsigned int)GetLastError());
+    goto Error;
+  }
 
-       if (blnHelp)
-       {
-               rConsole.Write(GetHelpString());
-       }
+  BOOL blnAdjRet;
+  blnAdjRet = AdjustTokenPrivileges(
+      hThreadToken,
+      FALSE,
+      &priv,
+      sizeof(TOKEN_PRIVILEGES),
+      (PTOKEN_PRIVILEGES)NULL,
+      (PDWORD)NULL);
+  dwError = GetLastError();
+  if (!blnAdjRet)
+  {
+    _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges fails with error: %u%s\n"),SE_SECURITY_NAME,(unsigned int)dwError,(dwError == 5)?_T(" (Access denied)"):_T(""));
+    goto Error;
+  }
+  
+  if (dwError != ERROR_SUCCESS)
+  {
+    if (dwError == ERROR_NOT_ALL_ASSIGNED)
+    {
+      _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot enable %s privilege.\nThe token does not have the %s privilege\n"),SE_SECURITY_NAME,SE_SECURITY_NAME);
+    }
+    else
+    {
+      _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges succeds with error: %u\n"),SE_SECURITY_NAME,(unsigned int)dwError);
+    }
+    
+    goto Error;
+  }
+  
+  if (!m_rTree.GetKey(pszKey?pszKey:_T("."),KEY_QUERY_VALUE|READ_CONTROL|ACCESS_SYSTEM_SECURITY,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    blnDo = FALSE;
+  }
+  
+  if (blnHelp)
+  {
+    rConsole.Write(GetHelpString());
+  }
 
-       if (blnDo&&blnHelp) rConsole.Write(_T("\n"));
+  if (blnDo&&blnHelp)
+    rConsole.Write(_T("\n"));
 
-       if (blnDo)
-       {
-               try
-               {
-                       if (!pKey)
-                               throw (SACL_CMD COMMAND_NA_ON_ROOT);
+  if (!blnDo)
+    return 0;
+  
+  if (Key.IsRoot())
+  {
+    _tcsncpy(pszError_msg,SACL_CMD COMMAND_NA_ON_ROOT,ERROR_MSG_BUFFER_SIZE-1);
+    goto Error;
+  }
+      
+  DWORD dwSecurityDescriptorLength;
+  rConsole.Write(_T("Key : "));
+  rConsole.Write(_T("\\"));
+  
+  rConsole.Write(Key.GetKeyName());
+  rConsole.Write(_T("\n"));
+  dwError = Key.GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
+  if (dwError != ERROR_SUCCESS)
+  {
+    _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot get security descriptor's length for current key.\nError: %u\n"),(unsigned int)dwError);
+    goto Error;
+  }
+  
+  pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
+  if (!pSecurityDescriptor)
+  {
+      _tcsncpy(pszError_msg,_T("\nOut of memory.\n"),ERROR_MSG_BUFFER_SIZE-1);
+      goto Error;
+  }
+  
+  DWORD dwSecurityDescriptorLength1;
+  dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
+  dwError = Key.GetSecurityDescriptor((SECURITY_INFORMATION)SACL_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
+  if (dwError != ERROR_SUCCESS)
+  {
+    _sntprintf(pszError_msg,ERROR_MSG_BUFFER_SIZE-1,_T("\nCannot get security descriptor for current key.\nError: %u%s\n"),(unsigned int)dwError,(dwError == 1314)?_T("(A required privilege is not held by the client.)\n"):_T(""));
+    goto Error;
+  }
+  
+  sd.AssociateDescriptor(pSecurityDescriptor);
+  sd.BeginSACLInteration();
+  
+  if ((!sd.DescriptorContainsSACL())||(sd.HasNULLSACL()))
+  {
+    _tcsncpy(pszError_msg,_T("Key has not SACL.\n"),ERROR_MSG_BUFFER_SIZE-1);
+    goto Error;
+  }
+  
+  if (!sd.HasValidSACL())
+  {
+    _tcsncpy(pszError_msg,_T("Invalid SACL.\n"),ERROR_MSG_BUFFER_SIZE-1);
+    goto Error;
+  }
+  
+  DWORD nACECount;
+  nACECount = sd.GetSACLEntriesCount();
+  rConsole.Write(_T("SACL has "));
+  TCHAR Buffer[256];
+  rConsole.Write(_itot(nACECount,Buffer,10));
+  rConsole.Write(_T(" ACEs.\n"));
+  ASSERT(sizeof(ACL) == 8);
+  rConsole.Write(_T("\n"));
+  for (DWORD i = 0 ; i < nACECount ; i++)
+  {
+    rConsole.Write(_T("\n"));
+    rConsole.Write(_T("\tACE Index: "));
+    rConsole.Write(_itot(i,Buffer,10));
+    rConsole.Write(_T("\n"));
+    rConsole.Write(_T("\tAudit Type: "));
+    BOOL blnFailed, blnSuccessful;
+    if (sd.GetSACLEntry(i,blnFailed,blnSuccessful) != CSecurityDescriptor::SystemAudit)
+    {
+      rConsole.Write(_T("Unknown ACE type.\nCannot continue ACE list dump.\n"));
+      goto AbortDumpSACL;
+    }
+    
+    if (blnFailed)
+      rConsole.Write(_T("Failed access"));
+    
+    if (blnFailed && blnSuccessful)
+      rConsole.Write(_T(" & "));
+    if (blnSuccessful)
+      rConsole.Write(_T("Successful access"));
+    rConsole.Write(_T("\n"));
+    
+    PSID pSID = sd.GetCurrentACE_SID();
+    if ((pSID == NULL)||(!IsValidSid(pSID)))
+    {
+      rConsole.Write(_T("\tInvalid SID.\n"));
+    }
+    
+    DWORD dwSIDStringSize = 0;
+    BOOL blnRet = GetTextualSid(pSID,NULL,&dwSIDStringSize);
+    ASSERT(!blnRet);
+    ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+    TCHAR *pszSID = new TCHAR[dwSIDStringSize];
 
-                       HANDLE hThreadToken = INVALID_HANDLE_VALUE;
-                       if (!OpenThreadToken(GetCurrentThread(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,FALSE,&hThreadToken))
-                       {       // OpenThreadToken fails
-                               dwError = GetLastError();
-                               if (dwError != ERROR_NO_TOKEN)
-                               {
-                                       _stprintf(err_msg,_T("\nCannot open thread token.\nOpenThreadToken fails with error: %u\n"),dwError);
-                                       throw err_msg;
-                               }
-                               // If the thread does not have an access token, we'll examine the
-                               // access token associated with the process.
-                               if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hThreadToken))
-                               {
-                                       _stprintf(err_msg,_T("\nCannot open process token.\nOpenProcessToken fails with error: %u\n"),GetLastError());
-                                       throw err_msg;
-                               }
-                       }
-                       ASSERT(hThreadToken != INVALID_HANDLE_VALUE);
-                       TOKEN_PRIVILEGES priv;
-                       priv.PrivilegeCount = 1;
-                       priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
-                       if (!LookupPrivilegeValue(
-                               NULL,                                                   // lookup privilege on local system
-                               SE_SECURITY_NAME,                               // privilege to lookup 
-                               &(priv.Privileges[0].Luid)))    // receives LUID of privilege
-                       {
-                               _stprintf(err_msg,_T("\nCannot retrieve the locally unique identifier for %s privilege.\nLookupPrivilegeValue error: %u\n"),SE_SECURITY_NAME,GetLastError());
-                               throw err_msg;
-                       }
-                       BOOL blnAdjRet = AdjustTokenPrivileges(
-                               hThreadToken,
-                               FALSE,
-                               &priv,
-                               sizeof(TOKEN_PRIVILEGES),
-                               (PTOKEN_PRIVILEGES)NULL,
-                               (PDWORD)NULL);
-                       dwError = GetLastError();
-                       if (!blnAdjRet)
-                       {
-                               _stprintf(err_msg,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges fails with error: %u%s\n"),SE_SECURITY_NAME,dwError,(dwError == 5)?_T(" (Access denied)"):_T(""));
-                               throw err_msg;
-                       }
-                       if (dwError != ERROR_SUCCESS)
-                       {
-                               if (dwError == ERROR_NOT_ALL_ASSIGNED)
-                               {
-                                       _stprintf(err_msg,_T("\nCannot enable %s privilege.\nThe token does not have the %s privilege\n"),SE_SECURITY_NAME,SE_SECURITY_NAME);
-                               }
-                               else
-                               {
-                                       _stprintf(err_msg,_T("\nCannot enable %s privilege.\nAdjustTokenPrivileges succeds with error: %u\n"),SE_SECURITY_NAME,dwError);
-                               }
-                               throw err_msg;
-                       }
-                       if (!pKey->IsPredefined())
-                       {
-                               dwError = pKey->Open(m_rTree.GetDesiredOpenKeyAccess()|ACCESS_SYSTEM_SECURITY);
-                               if (dwError != ERROR_SUCCESS)
-                               {
-                                       _stprintf(err_msg,_T("\nCannot reopen current key.\nError %u%s\n"),dwError,(dwError == 5)?_T(" (Access denied)"):_T(""));
-                                       throw err_msg;
-                               }
-                       }
-                       DWORD dwSecurityDescriptorLength;
-                       rConsole.Write(_T("Key : "));
-                       rConsole.Write(_T("\\"));
-                       rConsole.Write(pTree?pTree->GetCurrentPath():m_rTree.GetCurrentPath());
-                       rConsole.Write(_T("\n"));
-                       dwError = pKey->GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
-                       if (dwError != ERROR_SUCCESS)
-                       {
-                               _stprintf(err_msg,_T("\nCannot get security descriptor's length for current key.\nError: %u\n"),dwError);
-                               throw err_msg;
-                       }
-                       PSECURITY_DESCRIPTOR pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
-                       DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
-                       dwError = pKey->GetSecurityDescriptor((SECURITY_INFORMATION)SACL_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
-                       if (dwError != ERROR_SUCCESS)
-                       {
-                               _stprintf(err_msg,_T("\nCannot get security descriptor for current key.\nError: %u%s\n"),dwError,(dwError == 1314)?_T("(A required privilege is not held by the client.)\n"):_T(""));
-                               throw err_msg;
-                       }
-                       CSecurityDescriptor sd;
-                       sd.AssociateDescriptor(pSecurityDescriptor);
-                       sd.BeginSACLInteration();
-                       
-                       if ((!sd.DescriptorContainsSACL())||(sd.HasNULLSACL()))
-                       {
-                               throw _T("Key has not SACL.\n");
-                       }
-                       if (!sd.HasValidSACL())
-                       {
-                               throw _T("Invalid SACL.\n");
-                       }
-                       DWORD nACECount = sd.GetSACLEntriesCount();
-                       rConsole.Write(_T("SACL has "));
-                       TCHAR Buffer[256];
-                       rConsole.Write(_itot(nACECount,Buffer,10));
-                       rConsole.Write(_T(" ACEs.\n"));
-                       ASSERT(sizeof(ACL) == 8);
-                       rConsole.Write(_T("\n"));
-                       for (DWORD i = 0 ; i < nACECount ; i++)
-                       {
-                               rConsole.Write(_T("\n"));
-                               rConsole.Write(_T("\tACE Index: "));
-                               rConsole.Write(_itot(i,Buffer,10));
-                               rConsole.Write(_T("\n"));
-                               rConsole.Write(_T("\tAudit Type: "));
-                               BOOL blnFailed, blnSuccessful;
-                               if (sd.GetSACLEntry(i,blnFailed,blnSuccessful) != CSecurityDescriptor::SystemAudit)
-                               {
-                                       rConsole.Write(_T("Unknown ACE type.\nCannot continue ACE list dump.\n"));
-                                       goto AbortDumpSACL;
-                               }
-                               if (blnFailed) rConsole.Write(_T("Failed access"));
-                               if (blnFailed && blnSuccessful) rConsole.Write(_T(" & "));
-                               if (blnSuccessful) rConsole.Write(_T("Successful access"));
-                               rConsole.Write(_T("\n"));
-                               PSID pSID = sd.GetCurrentACE_SID();
-                               if ((pSID == NULL)||(!IsValidSid(pSID)))
-                               {
-                                       rConsole.Write(_T("\tInvalid SID.\n"));
-                               }
-                               DWORD dwSIDStringSize = 0;
-                               BOOL blnRet = GetTextualSid(pSID,NULL,&dwSIDStringSize);
-                               ASSERT(!blnRet);
-                               ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
-                               TCHAR *pchSID = new TCHAR[dwSIDStringSize];
-                               if(!GetTextualSid(pSID,pchSID,&dwSIDStringSize))
-                               {
-                                       dwError = GetLastError();
-                                       ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
-                                       rConsole.Write(_T("Error "));
-                                       TCHAR Buffer[256];
-                                       rConsole.Write(_itot(dwError,Buffer,10));
-                                       rConsole.Write(_T("\nGetting string representation of SID\n"));
-                               }
-                               else
-                               {
-                                       rConsole.Write(_T("\tSID: "));
-                                       rConsole.Write(pchSID);
-                                       rConsole.Write(_T("\n"));
-                               }
-                               delete [] pchSID;
-                               TCHAR *pchName, *pchDomainName;
-                               DWORD dwNameBufferLength, dwDomainNameBufferLength;
-                               dwNameBufferLength = 1024;
-                               dwDomainNameBufferLength = 1024;
-                               pchName = new TCHAR [dwNameBufferLength];
-                               pchDomainName = new TCHAR [dwDomainNameBufferLength];
-                               DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
-                               SID_NAME_USE Use;
-                               if (!LookupAccountSid(NULL,pSID,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
-                               {
-                                       rConsole.Write(_T("Error "));
-                                       TCHAR Buffer[256];
-                                       rConsole.Write(_itot(GetLastError(),Buffer,10));
-                                       rConsole.Write(_T("\n"));
-                               }
-                               else
-                               {
-                                       rConsole.Write(_T("\tTrustee Domain: "));
-                                       rConsole.Write(pchDomainName);
-                                       rConsole.Write(_T("\n"));
-                                       rConsole.Write(_T("\tTrustee Name: "));
-                                       rConsole.Write(pchName);
-                                       rConsole.Write(_T("\n\tSID type: "));
-                                       rConsole.Write(GetSidTypeName(Use));
-                                       rConsole.Write(_T("\n"));
-                               }
-                               DWORD dwAccessMask;
-                               sd.GetCurrentACE_AccessMask(dwAccessMask);
-                               wsprintf(Buffer,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask);
-                               rConsole.Write(Buffer);
-                               if (dwAccessMask & GENERIC_READ)
-                               {
-                                       rConsole.Write(_T("\t\tGENERIC_READ\n"));
-                               }
-                               if (dwAccessMask & GENERIC_WRITE)
-                               {
-                                       rConsole.Write(_T("\t\tGENERIC_WRITE\n"));
-                               }
-                               if (dwAccessMask & GENERIC_EXECUTE)
-                               {
-                                       rConsole.Write(_T("\t\tGENERIC_EXECUTE\n"));
-                               }
-                               if (dwAccessMask & GENERIC_ALL)
-                               {
-                                       rConsole.Write(_T("\t\tGENERIC_ALL\n"));
-                               }
-                               if (dwAccessMask & SYNCHRONIZE)
-                               {
-                                       rConsole.Write(_T("\t\tSYNCHRONIZE\n"));
-                               }
-                               if (dwAccessMask & WRITE_OWNER)
-                               {
-                                       rConsole.Write(_T("\t\tWRITE_OWNER\n"));
-                               }
-                               if (dwAccessMask & WRITE_DAC)
-                               {
-                                       rConsole.Write(_T("\t\tWRITE_DAC\n"));
-                               }
-                               if (dwAccessMask & READ_CONTROL)
-                               {
-                                       rConsole.Write(_T("\t\tREAD_CONTROL\n"));
-                               }
-                               if (dwAccessMask & DELETE)
-                               {
-                                       rConsole.Write(_T("\t\tDELETE\n"));
-                               }
-                               if (dwAccessMask & KEY_CREATE_LINK)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_CREATE_LINK\n"));
-                               }
-                               if (dwAccessMask & KEY_NOTIFY)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_NOTIFY\n"));
-                               }
-                               if (dwAccessMask & KEY_ENUMERATE_SUB_KEYS)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n"));
-                               }
-                               if (dwAccessMask & KEY_CREATE_SUB_KEY)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_CREATE_SUB_KEY\n"));
-                               }
-                               if (dwAccessMask & KEY_SET_VALUE)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_SET_VALUE\n"));
-                               }
-                               if (dwAccessMask & KEY_QUERY_VALUE)
-                               {
-                                       rConsole.Write(_T("\t\tKEY_QUERY_VALUE\n"));
-                               }
-                       }       // for
+    if (!pszSID)
+    {
+      _tcsncpy(pszError_msg,_T("\nOut of memory.\n"),ERROR_MSG_BUFFER_SIZE-1);
+      goto Error;
+    }
+    
+    if(!GetTextualSid(pSID,pszSID,&dwSIDStringSize))
+    {
+      dwError = GetLastError();
+      ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
+      rConsole.Write(_T("Error "));
+      TCHAR Buffer[256];
+      rConsole.Write(_itot(dwError,Buffer,10));
+      rConsole.Write(_T("\nGetting string representation of SID\n"));
+    }
+    else
+    {
+      rConsole.Write(_T("\tSID: "));
+      rConsole.Write(pszSID);
+      rConsole.Write(_T("\n"));
+    }
+    delete pszSID;
+    
+    TCHAR *pszName, *pszDomainName;
+    DWORD dwNameBufferLength, dwDomainNameBufferLength;
+    dwNameBufferLength = 1024;
+    dwDomainNameBufferLength = 1024;
+    
+    pszName = new TCHAR [dwNameBufferLength];
+    if (!pszName)
+    {
+      _tcsncpy(pszError_msg,_T("\nOut of memory.\n"),ERROR_MSG_BUFFER_SIZE-1);
+      goto Error;
+    }
+    
+    pszDomainName = new TCHAR [dwDomainNameBufferLength];
+    if (!pszDomainName)
+    {
+      _tcsncpy(pszError_msg,_T("\nOut of memory.\n"),ERROR_MSG_BUFFER_SIZE-1);
+      goto Error;
+    }
+    
+    DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
+    SID_NAME_USE Use;
+    if (!LookupAccountSid(NULL,pSID,pszName,&dwNameLength,pszDomainName,&dwDomainNameLength,&Use))
+    {
+      rConsole.Write(_T("Error "));
+      TCHAR Buffer[256];
+      rConsole.Write(_itot(GetLastError(),Buffer,10));
+      rConsole.Write(_T("\n"));
+    }
+    else
+    {
+      rConsole.Write(_T("\tTrustee Domain: "));
+      rConsole.Write(pszDomainName);
+      rConsole.Write(_T("\n"));
+      rConsole.Write(_T("\tTrustee Name: "));
+      rConsole.Write(pszName);
+      rConsole.Write(_T("\n\tSID type: "));
+      rConsole.Write(GetSidTypeName(Use));
+      rConsole.Write(_T("\n"));
+    }
+    DWORD dwAccessMask;
+    sd.GetCurrentACE_AccessMask(dwAccessMask);
+    wsprintf(Buffer,_T("\tAccess Mask: 0x%08lX\n"),dwAccessMask);
+    rConsole.Write(Buffer);
+    if (dwAccessMask & GENERIC_READ)
+    {
+      rConsole.Write(_T("\t\tGENERIC_READ\n"));
+    }
+    if (dwAccessMask & GENERIC_WRITE)
+    {
+      rConsole.Write(_T("\t\tGENERIC_WRITE\n"));
+    }
+    if (dwAccessMask & GENERIC_EXECUTE)
+    {
+      rConsole.Write(_T("\t\tGENERIC_EXECUTE\n"));
+    }
+    if (dwAccessMask & GENERIC_ALL)
+    {
+      rConsole.Write(_T("\t\tGENERIC_ALL\n"));
+    }
+    if (dwAccessMask & SYNCHRONIZE)
+    {
+      rConsole.Write(_T("\t\tSYNCHRONIZE\n"));
+    }
+    if (dwAccessMask & WRITE_OWNER)
+    {
+      rConsole.Write(_T("\t\tWRITE_OWNER\n"));
+    }
+    if (dwAccessMask & WRITE_DAC)
+    {
+      rConsole.Write(_T("\t\tWRITE_DAC\n"));
+    }
+    if (dwAccessMask & READ_CONTROL)
+    {
+      rConsole.Write(_T("\t\tREAD_CONTROL\n"));
+    }
+    if (dwAccessMask & DELETE)
+    {
+      rConsole.Write(_T("\t\tDELETE\n"));
+    }
+    if (dwAccessMask & KEY_CREATE_LINK)
+    {
+      rConsole.Write(_T("\t\tKEY_CREATE_LINK\n"));
+    }
+    if (dwAccessMask & KEY_NOTIFY)
+    {
+      rConsole.Write(_T("\t\tKEY_NOTIFY\n"));
+    }
+    if (dwAccessMask & KEY_ENUMERATE_SUB_KEYS)
+    {
+      rConsole.Write(_T("\t\tKEY_ENUMERATE_SUB_KEYS\n"));
+    }
+    if (dwAccessMask & KEY_CREATE_SUB_KEY)
+    {
+      rConsole.Write(_T("\t\tKEY_CREATE_SUB_KEY\n"));
+    }
+    if (dwAccessMask & KEY_SET_VALUE)
+    {
+      rConsole.Write(_T("\t\tKEY_SET_VALUE\n"));
+    }
+    if (dwAccessMask & KEY_QUERY_VALUE)
+    {
+      rConsole.Write(_T("\t\tKEY_QUERY_VALUE\n"));
+    }
+  }    // for
+  
 AbortDumpSACL:
-                       delete pSecurityDescriptor;
-               }
-               catch(TCHAR *pchError)
-               {
-                       rConsole.Write(pchError);
-               }
-       } // if (blnDo)
+  ASSERT(pSecurityDescriptor);
+  delete pSecurityDescriptor;
+
+  VERIFY(CloseHandle(hThreadToken));
 
        return 0;
+Error:
+  if (pSecurityDescriptor)
+    delete pSecurityDescriptor;
+
+  if (hThreadToken != INVALID_HANDLE_VALUE)
+    VERIFY(CloseHandle(hThreadToken));
+  
+  rConsole.Write(pszError_msg);
+  return 0;
 }
 
 const TCHAR * CShellCommandSACL::GetHelpString()
index b9becbb..e5a72af 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandSetValue.cpp,v 1.2 2000/10/24 20:17:42 narnaoud Exp $
+/* $Id: ShellCommandSetValue.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -104,77 +104,78 @@ CShellCommandSetValue::~CShellCommandSetValue()
 {
 }
 
-BOOL CShellCommandSetValue::Match(const TCHAR *pchCommand)
+BOOL CShellCommandSetValue::Match(const TCHAR *pszCommand)
 {
-       if (_tcsicmp(pchCommand,SET_VALUE_CMD) == 0)
+       if (_tcsicmp(pszCommand,SET_VALUE_CMD) == 0)
                return TRUE;
-       if (_tcsnicmp(pchCommand,SET_VALUE_CMD _T(".."),SET_VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)
+       if (_tcsnicmp(pszCommand,SET_VALUE_CMD _T(".."),SET_VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)
                return TRUE;
-       if (_tcsnicmp(pchCommand,SET_VALUE_CMD _T("/"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+       if (_tcsnicmp(pszCommand,SET_VALUE_CMD _T("/"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
                return TRUE;
-       if (_tcsnicmp(pchCommand,SET_VALUE_CMD _T("\\"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+       if (_tcsnicmp(pszCommand,SET_VALUE_CMD _T("\\"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
                return TRUE;
        return FALSE;
 }
 
 int CShellCommandSetValue::Execute(CConsole &rConsole, CArgumentParser& rArguments)
 {
+  LONG nError;
+  
        rArguments.ResetArgumentIteration();
-       TCHAR *pchCommandItself = rArguments.GetNextArgument();
+       TCHAR *pszCommandItself = rArguments.GetNextArgument();
 
-       TCHAR *pchParameter;
-       TCHAR *pchValueFull = NULL;
-       TCHAR *pchValueData = NULL;
+       TCHAR *pszParameter;
+       TCHAR *pszValueFull = NULL;
+       TCHAR *pszValueData = NULL;
        BOOL blnBadParameter = FALSE;
        BOOL blnHelp = FALSE;
-//     DWORD dwError;
        DWORD dwValueSize = 0;
        DWORD dwType = REG_NONE;
        BYTE *pDataBuffer = NULL;
 
-       if ((_tcsnicmp(pchCommandItself,SET_VALUE_CMD _T(".."),SET_VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
-               (_tcsnicmp(pchCommandItself,SET_VALUE_CMD _T("\\"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
+       if ((_tcsnicmp(pszCommandItself,SET_VALUE_CMD _T(".."),SET_VALUE_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
+               (_tcsnicmp(pszCommandItself,SET_VALUE_CMD _T("\\"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
        {
-               pchValueFull = pchCommandItself + SET_VALUE_CMD_LENGTH;
+               pszValueFull = pszCommandItself + SET_VALUE_CMD_LENGTH;
        }
-       else if (_tcsnicmp(pchCommandItself,SET_VALUE_CMD _T("/"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
+       else if (_tcsnicmp(pszCommandItself,SET_VALUE_CMD _T("/"),SET_VALUE_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
        {
-               pchParameter = pchCommandItself + SET_VALUE_CMD_LENGTH;
+               pszParameter = pszCommandItself + SET_VALUE_CMD_LENGTH;
                goto CheckValueArgument;
        }
 
-       while((pchParameter = rArguments.GetNextArgument()) != NULL)
+       while((pszParameter = rArguments.GetNextArgument()) != NULL)
        {
 CheckValueArgument:
                blnBadParameter = FALSE;
-               if (((*pchParameter == _T('/'))||(*pchParameter == _T('-')))
-                       &&(*(pchParameter+1) == _T('?')))
+               if (((*pszParameter == _T('/'))||(*pszParameter == _T('-')))
+                       &&(*(pszParameter+1) == _T('?')))
                {
                        blnHelp = TRUE;
                }
                else if (dwType == REG_NONE)
                {
-                       if (_tcsicmp(pchParameter,_T("b")) == 0)
+                       if (_tcsicmp(pszParameter,_T("b")) == 0)
                        {
                                dwType = REG_BINARY;
                        }
-                       else if (_tcsicmp(pchParameter,_T("dw")) == 0)
+                       else if (_tcsicmp(pszParameter,_T("dw")) == 0)
                        {
                                dwType = REG_DWORD;
                        }
-                       else if (_tcsicmp(pchParameter,_T("dwle")) == 0)
+                       else if (_tcsicmp(pszParameter,_T("dwle")) == 0)
                        {
                                dwType = REG_DWORD_LITTLE_ENDIAN;
                        }
-                       else if (_tcsicmp(pchParameter,_T("dwbe")) == 0)
+                       else if (_tcsicmp(pszParameter,_T("dwbe")) == 0)
                        {
                                dwType = REG_DWORD_BIG_ENDIAN;
                        }
-                       else if (_tcsicmp(pchParameter,_T("sz")) == 0)
+                       else if (_tcsicmp(pszParameter,_T("sz")) == 0)
                        {
                                dwType = REG_SZ;
                        }
-                       else if (_tcsicmp(pchParameter,_T("esz")) == 0)
+                       else if (_tcsicmp(pszParameter,_T("esz")) == 0)
                        {
                                dwType = REG_EXPAND_SZ;
                        }
@@ -183,13 +184,13 @@ CheckValueArgument:
                                blnBadParameter = TRUE;
                        }
                }
-               else if (pchValueData == NULL)
+               else if (pszValueData == NULL)
                {
-                       pchValueData = pchParameter;
+                       pszValueData = pszParameter;
                }
-               else if (!pchValueFull)
+               else if (!pszValueFull)
                {
-                       pchValueFull = pchParameter;
+                       pszValueFull = pszParameter;
                }
                else
                {
@@ -198,18 +199,17 @@ CheckValueArgument:
                if (blnBadParameter)
                {
                        rConsole.Write(_T("Bad parameter: "));
-                       rConsole.Write(pchParameter);
+                       rConsole.Write(pszParameter);
                        rConsole.Write(_T("\n"));
                }
        }
 
-       if (!pchValueData)
+       if (!pszValueData)
                blnHelp = TRUE;
        
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
-       TCHAR *pchValueName;
-       TCHAR *pchPath;
+       CRegistryKey Key;
+       TCHAR *pszValueName;
+       const TCHAR *pszPath;
        
        if (blnHelp)
        {
@@ -221,19 +221,19 @@ CheckValueArgument:
                return 0;
        }
 
-       if (pchValueFull)
+       if (pszValueFull)
        {
-               if (_tcscmp(pchValueFull,_T("\\")) == 0)
+               if (_tcscmp(pszValueFull,_T("\\")) == 0)
                        goto CommandNAonRoot;
 
-               TCHAR *pchSep = _tcsrchr(pchValueFull,_T('\\'));
-               pchValueName = pchSep?(pchSep+1):(pchValueFull);
-               pchPath = pchSep?pchValueFull:NULL;
+               TCHAR *pchSep = _tcsrchr(pszValueFull,_T('\\'));
+               pszValueName = pchSep?(pchSep+1):(pszValueFull);
+               pszPath = pchSep?pszValueFull:_T(".");
                                
-               //if (_tcsrchr(pchValueName,_T('.')))
+               //if (_tcsrchr(pszValueName,_T('.')))
                //{
-               //      pchValueName = _T("");
-               //      pchPath = pchValueFull;
+               //      pszValueName = _T("");
+               //      pszPath = pszValueFull;
                //}
                //else
                if (pchSep)
@@ -241,131 +241,130 @@ CheckValueArgument:
        }
        else
        {
-               pchValueName = _T("");
-               pchPath = NULL;
+               pszValueName = _T("");
+               pszPath = _T(".");
        }
                
-       if (pchPath)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)
-                       ||(!pTree->ChangeCurrentKey(pchPath)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchPath);
-                       rConsole.Write(_T("\n"));
-                       goto SkipCommand;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
+  if (!m_rTree.GetKey(pszPath,KEY_SET_VALUE,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    goto SkipCommand;
+  }
        
-       if (pKey)
-       {       // not root key ???
-               switch (dwType)
-               {
-               case REG_BINARY:
-                       {
-                               HANDLE hFile;
-                               DWORD dwBytesReaded;
-                               hFile = CreateFile(pchValueData,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
-                               if (hFile == INVALID_HANDLE_VALUE)
-                               {
-                                       rConsole.Write(_T("Cannot open file "));
-                                       rConsole.Write(pchValueData);
-                                       rConsole.Write(_T("\n"));
-                                       goto SkipCommand;
-                               }
-                               dwValueSize = GetFileSize(hFile,NULL);
-                               if (dwValueSize == -1)  // ok, that's right, we compare signed with unsigned here.
-                                                                               // GetFileSize is documented and declared to return DWORD.
-                                                                               // Error is indicated by checking if return is -1. Design->documentation bug ???
-                               {
-                                       rConsole.Write(_T("Cannot get size of file "));
-                                       rConsole.Write(pchValueData);
-                                       rConsole.Write(_T("\n"));
-                                       VERIFY(CloseHandle(hFile));
-                                       goto SkipCommand;
-                               }
-                               pDataBuffer = new BYTE [dwValueSize];
-                               if (!pDataBuffer)
-                               {
-                                       rConsole.Write(_T("Cannot load file into memory. Out of memory.\n"));
-                                       VERIFY(CloseHandle(hFile));
-                                       goto SkipCommand;
-                               }
-                               if (!ReadFile(hFile,pDataBuffer,dwValueSize,&dwBytesReaded,NULL))
-                               {
-                                       rConsole.Write(_T("Cannot load file into memory. Error reading file.\n"));
-                                       VERIFY(CloseHandle(hFile));
-                                       goto SkipCommand;
-                               }
+       if (Key.IsRoot())
+    goto CommandNAonRoot;
+  
+  switch (dwType)
+  {
+  case REG_BINARY:
+    {
+      HANDLE hFile;
+      DWORD dwBytesReaded;
+      hFile = CreateFile(pszValueData,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
+      if (hFile == INVALID_HANDLE_VALUE)
+      {
+        rConsole.Write(_T("Cannot open file "));
+        rConsole.Write(pszValueData);
+        rConsole.Write(_T("\n"));
+        goto SkipCommand;
+      }
+      dwValueSize = GetFileSize(hFile,NULL);
+      if (dwValueSize == (DWORD)-1)    // ok, that's right, we compare signed with unsigned here.
+        // GetFileSize is documented and declared to return DWORD.
+        // Error is indicated by checking if return is -1. Design->documentation bug ???
+      {
+        rConsole.Write(_T("Cannot get size of file "));
+        rConsole.Write(pszValueData);
+        rConsole.Write(_T("\n"));
+        VERIFY(CloseHandle(hFile));
+        goto SkipCommand;
+      }
+      pDataBuffer = new BYTE [dwValueSize];
+      if (!pDataBuffer)
+      {
+        rConsole.Write(_T("Cannot load file into memory. Out of memory.\n"));
+        VERIFY(CloseHandle(hFile));
+        goto SkipCommand;
+      }
+      if (!ReadFile(hFile,pDataBuffer,dwValueSize,&dwBytesReaded,NULL))
+      {
+        rConsole.Write(_T("Cannot load file into memory. Error reading file.\n"));
+        VERIFY(CloseHandle(hFile));
+        goto SkipCommand;
+      }
 
-                               VERIFY(CloseHandle(hFile));
-                               ASSERT(dwBytesReaded == dwValueSize);
-                       }
-                       break;
-               case REG_DWORD_LITTLE_ENDIAN:
-               case REG_DWORD_BIG_ENDIAN:
-                       dwValueSize = 4;
-                       pDataBuffer = (BYTE *) new BYTE [dwValueSize];
-                       if (!StringToDWORD(*(DWORD *)pDataBuffer,pchValueData))
-                       {
-                               rConsole.Write(_T("Cannot convert "));
-                               rConsole.Write(pchValueData);
-                               rConsole.Write(_T(" to DWORD \n"));
-                               goto SkipCommand;
-                       }
-                       if (dwType == REG_DWORD_BIG_ENDIAN)
-                       {
-                               unsigned char nByte;
-                               nByte = *pDataBuffer;
-                               *pDataBuffer = *(pDataBuffer+3);
-                               *(pDataBuffer+3) = nByte;
-                               nByte = *(pDataBuffer+1);
-                               *(pDataBuffer+1) = *(pDataBuffer+2);
-                               *(pDataBuffer+2) = nByte;
-                       }
-                       break;
-               case REG_SZ:
-               case REG_EXPAND_SZ:
-                       dwValueSize = _tcslen(pchValueData)+1;
-                       if (*pchValueData == _T('\"'))
-                       {
-                               dwValueSize -= 2;
-                               *(pchValueData+dwValueSize) = 0;
-                               pchValueData++;
-                       }
-                       dwValueSize *= sizeof(TCHAR);
-                       pDataBuffer = (BYTE *) new BYTE [dwValueSize];
-                       _tcscpy((TCHAR *)pDataBuffer,pchValueData);
-                       break;
-               default:
-                       ASSERT(FALSE);
-               }
+      VERIFY(CloseHandle(hFile));
+      ASSERT(dwBytesReaded == dwValueSize);
+    }
+    break;
+  case REG_DWORD_LITTLE_ENDIAN:
+  case REG_DWORD_BIG_ENDIAN:
+    dwValueSize = 4;
+    pDataBuffer = (BYTE *) new BYTE [dwValueSize];
+    if (!StringToDWORD(*(DWORD *)pDataBuffer,pszValueData))
+    {
+      rConsole.Write(_T("Cannot convert "));
+      rConsole.Write(pszValueData);
+      rConsole.Write(_T(" to DWORD \n"));
+      goto SkipCommand;
+    }
+    if (dwType == REG_DWORD_BIG_ENDIAN)
+    {
+      unsigned char nByte;
+      nByte = *pDataBuffer;
+      *pDataBuffer = *(pDataBuffer+3);
+      *(pDataBuffer+3) = nByte;
+      nByte = *(pDataBuffer+1);
+      *(pDataBuffer+1) = *(pDataBuffer+2);
+      *(pDataBuffer+2) = nByte;
+    }
+    break;
+  case REG_SZ:
+  case REG_EXPAND_SZ:
+    dwValueSize = _tcslen(pszValueData)+1;
+    if (*pszValueData == _T('\"'))
+    {
+      dwValueSize -= 2;
+      *(pszValueData+dwValueSize) = 0;
+      pszValueData++;
+    }
+    dwValueSize *= sizeof(TCHAR);
+    pDataBuffer = (BYTE *) new BYTE [dwValueSize];
+    _tcscpy((TCHAR *)pDataBuffer,pszValueData);
+    break;
+  default:
+    ASSERT(FALSE);
+  }
 
-               if (pKey->SetValue(pchValueName,dwType,pDataBuffer,dwValueSize) != ERROR_SUCCESS)
-                       rConsole.Write(_T("Cannot set value\n"));
-       } // if (pKey)
-       else
-       {
-CommandNAonRoot:
-               rConsole.Write(SET_VALUE_CMD COMMAND_NA_ON_ROOT);
-       }
+  {
+    size_t s = _tcslen(pszValueName);
+    if (s && (pszValueName[0] == _T('\"'))&&(pszValueName[s-1] == _T('\"')))
+    {
+      pszValueName[s-1] = 0;
+      pszValueName++;
+    }
+  }
 
-SkipCommand:
-       if (pTree)
-               delete pTree;
+  nError = Key.SetValue(pszValueName,dwType,pDataBuffer,dwValueSize);
+  if (nError != ERROR_SUCCESS)
+  {
+    char Buffer[254];
+    _stprintf(Buffer,_T("Cannot set value. Error is %u\n"),(unsigned int)nError);
+    rConsole.Write(Buffer);
+  }
+  else
+  {
+    InvalidateCompletion();
+  }
 
+SkipCommand:
        if (pDataBuffer)
                delete pDataBuffer;
        return 0;
+
+CommandNAonRoot:
+  rConsole.Write(SET_VALUE_CMD COMMAND_NA_ON_ROOT);
+  return 0;
 }
 
 const TCHAR * CShellCommandSetValue::GetHelpString()
index 983fd01..05560e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ShellCommandValue.cpp,v 1.2 2000/10/24 20:17:42 narnaoud Exp $
+/* $Id: ShellCommandValue.cpp,v 1.3 2001/01/10 01:25:29 narnaoud Exp $
  *
  * regexpl - Console Registry Explorer
  *
@@ -69,7 +69,7 @@ int CShellCommandValue::Execute(CConsole &rConsole, CArgumentParser& rArguments)
        BOOL blnUnicodeDump = FALSE;
        BOOL blnBadParameter = FALSE;
        BOOL blnHelp = FALSE;
-       DWORD dwError;
+       LONG nError;
        DWORD dwValueSize;
        DWORD dwType = REG_NONE;
        BYTE *pDataBuffer = NULL;
@@ -120,10 +120,9 @@ CheckValueArgument:
                }
        }
        
-       CRegistryTree *pTree = NULL;
-       CRegistryKey *pKey = NULL;
+       CRegistryKey Key;
        TCHAR *pchValueName;
-       TCHAR *pchPath;
+       const TCHAR *pszPath;
        
        if (blnHelp)
        {
@@ -142,7 +141,7 @@ CheckValueArgument:
 
                TCHAR *pchSep = _tcsrchr(pchValueFull,_T('\\'));
                pchValueName = pchSep?(pchSep+1):(pchValueFull);
-               pchPath = pchSep?pchValueFull:NULL;
+               pszPath = pchSep?pchValueFull:_T(".");
                                
                //if (_tcsrchr(pchValueName,_T('.')))
                //{
@@ -156,271 +155,266 @@ CheckValueArgument:
        else
        {
                pchValueName = _T("");
-               pchPath = NULL;
+               pszPath = _T(".");
        }
-               
-       if (pchPath)
-       {
-               pTree = new CRegistryTree(m_rTree);
-               if ((_tcscmp(pTree->GetCurrentPath(),m_rTree.GetCurrentPath()) != 0)
-                       ||(!pTree->ChangeCurrentKey(pchPath)))
-               {
-                       rConsole.Write(_T("Cannot open key "));
-                       rConsole.Write(pchPath);
-                       rConsole.Write(_T("\n"));
-                       goto SkipValueCommand;
-               }
-               else
-               {
-                       pKey = pTree->GetCurrentKey();
-               }
-       }
-       else
-       {
-               pKey = m_rTree.GetCurrentKey();
-       }
-       
-       if (pKey)
-       {       // not root key ???
-               rConsole.Write(_T("Value name : \""));
-               rConsole.Write(_T("\\"));
-               rConsole.Write(pTree?pTree->GetCurrentPath():m_rTree.GetCurrentPath());
-               rConsole.Write(*pchValueName?pchValueName:_T("\"(Default)\""));
-               rConsole.Write(_T("\"\n"));
-               size_t l = _tcslen(pchValueName);
-               if (l&&
-                       (*pchValueName == _T('\"'))&&
-                       (pchValueName[l-1] == _T('\"')))
-               {
-                       pchValueName[l-1] = 0;
-                       pchValueName++;
-               }
-               dwError = pKey->GetValue(pchValueName,NULL,NULL,&dwValueSize);
-               if (dwError == ERROR_SUCCESS)
-               {
-                       pDataBuffer = new BYTE [dwValueSize];
-                       pKey->GetValue(pchValueName,&dwType,pDataBuffer,&dwValueSize);
-                       rConsole.Write(_T("Value type : "));
-                       rConsole.Write(CRegistryKey::GetValueTypeName(dwType));
-                       rConsole.Write(_T("\nValue data : "));
-                       switch(dwType)
-                       {
-                       case REG_DWORD_LITTLE_ENDIAN:
-                               {
-                                       TCHAR Buffer[11];
-                                       unsigned int n = *pDataBuffer;
-                                       _stprintf(Buffer,_T("0x%08X\n"),n);
-                                       rConsole.Write(Buffer);
-                               }
-                               break;
-                       case REG_DWORD_BIG_ENDIAN:
-                               {
-                                       TCHAR Buffer[3];
-                                       rConsole.Write(_T("0x"));
-                                       for (unsigned int i = 0 ; i < dwValueSize ; i++)
-                                       {
-                                               _stprintf(Buffer,_T("%02X"),*(pDataBuffer+i));
-                                               rConsole.Write(Buffer);
-                                       }
-                               }
-                               rConsole.Write(_T("\n"));
-                               break;
-                       case REG_LINK:
-                               break;
-                       case REG_MULTI_SZ:
-                               {
-                                       TCHAR *pchCurrentString = (TCHAR *)pDataBuffer;
-                                       rConsole.Write(_T("\n"));
-                                       while(*pchCurrentString)
-                                       {
-                                               rConsole.Write(_T("\""));
-                                               rConsole.Write(pchCurrentString);
-                                               rConsole.Write(_T("\"\n"));
-                                               pchCurrentString += _tcslen(pchCurrentString)+1;
-                                       }
-                               }
-                               break;
-                       case REG_RESOURCE_LIST:
-                               break;
-                       case REG_SZ:
-                       case REG_EXPAND_SZ:
-                               rConsole.Write(_T("\""));
-                               rConsole.Write((TCHAR *)pDataBuffer);
-                               rConsole.Write(_T("\"\n"));
-                               break;
-                       case REG_BINARY:
-                       default:
-                               {
-                                       TCHAR Buffer[256];
-                                       DWORD i;
-                                       for (i = 0 ; i < dwValueSize ; i++)
-                                       {
-                                               if (i%16 == 0)
-                                               {       // ok this is begining of line
-                                                       rConsole.Write(_T("\n"));
-                                                       // print offset
-                                                       _stprintf(Buffer,_T("0x%08X  "),i);
-                                                       rConsole.Write(Buffer);
-                                               }
-                                               else if (i%8 == 0)
-                                               {       // this is the additional space between 7th and 8th byte in current line
-                                                       rConsole.Write(_T(" "));
-                                               }
-
-                                               // print current byte
-                                               unsigned int n = *(pDataBuffer+i);
-                                               _stprintf(Buffer,_T("%02X "),n);
-                                               rConsole.Write(Buffer);
-
-                                               if (i && (i%16 == 15))
-                                               {       // if this is the last byte in line
-                                                       // Dump text representation
-                                                       for (DWORD j = i-15; j <= i; j += blnUnicodeDump?2:1)\
-                                                       {
-                                                               if ((j%8 == 0)&&(j%16 != 0))
-                                                               {       // this is the additional space between 7th and 8th byte in current line
-                                                                       rConsole.Write(_T(" "));
-                                                               }
-                                                               ASSERT(i-j < 16);
-                                                               // write current char representation
-                                                               if (blnUnicodeDump)
-                                                               {
-                                                                       ASSERT(j%2 == 0);
-                                                                       wchar_t ch = *(TCHAR *)(pDataBuffer+j);
-                                                                       _stprintf(Buffer,
+
+  if (!m_rTree.GetKey(pszPath,KEY_READ,Key))
+  {
+    rConsole.Write(m_rTree.GetLastErrorDescription());
+    goto SkipValueCommand;
+  }
+
+       if (Key.IsRoot())
+    goto ValueCommandNAonRoot;
+  
+  {
+    rConsole.Write(_T("Value name : \""));
+    rConsole.Write(_T("\\"));
+    rConsole.Write(Key.GetKeyName());
+    size_t l = _tcslen(pchValueName);
+    if (l&&
+        (*pchValueName == _T('\"'))&&
+        (pchValueName[l-1] == _T('\"')))
+    {
+      pchValueName[l-1] = 0;
+      pchValueName++;
+    }
+    rConsole.Write(pchValueName);
+    rConsole.Write(_T("\"\n"));
+  
+    nError = Key.GetValue(pchValueName,NULL,NULL,&dwValueSize);
+    if (nError == ERROR_SUCCESS)
+    {
+      pDataBuffer = new BYTE [dwValueSize];
+      Key.GetValue(pchValueName,&dwType,pDataBuffer,&dwValueSize);
+      rConsole.Write(_T("Value type : "));
+      rConsole.Write(CRegistryKey::GetValueTypeName(dwType));
+      rConsole.Write(_T("\nValue data : "));
+      switch(dwType)
+      {
+      case REG_DWORD_LITTLE_ENDIAN:
+        {
+          TCHAR Buffer[11];
+          unsigned int n = *pDataBuffer;
+          _stprintf(Buffer,_T("0x%08X\n"),n);
+          rConsole.Write(Buffer);
+        }
+        break;
+      case REG_DWORD_BIG_ENDIAN:
+        {
+          TCHAR Buffer[3];
+          rConsole.Write(_T("0x"));
+          for (unsigned int i = 0 ; i < dwValueSize ; i++)
+          {
+            _stprintf(Buffer,_T("%02X"),*(pDataBuffer+i));
+            rConsole.Write(Buffer);
+          }
+        }
+        rConsole.Write(_T("\n"));
+        break;
+      case REG_LINK:
+        break;
+      case REG_MULTI_SZ:
+        {
+          TCHAR *pchCurrentString = (TCHAR *)pDataBuffer;
+          rConsole.Write(_T("\n"));
+          while(*pchCurrentString)
+          {
+            rConsole.Write(_T("\""));
+            rConsole.Write(pchCurrentString);
+            rConsole.Write(_T("\"\n"));
+            pchCurrentString += _tcslen(pchCurrentString)+1;
+          }
+        }
+        break;
+      case REG_RESOURCE_LIST:
+        break;
+      case REG_SZ:
+      case REG_EXPAND_SZ:
+        rConsole.Write(_T("\""));
+        rConsole.Write((TCHAR *)pDataBuffer);
+        rConsole.Write(_T("\"\n"));
+        break;
+      case REG_BINARY:
+      default:
+        {
+          TCHAR Buffer[256];
+          DWORD i;
+          for (i = 0 ; i < dwValueSize ; i++)
+          {
+            if (i%16 == 0)
+            {  // ok this is begining of line
+              rConsole.Write(_T("\n"));
+              // print offset
+              _stprintf(Buffer,_T("0x%08X  "),(unsigned int)i);
+              rConsole.Write(Buffer);
+            }
+            else if (i%8 == 0)
+            {  // this is the additional space between 7th and 8th byte in current line
+              rConsole.Write(_T(" "));
+            }
+
+            // print current byte
+            unsigned int n = *(pDataBuffer+i);
+            _stprintf(Buffer,_T("%02X "),n);
+            rConsole.Write(Buffer);
+
+            if (i && (i%16 == 15))
+            {  // if this is the last byte in line
+              // Dump text representation
+              for (DWORD j = i-15; j <= i; j += blnUnicodeDump?2:1)\
+                  {
+                    if ((j%8 == 0)&&(j%16 != 0))
+                    {  // this is the additional space between 7th and 8th byte in current line
+                      rConsole.Write(_T(" "));
+                    }
+                    ASSERT(i-j < 16);
+                    // write current char representation
+                    if (blnUnicodeDump)
+                    {
+                      ASSERT(j%2 == 0);
+                      wchar_t ch = *(TCHAR *)(pDataBuffer+j);
+
+                      _stprintf(Buffer,
 #ifdef _UNICODE
-                                                                               _T("%c"),
+                                _T("%c"),
 #else
-                                                                               _T("%C"),
+                                // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
+                                // %C in format string is a Microsoft extension.
+                                _T("%C"),
 #endif
-                                                                               iswprint(ch)?ch:L'.');
-                                                               }
-                                                               else
-                                                               {
-                                                                       unsigned char ch = *(pDataBuffer+j);
-                                                                       _stprintf(Buffer,
+                                iswprint(ch)?ch:L'.');
+                    }
+                    else
+                    {
+                      unsigned char ch = *(pDataBuffer+j);
+
+                      _stprintf(Buffer,
 #ifdef _UNICODE
-                                                                               _T("%C"),
+                                // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
+                                // %C in format string is a Microsoft extension.
+                                _T("%C"),
 #else
-                                                                               _T("%c"),
+                                _T("%c"),
 #endif
-                                                                               isprint(ch)?ch:'.');
-                                                               }
-                                                               rConsole.Write(Buffer);
-                                                       }       // for
-                                               }       // if
-                                       }       // for
-
-                                       // print text representation of last line if it is not full (it have less than 16 bytes)
-                                       // k is pseudo offset
-                                       for (DWORD k = i; k%16 != 0; k++)
-                                       {
-                                               if (k%8 == 0)
-                                               {       // this is the additional space between 7th and 8th byte in current line
-                                                       rConsole.Write(_T(" "));
-                                               }
-                                               _tcscpy(Buffer,_T("   "));      // the replacement of two digit of current byte + spacing
-                                               rConsole.Write(Buffer);
-                                               if (k && (k%16 == 15))
-                                               {       // if this is the last byte in line
-                                                       ASSERT((k-15)%16 == 0); // k-15 must point at begin of last line
-                                                       for (DWORD j = k-15; j < i; j += j += blnUnicodeDump?2:1)
-                                                       {
-                                                               if (blnUnicodeDump&&(j+1 >= i))
-                                                               {       // ok, buffer size is odd number, so we don't display last byte.
-                                                                       ASSERT(j+1 == i);
-                                                                       break;
-                                                               }
-                                                               if ((j%8 == 0)&&(j%16 != 0))
-                                                               {       // this is the additional space between 7th and 8th byte in current line
-                                                                       rConsole.Write(_T(" "));
-                                                               }
-
-                                                               // write current char representation
-                                                               if (blnUnicodeDump)
-                                                               {
-                                                                       ASSERT(j%2 == 0);
-                                                                       wchar_t ch = *(TCHAR *)(pDataBuffer+j);
-                                                                       _stprintf(Buffer,
+                                isprint(ch)?ch:'.');
+                    }
+                    rConsole.Write(Buffer);
+                  }    // for
+            }  // if
+          }    // for
+
+          // print text representation of last line if it is not full (it have less than 16 bytes)
+          // k is pseudo offset
+          for (DWORD k = i; k%16 != 0; k++)
+          {
+            if (k%8 == 0)
+            {  // this is the additional space between 7th and 8th byte in current line
+              rConsole.Write(_T(" "));
+            }
+            _tcscpy(Buffer,_T("   ")); // the replacement of two digit of current byte + spacing
+            rConsole.Write(Buffer);
+            if (k && (k%16 == 15))
+            {  // if this is the last byte in line
+              ASSERT((k-15)%16 == 0);  // k-15 must point at begin of last line
+              for (DWORD j = k-15; j < i; j += j += blnUnicodeDump?2:1)
+              {
+                if (blnUnicodeDump&&(j+1 >= i))
+                {      // ok, buffer size is odd number, so we don't display last byte.
+                  ASSERT(j+1 == i);
+                  break;
+                }
+                if ((j%8 == 0)&&(j%16 != 0))
+                {      // this is the additional space between 7th and 8th byte in current line
+                  rConsole.Write(_T(" "));
+                }
+
+                // write current char representation
+                if (blnUnicodeDump)
+                {
+                  ASSERT(j%2 == 0);
+                  wchar_t ch = *(TCHAR *)(pDataBuffer+j);
+
+                  _stprintf(Buffer,
 #ifdef _UNICODE
-                                                                               _T("%c"),
+                            _T("%c"),
 #else
-                                                                               _T("%C"),
+                            // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
+                            // %C in format string is a Microsoft extension.
+                            _T("%C"),
 #endif
-                                                                               iswprint(ch)?ch:L'.');
-                                                               }
-                                                               else
-                                                               {
-                                                                       unsigned char ch = *(pDataBuffer+j);
-                                                                       _stprintf(Buffer,
+                            iswprint(ch)?ch:L'.');
+                }
+                else
+                {
+                  unsigned char ch = *(pDataBuffer+j);
+
+                  _stprintf(Buffer,
 #ifdef _UNICODE
-                                                                               _T("%C"),
+                            // g++ may print warnings here (warning: __wchar_t format, different type arg (arg 3))
+                            // %C in format string is a Microsoft extension.
+                            _T("%C"),
 #else
-                                                                               _T("%c"),
+                            _T("%c"),
 #endif
-                                                                               isprint(ch)?ch:'.');
-                                                               }
-                                                               rConsole.Write(Buffer);
-                                                       } // for
-                                               } // if
-                                       } // for
-                               } // default:
-                               rConsole.Write(_T("\n"));
-                       } // switch
-                       rConsole.Write(_T("\n"));
+   &nbs