Leaked source code of windows server 2003
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.

954 lines
24 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: DMGDB.C
  3. *
  4. * DDE manager data handling routines
  5. *
  6. * Created: 12/14/88 Sanford Staab
  7. *
  8. * Copyright (c) 1988, 1989 Microsoft Corporation
  9. \***************************************************************************/
  10. #include "ddemlp.h"
  11. /***************************** Private Function ****************************\
  12. * PAPPINFO GetCurrentAppInfo()
  13. *
  14. * DESCRIPTION:
  15. * This routine uses the pid of the current thread to locate the information
  16. * pertaining to that thread. If not found, 0 is returned.
  17. *
  18. * This call fails if the DLL is in a callback state to prevent recursion.
  19. * if fChkCallback is set.
  20. *
  21. * History: 1/1/89 Created sanfords
  22. \***************************************************************************/
  23. PAPPINFO GetCurrentAppInfo(
  24. PAPPINFO paiStart)
  25. {
  26. register PAPPINFO pai;
  27. HANDLE hTaskCurrent;
  28. SEMENTER();
  29. if (pAppInfoList == NULL) {
  30. SEMLEAVE();
  31. return(0);
  32. }
  33. pai = paiStart ? paiStart->next : pAppInfoList;
  34. hTaskCurrent = GetCurrentTask();
  35. while (pai) {
  36. if (pai->hTask == hTaskCurrent) {
  37. SEMLEAVE();
  38. return(pai);
  39. }
  40. pai = pai->next;
  41. }
  42. SEMLEAVE();
  43. return(0);
  44. }
  45. /***************************** Private Function ****************************\
  46. * void UnlinkAppInfo(pai)
  47. * PAPPINFO pai;
  48. *
  49. * DESCRIPTION:
  50. * unlinks an pai safely. Does nothing if not linked.
  51. *
  52. * History: 1/1/89 Created sanfords
  53. \***************************************************************************/
  54. void UnlinkAppInfo(pai)
  55. PAPPINFO pai;
  56. {
  57. PAPPINFO paiT;
  58. AssertF(pai != NULL, "UnlinkAppInfo - NULL input");
  59. SEMENTER();
  60. if (pai == pAppInfoList) {
  61. pAppInfoList = pai->next;
  62. SEMLEAVE();
  63. return;
  64. }
  65. paiT = pAppInfoList;
  66. while (paiT && paiT->next != pai)
  67. paiT = paiT->next;
  68. if (paiT)
  69. paiT->next = pai->next;
  70. SEMLEAVE();
  71. return;
  72. }
  73. /***************************** Private Functions ***************************\
  74. * General List management functions.
  75. *
  76. * History:
  77. * Created 12/15/88 sanfords
  78. \***************************************************************************/
  79. PLST CreateLst(hheap, cbItem)
  80. HANDLE hheap;
  81. WORD cbItem;
  82. {
  83. PLST pLst;
  84. SEMENTER();
  85. if (!(pLst = (PLST)FarAllocMem(hheap, sizeof(LST)))) {
  86. SEMLEAVE();
  87. return(NULL);
  88. }
  89. pLst->hheap = hheap;
  90. pLst->cbItem = cbItem;
  91. pLst->pItemFirst = (PLITEM)NULL;
  92. SEMLEAVE();
  93. return(pLst);
  94. }
  95. void DestroyLst(pLst)
  96. PLST pLst;
  97. {
  98. if (pLst == NULL)
  99. return;
  100. SEMENTER();
  101. while (pLst->pItemFirst)
  102. RemoveLstItem(pLst, pLst->pItemFirst);
  103. FarFreeMem((LPSTR)pLst);
  104. SEMLEAVE();
  105. }
  106. void DestroyAdvLst(pLst)
  107. PLST pLst;
  108. {
  109. if (pLst == NULL)
  110. return;
  111. SEMENTER();
  112. while (pLst->pItemFirst) {
  113. FreeHsz(((PADVLI)(pLst->pItemFirst))->aItem);
  114. RemoveLstItem(pLst, pLst->pItemFirst);
  115. }
  116. FarFreeMem((LPSTR)pLst);
  117. SEMLEAVE();
  118. }
  119. PLITEM FindLstItem(pLst, npfnCmp, piSearch)
  120. PLST pLst;
  121. NPFNCMP npfnCmp;
  122. PLITEM piSearch;
  123. {
  124. PLITEM pi;
  125. if (pLst == NULL)
  126. return(NULL);
  127. SEMENTER();
  128. pi = pLst->pItemFirst;
  129. while (pi) {
  130. if ((*npfnCmp)((LPBYTE)pi + sizeof(LITEM), (LPBYTE)piSearch + sizeof(LITEM))) {
  131. SEMLEAVE();
  132. return(pi);
  133. }
  134. pi = pi->next;
  135. }
  136. SEMLEAVE();
  137. return(pi);
  138. }
  139. /*
  140. * Comparison functions for FindLstItem() and FindPileItem()
  141. */
  142. BOOL CmpDWORD(pb1, pb2)
  143. LPBYTE pb1;
  144. LPBYTE pb2;
  145. {
  146. return(*(LPDWORD)pb1 == *(LPDWORD)pb2);
  147. }
  148. BOOL CmpWORD(pb1, pb2)
  149. LPBYTE pb1;
  150. LPBYTE pb2;
  151. {
  152. return(*(LPWORD)pb1 == *(LPWORD)pb2);
  153. }
  154. BOOL CmpHIWORD(pb1, pb2)
  155. LPBYTE pb1;
  156. LPBYTE pb2;
  157. {
  158. return(*(LPWORD)(pb1 + 2) == *(LPWORD)(pb2 + 2));
  159. }
  160. /***************************** Private Function ****************************\
  161. * This routine creates a new list item for pLst and links it in according
  162. * to the ILST_ constant in afCmd. Returns a pointer to the new item
  163. * or NULL on failure.
  164. *
  165. * Note: This MUST be in the semaphore for use since the new list item
  166. * is filled with garbage on return yet is linked in.
  167. *
  168. *
  169. * History:
  170. * Created 9/12/89 Sanfords
  171. \***************************************************************************/
  172. PLITEM NewLstItem(pLst, afCmd)
  173. PLST pLst;
  174. WORD afCmd;
  175. {
  176. PLITEM pi, piT;
  177. if (pLst == NULL)
  178. return(NULL);
  179. SEMCHECKIN();
  180. pi = (PLITEM)FarAllocMem(pLst->hheap, pLst->cbItem + sizeof(LITEM));
  181. if (pi == NULL) {
  182. AssertF(FALSE, "NewLstItem - memory failure");
  183. return(NULL);
  184. }
  185. if (afCmd & ILST_NOLINK)
  186. return(pi);
  187. if (((piT = pLst->pItemFirst) == NULL) || (afCmd & ILST_FIRST)) {
  188. pi->next = piT;
  189. pLst->pItemFirst = pi;
  190. } else { /* ILST_LAST assumed */
  191. while (piT->next != NULL)
  192. piT = piT->next;
  193. piT->next = pi;
  194. pi->next = NULL;
  195. }
  196. return(pi);
  197. }
  198. /***************************** Private Function ****************************\
  199. * This routine unlinks and frees pi from pLst. If pi cannot be located
  200. * within pLst, it is freed anyway.
  201. *
  202. * History:
  203. * Created 9/12/89 Sanfords
  204. \***************************************************************************/
  205. BOOL RemoveLstItem(pLst, pi)
  206. PLST pLst;
  207. PLITEM pi;
  208. {
  209. PLITEM piT;
  210. if (pLst == NULL || pi == NULL)
  211. return(FALSE);
  212. SEMCHECKIN();
  213. if ((piT = pLst->pItemFirst) != NULL) {
  214. if (pi == piT) {
  215. pLst->pItemFirst = pi->next;
  216. } else {
  217. while (piT->next != pi && piT->next != NULL)
  218. piT = piT->next;
  219. if (piT->next != NULL)
  220. piT->next = pi->next; /* unlink */
  221. }
  222. } else {
  223. AssertF(FALSE, "Improper list item removal");
  224. return(FALSE);
  225. }
  226. FarFreeMem((LPSTR)pi);
  227. return(TRUE);
  228. }
  229. /*
  230. * ------------- Specific list routines -------------
  231. */
  232. /***************************** Private Function ****************************\
  233. * hwnd-hsz list functions
  234. *
  235. * History: 1/20/89 Created sanfords
  236. \***************************************************************************/
  237. void AddHwndHszList(
  238. ATOM a,
  239. HWND hwnd,
  240. PLST pLst)
  241. {
  242. PHWNDHSZLI phhi;
  243. AssertF(pLst->cbItem == sizeof(HWNDHSZLI), "AddHwndHszList - Bad item size");
  244. SEMENTER();
  245. if (!a || (BOOL)HwndFromHsz(a, pLst)) {
  246. SEMLEAVE();
  247. return;
  248. }
  249. phhi = (PHWNDHSZLI)NewLstItem(pLst, ILST_FIRST);
  250. phhi->hwnd = hwnd;
  251. phhi->a = a;
  252. IncHszCount(a); // structure copy
  253. SEMLEAVE();
  254. }
  255. void DestroyHwndHszList(pLst)
  256. PLST pLst;
  257. {
  258. if (pLst == NULL)
  259. return;
  260. AssertF(pLst->cbItem == sizeof(HWNDHSZLI), "DestroyHwndHszList - Bad item size");
  261. SEMENTER();
  262. while (pLst->pItemFirst) {
  263. FreeHsz(((PHWNDHSZLI)pLst->pItemFirst)->a);
  264. RemoveLstItem(pLst, pLst->pItemFirst);
  265. }
  266. FarFreeMem((LPSTR)pLst);
  267. SEMLEAVE();
  268. }
  269. HWND HwndFromHsz(
  270. ATOM a,
  271. PLST pLst)
  272. {
  273. HWNDHSZLI hhli;
  274. PHWNDHSZLI phhli;
  275. hhli.a = a;
  276. if (!(phhli = (PHWNDHSZLI)FindLstItem(pLst, CmpWORD, (PLITEM)&hhli)))
  277. return(NULL);
  278. return(phhli->hwnd);
  279. }
  280. /***************************** Private Function ****************************\
  281. * DESCRIPTION:
  282. * Advise list helper functions.
  283. *
  284. * History: 1/20/89 Created sanfords
  285. \***************************************************************************/
  286. /*
  287. * This will match an exact hsz/fmt pair with a 0 format or 0 item or 0 hwnd
  288. * being wild.
  289. */
  290. BOOL CmpAdv(
  291. LPBYTE pb1, // entry being compared
  292. LPBYTE pb2) // search for
  293. {
  294. PADVLI pali1 = (PADVLI)(pb1 - sizeof(LITEM));
  295. PADVLI pali2 = (PADVLI)(pb2 - sizeof(LITEM));
  296. if (pali2->aTopic == 0 || pali1->aTopic == pali2->aTopic) {
  297. if (pali2->hwnd == 0 || pali1->hwnd == pali2->hwnd) {
  298. if (pali2->aItem == 0 || pali1->aItem == pali2->aItem ) {
  299. if (pali2->wFmt == 0 || pali1->wFmt == pali2->wFmt) {
  300. return(TRUE);
  301. }
  302. }
  303. }
  304. }
  305. return(FALSE);
  306. }
  307. WORD CountAdvReqLeft(
  308. PADVLI pali)
  309. {
  310. ADVLI aliKey;
  311. register WORD cLoops = 0;
  312. SEMENTER();
  313. aliKey = *pali;
  314. aliKey.hwnd = 0; // all hwnds
  315. pali = (PADVLI)aliKey.next;
  316. while (pali) {
  317. if (CmpAdv(((LPBYTE)pali) + sizeof(LITEM),
  318. ((LPBYTE)&aliKey) + sizeof(LITEM))) {
  319. cLoops++;
  320. }
  321. pali = (PADVLI)pali->next;
  322. }
  323. SEMLEAVE();
  324. return(cLoops);
  325. }
  326. BOOL AddAdvList(
  327. PLST pLst,
  328. HWND hwnd,
  329. ATOM aTopic,
  330. ATOM aItem,
  331. WORD fsStatus,
  332. WORD wFmt)
  333. {
  334. PADVLI pali;
  335. AssertF(pLst->cbItem == sizeof(ADVLI), "AddAdvList - bad item size");
  336. if (!aItem)
  337. return(TRUE);
  338. SEMENTER();
  339. if (!(pali = FindAdvList(pLst, hwnd, aTopic, aItem, wFmt))) {
  340. IncHszCount(aItem); // structure copy
  341. pali = (PADVLI)NewLstItem(pLst, ILST_FIRST);
  342. }
  343. AssertF((BOOL)(DWORD)pali, "AddAdvList - NewLstItem() failed")
  344. if (pali != NULL) {
  345. pali->aItem = aItem;
  346. pali->aTopic = aTopic;
  347. pali->wFmt = wFmt;
  348. pali->fsStatus = fsStatus;
  349. pali->hwnd = hwnd;
  350. }
  351. SEMLEAVE();
  352. return((BOOL)(DWORD)pali);
  353. }
  354. /*
  355. * This will delete the matching Advise loop entry. If wFmt is 0, all
  356. * entries with the same hszItem are deleted.
  357. * Returns fNotEmptyAfterDelete.
  358. */
  359. BOOL DeleteAdvList(
  360. PLST pLst,
  361. HWND hwnd,
  362. ATOM aTopic,
  363. ATOM aItem,
  364. WORD wFmt)
  365. {
  366. PADVLI pali;
  367. AssertF(pLst->cbItem == sizeof(ADVLI), "DeleteAdvList - bad item size");
  368. SEMENTER();
  369. while (pali = (PADVLI)FindAdvList(pLst, hwnd, aTopic, aItem, wFmt)) {
  370. FreeHsz(pali->aItem);
  371. RemoveLstItem(pLst, (PLITEM)pali);
  372. }
  373. SEMLEAVE();
  374. return((BOOL)(DWORD)pLst->pItemFirst);
  375. }
  376. /***************************** Private Function ****************************\
  377. * This routine searches the advise list for and entry in hszItem. It returns
  378. * pAdvli only if the item is found.
  379. *
  380. * History:
  381. * Created 9/12/89 Sanfords
  382. \***************************************************************************/
  383. PADVLI FindAdvList(
  384. PLST pLst,
  385. HWND hwnd,
  386. ATOM aTopic,
  387. ATOM aItem,
  388. WORD wFmt)
  389. {
  390. ADVLI advli;
  391. AssertF(pLst->cbItem == sizeof(ADVLI), "FindAdvList - bad item size");
  392. advli.aItem = aItem;
  393. advli.aTopic = aTopic;
  394. advli.wFmt = wFmt;
  395. advli.hwnd = hwnd;
  396. return((PADVLI)FindLstItem(pLst, CmpAdv, (PLITEM)&advli));
  397. }
  398. /***************************** Private Function ****************************\
  399. * This routine searches for the next entry for hszItem. It returns
  400. * pAdvli only if the item is found. aTopic and hwnd should NOT be 0.
  401. *
  402. * History:
  403. * Created 11/15/89 Sanfords
  404. \***************************************************************************/
  405. PADVLI FindNextAdv(
  406. PADVLI padvli,
  407. HWND hwnd,
  408. ATOM aTopic,
  409. ATOM aItem)
  410. {
  411. SEMENTER();
  412. while ((padvli = (PADVLI)padvli->next) != NULL) {
  413. if (hwnd == 0 || hwnd == padvli->hwnd) {
  414. if (aTopic == 0 || aTopic == padvli->aTopic) {
  415. if (aItem == 0 || padvli->aItem == aItem) {
  416. break;
  417. }
  418. }
  419. }
  420. }
  421. SEMLEAVE();
  422. return(padvli);
  423. }
  424. /***************************** Private Function ****************************\
  425. * This routine removes all list items associated with hwnd.
  426. *
  427. * History:
  428. * Created 4/17/91 Sanfords
  429. \***************************************************************************/
  430. VOID CleanupAdvList(
  431. HWND hwnd,
  432. PCLIENTINFO pci)
  433. {
  434. PADVLI pali, paliNext;
  435. PLST plst;
  436. if (pci->ci.fs & ST_CLIENT) {
  437. plst = pci->pClientAdvList;
  438. } else {
  439. plst = pci->ci.pai->pServerAdvList;
  440. }
  441. AssertF(plst->cbItem == sizeof(ADVLI), "CleanupAdvList - bad item size");
  442. SEMENTER();
  443. for (pali = (PADVLI)plst->pItemFirst; pali; pali = paliNext) {
  444. paliNext = (PADVLI)pali->next;
  445. if (pali->hwnd == hwnd) {
  446. MONLINK(pci->ci.pai, FALSE, pali->fsStatus & DDE_FDEFERUPD,
  447. (HSZ)pci->ci.aServerApp, (HSZ)pci->ci.aTopic,
  448. (HSZ)pali->aItem, pali->wFmt,
  449. (pci->ci.fs & ST_CLIENT) ? FALSE : TRUE,
  450. (pci->ci.fs & ST_CLIENT) ?
  451. pci->ci.hConvPartner : MAKEHCONV(hwnd),
  452. (pci->ci.fs & ST_CLIENT) ?
  453. MAKEHCONV(hwnd) : pci->ci.hConvPartner);
  454. FreeHsz(pali->aItem);
  455. RemoveLstItem(plst, (PLITEM)pali);
  456. }
  457. }
  458. SEMLEAVE();
  459. }
  460. /***************************** Pile Functions ********************************\
  461. *
  462. * A pile is a list where each item is an array of subitems. This allows
  463. * a more memory efficient method of handling unordered lists.
  464. *
  465. \*****************************************************************************/
  466. PPILE CreatePile(hheap, cbItem, cItemsPerBlock)
  467. HANDLE hheap;
  468. WORD cbItem;
  469. WORD cItemsPerBlock;
  470. {
  471. PPILE ppile;
  472. if (!(ppile = (PPILE)FarAllocMem(hheap, sizeof(PILE)))) {
  473. SEMLEAVE();
  474. return(NULL);
  475. }
  476. ppile->pBlockFirst = NULL;
  477. ppile->hheap = hheap;
  478. ppile->cbBlock = cbItem * cItemsPerBlock + sizeof(PILEB);
  479. ppile->cSubItemsMax = cItemsPerBlock;
  480. ppile->cbSubItem = cbItem;
  481. return(ppile);
  482. }
  483. PPILE DestroyPile(pPile)
  484. PPILE pPile;
  485. {
  486. if (pPile == NULL)
  487. return(NULL);
  488. SEMENTER();
  489. while (pPile->pBlockFirst)
  490. RemoveLstItem((PLST)pPile, (PLITEM)pPile->pBlockFirst);
  491. FarFreeMem((LPSTR)pPile);
  492. SEMLEAVE();
  493. return(NULL);
  494. }
  495. WORD QPileItemCount(pPile)
  496. PPILE pPile;
  497. {
  498. register WORD c;
  499. PPILEB pBlock;
  500. if (pPile == NULL)
  501. return(0);
  502. SEMENTER();
  503. pBlock = pPile->pBlockFirst;
  504. c = 0;
  505. while (pBlock) {
  506. c += pBlock->cItems;
  507. pBlock = pBlock->next;
  508. }
  509. SEMLEAVE();
  510. return(c);
  511. }
  512. /***************************** Private Function ****************************\
  513. * Locate and return the pointer to the pile subitem who's key fields match
  514. * pbSearch using npfnCmp to compare the fields. If pbSearch == NULL, or
  515. * npfnCmp == NULL, the first subitem is returned.
  516. *
  517. * afCmd may be:
  518. * FPI_DELETE - delete the located item
  519. * In this case, the returned pointer is not valid.
  520. *
  521. * pppb points to where to store a pointer to the block which contained
  522. * the located item.
  523. *
  524. * if pppb == NULL, it is ignored.
  525. *
  526. * NULL is returned if pbSearch was not found or if the list was empty.
  527. *
  528. * History:
  529. * Created 9/12/89 Sanfords
  530. \***************************************************************************/
  531. LPBYTE FindPileItem(pPile, npfnCmp, pbSearch, afCmd)
  532. PPILE pPile;
  533. NPFNCMP npfnCmp;
  534. LPBYTE pbSearch;
  535. WORD afCmd;
  536. {
  537. LPBYTE psi; // subitem pointer.
  538. PPILEB pBlockCur; // current block pointer.
  539. register WORD i;
  540. if (pPile == NULL)
  541. return(NULL);
  542. SEMENTER();
  543. pBlockCur = pPile->pBlockFirst;
  544. /*
  545. * while this block is not the end...
  546. */
  547. while (pBlockCur) {
  548. for (psi = (LPBYTE)pBlockCur + sizeof(PILEB), i = 0;
  549. i < pBlockCur->cItems;
  550. psi += pPile->cbSubItem, i++) {
  551. if (pbSearch == NULL || npfnCmp == NULL || (*npfnCmp)(psi, pbSearch)) {
  552. if (afCmd & FPI_DELETE) {
  553. /*
  554. * remove entire block if this was the last subitem in it.
  555. */
  556. if (--pBlockCur->cItems == 0) {
  557. RemoveLstItem((PLST)pPile, (PLITEM)pBlockCur);
  558. } else {
  559. /*
  560. * copy last subitem in the block over the removed item.
  561. */
  562. hmemcpy(psi, (LPBYTE)pBlockCur + sizeof(PILEB) +
  563. pPile->cbSubItem * pBlockCur->cItems,
  564. pPile->cbSubItem);
  565. }
  566. }
  567. return(psi); // found
  568. }
  569. }
  570. pBlockCur = (PPILEB)pBlockCur->next;
  571. }
  572. SEMLEAVE();
  573. return(NULL); // not found.
  574. }
  575. /***************************** Private Function ****************************\
  576. * Places a copy of the subitem pointed to by pb into the first available
  577. * spot in the pile pPile. If npfnCmp != NULL, the pile is first searched
  578. * for a pb match. If found, pb replaces the located data.
  579. *
  580. * Returns:
  581. * API_FOUND if already there
  582. * API_ERROR if an error happened
  583. * API_ADDED if not found and added
  584. *
  585. * History:
  586. * Created 9/12/89 Sanfords
  587. \***************************************************************************/
  588. WORD AddPileItem(pPile, pb, npfnCmp)
  589. PPILE pPile;
  590. LPBYTE pb;
  591. BOOL (*npfnCmp)(LPBYTE pbb, LPBYTE pbSearch);
  592. {
  593. LPBYTE pbDst;
  594. PPILEB ppb;
  595. if (pPile == NULL)
  596. return(FALSE);
  597. SEMENTER();
  598. if (npfnCmp != NULL && (pbDst = FindPileItem(pPile, npfnCmp, pb, 0)) !=
  599. NULL) {
  600. hmemcpy(pbDst, pb, pPile->cbSubItem);
  601. SEMLEAVE();
  602. return(API_FOUND);
  603. }
  604. ppb = pPile->pBlockFirst;
  605. /*
  606. * locate a block with room
  607. */
  608. while ((ppb != NULL) && ppb->cItems == pPile->cSubItemsMax) {
  609. ppb = (PPILEB)ppb->next;
  610. }
  611. /*
  612. * If all full or no blocks, make a new one, link it on the bottom.
  613. */
  614. if (ppb == NULL) {
  615. ppb = (PPILEB)NewLstItem((PLST)pPile, ILST_LAST);
  616. if (ppb == NULL) {
  617. SEMLEAVE();
  618. return(API_ERROR);
  619. }
  620. ppb->cItems = 0;
  621. }
  622. /*
  623. * add the subitem
  624. */
  625. hmemcpy((LPBYTE)ppb + sizeof(PILEB) + pPile->cbSubItem * ppb->cItems++,
  626. pb, pPile->cbSubItem);
  627. SEMLEAVE();
  628. return(API_ADDED);
  629. }
  630. /***************************** Private Function ****************************\
  631. * Fills pb with a copy of the top item's data and removes it from the pile.
  632. * returns FALSE if the pile was empty.
  633. *
  634. * History:
  635. * Created 9/12/89 Sanfords
  636. \***************************************************************************/
  637. BOOL PopPileSubitem(pPile, pb)
  638. PPILE pPile;
  639. LPBYTE pb;
  640. {
  641. PPILEB ppb;
  642. LPBYTE pSrc;
  643. if ((pPile == NULL) || ((ppb = pPile->pBlockFirst) == NULL))
  644. return(FALSE);
  645. SEMENTER();
  646. pSrc = (LPBYTE)pPile->pBlockFirst + sizeof(PILEB);
  647. hmemcpy(pb, pSrc, pPile->cbSubItem);
  648. /*
  649. * remove entire block if this was the last subitem in it.
  650. */
  651. if (pPile->pBlockFirst->cItems == 1) {
  652. RemoveLstItem((PLST)pPile, (PLITEM)pPile->pBlockFirst);
  653. } else {
  654. /*
  655. * move last item in block to replace copied subitem and decrement
  656. * subitem count.
  657. */
  658. hmemcpy(pSrc, pSrc + pPile->cbSubItem * --pPile->pBlockFirst->cItems,
  659. pPile->cbSubItem);
  660. }
  661. SEMLEAVE();
  662. return(TRUE);
  663. }
  664. #if 0
  665. /***************************** Semaphore Functions *************************\
  666. * SEMENTER() and SEMLEAVE() are macros.
  667. *
  668. * History: 1/1/89 Created sanfords
  669. \***************************************************************************/
  670. void SemInit()
  671. {
  672. LPBYTE pSem;
  673. SHORT c;
  674. pSem = (LPBYTE) & FSRSemDmg;
  675. c = 0;
  676. while (c++ < sizeof(DOSFSRSEM)) {
  677. *pSem++ = 0;
  678. }
  679. FSRSemDmg.cb = sizeof(DOSFSRSEM);
  680. }
  681. void SemCheckIn()
  682. {
  683. PIDINFO pi;
  684. BOOL fin;
  685. DosGetPID(&pi);
  686. fin = (FSRSemDmg.cUsage > 0) && (FSRSemDmg.pid == pi.pid) && ((FSRSemDmg.tid ==
  687. pi.tid) || (FSRSemDmg.tid == -1));
  688. /*
  689. * !!! NOTE: during exitlists processing, semaphore TIDs are set to -1
  690. */
  691. AssertF(fin, "SemCheckIn - Out of Semaphore");
  692. if (!fin)
  693. SEMENTER();
  694. }
  695. void SemCheckOut()
  696. {
  697. PIDINFO pi;
  698. BOOL fOut;
  699. DosGetPID(&pi);
  700. fOut = FSRSemDmg.cUsage == 0 || FSRSemDmg.pid != pi.pid || FSRSemDmg.tid !=
  701. pi.tid;
  702. AssertF(fOut, "SemCheckOut - In Semaphore");
  703. if (!fOut)
  704. while (FSRSemDmg.cUsage)
  705. SEMLEAVE();
  706. }
  707. void SemEnter()
  708. {
  709. DosFSRamSemRequest(&FSRSemDmg, SEM_INDEFINITE_WAIT);
  710. }
  711. void SemLeave()
  712. {
  713. DosFSRamSemClear(&FSRSemDmg);
  714. }
  715. #endif // 0
  716. BOOL CopyHugeBlock(pSrc, pDst, cb)
  717. LPBYTE pSrc;
  718. LPBYTE pDst;
  719. DWORD cb;
  720. {
  721. DWORD cFirst;
  722. /*
  723. * |____________| |___________| |____________| |____________|
  724. * ^src ^
  725. *
  726. * |____________| |___________| |____________| |____________|
  727. * ^dst ^
  728. */
  729. /*
  730. * The following check determines whether the copy can be done
  731. * in one short copy operation. Checks whether the byte count
  732. * is small enough to span the bytes to the right of the greater
  733. * of pSrc and pDst.
  734. */
  735. cFirst = (DWORD)min(~LOWORD((DWORD)pSrc), ~LOWORD((DWORD)pDst)) + 1L;
  736. /* cFirst is # of bytes to end of seg, for buffer w/ biggest offset */
  737. if (cb < cFirst) {
  738. hmemcpy(pDst, pSrc, (WORD)cb);
  739. return(TRUE);
  740. }
  741. goto copyit; /* if not, jump into while loop */
  742. /*
  743. * Now at least one of the pointers is on a segment boundry.
  744. */
  745. while (cb) {
  746. cFirst = min(0x10000 - (LOWORD((DWORD)pSrc) | LOWORD((DWORD)pDst)), (LONG)cb);
  747. copyit:
  748. if (HIWORD(cFirst)) {
  749. /*
  750. * special case where pSrc and pDst both are on segment
  751. * bounds. Copy half at a time. First half first.
  752. */
  753. /*
  754. * |___________| |____________| |____________|
  755. * ^src ^
  756. *
  757. * |___________| |____________| |____________|
  758. * ^dst ^
  759. */
  760. cFirst >>= 1; /* half the span */
  761. hmemcpy(pDst, pSrc, (WORD)cFirst);
  762. pSrc += cFirst; /* inc ptrs */
  763. pDst += cFirst;
  764. cb -= cFirst; /* dec bytecount */
  765. }
  766. hmemcpy(pDst, pSrc, (WORD)cFirst);
  767. pSrc = HugeOffset(pSrc, cFirst);
  768. pDst = HugeOffset(pDst, cFirst);
  769. cb -= cFirst;
  770. /*
  771. * |____________| |___________| |____________| |____________|
  772. * ^src ^
  773. *
  774. * |____________| |___________| |____________| |____________|
  775. * ^dst ^
  776. */
  777. }
  778. return(TRUE);
  779. }
  780. /***************************************************************************\
  781. * Kills windows but avoids invalid window rips in debugger.
  782. \***************************************************************************/
  783. BOOL DmgDestroyWindow(hwnd)
  784. HWND hwnd;
  785. {
  786. if (IsWindow(hwnd))
  787. return(DestroyWindow(hwnd));
  788. return(TRUE);
  789. }
  790. BOOL ValidateHConv(
  791. HCONV hConv)
  792. {
  793. return(IsWindow((HWND)hConv) &&
  794. GetWindowWord((HWND)hConv, GWW_CHECKVAL) == HIWORD(hConv));
  795. }
  796. #ifdef DEBUG
  797. void _loadds fAssert(
  798. BOOL f,
  799. LPSTR pszComment,
  800. WORD line,
  801. LPSTR szfile,
  802. BOOL fWarning)
  803. {
  804. char szT[90];
  805. if (!f) {
  806. wsprintf(szT, "\n\rAssertion failure: %s:%d %s\n\r",
  807. szfile, line, pszComment);
  808. OutputDebugString((LPSTR)szT);
  809. if (!fWarning)
  810. DEBUGBREAK();
  811. }
  812. }
  813. #endif /* DEBUG */