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.

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