- fixed handle table structures
[reactos.git] / reactos / ntoskrnl / include / internal / ob.h
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: include/internal/objmgr.h
5 * PURPOSE: Object manager definitions
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 */
8
9 #ifndef __INCLUDE_INTERNAL_OBJMGR_H
10 #define __INCLUDE_INTERNAL_OBJMGR_H
11
12 #define NTOS_MODE_KERNEL
13 #include <ntos.h>
14
15 #define TAG_OBJECT_TYPE TAG('O', 'b', 'j', 'T')
16
17 struct _EPROCESS;
18
19 typedef struct
20 {
21 CSHORT Type;
22 CSHORT Size;
23 } COMMON_BODY_HEADER, *PCOMMON_BODY_HEADER;
24
25 typedef PVOID POBJECT;
26
27
28 typedef struct _OBJECT_TYPE
29 {
30 /*
31 * PURPOSE: Tag to be used when allocating objects of this type
32 */
33 ULONG Tag;
34
35 /*
36 * PURPOSE: Name of the type
37 */
38 UNICODE_STRING TypeName;
39
40 /*
41 * PURPOSE: Total number of objects of this type
42 */
43 ULONG TotalObjects;
44
45 /*
46 * PURPOSE: Total number of handles of this type
47 */
48 ULONG TotalHandles;
49
50 /*
51 * PURPOSE: Peak objects of this type
52 */
53 ULONG PeakObjects;
54
55 /*
56 * PURPOSE: Peak handles of this type
57 */
58 ULONG PeakHandles;
59
60 /*
61 * PURPOSE: Paged pool charge
62 */
63 ULONG PagedPoolCharge;
64
65 /*
66 * PURPOSE: Nonpaged pool charge
67 */
68 ULONG NonpagedPoolCharge;
69
70 /*
71 * PURPOSE: Mapping of generic access rights
72 */
73 PGENERIC_MAPPING Mapping;
74
75 /*
76 * PURPOSE: Dumps the object
77 * NOTE: To be defined
78 */
79 VOID STDCALL_FUNC (*Dump)(VOID);
80
81 /*
82 * PURPOSE: Opens the object
83 * NOTE: To be defined
84 */
85 VOID STDCALL_FUNC (*Open)(VOID);
86
87 /*
88 * PURPOSE: Called to close an object if OkayToClose returns true
89 */
90 VOID STDCALL_FUNC (*Close)(PVOID ObjectBody,
91 ULONG HandleCount);
92
93 /*
94 * PURPOSE: Called to delete an object when the last reference is removed
95 */
96 VOID STDCALL_FUNC (*Delete)(PVOID ObjectBody);
97
98 /*
99 * PURPOSE: Called when an open attempts to open a file apparently
100 * residing within the object
101 * RETURNS
102 * STATUS_SUCCESS NextObject was found
103 * STATUS_UNSUCCESSFUL NextObject not found
104 * STATUS_REPARSE Path changed, restart parsing the path
105 */
106 NTSTATUS STDCALL_FUNC (*Parse)(PVOID ParsedObject,
107 PVOID *NextObject,
108 PUNICODE_STRING FullPath,
109 PWSTR *Path,
110 ULONG Attributes);
111
112 /*
113 * PURPOSE: Called to set, query, delete or assign a security-descriptor
114 * to the object
115 * RETURNS
116 * STATUS_SUCCESS NextObject was found
117 */
118 NTSTATUS STDCALL_FUNC (*Security)(PVOID ObjectBody,
119 SECURITY_OPERATION_CODE OperationCode,
120 SECURITY_INFORMATION SecurityInformation,
121 PSECURITY_DESCRIPTOR SecurityDescriptor,
122 PULONG BufferLength);
123
124 /*
125 * PURPOSE: Called to query the name of the object
126 * RETURNS
127 * STATUS_SUCCESS NextObject was found
128 */
129 NTSTATUS STDCALL_FUNC (*QueryName)(PVOID ObjectBody,
130 POBJECT_NAME_INFORMATION ObjectNameInfo,
131 ULONG Length,
132 PULONG ReturnLength);
133
134 /*
135 * PURPOSE: Called when a process asks to close the object
136 */
137 VOID STDCALL_FUNC (*OkayToClose)(VOID);
138
139 NTSTATUS STDCALL_FUNC (*Create)(PVOID ObjectBody,
140 PVOID Parent,
141 PWSTR RemainingPath,
142 struct _OBJECT_ATTRIBUTES* ObjectAttributes);
143
144 VOID STDCALL_FUNC (*DuplicationNotify)(PEPROCESS DuplicateTo,
145 PEPROCESS DuplicateFrom,
146 PVOID Object);
147 } OBJECT_TYPE;
148
149
150
151 typedef struct _OBJECT_HEADER
152 /*
153 * PURPOSE: Header for every object managed by the object manager
154 */
155 {
156 UNICODE_STRING Name;
157 LIST_ENTRY Entry;
158 LONG RefCount;
159 LONG HandleCount;
160 BOOLEAN CloseInProcess;
161 BOOLEAN Permanent;
162 BOOLEAN Inherit;
163 struct _DIRECTORY_OBJECT* Parent;
164 POBJECT_TYPE ObjectType;
165 PSECURITY_DESCRIPTOR SecurityDescriptor;
166
167 /*
168 * PURPOSE: Object type
169 * NOTE: This overlaps the first member of the object body
170 */
171 CSHORT Type;
172
173 /*
174 * PURPOSE: Object size
175 * NOTE: This overlaps the second member of the object body
176 */
177 CSHORT Size;
178
179
180 } OBJECT_HEADER, *POBJECT_HEADER;
181
182
183 typedef struct _DIRECTORY_OBJECT
184 {
185 CSHORT Type;
186 CSHORT Size;
187
188 /*
189 * PURPOSE: Head of the list of our subdirectories
190 */
191 LIST_ENTRY head;
192 KSPIN_LOCK Lock;
193 } DIRECTORY_OBJECT, *PDIRECTORY_OBJECT;
194
195 typedef struct _SYMLINK_OBJECT
196 {
197 CSHORT Type;
198 CSHORT Size;
199 UNICODE_STRING TargetName;
200 LARGE_INTEGER CreateTime;
201 } SYMLINK_OBJECT, *PSYMLINK_OBJECT;
202
203
204 typedef struct _TYPE_OBJECT
205 {
206 CSHORT Type;
207 CSHORT Size;
208
209 /* pointer to object type data */
210 POBJECT_TYPE ObjectType;
211 } TYPE_OBJECT, *PTYPE_OBJECT;
212
213
214 /*
215 * Enumeration of object types
216 */
217 enum
218 {
219 OBJTYP_INVALID,
220 OBJTYP_TYPE,
221 OBJTYP_DIRECTORY,
222 OBJTYP_SYMLNK,
223 OBJTYP_DEVICE,
224 OBJTYP_THREAD,
225 OBJTYP_FILE,
226 OBJTYP_PROCESS,
227 OBJTYP_SECTION,
228 OBJTYP_MAX,
229 };
230
231 #define HEADER_TO_BODY(objhdr) \
232 (PVOID)((ULONG_PTR)objhdr + sizeof(OBJECT_HEADER) - sizeof(COMMON_BODY_HEADER))
233
234 #define BODY_TO_HEADER(objbdy) \
235 CONTAINING_RECORD(&(((PCOMMON_BODY_HEADER)objbdy)->Type), OBJECT_HEADER, Type)
236
237 #define OBJECT_ALLOC_SIZE(ObjectSize) ((ObjectSize)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER))
238
239 #define HANDLE_TO_EX_HANDLE(handle) \
240 (LONG)(((LONG)(handle) >> 2) - 1)
241 #define EX_HANDLE_TO_HANDLE(exhandle) \
242 (HANDLE)(((exhandle) + 1) << 2)
243
244 extern PDIRECTORY_OBJECT NameSpaceRoot;
245 extern POBJECT_TYPE ObSymbolicLinkType;
246
247 VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
248 POBJECT_HEADER Header,
249 PWSTR Name);
250 VOID ObpRemoveEntryDirectory(POBJECT_HEADER Header);
251
252 VOID
253 ObInitSymbolicLinkImplementation(VOID);
254
255
256 NTSTATUS ObCreateHandle(struct _EPROCESS* Process,
257 PVOID ObjectBody,
258 ACCESS_MASK GrantedAccess,
259 BOOLEAN Inherit,
260 PHANDLE Handle);
261 VOID ObCreateHandleTable(struct _EPROCESS* Parent,
262 BOOLEAN Inherit,
263 struct _EPROCESS* Process);
264 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
265 PVOID* ReturnedObject,
266 PUNICODE_STRING RemainingPath,
267 POBJECT_TYPE ObjectType);
268 VOID ObDeleteHandleTable(struct _EPROCESS* Process);
269
270 NTSTATUS
271 ObDeleteHandle(PEPROCESS Process,
272 HANDLE Handle);
273
274 NTSTATUS
275 ObpQueryHandleAttributes(HANDLE Handle,
276 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
277
278 NTSTATUS
279 ObpSetHandleAttributes(HANDLE Handle,
280 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
281
282 NTSTATUS
283 ObpCreateTypeObject(POBJECT_TYPE ObjectType);
284
285 ULONG
286 ObGetObjectHandleCount(PVOID Object);
287 NTSTATUS
288 ObDuplicateObject(PEPROCESS SourceProcess,
289 PEPROCESS TargetProcess,
290 HANDLE SourceHandle,
291 PHANDLE TargetHandle,
292 ACCESS_MASK DesiredAccess,
293 BOOLEAN InheritHandle,
294 ULONG Options);
295
296 ULONG
297 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable);
298
299 VOID
300 STDCALL
301 ObQueryDeviceMapInformation(PEPROCESS Process, PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo);
302
303 VOID FASTCALL
304 ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent);
305
306
307 /* Security descriptor cache functions */
308
309 NTSTATUS
310 ObpInitSdCache(VOID);
311
312 NTSTATUS
313 ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
314 OUT PSECURITY_DESCRIPTOR *DestinationSD);
315
316 NTSTATUS
317 ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
318
319 VOID
320 ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
321
322 VOID
323 ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
324
325 /* Secure object information functions */
326
327 typedef struct _CAPTURED_OBJECT_ATTRIBUTES
328 {
329 HANDLE RootDirectory;
330 ULONG Attributes;
331 PSECURITY_DESCRIPTOR SecurityDescriptor;
332 PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
333 } CAPTURED_OBJECT_ATTRIBUTES, *PCAPTURED_OBJECT_ATTRIBUTES;
334
335 NTSTATUS
336 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
337 IN KPROCESSOR_MODE AccessMode,
338 IN POOL_TYPE PoolType,
339 IN BOOLEAN CaptureIfKernel,
340 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
341 OUT PUNICODE_STRING ObjectName OPTIONAL);
342
343 VOID
344 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
345 IN PUNICODE_STRING ObjectName OPTIONAL,
346 IN KPROCESSOR_MODE AccessMode,
347 IN BOOLEAN CaptureIfKernel);
348
349 /* object information classes */
350
351 #define ICIF_QUERY 0x1
352 #define ICIF_SET 0x2
353 #define ICIF_QUERY_SIZE_VARIABLE 0x4
354 #define ICIF_SET_SIZE_VARIABLE 0x8
355 #define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE)
356
357 typedef struct _INFORMATION_CLASS_INFO
358 {
359 ULONG RequiredSizeQUERY;
360 ULONG RequiredSizeSET;
361 ULONG AlignmentSET;
362 ULONG AlignmentQUERY;
363 ULONG Flags;
364 } INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO;
365
366 #define ICI_SQ_SAME(Size, Alignment, Flags) \
367 { Size, Size, Alignment, Alignment, Flags }
368
369 #define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \
370 { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags }
371
372 #define CheckInfoClass(Class, BufferLen, ClassList, StatusVar, Mode) \
373 do { \
374 if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
375 { \
376 if(!(ClassList[Class].Flags & ICIF_##Mode)) \
377 { \
378 *(StatusVar) = STATUS_INVALID_INFO_CLASS; \
379 } \
380 else if(ClassList[Class].RequiredSize##Mode > 0 && \
381 (BufferLen) != ClassList[Class].RequiredSize##Mode) \
382 { \
383 if(!(ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \
384 (BufferLen) != ClassList[Class].RequiredSize##Mode) \
385 { \
386 *(StatusVar) = STATUS_INFO_LENGTH_MISMATCH; \
387 } \
388 } \
389 } \
390 else \
391 { \
392 *(StatusVar) = STATUS_INVALID_INFO_CLASS; \
393 } \
394 } while(0)
395
396
397 #define GetInfoClassAlignment(Class, ClassList, AlignmentVar, Mode) \
398 do { \
399 if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
400 { \
401 *(AlignmentVar) = ClassList[Class].Alignment##Mode; \
402 } \
403 else \
404 { \
405 *(AlignmentVar) = sizeof(ULONG); \
406 } \
407 } while(0)
408
409 #define ProbeQueryInfoBuffer(Buffer, BufferLen, Alignment, RetLen, PrevMode, StatusVar) \
410 do { \
411 if(PrevMode == UserMode) \
412 { \
413 _SEH_TRY \
414 { \
415 ProbeForWrite(Buffer, \
416 BufferLen, \
417 Alignment); \
418 if(RetLen != NULL) \
419 { \
420 ProbeForWrite(RetLen, \
421 sizeof(ULONG), \
422 1); \
423 } \
424 } \
425 _SEH_HANDLE \
426 { \
427 *(StatusVar) = _SEH_GetExceptionCode(); \
428 } \
429 _SEH_END; \
430 \
431 if(!NT_SUCCESS(*(StatusVar))) \
432 { \
433 DPRINT1("ProbeQueryInfoBuffer failed: 0x%x\n", *(StatusVar)); \
434 return *(StatusVar); \
435 } \
436 } \
437 } while(0)
438
439 #define ProbeSetInfoBuffer(Buffer, BufferLen, Alignment, PrevMode, StatusVar) \
440 do { \
441 if(PrevMode == UserMode) \
442 { \
443 _SEH_TRY \
444 { \
445 ProbeForRead(Buffer, \
446 BufferLen, \
447 Alignment); \
448 } \
449 _SEH_HANDLE \
450 { \
451 *(StatusVar) = _SEH_GetExceptionCode(); \
452 } \
453 _SEH_END; \
454 \
455 if(!NT_SUCCESS(*(StatusVar))) \
456 { \
457 DPRINT1("ProbeAllInfoBuffer failed: 0x%x\n", *(StatusVar)); \
458 return *(StatusVar); \
459 } \
460 } \
461 } while(0)
462
463 #define DefaultSetInfoBufferCheck(Class, ClassList, Buffer, BufferLen, PrevMode, StatusVar) \
464 do { \
465 ULONG _Alignment; \
466 /* get the preferred alignment for the information class or return */ \
467 /* default alignment in case the class doesn't exist */ \
468 GetInfoClassAlignment(Class, \
469 ClassList, \
470 &_Alignment, \
471 SET); \
472 \
473 /* probe the ENTIRE buffers and return on failure */ \
474 ProbeSetInfoBuffer(Buffer, \
475 BufferLen, \
476 _Alignment, \
477 PrevMode, \
478 StatusVar); \
479 \
480 /* validate information class index and check buffer size */ \
481 CheckInfoClass(Class, \
482 BufferLen, \
483 ClassList, \
484 StatusVar, \
485 SET); \
486 } while(0)
487
488 #define DefaultQueryInfoBufferCheck(Class, ClassList, Buffer, BufferLen, RetLen, PrevMode, StatusVar) \
489 do { \
490 ULONG _Alignment; \
491 /* get the preferred alignment for the information class or return */ \
492 /* alignment in case the class doesn't exist */ \
493 GetInfoClassAlignment(Class, \
494 ClassList, \
495 &_Alignment, \
496 QUERY); \
497 \
498 /* probe the ENTIRE buffers and return on failure */ \
499 ProbeQueryInfoBuffer(Buffer, \
500 BufferLen, \
501 _Alignment, \
502 RetLen, \
503 PrevMode, \
504 StatusVar); \
505 \
506 /* validate information class index and check buffer size */ \
507 CheckInfoClass(Class, \
508 BufferLen, \
509 ClassList, \
510 StatusVar, \
511 QUERY); \
512 } while(0)
513
514 #endif /* __INCLUDE_INTERNAL_OBJMGR_H */