2 * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
4 * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5 * LICENSED MATERIALS - PROPERTY OF IBM
16 #include <afs/pioctl_nt.h>
17 #include <afs/kautils.h>
18 #include "cm_config.h"
26 char NPName[] = "System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\NetworkProvider";
28 #define REG_CLIENT_PARMS_KEY "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"
29 #define REG_CLIENT_RETRY_INTERVAL_PARM "LoginRetryInterval"
30 #define REG_CLIENT_FAIL_SILENTLY_PARM "FailLoginsSilently"
31 #define DEFAULT_RETRY_INTERVAL 30 // seconds
32 #define DEFAULT_FAIL_SILENTLY FALSE
33 #define DEFAULT_SLEEP_INTERVAL 5 // seconds
36 /* Structure def copied from DDK (NTDEF.H) */
37 typedef struct UNICODE_STRING {
38 USHORT Length; /* number of bytes of Buffer actually used */
39 USHORT MaximumLength; /* sizeof buffer in bytes */
40 WCHAR *Buffer; /* 16 bit characters */
43 /* Structure def copied from NP API documentation */
44 typedef struct _MSV1_0_INTERACTIVE_LOGON {
45 DWORD MessageType; /* Actually this is an enum; ignored */
46 UNICODE_STRING LogonDomainName;
47 UNICODE_STRING UserName;
48 UNICODE_STRING Password;
49 } MSV1_0_INTERACTIVE_LOGON;
54 * We get a logon script pathname from the HKEY_LOCAL_MACHINE registry.
55 * I don't know what good this does; I just copied it from DFS.
57 * Returns NULL on failure.
59 WCHAR *GetLogonScript(void)
63 DWORD LSPtype, LSPsize;
67 * Get Network Provider key.
68 * Assume this works or we wouldn't be here.
70 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, NPName,
71 0, KEY_QUERY_VALUE, &NPKey);
74 * Get Logon Script pathname length
76 code = RegQueryValueEx(NPKey, "LogonScript", NULL,
77 &LSPtype, NULL, &LSPsize);
84 if (LSPtype != REG_SZ) { /* Maybe handle REG_EXPAND_SZ? */
89 script = (WCHAR *)LocalAlloc(LMEM_FIXED, LSPsize);
92 * Explicitly call UNICODE version
93 * Assume it will succeed since it did before
95 (void) RegQueryValueExW(NPKey, L"LogonScript", NULL,
96 &LSPtype, (LPBYTE)script, &LSPsize);
102 BOOLEAN AFSWillAutoStart(void)
107 BOOLEAN result = FALSE;
108 LPQUERY_SERVICE_CONFIG pConfig = NULL;
112 /* Open services manager */
113 scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
114 if (!scm) return FALSE;
116 /* Open AFSD service */
117 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
121 /* Query AFSD service config, first just to get buffer size */
122 /* Expected to fail, so don't test return value */
123 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
124 status = GetLastError();
125 if (status != ERROR_INSUFFICIENT_BUFFER)
128 /* Allocate buffer */
129 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED, BufSize);
133 /* Query AFSD service config, this time for real */
134 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
138 /* Is it autostart? */
139 if (pConfig->dwStartType < SERVICE_DEMAND_START)
145 CloseServiceHandle(svc);
147 CloseServiceHandle(scm);
152 DWORD MapAuthError(DWORD code)
155 case INTK_BADPW: return WN_BAD_PASSWORD;
156 case KERB_ERR_PRINCIPAL_UNKNOWN: return WN_BAD_USER;
157 default: return WN_NO_NETWORK;
161 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
165 case DLL_PROCESS_ATTACH:
166 /* Initialize AFS libraries */
171 /* Everything else succeeds but does nothing. */
172 case DLL_PROCESS_DETACH:
173 case DLL_THREAD_ATTACH:
174 case DLL_THREAD_DETACH:
182 DWORD APIENTRY NPGetCaps(DWORD index)
186 /* Don't have our own type; use somebody else's. */
187 return WNNC_NET_SUN_PC_NFS;
193 static void GetLoginBehavior(int *pRetryInterval, BOOLEAN *pFailSilently)
199 result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_CLIENT_PARMS_KEY, 0, KEY_QUERY_VALUE, &hKey);
200 if (result != ERROR_SUCCESS) {
201 *pRetryInterval = DEFAULT_RETRY_INTERVAL;
202 *pFailSilently = DEFAULT_FAIL_SILENTLY;
206 result = RegQueryValueEx(hKey, REG_CLIENT_RETRY_INTERVAL_PARM, 0, 0, (BYTE *)pRetryInterval, &dummyLen);
207 if (result != ERROR_SUCCESS)
208 *pRetryInterval = DEFAULT_RETRY_INTERVAL;
210 result = RegQueryValueEx(hKey, REG_CLIENT_FAIL_SILENTLY_PARM, 0, 0, (BYTE *)pFailSilently, &dummyLen);
211 if (result != ERROR_SUCCESS)
212 *pFailSilently = DEFAULT_FAIL_SILENTLY;
214 // Make sure this is really a bool value in the strict sense
215 *pFailSilently = !!*pFailSilently;
220 DWORD APIENTRY NPLogonNotify(
222 LPCWSTR lpAuthentInfoType,
223 LPVOID lpAuthentInfo,
224 LPCWSTR lpPreviousAuthentInfoType,
225 LPVOID lpPreviousAuthentInfo,
226 LPWSTR lpStationName,
227 LPVOID StationHandle,
228 LPWSTR *lpLogonScript)
233 MSV1_0_INTERACTIVE_LOGON *IL;
239 HWND hwndOwner = (HWND)StationHandle;
240 BOOLEAN failSilently;
242 int sleepInterval = DEFAULT_SLEEP_INTERVAL; // seconds
243 BOOLEAN afsWillAutoStart;
245 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
247 /* Are we interactive? */
248 interactive = (wcscmp(lpStationName, L"WinSta0") == 0);
250 /* Convert from Unicode to ANSI */
251 wcstombs(uname, IL->UserName.Buffer, 256);
252 wcstombs(password, IL->Password.Buffer, 256);
254 /* Check for zero length password */
255 if (password[0] == 0) {
257 reason = "zero length password is illegal";
262 code = cm_GetRootCellName(cell);
265 reason = "unknown cell";
269 /* Get user specified login behavior (or defaults) */
270 GetLoginBehavior(&retryInterval, &failSilently);
272 afsWillAutoStart = AFSWillAutoStart();
274 /* Possibly loop until AFS is started. */
276 code = ka_UserAuthenticateGeneral(
277 KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
278 uname, "", cell, password, 0, &pw_exp, 0,
281 /* If we've failed because the client isn't running yet and the
282 * client is set to autostart (and therefore it makes sense for
283 * us to wait for it to start) then sleep a while and try again.
284 * If the error was something else, then give up. */
285 if (code != KTC_NOCM && code != KTC_NOCMRPC || !afsWillAutoStart)
288 /* If the retry interval has expired and we still aren't
289 * logged in, then just give up if we are not in interactive
290 * mode or the failSilently flag is set, otherwise let the
291 * user know we failed and give them a chance to try again. */
292 if (retryInterval <= 0) {
293 if (!interactive || failSilently)
296 flag = MessageBox(hwndOwner,
297 "AFS is still starting. Retry?",
299 MB_ICONQUESTION | MB_RETRYCANCEL);
300 if (flag == IDCANCEL)
303 /* Wait just a little while and try again */
304 retryInterval = sleepInterval = DEFAULT_SLEEP_INTERVAL;
307 if (retryInterval < sleepInterval)
308 sleepInterval = retryInterval;
310 Sleep(sleepInterval * 1000);
312 retryInterval -= sleepInterval;
319 sprintf(msg, "Integrated login failed: %s", reason);
321 if (interactive && !failSilently)
322 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
327 h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
329 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
331 DeregisterEventSource(h);
335 /* Get logon script */
337 *lpLogonScript = GetLogonScript();
340 code = MapAuthError(code);
347 DWORD APIENTRY NPPasswordChangeNotify(
348 LPCWSTR lpAuthentInfoType,
349 LPVOID lpAuthentInfo,
350 LPCWSTR lpPreviousAuthentInfoType,
351 LPVOID lpPreviousAuthentInfo,
352 LPWSTR lpStationName,
353 LPVOID StationHandle,