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