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.

938 lines
23 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1995 **/
  4. /**********************************************************************/
  5. /*
  6. extmap.cxx
  7. This module contains the extension mapping to CGI or BGI scripts.
  8. FILE HISTORY:
  9. Johnl 22-Sep-1995 Created
  10. */
  11. #include "w3p.hxx"
  12. #include <rpc.h>
  13. #include <rpcndr.h>
  14. #include <mbstring.h>
  15. //
  16. // Name of the value under the parameters key containing the list of
  17. // script extension to BGI/CGI binaries.
  18. //
  19. #define HTTP_EXT_MAPS "Script Map"
  20. char Get[] = "GET";
  21. #define GET_SIZE (sizeof("GET"))
  22. //
  23. // This is the maximum size for a script map extension
  24. //
  25. #define MAX_EXT_LEN 128
  26. //
  27. // This list is the extension maps found in the registry - they always get
  28. // appended to the end of all extension mappings that are added to a particular
  29. // URI.
  30. //
  31. static BOOL fInitialized = FALSE;
  32. class EXT_MAP_ITEM
  33. {
  34. public:
  35. EXT_MAP_ITEM( const char * pszExtension,
  36. const char * pszImage,
  37. const DWORD dwFlags,
  38. const CHAR * pszExclusions,
  39. const DWORD dwExclusionLength)
  40. : _strExt ( pszExtension ),
  41. _strImage ( pszImage ),
  42. _GatewayType( GATEWAY_UNKNOWN ),
  43. _cchExt ( 0 ),
  44. _dwFlags ( dwFlags ),
  45. _fGetValid (0),
  46. _dwInclusionCount ( 0 ),
  47. _ppszInclusionTable ( NULL ),
  48. _pszInclusions ( NULL )
  49. {
  50. DWORD cch;
  51. _fValid = _strExt.IsValid() && _strImage.IsValid() && ExpandImage();
  52. if ( _fValid )
  53. {
  54. const CHAR * pchtmp = pszImage;
  55. _cchExt = _strExt.QueryCCH();
  56. //
  57. // Determine if this is a CGI or BGI gateway
  58. //
  59. while ( pchtmp = strchr( pchtmp + 1, '.' ))
  60. {
  61. if ( !_strnicmp( pchtmp, ".exe", 4 ))
  62. {
  63. _GatewayType = GATEWAY_CGI;
  64. }
  65. else if ( !_strnicmp( pchtmp, ".dll", 4 ))
  66. {
  67. _GatewayType = GATEWAY_BGI;
  68. }
  69. }
  70. if (!strcmp(pszExtension, "*"))
  71. {
  72. _fWildcard = TRUE;
  73. _dwFlags |= MD_SCRIPTMAPFLAG_WILDCARD;
  74. }
  75. else
  76. {
  77. _fWildcard = FALSE;
  78. _dwFlags &= ~MD_SCRIPTMAPFLAG_WILDCARD;
  79. }
  80. if (pszExclusions != NULL)
  81. {
  82. const CHAR *pszTemp;
  83. char *pszDest;
  84. _pszInclusions = new char[dwExclusionLength];
  85. if (_pszInclusions == NULL)
  86. {
  87. _fValid = FALSE;
  88. return;
  89. }
  90. _dwInclusionCount = 1;
  91. pszTemp = pszExclusions;
  92. pszDest = _pszInclusions;
  93. while (*pszTemp != '\0')
  94. {
  95. CHAR ch;
  96. ch = *pszTemp;
  97. pszTemp++;
  98. if (ch != ',')
  99. {
  100. *pszDest = ch;
  101. }
  102. else
  103. {
  104. *pszDest = '\0';
  105. _dwInclusionCount++;
  106. }
  107. pszDest++;
  108. }
  109. *pszDest = '\0';
  110. _ppszInclusionTable = new char *[_dwInclusionCount];
  111. if (_ppszInclusionTable == NULL)
  112. {
  113. _fValid = FALSE;
  114. return;
  115. }
  116. else
  117. {
  118. DWORD i;
  119. DWORD dwPos;
  120. pszTemp = _pszInclusions;
  121. i = 0;
  122. do {
  123. _ppszInclusionTable[i] = (CHAR *)pszTemp;
  124. if ( _fGetValid )
  125. {
  126. dwPos = 0;
  127. }
  128. while (*pszTemp != '\0')
  129. {
  130. if (dwPos < GET_SIZE)
  131. {
  132. if (*pszTemp == Get[dwPos])
  133. {
  134. dwPos++;
  135. if (dwPos == (GET_SIZE - 1))
  136. {
  137. if (*(pszTemp+1) == '\0')
  138. {
  139. _fGetValid = TRUE;
  140. }
  141. else
  142. {
  143. dwPos = GET_SIZE;
  144. }
  145. }
  146. }
  147. else
  148. {
  149. dwPos = GET_SIZE;
  150. }
  151. }
  152. pszTemp++;
  153. }
  154. DBG_ASSERT(*pszTemp == '\0');
  155. pszTemp++;
  156. i++;
  157. } while (i < _dwInclusionCount );
  158. }
  159. }
  160. else
  161. {
  162. _dwInclusionCount = 0;
  163. _ppszInclusionTable = NULL;
  164. _pszInclusions = NULL;
  165. }
  166. }
  167. }
  168. ~EXT_MAP_ITEM( )
  169. {
  170. delete _ppszInclusionTable;
  171. delete _pszInclusions;
  172. }
  173. GATEWAY_TYPE QueryGatewayType( VOID ) const
  174. { return _GatewayType; }
  175. const CHAR * QueryScript( VOID ) const
  176. { return _strImage.QueryStr(); }
  177. const CHAR * QueryExtension( VOID ) const
  178. { return _strExt.QueryStr(); }
  179. const BOOL AllowedOnReadDir()
  180. { return _dwFlags & MD_SCRIPTMAPFLAG_SCRIPT; }
  181. const DWORD QueryFlags()
  182. { return _dwFlags; }
  183. DWORD QueryCCHExt( VOID ) const
  184. { return _cchExt; }
  185. BOOL IsValid( VOID ) const
  186. { return _fValid; }
  187. BOOL IsWildCard( VOID ) const
  188. { return _fWildcard; }
  189. BOOL IsGetValid( VOID ) const
  190. { return _fGetValid; }
  191. BOOL ExpandImage( VOID );
  192. BOOL CheckInclusions(
  193. const CHAR *pszVerb
  194. );
  195. LIST_ENTRY _ListEntry;
  196. private:
  197. STR _strExt;
  198. STR _strImage;
  199. DWORD _cchExt;
  200. GATEWAY_TYPE _GatewayType;
  201. DWORD _fValid:1;
  202. DWORD _fWildcard:1;
  203. DWORD _fGetValid:1;
  204. DWORD _dwFlags;
  205. DWORD _dwInclusionCount;
  206. CHAR **_ppszInclusionTable;
  207. CHAR *_pszInclusions;
  208. };
  209. BOOL
  210. EXT_MAP_ITEM::ExpandImage( VOID )
  211. /*++
  212. Routine Description:
  213. Expand any embedded environment variables in the image.
  214. Return Value:
  215. TRUE if successful, FALSE if not.
  216. --*/
  217. {
  218. DWORD cbRet = 0;
  219. TCHAR achBuffer[ MAX_PATH + 1 ];
  220. DWORD cbBufLen = sizeof( achBuffer );
  221. cbRet = ExpandEnvironmentStringsA( _strImage.QueryStr(),
  222. achBuffer,
  223. cbBufLen );
  224. if ( !cbRet || ( cbRet > cbBufLen ) )
  225. {
  226. return FALSE;
  227. }
  228. else
  229. {
  230. return _strImage.Copy( achBuffer );
  231. }
  232. }
  233. //
  234. // Private globals.
  235. //
  236. BOOL
  237. W3_METADATA::BuildExtMap(
  238. CHAR *pszExtMapList
  239. )
  240. /*++
  241. Routine Description:
  242. Builds the extension mapping into the metadata. The input string is
  243. a multi-sz of comma seperated ext, image name strings.
  244. Return Value:
  245. TRUE if successfull, FALSE if not.
  246. --*/
  247. {
  248. EXT_MAP_ITEM * pExtMap;
  249. EXT_MAP_ITEM * pWCExtMapItem;
  250. LIST_ENTRY * pEntry;
  251. m_fAnyExtAllowedOnReadDir = FALSE;
  252. m_dwMaxExtLen = 0;
  253. do
  254. {
  255. CHAR *pszExt;
  256. CHAR *pszImage;
  257. CHAR *pszFlags;
  258. CHAR *pszExclusions;
  259. CHAR *pszTemp;
  260. CHAR *pszTemp2;
  261. CHAR *pszTemp3;
  262. DWORD dwExclusionSize;
  263. DWORD dwExtSize;
  264. pszExt = pszExtMapList;
  265. // Find the end of the extension, and temporarily NULL terminate it.
  266. pszImage = strchr(pszExt, ',');
  267. if (pszImage == NULL) {
  268. // Bad script map entry
  269. SetLastError(ERROR_INVALID_DATA);
  270. return FALSE;
  271. }
  272. pszTemp = pszImage++;
  273. *pszTemp = '\0';
  274. pszFlags = strchr(pszImage, ',');
  275. if (pszFlags == NULL) {
  276. // Bad script map entry
  277. SetLastError(ERROR_INVALID_DATA);
  278. return FALSE;
  279. }
  280. pszTemp2 = pszFlags++;
  281. *pszTemp2 = '\0';
  282. //
  283. // HOTFIX: make sure the extension is not too long to be copied to
  284. // our static buffer.
  285. //
  286. dwExtSize = strlen(pszExt);
  287. if (dwExtSize > MAX_EXT_LEN) {
  288. // Bad script map entry
  289. SetLastError(ERROR_INVALID_DATA);
  290. return FALSE;
  291. } else if (dwExtSize > m_dwMaxExtLen) {
  292. m_dwMaxExtLen = dwExtSize;
  293. }
  294. //
  295. // See if there's any excluded methods. If there are, break them out.
  296. //
  297. pszExclusions = strchr(pszFlags, ',');
  298. if (pszExclusions != NULL)
  299. {
  300. pszTemp3 = pszExclusions++;
  301. *pszTemp3 = '\0';
  302. dwExclusionSize = strlen(pszExclusions) + 1;
  303. pszExtMapList = pszExclusions + dwExclusionSize;
  304. }
  305. else
  306. {
  307. pszExtMapList = pszFlags + strlen(pszFlags) + 1;
  308. dwExclusionSize = 0;
  309. }
  310. //
  311. // HOTFIX: Now convert extension to lower case so we can avoid
  312. // multi-byte string compares that cause lock contention.
  313. //
  314. IISstrlwr( (PUCHAR) pszExt );
  315. //
  316. // Note we OR in the notransmit flag on *all* script mappings!
  317. //
  318. pExtMap = new EXT_MAP_ITEM( pszExt,
  319. pszImage,
  320. ((DWORD) atoi( pszFlags )),
  321. pszExclusions,
  322. dwExclusionSize);
  323. *pszTemp = ',';
  324. *pszTemp2 = ',';
  325. if (pszExclusions != NULL)
  326. {
  327. *pszTemp3 = '\0';
  328. }
  329. if ( !pExtMap ||
  330. !pExtMap->IsValid() )
  331. {
  332. delete pExtMap;
  333. return FALSE;
  334. }
  335. if (!pExtMap->IsWildCard())
  336. {
  337. InsertTailList( &m_ExtMapHead, &pExtMap->_ListEntry );
  338. }
  339. else
  340. {
  341. pWCExtMapItem = (EXT_MAP_ITEM *)QueryWildcardMapping();
  342. if (pWCExtMapItem != NULL)
  343. {
  344. delete pWCExtMapItem;
  345. }
  346. SetWildcardMapping( pExtMap );
  347. }
  348. if ( pExtMap->QueryFlags() )
  349. {
  350. m_fAnyExtAllowedOnReadDir = TRUE;
  351. }
  352. } while ( *pszExtMapList != '\0');
  353. return TRUE;
  354. } // W3_METADATA::BuildExtMap
  355. VOID
  356. W3_METADATA::TerminateExtMap(
  357. VOID
  358. )
  359. /*++
  360. Routine Description:
  361. Cleans up the extension map list
  362. --*/
  363. {
  364. LIST_ENTRY * pEntry;
  365. EXT_MAP_ITEM * pExtMap;
  366. while ( !IsListEmpty( &m_ExtMapHead ))
  367. {
  368. pExtMap = CONTAINING_RECORD( m_ExtMapHead.Flink,
  369. EXT_MAP_ITEM,
  370. _ListEntry );
  371. RemoveEntryList( &pExtMap->_ListEntry );
  372. delete pExtMap;
  373. }
  374. pExtMap = (EXT_MAP_ITEM *)QueryWildcardMapping();
  375. if (pExtMap != NULL)
  376. {
  377. delete pExtMap;
  378. }
  379. } // W3_METADATA::TerminateExtMap
  380. BOOL
  381. EXT_MAP_ITEM::CheckInclusions(
  382. const CHAR *pszVerb
  383. )
  384. /*++
  385. Routine Description:
  386. Check the extension map list to see if the input verb is included.
  387. If it is, we return TRUE, otherwise we return FALSE.
  388. --*/
  389. {
  390. DWORD i;
  391. //
  392. // Special case for EMPTY script map. Allow all verbs
  393. //
  394. if (0 == _dwInclusionCount)
  395. {
  396. return TRUE;
  397. }
  398. for (i = 0; i < _dwInclusionCount; i++)
  399. {
  400. if (!_stricmp(pszVerb, _ppszInclusionTable[i]))
  401. {
  402. return TRUE;
  403. }
  404. }
  405. return FALSE;
  406. } // EXT_MAP_ITEM::CheckInclusions
  407. BOOL
  408. W3_METADATA::LookupExtMap(
  409. IN const CHAR * pchExt,
  410. IN BOOL fNoWildcards,
  411. OUT STR * pstrGatewayImage,
  412. OUT GATEWAY_TYPE * pGatewayType,
  413. OUT DWORD * pcchExt,
  414. OUT BOOL * pfImageInURL,
  415. OUT BOOL * pfVerbExcluded,
  416. OUT DWORD * pdwFlags,
  417. IN const CHAR *pszVerb,
  418. IN enum HTTP_VERB Verb,
  419. IN OUT PVOID * ppvExtMapInfo
  420. )
  421. /*++
  422. Routine Description:
  423. Finds the admin specified mapping between a script extension and the
  424. associated CGI or BGI binary to run (or load).
  425. Arguments:
  426. pchExt - Pointer to possible extension to be mapped (i.e., '.pl')
  427. pstrGatewayImage - Receives the mapped binary image name
  428. pGatewayType - Specifies whether this is a BGI, CGI or MAP extension type
  429. pcchExt - Returns length of extension (including dot)
  430. pfImageInURL - Indicates an image was found encoded in the URL and not
  431. from a script extension mapping
  432. pdwFlags - Returns extension flags
  433. ppvExtMapInfo - Cached extension map info. If *ppvExtMapInfo is NULL on
  434. input, then set to the matched PEXT_MAP_ITEM. If not NULL
  435. on input, then it is used instead of doing lookup.
  436. --*/
  437. {
  438. EXT_MAP_ITEM * pExtMapItem;
  439. DWORD cchTillEOS;
  440. BOOL fRet;
  441. LIST_ENTRY * pEntry;
  442. BOOL bFoundMatch = FALSE;
  443. BOOL fUseExtMapInfo = *ppvExtMapInfo != NULL;
  444. *pGatewayType = GATEWAY_UNKNOWN;
  445. *pfVerbExcluded = FALSE;
  446. //
  447. // Check for wildcard mapping first
  448. //
  449. if (!fNoWildcards)
  450. {
  451. pExtMapItem = (EXT_MAP_ITEM *)QueryWildcardMapping();
  452. if (pExtMapItem != NULL)
  453. {
  454. if (Verb == HTV_GET && pExtMapItem->IsGetValid())
  455. {
  456. bFoundMatch = TRUE;
  457. }
  458. else
  459. {
  460. // If verb is not included, don't return the * script map.
  461. // Instead, continue to look for a script map match.
  462. bFoundMatch = pExtMapItem->CheckInclusions( pszVerb );
  463. }
  464. }
  465. }
  466. //
  467. // Look for the exact extension mapping if there's no wildcard
  468. //
  469. if (!bFoundMatch && pchExt != NULL)
  470. {
  471. if ( fUseExtMapInfo )
  472. {
  473. //
  474. // If caller passed in a non-NULL pExtMapInfo, then use it
  475. // instead of doing a manual lookup
  476. //
  477. if ( *ppvExtMapInfo != EXTMAP_UNKNOWN_PTR )
  478. {
  479. pExtMapItem = (EXT_MAP_ITEM*) *ppvExtMapInfo;
  480. bFoundMatch = TRUE;
  481. }
  482. }
  483. else
  484. {
  485. //
  486. // This buffer, rgchExtBuffer, holds a copy of a portion of a URL
  487. // which we are testing to see if it's a known extension. We copy
  488. // into this buffer so we can convert the extension to lower case
  489. // without disrupting the original.
  490. //
  491. CHAR rgchExtBuffer[MAX_EXT_LEN + 4];
  492. DWORD dwLength;
  493. DBG_ASSERT( *pchExt == '.' );
  494. //
  495. // HOTFIX: Now convert extension to lower case so we can avoid
  496. // multi-byte string compares that cause lock contention.
  497. //
  498. // Since we don't want to risk modifying the orignal URL, we
  499. // copy it into another buffer first.
  500. //
  501. cchTillEOS = strlen( pchExt );
  502. dwLength = min(cchTillEOS, m_dwMaxExtLen + 1);
  503. memcpy(rgchExtBuffer, pchExt, dwLength);
  504. rgchExtBuffer[ dwLength ] = 0;
  505. IISstrlwr( (PUCHAR) rgchExtBuffer );
  506. //
  507. // Look through the list of mappings
  508. //
  509. for ( pEntry = m_ExtMapHead.Flink;
  510. !bFoundMatch && pEntry != &m_ExtMapHead;
  511. pEntry = pEntry->Flink )
  512. {
  513. pExtMapItem = CONTAINING_RECORD( pEntry, EXT_MAP_ITEM, _ListEntry );
  514. if ( cchTillEOS >= pExtMapItem->QueryCCHExt() &&
  515. (pchExt[pExtMapItem->QueryCCHExt()] == '/' ||
  516. pchExt[pExtMapItem->QueryCCHExt()] == '\0' ) &&
  517. !memcmp( rgchExtBuffer,
  518. pExtMapItem->QueryExtension(),
  519. pExtMapItem->QueryCCHExt())
  520. )
  521. {
  522. bFoundMatch = TRUE;
  523. *ppvExtMapInfo = pExtMapItem;
  524. }
  525. }
  526. }
  527. }
  528. if (bFoundMatch)
  529. {
  530. *pGatewayType = pExtMapItem->QueryGatewayType();
  531. *pcchExt = pExtMapItem->QueryCCHExt();
  532. *pfImageInURL = FALSE;
  533. *pdwFlags = pExtMapItem->QueryFlags();
  534. //
  535. // Check that verb is included. If it isn't, we're still going to return
  536. // this item. Just indicate that the verb was excluded.
  537. //
  538. if (Verb != HTV_GET || !pExtMapItem->IsGetValid())
  539. {
  540. *pfVerbExcluded = !pExtMapItem->CheckInclusions(pszVerb);
  541. }
  542. fRet = pstrGatewayImage->Copy( pExtMapItem->QueryScript() );
  543. if ( !_stricmp( pExtMapItem->QueryScript(), "nogateway" ) )
  544. {
  545. *pGatewayType = GATEWAY_NONE;
  546. }
  547. return fRet;
  548. }
  549. if ( !pchExt || fUseExtMapInfo )
  550. {
  551. if ( !fUseExtMapInfo )
  552. {
  553. *ppvExtMapInfo = EXTMAP_UNKNOWN_PTR;
  554. }
  555. return TRUE;
  556. }
  557. //
  558. // Either the image will be specified in the URL or not found, so
  559. // just indicate it's in the URL. Not found has precedence.
  560. //
  561. *pfImageInURL = TRUE;
  562. *pdwFlags = 0;
  563. //
  564. // Look for CGI or BGI scripts in the URL itself
  565. //
  566. if ( cchTillEOS >= 4 &&
  567. (*(pchExt+4) == TEXT('/') ||
  568. *(pchExt+4) == TEXT('\0')) )
  569. {
  570. *pcchExt = 4;
  571. //
  572. // Don't confuse a menu map request with a gateway request
  573. //
  574. if ( !::_tcsnicmp( TEXT(".MAP"), pchExt, 4 ))
  575. {
  576. *pGatewayType = GATEWAY_MAP;
  577. return TRUE;
  578. }
  579. if ( !::_tcsnicmp( TEXT(".EXE"), pchExt, 4 ) ||
  580. !::_tcsnicmp( TEXT(".CGI"), pchExt, 4 ) ||
  581. !::_tcsnicmp( TEXT(".COM"), pchExt, 4 ))
  582. {
  583. *pGatewayType = GATEWAY_CGI;
  584. return TRUE;
  585. }
  586. else if (!::_tcsnicmp( TEXT(".DLL"), pchExt, 4 ) ||
  587. !::_tcsnicmp( TEXT(".ISA"), pchExt, 4 ) )
  588. {
  589. *pGatewayType = GATEWAY_BGI;
  590. return TRUE;
  591. }
  592. }
  593. *ppvExtMapInfo = EXTMAP_UNKNOWN_PTR;
  594. return TRUE;
  595. } // W3_METADATA::LookupExtMap
  596. APIERR
  597. ReadRegistryExtMap(
  598. VOID
  599. )
  600. /*++
  601. Routine Description:
  602. Builds the extension mapping from the registry
  603. Return Value:
  604. NO_ERROR if successful, win32 error code on failure
  605. --*/
  606. {
  607. HKEY hkeyParam;
  608. DWORD dwDisposition;
  609. LIST_ENTRY pEntry;
  610. APIERR err;
  611. DWORD i = 0;
  612. DWORD dwRegType;
  613. MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
  614. MULTISZ msz;
  615. BOOL fNeedToWrite = FALSE;
  616. if ( !fInitialized )
  617. {
  618. fInitialized = TRUE;
  619. }
  620. //
  621. // Get the list
  622. //
  623. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  624. W3_PARAMETERS_KEY "\\" HTTP_EXT_MAPS,
  625. 0,
  626. 0,
  627. 0,
  628. KEY_READ,
  629. NULL,
  630. &hkeyParam,
  631. &dwDisposition );
  632. if( err != NO_ERROR )
  633. {
  634. TCP_PRINT(( DBG_CONTEXT,
  635. "cannot open registry key, error %lu\n",
  636. err ));
  637. return NO_ERROR;
  638. }
  639. if ( !mb.Open( "/LM/W3SVC/",
  640. METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE ) ||
  641. !mb.GetMultisz( "",
  642. MD_SCRIPT_MAPS,
  643. IIS_MD_UT_FILE,
  644. &msz ))
  645. {
  646. TCP_PRINT(( DBG_CONTEXT,
  647. "cannot get the script maps from the metabase, error %d\n",
  648. GetLastError() ));
  649. return NO_ERROR;
  650. }
  651. while ( TRUE )
  652. {
  653. CHAR achExt[MAX_PATH+1];
  654. CHAR achImage[MAX_PATH+1];
  655. DWORD cchExt = sizeof( achExt );
  656. DWORD cchImage = sizeof( achImage );
  657. err = RegEnumValue( hkeyParam,
  658. i++,
  659. achExt,
  660. &cchExt,
  661. NULL,
  662. &dwRegType,
  663. (LPBYTE) achImage,
  664. &cchImage );
  665. if ( err == ERROR_NO_MORE_ITEMS )
  666. {
  667. err = NO_ERROR;
  668. break;
  669. }
  670. if ( dwRegType == REG_SZ )
  671. {
  672. const CHAR * psz;
  673. BOOL fFound = FALSE;
  674. //
  675. // Look for this script map in the metabase, if not found, add it
  676. //
  677. for ( psz = msz.First(); psz != NULL; psz = msz.Next( psz ) )
  678. {
  679. if ( !IISstrnicmp( (PUCHAR)achExt, (PUCHAR)psz, cchExt ))
  680. {
  681. fFound = TRUE;
  682. break;
  683. }
  684. }
  685. if ( !fFound )
  686. {
  687. STR str;
  688. CHAR achFlags[32];
  689. //
  690. // Note these scripts are added w/o the Script bit and with
  691. // the "never download" bit. In addition, we leave the
  692. // method exclusion list blank.
  693. //
  694. _itoa( 0, achFlags, 10 );
  695. if ( !str.Append( achExt ) ||
  696. !str.Append( "," ) ||
  697. !str.Append( achImage ) ||
  698. !str.Append( "," ) ||
  699. !str.Append( achFlags ) ||
  700. !msz.Append( str.QueryStr() ))
  701. {
  702. return err = GetLastError();
  703. break;
  704. }
  705. TCP_PRINT(( DBG_CONTEXT,
  706. "Added \"%s\" from registry as script map\n",
  707. str.QueryStr() ));
  708. fNeedToWrite = TRUE;
  709. }
  710. }
  711. }
  712. if ( fNeedToWrite )
  713. {
  714. if ( !mb.SetMultiSZ( "",
  715. MD_SCRIPT_MAPS,
  716. IIS_MD_UT_FILE,
  717. msz.QueryStr() ))
  718. {
  719. TCP_PRINT(( DBG_CONTEXT,
  720. "Failed to write MD_SCRIPT_MAPS back to metabase, error %d\n",
  721. GetLastError() ));
  722. }
  723. }
  724. RegCloseKey( hkeyParam );
  725. return err;
  726. }
  727. VOID
  728. FreeRegistryExtMap(
  729. VOID
  730. )
  731. {
  732. if ( !fInitialized )
  733. {
  734. return;
  735. }
  736. fInitialized = FALSE;
  737. }