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 _________________________________________________________________
16 #include <afs/param.h>
24 #include "get_cur_config.h"
25 #include "partition_utils.h"
27 #include <afs\dirpath.h>
28 #include <afs\afs_clientAdmin.h>
33 * DEFINITIONS _________________________________________________________________
39 * PROTOTYPES _________________________________________________________________
42 static void SetConfigDefaults();
43 static void RunCfgTool();
44 static void RunWizard();
45 static void CloseLibHandles(BOOL bExiting = FALSE);
47 void RegisterWizardHelp();
48 void RegisterConfigToolHelp();
50 // These are the prototypes for the dialog procs of each wizard page.
51 BOOL CALLBACK IntroPageDlgProc(HWND hRHS, UINT msg, WPARAM wp, LPARAM lp);
52 BOOL CALLBACK InfoPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
53 BOOL CALLBACK InfoPage2DlgProc(HWND hRHS, UINT msg, WPARAM wp, LPARAM lp);
54 BOOL CALLBACK FileServerPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
55 BOOL CALLBACK DBServerPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
56 BOOL CALLBACK BackupPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
57 BOOL CALLBACK PartitionPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
58 BOOL CALLBACK RootAfsPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
59 BOOL CALLBACK ReplicationPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
60 BOOL CALLBACK SysControlPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
61 BOOL CALLBACK ConfigServerPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wp, LPARAM lp);
64 static WIZARD_STATE g_aStates[] = {
65 { sidSTEP_ONE, IDD_INTRO_PAGE, (DLGPROC)IntroPageDlgProc, 0 },
66 { sidSTEP_TWO, IDD_INFO_PAGE, (DLGPROC)InfoPageDlgProc, 0 },
67 { sidSTEP_THREE, IDD_INFO_PAGE2_FIRST_SERVER, (DLGPROC)InfoPage2DlgProc, 0 },
68 { sidSTEP_FOUR, IDD_INFO_PAGE2_NOT_FIRST_SERVER,(DLGPROC)InfoPage2DlgProc, 0 },
69 { sidSTEP_FIVE, IDD_FILE_SERVER_PAGE, (DLGPROC)FileServerPageDlgProc, 0 },
70 { sidSTEP_SIX, IDD_DB_SERVER_PAGE, (DLGPROC)DBServerPageDlgProc, 0 },
71 { sidSTEP_SEVEN, IDD_BACKUP_SERVER_PAGE, (DLGPROC)BackupPageDlgProc, 0 },
72 { sidSTEP_EIGHT, IDD_PARTITION_PAGE, (DLGPROC)PartitionPageDlgProc, 0 },
73 { sidSTEP_NINE, IDD_ROOT_VOLUMES_PAGE, (DLGPROC)RootAfsPageDlgProc, 0 },
74 { sidSTEP_TEN, IDD_REPLICATION_PAGE, (DLGPROC)ReplicationPageDlgProc, 0 },
75 { sidSTEP_ELEVEN, IDD_SYS_CONTROL_PAGE, (DLGPROC)SysControlPageDlgProc, 0 },
76 { sidSTEP_TWELVE, IDD_CONFIG_SERVER_PAGE, (DLGPROC)ConfigServerPageDlgProc, 0 }
79 size_t g_nNumStates = sizeof(g_aStates) / sizeof(g_aStates[0]);
82 // Res ID's of text descriptions of each state
83 UINT g_StateDesc[] = {
101 * EXPORTED VARIABLES _________________________________________________________________
104 LPWIZARD g_pWiz = NULL;
105 LPPROPSHEET g_pSheet = NULL;
114 static void *hClientCell = 0;
121 * EXPORTED FUNCTIONS _________________________________________________________________
124 int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR pszCmdLineA, int nCmdShow)
126 afs_status_t nStatus;
128 TaLocale_LoadCorrespondingModule (hInst);
130 // Tell the applib our application's name
131 TCHAR szAppName[cchRESOURCE];
132 AfsAppLib_SetAppName(GetResString(GetAppTitleID(), szAppName));
134 // Open the admin libraries
135 int nResult = afsclient_Init(&nStatus);
137 ShowError(0, nStatus, IDS_CANT_INIT_ADMIN_LIBS);
142 char szLogPath[MAX_PATH];
143 sprintf(szLogPath, "%s\\%s", AFSDIR_SERVER_LOGS_DIRPATH, LOG_FILE_NAME);
144 if (!g_LogFile.Open(szLogPath))
145 ShowError(0, 0, IDS_CANT_OPEN_LOG_FILE);
147 // Register the help file with the applib's help system
148 AfsAppLib_RegisterHelpFile(TEXT("TaAfsCfg.hlp"));
150 /* Start up sockets */
152 WSAStartup(0x0101, &WSAjunk);
154 memset(&g_CfgData, 0, sizeof(CFG_DATA));
156 // Get this machine's local name
157 char szLocalName[sizeof(g_CfgData.szLocalName) / sizeof(TCHAR)];
158 if (gethostname(szLocalName, sizeof(szLocalName)) != 0) {
159 ShowError(GetFocus(), WSAGetLastError(), IDS_ERROR_LOCAL_HOST_NAME);
162 CopyAnsiToString(g_CfgData.szLocalName, szLocalName);
164 // Turn the local name into a host name
165 struct hostent *pHostEnt = gethostbyname(szLocalName);
167 ShowError(GetFocus(), WSAGetLastError(), IDS_ERROR_HOST_NAME);
170 CopyAnsiToString(g_CfgData.szHostname, pHostEnt->h_name, sizeof(g_CfgData.szHostname));
172 RegisterFastListClass();
174 // Get current config status
175 BOOL bCanceled = FALSE;
176 DWORD dwStatus = GetCurrentConfig(NULL, bCanceled);
177 if (dwStatus || bCanceled) {
179 ShowError(GetFocus(), dwStatus, IDS_CONFIG_CHECK_FAILED);
183 // Check the version of the client. It must be at least 35.
184 if (g_CfgData.nClientVersion < 35) {
186 nMajor = g_CfgData.nClientVersion / 10;
187 nMinor = g_CfgData.nClientVersion - (nMajor * 10);
188 g_LogFile.Write("The version of the AFS Client on this machine (%d.%d) is too old to run the server. The Client must be at least version 3.5.\r\n", nMajor, nMinor);
189 ErrorDialog(0, IDS_ERROR_CLIENT_VERSION);
193 // Run the appropriate interface
194 if ((strstr(_strlwr(pszCmdLineA), "wizard") != 0))
199 FreePartitionTable();
201 // Disconnect from the config and admin libraries
202 CloseLibHandles(TRUE);
208 * This is a dialog proc that is shared by all of the wizard pages. It
209 * handles things that are common to all of them. Each page also has its
212 BOOL CALLBACK WizStep_Common_DlgProc(HWND hRHS, UINT msg, WPARAM wp, LPARAM lp)
214 // Get the dialog's resource ID
215 int nIDD = GetWindowLong(hRHS, GWL_ID);
217 if (AfsAppLib_HandleHelp(nIDD, hRHS, msg, wp, lp))
221 case WM_INITDIALOG: MakeBold(hRHS, IDC_TITLE);
226 switch (LOWORD(wp)) {
237 BOOL QueryCancelWiz()
239 int nChoice = Message(MB_YESNO, IDS_WIZARD_APP_TITLE, IDS_CANCEL_DESC);
240 if (nChoice == IDYES) {
241 g_LogFile.Write("User has chosen to cancel the program.\r\n");
252 * Accessor functions for the g_CfgData variable. There are versions
253 * for both TCHARs and char *'s.
255 TCHAR GetDeviceName() { return g_CfgData.chDeviceName; }
256 LPTSTR GetPartitionName() { return g_CfgData.szPartitionName; }
257 LPTSTR GetHostName() { return g_CfgData.szHostname; }
258 LPTSTR GetSysControlMachine() { return g_CfgData.szSysControlMachine; }
259 LPTSTR GetCellName() { return g_CfgData.szCellName; }
260 LPTSTR GetServerPW() { return g_CfgData.szServerPW; }
261 LPTSTR GetAdminName() { return g_CfgData.szAdminName; }
262 LPTSTR GetAdminPW() { return g_CfgData.szAdminPW; }
263 LPTSTR GetAdminUID() { return g_CfgData.szAdminUID; }
264 LPTSTR GetLocalName() { return g_CfgData.szLocalName; }
265 LPTSTR GetHostname() { return g_CfgData.szHostname; }
266 LPTSTR GetCellServDbHostname() { return g_CfgData.szCellServDbHostname; }
267 LPTSTR GetClientCellName() { return g_CfgData.szClientCellName; }
268 LPTSTR GetSalvageLogFileName() { return g_CfgData.szSalvageLogFileName; }
270 LPTSTR GetClientNetbiosName()
272 static TCHAR szValue[MAX_MACHINE_NAME_LEN + 1];
274 lstrcpy(szValue, g_CfgData.szLocalName);
276 szValue[11] = TEXT('\0');
278 for (LPTSTR pch = szValue; *pch != TEXT('\0'); pch++) {
279 if (*pch == TEXT('.')) {
284 lstrcat(szValue, TEXT("-AFS"));
289 char GetDeviceNameA()
291 static char szValueA[2];
293 TCHAR devName[2] = TEXT("X");
294 devName[0] = g_CfgData.chDeviceName;
296 CopyStringToAnsi(szValueA, devName);
301 char *GetPartitionNameA()
303 static char szValueA[MAX_PARTITION_NAME_LEN + 1];
305 CopyStringToAnsi(szValueA, g_CfgData.szPartitionName);
310 char *GetSysControlMachineA()
312 static char szValueA[MAX_MACHINE_NAME_LEN + 1];
314 CopyStringToAnsi(szValueA, g_CfgData.szSysControlMachine);
321 static char szValueA[MAX_CELL_NAME_LEN + 1];
323 CopyStringToAnsi(szValueA, g_CfgData.szCellName);
330 static char szValueA[MAX_SERVER_PW_LEN + 1];
332 CopyStringToAnsi(szValueA, g_CfgData.szServerPW);
337 char *GetAdminNameA()
339 static char szValueA[MAX_ADMIN_NAME_LEN + 1];
341 CopyStringToAnsi(szValueA, g_CfgData.szAdminName);
348 static char szValueA[MAX_ADMIN_PW_LEN + 1];
350 CopyStringToAnsi(szValueA, g_CfgData.szAdminPW);
357 static char szValueA[MAX_UID_LEN + 1];
359 CopyStringToAnsi(szValueA, g_CfgData.szAdminUID);
364 char *GetLocalNameA()
366 static char szValueA[MAX_MACHINE_NAME_LEN + 1];
368 CopyStringToAnsi(szValueA, g_CfgData.szLocalName);
375 static char szValueA[MAX_MACHINE_NAME_LEN + 1];
377 CopyStringToAnsi(szValueA, g_CfgData.szHostname);
382 char *GetCellServDbHostnameA()
384 static char szValueA[MAX_MACHINE_NAME_LEN + 1];
386 CopyStringToAnsi(szValueA, g_CfgData.szCellServDbHostname);
391 char *GetClientCellNameA()
393 static char szValueA[MAX_CELL_NAME_LEN + 1];
395 CopyStringToAnsi(szValueA, g_CfgData.szClientCellName);
400 char *GetClientNetbiosNameA()
402 static char szValueA[MAX_MACHINE_NAME_LEN + 1];
405 CopyStringToAnsi(szValueA, g_CfgData.szLocalName);
409 if ((dotp = strchr(szValueA, '.')) != NULL) {
412 strcat(szValueA, "-AFS");
417 char *GetSalvageLogFileNameA()
419 static char szValueA[_MAX_PATH];
421 CopyStringToAnsi(szValueA, g_CfgData.szSalvageLogFileName);
427 BOOL GetLibHandles(afs_status_t *pStatus)
429 ASSERT(g_CfgData.szHostname[0]);
433 // ************************* NOTE ********************************
434 // * You MUST have already determined whether or not the host
435 // * and client config info is valid before calling this function.
436 // ***************************************************************
438 // This function can be called at any time to get handles to the cell and
439 // the config library. It will try to get the most powerful handle to the
440 // cell that it can, and then use that to open the config library. If the
441 // libraries are already open, it will close them first. Two handles to
442 // the config library will be opened, one to the server to be configured,
443 // and one to the client machine we are configuring from.
445 // There are two types of cell handles, NULL and Standard. A null handle
446 // can make calls to any server except DB servers. We need this primarily
447 // to talk to the bos server to determine the machine's current configuration,
448 // and to configure the client information if it is not already. A standard
449 // handle can talk to any server. Standard handles can be either authenticated
450 // or unauthenticated.
452 // Close all current handles
455 g_LogFile.Write("Getting handles to the cell and the config library.\r\n");
458 // Start by getting a null cell handle and using it to open the client
459 // connection to the config library.
460 g_LogFile.Write("Opening a NULL cell handle to use with the client config library handle.\r\n");
461 nResult = afsclient_NullCellOpen(&hClientCell, pStatus);
463 g_LogFile.Write("Failed to open a NULL cell handle: %lx.\r\n", (unsigned long)*pStatus);
467 // Get the client handle. We never need a better handle than this
468 // for the client, and so this handle will never be upgraded.
469 g_LogFile.Write("Getting config handle for the client.\r\n");
470 if (!cfg_HostOpen(hClientCell, GetHostnameA(), &g_hClient, pStatus)) {
471 g_LogFile.Write("Failed to get config handle: %lx.\r\n", (unsigned long)*pStatus);
476 // Now we need to get the most powerful cell handle that we can and use it
477 // to open the config library for the server.
479 // If the client info is valid and we know what cell the server should be in,
480 // and the client has that cell in its CellServDB, then we can get a Standard cell
481 // handle. However there is an exception: if this is the first server in the
482 // cell then there may not yet be an authentication server to talk to. In that
483 // case we use a null cell handle.
484 if (g_CfgData.bValidClientInfo && // Client config is valid
485 g_CfgData.szCellName[0] && // We have a cell name
486 (!g_CfgData.bFirstServer || g_CfgData.bAuthServerRunning)) // Auth server is running
488 g_LogFile.Write("Opening a non-NULL cell handle to use with the server config library handle.\r\n");
490 // Do we have the user info necessary to authenticate?
491 BOOL bHaveUserInfo = g_CfgData.szAdminName[0] && g_CfgData.szAdminPW[0];
493 // Open a standard cell handle. szAdminName and szAdminPW will either be NULL, or
494 // if they have been entered by the user, will be the admin name and password strings.
495 if ((!g_CfgData.bFirstServer || g_CfgData.bAdminPrincipalCreated) && bHaveUserInfo) {
496 g_LogFile.Write("Getting tokens in cell %s for user '%s'.\r\n", GetCellNameA(), GetAdminNameA());
497 nResult = afsclient_TokenGetNew(GetCellNameA(), GetAdminNameA(), GetAdminPWA(), &g_hToken, pStatus);
499 g_LogFile.Write("Getting unauthenticated tokens for cell '%s'.\r\n", GetCellNameA());
500 nResult = afsclient_TokenGetNew(GetCellNameA(), "", "", &g_hToken, pStatus);
504 g_LogFile.Write("Failed to get tokens for the specified cell: %lx.\r\n", (unsigned long)*pStatus);
508 // If the admin name and password are NULL, then this will be an unauthenticated
509 // connection to the cell.
510 g_LogFile.Write("Getting cell handle for cell %s.\r\n", GetCellNameA());
511 nResult = afsclient_CellOpen(GetCellNameA(), g_hToken, &g_hCell, pStatus);
513 g_LogFile.Write("Failed to open the cell: %lx.\r\n", (unsigned long)*pStatus);
517 g_LogFile.Write("Opening a NULL cell handle to use with the server config library handle.\r\n");
518 nResult = afsclient_NullCellOpen(&g_hCell, pStatus);
520 g_LogFile.Write("Failed to open a NULL cell handle: %lx.\r\n", (unsigned long)*pStatus);
525 // Get the server handle
526 g_LogFile.Write("Getting config library handle for the server.\r\n");
527 if (!cfg_HostOpen(g_hCell, GetHostnameA(), &g_hServer, pStatus)) {
528 g_LogFile.Write("Failed to get config library handle for the server: %lx.\r\n", (unsigned long)*pStatus);
535 BOOL GetHandles(HWND hParentDlg)
537 afs_status_t nStatus;
539 if (!GetLibHandles(&nStatus)) {
540 ShowError(hParentDlg, nStatus, IDS_GET_TOKENS_ERROR);
541 g_CfgData.szAdminPW[0] = 0;
550 * Static FUNCTIONS _________________________________________________________________
553 static void CloseLibHandles(BOOL bExiting)
555 afs_status_t nStatus;
557 // We will close them in the reverse order of their creation.
560 cfg_HostClose(g_hServer, &nStatus);
565 afsclient_CellClose(g_hCell, &nStatus);
570 afsclient_TokenClose(g_hToken, &nStatus);
574 // Only close the client cfg and cell handles if we are exiting.
577 cfg_HostClose(g_hClient, &nStatus);
582 afsclient_CellClose(hClientCell, &nStatus);
588 static void SetConfigDefaults()
590 if (g_CfgData.bWizard) {
591 if (g_CfgData.configFS == CS_NULL)
592 g_CfgData.configFS = CS_CONFIGURE;
594 if (g_CfgData.configDB == CS_NULL)
595 g_CfgData.configDB = CS_CONFIGURE;
597 if (g_CfgData.configBak == CS_NULL)
598 g_CfgData.configBak = CS_CONFIGURE;
600 if (g_CfgData.configPartition == CS_NULL)
601 g_CfgData.configPartition = CS_CONFIGURE;
603 if (g_CfgData.configRootVolumes == CS_NULL)
604 g_CfgData.configRootVolumes = CS_CONFIGURE;
606 if (g_CfgData.configRep == CS_NULL)
607 g_CfgData.configRep = CS_CONFIGURE;
609 if (g_CfgData.configSCS == CS_NULL)
610 g_CfgData.configSCS = CS_DONT_CONFIGURE;
612 if (g_CfgData.configSCC == CS_NULL)
613 g_CfgData.configSCC = CS_DONT_CONFIGURE;
616 lstrcpy(g_CfgData.szAdminName, TEXT("admin"));
617 lstrcpy(g_CfgData.szAdminUID, TEXT("0"));
619 g_CfgData.bUseNextUid = TRUE;
623 // Prototypes for each property page's dialog proc
624 BOOL CALLBACK PartitionsPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
625 BOOL CALLBACK ServicesPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
627 static void RunCfgTool()
629 // If the client info is invalid, then the config tool cannot run. Inform the user and
630 // ask if they want to run the wizard instead.
631 if (!g_CfgData.bValidClientInfo) {
632 int nChoice = MsgBox(0, IDS_NEED_CLIENT_INFO, GetAppTitleID(), MB_YESNO | MB_ICONSTOP);
633 if (nChoice == IDYES)
638 // If the server info is invalid, then the config tool cannot run. The Wizard must be run
639 // to initially configure the server. Inform the user and ask if they want to run the wizard instead.
640 if (!g_CfgData.bValidServerInfo) {
641 int nChoice = MsgBox(0, IDS_NEED_SERVER_INFO, GetAppTitleID(), MB_OKCANCEL | MB_ICONEXCLAMATION);
647 g_CfgData.bWizard = FALSE;
651 RegisterConfigToolHelp();
653 // Create the prop sheet
654 g_pSheet = PropSheet_Create(IDS_CFG_TOOL_APP_TITLE, TRUE);
657 PropSheet_AddTab(g_pSheet, IDS_PARTITIONS_PAGE_TITLE, IDD_PARTITIONS_PAGE, (DLGPROC)PartitionsPageDlgProc, 0, TRUE, TRUE);
658 PropSheet_AddTab(g_pSheet, IDS_SERVICES_PAGE_TITLE, IDD_SERVICES_PAGE, (DLGPROC)ServicesPageDlgProc, 0, TRUE);
660 // Let the user see it
661 PropSheet_ShowModal(g_pSheet);
664 static void RunWizard()
666 g_CfgData.bWizard = TRUE;
670 RegisterWizardHelp();
673 g_pWiz->SetDialogTemplate(IDD_WIZARD, IDC_WIZARD_LEFTPANE, IDC_WIZARD_RIGHTPANE, IDBACK, IDNEXT);
674 g_pWiz->SetGraphic(IDB_GRAPHIC_16, IDB_GRAPHIC_256);
675 g_pWiz->SetStates(g_aStates, g_nNumStates);
676 g_pWiz->SetGraphicCallback(PaintPageGraphic);
678 g_pWiz->SetState(sidSTEP_ONE);