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.

2357 lines
57 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. vroots.cxx
  5. Abstract:
  6. This module contains the front end to the virtual roots interface
  7. Author:
  8. John Ludeman (johnl) 16-Mar-1995
  9. Project:
  10. Internet Servers Common Server DLL
  11. Revisions:
  12. --*/
  13. //
  14. // Include Headers
  15. //
  16. #include <tcpdllp.hxx>
  17. #include <tsunami.hxx>
  18. #include <iistypes.hxx>
  19. #include <inetinfo.h>
  20. #include <imd.h>
  21. #include <inetreg.h>
  22. #include <mb.hxx>
  23. #include <w3svc.h>
  24. #if 1 // DBCS
  25. #include <mbstring.h>
  26. #endif
  27. #include <initguid.h>
  28. #include <iwamreg.h>
  29. BOOL
  30. RetrieveRootPassword(
  31. PCHAR pszRoot,
  32. PCHAR pszPassword,
  33. WCHAR * pszSecret
  34. );
  35. DWORD
  36. GetFileSystemType(
  37. IN LPCSTR pszRealPath,
  38. OUT LPDWORD lpdwFileSystem
  39. );
  40. VOID
  41. LogRootAddFailure(
  42. IN PIIS_SERVER_INSTANCE psi,
  43. PCHAR pszRoot,
  44. PCHAR pszDirectory,
  45. DWORD err,
  46. IN PCHAR pszMetaPath,
  47. IN MB * pmb
  48. );
  49. BOOL
  50. TsAddVrootsWithScmUpdate(
  51. PVOID pvContext,
  52. MB * pmb,
  53. VIRTUAL_ROOT * pvr
  54. );
  55. BOOL
  56. TsAddVroots(
  57. PVOID pvContext,
  58. MB * pmb,
  59. VIRTUAL_ROOT * pvr
  60. );
  61. HANDLE
  62. VrootLogonUser(
  63. IN CHAR * pszUser,
  64. IN CHAR * pszPassword
  65. );
  66. BOOL
  67. CrackUserAndDomain(
  68. CHAR * pszDomainAndUser,
  69. CHAR * * ppszUser,
  70. CHAR * * ppszDomain
  71. );
  72. VOID
  73. ClearSentinelEntry(
  74. IN MB * pMB
  75. );
  76. VOID
  77. RemoveUnmarkedRoots(
  78. IN MB * pMB
  79. );
  80. BOOL
  81. ReadVrootConfig(
  82. LPVOID pvMB,
  83. LPSTR szVRPath,
  84. LPSTR szDirectory,
  85. DWORD cbDirectory,
  86. LPSTR szUser,
  87. DWORD cbUser,
  88. LPSTR szPassword,
  89. DWORD cbPassword,
  90. DWORD *pdwMask,
  91. BOOL *pfDoCache
  92. );
  93. DWORD
  94. hextointW(
  95. WCHAR * pch
  96. );
  97. DWORD
  98. hextointA(
  99. CHAR * pch
  100. );
  101. BOOL
  102. IIS_SERVER_INSTANCE::TsReadVirtualRoots(
  103. MD_CHANGE_OBJECT * pcoChangeList
  104. )
  105. /*++
  106. Description:
  107. NT Version
  108. This function is overloaded. The behavaior keys on pcoChangeList
  109. being NULL or not.
  110. If pcoChangeList is NULL (default value), it reads the metabase
  111. key pointed at by pmb and adds each root item.
  112. If pcoChangeList is not NULL then it only reads the necessary values.
  113. Arguments:
  114. pcoChangeList : pointer to metabase changes.
  115. Note:
  116. Failure to add a virtual root is not fatal. An appropriate event
  117. will be logged listing the error and root.
  118. Returns:
  119. TRUE on success and FALSE if any failure.
  120. --*/
  121. {
  122. BOOL fRet;
  123. MB mb( (IMDCOM*) m_Service->QueryMDObject() );
  124. //
  125. // Unfortunately rename doesn't give us the name of the old object.
  126. // So treat it as default processing
  127. //
  128. if ((NULL == pcoChangeList) ||
  129. (MD_CHANGE_TYPE_RENAME_OBJECT == pcoChangeList->dwMDChangeType))
  130. {
  131. //
  132. // Default processing. Remove & Re-Read all VRoots. Expensive.
  133. //
  134. if ( !mb.Open( QueryMDPath(),
  135. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  136. {
  137. return FALSE;
  138. }
  139. //
  140. // Remove all of the old roots for this server
  141. //
  142. fRet = QueryVrootTable()->RemoveVirtualRoots();
  143. if ( fRet )
  144. {
  145. QueryVrootTable()->LockExclusive();
  146. if (NULL == pcoChangeList)
  147. {
  148. fRet = TsEnumVirtualRoots( TsAddVrootsWithScmUpdate, this, &mb );
  149. }
  150. else
  151. {
  152. fRet = TsEnumVirtualRoots( TsAddVroots, this, &mb );
  153. }
  154. QueryVrootTable()->Unlock();
  155. }
  156. }
  157. else
  158. {
  159. VIRTUAL_ROOT vr;
  160. CHAR szUser[UNLEN+1];
  161. CHAR szPassword[PWLEN+1];
  162. CHAR szDirectory[MAX_PATH + UNLEN + 3];
  163. DWORD dwMask;
  164. BOOL fDoCache;
  165. if (MD_CHANGE_TYPE_DELETE_OBJECT == pcoChangeList->dwMDChangeType)
  166. {
  167. return QueryVrootTable()->RemoveVirtualRoot(
  168. (LPSTR)pcoChangeList->pszMDPath + QueryMDPathLen()
  169. + sizeof(IIS_MD_INSTANCE_ROOT)
  170. );
  171. }
  172. if ( !mb.Open( (LPCSTR)pcoChangeList->pszMDPath,
  173. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  174. {
  175. return FALSE;
  176. }
  177. if (!ReadVrootConfig( &mb,
  178. "",
  179. szDirectory,
  180. sizeof(szDirectory),
  181. szUser,
  182. sizeof(szUser),
  183. szPassword,
  184. sizeof(szPassword),
  185. &dwMask,
  186. &fDoCache
  187. ))
  188. {
  189. return FALSE;
  190. }
  191. vr.pszAlias = (LPSTR)pcoChangeList->pszMDPath + QueryMDPathLen()
  192. + sizeof(IIS_MD_INSTANCE_ROOT);
  193. vr.pszMetaPath = "";
  194. vr.pszPath = szDirectory;
  195. vr.dwAccessPerm = dwMask;
  196. vr.pszUserName = szUser;
  197. vr.pszPassword = szPassword;
  198. vr.fDoCache = fDoCache;
  199. if (pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_ADD_OBJECT)
  200. {
  201. fRet = TsAddVroots(this, &mb, &vr);
  202. }
  203. else
  204. {
  205. //
  206. // Remove the original entry & re-read
  207. //
  208. if (!QueryVrootTable()->RemoveVirtualRoot(vr.pszAlias))
  209. {
  210. DBGPRINTF((DBG_CONTEXT,"Error %x removing vroot %s. \n",
  211. GetLastError(), vr.pszMetaPath ));
  212. }
  213. fRet = TsAddVroots(this, &mb, &vr);
  214. }
  215. }
  216. return fRet;
  217. } // TsReadVirtualRoots
  218. BOOL
  219. TsAddVrootsWithScmUpdate(
  220. PVOID pvContext,
  221. MB * pmb,
  222. VIRTUAL_ROOT * pvr
  223. )
  224. {
  225. ((IIS_SERVER_INSTANCE *) pvContext)->m_Service->StartUpIndicateClientActivity();
  226. return TsAddVroots(pvContext,pmb,pvr);
  227. }
  228. BOOL
  229. TsAddVroots(
  230. PVOID pvContext,
  231. MB * pmb,
  232. VIRTUAL_ROOT * pvr
  233. )
  234. {
  235. DWORD err = NO_ERROR;
  236. DWORD dwFileSystem;
  237. BOOL fRet = FALSE;
  238. HANDLE hToken = NULL;
  239. //
  240. // Clear this virtual directory's error status
  241. //
  242. if ( !pmb->SetDword( pvr->pszMetaPath,
  243. MD_WIN32_ERROR,
  244. IIS_MD_UT_SERVER,
  245. NO_ERROR,
  246. METADATA_VOLATILE ))
  247. {
  248. DBGPRINTF((DBG_CONTEXT,"Error %x setting win32 status from %s. \n",
  249. GetLastError(), pvr->pszMetaPath ));
  250. return FALSE;
  251. }
  252. if ( (pvr->pszUserName[0] != '\0') &&
  253. (pvr->pszPath[0] == '\\') && (pvr->pszPath[1] == '\\') )
  254. {
  255. if ( g_fW3OnlyNoAuth )
  256. {
  257. hToken = NULL;
  258. }
  259. else
  260. {
  261. hToken = VrootLogonUser( pvr->pszUserName,
  262. pvr->pszPassword );
  263. if ( hToken == NULL)
  264. {
  265. DBGPRINTF(( DBG_CONTEXT,
  266. "Adding path %s err %d, user=%s, pwd=%d\n",
  267. pvr->pszPath, GetLastError(), pvr->pszUserName, pvr->pszPassword ));
  268. //
  269. // Log error
  270. //
  271. LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
  272. pvr->pszAlias,
  273. pvr->pszPath,
  274. GetLastError(),
  275. pvr->pszMetaPath,
  276. pmb );
  277. }
  278. // Impersonate as user for GetFileSystemType()
  279. if ( hToken != NULL && !ImpersonateLoggedOnUser(hToken))
  280. {
  281. err = GetLastError();
  282. }
  283. }
  284. }
  285. if ( err == NO_ERROR )
  286. {
  287. if (pvr->pszPath[0] != '\0')
  288. {
  289. err = GetFileSystemType( pvr->pszPath, &dwFileSystem);
  290. } else {
  291. dwFileSystem = FS_ERROR;
  292. }
  293. if ( err != NO_ERROR) {
  294. DBGPRINTF(( DBG_CONTEXT,
  295. " GetFileSystemType(%s) failed.Error = %u.\n",
  296. pvr->pszPath,
  297. err));
  298. LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
  299. pvr->pszAlias,
  300. pvr->pszPath,
  301. err,
  302. pvr->pszMetaPath,
  303. pmb );
  304. }
  305. }
  306. //
  307. // Don't add roots that are invalid
  308. //
  309. if ( err == NO_ERROR )
  310. {
  311. if ( !((IIS_SERVER_INSTANCE *) pvContext)->QueryVrootTable()->AddVirtualRoot(
  312. pvr->pszAlias,
  313. pvr->pszPath,
  314. pvr->dwAccessPerm,
  315. pvr->pszUserName,
  316. hToken,
  317. dwFileSystem,
  318. pvr->fDoCache ))
  319. {
  320. err = GetLastError();
  321. DBGPRINTF(( DBG_CONTEXT,
  322. " AddVirtualRoot() failed. Error = %u.\n", err));
  323. LogRootAddFailure( (IIS_SERVER_INSTANCE *) pvContext,
  324. pvr->pszAlias,
  325. pvr->pszPath,
  326. err,
  327. pvr->pszMetaPath,
  328. pmb );
  329. }
  330. }
  331. if ( hToken != NULL)
  332. {
  333. RevertToSelf();
  334. }
  335. if ( err == NO_ERROR )
  336. {
  337. fRet = TRUE;
  338. }
  339. return fRet;
  340. } // TsAddVroots
  341. BOOL
  342. IIS_SERVER_INSTANCE::TsEnumVirtualRoots(
  343. PFN_VR_ENUM pfnCallback,
  344. VOID * pvContext,
  345. MB * pmbWebSite
  346. )
  347. {
  348. return TsRecursiveEnumVirtualRoots(
  349. pfnCallback,
  350. pvContext,
  351. IIS_MD_INSTANCE_ROOT "/",
  352. m_dwLevelsToScan,
  353. (LPVOID)pmbWebSite,
  354. TRUE );
  355. }
  356. BOOL
  357. IIS_SERVER_INSTANCE::TsRecursiveEnumVirtualRoots(
  358. PFN_VR_ENUM pfnCallback,
  359. VOID * pvContext,
  360. LPSTR pszCurrentPath,
  361. DWORD dwLevelsToScan,
  362. LPVOID pvMB,
  363. BOOL fGetRoot
  364. )
  365. /*++
  366. Description:
  367. Enumerates all of the virtual directories defined for this server
  368. instance
  369. Arguments:
  370. pfnCallback - Enumeration callback to call for each virtual directory
  371. pvContext - Context pfnCallback receives
  372. pszCurrentPath - path where to start scanning for VRoots
  373. dwLevelsToScan - # of levels to scan recursively for vroots
  374. pvMB - ptr to MB to access metabase. Is LPVOID to avoid having to include
  375. mb.hxx before any ref to iistypes.hxx
  376. fGetRoot - TRUE if pszCurrentPath is to be considered as vroot to process
  377. Returns:
  378. TRUE on success and FALSE if any failure.
  379. --*/
  380. {
  381. DWORD err;
  382. MB* pMB = (MB*)pvMB;
  383. DWORD cb;
  384. CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
  385. CHAR tmpBuf[sizeof(nameBuf)];
  386. DWORD cbCurrentPath;
  387. DWORD i = 0;
  388. VIRTUAL_ROOT vr;
  389. CHAR szUser[UNLEN+1];
  390. CHAR szPassword[PWLEN+1];
  391. CHAR szDirectory[MAX_PATH + UNLEN + 3];
  392. DWORD dwMask;
  393. BOOL fDoCache;
  394. //
  395. // Enumerate all of the listed items in the metabase
  396. // and add them
  397. //
  398. cbCurrentPath = strlen( pszCurrentPath );
  399. CopyMemory( nameBuf, pszCurrentPath, cbCurrentPath + 1);
  400. while ( TRUE ) {
  401. METADATA_RECORD mdRecord;
  402. DWORD dwFileSystem = FS_ERROR;
  403. err = NO_ERROR;
  404. if ( fGetRoot ) {
  405. fGetRoot = FALSE;
  406. } else {
  407. if ( !pMB->EnumObjects( pszCurrentPath,
  408. nameBuf + cbCurrentPath,
  409. i++ ))
  410. {
  411. break;
  412. }
  413. if ( dwLevelsToScan > 1 )
  414. {
  415. cb = strlen( nameBuf );
  416. nameBuf[ cb ] = '/';
  417. nameBuf[ cb + 1 ] = '\0';
  418. if ( !TsRecursiveEnumVirtualRoots(
  419. pfnCallback,
  420. pvContext,
  421. nameBuf,
  422. dwLevelsToScan - 1,
  423. pMB,
  424. FALSE ) )
  425. {
  426. return FALSE;
  427. }
  428. nameBuf[ cb ] = '\0';
  429. }
  430. }
  431. if (!ReadVrootConfig( pvMB,
  432. nameBuf,
  433. szDirectory,
  434. sizeof(szDirectory),
  435. szUser,
  436. sizeof(szUser),
  437. szPassword,
  438. sizeof(szPassword),
  439. &dwMask,
  440. &fDoCache
  441. ))
  442. {
  443. continue;
  444. }
  445. //
  446. // Now set things up for the callback
  447. //
  448. DBG_ASSERT( !_strnicmp( nameBuf, IIS_MD_INSTANCE_ROOT, sizeof(IIS_MD_INSTANCE_ROOT) - 1));
  449. //
  450. // Add can modify the root - don't modify the working vroot path
  451. //
  452. strcpy( tmpBuf, nameBuf );
  453. vr.pszAlias = tmpBuf + sizeof(IIS_MD_INSTANCE_ROOT) - 1;
  454. vr.pszMetaPath = tmpBuf;
  455. vr.pszPath = szDirectory;
  456. vr.dwAccessPerm = dwMask;
  457. vr.pszUserName = szUser;
  458. vr.pszPassword = szPassword;
  459. vr.fDoCache = fDoCache;
  460. if ( !pfnCallback( pvContext, pMB, &vr ))
  461. {
  462. //
  463. // !!! so what do we do here?
  464. //
  465. DBGPRINTF((DBG_CONTEXT,"EnumCallback returns FALSE\n"));
  466. }
  467. } // while
  468. return TRUE;
  469. } // Enum
  470. VOID
  471. LogRootAddFailure(
  472. IN PIIS_SERVER_INSTANCE psi,
  473. IN PCHAR pszRoot,
  474. IN PCHAR pszDirectory,
  475. IN DWORD err,
  476. IN PCHAR pszMetaPath,
  477. IN MB * pmb
  478. )
  479. {
  480. const CHAR * apsz[3];
  481. STR strError;
  482. psi->LoadStr( strError, err, FALSE ); // loads ANSI message. Convert to UNICODE
  483. apsz[0] = pszRoot;
  484. apsz[1] = pszDirectory;
  485. apsz[2] = strError.QueryStrA();
  486. psi->m_Service->LogEvent( INET_SVC_ADD_VIRTUAL_ROOT_FAILED,
  487. 3,
  488. apsz,
  489. err );
  490. //
  491. // Indicate the error on this virtual directory
  492. //
  493. if ( !pmb->SetDword( pszMetaPath,
  494. MD_WIN32_ERROR,
  495. IIS_MD_UT_SERVER,
  496. err,
  497. METADATA_VOLATILE ))
  498. {
  499. DBGPRINTF(( DBG_CONTEXT,
  500. "LogRootAddFailure: Unable to set win32 status\n" ));
  501. }
  502. } // LogRootAddFailure
  503. BOOL
  504. RetrieveRootPassword(
  505. PCHAR pszRoot,
  506. PCHAR pszPassword,
  507. PWCHAR pszSecret
  508. )
  509. /*++
  510. Description:
  511. This function retrieves the password for the specified root & address
  512. Arguments:
  513. pszRoot - Name of root + address in the form "/root,<address>".
  514. pszPassword - Receives password, must be at least PWLEN+1 characters
  515. pszSecret - Virtual Root password secret name
  516. Returns:
  517. TRUE on success and FALSE if any failure.
  518. --*/
  519. {
  520. BUFFER bufSecret;
  521. WCHAR * psz;
  522. WCHAR * pszTerm;
  523. WCHAR * pszNextLine;
  524. WCHAR wsRoot[MAX_PATH+1];
  525. DWORD cch;
  526. if ( !TsGetSecretW( pszSecret,
  527. &bufSecret ))
  528. {
  529. return FALSE;
  530. }
  531. //
  532. // Convert root to WCHAR
  533. //
  534. cch = MultiByteToWideChar( CP_ACP,
  535. MB_PRECOMPOSED,
  536. pszRoot,
  537. -1,
  538. wsRoot,
  539. MAX_PATH );
  540. wsRoot[cch] = L'\0';
  541. if ( cch == 0 ) {
  542. return FALSE;
  543. }
  544. psz = (WCHAR *) bufSecret.QueryPtr();
  545. //
  546. // Scan the list of roots looking for a match. The list looks like:
  547. //
  548. // <root>,<address>=<password>\0
  549. // <root>,<address>=<password>\0
  550. // \0
  551. //
  552. while ( *psz )
  553. {
  554. PWCHAR pszComma;
  555. pszNextLine = psz + wcslen(psz) + 1;
  556. pszTerm = wcschr( psz, L'=' );
  557. if ( !pszTerm )
  558. goto NextLine;
  559. *pszTerm = L'\0';
  560. //
  561. // remove the ,
  562. //
  563. pszComma = wcschr( psz, L',' );
  564. if ( pszComma != NULL ) {
  565. *pszComma = '\0';
  566. }
  567. if ( !_wcsicmp( wsRoot, psz ) )
  568. {
  569. //
  570. // We found a match, copy the password
  571. //
  572. (VOID) ConvertUnicodeToAnsi(
  573. pszTerm + 1,
  574. pszPassword,
  575. PWLEN + sizeof(CHAR));
  576. return TRUE;
  577. }
  578. NextLine:
  579. psz = pszNextLine;
  580. }
  581. //
  582. // If the matching root wasn't found, default to the empty password
  583. //
  584. *pszPassword = '\0';
  585. return TRUE;
  586. } // RetrieveRootPassword
  587. BOOL
  588. IIS_SERVER_INSTANCE::TsSetVirtualRoots(
  589. IN LPINETA_CONFIG_INFO pConfig
  590. )
  591. /*++
  592. Description:
  593. Writes the virtual roots specified in the config structure to the
  594. registry
  595. NOTE: This is basically legacy code for the IIS 3.0 RPC interface.
  596. Arguments:
  597. pConfig - new list of virtual
  598. Returns:
  599. TRUE on success and FALSE if any failure.
  600. --*/
  601. {
  602. DWORD err;
  603. DWORD dwDummy;
  604. LPINET_INFO_VIRTUAL_ROOT_LIST pRootsList;
  605. DWORD cch;
  606. DWORD i;
  607. DWORD dwMask;
  608. DWORD sentinelValue = 7777777;
  609. IWamAdmin* pIWamAdmin = NULL;
  610. MB mb( (IMDCOM*) m_Service->QueryMDObject() );
  611. HRESULT hr = NOERROR;
  612. STR strTmp;
  613. //
  614. // Do the metabase
  615. //
  616. IF_DEBUG(METABASE) {
  617. DBGPRINTF((DBG_CONTEXT,"Setting VR data on %s\n",
  618. QueryMDPath()));
  619. }
  620. if ( !mb.Open( QueryMDPath(),
  621. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  622. {
  623. IF_DEBUG(METABASE) {
  624. DBGPRINTF((DBG_CONTEXT,"Open MD instance root %s returns %d\n",
  625. QueryMDPath(), GetLastError() ));
  626. }
  627. return FALSE;
  628. }
  629. //
  630. // We need to create an application for each new virtual root set via
  631. // the IIS 3.0 RPC interface for ASP compatability
  632. //
  633. hr = CoCreateInstance(CLSID_WamAdmin,
  634. NULL,
  635. CLSCTX_SERVER,
  636. IID_IWamAdmin,
  637. (void **)&pIWamAdmin);
  638. if ( FAILED(hr) )
  639. {
  640. DBGPRINTF(( DBG_CONTEXT,
  641. "Failed to create WamAdmin interface, error %08lx\n",
  642. hr ));
  643. SetLastError( hr );
  644. return FALSE;
  645. }
  646. //
  647. // See if we need to delete any VRs
  648. //
  649. pRootsList = pConfig->VirtualRoots;
  650. if ( (pRootsList == NULL) || (pRootsList->cEntries == 0) ) {
  651. //
  652. // NO VRs. Delete the entire VR tree
  653. //
  654. if ( !mb.DeleteObject( IIS_MD_INSTANCE_ROOT ) )
  655. {
  656. IF_DEBUG(METABASE) {
  657. DBGPRINTF((DBG_CONTEXT,
  658. "Deleting VR root returns %d\n",GetLastError()));
  659. }
  660. }
  661. IF_DEBUG(METABASE) {
  662. DBGPRINTF((DBG_CONTEXT,"Empty list set on %s\n", QueryMDPath()));
  663. }
  664. goto exit;
  665. } else {
  666. //
  667. // Remove our secret value
  668. //
  669. ClearSentinelEntry( &mb );
  670. }
  671. for ( i = 0; i < pRootsList->cEntries; i++ ) {
  672. CHAR tmpRoot[MAX_PATH+1];
  673. CHAR tmpBuffer[MAX_PATH+1];
  674. BOOL fCreateApp = FALSE;
  675. DWORD rootLen;
  676. //
  677. // strings to ANSI
  678. //
  679. #define VROOT_ROOT IIS_MD_INSTANCE_ROOT
  680. #define CCH_VROOT_ROOT (sizeof(VROOT_ROOT) - 1)
  681. strcpy( tmpRoot, VROOT_ROOT );
  682. (VOID) ConvertUnicodeToAnsi(
  683. pRootsList->aVirtRootEntry[i].pszRoot,
  684. &tmpRoot[CCH_VROOT_ROOT],
  685. MAX_PATH);
  686. IF_DEBUG(METABASE) {
  687. DBGPRINTF((DBG_CONTEXT,"Setting data for root %s\n",tmpRoot));
  688. }
  689. rootLen = strlen(tmpRoot);
  690. //
  691. // Create the root
  692. //
  693. if ( !mb.AddObject( tmpRoot ) &&
  694. (GetLastError() != ERROR_ALREADY_EXISTS) )
  695. {
  696. DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
  697. tmpRoot, GetLastError() ));
  698. goto exit;
  699. }
  700. //
  701. // Set sentinel entry
  702. //
  703. if ( !mb.SetDword( tmpRoot,
  704. MD_VR_UPDATE,
  705. IIS_MD_UT_FILE,
  706. sentinelValue,
  707. 0 ))
  708. {
  709. DBGPRINTF((DBG_CONTEXT,
  710. "Error %d setting sentinel value %x for %s\n",
  711. GetLastError(), sentinelValue, tmpRoot));
  712. goto exit;
  713. }
  714. //
  715. // Set Path
  716. //
  717. (VOID) ConvertUnicodeToAnsi(
  718. pRootsList->aVirtRootEntry[i].pszDirectory,
  719. tmpBuffer,
  720. MAX_PATH+1);
  721. IF_DEBUG(METABASE) {
  722. DBGPRINTF((DBG_CONTEXT,"Directory path is %s\n",tmpBuffer));
  723. }
  724. //
  725. // Check to see if the path property already exists - if it does
  726. // then we won't create the application - only new virtual directories
  727. // get an application created for them
  728. //
  729. if ( !mb.GetStr( tmpRoot,
  730. MD_VR_PATH,
  731. IIS_MD_UT_FILE,
  732. &strTmp,
  733. METADATA_NO_ATTRIBUTES ))
  734. {
  735. fCreateApp = TRUE;
  736. }
  737. if ( !mb.SetString( tmpRoot,
  738. MD_VR_PATH,
  739. IIS_MD_UT_FILE,
  740. tmpBuffer ))
  741. {
  742. DBGPRINTF((DBG_CONTEXT,"Error %d setting path[%s] for %s\n",
  743. GetLastError(), tmpBuffer, tmpRoot));
  744. }
  745. if ( !mb.SetString( tmpRoot,
  746. MD_KEY_TYPE,
  747. IIS_MD_UT_SERVER,
  748. "IIsWebVirtualDir" ))
  749. {
  750. DBGPRINTF((DBG_CONTEXT,"Error %d setting ADSI type for %s\n",
  751. GetLastError(), tmpRoot));
  752. }
  753. //
  754. // Set Username
  755. //
  756. (VOID) ConvertUnicodeToAnsi(
  757. pRootsList->aVirtRootEntry[i].pszAccountName,
  758. tmpBuffer,
  759. MAX_PATH+1);
  760. if ( !mb.SetString( tmpRoot,
  761. MD_VR_USERNAME,
  762. IIS_MD_UT_FILE,
  763. tmpBuffer ))
  764. {
  765. DBGPRINTF((DBG_CONTEXT,"Error %d setting username for %s\n",
  766. GetLastError(), tmpRoot));
  767. }
  768. //
  769. // Set Mask
  770. //
  771. if ( !mb.SetDword( tmpRoot,
  772. MD_ACCESS_PERM,
  773. IIS_MD_UT_FILE,
  774. pRootsList->aVirtRootEntry[i].dwMask ))
  775. {
  776. DBGPRINTF((DBG_CONTEXT,"Error %d setting mask for %s\n",
  777. GetLastError(), tmpRoot));
  778. }
  779. if ( fCreateApp )
  780. {
  781. WCHAR wchFullPath[MAX_PATH];
  782. strcpy( tmpRoot, QueryMDPath() );
  783. strcat( tmpRoot, "/" VROOT_ROOT );
  784. if ( MultiByteToWideChar( CP_ACP,
  785. MB_PRECOMPOSED,
  786. tmpRoot,
  787. -1,
  788. wchFullPath,
  789. sizeof( wchFullPath ) / sizeof(WCHAR) ))
  790. {
  791. wcscat( wchFullPath, pRootsList->aVirtRootEntry[i].pszRoot );
  792. DBGPRINTF(( DBG_CONTEXT,
  793. "Creating application at %S\n",
  794. wchFullPath ));
  795. //
  796. // We need to close our metabase handle so WAM can create
  797. // the in process application
  798. //
  799. DBG_REQUIRE( mb.Close() );
  800. hr = pIWamAdmin->AppCreate( wchFullPath, TRUE);
  801. if ( FAILED( hr ))
  802. {
  803. DBGPRINTF(( DBG_CONTEXT,
  804. "Failed to create application, error %08lx\n",
  805. hr ));
  806. }
  807. //
  808. // Reopen the metabase for the next vroot
  809. //
  810. if ( !mb.Open( QueryMDPath(),
  811. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  812. {
  813. IF_DEBUG(METABASE) {
  814. DBGPRINTF((DBG_CONTEXT,"Open MD instance root %s returns %d\n",
  815. QueryMDPath(), GetLastError() ));
  816. }
  817. goto exit;
  818. }
  819. }
  820. }
  821. }
  822. //
  823. // Delete entries that do not have the sentinel entry
  824. //
  825. RemoveUnmarkedRoots( &mb );
  826. exit:
  827. //
  828. // If this is the downlevel instance, mirror it to the registry
  829. //
  830. if ( IsDownLevelInstance() ) {
  831. TsMirrorVirtualRoots( pConfig );
  832. }
  833. if ( pIWamAdmin ) {
  834. pIWamAdmin->Release();
  835. }
  836. return TRUE;
  837. } // IIS_SERVER_INSTANCE::TsSetVirtualRoots
  838. DWORD
  839. GetFileSystemType(
  840. IN LPCSTR pszRealPath,
  841. OUT LPDWORD lpdwFileSystem
  842. )
  843. /*++
  844. Gets file system specific information for a given path.
  845. It uses GetVolumeInfomration() to query the file system type
  846. and file system flags.
  847. On success the flags and file system type are returned in
  848. passed in pointers.
  849. Arguments:
  850. pszRealPath pointer to buffer containing path for which
  851. we are inquiring the file system details.
  852. lpdwFileSystem
  853. pointer to buffer to fill in the type of file system.
  854. Returns:
  855. NO_ERROR on success and Win32 error code if any error.
  856. --*/
  857. {
  858. # define MAX_FILE_SYSTEM_NAME_SIZE ( MAX_PATH)
  859. CHAR rgchBuf[MAX_FILE_SYSTEM_NAME_SIZE];
  860. CHAR rgchRoot[MAX_FILE_SYSTEM_NAME_SIZE];
  861. int i;
  862. DWORD dwReturn = ERROR_PATH_NOT_FOUND;
  863. DWORD len;
  864. if ( (pszRealPath == NULL) || (lpdwFileSystem == NULL)) {
  865. return ( ERROR_INVALID_PARAMETER);
  866. }
  867. ZeroMemory( rgchRoot, sizeof(rgchRoot) );
  868. *lpdwFileSystem = FS_ERROR;
  869. //
  870. // Copy just the root directory to rgchRoot for querying
  871. //
  872. IF_DEBUG( DLL_VIRTUAL_ROOTS) {
  873. DBGPRINTF( ( DBG_CONTEXT, " GetFileSystemType(%s).\n", pszRealPath));
  874. }
  875. if ( (pszRealPath[0] == '\\') &&
  876. (pszRealPath[1] == '\\')) {
  877. PCHAR pszEnd;
  878. //
  879. // this is an UNC name. Extract just the first two components
  880. //
  881. //
  882. pszEnd = strchr( pszRealPath+2, '\\');
  883. if ( pszEnd == NULL) {
  884. // just the server name present
  885. return ( ERROR_INVALID_PARAMETER);
  886. }
  887. #if 1 // DBCS enabling for share name
  888. pszEnd = (PCHAR)_mbschr( (PUCHAR)pszEnd+1, '\\');
  889. #else
  890. pszEnd = strchr( pszEnd+1, '\\');
  891. #endif
  892. len = ( ( pszEnd == NULL) ? strlen(pszRealPath)
  893. : (DIFF(pszEnd - pszRealPath) + 1) );
  894. //
  895. // Copy till the end of UNC Name only (exclude all other path info)
  896. //
  897. if ( len < (MAX_FILE_SYSTEM_NAME_SIZE - 1) ) {
  898. CopyMemory( rgchRoot, pszRealPath, len);
  899. rgchRoot[len] = '\0';
  900. } else {
  901. return ( ERROR_INVALID_NAME);
  902. }
  903. #if 1 // DBCS enabling for share name
  904. if ( *CharPrev( rgchRoot, rgchRoot + len ) != '\\' ) {
  905. #else
  906. if ( rgchRoot[len - 1] != '\\' ) {
  907. #endif
  908. if ( len < MAX_FILE_SYSTEM_NAME_SIZE - 2 ) {
  909. rgchRoot[len] = '\\';
  910. rgchRoot[len+1] = '\0';
  911. } else {
  912. return (ERROR_INVALID_NAME);
  913. }
  914. }
  915. } else {
  916. //
  917. // This is non UNC name.
  918. // Copy just the root directory to rgchRoot for querying
  919. //
  920. for( i = 0; i < 9 && pszRealPath[i] != '\0'; i++) {
  921. if ( (rgchRoot[i] = pszRealPath[i]) == ':') {
  922. break;
  923. }
  924. } // for
  925. if ( rgchRoot[i] != ':') {
  926. //
  927. // we could not find the root directory.
  928. // return with error value
  929. //
  930. return ( ERROR_INVALID_PARAMETER);
  931. }
  932. rgchRoot[i+1] = '\\'; // terminate the drive spec with a slash
  933. rgchRoot[i+2] = '\0'; // terminate the drive spec with null char
  934. } // else
  935. IF_DEBUG( DLL_VIRTUAL_ROOTS) {
  936. DBGPRINTF( ( DBG_CONTEXT, " GetVolumeInformation(%s).\n",
  937. rgchRoot));
  938. }
  939. //
  940. // The rgchRoot should end with a "\" (slash)
  941. // otherwise, the call will fail.
  942. //
  943. if ( GetVolumeInformation( rgchRoot, // lpRootPathName
  944. NULL, // lpVolumeNameBuffer
  945. 0, // len of volume name buffer
  946. NULL, // lpdwVolSerialNumber
  947. NULL, // lpdwMaxComponentLength
  948. NULL, // lpdwSystemFlags
  949. rgchBuf, // lpFileSystemNameBuff
  950. sizeof(rgchBuf)
  951. ) ) {
  952. dwReturn = NO_ERROR;
  953. if ( strcmp( rgchBuf, "FAT") == 0) {
  954. *lpdwFileSystem = FS_FAT;
  955. } else if ( strcmp( rgchBuf, "NTFS") == 0) {
  956. *lpdwFileSystem = FS_NTFS;
  957. } else if ( strcmp( rgchBuf, "HPFS") == 0) {
  958. *lpdwFileSystem = FS_HPFS;
  959. } else if ( strcmp( rgchBuf, "CDFS") == 0) {
  960. *lpdwFileSystem = FS_CDFS;
  961. } else if ( strcmp( rgchBuf, "OFS") == 0) {
  962. *lpdwFileSystem = FS_OFS;
  963. } else {
  964. *lpdwFileSystem = FS_FAT;
  965. }
  966. } else {
  967. dwReturn = GetLastError();
  968. IF_DEBUG( DLL_VIRTUAL_ROOTS) {
  969. DBGPRINTF( ( DBG_CONTEXT,
  970. " GetVolumeInformation( %s) failed with error %d\n",
  971. rgchRoot, dwReturn));
  972. }
  973. }
  974. return ( dwReturn);
  975. } // GetFileSystemType()
  976. HANDLE
  977. VrootLogonUser(
  978. IN CHAR * pszUser,
  979. IN CHAR * pszPassword
  980. )
  981. /*++
  982. This function uses the given parameters and logs on to generate
  983. a user handle for the account.
  984. Arguments:
  985. pszUser - pointer to string containing the user name.
  986. pszPassword - pointer to string containing the password.
  987. Returns:
  988. Handle for the logged on user on success.
  989. Returns NULL for errors.
  990. History:
  991. MuraliK 18-Jan-1996 Created.
  992. --*/
  993. {
  994. CHAR szDomainAndUser[IIS_DNLEN+UNLEN+2];
  995. CHAR * pszUserOnly;
  996. CHAR * pszDomain;
  997. HANDLE hToken = NULL;
  998. BOOL fReturn;
  999. //
  1000. // Validate parameters & state.
  1001. //
  1002. DBG_ASSERT( pszUser != NULL && *pszUser != '\0');
  1003. DBG_ASSERT( strlen(pszUser) < sizeof(szDomainAndUser) );
  1004. DBG_ASSERT( pszPassword != NULL);
  1005. DBG_ASSERT( strlen(pszPassword) <= PWLEN );
  1006. //
  1007. // Save a copy of the domain\user so we can squirrel around
  1008. // with it a bit.
  1009. //
  1010. strcpy( szDomainAndUser, pszUser );
  1011. //
  1012. // Crack the name into domain/user components.
  1013. // Then try and logon as the specified user.
  1014. //
  1015. fReturn = ( CrackUserAndDomain( szDomainAndUser,
  1016. &pszUserOnly,
  1017. &pszDomain ) &&
  1018. LogonUserA(pszUserOnly,
  1019. pszDomain,
  1020. pszPassword,
  1021. LOGON32_LOGON_NETWORK_CLEARTEXT, //LOGON32_LOGON_NETWORK,
  1022. LOGON32_PROVIDER_DEFAULT,
  1023. &hToken )
  1024. );
  1025. if ( !fReturn) {
  1026. //
  1027. // Logon user failed.
  1028. //
  1029. IF_DEBUG( DLL_SECURITY) {
  1030. DBGPRINTF(( DBG_CONTEXT,
  1031. " CrachUserAndDomain/LogonUser (%s) failed Error=%d\n",
  1032. pszUser, GetLastError()));
  1033. }
  1034. hToken = NULL;
  1035. } else {
  1036. HANDLE hImpersonation = NULL;
  1037. // we need to obtain the impersonation token, the primary token cannot
  1038. // be used for a lot of purposes :(
  1039. if (!pfnDuplicateTokenEx( hToken, // hSourceToken
  1040. TOKEN_ALL_ACCESS,
  1041. NULL,
  1042. SecurityImpersonation, // Obtain impersonation
  1043. TokenImpersonation,
  1044. &hImpersonation) // hDestinationToken
  1045. ) {
  1046. DBGPRINTF(( DBG_CONTEXT,
  1047. "Creating ImpersonationToken failed. Error = %d\n",
  1048. GetLastError()
  1049. ));
  1050. // cleanup and exit.
  1051. hImpersonation = NULL;
  1052. // Fall through for cleanup
  1053. }
  1054. //
  1055. // close original token. If Duplicate was successful,
  1056. // we should have ref in the hImpersonation.
  1057. // Send the impersonation token to the client.
  1058. //
  1059. CloseHandle( hToken);
  1060. hToken = hImpersonation;
  1061. }
  1062. //
  1063. // Success!
  1064. //
  1065. return hToken;
  1066. } // VrootLogonUser()
  1067. DWORD
  1068. hextointW(
  1069. WCHAR * pch
  1070. )
  1071. {
  1072. WCHAR * pchStart;
  1073. DWORD sum = 0;
  1074. DWORD mult = 1;
  1075. while ( *pch == L' ' )
  1076. pch++;
  1077. pchStart = pch;
  1078. while ( iswxdigit( *pch ) )
  1079. pch++;
  1080. while ( --pch >= pchStart )
  1081. {
  1082. sum += mult * ( *pch >= L'A' ? *pch + 10 - L'A' :
  1083. *pch - L'0' );
  1084. mult *= 16;
  1085. }
  1086. return sum;
  1087. }
  1088. DWORD
  1089. hextointA(
  1090. CHAR * pch
  1091. )
  1092. {
  1093. CHAR * pchStart;
  1094. DWORD sum = 0;
  1095. DWORD mult = 1;
  1096. while ( *pch == ' ' )
  1097. pch++;
  1098. pchStart = pch;
  1099. while ( isxdigit( (UCHAR)(*pch) ) )
  1100. pch++;
  1101. while ( --pch >= pchStart )
  1102. {
  1103. sum += mult * ( *pch >= 'A' ? *pch + 10 - 'A' :
  1104. *pch - '0' );
  1105. mult *= 16;
  1106. }
  1107. return sum;
  1108. } // hextointA
  1109. BOOL
  1110. IIS_SERVER_INSTANCE::MoveVrootFromRegToMD(
  1111. VOID
  1112. )
  1113. {
  1114. DBGPRINTF((DBG_CONTEXT,"MoveVrootFromRegToMD called!!!\n"));
  1115. return(TRUE);
  1116. } // IIS_SERVER_INSTANCE::MoveVrootFromRegToMD
  1117. BOOL
  1118. TsCopyVrootToRegistry(
  1119. PVOID pvContext,
  1120. MB * pmb,
  1121. VIRTUAL_ROOT * pvr
  1122. )
  1123. {
  1124. DWORD cch;
  1125. DWORD err;
  1126. HKEY hkey = (HKEY)pvContext;
  1127. CHAR szValue[ MAX_PATH + UNLEN + 2 ];
  1128. IF_DEBUG(METABASE) {
  1129. DBGPRINTF((DBG_CONTEXT,"CopyVrootToReg: Adding %s to registry\n",
  1130. pvr->pszAlias));
  1131. }
  1132. cch = wsprintfA( szValue,
  1133. "%s,%s,%X",
  1134. pvr->pszPath,
  1135. pvr->pszUserName,
  1136. pvr->dwAccessPerm );
  1137. DBG_ASSERT( cch < sizeof( szValue ) );
  1138. err = WriteRegistryStringA(hkey,
  1139. pvr->pszAlias,
  1140. szValue,
  1141. strlen(szValue),
  1142. REG_SZ);
  1143. DBG_ASSERT(err == NO_ERROR);
  1144. return(TRUE);
  1145. } // TsCopyVrootToRegistry
  1146. BOOL
  1147. IIS_SERVER_INSTANCE::MoveMDVroots2Registry(
  1148. VOID
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. Moves MD VR entries to the registry if registry VR key
  1153. does not exist at startup.
  1154. Arguments:
  1155. None.
  1156. Return Value:
  1157. None.
  1158. --*/
  1159. {
  1160. HKEY hkey = NULL;
  1161. HKEY hkeyRoots = NULL;
  1162. DWORD dwDisp;
  1163. DWORD err;
  1164. BOOL fMigrated = FALSE;
  1165. MB mb( (IMDCOM*) m_Service->QueryMDObject() );
  1166. DBG_ASSERT(IsDownLevelInstance());
  1167. IF_DEBUG(METABASE) {
  1168. DBGPRINTF((DBG_CONTEXT,"Entering MoveMDToRegAtStartup.\n"));
  1169. }
  1170. //
  1171. // see if the key exists
  1172. //
  1173. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1174. m_Service->QueryRegParamKey( ),
  1175. 0,
  1176. KEY_READ|KEY_WRITE,
  1177. &hkey );
  1178. if ( err != NO_ERROR ) {
  1179. DBGPRINTF(( DBG_CONTEXT,
  1180. "RegOpenKeyEx %s returned error %d\n",
  1181. m_Service->QueryRegParamKey(), err ));
  1182. goto exit;
  1183. }
  1184. //
  1185. // VR key?
  1186. //
  1187. err = RegCreateKeyEx( hkey,
  1188. VIRTUAL_ROOTS_KEY_A,
  1189. 0,
  1190. NULL,
  1191. 0,
  1192. KEY_READ|KEY_WRITE,
  1193. NULL,
  1194. &hkeyRoots,
  1195. &dwDisp );
  1196. if ( err != NO_ERROR ) {
  1197. IF_DEBUG(METABASE) {
  1198. DBGPRINTF((DBG_CONTEXT,
  1199. "Error %d in RegCreateKeyEx\n",err));
  1200. }
  1201. goto exit;
  1202. }
  1203. #if 0
  1204. Removing this if will mean everytime the server starts we migrate the registry
  1205. keys to the metabase. The only side effect this has is if somebody deleted the
  1206. a virtual directory from the metabase w/o the server started, that key will be
  1207. migrated back from the registry. With the server running it's not a big deal
  1208. since the server always mirrors the metabase to the registry on vroot changes.
  1209. if ( dwDisp == REG_OPENED_EXISTING_KEY ) {
  1210. IF_DEBUG(METABASE) {
  1211. DBGPRINTF((DBG_CONTEXT,
  1212. "Registry VR key found, aborting startup migration.\n"));
  1213. }
  1214. goto exit;
  1215. }
  1216. #endif
  1217. //
  1218. // Get the MD handle to the VR root
  1219. //
  1220. if ( !mb.Open( QueryMDPath(),
  1221. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  1222. {
  1223. DBGPRINTF((DBG_CONTEXT,"Open MD vr root returns %d\n",GetLastError()));
  1224. goto exit;
  1225. }
  1226. IF_DEBUG(METABASE) {
  1227. DBGPRINTF((DBG_CONTEXT,"Opening MD path[%s]\n",QueryMDPath()));
  1228. }
  1229. TsRecursiveEnumVirtualRoots(
  1230. TsCopyVrootToRegistry,
  1231. hkeyRoots,
  1232. IIS_MD_INSTANCE_ROOT "/",
  1233. 1,
  1234. (LPVOID)&mb,
  1235. TRUE );
  1236. mb.Close();
  1237. fMigrated = TRUE;
  1238. exit:
  1239. if ( hkey != NULL ) {
  1240. RegCloseKey(hkey);
  1241. }
  1242. if ( hkeyRoots != NULL ) {
  1243. RegCloseKey(hkeyRoots);
  1244. }
  1245. IF_DEBUG(METABASE) {
  1246. DBGPRINTF((DBG_CONTEXT,"Leaving MoveMDToRegAtStartup.\n"));
  1247. }
  1248. return(fMigrated);
  1249. } // IIS_SERVER_INSTANCE::MoveMDVroots2Registry
  1250. VOID
  1251. IIS_SERVER_INSTANCE::PdcHackVRReg2MD(
  1252. VOID
  1253. )
  1254. /*++
  1255. Routine Description:
  1256. Moves VR entries to the MD at startup.
  1257. Arguments:
  1258. None.
  1259. Return Value:
  1260. None.
  1261. --*/
  1262. {
  1263. DWORD err;
  1264. CHAR pszRoot[MAX_LENGTH_VIRTUAL_ROOT + MAX_LENGTH_ROOT_ADDR + 2];
  1265. CHAR pszDirectory[MAX_PATH + UNLEN + 3];
  1266. CHAR * pszUser;
  1267. DWORD cchRoot;
  1268. DWORD cchDir;
  1269. DWORD cch;
  1270. BOOL fRet = TRUE;
  1271. DWORD i = 0;
  1272. DWORD dwRegType;
  1273. DWORD dwMask;
  1274. PCHAR pszMask;
  1275. PCHAR tmpRoot;
  1276. DWORD dwAuthorization;
  1277. MB mb( (IMDCOM*) m_Service->QueryMDObject() );
  1278. HKEY hkey = NULL;
  1279. HKEY hkeyRoots = NULL;
  1280. DBG_ASSERT(IsDownLevelInstance());
  1281. IF_DEBUG(METABASE) {
  1282. DBGPRINTF((DBG_CONTEXT,"In MoveVrootFromRegToMD\n"));
  1283. }
  1284. //
  1285. // see if the key exists
  1286. //
  1287. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1288. m_Service->QueryRegParamKey( ),
  1289. 0,
  1290. KEY_READ,
  1291. &hkey );
  1292. if ( err != NO_ERROR ) {
  1293. DBGPRINTF(( DBG_CONTEXT, "RegOpenKeyEx returned error %d\n",err ));
  1294. return;
  1295. }
  1296. //
  1297. // VR key?
  1298. //
  1299. if ( err = RegOpenKeyEx( hkey,
  1300. VIRTUAL_ROOTS_KEY_A,
  1301. 0,
  1302. KEY_READ,
  1303. &hkeyRoots )) {
  1304. IF_DEBUG(METABASE) {
  1305. DBGPRINTF((DBG_CONTEXT,"RegOpenKeyEx %s failed with %d\n",
  1306. VIRTUAL_ROOTS_KEY_A, err));
  1307. }
  1308. goto exit;
  1309. }
  1310. //
  1311. // Key exists. Get the authorization key
  1312. //
  1313. {
  1314. HKEY instanceKey;
  1315. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1316. QueryRegParamKey(),
  1317. 0,
  1318. KEY_ALL_ACCESS,
  1319. &instanceKey );
  1320. if ( err != NO_ERROR ) {
  1321. goto exit;
  1322. }
  1323. dwAuthorization = ReadRegistryDword( instanceKey,
  1324. INETA_AUTHENTICATION,
  1325. INET_INFO_AUTH_ANONYMOUS );
  1326. RegCloseKey( instanceKey );
  1327. }
  1328. //
  1329. // Get the MD handle to the VR root
  1330. //
  1331. if ( !mb.Open( QueryMDPath(),
  1332. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE ))
  1333. {
  1334. DBGPRINTF((DBG_CONTEXT,"Open MD vr root returns %d\n",GetLastError()));
  1335. goto exit;
  1336. }
  1337. IF_DEBUG(METABASE) {
  1338. DBGPRINTF((DBG_CONTEXT,"Adding MD path[%s]\n",QueryMDPath()));
  1339. }
  1340. //
  1341. // Enumerate all of the listed items in the registry
  1342. // and add them
  1343. //
  1344. strcpy( pszRoot, IIS_MD_INSTANCE_ROOT );
  1345. tmpRoot = (PCHAR)pszRoot+sizeof( IIS_MD_INSTANCE_ROOT ) - 1;
  1346. while ( TRUE ) {
  1347. PCHAR pszComma;
  1348. cchRoot = sizeof( pszRoot ) - 1;
  1349. cchDir = sizeof( pszDirectory );
  1350. err = RegEnumValue( hkeyRoots,
  1351. i++,
  1352. tmpRoot,
  1353. &cchRoot,
  1354. NULL,
  1355. &dwRegType,
  1356. (LPBYTE) pszDirectory,
  1357. &cchDir );
  1358. if ( err == ERROR_NO_MORE_ITEMS ) {
  1359. break;
  1360. }
  1361. if ( dwRegType == REG_SZ ) {
  1362. //
  1363. // The optional user name is kept after the directory.
  1364. // Only used for UNC roots, ignore for others
  1365. //
  1366. if ( pszUser = strchr( pszDirectory, ',' ) )
  1367. {
  1368. *pszUser = '\0';
  1369. pszUser++;
  1370. } else {
  1371. pszUser = "";
  1372. }
  1373. //
  1374. // The optional access mask is kept after the user name. It must
  1375. // appear in upper case hex.
  1376. //
  1377. if ( pszUser && (pszMask = strchr( pszUser, ',' )) ) {
  1378. *pszMask = '\0';
  1379. pszMask++;
  1380. dwMask = hextointA( pszMask );
  1381. } else {
  1382. dwMask = VROOT_MASK_READ;
  1383. }
  1384. //
  1385. // Remove commas from the root
  1386. //
  1387. pszComma = strchr(tmpRoot, ',');
  1388. if ( pszComma != NULL ) {
  1389. *pszComma = '\0';
  1390. cchRoot--;
  1391. }
  1392. //
  1393. // Write it out to the metabase
  1394. //
  1395. cchRoot++;
  1396. //
  1397. // This is the root
  1398. //
  1399. if ( !mb.AddObject( pszRoot ) )
  1400. {
  1401. if ( GetLastError() != ERROR_ALREADY_EXISTS )
  1402. {
  1403. DBGPRINTF((DBG_CONTEXT,"AddMetaObject %s failed with %d\n",
  1404. pszRoot, GetLastError() ));
  1405. }
  1406. continue;
  1407. }
  1408. //
  1409. // Set Path
  1410. //
  1411. mb.SetString( pszRoot,
  1412. MD_VR_PATH,
  1413. IIS_MD_UT_FILE,
  1414. pszDirectory );
  1415. mb.SetString( pszRoot,
  1416. MD_KEY_TYPE,
  1417. IIS_MD_UT_SERVER,
  1418. "IIsWebVirtualDir" );
  1419. //
  1420. // Set Username
  1421. //
  1422. if ( pszUser && *pszUser )
  1423. {
  1424. mb.SetString( pszRoot,
  1425. MD_VR_USERNAME,
  1426. IIS_MD_UT_FILE,
  1427. pszUser );
  1428. }
  1429. //
  1430. // Set Mask
  1431. //
  1432. mb.SetDword( pszRoot,
  1433. MD_ACCESS_PERM,
  1434. IIS_MD_UT_FILE,
  1435. dwMask );
  1436. }
  1437. } // while
  1438. mb.Close();
  1439. exit:
  1440. if ( hkeyRoots != NULL ) {
  1441. RegCloseKey( hkeyRoots );
  1442. }
  1443. if ( hkey != NULL ) {
  1444. RegCloseKey( hkey );
  1445. }
  1446. return;
  1447. } // IIS_SERVER_INSTANCE::PdcHackVRReg2MD
  1448. VOID
  1449. IIS_SERVER_INSTANCE::TsMirrorVirtualRoots(
  1450. IN LPINETA_CONFIG_INFO pConfig
  1451. )
  1452. /*++
  1453. Description:
  1454. Writes the virtual roots specified in the config structure to the
  1455. registry
  1456. Arguments:
  1457. pConfig - new list of virtual
  1458. Returns:
  1459. TRUE on success and FALSE if any failure.
  1460. --*/
  1461. {
  1462. DWORD err;
  1463. HKEY hkey = NULL;
  1464. HKEY hkeyRoots = NULL;
  1465. DWORD dwDummy;
  1466. LPINET_INFO_VIRTUAL_ROOT_LIST pRootsList;
  1467. DWORD cch;
  1468. DWORD i;
  1469. DBG_ASSERT(IsDownLevelInstance());
  1470. pRootsList = pConfig->VirtualRoots;
  1471. //
  1472. // Write it to the root key
  1473. //
  1474. err = RegOpenKeyEx(
  1475. HKEY_LOCAL_MACHINE,
  1476. m_Service->QueryRegParamKey(),
  1477. 0,
  1478. KEY_ALL_ACCESS,
  1479. &hkey );
  1480. if ( err != NO_ERROR ) {
  1481. DBGPRINTF(( DBG_CONTEXT, "RegOpenKeyEx for returned error %d\n",err ));
  1482. return;
  1483. }
  1484. //
  1485. // First delete the key to remove any old values
  1486. //
  1487. if (err = RegDeleteKey( hkey,
  1488. VIRTUAL_ROOTS_KEY_A ))
  1489. {
  1490. DBGPRINTF(( DBG_CONTEXT,
  1491. "[TsMirrorVRoots] Unable to remove old values\n"));
  1492. }
  1493. if ( err = RegCreateKeyEx( hkey,
  1494. VIRTUAL_ROOTS_KEY_A,
  1495. 0,
  1496. NULL,
  1497. 0,
  1498. KEY_ALL_ACCESS,
  1499. NULL,
  1500. &hkeyRoots,
  1501. &dwDummy ))
  1502. {
  1503. goto exit;
  1504. }
  1505. //
  1506. // Permit empty list
  1507. //
  1508. if ( pRootsList == NULL ) {
  1509. goto exit;
  1510. }
  1511. for ( i = 0; i < pRootsList->cEntries; i++ ) {
  1512. WCHAR achValue[ MAX_PATH + UNLEN + 2 ];
  1513. cch = _snwprintf( achValue,
  1514. MAX_PATH + UNLEN + 1,
  1515. L"%s,%s,%X",
  1516. pRootsList->aVirtRootEntry[i].pszDirectory,
  1517. pRootsList->aVirtRootEntry[i].pszAccountName,
  1518. pRootsList->aVirtRootEntry[i].dwMask );
  1519. DBG_ASSERT( cch < sizeof( achValue ) / sizeof(WCHAR) );
  1520. achValue[ MAX_PATH + UNLEN + 1 ] = L'\0';
  1521. err = WriteRegistryStringW(hkeyRoots,
  1522. pRootsList->aVirtRootEntry[i].pszRoot,
  1523. achValue,
  1524. (wcslen(achValue) + 1) * sizeof(WCHAR),
  1525. REG_SZ);
  1526. if ( err != NO_ERROR ) {
  1527. goto exit;
  1528. }
  1529. }
  1530. exit:
  1531. if ( hkeyRoots != NULL ) {
  1532. RegCloseKey( hkeyRoots );
  1533. }
  1534. if ( hkey != NULL ) {
  1535. RegCloseKey( hkey );
  1536. }
  1537. return;
  1538. } // IIS_SERVER_INSTANCE::TsMirrorVirtualRoots
  1539. VOID
  1540. ClearSentinelEntry(
  1541. IN MB * pMB
  1542. )
  1543. /*++
  1544. Description:
  1545. Removes the sentinel entry from all VR for this instance
  1546. Arguments:
  1547. pMD - pointer to metabase helper object that points to the
  1548. instance metadatabase root.
  1549. Returns:
  1550. None.
  1551. --*/
  1552. {
  1553. BOOL fGetRoot = TRUE;
  1554. CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
  1555. DWORD i = 0;
  1556. IF_DEBUG(METABASE) {
  1557. DBGPRINTF((DBG_CONTEXT,"Entering ClearSentinelEntry\n"));
  1558. }
  1559. while ( TRUE ) {
  1560. METADATA_RECORD mdRecord;
  1561. nameBuf[0] = nameBuf[1] = '/';
  1562. if ( fGetRoot ) {
  1563. fGetRoot = FALSE;
  1564. nameBuf[2] = '\0';
  1565. } else {
  1566. if ( !pMB->EnumObjects( IIS_MD_INSTANCE_ROOT,
  1567. &nameBuf[2],
  1568. i++ ))
  1569. {
  1570. break;
  1571. }
  1572. }
  1573. //
  1574. // Delete sentinel value
  1575. //
  1576. if ( !pMB->DeleteData( nameBuf,
  1577. MD_VR_UPDATE,
  1578. IIS_MD_UT_FILE,
  1579. DWORD_METADATA
  1580. ))
  1581. {
  1582. IF_DEBUG(METABASE) {
  1583. DBGPRINTF((DBG_CONTEXT,"Error %x deleting sentinel from %s\n",
  1584. GetLastError(), nameBuf));
  1585. }
  1586. }
  1587. }
  1588. return;
  1589. } // ClearSentinelEntry
  1590. VOID
  1591. RemoveUnmarkedRoots(
  1592. IN MB * pMB
  1593. )
  1594. /*++
  1595. Description:
  1596. Removes roots that are not marked by sentinel
  1597. Arguments:
  1598. pMD - pointer to metabase helper object that points to the
  1599. instance metadatabase root.
  1600. Returns:
  1601. None.
  1602. --*/
  1603. {
  1604. BOOL fGetRoot = TRUE;
  1605. CHAR nameBuf[METADATA_MAX_NAME_LEN+2];
  1606. CHAR szDirectory[MAX_PATH+1];
  1607. DWORD cb;
  1608. DWORD i = 0;
  1609. BOOL fProcessingRoot;
  1610. IF_DEBUG(METABASE) {
  1611. DBGPRINTF((DBG_CONTEXT,"Entering RemoveUnmarkedRoots\n"));
  1612. }
  1613. while ( TRUE ) {
  1614. if ( fGetRoot ) {
  1615. strcpy( nameBuf, IIS_MD_INSTANCE_ROOT );
  1616. fProcessingRoot = TRUE;
  1617. fGetRoot = FALSE;
  1618. } else {
  1619. strcpy( nameBuf, IIS_MD_INSTANCE_ROOT "/" );
  1620. fProcessingRoot = FALSE;
  1621. if ( !pMB->EnumObjects( IIS_MD_INSTANCE_ROOT,
  1622. &nameBuf[strlen(nameBuf)],
  1623. i++ ))
  1624. {
  1625. break;
  1626. }
  1627. }
  1628. //
  1629. // Delete sentinel value. If delete successful, leave alone
  1630. //
  1631. if ( pMB->DeleteData( nameBuf,
  1632. MD_VR_UPDATE,
  1633. IIS_MD_UT_FILE,
  1634. DWORD_METADATA
  1635. ))
  1636. {
  1637. continue;
  1638. }
  1639. IF_DEBUG(METABASE) {
  1640. DBGPRINTF((DBG_CONTEXT,"Error %x deleting sentinel from %s\n",
  1641. GetLastError(), nameBuf));
  1642. }
  1643. //
  1644. // See if it has the path parameter
  1645. //
  1646. cb = sizeof( szDirectory );
  1647. if ( !pMB->GetString( nameBuf,
  1648. MD_VR_PATH,
  1649. IIS_MD_UT_FILE,
  1650. szDirectory,
  1651. &cb,
  1652. 0 ))
  1653. {
  1654. //
  1655. // Not a VR
  1656. //
  1657. DBGPRINTF((DBG_CONTEXT,
  1658. "Error %x reading path from %s. Not a VR.\n",
  1659. GetLastError(), nameBuf));
  1660. continue;
  1661. }
  1662. //
  1663. // Unmarked, delete the VR
  1664. //
  1665. IF_DEBUG(METABASE) {
  1666. DBGPRINTF((DBG_CONTEXT,"Deleting vroot %s[%d]\n",
  1667. nameBuf, fGetRoot));
  1668. }
  1669. if ( fProcessingRoot ) {
  1670. //
  1671. // if this is the root, just remove the path. Deleting the
  1672. // root is a potentially dangerous undertaking!
  1673. //
  1674. if ( !pMB->DeleteData( nameBuf,
  1675. MD_VR_PATH,
  1676. IIS_MD_UT_FILE,
  1677. STRING_METADATA
  1678. ))
  1679. {
  1680. DBGPRINTF((DBG_CONTEXT,"Error %x deleting root path\n",
  1681. GetLastError()));
  1682. }
  1683. } else {
  1684. //
  1685. // Delete the Vroot
  1686. //
  1687. if ( !pMB->DeleteObject( nameBuf ) )
  1688. {
  1689. DBGPRINTF((DBG_CONTEXT,"Error %x deleting %s\n",
  1690. GetLastError(), nameBuf));
  1691. } else {
  1692. //
  1693. // the delete moved the index back by 1
  1694. //
  1695. DBG_ASSERT( i != 0 );
  1696. --i;
  1697. }
  1698. }
  1699. fGetRoot = FALSE;
  1700. }
  1701. return;
  1702. } // RemoveUnmarkedRoots
  1703. BOOL
  1704. ReadVrootConfig(
  1705. LPVOID pvMB,
  1706. LPSTR szVRPath,
  1707. LPSTR szDirectory,
  1708. DWORD cbDirectory,
  1709. LPSTR szUser,
  1710. DWORD cbUser,
  1711. LPSTR szPassword,
  1712. DWORD cbPassword,
  1713. DWORD *pdwMask,
  1714. BOOL *pfDoCache
  1715. )
  1716. {
  1717. DWORD cb;
  1718. DWORD dwNoCache = 0;
  1719. MB* pMB = (MB*)pvMB;
  1720. //
  1721. // Get Directory path
  1722. //
  1723. cb = cbDirectory;
  1724. if ( !pMB->GetString( szVRPath,
  1725. MD_VR_PATH,
  1726. IIS_MD_UT_FILE,
  1727. szDirectory,
  1728. &cb,
  1729. 0 ))
  1730. {
  1731. #if DBG
  1732. if ( GetLastError() != MD_ERROR_DATA_NOT_FOUND )
  1733. {
  1734. DBGPRINTF((DBG_CONTEXT,"Error %x reading path from %s. Not a VR.\n",
  1735. GetLastError(), szVRPath));
  1736. }
  1737. #endif
  1738. return FALSE;
  1739. }
  1740. //
  1741. // Get mask
  1742. //
  1743. if ( !pMB->GetDword( szVRPath,
  1744. MD_ACCESS_PERM,
  1745. IIS_MD_UT_FILE,
  1746. pdwMask,
  1747. 0))
  1748. {
  1749. *pdwMask = VROOT_MASK_READ;
  1750. IF_DEBUG(ERROR) {
  1751. DBGPRINTF((DBG_CONTEXT,"Error %x reading mask from %s\n",
  1752. GetLastError(), szVRPath));
  1753. }
  1754. }
  1755. //
  1756. // Get username
  1757. //
  1758. cb = cbUser;
  1759. if ( !pMB->GetString( szVRPath,
  1760. MD_VR_USERNAME,
  1761. IIS_MD_UT_FILE,
  1762. szUser,
  1763. &cb,
  1764. 0))
  1765. {
  1766. szUser[0] = '\0';
  1767. }
  1768. IF_DEBUG(METABASE) {
  1769. DBGPRINTF((DBG_CONTEXT,"Read %s: Path[%s] User[%s] Mask[%d]\n",
  1770. szVRPath, szDirectory, szUser, *pdwMask));
  1771. }
  1772. if ( (szUser[0] != '\0') &&
  1773. (szDirectory[0] == '\\') && (szDirectory[1] == '\\') ) {
  1774. cb = cbPassword;
  1775. //
  1776. // Retrieve the password for this address/share
  1777. //
  1778. if ( !pMB->GetString( szVRPath,
  1779. MD_VR_PASSWORD,
  1780. IIS_MD_UT_FILE,
  1781. szPassword,
  1782. &cb,
  1783. METADATA_SECURE))
  1784. {
  1785. szPassword[0] = '\0';
  1786. }
  1787. }
  1788. else
  1789. {
  1790. szPassword[0] = '\0';
  1791. }
  1792. //
  1793. // Should we cache this vdir
  1794. //
  1795. pMB->GetDword( szVRPath,
  1796. MD_VR_NO_CACHE,
  1797. IIS_MD_UT_FILE,
  1798. &dwNoCache,
  1799. 0 );
  1800. *pfDoCache = !dwNoCache;
  1801. return TRUE;
  1802. }
  1803.