Branch setupapi
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
1 /* $Id$
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 <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18
19 /* GLOBALS ****************************************************************/
20
21 POBJECT_TYPE ObDirectoryType = NULL;
22 POBJECT_TYPE ObTypeObjectType = NULL;
23
24 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
25 /* FIXME: Move this somewhere else once devicemap support is in */
26 PDEVICE_MAP ObSystemDeviceMap = NULL;
27
28 static GENERIC_MAPPING ObpDirectoryMapping = {
29 STANDARD_RIGHTS_READ|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
30 STANDARD_RIGHTS_WRITE|DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY,
31 STANDARD_RIGHTS_EXECUTE|DIRECTORY_QUERY|DIRECTORY_TRAVERSE,
32 DIRECTORY_ALL_ACCESS};
33
34 static GENERIC_MAPPING ObpTypeMapping = {
35 STANDARD_RIGHTS_READ,
36 STANDARD_RIGHTS_WRITE,
37 STANDARD_RIGHTS_EXECUTE,
38 0x000F0001};
39
40 /* FUNCTIONS **************************************************************/
41
42 /*
43 * @implemented
44 */
45 NTSTATUS STDCALL
46 ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
47 ULONG Attributes,
48 PACCESS_STATE PassedAccessState,
49 ACCESS_MASK DesiredAccess,
50 POBJECT_TYPE ObjectType,
51 KPROCESSOR_MODE AccessMode,
52 PVOID ParseContext,
53 PVOID* ObjectPtr)
54 {
55 PVOID Object = NULL;
56 UNICODE_STRING RemainingPath;
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 NTSTATUS Status;
59
60 InitializeObjectAttributes(&ObjectAttributes,
61 ObjectPath,
62 Attributes,
63 NULL,
64 NULL);
65 Status = ObFindObject(&ObjectAttributes,
66 &Object,
67 &RemainingPath,
68 ObjectType);
69 if (!NT_SUCCESS(Status))
70 {
71 return(Status);
72 }
73 CHECKPOINT;
74 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath.Buffer, Object);
75
76 if (RemainingPath.Buffer != NULL || Object == NULL)
77 {
78 CHECKPOINT;
79 DPRINT("Object %p\n", Object);
80 *ObjectPtr = NULL;
81 RtlFreeUnicodeString (&RemainingPath);
82 return(STATUS_OBJECT_NAME_NOT_FOUND);
83 }
84 *ObjectPtr = Object;
85 RtlFreeUnicodeString (&RemainingPath);
86 return(STATUS_SUCCESS);
87 }
88
89
90 /**********************************************************************
91 * NAME EXPORTED
92 * ObOpenObjectByName
93 *
94 * DESCRIPTION
95 * Obtain a handle to an existing object.
96 *
97 * ARGUMENTS
98 * ObjectAttributes
99 * ...
100 * ObjectType
101 * ...
102 * ParseContext
103 * ...
104 * AccessMode
105 * ...
106 * DesiredAccess
107 * ...
108 * PassedAccessState
109 * ...
110 * Handle
111 * Handle to close.
112 *
113 * RETURN VALUE
114 * Status.
115 *
116 * @implemented
117 */
118 NTSTATUS STDCALL
119 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
120 IN POBJECT_TYPE ObjectType,
121 IN OUT PVOID ParseContext,
122 IN KPROCESSOR_MODE AccessMode,
123 IN ACCESS_MASK DesiredAccess,
124 IN PACCESS_STATE PassedAccessState,
125 OUT PHANDLE Handle)
126 {
127 UNICODE_STRING RemainingPath;
128 PVOID Object = NULL;
129 NTSTATUS Status;
130
131 DPRINT("ObOpenObjectByName(...)\n");
132
133 Status = ObFindObject(ObjectAttributes,
134 &Object,
135 &RemainingPath,
136 ObjectType);
137 if (!NT_SUCCESS(Status))
138 {
139 DPRINT("ObFindObject() failed (Status %lx)\n", Status);
140 return Status;
141 }
142
143 if (RemainingPath.Buffer != NULL ||
144 Object == NULL)
145 {
146 RtlFreeUnicodeString(&RemainingPath);
147 return STATUS_UNSUCCESSFUL;
148 }
149
150 Status = ObCreateHandle(PsGetCurrentProcess(),
151 Object,
152 DesiredAccess,
153 FALSE,
154 Handle);
155
156 ObDereferenceObject(Object);
157 RtlFreeUnicodeString(&RemainingPath);
158
159 return Status;
160 }
161
162 VOID
163 STDCALL
164 ObQueryDeviceMapInformation(PEPROCESS Process,
165 PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
166 {
167 //KIRQL OldIrql ;
168
169 /*
170 * FIXME: This is an ugly hack for now, to always return the System Device Map
171 * instead of returning the Process Device Map. Not important yet since we don't use it
172 */
173
174 /* FIXME: Acquire the DeviceMap Spinlock */
175 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
176
177 /* Make a copy */
178 DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
179 RtlMoveMemory(DeviceMapInfo->Query.DriveType, ObSystemDeviceMap->DriveType, sizeof(ObSystemDeviceMap->DriveType));
180
181 /* FIXME: Release the DeviceMap Spinlock */
182 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
183 }
184
185 VOID
186 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
187 POBJECT_HEADER Header,
188 PWSTR Name)
189 /*
190 * FUNCTION: Add an entry to a namespace directory
191 * ARGUMENTS:
192 * Parent = directory to add in
193 * Header = Header of the object to add the entry for
194 * Name = Name to give the entry
195 */
196 {
197 KIRQL oldlvl;
198
199 RtlCreateUnicodeString(&Header->Name, Name);
200 Header->Parent = Parent;
201
202 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
203 InsertTailList(&Parent->head, &Header->Entry);
204 KeReleaseSpinLock(&Parent->Lock, oldlvl);
205 }
206
207
208 VOID
209 ObpRemoveEntryDirectory(POBJECT_HEADER Header)
210 /*
211 * FUNCTION: Remove an entry from a namespace directory
212 * ARGUMENTS:
213 * Header = Header of the object to remove
214 */
215 {
216 KIRQL oldlvl;
217
218 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header);
219
220 KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
221 RemoveEntryList(&(Header->Entry));
222 KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
223 }
224
225
226 PVOID
227 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
228 PWSTR Name,
229 ULONG Attributes)
230 {
231 PLIST_ENTRY current = DirectoryObject->head.Flink;
232 POBJECT_HEADER current_obj;
233
234 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject, Name);
235
236 if (Name[0]==0)
237 {
238 return(DirectoryObject);
239 }
240 if (Name[0]=='.' && Name[1]==0)
241 {
242 return(DirectoryObject);
243 }
244 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
245 {
246 return(BODY_TO_HEADER(DirectoryObject)->Parent);
247 }
248 while (current!=(&(DirectoryObject->head)))
249 {
250 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
251 DPRINT(" Scanning: %S for: %S\n",current_obj->Name.Buffer, Name);
252 if (Attributes & OBJ_CASE_INSENSITIVE)
253 {
254 if (_wcsicmp(current_obj->Name.Buffer, Name)==0)
255 {
256 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
257 return(HEADER_TO_BODY(current_obj));
258 }
259 }
260 else
261 {
262 if ( wcscmp(current_obj->Name.Buffer, Name)==0)
263 {
264 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
265 return(HEADER_TO_BODY(current_obj));
266 }
267 }
268 current = current->Flink;
269 }
270 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__);
271 return(NULL);
272 }
273
274
275 NTSTATUS STDCALL
276 ObpParseDirectory(PVOID Object,
277 PVOID * NextObject,
278 PUNICODE_STRING FullPath,
279 PWSTR * Path,
280 ULONG Attributes)
281 {
282 PWSTR Start;
283 PWSTR End;
284 PVOID FoundObject;
285
286 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
287 Object,Path,*Path);
288
289 *NextObject = NULL;
290
291 if ((*Path) == NULL)
292 {
293 return STATUS_UNSUCCESSFUL;
294 }
295
296 Start = *Path;
297 if (*Start == L'\\')
298 Start++;
299
300 End = wcschr(Start, L'\\');
301 if (End != NULL)
302 {
303 *End = 0;
304 }
305
306 FoundObject = ObpFindEntryDirectory(Object, Start, Attributes);
307 if (FoundObject == NULL)
308 {
309 if (End != NULL)
310 {
311 *End = L'\\';
312 }
313 return STATUS_UNSUCCESSFUL;
314 }
315
316 ObReferenceObjectByPointer(FoundObject,
317 STANDARD_RIGHTS_REQUIRED,
318 NULL,
319 UserMode);
320
321 if (End != NULL)
322 {
323 *End = L'\\';
324 *Path = End;
325 }
326 else
327 {
328 *Path = NULL;
329 }
330
331 *NextObject = FoundObject;
332
333 return STATUS_SUCCESS;
334 }
335
336
337 NTSTATUS STDCALL
338 ObpCreateDirectory(PVOID ObjectBody,
339 PVOID Parent,
340 PWSTR RemainingPath,
341 POBJECT_ATTRIBUTES ObjectAttributes)
342 {
343 PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
344
345 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
346 ObjectBody, Parent, RemainingPath);
347
348 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
349 {
350 return(STATUS_UNSUCCESSFUL);
351 }
352
353 InitializeListHead(&DirectoryObject->head);
354 KeInitializeSpinLock(&DirectoryObject->Lock);
355
356 return(STATUS_SUCCESS);
357 }
358
359
360 VOID INIT_FUNCTION
361 ObInit(VOID)
362 /*
363 * FUNCTION: Initialize the object manager namespace
364 */
365 {
366 OBJECT_ATTRIBUTES ObjectAttributes;
367 UNICODE_STRING Name;
368 SECURITY_DESCRIPTOR SecurityDescriptor;
369
370 /* Initialize the security descriptor cache */
371 ObpInitSdCache();
372
373 /* create 'directory' object type */
374 ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
375
376 ObDirectoryType->Tag = TAG('D', 'I', 'R', 'T');
377 ObDirectoryType->TotalObjects = 0;
378 ObDirectoryType->TotalHandles = 0;
379 ObDirectoryType->MaxObjects = ULONG_MAX;
380 ObDirectoryType->MaxHandles = ULONG_MAX;
381 ObDirectoryType->PagedPoolCharge = 0;
382 ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
383 ObDirectoryType->Mapping = &ObpDirectoryMapping;
384 ObDirectoryType->Dump = NULL;
385 ObDirectoryType->Open = NULL;
386 ObDirectoryType->Close = NULL;
387 ObDirectoryType->Delete = NULL;
388 ObDirectoryType->Parse = ObpParseDirectory;
389 ObDirectoryType->Security = NULL;
390 ObDirectoryType->QueryName = NULL;
391 ObDirectoryType->OkayToClose = NULL;
392 ObDirectoryType->Create = ObpCreateDirectory;
393 ObDirectoryType->DuplicationNotify = NULL;
394
395 RtlRosInitUnicodeStringFromLiteral(&ObDirectoryType->TypeName,
396 L"Directory");
397
398 /* create 'type' object type*/
399 ObTypeObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
400
401 ObTypeObjectType->Tag = TAG('T', 'y', 'p', 'T');
402 ObTypeObjectType->TotalObjects = 0;
403 ObTypeObjectType->TotalHandles = 0;
404 ObTypeObjectType->MaxObjects = ULONG_MAX;
405 ObTypeObjectType->MaxHandles = ULONG_MAX;
406 ObTypeObjectType->PagedPoolCharge = 0;
407 ObTypeObjectType->NonpagedPoolCharge = sizeof(TYPE_OBJECT);
408 ObTypeObjectType->Mapping = &ObpTypeMapping;
409 ObTypeObjectType->Dump = NULL;
410 ObTypeObjectType->Open = NULL;
411 ObTypeObjectType->Close = NULL;
412 ObTypeObjectType->Delete = NULL;
413 ObTypeObjectType->Parse = NULL;
414 ObTypeObjectType->Security = NULL;
415 ObTypeObjectType->QueryName = NULL;
416 ObTypeObjectType->OkayToClose = NULL;
417 ObTypeObjectType->Create = NULL;
418 ObTypeObjectType->DuplicationNotify = NULL;
419
420 RtlRosInitUnicodeStringFromLiteral(&ObTypeObjectType->TypeName,
421 L"ObjectType");
422
423 /* Create security descriptor */
424 RtlCreateSecurityDescriptor(&SecurityDescriptor,
425 SECURITY_DESCRIPTOR_REVISION1);
426
427 RtlSetOwnerSecurityDescriptor(&SecurityDescriptor,
428 SeAliasAdminsSid,
429 FALSE);
430
431 RtlSetGroupSecurityDescriptor(&SecurityDescriptor,
432 SeLocalSystemSid,
433 FALSE);
434
435 RtlSetDaclSecurityDescriptor(&SecurityDescriptor,
436 TRUE,
437 SePublicDefaultDacl,
438 FALSE);
439
440 /* Create root directory */
441 InitializeObjectAttributes(&ObjectAttributes,
442 NULL,
443 OBJ_PERMANENT,
444 NULL,
445 &SecurityDescriptor);
446 ObCreateObject(KernelMode,
447 ObDirectoryType,
448 &ObjectAttributes,
449 KernelMode,
450 NULL,
451 sizeof(DIRECTORY_OBJECT),
452 0,
453 0,
454 (PVOID*)&NameSpaceRoot);
455
456 /* Create '\ObjectTypes' directory */
457 RtlRosInitUnicodeStringFromLiteral(&Name,
458 L"\\ObjectTypes");
459 InitializeObjectAttributes(&ObjectAttributes,
460 &Name,
461 OBJ_PERMANENT,
462 NULL,
463 &SecurityDescriptor);
464 ObCreateObject(KernelMode,
465 ObDirectoryType,
466 &ObjectAttributes,
467 KernelMode,
468 NULL,
469 sizeof(DIRECTORY_OBJECT),
470 0,
471 0,
472 NULL);
473
474 ObpCreateTypeObject(ObDirectoryType);
475 ObpCreateTypeObject(ObTypeObjectType);
476
477 /* Create 'symbolic link' object type */
478 ObInitSymbolicLinkImplementation();
479
480 /* FIXME: Hack Hack! */
481 ObSystemDeviceMap = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ObSystemDeviceMap), TAG('O', 'b', 'D', 'm'));
482 RtlZeroMemory(ObSystemDeviceMap, sizeof(*ObSystemDeviceMap));
483 }
484
485
486 NTSTATUS
487 ObpCreateTypeObject(POBJECT_TYPE ObjectType)
488 {
489 OBJECT_ATTRIBUTES ObjectAttributes;
490 WCHAR NameString[120];
491 PTYPE_OBJECT TypeObject = NULL;
492 UNICODE_STRING Name;
493 NTSTATUS Status;
494
495 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", &ObjectType->TypeName);
496 wcscpy(NameString, L"\\ObjectTypes\\");
497 wcscat(NameString, ObjectType->TypeName.Buffer);
498 RtlInitUnicodeString(&Name,
499 NameString);
500
501 InitializeObjectAttributes(&ObjectAttributes,
502 &Name,
503 OBJ_PERMANENT,
504 NULL,
505 NULL);
506 Status = ObCreateObject(KernelMode,
507 ObTypeObjectType,
508 &ObjectAttributes,
509 KernelMode,
510 NULL,
511 sizeof(TYPE_OBJECT),
512 0,
513 0,
514 (PVOID*)&TypeObject);
515 if (NT_SUCCESS(Status))
516 {
517 TypeObject->ObjectType = ObjectType;
518 }
519
520 return(STATUS_SUCCESS);
521 }
522
523 /* EOF */