1171ffc86fb74b73bc3bb7953be197ff39e477aa
[reactos.git] / reactos / ntoskrnl / cm / regobj.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/regobj.c
5 * PURPOSE: Registry object manipulation routines.
6 * UPDATE HISTORY:
7 */
8
9 #include <ddk/ntddk.h>
10 #include <internal/config.h>
11 #include <internal/ob.h>
12 #include <limits.h>
13 #include <string.h>
14 #include <internal/pool.h>
15 #include <internal/registry.h>
16
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 #include "cm.h"
21
22 extern POBJECT_TYPE CmiKeyType;
23 extern KSPIN_LOCK CmiKeyListLock;
24
25 NTSTATUS STDCALL
26 CmiObjectParse(PVOID ParsedObject,
27 PVOID *NextObject,
28 PUNICODE_STRING FullPath,
29 PWSTR *Path,
30 POBJECT_TYPE ObjectType,
31 ULONG Attributes)
32 {
33 CHAR cPath[MAX_PATH];
34 PWSTR end;
35 PKEY_OBJECT FoundObject;
36 PKEY_OBJECT ParsedKey=ParsedObject;
37 PKEY_BLOCK SubKeyBlock;
38 BLOCK_OFFSET BlockOffset;
39 NTSTATUS Status;
40 *NextObject = NULL;
41 if ((*Path) == NULL)
42 {
43 return STATUS_UNSUCCESSFUL;
44 }
45
46 if((*Path[0])=='\\')
47 {
48 end = wcschr((*Path)+1, '\\');
49 if (end != NULL)
50 *end = 0;
51 wcstombs(cPath,(*Path)+1,wcslen((*Path)+1));
52 cPath[wcslen( (*Path)+1)]=0;
53 }
54 else
55 {
56 end = wcschr((*Path), '\\');
57 if (end != NULL)
58 *end = 0;
59 wcstombs(cPath,(*Path),wcslen((*Path)));
60 cPath[wcslen( (*Path))]=0;
61 }
62
63 FoundObject = CmiScanKeyList(ParsedKey,cPath,Attributes);
64 if (FoundObject == NULL)
65 {
66 Status = CmiScanForSubKey(ParsedKey->RegistryFile,
67 ParsedKey->KeyBlock,
68 &SubKeyBlock,
69 &BlockOffset,
70 cPath,
71 0,
72 Attributes);
73 if(!NT_SUCCESS(Status) || SubKeyBlock == NULL)
74 {
75 if (end != NULL)
76 {
77 *end = '\\';
78 }
79 return STATUS_UNSUCCESSFUL;
80 }
81 /* Create new key object and put into linked list */
82 DPRINT("CmiObjectParse %s\n",cPath);
83 Status = ObCreateObject(NULL,
84 STANDARD_RIGHTS_REQUIRED,
85 NULL,
86 CmiKeyType,
87 (PVOID*)&FoundObject);
88 if (!NT_SUCCESS(Status))
89 {
90 return(Status);
91 }
92 FoundObject->Flags = 0;
93 FoundObject->Name = SubKeyBlock->Name;
94 FoundObject->NameSize = SubKeyBlock->NameSize;
95 FoundObject->KeyBlock = SubKeyBlock;
96 FoundObject->BlockOffset = BlockOffset;
97 FoundObject->RegistryFile = ParsedKey->RegistryFile;
98 CmiAddKeyToList(ParsedKey,FoundObject);
99 }
100 else
101 ObReferenceObjectByPointer(FoundObject,
102 STANDARD_RIGHTS_REQUIRED,
103 NULL,
104 UserMode);
105 DPRINT("CmiObjectParse %s\n",FoundObject->Name);
106 if (end != NULL)
107 {
108 *end = '\\';
109 *Path = end;
110 }
111 else
112 {
113 *Path = NULL;
114 }
115
116 *NextObject = FoundObject;
117
118 return STATUS_SUCCESS;
119 }
120
121 NTSTATUS STDCALL
122 CmiObjectCreate(PVOID ObjectBody,
123 PVOID Parent,
124 PWSTR RemainingPath,
125 struct _OBJECT_ATTRIBUTES* ObjectAttributes)
126 {
127 PKEY_OBJECT pKey=ObjectBody;
128 pKey->ParentKey = Parent;
129 if (RemainingPath)
130 {
131 if(RemainingPath[0]== L'\\')
132 {
133 pKey->Name = (PCHAR) (&RemainingPath[1]);
134 pKey->NameSize = wcslen(RemainingPath)-1;
135 }
136 else
137 {
138 pKey->Name = (PCHAR) RemainingPath;
139 pKey->NameSize = wcslen(RemainingPath);
140 }
141 }
142 else
143 pKey->NameSize = 0;
144
145 return STATUS_SUCCESS;
146 }
147
148 VOID STDCALL
149 CmiObjectDelete(PVOID DeletedObject)
150 {
151 PKEY_OBJECT KeyObject;
152
153 DPRINT("delete object key\n");
154 KeyObject = (PKEY_OBJECT) DeletedObject;
155 if(!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
156 {
157 DPRINT1("Key not found in parent list ???\n");
158 }
159 if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
160 {
161 DPRINT1("delete really key\n");
162 CmiDestroyBlock(KeyObject->RegistryFile,
163 KeyObject->KeyBlock,
164 KeyObject->BlockOffset);
165 }
166 else
167 {
168 CmiReleaseBlock(KeyObject->RegistryFile,
169 KeyObject->KeyBlock);
170 }
171 }
172
173 void
174 CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey)
175 {
176 KIRQL OldIrql;
177
178 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
179 if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
180 {
181 PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool
182 , (ParentKey->NumberOfSubKeys+1) * sizeof(DWORD));
183 if(ParentKey->NumberOfSubKeys > 0)
184 memcpy(tmpSubKeys,ParentKey->SubKeys
185 ,ParentKey->NumberOfSubKeys*sizeof(DWORD));
186 if(ParentKey->SubKeys) ExFreePool(ParentKey->SubKeys);
187 ParentKey->SubKeys=tmpSubKeys;
188 ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys+1;
189 }
190 /* FIXME : please maintain the list in alphabetic order */
191 /* to allow a dichotomic search */
192 ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
193 ObReferenceObjectByPointer(ParentKey,
194 STANDARD_RIGHTS_REQUIRED,
195 NULL,
196 UserMode);
197 NewKey->ParentKey = ParentKey;
198 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
199 }
200
201 NTSTATUS
202 CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
203 {
204 KIRQL OldIrql;
205 PKEY_OBJECT ParentKey;
206 DWORD Index;
207
208 ParentKey=KeyToRemove->ParentKey;
209 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
210 /* FIXME : if list maintained in alphabetic order, use dichotomic search */
211 for (Index=0; Index < ParentKey->NumberOfSubKeys; Index++)
212 {
213 if(ParentKey->SubKeys[Index] == KeyToRemove)
214 {
215 if (Index < ParentKey->NumberOfSubKeys-1)
216 memmove(&ParentKey->SubKeys[Index]
217 ,&ParentKey->SubKeys[Index+1]
218 ,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT));
219 ParentKey->NumberOfSubKeys--;
220 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
221 ObDereferenceObject(ParentKey);
222 return STATUS_SUCCESS;
223 }
224 }
225 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
226 return STATUS_UNSUCCESSFUL;
227 }
228
229 PKEY_OBJECT
230 CmiScanKeyList(PKEY_OBJECT Parent,
231 PCHAR KeyName,
232 ULONG Attributes)
233 {
234 KIRQL OldIrql;
235 PKEY_OBJECT CurKey;
236 DWORD Index;
237 WORD NameSize;
238 NameSize=strlen(KeyName);
239 KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
240 /* FIXME : if list maintained in alphabetic order, use dichotomic search */
241 for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
242 {
243 CurKey=Parent->SubKeys[Index];
244 if (Attributes & OBJ_CASE_INSENSITIVE)
245 {
246 if( NameSize == CurKey->NameSize
247 && !_strnicmp(KeyName,CurKey->Name,NameSize))
248 {
249 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
250 return CurKey;
251 }
252 }
253 else
254 {
255 if( NameSize == CurKey->NameSize
256 && !strncmp(KeyName,CurKey->Name,NameSize))
257 {
258 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
259 return CurKey;
260 }
261 }
262 }
263 KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
264
265 return NULL;
266 }