1 /*
2  * regexpl - Console Registry Explorer
3  *
4  * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 // ShellCommandOwner.cpp: implementation of the CShellCommandOwner class.
23 //
24 //////////////////////////////////////////////////////////////////////
25 
26 #include "ph.h"
27 #include "ShellCommandOwner.h"
28 #include "RegistryExplorer.h"
29 #include "SecurityDescriptor.h"
30 
31 #define OWNER_CMD			_T("OWNER")
32 #define OWNER_CMD_LENGTH	COMMAND_LENGTH(OWNER_CMD)
33 #define OWNER_CMD_SHORT_DESC	OWNER_CMD _T(" command is used to view")/*"/change"*/_T(" key's owner.\n")
34 
35 //////////////////////////////////////////////////////////////////////
36 // Construction/Destruction
37 //////////////////////////////////////////////////////////////////////
38 
39 CShellCommandOwner::CShellCommandOwner(CRegistryTree& rTree):m_rTree(rTree)
40 {
41 }
42 
43 CShellCommandOwner::~CShellCommandOwner()
44 {
45 }
46 
47 BOOL CShellCommandOwner::Match(const TCHAR *pchCommand)
48 {
49 	if (_tcsicmp(pchCommand,OWNER_CMD) == 0)
50 		return TRUE;
51 	if (_tcsnicmp(pchCommand,OWNER_CMD _T(".."),OWNER_CMD_LENGTH+2*sizeof(TCHAR)) == 0)
52 		return TRUE;
53 	if (_tcsnicmp(pchCommand,OWNER_CMD _T("/") ,OWNER_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
54 		return TRUE;
55 	if (_tcsnicmp(pchCommand,OWNER_CMD _T("\\"),OWNER_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
56 		return TRUE;
57 	return FALSE;
58 }
59 
60 int CShellCommandOwner::Execute(CConsole &rConsole, CArgumentParser& rArguments)
61 {
62 	const TCHAR *pchKey = NULL;
63 	BOOL blnDo = TRUE;
64 	BOOL blnBadParameter = FALSE;
65 	BOOL blnHelp = FALSE;
66 	const TCHAR *pchParameter;
67 	DWORD dwError;
68 
69 	rArguments.ResetArgumentIteration();
70 	const TCHAR *pchCommandItself = rArguments.GetNextArgument();
71 
72 	if ((_tcsnicmp(pchCommandItself,OWNER_CMD _T(".."),OWNER_CMD_LENGTH+2*sizeof(TCHAR)) == 0)||
73 		(_tcsnicmp(pchCommandItself,OWNER_CMD _T("\\"),OWNER_CMD_LENGTH+1*sizeof(TCHAR)) == 0))
74 	{
75 		pchKey = pchCommandItself + OWNER_CMD_LENGTH;
76 	}
77 	else if (_tcsnicmp(pchCommandItself,OWNER_CMD _T("/"),OWNER_CMD_LENGTH+1*sizeof(TCHAR)) == 0)
78 	{
79 		pchParameter = pchCommandItself + OWNER_CMD_LENGTH;
80 		goto CheckOwnerArgument;
81 	}
82 
83 	while((pchParameter = rArguments.GetNextArgument()) != NULL)
84 	{
85 CheckOwnerArgument:
86 		blnBadParameter = FALSE;
87 		if ((_tcsicmp(pchParameter,_T("/?")) == 0)
88 			||(_tcsicmp(pchParameter,_T("-?")) == 0))
89 		{
90 			blnHelp = TRUE;
91 			blnDo = pchKey != NULL;
92 		}
93 		else if (!pchKey)
94 		{
95 			pchKey = pchParameter;
96 			blnDo = TRUE;
97 		}
98 		else
99 		{
100 			blnBadParameter = TRUE;
101 		}
102 		if (blnBadParameter)
103 		{
104 			rConsole.Write(_T("Bad parameter: "));
105 			rConsole.Write(pchParameter);
106 			rConsole.Write(_T("\n"));
107 		}
108 	}
109 
110 	CRegistryKey Key;
111 
112   if (!m_rTree.GetKey(pchKey?pchKey:_T("."),KEY_QUERY_VALUE|READ_CONTROL,Key))
113   {
114     rConsole.Write(m_rTree.GetLastErrorDescription());
115     blnDo = FALSE;
116   }
117 
118 	if (blnHelp)
119 	{
120 		rConsole.Write(GetHelpString());
121 	}
122 
123 	if (blnDo&&blnHelp) rConsole.Write(_T("\n"));
124 
125 	if (!blnDo)
126     return 0;
127 
128   if (Key.IsRoot())
129   {	// root key
130     rConsole.Write(OWNER_CMD COMMAND_NA_ON_ROOT);
131     return 0;
132   }
133 
134   PISECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
135   TCHAR *pchName = NULL, *pchDomainName = NULL;
136   try
137   {
138     DWORD dwSecurityDescriptorLength;
139     rConsole.Write(_T("Key : "));
140     rConsole.Write(_T("\\"));
141     rConsole.Write(Key.GetKeyName());
142     rConsole.Write(_T("\n"));
143     dwError = Key.GetSecurityDescriptorLength(&dwSecurityDescriptorLength);
144     if (dwError != ERROR_SUCCESS) throw dwError;
145 
146     pSecurityDescriptor = (PISECURITY_DESCRIPTOR) new unsigned char [dwSecurityDescriptorLength];
147     DWORD dwSecurityDescriptorLength1 = dwSecurityDescriptorLength;
148     dwError = Key.GetSecurityDescriptor((SECURITY_INFORMATION)OWNER_SECURITY_INFORMATION,pSecurityDescriptor,&dwSecurityDescriptorLength1);
149     if (dwError != ERROR_SUCCESS) throw dwError;
150     PSID psidOwner;
151     BOOL blnOwnerDefaulted;
152     if (!GetSecurityDescriptorOwner(pSecurityDescriptor,&psidOwner,&blnOwnerDefaulted))
153       throw GetLastError();
154     if (psidOwner == NULL)
155     {
156       rConsole.Write(_T("Key has no owner."));
157     }
158     else
159     {
160       if (!IsValidSid(psidOwner))
161       {
162         rConsole.Write(_T("Key has invalid owner SID."));
163       }
164       else
165       {
166         rConsole.Write(_T("Key Owner: \n"));
167         DWORD dwSIDStringSize = 0;
168         BOOL blnRet = GetTextualSid(psidOwner,NULL,&dwSIDStringSize);
169         ASSERT(!blnRet);
170         ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
171         TCHAR *pchSID = new TCHAR[dwSIDStringSize];
172         if(!GetTextualSid(psidOwner,pchSID,&dwSIDStringSize))
173         {
174           dwError = GetLastError();
175           ASSERT(dwError != ERROR_INSUFFICIENT_BUFFER);
176           rConsole.Write(_T("Error "));
177           TCHAR Buffer[256];
178           rConsole.Write(_itoa(dwError,Buffer,10));
179           rConsole.Write(_T("\nGetting string representation of SID\n"));
180         }
181         else
182         {
183           rConsole.Write(_T("\tSID: "));
184           rConsole.Write(pchSID);
185           rConsole.Write(_T("\n"));
186         }
187         delete [] pchSID;
188         DWORD dwNameBufferLength, dwDomainNameBufferLength;
189         dwNameBufferLength = 1024;
190         dwDomainNameBufferLength = 1024;
191         pchName = new TCHAR [dwNameBufferLength];
192         pchDomainName = new TCHAR [dwDomainNameBufferLength];
193         DWORD dwNameLength = dwNameBufferLength, dwDomainNameLength = dwDomainNameBufferLength;
194         SID_NAME_USE Use;
195         if (!LookupAccountSid(NULL,psidOwner,pchName,&dwNameLength,pchDomainName,&dwDomainNameLength,&Use))
196           throw GetLastError();
197         else
198         {
199           rConsole.Write(_T("\tOwner Domain: "));
200           rConsole.Write(pchDomainName);
201           rConsole.Write(_T("\n"));
202           rConsole.Write(_T("\tOwner Name: "));
203           rConsole.Write(pchName);
204           rConsole.Write(_T("\n\tSID type: "));
205           rConsole.Write(GetSidTypeName(Use));
206           rConsole.Write(_T("\n"));
207           rConsole.Write(_T("\tOwner defaulted: "));
208           rConsole.Write(blnOwnerDefaulted?_T("Yes"):_T("No"));
209           rConsole.Write(_T("\n"));
210         }
211         delete [] pchName;
212         pchName = NULL;
213         delete [] pchDomainName;
214         pchDomainName = NULL;
215 
216       }
217     }
218     delete [] pSecurityDescriptor;
219   }
220   catch (DWORD dwError)
221   {
222     rConsole.Write(_T("Error "));
223     TCHAR Buffer[256];
224     rConsole.Write(_itoa(dwError,Buffer,10));
225     rConsole.Write(_T("\n"));
226     if (pchName) delete [] pchName;
227     if (pchDomainName) delete [] pchDomainName;
228     if (pSecurityDescriptor) delete [] pSecurityDescriptor;
229   }
230 
231 	return 0;
232 }
233 
234 const TCHAR * CShellCommandOwner::GetHelpString()
235 {
236 	return OWNER_CMD_SHORT_DESC
237 			_T("Syntax: ") OWNER_CMD _T(" [<KEY>] [/?]\n\n")
238 			_T("    <KEY> - Optional relative path of desired key.\n")
239 			_T("    /?    - This help.\n\n")
240 			_T("Without parameters, command displays information about owner of current key.\n");
241 }
242 
243 const TCHAR * CShellCommandOwner::GetHelpShortDescriptionString()
244 {
245 	return OWNER_CMD_SHORT_DESC;
246 }
247 
248