Merged mingw32 branch into main trunk
[reactos.git] / reactos / ntoskrnl / ob / namespc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ob/namespc.c
5 * PURPOSE: Manages the system namespace
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * 22/05/98: Created
9 */
10
11 /* INCLUDES ***************************************************************/
12
13 #include <wchar.h>
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/io.h>
17 #include <internal/string.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* GLOBALS ****************************************************************/
23
24 POBJECT_TYPE ObDirectoryType = NULL;
25
26 PDIRECTORY_OBJECT NameSpaceRoot = NULL;
27
28 /* FUNCTIONS **************************************************************/
29
30 NTSTATUS ObReferenceObjectByName(PUNICODE_STRING ObjectPath,
31 ULONG Attributes,
32 PACCESS_STATE PassedAccessState,
33 ACCESS_MASK DesiredAccess,
34 POBJECT_TYPE ObjectType,
35 KPROCESSOR_MODE AccessMode,
36 PVOID ParseContext,
37 PVOID* ObjectPtr)
38 {
39 PVOID Object;
40 PWSTR RemainingPath;
41 OBJECT_ATTRIBUTES ObjectAttributes;
42
43 InitializeObjectAttributes(&ObjectAttributes,
44 ObjectPath,
45 0,
46 NULL,
47 NULL);
48 ObFindObject(&ObjectAttributes,
49 &Object,
50 &RemainingPath);
51
52 if (RemainingPath != NULL ||
53 Object == NULL)
54 {
55 *ObjectPtr = NULL;
56 return(STATUS_UNSUCCESSFUL);
57 }
58 *ObjectPtr = Object;
59 return(STATUS_SUCCESS);
60 }
61
62 VOID ObAddEntryDirectory(PDIRECTORY_OBJECT Parent,
63 POBJECT Object,
64 PWSTR Name)
65 /*
66 * FUNCTION: Add an entry to a namespace directory
67 * ARGUMENTS:
68 * parent = directory to add in
69 * name = Name to give the entry
70 * Object = Header of the object to add the entry for
71 */
72 {
73 KIRQL oldlvl;
74 POBJECT_HEADER Header = BODY_TO_HEADER(Object);
75
76 RtlInitUnicodeString(&Header->Name, wcsdup(Name));
77 Header->Parent = Parent;
78
79 KeAcquireSpinLock(&Parent->Lock, &oldlvl);
80 InsertTailList(&Parent->head, &Header->Entry);
81 KeReleaseSpinLock(&Parent->Lock, oldlvl);
82 }
83
84 PVOID ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject,
85 PWSTR Name,
86 ULONG Attributes)
87 {
88 PLIST_ENTRY current = DirectoryObject->head.Flink;
89 POBJECT_HEADER current_obj;
90
91 DPRINT("ObDirLookup(dir %x, name %w)\n",DirectoryObject, Name);
92
93 if (Name[0]==0)
94 {
95 return(DirectoryObject);
96 }
97 if (Name[0]=='.' && Name[1]==0)
98 {
99 return(DirectoryObject);
100 }
101 if (Name[0]=='.' && Name[1]=='.' && Name[2]==0)
102 {
103 return(BODY_TO_HEADER(DirectoryObject)->Parent);
104 }
105 while (current!=(&(DirectoryObject->head)))
106 {
107 current_obj = CONTAINING_RECORD(current,OBJECT_HEADER,Entry);
108 DPRINT("Scanning %w %w\n",current_obj->Name.Buffer, Name);
109 if (Attributes & OBJ_CASE_INSENSITIVE)
110 {
111 if (wcsicmp(current_obj->Name.Buffer, Name)==0)
112 {
113 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
114 return(HEADER_TO_BODY(current_obj));
115 }
116 }
117 else
118 {
119 if ( wcscmp(current_obj->Name.Buffer, Name)==0)
120 {
121 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj));
122 return(HEADER_TO_BODY(current_obj));
123 }
124 }
125 current = current->Flink;
126 }
127 DPRINT("%s() = NULL\n",__FUNCTION__);
128 return(NULL);
129
130 }
131
132 PVOID ObpParseDirectory(PVOID Object, PWSTR* Path)
133 {
134 PWSTR end;
135 PVOID FoundObject;
136 NTSTATUS Status;
137
138 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %w)\n",
139 Object,Path,*Path);
140
141 if ((*Path) == NULL)
142 {
143 return(NULL);
144 }
145
146 end = wcschr((*Path)+1, '\\');
147 if (end != NULL)
148 {
149 *end = 0;
150 }
151
152 FoundObject = ObpFindEntryDirectory(Object, (*Path)+1, 0);
153
154 if (FoundObject == NULL)
155 {
156 if (end != NULL)
157 {
158 *end = '\\';
159 }
160 return(NULL);
161 }
162
163 ObReferenceObjectByPointer(FoundObject,
164 STANDARD_RIGHTS_REQUIRED,
165 NULL,
166 UserMode);
167
168 if (end != NULL)
169 {
170 *end = '\\';
171 *Path = end;
172 }
173 else
174 {
175 *Path = NULL;
176 }
177
178 return(FoundObject);
179 }
180
181 NTSTATUS ObpCreateDirectory(PVOID ObjectBody,
182 PVOID Parent,
183 PWSTR RemainingPath,
184 POBJECT_ATTRIBUTES ObjectAttributes)
185 {
186 PDIRECTORY_OBJECT DirectoryObject = (PDIRECTORY_OBJECT)ObjectBody;
187
188 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %w)\n",
189 ObjectBody, Parent, RemainingPath);
190
191 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
192 {
193 return(STATUS_UNSUCCESSFUL);
194 }
195
196 if (Parent != NULL && RemainingPath != NULL)
197 {
198 ObAddEntryDirectory(Parent, ObjectBody, RemainingPath+1);
199 }
200 InitializeListHead(&DirectoryObject->head);
201 KeInitializeSpinLock(&DirectoryObject->Lock);
202 return(STATUS_SUCCESS);
203 }
204
205 VOID ObInit(VOID)
206 /*
207 * FUNCTION: Initialize the object manager namespace
208 */
209 {
210 ANSI_STRING AnsiString;
211
212 ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
213
214 ObDirectoryType->TotalObjects = 0;
215 ObDirectoryType->TotalHandles = 0;
216 ObDirectoryType->MaxObjects = ULONG_MAX;
217 ObDirectoryType->MaxHandles = ULONG_MAX;
218 ObDirectoryType->PagedPoolCharge = 0;
219 ObDirectoryType->NonpagedPoolCharge = sizeof(DIRECTORY_OBJECT);
220 ObDirectoryType->Dump = NULL;
221 ObDirectoryType->Open = NULL;
222 ObDirectoryType->Close = NULL;
223 ObDirectoryType->Delete = NULL;
224 ObDirectoryType->Parse = ObpParseDirectory;
225 ObDirectoryType->Security = NULL;
226 ObDirectoryType->QueryName = NULL;
227 ObDirectoryType->OkayToClose = NULL;
228 ObDirectoryType->Create = ObpCreateDirectory;
229
230 RtlInitAnsiString(&AnsiString,"Directory");
231 RtlAnsiStringToUnicodeString(&ObDirectoryType->TypeName,
232 &AnsiString,TRUE);
233
234 NameSpaceRoot = ObCreateObject(NULL,
235 STANDARD_RIGHTS_REQUIRED,
236 NULL,
237 ObDirectoryType);
238 }
239
240 VOID ObRemoveEntry(POBJECT_HEADER Header)
241 {
242 KIRQL oldlvl;
243
244 DPRINT("ObRemoveEntry(Header %x)\n",Header);
245
246 KeAcquireSpinLock(&(Header->Parent->Lock),&oldlvl);
247 RemoveEntryList(&(Header->Entry));
248 KeReleaseSpinLock(&(Header->Parent->Lock),oldlvl);
249 }
250