xref: /reactos/dll/win32/rpcrt4/ndr_fullpointer.c (revision c2c66aff)
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 }
245