be409b899ebe0ed605b9e70da402abde67dd021a
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
1
2 /*
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/namespc.c
6 * PURPOSE: Manages the system namespace
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * 22/05/98: Created
10 */
11
12 /* INCLUDES ***************************************************************/
13
14 #include <limits.h>
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/io.h>
18 #include <internal/pool.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS ****************************************************************/
24
25 POBJECT_TYPE ObDirectoryType = NULL;
26
27 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
28
29 static GENERIC_MAPPING ObpDirectoryMapping = {
30 STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
31 STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
32 STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
33 DIRECTORY_ALL_ACCESS};
34
35 /* FUNCTIONS **************************************************************/
36
37 NTSTATUS STDCALL
38 ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
39 ULONG Attributes,
40 PACCESS_STATE PassedAccessState,
41 ACCESS_MASK DesiredAccess,
42 POBJECT_TYPE ObjectType,
43 KPROCESSOR_MODE AccessMode,
44 PVOID ParseContext,
45 PVOID* ObjectPtr)
46 {
47 PVOID Object = NULL;
48 UNICODE_STRING RemainingPath;
49 OBJECT_ATTRIBUTES ObjectAttributes;
50 NTSTATUS Status;
51
52 InitializeObjectAttributes(&ObjectAttributes,
53 ObjectPath,
54 Attributes,
55 NULL,
56 NULL);
57 Status = ObFindObject(&ObjectAttributes,
58 &Object,
59 &RemainingPath,
60 ObjectType);
61 if (!NT_SUCCESS(Status))
62 {
63 return(Status);
64 }
65 CHECKPOINT;
66 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
67
68 if (RemainingPath.Buffer != NULL || Object == NULL)
69 {
70 CHECKPOINT;
71 DPRINT("Object %p\n", Object);
72 *ObjectPtr = NULL;
73 RtlFreeUnicodeString (&RemainingPath);
74 return(STATUS_UNSUCCESSFUL);
75 }
76 *ObjectPtr = Object;
77 RtlFreeUnicodeString (&RemainingPath);
78 return(STATUS_SUCCESS);
79 }
80
81
82 /**********************************************************************
83 * NAME EXPORTED
84 * ObOpenObjectByName
85 *
86 * DESCRIPTION
87 * Obtain a handle to an existing object.
88 *
89 * ARGUMENTS
90 * ObjectAttributes
91 * ...
92 * ObjectType
93 * ...
94 * ParseContext
95 * ...
96 * AccessMode
97 * ...
98 * DesiredAccess
99 * ...
100 * PassedAccessState
101 * ...
102 * Handle
103 * Handle to close.
104 *
105 * RETURN VALUE
106 * Status.
107 */
108 NTSTATUS STDCALL
109 ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes,
110 POBJECT_TYPE ObjectType,
111 PVOID ParseContext,
112 KPROCESSOR_MODE AccessMode,
113 ACCESS_MASK DesiredAccess,
114 PACCESS_STATE PassedAccessState,
115 PHANDLE Handle)
116 {
117 UNICODE_STRING RemainingPath;
118 PVOID Object = NULL;
119 NTSTATUS Status;
120
121 DPRINT("ObOpenObjectByName()\n");
122
123 Status = ObFindObject(ObjectAttributes,
124 &Object,
125 &RemainingPath,
126 ObjectType);
127 if (!NT_SUCCESS(Status))
128 {
129 return Status;
130 }
131
132 if (RemainingPath.Buffer != NULL ||
133 Object == NULL)
134 {
135 RtlFreeUnicodeString(&RemainingPath);
136 return STATUS_UNSUCCESSFUL;
137 }
138
139 Status = ObCreateHandle(PsGetCurrentProcess(),
140 Object,
141 DesiredAccess,
142 FALSE,
143 Handle);
144
145 ObDereferenceObject(Object);
146 RtlFreeUnicodeString(&RemainingPath);
147
148 return Status;
149 }
150
151
152 VOID STDCALL ObAddEntryDirectory(PDIRECTORY_OBJECT Parent,
153 POBJECT Object,
154 PWSTR Name)
155 /*
156 * FUNCTION: Add an entry to a namespace directory
157 * ARGUMENTS:
158 * parent = directory to add in
159 * name = Name to give the entry
160 * Object = Header of the object to add the entry for
161 */
162 {
163 KIRQL oldlvl;
164 POBJECT_HEADER Header = BODY_TO_HEADER(Object);
165
166 RtlCreateUnicodeString(&Header->Name, Name);
167 Header->Parent = Parent;
168
169 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
170 InsertTailList(&Parent->head, &Header->Entry);
171 KeReleaseSpinLock(&Parent->Lock, oldlvl);
172 }
173
174 PVOID ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
175 PWSTR Name,
176 ULONG Attributes)
177 {
178 PLIST_ENTRY current = DirectoryObject->head.Flink;
179 POBJECT_HEADER current_obj;
180
181 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
182
183 if (Name[0]==0)
184 {
185 return(DirectoryObject);
186 }
187 if (Name[0]=='.' && Name[1]==0)
188 {
189 return(DirectoryObject);
190 }
191 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
192 {
193 return(BODY_TO_HEADER(DirectoryObject)->Parent);
194 }
195 while (current!=(&(DirectoryObject->head)))
196 {
197 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
198 DPRINT("Scanning %S %S\n",current_obj->Name.Buffer, Name);
199 if (Attributes & OBJ_CASE_INSENSITIVE)
200 {
201 if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
202 {
203 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
204 return(HEADER_TO_BODY(current_obj));
205 }
206 }
207 else
208 {
209 if ( wcscmp(current_obj->Name.Buffer, Name)==0)
210 {
211 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
212 return(HEADER_TO_BODY(current_obj));
213 }
214 }
215 current = current->Flink;
216 }
217 DPRINT("%s() = NULL\n",__FUNCTION__);
218 return(NULL);
219 }
220
221 NTSTATUS
222 ObpParseDirectory (
223 PVOID Object,
224 PVOID * NextObject,
225 PUNICODE_STRING FullPath,
226 PWSTR * Path,
227 POBJECT_TYPE ObjectType
228 )
229 {
230 PWSTR end;
231 PVOID FoundObject;
232
233 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
234 Object,Path,*Path);
235
236 *NextObject = NULL;
237
238 if ((*Path) == NULL)
239 {
240 return STATUS_UNSUCCESSFUL;
241 }
242
243 end = wcschr((*Path)+1, '\\');
244 if (end != NULL)
245 {
246 *end = 0;
247 }
248
249 FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, 0);
250
251 if (FoundObject == NULL)
252 {
253 if (end != NULL)
254 {
255 *end = '\\';
256 }
257 return STATUS_UNSUCCESSFUL;
258 }
259
260 ObReferenceObjectByPointer(FoundObject,
261 STANDARD_RIGHTS_REQUIRED,
262 NULL,
263 UserMode);
264
265 if (end != NULL)
266 {
267 *end = '\\';
268 *Path = end;
269 }
270 else
271 {
272 *Path = NULL;
273 }
274
275 *NextObject = FoundObject;
276
277 return STATUS_SUCCESS;
278 }
279
280 NTSTATUS ObpCreateDirectory(PVOID ObjectBody,
281 PVOID Parent,
282 PWSTR RemainingPath,
283 POBJECT_ATTRIBUTES ObjectAttributes)
284 {
285 PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
286
287 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
288 ObjectBody, Parent, RemainingPath);
289
290 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
291 {
292 return(STATUS_UNSUCCESSFUL);
293 }
294
295 if (Parent != NULL && RemainingPath != NULL)
296 {
297 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
298 }
299 InitializeListHead(&DirectoryObject->head);
300 KeInitializeSpinLock(&DirectoryObject->Lock);
301 return(STATUS_SUCCESS);
302 }
303
304 VOID ObInit(VOID)
305 /*
306 * FUNCTION: Initialize the object manager namespace
307 */
308 {
309 ANSI_STRING AnsiString;
310
311 ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
312
313 ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
314 ObDirectoryType->TotalObjects = 0;
315 ObDirectoryType->TotalHandles = 0;
316 ObDirectoryType->MaxObjects = ULONG_MAX;
317 ObDirectoryType->MaxHandles = ULONG_MAX;
318 ObDirectoryType->PagedPoolCharge = 0;
319 ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
320 ObDirectoryType->Mapping = &ObpDirectoryMapping;
321 ObDirectoryType->Dump = NULL;
322 ObDirectoryType->Open = NULL;
323 ObDirectoryType->Close = NULL;
324 ObDirectoryType->Delete = NULL;
325 ObDirectoryType->Parse = ObpParseDirectory;
326 ObDirectoryType->Security = NULL;
327 ObDirectoryType->QueryName = NULL;
328 ObDirectoryType->OkayToClose = NULL;
329 ObDirectoryType->Create = ObpCreateDirectory;
330
331 RtlInitAnsiString(&AnsiString,"Directory");
332 RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName,
333 &AnsiString,TRUE);
334
335 NameSpaceRoot = ObCreateObject(NULL,
336 STANDARD_RIGHTS_REQUIRED,
337 NULL,
338 ObDirectoryType);
339 }
340
341 VOID ObRemoveEntry(POBJECT_HEADER Header)
342 {
343 KIRQL oldlvl;
344
345 DPRINT("ObRemoveEntry(Header %x)\n",Header);
346
347 KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
348 RemoveEntryList(&(Header->Entry));
349 KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
350 }
351