- Implemented CsrDuplicateHandleTable.
[reactos.git] / reactos / subsys / csrss / api / handle.c
1 /* $Id$
2 *
3 * reactos/subsys/csrss/api/handle.c
4 *
5 * CSRSS handle functions
6 *
7 * ReactOS Operating System
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <csrss.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS *****************************************************************/
18
19 static unsigned ObjectDefinitionsCount = 0;
20 static PCSRSS_OBJECT_DEFINITION ObjectDefinitions = NULL;
21
22 BOOL
23 CsrIsConsoleHandle(HANDLE Handle)
24 {
25 return ((((ULONG)Handle) & 0x10000003) == 0x3) ? TRUE : FALSE;
26 }
27
28
29 NTSTATUS FASTCALL
30 CsrRegisterObjectDefinitions(PCSRSS_OBJECT_DEFINITION NewDefinitions)
31 {
32 unsigned NewCount;
33 PCSRSS_OBJECT_DEFINITION Scan;
34 PCSRSS_OBJECT_DEFINITION New;
35
36 NewCount = 0;
37 for (Scan = NewDefinitions; 0 != Scan->Type; Scan++)
38 {
39 NewCount++;
40 }
41
42 New = RtlAllocateHeap(CsrssApiHeap, 0,
43 (ObjectDefinitionsCount + NewCount)
44 * sizeof(CSRSS_OBJECT_DEFINITION));
45 if (NULL == New)
46 {
47 DPRINT1("Unable to allocate memory\n");
48 return STATUS_NO_MEMORY;
49 }
50 if (0 != ObjectDefinitionsCount)
51 {
52 RtlCopyMemory(New, ObjectDefinitions,
53 ObjectDefinitionsCount * sizeof(CSRSS_OBJECT_DEFINITION));
54 RtlFreeHeap(CsrssApiHeap, 0, ObjectDefinitions);
55 }
56 RtlCopyMemory(New + ObjectDefinitionsCount, NewDefinitions,
57 NewCount * sizeof(CSRSS_OBJECT_DEFINITION));
58 ObjectDefinitions = New;
59 ObjectDefinitionsCount += NewCount;
60
61 return STATUS_SUCCESS;
62 }
63
64 NTSTATUS STDCALL CsrGetObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle, Object_t **Object )
65 {
66 ULONG h = (((ULONG)Handle) >> 2) - 1;
67 DPRINT("CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
68
69 if (ProcessData == NULL)
70 {
71 return STATUS_INVALID_PARAMETER;
72 }
73 if (!CsrIsConsoleHandle(Handle) || ProcessData->HandleTableSize <= h)
74 {
75 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
76 return STATUS_INVALID_HANDLE;
77 }
78 *Object = ProcessData->HandleTable[h];
79 // DbgPrint( "CsrGetObject returning\n" );
80 return *Object ? STATUS_SUCCESS : STATUS_INVALID_HANDLE;
81 }
82
83
84 NTSTATUS STDCALL
85 CsrReleaseObjectByPointer(Object_t *Object)
86 {
87 BOOL Found;
88 unsigned DefIndex;
89
90 /* dec ref count */
91 if (InterlockedDecrement(&Object->ReferenceCount) == 0)
92 {
93 Found = FALSE;
94 for (DefIndex = 0; ! Found && DefIndex < ObjectDefinitionsCount; DefIndex++)
95 {
96 if (Object->Type == ObjectDefinitions[DefIndex].Type)
97 {
98 (ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object);
99 Found = TRUE;
100 }
101 }
102
103 if (! Found)
104 {
105 DPRINT1("CSR: Error: releaseing unknown object type 0x%x", Object->Type);
106 }
107 }
108
109 return STATUS_SUCCESS;
110 }
111
112
113 NTSTATUS STDCALL
114 CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
115 HANDLE Handle)
116 {
117 ULONG h = (((ULONG)Handle) >> 2) - 1;
118 NTSTATUS Status;
119
120 if (ProcessData == NULL)
121 {
122 return STATUS_INVALID_PARAMETER;
123 }
124 if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize || ProcessData->HandleTable[h] == NULL)
125 {
126 return STATUS_INVALID_HANDLE;
127 }
128
129 Status = CsrReleaseObjectByPointer(ProcessData->HandleTable[h]);
130
131 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
132 ProcessData->HandleTable[h] = 0;
133 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
134 return Status;
135 }
136
137 NTSTATUS STDCALL CsrInsertObject( PCSRSS_PROCESS_DATA ProcessData, PHANDLE Handle, Object_t *Object )
138 {
139 ULONG i;
140 PVOID* Block;
141
142 if (ProcessData == NULL)
143 {
144 return STATUS_INVALID_PARAMETER;
145 }
146
147 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
148
149 for (i = 0; i < ProcessData->HandleTableSize; i++)
150 {
151 if (ProcessData->HandleTable[i] == NULL)
152 {
153 break;
154 }
155 }
156 if (i >= ProcessData->HandleTableSize)
157 {
158 Block = RtlAllocateHeap(CsrssApiHeap,
159 HEAP_ZERO_MEMORY,
160 (ProcessData->HandleTableSize + 64) * sizeof(HANDLE));
161 if (Block == NULL)
162 {
163 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
164 return(STATUS_UNSUCCESSFUL);
165 }
166 RtlCopyMemory(Block,
167 ProcessData->HandleTable,
168 ProcessData->HandleTableSize * sizeof(HANDLE));
169 Block = InterlockedExchangePointer(&ProcessData->HandleTable, Block);
170 RtlFreeHeap( CsrssApiHeap, 0, Block );
171 ProcessData->HandleTableSize += 64;
172 }
173 ProcessData->HandleTable[i] = Object;
174 *Handle = (HANDLE)(((i + 1) << 2) | 0x3);
175 InterlockedIncrement( &Object->ReferenceCount );
176 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
177 return(STATUS_SUCCESS);
178 }
179
180 NTSTATUS STDCALL CsrDuplicateHandleTable(PCSRSS_PROCESS_DATA SourceProcessData,
181 PCSRSS_PROCESS_DATA TargetProcessData)
182 {
183 ULONG i;
184
185 if (SourceProcessData == NULL ||
186 TargetProcessData == NULL ||
187 TargetProcessData->HandleTableSize)
188 {
189 return STATUS_INVALID_PARAMETER;
190 }
191
192 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
193
194 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
195
196 TargetProcessData->HandleTable = RtlAllocateHeap(CsrssApiHeap,
197 HEAP_ZERO_MEMORY,
198 SourceProcessData->HandleTableSize * sizeof(HANDLE));
199 if (TargetProcessData->HandleTable == NULL)
200 {
201 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
202 return(STATUS_UNSUCCESSFUL);
203 }
204 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
205 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
206 {
207 if (SourceProcessData->HandleTable[i])
208 {
209 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
210 InterlockedIncrement( &SourceProcessData->HandleTable[i]->ReferenceCount );
211 }
212 }
213 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
214 return(STATUS_SUCCESS);
215 }
216
217 NTSTATUS STDCALL CsrVerifyObject( PCSRSS_PROCESS_DATA ProcessData, HANDLE Handle )
218 {
219 ULONG h = (((ULONG)Handle) >> 2) - 1;
220
221 if (ProcessData == NULL)
222 {
223 return STATUS_INVALID_PARAMETER;
224 }
225 if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize)
226 {
227 return STATUS_INVALID_HANDLE;
228 }
229
230 return ProcessData->HandleTable[h] ? STATUS_SUCCESS : STATUS_INVALID_HANDLE;
231 }
232
233 /* EOF */