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.

373 lines
8.7 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: asyncapi.cxx
  7. //
  8. // Contents: APIs for async docfiles
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 19-Dec-95 PhilipLa Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "astghead.cxx"
  18. #pragma hdrstop
  19. #ifndef ASYNC
  20. #define USE_FILELKB
  21. #endif
  22. #include "asyncapi.hxx"
  23. #include "filllkb.hxx"
  24. #ifdef USE_FILELKB
  25. #include "filebyte.hxx"
  26. #endif
  27. #ifdef ASYNC
  28. #include <expdf.hxx>
  29. #endif
  30. #if DBG == 1
  31. DECLARE_INFOLEVEL(astg);
  32. #endif
  33. #ifdef ASYNC
  34. #ifdef COORD
  35. SCODE DfFromLB(CPerContext *ppc,
  36. ILockBytes *plst,
  37. DFLAGS df,
  38. DWORD dwStartFlags,
  39. SNBW snbExclude,
  40. ITransaction *pTransaction,
  41. CExposedDocFile **ppdfExp,
  42. CLSID *pcid);
  43. #else
  44. SCODE DfFromLB(CPerContext *ppc,
  45. ILockBytes *plst,
  46. DFLAGS df,
  47. DWORD dwStartFlags,
  48. SNBW snbExclude,
  49. CExposedDocFile **ppdfExp,
  50. CLSID *pcid);
  51. #endif //COORD
  52. #endif //ASYNC
  53. STDAPI StgOpenAsyncDocfileOnIFillLockBytes(IFillLockBytes *pflb,
  54. DWORD grfMode,
  55. DWORD asyncFlags,
  56. IStorage **ppstgOpen)
  57. {
  58. #ifdef ASYNC
  59. SCODE sc;
  60. ILockBytes *pilb;
  61. IStorage *pstg;
  62. IFileLockBytes *pfl;
  63. sc = ValidateInterface(pflb, IID_IFillLockBytes);
  64. if (FAILED(sc))
  65. {
  66. return sc;
  67. }
  68. sc = ValidateOutPtrBuffer(ppstgOpen);
  69. if (FAILED(sc))
  70. {
  71. return sc;
  72. }
  73. *ppstgOpen = NULL;
  74. //We're going to do a song and dance here because the ILockBytes
  75. //implementation we return from StgGetIFillLockBytesOnFile won't
  76. //let you QI for ILockBytes (because those methods aren't thread safe,
  77. //among other things). Instead we QI for a private interface and do
  78. //a direct cast if that succeeds. Otherwise we're on someone else's
  79. //implementation so we just go right for ILockBytes.
  80. sc = pflb->QueryInterface(IID_IFileLockBytes, (void **)&pfl);
  81. if (FAILED(sc))
  82. {
  83. sc = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
  84. if (FAILED(sc))
  85. {
  86. return sc;
  87. }
  88. }
  89. else
  90. {
  91. pilb = (ILockBytes *)((CFileStream *)pfl);
  92. }
  93. //If we're operating on the docfile owned ILockBytes, then we can
  94. // go directly to DfFromLB instead of using StgOpenStorageOnILockBytes
  95. // which will avoid creating another shared heap.
  96. if (pfl != NULL)
  97. {
  98. pfl->Release();
  99. pilb = NULL;
  100. CFileStream *pfst = (CFileStream *)pflb;
  101. CPerContext *ppc = pfst->GetContextPointer();
  102. #ifdef MULTIHEAP
  103. CSafeMultiHeap smh(ppc);
  104. #endif
  105. #ifdef COORD
  106. astgChk(DfFromLB(ppc,
  107. pfst,
  108. ModeToDFlags(grfMode),
  109. pfst->GetStartFlags(),
  110. NULL,
  111. NULL,
  112. (CExposedDocFile **)&pstg,
  113. NULL));
  114. #else
  115. astgChk(DfFromLB(ppc,
  116. pfst,
  117. ModeToDFlags(grfMode),
  118. pfst->GetStartFlags(),
  119. NULL,
  120. (CExposedDocFile **)&pstg,
  121. NULL));
  122. #endif
  123. //Note: Don't release the ILB reference we got from the QI
  124. // above, since DfFromLB recorded that pointer but didn't
  125. // AddRef it.
  126. pfst->AddRef(); // CExposedDocfile will release this reference
  127. }
  128. else
  129. {
  130. IFillLockBytes *pflb2;
  131. if (SUCCEEDED(pilb->QueryInterface(IID_IDefaultFillLockBytes,
  132. (void **)&pflb2)))
  133. {
  134. CFillLockBytes *pflbDefault = (CFillLockBytes *)pflb;
  135. CPerContext *ppc;
  136. pflb2->Release();
  137. astgChk(StgOpenStorageOnILockBytes(pilb,
  138. NULL,
  139. grfMode,
  140. NULL,
  141. 0,
  142. &pstg));
  143. //Get PerContext pointer from pstg
  144. ppc = ((CExposedDocFile *)pstg)->GetContext();
  145. pflbDefault->SetContext(ppc);
  146. }
  147. else
  148. {
  149. astgChk(StgOpenStorageOnILockBytes(pilb,
  150. NULL,
  151. grfMode,
  152. NULL,
  153. 0,
  154. &pstg));
  155. }
  156. pilb->Release();
  157. pilb = NULL;
  158. }
  159. astgChkTo(EH_stg, ((CExposedDocFile *)pstg)->InitConnection(NULL));
  160. ((CExposedDocFile *)pstg)->SetAsyncFlags(asyncFlags);
  161. *ppstgOpen = pstg;
  162. return NOERROR;
  163. EH_stg:
  164. pstg->Release();
  165. Err:
  166. if (pilb != NULL)
  167. pilb->Release();
  168. if (sc == STG_E_PENDINGCONTROL)
  169. {
  170. sc = E_PENDING;
  171. }
  172. return ResultFromScode(sc);
  173. #else
  174. HRESULT hr;
  175. ILockBytes *pilb;
  176. IStorage *pstg;
  177. hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
  178. if (FAILED(hr))
  179. {
  180. return hr;
  181. }
  182. hr = StgOpenStorageOnILockBytes(pilb,
  183. NULL,
  184. grfMode,
  185. NULL,
  186. 0,
  187. &pstg);
  188. pilb->Release();
  189. if (FAILED(hr))
  190. {
  191. if (hr == STG_E_PENDINGCONTROL)
  192. {
  193. hr = E_PENDING;
  194. }
  195. return hr;
  196. }
  197. BOOL fDefault = FALSE;
  198. IFillLockBytes *pflbDefault;
  199. hr = pflb->QueryInterface(IID_IDefaultFillLockBytes,
  200. (void **)&pflbDefault);
  201. if (SUCCEEDED(hr))
  202. {
  203. fDefault = TRUE;
  204. pflbDefault->Release();
  205. }
  206. *ppstgOpen = new CAsyncRootStorage(pstg, pflb, fDefault);
  207. if (*ppstgOpen == NULL)
  208. {
  209. return STG_E_INSUFFICIENTMEMORY;
  210. }
  211. else
  212. {
  213. ((CAsyncRootStorage *)(*ppstgOpen))->SetAsyncFlags(asyncFlags);
  214. }
  215. return NOERROR;
  216. #endif //ASYNC
  217. }
  218. STDAPI StgGetIFillLockBytesOnILockBytes( ILockBytes *pilb,
  219. IFillLockBytes **ppflb)
  220. {
  221. SCODE sc = S_OK;
  222. CFillLockBytes *pflb = NULL;
  223. sc = ValidateOutPtrBuffer(ppflb);
  224. if (FAILED(sc))
  225. {
  226. return sc;
  227. }
  228. sc = ValidateInterface(pilb, IID_ILockBytes);
  229. if (FAILED(sc))
  230. {
  231. return sc;
  232. }
  233. pflb = new CFillLockBytes(pilb);
  234. if (pflb == NULL)
  235. {
  236. return STG_E_INSUFFICIENTMEMORY;
  237. }
  238. sc = pflb->Init();
  239. if (FAILED(sc))
  240. {
  241. pflb->Release();
  242. *ppflb = NULL;
  243. return sc;
  244. }
  245. *ppflb = pflb;
  246. return NOERROR;
  247. }
  248. STDAPI StgGetIFillLockBytesOnFile(OLECHAR const *pwcsName,
  249. IFillLockBytes **ppflb)
  250. {
  251. #ifndef USE_FILELKB
  252. SCODE sc;
  253. IMalloc *pMalloc;
  254. CFileStream *plst;
  255. CFillLockBytes *pflb;
  256. CPerContext *ppc;
  257. astgChk(ValidateNameW(pwcsName, _MAX_PATH));
  258. astgChk(ValidateOutPtrBuffer(ppflb));
  259. DfInitSharedMemBase();
  260. astgHChk(DfCreateSharedAllocator(&pMalloc, FALSE));
  261. astgMemTo(EH_Malloc, plst = new (pMalloc) CFileStream(pMalloc));
  262. astgChkTo(EH_plst, plst->InitGlobal(RSF_CREATE,
  263. DF_DIRECT | DF_READ |
  264. DF_WRITE | DF_DENYALL));
  265. astgChkTo(EH_plst, plst->InitFile(pwcsName));
  266. astgMemTo(EH_plstInit, ppc = new (pMalloc) CPerContext(pMalloc));
  267. astgChkTo(EH_ppc, ppc->InitNewContext());
  268. //We want 0 normal references on the per context, and one reference
  269. // to the shared memory.
  270. ppc->DecRef();
  271. plst->SetContext(ppc);
  272. plst->StartAsyncMode();
  273. astgChkTo(EH_plstInit, ppc->InitNotificationEvent(plst));
  274. *ppflb = (IFillLockBytes *)plst;
  275. return S_OK;
  276. EH_ppc:
  277. delete ppc;
  278. EH_plstInit:
  279. plst->Delete();
  280. EH_plst:
  281. plst->Release();
  282. EH_Malloc:
  283. pMalloc->Release();
  284. Err:
  285. return sc;
  286. #else
  287. SCODE sc;
  288. CFileLockBytes *pflb = NULL;
  289. pflb = new CFileLockBytes;
  290. if (pflb == NULL)
  291. {
  292. return STG_E_INSUFFICIENTMEMORY;
  293. }
  294. sc = pflb->Init(pwcsName);
  295. if (SUCCEEDED(sc))
  296. {
  297. sc = StgGetIFillLockBytesOnILockBytes(pflb, ppflb);
  298. }
  299. return sc;
  300. #endif // ASYNC
  301. }
  302. #if DBG == 1
  303. STDAPI StgGetDebugFileLockBytes(OLECHAR const *pwcsName, ILockBytes **ppilb)
  304. {
  305. #ifdef ASYNC
  306. return STG_E_UNIMPLEMENTEDFUNCTION;
  307. #else
  308. SCODE sc;
  309. CFileLockBytes *pflb;
  310. *ppilb = NULL;
  311. pflb = new CFileLockBytes;
  312. if (pflb == NULL)
  313. {
  314. return STG_E_INSUFFICIENTMEMORY;
  315. }
  316. sc = pflb->Init(pwcsName);
  317. if (FAILED(sc))
  318. {
  319. delete pflb;
  320. pflb = NULL;
  321. }
  322. *ppilb = pflb;
  323. return sc;
  324. #endif // ASYNC
  325. }
  326. #endif