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