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