diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index fc366092185..d27d75e88ca 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -13,6 +13,7 @@ C_SRCS = \ cproxy.c \ cpsf.c \ cstub.c \ + ndr_fullpointer.c \ ndr_marshall.c \ ndr_midl.c \ ndr_ole.c \ diff --git a/dlls/rpcrt4/ndr_fullpointer.c b/dlls/rpcrt4/ndr_fullpointer.c new file mode 100644 index 00000000000..f88c29982bd --- /dev/null +++ b/dlls/rpcrt4/ndr_fullpointer.c @@ -0,0 +1,159 @@ +/* + * Full Pointer Translation Routines + * + * Copyright 2006 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(unsigned long NumberOfPointers, + XLAT_SIDE XlatSide) +{ + unsigned long NumberOfBuckets = ((NumberOfPointers + 3) & 4) - 1; + PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables)); + + TRACE("(%ld, %d)\n", NumberOfPointers, XlatSide); + + pXlatTables->RefIdToPointer.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(void *) * NumberOfPointers); + pXlatTables->RefIdToPointer.StateTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(unsigned char) * NumberOfPointers); + pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers; + + TRACE("NumberOfBuckets = %ld\n", NumberOfBuckets); + pXlatTables->PointerToRefId.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets); + pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets; + pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1; + + pXlatTables->NextRefId = 1; + pXlatTables->XlatSide = XlatSide; + + return pXlatTables; +} + +void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) +{ + TRACE("(%p)\n", pXlatTables); + + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); + + HeapFree(GetProcessHeap(), 0, pXlatTables); +} + +static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, unsigned long RefId) +{ + if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries) + { + pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2; + pXlatTables->RefIdToPointer.XlatTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.XlatTable, + sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries); + pXlatTables->RefIdToPointer.StateTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.StateTable, + sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries); + + if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable) + pXlatTables->RefIdToPointer.NumberOfEntries = 0; + } +} + +int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables, + void *pPointer, unsigned char QueryType, + unsigned long *pRefId ) +{ + unsigned long Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + + TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId); + + if (!pPointer) + { + *pRefId = 0; + return 1; + } + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(pPointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; + + TRACE("pXlatTables->PointerToRefId.XlatTable = %p\n", pXlatTables->PointerToRefId.XlatTable); + TRACE("Hash = 0x%lx, pXlatTables->PointerToRefId.HashMask = 0x%lx\n", Hash, pXlatTables->PointerToRefId.HashMask); + XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) + if (pPointer == XlatTableEntry->Pointer) + { + *pRefId = XlatTableEntry->RefId; + if (pXlatTables->XlatSide == XLAT_SERVER) + return XlatTableEntry->State; + else + return 0; + } + + XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); + XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + XlatTableEntry->Pointer = pPointer; + XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++; + XlatTableEntry->State = QueryType; + pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; + + /* FIXME: insert pointer into mapping table */ + + return 0; +} + +int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + unsigned long RefId, + unsigned char QueryType, void **ppPointer) +{ + TRACE("(%p, 0x%lx, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); + + expand_pointer_table_if_necessary(pXlatTables, RefId); + + *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId]; + return 0; +} + +void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + unsigned long RefId, void *pPointer) +{ + FIXME("(%p, 0x%lx, %p)\n", pXlatTables, RefId, pPointer); +} + +int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer) +{ + FIXME("(%p, %p)\n", pXlatTables, Pointer); + + return 10; +} diff --git a/dlls/rpcrt4/rpcrt4.spec b/dlls/rpcrt4/rpcrt4.spec index 2a76670b447..84433f141c2 100644 --- a/dlls/rpcrt4/rpcrt4.spec +++ b/dlls/rpcrt4/rpcrt4.spec @@ -221,12 +221,12 @@ @ stdcall NdrFixedArrayMemorySize(ptr ptr) @ stdcall NdrFixedArrayUnmarshall(ptr ptr ptr long) @ stdcall NdrFreeBuffer(ptr) -@ stub NdrFullPointerFree -@ stub NdrFullPointerInsertRefId -@ stub NdrFullPointerQueryPointer -@ stub NdrFullPointerQueryRefId -@ stub NdrFullPointerXlatFree -@ stub NdrFullPointerXlatInit +@ stdcall NdrFullPointerFree(ptr ptr) +@ stdcall NdrFullPointerInsertRefId(ptr long ptr) +@ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) +@ stdcall NdrFullPointerQueryRefId(ptr long long ptr) +@ stdcall NdrFullPointerXlatFree(ptr) +@ stdcall NdrFullPointerXlatInit(long long) @ stdcall NdrGetBuffer(ptr long ptr) @ stub NdrGetDcomProtocolVersion @ stub NdrGetPartialBuffer diff --git a/dlls/rpcrt4/tests/ndr_marshall.c b/dlls/rpcrt4/tests/ndr_marshall.c index 817f4d8c6ae..26fcdb6270e 100644 --- a/dlls/rpcrt4/tests/ndr_marshall.c +++ b/dlls/rpcrt4/tests/ndr_marshall.c @@ -689,8 +689,130 @@ static void test_simple_struct(void) #endif } +static void test_fullpointer_xlat(void) +{ + PFULL_PTR_XLAT_TABLES pXlatTables; + unsigned long RefId; + int ret; + void *Pointer; + + pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT); + + /* "marshaling" phase */ + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%lx\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%lx\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%lx\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%lx\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0, "RefId should be 0 instead of 0x%lx\n", RefId); + + /* "unmarshaling" phase */ + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + todo_wine { + ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer); + } + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); + + NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + todo_wine { + ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer); + } + + NdrFullPointerXlatFree(pXlatTables); + + pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER); + + /* "unmarshaling" phase */ + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); + + NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + todo_wine { + ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); + } + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); + todo_wine { + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); + } + + /* "marshaling" phase */ + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + todo_wine { + ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId); + } + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + todo_wine { + ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId); + } + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); + todo_wine { + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x1 instead of 0x%lx\n", RefId); + } + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%lx\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + todo_wine { + ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%lx\n", RefId); + } + + /* "freeing" phase */ + + todo_wine { + ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + + ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + + ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + } + + NdrFullPointerXlatFree(pXlatTables); +} + START_TEST( ndr_marshall ) { test_simple_types(); test_simple_struct(); + test_fullpointer_xlat(); }