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