* Sync up to trunk HEAD (r62975).
[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 "precomp.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
24
25 PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers,
26 XLAT_SIDE XlatSide)
27 {
28 ULONG NumberOfBuckets;
29 PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables));
30
31 TRACE("(%d, %d)\n", NumberOfPointers, XlatSide);
32
33 if (!NumberOfPointers) NumberOfPointers = 512;
34 NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1;
35
36 pXlatTables->RefIdToPointer.XlatTable =
37 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
38 sizeof(void *) * NumberOfPointers);
39 pXlatTables->RefIdToPointer.StateTable =
40 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
41 sizeof(unsigned char) * NumberOfPointers);
42 pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers;
43
44 TRACE("NumberOfBuckets = %d\n", NumberOfBuckets);
45 pXlatTables->PointerToRefId.XlatTable =
46 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
47 sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets);
48 pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets;
49 pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1;
50
51 pXlatTables->NextRefId = 1;
52 pXlatTables->XlatSide = XlatSide;
53
54 return pXlatTables;
55 }
56
57 void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
58 {
59 ULONG i;
60
61 TRACE("(%p)\n", pXlatTables);
62
63 /* free the entries in the table */
64 for (i = 0; i < pXlatTables->PointerToRefId.NumberOfBuckets; i++)
65 {
66 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
67 for (XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[i];
68 XlatTableEntry; )
69 {
70 PFULL_PTR_TO_REFID_ELEMENT Next = XlatTableEntry->Next;
71 HeapFree(GetProcessHeap(), 0, XlatTableEntry);
72 XlatTableEntry = Next;
73 }
74 }
75
76 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable);
77 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
78 HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);
79
80 HeapFree(GetProcessHeap(), 0, pXlatTables);
81 }
82
83 static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId)
84 {
85 if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries)
86 {
87 pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2;
88 pXlatTables->RefIdToPointer.XlatTable =
89 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
90 pXlatTables->RefIdToPointer.XlatTable,
91 sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries);
92 pXlatTables->RefIdToPointer.StateTable =
93 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
94 pXlatTables->RefIdToPointer.StateTable,
95 sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries);
96
97 if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable)
98 pXlatTables->RefIdToPointer.NumberOfEntries = 0;
99 }
100 }
101
102 int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables,
103 void *pPointer, unsigned char QueryType,
104 ULONG *pRefId )
105 {
106 ULONG Hash = 0;
107 unsigned int i;
108 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
109
110 TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId);
111
112 if (!pPointer)
113 {
114 *pRefId = 0;
115 return 1;
116 }
117
118 /* simple hashing algorithm, don't know whether it matches native */
119 for (i = 0; i < sizeof(pPointer); i++)
120 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
121
122 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
123 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
124 if (pPointer == XlatTableEntry->Pointer)
125 {
126 *pRefId = XlatTableEntry->RefId;
127 if (XlatTableEntry->State & QueryType)
128 return 1;
129 XlatTableEntry->State |= QueryType;
130 return 0;
131 }
132
133 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
134 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
135 XlatTableEntry->Pointer = pPointer;
136 XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++;
137 XlatTableEntry->State = QueryType;
138 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
139
140 /* insert pointer into mapping table */
141 expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId);
142 if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId)
143 {
144 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
145 pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType;
146 }
147
148 return 0;
149 }
150
151 int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
152 ULONG RefId, unsigned char QueryType,
153 void **ppPointer)
154 {
155 TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer);
156
157 if (!RefId)
158 return 1;
159
160 expand_pointer_table_if_necessary(pXlatTables, RefId);
161
162 pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId);
163
164 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
165 {
166 *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
167 if (QueryType)
168 {
169 if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType)
170 return 1;
171 pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType;
172 return 0;
173 }
174 else
175 return 0;
176 }
177 *ppPointer = NULL;
178 return 0;
179 }
180
181 void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
182 ULONG RefId, void *pPointer)
183 {
184 ULONG Hash = 0;
185 unsigned int i;
186 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
187
188 TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer);
189
190 /* simple hashing algorithm, don't know whether it matches native */
191 for (i = 0; i < sizeof(pPointer); i++)
192 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
193
194 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
195 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
196 XlatTableEntry->Pointer = pPointer;
197 XlatTableEntry->RefId = RefId;
198 XlatTableEntry->State = 0;
199 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
200
201 /* insert pointer into mapping table */
202 expand_pointer_table_if_necessary(pXlatTables, RefId);
203 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
204 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
205 }
206
207 int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer)
208 {
209 ULONG Hash = 0;
210 unsigned int i;
211 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
212 ULONG RefId = 0;
213
214 TRACE("(%p, %p)\n", pXlatTables, Pointer);
215
216 if (!Pointer)
217 return 1;
218
219 /* simple hashing algorithm, don't know whether it matches native */
220 for (i = 0; i < sizeof(Pointer); i++)
221 Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i];
222
223 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
224 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
225 if (Pointer == XlatTableEntry->Pointer)
226 {
227 if (XlatTableEntry->State & 0x20)
228 return 0;
229 XlatTableEntry->State |= 0x20;
230 RefId = XlatTableEntry->RefId;
231 break;
232 }
233
234 if (!XlatTableEntry)
235 return 0;
236
237 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
238 {
239 pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20;
240 return 1;
241 }
242
243 return 0;
244 }