[NTOS]: No good deed goes unpunished. Continuing the novel/saga from a couple of...
[reactos.git] / reactos / subsystems / win32 / 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 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 CsrInsertObject(
152 PCSRSS_PROCESS_DATA ProcessData,
153 PHANDLE Handle,
154 Object_t *Object,
155 DWORD Access,
156 BOOL Inheritable)
157 {
158 ULONG i;
159 PVOID* Block;
160
161 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
162
163 for (i = 0; i < ProcessData->HandleTableSize; i++)
164 {
165 if (ProcessData->HandleTable[i].Object == NULL)
166 {
167 break;
168 }
169 }
170 if (i >= ProcessData->HandleTableSize)
171 {
172 Block = RtlAllocateHeap(CsrssApiHeap,
173 HEAP_ZERO_MEMORY,
174 (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
175 if (Block == NULL)
176 {
177 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
178 return(STATUS_UNSUCCESSFUL);
179 }
180 RtlCopyMemory(Block,
181 ProcessData->HandleTable,
182 ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
183 Block = _InterlockedExchangePointer((void* volatile)&ProcessData->HandleTable, Block);
184 RtlFreeHeap( CsrssApiHeap, 0, Block );
185 ProcessData->HandleTableSize += 64;
186 }
187 ProcessData->HandleTable[i].Object = Object;
188 ProcessData->HandleTable[i].Access = Access;
189 ProcessData->HandleTable[i].Inheritable = Inheritable;
190 *Handle = UlongToHandle((i << 2) | 0x3);
191 _InterlockedIncrement( &Object->ReferenceCount );
192 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
193 return(STATUS_SUCCESS);
194 }
195
196 NTSTATUS
197 WINAPI
198 CsrDuplicateHandleTable(
199 PCSRSS_PROCESS_DATA SourceProcessData,
200 PCSRSS_PROCESS_DATA TargetProcessData)
201 {
202 ULONG i;
203
204 if (TargetProcessData->HandleTableSize)
205 {
206 return STATUS_INVALID_PARAMETER;
207 }
208
209 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
210
211 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
212
213 TargetProcessData->HandleTable = RtlAllocateHeap(CsrssApiHeap,
214 HEAP_ZERO_MEMORY,
215 SourceProcessData->HandleTableSize
216 * sizeof(CSRSS_HANDLE));
217 if (TargetProcessData->HandleTable == NULL)
218 {
219 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
220 return(STATUS_UNSUCCESSFUL);
221 }
222 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
223 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
224 {
225 if (SourceProcessData->HandleTable[i].Object != NULL &&
226 SourceProcessData->HandleTable[i].Inheritable)
227 {
228 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
229 _InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount );
230 }
231 }
232 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
233 return(STATUS_SUCCESS);
234 }
235
236 NTSTATUS
237 WINAPI
238 CsrVerifyObject(
239 PCSRSS_PROCESS_DATA ProcessData,
240 HANDLE Handle)
241 {
242 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
243
244 if (h >= ProcessData->HandleTableSize ||
245 ProcessData->HandleTable[h].Object == NULL)
246 {
247 return STATUS_INVALID_HANDLE;
248 }
249
250 return STATUS_SUCCESS;
251 }
252
253 /* EOF */