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.

358 lines
9.8 KiB

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