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.

2634 lines
67 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. w32drprt
  5. Abstract:
  6. This module defines the parent for the Win32 client-side RDP
  7. Port Redirection "device" class hierarchy, W32DrPRT.
  8. Author:
  9. Tad Brockway 4/21/99
  10. Revision History:
  11. --*/
  12. #include <precom.h>
  13. #define TRC_FILE "W32DrPRT"
  14. #include "w32drprt.h"
  15. #include "proc.h"
  16. #include "drdbg.h"
  17. #include "utl.h"
  18. #ifdef OS_WINCE
  19. #include "wceinc.h"
  20. #endif
  21. #if DBG
  22. #include "tracecom.h"
  23. #endif
  24. //
  25. // COM port initialization default values.
  26. //
  27. // These value are copied from
  28. // \\muroc\slm\proj\win\src\CORE\SPOOL32\SPOOLSS\newdll\localmon.c
  29. //
  30. #define WRITE_TOTAL_TIMEOUT 60000 // 60 seconds localmon.c uses 3 seconds, but
  31. // this doesn't work in 9x. An application that
  32. // is aware that it is opening a serial device
  33. // will override this, so it only really applies
  34. // to serial printer redirection.
  35. #define READ_TOTAL_TIMEOUT 5000 // 5 seconds
  36. #define READ_INTERVAL_TIMEOUT 200 // 0.2 second
  37. ///////////////////////////////////////////////////////////////
  38. //
  39. // W32DrPRT Members
  40. //
  41. // Subclass off of the async parent device in CE because
  42. // overlapped IO is not supported. Non-overlapped IO doesn't
  43. // work right with the NT serial driver, so we need to use
  44. // overlapped IO in this case.
  45. //
  46. W32DrPRT::W32DrPRT(ProcObj *processObject, const DRSTRING portName,
  47. ULONG deviceID, const TCHAR *devicePath) :
  48. #ifdef OS_WINCE
  49. W32DrDeviceAsync(processObject, deviceID, devicePath),
  50. #else
  51. W32DrDeviceOverlapped(processObject, deviceID, devicePath),
  52. #endif
  53. DrPRT(portName, processObject)
  54. /*++
  55. Routine Description:
  56. Constructor
  57. Arguments:
  58. processObject - Associated Process Object
  59. portName - Name of the port.
  60. deviceID - Device ID for the port.
  61. devicePath - Path that can be opened via CreateFile for port.
  62. Return Value:
  63. NA
  64. --*/
  65. {
  66. DC_BEGIN_FN("W32DrPRT::W32DrPRT");
  67. //
  68. // Do nothing for now.
  69. //
  70. DC_END_FN();
  71. }
  72. W32DrPRT::~W32DrPRT()
  73. /*++
  74. Routine Description:
  75. Destructor
  76. Arguments:
  77. NA
  78. Return Value:
  79. NA
  80. --*/
  81. {
  82. DC_BEGIN_FN("W32DrPRT::~W32DrPRT");
  83. //
  84. // Do nothing for now.
  85. //
  86. DC_END_FN();
  87. }
  88. DRPORTHANDLE W32DrPRT::GetPortHandle(ULONG FileId)
  89. /*++
  90. Routine Description:
  91. Get Port's Open Handle
  92. Arguments:
  93. File Id from server
  94. Return Value:
  95. NA
  96. --*/
  97. {
  98. DrFile *pFile;
  99. pFile = _FileMgr->GetObject(FileId);
  100. if (pFile) {
  101. return pFile->GetFileHandle();
  102. }
  103. else {
  104. return INVALID_TSPORTHANDLE;
  105. }
  106. }
  107. VOID
  108. W32DrPRT::MsgIrpDeviceControl(
  109. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  110. IN UINT32 packetLen
  111. )
  112. /*++
  113. Routine Description:
  114. Handles Port IOCTL's
  115. Arguments:
  116. pIoRequestPacket - Request packet received from server.
  117. packetLen - Length of teh packet
  118. Return Value:
  119. The size (in bytes) of a device announce packet for this device.
  120. --*/
  121. {
  122. DC_BEGIN_FN("W32DrPRT::MsgIrpDeviceControl");
  123. //
  124. // Give the parent DrPRT class a shot at decoding the IOCTL
  125. // into the correct COMM function.
  126. //
  127. if (MsgIrpDeviceControlTranslate(pIoRequestPacket)) {
  128. TRC_DBG((TB, _T("Successfully decoded IOCTL.")));
  129. }
  130. //
  131. // Otherwise, we will just pass it on to the driver.
  132. //
  133. else {
  134. DispatchIOCTLDirectlyToDriver(pIoRequestPacket);
  135. }
  136. DC_END_FN();
  137. }
  138. #ifndef OS_WINCE
  139. HANDLE
  140. W32DrPRT::StartWaitOnMaskFunc(
  141. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  142. OUT DWORD *status
  143. )
  144. /*++
  145. Routine Description:
  146. Asynchronously handle a "wait on mask" function.
  147. Arguments:
  148. params - Context for the IO request.
  149. status - Return status for IO request in the form of a windows
  150. error code.
  151. Return Value:
  152. NA
  153. --*/
  154. {
  155. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  156. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  157. ULONG replyPacketSize = 0;
  158. LPDWORD serverEventMask;
  159. PBYTE outputBuf;
  160. HANDLE FileHandle;
  161. DC_BEGIN_FN("W32DrPRT::StartWaitOnMaskFunc");
  162. *status = ERROR_SUCCESS;
  163. // Assert the integrity of the IO context
  164. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  165. //
  166. // Get the IO request.
  167. //
  168. pIoRequest = &params->pIoRequestPacket->IoRequest;
  169. //
  170. // Get Port Handle
  171. //
  172. FileHandle = GetPortHandle(pIoRequest->FileId);
  173. //
  174. // Allocate reply buffer.
  175. //
  176. replyPacketSize = DR_IOCTL_REPLYBUFSIZE(pIoRequest);
  177. pReplyPacket = DrUTL_AllocIOCompletePacket(
  178. params->pIoRequestPacket,
  179. replyPacketSize
  180. );
  181. if (pReplyPacket == NULL) {
  182. *status = ERROR_NOT_ENOUGH_MEMORY;
  183. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  184. goto Cleanup;
  185. }
  186. //
  187. // Save the reply packet info to the context for this IO operation.
  188. //
  189. params->pIoReplyPacket = pReplyPacket;
  190. params->IoReplyPacketSize = replyPacketSize;
  191. //
  192. // Create an event for the overlapped IO.
  193. //
  194. memset(&params->overlapped, 0, sizeof(params->overlapped));
  195. params->overlapped.hEvent = CreateEvent(
  196. NULL, // no attribute.
  197. TRUE, // manual reset.
  198. FALSE, // initially not signalled.
  199. NULL // no name.
  200. );
  201. if (params->overlapped.hEvent == NULL) {
  202. TRC_ERR((TB, _T("Failed to create event")));
  203. *status = ERROR_NOT_ENOUGH_MEMORY;
  204. goto Cleanup;
  205. }
  206. //
  207. // Get a pointer to the output buffer and server's event mask.
  208. //
  209. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  210. serverEventMask = (LPDWORD)outputBuf;
  211. //
  212. // Use WaitCommEvent to handle the request.
  213. //
  214. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  215. if (!WaitCommEvent(FileHandle, serverEventMask, &params->overlapped)) {
  216. //
  217. // If IO is pending.
  218. //
  219. *status = GetLastError();
  220. if (*status == ERROR_IO_PENDING) {
  221. TRC_NRM((TB, _T("Pending IO.")));
  222. }
  223. else {
  224. TRC_ERR((TB, _T("Error %ld."), *status));
  225. goto Cleanup;
  226. }
  227. }
  228. else {
  229. TRC_NRM((TB, _T("Completed synchronously.")));
  230. *status = ERROR_SUCCESS;
  231. }
  232. Cleanup:
  233. //
  234. // If IO is pending, return the handle to the pending IO.
  235. //
  236. if (*status == ERROR_IO_PENDING) {
  237. DC_END_FN();
  238. return params->overlapped.hEvent;
  239. }
  240. //
  241. // Otherwise, return NULL so that the CompleteIOFunc can be called
  242. // to send the results to the server.
  243. //
  244. else {
  245. if (params->overlapped.hEvent != NULL) {
  246. CloseHandle(params->overlapped.hEvent);
  247. params->overlapped.hEvent = NULL;
  248. }
  249. DC_END_FN();
  250. return NULL;
  251. }
  252. }
  253. HANDLE
  254. W32DrPRT::_StartWaitOnMaskFunc(
  255. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  256. OUT DWORD *status
  257. )
  258. {
  259. return ((W32DrPRT*)params->pObject)->StartWaitOnMaskFunc(params, status);
  260. }
  261. #else // Windows CE
  262. HANDLE
  263. W32DrPRT::StartWaitOnMaskFunc(
  264. IN W32DRDEV_ASYNCIO_PARAMS *params,
  265. OUT DWORD *status
  266. )
  267. /*++
  268. Routine Description:
  269. Asynchronously handle a "wait on mask" function. Can't use overlapped
  270. IO in CE, so we will use a pooled thread.
  271. Arguments:
  272. params - Context for the IO request.
  273. status - Return status for IO request in the form of a windows
  274. error code.
  275. Return Value:
  276. NA
  277. --*/
  278. {
  279. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  280. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  281. ULONG replyPacketSize = 0;
  282. DC_BEGIN_FN("W32DrPRT::_StartWaitOnMaskFunc");
  283. *status = ERROR_SUCCESS;
  284. // Assert the integrity of the IO context
  285. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  286. //
  287. // Get the IO request.
  288. //
  289. pIoRequest = &params->pIoRequestPacket->IoRequest;
  290. //
  291. // Allocate reply buffer.
  292. //
  293. replyPacketSize = DR_IOCTL_REPLYBUFSIZE(pIoRequest);
  294. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  295. replyPacketSize) ;
  296. if (pReplyPacket == NULL) {
  297. *status = ERROR_NOT_ENOUGH_MEMORY;
  298. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  299. goto Cleanup;
  300. }
  301. //
  302. // Save the reply packet info to the context for this IO operation.
  303. //
  304. params->pIoReplyPacket = pReplyPacket;
  305. params->IoReplyPacketSize = replyPacketSize;
  306. //
  307. // Hand a read request off to the thread pool.
  308. //
  309. params->completionEvent = CreateEvent(
  310. NULL, // no attribute.
  311. TRUE, // manual reset.
  312. FALSE, // initially not signalled.
  313. NULL // no name.
  314. );
  315. if (params->completionEvent == NULL) {
  316. *status = GetLastError();
  317. TRC_ERR((TB, _T("Error in CreateEvent: %08X."), *status));
  318. }
  319. else {
  320. params->thrPoolReq = _threadPool->SubmitRequest(
  321. _AsyncWaitOnMaskFunc, params,
  322. params->completionEvent
  323. );
  324. if (params->thrPoolReq == INVALID_THREADPOOLREQUEST) {
  325. *status = ERROR_SERVICE_NO_THREAD;
  326. }
  327. }
  328. Cleanup:
  329. //
  330. // If IO is pending, return the handle to the pending IO.
  331. //
  332. if (params->thrPoolReq != INVALID_THREADPOOLREQUEST) {
  333. *status = ERROR_IO_PENDING;
  334. DC_END_FN();
  335. return params->completionEvent;
  336. }
  337. //
  338. // Otherwise, clean up the event handle and return NULL so that the
  339. // CompleteIOFunc can be called to send the results to the server.
  340. //
  341. else {
  342. if (params->completionEvent != NULL) {
  343. CloseHandle(params->completionEvent);
  344. params->completionEvent = NULL;
  345. }
  346. DC_END_FN();
  347. return NULL;
  348. }
  349. }
  350. HANDLE
  351. W32DrPRT::_StartWaitOnMaskFunc(
  352. IN W32DRDEV_ASYNCIO_PARAMS *params,
  353. OUT DWORD *status
  354. )
  355. {
  356. return ((W32DrPRT*)params->pObject)->StartWaitOnMaskFunc(params, status);
  357. }
  358. DWORD
  359. W32DrPRT::AsyncWaitOnMaskFunc(
  360. IN W32DRDEV_ASYNCIO_PARAMS *params
  361. )
  362. /*++
  363. Routine Description:
  364. Start an asynchronous "wait on mask operation." Can't use
  365. overlapped IO for this function, so we run it in a pooled thread.
  366. Arguments:
  367. params - Context for the IO request.
  368. Return Value:
  369. Returns a handle the pending IO object if the operation did not
  370. complete. Otherwise, NULL is returned.
  371. --*/
  372. {
  373. DWORD status;
  374. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  375. LPDWORD serverEventMask;
  376. PBYTE outputBuf;
  377. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  378. HANDLE FileHandle;
  379. DC_BEGIN_FN("W32DrPRT::AsyncWaitOnMaskFunc");
  380. //
  381. // Assert the integrity of the IO context
  382. //
  383. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  384. //
  385. // Get the IO request.
  386. //
  387. pIoRequest = &params->pIoRequestPacket->IoRequest;
  388. //
  389. // Get Port Handle
  390. //
  391. FileHandle = GetPortHandle(pIoRequest->FileId);
  392. //
  393. // Get a pointer to the output buffer and server's event mask.
  394. //
  395. pReplyPacket = params->pIoReplyPacket;
  396. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  397. serverEventMask = (LPDWORD)outputBuf;
  398. //
  399. // Use WaitCommEvent to handle the request.
  400. //
  401. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  402. if (!WaitCommEvent(FileHandle, serverEventMask, NULL)) {
  403. status = GetLastError();
  404. TRC_ERR((TB, _T("Error %ld."), status));
  405. }
  406. else {
  407. TRC_NRM((TB, _T("Completed successfully.")));
  408. status = ERROR_SUCCESS;
  409. }
  410. DC_END_FN();
  411. return status;
  412. }
  413. DWORD
  414. W32DrPRT::_AsyncWaitOnMaskFunc(
  415. IN PVOID params,
  416. IN HANDLE cancelEvent
  417. )
  418. {
  419. return ((W32DrPRT*)(((W32DRDEV_ASYNCIO_PARAMS *)params)->pObject))->AsyncWaitOnMaskFunc(
  420. (W32DRDEV_ASYNCIO_PARAMS *)params);
  421. }
  422. #endif
  423. void
  424. W32DrPRT::SerialSetTimeouts(
  425. IN PRDPDR_IOREQUEST_PACKET pIoReq
  426. )
  427. /*++
  428. Routine Description:
  429. Handle Serial Port Set Timeouts Request from Server.
  430. Arguments:
  431. pIoReq - Request packet received from server.
  432. Return Value:
  433. NA
  434. --*/
  435. {
  436. PBYTE inputBuf;
  437. NTSTATUS status = STATUS_SUCCESS;
  438. COMMTIMEOUTS commTimeouts;
  439. PSERIAL_TIMEOUTS newTimeouts;
  440. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  441. HANDLE FileHandle;
  442. DC_BEGIN_FN("W32DrPRT::SerialSetTimeouts");
  443. TRACEREQ(pIoReq);
  444. //
  445. // Get the IO request.
  446. //
  447. pIoRequest = &pIoReq->IoRequest;
  448. //
  449. // Get Port Handle
  450. //
  451. FileHandle = GetPortHandle(pIoRequest->FileId);
  452. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  453. //
  454. // Check the size of the incoming request.
  455. //
  456. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_TIMEOUTS));
  457. //
  458. // Get a pointer to the input buffer.
  459. //
  460. inputBuf = (PBYTE)(pIoReq + 1);
  461. //
  462. // Error check the timeout settings.
  463. //
  464. if (status == STATUS_SUCCESS) {
  465. newTimeouts = (PSERIAL_TIMEOUTS)inputBuf;
  466. if ((newTimeouts->ReadIntervalTimeout == MAXULONG) &&
  467. (newTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
  468. (newTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
  469. TRC_ERR((TB, _T("Invalid timeout parameters.")));
  470. status = STATUS_INVALID_PARAMETER;
  471. }
  472. }
  473. //
  474. // Set the new timeouts.
  475. //
  476. if (status == STATUS_SUCCESS) {
  477. commTimeouts.ReadIntervalTimeout = newTimeouts->ReadIntervalTimeout;
  478. commTimeouts.ReadTotalTimeoutMultiplier = newTimeouts->ReadTotalTimeoutMultiplier;
  479. commTimeouts.ReadTotalTimeoutConstant = newTimeouts->ReadTotalTimeoutConstant;
  480. commTimeouts.WriteTotalTimeoutMultiplier = newTimeouts->WriteTotalTimeoutMultiplier;
  481. commTimeouts.WriteTotalTimeoutConstant = newTimeouts->WriteTotalTimeoutConstant;
  482. if (!SetCommTimeouts(FileHandle, &commTimeouts)) {
  483. DWORD err = GetLastError();
  484. TRC_ALT((TB, _T("SetCommTimeouts failed with %08x"), err));
  485. status = TranslateWinError(err);
  486. }
  487. }
  488. //
  489. // Send the results to the server.
  490. //
  491. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  492. DefaultIORequestMsgHandle(pIoReq, status);
  493. DC_END_FN();
  494. }
  495. void
  496. W32DrPRT::SerialGetTimeouts(
  497. IN PRDPDR_IOREQUEST_PACKET pIoReq
  498. )
  499. /*++
  500. Routine Description:
  501. Handle Serial Port Get Timeouts Request from Server.
  502. Arguments:
  503. pIoReq - Request packet received from server.
  504. Return Value:
  505. NA
  506. --*/
  507. {
  508. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  509. NTSTATUS status = STATUS_SUCCESS;
  510. ULONG replyPacketSize;
  511. PBYTE outputBuf;
  512. PSERIAL_TIMEOUTS st;
  513. COMMTIMEOUTS ct;
  514. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  515. HANDLE FileHandle;
  516. DC_BEGIN_FN("W32DrPRT::SerialGetTimeouts");
  517. TRACEREQ(pIoReq);
  518. //
  519. // Get the IO request.
  520. //
  521. pIoRequest = &pIoReq->IoRequest;
  522. //
  523. // Get Port Handle
  524. //
  525. FileHandle = GetPortHandle(pIoRequest->FileId);
  526. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  527. //
  528. // Check the size of the output buffer.
  529. //
  530. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_TIMEOUTS));
  531. //
  532. // Allocate reply buffer.
  533. //
  534. if (status == STATUS_SUCCESS) {
  535. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  536. }
  537. //
  538. // Get the current timeout values.
  539. //
  540. if (status == STATUS_SUCCESS) {
  541. //
  542. // Get a pointer to the output buffer and the server timeout values.
  543. //
  544. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  545. st = (PSERIAL_TIMEOUTS)outputBuf;
  546. //
  547. // Get the client timeout values.
  548. //
  549. if (GetCommTimeouts(FileHandle, &ct)) {
  550. st->ReadIntervalTimeout = ct.ReadIntervalTimeout;
  551. st->ReadTotalTimeoutMultiplier = ct.ReadTotalTimeoutMultiplier;
  552. st->ReadTotalTimeoutConstant = ct.ReadTotalTimeoutConstant;
  553. st->WriteTotalTimeoutMultiplier = ct.WriteTotalTimeoutMultiplier;
  554. st->WriteTotalTimeoutConstant = ct.WriteTotalTimeoutConstant;
  555. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  556. = sizeof(SERIAL_TIMEOUTS);
  557. }
  558. else {
  559. DWORD err = GetLastError();
  560. TRC_ALT((TB, _T("GetCommTimeouts failed with %08x"), err));
  561. status = TranslateWinError(err);
  562. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  563. = 0;
  564. replyPacketSize = (ULONG)FIELD_OFFSET(
  565. RDPDR_IOCOMPLETION_PACKET,
  566. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  567. }
  568. //
  569. // Finish the response and send it.
  570. //
  571. pReplyPacket->IoCompletion.IoStatus = status;
  572. TRACERESP(pIoReq, pReplyPacket);
  573. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  574. }
  575. else {
  576. //
  577. // Send the results to the server.
  578. //
  579. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  580. DefaultIORequestMsgHandle(pIoReq, status);
  581. }
  582. DC_END_FN();
  583. }
  584. void
  585. W32DrPRT::SerialSetChars(
  586. IN PRDPDR_IOREQUEST_PACKET pIoReq
  587. )
  588. /*++
  589. Routine Description:
  590. Handle Serial Port Set Chars Request from Server.
  591. Arguments:
  592. pIoReq - Request packet received from server.
  593. Return Value:
  594. NA
  595. --*/
  596. {
  597. PBYTE inputBuf;
  598. NTSTATUS status = STATUS_SUCCESS;
  599. DCB dcb;
  600. PSERIAL_CHARS serverChars;
  601. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  602. HANDLE FileHandle;
  603. DC_BEGIN_FN("W32DrPRT::SerialSetChars");
  604. TRACEREQ(pIoReq);
  605. //
  606. // Get the IO request.
  607. //
  608. pIoRequest = &pIoReq->IoRequest;
  609. //
  610. // Get Port Handle
  611. //
  612. FileHandle = GetPortHandle(pIoRequest->FileId);
  613. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  614. //
  615. // Check the size of the incoming request.
  616. //
  617. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_CHARS));
  618. //
  619. // Get a pointer to the input buffer and the server serial characters
  620. // buffer.
  621. //
  622. inputBuf = (PBYTE)(pIoReq + 1);
  623. serverChars = (PSERIAL_CHARS)inputBuf;
  624. //
  625. // Get the current DCB.
  626. //
  627. if (status == STATUS_SUCCESS) {
  628. if (!GetCommState(FileHandle, &dcb)) {
  629. DWORD err = GetLastError();
  630. TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
  631. status = TranslateWinError(err);
  632. }
  633. }
  634. //
  635. // Set the comm chars and update the DCB.
  636. //
  637. if (status == STATUS_SUCCESS) {
  638. dcb.XonChar = serverChars->XonChar;
  639. dcb.XoffChar = serverChars->XoffChar;
  640. dcb.ErrorChar = serverChars->ErrorChar;
  641. dcb.ErrorChar = serverChars->BreakChar;
  642. dcb.EofChar = serverChars->EofChar;
  643. dcb.EvtChar = serverChars->EventChar;
  644. if (!SetCommState(FileHandle, &dcb)) {
  645. DWORD err = GetLastError();
  646. TRC_ALT((TB, _T("SetCommState failed with %08x"), err));
  647. status = TranslateWinError(err);
  648. }
  649. }
  650. //
  651. // Send the results to the server.
  652. //
  653. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  654. DefaultIORequestMsgHandle(pIoReq, status);
  655. DC_END_FN();
  656. }
  657. void
  658. W32DrPRT::SerialGetChars(
  659. IN PRDPDR_IOREQUEST_PACKET pIoReq
  660. )
  661. /*++
  662. Routine Description:
  663. Handle Serial Port Get Chars Request from Server.
  664. Arguments:
  665. pIoReq - Request packet received from server.
  666. Return Value:
  667. NA
  668. --*/
  669. {
  670. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  671. NTSTATUS status = STATUS_SUCCESS;
  672. DCB dcb;
  673. ULONG replyPacketSize;
  674. PBYTE outputBuf;
  675. PSERIAL_CHARS serverChars;
  676. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  677. HANDLE FileHandle;
  678. DC_BEGIN_FN("W32DrPRT::SerialGetChars");
  679. TRACEREQ(pIoReq);
  680. //
  681. // Get the IO request.
  682. //
  683. pIoRequest = &pIoReq->IoRequest;
  684. //
  685. // Get Port Handle
  686. //
  687. FileHandle = GetPortHandle(pIoRequest->FileId);
  688. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  689. //
  690. // Check the size of the output buffer.
  691. //
  692. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_CHARS));
  693. //
  694. // Allocate reply buffer.
  695. //
  696. if (status == STATUS_SUCCESS) {
  697. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  698. }
  699. //
  700. // Get the current DCB and grab the control character params.
  701. //
  702. if (status == STATUS_SUCCESS) {
  703. //
  704. // Get a pointer to the output buffer and control charcter params.
  705. //
  706. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  707. serverChars = (PSERIAL_CHARS)outputBuf;
  708. if (GetCommState(FileHandle, &dcb)) {
  709. serverChars->XonChar = dcb.XonChar;
  710. serverChars->XoffChar = dcb.XoffChar;
  711. serverChars->ErrorChar = dcb.ErrorChar;
  712. serverChars->BreakChar = dcb.ErrorChar;
  713. serverChars->EofChar = dcb.EofChar;
  714. serverChars->EventChar = dcb.EvtChar;
  715. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  716. = sizeof(SERIAL_CHARS);
  717. }
  718. else {
  719. DWORD err = GetLastError();
  720. TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
  721. status = TranslateWinError(err);
  722. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  723. = 0;
  724. replyPacketSize = (ULONG)FIELD_OFFSET(
  725. RDPDR_IOCOMPLETION_PACKET,
  726. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  727. }
  728. //
  729. // Finish the response and send it.
  730. //
  731. pReplyPacket->IoCompletion.IoStatus = status;
  732. TRACERESP(pIoReq, pReplyPacket);
  733. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  734. }
  735. else {
  736. //
  737. // Send the results to the server.
  738. //
  739. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  740. DefaultIORequestMsgHandle(pIoReq, status);
  741. }
  742. DC_END_FN();
  743. }
  744. void
  745. W32DrPRT::SerialResetDevice(
  746. IN PRDPDR_IOREQUEST_PACKET pIoReq
  747. )
  748. /*++
  749. Routine Description:
  750. Handle Serial Port Reset Device Request from Server.
  751. Arguments:
  752. pIoReq - Request packet received from server.
  753. Return Value:
  754. NA
  755. --*/
  756. {
  757. DC_BEGIN_FN("W32DrPRT::SerialResetDevice");
  758. TRACEREQ(pIoReq);
  759. //
  760. // Send the escape code to the serial port.
  761. //
  762. SerialHandleEscapeCode(pIoReq, RESETDEV);
  763. DC_END_FN();
  764. }
  765. void
  766. W32DrPRT::SerialSetQueueSize(
  767. IN PRDPDR_IOREQUEST_PACKET pIoReq
  768. )
  769. /*++
  770. Routine Description:
  771. Handle Serial Port Set Queue Size Request from Server.
  772. Arguments:
  773. pIoReq - Request packet received from server.
  774. Return Value:
  775. NA
  776. --*/
  777. {
  778. PBYTE inputBuf;
  779. NTSTATUS status = STATUS_SUCCESS;
  780. PSERIAL_QUEUE_SIZE serverQueueSize;
  781. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  782. HANDLE FileHandle;
  783. DC_BEGIN_FN("W32DrPRT::SerialSetQueueSize");
  784. TRACEREQ(pIoReq);
  785. //
  786. // Get the IO request.
  787. //
  788. pIoRequest = &pIoReq->IoRequest;
  789. //
  790. // Get Port Handle
  791. //
  792. FileHandle = GetPortHandle(pIoRequest->FileId);
  793. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  794. //
  795. // Check the size of the incoming request.
  796. //
  797. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_QUEUE_SIZE));
  798. //
  799. // Get a pointer to the input buffer and the server serial characters
  800. // buffer.
  801. //
  802. inputBuf = (PBYTE)(pIoReq + 1);
  803. serverQueueSize = (PSERIAL_QUEUE_SIZE)inputBuf;
  804. //
  805. // Set the queue size.
  806. //
  807. if (status == STATUS_SUCCESS) {
  808. if (!SetupComm(FileHandle, serverQueueSize->InSize,
  809. serverQueueSize->OutSize)) {
  810. DWORD err = GetLastError();
  811. TRC_ALT((TB, _T("SetCommState failed with %08x"), err));
  812. status = TranslateWinError(err);
  813. }
  814. }
  815. //
  816. // Send the results to the server.
  817. //
  818. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  819. DefaultIORequestMsgHandle(pIoReq, status);
  820. DC_END_FN();
  821. }
  822. void
  823. W32DrPRT::SerialGetWaitMask(
  824. IN PRDPDR_IOREQUEST_PACKET pIoReq
  825. )
  826. /*++
  827. Routine Description
  828. Handle Serial Port Get Wait Mask Request from Server.
  829. Arguments:
  830. pIoReq - Request packet received from server.
  831. Return Value:
  832. NA
  833. --*/
  834. {
  835. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  836. NTSTATUS status = STATUS_SUCCESS;
  837. ULONG replyPacketSize;
  838. PBYTE outputBuf;
  839. ULONG *serverWaitMask;
  840. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  841. HANDLE FileHandle;
  842. DC_BEGIN_FN("W32DrPRT::SerialGetWaitMask");
  843. TRACEREQ(pIoReq);
  844. //
  845. // Get the IO request.
  846. //
  847. pIoRequest = &pIoReq->IoRequest;
  848. //
  849. // Get Port Handle
  850. //
  851. FileHandle = GetPortHandle(pIoRequest->FileId);
  852. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  853. //
  854. // Check the size of the output buffer.
  855. //
  856. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(ULONG));
  857. //
  858. // Allocate reply buffer.
  859. //
  860. if (status == STATUS_SUCCESS) {
  861. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  862. }
  863. //
  864. // Get the current wait mask.
  865. //
  866. if (status == STATUS_SUCCESS) {
  867. //
  868. // Get a pointer to the output buffer server's wait mask.
  869. //
  870. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  871. serverWaitMask = (ULONG *)outputBuf;
  872. if (GetCommMask(FileHandle, serverWaitMask)) {
  873. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  874. = sizeof(ULONG);
  875. }
  876. else {
  877. DWORD err = GetLastError();
  878. TRC_ALT((TB, _T("GetCommMask failed with %08x"), err));
  879. status = TranslateWinError(err);
  880. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  881. = 0;
  882. replyPacketSize = (ULONG)FIELD_OFFSET(
  883. RDPDR_IOCOMPLETION_PACKET,
  884. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  885. }
  886. //
  887. // Finish the response and send it.
  888. //
  889. pReplyPacket->IoCompletion.IoStatus = status;
  890. TRACERESP(pIoReq, pReplyPacket);
  891. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  892. }
  893. else {
  894. //
  895. // Send the results to the server.
  896. //
  897. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  898. DefaultIORequestMsgHandle(pIoReq, status);
  899. }
  900. DC_END_FN();
  901. }
  902. void
  903. W32DrPRT::SerialSetWaitMask(
  904. IN PRDPDR_IOREQUEST_PACKET pIoReq
  905. )
  906. /*++
  907. Routine Description:
  908. Handle Serial Port Set Wait Mask Request from Server.
  909. Arguments:
  910. pIoReq - Request packet received from server.
  911. Return Value:
  912. NA
  913. --*/
  914. {
  915. PBYTE inputBuf;
  916. NTSTATUS status = STATUS_SUCCESS;
  917. ULONG *serverWaitMask;
  918. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  919. HANDLE FileHandle;
  920. DC_BEGIN_FN("W32DrPRT::SerialSetWaitMask");
  921. TRACEREQ(pIoReq);
  922. //
  923. // Get the IO request.
  924. //
  925. pIoRequest = &pIoReq->IoRequest;
  926. //
  927. // Get Port Handle
  928. //
  929. FileHandle = GetPortHandle(pIoRequest->FileId);
  930. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  931. //
  932. // Check the size of the incoming request.
  933. //
  934. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(ULONG));
  935. //
  936. // Get a pointer to the input buffer server's wait mask.
  937. //
  938. inputBuf = (PBYTE)(pIoReq + 1);
  939. serverWaitMask = (ULONG *)inputBuf;
  940. //
  941. // Set the mask.
  942. //
  943. if (status == STATUS_SUCCESS) {
  944. if (!SetCommMask(FileHandle, *serverWaitMask)) {
  945. DWORD err = GetLastError();
  946. TRC_ALT((TB, _T("SetCommMask failed with %08x"), err));
  947. status = TranslateWinError(err);
  948. }
  949. }
  950. //
  951. // Send the results to the server.
  952. //
  953. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  954. DefaultIORequestMsgHandle(pIoReq, status);
  955. DC_END_FN();
  956. }
  957. void
  958. W32DrPRT::SerialWaitOnMask(
  959. IN PRDPDR_IOREQUEST_PACKET pIoReq
  960. )
  961. /*++
  962. Routine Description:
  963. Handle Serial Port Wait on Mask Request from Server.
  964. Arguments:
  965. pIoReq - Request packet received from server.
  966. Return Value:
  967. NA
  968. --*/
  969. {
  970. DWORD status;
  971. #ifdef OS_WINCE
  972. W32DRDEV_ASYNCIO_PARAMS *params = NULL;
  973. #else
  974. W32DRDEV_OVERLAPPEDIO_PARAMS *params = NULL;
  975. #endif
  976. DWORD ntStatus;
  977. DC_BEGIN_FN("W32DrPRT::SerialWaitOnMask");
  978. TRACEREQ(pIoReq);
  979. //
  980. // Check the size of the output buffer.
  981. //
  982. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(DWORD));
  983. //
  984. // Allocate and dispatch an asynchronous IO request.
  985. //
  986. if (status == ERROR_SUCCESS) {
  987. #ifdef OS_WINCE
  988. params = new W32DRDEV_ASYNCIO_PARAMS(this, pIoReq);
  989. #else
  990. params = new W32DRDEV_OVERLAPPEDIO_PARAMS(this, pIoReq);
  991. #endif
  992. if (params != NULL ) {
  993. status = ProcessObject()->DispatchAsyncIORequest(
  994. (RDPAsyncFunc_StartIO)
  995. W32DrPRT::_StartWaitOnMaskFunc,
  996. (RDPAsyncFunc_IOComplete)_CompleteIOFunc,
  997. (RDPAsyncFunc_IOCancel)_CancelIOFunc,
  998. params
  999. );
  1000. }
  1001. else {
  1002. TRC_ERR((TB, _T("Memory alloc failed.")));
  1003. status = ERROR_NOT_ENOUGH_MEMORY;
  1004. }
  1005. }
  1006. //
  1007. // Translate to a Windows error status.
  1008. //
  1009. ntStatus = TranslateWinError(status);
  1010. //
  1011. // Clean up on error.
  1012. //
  1013. if (status != ERROR_SUCCESS) {
  1014. if (params != NULL) {
  1015. delete params;
  1016. }
  1017. //
  1018. // Send the results to the server.
  1019. //
  1020. DefaultIORequestMsgHandle(pIoReq, ntStatus);
  1021. }
  1022. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, ntStatus);
  1023. DC_END_FN();
  1024. }
  1025. void
  1026. W32DrPRT::SerialPurge(
  1027. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. Handle Serial Port Serial Purge Request from Server.
  1032. Arguments:
  1033. pIoReq - Request packet received from server.
  1034. Return Value:
  1035. NA
  1036. --*/
  1037. {
  1038. PBYTE inputBuf;
  1039. NTSTATUS status = STATUS_SUCCESS;
  1040. DWORD *purgeFlags;
  1041. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1042. HANDLE FileHandle;
  1043. DC_BEGIN_FN("W32DrPRT::SerialPurge");
  1044. TRACEREQ(pIoReq);
  1045. //
  1046. // Get the IO request.
  1047. //
  1048. pIoRequest = &pIoReq->IoRequest;
  1049. //
  1050. // Get Port Handle
  1051. //
  1052. FileHandle = GetPortHandle(pIoRequest->FileId);
  1053. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1054. //
  1055. // Check the size of the incoming request.
  1056. //
  1057. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(DWORD));
  1058. //
  1059. // Get a pointer to the input buffer and purge flags.
  1060. //
  1061. inputBuf = (PBYTE)(pIoReq + 1);
  1062. purgeFlags = (DWORD *)inputBuf;
  1063. //
  1064. // Purge.
  1065. //
  1066. if (status == STATUS_SUCCESS) {
  1067. if (!PurgeComm(FileHandle, *purgeFlags)) {
  1068. DWORD err = GetLastError();
  1069. TRC_ALT((TB, _T("PurgeComm failed with %08x"), err));
  1070. status = TranslateWinError(err);
  1071. }
  1072. }
  1073. //
  1074. // Send the results to the server.
  1075. //
  1076. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1077. DefaultIORequestMsgHandle(pIoReq, status);
  1078. DC_END_FN();
  1079. }
  1080. void
  1081. W32DrPRT::SerialGetHandflow(
  1082. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. Handle Serial Port Get Handflow Request from Server.
  1087. Arguments:
  1088. pIoReq - Request packet received from server.
  1089. Return Value:
  1090. NA
  1091. --*/
  1092. {
  1093. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1094. NTSTATUS status = STATUS_SUCCESS;
  1095. DCB dcb;
  1096. ULONG replyPacketSize;
  1097. PBYTE outputBuf;
  1098. PSERIAL_HANDFLOW handFlow;
  1099. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1100. HANDLE FileHandle;
  1101. DC_BEGIN_FN("W32DrPRT::SerialGetHandflow");
  1102. TRACEREQ(pIoReq);
  1103. //
  1104. // Get the IO request.
  1105. //
  1106. pIoRequest = &pIoReq->IoRequest;
  1107. //
  1108. // Get Port Handle
  1109. //
  1110. FileHandle = GetPortHandle(pIoRequest->FileId);
  1111. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1112. //
  1113. // Check the size of the output buffer.
  1114. //
  1115. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_HANDFLOW));
  1116. //
  1117. // Allocate reply buffer.
  1118. //
  1119. if (status == STATUS_SUCCESS) {
  1120. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1121. }
  1122. //
  1123. // Get the current DCB.
  1124. //
  1125. if (status == STATUS_SUCCESS) {
  1126. //
  1127. // Get a pointer to the output buffer server's serial hand flow struct.
  1128. //
  1129. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1130. handFlow = (PSERIAL_HANDFLOW)outputBuf;
  1131. if (GetCommState(FileHandle, &dcb)) {
  1132. //
  1133. // Set the hand flow fields based on the current value of fields
  1134. // in the DCB.
  1135. //
  1136. memset(handFlow, 0, sizeof(SERIAL_HANDFLOW));
  1137. //
  1138. // RTS Settings
  1139. //
  1140. handFlow->FlowReplace &= ~SERIAL_RTS_MASK;
  1141. switch (dcb.fRtsControl) {
  1142. case RTS_CONTROL_DISABLE:
  1143. break;
  1144. case RTS_CONTROL_ENABLE:
  1145. handFlow->FlowReplace |= SERIAL_RTS_CONTROL;
  1146. break;
  1147. case RTS_CONTROL_HANDSHAKE:
  1148. handFlow->FlowReplace |= SERIAL_RTS_HANDSHAKE;
  1149. break;
  1150. case RTS_CONTROL_TOGGLE:
  1151. handFlow->FlowReplace |= SERIAL_TRANSMIT_TOGGLE;
  1152. break;
  1153. default:
  1154. // Don't think this should ever happen?
  1155. ASSERT(FALSE);
  1156. }
  1157. //
  1158. // DTR Settings
  1159. //
  1160. handFlow->ControlHandShake &= ~SERIAL_DTR_MASK;
  1161. switch (dcb.fDtrControl) {
  1162. case DTR_CONTROL_DISABLE:
  1163. break;
  1164. case DTR_CONTROL_ENABLE:
  1165. handFlow->ControlHandShake |= SERIAL_DTR_CONTROL;
  1166. break;
  1167. case DTR_CONTROL_HANDSHAKE:
  1168. handFlow->ControlHandShake |= SERIAL_DTR_HANDSHAKE;
  1169. break;
  1170. default:
  1171. // Don't think this should ever happen?
  1172. ASSERT(FALSE);
  1173. }
  1174. if (dcb.fDsrSensitivity) {
  1175. handFlow->ControlHandShake |= SERIAL_DSR_SENSITIVITY;
  1176. }
  1177. if (dcb.fOutxCtsFlow) {
  1178. handFlow->ControlHandShake |= SERIAL_CTS_HANDSHAKE;
  1179. }
  1180. if (dcb.fOutxDsrFlow) {
  1181. handFlow->ControlHandShake |= SERIAL_DSR_HANDSHAKE;
  1182. }
  1183. if (dcb.fOutX) {
  1184. handFlow->FlowReplace |= SERIAL_AUTO_TRANSMIT;
  1185. }
  1186. if (dcb.fInX) {
  1187. handFlow->FlowReplace |= SERIAL_AUTO_RECEIVE;
  1188. }
  1189. if (dcb.fNull) {
  1190. handFlow->FlowReplace |= SERIAL_NULL_STRIPPING;
  1191. }
  1192. if (dcb.fErrorChar) {
  1193. handFlow->FlowReplace |= SERIAL_ERROR_CHAR;
  1194. }
  1195. if (dcb.fTXContinueOnXoff) {
  1196. handFlow->FlowReplace |= SERIAL_XOFF_CONTINUE;
  1197. }
  1198. if (dcb.fAbortOnError) {
  1199. handFlow->ControlHandShake |= SERIAL_ERROR_ABORT;
  1200. }
  1201. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1202. = sizeof(SERIAL_HANDFLOW);
  1203. }
  1204. else {
  1205. DWORD err = GetLastError();
  1206. TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
  1207. status = TranslateWinError(err);
  1208. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1209. = 0;
  1210. replyPacketSize = (ULONG)FIELD_OFFSET(
  1211. RDPDR_IOCOMPLETION_PACKET,
  1212. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1213. }
  1214. //
  1215. // Finish the response and send it.
  1216. //
  1217. pReplyPacket->IoCompletion.IoStatus = status;
  1218. TRACERESP(pIoReq, pReplyPacket);
  1219. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1220. }
  1221. else {
  1222. //
  1223. // Send the results to the server.
  1224. //
  1225. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1226. DefaultIORequestMsgHandle(pIoReq, status);
  1227. }
  1228. DC_END_FN();
  1229. }
  1230. void
  1231. W32DrPRT::SerialSetHandflow(
  1232. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. Handle Serial Port Set Handflow Request from Server.
  1237. Arguments:
  1238. pIoReq - Request packet received from server.
  1239. Return Value:
  1240. NA
  1241. --*/
  1242. {
  1243. PBYTE inputBuf;
  1244. NTSTATUS status = STATUS_SUCCESS;
  1245. DCB dcb;
  1246. PSERIAL_HANDFLOW handFlow;
  1247. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1248. HANDLE FileHandle;
  1249. DC_BEGIN_FN("W32DrPRT::SerialSetHandflow");
  1250. //
  1251. // Check the size of the incoming request.
  1252. //
  1253. status = DrUTL_CheckIOBufInputSize(pIoReq, sizeof(SERIAL_HANDFLOW));
  1254. TRACEREQ(pIoReq);
  1255. //
  1256. // Get the IO request.
  1257. //
  1258. pIoRequest = &pIoReq->IoRequest;
  1259. //
  1260. // Get Port Handle
  1261. //
  1262. FileHandle = GetPortHandle(pIoRequest->FileId);
  1263. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1264. //
  1265. // Get a pointer to the input buffer and the server serial characters
  1266. // buffer.
  1267. //
  1268. inputBuf = (PBYTE)(pIoReq + 1);
  1269. handFlow = (PSERIAL_HANDFLOW)inputBuf;
  1270. //
  1271. // Get the current DCB.
  1272. //
  1273. if (status == STATUS_SUCCESS) {
  1274. if (!GetCommState(FileHandle, &dcb)) {
  1275. DWORD err = GetLastError();
  1276. TRC_ALT((TB, _T("GetCommState failed with %08x"), err));
  1277. status = TranslateWinError(err);
  1278. }
  1279. }
  1280. //
  1281. // Update the DCB based on the new server-side handflow values.
  1282. //
  1283. if (status == STATUS_SUCCESS) {
  1284. if (handFlow->ControlHandShake & SERIAL_CTS_HANDSHAKE) {
  1285. dcb.fOutxCtsFlow = TRUE;
  1286. }
  1287. if (handFlow->ControlHandShake & SERIAL_DSR_HANDSHAKE) {
  1288. dcb.fOutxDsrFlow = TRUE;
  1289. }
  1290. if (handFlow->FlowReplace & SERIAL_AUTO_TRANSMIT) {
  1291. dcb.fOutX = TRUE;
  1292. }
  1293. if (handFlow->FlowReplace & SERIAL_AUTO_RECEIVE) {
  1294. dcb.fInX = TRUE;
  1295. }
  1296. if (handFlow->FlowReplace & SERIAL_NULL_STRIPPING) {
  1297. dcb.fNull = TRUE;
  1298. }
  1299. if (handFlow->FlowReplace & SERIAL_ERROR_CHAR) {
  1300. dcb.fErrorChar = TRUE;
  1301. }
  1302. if (handFlow->FlowReplace & SERIAL_XOFF_CONTINUE) {
  1303. dcb.fTXContinueOnXoff = TRUE;
  1304. }
  1305. if (handFlow->ControlHandShake & SERIAL_ERROR_ABORT) {
  1306. dcb.fAbortOnError = TRUE;
  1307. }
  1308. switch (handFlow->FlowReplace & SERIAL_RTS_MASK) {
  1309. case 0:
  1310. dcb.fRtsControl = RTS_CONTROL_DISABLE;
  1311. break;
  1312. case SERIAL_RTS_CONTROL:
  1313. dcb.fRtsControl = RTS_CONTROL_ENABLE;
  1314. break;
  1315. case SERIAL_RTS_HANDSHAKE:
  1316. dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  1317. break;
  1318. case SERIAL_TRANSMIT_TOGGLE:
  1319. dcb.fRtsControl = RTS_CONTROL_TOGGLE;
  1320. break;
  1321. }
  1322. switch (handFlow->ControlHandShake & SERIAL_DTR_MASK) {
  1323. case 0:
  1324. dcb.fDtrControl = DTR_CONTROL_DISABLE;
  1325. break;
  1326. case SERIAL_DTR_CONTROL:
  1327. dcb.fDtrControl = DTR_CONTROL_ENABLE;
  1328. break;
  1329. case SERIAL_DTR_HANDSHAKE:
  1330. dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
  1331. break;
  1332. }
  1333. dcb.fDsrSensitivity =
  1334. (handFlow->ControlHandShake & SERIAL_DSR_SENSITIVITY)?(TRUE):(FALSE);
  1335. dcb.XonLim = (WORD)handFlow->XonLimit;
  1336. dcb.XoffLim = (WORD)handFlow->XoffLimit;
  1337. }
  1338. //
  1339. // Update the DCB.
  1340. //
  1341. if (status == STATUS_SUCCESS) {
  1342. if (!SetCommState(FileHandle, &dcb)) {
  1343. DWORD err = GetLastError();
  1344. TRC_NRM((TB, _T("SetCommState failed with %08x"), err));
  1345. status = TranslateWinError(err);
  1346. }
  1347. }
  1348. //
  1349. // Send the results to the server.
  1350. //
  1351. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1352. DefaultIORequestMsgHandle(pIoReq, status);
  1353. DC_END_FN();
  1354. }
  1355. void
  1356. W32DrPRT::SerialGetModemStatus(
  1357. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. Handle Serial Port Get Modem Status Request from Server.
  1362. Arguments:
  1363. pIoReq - Request packet received from server.
  1364. Return Value:
  1365. NA
  1366. --*/
  1367. {
  1368. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1369. NTSTATUS status = STATUS_SUCCESS;
  1370. ULONG replyPacketSize;
  1371. PBYTE outputBuf;
  1372. LPDWORD modemStatus;
  1373. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1374. HANDLE FileHandle;
  1375. DC_BEGIN_FN("W32DrPRT::SerialGetModemStatus");
  1376. TRACEREQ(pIoReq);
  1377. //
  1378. // Get the IO request.
  1379. //
  1380. pIoRequest = &pIoReq->IoRequest;
  1381. //
  1382. // Get Port Handle
  1383. //
  1384. FileHandle = GetPortHandle(pIoRequest->FileId);
  1385. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1386. //
  1387. // Check the size of the output buffer.
  1388. //
  1389. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(DWORD));
  1390. //
  1391. // Allocate reply buffer.
  1392. //
  1393. if (status == STATUS_SUCCESS) {
  1394. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1395. }
  1396. //
  1397. // Get the current modem status.
  1398. //
  1399. if (status == STATUS_SUCCESS) {
  1400. //
  1401. // Get a pointer to the output buffer server's modem status.
  1402. //
  1403. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1404. modemStatus = (LPDWORD)outputBuf;
  1405. if (GetCommModemStatus(FileHandle, modemStatus)) {
  1406. TRC_NRM((TB, _T("GetCommModemStatus result: 0x%08x"), *modemStatus));
  1407. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1408. = sizeof(DWORD);
  1409. }
  1410. else {
  1411. DWORD err = GetLastError();
  1412. TRC_ERR((TB, _T("GetCommModemStatus failed with 0x%08x"), err));
  1413. status = TranslateWinError(err);
  1414. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1415. = 0;
  1416. replyPacketSize = (ULONG)FIELD_OFFSET(
  1417. RDPDR_IOCOMPLETION_PACKET,
  1418. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1419. }
  1420. //
  1421. // Finish the response and send it.
  1422. //
  1423. pReplyPacket->IoCompletion.IoStatus = status;
  1424. TRACERESP(pIoReq, pReplyPacket);
  1425. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1426. }
  1427. else {
  1428. //
  1429. // Send the results to the server.
  1430. //
  1431. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1432. DefaultIORequestMsgHandle(pIoReq, status);
  1433. }
  1434. DC_END_FN();
  1435. }
  1436. void
  1437. W32DrPRT::SerialGetDTRRTS(
  1438. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1439. )
  1440. /*++
  1441. Routine Description:
  1442. Handle Serial Port Get DTRRRTS Request from Server.
  1443. Arguments:
  1444. pIoReq - Request packet received from server.
  1445. Return Value:
  1446. NA
  1447. --*/
  1448. {
  1449. //
  1450. // This IOCTL is not supported by Win32 COMM functions. What
  1451. // else can we do, but pass it directly to the driver. We should ASSERT
  1452. // to find out under which circumstances this happens, however.
  1453. //
  1454. DC_BEGIN_FN("W32DrPRT::SerialGetDTRRTS");
  1455. TRACEREQ(pIoReq);
  1456. ASSERT(FALSE);
  1457. DispatchIOCTLDirectlyToDriver(pIoReq);
  1458. DC_END_FN();
  1459. }
  1460. void
  1461. W32DrPRT::SerialGetCommStatus(
  1462. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Handle Serial Port Get Comm Status Request from Server.
  1467. Arguments:
  1468. pIoReq - Request packet received from server.
  1469. Return Value:
  1470. NA
  1471. --*/
  1472. {
  1473. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1474. NTSTATUS status = STATUS_SUCCESS;
  1475. ULONG replyPacketSize;
  1476. PBYTE outputBuf;
  1477. PSERIAL_STATUS serverCommStatus;
  1478. COMSTAT localStatus;
  1479. DWORD errors;
  1480. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1481. HANDLE FileHandle;
  1482. DC_BEGIN_FN("W32DrPRT::SerialGetCommStatus");
  1483. TRACEREQ(pIoReq);
  1484. //
  1485. // Get the IO request.
  1486. //
  1487. pIoRequest = &pIoReq->IoRequest;
  1488. //
  1489. // Get Port Handle
  1490. //
  1491. FileHandle = GetPortHandle(pIoRequest->FileId);
  1492. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1493. //
  1494. // Check the size of the output buffer.
  1495. //
  1496. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_STATUS));
  1497. //
  1498. // Allocate reply buffer.
  1499. //
  1500. if (status == STATUS_SUCCESS) {
  1501. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1502. }
  1503. //
  1504. // Get the current communications status (via the ClearCommError API).
  1505. //
  1506. if (status == STATUS_SUCCESS) {
  1507. //
  1508. // Get a pointer to the output buffer server's modem status.
  1509. //
  1510. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1511. serverCommStatus = (PSERIAL_STATUS)outputBuf;
  1512. if (ClearCommError(FileHandle, &errors, &localStatus)) {
  1513. //
  1514. // Convert to server-representation of communication status.
  1515. //
  1516. serverCommStatus->HoldReasons = 0;
  1517. if (localStatus.fCtsHold) {
  1518. serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
  1519. }
  1520. if (localStatus.fDsrHold) {
  1521. serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR;
  1522. }
  1523. if (localStatus.fRlsdHold) {
  1524. serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD;
  1525. }
  1526. if (localStatus.fXoffHold) {
  1527. serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
  1528. }
  1529. if (localStatus.fXoffSent) {
  1530. serverCommStatus->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
  1531. }
  1532. serverCommStatus->EofReceived = (BOOLEAN)localStatus.fEof;
  1533. serverCommStatus->WaitForImmediate = (BOOLEAN)localStatus.fTxim;
  1534. serverCommStatus->AmountInInQueue = localStatus.cbInQue;
  1535. serverCommStatus->AmountInOutQueue = localStatus.cbOutQue;
  1536. serverCommStatus->Errors = 0;
  1537. if (errors & CE_BREAK) {
  1538. serverCommStatus->Errors |= SERIAL_ERROR_BREAK;
  1539. }
  1540. if (errors & CE_FRAME) {
  1541. serverCommStatus->Errors |= SERIAL_ERROR_FRAMING;
  1542. }
  1543. if (errors & CE_OVERRUN) {
  1544. serverCommStatus->Errors |= SERIAL_ERROR_OVERRUN;
  1545. }
  1546. if (errors & CE_RXOVER) {
  1547. serverCommStatus->Errors |= SERIAL_ERROR_QUEUEOVERRUN;
  1548. }
  1549. if (errors & CE_RXPARITY) {
  1550. serverCommStatus->Errors |= SERIAL_ERROR_PARITY;
  1551. }
  1552. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1553. = sizeof(SERIAL_STATUS);
  1554. }
  1555. else {
  1556. DWORD err = GetLastError();
  1557. TRC_ALT((TB, _T("ClearCommError failed with %08x"), err));
  1558. status = TranslateWinError(err);
  1559. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1560. = 0;
  1561. replyPacketSize = (ULONG)FIELD_OFFSET(
  1562. RDPDR_IOCOMPLETION_PACKET,
  1563. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1564. }
  1565. //
  1566. // Finish the response and send it.
  1567. //
  1568. pReplyPacket->IoCompletion.IoStatus = status;
  1569. TRACERESP(pIoReq, pReplyPacket);
  1570. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1571. }
  1572. else {
  1573. //
  1574. // Send the results to the server.
  1575. //
  1576. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1577. DefaultIORequestMsgHandle(pIoReq, status);
  1578. }
  1579. DC_END_FN();
  1580. }
  1581. void
  1582. W32DrPRT::SerialGetProperties(
  1583. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1584. )
  1585. /*++
  1586. Routine Description:
  1587. Handle Serial Port Get Properties Request from Server.
  1588. Arguments:
  1589. pIoReq - Request packet received from server.
  1590. Return Value:
  1591. NA
  1592. --*/
  1593. {
  1594. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1595. NTSTATUS status = STATUS_SUCCESS;
  1596. ULONG replyPacketSize;
  1597. PBYTE outputBuf;
  1598. PSERIAL_COMMPROP serverProperties;
  1599. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1600. HANDLE FileHandle;
  1601. DC_BEGIN_FN("W32DrPRT::SerialGetProperties");
  1602. TRACEREQ(pIoReq);
  1603. //
  1604. // Make sure that the windows defines and the NT defines are
  1605. // still in sync.
  1606. //
  1607. // Asserts are broken up because if the assert msg string is
  1608. // too long it causes a compile error
  1609. ASSERT((SERIAL_PCF_DTRDSR == PCF_DTRDSR) &&
  1610. (SERIAL_PCF_RTSCTS == PCF_RTSCTS) &&
  1611. (SERIAL_PCF_CD == PCF_RLSD) &&
  1612. (SERIAL_PCF_PARITY_CHECK == PCF_PARITY_CHECK) &&
  1613. (SERIAL_PCF_XONXOFF == PCF_XONXOFF) &&
  1614. (SERIAL_PCF_SETXCHAR == PCF_SETXCHAR) &&
  1615. (SERIAL_PCF_TOTALTIMEOUTS == PCF_TOTALTIMEOUTS) &&
  1616. (SERIAL_PCF_INTTIMEOUTS == PCF_INTTIMEOUTS) &&
  1617. (SERIAL_PCF_SPECIALCHARS == PCF_SPECIALCHARS) &&
  1618. (SERIAL_PCF_16BITMODE == PCF_16BITMODE) &&
  1619. (SERIAL_SP_PARITY == SP_PARITY) &&
  1620. (SERIAL_SP_BAUD == SP_BAUD) &&
  1621. (SERIAL_SP_DATABITS == SP_DATABITS) &&
  1622. (SERIAL_SP_STOPBITS == SP_STOPBITS) &&
  1623. (SERIAL_SP_HANDSHAKING == SP_HANDSHAKING) &&
  1624. (SERIAL_SP_PARITY_CHECK == SP_PARITY_CHECK) &&
  1625. (SERIAL_SP_CARRIER_DETECT == SP_RLSD));
  1626. ASSERT((SERIAL_BAUD_075 == BAUD_075) &&
  1627. (SERIAL_BAUD_110 == BAUD_110) &&
  1628. (SERIAL_BAUD_134_5 == BAUD_134_5) &&
  1629. (SERIAL_BAUD_150 == BAUD_150) &&
  1630. (SERIAL_BAUD_300 == BAUD_300) &&
  1631. (SERIAL_BAUD_600 == BAUD_600) &&
  1632. (SERIAL_BAUD_1200 == BAUD_1200) &&
  1633. (SERIAL_BAUD_1800 == BAUD_1800) &&
  1634. (SERIAL_BAUD_2400 == BAUD_2400) &&
  1635. (SERIAL_BAUD_4800 == BAUD_4800) &&
  1636. (SERIAL_BAUD_7200 == BAUD_7200) &&
  1637. (SERIAL_BAUD_9600 == BAUD_9600) &&
  1638. (SERIAL_BAUD_14400 == BAUD_14400) &&
  1639. (SERIAL_BAUD_19200 == BAUD_19200) &&
  1640. (SERIAL_BAUD_38400 == BAUD_38400) &&
  1641. (SERIAL_BAUD_56K == BAUD_56K) &&
  1642. (SERIAL_BAUD_57600 == BAUD_57600) &&
  1643. (SERIAL_BAUD_115200 == BAUD_115200) &&
  1644. (SERIAL_BAUD_USER == BAUD_USER) &&
  1645. (SERIAL_DATABITS_5 == DATABITS_5) &&
  1646. (SERIAL_DATABITS_6 == DATABITS_6) &&
  1647. (SERIAL_DATABITS_7 == DATABITS_7) &&
  1648. (SERIAL_DATABITS_8 == DATABITS_8) &&
  1649. (SERIAL_DATABITS_16 == DATABITS_16));
  1650. ASSERT((SERIAL_DATABITS_16X == DATABITS_16X) &&
  1651. (SERIAL_STOPBITS_10 == STOPBITS_10) &&
  1652. (SERIAL_STOPBITS_15 == STOPBITS_15) &&
  1653. (SERIAL_STOPBITS_20 == STOPBITS_20) &&
  1654. (SERIAL_PARITY_NONE == PARITY_NONE) &&
  1655. (SERIAL_PARITY_ODD == PARITY_ODD) &&
  1656. (SERIAL_PARITY_EVEN == PARITY_EVEN) &&
  1657. (SERIAL_PARITY_MARK == PARITY_MARK) &&
  1658. (SERIAL_PARITY_SPACE == PARITY_SPACE));
  1659. ASSERT((SERIAL_SP_UNSPECIFIED == PST_UNSPECIFIED) &&
  1660. (SERIAL_SP_RS232 == PST_RS232) &&
  1661. (SERIAL_SP_PARALLEL == PST_PARALLELPORT) &&
  1662. (SERIAL_SP_RS422 == PST_RS422) &&
  1663. (SERIAL_SP_RS423 == PST_RS423) &&
  1664. (SERIAL_SP_RS449 == PST_RS449) &&
  1665. (SERIAL_SP_FAX == PST_FAX) &&
  1666. (SERIAL_SP_SCANNER == PST_SCANNER) &&
  1667. (SERIAL_SP_BRIDGE == PST_NETWORK_BRIDGE) &&
  1668. (SERIAL_SP_LAT == PST_LAT) &&
  1669. (SERIAL_SP_TELNET == PST_TCPIP_TELNET) &&
  1670. (SERIAL_SP_X25 == PST_X25));
  1671. ASSERT(sizeof(SERIAL_COMMPROP) == sizeof(COMMPROP));
  1672. //
  1673. // Get the IO request.
  1674. //
  1675. pIoRequest = &pIoReq->IoRequest;
  1676. //
  1677. // Get Port Handle
  1678. //
  1679. FileHandle = GetPortHandle(pIoRequest->FileId);
  1680. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1681. //
  1682. // Check the size of the output buffer.
  1683. //
  1684. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(SERIAL_COMMPROP));
  1685. //
  1686. // Allocate reply buffer.
  1687. //
  1688. if (status == STATUS_SUCCESS) {
  1689. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1690. }
  1691. //
  1692. // Get the current properties.
  1693. //
  1694. if (status == STATUS_SUCCESS) {
  1695. //
  1696. // Get a pointer to the output buffer server's communication properties
  1697. //
  1698. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1699. serverProperties = (PSERIAL_COMMPROP)outputBuf;
  1700. if (GetCommProperties(FileHandle, (LPCOMMPROP)serverProperties)) {
  1701. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1702. = sizeof(SERIAL_COMMPROP);
  1703. }
  1704. else {
  1705. DWORD err = GetLastError();
  1706. TRC_ALT((TB, _T("GetCommProperties failed with %08x"), err));
  1707. status = TranslateWinError(err);
  1708. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1709. = 0;
  1710. replyPacketSize = (ULONG)FIELD_OFFSET(
  1711. RDPDR_IOCOMPLETION_PACKET,
  1712. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1713. }
  1714. //
  1715. // Finish the response and send it.
  1716. //
  1717. pReplyPacket->IoCompletion.IoStatus = status;
  1718. TRACERESP(pIoReq, pReplyPacket);
  1719. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1720. }
  1721. else {
  1722. //
  1723. // Send the results to the server.
  1724. //
  1725. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1726. DefaultIORequestMsgHandle(pIoReq, status);
  1727. }
  1728. DC_END_FN();
  1729. }
  1730. void
  1731. W32DrPRT::SerialXoffCounter(
  1732. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. Handle Serial Port XOFF Request from Server.
  1737. Arguments:
  1738. pIoReq - Request packet received from server.
  1739. Return Value:
  1740. NA
  1741. --*/
  1742. {
  1743. DC_BEGIN_FN("W32DrPRT::SerialXoffCounter");
  1744. TRACEREQ(pIoReq);
  1745. //
  1746. // This IOCTL is not supported by Win32 COMM functions. What
  1747. // else can we do, but pass it directly to the driver. We should ASSERT
  1748. // to find out under which circumstances this happens, however.
  1749. //
  1750. ASSERT(FALSE);
  1751. DispatchIOCTLDirectlyToDriver(pIoReq);
  1752. DC_END_FN();
  1753. }
  1754. void
  1755. W32DrPRT::SerialLSRMSTInsert(
  1756. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1757. )
  1758. /*++
  1759. Routine Description:
  1760. Handle Serial Port LSRMST Insert Request from Server.
  1761. Arguments:
  1762. pIoReq - Request packet received from server.
  1763. Return Value:
  1764. NA
  1765. --*/
  1766. {
  1767. DC_BEGIN_FN("W32DrPRT::SerialLSRMSTInsert");
  1768. TRACEREQ(pIoReq);
  1769. //
  1770. // This IOCTL is not supported by Win32 COMM functions. What
  1771. // else can we do, but pass it directly to the driver. We should ASSERT
  1772. // to find out under which circumstances this happens, however.
  1773. //
  1774. ASSERT(FALSE);
  1775. DispatchIOCTLDirectlyToDriver(pIoReq);
  1776. DC_END_FN();
  1777. }
  1778. void
  1779. W32DrPRT::SerialConfigSize(
  1780. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1781. )
  1782. /*++
  1783. Routine Description:
  1784. Handle Serial Port Get Config Size Request from Server.
  1785. We don't support the IOCTL that is used to fetch the
  1786. configuration. Neither does the NT serial driver ...
  1787. Arguments:
  1788. pIoReq - Request packet received from server.
  1789. Return Value:
  1790. NA
  1791. --*/
  1792. {
  1793. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1794. NTSTATUS status = STATUS_SUCCESS;
  1795. #ifndef OS_WINCE
  1796. DCB dcb;
  1797. #endif
  1798. ULONG replyPacketSize;
  1799. PBYTE outputBuf;
  1800. ULONG *configSize;
  1801. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1802. HANDLE FileHandle;
  1803. DC_BEGIN_FN("W32DrPRT::SerialConfigSize");
  1804. TRACEREQ(pIoReq);
  1805. //
  1806. // Get the IO request.
  1807. //
  1808. pIoRequest = &pIoReq->IoRequest;
  1809. //
  1810. // Get Port Handle
  1811. //
  1812. FileHandle = GetPortHandle(pIoRequest->FileId);
  1813. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1814. //
  1815. // Check the size of the output buffer.
  1816. //
  1817. status = DrUTL_CheckIOBufOutputSize(pIoReq, sizeof(ULONG));
  1818. //
  1819. // Allocate reply buffer.
  1820. //
  1821. if (status == STATUS_SUCCESS) {
  1822. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1823. }
  1824. //
  1825. // Get the configuration size.
  1826. //
  1827. if (status == STATUS_SUCCESS) {
  1828. //
  1829. // Get a pointer to the output buffer server's wait mask.
  1830. //
  1831. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1832. configSize = (ULONG *)outputBuf;
  1833. #ifndef OS_WINCE
  1834. if (GetCommConfig(FileHandle, NULL, configSize)) {
  1835. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1836. = sizeof(ULONG);
  1837. }
  1838. else {
  1839. DWORD err = GetLastError();
  1840. TRC_ALT((TB, _T("GetCommConfig failed with %08x"), err));
  1841. status = TranslateWinError(err);
  1842. #else
  1843. status = STATUS_NOT_SUPPORTED;
  1844. #endif
  1845. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1846. = 0;
  1847. replyPacketSize = (ULONG)FIELD_OFFSET(
  1848. RDPDR_IOCOMPLETION_PACKET,
  1849. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1850. #ifndef OS_WINCE
  1851. }
  1852. #endif
  1853. //
  1854. // Finish the response and send it.
  1855. //
  1856. pReplyPacket->IoCompletion.IoStatus = status;
  1857. TRACERESP(pIoReq, pReplyPacket);
  1858. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1859. }
  1860. else {
  1861. //
  1862. // Send the results to the server.
  1863. //
  1864. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1865. DefaultIORequestMsgHandle(pIoReq, status);
  1866. }
  1867. DC_END_FN();
  1868. }
  1869. void
  1870. W32DrPRT::SerialGetConfig(
  1871. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1872. )
  1873. /*++
  1874. Routine Description:
  1875. Handle Serial Port Get Config Request from Server.
  1876. Arguments:
  1877. pIoReq - Request packet received from server.
  1878. Return Value:
  1879. NA
  1880. --*/
  1881. {
  1882. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  1883. NTSTATUS status = STATUS_SUCCESS;
  1884. ULONG replyPacketSize;
  1885. PBYTE outputBuf;
  1886. ULONG configSize;
  1887. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1888. HANDLE FileHandle;
  1889. DC_BEGIN_FN("W32DrPRT::SerialGetConfig");
  1890. TRACEREQ(pIoReq);
  1891. //
  1892. // Get the IO request.
  1893. //
  1894. pIoRequest = &pIoReq->IoRequest;
  1895. //
  1896. // Get Port Handle
  1897. //
  1898. FileHandle = GetPortHandle(pIoRequest->FileId);
  1899. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  1900. //
  1901. // Allocate reply buffer.
  1902. //
  1903. status = DrUTL_AllocateReplyBuf(pIoReq, &pReplyPacket, &replyPacketSize);
  1904. //
  1905. // Get the configuration size.
  1906. //
  1907. if (status == STATUS_SUCCESS) {
  1908. //
  1909. // Get a pointer to the output buffer server's wait mask.
  1910. //
  1911. outputBuf = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  1912. configSize = pIoRequest->Parameters.DeviceIoControl.OutputBufferLength;
  1913. #ifndef OS_WINCE
  1914. if (GetCommConfig(FileHandle, (COMMCONFIG *)outputBuf, &configSize)) {
  1915. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1916. = configSize;
  1917. }
  1918. else {
  1919. DWORD err = GetLastError();
  1920. TRC_ALT((TB, _T("GetCommConfig failed with %08x"), err));
  1921. status = TranslateWinError(err);
  1922. #else
  1923. status = STATUS_NOT_SUPPORTED;
  1924. #endif
  1925. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength
  1926. = 0;
  1927. replyPacketSize = (ULONG)FIELD_OFFSET(
  1928. RDPDR_IOCOMPLETION_PACKET,
  1929. IoCompletion.Parameters.DeviceIoControl.OutputBuffer);
  1930. #ifndef OS_WINCE
  1931. }
  1932. #endif
  1933. //
  1934. // Finish the response and send it.
  1935. //
  1936. pReplyPacket->IoCompletion.IoStatus = status;
  1937. TRACERESP(pIoReq, pReplyPacket);
  1938. ProcessObject()->GetVCMgr().ChannelWrite(pReplyPacket, replyPacketSize);
  1939. }
  1940. else {
  1941. //
  1942. // Send the results to the server.
  1943. //
  1944. TRACERESP_WITHPARAMS(pIoReq, NULL, 0, status);
  1945. DefaultIORequestMsgHandle(pIoReq, status);
  1946. }
  1947. DC_END_FN();
  1948. }
  1949. void
  1950. W32DrPRT::SerialGetStats(
  1951. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1952. )
  1953. /*++
  1954. Routine Description:
  1955. Handle Serial Port Get Stats Request from Server.
  1956. Arguments:
  1957. pIoReq - Request packet received from server.
  1958. Return Value:
  1959. NA
  1960. --*/
  1961. {
  1962. DC_BEGIN_FN("W32DrPRT::SerialGetStats");
  1963. TRACEREQ(pIoReq);
  1964. //
  1965. // This IOCTL is not supported by Win32 COMM functions. What
  1966. // else can we do, but pass it directly to the driver. We should ASSERT
  1967. // to find out under which circumstances this happens, however.
  1968. //
  1969. ASSERT(FALSE);
  1970. DispatchIOCTLDirectlyToDriver(pIoReq);
  1971. DC_END_FN();
  1972. }
  1973. void
  1974. W32DrPRT::SerialClearStats(
  1975. IN PRDPDR_IOREQUEST_PACKET pIoReq
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. Handle Serial Port Clear Stats Request from Server.
  1980. Arguments:
  1981. pIoReq - Request packet received from server.
  1982. Return Value:
  1983. NA
  1984. --*/
  1985. {
  1986. DC_BEGIN_FN("W32DrPRT::SerialClearStats");
  1987. TRACEREQ(pIoReq);
  1988. //
  1989. // This IOCTL is not supported by Win32 COMM functions. What
  1990. // else can we do, but pass it directly to the driver. We should ASSERT
  1991. // to find out under which circumstances this happens, however.
  1992. //
  1993. ASSERT(FALSE);
  1994. DispatchIOCTLDirectlyToDriver(pIoReq);
  1995. DC_END_FN();
  1996. }
  1997. #ifndef OS_WINCE
  1998. BOOL
  1999. W32DrPRT::GetIniCommValues(
  2000. LPTSTR pName,
  2001. LPDCB pdcb
  2002. )
  2003. /*++
  2004. It goes to win.ini [ports] section to get the comm (serial) port
  2005. settings such as
  2006. com1:=9600,n,8,1
  2007. And build a DCB.
  2008. Code modified from
  2009. \\muroc\slm\proj\win\src\CORE\SPOOL32\SPOOLSS\newdll\localmon.c
  2010. --*/
  2011. {
  2012. COMMCONFIG ccDummy;
  2013. COMMCONFIG *pcc;
  2014. DWORD dwSize;
  2015. TCHAR buf[MAX_PATH];
  2016. DC_BEGIN_FN("GetIniCommValues");
  2017. int len = _tcslen(pName) - 1;
  2018. BOOL ret = FALSE;
  2019. HRESULT hr;
  2020. hr = StringCchCopy(buf, SIZE_TCHARS(buf), pName);
  2021. if (FAILED(hr)) {
  2022. TRC_ERR((TB,_T("Failed to copy pName to temp buf: 0x%x"),hr));
  2023. return FALSE;
  2024. }
  2025. if (buf[len] == _T(':'))
  2026. buf[len] = 0;
  2027. ccDummy.dwProviderSubType = PST_RS232;
  2028. dwSize = sizeof(ccDummy);
  2029. GetDefaultCommConfig(buf, &ccDummy, &dwSize);
  2030. if (pcc = (COMMCONFIG *)LocalAlloc(LPTR, dwSize))
  2031. {
  2032. pcc->dwProviderSubType = PST_RS232;
  2033. if (GetDefaultCommConfig(buf, pcc, &dwSize))
  2034. {
  2035. *pdcb = pcc->dcb;
  2036. ret = TRUE;
  2037. }
  2038. LocalFree(pcc);
  2039. }
  2040. DC_END_FN();
  2041. return ret;
  2042. }
  2043. #endif
  2044. VOID
  2045. W32DrPRT::InitializeSerialPort(
  2046. IN TCHAR *portName,
  2047. IN HANDLE portHandle
  2048. )
  2049. /*++
  2050. Routine Description:
  2051. Set a serial port to its initial state.
  2052. Arguments:
  2053. portName - Port name.
  2054. portHandle - Handle to open serial port.
  2055. Return Value:
  2056. This function always succeeds. Subsequent operations will fail if
  2057. the port cannot be properly initialized.
  2058. --*/
  2059. {
  2060. DCB dcb;
  2061. COMMTIMEOUTS cto;
  2062. DC_BEGIN_FN("W32DrPRT::InitializeSerialPort");
  2063. //
  2064. // Initialize serial port
  2065. //
  2066. if (!GetCommState(portHandle, &dcb)) {
  2067. TRC_ERR((TB, _T("GetCommState() returns %ld"), GetLastError()));
  2068. goto CLEANUPANDEXIT;
  2069. }
  2070. if (!GetCommTimeouts(portHandle, &cto)) {
  2071. TRC_ERR((TB, _T("GetCommTimeouts() returns %ld"), GetLastError()));
  2072. goto CLEANUPANDEXIT;
  2073. }
  2074. #ifndef OS_WINCE
  2075. if (!GetIniCommValues(portName, &dcb)) {
  2076. TRC_ERR((TB, _T("GetIniCommValues() returns %ld"), GetLastError()));
  2077. goto CLEANUPANDEXIT;
  2078. }
  2079. #endif
  2080. cto.WriteTotalTimeoutConstant = WRITE_TOTAL_TIMEOUT;
  2081. cto.ReadTotalTimeoutConstant = READ_TOTAL_TIMEOUT;
  2082. cto.ReadIntervalTimeout = READ_INTERVAL_TIMEOUT;
  2083. //
  2084. // Ignore error from following.
  2085. //
  2086. SetCommState(portHandle, &dcb);
  2087. SetCommTimeouts(portHandle, &cto);
  2088. CLEANUPANDEXIT:
  2089. DC_END_FN();
  2090. }