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 <debug.h>
19
20 PHANDLE_TABLE ObpKernelHandleTable = NULL;
21
22 /* PRIVATE FUNCTIONS *********************************************************/
23
24 PHANDLE_TABLE
25 NTAPI
ObReferenceProcessHandleTable(IN PEPROCESS Process)26 ObReferenceProcessHandleTable(IN PEPROCESS Process)
27 {
28 PHANDLE_TABLE HandleTable = NULL;
29
30 /* Lock the process */
31 if (ExAcquireRundownProtection(&Process->RundownProtect))
32 {
33 /* Get the handle table */
34 HandleTable = Process->ObjectTable;
35 if (!HandleTable)
36 {
37 /* No table, release the lock */
38 ExReleaseRundownProtection(&Process->RundownProtect);
39 }
40 }
41
42 /* Return the handle table */
43 return HandleTable;
44 }
45
46 VOID
47 NTAPI
ObDereferenceProcessHandleTable(IN PEPROCESS Process)48 ObDereferenceProcessHandleTable(IN PEPROCESS Process)
49 {
50 /* Release the process lock */
51 ExReleaseRundownProtection(&Process->RundownProtect);
52 }
53
54 ULONG
55 NTAPI
ObGetProcessHandleCount(IN PEPROCESS Process)56 ObGetProcessHandleCount(IN PEPROCESS Process)
57 {
58 ULONG HandleCount;
59 PHANDLE_TABLE HandleTable;
60
61 ASSERT(Process);
62
63 /* Ensure the handle table doesn't go away while we use it */
64 HandleTable = ObReferenceProcessHandleTable(Process);
65
66 if (HandleTable != NULL)
67 {
68 /* Count the number of handles the process has */
69 HandleCount = HandleTable->HandleCount;
70
71 /* Let the handle table go */
72 ObDereferenceProcessHandleTable(Process);
73 }
74 else
75 {
76 /* No handle table, no handles */
77 HandleCount = 0;
78 }
79
80 return HandleCount;
81 }
82
83 NTSTATUS
84 NTAPI
ObpReferenceProcessObjectByHandle(IN HANDLE Handle,IN PEPROCESS Process,IN PHANDLE_TABLE HandleTable,IN KPROCESSOR_MODE AccessMode,OUT PVOID * Object,OUT POBJECT_HANDLE_INFORMATION HandleInformation,OUT PACCESS_MASK AuditMask)85 ObpReferenceProcessObjectByHandle(IN HANDLE Handle,
86 IN PEPROCESS Process,
87 IN PHANDLE_TABLE HandleTable,
88 IN KPROCESSOR_MODE AccessMode,
89 OUT PVOID *Object,
90 OUT POBJECT_HANDLE_INFORMATION HandleInformation,
91 OUT PACCESS_MASK AuditMask)
92 {
93 PHANDLE_TABLE_ENTRY HandleEntry;
94 POBJECT_HEADER ObjectHeader;
95 ACCESS_MASK GrantedAccess;
96 ULONG Attributes;
97 PETHREAD Thread = PsGetCurrentThread();
98 NTSTATUS Status;
99
100 /* Assume failure */
101 *Object = NULL;
102
103 /* Check if this is a special handle */
104 if (HandleToLong(Handle) < 0)
105 {
106 /* Check if the caller wants the current process */
107 if (Handle == NtCurrentProcess())
108 {
109 /* Return handle info */
110 HandleInformation->HandleAttributes = 0;
111 HandleInformation->GrantedAccess = Process->GrantedAccess;
112
113 /* No audit mask */
114 *AuditMask = 0;
115
116 /* Reference ourselves */
117 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
118 InterlockedIncrementSizeT(&ObjectHeader->PointerCount);
119
120 /* Return the pointer */
121 *Object = Process;
122 ASSERT(*Object != NULL);
123 return STATUS_SUCCESS;
124 }
125
126 /* Check if the caller wants the current thread */
127 if (Handle == NtCurrentThread())
128 {
129 /* Return handle information */
130 HandleInformation->HandleAttributes = 0;
131 HandleInformation->GrantedAccess = Thread->GrantedAccess;
132
133 /* Reference ourselves */
134 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
135 InterlockedIncrementSizeT(&ObjectHeader->PointerCount);
136
137 /* No audit mask */
138 *AuditMask = 0;
139
140 /* Return the pointer */
141 *Object = Thread;
142 ASSERT(*Object != NULL);
143 return STATUS_SUCCESS;
144 }
145
146 /* This is a kernel handle... do we have access? */
147 if (AccessMode == KernelMode)
148 {
149 /* Use the kernel handle table and get the actual handle value */
150 Handle = ObKernelHandleToHandle(Handle);
151 HandleTable = ObpKernelHandleTable;
152 }
153 else
154 {
155 /* This is an illegal attempt to access a kernel handle */
156 return STATUS_INVALID_HANDLE;
157 }
158 }
159
160 /* Enter a critical region while we touch the handle table */
161 ASSERT(HandleTable != NULL);
162 KeEnterCriticalRegion();
163
164 /* Get the handle entry */
165 HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
166 if (HandleEntry)
167 {
168 /* Get the object header and validate the type*/
169 ObjectHeader = ObpGetHandleObject(HandleEntry);
170
171 /* Get the granted access and validate it */
172 GrantedAccess = HandleEntry->GrantedAccess;
173
174 /* Mask out the internal attributes */
175 Attributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
176
177 /* Fill out the information */
178 HandleInformation->HandleAttributes = Attributes;
179 HandleInformation->GrantedAccess = GrantedAccess;
180
181 /* No audit mask (FIXME!) */
182 *AuditMask = 0;
183
184 /* Return the pointer */
185 *Object = &ObjectHeader->Body;
186
187 /* Add a reference */
188 InterlockedIncrementSizeT(&ObjectHeader->PointerCount);
189
190 /* Unlock the handle */
191 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
192 KeLeaveCriticalRegion();
193
194 /* Return success */
195 ASSERT(*Object != NULL);
196 return STATUS_SUCCESS;
197 }
198 else
199 {
200 /* Invalid handle */
201 Status = STATUS_INVALID_HANDLE;
202 }
203
204 /* Return failure status */
205 KeLeaveCriticalRegion();
206 return Status;
207 }
208
209 BOOLEAN
210 NTAPI
ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry,IN HANDLE Handle,IN PVOID Context)211 ObpEnumFindHandleProcedure(IN PHANDLE_TABLE_ENTRY HandleEntry,
212 IN HANDLE Handle,
213 IN PVOID Context)
214 {
215 POBJECT_HEADER ObjectHeader;
216 ACCESS_MASK GrantedAccess;
217 ULONG HandleAttributes;
218 POBP_FIND_HANDLE_DATA FindData = Context;
219
220 /* Get the object header */
221 ObjectHeader = ObpGetHandleObject(HandleEntry);
222
223 /* Make sure it's valid and matching */
224 if ((FindData->ObjectHeader) && (FindData->ObjectHeader != ObjectHeader))
225 {
226 /* No match, fail */
227 return FALSE;
228 }
229
230 /* Now attempt to match the object type */
231 if ((FindData->ObjectType) && (FindData->ObjectType != ObjectHeader->Type))
232 {
233 /* No match, fail */
234 return FALSE;
235 }
236
237 /* Check if we have extra information */
238 if (FindData->HandleInformation)
239 {
240 /* Get the granted access and attributes */
241 GrantedAccess = HandleEntry->GrantedAccess;
242 HandleAttributes = HandleEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
243
244 /* Attempt to match them */
245 if ((FindData->HandleInformation->HandleAttributes != HandleAttributes) ||
246 (FindData->HandleInformation->GrantedAccess != GrantedAccess))
247 {
248 /* No match, fail */
249 return FALSE;
250 }
251 }
252
253 /* We have a match */
254 return TRUE;
255 }
256
257 POBJECT_HANDLE_COUNT_ENTRY
258 NTAPI
ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader)259 ObpInsertHandleCount(IN POBJECT_HEADER ObjectHeader)
260 {
261 POBJECT_HEADER_HANDLE_INFO HandleInfo;
262 POBJECT_HANDLE_COUNT_ENTRY FreeEntry;
263 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase, OldHandleDatabase;
264 ULONG i;
265 ULONG Size, OldSize;
266 OBJECT_HANDLE_COUNT_DATABASE SingleDatabase;
267 PAGED_CODE();
268
269 /* Get the handle info */
270 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
271 if (!HandleInfo) return NULL;
272
273 /* Check if we only have one entry */
274 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
275 {
276 /* Fill out the single entry */
277 SingleDatabase.CountEntries = 1;
278 SingleDatabase.HandleCountEntries[0] = HandleInfo->SingleEntry;
279
280 /* Use this as the old size */
281 OldHandleDatabase = &SingleDatabase;
282 OldSize = sizeof(SingleDatabase);
283
284 /* Now we'll have two entries, and an entire DB */
285 i = 2;
286 Size = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
287 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
288 }
289 else
290 {
291 /* We already have a DB, get the information from it */
292 OldHandleDatabase = HandleInfo->HandleCountDatabase;
293 i = OldHandleDatabase->CountEntries;
294 OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
295 ((i - 1) * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
296
297 /* Add 4 more entries */
298 i += 4;
299 Size = OldSize + (4 * sizeof(OBJECT_HANDLE_COUNT_ENTRY));
300 }
301
302 /* Allocate the DB */
303 HandleDatabase = ExAllocatePoolWithTag(PagedPool, Size, TAG_OB_HANDLE);
304 if (!HandleDatabase) return NULL;
305
306 /* Copy the old database */
307 RtlCopyMemory(HandleDatabase, OldHandleDatabase, OldSize);
308
309 /* Check if we he had a single entry before */
310 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
311 {
312 /* Now we have more */
313 ObjectHeader->Flags &= ~OB_FLAG_SINGLE_PROCESS;
314 }
315 else
316 {
317 /* Otherwise we had a DB, free it */
318 ExFreePoolWithTag(OldHandleDatabase, TAG_OB_HANDLE);
319 }
320
321 /* Find the end of the copy and zero out the new data */
322 FreeEntry = (PVOID)((ULONG_PTR)HandleDatabase + OldSize);
323 RtlZeroMemory(FreeEntry, Size - OldSize);
324
325 /* Set the new information and return the free entry */
326 HandleDatabase->CountEntries = i;
327 HandleInfo->HandleCountDatabase = HandleDatabase;
328 return FreeEntry;
329 }
330
331 NTSTATUS
332 NTAPI
ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader,IN PEPROCESS Process,IN OUT PULONG NewProcessHandleCount)333 ObpIncrementHandleDataBase(IN POBJECT_HEADER ObjectHeader,
334 IN PEPROCESS Process,
335 IN OUT PULONG NewProcessHandleCount)
336 {
337 POBJECT_HEADER_HANDLE_INFO HandleInfo;
338 POBJECT_HANDLE_COUNT_ENTRY HandleEntry, FreeEntry = NULL;
339 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
340 ULONG i;
341 PAGED_CODE();
342
343 /* Get the handle info and check if we only have one entry */
344 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
345 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
346 {
347 /* Check if the entry is free */
348 if (!HandleInfo->SingleEntry.HandleCount)
349 {
350 /* Add ours */
351 HandleInfo->SingleEntry.HandleCount = 1;
352 HandleInfo->SingleEntry.Process = Process;
353
354 /* Return success and 1 handle */
355 *NewProcessHandleCount = 1;
356 return STATUS_SUCCESS;
357 }
358 else if (HandleInfo->SingleEntry.Process == Process)
359 {
360 /* Busy entry, but same process */
361 *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount;
362 return STATUS_SUCCESS;
363 }
364 else
365 {
366 /* Insert a new entry */
367 FreeEntry = ObpInsertHandleCount(ObjectHeader);
368 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
369 ASSERT(!FreeEntry->Process);
370 ASSERT(!FreeEntry->HandleCount);
371
372 /* Fill it out */
373 FreeEntry->Process = Process;
374 FreeEntry->HandleCount = 1;
375
376 /* Return success and 1 handle */
377 *NewProcessHandleCount = 1;
378 return STATUS_SUCCESS;
379 }
380 }
381
382 /* We have a database instead */
383 HandleDatabase = HandleInfo->HandleCountDatabase;
384 if (HandleDatabase)
385 {
386 /* Get the entries and loop them */
387 i = HandleDatabase->CountEntries;
388 HandleEntry = &HandleDatabase->HandleCountEntries[0];
389 while (i)
390 {
391 /* Check if this is a match */
392 if (HandleEntry->Process == Process)
393 {
394 /* Found it, get the process handle count */
395 *NewProcessHandleCount = ++HandleEntry->HandleCount;
396 return STATUS_SUCCESS;
397 }
398 else if (!HandleEntry->HandleCount)
399 {
400 /* Found a free entry */
401 FreeEntry = HandleEntry;
402 }
403
404 /* Keep looping */
405 HandleEntry++;
406 i--;
407 }
408
409 /* Check if we couldn't find a free entry */
410 if (!FreeEntry)
411 {
412 /* Allocate one */
413 FreeEntry = ObpInsertHandleCount(ObjectHeader);
414 if (!FreeEntry) return STATUS_INSUFFICIENT_RESOURCES;
415 ASSERT(!FreeEntry->Process);
416 ASSERT(!FreeEntry->HandleCount);
417 }
418
419 /* Fill out the entry */
420 FreeEntry->Process = Process;
421 FreeEntry->HandleCount = 1;
422 *NewProcessHandleCount = 1;
423 }
424
425 /* Return success if we got here */
426 return STATUS_SUCCESS;
427 }
428
429 NTSTATUS
430 NTAPI
ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader,IN POBJECT_TYPE ObjectType,OUT PBOOLEAN NewObject)431 ObpChargeQuotaForObject(IN POBJECT_HEADER ObjectHeader,
432 IN POBJECT_TYPE ObjectType,
433 OUT PBOOLEAN NewObject)
434 {
435 POBJECT_HEADER_QUOTA_INFO ObjectQuota;
436 ULONG PagedPoolCharge, NonPagedPoolCharge;
437
438 /* Get quota information */
439 ObjectQuota = OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader);
440 *NewObject = FALSE;
441
442 /* Check if this is a new object */
443 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO)
444 {
445 /* Remove the flag */
446 ObjectHeader->Flags &= ~ OB_FLAG_CREATE_INFO;
447 if (ObjectQuota)
448 {
449 /* We have a quota, get the charges */
450 PagedPoolCharge = ObjectQuota->PagedPoolCharge +
451 ObjectQuota->SecurityDescriptorCharge;
452 NonPagedPoolCharge = ObjectQuota->NonPagedPoolCharge;
453 }
454 else
455 {
456 /* Get it from the object type */
457 PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
458 NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
459 }
460
461 /* Is this the system process? */
462 if (PsGetCurrentProcess() == PsInitialSystemProcess)
463 {
464 /* It is, don't do anything */
465 ObjectHeader->QuotaBlockCharged = OBP_SYSTEM_PROCESS_QUOTA;
466 }
467 else
468 {
469 /* Charge the quota */
470 ObjectHeader->QuotaBlockCharged = PsChargeSharedPoolQuota(PsGetCurrentProcess(),
471 PagedPoolCharge,
472 NonPagedPoolCharge);
473 }
474
475 /* Check if we don't have a quota block */
476 if (!ObjectHeader->QuotaBlockCharged) return STATUS_QUOTA_EXCEEDED;
477
478 /* Now set the flag */
479 *NewObject = TRUE;
480 }
481
482 /* Return success */
483 return STATUS_SUCCESS;
484 }
485
486 NTSTATUS
487 NTAPI
ObpValidateAccessMask(IN PACCESS_STATE AccessState)488 ObpValidateAccessMask(IN PACCESS_STATE AccessState)
489 {
490 PISECURITY_DESCRIPTOR SecurityDescriptor;
491
492 /* We're only interested if the object for this access state has an SD */
493 SecurityDescriptor = AccessState->SecurityDescriptor;
494 if (SecurityDescriptor)
495 {
496 /* Check if the SD has a system ACL but hasn't been granted access to get/set it */
497 if ((SecurityDescriptor->Control & SE_SACL_PRESENT) &&
498 !(AccessState->PreviouslyGrantedAccess & ACCESS_SYSTEM_SECURITY))
499 {
500 /* We're gonna need access */
501 AccessState->RemainingDesiredAccess |= ACCESS_SYSTEM_SECURITY;
502 }
503 }
504
505 /* This can't fail */
506 return STATUS_SUCCESS;
507 }
508
509 /*++
510 * @name ObpDecrementHandleCount
511 *
512 * The ObpDecrementHandleCount routine <FILLMEIN>
513 *
514 * @param ObjectBody
515 * <FILLMEIN>.
516 *
517 * @param Process
518 * <FILLMEIN>.
519 *
520 * @param GrantedAccess
521 * <FILLMEIN>.
522 *
523 * @return None.
524 *
525 * @remarks None.
526 *
527 *--*/
528 VOID
529 NTAPI
ObpDecrementHandleCount(IN PVOID ObjectBody,IN PEPROCESS Process,IN ACCESS_MASK GrantedAccess,IN POBJECT_TYPE ObjectType)530 ObpDecrementHandleCount(IN PVOID ObjectBody,
531 IN PEPROCESS Process,
532 IN ACCESS_MASK GrantedAccess,
533 IN POBJECT_TYPE ObjectType)
534 {
535 POBJECT_HEADER ObjectHeader;
536 LONG SystemHandleCount, ProcessHandleCount;
537 LONG NewCount;
538 KIRQL CalloutIrql;
539 POBJECT_HEADER_HANDLE_INFO HandleInfo;
540 POBJECT_HANDLE_COUNT_ENTRY HandleEntry;
541 POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
542 ULONG i;
543 PAGED_CODE();
544
545 /* Get the object type and header */
546 ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
547 OBTRACE(OB_HANDLE_DEBUG,
548 "%s - Decrementing count for: %p. HC PC %lx %lx\n",
549 __FUNCTION__,
550 ObjectBody,
551 ObjectHeader->HandleCount,
552 ObjectHeader->PointerCount);
553
554 /* Lock the object */
555 ObpAcquireObjectLock(ObjectHeader);
556
557 /* Set default counts */
558 SystemHandleCount = ObjectHeader->HandleCount;
559 ProcessHandleCount = 0;
560
561 /* Decrement the handle count */
562 NewCount = InterlockedDecrementSizeT(&ObjectHeader->HandleCount);
563
564 /* Check if we're out of handles and this was an exclusive object */
565 if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE))
566 {
567 /* Clear the exclusive flag */
568 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = NULL;
569 }
570
571 /* Is the object type keeping track of handles? */
572 if (ObjectType->TypeInfo.MaintainHandleCount)
573 {
574 /* Get handle information */
575 HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
576
577 /* Check if there's only a single entry */
578 if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
579 {
580 /* It should be us */
581 ASSERT(HandleInfo->SingleEntry.Process == Process);
582 ASSERT(HandleInfo->SingleEntry.HandleCount > 0);
583
584 /* Get the handle counts */
585 ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--;
586 HandleEntry = &HandleInfo->SingleEntry;
587 }
588 else
589 {
590 /* Otherwise, get the database */
591 HandleDatabase = HandleInfo->HandleCountDatabase;
592 if (HandleDatabase)
593 {
594 /* Get the entries and loop them */
595 i = HandleDatabase->CountEntries;
596 HandleEntry = &HandleDatabase->HandleCountEntries[0];
597 while (i)
598 {
599 /* Check if this is a match */
600 if ((HandleEntry->HandleCount) &&
601 (HandleEntry->Process == Process))
602 {
603 /* Found it, get the process handle count */
604 ProcessHandleCount = HandleEntry->HandleCount--;
605 break;
606 }
607
608 /* Keep looping */
609 HandleEntry++;
610 i--;
611 }
612 }
613 else
614 {
615 /* No database, so no entry */
616 HandleEntry = NULL;
617 }
618 }
619
620 /* Check if this is the last handle */
621 if (ProcessHandleCount == 1)
622 {
623 /* Then clear the entry */
624 HandleEntry->Process = NULL;
625 HandleEntry->HandleCount = 0;
626 }
627 }
628
629 /* Release the lock */
630 ObpReleaseObjectLock(ObjectHeader);
631
632 /* Check if we have a close procedure */
633 if (ObjectType->TypeInfo.CloseProcedure)
634 {
635 /* Call it */
636 ObpCalloutStart(&CalloutIrql);
637 ObjectType->TypeInfo.CloseProcedure(Process,
638 ObjectBody,
639 GrantedAccess,
640 ProcessHandleCount,
641 SystemHandleCount);
642 ObpCalloutEnd(CalloutIrql, "Close", ObjectType, ObjectBody);
643 }
644
645 /* Check if we should delete the object */
646 ObpDeleteNameCheck(ObjectBody);
647
648 /* Decrease the total number of handles for this type */
649 InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfHandles);
650 OBTRACE(OB_HANDLE_DEBUG,
651 "%s - Decremented count for: %p. HC PC %lx %lx\n",
652 __FUNCTION__,
653 ObjectBody,
654 ObjectHeader->HandleCount,
655 ObjectHeader->PointerCount);
656 }
657
658 /*++
659 * @name ObpCloseHandleTableEntry
660 *
661 * The ObpCloseHandleTableEntry routine <FILLMEIN>
662 *
663 * @param HandleTable
664 * <FILLMEIN>.
665 *
666 * @param HandleEntry
667 * <FILLMEIN>.
668 *
669 * @param Handle
670 * <FILLMEIN>.
671 *
672 * @param AccessMode
673 * <FILLMEIN>.
674 *
675 * @param IgnoreHandleProtection
676 * <FILLMEIN>.
677 *
678 * @return <FILLMEIN>.
679 *
680 * @remarks None.
681 *
682 *--*/
683 NTSTATUS
684 NTAPI
ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,IN PHANDLE_TABLE_ENTRY HandleEntry,IN HANDLE Handle,IN KPROCESSOR_MODE AccessMode,IN BOOLEAN IgnoreHandleProtection)685 ObpCloseHandleTableEntry(IN PHANDLE_TABLE HandleTable,
686 IN PHANDLE_TABLE_ENTRY HandleEntry,
687 IN HANDLE Handle,
688 IN KPROCESSOR_MODE AccessMode,
689 IN BOOLEAN IgnoreHandleProtection)
690 {
691 PVOID Body;
692 POBJECT_TYPE ObjectType;
693 POBJECT_HEADER ObjectHeader;
694 ACCESS_MASK GrantedAccess;
695 KIRQL CalloutIrql;
696 PAGED_CODE();
697
698 /* Get the object data */
699 ObjectHeader = ObpGetHandleObject(HandleEntry);
700 ObjectType = ObjectHeader->Type;
701 Body = &ObjectHeader->Body;
702 GrantedAccess = HandleEntry->GrantedAccess;
703 OBTRACE(OB_HANDLE_DEBUG,
704 "%s - Closing handle: %p for %p. HC PC %lx %lx\n",
705 __FUNCTION__,
706 Handle,
707 Body,
708 ObjectHeader->HandleCount,
709 ObjectHeader->PointerCount);
710
711 /* Check if the object has an Okay To Close procedure */
712 if (ObjectType->TypeInfo.OkayToCloseProcedure)
713 {
714 /* Call it and check if it's not letting us close it */
715 ObpCalloutStart(&CalloutIrql);
716 if (!ObjectType->TypeInfo.OkayToCloseProcedure(PsGetCurrentProcess(),
717 Body,
718 Handle,
719 AccessMode))
720 {
721 /* Fail */
722 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body);
723 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
724 return STATUS_HANDLE_NOT_CLOSABLE;
725 }
726
727 /* Success, validate callout retrn */
728 ObpCalloutEnd(CalloutIrql, "NtClose", ObjectType, Body);
729 }
730
731 /* The callback allowed us to close it, but does the handle itself? */
732 if ((HandleEntry->GrantedAccess & ObpAccessProtectCloseBit) &&
733 !(IgnoreHandleProtection))
734 {
735 /* It doesn't, are we from user mode? */
736 if (AccessMode != KernelMode)
737 {
738 /* We are! Unlock the entry */
739 ExUnlockHandleTableEntry(HandleTable, HandleEntry);
740
741 /* Make sure we have a debug port */
742 if (PsGetCurrentProcess()->DebugPort)
743 {
744 /* Raise an exception */
745 return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
746 }
747 else
748 {
749 /* Return the error instead */
750 return STATUS_HANDLE_NOT_CLOSABLE;
751 }
752 }
753 else
754 {
755 /* Otherwise, bugcheck the OS */
756 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0);
757 }
758 }
759
760 /* Destroy and unlock the handle entry */
761 ExDestroyHandle(HandleTable, Handle, HandleEntry);
762
763 /* Now decrement the handle count */
764 ObpDecrementHandleCount(Body,
765 PsGetCurrentProcess(),
766 GrantedAccess,
767 ObjectType);
768
769 /* Dereference the object as well */
770 ObDereferenceObject(Body);
771
772 /* Return to caller */
773 OBTRACE(OB_HANDLE_DEBUG,
774 "%s - Closed handle: %p for %p.\n",
775 __FUNCTION__,
776 Handle,
777 Body);
778 return STATUS_SUCCESS;
779 }
780
781 /*++
782 * @name ObpIncrementHandleCount
783 *
784 * The ObpIncrementHandleCount routine <FILLMEIN>
785 *
786 * @param Object
787 * <FILLMEIN>.
788 *
789 * @param AccessState
790 * <FILLMEIN>.
791 *
792 * @param AccessMode
793 * <FILLMEIN>.
794 *
795 * @param HandleAttributes
796 * <FILLMEIN>.
797 *
798 * @param Process
799 * <FILLMEIN>.
800 *
801 * @param OpenReason
802 * <FILLMEIN>.
803 *
804 * @return <FILLMEIN>.
805 *
806 * @remarks None.
807 *
808 *--*/
809 NTSTATUS
810 NTAPI
ObpIncrementHandleCount(IN PVOID Object,IN PACCESS_STATE AccessState OPTIONAL,IN KPROCESSOR_MODE AccessMode,IN ULONG HandleAttributes,IN PEPROCESS Process,IN OB_OPEN_REASON OpenReason)811 ObpIncrementHandleCount(IN PVOID Object,
812 IN PACCESS_STATE AccessState OPTIONAL,
813 IN KPROCESSOR_MODE AccessMode,
814 IN ULONG HandleAttributes,
815 IN PEPROCESS Process,
816 IN OB_OPEN_REASON OpenReason)
817 {
818 POBJECT_HEADER ObjectHeader;
819 POBJECT_TYPE ObjectType;
820 ULONG ProcessHandleCount;
821 NTSTATUS Status;
822 PEPROCESS ExclusiveProcess;
823 BOOLEAN Exclusive = FALSE, NewObject;
824 POBJECT_HEADER_CREATOR_INFO CreatorInfo;
825 KIRQL CalloutIrql;
826 KPROCESSOR_MODE ProbeMode;
827 ULONG Total;
828 POBJECT_HEADER_NAME_INFO NameInfo;
829 PAGED_CODE();
830
831 /* Get the object header and type */
832 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
833 ObjectType = ObjectHeader->Type;
834 OBTRACE(OB_HANDLE_DEBUG,
835 "%s - Incrementing count for: %p. Reason: %lx. HC PC %lx %lx\n",
836 __FUNCTION__,
837 Object,
838 OpenReason,
839 ObjectHeader->HandleCount,
840 ObjectHeader->PointerCount);
841
842 /* Check if caller is forcing user mode */
843 if (HandleAttributes & OBJ_FORCE_ACCESS_CHECK)
844 {
845 /* Force it */
846 ProbeMode = UserMode;
847 }
848 else
849 {
850 /* Keep original setting */
851 ProbeMode = AccessMode;
852 }
853
854 /* Lock the object */
855 ObpAcquireObjectLock(ObjectHeader);
856
857 /* Charge quota and remove the creator info flag */
858 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject);
859 if (!NT_SUCCESS(Status)) return Status;
860
861 /* Check if the open is exclusive */
862 if (HandleAttributes & OBJ_EXCLUSIVE)
863 {
864 /* Check if the object allows this, or if the inherit flag was given */
865 if ((HandleAttributes & OBJ_INHERIT) ||
866 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE))
867 {
868 /* Incorrect attempt */
869 Status = STATUS_INVALID_PARAMETER;
870 goto Quickie;
871 }
872
873 /* Check if we have access to it */
874 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader);
875 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) ||
876 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess())))
877 {
878 /* This isn't the right process */
879 Status = STATUS_ACCESS_DENIED;
880 goto Quickie;
881 }
882
883 /* Now you got exclusive access */
884 Exclusive = TRUE;
885 }
886 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) &&
887 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader)))
888 {
889 /* Caller didn't want exclusive access, but the object is exclusive */
890 Status = STATUS_ACCESS_DENIED;
891 goto Quickie;
892 }
893
894 /* Check for exclusive kernel object */
895 NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
896 if ((NameInfo) && (NameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE) &&
897 (ProbeMode != KernelMode))
898 {
899 /* Caller is not kernel, but the object is kernel exclusive */
900 Status = STATUS_ACCESS_DENIED;
901 goto Quickie;
902 }
903
904 /*
905 * Check if this is an object that went from 0 handles back to existence,
906 * but doesn't have an open procedure, only a close procedure. This means
907 * that it will never realize that the object is back alive, so we must
908 * fail the request.
909 */
910 if (!(ObjectHeader->HandleCount) &&
911 !(NewObject) &&
912 (ObjectType->TypeInfo.MaintainHandleCount) &&
913 !(ObjectType->TypeInfo.OpenProcedure) &&
914 (ObjectType->TypeInfo.CloseProcedure))
915 {
916 /* Fail */
917 Status = STATUS_UNSUCCESSFUL;
918 goto Quickie;
919 }
920
921 /* Check if we're opening an existing handle */
922 if ((OpenReason == ObOpenHandle) ||
923 ((OpenReason == ObDuplicateHandle) && (AccessState)))
924 {
925 /* Validate the caller's access to this object */
926 if (!ObCheckObjectAccess(Object,
927 AccessState,
928 TRUE,
929 ProbeMode,
930 &Status))
931 {
932 /* Access was denied, so fail */
933 goto Quickie;
934 }
935 }
936 else if (OpenReason == ObCreateHandle)
937 {
938 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
939 if (AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED)
940 {
941 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
942 AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED;
943 AccessState->RemainingDesiredAccess |= GENERIC_ALL;
944 }
945
946 /* Check if we have to map the GENERIC mask */
947 if (AccessState->RemainingDesiredAccess & GENERIC_ACCESS)
948 {
949 /* Map it to the correct access masks */
950 RtlMapGenericMask(&AccessState->RemainingDesiredAccess,
951 &ObjectType->TypeInfo.GenericMapping);
952 }
953
954 /* Check if the caller is trying to access system security */
955 if (AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY)
956 {
957 /* FIXME: TODO */
958 DPRINT1("ACCESS_SYSTEM_SECURITY not validated!\n");
959 }
960 }
961
962 /* Check if this is an exclusive handle */
963 if (Exclusive)
964 {
965 /* Save the owner process */
966 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process;
967 }
968
969 /* Increase the handle count */
970 InterlockedIncrementSizeT(&ObjectHeader->HandleCount);
971 ProcessHandleCount = 0;
972
973 /* Check if we have a handle database */
974 if (ObjectType->TypeInfo.MaintainHandleCount)
975 {
976 /* Increment the handle database */
977 Status = ObpIncrementHandleDataBase(ObjectHeader,
978 Process,
979 &ProcessHandleCount);
980 if (!NT_SUCCESS(Status))
981 {
982 /* FIXME: This should never happen for now */
983 DPRINT1("Unhandled case\n");
984 ASSERT(FALSE);
985 goto Quickie;
986 }
987 }
988
989 /* Release the lock */
990 ObpReleaseObjectLock(ObjectHeader);
991
992 /* Check if we have an open procedure */
993 Status = STATUS_SUCCESS;
994 if (ObjectType->TypeInfo.OpenProcedure)
995 {
996 /* Call it */
997 ObpCalloutStart(&CalloutIrql);
998 Status = ObjectType->TypeInfo.OpenProcedure(OpenReason,
999 Process,
1000 Object,
1001 AccessState ?
1002 AccessState->
1003 PreviouslyGrantedAccess :
1004 0,
1005 ProcessHandleCount);
1006 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object);
1007
1008 /* Check if the open procedure failed */
1009 if (!NT_SUCCESS(Status))
1010 {
1011 /* FIXME: This should never happen for now */
1012 DPRINT1("Unhandled case\n");
1013 ASSERT(FALSE);
1014 return Status;
1015 }
1016 }
1017
1018 /* Check if this is a create operation */
1019 if (OpenReason == ObCreateHandle)
1020 {
1021 /* Check if we have creator info */
1022 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
1023 if (CreatorInfo)
1024 {
1025 /* We do, acquire the lock */
1026 ObpEnterObjectTypeMutex(ObjectType);
1027
1028 /* Insert us on the list */
1029 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
1030
1031 /* Release the lock */
1032 ObpLeaveObjectTypeMutex(ObjectType);
1033 }
1034 }
1035
1036 /* Increase total number of handles */
1037 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
1038 if (Total > ObjectType->HighWaterNumberOfHandles)
1039 {
1040 /* Fixup count */
1041 ObjectType->HighWaterNumberOfHandles = Total;
1042 }
1043
1044 /* Trace call and return */
1045 OBTRACE(OB_HANDLE_DEBUG,
1046 "%s - Incremented count for: %p. Reason: %lx HC PC %lx %lx\n",
1047 __FUNCTION__,
1048 Object,
1049 OpenReason,
1050 ObjectHeader->HandleCount,
1051 ObjectHeader->PointerCount);
1052 return Status;
1053
1054 Quickie:
1055 /* Release lock and return */
1056 ObpReleaseObjectLock(ObjectHeader);
1057 return Status;
1058 }
1059
1060 /*++
1061 * @name ObpIncrementUnnamedHandleCount
1062 *
1063 * The ObpIncrementUnnamedHandleCount routine <FILLMEIN>
1064 *
1065 * @param Object
1066 * <FILLMEIN>.
1067 *
1068 * @param AccessState
1069 * <FILLMEIN>.
1070 *
1071 * @param AccessMode
1072 * <FILLMEIN>.
1073 *
1074 * @param HandleAttributes
1075 * <FILLMEIN>.
1076 *
1077 * @param Process
1078 * <FILLMEIN>.
1079 *
1080 * @param OpenReason
1081 * <FILLMEIN>.
1082 *
1083 * @return <FILLMEIN>.
1084 *
1085 * @remarks None.
1086 *
1087 *--*/
1088 NTSTATUS
1089 NTAPI
ObpIncrementUnnamedHandleCount(IN PVOID Object,IN PACCESS_MASK DesiredAccess,IN KPROCESSOR_MODE AccessMode,IN ULONG HandleAttributes,IN PEPROCESS Process)1090 ObpIncrementUnnamedHandleCount(IN PVOID Object,
1091 IN PACCESS_MASK DesiredAccess,
1092 IN KPROCESSOR_MODE AccessMode,
1093 IN ULONG HandleAttributes,
1094 IN PEPROCESS Process)
1095 {
1096 POBJECT_HEADER ObjectHeader;
1097 POBJECT_TYPE ObjectType;
1098 ULONG ProcessHandleCount;
1099 NTSTATUS Status;
1100 PEPROCESS ExclusiveProcess;
1101 BOOLEAN Exclusive = FALSE, NewObject;
1102 POBJECT_HEADER_CREATOR_INFO CreatorInfo;
1103 KIRQL CalloutIrql;
1104 ULONG Total;
1105
1106 /* Get the object header and type */
1107 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
1108 ObjectType = ObjectHeader->Type;
1109 OBTRACE(OB_HANDLE_DEBUG,
1110 "%s - Incrementing count for: %p. UNNAMED. HC PC %lx %lx\n",
1111 __FUNCTION__,
1112 Object,
1113 ObjectHeader->HandleCount,
1114 ObjectHeader->PointerCount);
1115
1116 /* Lock the object */
1117 ObpAcquireObjectLock(ObjectHeader);
1118
1119 /* Charge quota and remove the creator info flag */
1120 Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject);
1121 if (!NT_SUCCESS(Status)) return Status;
1122
1123 /* Check if the open is exclusive */
1124 if (HandleAttributes & OBJ_EXCLUSIVE)
1125 {
1126 /* Check if the object allows this, or if the inherit flag was given */
1127 if ((HandleAttributes & OBJ_INHERIT) ||
1128 !(ObjectHeader->Flags & OB_FLAG_EXCLUSIVE))
1129 {
1130 /* Incorrect attempt */
1131 Status = STATUS_INVALID_PARAMETER;
1132 goto Quickie;
1133 }
1134
1135 /* Check if we have access to it */
1136 ExclusiveProcess = OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader);
1137 if ((!(ExclusiveProcess) && (ObjectHeader->HandleCount)) ||
1138 ((ExclusiveProcess) && (ExclusiveProcess != PsGetCurrentProcess())))
1139 {
1140 /* This isn't the right process */
1141 Status = STATUS_ACCESS_DENIED;
1142 goto Quickie;
1143 }
1144
1145 /* Now you got exclusive access */
1146 Exclusive = TRUE;
1147 }
1148 else if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE) &&
1149 (OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader)))
1150 {
1151 /* Caller didn't want exclusive access, but the object is exclusive */
1152 Status = STATUS_ACCESS_DENIED;
1153 goto Quickie;
1154 }
1155
1156 /*
1157 * Check if this is an object that went from 0 handles back to existence,
1158 * but doesn't have an open procedure, only a close procedure. This means
1159 * that it will never realize that the object is back alive, so we must
1160 * fail the request.
1161 */
1162 if (!(ObjectHeader->HandleCount) &&
1163 !(NewObject) &&
1164 (ObjectType->TypeInfo.MaintainHandleCount) &&
1165 !(ObjectType->TypeInfo.OpenProcedure) &&
1166 (ObjectType->TypeInfo.CloseProcedure))
1167 {
1168 /* Fail */
1169 Status = STATUS_UNSUCCESSFUL;
1170 goto Quickie;
1171 }
1172
1173 /* Convert MAXIMUM_ALLOWED to GENERIC_ALL */
1174 if (*DesiredAccess & MAXIMUM_ALLOWED)
1175 {
1176 /* Mask out MAXIMUM_ALLOWED and stick GENERIC_ALL instead */
1177 *DesiredAccess &= ~MAXIMUM_ALLOWED;
1178 *DesiredAccess |= GENERIC_ALL;
1179 }
1180
1181 /* Check if we have to map the GENERIC mask */
1182 if (*DesiredAccess & GENERIC_ACCESS)
1183 {
1184 /* Map it to the correct access masks */
1185 RtlMapGenericMask(DesiredAccess,
1186 &ObjectType->TypeInfo.GenericMapping);
1187 }
1188
1189 /* Check if this is an exclusive handle */
1190 if (Exclusive)
1191 {
1192 /* Save the owner process */
1193 OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process;
1194 }
1195
1196 /* Increase the handle count */
1197 InterlockedIncrementSizeT(&ObjectHeader->HandleCount);
1198 ProcessHandleCount = 0;
1199
1200 /* Check if we have a handle database */
1201 if (ObjectType->TypeInfo.MaintainHandleCount)
1202 {
1203 /* Increment the handle database */
1204 Status = ObpIncrementHandleDataBase(ObjectHeader,
1205 Process,
1206 &ProcessHandleCount);
1207 if (!NT_SUCCESS(Status))
1208 {
1209 /* FIXME: This should never happen for now */
1210 DPRINT1("Unhandled case\n");
1211 ASSERT(FALSE);
1212 goto Quickie;
1213 }
1214 }
1215
1216 /* Release the lock */
1217 ObpReleaseObjectLock(ObjectHeader);
1218
1219 /* Check if we have an open procedure */
1220 Status = STATUS_SUCCESS;
1221 if (ObjectType->TypeInfo.OpenProcedure)
1222 {
1223 /* Call it */
1224 ObpCalloutStart(&CalloutIrql);
1225 Status = ObjectType->TypeInfo.OpenProcedure(ObCreateHandle,
1226 Process,
1227 Object,
1228 *DesiredAccess,
1229 ProcessHandleCount);
1230 ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object);
1231
1232 /* Check if the open procedure failed */
1233 if (!NT_SUCCESS(Status))
1234 {
1235 /* FIXME: This should never happen for now */
1236 DPRINT1("Unhandled case\n");
1237 ASSERT(FALSE);
1238 return Status;
1239 }
1240 }
1241
1242 /* Check if we have creator info */
1243 CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
1244 if (CreatorInfo)
1245 {
1246 /* We do, acquire the lock */
1247 ObpEnterObjectTypeMutex(ObjectType);
1248
1249 /* Insert us on the list */
1250 InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
1251
1252 /* Release the lock */
1253 ObpLeaveObjectTypeMutex(ObjectType);
1254 }
1255
1256 /* Increase total number of handles */
1257 Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
1258 if (Total > ObjectType->HighWaterNumberOfHandles)
1259 {
1260 /* Fixup count */
1261 ObjectType->HighWaterNumberOfHandles = Total;
1262 }
1263
1264 /* Trace call and return */
1265 OBTRACE(OB_HANDLE_DEBUG,
1266 "%s - Incremented count for: %p. UNNAMED HC PC %lx %lx\n",
1267 __FUNCTION__,
1268 Object,
1269 ObjectHeader->HandleCount,
1270 ObjectHeader->PointerCount);
1271 return Status;
1272
1273 Quickie:
1274 /* Release lock and return */
1275 ObpReleaseObjectLock(ObjectHeader);
1276 return Status;
1277 }
1278
1279 /*++
1280 * @name ObpCreateUnnamedHandle
1281 *
1282 * The ObpCreateUnnamedHandle routine <FILLMEIN>
1283 *
1284 * @param Object
1285 * <FILLMEIN>.
1286 *
1287 * @param DesiredAccess
1288 * <FILLMEIN>.
1289 *
1290 * @param AdditionalReferences
1291 * <FILLMEIN>.
1292 *
1293 * @param HandleAttributes
1294 * <FILLMEIN>.
1295 *
1296 * @param AccessMode
1297 * <FILLMEIN>.
1298 *
1299 * @param ReturnedObject
1300 * <FILLMEIN>.
1301 *
1302 * @param ReturnedHandle
1303 * <FILLMEIN>.
1304 *
1305 * @return <FILLMEIN>.
1306 *
1307 * @remarks None.
1308 *
1309 *--*/
1310 NTSTATUS
1311 NTAPI
ObpCreateUnnamedHandle(IN PVOID Object,IN ACCESS_MASK DesiredAccess,IN ULONG AdditionalReferences,IN ULONG HandleAttributes,IN KPROCESSOR_MODE AccessMode,OUT PVOID * ReturnedObject,OUT PHANDLE ReturnedHandle)1312 ObpCreateUnnamedHandle(IN PVOID Object,
1313 IN ACCESS_MASK DesiredAccess,
1314 IN ULONG AdditionalReferences,
1315 IN ULONG HandleAttributes,
1316 IN KPROCESSOR_MODE AccessMode,
1317 OUT PVOID *ReturnedObject,
1318 OUT PHANDLE ReturnedHandle)
1319 {
1320 HANDLE_TABLE_ENTRY NewEntry;
1321 POBJECT_HEADER ObjectHeader;
1322 HANDLE Handle;
1323 KAPC_STATE ApcState;
1324 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE;
1325 PVOID HandleTable;
1326 NTSTATUS Status;
1327 ACCESS_MASK GrantedAccess;
1328 POBJECT_TYPE ObjectType;
1329 PAGED_CODE();
1330
1331 /* Get the object header and type */
1332 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
1333 ObjectType = ObjectHeader->Type;
1334 OBTRACE(OB_HANDLE_DEBUG,
1335 "%s - Creating handle for: %p. UNNAMED. HC PC %lx %lx\n",
1336 __FUNCTION__,
1337 Object,
1338 ObjectHeader->HandleCount,
1339 ObjectHeader->PointerCount);
1340
1341 /* Save the object header */
1342 NewEntry.Object = ObjectHeader;
1343
1344 /* Mask out the internal attributes */
1345 NewEntry.ObAttributes |= HandleAttributes & OBJ_HANDLE_ATTRIBUTES;
1346
1347 /* Check if this is a kernel handle */
1348 if (HandleAttributes & OBJ_KERNEL_HANDLE)
1349 {
1350 /* Set the handle table */
1351 HandleTable = ObpKernelHandleTable;
1352 KernelHandle = TRUE;
1353
1354 /* Check if we're not in the system process */
1355 if (PsGetCurrentProcess() != PsInitialSystemProcess)
1356 {
1357 /* Attach to the system process */
1358 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
1359 AttachedToProcess = TRUE;
1360 }
1361 }
1362 else
1363 {
1364 /* Get the current handle table */
1365 HandleTable = PsGetCurrentProcess()->ObjectTable;
1366 }
1367
1368 /* Increment the handle count */
1369 Status = ObpIncrementUnnamedHandleCount(Object,
1370 &DesiredAccess,
1371 AccessMode,
1372 HandleAttributes,
1373 PsGetCurrentProcess());
1374 if (!NT_SUCCESS(Status))
1375 {
1376 /*
1377 * We failed (meaning security failure, according to NT Internals)
1378 * detach and return
1379 */
1380 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1381 return Status;
1382 }
1383
1384 /* Remove what's not in the valid access mask */
1385 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask |
1386 ACCESS_SYSTEM_SECURITY);
1387
1388 /* Handle extra references */
1389 if (AdditionalReferences)
1390 {
1391 /* Add them to the header */
1392 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount,
1393 AdditionalReferences);
1394 }
1395
1396 /* Save the access mask */
1397 NewEntry.GrantedAccess = GrantedAccess;
1398
1399 /*
1400 * Create the actual handle. We'll need to do this *after* calling
1401 * ObpIncrementHandleCount to make sure that Object Security is valid
1402 * (specified in Gl00my documentation on Ob)
1403 */
1404 OBTRACE(OB_HANDLE_DEBUG,
1405 "%s - Handle Properties: [%p-%lx-%lx]\n",
1406 __FUNCTION__,
1407 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
1408 Handle = ExCreateHandle(HandleTable, &NewEntry);
1409
1410 /* Make sure we got a handle */
1411 if (Handle)
1412 {
1413 /* Check if this was a kernel handle */
1414 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle);
1415
1416 /* Return handle and object */
1417 *ReturnedHandle = Handle;
1418
1419 /* Return the new object only if caller wanted it biased */
1420 if ((AdditionalReferences) && (ReturnedObject))
1421 {
1422 /* Return it */
1423 *ReturnedObject = Object;
1424 }
1425
1426 /* Detach if needed */
1427 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1428
1429 /* Trace and return */
1430 OBTRACE(OB_HANDLE_DEBUG,
1431 "%s - Returning Handle: %p HC PC %lx %lx\n",
1432 __FUNCTION__,
1433 Handle,
1434 ObjectHeader->HandleCount,
1435 ObjectHeader->PointerCount);
1436 return STATUS_SUCCESS;
1437 }
1438
1439 /* Handle extra references */
1440 if (AdditionalReferences)
1441 {
1442 /* Dereference it as many times as required */
1443 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount,
1444 -(LONG)AdditionalReferences);
1445 }
1446
1447 /* Decrement the handle count and detach */
1448 ObpDecrementHandleCount(&ObjectHeader->Body,
1449 PsGetCurrentProcess(),
1450 GrantedAccess,
1451 ObjectType);
1452
1453 /* Detach and fail */
1454 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1455 return STATUS_INSUFFICIENT_RESOURCES;
1456 }
1457
1458 /*++
1459 * @name ObpCreateHandle
1460 *
1461 * The ObpCreateHandle routine <FILLMEIN>
1462 *
1463 * @param OpenReason
1464 * <FILLMEIN>.
1465 *
1466 * @param Object
1467 * <FILLMEIN>.
1468 *
1469 * @param Type
1470 * <FILLMEIN>.
1471 *
1472 * @param AccessState
1473 * <FILLMEIN>.
1474 *
1475 * @param AdditionalReferences
1476 * <FILLMEIN>.
1477 *
1478 * @param HandleAttributes
1479 * <FILLMEIN>.
1480 *
1481 * @param AccessMode
1482 * <FILLMEIN>.
1483 *
1484 * @param ReturnedObject
1485 * <FILLMEIN>.
1486 *
1487 * @param ReturnedHandle
1488 * <FILLMEIN>.
1489 *
1490 * @return <FILLMEIN>.
1491 *
1492 * @remarks Cleans up the Lookup Context on return.
1493 *
1494 *--*/
1495 NTSTATUS
1496 NTAPI
ObpCreateHandle(IN OB_OPEN_REASON OpenReason,IN PVOID Object,IN POBJECT_TYPE Type OPTIONAL,IN PACCESS_STATE AccessState,IN ULONG AdditionalReferences,IN ULONG HandleAttributes,IN POBP_LOOKUP_CONTEXT Context,IN KPROCESSOR_MODE AccessMode,OUT PVOID * ReturnedObject,OUT PHANDLE ReturnedHandle)1497 ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
1498 IN PVOID Object,
1499 IN POBJECT_TYPE Type OPTIONAL,
1500 IN PACCESS_STATE AccessState,
1501 IN ULONG AdditionalReferences,
1502 IN ULONG HandleAttributes,
1503 IN POBP_LOOKUP_CONTEXT Context,
1504 IN KPROCESSOR_MODE AccessMode,
1505 OUT PVOID *ReturnedObject,
1506 OUT PHANDLE ReturnedHandle)
1507 {
1508 HANDLE_TABLE_ENTRY NewEntry;
1509 POBJECT_HEADER ObjectHeader;
1510 HANDLE Handle;
1511 KAPC_STATE ApcState;
1512 BOOLEAN AttachedToProcess = FALSE, KernelHandle = FALSE;
1513 POBJECT_TYPE ObjectType;
1514 PVOID HandleTable;
1515 NTSTATUS Status;
1516 ACCESS_MASK DesiredAccess, GrantedAccess;
1517 PAUX_ACCESS_DATA AuxData;
1518 PAGED_CODE();
1519
1520 /* Get the object header and type */
1521 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
1522 ObjectType = ObjectHeader->Type;
1523 OBTRACE(OB_HANDLE_DEBUG,
1524 "%s - Creating handle for: %p. Reason: %lx. HC PC %lx %lx\n",
1525 __FUNCTION__,
1526 Object,
1527 OpenReason,
1528 ObjectHeader->HandleCount,
1529 ObjectHeader->PointerCount);
1530
1531 /* Check if the types match */
1532 if ((Type) && (ObjectType != Type))
1533 {
1534 /* They don't, cleanup */
1535 if (Context) ObpReleaseLookupContext(Context);
1536 return STATUS_OBJECT_TYPE_MISMATCH;
1537 }
1538
1539 /* Save the object header */
1540 NewEntry.Object = ObjectHeader;
1541
1542 /* Check if this is a kernel handle */
1543 if (HandleAttributes & OBJ_KERNEL_HANDLE)
1544 {
1545 /* Set the handle table */
1546 HandleTable = ObpKernelHandleTable;
1547 KernelHandle = TRUE;
1548
1549 /* Check if we're not in the system process */
1550 if (PsGetCurrentProcess() != PsInitialSystemProcess)
1551 {
1552 /* Attach to the system process */
1553 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
1554 AttachedToProcess = TRUE;
1555 }
1556 }
1557 else
1558 {
1559 /* Get the current handle table */
1560 HandleTable = PsGetCurrentProcess()->ObjectTable;
1561 }
1562
1563 /* Increment the handle count */
1564 Status = ObpIncrementHandleCount(Object,
1565 AccessState,
1566 AccessMode,
1567 HandleAttributes,
1568 PsGetCurrentProcess(),
1569 OpenReason);
1570 if (!NT_SUCCESS(Status))
1571 {
1572 /*
1573 * We failed (meaning security failure, according to NT Internals)
1574 * detach and return
1575 */
1576 if (Context) ObpReleaseLookupContext(Context);
1577 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1578 return Status;
1579 }
1580
1581 /* Check if we are doing audits on close */
1582 if (AccessState->GenerateOnClose)
1583 {
1584 /* Force the attribute on */
1585 HandleAttributes |= OBJ_AUDIT_OBJECT_CLOSE;
1586 }
1587
1588 /* Mask out the internal attributes */
1589 NewEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES);
1590
1591 /* Get the original desired access */
1592 DesiredAccess = AccessState->RemainingDesiredAccess |
1593 AccessState->PreviouslyGrantedAccess;
1594
1595 /* Remove what's not in the valid access mask */
1596 GrantedAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask |
1597 ACCESS_SYSTEM_SECURITY);
1598
1599 /* Update the value in the access state */
1600 AccessState->PreviouslyGrantedAccess = GrantedAccess;
1601
1602 /* Get the auxiliary data */
1603 AuxData = AccessState->AuxData;
1604
1605 /* Handle extra references */
1606 if (AdditionalReferences)
1607 {
1608 /* Add them to the header */
1609 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount,
1610 AdditionalReferences);
1611 }
1612
1613 /* Now we can release the object */
1614 if (Context) ObpReleaseLookupContext(Context);
1615
1616 /* Save the access mask */
1617 NewEntry.GrantedAccess = GrantedAccess;
1618
1619 /*
1620 * Create the actual handle. We'll need to do this *after* calling
1621 * ObpIncrementHandleCount to make sure that Object Security is valid
1622 * (specified in Gl00my documentation on Ob)
1623 */
1624 OBTRACE(OB_HANDLE_DEBUG,
1625 "%s - Handle Properties: [%p-%lx-%lx]\n",
1626 __FUNCTION__,
1627 NewEntry.Object, NewEntry.ObAttributes & 3, NewEntry.GrantedAccess);
1628 Handle = ExCreateHandle(HandleTable, &NewEntry);
1629
1630 /* Make sure we got a handle */
1631 if (Handle)
1632 {
1633 /* Check if this was a kernel handle */
1634 if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle);
1635
1636 /* Return it */
1637 *ReturnedHandle = Handle;
1638
1639 /* Check if we need to generate on audit */
1640 if (AccessState->GenerateAudit)
1641 {
1642 /* Audit the handle creation */
1643 //SeAuditHandleCreation(AccessState, Handle);
1644 }
1645
1646 /* Check if this was a create */
1647 if (OpenReason == ObCreateHandle)
1648 {
1649 /* Check if we need to audit the privileges */
1650 if ((AuxData->PrivilegesUsed) &&
1651 (AuxData->PrivilegesUsed->PrivilegeCount))
1652 {
1653 /* Do the audit */
1654 #if 0
1655 SePrivilegeObjectAuditAlarm(Handle,
1656 &AccessState->
1657 SubjectSecurityContext,
1658 GrantedAccess,
1659 AuxData->PrivilegesUsed,
1660 TRUE,
1661 ExGetPreviousMode());
1662 #endif
1663 }
1664 }
1665
1666 /* Return the new object only if caller wanted it biased */
1667 if ((AdditionalReferences) && (ReturnedObject))
1668 {
1669 /* Return it */
1670 *ReturnedObject = Object;
1671 }
1672
1673 /* Detach if needed */
1674 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1675
1676 /* Trace and return */
1677 OBTRACE(OB_HANDLE_DEBUG,
1678 "%s - Returning Handle: %p HC PC %lx %lx\n",
1679 __FUNCTION__,
1680 Handle,
1681 ObjectHeader->HandleCount,
1682 ObjectHeader->PointerCount);
1683 return STATUS_SUCCESS;
1684 }
1685
1686 /* Decrement the handle count and detach */
1687 ObpDecrementHandleCount(&ObjectHeader->Body,
1688 PsGetCurrentProcess(),
1689 GrantedAccess,
1690 ObjectType);
1691
1692 /* Handle extra references */
1693 if (AdditionalReferences)
1694 {
1695 /* Check how many extra references were added */
1696 if (AdditionalReferences > 1)
1697 {
1698 /* Dereference it many times */
1699 InterlockedExchangeAddSizeT(&ObjectHeader->PointerCount,
1700 -(LONG)(AdditionalReferences - 1));
1701 }
1702
1703 /* Dereference the object one last time */
1704 ObDereferenceObject(Object);
1705 }
1706
1707 /* Detach if necessary and fail */
1708 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1709 return STATUS_INSUFFICIENT_RESOURCES;
1710 }
1711
1712 /*++
1713 * @name ObpCloseHandle
1714 *
1715 * The ObpCloseHandle routine <FILLMEIN>
1716 *
1717 * @param Handle
1718 * <FILLMEIN>.
1719 *
1720 * @param AccessMode
1721 * <FILLMEIN>.
1722 *
1723 * @return <FILLMEIN>.
1724 *
1725 * @remarks None.
1726 *
1727 *--*/
1728 NTSTATUS
1729 NTAPI
ObpCloseHandle(IN HANDLE Handle,IN KPROCESSOR_MODE AccessMode)1730 ObpCloseHandle(IN HANDLE Handle,
1731 IN KPROCESSOR_MODE AccessMode)
1732 {
1733 PVOID HandleTable;
1734 BOOLEAN AttachedToProcess = FALSE;
1735 KAPC_STATE ApcState;
1736 PHANDLE_TABLE_ENTRY HandleTableEntry;
1737 NTSTATUS Status;
1738 PEPROCESS Process = PsGetCurrentProcess();
1739 PAGED_CODE();
1740 OBTRACE(OB_HANDLE_DEBUG,
1741 "%s - Closing handle: %p\n", __FUNCTION__, Handle);
1742
1743 if (AccessMode == KernelMode && Handle == (HANDLE)-1)
1744 return STATUS_INVALID_HANDLE;
1745
1746 /* Check if we're dealing with a kernel handle */
1747 if (ObpIsKernelHandle(Handle, AccessMode))
1748 {
1749 /* Use the kernel table and convert the handle */
1750 HandleTable = ObpKernelHandleTable;
1751 Handle = ObKernelHandleToHandle(Handle);
1752
1753 /* Check if we're not in the system process */
1754 if (Process != PsInitialSystemProcess)
1755 {
1756 /* Attach to the system process */
1757 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
1758 AttachedToProcess = TRUE;
1759 }
1760 }
1761 else
1762 {
1763 /* Use the process's handle table */
1764 HandleTable = Process->ObjectTable;
1765 }
1766
1767 /* Enter a critical region to protect handle access */
1768 KeEnterCriticalRegion();
1769
1770 /* Get the handle entry */
1771 HandleTableEntry = ExMapHandleToPointer(HandleTable, Handle);
1772 if (HandleTableEntry)
1773 {
1774 /* Now close the entry */
1775 Status = ObpCloseHandleTableEntry(HandleTable,
1776 HandleTableEntry,
1777 Handle,
1778 AccessMode,
1779 FALSE);
1780
1781 /* We can quit the critical region now */
1782 KeLeaveCriticalRegion();
1783
1784 /* Detach and return success */
1785 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1786 }
1787 else
1788 {
1789 /* We failed, quit the critical region */
1790 KeLeaveCriticalRegion();
1791
1792 /* Detach */
1793 if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
1794
1795 /* Check if we have a valid handle that's not the process or thread */
1796 if ((Handle) &&
1797 (Handle != NtCurrentProcess()) &&
1798 (Handle != NtCurrentThread()))
1799 {
1800 /* Check if we came from user mode */
1801 if (AccessMode != KernelMode)
1802 {
1803 /* Check if we have no debug port */
1804 if (Process->DebugPort)
1805 {
1806 /* Make sure we're not attached */
1807 if (!KeIsAttachedProcess())
1808 {
1809 /* Raise an exception */
1810 return KeRaiseUserException(STATUS_INVALID_HANDLE);
1811 }
1812 }
1813 }
1814 else
1815 {
1816 /* This is kernel mode. Check if we're exiting */
1817 if (!(PsIsThreadTerminating(PsGetCurrentThread())) &&
1818 (Process->Peb))
1819 {
1820 /* Check if the debugger is enabled */
1821 if (KdDebuggerEnabled)
1822 {
1823 /* Bugcheck */
1824 KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0);
1825 }
1826 }
1827 }
1828 }
1829
1830 /* Set invalid status */
1831 Status = STATUS_INVALID_HANDLE;
1832 }
1833
1834 /* Return status */
1835 OBTRACE(OB_HANDLE_DEBUG,
1836 "%s - Closed handle: %p S: %lx\n",
1837 __FUNCTION__, Handle, Status);
1838 return Status;
1839 }
1840
1841 /*++
1842 * @name ObpSetHandleAttributes
1843 *
1844 * The ObpSetHandleAttributes routine <FILLMEIN>
1845 *
1846 * @param HandleTableEntry
1847 * <FILLMEIN>.
1848 *
1849 * @param Context
1850 * <FILLMEIN>.
1851 *
1852 * @return <FILLMEIN>.
1853 *
1854 * @remarks None.
1855 *
1856 *--*/
1857 BOOLEAN
1858 NTAPI
ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,IN ULONG_PTR Context)1859 ObpSetHandleAttributes(IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
1860 IN ULONG_PTR Context)
1861 {
1862 POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = (PVOID)Context;
1863 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
1864
1865 /* Check if making the handle inheritable */
1866 if (SetHandleInfo->Information.Inherit)
1867 {
1868 /* Check if inheriting is not supported for this object */
1869 if (ObjectHeader->Type->TypeInfo.InvalidAttributes & OBJ_INHERIT)
1870 {
1871 /* Fail without changing anything */
1872 return FALSE;
1873 }
1874
1875 /* Set the flag */
1876 HandleTableEntry->ObAttributes |= OBJ_INHERIT;
1877 }
1878 else
1879 {
1880 /* Otherwise this implies we're removing the flag */
1881 HandleTableEntry->ObAttributes &= ~OBJ_INHERIT;
1882 }
1883
1884 /* Check if making the handle protected */
1885 if (SetHandleInfo->Information.ProtectFromClose)
1886 {
1887 /* Set the flag */
1888 HandleTableEntry->GrantedAccess |= ObpAccessProtectCloseBit;
1889 }
1890 else
1891 {
1892 /* Otherwise, remove it */
1893 HandleTableEntry->GrantedAccess &= ~ObpAccessProtectCloseBit;
1894 }
1895
1896 /* Return success */
1897 return TRUE;
1898 }
1899
1900 /*++
1901 * @name ObpCloseHandleCallback
1902 *
1903 * The ObpCloseHandleCallback routine <FILLMEIN>
1904 *
1905 * @param HandleTable
1906 * <FILLMEIN>.
1907 *
1908 * @param Object
1909 * <FILLMEIN>.
1910 *
1911 * @param GrantedAccess
1912 * <FILLMEIN>.
1913 *
1914 * @param Context
1915 * <FILLMEIN>.
1916 *
1917 * @return <FILLMEIN>.
1918 *
1919 * @remarks None.
1920 *
1921 *--*/
1922 BOOLEAN
1923 NTAPI
ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry,IN HANDLE Handle,IN PVOID Context)1924 ObpCloseHandleCallback(IN PHANDLE_TABLE_ENTRY HandleTableEntry,
1925 IN HANDLE Handle,
1926 IN PVOID Context)
1927 {
1928 POBP_CLOSE_HANDLE_CONTEXT CloseContext = (POBP_CLOSE_HANDLE_CONTEXT)Context;
1929
1930 /* Simply decrement the handle count */
1931 ObpCloseHandleTableEntry(CloseContext->HandleTable,
1932 HandleTableEntry,
1933 Handle,
1934 CloseContext->AccessMode,
1935 TRUE);
1936 return TRUE;
1937 }
1938
1939 /*++
1940 * @name ObpDuplicateHandleCallback
1941 *
1942 * The ObpDuplicateHandleCallback routine <FILLMEIN>
1943 *
1944 * @param HandleTable
1945 * <FILLMEIN>.
1946 *
1947 * @param HandleTableEntry
1948 * <FILLMEIN>.
1949 *
1950 * @param Context
1951 * <FILLMEIN>.
1952 *
1953 * @return <FILLMEIN>.
1954 *
1955 * @remarks None.
1956 *
1957 *--*/
1958 BOOLEAN
1959 NTAPI
ObpDuplicateHandleCallback(IN PEPROCESS Process,IN PHANDLE_TABLE HandleTable,IN PHANDLE_TABLE_ENTRY OldEntry,IN PHANDLE_TABLE_ENTRY HandleTableEntry)1960 ObpDuplicateHandleCallback(IN PEPROCESS Process,
1961 IN PHANDLE_TABLE HandleTable,
1962 IN PHANDLE_TABLE_ENTRY OldEntry,
1963 IN PHANDLE_TABLE_ENTRY HandleTableEntry)
1964 {
1965 POBJECT_HEADER ObjectHeader;
1966 BOOLEAN Ret = FALSE;
1967 ACCESS_STATE AccessState;
1968 NTSTATUS Status;
1969 PAGED_CODE();
1970
1971 /* Make sure that the handle is inheritable */
1972 Ret = (HandleTableEntry->ObAttributes & OBJ_INHERIT) != 0;
1973 if (Ret)
1974 {
1975 /* Get the object header */
1976 ObjectHeader = ObpGetHandleObject(HandleTableEntry);
1977
1978 /* Increment the pointer count */
1979 InterlockedIncrementSizeT(&ObjectHeader->PointerCount);
1980
1981 /* Release the handle lock */
1982 ExUnlockHandleTableEntry(HandleTable, OldEntry);
1983
1984 /* Setup the access state */
1985 AccessState.PreviouslyGrantedAccess = HandleTableEntry->GrantedAccess;
1986
1987 /* Call the shared routine for incrementing handles */
1988 Status = ObpIncrementHandleCount(&ObjectHeader->Body,
1989 &AccessState,
1990 KernelMode,
1991 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES,
1992 Process,
1993 ObInheritHandle);
1994 if (!NT_SUCCESS(Status))
1995 {
1996 /* Return failure */
1997 ObDereferenceObject(&ObjectHeader->Body);
1998 Ret = FALSE;
1999 }
2000 }
2001 else
2002 {
2003 /* Release the handle lock */
2004 ExUnlockHandleTableEntry(HandleTable, OldEntry);
2005 }
2006
2007 /* Return duplication result */
2008 return Ret;
2009 }
2010
2011 /*++
2012 * @name ObClearProcessHandleTable
2013 *
2014 * The ObClearProcessHandleTable routine clears the handle table
2015 * of the given process.
2016 *
2017 * @param Process
2018 * The process of which the handle table should be cleared.
2019 *
2020 * @return None.
2021 *
2022 * @remarks None.
2023 *
2024 *--*/
2025 VOID
2026 NTAPI
ObClearProcessHandleTable(IN PEPROCESS Process)2027 ObClearProcessHandleTable(IN PEPROCESS Process)
2028 {
2029 PHANDLE_TABLE HandleTable;
2030 OBP_CLOSE_HANDLE_CONTEXT Context;
2031 KAPC_STATE ApcState;
2032 BOOLEAN AttachedToProcess = FALSE;
2033
2034 ASSERT(Process);
2035
2036 /* Ensure the handle table doesn't go away while we use it */
2037 HandleTable = ObReferenceProcessHandleTable(Process);
2038 if (!HandleTable) return;
2039
2040 /* Attach to the current process if needed */
2041 if (PsGetCurrentProcess() != Process)
2042 {
2043 KeStackAttachProcess(&Process->Pcb, &ApcState);
2044 AttachedToProcess = TRUE;
2045 }
2046
2047 /* Enter a critical region */
2048 KeEnterCriticalRegion();
2049
2050 /* Fill out the context */
2051 Context.AccessMode = UserMode;
2052 Context.HandleTable = HandleTable;
2053
2054 /* Sweep the handle table to close all handles */
2055 ExSweepHandleTable(HandleTable,
2056 ObpCloseHandleCallback,
2057 &Context);
2058
2059 /* Leave the critical region */
2060 KeLeaveCriticalRegion();
2061
2062 /* Detach if needed */
2063 if (AttachedToProcess)
2064 KeUnstackDetachProcess(&ApcState);
2065
2066 /* Let the handle table go */
2067 ObDereferenceProcessHandleTable(Process);
2068 }
2069
2070 /*++
2071 * @name ObInitProcess
2072 *
2073 * The ObInitProcess routine initializes the handle table for the process
2074 * to be initialized, by either creating a new one or duplicating it from
2075 * the parent process.
2076 *
2077 * @param Parent
2078 * A parent process (optional).
2079 *
2080 * @param Process
2081 * The process to initialize.
2082 *
2083 * @return Success or failure.
2084 *
2085 * @remarks None.
2086 *
2087 *--*/
2088 NTSTATUS
2089 NTAPI
ObInitProcess(IN PEPROCESS Parent OPTIONAL,IN PEPROCESS Process)2090 ObInitProcess(IN PEPROCESS Parent OPTIONAL,
2091 IN PEPROCESS Process)
2092 {
2093 PHANDLE_TABLE ParentTable, ObjectTable;
2094
2095 /* Check for a parent */
2096 if (Parent)
2097 {
2098 /* Reference the parent's table */
2099 ParentTable = ObReferenceProcessHandleTable(Parent);
2100 if (!ParentTable) return STATUS_PROCESS_IS_TERMINATING;
2101
2102 /* Duplicate it */
2103 ObjectTable = ExDupHandleTable(Process,
2104 ParentTable,
2105 ObpDuplicateHandleCallback,
2106 OBJ_INHERIT);
2107 }
2108 else
2109 {
2110 /* Otherwise just create a new table */
2111 ParentTable = NULL;
2112 ObjectTable = ExCreateHandleTable(Process);
2113 }
2114
2115 /* Make sure we have a table */
2116 if (ObjectTable)
2117 {
2118 /* Associate it */
2119 Process->ObjectTable = ObjectTable;
2120
2121 /* Check for auditing */
2122 if (SeDetailedAuditingWithToken(NULL))
2123 {
2124 /* FIXME: TODO */
2125 DPRINT1("Need auditing!\n");
2126 }
2127
2128 /* Get rid of the old table now */
2129 if (ParentTable) ObDereferenceProcessHandleTable(Parent);
2130
2131 /* We are done */
2132 return STATUS_SUCCESS;
2133 }
2134 else
2135 {
2136 /* Fail */
2137 Process->ObjectTable = NULL;
2138 if (ParentTable) ObDereferenceProcessHandleTable(Parent);
2139 return STATUS_INSUFFICIENT_RESOURCES;
2140 }
2141 }
2142
2143 /*++
2144 * @name ObKillProcess
2145 *
2146 * The ObKillProcess routine performs rundown operations on the process,
2147 * then clears and destroys its handle table.
2148 *
2149 * @param Process
2150 * The process to be killed.
2151 *
2152 * @return None.
2153 *
2154 * @remarks Called by the Object Manager cleanup code (kernel)
2155 * when a process is to be destroyed.
2156 *
2157 *--*/
2158 VOID
2159 NTAPI
ObKillProcess(IN PEPROCESS Process)2160 ObKillProcess(IN PEPROCESS Process)
2161 {
2162 PHANDLE_TABLE HandleTable;
2163 OBP_CLOSE_HANDLE_CONTEXT Context;
2164 BOOLEAN HardErrors;
2165 PAGED_CODE();
2166
2167 /* Wait for process rundown and then complete it */
2168 ExWaitForRundownProtectionRelease(&Process->RundownProtect);
2169 ExRundownCompleted(&Process->RundownProtect);
2170
2171 /* Get the object table */
2172 HandleTable = Process->ObjectTable;
2173 if (!HandleTable) return;
2174
2175 /* Disable hard errors while we close handles */
2176 HardErrors = IoSetThreadHardErrorMode(FALSE);
2177
2178 /* Enter a critical region */
2179 KeEnterCriticalRegion();
2180
2181 /* Fill out the context */
2182 Context.AccessMode = KernelMode;
2183 Context.HandleTable = HandleTable;
2184
2185 /* Sweep the handle table to close all handles */
2186 ExSweepHandleTable(HandleTable,
2187 ObpCloseHandleCallback,
2188 &Context);
2189 ASSERT(HandleTable->HandleCount == 0);
2190
2191 /* Leave the critical region */
2192 KeLeaveCriticalRegion();
2193
2194 /* Re-enable hard errors */
2195 IoSetThreadHardErrorMode(HardErrors);
2196
2197 /* Destroy the object table */
2198 Process->ObjectTable = NULL;
2199 ExDestroyHandleTable(HandleTable, NULL);
2200 }
2201
2202 NTSTATUS
2203 NTAPI
ObDuplicateObject(IN PEPROCESS SourceProcess,IN HANDLE SourceHandle,IN PEPROCESS TargetProcess OPTIONAL,IN PHANDLE TargetHandle OPTIONAL,IN ACCESS_MASK DesiredAccess,IN ULONG HandleAttributes,IN ULONG Options,IN KPROCESSOR_MODE PreviousMode)2204 ObDuplicateObject(IN PEPROCESS SourceProcess,
2205 IN HANDLE SourceHandle,
2206 IN PEPROCESS TargetProcess OPTIONAL,
2207 IN PHANDLE TargetHandle OPTIONAL,
2208 IN ACCESS_MASK DesiredAccess,
2209 IN ULONG HandleAttributes,
2210 IN ULONG Options,
2211 IN KPROCESSOR_MODE PreviousMode)
2212 {
2213 HANDLE_TABLE_ENTRY NewHandleEntry;
2214 BOOLEAN AttachedToProcess = FALSE;
2215 PVOID SourceObject;
2216 POBJECT_HEADER ObjectHeader;
2217 POBJECT_TYPE ObjectType;
2218 HANDLE NewHandle;
2219 KAPC_STATE ApcState;
2220 NTSTATUS Status;
2221 ACCESS_MASK TargetAccess, SourceAccess;
2222 ACCESS_STATE AccessState;
2223 PACCESS_STATE PassedAccessState = NULL;
2224 AUX_ACCESS_DATA AuxData;
2225 PHANDLE_TABLE HandleTable;
2226 OBJECT_HANDLE_INFORMATION HandleInformation;
2227 ULONG AuditMask;
2228 BOOLEAN KernelHandle = FALSE;
2229
2230 PAGED_CODE();
2231 OBTRACE(OB_HANDLE_DEBUG,
2232 "%s - Duplicating handle: %p for %p into %p\n",
2233 __FUNCTION__,
2234 SourceHandle,
2235 SourceProcess,
2236 TargetProcess);
2237
2238 /* Assume failure */
2239 if (TargetHandle) *TargetHandle = NULL;
2240
2241 /* Check if we're not duplicating the same access */
2242 if (!(Options & DUPLICATE_SAME_ACCESS))
2243 {
2244 /* Validate the desired access */
2245 Status = STATUS_SUCCESS; //ObpValidateDesiredAccess(DesiredAccess);
2246 if (!NT_SUCCESS(Status)) return Status;
2247 }
2248
2249 /* Reference the object table */
2250 HandleTable = ObReferenceProcessHandleTable(SourceProcess);
2251 if (!HandleTable) return STATUS_PROCESS_IS_TERMINATING;
2252
2253 /* Reference the process object */
2254 Status = ObpReferenceProcessObjectByHandle(SourceHandle,
2255 SourceProcess,
2256 HandleTable,
2257 PreviousMode,
2258 &SourceObject,
2259 &HandleInformation,
2260 &AuditMask);
2261 if (!NT_SUCCESS(Status))
2262 {
2263 /* Fail */
2264 ObDereferenceProcessHandleTable(SourceProcess);
2265 return Status;
2266 }
2267 else
2268 {
2269 /* Check if we have to don't have to audit object close */
2270 if (!(HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE))
2271 {
2272 /* Then there is no audit mask */
2273 AuditMask = 0;
2274 }
2275 }
2276
2277 /* Check if there's no target process */
2278 if (!TargetProcess)
2279 {
2280 /* Check if the caller wanted actual duplication */
2281 if (!(Options & DUPLICATE_CLOSE_SOURCE))
2282 {
2283 /* Invalid request */
2284 Status = STATUS_INVALID_PARAMETER;
2285 }
2286 else
2287 {
2288 /* Otherwise, do the attach */
2289 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
2290
2291 /* Close the handle and detach */
2292 NtClose(SourceHandle);
2293 KeUnstackDetachProcess(&ApcState);
2294 }
2295
2296 /* Return */
2297 ObDereferenceProcessHandleTable(SourceProcess);
2298 ObDereferenceObject(SourceObject);
2299 return Status;
2300 }
2301
2302 /* Create a kernel handle if asked, but only in the system process */
2303 if (PreviousMode == KernelMode &&
2304 HandleAttributes & OBJ_KERNEL_HANDLE &&
2305 TargetProcess == PsInitialSystemProcess)
2306 {
2307 KernelHandle = TRUE;
2308 }
2309
2310 /* Get the target handle table */
2311 HandleTable = ObReferenceProcessHandleTable(TargetProcess);
2312 if (!HandleTable)
2313 {
2314 /* Check if the caller wanted us to close the handle */
2315 if (Options & DUPLICATE_CLOSE_SOURCE)
2316 {
2317 /* Do the attach */
2318 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
2319
2320 /* Close the handle and detach */
2321 NtClose(SourceHandle);
2322 KeUnstackDetachProcess(&ApcState);
2323 }
2324
2325 /* Return */
2326 ObDereferenceProcessHandleTable(SourceProcess);
2327 ObDereferenceObject(SourceObject);
2328 return STATUS_PROCESS_IS_TERMINATING;
2329 }
2330
2331 /* Get the source access */
2332 SourceAccess = HandleInformation.GrantedAccess;
2333
2334 /* Check if we're not in the target process */
2335 if (TargetProcess != PsGetCurrentProcess())
2336 {
2337 /* Attach to it */
2338 KeStackAttachProcess(&TargetProcess->Pcb, &ApcState);
2339 AttachedToProcess = TRUE;
2340 }
2341
2342 /* Check if we're duplicating the attributes */
2343 if (Options & DUPLICATE_SAME_ATTRIBUTES)
2344 {
2345 /* Duplicate them */
2346 HandleAttributes = HandleInformation.HandleAttributes;
2347 }
2348 else
2349 {
2350 /* Don't allow caller to bypass auditing */
2351 HandleAttributes |= HandleInformation.HandleAttributes &
2352 OBJ_AUDIT_OBJECT_CLOSE;
2353 }
2354
2355 /* Check if we're duplicating the access */
2356 if (Options & DUPLICATE_SAME_ACCESS) DesiredAccess = SourceAccess;
2357
2358 /* Get object data */
2359 ObjectHeader = OBJECT_TO_OBJECT_HEADER(SourceObject);
2360 ObjectType = ObjectHeader->Type;
2361
2362 /* Fill out the entry */
2363 RtlZeroMemory(&NewHandleEntry, sizeof(HANDLE_TABLE_ENTRY));
2364 NewHandleEntry.Object = ObjectHeader;
2365 NewHandleEntry.ObAttributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES);
2366
2367 /* Check if we're using a generic mask */
2368 if (DesiredAccess & GENERIC_ACCESS)
2369 {
2370 /* Map it */
2371 RtlMapGenericMask(&DesiredAccess,
2372 &ObjectType->TypeInfo.GenericMapping);
2373 }
2374
2375 /* Set the target access, always propagate ACCESS_SYSTEM_SECURITY */
2376 TargetAccess = DesiredAccess & (ObjectType->TypeInfo.ValidAccessMask |
2377 ACCESS_SYSTEM_SECURITY);
2378 NewHandleEntry.GrantedAccess = TargetAccess;
2379
2380 /* Check if we're asking for new access */
2381 if (TargetAccess & ~SourceAccess)
2382 {
2383 /* We are. We need the security procedure to validate this */
2384 if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
2385 {
2386 /* Use our built-in access state */
2387 PassedAccessState = &AccessState;
2388 Status = SeCreateAccessState(&AccessState,
2389 &AuxData,
2390 TargetAccess,
2391 &ObjectType->TypeInfo.GenericMapping);
2392 }
2393 else
2394 {
2395 /* Otherwise we can't allow this privilege elevation */
2396 Status = STATUS_ACCESS_DENIED;
2397 }
2398 }
2399 else
2400 {
2401 /* We don't need an access state */
2402 Status = STATUS_SUCCESS;
2403 }
2404
2405 /* Make sure the access state was created OK */
2406 if (NT_SUCCESS(Status))
2407 {
2408 /* Add a new handle */
2409 Status = ObpIncrementHandleCount(SourceObject,
2410 PassedAccessState,
2411 PreviousMode,
2412 HandleAttributes,
2413 PsGetCurrentProcess(),
2414 ObDuplicateHandle);
2415 }
2416
2417 /* Check if we were attached */
2418 if (AttachedToProcess)
2419 {
2420 /* We can safely detach now */
2421 KeUnstackDetachProcess(&ApcState);
2422 AttachedToProcess = FALSE;
2423 }
2424
2425 /* Check if we have to close the source handle */
2426 if (Options & DUPLICATE_CLOSE_SOURCE)
2427 {
2428 /* Attach and close */
2429 KeStackAttachProcess(&SourceProcess->Pcb, &ApcState);
2430 NtClose(SourceHandle);
2431 KeUnstackDetachProcess(&ApcState);
2432 }
2433
2434 /* Check if we had an access state */
2435 if (PassedAccessState) SeDeleteAccessState(PassedAccessState);
2436
2437 /* Now check if incrementing actually failed */
2438 if (!NT_SUCCESS(Status))
2439 {
2440 /* Dereference handle tables */
2441 ObDereferenceProcessHandleTable(SourceProcess);
2442 ObDereferenceProcessHandleTable(TargetProcess);
2443
2444 /* Dereference the source object */
2445 ObDereferenceObject(SourceObject);
2446 return Status;
2447 }
2448
2449 if (NewHandleEntry.ObAttributes & OBJ_PROTECT_CLOSE)
2450 {
2451 NewHandleEntry.ObAttributes &= ~OBJ_PROTECT_CLOSE;
2452 NewHandleEntry.GrantedAccess |= ObpAccessProtectCloseBit;
2453 }
2454
2455 /* Now create the handle */
2456 NewHandle = ExCreateHandle(HandleTable, &NewHandleEntry);
2457 if (!NewHandle)
2458 {
2459 /* Undo the increment */
2460 ObpDecrementHandleCount(SourceObject,
2461 TargetProcess,
2462 TargetAccess,
2463 ObjectType);
2464
2465 /* Deference the object and set failure status */
2466 ObDereferenceObject(SourceObject);
2467 Status = STATUS_INSUFFICIENT_RESOURCES;
2468 }
2469
2470 /* Mark it as a kernel handle if requested */
2471 if (KernelHandle)
2472 {
2473 NewHandle = ObMarkHandleAsKernelHandle(NewHandle);
2474 }
2475
2476 /* Return the handle */
2477 if (TargetHandle) *TargetHandle = NewHandle;
2478
2479 /* Dereference handle tables */
2480 ObDereferenceProcessHandleTable(SourceProcess);
2481 ObDereferenceProcessHandleTable(TargetProcess);
2482
2483 /* Return status */
2484 OBTRACE(OB_HANDLE_DEBUG,
2485 "%s - Duplicated handle: %p for %p into %p. Source: %p HC PC %lx %lx\n",
2486 __FUNCTION__,
2487 NewHandle,
2488 SourceProcess,
2489 TargetProcess,
2490 SourceObject,
2491 ObjectHeader->PointerCount,
2492 ObjectHeader->HandleCount);
2493 return Status;
2494 }
2495
2496 /* PUBLIC FUNCTIONS *********************************************************/
2497
2498 /*++
2499 * @name ObOpenObjectByName
2500 * @implemented NT4
2501 *
2502 * The ObOpenObjectByName routine <FILLMEIN>
2503 *
2504 * @param ObjectAttributes
2505 * <FILLMEIN>.
2506 *
2507 * @param ObjectType
2508 * <FILLMEIN>.
2509 *
2510 * @param AccessMode
2511 * <FILLMEIN>.
2512 *
2513 * @param PassedAccessState
2514 * <FILLMEIN>.
2515 *
2516 * @param DesiredAccess
2517 * <FILLMEIN>.
2518 *
2519 * @param ParseContext
2520 * <FILLMEIN>.
2521 *
2522 * @param Handle
2523 * <FILLMEIN>.
2524 *
2525 * @return <FILLMEIN>.
2526 *
2527 * @remarks None.
2528 *
2529 *--*/
2530 NTSTATUS
2531 NTAPI
ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,IN POBJECT_TYPE ObjectType,IN KPROCESSOR_MODE AccessMode,IN PACCESS_STATE PassedAccessState,IN ACCESS_MASK DesiredAccess,IN OUT PVOID ParseContext,OUT PHANDLE Handle)2532 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
2533 IN POBJECT_TYPE ObjectType,
2534 IN KPROCESSOR_MODE AccessMode,
2535 IN PACCESS_STATE PassedAccessState,
2536 IN ACCESS_MASK DesiredAccess,
2537 IN OUT PVOID ParseContext,
2538 OUT PHANDLE Handle)
2539 {
2540 PVOID Object = NULL;
2541 UNICODE_STRING ObjectName;
2542 NTSTATUS Status, Status2;
2543 POBJECT_HEADER ObjectHeader;
2544 PGENERIC_MAPPING GenericMapping = NULL;
2545 OB_OPEN_REASON OpenReason;
2546 POB_TEMP_BUFFER TempBuffer;
2547 PAGED_CODE();
2548
2549 /* Assume failure */
2550 *Handle = NULL;
2551
2552 /* Check if we didn't get any Object Attributes */
2553 if (!ObjectAttributes)
2554 {
2555 /* Fail with special status code */
2556 return STATUS_INVALID_PARAMETER;
2557 }
2558
2559 /* Allocate the temporary buffer */
2560 TempBuffer = ExAllocatePoolWithTag(NonPagedPool,
2561 sizeof(OB_TEMP_BUFFER),
2562 TAG_OB_TEMP_STORAGE);
2563 if (!TempBuffer) return STATUS_INSUFFICIENT_RESOURCES;
2564
2565 /* Capture all the info */
2566 Status = ObpCaptureObjectCreateInformation(ObjectAttributes,
2567 AccessMode,
2568 AccessMode,
2569 TRUE,
2570 &TempBuffer->ObjectCreateInfo,
2571 &ObjectName);
2572 if (!NT_SUCCESS(Status))
2573 {
2574 /* Fail */
2575 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE);
2576 return Status;
2577 }
2578
2579 /* Check if we didn't get an access state */
2580 if (!PassedAccessState)
2581 {
2582 /* Try to get the generic mapping if we can */
2583 if (ObjectType) GenericMapping = &ObjectType->TypeInfo.GenericMapping;
2584
2585 /* Use our built-in access state */
2586 PassedAccessState = &TempBuffer->LocalAccessState;
2587 Status = SeCreateAccessState(&TempBuffer->LocalAccessState,
2588 &TempBuffer->AuxData,
2589 DesiredAccess,
2590 GenericMapping);
2591 if (!NT_SUCCESS(Status)) goto Quickie;
2592 }
2593
2594 /* Get the security descriptor */
2595 if (TempBuffer->ObjectCreateInfo.SecurityDescriptor)
2596 {
2597 /* Save it in the access state */
2598 PassedAccessState->SecurityDescriptor =
2599 TempBuffer->ObjectCreateInfo.SecurityDescriptor;
2600 }
2601
2602 /* Validate the access mask */
2603 Status = ObpValidateAccessMask(PassedAccessState);
2604 if (!NT_SUCCESS(Status))
2605 {
2606 /* Cleanup after lookup */
2607 ObpReleaseLookupContext(&TempBuffer->LookupContext);
2608 goto Cleanup;
2609 }
2610
2611 /* Now do the lookup */
2612 Status = ObpLookupObjectName(TempBuffer->ObjectCreateInfo.RootDirectory,
2613 &ObjectName,
2614 TempBuffer->ObjectCreateInfo.Attributes,
2615 ObjectType,
2616 AccessMode,
2617 ParseContext,
2618 TempBuffer->ObjectCreateInfo.SecurityQos,
2619 NULL,
2620 PassedAccessState,
2621 &TempBuffer->LookupContext,
2622 &Object);
2623 if (!NT_SUCCESS(Status))
2624 {
2625 /* Cleanup after lookup */
2626 ObpReleaseLookupContext(&TempBuffer->LookupContext);
2627 goto Cleanup;
2628 }
2629
2630 /* Check if this object has create information */
2631 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
2632 if (ObjectHeader->Flags & OB_FLAG_CREATE_INFO)
2633 {
2634 /* Then we are creating a new handle */
2635 OpenReason = ObCreateHandle;
2636
2637 /* Check if we still have create info */
2638 if (ObjectHeader->ObjectCreateInfo)
2639 {
2640 /* Free it */
2641 ObpFreeObjectCreateInformation(ObjectHeader->
2642 ObjectCreateInfo);
2643 ObjectHeader->ObjectCreateInfo = NULL;
2644 }
2645 }
2646 else
2647 {
2648 /* Otherwise, we are merely opening it */
2649 OpenReason = ObOpenHandle;
2650 }
2651
2652 /* Check if we have invalid object attributes */
2653 if (ObjectHeader->Type->TypeInfo.InvalidAttributes &
2654 TempBuffer->ObjectCreateInfo.Attributes)
2655 {
2656 /* Set failure code */
2657 Status = STATUS_INVALID_PARAMETER;
2658
2659 /* Cleanup after lookup */
2660 ObpReleaseLookupContext(&TempBuffer->LookupContext);
2661
2662 /* Dereference the object */
2663 ObDereferenceObject(Object);
2664 }
2665 else
2666 {
2667 /* Create the actual handle now */
2668 Status2 = ObpCreateHandle(OpenReason,
2669 Object,
2670 ObjectType,
2671 PassedAccessState,
2672 0,
2673 TempBuffer->ObjectCreateInfo.Attributes,
2674 &TempBuffer->LookupContext,
2675 AccessMode,
2676 NULL,
2677 Handle);
2678 if (!NT_SUCCESS(Status2))
2679 {
2680 ObDereferenceObject(Object);
2681 Status = Status2;
2682 }
2683 }
2684
2685 Cleanup:
2686 /* Delete the access state */
2687 if (PassedAccessState == &TempBuffer->LocalAccessState)
2688 {
2689 SeDeleteAccessState(PassedAccessState);
2690 }
2691
2692 Quickie:
2693 /* Release the object attributes and temporary buffer */
2694 ObpReleaseObjectCreateInformation(&TempBuffer->ObjectCreateInfo);
2695 if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
2696 ExFreePoolWithTag(TempBuffer, TAG_OB_TEMP_STORAGE);
2697
2698 /* Return status */
2699 OBTRACE(OB_HANDLE_DEBUG,
2700 "%s - returning Object %p with PC S: %lx %lx\n",
2701 __FUNCTION__,
2702 Object,
2703 Object ? OBJECT_TO_OBJECT_HEADER(Object)->PointerCount : -1,
2704 Status);
2705 return Status;
2706 }
2707
2708 /*++
2709 * @name ObOpenObjectByPointer
2710 * @implemented NT4
2711 *
2712 * The ObOpenObjectByPointer routine <FILLMEIN>
2713 *
2714 * @param Object
2715 * <FILLMEIN>.
2716 *
2717 * @param HandleAttributes
2718 * <FILLMEIN>.
2719 *
2720 * @param PassedAccessState
2721 * <FILLMEIN>.
2722 *
2723 * @param DesiredAccess
2724 * <FILLMEIN>.
2725 *
2726 * @param ObjectType
2727 * <FILLMEIN>.
2728 *
2729 * @param AccessMode
2730 * <FILLMEIN>.
2731 *
2732 * @param Handle
2733 * <FILLMEIN>.
2734 *
2735 * @return <FILLMEIN>.
2736 *
2737 * @remarks None.
2738 *
2739 *--*/
2740 NTSTATUS
2741 NTAPI
ObOpenObjectByPointer(IN PVOID Object,IN ULONG HandleAttributes,IN PACCESS_STATE PassedAccessState,IN ACCESS_MASK DesiredAccess,IN POBJECT_TYPE ObjectType,IN KPROCESSOR_MODE AccessMode,OUT PHANDLE Handle)2742 ObOpenObjectByPointer(IN PVOID Object,
2743 IN ULONG HandleAttributes,
2744 IN PACCESS_STATE PassedAccessState,
2745 IN ACCESS_MASK DesiredAccess,
2746 IN POBJECT_TYPE ObjectType,
2747 IN KPROCESSOR_MODE AccessMode,
2748 OUT PHANDLE Handle)
2749 {
2750 POBJECT_HEADER Header;
2751 NTSTATUS Status;
2752 ACCESS_STATE AccessState;
2753 AUX_ACCESS_DATA AuxData;
2754 PAGED_CODE();
2755
2756 /* Assume failure */
2757 *Handle = NULL;
2758
2759 /* Reference the object */
2760 Status = ObReferenceObjectByPointer(Object,
2761 0,
2762 ObjectType,
2763 AccessMode);
2764 if (!NT_SUCCESS(Status)) return Status;
2765
2766 /* Get the Header Info */
2767 Header = OBJECT_TO_OBJECT_HEADER(Object);
2768
2769 /* Check if we didn't get an access state */
2770 if (!PassedAccessState)
2771 {
2772 /* Use our built-in access state */
2773 PassedAccessState = &AccessState;
2774 Status = SeCreateAccessState(&AccessState,
2775 &AuxData,
2776 DesiredAccess,
2777 &Header->Type->TypeInfo.GenericMapping);
2778 if (!NT_SUCCESS(Status))
2779 {
2780 /* Fail */
2781 ObDereferenceObject(Object);
2782 return Status;
2783 }
2784 }
2785
2786 /* Check if we have invalid object attributes */
2787 if (Header->Type->TypeInfo.InvalidAttributes & HandleAttributes)
2788 {
2789 /* Delete the access state */
2790 if (PassedAccessState == &AccessState)
2791 {
2792 SeDeleteAccessState(PassedAccessState);
2793 }
2794
2795 /* Dereference the object */
2796 ObDereferenceObject(Object);
2797 return STATUS_INVALID_PARAMETER;
2798 }
2799
2800 /* Create the handle */
2801 Status = ObpCreateHandle(ObOpenHandle,
2802 Object,
2803 ObjectType,
2804 PassedAccessState,
2805 0,
2806 HandleAttributes,
2807 NULL,
2808 AccessMode,
2809 NULL,
2810 Handle);
2811 if (!NT_SUCCESS(Status)) ObDereferenceObject(Object);
2812
2813 /* Delete the access state */
2814 if (PassedAccessState == &AccessState)
2815 {
2816 SeDeleteAccessState(PassedAccessState);
2817 }
2818
2819 /* Return */
2820 OBTRACE(OB_HANDLE_DEBUG,
2821 "%s - returning Object with PC S: %lx %lx\n",
2822 __FUNCTION__,
2823 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
2824 Status);
2825 return Status;
2826 }
2827
2828 /*++
2829 * @name ObFindHandleForObject
2830 * @implemented NT4
2831 *
2832 * The ObFindHandleForObject routine <FILLMEIN>
2833 *
2834 * @param Process
2835 * <FILLMEIN>.
2836 *
2837 * @param Object
2838 * <FILLMEIN>.
2839 *
2840 * @param ObjectType
2841 * <FILLMEIN>.
2842 *
2843 * @param HandleInformation
2844 * <FILLMEIN>.
2845 *
2846 * @param HandleReturn
2847 * <FILLMEIN>.
2848 *
2849 * @return <FILLMEIN>.
2850 *
2851 * @remarks None.
2852 *
2853 *--*/
2854 BOOLEAN
2855 NTAPI
ObFindHandleForObject(IN PEPROCESS Process,IN PVOID Object,IN POBJECT_TYPE ObjectType,IN POBJECT_HANDLE_INFORMATION HandleInformation,OUT PHANDLE Handle)2856 ObFindHandleForObject(IN PEPROCESS Process,
2857 IN PVOID Object,
2858 IN POBJECT_TYPE ObjectType,
2859 IN POBJECT_HANDLE_INFORMATION HandleInformation,
2860 OUT PHANDLE Handle)
2861 {
2862 OBP_FIND_HANDLE_DATA FindData;
2863 BOOLEAN Result = FALSE;
2864 PVOID ObjectTable;
2865
2866 /* Make sure we have an object table */
2867 ObjectTable = ObReferenceProcessHandleTable(Process);
2868 if (ObjectTable)
2869 {
2870 /* Check if we have an object */
2871 if (Object)
2872 {
2873 /* Set its header */
2874 FindData.ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
2875 }
2876 else
2877 {
2878 /* Otherwise, no object to match*/
2879 FindData.ObjectHeader = NULL;
2880 }
2881
2882 /* Set other information */
2883 FindData.ObjectType = ObjectType;
2884 FindData.HandleInformation = HandleInformation;
2885
2886 /* Enumerate the handle table */
2887 if (ExEnumHandleTable(Process->ObjectTable,
2888 ObpEnumFindHandleProcedure,
2889 &FindData,
2890 Handle))
2891 {
2892 /* Set success */
2893 Result = TRUE;
2894 }
2895
2896 /* Let go of the table */
2897 ObDereferenceProcessHandleTable(Process);
2898 }
2899
2900 /* Return the result */
2901 return Result;
2902 }
2903
2904 /*++
2905 * @name ObInsertObject
2906 * @implemented NT4
2907 *
2908 * The ObInsertObject routine <FILLMEIN>
2909 *
2910 * @param Object
2911 * <FILLMEIN>.
2912 *
2913 * @param PassedAccessState
2914 * <FILLMEIN>.
2915 *
2916 * @param DesiredAccess
2917 * <FILLMEIN>.
2918 *
2919 * @param AdditionalReferences
2920 * <FILLMEIN>.
2921 *
2922 * @param ReferencedObject
2923 * <FILLMEIN>.
2924 *
2925 * @param Handle
2926 * <FILLMEIN>.
2927 *
2928 * @return <FILLMEIN>.
2929 *
2930 * @remarks None.
2931 *
2932 *--*/
2933 NTSTATUS
2934 NTAPI
ObInsertObject(IN PVOID Object,IN PACCESS_STATE AccessState OPTIONAL,IN ACCESS_MASK DesiredAccess,IN ULONG ObjectPointerBias,OUT PVOID * NewObject OPTIONAL,OUT PHANDLE Handle)2935 ObInsertObject(IN PVOID Object,
2936 IN PACCESS_STATE AccessState OPTIONAL,
2937 IN ACCESS_MASK DesiredAccess,
2938 IN ULONG ObjectPointerBias,
2939 OUT PVOID *NewObject OPTIONAL,
2940 OUT PHANDLE Handle)
2941 {
2942 POBJECT_CREATE_INFORMATION ObjectCreateInfo;
2943 POBJECT_HEADER ObjectHeader;
2944 POBJECT_TYPE ObjectType;
2945 PUNICODE_STRING ObjectName;
2946 PVOID InsertObject;
2947 PSECURITY_DESCRIPTOR ParentDescriptor = NULL;
2948 BOOLEAN SdAllocated = FALSE;
2949 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
2950 OBP_LOOKUP_CONTEXT Context;
2951 ACCESS_STATE LocalAccessState;
2952 AUX_ACCESS_DATA AuxData;
2953 OB_OPEN_REASON OpenReason;
2954 KPROCESSOR_MODE PreviousMode;
2955 NTSTATUS Status = STATUS_SUCCESS, RealStatus;
2956 BOOLEAN IsNewObject;
2957 PAGED_CODE();
2958
2959 /* Get the Header */
2960 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
2961
2962 /* Detect invalid insert */
2963 if (!(ObjectHeader->Flags & OB_FLAG_CREATE_INFO))
2964 {
2965 /* Display warning and break into debugger */
2966 DPRINT1("OB: Attempting to insert existing object %p\n", Object);
2967 DbgBreakPoint();
2968
2969 /* Allow debugger to continue */
2970 ObDereferenceObject(Object);
2971 return STATUS_INVALID_PARAMETER;
2972 }
2973
2974 /* Get the create and name info, as well as the object type */
2975 ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
2976 ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
2977 ObjectType = ObjectHeader->Type;
2978 ObjectName = NULL;
2979
2980 /* Check if this is an named object */
2981 if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
2982 {
2983 /* Get the object name */
2984 ObjectName = &ObjectNameInfo->Name;
2985 }
2986
2987 /* Sanity check */
2988 ASSERT((Handle) ||
2989 ((ObjectPointerBias == 0) &&
2990 (ObjectName == NULL) &&
2991 (ObjectType->TypeInfo.SecurityRequired) &&
2992 (NewObject == NULL)));
2993
2994 /* Check if the object is unnamed and also doesn't have security */
2995 PreviousMode = KeGetPreviousMode();
2996 if (!(ObjectType->TypeInfo.SecurityRequired) && !(ObjectName))
2997 {
2998 /* Assume failure */
2999 *Handle = NULL;
3000 ObjectHeader->ObjectCreateInfo = NULL;
3001
3002 /* Create the handle */
3003 Status = ObpCreateUnnamedHandle(Object,
3004 DesiredAccess,
3005 ObjectPointerBias + 1,
3006 ObjectCreateInfo->Attributes,
3007 PreviousMode,
3008 NewObject,
3009 Handle);
3010
3011 /* Free the create information */
3012 ObpFreeObjectCreateInformation(ObjectCreateInfo);
3013
3014 /* Release the object name information */
3015 ObpDereferenceNameInfo(ObjectNameInfo);
3016
3017 /* Remove the extra keep-alive reference */
3018 ObDereferenceObject(Object);
3019
3020 /* Return */
3021 OBTRACE(OB_HANDLE_DEBUG,
3022 "%s - returning Object with PC S: %lx %lx\n",
3023 __FUNCTION__,
3024 ObjectHeader->PointerCount,
3025 Status);
3026 return Status;
3027 }
3028
3029 /* Check if we didn't get an access state */
3030 if (!AccessState)
3031 {
3032 /* Use our built-in access state */
3033 AccessState = &LocalAccessState;
3034 Status = SeCreateAccessState(&LocalAccessState,
3035 &AuxData,
3036 DesiredAccess,
3037 &ObjectType->TypeInfo.GenericMapping);
3038 if (!NT_SUCCESS(Status))
3039 {
3040 /* Fail */
3041 ObpDereferenceNameInfo(ObjectNameInfo);
3042 ObDereferenceObject(Object);
3043 return Status;
3044 }
3045 }
3046
3047 /* Save the security descriptor */
3048 AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor;
3049
3050 /* Validate the access mask */
3051 Status = ObpValidateAccessMask(AccessState);
3052 if (!NT_SUCCESS(Status))
3053 {
3054 /* Fail */
3055 ObpDereferenceNameInfo(ObjectNameInfo);
3056 ObDereferenceObject(Object);
3057 return Status;
3058 }
3059
3060 /* Setup a lookup context */
3061 ObpInitializeLookupContext(&Context);
3062 InsertObject = Object;
3063 OpenReason = ObCreateHandle;
3064
3065 /* Check if the object is named */
3066 if (ObjectName)
3067 {
3068 /* Look it up */
3069 Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory,
3070 ObjectName,
3071 ObjectCreateInfo->Attributes,
3072 ObjectType,
3073 (ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) ?
3074 KernelMode : UserMode,
3075 ObjectCreateInfo->ParseContext,
3076 ObjectCreateInfo->SecurityQos,
3077 Object,
3078 AccessState,
3079 &Context,
3080 &InsertObject);
3081
3082 /* Check if we found an object that doesn't match the one requested */
3083 if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject))
3084 {
3085 /* This means we're opening an object, not creating a new one */
3086 OpenReason = ObOpenHandle;
3087
3088 /* Make sure the caller said it's OK to do this */
3089 if (ObjectCreateInfo->Attributes & OBJ_OPENIF)
3090 {
3091 /* He did, but did he want this type? */
3092 if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type)
3093 {
3094 /* Wrong type, so fail */
3095 Status = STATUS_OBJECT_TYPE_MISMATCH;
3096 }
3097 else
3098 {
3099 /* Right type, so warn */
3100 Status = STATUS_OBJECT_NAME_EXISTS;
3101 }
3102 }
3103 else
3104 {
3105 /* Check if this was a symbolic link */
3106 if (OBJECT_TO_OBJECT_HEADER(InsertObject)->Type ==
3107 ObpSymbolicLinkObjectType)
3108 {
3109 /* Dereference it */
3110 ObDereferenceObject(InsertObject);
3111 }
3112
3113 /* Caller wanted to create a new object, fail */
3114 Status = STATUS_OBJECT_NAME_COLLISION;
3115 }
3116 }
3117
3118 /* Check if anything until now failed */
3119 if (!NT_SUCCESS(Status))
3120 {
3121 /* Cleanup after lookup */
3122 ObpReleaseLookupContext(&Context);
3123
3124 /* Remove query reference that we added */
3125 ObpDereferenceNameInfo(ObjectNameInfo);
3126
3127 /* Dereference the object and delete the access state */
3128 ObDereferenceObject(Object);
3129 if (AccessState == &LocalAccessState)
3130 {
3131 /* We used a local one; delete it */
3132 SeDeleteAccessState(AccessState);
3133 }
3134
3135 /* Return failure code */
3136 return Status;
3137 }
3138 else
3139 {
3140 /* Check if this is a symbolic link */
3141 if (ObjectType == ObpSymbolicLinkObjectType)
3142 {
3143 /* Create the internal name */
3144 ObpCreateSymbolicLinkName(Object);
3145 }
3146 }
3147 }
3148
3149 /* Now check if this object is being created */
3150 if (InsertObject == Object)
3151 {
3152 /* Check if it's named or forces security */
3153 if ((ObjectName) || (ObjectType->TypeInfo.SecurityRequired))
3154 {
3155 /* Make sure it's inserted into an object directory */
3156 if ((ObjectNameInfo) && (ObjectNameInfo->Directory))
3157 {
3158 /* Get the current descriptor */
3159 ObGetObjectSecurity(ObjectNameInfo->Directory,
3160 &ParentDescriptor,
3161 &SdAllocated);
3162 }
3163
3164 /* Now assign it */
3165 Status = ObAssignSecurity(AccessState,
3166 ParentDescriptor,
3167 Object,
3168 ObjectType);
3169
3170 /* Check if we captured one */
3171 if (ParentDescriptor)
3172 {
3173 /* We did, release it */
3174 ObReleaseObjectSecurity(ParentDescriptor, SdAllocated);
3175 }
3176 else if (NT_SUCCESS(Status))
3177 {
3178 /* Other we didn't, but we were able to use the current SD */
3179 SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor,
3180 ObjectCreateInfo->ProbeMode,
3181 TRUE);
3182
3183 /* Clear the current one */
3184 AccessState->SecurityDescriptor =
3185 ObjectCreateInfo->SecurityDescriptor = NULL;
3186 }
3187 }
3188
3189 /* Check if anything until now failed */
3190 if (!NT_SUCCESS(Status))
3191 {
3192 /* Check if the directory was added */
3193 if (Context.DirectoryLocked)
3194 {
3195 /* Weird case where we need to do a manual delete */
3196 DPRINT1("Unhandled path\n");
3197 ASSERT(FALSE);
3198 }
3199
3200 /* Cleanup the lookup */
3201 ObpReleaseLookupContext(&Context);
3202
3203 /* Remove query reference that we added */
3204 ObpDereferenceNameInfo(ObjectNameInfo);
3205
3206 /* Dereference the object and delete the access state */
3207 ObDereferenceObject(Object);
3208 if (AccessState == &LocalAccessState)
3209 {
3210 /* We used a local one; delete it */
3211 SeDeleteAccessState(AccessState);
3212 }
3213
3214 /* Return failure code */
3215 ASSERT(FALSE);
3216 return Status;
3217 }
3218 }
3219
3220 /* Save the actual status until here */
3221 RealStatus = Status;
3222
3223 /* Check if caller wants us to create a handle */
3224 ObjectHeader->ObjectCreateInfo = NULL;
3225 if (Handle)
3226 {
3227 /* Create the handle */
3228 Status = ObpCreateHandle(OpenReason,
3229 InsertObject,
3230 NULL,
3231 AccessState,
3232 ObjectPointerBias + 1,
3233 ObjectCreateInfo->Attributes,
3234 &Context,
3235 PreviousMode,
3236 NewObject,
3237 Handle);
3238 if (!NT_SUCCESS(Status))
3239 {
3240 /* If the object had a name, backout everything */
3241 if (ObjectName) ObpDeleteNameCheck(Object);
3242
3243 /* Return the status of the failure */
3244 *Handle = NULL;
3245 RealStatus = Status;
3246 }
3247
3248 /* Remove a query reference */
3249 ObpDereferenceNameInfo(ObjectNameInfo);
3250
3251 /* Remove the extra keep-alive reference */
3252 ObDereferenceObject(Object);
3253 }
3254 else
3255 {
3256 /* Otherwise, lock the object */
3257 ObpAcquireObjectLock(ObjectHeader);
3258
3259 /* And charge quota for the process to make it appear as used */
3260 RealStatus = ObpChargeQuotaForObject(ObjectHeader,
3261 ObjectType,
3262 &IsNewObject);
3263
3264 /* Release the lock */
3265 ObpReleaseObjectLock(ObjectHeader);
3266
3267 /* Check if we failed and dereference the object if so */
3268 if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object);
3269 }
3270
3271 /* We can delete the Create Info now */
3272 ObpFreeObjectCreateInformation(ObjectCreateInfo);
3273
3274 /* Check if we created our own access state and delete it if so */
3275 if (AccessState == &LocalAccessState) SeDeleteAccessState(AccessState);
3276
3277 /* Return status code */
3278 OBTRACE(OB_HANDLE_DEBUG,
3279 "%s - returning Object with PC RS/S: %lx %lx %lx\n",
3280 __FUNCTION__,
3281 OBJECT_TO_OBJECT_HEADER(Object)->PointerCount,
3282 RealStatus, Status);
3283 return RealStatus;
3284 }
3285
3286 /*++
3287 * @name ObSetHandleAttributes
3288 * @implemented NT5.1
3289 *
3290 * The ObSetHandleAttributes routine <FILLMEIN>
3291 *
3292 * @param Handle
3293 * <FILLMEIN>.
3294 *
3295 * @param HandleFlags
3296 * <FILLMEIN>.
3297 *
3298 * @param PreviousMode
3299 * <FILLMEIN>.
3300 *
3301 * @return <FILLMEIN>.
3302 *
3303 * @remarks None.
3304 *
3305 *--*/
3306 NTSTATUS
3307 NTAPI
ObSetHandleAttributes(IN HANDLE Handle,IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags,IN KPROCESSOR_MODE PreviousMode)3308 ObSetHandleAttributes(IN HANDLE Handle,
3309 IN POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags,
3310 IN KPROCESSOR_MODE PreviousMode)
3311 {
3312 OBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleAttributesContext;
3313 BOOLEAN Result, AttachedToSystemProcess = FALSE;
3314 PHANDLE_TABLE HandleTable;
3315 KAPC_STATE ApcState;
3316 PAGED_CODE();
3317
3318 /* Check if this is a kernel handle */
3319 if (ObpIsKernelHandle(Handle, PreviousMode))
3320 {
3321 /* Use the kernel table and convert the handle */
3322 HandleTable = ObpKernelHandleTable;
3323 Handle = ObKernelHandleToHandle(Handle);
3324
3325 /* Check if we're not in the system process */
3326 if (PsGetCurrentProcess() != PsInitialSystemProcess)
3327 {
3328 /* Attach to the system process */
3329 KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
3330 AttachedToSystemProcess = TRUE;
3331 }
3332 }
3333 else
3334 {
3335 /* Get the current process' handle table */
3336 HandleTable = PsGetCurrentProcess()->ObjectTable;
3337 }
3338
3339 /* Initialize the handle attribute context */
3340 SetHandleAttributesContext.PreviousMode = PreviousMode;
3341 SetHandleAttributesContext.Information = *HandleFlags;
3342
3343 /* Invoke the ObpSetHandleAttributes callback */
3344 Result = ExChangeHandle(HandleTable,
3345 Handle,
3346 ObpSetHandleAttributes,
3347 (ULONG_PTR)&SetHandleAttributesContext);
3348
3349 /* Did we attach to the system process? */
3350 if (AttachedToSystemProcess)
3351 {
3352 /* Detach from it */
3353 KeUnstackDetachProcess(&ApcState);
3354 }
3355
3356 /* Return the result as an NTSTATUS value */
3357 return Result ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
3358 }
3359
3360 /*++
3361 * @name ObCloseHandle
3362 * @implemented NT5.1
3363 *
3364 * The ObCloseHandle routine <FILLMEIN>
3365 *
3366 * @param Handle
3367 * <FILLMEIN>.
3368 *
3369 * @param AccessMode
3370 * <FILLMEIN>.
3371 *
3372 * @return <FILLMEIN>.
3373 *
3374 * @remarks None.
3375 *
3376 *--*/
3377 NTSTATUS
3378 NTAPI
ObCloseHandle(IN HANDLE Handle,IN KPROCESSOR_MODE AccessMode)3379 ObCloseHandle(IN HANDLE Handle,
3380 IN KPROCESSOR_MODE AccessMode)
3381 {
3382 /* Call the internal API */
3383 return ObpCloseHandle(Handle, AccessMode);
3384 }
3385
3386 /*++
3387 * @name NtClose
3388 * @implemented NT4
3389 *
3390 * The NtClose routine <FILLMEIN>
3391 *
3392 * @param Handle
3393 * <FILLMEIN>.
3394 *
3395 * @return <FILLMEIN>.
3396 *
3397 * @remarks None.
3398 *
3399 *--*/
3400 NTSTATUS
3401 NTAPI
NtClose(IN HANDLE Handle)3402 NtClose(IN HANDLE Handle)
3403 {
3404 /* Call the internal API */
3405 return ObpCloseHandle(Handle, ExGetPreviousMode());
3406 }
3407
3408 NTSTATUS
3409 NTAPI
NtDuplicateObject(IN HANDLE SourceProcessHandle,IN HANDLE SourceHandle,IN HANDLE TargetProcessHandle OPTIONAL,OUT PHANDLE TargetHandle OPTIONAL,IN ACCESS_MASK DesiredAccess,IN ULONG HandleAttributes,IN ULONG Options)3410 NtDuplicateObject(IN HANDLE SourceProcessHandle,
3411 IN HANDLE SourceHandle,
3412 IN HANDLE TargetProcessHandle OPTIONAL,
3413 OUT PHANDLE TargetHandle OPTIONAL,
3414 IN ACCESS_MASK DesiredAccess,
3415 IN ULONG HandleAttributes,
3416 IN ULONG Options)
3417 {
3418 PEPROCESS SourceProcess, TargetProcess, Target;
3419 HANDLE hTarget;
3420 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
3421 NTSTATUS Status;
3422 OBTRACE(OB_HANDLE_DEBUG,
3423 "%s - Duplicating handle: %p for %p into %p.\n",
3424 __FUNCTION__,
3425 SourceHandle,
3426 SourceProcessHandle,
3427 TargetProcessHandle);
3428
3429 /* Check if we have a target handle */
3430 if ((TargetHandle) && (PreviousMode != KernelMode))
3431 {
3432 /* Enter SEH */
3433 _SEH2_TRY
3434 {
3435 /* Probe the handle and assume failure */
3436 ProbeForWriteHandle(TargetHandle);
3437 *TargetHandle = NULL;
3438 }
3439 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3440 {
3441 /* Return the exception code */
3442 _SEH2_YIELD(return _SEH2_GetExceptionCode());
3443 }
3444 _SEH2_END;
3445 }
3446
3447 /* Now reference the input handle */
3448 Status = ObReferenceObjectByHandle(SourceProcessHandle,
3449 PROCESS_DUP_HANDLE,
3450 PsProcessType,
3451 PreviousMode,
3452 (PVOID*)&SourceProcess,
3453 NULL);
3454 if (!NT_SUCCESS(Status)) return Status;
3455
3456 /* Check if got a target handle */
3457 if (TargetProcessHandle)
3458 {
3459 /* Now reference the output handle */
3460 Status = ObReferenceObjectByHandle(TargetProcessHandle,
3461 PROCESS_DUP_HANDLE,
3462 PsProcessType,
3463 PreviousMode,
3464 (PVOID*)&TargetProcess,
3465 NULL);
3466 if (NT_SUCCESS(Status))
3467 {
3468 /* Use this target process */
3469 Target = TargetProcess;
3470 }
3471 else
3472 {
3473 /* No target process */
3474 Target = NULL;
3475 }
3476 }
3477 else
3478 {
3479 /* No target process */
3480 Status = STATUS_SUCCESS;
3481 Target = NULL;
3482 }
3483
3484 /* Call the internal routine */
3485 Status = ObDuplicateObject(SourceProcess,
3486 SourceHandle,
3487 Target,
3488 &hTarget,
3489 DesiredAccess,
3490 HandleAttributes,
3491 Options,
3492 PreviousMode);
3493
3494 /* Check if the caller wanted the return handle */
3495 if (TargetHandle)
3496 {
3497 /* Protect the write to user mode */
3498 _SEH2_TRY
3499 {
3500 /* Write the new handle */
3501 *TargetHandle = hTarget;
3502 }
3503 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3504 {
3505 /* Otherwise, get the exception code */
3506 Status = _SEH2_GetExceptionCode();
3507 }
3508 _SEH2_END;
3509 }
3510
3511 /* Dereference the processes */
3512 OBTRACE(OB_HANDLE_DEBUG,
3513 "%s - Duplicated handle: %p into %p S %lx\n",
3514 __FUNCTION__,
3515 hTarget,
3516 TargetProcessHandle,
3517 Status);
3518 if (Target) ObDereferenceObject(Target);
3519 ObDereferenceObject(SourceProcess);
3520 return Status;
3521 }
3522
3523 BOOLEAN
3524 NTAPI
ObIsKernelHandle(IN HANDLE Handle)3525 ObIsKernelHandle(IN HANDLE Handle)
3526 {
3527 /* Use the inlined version. We know we are in kernel mode. */
3528 return ObpIsKernelHandle(Handle, KernelMode);
3529 }
3530
3531 /* EOF */
3532