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