1530 lines
37 KiB
C
1530 lines
37 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ortest.c
|
|
|
|
Abstract:
|
|
|
|
Simple test application for testing OR features directly.
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 1/24/1996 Bits 'n pieces
|
|
|
|
--*/
|
|
|
|
#include <or.h>
|
|
#include <stdio.h>
|
|
#include <umisc.h>
|
|
#include <uor.h>
|
|
#include <epmp.h>
|
|
|
|
typedef struct {
|
|
ID oid;
|
|
BOOL fReady;
|
|
BOOL fForceSecond;
|
|
} RundownRecord;
|
|
|
|
// Constants
|
|
|
|
const PWSTR pwstrOr = L"ncalrpc:[epmapper]";
|
|
|
|
// Globals
|
|
|
|
HANDLE hLocalOr = 0;
|
|
HANDLE hServerOrTest = 0;
|
|
PHPROCESS hMyProcess = 0;
|
|
|
|
BOOL fServer = TRUE;
|
|
BOOL fInternet = FALSE;
|
|
|
|
DWORD TestCase = 0;
|
|
DWORD Errors = 0;
|
|
|
|
OXID aOxids[5]; /* shared \ */
|
|
OXID_INFO aOxidInfo[5]; /* shared > between client and server */
|
|
OID aOids[100]; /* shared / */
|
|
|
|
RundownRecord aRundowns[100];
|
|
DWORD dwlimRundowns = 0;
|
|
|
|
OID reservedBase;
|
|
|
|
DUALSTRINGARRAY *pdsaMyExpandedStringBindings;
|
|
DUALSTRINGARRAY *pdsaMyCompressedSecurityBindings;
|
|
DUALSTRINGARRAY *pdsaMyTestBindings;
|
|
|
|
DUALSTRINGARRAY *pdsaLocalOrBindings;
|
|
MID gLocalMid;
|
|
|
|
void SyncWithClient(DWORD testcase);
|
|
error_status_t SyncWithServer(DWORD testcase);
|
|
void AddRundown(ID oid, BOOL fRundownTwice);
|
|
void WaitForAllRundowns();
|
|
RPC_STATUS ConnectToLocalOr();
|
|
RPC_STATUS Startup(PSZ, PSZ);
|
|
|
|
// Test events
|
|
|
|
HANDLE hServerEvent;
|
|
HANDLE hClientEvent;
|
|
HANDLE hRundownEvent;
|
|
|
|
|
|
//
|
|
// Intenet port tests - not really related to DCOM
|
|
// but is just a client to the endpoint mapper process
|
|
// so it runs fine here.
|
|
//
|
|
// Assumes the following config: (regini dcomtest.ini)
|
|
//
|
|
|
|
extern RPC_STATUS RPC_ENTRY
|
|
I_RpcServerAllocatePort(DWORD, PUSHORT);
|
|
|
|
RPC_STATUS
|
|
RunInternetPortTests()
|
|
{
|
|
RPC_STATUS status;
|
|
long allocstatus;
|
|
PVOID process1, process2, process3;
|
|
unsigned short port;
|
|
int i;
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
process1 = process2 = process3 = 0;
|
|
|
|
if (hLocalOr == 0)
|
|
{
|
|
status =
|
|
RpcBindingFromStringBinding(pwstrOr, &hLocalOr);
|
|
ASSERT(status == RPC_S_OK);
|
|
}
|
|
|
|
status = OpenEndpointMapper(hLocalOr,
|
|
&process1);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = OpenEndpointMapper(hLocalOr,
|
|
&process2);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = OpenEndpointMapper(hLocalOr,
|
|
&process3);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
status = AllocateReservedIPPort(process1,
|
|
PORT_DEFAULT,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1026);
|
|
|
|
status = AllocateReservedIPPort(process1,
|
|
PORT_INTERNET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1028);
|
|
|
|
status = AllocateReservedIPPort(process1,
|
|
PORT_INTERNET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1029);
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 499);
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 500);
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 501);
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 502);
|
|
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1025);
|
|
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1027);
|
|
|
|
|
|
status = AllocateReservedIPPort(process2,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OUT_OF_RESOURCES);
|
|
EQUAL(port, 0);
|
|
|
|
|
|
status = AllocateReservedIPPort(process3,
|
|
PORT_INTRANET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OUT_OF_RESOURCES);
|
|
EQUAL(port, 0);
|
|
|
|
status = AllocateReservedIPPort(process3,
|
|
PORT_INTERNET,
|
|
&allocstatus,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(allocstatus, RPC_S_OK);
|
|
EQUAL(port, 1030);
|
|
|
|
status =
|
|
RpcSmDestroyClientContext(&process2);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcSmDestroyClientContext(&process3);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcSmDestroyClientContext(&process1);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcBindingFree(&hLocalOr);
|
|
ASSERT(status == RPC_S_OK);
|
|
}
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTERNET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 1026);
|
|
|
|
status = I_RpcServerAllocatePort(0,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 1028);
|
|
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 499);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 500);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 501);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 502);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 1025);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(port, 1027);
|
|
|
|
status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
|
|
ASSERT(status == RPC_S_OUT_OF_RESOURCES);
|
|
EQUAL(port, 0);
|
|
|
|
status = I_RpcServerAllocatePort( RPC_C_USE_INTERNET_PORT
|
|
| RPC_C_USE_INTRANET_PORT,
|
|
&port);
|
|
ASSERT(status == RPC_S_INVALID_ARG);
|
|
EQUAL(port, 0);
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
// Server side
|
|
|
|
RPC_STATUS
|
|
RunServer()
|
|
{
|
|
RPC_STATUS status;
|
|
DWORD t;
|
|
OXID_INFO oi;
|
|
OID oidT;
|
|
int i;
|
|
OID aOidDels[2];
|
|
|
|
SyncWithClient(++TestCase);
|
|
|
|
// Allocate Oxids and Oids
|
|
|
|
aOxidInfo[0].dwTid = 1;
|
|
aOxidInfo[0].dwPid = 42;
|
|
aOxidInfo[0].dwAuthnHint = 4;
|
|
aOxidInfo[0].psa = 0;
|
|
|
|
status = UuidCreate(&aOxidInfo[0].ipidRemUnknown);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = ServerAllocateOXIDAndOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[0],
|
|
FALSE,
|
|
5,
|
|
&aOids[0],
|
|
&t,
|
|
&aOxidInfo[0],
|
|
pdsaMyExpandedStringBindings,
|
|
pdsaMyCompressedSecurityBindings);
|
|
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(t, 5);
|
|
|
|
status = ServerAllocateOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[0],
|
|
5,
|
|
&aOids[5],
|
|
&t);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(t, 5);
|
|
|
|
PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[0]);
|
|
for(i = 0; i < 10; i++)
|
|
{
|
|
PrintToConsole("\t%I64x\n", aOids[i]);
|
|
}
|
|
|
|
aOxidInfo[1].dwTid = 2;
|
|
aOxidInfo[1].dwPid = 42;
|
|
aOxidInfo[1].dwAuthnHint = 99;
|
|
aOxidInfo[1].psa = 0;
|
|
|
|
status = UuidCreate(&aOxidInfo[1].ipidRemUnknown);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = ServerAllocateOXIDAndOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[1],
|
|
FALSE,
|
|
10,
|
|
&aOids[10],
|
|
&t,
|
|
&aOxidInfo[1],
|
|
pdsaMyExpandedStringBindings,
|
|
pdsaMyTestBindings);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(t, 10);
|
|
|
|
PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[1]);
|
|
for(i = 10; i < 20; i++)
|
|
{
|
|
PrintToConsole("\t%I64x\n", aOids[i]);
|
|
}
|
|
|
|
aOxidInfo[2].dwTid = 3;
|
|
aOxidInfo[2].dwPid = 42;
|
|
aOxidInfo[2].dwAuthnHint = 17171717;
|
|
aOxidInfo[2].psa = 0;
|
|
|
|
status = UuidCreate(&aOxidInfo[2].ipidRemUnknown);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = ServerAllocateOXIDAndOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[2],
|
|
FALSE,
|
|
10,
|
|
&aOids[20],
|
|
&t,
|
|
&aOxidInfo[2],
|
|
pdsaMyExpandedStringBindings,
|
|
pdsaMyTestBindings);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
EQUAL(t, 10);
|
|
|
|
PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[2]);
|
|
for(i = 20; i < 30; i++)
|
|
{
|
|
PrintToConsole("\t%I64x\n", aOids[i]);
|
|
}
|
|
|
|
SyncWithClient(++TestCase);
|
|
|
|
status = ServerFreeOXIDAndOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
aOxids[1],
|
|
10,
|
|
&aOids[10]
|
|
);
|
|
|
|
ASSERT(status == OR_OK);
|
|
|
|
status = ServerFreeOXIDAndOIDs(
|
|
hLocalOr,
|
|
hMyProcess,
|
|
aOxids[2],
|
|
10,
|
|
&aOids[20]
|
|
);
|
|
|
|
ASSERT(status == OR_OK);
|
|
|
|
PrintToConsole("Freed OXID %I64x and %I64x\n", aOxids[1], aOxids[2]);
|
|
|
|
SyncWithClient(++TestCase);
|
|
|
|
// Wait for rundowns on oxid 0 of OIDs 0, 1, 7 and 9
|
|
|
|
AddRundown(aOids[0], FALSE);
|
|
AddRundown(aOids[1], FALSE);
|
|
AddRundown(aOids[7], FALSE);
|
|
AddRundown(aOids[9], FALSE);
|
|
|
|
WaitForAllRundowns();
|
|
|
|
SyncWithClient(++TestCase);
|
|
|
|
TestCase = ~0;
|
|
SyncWithClient(TestCase);
|
|
|
|
// Free OID 3 it shouldn't rundown after this; and an invalid oid.
|
|
|
|
aOidDels[0] = aOids[3];
|
|
aOidDels[1] = reservedBase;
|
|
|
|
status =
|
|
BulkUpdateOIDs(hLocalOr,
|
|
hMyProcess,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
2,
|
|
aOidDels,
|
|
0,
|
|
0
|
|
);
|
|
|
|
// Wait for rundowns on oxid 0 of OIDs 2, 4, 5, 6 and 8
|
|
// Client has exited
|
|
|
|
AddRundown(aOids[2], FALSE);
|
|
AddRundown(aOids[4], TRUE);
|
|
AddRundown(aOids[5], FALSE);
|
|
AddRundown(aOids[6], FALSE);
|
|
AddRundown(aOids[8], TRUE);
|
|
|
|
WaitForAllRundowns();
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
// Client side
|
|
RPC_STATUS
|
|
RunClient()
|
|
{
|
|
RPC_STATUS status;
|
|
DUALSTRINGARRAY *pdaRemoteOrBindings = 0;
|
|
OXID_INFO oi;
|
|
MID mid;
|
|
int i;
|
|
OXID_OID_PAIR aUpdates[10];
|
|
OID_MID_PAIR aDeletes[6];
|
|
OXID_REF aoxidRefs[2];
|
|
LONG aStatus[10];
|
|
|
|
SyncWithServer(++TestCase);
|
|
|
|
// Server has allocated oxids and oids
|
|
|
|
status =
|
|
GetState(hServerOrTest,
|
|
3,
|
|
30,
|
|
3,
|
|
aOxids,
|
|
aOids,
|
|
aOxidInfo,
|
|
&pdaRemoteOrBindings);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
ASSERT(pdaRemoteOrBindings);
|
|
EQUAL(aOxidInfo[0].psa, 0);
|
|
|
|
// Resolve OXID 0
|
|
oi.psa =0;
|
|
|
|
status =
|
|
ClientResolveOXID(hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[0],
|
|
pdaRemoteOrBindings,
|
|
FALSE,
|
|
&oi,
|
|
&mid);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
PrintToConsole("Resolved OXID: %I64x on MID %I64x\n", aOxids[0], mid);
|
|
EQUAL( ( (oi.dwTid == aOxidInfo[0].dwTid) || oi.dwTid == 0), 1);
|
|
EQUAL( ( (oi.dwPid == aOxidInfo[0].dwPid) || oi.dwPid == 0), 1);
|
|
EQUAL(oi.dwAuthnHint, aOxidInfo[0].dwAuthnHint);
|
|
if (memcmp(&oi.ipidRemUnknown, &aOxidInfo[0].ipidRemUnknown, sizeof(IPID)) != 0)
|
|
{
|
|
EQUAL(0, 1);
|
|
}
|
|
PrintDualStringArray("Expanded binding", oi.psa, FALSE);
|
|
MIDL_user_free(oi.psa);
|
|
|
|
// Add some valid and invalid oids
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
aUpdates[i].mid = mid;
|
|
aUpdates[i].oxid = aOxids[0];
|
|
aUpdates[i].oid = aOids[i];
|
|
}
|
|
|
|
aUpdates[9].mid = reservedBase;
|
|
aUpdates[8].oxid = reservedBase;
|
|
aUpdates[7].oid = reservedBase;
|
|
|
|
status =
|
|
BulkUpdateOIDs(hLocalOr,
|
|
hMyProcess,
|
|
10,
|
|
aUpdates,
|
|
aStatus,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
ASSERT(status == OR_PARTIAL_UPDATE);
|
|
for(i = 0; i < 7; i++)
|
|
{
|
|
EQUAL(aStatus[i], 0);
|
|
}
|
|
EQUAL(aStatus[7], 0); // Okay to register unknown OID
|
|
EQUAL(aStatus[8], OR_BADOXID);
|
|
EQUAL(aStatus[9], OR_BADOXID);
|
|
|
|
// Delete a few
|
|
|
|
// Add three not added last call
|
|
// .oxid and .mid correct
|
|
aUpdates[0].oid = aOids[8];
|
|
aUpdates[1].oid = aOids[9];
|
|
|
|
// Remove 2 added last call, 1 from this call and 2 invalid
|
|
for(i = 0; i < 6; i++)
|
|
{
|
|
aDeletes[i].oid = aOids[i];
|
|
aDeletes[i].mid = mid;
|
|
}
|
|
aDeletes[2].oid = aOids[9];
|
|
aDeletes[3].oid = reservedBase;
|
|
aDeletes[4].mid = reservedBase;
|
|
aDeletes[5].oid = aOids[6];
|
|
|
|
status =
|
|
BulkUpdateOIDs(hLocalOr,
|
|
hMyProcess,
|
|
2,
|
|
aUpdates,
|
|
aStatus,
|
|
6,
|
|
aDeletes,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
ASSERT(status == OR_OK);
|
|
EQUAL(aStatus[0], OR_OK);
|
|
EQUAL(aStatus[1], OR_OK);
|
|
|
|
// 6 has been added and deleted, add it again.
|
|
aUpdates[0].oid = aOids[6];
|
|
status =
|
|
BulkUpdateOIDs(hLocalOr,
|
|
hMyProcess,
|
|
1,
|
|
aUpdates,
|
|
aStatus,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
ASSERT(status == OR_OK);
|
|
EQUAL(aStatus[0], OR_OK);
|
|
|
|
// Final state: D - added and deleted, A - added, E - D + added, N not added
|
|
// OID: 0 1 2 3 4 5 6 7 8 9
|
|
// State: D D A A A A E N A D
|
|
|
|
// Resolve OXID 1
|
|
|
|
if (mid != gLocalMid)
|
|
{
|
|
MID mid2;
|
|
// No resolve required for local machine.
|
|
|
|
PrintToConsole("Remote server; resolving second OXID\n");
|
|
oi.psa = 0;
|
|
status =
|
|
ClientResolveOXID(hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[1],
|
|
pdaRemoteOrBindings,
|
|
FALSE,
|
|
&oi,
|
|
&mid2);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
PrintToConsole("Resolved OXID: %I64x on MID %I64x\n", aOxids[1], mid);
|
|
EQUAL(mid, mid2);
|
|
EQUAL(oi.dwTid, 0);
|
|
EQUAL(oi.dwPid, 0);
|
|
EQUAL(oi.dwAuthnHint, aOxidInfo[1].dwAuthnHint);
|
|
if (memcmp(&oi.ipidRemUnknown, &aOxidInfo[1].ipidRemUnknown, sizeof(IPID)) != 0)
|
|
{
|
|
EQUAL(0, 1);
|
|
}
|
|
PrintDualStringArray("Expanded binding", oi.psa, FALSE);
|
|
MIDL_user_free(oi.psa);
|
|
}
|
|
|
|
// Add some of the oids.
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
aUpdates[i].mid = mid;
|
|
aUpdates[i].oxid = aOxids[1];
|
|
aUpdates[i].oid = aOids[i+10];
|
|
}
|
|
|
|
// Release our processes hold on the oxids, this is okay since the OIDs
|
|
// are keeping them alive.
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
aoxidRefs[i].oxid = aOxids[i];
|
|
aoxidRefs[i].mid = mid;
|
|
}
|
|
aoxidRefs[0].refs = 1;
|
|
aoxidRefs[1].refs = 4; // invalid, will cause an DbgPrint in checked or.
|
|
|
|
status =
|
|
BulkUpdateOIDs(hLocalOr,
|
|
hMyProcess,
|
|
5,
|
|
aUpdates,
|
|
aStatus,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
2,
|
|
aoxidRefs);
|
|
|
|
ASSERT(status == OR_OK);
|
|
for(i = 0; i < 5; i++)
|
|
{
|
|
EQUAL(aStatus[i], 0);
|
|
}
|
|
|
|
SyncWithServer(++TestCase);
|
|
|
|
// Server has freed oxids and oids
|
|
|
|
// Can't test that adding an invalid OID is caught, because it
|
|
// isn't until the client actually pings the real server.
|
|
|
|
// Since the client has already resolved oxid1 we can re-resolve it.
|
|
|
|
// Try to lookup oxid 2 which has also been freed, it should fail.
|
|
|
|
oi.psa = 0;
|
|
|
|
status =
|
|
ClientResolveOXID(hLocalOr,
|
|
hMyProcess,
|
|
&aOxids[2],
|
|
pdaRemoteOrBindings,
|
|
FALSE,
|
|
&oi,
|
|
&mid);
|
|
|
|
ASSERT(status == OR_BADOXID);
|
|
EQUAL(oi.psa,0);
|
|
|
|
SyncWithServer(++TestCase);
|
|
|
|
// Server waited for first set of rundowns
|
|
|
|
SyncWithServer(++TestCase);
|
|
|
|
SyncWithServer(~0);
|
|
|
|
// Server will wait for the last set of rundowns.
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
RPC_STATUS status;
|
|
PSZ pszProtseq, pszServer;
|
|
|
|
argc--;
|
|
argv++;
|
|
|
|
pszServer = 0;
|
|
pszProtseq = "ncalrpc";
|
|
|
|
while(argc)
|
|
{
|
|
switch(argv[0][1])
|
|
{
|
|
case 't':
|
|
pszProtseq = argv[1];
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
case 'l':
|
|
case 'c':
|
|
fServer = FALSE;
|
|
break;
|
|
case 'i':
|
|
fInternet = TRUE;
|
|
break;
|
|
case 's':
|
|
pszServer = argv[1];
|
|
argc--;
|
|
argv++;
|
|
break;
|
|
default:
|
|
PrintToConsole("Usage: ortest [client|-client] [-internet] [-t protseq ] [-s server addr]\n"
|
|
);
|
|
return(0);
|
|
}
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
PrintToConsole("OrTest: %s starting...\n", fInternet ? "internet test" :
|
|
( fServer ? "server" : "client") );
|
|
|
|
if (fInternet)
|
|
{
|
|
status = RunInternetPortTests();
|
|
}
|
|
else
|
|
{
|
|
status = Startup(pszProtseq, pszServer);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status = ConnectToLocalOr();
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
if (fServer)
|
|
{
|
|
status = RunServer();
|
|
}
|
|
else
|
|
{
|
|
status = RunClient();
|
|
}
|
|
}
|
|
if (status == RPC_S_OK)
|
|
{
|
|
PrintToConsole("Test Passed\n");
|
|
}
|
|
else
|
|
{
|
|
PrintToConsole("Test Failed %d\n", Errors);
|
|
}
|
|
|
|
if (hLocalOr) RpcBindingFree(&hLocalOr);
|
|
if (hMyProcess) RpcSsDestroyClientContext(&hMyProcess);
|
|
if (hServerOrTest) RpcBindingFree(&hServerOrTest);
|
|
Sleep(1000);
|
|
return(0);
|
|
}
|
|
|
|
// Shared initialization code
|
|
|
|
RPC_STATUS
|
|
Startup(PSZ protseq, PSZ server)
|
|
{
|
|
RPC_STATUS status;
|
|
DUALSTRINGARRAY *pdsaT, *pdsaT2;
|
|
RPC_BINDING_VECTOR *pbv;
|
|
|
|
pdsaMyExpandedStringBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(500*2);
|
|
pdsaMyCompressedSecurityBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(4 + 6*2);
|
|
pdsaMyTestBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(4 + 19*2);
|
|
ASSERT( pdsaMyExpandedStringBindings
|
|
&& pdsaMyCompressedSecurityBindings
|
|
&& pdsaMyTestBindings);
|
|
|
|
pdsaMyCompressedSecurityBindings->wNumEntries = 6;
|
|
pdsaMyCompressedSecurityBindings->wSecurityOffset = 2;
|
|
pdsaMyCompressedSecurityBindings->aStringArray[0] = 0;
|
|
pdsaMyCompressedSecurityBindings->aStringArray[1] = 0;
|
|
pdsaMyCompressedSecurityBindings->aStringArray[2] = 10; // authn winnt
|
|
pdsaMyCompressedSecurityBindings->aStringArray[3] = -1; // authz none
|
|
pdsaMyCompressedSecurityBindings->aStringArray[4] = 0;
|
|
pdsaMyCompressedSecurityBindings->aStringArray[5] = 0;
|
|
|
|
_UseProtseq(0, L"ncalrpc", &pdsaT, &pdsaT2); // inits psaMyExpandedStringBindings
|
|
EQUAL( (pdsaT != 0), 1);
|
|
EQUAL( (pdsaT2 != 0), 1);
|
|
MIDL_user_free(pdsaT);
|
|
MIDL_user_free(pdsaT2);
|
|
|
|
pdsaMyTestBindings->wNumEntries = 19;
|
|
pdsaMyTestBindings->wSecurityOffset = 2;
|
|
memcpy(pdsaMyTestBindings->aStringArray,
|
|
L"\0\0\x7\xff" L"APrincipal\0\x9\xD\0\0",
|
|
19*2);
|
|
|
|
if (fServer)
|
|
{
|
|
|
|
// Listen to the remote (if any) protseq. Not part of the bindings
|
|
// registered with the OR until a callback to UseProtseq is made.
|
|
if (protseq)
|
|
{
|
|
status = RpcServerUseProtseqA(protseq, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
}
|
|
|
|
status = RpcServerInqBindings(&pbv);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcEpRegister(_IOrTest_ServerIfHandle, pbv, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcBindingVectorFree(&pbv);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
// Register UseProtseq callback IF
|
|
status =
|
|
RpcServerRegisterIf(_IOrCallback_ServerIfHandle, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
// Register test to test IF
|
|
status =
|
|
RpcServerRegisterIf(_IOrTest_ServerIfHandle, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
// Register rundown OID (fake ORPC) callback IF
|
|
status =
|
|
RpcServerRegisterIf(_IRundown_ServerIfHandle, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcServerListen(1, 10, TRUE);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
hServerEvent = CreateEvent(0, FALSE, FALSE, 0);
|
|
hClientEvent = CreateEvent(0, FALSE, FALSE, 0);
|
|
hRundownEvent = CreateEvent(0, FALSE, FALSE, 0);
|
|
|
|
ASSERT(hServerEvent && hClientEvent && hRundownEvent);
|
|
|
|
PrintToConsole("\tWaiting for client...\n");
|
|
|
|
SyncWithClient(++TestCase);
|
|
|
|
status = RPC_S_OK;
|
|
}
|
|
else
|
|
{
|
|
PSZ stringbinding;
|
|
|
|
// Make binding to remote OR
|
|
|
|
status =
|
|
RpcStringBindingComposeA(0, protseq, server, 0, 0, &stringbinding);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
status =
|
|
RpcBindingFromStringBindingA(stringbinding, &hServerOrTest);
|
|
|
|
if (status == RPC_S_OK)
|
|
{
|
|
status = TestBinding(hServerOrTest);
|
|
if (status != RPC_S_OK)
|
|
{
|
|
PrintToConsole("Connect to server failed %d\n", status);
|
|
return(status);
|
|
}
|
|
status = SyncWithServer(++TestCase);
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
RPC_STATUS
|
|
ConnectToLocalOr()
|
|
{
|
|
RPC_STATUS status;
|
|
DWORD timeout;
|
|
OXID reservedOxid;
|
|
BOOL disable;
|
|
DWORD authn;
|
|
DWORD imp;
|
|
BOOL mutual;
|
|
BOOL secref;
|
|
DWORD cServerSvc = 0;
|
|
PUSHORT pServerSvc = 0;
|
|
DWORD cClientSvc = 0;
|
|
PUSHORT pClientSvc = 0;
|
|
int i;
|
|
PWSTR pwstrLegacy = 0;
|
|
DWORD cAuthId = 0;
|
|
PSZ pszAuthId = 0;
|
|
DWORD flags, pid, scm_pid, tokenid;
|
|
|
|
status =
|
|
RpcBindingFromStringBinding(pwstrOr, &hLocalOr);
|
|
|
|
EQUAL(status, RPC_S_OK);
|
|
|
|
status = Connect(hLocalOr,
|
|
&hMyProcess,
|
|
&timeout,
|
|
&pdsaLocalOrBindings,
|
|
&gLocalMid,
|
|
5,
|
|
&reservedBase,
|
|
&flags,
|
|
&pwstrLegacy,
|
|
&authn,
|
|
&imp,
|
|
&cServerSvc,
|
|
&pServerSvc,
|
|
&cClientSvc,
|
|
&pClientSvc,
|
|
&pid,
|
|
&scm_pid,
|
|
&tokenid);
|
|
|
|
ASSERT(status == RPC_S_OK);
|
|
ASSERT(pdsaLocalOrBindings);
|
|
ASSERT(pServerSvc);
|
|
ASSERT(pClientSvc);
|
|
|
|
PrintToConsole("Connected to local object resolver:\n\tFlags:\n");
|
|
if (flags & CONNECT_DISABLEDCOM)
|
|
{
|
|
flags &= ~CONNECT_DISABLEDCOM;
|
|
PrintToConsole("\t\tDCOM DISABLED");
|
|
}
|
|
else
|
|
PrintToConsole("\t\tDCOM enabled");
|
|
|
|
if (flags & CONNECT_MUTUALAUTH)
|
|
{
|
|
flags &= ~CONNECT_MUTUALAUTH;
|
|
PrintToConsole("\tMutal authn");
|
|
}
|
|
else
|
|
PrintToConsole("\tNo Mutal authn");
|
|
|
|
if (flags & CONNECT_SECUREREF)
|
|
{
|
|
flags &= ~CONNECT_SECUREREF;
|
|
PrintToConsole("\tSecure reference counting\n");
|
|
}
|
|
else
|
|
PrintToConsole("\tStandard reference counting\n");
|
|
|
|
|
|
PrintToConsole("\tSecurity: authn: %d, imp: %d, legacy %S\n", authn, imp, pwstrLegacy);
|
|
PrintToConsole("\tTimeout %d seconds, mid %I64x\n"
|
|
"\tpid %d, scm pid %d, token id: %d\n",
|
|
timeout, gLocalMid, pid, scm_pid, tokenid);
|
|
PrintToConsole("\tReserved 5 oids, starting at %I64x\n", reservedBase);
|
|
PrintToConsole("\tServer security services: %d\n", cServerSvc);
|
|
for (i = 0; i < cServerSvc; i++ )
|
|
{
|
|
PrintToConsole("\t\tService: %d is %d\n", i, pServerSvc[i]);
|
|
}
|
|
PrintToConsole("\tClient security services: %d\n", cClientSvc);
|
|
for (i = 0; i < cClientSvc; i++ )
|
|
{
|
|
PrintToConsole("\t\tService: %d is %d\n", i, pClientSvc[i]);
|
|
}
|
|
PrintDualStringArray("Local OR bindings", pdsaLocalOrBindings, TRUE);
|
|
PrintToConsole("\n\n");
|
|
|
|
MIDL_user_free(pServerSvc);
|
|
MIDL_user_free(pClientSvc);
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
// Synchronization between ortest clients and servers
|
|
|
|
void
|
|
SyncWithClient(DWORD Test)
|
|
// Called by server thread at start of each test sequence
|
|
{
|
|
DWORD status;
|
|
|
|
if (Test > 1) SetEvent(hClientEvent);
|
|
|
|
PrintToConsole("Waiting for client sync: Test case %d\n", Test);
|
|
|
|
// Wait for the client to finish his test case
|
|
status = WaitForSingleObject(hServerEvent, 120*1000);
|
|
|
|
if (status == WAIT_TIMEOUT)
|
|
{
|
|
ASSERT(("Client never called back", 0));
|
|
}
|
|
|
|
if (Test == ~0)
|
|
{
|
|
SetEvent(hClientEvent);
|
|
Sleep(1000);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Managers for ortest servers
|
|
|
|
error_status_t
|
|
_TestBinding(
|
|
handle_t hClient
|
|
)
|
|
{
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
error_status_t
|
|
_WaitForNextTest(handle_t hClient,
|
|
DWORD Test)
|
|
// Called by client after each test sequence.
|
|
{
|
|
DWORD status;
|
|
|
|
if (Test != TestCase)
|
|
{
|
|
ASSERT(("Test case sync wrong", 0));
|
|
}
|
|
|
|
SetEvent(hServerEvent);
|
|
|
|
PrintToConsole("Client ready for test case %d\n", Test);
|
|
|
|
status = WaitForSingleObject(hClientEvent, 60*20*1000);
|
|
|
|
if (status == WAIT_TIMEOUT)
|
|
{
|
|
ASSERT(("Server never finished test case", 0));
|
|
}
|
|
|
|
}
|
|
|
|
error_status_t
|
|
SyncWithServer(DWORD Test)
|
|
{
|
|
RPC_STATUS status;
|
|
|
|
status = WaitForNextTest(hServerOrTest, Test);
|
|
|
|
EQUAL(status, RPC_S_OK);
|
|
return(status);
|
|
}
|
|
|
|
error_status_t
|
|
_GetState(
|
|
handle_t hClient,
|
|
long cOxids,
|
|
long cOids,
|
|
long cOxidInfos,
|
|
OXID aoxids[],
|
|
OID aoids[],
|
|
OXID_INFO aois[],
|
|
DUALSTRINGARRAY **ppdsaRemoteOrBindings
|
|
)
|
|
{
|
|
int i;
|
|
for (i = 0; i < cOxids; i++)
|
|
{
|
|
aoxids[i] = aOxids[i];
|
|
}
|
|
for (i = 0; i < cOids; i++)
|
|
{
|
|
aoids[i] = aOids[i];
|
|
}
|
|
for(i = 0; i < cOxidInfos; i++)
|
|
{
|
|
aois[i].dwTid = aOxidInfo[i].dwTid;
|
|
aois[i].dwPid = aOxidInfo[i].dwPid;
|
|
aois[i].dwAuthnHint = aOxidInfo[i].dwAuthnHint;
|
|
memcpy(&aois[i].ipidRemUnknown, &aOxidInfo[i].ipidRemUnknown, sizeof(IPID));
|
|
aois[i].psa = 0;
|
|
}
|
|
*ppdsaRemoteOrBindings = MIDL_user_allocate(4 + pdsaLocalOrBindings->wNumEntries * 2);
|
|
memcpy(*ppdsaRemoteOrBindings, pdsaLocalOrBindings, 4 + pdsaLocalOrBindings->wNumEntries * 2);
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
// Managers for OR callbacks
|
|
|
|
error_status_t
|
|
_UseProtseq(
|
|
IN handle_t hRpc,
|
|
IN PWSTR pwstrProtseq,
|
|
OUT DUALSTRINGARRAY **ppdsa,
|
|
OUT DUALSTRINGARRAY **ppdsaSecurity
|
|
)
|
|
{
|
|
RPC_STATUS status;
|
|
BOOL f;
|
|
DWORD t;
|
|
HANDLE hT;
|
|
TOKEN_USER *ptu;
|
|
BYTE buffer[512];
|
|
WCHAR buffer1[256];
|
|
|
|
if (hRpc)
|
|
{
|
|
status = RpcImpersonateClient(0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
f = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, &hT);
|
|
EQUAL(f, TRUE);
|
|
CloseHandle(hT);
|
|
|
|
f = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hT);
|
|
EQUAL(f, TRUE);
|
|
}
|
|
else
|
|
{
|
|
f = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hT);
|
|
EQUAL(f, TRUE);
|
|
}
|
|
|
|
f = GetTokenInformation(hT,
|
|
TokenUser,
|
|
buffer,
|
|
512,
|
|
&t);
|
|
EQUAL(f, TRUE);
|
|
ptu = (TOKEN_USER *)buffer;
|
|
|
|
CloseHandle(hT);
|
|
|
|
t = 256;
|
|
f = GetUserNameW(buffer1, &t);
|
|
if (f == FALSE)
|
|
{
|
|
PrintToConsole("Get user name failed %d\n", GetLastError());
|
|
}
|
|
|
|
PrintToConsole("UseProtseq %S called by %S:\n\t", pwstrProtseq, buffer1);
|
|
PrintSid(ptu->User.Sid);
|
|
|
|
RpcRevertToSelf();
|
|
|
|
if (!fServer && _wcsicmp(pwstrProtseq, L"ncalrpc") != 0)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
status = RpcServerUseProtseqW(pwstrProtseq, 0, 0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
// Construct new bindings array.
|
|
{
|
|
RPC_BINDING_VECTOR * pbv;
|
|
int i, j = 0;
|
|
PWSTR pT = pdsaMyExpandedStringBindings->aStringArray;
|
|
|
|
status = RpcServerInqBindings(&pbv);
|
|
EQUAL(status, RPC_S_OK);
|
|
|
|
for(i = 0; i < pbv->Count; i++)
|
|
{
|
|
PWSTR pStringBinding = 0;
|
|
status = RpcBindingToStringBinding(pbv->BindingH[i], &pStringBinding);
|
|
EQUAL(status, RPC_S_OK);
|
|
|
|
wcscpy(pT, pStringBinding);
|
|
j += wcslen(pT) + 1;
|
|
pT = wcschr(pT, 0);
|
|
pT++;
|
|
|
|
status = RpcStringFree(&pStringBinding);
|
|
EQUAL(status, RPC_S_OK);
|
|
EQUAL(pStringBinding, 0);
|
|
}
|
|
|
|
*pT = 0;
|
|
pdsaMyExpandedStringBindings->wNumEntries = j + 1 + 2;
|
|
pdsaMyExpandedStringBindings->wSecurityOffset = j + 1;
|
|
pT[1] = 0; // no security
|
|
pT[2] = 0;
|
|
}
|
|
|
|
*ppdsa = MIDL_user_allocate(sizeof(DUALSTRINGARRAY) + pdsaMyExpandedStringBindings->wNumEntries * 2);
|
|
|
|
ASSERT(*ppdsa);
|
|
|
|
(*ppdsa)->wNumEntries = pdsaMyExpandedStringBindings->wNumEntries;
|
|
(*ppdsa)->wSecurityOffset = pdsaMyExpandedStringBindings->wSecurityOffset;
|
|
memcpy((*ppdsa)->aStringArray,
|
|
pdsaMyExpandedStringBindings->aStringArray,
|
|
pdsaMyExpandedStringBindings->wNumEntries * 2);
|
|
|
|
|
|
*ppdsaSecurity = MIDL_user_allocate(sizeof(DUALSTRINGARRAY) + 6*2);
|
|
ASSERT(*ppdsaSecurity);
|
|
|
|
(*ppdsaSecurity)->wNumEntries = 6;
|
|
(*ppdsaSecurity)->wSecurityOffset = 2;
|
|
(*ppdsaSecurity)->aStringArray[0] = 0;
|
|
(*ppdsaSecurity)->aStringArray[1] = 0;
|
|
(*ppdsaSecurity)->aStringArray[2] = 10; // authn winnt
|
|
(*ppdsaSecurity)->aStringArray[3] = -1; // authz none
|
|
(*ppdsaSecurity)->aStringArray[4] = 0;
|
|
(*ppdsaSecurity)->aStringArray[5] = 0;
|
|
|
|
return(0);
|
|
}
|
|
|
|
error_status_t
|
|
_RawRundownOid(
|
|
handle_t hRpc,
|
|
ORPCTHIS *pthis,
|
|
LOCALTHIS *plocalthis,
|
|
ORPCTHAT *pthat,
|
|
ULONG cOid,
|
|
OID aOid[],
|
|
UCHAR afOk[]
|
|
)
|
|
{
|
|
int i, j;
|
|
RPC_STATUS status;
|
|
BOOL fFound;
|
|
IPID ipidT;
|
|
UCHAR buffer[512];
|
|
WCHAR buffer1[256];
|
|
DWORD t;
|
|
BOOL f;
|
|
HANDLE hT;
|
|
TOKEN_USER *ptu;
|
|
|
|
ASSERT(cOid);
|
|
ASSERT(plocalthis->callcat == CALLCAT_SYNCHRONOUS);
|
|
ASSERT(plocalthis->dwClientThread == 0);
|
|
ASSERT(pthis->extensions == 0);
|
|
ASSERT(pthis->version.MajorVersion == COM_MAJOR_VERSION);
|
|
ASSERT(pthis->version.MinorVersion == COM_MINOR_VERSION);
|
|
ASSERT(pthis->flags == ORPCF_LOCAL);
|
|
ASSERT(pthis->reserved1 == 0);
|
|
ASSERT(pthat->extensions == 0);
|
|
pthat->flags = 0;
|
|
|
|
status = RpcImpersonateClient(0);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
t = 256;
|
|
f = GetUserNameW(buffer1, &t);
|
|
if (f == FALSE)
|
|
{
|
|
PrintToConsole("Get user name failed %d\n", GetLastError());
|
|
}
|
|
|
|
f = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, &hT);
|
|
EQUAL(f, TRUE);
|
|
CloseHandle(hT);
|
|
|
|
f = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hT);
|
|
EQUAL(f, TRUE);
|
|
|
|
f = GetTokenInformation(hT,
|
|
TokenUser,
|
|
buffer,
|
|
512,
|
|
&t);
|
|
EQUAL(f, TRUE);
|
|
ptu = (TOKEN_USER *)buffer;
|
|
|
|
CloseHandle(hT);
|
|
|
|
status = RpcBindingInqObject(hRpc, &ipidT);
|
|
ASSERT(status == RPC_S_OK);
|
|
|
|
PrintToConsole("Rundown of %d oids called by %S:\n\t", cOid, buffer1);
|
|
PrintSid(ptu->User.Sid);
|
|
|
|
for (j = 0; j < cOid; j++)
|
|
{
|
|
fFound = FALSE;
|
|
|
|
PrintToConsole("Oid %I64x randown\n", aOid[j]);
|
|
|
|
for(i = 0; i < dwlimRundowns; i++)
|
|
{
|
|
if (aOid[j] == aRundowns[i].oid)
|
|
{
|
|
fFound = TRUE;
|
|
if (aRundowns[i].fForceSecond)
|
|
{
|
|
aRundowns[i].fForceSecond = FALSE;
|
|
afOk[j] = 0;
|
|
}
|
|
else
|
|
{
|
|
afOk[j] = 1;
|
|
EQUAL(aRundowns[i].fReady, TRUE);
|
|
aRundowns[i].fReady = FALSE;
|
|
|
|
aRundowns[i].oid = aRundowns[dwlimRundowns - 1].oid;
|
|
aRundowns[i].fReady = aRundowns[dwlimRundowns - 1].fReady;
|
|
aRundowns[i].fForceSecond = aRundowns[dwlimRundowns - 1].fForceSecond;
|
|
dwlimRundowns--;
|
|
|
|
SetEvent(hRundownEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
PrintToConsole("Unexpected oid rundown: %I64x\n", aOid[j]);
|
|
afOk[j] = 1;
|
|
}
|
|
}
|
|
|
|
RpcRevertToSelf();
|
|
return(0);
|
|
|
|
}
|
|
|
|
// Unimplement IRundown base methods
|
|
|
|
HRESULT
|
|
_DummyQueryInterfaceIOSCM(
|
|
handle_t rpc,
|
|
ORPCTHIS *pthis,
|
|
LOCALTHIS *plocalthis,
|
|
ORPCTHAT *pthat,
|
|
DWORD dummy)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
HRESULT
|
|
_DummyAddRefIOSCM(
|
|
handle_t rpc,
|
|
ORPCTHIS *pthis,
|
|
LOCALTHIS *plocalthis,
|
|
ORPCTHAT *pthat,
|
|
DWORD dummy)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
HRESULT
|
|
_DummyReleaseIOSCM(
|
|
handle_t rpc,
|
|
ORPCTHIS *pthis,
|
|
LOCALTHIS *plocalthis,
|
|
ORPCTHAT *pthat,
|
|
DWORD dummy)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
HRESULT
|
|
_DummyRemQuery(
|
|
handle_t handle
|
|
)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
_DummyRemAddRef(
|
|
handle_t handle
|
|
)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
_DummyRemRelease(
|
|
handle_t handle
|
|
)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
HRESULT
|
|
_DummyRemChangeRef(
|
|
handle_t handle
|
|
)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
HRESULT
|
|
_DummyRemQueryInterface2(
|
|
handle_t handle
|
|
)
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
|
|
// Rundown helpers
|
|
|
|
void
|
|
AddRundown(ID oid, BOOL fRundownTwice)
|
|
{
|
|
aRundowns[dwlimRundowns].oid = oid;
|
|
aRundowns[dwlimRundowns].fReady = TRUE;
|
|
aRundowns[dwlimRundowns].fForceSecond = fRundownTwice;
|
|
|
|
dwlimRundowns++;
|
|
}
|
|
|
|
void WaitForAllRundowns()
|
|
{
|
|
DWORD status;
|
|
int i;
|
|
BOOL fDone;
|
|
|
|
PrintToConsole("Waiting for rundowns...\n");
|
|
|
|
for(;;)
|
|
{
|
|
status = WaitForSingleObject(hRundownEvent, 19 * 60 * 1000);
|
|
|
|
if (status == WAIT_TIMEOUT)
|
|
{
|
|
PrintToConsole("Wait for rundowns took a long time...\n");
|
|
ASSERT(0);
|
|
}
|
|
|
|
fDone = TRUE;
|
|
|
|
for(i = 0; i < dwlimRundowns; i++)
|
|
{
|
|
if (aRundowns[i].fReady)
|
|
{
|
|
fDone = FALSE;
|
|
}
|
|
}
|
|
|
|
if (fDone)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Needs to link rtifs.lib, but shouldn't be called..
|
|
void FixupForUniquePointerServers(void *p)
|
|
{
|
|
ASSERT(0);
|
|
}
|