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