Files
raven/testdata/native_loader/rpc_replace_client.c
T

95 lines
3.0 KiB
C

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <rpc.h>
#include "rpc_replace.h"
/* How a server stub frees what it unmarshalled. A manager may free what an [in, out] pointer points to and hand back a block of its
* own: the stub then frees that block, never the one already given back. A structure behind a pointer goes after the pointers it
* holds, which are read from it, not from a freed block. Every block handed out is recorded, and a freed one is filled with a pattern
* and never reused, so a free of anything not live shows here instead of corrupting the heap of a later caller. */
static void *live[256];
static int live_count, bad_frees;
void *__RPC_USER MIDL_user_allocate(size_t size)
{
void *block = HeapAlloc(GetProcessHeap(), 0, size);
if (block && live_count < 256)
live[live_count++] = block;
return block;
}
void __RPC_USER MIDL_user_free(void *block)
{
if (!block)
return;
for (int i = 0; i < live_count; i++) {
if (live[i] == block) {
live[i] = live[--live_count];
SIZE_T size = HeapSize(GetProcessHeap(), 0, block);
for (SIZE_T at = 0; size != (SIZE_T)-1 && at < size; at++)
((BYTE *)block)[at] = 0x5a;
return;
}
}
bad_frees++;
}
void server_replace_name(handle_t binding, named *item)
{
(void)binding;
MIDL_user_free(item->name);
item->name = MIDL_user_allocate(sizeof(L"replaced"));
if (item->name)
lstrcpyW(item->name, L"replaced");
}
static int names_seen;
void server_take_name(handle_t binding, named *item)
{
(void)binding;
if (item && item->name && !lstrcmpW(item->name, L"taken"))
names_seen++;
}
void server_take_holder(handle_t binding, holder *item)
{
(void)binding;
if (item->inner && item->inner->name && !lstrcmpW(item->inner->name, L"held"))
names_seen++;
}
int raven_entry(void)
{
if (RpcServerUseProtseqEpW((RPC_WSTR)L"ncalrpc", RPC_C_PROTSEQ_MAX_REQS_DEFAULT, (RPC_WSTR)L"raven-replace", NULL) != RPC_S_OK) return 1;
if (RpcServerRegisterIf(server_rpc_replace_v1_0_s_ifspec, NULL, NULL) != RPC_S_OK) return 2;
if (RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE) != RPC_S_OK) return 3;
RPC_WSTR text = NULL;
RPC_BINDING_HANDLE binding = NULL;
if (RpcStringBindingComposeW(NULL, (RPC_WSTR)L"ncalrpc", NULL, (RPC_WSTR)L"raven-replace", NULL, &text) != RPC_S_OK) return 4;
if (RpcBindingFromStringBindingW(text, &binding) != RPC_S_OK) return 5;
RpcStringFreeW(&text);
for (int round = 0; round < 8; round++) {
named item = {MIDL_user_allocate(sizeof(L"original"))};
if (!item.name) return 6;
lstrcpyW(item.name, L"original");
replace_name(binding, &item);
if (!item.name || lstrcmpW(item.name, L"replaced")) return 7;
MIDL_user_free(item.name);
}
if (bad_frees) return 10 + bad_frees;
for (int round = 0; round < 8; round++) {
named item = {(wchar_t *)L"taken"};
take_name(binding, &item);
}
if (names_seen != 8) return 8;
for (int round = 0; round < 8; round++) {
named inner = {(wchar_t *)L"held"};
holder item = {&inner};
take_holder(binding, &item);
}
if (names_seen != 16) return 9;
RpcBindingFree(&binding);
return bad_frees ? 40 + bad_frees : 0;
}