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.

734 lines
19 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1992.
  5. //
  6. // File: filest.cxx
  7. //
  8. // Contents: Generic 16/32 filestream code
  9. //
  10. // History: 20-Nov-91 DrewB Created
  11. //
  12. //---------------------------------------------------------------
  13. #include <exphead.cxx>
  14. #pragma hdrstop
  15. #include <marshl.hxx>
  16. //+---------------------------------------------------------------------------
  17. //
  18. // Member: CFileStream::CFileStream, public
  19. //
  20. // Synopsis: Empty object constructor
  21. //
  22. // History: 26-Oct-92 DrewB Created
  23. //
  24. //----------------------------------------------------------------------------
  25. CFileStream::CFileStream(IMalloc * const pMalloc)
  26. : _pMalloc(pMalloc)
  27. {
  28. _cReferences = 1;
  29. _hFile = INVALID_FH;
  30. _hReserved = INVALID_FH;
  31. _hPreDuped = INVALID_FH;
  32. _pgfst = NULL;
  33. _grfLocal = 0;
  34. _sig = CFILESTREAM_SIG;
  35. #ifdef USE_FILEMAPPING
  36. _hMapObject = NULL;
  37. _pbBaseAddr = NULL;
  38. _cbViewSize = 0;
  39. #endif
  40. #ifdef ASYNC
  41. _ppc = NULL;
  42. #endif
  43. }
  44. //+--------------------------------------------------------------
  45. //
  46. // Member: CFileStream::InitGlobal, public
  47. //
  48. // Synopsis: Constructor for flags only
  49. //
  50. // Arguments: [dwStartFlags] - Startup flags
  51. // [df] - Permissions
  52. //
  53. // History: 08-Apr-92 DrewB Created
  54. //
  55. //---------------------------------------------------------------
  56. SCODE CFileStream::InitGlobal(DWORD dwStartFlags,
  57. DFLAGS df)
  58. {
  59. SCODE sc = S_OK;
  60. CGlobalFileStream *pgfstTemp;
  61. fsAssert(_pgfst == NULL);
  62. fsMem(pgfstTemp = new (_pMalloc) CGlobalFileStream(_pMalloc,
  63. NULL, df, dwStartFlags));
  64. _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfstTemp);
  65. _pgfst->Add(this);
  66. // Fall through
  67. EH_Err:
  68. return sc;
  69. }
  70. //+---------------------------------------------------------------------------
  71. //
  72. // Member: CFileStream::InitFromGlobal, public
  73. //
  74. // Synopsis: Initializes a filestream with a global filestream
  75. //
  76. // Arguments: [pgfst] - Global object
  77. //
  78. // History: 26-Oct-92 DrewB Created
  79. //
  80. //----------------------------------------------------------------------------
  81. void CFileStream::InitFromGlobal(CGlobalFileStream *pgfst)
  82. {
  83. _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfst);
  84. _pgfst->AddRef();
  85. _pgfst->Add(this);
  86. }
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Member: CFileStream::InitFromFileStream public
  90. //
  91. // Synopsis: Initializes a filestream with another CFileStream
  92. //
  93. // Arguments: [pfst] - Global object
  94. //
  95. // History: 24-Sep-1998 HenryLee Created
  96. //
  97. //----------------------------------------------------------------------------
  98. void CFileStream::InitFromFileStream (CFileStream *pfst)
  99. {
  100. _hFile = pfst->_hFile;
  101. _hMapObject = pfst->_hMapObject;
  102. _pbBaseAddr = pfst->_pbBaseAddr;
  103. _cbViewSize = pfst->_cbViewSize;
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Member: CGlobalFileStream::InitFromGlobalFileStream public
  108. //
  109. // Synopsis: Initializes a global filestream from another global filestream
  110. //
  111. // Arguments: [pgfs] - Global object
  112. //
  113. // History: 24-Sep-1998 HenryLee Created
  114. //
  115. //----------------------------------------------------------------------------
  116. void CGlobalFileStream::InitFromGlobalFileStream (CGlobalFileStream *pgfs)
  117. {
  118. #ifdef LARGE_DOCFILE
  119. _ulPos = pgfs->_ulPos;
  120. #else
  121. _ulLowPos = pgfs->_ulLowPos;
  122. #endif
  123. _cbMappedFileSize = pgfs->_cbMappedFileSize;
  124. _cbMappedCommitSize = pgfs->_cbMappedCommitSize;
  125. _dwMapFlags = pgfs->_dwMapFlags;
  126. lstrcpy (_awcMapName, pgfs->_awcMapName);
  127. lstrcpy (_awcPath, pgfs->_awcPath);
  128. #ifdef ASYNC
  129. _dwTerminate = pgfs->_dwTerminate;
  130. _ulHighWater = pgfs->_ulHighWater;
  131. _ulFailurePoint = pgfs->_ulFailurePoint;
  132. #endif // ASYNC
  133. #if DBG == 1
  134. _ulLastFilePos = pgfs->_ulLastFilePos;
  135. #endif
  136. _cbSector = pgfs->_cbSector;
  137. }
  138. //+--------------------------------------------------------------
  139. //
  140. // Member: CFileStream::vRelease, public
  141. //
  142. // Synopsis: PubList support
  143. //
  144. // History: 19-Aug-92 DrewB Created
  145. //
  146. //---------------------------------------------------------------
  147. ULONG CFileStream::vRelease(void)
  148. {
  149. LONG lRet;
  150. filestDebug((DEB_ITRACE, "In CFileStream::vRelease:%p()\n", this));
  151. fsAssert(_cReferences > 0);
  152. lRet = InterlockedDecrement(&_cReferences);
  153. if (lRet == 0)
  154. {
  155. #ifdef ASYNC
  156. if (_ppc != NULL)
  157. {
  158. #ifdef MULTIHEAP
  159. CSafeMultiHeap smh(_ppc);
  160. #endif
  161. SCODE sc;
  162. sc = TakeSem();
  163. fsAssert(SUCCEEDED(sc));
  164. CPerContext *ppc = _ppc;
  165. _ppc = NULL;
  166. delete this;
  167. if (ppc->ReleaseSharedMem() == 0)
  168. {
  169. #ifdef MULTIHEAP
  170. g_smAllocator.Uninit();
  171. #endif
  172. }
  173. }
  174. else
  175. #endif
  176. delete this;
  177. }
  178. return (ULONG)lRet;
  179. filestDebug((DEB_ITRACE, "Out CFileStream::vRelease => %d\n",lRet));
  180. }
  181. //+--------------------------------------------------------------
  182. //
  183. // Member: CFileStream::Release, public
  184. //
  185. // Synopsis: Releases resources for an LStream
  186. //
  187. // Returns: Appropriate status code
  188. //
  189. // History: 20-Feb-92 DrewB Created
  190. //
  191. //---------------------------------------------------------------
  192. STDMETHODIMP_(ULONG) CFileStream::Release(void)
  193. {
  194. ULONG ulRet;
  195. filestDebug((DEB_ITRACE, "In CFileStream::Release()\n"));
  196. fsAssert(_cReferences >= 1);
  197. ulRet = CFileStream::vRelease();
  198. filestDebug((DEB_ITRACE, "Out CFileStream::Release\n"));
  199. return ulRet;
  200. }
  201. //+--------------------------------------------------------------
  202. //
  203. // Member: CFileStream::AddRef, public
  204. //
  205. // Synopsis: Increases the ref count
  206. //
  207. // History: 27-Feb-92 DrewB Created
  208. //
  209. //---------------------------------------------------------------
  210. STDMETHODIMP_(ULONG) CFileStream::AddRef(void)
  211. {
  212. ULONG ulRet;
  213. filestDebug((DEB_ITRACE, "In CFileStream::AddRef()\n"));
  214. CFileStream::vAddRef();
  215. ulRet = _cReferences;
  216. filestDebug((DEB_ITRACE, "Out CFileStream::AddRef, %ld\n", _cReferences));
  217. return ulRet;
  218. }
  219. //+--------------------------------------------------------------
  220. //
  221. // Member: CFileStream::GetName, public
  222. //
  223. // Synopsis: Returns the internal path
  224. //
  225. // Arguments: [ppwcsName] - Name pointer return
  226. //
  227. // Returns: Appropriate status code
  228. //
  229. // Modifies: [ppwcsName]
  230. //
  231. // History: 24-Mar-92 DrewB Created
  232. //
  233. //---------------------------------------------------------------
  234. SCODE CFileStream::GetName(WCHAR **ppwcsName)
  235. {
  236. SCODE sc;
  237. filestDebug((DEB_ITRACE, "In CFileStream::GetName(%p)\n",
  238. ppwcsName));
  239. fsAssert(_pgfst->HasName());
  240. fsChk(DfAllocWC(lstrlenW(_pgfst->GetName())+1, ppwcsName));
  241. lstrcpyW(*ppwcsName, _pgfst->GetName());
  242. filestDebug((DEB_ITRACE, "Out CFileStream::GetName => %ws\n",
  243. *ppwcsName));
  244. EH_Err:
  245. return sc;
  246. }
  247. //+--------------------------------------------------------------
  248. //
  249. // Member: CFileStream::QueryInterface, public
  250. //
  251. // Synopsis: Returns an object for the requested interface
  252. //
  253. // Arguments: [iid] - Interface ID
  254. // [ppvObj] - Object return
  255. //
  256. // Returns: Appropriate status code
  257. //
  258. // Modifies: [ppvObj]
  259. //
  260. // History: 26-Mar-92 DrewB Created
  261. //
  262. //---------------------------------------------------------------
  263. STDMETHODIMP CFileStream::QueryInterface(REFIID iid, void **ppvObj)
  264. {
  265. SCODE sc;
  266. #ifdef ASYNC
  267. BOOL fIsAsync = (_ppc != NULL);
  268. #else
  269. const BOOL fIsAsync = FALSE;
  270. #endif
  271. filestDebug((DEB_ITRACE, "In CFileStream::QueryInterface(?, %p)\n",
  272. ppvObj));
  273. sc = S_OK;
  274. if (IsEqualIID(iid, IID_IFileLockBytes) ||
  275. IsEqualIID(iid, IID_IUnknown))
  276. {
  277. *ppvObj = (IFileLockBytes *)this;
  278. CFileStream::vAddRef();
  279. }
  280. else if ((IsEqualIID(iid, IID_ILockBytes)) && !fIsAsync)
  281. {
  282. *ppvObj = (ILockBytes *)this;
  283. CFileStream::vAddRef();
  284. }
  285. else if ((IsEqualIID(iid, IID_IMarshal)) && !fIsAsync)
  286. {
  287. *ppvObj = (IMarshal *)this;
  288. CFileStream::vAddRef();
  289. }
  290. #ifdef ASYNC
  291. else if (IsEqualIID(iid, IID_IFillLockBytes))
  292. {
  293. *ppvObj = (IFillLockBytes *)this;
  294. CFileStream::vAddRef();
  295. }
  296. else if (IsEqualIID(iid, IID_IFillInfo))
  297. {
  298. *ppvObj = (IFillInfo *)this;
  299. CFileStream::vAddRef();
  300. }
  301. #endif
  302. #if WIN32 >= 300
  303. else if (IsEqualIID(iid, IID_IAccessControl))
  304. {
  305. DWORD grfMode = 0;
  306. if (_pgfst->GetDFlags() & DF_TRANSACTED)
  307. grfMode |= STGM_TRANSACTED;
  308. if (_pgfst->GetDFlags() & DF_ACCESSCONTROL)
  309. grfMode |= STGM_EDIT_ACCESS_RIGHTS;
  310. // check if underlying file system supports security
  311. if (SUCCEEDED(sc = InitAccessControl(_hFile, grfMode, TRUE, NULL)))
  312. {
  313. *ppvObj = (IAccessControl *) this;
  314. CFileStream::vAddRef();
  315. }
  316. else sc = E_NOINTERFACE;
  317. }
  318. #endif
  319. else
  320. {
  321. sc = E_NOINTERFACE;
  322. }
  323. filestDebug((DEB_ITRACE, "Out CFileStream::QueryInterface => %p\n",
  324. ppvObj));
  325. return ResultFromScode(sc);
  326. }
  327. //+--------------------------------------------------------------
  328. //
  329. // Member: CFileStream::Unmarshal, public
  330. //
  331. // Synopsis: Creates a duplicate FileStream
  332. //
  333. // Arguments: [ptsm] - Marshal stream
  334. // [ppv] - New filestream return
  335. // [mshlflags] - Marshal flags
  336. //
  337. // Returns: Appropriate status code
  338. //
  339. // Modifies: [ppv]
  340. //
  341. // History: 14-Apr-92 DrewB Created
  342. //
  343. //---------------------------------------------------------------
  344. SCODE CFileStream::Unmarshal(IStream *pstm,
  345. void **ppv,
  346. DWORD mshlflags)
  347. {
  348. SCODE sc;
  349. WCHAR wcsPath[_MAX_PATH];
  350. CFileStream *pfst;
  351. CGlobalFileStream *pgfst;
  352. filestDebug((DEB_ITRACE, "In CFileStream::Unmarshal(%p, %p, %lu)\n",
  353. pstm, ppv, mshlflags));
  354. fsChk(UnmarshalPointer(pstm, (void **)&pgfst));
  355. pfst = pgfst->Find(GetCurrentContextId());
  356. if (pfst != NULL && !pfst->IsHandleValid())
  357. pfst = NULL;
  358. if (pfst)
  359. {
  360. pfst->AddRef();
  361. //
  362. // Scratch CFileStreams are always marshaled. If we marshal a
  363. // direct-mode Base file, then an unopen uninitialized scratch
  364. // CFileStream is also marshaled (don't call InitUnmarshal here).
  365. // If a substorage is later opened in transacted mode then the
  366. // unopen scratch CFileStream is initialized (given a filename
  367. // and opened). If the scratch is then marshaled, the reciever
  368. // must initialize his unopened scratch CFileStream.
  369. //
  370. if (pgfst->HasName())
  371. {
  372. fsChkTo(EH_pfst, pfst->InitUnmarshal());
  373. }
  374. }
  375. else
  376. {
  377. fsMemTo(EH_pgfst,
  378. pfst = new (pgfst->GetMalloc())
  379. CFileStream(pgfst->GetMalloc()));
  380. pfst->InitFromGlobal(pgfst);
  381. if (pgfst->HasName())
  382. {
  383. fsChkTo(EH_pfst, pfst->InitUnmarshal());
  384. }
  385. }
  386. *ppv = (void *)pfst;
  387. filestDebug((DEB_ITRACE, "Out CFileStream::Unmarshal => %p\n", *ppv));
  388. return S_OK;
  389. EH_pfst:
  390. pfst->Release();
  391. EH_pgfst:
  392. EH_Err:
  393. return sc;
  394. }
  395. //+--------------------------------------------------------------
  396. //
  397. // Member: CFileStream::GetUnmarshalClass, public
  398. //
  399. // Synopsis: Returns the class ID
  400. //
  401. // Arguments: [riid] - IID of object
  402. // [pv] - Unreferenced
  403. // [dwDestContext] - Unreferenced
  404. // [pvDestContext] - Unreferenced
  405. // [mshlflags] - Unreferenced
  406. // [pcid] - CLSID return
  407. //
  408. // Returns: Appropriate status code
  409. //
  410. // Modifies: [pcid]
  411. //
  412. // History: 04-May-92 DrewB Created
  413. //
  414. //---------------------------------------------------------------
  415. STDMETHODIMP CFileStream::GetUnmarshalClass(REFIID riid,
  416. void *pv,
  417. DWORD dwDestContext,
  418. LPVOID pvDestContext,
  419. DWORD mshlflags,
  420. LPCLSID pcid)
  421. {
  422. SCODE sc;
  423. filestDebug((DEB_ITRACE, "In CFileStream::GetUnmarshalClass("
  424. "riid, %p, %lu, %p, %lu, %p)\n", pv, dwDestContext,
  425. pvDestContext, mshlflags, pcid));
  426. UNREFERENCED_PARM(pv);
  427. UNREFERENCED_PARM(mshlflags);
  428. *pcid = CLSID_DfMarshal;
  429. sc = S_OK;
  430. filestDebug((DEB_ITRACE, "Out CFileStream::GetUnmarshalClass\n"));
  431. return ResultFromScode(sc);
  432. }
  433. //+--------------------------------------------------------------
  434. //
  435. // Member: CFileStream::GetMarshalSizeMax, public
  436. //
  437. // Synopsis: Returns the size needed for the marshal buffer
  438. //
  439. // Arguments: [iid] - IID of object being marshaled
  440. // [pv] - Unreferenced
  441. // [dwDestContext] - Unreferenced
  442. // [pvDestContext] - Unreferenced
  443. // [mshlflags] - Marshal flags
  444. // [pcbSize] - Size return
  445. //
  446. // Returns: Appropriate status code
  447. //
  448. // Modifies: [pcbSize]
  449. //
  450. // History: 04-May-92 DrewB Created
  451. //
  452. //---------------------------------------------------------------
  453. STDMETHODIMP CFileStream::GetMarshalSizeMax(REFIID riid,
  454. void *pv,
  455. DWORD dwDestContext,
  456. LPVOID pvDestContext,
  457. DWORD mshlflags,
  458. LPDWORD pcbSize)
  459. {
  460. SCODE sc;
  461. UNREFERENCED_PARM(pv);
  462. fsChk(Validate());
  463. sc = GetStdMarshalSize(riid, IID_ILockBytes, dwDestContext, pvDestContext,
  464. mshlflags, pcbSize, sizeof(CFileStream *),
  465. #ifdef ASYNC
  466. NULL,
  467. FALSE,
  468. NULL,
  469. #else
  470. NULL,
  471. #endif
  472. FALSE);
  473. fsAssert (_ppc == NULL); // async lockbytes are standard marshaled
  474. EH_Err:
  475. return sc;
  476. }
  477. //+--------------------------------------------------------------
  478. //
  479. // Member: CFileStream::MarshalInterface, public
  480. //
  481. // Synopsis: Marshals a given object
  482. //
  483. // Arguments: [pstStm] - Stream to write marshal data into
  484. // [iid] - Interface to marshal
  485. // [pv] - Unreferenced
  486. // [dwDestContext] - Unreferenced
  487. // [pvDestContext] - Unreferenced
  488. // [mshlflags] - Marshal flags
  489. //
  490. // Returns: Appropriate status code
  491. //
  492. // History: 04-May-92 DrewB Created
  493. //
  494. //---------------------------------------------------------------
  495. STDMETHODIMP CFileStream::MarshalInterface(IStream *pstStm,
  496. REFIID riid,
  497. void *pv,
  498. DWORD dwDestContext,
  499. LPVOID pvDestContext,
  500. DWORD mshlflags)
  501. {
  502. SCODE sc;
  503. #ifdef ASYNC
  504. fsAssert (_ppc == NULL); // async lockbytes are standard marshaled
  505. #endif
  506. filestDebug((DEB_ITRACE, "In CFileStream::MarshalInterface("
  507. "%p, iid, %p, %lu, %p, %lu)\n", pstStm, pv, dwDestContext,
  508. pvDestContext, mshlflags));
  509. UNREFERENCED_PARM(pv);
  510. fsChk(StartMarshal(pstStm, riid, IID_ILockBytes, mshlflags));
  511. fsChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst)));
  512. filestDebug((DEB_ITRACE, "Out CFileStream::MarshalInterface\n"));
  513. EH_Err:
  514. return sc;
  515. }
  516. //+--------------------------------------------------------------
  517. //
  518. // Member: CFileStream::UnmarshalInterface, public
  519. //
  520. // Synopsis: Non-functional
  521. //
  522. // Arguments: [pstStm] -
  523. // [iid] -
  524. // [ppvObj] -
  525. //
  526. // Returns: Appropriate status code
  527. //
  528. // Modifies: [ppvObj]
  529. //
  530. // History: 04-May-92 DrewB Created
  531. //
  532. //---------------------------------------------------------------
  533. STDMETHODIMP CFileStream::UnmarshalInterface(IStream *pstStm,
  534. REFIID iid,
  535. void **ppvObj)
  536. {
  537. return ResultFromScode(STG_E_INVALIDFUNCTION);
  538. }
  539. //+--------------------------------------------------------------
  540. //
  541. // Member: CFileStream::StaticReleaseMarshalData, public static
  542. //
  543. // Synopsis: Releases any references held in marshal data
  544. //
  545. // Arguments: [pstStm] - Marshal data stream
  546. //
  547. // Returns: Appropriate status code
  548. //
  549. // History: 02-Feb-94 DrewB Created
  550. //
  551. // Notes: Assumes standard marshal header has already been read
  552. //
  553. //---------------------------------------------------------------
  554. SCODE CFileStream::StaticReleaseMarshalData(IStream *pstStm,
  555. DWORD mshlflags)
  556. {
  557. SCODE sc;
  558. CGlobalFileStream *pgfst;
  559. filestDebug((DEB_ITRACE, "In CFileStream::StaticReleaseMarshalData:("
  560. "%p, %lX)\n", pstStm, mshlflags));
  561. fsChk(UnmarshalPointer(pstStm, (void **)&pgfst));
  562. filestDebug((DEB_ITRACE, "Out CFileStream::StaticReleaseMarshalData\n"));
  563. EH_Err:
  564. return sc;
  565. }
  566. //+--------------------------------------------------------------
  567. //
  568. // Member: CFileStream::ReleaseMarshalData, public
  569. //
  570. // Synopsis: Non-functional
  571. //
  572. // Arguments: [pstStm] -
  573. //
  574. // Returns: Appropriate status code
  575. //
  576. // History: 18-Sep-92 DrewB Created
  577. //
  578. //---------------------------------------------------------------
  579. STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm)
  580. {
  581. SCODE sc;
  582. DWORD mshlflags;
  583. IID iid;
  584. filestDebug((DEB_ITRACE, "In CFileStream::ReleaseMarshalData:%p(%p)\n",
  585. this, pstStm));
  586. fsChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
  587. fsAssert(IsEqualIID(iid, IID_ILockBytes));
  588. sc = StaticReleaseMarshalData(pstStm, mshlflags);
  589. filestDebug((DEB_ITRACE, "Out CFileStream::ReleaseMarshalData\n"));
  590. EH_Err:
  591. return ResultFromScode(sc);
  592. }
  593. //+--------------------------------------------------------------
  594. //
  595. // Member: CFileStream::DisconnectObject, public
  596. //
  597. // Synopsis: Non-functional
  598. //
  599. // Arguments: [dwReserved] -
  600. //
  601. // Returns: Appropriate status code
  602. //
  603. // History: 18-Sep-92 DrewB Created
  604. //
  605. //---------------------------------------------------------------
  606. STDMETHODIMP CFileStream::DisconnectObject(DWORD dwReserved)
  607. {
  608. return ResultFromScode(STG_E_INVALIDFUNCTION);
  609. }
  610. //+--------------------------------------------------------------
  611. //
  612. // Member: CFileStream::GetLocksSupported, public
  613. //
  614. // Synopsis: Return lock capabilities
  615. //
  616. // Arguments: [pdwLockFlags] -- place holder for lock flags
  617. //
  618. // Returns: Appropriate status code
  619. //
  620. // History: 12-Jul-93 AlexT Created
  621. //
  622. //---------------------------------------------------------------
  623. STDMETHODIMP CFileStream::GetLocksSupported(DWORD *pdwLockFlags)
  624. {
  625. *pdwLockFlags = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  626. return(ResultFromScode(S_OK));
  627. }