6567f896c12616b08c9dbf85d4b337529788bfd0
[reactos.git] / reactos / subsystems / win32 / csrss / csrsrv / 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 <srv.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 static
23 BOOL
24 CsrIsConsoleHandle(HANDLE Handle)
25 {
26 return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
27 }
28
29
30 NTSTATUS
31 FASTCALL
32 CsrRegisterObjectDefinitions(
33 PCSRSS_OBJECT_DEFINITION NewDefinitions)
34 {
35 unsigned NewCount;
36 PCSRSS_OBJECT_DEFINITION Scan;
37 PCSRSS_OBJECT_DEFINITION New;
38
39 NewCount = 0;
40 for (Scan = NewDefinitions; 0 != Scan->Type; Scan++)
41 {
42 NewCount++;
43 }
44
45 New = RtlAllocateHeap(CsrssApiHeap,
46 0,
47 (ObjectDefinitionsCount + NewCount)
48 * sizeof(CSRSS_OBJECT_DEFINITION));
49 if (NULL == New)
50 {
51 DPRINT1("Unable to allocate memory\n");
52 return STATUS_NO_MEMORY;
53 }
54
55 if (0 != ObjectDefinitionsCount)
56 {
57 RtlCopyMemory(New,
58 ObjectDefinitions,
59 ObjectDefinitionsCount * sizeof(CSRSS_OBJECT_DEFINITION));
60 RtlFreeHeap(CsrssApiHeap, 0, ObjectDefinitions);
61 }
62
63 RtlCopyMemory(New + ObjectDefinitionsCount,
64 NewDefinitions,
65 NewCount * sizeof(CSRSS_OBJECT_DEFINITION));
66 ObjectDefinitions = New;
67 ObjectDefinitionsCount += NewCount;
68
69 return STATUS_SUCCESS;
70 }
71
72 NTSTATUS
73 WINAPI
74 CsrGetObject(
75 PCSRSS_PROCESS_DATA ProcessData,
76 HANDLE Handle,
77 Object_t **Object,
78 DWORD Access )
79 {
80 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
81
82 DPRINT("CsrGetObject, Object: %x, %x, %x\n",
83 Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
84
85 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
86 if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
87 || (*Object = ProcessData->HandleTable[h].Object) == NULL
88 || ~ProcessData->HandleTable[h].Access & Access)
89 {
90 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
91 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
92 return STATUS_INVALID_HANDLE;
93 }
94 _InterlockedIncrement(&(*Object)->ReferenceCount);
95 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
96 // DbgPrint( "CsrGetObject returning\n" );
97 return STATUS_SUCCESS;
98 }
99
100
101 NTSTATUS
102 WINAPI
103 CsrReleaseObjectByPointer(
104 Object_t *Object)
105 {
106 unsigned DefIndex;
107
108 /* dec ref count */
109 if (_InterlockedDecrement(&Object->ReferenceCount) == 0)
110 {
111 for (DefIndex = 0; DefIndex < ObjectDefinitionsCount; DefIndex++)
112 {
113 if (Object->Type == ObjectDefinitions[DefIndex].Type)
114 {
115 (ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object);
116 return STATUS_SUCCESS;
117 }
118 }
119
120 DPRINT1("CSR: Error: releasing unknown object type 0x%x", Object->Type);
121 }
122
123 return STATUS_SUCCESS;
124 }
125
126
127 NTSTATUS
128 WINAPI
129 CsrReleaseObject(
130 PCSRSS_PROCESS_DATA ProcessData,
131 HANDLE Handle)
132 {
133 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
134 Object_t *Object;
135
136 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
137 if (h >= ProcessData->HandleTableSize
138 || (Object = ProcessData->HandleTable[h].Object) == NULL)
139 {
140 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
141 return STATUS_INVALID_HANDLE;
142 }
143 ProcessData->HandleTable[h].Object = NULL;
144 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
145
146 return CsrReleaseObjectByPointer(Object);
147 }
148
149 NTSTATUS
150 WINAPI
151 CsrReleaseConsole(
152 PCSRSS_PROCESS_DATA ProcessData)
153 {
154 ULONG HandleTableSize;
155 PCSRSS_HANDLE HandleTable;
156 PCSRSS_CONSOLE Console;
157 ULONG i;
158
159 /* Close all console handles and detach process from console */
160 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
161 HandleTableSize = ProcessData->HandleTableSize;
162 HandleTable = ProcessData->HandleTable;
163 Console = ProcessData->Console;
164 ProcessData->HandleTableSize = 0;
165 ProcessData->HandleTable = NULL;
166 ProcessData->Console = NULL;
167 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
168
169 for (i = 0; i < HandleTableSize; i++)
170 {
171 if (HandleTable[i].Object != NULL)
172 CsrReleaseObjectByPointer(HandleTable[i].Object);
173 }
174 RtlFreeHeap(CsrssApiHeap, 0, HandleTable);
175
176 if (Console != NULL)
177 {
178 RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)&Console->Header.Lock);
179 RemoveEntryList(&ProcessData->ProcessEntry);
180 RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)&Console->Header.Lock);
181 CsrReleaseObjectByPointer(&Console->Header);
182 return STATUS_SUCCESS;
183 }
184
185 return STATUS_INVALID_PARAMETER;
186 }
187
188 NTSTATUS
189 WINAPI
190 CsrInsertObject(
191 PCSRSS_PROCESS_DATA ProcessData,
192 PHANDLE Handle,
193 Object_t *Object,
194 DWORD Access,
195 BOOL Inheritable)
196 {
197 ULONG i;
198 PVOID* Block;
199
200 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
201
202 for (i = 0; i < ProcessData->HandleTableSize; i++)
203 {
204 if (ProcessData->HandleTable[i].Object == NULL)
205 {
206 break;
207 }
208 }
209 if (i >= ProcessData->HandleTableSize)
210 {
211 Block = RtlAllocateHeap(CsrssApiHeap,
212 HEAP_ZERO_MEMORY,
213 (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
214 if (Block == NULL)
215 {
216 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
217 return(STATUS_UNSUCCESSFUL);
218 }
219 RtlCopyMemory(Block,
220 ProcessData->HandleTable,
221 ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
222 Block = _InterlockedExchangePointer((void* volatile)&ProcessData->HandleTable, Block);
223 RtlFreeHeap( CsrssApiHeap, 0, Block );
224 ProcessData->HandleTableSize += 64;
225 }
226 ProcessData->HandleTable[i].Object = Object;
227 ProcessData->HandleTable[i].Access = Access;
228 ProcessData->HandleTable[i].Inheritable = Inheritable;
229 *Handle = UlongToHandle((i << 2) | 0x3);
230 _InterlockedIncrement( &Object->ReferenceCount );
231 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
232 return(STATUS_SUCCESS);
233 }
234
235 NTSTATUS
236 WINAPI
237 CsrDuplicateHandleTable(
238 PCSRSS_PROCESS_DATA SourceProcessData,
239 PCSRSS_PROCESS_DATA TargetProcessData)
240 {
241 ULONG i;
242
243 if (TargetProcessData->HandleTableSize)
244 {
245 return STATUS_INVALID_PARAMETER;
246 }
247
248 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
249
250 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
251
252 TargetProcessData->HandleTable = RtlAllocateHeap(CsrssApiHeap,
253 HEAP_ZERO_MEMORY,
254 SourceProcessData->HandleTableSize
255 * sizeof(CSRSS_HANDLE));
256 if (TargetProcessData->HandleTable == NULL)
257 {
258 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
259 return(STATUS_UNSUCCESSFUL);
260 }
261 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
262 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
263 {
264 if (SourceProcessData->HandleTable[i].Object != NULL &&
265 SourceProcessData->HandleTable[i].Inheritable)
266 {
267 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
268 _InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount );
269 }
270 }
271 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
272 return(STATUS_SUCCESS);
273 }
274
275 NTSTATUS
276 WINAPI
277 CsrVerifyObject(
278 PCSRSS_PROCESS_DATA ProcessData,
279 HANDLE Handle)
280 {
281 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
282
283 if (h >= ProcessData->HandleTableSize ||
284 ProcessData->HandleTable[h].Object == NULL)
285 {
286 return STATUS_INVALID_HANDLE;
287 }
288
289 return STATUS_SUCCESS;
290 }
291
292 /* EOF */