Sync with trunk r43000
[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 DPRINT("CsrGetObject, Object: %x, %x, %x\n", Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
82
83 DPRINT("CsrGetObject, Object: %x, %x, %x\n",
84 Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
85
86 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
87 if (!CsrIsConsoleHandle(Handle) || h >= ProcessData->HandleTableSize
88 || (*Object = ProcessData->HandleTable[h].Object) == NULL
89 || ~ProcessData->HandleTable[h].Access & Access)
90 {
91 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
92 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
93 return STATUS_INVALID_HANDLE;
94 }
95 _InterlockedIncrement(&(*Object)->ReferenceCount);
96 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
97 // DbgPrint( "CsrGetObject returning\n" );
98 return STATUS_SUCCESS;
99 }
100
101
102 NTSTATUS
103 WINAPI
104 CsrReleaseObjectByPointer(
105 Object_t *Object)
106 {
107 unsigned DefIndex;
108
109 /* dec ref count */
110 if (_InterlockedDecrement(&Object->ReferenceCount) == 0)
111 {
112 for (DefIndex = 0; DefIndex < ObjectDefinitionsCount; DefIndex++)
113 {
114 if (Object->Type == ObjectDefinitions[DefIndex].Type)
115 {
116 (ObjectDefinitions[DefIndex].CsrCleanupObjectProc)(Object);
117 return STATUS_SUCCESS;
118 }
119 }
120
121 DPRINT1("CSR: Error: releasing unknown object type 0x%x", Object->Type);
122 }
123
124 return STATUS_SUCCESS;
125 }
126
127
128 NTSTATUS
129 WINAPI
130 CsrReleaseObject(
131 PCSRSS_PROCESS_DATA ProcessData,
132 HANDLE Handle)
133 {
134 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
135 Object_t *Object;
136
137 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
138 if (h >= ProcessData->HandleTableSize
139 || (Object = ProcessData->HandleTable[h].Object) == NULL)
140 {
141 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
142 return STATUS_INVALID_HANDLE;
143 }
144 ProcessData->HandleTable[h].Object = NULL;
145 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
146
147 return CsrReleaseObjectByPointer(Object);
148 }
149
150 NTSTATUS
151 WINAPI
152 CsrInsertObject(
153 PCSRSS_PROCESS_DATA ProcessData,
154 PHANDLE Handle,
155 Object_t *Object,
156 DWORD Access,
157 BOOL Inheritable)
158 {
159 ULONG i;
160 PVOID* Block;
161
162 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
163
164 for (i = 0; i < ProcessData->HandleTableSize; i++)
165 {
166 if (ProcessData->HandleTable[i].Object == NULL)
167 {
168 break;
169 }
170 }
171 if (i >= ProcessData->HandleTableSize)
172 {
173 Block = RtlAllocateHeap(CsrssApiHeap,
174 HEAP_ZERO_MEMORY,
175 (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
176 if (Block == NULL)
177 {
178 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
179 return(STATUS_UNSUCCESSFUL);
180 }
181 RtlCopyMemory(Block,
182 ProcessData->HandleTable,
183 ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
184 Block = _InterlockedExchangePointer((void* volatile)&ProcessData->HandleTable, Block);
185 RtlFreeHeap( CsrssApiHeap, 0, Block );
186 ProcessData->HandleTableSize += 64;
187 }
188 ProcessData->HandleTable[i].Object = Object;
189 ProcessData->HandleTable[i].Access = Access;
190 ProcessData->HandleTable[i].Inheritable = Inheritable;
191 *Handle = (HANDLE)((i << 2) | 0x3);
192 _InterlockedIncrement( &Object->ReferenceCount );
193 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
194 return(STATUS_SUCCESS);
195 }
196
197 NTSTATUS
198 WINAPI
199 CsrDuplicateHandleTable(
200 PCSRSS_PROCESS_DATA SourceProcessData,
201 PCSRSS_PROCESS_DATA TargetProcessData)
202 {
203 ULONG i;
204
205 if (TargetProcessData->HandleTableSize)
206 {
207 return STATUS_INVALID_PARAMETER;
208 }
209
210 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
211
212 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
213
214 TargetProcessData->HandleTable = RtlAllocateHeap(CsrssApiHeap,
215 HEAP_ZERO_MEMORY,
216 SourceProcessData->HandleTableSize
217 * sizeof(CSRSS_HANDLE));
218 if (TargetProcessData->HandleTable == NULL)
219 {
220 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
221 return(STATUS_UNSUCCESSFUL);
222 }
223 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
224 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
225 {
226 if (SourceProcessData->HandleTable[i].Object != NULL &&
227 SourceProcessData->HandleTable[i].Inheritable)
228 {
229 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
230 _InterlockedIncrement( &SourceProcessData->HandleTable[i].Object->ReferenceCount );
231 }
232 }
233 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
234 return(STATUS_SUCCESS);
235 }
236
237 NTSTATUS
238 WINAPI
239 CsrVerifyObject(
240 PCSRSS_PROCESS_DATA ProcessData,
241 HANDLE Handle)
242 {
243 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
244
245 if (h >= ProcessData->HandleTableSize ||
246 ProcessData->HandleTable[h].Object == NULL)
247 {
248 return STATUS_INVALID_HANDLE;
249 }
250
251 return STATUS_SUCCESS;
252 }
253
254 /* EOF */