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