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