[FREELDR]
[reactos.git] / dll / win32 / rpcrt4 / ndr_fullpointer.c
1 /*
2 * Full Pointer Translation Routines
3 *
4 * Copyright 2006 Robert Shearman
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "rpc.h"
26 #include "rpcndr.h"
27
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
31
32 PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers,
33 XLAT_SIDE XlatSide)
34 {
35 ULONG NumberOfBuckets;
36 PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables));
37
38 TRACE("(%d, %d)\n", NumberOfPointers, XlatSide);
39
40 if (!NumberOfPointers) NumberOfPointers = 512;
41 NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1;
42
43 pXlatTables->RefIdToPointer.XlatTable =
44 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
45 sizeof(void *) * NumberOfPointers);
46 pXlatTables->RefIdToPointer.StateTable =
47 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
48 sizeof(unsigned char) * NumberOfPointers);
49 pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers;
50
51 TRACE("NumberOfBuckets = %d\n", NumberOfBuckets);
52 pXlatTables->PointerToRefId.XlatTable =
53 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
54 sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets);
55 pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets;
56 pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1;
57
58 pXlatTables->NextRefId = 1;
59 pXlatTables->XlatSide = XlatSide;
60
61 return pXlatTables;
62 }
63
64 void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
65 {
66 ULONG i;
67
68 TRACE("(%p)\n", pXlatTables);
69
70 /* free the entries in the table */
71 for (i = 0; i < pXlatTables->PointerToRefId.NumberOfBuckets; i++)
72 {
73 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
74 for (XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[i];
75 XlatTableEntry; )
76 {
77 PFULL_PTR_TO_REFID_ELEMENT Next = XlatTableEntry->Next;
78 HeapFree(GetProcessHeap(), 0, XlatTableEntry);
79 XlatTableEntry = Next;
80 }
81 }
82
83 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable);
84 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
85 HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);
86
87 HeapFree(GetProcessHeap(), 0, pXlatTables);
88 }
89
90 static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId)
91 {
92 if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries)
93 {
94 pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2;
95 pXlatTables->RefIdToPointer.XlatTable =
96 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
97 pXlatTables->RefIdToPointer.XlatTable,
98 sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries);
99 pXlatTables->RefIdToPointer.StateTable =
100 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
101 pXlatTables->RefIdToPointer.StateTable,
102 sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries);
103
104 if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable)
105 pXlatTables->RefIdToPointer.NumberOfEntries = 0;
106 }
107 }
108
109 int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables,
110 void *pPointer, unsigned char QueryType,
111 ULONG *pRefId )
112 {
113 ULONG Hash = 0;
114 unsigned int i;
115 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
116
117 TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId);
118
119 if (!pPointer)
120 {
121 *pRefId = 0;
122 return 1;
123 }
124
125 /* simple hashing algorithm, don't know whether it matches native */
126 for (i = 0; i < sizeof(pPointer); i++)
127 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
128
129 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
130 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
131 if (pPointer == XlatTableEntry->Pointer)
132 {
133 *pRefId = XlatTableEntry->RefId;
134 if (XlatTableEntry->State & QueryType)
135 return 1;
136 XlatTableEntry->State |= QueryType;
137 return 0;
138 }
139
140 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
141 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
142 XlatTableEntry->Pointer = pPointer;
143 XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++;
144 XlatTableEntry->State = QueryType;
145 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
146
147 /* insert pointer into mapping table */
148 expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId);
149 if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId)
150 {
151 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
152 pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType;
153 }
154
155 return 0;
156 }
157
158 int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
159 ULONG RefId, unsigned char QueryType,
160 void **ppPointer)
161 {
162 TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer);
163
164 if (!RefId)
165 return 1;
166
167 expand_pointer_table_if_necessary(pXlatTables, RefId);
168
169 pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId);
170
171 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
172 {
173 *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
174 if (QueryType)
175 {
176 if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType)
177 return 1;
178 pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType;
179 return 0;
180 }
181 else
182 return 0;
183 }
184 *ppPointer = NULL;
185 return 0;
186 }
187
188 void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
189 ULONG RefId, void *pPointer)
190 {
191 ULONG Hash = 0;
192 unsigned int i;
193 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
194
195 TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer);
196
197 /* simple hashing algorithm, don't know whether it matches native */
198 for (i = 0; i < sizeof(pPointer); i++)
199 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
200
201 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
202 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
203 XlatTableEntry->Pointer = pPointer;
204 XlatTableEntry->RefId = RefId;
205 XlatTableEntry->State = 0;
206 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
207
208 /* insert pointer into mapping table */
209 expand_pointer_table_if_necessary(pXlatTables, RefId);
210 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
211 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
212 }
213
214 int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer)
215 {
216 ULONG Hash = 0;
217 unsigned int i;
218 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
219 ULONG RefId = 0;
220
221 TRACE("(%p, %p)\n", pXlatTables, Pointer);
222
223 if (!Pointer)
224 return 1;
225
226 /* simple hashing algorithm, don't know whether it matches native */
227 for (i = 0; i < sizeof(Pointer); i++)
228 Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i];
229
230 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
231 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
232 if (Pointer == XlatTableEntry->Pointer)
233 {
234 if (XlatTableEntry->State & 0x20)
235 return 0;
236 XlatTableEntry->State |= 0x20;
237 RefId = XlatTableEntry->RefId;
238 break;
239 }
240
241 if (!XlatTableEntry)
242 return 0;
243
244 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
245 {
246 pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20;
247 return 1;
248 }
249
250 return 0;
251 }