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.

705 lines
20 KiB

  1. /****************************************************************************
  2. *
  3. * cappal.c
  4. *
  5. * Palette processing module.
  6. *
  7. * Microsoft Video for Windows Sample Capture Class
  8. *
  9. * Copyright (c) 1992, 1993 Microsoft Corporation. All Rights Reserved.
  10. *
  11. * You have a royalty-free right to use, modify, reproduce and
  12. * distribute the Sample Files (and/or any modified version) in
  13. * any way you find useful, provided that you agree that
  14. * Microsoft has no warranty obligations or liability for any
  15. * Sample Application Files which are modified.
  16. *
  17. ***************************************************************************/
  18. #define INC_OLE2
  19. #pragma warning(disable:4103)
  20. #include <windows.h>
  21. #include <windowsx.h>
  22. #include <win32.h>
  23. #include <mmsystem.h>
  24. #include <vfw.h>
  25. #include "ivideo32.h"
  26. #include "avicapi.h"
  27. #include "cappal.h"
  28. #include "capdib.h"
  29. #include "dibmap.h"
  30. //
  31. // Allocate and initialize palette resources at Window create time
  32. //
  33. BOOL PalInit (LPCAPSTREAM lpcs)
  34. {
  35. return (PalGetPaletteFromDriver (lpcs));
  36. }
  37. //
  38. // FreePaletteCache - free the RGB555 Xlate table
  39. //
  40. void FreePaletteCache (LPCAPSTREAM lpcs)
  41. {
  42. if (lpcs->lpCacheXlateTable) {
  43. GlobalFreePtr (lpcs->lpCacheXlateTable);
  44. lpcs->lpCacheXlateTable = NULL;
  45. }
  46. }
  47. //
  48. // Release palette resources at Window destroy time
  49. //
  50. void PalFini (LPCAPSTREAM lpcs)
  51. {
  52. PalDeleteCurrentPalette (lpcs);
  53. FreePaletteCache (lpcs);
  54. }
  55. //
  56. // Delete our palette if it isn't the system default palette
  57. //
  58. void PalDeleteCurrentPalette (LPCAPSTREAM lpcs)
  59. {
  60. if (lpcs->hPalCurrent &&
  61. (lpcs->hPalCurrent != GetStockObject(DEFAULT_PALETTE)))
  62. DeleteObject (lpcs->hPalCurrent);
  63. lpcs->hPalCurrent = NULL;
  64. }
  65. //
  66. // Get the current palette (from the driver)
  67. // Returns: TRUE if the driver can supply a palette
  68. //
  69. BOOL PalGetPaletteFromDriver (LPCAPSTREAM lpcs)
  70. {
  71. FCLOGPALETTE pal;
  72. PalDeleteCurrentPalette (lpcs);
  73. pal.palVersion = 0x0300;
  74. pal.palNumEntries = 256;
  75. lpcs->sCapDrvCaps.fDriverSuppliesPalettes = FALSE; // assume the worst
  76. if (lpcs->fHardwareConnected) {
  77. if (videoConfigure (lpcs->hVideoIn,
  78. DVM_PALETTE,
  79. VIDEO_CONFIGURE_GET | VIDEO_CONFIGURE_CURRENT, NULL,
  80. (LPVOID)&pal, sizeof(pal),
  81. NULL, 0 ) == DV_ERR_OK) {
  82. if (lpcs->hPalCurrent = CreatePalette ((LPLOGPALETTE) &pal))
  83. lpcs->sCapDrvCaps.fDriverSuppliesPalettes = TRUE;
  84. }
  85. }
  86. if (!lpcs->hPalCurrent)
  87. lpcs->hPalCurrent = GetStockObject (DEFAULT_PALETTE);
  88. DibNewPalette (lpcs, lpcs->hPalCurrent);
  89. return (lpcs->sCapDrvCaps.fDriverSuppliesPalettes);
  90. }
  91. //
  92. // Set the current palette used for capture by sending a copy to the driver
  93. // and then copying the entries to out DIB.
  94. // This may also be called when reconnecting a driver and using a cached
  95. // copy of the palette.
  96. // Returns TRUE on success, or FALSE on failure.
  97. //
  98. DWORD PalSendPaletteToDriver (LPCAPSTREAM lpcs, HPALETTE hpal, LPBYTE lpXlateTable)
  99. {
  100. short nColors;
  101. FCLOGPALETTE pal;
  102. HCURSOR hOldCursor;
  103. // The following can take a while so repaint our parent
  104. UpdateWindow (GetParent (lpcs-> hwnd));
  105. UpdateWindow (lpcs->hwnd);
  106. if (!hpal)
  107. return FALSE;
  108. // Allocate a xlate table cache?
  109. if (lpXlateTable) {
  110. if (lpcs->lpCacheXlateTable == NULL) {
  111. lpcs->lpCacheXlateTable = GlobalAllocPtr (GHND, 0x8000l);
  112. if (!lpcs->lpCacheXlateTable)
  113. return FALSE;
  114. }
  115. // If we're not using the cached table, update the cache
  116. if (lpcs->lpCacheXlateTable != lpXlateTable)
  117. _fmemcpy (lpcs->lpCacheXlateTable, lpXlateTable, (UINT) 0x8000l);
  118. }
  119. else {
  120. FreePaletteCache (lpcs);
  121. }
  122. // Don't destroy the current palette when reconnecting...
  123. if (hpal != lpcs->hPalCurrent) {
  124. PalDeleteCurrentPalette (lpcs);
  125. lpcs->hPalCurrent = hpal;
  126. }
  127. GetObject(hpal, sizeof(short), (LPVOID)&nColors);
  128. if( nColors <= 1 ) { //!!>
  129. return( FALSE );
  130. }
  131. nColors = min(256, nColors);
  132. hOldCursor = SetCursor (lpcs-> hWaitCursor);
  133. statusUpdateStatus (lpcs, IDS_CAP_STAT_PALETTE_BUILD);
  134. pal.palVersion = 0x0300;
  135. pal.palNumEntries = nColors;
  136. GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
  137. if (lpcs-> fHardwareConnected) {
  138. // first try to send both the xlate table and the palette
  139. if ((!lpXlateTable) || (videoConfigure( lpcs->hVideoIn,
  140. DVM_PALETTERGB555,
  141. VIDEO_CONFIGURE_SET, NULL,
  142. (LPLOGPALETTE)&pal, sizeof(pal),
  143. lpXlateTable, (DWORD) 0x8000) != 0)) {
  144. // else send just the palette and make the driver build the table
  145. if (videoConfigure( lpcs->hVideoIn,
  146. DVM_PALETTE,
  147. VIDEO_CONFIGURE_SET, NULL,
  148. (LPLOGPALETTE)&pal, sizeof(pal),
  149. NULL, 0 )) {
  150. // Scrncap doesn't support setting a palette, so
  151. // delete the palette cache
  152. FreePaletteCache (lpcs);
  153. }
  154. }
  155. }
  156. // Supermac wants us to get the palette again, they might have
  157. // mucked with it!
  158. PalGetPaletteFromDriver (lpcs);
  159. // Since the palette has changed, delete any existing compression
  160. // output format; this forces a new output format to be selected
  161. if (lpcs->CompVars.lpbiOut) {
  162. GlobalFreePtr (lpcs->CompVars.lpbiOut);
  163. lpcs->CompVars.lpbiOut = NULL;
  164. }
  165. if (lpcs->CompVars.hic) {
  166. if (ICSeqCompressFrameStart(&lpcs->CompVars, lpcs->lpBitsInfo) == 0) {
  167. errorUpdateError (lpcs, IDS_CAP_COMPRESSOR_ERROR);
  168. }
  169. }
  170. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  171. UpdateWindow (lpcs->hwnd);
  172. SetCursor (hOldCursor);
  173. statusUpdateStatus (lpcs, 0);
  174. return (TRUE);
  175. }
  176. //
  177. // CopyPalette, makes a copy of a GDI logical palette
  178. // Returns: a handle to the newly created palette, or NULL if error
  179. //
  180. HPALETTE CopyPalette (HPALETTE hpal)
  181. {
  182. LPLOGPALETTE lppal;
  183. short nNumEntries;
  184. if (!hpal)
  185. return NULL;
  186. GetObject (hpal,sizeof(short),(LPVOID)&nNumEntries);
  187. if (nNumEntries == 0)
  188. return NULL;
  189. lppal = (LPLOGPALETTE) GlobalAllocPtr (GHND,
  190. sizeof(LOGPALETTE) + nNumEntries * sizeof(PALETTEENTRY));
  191. if (!lppal)
  192. return NULL;
  193. lppal->palVersion = 0x300;
  194. lppal->palNumEntries = nNumEntries;
  195. GetPaletteEntries(hpal,0,nNumEntries,lppal->palPalEntry);
  196. hpal = CreatePalette(lppal);
  197. GlobalFreePtr (lppal);
  198. return hpal;
  199. }
  200. //
  201. // Allocate resources needed for palette capture
  202. // Returns DV_ERR_OK on success, or DV_ERR... on failure.
  203. // Note: if Init fails, you MUST call the Fini function to
  204. // release resources.
  205. //
  206. DWORD CapturePaletteInit (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
  207. {
  208. DWORD dwError = DV_ERR_OK;
  209. lpcp->lpBits = NULL;
  210. lpcp->lp16to8 = NULL;
  211. lpcp->lpHistogram = NULL;
  212. lpcp->lpbiSave = NULL;
  213. lpcp->wNumFrames = 0;
  214. // Init an RGB16 header
  215. lpcp->bi16.biSize = sizeof(BITMAPINFOHEADER);
  216. lpcp->bi16.biWidth = lpcs->dxBits;
  217. lpcp->bi16.biHeight = lpcs->dyBits;
  218. lpcp->bi16.biPlanes = 1;
  219. lpcp->bi16.biBitCount = 16;
  220. lpcp->bi16.biCompression = BI_RGB;
  221. lpcp->bi16.biSizeImage = DIBWIDTHBYTES(lpcp->bi16) * lpcp->bi16.biHeight;
  222. lpcp->bi16.biXPelsPerMeter= 0;
  223. lpcp->bi16.biYPelsPerMeter= 0;
  224. lpcp->bi16.biClrUsed = 0;
  225. lpcp->bi16.biClrImportant = 0;
  226. // Allocate memory for the histogram, DIB, and XLate table
  227. lpcp->lpBits = GlobalAllocPtr (GHND, lpcp->bi16.biSizeImage);
  228. lpcp->lp16to8 = GlobalAllocPtr (GHND, 0x8000l);
  229. lpcp->lpHistogram = InitHistogram(NULL);
  230. if (!lpcp->lpBits || !lpcp->lp16to8 || !lpcp->lpHistogram) {
  231. dwError = DV_ERR_NOMEM;
  232. goto PalInitError;
  233. }
  234. // Init the video header
  235. lpcp->vHdr.lpData = lpcp->lpBits;
  236. lpcp->vHdr.dwBufferLength = lpcp->bi16.biSizeImage;
  237. lpcp->vHdr.dwUser = 0;
  238. lpcp->vHdr.dwFlags = 0;
  239. // Save the current format
  240. lpcp->lpbiSave = DibGetCurrentFormat (lpcs);
  241. // Make sure we can set the format to 16 bit RGB
  242. if(dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
  243. VIDEO_CONFIGURE_SET, NULL,
  244. (LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
  245. NULL, 0 ) ) {
  246. goto PalInitError;
  247. }
  248. // Put everything back the way it was
  249. if (dwError = videoConfigure( lpcs->hVideoIn, DVM_FORMAT,
  250. VIDEO_CONFIGURE_SET, NULL,
  251. (LPBITMAPINFOHEADER)lpcp->lpbiSave, lpcp->lpbiSave->bmiHeader.biSize,
  252. NULL, 0 )) {
  253. goto PalInitError;
  254. }
  255. PalInitError:
  256. return dwError;
  257. }
  258. //
  259. // Free resources used for palette capture
  260. //
  261. DWORD CapturePaletteFini (LPCAPSTREAM lpcs, LPCAPPAL lpcp)
  262. {
  263. if (lpcp->lpBits) {
  264. GlobalFreePtr (lpcp->lpBits);
  265. lpcp->lpBits = NULL;
  266. }
  267. if (lpcp->lp16to8) {
  268. GlobalFreePtr (lpcp->lp16to8);
  269. lpcp->lp16to8 = NULL;
  270. }
  271. if (lpcp->lpHistogram) {
  272. FreeHistogram(lpcp->lpHistogram);
  273. lpcp->lpHistogram = NULL;
  274. }
  275. if (lpcp->lpbiSave) {
  276. GlobalFreePtr (lpcp->lpbiSave);
  277. lpcp->lpbiSave = NULL;
  278. }
  279. return DV_ERR_OK;
  280. }
  281. //
  282. // CapturePaletteFrames() The workhorse of capture palette.
  283. //
  284. DWORD CapturePaletteFrames (LPCAPSTREAM lpcs, LPCAPPAL lpcp, int nCount)
  285. {
  286. int j;
  287. DWORD dwError;
  288. // switch to RGB16 format
  289. if (dwError = videoConfigure( lpcs->hVideoIn,
  290. DVM_FORMAT,
  291. VIDEO_CONFIGURE_SET, NULL,
  292. (LPBITMAPINFOHEADER)&lpcp->bi16, sizeof(BITMAPINFOHEADER),
  293. NULL, 0 ))
  294. goto CaptureFramesError;
  295. for (j = 0; j < nCount; j++){
  296. // Get a frame
  297. dwError = videoFrame(lpcs->hVideoIn, &lpcp->vHdr);
  298. // Let the user see it
  299. InvalidateRect (lpcs->hwnd, NULL, TRUE);
  300. UpdateWindow (lpcs->hwnd);
  301. // Histogram it
  302. DibHistogram(&lpcp->bi16, lpcp->lpBits, 0, 0, -1, -1, lpcp->lpHistogram);
  303. lpcp->wNumFrames++;
  304. }
  305. dwError = videoConfigure( lpcs->hVideoIn,
  306. DVM_FORMAT,
  307. VIDEO_CONFIGURE_SET, NULL,
  308. (LPBITMAPINFOHEADER)lpcp->lpbiSave,
  309. lpcp->lpbiSave->bmiHeader.biSize,
  310. NULL, 0 );
  311. // videoFrame( lpcs->hVideoIn, &lpcs->VidHdr );
  312. CaptureFramesError:
  313. return dwError;
  314. }
  315. //
  316. // CapturePaletteAuto() capture a palette from the video source
  317. // without user intervention.
  318. // Returns TRUE on success, FALSE on error
  319. //
  320. BOOL CapturePaletteAuto (LPCAPSTREAM lpcs, int nCount, int nColors)
  321. {
  322. HPALETTE hpal;
  323. HCURSOR hOldCursor;
  324. DWORD dwError = DV_ERR_OK;
  325. CAPPAL cappal;
  326. LPCAPPAL lpcp;
  327. lpcp = &cappal;
  328. if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
  329. return FALSE;
  330. if (nColors <= 0 || nColors > 256)
  331. return FALSE;
  332. lpcp->wNumColors = max (nColors, 2); // at least 2 colors
  333. if (nCount <= 0)
  334. return FALSE;
  335. if (dwError = CapturePaletteInit (lpcs, lpcp))
  336. goto PalAutoExit;
  337. hOldCursor = SetCursor(lpcs->hWaitCursor);
  338. CapturePaletteFrames (lpcs, lpcp, nCount);
  339. /* we grabbed a frame, time to compute a palette */
  340. statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
  341. // The HPALETTE returned in the following becomes
  342. // our "global" palette, hence is not deleted here.
  343. hpal = HistogramPalette(lpcp->lpHistogram, lpcp->lp16to8, lpcp->wNumColors);
  344. // Send driver both the pal and xlate table
  345. PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
  346. videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // Update the display with a new image
  347. SetCursor(hOldCursor);
  348. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  349. UpdateWindow(lpcs->hwnd);
  350. lpcs->fUsingDefaultPalette = FALSE;
  351. PalAutoExit:
  352. CapturePaletteFini (lpcs, lpcp);
  353. statusUpdateStatus(lpcs, 0);
  354. // If an error happened, display it
  355. if (dwError)
  356. errorDriverID (lpcs, dwError);
  357. return (dwError == DV_ERR_OK);
  358. }
  359. //
  360. // CapturePaletteManual() capture a palette from the video source
  361. // with user intervention.
  362. // fGrab is TRUE on all but the last frame captured
  363. // Returns TRUE on success, FALSE on error
  364. //
  365. BOOL CapturePaletteManual (LPCAPSTREAM lpcs, BOOL fGrab, int nColors)
  366. {
  367. HPALETTE hpal;
  368. HCURSOR hOldCursor;
  369. LPCAPPAL lpcp;
  370. DWORD dwError = DV_ERR_OK;
  371. if (!lpcs->sCapDrvCaps.fDriverSuppliesPalettes)
  372. return FALSE;
  373. hOldCursor = SetCursor(lpcs->hWaitCursor);
  374. // We're initializing for the first time, so alloc everything
  375. if (lpcs->lpCapPal == NULL) {
  376. if (lpcp = (LPCAPPAL) GlobalAllocPtr (GHND, sizeof(CAPPAL))) {
  377. lpcs->lpCapPal = lpcp;
  378. if (nColors == 0)
  379. nColors = 256;
  380. lpcp->wNumColors = min (nColors, 256);
  381. dwError = CapturePaletteInit (lpcs, lpcp);
  382. }
  383. else
  384. dwError = IDS_CAP_OUTOFMEM;
  385. }
  386. lpcp = lpcs->lpCapPal;
  387. if (dwError != DV_ERR_OK)
  388. goto PalManualExit;
  389. // Add a frame to the histogram
  390. // Handle the case of telling us to stop before we ever started
  391. if (fGrab || !fGrab && (lpcp->wNumFrames == 0)) {
  392. CapturePaletteFrames (lpcs, lpcp, 1);
  393. lpcs->fUsingDefaultPalette = FALSE;
  394. }
  395. // All done, send the new palette to the driver
  396. if (!fGrab) {
  397. statusUpdateStatus(lpcs, IDS_CAP_STAT_OPTPAL_BUILD);
  398. // The HPALETTE returned in the following becomes
  399. // our "global" palette, hence is not deleted here.
  400. hpal = HistogramPalette(lpcp->lpHistogram,
  401. lpcp->lp16to8, lpcp->wNumColors);
  402. // Send driver both the pal and xlate table
  403. PalSendPaletteToDriver(lpcs, hpal, (LPBYTE)lpcp->lp16to8 );
  404. }
  405. videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // Update the display with a new image
  406. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  407. UpdateWindow(lpcs->hwnd);
  408. PalManualExit:
  409. if (!fGrab || (dwError != DV_ERR_OK)) {
  410. if (lpcp != NULL) {
  411. CapturePaletteFini (lpcs, lpcp);
  412. GlobalFreePtr (lpcp);
  413. lpcs->lpCapPal = NULL;
  414. }
  415. }
  416. SetCursor(hOldCursor);
  417. statusUpdateStatus(lpcs, 0);
  418. // If an error happened, display it
  419. if (dwError) {
  420. errorUpdateError (lpcs, (UINT) dwError);
  421. }
  422. return (dwError == DV_ERR_OK);
  423. }
  424. /*--------------------------------------------------------------+
  425. | fileSavePalette - save the current palette in a file |
  426. | |
  427. +--------------------------------------------------------------*/
  428. BOOL FAR PASCAL fileSavePalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
  429. {
  430. HPALETTE hpal;
  431. HMMIO hmmio;
  432. WORD w;
  433. HCURSOR hOldCursor;
  434. MMCKINFO ckRiff;
  435. MMCKINFO ck;
  436. short nColors;
  437. FCLOGPALETTE pal;
  438. BOOL fOK = FALSE;
  439. if ((hpal = lpcs->hPalCurrent) == NULL)
  440. return FALSE;
  441. hmmio = mmioOpen(lpszFileName, NULL, MMIO_WRITE);
  442. if( !hmmio ) {
  443. /* try and create */
  444. hmmio = mmioOpen(lpszFileName, NULL, MMIO_CREATE | MMIO_WRITE);
  445. if( !hmmio ) {
  446. /* find out if the file was read only or we are just */
  447. /* totally hosed up here. */
  448. hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
  449. if (hmmio){
  450. /* file was read only, error on it */
  451. errorUpdateError (lpcs, IDS_CAP_READONLYFILE, (LPTSTR) lpszFileName);
  452. mmioClose(hmmio, 0);
  453. return FALSE;
  454. } else {
  455. /* even weirder error has occured here, give CANTOPEN */
  456. errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR) lpszFileName);
  457. return FALSE;
  458. }
  459. }
  460. }
  461. hOldCursor = SetCursor( lpcs-> hWaitCursor );
  462. /* Seek to beginning of file, so we can write the header. */
  463. mmioSeek(hmmio, 0, SEEK_SET);
  464. /* Create RIFF chunk */
  465. ckRiff.fccType = mmioFOURCC('P','A','L',' ');
  466. if(mmioCreateChunk (hmmio,&ckRiff,MMIO_CREATERIFF)) {
  467. goto FileError;
  468. }
  469. /* Create Palette chunk */
  470. ck.cksize = 0;
  471. ck.ckid = mmioFOURCC('d','a','t','a');
  472. if(mmioCreateChunk(hmmio,&ck,0)) {
  473. goto FileError;
  474. }
  475. // Get the palette data here
  476. GetObject(hpal, sizeof(short), (LPVOID)&nColors);
  477. pal.palVersion = 0x0300;
  478. pal.palNumEntries = nColors;
  479. GetPaletteEntries(hpal, 0, nColors, pal.palPalEntry);
  480. // Calc the size of the logpalette
  481. // which is the sizeof palVersion + sizeof palNumEntries + colors
  482. w = sizeof (WORD) + sizeof (WORD) + nColors * sizeof (PALETTEENTRY);
  483. // Write out the palette
  484. if(mmioWrite(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
  485. goto FileError;
  486. }
  487. if(mmioAscend(hmmio, &ck, 0)) {
  488. goto FileError;
  489. }
  490. if(mmioAscend(hmmio, &ckRiff, 0)) {
  491. goto FileError;
  492. }
  493. fOK = TRUE;
  494. FileError:
  495. mmioClose( hmmio, 0 );
  496. SetCursor( hOldCursor );
  497. if (!fOK)
  498. errorUpdateError (lpcs, IDS_CAP_ERRORPALSAVE, (LPTSTR) lpszFileName);
  499. return fOK;
  500. }
  501. /*--------------------------------------------------------------+
  502. | fileOpenPalette - use a new palette from the specified file |
  503. | |
  504. +--------------------------------------------------------------*/
  505. BOOL FAR PASCAL fileOpenPalette(LPCAPSTREAM lpcs, LPTSTR lpszFileName)
  506. {
  507. HPALETTE hpal;
  508. HMMIO hmmio;
  509. WORD w;
  510. HCURSOR hOldCursor;
  511. MMCKINFO ckRiff;
  512. MMCKINFO ck;
  513. FCLOGPALETTE pal;
  514. BOOL fOK = FALSE;
  515. if ((hpal = lpcs->hPalCurrent) == NULL)
  516. return FALSE;
  517. hmmio = mmioOpen(lpszFileName, NULL, MMIO_READ);
  518. if( !hmmio ) {
  519. errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
  520. return FALSE;
  521. }
  522. hOldCursor = SetCursor( lpcs-> hWaitCursor );
  523. /* Seek to beginning of file, so we can read the header. */
  524. mmioSeek(hmmio, 0, SEEK_SET);
  525. /* Find the RIFF chunk */
  526. ckRiff.fccType = mmioFOURCC('P','A','L',' ');
  527. if(mmioDescend (hmmio, &ckRiff, NULL, MMIO_FINDRIFF)) {
  528. goto PalOpenError;
  529. }
  530. /* Find the data chunk */
  531. ck.cksize = 0;
  532. ck.ckid = mmioFOURCC('d','a','t','a');
  533. if(mmioDescend (hmmio, &ck, &ckRiff, MMIO_FINDCHUNK)) {
  534. goto PalOpenError;
  535. }
  536. // First read just the Version and number of entries
  537. // which is the sizeof palVersion + sizeof palNumEntries
  538. w = sizeof (WORD) + sizeof (WORD);
  539. if(mmioRead(hmmio, (LPBYTE)&pal, (DWORD) w) != (LONG) w) {
  540. goto PalOpenError;
  541. }
  542. // Do a bit of checking
  543. if ((pal.palVersion != 0x0300) || (pal.palNumEntries > 256))
  544. goto PalOpenError;
  545. // Now get the actual palette data
  546. // which is the sizeof palVersion + sizeof palNumEntries
  547. w = pal.palNumEntries * sizeof (PALETTEENTRY);
  548. if(mmioRead(hmmio, (LPBYTE)&pal.palPalEntry, (DWORD) w) != (LONG) w) {
  549. goto PalOpenError;
  550. }
  551. if (hpal = CreatePalette ((LPLOGPALETTE) &pal)) {
  552. PalSendPaletteToDriver (lpcs, hpal, NULL /*lpXlateTable */);
  553. fOK = TRUE;
  554. }
  555. videoFrame( lpcs->hVideoIn, &lpcs->VidHdr ); // grab a new frame
  556. PalOpenError:
  557. mmioClose( hmmio, 0 );
  558. SetCursor( hOldCursor );
  559. InvalidateRect(lpcs->hwnd, NULL, TRUE);
  560. UpdateWindow(lpcs->hwnd); // update the display with new frame
  561. if (!fOK)
  562. errorUpdateError (lpcs, IDS_CAP_ERRORPALOPEN, (LPTSTR) lpszFileName);
  563. else
  564. lpcs->fUsingDefaultPalette = FALSE;
  565. return fOK;
  566. }