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.

2569 lines
66 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // DbgRpc transports.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "pch.hpp"
  9. #include <ws2tcpip.h>
  10. // Crypto hashing requires a crypto provider to be available
  11. // (this may not always be the case on Win9x or NT4) so just go with Base64.
  12. #define HashPassword(Password, Buffer) Base64HashPassword(Password, Buffer)
  13. #ifdef _WIN32_WCE
  14. #define SYNC_SOCKETS
  15. #endif
  16. #ifndef NT_NATIVE
  17. BOOL
  18. CryptoHashPassword(PCSTR Password, PUCHAR Buffer)
  19. {
  20. BOOL Status = FALSE;
  21. HCRYPTPROV Prov;
  22. HCRYPTHASH Hash;
  23. ULONG HashSize;
  24. if (!CryptAcquireContext(&Prov, NULL, MS_DEF_PROV, PROV_RSA_FULL,
  25. CRYPT_VERIFYCONTEXT))
  26. {
  27. goto EH_Fail;
  28. }
  29. if (!CryptCreateHash(Prov, CALG_MD5, NULL, 0, &Hash))
  30. {
  31. goto EH_Prov;
  32. }
  33. if (!CryptHashData(Hash, (PBYTE)Password, strlen(Password), 0))
  34. {
  35. goto EH_Hash;
  36. }
  37. ZeroMemory(Buffer, MAX_PASSWORD_BUFFER);
  38. HashSize = MAX_PASSWORD_BUFFER;
  39. if (!CryptGetHashParam(Hash, HP_HASHVAL, Buffer, &HashSize, 0))
  40. {
  41. goto EH_Hash;
  42. }
  43. Status = TRUE;
  44. EH_Hash:
  45. CryptDestroyHash(Hash);
  46. EH_Prov:
  47. CryptReleaseContext(Prov, 0);
  48. EH_Fail:
  49. if (!Status)
  50. {
  51. DRPC_ERR(("Unable to hash password, %d\n", GetLastError()));
  52. }
  53. return Status;
  54. }
  55. #endif // #ifndef NT_NATIVE
  56. UCHAR g_Base64Table[64] =
  57. {
  58. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
  59. 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
  60. 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
  61. 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
  62. };
  63. BOOL
  64. Base64HashPassword(PCSTR Password, PUCHAR Buffer)
  65. {
  66. ULONG Len = strlen(Password);
  67. if ((Len * 4 + 2) / 3 > MAX_PASSWORD_BUFFER)
  68. {
  69. DRPC_ERR(("Unable to hash password\n"));
  70. return FALSE;
  71. }
  72. ZeroMemory(Buffer, MAX_PASSWORD_BUFFER);
  73. ULONG Collect;
  74. while (Len >= 3)
  75. {
  76. //
  77. // Collect three characters and turn them
  78. // into four output bytes.
  79. //
  80. Collect = *Password++;
  81. Collect = (Collect << 8) | *Password++;
  82. Collect = (Collect << 8) | *Password++;
  83. *Buffer++ = g_Base64Table[(Collect >> 18) & 0x3f];
  84. *Buffer++ = g_Base64Table[(Collect >> 12) & 0x3f];
  85. *Buffer++ = g_Base64Table[(Collect >> 6) & 0x3f];
  86. *Buffer++ = g_Base64Table[(Collect >> 0) & 0x3f];
  87. Len -= 3;
  88. }
  89. switch(Len)
  90. {
  91. case 2:
  92. Collect = *Password++;
  93. Collect = (Collect << 8) | *Password++;
  94. Collect <<= 8;
  95. *Buffer++ = g_Base64Table[(Collect >> 18) & 0x3f];
  96. *Buffer++ = g_Base64Table[(Collect >> 12) & 0x3f];
  97. *Buffer++ = g_Base64Table[(Collect >> 6) & 0x3f];
  98. *Buffer++ = '=';
  99. break;
  100. case 1:
  101. Collect = *Password++;
  102. Collect <<= 16;
  103. *Buffer++ = g_Base64Table[(Collect >> 18) & 0x3f];
  104. *Buffer++ = g_Base64Table[(Collect >> 12) & 0x3f];
  105. *Buffer++ = '=';
  106. *Buffer++ = '=';
  107. break;
  108. }
  109. return TRUE;
  110. }
  111. //----------------------------------------------------------------------------
  112. //
  113. // DbgRpcTransport.
  114. //
  115. //----------------------------------------------------------------------------
  116. PCSTR g_DbgRpcTransportNames[TRANS_COUNT] =
  117. {
  118. "tcp", "npipe", "ssl", "spipe", "1394", "com",
  119. };
  120. DbgRpcTransport::~DbgRpcTransport(void)
  121. {
  122. // Nothing to do.
  123. }
  124. ULONG
  125. DbgRpcTransport::GetNumberParameters(void)
  126. {
  127. return 3;
  128. }
  129. void
  130. DbgRpcTransport::GetParameter(ULONG Index,
  131. PSTR Name, ULONG NameSize,
  132. PSTR Value, ULONG ValueSize)
  133. {
  134. switch(Index)
  135. {
  136. case 0:
  137. if (m_ServerName[0])
  138. {
  139. CopyString(Name, "Server", NameSize);
  140. CopyString(Value, m_ServerName, ValueSize);
  141. }
  142. break;
  143. case 1:
  144. if (m_PasswordGiven)
  145. {
  146. CopyString(Name, "Password", NameSize);
  147. CopyString(Value, "*", ValueSize);
  148. }
  149. break;
  150. case 2:
  151. if (m_Hidden)
  152. {
  153. CopyString(Name, "Hidden", NameSize);
  154. }
  155. break;
  156. }
  157. }
  158. void
  159. DbgRpcTransport::ResetParameters(void)
  160. {
  161. m_PasswordGiven = FALSE;
  162. m_Hidden = FALSE;
  163. m_ServerName[0] = 0;
  164. m_ClientConnect = FALSE;
  165. m_ClientConnectAttempts = 0;
  166. }
  167. BOOL
  168. DbgRpcTransport::SetParameter(PCSTR Name, PCSTR Value)
  169. {
  170. if (!_stricmp(Name, "Password"))
  171. {
  172. if (Value == NULL)
  173. {
  174. DbgRpcError("Remoting password was not specified correctly\n");
  175. return FALSE;
  176. }
  177. if (!HashPassword(Value, m_HashedPassword))
  178. {
  179. return FALSE;
  180. }
  181. m_PasswordGiven = TRUE;
  182. }
  183. else if (!_stricmp(Name, "Hidden"))
  184. {
  185. m_Hidden = TRUE;
  186. }
  187. else
  188. {
  189. return FALSE;
  190. }
  191. return TRUE;
  192. }
  193. void
  194. DbgRpcTransport::CloneData(DbgRpcTransport* Trans)
  195. {
  196. strcpy(Trans->m_ServerName, m_ServerName);
  197. Trans->m_PasswordGiven = m_PasswordGiven;
  198. Trans->m_Hidden = m_Hidden;
  199. memcpy(Trans->m_HashedPassword, m_HashedPassword,
  200. sizeof(m_HashedPassword));
  201. Trans->m_ClientConnect = m_ClientConnect;
  202. Trans->m_ClientConnectAttempts = m_ClientConnectAttempts;
  203. }
  204. //----------------------------------------------------------------------------
  205. //
  206. // DbgRpcTcpTransport.
  207. //
  208. //----------------------------------------------------------------------------
  209. #ifndef NT_NATIVE
  210. DbgRpcTcpTransport::DbgRpcTcpTransport(void)
  211. {
  212. m_Name = g_DbgRpcTransportNames[TRANS_TCP];
  213. m_Sock = INVALID_SOCKET;
  214. ZeroMemory(&m_OlRead, sizeof(m_OlRead));
  215. ZeroMemory(&m_OlWrite, sizeof(m_OlWrite));
  216. }
  217. DbgRpcTcpTransport::~DbgRpcTcpTransport(void)
  218. {
  219. if (m_Sock != INVALID_SOCKET)
  220. {
  221. shutdown(m_Sock, 2);
  222. closesocket(m_Sock);
  223. m_Sock = INVALID_SOCKET;
  224. }
  225. #ifndef SYNC_SOCKETS
  226. if (m_OlRead.hEvent != NULL)
  227. {
  228. WSACloseEvent(m_OlRead.hEvent);
  229. ZeroMemory(&m_OlRead, sizeof(m_OlRead));
  230. }
  231. if (m_OlWrite.hEvent != NULL)
  232. {
  233. WSACloseEvent(m_OlWrite.hEvent);
  234. ZeroMemory(&m_OlWrite, sizeof(m_OlWrite));
  235. }
  236. #endif
  237. }
  238. ULONG
  239. DbgRpcTcpTransport::GetNumberParameters(void)
  240. {
  241. return 4 + DbgRpcTransport::GetNumberParameters();
  242. }
  243. void
  244. DbgRpcTcpTransport::GetParameter(ULONG Index,
  245. PSTR Name, ULONG NameSize,
  246. PSTR Value, ULONG ValueSize)
  247. {
  248. switch(Index)
  249. {
  250. case 0:
  251. if (SS_PORT(&m_Addr))
  252. {
  253. CopyString(Name, "Port", NameSize);
  254. PrintString(Value, ValueSize, "%d", ntohs(SS_PORT(&m_Addr)));
  255. if (m_TopPort)
  256. {
  257. ULONG Used = strlen(Value);
  258. PrintString(Value + Used, ValueSize - Used,
  259. ":%d", m_TopPort);
  260. }
  261. }
  262. break;
  263. case 1:
  264. if (m_AddrLength == sizeof(SOCKADDR_IN6))
  265. {
  266. CopyString(Name, "IpVersion", NameSize);
  267. Value[0] = '6';
  268. Value[1] = 0;
  269. }
  270. break;
  271. case 2:
  272. if (m_ClientConnectName[0])
  273. {
  274. CopyString(Name, "CliCon", NameSize);
  275. CopyString(Value, m_ClientConnectName, ValueSize);
  276. }
  277. break;
  278. case 3:
  279. if (m_ClientConnectAttempts)
  280. {
  281. CopyString(Name, "CliConLim", NameSize);
  282. PrintString(Value, ValueSize, "%d", m_ClientConnectAttempts);
  283. }
  284. break;
  285. default:
  286. DbgRpcTransport::GetParameter(Index - 4,
  287. Name, NameSize, Value, ValueSize);
  288. break;
  289. }
  290. }
  291. void
  292. DbgRpcTcpTransport::ResetParameters(void)
  293. {
  294. ZeroMemory(&m_Addr, sizeof(m_Addr));
  295. m_Addr.ss_family = AF_INET;
  296. m_AddrLength = sizeof(SOCKADDR_IN);
  297. m_TopPort = 0;
  298. m_ClientConnectName[0] = 0;
  299. // ClientConnectAddr parameters are taken from m_Addr
  300. // when clicon is used.
  301. DbgRpcTransport::ResetParameters();
  302. }
  303. BOOL
  304. DbgRpcTcpTransport::SetParameter(PCSTR Name, PCSTR Value)
  305. {
  306. if (!_stricmp(Name, "ipversion"))
  307. {
  308. ULONG Version;
  309. if (Value == NULL || sscanf(Value, "%d", &Version) != 1)
  310. {
  311. DbgRpcError("TCP parameters: "
  312. "the IP version was not specified correctly\n");
  313. return FALSE;
  314. }
  315. switch(Version)
  316. {
  317. case 4:
  318. m_Addr.ss_family = AF_INET;
  319. m_AddrLength = sizeof(SOCKADDR_IN);
  320. break;
  321. case 6:
  322. m_Addr.ss_family = AF_INET6;
  323. m_AddrLength = sizeof(SOCKADDR_IN6);
  324. break;
  325. default:
  326. DbgRpcError("TCP parameters: IP version must "
  327. "be 4 or 6\n");
  328. return FALSE;
  329. }
  330. }
  331. else if (!_stricmp(Name, "port"))
  332. {
  333. if (Value == NULL)
  334. {
  335. DbgRpcError("TCP parameters: "
  336. "the port number was not specified correctly\n");
  337. return FALSE;
  338. }
  339. ULONG Port;
  340. // Allow a range of ports to be specified if so desired.
  341. switch(sscanf(Value, "%i:%i", &Port, &m_TopPort))
  342. {
  343. case 0:
  344. Port = 0;
  345. // Fall through.
  346. case 1:
  347. m_TopPort = 0;
  348. break;
  349. }
  350. if (Port > 0xffff || m_TopPort > 0xffff)
  351. {
  352. DbgRpcError("TCP parameters: port numbers are "
  353. "limited to 16 bits\n");
  354. return FALSE;
  355. }
  356. SS_PORT(&m_Addr) = htons((USHORT)Port);
  357. }
  358. else if (!_stricmp(Name, "server"))
  359. {
  360. if (Value == NULL)
  361. {
  362. DbgRpcError("TCP parameters: "
  363. "the server name was not specified correctly\n");
  364. return FALSE;
  365. }
  366. if (InitIpAddress(Value, 0, &m_Addr, &m_AddrLength) != S_OK)
  367. {
  368. DbgRpcError("TCP parameters: "
  369. "the specified server (%s) does not exist\n",
  370. Value);
  371. return FALSE;
  372. }
  373. if (!CopyString(m_ServerName, Value, DIMA(m_ServerName)))
  374. {
  375. return FALSE;
  376. }
  377. }
  378. else if (!_stricmp(Name, "clicon"))
  379. {
  380. if (Value == NULL)
  381. {
  382. DbgRpcError("TCP parameters: "
  383. "the client name was not specified correctly\n");
  384. return FALSE;
  385. }
  386. m_ClientConnectAddr = m_Addr;
  387. if (InitIpAddress(Value, 0, &m_ClientConnectAddr,
  388. &m_ClientConnectAddrLength) != S_OK)
  389. {
  390. DbgRpcError("TCP parameters: "
  391. "the specified server (%s) does not exist\n",
  392. Value);
  393. return FALSE;
  394. }
  395. if (!CopyString(m_ClientConnectName, Value,
  396. DIMA(m_ClientConnectName)))
  397. {
  398. return FALSE;
  399. }
  400. m_ClientConnect = TRUE;
  401. // A client-connect server will only do one
  402. // connection outward and cannot receive connections
  403. // so there's no point in advertising it.
  404. m_Hidden = TRUE;
  405. // Normally the debugger creates two separate clients.
  406. m_ClientConnectAttempts = 2;
  407. }
  408. else if (!_stricmp(Name, "cliconlim"))
  409. {
  410. if (Value == NULL ||
  411. sscanf(Value, "%i", &m_ClientConnectAttempts) != 1)
  412. {
  413. DbgRpcError("TCP parameters: the client connect limit "
  414. "was not specified correctly\n");
  415. return FALSE;
  416. }
  417. }
  418. else
  419. {
  420. if (!DbgRpcTransport::SetParameter(Name, Value))
  421. {
  422. DbgRpcError("TCP parameters: %s is not a valid parameter\n", Name);
  423. return FALSE;
  424. }
  425. }
  426. return TRUE;
  427. }
  428. DbgRpcTransport*
  429. DbgRpcTcpTransport::Clone(void)
  430. {
  431. DbgRpcTcpTransport* Trans = new DbgRpcTcpTransport;
  432. if (Trans != NULL)
  433. {
  434. DbgRpcTransport::CloneData(Trans);
  435. Trans->m_Addr = m_Addr;
  436. Trans->m_AddrLength = m_AddrLength;
  437. Trans->m_TopPort = m_TopPort;
  438. memcpy(Trans->m_ClientConnectName, m_ClientConnectName,
  439. sizeof(Trans->m_ClientConnectName));
  440. Trans->m_ClientConnectAddr = m_ClientConnectAddr;
  441. Trans->m_ClientConnectAddrLength = m_ClientConnectAddrLength;
  442. }
  443. return Trans;
  444. }
  445. HRESULT
  446. DbgRpcTcpTransport::CreateServer(void)
  447. {
  448. if (m_ClientConnectName[0])
  449. {
  450. // If the server is going to initiate connection
  451. // to the client there's nothing to do here.
  452. return S_OK;
  453. }
  454. else
  455. {
  456. return CreateServerSocket();
  457. }
  458. }
  459. HRESULT
  460. DbgRpcTcpTransport::AcceptConnection(DbgRpcTransport** ClientTrans,
  461. PSTR Identity, ULONG IdentitySize)
  462. {
  463. HRESULT Status;
  464. DbgRpcTcpTransport* Trans;
  465. if (!(Trans = new DbgRpcTcpTransport))
  466. {
  467. return E_OUTOFMEMORY;
  468. }
  469. DbgRpcTransport::CloneData(Trans);
  470. if (m_ClientConnectName[0])
  471. {
  472. //
  473. // The server needs to initiate connection
  474. // to the client instead of accepting.
  475. //
  476. Trans->m_Addr = m_ClientConnectAddr;
  477. Trans->m_AddrLength = m_ClientConnectAddrLength;
  478. Status = Trans->ConnectSocket();
  479. }
  480. else
  481. {
  482. Status = Trans->AcceptSocketConnection(m_Sock);
  483. }
  484. if (Status != S_OK)
  485. {
  486. delete Trans;
  487. return Status;
  488. }
  489. GetAddressIdentity(&Trans->m_Addr,
  490. Trans->m_AddrLength,
  491. Identity,
  492. IdentitySize);
  493. *ClientTrans = Trans;
  494. return S_OK;
  495. }
  496. HRESULT
  497. DbgRpcTcpTransport::ConnectServer(void)
  498. {
  499. HRESULT Status;
  500. if (m_ClientConnectName[0])
  501. {
  502. //
  503. // We need to keep the server socket open
  504. // to allow multiple connects. There's no
  505. // good way to keep it associated with other
  506. // data on the client, though, as from the
  507. // client's point of view it's just doing multiple
  508. // separate connections. For now just keep
  509. // a global around.
  510. //
  511. static SOCKET s_ServSock = INVALID_SOCKET;
  512. EnterCriticalSection(&g_DbgRpcLock);
  513. if (s_ServSock == INVALID_SOCKET)
  514. {
  515. if ((Status = CreateServerSocket()) != S_OK)
  516. {
  517. LeaveCriticalSection(&g_DbgRpcLock);
  518. return Status;
  519. }
  520. s_ServSock = m_Sock;
  521. }
  522. LeaveCriticalSection(&g_DbgRpcLock);
  523. return AcceptSocketConnection(s_ServSock);
  524. }
  525. else
  526. {
  527. return ConnectSocket();
  528. }
  529. }
  530. ULONG
  531. DbgRpcTcpTransport::Read(ULONG Seq, PVOID Buffer, ULONG Len)
  532. {
  533. ULONG Done;
  534. Done = 0;
  535. while (Len > 0)
  536. {
  537. #ifndef SYNC_SOCKETS
  538. if (!WSAResetEvent(m_OlRead.hEvent))
  539. {
  540. break;
  541. }
  542. WSABUF SockBuf;
  543. ULONG SockDone;
  544. ULONG SockFlags;
  545. SockBuf.buf = (PSTR)Buffer;
  546. SockBuf.len = Len;
  547. SockFlags = 0;
  548. if (WSARecv(m_Sock, &SockBuf, 1, &SockDone, &SockFlags,
  549. &m_OlRead, NULL) == SOCKET_ERROR)
  550. {
  551. if (WSAGetLastError() == WSA_IO_PENDING)
  552. {
  553. if (!WSAGetOverlappedResult(m_Sock, &m_OlRead, &SockDone,
  554. TRUE, &SockFlags))
  555. {
  556. break;
  557. }
  558. }
  559. else
  560. {
  561. break;
  562. }
  563. }
  564. #else
  565. int SockDone;
  566. SockDone = recv(m_Sock, (PSTR)Buffer, Len, 0);
  567. #endif
  568. if (SockDone == 0)
  569. {
  570. // Socket connection was broken.
  571. break;
  572. }
  573. Buffer = (PVOID)((PUCHAR)Buffer + SockDone);
  574. Len -= SockDone;
  575. Done += SockDone;
  576. }
  577. return Done;
  578. }
  579. ULONG
  580. DbgRpcTcpTransport::Write(ULONG Seq, PVOID Buffer, ULONG Len)
  581. {
  582. ULONG Done;
  583. Done = 0;
  584. while (Len > 0)
  585. {
  586. #ifndef SYNC_SOCKETS
  587. if (!WSAResetEvent(m_OlWrite.hEvent))
  588. {
  589. break;
  590. }
  591. WSABUF SockBuf;
  592. ULONG SockDone;
  593. ULONG SockFlags;
  594. SockBuf.buf = (PSTR)Buffer;
  595. SockBuf.len = Len;
  596. SockFlags = 0;
  597. if (WSASend(m_Sock, &SockBuf, 1, &SockDone, SockFlags,
  598. &m_OlWrite, NULL) == SOCKET_ERROR)
  599. {
  600. if (WSAGetLastError() == WSA_IO_PENDING)
  601. {
  602. if (!WSAGetOverlappedResult(m_Sock, &m_OlWrite, &SockDone,
  603. TRUE, &SockFlags))
  604. {
  605. break;
  606. }
  607. }
  608. else
  609. {
  610. break;
  611. }
  612. }
  613. #else
  614. int SockDone;
  615. SockDone = send(m_Sock, (PSTR)Buffer, Len, 0);
  616. if (SockDone <= 0)
  617. {
  618. break;
  619. }
  620. #endif
  621. Buffer = (PVOID)((PUCHAR)Buffer + SockDone);
  622. Len -= SockDone;
  623. Done += SockDone;
  624. }
  625. return Done;
  626. }
  627. HRESULT
  628. DbgRpcTcpTransport::InitOl(void)
  629. {
  630. #ifndef SYNC_SOCKETS
  631. m_OlRead.hEvent = WSACreateEvent();
  632. if (m_OlRead.hEvent == NULL)
  633. {
  634. return HRESULT_FROM_WIN32(WSAGetLastError());
  635. }
  636. m_OlWrite.hEvent = WSACreateEvent();
  637. if (m_OlWrite.hEvent == NULL)
  638. {
  639. WSACloseEvent(m_OlRead.hEvent);
  640. m_OlRead.hEvent = NULL;
  641. return HRESULT_FROM_WIN32(WSAGetLastError());
  642. }
  643. #endif
  644. return S_OK;
  645. }
  646. void
  647. DbgRpcTcpTransport::GetAddressIdentity(PSOCKADDR_STORAGE Addr,
  648. int AddrLength,
  649. PSTR Identity,
  650. ULONG IdentitySize)
  651. {
  652. if (Addr->ss_family == AF_INET ||
  653. Addr->ss_family == AF_INET6)
  654. {
  655. CopyString(Identity, "tcp ", IdentitySize);
  656. struct hostent* Host =
  657. #if 0
  658. // This lookup is really slow and doesn't seem to work
  659. // very often so just don't bother.
  660. gethostbyaddr((PCSTR)Addr, AddrLength, Addr->ss_family);
  661. #else
  662. NULL;
  663. #endif
  664. if (Host != NULL)
  665. {
  666. CatString(Identity, Host->h_name, IdentitySize);
  667. CatString(Identity, " ", IdentitySize);
  668. }
  669. int IdLen = strlen(Identity);
  670. char ServerAndPort[INET6_ADDRSTRLEN + 19];
  671. DWORD SapLen = sizeof(ServerAndPort);
  672. if (WSAAddressToStringA((struct sockaddr *)Addr, AddrLength, NULL,
  673. ServerAndPort, &SapLen) == SOCKET_ERROR)
  674. {
  675. PrintString(Identity + IdLen, IdentitySize - IdLen,
  676. "<Addr Failure>, port %d",
  677. ntohs(SS_PORT(&m_Addr)));
  678. }
  679. else
  680. {
  681. CatString(Identity, ServerAndPort, IdentitySize);
  682. }
  683. }
  684. else
  685. {
  686. PrintString(Identity, IdentitySize, "tcp family %d, bytes %d",
  687. Addr->ss_family, AddrLength);
  688. }
  689. }
  690. HRESULT
  691. DbgRpcTcpTransport::CreateServerSocket(void)
  692. {
  693. HRESULT Status;
  694. //
  695. // We must create our sockets overlapped so that
  696. // we can control waiting for I/O completion.
  697. // If we leave the waiting to Winsock by using
  698. // synchronous sockets it uses an alertable wait
  699. // which can cause our event notification APCs to
  700. // be received in the middle of reading packets.
  701. //
  702. m_Sock = WSASocket(m_Addr.ss_family, SOCK_STREAM, 0, NULL, 0,
  703. WSA_FLAG_OVERLAPPED);
  704. if (m_Sock == INVALID_SOCKET)
  705. {
  706. Status = WIN32_STATUS(WSAGetLastError());
  707. goto EH_Fail;
  708. }
  709. for (;;)
  710. {
  711. if (bind(m_Sock, (struct sockaddr *)&m_Addr,
  712. m_AddrLength) != SOCKET_ERROR)
  713. {
  714. break;
  715. }
  716. ULONG Port = ntohs(SS_PORT(&m_Addr));
  717. Status = WIN32_STATUS(WSAGetLastError());
  718. if (Status == HRESULT_FROM_WIN32(WSAEADDRINUSE) &&
  719. m_TopPort > Port)
  720. {
  721. // The user has given a range of ports and
  722. // we haven't checked them all yet, so go
  723. // around again.
  724. SS_PORT(&m_Addr) = htons((USHORT)(Port + 1));
  725. }
  726. else
  727. {
  728. goto EH_Sock;
  729. }
  730. }
  731. //
  732. // Retrieve the port actually used in case port
  733. // zero was used to let TCP pick a port.
  734. //
  735. SOCKADDR_STORAGE Name;
  736. int Len;
  737. Len = sizeof(Name);
  738. if (getsockname(m_Sock, (struct sockaddr *)&Name, &Len) != 0)
  739. {
  740. Status = WIN32_STATUS(WSAGetLastError());
  741. goto EH_Sock;
  742. }
  743. // Copy just the port as we do not want
  744. // to update the rest of the address.
  745. SS_PORT(&m_Addr) = SS_PORT(&Name);
  746. // Turn off linger-on-close.
  747. int On;
  748. On = TRUE;
  749. setsockopt(m_Sock, SOL_SOCKET, SO_DONTLINGER,
  750. (char *)&On, sizeof(On));
  751. if (listen(m_Sock, SOMAXCONN) == SOCKET_ERROR)
  752. {
  753. Status = WIN32_STATUS(WSAGetLastError());
  754. goto EH_Sock;
  755. }
  756. return S_OK;
  757. EH_Sock:
  758. closesocket(m_Sock);
  759. m_Sock = INVALID_SOCKET;
  760. EH_Fail:
  761. return Status;
  762. }
  763. HRESULT
  764. DbgRpcTcpTransport::AcceptSocketConnection(SOCKET ServSock)
  765. {
  766. DRPC(("%X: Waiting to accept connection on socket %p\n",
  767. GetCurrentThreadId(), ServSock));
  768. m_AddrLength = sizeof(m_Addr);
  769. m_Sock = accept(ServSock, (struct sockaddr *)&m_Addr, &m_AddrLength);
  770. if (m_Sock == INVALID_SOCKET)
  771. {
  772. DRPC(("%X: Accept failed, %X\n",
  773. GetCurrentThreadId(), WSAGetLastError()));
  774. return HRESULT_FROM_WIN32(WSAGetLastError());
  775. }
  776. HRESULT Status = InitOl();
  777. if (Status != S_OK)
  778. {
  779. DRPC(("%X: InitOl failed, %X\n",
  780. GetCurrentThreadId(), Status));
  781. return Status;
  782. }
  783. int On = TRUE;
  784. setsockopt(m_Sock, IPPROTO_TCP, TCP_NODELAY,
  785. (PSTR)&On, sizeof(On));
  786. DRPC(("%X: Accept connection on socket %p\n",
  787. GetCurrentThreadId(), m_Sock));
  788. return S_OK;
  789. }
  790. HRESULT
  791. DbgRpcTcpTransport::ConnectSocket(void)
  792. {
  793. //
  794. // We must create our sockets overlapped so that
  795. // we can control waiting for I/O completion.
  796. // If we leave the waiting to Winsock by using
  797. // synchronous sockets it uses an alertable wait
  798. // which can cause our event notification APCs to
  799. // be received in the middle of reading packets.
  800. //
  801. m_Sock = WSASocket(m_Addr.ss_family, SOCK_STREAM, 0, NULL, 0,
  802. WSA_FLAG_OVERLAPPED);
  803. if (m_Sock != INVALID_SOCKET)
  804. {
  805. if (connect(m_Sock, (struct sockaddr *)&m_Addr,
  806. m_AddrLength) == SOCKET_ERROR ||
  807. InitOl() != S_OK)
  808. {
  809. closesocket(m_Sock);
  810. m_Sock = INVALID_SOCKET;
  811. }
  812. else
  813. {
  814. int On = TRUE;
  815. setsockopt(m_Sock, IPPROTO_TCP, TCP_NODELAY,
  816. (PSTR)&On, sizeof(On));
  817. DRPC(("%X: Connect on socket %p\n",
  818. GetCurrentThreadId(), m_Sock));
  819. }
  820. }
  821. return m_Sock != INVALID_SOCKET ? S_OK : RPC_E_SERVER_DIED;
  822. }
  823. #endif // #ifndef NT_NATIVE
  824. //----------------------------------------------------------------------------
  825. //
  826. // DbgRpcNamedPipeTransport.
  827. //
  828. //----------------------------------------------------------------------------
  829. #ifndef _WIN32_WCE
  830. DbgRpcNamedPipeTransport::~DbgRpcNamedPipeTransport(void)
  831. {
  832. if (m_Handle != NULL)
  833. {
  834. CloseHandle(m_Handle);
  835. m_Handle = NULL;
  836. }
  837. if (m_ReadOlap.hEvent != NULL)
  838. {
  839. CloseHandle(m_ReadOlap.hEvent);
  840. }
  841. if (m_WriteOlap.hEvent != NULL)
  842. {
  843. CloseHandle(m_WriteOlap.hEvent);
  844. }
  845. }
  846. ULONG
  847. DbgRpcNamedPipeTransport::GetNumberParameters(void)
  848. {
  849. return 1 + DbgRpcTransport::GetNumberParameters();
  850. }
  851. void
  852. DbgRpcNamedPipeTransport::GetParameter(ULONG Index,
  853. PSTR Name, ULONG NameSize,
  854. PSTR Value, ULONG ValueSize)
  855. {
  856. switch(Index)
  857. {
  858. case 0:
  859. if (m_Pipe[0])
  860. {
  861. CopyString(Name, "Pipe", NameSize);
  862. CopyString(Value, m_Pipe, ValueSize);
  863. }
  864. break;
  865. default:
  866. DbgRpcTransport::GetParameter(Index - 1,
  867. Name, NameSize, Value, ValueSize);
  868. break;
  869. }
  870. }
  871. void
  872. DbgRpcNamedPipeTransport::ResetParameters(void)
  873. {
  874. m_Pipe[0] = 0;
  875. m_Handle = NULL;
  876. DbgRpcTransport::ResetParameters();
  877. }
  878. BOOL
  879. DbgRpcNamedPipeTransport::SetParameter(PCSTR Name, PCSTR Value)
  880. {
  881. if (!_stricmp(Name, "server"))
  882. {
  883. if (Value == NULL)
  884. {
  885. DbgRpcError("NPIPE parameters: "
  886. "the server name was not specified correctly\n");
  887. return FALSE;
  888. }
  889. // Skip leading \\ if they were given.
  890. if (Value[0] == '\\' && Value[1] == '\\')
  891. {
  892. Value += 2;
  893. }
  894. if (!CopyString(m_ServerName, Value, DIMA(m_ServerName)))
  895. {
  896. return FALSE;
  897. }
  898. }
  899. else if (!_stricmp(Name, "pipe"))
  900. {
  901. if (Value == NULL)
  902. {
  903. DbgRpcError("NPIPE parameters: "
  904. "the pipe name was not specified correctly\n");
  905. return FALSE;
  906. }
  907. // Use the value as a printf format string so that
  908. // users can create unique names using the process and
  909. // thread IDs in their own format.
  910. PrintString(m_Pipe, DIMA(m_Pipe), Value,
  911. GetCurrentProcessId(), GetCurrentThreadId());
  912. }
  913. else
  914. {
  915. if (!DbgRpcTransport::SetParameter(Name, Value))
  916. {
  917. DbgRpcError("NPIPE parameters: %s is not a valid parameter\n",
  918. Name);
  919. return FALSE;
  920. }
  921. }
  922. return TRUE;
  923. }
  924. DbgRpcTransport*
  925. DbgRpcNamedPipeTransport::Clone(void)
  926. {
  927. DbgRpcNamedPipeTransport* Trans = new DbgRpcNamedPipeTransport;
  928. if (Trans != NULL)
  929. {
  930. DbgRpcTransport::CloneData(Trans);
  931. strcpy(Trans->m_Pipe, m_Pipe);
  932. }
  933. return Trans;
  934. }
  935. HRESULT
  936. DbgRpcNamedPipeTransport::CreateServer(void)
  937. {
  938. HANDLE Pipe;
  939. char PipeName[MAX_PARAM_VALUE + 16];
  940. #ifndef NT_NATIVE
  941. strcpy(PipeName, "\\\\.\\pipe\\");
  942. #else
  943. strcpy(PipeName, "\\Device\\NamedPipe\\");
  944. #endif
  945. strcat(PipeName, m_Pipe);
  946. // Check and see if this pipe already exists.
  947. // This might mess up whoever created the pipe if
  948. // there is one but it's better than creating a
  949. // duplicate pipe and having clients get messed up.
  950. #ifndef NT_NATIVE
  951. Pipe = CreateFile(PipeName, FILE_READ_DATA | FILE_WRITE_DATA,
  952. 0, NULL, OPEN_EXISTING, 0, NULL);
  953. #else
  954. Pipe = NtNativeCreateFileA(PipeName,
  955. FILE_READ_DATA | FILE_WRITE_DATA,
  956. 0, NULL, OPEN_EXISTING, 0, NULL, FALSE);
  957. #endif
  958. if (Pipe != INVALID_HANDLE_VALUE)
  959. {
  960. // Pipe is already in use.
  961. DRPC_ERR(("%X: Pipe %s is already in use\n",
  962. GetCurrentThreadId(), PipeName));
  963. CloseHandle(Pipe);
  964. return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  965. }
  966. return S_OK;
  967. }
  968. HRESULT
  969. DbgRpcNamedPipeTransport::AcceptConnection(DbgRpcTransport** ClientTrans,
  970. PSTR Identity, ULONG IdentitySize)
  971. {
  972. DbgRpcNamedPipeTransport* Trans = new DbgRpcNamedPipeTransport;
  973. if (Trans == NULL)
  974. {
  975. return E_OUTOFMEMORY;
  976. }
  977. DbgRpcTransport::CloneData(Trans);
  978. char PipeName[MAX_PARAM_VALUE + 16];
  979. #ifndef NT_NATIVE
  980. strcpy(PipeName, "\\\\.\\pipe\\");
  981. #else
  982. strcpy(PipeName, "\\Device\\NamedPipe\\");
  983. #endif
  984. strcat(PipeName, m_Pipe);
  985. #ifndef NT_NATIVE
  986. Trans->m_Handle =
  987. CreateNamedPipe(PipeName,
  988. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  989. PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  990. PIPE_UNLIMITED_INSTANCES, 4096, 4096, INFINITE,
  991. &g_AllAccessSecAttr);
  992. #else
  993. Trans->m_Handle =
  994. NtNativeCreateNamedPipeA(PipeName,
  995. PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  996. PIPE_WAIT | PIPE_READMODE_BYTE |
  997. PIPE_TYPE_BYTE,
  998. PIPE_UNLIMITED_INSTANCES, 4096, 4096,
  999. INFINITE,
  1000. &g_AllAccessSecAttr, FALSE);
  1001. #endif
  1002. if (Trans->m_Handle == INVALID_HANDLE_VALUE)
  1003. {
  1004. Trans->m_Handle = NULL;
  1005. delete Trans;
  1006. return WIN32_LAST_STATUS();
  1007. }
  1008. HRESULT Status;
  1009. if ((Status = CreateOverlappedPair(&Trans->m_ReadOlap,
  1010. &Trans->m_WriteOlap)) != S_OK)
  1011. {
  1012. delete Trans;
  1013. return Status;
  1014. }
  1015. DRPC(("%X: Waiting to accept connection on pipe %s\n",
  1016. GetCurrentThreadId(), m_Pipe));
  1017. if (!ConnectNamedPipe(Trans->m_Handle, &Trans->m_ReadOlap))
  1018. {
  1019. if (GetLastError() == ERROR_PIPE_CONNECTED)
  1020. {
  1021. goto Connected;
  1022. }
  1023. else if (GetLastError() == ERROR_IO_PENDING)
  1024. {
  1025. DWORD Unused;
  1026. if (GetOverlappedResult(Trans->m_Handle, &Trans->m_ReadOlap,
  1027. &Unused, TRUE))
  1028. {
  1029. goto Connected;
  1030. }
  1031. }
  1032. DRPC(("%X: Accept failed, %d\n",
  1033. GetCurrentThreadId(), GetLastError()));
  1034. delete Trans;
  1035. return WIN32_LAST_STATUS();
  1036. }
  1037. Connected:
  1038. DRPC(("%X: Accept connection on pipe %s\n",
  1039. GetCurrentThreadId(), m_Pipe));
  1040. *ClientTrans = Trans;
  1041. PrintString(Identity, IdentitySize, "npipe %s", m_Pipe);
  1042. return S_OK;
  1043. }
  1044. HRESULT
  1045. DbgRpcNamedPipeTransport::ConnectServer(void)
  1046. {
  1047. HRESULT Status;
  1048. char PipeName[2 * MAX_PARAM_VALUE + 16];
  1049. sprintf(PipeName, "\\\\%s\\pipe\\%s", m_ServerName, m_Pipe);
  1050. if ((Status = CreateOverlappedPair(&m_ReadOlap, &m_WriteOlap)) != S_OK)
  1051. {
  1052. return Status;
  1053. }
  1054. for (;;)
  1055. {
  1056. m_Handle = CreateFile(PipeName, FILE_READ_DATA | FILE_WRITE_DATA,
  1057. 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
  1058. NULL);
  1059. if (m_Handle != INVALID_HANDLE_VALUE)
  1060. {
  1061. break;
  1062. }
  1063. m_Handle = NULL;
  1064. if (GetLastError() != ERROR_PIPE_BUSY)
  1065. {
  1066. return WIN32_LAST_STATUS();
  1067. }
  1068. if (!WaitNamedPipe(PipeName, NMPWAIT_WAIT_FOREVER))
  1069. {
  1070. return WIN32_LAST_STATUS();
  1071. }
  1072. }
  1073. DRPC(("%X: Connect on pipe %s\n",
  1074. GetCurrentThreadId(), m_Pipe));
  1075. return S_OK;
  1076. }
  1077. ULONG
  1078. DbgRpcNamedPipeTransport::Read(ULONG Seq, PVOID Buffer, ULONG Len)
  1079. {
  1080. ULONG Done = 0;
  1081. ULONG Ret;
  1082. while (Len > 0)
  1083. {
  1084. if (!ReadFile(m_Handle, Buffer, Len, &Ret, &m_ReadOlap))
  1085. {
  1086. if (GetLastError() != ERROR_IO_PENDING ||
  1087. !GetOverlappedResult(m_Handle, &m_ReadOlap, &Ret, TRUE))
  1088. {
  1089. break;
  1090. }
  1091. }
  1092. Buffer = (PVOID)((PUCHAR)Buffer + Ret);
  1093. Len -= Ret;
  1094. Done += Ret;
  1095. }
  1096. return Done;
  1097. }
  1098. ULONG
  1099. DbgRpcNamedPipeTransport::Write(ULONG Seq, PVOID Buffer, ULONG Len)
  1100. {
  1101. ULONG Done = 0;
  1102. ULONG Ret;
  1103. while (Len > 0)
  1104. {
  1105. if (!WriteFile(m_Handle, Buffer, Len, &Ret, &m_WriteOlap))
  1106. {
  1107. if (GetLastError() != ERROR_IO_PENDING ||
  1108. !GetOverlappedResult(m_Handle, &m_WriteOlap, &Ret, TRUE))
  1109. {
  1110. break;
  1111. }
  1112. }
  1113. Buffer = (PVOID)((PUCHAR)Buffer + Ret);
  1114. Len -= Ret;
  1115. Done += Ret;
  1116. }
  1117. return Done;
  1118. }
  1119. #endif // #ifndef _WIN32_WCE
  1120. //----------------------------------------------------------------------------
  1121. //
  1122. // DbgRpc1394Transport.
  1123. //
  1124. //----------------------------------------------------------------------------
  1125. #ifndef _WIN32_WCE
  1126. #define TRANS1394_SYMLINK "Instance"
  1127. DbgRpc1394Transport::~DbgRpc1394Transport(void)
  1128. {
  1129. if (m_Handle != NULL)
  1130. {
  1131. CloseHandle(m_Handle);
  1132. m_Handle = NULL;
  1133. }
  1134. }
  1135. ULONG
  1136. DbgRpc1394Transport::GetNumberParameters(void)
  1137. {
  1138. return 1 + DbgRpcTransport::GetNumberParameters();
  1139. }
  1140. void
  1141. DbgRpc1394Transport::GetParameter(ULONG Index,
  1142. PSTR Name, ULONG NameSize,
  1143. PSTR Value, ULONG ValueSize)
  1144. {
  1145. switch(Index)
  1146. {
  1147. case 0:
  1148. if (m_AcceptChannel != 0)
  1149. {
  1150. CopyString(Name, "Channel", NameSize);
  1151. PrintString(Value, ValueSize, "%d", m_AcceptChannel);
  1152. }
  1153. break;
  1154. default:
  1155. DbgRpcTransport::GetParameter(Index - 1,
  1156. Name, NameSize, Value, ValueSize);
  1157. break;
  1158. }
  1159. }
  1160. void
  1161. DbgRpc1394Transport::ResetParameters(void)
  1162. {
  1163. m_AcceptChannel = 0;
  1164. m_StreamChannel = 0;
  1165. m_Handle = NULL;
  1166. DbgRpcTransport::ResetParameters();
  1167. }
  1168. BOOL
  1169. DbgRpc1394Transport::SetParameter(PCSTR Name, PCSTR Value)
  1170. {
  1171. if (!_stricmp(Name, "Channel"))
  1172. {
  1173. if (Value == NULL)
  1174. {
  1175. DbgRpcError("1394 parameters: "
  1176. "the channel was not specified correctly\n");
  1177. return FALSE;
  1178. }
  1179. m_AcceptChannel = atol(Value);
  1180. }
  1181. else
  1182. {
  1183. if (!DbgRpcTransport::SetParameter(Name, Value))
  1184. {
  1185. DbgRpcError("1394 parameters: %s is not a valid parameter\n",
  1186. Name);
  1187. return FALSE;
  1188. }
  1189. }
  1190. return TRUE;
  1191. }
  1192. DbgRpcTransport*
  1193. DbgRpc1394Transport::Clone(void)
  1194. {
  1195. DbgRpc1394Transport* Trans = new DbgRpc1394Transport;
  1196. if (Trans != NULL)
  1197. {
  1198. DbgRpcTransport::CloneData(Trans);
  1199. Trans->m_AcceptChannel = m_AcceptChannel;
  1200. }
  1201. return Trans;
  1202. }
  1203. HRESULT
  1204. DbgRpc1394Transport::CreateServer(void)
  1205. {
  1206. char Name[64];
  1207. m_StreamChannel = m_AcceptChannel;
  1208. return Create1394Channel(TRANS1394_SYMLINK, m_AcceptChannel,
  1209. Name, DIMA(Name), &m_Handle);
  1210. }
  1211. #define DBGRPC_1394_CONNECT '4931'
  1212. struct DbgRpc1394Connect
  1213. {
  1214. ULONG Signature;
  1215. ULONG Flags;
  1216. ULONG StreamChannel;
  1217. ULONG Reserved[5];
  1218. };
  1219. HRESULT
  1220. DbgRpc1394Transport::AcceptConnection(DbgRpcTransport** ClientTrans,
  1221. PSTR Identity, ULONG IdentitySize)
  1222. {
  1223. DbgRpc1394Transport* Trans = new DbgRpc1394Transport;
  1224. if (Trans == NULL)
  1225. {
  1226. return E_OUTOFMEMORY;
  1227. }
  1228. DbgRpcTransport::CloneData(Trans);
  1229. DRPC(("%X: Waiting to accept connection on channel %d\n",
  1230. GetCurrentThreadId(), m_AcceptChannel));
  1231. DbgRpc1394Connect Conn, CheckConn;
  1232. ULONG Done;
  1233. ZeroMemory(&CheckConn, sizeof(CheckConn));
  1234. CheckConn.Signature = DBGRPC_1394_CONNECT;
  1235. if (!ReadFile(m_Handle, &Conn, sizeof(Conn), &Done, NULL) ||
  1236. Done != sizeof(Conn))
  1237. {
  1238. DRPC(("%X: Accept failed, %d\n",
  1239. GetCurrentThreadId(), GetLastError()));
  1240. delete Trans;
  1241. return WIN32_LAST_STATUS();
  1242. }
  1243. if (memcmp(&Conn, &CheckConn, sizeof(Conn)) != 0)
  1244. {
  1245. DRPC(("%X: Accept information invalid\n",
  1246. GetCurrentThreadId()));
  1247. delete Trans;
  1248. return E_FAIL;
  1249. }
  1250. char StreamName[64];
  1251. HRESULT Status;
  1252. Conn.StreamChannel = m_StreamChannel + 1;
  1253. if ((Status = Open1394Channel(TRANS1394_SYMLINK,
  1254. Conn.StreamChannel,
  1255. StreamName, DIMA(StreamName),
  1256. &Trans->m_Handle)) != S_OK)
  1257. {
  1258. DRPC(("%X: Accept failed, 0x%X\n",
  1259. GetCurrentThreadId(), Status));
  1260. delete Trans;
  1261. return Status;
  1262. }
  1263. if (!WriteFile(m_Handle, &Conn, sizeof(Conn), &Done, NULL) ||
  1264. Done != sizeof(Conn))
  1265. {
  1266. DRPC(("%X: Accept failed, %d\n",
  1267. GetCurrentThreadId(), GetLastError()));
  1268. delete Trans;
  1269. return WIN32_LAST_STATUS();
  1270. }
  1271. Trans->m_AcceptChannel = m_AcceptChannel;
  1272. Trans->m_StreamChannel = Conn.StreamChannel;
  1273. m_StreamChannel++;
  1274. DRPC(("%X: Accept connection on channel %d, route to channel %d\n",
  1275. GetCurrentThreadId(), m_AcceptChannel, Conn.StreamChannel));
  1276. *ClientTrans = Trans;
  1277. PrintString(Identity, IdentitySize, "1394 %d", m_AcceptChannel);
  1278. return S_OK;
  1279. }
  1280. HRESULT
  1281. DbgRpc1394Transport::ConnectServer(void)
  1282. {
  1283. char Name[64];
  1284. HRESULT Status;
  1285. HANDLE Handle;
  1286. ULONG Done;
  1287. if ((Status = Create1394Channel(TRANS1394_SYMLINK, m_AcceptChannel,
  1288. Name, DIMA(Name), &Handle)) != S_OK)
  1289. {
  1290. return Status;
  1291. }
  1292. DbgRpc1394Connect Conn, CheckConn;
  1293. ZeroMemory(&Conn, sizeof(Conn));
  1294. Conn.Signature = DBGRPC_1394_CONNECT;
  1295. CheckConn = Conn;
  1296. if (!WriteFile(Handle, &Conn, sizeof(Conn), &Done, NULL) ||
  1297. Done != sizeof(Conn))
  1298. {
  1299. CloseHandle(Handle);
  1300. return WIN32_LAST_STATUS();
  1301. }
  1302. if (!ReadFile(Handle, &Conn, sizeof(Conn), &Done, NULL) ||
  1303. Done != sizeof(Conn))
  1304. {
  1305. CloseHandle(Handle);
  1306. return WIN32_LAST_STATUS();
  1307. }
  1308. CloseHandle(Handle);
  1309. CheckConn.StreamChannel = Conn.StreamChannel;
  1310. if (memcmp(&Conn, &CheckConn, sizeof(Conn)) != 0)
  1311. {
  1312. return E_FAIL;
  1313. }
  1314. if ((Status = Open1394Channel(TRANS1394_SYMLINK,
  1315. Conn.StreamChannel, Name, DIMA(Name),
  1316. &m_Handle)) != S_OK)
  1317. {
  1318. return Status;
  1319. }
  1320. m_StreamChannel = Conn.StreamChannel;
  1321. DRPC(("%X: Connect on channel %d, route to channel %d\n",
  1322. GetCurrentThreadId(), m_AcceptChannel, m_StreamChannel));
  1323. return S_OK;
  1324. }
  1325. ULONG
  1326. DbgRpc1394Transport::Read(ULONG Seq, PVOID Buffer, ULONG Len)
  1327. {
  1328. ULONG Done = 0;
  1329. ULONG Ret;
  1330. while (Len > 0)
  1331. {
  1332. if (!ReadFile(m_Handle, Buffer, Len, &Ret, NULL))
  1333. {
  1334. break;
  1335. }
  1336. Buffer = (PVOID)((PUCHAR)Buffer + Ret);
  1337. Len -= Ret;
  1338. Done += Ret;
  1339. }
  1340. return Done;
  1341. }
  1342. ULONG
  1343. DbgRpc1394Transport::Write(ULONG Seq, PVOID Buffer, ULONG Len)
  1344. {
  1345. ULONG Done = 0;
  1346. ULONG Ret;
  1347. while (Len > 0)
  1348. {
  1349. if (!WriteFile(m_Handle, Buffer, Len, &Ret, NULL))
  1350. {
  1351. break;
  1352. }
  1353. Buffer = (PVOID)((PUCHAR)Buffer + Ret);
  1354. Len -= Ret;
  1355. Done += Ret;
  1356. }
  1357. return Done;
  1358. }
  1359. #endif // #ifndef _WIN32_WCE
  1360. //----------------------------------------------------------------------------
  1361. //
  1362. // DbgRpcComTransport.
  1363. //
  1364. //----------------------------------------------------------------------------
  1365. #ifndef _WIN32_WCE
  1366. DbgRpcComTransport::~DbgRpcComTransport(void)
  1367. {
  1368. if (m_Handle != NULL)
  1369. {
  1370. CloseHandle(m_Handle);
  1371. }
  1372. if (m_ReadOlap.hEvent != NULL)
  1373. {
  1374. CloseHandle(m_ReadOlap.hEvent);
  1375. }
  1376. if (m_WriteOlap.hEvent != NULL)
  1377. {
  1378. CloseHandle(m_WriteOlap.hEvent);
  1379. }
  1380. }
  1381. ULONG
  1382. DbgRpcComTransport::GetNumberParameters(void)
  1383. {
  1384. return 3 + DbgRpcTransport::GetNumberParameters();
  1385. }
  1386. void
  1387. DbgRpcComTransport::GetParameter(ULONG Index,
  1388. PSTR Name, ULONG NameSize,
  1389. PSTR Value, ULONG ValueSize)
  1390. {
  1391. switch(Index)
  1392. {
  1393. case 0:
  1394. if (m_PortName[0])
  1395. {
  1396. CopyString(Name, "Port", NameSize);
  1397. CopyString(Value, m_PortName, ValueSize);
  1398. }
  1399. break;
  1400. case 1:
  1401. if (m_BaudRate)
  1402. {
  1403. CopyString(Name, "Baud", NameSize);
  1404. PrintString(Value, ValueSize, "%d", m_BaudRate);
  1405. }
  1406. break;
  1407. case 2:
  1408. if (m_AcceptChannel)
  1409. {
  1410. CopyString(Name, "Channel", NameSize);
  1411. PrintString(Value, ValueSize, "%d", m_AcceptChannel);
  1412. }
  1413. break;
  1414. default:
  1415. DbgRpcTransport::GetParameter(Index - 1,
  1416. Name, NameSize, Value, ValueSize);
  1417. break;
  1418. }
  1419. }
  1420. void
  1421. DbgRpcComTransport::ResetParameters(void)
  1422. {
  1423. m_PortName[0] = 0;
  1424. m_BaudRate = 0;
  1425. m_AcceptChannel = 0;
  1426. m_StreamChannel = 0;
  1427. m_Handle = NULL;
  1428. m_PortType = COM_PORT_STANDARD;
  1429. DbgRpcTransport::ResetParameters();
  1430. }
  1431. BOOL
  1432. DbgRpcComTransport::SetParameter(PCSTR Name, PCSTR Value)
  1433. {
  1434. if (!_stricmp(Name, "Port"))
  1435. {
  1436. if (Value == NULL)
  1437. {
  1438. DbgRpcError("COM parameters: "
  1439. "the port was not specified correctly\n");
  1440. return FALSE;
  1441. }
  1442. if (!SetComPortName(Value, m_PortName, DIMA(m_PortName)))
  1443. {
  1444. return FALSE;
  1445. }
  1446. }
  1447. else if (!_stricmp(Name, "Baud"))
  1448. {
  1449. if (Value == NULL)
  1450. {
  1451. DbgRpcError("COM parameters: "
  1452. "the baud rate was not specified correctly\n");
  1453. return FALSE;
  1454. }
  1455. m_BaudRate = atol(Value);
  1456. }
  1457. else if (!_stricmp(Name, "Channel"))
  1458. {
  1459. ULONG ValChan;
  1460. if (Value == NULL ||
  1461. (ValChan = atol(Value)) > 0xfe)
  1462. {
  1463. DbgRpcError("COM parameters: "
  1464. "the channel was not specified correctly\n");
  1465. return FALSE;
  1466. }
  1467. m_AcceptChannel = (UCHAR)ValChan;
  1468. }
  1469. else
  1470. {
  1471. if (!DbgRpcTransport::SetParameter(Name, Value))
  1472. {
  1473. DbgRpcError("COM parameters: %s is not a valid parameter\n", Name);
  1474. return FALSE;
  1475. }
  1476. }
  1477. return TRUE;
  1478. }
  1479. DbgRpcTransport*
  1480. DbgRpcComTransport::Clone(void)
  1481. {
  1482. DbgRpcComTransport* Trans = new DbgRpcComTransport;
  1483. if (Trans != NULL)
  1484. {
  1485. DbgRpcTransport::CloneData(Trans);
  1486. strcpy(Trans->m_PortName, m_PortName);
  1487. Trans->m_BaudRate = m_BaudRate;
  1488. Trans->m_AcceptChannel = m_AcceptChannel;
  1489. Trans->m_PortType = m_PortType;
  1490. // The serial port can only be opened once so
  1491. // just dup the handle for the new transport.
  1492. if (!DuplicateHandle(GetCurrentProcess(), m_Handle,
  1493. GetCurrentProcess(), &Trans->m_Handle,
  1494. 0, FALSE, DUPLICATE_SAME_ACCESS))
  1495. {
  1496. delete Trans;
  1497. Trans = NULL;
  1498. }
  1499. }
  1500. return Trans;
  1501. }
  1502. HRESULT
  1503. DbgRpcComTransport::CreateServer(void)
  1504. {
  1505. HRESULT Status;
  1506. if ((Status = InitializeChannels()) != S_OK)
  1507. {
  1508. return Status;
  1509. }
  1510. if ((Status = CreateOverlappedPair(&m_ReadOlap, &m_WriteOlap)) != S_OK)
  1511. {
  1512. return Status;
  1513. }
  1514. m_StreamChannel = m_AcceptChannel;
  1515. COM_PORT_PARAMS ComParams;
  1516. ZeroMemory(&ComParams, sizeof(ComParams));
  1517. ComParams.Type = m_PortType;
  1518. ComParams.PortName = m_PortName;
  1519. ComParams.BaudRate = m_BaudRate;
  1520. return OpenComPort(&ComParams, &m_Handle, &m_BaudRate);
  1521. }
  1522. #define DBGRPC_COM_CONNECT 'mCrD'
  1523. struct DbgRpcComConnect
  1524. {
  1525. ULONG Signature;
  1526. ULONG Flags;
  1527. ULONG StreamChannel;
  1528. ULONG Reserved[5];
  1529. };
  1530. HRESULT
  1531. DbgRpcComTransport::AcceptConnection(DbgRpcTransport** ClientTrans,
  1532. PSTR Identity, ULONG IdentitySize)
  1533. {
  1534. // Check for channel number overflow.
  1535. if (m_StreamChannel == 0xff)
  1536. {
  1537. return E_OUTOFMEMORY;
  1538. }
  1539. DbgRpcComTransport* Trans = new DbgRpcComTransport;
  1540. if (Trans == NULL)
  1541. {
  1542. return E_OUTOFMEMORY;
  1543. }
  1544. DbgRpcTransport::CloneData(Trans);
  1545. DRPC(("%X: Waiting to accept connection on port %s baud %d channel %d\n",
  1546. GetCurrentThreadId(), m_PortName, m_BaudRate, m_AcceptChannel));
  1547. DbgRpcComConnect Conn, CheckConn;
  1548. ZeroMemory(&CheckConn, sizeof(CheckConn));
  1549. CheckConn.Signature = DBGRPC_COM_CONNECT;
  1550. if (ChanRead(m_AcceptChannel, &Conn, sizeof(Conn)) != sizeof(Conn))
  1551. {
  1552. DRPC(("%X: Accept failed, %d\n",
  1553. GetCurrentThreadId(), GetLastError()));
  1554. delete Trans;
  1555. return WIN32_LAST_STATUS();
  1556. }
  1557. if (memcmp(&Conn, &CheckConn, sizeof(Conn)) != 0)
  1558. {
  1559. DRPC(("%X: Accept information invalid\n",
  1560. GetCurrentThreadId()));
  1561. delete Trans;
  1562. return E_FAIL;
  1563. }
  1564. Conn.StreamChannel = m_StreamChannel + 1;
  1565. if (ChanWrite(m_AcceptChannel, &Conn, sizeof(Conn)) != sizeof(Conn))
  1566. {
  1567. DRPC(("%X: Accept failed, %d\n",
  1568. GetCurrentThreadId(), GetLastError()));
  1569. delete Trans;
  1570. return WIN32_LAST_STATUS();
  1571. }
  1572. // Duplicate the handle so that every transport instance
  1573. // has its own to close.
  1574. if (!DuplicateHandle(GetCurrentProcess(), m_Handle,
  1575. GetCurrentProcess(), &Trans->m_Handle,
  1576. 0, FALSE, DUPLICATE_SAME_ACCESS))
  1577. {
  1578. DRPC(("%X: Accept failed, %d\n",
  1579. GetCurrentThreadId(), GetLastError()));
  1580. delete Trans;
  1581. return WIN32_LAST_STATUS();
  1582. }
  1583. HRESULT Status;
  1584. if ((Status = CreateOverlappedPair(&Trans->m_ReadOlap,
  1585. &Trans->m_WriteOlap)) != S_OK)
  1586. {
  1587. DRPC(("%X: Accept failed, 0x%X\n",
  1588. GetCurrentThreadId(), Status));
  1589. delete Trans;
  1590. return Status;
  1591. }
  1592. strcpy(Trans->m_PortName, m_PortName);
  1593. Trans->m_BaudRate = m_BaudRate;
  1594. Trans->m_AcceptChannel = m_AcceptChannel;
  1595. Trans->m_StreamChannel = (UCHAR)Conn.StreamChannel;
  1596. Trans->m_PortType = m_PortType;
  1597. m_StreamChannel++;
  1598. DRPC(("%X: Accept connection on channel %d, route to channel %d\n",
  1599. GetCurrentThreadId(), m_AcceptChannel, Conn.StreamChannel));
  1600. *ClientTrans = Trans;
  1601. PrintString(Identity, IdentitySize, "COM %s@%d chan %d",
  1602. m_PortName, m_BaudRate, m_AcceptChannel);
  1603. return S_OK;
  1604. }
  1605. HRESULT
  1606. DbgRpcComTransport::ConnectServer(void)
  1607. {
  1608. HRESULT Status;
  1609. if ((Status = InitializeChannels()) != S_OK)
  1610. {
  1611. return Status;
  1612. }
  1613. if ((Status = CreateOverlappedPair(&m_ReadOlap, &m_WriteOlap)) != S_OK)
  1614. {
  1615. return Status;
  1616. }
  1617. // If this is a clone it'll already have a handle.
  1618. // Otherwise this is the first connecting transport
  1619. // so it needs to really open the COM port.
  1620. if (m_Handle == NULL)
  1621. {
  1622. COM_PORT_PARAMS ComParams;
  1623. ZeroMemory(&ComParams, sizeof(ComParams));
  1624. ComParams.Type = m_PortType;
  1625. ComParams.PortName = m_PortName;
  1626. ComParams.BaudRate = m_BaudRate;
  1627. if ((Status = OpenComPort(&ComParams, &m_Handle, &m_BaudRate)) != S_OK)
  1628. {
  1629. return Status;
  1630. }
  1631. }
  1632. DbgRpcComConnect Conn, CheckConn;
  1633. ZeroMemory(&Conn, sizeof(Conn));
  1634. Conn.Signature = DBGRPC_COM_CONNECT;
  1635. CheckConn = Conn;
  1636. if (ChanWrite(m_AcceptChannel, &Conn, sizeof(Conn)) != sizeof(Conn))
  1637. {
  1638. CloseHandle(m_Handle);
  1639. m_Handle = NULL;
  1640. return WIN32_LAST_STATUS();
  1641. }
  1642. if (ChanRead(m_AcceptChannel, &Conn, sizeof(Conn)) != sizeof(Conn))
  1643. {
  1644. CloseHandle(m_Handle);
  1645. m_Handle = NULL;
  1646. return WIN32_LAST_STATUS();
  1647. }
  1648. CheckConn.StreamChannel = Conn.StreamChannel;
  1649. if (memcmp(&Conn, &CheckConn, sizeof(Conn)) != 0)
  1650. {
  1651. CloseHandle(m_Handle);
  1652. m_Handle = NULL;
  1653. return E_FAIL;
  1654. }
  1655. m_StreamChannel = (UCHAR)Conn.StreamChannel;
  1656. DRPC(("%X: Connect on channel %d, route to channel %d\n",
  1657. GetCurrentThreadId(), m_AcceptChannel, m_StreamChannel));
  1658. return S_OK;
  1659. }
  1660. #if 0
  1661. #define DCOM(Args) g_NtDllCalls.DbgPrint Args
  1662. #else
  1663. #define DCOM(Args)
  1664. #endif
  1665. #define DBGRPC_COM_FAILURE 0xffff
  1666. #define DBGRPC_COM_HEAD_SIG 0xdc
  1667. #define DBGRPC_COM_TAIL_SIG 0xcd
  1668. // In order to avoid overflowing the serial port when
  1669. // used at boot time, restrict the maximum size of
  1670. // a single chunk of data written. This must be
  1671. // less than 0xffff.
  1672. #ifdef NT_NATIVE
  1673. #define DBGRPC_COM_MAX_CHUNK (16 - sizeof(DbgRpcComStream))
  1674. #else
  1675. #define DBGRPC_COM_MAX_CHUNK 0xfffe
  1676. #endif
  1677. struct DbgRpcComStream
  1678. {
  1679. UCHAR Signature;
  1680. UCHAR Channel;
  1681. USHORT Len;
  1682. };
  1683. struct DbgRpcComQueue
  1684. {
  1685. DbgRpcComQueue* Next;
  1686. PUCHAR Data;
  1687. UCHAR Channel;
  1688. USHORT Len;
  1689. };
  1690. BOOL DbgRpcComTransport::s_ChanInitialized;
  1691. CRITICAL_SECTION DbgRpcComTransport::s_QueueLock;
  1692. HANDLE DbgRpcComTransport::s_QueueChangedEvent;
  1693. LONG DbgRpcComTransport::s_PortReadOwned;
  1694. CRITICAL_SECTION DbgRpcComTransport::s_PortWriteLock;
  1695. CRITICAL_SECTION DbgRpcComTransport::s_WriteAckLock;
  1696. HANDLE DbgRpcComTransport::s_WriteAckEvent;
  1697. DbgRpcComQueue* DbgRpcComTransport::s_QueueHead;
  1698. DbgRpcComQueue* DbgRpcComTransport::s_QueueTail;
  1699. ULONG
  1700. DbgRpcComTransport::Read(ULONG Seq, PVOID Buffer, ULONG Len)
  1701. {
  1702. ULONG Done = 0;
  1703. while (Len > 0)
  1704. {
  1705. USHORT Chunk = (USHORT)min(Len, DBGRPC_COM_MAX_CHUNK);
  1706. USHORT ChunkDone = ChanRead(m_StreamChannel, Buffer, Chunk);
  1707. Done += ChunkDone;
  1708. Buffer = (PUCHAR)Buffer + ChunkDone;
  1709. Len -= ChunkDone;
  1710. if (ChunkDone < Chunk)
  1711. {
  1712. break;
  1713. }
  1714. }
  1715. return Done;
  1716. }
  1717. ULONG
  1718. DbgRpcComTransport::Write(ULONG Seq, PVOID Buffer, ULONG Len)
  1719. {
  1720. ULONG Done = 0;
  1721. while (Len > 0)
  1722. {
  1723. USHORT Chunk = (USHORT)min(Len, DBGRPC_COM_MAX_CHUNK);
  1724. USHORT ChunkDone = ChanWrite(m_StreamChannel, Buffer, Chunk);
  1725. Done += ChunkDone;
  1726. Buffer = (PUCHAR)Buffer + ChunkDone;
  1727. Len -= ChunkDone;
  1728. if (ChunkDone < Chunk)
  1729. {
  1730. break;
  1731. }
  1732. }
  1733. return Done;
  1734. }
  1735. USHORT
  1736. DbgRpcComTransport::ScanQueue(UCHAR Chan, PVOID Buffer, USHORT Len)
  1737. {
  1738. USHORT Done = 0;
  1739. EnterCriticalSection(&s_QueueLock);
  1740. DbgRpcComQueue* Ent;
  1741. DbgRpcComQueue* Next;
  1742. DbgRpcComQueue* Prev;
  1743. Prev = NULL;
  1744. for (Ent = s_QueueHead; Ent != NULL && Len > 0; Ent = Next)
  1745. {
  1746. Next = Ent->Next;
  1747. DCOM(("%03X: Queue entry %p->%p %d,%d\n",
  1748. GetCurrentThreadId(),
  1749. Ent, Next, Ent->Channel, Ent->Len));
  1750. if (Ent->Channel == Chan)
  1751. {
  1752. // Found some input for this channel.
  1753. if (Len < Ent->Len)
  1754. {
  1755. DCOM(("%03X: Eat %d, leave %d\n",
  1756. GetCurrentThreadId(), Len, Ent->Len - Len));
  1757. memcpy(Buffer, Ent->Data, Len);
  1758. Ent->Data += Len;
  1759. Ent->Len -= Len;
  1760. Done += Len;
  1761. Len = 0;
  1762. }
  1763. else
  1764. {
  1765. DCOM(("%03X: Eat all %d\n",
  1766. GetCurrentThreadId(), Len));
  1767. memcpy(Buffer, Ent->Data, Ent->Len);
  1768. Buffer = (PVOID)((PUCHAR)Buffer + Ent->Len);
  1769. Done += Ent->Len;
  1770. Len -= Ent->Len;
  1771. // Remove used-up entry from list.
  1772. if (Prev == NULL)
  1773. {
  1774. s_QueueHead = Ent->Next;
  1775. }
  1776. else
  1777. {
  1778. Prev->Next = Ent->Next;
  1779. }
  1780. if (s_QueueTail == Ent)
  1781. {
  1782. s_QueueTail = Prev;
  1783. }
  1784. free(Ent);
  1785. continue;
  1786. }
  1787. }
  1788. Prev = Ent;
  1789. }
  1790. LeaveCriticalSection(&s_QueueLock);
  1791. return Done;
  1792. }
  1793. USHORT
  1794. DbgRpcComTransport::ScanPort(UCHAR Chan, PVOID Buffer, USHORT Len,
  1795. BOOL ScanForAck, UCHAR AckChan)
  1796. {
  1797. DbgRpcComStream Stream;
  1798. ULONG ReadDone;
  1799. USHORT Ret = 0;
  1800. if (ScanForAck)
  1801. {
  1802. DCOM(("%03X: Waiting to read header (ack chan %d)\n",
  1803. GetCurrentThreadId(), AckChan));
  1804. }
  1805. else
  1806. {
  1807. DCOM(("%03X: Waiting to read header\n",
  1808. GetCurrentThreadId()));
  1809. }
  1810. Rescan:
  1811. for (;;)
  1812. {
  1813. if (!ComPortRead(m_Handle, m_PortType, m_Timeout,
  1814. &Stream, sizeof(Stream), &ReadDone,
  1815. &m_ReadOlap) ||
  1816. ReadDone != sizeof(Stream))
  1817. {
  1818. return DBGRPC_COM_FAILURE;
  1819. }
  1820. // If a write ack came through release the waiting writer.
  1821. if (Stream.Signature == DBGRPC_COM_TAIL_SIG &&
  1822. Stream.Len == DBGRPC_COM_FAILURE)
  1823. {
  1824. DCOM(("%03X: Read write ack for chan %d\n",
  1825. GetCurrentThreadId(), Stream.Channel));
  1826. if (ScanForAck)
  1827. {
  1828. if (AckChan == Stream.Channel)
  1829. {
  1830. return (USHORT)ReadDone;
  1831. }
  1832. else
  1833. {
  1834. DCOM(("%03X: Read mismatched write ack, "
  1835. "read chan %d waiting for chan %d\n",
  1836. GetCurrentThreadId(), Stream.Channel, AckChan));
  1837. return DBGRPC_COM_FAILURE;
  1838. }
  1839. }
  1840. SetEvent(s_WriteAckEvent);
  1841. }
  1842. else if (Stream.Signature != DBGRPC_COM_HEAD_SIG ||
  1843. Stream.Len == DBGRPC_COM_FAILURE)
  1844. {
  1845. return DBGRPC_COM_FAILURE;
  1846. }
  1847. else
  1848. {
  1849. break;
  1850. }
  1851. }
  1852. DCOM(("%03X: Read %d,%d\n",
  1853. GetCurrentThreadId(), Stream.Channel, Stream.Len));
  1854. // If the data available is for this channel
  1855. // read it directly into the buffer.
  1856. if (!ScanForAck && Stream.Channel == Chan)
  1857. {
  1858. Ret = min(Stream.Len, Len);
  1859. DCOM(("%03X: Read direct body %d\n",
  1860. GetCurrentThreadId(), Ret));
  1861. if (!ComPortRead(m_Handle, m_PortType, m_Timeout,
  1862. Buffer, Ret, &ReadDone, &m_ReadOlap) ||
  1863. ReadDone != Ret)
  1864. {
  1865. return DBGRPC_COM_FAILURE;
  1866. }
  1867. Stream.Len -= Ret;
  1868. }
  1869. // If the data is for another channel or there's
  1870. // more than we need queue the remainder for
  1871. // later use.
  1872. if (Stream.Len > 0)
  1873. {
  1874. DbgRpcComQueue* Ent =
  1875. (DbgRpcComQueue*)malloc(sizeof(*Ent) + Stream.Len);
  1876. if (Ent == NULL)
  1877. {
  1878. return DBGRPC_COM_FAILURE;
  1879. }
  1880. Ent->Next = NULL;
  1881. Ent->Channel = Stream.Channel;
  1882. Ent->Len = Stream.Len;
  1883. Ent->Data = (PUCHAR)Ent + sizeof(*Ent);
  1884. DCOM(("%03X: Read queue body %d\n",
  1885. GetCurrentThreadId(), Ent->Len));
  1886. if (!ComPortRead(m_Handle, m_PortType, m_Timeout,
  1887. Ent->Data, Ent->Len, &ReadDone,
  1888. &m_ReadOlap) ||
  1889. ReadDone != Ent->Len)
  1890. {
  1891. free(Ent);
  1892. return DBGRPC_COM_FAILURE;
  1893. }
  1894. DCOM(("%03X: Queue add %p %d,%d\n",
  1895. GetCurrentThreadId(), Ent, Ent->Channel, Ent->Len));
  1896. EnterCriticalSection(&s_QueueLock);
  1897. if (s_QueueHead == NULL)
  1898. {
  1899. s_QueueHead = Ent;
  1900. }
  1901. else
  1902. {
  1903. s_QueueTail->Next = Ent;
  1904. }
  1905. s_QueueTail = Ent;
  1906. LeaveCriticalSection(&s_QueueLock);
  1907. }
  1908. //
  1909. // Acknowledge full receipt of the data.
  1910. //
  1911. Stream.Signature = DBGRPC_COM_TAIL_SIG;
  1912. Stream.Channel = Stream.Channel;
  1913. Stream.Len = DBGRPC_COM_FAILURE;
  1914. EnterCriticalSection(&s_PortWriteLock);
  1915. if (!ComPortWrite(m_Handle, m_PortType, &Stream, sizeof(Stream),
  1916. &ReadDone, &m_ReadOlap))
  1917. {
  1918. ReadDone = 0;
  1919. }
  1920. else
  1921. {
  1922. DCOM(("%03X: Wrote write ack for chan %d\n",
  1923. GetCurrentThreadId(), Stream.Channel));
  1924. }
  1925. LeaveCriticalSection(&s_PortWriteLock);
  1926. if (ReadDone != sizeof(Stream))
  1927. {
  1928. return DBGRPC_COM_FAILURE;
  1929. }
  1930. // Don't exit if we're waiting for an ack as
  1931. // we haven't received it yet.
  1932. if (ScanForAck)
  1933. {
  1934. SetEvent(s_QueueChangedEvent);
  1935. goto Rescan;
  1936. }
  1937. return Ret;
  1938. }
  1939. USHORT
  1940. DbgRpcComTransport::ChanRead(UCHAR Chan, PVOID Buffer, USHORT InLen)
  1941. {
  1942. USHORT Done = 0;
  1943. USHORT Len = InLen;
  1944. // The virtual channels require that all reads and writes
  1945. // be complete. A partial read or write will not match
  1946. // its channel header and will throw everything off.
  1947. DCOM(("%03X:ChanRead %d,%d\n",
  1948. GetCurrentThreadId(), Chan, Len));
  1949. while (Len > 0)
  1950. {
  1951. USHORT Queued;
  1952. // First check and see if input for this channel
  1953. // is already present in the queue.
  1954. Queued = ScanQueue(Chan, Buffer, Len);
  1955. Done += Queued;
  1956. Buffer = (PVOID)((PUCHAR)Buffer + Queued);
  1957. Len -= Queued;
  1958. if (Queued > 0)
  1959. {
  1960. DCOM(("%03X: Scan pass 1 gets %d from queue\n",
  1961. GetCurrentThreadId(), Queued));
  1962. }
  1963. if (Len == 0)
  1964. {
  1965. break;
  1966. }
  1967. //
  1968. // There wasn't enough queued input so try and
  1969. // read some more from the port.
  1970. //
  1971. if (InterlockedExchange(&s_PortReadOwned, TRUE) == TRUE)
  1972. {
  1973. // Somebody else owns the port so we can't
  1974. // read it. Just wait for the queue to change
  1975. // so we can check for data again.
  1976. // Set things to wait.
  1977. ResetEvent(s_QueueChangedEvent);
  1978. // There's a chance that the queue changed just before
  1979. // the event was reset and therefore that event set
  1980. // has been lost. Time out of this wait to ensure
  1981. // that nothing ever gets hung up indefinitely here.
  1982. if (WaitForSingleObject(s_QueueChangedEvent, 250) ==
  1983. WAIT_FAILED)
  1984. {
  1985. DCOM(("%03X: Change wait failed\n",
  1986. GetCurrentThreadId()));
  1987. return 0;
  1988. }
  1989. continue;
  1990. }
  1991. // We now own the port. The queue may have changed
  1992. // during the time we were acquiring ownership, though,
  1993. // so check it again.
  1994. Queued = ScanQueue(Chan, Buffer, Len);
  1995. Done += Queued;
  1996. Buffer = (PVOID)((PUCHAR)Buffer + Queued);
  1997. Len -= Queued;
  1998. if (Queued > 0)
  1999. {
  2000. DCOM(("%03X: Scan pass 2 gets %d from queue\n",
  2001. GetCurrentThreadId(), Queued));
  2002. }
  2003. if (Len > 0)
  2004. {
  2005. // Still need more input and we're now the
  2006. // owner of the port, so read.
  2007. USHORT Port = ScanPort(Chan, Buffer, Len, FALSE, 0);
  2008. if (Port == DBGRPC_COM_FAILURE)
  2009. {
  2010. // Critical error, fail immediately.
  2011. InterlockedExchange(&s_PortReadOwned, FALSE);
  2012. SetEvent(s_QueueChangedEvent);
  2013. DCOM(("%03X: Critical failure\n",
  2014. GetCurrentThreadId()));
  2015. return 0;
  2016. }
  2017. Done += Port;
  2018. Buffer = (PVOID)((PUCHAR)Buffer + Port);
  2019. Len -= Port;
  2020. if (Port > 0)
  2021. {
  2022. DCOM(("%03X: Scan %d from port\n",
  2023. GetCurrentThreadId(), Port));
  2024. }
  2025. }
  2026. InterlockedExchange(&s_PortReadOwned, FALSE);
  2027. SetEvent(s_QueueChangedEvent);
  2028. }
  2029. DCOM(("%03X: ChanRead %d,%d returns %d\n",
  2030. GetCurrentThreadId(), Chan, InLen, Done));
  2031. return Done;
  2032. }
  2033. USHORT
  2034. DbgRpcComTransport::ChanWrite(UCHAR Chan, PVOID Buffer, USHORT InLen)
  2035. {
  2036. USHORT Len = InLen;
  2037. DCOM(("%03X:ChanWrite %d,%d\n",
  2038. GetCurrentThreadId(), Chan, Len));
  2039. ULONG Done;
  2040. DbgRpcComStream Stream;
  2041. // The virtual channels require that all reads and writes
  2042. // be complete. A partial read or write will not match
  2043. // its channel header and will throw everything off.
  2044. Stream.Signature = DBGRPC_COM_HEAD_SIG;
  2045. Stream.Channel = Chan;
  2046. Stream.Len = Len;
  2047. // The write ack lock restricts things to a single
  2048. // unacknowledged write. The port write lock
  2049. // ensures that the multiple pieces of a write
  2050. // are sequential in the stream.
  2051. EnterCriticalSection(&s_WriteAckLock);
  2052. EnterCriticalSection(&s_PortWriteLock);
  2053. if (!ComPortWrite(m_Handle, m_PortType, &Stream, sizeof(Stream), &Done,
  2054. &m_WriteOlap) ||
  2055. Done != sizeof(Stream) ||
  2056. !ComPortWrite(m_Handle, m_PortType, Buffer, Len,
  2057. &Done, &m_WriteOlap) ||
  2058. Done != Len)
  2059. {
  2060. Done = 0;
  2061. }
  2062. LeaveCriticalSection(&s_PortWriteLock);
  2063. //
  2064. // Wait for data ack. This prevents too much data from
  2065. // being written to the serial port at once by limiting
  2066. // the amount of outstanding data to a single chunk's worth.
  2067. //
  2068. for (;;)
  2069. {
  2070. if (InterlockedExchange(&s_PortReadOwned, TRUE) == TRUE)
  2071. {
  2072. HANDLE Waits[2];
  2073. ULONG Wait;
  2074. // Somebody else owns the port so wait for their signal.
  2075. // Also wait for a port ownership change as we may
  2076. // need to switch to a direct port read.
  2077. Waits[0] = s_WriteAckEvent;
  2078. Waits[1] = s_QueueChangedEvent;
  2079. // Set things to wait.
  2080. ResetEvent(s_QueueChangedEvent);
  2081. Wait = WaitForMultipleObjects(2, Waits, FALSE, 250);
  2082. if (Wait == WAIT_OBJECT_0)
  2083. {
  2084. break;
  2085. }
  2086. else if (Wait == WAIT_FAILED)
  2087. {
  2088. DCOM(("%03X: Write ack wait failed, %d\n",
  2089. GetCurrentThreadId(), GetLastError()));
  2090. Done = 0;
  2091. break;
  2092. }
  2093. }
  2094. else
  2095. {
  2096. USHORT AckDone;
  2097. // We now own the port so directly read the ack.
  2098. // However, before we do we need to make one last
  2099. // check and see if somebody else read our ack
  2100. // in the time leading up to us acquiring port
  2101. // ownership.
  2102. if (WaitForSingleObject(s_WriteAckEvent, 0) != WAIT_OBJECT_0)
  2103. {
  2104. AckDone = ScanPort(Chan, &Stream, sizeof(Stream),
  2105. TRUE, Chan);
  2106. if (AckDone == DBGRPC_COM_FAILURE)
  2107. {
  2108. DCOM(("%03X: Failed scan for write ack\n",
  2109. GetCurrentThreadId()));
  2110. Done = 0;
  2111. }
  2112. }
  2113. InterlockedExchange(&s_PortReadOwned, FALSE);
  2114. SetEvent(s_QueueChangedEvent);
  2115. break;
  2116. }
  2117. }
  2118. LeaveCriticalSection(&s_WriteAckLock);
  2119. DCOM(("%03X: ChanWrite %d,%d returns %d\n",
  2120. GetCurrentThreadId(), Chan, InLen, Done));
  2121. return (USHORT)Done;
  2122. }
  2123. HRESULT
  2124. DbgRpcComTransport::InitializeChannels(void)
  2125. {
  2126. if (s_ChanInitialized)
  2127. {
  2128. return S_OK;
  2129. }
  2130. if ((s_QueueChangedEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
  2131. {
  2132. return WIN32_LAST_STATUS();
  2133. }
  2134. if ((s_WriteAckEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
  2135. {
  2136. return WIN32_LAST_STATUS();
  2137. }
  2138. __try
  2139. {
  2140. InitializeCriticalSection(&s_QueueLock);
  2141. InitializeCriticalSection(&s_PortWriteLock);
  2142. InitializeCriticalSection(&s_WriteAckLock);
  2143. }
  2144. __except(EXCEPTION_EXECUTE_HANDLER)
  2145. {
  2146. return E_OUTOFMEMORY;
  2147. }
  2148. s_ChanInitialized = TRUE;
  2149. return S_OK;
  2150. }
  2151. #endif // #ifndef _WIN32_WCE
  2152. //----------------------------------------------------------------------------
  2153. //
  2154. // Transport functions.
  2155. //
  2156. //----------------------------------------------------------------------------
  2157. DbgRpcTransport*
  2158. DbgRpcNewTransport(ULONG Trans)
  2159. {
  2160. switch(Trans)
  2161. {
  2162. #ifdef _WIN32_WCE
  2163. case TRANS_TCP:
  2164. return new DbgRpcTcpTransport;
  2165. #else
  2166. #ifndef NT_NATIVE
  2167. case TRANS_TCP:
  2168. return new DbgRpcTcpTransport;
  2169. case TRANS_SSL:
  2170. return new DbgRpcSecureChannelTransport(Trans, TRANS_TCP);
  2171. case TRANS_SPIPE:
  2172. return new DbgRpcSecureChannelTransport(Trans, TRANS_NPIPE);
  2173. #endif
  2174. case TRANS_NPIPE:
  2175. return new DbgRpcNamedPipeTransport;
  2176. case TRANS_1394:
  2177. return new DbgRpc1394Transport;
  2178. case TRANS_COM:
  2179. return new DbgRpcComTransport;
  2180. #endif // #ifdef _WIN32_WCE
  2181. default:
  2182. return NULL;
  2183. }
  2184. }
  2185. DbgRpcTransport*
  2186. DbgRpcCreateTransport(PCSTR Options)
  2187. {
  2188. ULONG Trans = ParameterStringParser::
  2189. GetParser(Options, TRANS_COUNT, g_DbgRpcTransportNames);
  2190. return DbgRpcNewTransport(Trans);
  2191. }
  2192. DbgRpcTransport*
  2193. DbgRpcInitializeTransport(PCSTR Options)
  2194. {
  2195. DbgRpcTransport* Trans = DbgRpcCreateTransport(Options);
  2196. if (Trans != NULL)
  2197. {
  2198. // Clean out any old parameter state.
  2199. Trans->ResetParameters();
  2200. if (!Trans->ParseParameters(Options))
  2201. {
  2202. delete Trans;
  2203. return NULL;
  2204. }
  2205. }
  2206. return Trans;
  2207. }