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 /* Allocated in Windows Driver Kit */
33 #ifndef WNNC_NET_OPENAFS
34 #define WNNC_NET_OPENAFS 0x00390000
37 #include <WINNT\afsreg.h>
39 DWORD TraceOption = 0;
43 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
45 void DebugEvent0(char *a)
47 HANDLE h; char *ptbuf[1];
49 if (!ISLOGONTRACE(TraceOption))
52 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
53 if (h != INVALID_HANDLE_VALUE) {
55 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
56 DeregisterEventSource(h);
61 void DebugEvent(char *b,...)
63 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
66 if (!ISLOGONTRACE(TraceOption))
69 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
70 if (h != INVALID_HANDLE_VALUE) {
72 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
75 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
76 DeregisterEventSource(h);
81 static HANDLE hInitMutex = NULL;
82 static BOOL bInit = FALSE;
84 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
90 case DLL_PROCESS_ATTACH:
91 /* Initialization Mutex */
93 hInitMutex = CreateMutex(NULL, FALSE, NULL);
95 WSAStartup( MAKEWORD(2,2), &wsaData );
98 case DLL_PROCESS_DETACH:
100 CloseHandle(hInitMutex);
105 case DLL_THREAD_ATTACH:
106 case DLL_THREAD_DETACH:
108 /* Everything else succeeds but does nothing. */
115 void AfsLogonInit(void)
117 if ( bInit == FALSE ) {
118 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
119 /* initAFSDirPath() initializes an array and sets a
120 * flag so that the initialization can only occur
121 * once. No cleanup will be done when the DLL is
122 * unloaded so the initialization will not be
123 * performed again on a subsequent reload
127 /* ka_Init initializes a number of error tables.
128 * and then calls ka_CellConfig() which grabs
129 * an afsconf_dir structure via afsconf_Open().
130 * Upon a second attempt to call ka_CellConfig()
131 * the structure will be released with afsconf_Close()
132 * and then re-opened. Could this corrupt memory?
134 * We only need this if we are not using KFW.
136 if (!KFW_is_available())
140 ReleaseMutex(hInitMutex);
144 CHAR *GenRandomName(CHAR *pbuf)
147 srand( (unsigned)time( NULL ) );
148 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
149 pbuf[i]='a'+(rand() % 26);
150 pbuf[MAXRANDOMNAMELEN-1]=0;
154 BOOLEAN AFSWillAutoStart(void)
159 BOOLEAN result = FALSE;
160 LPQUERY_SERVICE_CONFIG pConfig = NULL;
164 /* Open services manager */
165 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
166 if (!scm) return FALSE;
168 /* Open AFSD service */
169 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
173 /* Query AFSD service config, first just to get buffer size */
174 /* Expected to fail, so don't test return value */
175 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
176 status = GetLastError();
177 if (status != ERROR_INSUFFICIENT_BUFFER)
180 /* Allocate buffer */
181 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
185 /* Query AFSD service config, this time for real */
186 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
190 /* Is it autostart? */
191 if (pConfig->dwStartType < SERVICE_DEMAND_START)
197 CloseServiceHandle(svc);
199 CloseServiceHandle(scm);
204 DWORD MapAuthError(DWORD code)
207 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
208 * logon scripts for all credential managers, although they will still
209 * receive logon notifications. Since we don't want this, we return
210 * WN_SUCCESS. This is highly undesirable, but we also don't want to
211 * break other network providers.
215 return WN_NO_NETWORK; */
216 default: return WN_SUCCESS;
220 DWORD APIENTRY NPGetCaps(DWORD index)
224 /* Don't have our own type; use somebody else's. */
225 return WNNC_NET_OPENAFS;
228 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
237 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
238 DWORD profilePathLen )
241 LPWSTR ServerName = NULL;
242 LPUSER_INFO_3 p3 = NULL;
244 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
245 /* if NetGetAnyDCName fails, ServerName == NULL
246 * NetUserGetInfo will obtain local user information
248 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
249 if (code == NERR_Success)
251 code = NERR_UserNotFound;
253 if (p3->usri3_profile) {
254 DWORD len = lstrlenW(p3->usri3_profile);
256 /* Convert From Unicode to ANSI (UTF-8 for future) */
257 len = len < profilePathLen ? len : profilePathLen - 1;
258 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
259 profilePath[len] = '\0';
263 NetApiBufferFree(p3);
267 NetApiBufferFree(ServerName);
271 BOOL IsServiceRunning (void)
273 SERVICE_STATUS Status;
275 memset (&Status, 0x00, sizeof(Status));
276 Status.dwCurrentState = SERVICE_STOPPED;
278 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
281 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
283 QueryServiceStatus (hService, &Status);
284 CloseServiceHandle (hService);
287 CloseServiceHandle (hManager);
289 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
290 return (Status.dwCurrentState == SERVICE_RUNNING);
293 BOOL IsServiceStartPending (void)
295 SERVICE_STATUS Status;
297 memset (&Status, 0x00, sizeof(Status));
298 Status.dwCurrentState = SERVICE_STOPPED;
300 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
303 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
305 QueryServiceStatus (hService, &Status);
306 CloseServiceHandle (hService);
309 CloseServiceHandle (hManager);
311 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
312 return (Status.dwCurrentState == SERVICE_START_PENDING);
315 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
316 v:variable to receive value (reference type)
318 d:default, in case the value isn't on any of the keys
320 #define LOOKUPKEYCHAIN(v,t,d,n) \
322 rv = ~ERROR_SUCCESS; \
325 dwSize = sizeof(v); \
326 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
327 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
328 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
330 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
331 dwSize = sizeof(v); \
332 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
333 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
334 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
336 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
337 dwSize = sizeof(v); \
338 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
339 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
340 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
342 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
344 DebugEvent0(#v " being set to default"); \
348 /* Get domain specific configuration info. We are returning void because if anything goes wrong
349 we just return defaults.
352 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
353 HKEY hkParm = NULL; /* Service parameter */
354 HKEY hkNp = NULL; /* network provider key */
355 HKEY hkDoms = NULL; /* domains key */
356 HKEY hkDom = NULL; /* DOMAINS/domain key */
362 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
363 char *effDomain = NULL;
365 memset(opt, 0, sizeof(LogonOptions_t));
367 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
368 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
369 opt->flags = LOGON_FLAG_REMOTE;
371 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
372 if(GetComputerName(computerName, &dwSize)) {
373 if(!cm_stricmp_utf8(computerName, domain)) {
374 effDomain = "LOCALHOST";
375 opt->flags = LOGON_FLAG_LOCAL;
378 if (effDomain == NULL)
382 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
383 if(rv != ERROR_SUCCESS) {
385 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
388 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
389 if(rv != ERROR_SUCCESS) {
391 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
395 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
396 if( rv != ERROR_SUCCESS ) {
398 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
402 if(hkDoms && effDomain) {
403 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
404 if( rv != ERROR_SUCCESS ) {
406 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
407 /* If none of the domains match, we shouldn't use the domain key either */
412 DebugEvent0("Not opening domain key");
414 /* Each individual can either be specified on the domain key, the domains key or in the
415 net provider key. They fail over in that order. If none is found, we just use the
419 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
421 /* FailLoginsSilently */
422 dwSize = sizeof(dwDummy);
423 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
424 if (rv != ERROR_SUCCESS)
425 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
426 opt->failSilently = dwDummy ? 1 :0;
429 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
432 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
434 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
435 DebugEvent0("Integrated logon disabled");
436 goto cleanup; /* no need to lookup the logon script */
439 /* come up with SMB username */
440 if(ISHIGHSECURITY(opt->LogonOption)) {
441 DebugEvent0("High Security Mode active");
442 opt->smbName = malloc( MAXRANDOMNAMELEN );
443 if (opt->smbName == NULL)
445 GenRandomName(opt->smbName);
446 } else if (lpLogonId) {
447 /* username and domain for logon session is not necessarily the same as
448 username and domain passed into network provider. */
449 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
450 char lsaUsername[MAX_USERNAME_LENGTH]="";
451 char lsaDomain[MAX_DOMAIN_LENGTH]="";
455 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
456 if ( FAILED(Status) || plsd == NULL ) {
457 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
461 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
464 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
467 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
469 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
474 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
481 opt->smbName = malloc(len);
482 if (opt->smbName == NULL)
485 StringCbCopy(opt->smbName, len, lsaDomain);
486 StringCbCat(opt->smbName, len, "\\");
487 StringCbCat(opt->smbName, len, lsaUsername);
489 strlwr(opt->smbName);
493 LsaFreeReturnBuffer(plsd);
495 if (opt->smbName == NULL) {
498 DebugEvent("Constructing username using [%s] and [%s]",
501 len = strlen(username) + strlen(domain) + 2;
503 opt->smbName = malloc(len);
504 if (opt->smbName == NULL)
507 StringCbCopy(opt->smbName, len, domain);
508 StringCbCat(opt->smbName, len, "\\");
509 StringCbCat(opt->smbName, len, username);
511 strlwr(opt->smbName);
514 DebugEvent0("Looking up logon script");
516 /* First find out where the key is */
521 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
522 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
524 DebugEvent0("Located logon script in hkDom");
527 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
528 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
530 DebugEvent0("Located logon script in hkDoms");
532 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
533 else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
534 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
535 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
537 DebugEvent0("Located logon script in hkNp");
543 WCHAR *regscript = NULL;
544 WCHAR *regexscript = NULL;
545 WCHAR *regexuscript = NULL;
546 WCHAR *wuname = NULL;
551 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
554 wuname = malloc(len * sizeof(WCHAR));
556 goto doneLogonScript;
557 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
559 DebugEvent("Username is set for [%S]", wuname);
561 /* dwSize still has the size of the required buffer in bytes. */
562 regscript = malloc(dwSize);
564 goto doneLogonScript;
565 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
566 if(rv != ERROR_SUCCESS) {/* what the ..? */
567 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
568 goto doneLogonScript;
571 DebugEvent("Found logon script [%S]", regscript);
573 if(dwType == REG_EXPAND_SZ) {
576 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
577 regexscript = malloc(dwSize);
579 goto doneLogonScript;
580 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
582 regscript = regexscript;
584 if(dwReq > (dwSize / sizeof(WCHAR))) {
585 DebugEvent0("Overflow while expanding environment strings.");
586 goto doneLogonScript;
590 DebugEvent("After expanding env strings [%S]", regscript);
592 if(wcsstr(regscript, L"%s")) {
593 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
594 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
596 goto doneLogonScript;
597 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
599 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
601 goto doneLogonScript;
602 hr = StringCbCopyW(regexuscript, dwSize, regscript);
605 DebugEvent("After expanding username [%S]", regexuscript);
608 opt->logonScript = regexuscript;
610 LocalFree(regexuscript);
613 if(wuname) free(wuname);
614 if(regscript) free(regscript);
615 if(regexscript) free(regexscript);
618 DebugEvent0("Looking up TheseCells");
620 /* First find out where the key is */
625 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
626 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
628 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
630 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
631 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
633 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
635 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
636 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
638 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
644 CHAR * thesecells = NULL;
646 /* dwSize still has the size of the required buffer in bytes. */
647 thesecells = malloc(dwSize*2);
652 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
653 if(rv != ERROR_SUCCESS) {/* what the ..? */
654 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
658 DebugEvent("Found TheseCells [%s]", thesecells);
659 opt->theseCells = thesecells;
663 if (thesecells) free(thesecells);
666 DebugEvent0("Looking up Realm");
668 /* First find out where the key is */
673 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
674 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
676 DebugEvent("Located Realm in hkDom size %d", dwSize);
678 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
679 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
681 DebugEvent("Located Realm in hkDoms size %d", dwSize);
683 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
684 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
686 DebugEvent("Located Realm in hkNp size %d", dwSize);
694 /* dwSize still has the size of the required buffer in bytes. */
695 realm = malloc(dwSize*2);
700 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
701 if(rv != ERROR_SUCCESS) {/* what the ..? */
702 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
706 DebugEvent("Found Realm [%s]", realm);
711 if (realm) free(realm);
715 if(hkNp) RegCloseKey(hkNp);
716 if(hkDom) RegCloseKey(hkDom);
717 if(hkDoms) RegCloseKey(hkDoms);
718 if(hkParm) RegCloseKey(hkParm);
721 #undef LOOKUPKEYCHAIN
723 /* Try to find out which cell the given path is in. We must retain
724 the contents of *cell in case of failure. *cell is assumed to be
725 at least cellLen chars */
726 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
727 struct ViceIoctl blob;
728 char tcell[MAX_PATH];
732 blob.out_size = MAX_PATH;
735 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
738 strncpy(cell, tcell, cellLen);
739 cell[cellLen - 1] = '\0';
747 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
751 GetCPInfo(CP_ACP, &CodePageInfo);
753 if (CodePageInfo.MaxCharSize > 1)
754 // Only supporting non-Unicode strings
757 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
759 // Looks like unicode, better translate it
760 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
761 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
762 lpszOutputString, nOutStringLen-1, NULL, NULL);
763 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
767 lpszOutputString[0] = '\0';
769 } // UnicodeStringToANSI
771 DWORD APIENTRY NPLogonNotify(
773 LPCWSTR lpAuthentInfoType,
774 LPVOID lpAuthentInfo,
775 LPCWSTR lpPreviousAuthentInfoType,
776 LPVOID lpPreviousAuthentInfo,
777 LPWSTR lpStationName,
778 LPVOID StationHandle,
779 LPWSTR *lpLogonScript)
781 char uname[MAX_USERNAME_LENGTH]="";
782 char password[MAX_PASSWORD_LENGTH]="";
783 char logonDomain[MAX_DOMAIN_LENGTH]="";
784 char cell[256]="<non-integrated logon>";
785 char homePath[MAX_PATH]="";
786 char szLogonId[128] = "";
788 MSV1_0_INTERACTIVE_LOGON *IL;
790 DWORD code = 0, code2;
798 DWORD LSPtype, LSPsize;
801 HWND hwndOwner = (HWND)StationHandle;
803 BOOLEAN afsWillAutoStart;
805 BOOLEAN lowercased_name = TRUE;
807 LogonOptions_t opt; /* domain specific logon options */
811 /* Are we interactive? */
812 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
814 #ifdef DISABLE_NON_INTERACTIVE
815 /* Do not do anything if the logon session is not interactive. */
820 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
821 0, KEY_QUERY_VALUE, &NPKey);
822 LSPsize=sizeof(TraceOption);
823 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
824 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
828 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
830 /* Make sure the AFS Libraries are initialized */
833 /* Initialize Logon Script to none */
836 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
839 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
840 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
842 DebugEvent("Unsupported Authentication Info Type: %S",
847 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
849 /* Convert from Unicode to ANSI */
851 /*TODO: Use SecureZeroMemory to erase passwords */
852 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
853 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
854 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
857 /* Make sure AD-DOMANS sent from login that is sent to us is striped */
858 ctemp = strchr(uname, '@');
859 if (ctemp) *ctemp = 0;
861 /* is the name all lowercase? */
862 for ( ctemp = uname; *ctemp ; ctemp++) {
863 if ( !islower(*ctemp) ) {
864 lowercased_name = FALSE;
873 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
874 retryInterval = opt.retryInterval;
875 sleepInterval = opt.sleepInterval;
876 *lpLogonScript = opt.logonScript;
878 if (retryInterval < sleepInterval)
879 sleepInterval = retryInterval;
881 DebugEvent("Got logon script: %S",opt.logonScript);
883 afsWillAutoStart = AFSWillAutoStart();
885 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
886 opt.LogonOption,afsWillAutoStart);
888 /* Check for zero length password if integrated logon*/
889 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
890 if ( password[0] == 0 ) {
891 DebugEvent0("Password is the empty string");
893 reason = "zero length password is illegal";
897 /* Get cell name if doing integrated logon.
898 We might overwrite this if we are logging into an AD realm and we find out that
899 the user's home dir is in some other cell. */
900 DebugEvent("About to call cm_GetRootCellName(%s)",cell);
901 code = cm_GetRootCellName(cell);
903 DebugEvent0("Unable to obtain Root Cell");
905 reason = "unknown cell";
908 DebugEvent("Cell is %s",cell);
911 /* We get the user's home directory path, if applicable, though we can't lookup the
912 cell right away because the client service may not have started yet. This call
913 also sets the AD_REALM flag in opt.flags if applicable. */
914 if (ISREMOTE(opt.flags)) {
915 DebugEvent0("Is Remote");
916 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
920 /* loop until AFS is started. */
921 if (afsWillAutoStart) {
922 while (IsServiceRunning() || IsServiceStartPending()) {
923 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
924 opt.LogonOption,afsWillAutoStart);
926 if (ISADREALM(opt.flags)) {
927 code = GetFileCellName(homePath,cell,256);
929 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
931 /* Don't bail out if GetFileCellName failed.
932 * The home dir may not be in AFS after all.
937 /* if Integrated Logon */
938 if (ISLOGONINTEGRATED(opt.LogonOption))
940 if ( KFW_is_available() ) {
941 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
943 char * principal, *p;
946 StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
948 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
951 /* tlen is now the length of uname in characters */
952 principal = (char *)malloc(len * sizeof(char));
954 StringCchCopy(principal, len, uname);
955 p = principal + tlen;
957 StringCchCopy(p, len - tlen -1, opt.realm);
958 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
959 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
960 principal,opt.smbName,cell,code);
964 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
965 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
966 uname,opt.smbName,cell,code);
968 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
969 if (code == 0 && opt.theseCells) {
970 char * principal, *p;
973 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
975 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
978 /* tlen is now the length of uname in characters */
979 principal = (char *)malloc(len * sizeof(char));
981 StringCchCopy(principal, len, uname);
982 p = principal + tlen;
985 StringCchCopy(p, len - tlen -1, opt.realm);
987 StringCchCopy(p, len - tlen - 1, cell);
994 if ( cm_stricmp_utf8(p, cell) ) {
995 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
996 code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
997 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
998 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
999 principal,opt.smbName,p,code2);
1007 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
1008 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
1010 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1011 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
1013 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
1014 for ( ctemp = uname; *ctemp ; ctemp++) {
1015 *ctemp = tolower(*ctemp);
1017 lowercased_name = TRUE;
1021 /* is service started yet?*/
1023 /* If we've failed because the client isn't running yet and the
1024 * client is set to autostart (and therefore it makes sense for
1025 * us to wait for it to start) then sleep a while and try again.
1026 * If the error was something else, then give up. */
1027 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1031 /*JUST check to see if its running*/
1032 if (IsServiceRunning())
1034 if (!IsServiceStartPending()) {
1036 reason = "AFS Service start failed";
1041 /* If the retry interval has expired and we still aren't
1042 * logged in, then just give up if we are not in interactive
1043 * mode or the failSilently flag is set, otherwise let the
1044 * user know we failed and give them a chance to try again. */
1045 if (retryInterval <= 0) {
1046 reason = "AFS not running";
1047 if (!interactive || opt.failSilently)
1049 flag = MessageBox(hwndOwner,
1050 "AFS is still starting. Retry?",
1052 MB_ICONQUESTION | MB_RETRYCANCEL);
1053 if (flag == IDCANCEL)
1056 /* Wait just a little while and try again */
1057 retryInterval = opt.retryInterval;
1061 Sleep(sleepInterval * 1000);
1062 retryInterval -= sleepInterval;
1065 DebugEvent0("while loop exited");
1067 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1071 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1073 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1074 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1076 KFW_AFS_destroy_tickets_for_principal(uname);
1084 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1086 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1087 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1089 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1091 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1093 DeregisterEventSource(h);
1095 code = MapAuthError(code);
1098 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1101 LocalFree(*lpLogonScript);
1102 *lpLogonScript = NULL;
1103 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1108 if (opt.theseCells) free(opt.theseCells);
1109 if (opt.smbName) free(opt.smbName);
1110 if (opt.realm) free(opt.realm);
1112 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1116 DWORD APIENTRY NPPasswordChangeNotify(
1117 LPCWSTR lpAuthentInfoType,
1118 LPVOID lpAuthentInfo,
1119 LPCWSTR lpPreviousAuthentInfoType,
1120 LPVOID lpPreviousAuthentInfo,
1121 LPWSTR lpStationName,
1122 LPVOID StationHandle,
1125 BOOLEAN interactive;
1127 /* Are we interactive? */
1128 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1130 /* Do not do anything if the logon session is not interactive. */
1134 /* Make sure the AFS Libraries are initialized */
1137 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1141 #include <userenv.h>
1143 #include <afs/vice.h>
1144 #include <afs/fs_utils.h>
1146 BOOL IsPathInAfs(const CHAR *strPath)
1149 struct ViceIoctl blob;
1153 blob.out_size = 2048;
1156 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1163 typedef struct _WLX_NOTIFICATION_INFO {
1168 PWSTR WindowStation;
1171 PFNMSGECALLBACK pStatusCallback;
1172 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1175 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1177 DWORD LSPtype, LSPsize;
1180 /* Make sure the AFS Libraries are initialized */
1183 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1184 0, KEY_QUERY_VALUE, &NPKey);
1185 LSPsize=sizeof(TraceOption);
1186 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1187 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1189 RegCloseKey (NPKey);
1190 DebugEvent0("AFS_Startup_Event");
1193 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1196 TCHAR profileDir[1024] = TEXT("");
1198 PTOKEN_USER tokenUser = NULL;
1200 DWORD LSPtype, LSPsize;
1202 DWORD LogoffPreserveTokens = 0;
1205 /* Make sure the AFS Libraries are initialized */
1208 DebugEvent0("AFS_Logoff_Event - Start");
1210 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1211 0, KEY_QUERY_VALUE, &NPKey);
1212 LSPsize=sizeof(LogoffPreserveTokens);
1213 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1214 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1215 RegCloseKey (NPKey);
1217 if (!LogoffPreserveTokens) {
1218 memset(&opt, 0, sizeof(LogonOptions_t));
1220 if (pInfo->UserName && pInfo->Domain) {
1221 char username[MAX_USERNAME_LENGTH] = "";
1222 char domain[MAX_DOMAIN_LENGTH] = "";
1225 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1226 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1227 username, sizeof(username), NULL, NULL);
1229 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1230 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1231 domain, sizeof(domain), NULL, NULL);
1233 GetDomainLogonOptions(NULL, username, domain, &opt);
1236 if (ISREMOTE(opt.flags)) {
1237 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1239 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1240 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1242 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1244 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1249 /* We can't use pInfo->Domain for the domain since in the cross realm case
1250 * this is source domain and not the destination domain.
1252 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1253 WCHAR Domain[64]=L"";
1254 GetLocalShortDomain(Domain, sizeof(Domain));
1255 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1256 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1257 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1261 if (strlen(profileDir)) {
1262 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1263 if (!IsPathInAfs(profileDir)) {
1264 if (code = ktc_ForgetAllTokens())
1265 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1267 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1269 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1272 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1276 LocalFree(tokenUser);
1278 DebugEvent0("AFS_Logoff_Event - Local Logon");
1279 if (code = ktc_ForgetAllTokens())
1280 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1282 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1285 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1288 DebugEvent0("AFS_Logoff_Event - End");
1291 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1293 TCHAR profileDir[1024] = TEXT("");
1295 PTOKEN_USER tokenUser = NULL;
1297 WCHAR szUserW[128] = L"";
1298 char szUserA[128] = "";
1299 char szClient[MAX_PATH];
1300 char szPath[MAX_PATH] = "";
1306 /* Make sure the AFS Libraries are initialized */
1309 DebugEvent0("AFS_Logon_Event - Start");
1311 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1313 memset(&opt, 0, sizeof(LogonOptions_t));
1315 if (pInfo->UserName && pInfo->Domain) {
1316 char username[MAX_USERNAME_LENGTH] = "";
1317 char domain[MAX_DOMAIN_LENGTH] = "";
1320 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1322 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1323 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1324 username, sizeof(username), NULL, NULL);
1326 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1327 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1328 domain, sizeof(domain), NULL, NULL);
1330 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1331 GetDomainLogonOptions(NULL, username, domain, &opt);
1333 if (!pInfo->UserName)
1334 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1336 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1339 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1340 opt.LogonOption, opt.flags);
1342 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1343 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1344 goto done_logon_event;
1347 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1349 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1351 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1352 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1354 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1356 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1361 /* We can't use pInfo->Domain for the domain since in the cross realm case
1362 * this is source domain and not the destination domain.
1364 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1365 WCHAR Domain[64]=L"";
1366 GetLocalShortDomain(Domain, sizeof(Domain));
1367 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1368 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1369 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1373 if (strlen(profileDir)) {
1374 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1376 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1380 dwSize = sizeof(szUserA);
1381 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1382 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1383 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1388 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1389 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1391 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1393 memset (&nr, 0x00, sizeof(NETRESOURCE));
1394 nr.dwType=RESOURCETYPE_DISK;
1396 nr.lpRemoteName=szPath;
1397 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1399 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1400 szPath, szUserA,res);
1402 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1404 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1407 LocalFree(tokenUser);
1409 DebugEvent0("AFS_Logon_Event - End");
1413 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1415 NTSTATUS Status = 0;
1416 TOKEN_STATISTICS Stats;
1422 *ppSessionData = NULL;
1424 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1428 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1429 if ( FAILED(Status) || !ppSessionData )
1435 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1438 WCHAR szUserW[128] = L"";
1439 char szUserA[128] = "";
1440 char szPath[MAX_PATH] = "";
1441 char szLogonId[128] = "";
1443 char filename[MAX_PATH] = "";
1444 char newfilename[MAX_PATH] = "";
1445 char commandline[MAX_PATH+256] = "";
1446 STARTUPINFO startupinfo;
1447 PROCESS_INFORMATION procinfo;
1448 HANDLE hf = INVALID_HANDLE_VALUE;
1450 LUID LogonId = {0, 0};
1451 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1453 HKEY hKey1 = NULL, hKey2 = NULL;
1455 /* Make sure the KFW Libraries are initialized */
1458 DebugEvent0("KFW_Logon_Event - Start");
1460 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1462 if ( pLogonSessionData ) {
1463 LogonId = pLogonSessionData->LogonId;
1464 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1466 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1467 LsaFreeReturnBuffer( pLogonSessionData );
1469 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1473 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1474 if ( count > sizeof(filename) || count == 0 ) {
1475 GetWindowsDirectory(filename, sizeof(filename));
1478 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1479 if ( count > sizeof(filename) || count == 0 ) {
1480 GetWindowsDirectory(filename, sizeof(filename));
1483 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1484 DebugEvent0("KFW_Logon_Event - filename too long");
1488 strcat(filename, "\\");
1489 strcat(filename, szLogonId);
1491 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1492 FILE_ATTRIBUTE_NORMAL, NULL);
1493 if (hf == INVALID_HANDLE_VALUE) {
1494 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1499 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1500 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1501 DeleteFile(filename);
1505 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1506 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1510 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1511 DebugEvent0("KFW_Logon_Event - new filename too long");
1515 strcat(newfilename, "\\");
1516 strcat(newfilename, szLogonId);
1518 if (!MoveFileEx(filename, newfilename,
1519 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1520 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1524 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1526 GetStartupInfo(&startupinfo);
1527 if (CreateProcessAsUser( pInfo->hToken,
1533 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1539 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1541 WaitForSingleObject(procinfo.hProcess, 30000);
1543 CloseHandle(procinfo.hThread);
1544 CloseHandle(procinfo.hProcess);
1546 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1549 DeleteFile(filename);
1551 DebugEvent0("KFW_Logon_Event - End");