Implemented ObQueryObjectAuditingByHandle().
[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: handle.c,v 1.54 2003/10/21 21:46:02 ekohl Exp $
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 #define NTOS_MODE_KERNEL
33 #include <ntos.h>
34 #include <internal/ob.h>
35 #include <internal/ps.h>
36 #include <internal/pool.h>
37 #include <internal/safe.h>
38
39 #define NDEBUG
40 #include <internal/debug.h>
41
42 /* TYPES *******************************************************************/
43
44 /*
45 * PURPOSE: Defines a handle
46 */
47 typedef struct
48 {
49 PVOID ObjectBody;
50 ACCESS_MASK GrantedAccess;
51 } HANDLE_REP, *PHANDLE_REP;
52
53 #define HANDLE_BLOCK_ENTRIES ((PAGE_SIZE-sizeof(LIST_ENTRY))/sizeof(HANDLE_REP))
54
55 #define OB_HANDLE_FLAG_MASK 0x00000007
56 #define OB_HANDLE_FLAG_AUDIT 0x00000004
57 #define OB_HANDLE_FLAG_PROTECT 0x00000002
58 #define OB_HANDLE_FLAG_INHERIT 0x00000001
59
60 #define OB_POINTER_TO_ENTRY(Pointer) \
61 (PVOID)((ULONG_PTR)(Pointer) & ~OB_HANDLE_FLAG_MASK)
62
63 #define OB_ENTRY_TO_POINTER(Entry) \
64 (PVOID)((ULONG_PTR)(Entry) & ~OB_HANDLE_FLAG_MASK)
65
66 /*
67 * PURPOSE: Defines a page's worth of handles
68 */
69 typedef struct
70 {
71 LIST_ENTRY entry;
72 HANDLE_REP handles[HANDLE_BLOCK_ENTRIES];
73 } HANDLE_BLOCK, *PHANDLE_BLOCK;
74
75
76 /* GLOBALS *******************************************************************/
77
78 #define TAG_HANDLE_TABLE TAG('H', 'T', 'B', 'L')
79
80 /* FUNCTIONS ***************************************************************/
81
82
83 static PHANDLE_REP ObpGetObjectByHandle(PHANDLE_TABLE HandleTable, HANDLE h)
84 /*
85 * FUNCTION: Get the data structure for a handle
86 * ARGUMENTS:
87 * Process = Process to get the handle for
88 * h = Handle
89 * ARGUMENTS: A pointer to the information about the handle on success,
90 * NULL on failure
91 */
92 {
93 PLIST_ENTRY current;
94 unsigned int handle = (((unsigned int)h) >> 2) - 1;
95 unsigned int count=handle/HANDLE_BLOCK_ENTRIES;
96 HANDLE_BLOCK* blk = NULL;
97 unsigned int i;
98
99 DPRINT("ObpGetObjectByHandle(HandleTable %x, h %x)\n",HandleTable,h);
100
101 current = HandleTable->ListHead.Flink;
102 DPRINT("current %x\n",current);
103
104 for (i=0;i<count;i++)
105 {
106 current = current->Flink;
107 if (current == (&(HandleTable->ListHead)))
108 {
109 return(NULL);
110 }
111 }
112
113 blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
114 DPRINT("object: %p\n",&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
115 return(&(blk->handles[handle%HANDLE_BLOCK_ENTRIES]));
116 }
117
118
119 NTSTATUS
120 ObpQueryHandleAttributes(HANDLE Handle,
121 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
122 {
123 PEPROCESS Process;
124 KIRQL oldIrql;
125 PHANDLE_REP HandleRep;
126
127 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
128
129 Process = PsGetCurrentProcess();
130
131 KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
132 HandleRep = ObpGetObjectByHandle(&Process->HandleTable,
133 Handle);
134 if (HandleRep == NULL)
135 {
136 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
137 return STATUS_INVALID_HANDLE;
138 }
139
140 HandleInfo->Inherit =
141 ((ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_INHERIT);
142 HandleInfo->ProtectFromClose =
143 ((ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_PROTECT);
144
145 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
146
147 return STATUS_SUCCESS;
148 }
149
150
151 NTSTATUS
152 ObpSetHandleAttributes(HANDLE Handle,
153 POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
154 {
155 PEPROCESS Process;
156 KIRQL oldIrql;
157 PHANDLE_REP HandleRep;
158
159 DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle);
160
161 Process = PsGetCurrentProcess();
162
163 KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
164 HandleRep = ObpGetObjectByHandle(&Process->HandleTable,
165 Handle);
166 if (HandleRep == NULL)
167 {
168 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
169 return STATUS_INVALID_HANDLE;
170 }
171
172 if (HandleInfo->Inherit)
173 HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody | OB_HANDLE_FLAG_INHERIT);
174 else
175 HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody & ~OB_HANDLE_FLAG_INHERIT);
176
177 if (HandleInfo->ProtectFromClose)
178 HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody | OB_HANDLE_FLAG_PROTECT);
179 else
180 HandleRep->ObjectBody = (PVOID)((ULONG_PTR)HandleRep->ObjectBody & ~OB_HANDLE_FLAG_PROTECT);
181
182 /* FIXME: Do we need to set anything in the object header??? */
183
184 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
185
186 return STATUS_SUCCESS;
187 }
188
189
190 NTSTATUS
191 ObDuplicateObject(PEPROCESS SourceProcess,
192 PEPROCESS TargetProcess,
193 HANDLE SourceHandle,
194 PHANDLE TargetHandle,
195 ACCESS_MASK DesiredAccess,
196 BOOLEAN InheritHandle,
197 ULONG Options)
198 {
199 KIRQL oldIrql;
200 PHANDLE_REP SourceHandleRep;
201 PVOID ObjectBody;
202
203 KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
204 SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
205 SourceHandle);
206 if (SourceHandleRep == NULL)
207 {
208 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
209 return(STATUS_INVALID_HANDLE);
210 }
211 ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleRep->ObjectBody);
212 ObReferenceObjectByPointer(ObjectBody,
213 0,
214 NULL,
215 UserMode);
216
217 if (Options & DUPLICATE_SAME_ACCESS)
218 {
219 DesiredAccess = SourceHandleRep->GrantedAccess;
220 }
221
222 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
223 ObCreateHandle(TargetProcess,
224 ObjectBody,
225 DesiredAccess,
226 InheritHandle,
227 TargetHandle);
228
229 if (Options & DUPLICATE_CLOSE_SOURCE)
230 {
231 ZwClose(SourceHandle);
232 }
233
234 ObDereferenceObject(ObjectBody);
235 return(STATUS_SUCCESS);
236 }
237
238 /*
239 * @implemented
240 */
241 NTSTATUS STDCALL
242 NtDuplicateObject (IN HANDLE SourceProcessHandle,
243 IN HANDLE SourceHandle,
244 IN HANDLE TargetProcessHandle,
245 OUT PHANDLE UnsafeTargetHandle,
246 IN ACCESS_MASK DesiredAccess,
247 IN BOOLEAN InheritHandle,
248 ULONG Options)
249 /*
250 * FUNCTION: Copies a handle from one process space to another
251 * ARGUMENTS:
252 * SourceProcessHandle = The source process owning the handle. The
253 * source process should have opened
254 * the SourceHandle with PROCESS_DUP_HANDLE
255 * access.
256 * SourceHandle = The handle to the object.
257 * TargetProcessHandle = The destination process owning the handle
258 * TargetHandle (OUT) = Caller should supply storage for the
259 * duplicated handle.
260 * DesiredAccess = The desired access to the handle.
261 * InheritHandle = Indicates wheter the new handle will be inheritable
262 * or not.
263 * Options = Specifies special actions upon duplicating the handle.
264 * Can be one of the values DUPLICATE_CLOSE_SOURCE |
265 * DUPLICATE_SAME_ACCESS. DUPLICATE_CLOSE_SOURCE specifies
266 * that the source handle should be closed after duplicating.
267 * DUPLICATE_SAME_ACCESS specifies to ignore the
268 * DesiredAccess paramter and just grant the same access to
269 * the new handle.
270 * RETURNS: Status
271 * REMARKS: This function maps to the win32 DuplicateHandle.
272 */
273 {
274 PEPROCESS SourceProcess;
275 PEPROCESS TargetProcess;
276 PHANDLE_REP SourceHandleRep;
277 KIRQL oldIrql;
278 PVOID ObjectBody;
279 HANDLE TargetHandle;
280 NTSTATUS Status;
281
282 ASSERT_IRQL(PASSIVE_LEVEL);
283
284 Status = ObReferenceObjectByHandle(SourceProcessHandle,
285 PROCESS_DUP_HANDLE,
286 NULL,
287 UserMode,
288 (PVOID*)&SourceProcess,
289 NULL);
290 if (!NT_SUCCESS(Status))
291 {
292 return(Status);
293 }
294 Status = ObReferenceObjectByHandle(TargetProcessHandle,
295 PROCESS_DUP_HANDLE,
296 NULL,
297 UserMode,
298 (PVOID*)&TargetProcess,
299 NULL);
300 if (!NT_SUCCESS(Status))
301 {
302 ObDereferenceObject(SourceProcess);
303 return(Status);
304 }
305
306 /* Check for magic handle first */
307 if (SourceHandle == NtCurrentThread())
308 {
309 ObReferenceObjectByHandle(SourceHandle,
310 PROCESS_DUP_HANDLE,
311 NULL,
312 UserMode,
313 &ObjectBody,
314 NULL);
315
316 ObCreateHandle(TargetProcess,
317 ObjectBody,
318 THREAD_ALL_ACCESS,
319 InheritHandle,
320 &TargetHandle);
321 }
322 else
323 {
324 KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
325 SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
326 SourceHandle);
327 if (SourceHandleRep == NULL)
328 {
329 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
330 ObDereferenceObject(SourceProcess);
331 ObDereferenceObject(TargetProcess);
332 return(STATUS_INVALID_HANDLE);
333 }
334 ObjectBody = OB_ENTRY_TO_POINTER(SourceHandleRep->ObjectBody);
335 ObReferenceObjectByPointer(ObjectBody,
336 0,
337 NULL,
338 UserMode);
339
340 if (Options & DUPLICATE_SAME_ACCESS)
341 {
342 DesiredAccess = SourceHandleRep->GrantedAccess;
343 }
344
345 KeReleaseSpinLock(&SourceProcess->HandleTable.ListLock, oldIrql);
346 if (!((ULONG_PTR)SourceHandleRep->ObjectBody & OB_HANDLE_FLAG_INHERIT))
347 {
348 ObDereferenceObject(TargetProcess);
349 ObDereferenceObject(SourceProcess);
350 ObDereferenceObject(ObjectBody);
351 return STATUS_INVALID_HANDLE;
352 }
353 ObCreateHandle(TargetProcess,
354 ObjectBody,
355 DesiredAccess,
356 InheritHandle,
357 &TargetHandle);
358 }
359
360 if (Options & DUPLICATE_CLOSE_SOURCE)
361 {
362 ZwClose(SourceHandle);
363 }
364
365 ObDereferenceObject(TargetProcess);
366 ObDereferenceObject(SourceProcess);
367 ObDereferenceObject(ObjectBody);
368
369 Status = MmCopyToCaller(UnsafeTargetHandle, &TargetHandle, sizeof(HANDLE));
370 if (!NT_SUCCESS(Status))
371 {
372 return(Status);
373 }
374
375 return(STATUS_SUCCESS);
376 }
377
378 VOID ObCloseAllHandles(PEPROCESS Process)
379 {
380 KIRQL oldIrql;
381 PHANDLE_TABLE HandleTable;
382 PLIST_ENTRY current_entry;
383 PHANDLE_BLOCK current;
384 ULONG i;
385 PVOID ObjectBody;
386
387 DPRINT("ObCloseAllHandles(Process %x)\n", Process);
388
389 HandleTable = &Process->HandleTable;
390
391 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
392
393 current_entry = HandleTable->ListHead.Flink;
394
395 while (current_entry != &HandleTable->ListHead)
396 {
397 current = CONTAINING_RECORD(current_entry, HANDLE_BLOCK, entry);
398
399 for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++)
400 {
401 ObjectBody = OB_ENTRY_TO_POINTER(current->handles[i].ObjectBody);
402
403 if (ObjectBody != NULL)
404 {
405 POBJECT_HEADER Header = BODY_TO_HEADER(ObjectBody);
406
407 if (Header->ObjectType == PsProcessType ||
408 Header->ObjectType == PsThreadType)
409 {
410 DPRINT("Deleting handle to %x\n", ObjectBody);
411 }
412
413 ObReferenceObjectByPointer(ObjectBody,
414 0,
415 NULL,
416 UserMode);
417 InterlockedDecrement(&Header->HandleCount);
418 current->handles[i].ObjectBody = NULL;
419
420 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
421 if ((Header->ObjectType != NULL) &&
422 (Header->ObjectType->Close != NULL))
423 {
424 Header->ObjectType->Close(ObjectBody,
425 Header->HandleCount);
426 }
427
428 ObDereferenceObject(ObjectBody);
429 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
430 current_entry = &HandleTable->ListHead;
431 break;
432 }
433 }
434
435 current_entry = current_entry->Flink;
436 }
437 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
438 DPRINT("ObCloseAllHandles() finished\n");
439 DPRINT("Type %x\n", BODY_TO_HEADER(Process)->ObjectType);
440 }
441
442 VOID ObDeleteHandleTable(PEPROCESS Process)
443 /*
444 * FUNCTION: Deletes the handle table associated with a process
445 */
446 {
447 PLIST_ENTRY current = NULL;
448 PHANDLE_TABLE HandleTable = NULL;
449
450 ObCloseAllHandles(Process);
451
452 HandleTable = &Process->HandleTable;
453 current = RemoveHeadList(&HandleTable->ListHead);
454
455 while (current != &HandleTable->ListHead)
456 {
457 HANDLE_BLOCK* HandleBlock = CONTAINING_RECORD(current,
458 HANDLE_BLOCK,
459 entry);
460 DPRINT("Freeing %x\n", HandleBlock);
461 ExFreePool(HandleBlock);
462
463 current = RemoveHeadList(&HandleTable->ListHead);
464 }
465 }
466
467
468 VOID ObCreateHandleTable(PEPROCESS Parent,
469 BOOLEAN Inherit,
470 PEPROCESS Process)
471 /*
472 * FUNCTION: Creates a handle table for a process
473 * ARGUMENTS:
474 * Parent = Parent process (or NULL if this is the first process)
475 * Inherit = True if the process should inherit its parent's handles
476 * Process = Process whose handle table is to be created
477 */
478 {
479 PHANDLE_TABLE ParentHandleTable, HandleTable;
480 KIRQL oldIrql;
481 PLIST_ENTRY parent_current;
482 ULONG i;
483 PHANDLE_BLOCK current_block, new_block;
484
485 DPRINT("ObCreateHandleTable(Parent %x, Inherit %d, Process %x)\n",
486 Parent,Inherit,Process);
487
488 InitializeListHead(&(Process->HandleTable.ListHead));
489 KeInitializeSpinLock(&(Process->HandleTable.ListLock));
490
491 if (Parent != NULL)
492 {
493 ParentHandleTable = &Parent->HandleTable;
494 HandleTable = &Process->HandleTable;
495
496 KeAcquireSpinLock(&Parent->HandleTable.ListLock, &oldIrql);
497 KeAcquireSpinLockAtDpcLevel(&Process->HandleTable.ListLock);
498
499 parent_current = ParentHandleTable->ListHead.Flink;
500
501 while (parent_current != &ParentHandleTable->ListHead)
502 {
503 current_block = CONTAINING_RECORD(parent_current,
504 HANDLE_BLOCK,
505 entry);
506 new_block = ExAllocatePoolWithTag(NonPagedPool,
507 sizeof(HANDLE_BLOCK),
508 TAG_HANDLE_TABLE);
509 if (new_block == NULL)
510 {
511 break;
512 }
513 RtlZeroMemory(new_block, sizeof(HANDLE_BLOCK));
514
515 for (i=0; i<HANDLE_BLOCK_ENTRIES; i++)
516 {
517 if (current_block->handles[i].ObjectBody)
518 {
519 if ((ULONG_PTR)current_block->handles[i].ObjectBody & OB_HANDLE_FLAG_INHERIT)
520 {
521 new_block->handles[i].ObjectBody =
522 current_block->handles[i].ObjectBody;
523 new_block->handles[i].GrantedAccess =
524 current_block->handles[i].GrantedAccess;
525 InterlockedIncrement(&(BODY_TO_HEADER(OB_ENTRY_TO_POINTER(current_block->handles[i].ObjectBody))->HandleCount));
526 }
527 }
528 }
529 InsertTailList(&Process->HandleTable.ListHead, &new_block->entry);
530 parent_current = parent_current->Flink;
531 }
532 KeReleaseSpinLockFromDpcLevel(&Process->HandleTable.ListLock);
533 KeReleaseSpinLock(&Parent->HandleTable.ListLock, oldIrql);
534 }
535 }
536
537
538 NTSTATUS
539 ObDeleteHandle(PEPROCESS Process,
540 HANDLE Handle,
541 PVOID *ObjectBody)
542 {
543 PHANDLE_REP Rep;
544 PVOID Body;
545 KIRQL oldIrql;
546 PHANDLE_TABLE HandleTable;
547 POBJECT_HEADER Header;
548
549 DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
550
551 HandleTable = &Process->HandleTable;
552
553 KeAcquireSpinLock(&HandleTable->ListLock, &oldIrql);
554
555 Rep = ObpGetObjectByHandle(HandleTable, Handle);
556 if (Rep == NULL)
557 {
558 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
559 *ObjectBody = NULL;
560 return STATUS_INVALID_HANDLE;
561 }
562
563 if ((ULONG_PTR)Rep->ObjectBody & OB_HANDLE_FLAG_PROTECT)
564 {
565 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
566 *ObjectBody = NULL;
567 return STATUS_HANDLE_NOT_CLOSABLE;
568 }
569
570 Body = OB_ENTRY_TO_POINTER(Rep->ObjectBody);
571 DPRINT("ObjectBody %x\n", Body);
572 if (Body == NULL)
573 {
574 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
575 *ObjectBody = NULL;
576 return STATUS_UNSUCCESSFUL;
577 }
578
579 Header = BODY_TO_HEADER(Body);
580 ObReferenceObjectByPointer(Body,
581 0,
582 NULL,
583 UserMode);
584 InterlockedDecrement(&Header->HandleCount);
585 Rep->ObjectBody = NULL;
586
587 KeReleaseSpinLock(&HandleTable->ListLock, oldIrql);
588
589 if ((Header->ObjectType != NULL) &&
590 (Header->ObjectType->Close != NULL))
591 {
592 Header->ObjectType->Close(Body, Header->HandleCount);
593 }
594
595 *ObjectBody = Body;
596
597 DPRINT("Finished ObDeleteHandle()\n");
598
599 return STATUS_SUCCESS;
600 }
601
602
603 NTSTATUS ObCreateHandle(PEPROCESS Process,
604 PVOID ObjectBody,
605 ACCESS_MASK GrantedAccess,
606 BOOLEAN Inherit,
607 PHANDLE HandleReturn)
608 /*
609 * FUNCTION: Add a handle referencing an object
610 * ARGUMENTS:
611 * obj = Object body that the handle should refer to
612 * RETURNS: The created handle
613 * NOTE: The handle is valid only in the context of the current process
614 */
615 {
616 LIST_ENTRY* current;
617 unsigned int handle=1;
618 unsigned int i;
619 HANDLE_BLOCK* new_blk = NULL;
620 PHANDLE_TABLE HandleTable;
621 KIRQL oldlvl;
622
623 DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
624
625 assert(Process);
626
627 if (ObjectBody != NULL)
628 {
629 InterlockedIncrement(&(BODY_TO_HEADER(ObjectBody)->HandleCount));
630 }
631 HandleTable = &Process->HandleTable;
632 KeAcquireSpinLock(&HandleTable->ListLock, &oldlvl);
633 current = HandleTable->ListHead.Flink;
634 /*
635 * Scan through the currently allocated handle blocks looking for a free
636 * slot
637 */
638 while (current != (&HandleTable->ListHead))
639 {
640 HANDLE_BLOCK* blk = CONTAINING_RECORD(current,HANDLE_BLOCK,entry);
641
642 DPRINT("Current %x\n",current);
643
644 for (i=0;i<HANDLE_BLOCK_ENTRIES;i++)
645 {
646 DPRINT("Considering slot %d containing %x\n",i,blk->handles[i]);
647 if (blk->handles[i].ObjectBody == NULL)
648 {
649 blk->handles[i].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
650 if (Inherit)
651 blk->handles[i].ObjectBody = (PVOID)((ULONG_PTR)blk->handles[i].ObjectBody | OB_HANDLE_FLAG_INHERIT);
652 blk->handles[i].GrantedAccess = GrantedAccess;
653 KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
654 *HandleReturn = (HANDLE)((handle + i) << 2);
655 return(STATUS_SUCCESS);
656 }
657 }
658
659 handle = handle + HANDLE_BLOCK_ENTRIES;
660 current = current->Flink;
661 }
662
663 /*
664 * Add a new handle block to the end of the list
665 */
666 new_blk =
667 (HANDLE_BLOCK *)ExAllocatePoolWithTag(NonPagedPool,sizeof(HANDLE_BLOCK),
668 TAG_HANDLE_TABLE);
669 if (!new_blk)
670 {
671 *HandleReturn = (PHANDLE)NULL;
672 return(STATUS_INSUFFICIENT_RESOURCES);
673 }
674 RtlZeroMemory(new_blk,sizeof(HANDLE_BLOCK));
675 InsertTailList(&(Process->HandleTable.ListHead),
676 &new_blk->entry);
677 new_blk->handles[0].ObjectBody = OB_POINTER_TO_ENTRY(ObjectBody);
678 if (Inherit)
679 new_blk->handles[0].ObjectBody = (PVOID)((ULONG_PTR)new_blk->handles[0].ObjectBody | OB_HANDLE_FLAG_INHERIT);
680 new_blk->handles[0].GrantedAccess = GrantedAccess;
681 KeReleaseSpinLock(&HandleTable->ListLock, oldlvl);
682 *HandleReturn = (HANDLE)(handle << 2);
683 return(STATUS_SUCCESS);
684 }
685
686
687 /*
688 * @implemented
689 */
690 NTSTATUS STDCALL
691 ObQueryObjectAuditingByHandle(IN HANDLE Handle,
692 OUT PBOOLEAN GenerateOnClose)
693 {
694 PEPROCESS Process;
695 KIRQL oldIrql;
696 PHANDLE_REP HandleRep;
697
698 DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
699
700 Process = PsGetCurrentProcess();
701
702 KeAcquireSpinLock(&Process->HandleTable.ListLock, &oldIrql);
703 HandleRep = ObpGetObjectByHandle(&Process->HandleTable,
704 Handle);
705 if (HandleRep == NULL)
706 {
707 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
708 return STATUS_INVALID_HANDLE;
709 }
710
711 *GenerateOnClose = (BOOLEAN)((ULONG_PTR)HandleRep->ObjectBody | OB_HANDLE_FLAG_AUDIT);
712
713 KeReleaseSpinLock(&Process->HandleTable.ListLock, oldIrql);
714
715 return STATUS_SUCCESS;
716 }
717
718
719 /*
720 * @implemented
721 */
722 NTSTATUS STDCALL
723 ObReferenceObjectByHandle(HANDLE Handle,
724 ACCESS_MASK DesiredAccess,
725 POBJECT_TYPE ObjectType,
726 KPROCESSOR_MODE AccessMode,
727 PVOID* Object,
728 POBJECT_HANDLE_INFORMATION HandleInformation)
729 /*
730 * FUNCTION: Increments the reference count for an object and returns a
731 * pointer to its body
732 * ARGUMENTS:
733 * Handle = Handle for the object
734 * DesiredAccess = Desired access to the object
735 * ObjectType
736 * AccessMode
737 * Object (OUT) = Points to the object body on return
738 * HandleInformation (OUT) = Contains information about the handle
739 * on return
740 * RETURNS: Status
741 */
742 {
743 PHANDLE_REP HandleRep;
744 POBJECT_HEADER ObjectHeader;
745 KIRQL oldIrql;
746 PVOID ObjectBody;
747 ACCESS_MASK GrantedAccess;
748 ULONG Attributes;
749 NTSTATUS Status;
750
751 ASSERT_IRQL(PASSIVE_LEVEL);
752
753 DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, "
754 "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess,
755 ObjectType,AccessMode,Object);
756
757 /*
758 * Handle special handle names
759 */
760 if (Handle == NtCurrentProcess() &&
761 (ObjectType == PsProcessType || ObjectType == NULL))
762 {
763 DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
764
765 Status = ObReferenceObjectByPointer(PsGetCurrentProcess(),
766 PROCESS_ALL_ACCESS,
767 PsProcessType,
768 UserMode);
769 if (! NT_SUCCESS(Status))
770 {
771 return Status;
772 }
773
774 if (HandleInformation != NULL)
775 {
776 HandleInformation->HandleAttributes = 0; /* FIXME? */
777 HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
778 }
779
780 *Object = PsGetCurrentProcess();
781 DPRINT("Referencing current process %x\n", PsGetCurrentProcess());
782 return STATUS_SUCCESS;
783 }
784 else if (Handle == NtCurrentProcess())
785 {
786 CHECKPOINT;
787 return(STATUS_OBJECT_TYPE_MISMATCH);
788 }
789 if (Handle == NtCurrentThread() &&
790 (ObjectType == PsThreadType || ObjectType == NULL))
791 {
792 Status = ObReferenceObjectByPointer(PsGetCurrentThread(),
793 THREAD_ALL_ACCESS,
794 PsThreadType,
795 UserMode);
796 if (! NT_SUCCESS(Status))
797 {
798 return Status;
799 }
800
801 if (HandleInformation != NULL)
802 {
803 HandleInformation->HandleAttributes = 0; /* FIXME? */
804 HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
805 }
806
807 *Object = PsGetCurrentThread();
808 CHECKPOINT;
809 return STATUS_SUCCESS;
810 }
811 else if (Handle == NtCurrentThread())
812 {
813 CHECKPOINT;
814 return(STATUS_OBJECT_TYPE_MISMATCH);
815 }
816
817 KeAcquireSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
818 &oldIrql);
819 HandleRep = ObpGetObjectByHandle(&PsGetCurrentProcess()->HandleTable,
820 Handle);
821 if (HandleRep == NULL || HandleRep->ObjectBody == 0)
822 {
823 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
824 oldIrql);
825 return(STATUS_INVALID_HANDLE);
826 }
827 ObjectBody = OB_ENTRY_TO_POINTER(HandleRep->ObjectBody);
828 DPRINT("ObjectBody %p\n",ObjectBody);
829 ObjectHeader = BODY_TO_HEADER(ObjectBody);
830 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
831 ObReferenceObjectByPointer(ObjectBody,
832 0,
833 NULL,
834 UserMode);
835 Attributes = (ULONG_PTR)HandleRep->ObjectBody & OB_HANDLE_FLAG_MASK;
836 GrantedAccess = HandleRep->GrantedAccess;
837 KeReleaseSpinLock(&PsGetCurrentProcess()->HandleTable.ListLock,
838 oldIrql);
839
840 ObjectHeader = BODY_TO_HEADER(ObjectBody);
841 DPRINT("ObjectHeader->RefCount %lu\n",ObjectHeader->RefCount);
842
843 if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType)
844 {
845 CHECKPOINT;
846 return(STATUS_OBJECT_TYPE_MISMATCH);
847 }
848
849 if (ObjectHeader->ObjectType == PsProcessType)
850 {
851 DPRINT("Reference from %x\n", ((PULONG)&Handle)[-1]);
852 }
853
854 if (DesiredAccess && AccessMode == UserMode)
855 {
856 RtlMapGenericMask(&DesiredAccess, ObjectHeader->ObjectType->Mapping);
857
858 if (!(GrantedAccess & DesiredAccess) &&
859 !((~GrantedAccess) & DesiredAccess))
860 {
861 CHECKPOINT;
862 return(STATUS_ACCESS_DENIED);
863 }
864 }
865
866 if (HandleInformation != NULL)
867 {
868 HandleInformation->HandleAttributes = Attributes;
869 HandleInformation->GrantedAccess = GrantedAccess;
870 }
871
872 *Object = ObjectBody;
873
874 CHECKPOINT;
875 return(STATUS_SUCCESS);
876 }
877
878
879 /**********************************************************************
880 * NAME EXPORTED
881 * NtClose
882 *
883 * DESCRIPTION
884 * Closes a handle reference to an object.
885 *
886 * ARGUMENTS
887 * Handle
888 * Handle to close.
889 *
890 * RETURN VALUE
891 * Status.
892 *
893 * @implemented
894 */
895 NTSTATUS STDCALL
896 NtClose(IN HANDLE Handle)
897 {
898 PVOID ObjectBody;
899 POBJECT_HEADER Header;
900 NTSTATUS Status;
901
902 ASSERT_IRQL(PASSIVE_LEVEL);
903
904 DPRINT("NtClose(Handle %x)\n",Handle);
905
906 Status = ObDeleteHandle(PsGetCurrentProcess(),
907 Handle,
908 &ObjectBody);
909 if (!NT_SUCCESS(Status))
910 {
911 if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort)
912 KeRaiseUserException(Status);
913 return Status;
914 }
915
916 Header = BODY_TO_HEADER(ObjectBody);
917
918 DPRINT("Dereferencing %x\n", ObjectBody);
919 ObDereferenceObject(ObjectBody);
920
921 return(STATUS_SUCCESS);
922 }
923
924
925 /*
926 * @implemented
927 */
928 NTSTATUS STDCALL
929 ObInsertObject(IN PVOID Object,
930 IN PACCESS_STATE PassedAccessState OPTIONAL,
931 IN ACCESS_MASK DesiredAccess,
932 IN ULONG AdditionalReferences,
933 OUT PVOID* ReferencedObject OPTIONAL,
934 OUT PHANDLE Handle)
935 {
936 POBJECT_HEADER ObjectHeader;
937 ACCESS_MASK Access;
938
939 Access = DesiredAccess;
940 ObjectHeader = BODY_TO_HEADER(Object);
941
942 RtlMapGenericMask(&Access,
943 ObjectHeader->ObjectType->Mapping);
944
945 return(ObCreateHandle(PsGetCurrentProcess(),
946 Object,
947 Access,
948 ObjectHeader->Inherit,
949 Handle));
950 }
951
952 /* EOF */