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.

1420 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. /*
  666. * CreateLogicalDib
  667. *
  668. * Given a DDB and a HPALETTE create a "logical" DIB
  669. *
  670. * if the HBITMAP is NULL create a DIB from the system "stock" bitmap
  671. * This is used to save a logical palette to a disk file as a DIB
  672. *
  673. * if the HPALETTE is NULL use the system "stock" palette (ie the
  674. * system palette)
  675. *
  676. * a "logical" DIB is a DIB where the DIB color table *exactly* matches
  677. * the passed logical palette. There will be no system colors in the DIB
  678. * block, and a pixel value of <n> in the DIB will correspond to logical
  679. * palette index <n>.
  680. *
  681. * This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
  682. * option then converting the palindexes returned in the color table
  683. * from palette indexes to logical RGB values. The entire passed logical
  684. * palette is always copied to the DIB color table.
  685. *
  686. * The DIB color table will have exactly the same number of entries as
  687. * the logical palette. Normaly GetDIBits() will always set biClrUsed to
  688. * the maximum colors supported by the device regardless of the number of
  689. * colors in the logical palette
  690. *
  691. * Why would you want to do this? The major reason for a "logical" DIB
  692. * is so when the DIB is written to a disk file then reloaded the logical
  693. * palette created from the DIB color table will be the same as one used
  694. * originaly to create the bitmap. It also will prevent GDI from doing
  695. * nearest color matching on PC_RESERVED palettes.
  696. *
  697. * ** What do we do if the logical palette has more than 256 entries!!!!!
  698. * ** GetDIBits() may return logical palette index's that are greater than
  699. * ** 256, we cant represent these colors in the "logical" DIB
  700. * **
  701. * ** for now hose the caller?????
  702. *
  703. */
  704. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
  705. {
  706. BITMAP bm;
  707. BITMAPINFOHEADER bi;
  708. LPBITMAPINFOHEADER lpDib; // pointer to DIB
  709. LPBITMAPINFOHEADER lpbi; // temp pointer to BITMAPINFO
  710. DWORD dwLen;
  711. DWORD dw;
  712. int n;
  713. int nColors;
  714. HANDLE hdib;
  715. HDC hdc;
  716. BYTE FAR * lpBits;
  717. UINT FAR * lpCT;
  718. RGBQUAD FAR * lpRgb;
  719. PALETTEENTRY peT;
  720. HPALETTE hpalT;
  721. if (hpal == NULL)
  722. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  723. if (hbm == NULL)
  724. hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
  725. #ifdef WIN32
  726. nColors = 0; // GetObject only stores two bytes
  727. #endif
  728. GetObject(hpal,sizeof(nColors),(LPBYTE)&nColors);
  729. GetObject(hbm,sizeof(bm),(LPBYTE)&bm);
  730. if (biBits == 0)
  731. biBits = nColors > 16 ? 8 : 4;
  732. /*
  733. if (nColors > 256) // ACK!
  734. ; // How do we handle this????
  735. */
  736. bi.biSize = sizeof(BITMAPINFOHEADER);
  737. bi.biWidth = bm.bmWidth;
  738. bi.biHeight = bm.bmHeight;
  739. bi.biPlanes = 1;
  740. bi.biBitCount = biBits;
  741. bi.biCompression = BI_RGB;
  742. bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  743. bi.biXPelsPerMeter = 0;
  744. bi.biYPelsPerMeter = 0;
  745. bi.biClrUsed = nColors;
  746. bi.biClrImportant = 0;
  747. dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  748. hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
  749. if (!hdib)
  750. return NULL;
  751. lpbi = (BITMAPINFOHEADER*)GlobalAlloc(GMEM_FIXED,bi.biSize + 256 * sizeof(RGBQUAD));
  752. if (!lpbi)
  753. {
  754. GlobalFree(hdib);
  755. return NULL;
  756. }
  757. hdc = GetDC(NULL);
  758. hpalT = SelectPalette(hdc,hpal,TRUE);
  759. RealizePalette(hdc); // why is this needed on a MEMORY DC? GDI bug??
  760. lpDib = (BITMAPINFOHEADER*)GlobalLock(hdib);
  761. *lpbi = bi;
  762. *lpDib = bi;
  763. lpCT = (UINT FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
  764. lpRgb = (RGBQUAD FAR *)((LPBYTE)lpDib + (UINT)lpDib->biSize);
  765. lpBits = (LPBYTE)lpDib + (UINT)lpDib->biSize + PaletteSize(lpDib);
  766. /*
  767. * call GetDIBits to get the DIB bits and fill the color table with
  768. * logical palette index's
  769. */
  770. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  771. lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
  772. /*
  773. * Now convert the DIB bits into "real" logical palette index's
  774. *
  775. * lpCT points to the DIB color table wich is a UINT array of
  776. * logical palette index's
  777. *
  778. * lpBits points to the DIB bits, each DIB pixel is a index into
  779. * the DIB color table.
  780. *
  781. */
  782. if (biBits == 8)
  783. {
  784. for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE HUGE_T *)lpBits)++)
  785. *lpBits = (BYTE)lpCT[*lpBits];
  786. }
  787. else // biBits == 4
  788. {
  789. for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE HUGE_T *)lpBits)++)
  790. *lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
  791. }
  792. /*
  793. * Now copy the RGBs in the logical palette to the dib color table
  794. */
  795. for (n=0; n<nColors; n++,lpRgb++)
  796. {
  797. GetPaletteEntries(hpal,n,1,&peT);
  798. lpRgb->rgbRed = peT.peRed;
  799. lpRgb->rgbGreen = peT.peGreen;
  800. lpRgb->rgbBlue = peT.peBlue;
  801. lpRgb->rgbReserved = (BYTE)0;
  802. }
  803. GlobalUnlock(hdib);
  804. #ifdef WIN32
  805. GlobalFree(GlobalHandle(lpbi));
  806. #else
  807. GlobalFree(SELECTOROF(lpbi));
  808. #endif
  809. SelectPalette(hdc,hpalT,TRUE);
  810. ReleaseDC(NULL,hdc);
  811. return hdib;
  812. }
  813. /*
  814. * Draws bitmap <hbm> at the specifed position in DC <hdc>
  815. *
  816. */
  817. BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
  818. {
  819. HDC hdcBits;
  820. HPALETTE hpal,hpalT;
  821. BOOL f;
  822. if (!hdc || !hbm)
  823. return FALSE;
  824. hpal = SelectPalette(hdc,(HPALETTE)GetStockObject(DEFAULT_PALETTE),TRUE);
  825. SelectPalette(hdc,hpal,TRUE);
  826. hdcBits = CreateCompatibleDC(hdc);
  827. SelectObject(hdcBits,hbm);
  828. hpalT = SelectPalette(hdcBits,hpal,TRUE);
  829. RealizePalette(hdcBits);
  830. f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop);
  831. SelectPalette(hdcBits,hpalT,TRUE);
  832. DeleteDC(hdcBits);
  833. return f;
  834. }
  835. /*
  836. * Draws bitmap <hbm> at the specifed position in DC <hdc>
  837. *
  838. */
  839. BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
  840. {
  841. HDC hdcBits;
  842. BITMAP bm;
  843. BOOL f;
  844. if (!hdc || !hbm)
  845. return FALSE;
  846. hdcBits = CreateCompatibleDC(hdc);
  847. GetObject(hbm,sizeof(BITMAP),(LPBYTE)&bm);
  848. SelectObject(hdcBits,hbm);
  849. f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  850. DeleteDC(hdcBits);
  851. return f;
  852. }
  853. /*
  854. * SetDibUsage(hdib,hpal,wUsage)
  855. *
  856. * Modifies the color table of the passed DIB for use with the wUsage
  857. * parameter specifed.
  858. *
  859. * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  860. * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  861. * in the passed palette
  862. *
  863. */
  864. BOOL SetDibUsage(HANDLE hdib, HPALETTE hpal,UINT wUsage)
  865. {
  866. LPBITMAPINFOHEADER lpbi;
  867. PALETTEENTRY ape[MAXPALETTE];
  868. RGBQUAD FAR * pRgb;
  869. UINT FAR * pw;
  870. int nColors;
  871. int n;
  872. if (hpal == NULL)
  873. hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  874. if (!hdib)
  875. return FALSE;
  876. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  877. if (!lpbi)
  878. return FALSE;
  879. nColors = DibNumColors(lpbi);
  880. if (nColors > 0)
  881. {
  882. pRgb = (RGBQUAD FAR *)((LPBYTE)lpbi + (UINT)lpbi->biSize);
  883. switch (wUsage)
  884. {
  885. //
  886. // Set the DIB color table to palette indexes
  887. //
  888. case DIB_PAL_COLORS:
  889. for (pw = (UINT FAR*)pRgb,n=0; n<nColors; n++,pw++)
  890. *pw = n;
  891. break;
  892. //
  893. // Set the DIB color table to RGBQUADS
  894. //
  895. default:
  896. case DIB_RGB_COLORS:
  897. nColors = min(nColors,MAXPALETTE);
  898. GetPaletteEntries(hpal,0,nColors,ape);
  899. for (n=0; n<nColors; n++)
  900. {
  901. pRgb[n].rgbRed = ape[n].peRed;
  902. pRgb[n].rgbGreen = ape[n].peGreen;
  903. pRgb[n].rgbBlue = ape[n].peBlue;
  904. pRgb[n].rgbReserved = 0;
  905. }
  906. break;
  907. }
  908. }
  909. GlobalUnlock(hdib);
  910. return TRUE;
  911. }
  912. /*
  913. * SetPalFlags(hpal,iIndex, cnt, wFlags)
  914. *
  915. * Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
  916. * to the parameter specifed.
  917. *
  918. */
  919. BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags)
  920. {
  921. int i;
  922. BOOL f;
  923. HANDLE hpe;
  924. PALETTEENTRY FAR *lppe;
  925. if (hpal == NULL)
  926. return FALSE;
  927. if (cntEntries < 0) {
  928. #ifdef WIN32
  929. cntEntries = 0; // GetObject only stores two bytes
  930. #endif
  931. GetObject(hpal,sizeof(int),(LPBYTE)&cntEntries);
  932. }
  933. hpe = GlobalAlloc(GMEM_MOVEABLE,(LONG)cntEntries * sizeof(PALETTEENTRY));
  934. if (!hpe)
  935. return FALSE;
  936. lppe = (PALETTEENTRY*)GlobalLock(hpe);
  937. GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  938. for (i=0; i<cntEntries; i++)
  939. {
  940. lppe[i].peFlags = (BYTE)wFlags;
  941. }
  942. f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  943. GlobalUnlock(hpe);
  944. GlobalFree(hpe);
  945. return f;
  946. }
  947. /*
  948. * StretchDibBlt()
  949. *
  950. * draws a bitmap in CF_DIB format, using StretchDIBits()
  951. *
  952. * takes the same parameters as StretchBlt()
  953. */
  954. 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)
  955. {
  956. LPBITMAPINFOHEADER lpbi;
  957. LPBYTE pBuf;
  958. BOOL f;
  959. if (!hdib)
  960. {
  961. return PatBlt(hdc,x,y,dx,dy,rop);
  962. }
  963. if (wUsage == 0)
  964. {
  965. wUsage = DIB_RGB_COLORS;
  966. }
  967. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  968. if (!lpbi)
  969. {
  970. return FALSE;
  971. }
  972. if (dx0 == -1 && dy0 == -1)
  973. {
  974. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  975. {
  976. dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  977. dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  978. }
  979. else
  980. {
  981. dx0 = (int)lpbi->biWidth;
  982. dy0 = (int)lpbi->biHeight;
  983. }
  984. }
  985. if (dx < 0 && dy < 0)
  986. {
  987. dx = dx0 * (-dx);
  988. dy = dy0 * (-dy);
  989. }
  990. pBuf = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  991. f = StretchDIBits (
  992. hdc,
  993. x,y,
  994. dx,dy,
  995. x0,y0,
  996. dx0,dy0,
  997. pBuf, (LPBITMAPINFO)lpbi,
  998. wUsage,
  999. rop);
  1000. GlobalUnlock(hdib);
  1001. return f;
  1002. }
  1003. /*
  1004. * DibBlt()
  1005. *
  1006. * draws a bitmap in CF_DIB format, using SetDIBits to device.
  1007. *
  1008. * takes the same parameters as BitBlt()
  1009. */
  1010. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, UINT wUsage)
  1011. {
  1012. LPBITMAPINFOHEADER lpbi;
  1013. LPBYTE pBuf;
  1014. BOOL f;
  1015. if (!hdib)
  1016. return PatBlt(hdc,x0,y0,dx,dy,rop);
  1017. if (wUsage == 0)
  1018. wUsage = DIB_RGB_COLORS;
  1019. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  1020. if (!lpbi)
  1021. return FALSE;
  1022. if (dx == -1 && dy == -1)
  1023. {
  1024. if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1025. {
  1026. dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1027. dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1028. }
  1029. else
  1030. {
  1031. dx = (int)lpbi->biWidth;
  1032. dy = (int)lpbi->biHeight;
  1033. }
  1034. }
  1035. pBuf = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  1036. #if 0
  1037. f = SetDIBitsToDevice(hdc, x0, y0, dx, dy,
  1038. x1,y1,
  1039. x1,
  1040. dy,
  1041. pBuf, (LPBITMAPINFO)lpbi,
  1042. wUsage );
  1043. #else
  1044. f = StretchDIBits (
  1045. hdc,
  1046. x0,y0,
  1047. dx,dy,
  1048. x1,y1,
  1049. dx,dy,
  1050. pBuf, (LPBITMAPINFO)lpbi,
  1051. wUsage,
  1052. rop);
  1053. #endif
  1054. GlobalUnlock(hdib);
  1055. return f;
  1056. }
  1057. LPVOID DibLock(HANDLE hdib,int x, int y)
  1058. {
  1059. return DibXY((LPBITMAPINFOHEADER)GlobalLock(hdib),x,y);
  1060. }
  1061. VOID DibUnlock(HANDLE hdib)
  1062. {
  1063. GlobalUnlock(hdib);
  1064. }
  1065. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1066. {
  1067. BYTE HUGE_T *pBits;
  1068. DWORD ulWidthBytes;
  1069. pBits = (LPBYTE)lpbi + (UINT)lpbi->biSize + PaletteSize(lpbi);
  1070. ulWidthBytes = DIBWIDTHBYTES(*lpbi);
  1071. pBits += (ulWidthBytes * (long)y) + x;
  1072. return (LPVOID)pBits;
  1073. }
  1074. //
  1075. // These are the standard VGA colors, we will be stuck with until the
  1076. // end of time!
  1077. //
  1078. static DWORD CosmicColors[16] = {
  1079. 0x00000000 // 0000 black
  1080. ,0x00800000 // 0001 dark red
  1081. ,0x00008000 // 0010 dark green
  1082. ,0x00808000 // 0011 mustard
  1083. ,0x00000080 // 0100 dark blue
  1084. ,0x00800080 // 0101 purple
  1085. ,0x00008080 // 0110 dark turquoise
  1086. ,0x00C0C0C0 // 1000 gray
  1087. ,0x00808080 // 0111 dark gray
  1088. ,0x00FF0000 // 1001 red
  1089. ,0x0000FF00 // 1010 green
  1090. ,0x00FFFF00 // 1011 yellow
  1091. ,0x000000FF // 1100 blue
  1092. ,0x00FF00FF // 1101 pink (magenta)
  1093. ,0x0000FFFF // 1110 cyan
  1094. ,0x00FFFFFF // 1111 white
  1095. };
  1096. HANDLE CreateDib(WORD bits, int dx, int dy)
  1097. {
  1098. HANDLE hdib;
  1099. BITMAPINFOHEADER bi;
  1100. LPBITMAPINFOHEADER lpbi;
  1101. DWORD FAR * pRgb;
  1102. UINT i;
  1103. bi.biSize = sizeof(BITMAPINFOHEADER);
  1104. bi.biPlanes = 1;
  1105. bi.biBitCount = bits;
  1106. bi.biWidth = dx;
  1107. bi.biHeight = dy;
  1108. bi.biCompression = BI_RGB;
  1109. bi.biSizeImage = 0;
  1110. bi.biXPelsPerMeter = 0;
  1111. bi.biYPelsPerMeter = 0;
  1112. bi.biClrUsed = 0;
  1113. bi.biClrImportant = 0;
  1114. bi.biClrUsed = DibNumColors(&bi);
  1115. hdib = GlobalAlloc(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) +
  1116. + (long)bi.biClrUsed * sizeof(RGBQUAD)
  1117. + (long)DIBWIDTHBYTES(bi) * (long)dy);
  1118. if (hdib)
  1119. {
  1120. lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib);
  1121. *lpbi = bi;
  1122. pRgb = (unsigned long*)((LPBYTE)lpbi + lpbi->biSize);
  1123. //
  1124. // setup the color table
  1125. //
  1126. if (bits == 1)
  1127. {
  1128. pRgb[0] = CosmicColors[0];
  1129. pRgb[1] = CosmicColors[15];
  1130. }
  1131. else
  1132. {
  1133. for (i=0; i<bi.biClrUsed; i++)
  1134. pRgb[i] = CosmicColors[i % 16];
  1135. }
  1136. GlobalUnlock(hdib);
  1137. }
  1138. return hdib;
  1139. }
  1140. /*
  1141. * Private routines to read/write more than 64k
  1142. */
  1143. #define MAXREAD (UINT)(32u * 1024)
  1144. static DWORD NEAR PASCAL lread(HFILE fh, VOID FAR *pv, DWORD ul)
  1145. {
  1146. DWORD ulT = ul;
  1147. BYTE HUGE_T *hp = (unsigned char*)pv;
  1148. while (ul > MAXREAD) {
  1149. if (_lread(fh, (LPBYTE)hp, MAXREAD) != MAXREAD)
  1150. return 0;
  1151. ul -= MAXREAD;
  1152. hp += MAXREAD;
  1153. }
  1154. if (_lread(fh, (LPBYTE)hp, (UINT)ul) != (UINT)ul)
  1155. return 0;
  1156. return ulT;
  1157. }
  1158. static DWORD NEAR PASCAL lwrite(HFILE fh, VOID FAR *pv, DWORD ul)
  1159. {
  1160. DWORD ulT = ul;
  1161. BYTE HUGE_T *hp = (unsigned char*)pv;
  1162. while (ul > MAXREAD) {
  1163. if (_lwrite(fh, (const char*)hp, MAXREAD) != MAXREAD)
  1164. return 0;
  1165. ul -= MAXREAD;
  1166. hp += MAXREAD;
  1167. }
  1168. if (_lwrite(fh, (const char*)hp, (UINT)ul) != (UINT)ul)
  1169. return 0;
  1170. return ulT;
  1171. }