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 BOOL StartTheService (void)
323 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ|SERVICE_START)) != NULL)
326 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ|SERVICE_START)) != NULL)
328 StartService (hService, 0, NULL);
329 gle = GetLastError();
330 CloseServiceHandle (hService);
332 gle = GetLastError();
334 CloseServiceHandle (hManager);
336 DebugEvent("AFS AfsLogon - Service Start Return Code[0x%x]",gle);
340 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
341 v:variable to receive value (reference type)
343 d:default, in case the value isn't on any of the keys
345 #define LOOKUPKEYCHAIN(v,t,d,n) \
347 rv = ~ERROR_SUCCESS; \
350 dwSize = sizeof(v); \
351 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
352 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
353 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
355 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
356 dwSize = sizeof(v); \
357 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
358 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
359 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
361 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
362 dwSize = sizeof(v); \
363 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
364 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
365 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
367 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
369 DebugEvent0(#v " being set to default"); \
373 /* Get domain specific configuration info. We are returning void because if anything goes wrong
374 we just return defaults.
377 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
378 HKEY hkParm = NULL; /* Service parameter */
379 HKEY hkNp = NULL; /* network provider key */
380 HKEY hkDoms = NULL; /* domains key */
381 HKEY hkDom = NULL; /* DOMAINS/domain key */
387 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
388 char *effDomain = NULL;
390 memset(opt, 0, sizeof(LogonOptions_t));
392 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
393 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
394 opt->flags = LOGON_FLAG_REMOTE;
396 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
397 if(GetComputerName(computerName, &dwSize)) {
398 if(!cm_stricmp_utf8(computerName, domain)) {
399 effDomain = "LOCALHOST";
400 opt->flags = LOGON_FLAG_LOCAL;
403 if (effDomain == NULL)
407 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
408 if(rv != ERROR_SUCCESS) {
410 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
413 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
414 if(rv != ERROR_SUCCESS) {
416 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
420 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
421 if( rv != ERROR_SUCCESS ) {
423 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
427 if(hkDoms && effDomain) {
428 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
429 if( rv != ERROR_SUCCESS ) {
431 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
432 /* If none of the domains match, we shouldn't use the domain key either */
437 DebugEvent0("Not opening domain key");
439 /* Each individual can either be specified on the domain key, the domains key or in the
440 net provider key. They fail over in that order. If none is found, we just use the
444 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
446 /* FailLoginsSilently */
447 dwSize = sizeof(dwDummy);
448 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
449 if (rv != ERROR_SUCCESS)
450 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
451 opt->failSilently = dwDummy ? 1 :0;
454 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
457 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
459 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
460 DebugEvent0("Integrated logon disabled");
461 goto cleanup; /* no need to lookup the logon script */
464 /* come up with SMB username */
465 if(ISHIGHSECURITY(opt->LogonOption)) {
466 DebugEvent0("High Security Mode active");
467 opt->smbName = malloc( MAXRANDOMNAMELEN );
468 if (opt->smbName == NULL)
470 GenRandomName(opt->smbName);
471 } else if (lpLogonId) {
472 /* username and domain for logon session is not necessarily the same as
473 username and domain passed into network provider. */
474 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
475 char lsaUsername[MAX_USERNAME_LENGTH]="";
476 char lsaDomain[MAX_DOMAIN_LENGTH]="";
480 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
481 if ( FAILED(Status) || plsd == NULL ) {
482 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
486 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
489 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
492 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
494 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
499 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
506 opt->smbName = malloc(len);
507 if (opt->smbName == NULL)
510 StringCbCopy(opt->smbName, len, lsaDomain);
511 StringCbCat(opt->smbName, len, "\\");
512 StringCbCat(opt->smbName, len, lsaUsername);
514 strlwr(opt->smbName);
518 LsaFreeReturnBuffer(plsd);
520 if (opt->smbName == NULL) {
523 DebugEvent("Constructing username using [%s] and [%s]",
526 len = strlen(username) + strlen(domain) + 2;
528 opt->smbName = malloc(len);
529 if (opt->smbName == NULL)
532 StringCbCopy(opt->smbName, len, domain);
533 StringCbCat(opt->smbName, len, "\\");
534 StringCbCat(opt->smbName, len, username);
536 strlwr(opt->smbName);
539 DebugEvent0("Looking up logon script");
541 /* First find out where the key is */
546 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
547 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
549 DebugEvent0("Located logon script in hkDom");
552 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
553 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
555 DebugEvent0("Located logon script in hkDoms");
557 /* Note that the LogonScript in the NP key is only used if we are doing high security. */
558 else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
559 rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
560 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
562 DebugEvent0("Located logon script in hkNp");
568 WCHAR *regscript = NULL;
569 WCHAR *regexscript = NULL;
570 WCHAR *regexuscript = NULL;
571 WCHAR *wuname = NULL;
576 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
579 wuname = malloc(len * sizeof(WCHAR));
581 goto doneLogonScript;
582 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
584 DebugEvent("Username is set for [%S]", wuname);
586 /* dwSize still has the size of the required buffer in bytes. */
587 regscript = malloc(dwSize);
589 goto doneLogonScript;
590 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
591 if(rv != ERROR_SUCCESS) {/* what the ..? */
592 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
593 goto doneLogonScript;
596 DebugEvent("Found logon script [%S]", regscript);
598 if(dwType == REG_EXPAND_SZ) {
601 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
602 regexscript = malloc(dwSize);
604 goto doneLogonScript;
605 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
607 regscript = regexscript;
609 if(dwReq > (dwSize / sizeof(WCHAR))) {
610 DebugEvent0("Overflow while expanding environment strings.");
611 goto doneLogonScript;
615 DebugEvent("After expanding env strings [%S]", regscript);
617 if(wcsstr(regscript, L"%s")) {
618 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
619 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
621 goto doneLogonScript;
622 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
624 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
626 goto doneLogonScript;
627 hr = StringCbCopyW(regexuscript, dwSize, regscript);
630 DebugEvent("After expanding username [%S]", regexuscript);
633 opt->logonScript = regexuscript;
635 LocalFree(regexuscript);
638 if(wuname) free(wuname);
639 if(regscript) free(regscript);
640 if(regexscript) free(regexscript);
643 DebugEvent0("Looking up TheseCells");
645 /* First find out where the key is */
650 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
651 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
653 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
655 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
656 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
658 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
660 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
661 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
663 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
669 CHAR * thesecells = NULL, *p;
671 /* dwSize still has the size of the required buffer in bytes. */
672 thesecells = malloc(dwSize*2);
677 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
678 if(rv != ERROR_SUCCESS) {/* what the ..? */
679 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
683 /* TheseCells is a REG_MULTI_SZ */
684 if ( thesecells && thesecells[0]) {
685 for ( p=thesecells; *p; p += (strlen(p) + 1)) {
686 DebugEvent("Found TheseCells [%s]", p);
688 opt->theseCells = thesecells;
691 DebugEvent("TheseCells [REG_MULTI_SZ] not found");
695 if (thesecells) free(thesecells);
698 DebugEvent0("Looking up Realm");
700 /* First find out where the key is */
705 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
706 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
708 DebugEvent("Located Realm in hkDom size %d", dwSize);
710 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
711 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
713 DebugEvent("Located Realm in hkDoms size %d", dwSize);
715 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
716 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
718 DebugEvent("Located Realm in hkNp size %d", dwSize);
726 /* dwSize still has the size of the required buffer in bytes. */
727 realm = malloc(dwSize*2);
732 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
733 if(rv != ERROR_SUCCESS) {/* what the ..? */
734 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
738 DebugEvent("Found Realm [%s]", realm);
743 if (realm) free(realm);
747 if(hkNp) RegCloseKey(hkNp);
748 if(hkDom) RegCloseKey(hkDom);
749 if(hkDoms) RegCloseKey(hkDoms);
750 if(hkParm) RegCloseKey(hkParm);
753 #undef LOOKUPKEYCHAIN
755 /* Try to find out which cell the given path is in. We must retain
756 the contents of *cell in case of failure. *cell is assumed to be
757 at least cellLen chars */
758 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
759 struct ViceIoctl blob;
760 char tcell[MAX_PATH];
764 blob.out_size = MAX_PATH;
767 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
770 strncpy(cell, tcell, cellLen);
771 cell[cellLen - 1] = '\0';
779 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
783 GetCPInfo(CP_ACP, &CodePageInfo);
785 if (CodePageInfo.MaxCharSize > 1)
786 // Only supporting non-Unicode strings
789 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
791 // Looks like unicode, better translate it
792 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
793 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
794 lpszOutputString, nOutStringLen-1, NULL, NULL);
795 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
799 lpszOutputString[0] = '\0';
801 } // UnicodeStringToANSI
803 DWORD APIENTRY NPLogonNotify(
805 LPCWSTR lpAuthentInfoType,
806 LPVOID lpAuthentInfo,
807 LPCWSTR lpPreviousAuthentInfoType,
808 LPVOID lpPreviousAuthentInfo,
809 LPWSTR lpStationName,
810 LPVOID StationHandle,
811 LPWSTR *lpLogonScript)
813 char uname[MAX_USERNAME_LENGTH]="";
814 char password[MAX_PASSWORD_LENGTH]="";
815 char logonDomain[MAX_DOMAIN_LENGTH]="";
816 char cell[256]="<non-integrated logon>";
817 char homePath[MAX_PATH]="";
818 char szLogonId[128] = "";
820 MSV1_0_INTERACTIVE_LOGON *IL;
822 DWORD code = 0, code2;
830 DWORD LSPtype, LSPsize;
833 HWND hwndOwner = (HWND)StationHandle;
835 BOOLEAN afsWillAutoStart;
837 BOOLEAN lowercased_name = TRUE;
839 LogonOptions_t opt; /* domain specific logon options */
843 /* Are we interactive? */
844 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
846 #ifdef DISABLE_NON_INTERACTIVE
847 /* Do not do anything if the logon session is not interactive. */
852 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
853 0, KEY_QUERY_VALUE, &NPKey);
854 LSPsize=sizeof(TraceOption);
855 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
856 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
860 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
862 /* Make sure the AFS Libraries are initialized */
865 /* Initialize Logon Script to none */
868 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
871 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
872 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
874 DebugEvent("Unsupported Authentication Info Type: %S",
879 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
881 /* Convert from Unicode to ANSI */
883 /*TODO: Use SecureZeroMemory to erase passwords */
884 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
885 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
886 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
889 /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
890 ctemp = strchr(uname, '@');
894 if ( logonDomain[0] == '\0' )
895 StringCchCopy(logonDomain, MAX_DOMAIN_LENGTH, ctemp);
898 /* is the name all lowercase? */
899 for ( ctemp = uname; *ctemp ; ctemp++) {
900 if ( !islower(*ctemp) ) {
901 lowercased_name = FALSE;
910 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
911 retryInterval = opt.retryInterval;
912 sleepInterval = opt.sleepInterval;
913 *lpLogonScript = opt.logonScript;
915 if (retryInterval < sleepInterval)
916 sleepInterval = retryInterval;
918 DebugEvent("Got logon script: [%S]", opt.logonScript);
920 afsWillAutoStart = AFSWillAutoStart();
922 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
923 opt.LogonOption,afsWillAutoStart);
925 /* Check for zero length password if integrated logon*/
926 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
927 if ( password[0] == 0 ) {
928 DebugEvent0("Password is the empty string");
930 reason = "zero length password is illegal";
934 /* Get cell name if doing integrated logon.
935 We might overwrite this if we are logging into an AD realm and we find out that
936 the user's home dir is in some other cell. */
937 DebugEvent("About to call cm_GetRootCellName()");
938 code = cm_GetRootCellName(cell);
940 DebugEvent0("Unable to obtain Root Cell");
942 reason = "unknown cell";
945 DebugEvent("Default cell is %s", cell);
948 /* We get the user's home directory path, if applicable, though we can't lookup the
949 cell right away because the client service may not have started yet. This call
950 also sets the AD_REALM flag in opt.flags if applicable. */
951 if (ISREMOTE(opt.flags)) {
952 DebugEvent0("Is Remote");
953 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
957 /* loop until AFS is started. */
958 if (afsWillAutoStart) {
960 * If the service is configured for auto start but hasn't started yet,
963 if (!(IsServiceRunning() || IsServiceStartPending()))
966 while ( IsServiceStartPending() ) {
970 while (IsServiceRunning()) {
971 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
972 opt.LogonOption,afsWillAutoStart);
974 if (ISADREALM(opt.flags)) {
975 code = GetFileCellName(homePath,cell,256);
977 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
979 /* Don't bail out if GetFileCellName failed.
980 * The home dir may not be in AFS after all.
985 /* if Integrated Logon */
986 if (ISLOGONINTEGRATED(opt.LogonOption))
988 if ( KFW_is_available() ) {
989 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
991 char * principal, *p;
994 StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
996 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
999 /* tlen is now the length of uname in characters */
1000 principal = (char *)malloc(len * sizeof(char));
1002 StringCchCopy(principal, len, uname);
1003 p = principal + tlen;
1005 StringCchCopy(p, len - tlen -1, opt.realm);
1006 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
1007 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1008 principal,opt.smbName,cell,code);
1012 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
1013 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1014 uname,opt.smbName,cell,code);
1016 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1017 if (code == 0 && opt.theseCells) {
1018 char * principal, *p;
1021 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
1023 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
1026 /* tlen is now the length of uname in characters */
1027 principal = (char *)malloc(len * sizeof(char));
1029 StringCchCopy(principal, len, uname);
1030 p = principal + tlen;
1033 StringCchCopy(p, len - tlen -1, opt.realm);
1035 StringCchCopy(p, len - tlen - 1, cell);
1042 if ( cm_stricmp_utf8(p, cell) ) {
1043 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1044 code2 = KFW_AFS_get_cred(principal, p, password, 0, opt.smbName, &reason);
1045 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1046 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1047 principal,opt.smbName,p,code2);
1055 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
1056 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
1058 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1059 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
1061 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
1062 for ( ctemp = uname; *ctemp ; ctemp++) {
1063 *ctemp = tolower(*ctemp);
1065 lowercased_name = TRUE;
1069 /* is service started yet?*/
1071 /* If we've failed because the client isn't running yet and the
1072 * client is set to autostart (and therefore it makes sense for
1073 * us to wait for it to start) then sleep a while and try again.
1074 * If the error was something else, then give up. */
1075 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1079 /*JUST check to see if its running*/
1080 if (IsServiceRunning())
1082 if (!IsServiceStartPending()) {
1084 reason = "AFS Service start failed";
1089 /* If the retry interval has expired and we still aren't
1090 * logged in, then just give up if we are not in interactive
1091 * mode or the failSilently flag is set, otherwise let the
1092 * user know we failed and give them a chance to try again. */
1093 if (retryInterval <= 0) {
1094 reason = "AFS not running";
1095 if (!interactive || opt.failSilently)
1097 flag = MessageBox(hwndOwner,
1098 "AFS is still starting. Retry?",
1100 MB_ICONQUESTION | MB_RETRYCANCEL);
1101 if (flag == IDCANCEL)
1104 /* Wait just a little while and try again */
1105 retryInterval = opt.retryInterval;
1109 Sleep(sleepInterval * 1000);
1110 retryInterval -= sleepInterval;
1113 DebugEvent0("while loop exited");
1115 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1119 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1121 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1122 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1124 KFW_AFS_destroy_tickets_for_principal(uname);
1132 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1134 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1135 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1137 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1139 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1141 DeregisterEventSource(h);
1143 code = MapAuthError(code);
1146 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1149 LocalFree(*lpLogonScript);
1150 *lpLogonScript = NULL;
1151 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1156 if (opt.theseCells) free(opt.theseCells);
1157 if (opt.smbName) free(opt.smbName);
1158 if (opt.realm) free(opt.realm);
1160 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1164 DWORD APIENTRY NPPasswordChangeNotify(
1165 LPCWSTR lpAuthentInfoType,
1166 LPVOID lpAuthentInfo,
1167 LPCWSTR lpPreviousAuthentInfoType,
1168 LPVOID lpPreviousAuthentInfo,
1169 LPWSTR lpStationName,
1170 LPVOID StationHandle,
1173 BOOLEAN interactive;
1175 /* Are we interactive? */
1176 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1178 /* Do not do anything if the logon session is not interactive. */
1182 /* Make sure the AFS Libraries are initialized */
1185 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1189 #include <userenv.h>
1191 #include <afs/vice.h>
1192 #include <afs/fs_utils.h>
1194 BOOL IsPathInAfs(const CHAR *strPath)
1197 struct ViceIoctl blob;
1201 blob.out_size = 2048;
1204 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1211 typedef struct _WLX_NOTIFICATION_INFO {
1216 PWSTR WindowStation;
1219 PFNMSGECALLBACK pStatusCallback;
1220 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1223 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1225 DWORD LSPtype, LSPsize;
1228 /* Make sure the AFS Libraries are initialized */
1231 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1232 0, KEY_QUERY_VALUE, &NPKey);
1233 LSPsize=sizeof(TraceOption);
1234 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1235 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1237 RegCloseKey (NPKey);
1238 DebugEvent0("AFS_Startup_Event");
1241 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1244 TCHAR profileDir[1024] = TEXT("");
1246 PTOKEN_USER tokenUser = NULL;
1248 DWORD LSPtype, LSPsize;
1250 DWORD LogoffPreserveTokens = 0;
1253 /* Make sure the AFS Libraries are initialized */
1256 DebugEvent0("AFS_Logoff_Event - Start");
1258 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1259 0, KEY_QUERY_VALUE, &NPKey);
1260 LSPsize=sizeof(LogoffPreserveTokens);
1261 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1262 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1263 RegCloseKey (NPKey);
1265 if (!LogoffPreserveTokens) {
1266 memset(&opt, 0, sizeof(LogonOptions_t));
1268 if (pInfo->UserName && pInfo->Domain) {
1269 char username[MAX_USERNAME_LENGTH] = "";
1270 char domain[MAX_DOMAIN_LENGTH] = "";
1273 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1274 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1275 username, sizeof(username), NULL, NULL);
1277 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1278 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1279 domain, sizeof(domain), NULL, NULL);
1281 GetDomainLogonOptions(NULL, username, domain, &opt);
1284 if (ISREMOTE(opt.flags)) {
1285 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1287 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1288 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1290 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1292 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1297 /* We can't use pInfo->Domain for the domain since in the cross realm case
1298 * this is source domain and not the destination domain.
1300 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1301 WCHAR Domain[64]=L"";
1302 GetLocalShortDomain(Domain, sizeof(Domain));
1303 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1304 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1305 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1309 if (strlen(profileDir)) {
1310 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1311 if (!IsPathInAfs(profileDir)) {
1312 if (code = ktc_ForgetAllTokens())
1313 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1315 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1317 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1320 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1324 LocalFree(tokenUser);
1326 DebugEvent0("AFS_Logoff_Event - Local Logon");
1327 if (code = ktc_ForgetAllTokens())
1328 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1330 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1333 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1336 DebugEvent0("AFS_Logoff_Event - End");
1339 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1341 TCHAR profileDir[1024] = TEXT("");
1343 PTOKEN_USER tokenUser = NULL;
1345 WCHAR szUserW[128] = L"";
1346 char szUserA[128] = "";
1347 char szClient[MAX_PATH];
1348 char szPath[MAX_PATH] = "";
1354 /* Make sure the AFS Libraries are initialized */
1357 DebugEvent0("AFS_Logon_Event - Start");
1359 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1361 memset(&opt, 0, sizeof(LogonOptions_t));
1363 if (pInfo->UserName && pInfo->Domain) {
1364 char username[MAX_USERNAME_LENGTH] = "";
1365 char domain[MAX_DOMAIN_LENGTH] = "";
1368 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1370 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1371 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1372 username, sizeof(username), NULL, NULL);
1374 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1375 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1376 domain, sizeof(domain), NULL, NULL);
1378 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1379 GetDomainLogonOptions(NULL, username, domain, &opt);
1381 if (!pInfo->UserName)
1382 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1384 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1387 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1388 opt.LogonOption, opt.flags);
1390 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1391 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1392 goto done_logon_event;
1395 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1397 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1399 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1400 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1402 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1404 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1409 /* We can't use pInfo->Domain for the domain since in the cross realm case
1410 * this is source domain and not the destination domain.
1412 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1413 WCHAR Domain[64]=L"";
1414 GetLocalShortDomain(Domain, sizeof(Domain));
1415 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1416 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1417 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1421 if (strlen(profileDir)) {
1422 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1424 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1428 dwSize = sizeof(szUserA);
1429 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1430 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1431 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1436 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1437 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1439 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1441 memset (&nr, 0x00, sizeof(NETRESOURCE));
1442 nr.dwType=RESOURCETYPE_DISK;
1444 nr.lpRemoteName=szPath;
1445 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1447 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1448 szPath, szUserA,res);
1450 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1452 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1455 LocalFree(tokenUser);
1457 DebugEvent0("AFS_Logon_Event - End");
1461 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1463 NTSTATUS Status = 0;
1464 TOKEN_STATISTICS Stats;
1470 *ppSessionData = NULL;
1472 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1476 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1477 if ( FAILED(Status) || !ppSessionData )
1483 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1486 WCHAR szUserW[128] = L"";
1487 char szUserA[128] = "";
1488 char szPath[MAX_PATH] = "";
1489 char szLogonId[128] = "";
1491 char filename[MAX_PATH] = "";
1492 char newfilename[MAX_PATH] = "";
1493 char commandline[MAX_PATH+256] = "";
1494 STARTUPINFO startupinfo;
1495 PROCESS_INFORMATION procinfo;
1496 HANDLE hf = INVALID_HANDLE_VALUE;
1498 LUID LogonId = {0, 0};
1499 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1501 HKEY hKey1 = NULL, hKey2 = NULL;
1503 /* Make sure the KFW Libraries are initialized */
1506 DebugEvent0("KFW_Logon_Event - Start");
1508 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1510 if ( pLogonSessionData ) {
1511 LogonId = pLogonSessionData->LogonId;
1512 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1514 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1515 LsaFreeReturnBuffer( pLogonSessionData );
1517 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1521 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1522 if ( count > sizeof(filename) || count == 0 ) {
1523 GetWindowsDirectory(filename, sizeof(filename));
1526 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1527 if ( count > sizeof(filename) || count == 0 ) {
1528 GetWindowsDirectory(filename, sizeof(filename));
1531 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1532 DebugEvent0("KFW_Logon_Event - filename too long");
1536 strcat(filename, "\\");
1537 strcat(filename, szLogonId);
1539 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1540 FILE_ATTRIBUTE_NORMAL, NULL);
1541 if (hf == INVALID_HANDLE_VALUE) {
1542 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1547 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1548 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1549 DeleteFile(filename);
1553 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1554 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1558 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1559 DebugEvent0("KFW_Logon_Event - new filename too long");
1563 strcat(newfilename, "\\");
1564 strcat(newfilename, szLogonId);
1566 if (!MoveFileEx(filename, newfilename,
1567 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1568 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1572 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1574 GetStartupInfo(&startupinfo);
1575 if (CreateProcessAsUser( pInfo->hToken,
1581 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1587 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1589 WaitForSingleObject(procinfo.hProcess, 30000);
1591 CloseHandle(procinfo.hThread);
1592 CloseHandle(procinfo.hProcess);
1594 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1597 DeleteFile(filename);
1599 DebugEvent0("KFW_Logon_Event - End");