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