Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / WINNT / afssvrmgr / svc_viewlog.cpp
1 extern "C" {
2 #include <afs/param.h>
3 #include <afs/stds.h>
4 }
5
6 #include "svrmgr.h"
7 #include <shellapi.h>
8 #include "svc_viewlog.h"
9 #include "svc_general.h"
10
11
12 #define cchMAXLOG 20480  // show at most 20k worth of log file
13
14 #define cxMIN_VIEWLOG  250 // minimum size of View Log File dialog
15 #define cyMIN_VIEWLOG  200 // minimum size of View Log File dialog
16
17
18 /*
19  * RESIZING WINDOWS ___________________________________________________________
20  *
21  */
22
23 rwWindowData awdShowLog[] = {
24     { IDC_SVC_VIEWLOG_DESC,     raSizeX | raRepaint },
25     { IDC_SVC_VIEWLOG_FILENAME, raSizeX | raRepaint },
26     { IDC_VIEWLOG_TEXT,         raSizeX | raSizeY | raRepaint, MAKELONG(cxMIN_VIEWLOG,cyMIN_VIEWLOG) },
27     { IDC_SVC_VIEWLOG_CONTENTS, raSizeX },
28     { IDOK,                     raMoveX | raMoveY },
29     { IDC_VIEWLOG_SAVEAS,       raMoveX | raMoveY },
30     { idENDLIST, 0 }
31  };
32
33
34 /*
35  * PROTOTYPES _________________________________________________________________
36  *
37  */
38
39 BOOL CALLBACK Services_ShowLog_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
40 void Services_ShowLog_TakeNextStep (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp);
41 void Services_ShowLog_OnEndTask (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp, LPTASKPACKET ptp);
42 void Services_ShowLog_OnInitDialog (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp);
43 void Services_ShowLog_OnSaveAs (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp);
44 BOOL Services_ShowLog_Pick (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp);
45
46 BOOL CALLBACK Services_PickLog_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
47 void Services_PickLog_OnInitDialog (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp);
48
49
50 /*
51  * ROUTINES ___________________________________________________________________
52  *
53  */
54
55 void Services_ShowServiceLog (LPIDENT lpi)
56 {
57    LPSVC_VIEWLOG_PACKET lpp = New (SVC_VIEWLOG_PACKET);
58    lpp->lpiServer = lpi->GetServer();
59    lpp->lpiService = (lpi && lpi->fIsService()) ? lpi : NULL;
60    lpp->szLocal[0] = TEXT('\0');
61    lpp->szRemote[0] = TEXT('\0');
62    lpp->nDownloadAttempts = 0;
63
64    HWND hDlg = ModelessDialogParam (IDD_SVC_VIEWLOG, NULL, (DLGPROC)Services_ShowLog_DlgProc, (LPARAM)lpp);
65    AfsAppLib_RegisterModelessDialog (hDlg);
66 }
67
68
69 void Services_ShowServerLog (LPIDENT lpiServer, LPTSTR pszRemote)
70 {
71    LPSVC_VIEWLOG_PACKET lpp = New (SVC_VIEWLOG_PACKET);
72    lpp->lpiService = NULL;
73    lpp->lpiServer = lpiServer;
74    lpp->szLocal[0] = TEXT('\0');
75    lpp->nDownloadAttempts = 0;
76
77    if (pszRemote)
78       lstrcpy (lpp->szRemote, pszRemote);
79    else
80       lpp->szRemote[0] = TEXT('\0');
81
82    HWND hDlg = ModelessDialogParam (IDD_SVC_VIEWLOG, NULL, (DLGPROC)Services_ShowLog_DlgProc, (LPARAM)lpp);
83    AfsAppLib_RegisterModelessDialog (hDlg);
84 }
85
86
87 BOOL CALLBACK Services_ShowLog_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
88 {
89    if (AfsAppLib_HandleHelp (IDD_SVC_VIEWLOG, hDlg, msg, wp, lp))
90       return TRUE;
91
92    if (msg == WM_INITDIALOG)
93       SetWindowLong (hDlg, DWL_USER, lp);
94
95    LPSVC_VIEWLOG_PACKET lpp;
96    if ((lpp = (LPSVC_VIEWLOG_PACKET)GetWindowLong (hDlg, DWL_USER)) != NULL)
97       {
98       switch (msg)
99          {
100          case WM_INITDIALOG:
101             if (gr.rViewLog.right == 0)
102                GetWindowRect (hDlg, &gr.rViewLog);
103             ResizeWindow (hDlg, awdShowLog, rwaMoveToHere, &gr.rViewLog);
104
105             Services_ShowLog_TakeNextStep (hDlg, lpp);
106             break;
107
108          case WM_DESTROY:
109             if (lpp->szLocal[0] != TEXT('\0'))
110                DeleteFile (lpp->szLocal);
111             GetWindowRect (hDlg, &gr.rViewLog);
112             SetWindowLong (hDlg, DWL_USER, 0);
113             Delete (lpp);
114             break;
115
116          case WM_SIZE:
117             // if (lp==0), we're minimizing--don't call ResizeWindow().
118             //
119             if (lp != 0)
120                ResizeWindow (hDlg, awdShowLog, rwaFixupGuts);
121             break;
122
123          case WM_ENDTASK:
124             LPTASKPACKET ptp;
125             if ((ptp = (LPTASKPACKET)lp) == NULL)
126                Services_ShowLog_TakeNextStep (hDlg, lpp);
127             else
128                {
129                Services_ShowLog_OnEndTask (hDlg, lpp, ptp);
130                FreeTaskPacket (ptp);
131                }
132             break;
133
134          case WM_COMMAND:
135             switch (LOWORD(wp))
136               {
137               case IDOK:
138               case IDCANCEL:
139                  DestroyWindow (hDlg);
140                  break;
141
142               case IDC_VIEWLOG_SAVEAS:
143                  Services_ShowLog_OnSaveAs (hDlg, lpp);
144                  break;
145               }
146             break;
147
148          case WM_CTLCOLOREDIT:
149             if ((HWND)lp == GetDlgItem (hDlg, IDC_VIEWLOG_TEXT))
150                {
151                SetBkColor ((HDC)wp, GetSysColor (COLOR_WINDOW));
152                return (BOOL)CreateSolidBrush (GetSysColor (COLOR_WINDOW));
153                }
154             break;
155          }
156       }
157
158    return FALSE;
159 }
160
161
162 void Services_ShowLog_TakeNextStep (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp)
163 {
164    if (lpp->szLocal[0] != TEXT('\0'))
165       {
166       Services_ShowLog_OnInitDialog (hDlg, lpp);
167       ShowWindow (hDlg, SW_SHOW);
168       }
169    else if (lpp->szRemote[0] != TEXT('\0'))
170       {
171       LPSVC_VIEWLOG_PACKET lppNew = New (SVC_VIEWLOG_PACKET);
172       *lppNew = *lpp;
173       lpp->nDownloadAttempts++;
174       StartTask (taskSVC_VIEWLOG, hDlg, lppNew);  // downloads log file
175       }
176    else if (lpp->lpiService)
177       {
178       StartTask (taskSVC_FINDLOG, hDlg, lpp->lpiService);  // guesses log name
179       }
180    else
181       {
182       if (!Services_ShowLog_Pick (hDlg, lpp))
183          DestroyWindow (hDlg);
184       else
185          PostMessage (hDlg, WM_ENDTASK, 0, 0); // Services_ShowLog_TakeNextStep
186       }
187 }
188
189
190 void Services_ShowLog_OnEndTask (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp, LPTASKPACKET ptp)
191 {
192    if (ptp->idTask == taskSVC_FINDLOG)  // tried to guess log file name?
193       {
194       if (ptp->rc)
195          {
196          lstrcpy (lpp->szRemote, TASKDATA(ptp)->pszText1);
197          PostMessage (hDlg, WM_ENDTASK, 0, 0); // Services_ShowLog_TakeNextStep
198          }
199       else
200          {
201          if (!Services_ShowLog_Pick (hDlg, lpp))
202             DestroyWindow (hDlg);
203          else
204             PostMessage (hDlg, WM_ENDTASK, 0, 0); // Services_ShowLog_TakeNextStep
205          }
206       }
207    else if (ptp->idTask == taskSVC_VIEWLOG)  // tried to download log file?
208       {
209       if (ptp->rc)
210          {
211          lstrcpy (lpp->szLocal, TASKDATA(ptp)->pszText1);
212          PostMessage (hDlg, WM_ENDTASK, 0, 0); // Services_ShowLog_TakeNextStep
213          }
214       else
215          {
216          if (lpp->lpiService && lpp->nDownloadAttempts==1)
217             {
218             if (!Services_ShowLog_Pick (hDlg, lpp))
219                DestroyWindow (hDlg);
220             else
221                PostMessage (hDlg, WM_ENDTASK, 0, 0); // Services_ShowLog_TakeNextStep
222             }
223          else
224             {
225             TCHAR szServer[ cchNAME ];
226             lpp->lpiServer->GetServerName (szServer);
227             ErrorDialog (ptp->status, IDS_ERROR_VIEW_LOGFILE, TEXT("%s%s"), szServer, lpp->szRemote);
228             DestroyWindow (hDlg);
229             }
230          }
231       }
232 }
233
234
235 void Services_ShowLog_OnInitDialog (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp)
236 {
237    // If we're viewing the log file for a service, record the remote
238    // filename so the user won't ever have to enter it again.
239    //
240    if (lpp->lpiService)
241       {
242       LPSERVICE_PREF lpcp;
243       if ((lpcp = (LPSERVICE_PREF)lpp->lpiService->GetUserParam()) != NULL)
244          {
245          lstrcpy (lpcp->szLogFile, lpp->szRemote);
246          Services_SavePreferences (lpp->lpiService);
247          }
248       }
249
250    // Prepare the ShowLog dialog's static text controls
251    //
252    LPTSTR psz;
253    if (lpp->lpiService)
254       {
255       TCHAR szServer[ cchNAME ];
256       TCHAR szService[ cchNAME ];
257       lpp->lpiService->GetServerName (szServer);
258       lpp->lpiService->GetServiceName (szService);
259       psz = FormatString (IDS_VIEWLOG_FROMSERVICE, TEXT("%s%s"), szServer, szService);
260       }
261    else
262       {
263       TCHAR szServer[ cchNAME ];
264       lpp->lpiServer->GetServerName (szServer);
265       psz = FormatString (IDS_VIEWLOG_FROMSERVER, TEXT("%s"), szServer);
266       }
267    SetDlgItemText (hDlg, IDC_SVC_VIEWLOG_DESC, psz);
268    FreeString (psz);
269
270    TCHAR szText[ cchRESOURCE ];
271    GetDlgItemText (hDlg, IDC_SVC_VIEWLOG_FILENAME, szText, cchRESOURCE);
272    psz = FormatString (szText, TEXT("%s"), lpp->szRemote);
273    SetDlgItemText (hDlg, IDC_SVC_VIEWLOG_FILENAME, psz);
274    FreeString (psz);
275
276    // Read the log file into memory, and chunk its text into the
277    // edit control on the dialog.  If the file is over cchMAXLOG chars
278    // long, only read cchMAXLOG bytes from the end (make sure we start
279    // the read after a carriage return).
280    //
281    HANDLE hFile = CreateFile (lpp->szLocal, GENERIC_READ, 0, NULL,
282                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
283    if (hFile != INVALID_HANDLE_VALUE)
284       {
285       BOOL fTruncated = FALSE;
286       DWORD dwSize = GetFileSize (hFile, NULL);
287       if (dwSize > cchMAXLOG)
288          {
289          // find the first \r\n within the final cchMAXLOG chars of the file
290          //
291          SetFilePointer (hFile, 0-cchMAXLOG, NULL, FILE_END);
292
293          TCHAR ch;
294          DWORD cbRead;
295          while (ReadFile (hFile, &ch, 1, &cbRead, NULL) && cbRead)
296             {
297             if (ch == TEXT('\n'))
298                break;
299             }
300
301          dwSize -= SetFilePointer (hFile, 0, 0, FILE_CURRENT);
302          fTruncated = TRUE;
303          }
304
305       LPTSTR pszLog;
306       if ((pszLog = AllocateString (dwSize)) != NULL)
307          {
308          DWORD cbRead;
309          (void)ReadFile (hFile, pszLog, dwSize, &cbRead, NULL);
310          pszLog[ cbRead ] = TEXT('\0');
311
312          size_t cch = cbRead;
313          while ( cch &&
314                  (pszLog[ cch-1 ] == TEXT('\r')) ||
315                  (pszLog[ cch-1 ] == TEXT('\n')) )
316             {
317             pszLog[ --cch ] = TEXT('\0');
318             }
319
320          SetFocus (GetDlgItem (hDlg, IDC_VIEWLOG_TEXT));
321          SetDlgItemText (hDlg, IDC_VIEWLOG_TEXT, pszLog);
322          SendDlgItemMessage (hDlg, IDC_VIEWLOG_TEXT, EM_LINESCROLL, 0, 0xFFFF);
323          SendDlgItemMessage (hDlg, IDC_VIEWLOG_TEXT, EM_SETSEL, (WPARAM)-1, 0);
324
325          if (fTruncated)
326             {
327             size_t nLines = 1;
328             for (size_t ich = 0; ich < dwSize; ++ich)
329                {
330                if (pszLog[ich] == TEXT('\n'))
331                   ++nLines;
332                }
333
334             psz = FormatString (IDS_VIEWLOG_TRUNCATED, TEXT("%lu"), nLines);
335             SetDlgItemText (hDlg, IDC_SVC_VIEWLOG_CONTENTS, psz);
336             FreeString (psz);
337             }
338
339          FreeString (pszLog);
340          }
341
342       CloseHandle (hFile);
343       }
344 }
345
346
347 void Services_ShowLog_OnSaveAs (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp)
348 {
349    TCHAR szFilter[ cchRESOURCE ];
350    GetString (szFilter, IDS_SAVELOG_FILTER);
351    TCHAR chFilter = szFilter[ lstrlen(szFilter)-1 ];
352    for (LPTSTR pszFilter = szFilter;
353         (*pszFilter) && ((pszFilter = (LPTSTR)lstrchr (pszFilter, chFilter)) != NULL);
354         ++pszFilter)
355       {
356       *pszFilter = TEXT('\0');
357       }
358
359    TCHAR szSaveAs[ MAX_PATH ] = TEXT("");
360
361    OPENFILENAME sfn;
362    memset (&sfn, 0x00, sizeof(sfn));
363    sfn.lStructSize = sizeof(sfn);
364    sfn.hwndOwner = hDlg;
365    sfn.hInstance = THIS_HINST;
366    sfn.lpstrFilter = szFilter;
367    sfn.nFilterIndex = 1;
368    sfn.lpstrFile = szSaveAs;
369    sfn.nMaxFile = MAX_PATH;
370    sfn.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN |
371                OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
372    sfn.lpstrDefExt = TEXT("txt");
373
374    if (GetSaveFileName (&sfn))
375       {
376       TCHAR szzSource[ MAX_PATH+1 ];
377       lstrcpy (szzSource, lpp->szLocal);
378       szzSource[ lstrlen(szzSource)+1 ] = TEXT('\0');
379
380       TCHAR szzTarget[ MAX_PATH+1 ];
381       lstrcpy (szzTarget, szSaveAs);
382       szzTarget[ lstrlen(szzTarget)+1 ] = TEXT('\0');
383
384       SHFILEOPSTRUCT op;
385       memset (&op, 0x00, sizeof(op));
386       op.hwnd = hDlg;
387       op.wFunc = FO_COPY;
388       op.pFrom = szzSource;
389       op.pTo = szzTarget;
390       op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
391       SHFileOperation (&op);
392       }
393 }
394
395
396 BOOL Services_ShowLog_Pick (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp)
397 {
398    if (ModalDialogParam (IDD_SVC_LOGNAME, NULL, (DLGPROC)Services_PickLog_DlgProc, (LPARAM)lpp) != IDOK)
399       {
400       return FALSE;
401       }
402
403    if (lpp->szRemote[0] == TEXT('\0'))
404       {
405       return FALSE;
406       }
407
408    return TRUE;
409 }
410
411
412 BOOL CALLBACK Services_PickLog_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
413 {
414    if (AfsAppLib_HandleHelp (IDD_SVC_LOGNAME, hDlg, msg, wp, lp))
415       return TRUE;
416
417    if (msg == WM_INITDIALOG)
418       SetWindowLong (hDlg, DWL_USER, lp);
419
420    LPSVC_VIEWLOG_PACKET lpp;
421    if ((lpp = (LPSVC_VIEWLOG_PACKET)GetWindowLong (hDlg, DWL_USER)) != NULL)
422       {
423       switch (msg)
424          {
425          case WM_INITDIALOG:
426             Services_PickLog_OnInitDialog (hDlg, lpp);
427             break;
428
429          case WM_COMMAND:
430             switch (LOWORD(wp))
431                {
432                case IDOK:
433                   GetDlgItemText (hDlg, IDC_VIEWLOG_FILENAME, lpp->szRemote, MAX_PATH);
434                case IDCANCEL:
435                   EndDialog (hDlg, LOWORD(wp));
436                   break;
437                }
438             break;
439
440          case WM_ENDTASK:
441             LPTASKPACKET ptp;
442             if ((ptp = (LPTASKPACKET)lp) != NULL)
443                {
444                if (ptp->idTask == taskSVR_ENUM_TO_COMBOBOX)
445                   EnableWindow (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER), TRUE);
446                FreeTaskPacket (ptp);
447                }
448             break;
449
450          case WM_NOTIFY: 
451             switch (((LPNMHDR)lp)->code)
452                { 
453                case FLN_ITEMSELECT:
454                   if (IsWindowEnabled (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER)))
455                      {
456                      LPIDENT lpi;
457                      if ((lpi = (LPIDENT)FL_GetSelectedData (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER))) != NULL)
458                         lpp->lpiServer = lpi;
459                      }
460                   break;
461                }
462             break;
463          }
464       }
465
466    return FALSE;
467 }
468
469
470 void Services_PickLog_OnInitDialog (HWND hDlg, LPSVC_VIEWLOG_PACKET lpp)
471 {
472    SetDlgItemText (hDlg, IDC_VIEWLOG_FILENAME, lpp->szRemote);
473    EnableWindow (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER), FALSE);
474
475    if (lpp->lpiService)
476       {
477       TCHAR szServer[ cchNAME ];
478       TCHAR szService[ cchNAME ];
479       lpp->lpiService->GetServerName (szServer);
480       lpp->lpiService->GetServiceName (szService);
481
482       LPTSTR pszText = FormatString (IDS_VIEWLOG_DESC_NOFILE, TEXT("%s%s"), szServer, szService);
483       SetDlgItemText (hDlg, IDC_VIEWLOG_DESC, pszText);
484       FreeString (pszText);
485
486       CB_StartChange (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER), TRUE);
487       CB_AddItem (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER), szServer, (LPARAM)(lpp->lpiServer));
488       CB_EndChange (GetDlgItem (hDlg, IDC_VIEWLOG_SERVER), (LPARAM)(lpp->lpiServer));
489       }
490    else
491       {
492       LPSVR_ENUM_TO_COMBOBOX_PACKET lpEnum = New (SVR_ENUM_TO_COMBOBOX_PACKET);
493       lpEnum->hCombo = GetDlgItem (hDlg, IDC_VIEWLOG_SERVER);
494       lpEnum->lpiSelect = lpp->lpiServer;
495       StartTask (taskSVR_ENUM_TO_COMBOBOX, hDlg, lpEnum);
496       }
497
498    PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_VIEWLOG_FILENAME), TRUE);
499 }
500