From 4b2ab4975121a51150cf4db64e49f2a6c96d779b Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Tue, 5 Feb 2008 18:33:20 +0000 Subject: more eol-style git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20218 dc483132-0cff-0310-8789-dd5450dbe970 --- src/ccapi/lib/win/OldCC/client.cxx | 778 ++++++++++++++++++------------------- src/ccapi/lib/win/OldCC/rpc.cxx | 156 ++++---- src/ccapi/lib/win/ccapi.def | 76 ++-- src/ccapi/lib/win/ccapi_os_ipc.cxx | 744 +++++++++++++++++------------------ src/ccapi/lib/win/dllmain.cxx | 558 +++++++++++++------------- 5 files changed, 1156 insertions(+), 1156 deletions(-) (limited to 'src/ccapi/lib') diff --git a/src/ccapi/lib/win/OldCC/client.cxx b/src/ccapi/lib/win/OldCC/client.cxx index 1f9051093..4928d4c53 100644 --- a/src/ccapi/lib/win/OldCC/client.cxx +++ b/src/ccapi/lib/win/OldCC/client.cxx @@ -1,389 +1,389 @@ -/* - * $Header$ - * - * Copyright 2008 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#include "stdio.h" // KPKDBG - -#include "ccs_request.h" - -#include "ccapi.h" -#include "util.h" - -extern "C" { -#include "cci_debugging.h" -#include "tls.h" // KPKDBG - } - -#include "client.h" -#include "init.hxx" -#include "name.h" -#include "secure.hxx" - -#define SECONDS_TO_WAIT 10 - -#define STARTUP "CLIENT STARTUP: " -#define DISCONNECT "CLIENT DISCONNECT: " - -bool Client::s_init = false; -CcOsLock Client::sLock; - -static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) { - DWORD status = 0; - unsigned char * pszStringBinding = NULL; - - if (!ep) { - status = alloc_name(endpoint, "ep", isNT()); - } - else { - *endpoint = ep; - } - - if (!status) { - /* Use a convenience function to concatenate the elements of */ - /* the string binding into the proper sequence. */ - status = RpcStringBindingCompose(0, // uuid - (unsigned char*)"ncalrpc", // protseq - 0, // address - (unsigned char*)(*endpoint), // endpoint - 0, // options - &pszStringBinding); - cci_check_error(status); - } - - if (!status) { - /* Set the binding handle that will be used to bind to the server. */ - status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle); - cci_check_error(status); - } - - if (!status) { - // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not - // quite work on Win9x... - if (isNT()) { - RPC_SECURITY_QOS qos; - qos.Version = RPC_C_SECURITY_QOS_VERSION; - qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; - qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; - qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; - - status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle, - 0, // principal - RPC_C_AUTHN_LEVEL_CONNECT, - RPC_C_AUTHN_WINNT, - 0, // current address space - RPC_C_AUTHZ_NAME, - &qos); - cci_check_error(status); - } - } - - if (pszStringBinding) { - DWORD status = RpcStringFree(&pszStringBinding); - cci_check_error(status); - } - return cci_check_error(status); - } - -DWORD find_server(Init::InitInfo& info, LPSTR endpoint) { - DWORD status = 0; - LPSTR event_name = 0; - HANDLE hEvent = 0; - SECURITY_ATTRIBUTES sa = { 0 }; - PSECURITY_ATTRIBUTES psa = 0; - STARTUPINFO si = { 0 }; - PROCESS_INFORMATION pi = { 0 }; - char* szExe = 0; - char* szDir = 0; - BOOL bRes = FALSE; - char* cmdline = NULL; -#if 0 - HANDLE hToken = 0; -#endif - - psa = isNT() ? &sa : 0; - -// cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle); - status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle)); - if (status == RPC_S_NOT_LISTENING) { -// cci_debug_printf(" Server *NOT* found!"); - si.cb = sizeof(si); - - status = alloc_module_dir_name(CCAPI_DLL, &szDir); - - if (!status) { - status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe); - } - - if (!status) { - status = alloc_name(&event_name, "startup", isNT()); - cci_check_error(status); - } - - if (!status) { - if (isNT()) { - sa.nLength = sizeof(sa); - status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); - cci_check_error(status); - } - } - - if (!status) { - hEvent = CreateEvent(psa, FALSE, FALSE, event_name); - cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent); - if (!hEvent) status = GetLastError(); - } - - if (!status) { - -#if 0 - if (SecureClient::IsImp()) { - cci_debug_printf(STARTUP "Token is impersonation token")); - SecureClient::DuplicateImpAsPrimary(hToken); - } - else { - cci_debug_printf(STARTUP "Token is NOT impersonation token")); - } -#endif - -#if 0 - if (hToken) - bRes = CreateProcessAsUser(hToken, - szExe, // app name - NULL, // cmd line - psa, // SA - psa, // SA - FALSE, - CREATE_NEW_PROCESS_GROUP | - //CREATE_NEW_CONSOLE | - NORMAL_PRIORITY_CLASS | - // CREATE_NO_WINDOW | - DETACHED_PROCESS | - 0 - , - NULL, // environment - szDir, // current dir - &si, - &pi); - else -#endif - alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline); - bRes = CreateProcess( szExe, // app name - NULL, //cmdline, // cmd line is - psa, // SA - psa, // SA - FALSE, - CREATE_NEW_PROCESS_GROUP | - CREATE_NEW_CONSOLE | - NORMAL_PRIORITY_CLASS | - // CREATE_NO_WINDOW | - // DETACHED_PROCESS | /* KPK TODO: was set - restore */ - 0 - , - NULL, // environment - szDir, // current dir - &si, - &pi); - if (!bRes) { - status = GetLastError(); - cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status); - } - cci_debug_printf(" Waiting..."); - } - cci_check_error(status); - - if (!status) { - status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000); - status = RpcMgmtIsServerListening(ccs_request_IfHandle); - } - } - else if (status) { - cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status); - } - -#if 0 - if (hToken) - CloseHandle(hToken); -#endif - if (szDir) free_alloc_p(&szDir); - if (szExe) free_alloc_p(&szExe); - if (hEvent) CloseHandle(hEvent); - if (pi.hThread) CloseHandle(pi.hThread); - if (pi.hProcess) CloseHandle(pi.hProcess); - if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor); - return cci_check_error(status); - -} - -static -DWORD -authenticate_server(Init::InitInfo& info) { - DWORD challenge = 17; // XXX - maybe use random number - DWORD desired_response= challenge + 1; - HANDLE hMap = 0; - LPSTR mem_name = 0; - PDWORD pvalue = 0; - CC_UINT32 response = 0; - SECURITY_ATTRIBUTES sa = { 0 }; - DWORD status = 0; - - cci_debug_printf("%s entry", __FUNCTION__); - - status = alloc_name(&mem_name, "auth", isNT()); - cci_check_error(status); - - if (!status) { - if (isNT()) { - sa.nLength = sizeof(sa); - status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); - } - } - cci_check_error(status); - - if (!status) { - hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, - PAGE_READWRITE, 0, sizeof(DWORD), mem_name); - if (!hMap) - status = GetLastError(); - } - cci_check_error(status); - - if (!status) { - pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (!pvalue) status = GetLastError(); - } - cci_check_error(status); - - if (!status) { - *pvalue = challenge; - - RpcTryExcept { - response = ccs_authenticate( (CC_CHAR*)mem_name ); - } - RpcExcept(1) { - status = RpcExceptionCode(); - cci_check_error(status); - } - RpcEndExcept; - } - cci_check_error(status); - - if (!status) { - // Check response - if ((response != desired_response) && (*pvalue != desired_response)) { - cci_debug_printf(" Could not authenticate server."); - status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND? - } - else { - cci_debug_printf(" Server authenticated!"); - } - cci_check_error(status); - } - - free_alloc_p(&mem_name); - free_alloc_p(&sa.lpSecurityDescriptor); - if (pvalue) { - BOOL ok = UnmapViewOfFile(pvalue); -// DEBUG_ASSERT(ok); - } - if (hMap) CloseHandle(hMap); - return status; -} - -DWORD -Client::Disconnect() { - DWORD status = 0; - if (ccs_request_IfHandle) { - /* The calls to the remote procedures are complete. */ - /* Free the binding handle */ - status = RpcBindingFree(&ccs_request_IfHandle); - } - s_init = false; - return status; - } - -DWORD -Client::Connect(char* ep OPTIONAL) { - LPSTR endpoint = 0; - DWORD status = 0; - - if (!ccs_request_IfHandle) { - Init::InitInfo info; - - status = Init::Info(info); - cci_check_error(status); - - if (!status) { - status = bind_client(ep, info, &endpoint); - cci_check_error(status); - } - - if (!status) { - status = find_server(info, endpoint); - cci_check_error(status); - } - - if (!status) { - status = authenticate_server(info); - cci_check_error(status); - } - } - - - if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint); - - if (status) Client::Disconnect(); - return status; - } - -DWORD Client::Initialize(char* ep OPTIONAL) { - CcAutoLock AL(Client::sLock); - SecureClient s; - ccs_request_IfHandle = NULL; - if (s_init) return 0; - DWORD status = Client::Connect(ep); - if (!status) s_init = true; - return status; - } - -DWORD Client::Cleanup() { - CcAutoLock AL(Client::sLock); - SecureClient s; - return Client::Disconnect(); - } - -DWORD Client::Reconnect(char* ep OPTIONAL) { - CcAutoLock AL(Client::sLock); - SecureClient s; - DWORD status = 0; - - if (Initialized()) { - DWORD status = Client::Cleanup(); - } - if ( (!status) ) { - status = Client::Initialize(ep); - } - - return status; - } +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "stdio.h" // KPKDBG + +#include "ccs_request.h" + +#include "ccapi.h" +#include "util.h" + +extern "C" { +#include "cci_debugging.h" +#include "tls.h" // KPKDBG + } + +#include "client.h" +#include "init.hxx" +#include "name.h" +#include "secure.hxx" + +#define SECONDS_TO_WAIT 10 + +#define STARTUP "CLIENT STARTUP: " +#define DISCONNECT "CLIENT DISCONNECT: " + +bool Client::s_init = false; +CcOsLock Client::sLock; + +static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) { + DWORD status = 0; + unsigned char * pszStringBinding = NULL; + + if (!ep) { + status = alloc_name(endpoint, "ep", isNT()); + } + else { + *endpoint = ep; + } + + if (!status) { + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(0, // uuid + (unsigned char*)"ncalrpc", // protseq + 0, // address + (unsigned char*)(*endpoint), // endpoint + 0, // options + &pszStringBinding); + cci_check_error(status); + } + + if (!status) { + /* Set the binding handle that will be used to bind to the server. */ + status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle); + cci_check_error(status); + } + + if (!status) { + // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not + // quite work on Win9x... + if (isNT()) { + RPC_SECURITY_QOS qos; + qos.Version = RPC_C_SECURITY_QOS_VERSION; + qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; + qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; + qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; + + status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle, + 0, // principal + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + 0, // current address space + RPC_C_AUTHZ_NAME, + &qos); + cci_check_error(status); + } + } + + if (pszStringBinding) { + DWORD status = RpcStringFree(&pszStringBinding); + cci_check_error(status); + } + return cci_check_error(status); + } + +DWORD find_server(Init::InitInfo& info, LPSTR endpoint) { + DWORD status = 0; + LPSTR event_name = 0; + HANDLE hEvent = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + PSECURITY_ATTRIBUTES psa = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + char* szExe = 0; + char* szDir = 0; + BOOL bRes = FALSE; + char* cmdline = NULL; +#if 0 + HANDLE hToken = 0; +#endif + + psa = isNT() ? &sa : 0; + +// cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle); + status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle)); + if (status == RPC_S_NOT_LISTENING) { +// cci_debug_printf(" Server *NOT* found!"); + si.cb = sizeof(si); + + status = alloc_module_dir_name(CCAPI_DLL, &szDir); + + if (!status) { + status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + cci_check_error(status); + } + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + } + + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent); + if (!hEvent) status = GetLastError(); + } + + if (!status) { + +#if 0 + if (SecureClient::IsImp()) { + cci_debug_printf(STARTUP "Token is impersonation token")); + SecureClient::DuplicateImpAsPrimary(hToken); + } + else { + cci_debug_printf(STARTUP "Token is NOT impersonation token")); + } +#endif + +#if 0 + if (hToken) + bRes = CreateProcessAsUser(hToken, + szExe, // app name + NULL, // cmd line + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + //CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + DETACHED_PROCESS | + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + else +#endif + alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline); + bRes = CreateProcess( szExe, // app name + NULL, //cmdline, // cmd line is + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + // DETACHED_PROCESS | /* KPK TODO: was set - restore */ + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + if (!bRes) { + status = GetLastError(); + cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status); + } + cci_debug_printf(" Waiting..."); + } + cci_check_error(status); + + if (!status) { + status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000); + status = RpcMgmtIsServerListening(ccs_request_IfHandle); + } + } + else if (status) { + cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status); + } + +#if 0 + if (hToken) + CloseHandle(hToken); +#endif + if (szDir) free_alloc_p(&szDir); + if (szExe) free_alloc_p(&szExe); + if (hEvent) CloseHandle(hEvent); + if (pi.hThread) CloseHandle(pi.hThread); + if (pi.hProcess) CloseHandle(pi.hProcess); + if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor); + return cci_check_error(status); + +} + +static +DWORD +authenticate_server(Init::InitInfo& info) { + DWORD challenge = 17; // XXX - maybe use random number + DWORD desired_response= challenge + 1; + HANDLE hMap = 0; + LPSTR mem_name = 0; + PDWORD pvalue = 0; + CC_UINT32 response = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + + cci_debug_printf("%s entry", __FUNCTION__); + + status = alloc_name(&mem_name, "auth", isNT()); + cci_check_error(status); + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + } + } + cci_check_error(status); + + if (!status) { + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, + PAGE_READWRITE, 0, sizeof(DWORD), mem_name); + if (!hMap) + status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!pvalue) status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + *pvalue = challenge; + + RpcTryExcept { + response = ccs_authenticate( (CC_CHAR*)mem_name ); + } + RpcExcept(1) { + status = RpcExceptionCode(); + cci_check_error(status); + } + RpcEndExcept; + } + cci_check_error(status); + + if (!status) { + // Check response + if ((response != desired_response) && (*pvalue != desired_response)) { + cci_debug_printf(" Could not authenticate server."); + status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND? + } + else { + cci_debug_printf(" Server authenticated!"); + } + cci_check_error(status); + } + + free_alloc_p(&mem_name); + free_alloc_p(&sa.lpSecurityDescriptor); + if (pvalue) { + BOOL ok = UnmapViewOfFile(pvalue); +// DEBUG_ASSERT(ok); + } + if (hMap) CloseHandle(hMap); + return status; +} + +DWORD +Client::Disconnect() { + DWORD status = 0; + if (ccs_request_IfHandle) { + /* The calls to the remote procedures are complete. */ + /* Free the binding handle */ + status = RpcBindingFree(&ccs_request_IfHandle); + } + s_init = false; + return status; + } + +DWORD +Client::Connect(char* ep OPTIONAL) { + LPSTR endpoint = 0; + DWORD status = 0; + + if (!ccs_request_IfHandle) { + Init::InitInfo info; + + status = Init::Info(info); + cci_check_error(status); + + if (!status) { + status = bind_client(ep, info, &endpoint); + cci_check_error(status); + } + + if (!status) { + status = find_server(info, endpoint); + cci_check_error(status); + } + + if (!status) { + status = authenticate_server(info); + cci_check_error(status); + } + } + + + if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint); + + if (status) Client::Disconnect(); + return status; + } + +DWORD Client::Initialize(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + ccs_request_IfHandle = NULL; + if (s_init) return 0; + DWORD status = Client::Connect(ep); + if (!status) s_init = true; + return status; + } + +DWORD Client::Cleanup() { + CcAutoLock AL(Client::sLock); + SecureClient s; + return Client::Disconnect(); + } + +DWORD Client::Reconnect(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + DWORD status = 0; + + if (Initialized()) { + DWORD status = Client::Cleanup(); + } + if ( (!status) ) { + status = Client::Initialize(ep); + } + + return status; + } diff --git a/src/ccapi/lib/win/OldCC/rpc.cxx b/src/ccapi/lib/win/OldCC/rpc.cxx index 332f1c503..29edc3c57 100644 --- a/src/ccapi/lib/win/OldCC/rpc.cxx +++ b/src/ccapi/lib/win/OldCC/rpc.cxx @@ -1,79 +1,79 @@ -/* - * $Header$ - * - * Copyright 2008 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#include -#include - -extern "C" { -#include "CredentialsCache.h" -#include "secure.hxx" -#include "client.h" -#include "autolock.hxx" -#include "cci_debugging.h" - } - -extern HANDLE hCCAPIv2Mutex; - -#define MAKE_RPC_CALL(rc, x) \ -do { \ - WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \ - SecureClient* s = 0; \ - SecureClient::Start(s); \ - CcAutoLock* a = 0; \ - CcAutoLock::Start(a, Client::sLock); \ - RpcTryExcept { \ - cci_debug_printf("RpcTry: #x"); \ - x; \ - } \ - RpcExcept(1) { \ - rc = handle_exception(RpcExceptionCode()); \ - } \ - RpcEndExcept; \ - CcAutoLock::Stop(a); \ - SecureClient::Stop(s); \ - ReleaseMutex( hCCAPIv2Mutex ); \ -} while (0) - -static -DWORD -handle_exception(DWORD code) { - cci_debug_printf("Runtime reported exception %u", code); - if (code == RPC_S_SERVER_UNAVAILABLE) { - Client::Reconnect(0); - } - return 4; - } - -////////////////////////////////////////////////////////////////////////////// - -cc_int32 cc_initialize() { - - CLIENT_INIT_EX(true, 4); - cc_int32 rc = ccNoError; - - MAKE_RPC_CALL(rc, rc = 5); - return rc; +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +extern "C" { +#include "CredentialsCache.h" +#include "secure.hxx" +#include "client.h" +#include "autolock.hxx" +#include "cci_debugging.h" + } + +extern HANDLE hCCAPIv2Mutex; + +#define MAKE_RPC_CALL(rc, x) \ +do { \ + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \ + SecureClient* s = 0; \ + SecureClient::Start(s); \ + CcAutoLock* a = 0; \ + CcAutoLock::Start(a, Client::sLock); \ + RpcTryExcept { \ + cci_debug_printf("RpcTry: #x"); \ + x; \ + } \ + RpcExcept(1) { \ + rc = handle_exception(RpcExceptionCode()); \ + } \ + RpcEndExcept; \ + CcAutoLock::Stop(a); \ + SecureClient::Stop(s); \ + ReleaseMutex( hCCAPIv2Mutex ); \ +} while (0) + +static +DWORD +handle_exception(DWORD code) { + cci_debug_printf("Runtime reported exception %u", code); + if (code == RPC_S_SERVER_UNAVAILABLE) { + Client::Reconnect(0); + } + return 4; + } + +////////////////////////////////////////////////////////////////////////////// + +cc_int32 cc_initialize() { + + CLIENT_INIT_EX(true, 4); + cc_int32 rc = ccNoError; + + MAKE_RPC_CALL(rc, rc = 5); + return rc; } \ No newline at end of file diff --git a/src/ccapi/lib/win/ccapi.def b/src/ccapi/lib/win/ccapi.def index 0450331ec..d062e55f5 100644 --- a/src/ccapi/lib/win/ccapi.def +++ b/src/ccapi/lib/win/ccapi.def @@ -1,39 +1,39 @@ -;LIBRARY COMERR32 -HEAPSIZE 8192 - -EXPORTS - cci_debug_printf - - cc_initialize - - cci_string_new - cci_string_d_initializer - ccapi_string_release - - cci_credentials_iterator_new - cci_credentials_iterator_write - - cci_ccache_iterator_new - cci_ccache_iterator_write - - ccapi_ccache_iterator_release - ccapi_ccache_iterator_next - ccapi_ccache_iterator_clone - - ccapi_credentials_iterator_release - ccapi_credentials_iterator_next - ccapi_credentials_iterator_clone - -;debugging: - _cci_check_error - cci_os_ipc - cci_os_ipc_msg - cci_os_ipc_thread_init - cci_stream_data - cci_stream_write - cci_stream_new - - ccs_authenticate - - +;LIBRARY COMERR32 +HEAPSIZE 8192 + +EXPORTS + cci_debug_printf + + cc_initialize + + cci_string_new + cci_string_d_initializer + ccapi_string_release + + cci_credentials_iterator_new + cci_credentials_iterator_write + + cci_ccache_iterator_new + cci_ccache_iterator_write + + ccapi_ccache_iterator_release + ccapi_ccache_iterator_next + ccapi_ccache_iterator_clone + + ccapi_credentials_iterator_release + ccapi_credentials_iterator_next + ccapi_credentials_iterator_clone + +;debugging: + _cci_check_error + cci_os_ipc + cci_os_ipc_msg + cci_os_ipc_thread_init + cci_stream_data + cci_stream_write + cci_stream_new + + ccs_authenticate + + \ No newline at end of file diff --git a/src/ccapi/lib/win/ccapi_os_ipc.cxx b/src/ccapi/lib/win/ccapi_os_ipc.cxx index 7ee917627..770e75b6a 100644 --- a/src/ccapi/lib/win/ccapi_os_ipc.cxx +++ b/src/ccapi/lib/win/ccapi_os_ipc.cxx @@ -1,373 +1,373 @@ -/* - * $Header$ - * - * Copyright 2008 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -extern "C" { -#include "k5-thread.h" -#include "ccapi_os_ipc.h" -#include "tls.h" -#include "dllmain.h" -#include "ccs_reply.h" -#include "ccs_request.h" -#include "win-utils.h" -#include "ccutils.h" -#include "util.h" - } - -#include "CredentialsCache.h" -#include "secure.hxx" -#include "opts.hxx" -#include "client.h" -#include "autolock.hxx" -#include "cci_debugging.h" - -#define SECONDS_TO_WAIT 10 -#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle - -extern HANDLE hCCAPIv2Mutex; -ParseOpts::Opts opts = { 0 }; -PSECURITY_ATTRIBUTES psa = 0; -SECURITY_ATTRIBUTES sa = { 0 }; - -/* The layout of the rest of this module: - - The entrypoints defined in ccs_os_ipc.h: - cci_os_ipc_thread_init - cci_os_ipc - - Other routines needed by those four. - cci_os_connect - handle_exception - */ - -cc_int32 ccapi_connect(const struct tspdata* tsp); -static DWORD handle_exception(DWORD code); - -extern "C" { -cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, - cci_stream_t in_request_stream, - cc_int32 in_msg, - cci_stream_t* out_reply_stream); - } - -/* ------------------------------------------------------------------------ */ - -extern "C" cc_int32 cci_os_ipc_thread_init (void) { - cc_int32 err = ccNoError; - struct tspdata* ptspdata; - HANDLE replyEvent; - UUID __RPC_FAR uuid; - unsigned char __RPC_FAR* uuidString = NULL; - - if (!GetTspData(&ptspdata)) return ccErrNoMem; - - opts.cMinCalls = 1; - opts.cMaxCalls = 20; - opts.fDontWait = TRUE; - - err = cci_check_error(UuidCreate(&uuid)); // Get a UUID - if (err == RPC_S_OK) { // Convert to string - err = UuidToString(&uuid, &uuidString); - } - if (!err) { // Save in thread local storage - tspdata_setUUID(ptspdata, uuidString); - } - cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata)); - - // Initialize old CCAPI if necessary: - if (!err) if (!Init:: Initialized()) err = Init:: Initialize( ); - if (!err) if (!Client::Initialized()) err = Client::Initialize(0); - - if (!err) { - /* Whenever a reply to an RPC request is received, the RPC caller needs to - know when the reply has been received. It does that by waiting for a - client-specific event to be set. Define the event name to be _reply: */ - replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); - } - - if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); - else err = cci_check_error(GetLastError()); - - if (uuidString) RpcStringFree(&uuidString); - - return cci_check_error(err); - } - - -/* ------------------------------------------------------------------------ */ - -cc_int32 cci_os_ipc (cc_int32 in_launch_server, - cci_stream_t in_request_stream, - cci_stream_t* out_reply_stream) { - return cci_os_ipc_msg( in_launch_server, - in_request_stream, - CCMSG_REQUEST, - out_reply_stream); - } - -extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, - cci_stream_t in_request_stream, - cc_int32 in_msg, - cci_stream_t* out_reply_stream) { - - cc_int32 err = ccNoError; - cc_int32 done = FALSE; - cc_int32 try_count = 0; - cc_int32 server_died = FALSE; - TCHAR* pszStringBinding= NULL; - struct tspdata* ptspdata = NULL; - char* uuid = NULL; - int lenUUID = 0; - unsigned int trycount = 0; - time_t sst = 0; - STARTUPINFO si = { 0 }; - PROCESS_INFORMATION pi = { 0 }; - HANDLE replyEvent = 0; - BOOL bCCAPI_Connected= FALSE; - - if (!in_request_stream) { err = cci_check_error (ccErrBadParam); } - if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); } - - if (!GetTspData(&ptspdata)) {return ccErrBadParam;} - bCCAPI_Connected = tspdata_getConnected (ptspdata); - replyEvent = tspdata_getReplyEvent (ptspdata); - sst = tspdata_getSST (ptspdata); - uuid = tspdata_getUUID(ptspdata); - - // The lazy connection to the server has been put off as long as possible! - // ccapi_connect starts listening for replies as an RPC server and then - // calls ccs_rpc_connect. - if (!bCCAPI_Connected) { - err = cci_check_error(ccapi_connect(ptspdata)); - bCCAPI_Connected = !err; - tspdata_setConnected(ptspdata, bCCAPI_Connected); - } - - // Clear replyEvent so we can detect when a reply to our request has been received: - ResetEvent(replyEvent); - - //++ Use the old CCAPI implementation to try to talk to the server: - // It has all the code to use the RPC in a thread-safe way, make the endpoint, - // (re)connect and (re)start the server. - // Note: the old implementation wrapped the thread-safety stuff in a macro. - // Here it is expanded and thus duplicated for each RPC call. The new code has - // a very limited number of RPC calls, unlike the older code. - WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); - SecureClient* s = 0; - SecureClient::Start(s); - CcAutoLock* a = 0; - CcAutoLock::Start(a, Client::sLock); - - // Initialize old CCAPI if necessary: - if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); - if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); - - // New code using new RPC procedures for sending the data and receiving a reply: - if (!err) { - RpcTryExcept { - if (!GetTspData(&ptspdata)) {return ccErrBadParam;} - uuid = tspdata_getUUID(ptspdata); - lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */ - cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata); - cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst); - - ccs_rpc_request( /* make call with user message: */ - in_msg, /* Message type */ - (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */ - (unsigned char*)uuid, - cci_stream_size(in_request_stream), - (unsigned char*)cci_stream_data(in_request_stream), /* Data buffer */ - sst, /* session start time */ - (long*)(&err) ); /* Return code */ - } - RpcExcept(1) { - handle_exception(RpcExceptionCode()); - } - RpcEndExcept; - } - - cci_check_error(err); - CcAutoLock::Stop(a); - SecureClient::Stop(s); - ReleaseMutex(hCCAPIv2Mutex); - //-- Use the old CCAPI implementation to try to talk to the server. - - // Wait for reply handler to set event: - if (!err) { - cci_debug_printf(" Waiting for request reply."); - err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000)); - cci_debug_printf(" Request reply received!"); - } - - if (!err) { - err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); - } - - if (!err && server_died) { - err = cci_check_error (ccErrServerUnavailable); - } -#if 0 - if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { - err = ccNoError; /* If the server is not running just return an empty stream. */ - } -#endif - - if (!err) { - *out_reply_stream = tspdata_getStream(ptspdata); - } - - cci_debug_printf(" payload:<%s>", cci_stream_data(*out_reply_stream)); - - return cci_check_error (err); - } - - - -static DWORD handle_exception(DWORD code) { - cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); - if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { - Client::Reconnect(0); - } - return 4; - } - - -/* Establish a CCAPI connection with the server. - * The connect logic here is identical to the logic in the send request code. - * TODO: merge this connect code with that request code. - */ -cc_int32 ccapi_connect(const struct tspdata* tsp) { - BOOL bListen = TRUE; - char* endpoint = NULL; - HANDLE replyEvent = 0; - RPC_STATUS status = FALSE; - char* uuid = NULL; - - /* Start listening to our uuid before establishing the connection, - * so that when the server tries to call ccapi_listen, we will be ready. - */ - - /* Build complete RPC uuid using previous CCAPI implementation: */ - replyEvent = tspdata_getReplyEvent(tsp); - uuid = tspdata_getUUID(tsp); - endpoint = clientEndpoint(uuid); - cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); - - opts.cMinCalls = 1; - opts.cMaxCalls = 20; - opts.fDontWait = TRUE; - - if (!status) { - status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", - opts.cMaxCalls, - (RPC_CSTR)endpoint, - sa.lpSecurityDescriptor); // SD - cci_check_error(status); - } - - if (!status) { - status = RpcServerRegisterAuthInfo(0, // server principal - RPC_C_AUTHN_WINNT, - 0, - 0 ); - cci_check_error(status); - } - - cci_debug_printf("%s is listening ...", __FUNCTION__); - - if (!status) { - if (!isNT()) { - status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface - NULL, // MgrTypeUuid - NULL); // MgrEpv; null means use default - } - else { - status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface - NULL, // MgrTypeUuid - NULL, // MgrEpv; 0 means default - RPC_IF_ALLOW_SECURE_ONLY, - opts.cMaxCalls, - NULL); // No security callback. - } - - cci_check_error(status); - - if (!status) { - status = RpcServerListen(opts.cMinCalls, - opts.cMaxCalls, - TRUE); - cci_check_error(status); - } - } - - // Clear replyEvent so we can detect when a reply to our connect request has been received: - ResetEvent(replyEvent); - - // We use the old CCAPI implementation to try to talk to the server. - // It has all the code to make the uuid, (re)connect and (re)start the server. - WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); - SecureClient* s = 0; - SecureClient::Start(s); - CcAutoLock* a = 0; - CcAutoLock::Start(a, Client::sLock); - - // Initialize old CCAPI if necessary: - if (!status) if (!Init:: Initialized()) status = Init:: Initialize( ); - if (!status) if (!Client::Initialized()) status = Client::Initialize(0); - - // New code using new RPC procedures for sending the data and receiving a reply: - if (!status) { - RpcTryExcept { - ccs_rpc_connect( /* make call with user message: */ - CCMSG_CONNECT, /* Message type */ - (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */ - (unsigned char*)uuid, - (long*)(&status) ); /* Return code */ - } - RpcExcept(1) { - cci_check_error(RpcExceptionCode()); - status = ccErrBadInternalMessage; - } - RpcEndExcept; - } - - CcAutoLock::Stop(a); - SecureClient::Stop(s); - ReleaseMutex(hCCAPIv2Mutex); - - if (!status) { - cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__); - status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000); - status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); - cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : ""); - } - if (status) { - cci_debug_printf(" unexpected error while looking for server... (%u)", status); - } - - cci_debug_printf("%s TODO: check connect reply result.", __FUNCTION__); - cci_debug_printf("%s TODO: merge this connect code with that request code.", __FUNCTION__); - return status; +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include "k5-thread.h" +#include "ccapi_os_ipc.h" +#include "tls.h" +#include "dllmain.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" +#include "util.h" + } + +#include "CredentialsCache.h" +#include "secure.hxx" +#include "opts.hxx" +#include "client.h" +#include "autolock.hxx" +#include "cci_debugging.h" + +#define SECONDS_TO_WAIT 10 +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + +extern HANDLE hCCAPIv2Mutex; +ParseOpts::Opts opts = { 0 }; +PSECURITY_ATTRIBUTES psa = 0; +SECURITY_ATTRIBUTES sa = { 0 }; + +/* The layout of the rest of this module: + + The entrypoints defined in ccs_os_ipc.h: + cci_os_ipc_thread_init + cci_os_ipc + + Other routines needed by those four. + cci_os_connect + handle_exception + */ + +cc_int32 ccapi_connect(const struct tspdata* tsp); +static DWORD handle_exception(DWORD code); + +extern "C" { +cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream); + } + +/* ------------------------------------------------------------------------ */ + +extern "C" cc_int32 cci_os_ipc_thread_init (void) { + cc_int32 err = ccNoError; + struct tspdata* ptspdata; + HANDLE replyEvent; + UUID __RPC_FAR uuid; + unsigned char __RPC_FAR* uuidString = NULL; + + if (!GetTspData(&ptspdata)) return ccErrNoMem; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + err = cci_check_error(UuidCreate(&uuid)); // Get a UUID + if (err == RPC_S_OK) { // Convert to string + err = UuidToString(&uuid, &uuidString); + } + if (!err) { // Save in thread local storage + tspdata_setUUID(ptspdata, uuidString); + } + cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata)); + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = Init:: Initialize( ); + if (!err) if (!Client::Initialized()) err = Client::Initialize(0); + + if (!err) { + /* Whenever a reply to an RPC request is received, the RPC caller needs to + know when the reply has been received. It does that by waiting for a + client-specific event to be set. Define the event name to be _reply: */ + replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); + } + + if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); + else err = cci_check_error(GetLastError()); + + if (uuidString) RpcStringFree(&uuidString); + + return cci_check_error(err); + } + + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cci_stream_t* out_reply_stream) { + return cci_os_ipc_msg( in_launch_server, + in_request_stream, + CCMSG_REQUEST, + out_reply_stream); + } + +extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream) { + + cc_int32 err = ccNoError; + cc_int32 done = FALSE; + cc_int32 try_count = 0; + cc_int32 server_died = FALSE; + TCHAR* pszStringBinding= NULL; + struct tspdata* ptspdata = NULL; + char* uuid = NULL; + int lenUUID = 0; + unsigned int trycount = 0; + time_t sst = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + HANDLE replyEvent = 0; + BOOL bCCAPI_Connected= FALSE; + + if (!in_request_stream) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!GetTspData(&ptspdata)) {return ccErrBadParam;} + bCCAPI_Connected = tspdata_getConnected (ptspdata); + replyEvent = tspdata_getReplyEvent (ptspdata); + sst = tspdata_getSST (ptspdata); + uuid = tspdata_getUUID(ptspdata); + + // The lazy connection to the server has been put off as long as possible! + // ccapi_connect starts listening for replies as an RPC server and then + // calls ccs_rpc_connect. + if (!bCCAPI_Connected) { + err = cci_check_error(ccapi_connect(ptspdata)); + bCCAPI_Connected = !err; + tspdata_setConnected(ptspdata, bCCAPI_Connected); + } + + // Clear replyEvent so we can detect when a reply to our request has been received: + ResetEvent(replyEvent); + + //++ Use the old CCAPI implementation to try to talk to the server: + // It has all the code to use the RPC in a thread-safe way, make the endpoint, + // (re)connect and (re)start the server. + // Note: the old implementation wrapped the thread-safety stuff in a macro. + // Here it is expanded and thus duplicated for each RPC call. The new code has + // a very limited number of RPC calls, unlike the older code. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); + if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!err) { + RpcTryExcept { + if (!GetTspData(&ptspdata)) {return ccErrBadParam;} + uuid = tspdata_getUUID(ptspdata); + lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */ + cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata); + cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst); + + ccs_rpc_request( /* make call with user message: */ + in_msg, /* Message type */ + (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + cci_stream_size(in_request_stream), + (unsigned char*)cci_stream_data(in_request_stream), /* Data buffer */ + sst, /* session start time */ + (long*)(&err) ); /* Return code */ + } + RpcExcept(1) { + handle_exception(RpcExceptionCode()); + } + RpcEndExcept; + } + + cci_check_error(err); + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + //-- Use the old CCAPI implementation to try to talk to the server. + + // Wait for reply handler to set event: + if (!err) { + cci_debug_printf(" Waiting for request reply."); + err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000)); + cci_debug_printf(" Request reply received!"); + } + + if (!err) { + err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + } + + if (!err && server_died) { + err = cci_check_error (ccErrServerUnavailable); + } +#if 0 + if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { + err = ccNoError; /* If the server is not running just return an empty stream. */ + } +#endif + + if (!err) { + *out_reply_stream = tspdata_getStream(ptspdata); + } + + cci_debug_printf(" payload:<%s>", cci_stream_data(*out_reply_stream)); + + return cci_check_error (err); + } + + + +static DWORD handle_exception(DWORD code) { + cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); + if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { + Client::Reconnect(0); + } + return 4; + } + + +/* Establish a CCAPI connection with the server. + * The connect logic here is identical to the logic in the send request code. + * TODO: merge this connect code with that request code. + */ +cc_int32 ccapi_connect(const struct tspdata* tsp) { + BOOL bListen = TRUE; + char* endpoint = NULL; + HANDLE replyEvent = 0; + RPC_STATUS status = FALSE; + char* uuid = NULL; + + /* Start listening to our uuid before establishing the connection, + * so that when the server tries to call ccapi_listen, we will be ready. + */ + + /* Build complete RPC uuid using previous CCAPI implementation: */ + replyEvent = tspdata_getReplyEvent(tsp); + uuid = tspdata_getUUID(tsp); + endpoint = clientEndpoint(uuid); + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + if (!status) { + status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", + opts.cMaxCalls, + (RPC_CSTR)endpoint, + sa.lpSecurityDescriptor); // SD + cci_check_error(status); + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0 ); + cci_check_error(status); + } + + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!status) { + if (!isNT()) { + status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + opts.cMaxCalls, + NULL); // No security callback. + } + + cci_check_error(status); + + if (!status) { + status = RpcServerListen(opts.cMinCalls, + opts.cMaxCalls, + TRUE); + cci_check_error(status); + } + } + + // Clear replyEvent so we can detect when a reply to our connect request has been received: + ResetEvent(replyEvent); + + // We use the old CCAPI implementation to try to talk to the server. + // It has all the code to make the uuid, (re)connect and (re)start the server. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!status) if (!Init:: Initialized()) status = Init:: Initialize( ); + if (!status) if (!Client::Initialized()) status = Client::Initialize(0); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!status) { + RpcTryExcept { + ccs_rpc_connect( /* make call with user message: */ + CCMSG_CONNECT, /* Message type */ + (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + (long*)(&status) ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + status = ccErrBadInternalMessage; + } + RpcEndExcept; + } + + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + + if (!status) { + cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__); + status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000); + status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : ""); + } + if (status) { + cci_debug_printf(" unexpected error while looking for server... (%u)", status); + } + + cci_debug_printf("%s TODO: check connect reply result.", __FUNCTION__); + cci_debug_printf("%s TODO: merge this connect code with that request code.", __FUNCTION__); + return status; } \ No newline at end of file diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx index 7000e1418..dafbab28c 100644 --- a/src/ccapi/lib/win/dllmain.cxx +++ b/src/ccapi/lib/win/dllmain.cxx @@ -1,279 +1,279 @@ -/* - * $Header$ - * - * Copyright 2008 Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - */ - -#include -#include - -extern "C" { -#include "dllmain.h" -#include "tls.h" -#include "cci_debugging.h" -#include "ccapi_context.h" -#include "client.h" - -//void cci_thread_init__auxinit(); - } - -#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") - -// Process-specific data: -static DWORD dwTlsIndex; -static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. -static HANDLE sessionToken; -static char* ep_prefices[] = {"CCS", "CCAPI"}; -HANDLE hCCAPIv2Mutex = NULL; -DWORD firstThreadID = 0; - -// These data structures are used by the old CCAPI implementation -// to keep track of the state of the RPC connection. All data is static. -static Init init; -static Client client; - -// DllMain() is the entry-point function for this DLL. -BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle - DWORD fdwReason, // reason called - LPVOID lpvReserved) { // reserved - - struct tspdata* ptspdata; - BOOL fIgnore; - BOOL bStatus; - DWORD status = 0; // 0 is success. - DWORD maxUN = sizeof(_user); - unsigned int i = 0; - unsigned int j = 0; - - switch (fdwReason) { - // The DLL is loading due to process initialization or a call to LoadLibrary: - case DLL_PROCESS_ATTACH: - cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); - // Process-wide mutex used to allow only one thread at a time into the RPC code: - hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); - - // Figure out our username; it's process-wide: - bStatus = GetUserName(_user, &maxUN); - if (!bStatus) return bStatus; - - // Remove any characters that aren't valid endpoint characters: - while (_user[j] != 0) { - if (isalnum(_user[j])) _user[i++] = _user[j]; - j++; - } - _user[i] = '\0'; - - // Our logon session is determined in client.cxx, old CCAPI code carried - // over to this implementation. - - // Allocate a TLS index: - if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; - - // Initialize CCAPI once per DLL load: - firstThreadID = GetCurrentThreadId(); - - // Don't break; fallthrough: Initialize the TLS index for first thread. - - // The attached process creates a new thread: - case DLL_THREAD_ATTACH: - // Initialize the TLS index for this thread: - ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata)); - cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata); - if (ptspdata == NULL) return FALSE; - fIgnore = TlsSetValue(dwTlsIndex, ptspdata); - - memset(ptspdata, 0, sizeof(struct tspdata)); - - // Initialize CCAPI once per DLL load: - if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit(); - - break; - - // The thread of the attached process terminates: - case DLL_THREAD_DETACH: - cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); - // Release the allocated memory for this thread: - ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); - if (ptspdata != NULL) { - LocalFree((HLOCAL) ptspdata); - TlsSetValue(dwTlsIndex, NULL); - } - break; - - // DLL unload due to process termination or FreeLibrary: - case DLL_PROCESS_DETACH: - cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); - //++ Copied from previous implementation: - // Process Teardown "Problem" - // - // There are two problems that occur during process teardown: - // - // 1) Windows (NT/9x/2000) does not keep track of load/unload - // ordering dependencies for use in process teardown. - // - // 2) The RPC exception handling in the RPC calls do not work - // during process shutdown in Win9x. - // - // When a process is being torn down in Windows, the krbcc DLL - // may get a DLL_PROCESS_DETACH before other DLLs are done - // with it. Thus, it may disconnect from the RPC server - // before the last shutdown RPC call. - // - // On NT/2000, this is ok because the RPC call will fail and just - // return an error. - // - // On Win9x/Me, the RPC exception will not be caught. - // However, Win9x ignores exceptions during process shutdown, - // so the exception will never be seen unless a debugger is - // attached to the proccess. - // - // A good potential woraround would be to have a global - // variable that denotes whether the DLL is attached to the - // process. If it is not, all entrypoints into the DLL should - // return failure. - // - // A not as good workaround is below but ifdefed out. - // - // However, we can safely ignore this problem since it can - // only affects people running debuggers under 9x/Me who are - // using multiple DLLs that use this DLL. - // - WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); -#if 0 - bool process_teardown_workaround = false; - if (lpvReserved) { - Init::InitInfo info; - status = Init::Info(info); - if (status) break; - if (!info.isNT) process_teardown_workaround = true; - } - if (process_teardown_workaround) - break; -#endif - // return value is ignored, so we set status for debugging purposes - status = Client::Cleanup(); - status = Init::Cleanup(); - ReleaseMutex( hCCAPIv2Mutex ); - CloseHandle( hCCAPIv2Mutex ); - //-- Copied from previous implementation. - - // Release the allocated memory for this thread: - ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); - if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata); - TlsFree(dwTlsIndex); // Release the TLS index. - break; - - default: break; - } - - UNREFERENCED_PARAMETER(hinstDLL); // no whining! - UNREFERENCED_PARAMETER(lpvReserved); - return status ? FALSE : TRUE; -} - - -#ifdef __cplusplus // If used by C++ code, -extern "C" { // we need to export the C interface -#endif - -__declspec(dllexport) -BOOL WINAPI PutTspData(struct tspdata* dw) { - LPVOID lpvData; - struct tspdata** pData; // The stored memory pointer - - // Retrieve a data pointer for the current thread: - lpvData = TlsGetValue(dwTlsIndex); - - // If NULL, allocate memory for the TLS slot for this thread: - if (lpvData == NULL) { - lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata)); - if (lpvData == NULL) return FALSE; - if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE; - } - - pData = (struct tspdata**) lpvData; // Cast to my data type. - // In this example, it is only a pointer to a DWORD - // but it can be a structure pointer to contain more complicated data. - - (*pData) = dw; - return TRUE; - } - -__declspec(dllexport) -BOOL WINAPI GetTspData(struct tspdata** pdw) { - struct tspdata* pData; // The stored memory pointer - - pData = (struct tspdata*)TlsGetValue(dwTlsIndex); - if (pData == NULL) return FALSE; - (*pdw) = pData; - return TRUE; - } - -#if 0 // replaced by clientEndpoint / serverEndpoint. -__declspec(dllexport) -char* WINAPI getEndpoint(enum EndpointType ep) { - // The server endpoint is of the form CCS_ - // The client endpoint is of the form CCAPI_ - // Each client thread can have its own connection. - // - // NB: Caller must free the data the returned char* points to. - struct tspdata* pData; - char* s; - char* uuid; - unsigned int len; - - switch (ep) { - case EPT_SERVER: - s = (char*)malloc(32); // Length of CCS_ - sprintf(s, "%s_%ld", ep_prefices[EPT_SERVER], sessionToken); - break; - case EPT_CLIENT: - GetTspData(&pData); - uuid = tspdata_getUUID(pData); - len = 4 + strlen(ep_prefices[ep]) + strlen(_user) + strlen(uuid); - s = (char*)malloc(len); - sprintf(s, "%s_%s_%s", ep_prefices[EPT_CLIENT], _user, uuid); - break; - default:; - } - cci_debug_printf("%s(%d) returning %s", __FUNCTION__, ep, s); - - return s; - } -#endif - -#ifdef __cplusplus -} -#endif - -/*********************************************************************/ -/* MIDL allocate and free */ -/*********************************************************************/ - -void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { - return(malloc(len)); - } - -void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { - free(ptr); - } +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +extern "C" { +#include "dllmain.h" +#include "tls.h" +#include "cci_debugging.h" +#include "ccapi_context.h" +#include "client.h" + +//void cci_thread_init__auxinit(); + } + +#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") + +// Process-specific data: +static DWORD dwTlsIndex; +static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. +static HANDLE sessionToken; +static char* ep_prefices[] = {"CCS", "CCAPI"}; +HANDLE hCCAPIv2Mutex = NULL; +DWORD firstThreadID = 0; + +// These data structures are used by the old CCAPI implementation +// to keep track of the state of the RPC connection. All data is static. +static Init init; +static Client client; + +// DllMain() is the entry-point function for this DLL. +BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD fdwReason, // reason called + LPVOID lpvReserved) { // reserved + + struct tspdata* ptspdata; + BOOL fIgnore; + BOOL bStatus; + DWORD status = 0; // 0 is success. + DWORD maxUN = sizeof(_user); + unsigned int i = 0; + unsigned int j = 0; + + switch (fdwReason) { + // The DLL is loading due to process initialization or a call to LoadLibrary: + case DLL_PROCESS_ATTACH: + cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); + // Process-wide mutex used to allow only one thread at a time into the RPC code: + hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); + + // Figure out our username; it's process-wide: + bStatus = GetUserName(_user, &maxUN); + if (!bStatus) return bStatus; + + // Remove any characters that aren't valid endpoint characters: + while (_user[j] != 0) { + if (isalnum(_user[j])) _user[i++] = _user[j]; + j++; + } + _user[i] = '\0'; + + // Our logon session is determined in client.cxx, old CCAPI code carried + // over to this implementation. + + // Allocate a TLS index: + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + // Initialize CCAPI once per DLL load: + firstThreadID = GetCurrentThreadId(); + + // Don't break; fallthrough: Initialize the TLS index for first thread. + + // The attached process creates a new thread: + case DLL_THREAD_ATTACH: + // Initialize the TLS index for this thread: + ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata)); + cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata); + if (ptspdata == NULL) return FALSE; + fIgnore = TlsSetValue(dwTlsIndex, ptspdata); + + memset(ptspdata, 0, sizeof(struct tspdata)); + + // Initialize CCAPI once per DLL load: + if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit(); + + break; + + // The thread of the attached process terminates: + case DLL_THREAD_DETACH: + cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) { + LocalFree((HLOCAL) ptspdata); + TlsSetValue(dwTlsIndex, NULL); + } + break; + + // DLL unload due to process termination or FreeLibrary: + case DLL_PROCESS_DETACH: + cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); + //++ Copied from previous implementation: + // Process Teardown "Problem" + // + // There are two problems that occur during process teardown: + // + // 1) Windows (NT/9x/2000) does not keep track of load/unload + // ordering dependencies for use in process teardown. + // + // 2) The RPC exception handling in the RPC calls do not work + // during process shutdown in Win9x. + // + // When a process is being torn down in Windows, the krbcc DLL + // may get a DLL_PROCESS_DETACH before other DLLs are done + // with it. Thus, it may disconnect from the RPC server + // before the last shutdown RPC call. + // + // On NT/2000, this is ok because the RPC call will fail and just + // return an error. + // + // On Win9x/Me, the RPC exception will not be caught. + // However, Win9x ignores exceptions during process shutdown, + // so the exception will never be seen unless a debugger is + // attached to the proccess. + // + // A good potential woraround would be to have a global + // variable that denotes whether the DLL is attached to the + // process. If it is not, all entrypoints into the DLL should + // return failure. + // + // A not as good workaround is below but ifdefed out. + // + // However, we can safely ignore this problem since it can + // only affects people running debuggers under 9x/Me who are + // using multiple DLLs that use this DLL. + // + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); +#if 0 + bool process_teardown_workaround = false; + if (lpvReserved) { + Init::InitInfo info; + status = Init::Info(info); + if (status) break; + if (!info.isNT) process_teardown_workaround = true; + } + if (process_teardown_workaround) + break; +#endif + // return value is ignored, so we set status for debugging purposes + status = Client::Cleanup(); + status = Init::Cleanup(); + ReleaseMutex( hCCAPIv2Mutex ); + CloseHandle( hCCAPIv2Mutex ); + //-- Copied from previous implementation. + + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata); + TlsFree(dwTlsIndex); // Release the TLS index. + break; + + default: break; + } + + UNREFERENCED_PARAMETER(hinstDLL); // no whining! + UNREFERENCED_PARAMETER(lpvReserved); + return status ? FALSE : TRUE; +} + + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +__declspec(dllexport) +BOOL WINAPI PutTspData(struct tspdata* dw) { + LPVOID lpvData; + struct tspdata** pData; // The stored memory pointer + + // Retrieve a data pointer for the current thread: + lpvData = TlsGetValue(dwTlsIndex); + + // If NULL, allocate memory for the TLS slot for this thread: + if (lpvData == NULL) { + lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata)); + if (lpvData == NULL) return FALSE; + if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE; + } + + pData = (struct tspdata**) lpvData; // Cast to my data type. + // In this example, it is only a pointer to a DWORD + // but it can be a structure pointer to contain more complicated data. + + (*pData) = dw; + return TRUE; + } + +__declspec(dllexport) +BOOL WINAPI GetTspData(struct tspdata** pdw) { + struct tspdata* pData; // The stored memory pointer + + pData = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (pData == NULL) return FALSE; + (*pdw) = pData; + return TRUE; + } + +#if 0 // replaced by clientEndpoint / serverEndpoint. +__declspec(dllexport) +char* WINAPI getEndpoint(enum EndpointType ep) { + // The server endpoint is of the form CCS_ + // The client endpoint is of the form CCAPI_ + // Each client thread can have its own connection. + // + // NB: Caller must free the data the returned char* points to. + struct tspdata* pData; + char* s; + char* uuid; + unsigned int len; + + switch (ep) { + case EPT_SERVER: + s = (char*)malloc(32); // Length of CCS_ + sprintf(s, "%s_%ld", ep_prefices[EPT_SERVER], sessionToken); + break; + case EPT_CLIENT: + GetTspData(&pData); + uuid = tspdata_getUUID(pData); + len = 4 + strlen(ep_prefices[ep]) + strlen(_user) + strlen(uuid); + s = (char*)malloc(len); + sprintf(s, "%s_%s_%s", ep_prefices[EPT_CLIENT], _user, uuid); + break; + default:; + } + cci_debug_printf("%s(%d) returning %s", __FUNCTION__, ep, s); + + return s; + } +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } -- cgit