Added two missing calls to KeLeaveCriticalRegion.
[reactos.git] / reactos / ntoskrnl / ob / handle.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/ob/handle.c
24 * PURPOSE: Managing handles
25 * PROGRAMMER: David Welch (welch@cwcom.net)
26 * REVISION HISTORY:
27 * 17/06/98: Created
28 */
29
30 /* INCLUDES ****************************************************************/
31
32 #include <ntoskrnl.h>
33 #define NDEBUG
34 #include <internal/debug.h>
35
36 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) & \
37 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
38 EX_HANDLE_ENTRY_AUDITONCLOSE)))
39 #define EX_HTE_TO_HDR(hte) ((POBJECT_HEADER)((ULONG_PTR)((hte)->u1.Object) & \
40 ~(EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | \
41 EX_HANDLE_ENTRY_AUDITONCLOSE)))
42
43 /* FUNCTIONS ***************************************************************/
44
45
46 VOID
47 ObpDecrementHandleCount(PVOID ObjectBody)
48 {
49 POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
50 LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
51
52 if ((ObjectHeader->ObjectType != NULL) &&
53 (ObjectHeader->ObjectType->Close != NULL))
54 {
55 /* the handle count should be decremented but we pass the previous value
56 to the callback */
57 ObjectHeader->ObjectType->Close(ObjectBody, NewHandleCount + 1);
58 }
59
60 if(NewHandleCount == 0)
61 {
62 ObDereferenceObject(ObjectBody);
63 }
64 }
65
66
67 NTSTATUS
68 ObpQueryHandleAttributes(HANDLE Handle,
69 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
70 {
71 PEPROCESS Process;
72 PHANDLE_TABLE_ENTRY HandleTableEntry;
73 LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
74
75 PAGED_CODE();
76
77 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
78
79 KeEnterCriticalRegion();
80
81 Process = PsGetCurrentProcess();
82
83 HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
84 ExHandle);
85 if (HandleTableEntry == NULL)
86 {
87 KeLeaveCriticalRegion();
88 return STATUS_INVALID_HANDLE;
89 }
90
91 HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
92 HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
93
94 ExUnlockHandleTableEntry(Process->ObjectTable,
95 HandleTableEntry);
96
97 KeLeaveCriticalRegion();
98
99 return STATUS_SUCCESS;
100 }
101
102
103 NTSTATUS
104 ObpSetHandleAttributes(HANDLE Handle,
105 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
106 {
107 PEPROCESS Process;
108 PHANDLE_TABLE_ENTRY HandleTableEntry;
109 LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
110
111 PAGED_CODE();
112
113 DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle);
114
115 Process = PsGetCurrentProcess();
116
117 KeEnterCriticalRegion();
118
119 HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
120 ExHandle);
121 if (HandleTableEntry == NULL)
122 {
123 KeLeaveCriticalRegion();
124 return STATUS_INVALID_HANDLE;
125 }
126
127 if (HandleInfo->Inherit)
128 HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
129 else
130 HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
131
132 if (HandleInfo->ProtectFromClose)
133 HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
134 else
135 HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
136
137 /* FIXME: Do we need to set anything in the object header??? */
138
139 ExUnlockHandleTableEntry(Process->ObjectTable,
140 HandleTableEntry);
141
142 KeLeaveCriticalRegion();
143
144 return STATUS_SUCCESS;
145 }
146
147
148 NTSTATUS
149 ObDuplicateObject(PEPROCESS SourceProcess,
150 PEPROCESS TargetProcess,
151 HANDLE SourceHandle,
152 PHANDLE TargetHandle,
153 ACCESS_MASK DesiredAccess,
154 BOOLEAN InheritHandle,
155 ULONG Options)
156 {
157 PHANDLE_TABLE_ENTRY SourceHandleEntry;
158 HANDLE_TABLE_ENTRY NewHandleEntry;
159 PVOID ObjectBody;
160 POBJECT_HEADER ObjectHeader;
161 LONG ExTargetHandle;
162 LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle);
163
164 PAGED_CODE();
165
166 KeEnterCriticalRegion();
167
168 SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
169 ExSourceHandle);
170 if (SourceHandleEntry == NULL)
171 {
172 KeLeaveCriticalRegion();
173 return STATUS_INVALID_HANDLE;
174 }
175
176 ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
177 ObjectBody = HEADER_TO_BODY(ObjectHeader);
178
179 NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object;
180 if(InheritHandle)
181 NewHandleEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
182 else
183 NewHandleEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
184 NewHandleEntry.u2.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
185 SourceHandleEntry->u2.GrantedAccess :
186 DesiredAccess);
187
188 /* reference the object so it doesn't get deleted after releasing the lock
189 and before creating a new handle for it */
190 ObReferenceObject(ObjectBody);
191
192 /* increment the handle count of the object, it should always be >= 2 because
193 we're holding a handle lock to this object! if the new handle count was
194 1 here, we're in big trouble... it would've been safe to increment and
195 check the handle count without using interlocked functions because the
196 entry is locked, which means the handle count can't change. */
197 InterlockedIncrement(&ObjectHeader->HandleCount);
198 ASSERT(ObjectHeader->HandleCount >= 2);
199
200 ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
201 SourceHandleEntry);
202
203 KeLeaveCriticalRegion();
204
205 /* attempt to create the new handle */
206 ExTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
207 &NewHandleEntry);
208 if (ExTargetHandle != EX_INVALID_HANDLE)
209 {
210 if (Options & DUPLICATE_CLOSE_SOURCE)
211 {
212 ObDeleteHandle(SourceProcess,
213 SourceHandle);
214 }
215
216 ObDereferenceObject(ObjectBody);
217
218 *TargetHandle = EX_HANDLE_TO_HANDLE(ExTargetHandle);
219
220 return STATUS_SUCCESS;
221 }
222 else
223 {
224 /* decrement the handle count we previously incremented, but don't call the
225 closing procedure because we're not closing a handle! */
226 if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0)
227 {
228 ObDereferenceObject(ObjectBody);
229 }
230
231 ObDereferenceObject(ObjectBody);
232 return STATUS_UNSUCCESSFUL;
233 }
234 }
235
236 /*
237 * @implemented
238 */
239 NTSTATUS STDCALL
240 NtDuplicateObject (IN HANDLE SourceProcessHandle,
241 IN HANDLE SourceHandle,
242 IN HANDLE TargetProcessHandle,
243 OUT PHANDLE TargetHandle,
244 IN ACCESS_MASK DesiredAccess,
245 IN BOOLEAN InheritHandle,
246 ULONG Options)
247 /*
248 * FUNCTION: Copies a handle from one process space to another
249 * ARGUMENTS:
250 * SourceProcessHandle = The source process owning the handle. The
251 * source process should have opened
252 * the SourceHandle with PROCESS_DUP_HANDLE
253 * access.
254 * SourceHandle = The handle to the object.
255 * TargetProcessHandle = The destination process owning the handle
256 * TargetHandle (OUT) = Caller should supply storage for the
257 * duplicated handle.
258 * DesiredAccess = The desired access to the handle.
259 * InheritHandle = Indicates wheter the new handle will be inheritable
260 * or not.
261 * Options = Specifies special actions upon duplicating the handle.
262 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
263 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
264 * that the source handle should be closed after duplicating.
265 * DUPLICATE_SAME_ACCESS specifies to ignore the
266 * DesiredAccess paramter and just grant the same access to
267 * the new handle.
268 * RETURNS: Status
269 * REMARKS: This function maps to the win32 DuplicateHandle.
270 */
271 {
272 PEPROCESS SourceProcess;
273 PEPROCESS TargetProcess;
274 HANDLE hTarget;
275 KPROCESSOR_MODE PreviousMode;
276 NTSTATUS Status = STATUS_SUCCESS;
277
278 PAGED_CODE();
279
280 PreviousMode = ExGetPreviousMode();
281
282 if(PreviousMode != KernelMode)
283 {
284 _SEH_TRY
285 {
286 ProbeForWrite(TargetHandle,
287 sizeof(HANDLE),
288 sizeof(ULONG));
289 }
290 _SEH_HANDLE
291 {
292 Status = _SEH_GetExceptionCode();
293 }
294 _SEH_END;
295
296 if(!NT_SUCCESS(Status))
297 {
298 return Status;
299 }
300 }
301
302 Status = ObReferenceObjectByHandle(SourceProcessHandle,
303 PROCESS_DUP_HANDLE,
304 NULL,
305 PreviousMode,
306 (PVOID*)&SourceProcess,
307 NULL);
308 if (!NT_SUCCESS(Status))
309 {
310 return(Status);
311 }
312
313 Status = ObReferenceObjectByHandle(TargetProcessHandle,
314 PROCESS_DUP_HANDLE,
315 NULL,
316 PreviousMode,
317 (PVOID*)&TargetProcess,
318 NULL);
319 if (!NT_SUCCESS(Status))
320 {
321 ObDereferenceObject(SourceProcess);
322 return(Status);
323 }
324
325 /* Check for magic handle first */
326 if (SourceHandle == NtCurrentThread())
327 {
328 PVOID ObjectBody;
329
330 Status = ObReferenceObjectByHandle(SourceHandle,
331 PROCESS_DUP_HANDLE,
332 NULL,
333 PreviousMode,
334 &ObjectBody,
335 NULL);
336 if(NT_SUCCESS(Status))
337 {
338 Status = ObCreateHandle(TargetProcess,
339 ObjectBody,
340 THREAD_ALL_ACCESS,
341 InheritHandle,
342 &hTarget);
343
344 ObDereferenceObject(ObjectBody);
345
346 if (Options & DUPLICATE_CLOSE_SOURCE)
347 {
348 ObDeleteHandle(SourceProcess,
349 SourceHandle);
350 }
351 }
352 }
353 else
354 {
355 Status = ObDuplicateObject(SourceProcess,
356 TargetProcess,
357 SourceHandle,
358 &hTarget,
359 DesiredAccess,
360 InheritHandle,
361 Options);
362 }
363
364 ObDereferenceObject(TargetProcess);
365 ObDereferenceObject(SourceProcess);
366
367 if(NT_SUCCESS(Status))
368 {
369 _SEH_TRY
370 {
371 *TargetHandle = hTarget;
372 }
373 _SEH_HANDLE
374 {
375 Status = _SEH_GetExceptionCode();
376 }
377 _SEH_END;
378 }
379
380 return Status;
381 }
382
383 static VOID STDCALL
384 DeleteHandleCallback(PHANDLE_TABLE HandleTable,
385 PVOID Object,
386 ULONG GrantedAccess,
387 PVOID Context)
388 {
389 POBJECT_HEADER ObjectHeader;
390 PVOID ObjectBody;
391
392 PAGED_CODE();
393
394 ObjectHeader = EX_OBJ_TO_HDR(Object);
395 ObjectBody = HEADER_TO_BODY(ObjectHeader);
396
397 ObpDecrementHandleCount(ObjectBody);
398 }
399
400 VOID ObDeleteHandleTable(PEPROCESS Process)
401 /*
402 * FUNCTION: Deletes the handle table associated with a process
403 */
404 {
405 PAGED_CODE();
406
407 ExDestroyHandleTable(Process->ObjectTable,
408 DeleteHandleCallback,
409 Process);
410 }
411
412 static BOOLEAN STDCALL
413 DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
414 PHANDLE_TABLE_ENTRY HandleTableEntry,
415 PVOID Context)
416 {
417 POBJECT_HEADER ObjectHeader;
418 BOOLEAN Ret = FALSE;
419
420 PAGED_CODE();
421
422 Ret = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
423 if(Ret)
424 {
425 ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
426 if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
427 {
428 ObReferenceObjectByPointer(HEADER_TO_BODY(ObjectHeader),
429 0,
430 NULL,
431 UserMode);
432 }
433 }
434
435 return Ret;
436 }
437
438 VOID ObCreateHandleTable(PEPROCESS Parent,
439 BOOLEAN Inherit,
440 PEPROCESS Process)
441 /*
442 * FUNCTION: Creates a handle table for a process
443 * ARGUMENTS:
444 * Parent = Parent process (or NULL if this is the first process)
445 * Inherit = True if the process should inherit its parent's handles
446 * Process = Process whose handle table is to be created
447 */
448 {
449 PAGED_CODE();
450
451 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
452 Parent,Inherit,Process);
453 if(Parent != NULL)
454 {
455 Process->ObjectTable = ExDupHandleTable(Process,
456 DuplicateHandleCallback,
457 NULL,
458 Parent->ObjectTable);
459 }
460 else
461 {
462 Process->ObjectTable = ExCreateHandleTable(Process);
463 }
464 }
465
466
467 NTSTATUS
468 ObDeleteHandle(PEPROCESS Process,
469 HANDLE Handle)
470 {
471 PHANDLE_TABLE_ENTRY HandleEntry;
472 PVOID Body;
473 POBJECT_HEADER ObjectHeader;
474 LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
475
476 PAGED_CODE();
477
478 DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
479
480 KeEnterCriticalRegion();
481
482 HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
483 ExHandle);
484 if(HandleEntry != NULL)
485 {
486 if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
487 {
488 ExUnlockHandleTableEntry(Process->ObjectTable,
489 HandleEntry);
490
491 KeLeaveCriticalRegion();
492
493 return STATUS_HANDLE_NOT_CLOSABLE;
494 }
495
496 ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
497 Body = HEADER_TO_BODY(ObjectHeader);
498
499 ObpDecrementHandleCount(Body);
500
501 /* destroy and unlock the handle entry */
502 ExDestroyHandleByEntry(Process->ObjectTable,
503 HandleEntry,
504 ExHandle);
505
506 KeLeaveCriticalRegion();
507
508 return STATUS_SUCCESS;
509 }
510 KeLeaveCriticalRegion();
511 return STATUS_INVALID_HANDLE;
512 }
513
514
515 NTSTATUS
516 ObCreateHandle(PEPROCESS Process,
517 PVOID ObjectBody,
518 ACCESS_MASK GrantedAccess,
519 BOOLEAN Inherit,
520 PHANDLE HandleReturn)
521 /*
522 * FUNCTION: Add a handle referencing an object
523 * ARGUMENTS:
524 * obj = Object body that the handle should refer to
525 * RETURNS: The created handle
526 * NOTE: The handle is valid only in the context of the current process
527 */
528 {
529 HANDLE_TABLE_ENTRY NewEntry;
530 POBJECT_HEADER ObjectHeader;
531 LONG ExHandle;
532
533 PAGED_CODE();
534
535 DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
536
537 ASSERT(Process);
538 ASSERT(ObjectBody);
539
540 ObjectHeader = BODY_TO_HEADER(ObjectBody);
541
542 ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
543
544 NewEntry.u1.Object = ObjectHeader;
545 if(Inherit)
546 NewEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
547 else
548 NewEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
549 NewEntry.u2.GrantedAccess = GrantedAccess;
550
551 ExHandle = ExCreateHandle(Process->ObjectTable,
552 &NewEntry);
553 DPRINT("ObCreateHandle(0x%x)==0x%x [HT:0x%x]\n", ObjectHeader, *HandleReturn, Process->ObjectTable);
554 if(ExHandle != EX_INVALID_HANDLE)
555 {
556 if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
557 {
558 ObReferenceObjectByPointer(ObjectBody,
559 0,
560 NULL,
561 UserMode);
562 }
563
564 *HandleReturn = EX_HANDLE_TO_HANDLE(ExHandle);
565
566 return STATUS_SUCCESS;
567 }
568
569 return STATUS_UNSUCCESSFUL;
570 }
571
572
573 /*
574 * @implemented
575 */
576 NTSTATUS STDCALL
577 ObQueryObjectAuditingByHandle(IN HANDLE Handle,
578 OUT PBOOLEAN GenerateOnClose)
579 {
580 PHANDLE_TABLE_ENTRY HandleEntry;
581 PEPROCESS Process;
582 LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
583
584 PAGED_CODE();
585
586 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
587
588 Process = PsGetCurrentProcess();
589
590 KeEnterCriticalRegion();
591
592 HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
593 ExHandle);
594 if(HandleEntry != NULL)
595 {
596 *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
597
598 ExUnlockHandleTableEntry(Process->ObjectTable,
599 HandleEntry);
600
601 KeLeaveCriticalRegion();
602
603 return STATUS_SUCCESS;
604 }
605
606 KeLeaveCriticalRegion();
607
608 return STATUS_INVALID_HANDLE;
609 }
610
611
612 /*
613 * FUNCTION: Increments the reference count for an object and returns a
614 * pointer to its body
615 * ARGUMENTS:
616 * Handle = Handle for the object
617 * DesiredAccess = Desired access to the object
618 * ObjectType
619 * AccessMode
620 * Object (OUT) = Points to the object body on return
621 * HandleInformation (OUT) = Contains information about the handle
622 * on return
623 * RETURNS: Status
624 *
625 * @implemented
626 */
627 NTSTATUS STDCALL
628 ObReferenceObjectByHandle(HANDLE Handle,
629 ACCESS_MASK DesiredAccess,
630 POBJECT_TYPE ObjectType,
631 KPROCESSOR_MODE AccessMode,
632 PVOID* Object,
633 POBJECT_HANDLE_INFORMATION HandleInformation)
634 {
635 PHANDLE_TABLE_ENTRY HandleEntry;
636 POBJECT_HEADER ObjectHeader;
637 PVOID ObjectBody;
638 ACCESS_MASK GrantedAccess;
639 PGENERIC_MAPPING GenericMapping;
640 ULONG Attributes;
641 NTSTATUS Status;
642 LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle);
643
644 PAGED_CODE();
645
646 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
647 "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
648 ObjectType,AccessMode,Object);
649
650 /*
651 * Handle special handle names
652 */
653 if (Handle == NtCurrentProcess() &&
654 (ObjectType == PsProcessType || ObjectType == NULL))
655 {
656 Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
657 PROCESS_ALL_ACCESS,
658 PsProcessType,
659 UserMode);
660 if (! NT_SUCCESS(Status))
661 {
662 return Status;
663 }
664
665 if (HandleInformation != NULL)
666 {
667 HandleInformation->HandleAttributes = 0;
668 HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
669 }
670
671 *Object = PsGetCurrentProcess();
672 DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
673 return STATUS_SUCCESS;
674 }
675 else if (Handle == NtCurrentProcess())
676 {
677 CHECKPOINT;
678 return(STATUS_OBJECT_TYPE_MISMATCH);
679 }
680
681 if (Handle == NtCurrentThread() &&
682 (ObjectType == PsThreadType || ObjectType == NULL))
683 {
684 Status = ObReferenceObjectByPointer(PsGetCurrentThread(),
685 THREAD_ALL_ACCESS,
686 PsThreadType,
687 UserMode);
688 if (! NT_SUCCESS(Status))
689 {
690 return Status;
691 }
692
693 if (HandleInformation != NULL)
694 {
695 HandleInformation->HandleAttributes = 0;
696 HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
697 }
698
699 *Object = PsGetCurrentThread();
700 CHECKPOINT;
701 return STATUS_SUCCESS;
702 }
703 else if (Handle == NtCurrentThread())
704 {
705 CHECKPOINT;
706 return(STATUS_OBJECT_TYPE_MISMATCH);
707 }
708
709 KeEnterCriticalRegion();
710
711 HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable,
712 ExHandle);
713 if (HandleEntry == NULL)
714 {
715 KeLeaveCriticalRegion();
716 DPRINT("ExMapHandleToPointer() failed for handle 0x%x\n", Handle);
717 return(STATUS_INVALID_HANDLE);
718 }
719
720 ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
721 ObjectBody = HEADER_TO_BODY(ObjectHeader);
722
723 DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, PsGetCurrentProcess()->ObjectTable);
724
725 ObReferenceObjectByPointer(ObjectBody,
726 0,
727 NULL,
728 UserMode);
729 Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
730 EX_HANDLE_ENTRY_INHERITABLE |
731 EX_HANDLE_ENTRY_AUDITONCLOSE);
732 GrantedAccess = HandleEntry->u2.GrantedAccess;
733 GenericMapping = ObjectHeader->ObjectType->Mapping;
734
735 if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
736 {
737 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle);
738
739 ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
740 HandleEntry);
741
742 KeLeaveCriticalRegion();
743
744 return(STATUS_OBJECT_TYPE_MISMATCH);
745 }
746
747 ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable,
748 HandleEntry);
749
750 KeLeaveCriticalRegion();
751
752 if (DesiredAccess && AccessMode != KernelMode)
753 {
754 RtlMapGenericMask(&DesiredAccess, GenericMapping);
755
756 if (!(GrantedAccess & DesiredAccess) &&
757 !((~GrantedAccess) & DesiredAccess))
758 {
759 CHECKPOINT;
760 return(STATUS_ACCESS_DENIED);
761 }
762 }
763
764 if (HandleInformation != NULL)
765 {
766 HandleInformation->HandleAttributes = Attributes;
767 HandleInformation->GrantedAccess = GrantedAccess;
768 }
769
770 *Object = ObjectBody;
771
772 return(STATUS_SUCCESS);
773 }
774
775
776 /**********************************************************************
777 * NAME EXPORTED
778 * NtClose
779 *
780 * DESCRIPTION
781 * Closes a handle reference to an object.
782 *
783 * ARGUMENTS
784 * Handle
785 * Handle to close.
786 *
787 * RETURN VALUE
788 * Status.
789 *
790 * @implemented
791 */
792 NTSTATUS STDCALL
793 NtClose(IN HANDLE Handle)
794 {
795 NTSTATUS Status;
796
797 PAGED_CODE();
798
799 Status = ObDeleteHandle(PsGetCurrentProcess(),
800 Handle);
801 if (!NT_SUCCESS(Status))
802 {
803 if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
804 KeRaiseUserException(Status);
805 return Status;
806 }
807
808 return(STATUS_SUCCESS);
809 }
810
811
812 /*
813 * @implemented
814 */
815 NTSTATUS STDCALL
816 ObInsertObject(IN PVOID Object,
817 IN PACCESS_STATE PassedAccessState OPTIONAL,
818 IN ACCESS_MASK DesiredAccess,
819 IN ULONG AdditionalReferences,
820 OUT PVOID* ReferencedObject OPTIONAL,
821 OUT PHANDLE Handle)
822 {
823 POBJECT_HEADER ObjectHeader;
824 ACCESS_MASK Access;
825
826 PAGED_CODE();
827
828 Access = DesiredAccess;
829 ObjectHeader = BODY_TO_HEADER(Object);
830
831 RtlMapGenericMask(&Access,
832 ObjectHeader->ObjectType->Mapping);
833
834 return(ObCreateHandle(PsGetCurrentProcess(),
835 Object,
836 Access,
837 ObjectHeader->Inherit,
838 Handle));
839 }
840
841
842 ULONG
843 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
844 {
845 return HandleTable->HandleCount;
846 }
847
848 /*
849 * FUNCTION: Searches the handle table of a specified process whether it contains a
850 * valid handle to the Object we're looking for. If not, it'll create one.
851 *
852 * NOTES:
853 * The parameters of this function is basically a mixture of some of the parameters
854 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
855 * about what this function does (by it's name) makes clear what parameters it requires.
856 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
857 * required at all as it only has influence on the object security. This function doesn't
858 * want to get access to an object, it just looks for a valid handle and if it can't find
859 * one, it'll just create one. It wouldn't make sense to check for security again as the
860 * caller already has a pointer to the object.
861 *
862 * A test on an XP machine shows that this prototype appears to be correct.
863 *
864 * ARGUMENTS:
865 * Process = This parameter simply describes in which handle table we're looking
866 * for a handle to the object.
867 * Object = The object pointer that we're looking for
868 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
869 * ObReferenceObjectByPointer() provides.
870 * HandleInformation = This one has to be the opposite meaning of the usage in
871 * ObReferenceObjectByHandle(). If we actually found a valid
872 * handle in the table, we need to check against the information
873 * provided so we make sure this handle has all access rights
874 * (and attributes?!) we need. If they don't match, we can't
875 * use this handle and keep looking because the caller is likely
876 * to depend on these access rights.
877 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
878 * find a suitable handle in the handle table, return this handle, if
879 * not, we'll just create one using ObCreateHandle() with all access
880 * rights the caller needs.
881 *
882 * RETURNS: Status
883 *
884 * @unimplemented
885 */
886 NTSTATUS STDCALL
887 ObFindHandleForObject(IN PEPROCESS Process,
888 IN PVOID Object,
889 IN POBJECT_TYPE ObjectType,
890 IN POBJECT_HANDLE_INFORMATION HandleInformation,
891 OUT PHANDLE HandleReturn)
892 {
893 UNIMPLEMENTED;
894 return STATUS_UNSUCCESSFUL;
895 }
896
897 VOID
898 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
899 PEPROCESS Process,
900 int Count)
901 {
902 ULONG P;
903 // KIRQL oldIrql;
904
905 // pshi->HandleValue;
906
907 /*
908 This will never work with ROS! M$, I guess uses 0 -> 65535.
909 Ros uses 0 -> 4294967295!
910 */
911
912 P = (ULONG) Process->UniqueProcessId;
913 pshi->UniqueProcessId = (USHORT) P;
914
915 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
916
917 // pshi->GrantedAccess;
918 // pshi->Object;
919 // pshi->ObjectTypeIndex;
920 // pshi->HandleAttributes;
921
922 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
923
924 return;
925 }
926
927
928
929 /* EOF */