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.

237 lines
6.4 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. DelayShowGroup.cpp
  5. Abstract:
  6. When the ShowGroup command is sent to Program Manager (DDE),
  7. wait for the window to actually appear before returning.
  8. History:
  9. 10/05/2000 robkenny Created
  10. 02/13/2002 astritz Security Review
  11. --*/
  12. #include "precomp.h"
  13. #include <ParseDDE.h>
  14. IMPLEMENT_SHIM_BEGIN(DelayShowGroup)
  15. #include "ShimHookMacro.h"
  16. APIHOOK_ENUM_BEGIN
  17. APIHOOK_ENUM_ENTRY(DdeClientTransaction)
  18. APIHOOK_ENUM_END
  19. static DWORD dwMaxWaitTime = 5000; // 5 seconds
  20. // A list of DDE commands that we are interested in.
  21. const char * c_sDDECommands[] =
  22. {
  23. "ShowGroup",
  24. NULL,
  25. } ;
  26. // Return FALSE if this window contains the pathname in lParam
  27. BOOL
  28. CALLBACK WindowEnumCB(
  29. HWND hwnd, // handle to parent window
  30. LPARAM lParam // application-defined value
  31. )
  32. {
  33. BOOL bRet = TRUE;
  34. const char * szGroupName = (const char *)lParam;
  35. int cch = GetWindowTextLengthA(hwnd);
  36. if( cch > 0 )
  37. {
  38. // Include space for a null character.
  39. cch++;
  40. char *lpWindowTitle = (char *)malloc(cch*sizeof(char));
  41. if( lpWindowTitle )
  42. {
  43. int cchCopied = GetWindowTextA(hwnd, lpWindowTitle, cch);
  44. if( cchCopied > 0 && cchCopied < cch )
  45. {
  46. //DPF(eDbgLevelSpew, "Window(%s)\n", lpWindowTitle);
  47. if (_stricmp(lpWindowTitle, szGroupName) == 0)
  48. {
  49. bRet = FALSE;
  50. }
  51. }
  52. free(lpWindowTitle);
  53. }
  54. }
  55. return bRet; // keep enumming
  56. }
  57. // Determine if a window with the szGroupName exists on the sytem
  58. BOOL
  59. CheckForWindow(const char * szGroupName)
  60. {
  61. DWORD success = EnumDesktopWindows(NULL, WindowEnumCB, (LPARAM)szGroupName);
  62. BOOL retval = success == 0 && GetLastError() == 0;
  63. return retval;
  64. }
  65. // Check to see if this is a ShowGroup command,
  66. // if it is do not return until the window actually exists
  67. void
  68. DelayIfShowGroup(LPBYTE pData)
  69. {
  70. if (pData)
  71. {
  72. // Now we need to parse the string, looking for a DeleteGroup command
  73. // Format "ShowGroup(GroupName,ShowCommand[,CommonGroupFlag])"
  74. // CommonGroupFlag is optional
  75. char * pszBuf = StringDuplicateA((const char *)pData);
  76. if (!pszBuf)
  77. return;
  78. UINT * lpwCmd = GetDDECommands(pszBuf, c_sDDECommands, FALSE);
  79. if (lpwCmd)
  80. {
  81. // Store off lpwCmd so we can free the correct addr later
  82. UINT *lpwCmdTemp = lpwCmd;
  83. // Execute a command.
  84. while (*lpwCmd != (UINT)-1)
  85. {
  86. UINT wCmd = *lpwCmd++;
  87. // Subtract 1 to account for the terminating NULL
  88. if (wCmd < ARRAYSIZE(c_sDDECommands)-1)
  89. {
  90. // We found a command--it must be DeleteGroup--since there is only 1
  91. BOOL iCommonGroup = -1;
  92. // From DDE_ShowGroup
  93. if (*lpwCmd < 2 || *lpwCmd > 3)
  94. {
  95. goto Leave;
  96. }
  97. if (*lpwCmd == 3) {
  98. //
  99. // Need to check for common group flag
  100. //
  101. if (pszBuf[*(lpwCmd + 3)] == '1') {
  102. iCommonGroup = 1;
  103. } else {
  104. iCommonGroup = 0;
  105. }
  106. }
  107. const char * groupName = pszBuf + lpwCmd[1];
  108. // Build a path to the directory
  109. CString csGroupName;
  110. LPSTR pszGroupName;
  111. GetGroupPath(groupName, csGroupName, 0, iCommonGroup);
  112. pszGroupName = csGroupName.GetAnsi();
  113. // We need to wait until we have a window whose title matches this group
  114. DWORD dwStartTime = GetTickCount();
  115. DWORD dwNowTime = dwStartTime;
  116. BOOL bWindowExists = FALSE;
  117. while (dwNowTime - dwStartTime < dwMaxWaitTime)
  118. {
  119. bWindowExists = CheckForWindow(pszGroupName);
  120. if (bWindowExists)
  121. break;
  122. Sleep(100); // wait a bit more
  123. dwNowTime = GetTickCount();
  124. }
  125. LOGN(
  126. eDbgLevelError,
  127. "DelayIfShowGroup: %8s(%s).",
  128. bWindowExists ? "Show" : "Timeout",
  129. pszGroupName);
  130. }
  131. // Next command.
  132. lpwCmd += *lpwCmd + 1;
  133. }
  134. Leave:
  135. // Tidyup...
  136. GlobalFree(lpwCmdTemp);
  137. }
  138. free(pszBuf);
  139. }
  140. }
  141. HDDEDATA
  142. APIHOOK(DdeClientTransaction)(
  143. LPBYTE pData, // pointer to data to pass to server
  144. DWORD cbData, // length of data
  145. HCONV hConv, // handle to conversation
  146. HSZ hszItem, // handle to item name string
  147. UINT wFmt, // clipboard data format
  148. UINT wType, // transaction type
  149. DWORD dwTimeout, // time-out duration
  150. LPDWORD pdwResult // pointer to transaction result
  151. )
  152. {
  153. #if 0
  154. dwTimeout = 0x0fffffff; // a long time, enables me to debug explorer
  155. #endif
  156. if (pData && cbData != -1)
  157. {
  158. DPFN(eDbgLevelInfo, "DdeClientTransaction(%s) called.", pData);
  159. }
  160. // Pass data through untouched.
  161. HDDEDATA retval = ORIGINAL_API(DdeClientTransaction)(
  162. pData, // pointer to data to pass to server
  163. cbData, // length of data
  164. hConv, // handle to conversation
  165. hszItem, // handle to item name string
  166. wFmt, // clipboard data format
  167. wType, // transaction type
  168. dwTimeout, // time-out duration
  169. pdwResult // pointer to transaction result
  170. );
  171. if ( retval != 0 && pData && cbData != -1)
  172. DelayIfShowGroup(pData);
  173. return retval;
  174. }
  175. /*++
  176. Register hooked functions
  177. --*/
  178. HOOK_BEGIN
  179. APIHOOK_ENTRY(USER32.DLL, DdeClientTransaction)
  180. HOOK_END
  181. IMPLEMENT_SHIM_END