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>
16 #include <sys/types.h>
21 #define SECURITY_WIN32
30 #include <afs/pioctl_nt.h>
31 #include <afs/kautils.h>
34 #include "cm_config.h"
37 #include "lanahelper.h"
39 /* Allocated in Windows Driver Kit */
40 #ifndef WNNC_NET_OPENAFS
41 #define WNNC_NET_OPENAFS 0x00390000
44 #include <WINNT\afsreg.h>
46 DWORD TraceOption = 0;
51 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
53 void DebugEvent0(char *a)
55 HANDLE h; char *ptbuf[1];
57 if (!Debug && !ISLOGONTRACE(TraceOption))
60 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
61 if (h != INVALID_HANDLE_VALUE) {
63 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
64 DeregisterEventSource(h);
69 void DebugEvent(char *b,...)
71 HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
74 if (!Debug && !ISLOGONTRACE(TraceOption))
77 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
78 if (h != INVALID_HANDLE_VALUE) {
80 StringCbVPrintf(buf, MAXBUF_+1,b,marker);
83 ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
84 DeregisterEventSource(h);
89 static HANDLE hInitMutex = NULL;
90 static BOOL bInit = FALSE;
92 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
98 case DLL_PROCESS_ATTACH:
99 /* Initialization Mutex */
101 hInitMutex = CreateMutex(NULL, FALSE, NULL);
103 WSAStartup( MAKEWORD(2,2), &wsaData );
106 case DLL_PROCESS_DETACH:
108 CloseHandle(hInitMutex);
113 case DLL_THREAD_ATTACH:
114 case DLL_THREAD_DETACH:
116 /* Everything else succeeds but does nothing. */
123 void AfsLogonInit(void)
125 if ( bInit == FALSE ) {
126 if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
127 /* initAFSDirPath() initializes an array and sets a
128 * flag so that the initialization can only occur
129 * once. No cleanup will be done when the DLL is
130 * unloaded so the initialization will not be
131 * performed again on a subsequent reload
135 /* ka_Init initializes a number of error tables.
136 * and then calls ka_CellConfig() which grabs
137 * an afsconf_dir structure via afsconf_Open().
138 * Upon a second attempt to call ka_CellConfig()
139 * the structure will be released with afsconf_Close()
140 * and then re-opened. Could this corrupt memory?
142 * We only need this if we are not using KFW.
144 if (!KFW_is_available())
148 ReleaseMutex(hInitMutex);
152 CHAR *GenRandomName(CHAR *pbuf)
155 srand( (unsigned)time( NULL ) );
156 for (i=0;i<MAXRANDOMNAMELEN-1;i++)
157 pbuf[i]='a'+(rand() % 26);
158 pbuf[MAXRANDOMNAMELEN-1]=0;
162 BOOLEAN AFSWillAutoStart(void)
167 BOOLEAN result = FALSE;
168 LPQUERY_SERVICE_CONFIG pConfig = NULL;
172 /* Open services manager */
173 scm = OpenSCManager(NULL, NULL, GENERIC_READ);
174 if (!scm) return FALSE;
176 /* Open AFSD service */
177 svc = OpenService(scm, "TransarcAFSDaemon", SERVICE_QUERY_CONFIG);
181 /* Query AFSD service config, first just to get buffer size */
182 /* Expected to fail, so don't test return value */
183 (void) QueryServiceConfig(svc, NULL, 0, &BufSize);
184 status = GetLastError();
185 if (status != ERROR_INSUFFICIENT_BUFFER)
188 /* Allocate buffer */
189 pConfig = (LPQUERY_SERVICE_CONFIG)GlobalAlloc(GMEM_FIXED,BufSize);
193 /* Query AFSD service config, this time for real */
194 flag = QueryServiceConfig(svc, pConfig, BufSize, &BufSize);
198 /* Is it autostart? */
199 if (pConfig->dwStartType < SERVICE_DEMAND_START)
205 CloseServiceHandle(svc);
207 CloseServiceHandle(scm);
212 DWORD MapAuthError(DWORD code)
215 /* Unfortunately, returning WN_NO_NETWORK results in the MPR abandoning
216 * logon scripts for all credential managers, although they will still
217 * receive logon notifications. Since we don't want this, we return
218 * WN_SUCCESS. This is highly undesirable, but we also don't want to
219 * break other network providers.
223 return WN_NO_NETWORK; */
224 default: return WN_SUCCESS;
228 DWORD APIENTRY NPGetCaps(DWORD index)
233 * The purpose of this response is to let the system
234 * know which file system the network provider is associated with
235 * Microsoft issues these values starting from 1 with the exception
236 * of WNNC_CRED_MANAGER which is 0xFFFF. The provider type is
237 * stored in the hiword. Pick a value that is unused.
241 case WNNC_SPEC_VERSION:
242 return WNNC_SPEC_VERSION51;
245 /* Say we are already started, even though we might wait after we receive NPLogonNotify */
254 NetUserGetProfilePath( LPCWSTR Domain, LPCWSTR UserName, char * profilePath,
255 DWORD profilePathLen )
258 LPWSTR ServerName = NULL;
259 LPUSER_INFO_3 p3 = NULL;
261 NetGetAnyDCName(NULL, Domain, (LPBYTE *)&ServerName);
262 /* if NetGetAnyDCName fails, ServerName == NULL
263 * NetUserGetInfo will obtain local user information
265 code = NetUserGetInfo(ServerName, UserName, 3, (LPBYTE *)&p3);
266 if (code == NERR_Success)
268 code = NERR_UserNotFound;
270 if (p3->usri3_profile) {
271 DWORD len = lstrlenW(p3->usri3_profile);
273 /* Convert From Unicode to ANSI (UTF-8 for future) */
274 len = len < profilePathLen ? len : profilePathLen - 1;
275 WideCharToMultiByte(CP_UTF8, 0, p3->usri3_profile, len, profilePath, len, NULL, NULL);
276 profilePath[len] = '\0';
280 NetApiBufferFree(p3);
284 NetApiBufferFree(ServerName);
288 BOOL IsServiceRunning (void)
290 SERVICE_STATUS Status;
292 memset (&Status, 0x00, sizeof(Status));
293 Status.dwCurrentState = SERVICE_STOPPED;
295 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
298 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
300 QueryServiceStatus (hService, &Status);
301 CloseServiceHandle (hService);
304 CloseServiceHandle (hManager);
306 DebugEvent("AFS AfsLogon - Test Service Running Return Code[%x] ?Running[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_RUNNING));
307 return (Status.dwCurrentState == SERVICE_RUNNING);
310 BOOL IsServiceStartPending (void)
312 SERVICE_STATUS Status;
314 memset (&Status, 0x00, sizeof(Status));
315 Status.dwCurrentState = SERVICE_STOPPED;
317 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
320 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
322 QueryServiceStatus (hService, &Status);
323 CloseServiceHandle (hService);
326 CloseServiceHandle (hManager);
328 DebugEvent("AFS AfsLogon - Test Service Start Pending Return Code[%x] ?Start Pending[%d]",Status.dwCurrentState,(Status.dwCurrentState == SERVICE_START_PENDING));
329 return (Status.dwCurrentState == SERVICE_START_PENDING);
332 BOOL StartTheService (void)
337 if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ|SERVICE_START)) != NULL)
340 if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ|SERVICE_START)) != NULL)
342 StartService (hService, 0, NULL);
343 gle = GetLastError();
344 CloseServiceHandle (hService);
346 gle = GetLastError();
348 CloseServiceHandle (hManager);
350 DebugEvent("AFS AfsLogon - Service Start Return Code[0x%x]",gle);
354 /* LOOKUPKEYCHAIN: macro to look up the value in the list of keys in order until it's found
355 v:variable to receive value (reference type)
357 d:default, in case the value isn't on any of the keys
359 #define LOOKUPKEYCHAIN(v,t,d,n) \
361 rv = ~ERROR_SUCCESS; \
364 dwSize = sizeof(v); \
365 rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
366 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
367 DebugEvent(#v " found in hkDom with type [%d]", dwType); \
369 if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
370 dwSize = sizeof(v); \
371 rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
372 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
373 DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
375 if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
376 dwSize = sizeof(v); \
377 rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
378 if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
379 DebugEvent(#v " found in hkNp with type [%d]", dwType); \
381 if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
383 DebugEvent0(#v " being set to default"); \
387 /* Get domain specific configuration info. We are returning void because if anything goes wrong
388 we just return defaults.
391 GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOptions_t *opt ) {
392 HKEY hkParm = NULL; /* Service parameter */
393 HKEY hkNp = NULL; /* network provider key */
394 HKEY hkDoms = NULL; /* domains key */
395 HKEY hkDom = NULL; /* DOMAINS/domain key */
401 char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
402 char *effDomain = NULL;
404 memset(opt, 0, sizeof(LogonOptions_t));
406 DebugEvent("In GetDomainLogonOptions for user [%s] in domain [%s]", username, domain);
407 /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
408 opt->flags = LOGON_FLAG_REMOTE;
410 dwSize = MAX_COMPUTERNAME_LENGTH + 1;
411 if(GetComputerName(computerName, &dwSize)) {
412 if(!cm_stricmp_utf8(computerName, domain)) {
413 effDomain = "LOCALHOST";
414 opt->flags = LOGON_FLAG_LOCAL;
417 if (effDomain == NULL)
421 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
422 if(rv != ERROR_SUCCESS) {
424 DebugEvent("GetDomainLogonOption: Can't open parms key [%d]", rv);
427 rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY, 0, KEY_READ, &hkNp );
428 if(rv != ERROR_SUCCESS) {
430 DebugEvent("GetDomainLogonOptions: Can't open NP key [%d]", rv);
434 rv = RegOpenKeyEx( hkNp, REG_CLIENT_DOMAINS_SUBKEY, 0, KEY_READ, &hkDoms );
435 if( rv != ERROR_SUCCESS ) {
437 DebugEvent("GetDomainLogonOptions: Can't open Domains key [%d]", rv);
441 if(hkDoms && effDomain) {
442 rv = RegOpenKeyEx( hkDoms, effDomain, 0, KEY_READ, &hkDom );
443 if( rv != ERROR_SUCCESS ) {
445 DebugEvent("GetDomainLogonOptions: Can't open domain key for [%s] [%d]", effDomain, rv);
446 /* If none of the domains match, we shouldn't use the domain key either */
451 DebugEvent0("Not opening domain key");
453 /* Each individual can either be specified on the domain key, the domains key or in the
454 net provider key. They fail over in that order. If none is found, we just use the
458 LOOKUPKEYCHAIN(opt->LogonOption, REG_DWORD, DEFAULT_LOGON_OPTION, REG_CLIENT_LOGON_OPTION_PARM);
460 /* FailLoginsSilently */
461 dwSize = sizeof(dwDummy);
462 rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
463 if (rv != ERROR_SUCCESS)
464 LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
465 opt->failSilently = dwDummy ? 1 :0;
468 LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
471 LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
473 if(!ISLOGONINTEGRATED(opt->LogonOption)) {
474 DebugEvent0("Integrated logon disabled");
475 goto cleanup; /* no need to lookup the logon script */
478 /* come up with SMB username */
480 /* username and domain for logon session is not necessarily the same as
481 username and domain passed into network provider. */
482 PSECURITY_LOGON_SESSION_DATA plsd=NULL;
483 char lsaUsername[MAX_USERNAME_LENGTH]="";
484 char lsaDomain[MAX_DOMAIN_LENGTH]="";
488 Status = LsaGetLogonSessionData(lpLogonId, &plsd);
489 if ( FAILED(Status) || plsd == NULL ) {
490 DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
494 if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
497 if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
500 DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
502 if(SUCCEEDED(StringCbLength(lsaUsername, MAX_USERNAME_LENGTH, &tlen)))
507 if(SUCCEEDED(StringCbLength(lsaDomain, MAX_DOMAIN_LENGTH, &tlen)))
514 opt->smbName = malloc(len);
515 if (opt->smbName == NULL)
518 StringCbCopy(opt->smbName, len, lsaDomain);
519 StringCbCat(opt->smbName, len, "\\");
520 StringCbCat(opt->smbName, len, lsaUsername);
522 strlwr(opt->smbName);
526 LsaFreeReturnBuffer(plsd);
528 if (opt->smbName == NULL) {
531 DebugEvent("Constructing username using [%s] and [%s]",
534 len = strlen(username) + strlen(domain) + 2;
536 opt->smbName = malloc(len);
537 if (opt->smbName == NULL)
540 StringCbCopy(opt->smbName, len, domain);
541 StringCbCat(opt->smbName, len, "\\");
542 StringCbCat(opt->smbName, len, username);
544 strlwr(opt->smbName);
547 DebugEvent0("Looking up logon script");
549 /* First find out where the key is */
554 rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
555 if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
557 DebugEvent0("Located logon script in hkDom");
560 rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
561 if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
563 DebugEvent0("Located logon script in hkDoms");
565 /* Note that the LogonScript in the NP key not used. */
569 WCHAR *regscript = NULL;
570 WCHAR *regexscript = NULL;
571 WCHAR *regexuscript = NULL;
572 WCHAR *wuname = NULL;
577 StringCbLength(opt->smbName, MAX_USERNAME_LENGTH, &len);
580 wuname = malloc(len * sizeof(WCHAR));
582 goto doneLogonScript;
583 MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
585 DebugEvent("Username is set for [%S]", wuname);
587 /* dwSize still has the size of the required buffer in bytes. */
588 regscript = malloc(dwSize);
590 goto doneLogonScript;
591 rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
592 if(rv != ERROR_SUCCESS) {/* what the ..? */
593 DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
594 goto doneLogonScript;
597 DebugEvent("Found logon script [%S]", regscript);
599 if(dwType == REG_EXPAND_SZ) {
602 dwSize += MAX_PATH * sizeof(WCHAR); /* make room for environment expansion. */
603 regexscript = malloc(dwSize);
605 goto doneLogonScript;
606 dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
608 regscript = regexscript;
610 if(dwReq > (dwSize / sizeof(WCHAR))) {
611 DebugEvent0("Overflow while expanding environment strings.");
612 goto doneLogonScript;
616 DebugEvent("After expanding env strings [%S]", regscript);
618 if(wcsstr(regscript, L"%s")) {
619 dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
620 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
622 goto doneLogonScript;
623 hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
625 regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
627 goto doneLogonScript;
628 hr = StringCbCopyW(regexuscript, dwSize, regscript);
631 DebugEvent("After expanding username [%S]", regexuscript);
634 opt->logonScript = regexuscript;
636 LocalFree(regexuscript);
639 if(wuname) free(wuname);
640 if(regscript) free(regscript);
641 if(regexscript) free(regexscript);
644 DebugEvent0("Looking up TheseCells");
646 /* First find out where the key is */
651 rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
652 if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
654 DebugEvent("Located TheseCells in hkDom size %d", dwSize);
656 rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
657 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
659 DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
661 rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
662 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
664 DebugEvent("Located TheseCells in hkNp size %d", dwSize);
670 CHAR * thesecells = NULL, *p;
672 /* dwSize still has the size of the required buffer in bytes. */
673 thesecells = malloc(dwSize*2);
678 rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
679 if(rv != ERROR_SUCCESS) {/* what the ..? */
680 DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
684 /* TheseCells is a REG_MULTI_SZ */
685 if ( thesecells && thesecells[0]) {
686 for ( p=thesecells; *p; p += (strlen(p) + 1)) {
687 DebugEvent("Found TheseCells [%s]", p);
689 opt->theseCells = thesecells;
692 DebugEvent("TheseCells [REG_MULTI_SZ] not found");
696 if (thesecells) free(thesecells);
699 DebugEvent0("Looking up Realm");
701 /* First find out where the key is */
706 rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
707 if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
709 DebugEvent("Located Realm in hkDom size %d", dwSize);
711 rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
712 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
714 DebugEvent("Located Realm in hkDoms size %d", dwSize);
716 rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
717 if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
719 DebugEvent("Located Realm in hkNp size %d", dwSize);
727 /* dwSize still has the size of the required buffer in bytes. */
728 realm = malloc(dwSize*2);
733 rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
734 if(rv != ERROR_SUCCESS) {/* what the ..? */
735 DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
739 DebugEvent("Found Realm [%s]", realm);
744 if (realm) free(realm);
748 if(hkNp) RegCloseKey(hkNp);
749 if(hkDom) RegCloseKey(hkDom);
750 if(hkDoms) RegCloseKey(hkDoms);
751 if(hkParm) RegCloseKey(hkParm);
754 #undef LOOKUPKEYCHAIN
756 /* Try to find out which cell the given path is in. We must retain
757 the contents of *cell in case of failure. *cell is assumed to be
758 at least cellLen chars */
759 DWORD GetFileCellName(char * path, char * cell, size_t cellLen) {
760 struct ViceIoctl blob;
761 char tcell[MAX_PATH];
765 blob.out_size = MAX_PATH;
768 code = pioctl(path, VIOC_FILE_CELL_NAME, &blob, 1);
771 strncpy(cell, tcell, cellLen);
772 cell[cellLen - 1] = '\0';
780 UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOutStringLen)
784 GetCPInfo(CP_ACP, &CodePageInfo);
786 if (CodePageInfo.MaxCharSize > 1)
787 // Only supporting non-Unicode strings
790 if (uInputString.Buffer && ((LPBYTE) uInputString.Buffer)[1] == '\0')
792 // Looks like unicode, better translate it
793 // UNICODE_STRING specifies the length of the buffer string in Bytes not WCHARS
794 WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) uInputString.Buffer, uInputString.Length/2,
795 lpszOutputString, nOutStringLen-1, NULL, NULL);
796 lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
800 lpszOutputString[0] = '\0';
802 } // UnicodeStringToANSI
807 LPCWSTR lpAuthentInfoType,
808 LPVOID lpAuthentInfo,
809 LPCWSTR lpPreviousAuthentInfoType,
810 LPVOID lpPreviousAuthentInfo,
811 LPWSTR lpStationName,
812 LPVOID StationHandle,
813 LPWSTR *lpLogonScript)
815 char uname[MAX_USERNAME_LENGTH]="";
816 char password[MAX_PASSWORD_LENGTH]="";
817 char logonDomain[MAX_DOMAIN_LENGTH]="";
818 char cell[256]="<non-integrated logon>";
819 char homePath[MAX_PATH]="";
820 char szLogonId[128] = "";
822 MSV1_0_INTERACTIVE_LOGON *IL;
824 DWORD code = 0, code2;
832 DWORD LSPtype, LSPsize;
835 HWND hwndOwner = (HWND)StationHandle;
837 BOOLEAN afsWillAutoStart;
839 BOOLEAN lowercased_name = TRUE;
841 LogonOptions_t opt; /* domain specific logon options */
845 CtxtHandle LogonContext;
847 /* Are we interactive? */
848 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
850 #ifdef DISABLE_NON_INTERACTIVE
851 /* Do not do anything if the logon session is not interactive. */
856 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
857 0, KEY_QUERY_VALUE, &NPKey);
858 LSPsize=sizeof(TraceOption);
859 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
860 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
864 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PROVIDER_SUBKEY,
865 0, KEY_QUERY_VALUE, &NPKey);
866 LSPsize=sizeof(Debug);
867 RegQueryValueEx(NPKey, REG_CLIENT_DEBUG_PARM, NULL,
868 &LSPtype, (LPBYTE)&Debug, &LSPsize);
872 DebugEvent("NPLogonNotify - LoginId(%d,%d)", lpLogonId->HighPart, lpLogonId->LowPart);
874 /* Make sure the AFS Libraries are initialized */
877 /* Initialize Logon Script to none */
880 /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
883 if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") &&
884 wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
886 DebugEvent("Unsupported Authentication Info Type: %S",
891 IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
893 /* Convert from Unicode to ANSI */
895 /*TODO: Use SecureZeroMemory to erase passwords */
896 if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
897 !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
898 !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
901 /* Make sure AD-DOMAINS sent from login that is sent to us is stripped */
902 ctemp = strchr(uname, '@');
906 if ( logonDomain[0] == '\0' )
907 StringCchCopy(logonDomain, MAX_DOMAIN_LENGTH, ctemp);
910 /* is the name all lowercase? */
911 for ( ctemp = uname; *ctemp ; ctemp++) {
912 if ( !islower(*ctemp) ) {
913 lowercased_name = FALSE;
922 GetDomainLogonOptions( lpLogonId, uname, logonDomain, &opt );
923 retryInterval = opt.retryInterval;
924 sleepInterval = opt.sleepInterval;
925 *lpLogonScript = opt.logonScript;
927 if (retryInterval < sleepInterval)
928 sleepInterval = retryInterval;
930 DebugEvent("Got logon script: [%S]", opt.logonScript);
932 afsWillAutoStart = AFSWillAutoStart();
934 DebugEvent("LogonOption[%x], Service AutoStart[%d]",
935 opt.LogonOption,afsWillAutoStart);
937 /* Check for zero length password if integrated logon*/
938 if ( ISLOGONINTEGRATED(opt.LogonOption) ) {
939 if ( password[0] == 0 ) {
940 DebugEvent0("Password is the empty string");
942 reason = "zero length password is illegal";
946 /* Get cell name if doing integrated logon.
947 We might overwrite this if we are logging into an AD realm and we find out that
948 the user's home dir is in some other cell. */
949 DebugEvent0("About to call cm_GetRootCellName()");
950 code = cm_GetRootCellName(cell);
952 DebugEvent0("Unable to obtain Root Cell");
954 reason = "unknown cell";
956 DebugEvent("Default cell is %s", cell);
960 /* We get the user's home directory path, if applicable, though we can't lookup the
961 cell right away because the client service may not have started yet. This call
962 also sets the AD_REALM flag in opt.flags if applicable. */
963 if (ISREMOTE(opt.flags)) {
964 DebugEvent0("Is Remote");
965 GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
969 AFSCreatePAG(lpLogonId);
971 if (afsWillAutoStart) {
973 * If the service is configured for auto start but hasn't started yet,
976 if (!(IsServiceRunning() || IsServiceStartPending()))
979 /* loop until AFS is started or fails. */
980 while ( IsServiceStartPending() ) {
984 while (IsServiceRunning() && code != KTC_NOCM && code != KTC_NOCMRPC && code != KTC_NOCELL) {
985 DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
986 opt.LogonOption,afsWillAutoStart);
988 if (ISADREALM(opt.flags)) {
989 code = GetFileCellName(homePath,cell,256);
991 DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
993 /* Don't bail out if GetFileCellName failed.
994 * The home dir may not be in AFS after all.
999 /* if Integrated Logon */
1000 if (ISLOGONINTEGRATED(opt.LogonOption))
1002 LogonSSP(lpLogonId, &LogonContext);
1003 ImpersonateSecurityContext(&LogonContext);
1005 if ( KFW_is_available() ) {
1006 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1008 char * principal, *p;
1011 StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
1013 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
1016 /* tlen is now the length of uname in characters */
1017 principal = (char *)malloc(len * sizeof(char));
1019 StringCchCopy(principal, len, uname);
1020 p = principal + tlen;
1022 StringCchCopy(p, len - tlen -1, opt.realm);
1023 code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
1024 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1025 principal,opt.smbName,cell,code);
1029 code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
1030 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1031 uname,opt.smbName,cell,code);
1033 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1034 if (code == 0 && opt.theseCells) {
1035 char * principal, *p;
1038 StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
1040 StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
1043 /* tlen is now the length of uname in characters */
1044 principal = (char *)malloc(len * sizeof(char));
1046 StringCchCopy(principal, len, uname);
1047 p = principal + tlen;
1050 StringCchCopy(p, len - tlen -1, opt.realm);
1052 StringCchCopy(p, len - tlen - 1, cell);
1059 if ( cm_stricmp_utf8(p, cell) ) {
1060 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
1061 code2 = KFW_AFS_get_cred(principal, p, password, 0, opt.smbName, &reason);
1062 SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
1063 DebugEvent("KFW_AFS_get_cred uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
1064 principal,opt.smbName,p,code2);
1072 code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
1073 uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
1075 DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
1076 code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
1079 RevertSecurityContext(&LogonContext);
1080 DeleteSecurityContext(&LogonContext);
1082 if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
1083 for ( ctemp = uname; *ctemp ; ctemp++) {
1084 *ctemp = tolower(*ctemp);
1086 lowercased_name = TRUE;
1090 /* is service started yet?*/
1092 /* If we've failed because the client isn't running yet and the
1093 * client is set to autostart (and therefore it makes sense for
1094 * us to wait for it to start) then sleep a while and try again.
1095 * If the error was something else, then give up. */
1096 if (code != KTC_NOCM && code != KTC_NOCMRPC)
1100 /*JUST check to see if its running*/
1101 if (IsServiceRunning())
1103 if (!IsServiceStartPending()) {
1105 reason = "AFS Service start failed";
1110 /* If the retry interval has expired and we still aren't
1111 * logged in, then just give up if we are not in interactive
1112 * mode or the failSilently flag is set, otherwise let the
1113 * user know we failed and give them a chance to try again. */
1114 if (retryInterval <= 0) {
1115 reason = "AFS not running";
1116 if (!interactive || opt.failSilently)
1118 flag = MessageBox(hwndOwner,
1119 "AFS is still starting. Retry?",
1121 MB_ICONQUESTION | MB_RETRYCANCEL);
1122 if (flag == IDCANCEL)
1125 /* Wait just a little while and try again */
1126 retryInterval = opt.retryInterval;
1130 Sleep(sleepInterval * 1000);
1131 retryInterval -= sleepInterval;
1133 DebugEvent0("while loop exited");
1136 /* remove any kerberos 5 tickets currently held by the SYSTEM account
1140 if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
1142 sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
1143 KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
1145 KFW_AFS_destroy_tickets_for_principal(uname);
1153 StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
1155 if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
1156 MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
1158 h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
1160 ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
1162 DeregisterEventSource(h);
1164 code = MapAuthError(code);
1167 if (ISLOGONINTEGRATED(opt.LogonOption) && (code!=0))
1170 LocalFree(*lpLogonScript);
1171 *lpLogonScript = NULL;
1172 if (!afsWillAutoStart) // its not running, so if not autostart or integrated logon then just skip
1177 if (opt.theseCells) free(opt.theseCells);
1178 if (opt.smbName) free(opt.smbName);
1179 if (opt.realm) free(opt.realm);
1181 DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
1185 DWORD APIENTRY NPPasswordChangeNotify(
1186 LPCWSTR lpAuthentInfoType,
1187 LPVOID lpAuthentInfo,
1188 LPCWSTR lpPreviousAuthentInfoType,
1189 LPVOID lpPreviousAuthentInfo,
1190 LPWSTR lpStationName,
1191 LPVOID StationHandle,
1194 BOOLEAN interactive;
1196 /* Are we interactive? */
1197 interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
1199 /* Do not do anything if the logon session is not interactive. */
1203 /* Make sure the AFS Libraries are initialized */
1206 DebugEvent0("AFS AfsLogon - NPPasswordChangeNotify");
1210 #include <userenv.h>
1212 #include <afs/vice.h>
1213 #include <afs/fs_utils.h>
1215 BOOL IsPathInAfs(const CHAR *strPath)
1218 struct ViceIoctl blob;
1222 blob.out_size = 2048;
1225 code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1);
1232 typedef struct _WLX_NOTIFICATION_INFO {
1237 PWSTR WindowStation;
1240 PFNMSGECALLBACK pStatusCallback;
1241 } WLX_NOTIFICATION_INFO, *PWLX_NOTIFICATION_INFO;
1244 VOID AFS_Startup_Event( PWLX_NOTIFICATION_INFO pInfo )
1246 DWORD LSPtype, LSPsize;
1249 /* Make sure the AFS Libraries are initialized */
1252 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1253 0, KEY_QUERY_VALUE, &NPKey);
1254 LSPsize=sizeof(TraceOption);
1255 RegQueryValueEx(NPKey, REG_CLIENT_TRACE_OPTION_PARM, NULL,
1256 &LSPtype, (LPBYTE)&TraceOption, &LSPsize);
1258 RegCloseKey (NPKey);
1259 DebugEvent0("AFS_Startup_Event");
1262 VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
1265 TCHAR profileDir[1024] = TEXT("");
1267 PTOKEN_USER tokenUser = NULL;
1269 DWORD LSPtype, LSPsize;
1271 DWORD LogoffPreserveTokens = 0;
1274 /* Make sure the AFS Libraries are initialized */
1277 DebugEvent0("AFS_Logoff_Event - Start");
1279 (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1280 0, KEY_QUERY_VALUE, &NPKey);
1281 LSPsize=sizeof(LogoffPreserveTokens);
1282 RegQueryValueEx(NPKey, REG_CLIENT_LOGOFF_TOKENS_PARM, NULL,
1283 &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
1284 RegCloseKey (NPKey);
1286 if (!LogoffPreserveTokens) {
1287 memset(&opt, 0, sizeof(LogonOptions_t));
1289 if (pInfo->UserName && pInfo->Domain) {
1290 char username[MAX_USERNAME_LENGTH] = "";
1291 char domain[MAX_DOMAIN_LENGTH] = "";
1294 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1295 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1296 username, sizeof(username), NULL, NULL);
1298 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1299 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1300 domain, sizeof(domain), NULL, NULL);
1302 GetDomainLogonOptions(NULL, username, domain, &opt);
1305 if (ISREMOTE(opt.flags)) {
1306 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1308 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1309 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1311 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1313 DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1318 /* We can't use pInfo->Domain for the domain since in the cross realm case
1319 * this is source domain and not the destination domain.
1321 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1322 WCHAR Domain[64]=L"";
1323 GetLocalShortDomain(Domain, sizeof(Domain));
1324 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1325 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1326 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1330 if (strlen(profileDir)) {
1331 DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
1332 if (!IsPathInAfs(profileDir)) {
1333 if (code = ktc_ForgetAllTokens())
1334 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1336 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1338 DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
1341 DebugEvent0("AFS_Logoff_Event - Unable to load profile");
1345 LocalFree(tokenUser);
1347 DebugEvent0("AFS_Logoff_Event - Local Logon");
1348 if (code = ktc_ForgetAllTokens())
1349 DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
1351 DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
1354 DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
1357 DebugEvent0("AFS_Logoff_Event - End");
1360 VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1362 TCHAR profileDir[1024] = TEXT("");
1364 PTOKEN_USER tokenUser = NULL;
1366 WCHAR szUserW[128] = L"";
1367 char szUserA[128] = "";
1368 char szClient[MAX_PATH];
1369 char szPath[MAX_PATH] = "";
1375 /* Make sure the AFS Libraries are initialized */
1378 DebugEvent0("AFS_Logon_Event - Start");
1380 DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
1382 memset(&opt, 0, sizeof(LogonOptions_t));
1384 if (pInfo->UserName && pInfo->Domain) {
1385 char username[MAX_USERNAME_LENGTH] = "";
1386 char domain[MAX_DOMAIN_LENGTH] = "";
1389 DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
1391 StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
1392 WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
1393 username, sizeof(username), NULL, NULL);
1395 StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
1396 WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
1397 domain, sizeof(domain), NULL, NULL);
1399 DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
1400 GetDomainLogonOptions(NULL, username, domain, &opt);
1402 if (!pInfo->UserName)
1403 DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
1405 DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
1408 DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX",
1409 opt.LogonOption, opt.flags);
1411 if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
1412 DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
1413 goto done_logon_event;
1416 DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
1418 if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
1420 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
1421 tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
1423 if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
1425 DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
1430 /* We can't use pInfo->Domain for the domain since in the cross realm case
1431 * this is source domain and not the destination domain.
1433 if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
1434 WCHAR Domain[64]=L"";
1435 GetLocalShortDomain(Domain, sizeof(Domain));
1436 if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
1437 if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
1438 GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
1442 if (strlen(profileDir)) {
1443 DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir);
1445 DebugEvent0("AFS_Logon_Event - Unable to load profile");
1449 dwSize = sizeof(szUserA);
1450 if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
1451 StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
1452 WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL);
1457 lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL);
1458 StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient);
1460 DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA);
1462 memset (&nr, 0x00, sizeof(NETRESOURCE));
1463 nr.dwType=RESOURCETYPE_DISK;
1465 nr.lpRemoteName=szPath;
1466 res = WNetAddConnection2(&nr,NULL,szUserA,0);
1468 DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X",
1469 szPath, szUserA,res);
1471 DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded");
1473 DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError());
1476 LocalFree(tokenUser);
1478 DebugEvent0("AFS_Logon_Event - End");
1482 GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1484 NTSTATUS Status = 0;
1485 TOKEN_STATISTICS Stats;
1491 *ppSessionData = NULL;
1493 Success = GetTokenInformation( hToken, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1497 Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1498 if ( FAILED(Status) || !ppSessionData )
1504 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
1507 WCHAR szUserW[128] = L"";
1508 char szUserA[128] = "";
1509 char szPath[MAX_PATH] = "";
1510 char szLogonId[128] = "";
1512 char filename[MAX_PATH] = "";
1513 char newfilename[MAX_PATH] = "";
1514 char commandline[MAX_PATH+256] = "";
1515 STARTUPINFO startupinfo;
1516 PROCESS_INFORMATION procinfo;
1517 HANDLE hf = INVALID_HANDLE_VALUE;
1519 LUID LogonId = {0, 0};
1520 PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
1522 HKEY hKey1 = NULL, hKey2 = NULL;
1524 /* Make sure the KFW Libraries are initialized */
1527 DebugEvent0("KFW_Logon_Event - Start");
1529 GetSecurityLogonSessionData( pInfo->hToken, &pLogonSessionData );
1531 if ( pLogonSessionData ) {
1532 LogonId = pLogonSessionData->LogonId;
1533 DebugEvent("KFW_Logon_Event - LogonId(%d,%d)", LogonId.HighPart, LogonId.LowPart);
1535 sprintf(szLogonId,"%d.%d",LogonId.HighPart, LogonId.LowPart);
1536 LsaFreeReturnBuffer( pLogonSessionData );
1538 DebugEvent0("KFW_Logon_Event - Unable to determine LogonId");
1542 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1543 if ( count > sizeof(filename) || count == 0 ) {
1544 GetWindowsDirectory(filename, sizeof(filename));
1547 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
1548 if ( count > sizeof(filename) || count == 0 ) {
1549 GetWindowsDirectory(filename, sizeof(filename));
1552 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
1553 DebugEvent0("KFW_Logon_Event - filename too long");
1557 strcat(filename, "\\");
1558 strcat(filename, szLogonId);
1560 hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING,
1561 FILE_ATTRIBUTE_NORMAL, NULL);
1562 if (hf == INVALID_HANDLE_VALUE) {
1563 DebugEvent0("KFW_Logon_Event - file cannot be opened");
1568 if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
1569 DebugEvent0("KFW_Logon_Event - unable to set dacl");
1570 DeleteFile(filename);
1574 if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
1575 DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
1579 if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
1580 DebugEvent0("KFW_Logon_Event - new filename too long");
1584 strcat(newfilename, "\\");
1585 strcat(newfilename, szLogonId);
1587 if (!MoveFileEx(filename, newfilename,
1588 MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1589 DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
1593 sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
1595 GetStartupInfo(&startupinfo);
1596 if (CreateProcessAsUser( pInfo->hToken,
1602 CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
1608 DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
1610 WaitForSingleObject(procinfo.hProcess, 30000);
1612 CloseHandle(procinfo.hThread);
1613 CloseHandle(procinfo.hProcess);
1615 DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
1618 DeleteFile(filename);
1620 DebugEvent0("KFW_Logon_Event - End");