rpcrt4: Fix NdrFullPointerQueryRefId to make more tests pass.
[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(unsigned long NumberOfPointers,
33                                                     XLAT_SIDE XlatSide)
34 {
35     unsigned long NumberOfBuckets = ((NumberOfPointers + 3) & 4) - 1;
36     PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables));
37
38     TRACE("(%ld, %d)\n", NumberOfPointers, XlatSide);
39
40     pXlatTables->RefIdToPointer.XlatTable =
41         HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
42             sizeof(void *) * NumberOfPointers);
43     pXlatTables->RefIdToPointer.StateTable =
44         HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
45             sizeof(unsigned char) * NumberOfPointers);
46     pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers;
47
48     TRACE("NumberOfBuckets = %ld\n", NumberOfBuckets);
49     pXlatTables->PointerToRefId.XlatTable =
50         HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
51             sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets);
52     pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets;
53     pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1;
54
55     pXlatTables->NextRefId = 1;
56     pXlatTables->XlatSide = XlatSide;
57
58     return pXlatTables;
59 }
60
61 void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
62 {
63     TRACE("(%p)\n", pXlatTables);
64
65     HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable);
66     HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
67     HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);
68
69     HeapFree(GetProcessHeap(), 0, pXlatTables);
70 }
71
72 static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, unsigned long RefId)
73 {
74     if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries)
75     {
76         pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2;
77         pXlatTables->RefIdToPointer.XlatTable =
78             HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
79                 pXlatTables->RefIdToPointer.XlatTable,
80                 sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries);
81         pXlatTables->RefIdToPointer.StateTable =
82             HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
83                 pXlatTables->RefIdToPointer.StateTable,
84                 sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries);
85
86         if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable)
87             pXlatTables->RefIdToPointer.NumberOfEntries = 0;
88     }
89 }
90
91 int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables,
92                                       void *pPointer, unsigned char QueryType,
93                                       unsigned long *pRefId )
94 {
95     unsigned long Hash = 0;
96     int i;
97     PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
98
99     TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId);
100
101     if (!pPointer)
102     {
103         *pRefId = 0;
104         return 1;
105     }
106
107     /* simple hashing algorithm, don't know whether it matches native */
108     for (i = 0; i < sizeof(pPointer); i++)
109         Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
110
111     XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
112     for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next)
113         if (pPointer == XlatTableEntry->Pointer)
114         {
115             *pRefId = XlatTableEntry->RefId;
116             if (pXlatTables->XlatSide == XLAT_SERVER)
117                 return XlatTableEntry->State;
118             else
119                 return 0;
120         }
121
122     XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
123     XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
124     XlatTableEntry->Pointer = pPointer;
125     XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++;
126     XlatTableEntry->State = QueryType;
127     pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
128
129     /* insert pointer into mapping table */
130     expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId);
131     if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId)
132     {
133         pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
134         pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType;
135     }
136
137     return 0;
138 }
139
140 int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
141                                     unsigned long RefId,
142                                     unsigned char QueryType, void **ppPointer)
143 {
144     TRACE("(%p, 0x%lx, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer);
145
146     expand_pointer_table_if_necessary(pXlatTables, RefId);
147
148     pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId);
149
150     if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
151     {
152         *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId];
153         if (QueryType)
154             return pXlatTables->RefIdToPointer.StateTable[RefId];
155         else
156             return 0;
157     }
158     *ppPointer = NULL;
159     return 0;
160 }
161
162 void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables,
163                                       unsigned long RefId, void *pPointer)
164 {
165     unsigned long Hash = 0;
166     int i;
167     PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry;
168
169     TRACE("(%p, 0x%lx, %p)\n", pXlatTables, RefId, pPointer);
170
171     /* simple hashing algorithm, don't know whether it matches native */
172     for (i = 0; i < sizeof(pPointer); i++)
173         Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i];
174
175     XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry));
176     XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask];
177     XlatTableEntry->Pointer = pPointer;
178     XlatTableEntry->RefId = RefId;
179     XlatTableEntry->State = 0;
180     pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry;
181
182     /* insert pointer into mapping table */
183     expand_pointer_table_if_necessary(pXlatTables, RefId);
184     if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId)
185         pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer;
186 }
187
188 int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer)
189 {
190     FIXME("(%p, %p)\n", pXlatTables, Pointer);
191
192     return 10;
193 }