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.

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