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