/*++ 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 #include #include #include #include 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); }