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 } 252