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.

2003 lines
48 KiB

  1. /************************************************************************
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name :
  4. config.cpp
  5. Abstract :
  6. Configuration APIs
  7. Author :
  8. Revision History :
  9. ***********************************************************************/
  10. #include "precomp.h"
  11. #pragma warning( disable : 4355 )
  12. WCHAR *
  13. ConvertObjectPathToADSI(
  14. const WCHAR *ObjectPath )
  15. {
  16. WCHAR * ReturnPath = NULL;
  17. SIZE_T ReturnPathSize = 0;
  18. if ( _wcsnicmp( L"IIS://", (WCHAR*)ObjectPath, wcslen( L"IIS://") ) == 0 )
  19. {
  20. // already have an adsi path
  21. ReturnPathSize = wcslen( ObjectPath ) + 1;
  22. ReturnPath = new WCHAR[ ReturnPathSize ];
  23. if ( !ReturnPath )
  24. throw ComError( E_OUTOFMEMORY );
  25. memcpy( ReturnPath, ObjectPath, ReturnPathSize * sizeof( WCHAR ) );
  26. }
  27. else if ( _wcsnicmp( L"/LM/", (WCHAR*)ObjectPath, wcslen( L"/LM/" ) ) == 0 )
  28. {
  29. //metabase path to local machine
  30. ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
  31. ReturnPath = new WCHAR[ ReturnPathSize ];
  32. if ( !ReturnPath )
  33. throw ComError( E_OUTOFMEMORY );
  34. StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
  35. StringCchCatW( ReturnPath, ReturnPathSize, ObjectPath + wcslen( L"/LM/" ) );
  36. }
  37. else if ( _wcsnicmp( L"LM/", (WCHAR*)ObjectPath, wcslen( L"LM/" ) ) == 0 )
  38. {
  39. //metabase path to local machine
  40. ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://LocalHost/" ) + 1;
  41. ReturnPath = new WCHAR[ ReturnPathSize ];
  42. if ( !ReturnPath )
  43. throw ComError( E_OUTOFMEMORY );
  44. StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://LocalHost/" );
  45. StringCchCatW( ReturnPath, ReturnPathSize, ObjectPath + wcslen( L"LM/" ) );
  46. }
  47. else
  48. {
  49. //metabase path to another server
  50. ReturnPathSize = wcslen( (WCHAR*)ObjectPath ) + wcslen( L"IIS://" ) + 1;
  51. ReturnPath = new WCHAR[ ReturnPathSize ];
  52. if ( !ReturnPath )
  53. throw ComError( E_OUTOFMEMORY );
  54. if ( '/' == *(WCHAR*)ObjectPath )
  55. StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS:/" );
  56. else
  57. StringCchCopyW( ReturnPath, ReturnPathSize, L"IIS://" );
  58. StringCchCatW( ReturnPath, ReturnPathSize, (WCHAR*)ObjectPath );
  59. }
  60. return ReturnPath;
  61. }
  62. HRESULT
  63. GetTypeInfo(
  64. const GUID & guid,
  65. ITypeInfo **TypeInfo )
  66. {
  67. DWORD Result;
  68. HRESULT hr;
  69. WCHAR DllName[ MAX_PATH ];
  70. Result =
  71. GetModuleFileName(
  72. g_hinst,
  73. DllName,
  74. MAX_PATH - 1 );
  75. if ( !Result )
  76. return HRESULT_FROM_WIN32( GetLastError() );
  77. ITypeLib *TypeLib;
  78. hr = LoadTypeLibEx(
  79. DllName,
  80. REGKIND_NONE,
  81. &TypeLib );
  82. if ( FAILED( hr ) )
  83. return hr;
  84. hr = TypeLib->GetTypeInfoOfGuid(
  85. guid,
  86. TypeInfo );
  87. TypeLib->Release();
  88. return hr;
  89. }
  90. void
  91. FreeReturnedWorkItems(
  92. ULONG NamesReturned,
  93. LPWSTR **ItemNamesPtr )
  94. {
  95. LPWSTR *ItemNames = *ItemNamesPtr;
  96. if ( ItemNames )
  97. {
  98. for( ULONG i = 0; i < NamesReturned; i++ )
  99. {
  100. CoTaskMemFree( ItemNames[i] );
  101. }
  102. CoTaskMemFree( ItemNames );
  103. *ItemNamesPtr = NULL;
  104. }
  105. }
  106. HRESULT
  107. FindWorkItemForVDIR(
  108. ITaskScheduler *TaskScheduler,
  109. LPCWSTR Key,
  110. ITask **ReturnedTask,
  111. LPWSTR *ReturnedTaskName )
  112. {
  113. HRESULT Hr;
  114. SIZE_T KeyLength = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
  115. WORD DataLength;
  116. if ( ReturnedTask )
  117. *ReturnedTask = NULL;
  118. if ( ReturnedTaskName )
  119. *ReturnedTaskName = NULL;
  120. ITask *Task = NULL;
  121. IEnumWorkItems *EnumWorkItems = NULL;
  122. LPWSTR *ItemNames = NULL;
  123. BYTE *ItemData = NULL;
  124. ULONG NamesReturned = 0;
  125. try
  126. {
  127. THROW_COMERROR( TaskScheduler->Enum( &EnumWorkItems ) );
  128. while( 1 )
  129. {
  130. THROW_COMERROR( EnumWorkItems->Next( 255, &ItemNames, &NamesReturned ) );
  131. if ( !NamesReturned )
  132. throw ComError( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
  133. for ( ULONG i = 0; i < NamesReturned; i++ )
  134. {
  135. THROW_COMERROR( TaskScheduler->Activate( ItemNames[i], __uuidof( *Task ), (IUnknown**)&Task ) );
  136. THROW_COMERROR( Task->GetWorkItemData( &DataLength, &ItemData ) );
  137. if ( KeyLength == DataLength &&
  138. ( wcscmp( Key, (WCHAR*)ItemData ) == 0 ) )
  139. {
  140. // Found the item, cleanup and return
  141. if ( ReturnedTask )
  142. *ReturnedTask = Task;
  143. else
  144. Task->Release();
  145. if ( ReturnedTaskName )
  146. {
  147. *ReturnedTaskName = ItemNames[i];
  148. ItemNames[i] = NULL;
  149. }
  150. FreeReturnedWorkItems(
  151. NamesReturned,
  152. &ItemNames );
  153. EnumWorkItems->Release();
  154. CoTaskMemFree( ItemData );
  155. return S_OK;
  156. }
  157. Task->Release();
  158. Task = NULL;
  159. CoTaskMemFree( ItemData );
  160. ItemData = NULL;
  161. }
  162. FreeReturnedWorkItems(
  163. NamesReturned,
  164. &ItemNames );
  165. NamesReturned = 0;
  166. }
  167. }
  168. catch( ComError Error )
  169. {
  170. if ( EnumWorkItems )
  171. EnumWorkItems->Release();
  172. if ( Task )
  173. Task->Release();
  174. FreeReturnedWorkItems(
  175. NamesReturned,
  176. &ItemNames );
  177. CoTaskMemFree( ItemData );
  178. return Error.m_Hr;
  179. }
  180. }
  181. HRESULT
  182. CreateWorkItemForVDIR(
  183. ITaskScheduler *TaskScheduler,
  184. LPCWSTR Path,
  185. LPCWSTR Key )
  186. {
  187. WORD KeySize = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
  188. WCHAR ItemNameFormat[ MAX_PATH ];
  189. WCHAR ItemName[ MAX_PATH * 4 ];
  190. WCHAR Parameters[ MAX_PATH * 4];
  191. LoadString( g_hinst, IDS_WORK_ITEM_NAME, ItemNameFormat, MAX_PATH - 1 );
  192. // Use the last part of the path for the description
  193. const WCHAR *ShortPath = Path + wcslen( Path );
  194. while( *ShortPath != L'/' &&
  195. *ShortPath != L'\\' &&
  196. ShortPath != Path )
  197. ShortPath--;
  198. if ( *ShortPath == L'/' ||
  199. *ShortPath == L'\\' )
  200. ShortPath++;
  201. DWORD Result;
  202. void* InsertArray[2] = { (void*)ShortPath, (void*)Key };
  203. Result = FormatMessage(
  204. FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  205. (LPCVOID)ItemNameFormat,
  206. 0,
  207. 0,
  208. ItemName,
  209. MAX_PATH * 4,
  210. (va_list*)InsertArray );
  211. if ( !Result )
  212. return HRESULT_FROM_WIN32( GetLastError() );
  213. StringCbPrintfW(
  214. Parameters,
  215. sizeof( Parameters ),
  216. L"bitsmgr.dll,Cleanup_RunDLL %s \"%s\" %s", Path, ItemName, Key );
  217. WORD TriggerNumber;
  218. ITask *Task = NULL;
  219. ITaskTrigger *TaskTrigger = NULL;
  220. IPersistFile *PersistFile = NULL;
  221. try
  222. {
  223. HRESULT Hr;
  224. Hr = FindWorkItemForVDIR( TaskScheduler, Key, &Task, NULL );
  225. if ( SUCCEEDED( Hr ) )
  226. {
  227. // The work item already exists
  228. Task->Release();
  229. return S_OK;
  230. }
  231. if ( FAILED(Hr) && HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) != Hr )
  232. THROW_COMERROR( Hr );
  233. THROW_COMERROR( TaskScheduler->NewWorkItem( ItemName, CLSID_CTask, __uuidof( *Task ), (IUnknown**)&Task ) );
  234. // Set basic task data
  235. THROW_COMERROR( Task->SetApplicationName( L"%SystemRoot%\\system32\\rundll32.exe" ) );
  236. THROW_COMERROR( Task->SetMaxRunTime( INFINITE ) );
  237. THROW_COMERROR( Task->SetParameters( Parameters ) );
  238. THROW_COMERROR( Task->SetPriority( IDLE_PRIORITY_CLASS ) );
  239. THROW_COMERROR( Task->SetAccountInformation( L"", NULL ) ); //Run as localsystem
  240. THROW_COMERROR( Task->SetFlags( TASK_FLAG_RUN_ONLY_IF_LOGGED_ON | TASK_FLAG_HIDDEN ) );
  241. THROW_COMERROR( Task->SetWorkItemData( KeySize, (BYTE*)Key ) );
  242. // set trigger information. Set start time to now, with a default
  243. // interval of once a day.
  244. THROW_COMERROR( Task->CreateTrigger( &TriggerNumber, &TaskTrigger ) );
  245. SYSTEMTIME LocalTime;
  246. GetLocalTime( &LocalTime );
  247. TASK_TRIGGER Trigger;
  248. memset( &Trigger, 0, sizeof( Trigger ) );
  249. Trigger.cbTriggerSize = sizeof(Trigger);
  250. Trigger.wBeginYear = LocalTime.wYear;
  251. Trigger.wBeginMonth = LocalTime.wMonth;
  252. Trigger.wBeginDay = LocalTime.wDay;
  253. Trigger.wStartHour = LocalTime.wHour;
  254. Trigger.wStartMinute = LocalTime.wMinute;
  255. Trigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
  256. Trigger.MinutesDuration = 24 * 60; // 24 hours per day
  257. Trigger.MinutesInterval = 12 * 60; // twice per day
  258. Trigger.Type.Daily.DaysInterval = 1;
  259. THROW_COMERROR( TaskTrigger->SetTrigger( &Trigger ) );
  260. // Commit the changes to disk.
  261. THROW_COMERROR( Task->QueryInterface( __uuidof( IPersistFile ), (void**)&PersistFile ) );
  262. THROW_COMERROR( PersistFile->Save( NULL, TRUE ) );
  263. PersistFile->Release();
  264. TaskTrigger->Release();
  265. Task->Release();
  266. return S_OK;
  267. }
  268. catch( ComError Error )
  269. {
  270. if ( TaskTrigger )
  271. TaskTrigger->Release();
  272. if ( Task )
  273. Task->Release();
  274. if ( PersistFile )
  275. PersistFile->Release();
  276. TaskScheduler->Delete( ItemName );
  277. return Error.m_Hr;
  278. }
  279. }
  280. HRESULT
  281. DeleteWorkItemForVDIR(
  282. ITaskScheduler *TaskScheduler,
  283. LPWSTR Key )
  284. {
  285. HRESULT Hr;
  286. LPWSTR TaskName = NULL;
  287. Hr = FindWorkItemForVDIR( TaskScheduler, Key, NULL, &TaskName );
  288. if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Hr )
  289. return S_OK;
  290. if ( FAILED( Hr ) )
  291. return Hr;
  292. Hr = TaskScheduler->Delete( TaskName );
  293. CoTaskMemFree( TaskName );
  294. return Hr;
  295. }
  296. HRESULT
  297. ConnectToTaskScheduler(
  298. LPWSTR ComputerName,
  299. ITaskScheduler ** TaskScheduler )
  300. {
  301. HRESULT Hr;
  302. Hr = CoCreateInstance(
  303. CLSID_CTaskScheduler,
  304. NULL,
  305. CLSCTX_INPROC_SERVER,
  306. __uuidof( **TaskScheduler ),
  307. (void **) TaskScheduler );
  308. if ( FAILED( Hr ) )
  309. return Hr;
  310. Hr = (*TaskScheduler)->SetTargetComputer( ComputerName );
  311. if ( FAILED( Hr ) )
  312. {
  313. (*TaskScheduler)->Release();
  314. (*TaskScheduler) = NULL;
  315. return Hr;
  316. }
  317. return S_OK;
  318. }
  319. HRESULT
  320. IsBITSEnabledOnVDir(
  321. PropertyIDManager *PropertyManager,
  322. IMSAdminBase *IISAdminBase,
  323. LPWSTR VirtualDirectory,
  324. BOOL *IsEnabled )
  325. {
  326. HRESULT Hr;
  327. DWORD BufferRequired;
  328. *IsEnabled = false;
  329. DWORD IsEnabledVal;
  330. METADATA_RECORD MdRecord;
  331. memset( &MdRecord, 0, sizeof( MdRecord ) );
  332. MdRecord.dwMDDataType = DWORD_METADATA;
  333. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  334. MdRecord.dwMDDataLen = sizeof(IsEnabled);
  335. MdRecord.pbMDData = (PBYTE)&IsEnabledVal;
  336. Hr =
  337. IISAdminBase->GetData(
  338. METADATA_MASTER_ROOT_HANDLE,
  339. VirtualDirectory,
  340. &MdRecord,
  341. &BufferRequired );
  342. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  343. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  344. return S_OK;
  345. if ( FAILED( Hr ) )
  346. return Hr;
  347. *IsEnabled = IsEnabledVal ? true : false;
  348. return S_OK;
  349. }
  350. HRESULT
  351. EnableBITSForVDIR(
  352. PropertyIDManager *PropertyManager,
  353. IMSAdminBase *IISAdminBase,
  354. LPCWSTR Path )
  355. {
  356. HRESULT Hr;
  357. METADATA_HANDLE MdVDirKey = NULL;
  358. LPWSTR NewScriptMapBuffer = NULL;
  359. ITaskScheduler* TaskScheduler = NULL;
  360. try
  361. {
  362. Hr = DisableBITSForVDIR(
  363. PropertyManager,
  364. IISAdminBase,
  365. Path,
  366. true );
  367. if ( FAILED( Hr ) )
  368. throw ComError( Hr );
  369. // build the string to add to the scriptmap
  370. WCHAR SystemDir[ MAX_PATH + 1 ];
  371. if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) )
  372. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  373. WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
  374. StringCbPrintfW(
  375. ScriptMapString,
  376. sizeof( ScriptMapString ),
  377. L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW,
  378. SystemDir );
  379. int RetChars = wcslen( ScriptMapString );
  380. ScriptMapString[ RetChars ] = L'\0';
  381. ScriptMapString[ RetChars + 1] = L'\0';
  382. RetChars += 2; // ScriptMapScript is now double NULL terminated
  383. Hr =
  384. IISAdminBase->OpenKey(
  385. METADATA_MASTER_ROOT_HANDLE,
  386. Path,
  387. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  388. 30000,
  389. &MdVDirKey );
  390. if (FAILED(Hr))
  391. throw ComError(Hr);
  392. DWORD IsEnabled;
  393. DWORD BufferRequired;
  394. METADATA_RECORD MdRecord;
  395. DWORD AccessFlags;
  396. MdRecord.dwMDIdentifier = MD_ACCESS_PERM;
  397. MdRecord.dwMDAttributes = METADATA_INHERIT;
  398. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  399. MdRecord.dwMDDataType = DWORD_METADATA;
  400. MdRecord.dwMDDataLen = sizeof( AccessFlags );
  401. MdRecord.pbMDData = (unsigned char*)&AccessFlags;
  402. MdRecord.dwMDDataTag = 0;
  403. Hr =
  404. IISAdminBase->GetData(
  405. MdVDirKey,
  406. NULL,
  407. &MdRecord,
  408. &BufferRequired );
  409. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  410. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  411. {
  412. AccessFlags = 0;
  413. }
  414. else if ( FAILED( Hr ) )
  415. {
  416. throw ComError( Hr );
  417. }
  418. if ( AccessFlags & ( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE ) )
  419. {
  420. AccessFlags &= ~( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE );
  421. MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
  422. Hr =
  423. IISAdminBase->SetData(
  424. MdVDirKey,
  425. NULL,
  426. &MdRecord );
  427. if ( FAILED( Hr ) )
  428. throw ComError( Hr );
  429. }
  430. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  431. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  432. MdRecord.dwMDUserType = ALL_METADATA;
  433. MdRecord.dwMDDataType = DWORD_METADATA;
  434. MdRecord.dwMDDataLen = sizeof(IsEnabled);
  435. MdRecord.pbMDData = (PBYTE)&IsEnabled;
  436. MdRecord.dwMDDataTag = 0;
  437. Hr =
  438. IISAdminBase->GetData(
  439. MdVDirKey,
  440. NULL,
  441. &MdRecord,
  442. &BufferRequired );
  443. if ( FAILED( Hr ) )
  444. {
  445. if ( !( MD_ERROR_DATA_NOT_FOUND == Hr ||
  446. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) )
  447. {
  448. IISAdminBase->CloseKey( MdVDirKey );
  449. return S_OK;
  450. }
  451. }
  452. else if ( IsEnabled )
  453. {
  454. IISAdminBase->CloseKey( MdVDirKey );
  455. return S_OK;
  456. }
  457. //
  458. // retrieve the current scriptmap adding room to the allocated memory
  459. //
  460. memset( &MdRecord, 0, sizeof( MdRecord ) );
  461. MdRecord.dwMDDataType = MULTISZ_METADATA;
  462. MdRecord.dwMDAttributes = METADATA_INHERIT;
  463. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  464. MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS;
  465. MdRecord.dwMDDataLen = 0;
  466. MdRecord.pbMDData = (PBYTE)NULL;
  467. Hr =
  468. IISAdminBase->GetData(
  469. MdVDirKey,
  470. NULL,
  471. &MdRecord,
  472. &BufferRequired );
  473. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  474. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  475. {
  476. // The Current key doesn't exist.
  477. MdRecord.pbMDData = (PBYTE)ScriptMapString;
  478. MdRecord.dwMDDataLen = RetChars * sizeof(WCHAR);
  479. }
  480. else if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == Hr )
  481. {
  482. NewScriptMapBuffer = new WCHAR[ ( BufferRequired / sizeof(WCHAR) ) + RetChars ];
  483. MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer;
  484. MdRecord.dwMDDataLen = BufferRequired + ( RetChars * sizeof(WCHAR) );
  485. Hr =
  486. IISAdminBase->GetData(
  487. MdVDirKey,
  488. NULL,
  489. &MdRecord,
  490. &BufferRequired );
  491. if ( FAILED(Hr) )
  492. throw ComError( Hr );
  493. // append script entry at the end
  494. for( WCHAR *p = NewScriptMapBuffer; *p != 0; p += ( wcslen( p ) + 1 ) );
  495. memcpy( p, ScriptMapString, RetChars * sizeof(WCHAR) );
  496. MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer;
  497. MdRecord.dwMDDataLen = (DWORD)( ( (char*)p - (char*)NewScriptMapBuffer ) +
  498. ( RetChars * sizeof(WCHAR) ) );
  499. }
  500. else
  501. throw ComError( Hr );
  502. // Write out the new values starting with ScriptMap
  503. Hr =
  504. IISAdminBase->SetData(
  505. MdVDirKey,
  506. NULL,
  507. &MdRecord );
  508. if ( FAILED( Hr ) )
  509. throw ComError( Hr );
  510. // Set the enabled property
  511. DWORD EnableData = 1;
  512. memset( &MdRecord, 0, sizeof( MdRecord ) );
  513. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  514. MdRecord.dwMDDataType = DWORD_METADATA;
  515. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED );
  516. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  517. MdRecord.dwMDDataLen = sizeof(EnableData);
  518. MdRecord.pbMDData = (PBYTE)&EnableData;
  519. Hr =
  520. IISAdminBase->SetData(
  521. MdVDirKey,
  522. NULL,
  523. &MdRecord );
  524. if ( FAILED( Hr ) )
  525. throw ComError( Hr );
  526. delete[] NewScriptMapBuffer;
  527. // Create the task scheduler cleanup work item
  528. WCHAR GuidString[ 255 ];
  529. // first try looking up the guid
  530. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  531. MdRecord.dwMDDataType = STRING_METADATA;
  532. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  533. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  534. MdRecord.dwMDDataLen = sizeof( GuidString );
  535. MdRecord.pbMDData = (PBYTE)GuidString;
  536. MdRecord.dwMDDataTag = 0;
  537. Hr = IISAdminBase->GetData(
  538. MdVDirKey,
  539. NULL,
  540. &MdRecord,
  541. &BufferRequired );
  542. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  543. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  544. {
  545. // create a new guid and save it away
  546. GUID guid;
  547. THROW_COMERROR( CoCreateGuid( &guid ) );
  548. StringFromGUID2( guid, GuidString, 254 );
  549. MdRecord.dwMDDataLen = sizeof(WCHAR) * ( wcslen(GuidString) + 1 );
  550. MdRecord.pbMDData = (PBYTE)GuidString;
  551. THROW_COMERROR(
  552. IISAdminBase->SetData(
  553. MdVDirKey,
  554. NULL,
  555. &MdRecord ) );
  556. }
  557. else if ( FAILED( Hr ) )
  558. throw ComError( Hr );
  559. THROW_COMERROR( ConnectToTaskScheduler( NULL, &TaskScheduler ) );
  560. THROW_COMERROR( CreateWorkItemForVDIR( TaskScheduler, Path, GuidString ) );
  561. TaskScheduler->Release();
  562. IISAdminBase->CloseKey( MdVDirKey );
  563. return S_OK;
  564. }
  565. catch( ComError Exception )
  566. {
  567. if ( TaskScheduler )
  568. TaskScheduler->Release();
  569. DisableBITSForVDIR(
  570. PropertyManager,
  571. IISAdminBase,
  572. Path,
  573. false );
  574. delete[] NewScriptMapBuffer;
  575. if ( MdVDirKey )
  576. IISAdminBase->CloseKey( MdVDirKey );
  577. return Exception.m_Hr;
  578. }
  579. }
  580. HRESULT
  581. DisableBITSForVDIR(
  582. PropertyIDManager *PropertyManager,
  583. IMSAdminBase *IISAdminBase,
  584. LPCWSTR Path,
  585. bool DisableForEnable )
  586. {
  587. HRESULT Hr;
  588. METADATA_HANDLE MdVDirKey = NULL;
  589. LPWSTR OriginalScriptMap = NULL;
  590. LPWSTR NewScriptMap = NULL;
  591. ITaskScheduler* TaskScheduler = NULL;
  592. try
  593. {
  594. if ( !DisableForEnable )
  595. CleanupForRemoval( Path );
  596. // build the string to add to the scriptmap
  597. WCHAR SystemDir[ MAX_PATH + 1 ];
  598. if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) )
  599. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  600. WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
  601. StringCchPrintfW(
  602. ScriptMapString,
  603. MAX_PATH * 2 + 1,
  604. L"*,%s\\bitssrv.dll,1,BITS_COMMAND",
  605. SystemDir );
  606. int RetChars = wcslen( ScriptMapString );
  607. ScriptMapString[ RetChars ] = L'\0';
  608. ScriptMapString[ RetChars + 1] = L'\0';
  609. // ScriptMapScript is now double NULL terminated
  610. WCHAR ScriptMapString2[ MAX_PATH * 2 + 1];
  611. StringCbPrintfW(
  612. ScriptMapString2,
  613. sizeof( ScriptMapString2 ),
  614. L"*,%\\bitsserver.dll,1,BITS_COMMAND",
  615. SystemDir );
  616. RetChars = wcslen( ScriptMapString2 );
  617. ScriptMapString2[ RetChars ] = L'\0';
  618. ScriptMapString2[ RetChars + 1 ] = L'\0';
  619. // ScriptMapScript2 is not double NULL terminated
  620. WCHAR ScriptMapString3[ MAX_PATH * 2 + 1 ];
  621. StringCbPrintfW(
  622. ScriptMapString3,
  623. sizeof( ScriptMapString3 ),
  624. L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW,
  625. SystemDir );
  626. RetChars = wcslen( ScriptMapString3 );
  627. ScriptMapString3[ RetChars ] = L'\0';
  628. ScriptMapString3[ RetChars + 1] = L'\0';
  629. // ScriptMapScript3 is now double NULL terminated
  630. THROW_COMERROR(
  631. IISAdminBase->OpenKey(
  632. METADATA_MASTER_ROOT_HANDLE,
  633. Path,
  634. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  635. 30000,
  636. &MdVDirKey ) );
  637. //
  638. // retrieve the current scriptmap adding room to the allocated memory
  639. //
  640. DWORD BufferRequired;
  641. METADATA_RECORD MdRecord;
  642. memset( &MdRecord, 0, sizeof( MdRecord ) );
  643. MdRecord.dwMDDataType = MULTISZ_METADATA;
  644. MdRecord.dwMDAttributes = METADATA_INHERIT;
  645. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  646. MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS;
  647. MdRecord.dwMDDataLen = 0;
  648. MdRecord.pbMDData = (PBYTE)NULL;
  649. Hr =
  650. IISAdminBase->GetData(
  651. MdVDirKey,
  652. NULL,
  653. &MdRecord,
  654. &BufferRequired );
  655. if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  656. throw ComError( Hr );
  657. OriginalScriptMap = new WCHAR[ BufferRequired / 2 + 2 ];
  658. NewScriptMap = new WCHAR[ BufferRequired / 2 + 2 ];
  659. OriginalScriptMap[0] = OriginalScriptMap[1] = L'\0';
  660. MdRecord.dwMDDataLen = BufferRequired;
  661. MdRecord.pbMDData = (PBYTE)OriginalScriptMap;
  662. Hr =
  663. IISAdminBase->GetData(
  664. MdVDirKey,
  665. NULL,
  666. &MdRecord,
  667. &BufferRequired );
  668. if ( FAILED(Hr) )
  669. throw ComError( Hr );
  670. // Copy the orignal Scriptmap to the new scriptmap
  671. // removing bits goo in the process.
  672. LPWSTR CurrentOriginalItem = OriginalScriptMap;
  673. LPWSTR CurrentNewItem = NewScriptMap;
  674. for( ;L'\0' != *CurrentOriginalItem;
  675. CurrentOriginalItem += ( wcslen( CurrentOriginalItem ) + 1 ) )
  676. {
  677. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString ) == 0 )
  678. continue; //remove this item
  679. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString2 ) == 0 )
  680. continue;
  681. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString3 ) == 0 )
  682. continue;
  683. SIZE_T CurrentOriginalItemSize = wcslen( CurrentOriginalItem ) + 1;
  684. memcpy( CurrentNewItem, CurrentOriginalItem, CurrentOriginalItemSize * sizeof( WCHAR ) );
  685. CurrentNewItem += CurrentOriginalItemSize;
  686. }
  687. // Add the extra 0
  688. *CurrentNewItem++ = L'\0';
  689. MdRecord.dwMDDataLen = (DWORD)( (char*)CurrentNewItem - (char*)NewScriptMap );
  690. MdRecord.pbMDData = (PBYTE)NewScriptMap;
  691. // Set the is enabled property first
  692. DWORD EnableData = 0;
  693. METADATA_RECORD MdEnabledRecord;
  694. memset( &MdEnabledRecord, 0, sizeof( MdEnabledRecord ) );
  695. MdEnabledRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  696. MdEnabledRecord.dwMDDataType = DWORD_METADATA;
  697. MdEnabledRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED );
  698. MdEnabledRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  699. MdEnabledRecord.dwMDDataLen = sizeof(EnableData);
  700. MdEnabledRecord.pbMDData = (PBYTE)&EnableData;
  701. Hr =
  702. IISAdminBase->SetData(
  703. MdVDirKey,
  704. NULL,
  705. &MdEnabledRecord );
  706. if ( FAILED( Hr ) )
  707. throw ComError( Hr );
  708. // set the new scriptmap
  709. Hr =
  710. IISAdminBase->SetData(
  711. MdVDirKey,
  712. NULL,
  713. &MdRecord );
  714. if ( FAILED( Hr ) )
  715. throw ComError( Hr );
  716. WCHAR GuidString[ 255 ];
  717. memset( &MdRecord, 0, sizeof( MdRecord ) );
  718. MdRecord.dwMDDataType = STRING_METADATA;
  719. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  720. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  721. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  722. MdRecord.dwMDDataLen = sizeof( GuidString );
  723. MdRecord.pbMDData = (PBYTE)GuidString;
  724. Hr =
  725. IISAdminBase->GetData(
  726. MdVDirKey,
  727. NULL,
  728. &MdRecord,
  729. &BufferRequired );
  730. if ( FAILED( Hr ) && Hr != MD_ERROR_DATA_NOT_FOUND )
  731. throw ComError( Hr );
  732. if ( SUCCEEDED( Hr ) && !DisableForEnable )
  733. {
  734. THROW_COMERROR( ConnectToTaskScheduler( NULL, &TaskScheduler ) );
  735. THROW_COMERROR( DeleteWorkItemForVDIR( TaskScheduler, GuidString ) );
  736. TaskScheduler->Release();
  737. THROW_COMERROR(
  738. IISAdminBase->DeleteData(
  739. MdVDirKey,
  740. NULL,
  741. PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ),
  742. ALL_METADATA ) );
  743. }
  744. delete[] OriginalScriptMap;
  745. delete[] NewScriptMap;
  746. IISAdminBase->CloseKey( MdVDirKey );
  747. MdVDirKey = NULL;
  748. return S_OK;
  749. }
  750. catch( ComError Exception )
  751. {
  752. if ( TaskScheduler )
  753. TaskScheduler->Release();
  754. delete[] OriginalScriptMap;
  755. delete[] NewScriptMap;
  756. if ( MdVDirKey )
  757. IISAdminBase->CloseKey( MdVDirKey );
  758. return Exception.m_Hr;
  759. }
  760. }
  761. HRESULT
  762. FindWorkItemForVDIR(
  763. PropertyIDManager *PropertyManager,
  764. IMSAdminBase *AdminBase,
  765. LPCWSTR Path,
  766. LPWSTR *ReturnedTaskName )
  767. {
  768. if ( ReturnedTaskName )
  769. *ReturnedTaskName = NULL;
  770. WCHAR GuidString[ 255 ];
  771. DWORD BufferRequired;
  772. METADATA_RECORD MdRecord;
  773. HRESULT Hr;
  774. MdRecord.dwMDDataType = STRING_METADATA;
  775. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  776. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  777. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  778. MdRecord.dwMDDataLen = sizeof( GuidString );
  779. MdRecord.pbMDData = (PBYTE)GuidString;
  780. MdRecord.dwMDDataTag = 0;
  781. Hr =
  782. AdminBase->GetData(
  783. METADATA_MASTER_ROOT_HANDLE,
  784. Path,
  785. &MdRecord,
  786. &BufferRequired );
  787. if ( MD_ERROR_DATA_NOT_FOUND == Hr )
  788. return S_FALSE;
  789. ITaskScheduler* TaskScheduler = NULL;
  790. Hr = ConnectToTaskScheduler( NULL, &TaskScheduler );
  791. if ( FAILED( Hr ) )
  792. return Hr;
  793. Hr = FindWorkItemForVDIR( TaskScheduler, GuidString, NULL, ReturnedTaskName );
  794. // simply return NULL if the task item isn't found.
  795. if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Hr )
  796. Hr = S_FALSE;
  797. TaskScheduler->Release();
  798. return Hr;
  799. }
  800. CBITSExtensionSetupFactory::CBITSExtensionSetupFactory() :
  801. m_cref(1),
  802. m_TypeInfo(NULL)
  803. {
  804. OBJECT_CREATED
  805. }
  806. CBITSExtensionSetupFactory::~CBITSExtensionSetupFactory()
  807. {
  808. if ( m_TypeInfo )
  809. m_TypeInfo->Release();
  810. OBJECT_DESTROYED
  811. }
  812. STDMETHODIMP CBITSExtensionSetupFactory::QueryInterface(REFIID riid, LPVOID *ppv)
  813. {
  814. if (!ppv)
  815. return E_FAIL;
  816. *ppv = NULL;
  817. if (IsEqualIID(riid, IID_IUnknown))
  818. *ppv = static_cast<IUnknown *>(this);
  819. else if (IsEqualIID(riid, __uuidof(IBITSExtensionSetupFactory)))
  820. *ppv = static_cast<IBITSExtensionSetupFactory *>(this);
  821. if (*ppv)
  822. {
  823. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  824. return S_OK;
  825. }
  826. return E_NOINTERFACE;
  827. }
  828. STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::AddRef()
  829. {
  830. return InterlockedIncrement((LONG *)&m_cref);
  831. }
  832. STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::Release()
  833. {
  834. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  835. {
  836. // we need to decrement our object count in the DLL
  837. delete this;
  838. return 0;
  839. }
  840. return m_cref;
  841. }
  842. HRESULT
  843. CBITSExtensionSetupFactory::LoadTypeInfo()
  844. {
  845. if ( m_TypeInfo )
  846. return S_OK;
  847. return ::GetTypeInfo( __uuidof( IBITSExtensionSetupFactory ), &m_TypeInfo );
  848. }
  849. STDMETHODIMP
  850. CBITSExtensionSetupFactory::GetIDsOfNames(
  851. REFIID,
  852. OLECHAR FAR* FAR* rgszNames,
  853. unsigned int cNames,
  854. LCID,
  855. DISPID FAR* rgDispId )
  856. {
  857. HRESULT Hr;
  858. Hr = LoadTypeInfo();
  859. if ( FAILED( Hr ) )
  860. return Hr;
  861. return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
  862. }
  863. STDMETHODIMP
  864. CBITSExtensionSetupFactory::GetTypeInfo(
  865. unsigned int iTInfo,
  866. LCID lcid,
  867. ITypeInfo FAR* FAR* ppTInfo )
  868. {
  869. *ppTInfo = NULL;
  870. if(iTInfo != 0)
  871. return ResultFromScode(DISP_E_BADINDEX);
  872. HRESULT Hr;
  873. Hr = LoadTypeInfo();
  874. if ( FAILED( Hr ) )
  875. return Hr;
  876. m_TypeInfo->AddRef();
  877. *ppTInfo = m_TypeInfo;
  878. return NOERROR;
  879. }
  880. STDMETHODIMP
  881. CBITSExtensionSetupFactory::GetTypeInfoCount(
  882. unsigned int FAR* pctinfo )
  883. {
  884. *pctinfo = 1;
  885. return NOERROR;
  886. }
  887. STDMETHODIMP
  888. CBITSExtensionSetupFactory::Invoke(
  889. DISPID dispIdMember,
  890. REFIID,
  891. LCID,
  892. WORD wFlags,
  893. DISPPARAMS FAR* pDispParams,
  894. VARIANT FAR* pVarResult,
  895. EXCEPINFO FAR* pExcepInfo,
  896. unsigned int FAR* puArgErr )
  897. {
  898. HRESULT Hr;
  899. Hr = LoadTypeInfo();
  900. if ( FAILED( Hr ) )
  901. return Hr;
  902. return
  903. DispInvoke(
  904. this,
  905. m_TypeInfo,
  906. dispIdMember,
  907. wFlags,
  908. pDispParams,
  909. pVarResult,
  910. pExcepInfo,
  911. puArgErr);
  912. }
  913. STDMETHODIMP CBITSExtensionSetupFactory::GetObject(
  914. BSTR Path,
  915. IBITSExtensionSetup **ppExtensionSetup )
  916. {
  917. WCHAR *ObjectPath = NULL;
  918. IUnknown *Object = NULL;
  919. try
  920. {
  921. if ( !Path || !ppExtensionSetup )
  922. throw ComError( E_INVALIDARG );
  923. *ppExtensionSetup = NULL;
  924. ObjectPath = ConvertObjectPathToADSI( (WCHAR*)Path );
  925. THROW_COMERROR( ADsGetObject( BSTR( ObjectPath ), __uuidof( IUnknown ), (void**)&Object ) );
  926. delete ObjectPath;
  927. ObjectPath = NULL;
  928. CBITSExtensionSetup *SetupObj = new CBITSExtensionSetup( NULL, Object );
  929. if ( !SetupObj )
  930. throw ComError( E_OUTOFMEMORY );
  931. Object = NULL;
  932. *ppExtensionSetup = static_cast<IBITSExtensionSetup*>( SetupObj );
  933. return S_OK;
  934. }
  935. catch( ComError Error )
  936. {
  937. delete ObjectPath;
  938. if ( Object )
  939. Object->Release();
  940. return Error.m_Hr;
  941. }
  942. }
  943. STDMETHODIMP CNonDelegatingIUnknown::QueryInterface(REFIID riid, LPVOID *ppv)
  944. {
  945. if (!ppv)
  946. return E_FAIL;
  947. *ppv = NULL;
  948. if ( riid == __uuidof(IUnknown) )
  949. *ppv = static_cast<IUnknown *>(this);
  950. else if ( riid == __uuidof(IDispatch) )
  951. *ppv = static_cast<IDispatch*>(m_DelegatingIUnknown);
  952. else if ( riid == __uuidof(IBITSExtensionSetup) )
  953. *ppv = static_cast<IBITSExtensionSetup *>(m_DelegatingIUnknown);
  954. else if ( riid == __uuidof(IADsExtension) )
  955. *ppv = static_cast<IADsExtension *>(m_DelegatingIUnknown);
  956. if (*ppv)
  957. {
  958. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  959. return S_OK;
  960. }
  961. return E_NOINTERFACE;
  962. }
  963. STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::AddRef()
  964. {
  965. return InterlockedIncrement((LONG *)&m_cref);
  966. }
  967. STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::Release()
  968. {
  969. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  970. {
  971. // we need to decrement our object count in the DLL
  972. delete m_DelegatingIUnknown;
  973. return 0;
  974. }
  975. return m_cref;
  976. }
  977. CNonDelegatingIUnknown::CNonDelegatingIUnknown( CBITSExtensionSetup * DelegatingIUnknown ) :
  978. m_DelegatingIUnknown( DelegatingIUnknown ),
  979. m_cref(1)
  980. {
  981. }
  982. CBITSExtensionSetup::CBITSExtensionSetup( IUnknown *Outer, IUnknown *Object ) :
  983. m_pOuter( Outer ),
  984. m_pObject( Object ),
  985. m_OuterDispatch( NULL ),
  986. m_TypeInfo( NULL ),
  987. m_ADSIPath( NULL ),
  988. m_Path( NULL ),
  989. m_PropertyMan( NULL ),
  990. m_DelegationIUnknown( this ),
  991. m_RemoteInterface( NULL ),
  992. m_InitComplete( false ),
  993. m_Lock( 0 )
  994. {
  995. if ( m_pOuter )
  996. {
  997. HRESULT Hr = m_pOuter->QueryInterface( __uuidof( IDispatch ), (void**)&m_OuterDispatch );
  998. if ( FAILED( Hr ) )
  999. m_OuterDispatch = NULL;
  1000. }
  1001. OBJECT_CREATED
  1002. }
  1003. CBITSExtensionSetup::~CBITSExtensionSetup()
  1004. {
  1005. if ( m_pObject )
  1006. {
  1007. m_pObject->Release();
  1008. m_pObject = NULL;
  1009. }
  1010. if ( m_OuterDispatch )
  1011. m_OuterDispatch->Release();
  1012. if ( m_TypeInfo )
  1013. m_TypeInfo->Release();
  1014. delete[] m_Path; // Noop on NULL
  1015. m_Path = NULL;
  1016. if ( m_RemoteInterface )
  1017. m_RemoteInterface->Release();
  1018. delete m_PropertyMan;
  1019. SysFreeString( m_ADSIPath );
  1020. OBJECT_DESTROYED
  1021. }
  1022. STDMETHODIMP CBITSExtensionSetup::QueryInterface(REFIID riid, LPVOID *ppv)
  1023. {
  1024. if ( m_pOuter )
  1025. return m_pOuter->QueryInterface( riid, ppv );
  1026. else
  1027. return m_DelegationIUnknown.QueryInterface( riid, ppv );
  1028. }
  1029. STDMETHODIMP_(ULONG) CBITSExtensionSetup::AddRef()
  1030. {
  1031. if ( m_pOuter )
  1032. return m_pOuter->AddRef();
  1033. else
  1034. return m_DelegationIUnknown.AddRef();
  1035. }
  1036. STDMETHODIMP_(ULONG) CBITSExtensionSetup::Release()
  1037. {
  1038. if ( m_pOuter )
  1039. return m_pOuter->AddRef();
  1040. else
  1041. return m_DelegationIUnknown.AddRef();
  1042. }
  1043. HRESULT
  1044. CBITSExtensionSetup::LoadTypeInfo()
  1045. {
  1046. if ( m_TypeInfo )
  1047. return S_OK;
  1048. // Lock object
  1049. while( InterlockedExchange( &m_Lock, 1 ) )
  1050. Sleep( 0 );
  1051. HRESULT Hr = ::GetTypeInfo( __uuidof( IBITSExtensionSetup ), &m_TypeInfo );
  1052. // Unlock the object
  1053. InterlockedExchange( &m_Lock, 0 );
  1054. return Hr;
  1055. }
  1056. STDMETHODIMP
  1057. CBITSExtensionSetup::Operate(
  1058. ULONG dwCode,
  1059. VARIANT varData1,
  1060. VARIANT varData2,
  1061. VARIANT varData3)
  1062. {
  1063. return E_NOTIMPL;
  1064. }
  1065. STDMETHODIMP
  1066. CBITSExtensionSetup::PrivateGetIDsOfNames(
  1067. REFIID,
  1068. OLECHAR FAR* FAR* rgszNames,
  1069. unsigned int cNames,
  1070. LCID,
  1071. DISPID FAR* rgDispId )
  1072. {
  1073. HRESULT Hr;
  1074. Hr = LoadTypeInfo();
  1075. if ( FAILED( Hr ) )
  1076. return Hr;
  1077. return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
  1078. }
  1079. STDMETHODIMP
  1080. CBITSExtensionSetup::PrivateGetTypeInfo(
  1081. unsigned int iTInfo,
  1082. LCID lcid,
  1083. ITypeInfo FAR* FAR* ppTInfo )
  1084. {
  1085. *ppTInfo = NULL;
  1086. if(iTInfo != 0)
  1087. return ResultFromScode(DISP_E_BADINDEX);
  1088. HRESULT Hr;
  1089. Hr = LoadTypeInfo();
  1090. if ( FAILED( Hr ) )
  1091. return Hr;
  1092. m_TypeInfo->AddRef();
  1093. *ppTInfo = m_TypeInfo;
  1094. return NOERROR;
  1095. }
  1096. STDMETHODIMP
  1097. CBITSExtensionSetup::PrivateGetTypeInfoCount(
  1098. unsigned int FAR* pctinfo )
  1099. {
  1100. *pctinfo = 1;
  1101. return NOERROR;
  1102. }
  1103. STDMETHODIMP
  1104. CBITSExtensionSetup::PrivateInvoke(
  1105. DISPID dispIdMember,
  1106. REFIID,
  1107. LCID,
  1108. WORD wFlags,
  1109. DISPPARAMS FAR* pDispParams,
  1110. VARIANT FAR* pVarResult,
  1111. EXCEPINFO FAR* pExcepInfo,
  1112. unsigned int FAR* puArgErr )
  1113. {
  1114. HRESULT Hr;
  1115. Hr = LoadTypeInfo();
  1116. if ( FAILED( Hr ) )
  1117. return Hr;
  1118. return
  1119. DispInvoke(
  1120. static_cast<IBITSExtensionSetup*>(this),
  1121. m_TypeInfo,
  1122. dispIdMember,
  1123. wFlags,
  1124. pDispParams,
  1125. pVarResult,
  1126. pExcepInfo,
  1127. puArgErr);
  1128. }
  1129. STDMETHODIMP
  1130. CBITSExtensionSetup::GetIDsOfNames(
  1131. REFIID riid,
  1132. OLECHAR FAR* FAR* rgszNames,
  1133. unsigned int cNames,
  1134. LCID lcid,
  1135. DISPID FAR* rgDispId )
  1136. {
  1137. if ( m_OuterDispatch )
  1138. return m_OuterDispatch->GetIDsOfNames(
  1139. riid,
  1140. rgszNames,
  1141. cNames,
  1142. lcid,
  1143. rgDispId );
  1144. return PrivateGetIDsOfNames(
  1145. riid,
  1146. rgszNames,
  1147. cNames,
  1148. lcid,
  1149. rgDispId );
  1150. }
  1151. STDMETHODIMP
  1152. CBITSExtensionSetup::GetTypeInfo(
  1153. unsigned int iTInfo,
  1154. LCID lcid,
  1155. ITypeInfo FAR* FAR* ppTInfo )
  1156. {
  1157. if ( m_OuterDispatch )
  1158. return m_OuterDispatch->GetTypeInfo(
  1159. iTInfo,
  1160. lcid,
  1161. ppTInfo );
  1162. return
  1163. PrivateGetTypeInfo(
  1164. iTInfo,
  1165. lcid,
  1166. ppTInfo );
  1167. }
  1168. STDMETHODIMP
  1169. CBITSExtensionSetup::GetTypeInfoCount(
  1170. unsigned int FAR* pctinfo )
  1171. {
  1172. if ( m_OuterDispatch )
  1173. return m_OuterDispatch->GetTypeInfoCount( pctinfo );
  1174. return PrivateGetTypeInfoCount( pctinfo );
  1175. }
  1176. STDMETHODIMP
  1177. CBITSExtensionSetup::Invoke(
  1178. DISPID dispIdMember,
  1179. REFIID riid,
  1180. LCID lcid,
  1181. WORD wFlags,
  1182. DISPPARAMS FAR* pDispParams,
  1183. VARIANT FAR* pVarResult,
  1184. EXCEPINFO FAR* pExcepInfo,
  1185. unsigned int FAR* puArgErr )
  1186. {
  1187. if ( m_OuterDispatch )
  1188. return m_OuterDispatch->Invoke(
  1189. dispIdMember,
  1190. riid,
  1191. lcid,
  1192. wFlags,
  1193. pDispParams,
  1194. pVarResult,
  1195. pExcepInfo,
  1196. puArgErr );
  1197. return
  1198. PrivateInvoke(
  1199. dispIdMember,
  1200. riid,
  1201. lcid,
  1202. wFlags,
  1203. pDispParams,
  1204. pVarResult,
  1205. pExcepInfo,
  1206. puArgErr );
  1207. }
  1208. HRESULT
  1209. CBITSExtensionSetup::ConnectToRemoteExtension()
  1210. {
  1211. WCHAR *HostName = NULL;
  1212. WCHAR *NewPath = NULL;
  1213. BSTR NewPathBSTR = NULL;
  1214. IBITSExtensionSetupFactory* Factory = NULL;
  1215. try
  1216. {
  1217. // Extract out the host part of the path
  1218. const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1;
  1219. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 )
  1220. throw ComError( E_INVALIDARG );
  1221. WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize;
  1222. WCHAR *p = HostNameStart;
  1223. while( L'/' != *p )
  1224. {
  1225. if ( L'\0' == *p )
  1226. throw ComError( E_INVALIDARG );
  1227. p++;
  1228. }
  1229. SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0');
  1230. HostName = new WCHAR[ HostNameSize / sizeof(WCHAR) ];
  1231. if ( !HostName )
  1232. throw ComError( E_OUTOFMEMORY );
  1233. memcpy( HostName, HostNameStart, HostNameSize - sizeof(WCHAR) );
  1234. HostName[ ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ] = L'\0';
  1235. if ( L'\0' == *++p )
  1236. throw ComError( E_INVALIDARG );
  1237. SIZE_T NewPathSize = wcslen( L"IIS://LocalHost/" ) + wcslen( p ) + 1;
  1238. NewPath = new WCHAR[ NewPathSize ];
  1239. if ( !NewPath )
  1240. throw ComError( E_OUTOFMEMORY );
  1241. StringCchCopyW( NewPath, NewPathSize, L"IIS://LocalHost/" );
  1242. StringCchCatW( NewPath, NewPathSize, p );
  1243. NewPathBSTR = SysAllocString( NewPath );
  1244. if ( !NewPathBSTR )
  1245. throw ComError( E_OUTOFMEMORY );
  1246. COSERVERINFO coinfo;
  1247. coinfo.dwReserved1 = 0;
  1248. coinfo.dwReserved2 = 0;
  1249. coinfo.pAuthInfo = NULL;
  1250. coinfo.pwszName = HostName;
  1251. GUID guid = __uuidof( IBITSExtensionSetupFactory );
  1252. MULTI_QI mqi;
  1253. mqi.hr = S_OK;
  1254. mqi.pIID = &guid;
  1255. mqi.pItf = NULL;
  1256. THROW_COMERROR(
  1257. CoCreateInstanceEx(
  1258. __uuidof(BITSExtensionSetupFactory),
  1259. NULL,
  1260. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
  1261. &coinfo,
  1262. 1,
  1263. &mqi ) );
  1264. THROW_COMERROR( mqi.hr );
  1265. Factory = (IBITSExtensionSetupFactory*)mqi.pItf;
  1266. mqi.pItf = NULL;
  1267. THROW_COMERROR( Factory->GetObject( NewPathBSTR, &m_RemoteInterface ) );
  1268. Factory->Release();
  1269. SysFreeString( NewPathBSTR );
  1270. delete[] NewPath;
  1271. delete[] HostName;
  1272. return S_OK;
  1273. }
  1274. catch( ComError Error )
  1275. {
  1276. SysFreeString( NewPathBSTR );
  1277. delete[] HostName;
  1278. delete[] NewPath;
  1279. if ( Factory )
  1280. Factory->Release();
  1281. return Error.m_Hr;
  1282. }
  1283. }
  1284. HRESULT CBITSExtensionSetup::LoadPath()
  1285. {
  1286. HRESULT Hr;
  1287. if ( m_InitComplete )
  1288. return S_OK;
  1289. // Lock object
  1290. while( InterlockedExchange( &m_Lock, 1 ) )
  1291. Sleep( 0 );
  1292. if ( !m_PropertyMan )
  1293. {
  1294. m_PropertyMan = new PropertyIDManager();
  1295. if ( !m_PropertyMan )
  1296. {
  1297. Hr = E_OUTOFMEMORY;
  1298. goto error;
  1299. }
  1300. Hr = m_PropertyMan->LoadPropertyInfo();
  1301. if ( FAILED(Hr) )
  1302. {
  1303. delete m_PropertyMan;
  1304. m_PropertyMan = NULL;
  1305. goto error;
  1306. }
  1307. }
  1308. if ( !m_ADSIPath )
  1309. {
  1310. IADs *ObjectADS = NULL;
  1311. if ( m_pObject )
  1312. Hr = m_pObject->QueryInterface( __uuidof(*ObjectADS), (void**) &ObjectADS );
  1313. else
  1314. Hr = m_pOuter->QueryInterface( __uuidof(*ObjectADS), (void**) &ObjectADS );
  1315. if ( FAILED( Hr ) )
  1316. goto error;
  1317. Hr = ObjectADS->get_ADsPath( &m_ADSIPath );
  1318. ObjectADS->Release();
  1319. ObjectADS = NULL;
  1320. if ( FAILED( Hr ) )
  1321. goto error;
  1322. }
  1323. if ( !m_Path && !m_RemoteInterface )
  1324. {
  1325. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://LocalHost/", wcslen( L"IIS://LocalHost/" ) ) == 0 )
  1326. {
  1327. SIZE_T PathSize = wcslen( (WCHAR*)m_ADSIPath ) + 1;
  1328. m_Path = new WCHAR[ PathSize ];
  1329. if ( !m_Path )
  1330. {
  1331. Hr = E_OUTOFMEMORY;
  1332. goto error;
  1333. }
  1334. StringCchCopyW( m_Path, PathSize, L"/LM/" );
  1335. StringCchCatW( m_Path, PathSize, reinterpret_cast<WCHAR*>( m_ADSIPath ) + wcslen( L"IIS://LocalHost/" ) );
  1336. }
  1337. else
  1338. {
  1339. Hr = ConnectToRemoteExtension( );
  1340. if ( FAILED( Hr ) )
  1341. goto error;
  1342. }
  1343. }
  1344. m_InitComplete = true;
  1345. // unlock
  1346. InterlockedExchange( &m_Lock, 0 );
  1347. return S_OK;
  1348. error:
  1349. // unlock
  1350. InterlockedExchange( &m_Lock, 0 );
  1351. return Hr;
  1352. }
  1353. STDMETHODIMP CBITSExtensionSetup::EnableBITSUploads()
  1354. {
  1355. HRESULT Hr = LoadPath();
  1356. if ( FAILED(Hr) )
  1357. return Hr;
  1358. if ( m_RemoteInterface )
  1359. return m_RemoteInterface->EnableBITSUploads();
  1360. IMSAdminBase *AdminBase = NULL;
  1361. Hr =
  1362. CoCreateInstance(
  1363. GETAdminBaseCLSID(TRUE),
  1364. NULL,
  1365. CLSCTX_SERVER,
  1366. __uuidof( IMSAdminBase ),
  1367. (LPVOID*)&AdminBase );
  1368. if ( FAILED( Hr ) )
  1369. return Hr;
  1370. Hr = EnableBITSForVDIR( m_PropertyMan, AdminBase, m_Path );
  1371. AdminBase->Release();
  1372. return Hr;
  1373. }
  1374. STDMETHODIMP CBITSExtensionSetup::DisableBITSUploads()
  1375. {
  1376. HRESULT Hr = LoadPath();
  1377. if ( FAILED(Hr) )
  1378. return Hr;
  1379. if ( m_RemoteInterface )
  1380. return m_RemoteInterface->DisableBITSUploads();
  1381. IMSAdminBase *AdminBase = NULL;
  1382. Hr =
  1383. CoCreateInstance(
  1384. GETAdminBaseCLSID(TRUE),
  1385. NULL,
  1386. CLSCTX_SERVER,
  1387. __uuidof( IMSAdminBase ),
  1388. (LPVOID*)&AdminBase );
  1389. if ( FAILED( Hr ) )
  1390. return Hr;
  1391. Hr = DisableBITSForVDIR( m_PropertyMan, AdminBase, m_Path, false );
  1392. AdminBase->Release();
  1393. return Hr;
  1394. }
  1395. STDMETHODIMP
  1396. CBITSExtensionSetup::GetCleanupTaskName( BSTR *pTaskName )
  1397. {
  1398. *pTaskName = NULL;
  1399. HRESULT Hr = LoadPath();
  1400. if ( FAILED(Hr) )
  1401. return Hr;
  1402. if ( m_RemoteInterface )
  1403. return m_RemoteInterface->GetCleanupTaskName( pTaskName );
  1404. IMSAdminBase *AdminBase = NULL;
  1405. Hr =
  1406. CoCreateInstance(
  1407. GETAdminBaseCLSID(TRUE),
  1408. NULL,
  1409. CLSCTX_SERVER,
  1410. __uuidof( IMSAdminBase ),
  1411. (LPVOID*)&AdminBase );
  1412. if ( FAILED( Hr ) )
  1413. return Hr;
  1414. LPWSTR TaskName = NULL;
  1415. Hr = FindWorkItemForVDIR( m_PropertyMan, AdminBase, m_Path, &TaskName );
  1416. if ( SUCCEEDED( Hr ) && TaskName )
  1417. {
  1418. *pTaskName = SysAllocString( TaskName );
  1419. if ( !*pTaskName )
  1420. Hr = E_OUTOFMEMORY;
  1421. CoTaskMemFree( TaskName );
  1422. TaskName = NULL;
  1423. }
  1424. AdminBase->Release();
  1425. return Hr;
  1426. }
  1427. STDMETHODIMP
  1428. CBITSExtensionSetup::GetCleanupTask(
  1429. [in] REFIID riid,
  1430. [out,retval] IUnknown **ppUnk )
  1431. {
  1432. HRESULT Hr = S_OK;
  1433. ITaskScheduler *TaskScheduler = NULL;
  1434. BSTR ItemName = NULL;
  1435. WCHAR *HostName = NULL;
  1436. if ( ppUnk )
  1437. *ppUnk = NULL;
  1438. try
  1439. {
  1440. THROW_COMERROR( LoadPath() );
  1441. //
  1442. // Build the taskscheduler form of the host name
  1443. //
  1444. const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1;
  1445. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 )
  1446. throw ComError( E_INVALIDARG );
  1447. WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize;
  1448. WCHAR *p = HostNameStart;
  1449. while( L'/' != *p )
  1450. {
  1451. if ( L'\0' == *p )
  1452. throw ComError( E_INVALIDARG );
  1453. p++;
  1454. }
  1455. SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0');
  1456. HostName = new WCHAR[ ( HostNameSize / sizeof(WCHAR) ) + 2 ];
  1457. if ( !HostName )
  1458. throw ComError( E_OUTOFMEMORY );
  1459. HostName[0] = HostName[1] = L'\\';
  1460. memcpy( HostName + 2, HostNameStart, HostNameSize - sizeof(WCHAR) );
  1461. HostName[ ( ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ) + 2 ] = L'\0';
  1462. if ( _wcsicmp( HostName, L"\\\\LocalHost" ) == 0 )
  1463. {
  1464. delete[] HostName;
  1465. HostName = NULL;
  1466. }
  1467. THROW_COMERROR( ConnectToTaskScheduler( HostName, &TaskScheduler ) );
  1468. THROW_COMERROR( GetCleanupTaskName( &ItemName ) );
  1469. if ( ItemName )
  1470. THROW_COMERROR( TaskScheduler->Activate( (LPCWSTR)ItemName, riid, ppUnk ) );
  1471. else
  1472. Hr = S_FALSE;
  1473. }
  1474. catch( ComError Error )
  1475. {
  1476. Hr = Error.m_Hr;
  1477. }
  1478. if ( TaskScheduler )
  1479. TaskScheduler->Release();
  1480. SysFreeString( ItemName );
  1481. delete[] HostName;
  1482. return Hr;
  1483. }
  1484. #include "bitssrvcfgimp.h"