Source code of Windows XP (NT5)
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.

1646 lines
49 KiB

  1. #include "stdafx.h"
  2. #include <ole2.h>
  3. #include "iadm.h"
  4. #include "iiscnfgp.h"
  5. #include "mdkey.h"
  6. #include "mdacl.h"
  7. #include "inetinfo.h"
  8. #include "log.h"
  9. #include "svc.h"
  10. #include "dcomperm.h"
  11. #include "setpass.h"
  12. #include <comadmin.h> // CLSID_COMAdminCatalog
  13. #include "comadmii.c" // CLSID_COMAdminCatalog
  14. typedef TCHAR USERNAME_STRING_TYPE[MAX_PATH];
  15. typedef TCHAR PASSWORD_STRING_TYPE[LM20_PWLEN+1];
  16. typedef enum {
  17. GUFM_SUCCESS,
  18. GUFM_NO_PATH,
  19. GUFM_NO_PASSWORD,
  20. GUFM_NO_USER_ID
  21. } GUFM_RETURN;
  22. #define OPEN_TIMEOUT_VALUE 30000
  23. #define MD_SET_DATA_RECORD_EXT(PMDR, ID, ATTR, UTYPE, DTYPE, DLEN, PD) \
  24. { \
  25. (PMDR)->dwMDIdentifier=ID; \
  26. (PMDR)->dwMDAttributes=ATTR; \
  27. (PMDR)->dwMDUserType=UTYPE; \
  28. (PMDR)->dwMDDataType=DTYPE; \
  29. (PMDR)->dwMDDataLen=DLEN; \
  30. (PMDR)->pbMDData=(PBYTE)PD; \
  31. }
  32. #define SYSPREP_TEMPFILE_NAME _T("IISSysPr.tmp")
  33. #define SYSPREP_KNOWN_SECTION_NAME _T("paths")
  34. #define SYSPREP_KNOWN_REGISTRY_KEY _T("SysPrepIISInfo")
  35. #define SYSPREP_TEMP_PASSWORD_LENGTH 256
  36. #define SYSPREP_USE_SECRETS
  37. #define REG_ENABLEPASSSYNC_KEY _T("SOFTWARE\\Microsoft\\InetStp")
  38. #define REG_ENABLEPASSSYNC_VALUE _T("EnableUserAccountRestorePassSync")
  39. DWORD AddUserToMetabaseACL2(CString csKeyPath, LPTSTR szUserToAdd, ACCESS_ALLOWED_ACE * MyACEInfo);
  40. #ifndef _CHICAGO_
  41. HRESULT
  42. UpdateComApplications(
  43. IMSAdminBase2 * pcCom,
  44. LPCTSTR szWamUserName,
  45. LPCTSTR szWamUserPass
  46. )
  47. /*++
  48. Routine Description:
  49. If the IWAM account has been modified, it is necessary to update the
  50. the out of process com+ applications with the correct account
  51. information. This routine will collect all the com+ applications and
  52. reset the activation information.
  53. Arguments:
  54. pcCom - metabase object
  55. szWamUserName - the new user name
  56. szWamUserPass - the new user password
  57. Note:
  58. This routine is a royal pain in the butt. I take back
  59. all the good things I may have said about com automation.
  60. Return Value:
  61. HRESULT - Return value from failed API call
  62. - E_OUTOFMEMORY
  63. - S_OK - everything worked
  64. - S_FALSE - encountered a non-fatal error, unable
  65. to reset at least one application.
  66. --*/
  67. {
  68. HRESULT hr = NOERROR;
  69. BOOL fNoErrors = TRUE;
  70. METADATA_HANDLE hMetabase = NULL;
  71. WCHAR * pwszDataPaths = NULL;
  72. DWORD cchDataPaths = 0;
  73. BOOL fTryAgain;
  74. DWORD cMaxApplications;
  75. WCHAR * pwszCurrentPath;
  76. SAFEARRAY * psaApplications = NULL;
  77. SAFEARRAYBOUND rgsaBound[1];
  78. DWORD cApplications;
  79. VARIANT varAppKey;
  80. LONG rgIndices[1];
  81. METADATA_RECORD mdrAppIsolated;
  82. METADATA_RECORD mdrAppPackageId;
  83. DWORD dwAppIsolated;
  84. WCHAR wszAppPackageId[ 40 ];
  85. DWORD dwMDGetDataLen = 0;
  86. ICOMAdminCatalog * pComCatalog = NULL;
  87. ICatalogCollection * pComAppCollection = NULL;
  88. ICatalogObject * pComApp = NULL;
  89. BSTR bstrAppCollectionName = NULL;
  90. LONG nAppsInCollection;
  91. LONG iCurrentApp;
  92. LONG nChanges;
  93. VARIANT varOldAppIdentity;
  94. VARIANT varNewAppIdentity;
  95. VARIANT varNewAppPassword;
  96. // This is built unicode right now. Since all the com apis I need
  97. // are unicode only I'm using wide characters here. I should get
  98. // plenty of compiler errors if _UNICODE isn't defined, but just
  99. // in case....
  100. DBG_ASSERT( sizeof(TCHAR) == sizeof(WCHAR) );
  101. iisDebugOut((LOG_TYPE_TRACE, _T("UpdateComApplications():start\n")));
  102. // Init variants
  103. VariantInit( &varAppKey );
  104. VariantInit( &varOldAppIdentity );
  105. VariantInit( &varNewAppIdentity );
  106. VariantInit( &varNewAppPassword );
  107. //
  108. // Get the applications to be reset by querying the metabase paths
  109. //
  110. hr = pcCom->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  111. L"LM/W3SVC",
  112. METADATA_PERMISSION_READ,
  113. OPEN_TIMEOUT_VALUE,
  114. &hMetabase
  115. );
  116. if( FAILED(hr) )
  117. {
  118. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to open metabase (%08x)\n"),hr));
  119. goto cleanup;
  120. }
  121. // Get the data paths string
  122. fTryAgain = TRUE;
  123. do
  124. {
  125. hr = pcCom->GetDataPaths( hMetabase,
  126. NULL,
  127. MD_APP_PACKAGE_ID,
  128. STRING_METADATA,
  129. cchDataPaths,
  130. pwszDataPaths,
  131. &cchDataPaths
  132. );
  133. if( HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr )
  134. {
  135. delete[] pwszDataPaths;
  136. pwszDataPaths = NULL;
  137. pwszDataPaths = new WCHAR[cchDataPaths];
  138. if( !pwszDataPaths )
  139. {
  140. hr = E_OUTOFMEMORY;
  141. goto cleanup;
  142. }
  143. }
  144. else
  145. {
  146. fTryAgain = FALSE;
  147. }
  148. }
  149. while( fTryAgain );
  150. if( FAILED(hr) )
  151. {
  152. iisDebugOut((LOG_TYPE_ERROR, _T("Failed to find metadata (%08x) Data(%d)\n"),hr,MD_APP_PACKAGE_ID));
  153. goto cleanup;
  154. }
  155. else if (pwszDataPaths == NULL)
  156. {
  157. //
  158. // If we found no isolated apps, make the path list an empty multisz
  159. //
  160. cchDataPaths = 1;
  161. pwszDataPaths = new WCHAR[cchDataPaths];
  162. if( !pwszDataPaths )
  163. {
  164. hr = E_OUTOFMEMORY;
  165. goto cleanup;
  166. }
  167. pwszDataPaths[0] = L'\0';
  168. }
  169. // Determine the maximum number of applications
  170. cMaxApplications = 1; // The pooled application
  171. for( pwszCurrentPath = pwszDataPaths;
  172. *pwszCurrentPath != L'\0';
  173. pwszCurrentPath += wcslen(pwszCurrentPath) + 1
  174. )
  175. {
  176. cMaxApplications++;
  177. }
  178. //
  179. // Build a key array and load the com applications.
  180. //
  181. // Create an array to hold the keys
  182. rgsaBound[0].cElements = cMaxApplications;
  183. rgsaBound[0].lLbound = 0;
  184. psaApplications = SafeArrayCreate( VT_VARIANT, 1, rgsaBound );
  185. if( psaApplications == NULL )
  186. {
  187. hr = E_OUTOFMEMORY;
  188. goto cleanup;
  189. }
  190. // Set the out of process pool application key
  191. varAppKey.vt = VT_BSTR;
  192. varAppKey.bstrVal = SysAllocString( W3_OOP_POOL_PACKAGE_ID );
  193. if( !varAppKey.bstrVal )
  194. {
  195. hr = E_OUTOFMEMORY;
  196. goto cleanup;
  197. }
  198. rgIndices[0] = 0;
  199. hr = SafeArrayPutElement( psaApplications, rgIndices, &varAppKey );
  200. if( FAILED(hr) )
  201. {
  202. iisDebugOut((LOG_TYPE_ERROR, _T("Failed setting an element in a safe array (%08x)\n"),hr));
  203. goto cleanup;
  204. }
  205. // For each of the application paths determine if an out of process
  206. // application is defined there and set the appropriate key into
  207. // our array
  208. MD_SET_DATA_RECORD_EXT( &mdrAppIsolated,
  209. MD_APP_ISOLATED,
  210. METADATA_NO_ATTRIBUTES,
  211. ALL_METADATA,
  212. DWORD_METADATA,
  213. sizeof(DWORD),
  214. (PBYTE)&dwAppIsolated
  215. );
  216. MD_SET_DATA_RECORD_EXT( &mdrAppPackageId,
  217. MD_APP_PACKAGE_ID,
  218. METADATA_NO_ATTRIBUTES,
  219. ALL_METADATA,
  220. STRING_METADATA,
  221. sizeof(wszAppPackageId),
  222. (PBYTE)wszAppPackageId
  223. );
  224. wszAppPackageId[0] = L'\0';
  225. // Go through each data path and set it into our array if
  226. // it is an isolated application
  227. cApplications = 1; // Actual # of applications - 1 for pool
  228. for( pwszCurrentPath = pwszDataPaths;
  229. *pwszCurrentPath != L'\0';
  230. pwszCurrentPath += wcslen(pwszCurrentPath) + 1
  231. )
  232. {
  233. hr = pcCom->GetData( hMetabase,
  234. pwszCurrentPath,
  235. &mdrAppIsolated,
  236. &dwMDGetDataLen
  237. );
  238. if( FAILED(hr) )
  239. {
  240. iisDebugOut(( LOG_TYPE_ERROR,
  241. _T("Failed to get data from the metabase (%08x) Path(%S) Data(%d)\n"),
  242. hr,
  243. pwszCurrentPath,
  244. mdrAppIsolated.dwMDIdentifier
  245. ));
  246. fNoErrors = FALSE;
  247. continue;
  248. }
  249. // Is the application out of process
  250. if( dwAppIsolated == 1 )
  251. {
  252. // Get the application id
  253. hr = pcCom->GetData( hMetabase,
  254. pwszCurrentPath,
  255. &mdrAppPackageId,
  256. &dwMDGetDataLen
  257. );
  258. if( FAILED(hr) )
  259. {
  260. iisDebugOut(( LOG_TYPE_ERROR,
  261. _T("Failed to get data from the metabase (%08x) Path(%S) Data(%d)\n"),
  262. hr,
  263. pwszCurrentPath,
  264. mdrAppPackageId.dwMDIdentifier
  265. ));
  266. fNoErrors = FALSE;
  267. continue;
  268. }
  269. // Add the application id to the array
  270. VariantClear( &varAppKey );
  271. varAppKey.vt = VT_BSTR;
  272. varAppKey.bstrVal = SysAllocString( wszAppPackageId );
  273. if( !varAppKey.bstrVal )
  274. {
  275. hr = E_OUTOFMEMORY;
  276. goto cleanup;
  277. }
  278. rgIndices[0]++;
  279. hr = SafeArrayPutElement( psaApplications,
  280. rgIndices,
  281. &varAppKey
  282. );
  283. if( FAILED(hr) )
  284. {
  285. iisDebugOut(( LOG_TYPE_ERROR,
  286. _T("Failed to set safe array element (%08x)\n"),
  287. hr
  288. ));
  289. VariantClear( &varAppKey );
  290. rgIndices[0]--;
  291. fNoErrors = FALSE;
  292. continue;
  293. }
  294. cApplications++;
  295. }
  296. }
  297. // Done with the metabase
  298. pcCom->CloseKey(hMetabase);
  299. hMetabase = NULL;
  300. // Shrink the size of the safe-array if necessary
  301. if( cApplications < cMaxApplications )
  302. {
  303. rgsaBound[0].cElements = cApplications;
  304. hr = SafeArrayRedim( psaApplications, rgsaBound );
  305. if( FAILED(hr) )
  306. {
  307. iisDebugOut(( LOG_TYPE_ERROR,
  308. _T("Failed to redim safe array (%08x)\n"),
  309. hr
  310. ));
  311. goto cleanup;
  312. }
  313. }
  314. //
  315. // For each application reset the activation identity
  316. //
  317. // Use our key array to get the application collection
  318. hr = CoCreateInstance( CLSID_COMAdminCatalog,
  319. NULL,
  320. CLSCTX_SERVER,
  321. IID_ICOMAdminCatalog,
  322. (void**)&pComCatalog
  323. );
  324. if( FAILED(hr) )
  325. {
  326. iisDebugOut(( LOG_TYPE_ERROR,
  327. _T("Failed to create COM catalog (%08x)\n"),
  328. hr
  329. ));
  330. goto cleanup;
  331. }
  332. hr = pComCatalog->GetCollection( L"Applications",
  333. (IDispatch **)&pComAppCollection
  334. );
  335. if( FAILED(hr) )
  336. {
  337. iisDebugOut(( LOG_TYPE_ERROR,
  338. _T("Failed to get Applications collection (%08x)\n"),
  339. hr
  340. ));
  341. goto cleanup;
  342. }
  343. hr = pComAppCollection->PopulateByKey( psaApplications );
  344. if( FAILED(hr) )
  345. {
  346. iisDebugOut(( LOG_TYPE_ERROR,
  347. _T("Failed to populate Applications collection (%08x)\n"),
  348. hr
  349. ));
  350. goto cleanup;
  351. }
  352. // Iterate over the application collection and update all the
  353. // applications that use IWAM.
  354. hr = pComAppCollection->get_Count( &nAppsInCollection );
  355. if( FAILED(hr) )
  356. {
  357. iisDebugOut(( LOG_TYPE_ERROR,
  358. _T("Failed to get Applications count (%08x)\n"),
  359. hr
  360. ));
  361. goto cleanup;
  362. }
  363. // Init our new app identity and password.
  364. varNewAppIdentity.vt = VT_BSTR;
  365. varNewAppIdentity.bstrVal = SysAllocString( szWamUserName );
  366. if( !varNewAppIdentity.bstrVal )
  367. {
  368. hr = E_OUTOFMEMORY;
  369. goto cleanup;
  370. }
  371. varNewAppPassword.vt = VT_BSTR;
  372. varNewAppPassword.bstrVal = SysAllocString( szWamUserPass );
  373. if( !varNewAppPassword.bstrVal )
  374. {
  375. hr = E_OUTOFMEMORY;
  376. goto cleanup;
  377. }
  378. for( iCurrentApp = 0; iCurrentApp < nAppsInCollection; ++iCurrentApp )
  379. {
  380. if( pComApp )
  381. {
  382. pComApp->Release();
  383. pComApp = NULL;
  384. }
  385. if( varOldAppIdentity.vt != VT_EMPTY )
  386. {
  387. VariantClear( &varOldAppIdentity );
  388. }
  389. hr = pComAppCollection->get_Item( iCurrentApp,
  390. (IDispatch **)&pComApp );
  391. if( FAILED(hr) )
  392. {
  393. iisDebugOut(( LOG_TYPE_ERROR,
  394. _T("Failed to get item from Applications collection (%08x)\n"),
  395. hr
  396. ));
  397. fNoErrors = FALSE;
  398. continue;
  399. }
  400. // If the user has set this to something other than the IWAM_
  401. // user, then we will respect that and not reset the identiy.
  402. hr = pComApp->get_Value( L"Identity", &varOldAppIdentity );
  403. if( FAILED(hr) )
  404. {
  405. iisDebugOut(( LOG_TYPE_ERROR,
  406. _T("Failed to get Identify from Application (%08x)\n"),
  407. hr
  408. ));
  409. fNoErrors = FALSE;
  410. continue;
  411. }
  412. DBG_ASSERT( varOldAppIdentity.vt == VT_BSTR );
  413. if( varOldAppIdentity.vt == VT_BSTR )
  414. {
  415. if( memcmp( L"IWAM_", varOldAppIdentity.bstrVal, 10 ) == 0 )
  416. {
  417. hr = pComApp->put_Value( L"Identity", varNewAppIdentity );
  418. if( FAILED(hr) )
  419. {
  420. iisDebugOut(( LOG_TYPE_ERROR,
  421. _T("Failed to set new Identify (%08x)\n"),
  422. hr
  423. ));
  424. fNoErrors = FALSE;
  425. continue;
  426. }
  427. hr = pComApp->put_Value( L"Password", varNewAppPassword );
  428. if( FAILED(hr) )
  429. {
  430. iisDebugOut(( LOG_TYPE_ERROR,
  431. _T("Failed to set new Password (%08x)\n"),
  432. hr
  433. ));
  434. fNoErrors = FALSE;
  435. continue;
  436. }
  437. }
  438. else
  439. {
  440. DBGINFO(( DBG_CONTEXT,
  441. "Unrecognized application identity (%S)\n",
  442. varOldAppIdentity.bstrVal
  443. ));
  444. }
  445. }
  446. }
  447. hr = pComAppCollection->SaveChanges( &nChanges );
  448. if( FAILED(hr) )
  449. {
  450. iisDebugOut(( LOG_TYPE_ERROR,
  451. _T("Failed to save changes (%08x)\n"),
  452. hr
  453. ));
  454. goto cleanup;
  455. }
  456. goto cleanup;
  457. cleanup:
  458. if( hMetabase != NULL )
  459. {
  460. pcCom->CloseKey(hMetabase);
  461. }
  462. if( psaApplications != NULL )
  463. {
  464. SafeArrayDestroy( psaApplications );
  465. }
  466. if( pComCatalog != NULL )
  467. {
  468. pComCatalog->Release();
  469. }
  470. if( pComAppCollection != NULL )
  471. {
  472. pComAppCollection->Release();
  473. }
  474. if( pComApp != NULL )
  475. {
  476. pComApp->Release();
  477. }
  478. if( varAppKey.vt != VT_EMPTY )
  479. {
  480. VariantClear( &varAppKey );
  481. }
  482. if( varOldAppIdentity.vt != VT_EMPTY )
  483. {
  484. VariantClear( &varOldAppIdentity );
  485. }
  486. if( varNewAppIdentity.vt != VT_EMPTY )
  487. {
  488. VariantClear( &varNewAppIdentity );
  489. }
  490. if( varNewAppPassword.vt != VT_EMPTY )
  491. {
  492. VariantClear( &varNewAppPassword );
  493. }
  494. delete [] pwszDataPaths;
  495. iisDebugOut((LOG_TYPE_TRACE, _T("UpdateComApplications():end\n")));
  496. // return
  497. if( FAILED(hr) )
  498. {
  499. return hr;
  500. }
  501. else if( fNoErrors == FALSE )
  502. {
  503. return S_FALSE;
  504. }
  505. else
  506. {
  507. return S_OK;
  508. }
  509. }
  510. GUFM_RETURN GetUserFromMetabase(IMSAdminBase2 *pcCom,
  511. LPWSTR pszPath,
  512. DWORD dwUserMetaId,
  513. DWORD dwPasswordMetaId,
  514. USERNAME_STRING_TYPE ustUserBuf,
  515. PASSWORD_STRING_TYPE pstPasswordBuf)
  516. {
  517. HRESULT hresTemp;
  518. GUFM_RETURN gufmReturn = GUFM_SUCCESS;
  519. METADATA_RECORD mdrData;
  520. DWORD dwRequiredDataLen;
  521. METADATA_HANDLE mhOpenHandle;
  522. hresTemp = pcCom->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  523. pszPath,
  524. METADATA_PERMISSION_READ,
  525. OPEN_TIMEOUT_VALUE,
  526. &mhOpenHandle);
  527. if (FAILED(hresTemp)) {
  528. gufmReturn = GUFM_NO_PATH;
  529. }
  530. else {
  531. MD_SET_DATA_RECORD_EXT(&mdrData,
  532. dwUserMetaId,
  533. METADATA_NO_ATTRIBUTES,
  534. ALL_METADATA,
  535. STRING_METADATA,
  536. MAX_PATH * sizeof(TCHAR),
  537. (PBYTE)ustUserBuf)
  538. hresTemp = pcCom->GetData(mhOpenHandle,
  539. NULL,
  540. &mdrData,
  541. &dwRequiredDataLen);
  542. if (FAILED(hresTemp) || (ustUserBuf[0] == (TCHAR)'\0')) {
  543. gufmReturn = GUFM_NO_USER_ID;
  544. }
  545. else {
  546. MD_SET_DATA_RECORD_EXT(&mdrData,
  547. dwPasswordMetaId,
  548. METADATA_NO_ATTRIBUTES,
  549. ALL_METADATA,
  550. STRING_METADATA,
  551. MAX_PATH * sizeof(TCHAR),
  552. (PBYTE)pstPasswordBuf)
  553. hresTemp = pcCom->GetData(mhOpenHandle,
  554. NULL,
  555. &mdrData,
  556. &dwRequiredDataLen);
  557. if (FAILED(hresTemp)) {
  558. gufmReturn = GUFM_NO_PASSWORD;
  559. }
  560. }
  561. pcCom->CloseKey(mhOpenHandle);
  562. }
  563. return gufmReturn;
  564. }
  565. #endif
  566. HRESULT WINAPI SysPrepAclSyncIWam(void)
  567. {
  568. HRESULT hr = S_OK;
  569. IMSAdminBase2 * pcCom;
  570. GUFM_RETURN gufmTemp;
  571. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("start\n")));
  572. hr = CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase2,(void **) & pcCom);
  573. if (SUCCEEDED(hr))
  574. {
  575. #ifndef _CHICAGO_
  576. PASSWORD_STRING_TYPE pstAnonyPass;
  577. USERNAME_STRING_TYPE ustAnonyName;
  578. pstAnonyPass[0] = (TCHAR)'\0';
  579. ustAnonyName[0] = (TCHAR)'\0';
  580. //
  581. // Get the WAM username and password
  582. //
  583. gufmTemp = GetUserFromMetabase(pcCom,
  584. TEXT("LM/W3SVC"),
  585. MD_WAM_USER_NAME,
  586. MD_WAM_PWD,
  587. ustAnonyName,
  588. pstAnonyPass);
  589. UpdateComApplications(pcCom,ustAnonyName,pstAnonyPass);
  590. #endif
  591. pcCom->Release();
  592. }
  593. // Loop thru all the acl's
  594. // and get the values, store it somewhere
  595. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("end,ret=0x%x\n"),hr));
  596. return hr;
  597. }
  598. // function: ReSetIWamIUsrPasswds
  599. //
  600. // This function Changes the IWAM and IUSR passwords the
  601. // metabase. Then sets a reg entry, and stops and starts
  602. // iisadmin. This causes iisadmin to reset the password in NT,
  603. // and re sync the com objects.
  604. //
  605. // Return:
  606. // TRUE - Succeeded
  607. // FALSE - Failed
  608. //
  609. BOOL ReSetIWamIUsrPasswds(void)
  610. {
  611. DWORD dwType;
  612. DWORD dwValue;
  613. DWORD dwSize;
  614. DWORD dwOldRegValue;
  615. BOOL fOldRegWasSet = FALSE;
  616. CMDKey cmdKey;
  617. LPTSTR pszNewPassword = NULL;
  618. HKEY hKey;
  619. iisDebugOut((LOG_TYPE_TRACE, _T("ReSetIWamIUsrPasswds:start\n")));
  620. if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  621. REG_ENABLEPASSSYNC_KEY,
  622. 0,
  623. KEY_READ | KEY_WRITE,
  624. &hKey) != ERROR_SUCCESS)
  625. {
  626. // If we can not open the registry to set the flag,
  627. // there is not hope in resetting the password
  628. return FALSE;
  629. }
  630. cmdKey.OpenNode(TEXT("LM/W3SVC"));
  631. // Set New IUSR Password
  632. if (pszNewPassword = CreatePassword(LM20_PWLEN+1))
  633. {
  634. cmdKey.SetData(MD_ANONYMOUS_PWD,METADATA_INHERIT | METADATA_SECURE,IIS_MD_UT_FILE,STRING_METADATA,(_tcslen(pszNewPassword)+1)*sizeof(TCHAR),(LPBYTE) pszNewPassword);
  635. GlobalFree(pszNewPassword);
  636. }
  637. // Set New IWAM Password
  638. if (pszNewPassword = CreatePassword(LM20_PWLEN+1))
  639. {
  640. cmdKey.SetData(MD_WAM_PWD,METADATA_INHERIT | METADATA_SECURE,IIS_MD_UT_FILE,STRING_METADATA,(_tcslen(pszNewPassword)+1)*sizeof(TCHAR),(LPBYTE) pszNewPassword);
  641. GlobalFree(pszNewPassword);
  642. }
  643. cmdKey.Close();
  644. // Retrieve Old Value for REG_ENABLEPASSSYNC
  645. dwSize = sizeof(DWORD);
  646. if ( (RegQueryValueEx(hKey,REG_ENABLEPASSSYNC_VALUE,NULL,&dwType,(LPBYTE) &dwValue,&dwSize) == ERROR_SUCCESS) &&
  647. (dwType == REG_DWORD)
  648. )
  649. {
  650. fOldRegWasSet = TRUE;
  651. dwOldRegValue = dwValue;
  652. }
  653. // Set New Value
  654. dwSize = sizeof(DWORD);
  655. dwType = REG_DWORD;
  656. dwValue = 1;
  657. if (RegSetValueEx(hKey,REG_ENABLEPASSSYNC_VALUE,0,dwType,(LPBYTE) &dwValue,dwSize) == ERROR_SUCCESS)
  658. {
  659. // Stop IISAdmin Service
  660. StopServiceAndDependencies(TEXT("IISADMIN"), FALSE);
  661. // Start IISAdmin Service (this will resync the passwords)
  662. InetStartService(TEXT("IISADMIN"));
  663. // We are going to reboot after installing, so don't
  664. // worry about starting the services that we cascadingly
  665. // stopped
  666. // Reset the Key to the old value
  667. if (fOldRegWasSet)
  668. {
  669. dwSize = sizeof(DWORD);
  670. dwType = REG_DWORD;
  671. RegSetValueEx(hKey,REG_ENABLEPASSSYNC_VALUE,0,dwType,(LPBYTE) &dwOldRegValue,dwSize);
  672. }
  673. else
  674. {
  675. RegDeleteValue(hKey,REG_ENABLEPASSSYNC_VALUE);
  676. }
  677. }
  678. else
  679. {
  680. RegCloseKey(hKey);
  681. return FALSE;
  682. }
  683. RegCloseKey(hKey);
  684. return TRUE;
  685. }
  686. DWORD SysPrepTempfileWriteAclInfo(HANDLE hFile,CString csKeyPath)
  687. {
  688. DWORD dwReturn = E_FAIL;
  689. BOOL bFound = FALSE;
  690. DWORD attr, uType, dType, cbLen;
  691. CMDKey cmdKey;
  692. BUFFER bufData;
  693. PBYTE pData;
  694. int BufSize;
  695. PSECURITY_DESCRIPTOR pOldSd = NULL;
  696. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
  697. {
  698. return S_OK;
  699. }
  700. cmdKey.OpenNode(csKeyPath);
  701. if ( (METADATA_HANDLE) cmdKey )
  702. {
  703. pData = (PBYTE)(bufData.QueryPtr());
  704. BufSize = bufData.QuerySize();
  705. cbLen = 0;
  706. bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
  707. if (!bFound)
  708. {
  709. if (cbLen > 0)
  710. {
  711. if ( ! (bufData.Resize(cbLen)) )
  712. {
  713. iisDebugOut((LOG_TYPE_ERROR, _T("MDDumpAdminACL(): cmdKey.GetData. failed to resize to %d.!\n"), cbLen));
  714. }
  715. else
  716. {
  717. pData = (PBYTE)(bufData.QueryPtr());
  718. BufSize = cbLen;
  719. cbLen = 0;
  720. bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
  721. }
  722. }
  723. }
  724. cmdKey.Close();
  725. if (bFound)
  726. {
  727. // dump out the info
  728. // We've got the acl
  729. pOldSd = (PSECURITY_DESCRIPTOR) pData;
  730. if (IsValidSecurityDescriptor(pOldSd))
  731. {
  732. #ifndef _CHICAGO_
  733. DumpAdminACL(hFile,pOldSd);
  734. dwReturn = ERROR_SUCCESS;
  735. #endif
  736. }
  737. }
  738. else
  739. {
  740. // there was no acl to be found.
  741. }
  742. }
  743. return dwReturn;
  744. }
  745. void SysPrepTempfileWrite(HANDLE hFile,TCHAR * szBuf)
  746. {
  747. DWORD dwBytesWritten = 0;
  748. if (hFile != NULL && hFile != INVALID_HANDLE_VALUE)
  749. {
  750. if (WriteFile(hFile, szBuf, _tcslen(szBuf) * sizeof(TCHAR), &dwBytesWritten, NULL ) == FALSE )
  751. {iisDebugOut((LOG_TYPE_WARN, _T("WriteFile Failed=0x%x.\n"), GetLastError()));}
  752. }
  753. return;
  754. }
  755. // Loop thru all the acl's
  756. // and get the values, store it somewhere
  757. HRESULT WINAPI SysPrepAclBackup(void)
  758. {
  759. HRESULT hRes = S_OK;
  760. CMDKey cmdKey;
  761. CStringList cslpathList;
  762. POSITION pos;
  763. CString csPath;
  764. HANDLE hFile = INVALID_HANDLE_VALUE;
  765. DWORD dwBytesWritten = 0;
  766. TCHAR buf[256];
  767. TCHAR szTempFileNameFull[_MAX_PATH];
  768. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("start\n")));
  769. hRes = cmdKey.OpenNode(_T("/"));
  770. if ( FAILED(hRes) )
  771. {
  772. iisDebugOut((LOG_TYPE_ERROR, _T("OpenNode failed. err=0x%x.\n"), hRes));
  773. goto SysPrepAclBackup_Exit;
  774. }
  775. // get the sub-paths that have the data on them
  776. hRes = cmdKey.GetDataPaths( MD_ADMIN_ACL, BINARY_METADATA, cslpathList);
  777. if ( FAILED(hRes) )
  778. {
  779. iisDebugOut((LOG_TYPE_ERROR, _T("Update()-GetDataPaths failed. err=0x%x.\n"), hRes));
  780. goto SysPrepAclBackup_Exit;
  781. }
  782. // we now have the cstringlist of paths that need to be updated. Loop through the
  783. // list and update them all.
  784. // get the list's head position
  785. pos = cslpathList.GetHeadPosition();
  786. if ( NULL == pos )
  787. {
  788. goto SysPrepAclBackup_Exit;
  789. }
  790. // Create the tempfile
  791. if (!GetWindowsDirectory(szTempFileNameFull,_MAX_PATH))
  792. {
  793. goto SysPrepAclBackup_Exit;
  794. }
  795. AddPath(szTempFileNameFull, SYSPREP_TEMPFILE_NAME);
  796. if (GetFileAttributes(szTempFileNameFull) != 0xFFFFFFFF)
  797. {
  798. // if file already exists, then delete it
  799. SetFileAttributes(szTempFileNameFull, FILE_ATTRIBUTE_NORMAL);
  800. DeleteFile(szTempFileNameFull);
  801. }
  802. // create the file
  803. hFile = CreateFile(szTempFileNameFull,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  804. if (hFile == INVALID_HANDLE_VALUE)
  805. {
  806. hFile = NULL;
  807. goto SysPrepAclBackup_Exit;
  808. }
  809. SetFilePointer( hFile, NULL, NULL, FILE_END );
  810. // write a couple of bytes to the beginning of the file say that it's "unicode"
  811. WriteFile(hFile, (LPCVOID) 0xFF, 1, &dwBytesWritten, NULL);
  812. WriteFile(hFile, (LPCVOID) 0xFE, 1, &dwBytesWritten, NULL);
  813. // write a section so that setupapi api's can read it
  814. //
  815. //[version]
  816. //signature="$Windows NT$"
  817. memset(buf, 0, _tcslen(buf) * sizeof(TCHAR));
  818. _tcscpy(buf, _T("[version]\r\n"));SysPrepTempfileWrite(hFile, buf);
  819. _tcscpy(buf, _T("signature=\"$Windows NT$\"\r\n"));SysPrepTempfileWrite(hFile, buf);
  820. // Write in known section
  821. _stprintf(buf, _T("[%s]\r\n"),SYSPREP_KNOWN_SECTION_NAME);SysPrepTempfileWrite(hFile, buf);
  822. // Add entries for the [paths] section
  823. // [paths]
  824. // /
  825. // /w3svc/info
  826. // etc...
  827. //
  828. while ( NULL != pos )
  829. {
  830. // get the next path in question
  831. csPath = cslpathList.GetNext( pos );
  832. // Write to [paths] section
  833. _stprintf(buf, _T("%s\r\n"),csPath);
  834. SysPrepTempfileWrite(hFile, buf);
  835. // Save this whole list to the tempfile....
  836. //iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("[%s]\n"),csPath));
  837. }
  838. // close the metabase
  839. if ( (METADATA_HANDLE)cmdKey )
  840. {cmdKey.Close();}
  841. // go to the top of the list again
  842. pos = cslpathList.GetHeadPosition();
  843. while ( NULL != pos )
  844. {
  845. // get the next path in question
  846. csPath = cslpathList.GetNext( pos );
  847. // Write to [paths] section
  848. _stprintf(buf, _T("[%s]\r\n"),csPath);
  849. SysPrepTempfileWrite(hFile, buf);
  850. // Get the info that we will add to this section from looking up the metabase...
  851. // open up the metabase item for each of them.
  852. // Grab the AdminACL data, convert it to username/permissions
  853. // save the username/permission data into text format
  854. SysPrepTempfileWriteAclInfo(hFile,csPath);
  855. }
  856. SysPrepAclBackup_Exit:
  857. if ( (METADATA_HANDLE)cmdKey )
  858. {cmdKey.Close();}
  859. if (hFile)
  860. {CloseHandle(hFile);}
  861. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("end,ret=0x%x\n"),hRes));
  862. return hRes;
  863. }
  864. void SysPrepRestoreAclSection(IN HINF hFile, IN LPCTSTR szSection)
  865. {
  866. LPTSTR szLine = NULL;
  867. DWORD dwRequiredSize;
  868. BOOL bRet = FALSE;
  869. INFCONTEXT Context;
  870. // go to the beginning of the section in the INF file
  871. bRet = SetupFindFirstLine_Wrapped(hFile, szSection, NULL, &Context);
  872. if (!bRet)
  873. {
  874. goto SysPrepRestoreAclSection_Exit;
  875. }
  876. // loop through the items in the section.
  877. while (bRet)
  878. {
  879. // get the size of the memory we need for this
  880. bRet = SetupGetLineText(&Context, NULL, NULL, NULL, NULL, 0, &dwRequiredSize);
  881. // prepare the buffer to receive the line
  882. szLine = (LPTSTR)GlobalAlloc( GPTR, dwRequiredSize * sizeof(TCHAR) );
  883. if ( !szLine )
  884. {
  885. goto SysPrepRestoreAclSection_Exit;
  886. }
  887. // get the line from the inf file1
  888. if (SetupGetLineText(&Context, NULL, NULL, NULL, szLine, dwRequiredSize, NULL) == FALSE)
  889. {
  890. goto SysPrepRestoreAclSection_Exit;
  891. }
  892. // The line we get should look something like this:
  893. //
  894. //[/]
  895. //IIS_WPG,0x0,0x0,0x24,0x400ab
  896. //Administrators,0x0,0x0,0x18,0x400ab
  897. //Everyone,0x0,0x0,0x14,0x8
  898. // Get everything to the left of the "=" sign
  899. // this should be the username
  900. TCHAR szUserName[UNLEN + 1];
  901. ACCESS_ALLOWED_ACE MyNewACE;
  902. /*
  903. typedef struct _ACCESS_ALLOWED_ACE {
  904. ACE_HEADER Header;
  905. ACCESS_MASK Mask;
  906. ULONG SidStart;
  907. } ACCESS_ALLOWED_ACE;
  908. typedef struct _ACE_HEADER {
  909. UCHAR AceType;
  910. UCHAR AceFlags;
  911. USHORT AceSize;
  912. } ACE_HEADER;
  913. typedef ACE_HEADER *PACE_HEADER;
  914. typedef ULONG ACCESS_MASK;
  915. */
  916. TCHAR *token = NULL;
  917. token = _tcstok(szLine, _T(","));
  918. if (token == NULL)
  919. {
  920. goto SysPrepRestoreAclSection_Exit;
  921. }
  922. // Get the username
  923. _tcscpy(szUserName,token);
  924. // Get the next 4 values...
  925. token = _tcstok(NULL, _T(","));
  926. if (NULL == token){goto SysPrepRestoreAclSection_Exit;}
  927. MyNewACE.Header.AceType = (UCHAR) atodw(token);
  928. token = _tcstok(NULL, _T(","));
  929. if (NULL == token){goto SysPrepRestoreAclSection_Exit;}
  930. MyNewACE.Header.AceFlags = (UCHAR) atodw(token);
  931. token = _tcstok(NULL, _T(","));
  932. if (NULL == token){goto SysPrepRestoreAclSection_Exit;}
  933. MyNewACE.Header.AceSize = (USHORT) atodw(token);
  934. token = _tcstok(NULL, _T(","));
  935. if (NULL == token){goto SysPrepRestoreAclSection_Exit;}
  936. MyNewACE.Mask = atodw(token);
  937. //iisDebugOut((LOG_TYPE_TRACE, _T("NewACLinfo:%s,0x%x,0x%x,0x%x,0x%x\n"),szUserName,MyNewACE.Header.AceType,MyNewACE.Header.AceFlags,MyNewACE.Header.AceSize,MyNewACE.Mask));
  938. // Grab this info and create an ACL for it.
  939. AddUserToMetabaseACL2(szSection,szUserName,&MyNewACE);
  940. // find the next line in the section. If there is no next line it should return false
  941. bRet = SetupFindNextLine(&Context, &Context);
  942. // free the temporary buffer
  943. GlobalFree( szLine );szLine=NULL;
  944. szLine = NULL;
  945. }
  946. SysPrepRestoreAclSection_Exit:
  947. if (szLine) {GlobalFree(szLine);szLine=NULL;}
  948. return;
  949. }
  950. DWORD AddUserToMetabaseACL2(CString csKeyPath, LPTSTR szUserToAdd, ACCESS_ALLOWED_ACE * MyACEInfo)
  951. {
  952. DWORD dwReturn = E_FAIL;
  953. BOOL bFound = FALSE;
  954. DWORD attr, uType, dType, cbLen;
  955. CMDKey cmdKey;
  956. BUFFER bufData;
  957. PBYTE pData;
  958. int BufSize;
  959. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserToMetabaseACL2():start. MyACEInfo->Mask=0x%x.\n"), MyACEInfo->Mask));
  960. PSECURITY_DESCRIPTOR pOldSd = NULL;
  961. PSECURITY_DESCRIPTOR pNewSd = NULL;
  962. cmdKey.OpenNode(csKeyPath);
  963. if ( (METADATA_HANDLE) cmdKey )
  964. {
  965. pData = (PBYTE)(bufData.QueryPtr());
  966. BufSize = bufData.QuerySize();
  967. cbLen = 0;
  968. bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
  969. if (!bFound)
  970. {
  971. if (cbLen > 0)
  972. {
  973. if ( ! (bufData.Resize(cbLen)) )
  974. {
  975. iisDebugOut((LOG_TYPE_ERROR, _T("AddUserToMetabaseACL2(): cmdKey.GetData. failed to resize to %d.!\n"), cbLen));
  976. }
  977. else
  978. {
  979. pData = (PBYTE)(bufData.QueryPtr());
  980. BufSize = cbLen;
  981. cbLen = 0;
  982. bFound = cmdKey.GetData(MD_ADMIN_ACL, &attr, &uType, &dType, &cbLen, pData, BufSize);
  983. }
  984. }
  985. }
  986. cmdKey.Close();
  987. if (bFound)
  988. {
  989. // We've got the acl
  990. // so now we want to add a user to it.
  991. pOldSd = (PSECURITY_DESCRIPTOR) pData;
  992. if (IsValidSecurityDescriptor(pOldSd))
  993. {
  994. DWORD AccessMask = (MD_ACR_READ |MD_ACR_WRITE |MD_ACR_RESTRICTED_WRITE |MD_ACR_UNSECURE_PROPS_READ |MD_ACR_ENUM_KEYS |MD_ACR_WRITE_DAC);
  995. PSID principalSID = NULL;
  996. BOOL bWellKnownSID = FALSE;
  997. // Get the SID for the certain string (administrator or everyone or whoever)
  998. dwReturn = GetPrincipalSID(szUserToAdd, &principalSID, &bWellKnownSID);
  999. if (dwReturn != ERROR_SUCCESS)
  1000. {
  1001. iisDebugOut((LOG_TYPE_WARN, _T("AddUserToMetabaseACL2:GetPrincipalSID(%s) FAILED. Error()= 0x%x\n"), szUserToAdd, dwReturn));
  1002. return dwReturn;
  1003. }
  1004. #ifndef _CHICAGO_
  1005. //#define ACCESS_ALLOWED_ACE_TYPE (0x0)
  1006. //#define ACCESS_DENIED_ACE_TYPE (0x1)
  1007. //#define SYSTEM_AUDIT_ACE_TYPE (0x2)
  1008. if (FALSE == AddUserAccessToSD(pOldSd,principalSID,MyACEInfo->Mask,MyACEInfo->Header.AceType,&pNewSd))
  1009. {
  1010. return dwReturn;
  1011. }
  1012. if (pNewSd)
  1013. {
  1014. // We have a new self relative SD
  1015. // lets write it to the metabase.
  1016. if (IsValidSecurityDescriptor(pNewSd))
  1017. {
  1018. dwReturn = WriteSDtoMetaBase(pNewSd, csKeyPath);
  1019. }
  1020. else
  1021. {
  1022. iisDebugOut((LOG_TYPE_ERROR, _T("AddUserToMetabaseACL2:IsValidSecurityDescriptor failed, bad sd\n")));
  1023. }
  1024. }
  1025. #endif
  1026. }
  1027. }
  1028. else
  1029. {
  1030. // there was no acl to be found.
  1031. }
  1032. }
  1033. if (pNewSd){GlobalFree(pNewSd);}
  1034. iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("AddUserToMetabaseACL2():End. Return=0x%x.\n"), dwReturn));
  1035. return dwReturn;
  1036. }
  1037. HRESULT WINAPI SysPrepAclRestore(void)
  1038. {
  1039. HRESULT hr = S_OK;
  1040. HINF InfHandle;
  1041. TCHAR szTempFileNameFull[_MAX_PATH];
  1042. CStringList strList;
  1043. CString csTheSection = SYSPREP_KNOWN_SECTION_NAME;
  1044. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("start\n")));
  1045. //MDDumpAdminACL(_T("/"));
  1046. // Loop thru our data file
  1047. // Create the tempfile
  1048. if (!GetWindowsDirectory(szTempFileNameFull,_MAX_PATH))
  1049. {
  1050. goto SysPrepAclRestore_Exit;
  1051. }
  1052. AddPath(szTempFileNameFull, SYSPREP_TEMPFILE_NAME);
  1053. // Get a handle to it.
  1054. InfHandle = SetupOpenInfFile(szTempFileNameFull, NULL, INF_STYLE_WIN4, NULL);
  1055. if(InfHandle == INVALID_HANDLE_VALUE)
  1056. {
  1057. goto SysPrepAclRestore_Exit;
  1058. }
  1059. if (ERROR_SUCCESS == FillStrListWithListOfSections(InfHandle, strList, csTheSection))
  1060. {
  1061. // loop thru the list returned back
  1062. if (strList.IsEmpty() == FALSE)
  1063. {
  1064. POSITION pos;
  1065. CString csEntry;
  1066. pos = strList.GetHeadPosition();
  1067. while (pos)
  1068. {
  1069. csEntry = strList.GetAt(pos);
  1070. // go get this section and read thru it's info
  1071. SysPrepRestoreAclSection(InfHandle, csEntry);
  1072. strList.GetNext(pos);
  1073. }
  1074. }
  1075. }
  1076. //MDDumpAdminACL(_T("/"));
  1077. if (GetFileAttributes(szTempFileNameFull) != 0xFFFFFFFF)
  1078. {
  1079. // if file already exists, then delete it
  1080. SetFileAttributes(szTempFileNameFull, FILE_ATTRIBUTE_NORMAL);
  1081. DeleteFile(szTempFileNameFull);
  1082. }
  1083. SysPrepAclRestore_Exit:
  1084. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("end,ret=0x%x\n"),hr));
  1085. return hr;
  1086. }
  1087. //
  1088. // DO NOT REMOVE THIS ENTRY POINT
  1089. //
  1090. // Entry point used by SysPrep in Whistler
  1091. //
  1092. // When sysprep runs, it is going to reset the machine sid
  1093. // so when that happens all the crypto stuff is broken.
  1094. // we had to implement this stuff so that before sysprep
  1095. // changes the sid (and thus breaking crypto) we can save our
  1096. // working metabase off somewhere (without crypto key encryption)
  1097. //
  1098. // At some point after sysprep has changed the machine sid
  1099. // it will call us into SysPrepRestore() and we wil restore
  1100. // our metabase using the new crypto keys on the machine.
  1101. //
  1102. HRESULT WINAPI SysPrepBackup(void)
  1103. {
  1104. HRESULT hr = S_OK;
  1105. WCHAR lpwszBackupLocation[_MAX_PATH];
  1106. DWORD dwMDVersion;
  1107. DWORD dwMDFlags;
  1108. WCHAR * pwszPassword = NULL;
  1109. BOOL bThingsAreGood = FALSE;
  1110. IMSAdminBase2 * pIMSAdminBase2 = NULL;
  1111. _tcscpy(g_MyLogFile.m_szLogPreLineInfo, _T("SysPrepBackup:"));
  1112. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1113. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("start\n")));
  1114. #ifndef _CHICAGO_
  1115. #ifdef SYSPREP_USE_SECRETS
  1116. #else
  1117. CRegKey regBigString(HKEY_LOCAL_MACHINE, REG_INETSTP, KEY_ALL_ACCESS);
  1118. #endif
  1119. #endif
  1120. // Check if the user who loaded this dll
  1121. // and is calling this entry point has the right priv to do this!
  1122. if (FALSE == RunningAsAdministrator())
  1123. {
  1124. hr = E_ABORT;
  1125. iisDebugOut((LOG_TYPE_ERROR, _T("No admin priv, aborting\n")));
  1126. goto SysPrepBackup_Exit2;
  1127. }
  1128. // if the service doesn't exist, then we don't have to do anyting
  1129. if (CheckifServiceExist(_T("IISADMIN")) != 0 )
  1130. {
  1131. iisDebugOut((LOG_TYPE_TRACE, _T("IIS not installed. do nothing.\n")));
  1132. hr = S_OK;
  1133. goto SysPrepBackup_Exit2;
  1134. }
  1135. // start the iisadmin service before calling backup.
  1136. // this is because if the backup function is called and the metabase is not
  1137. // running, then the metabase must startup while backup is trying to lock the
  1138. // metabase for backup. a race condition will happen and sometimes backup will
  1139. // fail since the metabase may take a while before starting up.
  1140. // this function will wait till the service is fully started before returning
  1141. InetStartService(_T("IISADMIN"));
  1142. #ifndef _CHICAGO_
  1143. pwszPassword = CreatePassword(SYSPREP_TEMP_PASSWORD_LENGTH);
  1144. if (pwszPassword)
  1145. {
  1146. #ifdef SYSPREP_USE_SECRETS
  1147. // calling set
  1148. if (ERROR_SUCCESS == SetSecret(SYSPREP_KNOWN_REGISTRY_KEY,pwszPassword))
  1149. {
  1150. bThingsAreGood = TRUE;
  1151. }
  1152. #else
  1153. if ((HKEY) regBigString)
  1154. {
  1155. regBigString.SetValue(SYSPREP_KNOWN_REGISTRY_KEY, pwszPassword);
  1156. bThingsAreGood = TRUE;
  1157. }
  1158. #endif
  1159. }
  1160. //iisDebugOut((LOG_TYPE_TRACE, _T("PASSWORD=%s,len=%d\n"),pwszPassword,wcslen(pwszPassword)));
  1161. #endif
  1162. // Tell the metabase where it should backup to.
  1163. wcscpy(lpwszBackupLocation,L"");
  1164. dwMDFlags = MD_BACKUP_OVERWRITE | MD_BACKUP_SAVE_FIRST | MD_BACKUP_FORCE_BACKUP;
  1165. dwMDVersion = MD_BACKUP_MAX_VERSION;
  1166. #ifndef _CHICAGO_
  1167. hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  1168. #else
  1169. hr = CoInitialize(NULL);
  1170. #endif
  1171. // no need to call uninit
  1172. if( FAILED (hr))
  1173. {
  1174. iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx failed\n")));
  1175. goto SysPrepBackup_Exit2;
  1176. }
  1177. hr = ::CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase2,(void **) & pIMSAdminBase2);
  1178. if(FAILED (hr))
  1179. {
  1180. iisDebugOut((LOG_TYPE_ERROR, _T("CoCreateInstance on IID_IMSAdminBase2 failed\n")));
  1181. goto SysPrepBackup_Exit;
  1182. }
  1183. // Call the metabase function
  1184. if (SUCCEEDED(hr))
  1185. {
  1186. iisDebugOut((LOG_TYPE_TRACE, _T("BackupWithPasswd calling...\n")));
  1187. if (bThingsAreGood)
  1188. {
  1189. //iisDebugOut((LOG_TYPE_TRACE, _T("using org\n")));
  1190. hr = pIMSAdminBase2->BackupWithPasswd(lpwszBackupLocation, dwMDVersion, dwMDFlags, pwszPassword);
  1191. }
  1192. else
  1193. {
  1194. //iisDebugOut((LOG_TYPE_TRACE, _T("using backup\n")));
  1195. hr = pIMSAdminBase2->BackupWithPasswd(lpwszBackupLocation, dwMDVersion, dwMDFlags, L"null");
  1196. }
  1197. if (pIMSAdminBase2)
  1198. {
  1199. pIMSAdminBase2->Release();
  1200. pIMSAdminBase2 = NULL;
  1201. }
  1202. if (SUCCEEDED(hr))
  1203. {
  1204. iisDebugOut((LOG_TYPE_TRACE, _T("BackupWithPasswd SUCCEEDED\n")));
  1205. }
  1206. else
  1207. {
  1208. iisDebugOut((LOG_TYPE_ERROR, _T("BackupWithPasswd failed\n")));
  1209. }
  1210. // Save all the acl info somewhere.
  1211. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T("SysPrepAclBackup"));
  1212. SysPrepAclBackup();
  1213. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1214. }
  1215. SysPrepBackup_Exit:
  1216. CoUninitialize();
  1217. SysPrepBackup_Exit2:
  1218. if (pwszPassword) {GlobalFree(pwszPassword);pwszPassword=NULL;}
  1219. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("end,ret=0x%x\n"),hr));
  1220. _tcscpy(g_MyLogFile.m_szLogPreLineInfo, _T(""));
  1221. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1222. return hr;
  1223. }
  1224. //
  1225. // DO NOT REMOVE THIS ENTRY POINT
  1226. //
  1227. // Entry point used by SysPrep in Whistler
  1228. //
  1229. // When sysprep runs, it is going to reset the machine sid
  1230. // so when that happens all the crypto stuff is broken.
  1231. // we had to implement this stuff so that before sysprep
  1232. // changes the sid (and thus breaking crypto) we can save our
  1233. // working metabase off somewhere (without crypto key encryption)
  1234. //
  1235. // At some point after sysprep has changed the machine sid
  1236. // it will call us into SysPrepRestore() and we wil restore
  1237. // our metabase using the new crypto keys on the machine.
  1238. //
  1239. HRESULT WINAPI SysPrepRestore(void)
  1240. {
  1241. HRESULT hr = S_OK;
  1242. WCHAR lpwszBackupLocation[_MAX_PATH];
  1243. TCHAR szTempDir[_MAX_PATH];
  1244. TCHAR szSystemDir[_MAX_PATH];
  1245. DWORD dwMDVersion;
  1246. DWORD dwMDFlags;
  1247. WCHAR * pwszPassword = NULL;
  1248. IMSAdminBase2 * pIMSAdminBase2 = NULL;
  1249. BOOL bThingsAreGood = FALSE;
  1250. _tcscpy(g_MyLogFile.m_szLogPreLineInfo, _T("SysPrepRestore:"));
  1251. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1252. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("start\n")));
  1253. #ifndef _CHICAGO_
  1254. #ifdef SYSPREP_USE_SECRETS
  1255. BUFFER * pbufSecret = NULL;
  1256. #else
  1257. CRegKey regBigString(HKEY_LOCAL_MACHINE, REG_INETSTP, KEY_ALL_ACCESS);
  1258. #endif
  1259. #endif
  1260. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("SysPrepRestore start\n")));
  1261. // Check if the user who loaded this dll
  1262. // and is calling this entry point has the right priv to do this!
  1263. if (FALSE == RunningAsAdministrator())
  1264. {
  1265. hr = E_ABORT;
  1266. iisDebugOut((LOG_TYPE_ERROR, _T("No admin priv, aborting\n")));
  1267. goto SysPrepRestore_Exit2;
  1268. }
  1269. // if the service doesn't exist, then we don't have to do anyting
  1270. if (CheckifServiceExist(_T("IISADMIN")) != 0 )
  1271. {
  1272. iisDebugOut((LOG_TYPE_TRACE, _T("SysPrepRestore IIS not installed. do nothing.\n")));
  1273. hr = S_OK;
  1274. goto SysPrepRestore_Exit2;
  1275. }
  1276. // make sure the iisadmin service is stopped.
  1277. StopServiceAndDependencies(_T("IISADMIN"), TRUE);
  1278. #ifndef _CHICAGO_
  1279. #ifdef SYSPREP_USE_SECRETS
  1280. pbufSecret = new BUFFER();
  1281. if (pbufSecret)
  1282. {
  1283. if (GetSecret(SYSPREP_KNOWN_REGISTRY_KEY, pbufSecret))
  1284. {
  1285. LPWSTR pwsz = NULL;
  1286. pwsz = (WCHAR *) pbufSecret->QueryPtr();
  1287. // alloc some space the same size
  1288. pwszPassword = (WCHAR *) GlobalAlloc (GPTR, pbufSecret->QuerySize());
  1289. _tcscpy(pwszPassword, pwsz);
  1290. delete(pbufSecret);
  1291. pbufSecret = NULL;
  1292. bThingsAreGood = TRUE;
  1293. }
  1294. }
  1295. #else
  1296. if ((HKEY) regBigString)
  1297. {
  1298. CString csTheData;
  1299. if ( regBigString.QueryValue(SYSPREP_KNOWN_REGISTRY_KEY, csTheData) == ERROR_SUCCESS )
  1300. {
  1301. pwszPassword = (WCHAR *) GlobalAlloc (GPTR, (csTheData.GetLength() + 1) * sizeof(TCHAR) );
  1302. if (pwszPassword)
  1303. {
  1304. wcscpy(pwszPassword,csTheData);
  1305. bThingsAreGood = TRUE;
  1306. }
  1307. }
  1308. }
  1309. #endif
  1310. #endif
  1311. //iisDebugOut((LOG_TYPE_TRACE, _T("PASSWORD=%s,len=%d\n"),pwszPassword,wcslen(pwszPassword)));
  1312. // Tell the metabase where it should backup to.
  1313. wcscpy(lpwszBackupLocation,L"");
  1314. dwMDFlags = 0;
  1315. dwMDVersion = MD_BACKUP_MAX_VERSION;
  1316. //
  1317. // IISAdmin won't start up if the metabase.xml,mbschema.xml files are corrupted (bad signature)
  1318. // so delete them before restoring....
  1319. if (0 == GetSystemDirectory(szSystemDir, _MAX_PATH))
  1320. {
  1321. goto SysPrepRestore_Exit2;
  1322. }
  1323. // iis6 files -- for whistler server skus
  1324. _stprintf(szTempDir, _T("%s\\inetsrv\\Metabase.xml"),szSystemDir);
  1325. InetDeleteFile(szTempDir);
  1326. _stprintf(szTempDir, _T("%s\\inetsrv\\MBSchema.xml"),szSystemDir);
  1327. InetDeleteFile(szTempDir);
  1328. // iis51 files -- for whistler pro sku
  1329. _stprintf(szTempDir, _T("%s\\inetsrv\\metabase.bin"),szSystemDir);
  1330. InetDeleteFile(szTempDir);
  1331. #ifndef _CHICAGO_
  1332. hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  1333. #else
  1334. hr = CoInitialize(NULL);
  1335. #endif
  1336. // no need to call uninit
  1337. if( FAILED (hr))
  1338. {
  1339. iisDebugOut((LOG_TYPE_ERROR, _T("CoInitializeEx failed\n")));
  1340. goto SysPrepRestore_Exit2;
  1341. }
  1342. hr = ::CoCreateInstance(CLSID_MSAdminBase,NULL,CLSCTX_ALL,IID_IMSAdminBase2,(void **) & pIMSAdminBase2);
  1343. if(FAILED (hr))
  1344. {
  1345. iisDebugOut((LOG_TYPE_ERROR, _T("CoCreateInstance on IID_IMSAdminBase2 failed\n")));
  1346. goto SysPrepRestore_Exit;
  1347. }
  1348. // Call the metabase function
  1349. if (SUCCEEDED(hr))
  1350. {
  1351. iisDebugOut((LOG_TYPE_TRACE, _T("RestoreWithPasswd calling...\n")));
  1352. if (bThingsAreGood)
  1353. {
  1354. //iisDebugOut((LOG_TYPE_TRACE, _T("using org\n")));
  1355. hr = pIMSAdminBase2->RestoreWithPasswd(lpwszBackupLocation, dwMDVersion, dwMDFlags, pwszPassword);
  1356. }
  1357. else
  1358. {
  1359. //iisDebugOut((LOG_TYPE_TRACE, _T("using backup\n")));
  1360. hr = pIMSAdminBase2->RestoreWithPasswd(lpwszBackupLocation, dwMDVersion, dwMDFlags, L"null");
  1361. }
  1362. if (pIMSAdminBase2)
  1363. {
  1364. pIMSAdminBase2->Release();
  1365. pIMSAdminBase2 = NULL;
  1366. }
  1367. if (SUCCEEDED(hr))
  1368. {
  1369. // Delete the backup file that we used!
  1370. //MD_DEFAULT_BACKUP_LOCATION + ".md" + MD_BACKUP_MAX_VERSION
  1371. _stprintf(szTempDir, _T("%s\\inetsrv\\MetaBack\\%s.md%d"),szSystemDir,MD_DEFAULT_BACKUP_LOCATION,MD_BACKUP_MAX_VERSION);
  1372. InetDeleteFile(szTempDir);
  1373. _stprintf(szTempDir, _T("%s\\inetsrv\\MetaBack\\%s.sc%d"),szSystemDir,MD_DEFAULT_BACKUP_LOCATION,MD_BACKUP_MAX_VERSION);
  1374. InetDeleteFile(szTempDir);
  1375. iisDebugOut((LOG_TYPE_TRACE, _T("RestoreWithPasswd SUCCEEDED\n")));
  1376. #ifndef _CHICAGO_
  1377. #ifdef SYSPREP_USE_SECRETS
  1378. // we need to delete the Secret that we used here!
  1379. SetSecret(SYSPREP_KNOWN_REGISTRY_KEY,L" ");
  1380. #else
  1381. if ((HKEY) regBigString)
  1382. {
  1383. regBigString.DeleteValue(SYSPREP_KNOWN_REGISTRY_KEY);
  1384. }
  1385. #endif
  1386. #endif
  1387. // Do extra stuff
  1388. // like Re-applying the acl for the iis_wpg group to the "/" node
  1389. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T("SysPrepAclRestore"));
  1390. SysPrepAclRestore();
  1391. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1392. // syncronize wam with new iwam user
  1393. //_tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T("SysPrepAclSyncIWam"));
  1394. //SysPrepAclSyncIWam();
  1395. //_tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1396. }
  1397. else
  1398. {
  1399. iisDebugOut((LOG_TYPE_ERROR, _T("RestoreWithPasswd failed\n")));
  1400. }
  1401. }
  1402. // Reset the passwords, and allow iisadmin to fix the com information
  1403. if (!ReSetIWamIUsrPasswds())
  1404. {
  1405. iisDebugOut((LOG_TYPE_WARN, _T("ReSetIWamIUsrPasswds was unable to reset IUSR and IWAM passwords\n")));
  1406. }
  1407. SysPrepRestore_Exit:
  1408. CoUninitialize();
  1409. SysPrepRestore_Exit2:
  1410. if (pwszPassword) {GlobalFree(pwszPassword);pwszPassword=NULL;}
  1411. iisDebugOut((LOG_TYPE_PROGRAM_FLOW, _T("end,ret=0x%x\n"),hr));
  1412. _tcscpy(g_MyLogFile.m_szLogPreLineInfo, _T(""));
  1413. _tcscpy(g_MyLogFile.m_szLogPreLineInfo2, _T(""));
  1414. return hr;
  1415. }