win32-name-event-objects-20040228
[openafs.git] / src / WINNT / afsadmsvr / TaAfsAdmSvrClientBind.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "TaAfsAdmSvrClientInternal.h"
16
17 extern "C" {
18 #include <afs/afs_AdminErrors.h>
19 } // extern "C"
20
21
22 /*
23  * DEFINITIONS ________________________________________________________________
24  *
25  */
26
27 #define cmsecLOCAL_BIND_TIMEOUT  (15L * 1000L)  // wait up to 15 seconds to bind
28 #define cmsecLOCAL_BIND_SLEEP     (1L * 1000L)  // sleep for a second between
29
30
31 /*
32  * PROTOTYPES _________________________________________________________________
33  *
34  */
35
36 BOOL ValidateBinding (RPC_NS_HANDLE hBind, DWORD *pidClient, ULONG *pStatus);
37
38
39 /*
40  * ROUTINES ___________________________________________________________________
41  *
42  */
43
44 BOOL ADMINAPI BindToAdminServer (LPCTSTR pszAddress, BOOL fWait, DWORD *pidClient, ULONG *pStatus)
45 {
46    RPC_STATUS status = 0;
47
48    unsigned char *pszPROTOCOL = (unsigned char *)"ncacn_ip_tcp";
49    unsigned char *pszENTRYNAME = (unsigned char *)AFSADMSVR_ENTRYNAME_DEFAULT;
50    unsigned char szEndpoint[ 32 ];
51    wsprintf ((LPTSTR)szEndpoint, "%lu", AFSADMSVR_ENDPOINT_DEFAULT);
52
53    for (DWORD dwTickStart = GetTickCount(); ; )
54       {
55       // First we'll enumerate the name services around here to see if
56       // an admin server is already running.
57       //
58       RPC_NS_HANDLE hEnum;
59       if ((status = RpcNsBindingImportBegin (RPC_C_NS_SYNTAX_DEFAULT, pszENTRYNAME, ITaAfsAdminSvr_v1_0_c_ifspec, NULL, &hEnum)) == 0)
60          {
61          RPC_BINDING_HANDLE hBind;
62          status = RpcNsBindingImportNext (hEnum, &hBind);
63          RpcNsBindingImportDone (&hEnum);
64
65          if (status)
66             RpcBindingFree (&hBind);
67          else if (ValidateBinding (hBind, pidClient, (ULONG*)&status))
68             return TRUE;
69          else if (status != RPC_S_CALL_FAILED_DNE) // server rejected us!
70             break;
71          }
72
73       // Failing that, we'll try to bind to the well-known endpoint that the
74       // admin server may have had to use. (if RpcNsBindingExport failed.)
75       //
76       unsigned char *pszStringBinding = NULL;
77       if ((status = RpcStringBindingCompose (NULL, pszPROTOCOL, (unsigned char *)pszAddress, szEndpoint, NULL, &pszStringBinding)) == 0)
78          {
79          RPC_BINDING_HANDLE hBind;
80          status = RpcBindingFromStringBinding (pszStringBinding, &hBind);
81          RpcStringFree (&pszStringBinding);
82
83          if (status)
84             RpcBindingFree (&hBind);
85          else if (ValidateBinding (hBind, pidClient, (ULONG*)&status))
86             return TRUE;
87          else if (status != RPC_S_CALL_FAILED_DNE) // server rejected us!
88             break;
89          }
90
91       // If we can't wait any longer, fail. Otherwise, sleep for a little bit
92       // and try again.
93       //
94       if ((!fWait) || (GetTickCount() - dwTickStart > cmsecLOCAL_BIND_TIMEOUT))
95          break;
96
97       Sleep (cmsecLOCAL_BIND_SLEEP);
98       }
99
100    if (pStatus)
101       *pStatus = (LONG)status;
102    return FALSE;
103 }
104
105
106 BOOL ADMINAPI UnbindFromAdminServer (DWORD idClient, ULONG *pStatus)
107 {
108    BOOL rc = TRUE;
109    ULONG status = 0;
110
111    RpcTryExcept
112       {
113       ULONG status;
114       AfsAdmSvr_Disconnect (idClient, &status);
115       }
116    RpcExcept(1)
117       ;
118    RpcEndExcept
119
120    if ((status = RpcBindingFree (&hBindTaAfsAdminSvr)) != 0)
121       rc = FALSE;
122
123    if (!rc && pStatus)
124       *pStatus = (LONG)status;
125    return rc;
126 }
127
128
129 BOOL ADMINAPI ForkNewAdminServer (ULONG *pStatus)
130 {
131    // Before we can fork a new process, we have to find the program to run.
132    //
133    TCHAR szFile[ MAX_PATH ];
134    GetModuleFileName (GetModuleHandle(NULL), szFile, MAX_PATH);
135
136    LPTSTR pch;
137    if ((pch = (LPTSTR)lstrrchr (szFile, TEXT('\\'))) != NULL)
138       *(1+pch) = TEXT('\0');
139    lstrcat (szFile, AFSADMSVR_PROGRAM);
140
141    if (GetFileAttributes (szFile) == (DWORD)0xFFFFFFFF)
142       {
143       lstrcpy (szFile, AFSADMSVR_PROGRAM);  // hope it's on the path
144       }
145
146    // Try to launch the program. Error codes are returns <= 32.
147    // Remember to add the "Timed" keyword, so it will shut itself down
148    // if it's idle too long, and the "Manual" keyword so it won't automatically
149    // start opening a cell and looking around.
150    //
151    wsprintf (&szFile[ lstrlen(szFile) ], TEXT(" %s %s"), AFSADMSVR_KEYWORD_TIMED, AFSADMSVR_KEYWORD_MANUAL);
152
153    UINT hInst;
154    if ((hInst = WinExec (szFile, SW_HIDE)) <= 32)
155       {
156       if (pStatus)
157          *pStatus = (DWORD)hInst;
158       return FALSE;
159       }
160
161    return TRUE;
162 }
163
164
165 BOOL ValidateBinding (RPC_NS_HANDLE hBind, DWORD *pidClient, ULONG *pStatus)
166 {
167    RPC_NS_HANDLE hBindOld = hBindTaAfsAdminSvr;
168    BOOL rc = FALSE;
169    ULONG status = RPC_S_CALL_FAILED_DNE;
170
171    hBindTaAfsAdminSvr = hBind;
172
173    RpcTryExcept
174       {
175       STRING szMyName;
176       gethostname (szMyName, cchSTRING);
177
178       rc = AfsAdmSvr_Connect (szMyName, pidClient, &status);
179       }
180    RpcExcept(1)
181       {
182       rc = FALSE;
183       status = RPC_S_CALL_FAILED_DNE;
184       }
185    RpcEndExcept
186
187    if (!rc)
188       hBindTaAfsAdminSvr = hBindOld;
189    if (!rc && pStatus)
190       *pStatus = status;
191    return rc;
192 }
193
194
195 LPCTSTR ADMINAPI ResolveAddress (LPCTSTR pszAddress)
196 {
197    if (!pszAddress || !*pszAddress)
198       return NULL;
199
200    // The caller may have specified an IP address or a server name.
201    // If the former, we're done; if the latter, we'll have to look up
202    // the server's IP address.
203    //
204    if ((*pszAddress >= TEXT('0')) && (*pszAddress <= TEXT('9')))
205       return pszAddress;
206
207    HOSTENT *pEntry;
208    if ((pEntry = gethostbyname (pszAddress)) == NULL)
209       return pszAddress;  // we'll try it by name, but it probly won't work.
210
211    try {
212       static TCHAR szResolved[ 1024 ];
213       lstrcpy (szResolved, inet_ntoa (*(struct in_addr *)pEntry->h_addr));
214       return szResolved;
215    } catch (...) {
216       return pszAddress;  // we'll try it by name, but it probly won't work.
217    }
218 }
219