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.

1057 lines
27 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. metabase.cxx
  5. Abstract:
  6. Class that is used to modify the metabase
  7. Author:
  8. Christopher Achille (cachille)
  9. Project:
  10. Internet Services Setup
  11. Revision History:
  12. June 2001: Created
  13. --*/
  14. #include "stdafx.h"
  15. #include "iadm.h"
  16. #include "iiscnfgp.h"
  17. #include "mdkey.h"
  18. #include "mdentry.h"
  19. #include "metabase.hxx"
  20. #include "iiscnfg.h"
  21. #include "strfn.h"
  22. // function: GetSizeBasedOnMetaType
  23. //
  24. // Returns the DataSize for an object based on its type
  25. //
  26. DWORD
  27. CMetaBase::GetSizeBasedOnMetaType(DWORD dwDataType,LPTSTR szString)
  28. {
  29. DWORD dwRet = 0;
  30. switch (dwDataType)
  31. {
  32. case DWORD_METADATA:
  33. dwRet = 4;
  34. break;
  35. case STRING_METADATA:
  36. case EXPANDSZ_METADATA:
  37. if (szString == NULL)
  38. {
  39. dwRet = 0;
  40. }
  41. else
  42. {
  43. dwRet = (_tcslen((LPTSTR)szString) + 1) * sizeof(TCHAR);
  44. }
  45. break;
  46. case MULTISZ_METADATA:
  47. if (szString == NULL)
  48. {
  49. dwRet = 0;
  50. }
  51. else
  52. {
  53. dwRet = GetMultiStrSize((LPTSTR)szString) * sizeof(TCHAR);
  54. }
  55. break;
  56. case BINARY_METADATA:
  57. break;
  58. }
  59. return dwRet;
  60. }
  61. // function: FindStringinMultiSz
  62. //
  63. // Finds a string inside of a MultiSz
  64. //
  65. // Parameters:
  66. // szMultiSz - The MultiSz to search
  67. // szSearchString - The String to find
  68. //
  69. // Return:
  70. // True - It was found
  71. // False - It was not found
  72. BOOL
  73. CMetaBase::FindStringinMultiSz(LPTSTR szMultiSz, LPTSTR szSearchString)
  74. {
  75. LPTSTR szSearchCurrent;
  76. do
  77. {
  78. szSearchCurrent = szSearchString;
  79. while ( ( *szMultiSz != '\0' ) &&
  80. ( *szSearchCurrent != '\0' ) &&
  81. ( *szMultiSz == *szSearchCurrent ))
  82. {
  83. // While the strings are the same, and they do not hit a null terminator
  84. szMultiSz++;
  85. szSearchCurrent++;
  86. }
  87. if ( ( *szMultiSz == '\0' ) &&
  88. ( *szMultiSz == *szSearchCurrent )
  89. )
  90. {
  91. // The strings matched
  92. return TRUE;
  93. }
  94. while ( *szMultiSz != '\0' )
  95. {
  96. // Go to the end of this string
  97. szMultiSz++;
  98. }
  99. // Step right past the string terminator
  100. szMultiSz++;
  101. } while (*szMultiSz);
  102. return FALSE;
  103. }
  104. // function: VerifyParameters
  105. //
  106. // Verify the parameters are correct
  107. //
  108. BOOL
  109. CMetaBase_SetValue::VerifyParameters(CItemList &ciParams)
  110. {
  111. if ( ( ( ciParams.GetNumberOfItems() == 7 ) ||
  112. ( ( ciParams.GetNumberOfItems() == 8 ) && ciParams.IsNumber(7) )
  113. )
  114. &&
  115. ciParams.IsNumber(1) &&
  116. ciParams.IsNumber(2) &&
  117. ciParams.IsNumber(3) &&
  118. ciParams.IsNumber(4) &&
  119. ciParams.IsNumber(5)
  120. )
  121. {
  122. return TRUE;
  123. }
  124. return FALSE;
  125. }
  126. // funtion: DoInternalWork
  127. //
  128. // Set a value in the metabase
  129. //
  130. // Parameters:
  131. // ciList - Parameters for OpenNode, they are the following:
  132. // 0 -Location
  133. // 1- Id
  134. // 2- Inheritable
  135. // 3- UserType
  136. // 4- DataType
  137. // 5- Len
  138. // 6- Value
  139. // 7- bDontReplace - Should we replace the value if one already exists? (default==false)
  140. BOOL
  141. CMetaBase_SetValue::DoInternalWork(CItemList &ciParams)
  142. {
  143. CMDKey cmdKey;
  144. CMDValue cmdMetaValue;
  145. DWORD dwSize = ciParams.GetNumber(5);
  146. BOOL bRet = TRUE;
  147. if ( FAILED(cmdKey.OpenNode(ciParams.GetItem(0) ) ) )
  148. {
  149. // Could not open the key, so we fail
  150. return FALSE;
  151. }
  152. if (dwSize == 0)
  153. {
  154. dwSize = GetSizeBasedOnMetaType(ciParams.GetNumber(4),ciParams.GetItem(6));
  155. }
  156. if ( ( ciParams.GetNumberOfItems() == 8 ) && ( ciParams.GetNumber(7) == 1 ) )
  157. {
  158. // Make sure the value does not exist yet, because we don't want to replace the old one
  159. bRet = !cmdKey.GetData( cmdMetaValue, ciParams.GetNumber(1) );
  160. }
  161. if ( bRet )
  162. {
  163. // Set the value for this node
  164. cmdMetaValue.SetValue(ciParams.GetNumber(1),
  165. ciParams.GetNumber(2),
  166. ciParams.GetNumber(3),
  167. ciParams.GetNumber(4),
  168. dwSize,
  169. (LPTSTR) ciParams.GetItem(6));
  170. bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
  171. }
  172. cmdKey.Close();
  173. return bRet;
  174. }
  175. // function: GetMethodName
  176. //
  177. // Return the Method Name for this Class
  178. //
  179. LPTSTR
  180. CMetaBase_SetValue::GetMethodName()
  181. {
  182. return _T("Metabase_SetValue");
  183. }
  184. // function: VerifyParameters
  185. //
  186. // Verify the parameters are correct
  187. //
  188. BOOL
  189. CMetaBase_DelIDOnEverySite::VerifyParameters(CItemList &ciParams)
  190. {
  191. if ( ( ciParams.GetNumberOfItems() == 2 ) &&
  192. ciParams.IsNumber(0) &&
  193. ciParams.IsNumber(1)
  194. )
  195. {
  196. return TRUE;
  197. }
  198. return FALSE;
  199. }
  200. // funtion: DoInternalWork
  201. //
  202. // Set a value in the metabase
  203. //
  204. // Parameters:
  205. // ciList - Parameters for OpenNode, they are the following:
  206. // 0 - Id
  207. // 1 - Metabase Data Type
  208. BOOL
  209. CMetaBase_DelIDOnEverySite::DoInternalWork(CItemList &ciParams)
  210. {
  211. CMDKey cmdKey;
  212. DWORD dwId = ciParams.GetNumber(0);
  213. DWORD dwType = ciParams.GetNumber(1);
  214. BOOL bRet;
  215. CStringList cslpathList;
  216. POSITION pos;
  217. CString csPath;
  218. WCHAR wchKeyPath[_MAX_PATH];
  219. LPWSTR szwKeyPath = wchKeyPath;
  220. CString csBasePath = _T("LM/W3SVC");
  221. if ( FAILED( cmdKey.OpenNode( csBasePath ) ) )
  222. {
  223. // Could not open the key, so we fail
  224. return FALSE;
  225. }
  226. // get datapaths on the specified ID.
  227. if (FAILED( cmdKey.GetDataPaths( dwId, dwType, cslpathList) ))
  228. {
  229. // Could not GetDataPaths for this value
  230. return FALSE;
  231. }
  232. // close it so that we can open the various
  233. // other nodes that returned and delete the values from them
  234. cmdKey.Close();
  235. pos = cslpathList.GetHeadPosition();
  236. while ( NULL != pos )
  237. {
  238. bRet = TRUE;
  239. csPath = cslpathList.GetNext( pos );
  240. //iisDebugOut((LOG_TYPE_TRACE,_T("%s"),csPath));
  241. #if defined(UNICODE) || defined(_UNICODE)
  242. szwKeyPath = csPath.GetBuffer(0);
  243. #else
  244. if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)csPath.GetBuffer(0), -1, (LPWSTR)wchKeyPath, _MAX_PATH)==0)
  245. {
  246. // We could not convert the string to wide, so lets skip this one
  247. continue;
  248. }
  249. #endif
  250. // make a special case of the "/" path
  251. if ( wcscmp( szwKeyPath, L"/" ) != 0 )
  252. {
  253. //iisDebugOut((LOG_TYPE_TRACE,_T("%s -- del"),csPath));
  254. CString csNewPath;
  255. csNewPath = csBasePath + szwKeyPath;
  256. if ( SUCCEEDED(cmdKey.OpenNode(csNewPath) ) )
  257. {
  258. if ( FAILED(cmdKey.DeleteData(dwId, dwType) ) )
  259. {
  260. // i guess we don't need to report it..
  261. }
  262. cmdKey.Close();
  263. }
  264. }
  265. }
  266. return bRet;
  267. }
  268. // function: GetMethodName
  269. //
  270. // Return the Method Name for this Class
  271. //
  272. LPTSTR
  273. CMetaBase_DelIDOnEverySite::GetMethodName()
  274. {
  275. return _T("CMetaBase_DelIDOnEverySite");
  276. }
  277. // function: VerifyParameters
  278. //
  279. // Verify the parameters are correct
  280. //
  281. BOOL
  282. CMetaBase_IsAnotherSiteonPort80::VerifyParameters(CItemList &ciParams)
  283. {
  284. return ( ciParams.GetNumberOfItems() == 0 );
  285. }
  286. // function: FindSiteUsing80
  287. //
  288. // Find a Site that is using port80
  289. //
  290. // Parameters:
  291. // cmdKey - The key to the metabase node
  292. // dwId - The id of the item to find.
  293. //
  294. // Return
  295. // TRUE - It has been found
  296. // FALSE - It has not been found
  297. BOOL
  298. CMetaBase_IsAnotherSiteonPort80::SearchMultiSzforPort80(CMDKey &cmdKey, DWORD dwId)
  299. {
  300. CStringList cslpathList;
  301. POSITION pos;
  302. CString csPath;
  303. CMDValue cmdValue;
  304. WCHAR wchKeyPath[_MAX_PATH];
  305. LPWSTR szwKeyPath = wchKeyPath;
  306. if (FAILED( cmdKey.GetDataPaths( dwId, MULTISZ_METADATA, cslpathList) ))
  307. {
  308. // Could not GetDataPaths for this value
  309. return FALSE;
  310. }
  311. pos = cslpathList.GetHeadPosition();
  312. while ( NULL != pos )
  313. {
  314. csPath = cslpathList.GetNext( pos );
  315. #if defined(UNICODE) || defined(_UNICODE)
  316. szwKeyPath = csPath.GetBuffer(0);
  317. #else
  318. if (MultiByteToWideChar(CP_ACP, 0, (LPCSTR)csPath.GetBuffer(0), -1, (LPWSTR)wchKeyPath, _MAX_PATH)==0)
  319. {
  320. // We could not convert the string to wide, so lets skip this one
  321. continue;
  322. }
  323. #endif
  324. if ( ( wcscmp( szwKeyPath, L"/1/" ) != 0 ) &&
  325. ( cmdKey.GetData( cmdValue, dwId, szwKeyPath ) ) &&
  326. ( cmdValue.GetDataType() == MULTISZ_METADATA ) &&
  327. ( FindStringinMultiSz( (LPTSTR) cmdValue.GetData(), _T(":80:") ) )
  328. )
  329. {
  330. if ( ( !cmdKey.GetData( cmdValue, MD_SERVER_AUTOSTART, szwKeyPath ) ) ||
  331. ( !cmdValue.IsEqual( DWORD_METADATA, 4, (DWORD) 0 ) )
  332. )
  333. {
  334. // If GetData failed, or it succedded and the value is not 0, then we
  335. // have found a match.
  336. return TRUE;
  337. break;
  338. }
  339. }
  340. }
  341. return FALSE;
  342. }
  343. // function: IsAnotherSiteonPort80
  344. //
  345. // Reports back whether another site besides /W3SVC/1 is configured to bind to port 80
  346. // AND has AutoStart set to True
  347. //
  348. // Parameters
  349. // None
  350. //
  351. // Return
  352. // TRUE - Another site is running on port 80
  353. // FALSE - No other site is running on port 80
  354. BOOL
  355. CMetaBase_IsAnotherSiteonPort80::DoInternalWork(CItemList &ciList)
  356. {
  357. BOOL bRet = FALSE;
  358. CMDKey cmdKey;
  359. if ( FAILED( cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
  360. {
  361. // Could not open the w3svc node
  362. return FALSE;
  363. }
  364. if ( SearchMultiSzforPort80( cmdKey, MD_SERVER_BINDINGS) ||
  365. SearchMultiSzforPort80( cmdKey, MD_SECURE_BINDINGS)
  366. )
  367. {
  368. bRet = TRUE;
  369. }
  370. cmdKey.Close();
  371. return bRet;
  372. }
  373. // function: GetMethodName
  374. //
  375. // Return the Method Name for this Class
  376. //
  377. LPTSTR
  378. CMetaBase_IsAnotherSiteonPort80::GetMethodName()
  379. {
  380. return _T("Metabase_IsAnotherSiteonPort80");
  381. }
  382. // function: VerifyParameters
  383. //
  384. // Verify the parameters are correct
  385. //
  386. BOOL
  387. CMetaBase_VerifyValue::VerifyParameters(CItemList &ciParams)
  388. {
  389. if ( ( ciParams.GetNumberOfItems() == 5 ) &&
  390. ciParams.IsNumber(1) &&
  391. ciParams.IsNumber(2)
  392. )
  393. {
  394. return TRUE;
  395. }
  396. return FALSE;
  397. }
  398. // function: GetMethodName
  399. //
  400. // Return the Method Name for this Class
  401. //
  402. LPTSTR
  403. CMetaBase_VerifyValue::GetMethodName()
  404. {
  405. return _T("Metabase_VerifyValue");
  406. }
  407. // function: VerifyValue::DoWork
  408. //
  409. // Verify that the value in the particular metabase location, matches the
  410. // value in param[4]. If it does, return true.
  411. //
  412. // Parameters
  413. // 0 - Metabase Location
  414. // 1 - Metabase Id
  415. // 2 - Metabase Data Type
  416. // 3 - Data Length = 0 (default value is 0 (must calculate))
  417. // 4 - Metabase Value
  418. //
  419. // Return
  420. // TRUE - The values match
  421. // FALSE - The values do not match
  422. BOOL
  423. CMetaBase_VerifyValue::DoInternalWork(CItemList &ciList)
  424. {
  425. CMDKey cmdKey;
  426. CMDValue cmdValue;
  427. DWORD dwSize = ciList.GetNumber(3);
  428. BOOL bRet = FALSE;
  429. if ( FAILED( cmdKey.OpenNode( ciList.GetItem(0) ) ) )
  430. {
  431. // Could not open the w3svc node
  432. return FALSE;
  433. }
  434. if (dwSize == 0)
  435. {
  436. dwSize = GetSizeBasedOnMetaType(ciList.GetNumber(2),ciList.GetItem(4));
  437. }
  438. if ( cmdKey.GetData( cmdValue, ciList.GetNumber(1) ) )
  439. {
  440. if ( ( ( ciList.GetNumber(2) == DWORD_METADATA ) &&
  441. ( cmdValue.IsEqual( ciList.GetNumber(2), dwSize, (DWORD) ciList.GetNumber(4) ) )
  442. ) ||
  443. ( ( ciList.GetNumber(2) != DWORD_METADATA ) &&
  444. ( cmdValue.IsEqual( ciList.GetNumber(2), dwSize, (LPVOID) ciList.GetItem(4) ) )
  445. )
  446. )
  447. {
  448. bRet = TRUE;
  449. }
  450. }
  451. cmdKey.Close();
  452. return bRet;
  453. }
  454. // function: GetMethodName
  455. //
  456. // Return the Method Name for this Class
  457. //
  458. LPTSTR
  459. CMetaBase_ImportRestrictionList::GetMethodName()
  460. {
  461. return _T("Metabase_ImportRestrictionList");
  462. }
  463. // function: VerifyParameters
  464. //
  465. // Verify the parameters are correct
  466. //
  467. BOOL
  468. CMetaBase_ImportRestrictionList::VerifyParameters(CItemList &ciParams)
  469. {
  470. return ( (ciParams.GetNumberOfItems() == 3) &&
  471. ( ciParams.IsNumber(1) )
  472. );
  473. }
  474. // function: CreateMultiSzFromList
  475. //
  476. // Create a MultiSz from a List of comman delim items. So, take
  477. // <deny/allow>,<CGI Executable>,<CGI Executable>,... (ie. "0","c:\inetpub\scripts\mycgi.exe","c:\inetpub\scripts\pagecount.exe")
  478. // and convert to
  479. // <0/1>\0<CGI Executable>\0<CGI Executable>\0\0 (ie. 0\0c:\inetpub\scripts\mycgi.exe\0c:\inetpub\scripts\pagecount.exe\0\0)
  480. //
  481. // Parameters:
  482. // pBuff [out] - BUFFER class that is used to store the multisz
  483. // pdwRetSize [out] - The size of the multisz that was created (in Bytes, not chars)
  484. // szItems [in] - List of Items to put in MultiSz
  485. // cDelimeter [in[ - The delimeter for the list
  486. //
  487. // Return Values
  488. // TRUE - Successfull
  489. // FALSE - It failed to construct MultiSz
  490. BOOL
  491. CMetaBase_ImportRestrictionList::CreateMultiSzFromList(BUFFER *pBuff, DWORD *pdwRetSize, LPTSTR szItems, TCHAR cDelimeter)
  492. {
  493. LPTSTR szSource;
  494. LPTSTR szDest;
  495. BOOL bInQuotes = FALSE;
  496. // Fail if we don't have a string, or can not get a big enought buffer
  497. if ( ( !szItems ) ||
  498. ( !pBuff->Resize( ( _tcslen( szItems ) + 2 ) * sizeof(TCHAR) ) ) // Add 2, one for string term, and one for multisz term
  499. )
  500. {
  501. return FALSE;
  502. }
  503. szSource = szItems;
  504. szDest = (LPTSTR) pBuff->QueryPtr();
  505. while ( *szSource )
  506. {
  507. if ( *szSource == '"' )
  508. {
  509. bInQuotes = !bInQuotes;
  510. }
  511. else if ( ( *szSource == cDelimeter ) && !bInQuotes )
  512. {
  513. if ( ( szDest != pBuff->QueryPtr() ) &&
  514. ( *(szDest - 1) != '\0')
  515. )
  516. {
  517. *szDest = '\0';
  518. szDest++;
  519. }
  520. }
  521. else
  522. {
  523. *szDest = *szSource;
  524. szDest++;
  525. }
  526. szSource++;
  527. }
  528. // Lets make sure that the last string was terminated.
  529. if ( ( szDest != pBuff->QueryPtr() ) &&
  530. ( *(szDest - 1) != '\0')
  531. )
  532. {
  533. // Terminate last string
  534. *szDest = '\0';
  535. szDest++;
  536. }
  537. // Terminate MultiSz, and calc length
  538. *szDest++ = '\0';
  539. *pdwRetSize = (DWORD) (DWORD_PTR) (((LPBYTE) szDest) - ((LPBYTE) pBuff->QueryPtr()));
  540. return TRUE;
  541. }
  542. BOOL
  543. CMetaBase_ImportRestrictionList::ExpandEnvVar(BUFFER *pBuff)
  544. {
  545. BUFFER buffOriginal;
  546. DWORD dwLength;
  547. if ( _tcsstr( (LPTSTR) pBuff->QueryPtr(), _T("%") ) == NULL )
  548. {
  549. // There are no environment variables, so we can return
  550. return TRUE;
  551. }
  552. if ( !buffOriginal.Resize( pBuff->QuerySize() ) )
  553. {
  554. // Could not resize oringal big enough
  555. return FALSE;
  556. }
  557. memcpy(buffOriginal.QueryPtr(), pBuff->QueryPtr(), pBuff->QuerySize());
  558. dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), NULL, 0);
  559. if ( ( dwLength == 0 ) ||
  560. ( !pBuff->Resize( dwLength * sizeof(TCHAR) ) )
  561. )
  562. {
  563. // Something failed in ExpandEnvironmentStrings
  564. return FALSE;
  565. }
  566. dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), (LPTSTR) pBuff->QueryPtr() , pBuff->QuerySize() );
  567. if ( (dwLength != 0) && (dwLength <= pBuff->QuerySize() ) )
  568. {
  569. // It worked
  570. return TRUE;
  571. }
  572. return FALSE;
  573. }
  574. // function: DoInternalWork
  575. //
  576. // Import the RestrictionList
  577. //
  578. // Parameters:
  579. // 0 - The name of the item in the inf
  580. // 1 - The id
  581. // 2 - The Default value (MultiSz with ';' as seperator)
  582. //
  583. BOOL
  584. CMetaBase_ImportRestrictionList::DoInternalWork(CItemList &ciParams)
  585. {
  586. CMDKey cmdKey;
  587. CMDValue cmdMetaValue;
  588. BUFFER buffImportList;
  589. DWORD dwImportList;
  590. LPTSTR szList = NULL;
  591. INFCONTEXT Context;
  592. BOOL bRet = FALSE;
  593. BOOL bForceSetting = FALSE;
  594. if (g_pTheApp->m_fUnattended)
  595. {
  596. // If unattended, then look in unattend file for correct line
  597. if ( SetupFindFirstLine_Wrapped(g_pTheApp->m_hUnattendFile, UNATTEND_FILE_SECTION, ciParams.GetItem(0), &Context) )
  598. {
  599. DWORD dwRequiredSize = 0;
  600. BUFFER buffUnattend;
  601. BUFFER buffUnattendExpanded;
  602. if ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, NULL, 0, &dwRequiredSize) )
  603. {
  604. if ( ( buffUnattend.Resize( ( dwRequiredSize + 1 ) * sizeof(TCHAR) ) ) &&
  605. ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, (LPTSTR) buffUnattend.QueryPtr(), buffUnattend.QuerySize()/sizeof(TCHAR), NULL) ) &&
  606. ( ExpandEnvVar( &buffUnattend ) ) &&
  607. ( CreateMultiSzFromList( &buffImportList, &dwImportList, (LPTSTR) buffUnattend.QueryPtr(), RESTRICTIONLIST_DELIMITER ) )
  608. )
  609. {
  610. szList = (LPTSTR) buffImportList.QueryPtr();
  611. bForceSetting = TRUE;
  612. }
  613. }
  614. }
  615. }
  616. if ( !szList )
  617. {
  618. // If it could not be retrieved, set it to the default.
  619. if ( ( buffImportList.Resize(( _tcslen( ciParams.GetItem(2) ) + 2 ) * sizeof(TCHAR) ) ) &&
  620. ( CreateMultiSzFromList( &buffImportList, &dwImportList, ciParams.GetItem(2), RESTRICTIONLIST_DELIMITER) )
  621. )
  622. {
  623. szList = (LPTSTR) buffImportList.QueryPtr();
  624. }
  625. }
  626. if ( szList == NULL )
  627. {
  628. return FALSE;
  629. }
  630. // Set Value
  631. if ( FAILED(cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
  632. {
  633. // Could not open the key, so we fail
  634. return FALSE;
  635. }
  636. if ( bForceSetting ||
  637. !cmdKey.GetData(cmdMetaValue, ciParams.GetNumber(1) )
  638. )
  639. {
  640. // Set the value for this node
  641. if ( cmdMetaValue.SetValue( ciParams.GetNumber(1), // ID
  642. 0x0, // Attributes (Not inheritable)
  643. IIS_MD_UT_SERVER, // UType
  644. MULTISZ_METADATA, // DType
  645. dwImportList, // Size
  646. (LPTSTR) szList)
  647. )
  648. {
  649. bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
  650. }
  651. }
  652. cmdKey.Close();
  653. return bRet;
  654. }
  655. // function: GetMethodName
  656. //
  657. // Return the Method Name for this Class
  658. //
  659. LPTSTR
  660. CMetaBase_UpdateCustomDescList::GetMethodName()
  661. {
  662. return _T("Metabase_UpdateCustomDescList");
  663. }
  664. // function: VerifyParameters
  665. //
  666. // Verify the parameters are correct
  667. //
  668. BOOL
  669. CMetaBase_UpdateCustomDescList::VerifyParameters(CItemList &ciParams)
  670. {
  671. return ( (ciParams.GetNumberOfItems() == 3) &&
  672. ( ciParams.IsNumber(1) )
  673. );
  674. }
  675. // function: CreateMultiSzFromList
  676. //
  677. // Create a MultiSz from a List of comman delim items. So, take
  678. // <deleteable/not deleteable>,<description>,<filepath>,... (ie. "1","asp scripts","c:\winnt\system32\inetsrv\asp.dll")
  679. // and convert to
  680. // <0/1>\0<description>\0<filepath>\0\0 (ie. 1\0asp scripts\0c:\winnt\system32\inetsrv\asp.dll\0\0)
  681. //
  682. // Parameters:
  683. // pBuff [out] - BUFFER class that is used to store the multisz
  684. // pdwRetSize [out] - The size of the multisz that was created (in Bytes, not chars)
  685. // szItems [in] - List of Items to put in MultiSz
  686. // cDelimeter [in[ - The delimeter for the list
  687. //
  688. // Return Values
  689. // TRUE - Successfull
  690. // FALSE - It failed to construct MultiSz
  691. BOOL
  692. CMetaBase_UpdateCustomDescList::CreateMultiSzFromList(BUFFER *pBuff, DWORD *pdwRetSize, LPTSTR szItems, TCHAR cDelimeter)
  693. {
  694. LPTSTR szSource;
  695. LPTSTR szDest;
  696. BOOL bInQuotes = FALSE;
  697. // Fail if we don't have a string, or can not get a big enought buffer
  698. if ( ( !szItems ) ||
  699. ( !pBuff->Resize( ( _tcslen( szItems ) + 2 ) * sizeof(TCHAR) ) ) // Add 2, one for string term, and one for multisz term
  700. )
  701. {
  702. return FALSE;
  703. }
  704. szSource = szItems;
  705. szDest = (LPTSTR) pBuff->QueryPtr();
  706. while ( *szSource )
  707. {
  708. if ( *szSource == '"' )
  709. {
  710. bInQuotes = !bInQuotes;
  711. }
  712. else if ( ( *szSource == cDelimeter ) && !bInQuotes )
  713. {
  714. if ( ( szDest != pBuff->QueryPtr() ) &&
  715. ( *(szDest - 1) != '\0')
  716. )
  717. {
  718. *szDest = '\0';
  719. szDest++;
  720. }
  721. }
  722. else
  723. {
  724. *szDest = *szSource;
  725. szDest++;
  726. }
  727. szSource++;
  728. }
  729. // Lets make sure that the last string was terminated.
  730. if ( ( szDest != pBuff->QueryPtr() ) &&
  731. ( *(szDest - 1) != '\0')
  732. )
  733. {
  734. // Terminate last string
  735. *szDest = '\0';
  736. szDest++;
  737. }
  738. // Terminate MultiSz, and calc length
  739. *szDest++ = '\0';
  740. *pdwRetSize = (DWORD) (DWORD_PTR) (((LPBYTE) szDest) - ((LPBYTE) pBuff->QueryPtr()));
  741. return TRUE;
  742. }
  743. BOOL
  744. CMetaBase_UpdateCustomDescList::ExpandEnvVar(BUFFER *pBuff)
  745. {
  746. BUFFER buffOriginal;
  747. DWORD dwLength;
  748. if ( _tcsstr( (LPTSTR) pBuff->QueryPtr(), _T("%") ) == NULL )
  749. {
  750. // There are no environment variables, so we can return
  751. return TRUE;
  752. }
  753. if ( !buffOriginal.Resize( pBuff->QuerySize() ) )
  754. {
  755. // Could not resize oringal big enough
  756. return FALSE;
  757. }
  758. memcpy(buffOriginal.QueryPtr(), pBuff->QueryPtr(), pBuff->QuerySize());
  759. dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), NULL, 0);
  760. if ( ( dwLength == 0 ) ||
  761. ( !pBuff->Resize( dwLength * sizeof(TCHAR) ) )
  762. )
  763. {
  764. // Something failed in ExpandEnvironmentStrings
  765. return FALSE;
  766. }
  767. dwLength = ExpandEnvironmentStrings( (LPTSTR) buffOriginal.QueryPtr(), (LPTSTR) pBuff->QueryPtr() , pBuff->QuerySize()/sizeof(TCHAR) );
  768. if ( (dwLength != 0) &&
  769. (dwLength <= ( pBuff->QuerySize()/sizeof(TCHAR) ) ) )
  770. {
  771. // It worked
  772. return TRUE;
  773. }
  774. return FALSE;
  775. }
  776. // function: DoInternalWork
  777. //
  778. // Import the RestrictionList
  779. //
  780. // Parameters:
  781. // 0 - The name of the item in the inf
  782. // 1 - The id
  783. // 2 - The Default value (MultiSz with ';' as seperator)
  784. //
  785. BOOL
  786. CMetaBase_UpdateCustomDescList::DoInternalWork(CItemList &ciParams)
  787. {
  788. CMDKey cmdKey;
  789. CMDValue cmdMetaValue;
  790. BUFFER buffMyList;
  791. DWORD dwMyList;
  792. LPTSTR szList = NULL;
  793. INFCONTEXT Context;
  794. BOOL bRet = FALSE;
  795. BOOL bForceSetting = FALSE;
  796. if (g_pTheApp->m_fUnattended)
  797. {
  798. // If unattended, then look in unattend file for correct line
  799. if ( SetupFindFirstLine_Wrapped(g_pTheApp->m_hUnattendFile, UNATTEND_FILE_SECTION, ciParams.GetItem(0), &Context) )
  800. {
  801. DWORD dwRequiredSize = 0;
  802. BUFFER buffUnattend;
  803. BUFFER buffUnattendExpanded;
  804. if ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, NULL, 0, &dwRequiredSize) )
  805. {
  806. if ( ( buffUnattend.Resize( ( dwRequiredSize + 1 ) * sizeof(TCHAR) ) ) &&
  807. ( SetupGetLineText( &Context, INVALID_HANDLE_VALUE, NULL, NULL, (LPTSTR) buffUnattend.QueryPtr(), buffUnattend.QuerySize()/sizeof(TCHAR), NULL) ) &&
  808. ( ExpandEnvVar( &buffUnattend ) ) &&
  809. ( CreateMultiSzFromList( &buffMyList, &dwMyList, (LPTSTR) buffUnattend.QueryPtr(), CUSTOMDESCLIST_DELIMITER ) )
  810. )
  811. {
  812. szList = (LPTSTR) buffMyList.QueryPtr();
  813. bForceSetting = TRUE;
  814. }
  815. }
  816. }
  817. }
  818. if ( !szList )
  819. {
  820. // If it could not be retrieved, set it to the default.
  821. if ( ( buffMyList.Resize(( _tcslen( ciParams.GetItem(2) ) + 2 ) * sizeof(TCHAR) ) ) &&
  822. ( CreateMultiSzFromList( &buffMyList, &dwMyList, ciParams.GetItem(2), CUSTOMDESCLIST_DELIMITER) )
  823. )
  824. {
  825. szList = (LPTSTR) buffMyList.QueryPtr();
  826. }
  827. }
  828. if ( szList == NULL )
  829. {
  830. return FALSE;
  831. }
  832. // Set Value
  833. if ( FAILED(cmdKey.OpenNode( _T("LM/W3SVC") ) ) )
  834. {
  835. // Could not open the key, so we fail
  836. return FALSE;
  837. }
  838. // See if there is an existing value...
  839. // if there is then update the value with this one...
  840. // otherwise set it.
  841. CStringList cslMyNewAdditions;
  842. if (ERROR_SUCCESS != ConvertDoubleNullListToStringList(szList,cslMyNewAdditions,-1))
  843. {
  844. bForceSetting = TRUE;
  845. }
  846. // get the data
  847. DWORD dwAttributes = 0;
  848. DWORD dwMDDataType = MULTISZ_METADATA;
  849. CStringList cslMyOriginalList;
  850. if (bForceSetting || FAILED(cmdKey.GetMultiSzAsStringList(ciParams.GetNumber(1),&dwMDDataType,&dwAttributes,cslMyOriginalList)))
  851. {
  852. // do a fresh entry...
  853. // Set the value for this node
  854. if ( cmdMetaValue.SetValue(ciParams.GetNumber(1), // ID
  855. 0x0, // Attributes (Not inheritable)
  856. IIS_MD_UT_SERVER, // UType
  857. MULTISZ_METADATA, // DType
  858. dwMyList, // Size
  859. (LPTSTR) szList)
  860. )
  861. {
  862. bRet = cmdKey.SetData(cmdMetaValue, ciParams.GetNumber(1));
  863. }
  864. }
  865. else
  866. {
  867. // able to get it...so let's update it.
  868. // loop thru it and see if our entry is already in it...
  869. CString csNewEntryPart1;
  870. CString csNewEntryPart2;
  871. CString csNewEntryPart3;
  872. CString csExistingFilePath;
  873. BOOL bItsInTheListAlready = FALSE;
  874. BOOL bSomethingChanged = FALSE;
  875. POSITION pos = cslMyNewAdditions.GetHeadPosition();
  876. POSITION pos2 = NULL;
  877. while (pos)
  878. {
  879. bItsInTheListAlready = FALSE;
  880. // get the next value
  881. csNewEntryPart1 = cslMyNewAdditions.GetNext(pos);
  882. if (!pos){break;}
  883. csNewEntryPart2 = cslMyNewAdditions.GetNext(pos);
  884. if (!pos){break;}
  885. csNewEntryPart3 = cslMyNewAdditions.GetNext(pos);
  886. // see if this value is in our list...
  887. pos2 = cslMyOriginalList.GetHeadPosition();
  888. while (pos2)
  889. {
  890. // get the next value
  891. cslMyOriginalList.GetNext(pos2);
  892. if (!pos2){break;}
  893. csExistingFilePath = cslMyOriginalList.GetNext(pos2);
  894. if (!pos2){break;}
  895. // compare with other value
  896. //iisDebugOut((LOG_TYPE_TRACE,_T("UpdateCustomDescList:%s,%s"),csNewEntryPart2,csExistingFilePath));
  897. if (0 == _tcsicmp(csNewEntryPart2,csExistingFilePath))
  898. {
  899. // it's found in there!
  900. bItsInTheListAlready = TRUE;
  901. break;
  902. }
  903. cslMyOriginalList.GetNext(pos2);
  904. }
  905. if (FALSE == bItsInTheListAlready)
  906. {
  907. // Add it to the end of the list
  908. cslMyOriginalList.AddTail(csNewEntryPart1);
  909. cslMyOriginalList.AddTail(csNewEntryPart2);
  910. cslMyOriginalList.AddTail(csNewEntryPart3);
  911. bSomethingChanged = TRUE;
  912. }
  913. }
  914. if (TRUE == bSomethingChanged)
  915. {
  916. bRet = FALSE;
  917. if (ERROR_SUCCESS == cmdKey.SetMultiSzAsStringList(ciParams.GetNumber(1),MULTISZ_METADATA,0x0,cslMyOriginalList))
  918. {
  919. bRet = TRUE;
  920. }
  921. }
  922. }
  923. cmdKey.Close();
  924. return bRet;
  925. }