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.

1421 lines
32 KiB

  1. /*----------------------------------------------------------------------------*\
  2. | Routines for dealing with Device independent bitmaps |
  3. | |
  4. | History: |
  5. | 06/23/89 toddla Created |
  6. | |
  7. \*----------------------------------------------------------------------------*/
  8. #include <windows.h>
  9. #include "dib.h"
  10. #define HUGE_T
  11. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
  12. static DWORD NEAR PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul);
  13. static DWORD NEAR PASCAL lwrite(HFILE fh, VOID FAR *pv, DWORD ul);
  14. /* flags for _lseek */
  15. #define SEEK_CUR 1
  16. #define SEEK_END 2
  17. #define SEEK_SET 0
  18. /*
  19. * Open a DIB file and return a MEMORY DIB, a memory handle containing..
  20. *
  21. * BITMAP INFO bi
  22. * palette data
  23. * bits....
  24. *
  25. */
  26. HANDLE OpenDIB(LPTSTR szFile, HFILE fh)
  27. {
  28. BITMAPINFOHEADER bi;
  29. LPBITMAPINFOHEADER lpbi;
  30. DWORD dwLen;
  31. DWORD dwBits;
  32. HANDLE hdib;
  33. HANDLE h;
  34. #ifndef UNICODE
  35. OFSTRUCT of;
  36. #endif
  37. BOOL fOpened = FALSE;
  38. if (szFile != NULL) {
  39. #ifdef UNICODE
  40. fh = (HFILE)HandleToUlong(CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ,
  41. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
  42. #else
  43. fh = OpenFile(szFile, &of, OF_READ);
  44. #endif
  45. fOpened = TRUE;
  46. }
  47. if (fh == (HFILE)-1)
  48. return NULL;
  49. hdib = ReadDibBitmapInfo(fh);
  50. if (!hdib)
  51. return NULL;
  52. DibInfo((LPBITMAPINFOHEADER)GlobalLock(hdib),&bi); GlobalUnlock(hdib);
  53. /* How much memory do we need to hold the DIB */
  54. dwBits = bi.biSizeImage;
  55. dwLen = bi.biSize + PaletteSize(&bi) + dwBits;
  56. /* Can we get more memory? */
  57. h = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE);
  58. if (!h)
  59. {
  60. GlobalFree(hdib);
  61. hdib = NULL;
  62. }
  63. else
  64. {
  65. hdib = h;
  66. }
  67. if (hdib)
  68. {
  69. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  70. /* read in the bits */
  71. lread(fh, (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi), dwBits);
  72. GlobalUnlock(hdib);
  73. }
  74. if (fOpened)
  75. _lclose(fh);
  76. return hdib;
  77. }
  78. /*
  79. * Write a global handle in CF_DIB format to a file.
  80. *
  81. */
  82. BOOL WriteDIB(LPTSTR szFile,HFILE fh, HANDLE hdib)
  83. {
  84. BITMAPFILEHEADER hdr;
  85. LPBITMAPINFOHEADER lpbi;
  86. BITMAPINFOHEADER bi;
  87. DWORD dwSize;
  88. BOOL fOpened = FALSE;
  89. if (!hdib)
  90. return FALSE;
  91. if (szFile != NULL) {
  92. #ifdef UNICODE
  93. fh = (HFILE)HandleToUlong(CreateFile(szFile,GENERIC_WRITE | GENERIC_READ, 0,
  94. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
  95. #else
  96. OFSTRUCT of;
  97. fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
  98. #endif
  99. fOpened = TRUE;
  100. }
  101. if (fh == (HFILE)-1)
  102. return FALSE;
  103. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  104. DibInfo(lpbi,&bi);
  105. dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  106. hdr.bfType = BFT_BITMAP;
  107. hdr.bfSize = dwSize + sizeof(BITMAPFILEHEADER);
  108. hdr.bfReserved1 = 0;
  109. hdr.bfReserved2 = 0;
  110. hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  111. PaletteSize(lpbi);
  112. _lwrite(fh,(const char*)&hdr,sizeof(BITMAPFILEHEADER));
  113. lwrite(fh,(LPVOID)lpbi,dwSize);
  114. GlobalUnlock(hdib);
  115. if (fOpened)
  116. _lclose(fh);
  117. return TRUE;
  118. }
  119. /*
  120. * DibInfo(hbi, lpbi)
  121. *
  122. * retrives the DIB info associated with a CF_DIB format memory block.
  123. */
  124. BOOL DibInfo(LPBITMAPINFOHEADER lpbiSource, LPBITMAPINFOHEADER lpbiTarget)
  125. {
  126. if (lpbiSource)
  127. {
  128. *lpbiTarget = *lpbiSource;
  129. if (lpbiTarget->biSize == sizeof(BITMAPCOREHEADER))
  130. {
  131. BITMAPCOREHEADER bc;
  132. bc = *(LPBITMAPCOREHEADER)lpbiTarget;
  133. lpbiTarget->biSize = sizeof(BITMAPINFOHEADER);
  134. lpbiTarget->biWidth = (DWORD)bc.bcWidth;
  135. lpbiTarget->biHeight = (DWORD)bc.bcHeight;
  136. lpbiTarget->biPlanes = (UINT)bc.bcPlanes;
  137. lpbiTarget->biBitCount = (UINT)bc.bcBitCount;
  138. lpbiTarget->biCompression = BI_RGB;
  139. lpbiTarget->biSizeImage = 0;
  140. lpbiTarget->biXPelsPerMeter = 0;
  141. lpbiTarget->biYPelsPerMeter = 0;
  142. lpbiTarget->biClrUsed = 0;
  143. lpbiTarget->biClrImportant = 0;
  144. }
  145. /*
  146. * fill in the default fields
  147. */
  148. if (lpbiTarget->biSize != sizeof(BITMAPCOREHEADER))
  149. {
  150. if (lpbiTarget->biSizeImage == 0L)
  151. lpbiTarget->biSizeImage = (DWORD)DIBWIDTHBYTES(*lpbiTarget) * lpbiTarget->biHeight;
  152. if (lpbiTarget->biClrUsed == 0L)
  153. lpbiTarget->biClrUsed = DibNumColors(lpbiTarget);
  154. }
  155. return TRUE;
  156. }
  157. return FALSE;
  158. }
  159. HPALETTE CreateColorPalette()
  160. {
  161. LOGPALETTE *pPal;
  162. HPALETTE hpal = NULL;
  163. WORD nNumColors;
  164. BYTE red;
  165. BYTE green;
  166. BYTE blue;
  167. int i;
  168. nNumColors = MAXPALETTE;
  169. pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  170. if (!pPal)
  171. goto exit;
  172. pPal->palNumEntries = nNumColors;
  173. pPal->palVersion = PALVERSION;
  174. red = green = blue = 0;
  175. for (i = 0; i < pPal->palNumEntries; i++)
  176. {
  177. pPal->palPalEntry[i].peRed = red;
  178. pPal->palPalEntry[i].peGreen = green;
  179. pPal->palPalEntry[i].peBlue = blue;
  180. pPal->palPalEntry[i].peFlags = (BYTE)0;
  181. if (!(red += 32))
  182. if (!(green += 32))
  183. blue += 64;
  184. }
  185. hpal = CreatePalette(pPal);
  186. LocalFree((HANDLE)pPal);
  187. exit:
  188. return hpal;
  189. }
  190. /*
  191. * CreateBIPalette()
  192. *
  193. * Given a Pointer to a BITMAPINFO struct will create a
  194. * a GDI palette object from the color table.
  195. *
  196. * works with "old" and "new" DIB's
  197. *
  198. */
  199. HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
  200. {
  201. LOGPALETTE *pPal;
  202. HPALETTE hpal = NULL;
  203. WORD nNumColors;
  204. UINT i;
  205. RGBQUAD FAR *pRgb;
  206. BOOL fCoreHeader;
  207. if (!lpbi)
  208. return NULL;
  209. nNumColors = DibNumColors(lpbi);
  210. if (nNumColors)
  211. {
  212. fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
  213. pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
  214. pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  215. if (!pPal)
  216. goto exit;
  217. pPal->palNumEntries = nNumColors;
  218. pPal->palVersion = PALVERSION;
  219. for (i = 0; i < nNumColors; i++)
  220. {
  221. pPal->palPalEntry[i].peRed = pRgb->rgbRed;
  222. pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  223. pPal->palPalEntry[i].peBlue = pRgb->rgbBlue;
  224. pPal->palPalEntry[i].peFlags = (BYTE)0;
  225. if (fCoreHeader)
  226. //((LPBYTE)pRgb) += sizeof(RGBTRIPLE) ;
  227. pRgb += sizeof(RGBTRIPLE) ;
  228. else
  229. pRgb++;
  230. }
  231. hpal = CreatePalette(pPal);
  232. LocalFree((HANDLE)pPal);
  233. }
  234. else if (lpbi->biBitCount == 24)
  235. {
  236. hpal = CreateColorPalette();
  237. }
  238. exit:
  239. return hpal;
  240. }
  241. /*
  242. * CreateDibPalette()
  243. *
  244. * Given a Global HANDLE to a BITMAPINFO Struct
  245. * will create a GDI palette object from the color table.
  246. *
  247. * works with "old" and "new" DIB's
  248. *
  249. */
  250. HPALETTE CreateDibPalette(HANDLE hbi)
  251. {
  252. HPALETTE hpal;
  253. if (!hbi)
  254. return NULL;
  255. hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
  256. GlobalUnlock(hbi);
  257. return hpal;
  258. }
  259. HPALETTE CreateExplicitPalette()
  260. {
  261. PLOGPALETTE ppal;
  262. HPALETTE hpal;
  263. int i;
  264. #define NPAL 256
  265. ppal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
  266. ppal->palVersion = 0x300;
  267. ppal->palNumEntries = NPAL;
  268. for (i=0; i<NPAL; i++)
  269. {
  270. ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
  271. ppal->palPalEntry[i].peRed = (BYTE)i;
  272. ppal->palPalEntry[i].peGreen = (BYTE)0;
  273. ppal->palPalEntry[i].peBlue = (BYTE)0;
  274. }
  275. hpal = CreatePalette(ppal);
  276. LocalFree((HANDLE)ppal);
  277. return hpal;
  278. }
  279. /*
  280. * ReadDibBitmapInfo()
  281. *
  282. * Will read a file in DIB format and return a global HANDLE to it's
  283. * BITMAPINFO. This function will work with both "old" and "new"
  284. * bitmap formats, but will always return a "new" BITMAPINFO
  285. *
  286. */
  287. HANDLE ReadDibBitmapInfo(HFILE fh)
  288. {
  289. DWORD off;
  290. HANDLE hbi = NULL;
  291. int size;
  292. int i;
  293. UINT nNumColors;
  294. RGBQUAD FAR *pRgb;
  295. BITMAPINFOHEADER bi;
  296. BITMAPCOREHEADER bc;
  297. LPBITMAPINFOHEADER lpbi;
  298. BITMAPFILEHEADER bf;
  299. if (fh == (HFILE)-1)
  300. return NULL;
  301. off = _llseek(fh,0L,SEEK_CUR);
  302. if (sizeof(bf) != _lread(fh,(LPBYTE)&bf,sizeof(bf)))
  303. return FALSE;
  304. /*
  305. * do we have a RC HEADER?
  306. */
  307. if (!ISDIB(bf.bfType))
  308. {
  309. bf.bfOffBits = 0L;
  310. _llseek(fh,off,SEEK_SET);
  311. }
  312. if (sizeof(bi) != _lread(fh,(LPBYTE)&bi,sizeof(bi)))
  313. return FALSE;
  314. nNumColors = DibNumColors(&bi);
  315. /*
  316. * what type of bitmap info is this?
  317. */
  318. switch (size = (int)bi.biSize)
  319. {
  320. case sizeof(BITMAPINFOHEADER):
  321. break;
  322. case sizeof(BITMAPCOREHEADER):
  323. bc = *(BITMAPCOREHEADER*)&bi;
  324. bi.biSize = sizeof(BITMAPINFOHEADER);
  325. bi.biWidth = (DWORD)bc.bcWidth;
  326. bi.biHeight = (DWORD)bc.bcHeight;
  327. bi.biPlanes = (UINT)bc.bcPlanes;
  328. bi.biBitCount = (UINT)bc.bcBitCount;
  329. bi.biCompression = BI_RGB;
  330. bi.biSizeImage = 0;
  331. bi.biXPelsPerMeter = 0;
  332. bi.biYPelsPerMeter = 0;
  333. bi.biClrUsed = nNumColors;
  334. bi.biClrImportant = nNumColors;
  335. _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  336. break;
  337. default:
  338. return NULL; /* not a DIB */
  339. }
  340. /*
  341. * fill in some default values!
  342. */
  343. if (bi.biSizeImage == 0)
  344. {
  345. bi.biSizeImage = (DWORD)DIBWIDTHBYTES(bi) * bi.biHeight;
  346. }
  347. if (bi.biXPelsPerMeter == 0)
  348. {
  349. bi.biXPelsPerMeter = 0; // ??????????????
  350. }
  351. if (bi.biYPelsPerMeter == 0)
  352. {
  353. bi.biYPelsPerMeter = 0; // ??????????????
  354. }
  355. if (bi.biClrUsed == 0)
  356. {
  357. bi.biClrUsed = DibNumColors(&bi);
  358. }
  359. hbi = GlobalAlloc(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  360. if (!hbi)
  361. return NULL;
  362. lpbi = (BITMAPINFOHEADER *)GlobalLock(hbi);
  363. *lpbi = bi;
  364. pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + bi.biSize);
  365. if (nNumColors)
  366. {
  367. if (size == (int)sizeof(BITMAPCOREHEADER))
  368. {
  369. /*
  370. * convert a old color table (3 byte entries) to a new
  371. * color table (4 byte entries)
  372. */
  373. _lread(fh,(LPBYTE)pRgb,nNumColors * sizeof(RGBTRIPLE));
  374. for (i=nNumColors-1; i>=0; i--)
  375. {
  376. RGBQUAD rgb;
  377. rgb.rgbRed = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  378. rgb.rgbBlue = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  379. rgb.rgbGreen = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  380. rgb.rgbReserved = (BYTE)0;
  381. pRgb[i] = rgb;
  382. }
  383. }
  384. else
  385. {
  386. _lread(fh,(LPBYTE)pRgb,nNumColors * sizeof(RGBQUAD));
  387. }
  388. }
  389. if (bf.bfOffBits != 0L)
  390. _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  391. GlobalUnlock(hbi);
  392. return hbi;
  393. }
  394. /* How big is the palette? if bits per pel not 24
  395. * no of bytes to read is 6 for 1 bit, 48 for 4 bits
  396. * 256*3 for 8 bits and 0 for 24 bits
  397. */
  398. UINT PaletteSize(VOID FAR * pv)
  399. {
  400. #define lpbi ((LPBITMAPINFOHEADER)pv)
  401. #define lpbc ((LPBITMAPCOREHEADER)pv)
  402. UINT NumColors;
  403. NumColors = DibNumColors(lpbi);
  404. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  405. return NumColors * sizeof(RGBTRIPLE);
  406. else
  407. return NumColors * sizeof(RGBQUAD);
  408. #undef lpbi
  409. #undef lpbc
  410. }
  411. /* How Many colors does this DIB have?
  412. * this will work on both PM and Windows bitmap info structures.
  413. */
  414. WORD DibNumColors(VOID FAR * pv)
  415. {
  416. #define lpbi ((LPBITMAPINFOHEADER)pv)
  417. #define lpbc ((LPBITMAPCOREHEADER)pv)
  418. int bits;
  419. /*
  420. * with the new format headers, the size of the palette is in biClrUsed
  421. * else is dependent on bits per pixel
  422. */
  423. if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  424. {
  425. if (lpbi->biClrUsed != 0)
  426. return (UINT)lpbi->biClrUsed;
  427. bits = lpbi->biBitCount;
  428. }
  429. else
  430. {
  431. bits = lpbc->bcBitCount;
  432. }
  433. switch (bits)
  434. {
  435. case 1:
  436. return 2;
  437. case 4:
  438. return 16;
  439. case 8:
  440. return 256;
  441. default:
  442. return 0;
  443. }
  444. #undef lpbi
  445. #undef lpbc
  446. }
  447. /*
  448. * DibFromBitmap()
  449. *
  450. * Will create a global memory block in DIB format that represents the DDB
  451. * passed in
  452. *
  453. */
  454. HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, UINT wUsage)
  455. {
  456. BITMAP bm;
  457. BITMAPINFOHEADER bi;
  458. BITMAPINFOHEADER FAR *lpbi;
  459. DWORD dwLen;
  460. int nColors;
  461. HANDLE hdib;
  462. HANDLE h;
  463. HDC hdc;
  464. if (wUsage == 0)
  465. wUsage = DIB_RGB_COLORS;
  466. if (!hbm)
  467. return NULL;
  468. #if 0
  469. if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
  470. return CreateLogicalDib(hbm,biBits,hpal);
  471. #endif
  472. if (hpal == NULL)
  473. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  474. GetObject(hbm,sizeof(bm),(LPBYTE)&bm);
  475. #ifdef WIN32
  476. nColors = 0; // GetObject only stores two bytes
  477. #endif
  478. GetObject(hpal,sizeof(nColors),(LPBYTE)&nColors);
  479. if (biBits == 0)
  480. biBits = bm.bmPlanes * bm.bmBitsPixel;
  481. bi.biSize = sizeof(BITMAPINFOHEADER);
  482. bi.biWidth = bm.bmWidth;
  483. bi.biHeight = bm.bmHeight;
  484. bi.biPlanes = 1;
  485. bi.biBitCount = biBits;
  486. bi.biCompression = biStyle;
  487. bi.biSizeImage = 0;
  488. bi.biXPelsPerMeter = 0;
  489. bi.biYPelsPerMeter = 0;
  490. bi.biClrUsed = 0;
  491. bi.biClrImportant = 0;
  492. dwLen = bi.biSize + PaletteSize(&bi);
  493. hdc = CreateCompatibleDC(NULL);
  494. hpal = SelectPalette(hdc,hpal,TRUE);
  495. RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
  496. hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
  497. if (!hdib)
  498. goto exit;
  499. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  500. *lpbi = bi;
  501. /*
  502. * call GetDIBits with a NULL lpBits param, so it will calculate the
  503. * biSizeImage field for us
  504. */
  505. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  506. NULL, (LPBITMAPINFO)lpbi, wUsage);
  507. bi = *lpbi;
  508. GlobalUnlock(hdib);
  509. /*
  510. * HACK! if the driver did not fill in the biSizeImage field, make one up
  511. */
  512. if (bi.biSizeImage == 0)
  513. {
  514. bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  515. if (biStyle != BI_RGB)
  516. bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  517. }
  518. /*
  519. * realloc the buffer big enough to hold all the bits
  520. */
  521. dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  522. if (h = GlobalReAlloc(hdib,dwLen,GMEM_MOVEABLE))
  523. {
  524. hdib = h;
  525. }
  526. else
  527. {
  528. GlobalFree(hdib);
  529. hdib = NULL;
  530. goto exit;
  531. }
  532. /*
  533. * call GetDIBits with a NON-NULL lpBits param, and actualy get the
  534. * bits this time
  535. */
  536. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  537. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  538. (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi),
  539. (LPBITMAPINFO)lpbi, wUsage);
  540. bi = *lpbi;
  541. lpbi->biClrUsed = DibNumColors(lpbi) ;
  542. GlobalUnlock(hdib);
  543. exit:
  544. SelectPalette(hdc,hpal,TRUE);
  545. DeleteDC(hdc);
  546. return hdib;
  547. }
  548. /*
  549. * BitmapFromDib()
  550. *
  551. * Will create a DDB (Device Dependent Bitmap) given a global handle to
  552. * a memory block in CF_DIB format
  553. *
  554. */
  555. HBITMAP BitmapFromDib(HANDLE hdib, HPALETTE hpal, UINT wUsage)
  556. {
  557. LPBITMAPINFOHEADER lpbi;
  558. HPALETTE hpalT;
  559. HDC hdc;
  560. HBITMAP hbm;
  561. #if 0
  562. UINT dx,dy,bits;
  563. #endif
  564. if (!hdib)
  565. return NULL;
  566. if (wUsage == 0)
  567. wUsage = DIB_RGB_COLORS;
  568. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  569. if (!lpbi)
  570. return NULL;
  571. hdc = GetDC(NULL);
  572. // hdc = CreateCompatibleDC(NULL);
  573. if (hpal)
  574. {
  575. hpalT = SelectPalette(hdc,hpal,TRUE);
  576. RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
  577. }
  578. #if 0
  579. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  580. {
  581. dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  582. dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  583. bits = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  584. }
  585. else
  586. {
  587. dx = (UINT)lpbi->biWidth;
  588. dy = (UINT)lpbi->biHeight;
  589. bits = (UINT)lpbi->biBitCount;
  590. }
  591. if (bMonoBitmap /* || bits == 1 */)
  592. {
  593. hbm = CreateBitmap(dx,dy,1,1,NULL);
  594. }
  595. else
  596. {
  597. HDC hdcScreen = GetDC(NULL);
  598. hbm = CreateCompatibleBitmap(hdcScreen,dx,dy);
  599. ReleaseDC(NULL,hdcScreen);
  600. }
  601. if (hbm)
  602. {
  603. if (fErrProp)
  604. SetDIBitsErrProp(hdc,hbm,0,dy,
  605. (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi),
  606. (LPBITMAPINFO)lpbi,wUsage);
  607. else
  608. SetDIBits(hdc,hbm,0,dy,
  609. (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi),
  610. (LPBITMAPINFO)lpbi,wUsage);
  611. }
  612. #else
  613. hbm = CreateDIBitmap(hdc,
  614. (LPBITMAPINFOHEADER)lpbi,
  615. (LONG)CBM_INIT,
  616. (LPBYTE)lpbi + lpbi->biSize + PaletteSize(lpbi),
  617. (LPBITMAPINFO)lpbi,
  618. wUsage );
  619. #endif
  620. if (hpal && hpalT)
  621. SelectPalette(hdc,hpalT,TRUE);
  622. // DeleteDC(hdc);
  623. ReleaseDC(NULL,hdc);
  624. GlobalUnlock(hdib);
  625. return hbm;
  626. }
  627. /*
  628. * DibFromDib()
  629. *
  630. * Will convert a DIB in 1 format to a DIB in the specifed format
  631. *
  632. */
  633. HANDLE DibFromDib(HANDLE hdib, DWORD biStyle, WORD biBits, HPALETTE hpal, UINT wUsage)
  634. {
  635. BITMAPINFOHEADER bi;
  636. HBITMAP hbm;
  637. BOOL fKillPalette=FALSE;
  638. if (!hdib)
  639. return NULL;
  640. DibInfo((LPBITMAPINFOHEADER)GlobalLock(hdib),&bi); GlobalUnlock(hdib);
  641. /*
  642. * do we have the requested format already?
  643. */
  644. if (bi.biCompression == biStyle && (UINT)bi.biBitCount == biBits)
  645. return hdib;
  646. if (hpal == NULL)
  647. {
  648. hpal = CreateDibPalette(hdib);
  649. fKillPalette++;
  650. }
  651. hbm = BitmapFromDib(hdib,hpal,wUsage);
  652. if (hbm == NULL)
  653. {
  654. hdib = NULL;
  655. }
  656. else
  657. {
  658. hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
  659. DeleteObject(hbm);
  660. }
  661. if (fKillPalette && hpal)
  662. DeleteObject(hpal);
  663. return hdib;
  664. }
  665. #define MAKEP(sel,off) ((VOID FAR *)MAKELONG(off,sel))
  666. /*
  667. * CreateLogicalDib
  668. *
  669. * Given a DDB and a HPALETTE create a "logical" DIB
  670. *
  671. * if the HBITMAP is NULL create a DIB from the system "stock" bitmap
  672. * This is used to save a logical palette to a disk file as a DIB
  673. *
  674. * if the HPALETTE is NULL use the system "stock" palette (ie the
  675. * system palette)
  676. *
  677. * a "logical" DIB is a DIB where the DIB color table *exactly* matches
  678. * the passed logical palette. There will be no system colors in the DIB
  679. * block, and a pixel value of <n> in the DIB will correspond to logical
  680. * palette index <n>.
  681. *
  682. * This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
  683. * option then converting the palindexes returned in the color table
  684. * from palette indexes to logical RGB values. The entire passed logical
  685. * palette is always copied to the DIB color table.
  686. *
  687. * The DIB color table will have exactly the same number of entries as
  688. * the logical palette. Normaly GetDIBits() will always set biClrUsed to
  689. * the maximum colors supported by the device regardless of the number of
  690. * colors in the logical palette
  691. *
  692. * Why would you want to do this? The major reason for a "logical" DIB
  693. * is so when the DIB is written to a disk file then reloaded the logical
  694. * palette created from the DIB color table will be the same as one used
  695. * originaly to create the bitmap. It also will prevent GDI from doing
  696. * nearest color matching on PC_RESERVED palettes.
  697. *
  698. * ** What do we do if the logical palette has more than 256 entries!!!!!
  699. * ** GetDIBits() may return logical palette index's that are greater than
  700. * ** 256, we cant represent these colors in the "logical" DIB
  701. * **
  702. * ** for now hose the caller?????
  703. *
  704. */
  705. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
  706. {
  707. BITMAP bm;
  708. BITMAPINFOHEADER bi;
  709. LPBITMAPINFOHEADER lpDib; // pointer to DIB
  710. LPBITMAPINFOHEADER lpbi; // temp pointer to BITMAPINFO
  711. DWORD dwLen;
  712. DWORD dw;
  713. int n;
  714. int nColors;
  715. HANDLE hdib;
  716. HDC hdc;
  717. BYTE FAR * lpBits;
  718. UINT FAR * lpCT;
  719. RGBQUAD FAR * lpRgb;
  720. PALETTEENTRY peT;
  721. HPALETTE hpalT;
  722. if (hpal == NULL)
  723. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  724. if (hbm == NULL)
  725. hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
  726. #ifdef WIN32
  727. nColors = 0; // GetObject only stores two bytes
  728. #endif
  729. GetObject(hpal,sizeof(nColors),(LPBYTE)&nColors);
  730. GetObject(hbm,sizeof(bm),(LPBYTE)&bm);
  731. if (biBits == 0)
  732. biBits = nColors > 16 ? 8 : 4;
  733. /*
  734. if (nColors > 256) // ACK!
  735. ; // How do we handle this????
  736. */
  737. bi.biSize = sizeof(BITMAPINFOHEADER);
  738. bi.biWidth = bm.bmWidth;
  739. bi.biHeight = bm.bmHeight;
  740. bi.biPlanes = 1;
  741. bi.biBitCount = biBits;
  742. bi.biCompression = BI_RGB;
  743. bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  744. bi.biXPelsPerMeter = 0;
  745. bi.biYPelsPerMeter = 0;
  746. bi.biClrUsed = nColors;
  747. bi.biClrImportant = 0;
  748. dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  749. hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
  750. if (!hdib)
  751. return NULL;
  752. lpbi = (BITMAPINFOHEADER*)MAKEP(GlobalAlloc(GMEM_FIXED,bi.biSize + 256 * sizeof(RGBQUAD)),0);
  753. if (!lpbi)
  754. {
  755. GlobalFree(hdib);
  756. return NULL;
  757. }
  758. hdc = GetDC(NULL);
  759. hpalT = SelectPalette(hdc,hpal,TRUE);
  760. RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
  761. lpDib = (BITMAPINFOHEADER*)GlobalLock(hdib);
  762. *lpbi = bi;
  763. *lpDib = bi;
  764. lpCT = (UINT FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
  765. lpRgb = (RGBQUAD FAR *)((LPBYTE)lpDib + (UINT)lpDib->biSize);
  766. lpBits = (LPBYTE)lpDib + (UINT)lpDib->biSize + PaletteSize(lpDib);
  767. /*
  768. * call GetDIBits to get the DIB bits and fill the color table with
  769. * logical palette index's
  770. */
  771. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  772. lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
  773. /*
  774. * Now convert the DIB bits into "real" logical palette index's
  775. *
  776. * lpCT points to the DIB color table wich is a UINT array of
  777. * logical palette index's
  778. *
  779. * lpBits points to the DIB bits, each DIB pixel is a index into
  780. * the DIB color table.
  781. *
  782. */
  783. if (biBits == 8)
  784. {
  785. for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE HUGE_T *)lpBits)++)
  786. *lpBits = (BYTE)lpCT[*lpBits];
  787. }
  788. else // biBits == 4
  789. {
  790. for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE HUGE_T *)lpBits)++)
  791. *lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
  792. }
  793. /*
  794. * Now copy the RGBs in the logical palette to the dib color table
  795. */
  796. for (n=0; n<nColors; n++,lpRgb++)
  797. {
  798. GetPaletteEntries(hpal,n,1,&peT);
  799. lpRgb->rgbRed = peT.peRed;
  800. lpRgb->rgbGreen = peT.peGreen;
  801. lpRgb->rgbBlue = peT.peBlue;
  802. lpRgb->rgbReserved = (BYTE)0;
  803. }
  804. GlobalUnlock(hdib);
  805. #ifdef WIN32
  806. GlobalFree(GlobalHandle(lpbi));
  807. #else
  808. GlobalFree(SELECTOROF(lpbi));
  809. #endif
  810. SelectPalette(hdc,hpalT,TRUE);
  811. ReleaseDC(NULL,hdc);
  812. return hdib;
  813. }
  814. /*
  815. * Draws bitmap <hbm> at the specifed position in DC <hdc>
  816. *
  817. */
  818. BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
  819. {
  820. HDC hdcBits;
  821. HPALETTE hpal,hpalT;
  822. BOOL f;
  823. if (!hdc || !hbm)
  824. return FALSE;
  825. hpal = SelectPalette(hdc,(HPALETTE)GetStockObject(DEFAULT_PALETTE),TRUE);
  826. SelectPalette(hdc,hpal,TRUE);
  827. hdcBits = CreateCompatibleDC(hdc);
  828. SelectObject(hdcBits,hbm);
  829. hpalT = SelectPalette(hdcBits,hpal,TRUE);
  830. RealizePalette(hdcBits);
  831. f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop);
  832. SelectPalette(hdcBits,hpalT,TRUE);
  833. DeleteDC(hdcBits);
  834. return f;
  835. }
  836. /*
  837. * Draws bitmap <hbm> at the specifed position in DC <hdc>
  838. *
  839. */
  840. BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
  841. {
  842. HDC hdcBits;
  843. BITMAP bm;
  844. BOOL f;
  845. if (!hdc || !hbm)
  846. return FALSE;
  847. hdcBits = CreateCompatibleDC(hdc);
  848. GetObject(hbm,sizeof(BITMAP),(LPBYTE)&bm);
  849. SelectObject(hdcBits,hbm);
  850. f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  851. DeleteDC(hdcBits);
  852. return f;
  853. }
  854. /*
  855. * SetDibUsage(hdib,hpal,wUsage)
  856. *
  857. * Modifies the color table of the passed DIB for use with the wUsage
  858. * parameter specifed.
  859. *
  860. * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  861. * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  862. * in the passed palette
  863. *
  864. */
  865. BOOL SetDibUsage(HANDLE hdib, HPALETTE hpal,UINT wUsage)
  866. {
  867. LPBITMAPINFOHEADER lpbi;
  868. PALETTEENTRY ape[MAXPALETTE];
  869. RGBQUAD FAR * pRgb;
  870. UINT FAR * pw;
  871. int nColors;
  872. int n;
  873. if (hpal == NULL)
  874. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  875. if (!hdib)
  876. return FALSE;
  877. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  878. if (!lpbi)
  879. return FALSE;
  880. nColors = DibNumColors(lpbi);
  881. if (nColors > 0)
  882. {
  883. pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
  884. switch (wUsage)
  885. {
  886. //
  887. // Set the DIB color table to palette indexes
  888. //
  889. case DIB_PAL_COLORS:
  890. for (pw = (UINT FAR*)pRgb,n=0; n<nColors; n++,pw++)
  891. *pw = n;
  892. break;
  893. //
  894. // Set the DIB color table to RGBQUADS
  895. //
  896. default:
  897. case DIB_RGB_COLORS:
  898. nColors = min(nColors,MAXPALETTE);
  899. GetPaletteEntries(hpal,0,nColors,ape);
  900. for (n=0; n<nColors; n++)
  901. {
  902. pRgb[n].rgbRed = ape[n].peRed;
  903. pRgb[n].rgbGreen = ape[n].peGreen;
  904. pRgb[n].rgbBlue = ape[n].peBlue;
  905. pRgb[n].rgbReserved = 0;
  906. }
  907. break;
  908. }
  909. }
  910. GlobalUnlock(hdib);
  911. return TRUE;
  912. }
  913. /*
  914. * SetPalFlags(hpal,iIndex, cnt, wFlags)
  915. *
  916. * Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
  917. * to the parameter specifed.
  918. *
  919. */
  920. BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags)
  921. {
  922. int i;
  923. BOOL f;
  924. HANDLE hpe;
  925. PALETTEENTRY FAR *lppe;
  926. if (hpal == NULL)
  927. return FALSE;
  928. if (cntEntries < 0) {
  929. #ifdef WIN32
  930. cntEntries = 0; // GetObject only stores two bytes
  931. #endif
  932. GetObject(hpal,sizeof(int),(LPBYTE)&cntEntries);
  933. }
  934. hpe = GlobalAlloc(GMEM_MOVEABLE,(LONG)cntEntries * sizeof(PALETTEENTRY));
  935. if (!hpe)
  936. return FALSE;
  937. lppe = (PALETTEENTRY*)GlobalLock(hpe);
  938. GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  939. for (i=0; i<cntEntries; i++)
  940. {
  941. lppe[i].peFlags = (BYTE)wFlags;
  942. }
  943. f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  944. GlobalUnlock(hpe);
  945. GlobalFree(hpe);
  946. return f;
  947. }
  948. /*
  949. * StretchDibBlt()
  950. *
  951. * draws a bitmap in CF_DIB format, using StretchDIBits()
  952. *
  953. * takes the same parameters as StretchBlt()
  954. */
  955. BOOL StretchDibBlt(HDC hdc, int x, int y, int dx, int dy, HANDLE hdib, int x0, int y0, int dx0, int dy0, LONG rop, UINT wUsage)
  956. {
  957. LPBITMAPINFOHEADER lpbi;
  958. LPBYTE pBuf;
  959. BOOL f;
  960. if (!hdib)
  961. {
  962. return PatBlt(hdc,x,y,dx,dy,rop);
  963. }
  964. if (wUsage == 0)
  965. {
  966. wUsage = DIB_RGB_COLORS;
  967. }
  968. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  969. if (!lpbi)
  970. {
  971. return FALSE;
  972. }
  973. if (dx0 == -1 && dy0 == -1)
  974. {
  975. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  976. {
  977. dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  978. dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  979. }
  980. else
  981. {
  982. dx0 = (int)lpbi->biWidth;
  983. dy0 = (int)lpbi->biHeight;
  984. }
  985. }
  986. if (dx < 0 && dy < 0)
  987. {
  988. dx = dx0 * (-dx);
  989. dy = dy0 * (-dy);
  990. }
  991. pBuf = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  992. f = StretchDIBits (
  993. hdc,
  994. x,y,
  995. dx,dy,
  996. x0,y0,
  997. dx0,dy0,
  998. pBuf, (LPBITMAPINFO)lpbi,
  999. wUsage,
  1000. rop);
  1001. GlobalUnlock(hdib);
  1002. return f;
  1003. }
  1004. /*
  1005. * DibBlt()
  1006. *
  1007. * draws a bitmap in CF_DIB format, using SetDIBits to device.
  1008. *
  1009. * takes the same parameters as BitBlt()
  1010. */
  1011. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, UINT wUsage)
  1012. {
  1013. LPBITMAPINFOHEADER lpbi;
  1014. LPBYTE pBuf;
  1015. BOOL f;
  1016. if (!hdib)
  1017. return PatBlt(hdc,x0,y0,dx,dy,rop);
  1018. if (wUsage == 0)
  1019. wUsage = DIB_RGB_COLORS;
  1020. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  1021. if (!lpbi)
  1022. return FALSE;
  1023. if (dx == -1 && dy == -1)
  1024. {
  1025. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1026. {
  1027. dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1028. dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1029. }
  1030. else
  1031. {
  1032. dx = (int)lpbi->biWidth;
  1033. dy = (int)lpbi->biHeight;
  1034. }
  1035. }
  1036. pBuf = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  1037. #if 0
  1038. f = SetDIBitsToDevice(hdc, x0, y0, dx, dy,
  1039. x1,y1,
  1040. x1,
  1041. dy,
  1042. pBuf, (LPBITMAPINFO)lpbi,
  1043. wUsage );
  1044. #else
  1045. f = StretchDIBits (
  1046. hdc,
  1047. x0,y0,
  1048. dx,dy,
  1049. x1,y1,
  1050. dx,dy,
  1051. pBuf, (LPBITMAPINFO)lpbi,
  1052. wUsage,
  1053. rop);
  1054. #endif
  1055. GlobalUnlock(hdib);
  1056. return f;
  1057. }
  1058. LPVOID DibLock(HANDLE hdib,int x, int y)
  1059. {
  1060. return DibXY((LPBITMAPINFOHEADER)GlobalLock(hdib),x,y);
  1061. }
  1062. VOID DibUnlock(HANDLE hdib)
  1063. {
  1064. GlobalUnlock(hdib);
  1065. }
  1066. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1067. {
  1068. BYTE HUGE_T *pBits;
  1069. DWORD ulWidthBytes;
  1070. pBits = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  1071. ulWidthBytes = DIBWIDTHBYTES(*lpbi);
  1072. pBits += (ulWidthBytes * (long)y) + x;
  1073. return (LPVOID)pBits;
  1074. }
  1075. //
  1076. // These are the standard VGA colors, we will be stuck with until the
  1077. // end of time!
  1078. //
  1079. static DWORD CosmicColors[16] = {
  1080. 0x00000000 // 0000 black
  1081. ,0x00800000 // 0001 dark red
  1082. ,0x00008000 // 0010 dark green
  1083. ,0x00808000 // 0011 mustard
  1084. ,0x00000080 // 0100 dark blue
  1085. ,0x00800080 // 0101 purple
  1086. ,0x00008080 // 0110 dark turquoise
  1087. ,0x00C0C0C0 // 1000 gray
  1088. ,0x00808080 // 0111 dark gray
  1089. ,0x00FF0000 // 1001 red
  1090. ,0x0000FF00 // 1010 green
  1091. ,0x00FFFF00 // 1011 yellow
  1092. ,0x000000FF // 1100 blue
  1093. ,0x00FF00FF // 1101 pink (magenta)
  1094. ,0x0000FFFF // 1110 cyan
  1095. ,0x00FFFFFF // 1111 white
  1096. };
  1097. HANDLE CreateDib(WORD bits, int dx, int dy)
  1098. {
  1099. HANDLE hdib;
  1100. BITMAPINFOHEADER bi;
  1101. LPBITMAPINFOHEADER lpbi;
  1102. DWORD FAR * pRgb;
  1103. UINT i;
  1104. bi.biSize = sizeof(BITMAPINFOHEADER);
  1105. bi.biPlanes = 1;
  1106. bi.biBitCount = bits;
  1107. bi.biWidth = dx;
  1108. bi.biHeight = dy;
  1109. bi.biCompression = BI_RGB;
  1110. bi.biSizeImage = 0;
  1111. bi.biXPelsPerMeter = 0;
  1112. bi.biYPelsPerMeter = 0;
  1113. bi.biClrUsed = 0;
  1114. bi.biClrImportant = 0;
  1115. bi.biClrUsed = DibNumColors(&bi);
  1116. hdib = GlobalAlloc(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) +
  1117. + (long)bi.biClrUsed * sizeof(RGBQUAD)
  1118. + (long)DIBWIDTHBYTES(bi) * (long)dy);
  1119. if (hdib)
  1120. {
  1121. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  1122. *lpbi = bi;
  1123. pRgb = (unsigned long*)((LPBYTE)lpbi + lpbi->biSize);
  1124. //
  1125. // setup the color table
  1126. //
  1127. if (bits == 1)
  1128. {
  1129. pRgb[0] = CosmicColors[0];
  1130. pRgb[1] = CosmicColors[15];
  1131. }
  1132. else
  1133. {
  1134. for (i=0; i<bi.biClrUsed; i++)
  1135. pRgb[i] = CosmicColors[i % 16];
  1136. }
  1137. GlobalUnlock(hdib);
  1138. }
  1139. return hdib;
  1140. }
  1141. /*
  1142. * Private routines to read/write more than 64k
  1143. */
  1144. #define MAXREAD (UINT)(32u * 1024)
  1145. static DWORD NEAR PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul)
  1146. {
  1147. DWORD ulT = ul;
  1148. BYTE HUGE_T *hp = (unsigned char*)pv;
  1149. while (ul > MAXREAD) {
  1150. if (_lread(fh, (LPBYTE)hp, MAXREAD) != MAXREAD)
  1151. return 0;
  1152. ul -= MAXREAD;
  1153. hp += MAXREAD;
  1154. }
  1155. if (_lread(fh, (LPBYTE)hp, (UINT)ul) != (UINT)ul)
  1156. return 0;
  1157. return ulT;
  1158. }
  1159. static DWORD NEAR PASCAL lwrite(HFILE fh, VOID FAR *pv, DWORD ul)
  1160. {
  1161. DWORD ulT = ul;
  1162. BYTE HUGE_T *hp = (unsigned char*)pv;
  1163. while (ul > MAXREAD) {
  1164. if (_lwrite(fh, (const char*)hp, MAXREAD) != MAXREAD)
  1165. return 0;
  1166. ul -= MAXREAD;
  1167. hp += MAXREAD;
  1168. }
  1169. if (_lwrite(fh, (const char*)hp, (UINT)ul) != (UINT)ul)
  1170. return 0;
  1171. return ulT;
  1172. }