msvcrt: Added _set_fmode and _get_fmode implementation.
[wine] / dlls / 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 }