Lots of changes to the kernel
[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 assert_irql(PASSIVE_LEVEL);
133
134 DPRINT("ObCreateObject(Handle %x, ObjectAttributes %x, Type %x)\n");
135 if (ObjectAttributes != NULL &&
136 ObjectAttributes->ObjectName != NULL)
137 {
138 DPRINT("ObjectAttributes->ObjectName->Buffer %w\n",
139 ObjectAttributes->ObjectName->Buffer);
140 }
141
142 if (ObjectAttributes != NULL &&
143 ObjectAttributes->ObjectName != NULL)
144 {
145 ObFindObject(ObjectAttributes,
146 &Parent,
147 &RemainingPath);
148 }
149
150 Header = (POBJECT_HEADER)ExAllocatePool(NonPagedPool,
151 OBJECT_ALLOC_SIZE(Type));
152 ObInitializeObject(Header,
153 Handle,
154 DesiredAccess,
155 Type,
156 ObjectAttributes);
157 if (Header->ObjectType != NULL &&
158 Header->ObjectType->Create != NULL)
159 {
160 Status = Header->ObjectType->Create(HEADER_TO_BODY(Header),
161 Parent,
162 RemainingPath,
163 ObjectAttributes);
164 if (!NT_SUCCESS(Status))
165 {
166 return(NULL);
167 }
168 }
169 return(HEADER_TO_BODY(Header));
170 }
171
172 NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody,
173 ACCESS_MASK DesiredAccess,
174 POBJECT_TYPE ObjectType,
175 KPROCESSOR_MODE AccessMode)
176 /*
177 * FUNCTION: Increments the pointer reference count for a given object
178 * ARGUMENTS:
179 * ObjectBody = Object's body
180 * DesiredAccess = Desired access to the object
181 * ObjectType = Points to the object type structure
182 * AccessMode = Type of access check to perform
183 * RETURNS: Status
184 */
185 {
186 POBJECT_HEADER ObjectHeader;
187
188 DPRINT("ObReferenceObjectByPointer(ObjectBody %x, ObjectType %x)\n",
189 ObjectBody,ObjectType);
190
191 ObjectHeader = BODY_TO_HEADER(ObjectBody);
192
193 if (ObjectType != NULL && ObjectHeader->ObjectType != ObjectType)
194 {
195 DPRINT("Failed (type was %x %w)\n",ObjectHeader->ObjectType,
196 ObjectHeader->ObjectType->TypeName.Buffer);
197 return(STATUS_UNSUCCESSFUL);
198 }
199
200 ObjectHeader->RefCount++;
201
202 return(STATUS_SUCCESS);
203 }
204
205 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
206 {
207 DPRINT("ObPerformRetentionChecks(Header %x), RefCount %d, HandleCount %d\n",
208 Header,Header->RefCount,Header->HandleCount);
209
210 if (Header->RefCount < 0 || Header->HandleCount < 0)
211 {
212 DbgPrint("Object %x/%x has invalid reference or handle count\n",
213 Header,HEADER_TO_BODY(Header));
214 KeBugCheck(0);
215 }
216
217 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
218 !Header->Permanent)
219 {
220 if (Header->ObjectType != NULL &&
221 Header->ObjectType->Delete != NULL)
222 {
223 Header->ObjectType->Delete(HEADER_TO_BODY(Header));
224 }
225 if (Header->Name.Buffer != NULL)
226 {
227 ObRemoveEntry(Header);
228 }
229 DPRINT("ObPerformRetentionChecks() = Freeing object\n");
230 ExFreePool(Header);
231 }
232 return(STATUS_SUCCESS);
233 }
234
235 ULONG ObGetReferenceCount(PVOID ObjectBody)
236 {
237 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
238
239 return(Header->RefCount);
240 }
241
242 VOID ObDereferenceObject(PVOID ObjectBody)
243 /*
244 * FUNCTION: Decrements a given object's reference count and performs
245 * retention checks
246 * ARGUMENTS:
247 * ObjectBody = Body of the object
248 */
249 {
250 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
251
252 DPRINT("ObDeferenceObject(ObjectBody %x) RefCount %d\n",ObjectBody,
253 Header->RefCount);
254
255 Header->RefCount--;
256
257 ObPerformRetentionChecks(Header);
258 }