2 * Copyright 2000, International Business Machines Corporation and others.
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
14 #include <sys/types.h>
21 #include <afs/param.h>
23 #include <afs/pioctl_nt.h>
24 #include <afs/kautils.h>
27 #include "cm_config.h"
30 #include "lanahelper.h"
32 #include <WINNT\afsreg.h>
34 DWORD TraceOption = 0;
38 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
40 void DebugEvent0(char *a)
42 HANDLE h; char *ptbuf[1];
44 if (!ISLOGONTRACE(TraceOption))
47 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
48 if (h != INVALID_HANDLE_VALUE) {
50 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
51 DeregisterEventSource(h);
56 void DebugEvent(char *b,...)
58 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
61 if (!ISLOGONTRACE(TraceOption))
64 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
65 if (h != INVALID_HANDLE_VALUE) {
67 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
70 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
71 DeregisterEventSource(h);
76 static HANDLE hInitMutex = NULL;
77 static BOOL bInit = FALSE;
79 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
85 case DLL_PROCESS_ATTACH:
86 /* Initialization Mutex */
88 hInitMutex = CreateMutex(NULL, FALSE, NULL);
90 WSAStartup( MAKEWORD(2,2), &wsaData );
93 case DLL_PROCESS_DETACH:
95 CloseHandle(hInitMutex);
100 case DLL_THREAD_ATTACH:
101 case DLL_THREAD_DETACH:
103 /* Everything else succeeds but does nothing. */
110 void AfsLogonInit(void)
112 if ( bInit == FALSE ) {
113 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
114 /* initAFSDirPath() initializes an array and sets a
115 * flag so that the initialization can only occur
116 * once. No cleanup will be done when the DLL is
117 * unloaded so the initialization will not be
118 * performed again on a subsequent reload
122 /* ka_Init initializes a number of error tables.
123 * and then calls ka_CellConfig() which grabs
124 * an afsconf_dir structure via afsconf_Open().
125 * Upon a second attempt to call ka_CellConfig()
126 * the structure will be released with afsconf_Close()
127 * and then re-opened. Could this corrupt memory?
129 * We only need this if we are not using KFW.
131 if (!KFW_is_available())
135 ReleaseMutex(hInitMutex);
139 CHAR *GenRandomName(CHAR *pbuf)
142 srand( (unsigned)time( NULL ) );
143 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
144 pbuf[i]='a'+(rand() % 26);
145 pbuf[MAXRANDOMNAMELEN-1]=0;
149 BOOLEAN AFSWillAutoStart(void)
154 BOOLEAN result = FALSE;
155 LPQUERY_SERVICE_CONFIG pConfig = NULL;
159 /* Open services manager */
160 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
161 if (!scm) return FALSE;
163 /* Open AFSD service */
164 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
168 /* Query AFSD service config, first just to get buffer size */
169 /* Expected to fail, so don't test return value */
170 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
171 status = GetLastError();
172 if (status != ERROR_INSUFFICIENT_BUFFER)
175 /* Allocate buffer */
176 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
180 /* Query AFSD service config, this time for real */
181 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
185 /* Is it autostart? */
186 if (pConfig->dwStartType < SERVICE_DEMAND_START)
192 CloseServiceHandle(svc);
194 CloseServiceHandle(scm);
199 DWORD MapAuthError(DWORD code)
202 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
203 * logon scripts for all credential managers, although they will still
204 * receive logon notifications. Since we don't want this, we return
205 * WN_SUCCESS. This is highly undesirable, but we also don't want to
206 * break other network providers.
210 return WN_NO_NETWORK; */
211 default: return WN_SUCCESS;
215 DWORD APIENTRY NPGetCaps(DWORD index)
219 /* Don't have our own type; use somebody else's. */
220 return WNNC_NET_SUN_PC_NFS;
223 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
232 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
233 DWORD profilePathLen )
236 LPWSTR ServerName = NULL;
237 LPUSER_INFO_3 p3 = NULL;
239 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
240 /* if NetGetAnyDCName fails, ServerName == NULL
241 * NetUserGetInfo will obtain local user information
243 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
244 if (code == NERR_Success)
246 code = NERR_UserNotFound;
248 if (p3->usri3_profile) {
249 DWORD len = lstrlenW(p3->usri3_profile);
251 /* Convert From Unicode to ANSI (UTF-8 for future) */
252 len = len < profilePathLen ? len : profilePathLen - 1;
253 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
254 profilePath[len] = '\0';
258 NetApiBufferFree(p3);
262 NetApiBufferFree(ServerName);
266 BOOL IsServiceRunning (void)
268 SERVICE_STATUS Status;
270 memset (&Status, 0x00, sizeof(Status));
271 Status.dwCurrentState = SERVICE_STOPPED;
273 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
276 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
278 QueryServiceStatus (hService, &Status);
279 CloseServiceHandle (hService);
282 CloseServiceHandle (hManager);
284 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
285 return (Status.dwCurrentState == SERVICE_RUNNING);
288 BOOL IsServiceStartPending (void)
290 SERVICE_STATUS Status;
292 memset (&Status, 0x00, sizeof(Status));
293 Status.dwCurrentState = SERVICE_STOPPED;
295 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
298 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
300 QueryServiceStatus (hService, &Status);
301 CloseServiceHandle (hService);
304 CloseServiceHandle (hManager);
306 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
307 return (Status.dwCurrentState == SERVICE_START_PENDING);
310 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
311 v:variable to receive value (reference type)
313 d:default, in case the value isn't on any of the keys
315 #define LOOKUPKEYCHAIN(v,t,d,n) \
317 rv = ~ERROR_SUCCESS; \
320 dwSize = sizeof(v); \
321 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
322 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
323 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
325 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
326 dwSize = sizeof(v); \
327 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
328 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
329 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
331 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
332 dwSize = sizeof(v); \
333 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
334 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
335 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
337 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
339 DebugEvent0(#v " being set to default"); \
343 /* Get domain specific configuration info. We are returning void because if anything goes wrong
344 we just return defaults.
347 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
348 HKEY hkParm = NULL; /* Service parameter */
349 HKEY hkNp = NULL; /* network provider key */
350 HKEY hkDoms = NULL; /* domains key */
351 HKEY hkDom = NULL; /* DOMAINS/domain key */
357 char computerName[MAX_COMPUTERNAME_LENGTH + 1];
360 memset(opt, 0, sizeof(LogonOptions_t));
362 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
363 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
364 opt->flags = LOGON_FLAG_REMOTE;
366 dwSize = MAX_COMPUTERNAME_LENGTH;
367 if(GetComputerName(computerName, &dwSize)) {
368 if(!stricmp(computerName, domain)) {
369 effDomain = "LOCALHOST";
370 opt->flags = LOGON_FLAG_LOCAL;
378 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
379 if(rv != ERROR_SUCCESS) {
381 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
384 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
385 if(rv != ERROR_SUCCESS) {
387 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
391 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
392 if( rv != ERROR_SUCCESS ) {
394 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
398 if(hkDoms && effDomain) {
399 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
400 if( rv != ERROR_SUCCESS ) {
402 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
403 /* If none of the domains match, we shouldn't use the domain key either */
408 DebugEvent0("Not opening domain key");
410 /* Each individual can either be specified on the domain key, the domains key or in the
411 net provider key. They fail over in that order. If none is found, we just use the
415 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
417 /* FailLoginsSilently */
418 dwSize = sizeof(dwDummy);
419 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
420 if (rv != ERROR_SUCCESS)
421 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
422 opt->failSilently = !!dwDummy;
425 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
428 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
430 opt->logonScript = NULL;
433 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
434 goto cleanup; /* no need to lookup the logon script */
437 /* come up with SMB username */
438 if(ISHIGHSECURITY(opt->LogonOption)) {
439 opt->smbName = malloc( MAXRANDOMNAMELEN );
440 GenRandomName(opt->smbName);
441 } else if (lpLogonId) {
442 /* username and domain for logon session is not necessarily the same as
443 username and domain passed into network provider. */
444 PSECURITY_LOGON_SESSION_DATA plsd;
445 char lsaUsername[MAX_USERNAME_LENGTH];
446 char lsaDomain[MAX_DOMAIN_LENGTH];
449 LsaGetLogonSessionData(lpLogonId, &plsd);
451 UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH);
452 UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH);
454 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
456 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
461 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
468 opt->smbName = malloc(len);
470 StringCbCopy(opt->smbName, len, lsaDomain);
471 StringCbCat(opt->smbName, len, "\\");
472 StringCbCat(opt->smbName, len, lsaUsername);
474 strlwr(opt->smbName);
477 LsaFreeReturnBuffer(plsd);
481 DebugEvent("No LUID given. Constructing username using [%s] and [%s]",
484 len = strlen(username) + strlen(domain) + 2;
486 opt->smbName = malloc(len);
488 StringCbCopy(opt->smbName, len, username);
489 StringCbCat(opt->smbName, len, "\\");
490 StringCbCat(opt->smbName, len, domain);
492 strlwr(opt->smbName);
495 DebugEvent0("Looking up logon script");
497 /* First find out where the key is */
502 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
503 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
505 DebugEvent0("Located logon script in hkDom");
508 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
509 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
511 DebugEvent0("Located logon script in hkDoms");
513 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
514 else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
515 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
516 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
518 DebugEvent0("Located logon script in hkNp");
524 WCHAR *regscript = NULL;
525 WCHAR *regexscript = NULL;
526 WCHAR *regexuscript = NULL;
527 WCHAR *wuname = NULL;
532 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
535 wuname = malloc(len * sizeof(WCHAR));
537 goto doneLogonScript;
538 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
540 DebugEvent("Username is set for [%S]", wuname);
542 /* dwSize still has the size of the required buffer in bytes. */
543 regscript = malloc(dwSize);
545 goto doneLogonScript;
546 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
547 if(rv != ERROR_SUCCESS) {/* what the ..? */
548 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
549 goto doneLogonScript;
552 DebugEvent("Found logon script [%S]", regscript);
554 if(dwType == REG_EXPAND_SZ) {
557 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
558 regexscript = malloc(dwSize);
560 goto doneLogonScript;
561 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
563 regscript = regexscript;
565 if(dwReq > (dwSize / sizeof(WCHAR))) {
566 DebugEvent0("Overflow while expanding environment strings.");
567 goto doneLogonScript;
571 DebugEvent("After expanding env strings [%S]", regscript);
573 if(wcsstr(regscript, L"%s")) {
574 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
575 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
577 goto doneLogonScript;
578 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
580 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
582 goto doneLogonScript;
583 hr = StringCbCopyW(regexuscript, dwSize, regscript);
586 DebugEvent("After expanding username [%S]", regexuscript);
589 opt->logonScript = regexuscript;
591 LocalFree(regexuscript);
594 if(wuname) free(wuname);
595 if(regscript) free(regscript);
596 if(regexscript) free(regexscript);
599 DebugEvent0("Looking up TheseCells");
601 /* First find out where the key is */
606 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
607 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
609 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
611 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
612 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
614 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
616 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
617 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
619 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
625 CHAR * thesecells = NULL;
627 /* dwSize still has the size of the required buffer in bytes. */
628 thesecells = malloc(dwSize*2);
633 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
634 if(rv != ERROR_SUCCESS) {/* what the ..? */
635 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
639 DebugEvent("Found TheseCells [%s]", thesecells);
640 opt->theseCells = thesecells;
644 if (thesecells) free(thesecells);
647 DebugEvent0("Looking up Realm");
649 /* First find out where the key is */
654 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
655 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
657 DebugEvent("Located Realm in hkDom size %d", dwSize);
659 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
660 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
662 DebugEvent("Located Realm in hkDoms size %d", dwSize);
664 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
665 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
667 DebugEvent("Located Realm in hkNp size %d", dwSize);
675 /* dwSize still has the size of the required buffer in bytes. */
676 realm = malloc(dwSize*2);
681 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
682 if(rv != ERROR_SUCCESS) {/* what the ..? */
683 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
687 DebugEvent("Found Realm [%s]", realm);
692 if (realm) free(realm);
696 if(hkNp) RegCloseKey(hkNp);
697 if(hkDom) RegCloseKey(hkDom);
698 if(hkDoms) RegCloseKey(hkDoms);
699 if(hkParm) RegCloseKey(hkParm);
702 #undef LOOKUPKEYCHAIN
704 /* Try to find out which cell the given path is in. We must retain
705 the contents of *cell in case of failure. *cell is assumed to be
706 at least cellLen chars */
707 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
708 struct ViceIoctl blob;
709 char tcell[MAX_PATH];
713 blob.out_size = MAX_PATH;
716 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
719 strncpy(cell, tcell, cellLen);
720 cell[cellLen - 1] = '\0';
728 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
732 GetCPInfo(CP_ACP, &CodePageInfo);
734 if (CodePageInfo.MaxCharSize > 1)
735 // Only supporting non-Unicode strings
738 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
740 // Looks like unicode, better translate it
741 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
742 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
743 lpszOutputString, nOutStringLen-1, NULL, NULL);
744 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
748 lpszOutputString[0] = '\0';
750 } // UnicodeStringToANSI
752 DWORD APIENTRY NPLogonNotify(
754 LPCWSTR lpAuthentInfoType,
755 LPVOID lpAuthentInfo,
756 LPCWSTR lpPreviousAuthentInfoType,
757 LPVOID lpPreviousAuthentInfo,
758 LPWSTR lpStationName,
759 LPVOID StationHandle,
760 LPWSTR *lpLogonScript)
762 char uname[MAX_USERNAME_LENGTH]="";
763 char password[MAX_PASSWORD_LENGTH]="";
764 char logonDomain[MAX_DOMAIN_LENGTH]="";
765 char cell[256]="<non-integrated logon>";
766 char homePath[MAX_PATH]="";
767 char szLogonId[128] = "";
769 MSV1_0_INTERACTIVE_LOGON *IL;
771 DWORD code = 0, code2;
779 DWORD LSPtype, LSPsize;
782 HWND hwndOwner = (HWND)StationHandle;
784 BOOLEAN afsWillAutoStart;
786 BOOLEAN lowercased_name = TRUE;
788 LogonOptions_t opt; /* domain specific logon options */
792 /* Are we interactive? */
793 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
795 #ifdef DISABLE_NON_INTERACTIVE
796 /* Do not do anything if the logon session is not interactive. */
801 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
802 0, KEY_QUERY_VALUE, &NPKey);
803 LSPsize=sizeof(TraceOption);
804 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
805 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
809 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
811 /* Make sure the AFS Libraries are initialized */
814 /* Initialize Logon Script to none */
817 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
820 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
821 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
823 DebugEvent("Unsupported Authentication Info Type: %S",
828 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
830 /* Convert from Unicode to ANSI */
832 /*TODO: Use SecureZeroMemory to erase passwords */
833 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
834 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
835 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
838 /* Make sure AD-DOMANS sent from login that is sent to us is striped */
839 ctemp = strchr(uname, '@');
840 if (ctemp) *ctemp = 0;
842 /* is the name all lowercase? */
843 for ( ctemp = uname; *ctemp ; ctemp++) {
844 if ( !islower(*ctemp) ) {
845 lowercased_name = FALSE;
854 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
855 retryInterval = opt.retryInterval;
856 sleepInterval = opt.sleepInterval;
857 *lpLogonScript = opt.logonScript;
859 if (retryInterval < sleepInterval)
860 sleepInterval = retryInterval;
862 DebugEvent("Got logon script: %S",opt.logonScript);
864 afsWillAutoStart = AFSWillAutoStart();
866 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
867 opt.LogonOption,afsWillAutoStart);
869 /* Check for zero length password if integrated logon*/
870 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
871 if ( password[0] == 0 ) {
872 DebugEvent0("Password is the empty string");
874 reason = "zero length password is illegal";
878 /* Get cell name if doing integrated logon.
879 We might overwrite this if we are logging into an AD realm and we find out that
880 the user's home dir is in some other cell. */
881 DebugEvent("About to call cm_GetRootCellName(%s)",cell);
882 code = cm_GetRootCellName(cell);
884 DebugEvent0("Unable to obtain Root Cell");
886 reason = "unknown cell";
889 DebugEvent("Cell is %s",cell);
892 /* We get the user's home directory path, if applicable, though we can't lookup the
893 cell right away because the client service may not have started yet. This call
894 also sets the AD_REALM flag in opt.flags if applicable. */
895 if (ISREMOTE(opt.flags)) {
896 DebugEvent0("Is Remote");
897 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
901 /* loop until AFS is started. */
902 if (afsWillAutoStart) {
903 while (IsServiceRunning() || IsServiceStartPending()) {
904 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
905 opt.LogonOption,afsWillAutoStart);
907 if (ISADREALM(opt.flags)) {
908 code = GetFileCellName(homePath,cell,256);
910 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
912 /* Don't bail out if GetFileCellName failed.
913 * The home dir may not be in AFS after all.
918 /* if Integrated Logon */
919 if (ISLOGONINTEGRATED(opt.LogonOption))
921 if ( KFW_is_available() ) {
922 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
924 char * principal, *p;
927 StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
929 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
932 /* tlen is now the length of uname in characters */
933 principal = (char *)malloc(len * sizeof(char));
935 StringCchCopy(principal, len, uname);
936 p = principal + tlen;
938 StringCchCopy(p, len - tlen -1, opt.realm);
939 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
940 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
941 principal,opt.smbName,cell,code);
945 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
946 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
947 uname,opt.smbName,cell,code);
949 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
950 if (code == 0 && opt.theseCells) {
951 char * principal, *p;
954 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
956 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
959 /* tlen is now the length of uname in characters */
960 principal = (char *)malloc(len * sizeof(char));
962 StringCchCopy(principal, len, uname);
963 p = principal + tlen;
966 StringCchCopy(p, len - tlen -1, opt.realm);
968 StringCchCopy(p, len - tlen - 1, cell);
975 if ( stricmp(p, cell) ) {
976 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
977 code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
978 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
979 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
980 principal,opt.smbName,p,code2);
988 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
989 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
991 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
992 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
994 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
995 for ( ctemp = uname; *ctemp ; ctemp++) {
996 *ctemp = tolower(*ctemp);
998 lowercased_name = TRUE;
1002 /* is service started yet?*/
1004 /* If we've failed because the client isn't running yet and the
1005 * client is set to autostart (and therefore it makes sense for
1006 * us to wait for it to start) then sleep a while and try again.
1007 * If the error was something else, then give up. */
1008 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1012 /*JUST check to see if its running*/
1013 if (IsServiceRunning())
1015 if (!IsServiceStartPending()) {
1017 reason = "AFS Service start failed";
1022 /* If the retry interval has expired and we still aren't
1023 * logged in, then just give up if we are not in interactive
1024 * mode or the failSilently flag is set, otherwise let the
1025 * user know we failed and give them a chance to try again. */
1026 if (retryInterval <= 0) {
1027 reason = "AFS not running";
1028 if (!interactive || opt.failSilently)
1030 flag = MessageBox(hwndOwner,
1031 "AFS is still starting. Retry?",
1033 MB_ICONQUESTION | MB_RETRYCANCEL);
1034 if (flag == IDCANCEL)
1037 /* Wait just a little while and try again */
1038 retryInterval = opt.retryInterval;
1042 Sleep(sleepInterval * 1000);
1043 retryInterval -= sleepInterval;
1046 DebugEvent0("while loop exited");
1048 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1052 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1054 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1055 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1057 KFW_AFS_destroy_tickets_for_principal(uname);
1065 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1067 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1068 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1070 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1072 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1074 DeregisterEventSource(h);
1076 code = MapAuthError(code);
1079 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1082 LocalFree(*lpLogonScript);
1083 *lpLogonScript = NULL;
1084 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1089 if (opt.theseCells) free(opt.theseCells);
1090 if (opt.smbName) free(opt.smbName);
1091 if (opt.realm) free(opt.realm);
1093 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1097 DWORD APIENTRY NPPasswordChangeNotify(
1098 LPCWSTR lpAuthentInfoType,
1099 LPVOID lpAuthentInfo,
1100 LPCWSTR lpPreviousAuthentInfoType,
1101 LPVOID lpPreviousAuthentInfo,
1102 LPWSTR lpStationName,
1103 LPVOID StationHandle,
1106 BOOLEAN interactive;
1108 /* Are we interactive? */
1109 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1111 /* Do not do anything if the logon session is not interactive. */
1115 /* Make sure the AFS Libraries are initialized */
1118 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1122 #include <userenv.h>
1124 #include <afs/vice.h>
1125 #include <afs/fs_utils.h>
1127 BOOL IsPathInAfs(const CHAR *strPath)
1130 struct ViceIoctl blob;
1134 blob.out_size = 2048;
1137 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1144 typedef struct _WLX_NOTIFICATION_INFO {
1149 PWSTR WindowStation;
1152 PFNMSGECALLBACK pStatusCallback;
1153 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1156 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1158 DWORD LSPtype, LSPsize;
1161 /* Make sure the AFS Libraries are initialized */
1164 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1165 0, KEY_QUERY_VALUE, &NPKey);
1166 LSPsize=sizeof(TraceOption);
1167 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1168 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1170 RegCloseKey (NPKey);
1171 DebugEvent0("AFS_Startup_Event");
1174 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1177 TCHAR profileDir[1024] = TEXT("");
1179 PTOKEN_USER tokenUser = NULL;
1181 DWORD LSPtype, LSPsize;
1183 DWORD LogoffPreserveTokens = 0;
1186 /* Make sure the AFS Libraries are initialized */
1189 DebugEvent0("AFS_Logoff_Event - Start");
1191 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1192 0, KEY_QUERY_VALUE, &NPKey);
1193 LSPsize=sizeof(LogoffPreserveTokens);
1194 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1195 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1196 RegCloseKey (NPKey);
1198 if (!LogoffPreserveTokens) {
1199 memset(&opt, 0, sizeof(LogonOptions_t));
1201 if (pInfo->UserName && pInfo->Domain) {
1202 char username[MAX_USERNAME_LENGTH] = "";
1203 char domain[MAX_DOMAIN_LENGTH] = "";
1206 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1207 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1208 username, sizeof(username), NULL, NULL);
1210 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1211 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1212 domain, sizeof(domain), NULL, NULL);
1214 GetDomainLogonOptions(NULL, username, domain, &opt);
1217 if (ISREMOTE(opt.flags)) {
1218 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1220 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1221 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1223 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1225 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1230 /* We can't use pInfo->Domain for the domain since in the cross realm case
1231 * this is source domain and not the destination domain.
1233 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1234 WCHAR Domain[64]=L"";
1235 GetLocalShortDomain(Domain, sizeof(Domain));
1236 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1237 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1238 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1242 if (strlen(profileDir)) {
1243 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1244 if (!IsPathInAfs(profileDir)) {
1245 if (code = ktc_ForgetAllTokens())
1246 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1248 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1250 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1253 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1257 LocalFree(tokenUser);
1259 DebugEvent0("AFS_Logoff_Event - Local Logon");
1260 if (code = ktc_ForgetAllTokens())
1261 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1263 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1266 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1269 DebugEvent0("AFS_Logoff_Event - End");
1272 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1274 TCHAR profileDir[1024] = TEXT("");
1276 PTOKEN_USER tokenUser = NULL;
1278 WCHAR szUserW[128] = L"";
1279 char szUserA[128] = "";
1280 char szClient[MAX_PATH];
1281 char szPath[MAX_PATH] = "";
1287 /* Make sure the AFS Libraries are initialized */
1290 DebugEvent0("AFS_Logon_Event - Start");
1292 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1294 memset(&opt, 0, sizeof(LogonOptions_t));
1296 if (pInfo->UserName && pInfo->Domain) {
1297 char username[MAX_USERNAME_LENGTH] = "";
1298 char domain[MAX_DOMAIN_LENGTH] = "";
1301 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1303 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1304 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1305 username, sizeof(username), NULL, NULL);
1307 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1308 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1309 domain, sizeof(domain), NULL, NULL);
1311 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1312 GetDomainLogonOptions(NULL, username, domain, &opt);
1314 if (!pInfo->UserName)
1315 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1317 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1320 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1321 opt.LogonOption, opt.flags);
1323 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1324 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1325 goto done_logon_event;
1328 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1330 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1332 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1333 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1335 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1337 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1342 /* We can't use pInfo->Domain for the domain since in the cross realm case
1343 * this is source domain and not the destination domain.
1345 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1346 WCHAR Domain[64]=L"";
1347 GetLocalShortDomain(Domain, sizeof(Domain));
1348 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1349 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1350 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1354 if (strlen(profileDir)) {
1355 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1357 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1361 dwSize = sizeof(szUserA);
1362 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1363 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1364 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1369 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1370 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1372 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1374 memset (&nr, 0x00, sizeof(NETRESOURCE));
1375 nr.dwType=RESOURCETYPE_DISK;
1377 nr.lpRemoteName=szPath;
1378 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1380 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1381 szPath, szUserA,res);
1383 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1385 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1388 LocalFree(tokenUser);
1390 DebugEvent0("AFS_Logon_Event - End");
1394 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1396 NTSTATUS Status = 0;
1397 TOKEN_STATISTICS Stats;
1403 *ppSessionData = NULL;
1405 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1409 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1410 if ( FAILED(Status) || !ppSessionData )
1416 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1419 WCHAR szUserW[128] = L"";
1420 char szUserA[128] = "";
1421 char szPath[MAX_PATH] = "";
1422 char szLogonId[128] = "";
1424 char filename[MAX_PATH] = "";
1425 char newfilename[MAX_PATH] = "";
1426 char commandline[MAX_PATH+256] = "";
1427 STARTUPINFO startupinfo;
1428 PROCESS_INFORMATION procinfo;
1429 HANDLE hf = INVALID_HANDLE_VALUE;
1431 LUID LogonId = {0, 0};
1432 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1434 HKEY hKey1 = NULL, hKey2 = NULL;
1436 /* Make sure the KFW Libraries are initialized */
1439 DebugEvent0("KFW_Logon_Event - Start");
1441 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1443 if ( pLogonSessionData ) {
1444 LogonId = pLogonSessionData->LogonId;
1445 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1447 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1448 LsaFreeReturnBuffer( pLogonSessionData );
1450 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1454 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1455 if ( count > sizeof(filename) || count == 0 ) {
1456 GetWindowsDirectory(filename, sizeof(filename));
1459 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1460 if ( count > sizeof(filename) || count == 0 ) {
1461 GetWindowsDirectory(filename, sizeof(filename));
1464 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1465 DebugEvent0("KFW_Logon_Event - filename too long");
1469 strcat(filename, "\\");
1470 strcat(filename, szLogonId);
1472 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1473 FILE_ATTRIBUTE_NORMAL, NULL);
1474 if (hf == INVALID_HANDLE_VALUE) {
1475 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1480 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1481 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1482 DeleteFile(filename);
1486 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1487 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1491 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1492 DebugEvent0("KFW_Logon_Event - new filename too long");
1496 strcat(newfilename, "\\");
1497 strcat(newfilename, szLogonId);
1499 if (!MoveFileEx(filename, newfilename,
1500 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1501 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1505 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1507 GetStartupInfo(&startupinfo);
1508 if (CreateProcessAsUser( pInfo->hToken,
1514 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1520 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1522 WaitForSingleObject(procinfo.hProcess, 30000);
1524 CloseHandle(procinfo.hThread);
1525 CloseHandle(procinfo.hProcess);
1527 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1530 DeleteFile(filename);
1532 DebugEvent0("KFW_Logon_Event - End");