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