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
10 #include <afsconfig.h>
11 #include <afs/param.h>
18 #include <sys/types.h>
26 #include <afs/pioctl_nt.h>
27 #include <afs/kautils.h>
30 #include "cm_config.h"
33 #include "lanahelper.h"
35 /* Allocated in Windows Driver Kit */
36 #ifndef WNNC_NET_OPENAFS
37 #define WNNC_NET_OPENAFS 0x00390000
40 #include <WINNT\afsreg.h>
42 DWORD TraceOption = 0;
46 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
48 void DebugEvent0(char *a)
50 HANDLE h; char *ptbuf[1];
52 if (!ISLOGONTRACE(TraceOption))
55 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
56 if (h != INVALID_HANDLE_VALUE) {
58 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
59 DeregisterEventSource(h);
64 void DebugEvent(char *b,...)
66 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
69 if (!ISLOGONTRACE(TraceOption))
72 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
73 if (h != INVALID_HANDLE_VALUE) {
75 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
78 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
79 DeregisterEventSource(h);
84 static HANDLE hInitMutex = NULL;
85 static BOOL bInit = FALSE;
87 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
93 case DLL_PROCESS_ATTACH:
94 /* Initialization Mutex */
96 hInitMutex = CreateMutex(NULL, FALSE, NULL);
98 WSAStartup( MAKEWORD(2,2), &wsaData );
101 case DLL_PROCESS_DETACH:
103 CloseHandle(hInitMutex);
108 case DLL_THREAD_ATTACH:
109 case DLL_THREAD_DETACH:
111 /* Everything else succeeds but does nothing. */
118 void AfsLogonInit(void)
120 if ( bInit == FALSE ) {
121 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
122 /* initAFSDirPath() initializes an array and sets a
123 * flag so that the initialization can only occur
124 * once. No cleanup will be done when the DLL is
125 * unloaded so the initialization will not be
126 * performed again on a subsequent reload
130 /* ka_Init initializes a number of error tables.
131 * and then calls ka_CellConfig() which grabs
132 * an afsconf_dir structure via afsconf_Open().
133 * Upon a second attempt to call ka_CellConfig()
134 * the structure will be released with afsconf_Close()
135 * and then re-opened. Could this corrupt memory?
137 * We only need this if we are not using KFW.
139 if (!KFW_is_available())
143 ReleaseMutex(hInitMutex);
147 CHAR *GenRandomName(CHAR *pbuf)
150 srand( (unsigned)time( NULL ) );
151 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
152 pbuf[i]='a'+(rand() % 26);
153 pbuf[MAXRANDOMNAMELEN-1]=0;
157 BOOLEAN AFSWillAutoStart(void)
162 BOOLEAN result = FALSE;
163 LPQUERY_SERVICE_CONFIG pConfig = NULL;
167 /* Open services manager */
168 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
169 if (!scm) return FALSE;
171 /* Open AFSD service */
172 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
176 /* Query AFSD service config, first just to get buffer size */
177 /* Expected to fail, so don't test return value */
178 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
179 status = GetLastError();
180 if (status != ERROR_INSUFFICIENT_BUFFER)
183 /* Allocate buffer */
184 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
188 /* Query AFSD service config, this time for real */
189 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
193 /* Is it autostart? */
194 if (pConfig->dwStartType < SERVICE_DEMAND_START)
200 CloseServiceHandle(svc);
202 CloseServiceHandle(scm);
207 DWORD MapAuthError(DWORD code)
210 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
211 * logon scripts for all credential managers, although they will still
212 * receive logon notifications. Since we don't want this, we return
213 * WN_SUCCESS. This is highly undesirable, but we also don't want to
214 * break other network providers.
218 return WN_NO_NETWORK; */
219 default: return WN_SUCCESS;
223 DWORD APIENTRY NPGetCaps(DWORD index)
227 /* Don't have our own type; use somebody else's. */
228 return WNNC_NET_OPENAFS;
231 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
240 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
241 DWORD profilePathLen )
244 LPWSTR ServerName = NULL;
245 LPUSER_INFO_3 p3 = NULL;
247 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
248 /* if NetGetAnyDCName fails, ServerName == NULL
249 * NetUserGetInfo will obtain local user information
251 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
252 if (code == NERR_Success)
254 code = NERR_UserNotFound;
256 if (p3->usri3_profile) {
257 DWORD len = lstrlenW(p3->usri3_profile);
259 /* Convert From Unicode to ANSI (UTF-8 for future) */
260 len = len < profilePathLen ? len : profilePathLen - 1;
261 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
262 profilePath[len] = '\0';
266 NetApiBufferFree(p3);
270 NetApiBufferFree(ServerName);
274 BOOL IsServiceRunning (void)
276 SERVICE_STATUS Status;
278 memset (&Status, 0x00, sizeof(Status));
279 Status.dwCurrentState = SERVICE_STOPPED;
281 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
284 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
286 QueryServiceStatus (hService, &Status);
287 CloseServiceHandle (hService);
290 CloseServiceHandle (hManager);
292 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
293 return (Status.dwCurrentState == SERVICE_RUNNING);
296 BOOL IsServiceStartPending (void)
298 SERVICE_STATUS Status;
300 memset (&Status, 0x00, sizeof(Status));
301 Status.dwCurrentState = SERVICE_STOPPED;
303 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
306 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
308 QueryServiceStatus (hService, &Status);
309 CloseServiceHandle (hService);
312 CloseServiceHandle (hManager);
314 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
315 return (Status.dwCurrentState == SERVICE_START_PENDING);
318 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
319 v:variable to receive value (reference type)
321 d:default, in case the value isn't on any of the keys
323 #define LOOKUPKEYCHAIN(v,t,d,n) \
325 rv = ~ERROR_SUCCESS; \
328 dwSize = sizeof(v); \
329 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
330 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
331 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
333 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
334 dwSize = sizeof(v); \
335 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
336 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
337 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
339 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
340 dwSize = sizeof(v); \
341 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
342 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
343 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
345 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
347 DebugEvent0(#v " being set to default"); \
351 /* Get domain specific configuration info. We are returning void because if anything goes wrong
352 we just return defaults.
355 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
356 HKEY hkParm = NULL; /* Service parameter */
357 HKEY hkNp = NULL; /* network provider key */
358 HKEY hkDoms = NULL; /* domains key */
359 HKEY hkDom = NULL; /* DOMAINS/domain key */
365 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
366 char *effDomain = NULL;
368 memset(opt, 0, sizeof(LogonOptions_t));
370 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
371 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
372 opt->flags = LOGON_FLAG_REMOTE;
374 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
375 if(GetComputerName(computerName, &dwSize)) {
376 if(!cm_stricmp_utf8(computerName, domain)) {
377 effDomain = "LOCALHOST";
378 opt->flags = LOGON_FLAG_LOCAL;
381 if (effDomain == NULL)
385 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
386 if(rv != ERROR_SUCCESS) {
388 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
391 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
392 if(rv != ERROR_SUCCESS) {
394 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
398 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
399 if( rv != ERROR_SUCCESS ) {
401 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
405 if(hkDoms && effDomain) {
406 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
407 if( rv != ERROR_SUCCESS ) {
409 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
410 /* If none of the domains match, we shouldn't use the domain key either */
415 DebugEvent0("Not opening domain key");
417 /* Each individual can either be specified on the domain key, the domains key or in the
418 net provider key. They fail over in that order. If none is found, we just use the
422 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
424 /* FailLoginsSilently */
425 dwSize = sizeof(dwDummy);
426 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
427 if (rv != ERROR_SUCCESS)
428 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
429 opt->failSilently = dwDummy ? 1 :0;
432 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
435 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
437 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
438 DebugEvent0("Integrated logon disabled");
439 goto cleanup; /* no need to lookup the logon script */
442 /* come up with SMB username */
443 if(ISHIGHSECURITY(opt->LogonOption)) {
444 DebugEvent0("High Security Mode active");
445 opt->smbName = malloc( MAXRANDOMNAMELEN );
446 if (opt->smbName == NULL)
448 GenRandomName(opt->smbName);
449 } else if (lpLogonId) {
450 /* username and domain for logon session is not necessarily the same as
451 username and domain passed into network provider. */
452 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
453 char lsaUsername[MAX_USERNAME_LENGTH]="";
454 char lsaDomain[MAX_DOMAIN_LENGTH]="";
458 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
459 if ( FAILED(Status) || plsd == NULL ) {
460 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
464 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
467 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
470 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
472 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
477 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
484 opt->smbName = malloc(len);
485 if (opt->smbName == NULL)
488 StringCbCopy(opt->smbName, len, lsaDomain);
489 StringCbCat(opt->smbName, len, "\\");
490 StringCbCat(opt->smbName, len, lsaUsername);
492 strlwr(opt->smbName);
496 LsaFreeReturnBuffer(plsd);
498 if (opt->smbName == NULL) {
501 DebugEvent("Constructing username using [%s] and [%s]",
504 len = strlen(username) + strlen(domain) + 2;
506 opt->smbName = malloc(len);
507 if (opt->smbName == NULL)
510 StringCbCopy(opt->smbName, len, domain);
511 StringCbCat(opt->smbName, len, "\\");
512 StringCbCat(opt->smbName, len, username);
514 strlwr(opt->smbName);
517 DebugEvent0("Looking up logon script");
519 /* First find out where the key is */
524 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
525 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
527 DebugEvent0("Located logon script in hkDom");
530 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
531 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
533 DebugEvent0("Located logon script in hkDoms");
535 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
536 else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
537 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
538 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
540 DebugEvent0("Located logon script in hkNp");
546 WCHAR *regscript = NULL;
547 WCHAR *regexscript = NULL;
548 WCHAR *regexuscript = NULL;
549 WCHAR *wuname = NULL;
554 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
557 wuname = malloc(len * sizeof(WCHAR));
559 goto doneLogonScript;
560 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
562 DebugEvent("Username is set for [%S]", wuname);
564 /* dwSize still has the size of the required buffer in bytes. */
565 regscript = malloc(dwSize);
567 goto doneLogonScript;
568 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
569 if(rv != ERROR_SUCCESS) {/* what the ..? */
570 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
571 goto doneLogonScript;
574 DebugEvent("Found logon script [%S]", regscript);
576 if(dwType == REG_EXPAND_SZ) {
579 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
580 regexscript = malloc(dwSize);
582 goto doneLogonScript;
583 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
585 regscript = regexscript;
587 if(dwReq > (dwSize / sizeof(WCHAR))) {
588 DebugEvent0("Overflow while expanding environment strings.");
589 goto doneLogonScript;
593 DebugEvent("After expanding env strings [%S]", regscript);
595 if(wcsstr(regscript, L"%s")) {
596 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
597 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
599 goto doneLogonScript;
600 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
602 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
604 goto doneLogonScript;
605 hr = StringCbCopyW(regexuscript, dwSize, regscript);
608 DebugEvent("After expanding username [%S]", regexuscript);
611 opt->logonScript = regexuscript;
613 LocalFree(regexuscript);
616 if(wuname) free(wuname);
617 if(regscript) free(regscript);
618 if(regexscript) free(regexscript);
621 DebugEvent0("Looking up TheseCells");
623 /* First find out where the key is */
628 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
629 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
631 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
633 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
634 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
636 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
638 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
639 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
641 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
647 CHAR * thesecells = NULL;
649 /* dwSize still has the size of the required buffer in bytes. */
650 thesecells = malloc(dwSize*2);
655 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
656 if(rv != ERROR_SUCCESS) {/* what the ..? */
657 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
661 DebugEvent("Found TheseCells [%s]", thesecells);
662 opt->theseCells = thesecells;
666 if (thesecells) free(thesecells);
669 DebugEvent0("Looking up Realm");
671 /* First find out where the key is */
676 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
677 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
679 DebugEvent("Located Realm in hkDom size %d", dwSize);
681 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
682 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
684 DebugEvent("Located Realm in hkDoms size %d", dwSize);
686 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
687 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
689 DebugEvent("Located Realm in hkNp size %d", dwSize);
697 /* dwSize still has the size of the required buffer in bytes. */
698 realm = malloc(dwSize*2);
703 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
704 if(rv != ERROR_SUCCESS) {/* what the ..? */
705 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
709 DebugEvent("Found Realm [%s]", realm);
714 if (realm) free(realm);
718 if(hkNp) RegCloseKey(hkNp);
719 if(hkDom) RegCloseKey(hkDom);
720 if(hkDoms) RegCloseKey(hkDoms);
721 if(hkParm) RegCloseKey(hkParm);
724 #undef LOOKUPKEYCHAIN
726 /* Try to find out which cell the given path is in. We must retain
727 the contents of *cell in case of failure. *cell is assumed to be
728 at least cellLen chars */
729 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
730 struct ViceIoctl blob;
731 char tcell[MAX_PATH];
735 blob.out_size = MAX_PATH;
738 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
741 strncpy(cell, tcell, cellLen);
742 cell[cellLen - 1] = '\0';
750 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
754 GetCPInfo(CP_ACP, &CodePageInfo);
756 if (CodePageInfo.MaxCharSize > 1)
757 // Only supporting non-Unicode strings
760 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
762 // Looks like unicode, better translate it
763 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
764 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
765 lpszOutputString, nOutStringLen-1, NULL, NULL);
766 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
770 lpszOutputString[0] = '\0';
772 } // UnicodeStringToANSI
774 DWORD APIENTRY NPLogonNotify(
776 LPCWSTR lpAuthentInfoType,
777 LPVOID lpAuthentInfo,
778 LPCWSTR lpPreviousAuthentInfoType,
779 LPVOID lpPreviousAuthentInfo,
780 LPWSTR lpStationName,
781 LPVOID StationHandle,
782 LPWSTR *lpLogonScript)
784 char uname[MAX_USERNAME_LENGTH]="";
785 char password[MAX_PASSWORD_LENGTH]="";
786 char logonDomain[MAX_DOMAIN_LENGTH]="";
787 char cell[256]="<non-integrated logon>";
788 char homePath[MAX_PATH]="";
789 char szLogonId[128] = "";
791 MSV1_0_INTERACTIVE_LOGON *IL;
793 DWORD code = 0, code2;
801 DWORD LSPtype, LSPsize;
804 HWND hwndOwner = (HWND)StationHandle;
806 BOOLEAN afsWillAutoStart;
808 BOOLEAN lowercased_name = TRUE;
810 LogonOptions_t opt; /* domain specific logon options */
814 /* Are we interactive? */
815 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
817 #ifdef DISABLE_NON_INTERACTIVE
818 /* Do not do anything if the logon session is not interactive. */
823 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
824 0, KEY_QUERY_VALUE, &NPKey);
825 LSPsize=sizeof(TraceOption);
826 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
827 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
831 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
833 /* Make sure the AFS Libraries are initialized */
836 /* Initialize Logon Script to none */
839 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
842 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
843 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
845 DebugEvent("Unsupported Authentication Info Type: %S",
850 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
852 /* Convert from Unicode to ANSI */
854 /*TODO: Use SecureZeroMemory to erase passwords */
855 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
856 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
857 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
860 /* Make sure AD-DOMAINS sent from login that is sent to us is striped */
861 ctemp = strchr(uname, '@');
865 if ( logonDomain[0] == '\0' )
866 StringCchCopy(logonDomain, MAX_DOMAIN_LENGTH, ctemp);
869 /* is the name all lowercase? */
870 for ( ctemp = uname; *ctemp ; ctemp++) {
871 if ( !islower(*ctemp) ) {
872 lowercased_name = FALSE;
881 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
882 retryInterval = opt.retryInterval;
883 sleepInterval = opt.sleepInterval;
884 *lpLogonScript = opt.logonScript;
886 if (retryInterval < sleepInterval)
887 sleepInterval = retryInterval;
889 DebugEvent("Got logon script: %S",opt.logonScript);
891 afsWillAutoStart = AFSWillAutoStart();
893 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
894 opt.LogonOption,afsWillAutoStart);
896 /* Check for zero length password if integrated logon*/
897 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
898 if ( password[0] == 0 ) {
899 DebugEvent0("Password is the empty string");
901 reason = "zero length password is illegal";
905 /* Get cell name if doing integrated logon.
906 We might overwrite this if we are logging into an AD realm and we find out that
907 the user's home dir is in some other cell. */
908 DebugEvent("About to call cm_GetRootCellName(%s)",cell);
909 code = cm_GetRootCellName(cell);
911 DebugEvent0("Unable to obtain Root Cell");
913 reason = "unknown cell";
916 DebugEvent("Cell is %s",cell);
919 /* We get the user's home directory path, if applicable, though we can't lookup the
920 cell right away because the client service may not have started yet. This call
921 also sets the AD_REALM flag in opt.flags if applicable. */
922 if (ISREMOTE(opt.flags)) {
923 DebugEvent0("Is Remote");
924 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
928 /* loop until AFS is started. */
929 if (afsWillAutoStart) {
930 while (IsServiceRunning() || IsServiceStartPending()) {
931 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
932 opt.LogonOption,afsWillAutoStart);
934 if (ISADREALM(opt.flags)) {
935 code = GetFileCellName(homePath,cell,256);
937 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
939 /* Don't bail out if GetFileCellName failed.
940 * The home dir may not be in AFS after all.
945 /* if Integrated Logon */
946 if (ISLOGONINTEGRATED(opt.LogonOption))
948 if ( KFW_is_available() ) {
949 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
951 char * principal, *p;
954 StringCchLength(opt.realm, 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;
965 StringCchCopy(p, len - tlen -1, opt.realm);
966 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
967 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
968 principal,opt.smbName,cell,code);
972 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
973 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
974 uname,opt.smbName,cell,code);
976 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
977 if (code == 0 && opt.theseCells) {
978 char * principal, *p;
981 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
983 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
986 /* tlen is now the length of uname in characters */
987 principal = (char *)malloc(len * sizeof(char));
989 StringCchCopy(principal, len, uname);
990 p = principal + tlen;
993 StringCchCopy(p, len - tlen -1, opt.realm);
995 StringCchCopy(p, len - tlen - 1, cell);
1002 if ( cm_stricmp_utf8(p, cell) ) {
1003 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1004 code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
1005 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1006 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1007 principal,opt.smbName,p,code2);
1015 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
1016 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
1018 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1019 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
1021 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
1022 for ( ctemp = uname; *ctemp ; ctemp++) {
1023 *ctemp = tolower(*ctemp);
1025 lowercased_name = TRUE;
1029 /* is service started yet?*/
1031 /* If we've failed because the client isn't running yet and the
1032 * client is set to autostart (and therefore it makes sense for
1033 * us to wait for it to start) then sleep a while and try again.
1034 * If the error was something else, then give up. */
1035 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1039 /*JUST check to see if its running*/
1040 if (IsServiceRunning())
1042 if (!IsServiceStartPending()) {
1044 reason = "AFS Service start failed";
1049 /* If the retry interval has expired and we still aren't
1050 * logged in, then just give up if we are not in interactive
1051 * mode or the failSilently flag is set, otherwise let the
1052 * user know we failed and give them a chance to try again. */
1053 if (retryInterval <= 0) {
1054 reason = "AFS not running";
1055 if (!interactive || opt.failSilently)
1057 flag = MessageBox(hwndOwner,
1058 "AFS is still starting. Retry?",
1060 MB_ICONQUESTION | MB_RETRYCANCEL);
1061 if (flag == IDCANCEL)
1064 /* Wait just a little while and try again */
1065 retryInterval = opt.retryInterval;
1069 Sleep(sleepInterval * 1000);
1070 retryInterval -= sleepInterval;
1073 DebugEvent0("while loop exited");
1075 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1079 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1081 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1082 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1084 KFW_AFS_destroy_tickets_for_principal(uname);
1092 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1094 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1095 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1097 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1099 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1101 DeregisterEventSource(h);
1103 code = MapAuthError(code);
1106 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1109 LocalFree(*lpLogonScript);
1110 *lpLogonScript = NULL;
1111 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1116 if (opt.theseCells) free(opt.theseCells);
1117 if (opt.smbName) free(opt.smbName);
1118 if (opt.realm) free(opt.realm);
1120 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1124 DWORD APIENTRY NPPasswordChangeNotify(
1125 LPCWSTR lpAuthentInfoType,
1126 LPVOID lpAuthentInfo,
1127 LPCWSTR lpPreviousAuthentInfoType,
1128 LPVOID lpPreviousAuthentInfo,
1129 LPWSTR lpStationName,
1130 LPVOID StationHandle,
1133 BOOLEAN interactive;
1135 /* Are we interactive? */
1136 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1138 /* Do not do anything if the logon session is not interactive. */
1142 /* Make sure the AFS Libraries are initialized */
1145 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1149 #include <userenv.h>
1151 #include <afs/vice.h>
1152 #include <afs/fs_utils.h>
1154 BOOL IsPathInAfs(const CHAR *strPath)
1157 struct ViceIoctl blob;
1161 blob.out_size = 2048;
1164 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1171 typedef struct _WLX_NOTIFICATION_INFO {
1176 PWSTR WindowStation;
1179 PFNMSGECALLBACK pStatusCallback;
1180 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1183 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1185 DWORD LSPtype, LSPsize;
1188 /* Make sure the AFS Libraries are initialized */
1191 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1192 0, KEY_QUERY_VALUE, &NPKey);
1193 LSPsize=sizeof(TraceOption);
1194 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1195 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1197 RegCloseKey (NPKey);
1198 DebugEvent0("AFS_Startup_Event");
1201 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1204 TCHAR profileDir[1024] = TEXT("");
1206 PTOKEN_USER tokenUser = NULL;
1208 DWORD LSPtype, LSPsize;
1210 DWORD LogoffPreserveTokens = 0;
1213 /* Make sure the AFS Libraries are initialized */
1216 DebugEvent0("AFS_Logoff_Event - Start");
1218 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1219 0, KEY_QUERY_VALUE, &NPKey);
1220 LSPsize=sizeof(LogoffPreserveTokens);
1221 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1222 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1223 RegCloseKey (NPKey);
1225 if (!LogoffPreserveTokens) {
1226 memset(&opt, 0, sizeof(LogonOptions_t));
1228 if (pInfo->UserName && pInfo->Domain) {
1229 char username[MAX_USERNAME_LENGTH] = "";
1230 char domain[MAX_DOMAIN_LENGTH] = "";
1233 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1234 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1235 username, sizeof(username), NULL, NULL);
1237 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1238 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1239 domain, sizeof(domain), NULL, NULL);
1241 GetDomainLogonOptions(NULL, username, domain, &opt);
1244 if (ISREMOTE(opt.flags)) {
1245 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1247 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1248 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1250 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1252 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1257 /* We can't use pInfo->Domain for the domain since in the cross realm case
1258 * this is source domain and not the destination domain.
1260 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1261 WCHAR Domain[64]=L"";
1262 GetLocalShortDomain(Domain, sizeof(Domain));
1263 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1264 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1265 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1269 if (strlen(profileDir)) {
1270 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1271 if (!IsPathInAfs(profileDir)) {
1272 if (code = ktc_ForgetAllTokens())
1273 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1275 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1277 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1280 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1284 LocalFree(tokenUser);
1286 DebugEvent0("AFS_Logoff_Event - Local Logon");
1287 if (code = ktc_ForgetAllTokens())
1288 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1290 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1293 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1296 DebugEvent0("AFS_Logoff_Event - End");
1299 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1301 TCHAR profileDir[1024] = TEXT("");
1303 PTOKEN_USER tokenUser = NULL;
1305 WCHAR szUserW[128] = L"";
1306 char szUserA[128] = "";
1307 char szClient[MAX_PATH];
1308 char szPath[MAX_PATH] = "";
1314 /* Make sure the AFS Libraries are initialized */
1317 DebugEvent0("AFS_Logon_Event - Start");
1319 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1321 memset(&opt, 0, sizeof(LogonOptions_t));
1323 if (pInfo->UserName && pInfo->Domain) {
1324 char username[MAX_USERNAME_LENGTH] = "";
1325 char domain[MAX_DOMAIN_LENGTH] = "";
1328 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1330 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1331 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1332 username, sizeof(username), NULL, NULL);
1334 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1335 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1336 domain, sizeof(domain), NULL, NULL);
1338 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1339 GetDomainLogonOptions(NULL, username, domain, &opt);
1341 if (!pInfo->UserName)
1342 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1344 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1347 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1348 opt.LogonOption, opt.flags);
1350 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1351 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1352 goto done_logon_event;
1355 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1357 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1359 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1360 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1362 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1364 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1369 /* We can't use pInfo->Domain for the domain since in the cross realm case
1370 * this is source domain and not the destination domain.
1372 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1373 WCHAR Domain[64]=L"";
1374 GetLocalShortDomain(Domain, sizeof(Domain));
1375 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1376 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1377 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1381 if (strlen(profileDir)) {
1382 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1384 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1388 dwSize = sizeof(szUserA);
1389 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1390 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1391 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1396 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1397 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1399 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1401 memset (&nr, 0x00, sizeof(NETRESOURCE));
1402 nr.dwType=RESOURCETYPE_DISK;
1404 nr.lpRemoteName=szPath;
1405 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1407 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1408 szPath, szUserA,res);
1410 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1412 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1415 LocalFree(tokenUser);
1417 DebugEvent0("AFS_Logon_Event - End");
1421 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1423 NTSTATUS Status = 0;
1424 TOKEN_STATISTICS Stats;
1430 *ppSessionData = NULL;
1432 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1436 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1437 if ( FAILED(Status) || !ppSessionData )
1443 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1446 WCHAR szUserW[128] = L"";
1447 char szUserA[128] = "";
1448 char szPath[MAX_PATH] = "";
1449 char szLogonId[128] = "";
1451 char filename[MAX_PATH] = "";
1452 char newfilename[MAX_PATH] = "";
1453 char commandline[MAX_PATH+256] = "";
1454 STARTUPINFO startupinfo;
1455 PROCESS_INFORMATION procinfo;
1456 HANDLE hf = INVALID_HANDLE_VALUE;
1458 LUID LogonId = {0, 0};
1459 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1461 HKEY hKey1 = NULL, hKey2 = NULL;
1463 /* Make sure the KFW Libraries are initialized */
1466 DebugEvent0("KFW_Logon_Event - Start");
1468 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1470 if ( pLogonSessionData ) {
1471 LogonId = pLogonSessionData->LogonId;
1472 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1474 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1475 LsaFreeReturnBuffer( pLogonSessionData );
1477 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1481 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1482 if ( count > sizeof(filename) || count == 0 ) {
1483 GetWindowsDirectory(filename, sizeof(filename));
1486 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1487 if ( count > sizeof(filename) || count == 0 ) {
1488 GetWindowsDirectory(filename, sizeof(filename));
1491 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1492 DebugEvent0("KFW_Logon_Event - filename too long");
1496 strcat(filename, "\\");
1497 strcat(filename, szLogonId);
1499 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1500 FILE_ATTRIBUTE_NORMAL, NULL);
1501 if (hf == INVALID_HANDLE_VALUE) {
1502 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1507 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1508 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1509 DeleteFile(filename);
1513 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1514 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1518 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1519 DebugEvent0("KFW_Logon_Event - new filename too long");
1523 strcat(newfilename, "\\");
1524 strcat(newfilename, szLogonId);
1526 if (!MoveFileEx(filename, newfilename,
1527 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1528 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1532 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1534 GetStartupInfo(&startupinfo);
1535 if (CreateProcessAsUser( pInfo->hToken,
1541 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1547 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1549 WaitForSingleObject(procinfo.hProcess, 30000);
1551 CloseHandle(procinfo.hThread);
1552 CloseHandle(procinfo.hProcess);
1554 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1557 DeleteFile(filename);
1559 DebugEvent0("KFW_Logon_Event - End");