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.

1021 lines
20 KiB

  1. /*++
  2. * File name:
  3. * bmpdb.c
  4. * Contents:
  5. * Bitmap database manager
  6. * Almost all functions ARE NOT thread safe
  7. *
  8. * Copyright (C) 1998-1999 Microsoft Corp.
  9. --*/
  10. #include <windows.h>
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <string.h>
  16. #include <stdio.h>
  17. #include <malloc.h>
  18. #include "bmpdb.h"
  19. #define DB_NAME "bmpcache.db" // Database name
  20. #define TEMPDB_NAME "bmpcache.tmp" // Temp file, used to recopy the database
  21. // Global data
  22. int g_hDB = 0; // Handle to the opened database
  23. int g_hTempDB; // Temp handle
  24. BOOL g_bNeedToPack; // True if some entrys are deleted
  25. /*
  26. * Internal functions definition
  27. --*/
  28. void _PackDB(void);
  29. /*++
  30. * Function:
  31. * OpenDB
  32. * Description:
  33. * Opens and initializes the database
  34. * Arguments:
  35. * bWrite - TRUE if the caller wants to write in the database
  36. * Return value:
  37. * TRUE on success
  38. * Called by:
  39. * InitCache
  40. --*/
  41. BOOL OpenDB(BOOL bWrite)
  42. {
  43. int hFile, rv = TRUE;
  44. int oflag;
  45. if (g_hDB)
  46. // Already initialized
  47. goto exitpt;
  48. oflag = (bWrite)?_O_RDWR|_O_CREAT:_O_RDONLY;
  49. hFile = _open(DB_NAME, oflag|_O_BINARY, _S_IREAD|_S_IWRITE);
  50. if (hFile == -1)
  51. rv = FALSE;
  52. else
  53. g_hDB = hFile;
  54. g_bNeedToPack = FALSE;
  55. exitpt:
  56. return rv;
  57. }
  58. /*++
  59. * Function:
  60. * CloseDB
  61. * Description:
  62. * Closes the database deletes entry if necessary
  63. * Called by:
  64. * DeleteCache
  65. --*/
  66. VOID CloseDB(VOID)
  67. {
  68. if (!g_hDB)
  69. goto exitpt;
  70. if (g_bNeedToPack)
  71. _PackDB();
  72. else
  73. _close(g_hDB);
  74. g_hDB = 0;
  75. exitpt:
  76. ;
  77. }
  78. /*++
  79. * Function:
  80. * ReadGroup (Thread dependent)
  81. * Description:
  82. * Read the structure which represents
  83. * a bitmap group with the same IDs
  84. * Arguments:
  85. * nOffset - offset in the DB file
  86. * pGroup - pointer to the result
  87. * Return value:
  88. * TRUE on success
  89. * Called by:
  90. * internaly
  91. --*/
  92. BOOL ReadGroup(FOFFSET nOffset, PGROUPENTRY pGroup)
  93. {
  94. int rv = FALSE;
  95. if (!g_hDB)
  96. goto exitpt;
  97. if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
  98. goto exitpt;
  99. if (_read(g_hDB, pGroup, sizeof(*pGroup)) != sizeof(*pGroup))
  100. goto exitpt;
  101. rv = TRUE;
  102. exitpt:
  103. return rv;
  104. }
  105. /*++
  106. * Function:
  107. * WriteGroup (Thread dep)
  108. * Description:
  109. * Writes GROUPENTRY in the DB file
  110. * Arguments:
  111. * nOffset - where to store
  112. * pGroup - what to store
  113. * Return value:
  114. * TRUE on success
  115. * Called by:
  116. * internaly
  117. --*/
  118. BOOL WriteGroup(FOFFSET nOffset, PGROUPENTRY pGroup)
  119. {
  120. BOOL rv = FALSE;
  121. if (!g_hDB || !pGroup)
  122. goto exitpt;
  123. if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
  124. goto exitpt;
  125. if (_write(g_hDB, pGroup, sizeof(*pGroup)) != sizeof(*pGroup))
  126. goto exitpt;
  127. rv = TRUE;
  128. exitpt:
  129. return rv;
  130. }
  131. /*++
  132. * Function:
  133. * EnumerateGroups (thread dep)
  134. * Description:
  135. * Enumerates all groups from the DB
  136. * Arguments:
  137. * pfnEnumGrpProc - Callback function
  138. * pParam - Parameter passed to the callback
  139. * Called by:
  140. * internaly
  141. --*/
  142. VOID EnumerateGroups(PFNENUMGROUPS pfnEnumGrpProc, PVOID pParam)
  143. {
  144. GROUPENTRY Group;
  145. BOOL bRun;
  146. FOFFSET nOffs = 0;
  147. bRun = ReadGroup(nOffs, &Group);
  148. while(bRun) {
  149. if (!Group.bDeleted)
  150. bRun = pfnEnumGrpProc(nOffs, &Group, pParam) &&
  151. (Group.FOffsNext != 0);
  152. if (bRun)
  153. {
  154. nOffs = Group.FOffsNext;
  155. if (nOffs)
  156. bRun = ReadGroup(nOffs, &Group);
  157. else
  158. bRun = FALSE;
  159. }
  160. }
  161. }
  162. /*++
  163. * Function:
  164. * ReadBitmapHeader (Thread dep)
  165. * Description:
  166. * Read only the header of the bitmap
  167. * Arguments:
  168. * nOffset - where in the file
  169. * pBitmap - returned structure
  170. * Return value:
  171. * TRUE on success
  172. * Called by:
  173. * Internaly
  174. --*/
  175. BOOL ReadBitmapHeader(FOFFSET nOffset, PBMPENTRY pBitmap)
  176. {
  177. BOOL rv = FALSE;
  178. if (!g_hDB || !pBitmap)
  179. goto exitpt;
  180. if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
  181. goto exitpt;
  182. if (_read(g_hDB, pBitmap, sizeof(*pBitmap)) != sizeof(*pBitmap))
  183. goto exitpt;
  184. rv = TRUE;
  185. exitpt:
  186. return rv;
  187. }
  188. /*++
  189. * Function:
  190. * WriteBitmapHeader (Thread dep)
  191. * Description:
  192. * Writes only the bitmap header
  193. * Arguments:
  194. * nOffset - where to store
  195. * pBitmap - what to store
  196. * Return value:
  197. * TRUE on success
  198. * Called by:
  199. * internaly
  200. --*/
  201. BOOL WriteBitmapHeader(FOFFSET nOffset, PBMPENTRY pBitmap)
  202. {
  203. BOOL rv = FALSE;
  204. if (!g_hDB || !pBitmap)
  205. goto exitpt;
  206. if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
  207. goto exitpt;
  208. if (_write(g_hDB, pBitmap, sizeof(*pBitmap)) != sizeof(*pBitmap))
  209. goto exitpt;
  210. rv = TRUE;
  211. exitpt:
  212. return rv;
  213. }
  214. /*++
  215. * Function:
  216. * ReadBitmap (Thread dependent)
  217. * Description:
  218. * Read the whole bitmap and allocates memory for it
  219. * Arguments:
  220. * nOffset - from where
  221. * Return value:
  222. * Pointer to the result, NULL on error
  223. * Called by:
  224. * internaly
  225. --*/
  226. PBMPENTRY ReadBitmap(FOFFSET nOffset)
  227. {
  228. PBMPENTRY rv = NULL;
  229. if (!g_hDB)
  230. goto exitpt;
  231. rv = malloc(sizeof(*rv));
  232. if (rv)
  233. {
  234. rv->pData = NULL;
  235. if (!ReadBitmapHeader(nOffset, rv))
  236. goto exitpt1;
  237. rv->pData = malloc(rv->nDataSize);
  238. if (rv->pData &&
  239. _read(g_hDB, rv->pData, rv->nDataSize) != (long)rv->nDataSize)
  240. {
  241. goto exitpt1;
  242. }
  243. }
  244. exitpt:
  245. return rv;
  246. exitpt1:
  247. if (rv)
  248. {
  249. if (rv->pData)
  250. free(rv->pData);
  251. free(rv);
  252. }
  253. return NULL;
  254. }
  255. /*++
  256. * Function:
  257. * FreeBitmap
  258. * Description:
  259. * Frees the resources allocated in ReadBitmap
  260. * Arguments:
  261. * pBmp - The bitmap
  262. * Called by:
  263. * internaly
  264. --*/
  265. VOID FreeBitmap(PBMPENTRY pBmp)
  266. {
  267. if (pBmp)
  268. {
  269. if (pBmp->pData)
  270. free(pBmp->pData);
  271. free(pBmp);
  272. }
  273. }
  274. /*++
  275. * Function:
  276. * EnumerateBitmaps
  277. * Description:
  278. * Enumaretes all bitmaps within a group
  279. * Arguments:
  280. * nOffset - Location
  281. * pfnEnumProc - Callback
  282. * pParam - callback parameter
  283. * Called by:
  284. * internaly
  285. --*/
  286. VOID EnumerateBitmaps(FOFFSET nOffset, PFNENUMBITMAPS pfnEnumProc, PVOID pParam)
  287. {
  288. PBMPENTRY pBmp;
  289. BOOL bRun = TRUE;
  290. while(bRun && nOffset && (pBmp = ReadBitmap(nOffset)))
  291. {
  292. if (!pBmp->bDeleted)
  293. bRun = pfnEnumProc(nOffset, pBmp, pParam);
  294. nOffset = pBmp->FOffsNext;
  295. FreeBitmap(pBmp);
  296. }
  297. }
  298. /*++
  299. * Function:
  300. * FindGroup
  301. * Description:
  302. * Retrieves a group by ID
  303. * Arguments:
  304. * szWText - the ID
  305. * Return value:
  306. * Group location, -1 on error
  307. --*/
  308. FOFFSET FindGroup(LPWSTR szWText)
  309. {
  310. GROUPENTRY Group;
  311. BOOL bRun;
  312. FOFFSET rv = 0;
  313. bRun = ReadGroup(0, &Group);
  314. while(bRun)
  315. {
  316. if (!Group.bDeleted && !wcscmp(Group.WText, szWText))
  317. break;
  318. if (!Group.FOffsNext)
  319. bRun = FALSE;
  320. else
  321. {
  322. rv = Group.FOffsNext;
  323. bRun = ReadGroup(Group.FOffsNext, &Group);
  324. }
  325. }
  326. if (!bRun)
  327. rv = -1;
  328. return rv;
  329. }
  330. /*++
  331. * Function:
  332. * FindBitmap
  333. * Description:
  334. * Finds a bitmap by ID and comment
  335. * Arguments:
  336. * szWText - ID
  337. * szComment - the comment
  338. * Return value:
  339. * The location of the bitmap, -1 on error
  340. --*/
  341. FOFFSET FindBitmap(LPWSTR szWText, char *szComment)
  342. {
  343. FOFFSET nGrpOffs, nBmpOffs;
  344. GROUPENTRY group;
  345. BMPENTRY Bitmap;
  346. FOFFSET rv = -1;
  347. BOOL bRun;
  348. if ((nGrpOffs = FindGroup(szWText)) == -1)
  349. goto exitpt;
  350. if (!ReadGroup(nGrpOffs, &group))
  351. goto exitpt;
  352. nBmpOffs = group.FOffsBmp;
  353. bRun = TRUE;
  354. while(bRun)
  355. {
  356. bRun = ReadBitmapHeader(nBmpOffs, &Bitmap);
  357. if (bRun)
  358. {
  359. if (!Bitmap.bDeleted && !strcmp(Bitmap.szComment, szComment))
  360. break;
  361. nBmpOffs = Bitmap.FOffsNext;
  362. }
  363. }
  364. if (bRun)
  365. rv = nBmpOffs;
  366. exitpt:
  367. return rv;
  368. }
  369. /*++
  370. * Function:
  371. * CheckSum
  372. * Description:
  373. * Calculates a check sum for block of memory
  374. * Helps for bitmaps comapring
  375. * Arguments:
  376. * pData - pointer to the block
  377. * nLen - block size
  378. * Return value:
  379. * the checksum
  380. * Called by:
  381. * AddBitMap, Glyph2String
  382. --*/
  383. UINT
  384. CheckSum(PVOID pData, UINT nLen)
  385. {
  386. UINT nChkSum = 0;
  387. BYTE *pbBlock = (BYTE *)pData;
  388. for(;nLen; nLen--, pbBlock++)
  389. nChkSum += (*pbBlock);
  390. return nChkSum;
  391. }
  392. /*++
  393. * Function:
  394. * AddBitmap (Thread dependent)
  395. * Description:
  396. * Adds a BitMap to the DB
  397. * Arguments:
  398. * pBitmap - the bitmap
  399. * szWText - ID
  400. * Return value:
  401. * TRUE on success
  402. * Called by:
  403. * glyphspy.c
  404. --*/
  405. BOOL AddBitMap(PBMPENTRY pBitmap, LPCWSTR szWText)
  406. {
  407. BMPENTRY bmp;
  408. GROUPENTRY group;
  409. INT strl;
  410. BOOL rv = FALSE;
  411. FOFFSET lGroupOffs, lBmpOffs;
  412. GROUPENTRY grpTemp;
  413. BMPENTRY bmpTemp;
  414. FOFFSET nOffs;
  415. PVOID pData;
  416. if (!g_hDB || !pBitmap || !pBitmap->pData || !wcslen(szWText))
  417. goto exitpt;
  418. memset(&group, 0, sizeof(group));
  419. memset(&bmp, 0, sizeof(bmp));
  420. bmp.nDataSize = pBitmap->nDataSize;
  421. bmp.bmiSize = pBitmap->bmiSize;
  422. bmp.bmpSize = pBitmap->bmpSize;
  423. bmp.xSize = pBitmap->xSize;
  424. bmp.ySize = pBitmap->ySize;
  425. bmp.nChkSum = CheckSum(pBitmap->pData, pBitmap->nDataSize);
  426. strcpy(bmp.szComment, pBitmap->szComment);
  427. strl = wcslen(szWText);
  428. if (strl > (sizeof(group.WText) - 1)/sizeof(WCHAR))
  429. strl = (sizeof(group.WText) - 1)/sizeof(WCHAR);
  430. wcsncpy(group.WText, szWText, strl);
  431. group.WText[strl] = 0;
  432. // Create group
  433. if ((lGroupOffs = FindGroup(group.WText)) == -1)
  434. {
  435. // A new group will be created
  436. lGroupOffs = _lseek(g_hDB, 0, SEEK_END);
  437. group.FOffsMe = lGroupOffs;
  438. if (_write(g_hDB, &group, sizeof(group)) != sizeof(group))
  439. {
  440. goto exitpt;
  441. }
  442. // Add this group to the list
  443. if (lGroupOffs)
  444. {
  445. nOffs = 0;
  446. while(ReadGroup(nOffs, &grpTemp) && grpTemp.FOffsNext)
  447. nOffs = grpTemp.FOffsNext;
  448. grpTemp.FOffsNext = lGroupOffs;
  449. if (!WriteGroup(nOffs, &grpTemp))
  450. goto exitpt;
  451. }
  452. } else {
  453. if (ReadGroup(lGroupOffs, &group) == -1)
  454. goto exitpt;
  455. }
  456. // Write the bitmap itself
  457. lBmpOffs = _lseek(g_hDB, 0, SEEK_END);
  458. bmp.FOffsMe = lBmpOffs;
  459. if (_write(g_hDB, &bmp, sizeof(bmp)) != sizeof(bmp))
  460. {
  461. goto exitpt;
  462. }
  463. if (_write(g_hDB, pBitmap->pData, pBitmap->nDataSize) !=
  464. (long)pBitmap->nDataSize)
  465. {
  466. goto exitpt;
  467. }
  468. // Add the bitmap to the list
  469. if (group.FOffsBmp)
  470. {
  471. nOffs = group.FOffsBmp;
  472. // Find end of the list and add
  473. while(ReadBitmapHeader(nOffs, &bmpTemp) && bmpTemp.FOffsNext)
  474. nOffs = bmpTemp.FOffsNext;
  475. bmpTemp.FOffsNext = lBmpOffs;
  476. if (!WriteBitmapHeader(nOffs, &bmpTemp))
  477. goto exitpt;
  478. } else {
  479. // No list add to group pointer
  480. group.FOffsBmp = lBmpOffs;
  481. if (!WriteGroup(lGroupOffs, &group))
  482. goto exitpt;
  483. }
  484. rv = TRUE;
  485. exitpt:
  486. return rv;
  487. }
  488. /*++
  489. * Ascii version of AddBitMap
  490. --*/
  491. BOOL AddBitMapA(PBMPENTRY pBitmap, LPCSTR szAText)
  492. {
  493. WCHAR szWText[MAX_STRING_LENGTH];
  494. BOOL rv = FALSE;
  495. INT ccAText = strlen(szAText);
  496. if (!strlen(szAText) ||
  497. !MultiByteToWideChar(
  498. CP_ACP,
  499. MB_ERR_INVALID_CHARS,
  500. szAText,
  501. -1,
  502. szWText,
  503. MAX_STRING_LENGTH - 1))
  504. goto exitpt;
  505. rv = AddBitMap(pBitmap, szWText);
  506. exitpt:
  507. return rv;
  508. }
  509. /*++
  510. * Function:
  511. * DeleteBitmapByPointer (Thread dep)
  512. * Description:
  513. * Deletes a bitmap identified by pointer
  514. * Arguments:
  515. * nBmpOffset - the pointer
  516. * Return value:
  517. * TRUE on success
  518. * Called by:
  519. * glyphspy.c
  520. --*/
  521. BOOL DeleteBitmapByPointer(FOFFSET nBmpOffs)
  522. {
  523. BMPENTRY Bitmap;
  524. BOOL rv = FALSE;
  525. if (!g_hDB || !nBmpOffs)
  526. goto exitpt;
  527. if (!ReadBitmapHeader(nBmpOffs, &Bitmap))
  528. goto exitpt;
  529. if (Bitmap.bDeleted)
  530. goto exitpt;
  531. Bitmap.bDeleted = TRUE;
  532. if (!WriteBitmapHeader(nBmpOffs, &Bitmap))
  533. goto exitpt;
  534. g_bNeedToPack = TRUE;
  535. rv = TRUE;
  536. exitpt:
  537. return rv;
  538. }
  539. /*++
  540. * Function:
  541. * DeleteGroupByPointer (Thread dep)
  542. * Description:
  543. * Deletes group with the same ID by pointer
  544. * Arguments:
  545. * nGrpOffs - the pointer
  546. * Return value:
  547. * TRUE on success
  548. * Called by:
  549. * glyphspy.c
  550. --*/
  551. BOOL DeleteGroupByPointer(FOFFSET nGrpOffs)
  552. {
  553. GROUPENTRY Group;
  554. BOOL rv = FALSE;
  555. if (!g_hDB)
  556. goto exitpt;
  557. if (!ReadGroup(nGrpOffs, &Group))
  558. goto exitpt;
  559. if (Group.bDeleted)
  560. goto exitpt;
  561. Group.bDeleted = TRUE;
  562. if (!WriteGroup(nGrpOffs, &Group))
  563. goto exitpt;
  564. g_bNeedToPack = TRUE;
  565. rv = TRUE;
  566. exitpt:
  567. return rv;
  568. }
  569. /*++
  570. * Function:
  571. * DeleteBitmap (Thread dep)
  572. * Description:
  573. * Deletes a bitmap identified by ID and comment
  574. * Arguments:
  575. * szWText - the ID
  576. * szComment - the comment
  577. * Return value:
  578. * TRUE on success
  579. --*/
  580. BOOL DeleteBitmap(LPWSTR szWText, char *szComment)
  581. {
  582. FOFFSET nBmpOffs;
  583. BOOL rv = FALSE;
  584. BMPENTRY Bitmap;
  585. if (!g_hDB)
  586. goto exitpt;
  587. nBmpOffs = FindBitmap(szWText, szComment);
  588. if (nBmpOffs == -1)
  589. goto exitpt;
  590. if (!ReadBitmapHeader(nBmpOffs, &Bitmap))
  591. goto exitpt;
  592. if (Bitmap.bDeleted)
  593. goto exitpt;
  594. Bitmap.bDeleted = TRUE;
  595. if (!WriteBitmapHeader(nBmpOffs, &Bitmap))
  596. goto exitpt;
  597. g_bNeedToPack = TRUE;
  598. rv = TRUE;
  599. exitpt:
  600. return rv;
  601. }
  602. /*++
  603. * Function:
  604. * _PackDB (Thread dep)
  605. * Description:
  606. * Copies the all database in new file removing
  607. * the deleted entrys
  608. * If it fails leaves the old file
  609. * Called by:
  610. * CloseDB
  611. --*/
  612. void _PackDB(void)
  613. {
  614. GROUPENTRY group;
  615. FOFFSET lGrpOffs = 0;
  616. FOFFSET lBmpOffs;
  617. if (!g_bNeedToPack)
  618. goto exitpt;
  619. g_hTempDB = _open(TEMPDB_NAME,
  620. _O_RDWR|_O_TRUNC|_O_CREAT|_O_BINARY,
  621. _S_IREAD|_S_IWRITE);
  622. if (g_hTempDB == -1)
  623. goto exitpt;
  624. do {
  625. if (!ReadGroup(lGrpOffs, &group))
  626. goto exitpt;
  627. if (!group.bDeleted)
  628. {
  629. lBmpOffs = group.FOffsBmp;
  630. while(lBmpOffs)
  631. {
  632. BMPENTRY Bitmap;
  633. if (!ReadBitmapHeader(lBmpOffs, &Bitmap))
  634. goto exitpt;
  635. if (!Bitmap.bDeleted)
  636. {
  637. PBMPENTRY pBmp = ReadBitmap(lBmpOffs);
  638. if (pBmp)
  639. {
  640. int hSwap;
  641. hSwap = g_hDB;
  642. g_hDB = g_hTempDB;
  643. g_hTempDB = hSwap;
  644. AddBitMap(pBmp,
  645. group.WText);
  646. hSwap = g_hDB;
  647. g_hDB = g_hTempDB;
  648. g_hTempDB = hSwap;
  649. FreeBitmap(pBmp);
  650. }
  651. }
  652. lBmpOffs = Bitmap.FOffsNext;
  653. }
  654. }
  655. lGrpOffs = group.FOffsNext;
  656. } while (lGrpOffs);
  657. _close(g_hTempDB);
  658. _close(g_hDB);
  659. remove(DB_NAME);
  660. rename(TEMPDB_NAME, DB_NAME);
  661. exitpt:
  662. ;
  663. }
  664. /*++
  665. * Function:
  666. * _CollectGroups (Thread dep)
  667. * Description:
  668. * Callback function wich collects all groups
  669. * from the database in linked list
  670. * Arguments:
  671. * nOffs - pointer to group record in the database
  672. * pGroup - ghe group
  673. * ppList - the list
  674. * Return value:
  675. * TRUE on success
  676. * Called by:
  677. * GetGroupList thru EnumerateGroups
  678. --*/
  679. BOOL _cdecl _CollectGroups(FOFFSET nOffs,
  680. PGROUPENTRY pGroup,
  681. PGROUPENTRY *ppList)
  682. {
  683. BOOL rv = FALSE;
  684. PGROUPENTRY pNewGrp, pIter, pPrev;
  685. if (!pGroup)
  686. goto exitpt;
  687. pNewGrp = malloc(sizeof(*pNewGrp));
  688. if (!pNewGrp)
  689. goto exitpt;
  690. memcpy(pNewGrp, pGroup, sizeof(*pNewGrp));
  691. // Add to the end of the queue
  692. pNewGrp->pNext = NULL;
  693. pPrev = NULL;
  694. pIter = *ppList;
  695. while(pIter)
  696. {
  697. pPrev = pIter;
  698. pIter = pIter->pNext;
  699. }
  700. if (pPrev)
  701. pPrev->pNext = pNewGrp;
  702. else
  703. (*ppList) = pNewGrp;
  704. rv = TRUE;
  705. exitpt:
  706. return rv;
  707. }
  708. /*++
  709. * Function:
  710. * GetGroupList
  711. * Description:
  712. * Gets all groups from the database
  713. * Return value:
  714. * linked list
  715. * Called by:
  716. * InitCache, glyphspy.c
  717. --*/
  718. PGROUPENTRY GetGroupList(VOID)
  719. {
  720. PGROUPENTRY pList = NULL;
  721. EnumerateGroups(_CollectGroups, &pList);
  722. return pList;
  723. }
  724. /*++
  725. * Function:
  726. * FreeGroupList
  727. * Description:
  728. * Frees the list allocated in GetGroupList
  729. * Arguments:
  730. * pList - the list
  731. * Called by:
  732. * DeleteCache, glyphspy.c
  733. --*/
  734. VOID FreeGroupList(PGROUPENTRY pList)
  735. {
  736. PGROUPENTRY pTmp, pIter = pList;
  737. while(pIter)
  738. {
  739. pTmp = pIter;
  740. pIter = pIter->pNext;
  741. free(pTmp);
  742. }
  743. }
  744. /*++
  745. * Function:
  746. * _CollectBitmaps (thread dep)
  747. * Description:
  748. * collects bitmaps in linked list
  749. * Arguments:
  750. * nOffs - pointer in the file
  751. * pBitmap - the bitmap
  752. * ppList - the list
  753. * Return value:
  754. * TRUE on success
  755. * Called by:
  756. * GetBitmapList thru EnumerateBitmaps
  757. --*/
  758. BOOL _cdecl _CollectBitmaps(FOFFSET nOffs,PBMPENTRY pBitmap, PBMPENTRY *ppList)
  759. {
  760. BOOL rv = FALSE;
  761. PBMPENTRY pNewBmp, pIter, pPrev;
  762. if (!pBitmap)
  763. goto exitpt;
  764. pNewBmp = malloc(sizeof(*pNewBmp));
  765. if (!pNewBmp)
  766. goto exitpt;
  767. memcpy(pNewBmp, pBitmap, sizeof(*pNewBmp));
  768. if (pNewBmp->nDataSize)
  769. {
  770. pNewBmp->pData = malloc(pNewBmp->nDataSize);
  771. if (!pNewBmp->pData)
  772. goto exitpt1;
  773. memcpy(pNewBmp->pData, pBitmap->pData, pNewBmp->nDataSize);
  774. } else
  775. pNewBmp->pData = NULL;
  776. // Add to the end of the queue
  777. pNewBmp->pNext = NULL;
  778. pPrev = NULL;
  779. pIter = *ppList;
  780. while(pIter)
  781. {
  782. pPrev = pIter;
  783. pIter = pIter->pNext;
  784. }
  785. if (pPrev)
  786. pPrev->pNext = pNewBmp;
  787. else
  788. (*ppList) = pNewBmp;
  789. rv = TRUE;
  790. exitpt:
  791. return rv;
  792. exitpt1:
  793. free(pNewBmp);
  794. return FALSE;
  795. }
  796. /*++
  797. * Function:
  798. * GetBitmapList (thread dep)
  799. * Description:
  800. * Gets all bitmaps within a group
  801. * Return value:
  802. * linked list
  803. * Called by:
  804. * Glyph2String, BitmapCacheLookup, glyphspy.c
  805. --*/
  806. PBMPENTRY GetBitmapList(HDC hDC, FOFFSET nOffs)
  807. {
  808. PBMPENTRY pList = NULL;
  809. PBMPENTRY pIter;
  810. EnumerateBitmaps(nOffs, _CollectBitmaps, &pList);
  811. pIter = pList;
  812. while(pIter)
  813. {
  814. // Create bitmaps if needed
  815. if (hDC)
  816. {
  817. if (!pIter->bmiSize)
  818. pIter->hBitmap =
  819. CreateBitmap(pIter->xSize,
  820. pIter->ySize,
  821. 1, 1,
  822. pIter->pData);
  823. else {
  824. pIter->hBitmap =
  825. CreateDIBitmap(hDC,
  826. (BITMAPINFOHEADER *)
  827. pIter->pData,
  828. CBM_INIT,
  829. ((BYTE *)(pIter->pData)) + pIter->bmiSize,
  830. (BITMAPINFO *)
  831. pIter->pData,
  832. DIB_PAL_COLORS);
  833. DeleteDC(hDC);
  834. }
  835. } else
  836. pIter->hBitmap = NULL;
  837. pIter = pIter->pNext;
  838. }
  839. return pList;
  840. }
  841. /*++
  842. * Function:
  843. * FreeBitmapList
  844. * Description:
  845. * Deletes resources allocated by GetBitmapList
  846. * Arguments:
  847. * pList - the list
  848. * Called by:
  849. * DeleteCache, glyphspy.c
  850. --*/
  851. VOID FreeBitmapList(PBMPENTRY pList)
  852. {
  853. PBMPENTRY pTmp, pIter = pList;
  854. while(pIter)
  855. {
  856. pTmp = pIter;
  857. pIter = pIter->pNext;
  858. if (pTmp->hBitmap)
  859. DeleteObject(pTmp->hBitmap);
  860. if ( pTmp->pData )
  861. free( pTmp->pData );
  862. free(pTmp);
  863. }
  864. }