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.

776 lines
21 KiB

  1. #include <pch.cxx>
  2. #pragma hdrstop
  3. #define TRKDATA_ALLOCATE
  4. #include "trkcom.hxx"
  5. #include "trklib.hxx"
  6. #if !defined(_UNICODE) || defined(OLE2ANSI)
  7. #error This ILinkTrack implementation is only compatible on a Unicode build
  8. #endif
  9. //+----------------------------------------------------------------------------
  10. //
  11. // Method: CTrackFile/~CTrackFile
  12. //
  13. // Synopsis: Construction/Destruction
  14. //
  15. // Arguments: None
  16. //
  17. // Returns: None
  18. //
  19. //+----------------------------------------------------------------------------
  20. CTrackFile::CTrackFile()
  21. {
  22. _cRefs = 0;
  23. _fDirty = FALSE;
  24. _fLoaded = FALSE;
  25. memset( &_PersistentState, 0, sizeof(_PersistentState) );
  26. }
  27. CTrackFile::~CTrackFile()
  28. {
  29. }
  30. //+----------------------------------------------------------------------------
  31. //
  32. // Method: IUnknown methods
  33. //
  34. // Synopsis: IUnknown
  35. //
  36. //+----------------------------------------------------------------------------
  37. ULONG
  38. CTrackFile::AddRef()
  39. {
  40. long cNew;
  41. cNew = InterlockedIncrement( &_cRefs );
  42. return( cNew );
  43. }
  44. ULONG
  45. CTrackFile::Release()
  46. {
  47. long cNew;
  48. cNew = InterlockedDecrement( &_cRefs );
  49. if( 0 == cNew )
  50. delete this;
  51. return( cNew >= 0 ? cNew : 0 );
  52. }
  53. HRESULT
  54. CTrackFile::QueryInterface( REFIID iid, void ** ppvObject )
  55. {
  56. HRESULT hr = E_NOINTERFACE;
  57. // Parameter validation
  58. if( NULL == ppvObject )
  59. {
  60. hr = E_INVALIDARG;
  61. goto Exit;
  62. }
  63. *ppvObject = NULL;
  64. if( IID_IUnknown == iid
  65. ||
  66. IID_ITrackFile == iid )
  67. {
  68. AddRef();
  69. *ppvObject = (void*) (IUnknown*) (ITrackFile*) this;
  70. hr = S_OK;
  71. }
  72. else if( IID_ITrackFileRestricted == iid )
  73. {
  74. AddRef();
  75. *ppvObject = (void*) (ITrackFileRestricted*) this;
  76. hr = S_OK;
  77. }
  78. else if( IID_IPersistMemory == iid )
  79. {
  80. AddRef();
  81. *ppvObject = (void*) (IPersistMemory*) this;
  82. hr = S_OK;
  83. }
  84. else if( IID_IPersistStreamInit == iid )
  85. {
  86. AddRef();
  87. *ppvObject = (void*) (IPersistStreamInit*) this;
  88. hr = S_OK;
  89. }
  90. Exit:
  91. return( hr );
  92. }
  93. //+----------------------------------------------------------------------------
  94. //
  95. // Method: CreateFromPath (ITrack*)
  96. //
  97. // Synopsis: Create a link client for a link source file.
  98. //
  99. // Arguments: [poszPath] (in)
  100. // The file to which to link.
  101. //
  102. // Returns: HRESULT
  103. //
  104. //+----------------------------------------------------------------------------
  105. HRESULT
  106. CTrackFile::CreateFromPath( const OLECHAR * poszPath )
  107. {
  108. HRESULT hr = S_OK;
  109. NTSTATUS status = STATUS_SUCCESS;
  110. CDomainRelativeObjId droidCurrent, droidBirth;
  111. // Parameter validation
  112. if( NULL == poszPath )
  113. {
  114. hr = E_INVALIDARG;
  115. goto Exit;
  116. }
  117. __try
  118. {
  119. status = GetDroids( poszPath, &droidCurrent, &droidBirth, RGO_GET_OBJECTID );
  120. if( !NT_SUCCESS(status) )
  121. {
  122. hr = HRESULT_FROM_NT(status);
  123. goto Exit;
  124. }
  125. }
  126. __except( BreakOnDebuggableException() )
  127. {
  128. hr = GetExceptionCode();
  129. }
  130. if( FAILED(hr) ) goto Exit;
  131. _fLoaded = FALSE;
  132. InitNew();
  133. _fDirty = TRUE;
  134. _PersistentState.droidCurrent = droidCurrent;
  135. _PersistentState.droidBirth = droidBirth;
  136. Exit:
  137. if( SUCCEEDED(hr) )
  138. TrkLog(( TRKDBG_CREATE, TEXT("Link created to %s"), poszPath ));
  139. hr = MapTR2HR( hr );
  140. return( hr );
  141. }
  142. //+----------------------------------------------------------------------------
  143. //
  144. // Method: Resolve (ITrack*)
  145. //
  146. // Synopsis: Determine the current path of a link source.
  147. //
  148. // Arguments: [pcbPath] (in/out)
  149. // In: The size of the poszPath buffer
  150. // Out: The actual path length (including the null terminator)
  151. // [poszPath] (out)
  152. // The link source's current path.
  153. // [dwMillisecondTimeout] (in)
  154. // A suggestion as to when this method should give up
  155. // and return if it hasn't yet found the file.
  156. //
  157. // Returns: HRESULT
  158. //
  159. //+----------------------------------------------------------------------------
  160. // BUGBUG P1: Optionally return the GetFileAttributesEx info, so that the
  161. // shell doesn't have to re-open the file.
  162. HRESULT
  163. CTrackFile::Resolve( DWORD *pcbPath, OLECHAR * poszPath, DWORD dwMillisecondTimeout )
  164. {
  165. return( Resolve( pcbPath, poszPath, dwMillisecondTimeout, TRK_MEND_DEFAULT ));
  166. }
  167. HRESULT
  168. CTrackFile::Resolve( DWORD *pcbPath, OLECHAR * poszPath, DWORD dwMillisecondTimeout,
  169. DWORD Restrictions )
  170. {
  171. HRESULT hr = E_FAIL;
  172. CMachineId mcidLocal( MCID_LOCAL );
  173. CRpcClientBinding rc;
  174. CDomainRelativeObjId droidNew;
  175. CDomainRelativeObjId droidBirth;
  176. CDomainRelativeObjId droidCurrent;
  177. OLECHAR oszPathActual[ MAX_PATH + 1 ];
  178. DWORD cbPathActual = 0;
  179. CFILETIME cftDue;
  180. // Parameter validation
  181. if( NULL == pcbPath
  182. ||
  183. NULL == poszPath )
  184. {
  185. hr = E_INVALIDARG;
  186. goto Exit;
  187. }
  188. else if( !_fLoaded )
  189. {
  190. hr = E_UNEXPECTED;
  191. goto Exit;
  192. }
  193. __try
  194. {
  195. cftDue.IncrementMilliseconds( dwMillisecondTimeout );
  196. droidBirth = _PersistentState.droidBirth;
  197. droidCurrent = _PersistentState.droidCurrent;
  198. rc.RcInitialize( mcidLocal, s_tszTrkWksLocalRpcProtocol, s_tszTrkWksLocalRpcEndPoint );
  199. RpcTryExcept
  200. {
  201. CMachineId mcidLast, mcidCurrent;
  202. ULONG cbFileName = (MAX_PATH + 1) * sizeof(TCHAR);
  203. CDomainRelativeObjId droidBirthNew;
  204. hr = LnkMendLink( rc,
  205. cftDue,
  206. Restrictions,
  207. &droidBirth,
  208. &droidCurrent,
  209. &mcidLast,
  210. &droidBirthNew,
  211. &droidNew,
  212. &mcidCurrent,
  213. &cbFileName,
  214. oszPathActual );
  215. }
  216. RpcExcept( BreakOnDebuggableException() )
  217. {
  218. hr = HRESULT_FROM_WIN32( RpcExceptionCode() );
  219. }
  220. RpcEndExcept;
  221. if( FAILED(hr) ) goto Exit;
  222. // Compare droidBirth and droidCurrent with the ones in _PersistentState.
  223. // If the same, do not set _fDirty.
  224. if(droidBirth != _PersistentState.droidBirth)
  225. {
  226. _PersistentState.droidBirth = droidBirth;
  227. _fDirty = TRUE;
  228. }
  229. if(droidNew != _PersistentState.droidCurrent)
  230. {
  231. _PersistentState.droidCurrent = droidNew;
  232. _fDirty = TRUE;
  233. }
  234. cbPathActual = ( ocslen(oszPathActual) + 1 ) * sizeof(OLECHAR);
  235. if( cbPathActual > *pcbPath )
  236. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  237. else
  238. ocscpy( poszPath, oszPathActual );
  239. *pcbPath = cbPathActual;
  240. if( FAILED(hr) ) goto Exit;
  241. }
  242. __except( EXCEPTION_EXECUTE_HANDLER )
  243. {
  244. hr = GetExceptionCode();
  245. goto Exit;
  246. }
  247. Exit:
  248. return( hr );
  249. }
  250. //+----------------------------------------------------------------------------
  251. //
  252. // Method: Open (ITrackFile)
  253. //
  254. // Synopsis: Open the referent file ensure that its object ID is
  255. // correct. If the object ID is not correct, or the
  256. // file could not be found, then perform a Resolve.
  257. //
  258. // Arguments: [pcbPathHint] (in/out)
  259. // In: The size of the poszPathHint buffer
  260. // Out: The actual path length (including the null terminator)
  261. // [poszPathHint] (in/out)
  262. // The suggested path to the file. If the path turns out not
  263. // to be correct, an updated path is returned.
  264. // [dwMillisecondTimeout] (in)
  265. // A suggestion as to when this method should give up
  266. // and return if it hasn't yet found the file.
  267. // [dwDesiredAccess] (in)
  268. // Access mode for the open file (see Win32 CreateFile)
  269. // [dwShareMode] (in)
  270. // Sharing for the open file (see Win32 CreateFile)
  271. // [dwFlags] (in)
  272. // Specifies the flags for the file (see the FILE_FLAG_*
  273. // values in the Win32 CreateFile).
  274. // [phFile] (out)
  275. // The open file handle. It is because of this parameter
  276. // That the ITrackFile interface is [local].
  277. //
  278. // Returns: HRESULT
  279. //
  280. //+----------------------------------------------------------------------------
  281. STDMETHODIMP CTrackFile::Open( /*in, out*/ DWORD * pcbPathHint,
  282. /*in, out, size_is(*pcbPathHint), string*/ OLECHAR * poszPathHint,
  283. /*in*/ DWORD dwMillisecondTimeout,
  284. /*in*/ DWORD dwDesiredAccess, // access (read-write) mode
  285. /*in*/ DWORD dwShareMode, // share mode
  286. /*in*/ DWORD dwFlags,
  287. /*out*/ HANDLE * phFile )
  288. {
  289. return E_NOTIMPL;
  290. /*
  291. HRESULT hr = S_OK;
  292. BOOL fTimeout = TRUE;
  293. NTSTATUS status = STATUS_SUCCESS;
  294. HANDLE hFile = INVALID_HANDLE_VALUE;
  295. FILE_OBJECTID_BUFFER fobOID;
  296. IO_STATUS_BLOCK Iosb;
  297. CObjId cobjidFile;
  298. DWORD dwTickCountTimeout, dwTickCountNow;
  299. // ----------
  300. // Initialize
  301. // ----------
  302. *phFile = INVALID_HANDLE_VALUE;
  303. // Ensure we have an ObjectID to check against.
  304. if( !_fLoaded )
  305. {
  306. hr = E_UNEXPECTED;
  307. goto Exit;
  308. }
  309. // Calculate the absolute deadline.
  310. dwTickCountNow = GetTickCount();
  311. dwTickCountTimeout = dwTickCountNow + dwMillisecondTimeout;
  312. if( dwTickCountTimeout < dwTickCountNow )
  313. {
  314. // Bad dwMillisecondTimeout value
  315. hr = E_INVALIDARG;
  316. goto Exit;
  317. }
  318. // -------------
  319. // Open the File
  320. // -------------
  321. do
  322. {
  323. // Open the file
  324. hFile = CreateFile( poszPathHint, dwDesiredAccess, dwShareMode, NULL,
  325. OPEN_EXISTING, dwFlags, NULL );
  326. if( INVALID_HANDLE_VALUE == hFile )
  327. {
  328. hr = HRESULT_FROM_WIN32( GetLastError() );
  329. goto Exit;
  330. }
  331. // Get the object ID
  332. status = NtFsControlFile(
  333. hFile,
  334. NULL,
  335. NULL,
  336. NULL,
  337. &Iosb,
  338. FSCTL_GET_OBJECT_ID,
  339. NULL, // In buffer
  340. 0, // In buffer size
  341. &fobOID, // Out buffer
  342. sizeof(fobOID) ); // Out buffer size
  343. if( !NT_SUCCESS(status) )
  344. {
  345. hr = HRESULT_FROM_NT( status );
  346. goto Exit;
  347. }
  348. // Verify the object ID
  349. cobjidFile.Load( fobOID, LINK_TYPE_FILE );
  350. if( cobjidFile == _PersistentState.droidCurrent.GetObjId() )
  351. {
  352. // We found a good file and we're done.
  353. fTimeout = FALSE;
  354. break;
  355. }
  356. else
  357. {
  358. // Try to find the correct file.
  359. hr = Resolve( pcbPathHint, poszPathHint, dwTickCountTimeout - GetTickCount() );
  360. if( FAILED(hr) ) goto Exit;
  361. }
  362. } while( GetTickCount() < dwTickCountTimeout );
  363. // Did the previous loop end because of a timeout?
  364. if( fTimeout )
  365. {
  366. hr = HRESULT_FROM_WIN32( ERROR_TIMEOUT );
  367. goto Exit;
  368. }
  369. // We completed successfully.
  370. *phFile = hFile;
  371. hFile = INVALID_HANDLE_VALUE;
  372. hr = S_OK;
  373. // ----
  374. // Exit
  375. // ----
  376. Exit:
  377. if( INVALID_HANDLE_VALUE != hFile )
  378. CloseHandle( hFile );
  379. return( hr );
  380. */
  381. } // CTrackFile::Open()
  382. //+----------------------------------------------------------------------------
  383. //
  384. // Method: GetClassID (IPersistMemory & IPersistStreamInit)
  385. //
  386. // Returns: HRESULT
  387. //
  388. //+----------------------------------------------------------------------------
  389. STDMETHODIMP
  390. CTrackFile::GetClassID( CLSID *pClassID )
  391. {
  392. if(NULL == pClassID)
  393. {
  394. return E_POINTER;
  395. }
  396. *pClassID = IID_ITrackFile;
  397. return( S_OK );
  398. }
  399. //+----------------------------------------------------------------------------
  400. //
  401. // Method: IsDirty (IPersistMemory & IPersistStreamInit)
  402. //
  403. // Returns: HRESULT
  404. // S_OK => Dirty, S_FALSE => clean
  405. //
  406. //+----------------------------------------------------------------------------
  407. STDMETHODIMP
  408. CTrackFile::IsDirty()
  409. {
  410. return( _fDirty ? S_OK : S_FALSE );
  411. }
  412. //+----------------------------------------------------------------------------
  413. //
  414. // Method: Load (IPersistMemory)
  415. //
  416. // Synopsis: Load the TrackFile object from persistent state.
  417. //
  418. // Arguments: [pvMem]
  419. // Points to the serialization buffer.
  420. // [cbSize]
  421. // Size of the serialization buffer.
  422. //
  423. // Returns: None
  424. //
  425. //+----------------------------------------------------------------------------
  426. STDMETHODIMP
  427. CTrackFile::Load( void * pvMem, ULONG cbSize )
  428. {
  429. LinkTrackPersistentState PersistentState;
  430. if( NULL == pvMem )
  431. return( E_POINTER );
  432. else if( _fLoaded )
  433. return( E_UNEXPECTED );
  434. else if( sizeof(_PersistentState) > cbSize )
  435. return( E_INVALIDARG );
  436. else if( ( (LinkTrackPersistentState*) pvMem )->clsid != IID_ITrackFile )
  437. return( E_INVALIDARG );
  438. else if( ( (LinkTrackPersistentState*) pvMem )->cbSize < sizeof(_PersistentState) )
  439. return( E_INVALIDARG );
  440. else
  441. {
  442. _PersistentState = *(LinkTrackPersistentState*) pvMem;
  443. _fLoaded = TRUE;
  444. return( S_OK );
  445. }
  446. }
  447. //+----------------------------------------------------------------------------
  448. //
  449. // Method: Save(IPersistMemory)
  450. //
  451. // Synopsis: Save the persistent state to a memory buffer.
  452. //
  453. // Arguments: [pvMem]
  454. // The buffer to which we'll save.
  455. // [fClearDirty]
  456. // TRUE => we'll set _fDirty to FALSE on a successful save.
  457. // [cbSize]
  458. // The available buffer in pvMem.
  459. //
  460. // Returns: HRESULT
  461. //
  462. //+----------------------------------------------------------------------------
  463. STDMETHODIMP
  464. CTrackFile::Save( void* pvMem, BOOL fClearDirty, ULONG cbSize )
  465. {
  466. if( NULL == pvMem )
  467. return( E_POINTER );
  468. else if( !_fLoaded )
  469. return( E_UNEXPECTED );
  470. else if( sizeof(_PersistentState) > cbSize )
  471. return( E_INVALIDARG );
  472. else
  473. {
  474. *(LinkTrackPersistentState*) pvMem = _PersistentState;
  475. if( fClearDirty )
  476. _fDirty = FALSE;
  477. return( S_OK );
  478. }
  479. }
  480. //+----------------------------------------------------------------------------
  481. //
  482. // Method: InitNew
  483. //
  484. // Synopsis: Initialize the TrackFile object.
  485. //
  486. // Arguments: None
  487. //
  488. // Returns: None
  489. //
  490. //+----------------------------------------------------------------------------
  491. STDMETHODIMP
  492. CTrackFile::InitNew()
  493. {
  494. if( _fLoaded )
  495. return( E_UNEXPECTED );
  496. else
  497. {
  498. memset( &_PersistentState, 0, sizeof(_PersistentState) );
  499. _PersistentState.cbSize = sizeof(_PersistentState);
  500. _PersistentState.clsid = IID_ITrackFile;
  501. _fLoaded = TRUE;
  502. return( S_OK );
  503. }
  504. }
  505. //+----------------------------------------------------------------------------
  506. //
  507. // Method: GetSizeMax (IPersistMemory)
  508. //
  509. // Synopsis: Returns the size necessary to pass to IPersist:Save
  510. //
  511. // Arguments: [pcbSize]
  512. //
  513. // Returns: HRESULT
  514. //
  515. //+----------------------------------------------------------------------------
  516. STDMETHODIMP
  517. CTrackFile::GetSizeMax( ULONG *pcbSize )
  518. {
  519. if( NULL == pcbSize )
  520. return( E_POINTER );
  521. else
  522. {
  523. *pcbSize = sizeof(_PersistentState);
  524. return( S_OK );
  525. }
  526. }
  527. //+----------------------------------------------------------------------------
  528. //
  529. // Method: GetSizeMax (IPersistStreamInit)
  530. //
  531. // Synopsis: Returns the size necessary.
  532. //
  533. // Arguments: [pcbSize]
  534. //
  535. // Returns: HRESULT
  536. //
  537. //+----------------------------------------------------------------------------
  538. STDMETHODIMP
  539. CTrackFile::GetSizeMax( ULARGE_INTEGER* pcbSize )
  540. {
  541. if( NULL == pcbSize )
  542. return( E_POINTER );
  543. else
  544. {
  545. pcbSize->QuadPart = sizeof(_PersistentState);
  546. return( S_OK );
  547. }
  548. }
  549. //+----------------------------------------------------------------------------
  550. //
  551. // Method: Load (IPersistStreamInit)
  552. //
  553. // Synopsis: Load the TrackFile object from a stream.
  554. //
  555. // Arguments: [pStm]
  556. // Points to the IStream interface.
  557. //
  558. // Returns: HRESULT
  559. //
  560. //+----------------------------------------------------------------------------
  561. STDMETHODIMP
  562. CTrackFile::Load(IStream* pStm)
  563. {
  564. HRESULT hr; // return value
  565. LinkTrackPersistentState PersistentState; // tmp storage
  566. ULONG cbRead; // # of bytes read
  567. LARGE_INTEGER cbOffset; // = -cbRead
  568. ULONG cbSize = sizeof(_PersistentState);
  569. if(NULL == pStm)
  570. return(E_POINTER);
  571. else if(_fLoaded)
  572. return(E_UNEXPECTED);
  573. // Read _PersistentState from the stream and check if the read is
  574. // successful. If not, revert back the seek pointer in pStm, and
  575. // return the HRESULT.
  576. hr = pStm->Read((byte*)&PersistentState, cbSize, &cbRead);
  577. if(FAILED(hr) || cbSize != cbRead)
  578. {
  579. cbOffset.QuadPart = -static_cast<LONGLONG>(cbRead);
  580. goto Exit;
  581. }
  582. // So now we successfully read the _PersistentState into memory, check to
  583. // see if we read garbage. If so, revert and return the error.
  584. // xxx What error message should be returned for this?
  585. if(PersistentState.clsid != IID_ITrackFile)
  586. {
  587. cbOffset.QuadPart = -static_cast<LONGLONG>(cbRead);
  588. hr = E_FAIL;
  589. goto Exit;
  590. }
  591. // Everything went well. Now we can copy _PersistentState from its
  592. // temporary storage to its real storage.
  593. _PersistentState = PersistentState;
  594. _fLoaded = TRUE;
  595. return(S_OK);
  596. Exit:
  597. pStm->Seek(cbOffset, STREAM_SEEK_CUR, NULL);
  598. return(hr);
  599. }
  600. //+----------------------------------------------------------------------------
  601. //
  602. // Method: Save (IPersistStreamInit)
  603. //
  604. // Synopsis: Save the persistent state to a stream.
  605. //
  606. // Arguments: [pStm]
  607. // The IStream interface we use to save.
  608. // [fClearDirty]
  609. // TRUE => we'll set _fDirty to FALSE on a successful save.
  610. //
  611. // Returns: HRESULT
  612. //
  613. //+----------------------------------------------------------------------------
  614. STDMETHODIMP
  615. CTrackFile::Save(IStream* pStm, BOOL fClearDirty)
  616. {
  617. HRESULT hr;
  618. ULONG cbSize = sizeof(_PersistentState);
  619. ULONG cbWritten; // # of bytes written
  620. LARGE_INTEGER cbOffset; // same as cbWritten
  621. if(NULL == pStm)
  622. return(E_POINTER);
  623. else if( !_fLoaded )
  624. return(E_UNEXPECTED);
  625. else
  626. {
  627. // Write the _PersistentState to the stream and check the return value.
  628. // If failed, revert the changes in IStream and return the HRESULT.
  629. hr = pStm->Write((byte*)&_PersistentState, cbSize, &cbWritten);
  630. if(FAILED(hr))
  631. {
  632. cbOffset.QuadPart = -static_cast<LONGLONG>(cbWritten);
  633. pStm->Seek(cbOffset, STREAM_SEEK_CUR, NULL);
  634. return hr;
  635. }
  636. if(fClearDirty)
  637. _fDirty = FALSE;
  638. return(S_OK);
  639. }
  640. }