rx: Remove RX_CALL_BUSY
[openafs.git] / src / WINNT / afssvrcfg / salvage_results_dlg.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 /*
11  * INCLUDES ___________________________________________________________________
12  *
13  */
14 #include <winsock2.h>
15 #include <ws2tcpip.h>
16
17 extern "C" {
18 #include <afsconfig.h>
19 #include <afs/param.h>
20 #include <roken.h>
21 }
22
23 #include "afscfg.h"             // Main header for this application
24 #include "resource.h"
25 #include "salvage_results_dlg.h"
26 extern "C" {
27 #include <afs\afs_bosAdmin.h>
28 }
29
30
31 /*
32  * DEFINITIONS _________________________________________________________________
33  *
34  */
35 static const int     UPDATE_INTERVAL        = 5000;             // milleseconds
36 static const int     LOG_BUF_SIZE           = 25000;            // bytes
37 static const int     EDIT_CONTROL_MAX_CHARS = 64000;            // Max chars an edit control can hold
38 static const char   *SALVAGE_LOG_FILE_NAME  = "SalvageLog.txt";
39
40 static rwWindowData arwDialog[] = {
41         { IDC_LOG,      raSizeX | raSizeY,      MAKELONG(350, 150), 0 },
42         { IDC_CLOSE,    raMoveX | raMoveY,      0,      0 },
43         { 9,            raMoveX | raMoveY,      0,      0 },
44         { idENDLIST,    0,                      0,      0 }
45 };
46
47
48 /*
49  * Variables _________________________________________________________________
50  *
51  */
52 static HWND hDlg = 0;                                           // HWND for this page's dialog
53 static HWND hLogo;
54 static afs_status_t nStatus;
55 static void *hServer;
56 static int nResult;
57 static BOOL bSalvageComplete;
58
59
60 /*
61  * PROTOTYPES _________________________________________________________________
62  *
63  */
64 static void OnInitDialog(HWND hwndDlg);
65 static void OnClose();
66 static void SetMessages(int nStatusMsgID, int nLogMsgID);
67 static DWORD WINAPI ShowResults(LPVOID param);
68 static void SaveLogToDisk(char *pszLogBuf, char *pszFileName);
69 static char *AddCarriageReturnsToLog(char *pszInBuf, char *&pszOutBuf);
70 static char *GetMaxPartOfLogWeCanShow(char *pszLogBuf);
71 static BOOL AllocMemory(char *&pszLogBuf, int nBufSize);
72
73 BOOL CALLBACK SalvageResultsDlgProc(HWND hRHS, UINT msg, WPARAM wp, LPARAM lp);
74
75
76 /*
77  * EXPORTED FUNCTIONS _________________________________________________________
78  *
79  */
80 BOOL ShowSalvageResults(HWND hParent)
81 {
82     int nResult = ModalDialog(IDD_SALVAGE_RESULTS, hParent, (DLGPROC)SalvageResultsDlgProc);
83
84     return (nResult == IDOK);
85 }
86
87
88 /*
89  * Dialog Proc _________________________________________________________________
90  *
91  */
92 BOOL CALLBACK SalvageResultsDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp)
93 {
94     if (AfsAppLib_HandleHelp(IDD_SALVAGE_RESULTS, hwndDlg, msg, wp, lp))
95         return TRUE;
96
97     switch (msg) {
98     case WM_INITDIALOG:
99         OnInitDialog(hwndDlg);
100         break;
101
102     case WM_COMMAND:
103         switch (LOWORD(wp)) {
104         case IDC_CLOSE:
105             OnClose();
106             break;
107
108         case IDCANCEL:
109             if (bSalvageComplete)
110                 OnClose();
111         }
112         break;
113
114     case WM_SIZE:
115         if (lp != 0)
116             ResizeWindow(hwndDlg, arwDialog, rwaFixupGuts);
117         break;
118     }
119
120     return FALSE;
121 }
122
123
124 /*
125  * STATIC FUNCTIONS _________________________________________________________________
126  *
127  */
128
129 /*
130  * Event Handler Functions __________________________________________________________
131  *
132  */
133 static void OnInitDialog(HWND hwndDlg)
134 {
135     hDlg = hwndDlg;
136
137     bSalvageComplete = FALSE;
138
139     ResizeWindow(hDlg, arwDialog, rwaFixupGuts);
140
141     hLogo = GetDlgItem(hDlg, IDC_LOGO);
142
143     AfsAppLib_StartAnimation(hLogo, 8);
144
145     SetMessages(IDS_SALVAGING, IDS_CURRENT_SALVAGE_LOG);
146
147     nResult = bos_ServerOpen(g_hCell, GetHostnameA(), &hServer, &nStatus);
148     if (!nResult) {
149         ShowError(hDlg, nStatus, IDS_BOS_OPEN_FAILED);
150         return;
151     }
152
153     // Remove the start menu - we do this so the user can't close
154     // the dialog while salvage is being performed.
155     DWORD dw;
156     dw = GetWindowLong(hDlg, GWL_STYLE);
157     dw &= ~WS_SYSMENU;
158     SetWindowLong(hDlg, GWL_STYLE, dw);
159
160     // Create a thread to keep the view of the log up to date
161     DWORD dwThreadID;
162     HANDLE hThread = CreateThread(0, 0, ShowResults, 0, 0, &dwThreadID);
163     CloseHandle(hThread);
164 }
165
166 static void OnClose()
167 {
168     bos_ServerClose(hServer, &nStatus);
169
170     EndDialog(hDlg, IDOK);
171 }
172
173
174 /*
175  * Utility Functions _________________________________________________________________
176  *
177  */
178 static void SetMessages(int nStatusMsgID, int nLogMsgID)
179 {
180     TCHAR szMsgBuf[cchRESOURCE];
181
182     SetDlgItemText(hDlg, IDC_SALVAGE_STATUS, GetResString(nStatusMsgID, szMsgBuf));
183     SetDlgItemText(hDlg, IDC_LOG_TITLE, GetResString(nLogMsgID, szMsgBuf));
184 }
185
186 static char *AddCarriageReturnsToLog(char *pszInBuf, char *& pszOutBuf)
187 {
188     ASSERT(pszInBuf);
189
190     char *pInBuf = pszInBuf;
191
192     // How man new lines are there?
193     int nNumNLs = 0;
194
195     while (*pInBuf) {
196         if (*pInBuf == '\n')
197             nNumNLs++;
198         pInBuf++;
199     }
200
201     // Allocate enough memory for the log buffer plus CRs plus a NULL
202     if (!AllocMemory(pszOutBuf, strlen(pszInBuf) + nNumNLs + 1))
203         return 0;
204
205     // Copy over the whole buffer, adding \r's as we go.  The edit control
206     // seems to need \r before \n, so we set it up that way.
207     pInBuf = pszInBuf;
208     char *pOutBuf = pszOutBuf;
209
210     while (*pInBuf) {
211         if (*pInBuf == '\n') {
212             *pOutBuf++ = '\r';
213             *pOutBuf++ = '\n';
214         } else
215             *pOutBuf++ = *pInBuf;
216
217         pInBuf++;
218     }
219
220     *pOutBuf = 0;
221
222     return pszOutBuf;
223 }
224
225 static char *GetMaxPartOfLogWeCanShow(char *pszLogBuf)
226 {
227     ASSERT(pszLogBuf);
228
229     // Find out how much of the log buffer is in use
230     int nLen = strlen(pszLogBuf);
231
232     if (nLen < EDIT_CONTROL_MAX_CHARS)
233         return pszLogBuf;
234
235     // Buffer is bigger than maximum, so find the last full line
236     // under the limit and return it.
237     char *psz = pszLogBuf + nLen - EDIT_CONTROL_MAX_CHARS;
238
239     // Make sure we return the beginning of a line
240     while (*psz && (*psz != '\n'))
241         psz++;
242
243     if (*psz == '\n')
244         psz++;
245
246     return psz;
247 }
248
249 static BOOL AllocMemory(char *&pszLogBuf, int nBufSize)
250 {
251     if (pszLogBuf)
252         delete pszLogBuf;
253
254     pszLogBuf = new char[nBufSize];
255
256     if (!pszLogBuf) {
257         g_LogFile.Write("Failed to allocate memory (%d bytes) for the salvage log buffer.\r\n", nBufSize);
258         return FALSE;
259     }
260
261     return TRUE;
262 }
263
264 static void SaveLogToDisk(char *pszLogBuf, char *pszFileName)
265 {
266     // If no log file was specified by the user, then do nothing
267     if (!pszFileName[0])
268         return;
269
270     FILE *fp = fopen(pszFileName, "w");
271     if (!fp) {
272         ShowError(hDlg, 0, IDS_ERROR_SAVING_SALVAGE_LOG_TO_DISK);
273         return;
274     }
275
276     fprintf(fp, "%s", pszLogBuf);
277
278     fclose(fp);
279 }
280
281 static DWORD WINAPI ShowResults(LPVOID param)
282 {
283     ULONG nBufSize = LOG_BUF_SIZE;
284     char *pszLogBuf = 0;
285     char *pszLogBufWithCRs = 0;
286     DWORD dwWait = WAIT_TIMEOUT;
287     DWORD rc = 1;
288     ULONG nLogSize = LOG_BUF_SIZE;
289
290     if (!AllocMemory(pszLogBuf, nBufSize))
291         return 0;
292
293     while (dwWait != WAIT_OBJECT_0) {
294         // Wait for either the salvage thread to terminate or our update
295         // interval to pass.
296         dwWait = WaitForSingleObject(g_CfgData.hSalvageThread, UPDATE_INTERVAL);
297
298         // In either case, update the log display for the user
299
300         // Get the salvage log as it currently exists
301       getlog:
302         nResult = bos_LogGet(hServer, "SalvageLog", &nLogSize, pszLogBuf, &nStatus);
303         if (!nResult) {
304             if (nStatus == ADMMOREDATA) {
305                 // If salvage isn't done, then get a bigger buffer than we need to
306                 // prevent future ADMMOREDATA errors.
307                 nBufSize = nLogSize;
308                 if (dwWait != WAIT_OBJECT_0) {
309                     nBufSize += LOG_BUF_SIZE;
310                     nLogSize = nBufSize;
311                 }
312                 if (AllocMemory(pszLogBuf, nBufSize))
313                     goto getlog;
314             }
315
316             rc = 0;
317             break;
318         }
319
320         // NULL-terminate the log
321         pszLogBuf[nLogSize] = 0;
322
323         // The edit control that we use to show the log to the user needs \r\n at the end
324         // of each line, but the salvage log only has \n.  We must replace the \n with
325         // \r\n before showing the log.
326         if (!AddCarriageReturnsToLog(pszLogBuf, pszLogBufWithCRs)) {
327             rc = 0;
328             break;
329         }
330
331         // The edit control has a limit to the number of characters it can hold.  If the log
332         // is bigger than that limit, then we will show the maximum portion of the end of the
333         // log that we can fit in the edit control.
334         char *pszLogToShow = GetMaxPartOfLogWeCanShow(pszLogBufWithCRs);
335
336         // Put it into the edit control so the user can see it
337         SetDlgItemText(hDlg, IDC_LOG, A2S(pszLogToShow));
338     }
339
340     AfsAppLib_StopAnimation(hLogo);
341
342     if (rc) {
343         SetMessages(IDS_SALVAGE_COMPLETE, IDS_FINAL_SALVAGE_LOG);
344         SaveLogToDisk(pszLogBufWithCRs, GetSalvageLogFileNameA());
345         MsgBox(hDlg, IDS_SALVAGE_COMPLETE, GetAppTitleID(), MB_OK);
346     } else {
347         SetMessages(IDS_SALVAGING, IDS_CANT_GET_SALVAGE_LOG);
348         ShowError(hDlg, nStatus, IDS_CANT_GET_SALVAGE_LOG);
349     }
350
351     CloseHandle(g_CfgData.hSalvageThread);
352
353     if (pszLogBuf)
354         delete pszLogBuf;
355
356     if (pszLogBufWithCRs)
357         delete pszLogBufWithCRs;
358
359     SetEnable(hDlg, IDC_CLOSE);
360
361     bSalvageComplete = TRUE;
362
363     return rc;
364 }
365