Extensive changes to the objmgr
[reactos.git] / reactos / ntoskrnl / ob / object.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ob/object.c
5 * PURPOSE: Implements generic object managment functions
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 * 10/06/98: Created
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/ob.h>
15 #include <wstring.h>
16 #include <string.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* FUNCTIONS ************************************************************/
22
23 VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
24 PHANDLE Handle,
25 ACCESS_MASK DesiredAccess,
26 POBJECT_TYPE Type,
27 POBJECT_ATTRIBUTES ObjectAttributes)
28 {
29 ObjectHeader->HandleCount = 1;
30 ObjectHeader->RefCount = 1;
31 ObjectHeader->ObjectType = Type;
32 ObjectHeader->Permanent = FALSE;
33 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
34 if (Handle != NULL)
35 {
36 *Handle = ObInsertHandle(KeGetCurrentProcess(),
37 HEADER_TO_BODY(ObjectHeader),
38 DesiredAccess,
39 FALSE);
40 }
41 }
42
43 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
44 PVOID* ReturnedObject,
45 PWSTR* RemainingPath)
46 {
47 PVOID NextObject;
48 PVOID CurrentObject;
49 POBJECT_HEADER CurrentHeader;
50 NTSTATUS Status;
51 PWSTR Path;
52 PWSTR current;
53
54 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
55 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
56 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
57 ObjectAttributes->ObjectName->Buffer);
58
59 if (ObjectAttributes->RootDirectory == NULL)
60 {
61 ObReferenceObjectByPointer(NameSpaceRoot,
62 DIRECTORY_TRAVERSE,
63 NULL,
64 UserMode);
65 CurrentObject = NameSpaceRoot;
66 }
67 else
68 {
69 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
70 DIRECTORY_TRAVERSE,
71 NULL,
72 UserMode,
73 &CurrentObject,
74 NULL);
75 if (!NT_SUCCESS(Status))
76 {
77 return(Status);
78 }
79 }
80
81 Path = ObjectAttributes->ObjectName->Buffer;
82
83 if (Path[0] == 0)
84 {
85 *ReturnedObject = CurrentObject;
86 return(STATUS_SUCCESS);
87 }
88
89 if (Path[0] != '\\')
90 {
91 return(STATUS_UNSUCCESSFUL);
92 }
93
94 current = Path;
95
96 while (TRUE)
97 {
98 DPRINT("current %w\n",current);
99 CurrentHeader = BODY_TO_HEADER(CurrentObject);
100 if (CurrentHeader->ObjectType->Parse == NULL)
101 {
102 break;
103 }
104 NextObject = CurrentHeader->ObjectType->Parse(CurrentObject,
105 &current);
106 if (NextObject == NULL)
107 {
108 break;
109 }
110 ObDereferenceObject(CurrentObject);
111 CurrentObject = NextObject;
112 }
113
114 *RemainingPath = current;
115 *ReturnedObject = CurrentObject;
116
117 return(STATUS_SUCCESS);
118 }
119
120 PVOID ObCreateObject(PHANDLE Handle,
121 ACCESS_MASK DesiredAccess,
122 POBJECT_ATTRIBUTES ObjectAttributes,
123 POBJECT_TYPE Type)
124 {
125 PVOID Parent = NULL;
126 PWSTR RemainingPath = NULL;
127 POBJECT_HEADER Header;
128 NTSTATUS Status;
129
130 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
131 if (ObjectAttributes != NULL &&
132 ObjectAttributes->ObjectName != NULL)
133 {
134 DPRINT("ObjectAttributes->ObjectName->Buffer %w\n",
135 ObjectAttributes->ObjectName->Buffer);
136 }
137
138 if (ObjectAttributes != NULL &&
139 ObjectAttributes->ObjectName != NULL)
140 {
141 ObFindObject(ObjectAttributes,
142 &Parent,
143 &RemainingPath);
144 }
145
146 Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
147 OBJECT_ALLOC_SIZE(Type));
148 ObInitializeObject(Header,
149 Handle,
150 DesiredAccess,
151 Type,
152 ObjectAttributes);
153 if (Header->ObjectType != NULL &&
154 Header->ObjectType->Create != NULL)
155 {
156 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
157 Parent,
158 RemainingPath,
159 ObjectAttributes);
160 if (!NT_SUCCESS(Status))
161 {
162 return(NULL);
163 }
164 }
165 return(HEADER_TO_BODY(Header));
166 }
167
168 NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody,
169 ACCESS_MASK DesiredAccess,
170 POBJECT_TYPE ObjectType,
171 KPROCESSOR_MODE AccessMode)
172 /*
173 * FUNCTION: Increments the pointer reference count for a given object
174 * ARGUMENTS:
175 * ObjectBody = Object's body
176 * DesiredAccess = Desired access to the object
177 * ObjectType = Points to the object type structure
178 * AccessMode = Type of access check to perform
179 * RETURNS: Status
180 */
181 {
182 POBJECT_HEADER ObjectHeader;
183
184 DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
185 ObjectBody,ObjectType);
186
187 ObjectHeader = BODY_TO_HEADER(ObjectBody);
188
189 if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
190 {
191 DPRINT("Failed (type was %x %w)\n",ObjectHeader->ObjectType,
192 ObjectHeader->ObjectType->TypeName.Buffer);
193 return(STATUS_UNSUCCESSFUL);
194 }
195
196 ObjectHeader->RefCount++;
197 return(STATUS_SUCCESS);
198 }
199
200 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
201 {
202 DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
203 Header,Header->RefCount,Header->HandleCount);
204
205 if (Header->RefCount < 0 || Header->HandleCount < 0)
206 {
207 KeBugCheck(0);
208 }
209
210 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
211 !Header->Permanent)
212 {
213 if (Header->ObjectType != NULL &&
214 Header->ObjectType->Delete != NULL)
215 {
216 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
217 }
218 if (Header->Name.Buffer != NULL)
219 {
220 ObRemoveEntry(Header);
221 }
222 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
223 ExFreePool(Header);
224 }
225 return(STATUS_SUCCESS);
226 }
227
228 VOID ObDereferenceObject(PVOID ObjectBody)
229 /*
230 * FUNCTION: Decrements a given object's reference count and performs
231 * retention checks
232 * ARGUMENTS:
233 * ObjectBody = Body of the object
234 */
235 {
236 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
237
238 DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
239 Header->RefCount);
240
241 Header->RefCount--;
242 ObPerformRetentionChecks(Header);
243 }
244
245 NTSTATUS ObReferenceObjectByHandle(HANDLE Handle,
246 ACCESS_MASK DesiredAccess,
247 POBJECT_TYPE ObjectType,
248 KPROCESSOR_MODE AccessMode,
249 PVOID* Object,
250 POBJECT_HANDLE_INFORMATION
251 HandleInformationPtr)
252 /*
253 * FUNCTION: Increments the reference count for an object and returns a
254 * pointer to its body
255 * ARGUMENTS:
256 * Handle = Handle for the object
257 * DesiredAccess = Desired access to the object
258 * ObjectType
259 * AccessMode
260 * Object (OUT) = Points to the object body on return
261 * HandleInformation (OUT) = Contains information about the handle
262 * on return
263 * RETURNS: Status
264 */
265 {
266 PHANDLE_REP HandleRep;
267 POBJECT_HEADER ObjectHeader;
268
269 ASSERT_IRQL(PASSIVE_LEVEL);
270
271 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
272 "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
273 ObjectType,AccessMode,Object);
274
275 if (Handle == NtCurrentProcess())
276 {
277 *Object = PsGetCurrentProcess();
278 return(STATUS_SUCCESS);
279 }
280 if (Handle == NtCurrentThread())
281 {
282 *Object = PsGetCurrentThread();
283 return(STATUS_SUCCESS);
284 }
285
286 HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle);
287 if (HandleRep == NULL || HandleRep->ObjectBody == NULL)
288 {
289 return(STATUS_INVALID_HANDLE);
290 }
291
292 ObjectHeader = BODY_TO_HEADER(HandleRep->ObjectBody);
293
294 if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
295 {
296 return(STATUS_UNSUCCESSFUL);
297 }
298
299 if (!(HandleRep->GrantedAccess & DesiredAccess))
300 {
301 return(STATUS_ACCESS_DENIED);
302 }
303
304 ObjectHeader->RefCount++;
305
306 *Object = HandleRep->ObjectBody;
307
308 return(STATUS_SUCCESS);
309 }