windows-misc-20050102
[openafs.git] / src / WINNT / afssvrcfg / partitions_page.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 extern "C" {
15 #include <afs/param.h>
16 #include <afs/stds.h>
17 }
18
19 #include "afscfg.h"
20 #include "resource.h"
21 #include "create_partition_dlg.h"
22 #include "partition_utils.h"
23 #include "salvage_results_dlg.h"
24 extern "C" {
25 #include <afs\afs_vosAdmin.h>
26 #include <afs\afs_clientAdmin.h>
27 }
28
29
30 // TODO:  Add context menu to fastlist
31
32
33 /*
34  * DEFINITIONS _________________________________________________________________
35  *
36  */
37 #define MAX_PARTITIONS  26
38
39 static HWND hDlg = 0;
40 static HWND hPartitionList = 0;
41 static HLISTITEM hSelectedItem;
42
43 static TCHAR szYes[cchRESOURCE];
44 static TCHAR szNo[cchRESOURCE];
45
46 static const UINT DISK_DRIVE_IMAGE = 0;
47 //static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
48 //static const UINT DISK_DRIVE_WITH_WARNING_IMAGE = 2;
49
50 // Remember the config state of the FS so we can detect when it changes.
51 // When it changes we must redisplay the partition info.
52 static CONFIG_STATE configFS;
53
54
55
56 /*
57  * PROTOTYPES _________________________________________________________________
58  *
59  */
60 BOOL ShowSalvageDlg(HWND hParent, LPCTSTR pszPartitionName);
61
62 static void OnCreatePartitions();
63 static void OnInitDialog(HWND hwndDlg);
64 static void SetupListCols();
65 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags = FLCF_JUSTIFY_LEFT);
66 static void ShowPartitions();
67 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries);
68 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions);
69 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms);
70 static void SetupImageLists();
71 static void OnRemove();
72 static BOOL CheckShowPartitions();
73 static void OnSalvage();
74 static void CheckEnableSalvage();
75
76
77 /*
78  * EXPORTED FUNCTIONS _________________________________________________________________
79  *
80  */
81 /*
82  * Dialog Proc _________________________________________________________________
83  *
84  */
85 BOOL CALLBACK PartitionsPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
86 {
87         if (AfsAppLib_HandleHelp(IDD_PARTITIONS_PAGE, hwndDlg, uMsg, wParam, lParam))
88                 return TRUE;
89
90         switch (uMsg) {
91                 case WM_INITDIALOG:     OnInitDialog(hwndDlg);
92                                                         break;
93         
94                 case WM_COMMAND:        switch (LOWORD(wParam)) {
95                                                                 case IDINIT:            CheckShowPartitions();
96                                                                                                         break;
97
98                                                                 case IDC_CREATE_PARTITIONS:     
99                                                                                                         OnCreatePartitions();
100                                                                                                         break;
101                                                         
102                                                                 case IDC_REMOVE:        OnRemove();
103                                                                                                         break;
104
105                                                                 case IDC_SALVAGE:       OnSalvage();
106                                                                                                         break;
107                                                         }
108                                                         break;
109
110                 case WM_NOTIFY:         if ((((LPNMHDR)lParam)->code) == FLN_ITEMSELECT)
111                                                                 OnListSelection((LPFLN_ITEMSELECT_PARAMS)lParam);
112                                                         break;
113         }
114
115         return FALSE;
116 }
117
118 void UpdatePartitionList()
119 {
120         ShowPartitions();
121         CheckEnableSalvage();
122 }
123
124
125 /*
126  * STATIC FUNCTIONS _________________________________________________________________
127  *
128  */
129
130 /*
131  * Event Handler Functions _________________________________________________________________
132  *
133  */
134 static void OnInitDialog(HWND hwndDlg)
135 {
136         hDlg = hwndDlg;
137
138 //      PropSheet_CancelToClose(GetParent(hDlg));
139
140         hSelectedItem = 0;
141
142         hPartitionList = GetDlgItem(hDlg, IDC_PARTITION_LIST);
143         _ASSERTE(hPartitionList);
144
145         SetupImageLists();
146
147         GetString(szYes, IDS_YES);
148         GetString(szNo, IDS_NO);
149
150         SetupListCols();
151
152         configFS = g_CfgData.configFS;
153
154         ShowPartitions();
155
156         CheckEnableSalvage();
157 }
158
159 static void OnCreatePartitions()
160 {
161         if (CreatePartition(hDlg))
162                 ShowPartitions();
163 }
164
165 static void OnListSelection(LPFLN_ITEMSELECT_PARAMS pItemParms)
166 {
167         ASSERT(pItemParms);
168
169         hSelectedItem = pItemParms->hItem;
170
171         ENABLE_STATE es = pItemParms->hItem ? ES_ENABLE : ES_DISABLE;
172
173         SetEnable(hDlg, IDC_REMOVE, es);
174         SetEnable(hDlg, IDC_REMOVE_MSG, es);
175 }
176
177 static void OnRemove()
178 {
179         ASSERT(hSelectedItem);
180         ASSERT(g_hServer);
181         
182         afs_status_t nStatus;
183
184         BOOL bExported = (BOOL)FastList_GetItemParam(hPartitionList, hSelectedItem);
185         if (bExported) {
186                 MsgBox(hDlg, IDS_CANT_DELETE_EXPORTED_PARTITION, GetAppTitleID(), MB_OK | MB_ICONSTOP);
187                 return;
188         }
189
190         LPCTSTR pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
191         ASSERT(pszPartitionName);
192
193         int nResult = Message(MB_ICONQUESTION | MB_YESNO, GetAppTitleID(), IDS_DELETE_PARTITION_PROMPT, TEXT("%s"), pszPartitionName);
194         if (nResult == IDNO)
195                 return;
196
197         g_LogFile.Write("Removing partition '%s'.\r\n", (char *)S2A(pszPartitionName));
198         nResult = cfg_HostPartitionTableRemoveEntry(g_hServer, S2A(pszPartitionName), &nStatus);
199         if (!nResult) {
200                 ShowError(hDlg, nStatus, IDS_REMOVE_PARTITION_ERROR);
201                 return;
202         }
203
204         FastList_RemoveItem(hPartitionList, hSelectedItem);
205
206         CheckEnableSalvage();
207 }
208
209 static void OnSalvage()
210 {
211     // Can't salvage if the file server is not configured
212     if (!Configured(g_CfgData.configFS)) {
213         ShowError(hDlg, 0, IDS_CANT_SALVAGE_WHEN_FS_NOT_CONFIGURED);
214         return;
215     }
216
217         LPCTSTR pszPartitionName = TEXT("");
218
219         if (hSelectedItem) {
220                 pszPartitionName = FastList_GetItemText(hPartitionList, hSelectedItem, 0);
221                 ASSERT(pszPartitionName);
222         }       
223
224         if (!ShowSalvageDlg(hDlg, pszPartitionName))
225         return;
226
227     ShowSalvageResults(hDlg);
228
229     // Since a salvage was performed, there may be partitions exported that were
230     // not exported before the salvage.  Salvage may stop and restart the file
231     // server, which will pick up the previously unexported partitions.  We will
232     // update our partition list in case this has happened.
233     UpdatePartitionList();
234 }
235
236
237 /*
238  * Utility Functions _________________________________________________________________
239  *
240  */
241 static BOOL CheckShowPartitions()
242 {
243         if (configFS != g_CfgData.configFS) {
244                 configFS = g_CfgData.configFS;
245         UpdatePartitionList();
246                 return TRUE;
247         }
248
249         return FALSE;
250 }
251
252 static void SetupImageLists()
253 {
254         HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
255
256         AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
257         AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
258
259         FastList_SetImageLists(hPartitionList, hiList, 0);
260 }
261
262 static void AddColumn(int nWidth, LPCTSTR pszTitle, DWORD dwFlags)
263 {
264         static int nCol = 1;
265         FASTLISTCOLUMN col;
266         
267         col.dwFlags = dwFlags;
268         col.cxWidth = nWidth;
269         lstrcpy(col.szText, pszTitle);
270         
271         FastList_SetColumn(hPartitionList, nCol++, &col);
272 }
273
274 static void SetupListCols()
275 {
276         TCHAR szMsg[cchRESOURCE];
277
278         AddColumn(75, GetResString(IDS_NAME, szMsg));
279         AddColumn(55, GetResString(IDS_DRIVE, szMsg));
280         AddColumn(60, GetResString(IDS_EXPORTED, szMsg));
281         AddColumn(75, GetResString(IDS_TOTAL, szMsg), FLCF_JUSTIFY_RIGHT);
282         AddColumn(75, GetResString(IDS_FREE, szMsg), FLCF_JUSTIFY_RIGHT);
283 }
284
285 cfg_partitionEntry_t *GetPartitionTableFromRegistry(int& cEntries)
286 {
287         afs_status_t nStatus;
288  
289         // Read the parition table out of the registry
290         int nResult = ReadPartitionTable(&nStatus);
291         if (!nResult) {
292                 ShowError(hDlg, nStatus, IDS_READ_PARTITIONS_ERROR);
293                 return 0;
294         }
295
296         return GetPartitionTable(cEntries);
297 }
298
299 static vos_partitionEntry_t *GetPartitionTableFromVos(int &nNumPartitions)
300 {
301         ASSERT(g_hCell);
302         ASSERT(g_CfgData.szHostname[0]);
303
304         nNumPartitions = 0;
305
306         if (g_CfgData.configFS != CS_ALREADY_CONFIGURED)
307                 return 0;
308
309         static vos_partitionEntry_t aPartitions[MAX_PARTITIONS];
310         afs_status_t nStatus, nIgnore;
311         void *hServer = 0;
312         int nNumParts = 0;
313
314         // Open this server
315         g_LogFile.Write("Opening server %s.\r\n", GetHostnameA());
316         int nResult = vos_ServerOpen(g_hCell, GetHostnameA(), &hServer, &nStatus);
317         if (nResult) {
318                 
319                 // Read the partition info
320                 g_LogFile.Write("Reading paritition information for this server.\r\n");
321                 void *iterID;
322
323                 nResult = vos_PartitionGetBegin(g_hCell, hServer, 0, &iterID, &nStatus);
324                 if (nResult) {
325                         while (nNumParts < MAX_PARTITIONS) {
326                                 nResult = vos_PartitionGetNext(iterID, &aPartitions[nNumParts], &nStatus);
327                                 if (!nResult) {
328                                         if (nStatus == ADMITERATORDONE) {
329                                                 nResult = 1;
330                                                 nStatus = 0;
331                                         }
332                                         break;
333                                 }
334
335                                 nNumParts++;
336                         }
337                         vos_PartitionGetDone(iterID, &nIgnore);
338                 }
339                 vos_ServerClose(hServer, &nIgnore);
340         }
341         
342         if (!nResult) {
343                 ShowError(hDlg, nStatus, IDS_GET_PARTITION_LIST_ERROR);
344                 return 0;
345         }
346
347         nNumPartitions = nNumParts;
348
349         return aPartitions;
350 }
351
352 // Convert a disk space value in Kbytes into a string
353 static LPTSTR DiskSpaceToString(int nSpace)
354 {
355         const float oneMB = 1024;       // in K bytes
356         const double oneGB = oneMB * 1024;
357         const double oneTB = oneGB * 1024;
358
359         static TCHAR szSpace[64];
360         double space;
361         LPTSTR pszUnits;
362
363         space = nSpace; 
364
365         if (space >= oneTB) {
366                 space /= oneTB;
367                 pszUnits = TEXT(" TB");
368         } else if (space >= oneGB) {
369                 space /= oneGB;
370                 pszUnits = TEXT(" GB");
371     } else if (space >= oneMB) {
372                 space /= oneMB;
373                 pszUnits = TEXT(" MB");
374         } else
375                 pszUnits = TEXT(" KB");
376
377         int nNumDecimals = 0;
378         if (space - double(int(space)) > 0)
379                 nNumDecimals = 2;
380
381         _stprintf(szSpace, TEXT("%3.*f%s"), nNumDecimals, space, pszUnits);
382
383         return szSpace;
384 }
385
386 static void ShowPartitions()
387 {
388         FastList_RemoveAll(hPartitionList);
389
390         int cRegParts = 0, cVosParts = 0;
391
392     // If we got nothing from the registry, then leave the list empty
393         cfg_partitionEntry_t *pRegParts = GetPartitionTableFromRegistry(cRegParts);
394     if (!pRegParts)
395         return;
396
397     // If we failed to get vos info, then only show the registry info
398         vos_partitionEntry_t *pVosParts = GetPartitionTableFromVos(cVosParts);
399     if (!pVosParts)
400         cVosParts = 0;
401
402         // We have two partition tables, one from the registry and one from the vos
403         // library.  The one from the vos library tells us the partitions that are
404         // currently exported.  The one from the registry tells us the partitions
405         // that will be exported after the file server restarts.  The registry list
406         // should always be at least as big as the vos list.  The vos list can be
407         // smaller if one of the disks could not be exported.  To add a new partition,
408         // an entry must be added to the registry table and then the file server must
409         // be restarted.  To remove an entry, the partition must not be exported (due
410         // to an error) or the file server must not be running, in which case nothing
411         // will be exported.
412
413         // To display the partitions to the user, we use the list from the registry,
414         // looking up each of its entries in the vos list to see if it is exported,
415         // and if it is, to get its size info.
416
417
418         for (int nCurRegPart = 0; nCurRegPart < cRegParts; nCurRegPart++) {
419         LPTSTR pPartNameAsString = AnsiToString(pRegParts[nCurRegPart].partitionName);
420
421         // Show the partition in the list
422                 FASTLISTADDITEM ai = { 0, DISK_DRIVE_IMAGE, IMAGE_NOIMAGE, pPartNameAsString, 0, 0 };
423                 HLISTITEM hItem = FastList_AddItem(hPartitionList, &ai);
424
425         FreeString(pPartNameAsString);
426
427                 FastList_SetItemText(hPartitionList, hItem, 1, pRegParts[nCurRegPart].deviceName);
428                 
429                 // For the rest of the info we need to know if this guy is exported.
430                 // Look him up in the vos table.
431                 BOOL bExported = FALSE;
432                 int nTotalSpace = 0;
433                 int nFreeSpace = 0;
434                 
435                 for (int nCurVosPart = 0; nCurVosPart < cVosParts; nCurVosPart++) {
436                         if (stricmp(pVosParts[nCurVosPart].name, pRegParts[nCurRegPart].partitionName) == 0) {
437                                 bExported = TRUE;
438                                 nTotalSpace = pVosParts[nCurVosPart].totalSpace;
439                                 nFreeSpace = pVosParts[nCurVosPart].totalFreeSpace;
440                                 break;
441                         }
442                 }
443
444                 FastList_SetItemText(hPartitionList, hItem, 2, bExported ? szYes : szNo);
445                 FastList_SetItemText(hPartitionList, hItem, 3, bExported ? DiskSpaceToString(nTotalSpace) : TEXT(""));
446                 FastList_SetItemText(hPartitionList, hItem, 4, bExported ? DiskSpaceToString(nFreeSpace) : TEXT(""));
447                 
448                 // Set the item param to indicate that this partition is exported or not
449                 FastList_SetItemParam(hPartitionList, hItem, bExported);
450         
451         
452     }
453 }
454
455 static void CheckEnableSalvage()
456 {
457         ENABLE_STATE es = (FastList_GetItemCount(hPartitionList) > 0) ? ES_ENABLE : ES_DISABLE;
458
459         SetEnable(hDlg, IDC_SALVAGE, es);
460         SetEnable(hDlg, IDC_SALVAGE_MSG, es);
461 }
462