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.

1099 lines
26 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Engine interface proxies and stubs.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // Generated headers.
  10. #include "dbgeng_p.hpp"
  11. #include "dbgeng_s.hpp"
  12. #include "dbgsvc_p.hpp"
  13. #include "dbgsvc_s.hpp"
  14. //----------------------------------------------------------------------------
  15. //
  16. // Initialization.
  17. //
  18. //----------------------------------------------------------------------------
  19. void
  20. DbgRpcInitializeClient(void)
  21. {
  22. DbgRpcInitializeStubTables_dbgeng(DBGRPC_SIF_DBGENG_FIRST);
  23. DbgRpcInitializeStubTables_dbgsvc(DBGRPC_SIF_DBGSVC_FIRST);
  24. // Ensure that the V1 interfaces can't change.
  25. C_ASSERT(DBGRPC_UNIQUE_IDebugAdvanced == 19156);
  26. C_ASSERT(DBGRPC_UNIQUE_IDebugBreakpoint == 76131);
  27. C_ASSERT(DBGRPC_UNIQUE_IDebugClient == 229769);
  28. C_ASSERT(DBGRPC_UNIQUE_IDebugControl == 590362);
  29. C_ASSERT(DBGRPC_UNIQUE_IDebugDataSpaces == 180033);
  30. C_ASSERT(DBGRPC_UNIQUE_IDebugEventCallbacks == 87804);
  31. C_ASSERT(DBGRPC_UNIQUE_IDebugInputCallbacks == 10391);
  32. C_ASSERT(DBGRPC_UNIQUE_IDebugOutputCallbacks == 9646);
  33. C_ASSERT(DBGRPC_UNIQUE_IDebugRegisters == 69746);
  34. C_ASSERT(DBGRPC_UNIQUE_IDebugSymbolGroup == 53300);
  35. C_ASSERT(DBGRPC_UNIQUE_IDebugSymbols == 376151);
  36. C_ASSERT(DBGRPC_UNIQUE_IDebugSystemObjects == 135421);
  37. // Ensure that the V2 interfaces can't change.
  38. C_ASSERT(DBGRPC_UNIQUE_IDebugClient2 == 258161);
  39. C_ASSERT(DBGRPC_UNIQUE_IDebugControl2 == 635813);
  40. C_ASSERT(DBGRPC_UNIQUE_IDebugDataSpaces2 == 231471);
  41. C_ASSERT(DBGRPC_UNIQUE_IDebugSymbols2 == 435328);
  42. C_ASSERT(DBGRPC_UNIQUE_IDebugSystemObjects2 == 155936);
  43. }
  44. //----------------------------------------------------------------------------
  45. //
  46. // Proxy and stub support.
  47. //
  48. //----------------------------------------------------------------------------
  49. DbgRpcStubFunction
  50. DbgRpcGetStub(USHORT StubIndex)
  51. {
  52. USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
  53. USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
  54. DbgRpcStubFunctionTable* Table;
  55. if (If <= DBGRPC_SIF_DBGENG_LAST)
  56. {
  57. Table = g_DbgRpcStubs_dbgeng;
  58. }
  59. else if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
  60. If >= DBGRPC_SIF_DBGSVC_LAST)
  61. {
  62. Table = g_DbgRpcStubs_dbgsvc;
  63. If -= DBGRPC_SIF_DBGSVC_FIRST;
  64. }
  65. else
  66. {
  67. return NULL;
  68. }
  69. if (Mth >= Table[If].Count)
  70. {
  71. return NULL;
  72. }
  73. return Table[If].Functions[Mth];
  74. }
  75. #if DBG
  76. PCSTR
  77. DbgRpcGetStubName(USHORT StubIndex)
  78. {
  79. USHORT If = (USHORT) DBGRPC_STUB_INDEX_INTERFACE(StubIndex);
  80. USHORT Mth = (USHORT) DBGRPC_STUB_INDEX_METHOD(StubIndex);
  81. DbgRpcStubFunctionTable* Table;
  82. PCSTR** Names;
  83. if (If <= DBGRPC_SIF_DBGENG_LAST)
  84. {
  85. Table = g_DbgRpcStubs_dbgeng;
  86. Names = g_DbgRpcStubNames_dbgeng;
  87. }
  88. else if (If >= DBGRPC_SIF_DBGSVC_FIRST &&
  89. If >= DBGRPC_SIF_DBGSVC_LAST)
  90. {
  91. Table = g_DbgRpcStubs_dbgsvc;
  92. Names = g_DbgRpcStubNames_dbgsvc;
  93. If -= DBGRPC_SIF_DBGSVC_FIRST;
  94. }
  95. else
  96. {
  97. return "!InvalidInterface!";
  98. }
  99. if (Mth >= Table[If].Count)
  100. {
  101. return "!InvalidStubIndex!";
  102. }
  103. return Names[If][Mth];
  104. }
  105. #endif // #if DBG
  106. HRESULT
  107. DbgRpcPreallocProxy(REFIID InterfaceId, PVOID* Interface,
  108. DbgRpcProxy** Proxy, PULONG IfUnique)
  109. {
  110. HRESULT Status;
  111. Status = DbgRpcPreallocProxy_dbgeng(InterfaceId, Interface,
  112. Proxy, IfUnique);
  113. if (Status == E_NOINTERFACE)
  114. {
  115. Status = DbgRpcPreallocProxy_dbgsvc(InterfaceId, Interface,
  116. Proxy, IfUnique);
  117. }
  118. return Status;
  119. }
  120. void
  121. DbgRpcDeleteProxy(class DbgRpcProxy* Proxy)
  122. {
  123. // All proxies used here are similar simple single
  124. // vtable proxy objects so IDebugClient can represent them all.
  125. delete (ProxyIDebugClient*)Proxy;
  126. }
  127. HRESULT
  128. DbgRpcServerThreadInitialize(void)
  129. {
  130. return g_Target->ThreadInitialize();
  131. }
  132. void
  133. DbgRpcServerThreadUninitialize(void)
  134. {
  135. g_Target->ThreadUninitialize();
  136. }
  137. void
  138. DbgRpcError(char* Format, ...)
  139. {
  140. va_list Args;
  141. va_start(Args, Format);
  142. MaskOutVa(DEBUG_OUTPUT_ERROR, Format, Args, TRUE);
  143. va_end(Args);
  144. }
  145. //----------------------------------------------------------------------------
  146. //
  147. // Generated RPC proxies and stubs.
  148. //
  149. //----------------------------------------------------------------------------
  150. #include "dbgeng_p.cpp"
  151. #include "dbgeng_s.cpp"
  152. //----------------------------------------------------------------------------
  153. //
  154. // Hand-written proxies and stubs.
  155. //
  156. //----------------------------------------------------------------------------
  157. STDMETHODIMP
  158. ProxyIDebugClient::CreateClient(
  159. OUT PDEBUG_CLIENT* Client
  160. )
  161. {
  162. DbgRpcConnection* Conn;
  163. // Always look up the owning connection.
  164. Conn = DbgRpcGetConnection(m_OwningThread);
  165. if (Conn == NULL)
  166. {
  167. return RPC_E_CONNECTION_TERMINATED;
  168. }
  169. if (GetCurrentThreadId() != m_OwningThread)
  170. {
  171. // The caller wants a new client for a new thread.
  172. // Create a new RPC connection based on the owning connection.
  173. DbgRpcTransport* Trans = Conn->m_Trans->Clone();
  174. if (Trans == NULL)
  175. {
  176. return E_OUTOFMEMORY;
  177. }
  178. return DbgRpcCreateServerConnection(Trans, &IID_IDebugClient,
  179. (IUnknown**)Client);
  180. }
  181. //
  182. // Just creating another client for the owning thread.
  183. // Normal RPC.
  184. //
  185. HRESULT Status;
  186. DbgRpcCall Call;
  187. PUCHAR Data;
  188. PDEBUG_CLIENT Proxy;
  189. if ((Data = Conn->StartCall(&Call, m_ObjectId,
  190. DBGRPC_STUB_INDEX(m_InterfaceIndex,
  191. DBGRPC_SMTH_IDebugClient_CreateClient),
  192. 0, sizeof(DbgRpcObjectId))) == NULL)
  193. {
  194. Status = E_OUTOFMEMORY;
  195. }
  196. else
  197. {
  198. if ((Proxy = DbgRpcPreallocIDebugClientProxy()) == NULL)
  199. {
  200. Status = E_OUTOFMEMORY;
  201. }
  202. else
  203. {
  204. Status = Conn->SendReceive(&Call, &Data);
  205. if (Status == S_OK)
  206. {
  207. *Client = (PDEBUG_CLIENT)
  208. ((ProxyIDebugClient*)Proxy)->
  209. InitializeProxy(*(DbgRpcObjectId*)Data, Proxy);
  210. }
  211. else
  212. {
  213. delete Proxy;
  214. }
  215. }
  216. Conn->FreeData(Data);
  217. }
  218. return Status;
  219. }
  220. STDMETHODIMP
  221. ProxyIDebugClient::StartProcessServer(
  222. IN ULONG Flags,
  223. IN PCSTR Options,
  224. IN PVOID Reserved
  225. )
  226. {
  227. if (::GetCurrentThreadId() != m_OwningThread)
  228. {
  229. return E_INVALIDARG;
  230. }
  231. if (Reserved != NULL)
  232. {
  233. return E_INVALIDARG;
  234. }
  235. DbgRpcConnection* Conn;
  236. DbgRpcCall Call;
  237. PUCHAR Data;
  238. HRESULT Status;
  239. ULONG Len = strlen(Options) + 1;
  240. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  241. (Data = Conn->StartCall(&Call, m_ObjectId,
  242. DBGRPC_STUB_INDEX(m_InterfaceIndex,
  243. DBGRPC_SMTH_IDebugClient_StartProcessServer),
  244. Len + sizeof(ULONG), 0)) == NULL)
  245. {
  246. Status = E_OUTOFMEMORY;
  247. }
  248. else
  249. {
  250. PUCHAR InData = Data;
  251. *(ULONG*)InData = Flags;
  252. InData += sizeof(ULONG);
  253. memcpy(InData, Options, Len);
  254. Status = Conn->SendReceive(&Call, &Data);
  255. Conn->FreeData(Data);
  256. }
  257. return Status;
  258. }
  259. STDMETHODIMP
  260. ProxyIDebugClient2::CreateClient(
  261. OUT PDEBUG_CLIENT* Client
  262. )
  263. {
  264. DbgRpcConnection* Conn;
  265. // Always look up the owning connection.
  266. Conn = DbgRpcGetConnection(m_OwningThread);
  267. if (Conn == NULL)
  268. {
  269. return RPC_E_CONNECTION_TERMINATED;
  270. }
  271. if (GetCurrentThreadId() != m_OwningThread)
  272. {
  273. // The caller wants a new client for a new thread.
  274. // Create a new RPC connection based on the owning connection.
  275. DbgRpcTransport* Trans = Conn->m_Trans->Clone();
  276. if (Trans == NULL)
  277. {
  278. return E_OUTOFMEMORY;
  279. }
  280. return DbgRpcCreateServerConnection(Trans, &IID_IDebugClient,
  281. (IUnknown**)Client);
  282. }
  283. //
  284. // Just creating another client for the owning thread.
  285. // Normal RPC.
  286. //
  287. HRESULT Status;
  288. DbgRpcCall Call;
  289. PUCHAR Data;
  290. PDEBUG_CLIENT Proxy;
  291. if ((Data = Conn->StartCall(&Call, m_ObjectId,
  292. DBGRPC_STUB_INDEX(m_InterfaceIndex,
  293. DBGRPC_SMTH_IDebugClient2_CreateClient),
  294. 0, sizeof(DbgRpcObjectId))) == NULL)
  295. {
  296. Status = E_OUTOFMEMORY;
  297. }
  298. else
  299. {
  300. if ((Proxy = DbgRpcPreallocIDebugClientProxy()) == NULL)
  301. {
  302. Status = E_OUTOFMEMORY;
  303. }
  304. else
  305. {
  306. Status = Conn->SendReceive(&Call, &Data);
  307. if (Status == S_OK)
  308. {
  309. *Client = (PDEBUG_CLIENT)
  310. ((ProxyIDebugClient*)Proxy)->
  311. InitializeProxy(*(DbgRpcObjectId*)Data, Proxy);
  312. }
  313. else
  314. {
  315. delete Proxy;
  316. }
  317. }
  318. Conn->FreeData(Data);
  319. }
  320. return Status;
  321. }
  322. STDMETHODIMP
  323. ProxyIDebugClient2::StartProcessServer(
  324. IN ULONG Flags,
  325. IN PCSTR Options,
  326. IN PVOID Reserved
  327. )
  328. {
  329. if (::GetCurrentThreadId() != m_OwningThread)
  330. {
  331. return E_INVALIDARG;
  332. }
  333. if (Reserved != NULL)
  334. {
  335. return E_INVALIDARG;
  336. }
  337. DbgRpcConnection* Conn;
  338. DbgRpcCall Call;
  339. PUCHAR Data;
  340. HRESULT Status;
  341. ULONG Len = strlen(Options) + 1;
  342. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  343. (Data = Conn->StartCall(&Call, m_ObjectId,
  344. DBGRPC_STUB_INDEX(m_InterfaceIndex,
  345. DBGRPC_SMTH_IDebugClient2_StartProcessServer),
  346. Len + sizeof(ULONG), 0)) == NULL)
  347. {
  348. Status = E_OUTOFMEMORY;
  349. }
  350. else
  351. {
  352. PUCHAR InData = Data;
  353. *(ULONG*)InData = Flags;
  354. InData += sizeof(ULONG);
  355. memcpy(InData, Options, Len);
  356. Status = Conn->SendReceive(&Call, &Data);
  357. Conn->FreeData(Data);
  358. }
  359. return Status;
  360. }
  361. //
  362. // The following methods are hand-written to convert
  363. // varargs output into simple strings before sending
  364. // them on.
  365. //
  366. STDMETHODIMPV
  367. ProxyIDebugControl::Output(
  368. IN ULONG Mask,
  369. IN PCSTR Format,
  370. ...
  371. )
  372. {
  373. va_list Args;
  374. HRESULT Status;
  375. if (::GetCurrentThreadId() != m_OwningThread)
  376. {
  377. return E_INVALIDARG;
  378. }
  379. va_start(Args, Format);
  380. Status = OutputVaList(Mask, Format, Args);
  381. va_end(Args);
  382. return Status;
  383. }
  384. STDMETHODIMP
  385. ProxyIDebugControl::OutputVaList(
  386. THIS_
  387. IN ULONG Mask,
  388. IN PCSTR Format,
  389. IN va_list Args
  390. )
  391. {
  392. int Len;
  393. // Need the engine lock for the global buffers.
  394. ENTER_ENGINE();
  395. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  396. {
  397. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  398. g_FormatBuffer, Args);
  399. }
  400. else
  401. {
  402. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  403. }
  404. if (Len <= 0)
  405. {
  406. LEAVE_ENGINE();
  407. return E_INVALIDARG;
  408. }
  409. else
  410. {
  411. Len++;
  412. }
  413. DbgRpcConnection* Conn;
  414. DbgRpcCall Call;
  415. PUCHAR Data;
  416. HRESULT Status;
  417. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  418. (Data = Conn->StartCall(&Call, m_ObjectId,
  419. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
  420. DBGRPC_SMTH_IDebugControl_OutputVaList),
  421. Len + sizeof(ULONG), 0)) == NULL)
  422. {
  423. LEAVE_ENGINE();
  424. Status = E_OUTOFMEMORY;
  425. }
  426. else
  427. {
  428. PUCHAR InData = Data;
  429. *(ULONG*)InData = Mask;
  430. InData += sizeof(ULONG);
  431. memcpy(InData, g_OutBuffer, Len);
  432. LEAVE_ENGINE();
  433. Status = Conn->SendReceive(&Call, &Data);
  434. Conn->FreeData(Data);
  435. }
  436. return Status;
  437. }
  438. STDMETHODIMPV
  439. ProxyIDebugControl::ControlledOutput(
  440. THIS_
  441. IN ULONG OutputControl,
  442. IN ULONG Mask,
  443. IN PCSTR Format,
  444. ...
  445. )
  446. {
  447. va_list Args;
  448. HRESULT Status;
  449. if (::GetCurrentThreadId() != m_OwningThread)
  450. {
  451. return E_INVALIDARG;
  452. }
  453. va_start(Args, Format);
  454. Status = ControlledOutputVaList(OutputControl, Mask, Format, Args);
  455. va_end(Args);
  456. return Status;
  457. }
  458. STDMETHODIMP
  459. ProxyIDebugControl::ControlledOutputVaList(
  460. THIS_
  461. IN ULONG OutputControl,
  462. IN ULONG Mask,
  463. IN PCSTR Format,
  464. IN va_list Args
  465. )
  466. {
  467. int Len;
  468. // Need the engine lock for the global buffers.
  469. ENTER_ENGINE();
  470. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  471. {
  472. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  473. g_FormatBuffer, Args);
  474. }
  475. else
  476. {
  477. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  478. }
  479. if (Len <= 0)
  480. {
  481. LEAVE_ENGINE();
  482. return E_INVALIDARG;
  483. }
  484. else
  485. {
  486. Len++;
  487. }
  488. DbgRpcConnection* Conn;
  489. DbgRpcCall Call;
  490. PUCHAR Data;
  491. HRESULT Status;
  492. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  493. (Data = Conn->StartCall(&Call, m_ObjectId,
  494. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
  495. DBGRPC_SMTH_IDebugControl_ControlledOutputVaList),
  496. Len + 2 * sizeof(ULONG), 0)) == NULL)
  497. {
  498. LEAVE_ENGINE();
  499. Status = E_OUTOFMEMORY;
  500. }
  501. else
  502. {
  503. PUCHAR InData = Data;
  504. *(ULONG*)InData = OutputControl;
  505. InData += sizeof(ULONG);
  506. *(ULONG*)InData = Mask;
  507. InData += sizeof(ULONG);
  508. memcpy(InData, g_OutBuffer, Len);
  509. LEAVE_ENGINE();
  510. Status = Conn->SendReceive(&Call, &Data);
  511. Conn->FreeData(Data);
  512. }
  513. return Status;
  514. }
  515. STDMETHODIMPV
  516. ProxyIDebugControl::OutputPrompt(
  517. IN ULONG OutputControl,
  518. IN OPTIONAL PCSTR Format,
  519. ...
  520. )
  521. {
  522. va_list Args;
  523. HRESULT Status;
  524. if (::GetCurrentThreadId() != m_OwningThread)
  525. {
  526. return E_INVALIDARG;
  527. }
  528. va_start(Args, Format);
  529. Status = OutputPromptVaList(OutputControl, Format, Args);
  530. va_end(Args);
  531. return Status;
  532. }
  533. STDMETHODIMP
  534. ProxyIDebugControl::OutputPromptVaList(
  535. THIS_
  536. IN ULONG OutputControl,
  537. IN OPTIONAL PCSTR Format,
  538. IN va_list Args
  539. )
  540. {
  541. int Len;
  542. if (Format != NULL)
  543. {
  544. // Need the engine lock for the global buffers.
  545. ENTER_ENGINE();
  546. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  547. {
  548. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  549. g_FormatBuffer, Args);
  550. }
  551. else
  552. {
  553. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  554. }
  555. if (Len <= 0)
  556. {
  557. LEAVE_ENGINE();
  558. return E_INVALIDARG;
  559. }
  560. else
  561. {
  562. Len++;
  563. }
  564. }
  565. else
  566. {
  567. Len = 0;
  568. }
  569. DbgRpcConnection* Conn;
  570. DbgRpcCall Call;
  571. PUCHAR Data;
  572. HRESULT Status;
  573. // Presence/absence of text will be detected in the stub
  574. // by checking the input size on the call.
  575. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  576. (Data = Conn->StartCall(&Call, m_ObjectId,
  577. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl,
  578. DBGRPC_SMTH_IDebugControl_OutputPromptVaList),
  579. Len + sizeof(ULONG), 0)) == NULL)
  580. {
  581. if (Format != NULL)
  582. {
  583. LEAVE_ENGINE();
  584. }
  585. Status = E_OUTOFMEMORY;
  586. }
  587. else
  588. {
  589. PUCHAR InData = Data;
  590. *(ULONG*)InData = OutputControl;
  591. InData += sizeof(ULONG);
  592. memcpy(InData, g_OutBuffer, Len);
  593. if (Format != NULL)
  594. {
  595. LEAVE_ENGINE();
  596. }
  597. Status = Conn->SendReceive(&Call, &Data);
  598. Conn->FreeData(Data);
  599. }
  600. return Status;
  601. }
  602. STDMETHODIMPV
  603. ProxyIDebugControl2::Output(
  604. IN ULONG Mask,
  605. IN PCSTR Format,
  606. ...
  607. )
  608. {
  609. va_list Args;
  610. HRESULT Status;
  611. if (::GetCurrentThreadId() != m_OwningThread)
  612. {
  613. return E_INVALIDARG;
  614. }
  615. va_start(Args, Format);
  616. Status = OutputVaList(Mask, Format, Args);
  617. va_end(Args);
  618. return Status;
  619. }
  620. STDMETHODIMP
  621. ProxyIDebugControl2::OutputVaList(
  622. THIS_
  623. IN ULONG Mask,
  624. IN PCSTR Format,
  625. IN va_list Args
  626. )
  627. {
  628. int Len;
  629. // Need the engine lock for the global buffers.
  630. ENTER_ENGINE();
  631. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  632. {
  633. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  634. g_FormatBuffer, Args);
  635. }
  636. else
  637. {
  638. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  639. }
  640. if (Len <= 0)
  641. {
  642. LEAVE_ENGINE();
  643. return E_INVALIDARG;
  644. }
  645. else
  646. {
  647. Len++;
  648. }
  649. DbgRpcConnection* Conn;
  650. DbgRpcCall Call;
  651. PUCHAR Data;
  652. HRESULT Status;
  653. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  654. (Data = Conn->StartCall(&Call, m_ObjectId,
  655. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
  656. DBGRPC_SMTH_IDebugControl2_OutputVaList),
  657. Len + sizeof(ULONG), 0)) == NULL)
  658. {
  659. LEAVE_ENGINE();
  660. Status = E_OUTOFMEMORY;
  661. }
  662. else
  663. {
  664. PUCHAR InData = Data;
  665. *(ULONG*)InData = Mask;
  666. InData += sizeof(ULONG);
  667. memcpy(InData, g_OutBuffer, Len);
  668. LEAVE_ENGINE();
  669. Status = Conn->SendReceive(&Call, &Data);
  670. Conn->FreeData(Data);
  671. }
  672. return Status;
  673. }
  674. STDMETHODIMPV
  675. ProxyIDebugControl2::ControlledOutput(
  676. THIS_
  677. IN ULONG OutputControl,
  678. IN ULONG Mask,
  679. IN PCSTR Format,
  680. ...
  681. )
  682. {
  683. va_list Args;
  684. HRESULT Status;
  685. if (::GetCurrentThreadId() != m_OwningThread)
  686. {
  687. return E_INVALIDARG;
  688. }
  689. va_start(Args, Format);
  690. Status = ControlledOutputVaList(OutputControl, Mask, Format, Args);
  691. va_end(Args);
  692. return Status;
  693. }
  694. STDMETHODIMP
  695. ProxyIDebugControl2::ControlledOutputVaList(
  696. THIS_
  697. IN ULONG OutputControl,
  698. IN ULONG Mask,
  699. IN PCSTR Format,
  700. IN va_list Args
  701. )
  702. {
  703. int Len;
  704. // Need the engine lock for the global buffers.
  705. ENTER_ENGINE();
  706. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  707. {
  708. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  709. g_FormatBuffer, Args);
  710. }
  711. else
  712. {
  713. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  714. }
  715. if (Len <= 0)
  716. {
  717. LEAVE_ENGINE();
  718. return E_INVALIDARG;
  719. }
  720. else
  721. {
  722. Len++;
  723. }
  724. DbgRpcConnection* Conn;
  725. DbgRpcCall Call;
  726. PUCHAR Data;
  727. HRESULT Status;
  728. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  729. (Data = Conn->StartCall(&Call, m_ObjectId,
  730. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
  731. DBGRPC_SMTH_IDebugControl2_ControlledOutputVaList),
  732. Len + 2 * sizeof(ULONG), 0)) == NULL)
  733. {
  734. LEAVE_ENGINE();
  735. Status = E_OUTOFMEMORY;
  736. }
  737. else
  738. {
  739. PUCHAR InData = Data;
  740. *(ULONG*)InData = OutputControl;
  741. InData += sizeof(ULONG);
  742. *(ULONG*)InData = Mask;
  743. InData += sizeof(ULONG);
  744. memcpy(InData, g_OutBuffer, Len);
  745. LEAVE_ENGINE();
  746. Status = Conn->SendReceive(&Call, &Data);
  747. Conn->FreeData(Data);
  748. }
  749. return Status;
  750. }
  751. STDMETHODIMPV
  752. ProxyIDebugControl2::OutputPrompt(
  753. IN ULONG OutputControl,
  754. IN OPTIONAL PCSTR Format,
  755. ...
  756. )
  757. {
  758. va_list Args;
  759. HRESULT Status;
  760. if (::GetCurrentThreadId() != m_OwningThread)
  761. {
  762. return E_INVALIDARG;
  763. }
  764. va_start(Args, Format);
  765. Status = OutputPromptVaList(OutputControl, Format, Args);
  766. va_end(Args);
  767. return Status;
  768. }
  769. STDMETHODIMP
  770. ProxyIDebugControl2::OutputPromptVaList(
  771. THIS_
  772. IN ULONG OutputControl,
  773. IN OPTIONAL PCSTR Format,
  774. IN va_list Args
  775. )
  776. {
  777. int Len;
  778. if (Format != NULL)
  779. {
  780. // Need the engine lock for the global buffers.
  781. ENTER_ENGINE();
  782. if (TranslateFormat(g_FormatBuffer, Format, Args, OUT_BUFFER_SIZE - 1))
  783. {
  784. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1,
  785. g_FormatBuffer, Args);
  786. }
  787. else
  788. {
  789. Len = _vsnprintf(g_OutBuffer, OUT_BUFFER_SIZE - 1, Format, Args);
  790. }
  791. if (Len <= 0)
  792. {
  793. LEAVE_ENGINE();
  794. return E_INVALIDARG;
  795. }
  796. else
  797. {
  798. Len++;
  799. }
  800. }
  801. else
  802. {
  803. Len = 0;
  804. }
  805. DbgRpcConnection* Conn;
  806. DbgRpcCall Call;
  807. PUCHAR Data;
  808. HRESULT Status;
  809. // Presence/absence of text will be detected in the stub
  810. // by checking the input size on the call.
  811. if ((Conn = DbgRpcGetConnection(m_OwningThread)) == NULL ||
  812. (Data = Conn->StartCall(&Call, m_ObjectId,
  813. DBGRPC_STUB_INDEX(DBGRPC_SIF_IDebugControl2,
  814. DBGRPC_SMTH_IDebugControl2_OutputPromptVaList),
  815. Len + sizeof(ULONG), 0)) == NULL)
  816. {
  817. if (Format != NULL)
  818. {
  819. LEAVE_ENGINE();
  820. }
  821. Status = E_OUTOFMEMORY;
  822. }
  823. else
  824. {
  825. PUCHAR InData = Data;
  826. *(ULONG*)InData = OutputControl;
  827. InData += sizeof(ULONG);
  828. memcpy(InData, g_OutBuffer, Len);
  829. if (Format != NULL)
  830. {
  831. LEAVE_ENGINE();
  832. }
  833. Status = Conn->SendReceive(&Call, &Data);
  834. Conn->FreeData(Data);
  835. }
  836. return Status;
  837. }
  838. HRESULT
  839. SFN_IDebugClient_StartProcessServer(
  840. IUnknown* __drpc_If,
  841. DbgRpcConnection* __drpc_Conn,
  842. DbgRpcCall* __drpc_Call,
  843. PUCHAR __drpc_InData,
  844. PUCHAR __drpc_OutData
  845. )
  846. {
  847. ULONG Flags = *(ULONG*)__drpc_InData;
  848. __drpc_InData += sizeof(ULONG);
  849. return ((IDebugClient*)__drpc_If)->
  850. StartProcessServer(Flags, (PSTR)__drpc_InData, NULL);
  851. }
  852. HRESULT
  853. SFN_IDebugClient2_StartProcessServer(
  854. IUnknown* __drpc_If,
  855. DbgRpcConnection* __drpc_Conn,
  856. DbgRpcCall* __drpc_Call,
  857. PUCHAR __drpc_InData,
  858. PUCHAR __drpc_OutData
  859. )
  860. {
  861. ULONG Flags = *(ULONG*)__drpc_InData;
  862. __drpc_InData += sizeof(ULONG);
  863. return ((IDebugClient2*)__drpc_If)->
  864. StartProcessServer(Flags, (PSTR)__drpc_InData, NULL);
  865. }
  866. HRESULT
  867. SFN_IDebugControl_OutputVaList(
  868. IUnknown* __drpc_If,
  869. DbgRpcConnection* __drpc_Conn,
  870. DbgRpcCall* __drpc_Call,
  871. PUCHAR __drpc_InData,
  872. PUCHAR __drpc_OutData
  873. )
  874. {
  875. ULONG Mask = *(ULONG*)__drpc_InData;
  876. __drpc_InData += sizeof(ULONG);
  877. return ((IDebugControl*)__drpc_If)->
  878. Output(Mask, "%s", (PSTR)__drpc_InData);
  879. }
  880. HRESULT
  881. SFN_IDebugControl_ControlledOutputVaList(
  882. IUnknown* __drpc_If,
  883. DbgRpcConnection* __drpc_Conn,
  884. DbgRpcCall* __drpc_Call,
  885. PUCHAR __drpc_InData,
  886. PUCHAR __drpc_OutData
  887. )
  888. {
  889. ULONG OutputControl = *(ULONG*)__drpc_InData;
  890. __drpc_InData += sizeof(ULONG);
  891. ULONG Mask = *(ULONG*)__drpc_InData;
  892. __drpc_InData += sizeof(ULONG);
  893. return ((IDebugControl*)__drpc_If)->
  894. ControlledOutput(OutputControl, Mask, "%s", (PSTR)__drpc_InData);
  895. }
  896. HRESULT
  897. SFN_IDebugControl_OutputPromptVaList(
  898. IUnknown* __drpc_If,
  899. DbgRpcConnection* __drpc_Conn,
  900. DbgRpcCall* __drpc_Call,
  901. PUCHAR __drpc_InData,
  902. PUCHAR __drpc_OutData
  903. )
  904. {
  905. ULONG OutputControl = *(ULONG*)__drpc_InData;
  906. __drpc_InData += sizeof(ULONG);
  907. if (__drpc_Call->InSize > sizeof(ULONG))
  908. {
  909. return ((IDebugControl*)__drpc_If)->
  910. OutputPrompt(OutputControl, "%s", (PSTR)__drpc_InData);
  911. }
  912. else
  913. {
  914. return ((IDebugControl*)__drpc_If)->OutputPrompt(OutputControl, NULL);
  915. }
  916. }
  917. HRESULT
  918. SFN_IDebugControl2_OutputVaList(
  919. IUnknown* __drpc_If,
  920. DbgRpcConnection* __drpc_Conn,
  921. DbgRpcCall* __drpc_Call,
  922. PUCHAR __drpc_InData,
  923. PUCHAR __drpc_OutData
  924. )
  925. {
  926. ULONG Mask = *(ULONG*)__drpc_InData;
  927. __drpc_InData += sizeof(ULONG);
  928. return ((IDebugControl2*)__drpc_If)->
  929. Output(Mask, "%s", (PSTR)__drpc_InData);
  930. }
  931. HRESULT
  932. SFN_IDebugControl2_ControlledOutputVaList(
  933. IUnknown* __drpc_If,
  934. DbgRpcConnection* __drpc_Conn,
  935. DbgRpcCall* __drpc_Call,
  936. PUCHAR __drpc_InData,
  937. PUCHAR __drpc_OutData
  938. )
  939. {
  940. ULONG OutputControl = *(ULONG*)__drpc_InData;
  941. __drpc_InData += sizeof(ULONG);
  942. ULONG Mask = *(ULONG*)__drpc_InData;
  943. __drpc_InData += sizeof(ULONG);
  944. return ((IDebugControl2*)__drpc_If)->
  945. ControlledOutput(OutputControl, Mask, "%s", (PSTR)__drpc_InData);
  946. }
  947. HRESULT
  948. SFN_IDebugControl2_OutputPromptVaList(
  949. IUnknown* __drpc_If,
  950. DbgRpcConnection* __drpc_Conn,
  951. DbgRpcCall* __drpc_Call,
  952. PUCHAR __drpc_InData,
  953. PUCHAR __drpc_OutData
  954. )
  955. {
  956. ULONG OutputControl = *(ULONG*)__drpc_InData;
  957. __drpc_InData += sizeof(ULONG);
  958. if (__drpc_Call->InSize > sizeof(ULONG))
  959. {
  960. return ((IDebugControl2*)__drpc_If)->
  961. OutputPrompt(OutputControl, "%s", (PSTR)__drpc_InData);
  962. }
  963. else
  964. {
  965. return ((IDebugControl2*)__drpc_If)->OutputPrompt(OutputControl, NULL);
  966. }
  967. }