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.

360 lines
9.3 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "Remote.h"
  5. #include "Server.h"
  6. //
  7. // This module uses mailslots to broadcast the existence of
  8. // this remote server to allow a form of browsing for
  9. // remote server instances. This is disabled in the
  10. // customer version of remote.exe, and can be disabled
  11. // in the internal version using the /v- switch to
  12. // remote /s.
  13. //
  14. // remoteds.c implements a listener that allows searching.
  15. //
  16. #define INITIAL_SLEEP_PERIOD (35 * 1000) // 35 seconds before first
  17. #define INITIAL_AD_RATE (10 * 60 * 1000) // 10 minutes between 1 & 2,
  18. #define MAXIMUM_AD_RATE (120 * 60 * 1000) // doubling until 120 minutes max
  19. OVERLAPPED olMailslot;
  20. HANDLE hAdTimer = INVALID_HANDLE_VALUE;
  21. HANDLE hMailslot = INVALID_HANDLE_VALUE;
  22. DWORD dwTimerInterval; // milliseconds
  23. BOOL bSynchAdOnly;
  24. BOOL bSendingToMailslot;
  25. char szMailslotName[64]; // netbios names are short
  26. char szSend[1024];
  27. #define MAX_MAILSLOT_SPEWS 2
  28. DWORD dwMailslotErrors;
  29. VOID
  30. InitAd(
  31. BOOL IsAdvertise
  32. )
  33. {
  34. DWORD cb;
  35. PWKSTA_INFO_101 pwki101;
  36. LARGE_INTEGER DueTime;
  37. if (IsAdvertise) {
  38. // Unless Win32s or Win9x support named pipe servers...
  39. ASSERT(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  40. // Problems with overlapped writes to a mailslot sometimes
  41. // cause remote.exe to zombie on exit on NT4, undebuggable
  42. // and unkillable because of an abandoned RDR1 IRP which
  43. // never completes.
  44. //
  45. // So on NT4 we only send messages at startup and shutdown
  46. // and send them synchronously using a nonoverlapped handle.
  47. //
  48. bSynchAdOnly = (OsVersionInfo.dwMajorVersion <= 4);
  49. //
  50. // Get currently active computername and browser/mailslot
  51. // domain/workgroup using one call to NetWkstaGetInfo.
  52. // This is unicode-only, we'll use wsprintf's %ls to
  53. // convert to 8-bit characters.
  54. //
  55. // remoteds.exe needs to be run on a workstation that is
  56. // part of the domain or workgroup of the same name,
  57. // and be in broadcast range, to receive our sends.
  58. //
  59. if (pfnNetWkstaGetInfo(NULL, 101, (LPBYTE *) &pwki101)) {
  60. printf("REMOTE: unable to get computer/domain name, not advertising.\n");
  61. return;
  62. }
  63. wsprintf(
  64. szMailslotName,
  65. "\\\\%ls\\MAILSLOT\\REMOTE\\DEBUGGERS",
  66. pwki101->wki101_langroup
  67. );
  68. wsprintf(
  69. szSend,
  70. "%ls\t%d\t%s\t%s",
  71. pwki101->wki101_computername,
  72. GetCurrentProcessId(),
  73. PipeName,
  74. ChildCmd
  75. );
  76. pfnNetApiBufferFree(pwki101);
  77. pwki101 = NULL;
  78. //
  79. // Broadcast mailslots are limited to 400 message bytes
  80. //
  81. szSend[399] = 0;
  82. if (bSynchAdOnly) {
  83. hMailslot =
  84. CreateFile(
  85. szMailslotName,
  86. GENERIC_WRITE,
  87. FILE_SHARE_WRITE,
  88. NULL,
  89. OPEN_EXISTING,
  90. 0,
  91. NULL
  92. );
  93. if (hMailslot != INVALID_HANDLE_VALUE) {
  94. if ( ! WriteFile(
  95. hMailslot,
  96. szSend,
  97. strlen(szSend) + 1,
  98. &cb,
  99. NULL
  100. )) {
  101. printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
  102. }
  103. } else {
  104. printf("REMOTE: Failed to create mailslot, error %d\n", GetLastError());
  105. }
  106. } else { // we can do async mailslot I/O
  107. //
  108. // Create a waitable timer and set it to fire first in
  109. // INITIAL_SLEEP_PERIOD milliseconds by calling the
  110. // completion routine AdvertiseTimerFired. It will
  111. // be given an inital period of INITIAL_AD_RATE ms.
  112. //
  113. hAdTimer =
  114. pfnCreateWaitableTimer(
  115. NULL, // security
  116. FALSE, // bManualReset, we want auto-reset
  117. NULL // unnamed
  118. );
  119. DueTime.QuadPart = Int32x32To64(INITIAL_SLEEP_PERIOD, -10000);
  120. dwTimerInterval = INITIAL_AD_RATE;
  121. pfnSetWaitableTimer(
  122. hAdTimer,
  123. &DueTime,
  124. dwTimerInterval,
  125. AdvertiseTimerFired,
  126. 0, // arg to compl. rtn
  127. TRUE
  128. );
  129. }
  130. }
  131. }
  132. VOID
  133. ShutAd(
  134. BOOL IsAdvertise
  135. )
  136. {
  137. DWORD cb;
  138. BOOL b;
  139. if (IsAdvertise) {
  140. if (INVALID_HANDLE_VALUE != hAdTimer) {
  141. pfnCancelWaitableTimer(hAdTimer);
  142. CloseHandle(hAdTimer);
  143. hAdTimer = INVALID_HANDLE_VALUE;
  144. }
  145. if (INVALID_HANDLE_VALUE != hMailslot &&
  146. ! bSendingToMailslot) {
  147. //
  148. // Tell any listening remoteds's we're
  149. // outta here. Do this by tacking on
  150. // a ^B at the end of the string (as
  151. // in Bye).
  152. //
  153. strcat(szSend, "\x2");
  154. if (bSynchAdOnly) { // overlapped handle or not?
  155. b = WriteFile(
  156. hMailslot,
  157. szSend,
  158. strlen(szSend) + 1,
  159. &cb,
  160. NULL
  161. );
  162. } else {
  163. b = WriteFileSynch(
  164. hMailslot,
  165. szSend,
  166. strlen(szSend) + 1,
  167. &cb,
  168. 0,
  169. &olMainThread
  170. );
  171. }
  172. if ( ! b ) {
  173. printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
  174. }
  175. }
  176. if (INVALID_HANDLE_VALUE != hMailslot) {
  177. printf("\rREMOTE: closing mailslot... ");
  178. fflush(stdout);
  179. CloseHandle(hMailslot);
  180. hMailslot = INVALID_HANDLE_VALUE;
  181. printf("\r \r");
  182. fflush(stdout);
  183. }
  184. }
  185. }
  186. VOID
  187. APIENTRY
  188. AdvertiseTimerFired(
  189. LPVOID pArg,
  190. DWORD dwTimerLo,
  191. DWORD dwTimerHi
  192. )
  193. {
  194. UNREFERENCED_PARAMETER( pArg );
  195. UNREFERENCED_PARAMETER( dwTimerLo );
  196. UNREFERENCED_PARAMETER( dwTimerHi );
  197. if (INVALID_HANDLE_VALUE == hMailslot) {
  198. hMailslot =
  199. CreateFile(
  200. szMailslotName,
  201. GENERIC_WRITE,
  202. FILE_SHARE_WRITE,
  203. NULL,
  204. OPEN_EXISTING,
  205. FILE_FLAG_OVERLAPPED,
  206. NULL
  207. );
  208. }
  209. if (INVALID_HANDLE_VALUE != hMailslot) {
  210. ZeroMemory(&olMailslot, sizeof(olMailslot));
  211. bSendingToMailslot = TRUE;
  212. if ( ! WriteFileEx(
  213. hMailslot,
  214. szSend,
  215. strlen(szSend) + 1,
  216. &olMailslot,
  217. WriteMailslotCompleted
  218. )) {
  219. bSendingToMailslot = FALSE;
  220. if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {
  221. DWORD dwError;
  222. char szErrorText[512];
  223. dwError = GetLastError();
  224. FormatMessage(
  225. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  226. NULL,
  227. dwError,
  228. 0,
  229. szErrorText,
  230. sizeof szErrorText,
  231. NULL
  232. );
  233. //
  234. // FormatMessage has put a newline at the end of szErrorText
  235. //
  236. printf(
  237. "REMOTE: Advertisement failed, mailslot error %d:\n%s",
  238. dwError,
  239. szErrorText
  240. );
  241. }
  242. //
  243. // Try reopening the mailslot next time, can't hurt.
  244. //
  245. CloseHandle(hMailslot);
  246. hMailslot = INVALID_HANDLE_VALUE;
  247. }
  248. }
  249. }
  250. VOID
  251. WINAPI
  252. WriteMailslotCompleted(
  253. DWORD dwError,
  254. DWORD cbWritten,
  255. LPOVERLAPPED lpO
  256. )
  257. {
  258. LARGE_INTEGER DueTime;
  259. bSendingToMailslot = FALSE;
  260. if (dwError ||
  261. (strlen(szSend) + 1) != cbWritten) {
  262. if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {
  263. printf("REMOTE: write failed on mailslot, error %d cb %d (s/b %d)\n",
  264. dwError, cbWritten, (strlen(szSend) + 1));
  265. }
  266. return;
  267. }
  268. //
  269. // If we succeeded in writing the mailslot, double the timer interval
  270. // up to the limit.
  271. //
  272. if (dwTimerInterval < MAXIMUM_AD_RATE) {
  273. dwTimerInterval = max(dwTimerInterval * 2, MAXIMUM_AD_RATE);
  274. DueTime.QuadPart = Int32x32To64(dwTimerInterval, -10000);
  275. if (INVALID_HANDLE_VALUE != hAdTimer) {
  276. pfnSetWaitableTimer(
  277. hAdTimer,
  278. &DueTime,
  279. dwTimerInterval,
  280. AdvertiseTimerFired,
  281. 0, // arg to compl. rtn
  282. TRUE
  283. );
  284. }
  285. }
  286. }