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.

994 lines
22 KiB

  1. //
  2. // HET.C
  3. // Hosted Entity Tracker
  4. //
  5. // Copyright(c) Microsoft 1997-
  6. //
  7. #include <as16.h>
  8. //
  9. // OSI and HET apis are the equivalent of the NT HOOK functionality.
  10. // HET_DD apis are the equivalent of the NT display driver apis.
  11. //
  12. /////
  13. //
  14. // HOOK functionality
  15. //
  16. /////
  17. BOOL WINAPI OSIIsWindowScreenSaver16(HWND hwnd)
  18. {
  19. BOOL fScreenSaver;
  20. DebugEntry(OSIIsWindowScreenSaver16);
  21. //
  22. // If there is no screen saver active, this window can't be one.
  23. //
  24. fScreenSaver = FALSE;
  25. SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fScreenSaver, 0);
  26. if (fScreenSaver)
  27. {
  28. char szClassName[64];
  29. //
  30. // Is the class name WindowsScreenSaverClass? This is what all
  31. // screen savers using the Win95 toolkit use. BOGUS BUGBUG
  32. // EXCEPT FOR THE IE4 CHANNEL SCREEN SAVER.
  33. //
  34. if (!GetClassName(hwnd, szClassName, sizeof(szClassName)) ||
  35. lstrcmp(szClassName, HET_SCREEN_SAVER_CLASS))
  36. {
  37. fScreenSaver = FALSE;
  38. }
  39. }
  40. DebugExitBOOL(OSIIsWindowScreenSaver16, fScreenSaver);
  41. return(fScreenSaver);
  42. }
  43. //
  44. // OSIStartWindowTracking16()
  45. //
  46. // This installs our global call window proc hook then watches windows
  47. // being created, destroyed, shown, hidden and looks for relationships via
  48. // process or related process info to the currently shared windows.
  49. //
  50. BOOL WINAPI OSIStartWindowTracking16(void)
  51. {
  52. BOOL rc = FALSE;
  53. DebugEntry(OSIStartWindowTracking16);
  54. ASSERT(!g_hetTrackHook);
  55. //
  56. // Install window/task tracking hook
  57. //
  58. g_hetTrackHook = SetWindowsHookEx(WH_CALLWNDPROC, HETTrackProc, g_hInstAs16, NULL);
  59. if (!g_hetTrackHook)
  60. {
  61. ERROR_OUT(("Can't install WH_CALLWNDPROC hook"));
  62. DC_QUIT;
  63. }
  64. //
  65. // Install event hook
  66. //
  67. g_hetEventHook = SetWindowsHookEx(WH_CBT, HETEventProc, g_hInstAs16, NULL);
  68. if (!g_hetEventHook)
  69. {
  70. ERROR_OUT(("Can't install WH_CBT hook"));
  71. DC_QUIT;
  72. }
  73. rc = TRUE;
  74. DC_EXIT_POINT:
  75. DebugExitBOOL(OSIStartWindowTracking16, rc);
  76. return(rc);
  77. }
  78. //
  79. // OSIStopWindowTracking16()
  80. //
  81. void WINAPI OSIStopWindowTracking16(void)
  82. {
  83. DebugEntry(OSIStopWindowTracking16);
  84. //
  85. // Remove Graphic Output hooks
  86. //
  87. HETDDViewing(FALSE);
  88. //
  89. // Remove event hook
  90. //
  91. if (g_hetEventHook)
  92. {
  93. UnhookWindowsHookEx(g_hetEventHook);
  94. g_hetEventHook = NULL;
  95. }
  96. //
  97. // Remove window/task tracking hook
  98. //
  99. if (g_hetTrackHook)
  100. {
  101. UnhookWindowsHookEx(g_hetTrackHook);
  102. g_hetTrackHook = NULL;
  103. }
  104. DebugExitVOID(OSIStopWindowTracking16);
  105. }
  106. //
  107. // HETEventProc()
  108. // This is a global CBT hook that prevents the screensaver from kicking
  109. // in when sharing.
  110. //
  111. LRESULT CALLBACK HETEventProc
  112. (
  113. int nCode,
  114. WPARAM wParam,
  115. LPARAM lParam
  116. )
  117. {
  118. LRESULT lResult;
  119. DebugEntry(HETEventProc);
  120. if ((nCode == HCBT_SYSCOMMAND) && (wParam == SC_SCREENSAVE))
  121. {
  122. // Prevent the screen saver from starting. NONZERO means disallow.
  123. WARNING_OUT(("Preventing screensaver from starting, we're currently sharing"));
  124. lResult = TRUE;
  125. }
  126. else
  127. {
  128. lResult = CallNextHookEx(g_hetEventHook, nCode, wParam, lParam);
  129. }
  130. DebugExitDWORD(HETEventProc, lResult);
  131. return(lResult);
  132. }
  133. //
  134. // HETTrackProc()
  135. //
  136. // This is the global hook that watches for windows coming & going,
  137. // showing & hiding to see if new ones related to shared ones should also
  138. // be shared. This covers related processes as well as related windows.
  139. //
  140. LRESULT CALLBACK HETTrackProc
  141. (
  142. int nCode,
  143. WPARAM wParam,
  144. LPARAM lParam
  145. )
  146. {
  147. LPCWPSTRUCT lpCwp;
  148. LPWINDOWPOS lpPos;
  149. LRESULT lResult;
  150. DebugEntry(HETTrackProc);
  151. //
  152. // wParam is a BOOL, TRUE if this is interthread
  153. // lParam is a pointer to a CWPSTRUCT
  154. //
  155. lpCwp = (LPCWPSTRUCT)lParam;
  156. ASSERT(!IsBadReadPtr(lpCwp, sizeof(*lpCwp)));
  157. //
  158. // We better be tracking still
  159. //
  160. ASSERT(g_hetTrackHook);
  161. //
  162. // Skip calls that happen in CONF itself. This is our implementation
  163. // of the SKIP_OWNPROCESS WinEvent option in NT's hook dll
  164. //
  165. if (GetCurrentTask() != g_hCoreTask)
  166. {
  167. switch (lpCwp->message)
  168. {
  169. case WM_NCCREATE:
  170. HETHandleCreate(lpCwp->hwnd);
  171. break;
  172. case WM_NCDESTROY:
  173. HETHandleDestroy(lpCwp->hwnd);
  174. break;
  175. case WM_NCPAINT:
  176. //
  177. // This will catch being shown before WINDOWPOSCHANGED does.
  178. // We still keep that for a catch all.
  179. //
  180. if (IsWindowVisible(lpCwp->hwnd))
  181. {
  182. HETHandleShow(lpCwp->hwnd, FALSE);
  183. }
  184. break;
  185. case WM_WINDOWPOSCHANGED:
  186. lpPos = (LPWINDOWPOS)lpCwp->lParam;
  187. ASSERT(!IsBadReadPtr(lpPos, sizeof(WINDOWPOS)));
  188. if (!(lpPos->flags & SWP_NOMOVE))
  189. HETCheckParentChange(lpCwp->hwnd);
  190. if (lpPos->flags & SWP_SHOWWINDOW)
  191. HETHandleShow(lpCwp->hwnd, TRUE);
  192. else if (lpPos->flags & SWP_HIDEWINDOW)
  193. HETHandleHide(lpCwp->hwnd);
  194. break;
  195. }
  196. }
  197. lResult = CallNextHookEx(g_hetTrackHook, nCode, wParam, lParam);
  198. DebugExitDWORD(HETTrackProc, lResult);
  199. return(lResult);
  200. }
  201. //
  202. // HETHandleCreate()
  203. //
  204. void HETHandleCreate(HWND hwnd)
  205. {
  206. HET_TRACK_INFO hti;
  207. UINT hostType;
  208. DebugEntry(HETHandleCreate);
  209. //
  210. // Ignore child windows
  211. //
  212. if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  213. {
  214. if (GetParent(hwnd) != g_osiDesktopWindow)
  215. {
  216. TRACE_OUT(("Skipping child window %04x create", hwnd));
  217. DC_QUIT;
  218. }
  219. }
  220. hti.idThread = g_lpfnGetWindowThreadProcessId(hwnd, &hti.idProcess);
  221. //
  222. // Ignore special shell threads
  223. //
  224. if (HET_IsShellThread(hti.idThread))
  225. {
  226. TRACE_OUT(("Skipping shell thread window %04x create", hwnd));
  227. DC_QUIT;
  228. }
  229. //
  230. // We don't need to ignore menus. Only when first shared do we skip
  231. // menus. The cached one we never want to share. The others will
  232. // go away almost immediately. From now on, we treat them the same
  233. // as other windows.
  234. //
  235. //
  236. // Figure out what to do.
  237. //
  238. hti.hwndUs = hwnd;
  239. hti.cWndsApp = 0;
  240. hti.cWndsSharedThread = 0;
  241. hti.cWndsSharedProcess = 0;
  242. UpOneLevel:
  243. EnumWindows(HETShareEnum, (LPARAM)(LPHET_TRACK_INFO)&hti);
  244. if (hti.cWndsSharedThread)
  245. {
  246. TRACE_OUT(("New window %04x in shared thread %08lx",
  247. hwnd, hti.idThread));
  248. hostType = HET_HOSTED_PERMANENT | HET_HOSTED_BYTHREAD;
  249. }
  250. else if (hti.cWndsSharedProcess)
  251. {
  252. TRACE_OUT(("New window %04x in shared process %08lx",
  253. hwnd, hti.idProcess));
  254. hostType = HET_HOSTED_PERMANENT | HET_HOSTED_BYPROCESS;
  255. }
  256. else if (hti.cWndsApp)
  257. {
  258. //
  259. // There's another window in our app, but none are shared. So don't
  260. // share us either.
  261. //
  262. TRACE_OUT(("New window %04x in unshared process %08lx",
  263. hwnd, hti.idProcess));
  264. DC_QUIT;
  265. }
  266. else
  267. {
  268. DWORD idParentProcess;
  269. // Loop through our ancestor processes (no thread info at this point)
  270. HETGetParentProcessID(hti.idProcess, &idParentProcess);
  271. if (!idParentProcess)
  272. {
  273. TRACE_OUT(("Can't get parent of process %08lx", hti.idProcess));
  274. DC_QUIT;
  275. }
  276. //
  277. // We know if we got here that all our favorite fields are still
  278. // zero. So just loop! But NULL out idThread to avoid matching
  279. // anything while we look at our parent.
  280. //
  281. TRACE_OUT(("First window %04x in process %08lx, checking parent %08lx",
  282. hwnd, hti.idProcess, idParentProcess));
  283. hti.idThread = 0;
  284. hti.idProcess = idParentProcess;
  285. goto UpOneLevel;
  286. }
  287. //
  288. // OK, we are going to share this. No need to repaint, all our
  289. // notifications are synchronous.
  290. //
  291. OSIShareWindow16(hwnd, hostType, FALSE, TRUE);
  292. DC_EXIT_POINT:
  293. DebugExitVOID(HETHandleCreate);
  294. }
  295. //
  296. // HETHandleDestroy()
  297. // Handles the destruction of a window
  298. //
  299. void HETHandleDestroy(HWND hwnd)
  300. {
  301. DebugEntry(HETHandleDestroy);
  302. //
  303. // Blow away our cache. Our cache holds the last window
  304. // drawing happened for, whether it was shared or not,
  305. // to let us more quickly decide whether we care.
  306. //
  307. OSIUnshareWindow16(hwnd, TRUE);
  308. if (hwnd == g_oeLastWindow)
  309. {
  310. TRACE_OUT(("Tossing oe cached window %04x", g_oeLastWindow));
  311. g_oeLastWindow = NULL;
  312. }
  313. DebugExitVOID(HETHandleDestroy);
  314. }
  315. //
  316. // HETHandleShow()
  317. //
  318. void HETHandleShow
  319. (
  320. HWND hwnd,
  321. BOOL fForceRepaint
  322. )
  323. {
  324. UINT hostType;
  325. HET_TRACK_INFO hti;
  326. DebugEntry(HETHandleShow);
  327. hostType = HET_GetHosting(hwnd);
  328. //
  329. // If this window is a real child, clear the hosting property. Usually
  330. // one isn't there. But in the case of a top level window becoming
  331. // a child of another, we want to wipe out junk.
  332. //
  333. if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  334. {
  335. if (GetParent(hwnd) != g_osiDesktopWindow)
  336. {
  337. TRACE_OUT(("Skipping child window 0x%04x show", hwnd));
  338. if (hostType)
  339. {
  340. WARNING_OUT(("Unsharing shared child window 0x%04 from SHOW", hwnd));
  341. OSIUnshareWindow16(hwnd, TRUE);
  342. }
  343. DC_QUIT;
  344. }
  345. }
  346. //
  347. // Is this guy already shared? Nothing to do if so. Unlike NT,
  348. // we don't get async notifications.
  349. //
  350. if (hostType)
  351. {
  352. TRACE_OUT(("Window %04x already shared, ignoring show", hwnd));
  353. DC_QUIT;
  354. }
  355. //
  356. // Here's where we also enumerate the top level windows and find a
  357. // match. But we DO not track across processes in this case. Instead
  358. // we look at the owner if there is one.
  359. //
  360. // This solves the create-as-a-child then change to a top level
  361. // window problem, like combo dropdowns.
  362. //
  363. hti.idThread = g_lpfnGetWindowThreadProcessId(hwnd, &hti.idProcess);
  364. //
  365. // Ignore special shell threads
  366. //
  367. if (HET_IsShellThread(hti.idThread))
  368. {
  369. TRACE_OUT(("Skipping shell thread window 0x%04x show", hwnd));
  370. DC_QUIT;
  371. }
  372. hti.hwndUs = hwnd;
  373. hti.cWndsApp = 0;
  374. hti.cWndsSharedThread = 0;
  375. hti.cWndsSharedProcess = 0;
  376. EnumWindows(HETShareEnum, (LPARAM)(LPHET_TRACK_INFO)&hti);
  377. //
  378. // These kinds of windows are always only temp shared. They don't
  379. // start out as top level windows that we saw from the beginning or
  380. // watched created. These are SetParent() or menu kinds of dudes, so
  381. // for a lot of reasons we're plain safer sharing these babies only
  382. // temporarily
  383. //
  384. //
  385. // Anything else shared on this thread/process, the decision is easy.
  386. // Otherwise, we look at the ownership trail.
  387. //
  388. if (!hti.cWndsSharedThread && !hti.cWndsSharedProcess)
  389. {
  390. HWND hwndOwner;
  391. //
  392. // Does it have an owner that is shared?
  393. //
  394. hwndOwner = hwnd;
  395. while (hwndOwner = GetWindow(hwndOwner, GW_OWNER))
  396. {
  397. if (HET_GetHosting(hwndOwner))
  398. {
  399. TRACE_OUT(("Found shared owner %04x of window %04x", hwndOwner, hwnd));
  400. break;
  401. }
  402. }
  403. if (!hwndOwner)
  404. {
  405. DC_QUIT;
  406. }
  407. }
  408. //
  409. // We maybe getting this too late, like in the case of a menu coming up,
  410. // and it may have already painted/erased. So invalidate this baby.
  411. // That's what the fForceRepaint parameter is for. That is only true
  412. // when coming from WM_WINDOWPOSCHANGED after an explicit WM_SHOWWINDOW
  413. // call. Most of the time, we catch WM_NCPAINT though, for show.
  414. //
  415. TRACE_OUT(("Sharing temporary window %04x", hwnd));
  416. OSIShareWindow16(hwnd, HET_HOSTED_BYWINDOW | HET_HOSTED_TEMPORARY,
  417. fForceRepaint, TRUE);
  418. DC_EXIT_POINT:
  419. DebugExitVOID(HETHandleShow);
  420. }
  421. //
  422. // HETHandleHide()
  423. //
  424. void HETHandleHide(HWND hwnd)
  425. {
  426. UINT hostType;
  427. DebugEntry(HETHandleHide);
  428. hostType = HET_GetHosting(hwnd);
  429. if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  430. {
  431. if (GetParent(hwnd) != GetDesktopWindow())
  432. {
  433. TRACE_OUT(("Skipping child window %04x hide", hwnd));
  434. if (hostType)
  435. {
  436. WARNING_OUT(("Unsharing shared child window 0x%04 from HIDE", hwnd));
  437. OSIUnshareWindow16(hwnd, TRUE);
  438. }
  439. DC_QUIT;
  440. }
  441. }
  442. if (!hostType)
  443. {
  444. //
  445. // Unlike NT, we don't get hide notifications out of context, so
  446. // we don't need to recount the top level guys.
  447. //
  448. TRACE_OUT(("Window %04x not shared, ignoring hide", hwnd));
  449. }
  450. else if (hostType & HET_HOSTED_TEMPORARY)
  451. {
  452. TRACE_OUT(("Unsharing temporary window %04x", hwnd));
  453. OSIUnshareWindow16(hwnd, TRUE);
  454. }
  455. else
  456. {
  457. ASSERT(hostType & HET_HOSTED_PERMANENT);
  458. // Nothing to do
  459. TRACE_OUT(("Window %04x permanently shared, ignoring hide", hwnd));
  460. }
  461. DC_EXIT_POINT:
  462. DebugExitVOID(HETHandleHide);
  463. }
  464. //
  465. // HETCheckParentChange()
  466. //
  467. // On a windowposchange with MOVE, we make sure that no child window has the
  468. // hosting property. When a window's parent changes, it is always moved,
  469. // so that's the best way I have to check for it. Since we only look at
  470. // top level windows, converted-to-children windows will stay shared forever
  471. // and won't show up in the share menu.
  472. //
  473. // This is NOT perfect. If the child is not moving to a different position
  474. // relative to the two parents, we won't see anything. But for the case
  475. // where one is switching to/from top level, its very likely we will come
  476. // through here. More likely than checking for hide/show.
  477. //
  478. void HETCheckParentChange(HWND hwnd)
  479. {
  480. DebugEntry(HETCheckParentChange);
  481. if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  482. {
  483. if (GetParent(hwnd) != GetDesktopWindow())
  484. {
  485. UINT hostType;
  486. hostType = HET_GetHosting(hwnd);
  487. if (hostType)
  488. {
  489. WARNING_OUT(("Unsharing shared child window 0x%04x from MOVE", hwnd));
  490. OSIUnshareWindow16(hwnd, TRUE);
  491. }
  492. }
  493. }
  494. DebugExitVOID(HETCheckParentChange);
  495. }
  496. //
  497. // HETShareEnum()
  498. //
  499. // This is the EnumWindows() callback. We stop when we find the first
  500. // matching shared window (thread or process). We keep a running tally
  501. // of the count of all top level windows in our process (not shared by
  502. // thread or process) at the same time. This lets us do tracking.
  503. //
  504. BOOL CALLBACK HETShareEnum(HWND hwnd, LPARAM lParam)
  505. {
  506. LPHET_TRACK_INFO lphti = (LPHET_TRACK_INFO)lParam;
  507. DWORD idProcess;
  508. DWORD idThread;
  509. UINT hostType;
  510. BOOL rc = TRUE;
  511. DebugEntry(HETShareEnum);
  512. // Skip ourself.
  513. if (hwnd == lphti->hwndUs)
  514. {
  515. DC_QUIT;
  516. }
  517. // Skip if window is gone.
  518. idThread = g_lpfnGetWindowThreadProcessId(hwnd, &idProcess);
  519. if (!idThread)
  520. {
  521. DC_QUIT;
  522. }
  523. //
  524. // Do the processes match? If not, easy amscray
  525. //
  526. if (idProcess != lphti->idProcess)
  527. {
  528. DC_QUIT;
  529. }
  530. lphti->cWndsApp++;
  531. hostType = HET_GetHosting(hwnd);
  532. if (!hostType)
  533. {
  534. DC_QUIT;
  535. }
  536. //
  537. // Now, if this window is shared by thread or process, do the right
  538. // thing.
  539. //
  540. if (hostType & HET_HOSTED_BYPROCESS)
  541. {
  542. // We have a match. We can return immediately.
  543. lphti->cWndsSharedProcess++;
  544. rc = FALSE;
  545. }
  546. else if (hostType & HET_HOSTED_BYTHREAD)
  547. {
  548. //
  549. // For WOW apps, we don't want this one, if in a separate thread, to
  550. // count. No matter what.
  551. //
  552. if (idThread == lphti->idThread)
  553. {
  554. lphti->cWndsSharedThread++;
  555. rc = FALSE;
  556. }
  557. }
  558. DC_EXIT_POINT:
  559. DebugExitBOOL(HETShareEnum, rc);
  560. return(rc);
  561. }
  562. //
  563. // HET_IsShellThread()
  564. // Returns TRUE if thread is one of shell's special threads
  565. //
  566. BOOL HET_IsShellThread(DWORD threadID)
  567. {
  568. BOOL rc;
  569. DebugEntry(HET_IsShellThread);
  570. if ((threadID == g_lpfnGetWindowThreadProcessId(HET_GetShellDesktop(), NULL)) ||
  571. (threadID == g_lpfnGetWindowThreadProcessId(HET_GetShellTray(), NULL)))
  572. {
  573. rc = TRUE;
  574. }
  575. else
  576. {
  577. rc = FALSE;
  578. }
  579. DebugExitBOOL(HET_IsShellThread, rc);
  580. return(rc);
  581. }
  582. //
  583. // OSIShareWindow16()
  584. // This shares a window. This is called when
  585. // * An app is unshared
  586. // * A window is destroyed
  587. // * A temporarily shared window is hidden
  588. //
  589. // This returns TRUE if it shared a window
  590. //
  591. BOOL WINAPI OSIShareWindow16
  592. (
  593. HWND hwnd,
  594. UINT hostType,
  595. BOOL fRepaint,
  596. BOOL fUpdateCount
  597. )
  598. {
  599. BOOL rc = FALSE;
  600. DebugEntry(OSIShareWindow16);
  601. //
  602. // Set the property
  603. //
  604. if (!HET_SetHosting(hwnd, hostType))
  605. {
  606. ERROR_OUT(("Couldn't set shared property on window %04x", hwnd));
  607. DC_QUIT;
  608. }
  609. //
  610. // Toss out our cache--it could have been a child of this one.
  611. //
  612. g_oeLastWindow = NULL;
  613. TRACE_OUT(("Shared window %04x of type %04x", hwnd, hostType));
  614. //
  615. // Repaint it
  616. //
  617. if (fRepaint)
  618. {
  619. USR_RepaintWindow(hwnd);
  620. }
  621. if (fUpdateCount)
  622. {
  623. PostMessageNoFail(g_asMainWindow, DCS_NEWTOPLEVEL_MSG, TRUE, 0);
  624. }
  625. rc = TRUE;
  626. DC_EXIT_POINT:
  627. DebugExitBOOL(OSIShareWindow16, rc);
  628. return(rc);
  629. }
  630. //
  631. // OSIUnshareWindow16()
  632. // This unshares a window. This is called when
  633. // * An app is unshared
  634. // * A window is destroyed
  635. // * A temporarily shared window is hidden
  636. //
  637. // This returns TRUE if it unshared a shared window.
  638. //
  639. BOOL WINAPI OSIUnshareWindow16
  640. (
  641. HWND hwnd,
  642. BOOL fUpdateCount
  643. )
  644. {
  645. BOOL rc = FALSE;
  646. UINT hostType;
  647. DebugEntry(OSIUnshareWindow16);
  648. //
  649. // This gets the old property and clears it in one step.
  650. //
  651. hostType = HET_ClearHosting(hwnd);
  652. if (!hostType)
  653. {
  654. //
  655. // Unlike NT, all the destroy notifications we get are synchronous.
  656. // So we don't need to recalculate the total.
  657. //
  658. DC_QUIT;
  659. }
  660. TRACE_OUT(("Unsharing window %04x of type %04x", hwnd, hostType));
  661. //
  662. // Toss our cache--the sharing status of some window has changed.
  663. //
  664. g_oeLastWindow = NULL;
  665. //
  666. // Update the top level count
  667. //
  668. if (fUpdateCount)
  669. {
  670. PostMessageNoFail(g_asMainWindow, DCS_NEWTOPLEVEL_MSG, FALSE, 0);
  671. }
  672. rc = TRUE;
  673. DC_EXIT_POINT:
  674. DebugExitBOOL(OSI_UnshareWindow, rc);
  675. return(rc);
  676. }
  677. //
  678. // HET_WindowIsHosted()
  679. // Returns TRUE if a window is shared. This is used by the IM code in its
  680. // high level hooks.
  681. //
  682. BOOL HET_WindowIsHosted(HWND hwnd)
  683. {
  684. BOOL rc = FALSE;
  685. HWND hwndParent;
  686. DebugEntry(HETHookWindowIsHosted);
  687. if (!hwnd)
  688. DC_QUIT;
  689. //
  690. // Walk up to the top level window this one is inside of
  691. //
  692. while (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD)
  693. {
  694. hwndParent = GetParent(hwnd);
  695. if (hwndParent == GetDesktopWindow())
  696. break;
  697. hwnd = hwndParent;
  698. }
  699. rc = HET_GetHosting(hwnd);
  700. DC_EXIT_POINT:
  701. DebugExitBOOL(HET_WindowIsHosted, rc);
  702. return(rc);
  703. }
  704. //
  705. // HETGetParentProcessID()
  706. // Get parent process if this one
  707. //
  708. void HETGetParentProcessID
  709. (
  710. DWORD processID,
  711. LPDWORD pParentProcessID
  712. )
  713. {
  714. //
  715. // Get the ID of the parent process
  716. //
  717. ASSERT(processID);
  718. *pParentProcessID = GetProcessDword(processID, GPD_PARENT);
  719. }
  720. /////
  721. //
  722. // DISPLAY DRIVER functionality
  723. //
  724. /////
  725. //
  726. // HET_DDInit()
  727. //
  728. BOOL HET_DDInit(void)
  729. {
  730. return(TRUE);
  731. }
  732. //
  733. // HET_DDTerm()
  734. //
  735. void HET_DDTerm(void)
  736. {
  737. DebugEntry(HET_DDTerm);
  738. //
  739. // Make sure we stop hosting
  740. //
  741. g_hetDDDesktopIsShared = FALSE;
  742. OSIStopWindowTracking16();
  743. DebugExitVOID(HET_DDTerm);
  744. }
  745. //
  746. // HET_DDProcessRequest()
  747. // Handles HET escapes
  748. //
  749. BOOL HET_DDProcessRequest
  750. (
  751. UINT fnEscape,
  752. LPOSI_ESCAPE_HEADER pResult,
  753. DWORD cbResult
  754. )
  755. {
  756. BOOL rc = TRUE;
  757. DebugEntry(HET_DDProcessRequest);
  758. switch (fnEscape)
  759. {
  760. //
  761. // NOTE:
  762. // Unlike NT, we have no need of keeping a duplicated list of
  763. // shared windows. We can make window calls directly, and can use
  764. // GetProp to find out.
  765. //
  766. case HET_ESC_UNSHARE_ALL:
  767. {
  768. // Nothing to do
  769. }
  770. break;
  771. case HET_ESC_SHARE_DESKTOP:
  772. {
  773. ASSERT(!g_hetDDDesktopIsShared);
  774. g_hetDDDesktopIsShared = TRUE;
  775. }
  776. break;
  777. case HET_ESC_UNSHARE_DESKTOP:
  778. {
  779. ASSERT(g_hetDDDesktopIsShared);
  780. g_hetDDDesktopIsShared = FALSE;
  781. HETDDViewing(FALSE);
  782. }
  783. break;
  784. case HET_ESC_VIEWER:
  785. {
  786. HETDDViewing(((LPHET_VIEWER)pResult)->viewersPresent != 0);
  787. break;
  788. }
  789. default:
  790. {
  791. ERROR_OUT(("Unrecognized HET escape"));
  792. rc = FALSE;
  793. }
  794. break;
  795. }
  796. DebugExitBOOL(HET_DDProcessRequest, rc);
  797. return(rc);
  798. }
  799. //
  800. // HETDDViewing()
  801. //
  802. // Called when viewing of our shared apps starts/stops. Naturally, no longer
  803. // sharing anything stops viewing also.
  804. //
  805. void HETDDViewing(BOOL fViewers)
  806. {
  807. DebugEntry(HETDDViewing);
  808. if (g_oeViewers != fViewers)
  809. {
  810. g_oeViewers = fViewers;
  811. OE_DDViewing(fViewers);
  812. }
  813. DebugExitVOID(HETDDViewing);
  814. }