Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

758 lines
20 KiB

  1. /****************************************************************************
  2. *
  3. * MODULE : PREVIEW.C
  4. *
  5. ****************************************************************************/
  6. #include <windows.h>
  7. #include <windowsx.h>
  8. #include <mmsystem.h>
  9. #include <commdlg.h>
  10. #include "preview.h"
  11. #include "mciwnd.h"
  12. typedef struct {
  13. HWND hwnd; // common dialog handle.
  14. LPOPENFILENAME pofn;
  15. LPARAM lCustData; // hold old value
  16. DWORD Flags;
  17. UINT (CALLBACK *lpfnHook)(HWND, UINT, WPARAM, LPARAM);
  18. RECT rcPreview;
  19. RECT rcImage;
  20. RECT rcText;
  21. HWND hwndMci;
  22. HFONT hfont;
  23. HPALETTE hpal;
  24. HANDLE hdib;
  25. char Title[128];
  26. } PreviewStuff, FAR *PPreviewStuff;
  27. #define PREVIEW_PROP "PreviewStuff"
  28. #ifdef WIN32
  29. #define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,(LPVOID)(p))
  30. #define GetPreviewStuff(hwnd) (PPreviewStuff)(LPVOID)GetProp(hwnd, PREVIEW_PROP)
  31. #define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
  32. #else
  33. #define SetPreviewStuff(hwnd, p) SetProp(hwnd,PREVIEW_PROP,HIWORD(p))
  34. #define GetPreviewStuff(hwnd) (PPreviewStuff)MAKELONG(0, GetProp(hwnd, PREVIEW_PROP))
  35. #define RemovePreviewStuff(hwnd) RemoveProp(hwnd,PREVIEW_PROP)
  36. #endif
  37. /***************************************************************************
  38. *
  39. ****************************************************************************/
  40. static BOOL PreviewOpen (HWND hwnd, LPOPENFILENAME pofn);
  41. static BOOL PreviewFile (PPreviewStuff p, LPSTR szFile);
  42. static BOOL PreviewPaint(PPreviewStuff p);
  43. static BOOL PreviewSize (PPreviewStuff p);
  44. static BOOL PreviewClose(PPreviewStuff p);
  45. static HANDLE GetRiffDisp(LPSTR lpszFile, LPSTR szText, int iLen);
  46. /***************************************************************************
  47. *
  48. ****************************************************************************/
  49. static BOOL PreviewOpen(HWND hwnd, LPOPENFILENAME pofn)
  50. {
  51. LOGFONT lf;
  52. PPreviewStuff p;
  53. RECT rc;
  54. p = (LPVOID)pofn->lCustData;
  55. pofn->lCustData = p->lCustData;
  56. SetPreviewStuff(hwnd, p);
  57. p->hwnd = hwnd;
  58. p->pofn = pofn;
  59. //
  60. // create a MCI window for preview.
  61. //
  62. p->hwndMci = MCIWndCreate(p->hwnd, NULL,
  63. // MCIWNDF_NOAUTOSIZEWINDOW |
  64. // MCIWNDF_NOPLAYBAR |
  65. // MCIWNDF_NOAUTOSIZEMOVIE |
  66. MCIWNDF_NOMENU |
  67. // MCIWNDF_SHOWNAME |
  68. // MCIWNDF_SHOWPOS |
  69. // MCIWNDF_SHOWMODE |
  70. // MCIWNDF_RECORD |
  71. MCIWNDF_NOERRORDLG |
  72. WS_CHILD | WS_BORDER,
  73. NULL);
  74. //
  75. // locate the preview in the lower corner of the dialog (below the
  76. // cancel button)
  77. //
  78. GetClientRect(hwnd, &p->rcPreview);
  79. GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc);
  80. ScreenToClient(hwnd, (LPPOINT)&rc);
  81. ScreenToClient(hwnd, (LPPOINT)&rc+1);
  82. // The open space we're allowed to use in the dialog is different in NT and on
  83. // Win31. Under NT there is a network button at the bottom of the dialog on
  84. // the right hand side, so we use the area from just under the CANCEL button to
  85. // a little more than 1 button height from the bottom of the dialog.
  86. // Under Win31, the network button is under CANCEL, so we use the area a little
  87. // over one button height under CANCEL, to just about the bottom of the dialog.
  88. #ifdef WIN32
  89. if (1)
  90. #else
  91. if (GetWinFlags() & WF_WINNT)
  92. #endif
  93. {
  94. p->rcPreview.top = rc.bottom + 4;
  95. p->rcPreview.left = rc.left;
  96. p->rcPreview.right = rc.right;
  97. p->rcPreview.bottom -= (rc.bottom - rc.top) + 12;
  98. } else {
  99. p->rcPreview.top = rc.bottom + (rc.bottom - rc.top) + 12;
  100. p->rcPreview.left = rc.left;
  101. p->rcPreview.right = rc.right;
  102. p->rcPreview.bottom -= 4; // leave a little room at the bottom
  103. }
  104. //
  105. // create a font to use.
  106. //
  107. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0);
  108. p->hfont = CreateFontIndirect(&lf);
  109. return TRUE;
  110. }
  111. /***************************************************************************
  112. *
  113. ****************************************************************************/
  114. static BOOL PreviewClose(PPreviewStuff p)
  115. {
  116. if (p == NULL)
  117. return FALSE;
  118. PreviewFile(p, NULL);
  119. RemovePreviewStuff(p->hwnd);
  120. if (p->hfont)
  121. DeleteObject(p->hfont);
  122. if (p->hwndMci)
  123. MCIWndDestroy(p->hwndMci);
  124. }
  125. /***************************************************************************
  126. *
  127. ****************************************************************************/
  128. #define SLASH(c) ((c) == '/' || (c) == '\\')
  129. static LPSTR NiceName(LPSTR szPath)
  130. {
  131. LPSTR sz;
  132. LPSTR lpsztmp;
  133. for (sz=szPath; *sz; sz++)
  134. ;
  135. for (; sz>szPath && !SLASH(*sz) && *sz!=':'; sz =AnsiPrev(szPath, sz))
  136. ;
  137. if(sz>szPath) sz = AnsiNext(sz) ;
  138. for(lpsztmp = sz; *lpsztmp && *lpsztmp != '.'; lpsztmp = AnsiNext(lpsztmp))
  139. ;
  140. *lpsztmp = '\0';
  141. AnsiLower(sz);
  142. AnsiUpperBuff(sz, 1);
  143. return sz;
  144. }
  145. /***************************************************************************
  146. *
  147. ****************************************************************************/
  148. static BOOL PreviewFile(PPreviewStuff p, LPSTR szFile)
  149. {
  150. if (p == NULL || !p->hwndMci)
  151. return FALSE;
  152. p->Title[0] = 0;
  153. ShowWindow(p->hwndMci, SW_HIDE);
  154. MCIWndClose(p->hwndMci);
  155. if (p->hdib)
  156. GlobalFree(p->hdib);
  157. if (p->hpal)
  158. DeleteObject(p->hpal);
  159. p->hdib = NULL;
  160. p->hpal = NULL;
  161. PreviewPaint(p);
  162. if (szFile == NULL)
  163. return TRUE;
  164. if (MCIWndOpen(p->hwndMci, szFile, 0) == 0)
  165. {
  166. lstrcpy(p->Title, NiceName(szFile));
  167. if (MCIWndUseTime(p->hwndMci) == 0)
  168. {
  169. LONG len;
  170. UINT min,sec;
  171. len = MCIWndGetLength(p->hwndMci);
  172. if (len > 0)
  173. {
  174. #define ONE_HOUR (60ul*60ul*1000ul)
  175. #define ONE_MINUTE (60ul*1000ul)
  176. #define ONE_SECOND (1000ul)
  177. min = (UINT)(len / ONE_MINUTE) % 60;
  178. sec = (UINT)(len / ONE_SECOND) % 60;
  179. wsprintf(p->Title + lstrlen(p->Title), " (%02d:%02d)", min, sec);
  180. }
  181. }
  182. }
  183. PreviewSize(p);
  184. PreviewPaint(p);
  185. return TRUE;
  186. }
  187. /***************************************************************************
  188. *
  189. ****************************************************************************/
  190. static BOOL PreviewSize(PPreviewStuff p)
  191. {
  192. RECT rc;
  193. RECT rcImage;
  194. RECT rcText;
  195. RECT rcPreview;
  196. HDC hdc;
  197. int dx;
  198. int dy;
  199. int dyPlayBar;
  200. SetRectEmpty(&p->rcText);
  201. SetRectEmpty(&p->rcImage);
  202. //
  203. // if nothing to do clear it.
  204. //
  205. if (p->Title[0] == 0 && p->hdib == NULL)
  206. return FALSE;
  207. rcPreview = p->rcPreview;
  208. //
  209. // compute the text rect, using DrawText
  210. //
  211. hdc = GetDC(p->hwnd);
  212. SelectObject(hdc, p->hfont);
  213. rcText = rcPreview;
  214. rcText.bottom = rcText.top;
  215. DrawText(hdc, p->Title, -1, &rcText, DT_CALCRECT|DT_LEFT|DT_WORDBREAK);
  216. ReleaseDC(p->hwnd, hdc);
  217. //
  218. // compute the image size
  219. //
  220. MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, MCIWNDF_NOPLAYBAR);
  221. GetWindowRect(p->hwndMci, &rc);
  222. dx = rc.right - rc.left;
  223. dy = rc.bottom - rc.top;
  224. MCIWndChangeStyles(p->hwndMci, MCIWNDF_NOPLAYBAR, 0);
  225. GetWindowRect(p->hwndMci, &rc);
  226. dyPlayBar = rc.bottom - rc.top - dy;
  227. rcImage = rcPreview;
  228. rcImage.bottom -= dyPlayBar;
  229. //
  230. // if wider than preview area scale to fit
  231. //
  232. if (dx > rcImage.right - rcImage.left)
  233. {
  234. rcImage.bottom = rcImage.top + MulDiv(dy,rcImage.right-rcImage.left,dx);
  235. }
  236. //
  237. // if x2 will fit then use it
  238. //
  239. else if (dx * 2 < rcImage.right - rcImage.left)
  240. {
  241. rcImage.right = rcImage.left + dx*2;
  242. rcImage.bottom = rcImage.top + dy*2;
  243. }
  244. //
  245. // else center the image in the preview area
  246. //
  247. else
  248. {
  249. rcImage.right = rcImage.left + dx;
  250. rcImage.bottom = rcImage.top + dy;
  251. }
  252. if (rcImage.bottom > rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar)
  253. {
  254. rcImage.bottom = rcPreview.bottom - (rcText.bottom - rcText.top) - dyPlayBar;
  255. rcImage.right = rcPreview.left + MulDiv(dx,rcImage.bottom-rcImage.top,dy);
  256. rcImage.left = rcPreview.left;
  257. }
  258. rcImage.bottom += dyPlayBar;
  259. //
  260. // now center
  261. //
  262. dx = ((rcPreview.right - rcPreview.left) - (rcText.right - rcText.left))/2;
  263. OffsetRect(&rcText, dx, 0);
  264. dx = ((rcPreview.right - rcPreview.left) - (rcImage.right - rcImage.left))/2;
  265. OffsetRect(&rcImage, dx, 0);
  266. dy = rcPreview.bottom - rcPreview.top;
  267. dy -= rcImage.bottom - rcImage.top;
  268. dy -= rcText.bottom - rcText.top;
  269. if (dy < 0)
  270. dy = 0;
  271. else
  272. dy = dy / 2;
  273. OffsetRect(&rcImage, 0, dy);
  274. OffsetRect(&rcText, 0, dy + rcImage.bottom - rcImage.top + 2);
  275. //
  276. // store RECTs
  277. //
  278. p->rcImage = rcImage;
  279. p->rcText = rcText;
  280. //
  281. // position window.
  282. //
  283. SetWindowPos(p->hwndMci, NULL, rcImage.left, rcImage.top,
  284. rcImage.right - rcImage.left, rcImage.bottom - rcImage.top,
  285. SWP_NOZORDER | SWP_NOACTIVATE);
  286. ShowWindow(p->hwndMci, SW_SHOW);
  287. return TRUE;
  288. }
  289. /***************************************************************************
  290. *
  291. ****************************************************************************/
  292. static BOOL PreviewPaint(PPreviewStuff p)
  293. {
  294. HDC hdc;
  295. HBRUSH hbr;
  296. HWND hwnd = p->hwnd;
  297. if (p == NULL)
  298. return TRUE;
  299. hdc = GetDC(hwnd);
  300. hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hwnd, CTLCOLOR_DLG));
  301. ////FillRect(hdc, &p->rcPreview, hbr);
  302. FillRect(hdc, &p->rcText, hbr);
  303. SelectObject(hdc, p->hfont);
  304. DrawText(hdc, p->Title, -1, &p->rcText, DT_LEFT|DT_WORDBREAK);
  305. ReleaseDC(hwnd, hdc);
  306. return TRUE;
  307. }
  308. /***************************************************************************
  309. *
  310. ****************************************************************************/
  311. /* Combo boxes */
  312. #define cmb1 0x0470
  313. #define cmb2 0x0471
  314. /* Listboxes */
  315. #define lst1 0x0460
  316. #define lst2 0x0461
  317. /* Edit controls */
  318. #define edt1 0x0480
  319. #define ID_TIMER 1234
  320. #define PREVIEWWAIT 1000
  321. WORD FAR PASCAL _loadds GetFileNamePreviewHook(HWND hwnd, unsigned msg, WORD wParam, LONG lParam)
  322. {
  323. int i;
  324. char ach[80];
  325. PPreviewStuff p;
  326. p = GetPreviewStuff(hwnd);
  327. switch (msg) {
  328. case WM_COMMAND:
  329. switch (wParam)
  330. {
  331. case lst1:
  332. if (HIWORD(lParam) == LBN_SELCHANGE)
  333. {
  334. KillTimer(hwnd, ID_TIMER);
  335. SetTimer(hwnd, ID_TIMER, PREVIEWWAIT, NULL);
  336. }
  337. break;
  338. case IDOK:
  339. case IDCANCEL:
  340. KillTimer(hwnd, ID_TIMER);
  341. PreviewFile(p, NULL);
  342. break;
  343. case cmb1:
  344. case cmb2:
  345. case lst2:
  346. if (HIWORD(lParam) == LBN_SELCHANGE)
  347. {
  348. KillTimer(hwnd, ID_TIMER);
  349. PreviewFile(p, NULL);
  350. }
  351. break;
  352. }
  353. break;
  354. case WM_TIMER:
  355. if (wParam == ID_TIMER)
  356. {
  357. KillTimer(hwnd, ID_TIMER);
  358. ach[0] = 0;
  359. i = (int)SendDlgItemMessage(hwnd, lst1, LB_GETCURSEL, 0, 0L);
  360. SendDlgItemMessage(hwnd, lst1, LB_GETTEXT, i, (LONG)(LPSTR)ach);
  361. PreviewFile(p, ach);
  362. return TRUE;
  363. }
  364. break;
  365. case WM_QUERYNEWPALETTE:
  366. case WM_PALETTECHANGED:
  367. if (p && p->hwndMci)
  368. SendMessage(p->hwndMci, msg, wParam, lParam);
  369. break;
  370. case WM_PAINT:
  371. PreviewPaint(p);
  372. break;
  373. case WM_INITDIALOG:
  374. PreviewOpen(hwnd, (LPOPENFILENAME)lParam);
  375. p = GetPreviewStuff(hwnd);
  376. if (!(p->Flags & OFN_ENABLEHOOK))
  377. return TRUE;
  378. break;
  379. case WM_DESTROY:
  380. PreviewClose(p);
  381. break;
  382. }
  383. if (p && (p->Flags & OFN_ENABLEHOOK))
  384. return p->lpfnHook(hwnd, msg, wParam, lParam);
  385. else
  386. return FALSE;
  387. }
  388. /***************************************************************************
  389. *
  390. ****************************************************************************/
  391. static BOOL GetFileNamePreview(LPOPENFILENAME lpofn, BOOL fSave)
  392. {
  393. BOOL f;
  394. PPreviewStuff p;
  395. //////// Link to COMMDLG
  396. HINSTANCE h;
  397. BOOL (WINAPI *GetFileNameProc)(OPENFILENAME FAR*) = NULL;
  398. if ((h = LoadLibrary("COMMDLG.DLL")) >= HINSTANCE_ERROR)
  399. (FARPROC)GetFileNameProc = GetProcAddress(h,
  400. fSave ? "GetSaveFileName" : "GetOpenFileName");
  401. if (GetFileNameProc == NULL)
  402. return FALSE; //!!! what's the right error here?
  403. ////////////////
  404. #ifndef OFN_NONETWORKBUTTON
  405. #define OFN_NONETWORKBUTTON 0x00020000
  406. #endif
  407. // If we have a READ ONLY checkbox, or both HELP and NETWORK, then it's in
  408. // our way, so get rid of it. (keep NETWORK, lose HELP)
  409. if (!(lpofn->Flags & OFN_HIDEREADONLY))
  410. lpofn->Flags |= OFN_HIDEREADONLY;
  411. if ((lpofn->Flags & OFN_SHOWHELP) && !(lpofn->Flags & OFN_NONETWORKBUTTON))
  412. lpofn->Flags &= ~OFN_SHOWHELP;
  413. p = (LPVOID)GlobalAllocPtr(GHND, sizeof(PreviewStuff));
  414. if (p == NULL)
  415. {
  416. f = GetFileNameProc(lpofn);
  417. }
  418. else
  419. {
  420. p->lpfnHook = lpofn->lpfnHook;
  421. p->Flags = lpofn->Flags;
  422. p->lCustData = lpofn->lCustData;
  423. lpofn->lpfnHook = GetFileNamePreviewHook;
  424. lpofn->Flags |= OFN_ENABLEHOOK;
  425. lpofn->lCustData = (LPARAM)p;
  426. f = GetFileNameProc(lpofn);
  427. lpofn->lpfnHook = p->lpfnHook;
  428. lpofn->Flags = p->Flags;
  429. GlobalFreePtr(p);
  430. }
  431. FreeLibrary(h); //!!! should we free DLL?
  432. return f;
  433. }
  434. /**************************************************************************
  435. * @doc EXTERNAL
  436. *
  437. * @api BOOL | GetOpenFileNamePreview | This is just like <f GetOpenFileName>
  438. * in COMMDLG, but with a preview window so people can see what movie
  439. * they're opening.
  440. *
  441. * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetOpenFileName>.
  442. *
  443. * @rdesc Returns true if a file was opened.
  444. *
  445. * @xref GetOpenFileName
  446. *
  447. *************************************************************************/
  448. BOOL FAR PASCAL _loadds GetOpenFileNamePreview(LPOPENFILENAME lpofn)
  449. {
  450. return GetFileNamePreview(lpofn, FALSE);
  451. }
  452. /**************************************************************************
  453. * @doc EXTERNAL
  454. *
  455. * @api BOOL | GetSaveFileNamePreview | This is just like <f GetSaveFileName>
  456. * in COMMDLG, but with a preview window so people can see what movie
  457. * they're saving over.
  458. *
  459. * @parm LPOPENFILENAME | lpofn | See the documentation for <f GetSaveFileName>.
  460. *
  461. * @rdesc Returns true if a file was opened.
  462. *
  463. * @xref GetSaveFileName
  464. *
  465. *************************************************************************/
  466. BOOL FAR PASCAL _loadds GetSaveFileNamePreview(LPOPENFILENAME lpofn)
  467. {
  468. return GetFileNamePreview(lpofn, TRUE);
  469. }
  470. #if 0 ///////////////////// DONT NEED THIS
  471. /****************************************************************************
  472. *
  473. ****************************************************************************/
  474. //#define FOURCC_RIFF mmioFOURCC('R','I','F','F')
  475. #define FOURCC_INFO mmioFOURCC('I','N','F','O')
  476. #define FOURCC_DISP mmioFOURCC('D','I','S','P')
  477. #define FOURCC_INAM mmioFOURCC('I','N','A','M')
  478. #define FOURCC_ISBJ mmioFOURCC('I','S','B','J')
  479. #define DibSizeImage(lpbi) (\
  480. (DWORD)(UINT)((((int)lpbi->biBitCount*(int)lpbi->biWidth+31)&~31)>>3) * \
  481. (DWORD)(UINT)lpbi->biHeight)
  482. #define DibSize(lpbi) \
  483. (lpbi->biSize + ((int)lpbi->biClrUsed * sizeof(RGBQUAD)) + lpbi->biSizeImage)
  484. #define DibNumColors(lpbi) \
  485. (lpbi->biBitCount <= 8 ? (1 << (int)lpbi->biBitCount) : 0)
  486. /****************************************************************************
  487. *
  488. * get both the DISP(CF_DIB) and the DISP(CF_TEXT) info in one pass, this is
  489. * much faster than doing multiple passes over the file.
  490. *
  491. ****************************************************************************/
  492. static HANDLE GetRiffDisp(LPSTR lpszFile, LPSTR szText, int iLen)
  493. {
  494. HMMIO hmmio;
  495. MMCKINFO ck;
  496. MMCKINFO ckINFO;
  497. MMCKINFO ckRIFF;
  498. HANDLE h = NULL;
  499. LONG lSize;
  500. DWORD dw;
  501. HCURSOR hcur = NULL;
  502. if (szText)
  503. szText[0] = 0;
  504. /* Open the file */
  505. hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ);
  506. if (hmmio == NULL)
  507. return NULL;
  508. mmioSeek(hmmio, 0, SEEK_SET);
  509. /* descend the input file into the RIFF chunk */
  510. if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
  511. goto error;
  512. if (ckRIFF.ckid != FOURCC_RIFF)
  513. goto error;
  514. while (!mmioDescend(hmmio, &ck, &ckRIFF, 0))
  515. {
  516. if (ck.ckid == FOURCC_DISP)
  517. {
  518. if (hcur == NULL)
  519. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  520. /* Read dword into dw, break if read unsuccessful */
  521. if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw))
  522. goto error;
  523. /* Find out how much memory to allocate */
  524. lSize = ck.cksize - sizeof(dw);
  525. if ((int)dw == CF_DIB && h == NULL)
  526. {
  527. /* get a handle to memory to hold the description and lock it down */
  528. if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  529. goto error;
  530. if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
  531. goto error;
  532. }
  533. else if ((int)dw == CF_TEXT && szText[0] == 0)
  534. {
  535. if (lSize > iLen-1)
  536. lSize = iLen-1;
  537. szText[lSize] = 0;
  538. if (mmioRead(hmmio, szText, lSize) != lSize)
  539. goto error;
  540. }
  541. }
  542. else if (ck.ckid == FOURCC_LIST &&
  543. ck.fccType == FOURCC_INFO &&
  544. szText[0] == 0)
  545. {
  546. while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
  547. {
  548. switch (ckINFO.ckid)
  549. {
  550. case FOURCC_INAM:
  551. // case FOURCC_ISBJ:
  552. lSize = ck.cksize;
  553. if (lSize > iLen-1)
  554. lSize = iLen-1;
  555. szText[lSize] = 0;
  556. if (mmioRead(hmmio, szText, lSize) != lSize)
  557. goto error;
  558. break;
  559. }
  560. if (mmioAscend(hmmio, &ckINFO, 0))
  561. break;
  562. }
  563. }
  564. //
  565. // if we have both a picture and a title, then exit.
  566. //
  567. if (h != NULL && szText[0] != 0)
  568. break;
  569. /* Ascend so that we can descend into next chunk
  570. */
  571. if (mmioAscend(hmmio, &ck, 0))
  572. break;
  573. }
  574. goto exit;
  575. error:
  576. if (h)
  577. GlobalFree(h);
  578. h = NULL;
  579. ckRIFF.fccType = 0;
  580. exit:
  581. mmioClose(hmmio, 0);
  582. //
  583. // verify and correct the DIB
  584. //
  585. if (h)
  586. {
  587. LPBITMAPINFOHEADER lpbi;
  588. lpbi = (LPVOID)GlobalLock(h);
  589. if (lpbi->biSize < sizeof(BITMAPINFOHEADER))
  590. goto error;
  591. if (lpbi->biClrUsed == 0)
  592. lpbi->biClrUsed = DibNumColors(lpbi);
  593. if (lpbi->biSizeImage == 0)
  594. lpbi->biSizeImage = DibSizeImage(lpbi);
  595. if (DibSize(lpbi) > GlobalSize(h))
  596. goto error;
  597. }
  598. if (hcur)
  599. SetCursor(hcur);
  600. return h;
  601. }
  602. #endif ///////////////////// DONT NEED THIS