Windows NT 4.0 source code leak
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.

707 lines
19 KiB

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