1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert * $Header$
3*7f2fe78bSCy Schubert *
4*7f2fe78bSCy Schubert * Copyright 2008 Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert #include "stdio.h" // KPKDBG
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert #include "ccs_request.h"
30*7f2fe78bSCy Schubert
31*7f2fe78bSCy Schubert #include "ccapi.h"
32*7f2fe78bSCy Schubert #include "util.h"
33*7f2fe78bSCy Schubert
34*7f2fe78bSCy Schubert extern "C" {
35*7f2fe78bSCy Schubert #include "cci_debugging.h"
36*7f2fe78bSCy Schubert #include "tls.h" // KPKDBG
37*7f2fe78bSCy Schubert }
38*7f2fe78bSCy Schubert
39*7f2fe78bSCy Schubert #include "client.h"
40*7f2fe78bSCy Schubert #include "init.hxx"
41*7f2fe78bSCy Schubert #include "name.h"
42*7f2fe78bSCy Schubert #include "secure.hxx"
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert #define SECONDS_TO_WAIT 10
45*7f2fe78bSCy Schubert
46*7f2fe78bSCy Schubert #define STARTUP "CLIENT STARTUP: "
47*7f2fe78bSCy Schubert #define DISCONNECT "CLIENT DISCONNECT: "
48*7f2fe78bSCy Schubert
49*7f2fe78bSCy Schubert bool Client::s_init = false;
50*7f2fe78bSCy Schubert CcOsLock Client::sLock;
51*7f2fe78bSCy Schubert
bind_client(char * ep OPTIONAL,Init::InitInfo & info,LPSTR * endpoint)52*7f2fe78bSCy Schubert static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) {
53*7f2fe78bSCy Schubert DWORD status = 0;
54*7f2fe78bSCy Schubert unsigned char * pszStringBinding = NULL;
55*7f2fe78bSCy Schubert
56*7f2fe78bSCy Schubert if (!ep) {
57*7f2fe78bSCy Schubert status = alloc_name(endpoint, "ep", isNT());
58*7f2fe78bSCy Schubert }
59*7f2fe78bSCy Schubert else {
60*7f2fe78bSCy Schubert *endpoint = ep;
61*7f2fe78bSCy Schubert }
62*7f2fe78bSCy Schubert
63*7f2fe78bSCy Schubert if (!status) {
64*7f2fe78bSCy Schubert /* Use a convenience function to concatenate the elements of */
65*7f2fe78bSCy Schubert /* the string binding into the proper sequence. */
66*7f2fe78bSCy Schubert status = RpcStringBindingCompose(0, // uuid
67*7f2fe78bSCy Schubert (unsigned char*)"ncalrpc", // protseq
68*7f2fe78bSCy Schubert 0, // address
69*7f2fe78bSCy Schubert (unsigned char*)(*endpoint), // endpoint
70*7f2fe78bSCy Schubert 0, // options
71*7f2fe78bSCy Schubert &pszStringBinding);
72*7f2fe78bSCy Schubert cci_check_error(status);
73*7f2fe78bSCy Schubert }
74*7f2fe78bSCy Schubert
75*7f2fe78bSCy Schubert if (!status) {
76*7f2fe78bSCy Schubert /* Set the binding handle that will be used to bind to the server. */
77*7f2fe78bSCy Schubert status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle);
78*7f2fe78bSCy Schubert cci_check_error(status);
79*7f2fe78bSCy Schubert }
80*7f2fe78bSCy Schubert
81*7f2fe78bSCy Schubert if (!status) {
82*7f2fe78bSCy Schubert // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not
83*7f2fe78bSCy Schubert // quite work on Win9x...
84*7f2fe78bSCy Schubert if (isNT()) {
85*7f2fe78bSCy Schubert RPC_SECURITY_QOS qos;
86*7f2fe78bSCy Schubert qos.Version = RPC_C_SECURITY_QOS_VERSION;
87*7f2fe78bSCy Schubert qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
88*7f2fe78bSCy Schubert qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
89*7f2fe78bSCy Schubert qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
90*7f2fe78bSCy Schubert
91*7f2fe78bSCy Schubert status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle,
92*7f2fe78bSCy Schubert 0, // principal
93*7f2fe78bSCy Schubert RPC_C_AUTHN_LEVEL_CONNECT,
94*7f2fe78bSCy Schubert RPC_C_AUTHN_WINNT,
95*7f2fe78bSCy Schubert 0, // current address space
96*7f2fe78bSCy Schubert RPC_C_AUTHZ_NAME,
97*7f2fe78bSCy Schubert &qos);
98*7f2fe78bSCy Schubert cci_check_error(status);
99*7f2fe78bSCy Schubert }
100*7f2fe78bSCy Schubert }
101*7f2fe78bSCy Schubert
102*7f2fe78bSCy Schubert if (pszStringBinding) {
103*7f2fe78bSCy Schubert DWORD status = RpcStringFree(&pszStringBinding);
104*7f2fe78bSCy Schubert cci_check_error(status);
105*7f2fe78bSCy Schubert }
106*7f2fe78bSCy Schubert return cci_check_error(status);
107*7f2fe78bSCy Schubert }
108*7f2fe78bSCy Schubert
find_server(Init::InitInfo & info,LPSTR endpoint)109*7f2fe78bSCy Schubert DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
110*7f2fe78bSCy Schubert DWORD status = 0;
111*7f2fe78bSCy Schubert LPSTR event_name = 0;
112*7f2fe78bSCy Schubert HANDLE hEvent = 0;
113*7f2fe78bSCy Schubert SECURITY_ATTRIBUTES sa = { 0 };
114*7f2fe78bSCy Schubert PSECURITY_ATTRIBUTES psa = 0;
115*7f2fe78bSCy Schubert STARTUPINFO si = { 0 };
116*7f2fe78bSCy Schubert PROCESS_INFORMATION pi = { 0 };
117*7f2fe78bSCy Schubert char* szExe = 0;
118*7f2fe78bSCy Schubert char* szDir = 0;
119*7f2fe78bSCy Schubert BOOL bRes = FALSE;
120*7f2fe78bSCy Schubert char* cmdline = NULL;
121*7f2fe78bSCy Schubert
122*7f2fe78bSCy Schubert psa = isNT() ? &sa : 0;
123*7f2fe78bSCy Schubert
124*7f2fe78bSCy Schubert cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle);
125*7f2fe78bSCy Schubert status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle));
126*7f2fe78bSCy Schubert if (status == RPC_S_NOT_LISTENING) {
127*7f2fe78bSCy Schubert cci_debug_printf(" Server *NOT* found!");
128*7f2fe78bSCy Schubert si.cb = sizeof(si);
129*7f2fe78bSCy Schubert
130*7f2fe78bSCy Schubert status = alloc_module_dir_name(CCAPI_DLL, &szDir);
131*7f2fe78bSCy Schubert
132*7f2fe78bSCy Schubert if (!status) {
133*7f2fe78bSCy Schubert status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe);
134*7f2fe78bSCy Schubert }
135*7f2fe78bSCy Schubert
136*7f2fe78bSCy Schubert if (!status) {
137*7f2fe78bSCy Schubert status = alloc_name(&event_name, "startup", isNT());
138*7f2fe78bSCy Schubert cci_check_error(status);
139*7f2fe78bSCy Schubert }
140*7f2fe78bSCy Schubert
141*7f2fe78bSCy Schubert if (!status) {
142*7f2fe78bSCy Schubert if (isNT()) {
143*7f2fe78bSCy Schubert sa.nLength = sizeof(sa);
144*7f2fe78bSCy Schubert status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
145*7f2fe78bSCy Schubert cci_check_error(status);
146*7f2fe78bSCy Schubert }
147*7f2fe78bSCy Schubert }
148*7f2fe78bSCy Schubert
149*7f2fe78bSCy Schubert if (!status) {
150*7f2fe78bSCy Schubert hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
151*7f2fe78bSCy Schubert cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent);
152*7f2fe78bSCy Schubert if (!hEvent) status = GetLastError();
153*7f2fe78bSCy Schubert }
154*7f2fe78bSCy Schubert
155*7f2fe78bSCy Schubert if (!status) {
156*7f2fe78bSCy Schubert alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);
157*7f2fe78bSCy Schubert bRes = CreateProcess( szExe, // app name
158*7f2fe78bSCy Schubert NULL, //cmdline, // cmd line is <server endpoint -[DC]>
159*7f2fe78bSCy Schubert psa, // SA
160*7f2fe78bSCy Schubert psa, // SA
161*7f2fe78bSCy Schubert FALSE,
162*7f2fe78bSCy Schubert CREATE_NEW_PROCESS_GROUP |
163*7f2fe78bSCy Schubert NORMAL_PRIORITY_CLASS |
164*7f2fe78bSCy Schubert #ifdef CCAPI_LAUNCH_SERVER_WITH_CONSOLE
165*7f2fe78bSCy Schubert CREATE_NEW_CONSOLE |
166*7f2fe78bSCy Schubert #else
167*7f2fe78bSCy Schubert DETACHED_PROCESS |
168*7f2fe78bSCy Schubert #endif
169*7f2fe78bSCy Schubert 0,
170*7f2fe78bSCy Schubert NULL, // environment
171*7f2fe78bSCy Schubert szDir, // current dir
172*7f2fe78bSCy Schubert &si,
173*7f2fe78bSCy Schubert &pi);
174*7f2fe78bSCy Schubert if (!bRes) {
175*7f2fe78bSCy Schubert status = GetLastError();
176*7f2fe78bSCy Schubert cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status);
177*7f2fe78bSCy Schubert }
178*7f2fe78bSCy Schubert cci_debug_printf(" Waiting...");
179*7f2fe78bSCy Schubert }
180*7f2fe78bSCy Schubert cci_check_error(status);
181*7f2fe78bSCy Schubert
182*7f2fe78bSCy Schubert if (!status) {
183*7f2fe78bSCy Schubert status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000);
184*7f2fe78bSCy Schubert status = RpcMgmtIsServerListening(ccs_request_IfHandle);
185*7f2fe78bSCy Schubert }
186*7f2fe78bSCy Schubert }
187*7f2fe78bSCy Schubert else if (status) {
188*7f2fe78bSCy Schubert cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);
189*7f2fe78bSCy Schubert }
190*7f2fe78bSCy Schubert
191*7f2fe78bSCy Schubert if (szDir) free_alloc_p(&szDir);
192*7f2fe78bSCy Schubert if (szExe) free_alloc_p(&szExe);
193*7f2fe78bSCy Schubert if (hEvent) CloseHandle(hEvent);
194*7f2fe78bSCy Schubert if (pi.hThread) CloseHandle(pi.hThread);
195*7f2fe78bSCy Schubert if (pi.hProcess) CloseHandle(pi.hProcess);
196*7f2fe78bSCy Schubert if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor);
197*7f2fe78bSCy Schubert return cci_check_error(status);
198*7f2fe78bSCy Schubert
199*7f2fe78bSCy Schubert }
200*7f2fe78bSCy Schubert
201*7f2fe78bSCy Schubert static
202*7f2fe78bSCy Schubert DWORD
make_random_challenge(DWORD * challenge_out)203*7f2fe78bSCy Schubert make_random_challenge(DWORD *challenge_out) {
204*7f2fe78bSCy Schubert HCRYPTPROV provider;
205*7f2fe78bSCy Schubert DWORD status = 0;
206*7f2fe78bSCy Schubert *challenge_out = 0;
207*7f2fe78bSCy Schubert if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
208*7f2fe78bSCy Schubert CRYPT_VERIFYCONTEXT)) {
209*7f2fe78bSCy Schubert status = GetLastError();
210*7f2fe78bSCy Schubert cci_check_error(status);
211*7f2fe78bSCy Schubert return status;
212*7f2fe78bSCy Schubert }
213*7f2fe78bSCy Schubert if (!CryptGenRandom(provider, sizeof(*challenge_out),
214*7f2fe78bSCy Schubert (BYTE *)challenge_out)) {
215*7f2fe78bSCy Schubert status = GetLastError();
216*7f2fe78bSCy Schubert cci_check_error(status);
217*7f2fe78bSCy Schubert return status;
218*7f2fe78bSCy Schubert }
219*7f2fe78bSCy Schubert if (!CryptReleaseContext(provider, 0)) {
220*7f2fe78bSCy Schubert /*
221*7f2fe78bSCy Schubert * Note: even though CryptReleaseContext() failed, we don't really
222*7f2fe78bSCy Schubert * care since a) we've already successfully obtained our challenge
223*7f2fe78bSCy Schubert * anyway and b) at least one of the potential errors, "ERROR_BUSY"
224*7f2fe78bSCy Schubert * does not really seem to be an error at all. So GetLastError() is
225*7f2fe78bSCy Schubert * logged for informational purposes only and should not be returned.
226*7f2fe78bSCy Schubert */
227*7f2fe78bSCy Schubert cci_check_error(GetLastError());
228*7f2fe78bSCy Schubert }
229*7f2fe78bSCy Schubert return status;
230*7f2fe78bSCy Schubert }
231*7f2fe78bSCy Schubert
232*7f2fe78bSCy Schubert static
233*7f2fe78bSCy Schubert DWORD
authenticate_server(Init::InitInfo & info)234*7f2fe78bSCy Schubert authenticate_server(Init::InitInfo& info) {
235*7f2fe78bSCy Schubert DWORD challenge, desired_response;
236*7f2fe78bSCy Schubert HANDLE hMap = 0;
237*7f2fe78bSCy Schubert LPSTR mem_name = 0;
238*7f2fe78bSCy Schubert PDWORD pvalue = 0;
239*7f2fe78bSCy Schubert CC_UINT32 response = 0;
240*7f2fe78bSCy Schubert SECURITY_ATTRIBUTES sa = { 0 };
241*7f2fe78bSCy Schubert DWORD status = 0;
242*7f2fe78bSCy Schubert
243*7f2fe78bSCy Schubert cci_debug_printf("%s entry", __FUNCTION__);
244*7f2fe78bSCy Schubert
245*7f2fe78bSCy Schubert status = alloc_name(&mem_name, "auth", isNT());
246*7f2fe78bSCy Schubert cci_check_error(status);
247*7f2fe78bSCy Schubert
248*7f2fe78bSCy Schubert if (!status) {
249*7f2fe78bSCy Schubert status = make_random_challenge(&challenge);
250*7f2fe78bSCy Schubert desired_response = challenge + 1;
251*7f2fe78bSCy Schubert cci_check_error(status);
252*7f2fe78bSCy Schubert }
253*7f2fe78bSCy Schubert
254*7f2fe78bSCy Schubert if (!status) {
255*7f2fe78bSCy Schubert if (isNT()) {
256*7f2fe78bSCy Schubert sa.nLength = sizeof(sa);
257*7f2fe78bSCy Schubert status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
258*7f2fe78bSCy Schubert }
259*7f2fe78bSCy Schubert }
260*7f2fe78bSCy Schubert cci_check_error(status);
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert if (!status) {
263*7f2fe78bSCy Schubert hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0,
264*7f2fe78bSCy Schubert PAGE_READWRITE, 0, sizeof(DWORD), mem_name);
265*7f2fe78bSCy Schubert if (!hMap)
266*7f2fe78bSCy Schubert status = GetLastError();
267*7f2fe78bSCy Schubert }
268*7f2fe78bSCy Schubert cci_check_error(status);
269*7f2fe78bSCy Schubert
270*7f2fe78bSCy Schubert if (!status) {
271*7f2fe78bSCy Schubert pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
272*7f2fe78bSCy Schubert if (!pvalue) status = GetLastError();
273*7f2fe78bSCy Schubert }
274*7f2fe78bSCy Schubert cci_check_error(status);
275*7f2fe78bSCy Schubert
276*7f2fe78bSCy Schubert if (!status) {
277*7f2fe78bSCy Schubert *pvalue = challenge;
278*7f2fe78bSCy Schubert
279*7f2fe78bSCy Schubert RpcTryExcept {
280*7f2fe78bSCy Schubert response = ccs_authenticate( (CC_CHAR*)mem_name );
281*7f2fe78bSCy Schubert }
282*7f2fe78bSCy Schubert RpcExcept(1) {
283*7f2fe78bSCy Schubert status = RpcExceptionCode();
284*7f2fe78bSCy Schubert cci_check_error(status);
285*7f2fe78bSCy Schubert }
286*7f2fe78bSCy Schubert RpcEndExcept;
287*7f2fe78bSCy Schubert }
288*7f2fe78bSCy Schubert cci_check_error(status);
289*7f2fe78bSCy Schubert
290*7f2fe78bSCy Schubert if (!status) {
291*7f2fe78bSCy Schubert // Check response
292*7f2fe78bSCy Schubert if ((response != desired_response) && (*pvalue != desired_response)) {
293*7f2fe78bSCy Schubert cci_debug_printf(" Could not authenticate server.");
294*7f2fe78bSCy Schubert status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND?
295*7f2fe78bSCy Schubert }
296*7f2fe78bSCy Schubert else {
297*7f2fe78bSCy Schubert cci_debug_printf(" Server authenticated!");
298*7f2fe78bSCy Schubert }
299*7f2fe78bSCy Schubert cci_check_error(status);
300*7f2fe78bSCy Schubert }
301*7f2fe78bSCy Schubert
302*7f2fe78bSCy Schubert free_alloc_p(&mem_name);
303*7f2fe78bSCy Schubert free_alloc_p(&sa.lpSecurityDescriptor);
304*7f2fe78bSCy Schubert if (pvalue) {
305*7f2fe78bSCy Schubert BOOL ok = UnmapViewOfFile(pvalue);
306*7f2fe78bSCy Schubert // DEBUG_ASSERT(ok);
307*7f2fe78bSCy Schubert }
308*7f2fe78bSCy Schubert if (hMap) CloseHandle(hMap);
309*7f2fe78bSCy Schubert return status;
310*7f2fe78bSCy Schubert }
311*7f2fe78bSCy Schubert
312*7f2fe78bSCy Schubert DWORD
Disconnect()313*7f2fe78bSCy Schubert Client::Disconnect() {
314*7f2fe78bSCy Schubert DWORD status = 0;
315*7f2fe78bSCy Schubert if (ccs_request_IfHandle) {
316*7f2fe78bSCy Schubert /* The calls to the remote procedures are complete. */
317*7f2fe78bSCy Schubert /* Free the binding handle */
318*7f2fe78bSCy Schubert status = RpcBindingFree(&ccs_request_IfHandle);
319*7f2fe78bSCy Schubert }
320*7f2fe78bSCy Schubert s_init = false;
321*7f2fe78bSCy Schubert return status;
322*7f2fe78bSCy Schubert }
323*7f2fe78bSCy Schubert
324*7f2fe78bSCy Schubert DWORD
Connect(char * ep OPTIONAL)325*7f2fe78bSCy Schubert Client::Connect(char* ep OPTIONAL) {
326*7f2fe78bSCy Schubert LPSTR endpoint = 0;
327*7f2fe78bSCy Schubert DWORD status = 0;
328*7f2fe78bSCy Schubert
329*7f2fe78bSCy Schubert if (!ccs_request_IfHandle) {
330*7f2fe78bSCy Schubert Init::InitInfo info;
331*7f2fe78bSCy Schubert
332*7f2fe78bSCy Schubert status = Init::Info(info);
333*7f2fe78bSCy Schubert cci_check_error(status);
334*7f2fe78bSCy Schubert
335*7f2fe78bSCy Schubert if (!status) {
336*7f2fe78bSCy Schubert status = bind_client(ep, info, &endpoint);
337*7f2fe78bSCy Schubert cci_check_error(status);
338*7f2fe78bSCy Schubert }
339*7f2fe78bSCy Schubert
340*7f2fe78bSCy Schubert if (!status) {
341*7f2fe78bSCy Schubert status = find_server(info, endpoint);
342*7f2fe78bSCy Schubert cci_check_error(status);
343*7f2fe78bSCy Schubert }
344*7f2fe78bSCy Schubert
345*7f2fe78bSCy Schubert if (!status) {
346*7f2fe78bSCy Schubert status = authenticate_server(info);
347*7f2fe78bSCy Schubert cci_check_error(status);
348*7f2fe78bSCy Schubert }
349*7f2fe78bSCy Schubert }
350*7f2fe78bSCy Schubert
351*7f2fe78bSCy Schubert
352*7f2fe78bSCy Schubert if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint);
353*7f2fe78bSCy Schubert
354*7f2fe78bSCy Schubert if (status) Client::Disconnect();
355*7f2fe78bSCy Schubert return status;
356*7f2fe78bSCy Schubert }
357*7f2fe78bSCy Schubert
Initialize(char * ep OPTIONAL)358*7f2fe78bSCy Schubert DWORD Client::Initialize(char* ep OPTIONAL) {
359*7f2fe78bSCy Schubert CcAutoTryLock AL(Client::sLock);
360*7f2fe78bSCy Schubert if (!AL.IsLocked() || s_init)
361*7f2fe78bSCy Schubert return 0;
362*7f2fe78bSCy Schubert SecureClient s;
363*7f2fe78bSCy Schubert ccs_request_IfHandle = NULL;
364*7f2fe78bSCy Schubert DWORD status = Client::Connect(ep);
365*7f2fe78bSCy Schubert if (!status) s_init = true;
366*7f2fe78bSCy Schubert return status;
367*7f2fe78bSCy Schubert }
368*7f2fe78bSCy Schubert
Cleanup()369*7f2fe78bSCy Schubert DWORD Client::Cleanup() {
370*7f2fe78bSCy Schubert CcAutoLock AL(Client::sLock);
371*7f2fe78bSCy Schubert SecureClient s;
372*7f2fe78bSCy Schubert return Client::Disconnect();
373*7f2fe78bSCy Schubert }
374*7f2fe78bSCy Schubert
Reconnect(char * ep OPTIONAL)375*7f2fe78bSCy Schubert DWORD Client::Reconnect(char* ep OPTIONAL) {
376*7f2fe78bSCy Schubert CcAutoLock AL(Client::sLock);
377*7f2fe78bSCy Schubert SecureClient s;
378*7f2fe78bSCy Schubert DWORD status = 0;
379*7f2fe78bSCy Schubert
380*7f2fe78bSCy Schubert if (Initialized()) {
381*7f2fe78bSCy Schubert DWORD status = Client::Cleanup();
382*7f2fe78bSCy Schubert }
383*7f2fe78bSCy Schubert if ( (!status) ) {
384*7f2fe78bSCy Schubert status = Client::Initialize(ep);
385*7f2fe78bSCy Schubert }
386*7f2fe78bSCy Schubert
387*7f2fe78bSCy Schubert return status;
388*7f2fe78bSCy Schubert }
389