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.

330 lines
9.4 KiB

  1. /*************************************************************************
  2. *
  3. * winstmsg.c
  4. *
  5. * Handle the directing of messages to a specific Session
  6. * for the event notification service. (net send NAME msg...)
  7. *
  8. *
  9. * This also supports directing print spooler messages sent to
  10. * the machine name to the Session of the user who spooled the
  11. * request.
  12. *
  13. *************************************************************************/
  14. //
  15. // Includes
  16. //
  17. #include "msrv.h"
  18. #include <msgdbg.h> // STATIC and MSG_LOG
  19. #include <string.h> // memcpy
  20. #include <wchar.h>
  21. #include <winuser.h> // MessageBox
  22. #include "msgdata.h" // GlobalMsgDisplayEvent
  23. #define CONSOLE_LOGONID 0
  24. BOOL g_IsTerminalServer;
  25. PWINSTATION_QUERY_INFORMATION gpfnWinStationQueryInformation;
  26. PWINSTATION_SEND_MESSAGE gpfnWinStationSendMessage;
  27. PWINSTATION_FREE_MEMORY gpfnWinStationFreeMemory;
  28. PWINSTATION_ENUMERATE gpfnWinStationEnumerate;
  29. //
  30. // Functions defined here
  31. //
  32. BOOL
  33. InitializeMultiUserFunctionsPtrs (void);
  34. void
  35. SendMessageBoxToSession(LPWSTR pMessage,
  36. LPWSTR pTitle,
  37. ULONG SessionId
  38. );
  39. /*****************************************************************************
  40. *
  41. * MultiUserInitMessage
  42. *
  43. * Init the _HYDRA_ message support.
  44. *
  45. *
  46. * ENTRY:
  47. * Param1 (input/output)
  48. * Comments
  49. *
  50. * EXIT:
  51. * STATUS_SUCCESS - no error
  52. *
  53. ****************************************************************************/
  54. NET_API_STATUS
  55. MultiUserInitMessage( VOID )
  56. {
  57. HANDLE hInst;
  58. NET_API_STATUS Status = NERR_Success;
  59. MSG_LOG(TRACE,"Entering MultiUserInitMessage\n",0)
  60. g_IsTerminalServer = !!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer));
  61. if (g_IsTerminalServer)
  62. {
  63. if ( !InitializeMultiUserFunctionsPtrs() )
  64. {
  65. Status = NERR_InternalError;
  66. }
  67. }
  68. return Status;
  69. }
  70. /****************************************************************************\
  71. *
  72. * FUNCTION: InitializeMultiUserFunctions
  73. *
  74. * PURPOSE: Load Winsta.dll and store function pointers
  75. *
  76. * HISTORY:
  77. *
  78. *
  79. \****************************************************************************/
  80. BOOL
  81. InitializeMultiUserFunctionsPtrs (void)
  82. {
  83. HANDLE dllHandle;
  84. //
  85. // Load winsta.dll
  86. //
  87. dllHandle = LoadLibraryW(L"winsta.dll");
  88. if (dllHandle == NULL) {
  89. return FALSE;
  90. }
  91. //
  92. // get the pointers to the required functions
  93. //
  94. //WinStationQueryInformationW
  95. gpfnWinStationQueryInformation = (PWINSTATION_QUERY_INFORMATION) GetProcAddress(
  96. dllHandle,
  97. "WinStationQueryInformationW"
  98. );
  99. if (gpfnWinStationQueryInformation == NULL) {
  100. DbgPrint("InitializeMultiUserFunctions: Failed to get WinStationQueryInformationW Proc %d\n",GetLastError());
  101. FreeLibrary(dllHandle);
  102. return FALSE;
  103. }
  104. //WinStationEnumerateW
  105. gpfnWinStationEnumerate = (PWINSTATION_ENUMERATE) GetProcAddress(
  106. dllHandle,
  107. "WinStationEnumerateW"
  108. );
  109. if (gpfnWinStationEnumerate == NULL) {
  110. DbgPrint("InitializeMultiUserFunctions: Failed to get WinStationEnumerateW Proc %d\n",GetLastError());
  111. FreeLibrary(dllHandle);
  112. return FALSE;
  113. }
  114. //WinStationSendMessageW
  115. gpfnWinStationSendMessage = (PWINSTATION_SEND_MESSAGE) GetProcAddress(
  116. dllHandle,
  117. "WinStationSendMessageW"
  118. );
  119. if (gpfnWinStationSendMessage == NULL) {
  120. DbgPrint("InitializeMultiUserFunctions: Failed to get WinStationSendMessageW Proc %d\n",GetLastError());
  121. FreeLibrary(dllHandle);
  122. return FALSE;
  123. }
  124. //WinStationFreeMemory
  125. gpfnWinStationFreeMemory = (PWINSTATION_FREE_MEMORY) GetProcAddress(
  126. dllHandle,
  127. "WinStationFreeMemory"
  128. );
  129. if (gpfnWinStationFreeMemory == NULL) {
  130. DbgPrint("InitializeMultiUserFunctions: Failed to get WinStationFreeMemory Proc %d\n",GetLastError());
  131. FreeLibrary(dllHandle);
  132. return FALSE;
  133. }
  134. return TRUE;
  135. }
  136. /*****************************************************************************
  137. *
  138. * MsgArrivalBeep
  139. *
  140. * Handle the decision of whether we should Beep the console
  141. * when a message arrives.
  142. *
  143. * ENTRY:
  144. *
  145. * SessionId
  146. * Session Id of the recipient
  147. *
  148. * EXIT:
  149. * STATUS_SUCCESS - no error
  150. *
  151. ****************************************************************************/
  152. VOID
  153. MsgArrivalBeep(
  154. ULONG SessionId
  155. )
  156. {
  157. // very simple, isn'nt it ?
  158. //
  159. // only beep on the console
  160. //
  161. if (( SessionId == 0) || (SessionId == EVERYBODY_SESSION_ID))
  162. {
  163. MessageBeep(MB_OK);
  164. }
  165. }
  166. /*****************************************************************************
  167. *
  168. * DisplayMessage
  169. *
  170. * Display the incoming message to the proper user, regardless of
  171. * whether they are on the Console or a connected Session.
  172. *
  173. * The target user is embedded in the message and must be parsed out.
  174. *
  175. * ENTRY:
  176. * pMessage (input)
  177. * Message to deliver
  178. *
  179. * pTitle (input)
  180. * Title for the message box to use
  181. *
  182. * EXIT:
  183. * TRUE - At least once instance of user was found
  184. * and the message sent.
  185. *
  186. * FALSE - No instances of the user on any Sessions where
  187. * found.
  188. *
  189. ****************************************************************************/
  190. INT
  191. DisplayMessage(
  192. LPWSTR pMessage,
  193. LPWSTR pTitle,
  194. ULONG SessionId
  195. )
  196. {
  197. LPWSTR pName;
  198. INT Result = FALSE;
  199. UINT WdCount, i;
  200. PLOGONID pWd, pWdTmp;
  201. if (SessionId != EVERYBODY_SESSION_ID) // if it is not a message broadcasted to every session
  202. {
  203. SendMessageBoxToSession(pMessage,
  204. pTitle,
  205. SessionId);
  206. }
  207. else
  208. {
  209. // Enumerate the Sessions
  210. if ( gpfnWinStationEnumerate( SERVERNAME_CURRENT, &pWd, &WdCount ) )
  211. {
  212. pWdTmp = pWd;
  213. for( i=0; i < WdCount; i++ ) {
  214. if ((pWdTmp->State == State_Connected) ||
  215. (pWdTmp->State == State_Active) ||
  216. (pWdTmp->State == State_Disconnected))
  217. {
  218. SendMessageBoxToSession(pMessage,
  219. pTitle,
  220. pWdTmp->SessionId);
  221. }
  222. pWdTmp++;
  223. }
  224. // Free enumeration memory
  225. gpfnWinStationFreeMemory(pWd);
  226. }
  227. else
  228. {
  229. MSG_LOG (ERROR, "DisplayMessageW: WinStationEnumerate failed, error = %d:\n",GetLastError());
  230. //
  231. // Termsrv is now started by default on platforms so if this fails there is something wrong in termsrv
  232. }
  233. }
  234. return (TRUE);
  235. }
  236. /*****************************************************************************
  237. *
  238. * SendMessageBoxToSession
  239. *
  240. * Sends the message to the indicated Winstation
  241. *
  242. * ENTRY:
  243. * pMessage
  244. * pTitle
  245. * SessionId
  246. *
  247. ****************************************************************************/
  248. void
  249. SendMessageBoxToSession(LPWSTR pMessage,
  250. LPWSTR pTitle,
  251. ULONG SessionId
  252. )
  253. {
  254. ULONG TitleLength, MessageLength, Response;
  255. // Now send the message
  256. TitleLength = (wcslen( pTitle ) + 1) * sizeof(WCHAR);
  257. MessageLength = (wcslen( pMessage ) + 1) * sizeof(WCHAR);
  258. if( !gpfnWinStationSendMessage( SERVERNAME_CURRENT,
  259. SessionId,
  260. pTitle,
  261. TitleLength,
  262. pMessage,
  263. MessageLength,
  264. MB_OK | MB_DEFAULT_DESKTOP_ONLY,
  265. (ULONG)-1,
  266. &Response,
  267. TRUE ) ) {
  268. MSG_LOG(ERROR," Error in WinStationSendMessage for session %d\n", SessionId);
  269. //
  270. // We have actually found the user, but some WinStation
  271. // problem prevented delivery. If we return false here, the
  272. // top level message service code will try to keep sending the
  273. // message forever. So we return success here so that the message
  274. // gets dropped, and we do not hang the msgsvc thread as it
  275. // continually tries to re-send the message.
  276. //
  277. }
  278. return;
  279. }