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.

887 lines
24 KiB

  1. #include "precomp.h"
  2. //
  3. // HET.C
  4. // Hosted Entity Tracker, NT Display Driver version
  5. //
  6. // Copyright(c)Microsoft 1997-
  7. //
  8. #include <limits.h>
  9. //
  10. // HET_DDTerm()
  11. //
  12. void HET_DDTerm(void)
  13. {
  14. LPHET_WINDOW_MEMORY pMem;
  15. DebugEntry(HET_DDTerm);
  16. //
  17. // Clean up any window/graphics tracking stuff
  18. //
  19. g_hetDDDesktopIsShared = FALSE;
  20. HETDDViewing(NULL, FALSE);
  21. HETDDUnshareAll();
  22. //
  23. // Loop through the memory list blocks, freeing each. Then clear
  24. // the Window and Free lists.
  25. //
  26. while (pMem = COM_BasedListFirst(&g_hetMemoryList, FIELD_OFFSET(HET_WINDOW_MEMORY, chain)))
  27. {
  28. TRACE_OUT(("HET_DDTerm: Freeing memory block %lx", pMem));
  29. COM_BasedListRemove(&(pMem->chain));
  30. EngFreeMem(pMem);
  31. }
  32. //
  33. // Clear the window linked lists since they contain elements in
  34. // the now free memory block.
  35. //
  36. COM_BasedListInit(&g_hetFreeWndList);
  37. COM_BasedListInit(&g_hetWindowList);
  38. DebugExitVOID(HET_DDTerm);
  39. }
  40. //
  41. // HET_DDProcessRequest - see host.h
  42. //
  43. ULONG HET_DDProcessRequest(SURFOBJ *pso,
  44. UINT cjIn,
  45. void * pvIn,
  46. UINT cjOut,
  47. void * pvOut)
  48. {
  49. ULONG rc = TRUE;
  50. LPOSI_ESCAPE_HEADER pHeader;
  51. DebugEntry(HET_DDProcessRequest);
  52. pHeader = pvIn;
  53. TRACE_OUT(( "Request %#x", pHeader->escapeFn));
  54. switch (pHeader->escapeFn)
  55. {
  56. case HET_ESC_SHARE_WINDOW:
  57. {
  58. if ((cjIn != sizeof(HET_SHARE_WINDOW)) ||
  59. (cjOut != sizeof(HET_SHARE_WINDOW)))
  60. {
  61. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_SHARE_WINDOW",
  62. cjIn, cjOut));
  63. rc = FALSE;
  64. DC_QUIT;
  65. }
  66. ((LPHET_SHARE_WINDOW)pvOut)->result =
  67. HETDDShareWindow(pso, (LPHET_SHARE_WINDOW)pvIn);
  68. }
  69. break;
  70. case HET_ESC_UNSHARE_WINDOW:
  71. {
  72. if ((cjIn != sizeof(HET_UNSHARE_WINDOW)) ||
  73. (cjOut != sizeof(HET_UNSHARE_WINDOW)))
  74. {
  75. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_UNSHARE_WINDOW",
  76. cjIn, cjOut));
  77. rc = FALSE;
  78. DC_QUIT;
  79. }
  80. HETDDUnshareWindow((LPHET_UNSHARE_WINDOW)pvIn);
  81. }
  82. break;
  83. case HET_ESC_UNSHARE_ALL:
  84. {
  85. if ((cjIn != sizeof(HET_UNSHARE_ALL)) ||
  86. (cjOut != sizeof(HET_UNSHARE_ALL)))
  87. {
  88. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_UNSHARE_ALL",
  89. cjIn, cjOut));
  90. rc = FALSE;
  91. DC_QUIT;
  92. }
  93. HETDDUnshareAll();
  94. }
  95. break;
  96. case HET_ESC_SHARE_DESKTOP:
  97. {
  98. if ((cjIn != sizeof(HET_SHARE_DESKTOP)) ||
  99. (cjOut != sizeof(HET_SHARE_DESKTOP)))
  100. {
  101. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_SHARE_DESKTOP",
  102. cjIn, cjOut));
  103. rc = FALSE;
  104. DC_QUIT;
  105. }
  106. g_hetDDDesktopIsShared = TRUE;
  107. }
  108. break;
  109. case HET_ESC_UNSHARE_DESKTOP:
  110. {
  111. if ((cjIn != sizeof(HET_UNSHARE_DESKTOP)) ||
  112. (cjOut != sizeof(HET_UNSHARE_DESKTOP)))
  113. {
  114. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_UNSHARE_DESKTOP",
  115. cjIn, cjOut));
  116. rc = FALSE;
  117. DC_QUIT;
  118. }
  119. g_hetDDDesktopIsShared = FALSE;
  120. HETDDViewing(NULL, FALSE);
  121. }
  122. break;
  123. case HET_ESC_VIEWER:
  124. {
  125. //
  126. // We may turn OFF viewing but keep stuff shared and the windows
  127. // tracked -- hosting a meeting and sharing something, for
  128. // example.
  129. //
  130. if ((cjIn != sizeof(HET_VIEWER)) ||
  131. (cjOut != sizeof(HET_VIEWER)))
  132. {
  133. ERROR_OUT(("HET_DDProcessRequest: Invalid sizes %d, %d for HET_ESC_VIEWER",
  134. cjIn, cjOut));
  135. rc = FALSE;
  136. DC_QUIT;
  137. }
  138. HETDDViewing(pso, (((LPHET_VIEWER)pvIn)->viewersPresent != 0));
  139. break;
  140. }
  141. default:
  142. {
  143. ERROR_OUT(( "Unknown request type %#x", pHeader->escapeFn));
  144. rc = FALSE;
  145. }
  146. break;
  147. }
  148. DC_EXIT_POINT:
  149. DebugExitDWORD(HET_DDProcessRequest, rc);
  150. return(rc);
  151. }
  152. //
  153. // HET_DDOutputIsHosted - see host.h
  154. //
  155. BOOL HET_DDOutputIsHosted(POINT pt)
  156. {
  157. BOOL rc = FALSE;
  158. UINT j;
  159. LPHET_WINDOW_STRUCT pWnd;
  160. DebugEntry(HET_DDOutputIsHosted);
  161. //
  162. // Now check to see if the desktop is shared - if it is then simply
  163. // return TRUE.
  164. //
  165. if (g_hetDDDesktopIsShared)
  166. {
  167. rc = TRUE;
  168. DC_QUIT;
  169. }
  170. //
  171. // Search through the window list
  172. //
  173. pWnd = COM_BasedListFirst(&g_hetWindowList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  174. while (pWnd != NULL)
  175. {
  176. //
  177. // Search each enumerated rectangle
  178. //
  179. TRACE_OUT(( "Window %#x has %u rectangle(s)",
  180. pWnd, pWnd->rects.c));
  181. for (j = 0; j < pWnd->rects.c; j++)
  182. {
  183. //
  184. // See whether the point passed in is within this rectangle.
  185. // Note that at this point we are dealing with exclusive
  186. // co-ordinates.
  187. //
  188. if ((pt.x >= pWnd->rects.arcl[j].left) &&
  189. (pt.x < pWnd->rects.arcl[j].right) &&
  190. (pt.y >= pWnd->rects.arcl[j].top) &&
  191. (pt.y < pWnd->rects.arcl[j].bottom))
  192. {
  193. TRACE_OUT((
  194. "Pt {%d, %d}, in win %#x rect %u {%ld, %ld, %ld, %ld}",
  195. pt.x, pt.y, pWnd->hwnd, j,
  196. pWnd->rects.arcl[j].left, pWnd->rects.arcl[j].right,
  197. pWnd->rects.arcl[j].top, pWnd->rects.arcl[j].bottom ));
  198. //
  199. // Found it! Re-order the list, most recently used first
  200. //
  201. COM_BasedListRemove(&(pWnd->chain));
  202. COM_BasedListInsertAfter(&g_hetWindowList, &(pWnd->chain));
  203. //
  204. // Stop looking
  205. //
  206. rc = TRUE;
  207. DC_QUIT;
  208. }
  209. TRACE_OUT(( "Pt not in win %#x rect %u {%ld, %ld, %ld, %ld}",
  210. pWnd->hwnd, j,
  211. pWnd->rects.arcl[j].left, pWnd->rects.arcl[j].right,
  212. pWnd->rects.arcl[j].top, pWnd->rects.arcl[j].bottom ));
  213. } // for all rectangles
  214. //
  215. // Move on to next window
  216. //
  217. pWnd = COM_BasedListNext(&g_hetWindowList, pWnd, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  218. }
  219. DC_EXIT_POINT:
  220. DebugExitBOOL(HET_DDOutputIsHosted, rc);
  221. return(rc);
  222. }
  223. //
  224. // HET_DDOutputRectIsHosted - see host.h
  225. //
  226. BOOL HET_DDOutputRectIsHosted(LPRECT pRect)
  227. {
  228. BOOL rc = FALSE;
  229. UINT j;
  230. LPHET_WINDOW_STRUCT pWnd;
  231. RECT rectIntersect;
  232. DebugEntry(HET_DDOutputRectIsHosted);
  233. //
  234. // Now check to see if the desktop is shared - if it is then simply
  235. // return TRUE.
  236. //
  237. if (g_hetDDDesktopIsShared)
  238. {
  239. rc = TRUE;
  240. DC_QUIT;
  241. }
  242. //
  243. // Search through the window list
  244. //
  245. pWnd = COM_BasedListFirst(&g_hetWindowList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  246. while (pWnd != NULL)
  247. {
  248. //
  249. // Search each enumerated rectangle
  250. //
  251. TRACE_OUT(( "Window %#x has %u rectangle(s)",
  252. pWnd, pWnd->rects.c));
  253. for (j = 0; j < pWnd->rects.c; j++)
  254. {
  255. //
  256. // See whether the rect passed in intersects this rectangle.
  257. // Note that at this point we are dealing with exclusive
  258. // co-ordinates.
  259. //
  260. rectIntersect.left = max( pRect->left,
  261. pWnd->rects.arcl[j].left );
  262. rectIntersect.top = max( pRect->top,
  263. pWnd->rects.arcl[j].top );
  264. rectIntersect.right = min( pRect->right,
  265. pWnd->rects.arcl[j].right );
  266. rectIntersect.bottom = min( pRect->bottom,
  267. pWnd->rects.arcl[j].bottom );
  268. //
  269. // If the intersection rectangle is well-ordered and non-NULL
  270. // then we have an intersection.
  271. //
  272. // The rects that we are dealing with are exclusive.
  273. //
  274. if ((rectIntersect.left < rectIntersect.right) &&
  275. (rectIntersect.top < rectIntersect.bottom))
  276. {
  277. TRACE_OUT((
  278. "Rect {%d, %d, %d, %d} intersects win %#x rect %u {%ld, %ld, %ld, %ld}",
  279. pRect->left, pRect->top, pRect->right, pRect->bottom,
  280. pWnd, j,
  281. pWnd->rects.arcl[j].left, pWnd->rects.arcl[j].right,
  282. pWnd->rects.arcl[j].top, pWnd->rects.arcl[j].bottom ));
  283. //
  284. // Found it! Re-order the list, most recently used first
  285. //
  286. COM_BasedListRemove(&(pWnd->chain));
  287. COM_BasedListInsertAfter(&g_hetWindowList, &(pWnd->chain));
  288. //
  289. // Stop looking
  290. //
  291. rc = TRUE;
  292. DC_QUIT;
  293. }
  294. TRACE_OUT(( "Rect not in win %#x rect %u {%ld, %ld, %ld, %ld}",
  295. pWnd, j,
  296. pWnd->rects.arcl[j].left, pWnd->rects.arcl[j].right,
  297. pWnd->rects.arcl[j].top, pWnd->rects.arcl[j].bottom ));
  298. } // for all rectangles
  299. //
  300. // Move on to next window
  301. //
  302. pWnd = COM_BasedListNext(&g_hetWindowList, pWnd, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  303. }
  304. DC_EXIT_POINT:
  305. DebugExitBOOL(HET_DDOutputRectIsHosted, rc);
  306. return(rc);
  307. }
  308. //
  309. //
  310. // Name: HETDDVisRgnCallback
  311. //
  312. // Description: WNDOBJ Callback
  313. //
  314. // Params: pWo - pointer to the WNDOBJ which has changed
  315. // fl - flags (se NT DDK documentation)
  316. //
  317. // Returns: none
  318. //
  319. // Operation:
  320. //
  321. //
  322. VOID CALLBACK HETDDVisRgnCallback(PWNDOBJ pWo, FLONG fl)
  323. {
  324. ULONG count;
  325. int size;
  326. LPHET_WINDOW_STRUCT pWnd;
  327. RECTL rectl;
  328. UINT i;
  329. DebugEntry(HETDDVisRgnCallback);
  330. //
  331. // Some calls pass a NULL pWo - exit now in this case
  332. //
  333. if (pWo == NULL)
  334. {
  335. DC_QUIT;
  336. }
  337. //
  338. // Find the window structure for this window
  339. //
  340. pWnd = pWo->pvConsumer;
  341. if (pWnd == NULL)
  342. {
  343. ERROR_OUT(( "Wndobj %x (fl %x) has no window structure", pWo, fl));
  344. DC_QUIT;
  345. }
  346. //
  347. // Check for window deletion
  348. //
  349. if (fl & WOC_DELETE)
  350. {
  351. TRACE_OUT(( "Wndobj %x (structure %x) deleted", pWo, pWo->pvConsumer));
  352. // ASSERT the window is valid
  353. ASSERT(pWnd->hwnd != NULL);
  354. //
  355. // Move the window from the active to the free list
  356. //
  357. COM_BasedListRemove(&(pWnd->chain));
  358. COM_BasedListInsertAfter(&g_hetFreeWndList, &(pWnd->chain));
  359. #ifdef DEBUG
  360. // Check if this has reentrancy problems
  361. pWnd->hwnd = NULL;
  362. #endif
  363. //
  364. // Do any processing if this is the last window to be unshared.
  365. //
  366. // If we are not keeping track of any windows, the first pointer in
  367. // the list will point to itself, ie list head->next == 0
  368. //
  369. if (g_hetWindowList.next == 0)
  370. {
  371. HETDDViewing(NULL, FALSE);
  372. }
  373. //
  374. // Exit now
  375. //
  376. DC_QUIT;
  377. }
  378. //
  379. // If we get here, this callback must be for a new visible region on a
  380. // tracked window.
  381. //
  382. //
  383. // Start the enumeration. This function is supposed to count the
  384. // rectangles, but it always returns 0.
  385. //
  386. WNDOBJ_cEnumStart(pWo, CT_RECTANGLES, CD_ANY, 200);
  387. //
  388. // BOGUS BUGBUG LAURABU (perf opt for NT):
  389. //
  390. // NT will enum up to HET_WINDOW_RECTS at a time. Note that the enum
  391. // function returns FALSE if, after obtaining the current batch, none
  392. // are left to grab the next time.
  393. //
  394. // If the visrgn is composed of more than that, we will wipe out the
  395. // previous set of rects, then ensure that the bounding box of the
  396. // preceding rects is the last rect in the list.
  397. //
  398. // This is bad in several cases. For example if there are n visrgn piece
  399. // rects, and n == c*HET_WINDOW_RECTS + 1, we will end up with 2 entries:
  400. // * The last piece rect
  401. // * The bounding box of the previous n-1 piece rects
  402. // A lot of output may be accumulated in deadspace as a result.
  403. //
  404. // A better algorithm may be to fill the first HET_WINDOW_RECTS-1 slots,
  405. // then union the rest into the last rectangle. That way we make use of
  406. // all the slots. But this could be awkward, since we need a scratch
  407. // ENUM_RECT struct rather than using the HET_WINDOW_STRUCT directly.
  408. //
  409. //
  410. // First time through, enumerate HET_WINDOW_RECTS rectangles.
  411. // Subsequent times, enumerate HET_WINDOW_RECTS-1 (see bottom of loop).
  412. // This guarantees that there will be room to store a combined
  413. // rectangle when we finally finish enumerating them.
  414. //
  415. pWnd->rects.c = HET_WINDOW_RECTS;
  416. rectl.left = LONG_MAX;
  417. rectl.top = LONG_MAX;
  418. rectl.right = 0;
  419. rectl.bottom = 0;
  420. //
  421. // Enumerate the rectangles
  422. // NOTE that WNDOBJ_bEnum returns FALSE when there is nothing left
  423. // to enumerate AFTER grabbing this set.
  424. //
  425. while (WNDOBJ_bEnum(pWo, sizeof(pWnd->rects), (ULONG *)&pWnd->rects))
  426. {
  427. #ifdef _DEBUG
  428. {
  429. char trcStr[200];
  430. UINT j;
  431. sprintf(trcStr, "WNDOBJ %p %d: ", pWo, pWnd->rects.c);
  432. for (j = 0; j < pWnd->rects.c; j++)
  433. {
  434. sprintf(trcStr, "%s {%ld, %ld, %ld, %ld} ", trcStr,
  435. pWnd->rects.arcl[j].left, pWnd->rects.arcl[j].top,
  436. pWnd->rects.arcl[j].right, pWnd->rects.arcl[j].bottom);
  437. if ((j & 3) == 3) // output every 4th rect
  438. {
  439. TRACE_OUT(( "%s", trcStr));
  440. strcpy(trcStr, " ");
  441. }
  442. }
  443. if ((j & 3) != 0) // if any rects left
  444. {
  445. TRACE_OUT(( "%s", trcStr));
  446. }
  447. }
  448. #endif
  449. //
  450. // Combine the preceding rectangles into one bounding rectangle
  451. //
  452. for (i = 0; i < pWnd->rects.c; i++)
  453. {
  454. if (pWnd->rects.arcl[i].left < rectl.left)
  455. {
  456. rectl.left = pWnd->rects.arcl[i].left;
  457. }
  458. if (pWnd->rects.arcl[i].top < rectl.top)
  459. {
  460. rectl.top = pWnd->rects.arcl[i].top;
  461. }
  462. if (pWnd->rects.arcl[i].right > rectl.right)
  463. {
  464. rectl.right = pWnd->rects.arcl[i].right;
  465. }
  466. if (pWnd->rects.arcl[i].bottom > rectl.bottom)
  467. {
  468. rectl.bottom = pWnd->rects.arcl[i].bottom;
  469. }
  470. }
  471. TRACE_OUT(( "Combined into {%ld, %ld, %ld, %ld}",
  472. rectl.left, rectl.top, rectl.right, rectl.bottom));
  473. //
  474. // Second & subsequent times, enumerate HET_WINDOW_RECTS-1
  475. //
  476. pWnd->rects.c = HET_WINDOW_RECTS - 1;
  477. }
  478. //
  479. // If any combining was done, save the combined rectangle now.
  480. //
  481. if (rectl.right != 0)
  482. {
  483. pWnd->rects.arcl[pWnd->rects.c] = rectl;
  484. pWnd->rects.c++;
  485. TRACE_OUT(( "Add combined rectangle to list"));
  486. }
  487. //
  488. // On the assumption that this WNDOBJ is the most likely to be the
  489. // target of the next output command, move it to the top of the list.
  490. //
  491. COM_BasedListRemove(&(pWnd->chain));
  492. COM_BasedListInsertAfter(&g_hetWindowList, &(pWnd->chain));
  493. //
  494. // Return to caller
  495. //
  496. DC_EXIT_POINT:
  497. DebugExitVOID(HETDDVisRgnCallback);
  498. }
  499. //
  500. //
  501. // Name: HETDDShareWindow
  502. //
  503. // Description: Share a window (DD processing)
  504. //
  505. // Params: pso - SURFOBJ
  506. // pReq - request received from DrvEscape
  507. //
  508. //
  509. BOOL HETDDShareWindow(SURFOBJ *pso, LPHET_SHARE_WINDOW pReq)
  510. {
  511. PWNDOBJ pWo;
  512. FLONG fl = WO_RGN_CLIENT | WO_RGN_UPDATE_ALL | WO_RGN_WINDOW;
  513. LPHET_WINDOW_STRUCT pWnd;
  514. BOOL rc = FALSE;
  515. DebugEntry(HETDDShareWindow);
  516. ASSERT(!g_hetDDDesktopIsShared);
  517. //
  518. // Try to track the window
  519. //
  520. pWo = EngCreateWnd(pso, (HWND)pReq->winID, HETDDVisRgnCallback, fl, 0);
  521. //
  522. // Failed to track window - exit now
  523. //
  524. if (pWo == 0)
  525. {
  526. ERROR_OUT(( "Failed to track window %#x", pReq->winID));
  527. DC_QUIT;
  528. }
  529. //
  530. // Window is already tracked. This happens when an invisible window is
  531. // shown in a process the USER shared, and we caught its create.
  532. //
  533. if (pWo == (PWNDOBJ)-1)
  534. {
  535. //
  536. // No more to do here
  537. //
  538. TRACE_OUT(( "Window %#x already tracked", pReq->winID));
  539. rc = TRUE;
  540. DC_QUIT;
  541. }
  542. //
  543. // Add window into our list.
  544. //
  545. //
  546. // Find free window structure
  547. //
  548. pWnd = COM_BasedListFirst(&g_hetFreeWndList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  549. //
  550. // If no free structures, grow the list
  551. //
  552. if (pWnd == NULL)
  553. {
  554. if (!HETDDAllocWndMem())
  555. {
  556. ERROR_OUT(( "Unable to allocate new window structures"));
  557. DC_QUIT;
  558. }
  559. pWnd = COM_BasedListFirst(&g_hetFreeWndList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  560. }
  561. //
  562. // Fill in the structure
  563. //
  564. TRACE_OUT(( "Fill in details for new window"));
  565. pWnd->hwnd = (HWND)pReq->winID;
  566. pWnd->wndobj = pWo;
  567. //
  568. // Set this to zero. There's a brief period between the time we put
  569. // this in our tracked list and the time we get called back to recalc
  570. // the visrgn (because the ring 3 code invalidates the window completely).
  571. // We might get graphical output and we don't want to parse garbage
  572. // from this window's record.
  573. //
  574. pWnd->rects.c = 0;
  575. //
  576. // Move the window structure from free to active list
  577. //
  578. COM_BasedListRemove(&(pWnd->chain));
  579. COM_BasedListInsertAfter(&g_hetWindowList, &(pWnd->chain));
  580. //
  581. // Save backwards pointer in the WNDOBJ
  582. // THIS MUST BE LAST since our callback can happen anytime afterwards.
  583. //
  584. // NOTE that the window's visrgn rects get into our list because the
  585. // ring3 code completely invalidates the window, causing the callback
  586. // to get called.
  587. //
  588. TRACE_OUT(( "Save pointer %#lx in Wndobj %#x", pWnd, pWo));
  589. WNDOBJ_vSetConsumer(pWo, pWnd);
  590. rc = TRUE;
  591. DC_EXIT_POINT:
  592. DebugExitBOOL(HETDDShareWindow, rc);
  593. return(rc);
  594. }
  595. //
  596. //
  597. // Name: HETDDUnshareWindow
  598. //
  599. // Description: Unshare a window (DD processing)
  600. //
  601. //
  602. //
  603. void HETDDUnshareWindow(LPHET_UNSHARE_WINDOW pReq)
  604. {
  605. LPHET_WINDOW_STRUCT pWnd, pNextWnd;
  606. DebugEntry(HETDDUnshareWindow);
  607. TRACE_OUT(( "Unshare %x", pReq->winID));
  608. //
  609. // Scan window list for this window and its descendants
  610. //
  611. pWnd = COM_BasedListFirst(&g_hetWindowList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  612. while (pWnd != NULL)
  613. {
  614. //
  615. // If this window is being unshared, free it
  616. //
  617. pNextWnd = COM_BasedListNext(&g_hetWindowList, pWnd, FIELD_OFFSET(HET_WINDOW_STRUCT, chain));
  618. if (pWnd->hwnd == (HWND)pReq->winID)
  619. {
  620. TRACE_OUT(( "Unsharing %x", pReq->winID));
  621. //
  622. // Stop tracking the window
  623. //
  624. HETDDDeleteAndFreeWnd(pWnd);
  625. }
  626. //
  627. // Go on to (previously saved) next window
  628. //
  629. pWnd = pNextWnd;
  630. }
  631. //
  632. // Return to caller
  633. //
  634. DebugExitVOID(HETDDUnshareWindow);
  635. }
  636. //
  637. //
  638. // Name: HETDDUnshareAll
  639. //
  640. // Description: Unshare all windows (DD processing) (what did you expect)
  641. //
  642. //
  643. void HETDDUnshareAll(void)
  644. {
  645. LPHET_WINDOW_STRUCT pWnd;
  646. DebugEntry(HETDDUnshareAll);
  647. //
  648. // Clear all window structures
  649. //
  650. while (pWnd = COM_BasedListFirst(&g_hetWindowList, FIELD_OFFSET(HET_WINDOW_STRUCT, chain)))
  651. {
  652. TRACE_OUT(( "Unshare Window structure %x", pWnd));
  653. //
  654. // Stop tracking the window
  655. //
  656. HETDDDeleteAndFreeWnd(pWnd);
  657. }
  658. //
  659. // Return to caller
  660. //
  661. DebugExitVOID(HETDDUnshareAll);
  662. }
  663. //
  664. //
  665. // Name: HETDDAllocWndMem
  666. //
  667. // Description: Allocate memory for a (new) window list
  668. //
  669. // Parameters: None
  670. //
  671. //
  672. BOOL HETDDAllocWndMem(void)
  673. {
  674. BOOL rc = FALSE;
  675. int i;
  676. LPHET_WINDOW_MEMORY pNew;
  677. DebugEntry(HETDDAllocWndMem);
  678. //
  679. // Allocate a new strucure
  680. //
  681. pNew = EngAllocMem(FL_ZERO_MEMORY, sizeof(HET_WINDOW_MEMORY), OSI_ALLOC_TAG);
  682. if (pNew == NULL)
  683. {
  684. ERROR_OUT(("HETDDAllocWndMem: unable to allocate memory"));
  685. DC_QUIT;
  686. }
  687. //
  688. // Add this memory block to the list of memory blocks
  689. //
  690. COM_BasedListInsertAfter(&g_hetMemoryList, &(pNew->chain));
  691. //
  692. // Add all new entries to free list
  693. //
  694. TRACE_OUT(("HETDDAllocWndMem: adding new entries to free list"));
  695. for (i = 0; i < HET_WINDOW_COUNT; i++)
  696. {
  697. COM_BasedListInsertAfter(&g_hetFreeWndList, &(pNew->wnd[i].chain));
  698. }
  699. rc = TRUE;
  700. DC_EXIT_POINT:
  701. DebugExitBOOL(HETDDAllocWndMem, rc);
  702. return(rc);
  703. }
  704. //
  705. //
  706. // Name: HETDDDeleteAndFreeWnd
  707. //
  708. // Description: Delete and window and free its window structure
  709. //
  710. // Parameters: pWnd - pointer to window structure to delete & free
  711. //
  712. // Returns: none
  713. //
  714. // Operation: Ths function stops tracking a window and frees its memory
  715. //
  716. //
  717. void HETDDDeleteAndFreeWnd(LPHET_WINDOW_STRUCT pWnd)
  718. {
  719. DebugEntry(HETDDDeleteAndFreeWnd);
  720. //
  721. // Stop tracking the window
  722. //
  723. EngDeleteWnd(pWnd->wndobj);
  724. //
  725. // NOTE LAURABU! EngDeleteWnd() will call the VisRgnCallback with
  726. // WO_DELETE, which will cause us to exectute a duplicate of exactly
  727. // the code below. So why do it twice (which is scary anyway), especially
  728. // the stop hosting code?
  729. //
  730. ASSERT(pWnd->hwnd == NULL);
  731. //
  732. // Return to caller
  733. //
  734. DebugExitVOID(HETDDDeleteAndFreeWnd);
  735. }
  736. //
  737. // HETDDViewers()
  738. //
  739. // Called when viewing of our shared apps starts/stops. Naturally, no longer
  740. // sharing anything stops viewing also.
  741. //
  742. void HETDDViewing
  743. (
  744. SURFOBJ * pso,
  745. BOOL fViewers
  746. )
  747. {
  748. DebugEntry(HETDDViewers);
  749. if (g_oeViewers != fViewers)
  750. {
  751. g_oeViewers = fViewers;
  752. CM_DDViewing(pso, fViewers);
  753. if (g_oeViewers)
  754. {
  755. //
  756. // Force palette grab.
  757. //
  758. g_asSharedMemory->pmPaletteChanged = TRUE;
  759. }
  760. }
  761. DebugExitVOID(HETDDViewing);
  762. }