9c2eec3521a27e5db87d46c157296a94bcc3bdd8
[openafs.git] / src / WINNT / win9xpanel / WinAfsLoad.cpp
1 // WinAfsLoad.cpp : Defines the class behaviors for the application.
2 //
3 /* Copyright 2000, International Business Machines Corporation and others.
4         All Rights Reserved.
5  
6         This software has been released under the terms of the IBM Public
7         License.  For details, see the LICENSE file in the top-level source
8         directory or online at http://www.openafs.org/dl/license10.html
9 */
10
11 #include "stdafx.h"
12 #include "WinAfsLoad.h"
13 #include "WinAfsLoadDlg.h"
14 #include "cregkey.h"
15 #include "api95.h"
16 #include "termwarn.h"
17 #include "myframe.h"
18 #include "afsmsg95.h"
19 #include "Tlhelp32.h"
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #undef THIS_FILE
24 static char THIS_FILE[] = __FILE__;
25 #endif
26
27 /////////////////////////////////////////////////////////////////////////////
28 // CWinAfsLoadApp
29
30 BEGIN_MESSAGE_MAP(CWinAfsLoadApp, CWinApp)
31         //{{AFX_MSG_MAP(CWinAfsLoadApp)
32         //}}AFX_MSG_MAP
33         ON_COMMAND(ID_HELP, CWinApp::OnHelp)
34         ON_THREAD_MESSAGE(WM_UIONPARM,OnNotifyReturn)
35         ON_THREAD_MESSAGE(WSA_EVENT, OnAfsEvent)
36 END_MESSAGE_MAP()
37
38 /////////////////////////////////////////////////////////////////////////////
39 // CWinAfsLoadApp construction
40
41 CWinAfsLoadApp::CWinAfsLoadApp()
42 {
43         // TODO: add construction code here,
44         // Place all significant initialization in InitInstance
45 }
46
47 /////////////////////////////////////////////////////////////////////////////
48 // The one and only CWinAfsLoadApp object
49
50 CWinAfsLoadApp theApp;
51
52 /////////////////////////////////////////////////////////////////////////////
53 // CWinAfsLoadApp initialization
54
55 HWND CWinAfsLoadApp::m_hAfsLoadFinish=0;
56 HWND CWinAfsLoadApp::m_hAfsLoad=0;
57 CString CWinAfsLoadApp::m_sDosAppName;
58 /*
59                 DWORD dwProcessID;
60                 ::GetWindowThreadProcessId (hWnd, &dwProcessID);
61 */
62 BOOL CALLBACK CWinAfsLoadApp::EnumWindowsProc(HWND hWnd, LPARAM lParam)
63 {
64         CWnd *wnd=CWnd::FromHandle(hWnd);
65         CString msg;
66         CString sFinish;
67         wnd->GetWindowText(msg);
68         if ( (!m_sDosAppName.IsEmpty()) 
69                 && (m_sDosAppName!=""))
70         {
71                 if (msg==m_sDosAppName)
72                         m_hAfsLoad=hWnd;
73                 sFinish.Format("Finished - %s",m_sDosAppName);
74                 if (msg==sFinish)
75                         m_hAfsLoadFinish=hWnd;
76         }
77         if (msg==DOSTITLE)
78                 m_hAfsLoad=hWnd;
79         if ((msg==DOSTITLEFINISH)||(msg==APPTITLEFINISH))
80                 m_hAfsLoadFinish=hWnd;
81         return ((m_hAfsLoad==0) && (m_hAfsLoadFinish==0));
82 }
83
84 int CWinAfsLoadApp::ExitInstance() 
85 {
86         // TODO: Add your specialized code here and/or call the base class
87         if (m_pCMyUIThread)
88         {
89                 SetNotifyEventSuspend();
90                 m_pCMyUIThread->PostThreadMessage(WM_UIONPARM,ONPARMCLOSE,0);
91                 WaitForSingleObject(CMyUIThread::m_hEventThreadKilled, INFINITE);
92                 CloseHandle(CMyUIThread::m_hEventThreadKilled);
93                 m_pCMyUIThread=NULL;
94         }
95         return CWinApp::ExitInstance();
96 }
97
98 BOOL CWinAfsLoadApp::InitInstance()
99 {
100         HWND hwnd=FindWindow(NULL,"AFS Activity Log");
101         CString msg;
102         msg.LoadString(IDD_ACTIVITYLOG);
103         if (hwnd)
104         {
105                 ::PostMessage(hwnd,WM_SYSCOMMAND,IDM_VISIBLE,0);
106                 return FALSE;
107         }
108         EnumWindows (CWinAfsLoadApp::EnumWindowsProc, (LPARAM) 0);      //lets grab other open windows and close them down
109         if (!AfxSocketInit())
110         {
111                 AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
112                 return FALSE;
113         }
114
115         // Standard initialization
116         // If you are not using these features and wish to reduce the size
117         //  of your final executable, you should remove from the following
118         //  the specific initialization routines you do not need.
119
120 #ifdef _AFXDLL
121         Enable3dControls();                     // Call this when using MFC in a shared DLL
122 #else
123         Enable3dControlsStatic();       // Call this when linking to MFC statically
124 #endif
125
126         PCHAR pPath=getenv("AFSCONF");
127         m_sTargetDir.Empty();
128         if (!pPath)
129                 AfxMessageBox("AFS Error - Improper installation, Enviornemnt variable AFSCONF missing",MB_ICONWARNING | MB_OK);
130         else 
131                 m_sTargetDir.Format("%s\\",pPath);
132
133 //      CString t(m_sTargetDir);
134 //      t+="afs-light.hlp";
135
136         m_pszHelpFilePath=_tcsdup(_T("afswin9x.hlp"));
137 // initialize variables
138         CRegkey regkey("AFS\\Window");
139         if (regkey.Getkey()!=0)
140         {
141                 DWORD len=64;
142                 regkey.GetString("Title",m_sDosAppName,len);
143         }
144         RegOptions(TRUE);
145
146         if ((m_pCMyUIThread=(CMyUIThread *)AfxBeginThread(RUNTIME_CLASS(CMyUIThread)),THREAD_PRIORITY_IDLE)==NULL)
147         {// need to create a very low priority else it will interfere with other windows
148                 AfxMessageBox("Error creating background thread for progress bar! /nApplicaton still operational.");
149                 m_pCMyUIThread=NULL;
150         } else
151                 m_pCMyUIThread->m_hEventThreadKilled    //used to test when thread is done
152                         = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset, initially reset
153         // scan for command line options
154         // show userid: password: connect
155         CharLower(m_lpCmdLine);
156         m_bShowAfs=(strstr(m_lpCmdLine,"show")!=NULL);
157         if (m_bLogWindow)
158                 ShowLog(TRUE);
159         if (m_bLog)
160                 ShowPrint(TRUE);
161         char *str=NULL;
162         CString cUserName;
163         strlwr(m_lpCmdLine);    //convert to lower case
164         if ((str=strstr(m_lpCmdLine,"userid:"))!=NULL)  // 
165         {
166                 cUserName=(strstr(str,":"));
167         }
168         CString cPassWord;
169         if ((str=strstr(m_lpCmdLine,"password:"))!=NULL)
170         {
171                 cPassWord=(strstr(str,":"));
172         }
173 //      BOOL bConnect=(strstr(m_lpCmdLine,"connect")!=NULL);
174
175         if (m_hAfsLoadFinish)   // SOME REASON THE WINDOW WAS NOT SHUT DOWN, SO LETES KILL IT
176         {
177                 ::SendMessage(m_hAfsLoadFinish,WM_CLOSE,0,0);
178                 LOG("WM_CLOSE");
179         }
180         if (m_hAfsLoad) // Something wrong, BACKGROUND is running without dialog
181         {
182                 CTermWarn *pModeless = new CTermWarn(NULL);
183                 pModeless->Create();
184                 pModeless->SetActiveWindow();
185                 ShutdownAfs();
186                 CTime startTime = CTime::GetCurrentTime();
187                 CTimeSpan elapsedTime;
188                 do 
189                 {
190                         Sleep(500);
191                         m_hAfsLoad=0;
192                         EnumWindows (EnumWindowsProc, (LPARAM) 0);      //lets prevent multiple instances!
193                         elapsedTime= CTime::GetCurrentTime() - startTime;
194                         if (elapsedTime.GetTotalSeconds()>10) 
195                         {
196                                 if (pModeless)
197                                         pModeless->OnCancel();
198                                 ::ShowWindow(m_hAfsLoad,SW_SHOWNORMAL);
199                                 ::AfxMessageBox("AFS Error - Warning AFS Client Console still running.\n Locate the console and use Control C to manually terminate it!");
200                                 return FALSE;
201                         }
202                 } while (m_hAfsLoad);
203                 if (m_hAfsLoadFinish)   // SOME REASON THE WINDOW WAS NOT SHUT DOWN, SO LETES KILL IT
204                 {
205                         ::SendMessage(m_hAfsLoadFinish,WM_CLOSE,0,0);
206                         LOG("WM_CLOSE");
207                 }
208                 if (pModeless)
209                         pModeless->OnCancel();
210         }
211         CWinAfsLoadDlg dlg(cUserName,cPassWord);
212         m_pMainWnd = &dlg;
213         int nResponse = dlg.DoModal();
214         if (nResponse == IDOK)
215         {
216                 // TODO: Place code here to handle when the dialog is
217                 //  dismissed with OK
218         }
219         else if (nResponse == IDCANCEL)
220         {
221                 // TODO: Place code here to handle when the dialog is
222                 //  dismissed with Cancel
223         }
224
225         // Since the dialog has been closed, return FALSE so that we exit the
226         //  application, rather than start the application's message pump.
227         return TRUE;
228 }
229
230 BOOL CWinAfsLoadApp::RegOptions(BOOL fetch)
231 {
232         CRegkey regkey("AFS\\Window");
233         if (regkey.Getkey()==0) return FALSE;
234         DWORD w=0;
235         DWORD len=sizeof(w);
236         if (fetch)
237         {
238                 regkey.GetBinary("CommandSettings",(LPBYTE)(&w),len);
239                 m_bLogWindow=((w & 2)!=0);
240                 m_bLog=((w & 4)!=0);
241                 m_bConnect=((w & 1)!=0);
242         } else
243         {
244                 w=((m_bLogWindow)?2:0) | ((m_bLog)?4:0) | ((m_bConnect)?1:0);
245                 regkey.PutBinary("CommandSettings",(LPBYTE)(&w),sizeof(DWORD));
246         }
247         return TRUE;
248 }
249
250 void CWinAfsLoadApp::Log(const char *s)
251 {
252         TRACE("%s\n",s);
253         if ((!m_bLogWindow) && (!m_bLog)) return;
254         if (s)
255         {
256                 SYSTEMTIME timeDest;
257                 GetSystemTime(&timeDest);
258                 CString *mt=new CString;        //release is handled by CMyUIThread
259                 mt->Format("(%02d:%02d:%2d-%03d)%s\r\n",
260                         timeDest.wHour,
261                         timeDest.wMinute,
262                         timeDest.wSecond,
263                         timeDest.wMilliseconds,s);
264                 m_pCMyUIThread->PostThreadMessage(WM_LOG,0,(LPARAM)mt);
265         }
266         else
267                 m_pCMyUIThread->PostThreadMessage(WM_LOG,0,0);
268 }
269
270 void CWinAfsLoadApp::Log(const char *f,const DWORD d)
271 {
272         CString msg;
273         msg.Format(f,d);
274         Log(msg);
275 }
276
277 void CWinAfsLoadApp::Log(const char *f,const DWORD d,const DWORD d2)
278 {
279         CString msg;
280         msg.Format(f,d,d2);
281         Log(msg);
282 }
283
284 void CWinAfsLoadApp::Log(const char *f,const char*s)
285 {
286         CString msg;
287         msg.Format(f,s);
288         Log(msg);
289 }
290
291 void CWinAfsLoadApp::Log(const char *f,const char*s,const char*s2)
292 {
293         CString msg;
294         msg.Format(f,s,s2);
295         Log(msg);
296 }
297
298 void CWinAfsLoadApp::Log(const char *f,const char*s,const char*s2,const char*s3)
299 {
300         CString msg;
301         msg.Format(f,s,s2,s3);
302         Log(msg);
303 }
304
305 void CWinAfsLoadApp::ShowLog(BOOL yes)
306 {
307         m_pCMyUIThread->PostThreadMessage(WM_LOG,LOGSHOWWINDOW,yes);
308 }
309
310 void CWinAfsLoadApp::ShowPrint(BOOL yes)
311 {
312         CString *mp=new CString();
313         mp->Format("%s\\afscli.log",getenv("AFSCONF"));
314         m_pCMyUIThread->PostThreadMessage(WM_LOG,LOGSHOWPRINT,(yes)?(LPARAM)mp:NULL);
315 }
316
317 void CWinAfsLoadApp::Progress(VOID *ptr, UINT mode)
318 {
319         // you cannot obtain the handle to the window int these routines so you have enough time to create the window
320         // It is ok to postmessage to a window in a different thread!
321         if (m_pCMyUIThread==NULL) return;
322         switch (mode)
323         {
324         case ProgFSetTitle:
325                 ::PostMessage(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd()
326                         ,WM_PROGRESSPARM,ProgFSetTitle,(LPARAM)ptr);
327                 break;
328         case ProgFHide:
329                 ::PostMessage(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd()
330                         ,WM_PROGRESSPARM,ProgFHide,0);
331                 break;
332         case ProgFNext:
333                 ::PostMessage(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd(),WM_PROGRESSPARM,ProgFNext,0);
334                 BringWindowToTop(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd());
335                 break;
336         default:
337                 ::PostMessage(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd(),WM_PROGRESSPARM,ProgFOpt,mode);
338                 BringWindowToTop(((CDialog *)m_pCMyUIThread->GetMainWnd())->GetSafeHwnd());
339                 ((CDialog *)m_pCMyUIThread->GetMainWnd())->CenterWindow((CWnd *)ptr);
340         case 0:
341                 break;
342         }
343 }
344
345 void CWinAfsLoadApp::RequestUISuspendEvent(UINT mode)
346 {
347         SetNotifyEventSuspend();
348         m_pCMyUIThread->PostThreadMessage(WM_UIONPARM,mode,0);
349 }
350
351 void CWinAfsLoadApp::RequestUIPostEvent(UINT mode,WPARAM wp,LPARAM lp)
352 {
353         SetNotifyEventPostMessage();
354         m_pCMyUIThread->PostThreadMessage(mode,wp,lp);
355 }
356
357
358 /*
359 There is no queue for messages (only one event) therefore messages passed to us
360 are not queued and stored in m_sMsg & m_wParam;
361 */
362
363 void CWinAfsLoadApp::SetNotifyEventSuspend()
364 {
365         ResetEvent(CMyUIThread::m_hEventThreadKilled);
366         m_uNotifyMessage=1;
367 }
368
369 void CWinAfsLoadApp::WaitForEvent(UINT logintime,WPARAM *wp,CString *msg)
370 {
371         switch (WaitForSingleObject(CMyUIThread::m_hEventThreadKilled, logintime))
372         {
373         case WAIT_OBJECT_0:
374                 LOG("OnAfsEvent - Receive Good Status ");
375                 *msg=m_sMsg;
376                 break;
377         default:
378                 *wp=AFS_EXITCODE_GENERAL_FAILURE;
379                 *msg="AFS Client timed out, failure to respond\r\nCheck Network Connection.";
380                 LOG("OnAfsEvent %s",(const char *)*msg);
381                 return;
382         }
383         *wp=m_wParam;
384 }
385
386 /*
387 Tthis funciton is called from UIThread (different thread) 
388         and should not contain and Windows stuff assocaited with CWinAFSLoad.
389 It is used to display messages from a backgound process or during PowerSuspend denial
390 NOTICE: PostThreadMessage leaves deletion of message up to caller
391         WaitEvent does not have to delete message because Wait is not queued like PostMessage
392 */
393 void CWinAfsLoadApp::WSANotifyFromUI(WPARAM wp,const char *msg)
394 {       
395         TRACE("CWinAfsLoadApp::Notify wp=%d,msg=[%s]\n",wp,msg);
396         switch (m_uNotifyMessage)
397         {
398         case 2:
399                 {// for post message use allocated memory to hold results and pass back to main thread
400                 CString *mp=new CString;                //memory is released by destination routine!
401                 *mp=msg;
402                 PostThreadMessage(WSA_EVENT,wp,(LPARAM)mp);     //this goes to WSA_EVENT
403                 }
404                 break;
405         case 1:
406                 // For setting the Event completion, pass information back to calling thread
407                 m_wParam=wp;
408                 m_sMsg=msg;     
409                 SetEvent(CMyUIThread::m_hEventThreadKilled);
410                 m_uNntifyMessage=0;
411                 break;
412         default:
413                 break;
414         }
415 }
416
417 void CWinAfsLoadApp::NotifyFromUI(WPARAM wp,const char *msg)
418 {// called from UIThread to notify return status
419         CString *mp=NULL;
420         if (msg)
421         {
422                 mp=new CString;         //memory is released by destination routine!
423                 *mp=msg;
424                 TRACE("CWinAfsLoadApp::Notify wp=%d,msg=[%s]\n",wp,msg);
425         } else
426                 TRACE("CWinAfsLoadApp::Notify wp=%d,msg=NULL\n",wp);
427         if (wp)
428                 PostThreadMessage(WM_UIONPARM,wp,(LPARAM)mp);
429 }
430
431 LRESULT CWinAfsLoadApp::OnNotifyReturn(WPARAM wParam, LPARAM lParam)
432 {
433         if (m_pMainWnd)
434                 return ((CWinAfsLoadDlg *)m_pMainWnd)->OnNotifyReturn(wParam,lParam);
435         return TRUE;
436 }
437
438 LRESULT CWinAfsLoadApp::OnAfsEvent(WPARAM wParam, LPARAM lParam)
439 {
440         if (m_pMainWnd)
441                 return ((CWinAfsLoadDlg *)m_pMainWnd)->OnAfsEvent(wParam,lParam);
442         return TRUE;
443 }
444