Merge 25584, 25588.
[reactos.git] / reactos / ntoskrnl / ob / obhandle.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/obhandle.c
5 * PURPOSE: Manages all functions related to the Object Manager handle
6 * implementation, including creating and destroying handles
7 * and/or handle tables, duplicating objects, and setting the
8 * permanent or temporary flags.
9 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
10 * Eric Kohl
11 * Thomas Weidenmueller (w3seek@reactos.org)
12 */
13
14 /* INCLUDES ******************************************************************/
15
16 #include <ntoskrnl.h>
17 #define NDEBUG
18 #include <internal/debug.h>
19
20 PHANDLE_TABLE ObpKernelHandleTable = NULL;
21
22 /* PRIVATE FUNCTIONS *********************************************************/
23
24 NTSTATUS
25 NTAPI
26 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader,
27 IN POBJECT_TYPE ObjectType)
28 {
29 POBJECT_HEADER_QUOTA_INFO ObjectQuota;
30 ULONG PagedPoolCharge, NonPagedPoolCharge;
31 PEPROCESS Process;
32
33 /* Get quota information */
34 ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader);
35
36 /* Check if this is a new object */
37 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO)
38 {
39 /* Remove the flag */
40 ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO;
41 if (ObjectQuota)
42 {
43 /* We have a quota, get the charges */
44 PagedPoolCharge = ObjectQuota->PagedPoolCharge;
45 NonPagedPoolCharge = ObjectQuota->NonPagedPoolCharge;
46 }
47 else
48 {
49 /* Get it from the object type */
50 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
51 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
52 }
53
54 /*
55 * Charge the quota
56 * FIXME: This is a *COMPLETE* guess and probably defintely not the way to do this.
57 */
58 Process = PsGetCurrentProcess();
59 Process->QuotaBlock->QuotaEntry[PagedPool].Usage += PagedPoolCharge;
60 Process->QuotaBlock->QuotaEntry[NonPagedPool].Usage += NonPagedPoolCharge;
61 ObjectHeader->QuotaBlockCharged = Process->QuotaBlock;
62 }
63
64 /* Return success */
65 return STATUS_SUCCESS;
66 }
67
68 /*++
69 * @name ObpDecrementHandleCount
70 *
71 * The ObpDecrementHandleCount routine <FILLMEIN>
72 *
73 * @param ObjectBody
74 * <FILLMEIN>.
75 *
76 * @param Process
77 * <FILLMEIN>.
78 *
79 * @param GrantedAccess
80 * <FILLMEIN>.
81 *
82 * @return None.
83 *
84 * @remarks None.
85 *
86 *--*/
87 VOID
88 NTAPI
89 ObpDecrementHandleCount(IN PVOID ObjectBody,
90 IN PEPROCESS Process,
91 IN ACCESS_MASK GrantedAccess)
92 {
93 POBJECT_HEADER ObjectHeader;
94 POBJECT_TYPE ObjectType;
95 LONG SystemHandleCount, ProcessHandleCount;
96 LONG NewCount;
97 POBJECT_HEADER_CREATOR_INFO CreatorInfo;
98
99 /* Get the object type and header */
100 ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
101 ObjectType = ObjectHeader->Type;
102 OBTRACE(OB_HANDLE_DEBUG,
103 "%s - Decrementing count for: %p. HC LC %lx %lx\n",
104 __FUNCTION__,
105 ObjectBody,
106 ObjectHeader->HandleCount,
107 ObjectHeader->PointerCount);
108
109 /* Lock the object type */
110 ObpEnterObjectTypeMutex(ObjectType);
111
112 /* FIXME: The process handle count should be in the Handle DB. Investigate */
113 SystemHandleCount = ObjectHeader->HandleCount;
114 ProcessHandleCount = 0;
115
116 /* Decrement the handle count */
117 NewCount = InterlockedDecrement(&ObjectHeader->HandleCount);
118
119 /* Check if we're out of handles */
120 if (!NewCount)
121 {
122 /* Get the creator info */
123 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
124 if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
125 {
126 /* Remove it from the list and re-initialize it */
127 RemoveEntryList(&CreatorInfo->TypeList);
128 InitializeListHead(&CreatorInfo->TypeList);
129 }
130 }
131
132 /* Release the lock */
133 ObpLeaveObjectTypeMutex(ObjectType);
134
135 /* Check if we have a close procedure */
136 if (ObjectType->TypeInfo.CloseProcedure)
137 {
138 /* Call it */
139 ObjectType->TypeInfo.CloseProcedure(Process,
140 ObjectBody,
141 GrantedAccess,
142 ProcessHandleCount,
143 SystemHandleCount);
144 }
145
146 /* Check if we should delete the object */
147 ObpDeleteNameCheck(ObjectBody);
148
149 /* Decrease the total number of handles for this type */
150 InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfHandles);
151 OBTRACE(OB_HANDLE_DEBUG,
152 "%s - Decremented count for: %p. HC LC %lx %lx\n",
153 __FUNCTION__,
154 ObjectBody,
155 ObjectHeader->HandleCount,
156 ObjectHeader->PointerCount);
157 }
158
159 /*++
160 * @name ObpCloseHandleTableEntry
161 *
162 * The ObpCloseHandleTableEntry routine <FILLMEIN>
163 *
164 * @param HandleTable
165 * <FILLMEIN>.
166 *
167 * @param HandleEntry
168 * <FILLMEIN>.
169 *
170 * @param Handle
171 * <FILLMEIN>.
172 *
173 * @param AccessMode
174 * <FILLMEIN>.
175 *
176 * @param IgnoreHandleProtection
177 * <FILLMEIN>.
178 *
179 * @return <FILLMEIN>.
180 *
181 * @remarks None.
182 *
183 *--*/
184 NTSTATUS
185 NTAPI
186 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
187 IN PHANDLE_TABLE_ENTRY HandleEntry,
188 IN HANDLE Handle,
189 IN KPROCESSOR_MODE AccessMode,
190 IN BOOLEAN IgnoreHandleProtection)
191 {
192 PVOID Body;
193 POBJECT_TYPE ObjectType;
194 POBJECT_HEADER ObjectHeader;
195 ACCESS_MASK GrantedAccess;
196 PAGED_CODE();
197
198 /* Get the object data */
199 ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
200 ObjectType = ObjectHeader->Type;
201 Body = &ObjectHeader->Body;
202 GrantedAccess = HandleEntry->GrantedAccess;
203 OBTRACE(OB_HANDLE_DEBUG,
204 "%s - Closing handle: %lx for %p. HC LC %lx %lx\n",
205 __FUNCTION__,
206 Handle,
207 Body,
208 ObjectHeader->HandleCount,
209 ObjectHeader->PointerCount);
210
211 /* Check if the object has an Okay To Close procedure */
212 if (ObjectType->TypeInfo.OkayToCloseProcedure)
213 {
214 /* Call it and check if it's not letting us close it */
215 if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(),
216 Body,
217 Handle,
218 AccessMode))
219 {
220 /* Fail */
221 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
222 return STATUS_HANDLE_NOT_CLOSABLE;
223 }
224 }
225
226 /* The callback allowed us to close it, but does the handle itself? */
227 if ((HandleEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) &&
228 !(IgnoreHandleProtection))
229 {
230 /* It doesn't, are we from user mode? */
231 if (AccessMode != KernelMode)
232 {
233 /* We are! Unlock the entry */
234 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
235
236 /* Make sure we have an exception port */
237 if (PsGetCurrentProcess()->ExceptionPort)
238 {
239 /* Raise an exception */
240 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
241 }
242 else
243 {
244 /* Return the error isntead */
245 return STATUS_HANDLE_NOT_CLOSABLE;
246 }
247 }
248
249 /* Otherwise, we are kernel mode, so unlock the entry and return */
250 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
251 return STATUS_HANDLE_NOT_CLOSABLE;
252 }
253
254 /* Destroy and unlock the handle entry */
255 ExDestroyHandleByEntry(HandleTable, HandleEntry, Handle);
256
257 /* Now decrement the handle count */
258 ObpDecrementHandleCount(Body, PsGetCurrentProcess(), GrantedAccess);
259
260 /* Dereference the object as well */
261 ASSERT(ObjectHeader->Type);
262 ASSERT(ObjectHeader->PointerCount != 0xCCCCCCCC);
263
264 ObDereferenceObject(Body);
265
266 /* Return to caller */
267 OBTRACE(OB_HANDLE_DEBUG,
268 "%s - Closed handle: %lx for %p. HC LC %lx %lx\n",
269 __FUNCTION__,
270 Handle,
271 Body,
272 ObjectHeader->HandleCount,
273 ObjectHeader->PointerCount);
274 return STATUS_SUCCESS;
275 }
276
277 /*++
278 * @name ObpIncrementHandleCount
279 *
280 * The ObpIncrementHandleCount routine <FILLMEIN>
281 *
282 * @param Object
283 * <FILLMEIN>.
284 *
285 * @param AccessState
286 * <FILLMEIN>.
287 *
288 * @param AccessMode
289 * <FILLMEIN>.
290 *
291 * @param HandleAttributes
292 * <FILLMEIN>.
293 *
294 * @param Process
295 * <FILLMEIN>.
296 *
297 * @param OpenReason
298 * <FILLMEIN>.
299 *
300 * @return <FILLMEIN>.
301 *
302 * @remarks None.
303 *
304 *--*/
305 NTSTATUS
306 NTAPI
307 ObpIncrementHandleCount(IN PVOID Object,
308 IN PACCESS_STATE AccessState,
309 IN KPROCESSOR_MODE AccessMode,
310 IN ULONG HandleAttributes,
311 IN PEPROCESS Process,
312 IN OB_OPEN_REASON OpenReason)
313 {
314 POBJECT_HEADER ObjectHeader;
315 POBJECT_TYPE ObjectType;
316 ULONG ProcessHandleCount;
317 NTSTATUS Status;
318
319 /* Get the object header and type */
320 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
321 ObjectType = ObjectHeader->Type;
322 OBTRACE(OB_HANDLE_DEBUG,
323 "%s - Incrementing count for: %p. Reason: %lx. HC LC %lx %lx\n",
324 __FUNCTION__,
325 Object,
326 OpenReason,
327 ObjectHeader->HandleCount,
328 ObjectHeader->PointerCount);
329
330 /* Lock the object type */
331 ObpEnterObjectTypeMutex(ObjectType);
332
333 /* Charge quota and remove the creator info flag */
334 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType);
335 if (!NT_SUCCESS(Status)) return Status;
336
337 /* Check if we're opening an existing handle */
338 if (OpenReason == ObOpenHandle)
339 {
340 /* Validate the caller's access to this object */
341 if (!ObCheckObjectAccess(Object,
342 AccessState,
343 TRUE,
344 AccessMode,
345 &Status))
346 {
347 /* Access was denied, so fail */
348 return Status;
349 }
350 }
351 else if (OpenReason == ObCreateHandle)
352 {
353 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
354 if (AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED)
355 {
356 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
357 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED;
358 AccessState->RemainingDesiredAccess |= GENERIC_ALL;
359 }
360
361 /* Check if we have to map the GENERIC mask */
362 if (AccessState->RemainingDesiredAccess & GENERIC_ACCESS)
363 {
364 /* Map it to the correct access masks */
365 RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
366 &ObjectType->TypeInfo.GenericMapping);
367 }
368 }
369
370 /* Increase the handle count */
371 InterlockedIncrement(&ObjectHeader->HandleCount);
372
373 /* Release the lock */
374 ObpLeaveObjectTypeMutex(ObjectType);
375
376 /* FIXME: Use the Handle Database */
377 ProcessHandleCount = 0;
378
379 /* Check if we have an open procedure */
380 if (ObjectType->TypeInfo.OpenProcedure)
381 {
382 /* Call it */
383 ObjectType->TypeInfo.OpenProcedure(OpenReason,
384 Process,
385 Object,
386 AccessState->PreviouslyGrantedAccess,
387 ProcessHandleCount);
388 }
389
390 /* Increase total number of handles */
391 InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
392 OBTRACE(OB_HANDLE_DEBUG,
393 "%s - Incremented count for: %p. Reason: %lx HC LC %lx %lx\n",
394 __FUNCTION__,
395 Object,
396 OpenReason,
397 ObjectHeader->HandleCount,
398 ObjectHeader->PointerCount);
399 return STATUS_SUCCESS;
400 }
401
402 /*++
403 * @name ObpIncrementUnnamedHandleCount
404 *
405 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
406 *
407 * @param Object
408 * <FILLMEIN>.
409 *
410 * @param AccessState
411 * <FILLMEIN>.
412 *
413 * @param AccessMode
414 * <FILLMEIN>.
415 *
416 * @param HandleAttributes
417 * <FILLMEIN>.
418 *
419 * @param Process
420 * <FILLMEIN>.
421 *
422 * @param OpenReason
423 * <FILLMEIN>.
424 *
425 * @return <FILLMEIN>.
426 *
427 * @remarks None.
428 *
429 *--*/
430 NTSTATUS
431 NTAPI
432 ObpIncrementUnnamedHandleCount(IN PVOID Object,
433 IN PACCESS_MASK DesiredAccess,
434 IN KPROCESSOR_MODE AccessMode,
435 IN ULONG HandleAttributes,
436 IN PEPROCESS Process)
437 {
438 POBJECT_HEADER ObjectHeader;
439 POBJECT_TYPE ObjectType;
440 ULONG ProcessHandleCount;
441 NTSTATUS Status;
442
443 /* Get the object header and type */
444 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
445 ObjectType = ObjectHeader->Type;
446 OBTRACE(OB_HANDLE_DEBUG,
447 "%s - Incrementing count for: %p. UNNAMED. HC LC %lx %lx\n",
448 __FUNCTION__,
449 Object,
450 ObjectHeader->HandleCount,
451 ObjectHeader->PointerCount);
452
453 /* Lock the object type */
454 ObpEnterObjectTypeMutex(ObjectType);
455
456 /* Charge quota and remove the creator info flag */
457 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType);
458 if (!NT_SUCCESS(Status)) return Status;
459
460 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
461 if (*DesiredAccess & MAXIMUM_ALLOWED)
462 {
463 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
464 *DesiredAccess &= ~MAXIMUM_ALLOWED;
465 *DesiredAccess |= GENERIC_ALL;
466 }
467
468 /* Check if we have to map the GENERIC mask */
469 if (*DesiredAccess & GENERIC_ACCESS)
470 {
471 /* Map it to the correct access masks */
472 RtlMapGenericMask(DesiredAccess,
473 &ObjectType->TypeInfo.GenericMapping);
474 }
475
476 /* Increase the handle count */
477 InterlockedIncrement(&ObjectHeader->HandleCount);
478
479 /* Release the object type */
480 ObpLeaveObjectTypeMutex(ObjectType);
481
482 /* FIXME: Use the Handle Database */
483 ProcessHandleCount = 0;
484
485 /* Check if we have an open procedure */
486 if (ObjectType->TypeInfo.OpenProcedure)
487 {
488 /* Call it */
489 ObjectType->TypeInfo.OpenProcedure(ObCreateHandle,
490 Process,
491 Object,
492 *DesiredAccess,
493 ProcessHandleCount);
494 }
495
496 /* Increase total number of handles */
497 InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
498 OBTRACE(OB_HANDLE_DEBUG,
499 "%s - Incremented count for: %p. UNNAMED HC LC %lx %lx\n",
500 __FUNCTION__,
501 Object,
502 ObjectHeader->HandleCount,
503 ObjectHeader->PointerCount);
504 return STATUS_SUCCESS;
505 }
506
507 /*++
508 * @name ObpCreateUnnamedHandle
509 *
510 * The ObpCreateUnnamedHandle routine <FILLMEIN>
511 *
512 * @param Object
513 * <FILLMEIN>.
514 *
515 * @param DesiredAccess
516 * <FILLMEIN>.
517 *
518 * @param AdditionalReferences
519 * <FILLMEIN>.
520 *
521 * @param HandleAttributes
522 * <FILLMEIN>.
523 *
524 * @param AccessMode
525 * <FILLMEIN>.
526 *
527 * @param ReturnedObject
528 * <FILLMEIN>.
529 *
530 * @param ReturnedHandle
531 * <FILLMEIN>.
532 *
533 * @return <FILLMEIN>.
534 *
535 * @remarks None.
536 *
537 *--*/
538 NTSTATUS
539 NTAPI
540 ObpCreateUnnamedHandle(IN PVOID Object,
541 IN ACCESS_MASK DesiredAccess,
542 IN ULONG AdditionalReferences,
543 IN ULONG HandleAttributes,
544 IN KPROCESSOR_MODE AccessMode,
545 OUT PVOID *ReturnedObject,
546 OUT PHANDLE ReturnedHandle)
547 {
548 HANDLE_TABLE_ENTRY NewEntry;
549 POBJECT_HEADER ObjectHeader;
550 HANDLE Handle;
551 KAPC_STATE ApcState;
552 BOOLEAN AttachedToProcess = FALSE;
553 PVOID HandleTable;
554 NTSTATUS Status;
555 ULONG i;
556 PAGED_CODE();
557
558 /* Get the object header and type */
559 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
560 OBTRACE(OB_HANDLE_DEBUG,
561 "%s - Creating handle for: %p. UNNAMED. HC LC %lx %lx\n",
562 __FUNCTION__,
563 Object,
564 ObjectHeader->HandleCount,
565 ObjectHeader->PointerCount);
566
567 /* Check if this is a kernel handle */
568 if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode))
569 {
570 /* Set the handle table */
571 HandleTable = ObpKernelHandleTable;
572
573 /* Check if we're not in the system process */
574 if (PsGetCurrentProcess() != PsInitialSystemProcess)
575 {
576 /* Attach to the system process */
577 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
578 AttachedToProcess = TRUE;
579 }
580 }
581 else
582 {
583 /* Get the current handle table */
584 HandleTable = PsGetCurrentProcess()->ObjectTable;
585 }
586
587 /* Increment the handle count */
588 Status = ObpIncrementUnnamedHandleCount(Object,
589 &DesiredAccess,
590 AccessMode,
591 HandleAttributes,
592 PsGetCurrentProcess());
593 if (!NT_SUCCESS(Status))
594 {
595 /*
596 * We failed (meaning security failure, according to NT Internals)
597 * detach and return
598 */
599 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
600 return Status;
601 }
602
603 /* Save the object header (assert its validity too) */
604 ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
605 NewEntry.Object = ObjectHeader;
606
607 /* Mask out the internal attributes */
608 NewEntry.ObAttributes |= HandleAttributes &
609 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
610 EX_HANDLE_ENTRY_INHERITABLE |
611 EX_HANDLE_ENTRY_AUDITONCLOSE);
612
613 /* Save the access mask */
614 NewEntry.GrantedAccess = DesiredAccess;
615
616 /* Handle extra references */
617 if (AdditionalReferences)
618 {
619 /* Make a copy in case we fail later below */
620 i = AdditionalReferences;
621 while (i--)
622 {
623 /* Increment the count */
624 InterlockedIncrement(&ObjectHeader->PointerCount);
625 }
626 }
627
628 /*
629 * Create the actual handle. We'll need to do this *after* calling
630 * ObpIncrementHandleCount to make sure that Object Security is valid
631 * (specified in Gl00my documentation on Ob)
632 */
633 OBTRACE(OB_HANDLE_DEBUG,
634 "%s - Handle Properties: [%p-%lx-%lx]\n",
635 __FUNCTION__,
636 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
637 Handle = ExCreateHandle(HandleTable, &NewEntry);
638
639 /* Detach if needed */
640 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
641
642 /* Make sure we got a handle */
643 if (Handle)
644 {
645 /* Check if this was a kernel handle */
646 if (HandleAttributes & OBJ_KERNEL_HANDLE)
647 {
648 /* Set the kernel handle bit */
649 Handle = ObMarkHandleAsKernelHandle(Handle);
650 }
651
652 /* Return handle and object */
653 *ReturnedHandle = Handle;
654 if (ReturnedObject) *ReturnedObject = Object;
655 OBTRACE(OB_HANDLE_DEBUG,
656 "%s - Returning Handle: %lx HC LC %lx %lx\n",
657 __FUNCTION__,
658 Handle,
659 ObjectHeader->HandleCount,
660 ObjectHeader->PointerCount);
661 return STATUS_SUCCESS;
662 }
663
664 /* Handle extra references */
665 while (AdditionalReferences--)
666 {
667 /* Decrement the count */
668 InterlockedDecrement(&ObjectHeader->PointerCount);
669 }
670
671 /* Decrement the handle count and detach */
672 ObpDecrementHandleCount(&ObjectHeader->Body,
673 PsGetCurrentProcess(),
674 NewEntry.GrantedAccess);
675 return STATUS_INSUFFICIENT_RESOURCES;
676 }
677
678 /*++
679 * @name ObpCreateHandle
680 *
681 * The ObpCreateHandle routine <FILLMEIN>
682 *
683 * @param OpenReason
684 * <FILLMEIN>.
685 *
686 * @param Object
687 * <FILLMEIN>.
688 *
689 * @param Type
690 * <FILLMEIN>.
691 *
692 * @param AccessState
693 * <FILLMEIN>.
694 *
695 * @param AdditionalReferences
696 * <FILLMEIN>.
697 *
698 * @param HandleAttributes
699 * <FILLMEIN>.
700 *
701 * @param AccessMode
702 * <FILLMEIN>.
703 *
704 * @param ReturnedObject
705 * <FILLMEIN>.
706 *
707 * @param ReturnedHandle
708 * <FILLMEIN>.
709 *
710 * @return <FILLMEIN>.
711 *
712 * @remarks Gloomy says OpenReason is "enables Security" if == 1.
713 * since this function *has* to call ObpIncrementHandleCount,
714 * which needs to somehow know the OpenReason, and since
715 * ObOpenHandle == 1, I'm guessing this is actually the
716 * OpenReason. Also makes sense since this function is shared
717 * by Duplication, Creation and Opening..
718 *
719 *--*/
720 NTSTATUS
721 NTAPI
722 ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
723 IN PVOID Object,
724 IN POBJECT_TYPE Type OPTIONAL,
725 IN PACCESS_STATE AccessState,
726 IN ULONG AdditionalReferences,
727 IN ULONG HandleAttributes,
728 IN KPROCESSOR_MODE AccessMode,
729 OUT PVOID *ReturnedObject,
730 OUT PHANDLE ReturnedHandle)
731 {
732 HANDLE_TABLE_ENTRY NewEntry;
733 POBJECT_HEADER ObjectHeader;
734 HANDLE Handle;
735 KAPC_STATE ApcState;
736 BOOLEAN AttachedToProcess = FALSE;
737 POBJECT_TYPE ObjectType;
738 PVOID HandleTable;
739 NTSTATUS Status;
740 ULONG i;
741 PAGED_CODE();
742
743 /* Get the object header and type */
744 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
745 ObjectType = ObjectHeader->Type;
746 OBTRACE(OB_HANDLE_DEBUG,
747 "%s - Creating handle for: %p. Reason: %lx. HC LC %lx %lx\n",
748 __FUNCTION__,
749 Object,
750 OpenReason,
751 ObjectHeader->HandleCount,
752 ObjectHeader->PointerCount);
753
754 /* Check if the types match */
755 if ((Type) && (ObjectType != Type)) return STATUS_OBJECT_TYPE_MISMATCH;
756
757 /* Check if this is a kernel handle */
758 if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode == KernelMode))
759 {
760 /* Set the handle table */
761 HandleTable = ObpKernelHandleTable;
762
763 /* Check if we're not in the system process */
764 if (PsGetCurrentProcess() != PsInitialSystemProcess)
765 {
766 /* Attach to the system process */
767 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
768 AttachedToProcess = TRUE;
769 }
770 }
771 else
772 {
773 /* Get the current handle table */
774 HandleTable = PsGetCurrentProcess()->ObjectTable;
775 }
776
777 /* Increment the handle count */
778 Status = ObpIncrementHandleCount(Object,
779 AccessState,
780 AccessMode,
781 HandleAttributes,
782 PsGetCurrentProcess(),
783 OpenReason);
784 if (!NT_SUCCESS(Status))
785 {
786 /*
787 * We failed (meaning security failure, according to NT Internals)
788 * detach and return
789 */
790 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
791 return Status;
792 }
793
794 /* Save the object header (assert its validity too) */
795 ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
796 NewEntry.Object = ObjectHeader;
797
798 /* Mask out the internal attributes */
799 NewEntry.ObAttributes |= HandleAttributes &
800 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
801 EX_HANDLE_ENTRY_INHERITABLE |
802 EX_HANDLE_ENTRY_AUDITONCLOSE);
803
804 /* Save the access mask */
805 NewEntry.GrantedAccess = AccessState->RemainingDesiredAccess |
806 AccessState->PreviouslyGrantedAccess;
807
808 /* Handle extra references */
809 if (AdditionalReferences)
810 {
811 /* Make a copy in case we fail later below */
812 i = AdditionalReferences;
813 while (i--)
814 {
815 /* Increment the count */
816 InterlockedIncrement(&ObjectHeader->PointerCount);
817 }
818 }
819
820 /*
821 * Create the actual handle. We'll need to do this *after* calling
822 * ObpIncrementHandleCount to make sure that Object Security is valid
823 * (specified in Gl00my documentation on Ob)
824 */
825 OBTRACE(OB_HANDLE_DEBUG,
826 "%s - Handle Properties: [%p-%lx-%lx]\n",
827 __FUNCTION__,
828 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
829 Handle = ExCreateHandle(HandleTable, &NewEntry);
830
831 /* Detach if needed */
832 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
833
834 /* Make sure we got a handle */
835 if (Handle)
836 {
837 /* Check if this was a kernel handle */
838 if (HandleAttributes & OBJ_KERNEL_HANDLE)
839 {
840 /* Set the kernel handle bit */
841 Handle = ObMarkHandleAsKernelHandle(Handle);
842 }
843
844 /* Return handle and object */
845 *ReturnedHandle = Handle;
846 if (ReturnedObject) *ReturnedObject = Object;
847 OBTRACE(OB_HANDLE_DEBUG,
848 "%s - Returning Handle: %lx HC LC %lx %lx\n",
849 __FUNCTION__,
850 Handle,
851 ObjectHeader->HandleCount,
852 ObjectHeader->PointerCount);
853 return STATUS_SUCCESS;
854 }
855
856 /* Handle extra references */
857 while (AdditionalReferences--)
858 {
859 /* Increment the count */
860 InterlockedDecrement(&ObjectHeader->PointerCount);
861 }
862
863 /* Decrement the handle count and detach */
864 ObpDecrementHandleCount(&ObjectHeader->Body,
865 PsGetCurrentProcess(),
866 NewEntry.GrantedAccess);
867 return STATUS_INSUFFICIENT_RESOURCES;
868 }
869
870 /*++
871 * @name ObpCloseHandle
872 *
873 * The ObpCloseHandle routine <FILLMEIN>
874 *
875 * @param Handle
876 * <FILLMEIN>.
877 *
878 * @param AccessMode
879 * <FILLMEIN>.
880 *
881 * @return <FILLMEIN>.
882 *
883 * @remarks None.
884 *
885 *--*/
886 NTSTATUS
887 NTAPI
888 ObpCloseHandle(IN HANDLE Handle,
889 IN KPROCESSOR_MODE AccessMode)
890 {
891 PVOID HandleTable;
892 BOOLEAN AttachedToProcess = FALSE;
893 KAPC_STATE ApcState;
894 PHANDLE_TABLE_ENTRY HandleTableEntry;
895 NTSTATUS Status;
896 PAGED_CODE();
897 OBTRACE(OB_HANDLE_DEBUG,
898 "%s - Closing handle: %lx\n", __FUNCTION__, Handle);
899
900 /* Check if we're dealing with a kernel handle */
901 if (ObIsKernelHandle(Handle, AccessMode))
902 {
903 /* Use the kernel table and convert the handle */
904 HandleTable = ObpKernelHandleTable;
905 Handle = ObKernelHandleToHandle(Handle);
906
907 /* Check if we're not in the system process */
908 if (PsGetCurrentProcess() != PsInitialSystemProcess)
909 {
910 /* Attach to the system process */
911 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
912 AttachedToProcess = TRUE;
913 }
914 }
915 else
916 {
917 /* Use the process's handle table */
918 HandleTable = PsGetCurrentProcess()->ObjectTable;
919 }
920
921 /* Enter a critical region to protect handle access */
922 KeEnterCriticalRegion();
923
924 /* Get the handle entry */
925 HandleTableEntry = ExMapHandleToPointer(HandleTable, Handle);
926 if (HandleTableEntry)
927 {
928 /* Now close the entry */
929 Status = ObpCloseHandleTableEntry(HandleTable,
930 HandleTableEntry,
931 Handle,
932 AccessMode,
933 FALSE);
934
935 /* We can quit the critical region now */
936 KeLeaveCriticalRegion();
937
938 /* Detach and return success */
939 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
940 return STATUS_SUCCESS;
941 }
942 else
943 {
944 /* We failed, quit the critical region */
945 KeLeaveCriticalRegion();
946
947 /* Detach */
948 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
949
950 /* Check if this was a user-mode caller with a valid exception port */
951 if ((AccessMode != KernelMode) &&
952 (PsGetCurrentProcess()->ExceptionPort))
953 {
954 /* Raise an exception */
955 Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
956 }
957 else
958 {
959 /* Just return the status */
960 Status = STATUS_INVALID_HANDLE;
961 }
962 }
963
964 /* Return status */
965 OBTRACE(OB_HANDLE_DEBUG,
966 "%s - Closed handle: %lx S: %lx\n",
967 __FUNCTION__, Handle, Status);
968 return Status;
969 }
970
971 /*++
972 * @name ObpSetHandleAttributes
973 *
974 * The ObpSetHandleAttributes routine <FILLMEIN>
975 *
976 * @param HandleTable
977 * <FILLMEIN>.
978 *
979 * @param HandleTableEntry
980 * <FILLMEIN>.
981 *
982 * @param Context
983 * <FILLMEIN>.
984 *
985 * @return <FILLMEIN>.
986 *
987 * @remarks None.
988 *
989 *--*/
990 BOOLEAN
991 NTAPI
992 ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
993 IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
994 IN PVOID Context)
995 {
996 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo =
997 (POBP_SET_HANDLE_ATTRIBUTES_CONTEXT)Context;
998 POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
999 PAGED_CODE();
1000
1001 /* Don't allow operations on kernel objects */
1002 if ((ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) &&
1003 (SetHandleInfo->PreviousMode != KernelMode))
1004 {
1005 /* Fail */
1006 return FALSE;
1007 }
1008
1009 /* Check if making the handle inheritable */
1010 if (SetHandleInfo->Information.Inherit)
1011 {
1012 /* Check if inheriting is not supported for this object */
1013 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & OBJ_INHERIT)
1014 {
1015 /* Fail without changing anything */
1016 return FALSE;
1017 }
1018
1019 /* Set the flag */
1020 HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
1021 }
1022 else
1023 {
1024 /* Otherwise this implies we're removing the flag */
1025 HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
1026 }
1027
1028 /* Check if making the handle protected */
1029 if (SetHandleInfo->Information.ProtectFromClose)
1030 {
1031 /* Set the flag */
1032 HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
1033 }
1034 else
1035 {
1036 /* Otherwise, remove it */
1037 HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
1038 }
1039
1040 /* Return success */
1041 return TRUE;
1042 }
1043
1044 /*++
1045 * @name ObpCloseHandleCallback
1046 *
1047 * The ObpCloseHandleCallback routine <FILLMEIN>
1048 *
1049 * @param HandleTable
1050 * <FILLMEIN>.
1051 *
1052 * @param Object
1053 * <FILLMEIN>.
1054 *
1055 * @param GrantedAccess
1056 * <FILLMEIN>.
1057 *
1058 * @param Context
1059 * <FILLMEIN>.
1060 *
1061 * @return <FILLMEIN>.
1062 *
1063 * @remarks None.
1064 *
1065 *--*/
1066 VOID
1067 NTAPI
1068 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry,
1069 IN HANDLE Handle,
1070 IN PVOID Context)
1071 {
1072 POBP_CLOSE_HANDLE_CONTEXT CloseContext = (POBP_CLOSE_HANDLE_CONTEXT)Context;
1073
1074 /* Simply decrement the handle count */
1075 ObpCloseHandleTableEntry(CloseContext->HandleTable,
1076 HandleTableEntry,
1077 Handle,
1078 CloseContext->AccessMode,
1079 TRUE);
1080 }
1081
1082 /*++
1083 * @name ObpDuplicateHandleCallback
1084 *
1085 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1086 *
1087 * @param HandleTable
1088 * <FILLMEIN>.
1089 *
1090 * @param HandleTableEntry
1091 * <FILLMEIN>.
1092 *
1093 * @param Context
1094 * <FILLMEIN>.
1095 *
1096 * @return <FILLMEIN>.
1097 *
1098 * @remarks None.
1099 *
1100 *--*/
1101 BOOLEAN
1102 NTAPI
1103 ObpDuplicateHandleCallback(IN PHANDLE_TABLE HandleTable,
1104 IN PHANDLE_TABLE_ENTRY HandleTableEntry,
1105 IN PVOID Context)
1106 {
1107 POBJECT_HEADER ObjectHeader;
1108 BOOLEAN Ret = FALSE;
1109 ACCESS_STATE AccessState;
1110 NTSTATUS Status;
1111 PAGED_CODE();
1112
1113 /* Make sure that the handle is inheritable */
1114 Ret = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
1115 if (Ret)
1116 {
1117 /* Get the object header */
1118 ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
1119
1120 /* Setup the access state */
1121 AccessState.PreviouslyGrantedAccess = HandleTableEntry->GrantedAccess;
1122
1123 /* Call the shared routine for incrementing handles */
1124 Status = ObpIncrementHandleCount(&ObjectHeader->Body,
1125 &AccessState,
1126 KernelMode,
1127 HandleTableEntry->ObAttributes,
1128 PsGetCurrentProcess(),
1129 ObInheritHandle);
1130 if (!NT_SUCCESS(Status))
1131 {
1132 /* Return failure */
1133 Ret = FALSE;
1134 }
1135 else
1136 {
1137 /* Otherwise increment the pointer count */
1138 InterlockedIncrement(&ObjectHeader->PointerCount);
1139 }
1140 }
1141
1142 /* Return duplication result */
1143 return Ret;
1144 }
1145
1146 VOID
1147 NTAPI
1148 ObClearProcessHandleTable(IN PEPROCESS Process)
1149 {
1150 /* FIXME */
1151 }
1152
1153 /*++
1154 * @name ObpCreateHandleTable
1155 *
1156 * The ObpCreateHandleTable routine <FILLMEIN>
1157 *
1158 * @param Parent
1159 * <FILLMEIN>.
1160 *
1161 * @param Process
1162 * <FILLMEIN>.
1163 *
1164 * @return <FILLMEIN>.
1165 *
1166 * @remarks None.
1167 *
1168 *--*/
1169 NTSTATUS
1170 NTAPI
1171 ObpCreateHandleTable(IN PEPROCESS Parent,
1172 IN PEPROCESS Process)
1173 {
1174 PHANDLE_TABLE HandleTable;
1175 PAGED_CODE();
1176
1177 /* Check if we have a parent */
1178 if (Parent)
1179 {
1180 /* Duplicate the parent's */
1181 HandleTable = ExDupHandleTable(Process,
1182 ObpDuplicateHandleCallback,
1183 NULL,
1184 Parent->ObjectTable);
1185 }
1186 else
1187 {
1188 /* Create a new one */
1189 HandleTable = ExCreateHandleTable(Process);
1190 }
1191
1192 /* Now write it and make sure we got one */
1193 Process->ObjectTable = HandleTable;
1194 if (!HandleTable) return STATUS_INSUFFICIENT_RESOURCES;
1195
1196 /* If we got here then the table was created OK */
1197 return STATUS_SUCCESS;
1198 }
1199
1200 /*++
1201 * @name ObKillProcess
1202 *
1203 * The ObKillProcess routine <FILLMEIN>
1204 *
1205 * @param Process
1206 * <FILLMEIN>.
1207 *
1208 * @return None.
1209 *
1210 * @remarks None.
1211 *
1212 *--*/
1213 VOID
1214 NTAPI
1215 ObKillProcess(IN PEPROCESS Process)
1216 {
1217 PHANDLE_TABLE HandleTable = Process->ObjectTable;
1218 OBP_CLOSE_HANDLE_CONTEXT Context;
1219 PAGED_CODE();
1220
1221 /* Enter a critical region */
1222 KeEnterCriticalRegion();
1223
1224 /* Fill out the context */
1225 Context.AccessMode = KernelMode;
1226 Context.HandleTable = HandleTable;
1227
1228 /* Sweep the handle table to close all handles */
1229 ExSweepHandleTable(HandleTable,
1230 ObpCloseHandleCallback,
1231 &Context);
1232
1233 /* Destroy the table and leave the critical region */
1234 ExDestroyHandleTable(HandleTable);
1235 KeLeaveCriticalRegion();
1236
1237 /* Clear the object table */
1238 Process->ObjectTable = NULL;
1239 }
1240
1241 NTSTATUS
1242 NTAPI
1243 ObDuplicateObject(IN PEPROCESS SourceProcess,
1244 IN HANDLE SourceHandle,
1245 IN PEPROCESS TargetProcess OPTIONAL,
1246 IN PHANDLE TargetHandle OPTIONAL,
1247 IN ACCESS_MASK DesiredAccess,
1248 IN ULONG HandleAttributes,
1249 IN ULONG Options,
1250 IN KPROCESSOR_MODE PreviousMode)
1251 {
1252 HANDLE_TABLE_ENTRY NewHandleEntry;
1253 BOOLEAN AttachedToProcess = FALSE;
1254 PVOID SourceObject;
1255 POBJECT_HEADER ObjectHeader;
1256 POBJECT_TYPE ObjectType;
1257 HANDLE NewHandle;
1258 KAPC_STATE ApcState;
1259 NTSTATUS Status = STATUS_SUCCESS;
1260 ACCESS_MASK TargetAccess, SourceAccess;
1261 ACCESS_STATE AccessState;
1262 PACCESS_STATE PassedAccessState = NULL;
1263 AUX_DATA AuxData;
1264 PHANDLE_TABLE HandleTable = NULL;
1265 OBJECT_HANDLE_INFORMATION HandleInformation;
1266 PAGED_CODE();
1267 OBTRACE(OB_HANDLE_DEBUG,
1268 "%s - Duplicating handle: %lx for %p into %p\n",
1269 __FUNCTION__,
1270 SourceHandle,
1271 SourceProcess,
1272 TargetProcess);
1273
1274 /* Check if we're not in the source process */
1275 if (SourceProcess != PsGetCurrentProcess())
1276 {
1277 /* Attach to it */
1278 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
1279 AttachedToProcess = TRUE;
1280 }
1281
1282 /* Now reference the source handle */
1283 Status = ObReferenceObjectByHandle(SourceHandle,
1284 0,
1285 NULL,
1286 PreviousMode,
1287 (PVOID*)&SourceObject,
1288 &HandleInformation);
1289
1290 /* Check if we were attached */
1291 if (AttachedToProcess)
1292 {
1293 /* We can safely detach now */
1294 KeUnstackDetachProcess(&ApcState);
1295 AttachedToProcess = FALSE;
1296 }
1297
1298 /* Fail if we couldn't reference it */
1299 if (!NT_SUCCESS(Status)) return Status;
1300
1301 /* Get the source access */
1302 SourceAccess = HandleInformation.GrantedAccess;
1303
1304 /* Check if we're not in the target process */
1305 if (TargetProcess != PsGetCurrentProcess())
1306 {
1307 /* Attach to it */
1308 KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
1309 AttachedToProcess = TRUE;
1310 }
1311
1312 /* Check if we're duplicating the attributes */
1313 if (Options & DUPLICATE_SAME_ATTRIBUTES)
1314 {
1315 /* Duplicate them */
1316 HandleAttributes = HandleInformation.HandleAttributes;
1317 }
1318
1319 /* Check if we're duplicating the access */
1320 if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess;
1321
1322 /* Get object data */
1323 ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject);
1324 ObjectType = ObjectHeader->Type;
1325
1326 /* Fill out the entry */
1327 NewHandleEntry.Object = ObjectHeader;
1328 NewHandleEntry.ObAttributes |= HandleAttributes &
1329 (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
1330 EX_HANDLE_ENTRY_INHERITABLE |
1331 EX_HANDLE_ENTRY_AUDITONCLOSE);
1332
1333 /* Check if we're using a generic mask */
1334 if (DesiredAccess & GENERIC_ACCESS)
1335 {
1336 /* Map it */
1337 RtlMapGenericMask(&DesiredAccess, &ObjectType->TypeInfo.GenericMapping);
1338 }
1339
1340 /* Set the target access */
1341 TargetAccess = DesiredAccess;
1342 NewHandleEntry.GrantedAccess = TargetAccess;
1343
1344 /* Check if we're asking for new access */
1345 if (TargetAccess & ~SourceAccess)
1346 {
1347 /* We are. We need the security procedure to validate this */
1348 if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
1349 {
1350 /* Use our built-in access state */
1351 PassedAccessState = &AccessState;
1352 Status = SeCreateAccessState(&AccessState,
1353 &AuxData,
1354 TargetAccess,
1355 &ObjectType->TypeInfo.GenericMapping);
1356 }
1357 else
1358 {
1359 /* Otherwise we can't allow this privilege elevation */
1360 Status = STATUS_ACCESS_DENIED;
1361 }
1362 }
1363 else
1364 {
1365 /* We don't need an access state */
1366 Status = STATUS_SUCCESS;
1367 }
1368
1369 /* Make sure the access state was created OK */
1370 if (NT_SUCCESS(Status))
1371 {
1372 /* Add a new handle */
1373 Status = ObpIncrementHandleCount(SourceObject,
1374 PassedAccessState,
1375 PreviousMode,
1376 HandleAttributes,
1377 PsGetCurrentProcess(),
1378 ObDuplicateHandle);
1379
1380 /* Set the handle table, now that we know this handle was added */
1381 HandleTable = PsGetCurrentProcess()->ObjectTable;
1382 }
1383
1384 /* Check if we were attached */
1385 if (AttachedToProcess)
1386 {
1387 /* We can safely detach now */
1388 KeUnstackDetachProcess(&ApcState);
1389 AttachedToProcess = FALSE;
1390 }
1391
1392 /* Check if we have to close the source handle */
1393 if (Options & DUPLICATE_CLOSE_SOURCE)
1394 {
1395 /* Attach and close */
1396 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
1397 NtClose(SourceHandle);
1398 KeUnstackDetachProcess(&ApcState);
1399 }
1400
1401 /* Check if we had an access state */
1402 if (PassedAccessState) SeDeleteAccessState(PassedAccessState);
1403
1404 /* Now check if incrementing actually failed */
1405 if (!NT_SUCCESS(Status))
1406 {
1407 /* Dereference the source object */
1408 ObDereferenceObject(SourceObject);
1409 return Status;
1410 }
1411
1412 /* Now create the handle */
1413 NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry);
1414 if (!NewHandle)
1415 {
1416 /* Undo the increment */
1417 ObpDecrementHandleCount(SourceObject,
1418 TargetProcess,
1419 TargetAccess);
1420
1421 /* Deference the object and set failure status */
1422 ObDereferenceObject(SourceObject);
1423 Status = STATUS_INSUFFICIENT_RESOURCES;
1424 }
1425
1426 /* Return the handle */
1427 if (TargetHandle) *TargetHandle = NewHandle;
1428
1429 /* Return status */
1430 OBTRACE(OB_HANDLE_DEBUG,
1431 "%s - Duplicated handle: %lx for %p into %p. Source: %p HC PC %lx %lx\n",
1432 __FUNCTION__,
1433 NewHandle,
1434 SourceProcess,
1435 TargetProcess,
1436 SourceObject,
1437 ObjectHeader->PointerCount,
1438 ObjectHeader->HandleCount);
1439 return Status;
1440 }
1441
1442 /* PUBLIC FUNCTIONS *********************************************************/
1443
1444 /*++
1445 * @name ObOpenObjectByName
1446 * @implemented NT4
1447 *
1448 * The ObOpenObjectByName routine <FILLMEIN>
1449 *
1450 * @param ObjectAttributes
1451 * <FILLMEIN>.
1452 *
1453 * @param ObjectType
1454 * <FILLMEIN>.
1455 *
1456 * @param AccessMode
1457 * <FILLMEIN>.
1458 *
1459 * @param PassedAccessState
1460 * <FILLMEIN>.
1461 *
1462 * @param DesiredAccess
1463 * <FILLMEIN>.
1464 *
1465 * @param ParseContext
1466 * <FILLMEIN>.
1467 *
1468 * @param Handle
1469 * <FILLMEIN>.
1470 *
1471 * @return <FILLMEIN>.
1472 *
1473 * @remarks None.
1474 *
1475 *--*/
1476 NTSTATUS
1477 NTAPI
1478 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
1479 IN POBJECT_TYPE ObjectType,
1480 IN KPROCESSOR_MODE AccessMode,
1481 IN PACCESS_STATE PassedAccessState,
1482 IN ACCESS_MASK DesiredAccess,
1483 IN OUT PVOID ParseContext,
1484 OUT PHANDLE Handle)
1485 {
1486 PVOID Object = NULL;
1487 UNICODE_STRING ObjectName;
1488 OBJECT_CREATE_INFORMATION ObjectCreateInfo;
1489 NTSTATUS Status;
1490 OBP_LOOKUP_CONTEXT Context;
1491 POBJECT_HEADER ObjectHeader;
1492 AUX_DATA AuxData;
1493 PGENERIC_MAPPING GenericMapping = NULL;
1494 ACCESS_STATE AccessState;
1495 OB_OPEN_REASON OpenReason;
1496 PAGED_CODE();
1497
1498 /* Check if we didn't get any Object Attributes */
1499 if (!ObjectAttributes)
1500 {
1501 /* Fail with special status code */
1502 *Handle = NULL;
1503 return STATUS_INVALID_PARAMETER;
1504 }
1505
1506 /* Capture all the info */
1507 Status = ObpCaptureObjectAttributes(ObjectAttributes,
1508 AccessMode,
1509 TRUE,
1510 &ObjectCreateInfo,
1511 &ObjectName);
1512 if (!NT_SUCCESS(Status)) return Status;
1513
1514 /* Check if we didn't get an access state */
1515 if (!PassedAccessState)
1516 {
1517 /* Try to get the generic mapping if we can */
1518 if (ObjectType) GenericMapping = &ObjectType->TypeInfo.GenericMapping;
1519
1520 /* Use our built-in access state */
1521 PassedAccessState = &AccessState;
1522 Status = SeCreateAccessState(&AccessState,
1523 &AuxData,
1524 DesiredAccess,
1525 GenericMapping);
1526 if (!NT_SUCCESS(Status)) goto Quickie;
1527 }
1528
1529 /* Get the security descriptor */
1530 if (ObjectCreateInfo.SecurityDescriptor)
1531 {
1532 /* Save it in the access state */
1533 PassedAccessState->SecurityDescriptor =
1534 ObjectCreateInfo.SecurityDescriptor;
1535 }
1536
1537 /* Now do the lookup */
1538 Status = ObFindObject(ObjectCreateInfo.RootDirectory,
1539 &ObjectName,
1540 ObjectCreateInfo.Attributes,
1541 AccessMode,
1542 &Object,
1543 ObjectType,
1544 &Context,
1545 PassedAccessState,
1546 ObjectCreateInfo.SecurityQos,
1547 ParseContext,
1548 NULL);
1549 if (!NT_SUCCESS(Status)) goto Cleanup;
1550
1551 /* Check if this object has create information */
1552 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
1553 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO)
1554 {
1555 /* Then we are creating a new handle */
1556 OpenReason = ObCreateHandle;
1557
1558 /* Check if we still have create info */
1559 if (ObjectHeader->ObjectCreateInfo)
1560 {
1561 /* Free it */
1562 ObpFreeAndReleaseCapturedAttributes(ObjectHeader->
1563 ObjectCreateInfo);
1564 ObjectHeader->ObjectCreateInfo = NULL;
1565 }
1566 }
1567 else
1568 {
1569 /* Otherwise, we are merely opening it */
1570 OpenReason = ObOpenHandle;
1571 }
1572
1573 /* Create the actual handle now */
1574 Status = ObpCreateHandle(OpenReason,
1575 Object,
1576 ObjectType,
1577 PassedAccessState,
1578 0,
1579 ObjectCreateInfo.Attributes,
1580 AccessMode,
1581 NULL,
1582 Handle);
1583 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object);
1584
1585 Cleanup:
1586 /* Delete the access state */
1587 if (PassedAccessState == &AccessState)
1588 {
1589 SeDeleteAccessState(PassedAccessState);
1590 }
1591
1592 /* Release the object attributes and return status */
1593 Quickie:
1594 ObpReleaseCapturedAttributes(&ObjectCreateInfo);
1595 if (ObjectName.Buffer) ObpReleaseCapturedName(&ObjectName);
1596 OBTRACE(OB_HANDLE_DEBUG,
1597 "%s - returning Object %p with PC S: %lx %lx\n",
1598 __FUNCTION__,
1599 Object,
1600 Object ? OBJECT_TO_OBJECT_HEADER(Object)->PointerCount : -1,
1601 Status);
1602 return Status;
1603 }
1604
1605 /*++
1606 * @name ObOpenObjectByPointer
1607 * @implemented NT4
1608 *
1609 * The ObOpenObjectByPointer routine <FILLMEIN>
1610 *
1611 * @param Object
1612 * <FILLMEIN>.
1613 *
1614 * @param HandleAttributes
1615 * <FILLMEIN>.
1616 *
1617 * @param PassedAccessState
1618 * <FILLMEIN>.
1619 *
1620 * @param DesiredAccess
1621 * <FILLMEIN>.
1622 *
1623 * @param ObjectType
1624 * <FILLMEIN>.
1625 *
1626 * @param AccessMode
1627 * <FILLMEIN>.
1628 *
1629 * @param Handle
1630 * <FILLMEIN>.
1631 *
1632 * @return <FILLMEIN>.
1633 *
1634 * @remarks None.
1635 *
1636 *--*/
1637 NTSTATUS
1638 NTAPI
1639 ObOpenObjectByPointer(IN PVOID Object,
1640 IN ULONG HandleAttributes,
1641 IN PACCESS_STATE PassedAccessState,
1642 IN ACCESS_MASK DesiredAccess,
1643 IN POBJECT_TYPE ObjectType,
1644 IN KPROCESSOR_MODE AccessMode,
1645 OUT PHANDLE Handle)
1646 {
1647 POBJECT_HEADER Header;
1648 NTSTATUS Status;
1649 ACCESS_STATE AccessState;
1650 AUX_DATA AuxData;
1651 PAGED_CODE();
1652
1653 /* Get the Header Info */
1654 Header = OBJECT_TO_OBJECT_HEADER(Object);
1655
1656 /* Reference the object */
1657 Status = ObReferenceObjectByPointer(Object,
1658 0,
1659 ObjectType,
1660 AccessMode);
1661 if (!NT_SUCCESS(Status)) return Status;
1662
1663 /* Check if we didn't get an access state */
1664 if (!PassedAccessState)
1665 {
1666 /* Use our built-in access state */
1667 PassedAccessState = &AccessState;
1668 Status = SeCreateAccessState(&AccessState,
1669 &AuxData,
1670 DesiredAccess,
1671 &Header->Type->TypeInfo.GenericMapping);
1672 if (!NT_SUCCESS(Status))
1673 {
1674 /* Fail */
1675 ObDereferenceObject(Object);
1676 return Status;
1677 }
1678 }
1679
1680 /* Create the handle */
1681 Status = ObpCreateHandle(ObOpenHandle,
1682 Object,
1683 ObjectType,
1684 PassedAccessState,
1685 0,
1686 HandleAttributes,
1687 AccessMode,
1688 NULL,
1689 Handle);
1690 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object);
1691
1692 /* Delete the access state */
1693 if (PassedAccessState == &AccessState)
1694 {
1695 SeDeleteAccessState(PassedAccessState);
1696 }
1697
1698 /* Return */
1699 OBTRACE(OB_HANDLE_DEBUG,
1700 "%s - returning Object with PC S: %lx %lx\n",
1701 __FUNCTION__,
1702 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
1703 Status);
1704 return Status;
1705 }
1706
1707 NTSTATUS STDCALL
1708 ObFindHandleForObject(IN PEPROCESS Process,
1709 IN PVOID Object,
1710 IN POBJECT_TYPE ObjectType,
1711 IN POBJECT_HANDLE_INFORMATION HandleInformation,
1712 OUT PHANDLE HandleReturn)
1713 {
1714 DPRINT("ObFindHandleForObject is unimplemented!\n");
1715 return STATUS_UNSUCCESSFUL;
1716 }
1717
1718 /*++
1719 * @name ObInsertObject
1720 * @implemented NT4
1721 *
1722 * The ObInsertObject routine <FILLMEIN>
1723 *
1724 * @param Object
1725 * <FILLMEIN>.
1726 *
1727 * @param PassedAccessState
1728 * <FILLMEIN>.
1729 *
1730 * @param DesiredAccess
1731 * <FILLMEIN>.
1732 *
1733 * @param AdditionalReferences
1734 * <FILLMEIN>.
1735 *
1736 * @param ReferencedObject
1737 * <FILLMEIN>.
1738 *
1739 * @param Handle
1740 * <FILLMEIN>.
1741 *
1742 * @return <FILLMEIN>.
1743 *
1744 * @remarks None.
1745 *
1746 *--*/
1747 NTSTATUS
1748 NTAPI
1749 ObInsertObject(IN PVOID Object,
1750 IN PACCESS_STATE PassedAccessState OPTIONAL,
1751 IN ACCESS_MASK DesiredAccess,
1752 IN ULONG AdditionalReferences,
1753 OUT PVOID *ReferencedObject OPTIONAL,
1754 OUT PHANDLE Handle)
1755 {
1756 POBJECT_CREATE_INFORMATION ObjectCreateInfo;
1757 POBJECT_HEADER Header;
1758 POBJECT_TYPE ObjectType;
1759 PVOID FoundObject = Object;
1760 POBJECT_HEADER FoundHeader = NULL;
1761 NTSTATUS Status = STATUS_SUCCESS, RealStatus;
1762 PSECURITY_DESCRIPTOR DirectorySd = NULL;
1763 BOOLEAN SdAllocated;
1764 OBP_LOOKUP_CONTEXT Context;
1765 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
1766 ACCESS_STATE AccessState;
1767 AUX_DATA AuxData;
1768 BOOLEAN IsNamed = FALSE;
1769 OB_OPEN_REASON OpenReason = ObCreateHandle;
1770 PAGED_CODE();
1771
1772 /* Get the Header and Create Info */
1773 Header = OBJECT_TO_OBJECT_HEADER(Object);
1774 ObjectCreateInfo = Header->ObjectCreateInfo;
1775 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
1776 ObjectType = Header->Type;
1777
1778 /* Check if this is an named object */
1779 if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) IsNamed = TRUE;
1780
1781 /* Check if the object is unnamed and also doesn't have security */
1782 if ((!ObjectType->TypeInfo.SecurityRequired) && !(IsNamed))
1783 {
1784 /* ReactOS HACK */
1785 if (Handle)
1786 {
1787 /* Assume failure */
1788 *Handle = NULL;
1789
1790 /* Create the handle */
1791 Status = ObpCreateUnnamedHandle(Object,
1792 DesiredAccess,
1793 AdditionalReferences + 1,
1794 ObjectCreateInfo->Attributes,
1795 ExGetPreviousMode(),
1796 ReferencedObject,
1797 Handle);
1798 }
1799
1800 /* Free the create information */
1801 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
1802 Header->ObjectCreateInfo = NULL;
1803
1804 /* Remove the extra keep-alive reference */
1805 if (Handle) ObDereferenceObject(Object);
1806
1807 /* Return */
1808 OBTRACE(OB_HANDLE_DEBUG,
1809 "%s - returning Object with PC S: %lx %lx\n",
1810 __FUNCTION__,
1811 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
1812 Status);
1813 return Status;
1814 }
1815
1816 /* Check if we didn't get an access state */
1817 if (!PassedAccessState)
1818 {
1819 /* Use our built-in access state */
1820 PassedAccessState = &AccessState;
1821 Status = SeCreateAccessState(&AccessState,
1822 &AuxData,
1823 DesiredAccess,
1824 &ObjectType->TypeInfo.GenericMapping);
1825 if (!NT_SUCCESS(Status))
1826 {
1827 /* Fail */
1828 ObDereferenceObject(Object);
1829 return Status;
1830 }
1831 }
1832
1833 /* Save the security descriptor */
1834 PassedAccessState->SecurityDescriptor =
1835 ObjectCreateInfo->SecurityDescriptor;
1836
1837 /* Check if the object is named */
1838 if (IsNamed)
1839 {
1840 /* Look it up */
1841 Status = ObFindObject(ObjectCreateInfo->RootDirectory,
1842 &ObjectNameInfo->Name,
1843 ObjectCreateInfo->Attributes,
1844 (Header->Flags & OB_FLAG_KERNEL_MODE) ?
1845 KernelMode : UserMode,
1846 &FoundObject,
1847 ObjectType,
1848 &Context,
1849 PassedAccessState,
1850 ObjectCreateInfo->SecurityQos,
1851 ObjectCreateInfo->ParseContext,
1852 Object);
1853 /* Check if we found an object that doesn't match the one requested */
1854 if ((NT_SUCCESS(Status)) && (FoundObject) && (Object != FoundObject))
1855 {
1856 /* This means we're opening an object, not creating a new one */
1857 FoundHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
1858 OpenReason = ObOpenHandle;
1859
1860 /* Make sure the caller said it's OK to do this */
1861 if (ObjectCreateInfo->Attributes & OBJ_OPENIF)
1862 {
1863 /* He did, but did he want this type? */
1864 if (ObjectType != FoundHeader->Type)
1865 {
1866 /* Wrong type, so fail */
1867 Status = STATUS_OBJECT_TYPE_MISMATCH;
1868 }
1869 else
1870 {
1871 /* Right type, so warn */
1872 Status = STATUS_OBJECT_NAME_EXISTS;
1873 }
1874 }
1875 else
1876 {
1877 /* Caller wanted to create a new object, fail */
1878 Status = STATUS_OBJECT_NAME_COLLISION;
1879 }
1880 }
1881
1882 /* Check if anything until now failed */
1883 if (!NT_SUCCESS(Status))
1884 {
1885 /* We failed, dereference the object and delete the access state */
1886 ObDereferenceObject(Object);
1887 if (PassedAccessState == &AccessState)
1888 {
1889 /* We used a local one; delete it */
1890 SeDeleteAccessState(PassedAccessState);
1891 }
1892
1893 /* Return failure code */
1894 return Status;
1895 }
1896 }
1897
1898 /* Now check if this object is being created */
1899 if (FoundObject == Object)
1900 {
1901 /* Check if it's named or forces security */
1902 if ((IsNamed) || (ObjectType->TypeInfo.SecurityRequired))
1903 {
1904 /* Make sure it's inserted into an object directory */
1905 if ((ObjectNameInfo) && (ObjectNameInfo->Directory))
1906 {
1907 /* Get the current descriptor */
1908 ObGetObjectSecurity(ObjectNameInfo->Directory,
1909 &DirectorySd,
1910 &SdAllocated);
1911 }
1912
1913 /* Now assign it */
1914 Status = ObAssignSecurity(PassedAccessState,
1915 DirectorySd,
1916 Object,
1917 ObjectType);
1918
1919 /* Check if we captured one */
1920 if (DirectorySd)
1921 {
1922 /* We did, release it */
1923 ObReleaseObjectSecurity(DirectorySd, SdAllocated);
1924 }
1925 else if (NT_SUCCESS(Status))
1926 {
1927 /* Other we didn't, but we were able to use the current SD */
1928 SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
1929 ObjectCreateInfo->ProbeMode,
1930 TRUE);
1931
1932 /* Clear the current one */
1933 PassedAccessState->SecurityDescriptor =
1934 ObjectCreateInfo->SecurityDescriptor = NULL;
1935 }
1936 }
1937
1938 /* Check if anything until now failed */
1939 if (!NT_SUCCESS(Status))
1940 {
1941 /* We failed, dereference the object and delete the access state */
1942 KEBUGCHECK(0);
1943 ObDereferenceObject(Object);
1944 if (PassedAccessState == &AccessState)
1945 {
1946 /* We used a local one; delete it */
1947 SeDeleteAccessState(PassedAccessState);
1948 }
1949
1950 /* Return failure code */
1951 return Status;
1952 }
1953 }
1954
1955 /* Save the actual status until here */
1956 RealStatus = Status;
1957
1958 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1959 * without a valid Process until I finalize the startup patch,
1960 * so don't create a handle if this is the case. We also don't create
1961 * a handle if Handle is NULL when the Registry Code calls it, because
1962 * the registry code totally bastardizes the Ob and needs to be fixed
1963 */
1964 if (Handle)
1965 {
1966 /* Create the handle */
1967 Status = ObpCreateHandle(OpenReason,
1968 FoundObject,
1969 NULL,
1970 PassedAccessState,
1971 AdditionalReferences + 1,
1972 ObjectCreateInfo->Attributes,
1973 ExGetPreviousMode(),
1974 ReferencedObject,
1975 Handle);
1976 }
1977
1978 /* We can delete the Create Info now */
1979 Header->ObjectCreateInfo = NULL;
1980 ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
1981
1982 /* Check if creating the handle failed */
1983 if (!NT_SUCCESS(Status))
1984 {
1985 /* If the object had a name, backout everything */
1986 if (IsNamed) ObpDeleteNameCheck(Object);
1987 }
1988
1989 /* Remove the extra keep-alive reference */
1990 if (Handle) ObDereferenceObject(Object);
1991
1992 /* Check our final status */
1993 if (!NT_SUCCESS(Status))
1994 {
1995 /* Return the status of the failure */
1996 *Handle = NULL;
1997 RealStatus = Status;
1998 }
1999
2000 /* Check if we created our own access state */
2001 if (PassedAccessState == &AccessState)
2002 {
2003 /* We used a local one; delete it */
2004 SeDeleteAccessState(PassedAccessState);
2005 }
2006
2007 /* Return status code */
2008 OBTRACE(OB_HANDLE_DEBUG,
2009 "%s - returning Object with PC S/RS: %lx %lx %lx\n",
2010 __FUNCTION__,
2011 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
2012 RealStatus, Status);
2013 return RealStatus;
2014 }
2015
2016 /*++
2017 * @name ObCloseHandle
2018 * @implemented NT5.1
2019 *
2020 * The ObCloseHandle routine <FILLMEIN>
2021 *
2022 * @param Handle
2023 * <FILLMEIN>.
2024 *
2025 * @param AccessMode
2026 * <FILLMEIN>.
2027 *
2028 * @return <FILLMEIN>.
2029 *
2030 * @remarks None.
2031 *
2032 *--*/
2033 NTSTATUS
2034 NTAPI
2035 ObCloseHandle(IN HANDLE Handle,
2036 IN KPROCESSOR_MODE AccessMode)
2037 {
2038 /* Call the internal API */
2039 return ObpCloseHandle(Handle, AccessMode);
2040 }
2041
2042 /*++
2043 * @name NtClose
2044 * @implemented NT4
2045 *
2046 * The NtClose routine <FILLMEIN>
2047 *
2048 * @param Handle
2049 * <FILLMEIN>.
2050 *
2051 * @return <FILLMEIN>.
2052 *
2053 * @remarks None.
2054 *
2055 *--*/
2056 NTSTATUS
2057 NTAPI
2058 NtClose(IN HANDLE Handle)
2059 {
2060 //
2061 // Call the internal API
2062 //
2063 return ObpCloseHandle(Handle, ExGetPreviousMode());
2064 }
2065
2066 NTSTATUS
2067 NTAPI
2068 NtDuplicateObject(IN HANDLE SourceProcessHandle,
2069 IN HANDLE SourceHandle,
2070 IN HANDLE TargetProcessHandle OPTIONAL,
2071 OUT PHANDLE TargetHandle OPTIONAL,
2072 IN ACCESS_MASK DesiredAccess,
2073 IN ULONG HandleAttributes,
2074 IN ULONG Options)
2075 {
2076 PEPROCESS SourceProcess, TargetProcess, Target;
2077 HANDLE hTarget;
2078 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
2079 NTSTATUS Status = STATUS_SUCCESS;
2080 PAGED_CODE();
2081 OBTRACE(OB_HANDLE_DEBUG,
2082 "%s - Duplicating handle: %lx for %lx into %lx.\n",
2083 __FUNCTION__,
2084 SourceHandle,
2085 SourceProcessHandle,
2086 TargetProcessHandle);
2087
2088 if((TargetHandle) && (PreviousMode != KernelMode))
2089 {
2090 /* Enter SEH */
2091 _SEH_TRY
2092 {
2093 /* Probe the handle */
2094 ProbeForWriteHandle(TargetHandle);
2095 }
2096 _SEH_HANDLE
2097 {
2098 /* Get the exception status */
2099 Status = _SEH_GetExceptionCode();
2100 }
2101 _SEH_END;
2102
2103 /* Fail if the pointer was invalid */
2104 if (!NT_SUCCESS(Status)) return Status;
2105 }
2106
2107 /* Now reference the input handle */
2108 Status = ObReferenceObjectByHandle(SourceProcessHandle,
2109 PROCESS_DUP_HANDLE,
2110 PsProcessType,
2111 PreviousMode,
2112 (PVOID*)&SourceProcess,
2113 NULL);
2114 if (!NT_SUCCESS(Status)) return(Status);
2115
2116 /* Check if got a target handle */
2117 if (TargetProcessHandle)
2118 {
2119 /* Now reference the output handle */
2120 Status = ObReferenceObjectByHandle(TargetProcessHandle,
2121 PROCESS_DUP_HANDLE,
2122 PsProcessType,
2123 PreviousMode,
2124 (PVOID*)&TargetProcess,
2125 NULL);
2126 if (NT_SUCCESS(Status))
2127 {
2128 /* Use this target process */
2129 Target = TargetProcess;
2130 }
2131 else
2132 {
2133 /* No target process */
2134 Target = NULL;
2135 }
2136 }
2137 else
2138 {
2139 /* No target process */
2140 Status = STATUS_SUCCESS;
2141 Target = NULL;
2142 }
2143
2144 /* Call the internal routine */
2145 Status = ObDuplicateObject(SourceProcess,
2146 SourceHandle,
2147 Target,
2148 &hTarget,
2149 DesiredAccess,
2150 HandleAttributes,
2151 Options,
2152 PreviousMode);
2153
2154 /* Check if the caller wanted the return handle */
2155 if (TargetHandle)
2156 {
2157 /* Protect the write to user mode */
2158 _SEH_TRY
2159 {
2160 /* Write the new handle */
2161 *TargetHandle = hTarget;
2162 }
2163 _SEH_HANDLE
2164 {
2165 /* Otherwise, get the exception code */
2166 Status = _SEH_GetExceptionCode();
2167 }
2168 _SEH_END;
2169 }
2170
2171 /* Dereference the processes */
2172 OBTRACE(OB_HANDLE_DEBUG,
2173 "%s - Duplicated handle: %lx into %lx S %lx\n",
2174 __FUNCTION__,
2175 hTarget,
2176 TargetProcessHandle,
2177 Status);
2178 ObDereferenceObject(Target);
2179 ObDereferenceObject(SourceProcess);
2180 return Status;
2181 }
2182
2183 #undef ObIsKernelHandle
2184 BOOLEAN
2185 NTAPI
2186 ObIsKernelHandle(IN HANDLE Handle)
2187 {
2188 /* We know we're kernel mode, so just check for the kernel handle flag */
2189 return (BOOLEAN)((ULONG_PTR)Handle & KERNEL_HANDLE_FLAG);
2190 }
2191
2192 /* EOF */