Fixed some more ntoskrnl exports
[reactos.git] / reactos / ntoskrnl / ob / object.c
1 /* $Id: object.c,v 1.23 2000/05/09 21:30:06 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/object.c
6 * PURPOSE: Implements generic object managment functions
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 10/06/98: Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <wchar.h>
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/string.h>
18 #include <internal/ps.h>
19 #include <internal/id.h>
20 #include <internal/ke.h>
21
22 #define NDEBUG
23 #include <internal/debug.h>
24
25 /* FUNCTIONS ************************************************************/
26
27 /**********************************************************************
28 * NAME PRIVATE
29 * ObInitializeObject
30 *
31 * DESCRIPTION
32 *
33 * ARGUMENTS
34 *
35 * RETURN VALUE
36 */
37 VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
38 PHANDLE Handle,
39 ACCESS_MASK DesiredAccess,
40 POBJECT_TYPE Type,
41 POBJECT_ATTRIBUTES ObjectAttributes)
42 {
43 ObjectHeader->HandleCount = 0;
44 ObjectHeader->RefCount = 1;
45 ObjectHeader->ObjectType = Type;
46 if (ObjectAttributes != NULL &&
47 ObjectAttributes->Attributes & OBJ_PERMANENT)
48 {
49 ObjectHeader->Permanent = TRUE;
50 }
51 else
52 {
53 ObjectHeader->Permanent = FALSE;
54 }
55 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
56 if (Handle != NULL)
57 {
58 ObCreateHandle(PsGetCurrentProcess(),
59 HEADER_TO_BODY(ObjectHeader),
60 DesiredAccess,
61 FALSE,
62 Handle);
63 }
64 }
65
66
67 /**********************************************************************
68 * NAME PRIVATE
69 * ObFindObject@12
70 *
71 * DESCRIPTION
72 *
73 * ARGUMENTS
74 *
75 * RETURN VALUE
76 */
77 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
78 PVOID* ReturnedObject,
79 PWSTR* RemainingPath)
80 {
81 PVOID NextObject;
82 PVOID CurrentObject;
83 POBJECT_HEADER CurrentHeader;
84 NTSTATUS Status;
85 PWSTR Path;
86 PWSTR current;
87
88 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
89 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
90 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
91 ObjectAttributes->ObjectName->Buffer);
92
93 if (ObjectAttributes->RootDirectory == NULL)
94 {
95 ObReferenceObjectByPointer(NameSpaceRoot,
96 DIRECTORY_TRAVERSE,
97 NULL,
98 UserMode);
99 CurrentObject = NameSpaceRoot;
100 }
101 else
102 {
103 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
104 DIRECTORY_TRAVERSE,
105 NULL,
106 UserMode,
107 &CurrentObject,
108 NULL);
109 if (!NT_SUCCESS(Status))
110 {
111 return(Status);
112 }
113 }
114
115 Path = ObjectAttributes->ObjectName->Buffer;
116
117 if (Path[0] == 0)
118 {
119 *ReturnedObject = CurrentObject;
120 return(STATUS_SUCCESS);
121 }
122
123 if (Path[0] != '\\')
124 {
125 return(STATUS_UNSUCCESSFUL);
126 }
127
128 current = Path;
129
130 while (TRUE)
131 {
132 DPRINT("current %S\n",current);
133 CurrentHeader = BODY_TO_HEADER(CurrentObject);
134 if (CurrentHeader->ObjectType->Parse == NULL)
135 {
136 DPRINT("Current object can't parse\n");
137 break;
138 }
139 NextObject = CurrentHeader->ObjectType->Parse(CurrentObject,
140 &current);
141 if (NextObject == NULL)
142 {
143 break;
144 }
145 ObDereferenceObject(CurrentObject);
146 CurrentObject = NextObject;
147 }
148
149 *RemainingPath = current;
150 *ReturnedObject = CurrentObject;
151
152 return(STATUS_SUCCESS);
153 }
154
155
156 /**********************************************************************
157 * NAME EXPORTED
158 * ObCreateObject@36
159 *
160 * DESCRIPTION
161 *
162 * ARGUMENTS
163 *
164 * RETURN VALUE
165 */
166 PVOID STDCALL ObCreateObject(PHANDLE Handle,
167 ACCESS_MASK DesiredAccess,
168 POBJECT_ATTRIBUTES ObjectAttributes,
169 POBJECT_TYPE Type)
170 {
171 PVOID Parent = NULL;
172 PWSTR RemainingPath = NULL;
173 POBJECT_HEADER Header;
174 NTSTATUS Status;
175
176 assert_irql(APC_LEVEL);
177
178 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
179 if (ObjectAttributes != NULL &&
180 ObjectAttributes->ObjectName != NULL)
181 {
182 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
183 ObjectAttributes->ObjectName->Buffer);
184 }
185
186 if (ObjectAttributes != NULL &&
187 ObjectAttributes->ObjectName != NULL)
188 {
189 ObFindObject(ObjectAttributes,
190 &Parent,
191 &RemainingPath);
192 }
193
194 Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
195 OBJECT_ALLOC_SIZE(Type));
196 ObInitializeObject(Header,
197 Handle,
198 DesiredAccess,
199 Type,
200 ObjectAttributes);
201 if (Header->ObjectType != NULL &&
202 Header->ObjectType->Create != NULL)
203 {
204 DPRINT("Calling %x\n", Header->ObjectType);
205 DPRINT("Calling %x\n", Header->ObjectType->Create);
206 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
207 Parent,
208 RemainingPath,
209 ObjectAttributes);
210 if (!NT_SUCCESS(Status))
211 {
212 ObDereferenceObject( Parent );
213 RtlFreeUnicodeString( &Header->Name );
214 ExFreePool( Header );
215 return(NULL);
216 }
217 }
218 return(HEADER_TO_BODY(Header));
219 }
220
221 NTSTATUS STDCALL ObReferenceObjectByPointer(PVOID ObjectBody,
222 ACCESS_MASK DesiredAccess,
223 POBJECT_TYPE ObjectType,
224 KPROCESSOR_MODE AccessMode)
225 /*
226 * FUNCTION: Increments the pointer reference count for a given object
227 * ARGUMENTS:
228 * ObjectBody = Object's body
229 * DesiredAccess = Desired access to the object
230 * ObjectType = Points to the object type structure
231 * AccessMode = Type of access check to perform
232 * RETURNS: Status
233 */
234 {
235 POBJECT_HEADER ObjectHeader;
236
237 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
238 // ObjectBody,ObjectType);
239
240 ObjectHeader = BODY_TO_HEADER(ObjectBody);
241
242 if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
243 {
244 DPRINT("Failed %x (type was %x %S) should %x\n",
245 ObjectHeader,
246 ObjectHeader->ObjectType,
247 ObjectHeader->ObjectType->TypeName.Buffer,
248 ObjectType);
249 KeBugCheck(0);
250 return(STATUS_UNSUCCESSFUL);
251 }
252 if (ObjectHeader->ObjectType == PsProcessType)
253 {
254 DPRINT("Ref p 0x%x refcount %d type %x ",
255 ObjectBody, ObjectHeader->RefCount, PsProcessType);
256 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
257 }
258 if (ObjectHeader->ObjectType == PsThreadType)
259 {
260 DPRINT("Deref t 0x%x with refcount %d type %x ",
261 ObjectBody, ObjectHeader->RefCount, PsThreadType);
262 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
263 }
264
265 ObjectHeader->RefCount++;
266
267 return(STATUS_SUCCESS);
268 }
269
270 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
271 {
272 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
273 // Header,Header->RefCount,Header->HandleCount);
274
275 if (Header->RefCount < 0)
276 {
277 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
278 Header, HEADER_TO_BODY(Header), Header->RefCount);
279 KeBugCheck(0);
280 }
281 if (Header->HandleCount < 0)
282 {
283 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
284 Header, HEADER_TO_BODY(Header), Header->HandleCount);
285 KeBugCheck(0);
286 }
287
288 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
289 !Header->Permanent)
290 {
291 if (Header->ObjectType != NULL &&
292 Header->ObjectType->Delete != NULL)
293 {
294 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
295 }
296 if (Header->Name.Buffer != NULL)
297 {
298 ObRemoveEntry(Header);
299 RtlFreeUnicodeString( &Header->Name );
300 }
301 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
302 ExFreePool(Header);
303 }
304 return(STATUS_SUCCESS);
305 }
306
307 ULONG ObGetReferenceCount(PVOID ObjectBody)
308 {
309 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
310
311 return(Header->RefCount);
312 }
313
314 ULONG ObGetHandleCount(PVOID ObjectBody)
315 {
316 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
317
318 return(Header->HandleCount);
319 }
320
321
322 /**********************************************************************
323 * NAME EXPORTED
324 * @ObfReferenceObject@0
325 *
326 * DESCRIPTION
327 * Increments a given object's reference count and performs
328 * retention checks.
329 *
330 * ARGUMENTS
331 * ObjectBody
332 * Body of the object.
333 *
334 * RETURN VALUE
335 * The current value of the reference counter.
336 */
337 ULONG FASTCALL ObfReferenceObject(PVOID ObjectBody)
338 {
339 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
340 ULONG ReferenceCount;
341
342 ReferenceCount = Header->RefCount++;
343
344 ObPerformRetentionChecks (Header);
345
346 return(ReferenceCount);
347 }
348
349
350 VOID FASTCALL ObfDereferenceObject (PVOID ObjectBody)
351 /*
352 * FUNCTION: Decrements a given object's reference count and performs
353 * retention checks
354 * ARGUMENTS:
355 * ObjectBody = Body of the object
356 */
357 {
358 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
359 extern POBJECT_TYPE PsProcessType;
360
361 // DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
362 // Header->RefCount);
363
364 if (Header->ObjectType == PsProcessType)
365 {
366 DPRINT("Deref p 0x%x with refcount %d type %x ",
367 ObjectBody, Header->RefCount, PsProcessType);
368 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
369 }
370 if (Header->ObjectType == PsThreadType)
371 {
372 DPRINT("Deref t 0x%x with refcount %d type %x ",
373 ObjectBody, Header->RefCount, PsThreadType);
374 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
375 }
376
377 Header->RefCount--;
378
379 ObPerformRetentionChecks(Header);
380 }
381
382
383 VOID STDCALL ObDereferenceObject (PVOID ObjectBody)
384 {
385 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
386 extern POBJECT_TYPE PsProcessType;
387
388 if (Header->ObjectType == PsProcessType)
389 {
390 DPRINT("Deref p 0x%x with refcount %d type %x ",
391 ObjectBody, Header->RefCount, PsProcessType);
392 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
393 }
394
395 ObfDereferenceObject (ObjectBody);
396 }
397
398
399 /* EOF */