Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2827 lines
77 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. #include <sddl.h>
  12. #pragma warning( disable : 4355 )
  13. HRESULT
  14. GetTypeInfo(
  15. const GUID & guid,
  16. ITypeInfo **TypeInfo )
  17. {
  18. DWORD Result;
  19. HRESULT hr;
  20. WCHAR DllName[ MAX_PATH ];
  21. Result =
  22. GetModuleFileName(
  23. g_hinst,
  24. DllName,
  25. MAX_PATH - 1 );
  26. if ( !Result )
  27. return HRESULT_FROM_WIN32( GetLastError() );
  28. ITypeLib *TypeLib;
  29. hr = LoadTypeLibEx(
  30. DllName,
  31. REGKIND_NONE,
  32. &TypeLib );
  33. if ( FAILED( hr ) )
  34. return hr;
  35. hr = TypeLib->GetTypeInfoOfGuid(
  36. guid,
  37. TypeInfo );
  38. TypeLib->Release();
  39. return hr;
  40. }
  41. void
  42. FreeReturnedWorkItems(
  43. ULONG NamesReturned,
  44. LPWSTR **ItemNamesPtr )
  45. {
  46. LPWSTR *ItemNames = *ItemNamesPtr;
  47. if ( ItemNames )
  48. {
  49. for( ULONG i = 0; i < NamesReturned; i++ )
  50. {
  51. CoTaskMemFree( ItemNames[i] );
  52. }
  53. CoTaskMemFree( ItemNames );
  54. *ItemNamesPtr = NULL;
  55. }
  56. }
  57. void
  58. FindWorkItemForVDIR(
  59. SmartITaskSchedulerPointer TaskScheduler,
  60. LPCWSTR Key,
  61. SmartITaskPointer* ReturnedTask,
  62. LPWSTR* ReturnedTaskName )
  63. {
  64. HRESULT Hr;
  65. SIZE_T KeyLength = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
  66. WORD DataLength;
  67. if ( ReturnedTask )
  68. (*ReturnedTask).Clear();
  69. if ( ReturnedTaskName )
  70. *ReturnedTaskName = NULL;
  71. SmartITaskPointer Task;
  72. SmartIEnumWorkItemsPointer EnumWorkItems;
  73. LPWSTR *ItemNames = NULL;
  74. BYTE *ItemData = NULL;
  75. ULONG NamesReturned = 0;
  76. try
  77. {
  78. THROW_COMERROR( TaskScheduler->Enum( EnumWorkItems.GetRecvPointer() ) );
  79. while( 1 )
  80. {
  81. THROW_COMERROR( EnumWorkItems->Next( 255, &ItemNames, &NamesReturned ) );
  82. if ( !NamesReturned )
  83. throw ComError( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
  84. for ( ULONG i = 0; i < NamesReturned; i++ )
  85. {
  86. THROW_COMERROR( TaskScheduler->Activate( ItemNames[i], Task.GetUUID(),
  87. (IUnknown**)Task.GetRecvPointer() ) );
  88. THROW_COMERROR( Task->GetWorkItemData( &DataLength, &ItemData ) );
  89. if ( KeyLength == DataLength &&
  90. ( wcscmp( Key, (WCHAR*)ItemData ) == 0 ) )
  91. {
  92. // Found the item, cleanup and return
  93. if ( ReturnedTask )
  94. *ReturnedTask = Task;
  95. if ( ReturnedTaskName )
  96. {
  97. *ReturnedTaskName = ItemNames[i];
  98. ItemNames[i] = NULL;
  99. }
  100. FreeReturnedWorkItems(
  101. NamesReturned,
  102. &ItemNames );
  103. CoTaskMemFree( ItemData );
  104. return;
  105. }
  106. CoTaskMemFree( ItemData );
  107. ItemData = NULL;
  108. }
  109. FreeReturnedWorkItems(
  110. NamesReturned,
  111. &ItemNames );
  112. NamesReturned = 0;
  113. }
  114. }
  115. catch( ComError Error )
  116. {
  117. FreeReturnedWorkItems(
  118. NamesReturned,
  119. &ItemNames );
  120. CoTaskMemFree( ItemData );
  121. throw;
  122. }
  123. }
  124. WCHAR *BasePathOf( IN WCHAR *pPath )
  125. {
  126. WCHAR *pBasePath;
  127. if (!pPath)
  128. {
  129. return NULL;
  130. }
  131. if ( (pBasePath=wcsrchr(pPath,L'/'))
  132. || (pBasePath=wcsrchr(pPath,L'\\')) )
  133. {
  134. pBasePath++;
  135. }
  136. else
  137. {
  138. pBasePath = pPath;
  139. }
  140. return pBasePath;
  141. }
  142. void CreateWorkItemForVDIR(
  143. IN SmartITaskSchedulerPointer TaskScheduler,
  144. IN LPWSTR Path,
  145. IN LPWSTR Key )
  146. {
  147. WORD KeySize = sizeof(WCHAR) * ( wcslen( Key ) + 1 );
  148. WCHAR ItemName[MAX_PATH];
  149. WCHAR ItemCommentFormat[MAX_PATH];
  150. WCHAR ItemComment[2*MAX_PATH];
  151. WCHAR Parameters[4*MAX_PATH];
  152. //
  153. // Use the last part of the path for the item name and description comment.
  154. //
  155. const WCHAR *pBasePath = BasePathOf(Path);
  156. if (!pBasePath || 0==wcslen(pBasePath))
  157. {
  158. throw ComError( HRESULT_FROM_WIN32(ERROR_INVALID_NAME) );
  159. }
  160. //
  161. // Construct the description/comment string.
  162. //
  163. DWORD Result;
  164. void* InsertArray[2] = { (void*)pBasePath, (void*)Key };
  165. if ( !LoadString(g_hinst, IDS_WORK_ITEM_COMMENT, ItemCommentFormat, MAX_PATH) )
  166. {
  167. throw ComError( HRESULT_FROM_WIN32(GetLastError()) );
  168. }
  169. Result = FormatMessage( FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  170. (LPCVOID)ItemCommentFormat,
  171. 0,
  172. 0,
  173. ItemComment,
  174. ARRAY_ELEMENTS(ItemComment),
  175. (va_list*)InsertArray );
  176. ItemComment[ ARRAY_ELEMENTS(ItemComment) - 1 ] = L'\0';
  177. if ( !Result )
  178. {
  179. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  180. }
  181. //
  182. // Construct the task scheduler item name. Since StringCchPrintfW() is always
  183. // defined to return a (possibly trunctated) buffer, we can ignore the error
  184. // return in this case.
  185. //
  186. StringCchPrintfW(
  187. ItemName,
  188. ARRAY_ELEMENTS(ItemName),
  189. L"BITS_%s_%s", pBasePath, Key );
  190. //
  191. // Construct the runstring for the task.
  192. //
  193. StringCchPrintfW(
  194. Parameters,
  195. ARRAY_ELEMENTS(Parameters),
  196. L"bitsmgr.dll,Cleanup_RunDLL %s \"%s\" %s", Path, ItemName, Key );
  197. WORD TriggerNumber;
  198. SmartITaskPointer Task;
  199. SmartITaskTriggerPointer TaskTrigger;
  200. SmartIPersistFilePointer PersistFile;
  201. try
  202. {
  203. try
  204. {
  205. FindWorkItemForVDIR( TaskScheduler, Key, &Task, NULL );
  206. return; // work item already found
  207. }
  208. catch( ComError Error )
  209. {
  210. if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) != Error.m_Hr )
  211. throw;
  212. }
  213. // error not found
  214. THROW_COMERROR( TaskScheduler->NewWorkItem( ItemName, CLSID_CTask,
  215. Task.GetUUID(), (IUnknown**)Task.GetRecvPointer() ) );
  216. // Set basic task data
  217. THROW_COMERROR( Task->SetApplicationName( L"%SystemRoot%\\system32\\rundll32.exe" ) );
  218. THROW_COMERROR( Task->SetMaxRunTime( INFINITE ) );
  219. THROW_COMERROR( Task->SetParameters( Parameters ) );
  220. THROW_COMERROR( Task->SetPriority( IDLE_PRIORITY_CLASS ) );
  221. THROW_COMERROR( Task->SetAccountInformation( L"", NULL ) ); //Run as localsystem
  222. THROW_COMERROR( Task->SetFlags( TASK_FLAG_RUN_ONLY_IF_LOGGED_ON | TASK_FLAG_HIDDEN ) );
  223. THROW_COMERROR( Task->SetWorkItemData( KeySize, (BYTE*)Key ) );
  224. Task->SetComment( ItemComment ); // Don't fail if this one fails...
  225. // Set the trigger information. Set start time to now, with a default
  226. // interval of once a day.
  227. THROW_COMERROR( Task->CreateTrigger( &TriggerNumber, TaskTrigger.GetRecvPointer() ) );
  228. SYSTEMTIME LocalTime;
  229. GetLocalTime( &LocalTime );
  230. TASK_TRIGGER Trigger;
  231. memset( &Trigger, 0, sizeof( Trigger ) );
  232. Trigger.cbTriggerSize = sizeof(Trigger);
  233. Trigger.wBeginYear = LocalTime.wYear;
  234. Trigger.wBeginMonth = LocalTime.wMonth;
  235. Trigger.wBeginDay = LocalTime.wDay;
  236. Trigger.wStartHour = LocalTime.wHour;
  237. Trigger.wStartMinute = LocalTime.wMinute;
  238. Trigger.TriggerType = TASK_TIME_TRIGGER_DAILY;
  239. Trigger.MinutesDuration = 24 * 60; // 24 hours per day
  240. Trigger.MinutesInterval = 12 * 60; // twice per day
  241. Trigger.Type.Daily.DaysInterval = 1;
  242. THROW_COMERROR( TaskTrigger->SetTrigger( &Trigger ) );
  243. // Commit the changes to disk.
  244. THROW_COMERROR( Task->QueryInterface( PersistFile.GetUUID(),
  245. (void**)PersistFile.GetRecvPointer() ) );
  246. THROW_COMERROR( PersistFile->Save( NULL, TRUE ) );
  247. }
  248. catch( ComError Error )
  249. {
  250. TaskScheduler->Delete( ItemName );
  251. throw;
  252. }
  253. }
  254. void
  255. DeleteWorkItemForVDIR(
  256. SmartITaskSchedulerPointer TaskScheduler,
  257. LPWSTR Key )
  258. {
  259. LPWSTR TaskName = NULL;
  260. try
  261. {
  262. FindWorkItemForVDIR( TaskScheduler, Key, NULL, &TaskName );
  263. THROW_COMERROR( TaskScheduler->Delete( TaskName ) );
  264. }
  265. catch( ComError Error )
  266. {
  267. CoTaskMemFree( TaskName );
  268. if ( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Error.m_Hr )
  269. return;
  270. throw;
  271. }
  272. }
  273. void
  274. ConnectToTaskScheduler(
  275. LPWSTR ComputerName,
  276. SmartITaskSchedulerPointer * TaskScheduler )
  277. {
  278. THROW_COMERROR(
  279. CoCreateInstance(
  280. CLSID_CTaskScheduler,
  281. NULL,
  282. CLSCTX_INPROC_SERVER,
  283. (*TaskScheduler).GetUUID(),
  284. (void**)(*TaskScheduler).GetRecvPointer() ) );
  285. THROW_COMERROR( (*TaskScheduler)->SetTargetComputer( ComputerName ) );
  286. }
  287. void
  288. IsBITSEnabledOnVDir(
  289. PropertyIDManager *PropertyManager,
  290. IMSAdminBase *IISAdminBase,
  291. LPWSTR VirtualDirectory,
  292. BOOL *IsEnabled )
  293. {
  294. DWORD BufferRequired;
  295. *IsEnabled = false;
  296. DWORD IsEnabledVal;
  297. METADATA_RECORD MdRecord;
  298. memset( &MdRecord, 0, sizeof( MdRecord ) );
  299. MdRecord.dwMDDataType = DWORD_METADATA;
  300. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  301. MdRecord.dwMDDataLen = sizeof(IsEnabled);
  302. MdRecord.pbMDData = (PBYTE)&IsEnabledVal;
  303. try
  304. {
  305. THROW_COMERROR(
  306. IISAdminBase->GetData(
  307. METADATA_MASTER_ROOT_HANDLE,
  308. VirtualDirectory,
  309. &MdRecord,
  310. &BufferRequired ) );
  311. }
  312. catch( ComError Error )
  313. {
  314. if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
  315. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Error.m_Hr )
  316. return;
  317. throw;
  318. }
  319. *IsEnabled = IsEnabledVal ? true : false;
  320. }
  321. LPWSTR
  322. BITSGetFileOwnerSidString(LPCWSTR szFile)
  323. {
  324. DWORD cbSizeNeeded = 0;
  325. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  326. PSID pOwnerSid = NULL;
  327. BOOL fOwnerDefaulted = FALSE;
  328. LPWSTR pszSidString = NULL;
  329. try
  330. {
  331. //
  332. // Retrieve the file owner. Call GetFileSecurity twice - first to get
  333. // the buffer size, then the actual information retrieval.
  334. //
  335. if (!GetFileSecurity(szFile, OWNER_SECURITY_INFORMATION, NULL, 0, &cbSizeNeeded))
  336. {
  337. DWORD dwError = GetLastError();
  338. if (dwError != ERROR_INSUFFICIENT_BUFFER)
  339. {
  340. throw ComError( HRESULT_FROM_WIN32( dwError ) );
  341. }
  342. }
  343. else
  344. {
  345. // we don't expect this to ever succeed
  346. throw ComError( E_UNEXPECTED );
  347. }
  348. //
  349. // Allocate the buffer space necessary and retrieve the info.
  350. //
  351. pSecurityDescriptor = reinterpret_cast<SECURITY_DESCRIPTOR *>(new BYTE[cbSizeNeeded]);
  352. THROW_OUTOFMEMORY_IFNULL(pSecurityDescriptor);
  353. if (!GetFileSecurity(szFile, OWNER_SECURITY_INFORMATION, pSecurityDescriptor, cbSizeNeeded, &cbSizeNeeded))
  354. {
  355. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  356. }
  357. //
  358. // Retrieve & validate the owner sid.
  359. //
  360. if (!GetSecurityDescriptorOwner(pSecurityDescriptor, &pOwnerSid, &fOwnerDefaulted))
  361. {
  362. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  363. }
  364. if (!IsValidSid(pOwnerSid))
  365. {
  366. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  367. }
  368. if(!ConvertSidToStringSidW(pOwnerSid, &pszSidString))
  369. {
  370. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  371. }
  372. }
  373. catch ( ComError Error )
  374. {
  375. if (pSecurityDescriptor)
  376. {
  377. delete [] reinterpret_cast<BYTE *>(pSecurityDescriptor);
  378. pSecurityDescriptor = NULL;
  379. }
  380. throw;
  381. }
  382. //
  383. // Everthing went fine
  384. //
  385. if (pSecurityDescriptor)
  386. {
  387. delete [] reinterpret_cast<BYTE *>(pSecurityDescriptor);
  388. pSecurityDescriptor = NULL;
  389. }
  390. // caller should free this memory
  391. return pszSidString;
  392. }
  393. LPWSTR
  394. BITSAddAclForDirectoryOwner(LPCWSTR szBaseAcl, LPCWSTR szUserPartialAclPrefix, LPCWSTR szDirectory)
  395. {
  396. LPCWSTR szUserPartialAclSuffix = L")";
  397. LPWSTR szFullAcl = NULL;
  398. DWORD cchFullAcl = 0;
  399. LPWSTR pszUserSID = NULL;
  400. try
  401. {
  402. pszUserSID = BITSGetFileOwnerSidString(szDirectory);
  403. cchFullAcl = wcslen(szBaseAcl) + wcslen(szUserPartialAclPrefix) + wcslen(pszUserSID) + wcslen(szUserPartialAclSuffix) + 1;
  404. // ATT: this buffer is being allocated and it should be freed by the caller
  405. szFullAcl = new WCHAR[ cchFullAcl ];
  406. THROW_OUTOFMEMORY_IFNULL(szFullAcl);
  407. StringCchPrintfW(szFullAcl, cchFullAcl, L"%ws%ws%ws%ws", szBaseAcl, szUserPartialAclPrefix, pszUserSID, szUserPartialAclSuffix);
  408. }
  409. catch( ComError Error )
  410. {
  411. //
  412. // Free the String SID obtained by calling ConvertSidToStringSid()
  413. //
  414. if (pszUserSID)
  415. {
  416. LocalFree(reinterpret_cast<HLOCAL>(pszUserSID));
  417. pszUserSID = NULL;
  418. }
  419. }
  420. //
  421. // Free the String SID obtained by calling ConvertSidToStringSid()
  422. //
  423. if (pszUserSID)
  424. {
  425. LocalFree(reinterpret_cast<HLOCAL>(pszUserSID));
  426. pszUserSID = NULL;
  427. }
  428. // this string should be freed by the caller
  429. return szFullAcl;
  430. }
  431. void
  432. BITSCreateDirectory(
  433. const WCHAR *Path,
  434. const WCHAR *SDString,
  435. BOOL fAllowInheritanceFromParent,
  436. BOOL fAddOwnerExplicitly )
  437. {
  438. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  439. PACL pDacl = NULL;
  440. BOOL fDaclPresent = TRUE;
  441. BOOL fDaclDefaulted = TRUE;
  442. DWORD dwProtectedFlag = 0;
  443. DWORD dwError = ERROR_SUCCESS;
  444. LPWSTR szExpandedAcl = NULL;
  445. try
  446. {
  447. //
  448. // Note that we are setting the SecurityDescriptor as NULL initially.
  449. // We will set the security separately via SetNamedSecurityInfo(), otherwise
  450. // the inherited ACLs will not be computed.
  451. //
  452. if (!CreateDirectory(Path, NULL))
  453. {
  454. dwError = GetLastError();
  455. // ignore error if directory already exists
  456. if ( ERROR_ALREADY_EXISTS != dwError )
  457. {
  458. throw ComError( HRESULT_FROM_WIN32( dwError ) );
  459. }
  460. }
  461. //
  462. // If we were given a security descriptor string, use it to set the security permissions
  463. //
  464. if ( SDString )
  465. {
  466. if (fAddOwnerExplicitly)
  467. {
  468. //
  469. // Grab the SID for the Owner of the directory we just created, transform it to string
  470. // format and add it to the SDDL string that we were given.
  471. // We do this in order to guarantee to the owner of the directory the right to
  472. // create subdirectories and files. CO permissions will only last during creation time,
  473. // so it doesn't help in our scenario. This behavior was confirmed by the Security team.
  474. //
  475. szExpandedAcl = BITSAddAclForDirectoryOwner(SDString, BITS_EXPLICITOWNER_PARTIAL_ACL, Path);
  476. }
  477. if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
  478. (szExpandedAcl? szExpandedAcl : SDString), // security descriptor string
  479. SDDL_REVISION_1, // revision level
  480. &pSecurityDescriptor, // SD
  481. NULL ) ) // SD size
  482. {
  483. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  484. }
  485. SECURITY_ATTRIBUTES SecurityAttributes =
  486. {
  487. sizeof( SECURITY_ATTRIBUTES ),
  488. pSecurityDescriptor,
  489. FALSE
  490. };
  491. if (!GetSecurityDescriptorDacl(pSecurityDescriptor, &fDaclPresent, &pDacl, &fDaclDefaulted))
  492. {
  493. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  494. }
  495. if (!fDaclPresent || !pDacl)
  496. {
  497. throw ComError( HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) );
  498. }
  499. //
  500. // Decide if we are going to interrupt the inheritance from the parent or not.
  501. //
  502. dwProtectedFlag = (fAllowInheritanceFromParent? UNPROTECTED_DACL_SECURITY_INFORMATION : PROTECTED_DACL_SECURITY_INFORMATION);
  503. //
  504. // Set the permissions in the directory
  505. //
  506. dwError = SetNamedSecurityInfoW(
  507. (WCHAR *)Path, // object name
  508. SE_FILE_OBJECT, // object type
  509. DACL_SECURITY_INFORMATION | dwProtectedFlag, // Security info flags
  510. NULL, // psidOwner
  511. NULL, // psidGroup
  512. pDacl, // pDacl
  513. NULL); // pSacl
  514. if (dwError != ERROR_SUCCESS)
  515. {
  516. throw ComError( HRESULT_FROM_WIN32( dwError ) );
  517. }
  518. }
  519. }
  520. catch ( ComError Error )
  521. {
  522. if ( szExpandedAcl)
  523. {
  524. delete [] szExpandedAcl;
  525. szExpandedAcl = NULL;
  526. }
  527. if ( pSecurityDescriptor )
  528. {
  529. LocalFree( pSecurityDescriptor );
  530. }
  531. throw;
  532. }
  533. //
  534. // Success! Cleanup...
  535. //
  536. if ( szExpandedAcl)
  537. {
  538. delete [] szExpandedAcl;
  539. szExpandedAcl = NULL;
  540. }
  541. if ( pSecurityDescriptor )
  542. {
  543. LocalFree( pSecurityDescriptor );
  544. }
  545. }
  546. void
  547. LogDeleteError(
  548. DWORD Message,
  549. StringHandle Name,
  550. HRESULT Hr )
  551. {
  552. HANDLE EventHandle =
  553. RegisterEventSource(
  554. NULL, // server name
  555. EVENT_LOG_SOURCE_NAME // source name
  556. );
  557. if ( EventHandle )
  558. {
  559. const WCHAR *Strings[] = { (const WCHAR*)Name };
  560. ReportEvent(
  561. EventHandle, // handle to event log
  562. EVENTLOG_ERROR_TYPE, // event type
  563. BITSRV_EVENTLOG_CLEANUP_CATAGORY, // event category
  564. Message, // event identifier
  565. NULL, // user security identifier
  566. 1, // number of strings to merge
  567. sizeof( Hr ), // size of binary data
  568. Strings, // array of strings to merge
  569. &Hr // binary data buffer
  570. );
  571. DeregisterEventSource( EventHandle );
  572. }
  573. }
  574. //---------------------------------------------------------------------------
  575. // DeleteDirectoryTree()
  576. //
  577. // Recursive delete of a directory tree.
  578. //
  579. // Note: Do not follow or delete reparse points.
  580. //---------------------------------------------------------------------------
  581. void
  582. DeleteDirectoryTree( IN StringHandle Directory )
  583. {
  584. StringHandle SearchString = Directory + StringHandle(L"\\*");
  585. HANDLE FindHandle = INVALID_HANDLE_VALUE;
  586. WIN32_FIND_DATA FindData;
  587. WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
  588. try
  589. {
  590. if (!GetFileAttributesEx(Directory,
  591. GetFileExInfoStandard,
  592. &FileAttributes))
  593. {
  594. throw ComError(HRESULT_FROM_WIN32(GetLastError()));
  595. }
  596. // If the specified directory is a reparse point then ignore it.
  597. if (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
  598. {
  599. return;
  600. }
  601. FindHandle = FindFirstFile( SearchString, &FindData );
  602. if ( INVALID_HANDLE_VALUE == FindHandle )
  603. {
  604. throw ComError(HRESULT_FROM_WIN32(GetLastError()));
  605. }
  606. do
  607. {
  608. // Ignore reparse points.
  609. if ( FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
  610. {
  611. continue;
  612. }
  613. // Ignore this and parent directory references.
  614. if ( ( _wcsicmp( L".", FindData.cFileName ) == 0 )
  615. || ( _wcsicmp( L"..", FindData.cFileName ) == 0 ) )
  616. {
  617. continue;
  618. }
  619. StringHandle NewItem = Directory
  620. + StringHandle(L"\\")
  621. + StringHandle( FindData.cFileName );
  622. if ( FILE_ATTRIBUTE_DIRECTORY & FindData.dwFileAttributes )
  623. {
  624. DeleteDirectoryTree( NewItem );
  625. }
  626. else
  627. {
  628. if ( !DeleteFile( NewItem ) )
  629. {
  630. HRESULT DeleteHr = HRESULT_FROM_WIN32( GetLastError() );
  631. LogDeleteError(
  632. BITSSRV_EVENTLOG_DELETEFILE_ERROR,
  633. NewItem,
  634. DeleteHr );
  635. }
  636. }
  637. } while( FindNextFile( FindHandle, &FindData ) );
  638. FindClose( FindHandle );
  639. FindHandle = INVALID_HANDLE_VALUE;
  640. if ( !RemoveDirectory( Directory ) )
  641. {
  642. HRESULT DeleteHr = HRESULT_FROM_WIN32( GetLastError() );
  643. LogDeleteError(
  644. BITSSRV_EVENTLOG_REMOVEDIRECTORY_ERROR,
  645. Directory,
  646. DeleteHr );
  647. }
  648. }
  649. catch( const ComError & )
  650. {
  651. if ( INVALID_HANDLE_VALUE != FindHandle)
  652. {
  653. FindClose( FindHandle );
  654. }
  655. throw;
  656. }
  657. }
  658. void
  659. CreateBITSCacheDirectory(
  660. PropertyIDManager *PropertyManager,
  661. SmartIMSAdminBasePointer IISAdminBase,
  662. METADATA_HANDLE MdVDirKey,
  663. StringHandle GuidString )
  664. {
  665. DWORD BufferRequired;
  666. WCHAR VDirPath[ MAX_PATH ];
  667. WCHAR VDirSessionDir[ MAX_PATH ];
  668. METADATA_RECORD MdRecord;
  669. MdRecord.dwMDIdentifier = MD_VR_PATH;
  670. MdRecord.dwMDAttributes = METADATA_INHERIT;
  671. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  672. MdRecord.dwMDDataType = STRING_METADATA;
  673. MdRecord.dwMDDataLen = sizeof( VDirPath );
  674. MdRecord.pbMDData = (unsigned char*)VDirPath;
  675. MdRecord.dwMDDataTag = 0;
  676. THROW_COMERROR(
  677. IISAdminBase->GetData(
  678. MdVDirKey,
  679. NULL,
  680. &MdRecord,
  681. &BufferRequired ) );
  682. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
  683. MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
  684. MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
  685. THROW_COMERROR(
  686. IISAdminBase->GetData(
  687. MdVDirKey,
  688. NULL,
  689. &MdRecord,
  690. &BufferRequired ) );
  691. StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
  692. StringHandle( VDirSessionDir );
  693. StringHandle CleanupGuids = VDirSessionDirPath + StringHandle( L"\\" ) +
  694. StringHandle( CLEANUP_GUIDS_NAME );
  695. StringHandle CleanupGuidFile = CleanupGuids + StringHandle( L"\\" ) +
  696. GuidString;
  697. StringHandle VDirRequestsPath = VDirSessionDirPath + StringHandle( L"\\" ) +
  698. StringHandle( REQUESTS_DIR_NAMEW );
  699. StringHandle VDirRepliesPath = VDirSessionDirPath + StringHandle( L"\\" ) +
  700. StringHandle( REPLIES_DIR_NAMEW );
  701. //
  702. // Start some filesystem work
  703. //
  704. // *If* our VDir is located in a remote share, use the IIS
  705. // connection account info to connect to the share
  706. //
  707. CAccessRemoteVDir oVDir;
  708. oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
  709. try
  710. {
  711. BITSCreateDirectory(
  712. VDirSessionDirPath,
  713. BITS_SESSIONS_DIR_ACL,
  714. FALSE, // turn on the PROTECTED flag on the ACL, such that inheritance is interupted from the parent
  715. TRUE ); // explicitly add the SID of the creator owner to the ACL. Note that inheritance will be computed
  716. BITSCreateDirectory(
  717. CleanupGuids,
  718. BITS_CLEANUPGUIDS_DIR_ACL,
  719. TRUE, // Let the ACL for this directory inherit from the parent
  720. FALSE );// don't add the SID for the owner. It will be inherited
  721. {
  722. HANDLE GuidFile =
  723. CreateFile(
  724. CleanupGuidFile,
  725. GENERIC_ALL,
  726. 0,
  727. NULL,
  728. OPEN_ALWAYS,
  729. FILE_ATTRIBUTE_NORMAL,
  730. NULL );
  731. if ( INVALID_HANDLE_VALUE == GuidFile )
  732. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  733. CloseHandle( GuidFile );
  734. }
  735. BITSCreateDirectory(
  736. VDirRequestsPath,
  737. BITS_REQUESTS_DIR_ACL,
  738. TRUE, // Let the ACL for this directory inherit from the parent
  739. FALSE );// don't add the SID for the owner. It will be inherited
  740. BITSCreateDirectory(
  741. VDirRepliesPath,
  742. BITS_REPLIES_DIR_ACL,
  743. TRUE, // Let the ACL for this directory inherit from the parent
  744. FALSE );// don't add the SID for the owner. It will be inherited
  745. }
  746. catch( ComError Error )
  747. {
  748. // don't let this error propagate with the wrong user
  749. oVDir.RevertFromUNCAccount();
  750. throw;
  751. }
  752. //
  753. // Done with the filesystem access
  754. //
  755. oVDir.RevertFromUNCAccount();
  756. StringHandle SessionDirKeyPath = StringHandle( VDirSessionDir );
  757. StringHandle RequestsDirKeyPath = SessionDirKeyPath + StringHandle( L"\\" ) +
  758. StringHandle( REQUESTS_DIR_NAMEW );
  759. StringHandle RepliesDirKeyPath = SessionDirKeyPath + StringHandle( L"\\" ) +
  760. StringHandle( REPLIES_DIR_NAMEW );
  761. {
  762. HRESULT Hr = IISAdminBase->AddKey(
  763. MdVDirKey,
  764. SessionDirKeyPath );
  765. if ( FAILED( Hr ) && ( HRESULT_FROM_WIN32( ERROR_DUP_NAME ) != Hr ) )
  766. throw ComError( Hr );
  767. }
  768. {
  769. HRESULT Hr = IISAdminBase->AddKey(
  770. MdVDirKey,
  771. RepliesDirKeyPath );
  772. if ( FAILED( Hr ) && ( HRESULT_FROM_WIN32( ERROR_DUP_NAME ) != Hr ) )
  773. throw ComError( Hr );
  774. }
  775. DWORD AccessPermission = 0;
  776. MdRecord.dwMDIdentifier = MD_ACCESS_PERM;
  777. MdRecord.dwMDAttributes = METADATA_INHERIT;
  778. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  779. MdRecord.dwMDDataType = DWORD_METADATA;
  780. MdRecord.dwMDDataLen = sizeof( AccessPermission );
  781. MdRecord.pbMDData = (unsigned char*)&AccessPermission;
  782. MdRecord.dwMDDataTag = 0;
  783. THROW_COMERROR(
  784. IISAdminBase->SetData(
  785. MdVDirKey, //metadata handle..
  786. SessionDirKeyPath, //path of the key relative to hMDHandle.
  787. &MdRecord ) );
  788. AccessPermission = 1; // read only permissions
  789. THROW_COMERROR(
  790. IISAdminBase->SetData(
  791. MdVDirKey, //metadata handle..
  792. RepliesDirKeyPath, //path of the key relative to hMDHandle.
  793. &MdRecord ) );
  794. //
  795. // Set BITS-Sessions to disable browse.
  796. //
  797. DWORD BrowsePermission = 0;
  798. MdRecord.dwMDIdentifier = MD_DIRECTORY_BROWSING;
  799. MdRecord.dwMDAttributes = METADATA_INHERIT;
  800. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  801. MdRecord.dwMDDataType = DWORD_METADATA;
  802. MdRecord.dwMDDataLen = sizeof( BrowsePermission );
  803. MdRecord.pbMDData = (unsigned char*)&BrowsePermission;
  804. MdRecord.dwMDDataTag = 0;
  805. THROW_COMERROR(
  806. IISAdminBase->GetData(
  807. MdVDirKey,
  808. NULL,
  809. &MdRecord,
  810. &BufferRequired ) );
  811. BrowsePermission &= ~MD_DIRBROW_ENABLED;
  812. MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
  813. THROW_COMERROR(
  814. IISAdminBase->SetData(
  815. MdVDirKey,
  816. SessionDirKeyPath,
  817. &MdRecord ) );
  818. }
  819. void
  820. DeleteBITSCacheDirectory(
  821. PropertyIDManager *PropertyManager,
  822. SmartIMSAdminBasePointer IISAdminBase,
  823. METADATA_HANDLE MdVDirKey,
  824. const WCHAR *szObjectPath )
  825. {
  826. DWORD BufferRequired;
  827. WCHAR VDirPath[ MAX_PATH ];
  828. WCHAR VDirSessionDir[ MAX_PATH ];
  829. METADATA_RECORD MdRecord;
  830. MdRecord.dwMDIdentifier = MD_VR_PATH;
  831. MdRecord.dwMDAttributes = METADATA_INHERIT;
  832. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  833. MdRecord.dwMDDataType = STRING_METADATA;
  834. MdRecord.dwMDDataLen = sizeof( VDirPath );
  835. MdRecord.pbMDData = (unsigned char*)VDirPath;
  836. MdRecord.dwMDDataTag = 0;
  837. THROW_COMERROR(
  838. IISAdminBase->GetData(
  839. MdVDirKey,
  840. NULL,
  841. &MdRecord,
  842. &BufferRequired ) );
  843. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
  844. MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
  845. MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
  846. THROW_COMERROR(
  847. IISAdminBase->GetData(
  848. MdVDirKey,
  849. NULL,
  850. &MdRecord,
  851. &BufferRequired ) );
  852. WCHAR GuidString[ 255 ];
  853. {
  854. MdRecord.dwMDDataType = STRING_METADATA;
  855. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  856. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  857. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  858. MdRecord.dwMDDataLen = sizeof( GuidString );
  859. MdRecord.pbMDData = (PBYTE)GuidString;
  860. MdRecord.dwMDDataTag = 0;
  861. HRESULT Hr =
  862. IISAdminBase->GetData(
  863. MdVDirKey,
  864. NULL,
  865. &MdRecord,
  866. &BufferRequired );
  867. if ( MD_ERROR_DATA_NOT_FOUND == Hr )
  868. return; // The cache directory was never created.
  869. THROW_COMERROR( Hr );
  870. }
  871. StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
  872. StringHandle( VDirSessionDir );
  873. StringHandle CleanupGuids = VDirSessionDirPath + StringHandle( L"\\" ) +
  874. StringHandle( CLEANUP_GUIDS_NAME );
  875. StringHandle CleanupGuidFile = CleanupGuids + StringHandle( L"\\" ) +
  876. GuidString;
  877. //
  878. // Prepare to do some filesystem work
  879. //
  880. // *If* our VDir is located in a remote share, use the IIS
  881. // connection account info to impersonate that user
  882. CAccessRemoteVDir oVDir;
  883. oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
  884. try
  885. {
  886. DeleteFile( CleanupGuidFile );
  887. BOOL RemovedCleanupDirs = RemoveDirectory( CleanupGuids );
  888. if ( RemovedCleanupDirs ||
  889. ERROR_PATH_NOT_FOUND == GetLastError() ||
  890. ERROR_FILE_NOT_FOUND == GetLastError() )
  891. {
  892. // This is the last "enlistment"
  893. DeleteDirectoryTree( VDirSessionDirPath );
  894. }
  895. }
  896. catch( ComError Error )
  897. {
  898. // don't let this error propagate with the wrong user
  899. oVDir.RevertFromUNCAccount();
  900. throw;
  901. }
  902. //
  903. // Done with the filesystem access
  904. //
  905. oVDir.RevertFromUNCAccount();
  906. IISAdminBase->DeleteKey( MdVDirKey, VDirSessionDir );
  907. }
  908. void
  909. DeleteOldBITSCacheDirectory(
  910. PropertyIDManager *PropertyManager,
  911. SmartIMSAdminBasePointer IISAdminBase,
  912. METADATA_HANDLE MdVDirKey,
  913. const WCHAR *szObjectPath )
  914. {
  915. DWORD BufferRequired;
  916. WCHAR VDirPath[ MAX_PATH ];
  917. WCHAR VDirSessionDir[ MAX_PATH ];
  918. METADATA_RECORD MdRecord;
  919. MdRecord.dwMDIdentifier = MD_VR_PATH;
  920. MdRecord.dwMDAttributes = METADATA_INHERIT;
  921. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  922. MdRecord.dwMDDataType = STRING_METADATA;
  923. MdRecord.dwMDDataLen = sizeof( VDirPath );
  924. MdRecord.pbMDData = (unsigned char*)VDirPath;
  925. MdRecord.dwMDDataTag = 0;
  926. THROW_COMERROR(
  927. IISAdminBase->GetData(
  928. MdVDirKey,
  929. NULL,
  930. &MdRecord,
  931. &BufferRequired ) );
  932. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CONNECTION_DIR );
  933. MdRecord.dwMDDataLen = sizeof( VDirSessionDir );
  934. MdRecord.pbMDData = (unsigned char*)VDirSessionDir;
  935. THROW_COMERROR(
  936. IISAdminBase->GetData(
  937. MdVDirKey,
  938. NULL,
  939. &MdRecord,
  940. &BufferRequired ) );
  941. StringHandle VDirSessionDirPath = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
  942. StringHandle( VDirSessionDir );
  943. StringHandle VDirSessionDirPath2 = StringHandle( VDirPath ) + StringHandle( L"\\" ) +
  944. StringHandle( VDirSessionDir ) + StringHandle(L".bak");
  945. StringHandle DirectoryToDelete;
  946. //
  947. // Prepare to do some filesystem work
  948. //
  949. // *If* our VDir is located in a remote share, use the IIS
  950. // connection account info to impersonate that user
  951. CAccessRemoteVDir oVDir;
  952. oVDir.LoginToUNC( IISAdminBase, MdVDirKey );
  953. try
  954. {
  955. if ( !MoveFileEx(
  956. VDirSessionDirPath,
  957. VDirSessionDirPath2,
  958. 0 ) )
  959. {
  960. DWORD dwError = GetLastError();
  961. if ( ERROR_PATH_NOT_FOUND == dwError ||
  962. ERROR_FILE_NOT_FOUND == dwError )
  963. {
  964. oVDir.RevertFromUNCAccount();
  965. return;
  966. }
  967. DirectoryToDelete = VDirSessionDirPath;
  968. }
  969. else
  970. {
  971. DirectoryToDelete = VDirSessionDirPath2;
  972. }
  973. DeleteDirectoryTree( DirectoryToDelete );
  974. }
  975. catch( ComError Error )
  976. {
  977. // don't let this error propagate with the wrong user
  978. oVDir.RevertFromUNCAccount();
  979. throw;
  980. }
  981. //
  982. // Done with the filesystem access
  983. //
  984. oVDir.RevertFromUNCAccount();
  985. }
  986. void
  987. GetVDirPropertyVersion(
  988. PropertyIDManager *PropertyManager,
  989. SmartIMSAdminBasePointer IISAdminBase,
  990. METADATA_HANDLE MdVDirKey,
  991. bool * pIsEnabled,
  992. DWORD * pdwVersion )
  993. {
  994. *pIsEnabled = false;
  995. *pdwVersion = 0;
  996. HRESULT Hr;
  997. DWORD IsEnabled = 0;
  998. METADATA_RECORD MdRecord;
  999. DWORD BufferRequired;
  1000. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  1001. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1002. MdRecord.dwMDUserType = ALL_METADATA;
  1003. MdRecord.dwMDDataType = DWORD_METADATA;
  1004. MdRecord.dwMDDataLen = sizeof(IsEnabled);
  1005. MdRecord.pbMDData = (PBYTE)&IsEnabled;
  1006. MdRecord.dwMDDataTag = 0;
  1007. Hr =
  1008. IISAdminBase->GetData(
  1009. MdVDirKey,
  1010. NULL,
  1011. &MdRecord,
  1012. &BufferRequired );
  1013. if ( FAILED( Hr ) )
  1014. {
  1015. if ( !( MD_ERROR_DATA_NOT_FOUND == Hr ||
  1016. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) )
  1017. throw ComError( Hr );
  1018. }
  1019. *pIsEnabled = !!IsEnabled;
  1020. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_METADATA_VERSION );
  1021. MdRecord.dwMDDataLen = sizeof(*pdwVersion);
  1022. MdRecord.pbMDData = (PBYTE)pdwVersion;
  1023. Hr =
  1024. IISAdminBase->GetData(
  1025. MdVDirKey,
  1026. NULL,
  1027. &MdRecord,
  1028. &BufferRequired );
  1029. if ( FAILED( Hr ) )
  1030. {
  1031. if ( !( MD_ERROR_DATA_NOT_FOUND == Hr ||
  1032. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr ) )
  1033. throw ComError( Hr );
  1034. }
  1035. }
  1036. void
  1037. SetVDirEnabled(
  1038. PropertyIDManager *PropertyManager,
  1039. SmartIMSAdminBasePointer IISAdminBase,
  1040. METADATA_HANDLE MdVDirKey )
  1041. {
  1042. METADATA_RECORD MdRecord;
  1043. DWORD EnableData = 1;
  1044. DWORD MetadataVersion = CURRENT_UPLOAD_METADATA_VERSION;
  1045. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_METADATA_VERSION );
  1046. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1047. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_METADATA_VERSION );
  1048. MdRecord.dwMDDataType = DWORD_METADATA;
  1049. MdRecord.dwMDDataLen = sizeof(MetadataVersion);
  1050. MdRecord.pbMDData = (PBYTE)&MetadataVersion;
  1051. MdRecord.dwMDDataTag = 0;
  1052. THROW_COMERROR(
  1053. IISAdminBase->SetData(
  1054. MdVDirKey,
  1055. NULL,
  1056. &MdRecord ) );
  1057. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  1058. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED );
  1059. MdRecord.dwMDDataLen = sizeof(EnableData);
  1060. MdRecord.pbMDData = (PBYTE)&EnableData;
  1061. THROW_COMERROR(
  1062. IISAdminBase->SetData(
  1063. MdVDirKey,
  1064. NULL,
  1065. &MdRecord ) );
  1066. }
  1067. void
  1068. EnableBITSForVDIR(
  1069. PropertyIDManager *PropertyManager,
  1070. SmartIMSAdminBasePointer IISAdminBase,
  1071. LPWSTR Path )
  1072. {
  1073. HRESULT Hr;
  1074. METADATA_RECORD MdRecord;
  1075. METADATA_HANDLE MdVDirKey = NULL;
  1076. LPWSTR NewScriptMapBuffer = NULL;
  1077. SmartITaskSchedulerPointer TaskScheduler;
  1078. DWORD BufferRequired;
  1079. bool IsEnabled = 0;
  1080. DWORD MetadataVersion = 0;
  1081. try
  1082. {
  1083. THROW_COMERROR(
  1084. IISAdminBase->OpenKey(
  1085. METADATA_MASTER_ROOT_HANDLE,
  1086. Path,
  1087. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1088. METABASE_OPEN_KEY_TIMEOUT,
  1089. &MdVDirKey ) );
  1090. GetVDirPropertyVersion(
  1091. PropertyManager,
  1092. IISAdminBase,
  1093. MdVDirKey,
  1094. &IsEnabled,
  1095. &MetadataVersion );
  1096. if ( IsEnabled )
  1097. {
  1098. if ( MetadataVersion >= CURRENT_UPLOAD_METADATA_VERSION )
  1099. {
  1100. // Nothing to do, just leave.
  1101. IISAdminBase->CloseKey( MdVDirKey );
  1102. return;
  1103. }
  1104. IISAdminBase->CloseKey( MdVDirKey );
  1105. MdVDirKey = NULL;
  1106. DisableBITSForVDIR(
  1107. PropertyManager,
  1108. IISAdminBase,
  1109. Path,
  1110. false,
  1111. true );
  1112. EnableBITSForVDIR(
  1113. PropertyManager,
  1114. IISAdminBase,
  1115. Path );
  1116. return;
  1117. }
  1118. // Generate the new GUID string
  1119. WCHAR GuidString[ 255 ];
  1120. // first try looking up the guid
  1121. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1122. MdRecord.dwMDDataType = STRING_METADATA;
  1123. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  1124. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  1125. MdRecord.dwMDDataLen = sizeof( GuidString );
  1126. MdRecord.pbMDData = (PBYTE)GuidString;
  1127. MdRecord.dwMDDataTag = 0;
  1128. Hr = IISAdminBase->GetData(
  1129. MdVDirKey,
  1130. NULL,
  1131. &MdRecord,
  1132. &BufferRequired );
  1133. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  1134. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  1135. {
  1136. // create a new guid and save it away
  1137. GUID guid;
  1138. THROW_COMERROR( CoCreateGuid( &guid ) );
  1139. StringFromGUID2( guid, GuidString, 254 );
  1140. MdRecord.dwMDDataLen = sizeof(WCHAR) * ( wcslen(GuidString) + 1 );
  1141. MdRecord.pbMDData = (PBYTE)GuidString;
  1142. THROW_COMERROR(
  1143. IISAdminBase->SetData(
  1144. MdVDirKey,
  1145. NULL,
  1146. &MdRecord ) );
  1147. }
  1148. else if ( FAILED( Hr ) )
  1149. throw ComError( Hr );
  1150. // build the string to add to the scriptmap
  1151. WCHAR SystemDir[ MAX_PATH + 1 ];
  1152. if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) )
  1153. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  1154. SystemDir[ MAX_PATH ] = L'\0';
  1155. WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
  1156. StringCchPrintfW(
  1157. ScriptMapString,
  1158. ARRAY_ELEMENTS( ScriptMapString ),
  1159. L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW,
  1160. SystemDir );
  1161. int RetChars = wcslen( ScriptMapString );
  1162. ScriptMapString[ RetChars ] = L'\0';
  1163. ScriptMapString[ RetChars + 1] = L'\0';
  1164. RetChars += 2; // ScriptMapScript is now double NULL terminated
  1165. CreateBITSCacheDirectory(
  1166. PropertyManager,
  1167. IISAdminBase,
  1168. MdVDirKey,
  1169. StringHandle( GuidString ) );
  1170. DWORD AccessFlags;
  1171. MdRecord.dwMDIdentifier = MD_ACCESS_PERM;
  1172. MdRecord.dwMDAttributes = METADATA_INHERIT;
  1173. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  1174. MdRecord.dwMDDataType = DWORD_METADATA;
  1175. MdRecord.dwMDDataLen = sizeof( AccessFlags );
  1176. MdRecord.pbMDData = (unsigned char*)&AccessFlags;
  1177. MdRecord.dwMDDataTag = 0;
  1178. try
  1179. {
  1180. THROW_COMERROR(
  1181. IISAdminBase->GetData(
  1182. MdVDirKey,
  1183. NULL,
  1184. &MdRecord,
  1185. &BufferRequired ) );
  1186. }
  1187. catch( ComError Error )
  1188. {
  1189. if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
  1190. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Error.m_Hr )
  1191. {
  1192. AccessFlags = 0;
  1193. }
  1194. else
  1195. throw;
  1196. }
  1197. if ( AccessFlags & ( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE ) )
  1198. {
  1199. AccessFlags &= ~( MD_ACCESS_SCRIPT | MD_ACCESS_EXECUTE );
  1200. MdRecord.dwMDAttributes &= ~METADATA_ISINHERITED;
  1201. THROW_COMERROR(
  1202. IISAdminBase->SetData(
  1203. MdVDirKey,
  1204. NULL,
  1205. &MdRecord ) );
  1206. }
  1207. //
  1208. // retrieve the current scriptmap adding room to the allocated memory
  1209. //
  1210. memset( &MdRecord, 0, sizeof( MdRecord ) );
  1211. MdRecord.dwMDDataType = MULTISZ_METADATA;
  1212. MdRecord.dwMDAttributes = METADATA_INHERIT;
  1213. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  1214. MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS;
  1215. MdRecord.dwMDDataLen = 0;
  1216. MdRecord.pbMDData = (PBYTE)NULL;
  1217. MdRecord.dwMDDataTag = 0;
  1218. Hr =
  1219. IISAdminBase->GetData(
  1220. MdVDirKey,
  1221. NULL,
  1222. &MdRecord,
  1223. &BufferRequired );
  1224. if ( MD_ERROR_DATA_NOT_FOUND == Hr ||
  1225. HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) == Hr )
  1226. {
  1227. // The Current key doesn't exist.
  1228. MdRecord.pbMDData = (PBYTE)ScriptMapString;
  1229. MdRecord.dwMDDataLen = RetChars * sizeof(WCHAR);
  1230. }
  1231. else if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) == Hr )
  1232. {
  1233. NewScriptMapBuffer = new WCHAR[ ( BufferRequired / sizeof(WCHAR) ) + RetChars ];
  1234. MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer;
  1235. MdRecord.dwMDDataLen = BufferRequired + ( RetChars * sizeof(WCHAR) );
  1236. THROW_COMERROR(
  1237. IISAdminBase->GetData(
  1238. MdVDirKey,
  1239. NULL,
  1240. &MdRecord,
  1241. &BufferRequired ) );
  1242. // append script entry at the end
  1243. for( WCHAR *p = NewScriptMapBuffer; *p != 0; p += ( wcslen( p ) + 1 ) );
  1244. memcpy( p, ScriptMapString, RetChars * sizeof(WCHAR) );
  1245. MdRecord.pbMDData = (PBYTE)NewScriptMapBuffer;
  1246. MdRecord.dwMDDataLen = (DWORD)( ( (char*)p - (char*)NewScriptMapBuffer ) +
  1247. ( RetChars * sizeof(WCHAR) ) );
  1248. }
  1249. else
  1250. throw ComError( Hr );
  1251. THROW_COMERROR(
  1252. IISAdminBase->SetData(
  1253. MdVDirKey,
  1254. NULL,
  1255. &MdRecord ) );
  1256. // Create the task scheduler cleanup work item
  1257. ConnectToTaskScheduler( NULL, &TaskScheduler );
  1258. CreateWorkItemForVDIR( TaskScheduler, Path, GuidString );
  1259. delete[] NewScriptMapBuffer;
  1260. NewScriptMapBuffer = NULL;
  1261. SetVDirEnabled(
  1262. PropertyManager,
  1263. IISAdminBase,
  1264. MdVDirKey );
  1265. IISAdminBase->CloseKey( MdVDirKey );
  1266. }
  1267. catch( ComError Exception )
  1268. {
  1269. if ( MdVDirKey )
  1270. {
  1271. delete[] NewScriptMapBuffer;
  1272. IISAdminBase->CloseKey( MdVDirKey );
  1273. try
  1274. {
  1275. DisableBITSForVDIR(
  1276. PropertyManager,
  1277. IISAdminBase,
  1278. Path,
  1279. true,
  1280. false );
  1281. }
  1282. catch( const ComError & )
  1283. {
  1284. }
  1285. }
  1286. throw;
  1287. }
  1288. }
  1289. void
  1290. DisableBITSForVDIR(
  1291. PropertyIDManager *PropertyManager,
  1292. SmartIMSAdminBasePointer IISAdminBase,
  1293. LPCWSTR Path,
  1294. bool RollbackCleanup,
  1295. bool DisableForUpgrade )
  1296. {
  1297. METADATA_HANDLE MdVDirKey = NULL;
  1298. LPWSTR OriginalScriptMap = NULL;
  1299. LPWSTR NewScriptMap = NULL;
  1300. SmartITaskSchedulerPointer TaskScheduler;
  1301. try
  1302. {
  1303. #if 0
  1304. if ( !RollbackCleanup && !DisableForUpgrade )
  1305. CleanupForRemoval( Path );
  1306. #endif
  1307. // build the string to add to the scriptmap
  1308. WCHAR SystemDir[ MAX_PATH + 1 ];
  1309. if (!GetSystemDirectoryW( SystemDir, MAX_PATH ) )
  1310. throw ComError( HRESULT_FROM_WIN32( GetLastError() ) );
  1311. WCHAR ScriptMapString[ MAX_PATH * 2 + 1 ];
  1312. StringCchPrintfW(
  1313. ScriptMapString,
  1314. MAX_PATH * 2 + 1,
  1315. L"*,%s\\bitssrv.dll,1,BITS_COMMAND",
  1316. SystemDir );
  1317. int RetChars = wcslen( ScriptMapString );
  1318. ScriptMapString[ RetChars ] = L'\0';
  1319. ScriptMapString[ RetChars + 1] = L'\0';
  1320. // ScriptMapScript is now double NULL terminated
  1321. WCHAR ScriptMapString2[ MAX_PATH * 2 + 1];
  1322. StringCchPrintfW(
  1323. ScriptMapString2,
  1324. ARRAY_ELEMENTS( ScriptMapString2 ),
  1325. L"*,%\\bitsserver.dll,1,BITS_COMMAND",
  1326. SystemDir );
  1327. RetChars = wcslen( ScriptMapString2 );
  1328. ScriptMapString2[ RetChars ] = L'\0';
  1329. ScriptMapString2[ RetChars + 1 ] = L'\0';
  1330. // ScriptMapScript2 is not double NULL terminated
  1331. WCHAR ScriptMapString3[ MAX_PATH * 2 + 1 ];
  1332. StringCchPrintfW(
  1333. ScriptMapString3,
  1334. ARRAY_ELEMENTS( ScriptMapString3 ),
  1335. L"*,%s\\bitssrv.dll,1," BITS_COMMAND_VERBW,
  1336. SystemDir );
  1337. RetChars = wcslen( ScriptMapString3 );
  1338. ScriptMapString3[ RetChars ] = L'\0';
  1339. ScriptMapString3[ RetChars + 1] = L'\0';
  1340. // ScriptMapScript3 is now double NULL terminated
  1341. THROW_COMERROR(
  1342. IISAdminBase->OpenKey(
  1343. METADATA_MASTER_ROOT_HANDLE,
  1344. Path,
  1345. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1346. METABASE_OPEN_KEY_TIMEOUT,
  1347. &MdVDirKey ) );
  1348. if ( DisableForUpgrade )
  1349. {
  1350. DeleteOldBITSCacheDirectory(
  1351. PropertyManager,
  1352. IISAdminBase,
  1353. MdVDirKey,
  1354. Path );
  1355. }
  1356. else
  1357. {
  1358. DeleteBITSCacheDirectory(
  1359. PropertyManager,
  1360. IISAdminBase,
  1361. MdVDirKey,
  1362. Path );
  1363. }
  1364. //
  1365. // retrieve the current scriptmap adding room to the allocated memory
  1366. //
  1367. DWORD BufferRequired;
  1368. METADATA_RECORD MdRecord;
  1369. memset( &MdRecord, 0, sizeof( MdRecord ) );
  1370. MdRecord.dwMDDataType = MULTISZ_METADATA;
  1371. MdRecord.dwMDAttributes = METADATA_INHERIT;
  1372. MdRecord.dwMDUserType = IIS_MD_UT_FILE;
  1373. MdRecord.dwMDIdentifier = MD_SCRIPT_MAPS;
  1374. MdRecord.dwMDDataLen = 0;
  1375. MdRecord.pbMDData = (PBYTE)NULL;
  1376. HRESULT Hr =
  1377. IISAdminBase->GetData(
  1378. MdVDirKey,
  1379. NULL,
  1380. &MdRecord,
  1381. &BufferRequired );
  1382. if ( HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER ) != Hr )
  1383. throw ComError( Hr );
  1384. OriginalScriptMap = new WCHAR[ BufferRequired / 2 + 2 ];
  1385. NewScriptMap = new WCHAR[ BufferRequired / 2 + 2 ];
  1386. OriginalScriptMap[0] = OriginalScriptMap[1] = L'\0';
  1387. MdRecord.dwMDDataLen = BufferRequired;
  1388. MdRecord.pbMDData = (PBYTE)OriginalScriptMap;
  1389. THROW_COMERROR(
  1390. IISAdminBase->GetData(
  1391. MdVDirKey,
  1392. NULL,
  1393. &MdRecord,
  1394. &BufferRequired ) );
  1395. // Copy the orignal Scriptmap to the new scriptmap
  1396. // removing bits goo in the process.
  1397. LPWSTR CurrentOriginalItem = OriginalScriptMap;
  1398. LPWSTR CurrentNewItem = NewScriptMap;
  1399. for( ;L'\0' != *CurrentOriginalItem;
  1400. CurrentOriginalItem += ( wcslen( CurrentOriginalItem ) + 1 ) )
  1401. {
  1402. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString ) == 0 )
  1403. continue; //remove this item
  1404. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString2 ) == 0 )
  1405. continue;
  1406. if ( _wcsicmp( CurrentOriginalItem, ScriptMapString3 ) == 0 )
  1407. continue;
  1408. SIZE_T CurrentOriginalItemSize = wcslen( CurrentOriginalItem ) + 1;
  1409. memcpy( CurrentNewItem, CurrentOriginalItem, CurrentOriginalItemSize * sizeof( WCHAR ) );
  1410. CurrentNewItem += CurrentOriginalItemSize;
  1411. }
  1412. // Add the extra 0
  1413. *CurrentNewItem++ = L'\0';
  1414. MdRecord.dwMDDataLen = (DWORD)( (char*)CurrentNewItem - (char*)NewScriptMap );
  1415. MdRecord.pbMDData = (PBYTE)NewScriptMap;
  1416. // set the new scriptmap
  1417. THROW_COMERROR(
  1418. IISAdminBase->SetData(
  1419. MdVDirKey,
  1420. NULL,
  1421. &MdRecord ) );
  1422. // Set the enabled property first
  1423. DWORD EnableData = 0;
  1424. METADATA_RECORD MdEnabledRecord;
  1425. MdEnabledRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1426. MdEnabledRecord.dwMDDataType = DWORD_METADATA;
  1427. MdEnabledRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_UPLOAD_ENABLED );
  1428. MdEnabledRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_UPLOAD_ENABLED );
  1429. MdEnabledRecord.dwMDDataLen = sizeof(EnableData);
  1430. MdEnabledRecord.pbMDData = (PBYTE)&EnableData;
  1431. MdEnabledRecord.dwMDDataTag = 0;
  1432. THROW_COMERROR(
  1433. IISAdminBase->SetData(
  1434. MdVDirKey,
  1435. NULL,
  1436. &MdEnabledRecord ) );
  1437. if ( !DisableForUpgrade )
  1438. {
  1439. WCHAR GuidString[ 255 ];
  1440. memset( &MdRecord, 0, sizeof( MdRecord ) );
  1441. MdRecord.dwMDDataType = STRING_METADATA;
  1442. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1443. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  1444. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  1445. MdRecord.dwMDDataLen = sizeof( GuidString );
  1446. MdRecord.pbMDData = (PBYTE)GuidString;
  1447. Hr =
  1448. IISAdminBase->GetData(
  1449. MdVDirKey,
  1450. NULL,
  1451. &MdRecord,
  1452. &BufferRequired );
  1453. if ( FAILED( Hr ) && Hr != MD_ERROR_DATA_NOT_FOUND )
  1454. throw ComError( Hr );
  1455. if ( SUCCEEDED( Hr ) )
  1456. {
  1457. try
  1458. {
  1459. ConnectToTaskScheduler( NULL, &TaskScheduler );
  1460. DeleteWorkItemForVDIR( TaskScheduler, GuidString );
  1461. THROW_COMERROR(
  1462. IISAdminBase->DeleteData(
  1463. MdVDirKey,
  1464. NULL,
  1465. PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY ),
  1466. ALL_METADATA ) );
  1467. }
  1468. catch( const ComError & )
  1469. {
  1470. if ( !RollbackCleanup )
  1471. throw;
  1472. }
  1473. }
  1474. }
  1475. delete[] OriginalScriptMap;
  1476. delete[] NewScriptMap;
  1477. IISAdminBase->CloseKey( MdVDirKey );
  1478. MdVDirKey = NULL;
  1479. }
  1480. catch( ComError Exception )
  1481. {
  1482. delete[] OriginalScriptMap;
  1483. delete[] NewScriptMap;
  1484. if ( MdVDirKey )
  1485. IISAdminBase->CloseKey( MdVDirKey );
  1486. throw;
  1487. }
  1488. }
  1489. void
  1490. FindWorkItemForVDIR(
  1491. PropertyIDManager *PropertyManager,
  1492. SmartIMSAdminBasePointer AdminBase,
  1493. LPCWSTR Path,
  1494. LPWSTR *ReturnedTaskName )
  1495. {
  1496. if ( ReturnedTaskName )
  1497. *ReturnedTaskName = NULL;
  1498. try
  1499. {
  1500. WCHAR GuidString[ 255 ];
  1501. DWORD BufferRequired;
  1502. METADATA_RECORD MdRecord;
  1503. HRESULT Hr;
  1504. MdRecord.dwMDDataType = STRING_METADATA;
  1505. MdRecord.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  1506. MdRecord.dwMDUserType = PropertyManager->GetPropertyUserType( MD_BITS_CLEANUP_WORKITEM_KEY );
  1507. MdRecord.dwMDIdentifier = PropertyManager->GetPropertyMetabaseID( MD_BITS_CLEANUP_WORKITEM_KEY );
  1508. MdRecord.dwMDDataLen = sizeof( GuidString );
  1509. MdRecord.pbMDData = (PBYTE)GuidString;
  1510. MdRecord.dwMDDataTag = 0;
  1511. THROW_COMERROR(
  1512. AdminBase->GetData(
  1513. METADATA_MASTER_ROOT_HANDLE,
  1514. Path,
  1515. &MdRecord,
  1516. &BufferRequired ) );
  1517. SmartITaskSchedulerPointer TaskScheduler;
  1518. ConnectToTaskScheduler( NULL, &TaskScheduler );
  1519. FindWorkItemForVDIR( TaskScheduler, GuidString, NULL, ReturnedTaskName );
  1520. }
  1521. catch( ComError Error )
  1522. {
  1523. // simply return NULL if the task item isn't found.
  1524. if ( MD_ERROR_DATA_NOT_FOUND == Error.m_Hr ||
  1525. HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) == Error.m_Hr )
  1526. throw ComError( S_FALSE );
  1527. }
  1528. }
  1529. CBITSExtensionSetupFactory::CBITSExtensionSetupFactory() :
  1530. m_cref(1),
  1531. m_TypeInfo(NULL)
  1532. {
  1533. OBJECT_CREATED
  1534. }
  1535. CBITSExtensionSetupFactory::~CBITSExtensionSetupFactory()
  1536. {
  1537. if ( m_TypeInfo )
  1538. m_TypeInfo->Release();
  1539. OBJECT_DESTROYED
  1540. }
  1541. STDMETHODIMP CBITSExtensionSetupFactory::QueryInterface(REFIID riid, LPVOID *ppv)
  1542. {
  1543. if (!ppv)
  1544. return E_FAIL;
  1545. *ppv = NULL;
  1546. if (IsEqualIID(riid, IID_IUnknown))
  1547. *ppv = static_cast<IUnknown *>(this);
  1548. else if (IsEqualIID(riid, __uuidof(IBITSExtensionSetupFactory)))
  1549. *ppv = static_cast<IBITSExtensionSetupFactory *>(this);
  1550. if (*ppv)
  1551. {
  1552. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  1553. return S_OK;
  1554. }
  1555. return E_NOINTERFACE;
  1556. }
  1557. STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::AddRef()
  1558. {
  1559. return InterlockedIncrement((LONG *)&m_cref);
  1560. }
  1561. STDMETHODIMP_(ULONG) CBITSExtensionSetupFactory::Release()
  1562. {
  1563. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  1564. {
  1565. // we need to decrement our object count in the DLL
  1566. delete this;
  1567. return 0;
  1568. }
  1569. return m_cref;
  1570. }
  1571. HRESULT
  1572. CBITSExtensionSetupFactory::LoadTypeInfo()
  1573. {
  1574. if ( m_TypeInfo )
  1575. return S_OK;
  1576. return ::GetTypeInfo( __uuidof( IBITSExtensionSetupFactory ), &m_TypeInfo );
  1577. }
  1578. STDMETHODIMP
  1579. CBITSExtensionSetupFactory::GetIDsOfNames(
  1580. REFIID,
  1581. OLECHAR FAR* FAR* rgszNames,
  1582. unsigned int cNames,
  1583. LCID,
  1584. DISPID FAR* rgDispId )
  1585. {
  1586. HRESULT Hr;
  1587. Hr = LoadTypeInfo();
  1588. if ( FAILED( Hr ) )
  1589. return Hr;
  1590. return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
  1591. }
  1592. STDMETHODIMP
  1593. CBITSExtensionSetupFactory::GetTypeInfo(
  1594. unsigned int iTInfo,
  1595. LCID lcid,
  1596. ITypeInfo FAR* FAR* ppTInfo )
  1597. {
  1598. *ppTInfo = NULL;
  1599. if(iTInfo != 0)
  1600. return ResultFromScode(DISP_E_BADINDEX);
  1601. HRESULT Hr;
  1602. Hr = LoadTypeInfo();
  1603. if ( FAILED( Hr ) )
  1604. return Hr;
  1605. m_TypeInfo->AddRef();
  1606. *ppTInfo = m_TypeInfo;
  1607. return NOERROR;
  1608. }
  1609. STDMETHODIMP
  1610. CBITSExtensionSetupFactory::GetTypeInfoCount(
  1611. unsigned int FAR* pctinfo )
  1612. {
  1613. *pctinfo = 1;
  1614. return NOERROR;
  1615. }
  1616. STDMETHODIMP
  1617. CBITSExtensionSetupFactory::Invoke(
  1618. DISPID dispIdMember,
  1619. REFIID,
  1620. LCID,
  1621. WORD wFlags,
  1622. DISPPARAMS FAR* pDispParams,
  1623. VARIANT FAR* pVarResult,
  1624. EXCEPINFO FAR* pExcepInfo,
  1625. unsigned int FAR* puArgErr )
  1626. {
  1627. HRESULT Hr;
  1628. Hr = LoadTypeInfo();
  1629. if ( FAILED( Hr ) )
  1630. return Hr;
  1631. return
  1632. DispInvoke(
  1633. this,
  1634. m_TypeInfo,
  1635. dispIdMember,
  1636. wFlags,
  1637. pDispParams,
  1638. pVarResult,
  1639. pExcepInfo,
  1640. puArgErr);
  1641. }
  1642. STDMETHODIMP CBITSExtensionSetupFactory::GetObject(
  1643. BSTR Path,
  1644. IBITSExtensionSetup **ppExtensionSetup )
  1645. {
  1646. WCHAR *ObjectPath = NULL;
  1647. IUnknown *Object = NULL;
  1648. try
  1649. {
  1650. if ( !Path || !ppExtensionSetup )
  1651. throw ComError( E_INVALIDARG );
  1652. *ppExtensionSetup = NULL;
  1653. ObjectPath = CSimplePropertyReader::ConvertObjectPathToADSI( (WCHAR*)Path );
  1654. THROW_COMERROR( ADsGetObject( BSTR( ObjectPath ), __uuidof( IUnknown ), (void**)&Object ) );
  1655. delete ObjectPath;
  1656. ObjectPath = NULL;
  1657. CBITSExtensionSetup *SetupObj = new CBITSExtensionSetup( NULL, Object );
  1658. if ( !SetupObj )
  1659. throw ComError( E_OUTOFMEMORY );
  1660. Object = NULL;
  1661. *ppExtensionSetup = static_cast<IBITSExtensionSetup*>( SetupObj );
  1662. return S_OK;
  1663. }
  1664. catch( ComError Error )
  1665. {
  1666. delete ObjectPath;
  1667. if ( Object )
  1668. Object->Release();
  1669. return Error.m_Hr;
  1670. }
  1671. }
  1672. STDMETHODIMP CNonDelegatingIUnknown::QueryInterface(REFIID riid, LPVOID *ppv)
  1673. {
  1674. if (!ppv)
  1675. return E_FAIL;
  1676. *ppv = NULL;
  1677. if ( riid == __uuidof(IUnknown) )
  1678. *ppv = static_cast<IUnknown *>(this);
  1679. else if ( riid == __uuidof(IDispatch) )
  1680. *ppv = static_cast<IDispatch*>(m_DelegatingIUnknown);
  1681. else if ( riid == __uuidof(IBITSExtensionSetup) )
  1682. *ppv = static_cast<IBITSExtensionSetup *>(m_DelegatingIUnknown);
  1683. else if ( riid == __uuidof(IADsExtension) )
  1684. *ppv = static_cast<IADsExtension *>(m_DelegatingIUnknown);
  1685. if (*ppv)
  1686. {
  1687. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  1688. return S_OK;
  1689. }
  1690. return E_NOINTERFACE;
  1691. }
  1692. STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::AddRef()
  1693. {
  1694. return InterlockedIncrement((LONG *)&m_cref);
  1695. }
  1696. STDMETHODIMP_(ULONG) CNonDelegatingIUnknown::Release()
  1697. {
  1698. if (InterlockedDecrement((LONG *)&m_cref) == 0)
  1699. {
  1700. // we need to decrement our object count in the DLL
  1701. delete m_DelegatingIUnknown;
  1702. return 0;
  1703. }
  1704. return m_cref;
  1705. }
  1706. CNonDelegatingIUnknown::CNonDelegatingIUnknown( CBITSExtensionSetup * DelegatingIUnknown ) :
  1707. m_DelegatingIUnknown( DelegatingIUnknown ),
  1708. m_cref(1)
  1709. {
  1710. }
  1711. CBITSExtensionSetup::CBITSExtensionSetup( IUnknown *Outer, IUnknown *Object ) :
  1712. m_pOuter( Outer ),
  1713. m_pObject( Object ),
  1714. m_OuterDispatch( NULL ),
  1715. m_TypeInfo( NULL ),
  1716. m_ADSIPath( NULL ),
  1717. m_Path( NULL ),
  1718. m_PropertyMan( NULL ),
  1719. m_DelegationIUnknown( this ),
  1720. m_RemoteInterface( NULL ),
  1721. m_InitComplete( false ),
  1722. m_Lock( 0 )
  1723. {
  1724. if ( m_pOuter )
  1725. {
  1726. HRESULT Hr = m_pOuter->QueryInterface( __uuidof( IDispatch ), (void**)&m_OuterDispatch );
  1727. if ( FAILED( Hr ) )
  1728. m_OuterDispatch = NULL;
  1729. }
  1730. OBJECT_CREATED
  1731. }
  1732. CBITSExtensionSetup::~CBITSExtensionSetup()
  1733. {
  1734. if ( m_pObject )
  1735. {
  1736. m_pObject->Release();
  1737. m_pObject = NULL;
  1738. }
  1739. if ( m_OuterDispatch )
  1740. m_OuterDispatch->Release();
  1741. if ( m_TypeInfo )
  1742. m_TypeInfo->Release();
  1743. delete[] m_Path; // Noop on NULL
  1744. m_Path = NULL;
  1745. if ( m_RemoteInterface )
  1746. m_RemoteInterface->Release();
  1747. delete m_PropertyMan;
  1748. SysFreeString( m_ADSIPath );
  1749. OBJECT_DESTROYED
  1750. }
  1751. STDMETHODIMP CBITSExtensionSetup::QueryInterface(REFIID riid, LPVOID *ppv)
  1752. {
  1753. if ( m_pOuter )
  1754. return m_pOuter->QueryInterface( riid, ppv );
  1755. else
  1756. return m_DelegationIUnknown.QueryInterface( riid, ppv );
  1757. }
  1758. STDMETHODIMP_(ULONG) CBITSExtensionSetup::AddRef()
  1759. {
  1760. if ( m_pOuter )
  1761. return m_pOuter->AddRef();
  1762. else
  1763. return m_DelegationIUnknown.AddRef();
  1764. }
  1765. STDMETHODIMP_(ULONG) CBITSExtensionSetup::Release()
  1766. {
  1767. if ( m_pOuter )
  1768. return m_pOuter->AddRef();
  1769. else
  1770. return m_DelegationIUnknown.AddRef();
  1771. }
  1772. HRESULT
  1773. CBITSExtensionSetup::LoadTypeInfo()
  1774. {
  1775. if ( m_TypeInfo )
  1776. return S_OK;
  1777. // Lock object
  1778. while( InterlockedExchange( &m_Lock, 1 ) )
  1779. Sleep( 0 );
  1780. HRESULT Hr = ::GetTypeInfo( __uuidof( IBITSExtensionSetup ), &m_TypeInfo );
  1781. // Unlock the object
  1782. InterlockedExchange( &m_Lock, 0 );
  1783. return Hr;
  1784. }
  1785. STDMETHODIMP
  1786. CBITSExtensionSetup::Operate(
  1787. ULONG dwCode,
  1788. VARIANT varData1,
  1789. VARIANT varData2,
  1790. VARIANT varData3)
  1791. {
  1792. return E_NOTIMPL;
  1793. }
  1794. STDMETHODIMP
  1795. CBITSExtensionSetup::PrivateGetIDsOfNames(
  1796. REFIID,
  1797. OLECHAR FAR* FAR* rgszNames,
  1798. unsigned int cNames,
  1799. LCID,
  1800. DISPID FAR* rgDispId )
  1801. {
  1802. HRESULT Hr;
  1803. Hr = LoadTypeInfo();
  1804. if ( FAILED( Hr ) )
  1805. return Hr;
  1806. return DispGetIDsOfNames( m_TypeInfo, rgszNames, cNames, rgDispId);
  1807. }
  1808. STDMETHODIMP
  1809. CBITSExtensionSetup::PrivateGetTypeInfo(
  1810. unsigned int iTInfo,
  1811. LCID lcid,
  1812. ITypeInfo FAR* FAR* ppTInfo )
  1813. {
  1814. *ppTInfo = NULL;
  1815. if(iTInfo != 0)
  1816. return ResultFromScode(DISP_E_BADINDEX);
  1817. HRESULT Hr;
  1818. Hr = LoadTypeInfo();
  1819. if ( FAILED( Hr ) )
  1820. return Hr;
  1821. m_TypeInfo->AddRef();
  1822. *ppTInfo = m_TypeInfo;
  1823. return NOERROR;
  1824. }
  1825. STDMETHODIMP
  1826. CBITSExtensionSetup::PrivateGetTypeInfoCount(
  1827. unsigned int FAR* pctinfo )
  1828. {
  1829. *pctinfo = 1;
  1830. return NOERROR;
  1831. }
  1832. STDMETHODIMP
  1833. CBITSExtensionSetup::PrivateInvoke(
  1834. DISPID dispIdMember,
  1835. REFIID,
  1836. LCID,
  1837. WORD wFlags,
  1838. DISPPARAMS FAR* pDispParams,
  1839. VARIANT FAR* pVarResult,
  1840. EXCEPINFO FAR* pExcepInfo,
  1841. unsigned int FAR* puArgErr )
  1842. {
  1843. HRESULT Hr;
  1844. Hr = LoadTypeInfo();
  1845. if ( FAILED( Hr ) )
  1846. return Hr;
  1847. return
  1848. DispInvoke(
  1849. static_cast<IBITSExtensionSetup*>(this),
  1850. m_TypeInfo,
  1851. dispIdMember,
  1852. wFlags,
  1853. pDispParams,
  1854. pVarResult,
  1855. pExcepInfo,
  1856. puArgErr);
  1857. }
  1858. STDMETHODIMP
  1859. CBITSExtensionSetup::GetIDsOfNames(
  1860. REFIID riid,
  1861. OLECHAR FAR* FAR* rgszNames,
  1862. unsigned int cNames,
  1863. LCID lcid,
  1864. DISPID FAR* rgDispId )
  1865. {
  1866. if ( m_OuterDispatch )
  1867. return m_OuterDispatch->GetIDsOfNames(
  1868. riid,
  1869. rgszNames,
  1870. cNames,
  1871. lcid,
  1872. rgDispId );
  1873. return PrivateGetIDsOfNames(
  1874. riid,
  1875. rgszNames,
  1876. cNames,
  1877. lcid,
  1878. rgDispId );
  1879. }
  1880. STDMETHODIMP
  1881. CBITSExtensionSetup::GetTypeInfo(
  1882. unsigned int iTInfo,
  1883. LCID lcid,
  1884. ITypeInfo FAR* FAR* ppTInfo )
  1885. {
  1886. if ( m_OuterDispatch )
  1887. return m_OuterDispatch->GetTypeInfo(
  1888. iTInfo,
  1889. lcid,
  1890. ppTInfo );
  1891. return
  1892. PrivateGetTypeInfo(
  1893. iTInfo,
  1894. lcid,
  1895. ppTInfo );
  1896. }
  1897. STDMETHODIMP
  1898. CBITSExtensionSetup::GetTypeInfoCount(
  1899. unsigned int FAR* pctinfo )
  1900. {
  1901. if ( m_OuterDispatch )
  1902. return m_OuterDispatch->GetTypeInfoCount( pctinfo );
  1903. return PrivateGetTypeInfoCount( pctinfo );
  1904. }
  1905. STDMETHODIMP
  1906. CBITSExtensionSetup::Invoke(
  1907. DISPID dispIdMember,
  1908. REFIID riid,
  1909. LCID lcid,
  1910. WORD wFlags,
  1911. DISPPARAMS FAR* pDispParams,
  1912. VARIANT FAR* pVarResult,
  1913. EXCEPINFO FAR* pExcepInfo,
  1914. unsigned int FAR* puArgErr )
  1915. {
  1916. if ( m_OuterDispatch )
  1917. return m_OuterDispatch->Invoke(
  1918. dispIdMember,
  1919. riid,
  1920. lcid,
  1921. wFlags,
  1922. pDispParams,
  1923. pVarResult,
  1924. pExcepInfo,
  1925. puArgErr );
  1926. return
  1927. PrivateInvoke(
  1928. dispIdMember,
  1929. riid,
  1930. lcid,
  1931. wFlags,
  1932. pDispParams,
  1933. pVarResult,
  1934. pExcepInfo,
  1935. puArgErr );
  1936. }
  1937. HRESULT
  1938. CBITSExtensionSetup::ConnectToRemoteExtension()
  1939. {
  1940. WCHAR *HostName = NULL;
  1941. WCHAR *NewPath = NULL;
  1942. BSTR NewPathBSTR = NULL;
  1943. IBITSExtensionSetupFactory* Factory = NULL;
  1944. try
  1945. {
  1946. // Extract out the host part of the path
  1947. const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1;
  1948. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 )
  1949. throw ComError( E_INVALIDARG );
  1950. WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize;
  1951. WCHAR *p = HostNameStart;
  1952. while( L'/' != *p )
  1953. {
  1954. if ( L'\0' == *p )
  1955. throw ComError( E_INVALIDARG );
  1956. p++;
  1957. }
  1958. SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0');
  1959. HostName = new WCHAR[ HostNameSize / sizeof(WCHAR) ];
  1960. memcpy( HostName, HostNameStart, HostNameSize - sizeof(WCHAR) );
  1961. HostName[ ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ] = L'\0';
  1962. if ( L'\0' == *++p )
  1963. throw ComError( E_INVALIDARG );
  1964. SIZE_T NewPathSize = wcslen( L"IIS://LocalHost/" ) + wcslen( p ) + 1;
  1965. NewPath = new WCHAR[ NewPathSize ];
  1966. StringCchCopyW( NewPath, NewPathSize, L"IIS://LocalHost/" );
  1967. StringCchCatW( NewPath, NewPathSize, p );
  1968. NewPathBSTR = SysAllocString( NewPath );
  1969. if ( !NewPathBSTR )
  1970. throw ComError( E_OUTOFMEMORY );
  1971. COSERVERINFO coinfo;
  1972. coinfo.dwReserved1 = 0;
  1973. coinfo.dwReserved2 = 0;
  1974. coinfo.pAuthInfo = NULL;
  1975. coinfo.pwszName = HostName;
  1976. GUID guid = __uuidof( IBITSExtensionSetupFactory );
  1977. MULTI_QI mqi;
  1978. mqi.hr = S_OK;
  1979. mqi.pIID = &guid;
  1980. mqi.pItf = NULL;
  1981. THROW_COMERROR(
  1982. CoCreateInstanceEx(
  1983. __uuidof(BITSExtensionSetupFactory),
  1984. NULL,
  1985. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
  1986. &coinfo,
  1987. 1,
  1988. &mqi ) );
  1989. THROW_COMERROR( mqi.hr );
  1990. Factory = (IBITSExtensionSetupFactory*)mqi.pItf;
  1991. mqi.pItf = NULL;
  1992. THROW_COMERROR( Factory->GetObject( NewPathBSTR, &m_RemoteInterface ) );
  1993. Factory->Release();
  1994. SysFreeString( NewPathBSTR );
  1995. delete[] NewPath;
  1996. delete[] HostName;
  1997. return S_OK;
  1998. }
  1999. catch( ComError Error )
  2000. {
  2001. SysFreeString( NewPathBSTR );
  2002. delete[] HostName;
  2003. delete[] NewPath;
  2004. if ( Factory )
  2005. Factory->Release();
  2006. return Error.m_Hr;
  2007. }
  2008. }
  2009. HRESULT CBITSExtensionSetup::LoadPath()
  2010. {
  2011. if ( m_InitComplete )
  2012. return S_OK;
  2013. // Lock object
  2014. while( InterlockedExchange( &m_Lock, 1 ) )
  2015. Sleep( 0 );
  2016. try
  2017. {
  2018. if ( !m_PropertyMan )
  2019. {
  2020. m_PropertyMan = new PropertyIDManager();
  2021. HRESULT Hr = m_PropertyMan->LoadPropertyInfo();
  2022. if ( FAILED(Hr) )
  2023. {
  2024. delete m_PropertyMan;
  2025. m_PropertyMan = NULL;
  2026. throw ComError( Hr );
  2027. }
  2028. }
  2029. if ( !m_ADSIPath )
  2030. {
  2031. SmartIADsPointer ObjectADS;
  2032. if ( m_pObject )
  2033. THROW_COMERROR(
  2034. m_pObject->QueryInterface( __uuidof(*ObjectADS),
  2035. (void**) ObjectADS.GetRecvPointer() ) );
  2036. else
  2037. THROW_COMERROR(
  2038. m_pOuter->QueryInterface( __uuidof(*ObjectADS),
  2039. (void**) ObjectADS.GetRecvPointer() ) );
  2040. THROW_COMERROR( ObjectADS->get_ADsPath( &m_ADSIPath ) );
  2041. }
  2042. if ( !m_Path && !m_RemoteInterface )
  2043. {
  2044. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://LocalHost/", wcslen( L"IIS://LocalHost/" ) ) == 0 )
  2045. {
  2046. SIZE_T PathSize = wcslen( (WCHAR*)m_ADSIPath ) + 1;
  2047. m_Path = new WCHAR[ PathSize ];
  2048. StringCchCopyW( m_Path, PathSize, L"/LM/" );
  2049. StringCchCatW( m_Path, PathSize, reinterpret_cast<WCHAR*>( m_ADSIPath ) + wcslen( L"IIS://LocalHost/" ) );
  2050. }
  2051. else
  2052. {
  2053. THROW_COMERROR( ConnectToRemoteExtension( ) );
  2054. }
  2055. }
  2056. m_InitComplete = true;
  2057. // unlock
  2058. InterlockedExchange( &m_Lock, 0 );
  2059. return S_OK;
  2060. }
  2061. catch( ComError Error )
  2062. {
  2063. InterlockedExchange( &m_Lock, 0 );
  2064. return Error.m_Hr;
  2065. }
  2066. }
  2067. STDMETHODIMP CBITSExtensionSetup::EnableBITSUploads()
  2068. {
  2069. try
  2070. {
  2071. THROW_COMERROR( LoadPath() );
  2072. if ( m_RemoteInterface )
  2073. return m_RemoteInterface->EnableBITSUploads();
  2074. SmartIMSAdminBasePointer AdminBase;
  2075. THROW_COMERROR(
  2076. CoCreateInstance(
  2077. GETAdminBaseCLSID(TRUE),
  2078. NULL,
  2079. CLSCTX_SERVER,
  2080. AdminBase.GetUUID(),
  2081. (LPVOID*)AdminBase.GetRecvPointer() ) );
  2082. EnableBITSForVDIR( m_PropertyMan, AdminBase, m_Path );
  2083. return S_OK;
  2084. }
  2085. catch( ComError Error )
  2086. {
  2087. return Error.m_Hr;
  2088. }
  2089. }
  2090. STDMETHODIMP CBITSExtensionSetup::DisableBITSUploads()
  2091. {
  2092. try
  2093. {
  2094. THROW_COMERROR( LoadPath() );
  2095. if ( m_RemoteInterface )
  2096. return m_RemoteInterface->DisableBITSUploads();
  2097. SmartIMSAdminBasePointer AdminBase;
  2098. THROW_COMERROR(
  2099. CoCreateInstance(
  2100. GETAdminBaseCLSID(TRUE),
  2101. NULL,
  2102. CLSCTX_SERVER,
  2103. AdminBase.GetUUID(),
  2104. (LPVOID*)AdminBase.GetRecvPointer() ) );
  2105. DisableBITSForVDIR( m_PropertyMan, AdminBase, m_Path, false, false );
  2106. return S_OK;
  2107. }
  2108. catch( ComError Error )
  2109. {
  2110. return Error.m_Hr;
  2111. }
  2112. }
  2113. STDMETHODIMP
  2114. CBITSExtensionSetup::GetCleanupTaskName( BSTR *pTaskName )
  2115. {
  2116. LPWSTR TaskName = NULL;
  2117. try
  2118. {
  2119. *pTaskName = NULL;
  2120. THROW_COMERROR( LoadPath() );
  2121. if ( m_RemoteInterface )
  2122. return m_RemoteInterface->GetCleanupTaskName( pTaskName );
  2123. SmartIMSAdminBasePointer AdminBase;
  2124. THROW_COMERROR(
  2125. CoCreateInstance(
  2126. GETAdminBaseCLSID(TRUE),
  2127. NULL,
  2128. CLSCTX_SERVER,
  2129. AdminBase.GetUUID(),
  2130. (LPVOID*)AdminBase.GetRecvPointer() ) );
  2131. FindWorkItemForVDIR( m_PropertyMan, AdminBase, m_Path, &TaskName );
  2132. if ( TaskName )
  2133. {
  2134. *pTaskName = SysAllocString( TaskName );
  2135. if ( !*pTaskName )
  2136. throw ComError( E_OUTOFMEMORY );
  2137. CoTaskMemFree( TaskName );
  2138. TaskName = NULL;
  2139. }
  2140. return S_OK;
  2141. }
  2142. catch( ComError Error )
  2143. {
  2144. CoTaskMemFree( TaskName );
  2145. return Error.m_Hr;
  2146. }
  2147. }
  2148. STDMETHODIMP
  2149. CBITSExtensionSetup::GetCleanupTask(
  2150. [in] REFIID riid,
  2151. [out,retval] IUnknown **ppUnk )
  2152. {
  2153. HRESULT Hr = S_OK;
  2154. SmartITaskSchedulerPointer TaskScheduler;
  2155. BSTR ItemName = NULL;
  2156. WCHAR *HostName = NULL;
  2157. if ( ppUnk )
  2158. *ppUnk = NULL;
  2159. try
  2160. {
  2161. THROW_COMERROR( LoadPath() );
  2162. //
  2163. // Build the taskscheduler form of the host name
  2164. //
  2165. const SIZE_T PrefixSize = sizeof(L"IIS://")/sizeof(WCHAR) - 1;
  2166. if ( _wcsnicmp( (WCHAR*)m_ADSIPath, L"IIS://", PrefixSize ) != 0 )
  2167. throw ComError( E_INVALIDARG );
  2168. WCHAR *HostNameStart = ((WCHAR*)m_ADSIPath) + PrefixSize;
  2169. WCHAR *p = HostNameStart;
  2170. while( L'/' != *p )
  2171. {
  2172. if ( L'\0' == *p )
  2173. throw ComError( E_INVALIDARG );
  2174. p++;
  2175. }
  2176. SIZE_T HostNameSize = (char*)p - (char*)HostNameStart + sizeof(L'\0');
  2177. HostName = new WCHAR[ ( HostNameSize / sizeof(WCHAR) ) + 2 ];
  2178. HostName[0] = HostName[1] = L'\\';
  2179. memcpy( HostName + 2, HostNameStart, HostNameSize - sizeof(WCHAR) );
  2180. HostName[ ( ( HostNameSize - sizeof(WCHAR) ) / sizeof(WCHAR) ) + 2 ] = L'\0';
  2181. if ( _wcsicmp( HostName, L"\\\\LocalHost" ) == 0 )
  2182. {
  2183. delete[] HostName;
  2184. HostName = NULL;
  2185. }
  2186. ConnectToTaskScheduler( HostName, &TaskScheduler );
  2187. THROW_COMERROR( GetCleanupTaskName( &ItemName ) );
  2188. if ( ItemName )
  2189. THROW_COMERROR( TaskScheduler->Activate( (LPCWSTR)ItemName, riid, ppUnk ) );
  2190. else
  2191. Hr = S_FALSE;
  2192. }
  2193. catch( ComError Error )
  2194. {
  2195. Hr = Error.m_Hr;
  2196. }
  2197. SysFreeString( ItemName );
  2198. delete[] HostName;
  2199. return Hr;
  2200. }
  2201. #include "bitssrvcfgimp.h"