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.

1401 lines
45 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1994-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddstream.cpp
  6. * Content: DirectDraw surface file I/O
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 30-sep-97 jeffno Original implementation
  11. *
  12. ***************************************************************************/
  13. extern "C"
  14. {
  15. #include "ddrawpr.h"
  16. }
  17. #include <ImgUtil.H>
  18. #include "decoder.h"
  19. /*
  20. * This routine takes a source surface freshly loaded from some file, and transfers
  21. * the bits to some target surface. Palette will be transferred also, if set.
  22. * dwFlags are as defined for CreateSurfaceFromFile.
  23. */
  24. HRESULT TransferBitsToTarget(
  25. LPDIRECTDRAWSURFACE lpDDSource,
  26. LPDIRECTDRAWSURFACE4 lpDDSTarget,
  27. LPDDSURFACEDESC2 pDDSD,
  28. DWORD dwFlags)
  29. {
  30. HRESULT hr =DD_OK;
  31. DDSURFACEDESC ddsd;
  32. RECT rDest;
  33. LPDIRECTDRAWSURFACE4 lpDDSource4;
  34. /*
  35. * We need to transfer a palette to the target surface if required.
  36. * Don't do it if the app doesn't want a palette. Don't do it if there's
  37. * no palette in the working surface.
  38. */
  39. if ( (dwFlags & DDLS_IGNOREPALETTE) == 0)
  40. {
  41. LPDIRECTDRAWPALETTE pPal = NULL;
  42. hr = lpDDSource->GetPalette(&pPal);
  43. if (SUCCEEDED(hr))
  44. {
  45. /*
  46. * If the target surface isn't palettized, this will fail.
  47. * That's OK.
  48. */
  49. lpDDSTarget->SetPalette((LPDIRECTDRAWPALETTE2)pPal);
  50. pPal->Release();
  51. }
  52. }
  53. /*
  54. * If we aren't stretching or we're maintaining aspect ratio, then there's the possibility
  55. * of some of the target surface's pixels not being filled. Fill them with
  56. * phys color zero.
  57. * I threw in bilinear as well, because the current definition samples the target
  58. * even when full stretch.
  59. */
  60. if ( (dwFlags & (DDLS_MAINTAINASPECTRATIO|DDLS_BILINEARFILTER)) || ((dwFlags & DDLS_STRETCHTOFIT)==0) )
  61. {
  62. DDBLTFX ddbltfx;
  63. ddbltfx.dwSize = sizeof(ddbltfx);
  64. ddbltfx.dwFillColor = 0;
  65. /*
  66. * Ignore the error code. The nicest thing is to keep going anyway
  67. */
  68. lpDDSTarget->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx);
  69. }
  70. /*
  71. * Note that we always shrink the image to fit if necessary.
  72. * We never take the smaller subrect of the source when the passed-in
  73. * size is smaller than the image
  74. */
  75. /*
  76. * Set dest rect to the size of the image
  77. * Calling a v1 surface, so better pass proper size.
  78. */
  79. ddsd.dwSize =sizeof(DDSURFACEDESC);
  80. hr = lpDDSource->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
  81. DDASSERT(SUCCEEDED(hr));
  82. SetRect(&rDest,0,0,ddsd.dwWidth,ddsd.dwHeight);
  83. if (dwFlags & DDLS_STRETCHTOFIT)
  84. {
  85. /*
  86. * Override the dest rect to the size passed in
  87. */
  88. SetRect(&rDest,0,0,pDDSD->dwWidth,pDDSD->dwHeight);
  89. if (dwFlags & DDLS_MAINTAINASPECTRATIO)
  90. {
  91. /*
  92. * Back off if necessary to maintain aspect ratio.
  93. * This calculates the dest width we need to maintain AR
  94. */
  95. DWORD dwProperWidth = ddsd.dwWidth*pDDSD->dwHeight/ddsd.dwHeight;
  96. if (dwProperWidth > pDDSD->dwWidth)
  97. {
  98. SetRect(&rDest,0,0,pDDSD->dwWidth,ddsd.dwHeight*pDDSD->dwWidth/ddsd.dwWidth);
  99. }
  100. else if (dwProperWidth < pDDSD->dwWidth)
  101. {
  102. SetRect(&rDest,0,0,dwProperWidth,pDDSD->dwHeight);
  103. }
  104. }
  105. DDASSERT(rDest.right <= (int) pDDSD->dwWidth);
  106. DDASSERT(rDest.bottom <= (int) pDDSD->dwHeight);
  107. }
  108. else
  109. {
  110. /*
  111. * If we're shrinking, we'll just stretch anyway. The alternative is to take
  112. * a smaller central subrect of the source image. That seems kinda useless.
  113. */
  114. if (pDDSD)
  115. {
  116. if (pDDSD->dwWidth < ddsd.dwWidth)
  117. {
  118. rDest.left=0;
  119. rDest.right = pDDSD->dwWidth;
  120. }
  121. if (pDDSD->dwHeight < ddsd.dwHeight)
  122. {
  123. rDest.top=0;
  124. rDest.bottom = pDDSD->dwHeight;
  125. }
  126. }
  127. }
  128. /*
  129. * Add space above/below to center the image in the dest
  130. */
  131. if (dwFlags & DDLS_CENTER)
  132. {
  133. OffsetRect(&rDest, (pDDSD->dwWidth - rDest.right)/2, (pDDSD->dwHeight - rDest.bottom)/2);
  134. }
  135. hr = lpDDSource->QueryInterface(IID_IDirectDrawSurface4, (void**) &lpDDSource4);
  136. if (SUCCEEDED(hr))
  137. {
  138. hr = lpDDSTarget->AlphaBlt(
  139. &rDest,
  140. lpDDSource4,
  141. NULL,
  142. ((dwFlags & DDLS_BILINEARFILTER)?DDABLT_BILINEARFILTER:0)|DDABLT_WAIT,
  143. NULL);
  144. if (FAILED(hr))
  145. {
  146. /*
  147. * ATTENTION: Sort of. At the moment, AlphaBlt refuses to blt to a palette-indexed surface.
  148. * We'll just try blt as a backup
  149. */
  150. hr = lpDDSTarget->Blt(
  151. &rDest,
  152. lpDDSource4,
  153. NULL,
  154. DDBLT_WAIT,
  155. NULL);
  156. }
  157. if (FAILED(hr))
  158. {
  159. DPF_ERR("Could not blt from temporary surface to target surface!");
  160. }
  161. lpDDSource4->Release();
  162. }
  163. return hr;
  164. }
  165. HRESULT CreateOrLoadSurfaceFromStream( LPDIRECTDRAW4 lpDD, IStream *pSource, LPDDSURFACEDESC2 pDDSD, DWORD dwFlags, LPDIRECTDRAWSURFACE4 * ppSurface, IUnknown * pUnkOuter)
  166. {
  167. LPDDRAWI_DIRECTDRAW_INT this_int;
  168. // validate arguments
  169. TRY
  170. {
  171. if( !VALID_PTR_PTR(ppSurface ) )
  172. {
  173. DPF_ERR("You must supply a valid surface pointer");
  174. return DDERR_INVALIDPARAMS;
  175. }
  176. *ppSurface = NULL;
  177. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  178. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  179. {
  180. DPF_ERR("Bad DirectDraw pointer");
  181. return DDERR_INVALIDOBJECT;
  182. }
  183. if( !pSource )
  184. {
  185. DPF_ERR("You must supply a valid stream pointer");
  186. return DDERR_INVALIDPARAMS;
  187. }
  188. /*
  189. * Validate flags
  190. */
  191. if (dwFlags & ~DDLS_VALID)
  192. {
  193. DPF_ERR("Invalid flags");
  194. return DDERR_INVALIDPARAMS;
  195. }
  196. if (dwFlags & ~DDLS_VALID)
  197. {
  198. DPF_ERR("Invalid flags");
  199. return DDERR_INVALIDPARAMS;
  200. }
  201. //ATTENTION: DDLS_MERGEPALETTE isn't implemented. Implement it when the palette 2 interface goes in.
  202. if ( (dwFlags & (DDLS_IGNOREPALETTE|DDLS_MERGEPALETTE)) == (DDLS_IGNOREPALETTE|DDLS_MERGEPALETTE) )
  203. {
  204. DPF_ERR("Can only specify one of DDLS_IGNOREPALETTE or DDLS_MERGEPALETTE");
  205. return DDERR_INVALIDPARAMS;
  206. }
  207. if ( (dwFlags & DDLS_STRETCHTOFIT) || (dwFlags & DDLS_CENTER) )
  208. {
  209. if (!pDDSD)
  210. {
  211. DPF_ERR("Can't specify DDLS_STRETCHTOFIT or DDLS_CENTER without a DDSURFACEDESC2 with valid dwWidth and dwHeight");
  212. return DDERR_INVALIDPARAMS;
  213. }
  214. if ( ( (pDDSD->dwFlags & (DDSD_WIDTH|DDSD_HEIGHT)) == 0) || !pDDSD->dwWidth || !pDDSD->dwHeight )
  215. {
  216. DPF_ERR("Can't specify DDLS_STRETCHTOFIT or DDLS_CENTER without a DDSURFACEDESC2 with valid dwWidth and dwHeight");
  217. return DDERR_INVALIDPARAMS;
  218. }
  219. }
  220. if (! (dwFlags & DDLS_STRETCHTOFIT) )
  221. {
  222. if (dwFlags & (DDLS_BILINEARFILTER|DDLS_MAINTAINASPECTRATIO))
  223. {
  224. DPF_ERR("DDLS_STRETCHTOFIT required for DDLS_BILINEARFILTER or DDLS_MAINTAINASPECTRATIO");
  225. return DDERR_INVALIDPARAMS;
  226. }
  227. }
  228. }
  229. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  230. {
  231. DPF_ERR( "Exception encountered validating parameters" );
  232. return DDERR_INVALIDPARAMS;
  233. }
  234. HRESULT hr = DD_OK;
  235. FILTERINFO ImgInfo;
  236. CImageDecodeEventSink EventSink;
  237. ZeroMemory(&ImgInfo, sizeof(ImgInfo));
  238. /*
  239. * Default to device's bit depth
  240. * This is no longer necessary. We always create a staging surface in the filter's
  241. * desired format.
  242. */
  243. //ImgInfo._colorMode = this_int->lpLcl->lpGbl->vmiData.ddpfDisplay.dwRGBBitCount;
  244. EventSink.Init(&ImgInfo);
  245. typedef HRESULT (*funcptr)(IStream*, IMapMIMEToCLSID*, IImageDecodeEventSink*);
  246. funcptr pfnDecodeImage;
  247. //EventSink->AddRef();
  248. EventSink.SetDDraw( lpDD );
  249. HINSTANCE hLibInst = LoadLibrary( "ImgUtil.dll" );
  250. if( hLibInst )
  251. {
  252. pfnDecodeImage = (funcptr) GetProcAddress(hLibInst, "DecodeImage");
  253. if( pfnDecodeImage )
  254. {
  255. hr = (*pfnDecodeImage)( pSource, NULL, (IImageDecodeEventSink *)&EventSink );
  256. }
  257. else
  258. {
  259. DPF_ERR( "GetProcAddress failure for DecodeImage in ImgUtil.dll" );
  260. hr = DDERR_UNSUPPORTED;
  261. }
  262. FreeLibrary( hLibInst );
  263. }
  264. else
  265. {
  266. DPF_ERR( "LoadLibrary failure on ImgUtil.dll" );
  267. hr = DDERR_UNSUPPORTED;
  268. }
  269. if( SUCCEEDED( hr ) )
  270. {
  271. LPDIRECTDRAWSURFACE lpDDS = EventSink.m_pFilter->m_pDDrawSurface;
  272. if (lpDDS)
  273. {
  274. DDSURFACEDESC2 ddsd;
  275. DDSURFACEDESC ddsdWorking;
  276. ZeroMemory(&ddsdWorking,sizeof(ddsdWorking));
  277. ddsdWorking.dwSize = sizeof(ddsdWorking);
  278. ZeroMemory(&ddsd,sizeof(ddsd));
  279. ddsd.dwSize = sizeof(ddsd);
  280. /*
  281. * The decode succeeded, so now marshal the bits into the requested surface type
  282. */
  283. if (pDDSD)
  284. {
  285. /*
  286. * App cares about at least some of the parameters of the target surface.
  287. * We'll take what they give us and potentially fill in some more.
  288. */
  289. ddsd = *pDDSD;
  290. }
  291. /*
  292. * We may need some data from the original loaded surface.
  293. * Ignore the return code. It's better just to carry on.
  294. */
  295. hr = lpDDS->GetSurfaceDesc(&ddsdWorking);
  296. if ( (ddsd.dwFlags & (DDSD_WIDTH|DDSD_HEIGHT)) == 0 )
  297. {
  298. /*
  299. * App doesn't care what size the surface is, so we'll setup
  300. * the size for them.
  301. */
  302. ddsd.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
  303. ddsd.dwWidth = ddsdWorking.dwWidth;
  304. ddsd.dwHeight = ddsdWorking.dwHeight;
  305. }
  306. if ( (ddsd.dwFlags & DDSD_CAPS) == 0)
  307. {
  308. /*
  309. * App doesn't care about surface caps. We'll give them offscreen plain
  310. */
  311. ddsd.dwFlags |= DDSD_CAPS;
  312. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  313. ddsd.ddsCaps.dwCaps2 = 0;
  314. ddsd.ddsCaps.dwCaps3 = 0;
  315. ddsd.ddsCaps.dwCaps4 = 0;
  316. }
  317. if ( (ddsd.dwFlags & DDSD_PIXELFORMAT) == 0)
  318. {
  319. /*
  320. * If the app didn't specify a pixel format, then we will return
  321. * the original pixel format as decoded by the decode filter.
  322. * This should be a close approximation of the format of the original
  323. * file. Note that this stipulation could mean that the CreateSurface
  324. * will dump the surface in sysmem. It's good for our routine to
  325. * have the same semantics as CreateSurface.
  326. */
  327. ddsd.dwFlags |= DDSD_PIXELFORMAT;
  328. ddsd.ddpfPixelFormat = ddsdWorking.ddpfPixelFormat;
  329. }
  330. /*
  331. * Could we avoid creating a target surface and doing the blt altogether?
  332. * It wouldn't really buy much. If the app didn't specify a memory type, then
  333. * we probe to see if we can create a vidmem version by calling createsurface.
  334. * If we get a vidmem back, then we copy the bits and use it. If we get a sysmem
  335. * back then we could optimize that case by not doing the blt to get the
  336. * data into the target surface and returning the working surface directly.
  337. * One tiny disadvantage would be that the target surface would be explicit
  338. * sysmem, whereas the normal createsurface semantics would make that surface
  339. * an implicit sysmem surface.
  340. */
  341. /*
  342. * We don't do the create surface if a surface is passed in (as denoted
  343. * by *ppSurface being non-null)
  344. */
  345. if(SUCCEEDED(hr) && (NULL == (*ppSurface)) )
  346. {
  347. hr = lpDD->CreateSurface(&ddsd, ppSurface, pUnkOuter);
  348. }
  349. /*
  350. * Now blt the working surface to whatever the target was supposed to be...
  351. * Note this routine may transfer a reference to a palette as well.
  352. */
  353. if(SUCCEEDED(hr))
  354. {
  355. hr = TransferBitsToTarget(lpDDS, *ppSurface, pDDSD, dwFlags);
  356. }
  357. else
  358. {
  359. DPF_ERR("Create surface failed!");
  360. }
  361. }
  362. else
  363. {
  364. /*
  365. * Decode returned a NULL ddraw surface, even tho DecodeImage returned ok
  366. */
  367. hr = DDERR_INVALIDSTREAM;
  368. }
  369. }
  370. // pEventSink->Release();
  371. return hr;
  372. } /* DD_CreateSurfaceFromFile */
  373. extern "C" HRESULT DDAPI DD_CreateSurfaceFromStream(
  374. LPDIRECTDRAW4 lpDD,
  375. IStream *pSource,
  376. LPDDSURFACEDESC2 pDDSD,
  377. DWORD dwFlags,
  378. LPDIRECTDRAWSURFACE4 * ppSurface,
  379. IUnknown * pUnkOuter)
  380. {
  381. *ppSurface = 0;
  382. return CreateOrLoadSurfaceFromStream(lpDD, pSource, pDDSD, dwFlags, ppSurface, pUnkOuter);
  383. }
  384. extern "C" HRESULT DDAPI DD_CreateSurfaceFromFile( LPDIRECTDRAW4 lpDD, BSTR DisplayName, LPDDSURFACEDESC2 pDDSD, DWORD dwFlags, LPDIRECTDRAWSURFACE4 * ppSurface, IUnknown * pUnkOuter)
  385. {
  386. lpDD;
  387. pDDSD;
  388. pUnkOuter;
  389. // validate arguments
  390. if( !DisplayName || !ppSurface )
  391. {
  392. DPF_ERR("You must supply a valid filename and surface pointer");
  393. return E_POINTER;
  394. }
  395. if (FAILED(CoInitialize(NULL)))
  396. {
  397. DPF_ERR("Failed CoInitialize");
  398. return DDERR_UNSUPPORTED;
  399. }
  400. IMoniker *pmk;
  401. IBindCtx *pbctx;
  402. IStream *pStream;
  403. HRESULT hr = CreateURLMoniker(NULL, DisplayName, &pmk);
  404. if( SUCCEEDED( hr ) )
  405. {
  406. hr = CreateBindCtx(0, &pbctx);
  407. if( SUCCEEDED( hr ) )
  408. {
  409. hr = pmk->BindToStorage(pbctx, NULL, IID_IStream, (void **)&pStream);
  410. if( SUCCEEDED( hr ) )
  411. {
  412. hr = DD_CreateSurfaceFromStream( lpDD, pStream, pDDSD, dwFlags, ppSurface ,pUnkOuter );
  413. pStream->Release();
  414. }
  415. else
  416. {
  417. DPF_ERR("Could not BindToStorage");
  418. if (hr == INET_E_UNKNOWN_PROTOCOL)
  419. DPF_ERR("Fully qualified path name is required");
  420. if (hr == INET_E_RESOURCE_NOT_FOUND)
  421. DPF_ERR("Resource not found. Fully qualified path name is required");
  422. }
  423. pbctx->Release();
  424. }
  425. else
  426. {
  427. DPF_ERR("Could not CreateBindCtx");
  428. }
  429. pmk->Release();
  430. }
  431. else
  432. {
  433. DPF_ERR("Could not CreateURLMoniker");
  434. }
  435. return hr;
  436. return DD_OK;
  437. }
  438. /*
  439. * Persistence interfaces
  440. * These methods read and write streams of the following form:
  441. *
  442. * Element Description
  443. * -------------------------------------------------------------------------------------------------
  444. * Type Name
  445. *
  446. * GUID tag GUID_DirectDrawSurfaceStream. Tags the stream as a surface stream
  447. * DWORD dwWidth Width in pixels of the image data
  448. * DWORD dwHeight Height in pixels of the image data
  449. * DDPIXELFORMAT Format Format of image data
  450. * DWORD dwPaletteCaps Palette caps. Zero if no palette.
  451. * PALETTESTREAM PaletteData This field is only present if the dwPaletteCaps field is non-zero
  452. * GUID CompressionFormat This field is only present if one of the DDPF_OPT flags is specified in Format
  453. * DWORD dwDataSize Number of bytes that follow
  454. * BYTE[] SurfaceData dwDataSize bytes of surface data
  455. * PRIVATEDATA PrivateSurfaceData
  456. *
  457. *
  458. * The PALETTESTREAM stream element has the following format:
  459. *
  460. * Element Description
  461. * -------------------------------------------------------------------------------------------------
  462. * Type Name
  463. * GUID tag GUID_DirectDrawPaletteeStream. Tags the stream as a palette stream
  464. * DWORD dwPaletteFlags Palette flags made up of DDPCAPS bits.
  465. * PALETTEENTRY[] PaletteEntries The number of palette entries specified by the flags in dwPaletteFlags.
  466. * PRIVATEDATA PrivatePaletteData Private palette data.
  467. *
  468. *
  469. * The PRIVATEDATA stream element has the following format:
  470. *
  471. * Element Description
  472. * -------------------------------------------------------------------------------------------------
  473. * Type Name
  474. *
  475. * DWORD dwPrivateDataCount The number of private data blocks which follow
  476. * GUID GUIDTag Tag for this block of private data, as specified by IDDS4:SetClientData
  477. * DWORD dwPrivateSize Number of bytes of private data in this block
  478. * BYTE[] PrivateData dwPrivateSize bytes of private data
  479. *
  480. * Note private data that are of pointer type (i.e. point to a user-allocated data block) will
  481. * NOT be saved by these methods.
  482. *
  483. */
  484. template<class Object> HRESULT InternalReadPrivateData(
  485. IStream * pStrm,
  486. Object * lpObject)
  487. {
  488. HRESULT ddrval;
  489. DWORD dwCount;
  490. ddrval = pStrm->Read((void*) & dwCount, sizeof(DWORD), NULL);
  491. if (FAILED(ddrval))
  492. {
  493. DPF_ERR("Stream read failed on private data count");
  494. return ddrval;
  495. }
  496. for(;dwCount;dwCount--)
  497. {
  498. GUID guid;
  499. DWORD cbData;
  500. LPVOID pData;
  501. ddrval = pStrm->Read((void*) & guid, sizeof(guid), NULL);
  502. if (FAILED(ddrval))
  503. {
  504. DPF_ERR("Stream read failed on private data GUID");
  505. return ddrval;
  506. }
  507. ddrval = pStrm->Read((void*) & cbData, sizeof(cbData), NULL);
  508. if (FAILED(ddrval))
  509. {
  510. DPF_ERR("Stream read failed on private data GUID");
  511. return ddrval;
  512. }
  513. pData = MemAlloc(cbData);
  514. if (pData)
  515. {
  516. ddrval = pStrm->Read((void*) pData, cbData, NULL);
  517. if (FAILED(ddrval))
  518. {
  519. DPF_ERR("Stream read failed on private data GUID");
  520. return ddrval;
  521. }
  522. ddrval = lpObject->SetPrivateData(guid, pData, cbData, 0);
  523. MemFree(pData);
  524. if (FAILED(ddrval))
  525. {
  526. DPF_ERR("Could not set private data");
  527. return ddrval;
  528. }
  529. }
  530. else
  531. {
  532. DPF_ERR("Couln't alloc enough space for private data");
  533. ddrval = DDERR_OUTOFMEMORY;
  534. return ddrval;
  535. }
  536. }
  537. return ddrval;
  538. }
  539. HRESULT myWriteClassStm(IStream * pStrm, LPGUID pGUID)
  540. {
  541. return pStrm->Write(pGUID, sizeof(*pGUID),NULL);
  542. }
  543. HRESULT myReadClassStm(IStream * pStrm, LPGUID pGUID)
  544. {
  545. return pStrm->Read(pGUID, sizeof(*pGUID),NULL);
  546. }
  547. /*
  548. * Be sure to call ENTER_DDRAW before and LEAVE_DDRAW after
  549. * calling this function!
  550. */
  551. HRESULT InternalWritePrivateData(
  552. IStream * pStrm,
  553. LPPRIVATEDATANODE pPrivateDataHead)
  554. {
  555. HRESULT ddrval;
  556. DWORD dwCount = 0;
  557. LPPRIVATEDATANODE pPrivateData = pPrivateDataHead;
  558. while(1)
  559. {
  560. while(pPrivateData)
  561. {
  562. if (pPrivateData->dwFlags == 0)
  563. {
  564. dwCount++;
  565. }
  566. pPrivateData = pPrivateData->pNext;
  567. }
  568. ddrval = pStrm->Write((void*) & dwCount, sizeof(dwCount), NULL);
  569. if (FAILED(ddrval))
  570. {
  571. DPF_ERR("Stream write failed on count of private data");
  572. break;
  573. }
  574. pPrivateData = pPrivateDataHead;
  575. while(pPrivateData)
  576. {
  577. if (pPrivateData->dwFlags == 0)
  578. {
  579. ddrval = myWriteClassStm(pStrm, &(pPrivateData->guid));
  580. if (SUCCEEDED(ddrval))
  581. {
  582. ddrval = pStrm->Write((void*) &(pPrivateData->cbData), sizeof(DWORD), NULL);
  583. if (SUCCEEDED(ddrval))
  584. {
  585. ddrval = pStrm->Write((void*) pPrivateData->pData, pPrivateData->cbData, NULL);
  586. if (FAILED(ddrval))
  587. break;
  588. }
  589. else
  590. break;
  591. }
  592. else
  593. break;
  594. }
  595. pPrivateData = pPrivateData->pNext;
  596. }
  597. break;
  598. }
  599. return ddrval;
  600. }
  601. extern "C" HRESULT DDAPI DD_Surface_Persist_GetClassID(LPDIRECTDRAWSURFACE lpDDS, CLSID * pClassID)
  602. {
  603. TRY
  604. {
  605. memcpy(pClassID, & GUID_DirectDrawSurfaceStream, sizeof(*pClassID));
  606. }
  607. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  608. {
  609. DPF_ERR( "Exception encountered copying GUID" );
  610. return DDERR_INVALIDPARAMS;
  611. }
  612. return DD_OK;
  613. }
  614. extern "C" HRESULT DDAPI DD_Surface_PStream_IsDirty(LPDIRECTDRAWSURFACE lpDDS)
  615. {
  616. LPDDRAWI_DDRAWSURFACE_INT this_int;
  617. LPDDRAWI_DDRAWSURFACE_GBL_MORE this_more;
  618. ENTER_DDRAW();
  619. TRY
  620. {
  621. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDS;
  622. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  623. {
  624. LEAVE_DDRAW();
  625. return DDERR_INVALIDOBJECT;
  626. }
  627. this_more = GET_LPDDRAWSURFACE_GBL_MORE(this_int->lpLcl->lpGbl);
  628. if ( (this_more->dwSaveStamp == 0 ) ||
  629. (this_more->dwContentsStamp != this_more->dwSaveStamp) )
  630. {
  631. LEAVE_DDRAW();
  632. return S_OK;
  633. }
  634. }
  635. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  636. {
  637. DPF_ERR( "Exception encountered checking dirty" );
  638. LEAVE_DDRAW();
  639. return DDERR_INVALIDPARAMS;
  640. }
  641. LEAVE_DDRAW();
  642. return S_FALSE;
  643. }
  644. extern "C" HRESULT DDAPI DD_Surface_PStream_Load(LPDIRECTDRAWSURFACE lpDDS, IStream * pStrm)
  645. {
  646. DDSURFACEDESC2 ddsd;
  647. HRESULT ddrval;
  648. LPDDRAWI_DDRAWSURFACE_INT this_int;
  649. LPDIRECTDRAWSURFACE4 lpDDS1 = NULL;
  650. if (!VALID_PTR(pStrm,sizeof(*pStrm)))
  651. {
  652. DPF_ERR("Bad stream pointer");
  653. return DDERR_INVALIDPARAMS;
  654. }
  655. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDS;
  656. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  657. {
  658. return DDERR_INVALIDOBJECT;
  659. }
  660. /*
  661. * DO THE QI for DDOPTSURF HERE
  662. * and appropriate loading
  663. */
  664. ddrval = lpDDS->QueryInterface(IID_IDirectDrawSurface4, (void**) & lpDDS1);
  665. if (SUCCEEDED(ddrval))
  666. {
  667. ZeroMemory(&ddsd,sizeof(ddsd));
  668. ddsd.dwSize = sizeof(ddsd);
  669. ddrval = lpDDS1->Lock(NULL, &ddsd,DDLOCK_WAIT,NULL);
  670. if (SUCCEEDED(ddrval))
  671. {
  672. if (ddsd.ddpfPixelFormat.dwFlags & (DDPF_FOURCC) )
  673. {
  674. DPF_ERR("The surface isn't streamable. Bad pixel format");
  675. ddrval = DDERR_INVALIDPIXELFORMAT;
  676. }
  677. else
  678. {
  679. while(SUCCEEDED(ddrval)) //a fake try-except while
  680. {
  681. DWORD y;
  682. DWORD dwStreamWidth,dwStreamHeight;
  683. DWORD dwPalCaps;
  684. DDPIXELFORMAT ddpfStream;
  685. CLSID clsid;
  686. /*
  687. * First attempt to read stream format GUID
  688. */
  689. ddrval = myReadClassStm(pStrm, & clsid);
  690. //don't bother to check return code, since the following test will fail in that case
  691. if (!IsEqualGUID(clsid, GUID_DirectDrawSurfaceStream))
  692. {
  693. DPF_ERR("The stream does not contain a directdraw surface stream");
  694. ddrval = DDERR_INVALIDSTREAM;
  695. break;
  696. }
  697. /*
  698. * Get image format from stream
  699. */
  700. ddrval = pStrm->Read((void*) & dwStreamWidth, sizeof(dwStreamWidth), NULL);
  701. if (FAILED(ddrval))
  702. {
  703. DPF_ERR("Stream read failed on width");
  704. break;
  705. }
  706. ddrval = pStrm->Read((void*) & dwStreamHeight, sizeof(dwStreamHeight), NULL);
  707. if (FAILED(ddrval))
  708. {
  709. DPF_ERR("Stream read failed on height");
  710. break;
  711. }
  712. ddrval = pStrm->Read((void*) & ddpfStream, sizeof(ddpfStream), NULL);
  713. if (FAILED(ddrval))
  714. {
  715. DPF_ERR("Stream read failed on pixel format");
  716. break;
  717. }
  718. if (!doPixelFormatsMatch(&ddpfStream, &ddsd.ddpfPixelFormat))
  719. {
  720. DPF_ERR("Stream pixel format does not match that of surface!");
  721. break;
  722. }
  723. ddrval = pStrm->Read((void*) & dwPalCaps, sizeof(dwPalCaps), NULL);
  724. if (FAILED(ddrval))
  725. {
  726. DPF_ERR("Stream read failed on palette caps");
  727. break;
  728. }
  729. /*
  730. * If a palette exists, then either create one or grab the palette from the surface
  731. * and try to stream its data in too.
  732. */
  733. if (dwPalCaps)
  734. {
  735. LPDIRECTDRAWPALETTE2 lpDDPal;
  736. ddrval = lpDDS1->GetPalette(& lpDDPal);
  737. if (ddrval == DDERR_NOPALETTEATTACHED)
  738. {
  739. PALETTEENTRY pe[256]; //just a dummy
  740. ddrval = DD_CreatePalette(
  741. (IDirectDraw*)(this_int->lpLcl->lpGbl) ,
  742. dwPalCaps,
  743. pe,
  744. (LPDIRECTDRAWPALETTE*)&lpDDPal,
  745. NULL);
  746. if (FAILED(ddrval))
  747. {
  748. DPF_ERR("Failed to create palette for surface ");
  749. break;
  750. }
  751. ddrval = lpDDS1->SetPalette(lpDDPal);
  752. if (FAILED(ddrval))
  753. {
  754. lpDDPal->Release();
  755. DPF_ERR("Could not set palette into surface ");
  756. break;
  757. }
  758. }
  759. if (SUCCEEDED(ddrval))
  760. {
  761. /*
  762. * Stream palette from stream
  763. */
  764. ddrval = DD_Palette_PStream_Load( (LPDIRECTDRAWPALETTE) lpDDPal,pStrm);
  765. lpDDPal->Release();
  766. if (FAILED(ddrval))
  767. {
  768. break;
  769. }
  770. }
  771. }
  772. /*
  773. * Here we check for DDPF_OPT... and load a compression GUID if necessary
  774. if (ddpfStream.dwFlags & (DDPF_OPTCOMPRESSED|DDPF_OPTREORDERED) )
  775. {
  776. ddrval = myReadClassStm(pStrm, & clsid);
  777. }
  778. else
  779. //Surface is not compressed, so lock and read....
  780. */
  781. /*
  782. * And finally read the data
  783. */
  784. for (y=0;y<ddsd.dwHeight;y++)
  785. {
  786. ddrval = pStrm->Read((void*) ((DWORD) ddsd.lpSurface + y*ddsd.lPitch),
  787. (ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8),
  788. NULL);
  789. if (FAILED(ddrval))
  790. {
  791. DPF_ERR("Stream read failed");
  792. break;
  793. }
  794. }
  795. /*
  796. * Read private data
  797. */
  798. ddrval = InternalReadPrivateData(pStrm, lpDDS1);
  799. break;
  800. }
  801. } // OK pixel format
  802. lpDDS1->Unlock(NULL);
  803. }//lock succeeded
  804. else
  805. {
  806. DPF_ERR("Could not lock surface");
  807. }
  808. lpDDS1->Release();
  809. }// QIed for ddsurf ok
  810. else
  811. {
  812. DPF_ERR("Bad surface object... can't QI itself for IDirectDrawSurface...");
  813. }
  814. return ddrval;
  815. }
  816. extern "C" HRESULT DDAPI DD_Surface_PStream_Save(LPDIRECTDRAWSURFACE lpDDS, IStream * pStrm, BOOL bClearDirty)
  817. {
  818. DDSURFACEDESC2 ddsd;
  819. HRESULT ddrval;
  820. LPDDRAWI_DDRAWSURFACE_INT this_int;
  821. LPDIRECTDRAWSURFACE4 lpDDS1 = NULL;
  822. if (!VALID_PTR(pStrm,sizeof(*pStrm)))
  823. {
  824. DPF_ERR("Bad stream pointer");
  825. return DDERR_INVALIDPARAMS;
  826. }
  827. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDS;
  828. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  829. {
  830. return DDERR_INVALIDOBJECT;
  831. }
  832. /*
  833. * DO THE QI for DDOPTSURF HERE
  834. */
  835. ddrval = lpDDS->QueryInterface(IID_IDirectDrawSurface4, (void**) & lpDDS1);
  836. if (SUCCEEDED(ddrval))
  837. {
  838. ZeroMemory(&ddsd,sizeof(ddsd));
  839. ddsd.dwSize = sizeof(ddsd);
  840. ddrval = lpDDS1->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
  841. if (SUCCEEDED(ddrval))
  842. {
  843. if (ddsd.ddpfPixelFormat.dwFlags & (DDPF_FOURCC) )
  844. {
  845. DPF_ERR("The surface isn't streamable. Bad pixel format");
  846. ddrval = DDERR_INVALIDPIXELFORMAT;
  847. }
  848. else
  849. {
  850. while(SUCCEEDED(ddrval)) //a fake try-except while
  851. {
  852. LPDIRECTDRAWPALETTE2 lpDDPal;
  853. DWORD y,dwWritten;
  854. /*
  855. * First attempt to read stream format GUID
  856. */
  857. ddrval = myWriteClassStm(pStrm, (LPGUID) & GUID_DirectDrawSurfaceStream);
  858. if (FAILED(ddrval))
  859. {
  860. DPF_ERR("Failed to write stream ID ");
  861. ddrval = DDERR_INVALIDSTREAM;
  862. break;
  863. }
  864. /*
  865. * Get image format from stream
  866. */
  867. ddrval = pStrm->Write((void*) & ddsd.dwWidth, sizeof(DWORD), NULL);
  868. if (FAILED(ddrval))
  869. {
  870. DPF_ERR("Stream write failed on width");
  871. break;
  872. }
  873. ddrval = pStrm->Write((void*) & ddsd.dwHeight, sizeof(DWORD), NULL);
  874. if (FAILED(ddrval))
  875. {
  876. DPF_ERR("Stream write failed on Height");
  877. break;
  878. }
  879. ddrval = pStrm->Write((void*) & ddsd.ddpfPixelFormat, sizeof(ddsd.ddpfPixelFormat), NULL);
  880. if (FAILED(ddrval))
  881. {
  882. DPF_ERR("Stream write failed on width");
  883. break;
  884. }
  885. /*
  886. * If a palette exists, then write it out
  887. */
  888. ddrval = lpDDS1->GetPalette(&lpDDPal);
  889. if (SUCCEEDED(ddrval))
  890. {
  891. ddrval = lpDDPal->GetCaps(&dwWritten);
  892. if (SUCCEEDED(ddrval))
  893. {
  894. ddrval = pStrm->Write((void*) & dwWritten, sizeof(dwWritten), NULL);
  895. if (FAILED(ddrval))
  896. {
  897. DPF_ERR("Stream write failed on palette caps");
  898. break;
  899. }
  900. /*
  901. * Stream palette from stream
  902. */
  903. ddrval = DD_Palette_PStream_Save((LPDIRECTDRAWPALETTE)lpDDPal,pStrm,bClearDirty);
  904. if (FAILED(ddrval))
  905. {
  906. lpDDPal->Release();
  907. break;
  908. }
  909. }
  910. else
  911. {
  912. DPF_ERR("Could not get palette caps");
  913. lpDDPal->Release();
  914. break;
  915. }
  916. lpDDPal->Release();
  917. }
  918. else
  919. {
  920. dwWritten = 0;
  921. ddrval = pStrm->Write((void*) & dwWritten, sizeof(dwWritten),NULL);
  922. if (FAILED(ddrval))
  923. {
  924. DPF_ERR("Stream write failed on palette caps");
  925. break;
  926. }
  927. }
  928. /*
  929. * Here we check for DDPF_OPT... and load a compression GUID if necessary
  930. if (ddpfStream.dwFlags & (DDPF_OPTCOMPRESSED|DDPF_OPTREORDERED) )
  931. {
  932. ddrval = myReadClassStm(pStrm, & clsid);
  933. }
  934. else
  935. //Surface is not compressed, so lock and read....
  936. */
  937. /*
  938. * And finally write the data
  939. */
  940. for (y=0;y<ddsd.dwHeight;y++)
  941. {
  942. ddrval = pStrm->Write((void*) ((DWORD) ddsd.lpSurface + y*ddsd.lPitch),
  943. (ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8),
  944. NULL);
  945. if (FAILED(ddrval))
  946. {
  947. DPF_ERR("Stream write failed");
  948. break;
  949. }
  950. }
  951. /*
  952. * Write out private data
  953. */
  954. ENTER_DDRAW();
  955. ddrval = InternalWritePrivateData(pStrm,
  956. this_int->lpLcl->lpSurfMore->pPrivateDataHead);
  957. LEAVE_DDRAW();
  958. break;
  959. }
  960. } // OK pixel format
  961. lpDDS1->Unlock(NULL);
  962. }//lock succeeded
  963. else
  964. {
  965. DPF_ERR("Could not lock surface");
  966. }
  967. lpDDS1->Release();
  968. }// QIed for ddsurf ok
  969. else
  970. {
  971. DPF_ERR("Bad surface object... can't QI itself for IDirectDrawSurface...");
  972. }
  973. if (SUCCEEDED(ddrval) && bClearDirty)
  974. {
  975. ENTER_DDRAW();
  976. GET_LPDDRAWSURFACE_GBL_MORE(this_int->lpLcl->lpGbl)->dwSaveStamp =
  977. GET_LPDDRAWSURFACE_GBL_MORE(this_int->lpLcl->lpGbl)->dwContentsStamp ;
  978. LEAVE_DDRAW();
  979. }
  980. return ddrval;
  981. }
  982. /*
  983. * How to calculate the size of a streamable object without really trying.
  984. * You make a dummy IStream interface with only one valid method: Write.
  985. * When Write is called you count the bytes and return OK. As long as the
  986. * client (i.e. our surface and palette IPersistStream interfaces) call
  987. * nothing but Write, it should work. Since the total is part of the fake
  988. * stream object which is on the stack, this is thread-safe too.
  989. */
  990. LPVOID CheatStreamCallbacks[3+11];
  991. typedef struct
  992. {
  993. LPVOID * lpVtbl;
  994. DWORD dwTotal;
  995. } SUPERCHEATSTREAM;
  996. HRESULT __stdcall SuperMegaCheater(SUPERCHEATSTREAM * pCheater, LPVOID pBuffer, ULONG dwSize, ULONG * pWritten)
  997. {
  998. pCheater->dwTotal += dwSize;
  999. return S_OK;
  1000. }
  1001. extern "C" HRESULT DDAPI DD_PStream_GetSizeMax(IPersistStream * lpSurfOrPalette, ULARGE_INTEGER * pMax)
  1002. {
  1003. HRESULT ddrval = DD_OK;
  1004. SUPERCHEATSTREAM SuperCheat;
  1005. if (!VALID_PTR(pMax,sizeof(ULARGE_INTEGER)))
  1006. {
  1007. DPF_ERR("Bad stream pointer");
  1008. return DDERR_INVALIDPARAMS;
  1009. }
  1010. SuperCheat.lpVtbl = CheatStreamCallbacks;
  1011. CheatStreamCallbacks[4] = (LPVOID)SuperMegaCheater;
  1012. SuperCheat.dwTotal = 0;
  1013. lpSurfOrPalette->Save((IStream*) & SuperCheat, FALSE);
  1014. pMax->LowPart = SuperCheat.dwTotal;
  1015. pMax->HighPart = 0;
  1016. return S_OK;
  1017. }
  1018. extern "C" HRESULT DDAPI DD_Palette_PStream_IsDirty(LPDIRECTDRAWPALETTE lpDDP)
  1019. {
  1020. LPDDRAWI_DDRAWPALETTE_INT this_int;
  1021. LPDDRAWI_DDRAWPALETTE_GBL this_gbl;
  1022. ENTER_DDRAW();
  1023. TRY
  1024. {
  1025. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpDDP;
  1026. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  1027. {
  1028. LEAVE_DDRAW();
  1029. return DDERR_INVALIDOBJECT;
  1030. }
  1031. this_gbl = this_int->lpLcl->lpGbl;
  1032. if ( (this_gbl->dwSaveStamp == 0 ) ||
  1033. (this_gbl->dwContentsStamp != this_gbl->dwSaveStamp) )
  1034. {
  1035. LEAVE_DDRAW();
  1036. return S_OK;
  1037. }
  1038. }
  1039. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1040. {
  1041. DPF_ERR( "Exception encountered checking dirty" );
  1042. LEAVE_DDRAW();
  1043. return DDERR_INVALIDPARAMS;
  1044. }
  1045. LEAVE_DDRAW();
  1046. return S_FALSE;
  1047. }
  1048. extern "C" HRESULT DDAPI DD_Palette_Persist_GetClassID(LPDIRECTDRAWPALETTE lpDDP, CLSID * pClassID)
  1049. {
  1050. TRY
  1051. {
  1052. memcpy(pClassID, & GUID_DirectDrawPaletteStream, sizeof(*pClassID));
  1053. }
  1054. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1055. {
  1056. DPF_ERR( "Exception encountered copying GUID" );
  1057. return DDERR_INVALIDPARAMS;
  1058. }
  1059. return DD_OK;
  1060. }
  1061. extern "C" HRESULT DDAPI DD_Palette_PStream_Load(LPDIRECTDRAWPALETTE lpStream, IStream * pStrm)
  1062. {
  1063. PALETTEENTRY pe[256];
  1064. HRESULT ddrval;
  1065. DWORD dwCaps, dwStreamCaps;
  1066. DWORD dwSize;
  1067. DWORD dwNumEntries;
  1068. LPDDRAWI_DDRAWPALETTE_INT this_int;
  1069. GUID g;
  1070. LPDIRECTDRAWPALETTE2 lpDDP;
  1071. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpStream;
  1072. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  1073. {
  1074. return DDERR_INVALIDOBJECT;
  1075. }
  1076. ddrval = lpStream->QueryInterface( IID_IDirectDrawPalette2, (void**)& lpDDP);
  1077. if (FAILED(ddrval))
  1078. {
  1079. DPF_ERR("Couldn't QI stream for palette");
  1080. return ddrval;
  1081. }
  1082. ddrval = lpDDP->GetCaps(&dwCaps);
  1083. if (SUCCEEDED(ddrval))
  1084. {
  1085. dwNumEntries = FLAGS_TO_SIZE(SIZE_PCAPS_TO_FLAGS(dwCaps));
  1086. dwSize = dwNumEntries;
  1087. if ((dwCaps & DDPCAPS_8BITENTRIES) == 0)
  1088. {
  1089. //the color table is really palettee entries
  1090. dwSize *=sizeof(PALETTEENTRY);
  1091. }
  1092. //if it weren 8 bit entries, then dwSize would already be the size of the color table
  1093. ddrval = pStrm->Read((LPVOID) &g, sizeof(GUID_DirectDrawPaletteStream),NULL);
  1094. if (SUCCEEDED(ddrval))
  1095. {
  1096. if (IsEqualGUID(g, GUID_DirectDrawPaletteStream))
  1097. {
  1098. ddrval = pStrm->Read((LPVOID) &dwStreamCaps, sizeof(DWORD),NULL);
  1099. if (SUCCEEDED(ddrval))
  1100. {
  1101. if (dwCaps == dwStreamCaps)
  1102. {
  1103. ddrval = pStrm->Read((LPVOID) pe, dwSize,NULL);
  1104. if (SUCCEEDED(ddrval))
  1105. {
  1106. ddrval = lpDDP->SetEntries(0,0,dwNumEntries,pe);
  1107. if (SUCCEEDED(ddrval))
  1108. {
  1109. /*
  1110. * Read private data
  1111. */
  1112. ddrval = InternalReadPrivateData(pStrm, lpDDP);
  1113. if (FAILED(ddrval))
  1114. {
  1115. DPF_ERR("Couldn't read private data");
  1116. }
  1117. }
  1118. else
  1119. {
  1120. DPF_ERR("Couldn't set palette entries");
  1121. }
  1122. }
  1123. else
  1124. {
  1125. DPF_ERR("Couldn't read palette entries");
  1126. }
  1127. }
  1128. else
  1129. {
  1130. DPF_ERR("Palette stream caps don't match palette object's caps");
  1131. ddrval = DDERR_INVALIDSTREAM;
  1132. }
  1133. }
  1134. else
  1135. {
  1136. DPF_ERR("Couldn't read palette caps");
  1137. }
  1138. }
  1139. else
  1140. {
  1141. DPF_ERR("Stream doesn't contain a ddraw palette stream tag");
  1142. ddrval = DDERR_INVALIDSTREAM;
  1143. }
  1144. }
  1145. else
  1146. {
  1147. DPF_ERR("Couldn't read palette stream tag");
  1148. }
  1149. }
  1150. else
  1151. {
  1152. DPF_ERR("Couldn't get palette caps");
  1153. }
  1154. lpDDP->Release();
  1155. return ddrval;
  1156. }
  1157. extern "C" HRESULT DDAPI DD_Palette_PStream_Save(LPDIRECTDRAWPALETTE lpStream, IStream * pStrm, BOOL bClearDirty)
  1158. {
  1159. PALETTEENTRY pe[256];
  1160. HRESULT ddrval;
  1161. DWORD dwCaps;
  1162. DWORD dwSize;
  1163. LPDDRAWI_DDRAWPALETTE_INT this_int;
  1164. LPDIRECTDRAWPALETTE lpDDP;
  1165. this_int = (LPDDRAWI_DDRAWPALETTE_INT) lpStream;
  1166. if( !VALID_DIRECTDRAWPALETTE_PTR( this_int ) )
  1167. {
  1168. return DDERR_INVALIDOBJECT;
  1169. }
  1170. ddrval = lpStream->QueryInterface(IID_IDirectDrawPalette, (void**) &lpDDP);
  1171. if (FAILED(ddrval))
  1172. {
  1173. DPF_ERR("Couldn't QI stream for palette");
  1174. return ddrval;
  1175. }
  1176. ddrval = lpDDP->GetCaps(&dwCaps);
  1177. if (SUCCEEDED(ddrval))
  1178. {
  1179. dwSize = FLAGS_TO_SIZE(SIZE_PCAPS_TO_FLAGS(dwCaps));
  1180. ddrval = lpDDP->GetEntries(0,0,dwSize,pe);
  1181. if (SUCCEEDED(ddrval))
  1182. {
  1183. if ((dwCaps & DDPCAPS_8BITENTRIES) == 0)
  1184. {
  1185. //the color table is really palettee entries
  1186. dwSize *=sizeof(PALETTEENTRY);
  1187. }
  1188. //if it weren 8 bit entries, then dwSize would already be the size of the color table
  1189. ddrval = pStrm->Write((LPVOID) &GUID_DirectDrawPaletteStream, sizeof(GUID_DirectDrawPaletteStream),NULL);
  1190. if (SUCCEEDED(ddrval))
  1191. {
  1192. ddrval = pStrm->Write((LPVOID) &dwCaps, sizeof(DWORD),NULL);
  1193. if (SUCCEEDED(ddrval))
  1194. {
  1195. ddrval = pStrm->Write((LPVOID) pe, dwSize,NULL);
  1196. if (SUCCEEDED(ddrval))
  1197. {
  1198. ENTER_DDRAW();
  1199. ddrval = InternalWritePrivateData(pStrm,
  1200. this_int->lpLcl->pPrivateDataHead);
  1201. LEAVE_DDRAW();
  1202. if (SUCCEEDED(ddrval))
  1203. {
  1204. if (bClearDirty)
  1205. {
  1206. ENTER_DDRAW();
  1207. (this_int->lpLcl->lpGbl)->dwSaveStamp = (this_int->lpLcl->lpGbl)->dwContentsStamp ;
  1208. LEAVE_DDRAW();
  1209. }
  1210. }
  1211. else
  1212. {
  1213. DPF_ERR("Couldn't write palette private data");
  1214. }
  1215. }
  1216. else
  1217. {
  1218. DPF_ERR("Couldn't write palette entries");
  1219. }
  1220. }
  1221. else
  1222. {
  1223. DPF_ERR("Couldn't write palette caps");
  1224. }
  1225. }
  1226. else
  1227. {
  1228. DPF_ERR("Couldn't write palette stream tag");
  1229. }
  1230. }
  1231. else
  1232. {
  1233. DPF_ERR("COuldn't get palette entries");
  1234. }
  1235. }
  1236. else
  1237. {
  1238. DPF_ERR("Couldn't get palette caps");
  1239. }
  1240. lpDDP->Release();
  1241. return ddrval;
  1242. }