- Implemented InterlockedBitTestAndReset, InterlockedBitTestAndSet, InterlockedExchan...
[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 GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
37
38 /* GLOBALS *****************************************************************/
39
40 PHANDLE_TABLE ObpKernelHandleTable = NULL;
41
42 /* TEMPORARY HACK. DO NOT REMOVE -- Alex */
43 NTSTATUS
44 STDCALL
45 ExpDesktopCreate(PVOID ObjectBody,
46 PVOID Parent,
47 PWSTR RemainingPath,
48 POBJECT_CREATE_INFORMATION ObjectCreateInformation);
49
50 /* FUNCTIONS ***************************************************************/
51
52 static VOID
53 ObpDecrementHandleCount(PVOID ObjectBody)
54 {
55 POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody);
56 LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
57 DPRINT("Header: %x\n", ObjectHeader);
58 DPRINT("NewHandleCount: %x\n", NewHandleCount);
59 DPRINT("HEADER_TO_OBJECT_NAME: %x\n", HEADER_TO_OBJECT_NAME(ObjectHeader));
60
61 if ((ObjectHeader->Type != NULL) &&
62 (ObjectHeader->Type->TypeInfo.CloseProcedure != NULL))
63 {
64 /* the handle count should be decremented but we pass the previous value
65 to the callback */
66 ObjectHeader->Type->TypeInfo.CloseProcedure(ObjectBody, NewHandleCount + 1);
67 }
68
69 if(NewHandleCount == 0)
70 {
71 if(HEADER_TO_OBJECT_NAME(ObjectHeader) &&
72 HEADER_TO_OBJECT_NAME(ObjectHeader)->Directory != NULL &&
73 !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
74 {
75 /* delete the object from the namespace when the last handle got closed.
76 Only do this if it's actually been inserted into the namespace and
77 if it's not a permanent object. */
78 ObpRemoveEntryDirectory(ObjectHeader);
79 }
80
81 /* remove the keep-alive reference */
82 ObDereferenceObject(ObjectBody);
83 }
84 }
85
86
87 NTSTATUS
88 NTAPI
89 ObpQueryHandleAttributes(HANDLE Handle,
90 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
91 {
92 PHANDLE_TABLE_ENTRY HandleTableEntry;
93 PEPROCESS Process, CurrentProcess;
94 KAPC_STATE ApcState;
95 BOOLEAN AttachedToProcess = FALSE;
96 NTSTATUS Status = STATUS_SUCCESS;
97
98 PAGED_CODE();
99
100 DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle);
101 CurrentProcess = PsGetCurrentProcess();
102
103 KeEnterCriticalRegion();
104
105 if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
106 {
107 Process = PsInitialSystemProcess;
108 Handle = ObKernelHandleToHandle(Handle);
109
110 if (Process != CurrentProcess)
111 {
112 KeStackAttachProcess(&Process->Pcb,
113 &ApcState);
114 AttachedToProcess = TRUE;
115 }
116 }
117 else
118 {
119 Process = CurrentProcess;
120 }
121
122 HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
123 Handle);
124 if (HandleTableEntry != NULL)
125 {
126 HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
127 HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
128
129 ExUnlockHandleTableEntry(Process->ObjectTable,
130 HandleTableEntry);
131 }
132 else
133 Status = STATUS_INVALID_HANDLE;
134
135 if (AttachedToProcess)
136 {
137 KeUnstackDetachProcess(&ApcState);
138 }
139
140 KeLeaveCriticalRegion();
141
142 return Status;
143 }
144
145
146 NTSTATUS
147 NTAPI
148 ObpSetHandleAttributes(HANDLE Handle,
149 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
150 {
151 PHANDLE_TABLE_ENTRY HandleTableEntry;
152 PEPROCESS Process, CurrentProcess;
153 KAPC_STATE ApcState;
154 BOOLEAN AttachedToProcess = FALSE;
155 NTSTATUS Status = STATUS_SUCCESS;
156
157 PAGED_CODE();
158
159 DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
160 CurrentProcess = PsGetCurrentProcess();
161
162 KeEnterCriticalRegion();
163
164 if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
165 {
166 Process = PsInitialSystemProcess;
167 Handle = ObKernelHandleToHandle(Handle);
168
169 if (Process != CurrentProcess)
170 {
171 KeStackAttachProcess(&Process->Pcb,
172 &ApcState);
173 AttachedToProcess = TRUE;
174 }
175 }
176 else
177 {
178 Process = CurrentProcess;
179 }
180
181 HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable,
182 Handle);
183 if (HandleTableEntry != NULL)
184 {
185 if (HandleInfo->Inherit)
186 HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
187 else
188 HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
189
190 if (HandleInfo->ProtectFromClose)
191 HandleTableEntry->u1.ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
192 else
193 HandleTableEntry->u1.ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
194
195 /* FIXME: Do we need to set anything in the object header??? */
196
197 ExUnlockHandleTableEntry(Process->ObjectTable,
198 HandleTableEntry);
199 }
200 else
201 Status = STATUS_INVALID_HANDLE;
202
203 if (AttachedToProcess)
204 {
205 KeUnstackDetachProcess(&ApcState);
206 }
207
208 KeLeaveCriticalRegion();
209
210 return Status;
211 }
212
213
214 static NTSTATUS
215 ObpDeleteHandle(HANDLE Handle)
216 {
217 PHANDLE_TABLE_ENTRY HandleEntry;
218 PVOID Body;
219 POBJECT_HEADER ObjectHeader;
220 PHANDLE_TABLE ObjectTable;
221
222 PAGED_CODE();
223
224 DPRINT("ObpDeleteHandle(Handle %p)\n",Handle);
225
226 ObjectTable = PsGetCurrentProcess()->ObjectTable;
227
228 KeEnterCriticalRegion();
229
230 HandleEntry = ExMapHandleToPointer(ObjectTable,
231 Handle);
232 if(HandleEntry != NULL)
233 {
234 if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE)
235 {
236 ExUnlockHandleTableEntry(ObjectTable,
237 HandleEntry);
238
239 KeLeaveCriticalRegion();
240
241 return STATUS_HANDLE_NOT_CLOSABLE;
242 }
243
244 ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
245 Body = &ObjectHeader->Body;
246
247 /* destroy and unlock the handle entry */
248 ExDestroyHandleByEntry(ObjectTable,
249 HandleEntry,
250 Handle);
251
252 ObpDecrementHandleCount(Body);
253
254 KeLeaveCriticalRegion();
255
256 return STATUS_SUCCESS;
257 }
258 KeLeaveCriticalRegion();
259 return STATUS_INVALID_HANDLE;
260 }
261
262
263 NTSTATUS
264 NTAPI
265 ObDuplicateObject(PEPROCESS SourceProcess,
266 PEPROCESS TargetProcess,
267 HANDLE SourceHandle,
268 PHANDLE TargetHandle,
269 ACCESS_MASK DesiredAccess,
270 ULONG HandleAttributes,
271 ULONG Options)
272 {
273 PHANDLE_TABLE_ENTRY SourceHandleEntry;
274 HANDLE_TABLE_ENTRY NewHandleEntry;
275 BOOLEAN AttachedToProcess = FALSE;
276 PVOID ObjectBody;
277 POBJECT_HEADER ObjectHeader;
278 ULONG NewHandleCount;
279 HANDLE NewTargetHandle;
280 PEPROCESS CurrentProcess;
281 KAPC_STATE ApcState;
282 NTSTATUS Status = STATUS_SUCCESS;
283
284 PAGED_CODE();
285
286 if(SourceProcess == NULL ||
287 ObIsKernelHandle(SourceHandle, ExGetPreviousMode()))
288 {
289 SourceProcess = PsInitialSystemProcess;
290 SourceHandle = ObKernelHandleToHandle(SourceHandle);
291 }
292
293 CurrentProcess = PsGetCurrentProcess();
294
295 KeEnterCriticalRegion();
296
297 if (SourceProcess != CurrentProcess)
298 {
299 KeStackAttachProcess(&SourceProcess->Pcb,
300 &ApcState);
301 AttachedToProcess = TRUE;
302 }
303 SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable,
304 SourceHandle);
305 if (SourceHandleEntry == NULL)
306 {
307 if (AttachedToProcess)
308 {
309 KeUnstackDetachProcess(&ApcState);
310 }
311
312 KeLeaveCriticalRegion();
313 return STATUS_INVALID_HANDLE;
314 }
315
316 ObjectHeader = EX_HTE_TO_HDR(SourceHandleEntry);
317 ObjectBody = &ObjectHeader->Body;
318
319 NewHandleEntry.u1.Object = SourceHandleEntry->u1.Object;
320 if(HandleAttributes & OBJ_INHERIT)
321 NewHandleEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
322 else
323 NewHandleEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
324 NewHandleEntry.u2.GrantedAccess = ((Options & DUPLICATE_SAME_ACCESS) ?
325 SourceHandleEntry->u2.GrantedAccess :
326 DesiredAccess);
327 if (Options & DUPLICATE_SAME_ACCESS)
328 {
329 NewHandleEntry.u2.GrantedAccess = SourceHandleEntry->u2.GrantedAccess;
330 }
331 else
332 {
333 if (DesiredAccess & GENERIC_ANY)
334 {
335 RtlMapGenericMask(&DesiredAccess,
336 &ObjectHeader->Type->TypeInfo.GenericMapping);
337 }
338 NewHandleEntry.u2.GrantedAccess = DesiredAccess;
339 }
340
341 /* reference the object so it doesn't get deleted after releasing the lock
342 and before creating a new handle for it */
343 ObReferenceObject(ObjectBody);
344
345 /* increment the handle count of the object, it should always be >= 2 because
346 we're holding a handle lock to this object! if the new handle count was
347 1 here, we're in big trouble... it would've been safe to increment and
348 check the handle count without using interlocked functions because the
349 entry is locked, which means the handle count can't change. */
350 NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount);
351 ASSERT(NewHandleCount >= 2);
352
353 ExUnlockHandleTableEntry(SourceProcess->ObjectTable,
354 SourceHandleEntry);
355
356 if (AttachedToProcess)
357 {
358 KeUnstackDetachProcess(&ApcState);
359 AttachedToProcess = FALSE;
360 }
361
362 if (TargetProcess != CurrentProcess)
363 {
364 KeStackAttachProcess(&TargetProcess->Pcb,
365 &ApcState);
366 AttachedToProcess = TRUE;
367 }
368
369 /* attempt to create the new handle */
370 NewTargetHandle = ExCreateHandle(TargetProcess->ObjectTable,
371 &NewHandleEntry);
372 if (AttachedToProcess)
373 {
374 KeUnstackDetachProcess(&ApcState);
375 AttachedToProcess = FALSE;
376 }
377
378 if (NewTargetHandle != NULL)
379 {
380 if (Options & DUPLICATE_CLOSE_SOURCE)
381 {
382 if (SourceProcess != CurrentProcess)
383 {
384 KeStackAttachProcess(&SourceProcess->Pcb,
385 &ApcState);
386 AttachedToProcess = TRUE;
387 }
388
389 /* delete the source handle */
390 ObpDeleteHandle(SourceHandle);
391
392 if (AttachedToProcess)
393 {
394 KeUnstackDetachProcess(&ApcState);
395 }
396 }
397
398 ObDereferenceObject(ObjectBody);
399
400 *TargetHandle = NewTargetHandle;
401 }
402 else
403 {
404 /* decrement the handle count we previously incremented, but don't call the
405 closing procedure because we're not closing a handle! */
406 if(InterlockedDecrement(&ObjectHeader->HandleCount) == 0)
407 {
408 ObDereferenceObject(ObjectBody);
409 }
410
411 ObDereferenceObject(ObjectBody);
412 Status = STATUS_UNSUCCESSFUL;
413 }
414
415 KeLeaveCriticalRegion();
416
417 return Status;
418 }
419
420 /*
421 * @implemented
422 */
423 NTSTATUS STDCALL
424 NtDuplicateObject (IN HANDLE SourceProcessHandle,
425 IN HANDLE SourceHandle,
426 IN HANDLE TargetProcessHandle,
427 OUT PHANDLE TargetHandle OPTIONAL,
428 IN ACCESS_MASK DesiredAccess,
429 IN ULONG HandleAttributes,
430 IN ULONG Options)
431 /*
432 * FUNCTION: Copies a handle from one process space to another
433 * ARGUMENTS:
434 * SourceProcessHandle = The source process owning the handle. The
435 * source process should have opened
436 * the SourceHandle with PROCESS_DUP_HANDLE
437 * access.
438 * SourceHandle = The handle to the object.
439 * TargetProcessHandle = The destination process owning the handle
440 * TargetHandle (OUT) = Caller should supply storage for the
441 * duplicated handle.
442 * DesiredAccess = The desired access to the handle.
443 * HandleAttributes = The desired handle attributes.
444 * Options = Specifies special actions upon duplicating the handle.
445 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
446 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
447 * that the source handle should be closed after duplicating.
448 * DUPLICATE_SAME_ACCESS specifies to ignore the
449 * DesiredAccess paramter and just grant the same access to
450 * the new handle.
451 * RETURNS: Status
452 * REMARKS: This function maps to the win32 DuplicateHandle.
453 */
454 {
455 PEPROCESS SourceProcess;
456 PEPROCESS TargetProcess;
457 PEPROCESS CurrentProcess;
458 HANDLE hTarget;
459 BOOLEAN AttachedToProcess = FALSE;
460 KPROCESSOR_MODE PreviousMode;
461 KAPC_STATE ApcState;
462 NTSTATUS Status = STATUS_SUCCESS;
463
464 PAGED_CODE();
465
466 PreviousMode = ExGetPreviousMode();
467
468 if(TargetHandle != NULL && PreviousMode != KernelMode)
469 {
470 _SEH_TRY
471 {
472 ProbeForWriteHandle(TargetHandle);
473 }
474 _SEH_HANDLE
475 {
476 Status = _SEH_GetExceptionCode();
477 }
478 _SEH_END;
479
480 if(!NT_SUCCESS(Status))
481 {
482 return Status;
483 }
484 }
485
486 Status = ObReferenceObjectByHandle(SourceProcessHandle,
487 PROCESS_DUP_HANDLE,
488 NULL,
489 PreviousMode,
490 (PVOID*)&SourceProcess,
491 NULL);
492 if (!NT_SUCCESS(Status))
493 {
494 return(Status);
495 }
496
497 Status = ObReferenceObjectByHandle(TargetProcessHandle,
498 PROCESS_DUP_HANDLE,
499 NULL,
500 PreviousMode,
501 (PVOID*)&TargetProcess,
502 NULL);
503 if (!NT_SUCCESS(Status))
504 {
505 ObDereferenceObject(SourceProcess);
506 return(Status);
507 }
508
509 CurrentProcess = PsGetCurrentProcess();
510
511 /* Check for magic handle first */
512 if (SourceHandle == NtCurrentThread() ||
513 SourceHandle == NtCurrentProcess())
514 {
515 PVOID ObjectBody;
516 POBJECT_TYPE ObjectType;
517
518 ObjectType = (SourceHandle == NtCurrentThread()) ? PsThreadType : PsProcessType;
519
520 Status = ObReferenceObjectByHandle(SourceHandle,
521 0,
522 ObjectType,
523 PreviousMode,
524 &ObjectBody,
525 NULL);
526 if(NT_SUCCESS(Status))
527 {
528 if (Options & DUPLICATE_SAME_ACCESS)
529 {
530 /* grant all access rights */
531 DesiredAccess = ((ObjectType == PsThreadType) ? THREAD_ALL_ACCESS : PROCESS_ALL_ACCESS);
532 }
533 else
534 {
535 if (DesiredAccess & GENERIC_ANY)
536 {
537 RtlMapGenericMask(&DesiredAccess,
538 &ObjectType->TypeInfo.GenericMapping);
539 }
540 }
541
542 if (TargetProcess != CurrentProcess)
543 {
544 KeStackAttachProcess(&TargetProcess->Pcb,
545 &ApcState);
546 AttachedToProcess = TRUE;
547 }
548
549 Status = ObpCreateHandle(ObjectBody,
550 DesiredAccess,
551 HandleAttributes,
552 &hTarget);
553
554 if (AttachedToProcess)
555 {
556 KeUnstackDetachProcess(&ApcState);
557 AttachedToProcess = FALSE;
558 }
559
560 ObDereferenceObject(ObjectBody);
561
562 if (Options & DUPLICATE_CLOSE_SOURCE)
563 {
564 if (SourceProcess != CurrentProcess)
565 {
566 KeStackAttachProcess(&SourceProcess->Pcb,
567 &ApcState);
568 AttachedToProcess = TRUE;
569 }
570
571 ObpDeleteHandle(SourceHandle);
572
573 if (AttachedToProcess)
574 {
575 KeUnstackDetachProcess(&ApcState);
576 }
577 }
578 }
579 }
580 else
581 {
582 Status = ObDuplicateObject(SourceProcess,
583 TargetProcess,
584 SourceHandle,
585 &hTarget,
586 DesiredAccess,
587 HandleAttributes,
588 Options);
589 }
590
591 ObDereferenceObject(TargetProcess);
592 ObDereferenceObject(SourceProcess);
593
594 if(NT_SUCCESS(Status) && TargetHandle != NULL)
595 {
596 _SEH_TRY
597 {
598 *TargetHandle = hTarget;
599 }
600 _SEH_HANDLE
601 {
602 Status = _SEH_GetExceptionCode();
603 }
604 _SEH_END;
605 }
606
607 return Status;
608 }
609
610 static VOID STDCALL
611 SweepHandleCallback(PHANDLE_TABLE HandleTable,
612 PVOID Object,
613 ULONG GrantedAccess,
614 PVOID Context)
615 {
616 POBJECT_HEADER ObjectHeader;
617 PVOID ObjectBody;
618
619 PAGED_CODE();
620
621 ObjectHeader = EX_OBJ_TO_HDR(Object);
622 ObjectBody = &ObjectHeader->Body;
623
624 ObpDecrementHandleCount(ObjectBody);
625 }
626
627 static BOOLEAN STDCALL
628 DuplicateHandleCallback(PHANDLE_TABLE HandleTable,
629 PHANDLE_TABLE_ENTRY HandleTableEntry,
630 PVOID Context)
631 {
632 POBJECT_HEADER ObjectHeader;
633 BOOLEAN Ret = FALSE;
634
635 PAGED_CODE();
636
637 Ret = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0;
638 if(Ret)
639 {
640 ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
641 if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
642 {
643 ObReferenceObject(&ObjectHeader->Body);
644 }
645 }
646
647 return Ret;
648 }
649
650 VOID
651 NTAPI
652 ObCreateHandleTable(PEPROCESS Parent,
653 BOOLEAN Inherit,
654 PEPROCESS Process)
655 /*
656 * FUNCTION: Creates a handle table for a process
657 * ARGUMENTS:
658 * Parent = Parent process (or NULL if this is the first process)
659 * Inherit = True if the process should inherit its parent's handles
660 * Process = Process whose handle table is to be created
661 */
662 {
663 PAGED_CODE();
664
665 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
666 Parent,Inherit,Process);
667 if(Parent != NULL)
668 {
669 Process->ObjectTable = ExDupHandleTable(Process,
670 DuplicateHandleCallback,
671 NULL,
672 Parent->ObjectTable);
673 }
674 else
675 {
676 Process->ObjectTable = ExCreateHandleTable(Process);
677 }
678 }
679
680
681 VOID
682 STDCALL
683 ObKillProcess(PEPROCESS Process)
684 {
685 PAGED_CODE();
686
687 /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */
688 ExSweepHandleTable(Process->ObjectTable,
689 SweepHandleCallback,
690 Process);
691 ExDestroyHandleTable(Process->ObjectTable);
692 Process->ObjectTable = NULL;
693 }
694
695
696 NTSTATUS
697 NTAPI
698 ObpCreateHandle(PVOID ObjectBody,
699 ACCESS_MASK GrantedAccess,
700 ULONG HandleAttributes,
701 PHANDLE HandleReturn)
702 /*
703 * FUNCTION: Add a handle referencing an object
704 * ARGUMENTS:
705 * obj = Object body that the handle should refer to
706 * RETURNS: The created handle
707 * NOTE: The handle is valid only in the context of the current process
708 */
709 {
710 HANDLE_TABLE_ENTRY NewEntry;
711 PEPROCESS Process, CurrentProcess;
712 POBJECT_HEADER ObjectHeader;
713 HANDLE Handle;
714 KAPC_STATE ApcState;
715 BOOLEAN AttachedToProcess = FALSE;
716
717 PAGED_CODE();
718
719 DPRINT("ObpCreateHandle(obj %p)\n",ObjectBody);
720
721 ASSERT(ObjectBody);
722
723 CurrentProcess = PsGetCurrentProcess();
724
725 ObjectHeader = BODY_TO_HEADER(ObjectBody);
726
727 /* check that this is a valid kernel pointer */
728 ASSERT((ULONG_PTR)ObjectHeader & EX_HANDLE_ENTRY_LOCKED);
729
730 if (GrantedAccess & MAXIMUM_ALLOWED)
731 {
732 GrantedAccess &= ~MAXIMUM_ALLOWED;
733 GrantedAccess |= GENERIC_ALL;
734 }
735
736 if (GrantedAccess & GENERIC_ANY)
737 {
738 RtlMapGenericMask(&GrantedAccess,
739 &ObjectHeader->Type->TypeInfo.GenericMapping);
740 }
741
742 NewEntry.u1.Object = ObjectHeader;
743 if(HandleAttributes & OBJ_INHERIT)
744 NewEntry.u1.ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
745 else
746 NewEntry.u1.ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
747 NewEntry.u2.GrantedAccess = GrantedAccess;
748
749 if ((HandleAttributes & OBJ_KERNEL_HANDLE) &&
750 ExGetPreviousMode == KernelMode)
751 {
752 Process = PsInitialSystemProcess;
753 if (Process != CurrentProcess)
754 {
755 KeStackAttachProcess(&Process->Pcb,
756 &ApcState);
757 AttachedToProcess = TRUE;
758 }
759 }
760 else
761 {
762 Process = CurrentProcess;
763 /* mask out the OBJ_KERNEL_HANDLE attribute */
764 HandleAttributes &= ~OBJ_KERNEL_HANDLE;
765 }
766
767 Handle = ExCreateHandle(Process->ObjectTable,
768 &NewEntry);
769
770 if (AttachedToProcess)
771 {
772 KeUnstackDetachProcess(&ApcState);
773 }
774
775 if(Handle != NULL)
776 {
777 if (HandleAttributes & OBJ_KERNEL_HANDLE)
778 {
779 /* mark the handle value */
780 Handle = ObMarkHandleAsKernelHandle(Handle);
781 }
782
783 if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1)
784 {
785 ObReferenceObject(ObjectBody);
786 }
787
788 *HandleReturn = Handle;
789
790 return STATUS_SUCCESS;
791 }
792
793 return STATUS_UNSUCCESSFUL;
794 }
795
796
797 /*
798 * @implemented
799 */
800 NTSTATUS STDCALL
801 ObQueryObjectAuditingByHandle(IN HANDLE Handle,
802 OUT PBOOLEAN GenerateOnClose)
803 {
804 PHANDLE_TABLE_ENTRY HandleEntry;
805 PEPROCESS Process, CurrentProcess;
806 KAPC_STATE ApcState;
807 BOOLEAN AttachedToProcess = FALSE;
808 NTSTATUS Status = STATUS_SUCCESS;
809
810 PAGED_CODE();
811
812 DPRINT("ObQueryObjectAuditingByHandle(Handle %p)\n", Handle);
813
814 CurrentProcess = PsGetCurrentProcess();
815
816 KeEnterCriticalRegion();
817
818 if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
819 {
820 Process = PsInitialSystemProcess;
821 Handle = ObKernelHandleToHandle(Handle);
822
823 if (Process != CurrentProcess)
824 {
825 KeStackAttachProcess(&Process->Pcb,
826 &ApcState);
827 AttachedToProcess = TRUE;
828 }
829 }
830 else
831 Process = CurrentProcess;
832
833 HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
834 Handle);
835 if(HandleEntry != NULL)
836 {
837 *GenerateOnClose = (HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_AUDITONCLOSE) != 0;
838
839 ExUnlockHandleTableEntry(Process->ObjectTable,
840 HandleEntry);
841 }
842 else
843 Status = STATUS_INVALID_HANDLE;
844
845 if (AttachedToProcess)
846 {
847 KeUnstackDetachProcess(&ApcState);
848 }
849
850 KeLeaveCriticalRegion();
851
852 return Status;
853 }
854
855
856 /*
857 * FUNCTION: Increments the reference count for an object and returns a
858 * pointer to its body
859 * ARGUMENTS:
860 * Handle = Handle for the object
861 * DesiredAccess = Desired access to the object
862 * ObjectType
863 * AccessMode
864 * Object (OUT) = Points to the object body on return
865 * HandleInformation (OUT) = Contains information about the handle
866 * on return
867 * RETURNS: Status
868 *
869 * @implemented
870 */
871 NTSTATUS STDCALL
872 ObReferenceObjectByHandle(HANDLE Handle,
873 ACCESS_MASK DesiredAccess,
874 POBJECT_TYPE ObjectType,
875 KPROCESSOR_MODE AccessMode,
876 PVOID* Object,
877 POBJECT_HANDLE_INFORMATION HandleInformation)
878 {
879 PHANDLE_TABLE_ENTRY HandleEntry;
880 POBJECT_HEADER ObjectHeader;
881 PVOID ObjectBody;
882 ACCESS_MASK GrantedAccess;
883 ULONG Attributes;
884 PEPROCESS CurrentProcess, Process;
885 BOOLEAN AttachedToProcess = FALSE;
886 KAPC_STATE ApcState;
887
888 PAGED_CODE();
889
890 DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
891 "ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
892 ObjectType,AccessMode,Object);
893
894 if (Handle == NULL)
895 {
896 return STATUS_INVALID_HANDLE;
897 }
898
899 CurrentProcess = PsGetCurrentProcess();
900
901 /*
902 * Handle special handle names
903 */
904 if (Handle == NtCurrentProcess() &&
905 (ObjectType == PsProcessType || ObjectType == NULL))
906 {
907 ObReferenceObject(CurrentProcess);
908
909 if (HandleInformation != NULL)
910 {
911 HandleInformation->HandleAttributes = 0;
912 HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
913 }
914
915 *Object = CurrentProcess;
916 DPRINT("Referencing current process %p\n", CurrentProcess);
917 return STATUS_SUCCESS;
918 }
919 else if (Handle == NtCurrentProcess())
920 {
921 CHECKPOINT;
922 return(STATUS_OBJECT_TYPE_MISMATCH);
923 }
924
925 if (Handle == NtCurrentThread() &&
926 (ObjectType == PsThreadType || ObjectType == NULL))
927 {
928 PETHREAD CurrentThread = PsGetCurrentThread();
929
930 ObReferenceObject(CurrentThread);
931
932 if (HandleInformation != NULL)
933 {
934 HandleInformation->HandleAttributes = 0;
935 HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
936 }
937
938 *Object = CurrentThread;
939 CHECKPOINT;
940 return STATUS_SUCCESS;
941 }
942 else if (Handle == NtCurrentThread())
943 {
944 CHECKPOINT;
945 return(STATUS_OBJECT_TYPE_MISMATCH);
946 }
947
948 /* desire as much access rights as possible */
949 if (DesiredAccess & MAXIMUM_ALLOWED)
950 {
951 DesiredAccess &= ~MAXIMUM_ALLOWED;
952 DesiredAccess |= GENERIC_ALL;
953 }
954
955 if(ObIsKernelHandle(Handle, AccessMode))
956 {
957 Process = PsInitialSystemProcess;
958 Handle = ObKernelHandleToHandle(Handle);
959 }
960 else
961 {
962 Process = CurrentProcess;
963 }
964
965 KeEnterCriticalRegion();
966
967 if (Process != CurrentProcess)
968 {
969 KeStackAttachProcess(&Process->Pcb,
970 &ApcState);
971 AttachedToProcess = TRUE;
972 }
973
974 HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
975 Handle);
976 if (HandleEntry == NULL)
977 {
978 if (AttachedToProcess)
979 {
980 KeUnstackDetachProcess(&ApcState);
981 }
982 KeLeaveCriticalRegion();
983 DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
984 return(STATUS_INVALID_HANDLE);
985 }
986
987 ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
988 ObjectBody = &ObjectHeader->Body;
989
990 DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
991
992 if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
993 {
994 DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
995
996 ExUnlockHandleTableEntry(Process->ObjectTable,
997 HandleEntry);
998
999 if (AttachedToProcess)
1000 {
1001 KeUnstackDetachProcess(&ApcState);
1002 }
1003
1004 KeLeaveCriticalRegion();
1005
1006 return(STATUS_OBJECT_TYPE_MISMATCH);
1007 }
1008
1009 /* map the generic access masks if the caller asks for generic access */
1010 if (DesiredAccess & GENERIC_ANY)
1011 {
1012 RtlMapGenericMask(&DesiredAccess,
1013 &BODY_TO_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
1014 }
1015
1016 GrantedAccess = HandleEntry->u2.GrantedAccess;
1017
1018 /* Unless running as KernelMode, deny access if caller desires more access
1019 rights than the handle can grant */
1020 if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
1021 {
1022 ExUnlockHandleTableEntry(Process->ObjectTable,
1023 HandleEntry);
1024
1025 if (AttachedToProcess)
1026 {
1027 KeUnstackDetachProcess(&ApcState);
1028 }
1029
1030 KeLeaveCriticalRegion();
1031
1032 DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
1033
1034 return(STATUS_ACCESS_DENIED);
1035 }
1036
1037 ObReferenceObject(ObjectBody);
1038
1039 Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
1040 EX_HANDLE_ENTRY_INHERITABLE |
1041 EX_HANDLE_ENTRY_AUDITONCLOSE);
1042
1043 ExUnlockHandleTableEntry(Process->ObjectTable,
1044 HandleEntry);
1045
1046 if (AttachedToProcess)
1047 {
1048 KeUnstackDetachProcess(&ApcState);
1049 }
1050
1051 KeLeaveCriticalRegion();
1052
1053 if (HandleInformation != NULL)
1054 {
1055 HandleInformation->HandleAttributes = Attributes;
1056 HandleInformation->GrantedAccess = GrantedAccess;
1057 }
1058
1059 *Object = ObjectBody;
1060
1061 return(STATUS_SUCCESS);
1062 }
1063
1064
1065 /**********************************************************************
1066 * NAME EXPORTED
1067 * NtClose
1068 *
1069 * DESCRIPTION
1070 * Closes a handle reference to an object.
1071 *
1072 * ARGUMENTS
1073 * Handle
1074 * Handle to close.
1075 *
1076 * RETURN VALUE
1077 * Status.
1078 *
1079 * @implemented
1080 */
1081 NTSTATUS STDCALL
1082 NtClose(IN HANDLE Handle)
1083 {
1084 PEPROCESS Process, CurrentProcess;
1085 BOOLEAN AttachedToProcess = FALSE;
1086 KAPC_STATE ApcState;
1087 NTSTATUS Status;
1088 KPROCESSOR_MODE PreviousMode;
1089
1090 PAGED_CODE();
1091
1092 PreviousMode = ExGetPreviousMode();
1093 CurrentProcess = PsGetCurrentProcess();
1094
1095 if(ObIsKernelHandle(Handle, PreviousMode))
1096 {
1097 Process = PsInitialSystemProcess;
1098 Handle = ObKernelHandleToHandle(Handle);
1099
1100 if (Process != CurrentProcess)
1101 {
1102 KeStackAttachProcess(&Process->Pcb,
1103 &ApcState);
1104 AttachedToProcess = TRUE;
1105 }
1106 }
1107 else
1108 Process = CurrentProcess;
1109
1110 Status = ObpDeleteHandle(Handle);
1111
1112 if (AttachedToProcess)
1113 {
1114 KeUnstackDetachProcess(&ApcState);
1115 }
1116
1117 if (!NT_SUCCESS(Status))
1118 {
1119 if((PreviousMode != KernelMode) &&
1120 (CurrentProcess->ExceptionPort))
1121 {
1122 KeRaiseUserException(Status);
1123 }
1124 return Status;
1125 }
1126
1127 return(STATUS_SUCCESS);
1128 }
1129
1130
1131 /*
1132 * @implemented
1133 */
1134 NTSTATUS
1135 STDCALL
1136 ObInsertObject(IN PVOID Object,
1137 IN PACCESS_STATE PassedAccessState OPTIONAL,
1138 IN ACCESS_MASK DesiredAccess,
1139 IN ULONG AdditionalReferences,
1140 OUT PVOID* ReferencedObject OPTIONAL,
1141 OUT PHANDLE Handle)
1142 {
1143 POBJECT_CREATE_INFORMATION ObjectCreateInfo;
1144 POBJECT_HEADER Header;
1145 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
1146 PVOID FoundObject = NULL;
1147 POBJECT_HEADER FoundHeader = NULL;
1148 NTSTATUS Status = STATUS_SUCCESS;
1149 UNICODE_STRING RemainingPath;
1150 BOOLEAN ObjectAttached = FALSE;
1151 PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL;
1152 SECURITY_SUBJECT_CONTEXT SubjectContext;
1153
1154 PAGED_CODE();
1155
1156 /* Get the Header and Create Info */
1157 DPRINT("ObInsertObject: %x\n", Object);
1158 Header = BODY_TO_HEADER(Object);
1159 ObjectCreateInfo = Header->ObjectCreateInfo;
1160 ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
1161
1162 /* First try to find the Object */
1163 if (ObjectNameInfo && ObjectNameInfo->Name.Buffer)
1164 {
1165 DPRINT("Object has a name. Trying to find it: %wZ.\n", &ObjectNameInfo->Name);
1166 Status = ObFindObject(ObjectCreateInfo,
1167 &ObjectNameInfo->Name,
1168 &FoundObject,
1169 &RemainingPath,
1170 NULL);
1171 DPRINT("FoundObject: %x, Path: %wZ\n", FoundObject, &RemainingPath);
1172 if (!NT_SUCCESS(Status))
1173 {
1174 DPRINT1("ObFindObject() failed! (Status 0x%x)\n", Status);
1175 return Status;
1176 }
1177
1178 if (FoundObject)
1179 {
1180 DPRINT("Getting header: %x\n", FoundObject);
1181 FoundHeader = BODY_TO_HEADER(FoundObject);
1182 }
1183
1184 if (FoundHeader && RemainingPath.Buffer == NULL)
1185 {
1186 DPRINT("Object exists\n");
1187 ObDereferenceObject(FoundObject);
1188 return STATUS_OBJECT_NAME_COLLISION;
1189 }
1190 }
1191 else
1192 {
1193 DPRINT("No name, empty remaining path\n");
1194 RtlInitUnicodeString(&RemainingPath, NULL);
1195 }
1196
1197 if (FoundHeader && FoundHeader->Type == ObDirectoryType &&
1198 RemainingPath.Buffer)
1199 {
1200 /* The name was changed so let's update it */
1201 /* FIXME: TEMPORARY HACK This will go in ObFindObject in the next commit */
1202 PVOID NewName;
1203 PWSTR BufferPos = RemainingPath.Buffer;
1204 ULONG Delta = 0;
1205
1206 ObpAddEntryDirectory(FoundObject, Header, NULL);
1207 ObjectAttached = TRUE;
1208
1209 ObjectNameInfo = HEADER_TO_OBJECT_NAME(Header);
1210
1211 if (BufferPos[0] == L'\\')
1212 {
1213 BufferPos++;
1214 Delta = sizeof(WCHAR);
1215 }
1216 NewName = ExAllocatePool(NonPagedPool, RemainingPath.MaximumLength - Delta);
1217 RtlMoveMemory(NewName, BufferPos, RemainingPath.MaximumLength - Delta);
1218 if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
1219 ObjectNameInfo->Name.Buffer = NewName;
1220 ObjectNameInfo->Name.Length = RemainingPath.Length - Delta;
1221 ObjectNameInfo->Name.MaximumLength = RemainingPath.MaximumLength - Delta;
1222 DPRINT("Name: %S\n", ObjectNameInfo->Name.Buffer);
1223 }
1224
1225 if ((Header->Type == IoFileObjectType) ||
1226 (Header->Type == ExDesktopObjectType) ||
1227 (Header->Type->TypeInfo.OpenProcedure != NULL))
1228 {
1229 DPRINT("About to call Open Routine\n");
1230 if (Header->Type == IoFileObjectType)
1231 {
1232 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1233 DPRINT("Calling IopCreateFile: %x\n", FoundObject);
1234 Status = IopCreateFile(&Header->Body,
1235 FoundObject,
1236 RemainingPath.Buffer,
1237 ObjectCreateInfo);
1238 DPRINT("Called IopCreateFile: %x\n", Status);
1239
1240 }
1241 else if (Header->Type == ExDesktopObjectType)
1242 {
1243 /* TEMPORARY HACK. DO NOT TOUCH -- Alex */
1244 DPRINT("Calling ExpDesktopCreate\n");
1245 Status = ExpDesktopCreate(&Header->Body,
1246 FoundObject,
1247 RemainingPath.Buffer,
1248 ObjectCreateInfo);
1249 }
1250 else if (Header->Type->TypeInfo.OpenProcedure != NULL)
1251 {
1252 DPRINT("Calling %x\n", Header->Type->TypeInfo.OpenProcedure);
1253 Status = Header->Type->TypeInfo.OpenProcedure(ObCreateHandle,
1254 &Header->Body,
1255 NULL,
1256 0,
1257 0);
1258 }
1259
1260 if (!NT_SUCCESS(Status))
1261 {
1262 DPRINT("Create Failed\n");
1263 if (ObjectAttached == TRUE)
1264 {
1265 ObpRemoveEntryDirectory(Header);
1266 }
1267 if (FoundObject)
1268 {
1269 ObDereferenceObject(FoundObject);
1270 }
1271 RtlFreeUnicodeString(&RemainingPath);
1272 return Status;
1273 }
1274 }
1275
1276 RtlFreeUnicodeString(&RemainingPath);
1277
1278 DPRINT("Security Assignment in progress\n");
1279 SeCaptureSubjectContext(&SubjectContext);
1280
1281 /* Build the new security descriptor */
1282 Status = SeAssignSecurity((FoundHeader != NULL) ? FoundHeader->SecurityDescriptor : NULL,
1283 (ObjectCreateInfo != NULL) ? ObjectCreateInfo->SecurityDescriptor : NULL,
1284 &NewSecurityDescriptor,
1285 (Header->Type == ObDirectoryType),
1286 &SubjectContext,
1287 &Header->Type->TypeInfo.GenericMapping,
1288 PagedPool);
1289
1290 if (NT_SUCCESS(Status))
1291 {
1292 DPRINT("NewSecurityDescriptor %p\n", NewSecurityDescriptor);
1293
1294 if (Header->Type->TypeInfo.SecurityProcedure != NULL)
1295 {
1296 /* Call the security method */
1297 Status = Header->Type->TypeInfo.SecurityProcedure(&Header->Body,
1298 AssignSecurityDescriptor,
1299 0,
1300 NewSecurityDescriptor,
1301 NULL,
1302 NULL,
1303 NonPagedPool,
1304 NULL);
1305 }
1306 else
1307 {
1308 /* Assign the security descriptor to the object header */
1309 Status = ObpAddSecurityDescriptor(NewSecurityDescriptor,
1310 &Header->SecurityDescriptor);
1311 DPRINT("Object security descriptor %p\n", Header->SecurityDescriptor);
1312 }
1313
1314 /* Release the new security descriptor */
1315 SeDeassignSecurity(&NewSecurityDescriptor);
1316 }
1317
1318 DPRINT("Security Complete\n");
1319 SeReleaseSubjectContext(&SubjectContext);
1320
1321 /* Create the Handle */
1322 /* HACKHACK: Because of ROS's incorrect startup, this can be called
1323 * without a valid Process until I finalize the startup patch,
1324 * so don't create a handle if this is the case. We also don't create
1325 * a handle if Handle is NULL when the Registry Code calls it, because
1326 * the registry code totally bastardizes the Ob and needs to be fixed
1327 */
1328 DPRINT("Creating handle\n");
1329 if (Handle != NULL)
1330 {
1331 Status = ObpCreateHandle(&Header->Body,
1332 DesiredAccess,
1333 ObjectCreateInfo->Attributes,
1334 Handle);
1335 DPRINT("handle Created: %d. refcount. handlecount %d %d\n",
1336 *Handle, Header->PointerCount, Header->HandleCount);
1337 }
1338
1339 /* We can delete the Create Info now */
1340 Header->ObjectCreateInfo = NULL;
1341 ObpReleaseCapturedAttributes(ObjectCreateInfo);
1342 ExFreePool(ObjectCreateInfo);
1343
1344 DPRINT("Status %x\n", Status);
1345 return Status;
1346 }
1347
1348
1349 ULONG
1350 NTAPI
1351 ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable)
1352 {
1353 return HandleTable->HandleCount;
1354 }
1355
1356 /*
1357 * FUNCTION: Searches the handle table of a specified process whether it contains a
1358 * valid handle to the Object we're looking for. If not, it'll create one.
1359 *
1360 * NOTES:
1361 * The parameters of this function is basically a mixture of some of the parameters
1362 * of ObReferenceObjectByHandle() and ObReferenceObjectByPointer(). A little thinking
1363 * about what this function does (by it's name) makes clear what parameters it requires.
1364 * For example the AccessMode parameter of ObReferenceObjectByHandle/Pointer() is not
1365 * required at all as it only has influence on the object security. This function doesn't
1366 * want to get access to an object, it just looks for a valid handle and if it can't find
1367 * one, it'll just create one. It wouldn't make sense to check for security again as the
1368 * caller already has a pointer to the object.
1369 *
1370 * A test on an XP machine shows that this prototype appears to be correct.
1371 *
1372 * ARGUMENTS:
1373 * Process = This parameter simply describes in which handle table we're looking
1374 * for a handle to the object.
1375 * Object = The object pointer that we're looking for
1376 * ObjectType = Just a sanity check as ObReferenceObjectByHandle() and
1377 * ObReferenceObjectByPointer() provides.
1378 * HandleInformation = This one has to be the opposite meaning of the usage in
1379 * ObReferenceObjectByHandle(). If we actually found a valid
1380 * handle in the table, we need to check against the information
1381 * provided so we make sure this handle has all access rights
1382 * (and attributes?!) we need. If they don't match, we can't
1383 * use this handle and keep looking because the caller is likely
1384 * to depend on these access rights.
1385 * HandleReturn = The last parameter is the same as in ObCreateHandle(). If we could
1386 * find a suitable handle in the handle table, return this handle, if
1387 * not, we'll just create one using ObCreateHandle() with all access
1388 * rights the caller needs.
1389 *
1390 * RETURNS: Status
1391 *
1392 * @unimplemented
1393 */
1394 NTSTATUS STDCALL
1395 ObFindHandleForObject(IN PEPROCESS Process,
1396 IN PVOID Object,
1397 IN POBJECT_TYPE ObjectType,
1398 IN POBJECT_HANDLE_INFORMATION HandleInformation,
1399 OUT PHANDLE HandleReturn)
1400 {
1401 DPRINT("ObFindHandleForObject is unimplemented!\n");
1402 return STATUS_UNSUCCESSFUL;
1403 }
1404
1405 VOID
1406 ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi,
1407 PEPROCESS Process,
1408 int Count)
1409 {
1410 ULONG P;
1411 // KIRQL oldIrql;
1412
1413 // pshi->HandleValue;
1414
1415 /*
1416 This will never work with ROS! M$, I guess uses 0 -> 65535.
1417 Ros uses 0 -> 4294967295!
1418 */
1419
1420 P = (ULONG) Process->UniqueProcessId;
1421 pshi->UniqueProcessId = (USHORT) P;
1422
1423 // KeAcquireSpinLock( &Process->HandleTable.ListLock, &oldIrql );
1424
1425 // pshi->GrantedAccess;
1426 // pshi->Object;
1427 // pshi->TypeIndex;
1428 // pshi->HandleAttributes;
1429
1430 // KeReleaseSpinLock( &Process->HandleTable.ListLock, oldIrql );
1431
1432 return;
1433 }
1434
1435
1436
1437 /* EOF */