Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2719 lines
78 KiB

  1. //--------------------------------------------------------------------------
  2. #ifndef WIN32_LEAN_AND_MEAN
  3. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
  4. #endif
  5. #ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
  6. #define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
  7. #endif
  8. // Windows Header Files:
  9. #include <windows.h>
  10. #include <sddl.h>
  11. #include <setupapi.h>
  12. #include <lmcons.h>
  13. #include "ocmanage.h"
  14. #include "uddiocm.h"
  15. #include "uddiinst.h"
  16. #include "assert.h"
  17. #include "..\shared\common.h"
  18. #include "resource.h"
  19. #include "objectpicker.h"
  20. #include <shlobj.h>
  21. #include <ntsecapi.h>
  22. #include <iiscnfg.h> // MD_ & IIS_MD_ defines
  23. #ifndef MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM
  24. #define MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM 0
  25. #define MD_APPPOOL_IDENTITY_TYPE_LOCALSERVICE 1
  26. #define MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE 2
  27. #define MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER 3
  28. #endif
  29. #define NOT_FIRST_OR_LAST_WIZARD_PAGE false
  30. #define FINAL_WIZARD_PAGE true
  31. #define WELCOME_WIZARD_PAGE true
  32. #ifndef STATUS_SUCCESS
  33. #define STATUS_SUCCESS 0
  34. #endif
  35. //--------------------------------------------------------------------------
  36. #define PASSWORD_LEN PWLEN // maximum password length
  37. #define USERNAME_LEN UNLEN // maximum user name length
  38. #define UDDI_MAXPROVNAME_LEN 255 // maximum UDDI Business Entity name length
  39. #define UDDI_ILLEGALNAMECHARS TEXT( "\":;/\\?*" )
  40. extern HINSTANCE g_hInstance;
  41. extern CUDDIInstall g_uddiComponents;
  42. static CDBInstance g_dbLocalInstances;
  43. static CDBInstance g_dbRemoteInstances;
  44. static HWND g_hPropSheet = NULL ;
  45. static HFONT g_hTitleFont = 0;
  46. static TCHAR g_szPwd[ PASSWORD_LEN + 1 ];
  47. //
  48. // "allowed" drive letters for a clustered environment scenario.
  49. // Not used for a "regular" installation
  50. //
  51. static CLST_ALLOWED_DRIVES gAllowedClusterDrives;
  52. //
  53. // This controls whether the Data Paths page will be shown in "simple" mode by default
  54. //
  55. static BOOL g_bSimpleDatapathUI = TRUE;
  56. static BOOL g_bResetPathFields = FALSE;
  57. //
  58. // This controls whether we do clustering data collection. This variable is used
  59. // to coordinate operation between pages
  60. //
  61. static BOOL g_bSkipClusterAnalysis = FALSE;
  62. static BOOL g_bOnActiveClusterNode = TRUE;
  63. static BOOL g_bPreserveDatabase = FALSE;
  64. static int DisplayUDDIErrorDialog( HWND hDlg, UINT uMsgID, UINT uType = MB_OK | MB_ICONWARNING, DWORD dwError = 0 );
  65. static void ParseUserAccount( PTCHAR szDomainAndUser, UINT uDomainAndUserSize, PTCHAR szUser, UINT uUserSize, PTCHAR szDomain, UINT uDomainSize, bool &bLocalAccount );
  66. static BOOL GetWellKnownAccountName( WELL_KNOWN_SID_TYPE sidWellKnown, TCHAR *pwszName, DWORD *pcbSize );
  67. BOOL ShowBrowseDirDialog( HWND hParent, LPCTSTR szTitle, LPTSTR szOutBuf );
  68. int CALLBACK BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData );
  69. static BOOL GrantNetworkLogonRights( LPCTSTR pwszDomainUser );
  70. //--------------------------------------------------------------------------
  71. INT_PTR CALLBACK LocalDBInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  72. INT_PTR CALLBACK RemoteDBInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  73. INT_PTR CALLBACK SSLDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  74. INT_PTR CALLBACK ProviderInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  75. INT_PTR CALLBACK AddSvcDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  76. INT_PTR CALLBACK LoginDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  77. INT_PTR CALLBACK WizardSummaryDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  78. INT_PTR CALLBACK DataPathsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  79. INT_PTR CALLBACK ExistingDBInstanceProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  80. INT_PTR CALLBACK ClusterDataDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  81. BOOL CALLBACK ConfirmPasswordDlgProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam );
  82. //--------------------------------------------------------------------------
  83. static int DisplayUDDIErrorDialog( HWND hDlg, UINT uMsgID, UINT uType, DWORD dwError )
  84. {
  85. TCHAR szMsg[ 1000 ];
  86. TCHAR szTitle[ 100 ];
  87. LoadString( g_hInstance, uMsgID, szMsg, sizeof( szMsg ) / sizeof( TCHAR ) );
  88. LoadString( g_hInstance, IDS_TITLE, szTitle, sizeof( szTitle ) / sizeof( TCHAR ) );
  89. tstring cMsg = szMsg;
  90. if( dwError )
  91. {
  92. LPVOID lpMsgBuf;
  93. FormatMessage(
  94. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  95. FORMAT_MESSAGE_FROM_SYSTEM |
  96. FORMAT_MESSAGE_IGNORE_INSERTS,
  97. NULL,
  98. dwError,
  99. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  100. (LPTSTR) &lpMsgBuf,
  101. 0,
  102. NULL
  103. );
  104. //
  105. // FIX: 718923: this used to throw an exception if lpMsgBuf was NULL
  106. //
  107. if( lpMsgBuf )
  108. {
  109. if ( cMsg.length() > 0 )
  110. cMsg.append( TEXT( " " ) );
  111. cMsg.append( (LPTSTR) lpMsgBuf );
  112. LocalFree( lpMsgBuf );
  113. }
  114. }
  115. return MessageBox( hDlg, cMsg.c_str(), szTitle, uType );
  116. }
  117. //--------------------------------------------------------------------------
  118. inline int SkipWizardPage( const HWND hdlg )
  119. {
  120. SetWindowLongPtr( hdlg, DWLP_MSGRESULT, -1 );
  121. return 1; //Must return 1 for the page to be skipped
  122. }
  123. //--------------------------------------------------------------------------
  124. static HPROPSHEETPAGE CreatePage(
  125. const int nID,
  126. const DLGPROC pDlgProc,
  127. const PTCHAR szTitle,
  128. const PTCHAR szSubTitle,
  129. bool bFirstOrLast )
  130. {
  131. PROPSHEETPAGE Page;
  132. memset( &Page, 0, sizeof( PROPSHEETPAGE ) );
  133. Page.dwSize = sizeof( PROPSHEETPAGE );
  134. Page.dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE | PSP_USETITLE;
  135. // use PSP_USETITLE without specifying szTitle to keep from overwriting the default propery page title
  136. if ( bFirstOrLast )
  137. {
  138. Page.dwFlags |= PSP_HIDEHEADER;
  139. }
  140. Page.hInstance = ( HINSTANCE )g_hInstance;
  141. Page.pszTemplate = MAKEINTRESOURCE( nID );
  142. Page.pfnDlgProc = pDlgProc;
  143. Page.pszHeaderTitle = _tcsdup( szTitle );
  144. Page.pszHeaderSubTitle = _tcsdup( szSubTitle );
  145. HPROPSHEETPAGE PageHandle = CreatePropertySheetPage( &Page );
  146. return PageHandle;
  147. }
  148. //--------------------------------------------------------------------------
  149. DWORD AddUDDIWizardPages( const TCHAR *ComponentId, const WizardPagesType WhichOnes, SETUP_REQUEST_PAGES *SetupPages )
  150. {
  151. ENTER();
  152. HPROPSHEETPAGE pPage = NULL;
  153. DWORD iPageIndex = 0 ;
  154. TCHAR szTitle[ 256 ];
  155. TCHAR szSubtitle[ 256 ];
  156. LoadString( g_hInstance, IDS_TITLE, szTitle, sizeof( szTitle ) / sizeof( TCHAR ) );
  157. //
  158. // only add our pages when the OCM asks for the "Late Pages"
  159. //
  160. if( WizPagesLate == WhichOnes )
  161. {
  162. if( SetupPages->MaxPages < 9 )
  163. return 9;
  164. //
  165. // add the local db instance selection page
  166. //
  167. LoadString( g_hInstance, IDS_DB_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  168. pPage = CreatePage( IDD_DB_INSTANCE, LocalDBInstanceDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  169. if ( NULL == pPage )
  170. {
  171. Log( TEXT( "***Unable to add the IDD_DB_INSTANCE Property Page" ) );
  172. return( (DWORD)( -1 ) );
  173. }
  174. SetupPages->Pages[iPageIndex] = pPage;
  175. iPageIndex++;
  176. //
  177. // add the hidden clustering "data collector" page
  178. //
  179. pPage = CreatePage( IDD_CLUSTDATA, ClusterDataDlgProc, TEXT( "" ), TEXT( "" ), NOT_FIRST_OR_LAST_WIZARD_PAGE );
  180. if ( NULL == pPage )
  181. {
  182. Log( TEXT( "***Unable to add the IDD_CLUSTDATA Property Page" ) );
  183. return( (DWORD)( -1 ) );
  184. }
  185. SetupPages->Pages[iPageIndex] = pPage;
  186. iPageIndex++;
  187. //
  188. // add the "uddi instance found" info page
  189. //
  190. LoadString( g_hInstance, IDS_EXISTINGDB_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  191. pPage = CreatePage( IDD_EXISTING_DBINSTANCE, ExistingDBInstanceProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  192. if ( NULL == pPage )
  193. {
  194. Log( TEXT( "***Unable to add the IDD_EXISTING_DBINSTANCE Property Page" ) );
  195. return( (DWORD)( -1 ) );
  196. }
  197. SetupPages->Pages[iPageIndex] = pPage;
  198. iPageIndex++;
  199. //
  200. // add the SSL page
  201. //
  202. LoadString( g_hInstance, IDS_SSL_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  203. pPage = CreatePage( IDD_SSL, SSLDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  204. if ( NULL == pPage )
  205. {
  206. Log( TEXT( "***Unable to add the IDD_SSL Property Page" ) );
  207. return( (DWORD)( -1 ) );
  208. }
  209. SetupPages->Pages[iPageIndex] = pPage;
  210. iPageIndex++;
  211. //
  212. // add the remote db instance selection page
  213. //
  214. LoadString( g_hInstance, IDS_REMOTE_DB_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  215. pPage = CreatePage( IDD_REMOTE_DB, RemoteDBInstanceDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  216. if ( NULL == pPage )
  217. {
  218. Log( TEXT( "***Unable to add the IDD_REMOTE_DB Property Page" ) );
  219. return( (DWORD)( -1 ) );
  220. }
  221. SetupPages->Pages[iPageIndex] = pPage;
  222. iPageIndex++;
  223. //
  224. // add the data file path(s) selection page
  225. //
  226. LoadString( g_hInstance, IDS_FILEPATHS_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  227. pPage = CreatePage( IDD_DATAPATHS, DataPathsDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  228. if ( NULL == pPage )
  229. {
  230. Log( TEXT( "***Unable to add the IDD_DATAPATHS Property Page" ) );
  231. return( (DWORD)( -1 ) );
  232. }
  233. SetupPages->Pages[iPageIndex] = pPage;
  234. iPageIndex++;
  235. //
  236. // add the authentication page
  237. //
  238. LoadString( g_hInstance, IDS_LOGIN_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  239. pPage = CreatePage( IDD_LOGIN, LoginDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  240. if ( NULL == pPage )
  241. {
  242. Log( TEXT( "***Unable to add the IDD_LOGIN Property Page" ) );
  243. return( (DWORD)( -1 ) );
  244. }
  245. SetupPages->Pages[iPageIndex] = pPage;
  246. iPageIndex++;
  247. //
  248. // add the UDDI Provider Name page
  249. //
  250. LoadString( g_hInstance, IDS_UDDIPROV_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  251. pPage = CreatePage( IDD_SITE_NAME, ProviderInstanceDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  252. if ( NULL == pPage )
  253. {
  254. Log( TEXT( "***Unable to add the IDD_SITE_NAME Property Page" ) );
  255. return( (DWORD)( -1 ) );
  256. }
  257. SetupPages->Pages[iPageIndex] = pPage;
  258. iPageIndex++;
  259. //
  260. // add the UDDI "Add Service / Update AD"
  261. //
  262. LoadString( g_hInstance, IDS_UDDIADDSVC_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  263. pPage = CreatePage( IDD_ADD_SERVICES, AddSvcDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  264. if ( NULL == pPage )
  265. {
  266. Log( TEXT( "***Unable to add the IDD_ADD_SERVICES Property Page" ) );
  267. return( (DWORD)( -1 ) );
  268. }
  269. SetupPages->Pages[iPageIndex] = pPage;
  270. iPageIndex++;
  271. //
  272. // add the wizard summary page
  273. //
  274. /*
  275. LoadString( g_hInstance, IDS_WIZARD_SUMMARY_SUBTITLE, szSubtitle, sizeof( szSubtitle ) / sizeof( TCHAR ) );
  276. pPage = CreatePage( IDD_WIZARD_SUMMARY, WizardSummaryDlgProc, szTitle, szSubtitle, NOT_FIRST_OR_LAST_WIZARD_PAGE );
  277. //pPage = CreatePage( IDD_WIZARD_SUMMARY, WizardSummaryDlgProc, szTitle, szSubtitle, FINAL_WIZARD_PAGE );
  278. if ( NULL == pPage )
  279. {
  280. Log( TEXT( "***Unable to add the IDD_LOGIN Property Page" ) );
  281. return( ( DWORD )( -1 ) );
  282. }
  283. SetupPages->Pages[iPageIndex] = pPage;
  284. iPageIndex++;
  285. */
  286. }
  287. return iPageIndex;
  288. }
  289. //--------------------------------------------------------------------------
  290. INT_PTR CALLBACK LocalDBInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  291. {
  292. switch( msg )
  293. {
  294. case WM_INITDIALOG:
  295. {
  296. //
  297. // start off with MSDE to not install
  298. //
  299. g_uddiComponents.SetInstallLevel( UDDI_MSDE, UDDI_NOACTION );
  300. //
  301. // get a handle to the list box
  302. //
  303. HWND hwndList = GetDlgItem( hDlg, IDC_LIST_DB_INSTANCES );
  304. //
  305. // Get the list of SQL 2000 ( only ) database instances and, if any are found, populate the list box
  306. //
  307. LONG iRet = g_dbLocalInstances.GetInstalledDBInstanceNames();
  308. if( ERROR_SUCCESS == iRet )
  309. {
  310. TCHAR szBuffer[ 50 ];
  311. for( int i = 0; i < g_dbLocalInstances.GetInstanceCount(); i++ )
  312. {
  313. if( g_dbLocalInstances.GetInstanceName( i, szBuffer, 50 ) )
  314. {
  315. DWORD iIndex = (DWORD) SendMessage( hwndList, CB_ADDSTRING, 0, (LPARAM)szBuffer );
  316. SendMessage( hwndList, CB_SETITEMDATA, (WPARAM) iIndex, (LPARAM)i );
  317. }
  318. }
  319. }
  320. //
  321. // Is SQL on this box?
  322. //
  323. if( g_dbLocalInstances.GetInstanceCount() > 0 )
  324. {
  325. //
  326. // select the SQL radio button
  327. //
  328. CheckRadioButton( hDlg,
  329. IDC_RADIO_INSTALL_MSDE,
  330. IDC_RADIO_USE_EXISTING_INSTANCE,
  331. IDC_RADIO_USE_EXISTING_INSTANCE );
  332. //
  333. // is there an instance named "UDDI" on this machine?
  334. //
  335. // If NO, then select the 1st entry in the combo box.
  336. //
  337. // If YES, then select the "UDDI" entry from the combo box. Also, disable
  338. // the option to select MSDE.
  339. //
  340. // FIX: 763442 There was a problem with the test to determine if a SQL Instance named
  341. // "UDDI" was installed.
  342. //
  343. // BUGBUG:CREEVES This function is named improperly Is...() should return a bool
  344. //
  345. if( g_dbLocalInstances.IsInstanceInstalled( UDDI_MSDE_INSTANCE_NAME ) >= 0 )
  346. {
  347. //
  348. // Found a SQL Instance named "UDDI"
  349. //
  350. //
  351. // Disable the MSDE radio, as there is another UDDI instance found
  352. //
  353. EnableWindow( GetDlgItem( hDlg, IDC_RADIO_INSTALL_MSDE ), false );
  354. SendMessage( hwndList, CB_SETCURSEL, 0, 0 );
  355. }
  356. else
  357. {
  358. //
  359. // A SQL Instance named "UDDI" was not found
  360. //
  361. SendMessage( hwndList, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) UDDI_MSDE_INSTANCE_NAME );
  362. }
  363. }
  364. else
  365. {
  366. //
  367. // there are no sql instances on this machine
  368. // disable the SQL radio button and list box
  369. //
  370. EnableWindow( GetDlgItem( hDlg, IDC_LIST_DB_INSTANCES ), false );
  371. EnableWindow( GetDlgItem( hDlg, IDC_RADIO_USE_EXISTING_INSTANCE ), false );
  372. //
  373. // select the MSDE radio button
  374. //
  375. CheckRadioButton( hDlg,
  376. IDC_RADIO_INSTALL_MSDE,
  377. IDC_RADIO_USE_EXISTING_INSTANCE,
  378. IDC_RADIO_INSTALL_MSDE );
  379. }
  380. //
  381. // find out if our instance of MSDE ( SqlRun08.msi ) is already used on this machine
  382. //
  383. bool bIsSqlRun08AlreadyUsed = false;
  384. if( !IsSQLRun08AlreadyUsed( &bIsSqlRun08AlreadyUsed ) )
  385. {
  386. Log( TEXT( "IsSQLRun08AlreadyUsed() failed" ) );
  387. break;
  388. }
  389. if( bIsSqlRun08AlreadyUsed )
  390. {
  391. //
  392. // MSDE is already installed, so disable the MSDE radio button
  393. //
  394. EnableWindow( GetDlgItem( hDlg, IDC_RADIO_INSTALL_MSDE ), false );
  395. }
  396. else
  397. {
  398. //
  399. // MSDE is NOT on this box, but before we select the MSDE radio button
  400. // we want to see if there is a SQL instance named UDDI,
  401. // if so we'll make that the default.
  402. //
  403. if( -1 == g_dbLocalInstances.IsInstanceInstalled( UDDI_MSDE_INSTANCE_NAME ) )
  404. {
  405. CheckRadioButton( hDlg,
  406. IDC_RADIO_INSTALL_MSDE,
  407. IDC_RADIO_USE_EXISTING_INSTANCE,
  408. IDC_RADIO_INSTALL_MSDE );
  409. }
  410. }
  411. //
  412. // enable/disable the list box
  413. //
  414. EnableWindow( GetDlgItem( hDlg, IDC_LIST_DB_INSTANCES ), IsDlgButtonChecked( hDlg, IDC_RADIO_USE_EXISTING_INSTANCE ) );
  415. }
  416. break;
  417. case WM_COMMAND:
  418. //
  419. // someone clicked a radio button:
  420. //
  421. if( LOWORD( wParam ) == IDC_RADIO_INSTALL_MSDE || LOWORD( wParam ) == IDC_RADIO_USE_EXISTING_INSTANCE )
  422. {
  423. if( HIWORD( wParam ) == BN_CLICKED )
  424. {
  425. // disable the list box if its radio button is not clicked
  426. EnableWindow( GetDlgItem( hDlg, IDC_LIST_DB_INSTANCES ), IsDlgButtonChecked( hDlg, IDC_RADIO_USE_EXISTING_INSTANCE ) );
  427. }
  428. }
  429. break;
  430. case WM_NOTIFY:
  431. {
  432. switch( ( ( NMHDR * )lParam )->code )
  433. {
  434. //
  435. // this is called once when the page is created
  436. //
  437. case PSN_SETACTIVE:
  438. {
  439. //
  440. // this page needed only if we are installing the DB
  441. //
  442. g_uddiComponents.UpdateAllInstallLevel();
  443. //
  444. // Set the flag for ClusterDataProc so that when the user clicks "Next"
  445. // it won't skip the data collection step
  446. //
  447. g_bSkipClusterAnalysis = FALSE;
  448. if( g_uddiComponents.IsInstalling( UDDI_DB ) )
  449. {
  450. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  451. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  452. return 1;
  453. }
  454. else
  455. {
  456. return SkipWizardPage( hDlg );
  457. }
  458. }
  459. //
  460. // this message is sent when the user presses the "next" button
  461. //
  462. case PSN_WIZNEXT:
  463. {
  464. //
  465. // are we installing MSDE?
  466. //
  467. bool bInstallMSDE = ( BST_CHECKED == IsDlgButtonChecked( hDlg, IDC_RADIO_INSTALL_MSDE ) );
  468. if( bInstallMSDE )
  469. {
  470. //
  471. // check to see if SqlRun08 is already on this box
  472. //
  473. bool bIsSqlRun08AlreadyUsed = false;
  474. IsSQLRun08AlreadyUsed( &bIsSqlRun08AlreadyUsed );
  475. if( bIsSqlRun08AlreadyUsed )
  476. {
  477. DisplayUDDIErrorDialog( hDlg, IDS_MSDE_ALREADY_USED );
  478. SetWindowLongPtr( hDlg,DWLP_MSGRESULT, 1 );
  479. return 1; // to keep the focus on this page
  480. }
  481. //
  482. // set the MSDE instance name to "UDDI"
  483. //
  484. g_uddiComponents.SetDBInstanceName( UDDI_LOCAL_COMPUTER, UDDI_MSDE_INSTANCE_NAME, UDDI_INSTALLING_MSDE, false );
  485. //
  486. // set MSDE to install
  487. //
  488. g_uddiComponents.SetInstallLevel( UDDI_MSDE, UDDI_INSTALL, TRUE );
  489. //
  490. // exit this property page
  491. //
  492. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  493. return 1; // done
  494. }
  495. //
  496. // we are using an existing instance of SQL
  497. //
  498. else
  499. {
  500. //
  501. // get a handle to the combobox
  502. //
  503. HWND hwndList = GetDlgItem( hDlg, IDC_LIST_DB_INSTANCES );
  504. //
  505. // get the index of the string that is currently selected in the combobox
  506. //
  507. int nItem = ( int ) SendMessage( hwndList, CB_GETCURSEL, 0, 0 );
  508. //
  509. // if no string is selected, raise an error
  510. //
  511. if( CB_ERR == nItem )
  512. {
  513. DisplayUDDIErrorDialog( hDlg, IDS_NO_INSTANCE_MSG );
  514. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  515. return 1; // to keep the focus on this page
  516. }
  517. //
  518. // get the index into the instance array of the selected item
  519. //
  520. int nInstanceIndex = ( int ) SendMessage( hwndList, CB_GETITEMDATA, nItem, ( LPARAM ) 0 );
  521. //
  522. // Now verify that the selected instance meets our requirements
  523. //
  524. if( CompareVersions( g_dbLocalInstances.m_dbinstance[ nInstanceIndex ].cSPVersion.c_str(),
  525. MIN_SQLSP_VERSION ) < 0 )
  526. {
  527. DisplayUDDIErrorDialog( hDlg, IDS_SQLSPVERSION_TOO_LOW );
  528. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  529. return 1; // to keep the focus on this page
  530. }
  531. //
  532. // set the instance name
  533. //
  534. g_uddiComponents.SetDBInstanceName(
  535. g_dbLocalInstances.m_dbinstance[ nInstanceIndex ].cComputerName.c_str(),
  536. g_dbLocalInstances.m_dbinstance[ nInstanceIndex ].cSQLInstanceName.c_str(),
  537. UDDI_NOT_INSTALLING_MSDE,
  538. g_dbLocalInstances.m_dbinstance[ nInstanceIndex ].bIsCluster );
  539. //
  540. // Set MSDE to NOT INSTALL
  541. //
  542. g_uddiComponents.SetInstallLevel( UDDI_MSDE, UDDI_NOACTION );
  543. //
  544. // exit this property page
  545. //
  546. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  547. return 1; // done
  548. }
  549. }
  550. case PSN_QUERYCANCEL:
  551. {
  552. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  553. return 1;
  554. }
  555. }
  556. }
  557. }
  558. return 0;
  559. }
  560. //--------------------------------------------------------------------------
  561. INT_PTR CALLBACK SSLDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  562. {
  563. switch( msg )
  564. {
  565. case WM_INITDIALOG:
  566. //
  567. // turn SSL on by default
  568. //
  569. CheckRadioButton( hDlg, IDC_SSL_YES, IDC_SSL_NO, IDC_SSL_YES );
  570. break;
  571. case WM_COMMAND:
  572. break;
  573. case WM_NOTIFY:
  574. {
  575. switch( ( ( NMHDR * )lParam )->code )
  576. {
  577. //
  578. // this is called once when the page is created
  579. //
  580. case PSN_SETACTIVE:
  581. {
  582. //
  583. // this page needed only if we are installing the DB
  584. //
  585. g_uddiComponents.UpdateAllInstallLevel();
  586. if( g_uddiComponents.IsInstalling( UDDI_DB ) && g_bOnActiveClusterNode && !g_bPreserveDatabase )
  587. {
  588. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  589. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  590. return 1;
  591. }
  592. else
  593. {
  594. return SkipWizardPage( hDlg );
  595. }
  596. }
  597. case PSN_WIZNEXT:
  598. {
  599. //
  600. // set the SSL mode by adding a property to the DB setup command line
  601. //
  602. bool bUseSSL = ( BST_CHECKED == IsDlgButtonChecked( hDlg, IDC_SSL_YES ) );
  603. g_uddiComponents.AddProperty( UDDI_DB, TEXT( "SSL" ), bUseSSL ? 1 : 0 );
  604. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  605. return 1;
  606. }
  607. case PSN_QUERYCANCEL:
  608. {
  609. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  610. return 1;
  611. }
  612. }
  613. }
  614. }
  615. return 0;
  616. }
  617. //
  618. //--------------------------------------------------------------------------
  619. //
  620. INT_PTR CALLBACK ProviderInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  621. {
  622. switch( msg )
  623. {
  624. case WM_INITDIALOG:
  625. //
  626. // set the maximum edit field length
  627. //
  628. SendMessage( GetDlgItem( hDlg, IDC_SITE_NAME ), EM_LIMITTEXT, ( WPARAM ) UDDI_MAXPROVNAME_LEN, 0 );
  629. break;
  630. case WM_COMMAND:
  631. break;
  632. case WM_NOTIFY:
  633. {
  634. switch( ( ( NMHDR * )lParam )->code )
  635. {
  636. //
  637. // this is called once when the page is created
  638. //
  639. case PSN_SETACTIVE:
  640. {
  641. //
  642. // this page needed only if we are installing the DB
  643. //
  644. g_uddiComponents.UpdateAllInstallLevel();
  645. if( g_uddiComponents.IsInstalling( UDDI_DB ) && g_bOnActiveClusterNode && !g_bPreserveDatabase )
  646. {
  647. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  648. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  649. return 1;
  650. }
  651. else
  652. {
  653. return SkipWizardPage( hDlg );
  654. }
  655. }
  656. case PSN_WIZNEXT:
  657. {
  658. //
  659. // set the Provider Instance Name by adding a property to the DB setup command line
  660. //
  661. TCHAR buf[ UDDI_MAXPROVNAME_LEN + 1 ];
  662. ZeroMemory( buf, sizeof buf );
  663. int iChars = GetWindowText( GetDlgItem( hDlg, IDC_SITE_NAME ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  664. if( 0 == iChars )
  665. {
  666. DisplayUDDIErrorDialog( hDlg, IDS_ZERO_LEN_PROVIDER_NAME );
  667. SetFocus( GetDlgItem( hDlg, IDC_SITE_NAME ) );
  668. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  669. return 1; // to keep the focus on this page
  670. }
  671. //
  672. // Now verify that the instance name does not contain illegal characters
  673. //
  674. TCHAR *pIllegalChar = _tcspbrk( buf, UDDI_ILLEGALNAMECHARS );
  675. if ( pIllegalChar )
  676. {
  677. DisplayUDDIErrorDialog( hDlg, IDS_UDDI_ILLEGALCHARACTERS );
  678. SetFocus( GetDlgItem( hDlg, IDC_SITE_NAME ) );
  679. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  680. return 1; // to keep the focus on this page
  681. }
  682. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_UDDIPROVIDER, buf );
  683. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  684. return 1;
  685. }
  686. case PSN_QUERYCANCEL:
  687. {
  688. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  689. return 1;
  690. }
  691. }
  692. }
  693. }
  694. return 0;
  695. }
  696. //
  697. //-----------------------------------------------------------------------------------
  698. //
  699. void ToggleDatapathUI ( HWND hDlg, BOOL bToSimple )
  700. {
  701. TCHAR szBuf[ 256 ];
  702. if ( bToSimple )
  703. {
  704. //
  705. // Hide fields
  706. //
  707. ShowWindow( GetDlgItem( hDlg, IDC_COREPATH_1 ), SW_HIDE );
  708. ShowWindow( GetDlgItem( hDlg, IDC_COREPATH_2 ), SW_HIDE );
  709. ShowWindow( GetDlgItem( hDlg, IDC_JRNLPATH ), SW_HIDE );
  710. ShowWindow( GetDlgItem( hDlg, IDC_STAGINGPATH ), SW_HIDE );
  711. ShowWindow( GetDlgItem( hDlg, IDC_XLOGPATH ), SW_HIDE );
  712. //
  713. // Hide buttons
  714. //
  715. ShowWindow( GetDlgItem( hDlg, IDC_BROWSECOREPATH1 ), SW_HIDE );
  716. ShowWindow( GetDlgItem( hDlg, IDC_BROWSECOREPATH2 ), SW_HIDE );
  717. ShowWindow( GetDlgItem( hDlg, IDC_BROWSEJRNLPATH ), SW_HIDE );
  718. ShowWindow( GetDlgItem( hDlg, IDC_BROWSESTAGINGPATH ), SW_HIDE );
  719. ShowWindow( GetDlgItem( hDlg, IDC_BROWSEXLOGPATH ), SW_HIDE );
  720. ShowWindow( GetDlgItem( hDlg, IDC_LESS_BTN ), SW_HIDE );
  721. ShowWindow( GetDlgItem( hDlg, IDC_MORE_BTN ), SW_SHOW );
  722. //
  723. // Hide labels and adjust the text
  724. //
  725. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_C1 ), SW_HIDE );
  726. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_C2 ), SW_HIDE );
  727. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_JRNL ), SW_HIDE );
  728. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_STG ), SW_HIDE );
  729. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_XLOG ), SW_HIDE );
  730. LoadString( g_hInstance, IDS_LABEL_SYSPATHSIMPLE, szBuf, (sizeof szBuf / sizeof szBuf[0]) - 1 );
  731. SetDlgItemText( hDlg, IDC_STATIC_SYS, szBuf );
  732. }
  733. else
  734. {
  735. //
  736. // Show fields
  737. //
  738. ShowWindow( GetDlgItem( hDlg, IDC_COREPATH_1 ), SW_SHOW );
  739. ShowWindow( GetDlgItem( hDlg, IDC_COREPATH_2 ), SW_SHOW );
  740. ShowWindow( GetDlgItem( hDlg, IDC_JRNLPATH ), SW_SHOW );
  741. ShowWindow( GetDlgItem( hDlg, IDC_STAGINGPATH ), SW_SHOW );
  742. ShowWindow( GetDlgItem( hDlg, IDC_XLOGPATH ), SW_SHOW );
  743. //
  744. // Show buttons
  745. //
  746. ShowWindow( GetDlgItem( hDlg, IDC_MORE_BTN ), SW_HIDE );
  747. ShowWindow( GetDlgItem( hDlg, IDC_LESS_BTN ), SW_SHOW );
  748. ShowWindow( GetDlgItem( hDlg, IDC_BROWSECOREPATH1 ), SW_SHOW );
  749. ShowWindow( GetDlgItem( hDlg, IDC_BROWSECOREPATH2 ), SW_SHOW );
  750. ShowWindow( GetDlgItem( hDlg, IDC_BROWSEJRNLPATH ), SW_SHOW );
  751. ShowWindow( GetDlgItem( hDlg, IDC_BROWSESTAGINGPATH ), SW_SHOW );
  752. ShowWindow( GetDlgItem( hDlg, IDC_BROWSEXLOGPATH ), SW_SHOW );
  753. //
  754. // Show labels and adjust the text
  755. //
  756. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_C1 ), SW_SHOW );
  757. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_C2 ), SW_SHOW );
  758. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_JRNL ), SW_SHOW );
  759. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_STG ), SW_SHOW );
  760. ShowWindow( GetDlgItem( hDlg, IDC_STATIC_XLOG ), SW_SHOW );
  761. LoadString( g_hInstance, IDS_LABEL_SYSPATH_ADV, szBuf, (sizeof szBuf / sizeof szBuf[0]) - 1 );
  762. SetDlgItemText( hDlg, IDC_STATIC_SYS, szBuf );
  763. }
  764. }
  765. void SetAllDatapathFields ( HWND hDlg, LPCTSTR szValue )
  766. {
  767. SetDlgItemText( hDlg, IDC_SYSPATH, szValue );
  768. SetDlgItemText( hDlg, IDC_COREPATH_1, szValue );
  769. SetDlgItemText( hDlg, IDC_COREPATH_2, szValue );
  770. SetDlgItemText( hDlg, IDC_JRNLPATH, szValue );
  771. SetDlgItemText( hDlg, IDC_STAGINGPATH, szValue );
  772. SetDlgItemText( hDlg, IDC_XLOGPATH, szValue );
  773. }
  774. INT_PTR CALLBACK ClusterDataDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  775. {
  776. switch( msg )
  777. {
  778. case WM_NOTIFY:
  779. {
  780. switch( ( ( NMHDR * )lParam )->code )
  781. {
  782. //
  783. // this is called once when the page is created
  784. //
  785. case PSN_SETACTIVE:
  786. {
  787. bool bSuppressInactiveWarning = false;
  788. //
  789. // We ALWAYS skip the page, but if this is a DB installation, then we
  790. // also need to do some data collection here
  791. //
  792. g_uddiComponents.UpdateAllInstallLevel();
  793. if( !g_bSkipClusterAnalysis )
  794. {
  795. //
  796. // Here we do our cluster environment checks
  797. //
  798. gAllowedClusterDrives.driveCount = 0;
  799. g_bOnActiveClusterNode = TRUE;
  800. //
  801. // Make sure we keep out installation properties in sync with the
  802. // cluster configuration
  803. //
  804. g_uddiComponents.DeleteProperty( UDDI_DB, PROPKEY_CLUSTERNODETYPE );
  805. g_uddiComponents.DeleteProperty( UDDI_WEB, PROPKEY_CLUSTERNODETYPE );
  806. if ( g_uddiComponents.IsClusteredDBInstance() )
  807. {
  808. //
  809. // First, try connecting to the database
  810. // If the database already exists, then just leave it
  811. // intact and skip the drive enumeration process
  812. //
  813. TCHAR szVerBuf[ 256 ] = {0};
  814. size_t cbVerBuf = DIM( szVerBuf ) - 1;
  815. HCURSOR hcrHourglass = LoadCursor( NULL, IDC_WAIT );
  816. HCURSOR hcrCurr = SetCursor( hcrHourglass );
  817. HRESULT hr = GetDBSchemaVersion( g_uddiComponents.GetFullDBInstanceName(),
  818. szVerBuf, cbVerBuf );
  819. SetCursor( hcrCurr );
  820. if ( SUCCEEDED( hr ) && _tcslen( szVerBuf ) )
  821. {
  822. g_bPreserveDatabase = TRUE;
  823. int iRes = DisplayUDDIErrorDialog( hDlg, IDS_DB_EXISTS, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 );
  824. if ( iRes == IDNO )
  825. {
  826. // force user to the instance selection page
  827. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_DB_INSTANCE );
  828. return 1;
  829. }
  830. bSuppressInactiveWarning = true;
  831. }
  832. else
  833. {
  834. g_bPreserveDatabase = FALSE;
  835. }
  836. cDrvMap::size_type nDrivesFound = 0;
  837. HCLUSTER hCls = OpenCluster( NULL );
  838. if ( !hCls )
  839. {
  840. DisplayUDDIErrorDialog( hDlg, IDS_CANTOPENCLUSTER );
  841. // force user to the previous page
  842. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_DB_INSTANCE );
  843. return 1;
  844. }
  845. hcrCurr = SetCursor( hcrHourglass );
  846. //
  847. // now we will format the instance name and collect the data
  848. //
  849. try
  850. {
  851. TCHAR szComputerName[ 256 ] = {0};
  852. WCHAR szNode[ 256 ] = {0};
  853. DWORD dwErr = ERROR_SUCCESS;
  854. DWORD cbComputerName = DIM( szComputerName );
  855. DWORD cbNode = DIM( szNode );
  856. cStrList cDependencies;
  857. cDrvMap cPhysicalDrives;
  858. tstring sServerName = g_uddiComponents.GetDBComputerName();
  859. tstring sInstance = g_uddiComponents.GetDBInstanceName();
  860. if ( !_tcsicmp( sInstance.c_str(), DEFAULT_SQL_INSTANCE_NAME ) )
  861. sInstance = DEFAULT_SQL_INSTANCE_NATIVE;
  862. sServerName += TEXT( "\\" );
  863. sServerName += sInstance;
  864. dwErr = GetSqlNode( sServerName.c_str(), szNode, cbNode );
  865. if ( dwErr != ERROR_SUCCESS )
  866. throw dwErr;
  867. GetComputerName( szComputerName, &cbComputerName );
  868. //
  869. // Are we on the same node as the Sql server instance?
  870. //
  871. g_bOnActiveClusterNode = ( !_tcsicmp( szComputerName, szNode ) );
  872. gAllowedClusterDrives.driveCount = 0;
  873. //
  874. // if we are installing database components,
  875. // then we will need to go one step further and analyse
  876. // the drive dependencies etc.
  877. //
  878. if ( g_bOnActiveClusterNode )
  879. {
  880. if ( g_uddiComponents.IsInstalling( UDDI_DB ) && !g_bPreserveDatabase )
  881. {
  882. //
  883. // We are on an active (owning) node. Let's collect the drive data
  884. //
  885. dwErr = EnumSQLDependencies( hCls, &cDependencies, sServerName.c_str() );
  886. if ( dwErr != ERROR_SUCCESS )
  887. throw dwErr;
  888. dwErr = EnumPhysicalDrives( hCls, &cDependencies, &cPhysicalDrives );
  889. if ( dwErr != ERROR_SUCCESS )
  890. throw dwErr;
  891. int idx = 0;
  892. nDrivesFound = cPhysicalDrives.size();
  893. if ( nDrivesFound == 0 )
  894. {
  895. DisplayUDDIErrorDialog( hDlg, IDS_NOCLUSTERRESAVAIL );
  896. // force user to the previous page
  897. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_DB_INSTANCE );
  898. return 1;
  899. }
  900. //
  901. // We are in an active node, make sure the user wants to continue
  902. //
  903. int iRes = DisplayUDDIErrorDialog( hDlg, IDS_ACTIVENODE_DB, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 );
  904. if ( iRes == IDNO )
  905. {
  906. // force user to the instance selection page
  907. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_DB_INSTANCE );
  908. return 1;
  909. }
  910. for ( cDrvIterator it = cPhysicalDrives.begin(); it != cPhysicalDrives.end(); it++ )
  911. {
  912. gAllowedClusterDrives.drives[ idx ] = it->second.sDriveLetter;
  913. idx++;
  914. }
  915. gAllowedClusterDrives.driveCount = idx;
  916. }
  917. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_CLUSTERNODETYPE, PROPKEY_ACTIVENODE );
  918. g_uddiComponents.AddProperty( UDDI_WEB, PROPKEY_CLUSTERNODETYPE, PROPKEY_ACTIVENODE );
  919. }
  920. else
  921. {
  922. if ( g_uddiComponents.IsInstalling( UDDI_DB ) &&
  923. !bSuppressInactiveWarning )
  924. {
  925. //
  926. // We are on a passive node. Make a note
  927. //
  928. int iRes = DisplayUDDIErrorDialog( hDlg, IDS_PASSIVENODE_DB, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 );
  929. if ( iRes == IDNO )
  930. {
  931. // force user to the instance selection page
  932. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_DB_INSTANCE );
  933. return 1;
  934. }
  935. }
  936. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_CLUSTERNODETYPE, PROPKEY_PASSIVENODE );
  937. g_uddiComponents.AddProperty( UDDI_WEB, PROPKEY_CLUSTERNODETYPE, PROPKEY_PASSIVENODE );
  938. }
  939. }
  940. catch (...)
  941. {
  942. DisplayUDDIErrorDialog( hDlg, IDS_GENERALCLUSTERR );
  943. // force user to the previous page (SSL)
  944. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_SSL );
  945. return 1;
  946. }
  947. CloseCluster( hCls );
  948. SetCursor( hcrCurr );
  949. //
  950. // Finally, signal the next page that the data has changed
  951. //
  952. g_bResetPathFields = TRUE;
  953. }
  954. else
  955. {
  956. gAllowedClusterDrives.driveCount = -1;
  957. g_bPreserveDatabase = FALSE;
  958. }
  959. //
  960. // Finally, set the flag to indicate that the job is done
  961. //
  962. g_bSkipClusterAnalysis = TRUE;
  963. }
  964. return SkipWizardPage( hDlg );
  965. }
  966. case PSN_QUERYCANCEL:
  967. {
  968. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  969. return 1;
  970. }
  971. }
  972. }
  973. }
  974. return 0;
  975. }
  976. INT_PTR CALLBACK DataPathsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  977. {
  978. tstring sTmpString;
  979. BOOL bRes = FALSE;
  980. TCHAR szTmpPath[ MAX_PATH + 1 ];
  981. TCHAR szTmpTitle[ 256 ];
  982. switch( msg )
  983. {
  984. case WM_INITDIALOG:
  985. //
  986. // set the maximum edit field length
  987. //
  988. SendMessage( GetDlgItem( hDlg, IDC_SYSPATH ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  989. SendMessage( GetDlgItem( hDlg, IDC_COREPATH_1 ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  990. SendMessage( GetDlgItem( hDlg, IDC_COREPATH_2 ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  991. SendMessage( GetDlgItem( hDlg, IDC_JRNLPATH ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  992. SendMessage( GetDlgItem( hDlg, IDC_STAGINGPATH ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  993. SendMessage( GetDlgItem( hDlg, IDC_XLOGPATH ), EM_LIMITTEXT, ( WPARAM ) MAX_PATH, 0 );
  994. //
  995. // are we in a clustered environment ?
  996. //
  997. if ( g_uddiComponents.IsClusteredDBInstance() )
  998. {
  999. if ( gAllowedClusterDrives.driveCount > 0 )
  1000. {
  1001. sTmpString = gAllowedClusterDrives.drives[ 0 ];
  1002. sTmpString += TEXT( "\\uddi\\data" );
  1003. }
  1004. else
  1005. {
  1006. //
  1007. // falling back on a default data path. This should never happen,
  1008. // this is just a safety net for us
  1009. //
  1010. sTmpString = g_uddiComponents.GetDefaultDataPath();
  1011. }
  1012. }
  1013. else
  1014. sTmpString = g_uddiComponents.GetDefaultDataPath();
  1015. //
  1016. // Set the fields
  1017. //
  1018. SetAllDatapathFields( hDlg, sTmpString.c_str() );
  1019. //
  1020. // now hide the controls and set the dialog into the default mode
  1021. //
  1022. if ( g_bSimpleDatapathUI )
  1023. ToggleDatapathUI( hDlg, TRUE );
  1024. else
  1025. ToggleDatapathUI( hDlg, FALSE );
  1026. break;
  1027. case WM_COMMAND:
  1028. switch( LOWORD( wParam ) )
  1029. {
  1030. case IDC_MORE_BTN: // toggle to the "advanced mode"
  1031. {
  1032. g_bSimpleDatapathUI = FALSE;
  1033. ToggleDatapathUI( hDlg, FALSE );
  1034. }
  1035. break;
  1036. case IDC_LESS_BTN: // toggle to the "simple mode"
  1037. {
  1038. g_bSimpleDatapathUI = TRUE;
  1039. ToggleDatapathUI( hDlg, TRUE );
  1040. }
  1041. break;
  1042. case IDC_BROWSESYSPATH:
  1043. {
  1044. LoadString( g_hInstance, IDS_PROMPT_SELSYSDATAPATH, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1045. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1046. if ( bRes )
  1047. {
  1048. SetDlgItemText( hDlg, IDC_SYSPATH, szTmpPath );
  1049. if ( g_bSimpleDatapathUI )
  1050. SetAllDatapathFields( hDlg, szTmpPath );
  1051. }
  1052. break;
  1053. }
  1054. case IDC_BROWSECOREPATH1:
  1055. {
  1056. LoadString( g_hInstance, IDS_PROMPT_SELCOREPATH_1, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1057. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1058. if ( bRes )
  1059. SetDlgItemText( hDlg, IDC_COREPATH_1, szTmpPath );
  1060. break;
  1061. }
  1062. case IDC_BROWSECOREPATH2:
  1063. {
  1064. LoadString( g_hInstance, IDS_PROMPT_SELCOREPATH_2, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1065. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1066. if ( bRes )
  1067. SetDlgItemText( hDlg, IDC_COREPATH_2, szTmpPath );
  1068. break;
  1069. }
  1070. case IDC_BROWSEJRNLPATH:
  1071. {
  1072. LoadString( g_hInstance, IDS_PROMPT_SELJRNLPATH, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1073. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1074. if ( bRes )
  1075. SetDlgItemText( hDlg, IDC_JRNLPATH, szTmpPath );
  1076. break;
  1077. }
  1078. case IDC_BROWSESTAGINGPATH:
  1079. {
  1080. LoadString( g_hInstance, IDS_PROMPT_SELSTGPATH, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1081. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1082. if ( bRes )
  1083. SetDlgItemText( hDlg, IDC_STAGINGPATH, szTmpPath );
  1084. break;
  1085. }
  1086. case IDC_BROWSEXLOGPATH:
  1087. {
  1088. LoadString( g_hInstance, IDS_PROMPT_SELXLOGPATH, szTmpTitle, sizeof szTmpTitle / sizeof szTmpTitle[0] );
  1089. bRes = ShowBrowseDirDialog( hDlg, szTmpTitle, szTmpPath );
  1090. if ( bRes )
  1091. SetDlgItemText( hDlg, IDC_XLOGPATH, szTmpPath );
  1092. break;
  1093. }
  1094. default:
  1095. break;
  1096. }
  1097. break;
  1098. case WM_NOTIFY:
  1099. {
  1100. switch( ( ( NMHDR * )lParam )->code )
  1101. {
  1102. //
  1103. // this is called once when the page is created
  1104. //
  1105. case PSN_SETACTIVE:
  1106. {
  1107. //
  1108. // this page needed only if we are installing the DB
  1109. //
  1110. g_uddiComponents.UpdateAllInstallLevel();
  1111. if( g_uddiComponents.IsInstalling( UDDI_DB ) && g_bOnActiveClusterNode && !g_bPreserveDatabase )
  1112. {
  1113. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1114. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1115. //
  1116. // Check whether we need to update the data path fileds
  1117. // due to a change in the clustering data
  1118. //
  1119. if ( g_bResetPathFields )
  1120. {
  1121. if ( g_uddiComponents.IsClusteredDBInstance() )
  1122. {
  1123. if ( gAllowedClusterDrives.driveCount > 0 )
  1124. {
  1125. sTmpString = gAllowedClusterDrives.drives[ 0 ];
  1126. sTmpString += TEXT( "\\uddi\\data" );
  1127. }
  1128. else // falling back on a default data path
  1129. {
  1130. sTmpString = g_uddiComponents.GetDefaultDataPath();
  1131. }
  1132. }
  1133. else
  1134. sTmpString = g_uddiComponents.GetDefaultDataPath();
  1135. //
  1136. // Set the fields
  1137. //
  1138. SetAllDatapathFields( hDlg, sTmpString.c_str() );
  1139. }
  1140. g_bResetPathFields = FALSE;
  1141. return 1;
  1142. }
  1143. else
  1144. {
  1145. return SkipWizardPage( hDlg );
  1146. }
  1147. }
  1148. case PSN_WIZNEXT:
  1149. {
  1150. //
  1151. // set the Provider Instance Name by adding a property to the DB setup command line
  1152. //
  1153. TCHAR buf[ MAX_PATH + 1 ];
  1154. ZeroMemory( buf, sizeof buf );
  1155. //
  1156. // System Data File path
  1157. //
  1158. GetWindowText( GetDlgItem( hDlg, IDC_SYSPATH ), buf, ( sizeof buf / sizeof buf[0] ) - 1 );
  1159. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1160. _tcscat( buf, TEXT( "\\" ) );
  1161. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_SYSPATH, buf );
  1162. ZeroMemory( buf, sizeof buf );
  1163. //
  1164. // Core Data File path #1
  1165. //
  1166. GetWindowText( GetDlgItem( hDlg, IDC_COREPATH_1 ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  1167. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1168. _tcscat( buf, TEXT( "\\" ) );
  1169. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_COREPATH_1, buf );
  1170. ZeroMemory( buf, sizeof buf );
  1171. //
  1172. // Core Data File path #2
  1173. //
  1174. GetWindowText( GetDlgItem( hDlg, IDC_COREPATH_2 ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  1175. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1176. _tcscat( buf, TEXT( "\\" ) );
  1177. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_COREPATH_2, buf );
  1178. ZeroMemory( buf, sizeof buf );
  1179. //
  1180. // Journal Data File path
  1181. //
  1182. GetWindowText( GetDlgItem( hDlg, IDC_JRNLPATH ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  1183. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1184. _tcscat( buf, TEXT( "\\" ) );
  1185. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_JRNLPATH, buf );
  1186. ZeroMemory( buf, sizeof buf );
  1187. //
  1188. // Staging Data File path
  1189. //
  1190. GetWindowText( GetDlgItem( hDlg, IDC_STAGINGPATH ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  1191. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1192. _tcscat( buf, TEXT( "\\" ) );
  1193. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_STGPATH, buf );
  1194. ZeroMemory( buf, sizeof buf );
  1195. //
  1196. // Xact Log File path
  1197. //
  1198. GetWindowText( GetDlgItem( hDlg, IDC_XLOGPATH ), buf, ( sizeof( buf ) / sizeof( buf[0] ) ) -1 );
  1199. if ( _tcslen( buf ) && ( buf[ _tcslen( buf ) - 1 ] == TEXT( '\\' ) ) )
  1200. _tcscat( buf, TEXT( "\\" ) );
  1201. g_uddiComponents.AddProperty( UDDI_DB, PROPKEY_XLOGPATH, buf );
  1202. ZeroMemory( buf, sizeof buf );
  1203. //
  1204. // Finally, we can leave the page
  1205. //
  1206. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1207. return 1;
  1208. }
  1209. case PSN_QUERYCANCEL:
  1210. {
  1211. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1212. return 1;
  1213. }
  1214. }
  1215. }
  1216. }
  1217. return 0;
  1218. }
  1219. //
  1220. //--------------------------------------------------------------------------
  1221. //
  1222. INT_PTR CALLBACK ExistingDBInstanceProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1223. {
  1224. TCHAR buf[ 1024 ];
  1225. ULONG cbBuf = ( sizeof buf / sizeof buf[0] );
  1226. bool bRes = false;
  1227. switch( msg )
  1228. {
  1229. case WM_INITDIALOG:
  1230. //
  1231. // set the database instance name field
  1232. //
  1233. ZeroMemory( buf, sizeof buf );
  1234. bRes = g_dbLocalInstances.GetUDDIDBInstanceName( NULL, buf, &cbBuf );
  1235. if ( bRes )
  1236. {
  1237. if ( !_tcsstr( buf, TEXT( "\\") ) )
  1238. {
  1239. //
  1240. // Add the machine name
  1241. //
  1242. TCHAR szMachineName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  1243. DWORD dwLen = MAX_COMPUTERNAME_LENGTH + 1;
  1244. ZeroMemory (szMachineName, sizeof szMachineName );
  1245. if ( GetComputerName( szMachineName, &dwLen ) )
  1246. {
  1247. TCHAR szTmp[ 1024 ];
  1248. _tcscpy( szTmp, szMachineName );
  1249. _tcscat( szTmp, TEXT( "\\" ) );
  1250. _tcscat( szTmp, buf );
  1251. _tcscpy( buf, szTmp );
  1252. }
  1253. }
  1254. SetDlgItemText( hDlg, IDC_INSTANCENAME, buf );
  1255. }
  1256. break;
  1257. case WM_COMMAND:
  1258. break;
  1259. case WM_NOTIFY:
  1260. {
  1261. switch( ( ( NMHDR * )lParam )->code )
  1262. {
  1263. //
  1264. // this is called once when the page is created
  1265. //
  1266. case PSN_SETACTIVE:
  1267. {
  1268. //
  1269. // this page needed only if we are installing the Web & DB is here
  1270. //
  1271. g_uddiComponents.UpdateAllInstallLevel();
  1272. if( g_uddiComponents.IsInstalled( UDDI_DB ) &&
  1273. !g_uddiComponents.IsUninstalling( UDDI_DB ) &&
  1274. g_uddiComponents.IsInstalling( UDDI_WEB ) )
  1275. {
  1276. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1277. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1278. return 1;
  1279. }
  1280. else
  1281. {
  1282. return SkipWizardPage( hDlg );
  1283. }
  1284. }
  1285. case PSN_WIZNEXT:
  1286. {
  1287. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1288. return 1;
  1289. }
  1290. case PSN_QUERYCANCEL:
  1291. {
  1292. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1293. return 1;
  1294. }
  1295. }
  1296. }
  1297. }
  1298. return 0;
  1299. }
  1300. //
  1301. //--------------------------------------------------------------------------
  1302. //
  1303. INT_PTR CALLBACK AddSvcDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1304. {
  1305. switch( msg )
  1306. {
  1307. case WM_INITDIALOG:
  1308. //
  1309. // Check the Publish This Site checkbox
  1310. //
  1311. CheckDlgButton( hDlg, IDC_CHECK_ADDSVC, BST_CHECKED );
  1312. break;
  1313. case WM_COMMAND:
  1314. break;
  1315. case WM_NOTIFY:
  1316. {
  1317. switch( ( ( NMHDR * )lParam )->code )
  1318. {
  1319. //
  1320. // this is called once when the page is created
  1321. //
  1322. case PSN_SETACTIVE:
  1323. {
  1324. //
  1325. // this page needed only if we are installing the DB
  1326. //
  1327. g_uddiComponents.UpdateAllInstallLevel();
  1328. if( g_uddiComponents.IsInstalling( UDDI_WEB ) )
  1329. {
  1330. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1331. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1332. return 1;
  1333. }
  1334. else
  1335. {
  1336. return SkipWizardPage( hDlg );
  1337. }
  1338. }
  1339. case PSN_WIZNEXT:
  1340. {
  1341. //
  1342. // set the "Add Services" and "Update AD" flags by adding the installation properties
  1343. //
  1344. bool bChecked = ( BST_CHECKED == IsDlgButtonChecked( hDlg, IDC_CHECK_ADDSVC ) );
  1345. g_uddiComponents.AddProperty( UDDI_WEB, PROPKEY_ADDSERVICES, ( bChecked ? 1 : 0 ) );
  1346. g_uddiComponents.AddProperty( UDDI_WEB, PROPKEY_UPDATE_AD, ( bChecked ? 1 : 0 ) );
  1347. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1348. return 1;
  1349. }
  1350. case PSN_QUERYCANCEL:
  1351. {
  1352. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1353. return 1;
  1354. }
  1355. }
  1356. }
  1357. }
  1358. return 0;
  1359. }
  1360. //
  1361. //--------------------------------------------------------------------------
  1362. //
  1363. INT_PTR CALLBACK RemoteDBInstanceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1364. {
  1365. switch( msg )
  1366. {
  1367. case WM_COMMAND:
  1368. if( LOWORD( wParam ) == IDC_BROWSE_MACHINES )
  1369. {
  1370. //
  1371. // use the object picker to select the remote machine name
  1372. //
  1373. HRESULT hr;
  1374. BOOL bIsStd = FALSE;
  1375. TCHAR szComputerName[ 256 ] = {0};
  1376. if ( !ObjectPicker( hDlg, OP_COMPUTER, szComputerName, 256 ) )
  1377. break; // user pressed cancel
  1378. hr = IsStandardServer( szComputerName, &bIsStd );
  1379. if ( SUCCEEDED( hr ) && bIsStd )
  1380. {
  1381. DisplayUDDIErrorDialog( hDlg, IDS_CANTCONNTOSTD, MB_OK | MB_ICONWARNING );
  1382. break;
  1383. }
  1384. //
  1385. // write the machine name into the static text box, and them clear the combo box
  1386. //
  1387. SendMessage( GetDlgItem( hDlg, IDC_REMOTE_MACHINE ), WM_SETTEXT, 0, ( LPARAM ) szComputerName );
  1388. //
  1389. // find out if a UDDI database already exists on that remote machine
  1390. //
  1391. TCHAR szInstanceName[ 100 ];
  1392. ULONG uLen = 100;
  1393. if( g_dbRemoteInstances.GetUDDIDBInstanceName( szComputerName, szInstanceName, &uLen ) )
  1394. {
  1395. //
  1396. // write the db instance name into the static text box
  1397. //
  1398. SendMessage( GetDlgItem( hDlg, IDC_REMOTE_INSTANCE ), WM_SETTEXT, 0, ( LPARAM ) szInstanceName );
  1399. }
  1400. else
  1401. {
  1402. //
  1403. // remote machine was not accessable or did not have any instances
  1404. //
  1405. DisplayUDDIErrorDialog( hDlg, IDS_UDDI_DB_NOT_EXIST, MB_OK | MB_ICONWARNING );
  1406. }
  1407. }
  1408. break;
  1409. case WM_NOTIFY:
  1410. {
  1411. switch( ( ( NMHDR * )lParam )->code )
  1412. {
  1413. //
  1414. // this is called once when the page is created
  1415. //
  1416. case PSN_SETACTIVE:
  1417. {
  1418. //
  1419. // needed if user is installing web and NOT the db, or the db is not installed
  1420. //
  1421. g_uddiComponents.UpdateAllInstallLevel();
  1422. if( g_uddiComponents.IsInstalling( UDDI_WEB ) && !g_uddiComponents.IsInstalling( UDDI_DB ) &&
  1423. ( !g_uddiComponents.IsInstalled( UDDI_DB ) || g_uddiComponents.IsUninstalling( UDDI_DB ) ) )
  1424. {
  1425. UINT osMask = g_uddiComponents.GetOSSuiteMask();
  1426. BOOL bAdv = ( osMask & VER_SUITE_DATACENTER ) || ( osMask & VER_SUITE_ENTERPRISE );
  1427. EnableWindow( GetDlgItem( hDlg, IDC_BROWSE_MACHINES ), bAdv );
  1428. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1429. SetWindowLongPtr( hDlg,DWLP_MSGRESULT,0 );
  1430. return 1;
  1431. }
  1432. else
  1433. {
  1434. return SkipWizardPage( hDlg );
  1435. }
  1436. }
  1437. //
  1438. // this is called when the user presses "next"
  1439. //
  1440. case PSN_WIZNEXT:
  1441. {
  1442. //
  1443. // get the remote machine name from the edit control
  1444. //
  1445. TCHAR szComputerName[ 129 ];
  1446. UINT iChars = ( UINT ) SendMessage( GetDlgItem( hDlg, IDC_REMOTE_MACHINE ), WM_GETTEXT, 129, ( LPARAM ) szComputerName );
  1447. if( 0 == iChars )
  1448. {
  1449. DisplayUDDIErrorDialog( hDlg, IDS_SELECT_REMOTE_COMPUTER );
  1450. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1451. return 1; // to keep the focus on this page
  1452. }
  1453. //
  1454. // get the index of the database instance selection in the combobox
  1455. //
  1456. TCHAR szRemoteDBInstance[ 100 ];
  1457. iChars = ( UINT ) SendMessage( GetDlgItem( hDlg, IDC_REMOTE_INSTANCE ), WM_GETTEXT, 100, ( LPARAM ) szRemoteDBInstance );
  1458. if( 0 == iChars )
  1459. {
  1460. DisplayUDDIErrorDialog( hDlg, IDS_UDDI_DB_NOT_EXIST );
  1461. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1462. return 1; // to keep the focus on this page
  1463. }
  1464. //
  1465. // save the computer and instance name. As we are using a remote node here,
  1466. // we don't really care whether it is on cluster or not
  1467. //
  1468. g_uddiComponents.SetDBInstanceName( szComputerName, szRemoteDBInstance, UDDI_NOT_INSTALLING_MSDE, false );
  1469. //
  1470. // the web installer needs the remote machine name to properly add the login
  1471. //
  1472. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "REMOTE_MACHINE_NAME" ), szComputerName );
  1473. Log( TEXT( "User selected remote computer %s and database instance %s" ), szComputerName, szRemoteDBInstance );
  1474. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1475. return 1; // done
  1476. }
  1477. case PSN_QUERYCANCEL:
  1478. {
  1479. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1480. return 1;
  1481. }
  1482. }
  1483. }
  1484. }
  1485. return 0;
  1486. }
  1487. //--------------------------------------------------------------------------
  1488. INT_PTR CALLBACK LoginDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1489. {
  1490. switch( msg )
  1491. {
  1492. case WM_INITDIALOG:
  1493. //
  1494. // set the limit of the length of the password
  1495. //
  1496. SendMessage( GetDlgItem( hDlg, IDC_PASSWORD ), EM_LIMITTEXT, ( WPARAM ) PASSWORD_LEN, 0 );
  1497. SendMessage( GetDlgItem( hDlg, IDC_USER_NAME ), EM_LIMITTEXT, ( WPARAM ) USERNAME_LEN, 0 );
  1498. break;
  1499. case WM_COMMAND:
  1500. //
  1501. // user clicked a radio button:
  1502. //
  1503. if( LOWORD( wParam ) == IDC_RADIO_NETWORK_SERVICE || LOWORD( wParam ) == IDC_RADIO_DOMAIN_ACCT )
  1504. {
  1505. if( HIWORD( wParam ) == BN_CLICKED )
  1506. {
  1507. EnableWindow( GetDlgItem( hDlg, IDC_USER_NAME ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1508. EnableWindow( GetDlgItem( hDlg, IDC_USER_NAME_PROMPT ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1509. EnableWindow( GetDlgItem( hDlg, IDC_PASSWORD ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1510. EnableWindow( GetDlgItem( hDlg, IDC_PASSWORD_PROMPT ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1511. EnableWindow( GetDlgItem( hDlg, IDC_BROWSE_USERS ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1512. }
  1513. }
  1514. //
  1515. // if the user clicked the "Browse" button
  1516. //
  1517. else if( LOWORD( wParam ) == IDC_BROWSE_USERS )
  1518. {
  1519. //
  1520. // use the object picker to select the user
  1521. //
  1522. TCHAR szDomainUser[ 256 ];
  1523. if ( !ObjectPicker( hDlg, OP_USER, szDomainUser, 256 ) )
  1524. break;
  1525. //
  1526. // write the machine name into the static text box
  1527. //
  1528. SendMessage( GetDlgItem( hDlg, IDC_USER_NAME ), WM_SETTEXT, 0, ( LPARAM ) szDomainUser );
  1529. }
  1530. break;
  1531. case WM_NOTIFY:
  1532. {
  1533. switch( ( ( NMHDR * )lParam )->code )
  1534. {
  1535. //
  1536. // this is called once when the page is created
  1537. //
  1538. case PSN_SETACTIVE:
  1539. {
  1540. //
  1541. // this page is needed only when the WEB is being installed
  1542. //
  1543. g_uddiComponents.UpdateAllInstallLevel();
  1544. if( g_uddiComponents.IsInstalling( UDDI_WEB ) )
  1545. {
  1546. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1547. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1548. bool bIsClustered = g_uddiComponents.IsClusteredDBInstance();
  1549. if( ( g_uddiComponents.IsInstalling( UDDI_DB ) ||
  1550. ( g_uddiComponents.IsInstalled( UDDI_DB ) && !g_uddiComponents.IsUninstalling( UDDI_DB ) ) ) &&
  1551. !bIsClustered )
  1552. {
  1553. CheckRadioButton( hDlg, IDC_RADIO_NETWORK_SERVICE, IDC_RADIO_DOMAIN_ACCT, IDC_RADIO_NETWORK_SERVICE );
  1554. }
  1555. //
  1556. // db is not on the local box, so disable the network service account option
  1557. //
  1558. else
  1559. {
  1560. CheckRadioButton( hDlg, IDC_RADIO_NETWORK_SERVICE, IDC_RADIO_DOMAIN_ACCT, IDC_RADIO_DOMAIN_ACCT );
  1561. EnableWindow( GetDlgItem( hDlg, IDC_RADIO_NETWORK_SERVICE ), FALSE );
  1562. SetFocus( GetDlgItem( hDlg, IDC_USER_NAME ) );
  1563. }
  1564. EnableWindow( GetDlgItem( hDlg, IDC_USER_NAME ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1565. EnableWindow( GetDlgItem( hDlg, IDC_USER_NAME_PROMPT ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1566. EnableWindow( GetDlgItem( hDlg, IDC_PASSWORD ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1567. EnableWindow( GetDlgItem( hDlg, IDC_PASSWORD_PROMPT ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1568. EnableWindow( GetDlgItem( hDlg, IDC_BROWSE_USERS ), IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1569. }
  1570. else
  1571. {
  1572. return SkipWizardPage( hDlg );
  1573. }
  1574. return 1;
  1575. }
  1576. //
  1577. // this is called when the user presses "next"
  1578. //
  1579. case PSN_WIZNEXT:
  1580. {
  1581. //
  1582. // Get ready for the SID-to-user name conversions
  1583. //
  1584. TCHAR szSidStr[ 1024 ];
  1585. TCHAR szRemote[ 1024 ];
  1586. TCHAR szRemoteUser[ 1024 ];
  1587. DWORD cbSidStr = sizeof szSidStr / sizeof szSidStr[0];
  1588. DWORD cbRemoteUser = sizeof szRemoteUser / sizeof szRemoteUser[0];
  1589. TCHAR szComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  1590. DWORD dwCompNameLen = MAX_COMPUTERNAME_LENGTH + 1;
  1591. GetComputerName( szComputerName, &dwCompNameLen );
  1592. ZeroMemory( szRemote, sizeof szRemote );
  1593. if( NULL == g_uddiComponents.GetProperty( UDDI_WEB, TEXT( "REMOTE_MACHINE_NAME" ), szRemote ) )
  1594. {
  1595. _tcscpy( szRemote, szComputerName );
  1596. }
  1597. //
  1598. // set the property that defines whether we are using "Network Service" or a "User Login"
  1599. //
  1600. bool bUserAcct = ( BST_CHECKED == IsDlgButtonChecked( hDlg, IDC_RADIO_DOMAIN_ACCT ) );
  1601. //
  1602. // set the properties that denotes a domain user
  1603. //
  1604. if( bUserAcct )
  1605. {
  1606. TCHAR szDomainUser[ USERNAME_LEN + 1 ];
  1607. //
  1608. // verify the user name length > 0
  1609. //
  1610. int iChars = GetWindowText( GetDlgItem( hDlg, IDC_USER_NAME ), szDomainUser, sizeof( szDomainUser ) / sizeof( TCHAR ) );
  1611. if( 0 == iChars )
  1612. {
  1613. DisplayUDDIErrorDialog( hDlg, IDS_ZERO_LEN_USER_NAME );
  1614. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1615. return 1; // to keep the focus on this page
  1616. }
  1617. //
  1618. // make the user retype the password
  1619. //
  1620. GetWindowText( GetDlgItem( hDlg, IDC_PASSWORD ), g_szPwd, sizeof( g_szPwd ) / sizeof( TCHAR ) );
  1621. INT_PTR iRet = DialogBox(
  1622. g_hInstance,
  1623. MAKEINTRESOURCE( IDD_CONFIRM_PW ),
  1624. hDlg,
  1625. ConfirmPasswordDlgProc );
  1626. if( IDCANCEL == iRet )
  1627. {
  1628. //
  1629. // user pressed Cancel to the confirm dialog
  1630. //
  1631. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1632. return 1; // to keep the focus on this page
  1633. }
  1634. TCHAR szUser[ USERNAME_LEN + 1 ];
  1635. TCHAR szDomain[ 256 ];
  1636. DWORD cbDomain = sizeof( szDomain ) / sizeof( szDomain[0] );
  1637. bool bLocalAccount;
  1638. ZeroMemory( szUser, sizeof( szUser ) );
  1639. ZeroMemory( szDomain, sizeof( szDomain ) );
  1640. ParseUserAccount(
  1641. szDomainUser, sizeof( szDomainUser ) / sizeof ( TCHAR ),
  1642. szUser, sizeof( szUser ) / sizeof ( TCHAR ),
  1643. szDomain, sizeof( szDomain ) / sizeof ( TCHAR ),
  1644. bLocalAccount );
  1645. //
  1646. // try to login as this account
  1647. // if there is no domain name specified
  1648. // then assume local account
  1649. //
  1650. if ( bLocalAccount )
  1651. {
  1652. _tcscpy( szDomain, TEXT( "." ) );
  1653. //
  1654. // are we on a cluster ?
  1655. //
  1656. if ( g_uddiComponents.IsClusteredDBInstance() )
  1657. {
  1658. DisplayUDDIErrorDialog( hDlg, IDS_WRONGLOGONTYPE, MB_OK | MB_ICONWARNING, GetLastError() );
  1659. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1660. return 1; // to keep the focus on this page
  1661. }
  1662. }
  1663. BOOL fLogonRights = GrantNetworkLogonRights( szDomainUser );
  1664. if( !fLogonRights )
  1665. {
  1666. //
  1667. // FIX: 727877: needed error dialog
  1668. //
  1669. DisplayUDDIErrorDialog( hDlg, IDS_LOGIN_ERROR, MB_OK | MB_ICONWARNING, E_FAIL );
  1670. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1671. return 1;
  1672. }
  1673. HANDLE hToken = NULL;
  1674. BOOL bIsGoodLogin = LogonUser(
  1675. szUser,
  1676. _tcslen( szDomain ) > 0 ? szDomain : NULL,
  1677. g_szPwd,
  1678. LOGON32_LOGON_INTERACTIVE,
  1679. LOGON32_PROVIDER_DEFAULT,
  1680. &hToken);
  1681. if( bIsGoodLogin )
  1682. {
  1683. HRESULT hr = S_OK;
  1684. Log( _T( "LogonUser succeeded with %s." ), szDomainUser );
  1685. //
  1686. // FIX: 718923: needed to test connectivity with SQL server via impersonation and OLEDB call
  1687. //
  1688. //
  1689. // If we're not installing MSDE, then a database exists for us to check connectivity.
  1690. //
  1691. if( !g_uddiComponents.IsInstalling( UDDI_MSDE ) )
  1692. {
  1693. //
  1694. // Only check this when we're not installing the db components (i.e. off-machine setup)
  1695. //
  1696. if( !g_uddiComponents.IsInstalling( UDDI_DB ) )
  1697. {
  1698. HCURSOR hcrHourglass = LoadCursor( NULL, IDC_WAIT );
  1699. HCURSOR hcrCurr = SetCursor( hcrHourglass );
  1700. //
  1701. // If workgroup account, we need to give AddServiceAccount the workgroup account on the db server.
  1702. // Else, just pass the domain account.
  1703. //
  1704. tstring sServerName;
  1705. if( bLocalAccount )
  1706. {
  1707. sServerName = g_uddiComponents.GetDBComputerName();
  1708. sServerName += _T( "\\" );
  1709. sServerName += szUser;
  1710. }
  1711. else
  1712. {
  1713. sServerName = szDomainUser;
  1714. }
  1715. Log( _T( "Before AddServiceAccount for user %s, instance %s." ), sServerName.c_str(), g_uddiComponents.GetFullDBInstanceName() );
  1716. //
  1717. // Add user to service account on db.
  1718. //
  1719. hr = AddServiceAccount( g_uddiComponents.GetFullDBInstanceName(), sServerName.c_str() );
  1720. if( SUCCEEDED( hr ) )
  1721. {
  1722. if( ImpersonateLoggedOnUser( hToken ) )
  1723. {
  1724. Log( _T( "Successfully impersonated user %s\\%s." ), szDomain, szUser);
  1725. TCHAR szVerBuf[ 256 ] = {0};
  1726. size_t cbVerBuf = DIM( szVerBuf ) - 1;
  1727. Log( _T( "Before GetDBSchemaVersion for instance %s." ), g_uddiComponents.GetFullDBInstanceName() );
  1728. //
  1729. // Try connecting to the database with the impersonated user token.
  1730. //
  1731. hr = GetDBSchemaVersion( g_uddiComponents.GetFullDBInstanceName(), szVerBuf, cbVerBuf );
  1732. Log( _T( "GetDBSchemaVersion returned %s, HRESULT %x." ), szVerBuf, hr );
  1733. RevertToSelf();
  1734. }
  1735. else
  1736. {
  1737. //
  1738. // Get error from ImpersonateLoggedOnUser
  1739. //
  1740. hr = GetLastError();
  1741. }
  1742. }
  1743. else
  1744. {
  1745. Log( _T( "AddServiceAccount failed, HRESULT %x." ), hr );
  1746. }
  1747. SetCursor( hcrCurr );
  1748. }
  1749. }
  1750. CloseHandle( hToken );
  1751. if( FAILED( hr ) )
  1752. {
  1753. Log( _T( "Failed to verify connectivity, putting up error dialog, HRESULT %x" ), hr );
  1754. //
  1755. // not a good login, so raise error dialog and keep focus on this property page
  1756. //
  1757. DisplayUDDIErrorDialog( hDlg, IDS_LOGIN_ERROR, MB_OK | MB_ICONWARNING, hr );
  1758. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1759. Log( _T( "Put up error dialog, returning." ) );
  1760. return 1; // to keep the focus on this page
  1761. }
  1762. }
  1763. else
  1764. {
  1765. Log( _T( "LogonUser failed, %x." ), GetLastError() );
  1766. //
  1767. // not a good login, so raise error dialog and keep focus on this property page
  1768. //
  1769. DisplayUDDIErrorDialog( hDlg, IDS_LOGIN_ERROR, MB_OK | MB_ICONWARNING, GetLastError() );
  1770. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1771. return 1; // to keep the focus on this page
  1772. }
  1773. //
  1774. // set the property that denotes a domain user login will be used in the iis app pool
  1775. //
  1776. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "APPPOOL_IDENTITY_TYPE" ), MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER );
  1777. //
  1778. // the web and installer needs the user name
  1779. //
  1780. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "WAM_USER_NAME" ), szDomainUser );
  1781. g_uddiComponents.AddProperty( UDDI_WEB, TEXT("WAM_PWD"), g_szPwd );
  1782. //
  1783. // the web installer needs to put the pw into the IIS app pool settings
  1784. //
  1785. _tcscpy( szRemoteUser, szRemote );
  1786. _tcscat( szRemoteUser, TEXT( "\\" ) );
  1787. _tcscat( szRemoteUser, szUser );
  1788. if( bLocalAccount )
  1789. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "LCL_USER_NAME" ), szRemoteUser );
  1790. else
  1791. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "LCL_USER_NAME" ), szDomainUser );
  1792. }
  1793. //
  1794. // the user specified the Network Service account
  1795. //
  1796. else
  1797. {
  1798. //
  1799. // set the property that denotes "Network Service"
  1800. //
  1801. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "APPPOOL_IDENTITY_TYPE" ), MD_APPPOOL_IDENTITY_TYPE_NETWORKSERVICE );
  1802. //
  1803. // the web and db installers need the user name
  1804. //
  1805. TCHAR wszNetworkServiceName[ 512 ];
  1806. DWORD cbSize = 512 * sizeof( TCHAR );
  1807. BOOL b = GetWellKnownAccountName( WinNetworkServiceSid, wszNetworkServiceName, &cbSize );
  1808. if( !b )
  1809. {
  1810. Log( _T( "Call to GetNetworkServiceAccountName failed." ) );
  1811. }
  1812. else
  1813. {
  1814. Log( _T( "Network Service account name on this machine = %s" ), wszNetworkServiceName );
  1815. }
  1816. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "WAM_USER_NAME" ), wszNetworkServiceName );
  1817. //
  1818. // no need for the pw, so clear out this property
  1819. //
  1820. g_uddiComponents.DeleteProperty( UDDI_WEB, TEXT( "WAM_PWD" ) );
  1821. //
  1822. // Now also save the SID for the WAM_USER
  1823. //
  1824. TCHAR szUser[ USERNAME_LEN + 1 ];
  1825. TCHAR szDomain[ 256 ];
  1826. DWORD cbUser = sizeof szUser / sizeof szUser[0];
  1827. DWORD cbDomain = sizeof szDomain / sizeof szDomain[0];
  1828. if( !GetLocalSidString( WinNetworkServiceSid, szSidStr, cbSidStr ) )
  1829. {
  1830. DisplayUDDIErrorDialog( hDlg, IDS_GETSID_ERROR, MB_OK | MB_ICONWARNING, GetLastError() );
  1831. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1832. return 1; // to keep the focus on this page
  1833. }
  1834. if( !GetRemoteAcctName( szRemote, szSidStr, szUser, &cbUser, szDomain, &cbDomain ) )
  1835. {
  1836. DisplayUDDIErrorDialog( hDlg, IDS_GETREMOTEACCT_ERROR, MB_OK | MB_ICONWARNING, GetLastError() );
  1837. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 1 );
  1838. return 1; // to keep the focus on this page
  1839. }
  1840. _tcscpy( szRemoteUser, szDomain );
  1841. _tcscat( szRemoteUser, TEXT( "\\" ) );
  1842. _tcscat( szRemoteUser, szUser );
  1843. g_uddiComponents.AddProperty( UDDI_WEB, TEXT( "LCL_USER_NAME" ), szRemoteUser );
  1844. }
  1845. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1846. return 1;
  1847. }
  1848. case PSN_QUERYCANCEL:
  1849. {
  1850. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1851. return 1;
  1852. }
  1853. }
  1854. }
  1855. }
  1856. return 0;
  1857. }
  1858. //--------------------------------------------------------------------------
  1859. BOOL CALLBACK ConfirmPasswordDlgProc(
  1860. HWND hwndDlg,
  1861. UINT message,
  1862. WPARAM wParam,
  1863. LPARAM lParam)
  1864. {
  1865. switch( message )
  1866. {
  1867. case WM_INITDIALOG:
  1868. {
  1869. //
  1870. // set the limit of the length of the password
  1871. //
  1872. SendMessage( GetDlgItem( hwndDlg, IDC_CONFIRM_PW ), EM_LIMITTEXT, ( WPARAM ) PASSWORD_LEN, 0 );
  1873. }
  1874. break;
  1875. case WM_COMMAND:
  1876. switch( LOWORD( wParam ) )
  1877. {
  1878. case IDOK:
  1879. TCHAR szPW[ PASSWORD_LEN + 1 ];
  1880. GetDlgItemText( hwndDlg, IDC_CONFIRM_PW, szPW, sizeof( szPW ) / sizeof( TCHAR ) );
  1881. if( 0 != _tcscmp( szPW, g_szPwd ) )
  1882. {
  1883. DisplayUDDIErrorDialog( hwndDlg, IDS_PW_MISMATCH );
  1884. ::SetDlgItemText( hwndDlg, IDC_CONFIRM_PW, TEXT( "" ) );
  1885. return TRUE;
  1886. }
  1887. // fall through...
  1888. case IDCANCEL:
  1889. EndDialog( hwndDlg, wParam );
  1890. return TRUE;
  1891. }
  1892. }
  1893. return FALSE;
  1894. }
  1895. //--------------------------------------------------------------------------
  1896. INT_PTR CALLBACK WizardSummaryDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1897. {
  1898. switch( msg )
  1899. {
  1900. case WM_INITDIALOG:
  1901. {
  1902. tstring msg;
  1903. TCHAR szMsg[ 2048 ] = { 0 };
  1904. DWORD dwLen = sizeof( szMsg ) / sizeof( TCHAR ) ;
  1905. int iStrLen = LoadString( g_hInstance, IDS_WIZARD_SUMMARY_GENERAL, szMsg, dwLen );
  1906. assert( iStrLen );
  1907. msg = szMsg;
  1908. if( g_uddiComponents.IsInstalling( UDDI_DB ) )
  1909. {
  1910. iStrLen = LoadString( g_hInstance, IDS_WIZARD_SUMMARY_DB, szMsg, dwLen );
  1911. assert( iStrLen );
  1912. msg += TEXT( "\n\n" );
  1913. msg += szMsg;
  1914. }
  1915. if( g_uddiComponents.IsInstalling( UDDI_WEB ) )
  1916. {
  1917. iStrLen = LoadString( g_hInstance, IDS_WIZARD_SUMMARY_WEB, szMsg, dwLen );
  1918. assert( iStrLen );
  1919. msg += TEXT( "\n\n" );
  1920. msg += szMsg;
  1921. }
  1922. if( g_uddiComponents.IsInstalling( UDDI_ADMIN ) )
  1923. {
  1924. iStrLen = LoadString( g_hInstance, IDS_WIZARD_SUMMARY_ADMIN, szMsg, dwLen );
  1925. assert( iStrLen );
  1926. msg += TEXT( "\n\n" );
  1927. msg += szMsg;
  1928. }
  1929. SetWindowText( GetDlgItem( hDlg, IDC_SUMMARY ), msg.c_str() );
  1930. break;
  1931. }
  1932. case WM_COMMAND:
  1933. break;
  1934. case WM_NOTIFY:
  1935. {
  1936. switch( ( ( NMHDR * )lParam )->code )
  1937. {
  1938. //
  1939. // this is called once when the page is created
  1940. //
  1941. case PSN_SETACTIVE:
  1942. {
  1943. g_uddiComponents.UpdateAllInstallLevel();
  1944. if( g_uddiComponents.IsAnyInstalling() )
  1945. {
  1946. //PropSheet_SetWizButtons( GetParent( hDlg ), 0 );
  1947. PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  1948. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1949. return 1;
  1950. }
  1951. else
  1952. {
  1953. return SkipWizardPage( hDlg );
  1954. }
  1955. }
  1956. case PSN_KILLACTIVE:
  1957. case PSN_WIZBACK:
  1958. case PSN_WIZFINISH:
  1959. case PSN_QUERYCANCEL:
  1960. case PSN_WIZNEXT:
  1961. {
  1962. SetWindowLongPtr( hDlg, DWLP_MSGRESULT, 0 );
  1963. return 1;
  1964. }
  1965. }
  1966. }
  1967. }
  1968. return 0;
  1969. }
  1970. //--------------------------------------------------------------------------
  1971. static void ParseUserAccount( PTCHAR szDomainAndUser, UINT uDomainAndUserSize, PTCHAR szUser, UINT uUserSize, PTCHAR szDomain, UINT uDomainSize, bool &bLocalAccount )
  1972. {
  1973. //
  1974. // see if the user picked a local machine account
  1975. //
  1976. TCHAR szComputerName[ MAX_COMPUTERNAME_LENGTH + 1 ];
  1977. DWORD dwCompNameLen = MAX_COMPUTERNAME_LENGTH + 1;
  1978. szComputerName[ 0 ] = 0x00;
  1979. GetComputerName( szComputerName, &dwCompNameLen );
  1980. bLocalAccount = false;
  1981. //
  1982. // this string is in the format <domain>\<username>,
  1983. // so look for a whack, if found parse out the domain and user name
  1984. //
  1985. _tcsncpy( szDomain, szDomainAndUser, uDomainSize );
  1986. szDomain[ uDomainSize - 1 ] = NULL;
  1987. PTCHAR pWhack = _tcschr( szDomain, '\\' );
  1988. //
  1989. // a whack was not found, so assume it is a user on the local machine
  1990. //
  1991. if( NULL == pWhack )
  1992. {
  1993. //
  1994. // return the user name and a blank domain name
  1995. //
  1996. _tcsncpy( szUser, szDomainAndUser, uUserSize );
  1997. szUser[ uUserSize - 1 ] = NULL;
  1998. _tcscpy( szDomain, TEXT( "" ) );
  1999. //
  2000. // if the domain or machine was not specified, then
  2001. // assume the local machine and prepend it
  2002. //
  2003. tstring cDomainAndUser = szComputerName;
  2004. cDomainAndUser.append( TEXT( "\\" ) );
  2005. cDomainAndUser.append( szUser );
  2006. _tcsncpy( szDomainAndUser, cDomainAndUser.c_str(), uDomainAndUserSize );
  2007. bLocalAccount = true;
  2008. return;
  2009. }
  2010. //
  2011. // null the "whack" and step to the next character
  2012. //
  2013. *pWhack = NULL;
  2014. pWhack++;
  2015. _tcsncpy( szUser, pWhack, uUserSize );
  2016. szUser[ uUserSize - 1 ] = NULL;
  2017. //
  2018. // see if the user picked a local machine account.
  2019. // if he did pick a local machine account,
  2020. // null the domain and return only the login
  2021. //
  2022. if( 0 == _tcsicmp( szDomain, szComputerName ) )
  2023. {
  2024. *szDomain = NULL;
  2025. bLocalAccount = true;
  2026. }
  2027. }
  2028. //---------------------------------------------------------------------------------------
  2029. // Shows the shell dialog that allows user to browse for a directory
  2030. // Returns FALSE if the dialog was cancelled, or TRUE and the chosen directory
  2031. // otherwise. The buffer is expected to be at least MAX_PATH character long
  2032. //
  2033. BOOL ShowBrowseDirDialog( HWND hParent, LPCTSTR szTitle, LPTSTR szOutBuf )
  2034. {
  2035. BOOL bRes = FALSE;
  2036. TCHAR szDispName[ MAX_PATH + 1 ];
  2037. if ( IsBadStringPtr( szOutBuf, MAX_PATH ) ) return FALSE;
  2038. HRESULT hr = ::CoInitialize( NULL );
  2039. if ( FAILED( hr ) )
  2040. return FALSE;
  2041. try
  2042. {
  2043. BROWSEINFO binfo;
  2044. LPITEMIDLIST lpItemID = NULL;
  2045. ZeroMemory ( &binfo, sizeof binfo );
  2046. SHGetFolderLocation( NULL, CSIDL_DRIVES, NULL, NULL, &lpItemID );
  2047. binfo.hwndOwner = hParent;
  2048. binfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_UAHINT | BIF_DONTGOBELOWDOMAIN;
  2049. binfo.lpszTitle = szTitle;
  2050. binfo.pszDisplayName = szDispName;
  2051. binfo.lpfn = BrowseCallbackProc;
  2052. binfo.pidlRoot = lpItemID;
  2053. if ( gAllowedClusterDrives.driveCount >= 0 )
  2054. binfo.lParam = (LPARAM) &gAllowedClusterDrives;
  2055. else
  2056. binfo.lParam = NULL;
  2057. lpItemID = SHBrowseForFolder( &binfo );
  2058. if ( !lpItemID )
  2059. bRes = FALSE;
  2060. else
  2061. {
  2062. bRes = SHGetPathFromIDList( lpItemID, szOutBuf );
  2063. }
  2064. }
  2065. catch (...)
  2066. {
  2067. bRes = FALSE;
  2068. }
  2069. ::CoUninitialize();
  2070. return bRes;
  2071. }
  2072. int CALLBACK BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
  2073. {
  2074. TCHAR szBuf[ MAX_PATH + 1 ];
  2075. if ( uMsg == BFFM_SELCHANGED )
  2076. {
  2077. TCHAR szDrive[ _MAX_DRIVE + 2 ];
  2078. LPITEMIDLIST lpItemID = (LPITEMIDLIST) lParam;
  2079. CLST_ALLOWED_DRIVES *lpAllowedDrives = (CLST_ALLOWED_DRIVES *) lpData;
  2080. BOOL bEnableOK = FALSE;
  2081. if ( SHGetPathFromIDList( lpItemID, szBuf ) )
  2082. {
  2083. bEnableOK = TRUE;
  2084. try
  2085. {
  2086. _tsplitpath( szBuf, szDrive, NULL, NULL, NULL );
  2087. size_t iDriveLen = _tcslen( szDrive );
  2088. _tcscat( szDrive, TEXT( "\\" ) );
  2089. UINT uiDevType = GetDriveType( szDrive );
  2090. if ( uiDevType != DRIVE_FIXED )
  2091. {
  2092. bEnableOK = FALSE;
  2093. }
  2094. else if ( lpAllowedDrives )
  2095. {
  2096. if ( lpAllowedDrives->driveCount > 0 )
  2097. {
  2098. szDrive[ iDriveLen ] = 0; // drop the slash
  2099. BOOL bFound = FALSE;
  2100. for ( int idx = 0; idx < lpAllowedDrives->driveCount; idx++ )
  2101. {
  2102. if ( !_tcsicmp( lpAllowedDrives->drives[ idx ].c_str(), szDrive ) )
  2103. {
  2104. bFound = TRUE;
  2105. break;
  2106. }
  2107. }
  2108. bEnableOK = bFound;
  2109. }
  2110. else if ( lpAllowedDrives->driveCount == 0 )
  2111. {
  2112. bEnableOK = FALSE;
  2113. }
  2114. }
  2115. }
  2116. catch (...)
  2117. {
  2118. }
  2119. }
  2120. SendMessage ( hwnd, BFFM_ENABLEOK, 0, bEnableOK );
  2121. }
  2122. return 0;
  2123. }
  2124. //
  2125. // GetWellKnownAccountName
  2126. //
  2127. // WELL_KNOWN_SID_TYPE is a system enumeration on Win XP & later, and
  2128. // Windows Server 2003 & later. It enumerates the well known SIDs.
  2129. //
  2130. // Using the functions CreateWellKnownSid, and LookupAccountSid, we
  2131. // can retrieve the account name & domain. These functions are locale
  2132. // independent.
  2133. //
  2134. BOOL
  2135. GetWellKnownAccountName( WELL_KNOWN_SID_TYPE idSidWellKnown, TCHAR *pwszName, DWORD *pcbSize )
  2136. {
  2137. ENTER();
  2138. //
  2139. // Initialize our output varable.
  2140. //
  2141. memset( pwszName, 0, *pcbSize );
  2142. //
  2143. // These are used for the call to LookupAccountSid.
  2144. //
  2145. TCHAR wszUserName[ 512 ];
  2146. DWORD cbUserName = 512 * sizeof( TCHAR );
  2147. TCHAR wszDomainName[ 512 ];
  2148. DWORD cbDomainName = 512 * sizeof( TCHAR );
  2149. memset( wszUserName, 0, cbUserName );
  2150. memset( wszDomainName, 0, cbDomainName );
  2151. //
  2152. // Try to allocate a buffer for the SID.
  2153. //
  2154. DWORD cbMaxSid = SECURITY_MAX_SID_SIZE;
  2155. PSID psidWellKnown = LocalAlloc( LMEM_FIXED, cbMaxSid );
  2156. if( NULL == psidWellKnown )
  2157. {
  2158. Log( _T( "Call to LocalAlloc failed." ) );
  2159. return FALSE;
  2160. }
  2161. //
  2162. // Create the SID.
  2163. //
  2164. BOOL b = CreateWellKnownSid( idSidWellKnown, NULL, psidWellKnown, &cbMaxSid );
  2165. if( !b )
  2166. {
  2167. Log( _T( "Call to CreateWellKnownSid failed." ) );
  2168. LocalFree( psidWellKnown );
  2169. return FALSE;
  2170. }
  2171. //
  2172. // Use the SID to determine the user name & domain name.
  2173. //
  2174. // For example, for idSidWellKnown = WinNetworkServiceSid,
  2175. // wszDomainName = "NT AUTHORITY"
  2176. // wszUserName = "NETWORK SERVICE"
  2177. //
  2178. SID_NAME_USE snu;
  2179. b = LookupAccountSid( NULL, psidWellKnown, wszUserName, &cbUserName, wszDomainName, &cbDomainName, &snu );
  2180. LocalFree( psidWellKnown );
  2181. if( !b )
  2182. {
  2183. Log( _T( "Call to LookupAccountSid failed." ) );
  2184. return FALSE;
  2185. }
  2186. else
  2187. {
  2188. Log( _T( "LookupAccountSid succeeded! domain name = %s, account name = %s" ), wszDomainName, wszUserName );
  2189. _tcsncat( pwszName, wszDomainName, *pcbSize );
  2190. _tcsncat( pwszName, _T( "\\" ), *pcbSize );
  2191. _tcsncat( pwszName, wszUserName, *pcbSize );
  2192. *pcbSize = _tcslen( pwszName ) * sizeof( TCHAR );
  2193. return TRUE;
  2194. }
  2195. }
  2196. BOOL
  2197. GrantNetworkLogonRights( LPCTSTR pwszUser )
  2198. {
  2199. //
  2200. // 1. Check our params.
  2201. //
  2202. if( NULL == pwszUser )
  2203. {
  2204. Log( _T( "NULL specified as domain user to function: GrantNetworkLogonRights. Returning FALSE." ) );
  2205. return FALSE;
  2206. }
  2207. TCHAR wszUser[ 1024 ];
  2208. memset( wszUser, 0, 1024 * sizeof( TCHAR ) );
  2209. //
  2210. // If the user account is a local account, it will be prefixed
  2211. // with ".\" For example: ".\Administrator".
  2212. //
  2213. // For some reason, LookupAccountName (which we rely on just below) wants
  2214. // local accounts not to be prefixed with ".\".
  2215. //
  2216. if( 0 == _tcsnicmp( _T( ".\\" ), pwszUser, 2 ) )
  2217. {
  2218. _tcsncpy( wszUser, &pwszUser[ 2 ], _tcslen( pwszUser ) - 2 );
  2219. }
  2220. else
  2221. {
  2222. _tcsncpy( wszUser, pwszUser, _tcslen( pwszUser ) );
  2223. }
  2224. Log( _T( "Account we will attempt to grant network logon rights = %s." ), wszUser );
  2225. //
  2226. // 2. Get the SID of the specified user.
  2227. //
  2228. PSID pUserSID = NULL;
  2229. DWORD cbUserSID = SECURITY_MAX_SID_SIZE;
  2230. TCHAR wszDomain[ 1024 ];
  2231. DWORD cbDomain = 1024 * sizeof( TCHAR );
  2232. SID_NAME_USE pUse;
  2233. pUserSID = LocalAlloc( LMEM_FIXED, cbUserSID );
  2234. if( NULL == pUserSID )
  2235. {
  2236. Log( _T( "Call to LocalAlloc failed." ) );
  2237. return FALSE;
  2238. }
  2239. memset( pUserSID, 0, cbUserSID );
  2240. BOOL fAPISuccess = LookupAccountName( NULL, wszUser, pUserSID, &cbUserSID, wszDomain, &cbDomain, &pUse );
  2241. if( !fAPISuccess )
  2242. {
  2243. Log( _T( "Call to LookupAccountName failed for user: %s." ), wszUser );
  2244. LocalFree( pUserSID );
  2245. return FALSE;
  2246. }
  2247. else
  2248. {
  2249. Log( _T( "Call to LookupAccountName succeeded for user: %s." ), wszUser );
  2250. }
  2251. //
  2252. // 3. Get a handle to Policy Object.
  2253. //
  2254. LSA_UNICODE_STRING lusMachineName;
  2255. lusMachineName.Length = 0;
  2256. lusMachineName.MaximumLength = 0;
  2257. lusMachineName.Buffer = NULL;
  2258. LSA_OBJECT_ATTRIBUTES loaObjAttrs;
  2259. memset( &loaObjAttrs, 0, sizeof( LSA_OBJECT_ATTRIBUTES ) );
  2260. ACCESS_MASK accessMask = POLICY_LOOKUP_NAMES | POLICY_CREATE_ACCOUNT;
  2261. LSA_HANDLE lhPolicy = NULL;
  2262. NTSTATUS status = LsaOpenPolicy( &lusMachineName, &loaObjAttrs, accessMask, &lhPolicy );
  2263. if( STATUS_SUCCESS != status )
  2264. {
  2265. Log( _T( "Call to LsaOpenPolicy failed." ) );
  2266. LocalFree( pUserSID );
  2267. return FALSE;
  2268. }
  2269. else
  2270. {
  2271. Log( _T( "Call to LsaOpenPolicy succeeded." ) );
  2272. }
  2273. //
  2274. // 4. Check & see if the user already has the account rights they need.
  2275. //
  2276. PLSA_UNICODE_STRING plusRights = NULL;
  2277. ULONG ulRightsCount = 0;
  2278. BOOL fHasNetworkLogonRights = FALSE;
  2279. status = LsaEnumerateAccountRights( lhPolicy, pUserSID, &plusRights, &ulRightsCount );
  2280. if( STATUS_SUCCESS == status )
  2281. {
  2282. for( ULONG i = 0; i < ulRightsCount; i++ )
  2283. {
  2284. if( 0 == wcscmp( plusRights[ i ].Buffer, SE_NETWORK_LOGON_NAME ) )
  2285. {
  2286. fHasNetworkLogonRights = TRUE;
  2287. Log( _T( "User account: %s already has network logon rights." ), wszUser );
  2288. break;
  2289. }
  2290. }
  2291. LsaFreeMemory( plusRights );
  2292. }
  2293. else
  2294. {
  2295. fHasNetworkLogonRights = FALSE;
  2296. }
  2297. //
  2298. // 5. If we need to add account rights, then add them.
  2299. //
  2300. BOOL fRet = FALSE;
  2301. if( !fHasNetworkLogonRights )
  2302. {
  2303. WCHAR wszNetworkLogon[] = L"SeNetworkLogonRight";
  2304. int iLen = wcslen( wszNetworkLogon );
  2305. LSA_UNICODE_STRING lusNetworkLogon;
  2306. lusNetworkLogon.Length = iLen * sizeof( WCHAR );
  2307. lusNetworkLogon.MaximumLength = ( iLen + 1 ) * sizeof( WCHAR );
  2308. lusNetworkLogon.Buffer = wszNetworkLogon;
  2309. status = LsaAddAccountRights( lhPolicy, pUserSID, &lusNetworkLogon, 1 );
  2310. if( STATUS_SUCCESS == status )
  2311. {
  2312. Log( _T( "User account: %s now has network logon rights." ), wszUser );
  2313. fRet = TRUE;
  2314. }
  2315. else
  2316. {
  2317. Log( _T( "Attempt to grant user account: %s logon rights failed." ), wszUser );
  2318. fRet = FALSE;
  2319. }
  2320. }
  2321. else
  2322. {
  2323. fRet = TRUE;
  2324. }
  2325. LocalFree( pUserSID );
  2326. LsaClose( lhPolicy );
  2327. return fRet;
  2328. }