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.

603 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Starts a process server and sleeps forever.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include <stdio.h>
  9. #ifdef _DBGSRV_
  10. #include <dbgeng.h>
  11. #else
  12. #ifndef _WIN32_WCE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #endif
  17. #ifdef _NTDBGSRV_
  18. #define _ADVAPI32_
  19. #define _KERNEL32_
  20. #endif
  21. #include <windows.h>
  22. #include <wcecompat.h>
  23. #define INITGUID
  24. #include <objbase.h>
  25. #ifndef _WIN32_WCE
  26. #define NOEXTAPI
  27. #include <wdbgexts.h>
  28. #include <ntdbg.h>
  29. #endif
  30. #define NTDLL_APIS
  31. #include <dllimp.h>
  32. #include <dbgrpc.hpp>
  33. #include <dbgsvc.h>
  34. #include <dbgsvc.hpp>
  35. #ifdef _NTDBGSRV_
  36. // The .CRT section is generated when static intializers,
  37. // such as global class instances, exist. It needs to
  38. // be merged into .data to avoid a linker warning.
  39. #pragma comment(linker, "/merge:.CRT=.data")
  40. #endif
  41. #endif // #ifdef _DBGSRV_
  42. #include <cmnutil.hpp>
  43. #if defined(_NTDBGSRV_)
  44. #define APP_NAME "ntdbgsrv"
  45. #elif defined(_MDBGSRV_)
  46. #define APP_NAME "mdbgsrv"
  47. #elif defined(_DBGSRV_)
  48. #define APP_NAME "dbgsrv"
  49. #else
  50. #error Bad build type.
  51. #endif
  52. void DECLSPEC_NORETURN
  53. PanicExit(char* Title, char* Msg)
  54. {
  55. #if defined(_NTDBGSRV_)
  56. if (Title)
  57. {
  58. DbgPrint("%s: %s", Title, Msg);
  59. }
  60. else
  61. {
  62. DbgPrint("%s", Msg);
  63. }
  64. NtTerminateProcess(NtCurrentProcess(), (NTSTATUS)1);
  65. #elif defined(_MDBGSRV_)
  66. if (Title)
  67. {
  68. OutputDebugStringA(Title);
  69. OutputDebugStringA(": ");
  70. }
  71. OutputDebugStringA(Msg);
  72. #ifdef _WIN32_WCE
  73. exit(1);
  74. #else
  75. ExitProcess(1);
  76. #endif
  77. #elif defined(_DBGSRV_)
  78. MessageBox(GetDesktopWindow(), Msg, Title, MB_OK);
  79. exit(1);
  80. #else
  81. #error Bad build type.
  82. #endif
  83. }
  84. void DECLSPEC_NORETURN
  85. PanicVa(char* Title, char* Format, va_list Args)
  86. {
  87. char Msg[256];
  88. _vsnprintf(Msg, sizeof(Msg), Format, Args);
  89. Msg[sizeof(Msg) - 1] = 0;
  90. PanicExit(Title, Msg);
  91. }
  92. void
  93. PanicMessage(char* Title, char* Format, ...)
  94. {
  95. va_list Args;
  96. va_start(Args, Format);
  97. PanicVa(Title, Format, Args);
  98. va_end(Args);
  99. }
  100. void DECLSPEC_NORETURN
  101. PanicStatus(HRESULT Status, char* Format, ...)
  102. {
  103. va_list Args;
  104. char Msg[256];
  105. char Err[32];
  106. va_start(Args, Format);
  107. _vsnprintf(Msg, sizeof(Msg), Format, Args);
  108. Msg[sizeof(Msg) - 1] = 0;
  109. va_end(Args);
  110. sprintf(Err, "Error 0x%08X", Status);
  111. PanicExit(Err, Msg);
  112. }
  113. #ifndef _DBGSRV_
  114. #if DBG
  115. void
  116. DbgAssertionFailed(PCSTR File, int Line, PCSTR Str)
  117. {
  118. PanicMessage("Assertion failed", "%s(%d)\n %s\n",
  119. File, Line, Str);
  120. }
  121. #endif
  122. //----------------------------------------------------------------------------
  123. //
  124. // Proxy and stub support.
  125. //
  126. //----------------------------------------------------------------------------
  127. // Generated headers.
  128. #include "dbgsvc_p.hpp"
  129. #include "dbgsvc_s.hpp"
  130. void
  131. DbgRpcInitializeClient(void)
  132. {
  133. DbgRpcInitializeStubTables_dbgsvc(DBGRPC_SIF_DBGSVC_FIRST);
  134. }
  135. DbgRpcStubFunction
  136. DbgRpcGetStub(USHORT StubIndex)
  137. {
  138. USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
  139. USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
  140. DbgRpcStubFunctionTable* Table;
  141. if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
  142. If >= DBGRPC_SIF_DBGSVC_LAST)
  143. {
  144. Table = g_DbgRpcStubs_dbgsvc;
  145. If -= DBGRPC_SIF_DBGSVC_FIRST;
  146. }
  147. else
  148. {
  149. return NULL;
  150. }
  151. if (Mth >= Table[If].Count)
  152. {
  153. return NULL;
  154. }
  155. return Table[If].Functions[Mth];
  156. }
  157. #if DBG
  158. PCSTR
  159. DbgRpcGetStubName(USHORT StubIndex)
  160. {
  161. USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
  162. USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
  163. DbgRpcStubFunctionTable* Table;
  164. PCSTR** Names;
  165. if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
  166. If >= DBGRPC_SIF_DBGSVC_LAST)
  167. {
  168. Table = g_DbgRpcStubs_dbgsvc;
  169. Names = g_DbgRpcStubNames_dbgsvc;
  170. If -= DBGRPC_SIF_DBGSVC_FIRST;
  171. }
  172. else
  173. {
  174. return "!InvalidInterface!";
  175. }
  176. if (Mth >= Table[If].Count)
  177. {
  178. return "!InvalidStubIndex!";
  179. }
  180. return Names[If][Mth];
  181. }
  182. #endif // #if DBG
  183. HRESULT
  184. DbgRpcPreallocProxy(REFIID InterfaceId, PVOID* Interface,
  185. DbgRpcProxy** Proxy, PULONG IfUnique)
  186. {
  187. return DbgRpcPreallocProxy_dbgsvc(InterfaceId, Interface,
  188. Proxy, IfUnique);
  189. }
  190. void
  191. DbgRpcDeleteProxy(class DbgRpcProxy* Proxy)
  192. {
  193. // All proxies used here are similar simple single
  194. // vtable proxy objects so IDebugClient can represent them all.
  195. delete (ProxyIUserDebugServices*)Proxy;
  196. }
  197. HRESULT
  198. DbgRpcServerThreadInitialize(void)
  199. {
  200. // Nothing to do.
  201. return S_OK;
  202. }
  203. void
  204. DbgRpcServerThreadUninitialize(void)
  205. {
  206. // Nothing to do.
  207. }
  208. void
  209. DbgRpcError(char* Format, ...)
  210. {
  211. va_list Args;
  212. va_start(Args, Format);
  213. PanicVa(NULL, Format, Args);
  214. va_end(Args);
  215. }
  216. DBGRPC_SIMPLE_FACTORY(LiveUserDebugServices, __uuidof(IUserDebugServices), \
  217. "Remote Process Server", (TRUE))
  218. LiveUserDebugServicesFactory g_LiveUserDebugServicesFactory;
  219. #ifdef _NTDBGSRV_
  220. #ifdef _M_IA64
  221. #pragma section(".CRT$XCA",long,read)
  222. #pragma section(".CRT$XCZ",long,read)
  223. #pragma section(".CRT$XIA",long,read)
  224. #pragma section(".CRT$XIZ",long,read)
  225. #define _CRTALLOC(x) __declspec(allocate(x))
  226. #else /* ndef _M_IA64 */
  227. #define _CRTALLOC(x)
  228. #endif /* ndef _M_IA64 */
  229. typedef void (__cdecl *_PVFV)(void);
  230. extern "C"
  231. {
  232. // C initializers collect here.
  233. #pragma data_seg(".CRT$XIA")
  234. _CRTALLOC(".CRT$XIA") _PVFV __xi_a[] = { NULL };
  235. #pragma data_seg(".CRT$XIZ")
  236. _CRTALLOC(".CRT$XIZ") _PVFV __xi_z[] = { NULL };
  237. // C++ initializers collect here.
  238. #pragma data_seg(".CRT$XCA")
  239. _CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = { NULL };
  240. #pragma data_seg(".CRT$XCZ")
  241. _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[] = { NULL };
  242. };
  243. void __cdecl
  244. _initterm (_PVFV * pfbegin, _PVFV * pfend)
  245. {
  246. /*
  247. * walk the table of function pointers from the bottom up, until
  248. * the end is encountered. Do not skip the first entry. The initial
  249. * value of pfbegin points to the first valid entry. Do not try to
  250. * execute what pfend points to. Only entries before pfend are valid.
  251. */
  252. while ( pfbegin < pfend )
  253. {
  254. /*
  255. * if current table entry is non-NULL, call thru it.
  256. */
  257. if ( *pfbegin != NULL )
  258. {
  259. (**pfbegin)();
  260. }
  261. ++pfbegin;
  262. }
  263. }
  264. #endif // #ifdef _NTDBGSRV_
  265. void
  266. Run(PSTR Options, PWSTR CreateCmd, ULONG CreateFlags)
  267. {
  268. HRESULT Status;
  269. #ifdef _NTDBGSRV_
  270. DbgPrint("Running %s with '%s'\n", APP_NAME, Options);
  271. #else
  272. OutputDebugStringA("Running ");
  273. OutputDebugStringA(APP_NAME);
  274. OutputDebugStringA(" with '");
  275. OutputDebugStringA(Options);
  276. OutputDebugStringA("'\n");
  277. #endif
  278. if ((Status = InitDynamicCalls(&g_NtDllCallsDesc)) != S_OK)
  279. {
  280. PanicStatus(Status, "InitDynamicCalls\n");
  281. }
  282. ULONG Flags;
  283. if ((Status = g_LiveUserDebugServices.Initialize(&Flags)) != S_OK)
  284. {
  285. PanicStatus(Status, "LiveUserDebugServices::Initialize\n");
  286. }
  287. //
  288. // Create the server.
  289. //
  290. if ((Status = DbgRpcCreateServer(Options,
  291. &g_LiveUserDebugServicesFactory,
  292. FALSE)) != S_OK)
  293. {
  294. PanicStatus(Status, "StartProcessServer\n");
  295. }
  296. //
  297. // If there's a creation request create the process.
  298. //
  299. if (CreateCmd)
  300. {
  301. ULONG ProcId, ThreadId;
  302. ULONG64 ProcHandle, ThreadHandle;
  303. if ((Status = g_LiveUserDebugServices.
  304. CreateProcessW(CreateCmd, CreateFlags, TRUE, NULL,
  305. &ProcId, &ThreadId,
  306. &ProcHandle, &ThreadHandle)) != S_OK)
  307. {
  308. PanicStatus(Status, "CreateProcessW\n");
  309. }
  310. g_LiveUserDebugServices.CloseHandle(ProcHandle);
  311. g_LiveUserDebugServices.CloseHandle(ThreadHandle);
  312. }
  313. //
  314. // Wait forever for the server to exit.
  315. //
  316. for (;;)
  317. {
  318. Sleep(1000);
  319. if (g_UserServicesUninitialized)
  320. {
  321. break;
  322. }
  323. }
  324. DbgRpcDeregisterServers();
  325. }
  326. #else // #ifndef _DBGSRV_
  327. void
  328. Run(PSTR Options, PWSTR CreateCmd, ULONG CreateFlags)
  329. {
  330. HRESULT Status;
  331. PDEBUG_CLIENT BaseClient;
  332. PDEBUG_CLIENT3 Client;
  333. if ((Status = DebugCreate(__uuidof(IDebugClient),
  334. (void**)&BaseClient)) != S_OK)
  335. {
  336. PanicStatus(Status, "DebugCreate\n");
  337. }
  338. if ((Status = BaseClient->QueryInterface(__uuidof(IDebugClient3),
  339. (void**)&Client)) != S_OK)
  340. {
  341. PanicStatus(Status, "dbgeng version 3 is required\n");
  342. }
  343. BaseClient->Release();
  344. //
  345. // Create the server.
  346. //
  347. if ((Status = Client->
  348. StartProcessServer(DEBUG_CLASS_USER_WINDOWS, Options, NULL)) != S_OK)
  349. {
  350. PanicStatus(Status, "StartProcessServer\n");
  351. }
  352. //
  353. // If there's a creation request create the process.
  354. //
  355. if (CreateCmd)
  356. {
  357. if ((Status = Client->
  358. CreateProcessWide(0, CreateCmd, CreateFlags)) != S_OK)
  359. {
  360. Client->Release();
  361. PanicStatus(Status, "CreateProcessWide\n");
  362. }
  363. }
  364. //
  365. // Wait forever for the server to exit.
  366. //
  367. Client->WaitForProcessServerEnd(INFINITE);
  368. Client->EndSession(DEBUG_END_REENTRANT);
  369. Client->Release();
  370. }
  371. #endif // #ifndef _DBGSRV_
  372. void __cdecl
  373. main(int Argc, char** Argv)
  374. {
  375. HRESULT Status;
  376. PSTR Options = NULL;
  377. BOOL Usage = FALSE;
  378. BOOL CreateSuspended = FALSE;
  379. BOOL CreateArgs = FALSE;
  380. int ArgChars;
  381. #ifdef _NTDBGSRV_
  382. // Manually invoke C and C++ initializers.
  383. _initterm( __xi_a, __xi_z );
  384. _initterm( __xc_a, __xc_z );
  385. #endif
  386. ArgChars = strlen(Argv[0]);
  387. while (--Argc > 0)
  388. {
  389. Argv++;
  390. if (Argc > 1 && !strcmp(*Argv, "-t"))
  391. {
  392. ArgChars += strlen(*Argv) + 1;
  393. Options = *++Argv;
  394. Argc--;
  395. }
  396. else if (!strcmp(*Argv, "-c"))
  397. {
  398. // Ignore the remainder of the command line.
  399. CreateArgs = TRUE;
  400. break;
  401. }
  402. else if (!strcmp(*Argv, "-cs"))
  403. {
  404. // Ignore the remainder of the command line.
  405. CreateSuspended = TRUE;
  406. CreateArgs = TRUE;
  407. break;
  408. }
  409. else if (!strcmp(*Argv, "-x"))
  410. {
  411. // Ignore the remainder of the command line.
  412. break;
  413. }
  414. else
  415. {
  416. if (**Argv == '-' ||
  417. Argc != 1)
  418. {
  419. Usage = TRUE;
  420. }
  421. else
  422. {
  423. Options = *Argv;
  424. }
  425. break;
  426. }
  427. ArgChars += strlen(*Argv) + 1;
  428. }
  429. if (Usage || !Options)
  430. {
  431. PanicExit("Invalid Command Line",
  432. "Usage: dbgsrv [-t <transport>] [-x] [-c[s] <args...>]\n"
  433. " transport: tcp | npipe | ssl | spipe | 1394 | com\n"
  434. " for tcp use: port=<socket port #>\n"
  435. " for npipe use: pipe=<name of pipe>\n"
  436. " for 1394 use: channel=<channel #>\n"
  437. " for com use: port=<COM port>,baud=<baud rate>,\n"
  438. " channel=<channel #>\n"
  439. " for ssl and spipe see the documentation\n"
  440. "\n"
  441. "Example: " APP_NAME " -t npipe:pipe=foobar\n");
  442. }
  443. //
  444. // If there are process creation args on the
  445. // end of the command line locate them in the
  446. // real command line.
  447. //
  448. PWSTR CreateCmd = NULL;
  449. ULONG CreateFlags = 0;
  450. if (CreateArgs)
  451. {
  452. if (CreateSuspended)
  453. {
  454. CreateFlags |= CREATE_SUSPENDED;
  455. }
  456. CreateCmd = GetCommandLineW();
  457. if (!CreateCmd)
  458. {
  459. PSTR CmdA = GetCommandLineA();
  460. if (!CmdA)
  461. {
  462. PanicStatus(E_FAIL, "Unable to get command line\n");
  463. }
  464. if ((Status = AnsiToWide(CmdA, &CreateCmd)) != S_OK)
  465. {
  466. PanicStatus(Status, "AnsiToWide\n");
  467. }
  468. }
  469. CreateCmd += ArgChars;
  470. while (*CreateCmd &&
  471. ((CreateCmd[0] != L' ' && CreateCmd[0] != L'\t') ||
  472. CreateCmd[1] != L'-' ||
  473. CreateCmd[2] != L'c' ||
  474. (!CreateSuspended &&
  475. (CreateCmd[3] != L' ' && CreateCmd[3] != L'\t')) ||
  476. (CreateSuspended &&
  477. (CreateCmd[3] != L's' ||
  478. (CreateCmd[4] != L' ' && CreateCmd[4] != L'\t')))))
  479. {
  480. CreateCmd++;
  481. }
  482. if (!*CreateCmd)
  483. {
  484. PanicExit("Invalid Command Line", "Unable to locate -c[s]");
  485. }
  486. if (CreateSuspended)
  487. {
  488. CreateCmd += 4;
  489. }
  490. else
  491. {
  492. CreateCmd += 3;
  493. }
  494. while (*CreateCmd == L' ' || *CreateCmd == L'\t')
  495. {
  496. CreateCmd++;
  497. }
  498. }
  499. Run(Options, CreateCmd, CreateFlags);
  500. }