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