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.

178 lines
5.6 KiB

  1. /***************************************************************************\
  2. *
  3. * DLGEND.C -
  4. *
  5. * Copyright (c) 1985 - 1999, Microsoft Corporation
  6. *
  7. * Dialog Destruction Routines
  8. *
  9. * ??-???-???? mikeke Ported from Win 3.0 sources
  10. * 12-Feb-1991 mikeke Added Revalidation code
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /***************************************************************************\
  15. * EndDialog
  16. *
  17. * History:
  18. * 11-Dec-1990 mikeke ported from win30
  19. \***************************************************************************/
  20. FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, EndDialog, HWND, hwnd, INT_PTR, result)
  21. BOOL EndDialog(
  22. HWND hwnd,
  23. INT_PTR result)
  24. {
  25. PWND pwnd;
  26. PWND pwndOwner;
  27. HWND hwndOwner;
  28. BOOL fWasActive = FALSE;
  29. #ifdef SYSMODALWINDOWS
  30. HWND hwndOldSysModal;
  31. #endif
  32. if ((pwnd = ValidateHwnd(hwnd)) == NULL) {
  33. return (0L);
  34. }
  35. CheckLock(pwnd);
  36. /*
  37. * Must do special validation here to make sure pwnd is a dialog window.
  38. */
  39. if (!ValidateDialogPwnd(pwnd))
  40. return 0;
  41. if (SAMEWOWHANDLE(hwnd, GetActiveWindow())) {
  42. fWasActive = TRUE;
  43. }
  44. /*
  45. * GetWindowCreator returns either a kernel address or NULL.
  46. */
  47. pwndOwner = GetWindowCreator(pwnd);
  48. if (pwndOwner != NULL) {
  49. /*
  50. * Hide the window.
  51. */
  52. pwndOwner = REBASEPTR(pwnd, pwndOwner);
  53. hwndOwner = HWq(pwndOwner);
  54. if (!PDLG(pwnd)->fDisabled) {
  55. NtUserEnableWindow(hwndOwner, TRUE);
  56. }
  57. } else {
  58. hwndOwner = NULL;
  59. }
  60. /*
  61. * Terminate Mode Loop.
  62. */
  63. PDLG(pwnd)->fEnd = TRUE;
  64. PDLG(pwnd)->result = result;
  65. if (fWasActive && IsChild(hwnd, GetFocus())) {
  66. /*
  67. * Set focus to the dialog box so that any control which has the focus
  68. * can do an kill focus processing. Most useful for combo boxes so that
  69. * they can popup their dropdowns before destroying/hiding the dialog
  70. * box window. Note that we only do this if the focus is currently at a
  71. * child of this dialog box. We also need to make sure we are the active
  72. * window because this may be happening while we are in a funny state.
  73. * ie. the activation is in the middle of changing but the focus hasn't
  74. * changed yet. This happens with TaskMan (or maybe with other apps that
  75. * change the focus/activation at funny times).
  76. */
  77. NtUserSetFocus(hwnd);
  78. }
  79. NtUserSetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  80. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
  81. SWP_NOSIZE | SWP_NOZORDER);
  82. #ifdef SYSMODALWINDOWS
  83. /*
  84. * If this guy was sysmodal, set the sysmodal flag to previous guy so we
  85. * won't have a hidden sysmodal window that will mess things
  86. * up royally...
  87. */
  88. if (pwnd == gspwndSysModal) {
  89. hwndOldSysModal = PDLG(pwnd)->hwndSysModalSave;
  90. if (hwndOldSysModal && !IsWindow(hwndOldSysModal))
  91. hwndOldSysModal = NULL;
  92. SetSysModalWindow(hwndOldSysModal);
  93. // If there was a previous system modal window, we want to
  94. // activate it instead of this window's owner.
  95. //
  96. if (hwndOldSysModal)
  97. hwndOwner = hwndOldSysModal;
  98. }
  99. #endif
  100. /*
  101. * Don't do any activation unless we were previously active.
  102. */
  103. if (fWasActive && hwndOwner) {
  104. NtUserSetActiveWindow(hwndOwner);
  105. } else {
  106. /*
  107. * If at this point we are still the active window it means that
  108. * we have fallen into the black hole of being the only visible
  109. * window in the system when we hid ourselves. This is a bug and
  110. * needs to be fixed better later on. For now, though, just
  111. * set the active and focus window to NULL.
  112. */
  113. if (SAMEWOWHANDLE(hwnd, GetActiveWindow())) {
  114. // The next two lines are *not* the equivalent of the two Unlock
  115. // statements that were in Daytona server-side dlgend.c. So, we
  116. // need to go over to server/kernel and do it right. This fixes
  117. // a problem in Visual Slick, which had the MDI window lose focus
  118. // when a message box was dismissed. FritzS
  119. // SetActiveWindow(NULL);
  120. // SetFocus(NULL);
  121. NtUserCallNoParam(SFI_ZAPACTIVEANDFOCUS);
  122. }
  123. }
  124. #ifdef SYSMODALWINDOWS
  125. /*
  126. * If this guy was sysmodal, set the sysmodal flag to previous guy so we
  127. * won't have a hidden sysmodal window that will mess things
  128. * up
  129. * See comments for Bug #134; SANKAR -- 08-25-89 --;
  130. */
  131. if (pwnd == gspwndSysModal) {
  132. /*
  133. * Check if the previous Sysmodal guy is still valid?
  134. */
  135. hwndOldSysModal = PDLG(pwnd)->hwndSysModalSave;
  136. if (hwndOldSysModal && !IsWindow(hwndOldSysModal))
  137. hwndOldSysModal = NULL;
  138. SetSysModalWindow(hwndOldSysModal);
  139. }
  140. #endif
  141. /*
  142. * Make sure the dialog loop will wake and destroy the window.
  143. * The dialog loop is waiting on posted events (WaitMessage). If
  144. * EndDialog is called due to a sent message from another thread the
  145. * dialog loop will keep waiting for posted events and not destroy
  146. * the window. This happens when the dialog is obscured.
  147. * This is a problem with winfile and its copy/move dialog.
  148. */
  149. PostMessage(hwnd, WM_NULL, 0, 0);
  150. return TRUE;
  151. }