win95-initial-port-20010430
[openafs.git] / src / WINNT / win9xpanel / CAfs.cpp
diff --git a/src/WINNT/win9xpanel/CAfs.cpp b/src/WINNT/win9xpanel/CAfs.cpp
new file mode 100644 (file)
index 0000000..2853f48
--- /dev/null
@@ -0,0 +1,523 @@
+/* Copyright 2000, International Business Machines Corporation and others.
+       All Rights Reserved.
+       This software has been released under the terms of the IBM Public
+       License.  For details, see the LICENSE file in the top-level source
+       directory or online at http://www.openafs.org/dl/license10.html
+*/
+
+#include "stdafx.h"
+#ifdef _MFC_VER
+extern "C" {
+#endif
+#include <afs\param.h>
+#include <afs\stds.h>
+#include <afs\kautils.h>
+#include "cm_config.h"
+#include "cmd.h"
+#ifdef _MFC_VER
+       }
+#endif
+#include "api95.h"
+#include "cregkey.h"
+#include "cafs.h"
+#include <Svrapi.h>
+#include "afsmsg95.h"
+
+#include "WinAfsLoad.h"
+
+#define AFS_KERBEROS_ENV
+
+#ifndef KABADARGUMENT
+#undef KABADARGUMENT
+#define KABADARGUMENT 1
+#endif
+#define KLOGEXIT(code) exit(code)
+
+#define LENDIR 128
+
+//#define _DEBUG        
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define HOURSLEFT 24
+
+CProgress::CProgress(CWnd *wnd, UINT mode)
+{
+       m_pWnd=wnd;
+       // you cannot obtain the handle to the window int these routines so you have enough time to create the window
+       PROGRESS(wnd,mode);
+}
+
+CProgress::~CProgress()
+{
+       PROGRESS(NULL,ProgFHide);
+}
+
+void CProgress::SetTitle(const char *t1,const char *t2,const char *t3)
+{
+       char *msg=new char[strlen(t1)+strlen(t2)+strlen(t3)+3];
+       strcpy(msg,t1);
+       strcpy(msg+strlen(t1)+1,t2);
+       strcpy(msg+strlen(t1)+strlen(t2)+2,t3);
+       PROGRESS(msg,ProgFSetTitle);
+}
+
+void CProgress::Next()
+{
+       PROGRESS(m_pWnd,ProgFNext);
+}
+
+void CProgress::Finish()
+{
+       PROGRESS(NULL,ProgFHide);
+}
+
+
+CAfs::~CAfs()
+{
+       // let the OS kill the progress bar thread
+}
+
+void CAfs::FinishProgress()
+{
+       PROGRESS(NULL,ProgFHide);
+}
+
+BOOL CALLBACK CAfs::EnumWindowsProcShutdown(HWND hWnd, LPARAM lParam)
+{
+       CWnd *wnd=CWnd::FromHandle(hWnd);
+       CString msg;
+       CString sFinish;
+       wnd->GetWindowText(msg);
+       if (msg==m_sDosAppName)
+               m_hAfsLoad=hWnd;
+       sFinish.Format("Finished - %s",m_sDosAppName);
+       if (msg==sFinish)
+               m_hAfsLoadFinish=hWnd;
+       return ((m_hAfsLoad==0) && (m_hAfsLoadFinish==0));
+}
+
+BOOL CAfs::Init(CWnd *wnd,CString &msg)
+{
+       ka_Init(0);
+       return TRUE;
+}
+
+HWND CAfs::m_hAfsLoad;
+HWND CAfs::m_hAfsLoadFinish;
+CString CAfs::m_sDosAppName;
+
+BOOL CALLBACK CAfs::EnumWindowsProc(HWND hWnd, LPARAM lParam)
+{
+       CWnd *wnd=CWnd::FromHandle(hWnd);
+       CString msg;
+       wnd->GetWindowText(msg);
+       DWORD dwProcessID;
+       ::GetWindowThreadProcessId (hWnd, &dwProcessID);
+       if (dwProcessID == (DWORD) lParam)
+       {
+               if (msg.IsEmpty()) return TRUE;
+               m_hAfsLoad=hWnd;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+BOOL CAfs::Create(CString &msg,CString sCompName,PROCESS_INFORMATION &procInfo)
+{
+       DWORD rc;
+// lets make sure there are no other instances of the client   
+       m_hAfsLoadFinish=m_hAfsLoad=0;
+       EnumWindows (EnumWindowsProcShutdown, (LPARAM) 0);      //lets prevent multiple instances!
+       if (m_hAfsLoad)
+               Shutdown(msg);
+       else if (m_hAfsLoadFinish)      // SOME REASON THE WINDOW WAS NOT SHUT DOWN, SO LETES KILL IT
+       {
+               ::SendMessage(m_hAfsLoadFinish,WM_CLOSE,0,0);
+               LOG("WM_CLOSE");
+       }
+       CRegkey regkey("AFS\\Window");
+       UINT logintime=0;
+       DWORD size=sizeof(logintime);
+       regkey.GetBinary("LoginTime",(LPBYTE)&logintime,size);
+       if (logintime<=0) {
+#ifdef _DEBUG
+               logintime=10;
+#else
+               logintime=40;
+#endif
+               regkey.PutBinary("LoginTime",(LPBYTE)&logintime,size);
+       }
+       int Pipe = 0;
+       GetStartupInfo(&m_startUpInfo);
+       m_startUpInfo.lpTitle = DOSTITLE;
+       m_startUpInfo.wShowWindow = (CWINAFSLOADAPP->m_bShowAfs) ?SW_SHOW :SW_HIDE;//SW_SHOWMINIMIZED;//SW_HIDE;
+       m_startUpInfo.dwFlags|=STARTF_USESHOWWINDOW;
+       CWINAFSLOADAPP->SetNotifyEventSuspend();        //this needs to be done before createprocess, incase notification occurs before WaitSuspend
+       LOG("Start AFSD Creation");
+       rc = CreateProcess(NULL /*appName 16bit apps should be null*/,CMDLINE, NULL, NULL, FALSE,
+                     /*DETACHED_PROCESS |*/ CREATE_NEW_CONSOLE | HIGH_PRIORITY_CLASS /*NORMAL_PRIORITY_CLASS*/,
+                     NULL, NULL, &m_startUpInfo, &procInfo);
+
+       LOG("AFSD Creation done - wait for notification");
+       if (!rc) {
+               msg.Format("Error creating AFS Client Console process, Status=0x%0x", GetLastError());
+               return FALSE;
+       }
+       WPARAM wp;
+       CWINAFSLOADAPP->WaitForEvent(logintime*1000,&wp,&msg);
+       switch (wp)
+       {
+       case AFS_EXITCODE_NORMAL:
+               // extract machine name for logon
+               msg=msg.Right(msg.GetLength()-msg.Find('#')-1);
+               m_sMountName.Format("\\\\%s",msg.Left(msg.ReverseFind('#')));
+               if (m_sMountName=="\\\\")
+               {
+                       m_sMountName.Format("\\\\%s-AFS",sCompName.Left(11));
+               }
+               break;
+       default:
+               return FALSE;
+       }
+       EnumWindows (EnumWindowsProc, (LPARAM) procInfo.dwProcessId);
+       CString name;
+       int len=0;
+       if (m_hAfsLoad)
+       {
+               len=GetWindowText(m_hAfsLoad,name.GetBuffer(64),63);
+               m_sDosAppName=name;
+       }
+       if (name==DOSTITLE) return TRUE;
+       if ((len==0)||(name==DOSTITLEFINISH) || (name==APPTITLEFINISH))
+       {
+               msg="AFS Client Console did not start properly!";
+               CString temp;
+               Shutdown(temp);
+               return FALSE;
+       }
+       regkey.PutString("Title",name);
+       return TRUE;
+}
+
+BOOL CAfs::CheckNet(CString &msg)
+{
+       TCHAR szDrive[] = TEXT("*:");
+       TCHAR szMapping[ MAX_PATH ] = TEXT("");
+       LPTSTR pszSubmount = szMapping;
+//     TCHAR scan[MAX_PATH];
+    DWORD dwSize = MAX_PATH;
+//     TCHAR pBuffer[MAX_PATH];
+//     wsprintf(scan, "\\\\%s", compname);
+       for (TCHAR chDrive = 'D'; chDrive <= 'Z'; ++chDrive)
+       {
+               szDrive[0]=chDrive;
+               if (WNetGetConnection (szDrive, szMapping, &dwSize) == NO_ERROR)
+               {
+                       CHAR *p=strstr(szMapping,m_sMountName);
+                       if (p)
+                       {
+                               p=strrchr(szMapping,'\\')+1;
+                               if (!Dismount(msg,szDrive,FALSE))
+                               {
+                                       msg.Format("Drive %s has Open Files",szDrive);
+                                       return FALSE;
+                               }
+                               Mount(msg,szDrive,p);
+                       }
+               }
+       }
+       return TRUE;
+}
+
+
+BOOL CAfs::Mount(CString &msg,const char *drvLetter,const char *path)
+{
+       char resource[256];
+       NETRESOURCE nr;
+       int oundHome=0;
+       int Pipe = 0;
+       CWait wait;             //simple way to set cursor busy
+       memset(&nr, 0, sizeof(NETRESOURCE));
+       ASSERT(strlen(m_sMountName)!=0);
+       wsprintf(resource, "%s\\%s", m_sMountName,path);
+       nr.dwType = RESOURCETYPE_DISK;
+       nr.lpProvider = NULL;
+       nr.lpLocalName = (char *)drvLetter;
+       nr.lpRemoteName = resource;
+       switch (WNetAddConnection2(&nr, 0, 0, 0))
+       {
+       case ERROR_ACCESS_DENIED:
+               msg.Format("Access to the network resource was denied, cannot connect '%s%s'",drvLetter,path);
+               return FALSE;
+       case ERROR_ALREADY_ASSIGNED: 
+               msg.Format("Drive %s specified by the path, '%s', is already connected to a network resource",drvLetter,path);
+               return FALSE;
+       case ERROR_BAD_DEVICE: 
+               msg.Format("Path '%s' is invalid",path);
+               return FALSE;
+       case ERROR_BAD_NET_NAME: 
+               msg.Format("Path '%s' is not acceptable to any network resource provider, either because the resource name is invalid, or because the named resource cannot be located",path);
+               return FALSE;
+       case ERROR_BAD_PROFILE: 
+               msg.Format("The user profile is in an incorrect format, cannot add '%s%s'",drvLetter,path);
+               return FALSE;
+       case ERROR_BUSY: 
+               msg.Format("The router or provider is busy, possibly initializing. Please retry, cannot add %s%s",drvLetter,path);
+               return FALSE;
+       case ERROR_INVALID_PASSWORD: 
+               msg.Format("The specified password is invalid, cannot add '%s%s'",drvLetter,path);
+               return FALSE;
+       case NO_ERROR:
+               return TRUE;
+       default:
+               msg.Format("Network error adding '%s%s'",drvLetter,path);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+BOOL CAfs::Dismount(CString &msg,const char *drvLetter,BOOL force)
+{
+       int Pipe = 0;
+       DWORD ret=-1;
+       CWait wait;             //simple way to set cursor busy
+       ret=WNetCancelConnection2(drvLetter,CONNECT_UPDATE_PROFILE,force);
+       switch (ret)
+       {
+       case ERROR_DEVICE_IN_USE:
+               msg.Format("A device is in use and '%s' cannot be disconnected",drvLetter);
+               return FALSE;
+       case ERROR_OPEN_FILES:
+               msg.Format("There are open files on '%s' and cannot be disconnected",drvLetter);
+               return FALSE;
+       case ERROR_NOT_CONNECTED:
+       case NO_ERROR:
+       default:
+               break;
+       }
+       return TRUE;
+}
+
+BOOL CAfs::Authencate(CString &msg,const char * name,const char * password)
+{
+       DWORD rc;
+       char instance[8];
+       char realm[256];
+       int lifetime;
+       char *reason;
+       int oundHome=0;
+       long password_expires;
+       int Pipe = 0;
+       cm_GetRootCellName(m_cCell);
+       strcpy(realm, m_cCell);
+       lifetime = 0;
+       instance[0] = 0;
+    rc = ka_UserAuthenticateGeneral (KA_USERAUTH_VERSION,
+                                    (PCHAR)name, instance, realm, (PCHAR)password, lifetime,
+                                    &password_expires, 0, &reason);
+       if (rc) {
+               if (strstr(reason,"skewed"))
+               {
+                       char buf[32];
+                       if (GetEnvironmentVariable("TZ",buf,32))
+                       {
+                               msg.Format("Unable to authenticate to AFS because:\n '%s'.\nCheck Enviornment Variable 'TZ=%s', either remove it (See Autoexec.bat) or set it correctly.",reason,buf);
+                               return FALSE;
+                       }
+               }
+               msg.Format("Unable to authenticate to AFS because:\n '%s'.", reason);
+               return FALSE;
+       }
+
+#ifndef AFS_KERBEROS_ENV
+       if (writeTicketFile) {
+               code = krb_write_ticket_file (realm);
+               if (!Silent) {
+                       if (code) 
+                               com_err (rn, code, "writing Kerberos ticket file");
+                       else {
+                               m_pParent->Log("Wrote ticket file to /tmp");
+                       }
+               }
+       }
+#endif
+       m_tTotalSpanTime=0;                     //reset total time to 0 so ScanTokens will reset it
+       return ScanTokens(msg);
+}
+
+BOOL CAfs::StartExployer(CString &msg,const char *udrive)
+{
+       DWORD rc;
+       PROCESS_INFORMATION procInfo;
+       STARTUPINFO startUpInfo;
+       int Pipe = 0;
+       int code;
+       WIN32_FIND_DATA FileData;
+       CString dir;
+       dir.Format("%s\\*",udrive);
+       HANDLE hFile= FindFirstFile(
+               dir,               // file name
+               &FileData);
+       if (hFile==INVALID_HANDLE_VALUE)
+       {
+               msg.Format("Unable to open Explorer, Drive '%s' is connected but not accessable.",udrive);
+               return FALSE;
+       }
+       FindClose(hFile);
+       char wdir[LENDIR+1];
+       code = GetWindowsDirectory(wdir, sizeof(wdir));
+    
+       if (code == 0 || code > sizeof(wdir))
+      strcpy(wdir, "c:\\windows");
+       CString cmdLine;
+       cmdLine.Format("%s\\explorer.exe /n,/e,%s\\",wdir,udrive);
+       GetStartupInfo(&startUpInfo);
+    startUpInfo.lpTitle = NULL;
+    startUpInfo.wShowWindow = SW_SHOWNORMAL;
+    rc = CreateProcess(NULL /*appName*/
+               ,cmdLine.GetBuffer(cmdLine.GetLength())
+               , NULL, NULL, FALSE
+               ,DETACHED_PROCESS | NORMAL_PRIORITY_CLASS
+               ,NULL, NULL, &startUpInfo, &procInfo);
+       if (rc!=0) return TRUE;
+       LPVOID lpMsgBuf;
+       FormatMessage( 
+               FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+           FORMAT_MESSAGE_FROM_SYSTEM | 
+               FORMAT_MESSAGE_IGNORE_INSERTS,
+           NULL,
+               GetLastError(),
+           MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+               (LPTSTR) &lpMsgBuf,
+           0,
+               NULL 
+       );
+       msg.Format("Unable to open Explorer, %s.",lpMsgBuf);
+       LocalFree( lpMsgBuf );
+       return FALSE;
+}
+
+BOOL CAfs::Shutdown(CString &msg)
+{
+       CWINAFSLOADAPP->ClearNotify();
+       ShutdownAfs();
+       m_hAfsLoadFinish=0;
+       CTime startTime = CTime::GetCurrentTime();
+       CTimeSpan elapsedTime;
+       do 
+       {
+               m_hAfsLoad=0;
+               EnumWindows (EnumWindowsProcShutdown, (LPARAM) 0);      //lets prevent multiple instances!
+               Sleep(500);
+               elapsedTime= CTime::GetCurrentTime() - startTime;
+               if (elapsedTime.GetTotalSeconds()>10) 
+               {
+                       msg="AFS Client Console was not terminated properly!";
+                       ::ShowWindow(m_hAfsLoad,SW_SHOWNORMAL);
+                       return FALSE;
+               }
+       } while (m_hAfsLoad);
+       if (m_hAfsLoadFinish==0)
+       {
+               Sleep(250);     //maybe it takes a little time between process kill and window display??
+               EnumWindows (EnumWindowsProcShutdown, (LPARAM) 0);      //lets prevent multiple instances!
+       }
+       if (m_hAfsLoadFinish)   // SOME REASON THE WINDOW WAS NOT SHUT DOWN, SO LETES KILL IT
+       {
+               ::SendMessage(m_hAfsLoadFinish,WM_CLOSE,0,0);
+               LOG("WM_CLOSE2");
+       }
+       return TRUE;
+}
+
+
+/*
+       struct afsconf_cell {
+               char name[MAXCELLCHARS];            Cell name
+               short numServers;                   Num active servers for the cell
+               short flags;                                            useful flags
+               struct sockaddr_in hostAddr[MAXHOSTSPERCELL]; IP addresses for cell's servers
+               char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS]; Names for cell's servers
+               char *linkedCell;                   Linked cell name, if any
+       }
+*/
+
+BOOL CAfs::ScanTokens(CString &msg)
+{
+       int cellNum;
+       int rc;
+       struct ktc_principal serviceName, clientName;
+       struct ktc_token token;
+       cellNum = 0;
+       msg="";
+       while (1) {
+               rc = ktc_ListTokens(cellNum, &cellNum, &serviceName);
+               if (rc == KTC_NOENT) {
+                       return TRUE;
+                       break;
+               }
+               else if (rc == KTC_NOCM) {
+                       return TRUE;
+               }
+               else if (rc) {
+                       msg.Format("AFS Scan token error - Unexpected error, code 0x%0x\n", rc);
+                       return FALSE;
+               }
+               else {
+                       rc = ktc_GetToken(&serviceName, &token, sizeof(token),
+                                         &clientName);
+                       if (rc) {
+                               msg.Format("Unexpected error, service %s.%s.%s, code 0x%0x\n",
+                                       serviceName.name, serviceName.instance,
+                                       serviceName.cell, rc);
+                               return FALSE;
+                       }
+                       m_dTokenEndTime=token.endTime;
+                       if (m_tTotalSpanTime.GetTotalSeconds()==0)
+                               m_tTotalSpanTime=::CTime(m_dTokenEndTime)-CTime::GetCurrentTime();
+               }
+       }
+       return TRUE;
+}
+
+UINT CAfs::TestTokenTime(CString &msg)
+{
+       CTimeSpan timeleft=::CTime(m_dTokenEndTime)-CTime::GetCurrentTime();
+#ifdef _DEBUG
+       DWORD dt=timeleft.GetTotalMinutes();
+       DWORD dl=m_tTotalSpanTime.GetTotalMinutes();
+       if (timeleft.GetTotalMinutes()<=m_tTotalSpanTime.GetTotalMinutes()-2)
+       {
+               msg="Authenication Expired: No Time left.";
+               return 2;
+       }
+       msg.Format("Authenication will expire in Hours:%d Minutes:%d",timeleft.GetTotalHours()
+               ,timeleft.GetTotalMinutes()-timeleft.GetTotalHours()*60);
+       return (timeleft.GetTotalMinutes()>(m_tTotalSpanTime.GetTotalMinutes()-1))?0:1;
+#else
+       if (timeleft.GetTotalMinutes()<=0)
+       {
+               msg="Authenication Expired: No Time left.";
+               return 2;
+       }
+       if (
+               (timeleft.GetTotalMinutes()>=(m_tTotalSpanTime.GetTotalMinutes()/7)-1)
+               && (timeleft.GetTotalMinutes()<=(m_tTotalSpanTime.GetTotalMinutes()/7)+1)
+               )
+       {
+               LOG("TimeLeft %d Total Span time %d",timeleft.GetTotalMinutes()
+                       ,m_tTotalSpanTime.GetTotalMinutes());
+               return (ScanTokens(msg))?0:-1;
+       }
+       msg.Format("Authenication will expire in Hours:%d Minutes:%d",timeleft.GetTotalHours()
+               ,timeleft.GetTotalMinutes()-timeleft.GetTotalHours()*60);
+       return (timeleft.GetTotalMinutes()>(m_tTotalSpanTime.GetTotalMinutes()/7))?0:1;
+#endif
+}
+