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.

2151 lines
66 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. setup.cpp
  5. Abstract:
  6. Setup code called from regsvr32
  7. --*/
  8. #include "precomp.h"
  9. #include <setupapi.h>
  10. const DWORD CONFIG_BUFFER_MAX = 4096;
  11. BSTR g_PropertyBSTR = NULL;
  12. BSTR g_SyntaxBSTR = NULL;
  13. BSTR g_UserTypeBSTR = NULL;
  14. BSTR g_InheritBSTR = NULL;
  15. BSTR g_ClassBSTR = NULL;
  16. BSTR g_IsapiRestrictionListBSTR = NULL;
  17. BSTR g_RestrictionListCustomDescBSTR = NULL;
  18. BSTR g_FilterLoadOrderBSTR = NULL;
  19. BSTR g_IIsFilterBSTR = NULL;
  20. BSTR g_InProcessIsapiAppsBSTR = NULL;
  21. BSTR g_bitsserverBSTR = NULL;
  22. BSTR g_bitserverBSTR = NULL;
  23. BSTR g_MetaIDBSTR = NULL;
  24. BSTR g_WebSvcExtRestrictionListBSTR = NULL;
  25. WCHAR g_ISAPIPath[ MAX_PATH ];
  26. WCHAR g_ExtensionNameString[ MAX_PATH ];
  27. void
  28. LogSetup(
  29. LogSeverity Severity,
  30. PCTSTR Format,
  31. ...)
  32. {
  33. va_list arglist;
  34. va_start( arglist, Format );
  35. CHAR Buffer[256];
  36. StringCchVPrintfA(
  37. Buffer,
  38. sizeof(Buffer) - 1,
  39. Format, arglist );
  40. SetupLogError( Buffer, Severity );
  41. }
  42. BOOL g_IsWindowsXP = FALSE;
  43. void
  44. DetectProductVersion()
  45. {
  46. OSVERSIONINFO VersionInfo;
  47. VersionInfo.dwOSVersionInfoSize = sizeof( VersionInfo );
  48. LogSetup( LogSevInformation, "[BITSSRV] Detecting product version\r\n" );
  49. if ( !GetVersionEx( &VersionInfo ) )
  50. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  51. switch( VersionInfo.dwPlatformId )
  52. {
  53. case VER_PLATFORM_WIN32_NT:
  54. if ( VersionInfo.dwMajorVersion < 5 )
  55. {
  56. LogSetup( LogSevFatalError, "[BITSSRV] Unsupported platform\r\n" );
  57. THROW_COMERROR( E_FAIL );
  58. }
  59. if ( VersionInfo.dwMajorVersion > 5 )
  60. {
  61. g_IsWindowsXP = TRUE;;
  62. return;
  63. }
  64. g_IsWindowsXP = ( VersionInfo.dwMinorVersion > 0 );
  65. return;
  66. default:
  67. LogSetup( LogSevFatalError, "[BITSSRV] Unsupported platform\r\n" );
  68. THROW_COMERROR( E_FAIL );
  69. }
  70. }
  71. void
  72. InitializeSetup()
  73. {
  74. LogSetup( LogSevInformation, "[BITSSRV] Starting Initialization of strings\r\n" );
  75. g_PropertyBSTR = SysAllocString( L"Property" );
  76. g_SyntaxBSTR = SysAllocString( L"Syntax" );
  77. g_UserTypeBSTR = SysAllocString( L"UserType" );
  78. g_InheritBSTR = SysAllocString( L"Inherit" );
  79. g_ClassBSTR = SysAllocString( L"Class" );
  80. g_IsapiRestrictionListBSTR = SysAllocString( L"IsapiRestrictionList" );
  81. g_RestrictionListCustomDescBSTR = SysAllocString( L"RestrictionListCustomDesc" );
  82. g_FilterLoadOrderBSTR = SysAllocString( L"FilterLoadOrder" );
  83. g_IIsFilterBSTR = SysAllocString( L"IIsFilter" );
  84. g_InProcessIsapiAppsBSTR = SysAllocString( L"InProcessIsapiApps" );
  85. g_bitsserverBSTR = SysAllocString( L"bitsserver" );
  86. g_bitserverBSTR = SysAllocString( L"bitserver" );
  87. g_MetaIDBSTR = SysAllocString( L"MetaId" );
  88. g_WebSvcExtRestrictionListBSTR = SysAllocString( L"WebSvcExtRestrictionList" );
  89. if ( !g_PropertyBSTR || !g_SyntaxBSTR || !g_UserTypeBSTR ||
  90. !g_InheritBSTR | !g_ClassBSTR || !g_IsapiRestrictionListBSTR ||
  91. !g_RestrictionListCustomDescBSTR || !g_FilterLoadOrderBSTR || !g_IIsFilterBSTR ||
  92. !g_InProcessIsapiAppsBSTR || !g_bitsserverBSTR || !g_bitserverBSTR || !g_MetaIDBSTR ||
  93. !g_WebSvcExtRestrictionListBSTR )
  94. {
  95. SysFreeString( g_PropertyBSTR );
  96. SysFreeString( g_SyntaxBSTR );
  97. SysFreeString( g_UserTypeBSTR );
  98. SysFreeString( g_InheritBSTR );
  99. SysFreeString( g_ClassBSTR );
  100. SysFreeString( g_IsapiRestrictionListBSTR );
  101. SysFreeString( g_RestrictionListCustomDescBSTR );
  102. SysFreeString( g_FilterLoadOrderBSTR );
  103. SysFreeString( g_IIsFilterBSTR );
  104. SysFreeString( g_InProcessIsapiAppsBSTR );
  105. SysFreeString( g_bitsserverBSTR );
  106. SysFreeString( g_bitserverBSTR );
  107. SysFreeString( g_MetaIDBSTR );
  108. SysFreeString( g_WebSvcExtRestrictionListBSTR );
  109. g_PropertyBSTR = g_SyntaxBSTR = g_UserTypeBSTR =
  110. g_InheritBSTR = g_ClassBSTR = g_IsapiRestrictionListBSTR =
  111. g_RestrictionListCustomDescBSTR = g_FilterLoadOrderBSTR = g_IIsFilterBSTR =
  112. g_InProcessIsapiAppsBSTR = g_bitsserverBSTR = g_bitserverBSTR = g_MetaIDBSTR =
  113. g_WebSvcExtRestrictionListBSTR = NULL;
  114. throw ComError( E_OUTOFMEMORY );
  115. }
  116. DWORD dwRet =
  117. GetModuleFileNameW(
  118. g_hinst,
  119. g_ISAPIPath,
  120. MAX_PATH );
  121. if ( !dwRet )
  122. return THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  123. if (! LoadStringW(
  124. g_hinst,
  125. IDS_EXTENSION_NAME,
  126. g_ExtensionNameString,
  127. MAX_PATH ) )
  128. return THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  129. // ensure termination
  130. g_ExtensionNameString[ MAX_PATH - 1 ] = g_ISAPIPath[ MAX_PATH - 1 ] = L'\0';
  131. }
  132. void
  133. CleanupSetup()
  134. {
  135. LogSetup( LogSevInformation, "[BITSSRV] Starting setup cleanup\r\n" );
  136. SysFreeString( g_PropertyBSTR );
  137. SysFreeString( g_SyntaxBSTR );
  138. SysFreeString( g_UserTypeBSTR );
  139. SysFreeString( g_InheritBSTR );
  140. SysFreeString( g_ClassBSTR );
  141. SysFreeString( g_IsapiRestrictionListBSTR );
  142. SysFreeString( g_RestrictionListCustomDescBSTR );
  143. SysFreeString( g_FilterLoadOrderBSTR );
  144. SysFreeString( g_IIsFilterBSTR );
  145. SysFreeString( g_InProcessIsapiAppsBSTR );
  146. SysFreeString( g_bitsserverBSTR );
  147. SysFreeString( g_bitserverBSTR );
  148. SysFreeString( g_MetaIDBSTR );
  149. SysFreeString( g_WebSvcExtRestrictionListBSTR );
  150. g_PropertyBSTR = g_SyntaxBSTR = g_UserTypeBSTR =
  151. g_InheritBSTR = g_ClassBSTR = g_IsapiRestrictionListBSTR =
  152. g_RestrictionListCustomDescBSTR = g_FilterLoadOrderBSTR = g_IIsFilterBSTR =
  153. g_InProcessIsapiAppsBSTR = g_bitsserverBSTR = g_MetaIDBSTR =
  154. g_WebSvcExtRestrictionListBSTR = NULL;
  155. }
  156. typedef SmartRefPointer<IADs> SmartIADsPointer;
  157. typedef SmartRefPointer<IADsClass> SmartIADsClassPointer;
  158. typedef SmartRefPointer<IADsContainer> SmartIADsContainerPointer;
  159. void RemoveFilterHelper(
  160. WCHAR * Buffer,
  161. const WCHAR * const ToRemove )
  162. {
  163. WCHAR *ToReplace;
  164. SIZE_T FragmentLength = wcslen( ToRemove );
  165. while( ToReplace = wcsstr( Buffer, ToRemove ) )
  166. {
  167. WCHAR *Next = ToReplace + FragmentLength;
  168. memmove( ToReplace, Next, sizeof(WCHAR) * ( wcslen( Next ) + 1 ) );
  169. Buffer = ToReplace;
  170. }
  171. }
  172. DWORD
  173. BITSGetStartupInfoFilter(
  174. DWORD Status )
  175. {
  176. //
  177. // The following exceptions are documented
  178. // to be thrown by GetStartupInfoA
  179. //
  180. switch( Status )
  181. {
  182. case STATUS_NO_MEMORY:
  183. case STATUS_INVALID_PARAMETER_2:
  184. case STATUS_BUFFER_OVERFLOW:
  185. return EXCEPTION_EXECUTE_HANDLER;
  186. default:
  187. return EXCEPTION_CONTINUE_SEARCH;
  188. }
  189. }
  190. HRESULT
  191. BITSGetStartupInfo(
  192. LPSTARTUPINFO lpStartupInfo )
  193. {
  194. __try
  195. {
  196. GetStartupInfoA( lpStartupInfo );
  197. }
  198. __except( BITSGetStartupInfoFilter( GetExceptionCode() ) )
  199. {
  200. return E_OUTOFMEMORY;
  201. }
  202. return S_OK;
  203. }
  204. void
  205. RestartIIS()
  206. {
  207. LogSetup( LogSevInformation, "[BITSSRV] Restarting IIS\r\n" );
  208. //
  209. // Restarts IIS by calling "iisreset /restart" at the commandline.
  210. //
  211. STARTUPINFO StartupInfo;
  212. THROW_COMERROR( BITSGetStartupInfo( &StartupInfo ) );
  213. #define IISRESET_EXE "iisreset.exe"
  214. #define IISRESET_CMDLINE "iisreset /RESTART /NOFORCE"
  215. PROCESS_INFORMATION ProcessInfo;
  216. CHAR sApplicationPath[MAX_PATH];
  217. CHAR *pApplicationName = NULL;
  218. CHAR sCmdLine[MAX_PATH];
  219. DWORD dwLen = MAX_PATH;
  220. DWORD dwCount;
  221. dwCount = SearchPath(NULL, // Search Path, NULL is PATH
  222. IISRESET_EXE, // Application
  223. NULL, // Extension (already specified)
  224. dwLen, // Length (char's) of sApplicationPath
  225. sApplicationPath, // Path + Name for application
  226. &pApplicationName ); // File part of sApplicationPath
  227. if (dwCount == 0)
  228. {
  229. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  230. }
  231. if (dwCount > dwLen)
  232. {
  233. THROW_COMERROR( HRESULT_FROM_WIN32( ERROR_BUFFER_OVERFLOW ) );
  234. }
  235. StringCbCopyA( sCmdLine, sizeof( sCmdLine ), IISRESET_CMDLINE);
  236. BOOL RetVal = CreateProcess(
  237. sApplicationPath, // name of executable module
  238. sCmdLine, // command line string
  239. NULL, // SD
  240. NULL, // SD
  241. FALSE, // handle inheritance option
  242. CREATE_NO_WINDOW, // creation flags
  243. NULL, // new environment block
  244. NULL, // current directory name
  245. &StartupInfo, // startup information
  246. &ProcessInfo // process information
  247. );
  248. if ( !RetVal )
  249. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  250. WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
  251. DWORD Status;
  252. GetExitCodeProcess( ProcessInfo.hProcess, &Status );
  253. CloseHandle( ProcessInfo.hProcess );
  254. CloseHandle( ProcessInfo.hThread );
  255. THROW_COMERROR( HRESULT_FROM_WIN32( Status ) );
  256. }
  257. #if 0
  258. // Can't enabled for now because IIS6 has a memory
  259. // corruption problem is a property attribute is changed.
  260. void EnsurePropertyInheritance(
  261. SmartIADsContainerPointer & Container,
  262. BSTR PropertyNameBSTR )
  263. {
  264. SmartVariant var;
  265. SmartIDispatchPointer Dispatch;
  266. SmartIADsPointer MbProperty;
  267. VariantInit( &var );
  268. THROW_COMERROR(
  269. Container->GetObject(
  270. g_PropertyBSTR,
  271. PropertyNameBSTR,
  272. Dispatch.GetRecvPointer() ) );
  273. THROW_COMERROR(
  274. Dispatch->QueryInterface( MbProperty.GetUUID(),
  275. reinterpret_cast<void**>( MbProperty.GetRecvPointer() ) ) );
  276. var.boolVal = VARIANT_TRUE;
  277. var.vt = VT_BOOL;
  278. THROW_COMERROR( MbProperty->Put( g_InheritBSTR, var ) );
  279. THROW_COMERROR( MbProperty->SetInfo() );
  280. }
  281. #endif
  282. void InstallPropertySchema( )
  283. {
  284. //
  285. // Installs the ADSI schema with the new metabase properties.
  286. //
  287. LogSetup( LogSevInformation, "[BITSSRV] Installing property schema\r\n" );
  288. SmartVariant var;
  289. SmartIADsContainerPointer MbSchemaContainer;
  290. THROW_COMERROR(
  291. ADsGetObject(
  292. L"IIS://LocalHost/Schema",
  293. MbSchemaContainer.GetUUID(),
  294. reinterpret_cast<void**>( MbSchemaContainer.GetRecvPointer() ) ) );
  295. SmartIDispatchPointer Dispatch;
  296. SmartIADsPointer MbProperty;
  297. SmartIADsClassPointer MbClass;
  298. BSTR PropertyNameBSTR = NULL;
  299. BSTR PropertyClassBSTR = NULL;
  300. try
  301. {
  302. for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
  303. {
  304. LogSetup( LogSevInformation, "[BITSSRV] Installing property %u\r\n", (UINT32)i );
  305. PropertyNameBSTR = SysAllocString( g_Properties[i].PropertyName );
  306. PropertyClassBSTR = SysAllocString( g_Properties[i].ClassName );
  307. if ( !PropertyNameBSTR || !PropertyClassBSTR )
  308. throw ComError( E_OUTOFMEMORY );
  309. {
  310. HRESULT Hr =
  311. MbSchemaContainer->Create(
  312. g_PropertyBSTR,
  313. PropertyNameBSTR,
  314. Dispatch.GetRecvPointer() );
  315. if ( Hr == E_ADS_OBJECT_EXISTS )
  316. {
  317. // Ensure property is inheritable
  318. // EnsurePropertyInheritance( MbSchemaContainer, PropertyNameBSTR );
  319. SysFreeString( PropertyNameBSTR );
  320. SysFreeString( PropertyClassBSTR );
  321. PropertyNameBSTR = PropertyClassBSTR = NULL;
  322. continue;
  323. }
  324. THROW_COMERROR( Hr );
  325. }
  326. THROW_COMERROR(
  327. Dispatch->QueryInterface( MbProperty.GetUUID(),
  328. reinterpret_cast<void**>( MbProperty.GetRecvPointer() ) ) );
  329. var.bstrVal = SysAllocString( g_Properties[i].Syntax );
  330. var.vt = VT_BSTR;
  331. if ( !var.bstrVal )
  332. THROW_COMERROR( E_OUTOFMEMORY );
  333. THROW_COMERROR( MbProperty->Put( g_SyntaxBSTR, var ) );
  334. VariantClear( &var );
  335. var.ulVal = g_Properties[i].UserType;
  336. var.vt = VT_UI4;
  337. THROW_COMERROR( MbProperty->Put( g_UserTypeBSTR, var ) );
  338. var.boolVal = VARIANT_TRUE;
  339. var.vt = VT_BOOL;
  340. THROW_COMERROR( MbProperty->Put( g_InheritBSTR, var ) );
  341. THROW_COMERROR( MbProperty->SetInfo() );
  342. VariantClear( &var );
  343. if ( i == MD_BITS_UPLOAD_METADATA_VERSION )
  344. {
  345. // hack for IIS ID allocation bug
  346. MbProperty->Get( g_MetaIDBSTR, &var );
  347. THROW_COMERROR( VariantChangeType( &var, &var, 0, VT_UI4 ) );
  348. if ( var.ulVal == 130008 )
  349. {
  350. LogSetup( LogSevWarning, "[BITSSRV] Invoking hack for IIS allocation bug(MD_BITS_UPLOAD_METADATA_VERSION)\r\n" );
  351. var.ulVal = 130009;
  352. MbProperty->Put( g_MetaIDBSTR, var );
  353. MbProperty->SetInfo();
  354. }
  355. }
  356. #if defined( ALLOW_OVERWRITES )
  357. else if ( i == MD_BITS_ALLOW_OVERWRITES )
  358. {
  359. // another hack for IIS ID allocation bug
  360. MbProperty->Get( g_MetaIDBSTR, &var );
  361. THROW_COMERROR( VariantChangeType( &var, &var, 0, VT_UI4 ) );
  362. if ( var.ulVal == 130009 )
  363. {
  364. LogSetup( LogSevWarning, "[BITSSRV] Invoking hack for IIS allocation bug(MD_BITS_ALLOW_OVERWRITES)\r\n" );
  365. var.ulVal = 130010;
  366. MbProperty->Put( g_MetaIDBSTR, var );
  367. MbProperty->SetInfo();
  368. }
  369. }
  370. #endif
  371. THROW_COMERROR(
  372. MbSchemaContainer->GetObject( g_ClassBSTR, PropertyClassBSTR,
  373. Dispatch.GetRecvPointer() ) );
  374. THROW_COMERROR(
  375. Dispatch->QueryInterface( MbClass.GetUUID(),
  376. reinterpret_cast<void**>( MbClass.GetRecvPointer() ) ) );
  377. THROW_COMERROR( MbClass->get_OptionalProperties( &var ) );
  378. SAFEARRAY* Array = var.parray;
  379. long LBound;
  380. long UBound;
  381. THROW_COMERROR( SafeArrayGetLBound( Array, 1, &LBound ) );
  382. THROW_COMERROR( SafeArrayGetUBound( Array, 1, &UBound ) );
  383. UBound++; // Add one to the upper bound
  384. SAFEARRAYBOUND SafeBounds;
  385. SafeBounds.lLbound = LBound;
  386. SafeBounds.cElements = UBound - LBound + 1;
  387. THROW_COMERROR( SafeArrayRedim( Array, &SafeBounds ) );
  388. VARIANT bstrvar;
  389. VariantInit( &bstrvar );
  390. bstrvar.vt = VT_BSTR;
  391. bstrvar.bstrVal = SysAllocString( g_Properties[i].PropertyName );
  392. if ( !bstrvar.bstrVal )
  393. THROW_COMERROR( E_OUTOFMEMORY );
  394. long Dim = (long)UBound;
  395. THROW_COMERROR( SafeArrayPutElement( Array, &Dim, &bstrvar ) );
  396. VariantClear( &bstrvar );
  397. THROW_COMERROR( MbClass->put_OptionalProperties( var ) );
  398. THROW_COMERROR( MbClass->SetInfo() );
  399. SysFreeString( PropertyNameBSTR );
  400. SysFreeString( PropertyClassBSTR );
  401. PropertyNameBSTR = PropertyClassBSTR = NULL;
  402. }
  403. }
  404. catch( ComError Error )
  405. {
  406. LogSetup( LogSevError, "[BITSSRV] Error detected while installing property schema, error %u\r\n" );
  407. SysFreeString( PropertyNameBSTR );
  408. SysFreeString( PropertyClassBSTR );
  409. PropertyNameBSTR = PropertyClassBSTR = NULL;
  410. throw;
  411. }
  412. return;
  413. }
  414. void RemovePropertySchema( )
  415. {
  416. // Removes our properties from the metabase schema
  417. LogSetup( LogSevInformation, "[BITSSRV] Starting RemovePropertySchema\r\n" );
  418. SmartVariant var;
  419. SmartIADsContainerPointer MbSchemaContainer;
  420. THROW_COMERROR(
  421. ADsGetObject(
  422. L"IIS://LocalHost/Schema",
  423. MbSchemaContainer.GetUUID(),
  424. reinterpret_cast<void**>( MbSchemaContainer.GetRecvPointer() ) ) );
  425. SmartIDispatchPointer Dispatch;
  426. SmartIADsClassPointer MbClass;
  427. SmartIADsPointer Object;
  428. BSTR PropertyNameBSTR = NULL;
  429. BSTR PropertyClassBSTR = NULL;
  430. for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
  431. {
  432. LogSetup( LogSevInformation, "[BITSSRV] Removing property number, %u\r\n", i );
  433. PropertyNameBSTR = SysAllocString( g_Properties[i].PropertyName );
  434. PropertyClassBSTR = SysAllocString( g_Properties[i].ClassName );
  435. if ( !PropertyNameBSTR || !PropertyClassBSTR )
  436. throw ComError( E_OUTOFMEMORY );
  437. MbSchemaContainer->Delete( g_PropertyBSTR, PropertyNameBSTR );
  438. THROW_COMERROR(
  439. MbSchemaContainer->QueryInterface( Object.GetUUID(),
  440. reinterpret_cast<void**>( Object.GetRecvPointer() ) ) );
  441. Object->SetInfo();
  442. THROW_COMERROR(
  443. MbSchemaContainer->GetObject( g_ClassBSTR, PropertyClassBSTR,
  444. Dispatch.GetRecvPointer() ) );
  445. THROW_COMERROR(
  446. Dispatch->QueryInterface( MbClass.GetUUID(),
  447. reinterpret_cast<void**>( MbClass.GetRecvPointer() ) ) );
  448. THROW_COMERROR( MbClass->get_OptionalProperties( &var ) );
  449. SAFEARRAY* Array = var.parray;
  450. SafeArrayLocker ArrayLock( Array );
  451. ArrayLock.Lock();
  452. ULONG NewSize = 0;
  453. SIZE_T j = Array->rgsabound[0].lLbound;
  454. SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  455. while( j < k )
  456. {
  457. VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
  458. // This element is fine, keep it
  459. if ( 0 != _wcsicmp( (WCHAR*)JElem.bstrVal, BSTR( g_Properties[i].PropertyName ) ) )
  460. {
  461. NewSize++;
  462. j++;
  463. }
  464. else
  465. {
  466. // find a suitable element to replace the bad element with
  467. while( j < --k )
  468. {
  469. VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
  470. if ( 0 != _wcsicmp( (WCHAR*)KElem.bstrVal, BSTR( g_Properties[i].PropertyName ) ) )
  471. {
  472. // found element. move it
  473. VARIANT temp = JElem;
  474. JElem = KElem;
  475. KElem = temp;
  476. break;
  477. }
  478. }
  479. }
  480. }
  481. SAFEARRAYBOUND ArrayBounds;
  482. ArrayBounds = Array->rgsabound[0];
  483. ArrayBounds.cElements = NewSize;
  484. ArrayLock.Unlock();
  485. THROW_COMERROR( SafeArrayRedim( Array, &ArrayBounds ) );
  486. THROW_COMERROR( MbClass->put_OptionalProperties( var ) );
  487. THROW_COMERROR( MbClass->SetInfo() );
  488. VariantClear( &var );
  489. }
  490. }
  491. void InstallDefaultValues( )
  492. {
  493. //
  494. // Install default values for the configuration. Do this at the top and let inheritance deal with it.
  495. //
  496. LogSetup( LogSevInformation, "[BITSSRV] Starting InstallDefaultValues\r\n" );
  497. METADATA_RECORD mdr;
  498. METADATA_HANDLE mdHandle = NULL;
  499. DWORD Value;
  500. PropertyIDManager PropertyMan;
  501. THROW_COMERROR( PropertyMan.LoadPropertyInfo() );
  502. SmartMetabasePointer IISAdminBase;
  503. THROW_COMERROR(
  504. CoCreateInstance(
  505. GETAdminBaseCLSID(TRUE),
  506. NULL,
  507. CLSCTX_SERVER,
  508. IISAdminBase.GetUUID(),
  509. (LPVOID*)IISAdminBase.GetRecvPointer() ) );
  510. THROW_COMERROR(
  511. IISAdminBase->OpenKey(
  512. METADATA_MASTER_ROOT_HANDLE,
  513. L"/LM/W3SVC",
  514. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  515. METABASE_OPEN_KEY_TIMEOUT,
  516. &mdHandle ) );
  517. try
  518. {
  519. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
  520. mdr.dwMDAttributes = METADATA_INHERIT;
  521. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_CONNECTION_DIR );
  522. mdr.dwMDDataType = STRING_METADATA;
  523. mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_CONNECTION_DIR;
  524. mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_CONNECTION_DIR ) + 1 );
  525. mdr.dwMDDataTag = 0;
  526. THROW_COMERROR(
  527. IISAdminBase->SetData(
  528. mdHandle,
  529. NULL,
  530. &mdr ) );
  531. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_MAX_FILESIZE );
  532. mdr.dwMDAttributes = METADATA_INHERIT;
  533. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_MAX_FILESIZE );
  534. mdr.dwMDDataType = STRING_METADATA;
  535. mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_MAX_FILESIZE;
  536. mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_MAX_FILESIZE ) + 1 );
  537. mdr.dwMDDataTag = 0;
  538. THROW_COMERROR(
  539. IISAdminBase->SetData(
  540. mdHandle,
  541. NULL,
  542. &mdr ) );
  543. Value = MD_DEFAULT_NO_PROGESS_TIMEOUT;
  544. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_NO_PROGRESS_TIMEOUT );
  545. mdr.dwMDAttributes = METADATA_INHERIT;
  546. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_NO_PROGRESS_TIMEOUT );
  547. mdr.dwMDDataType = DWORD_METADATA;
  548. mdr.pbMDData = (PBYTE)&Value;
  549. mdr.dwMDDataLen = sizeof(Value);
  550. mdr.dwMDDataTag = 0;
  551. THROW_COMERROR(
  552. IISAdminBase->SetData(
  553. mdHandle,
  554. NULL,
  555. &mdr ) );
  556. Value = (DWORD)MD_DEFAULT_BITS_NOTIFICATION_URL_TYPE;
  557. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL_TYPE );
  558. mdr.dwMDAttributes = METADATA_INHERIT;
  559. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_NOTIFICATION_URL_TYPE );
  560. mdr.dwMDDataType = DWORD_METADATA;
  561. mdr.pbMDData = (PBYTE)&Value;
  562. mdr.dwMDDataLen = sizeof(Value);
  563. mdr.dwMDDataTag = 0;
  564. THROW_COMERROR(
  565. IISAdminBase->SetData(
  566. mdHandle,
  567. NULL,
  568. &mdr ) );
  569. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_NOTIFICATION_URL );
  570. mdr.dwMDAttributes = METADATA_INHERIT;
  571. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_NOTIFICATION_URL );
  572. mdr.dwMDDataType = STRING_METADATA;
  573. mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_NOTIFICATION_URL;
  574. mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_NOTIFICATION_URL ) + 1 );;
  575. mdr.dwMDDataTag = 0;
  576. THROW_COMERROR(
  577. IISAdminBase->SetData(
  578. mdHandle,
  579. NULL,
  580. &mdr ) );
  581. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_HOSTID );
  582. mdr.dwMDAttributes = METADATA_INHERIT;
  583. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_HOSTID );
  584. mdr.dwMDDataType = STRING_METADATA;
  585. mdr.pbMDData = (PBYTE)MD_DEFAULT_BITS_HOSTID;
  586. mdr.dwMDDataLen = sizeof(WCHAR) * ( wcslen( MD_DEFAULT_BITS_HOSTID ) + 1 );
  587. mdr.dwMDDataTag = 0;
  588. THROW_COMERROR(
  589. IISAdminBase->SetData(
  590. mdHandle,
  591. NULL,
  592. &mdr ) );
  593. Value = MD_DEFAULT_HOSTID_FALLBACK_TIMEOUT;
  594. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_HOSTID_FALLBACK_TIMEOUT );
  595. mdr.dwMDAttributes = METADATA_INHERIT;
  596. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_HOSTID_FALLBACK_TIMEOUT );
  597. mdr.dwMDDataType = DWORD_METADATA;
  598. mdr.pbMDData = (PBYTE)&Value;
  599. mdr.dwMDDataLen = sizeof(Value);
  600. mdr.dwMDDataTag = 0;
  601. THROW_COMERROR(
  602. IISAdminBase->SetData(
  603. mdHandle,
  604. NULL,
  605. &mdr ) );
  606. #if defined( ALLOW_OVERWRITES )
  607. Value = MD_DEFAULT_BITS_ALLOW_OVERWRITES;
  608. mdr.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_ALLOW_OVERWRITES );
  609. mdr.dwMDAttributes = METADATA_INHERIT;
  610. mdr.dwMDUserType = PropertyMan.GetPropertyUserType( MD_BITS_ALLOW_OVERWRITES );
  611. mdr.dwMDDataType = DWORD_METADATA;
  612. mdr.pbMDData = (PBYTE)&Value;
  613. mdr.dwMDDataLen = sizeof(Value);
  614. mdr.dwMDDataTag = 0;
  615. THROW_COMERROR(
  616. IISAdminBase->SetData(
  617. mdHandle,
  618. NULL,
  619. &mdr ) );
  620. #endif
  621. IISAdminBase->CloseKey( mdHandle );
  622. }
  623. catch( ComError Error )
  624. {
  625. if ( mdHandle )
  626. IISAdminBase->CloseKey( mdHandle );
  627. }
  628. }
  629. void
  630. AddDllToIISList(
  631. SAFEARRAY* Array )
  632. {
  633. //
  634. // Add the ISAPI to the IIS list.
  635. //
  636. // Search for the DLL. If its already in the list, do nothing
  637. LogSetup( LogSevInformation, "[BITSSRV] Starting AddDllToIISList\r\n" );
  638. SafeArrayLocker ArrayLocker( Array );
  639. ArrayLocker.Lock();
  640. for ( unsigned int i = Array->rgsabound[0].lLbound;
  641. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements; i++ )
  642. {
  643. VARIANT & IElem = ((VARIANT*)Array->pvData)[i];
  644. if ( _wcsicmp( (WCHAR*)IElem.bstrVal, g_ISAPIPath ) == 0 )
  645. {
  646. // Dll is already in the list, do nothing
  647. return;
  648. }
  649. }
  650. // Need to add the DLL
  651. SAFEARRAYBOUND SafeBounds;
  652. SafeBounds.lLbound = Array->rgsabound[0].lLbound;
  653. SafeBounds.cElements = Array->rgsabound[0].cElements+1;
  654. ArrayLocker.Unlock();
  655. THROW_COMERROR( SafeArrayRedim( Array, &SafeBounds ) );
  656. SmartVariant bstrvar;
  657. bstrvar.vt = VT_BSTR;
  658. bstrvar.bstrVal = SysAllocString( g_ISAPIPath );
  659. if ( !bstrvar.bstrVal )
  660. THROW_COMERROR( E_OUTOFMEMORY );
  661. long Index = SafeBounds.lLbound + SafeBounds.cElements - 1;
  662. THROW_COMERROR( SafeArrayPutElement( Array, &Index, (void*)&bstrvar ) );
  663. }
  664. void
  665. RemoveDllFromIISList(
  666. SAFEARRAY *Array )
  667. {
  668. // Remove the DLL from the IIS list
  669. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveDllFromIISList\r\n" );
  670. SafeArrayLocker ArrayLocker( Array );
  671. ArrayLocker.Lock();
  672. ULONG NewSize = 0;
  673. SIZE_T j = Array->rgsabound[0].lLbound;
  674. SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  675. while( j < k )
  676. {
  677. VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
  678. // This element is fine, keep it
  679. if ( 0 != _wcsicmp( (WCHAR*)JElem.bstrVal, g_ISAPIPath ) )
  680. {
  681. NewSize++;
  682. j++;
  683. }
  684. else
  685. {
  686. // find a suitable element to replace the bad element with
  687. while( j < --k )
  688. {
  689. VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
  690. if ( 0 != _wcsicmp( (WCHAR*)KElem.bstrVal, g_ISAPIPath ) )
  691. {
  692. // found element. move it
  693. VARIANT temp = JElem;
  694. JElem = KElem;
  695. KElem = temp;
  696. break;
  697. }
  698. }
  699. }
  700. }
  701. SAFEARRAYBOUND ArrayBounds;
  702. ArrayBounds = Array->rgsabound[0];
  703. ArrayBounds.cElements = NewSize;
  704. ArrayLocker.Unlock();
  705. THROW_COMERROR( SafeArrayRedim( Array, &ArrayBounds ) );
  706. }
  707. void
  708. ModifyLockdownList( bool Add )
  709. {
  710. // Toplevel function to modify the IIS lockdown list.
  711. // If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
  712. LogSetup( LogSevInformation, "[BITSSRV] Starting ModifyLockdownList Add(%u)\r\n", (UINT32)Add );
  713. SmartIADsPointer Service;
  714. SAFEARRAY* Array = NULL;
  715. SmartVariant var;
  716. THROW_COMERROR(
  717. ADsGetObject( L"IIS://LocalHost/W3SVC",
  718. Service.GetUUID(), (void**)Service.GetRecvPointer() ) );
  719. {
  720. HRESULT Hr = Service->Get( g_IsapiRestrictionListBSTR, &var );
  721. if ( FAILED(Hr) )
  722. {
  723. // This property doesn't exist on IIS5 or IIS5.1 don't install it
  724. return;
  725. }
  726. }
  727. Array = var.parray;
  728. {
  729. SafeArrayLocker ArrayLocker( Array );
  730. ArrayLocker.Lock();
  731. if ( !Array->rgsabound[0].cElements )
  732. {
  733. // The array has no elements which means no restrictions.
  734. return;
  735. }
  736. VARIANT & FirstElem = ((VARIANT*)Array->pvData)[ Array->rgsabound[0].lLbound ];
  737. if ( _wcsicmp(L"0", (WCHAR*)FirstElem.bstrVal ) == 0 )
  738. {
  739. //
  740. // According to the IIS6 spec, a 0 means that all ISAPIs are denied except
  741. // those that are explicitly listed.
  742. //
  743. // If installing: add to the list.
  744. // If uninstalling: remove from the list
  745. //
  746. ArrayLocker.Unlock();
  747. if ( Add )
  748. AddDllToIISList( Array );
  749. else
  750. RemoveDllFromIISList( Array );
  751. }
  752. else if ( _wcsicmp( L"1", (WCHAR*)FirstElem.bstrVal ) == 0 )
  753. {
  754. //
  755. // According to the IIS6 spec, a 1 means that all ISAPIs are allowed except
  756. // those that are explicitly denied.
  757. //
  758. // If installing: remove from the list
  759. // If uninstalling: Do nothing
  760. //
  761. ArrayLocker.Unlock();
  762. if ( Add )
  763. RemoveDllFromIISList( Array );
  764. }
  765. else
  766. {
  767. LogSetup( LogSevInformation, "[BITSSRV] The old IIS lockdown list is corrupt\r\n" );
  768. THROW_COMERROR( E_FAIL );
  769. }
  770. THROW_COMERROR( Service->Put( g_IsapiRestrictionListBSTR, var ) );
  771. THROW_COMERROR( Service->SetInfo() );
  772. }
  773. }
  774. void
  775. AddToLockdownListDisplayPutString(
  776. SAFEARRAY *Array,
  777. unsigned long Position,
  778. const WCHAR *String )
  779. {
  780. LogSetup( LogSevInformation, "[BITSSRV] Starting AddToLockdownListDisplayPutString\r\n" );
  781. SmartVariant Var;
  782. Var.vt = VT_BSTR;
  783. Var.bstrVal = SysAllocString( String );
  784. if ( !Var.bstrVal )
  785. THROW_COMERROR( E_OUTOFMEMORY );
  786. long Index = (unsigned long)Position;
  787. THROW_COMERROR( SafeArrayPutElement( Array, &Index, (void*)&Var ) );
  788. }
  789. void
  790. AddToLockdownListDisplay( SAFEARRAY *Array )
  791. {
  792. //
  793. // Check to see if the ISAPI is already in the list. If it is, don't modify
  794. // list.
  795. //
  796. LogSetup( LogSevInformation, "[BITSSRV] Starting AddToLockdownListDisplay\r\n" );
  797. SafeArrayLocker ArrayLocker( Array );
  798. ArrayLocker.Lock();
  799. for( unsigned long i = Array->rgsabound[0].lLbound;
  800. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  801. i++ )
  802. {
  803. VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
  804. BSTR BSTRString = CurrentElement.bstrVal;
  805. if ( _wcsicmp( (WCHAR*)BSTRString, g_ISAPIPath ) == 0 )
  806. {
  807. // ISAPI is already in the list, don't do anything
  808. return;
  809. }
  810. }
  811. SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
  812. unsigned long OldSize = SafeArrayBound.cElements;
  813. SafeArrayBound.cElements += 3;
  814. ArrayLocker.Unlock();
  815. THROW_COMERROR( SafeArrayRedim( Array, &SafeArrayBound ) );
  816. AddToLockdownListDisplayPutString( Array, OldSize, L"1" );
  817. AddToLockdownListDisplayPutString( Array, OldSize + 1, g_ISAPIPath );
  818. AddToLockdownListDisplayPutString( Array, OldSize + 2, g_ExtensionNameString );
  819. }
  820. void
  821. SafeArrayRemoveSlice(
  822. SAFEARRAY *Array,
  823. unsigned long lBound,
  824. unsigned long uBound )
  825. {
  826. // Remove a slice of an array.
  827. LogSetup( LogSevInformation, "[BITSSRV] Starting SafeArrayRemoveSlice\r\n" );
  828. SIZE_T ElementsToRemove = uBound - lBound + 1;
  829. SafeArrayLocker ArrayLocker( Array );
  830. ArrayLocker.Lock();
  831. if ( uBound + 1 < Array->rgsabound[0].cElements )
  832. {
  833. // At least one element exists above this element
  834. // Step 1, move slice to temp storage
  835. VARIANT *Temp = (VARIANT*)new BYTE[ sizeof(VARIANT) * ElementsToRemove ];
  836. memcpy( Temp, &((VARIANT*)Array->pvData)[ lBound ], sizeof(VARIANT)*ElementsToRemove );
  837. // Step 2, collapse hole left by slice
  838. memmove( &((VARIANT*)Array->pvData)[ lBound ],
  839. &((VARIANT*)Array->pvData)[ uBound + 1 ],
  840. sizeof(VARIANT) * ( Array->rgsabound[0].cElements - ( uBound + 1 ) ) );
  841. // Step 3, move slice to end of array
  842. memcpy( &((VARIANT*)Array->pvData)[ Array->rgsabound[0].cElements - ElementsToRemove ],
  843. Temp,
  844. sizeof(VARIANT)*ElementsToRemove );
  845. delete[] Temp;
  846. }
  847. SAFEARRAYBOUND SafeArrayBound = Array->rgsabound[0];
  848. SafeArrayBound.cElements -= (ULONG)ElementsToRemove;
  849. ArrayLocker.Unlock();
  850. SafeArrayRedim( Array, &SafeArrayBound );
  851. }
  852. void
  853. RemoveFromLockdownListDisplay(
  854. SAFEARRAY *Array )
  855. {
  856. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveFromLockdownListDisplay\r\n" );
  857. SafeArrayLocker ArrayLocker( Array );
  858. ArrayLocker.Lock();
  859. for( unsigned int i = Array->rgsabound[0].lLbound;
  860. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  861. i++ )
  862. {
  863. VARIANT & CurrentElement = ((VARIANT*)Array->pvData)[ i ];
  864. BSTR BSTRString = CurrentElement.bstrVal;
  865. if ( _wcsicmp( (WCHAR*)BSTRString, g_ISAPIPath ) == 0 )
  866. {
  867. // ISAPI is in the list, remove it
  868. ArrayLocker.Unlock();
  869. SafeArrayRemoveSlice(
  870. Array,
  871. (i == 0) ? 0 : i - 1,
  872. min( i + 1, Array->rgsabound[0].cElements - 1 ) );
  873. ArrayLocker.Lock();
  874. }
  875. }
  876. // ISAPI wasn't found. Nothing to do.
  877. }
  878. void
  879. ModifyLockdownListDisplay( bool Add )
  880. {
  881. LogSetup( LogSevInformation, "[BITSSRV] Starting ModifyLockdownListDisplay Add(%u)\r\n", (UINT32)Add );
  882. SAFEARRAY* Array = NULL;
  883. SmartIADsPointer Service;
  884. SmartVariant var;
  885. THROW_COMERROR(
  886. ADsGetObject( L"IIS://LocalHost/W3SVC",
  887. Service.GetUUID(), (void**)Service.GetRecvPointer() ) );
  888. {
  889. HRESULT Hr = Service->Get( g_RestrictionListCustomDescBSTR, &var );
  890. if ( FAILED(Hr) )
  891. {
  892. // This property doesn't exist on IIS5 or IIS5.1 don't install or uninstall it
  893. return;
  894. }
  895. }
  896. Array = var.parray;
  897. if ( Add )
  898. AddToLockdownListDisplay( Array );
  899. else
  900. RemoveFromLockdownListDisplay( Array );
  901. THROW_COMERROR( Service->Put( g_RestrictionListCustomDescBSTR, var ) );
  902. THROW_COMERROR( Service->SetInfo() );
  903. }
  904. void
  905. RemoveFilterIfNeeded()
  906. {
  907. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveFilterIfNeeded\r\n" );
  908. SmartVariant var;
  909. WCHAR *LoadOrder = NULL;
  910. MemoryArrayCleaner<WCHAR> LoadOrderCleaner( LoadOrder ); // frees temp memory
  911. SmartIADsContainerPointer MbFiltersContainer;
  912. SmartIADsPointer Object;
  913. THROW_COMERROR(
  914. ADsGetObject( L"IIS://LocalHost/W3SVC/Filters",
  915. MbFiltersContainer.GetUUID(), (void**)MbFiltersContainer.GetRecvPointer() ) );
  916. // Remove bits from the load path
  917. THROW_COMERROR( MbFiltersContainer->QueryInterface( Object.GetUUID(), (void**)Object.GetRecvPointer() ) );
  918. THROW_COMERROR( Object->Get( g_FilterLoadOrderBSTR, &var ) );
  919. THROW_COMERROR( VariantChangeType( &var, &var, 0, VT_BSTR ) );
  920. SIZE_T LoadOrderLength = wcslen( (WCHAR*)var.bstrVal ) + 1;
  921. LoadOrder = new WCHAR[ LoadOrderLength ]; // freed on cleanup
  922. memcpy( LoadOrder, (WCHAR*)var.bstrVal, LoadOrderLength * sizeof( WCHAR ) );
  923. // remove any old bitsserver entries
  924. RemoveFilterHelper( LoadOrder, L",bitsserver" );
  925. RemoveFilterHelper( LoadOrder, L"bitsserver," );
  926. RemoveFilterHelper( LoadOrder, L"bitsserver" );
  927. RemoveFilterHelper( LoadOrder, L",bitserver" );
  928. RemoveFilterHelper( LoadOrder, L"bitserver," );
  929. RemoveFilterHelper( LoadOrder, L"bitserver" );
  930. var.vt = VT_BSTR;
  931. var.bstrVal = SysAllocString( LoadOrder );
  932. if ( !var.bstrVal )
  933. THROW_COMERROR( E_OUTOFMEMORY );
  934. THROW_COMERROR( Object->Put( g_FilterLoadOrderBSTR, var ) );
  935. THROW_COMERROR( Object->SetInfo() );
  936. MbFiltersContainer->Delete( g_IIsFilterBSTR, g_bitsserverBSTR );
  937. MbFiltersContainer->Delete( g_IIsFilterBSTR, g_bitserverBSTR );
  938. Object->SetInfo();
  939. }
  940. void
  941. ModifyInProcessList( bool Add )
  942. {
  943. // Toplevel function to modify the IIS inprocess list.
  944. // If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
  945. LogSetup( LogSevInformation, "[BITSSRV] Starting ModifyInProcessList, Add(%u)\r\n", (UINT32)Add );
  946. SmartIADsPointer Service;
  947. SmartVariant var;
  948. THROW_COMERROR(
  949. ADsGetObject( L"IIS://LocalHost/W3SVC",
  950. Service.GetUUID(), (void**)Service.GetRecvPointer() ) );
  951. THROW_COMERROR( Service->Get( g_InProcessIsapiAppsBSTR, &var ) );
  952. if ( Add )
  953. AddDllToIISList( var.parray );
  954. else
  955. RemoveDllFromIISList( var.parray );
  956. THROW_COMERROR( Service->Put( g_InProcessIsapiAppsBSTR, var ) );
  957. THROW_COMERROR( Service->SetInfo() );
  958. }
  959. void
  960. RemoveFromWebSvcList(
  961. SAFEARRAY *Array )
  962. {
  963. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveFromWebSvcList\r\n" );
  964. StringHandleW SearchString = L",";
  965. SearchString += g_ISAPIPath;
  966. SearchString += L",";
  967. SafeArrayLocker ArrayLocker( Array );
  968. ArrayLocker.Lock();
  969. ULONG NewSize = 0;
  970. SIZE_T j = Array->rgsabound[0].lLbound;
  971. SIZE_T k = Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements;
  972. while( j < k )
  973. {
  974. VARIANT & JElem = ((VARIANT*)Array->pvData)[j];
  975. // This element is fine, keep it
  976. if ( !wcsstr( (WCHAR*)JElem.bstrVal, (const WCHAR*)SearchString ) )
  977. {
  978. NewSize++;
  979. j++;
  980. }
  981. else
  982. {
  983. // find a suitable element to replace the bad element with
  984. while( j < --k )
  985. {
  986. VARIANT & KElem = ((VARIANT*)Array->pvData)[k];
  987. if ( !wcsstr( (WCHAR*)KElem.bstrVal, (const WCHAR*)SearchString ) )
  988. {
  989. // found element. move it
  990. VARIANT temp = JElem;
  991. JElem = KElem;
  992. KElem = temp;
  993. break;
  994. }
  995. }
  996. }
  997. }
  998. SAFEARRAYBOUND ArrayBounds;
  999. ArrayBounds = Array->rgsabound[0];
  1000. ArrayBounds.cElements = NewSize;
  1001. ArrayLocker.Unlock();
  1002. THROW_COMERROR( SafeArrayRedim( Array, &ArrayBounds ) );
  1003. }
  1004. void
  1005. AddToWebSvcList(
  1006. SAFEARRAY* Array )
  1007. {
  1008. //
  1009. // Add the ISAPI to the IIS list.
  1010. //
  1011. LogSetup( LogSevInformation, "[BITSSRV] Starting AddToWebSvcList\r\n" );
  1012. // Search for the DLL. If its already in the list, do nothing
  1013. SafeArrayLocker ArrayLocker( Array );
  1014. ArrayLocker.Lock();
  1015. // Enclose the path with commas to decrease chance of a false hit
  1016. StringHandleW ISAPIPath = L",";
  1017. ISAPIPath += g_ISAPIPath;
  1018. ISAPIPath += L",";
  1019. for ( unsigned int i = Array->rgsabound[0].lLbound;
  1020. i < Array->rgsabound[0].lLbound + Array->rgsabound[0].cElements; i++ )
  1021. {
  1022. VARIANT & IElem = ((VARIANT*)Array->pvData)[i];
  1023. if ( wcsstr( (WCHAR*)IElem.bstrVal, (const WCHAR*)ISAPIPath ) )
  1024. {
  1025. // Dll is already in the list, do nothing
  1026. return;
  1027. }
  1028. }
  1029. // Need to add the DLL
  1030. SAFEARRAYBOUND SafeBounds;
  1031. SafeBounds.lLbound = Array->rgsabound[0].lLbound;
  1032. SafeBounds.cElements = Array->rgsabound[0].cElements+1;
  1033. ArrayLocker.Unlock();
  1034. THROW_COMERROR( SafeArrayRedim( Array, &SafeBounds ) );
  1035. // build the lockdown string
  1036. StringHandleW LockdownString;
  1037. LockdownString += L"1,"; // Is enabled
  1038. LockdownString += g_ISAPIPath; // ISAPI path
  1039. LockdownString += L",0," BITS_GROUP_IDW L","; // not deletable
  1040. LockdownString += g_ExtensionNameString; // description
  1041. SmartVariant bstrvar;
  1042. bstrvar.vt = VT_BSTR;
  1043. bstrvar.bstrVal = SysAllocString( (const WCHAR*)LockdownString );
  1044. if ( !bstrvar.bstrVal )
  1045. THROW_COMERROR( E_OUTOFMEMORY );
  1046. long Index = SafeBounds.lLbound + SafeBounds.cElements - 1;
  1047. THROW_COMERROR( SafeArrayPutElement( Array, &Index, (void*)&bstrvar ) );
  1048. }
  1049. void
  1050. ModifyWebSvcRestrictionList( bool Add )
  1051. {
  1052. // Toplevel function to modify the IIS lockdown list.
  1053. // If Add is 1, then the ISAPI is added. If Add is 0, then the ISAPI is removed.
  1054. LogSetup( LogSevInformation, "[BITSSRV] Starting ModifyWebSvcRestrictionList, Add(%u)\r\n", (UINT32)Add );
  1055. SmartIADsPointer Service;
  1056. SAFEARRAY* Array = NULL;
  1057. SmartVariant var;
  1058. THROW_COMERROR(
  1059. ADsGetObject( L"IIS://LocalHost/W3SVC",
  1060. Service.GetUUID(), (void**)Service.GetRecvPointer() ) );
  1061. {
  1062. HRESULT Hr = Service->Get( g_WebSvcExtRestrictionListBSTR, &var );
  1063. if ( FAILED(Hr) )
  1064. {
  1065. // This property doesn't exist on IIS5 or IIS5.1 don't install it
  1066. return;
  1067. }
  1068. }
  1069. Array = var.parray;
  1070. if ( Add )
  1071. AddToWebSvcList( Array );
  1072. else
  1073. RemoveFromWebSvcList( Array );
  1074. THROW_COMERROR( Service->Put( g_WebSvcExtRestrictionListBSTR, var ) );
  1075. THROW_COMERROR( Service->SetInfo() );
  1076. }
  1077. void
  1078. StartupMSTask()
  1079. {
  1080. LogSetup( LogSevInformation, "[BITSSRV] Starting StartMSTask\r\n" );
  1081. SC_HANDLE hSC = NULL;
  1082. SC_HANDLE hSchSvc = NULL;
  1083. BYTE* ConfigBuffer = NULL;
  1084. MemoryArrayCleaner<BYTE> ConfigBufferCleaner( ConfigBuffer );
  1085. DWORD BytesNeeded = 0;
  1086. try
  1087. {
  1088. hSC = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1089. if (hSC == NULL)
  1090. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1091. hSchSvc = OpenService(hSC,
  1092. "Schedule",
  1093. SERVICE_ALL_ACCESS );
  1094. if ( !hSchSvc )
  1095. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1096. SERVICE_STATUS SvcStatus;
  1097. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  1098. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1099. if (SvcStatus.dwCurrentState == SERVICE_RUNNING)
  1100. {
  1101. // Service is already running
  1102. CloseServiceHandle( hSC );
  1103. CloseServiceHandle( hSchSvc );
  1104. return;
  1105. }
  1106. LogSetup( LogSevInformation, "[BITSSRV] MSTask isn't running, need to start it up\r\n" );
  1107. SetLastError( ERROR_SUCCESS );
  1108. ConfigBuffer = new BYTE[CONFIG_BUFFER_MAX];
  1109. if (!ConfigBuffer)
  1110. {
  1111. throw ComError(E_OUTOFMEMORY);
  1112. }
  1113. if ( !QueryServiceConfig(
  1114. hSchSvc,
  1115. (LPQUERY_SERVICE_CONFIG)ConfigBuffer,
  1116. BytesNeeded,
  1117. &BytesNeeded ) )
  1118. {
  1119. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1120. }
  1121. if ( ((LPQUERY_SERVICE_CONFIG)ConfigBuffer)->dwStartType != SERVICE_AUTO_START )
  1122. {
  1123. if ( !ChangeServiceConfig(
  1124. hSchSvc,
  1125. SERVICE_NO_CHANGE, // type of service
  1126. SERVICE_AUTO_START, // when to start service
  1127. SERVICE_NO_CHANGE, // severity of start failure
  1128. NULL, // service binary file name
  1129. NULL, // load ordering group name
  1130. NULL, // tag identifier
  1131. NULL, // array of dependency names
  1132. NULL, // account name
  1133. NULL, // account password
  1134. NULL // display name
  1135. ) )
  1136. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1137. }
  1138. if ( StartService(hSchSvc, 0, NULL) == FALSE )
  1139. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1140. // Poll for the service to enter the running or error state
  1141. while( 1 )
  1142. {
  1143. if (QueryServiceStatus(hSchSvc, &SvcStatus) == FALSE)
  1144. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1145. if ( SvcStatus.dwCurrentState == SERVICE_STOPPED ||
  1146. SvcStatus.dwCurrentState == SERVICE_PAUSED )
  1147. throw ComError( HRESULT_FROM_WIN32( SvcStatus.dwCurrentState ) );
  1148. if ( SvcStatus.dwCurrentState == SERVICE_RUNNING )
  1149. break;
  1150. }
  1151. CloseServiceHandle( hSC );
  1152. CloseServiceHandle( hSchSvc );
  1153. }
  1154. catch( ComError Error )
  1155. {
  1156. if ( hSchSvc )
  1157. CloseServiceHandle( hSC );
  1158. if ( hSC )
  1159. CloseServiceHandle( hSchSvc );
  1160. }
  1161. }
  1162. #if 0
  1163. void
  1164. ProcessVerbsInIniSection(
  1165. WCHAR *Section,
  1166. WCHAR *Verb,
  1167. WCHAR *FileName,
  1168. bool Add )
  1169. {
  1170. WCHAR *SectionData = (WCHAR*)new WCHAR[ 32768 ];
  1171. MemoryArrayCleaner<WCHAR> SectionDataCleaner( SectionData );
  1172. WCHAR *NewSectionData = (WCHAR*)new WCHAR[ 32768 * 2 ];
  1173. MemoryArrayCleaner<WCHAR> NewSectionDataCleaner( SectionData );
  1174. DWORD Result =
  1175. GetPrivateProfileSectionW(
  1176. Section, // section name
  1177. SectionData, // return buffer
  1178. 32768, // size of return buffer
  1179. FileName // initialization file name
  1180. );
  1181. if ( Result == 32768 - 2 )
  1182. {
  1183. // The buffer is not large enough. Interestingly,
  1184. // even urlscan is not capable of handing a section this
  1185. // large so just assume the file is corrupt and ignore it.
  1186. return;
  1187. }
  1188. if ( Add )
  1189. {
  1190. // Loop through the list copying it to the new buffer.
  1191. // Stop if the verb has already been added.
  1192. WCHAR *OriginalVerb = SectionData;
  1193. WCHAR *NewVerb = NewSectionData;
  1194. while( *OriginalVerb )
  1195. {
  1196. if ( wcscmp( OriginalVerb, Verb ) == 0 )
  1197. {
  1198. // verb already found, no more processing needed
  1199. return;
  1200. }
  1201. SIZE_T VerbSize = wcslen( OriginalVerb ) + 1;
  1202. memcpy( NewVerb, OriginalVerb, sizeof( WCHAR ) * VerbSize );
  1203. OriginalVerb += VerbSize;
  1204. NewVerb += VerbSize;
  1205. }
  1206. // add the verb since it hasn't been added
  1207. SIZE_T VerbSize = wcslen( Verb ) + 1;
  1208. memcpy( NewVerb, Verb, sizeof( WCHAR ) * VerbSize );
  1209. NewVerb[ VerbSize ] = '\0'; // end the list
  1210. }
  1211. else
  1212. {
  1213. // Loop though the list copying all nonmatching verbs to the new buffer
  1214. // Keep track if list changes
  1215. bool ListChanged = false;
  1216. WCHAR *OriginalVerb = SectionData;
  1217. WCHAR *NewVerb = NewSectionData;
  1218. while( *OriginalVerb )
  1219. {
  1220. if ( wcscmp( OriginalVerb, Verb ) == 0 )
  1221. {
  1222. // verb to remove, skip it
  1223. OriginalVerb += wcslen( OriginalVerb ) + 1;
  1224. ListChanged = true;
  1225. }
  1226. else
  1227. {
  1228. // copy the verb
  1229. SIZE_T VerbSize = wcslen( OriginalVerb ) + 1;
  1230. memcpy( NewVerb, OriginalVerb, sizeof( WCHAR ) * VerbSize );
  1231. OriginalVerb += VerbSize;
  1232. NewVerb += VerbSize;
  1233. }
  1234. }
  1235. if ( !ListChanged )
  1236. {
  1237. return;
  1238. }
  1239. *NewVerb = '\0'; // end the list
  1240. }
  1241. if ( !WritePrivateProfileSectionW(
  1242. Section, // section name
  1243. NewSectionData, // data
  1244. FileName // file name
  1245. ) )
  1246. {
  1247. THROW_COMERROR( HRESULT_FROM_WIN32( GetLastError() ) );
  1248. }
  1249. }
  1250. void ModifyURLScanFiles(
  1251. bool Add )
  1252. {
  1253. // Loop though the list of filters and find valid copies of urlscan.ini
  1254. SmartIADsContainerPointer MbFiltersContainer;
  1255. SmartIEnumVARIANTPointer EnumVariant;
  1256. SmartIADsPointer Filter;
  1257. SmartIUnknownPointer Unknown;
  1258. SmartVariant Var;
  1259. THROW_COMERROR(
  1260. ADsGetObject( L"IIS://LocalHost/W3SVC/Filters",
  1261. MbFiltersContainer.GetUUID(), (void**)MbFiltersContainer.GetRecvPointer() ) );
  1262. THROW_COMERROR( MbFiltersContainer->get__NewEnum( Unknown.GetRecvPointer() ) );
  1263. THROW_COMERROR( Unknown->QueryInterface( EnumVariant.GetUUID(),
  1264. (void**)EnumVariant.GetRecvPointer() ) );
  1265. while( 1 )
  1266. {
  1267. ULONG NumberFetched;
  1268. THROW_COMERROR( EnumVariant->Next( 1, &Var, &NumberFetched ) );
  1269. if ( S_FALSE == Hr )
  1270. {
  1271. // All the filters were looped though.
  1272. return;
  1273. }
  1274. THROW_COMERROR( VariantChangeType( &Var, &Var, 0, VT_UNKNOWN ) );
  1275. THROW_COMERROR( Var.punkVal->QueryInterface( Filter.GetUUID(),
  1276. (void**)Filter.GetRecvPointer() ) );
  1277. VariantClear( &Var );
  1278. THROW_COMERROR( Filter->Get( (BSTR)L"FilterPath", &Var ) );
  1279. THROW_COMERROR( VariantChangeType( &Var, &Var, 0, VT_BSTR ) );
  1280. // Test if this is UrlScan and bash the filepart
  1281. WCHAR * FilterPathString = (WCHAR*)Var.bstrVal;
  1282. SIZE_T FilterPathStringSize = wcslen( FilterPathString );
  1283. const WCHAR UrlScanDllName[] = L"urlscan.dll";
  1284. const WCHAR UrlScanIniName[] = L"urlscan.ini";
  1285. const SIZE_T UrlScanNameSize = sizeof( UrlScanDllName ) / sizeof( *UrlScanDllName );
  1286. if ( FilterPathStringSize < UrlScanNameSize )
  1287. continue;
  1288. WCHAR * FilterPathStringFilePart = FilterPathString + FilterPathStringSize - UrlScanNameSize;
  1289. if ( _wcsicmp( FilterPathStringFilePart, UrlScanDllName ) != 0 )
  1290. continue;
  1291. // this is an urlscan.dll filter, bash the filename to get the ini file name
  1292. wcscpy( FilterPathStringFilePart, UrlScanIniName );
  1293. WCHAR *IniFileName = FilterPathString;
  1294. UINT AllowVerbs =
  1295. GetPrivateProfileIntW(
  1296. L"options",
  1297. L"UseAllowVerbs",
  1298. -1,
  1299. IniFileName );
  1300. if ( AllowVerbs != 0 && AllowVerbs != 1 )
  1301. continue; // missing or broken ini file
  1302. if ( AllowVerbs )
  1303. THROW_COMERROR( ProcessVerbsInIniSection( L"AllowVerbs", L"BITS_POST",
  1304. IniFileName, Add ) );
  1305. else
  1306. THROW_COMERROR( ProcessVerbsInIniSection( L"DenyVerbs", L"BITS_POST",
  1307. IniFileName, !Add ) );
  1308. }
  1309. }
  1310. #endif
  1311. void UpgradeOrDisableVDirs( bool ShouldUpgrade )
  1312. {
  1313. // If ShouldUpgrade is true, then all the BITS virtual directories will be upgraded.
  1314. // If ShouldUpgrade is false, then this is a deinstall then all virtual directories
  1315. // that are enabled will be disabled.
  1316. if ( ShouldUpgrade )
  1317. {
  1318. LogSetup( LogSevInformation, "[BITSSRV] Starting upgrade of virtual directories\r\n" );
  1319. }
  1320. else
  1321. {
  1322. LogSetup( LogSevInformation, "[BITSSRV] Starting disable of virtual directories\r\n" );
  1323. }
  1324. SmartBITSExtensionSetupFactoryPointer SetupFactory;
  1325. SmartMetabasePointer AdminBase;
  1326. {
  1327. HRESULT Hr =
  1328. CoCreateInstance(
  1329. __uuidof( BITSExtensionSetupFactory ),
  1330. NULL,
  1331. CLSCTX_INPROC_SERVER,
  1332. __uuidof( IBITSExtensionSetupFactory ),
  1333. (void**)SetupFactory.GetRecvPointer() );
  1334. if ( REGDB_E_CLASSNOTREG == Hr )
  1335. {
  1336. // This must be a new install, or the factory was never registered
  1337. // Nothing to upgrade. Or the factory was removed.
  1338. LogSetup( LogSevInformation, "[BITSSRV] Nothing to upgrade or disable\r\n" );
  1339. return;
  1340. }
  1341. THROW_COMERROR( Hr );
  1342. }
  1343. THROW_COMERROR(
  1344. CoCreateInstance(
  1345. GETAdminBaseCLSID(TRUE),
  1346. NULL,
  1347. CLSCTX_SERVER,
  1348. AdminBase.GetUUID(),
  1349. (LPVOID*)AdminBase.GetRecvPointer() ) );
  1350. PropertyIDManager PropertyMan;
  1351. THROW_COMERROR( PropertyMan.LoadPropertyInfo() );
  1352. WCHAR *PathBuffer = NULL;
  1353. WCHAR *CurrentPath = NULL;
  1354. BSTR VDirToModifyBSTR = NULL;
  1355. try
  1356. {
  1357. PathBuffer = new WCHAR[ 256 ];
  1358. DWORD RequiredBufferSize = 0;
  1359. {
  1360. HRESULT Hr =
  1361. AdminBase->GetDataPaths(
  1362. METADATA_MASTER_ROOT_HANDLE, //metabase handle.
  1363. L"\\LM\\W3SVC", //path to the key, relative to hMDHandle.
  1364. PropertyMan.GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ), //identifier of the data.
  1365. DWORD_METADATA, //type of data.
  1366. 256, //the size, in wchars, of pbBuffe.r.
  1367. PathBuffer, //the buffer that receives the data.
  1368. &RequiredBufferSize //if the method fails, receives
  1369. );
  1370. if ( SUCCEEDED( Hr ) )
  1371. goto process_buffer;
  1372. if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  1373. throw ComError( Hr );
  1374. }
  1375. delete[] PathBuffer;
  1376. PathBuffer = NULL;
  1377. PathBuffer = new WCHAR[ RequiredBufferSize ];
  1378. THROW_COMERROR(
  1379. AdminBase->GetDataPaths(
  1380. METADATA_MASTER_ROOT_HANDLE, //metabase handle.
  1381. L"\\LM\\W3SVC", //path to the key, relative to hMDHandle.
  1382. PropertyMan.GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED ), //identifier of the data.
  1383. DWORD_METADATA, //type of data.
  1384. RequiredBufferSize, //the size, in wchars, of pbBuffe.r.
  1385. PathBuffer, //the buffer that receives the data.
  1386. &RequiredBufferSize //if the method fails, receives
  1387. ) );
  1388. process_buffer:
  1389. for( CurrentPath = PathBuffer; *CurrentPath; CurrentPath += wcslen( CurrentPath ) + 1 )
  1390. {
  1391. DWORD BufferRequired;
  1392. METADATA_RECORD MdRecord;
  1393. DWORD IsEnabled = 0;
  1394. MdRecord.dwMDIdentifier = PropertyMan.GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  1395. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1396. MdRecord.dwMDUserType = ALL_METADATA;
  1397. MdRecord.dwMDDataType = DWORD_METADATA;
  1398. MdRecord.dwMDDataLen = sizeof(IsEnabled);
  1399. MdRecord.pbMDData = (PBYTE)&IsEnabled;
  1400. MdRecord.dwMDDataTag = 0;
  1401. THROW_COMERROR(
  1402. AdminBase->GetData(
  1403. METADATA_MASTER_ROOT_HANDLE,
  1404. CurrentPath,
  1405. &MdRecord,
  1406. &BufferRequired ) );
  1407. if ( IsEnabled )
  1408. {
  1409. SmartBITSExtensionSetupPointer Setup;
  1410. VDirToModifyBSTR = SysAllocString( CurrentPath );
  1411. LogSetup( LogSevInformation, "[BITSSRV] Handleing upgrade/disable of %S\r\n", (WCHAR*)VDirToModifyBSTR );
  1412. THROW_COMERROR(
  1413. SetupFactory->GetObject( VDirToModifyBSTR, Setup.GetRecvPointer() ) );
  1414. if ( ShouldUpgrade )
  1415. THROW_COMERROR( Setup->EnableBITSUploads() );
  1416. else
  1417. THROW_COMERROR( Setup->DisableBITSUploads() );
  1418. SysFreeString( VDirToModifyBSTR );
  1419. VDirToModifyBSTR = NULL;
  1420. }
  1421. }
  1422. }
  1423. catch( ComError Error )
  1424. {
  1425. if ( PathBuffer )
  1426. delete[] PathBuffer;
  1427. SysFreeString( VDirToModifyBSTR );
  1428. throw Error;
  1429. }
  1430. }
  1431. void
  1432. RemoveProperty(
  1433. SmartMetabasePointer & AdminBase,
  1434. PropertyIDManager & PropertyMan,
  1435. METADATA_HANDLE RootHandle,
  1436. DWORD PropNumber )
  1437. {
  1438. WCHAR *PathBuffer = NULL;
  1439. WCHAR *CurrentPath = NULL;
  1440. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveProperty(PropNumber %u)\r\n", PropNumber );
  1441. try
  1442. {
  1443. PathBuffer = new WCHAR[ 256 ];
  1444. DWORD RequiredBufferSize = 0;
  1445. {
  1446. HRESULT Hr =
  1447. AdminBase->GetDataPaths(
  1448. RootHandle, //metabase handle.
  1449. NULL, //path to the key, relative to hMDHandle.
  1450. PropertyMan.GetPropertyMetabaseID( PropNumber ), //identifier of the data.
  1451. ALL_METADATA, //type of data.
  1452. 256, //the size, in wchars, of pbBuffer.
  1453. PathBuffer, //the buffer that receives the data.
  1454. &RequiredBufferSize //if the method fails, receives
  1455. );
  1456. if ( SUCCEEDED( Hr ) )
  1457. goto process_buffer;
  1458. if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  1459. throw ComError( Hr );
  1460. }
  1461. delete[] PathBuffer;
  1462. PathBuffer = NULL;
  1463. PathBuffer = new WCHAR[ RequiredBufferSize ];
  1464. THROW_COMERROR(
  1465. AdminBase->GetDataPaths(
  1466. RootHandle, //metabase handle.
  1467. NULL, //path to the key, relative to hMDHandle.
  1468. PropertyMan.GetPropertyMetabaseID( PropNumber ), //identifier of the data.
  1469. ALL_METADATA, //type of data.
  1470. RequiredBufferSize, //the size, in wchars, of pbBuffe.r.
  1471. PathBuffer, //the buffer that receives the data.
  1472. &RequiredBufferSize //if the method fails, receives
  1473. ) );
  1474. process_buffer:
  1475. for( CurrentPath = PathBuffer; *CurrentPath; CurrentPath += wcslen( CurrentPath ) + 1 )
  1476. {
  1477. THROW_COMERROR(
  1478. AdminBase->DeleteData(
  1479. RootHandle, //metadata handle.
  1480. CurrentPath, //path to the key relative to hMDHandle.
  1481. PropertyMan.GetPropertyMetabaseID( PropNumber ),//identifier of the data.
  1482. ALL_METADATA //type of data to remove.
  1483. ) );
  1484. }
  1485. }
  1486. catch( ComError Error )
  1487. {
  1488. if ( PathBuffer )
  1489. delete[] PathBuffer;
  1490. throw Error;
  1491. }
  1492. }
  1493. void RemoveMetabaseProperties()
  1494. {
  1495. LogSetup( LogSevInformation, "[BITSSRV] Starting RemoveMetabaseProperties\r\n" );
  1496. SmartMetabasePointer AdminBase;
  1497. THROW_COMERROR(
  1498. CoCreateInstance(
  1499. GETAdminBaseCLSID(TRUE),
  1500. NULL,
  1501. CLSCTX_SERVER,
  1502. AdminBase.GetUUID(),
  1503. (LPVOID*)AdminBase.GetRecvPointer() ) );
  1504. PropertyIDManager PropertyMan;
  1505. THROW_COMERROR( PropertyMan.LoadPropertyInfo() );
  1506. METADATA_HANDLE RootHandle = NULL;
  1507. try
  1508. {
  1509. THROW_COMERROR( AdminBase->OpenKey(
  1510. METADATA_MASTER_ROOT_HANDLE, //metabase handle.
  1511. L"\\LM\\W3SVC", //path to the key, relative to hMDHandle.
  1512. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1513. METABASE_OPEN_KEY_TIMEOUT,
  1514. &RootHandle //receives the handle to the opened key.
  1515. ) );
  1516. for ( SIZE_T i = 0; i < g_NumberOfProperties; i++ )
  1517. {
  1518. RemoveProperty( AdminBase, PropertyMan, RootHandle, g_Properties[i].PropertyNumber );
  1519. }
  1520. AdminBase->CloseKey( RootHandle );
  1521. RootHandle = NULL;
  1522. }
  1523. catch( ComError )
  1524. {
  1525. if ( RootHandle )
  1526. {
  1527. AdminBase->CloseKey( RootHandle );
  1528. }
  1529. throw;
  1530. }
  1531. }
  1532. void FlushMetabase()
  1533. {
  1534. LogSetup( LogSevInformation, "[BITSSRV] Starting FlushMetabase\r\n" );
  1535. SmartMetabasePointer IISAdminBase;
  1536. THROW_COMERROR(
  1537. CoCreateInstance(
  1538. GETAdminBaseCLSID(TRUE),
  1539. NULL,
  1540. CLSCTX_SERVER,
  1541. IISAdminBase.GetUUID(),
  1542. (LPVOID*)IISAdminBase.GetRecvPointer() ) );
  1543. IISAdminBase->SaveData();
  1544. }
  1545. STDAPI DllRegisterServer()
  1546. {
  1547. try
  1548. {
  1549. LogSetup( LogSevInformation, "[BITSSRV] Starting regsvr of bitssrv.dll\r\n" );
  1550. DetectProductVersion();
  1551. InitializeSetup();
  1552. RemoveFilterIfNeeded();
  1553. StartupMSTask();
  1554. InstallPropertySchema();
  1555. InstallDefaultValues();
  1556. ModifyLockdownList( true );
  1557. ModifyLockdownListDisplay( true );
  1558. ModifyInProcessList( true );
  1559. ModifyWebSvcRestrictionList( true );
  1560. #if 0
  1561. ModifyURLScanFiles( true );
  1562. #endif
  1563. UpgradeOrDisableVDirs( true ); // this is an upgrade
  1564. FlushMetabase();
  1565. // Restart of IIS is not needed on windows xp/.NET server
  1566. // IIS is smart enough to pickup the metabase changes
  1567. if ( !g_IsWindowsXP )
  1568. RestartIIS();
  1569. LogSetup( LogSevInformation, "[BITSSRV] Finishing regsvr of bitssrv.dll\r\n" );
  1570. }
  1571. catch( ComError Error )
  1572. {
  1573. LogSetup( LogSevFatalError, "[BITSSRV] Hit fatal error in regsvr32 of bitssrv.dll, error %u\r\n", Error.m_Hr );
  1574. return Error.m_Hr;
  1575. }
  1576. return S_OK;
  1577. }
  1578. STDAPI DllUnregisterServer()
  1579. {
  1580. //
  1581. // Main entry point for setup unregistration
  1582. //
  1583. try
  1584. {
  1585. LogSetup( LogSevInformation, "[BITSSRV] Starting regsvr /u of bitssrv.dll\r\n" );
  1586. DetectProductVersion();
  1587. InitializeSetup();
  1588. UpgradeOrDisableVDirs( false ); // disable all vdirs
  1589. RemoveMetabaseProperties(); // remove all lingering properties
  1590. RemovePropertySchema();
  1591. ModifyLockdownList( false );
  1592. ModifyLockdownListDisplay( false );
  1593. ModifyInProcessList( false );
  1594. ModifyWebSvcRestrictionList( false );
  1595. FlushMetabase();
  1596. // restart IIS to force an unload of the ISAPI
  1597. RestartIIS();
  1598. LogSetup( LogSevInformation, "[BITSSRV] Finishing regsvr /u of bitssrv.dll\r\n" );
  1599. }
  1600. catch( ComError Error )
  1601. {
  1602. LogSetup( LogSevFatalError, "[BITSSRV] Hit fatal error in regsvr32 /u of bitssrv.dll, error %u\r\n", Error.m_Hr );
  1603. return Error.m_Hr;
  1604. }
  1605. return S_OK;
  1606. }