rpcrt4: Ignore fMustAlloc in PointerUnmarshall().
Use our own heuristics to decide whether we, or the inner routine, must allocate. Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
61fdcfdd36
commit
03be1605db
|
@ -865,7 +865,11 @@ static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
|
||||
/* pPointer is the pointer that we will unmarshal into; pSrcPointer is the
|
||||
* pointer to memory which we may attempt to reuse if non-NULL. Usually these
|
||||
* are the same; for the case when they aren't, see EmbeddedPointerUnmarshall(). */
|
||||
* are the same; for the case when they aren't, see EmbeddedPointerUnmarshall().
|
||||
*
|
||||
* fMustAlloc seems to determine whether we can allocate from the buffer (if we
|
||||
* are on the server side). It's ignored here, since we can't allocate a pointer
|
||||
* from the buffer. */
|
||||
static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
||||
unsigned char *Buffer,
|
||||
unsigned char **pPointer,
|
||||
|
@ -877,7 +881,7 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
PFORMAT_STRING desc;
|
||||
NDR_UNMARSHALL m;
|
||||
DWORD pointer_id = 0;
|
||||
BOOL pointer_needs_unmarshaling;
|
||||
BOOL pointer_needs_unmarshaling, need_alloc = FALSE, inner_must_alloc = FALSE;
|
||||
|
||||
TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc);
|
||||
TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr);
|
||||
|
@ -902,11 +906,13 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
case FC_OP: /* object pointer - we must free data before overwriting it */
|
||||
pointer_id = NDR_LOCAL_UINT32_READ(Buffer);
|
||||
TRACE("pointer_id is 0x%08x\n", pointer_id);
|
||||
if (!fMustAlloc && pSrcPointer)
|
||||
{
|
||||
|
||||
/* An object pointer always allocates new memory (it cannot point to the
|
||||
* buffer). */
|
||||
inner_must_alloc = TRUE;
|
||||
|
||||
if (pSrcPointer)
|
||||
FIXME("free object pointer %p\n", pSrcPointer);
|
||||
fMustAlloc = TRUE;
|
||||
}
|
||||
if (pointer_id)
|
||||
pointer_needs_unmarshaling = TRUE;
|
||||
else
|
||||
|
@ -931,31 +937,31 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
unsigned char **current_ptr = pPointer;
|
||||
if (pStubMsg->IsClient) {
|
||||
TRACE("client\n");
|
||||
/* if we aren't forcing allocation of memory then try to use the existing
|
||||
* (source) pointer to unmarshall the data into so that [in,out]
|
||||
* parameters behave correctly. it doesn't matter if the parameter is
|
||||
* [out] only since in that case the pointer will be NULL. we force
|
||||
* allocation when the source pointer is NULL here instead of in the type
|
||||
* unmarshalling routine for the benefit of the deref code below */
|
||||
if (!fMustAlloc) {
|
||||
if (pSrcPointer) {
|
||||
TRACE("setting *pPointer to %p\n", pSrcPointer);
|
||||
*pPointer = pSrcPointer;
|
||||
} else
|
||||
fMustAlloc = TRUE;
|
||||
/* Try to use the existing (source) pointer to unmarshall the data into
|
||||
* so that [in, out] or [out, ref] parameters behave correctly. If the
|
||||
* source pointer is NULL and we are not dereferencing, we must force the
|
||||
* inner marshalling routine to allocate, since otherwise it will crash. */
|
||||
if (pSrcPointer)
|
||||
{
|
||||
TRACE("setting *pPointer to %p\n", pSrcPointer);
|
||||
*pPointer = pSrcPointer;
|
||||
}
|
||||
else
|
||||
need_alloc = inner_must_alloc = TRUE;
|
||||
} else {
|
||||
TRACE("server\n");
|
||||
/* the memory in a stub is never initialised, so we have to work out here
|
||||
* whether we have to initialise it so we can use the optimisation of
|
||||
* setting the pointer to the buffer, if possible, or set fMustAlloc to
|
||||
* TRUE. */
|
||||
/* We can use an existing source pointer here only if it is on-stack,
|
||||
* probably since otherwise NdrPointerFree() might later try to free a
|
||||
* pointer we don't know the provenance of. Otherwise we must always
|
||||
* allocate if we are dereferencing. We never need to force the inner
|
||||
* routine to allocate here, since it will either write into an existing
|
||||
* pointer, or use a pointer to the buffer. */
|
||||
if (attr & FC_POINTER_DEREF)
|
||||
{
|
||||
if (pSrcPointer && (attr & FC_ALLOCED_ON_STACK))
|
||||
*pPointer = pSrcPointer;
|
||||
else
|
||||
fMustAlloc = TRUE;
|
||||
need_alloc = TRUE;
|
||||
}
|
||||
else
|
||||
*pPointer = NULL;
|
||||
|
@ -965,15 +971,14 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
|
|||
FIXME("FC_ALLOCATE_ALL_NODES not implemented\n");
|
||||
|
||||
if (attr & FC_POINTER_DEREF) {
|
||||
if (fMustAlloc)
|
||||
if (need_alloc)
|
||||
*pPointer = NdrAllocateZero(pStubMsg, sizeof(void *));
|
||||
|
||||
current_ptr = *(unsigned char***)current_ptr;
|
||||
TRACE("deref => %p\n", current_ptr);
|
||||
if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE;
|
||||
}
|
||||
m = NdrUnmarshaller[*desc & NDR_TABLE_MASK];
|
||||
if (m) m(pStubMsg, current_ptr, desc, fMustAlloc);
|
||||
if (m) m(pStubMsg, current_ptr, desc, inner_must_alloc);
|
||||
else FIXME("no unmarshaller for data type=%02x\n", *desc);
|
||||
|
||||
if (type == FC_FP)
|
||||
|
|
|
@ -295,16 +295,11 @@ static void test_pointer_marshal(const unsigned char *formattypes,
|
|||
ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 );
|
||||
ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
|
||||
/* doesn't allocate mem in this case */
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
|
||||
}
|
||||
ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx);
|
||||
ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen);
|
||||
ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize);
|
||||
|
||||
todo_wine {
|
||||
ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
}
|
||||
ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
NdrPointerFree(&StubMsg, mem, formattypes);
|
||||
|
@ -373,7 +368,6 @@ todo_wine {
|
|||
if (formattypes[2] == FC_ENUM16)
|
||||
ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
else
|
||||
todo_wine_if(formattypes[1] & FC_POINTER_DEREF)
|
||||
ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
|
@ -387,12 +381,10 @@ todo_wine_if(formattypes[1] & FC_POINTER_DEREF)
|
|||
* knowing that the memory allocated by NdrPointerUnmarshall() isn't
|
||||
* stack memory. In practice it always *is* stack memory if ON_STACK is
|
||||
* set, so this leak isn't a concern. */
|
||||
todo_wine
|
||||
ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
else
|
||||
todo_wine_if((formattypes[1] & FC_POINTER_DEREF) && !(formattypes[1] & FC_ALLOCED_ON_STACK))
|
||||
ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
/* reset the buffer and call with must alloc */
|
||||
|
@ -408,7 +400,6 @@ todo_wine_if((formattypes[1] & FC_POINTER_DEREF) && !(formattypes[1] & FC_ALLOCE
|
|||
if (formattypes[2] == FC_ENUM16)
|
||||
ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
else
|
||||
todo_wine
|
||||
ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
|
@ -417,12 +408,10 @@ todo_wine
|
|||
ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
{
|
||||
todo_wine
|
||||
ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
else
|
||||
todo_wine
|
||||
ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
/* Τest with an existing pointer. Unless it's a stack pointer (and deref'd)
|
||||
|
@ -446,10 +435,8 @@ todo_wine
|
|||
if (formattypes[2] == FC_ENUM16)
|
||||
ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
todo_wine
|
||||
ok(my_alloc_called == 0, "%s: my_alloc got called %d times\n", msgpfx, my_free_called);
|
||||
else
|
||||
todo_wine_if(formattypes[1] & FC_POINTER_DEREF)
|
||||
ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
|
@ -458,12 +445,10 @@ todo_wine_if(formattypes[1] & FC_POINTER_DEREF)
|
|||
ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
{
|
||||
todo_wine
|
||||
ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
else
|
||||
todo_wine_if((formattypes[1] & FC_POINTER_DEREF) && !(formattypes[1] & FC_ALLOCED_ON_STACK))
|
||||
ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
/* reset the buffer and call with must alloc */
|
||||
|
@ -475,7 +460,6 @@ todo_wine_if((formattypes[1] & FC_POINTER_DEREF) && !(formattypes[1] & FC_ALLOCE
|
|||
ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 );
|
||||
ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr);
|
||||
if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
todo_wine
|
||||
ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig);
|
||||
else
|
||||
ok(mem != mem_orig, "%s: mem has not changed\n", msgpfx);
|
||||
|
@ -485,10 +469,8 @@ todo_wine
|
|||
if (formattypes[2] == FC_ENUM16)
|
||||
ok(my_alloc_called == 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
todo_wine
|
||||
ok(my_alloc_called == 0, "%s: my_alloc got called %d times\n", msgpfx, my_free_called);
|
||||
else
|
||||
todo_wine
|
||||
ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called);
|
||||
ok(!my_free_called, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
|
@ -497,12 +479,10 @@ todo_wine
|
|||
ok(my_free_called == 1, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
else if ((formattypes[1] & FC_ALLOCED_ON_STACK) && (formattypes[1] & FC_POINTER_DEREF))
|
||||
{
|
||||
todo_wine
|
||||
ok(my_free_called == 0, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
else
|
||||
todo_wine
|
||||
ok(my_free_called == num_additional_allocs, "%s: my_free got called %d times\n", msgpfx, my_free_called);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart);
|
||||
|
@ -797,10 +777,8 @@ static void test_nontrivial_pointer_types(void)
|
|||
my_alloc_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
|
||||
my_free_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
|
@ -830,7 +808,6 @@ static void test_nontrivial_pointer_types(void)
|
|||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
|
||||
ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
|
||||
todo_wine
|
||||
ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
|
||||
|
@ -839,7 +816,6 @@ static void test_nontrivial_pointer_types(void)
|
|||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
ok(mem != StubMsg.BufferStart, "mem pointing at buffer\n");
|
||||
todo_wine
|
||||
ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called);
|
||||
NdrPointerFree( &StubMsg, mem, &fmtstr_ref_unique_out[4] );
|
||||
|
||||
|
@ -849,7 +825,6 @@ static void test_nontrivial_pointer_types(void)
|
|||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 0);
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
todo_wine
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
|
||||
my_alloc_called = 0;
|
||||
|
@ -857,10 +832,8 @@ todo_wine
|
|||
*(void **)mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, &fmtstr_ref_unique_out[4], 1);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
ok(mem == mem_orig, "mem alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
|
||||
mem = my_alloc(sizeof(void *));
|
||||
*(void **)mem = NULL;
|
||||
|
@ -1740,10 +1713,8 @@ static void test_conformant_string(void)
|
|||
my_alloc_called = 0;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
|
||||
todo_wine {
|
||||
ok(mem == mem_orig, "mem not alloced\n");
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
/* Prevent a memory leak when running with Wine.
|
||||
Remove once the todo_wine block above is fixed. */
|
||||
|
@ -1775,11 +1746,9 @@ todo_wine {
|
|||
mem = NULL;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
|
||||
todo_wine {
|
||||
ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
|
||||
"mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
my_alloc_called = 0;
|
||||
mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc));
|
||||
|
@ -1793,11 +1762,9 @@ todo_wine {
|
|||
mem = mem_orig;
|
||||
StubMsg.Buffer = StubMsg.BufferStart;
|
||||
NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1);
|
||||
todo_wine {
|
||||
ok(mem == StubMsg.BufferStart + 12 || broken(!mem), /* win9x, nt4 */
|
||||
"mem not pointing at buffer %p/%p\n", mem, StubMsg.BufferStart + 12 );
|
||||
ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called);
|
||||
}
|
||||
|
||||
mem = my_alloc(10);
|
||||
my_free_called = 0;
|
||||
|
|
Loading…
Reference in New Issue