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.

897 lines
26 KiB

  1. //+==================================================================
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1998.
  5. //
  6. // File: PropAPI.cxx
  7. //
  8. // This file provides the Property Set API routines.
  9. //
  10. // APIs: StgCreatePropSetStg (creates an IPropertySetStorage)
  11. // StgCreatePropStg (creates an IPropertyStorage)
  12. // StgOpenPropStg (opens an IPropertyStorage)
  13. // StgCreateStorageOnHandle (private, not a public API)
  14. // StgOpenStorageOnHandle (private, not a public API)
  15. //
  16. // History:
  17. //
  18. // 3/10/98 MikeHill - Added StgCreate/OpenStorageOnHandle
  19. // 5/6/98 MikeHill - Rewrite StgCreate/OpenStorageOnHandle.
  20. // 5/18/98 MikeHill
  21. // - Use new CPropertySetStorage constructor.
  22. //
  23. //+==================================================================
  24. #include <pch.cxx>
  25. #ifdef _MAC_NODOC
  26. ASSERTDATA // File-specific data for FnAssert
  27. #endif
  28. //+------------------------------------------------------------------
  29. //
  30. // Function: QueryForIStream
  31. //
  32. // Synopsis: This routine queries an IUnknown for
  33. // an IStream interface. This is isolated into
  34. // a separate routine because some workaround code
  35. // is required on the Mac.
  36. //
  37. // Inputs: [IUnknown*] pUnk
  38. // The interface to be queried.
  39. // [IStream**] ppStm
  40. // Location to return the result.
  41. //
  42. // Returns: [HRESULT]
  43. //
  44. // Notes: On older Mac implementations (<=2.08, <=~1996)
  45. // the memory-based IStream implementation
  46. // (created by CreateStreamOnHGlobal) had a bug
  47. // in QueryInterface: when you QI for an
  48. // IStream or IUnknown, an addref is done, but an
  49. // HR of E_NOINTERFACE is returned.
  50. //
  51. // Below, we look for this condition: if we get an
  52. // E_NOINTERFACE on the Mac, we check to see if it's
  53. // an OLE mem-based IStream. If it is, we simply cast
  54. // IUnknown as an IStream. We validate it as an OLE
  55. // the mem-based IStream by creating one of our own, and
  56. // comparing the QueryInterface addresses.
  57. //
  58. // This is some ugly code, but at least it is isolated,
  59. // only runs on the older Macs, and ensures that we
  60. // work on all platforms.
  61. //
  62. //+------------------------------------------------------------------
  63. inline HRESULT QueryForIStream( IUnknown * pUnk, IStream** ppStm )
  64. {
  65. HRESULT hr;
  66. // Attempt to get the interface
  67. hr = pUnk->QueryInterface( IID_IStream, (void**) ppStm );
  68. #ifdef _MAC
  69. // On the Mac, if we get a no-interface error, see if it is really
  70. // a buggy mem-based IStream implementation.
  71. if( E_NOINTERFACE == hr )
  72. {
  73. IStream *pstmMem = NULL;
  74. // Create our own mem-based IStream.
  75. hr = CreateStreamOnHGlobal( NULL, TRUE, &pstmMem );
  76. if( FAILED(hr) ) goto Exit;
  77. // If the mem-based Stream's QI implementation has the same
  78. // address as the Unknown's QI implementation, then the Unknown
  79. // must be an OLE mem-based stream.
  80. if( pUnk->QueryInterface == pstmMem->QueryInterface )
  81. {
  82. // We can just cast the IUnknown* as an IStream* and
  83. // we're done (the original QI, despite returning an
  84. // error, has already done an AddRef).
  85. hr = S_OK;
  86. *ppStm = (IStream*) pUnk;
  87. }
  88. else
  89. {
  90. // This is a real no-interface error, so let's return it.
  91. hr = E_NOINTERFACE;
  92. }
  93. pstmMem->Release();
  94. }
  95. // ----
  96. // Exit
  97. // ----
  98. Exit:
  99. #endif // #ifdef _MAC
  100. return( hr );
  101. } // QueryForIStream()
  102. //+------------------------------------------------------------------
  103. //
  104. // Function: StgCreatePropStg
  105. //
  106. // Synopsis: Given an IStorage or IStream, create an
  107. // IPropertyStorage. This is similar to the
  108. // IPropertySetStorage::Create method. Existing
  109. // contents of the Storage/Stream are removed.
  110. //
  111. // Inputs: [IUnknown*] pUnk
  112. // An IStorage* for non-simple propsets,
  113. // an IStream* for simple. grfFlags is
  114. // used to disambiguate.
  115. // [REFFMTID] fmtid
  116. // The ID of the property set.
  117. // [DWORD] grfFlags
  118. // From the PROPSETFLAG_* enumeration.
  119. // [IPropertySetStorage**] ppPropStg
  120. // The result.
  121. //
  122. // Returns: [HRESULT]
  123. //
  124. // Notes: The caller is responsible for maintaining
  125. // thread-safety between the original
  126. // IStorage/IStream and this IPropertyStorage.
  127. //
  128. //+------------------------------------------------------------------
  129. STDAPI StgCreatePropStg( IUnknown *pUnk,
  130. REFFMTID fmtid,
  131. const CLSID *pclsid,
  132. DWORD grfFlags,
  133. DWORD dwReserved,
  134. IPropertyStorage **ppPropStg)
  135. {
  136. // ------
  137. // Locals
  138. // ------
  139. HRESULT hr;
  140. IStream *pstm = NULL;
  141. IStorage *pstg = NULL;
  142. CPropertyStorage *pPropStg = NULL;
  143. // ----------
  144. // Validation
  145. // ----------
  146. propXTraceStatic( "StgCreatePropStg" );
  147. GEN_VDATEIFACE_LABEL( pUnk, E_INVALIDARG, Exit, hr );
  148. GEN_VDATEREADPTRIN_LABEL(&fmtid, FMTID, E_INVALIDARG, Exit, hr );
  149. GEN_VDATEPTRIN_LABEL(pclsid, CLSID, E_INVALIDARG, Exit, hr );
  150. // grfFlags is validated by CPropertyStorage
  151. GEN_VDATEPTROUT_LABEL( ppPropStg, IPropertyStorage*, E_INVALIDARG, Exit, hr );
  152. *ppPropStg = NULL;
  153. propTraceParameters(( "pUnk=%p, fmtid=%s, clsid=%s, grfFlags=%s, dwReserved=0x%x, ppPropStg=%p",
  154. pUnk, static_cast<const char*>(CStringize(fmtid)),
  155. static_cast<const char*>(CStringize(*pclsid)),
  156. static_cast<const char*>(CStringize(SGrfFlags(grfFlags))),
  157. dwReserved, ppPropStg ));
  158. // -----------------------
  159. // Non-Simple Property Set
  160. // -----------------------
  161. if( grfFlags & PROPSETFLAG_NONSIMPLE )
  162. {
  163. // Get the IStorage*
  164. hr = pUnk->QueryInterface( IID_IStorage, (void**) &pstg );
  165. if( FAILED(hr) ) goto Exit;
  166. // Create the IPropertyStorage implementation
  167. pPropStg = new CPropertyStorage( MAPPED_STREAM_CREATE );
  168. if( NULL== pPropStg )
  169. {
  170. hr = E_OUTOFMEMORY;
  171. goto Exit;
  172. }
  173. // Initialize the IPropertyStorage
  174. hr = pPropStg->Create( pstg, fmtid, pclsid, grfFlags,
  175. 0 ); // We don't know the grfMode
  176. if( FAILED(hr) ) goto Exit;
  177. } // if( grfFlags & PROPSETFLAG_NONSIMPLE )
  178. // -------------------
  179. // Simple Property Set
  180. // -------------------
  181. else
  182. {
  183. // Get the IStream*
  184. hr = QueryForIStream( pUnk, &pstm );
  185. if( FAILED(hr) ) goto Exit;
  186. // Create an IPropertyStorage implementation.
  187. pPropStg = new CPropertyStorage( MAPPED_STREAM_CREATE );
  188. if( NULL == pPropStg )
  189. {
  190. hr = E_OUTOFMEMORY;
  191. goto Exit;
  192. }
  193. // Initialize the IPropertyStorage (which
  194. // is responsible for sizing and seeking the
  195. // stream).
  196. hr = pPropStg->Create( pstm, fmtid, pclsid, grfFlags,
  197. 0 ); // We don't know the grfMode
  198. if( FAILED(hr) ) goto Exit;
  199. } // if( grfFlags & PROPSETFLAG_NONSIMPLE ) ... else
  200. // ----
  201. // Exit
  202. // ----
  203. *ppPropStg = static_cast<IPropertyStorage*>(pPropStg);
  204. pPropStg = NULL;
  205. Exit:
  206. // If we created pPropStg, and there was an error, delete it.
  207. #if DBG
  208. if( FAILED(hr) )
  209. {
  210. propDbg((DEB_ERROR, "StgCreatePropStg returns %08X\n", hr ));
  211. }
  212. #endif
  213. if( NULL != pPropStg )
  214. delete pPropStg;
  215. if( NULL != pstm )
  216. pstm->Release();
  217. if( NULL != pstg )
  218. pstg->Release();
  219. return( hr );
  220. } // StgCreatePropStg()
  221. //+------------------------------------------------------------------
  222. //
  223. // Function: StgOpenPropStg
  224. //
  225. // Synopsis: Given an IStorage or IStream which hold a
  226. // serialized property set, create an
  227. // IPropertyStorage. This is similar to the
  228. // IPropertySetStorage::Open method.
  229. //
  230. // Inputs: [IUnknown*] pUnk
  231. // An IStorage* for non-simple propsets,
  232. // an IStream* for simple. grfFlags is
  233. // used to disambiguate.
  234. // [REFFMTID] fmtid
  235. // The ID of the property set.
  236. // [DWORD] grfFlags
  237. // From the PROPSETFLAG_* enumeration.
  238. // [IPropertySetStorage**] ppPropStg
  239. // The result.
  240. //
  241. // Returns: [HRESULT]
  242. //
  243. // Notes: The caller is responsible for maintaining
  244. // thread-safety between the original
  245. // IStorage/IStream and this IPropertyStorage.
  246. //
  247. //+------------------------------------------------------------------
  248. STDAPI StgOpenPropStg( IUnknown* pUnk,
  249. REFFMTID fmtid,
  250. DWORD grfFlags,
  251. DWORD dwReserved,
  252. IPropertyStorage **ppPropStg)
  253. {
  254. // ------
  255. // Locals
  256. // ------
  257. HRESULT hr;
  258. IStream *pstm = NULL;
  259. IStorage *pstg = NULL;
  260. CPropertyStorage *pPropStg = NULL;
  261. // ----------
  262. // Validation
  263. // ----------
  264. propXTraceStatic( "StgOpenPropStg" );
  265. GEN_VDATEIFACE_LABEL( pUnk, E_INVALIDARG, Exit, hr );
  266. GEN_VDATEREADPTRIN_LABEL(&fmtid, FMTID, E_INVALIDARG, Exit, hr);
  267. // grfFlags is validated by CPropertyStorage
  268. GEN_VDATEPTROUT_LABEL( ppPropStg, IPropertyStorage*, E_INVALIDARG, Exit, hr );
  269. propTraceParameters(( "pUnk=%p, fmtid=%s, grfFlags=%s, dwReserved=0x%x, ppPropStg=%p",
  270. pUnk, static_cast<const char*>(CStringize(fmtid)),
  271. static_cast<const char*>(CStringize(SGrfFlags(grfFlags))),
  272. dwReserved, ppPropStg ));
  273. // -----------------------
  274. // Non-Simple Property Set
  275. // -----------------------
  276. *ppPropStg = NULL;
  277. if( grfFlags & PROPSETFLAG_NONSIMPLE )
  278. {
  279. // Get the IStorage*
  280. hr = pUnk->QueryInterface( IID_IStorage, (void**) &pstg );
  281. if( FAILED(hr) ) goto Exit;
  282. // Create an IPropertyStorage* implementation.
  283. pPropStg = new CPropertyStorage( MAPPED_STREAM_CREATE );
  284. if( NULL == pPropStg )
  285. {
  286. hr = E_OUTOFMEMORY;
  287. goto Exit;
  288. }
  289. // Initialize the IPropertyStorage by reading
  290. // the serialized property set.
  291. hr = pPropStg->Open( pstg, fmtid, grfFlags,
  292. 0 ); // We don't know the grfMode
  293. if( FAILED(hr) ) goto Exit;
  294. } // if( grfFlags & PROPSETFLAG_NONSIMPLE )
  295. // -------------------
  296. // Simple Property Set
  297. // -------------------
  298. else
  299. {
  300. // Get the IStream*
  301. hr = QueryForIStream( pUnk, &pstm );
  302. if( FAILED(hr) ) goto Exit;
  303. // Create an IPropertyStorage* implementation.
  304. pPropStg = new CPropertyStorage(MAPPED_STREAM_CREATE );
  305. if( NULL == pPropStg )
  306. {
  307. hr = E_OUTOFMEMORY;
  308. goto Exit;
  309. }
  310. // Initialize the IPropertyStorage by reading
  311. // the serialized property set (the CPropertyStorage
  312. // is responsible for seeking to the stream start).
  313. hr = pPropStg->Open( pstm, fmtid, grfFlags,
  314. 0, // We don't know the grfMode
  315. FALSE ); // Not deleting
  316. if( FAILED(hr) ) goto Exit;
  317. } // if( grfFlags & PROPSETFLAG_NONSIMPLE ) ... else
  318. // ----
  319. // Exit
  320. // ----
  321. *ppPropStg = static_cast<IPropertyStorage*>(pPropStg);
  322. pPropStg = NULL;
  323. Exit:
  324. #if DBG
  325. if( FAILED(hr) )
  326. {
  327. propDbg((DEB_ERROR, "StgOpenPropStg returns %08X\n", hr ));
  328. }
  329. #endif
  330. if( NULL != pPropStg )
  331. delete pPropStg;
  332. if( NULL != pstm )
  333. pstm->Release();
  334. if( NULL != pstg )
  335. pstg->Release();
  336. return( hr );
  337. } // StgOpenPropStg()
  338. //+------------------------------------------------------------------
  339. //
  340. // Function: StgCreatePropSetStg
  341. //
  342. // Synopsis: Given an IStorage, create an IPropertySetStorage.
  343. // This is similar to QI-ing a DocFile IStorage for
  344. // the IPropertySetStorage interface.
  345. //
  346. // Inputs: [IStorage*] pStorage
  347. // Will be held by the propsetstg and used
  348. // for create/open.
  349. // [IPropertySetStorage**] ppPropSetStg
  350. // Receives the result.
  351. //
  352. // Returns: [HRESULT]
  353. //
  354. // Notes: The caller is responsible for maintaining
  355. // thread-safety between the original
  356. // IStorage and this IPropertySetStorage.
  357. //
  358. //+------------------------------------------------------------------
  359. STDAPI
  360. StgCreatePropSetStg( IStorage *pStorage,
  361. DWORD dwReserved,
  362. IPropertySetStorage **ppPropSetStg)
  363. {
  364. HRESULT hr = S_OK;
  365. CPropertySetStorage *pPropSetStg = NULL;
  366. // Validation
  367. propXTraceStatic( "StgCreatePropSetStg" );
  368. GEN_VDATEIFACE_LABEL( pStorage, E_INVALIDARG, Exit, hr );
  369. GEN_VDATEPTROUT_LABEL( ppPropSetStg, IPropertySetStorage*, E_INVALIDARG, Exit, hr );
  370. propTraceParameters(( "pStorage=%p, dwReserved=0x%x, ppPropSetStg=%p",
  371. pStorage, dwReserved, ppPropSetStg ));
  372. // Create the IPropertySetStorage implementation.
  373. pPropSetStg = new CPropertySetStorage( MAPPED_STREAM_CREATE );
  374. if( NULL == pPropSetStg )
  375. {
  376. hr = E_OUTOFMEMORY;
  377. goto Exit;
  378. }
  379. // Pass the caller-provided storage into the CPropertySetStorage
  380. pPropSetStg->Init( pStorage, /*IBlockingLock*/ NULL,
  381. TRUE ); // fControlLifetime (=> addref)
  382. // ----
  383. // Exit
  384. // ----
  385. hr = S_OK;
  386. *ppPropSetStg = static_cast<IPropertySetStorage*>(pPropSetStg);
  387. pPropSetStg = NULL;
  388. Exit:
  389. RELEASE_INTERFACE(pPropSetStg);
  390. if( FAILED(hr) )
  391. propDbg((DEB_ERROR, "StgCreatePropSetStg() returns %08X\n", hr ));
  392. return( hr );
  393. } // StgCreatePropSetStg()
  394. //+----------------------------------------------------------------------------
  395. //
  396. // Function: FmtIdToPropStgName
  397. //
  398. // Synopsis: This function maps a property set's FMTID to the name of
  399. // the Stream or Storage which contains it. This name
  400. // is 27 characters (including the terminator).
  401. //
  402. // Inputs: [const FMTID*] pfmtid (in)
  403. // The FMTID of the property set.
  404. // [LPOLESTR] oszName (out)
  405. // The name of the Property Set's Stream/Storage
  406. //
  407. // Returns: [HRESULT] S_OK or E_INVALIDARG
  408. //
  409. //+----------------------------------------------------------------------------
  410. STDAPI
  411. FmtIdToPropStgName( const FMTID *pfmtid, LPOLESTR oszName )
  412. {
  413. HRESULT hr = S_OK;
  414. // Validate Inputs
  415. propXTraceStatic( "FmtIdToPropStgName" );
  416. GEN_VDATEREADPTRIN_LABEL(pfmtid, FMTID, E_INVALIDARG, Exit, hr);
  417. VDATESIZEPTROUT_LABEL(oszName,
  418. sizeof(OLECHAR) * (CCH_MAX_PROPSTG_NAME+1),
  419. Exit, hr);
  420. propTraceParameters(( "fmtid=%s, oszName=%p",
  421. static_cast<const char*>(CStringize(*pfmtid)), oszName ));
  422. // Make the Conversion
  423. PrGuidToPropertySetName( pfmtid, oszName );
  424. // Exit
  425. Exit:
  426. if( FAILED(hr) )
  427. {
  428. propDbg((DEB_ERROR, "FmtIdToPropStgName returns %08X\n", hr ));
  429. }
  430. return( hr );
  431. } // FmtIdToPropStgName()
  432. //+----------------------------------------------------------------------------
  433. //
  434. // Function: PropStgNameToFmtId
  435. //
  436. // Synopsis: This function maps a property set's Stream/Storage name
  437. // to its FMTID.
  438. //
  439. // Inputs: [const LPOLESTR] oszName (in)
  440. // The name of the Property Set's Stream/Storage
  441. // [FMTID*] pfmtid (out)
  442. // The FMTID of the property set.
  443. //
  444. //
  445. // Returns: [HRESULT] S_OK or E_INVALIDARG
  446. //
  447. //+----------------------------------------------------------------------------
  448. STDAPI
  449. PropStgNameToFmtId( const LPOLESTR oszName, FMTID *pfmtid )
  450. {
  451. HRESULT hr = S_OK;
  452. // Validate Inputs
  453. propXTraceStatic( "PropStgNameToFmtId" );
  454. GEN_VDATEPTROUT_LABEL(pfmtid, FMTID, E_INVALIDARG, Exit, hr);
  455. propTraceParameters(( "oszName=%p, *pfmtid=%s", oszName,
  456. static_cast<const char*>(CStringize(*pfmtid)) ));
  457. #ifdef OLE2ANSI
  458. if( FAILED(hr = ValidateNameA(oszName, CCH_MAX_PROPSTG_NAME )))
  459. goto Exit;
  460. #else
  461. if( FAILED(hr = ValidateNameW(oszName, CCH_MAX_PROPSTG_NAME )))
  462. goto Exit;
  463. #endif
  464. // Make the Conversion, passing in the name and its character-length
  465. // (not including the null-terminator).
  466. PrPropertySetNameToGuid( ocslen(oszName), oszName, pfmtid );
  467. // Exit
  468. Exit:
  469. propDbg(( DbgFlag(hr,DEB_TRACE), "PropStgNameToFmtId returns %08x", hr ));
  470. return( hr );
  471. } // PropStgNameToFmtId()
  472. //+----------------------------------------------------------------------------
  473. //
  474. // Function: CreateOrOpenDocfileOnHandle
  475. //
  476. // Create or open a Docfile IStorage (or QI-able interface) on a given
  477. // handle.
  478. //
  479. //+----------------------------------------------------------------------------
  480. CreateOrOpenDocfileOnHandle( IN BOOL fCreate,
  481. IN DWORD grfMode,
  482. IN HANDLE *phStream,
  483. IN REFIID riid,
  484. OUT void ** ppObjectOpen)
  485. {
  486. HRESULT hr = S_OK;
  487. NTSTATUS status = STATUS_SUCCESS;
  488. CNtfsStream *pnffstm = NULL;
  489. CNFFTreeMutex *pmutex = NULL;
  490. IStorage *pstg = NULL;
  491. propITraceStatic( "CreateOrOpenDocfileOnHandle" );
  492. // --------------------
  493. // Create an ILockBytes
  494. // --------------------
  495. // Instantiate a mutex
  496. pmutex = new CNFFTreeMutex();
  497. if( NULL == pmutex )
  498. {
  499. hr = E_OUTOFMEMORY;
  500. goto Exit;
  501. }
  502. hr = pmutex->Init();
  503. if ( FAILED(hr) ) goto Exit;
  504. // Use the mutex to instantiate an NFF stream object
  505. pnffstm = new CNtfsStream( NULL, pmutex );
  506. if( NULL == pnffstm )
  507. {
  508. hr = E_OUTOFMEMORY;
  509. goto Exit;
  510. }
  511. // Put the stream handle and grfMode into the NFF stream object.
  512. // We now have our ILockBytes implementation for the given handle.
  513. hr = pnffstm->Init( *phStream, grfMode, NULL, NULL );
  514. if( FAILED(hr) ) goto Exit;
  515. *phStream = INVALID_HANDLE_VALUE;
  516. // ----------------
  517. // Open the Storage
  518. // ----------------
  519. if( fCreate )
  520. {
  521. hr = StgCreateDocfileOnILockBytes( pnffstm, grfMode, 0, &pstg );
  522. }
  523. else
  524. {
  525. hr = StgOpenStorageOnILockBytes( pnffstm, NULL, grfMode, NULL, 0, &pstg );
  526. // STG_E_INVALIDHEADER in some paths of the above call gets converted into
  527. // STG_E_FILEALREADYEXISTS, which doesn't make a whole lot of sense from
  528. // from our point of view (we already knew it existed, we wanted to open it). So,
  529. // translate it back.
  530. if( STG_E_FILEALREADYEXISTS == hr )
  531. hr = STG_E_INVALIDHEADER;
  532. }
  533. if( FAILED(hr) ) goto Exit;
  534. // QI for the caller-requested IID
  535. hr = pstg->QueryInterface( riid, ppObjectOpen );
  536. if( FAILED(hr) ) goto Exit;
  537. hr = S_OK;
  538. Exit:
  539. RELEASE_INTERFACE(pnffstm);
  540. RELEASE_INTERFACE(pstg);
  541. RELEASE_INTERFACE(pmutex);
  542. return( hr );
  543. }
  544. //+----------------------------------------------------------------------------
  545. //
  546. // CreateOrOpenStorageOnHandle
  547. // StgCreateStorageOnHandle
  548. // StgOpenStorageOnHandle
  549. //
  550. // Given a handle, create or open a storage.
  551. // The caller-provided handle is duplicated.
  552. //
  553. //+----------------------------------------------------------------------------
  554. CreateOrOpenStorageOnHandle( IN BOOL fCreate,
  555. IN DWORD grfMode,
  556. IN DWORD stgfmt,
  557. IN HANDLE hStream,
  558. IN REFIID riid,
  559. OUT void ** ppObjectOpen)
  560. {
  561. HRESULT hr = S_OK;
  562. HANDLE hStreamInternal = INVALID_HANDLE_VALUE;
  563. NTSTATUS status = STATUS_SUCCESS;
  564. BOOL fIsStorageFile = FALSE;
  565. OVERLAPPED olpTemp;
  566. propXTraceStatic( "CreateOrOpenStorageOnHandle" );
  567. ZeroMemory( &olpTemp, sizeof(OVERLAPPED) );
  568. propTraceParameters(( "fCreate=%s, grfMode=%s, stgfmt=0x%x, hStream=%p, riid=%s, ppObjectOpen=%p",
  569. fCreate?"TRUE":"FALSE",
  570. static_cast<const char*>(CStringize(SGrfMode(grfMode))),
  571. stgfmt, hStream,
  572. static_cast<const char*>(CStringize(riid)), ppObjectOpen ));
  573. hr = VerifyPerms (grfMode, TRUE);
  574. if (FAILED(hr))
  575. return hr;
  576. // Make a copy of the handle so that the caller can still call
  577. // CloseHandle.
  578. if( !DuplicateHandle( GetCurrentProcess(), hStream,
  579. GetCurrentProcess(), &hStreamInternal,
  580. 0, // dwDesiredAccess, ignored because of DUPLICATE_SAME_ACCESS below
  581. FALSE, // bInheritHandle
  582. DUPLICATE_SAME_ACCESS ))
  583. {
  584. hr = HRESULT_FROM_WIN32(GetLastError());
  585. hStreamInternal = INVALID_HANDLE_VALUE;
  586. goto Exit;
  587. }
  588. // Set up an overlapped structure in preparation to call
  589. // StgIsStorageFileHandle
  590. olpTemp.hEvent = CreateEvent( NULL, // Security Attributes.
  591. TRUE, // Manual Reset Flag.
  592. FALSE, // Inital State = Signaled, Flag.
  593. NULL ); // Name
  594. if( NULL == olpTemp.hEvent )
  595. {
  596. hr = HRESULT_FROM_WIN32( GetLastError() );
  597. goto Exit;
  598. }
  599. // Does this handle represent a docfile?
  600. hr = StgIsStorageFileHandle( hStreamInternal, &olpTemp );
  601. if( HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION) == hr )
  602. {
  603. // This is the error we get when the handle is to a directory.
  604. // See if that's really the case, and if so assume that this isn't
  605. // a docfile.
  606. // Do not move this in StgIsStorageFileHandle for compatibility
  607. BY_HANDLE_FILE_INFORMATION ByHandleFileInformation;
  608. if( GetFileInformationByHandle( hStreamInternal, &ByHandleFileInformation ))
  609. {
  610. if( FILE_ATTRIBUTE_DIRECTORY & ByHandleFileInformation.dwFileAttributes )
  611. hr = S_FALSE;
  612. }
  613. }
  614. if( FAILED(hr) ) goto Exit;
  615. if( S_OK == hr )
  616. fIsStorageFile = TRUE;
  617. else
  618. DfpAssert( S_FALSE == hr );
  619. // Is this the create of a docfile/storage, or the open of an
  620. // existing docfile?
  621. if( fCreate && ( STGFMT_DOCFILE == stgfmt || STGFMT_STORAGE == stgfmt )
  622. ||
  623. !fCreate && fIsStorageFile )
  624. {
  625. // In the open path, the caller must request
  626. // either any, docfile, or storage.
  627. if( !fCreate
  628. &&
  629. STGFMT_ANY != stgfmt
  630. &&
  631. STGFMT_DOCFILE != stgfmt
  632. &&
  633. STGFMT_STORAGE != stgfmt )
  634. {
  635. hr = STG_E_INVALIDPARAMETER;
  636. goto Exit;
  637. }
  638. // Create/Open the docfile. hStreamInternal may be changed
  639. // to INVALID_HANDLE_VALUE.
  640. hr = CreateOrOpenDocfileOnHandle( fCreate, grfMode, &hStreamInternal,
  641. riid, ppObjectOpen );
  642. if( FAILED(hr) ) goto Exit;
  643. }
  644. // Otherwise, this should be the create/open of an NFF
  645. else if( fCreate && STGFMT_FILE == stgfmt
  646. ||
  647. !fCreate && !fIsStorageFile )
  648. {
  649. // In the open path, the caller must request either any or file.
  650. if( !fCreate && STGFMT_ANY != stgfmt && STGFMT_FILE != stgfmt )
  651. {
  652. hr = STG_E_INVALIDPARAMETER;
  653. goto Exit;
  654. }
  655. // Instantiate the NFF IStorage.
  656. hr = NFFOpenOnHandle( fCreate, grfMode, STGFMT_FILE,
  657. &hStreamInternal, riid, ppObjectOpen );
  658. if( FAILED(hr) ) goto Exit;
  659. }
  660. else
  661. {
  662. hr = STG_E_INVALIDPARAMETER;
  663. goto Exit;
  664. }
  665. hr = S_OK;
  666. Exit:
  667. if( INVALID_HANDLE_VALUE != hStreamInternal )
  668. CloseHandle( hStreamInternal );
  669. if( NULL != olpTemp.hEvent )
  670. CloseHandle( olpTemp.hEvent );
  671. if( STG_E_INVALIDFUNCTION == hr // This happens e.g. when we try to get NFF propsets on FAT
  672. || // This happens when we try to read a FAT directory file
  673. HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) == hr )
  674. {
  675. propSuppressExitErrors();
  676. }
  677. return( hr );
  678. } // CreateOrOpenStorageOnHandle
  679. STDAPI
  680. StgCreateStorageOnHandle( IN HANDLE hStream,
  681. IN DWORD grfMode,
  682. IN DWORD stgfmt,
  683. IN void *reserved1,
  684. IN void *reserved2,
  685. IN REFIID riid,
  686. OUT void **ppObjectOpen )
  687. {
  688. return( CreateOrOpenStorageOnHandle( TRUE, grfMode, stgfmt, hStream, riid, ppObjectOpen ));
  689. }
  690. STDAPI
  691. StgOpenStorageOnHandle( IN HANDLE hStream,
  692. IN DWORD grfMode,
  693. IN void *reserved1,
  694. IN void *reserved2,
  695. IN REFIID riid,
  696. OUT void **ppObjectOpen )
  697. {
  698. return( CreateOrOpenStorageOnHandle( FALSE, grfMode, STGFMT_ANY, hStream, riid, ppObjectOpen ));
  699. }