fixed some more warnings
[reactos.git] / reactos / subsys / system / regedit / security.c
1 /*
2 * Regedit ACL Editor for Registry Keys
3 *
4 * Copyright (C) 2004 Thomas Weidenmueller <w3seek@reactos.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
22 #define INITGUID
23 #include <windows.h>
24 #include <tchar.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <accctrl.h>
28 #include <objbase.h>
29 #include <basetyps.h>
30 #include <unknwn.h>
31 #include "security.h"
32 #include "regproc.h"
33 #include "resource.h"
34
35 /******************************************************************************
36 Implementation of the CRegKeySecurity interface
37 ******************************************************************************/
38
39 SI_ACCESS RegAccess[] = {
40 {&GUID_NULL, KEY_ALL_ACCESS, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_FULLCONTROL), SI_ACCESS_GENERAL | SI_ACCESS_SPECIFIC},
41 {&GUID_NULL, KEY_READ, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_READ), SI_ACCESS_GENERAL},
42 {&GUID_NULL, KEY_QUERY_VALUE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_QUERYVALUE), SI_ACCESS_SPECIFIC},
43 {&GUID_NULL, KEY_SET_VALUE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_SETVALUE), SI_ACCESS_SPECIFIC},
44 {&GUID_NULL, KEY_CREATE_SUB_KEY, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_CREATESUBKEY), SI_ACCESS_SPECIFIC},
45 {&GUID_NULL, KEY_ENUMERATE_SUB_KEYS, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_ENUMERATESUBKEYS), SI_ACCESS_SPECIFIC},
46 {&GUID_NULL, KEY_NOTIFY, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_NOTIFY), SI_ACCESS_SPECIFIC},
47 {&GUID_NULL, KEY_CREATE_LINK, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_CREATELINK), SI_ACCESS_SPECIFIC},
48 {&GUID_NULL, DELETE, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_DELETE), SI_ACCESS_SPECIFIC},
49 {&GUID_NULL, WRITE_DAC, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_WRITEDAC), SI_ACCESS_SPECIFIC},
50 {&GUID_NULL, WRITE_OWNER, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_WRITEOWNER), SI_ACCESS_SPECIFIC},
51 {&GUID_NULL, READ_CONTROL, (LPWSTR)MAKEINTRESOURCE(IDS_ACCESS_READCONTROL), SI_ACCESS_SPECIFIC},
52 };
53
54 DWORD RegDefaultAccess = 1; /* KEY_READ */
55
56 GENERIC_MAPPING RegAccessMasks = {
57 KEY_READ,
58 KEY_WRITE,
59 KEY_EXECUTE,
60 KEY_ALL_ACCESS
61 };
62
63 SI_INHERIT_TYPE RegInheritTypes[] = {
64 {&GUID_NULL, 0, (LPWSTR)MAKEINTRESOURCE(IDS_INHERIT_THISKEYONLY)},
65 {&GUID_NULL, CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCE(IDS_INHERIT_THISKEYANDSUBKEYS)},
66 {&GUID_NULL, INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, (LPWSTR)MAKEINTRESOURCE(IDS_INHERIT_SUBKEYSONLY)},
67 };
68
69
70 LPREGKEYSECURITY CRegKeySecurity_fnConstructor(HANDLE Handle, SE_OBJECT_TYPE ObjectType, SI_OBJECT_INFO *ObjectInfo, BOOL *Btn)
71 {
72 LPREGKEYSECURITY obj;
73
74 obj = (LPREGKEYSECURITY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(REGKEYSECURITY));
75 if(obj != NULL)
76 {
77 obj->ref = 1;
78 obj->lpVtbl = &efvt;
79 obj->Handle = Handle;
80 obj->ObjectType = ObjectType;
81 obj->ObjectInfo = *ObjectInfo;
82 obj->Btn = Btn;
83 }
84
85 return obj;
86 }
87
88 HRESULT STDMETHODCALLTYPE
89 CRegKeySecurity_fnQueryInterface(LPREGKEYSECURITY this,
90 REFIID iid,
91 PVOID *pvObject)
92 {
93 if(IsEqualGUID(iid, &IID_IUnknown) ||
94 IsEqualGUID(iid, &IID_CRegKeySecurity))
95 {
96 *pvObject = this;
97 return S_OK;
98 }
99
100 *pvObject = NULL;
101 return E_NOINTERFACE;
102 }
103
104 ULONG STDMETHODCALLTYPE
105 CRegKeySecurity_fnAddRef(LPREGKEYSECURITY this)
106 {
107 return (ULONG)InterlockedIncrement((LONG*)&this->ref);
108 }
109
110 ULONG STDMETHODCALLTYPE
111 CRegKeySecurity_fnRelease(LPREGKEYSECURITY this)
112 {
113 ULONG rfc;
114
115 rfc = (ULONG)InterlockedDecrement((LONG*)&this->ref);
116 if(rfc == 0)
117 {
118 HeapFree(GetProcessHeap(), 0, this);
119 }
120 return rfc;
121 }
122
123 HRESULT STDMETHODCALLTYPE
124 CRegKeySecurity_fnGetObjectInformation(LPREGKEYSECURITY this,
125 PSI_OBJECT_INFO pObjectInfo)
126 {
127 *pObjectInfo = this->ObjectInfo;
128 return S_OK;
129 }
130
131 HRESULT STDMETHODCALLTYPE
132 CRegKeySecurity_fnGetSecurity(LPREGKEYSECURITY this,
133 SECURITY_INFORMATION RequestedInformation,
134 PSECURITY_DESCRIPTOR* ppSecurityDescriptor,
135 BOOL fDefault)
136 {
137 /* FIXME */
138 if(GetSecurityInfo(this->Handle, this->ObjectType, RequestedInformation, 0, 0,
139 0, 0, ppSecurityDescriptor) == ERROR_SUCCESS)
140 {
141 return S_OK;
142 }
143 else
144 {
145 return E_ACCESSDENIED;
146 }
147 }
148
149 HRESULT STDMETHODCALLTYPE
150 CRegKeySecurity_fnSetSecurity(LPREGKEYSECURITY this,
151 SECURITY_INFORMATION RequestedInformation,
152 PSECURITY_DESCRIPTOR pSecurityDescriptor)
153 {
154 /* FIXME */
155 *this->Btn = TRUE;
156 return S_OK;
157 }
158
159 HRESULT STDMETHODCALLTYPE
160 CRegKeySecurity_fnGetAccessRights(LPREGKEYSECURITY this,
161 const GUID* pguidObjectType,
162 DWORD dwFlags,
163 PSI_ACCESS* ppAccess,
164 ULONG* pcAccesses,
165 ULONG* piDefaultAccess)
166 {
167 *ppAccess = RegAccess;
168 *pcAccesses = sizeof(RegAccess) / sizeof(SI_ACCESS);
169 *piDefaultAccess = RegDefaultAccess;
170 return S_OK;
171 }
172
173 HRESULT STDMETHODCALLTYPE
174 CRegKeySecurity_fnMapGeneric(LPREGKEYSECURITY this,
175 const GUID* pguidObjectType,
176 UCHAR* pAceFlags,
177 ACCESS_MASK* pMask)
178 {
179 MapGenericMask(pMask, (PGENERIC_MAPPING)&RegAccessMasks);
180 *pMask &= ~SYNCHRONIZE;
181 return S_OK;
182 }
183
184 HRESULT STDMETHODCALLTYPE
185 CRegKeySecurity_fnGetInheritTypes(LPREGKEYSECURITY this,
186 PSI_INHERIT_TYPE* ppInheritTypes,
187 ULONG* pcInheritTypes)
188 {
189 /* FIXME */
190 if(this->ObjectInfo.dwFlags & SI_CONTAINER)
191 {
192 *ppInheritTypes = RegInheritTypes;
193 *pcInheritTypes = sizeof(RegInheritTypes) / sizeof(SI_INHERIT_TYPE);
194 return S_OK;
195 }
196 return E_NOTIMPL;
197 }
198
199 HRESULT STDMETHODCALLTYPE
200 CRegKeySecurity_fnPropertySheetPageCallback(LPREGKEYSECURITY this,
201 HWND hwnd,
202 UINT uMsg,
203 SI_PAGE_TYPE uPage)
204 {
205 /* FIXME */
206 return S_OK;
207 }
208
209
210 /******************************************************************************/
211
212 #define ACLUI_DLL _T("aclui.dll")
213 #define FN_EDITSECURITY "EditSecurity" /* no unicode, GetProcAddr doesn't accept unicode! */
214
215 typedef struct _CHANGE_CONTEXT
216 {
217 HKEY hKey;
218 LPTSTR KeyString;
219 } CHANGE_CONTEXT, *PCHANGE_CONTEXT;
220
221 typedef BOOL (WINAPI *PEDITSECURITY)(HWND hwndOwner,
222 LPREGKEYSECURITY psi);
223
224 static PEDITSECURITY pfnEditSecurity;
225 static HMODULE hAclUiDll;
226
227 BOOL
228 InitializeAclUiDll(VOID)
229 {
230 if(!(hAclUiDll = LoadLibrary(ACLUI_DLL)))
231 {
232 return FALSE;
233 }
234 if(!(pfnEditSecurity = (PEDITSECURITY)GetProcAddress(hAclUiDll, FN_EDITSECURITY)))
235 {
236 FreeLibrary(hAclUiDll);
237 hAclUiDll = NULL;
238 return FALSE;
239 }
240
241 return TRUE;
242 }
243
244 VOID
245 UnloadAclUiDll(VOID)
246 {
247 if(hAclUiDll != NULL)
248 {
249 FreeLibrary(hAclUiDll);
250 }
251 }
252
253 BOOL
254 RegKeyEditPermissions(HWND hWndOwner,
255 HKEY hKey,
256 LPCTSTR lpMachine,
257 LPCTSTR lpKeyName)
258 {
259 BOOL Result;
260 HMODULE hAclEditDll;
261 LPWSTR Machine, KeyName;
262 HKEY hInfoKey;
263 LPREGKEYSECURITY RegKeySecurity;
264 SI_OBJECT_INFO ObjectInfo;
265
266 if(pfnEditSecurity == NULL)
267 {
268 return FALSE;
269 }
270
271 #ifndef UNICODE
272 /* aclui.dll only accepts unicode strings, convert them */
273 if(lpMachine != NULL)
274 {
275 int lnMachine = lstrlen(lpMachine);
276 if(!(Machine = HeapAlloc(GetProcessHeap(), 0, (lnMachine + 1) * sizeof(WCHAR))))
277 {
278 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
279 return FALSE;
280 }
281 if(lnMachine > 0)
282 {
283 MultiByteToWideChar(CP_ACP, 0, lpMachine, -1, Machine, lnMachine + 1);
284 }
285 else
286 *Machine = L'\0';
287 }
288 else
289 Machine = NULL;
290
291 if(lpKeyName != NULL)
292 {
293 int lnKeyName = lstrlen(lpKeyName);
294 if(!(KeyName = HeapAlloc(GetProcessHeap(), 0, (lnKeyName + 1) * sizeof(WCHAR))))
295 {
296 if(Machine != NULL)
297 {
298 HeapFree(GetProcessHeap(), 0, Machine);
299 }
300 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
301 return FALSE;
302 }
303 if(lnKeyName > 0)
304 {
305 MultiByteToWideChar(CP_ACP, 0, lpKeyName, -1, KeyName, lnKeyName + 1);
306 }
307 else
308 *KeyName = L'\0';
309 }
310 else
311 KeyName = NULL;
312 #else
313 Machine = (LPWSTR)lpMachine;
314 KeyName = (LPWSTR)lpKeyName;
315 #endif
316
317 /* try to open the key again with more access rights */
318 if(RegOpenKeyEx(hKey, NULL, 0, READ_CONTROL, &hInfoKey) != ERROR_SUCCESS)
319 {
320 /* FIXME - print error with FormatMessage */
321 return FALSE;
322 }
323
324 ObjectInfo.dwFlags = SI_EDIT_ALL | SI_ADVANCED | SI_CONTAINER | SI_OWNER_RECURSE | SI_EDIT_PERMS;
325 ObjectInfo.hInstance = hInst;
326 ObjectInfo.pszServerName = Machine;
327 ObjectInfo.pszObjectName = KeyName;
328 ObjectInfo.pszPageTitle = KeyName;
329
330 if(!(RegKeySecurity = CRegKeySecurity_fnConstructor(hInfoKey, SE_REGISTRY_KEY, &ObjectInfo, &Result)))
331 {
332 /* FIXME - print error with FormatMessage */
333 return FALSE;
334 }
335
336 /* display the security editor dialog */
337 pfnEditSecurity(hWndOwner, RegKeySecurity);
338
339 /* dereference the interface, it should be destroyed here */
340 CRegKeySecurity_fnRelease(RegKeySecurity);
341
342 RegCloseKey(hInfoKey);
343
344 #ifndef UNICODE
345 if(Machine != NULL)
346 {
347 HeapFree(GetProcessHeap(), 0, Machine);
348 }
349 if(KeyName != NULL)
350 {
351 HeapFree(GetProcessHeap(), 0, KeyName);
352 }
353 #endif
354
355 return Result;
356 }
357
358 /* EOF */