2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * INCLUDES _________________________________________________________________
18 #include <afsconfig.h>
19 #include <afs/param.h>
26 #include "cfg_utils.h"
28 #include <afs\afs_vosAdmin.h>
29 #include <afs\afs_bosAdmin.h>
30 #include <afs\afs_clientAdmin.h>
31 #include <afs\afsint.h>
32 #include <afs\volser.h>
33 #include <afs\dirpath.h>
34 #include <WINNT\afsreg.h>
35 #include <afs\smb_iocons.h>
36 #include <afs\pioctl_nt.h>
40 #include "get_pw_dlg.h"
43 #include "get_cur_config.h"
47 * PROTOTYPES _________________________________________________________________
50 static void OnInitDialog(HWND hwndDlg);
51 static void SetupConfigSteps();
52 static void OnConfig();
53 static DWORD WINAPI ConfigServer(LPVOID param);
54 static BOOL CheckCancel();
55 static void ShowCurrentStep(UINT uiMsgID);
56 static void ShowCurrentStep(TCHAR *pszMsg);
57 static void InitProgressBar();
58 static BOOL CheckResult(int nResult, int nStatus);
59 static BOOL VosOpenServer();
60 static void VosCloseServer();
61 static BOOL ConfigPartition();
62 static BOOL DefineCellForServer();
63 static BOOL DefineCellForClient();
64 static BOOL StartBosServer();
65 static BOOL StartAuthServer();
66 static BOOL CreatePrincipalAndKey();
67 static BOOL StartDbServers();
68 static BOOL CreateAdminPrincipal();
69 static BOOL StartFsVlAndSalvager();
70 static BOOL ConfigSCC();
71 static BOOL ConfigSCS();
72 static BOOL CreateRootAfs();
73 static BOOL StartClient();
74 static BOOL SetRootAcl();
75 static BOOL CreateRootCell();
76 static BOOL MountRootCellStandard();
77 static BOOL SetRootCellAcl();
78 static BOOL MountRootCellRW();
79 static BOOL Replicate();
80 static BOOL EnableAuthChecking();
81 static BOOL UpgradeLibHandles();
82 static BOOL RestartServers();
83 static BOOL AddToCellServDB();
84 static BOOL RemoveFromCellServDB();
85 static BOOL UpdateCellServDB(BOOL bAdding);
86 static BOOL RestartAllDbServers();
87 static BOOL UnconfigDB();
88 static BOOL UnconfigBak();
89 static BOOL UnconfigFS();
90 static BOOL UnconfigSCS();
91 static BOOL UnconfigSCC();
92 static BOOL PostConfig();
93 static void ShowConfigControls(BOOL bShow = TRUE);
94 static void UpdateConfigProgress(int nStepNum);
95 static void ShowTitle();
96 static void ViewLog();
97 static void ShowConfigFailedMsg();
98 static BOOL Unconfiguring();
99 static BOOL GetCellServDB(char **ppszCellServDB);
100 static BOOL FreeCellServDB();
101 static char *GetVicepName();
102 static void ShowViewLogButton();
103 static BOOL CreateRootAfsDriveMapping();
104 static BOOL StopClient();
105 static BOOL GetRootVolumeInfo();
107 BOOL CALLBACK ConfigServerPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
111 * DEFINITIONS _________________________________________________________________
114 #define QUORUM_WAIT_TIMEOUT 3 * 60 // 3 minutes in seconds
115 #define ROOT_VOLUMES_QUOTA 5000 // k bytes
116 #define RX_TIMEOUT 15 * 1000 // 15 seconds in milleseconds
117 #define CELLSERVDB_UPDATE_TIMEOUT RX_TIMEOUT * 2
118 #define INVALID_PARTITION_ID (UINT)VOLMAXPARTS + 1
119 #define CLIENT_START_TIMEOUT 2 * 60 // 2 minutes in seconds
120 #define CLIENT_STOP_TIMEOUT 3 * 60 // 2 minutes in seconds
123 // The code below is used in so many places that I decided to put it
124 // into macros so that the main line of the code would be easier to follow.
125 #define CHECK_CANCEL if (CheckCancel()) return FALSE
126 #define CHECK_RESULT if (!CheckResult(m_nResult, m_nStatus)) return FALSE
128 #define IF_WIZ(x) { if (g_pWiz) (x); }
131 static HWND m_hDlg = 0; // Window handle of this dialog
132 static BOOL m_bConfiguring = FALSE; // TRUE if configuring
133 static BOOL m_bConfigured = FALSE; // TRUE if configuration was successful
134 static BOOL m_bConfigFailed = FALSE; // TRUE if configuration failed
135 static BOOL m_bCheckCancel = FALSE; // TRUE if user pressed cancel - we will ask for confirmation
136 static BOOL m_bCancel = FALSE; // TRUE if user confirmed cancel - we will cancel configuration
137 static void* m_hvosServer = 0; // vos library server handle
138 static const int MAX_STEPS = 34; // Max number of config steps
139 static afs_status_t m_nStatus; // Error code if a cfg library function fails
140 static int m_nResult; // Boolean return code from cfg library calls
141 static int m_nNumSteps; // Number of config steps that will be performed
142 static BOOL m_bDbServersRestarted; // TRUE if all Database servers were restarted
143 static BOOL m_bMustChangeClientCell; // TRUE if client is in different cell than server
144 static HANDLE m_hCellServDBUpdateEvent;
145 static LPCTSTR m_pszCellServDBUpdateEventName = TEXT("CellServDBUpdateEvent");
146 static const int m_CallBackID = 6;
147 static UINT m_nPartitionID = INVALID_PARTITION_ID;
148 static BOOL m_bCellServDbUpdateErr = FALSE;
149 static TCHAR m_szCellServDbUpdateErrMsg[cchRESOURCE];
150 static LONG m_nServerUpdates = 0;
151 static char * m_pszCellDbHosts = 0;
152 static BOOL m_bNoAuthMode = TRUE;
153 static char m_szVicepName[9];
154 static BOOL m_bMustExit;
155 static BOOL m_bCfgInfoInvalidated;
156 static BOOL m_bUnconfiguringLastDBServer;
157 static BOOL m_bClientTokensSet;
158 static BOOL m_bRootAfsDriveMappingCreated;
159 static char m_szDriveToMapTo[3];
160 static BOOL m_bWeCreatedRootAfs;
161 static BOOL m_bWeCreatedRootCell;
163 static CRITICAL_SECTION m_CritSec;
165 typedef BOOL (*STEP_FUNC)(); // All config functions have this signature
169 * Structure that is used to form an array of all possible configuration steps.
172 STEP_STATE eState; // Where we are at in performing this step
173 STEP_FUNC pFunc; // Function used to perform this step
174 UINT nDescCtrlID; // Control ID of the static used to hold the steps description
175 UINT nGraphicCtrlID; // Control ID of the static that will display the graphic
176 UINT nMsgID; // Message to show when performing this step
177 UINT nDescID; // Step description to show
182 * Structure that holds info about the static controls that show the step description
183 * and the graphic that corresponds to the step state. There are 8 of these; they
184 * are configured at runtime depending on what configuration steps are to be performed.
185 * These are assigned into the appropriate step structure above. I could have just
186 * stuck an index from the array of these structures into the struct above, but decided
187 * to just reproduce the two fields for ease of use.
189 struct STEP_GUI_INFO {
190 UINT nDescCtrlID; // Control ID of the static used to hold the steps description
191 UINT nGraphicCtrlID; // Control ID of the static that will display the graphic
194 static STEP_GUI_INFO StepGuiCtrlIDs[] = {
195 { IDC_STEP1, IDC_STEP1_GRAPHIC },
196 { IDC_STEP2, IDC_STEP2_GRAPHIC },
197 { IDC_STEP3, IDC_STEP3_GRAPHIC },
198 { IDC_STEP4, IDC_STEP4_GRAPHIC },
199 { IDC_STEP5, IDC_STEP5_GRAPHIC },
200 { IDC_STEP6, IDC_STEP6_GRAPHIC },
201 { IDC_STEP7, IDC_STEP7_GRAPHIC },
202 { IDC_STEP8, IDC_STEP8_GRAPHIC }
207 * Each step that can possibly be performed is given an ID here. Each
208 * ID corresponds to an index of a config step in the array below. This
209 * enum MUST match the order of the steps in the STEPS arrray below.
212 SID_CONFIG_PARTITION,
213 SID_DEFINE_CELL_FOR_SERVER,
214 SID_DEFINE_CELL_FOR_CLIENT,
217 SID_CREATE_PRINCIPAL_AND_KEY,
219 SID_START_DB_AND_BAK,
221 SID_CREATE_ADMIN_PRINCIPAL,
222 SID_START_FS_VL_AND_SALVAGER,
228 SID_CREATE_ROOT_CELL,
229 SID_MOUNT_ROOT_CELL_STANDARD,
230 SID_SET_ROOT_CELL_ACL,
231 SID_MOUNT_ROOT_CELL_RW,
233 SID_ENABLE_AUTH_CHECKING,
235 SID_ADD_TO_CELLSERVDB,
236 SID_RESTART_ALL_DB_SERVERS,
245 SID_GET_ROOT_VOLUME_INFO
248 static CONFIG_STEP m_ConfigSteps[MAX_STEPS * 2]; // Filled with ID's of steps needed to perform configuration
251 * This is our array of config steps. There is one entry for each possible configuration
252 * step. Not all steps will necessarily be performed; it depends on the current config of
253 * the machine and what the user chooses. We prefill here the config function, the res
254 * string to show for the step status message, and if applicable, the res string to show
255 * for the step description. All steps have a status message that is shown right above the
256 * progress bar during configuration; only certain steps have a description. These are the
257 * ones that show up in the list of config steps on the dialog and have a state graphic next
258 * to them. All other values here are changed to their actual value at runtime. The order
259 * the steps appear here is NOT necessarily the order they will be performed in. That order
260 * depends on exactly how the server is being configured.
262 static CONFIG_STEP STEPS[MAX_STEPS] = {
263 { SS_STEP_TO_BE_DONE, ConfigPartition, 0, 0, IDS_PARTITION_STEP, IDS_PARTITION_STEP_DESC },
264 { SS_STEP_TO_BE_DONE, DefineCellForServer, 0, 0, IDS_DEFINE_CELL_NAME_STEP, 0 },
265 { SS_STEP_TO_BE_DONE, DefineCellForClient, 0, 0, IDS_DEFINE_CELL_MEMBERSHIP_STEP, 0 },
266 { SS_STEP_TO_BE_DONE, StartBosServer, 0, 0, IDS_START_BOS_SERVER_STEP, 0 },
267 { SS_STEP_TO_BE_DONE, StartAuthServer, 0, 0, IDS_START_AUTH_SERVER_STEP, 0 },
268 { SS_STEP_TO_BE_DONE, CreatePrincipalAndKey,0, 0, IDS_CREATE_PRINCIPAL_AND_KEY_STEP,0 },
269 { SS_STEP_TO_BE_DONE, StartDbServers, 0, 0, IDS_START_DB_STEP, IDS_DB_STEP_DESC },
270 { SS_STEP_TO_BE_DONE, StartDbServers, 0, 0, IDS_START_DB_AND_BK_STEP, IDS_DB_AND_BK_STEP_DESC },
271 { SS_STEP_TO_BE_DONE, StartDbServers, 0, 0, IDS_START_BK_STEP, IDS_BK_STEP_DESC },
272 { SS_STEP_TO_BE_DONE, CreateAdminPrincipal, 0, 0, IDS_CREATE_ADMIN_PRINCIPAL_STEP, 0 },
273 { SS_STEP_TO_BE_DONE, StartFsVlAndSalvager, 0, 0, IDS_START_FS_STEP, IDS_FS_STEP_DESC },
274 { SS_STEP_TO_BE_DONE, ConfigSCC, 0, 0, IDS_START_SCC_STEP, IDS_SCC_STEP_DESC },
275 { SS_STEP_TO_BE_DONE, ConfigSCS, 0, 0, IDS_START_SCS_STEP, IDS_SCS_STEP_DESC },
276 { SS_STEP_TO_BE_DONE, CreateRootAfs, 0, 0, IDS_CREATE_ROOT_AFS_STEP, IDS_ROOT_AFS_STEP_DESC },
277 { SS_STEP_TO_BE_DONE, StartClient, 0, 0, IDS_START_CLIENT_STEP, 0 },
278 { SS_STEP_TO_BE_DONE, SetRootAcl, 0, 0, IDS_SET_ROOT_ACL_STEP, 0 },
279 { SS_STEP_TO_BE_DONE, CreateRootCell, 0, 0, IDS_CREATE_ROOT_CELL_STEP, 0 },
280 { SS_STEP_TO_BE_DONE, MountRootCellStandard,0, 0, IDS_MOUNT_ROOT_CELL_STANDARD_STEP,0 },
281 { SS_STEP_TO_BE_DONE, SetRootCellAcl, 0, 0, IDS_SET_ROOT_CELL_ACL_STEP, 0 },
282 { SS_STEP_TO_BE_DONE, MountRootCellRW, 0, 0, IDS_MOUNT_ROOT_CELL_RW_STEP, 0 },
283 { SS_STEP_TO_BE_DONE, Replicate, 0, 0, IDS_REP_STEP, IDS_REP_STEP_DESC },
284 { SS_STEP_TO_BE_DONE, EnableAuthChecking, 0, 0, IDS_ENABLE_AUTH_CHECKING_STEP, 0 },
285 { SS_STEP_TO_BE_DONE, RestartServers, 0, 0, IDS_RESTART_SERVERS_STEP, 0 },
286 { SS_STEP_TO_BE_DONE, AddToCellServDB, 0, 0, IDS_ADD_TO_CELLSERVDB_STEP, 0 },
287 { SS_STEP_TO_BE_DONE, RestartAllDbServers, 0, 0, IDS_RESTART_ALL_DB_SERVERS_STEP, 0 },
288 { SS_STEP_TO_BE_DONE, VosOpenServer, 0, 0, IDS_NO_MSG_STEP, 0 },
289 { SS_STEP_TO_BE_DONE, UnconfigDB, 0, 0, IDS_UNCONFIG_DB_STEP, IDS_UNCONFIG_DB_STEP_DESC },
290 { SS_STEP_TO_BE_DONE, UnconfigBak, 0, 0, IDS_UNCONFIG_BK_STEP, IDS_UNCONFIG_BK_STEP_DESC },
291 { SS_STEP_TO_BE_DONE, UnconfigFS, 0, 0, IDS_UNCONFIG_FS_STEP, IDS_UNCONFIG_FS_STEP_DESC },
292 { SS_STEP_TO_BE_DONE, UnconfigSCS, 0, 0, IDS_UNCONFIG_SCS_STEP, IDS_UNCONFIG_SCS_STEP_DESC },
293 { SS_STEP_TO_BE_DONE, UnconfigSCC, 0, 0, IDS_UNCONFIG_SCC_STEP, IDS_UNCONFIG_SCC_STEP_DESC },
294 { SS_STEP_TO_BE_DONE, PostConfig, 0, 0, IDS_NO_MSG_STEP, 0 },
295 { SS_STEP_TO_BE_DONE, UpgradeLibHandles, 0, 0, IDS_GET_CREDENTIALS_STEP, 0 },
296 { SS_STEP_TO_BE_DONE, GetRootVolumeInfo, 0, 0, IDS_NO_MSG_STEP, 0 },
301 * These are the steps to perform when configuring the very first server.
303 static STEP_ID FirstServerSteps[] = {
304 SID_CONFIG_PARTITION,
305 SID_DEFINE_CELL_FOR_SERVER,
306 SID_DEFINE_CELL_FOR_CLIENT,
309 SID_CREATE_PRINCIPAL_AND_KEY,
311 SID_CREATE_ADMIN_PRINCIPAL,
312 SID_START_FS_VL_AND_SALVAGER,
318 SID_CREATE_ROOT_CELL,
319 SID_MOUNT_ROOT_CELL_STANDARD,
320 SID_SET_ROOT_CELL_ACL,
321 SID_MOUNT_ROOT_CELL_RW,
323 SID_ENABLE_AUTH_CHECKING
326 static STEP_ID InvalidServerInfoSteps[] = {
327 SID_DEFINE_CELL_FOR_SERVER,
329 SID_CREATE_PRINCIPAL_AND_KEY,
330 SID_CREATE_ADMIN_PRINCIPAL,
331 SID_ENABLE_AUTH_CHECKING
334 static STEP_ID InvalidClientInfoSteps[] = {
335 SID_DEFINE_CELL_FOR_CLIENT,
339 static STEP_ID PreconfigSteps[] = {
340 SID_GET_CREDENTIALS, // Always do this so we will always have credentials - need this for the config manager.
341 SID_VOS_OPEN_SERVER // We'll always do this step so we know we can make vos calls
344 static STEP_ID UnconfigDbSteps[] = {
346 SID_RESTART_ALL_DB_SERVERS
349 static STEP_ID UnconfigBakSteps[] = {
354 static STEP_ID UnconfigFsSteps[] = {
358 static STEP_ID UnconfigScsSteps[] = {
362 static STEP_ID UnconfigSccSteps[] = {
366 static STEP_ID FsSteps[] = {
367 SID_START_FS_VL_AND_SALVAGER
370 static STEP_ID DbSteps[] = {
371 SID_ADD_TO_CELLSERVDB,
373 SID_RESTART_ALL_DB_SERVERS
376 static STEP_ID DbAndBakSteps[] = {
377 SID_ADD_TO_CELLSERVDB,
378 SID_START_DB_AND_BAK,
379 SID_RESTART_ALL_DB_SERVERS
382 static STEP_ID BakOnlySteps[] = {
386 static STEP_ID PartitionSteps[] = {
390 static STEP_ID CheckRootVolumesSteps[] = {
391 SID_GET_ROOT_VOLUME_INFO
394 static STEP_ID RootVolumesSteps[] = {
396 SID_START_CLIENT, // TODO: Must check what happens if client started previously and failed because root.afs didn't exist.
398 SID_CREATE_ROOT_CELL,
399 SID_MOUNT_ROOT_CELL_STANDARD,
400 SID_SET_ROOT_CELL_ACL,
401 SID_MOUNT_ROOT_CELL_RW,
404 static STEP_ID ReplicationSteps[] = {
408 static STEP_ID ScsSteps[] = {
412 static STEP_ID SccSteps[] = {
416 static STEP_ID PostConfigSteps[] = {
423 * EXPORTED FUNCTIONS _________________________________________________________________
426 BOOL Configure(HWND hParent, BOOL& bMustExit)
428 int nResult = ModalDialog(IDD_CONFIG_SERVER, hParent, (DLGPROC)ConfigServerPageDlgProc);
430 bMustExit = m_bMustExit;
432 return !m_bConfigFailed;
437 * Dialog Proc _________________________________________________________________
440 BOOL CALLBACK ConfigServerPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp)
444 OnInitDialog(hwndDlg);
448 switch (LOWORD(wp)) {
454 IF_WIZ(g_pWiz->SetState(sidSTEP_ELEVEN));
458 // If configuring, handle cancel here.
459 // Otherwise, use common handler below.
460 if (m_bConfiguring) {
461 ShowCurrentStep(IDS_CANCEL_PENDING);
462 m_bCheckCancel = TRUE;
465 EndDialog(m_hDlg, m_bConfigured);
472 if (WizStep_Common_DlgProc (hwndDlg, msg, wp, lp))
480 * STATIC FUNCTIONS _________________________________________________________________
486 * This function is the window proc for the static controls used to display the picture
487 * (blue dot, checkmark, or red X) that indicates the state of each step.
489 * Which step to draw the state for is determined and then the state picture is displayed.
491 static BOOL CALLBACK StepGrahpicDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
493 // We only handle the paint message. All other message are passed on to the
494 // static control's normal window proc.
495 if (uMsg == WM_PAINT) {
496 for (int ii = 0; ii < m_nNumSteps; ii++) {
497 // Find the step that corresponds to the window we are supposed to paint
498 if (hwnd == GetDlgItem(m_hDlg, m_ConfigSteps[ii].nGraphicCtrlID)) {
499 PaintStepGraphic(hwnd, m_ConfigSteps[ii].eState); // Show the graphic for this step
505 return CallWindowProc((WNDPROC)Subclass_FindNextHook(hwnd, StepGrahpicDlgProc), hwnd, uMsg, wParam, lParam);
511 * Event Handler Functions _________________________________________________________________
514 static void OnInitDialog(HWND hwndDlg)
518 // Initialize our global variables - only the ones that should not
519 // preserve their state if the user leaves and returns to this page.
520 m_bConfiguring = FALSE;
521 m_bConfigured = FALSE;
522 m_bConfigFailed = FALSE;
523 m_bCheckCancel = FALSE;
525 m_bMustChangeClientCell = FALSE;
527 m_nPartitionID = INVALID_PARTITION_ID;
528 m_bCellServDbUpdateErr = FALSE;
529 m_nServerUpdates = 0;
530 m_pszCellDbHosts = 0;
532 m_bNoAuthMode = !g_CfgData.bValidServerInfo;
533 m_szVicepName[0] = 0;
535 m_bCfgInfoInvalidated = FALSE;
536 m_bUnconfiguringLastDBServer = g_CfgData.bLastDBServer && ShouldUnconfig(g_CfgData.configDB);
537 m_bClientTokensSet = FALSE;
538 m_bRootAfsDriveMappingCreated = FALSE;
539 m_bWeCreatedRootAfs = FALSE;
540 m_bWeCreatedRootCell = FALSE;
542 IF_WIZ(g_pWiz->EnableButtons(BACK_BUTTON));
543 IF_WIZ(g_pWiz->SetButtonText(IDNEXT, IDS_CONFIGURE));
544 IF_WIZ(g_pWiz->SetDefaultControl(IDNEXT));
546 TCHAR szMsg[cchRESOURCE] = TEXT("");
548 // Show the cellname in the title
551 // If this is the wizard, then check if there is nothing to do and
552 // inform the user. If this is not the wizard, then we should
553 // not even get to this point. The config tool will not call
554 // the config function if there is nothing to do.
556 // Is everything already configured?
557 if ((g_CfgData.configFS == CS_ALREADY_CONFIGURED) &&
558 (g_CfgData.configDB == CS_ALREADY_CONFIGURED) &&
559 (g_CfgData.configBak == CS_ALREADY_CONFIGURED) &&
560 (g_CfgData.configPartition == CS_ALREADY_CONFIGURED) &&
561 (g_CfgData.configRootVolumes == CS_ALREADY_CONFIGURED) &&
562 (g_CfgData.configRep == CS_ALREADY_CONFIGURED) &&
563 ((g_CfgData.configSCS == CS_ALREADY_CONFIGURED) ||
564 (g_CfgData.configSCC == CS_ALREADY_CONFIGURED)))
566 GetString(szMsg, IDS_ALREADY_CONFIGURED);
568 // Is there nothing to configure?
569 else if ((g_CfgData.configFS != CS_CONFIGURE) &&
570 (g_CfgData.configDB != CS_CONFIGURE) &&
571 (g_CfgData.configBak != CS_CONFIGURE) &&
572 (g_CfgData.configPartition != CS_CONFIGURE) &&
573 (g_CfgData.configRootVolumes != CS_CONFIGURE) &&
574 (g_CfgData.configRep != CS_CONFIGURE) &&
575 (g_CfgData.configSCS != CS_CONFIGURE) &&
576 (g_CfgData.configSCC != CS_CONFIGURE))
578 GetString(szMsg, IDS_NOTHING_TO_CONFIGURE);
581 // If there's a can't configure message, then show it
583 // Hide all controls except for the message window
584 ShowWnd(m_hDlg, IDC_ALL_NEEDED_MSG, FALSE);
585 ShowWnd(m_hDlg, IDC_FOLLOWING_STEPS_MSG, FALSE);
587 for (int i = 0; i < sizeof(StepGuiCtrlIDs) / sizeof(StepGuiCtrlIDs[0]); i++) {
588 ShowWnd(m_hDlg, StepGuiCtrlIDs[i].nDescCtrlID, FALSE);
589 ShowWnd(m_hDlg, StepGuiCtrlIDs[i].nGraphicCtrlID, FALSE);
592 ShowWnd(m_hDlg, IDC_CURRENT_STEP_LABEL, FALSE);
593 ShowWnd(m_hDlg, IDC_CURRENT_STEP, FALSE);
594 ShowWnd(m_hDlg, IDC_CONFIG_PROGRESS, FALSE);
595 ShowWnd(m_hDlg, IDC_PERCENT_COMPLETE_LABEL, FALSE);
596 ShowWnd(m_hDlg, IDC_PERCENT_COMPLETE, FALSE);
597 ShowWnd(m_hDlg, IDC_CANT_CONFIG_MSG, FALSE);
600 SetWndText(m_hDlg, IDC_STATUS_MSG, szMsg);
606 // Determine which steps to perform and which should be displayed
609 if (!g_CfgData.bWizard) {
614 // This must be done after SetupConfigSteps(), which assings a nGraphicCtrlID
615 // value to the appropriate steps. After the following code is executed, the graphic
616 // for each step will be drawn automatically whenever the dialog is repainted.
617 for (UINT ii = 0; ii < MAX_STEPS; ii++) {
618 if (m_ConfigSteps[ii].nGraphicCtrlID)
619 Subclass_AddHook(GetDlgItem(m_hDlg, m_ConfigSteps[ii].nGraphicCtrlID), StepGrahpicDlgProc);
622 IF_WIZ(g_pWiz->EnableButtons(BACK_BUTTON | NEXT_BUTTON));
625 // User has pressed the Config (or Exit) button.
626 static void OnConfig()
628 ASSERT(g_CfgData.szCellName[0]);
630 // Has user pressed the Exit button?
632 IF_WIZ(g_pWiz->Show(FALSE));
636 // Has user pressed the View Log button?
637 if (m_bConfigFailed) {
642 // Must we change the client's cell? See if user minds...
643 if (m_bMustChangeClientCell) {
644 if (ShowWarning(m_hDlg, IDS_CLIENT_CELL_WILL_CHANGE) == IDCANCEL) {
649 // Create a thread to perform the configuration steps
652 // Start configuring...
653 HANDLE hThread = CreateThread(0, 0, ConfigServer, 0, 0, &dwThreadID);
655 CloseHandle(hThread);
660 * Utility Functions _________________________________________________________________
663 static void ShowExitButton()
666 g_pWiz->SetButtonText(IDNEXT, IDS_EXIT);
669 SetWndText(m_hDlg, IDCANCEL, IDS_EXIT);
671 SetWndText(m_hDlg, IDCANCEL, IDS_CLOSE);
675 static void ShowTitle()
677 ASSERT(g_CfgData.szCellName[0]);
679 TCHAR szMsg[cchRESOURCE];
681 GetString(szMsg, IDS_CONFIG_INTO_CELL_MSG);
683 lstrcat(szMsg, g_CfgData.szCellName);
684 lstrcat(szMsg, TEXT("."));
686 SetWndText(m_hDlg, IDC_TITLE, szMsg);
689 static BOOL Unconfiguring()
691 return ShouldUnconfig(g_CfgData.configFS) ||
692 ShouldUnconfig(g_CfgData.configDB) ||
693 ShouldUnconfig(g_CfgData.configBak) ||
694 ShouldUnconfig(g_CfgData.configSCS) ||
695 ShouldUnconfig(g_CfgData.configSCC);
698 static void AddSteps(STEP_ID *pSteps, int nNumNewSteps)
701 ASSERT(nNumNewSteps > 0);
703 if (m_nNumSteps + nNumNewSteps > MAX_STEPS) {
708 // Add the new steps to the array of steps
709 for (int nNewStep = 0; nNewStep < nNumNewSteps; nNewStep++) {
710 STEP_ID nStepID = pSteps[nNewStep];
713 m_ConfigSteps[m_nNumSteps++] = STEPS[nStepID];
717 static void GetStepsToPerform()
719 #define NUM_STEPS(x) (sizeof((x)) / sizeof(STEP_ID))
721 // Is this the first server?
722 if (g_CfgData.bFirstServer) {
723 // We may have to change the FirstServerSteps, so loop over them
724 // and only add the ones we need. All of the FirstServerSteps
725 // are required except for the ones for backup and sys control
726 // machine. If the user doesn't want those then we won't put
727 // them into the array of steps to perform. Also, we may not need
728 // to make the AFS partition (if it already exists).
729 for (int i = 0; i < NUM_STEPS(FirstServerSteps); i++) {
730 STEP_ID curStep = FirstServerSteps[i];
732 if ((curStep == SID_START_DB) && ShouldConfig(g_CfgData.configBak))
733 curStep = SID_START_DB_AND_BAK;
734 else if ((curStep == SID_CONFIG_SCS) && !ShouldConfig(g_CfgData.configSCS))
736 else if ((curStep == SID_CONFIG_PARTITION) && !ShouldConfig(g_CfgData.configPartition))
739 AddSteps(&curStep, 1);
745 // Make sure client info is valid
746 if (!g_CfgData.bValidClientInfo || (lstrcmp(g_CfgData.szClientCellName, g_CfgData.szCellName) != 0)) {
747 m_bMustChangeClientCell = TRUE;
748 AddSteps(InvalidClientInfoSteps, NUM_STEPS(InvalidClientInfoSteps));
751 // Make sure server info is valid
752 if (!g_CfgData.bValidServerInfo)
753 AddSteps(InvalidServerInfoSteps, NUM_STEPS(InvalidServerInfoSteps));
755 // Add steps that should always be performed
756 AddSteps(PreconfigSteps, NUM_STEPS(PreconfigSteps));
759 * Do unconfiguration first
762 // Unconfigure File Server?
763 if (ShouldUnconfig(g_CfgData.configFS))
764 AddSteps(UnconfigFsSteps, NUM_STEPS(UnconfigFsSteps));
766 // Unconfigure Database Server? Will also automatically unconfig backup server.
767 if (ShouldUnconfig(g_CfgData.configDB))
768 AddSteps(UnconfigDbSteps, NUM_STEPS(UnconfigDbSteps));
769 // Unconfigure Backup Server?
770 else if (ShouldUnconfig(g_CfgData.configBak))
771 AddSteps(UnconfigBakSteps, NUM_STEPS(UnconfigBakSteps));
773 // Unconfigure System Control Server?
774 if (ShouldUnconfig(g_CfgData.configSCS))
775 AddSteps(UnconfigScsSteps, NUM_STEPS(UnconfigScsSteps));
777 // Unconfigure System Control Client?
778 if (ShouldUnconfig(g_CfgData.configSCC))
779 AddSteps(UnconfigSccSteps, NUM_STEPS(UnconfigSccSteps));
782 * Now do configuration
786 if (ShouldConfig(g_CfgData.configPartition))
787 AddSteps(PartitionSteps, NUM_STEPS(PartitionSteps));
789 // Database and backup server
790 if (ShouldConfig(g_CfgData.configDB)) {
791 if (ShouldConfig(g_CfgData.configBak))
792 AddSteps(DbAndBakSteps, NUM_STEPS(DbAndBakSteps));
794 AddSteps(DbSteps, NUM_STEPS(DbSteps));
795 } else if (ShouldConfig(g_CfgData.configBak))
796 AddSteps(BakOnlySteps, NUM_STEPS(BakOnlySteps));
799 if (ShouldConfig(g_CfgData.configFS))
800 AddSteps(FsSteps, NUM_STEPS(FsSteps));
802 if (!g_CfgData.bRootVolumesExistanceKnown || !g_CfgData.bRootVolumesReplicationKnown)
803 AddSteps(CheckRootVolumesSteps, NUM_STEPS(CheckRootVolumesSteps));
806 if (ShouldConfig(g_CfgData.configRootVolumes))
807 AddSteps(RootVolumesSteps, NUM_STEPS(RootVolumesSteps));
810 if (ShouldConfig(g_CfgData.configRep))
811 AddSteps(ReplicationSteps, NUM_STEPS(ReplicationSteps));
813 // System control server
814 if (ShouldConfig(g_CfgData.configSCS))
815 AddSteps(ScsSteps, NUM_STEPS(ScsSteps));
817 // System control client
818 if (ShouldConfig(g_CfgData.configSCC))
819 AddSteps(SccSteps, NUM_STEPS(SccSteps));
821 // Perform any steps necessary after all normal configuration has finished.
822 // For instance, if all servers were shut down, then we ask the user if they
823 // want the config info invalidated. Also, if the last db server was stopped,
824 // then we will stop the client as well.
825 AddSteps(PostConfigSteps, NUM_STEPS(PostConfigSteps));
828 // For steps that should have a place on the dialog, assign them the
829 // next available position.
830 static void SetupStepGUI(CONFIG_STEP& step, UINT& nDispPos)
832 step.eState = SS_STEP_TO_BE_DONE;
834 // If this step has a msg ID then it is a step that gets displayed to the
835 // user. Show it in the dialog.
837 // Give this step a position on the dialog in which to show its message
838 step.nDescCtrlID = StepGuiCtrlIDs[nDispPos].nDescCtrlID;
839 step.nGraphicCtrlID = StepGuiCtrlIDs[nDispPos].nGraphicCtrlID;
841 // Show this step's text in the proper static control
842 SetWndText(m_hDlg, step.nDescCtrlID, step.nDescID);
844 // Show the static control
845 ShowWnd(m_hDlg, step.nDescCtrlID);
847 // Show the graphic control
848 ShowWnd(m_hDlg, step.nGraphicCtrlID);
854 static void SetupConfigSteps()
856 UINT nDispPos = 0; // Which StepGuiCtrlID to use, if applicable
859 // Determine which steps are going to be performed. For the ones that
860 // will be, show their description message in the appropriate place on
863 ASSERT(m_nNumSteps > 0);
865 // For steps that should have a place on the dialog, assign them the
866 // next available position.
867 for (int i = 0; i < m_nNumSteps; i++)
868 SetupStepGUI(m_ConfigSteps[i], nDispPos);
871 static BOOL CheckResult(int nResult, int nStatus)
878 ShowError(m_hDlg, nStatus, IDS_CONFIG_ERROR);
883 static BOOL CheckCancel()
885 // If we already know we are cancelling then return
889 // If user didn't press Cancel button, then return FALSE
893 ASSERT(m_bConfiguring);
895 TCHAR szMsg[cchRESOURCE];
896 TCHAR szTitle[cchRESOURCE];
898 GetString(szMsg, IDS_CANCEL_CONFIG_MSG);
899 GetString(szTitle, GetAppTitleID());
901 // Ask user if they really want to cancel
902 int nChoice = MessageBox(m_hDlg, szMsg, szTitle, MB_YESNO | MB_ICONQUESTION);
904 m_bCancel = (nChoice == IDYES);
906 m_bCheckCancel = FALSE;
912 * Show the current config step, UNLESS the user has pressed the Cancel
913 * button, in which case a "cancel pending" message is already being
914 * displayed and we don't want it replace with this new message.
916 static void ShowCurrentStep(UINT uiMsgID)
918 if (!m_bCheckCancel && uiMsgID) {
919 SetWndText(m_hDlg, IDC_CURRENT_STEP, uiMsgID);
920 ForceUpdateWindow(m_hDlg, IDC_CURRENT_STEP);
924 static void ShowCurrentStep(TCHAR *pszMsg)
926 if (!m_bCheckCancel && pszMsg) {
927 SetWndText(m_hDlg, IDC_CURRENT_STEP, pszMsg);
928 ForceUpdateWindow(m_hDlg, IDC_CURRENT_STEP);
932 // Set the range and step increment for the progress bar.
933 static void InitProgressBar()
935 SendDlgItemMessage(m_hDlg, IDC_CONFIG_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, m_nNumSteps));
936 SendDlgItemMessage(m_hDlg, IDC_CONFIG_PROGRESS, PBM_SETSTEP, 1, 0);
939 static char *GetVicepName()
941 ASSERT((lstrlen(g_CfgData.szPartitionName) == 1) || (lstrlen(g_CfgData.szPartitionName) == 2));
943 // Construct the partition name
944 if (!m_szVicepName[0])
945 sprintf(m_szVicepName, "/vicep%s", GetPartitionNameA());
947 return m_szVicepName;
952 * Configuration Functions _________________________________________________________________
956 static BOOL VosOpenServer()
958 ASSERT(m_hvosServer == 0);
959 ASSERT(g_CfgData.szHostname[0]);
962 g_LogFile.Write("Opening server %s.\r\n", GetHostnameA());
964 m_nResult = vos_ServerOpen(g_hCell, GetHostnameA(), &m_hvosServer, &m_nStatus);
970 static BOOL ConfigPartition()
973 ASSERT(g_CfgData.chDeviceName);
975 // Constuct the device name
976 char szDevName[] = "?:";
977 szDevName[0] = GetDeviceNameA();
979 g_LogFile.Write("Adding an AFS partition on device '%s' with name '%s'.\r\n", szDevName, GetVicepName());
981 m_nResult = cfg_HostPartitionTableAddEntry(g_hServer, GetVicepName(), szDevName, &m_nStatus);
987 static BOOL FreeCellServDB()
989 afs_status_t nIgnore;
991 if (m_pszCellDbHosts) {
992 cfg_StringDeallocate(m_pszCellDbHosts, &nIgnore);
999 static BOOL GetCellServDB(char **ppszCellServDB)
1001 ASSERT(g_CfgData.szCellServDbHostname[0]);
1003 afs_status_t nIgnore;
1004 char *pszCellname = 0;
1006 g_LogFile.Write("Getting CellServDB from host %s.\r\n", GetCellServDbHostnameA());
1007 m_nResult = cfg_CellServDbEnumerate(GetCellServDbHostnameA(), &pszCellname, ppszCellServDB, &m_nStatus);
1010 // The cell name from this call better match the cell name we got previously
1011 if (strcmp(GetCellNameA(), pszCellname) != 0) {
1012 ShowError(m_hDlg, 0, IDS_WRONG_CELL);
1017 cfg_StringDeallocate(pszCellname, &nIgnore);
1019 g_LogFile.WriteMultistring(*ppszCellServDB);
1024 // Define cell name and cell membership for server
1025 static BOOL DefineCellForServer()
1028 ASSERT(g_CfgData.szCellName[0]);
1030 // CellServDB entries
1031 char *pszEntries = 0;
1033 // If not first server, get list of other hosts
1034 if (!g_CfgData.bFirstServer) {
1035 if (!m_pszCellDbHosts) {
1036 m_nResult = GetCellServDB(&m_pszCellDbHosts);
1040 pszEntries = m_pszCellDbHosts;
1042 // Make the hostname a multistring
1043 _tcsncat(g_CfgData.szHostname, TEXT("\0"), MAX_PARTITION_NAME_LEN);
1044 pszEntries = GetHostnameA();
1047 g_LogFile.Write("Putting this host in cell '%s'.\r\n", GetCellNameA());
1049 ASSERT(g_CfgData.szCellName[0]);
1051 m_nResult = cfg_HostSetCell(g_hServer, GetCellNameA(), pszEntries, &m_nStatus);
1054 g_CfgData.bValidServerInfo = TRUE;
1059 static BOOL StopClient()
1061 g_LogFile.Write("Stopping the client.\r\n");
1063 m_nResult = cfg_ClientStop(g_hClient, CLIENT_STOP_TIMEOUT, &m_nStatus);
1069 static BOOL DefineCellForClient()
1072 ASSERT(g_CfgData.szCellName[0]);
1078 // CellServDB entries
1079 char *pszEntries = 0;
1081 // If not first server, get list of other hosts
1082 if (!g_CfgData.bFirstServer) {
1083 if (!m_pszCellDbHosts) {
1084 m_nResult = GetCellServDB(&m_pszCellDbHosts);
1088 pszEntries = m_pszCellDbHosts;
1090 // Make the hostname a multistring
1091 _tcsncat(g_CfgData.szHostname, TEXT("\0"), MAX_PARTITION_NAME_LEN);
1092 pszEntries = GetHostnameA();
1095 g_LogFile.Write("Putting the AFS Client in this host's cell.\r\n");
1097 m_nResult = cfg_ClientSetCell(g_hClient, GetCellNameA(), pszEntries, &m_nStatus);
1100 // Update our state info about the client
1101 g_CfgData.bValidClientInfo = TRUE;
1102 lstrcpy(g_CfgData.szClientCellName, g_CfgData.szCellName);
1104 if (!g_CfgData.bFirstServer) {
1105 if (!UpgradeLibHandles())
1112 static BOOL StartBosServer()
1116 g_LogFile.Write("Starting the bos server in %s mode.\r\n", m_bNoAuthMode ? "no auth" : "auth");
1118 m_nResult = cfg_BosServerStart(g_hServer, m_bNoAuthMode, BOSSERVER_START_TIMEOUT, &m_nStatus);
1124 static BOOL StartAuthServer()
1127 ASSERT(g_CfgData.bFirstServer);
1129 g_LogFile.Write("Starting the authentication server.\r\n");
1131 m_nResult = cfg_AuthServerStart(g_hServer, &m_nStatus);
1134 g_CfgData.bAuthServerRunning = TRUE;
1139 static BOOL CreatePrincipalAndKey()
1143 if (!UpgradeLibHandles())
1146 // Create AFS server principal and put key in local Keyfile
1147 LPTSTR pszServerPW = 0;
1149 g_LogFile.Write("Setting the AFS Principal.\r\n");
1151 if (g_CfgData.bFirstServer) {
1152 ASSERT(g_CfgData.szServerPW[0]);
1153 pszServerPW = GetServerPW();
1159 m_nResult = cfg_HostSetAfsPrincipal(g_hServer, (short)g_CfgData.bFirstServer, S2A(pszServerPW), &m_nStatus);
1161 if (m_nStatus == ADMCFGAFSPASSWDINVALID)
1162 MsgBox(m_hDlg, IDS_BAD_PW, GetAppTitleID(), MB_OK);
1164 if ((m_nStatus == ADMCFGAFSPASSWDINVALID) || (m_nStatus == ADMCFGAFSKEYNOTAVAILABLE)) {
1165 // Ask user for the AFS principal password
1166 if (!GetAfsPrincipalPassword(m_hDlg, pszServerPW)) {
1179 static BOOL StartDbServers()
1183 g_LogFile.Write("Starting the following servers: Protection Volume Location ");
1184 if (IsStepEnabled(g_CfgData.configBak))
1185 g_LogFile.Write("Backup ");
1186 if (!g_CfgData.bFirstServer)
1187 g_LogFile.Write("Authentication");
1188 g_LogFile.Write("\r\n");
1190 // Start Protection, Volume Location, and Backup (optional) database servers
1191 m_nResult = cfg_DbServersStart(g_hServer, ShouldConfig(g_CfgData.configBak), &m_nStatus);
1194 // Must wait for this now so we can then talk to them.
1195 if (g_CfgData.bFirstServer) {
1196 g_LogFile.Write("Waiting for database servers to reach quorum.\r\n");
1197 m_nResult = cfg_DbServersWaitForQuorum(g_hServer, QUORUM_WAIT_TIMEOUT, &m_nStatus);
1204 static BOOL CreateAdminPrincipal()
1207 ASSERT(g_CfgData.szAdminName[0]);
1209 // Create generic admin principal and put in local Userlist
1210 char *pszAdminPW = 0;
1213 if (g_CfgData.bFirstServer) {
1214 ASSERT(g_CfgData.szAdminPW[0]);
1215 ASSERT(g_CfgData.szAdminUID[0]);
1216 pszAdminPW = GetAdminPWA();
1217 nUID = atoi(GetAdminUIDA());
1218 g_LogFile.Write("Setting Admin Principal to '%s' and UID to %d.\r\n", GetAdminNameA(), nUID);
1220 g_LogFile.Write("Setting Admin Principal to '%s'.\r\n", GetAdminNameA());
1222 m_nResult = cfg_HostSetAdminPrincipal(g_hServer, (short)g_CfgData.bFirstServer, GetAdminNameA(), pszAdminPW, nUID, &m_nStatus);
1225 g_CfgData.bAdminPrincipalCreated = TRUE;
1227 if (g_CfgData.bFirstServer) {
1228 if (!UpgradeLibHandles())
1235 static BOOL StartFsVlAndSalvager()
1239 g_LogFile.Write("Starting the File Server.\r\n");
1241 m_nResult = cfg_FileServerStart(g_hServer, &m_nStatus);
1247 static BOOL ConfigSCS()
1251 g_LogFile.Write("Configuring the System Control Server.\r\n");
1253 m_nResult = cfg_SysBinServerStart(g_hServer, TRUE, FALSE, &m_nStatus);
1259 static BOOL ConfigSCC()
1262 ASSERT(g_CfgData.szSysControlMachine[0]);
1264 g_LogFile.Write("Configuring the System Control Client.\r\n");
1266 m_nResult = cfg_SysControlClientStart(g_hServer, GetSysControlMachineA(), &m_nStatus);
1272 static BOOL GetPartitionID()
1274 if (m_nPartitionID != INVALID_PARTITION_ID)
1277 g_LogFile.Write("Translating the parition name '%s' to an ID.\r\n", GetVicepName());
1279 m_nResult = vos_PartitionNameToId(GetVicepName(), &m_nPartitionID, &m_nStatus);
1282 g_LogFile.Write("The ID for partition '%s' is %d.\r\n", GetVicepName(), m_nPartitionID);
1284 ASSERT(m_nPartitionID != INVALID_PARTITION_ID);
1289 static BOOL GetRootVolumeInfo()
1293 if (!g_CfgData.bRootVolumesExistanceKnown) {
1294 m_nStatus = DoRootVolumesExist(bResult);
1295 m_nResult = !m_nStatus;
1298 g_CfgData.bRootVolumesExistanceKnown = TRUE;
1301 if (!g_CfgData.bRootVolumesReplicationKnown) {
1302 m_nStatus = AreRootVolumesReplicated(bResult);
1303 m_nResult = !m_nStatus;
1306 g_CfgData.bRootVolumesReplicationKnown = TRUE;
1312 static BOOL CreateRootAfs()
1315 ASSERT(m_hvosServer);
1317 // If the root.afs volume already exists, then just return. We can get to this step
1318 // and root.afs already exist if:
1320 // 1) We could not determine the status of the root volumes when the app was started
1321 // and the user asked us to create the root volumes if they don't exist.
1323 // 2) Since there is only one page from which the user decides if they want to create
1324 // the root volumes, there is a chance that one of the root volumes may exist while
1325 // the other doesn't. If that is the case the user is told that the "root volumes"
1326 // don't exist. If they choose to create them, we do this check here to make sure
1327 // we only create the one that doesn't exist.
1329 if (g_CfgData.bRootAfsExists)
1332 if (!GetPartitionID())
1335 // If the client is running then stop it - creating root.afs will confuse it.
1336 // It will be started again after root.afs is created.
1340 g_LogFile.Write("Creating volume root.afs on partition %d with a quota of %d.\r\n", m_nPartitionID, ROOT_VOLUMES_QUOTA);
1342 m_nResult = vos_VolumeCreate(g_hCell, m_hvosServer, 0, m_nPartitionID, "root.afs", ROOT_VOLUMES_QUOTA, &g_CfgData.nRootAfsID, &m_nStatus);
1346 g_LogFile.Write("Volume root.afs was created with an ID of %d.\r\n", g_CfgData.nRootAfsID);
1348 g_CfgData.bRootAfsExists = TRUE;
1350 m_bWeCreatedRootAfs = TRUE;
1355 static BOOL StartClient()
1359 g_LogFile.Write("Starting the AFS Client.\r\n");
1361 m_nResult = cfg_ClientStart(g_hClient, CLIENT_START_TIMEOUT, &m_nStatus);
1367 static BOOL SetTokensInClient()
1369 if (m_bClientTokensSet)
1372 g_LogFile.Write("Putting our tokens into the AFS Client.\r\n");
1374 m_nResult = afsclient_TokenSet(g_hToken, &m_nStatus);
1377 m_bClientTokensSet = TRUE;
1382 static BOOL IsClientFreelance(void)
1389 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1390 0, KEY_QUERY_VALUE, &parmKey);
1391 if (code == ERROR_SUCCESS) {
1392 dummyLen = sizeof(enabled);
1393 code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL,
1394 (BYTE *) &enabled, &dummyLen);
1395 RegCloseKey (parmKey);
1397 return (enabled?TRUE:FALSE);
1400 static char space[2048];
1401 static BOOL IsRootAfsMountPoint(void)
1403 struct ViceIoctl blob;
1406 blob.in = ".root.afs";
1408 blob.out_size = sizeof(space);
1410 memset(space, 0, sizeof(space));
1412 code = pioctl(GetClientNetbiosNameA(), VIOC_AFS_STAT_MT_PT, &blob, 1);
1416 static BOOL CreateFreelanceRootAfsMountPoint(char * path)
1418 struct ViceIoctl blob;
1421 if (IsRootAfsMountPoint())
1424 blob.in = "%root.afs";
1426 blob.out_size = sizeof(space);
1428 memset(space, 0, sizeof(space));
1430 code = pioctl(path, VIOC_AFS_CREATE_MT_PT, &blob, 1);
1434 static BOOL CreateRootAfsDriveMapping(void)
1436 if (m_bRootAfsDriveMappingCreated)
1439 g_LogFile.Write("Attempting to create a drive mapping into AFS.\r\n");
1441 char szAfsRootDir[_MAX_PATH];
1443 if ( IsClientFreelance() )
1445 sprintf(szAfsRootDir, "\\\\%s\\all\\.root.afs", GetClientNetbiosNameA());
1446 if ( !CreateFreelanceRootAfsMountPoint(szAfsRootDir) )
1449 sprintf(szAfsRootDir, "\\\\%s\\all", GetClientNetbiosNameA());
1451 strcpy(m_szDriveToMapTo, "_:");
1453 // We will try all drives from D to Z.
1458 memset (&nr, 0x00, sizeof(NETRESOURCE));
1460 for (chDriveLetter = 'Z'; (chDriveLetter > 'C') && !m_bRootAfsDriveMappingCreated; chDriveLetter--) {
1461 m_szDriveToMapTo[0] = chDriveLetter;
1462 g_LogFile.Write("Attempting to map %s to %s: ", m_szDriveToMapTo, szAfsRootDir);
1464 nr.dwType=RESOURCETYPE_DISK;
1465 nr.lpLocalName=m_szDriveToMapTo;
1466 nr.lpRemoteName=szAfsRootDir;
1467 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
1468 DWORD res=WNetAddConnection2(&nr,NULL,NULL,0);
1469 m_bRootAfsDriveMappingCreated = (res == NO_ERROR);
1470 // m_bRootAfsDriveMappingCreated = (WNetAddConnection(A2S(szAfsRootDir), TEXT(""), A2S(m_szDriveToMapTo)) == NO_ERROR);
1471 g_LogFile.Write(m_bRootAfsDriveMappingCreated ? "succeeded.\r\n" : "failed.\r\n");
1474 // If we couldn't map a drive, then ask the user to unmap something.
1475 if (!m_bRootAfsDriveMappingCreated) {
1476 int nChoice = MsgBox(m_hDlg, IDS_CANT_MAP_ROOT_AFS, GetAppTitleID(), MB_ICONEXCLAMATION | MB_OKCANCEL);
1477 if (nChoice == IDOK)
1481 return m_bRootAfsDriveMappingCreated;
1484 static BOOL SetRootAcl()
1486 // Only do this if we just created root.afs
1487 if (!m_bWeCreatedRootAfs)
1490 if (!SetTokensInClient())
1493 if (!CreateRootAfsDriveMapping())
1496 g_LogFile.Write("Setting the ACL on root.afs.\r\n");
1498 acl_t acl = { READ, NO_WRITE, LOOKUP, NO_DELETE, NO_INSERT, NO_LOCK, NO_ADMIN };
1500 m_nResult = afsclient_ACLEntryAdd(m_szDriveToMapTo, "system:anyuser", &acl, &m_nStatus);
1507 static BOOL CreateRootCell()
1510 ASSERT(m_hvosServer);
1512 // If the root.cell volume already exists, then just return. We can get to this step
1513 // and root.cell already exist if:
1515 // 1) We could not determine the status of the root volumes when the app was started
1516 // and the user asked us to create the root volumes if they don't exist.
1518 // 2) Since there is only one page from which the user decides if they want to create
1519 // the root volumes, there is a chance that one of the root volumes may exist while
1520 // the other doesn't. If that is the case the user is told that the "root volumes"
1521 // don't exist. If they choose to create them, we do this check here to make sure
1522 // we only create the one that doesn't exist.
1524 if (g_CfgData.bRootCellExists)
1527 // If root.afs exists and we did not just create it, then we cannot make root.cell. For
1528 // now, just pretend we succeeded. TODO: We must handle this better in a future version.
1529 // We can't at this time because the program strings are frozen - we can't add new
1531 if (g_CfgData.bRootAfsExists && !m_bWeCreatedRootAfs)
1534 if (!GetPartitionID())
1537 g_LogFile.Write("Creating volume root.cell on partition %d with a quota of %d.\r\n", m_nPartitionID, ROOT_VOLUMES_QUOTA);
1539 m_nResult = vos_VolumeCreate(g_hCell, m_hvosServer, 0, m_nPartitionID, "root.cell", ROOT_VOLUMES_QUOTA, &g_CfgData.nRootCellID, &m_nStatus);
1542 g_LogFile.Write("Volume root.cell was created with an ID of %d.\r\n", g_CfgData.nRootCellID);
1544 g_CfgData.bRootCellExists = TRUE;
1546 m_bWeCreatedRootCell = TRUE;
1551 static char *GetRootCellDir()
1553 static char szDir[MAX_CELL_NAME_LEN + 5] = "";
1556 ASSERT(g_CfgData.szCellName[0]);
1557 sprintf(szDir, "%s\\%s", m_szDriveToMapTo, GetCellNameA());
1563 static char *GetRootCellReadWriteDir()
1565 static char szDir[MAX_CELL_NAME_LEN + 5] = "";
1568 ASSERT(g_CfgData.szCellName[0]);
1569 sprintf(szDir, "%s\\.%s", m_szDriveToMapTo, GetCellNameA());
1575 static BOOL MountRootCellStandard()
1577 ASSERT(g_CfgData.szCellName[0]);
1579 // Only do this if we just created root.cell
1580 if (!m_bWeCreatedRootCell)
1583 if (!SetTokensInClient())
1586 if (!CreateRootAfsDriveMapping())
1589 g_LogFile.Write("Mouting root.cell with a Standard mount point at path %s.\r\n", GetRootCellDir());
1591 m_nResult = afsclient_MountPointCreate(g_hCell, GetRootCellDir(), "root.cell", READ_ONLY, CHECK_VOLUME, &m_nStatus);
1597 static BOOL SetRootCellAcl()
1599 // Only do this if we just created root.cell
1600 if (!m_bWeCreatedRootCell)
1603 if (!SetTokensInClient())
1606 g_LogFile.Write("Setting the ACL on root.cell (dir %s).\r\n", GetRootCellDir());
1608 acl_t acl = { READ, NO_WRITE, LOOKUP, NO_DELETE, NO_INSERT, NO_LOCK, NO_ADMIN };
1610 m_nResult = afsclient_ACLEntryAdd(GetRootCellDir(), "system:anyuser", &acl, &m_nStatus);
1616 static BOOL MountRootCellRW()
1618 ASSERT(g_CfgData.szCellName[0]);
1620 // Only do this if we just created root.cell
1621 if (!m_bWeCreatedRootCell)
1624 if (!SetTokensInClient())
1627 if (!CreateRootAfsDriveMapping())
1630 g_LogFile.Write("Mounting root.cell with a Read/Write mount point at path %s.\r\n", GetRootCellReadWriteDir());
1632 m_nResult = afsclient_MountPointCreate(g_hCell, GetRootCellReadWriteDir(), "root.cell", READ_WRITE, CHECK_VOLUME, &m_nStatus);
1638 static BOOL Replicate()
1641 ASSERT(m_hvosServer);
1643 if (!GetPartitionID())
1646 // If only one of the volumes is not replicated, then only replicate
1647 // that volume, or if we could not determine if they were replicated
1648 // until configuration began, and they are replicated, then do nothing.
1650 if (g_CfgData.bRootAfsExists && !g_CfgData.bRootAfsReplicated) {
1651 g_LogFile.Write("Creating a read only site for volume root.afs using partition ID %d and volume ID %d.\r\n", m_nPartitionID, g_CfgData.nRootAfsID);
1653 m_nResult = vos_VLDBReadOnlySiteCreate(g_hCell, m_hvosServer, 0, m_nPartitionID, g_CfgData.nRootAfsID, &m_nStatus);
1656 g_LogFile.Write("Releasing the root.afs volume using volume ID %d.\r\n", g_CfgData.nRootAfsID);
1658 m_nResult = vos_VolumeRelease(g_hCell, 0, g_CfgData.nRootAfsID, VOS_NORMAL, &m_nStatus);
1661 g_CfgData.bRootAfsReplicated = TRUE;
1664 if (g_CfgData.bRootCellExists && !g_CfgData.bRootCellReplicated) {
1665 g_LogFile.Write("Creating a read only site for volume root.cell using partition ID %d and volume ID %d.\r\n", m_nPartitionID, g_CfgData.nRootCellID);
1667 m_nResult = vos_VLDBReadOnlySiteCreate(g_hCell, m_hvosServer, 0, m_nPartitionID, g_CfgData.nRootCellID, &m_nStatus);
1670 g_LogFile.Write("Releasing the root.cell volume using volume ID %d.\r\n", g_CfgData.nRootCellID);
1672 m_nResult = vos_VolumeRelease(g_hCell, 0, g_CfgData.nRootCellID, VOS_NORMAL, &m_nStatus);
1675 g_CfgData.bRootCellReplicated = TRUE;
1681 static BOOL EnableAuthChecking()
1684 ASSERT(g_CfgData.szHostname[0]);
1688 g_LogFile.Write("Bos open of server '%s'.\r\n", GetHostnameA());
1689 m_nResult = bos_ServerOpen(g_hCell, GetHostnameA(), &hbosServer, &m_nStatus);
1694 g_LogFile.Write("Enabling auth checking.\r\n");
1695 m_nResult = bos_AuthSet(hbosServer, BOS_AUTH_REQUIRED, &m_nStatus);
1698 g_LogFile.Write("Closing bos server connection.\r\n");
1699 m_nResult = bos_ServerClose(hbosServer, &m_nStatus);
1705 static BOOL UpgradeLibHandles()
1707 ASSERT(g_CfgData.szCellName[0]);
1708 ASSERT(g_CfgData.szAdminName[0]);
1709 ASSERT(g_CfgData.szAdminPW[0]);
1711 g_LogFile.Write("Getting credentials in cell '%s' as admin '%s'.\r\n", GetCellNameA(), GetAdminNameA());
1713 m_nResult = GetLibHandles(&m_nStatus);
1719 static BOOL RestartServers()
1725 g_LogFile.Write("Bos open of server '%s'.\r\n", GetHostnameA());
1726 m_nResult = bos_ServerOpen(g_hCell, GetHostnameA(), &hbosServer, &m_nStatus);
1731 g_LogFile.Write("Stopping and restarting all bos processes.\r\n");
1732 m_nResult = bos_ProcessAllStopAndRestart(hbosServer, BOS_RESTART_BOS_SERVER, &m_nStatus);
1735 g_LogFile.Write("Closing bos server connection.\r\n");
1736 m_nResult = bos_ServerClose(hbosServer, &m_nStatus);
1742 void DbAddHostCallback(void *callBackId, cfg_cellServDbStatus_t *statusItemP, int status)
1744 // Is this our call back ID?
1745 if (callBackId != (void *)&m_CallBackID)
1748 // Update the var that tracks server updates so the main config thread won't
1749 // think we have timed out.
1750 EnterCriticalSection(&m_CritSec);
1752 LeaveCriticalSection(&m_CritSec);
1754 // Is this the last callback?
1757 m_nResult = !status;
1758 SetEvent(m_hCellServDBUpdateEvent); // Signal config thread that we are done
1764 // Did the update of the current host succeed?
1765 if (statusItemP->status == 0)
1766 nStrID = IDS_UPDATING_CELLSERVDB_HOST_SUCCEEDED;
1768 m_bCellServDbUpdateErr = TRUE;
1769 nStrID = IDS_UPDATING_CELLSERVDB_HOST_FAILED;
1772 TCHAR szMsg[cchRESOURCE];
1773 GetString(szMsg, nStrID);
1774 _tcscat(szMsg, A2S(statusItemP->fsDbHost));
1775 ShowCurrentStep(szMsg);
1777 g_LogFile.Write("Update of the CellServDB file on host %s %s.\r\n", statusItemP->fsDbHost, statusItemP->status ? "failed" : "succeeded");
1779 cfg_CellServDbStatusDeallocate(statusItemP, &m_nStatus);
1780 // We don't care if this fails
1783 static BOOL UpdateCellServDB(BOOL bAdding)
1786 ASSERT(g_CfgData.szCellName[0]);
1790 cfg_cellServDbUpdateCallBack_t callBack = (cfg_cellServDbUpdateCallBack_t)DbAddHostCallback;
1792 // Create the event that the callback routine will use to tell us it is finished.
1793 // If we fail to create the event then don't use a callback routine.
1794 m_hCellServDBUpdateEvent = CreateEvent(NULL /* Sec */, FALSE /* Manual Reset */, FALSE /* Initial State */, m_pszCellServDBUpdateEventName);
1795 if (!m_hCellServDBUpdateEvent) {
1796 // Cause the CHECK_RESULT below to fail
1798 m_nStatus = GetLastError();
1802 // Create our critical section
1803 InitializeCriticalSection(&m_CritSec);
1805 // Update CellServDB via a SCM if the user specified one
1807 if (g_CfgData.szSysControlMachine[0]) {
1808 pszSCM = GetSysControlMachineA();
1809 g_LogFile.Write("We will update CellServDB using Sys Control Machine %s.\r\n", pszSCM);
1812 // Update CellServDB on all servers
1813 g_LogFile.Write("Updating CellServDB on all servers in the cell.\r\n");
1815 m_nResult = cfg_CellServDbAddHost(g_hServer, pszSCM, callBack, (void *)&m_CallBackID, &nMaxUpdates, &m_nStatus);
1817 m_nResult = cfg_CellServDbRemoveHost(g_hServer, pszSCM, callBack, (void *)&m_CallBackID, &nMaxUpdates, &m_nStatus);
1820 // Update CellServDB for the client on this machine
1821 g_LogFile.Write("Updating the client's CellServDB.\r\n");
1823 cfg_ClientCellServDbAdd(g_hClient, GetCellNameA(), GetHostnameA(), &m_nStatus);
1825 cfg_ClientCellServDbRemove(g_hClient, GetCellNameA(), GetHostnameA(), &m_nStatus);
1831 switch (WaitForSingleObject(m_hCellServDBUpdateEvent, CELLSERVDB_UPDATE_TIMEOUT))
1833 case WAIT_OBJECT_0: bDone = TRUE; // The callback function signalled us that it is done.
1837 // We timed out so see if a server was updated. If it was then all is cool
1838 // and we can keep going (after clearing the server update count flag).
1839 EnterCriticalSection(&m_CritSec);
1841 if (m_nServerUpdates)
1842 m_nServerUpdates = 0;
1844 // There were no server updates, so we really did timeout
1845 TCHAR szMsg[cchRESOURCE];
1846 GetString(szMsg, IDS_CELLSERVDB_UPDATE_PROBLEM);
1847 _tcscat(m_szCellServDbUpdateErrMsg, szMsg);
1851 LeaveCriticalSection(&m_CritSec);
1855 // No other return values are valid when waiting on an event object
1861 DeleteCriticalSection(&m_CritSec);
1863 CloseHandle(m_hCellServDBUpdateEvent);
1865 // See if a failure occurred in the callback
1871 static BOOL AddToCellServDB()
1873 return UpdateCellServDB(TRUE);
1876 static BOOL RemoveFromCellServDB()
1878 return UpdateCellServDB(FALSE);
1881 static BOOL RestartAllDbServers()
1885 if (m_bUnconfiguringLastDBServer)
1888 g_LogFile.Write("Restarting all DB servers.\r\n");
1889 m_nResult = cfg_DbServersRestartAll(g_hServer, &m_nStatus);
1892 g_LogFile.Write("Waiting for all DB servers to reach quorum.\r\n");
1893 m_nResult = cfg_DbServersWaitForQuorum(g_hServer, QUORUM_WAIT_TIMEOUT, &m_nStatus);
1896 m_bDbServersRestarted = TRUE;
1901 static BOOL UnconfigDB()
1905 m_nResult = RemoveFromCellServDB();
1908 m_nResult = cfg_DbServersStop(g_hServer, &m_nStatus);
1914 static BOOL UnconfigBak()
1918 int nResult = cfg_DbServersStopAllBackup(g_hServer, &m_nStatus);
1924 static BOOL UnconfigFS()
1928 m_nResult = cfg_FileServerStop(g_hServer, &m_nStatus);
1934 static BOOL UnconfigSCS()
1938 m_nResult = cfg_UpdateServerStop(g_hServer, &m_nStatus);
1941 // Since we are no longer the SCS machine, we better null this guy.
1942 g_CfgData.szSysControlMachine[0] = 0;
1947 static BOOL UnconfigSCC()
1951 m_nResult = cfg_UpdateClientStop(g_hServer, cfg_upclientSysBosSuffix, &m_nStatus);
1957 static BOOL AllServicesUnconfigured()
1959 #define NOTCONFIGURED(x) (((x) == CS_UNCONFIGURE) || ((x) == CS_NULL))
1961 return (NOTCONFIGURED(g_CfgData.configFS) &&
1962 NOTCONFIGURED(g_CfgData.configDB) &&
1963 NOTCONFIGURED(g_CfgData.configBak) &&
1964 NOTCONFIGURED(g_CfgData.configSCS) &&
1965 NOTCONFIGURED(g_CfgData.configSCC));
1968 static BOOL PostConfig()
1972 short isStarted = 0, bosProcsRunning = 0;
1974 if (!AllServicesUnconfigured())
1977 // If there is now no cell, then stop the client
1978 if (m_bUnconfiguringLastDBServer) {
1979 ShowCurrentStep(IDS_STOP_CLIENT_STEP);
1984 // Ask user if the config info should be invalided
1985 g_LogFile.Write("No services are configured so we will ask the user if they want to invalidate the server config info.\r\n");
1986 int nChoice = Message(MB_OK | MB_YESNO, GetAppTitleID(), IDS_INVALIDATE_CFG_INFO);
1987 if (nChoice == IDNO) {
1988 g_LogFile.Write("User has chosen NOT to invalidate the server config info.\r\n");
1992 ShowCurrentStep(IDS_INVALIDATE_CONFIG_INFO_STEP);
1994 g_LogFile.Write("User has chosen to invalidate the server config info.\r\n");
1996 g_LogFile.Write("Stopping the bos server.\r\n");
1997 m_nResult = cfg_BosServerStop(g_hServer, BOSSERVER_STOP_TIMEOUT, &m_nStatus);
2000 g_LogFile.Write("Invalidating the config info.\r\n");
2001 m_nResult = cfg_HostInvalidate(g_hServer, &m_nStatus);
2004 m_bCfgInfoInvalidated = TRUE;
2011 static void VosCloseServer()
2014 g_LogFile.Write("Closing the connection to this server.\r\n");
2015 vos_ServerClose(m_hvosServer, &m_nStatus);
2020 static void ShowConfigControls(BOOL bShow)
2022 ShowWnd(m_hDlg, IDC_CURRENT_STEP_LABEL, bShow);
2023 ShowWnd(m_hDlg, IDC_CURRENT_STEP, bShow);
2024 ShowWnd(m_hDlg, IDC_CONFIG_PROGRESS, bShow);
2025 ShowWnd(m_hDlg, IDC_PERCENT_COMPLETE_LABEL, bShow);
2026 ShowWnd(m_hDlg, IDC_PERCENT_COMPLETE, bShow);
2027 ShowWnd(m_hDlg, IDC_STATUS_MSG, !bShow);
2030 static void UpdateConfigProgress(int nStepNum)
2032 // Update the progress bar
2033 SendDlgItemMessage(m_hDlg, IDC_CONFIG_PROGRESS, PBM_STEPIT, 0, 0);
2035 // Update the percent complete
2037 _stprintf(buf, TEXT("%2d%%"), nStepNum * 100 / m_nNumSteps);
2039 SetWndText(m_hDlg, IDC_PERCENT_COMPLETE, buf);
2040 ForceUpdateWindow(m_hDlg, IDC_PERCENT_COMPLETE);
2043 static void ViewLog()
2045 char szCmdLine[MAX_PATH];
2047 if (_access(g_LogFile.GetPath(), 0) != 0) {
2048 ShowError(m_hDlg, 0, IDS_ERROR_NO_LOG_FILE);
2052 sprintf(szCmdLine, "notepad.exe %s", g_LogFile.GetPath());
2054 UINT result = WinExec(szCmdLine, SW_SHOW);
2056 ShowError(m_hDlg, result, IDS_VIEW_LOG_ERROR);
2059 static void AssignFailure(int nCurStep, int nLastMainStep)
2061 // A config step has failed, so we will first set its state to
2062 // failure. If the step does not have a place on the dialog
2063 // the we must find some other control to show the red X that
2064 // indicates failure.
2066 m_ConfigSteps[nCurStep].eState = SS_STEP_FAILED;
2068 // Is the step displayed on the dialog?
2069 if (m_ConfigSteps[nCurStep].nDescID != 0)
2072 // It isn't so find nearest one that is
2073 for (int ii = nCurStep + 1; ii < m_nNumSteps; ii++) {
2074 CONFIG_STEP& step = m_ConfigSteps[ii];
2075 if (step.nDescID != 0) {
2076 step.eState = SS_STEP_FAILED;
2077 IF_WIZ(ForceUpdateWindow(m_hDlg, step.nGraphicCtrlID));
2082 // There is no step on the dialog that is after us, so
2083 // use the last one that is there.
2084 m_ConfigSteps[nLastMainStep].eState = SS_STEP_FAILED;
2085 IF_WIZ(ForceUpdateWindow(m_hDlg, m_ConfigSteps[nLastMainStep].nGraphicCtrlID));
2088 static int GetLastMainStep()
2090 for (int ii = m_nNumSteps - 1; ii >= 0; ii--) {
2091 if (m_ConfigSteps[ii].nDescID != 0)
2095 ASSERT(FALSE); // This should never happen!
2100 static void ShowConfigFailedMsg()
2102 LPTSTR pszMsg = FormatString(IDS_CONFIG_FAILED, TEXT("%hs%hs"), LOG_FILE_NAME, AFSDIR_SERVER_LOGS_DIRPATH);
2104 SetWndText(m_hDlg, IDC_STATUS_MSG, pszMsg);
2109 static void ShowViewLogButton()
2112 g_pWiz->SetButtonText(IDNEXT, IDS_VIEW_LOG);
2114 ShowAndEnable(m_hDlg, IDNEXT);
2115 MoveWnd(m_hDlg, IDCANCEL, -45, 0);
2116 // I had to add the code below because of a problem, where if config failed, the
2117 // error message dialog would display over our window, and when our window next got
2118 // fully displayed, the buttons would be misdrawn.
2119 ForceUpdateWindow(m_hDlg, IDNEXT);
2120 ForceUpdateWindow(m_hDlg, IDCANCEL);
2124 static DWORD WINAPI ConfigServer(LPVOID param)
2129 hLogo = GetDlgItem(m_hDlg, IDC_LOGO);
2130 AfsAppLib_StartAnimation(hLogo);
2133 // Disable all buttons (doesn't affect the Cancel button)
2134 IF_WIZ(g_pWiz->EnableButtons(0));
2136 g_LogFile.Write("Configuring server\r\n");
2138 m_bConfiguring = TRUE;
2139 m_bConfigured = FALSE;
2140 m_bDbServersRestarted = FALSE;
2142 // Hide the message window and show the config controls
2143 ShowConfigControls();
2147 BOOL bResult = TRUE;
2151 IF_WIZ(nLastMainStep = GetLastMainStep());
2153 // Loop over each config step performing the ones that are enabled.
2154 for (int nCurStep = 0; (nCurStep < m_nNumSteps) && bResult; nCurStep++) {
2155 CONFIG_STEP& step = m_ConfigSteps[nCurStep];
2159 // Show this step's status message
2160 ShowCurrentStep(step.nMsgID);
2162 step.eState = SS_STEP_IN_PROGRESS;
2164 // If this is a displayed step, then update its display
2165 if (step.nGraphicCtrlID)
2166 IF_WIZ(ForceUpdateWindow(m_hDlg, step.nGraphicCtrlID));
2171 // Perform the config function
2172 bResult = step.pFunc();
2176 // Changing a step's state changes what picture is shown on the dialog
2177 // (if that state is displayed on the dialog).
2179 // If this is the last displayed step, then don't change its state
2180 // because there may still be more steps to perform. We want to use
2181 // the last step's picture to indicate the final config state.
2183 // If not last step, then change state
2184 if (nCurStep != nLastMainStep)
2185 step.eState = SS_STEP_FINISHED;
2187 // If last step then go ahead and show the state - but do it on the last
2188 // step displayed on the dialog (nLastMainStep).
2189 if (nCurStep == m_nNumSteps - 1) {
2190 m_ConfigSteps[nLastMainStep].eState = SS_STEP_FINISHED;
2191 // Do the next line so ForceUpdateWindow below will redraw the
2193 step = m_ConfigSteps[nLastMainStep];
2197 UpdateConfigProgress(nStepNum);
2199 // Show the 'X' error marker on the next unprocessed step, or on the
2200 // last step if there are no more.
2201 IF_WIZ(AssignFailure(nCurStep, nLastMainStep));
2202 step.eState = SS_STEP_FAILED;
2205 if (step.nGraphicCtrlID)
2206 IF_WIZ(ForceUpdateWindow(m_hDlg, step.nGraphicCtrlID));
2209 // Close m_hvosServer if it is open
2212 // Hide the config controls and show the message window
2213 ShowConfigControls(FALSE);
2216 if (CheckCancel()) {
2217 g_LogFile.Write("User has canceled configuration.\r\n");
2218 SetWndText(m_hDlg, IDC_STATUS_MSG, IDS_CONFIG_CANCELED);
2219 IF_WIZ(g_pWiz->EnableButtons(BACK_BUTTON));
2222 } else if (bResult) {
2223 g_LogFile.Write("Configuration succeeded.\r\n");
2224 if (g_CfgData.bFirstServer)
2225 SetWndText(m_hDlg, IDC_STATUS_MSG, IDS_CONFIG_SUCCEEDED_FIRST_SERVER);
2226 else if (m_bDbServersRestarted)
2227 SetWndText(m_hDlg, IDC_STATUS_MSG, IDS_CONFIG_SUCCEEDED_NEED_CELLSERVDB_UPDATE);
2229 SetWndText(m_hDlg, IDC_STATUS_MSG, IDS_CONFIG_SUCCEEDED);
2230 IF_WIZ(g_pWiz->EnableButtons(NEXT_BUTTON));
2232 m_bConfigured = TRUE;
2234 // Disable cancel button
2235 IF_WIZ(SetEnable(g_pWiz->GetWindow(), IDCANCEL, ES_DISABLE));
2237 g_LogFile.Write("Configuration has failed.\r\n");
2238 ShowConfigFailedMsg();
2239 // Prevent partial configuration
2240 if (!g_CfgData.bValidServerInfo)
2241 cfg_HostInvalidate(g_hServer, &m_nStatus);
2242 IF_WIZ(g_pWiz->EnableButtons(NEXT_BUTTON));
2243 ShowViewLogButton();
2244 m_bConfigFailed = TRUE;
2248 AfsAppLib_StopAnimation(hLogo);
2250 IF_WIZ(g_pWiz->SetDefaultControl(IDNEXT));
2252 m_bConfiguring = FALSE;
2254 // Show the user any CellServDB update errors
2255 if (m_bCellServDbUpdateErr) {
2256 TCHAR szTitle[cchRESOURCE], szMsg[cchRESOURCE + MAX_PATH];
2257 GetString(szTitle, GetAppTitleID());
2258 GetString(szMsg, IDS_CELLSERVDB_UPDATE_ERRORS_ARE_IN_LOG_FILE);
2259 lstrcat(szMsg, A2S(g_LogFile.GetPath()));
2260 lstrcat(szMsg, TEXT("."));
2261 MessageBox(m_hDlg, szMsg, szTitle, MB_OK | MB_ICONEXCLAMATION);
2264 // Warn the user if we are going to force the config manager to exit
2266 if (m_bUnconfiguringLastDBServer)
2267 MsgBox(m_hDlg, IDS_CELL_IS_GONE_MUST_EXIT, GetAppTitleID(), MB_OK | MB_ICONSTOP);
2269 MsgBox(m_hDlg, IDS_CONFIG_INFO_INVALIDATED, GetAppTitleID(), MB_OK);
2272 // Unmap the root afs drive if we had one
2273 if (m_bRootAfsDriveMappingCreated) {
2274 // Let's not bother the user if this fails; we'll just log it.
2275 g_LogFile.Write("Attempting to remove the drive mapping to root.afs: ");
2276 BOOL bCanceled = WNetCancelConnection(A2S(m_szDriveToMapTo), TRUE) == NO_ERROR;
2277 g_LogFile.Write(bCanceled ? "succeeded.\r\n" : "failed.\r\n");
2278 m_bRootAfsDriveMappingCreated = !bCanceled;