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.

737 lines
20 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. StringCbCopy (_awcMapName, sizeof(_awcMapName), pgfs->_awcMapName);
  127. StringCbCopy (_awcPath, sizeof(_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. StringCchCopyW(*ppwcsName, lstrlenW(_pgfst->GetName())+1, _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. CFileStream *pfst;
  350. CGlobalFileStream *pgfst;
  351. filestDebug((DEB_ITRACE, "In CFileStream::Unmarshal(%p, %p, %lu)\n",
  352. pstm, ppv, mshlflags));
  353. fsChk(UnmarshalPointer(pstm, (void **)&pgfst));
  354. pfst = pgfst->Find(GetCurrentContextId());
  355. if (pfst != NULL && !pfst->IsHandleValid())
  356. pfst = NULL;
  357. if (pfst)
  358. {
  359. pfst->AddRef();
  360. //
  361. // Scratch CFileStreams are always marshaled. If we marshal a
  362. // direct-mode Base file, then an unopen uninitialized scratch
  363. // CFileStream is also marshaled (don't call InitUnmarshal here).
  364. // If a substorage is later opened in transacted mode then the
  365. // unopen scratch CFileStream is initialized (given a filename
  366. // and opened). If the scratch is then marshaled, the reciever
  367. // must initialize his unopened scratch CFileStream.
  368. //
  369. if (pgfst->HasName())
  370. {
  371. fsChkTo(EH_pfst, pfst->InitUnmarshal());
  372. }
  373. }
  374. else
  375. {
  376. fsMemTo(EH_pgfst,
  377. pfst = new (pgfst->GetMalloc())
  378. CFileStream(pgfst->GetMalloc()));
  379. pfst->InitFromGlobal(pgfst);
  380. if (pgfst->HasName())
  381. {
  382. fsChkTo(EH_pfst, pfst->InitUnmarshal());
  383. }
  384. }
  385. *ppv = (void *)pfst;
  386. filestDebug((DEB_ITRACE, "Out CFileStream::Unmarshal => %p\n", *ppv));
  387. return S_OK;
  388. EH_pfst:
  389. pfst->Release();
  390. EH_pgfst:
  391. EH_Err:
  392. return sc;
  393. }
  394. //+--------------------------------------------------------------
  395. //
  396. // Member: CFileStream::GetUnmarshalClass, public
  397. //
  398. // Synopsis: Returns the class ID
  399. //
  400. // Arguments: [riid] - IID of object
  401. // [pv] - Unreferenced
  402. // [dwDestContext] - Unreferenced
  403. // [pvDestContext] - Unreferenced
  404. // [mshlflags] - Unreferenced
  405. // [pcid] - CLSID return
  406. //
  407. // Returns: Appropriate status code
  408. //
  409. // Modifies: [pcid]
  410. //
  411. // History: 04-May-92 DrewB Created
  412. //
  413. //---------------------------------------------------------------
  414. STDMETHODIMP CFileStream::GetUnmarshalClass(REFIID riid,
  415. void *pv,
  416. DWORD dwDestContext,
  417. LPVOID pvDestContext,
  418. DWORD mshlflags,
  419. LPCLSID pcid)
  420. {
  421. SCODE sc;
  422. filestDebug((DEB_ITRACE, "In CFileStream::GetUnmarshalClass("
  423. "riid, %p, %lu, %p, %lu, %p)\n", pv, dwDestContext,
  424. pvDestContext, mshlflags, pcid));
  425. UNREFERENCED_PARM(pv);
  426. UNREFERENCED_PARM(mshlflags);
  427. *pcid = CLSID_DfMarshal;
  428. sc = S_OK;
  429. filestDebug((DEB_ITRACE, "Out CFileStream::GetUnmarshalClass\n"));
  430. return ResultFromScode(sc);
  431. }
  432. //+--------------------------------------------------------------
  433. //
  434. // Member: CFileStream::GetMarshalSizeMax, public
  435. //
  436. // Synopsis: Returns the size needed for the marshal buffer
  437. //
  438. // Arguments: [iid] - IID of object being marshaled
  439. // [pv] - Unreferenced
  440. // [dwDestContext] - Unreferenced
  441. // [pvDestContext] - Unreferenced
  442. // [mshlflags] - Marshal flags
  443. // [pcbSize] - Size return
  444. //
  445. // Returns: Appropriate status code
  446. //
  447. // Modifies: [pcbSize]
  448. //
  449. // History: 04-May-92 DrewB Created
  450. //
  451. //---------------------------------------------------------------
  452. STDMETHODIMP CFileStream::GetMarshalSizeMax(REFIID riid,
  453. void *pv,
  454. DWORD dwDestContext,
  455. LPVOID pvDestContext,
  456. DWORD mshlflags,
  457. LPDWORD pcbSize)
  458. {
  459. SCODE sc;
  460. UNREFERENCED_PARM(pv);
  461. fsChk(Validate());
  462. sc = GetStdMarshalSize(riid, IID_ILockBytes, dwDestContext, pvDestContext,
  463. mshlflags, pcbSize, sizeof(CFileStream *),
  464. #ifdef ASYNC
  465. NULL,
  466. FALSE,
  467. NULL,
  468. #else
  469. NULL,
  470. #endif
  471. FALSE);
  472. fsAssert (_ppc == NULL); // async lockbytes are standard marshaled
  473. EH_Err:
  474. return sc;
  475. }
  476. //+--------------------------------------------------------------
  477. //
  478. // Member: CFileStream::MarshalInterface, public
  479. //
  480. // Synopsis: Marshals a given object
  481. //
  482. // Arguments: [pstStm] - Stream to write marshal data into
  483. // [iid] - Interface to marshal
  484. // [pv] - Unreferenced
  485. // [dwDestContext] - Unreferenced
  486. // [pvDestContext] - Unreferenced
  487. // [mshlflags] - Marshal flags
  488. //
  489. // Returns: Appropriate status code
  490. //
  491. // History: 04-May-92 DrewB Created
  492. //
  493. //---------------------------------------------------------------
  494. STDMETHODIMP CFileStream::MarshalInterface(IStream *pstStm,
  495. REFIID riid,
  496. void *pv,
  497. DWORD dwDestContext,
  498. LPVOID pvDestContext,
  499. DWORD mshlflags)
  500. {
  501. SCODE sc;
  502. #ifdef ASYNC
  503. fsAssert (_ppc == NULL); // async lockbytes are standard marshaled
  504. #endif
  505. filestDebug((DEB_ITRACE, "In CFileStream::MarshalInterface("
  506. "%p, iid, %p, %lu, %p, %lu)\n", pstStm, pv, dwDestContext,
  507. pvDestContext, mshlflags));
  508. UNREFERENCED_PARM(pv);
  509. fsChk(StartMarshal(pstStm, riid, IID_ILockBytes, mshlflags));
  510. fsChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst)));
  511. filestDebug((DEB_ITRACE, "Out CFileStream::MarshalInterface\n"));
  512. EH_Err:
  513. return sc;
  514. }
  515. //+--------------------------------------------------------------
  516. //
  517. // Member: CFileStream::UnmarshalInterface, public
  518. //
  519. // Synopsis: Non-functional
  520. //
  521. // Arguments: [pstStm] -
  522. // [iid] -
  523. // [ppvObj] -
  524. //
  525. // Returns: Appropriate status code
  526. //
  527. // Modifies: [ppvObj]
  528. //
  529. // History: 04-May-92 DrewB Created
  530. //
  531. //---------------------------------------------------------------
  532. STDMETHODIMP CFileStream::UnmarshalInterface(IStream *pstStm,
  533. REFIID iid,
  534. void **ppvObj)
  535. {
  536. return ResultFromScode(STG_E_INVALIDFUNCTION);
  537. }
  538. //+--------------------------------------------------------------
  539. //
  540. // Member: CFileStream::StaticReleaseMarshalData, public static
  541. //
  542. // Synopsis: Releases any references held in marshal data
  543. //
  544. // Arguments: [pstStm] - Marshal data stream
  545. //
  546. // Returns: Appropriate status code
  547. //
  548. // History: 02-Feb-94 DrewB Created
  549. //
  550. // Notes: Assumes standard marshal header has already been read
  551. //
  552. //---------------------------------------------------------------
  553. SCODE CFileStream::StaticReleaseMarshalData(IStream *pstStm,
  554. DWORD mshlflags)
  555. {
  556. SCODE sc;
  557. CGlobalFileStream *pgfst;
  558. filestDebug((DEB_ITRACE, "In CFileStream::StaticReleaseMarshalData:("
  559. "%p, %lX)\n", pstStm, mshlflags));
  560. fsChk(UnmarshalPointer(pstStm, (void **)&pgfst));
  561. filestDebug((DEB_ITRACE, "Out CFileStream::StaticReleaseMarshalData\n"));
  562. EH_Err:
  563. return sc;
  564. }
  565. //+--------------------------------------------------------------
  566. //
  567. // Member: CFileStream::ReleaseMarshalData, public
  568. //
  569. // Synopsis: Non-functional
  570. //
  571. // Arguments: [pstStm] -
  572. //
  573. // Returns: Appropriate status code
  574. //
  575. // History: 18-Sep-92 DrewB Created
  576. //
  577. //---------------------------------------------------------------
  578. STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm)
  579. {
  580. SCODE sc;
  581. DWORD mshlflags;
  582. IID iid;
  583. filestDebug((DEB_ITRACE, "In CFileStream::ReleaseMarshalData:%p(%p)\n",
  584. this, pstStm));
  585. fsChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
  586. fsAssert(IsEqualIID(iid, IID_ILockBytes));
  587. sc = StaticReleaseMarshalData(pstStm, mshlflags);
  588. filestDebug((DEB_ITRACE, "Out CFileStream::ReleaseMarshalData\n"));
  589. EH_Err:
  590. return ResultFromScode(sc);
  591. }
  592. //+--------------------------------------------------------------
  593. //
  594. // Member: CFileStream::DisconnectObject, public
  595. //
  596. // Synopsis: Non-functional
  597. //
  598. // Arguments: [dwReserved] -
  599. //
  600. // Returns: Appropriate status code
  601. //
  602. // History: 18-Sep-92 DrewB Created
  603. //
  604. //---------------------------------------------------------------
  605. STDMETHODIMP CFileStream::DisconnectObject(DWORD dwReserved)
  606. {
  607. return ResultFromScode(STG_E_INVALIDFUNCTION);
  608. }
  609. //+--------------------------------------------------------------
  610. //
  611. // Member: CFileStream::GetLocksSupported, public
  612. //
  613. // Synopsis: Return lock capabilities
  614. //
  615. // Arguments: [pdwLockFlags] -- place holder for lock flags
  616. //
  617. // Returns: Appropriate status code
  618. //
  619. // History: 12-Jul-93 AlexT Created
  620. //
  621. //---------------------------------------------------------------
  622. STDMETHODIMP CFileStream::GetLocksSupported(DWORD *pdwLockFlags)
  623. {
  624. if (pdwLockFlags != NULL)
  625. *pdwLockFlags = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
  626. else
  627. return STG_E_INVALIDPOINTER;
  628. return S_OK ;
  629. }