Removed obsolete linux header files
[reactos.git] / reactos / ntoskrnl / ob / object.c
1 /* $Id: object.c,v 1.29 2000/10/22 16:36:53 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 <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/ps.h>
17 #include <internal/id.h>
18 #include <internal/ke.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* FUNCTIONS ************************************************************/
24
25 PVOID HEADER_TO_BODY(POBJECT_HEADER obj)
26 {
27 return(((void *)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER));
28 }
29
30 POBJECT_HEADER BODY_TO_HEADER(PVOID body)
31 {
32 PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body;
33 return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type));
34 }
35
36
37 /**********************************************************************
38 * NAME PRIVATE
39 * ObInitializeObject
40 *
41 * DESCRIPTION
42 *
43 * ARGUMENTS
44 *
45 * RETURN VALUE
46 */
47 VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
48 PHANDLE Handle,
49 ACCESS_MASK DesiredAccess,
50 POBJECT_TYPE Type,
51 POBJECT_ATTRIBUTES ObjectAttributes)
52 {
53 ObjectHeader->HandleCount = 0;
54 ObjectHeader->RefCount = 1;
55 ObjectHeader->ObjectType = Type;
56 if (ObjectAttributes != NULL &&
57 ObjectAttributes->Attributes & OBJ_PERMANENT)
58 {
59 ObjectHeader->Permanent = TRUE;
60 }
61 else
62 {
63 ObjectHeader->Permanent = FALSE;
64 }
65 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
66 if (Handle != NULL)
67 {
68 ObCreateHandle(PsGetCurrentProcess(),
69 HEADER_TO_BODY(ObjectHeader),
70 DesiredAccess,
71 FALSE,
72 Handle);
73 }
74 }
75
76
77 /**********************************************************************
78 * NAME PRIVATE
79 * ObFindObject@16
80 *
81 * DESCRIPTION
82 *
83 * ARGUMENTS
84 * ObjectAttributes
85 *
86 * ReturnedObject
87 *
88 * RemainigPath
89 * Pointer to a unicode string that will contain the
90 * remaining path if the function returns successfully.
91 * The caller must free the buffer after use by calling
92 * RtlFreeUnicodeString ().
93 *
94 * ObjectType
95 * Optional pointer to an object type. This is used to
96 * descide if a symbolic link object will be parsed or not.
97 *
98 * RETURN VALUE
99 */
100 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
101 PVOID* ReturnedObject,
102 PUNICODE_STRING RemainingPath,
103 POBJECT_TYPE ObjectType)
104 {
105 PVOID NextObject;
106 PVOID CurrentObject;
107 PVOID RootObject;
108 POBJECT_HEADER CurrentHeader;
109 NTSTATUS Status;
110 PWSTR Path;
111 PWSTR current;
112 UNICODE_STRING PathString;
113
114 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
115 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
116 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
117 ObjectAttributes->ObjectName->Buffer);
118
119 RtlInitUnicodeString (RemainingPath, NULL);
120
121 if (ObjectAttributes->RootDirectory == NULL)
122 {
123 ObReferenceObjectByPointer(NameSpaceRoot,
124 DIRECTORY_TRAVERSE,
125 NULL,
126 UserMode);
127 CurrentObject = NameSpaceRoot;
128 }
129 else
130 {
131 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
132 DIRECTORY_TRAVERSE,
133 NULL,
134 UserMode,
135 &CurrentObject,
136 NULL);
137 if (!NT_SUCCESS(Status))
138 {
139 return(Status);
140 }
141 }
142
143 Path = ObjectAttributes->ObjectName->Buffer;
144
145 if (Path[0] == 0)
146 {
147 *ReturnedObject = CurrentObject;
148 return(STATUS_SUCCESS);
149 }
150
151 if ((ObjectAttributes->RootDirectory == NULL) && (Path[0] != '\\'))
152 {
153 return(STATUS_UNSUCCESSFUL);
154 }
155
156 if (Path)
157 {
158 // if ( Path[0] != '\\' )
159 // {
160 // RtlCreateUnicodeString (&PathString, L"\\");
161 // RtlAppendUnicodeToString (&PathString, Path);
162 // }
163 // else
164 RtlCreateUnicodeString (&PathString, Path);
165 current = PathString.Buffer;
166 }
167 else
168 {
169 RtlInitUnicodeString (&PathString, NULL);
170 current = NULL;
171 }
172
173 RootObject = CurrentObject;
174
175 while (TRUE)
176 {
177 DPRINT("current %S\n",current);
178 CurrentHeader = BODY_TO_HEADER(CurrentObject);
179 if (CurrentHeader->ObjectType->Parse == NULL)
180 {
181 DPRINT("Current object can't parse\n");
182 break;
183 }
184 Status = CurrentHeader->ObjectType->Parse(CurrentObject,
185 &NextObject,
186 &PathString,
187 &current,
188 ObjectType);
189 if (Status == STATUS_REPARSE)
190 {
191 /* reparse the object path */
192 NextObject = RootObject;
193 current = PathString.Buffer;
194
195 ObReferenceObjectByPointer(NextObject,
196 DIRECTORY_TRAVERSE,
197 NULL,
198 UserMode);
199 }
200
201 if (NextObject == NULL)
202 {
203 break;
204 }
205 ObDereferenceObject(CurrentObject);
206 CurrentObject = NextObject;
207 }
208
209 if (current)
210 RtlCreateUnicodeString (RemainingPath, current);
211 RtlFreeUnicodeString (&PathString);
212 *ReturnedObject = CurrentObject;
213
214 return(STATUS_SUCCESS);
215 }
216
217
218 /**********************************************************************
219 * NAME EXPORTED
220 * ObCreateObject@36
221 *
222 * DESCRIPTION
223 *
224 * ARGUMENTS
225 *
226 * RETURN VALUE
227 */
228 PVOID STDCALL ObCreateObject(PHANDLE Handle,
229 ACCESS_MASK DesiredAccess,
230 POBJECT_ATTRIBUTES ObjectAttributes,
231 POBJECT_TYPE Type)
232 {
233 PVOID Parent = NULL;
234 UNICODE_STRING RemainingPath;
235 POBJECT_HEADER Header;
236 NTSTATUS Status;
237
238 assert_irql(APC_LEVEL);
239
240 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
241 if (ObjectAttributes != NULL &&
242 ObjectAttributes->ObjectName != NULL)
243 {
244 DPRINT("ObjectAttributes->ObjectName->Buffer %S\n",
245 ObjectAttributes->ObjectName->Buffer);
246 }
247
248 if (ObjectAttributes != NULL &&
249 ObjectAttributes->ObjectName != NULL)
250 {
251 ObFindObject(ObjectAttributes,
252 &Parent,
253 &RemainingPath,
254 NULL);
255 }
256 else
257 {
258 RtlInitUnicodeString (&RemainingPath, NULL);
259 }
260 Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
261 OBJECT_ALLOC_SIZE(Type));
262 ObInitializeObject(Header,
263 Handle,
264 DesiredAccess,
265 Type,
266 ObjectAttributes);
267 if (Header->ObjectType != NULL &&
268 Header->ObjectType->Create != NULL)
269 {
270 DPRINT("Calling %x\n", Header->ObjectType);
271 DPRINT("Calling %x\n", Header->ObjectType->Create);
272 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
273 Parent,
274 RemainingPath.Buffer,
275 ObjectAttributes);
276 if (!NT_SUCCESS(Status))
277 {
278 ObDereferenceObject( Parent );
279 RtlFreeUnicodeString( &Header->Name );
280 RtlFreeUnicodeString( &RemainingPath );
281 ExFreePool( Header );
282 return(NULL);
283 }
284 }
285 RtlFreeUnicodeString( &RemainingPath );
286 return(HEADER_TO_BODY(Header));
287 }
288
289 NTSTATUS STDCALL ObReferenceObjectByPointer(PVOID ObjectBody,
290 ACCESS_MASK DesiredAccess,
291 POBJECT_TYPE ObjectType,
292 KPROCESSOR_MODE AccessMode)
293 /*
294 * FUNCTION: Increments the pointer reference count for a given object
295 * ARGUMENTS:
296 * ObjectBody = Object's body
297 * DesiredAccess = Desired access to the object
298 * ObjectType = Points to the object type structure
299 * AccessMode = Type of access check to perform
300 * RETURNS: Status
301 */
302 {
303 POBJECT_HEADER ObjectHeader;
304
305 // DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
306 // ObjectBody,ObjectType);
307
308 ObjectHeader = BODY_TO_HEADER(ObjectBody);
309
310 if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
311 {
312 DPRINT("Failed %x (type was %x %S) should %x\n",
313 ObjectHeader,
314 ObjectHeader->ObjectType,
315 ObjectHeader->ObjectType->TypeName.Buffer,
316 ObjectType);
317 KeBugCheck(0);
318 return(STATUS_UNSUCCESSFUL);
319 }
320 if (ObjectHeader->ObjectType == PsProcessType)
321 {
322 DPRINT("Ref p 0x%x refcount %d type %x ",
323 ObjectBody, ObjectHeader->RefCount, PsProcessType);
324 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
325 }
326 if (ObjectHeader->ObjectType == PsThreadType)
327 {
328 DPRINT("Deref t 0x%x with refcount %d type %x ",
329 ObjectBody, ObjectHeader->RefCount, PsThreadType);
330 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
331 }
332
333 ObjectHeader->RefCount++;
334
335 return(STATUS_SUCCESS);
336 }
337
338 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
339 {
340 // DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
341 // Header,Header->RefCount,Header->HandleCount);
342
343 if (Header->RefCount < 0)
344 {
345 DbgPrint("Object %x/%x has invalid reference count (%d)\n",
346 Header, HEADER_TO_BODY(Header), Header->RefCount);
347 KeBugCheck(0);
348 }
349 if (Header->HandleCount < 0)
350 {
351 DbgPrint("Object %x/%x has invalid handle count (%d)\n",
352 Header, HEADER_TO_BODY(Header), Header->HandleCount);
353 KeBugCheck(0);
354 }
355
356 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
357 !Header->Permanent)
358 {
359 if (Header->ObjectType != NULL &&
360 Header->ObjectType->Delete != NULL)
361 {
362 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
363 }
364 if (Header->Name.Buffer != NULL)
365 {
366 ObRemoveEntry(Header);
367 RtlFreeUnicodeString( &Header->Name );
368 }
369 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
370 ExFreePool(Header);
371 }
372 return(STATUS_SUCCESS);
373 }
374
375 ULONG ObGetReferenceCount(PVOID ObjectBody)
376 {
377 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
378
379 return(Header->RefCount);
380 }
381
382 ULONG ObGetHandleCount(PVOID ObjectBody)
383 {
384 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
385
386 return(Header->HandleCount);
387 }
388
389
390 /**********************************************************************
391 * NAME EXPORTED
392 * @ObfReferenceObject@0
393 *
394 * DESCRIPTION
395 * Increments a given object's reference count and performs
396 * retention checks.
397 *
398 * ARGUMENTS
399 * ObjectBody
400 * Body of the object.
401 *
402 * RETURN VALUE
403 * The current value of the reference counter.
404 */
405 ULONG FASTCALL ObfReferenceObject(PVOID ObjectBody)
406 {
407 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
408 ULONG ReferenceCount;
409
410 ReferenceCount = Header->RefCount++;
411
412 ObPerformRetentionChecks (Header);
413
414 return(ReferenceCount);
415 }
416
417
418 VOID FASTCALL ObfDereferenceObject (PVOID ObjectBody)
419 /*
420 * FUNCTION: Decrements a given object's reference count and performs
421 * retention checks
422 * ARGUMENTS:
423 * ObjectBody = Body of the object
424 */
425 {
426 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
427 extern POBJECT_TYPE PsProcessType;
428
429 // DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
430 // Header->RefCount);
431
432 if (Header->ObjectType == PsProcessType)
433 {
434 DPRINT("Deref p 0x%x with refcount %d type %x ",
435 ObjectBody, Header->RefCount, PsProcessType);
436 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
437 }
438 if (Header->ObjectType == PsThreadType)
439 {
440 DPRINT("Deref t 0x%x with refcount %d type %x ",
441 ObjectBody, Header->RefCount, PsThreadType);
442 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
443 }
444
445 Header->RefCount--;
446
447 ObPerformRetentionChecks(Header);
448 }
449
450
451 VOID STDCALL ObDereferenceObject (PVOID ObjectBody)
452 {
453 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
454 extern POBJECT_TYPE PsProcessType;
455
456 if (Header->ObjectType == PsProcessType)
457 {
458 DPRINT("Deref p 0x%x with refcount %d type %x ",
459 ObjectBody, Header->RefCount, PsProcessType);
460 DPRINT("eip %x\n", ((PULONG)&ObjectBody)[-1]);
461 }
462
463 ObfDereferenceObject (ObjectBody);
464 }
465
466
467 /* EOF */