xref: /reactos/ntoskrnl/ob/obhandle.c (revision 156053ca)
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