Several bug fixes
[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 <wchar.h>
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/string.h>
17 #include <internal/id.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* FUNCTIONS ************************************************************/
23
24 VOID ObInitializeObject(POBJECT_HEADER ObjectHeader,
25 PHANDLE Handle,
26 ACCESS_MASK DesiredAccess,
27 POBJECT_TYPE Type,
28 POBJECT_ATTRIBUTES ObjectAttributes)
29 {
30 ObjectHeader->HandleCount = 1;
31 ObjectHeader->RefCount = 1;
32 ObjectHeader->ObjectType = Type;
33 ObjectHeader->Permanent = FALSE;
34 RtlInitUnicodeString(&(ObjectHeader->Name),NULL);
35 if (Handle != NULL)
36 {
37 ObCreateHandle(PsGetCurrentProcess(),
38 HEADER_TO_BODY(ObjectHeader),
39 DesiredAccess,
40 FALSE,
41 Handle);
42 }
43 }
44
45 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
46 PVOID* ReturnedObject,
47 PWSTR* RemainingPath)
48 {
49 PVOID NextObject;
50 PVOID CurrentObject;
51 POBJECT_HEADER CurrentHeader;
52 NTSTATUS Status;
53 PWSTR Path;
54 PWSTR current;
55
56 DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, "
57 "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath);
58 DPRINT("ObjectAttributes->ObjectName->Buffer %x\n",
59 ObjectAttributes->ObjectName->Buffer);
60
61 if (ObjectAttributes->RootDirectory == NULL)
62 {
63 ObReferenceObjectByPointer(NameSpaceRoot,
64 DIRECTORY_TRAVERSE,
65 NULL,
66 UserMode);
67 CurrentObject = NameSpaceRoot;
68 }
69 else
70 {
71 Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory,
72 DIRECTORY_TRAVERSE,
73 NULL,
74 UserMode,
75 &CurrentObject,
76 NULL);
77 if (!NT_SUCCESS(Status))
78 {
79 return(Status);
80 }
81 }
82
83 Path = ObjectAttributes->ObjectName->Buffer;
84
85 if (Path[0] == 0)
86 {
87 *ReturnedObject = CurrentObject;
88 return(STATUS_SUCCESS);
89 }
90
91 if (Path[0] != '\\')
92 {
93 return(STATUS_UNSUCCESSFUL);
94 }
95
96 current = Path;
97
98 while (TRUE)
99 {
100 DPRINT("current %w\n",current);
101 CurrentHeader = BODY_TO_HEADER(CurrentObject);
102 if (CurrentHeader->ObjectType->Parse == NULL)
103 {
104 break;
105 }
106 NextObject = CurrentHeader->ObjectType->Parse(CurrentObject,
107 &current);
108 if (NextObject == NULL)
109 {
110 break;
111 }
112 ObDereferenceObject(CurrentObject);
113 CurrentObject = NextObject;
114 }
115
116 *RemainingPath = current;
117 *ReturnedObject = CurrentObject;
118
119 return(STATUS_SUCCESS);
120 }
121
122 PVOID ObCreateObject(PHANDLE Handle,
123 ACCESS_MASK DesiredAccess,
124 POBJECT_ATTRIBUTES ObjectAttributes,
125 POBJECT_TYPE Type)
126 {
127 PVOID Parent = NULL;
128 PWSTR RemainingPath = NULL;
129 POBJECT_HEADER Header;
130 NTSTATUS Status;
131
132 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
133 if (ObjectAttributes != NULL &&
134 ObjectAttributes->ObjectName != NULL)
135 {
136 DPRINT("ObjectAttributes->ObjectName->Buffer %w\n",
137 ObjectAttributes->ObjectName->Buffer);
138 }
139
140 if (ObjectAttributes != NULL &&
141 ObjectAttributes->ObjectName != NULL)
142 {
143 ObFindObject(ObjectAttributes,
144 &Parent,
145 &RemainingPath);
146 }
147
148 Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
149 OBJECT_ALLOC_SIZE(Type));
150 ObInitializeObject(Header,
151 Handle,
152 DesiredAccess,
153 Type,
154 ObjectAttributes);
155 if (Header->ObjectType != NULL &&
156 Header->ObjectType->Create != NULL)
157 {
158 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
159 Parent,
160 RemainingPath,
161 ObjectAttributes);
162 if (!NT_SUCCESS(Status))
163 {
164 return(NULL);
165 }
166 }
167 return(HEADER_TO_BODY(Header));
168 }
169
170 NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody,
171 ACCESS_MASK DesiredAccess,
172 POBJECT_TYPE ObjectType,
173 KPROCESSOR_MODE AccessMode)
174 /*
175 * FUNCTION: Increments the pointer reference count for a given object
176 * ARGUMENTS:
177 * ObjectBody = Object's body
178 * DesiredAccess = Desired access to the object
179 * ObjectType = Points to the object type structure
180 * AccessMode = Type of access check to perform
181 * RETURNS: Status
182 */
183 {
184 POBJECT_HEADER ObjectHeader;
185
186 DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
187 ObjectBody,ObjectType);
188
189 ObjectHeader = BODY_TO_HEADER(ObjectBody);
190
191 if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
192 {
193 DPRINT("Failed (type was %x %w)\n",ObjectHeader->ObjectType,
194 ObjectHeader->ObjectType->TypeName.Buffer);
195 return(STATUS_UNSUCCESSFUL);
196 }
197
198 ObjectHeader->RefCount++;
199
200 return(STATUS_SUCCESS);
201 }
202
203 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
204 {
205 DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
206 Header,Header->RefCount,Header->HandleCount);
207
208 if (Header->RefCount < 0 || Header->HandleCount < 0)
209 {
210 DbgPrint("Object %x/%x has invalid reference or handle count\n",
211 Header,HEADER_TO_BODY(Header));
212 KeBugCheck(0);
213 }
214
215 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
216 !Header->Permanent)
217 {
218 if (Header->ObjectType != NULL &&
219 Header->ObjectType->Delete != NULL)
220 {
221 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
222 }
223 if (Header->Name.Buffer != NULL)
224 {
225 ObRemoveEntry(Header);
226 }
227 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
228 ExFreePool(Header);
229 }
230 return(STATUS_SUCCESS);
231 }
232
233 ULONG ObGetReferenceCount(PVOID ObjectBody)
234 {
235 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
236
237 return(Header->RefCount);
238 }
239
240 VOID ObDereferenceObject(PVOID ObjectBody)
241 /*
242 * FUNCTION: Decrements a given object's reference count and performs
243 * retention checks
244 * ARGUMENTS:
245 * ObjectBody = Body of the object
246 */
247 {
248 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
249
250 DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
251 Header->RefCount);
252
253 Header->RefCount--;
254
255 ObPerformRetentionChecks(Header);
256 }