Various changes to support the executable/driver loader
[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@mcmail.com)
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
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 /* FUNCTIONS ************************************************************/
21
22 NTSTATUS STDCALL NtSetInformationObject(IN HANDLE ObjectHandle,
23 IN CINT ObjectInformationClass,
24 IN PVOID ObjectInformation,
25 IN ULONG Length)
26 {
27 return(ZwSetInformationObject(ObjectHandle,
28 ObjectInformationClass,
29 ObjectInformation,
30 Length));
31 }
32
33 NTSTATUS STDCALL ZwSetInformationObject(IN HANDLE ObjectHandle,
34 IN CINT ObjectInformationClass,
35 IN PVOID ObjectInformation,
36 IN ULONG Length)
37 {
38 UNIMPLEMENTED;
39 }
40
41 NTSTATUS STDCALL NtQueryObject(IN HANDLE ObjectHandle,
42 IN CINT ObjectInformationClass,
43 OUT PVOID ObjectInformation,
44 IN ULONG Length,
45 OUT PULONG ResultLength)
46 {
47 return(ZwQueryObject(ObjectHandle,
48 ObjectInformationClass,
49 ObjectInformation,
50 Length,
51 ResultLength));
52 }
53
54 NTSTATUS STDCALL ZwQueryObject(IN HANDLE ObjectHandle,
55 IN CINT ObjectInformationClass,
56 OUT PVOID ObjectInformation,
57 IN ULONG Length,
58 OUT PULONG ResultLength)
59 {
60 UNIMPLEMENTED
61 }
62
63 NTSTATUS NtMakeTemporaryObject(HANDLE Handle)
64 {
65 return(ZwMakeTemporaryObject(Handle));
66 }
67
68 NTSTATUS ZwMakeTemporaryObject(HANDLE Handle)
69 {
70 PVOID Object;
71 NTSTATUS Status;
72 POBJECT_HEADER ObjectHeader;
73
74 Status = ObReferenceObjectByHandle(Handle,
75 0,
76 NULL,
77 KernelMode,
78 &Object,
79 NULL);
80 if (Status != STATUS_SUCCESS)
81 {
82 return(Status);
83 }
84
85 ObjectHeader = BODY_TO_HEADER(Object);
86 ObjectHeader->Permanent = FALSE;
87
88 ObDereferenceObject(Object);
89
90 return(STATUS_SUCCESS);
91 }
92
93 PVOID ObGenericCreateObject(PHANDLE Handle,
94 ACCESS_MASK DesiredAccess,
95 POBJECT_ATTRIBUTES ObjectAttributes,
96 POBJECT_TYPE Type)
97 {
98 POBJECT_HEADER hdr = NULL;
99 UNICODE_STRING ObjectName;
100 PWSTR path;
101 PWSTR name;
102 PWSTR Ignored;
103
104 DPRINT("ObGenericCreateObject(Handle %x, DesiredAccess %x,"
105 "ObjectAttributes %x, Type %x)\n",Handle,DesiredAccess,
106 ObjectAttributes,Type);
107
108 /*
109 * Allocate the object body and header
110 */
111 hdr=(POBJECT_HEADER)ExAllocatePool(NonPagedPool,OBJECT_ALLOC_SIZE(Type));
112 if (hdr==NULL)
113 {
114 return(NULL);
115 }
116
117 /*
118 * If unnamed then initalize
119 */
120 if (ObjectAttributes==NULL)
121 {
122 ObInitializeObjectHeader(Type,NULL,hdr);
123 if (Handle != NULL)
124 {
125 *Handle = ObInsertHandle(KeGetCurrentProcess(),
126 HEADER_TO_BODY(hdr),
127 DesiredAccess,
128 FALSE);
129 }
130 return(HEADER_TO_BODY(hdr));
131 }
132
133 /*
134 * Copy the object name into a buffer
135 */
136 DPRINT("ObjectAttributes->ObjectName %x\n",ObjectAttributes->ObjectName);
137 DPRINT("ObjectAttributes->ObjectName->Length %d\n",
138 ObjectAttributes->ObjectName->Length);
139 ObjectName.MaximumLength = ObjectAttributes->ObjectName->Length;
140 ObjectName.Buffer = ExAllocatePool(NonPagedPool,
141 ((ObjectAttributes->ObjectName->Length+1)*2));
142 if (ObjectName.Buffer==NULL)
143 {
144 return(NULL);
145 }
146 RtlCopyUnicodeString(&ObjectName,ObjectAttributes->ObjectName);
147
148 /*
149 * Seperate the name into a path and name
150 */
151 name = wcsrchr(ObjectName.Buffer,'\\');
152 if (name==NULL)
153 {
154 name=ObjectName.Buffer;
155 path=NULL;
156 }
157 else
158 {
159 path=ObjectName.Buffer;
160 *name=0;
161 name=name+1;
162 }
163
164 ObLookupObject(ObjectAttributes->RootDirectory,path,
165 &hdr->Parent,&Ignored, 0L);
166
167 /*
168 * Initialize the object header
169 */
170 ObInitializeObjectHeader(Type,name,hdr);
171 ObCreateEntry(hdr->Parent,hdr);
172
173 DPRINT("Handle %x\n",Handle);
174 if (Handle != NULL)
175 {
176 *Handle = ObInsertHandle(KeGetCurrentProcess(),
177 HEADER_TO_BODY(hdr),
178 DesiredAccess,
179 FALSE);
180 }
181
182 return(HEADER_TO_BODY(hdr));
183 }
184
185 VOID ObInitializeObjectHeader(POBJECT_TYPE Type, PWSTR name,
186 POBJECT_HEADER ObjectHeader)
187 /*
188 * FUNCTION: Creates a new object
189 * ARGUMENT:
190 * id = Identifier for the type of object
191 * obj = Pointer to the header of the object
192 */
193 {
194 PWSTR temp_name;
195
196 DPRINT("ObInitializeObjectHeader(id %x name %w obj %x)\n",Type,
197 name,ObjectHeader);
198
199 ObjectHeader->HandleCount = 0;
200 ObjectHeader->RefCount = 0;
201 ObjectHeader->ObjectType = Type;
202 ObjectHeader->Permanent = FALSE;
203 if (name==NULL)
204 {
205 ObjectHeader->Name.Length=0;
206 ObjectHeader->Name.Buffer=NULL;
207 }
208 else
209 {
210 ObjectHeader->Name.MaximumLength = wstrlen(name);
211 ObjectHeader->Name.Buffer = ExAllocatePool(NonPagedPool,
212 (ObjectHeader->Name.MaximumLength+1)*2);
213 RtlInitUnicodeString(&ObjectHeader->Name,name);
214 }
215 }
216
217
218 NTSTATUS ObReferenceObjectByPointer(PVOID ObjectBody,
219 ACCESS_MASK DesiredAccess,
220 POBJECT_TYPE ObjectType,
221 KPROCESSOR_MODE AccessMode)
222 /*
223 * FUNCTION: Increments the pointer reference count for a given object
224 * ARGUMENTS:
225 * ObjectBody = Object's body
226 * DesiredAccess = Desired access to the object
227 * ObjectType = Points to the object type structure
228 * AccessMode = Type of access check to perform
229 * RETURNS: Status
230 */
231 {
232 POBJECT_HEADER Object;
233
234 DPRINT("ObReferenceObjectByPointer(%x)\n",ObjectBody);
235
236 Object = BODY_TO_HEADER(ObjectBody);
237 Object->RefCount++;
238 return(STATUS_SUCCESS);
239 }
240
241 NTSTATUS ObPerformRetentionChecks(POBJECT_HEADER Header)
242 {
243 if (Header->RefCount == 0 && Header->HandleCount == 0 &&
244 !Header->Permanent)
245 {
246 ObRemoveEntry(Header);
247 ExFreePool(Header);
248 }
249 return(STATUS_SUCCESS);
250 }
251
252 VOID ObDereferenceObject(PVOID ObjectBody)
253 /*
254 * FUNCTION: Decrements a given object's reference count and performs
255 * retention checks
256 * ARGUMENTS:
257 * ObjectBody = Body of the object
258 */
259 {
260 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
261 Header->RefCount--;
262 ObPerformRetentionChecks(Header);
263 }
264
265
266 NTSTATUS NtClose(HANDLE Handle)
267 {
268 return(ZwClose(Handle));
269 }
270
271 NTSTATUS ZwClose(HANDLE Handle)
272 /*
273 * FUNCTION: Closes a handle reference to an object
274 * ARGUMENTS:
275 * Handle = handle to close
276 * RETURNS: Status
277 */
278 {
279 PVOID ObjectBody;
280 POBJECT_HEADER Header;
281 PHANDLE_REP HandleRep;
282
283 assert_irql(PASSIVE_LEVEL);
284
285 HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle);
286 if (HandleRep == NULL)
287 {
288 return(STATUS_INVALID_HANDLE);
289 }
290 ObjectBody = HandleRep->ObjectBody;
291
292 HandleRep->ObjectBody = NULL;
293
294 Header = BODY_TO_HEADER(ObjectBody);
295
296 Header->HandleCount--;
297 ObPerformRetentionChecks(Header);
298
299 return(STATUS_SUCCESS);
300 }
301
302 NTSTATUS ObReferenceObjectByHandle(HANDLE Handle,
303 ACCESS_MASK DesiredAccess,
304 POBJECT_TYPE ObjectType,
305 KPROCESSOR_MODE AccessMode,
306 PVOID* Object,
307 POBJECT_HANDLE_INFORMATION
308 HandleInformationPtr
309 )
310 /*
311 * FUNCTION: Increments the reference count for an object and returns a
312 * pointer to its body
313 * ARGUMENTS:
314 * Handle = Handle for the object
315 * DesiredAccess = Desired access to the object
316 * ObjectType
317 * AccessMode
318 * Object (OUT) = Points to the object body on return
319 * HandleInformation (OUT) = Contains information about the handle
320 * on return
321 * RETURNS: Status
322 */
323 {
324 PHANDLE_REP HandleRep;
325 POBJECT_HEADER ObjectHeader;
326
327 ASSERT_IRQL(PASSIVE_LEVEL);
328
329 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
330 "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
331 ObjectType,AccessMode,Object);
332
333 if (Handle == NtCurrentProcess())
334 {
335 *Object = PsGetCurrentProcess();
336 return(STATUS_SUCCESS);
337 }
338 if (Handle == NtCurrentThread())
339 {
340 *Object = PsGetCurrentThread();
341 return(STATUS_SUCCESS);
342 }
343
344 HandleRep = ObTranslateHandle(KeGetCurrentProcess(),Handle);
345 if (HandleRep == NULL || HandleRep->ObjectBody == NULL)
346 {
347 return(STATUS_INVALID_HANDLE);
348 }
349
350 ObjectHeader = BODY_TO_HEADER(HandleRep->ObjectBody);
351
352 if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
353 {
354 return(STATUS_UNSUCCESSFUL);
355 }
356
357 if (!(HandleRep->GrantedAccess & DesiredAccess))
358 {
359 return(STATUS_ACCESS_DENIED);
360 }
361
362 ObjectHeader->RefCount++;
363
364 *Object = HandleRep->ObjectBody;
365
366 return(STATUS_SUCCESS);
367 }