urlmon: Improve ObtainUserAgentString conformance to native.
[wine.git] / dlls / rpcrt4 / ndr_fullpointer.c
blob5640769783dff69997f53296b0bba1da0a20a13f
1 /*
2 * Full Pointer Translation Routines
4 * Copyright 2006 Robert Shearman
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.
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.
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "rpc.h"
26 #include "rpcndr.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
32 PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers,
33 XLAT_SIDE XlatSide)
35 ULONG NumberOfBuckets;
36 PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables));
38 TRACE("(%d, %d)\n", NumberOfPointers, XlatSide);
40 if (!NumberOfPointers) NumberOfPointers = 512;
41 NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1;
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;
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;
58 pXlatTables->NextRefId = 1;
59 pXlatTables->XlatSide = XlatSide;
61 return pXlatTables;
64 void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
66 TRACE("(%p)\n", pXlatTables);
68 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable);
69 HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
70 HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);
72 HeapFree(GetProcessHeap(), 0, pXlatTables);
75 static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId)
77 if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries)
79 pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2;
80 pXlatTables->RefIdToPointer.XlatTable =
81 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
82 pXlatTables->RefIdToPointer.XlatTable,
83 sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries);
84 pXlatTables->RefIdToPointer.StateTable =
85 HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
86 pXlatTables->RefIdToPointer.StateTable,
87 sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries);
89 if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable)
90 pXlatTables->RefIdToPointer.NumberOfEntries = 0;
94 int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables,
95 void *pPointer, unsigned char QueryType,
96 ULONG *pRefId )
98 ULONG Hash = 0;
99 int i;
100 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
102 TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId);
104 if (!pPointer)
106 *pRefId = 0;
107 return 1;
110 /* simple hashing algorithm, don't know whether it matches native */
111 for (i = 0; i < sizeof(pPointer); i++)
112 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
114 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
115 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
116 if (pPointer == XlatTableEntry->Pointer)
118 *pRefId = XlatTableEntry->RefId;
119 if (XlatTableEntry->State & QueryType)
120 return 1;
121 XlatTableEntry->State |= QueryType;
122 return 0;
125 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
126 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
127 XlatTableEntry->Pointer = pPointer;
128 XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++;
129 XlatTableEntry->State = QueryType;
130 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
132 /* insert pointer into mapping table */
133 expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId);
134 if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId)
136 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
137 pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType;
140 return 0;
143 int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
144 ULONG RefId, unsigned char QueryType,
145 void **ppPointer)
147 TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer);
149 expand_pointer_table_if_necessary(pXlatTables, RefId);
151 pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId);
153 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
155 *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
156 if (QueryType)
158 if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType)
159 return 1;
160 pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType;
161 return 0;
163 else
164 return 0;
166 *ppPointer = NULL;
167 return 0;
170 void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
171 ULONG RefId, void *pPointer)
173 ULONG Hash = 0;
174 int i;
175 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
177 TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer);
179 /* simple hashing algorithm, don't know whether it matches native */
180 for (i = 0; i < sizeof(pPointer); i++)
181 Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
183 XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
184 XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
185 XlatTableEntry->Pointer = pPointer;
186 XlatTableEntry->RefId = RefId;
187 XlatTableEntry->State = 0;
188 pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
190 /* insert pointer into mapping table */
191 expand_pointer_table_if_necessary(pXlatTables, RefId);
192 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
193 pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
196 int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer)
198 ULONG Hash = 0;
199 int i;
200 PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
201 ULONG RefId = 0;
203 TRACE("(%p, %p)\n", pXlatTables, Pointer);
205 if (!Pointer)
206 return 1;
208 /* simple hashing algorithm, don't know whether it matches native */
209 for (i = 0; i < sizeof(Pointer); i++)
210 Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i];
212 XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
213 for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
214 if (Pointer == XlatTableEntry->Pointer)
216 if (XlatTableEntry->State & 0x20)
217 return 0;
218 XlatTableEntry->State |= 0x20;
219 RefId = XlatTableEntry->RefId;
220 break;
223 if (!XlatTableEntry)
224 return 0;
226 if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
228 pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20;
229 return 1;
232 return 0;