3e4df5e920c28f04b39b3fae935d482231487e20
[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 Permanent;
161 BOOLEAN Inherit;
162 struct _DIRECTORY_OBJECT* Parent;
163 POBJECT_TYPE ObjectType;
164 PSECURITY_DESCRIPTOR SecurityDescriptor;
165
166 /*
167 * PURPOSE: Object type
168 * NOTE: This overlaps the first member of the object body
169 */
170 CSHORT Type;
171
172 /*
173 * PURPOSE: Object size
174 * NOTE: This overlaps the second member of the object body
175 */
176 CSHORT Size;
177
178
179 } OBJECT_HEADER, *POBJECT_HEADER;
180
181
182 typedef struct _DIRECTORY_OBJECT
183 {
184 CSHORT Type;
185 CSHORT Size;
186
187 /*
188 * PURPOSE: Head of the list of our subdirectories
189 */
190 LIST_ENTRY head;
191 KSPIN_LOCK Lock;
192 } DIRECTORY_OBJECT, *PDIRECTORY_OBJECT;
193
194 typedef struct _SYMLINK_OBJECT
195 {
196 CSHORT Type;
197 CSHORT Size;
198 UNICODE_STRING TargetName;
199 LARGE_INTEGER CreateTime;
200 } SYMLINK_OBJECT, *PSYMLINK_OBJECT;
201
202
203 typedef struct _TYPE_OBJECT
204 {
205 CSHORT Type;
206 CSHORT Size;
207
208 /* pointer to object type data */
209 POBJECT_TYPE ObjectType;
210 } TYPE_OBJECT, *PTYPE_OBJECT;
211
212
213 /*
214 * Enumeration of object types
215 */
216 enum
217 {
218 OBJTYP_INVALID,
219 OBJTYP_TYPE,
220 OBJTYP_DIRECTORY,
221 OBJTYP_SYMLNK,
222 OBJTYP_DEVICE,
223 OBJTYP_THREAD,
224 OBJTYP_FILE,
225 OBJTYP_PROCESS,
226 OBJTYP_SECTION,
227 OBJTYP_MAX,
228 };
229
230 #define HEADER_TO_BODY(objhdr) \
231 (PVOID)((ULONG_PTR)objhdr + sizeof(OBJECT_HEADER) - sizeof(COMMON_BODY_HEADER))
232
233 #define BODY_TO_HEADER(objbdy) \
234 CONTAINING_RECORD(&(((PCOMMON_BODY_HEADER)objbdy)->Type), OBJECT_HEADER, Type)
235
236 #define OBJECT_ALLOC_SIZE(ObjectSize) ((ObjectSize)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER))
237
238 #define HANDLE_TO_EX_HANDLE(handle) \
239 (LONG)(((LONG)(handle) >> 2) - 1)
240 #define EX_HANDLE_TO_HANDLE(exhandle) \
241 (HANDLE)(((exhandle) + 1) << 2)
242
243 extern PDIRECTORY_OBJECT NameSpaceRoot;
244 extern POBJECT_TYPE ObSymbolicLinkType;
245
246 VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent,
247 POBJECT_HEADER Header,
248 PWSTR Name);
249 VOID ObpRemoveEntryDirectory(POBJECT_HEADER Header);
250
251 VOID
252 ObInitSymbolicLinkImplementation(VOID);
253
254
255 NTSTATUS ObCreateHandle(struct _EPROCESS* Process,
256 PVOID ObjectBody,
257 ACCESS_MASK GrantedAccess,
258 BOOLEAN Inherit,
259 PHANDLE Handle);
260 VOID ObCreateHandleTable(struct _EPROCESS* Parent,
261 BOOLEAN Inherit,
262 struct _EPROCESS* Process);
263 NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes,
264 PVOID* ReturnedObject,
265 PUNICODE_STRING RemainingPath,
266 POBJECT_TYPE ObjectType);
267 VOID ObDeleteHandleTable(struct _EPROCESS* Process);
268
269 NTSTATUS
270 ObDeleteHandle(PEPROCESS Process,
271 HANDLE Handle);
272
273 NTSTATUS
274 ObpQueryHandleAttributes(HANDLE Handle,
275 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
276
277 NTSTATUS
278 ObpSetHandleAttributes(HANDLE Handle,
279 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo);
280
281 NTSTATUS
282 ObpCreateTypeObject(POBJECT_TYPE ObjectType);
283
284 ULONG
285 ObGetObjectHandleCount(PVOID Object);
286 NTSTATUS
287 ObDuplicateObject(PEPROCESS SourceProcess,
288 PEPROCESS TargetProcess,
289 HANDLE SourceHandle,
290 PHANDLE TargetHandle,
291 ACCESS_MASK DesiredAccess,
292 BOOLEAN InheritHandle,
293 ULONG Options);
294
295 ULONG
296 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable);
297
298 VOID
299 STDCALL
300 ObQueryDeviceMapInformation(PEPROCESS Process, PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo);
301
302 VOID FASTCALL
303 ObpSetPermanentObject (IN PVOID ObjectBody, IN BOOLEAN Permanent);
304
305
306 /* Security descriptor cache functions */
307
308 NTSTATUS
309 ObpInitSdCache(VOID);
310
311 NTSTATUS
312 ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD,
313 OUT PSECURITY_DESCRIPTOR *DestinationSD);
314
315 NTSTATUS
316 ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
317
318 VOID
319 ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
320
321 VOID
322 ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor);
323
324 /* Secure object information functions */
325
326 typedef struct _CAPTURED_OBJECT_ATTRIBUTES
327 {
328 HANDLE RootDirectory;
329 ULONG Attributes;
330 PSECURITY_DESCRIPTOR SecurityDescriptor;
331 PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
332 } CAPTURED_OBJECT_ATTRIBUTES, *PCAPTURED_OBJECT_ATTRIBUTES;
333
334 NTSTATUS
335 ObpCaptureObjectAttributes(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
336 IN KPROCESSOR_MODE AccessMode,
337 IN POOL_TYPE PoolType,
338 IN BOOLEAN CaptureIfKernel,
339 OUT PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
340 OUT PUNICODE_STRING ObjectName OPTIONAL);
341
342 VOID
343 ObpReleaseObjectAttributes(IN PCAPTURED_OBJECT_ATTRIBUTES CapturedObjectAttributes OPTIONAL,
344 IN PUNICODE_STRING ObjectName OPTIONAL,
345 IN KPROCESSOR_MODE AccessMode,
346 IN BOOLEAN CaptureIfKernel);
347
348 /* object information classes */
349
350 #define ICIF_QUERY 0x1
351 #define ICIF_SET 0x2
352 #define ICIF_QUERY_SIZE_VARIABLE 0x4
353 #define ICIF_SET_SIZE_VARIABLE 0x8
354 #define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE)
355
356 typedef struct _INFORMATION_CLASS_INFO
357 {
358 ULONG RequiredSizeQUERY;
359 ULONG RequiredSizeSET;
360 ULONG AlignmentSET;
361 ULONG AlignmentQUERY;
362 ULONG Flags;
363 } INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO;
364
365 #define ICI_SQ_SAME(Size, Alignment, Flags) \
366 { Size, Size, Alignment, Alignment, Flags }
367
368 #define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \
369 { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags }
370
371 #define CheckInfoClass(Class, BufferLen, ClassList, StatusVar, Mode) \
372 do { \
373 if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
374 { \
375 if(!(ClassList[Class].Flags & ICIF_##Mode)) \
376 { \
377 *(StatusVar) = STATUS_INVALID_INFO_CLASS; \
378 } \
379 else if(ClassList[Class].RequiredSize##Mode > 0 && \
380 (BufferLen) != ClassList[Class].RequiredSize##Mode) \
381 { \
382 if(!(ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \
383 (BufferLen) != ClassList[Class].RequiredSize##Mode) \
384 { \
385 *(StatusVar) = STATUS_INFO_LENGTH_MISMATCH; \
386 } \
387 } \
388 } \
389 else \
390 { \
391 *(StatusVar) = STATUS_INVALID_INFO_CLASS; \
392 } \
393 } while(0)
394
395
396 #define GetInfoClassAlignment(Class, ClassList, AlignmentVar, Mode) \
397 do { \
398 if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \
399 { \
400 *(AlignmentVar) = ClassList[Class].Alignment##Mode; \
401 } \
402 else \
403 { \
404 *(AlignmentVar) = sizeof(ULONG); \
405 } \
406 } while(0)
407
408 #define ProbeQueryInfoBuffer(Buffer, BufferLen, Alignment, RetLen, PrevMode, StatusVar) \
409 do { \
410 if(PrevMode == UserMode) \
411 { \
412 _SEH_TRY \
413 { \
414 ProbeForWrite(Buffer, \
415 BufferLen, \
416 Alignment); \
417 if(RetLen != NULL) \
418 { \
419 ProbeForWrite(RetLen, \
420 sizeof(ULONG), \
421 1); \
422 } \
423 } \
424 _SEH_HANDLE \
425 { \
426 *(StatusVar) = _SEH_GetExceptionCode(); \
427 } \
428 _SEH_END; \
429 \
430 if(!NT_SUCCESS(*(StatusVar))) \
431 { \
432 DPRINT1("ProbeQueryInfoBuffer failed: 0x%x\n", *(StatusVar)); \
433 return *(StatusVar); \
434 } \
435 } \
436 } while(0)
437
438 #define ProbeSetInfoBuffer(Buffer, BufferLen, Alignment, PrevMode, StatusVar) \
439 do { \
440 if(PrevMode == UserMode) \
441 { \
442 _SEH_TRY \
443 { \
444 ProbeForRead(Buffer, \
445 BufferLen, \
446 Alignment); \
447 } \
448 _SEH_HANDLE \
449 { \
450 *(StatusVar) = _SEH_GetExceptionCode(); \
451 } \
452 _SEH_END; \
453 \
454 if(!NT_SUCCESS(*(StatusVar))) \
455 { \
456 DPRINT1("ProbeAllInfoBuffer failed: 0x%x\n", *(StatusVar)); \
457 return *(StatusVar); \
458 } \
459 } \
460 } while(0)
461
462 #define DefaultSetInfoBufferCheck(Class, ClassList, Buffer, BufferLen, PrevMode, StatusVar) \
463 do { \
464 ULONG _Alignment; \
465 /* get the preferred alignment for the information class or return */ \
466 /* default alignment in case the class doesn't exist */ \
467 GetInfoClassAlignment(Class, \
468 ClassList, \
469 &_Alignment, \
470 SET); \
471 \
472 /* probe the ENTIRE buffers and return on failure */ \
473 ProbeSetInfoBuffer(Buffer, \
474 BufferLen, \
475 _Alignment, \
476 PrevMode, \
477 StatusVar); \
478 \
479 /* validate information class index and check buffer size */ \
480 CheckInfoClass(Class, \
481 BufferLen, \
482 ClassList, \
483 StatusVar, \
484 SET); \
485 } while(0)
486
487 #define DefaultQueryInfoBufferCheck(Class, ClassList, Buffer, BufferLen, RetLen, PrevMode, StatusVar) \
488 do { \
489 ULONG _Alignment; \
490 /* get the preferred alignment for the information class or return */ \
491 /* alignment in case the class doesn't exist */ \
492 GetInfoClassAlignment(Class, \
493 ClassList, \
494 &_Alignment, \
495 QUERY); \
496 \
497 /* probe the ENTIRE buffers and return on failure */ \
498 ProbeQueryInfoBuffer(Buffer, \
499 BufferLen, \
500 _Alignment, \
501 RetLen, \
502 PrevMode, \
503 StatusVar); \
504 \
505 /* validate information class index and check buffer size */ \
506 CheckInfoClass(Class, \
507 BufferLen, \
508 ClassList, \
509 StatusVar, \
510 QUERY); \
511 } while(0)
512
513 #endif /* __INCLUDE_INTERNAL_OBJMGR_H */