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.

2088 lines
55 KiB

  1. //****************************************************************************
  2. //
  3. // Microsoft NT Remote Access Service
  4. //
  5. // Copyright (C) 1992-93 Microsft Corporation. All rights reserved.
  6. //
  7. // Filename: serial.c
  8. //
  9. // Revision History
  10. //
  11. // Sep 3, 1992 J. Perry Hannah Created
  12. //
  13. //
  14. // Description: This file contains all entry points for SERIAL.DLL
  15. // which is the media DLL for serial ports.
  16. //
  17. //****************************************************************************
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <rasman.h>
  23. #include <raserror.h>
  24. #include <rasfile.h>
  25. #include <mprlog.h>
  26. #include <rtutils.h>
  27. #include <rasmxs.h>
  28. #include <wanpub.h>
  29. #include <asyncpub.h>
  30. #include <media.h>
  31. #include <serial.h>
  32. #include <serialpr.h>
  33. #include <stdlib.h>
  34. #include <malloc.h>
  35. #include <string.h>
  36. //* Global Variables *******************************************************
  37. //
  38. SERIALPCB *gpSerialPCB; // Points to Serial PCB linked list
  39. HANDLE ghRasfileMutex; // Mutex used to protect access to Rasfile
  40. HRASFILE ghIniFile; // Handle to Serial.ini memory image
  41. HANDLE ghAsyMac; // Handle to AsyncMac driver
  42. DWORD gLastError;
  43. //* Prototypes For APIs That Are Called Internally *************************
  44. //
  45. DWORD PortClearStatistics(HANDLE hIOPort);
  46. OVERLAPPED overlapped ;
  47. //* Initialization Routine *************************************************
  48. //
  49. //* SerialDllEntryPoint
  50. //
  51. // Function: Initializes Serial DLL when the DLL is loaded into memory,
  52. // and cleans up when the last process detaches from the DLL.
  53. //
  54. // Returns: TRUE if successful, else FALSE.
  55. //
  56. //*
  57. BOOL APIENTRY
  58. SerialDllEntryPoint(HANDLE hDll, DWORD dwReason, LPVOID pReserved)
  59. {
  60. static BOOL bFirstCall = TRUE;
  61. char szIniFilePath[MAX_PATH];
  62. WCHAR szDriverName[] = ASYNCMAC_FILENAME;
  63. DebugPrintf(("SerialDllEntryPoint\n"));
  64. //DbgPrint("SerialDllEntryPoint\n");
  65. switch(dwReason)
  66. {
  67. case DLL_PROCESS_ATTACH:
  68. if (bFirstCall)
  69. {
  70. DebugPrintf(("\tProcess Attach.\n"));
  71. // Open Serial.ini file
  72. *szIniFilePath = '\0';
  73. GetIniFileName(szIniFilePath, sizeof(szIniFilePath));
  74. ghIniFile = RasfileLoad(szIniFilePath, RFM_READONLY, NULL, NULL);
  75. DebugPrintf(("INI: %s, ghIniFile: 0x%08x\n", szIniFilePath, ghIniFile));
  76. /*
  77. if (ghIniFile == INVALID_HRASFILE)
  78. {
  79. LogError(ROUTERLOG_CANNOT_OPEN_SERIAL_INI, 0, NULL, 0xffffffff);
  80. return(FALSE);
  81. } */
  82. if ((ghRasfileMutex = CreateMutex (NULL,FALSE,NULL)) == NULL)
  83. return FALSE ;
  84. // Get handle to Asyncmac driver
  85. /*
  86. ghAsyMac = CreateFileW(szDriverName,
  87. GENERIC_READ | GENERIC_WRITE,
  88. FILE_SHARE_READ | FILE_SHARE_WRITE,
  89. NULL, //No security attribs
  90. OPEN_EXISTING,
  91. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  92. NULL); //No template file
  93. DebugPrintf(("ghAsyMac: 0x%08x\n", ghAsyMac));
  94. if (ghAsyMac == INVALID_HANDLE_VALUE)
  95. {
  96. DebugPrintf(("CreateFileError: %d\n", GetLastError()));
  97. LogError(ROUTERLOG_CANNOT_GET_ASYNCMAC_HANDLE, 0, NULL, 0xffffffff);
  98. return(FALSE);
  99. } */
  100. bFirstCall = FALSE;
  101. }
  102. break;
  103. case DLL_PROCESS_DETACH:
  104. DebugPrintf(("\tProcess Detach.\n"));
  105. if(INVALID_HANDLE_VALUE != ghRasfileMutex
  106. && NULL != ghRasfileMutex)
  107. {
  108. CloseHandle(ghRasfileMutex);
  109. ghRasfileMutex = INVALID_HANDLE_VALUE;
  110. }
  111. break;
  112. case DLL_THREAD_ATTACH:
  113. DebugPrintf(("\tThread Attach.\n"));
  114. break;
  115. case DLL_THREAD_DETACH:
  116. DebugPrintf(("\tThread Detach.\n"));
  117. break;
  118. }
  119. return(TRUE);
  120. UNREFERENCED_PARAMETER(hDll);
  121. UNREFERENCED_PARAMETER(pReserved);
  122. }
  123. //* Serial APIs ************************************************************
  124. //
  125. //* PortEnum ---------------------------------------------------------------
  126. //
  127. // Function: This API returns a buffer containing a PortMediaInfo struct.
  128. //
  129. // Returns: SUCCESS
  130. // ERROR_BUFFER_TOO_SMALL
  131. // ERROR_READING_SECTIONNAME
  132. // ERROR_READING_DEVICETYPE
  133. // ERROR_READING_DEVICENAME
  134. // ERROR_READING_USAGE
  135. // ERROR_BAD_USAGE_IN_INI_FILE
  136. //
  137. //*
  138. DWORD APIENTRY
  139. PortEnum(BYTE *pBuffer, DWORD *pdwSize, DWORD *pdwNumPorts)
  140. {
  141. DWORD dwAvailable;
  142. TCHAR szUsage[RAS_MAXLINEBUFLEN];
  143. CHAR szMacName[MAC_NAME_SIZE] ;
  144. PortMediaInfo *pPMI;
  145. BYTE buffer [1000] ;
  146. DWORD dwBytesReturned;
  147. TCHAR *pszBuffer = NULL;
  148. DWORD dwErr = ERROR_SUCCESS;
  149. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  150. DebugPrintf(("PortEnum\n"));
  151. // Count number of sections in serial.ini
  152. *pdwNumPorts = 0;
  153. // Begin Exclusion
  154. WaitForSingleObject(ghRasfileMutex, INFINITE);
  155. if ( INVALID_HRASFILE != ghIniFile
  156. && RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_FILE))
  157. (*pdwNumPorts)++;
  158. else
  159. {
  160. *pdwSize = 0;
  161. // End Exclusion
  162. ReleaseMutex(ghRasfileMutex);
  163. return(SUCCESS);
  164. }
  165. while(RasfileFindNextLine(ghIniFile, RFL_SECTION, RFS_FILE))
  166. (*pdwNumPorts)++;
  167. // End Exclusion
  168. ReleaseMutex(ghRasfileMutex);
  169. // Calculate size of buffer needed
  170. dwAvailable = *pdwSize;
  171. *pdwSize = sizeof(PortMediaInfo) * (*pdwNumPorts);
  172. if (*pdwSize > dwAvailable)
  173. return(ERROR_BUFFER_TOO_SMALL);
  174. // Translate serial.ini file section by section into pBuffer
  175. pPMI = (PortMediaInfo *) pBuffer;
  176. // Begin Exclusion
  177. WaitForSingleObject(ghRasfileMutex, INFINITE);
  178. RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_FILE);
  179. #if 0
  180. // Need to get the MAC name
  181. if (!DeviceIoControl(ghAsyMac,
  182. IOCTL_ASYMAC_ENUM,
  183. buffer,
  184. sizeof(buffer),
  185. buffer,
  186. sizeof(buffer),
  187. &dwBytesReturned,
  188. &overlapped))
  189. {
  190. // End Exclusion
  191. ReleaseMutex(ghRasfileMutex);
  192. return(GetLastError());
  193. }
  194. wcstombs(szMacName, ((PASYMAC_ENUM)buffer)->AdapterInfo[0].MacName,
  195. wcslen(((PASYMAC_ENUM)buffer)->AdapterInfo[0].MacName)+1) ;
  196. #else
  197. szMacName[0] = '\0' ;
  198. #endif
  199. pszBuffer = LocalAlloc(LPTR, RAS_MAXLINEBUFLEN);
  200. if(NULL == pszBuffer)
  201. {
  202. ReleaseMutex(ghRasfileMutex);
  203. return GetLastError();
  204. }
  205. do
  206. {
  207. // Get Section Name (same as Port Name)
  208. if (!RasfileGetSectionName(ghIniFile, pPMI->PMI_Name))
  209. {
  210. // End Exclusion
  211. ReleaseMutex(ghRasfileMutex);
  212. dwErr = ERROR_READING_SECTIONNAME;
  213. break;
  214. }
  215. // Set Binding Name
  216. strcpy (pPMI->PMI_MacBindingName, szMacName) ;
  217. // Get Device Type
  218. if(!(RasfileFindNextKeyLine(ghIniFile, SER_DEVICETYPE_KEY, RFS_SECTION) &&
  219. RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer/* pPMI->PMI_DeviceType*/)))
  220. {
  221. // End Exclusion
  222. CopyMemory(pPMI->PMI_DeviceType, pszBuffer, MAX_DEVICETYPE_NAME);
  223. ReleaseMutex(ghRasfileMutex);
  224. dwErr = ERROR_READING_DEVICETYPE;
  225. break;
  226. }
  227. CopyMemory(pPMI->PMI_DeviceType, pszBuffer, MAX_DEVICETYPE_NAME);
  228. ZeroMemory(pszBuffer, sizeof(RAS_MAXLINEBUFLEN));
  229. // Get Device Name
  230. if (!(RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_SECTION) &&
  231. RasfileFindNextKeyLine(ghIniFile, SER_DEVICENAME_KEY, RFS_SECTION) &&
  232. RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer /*pPMI->PMI_DeviceName*/)))
  233. {
  234. // End Exclusion
  235. CopyMemory(pPMI->PMI_DeviceName, pszBuffer, MAX_DEVICE_NAME);
  236. ReleaseMutex(ghRasfileMutex);
  237. dwErr = ERROR_READING_DEVICENAME;
  238. break;
  239. }
  240. CopyMemory(pPMI->PMI_DeviceName, pszBuffer, MAX_DEVICE_NAME);
  241. ZeroMemory(pszBuffer, RAS_MAXLINEBUFLEN);
  242. // Get Usage
  243. if (!(RasfileFindFirstLine(ghIniFile, RFL_SECTION, RFS_SECTION) &&
  244. RasfileFindNextKeyLine(ghIniFile, SER_USAGE_KEY, RFS_SECTION) &&
  245. RasfileGetKeyValueFields(ghIniFile, NULL, pszBuffer /*szUsage*/)))
  246. {
  247. // End Exclusion
  248. CopyMemory(szUsage, pszBuffer, RAS_MAXLINEBUFLEN);
  249. ReleaseMutex(ghRasfileMutex);
  250. dwErr = ERROR_READING_USAGE;
  251. break;
  252. }
  253. CopyMemory(szUsage, pszBuffer, RAS_MAXLINEBUFLEN);
  254. if (!StrToUsage(szUsage, &(pPMI->PMI_Usage)))
  255. {
  256. // End Exclusion
  257. ReleaseMutex(ghRasfileMutex);
  258. dwErr = ERROR_BAD_USAGE_IN_INI_FILE;
  259. break;
  260. }
  261. pPMI->PMI_LineDeviceId = INVALID_TAPI_ID;
  262. pPMI->PMI_AddressId = INVALID_TAPI_ID;
  263. pPMI++;
  264. }while(RasfileFindNextLine(ghIniFile, RFL_SECTION, RFS_FILE));
  265. if(NULL != pszBuffer)
  266. {
  267. LocalFree(pszBuffer);
  268. }
  269. // End Exclusion
  270. ReleaseMutex(ghRasfileMutex);
  271. return(dwErr);
  272. }
  273. //* PortOpen ---------------------------------------------------------------
  274. //
  275. // Function: This API opens a COM port. It takes the port name in ASCIIZ
  276. // form and supplies a handle to the open port. hNotify is use
  277. // to notify the caller if the device on the port shuts down.
  278. //
  279. // PortOpen allocates a SerialPCB and places it at the head of
  280. // the linked list of Serial Port Control Blocks.
  281. //
  282. // Returns: SUCCESS
  283. // ERROR_PORT_NOT_CONFIGURED
  284. // ERROR_DEVICE_NOT_READY
  285. //
  286. //*
  287. DWORD APIENTRY
  288. PortOpen(
  289. char *pszPortName,
  290. HANDLE *phIOPort,
  291. HANDLE hIoCompletionPort,
  292. DWORD dwCompletionKey)
  293. {
  294. SERIALPCB *pSPCB ;
  295. DWORD dwRC, dwStatus = 0;
  296. TCHAR szPort[MAX_PATH];
  297. WCHAR szDriverName[] = ASYNCMAC_FILENAME;
  298. try
  299. {
  300. DebugPrintf(("PortOpen: %s\n", pszPortName));
  301. // Check serial.ini to see that pszPortName is configured for RAS
  302. // Begin Exclusion
  303. if(INVALID_HRASFILE == ghIniFile)
  304. {
  305. return ERROR_PORT_NOT_CONFIGURED;
  306. }
  307. WaitForSingleObject(ghRasfileMutex, INFINITE);
  308. #if DBG
  309. ASSERT(INVALID_HRASFILE != ghIniFile );
  310. #endif
  311. if (!RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE))
  312. {
  313. // End Exclusion
  314. ReleaseMutex(ghRasfileMutex);
  315. return(ERROR_PORT_NOT_CONFIGURED);
  316. }
  317. // End Exclusion
  318. ReleaseMutex(ghRasfileMutex);
  319. // Prepend \\.\ to COMx
  320. strcpy(szPort, "\\\\.\\");
  321. strcat(szPort, pszPortName);
  322. // Open Port
  323. *phIOPort = CreateFile(szPort,
  324. GENERIC_READ | GENERIC_WRITE,
  325. FILE_EXCLUSIVE_MODE,
  326. NULL, //No Security Attributes
  327. OPEN_EXISTING,
  328. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  329. NULL); //No Template File
  330. DebugPrintf(("hioport: 0x%08x\n", *phIOPort));
  331. //DbgPrint("hioport: 0x%08x\n", *phIOPort);
  332. if (*phIOPort == INVALID_HANDLE_VALUE)
  333. {
  334. dwRC = GetLastError();
  335. if (dwRC == ERROR_ACCESS_DENIED)
  336. return (ERROR_PORT_ALREADY_OPEN);
  337. else if (dwRC == ERROR_FILE_NOT_FOUND)
  338. return (ERROR_PORT_NOT_FOUND) ;
  339. else
  340. return(dwRC);
  341. }
  342. //
  343. // Associate an I/O completion port with
  344. // the file handle.
  345. //
  346. if (CreateIoCompletionPort(
  347. *phIOPort,
  348. hIoCompletionPort,
  349. dwCompletionKey,
  350. 0) == NULL)
  351. {
  352. CloseHandle(*phIOPort);
  353. *phIOPort = NULL;
  354. return GetLastError();
  355. }
  356. #ifdef notdef
  357. {
  358. DWORD dwBytesReturned ;
  359. #define FILE_DEVICE_SERIAL_PORT 0x0000001b
  360. #define _SERIAL_CONTROL_CODE(request,method) \
  361. ((FILE_DEVICE_SERIAL_PORT)<<16 | (request<<2) | method)
  362. #define IOCTL_SERIAL_PRIVATE_RAS _SERIAL_CONTROL_CODE(4000, METHOD_BUFFERED)
  363. DeviceIoControl(*phIOPort,
  364. IOCTL_SERIAL_PRIVATE_RAS,
  365. NULL,
  366. 0,
  367. NULL,
  368. 0,
  369. &dwBytesReturned,
  370. NULL) ;
  371. }
  372. #endif
  373. // Set Queue sizes and default values for Comm Port
  374. if (!SetupComm(*phIOPort, INPUT_QUEUE_SIZE, OUTPUT_QUEUE_SIZE))
  375. {
  376. LogError(ROUTERLOG_SERIAL_QUEUE_SIZE_SMALL, 0, NULL, 0xffffffff);
  377. }
  378. SetCommDefaults(*phIOPort, pszPortName);
  379. // Add a Serial PCB to head of list and set eDeviceType
  380. AddPortToList(*phIOPort, pszPortName);
  381. pSPCB = FindPortInList(*phIOPort, NULL) ; //Find port just added
  382. if(NULL == pSPCB)
  383. {
  384. CloseHandle(*phIOPort);
  385. *phIOPort = NULL;
  386. return ERROR_PORT_NOT_FOUND;
  387. }
  388. // Get handle to Asyncmac driver
  389. pSPCB->hAsyMac = CreateFileW(szDriverName,
  390. GENERIC_READ | GENERIC_WRITE,
  391. FILE_SHARE_READ | FILE_SHARE_WRITE,
  392. NULL, //No security attribs
  393. OPEN_EXISTING,
  394. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  395. NULL); //No template file
  396. DebugPrintf(("pSPCB->hAsyMac: 0x%08x\n", pSPCB->hAsyMac));
  397. //DbgPrint("pSPCB->hAsyMac: 0x%08x\n", pSPCB->hAsyMac);
  398. if (pSPCB->hAsyMac == INVALID_HANDLE_VALUE)
  399. {
  400. DWORD dwErr;
  401. dwErr = GetLastError();
  402. DebugPrintf(("CreateFileError: %d\n", dwErr));
  403. //DbgPrint("CreateFileError: %d\n", dwErr);
  404. LogError(ROUTERLOG_CANNOT_GET_ASYNCMAC_HANDLE, 0, NULL, 0xffffffff);
  405. CloseHandle(*phIOPort);
  406. *phIOPort = NULL;
  407. return(dwErr);
  408. }
  409. //
  410. // Associate the I/O completion port with
  411. // the asyncmac file handle
  412. //
  413. if (CreateIoCompletionPort(pSPCB->hAsyMac,
  414. hIoCompletionPort,
  415. dwCompletionKey,
  416. 0) == NULL)
  417. {
  418. DWORD dwErr;
  419. dwErr = GetLastError();
  420. //DbgPrint("PortOpen: Failed to create IoCompletionPort %d\n", dwErr);
  421. CloseHandle(*phIOPort);
  422. *phIOPort = NULL;
  423. return dwErr;
  424. }
  425. dwRC = InitCarrierBps(pszPortName, pSPCB->szCarrierBPS);
  426. if (dwRC != SUCCESS)
  427. {
  428. gLastError = dwRC;
  429. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  430. }
  431. // Check that device is powered on and ready (DSR is up) If it is then
  432. // we monitor DSR - else - we do not monitor DSR until we are connected.
  433. //
  434. GetCommModemStatus(*phIOPort, &dwStatus);
  435. pSPCB->dwPreviousModemStatus = 0;
  436. if ( ! (dwStatus & MS_DSR_ON))
  437. // DSR is not raised by the device = assume that it will not raise
  438. // it until its connected.
  439. //
  440. pSPCB->dwActiveDSRMask = pSPCB->dwMonitorDSRMask = 0 ;
  441. else {
  442. // Tell system to signal rasman if DSR drops
  443. pSPCB->dwActiveDSRMask = pSPCB->dwMonitorDSRMask = EV_DSR ;
  444. //DbgPrint("PortOpen: Setting mask 0x%x\n", EV_DSR);
  445. SetCommMask(*phIOPort, EV_DSR);
  446. if (!WaitCommEvent(*phIOPort,
  447. &(pSPCB->dwEventMask),
  448. (LPOVERLAPPED)&(pSPCB->MonitorDevice)))
  449. {
  450. //DbgPrint("PortOpen: WaitCommEvent. %d\n", GetLastError());
  451. }
  452. }
  453. // Set values in Serial Port Control Block
  454. GetDefaultOffStr(*phIOPort, pszPortName);
  455. }
  456. except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH)
  457. {
  458. return(gLastError);
  459. }
  460. return(SUCCESS);
  461. }
  462. //* PortClose --------------------------------------------------------------
  463. //
  464. // Function: This API closes the COM port for the input handle. It also
  465. // finds the SerialPCB for the input handle, removes it from
  466. // the linked list, and frees the memory for it
  467. //
  468. // Returns: SUCCESS
  469. // Values returned by GetLastError()
  470. //
  471. //*
  472. DWORD APIENTRY
  473. PortClose (HANDLE hIOPort)
  474. {
  475. SERIALPCB *pPrev, *pSPCB = gpSerialPCB;
  476. DebugPrintf(("PortClose\n"));
  477. // Find the SerialPCB which contains hIOPOrt
  478. pSPCB = FindPortInList(hIOPort, &pPrev);
  479. if (pSPCB == NULL)
  480. return(ERROR_PORT_NOT_OPEN);
  481. // Remove the found SerialPCB
  482. if (pSPCB == gpSerialPCB)
  483. gpSerialPCB = pSPCB->pNextSPCB;
  484. else
  485. pPrev->pNextSPCB = pSPCB->pNextSPCB;
  486. // Cancel wait on this port (WaitCommEvent)
  487. //
  488. //DbgPrint("PortClose: Setting mask to 0\n");
  489. SetCommMask(hIOPort, 0);
  490. // Drop DTR
  491. //
  492. EscapeCommFunction(hIOPort, CLRDTR);
  493. // Close COM Port
  494. //
  495. if (!CloseHandle(hIOPort))
  496. return(GetLastError());
  497. // close the asymac file we associated with this com port
  498. if (!CloseHandle(pSPCB->hAsyMac))
  499. return GetLastError();
  500. // Free portcontrolblock: note this must be done after CloseHandle since the struct
  501. // contains an overlapped struct used for i/o on the port. this overlapped struct
  502. // is freed when the handle to the port is closed.
  503. //
  504. free(pSPCB);
  505. return(SUCCESS);
  506. }
  507. //* PortGetInfo ------------------------------------------------------------
  508. //
  509. // Function: This API returns a block of information to the caller about
  510. // the port state. This API may be called before the port is
  511. // open in which case it will return inital default values
  512. // instead of actual port values.
  513. //
  514. // If the API is to be called before the port is open, set hIOPort
  515. // to INVALID_HANDLE_VALUE and pszPortName to the port name. If
  516. // hIOPort is valid (the port is open), pszPortName may be set
  517. // to NULL.
  518. //
  519. // hIOPort pSPCB := FindPortNameInList() Port
  520. // ------- ----------------------------- ------
  521. // valid x open
  522. // invalid non_null open
  523. // invalid null closed
  524. //
  525. // Returns: SUCCESS
  526. // ERROR_BUFFER_TOO_SMALL
  527. //*
  528. DWORD APIENTRY
  529. PortGetInfo(HANDLE hIOPort, TCHAR *pszPortName, BYTE *pBuffer, DWORD *pdwSize)
  530. {
  531. SERIALPCB *pSPCB;
  532. DCB DCB;
  533. RAS_PARAMS *pParam;
  534. TCHAR *pValue;
  535. TCHAR szDefaultOff[RAS_MAXLINEBUFLEN];
  536. TCHAR szClientDefaultOff[RAS_MAXLINEBUFLEN];
  537. TCHAR szDeviceType[MAX_DEVICETYPE_NAME + 1];
  538. TCHAR szDeviceName[MAX_DEVICE_NAME + 1];
  539. TCHAR szPortName[MAX_PORT_NAME + 1];
  540. TCHAR szConnectBPS[MAX_BPS_STR_LEN], szCarrierBPS[MAX_BPS_STR_LEN];
  541. DWORD dwConnectBPSLen, dwCarrierBPSLen, dwDefaultOffLen;
  542. DWORD dwDeviceTypeLen, dwDeviceNameLen, dwPortNameLen;
  543. DWORD dwClientDefaultOffLen;
  544. DWORD dwStructSize;
  545. DWORD dwAvailable, dwNumOfParams = 12;
  546. try
  547. {
  548. DebugPrintf(("PortGetInfo\n"));
  549. if (hIOPort == INVALID_HANDLE_VALUE &&
  550. (pSPCB = FindPortNameInList(pszPortName)) == NULL)
  551. {
  552. // Port is not yet open
  553. // Read from Serial.ini
  554. GetValueFromFile(pszPortName, SER_DEFAULTOFF_KEY, szDefaultOff, RAS_MAXLINEBUFLEN);
  555. GetValueFromFile(pszPortName, SER_MAXCONNECTBPS_KEY, szConnectBPS, MAX_BPS_STR_LEN);
  556. GetValueFromFile(pszPortName, SER_MAXCARRIERBPS_KEY, szCarrierBPS, MAX_BPS_STR_LEN);
  557. GetValueFromFile(pszPortName, SER_DEVICETYPE_KEY, szDeviceType, MAX_DEVICETYPE_NAME + 1);
  558. GetValueFromFile(pszPortName, SER_DEVICENAME_KEY, szDeviceName, MAX_DEVICE_NAME + 1);
  559. strcpy(szPortName, pszPortName);
  560. // Set RAS default values in the DCB
  561. SetDcbDefaults(&DCB);
  562. }
  563. else
  564. {
  565. // Port is open; Get a Device Control Block with current port values
  566. if (hIOPort != INVALID_HANDLE_VALUE)
  567. {
  568. pSPCB = FindPortInList(hIOPort, NULL);
  569. if (pSPCB == NULL)
  570. {
  571. gLastError = ERROR_PORT_NOT_OPEN;
  572. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  573. }
  574. }
  575. if (!GetCommState(pSPCB->hIOPort, &DCB))
  576. {
  577. gLastError = GetLastError();
  578. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  579. }
  580. _itoa(DCB.BaudRate, szConnectBPS, 10);
  581. strcpy(szCarrierBPS, pSPCB->szCarrierBPS);
  582. strcpy(szDefaultOff, pSPCB->szDefaultOff);
  583. strcpy(szDeviceType, pSPCB->szDeviceType);
  584. strcpy(szDeviceName, pSPCB->szDeviceName);
  585. strcpy(szPortName, pSPCB->szPortName);
  586. }
  587. // Read from Serial.ini even if port is open
  588. GetValueFromFile(szPortName, SER_C_DEFAULTOFFSTR_KEY, szClientDefaultOff, RAS_MAXLINEBUFLEN);
  589. // Calculate Buffer size needed
  590. dwStructSize = sizeof(RASMAN_PORTINFO)
  591. + sizeof(RAS_PARAMS) * (dwNumOfParams - 1);
  592. dwConnectBPSLen = strlen(szConnectBPS);
  593. dwCarrierBPSLen = strlen(szCarrierBPS);
  594. dwDeviceTypeLen = strlen(szDeviceType);
  595. dwDeviceNameLen = strlen(szDeviceName);
  596. dwDefaultOffLen = strlen(szDefaultOff);
  597. dwPortNameLen = strlen(szPortName);
  598. dwClientDefaultOffLen = strlen(szClientDefaultOff);
  599. dwAvailable = *pdwSize;
  600. *pdwSize = (dwStructSize + dwConnectBPSLen + dwCarrierBPSLen
  601. + dwDeviceTypeLen + dwDeviceNameLen
  602. + dwDefaultOffLen + dwPortNameLen
  603. + dwClientDefaultOffLen +
  604. + 7L); //Zero bytes
  605. if (*pdwSize > dwAvailable)
  606. return(ERROR_BUFFER_TOO_SMALL);
  607. // Fill in Buffer
  608. ((RASMAN_PORTINFO *)pBuffer)->PI_NumOfParams = ( WORD ) dwNumOfParams;
  609. pParam = ((RASMAN_PORTINFO *)pBuffer)->PI_Params;
  610. pValue = pBuffer + dwStructSize;
  611. strcpy(pParam->P_Key, SER_CONNECTBPS_KEY);
  612. pParam->P_Type = String;
  613. pParam->P_Attributes = 0;
  614. pParam->P_Value.String.Length = dwConnectBPSLen;
  615. pParam->P_Value.String.Data = pValue;
  616. strcpy(pParam->P_Value.String.Data, szConnectBPS);
  617. pValue += dwConnectBPSLen + 1;
  618. pParam++;
  619. strcpy(pParam->P_Key, SER_DATABITS_KEY);
  620. pParam->P_Type = Number;
  621. pParam->P_Attributes = 0;
  622. pParam->P_Value.Number = DCB.ByteSize;
  623. pParam++;
  624. strcpy(pParam->P_Key, SER_PARITY_KEY);
  625. pParam->P_Type = Number;
  626. pParam->P_Attributes = 0;
  627. pParam->P_Value.Number = DCB.Parity;
  628. pParam++;
  629. strcpy(pParam->P_Key, SER_STOPBITS_KEY);
  630. pParam->P_Type = Number;
  631. pParam->P_Attributes = 0;
  632. pParam->P_Value.Number = DCB.StopBits;
  633. pParam++;
  634. strcpy(pParam->P_Key, SER_HDWFLOWCTRLON_KEY);
  635. pParam->P_Type = Number;
  636. pParam->P_Attributes = 0;
  637. pParam->P_Value.Number = DCB.fOutxCtsFlow;
  638. pParam++;
  639. strcpy(pParam->P_Key, SER_CARRIERBPS_KEY);
  640. pParam->P_Type = String;
  641. pParam->P_Attributes = 0;
  642. pParam->P_Value.String.Length = dwCarrierBPSLen;
  643. pParam->P_Value.String.Data = pValue;
  644. strcpy(pParam->P_Value.String.Data, szCarrierBPS);
  645. pValue += dwCarrierBPSLen + 1;
  646. pParam++;
  647. strcpy(pParam->P_Key, SER_ERRORCONTROLON_KEY);
  648. pParam->P_Type = Number;
  649. pParam->P_Attributes = 0;
  650. if (pSPCB == NULL)
  651. pParam->P_Value.Number = FALSE;
  652. else
  653. pParam->P_Value.Number = pSPCB->bErrorControlOn;
  654. pParam++;
  655. strcpy(pParam->P_Key, SER_DEFAULTOFFSTR_KEY);
  656. pParam->P_Type = String;
  657. pParam->P_Attributes = 0;
  658. pParam->P_Value.String.Length = dwDefaultOffLen;
  659. pParam->P_Value.String.Data = pValue;
  660. strcpy(pParam->P_Value.String.Data, szDefaultOff);
  661. pValue += dwDefaultOffLen + 1;
  662. pParam++;
  663. strcpy(pParam->P_Key, SER_DEVICETYPE_KEY);
  664. pParam->P_Type = String;
  665. pParam->P_Attributes = 0;
  666. pParam->P_Value.String.Length = dwDeviceTypeLen;
  667. pParam->P_Value.String.Data = pValue;
  668. strcpy(pParam->P_Value.String.Data, szDeviceType);
  669. pValue += dwDeviceTypeLen + 1;
  670. pParam++;
  671. strcpy(pParam->P_Key, SER_DEVICENAME_KEY);
  672. pParam->P_Type = String;
  673. pParam->P_Attributes = 0;
  674. pParam->P_Value.String.Length = dwDeviceNameLen;
  675. pParam->P_Value.String.Data = pValue;
  676. strcpy(pParam->P_Value.String.Data, szDeviceName);
  677. pValue += dwDeviceNameLen + 1;
  678. pParam++;
  679. strcpy(pParam->P_Key, SER_PORTNAME_KEY);
  680. pParam->P_Type = String;
  681. pParam->P_Attributes = 0;
  682. pParam->P_Value.String.Length = dwPortNameLen;
  683. pParam->P_Value.String.Data = pValue;
  684. strcpy(pParam->P_Value.String.Data, szPortName);
  685. pValue += dwPortNameLen + 1;
  686. pParam++;
  687. strcpy(pParam->P_Key, SER_C_DEFAULTOFFSTR_KEY);
  688. pParam->P_Type = String;
  689. pParam->P_Attributes = 0;
  690. pParam->P_Value.String.Length = dwClientDefaultOffLen;
  691. pParam->P_Value.String.Data = pValue;
  692. strcpy(pParam->P_Value.String.Data, szClientDefaultOff);
  693. //pValue += dwClientDefaultOffLen + 1;
  694. return(SUCCESS);
  695. }
  696. except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH)
  697. {
  698. return(gLastError);
  699. }
  700. }
  701. //* PortSetInfo ------------------------------------------------------------
  702. //
  703. // Function: The values for most input keys are used to set the port
  704. // parameters directly. However, the carrier BPS and the
  705. // error conrol on flag set fields in the Serial Port Control
  706. // Block only, and not the port.
  707. //
  708. // Returns: SUCCESS
  709. // ERROR_WRONG_INFO_SPECIFIED
  710. // Values returned by GetLastError()
  711. //*
  712. DWORD APIENTRY
  713. PortSetInfo(HANDLE hIOPort, RASMAN_PORTINFO *pInfo)
  714. {
  715. RAS_PARAMS *p;
  716. SERIALPCB *pSPCB;
  717. DCB DCB;
  718. WORD i;
  719. BOOL bTypeError = FALSE;
  720. try
  721. {
  722. DebugPrintf(("PortSetInfo\n\thPort = %d\n", hIOPort));
  723. // Find the SerialPCB which contains hIOPOrt
  724. pSPCB = FindPortInList(hIOPort, NULL);
  725. if (pSPCB == NULL)
  726. {
  727. gLastError = ERROR_PORT_NOT_OPEN;
  728. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  729. }
  730. // Get a Device Control Block with current port values
  731. if (!GetCommState(hIOPort, &DCB))
  732. return(GetLastError());
  733. // Set DCB and PCB values
  734. for (i=0, p=pInfo->PI_Params; i<pInfo->PI_NumOfParams; i++, p++)
  735. {
  736. // Set DCB values
  737. if (_stricmp(p->P_Key, SER_CONNECTBPS_KEY) == 0)
  738. DCB.BaudRate = ValueToNum(p);
  739. else if (_stricmp(p->P_Key, SER_DATABITS_KEY) == 0)
  740. DCB.ByteSize = (BYTE) ValueToNum(p);
  741. else if (_stricmp(p->P_Key, SER_PARITY_KEY) == 0)
  742. DCB.Parity = (BYTE) ValueToNum(p);
  743. else if (_stricmp(p->P_Key, SER_STOPBITS_KEY) == 0)
  744. DCB.StopBits = (BYTE) ValueToNum(p);
  745. else if (_stricmp(p->P_Key, SER_HDWFLOWCTRLON_KEY) == 0)
  746. DCB.fOutxCtsFlow = ValueToBool(p);
  747. // Set PCB values
  748. else if (_stricmp(p->P_Key, SER_CARRIERBPS_KEY) == 0)
  749. if (p->P_Type == String)
  750. {
  751. strncpy(pSPCB->szCarrierBPS,
  752. p->P_Value.String.Data,
  753. p->P_Value.String.Length);
  754. pSPCB->szCarrierBPS[p->P_Value.String.Length] = '\0';
  755. }
  756. else
  757. _itoa(p->P_Value.Number, pSPCB->szCarrierBPS, 10);
  758. else if (_stricmp(p->P_Key, SER_ERRORCONTROLON_KEY) == 0)
  759. pSPCB->bErrorControlOn = ValueToBool(p);
  760. else if (_stricmp(p->P_Key, SER_DEFAULTOFF_KEY) == 0)
  761. if (p->P_Type == String)
  762. {
  763. strncpy(pSPCB->szDefaultOff,
  764. p->P_Value.String.Data,
  765. p->P_Value.String.Length);
  766. pSPCB->szDefaultOff[p->P_Value.String.Length] = '\0';
  767. }
  768. else
  769. pSPCB->szDefaultOff[0] = USE_DEVICE_INI_DEFAULT;
  770. else
  771. return(ERROR_WRONG_INFO_SPECIFIED);
  772. } // for
  773. // Send DCB to Port
  774. if (!SetCommState(hIOPort, &DCB))
  775. return(GetLastError());
  776. return(SUCCESS);
  777. }
  778. except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH)
  779. {
  780. return(gLastError);
  781. }
  782. }
  783. //* PortTestSignalState ----------------------------------------------------
  784. //
  785. // Function: This API indicates the state of the DSR and DTR lines.
  786. // DSR - Data Set Ready
  787. // DCD - Data Carrier Detect (RLSD - Received Line Signal Detect)
  788. //
  789. // Returns: SUCCESS
  790. // Values returned by GetLastError()
  791. //
  792. //*
  793. DWORD APIENTRY
  794. PortTestSignalState(HANDLE hIOPort, DWORD *pdwDeviceState)
  795. {
  796. DWORD dwModemStatus;
  797. SERIALPCB *pSPCB;
  798. DWORD dwSetMask = 0 ;
  799. DebugPrintf(("PortTestSignalState\n"));
  800. *pdwDeviceState = 0;
  801. if ((pSPCB = FindPortInList (hIOPort, NULL)) == NULL)
  802. return ERROR_PORT_NOT_OPEN ;
  803. if (!GetCommModemStatus(hIOPort, &dwModemStatus))
  804. {
  805. *pdwDeviceState = 0xffffffff;
  806. return(GetLastError());
  807. }
  808. // If DSR is down AND it was up before then mark it as a hw failure.
  809. //
  810. if ((!(dwModemStatus & MS_DSR_ON)) && (pSPCB->dwMonitorDSRMask))
  811. *pdwDeviceState |= SS_HARDWAREFAILURE;
  812. // Similarly, if DCD is down and it was up before then link has dropped.
  813. //
  814. if (!(dwModemStatus & MS_RLSD_ON))
  815. *pdwDeviceState |= SS_LINKDROPPED;
  816. else
  817. dwSetMask = EV_RLSD ;
  818. if (pSPCB->uRasEndpoint != INVALID_HANDLE_VALUE) {
  819. ASYMAC_DCDCHANGE A ;
  820. DWORD dwBytesReturned;
  821. A.MacAdapter = NULL ;
  822. A.hNdisEndpoint = (HANDLE) pSPCB->uRasEndpoint ;
  823. DeviceIoControl(pSPCB->hAsyMac,
  824. IOCTL_ASYMAC_DCDCHANGE,
  825. &A,
  826. sizeof(A),
  827. &A,sizeof(A),
  828. &dwBytesReturned,
  829. (LPOVERLAPPED)&(pSPCB->MonitorDevice)) ;
  830. } else {
  831. dwSetMask |= (pSPCB->dwMonitorDSRMask) ; // Only monitor DSR if it is used.
  832. if (dwSetMask == 0)
  833. return (SUCCESS) ; // do not set wait mask.
  834. if (dwModemStatus == pSPCB->dwPreviousModemStatus)
  835. {
  836. //DbgPrint("PortTestSignalState: Modemstatus hasn't changed\n");
  837. return SUCCESS;
  838. }
  839. else
  840. pSPCB->dwPreviousModemStatus = dwModemStatus;
  841. //DbgPrint("PortTestSignalState: Setting mask ox%x\n", dwSetMask);
  842. SetCommMask(hIOPort, dwSetMask);
  843. // Start a new wait on signal lines (DSR and/or DCD)
  844. if (!WaitCommEvent(hIOPort,
  845. &(pSPCB->dwEventMask),
  846. (LPOVERLAPPED)&(pSPCB->MonitorDevice)))
  847. {
  848. //DbgPrint("PortTestSignalState: WaitCommEvent. %d\n", GetLastError());
  849. }
  850. }
  851. return(SUCCESS);
  852. }
  853. //* PortConnect ------------------------------------------------------------
  854. //
  855. // Function: This API is called when a connection has been completed and some
  856. // steps need to be taken, If bWaitForDevice is set then we monitor DCD only
  857. // else,
  858. // It in turn calls the asyncmac device driver in order to
  859. // indicate to asyncmac that the port and the connection
  860. // over it are ready for commumication.
  861. //
  862. // pdwCompressionInfo is an output only parameter which
  863. // indicates the type(s) of compression supported by the MAC.
  864. //
  865. // bWaitForDevice is set to TRUE when we just want to start monitoring DCD
  866. //
  867. // Returns: SUCCESS
  868. // ERROR_PORT_NOT_OPEN
  869. // ERROR_NO_CONNECTION
  870. // Values returned by GetLastError()
  871. //
  872. //*
  873. DWORD APIENTRY
  874. PortConnect(HANDLE hIOPort,
  875. BOOL bWaitForDevice,
  876. HANDLE *pRasEndpoint)
  877. {
  878. ASYMAC_OPEN AsyMacOpen;
  879. ASYMAC_DCDCHANGE A ;
  880. SERIALPCB *pSPCB;
  881. BOOL bPadDevice;
  882. DWORD dwModemStatus, dwBytesReturned;
  883. TCHAR szDeviceType[RAS_MAXLINEBUFLEN];
  884. // This is a special mode of PortConnect where all we do is start monitoring DCD
  885. // Hand off to asyncmac does not happen till the next call to port connect where the
  886. // bWaitForDevice flag is false
  887. //
  888. if (bWaitForDevice) {
  889. pSPCB = FindPortInList(hIOPort, NULL);
  890. if (pSPCB == NULL)
  891. {
  892. gLastError = ERROR_PORT_NOT_OPEN;
  893. return ERROR_NO_CONNECTION ;
  894. }
  895. if (!GetCommModemStatus(hIOPort, &dwModemStatus))
  896. return(GetLastError());
  897. // UPDATE the DSR monitoring
  898. //
  899. if (!(dwModemStatus & MS_DSR_ON))
  900. pSPCB->dwMonitorDSRMask = 0 ;
  901. else
  902. pSPCB->dwMonitorDSRMask = EV_DSR ;
  903. // Tell serial driver to signal rasman if DCD, (and DSR, if it was used) drop
  904. //
  905. //DbgPrint("PortConnect: Setting mask to 0x%x\n",EV_RLSD | (pSPCB->dwMonitorDSRMask));
  906. if (!SetCommMask(hIOPort, EV_RLSD | (pSPCB->dwMonitorDSRMask)))
  907. return(GetLastError());
  908. WaitCommEvent(hIOPort,
  909. &(pSPCB->dwEventMask),
  910. (LPOVERLAPPED) &(pSPCB->MonitorDevice)) ;
  911. return SUCCESS ;
  912. }
  913. // Else we do both - change DCD monitoring and handing off context to asyncmac
  914. //
  915. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  916. try
  917. {
  918. DebugPrintf(("PortConnect\n"));
  919. // Find port in list
  920. pSPCB = FindPortInList(hIOPort, NULL);
  921. if (pSPCB == NULL)
  922. {
  923. gLastError = ERROR_PORT_NOT_OPEN;
  924. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  925. }
  926. //Make sure connection is still up
  927. if (!GetCommModemStatus(hIOPort, &dwModemStatus))
  928. return(GetLastError());
  929. // Make sure that DSR is still up (if it ever was up!)
  930. if ((!(dwModemStatus & MS_DSR_ON)) && (pSPCB->dwMonitorDSRMask)) {
  931. OutputDebugString ("DSR down!!!\r\n") ;
  932. return(ERROR_NO_CONNECTION); //Device is down
  933. }
  934. if (!(dwModemStatus & MS_RLSD_ON) ) {
  935. OutputDebugString ("DCD down!!!\r\n") ;
  936. return(ERROR_NO_CONNECTION); //DCD is down
  937. }
  938. // // UPDATE the DSR monitoring
  939. // //
  940. // if ( ! (dwModemStatus & MS_DSR_ON)) {
  941. // pSPCB->dwMonitorDSRMask = 0 ;
  942. // } else {
  943. // pSPCB->dwMonitorDSRMask = EV_DSR ;
  944. // }
  945. //
  946. // // Tell system to signal rasman if DCD, (and DSR, if it was used) drop
  947. //
  948. // if (!SetCommMask(hIOPort, EV_RLSD | (pSPCB->dwMonitorDSRMask)))
  949. // return(GetLastError());
  950. //
  951. // WaitCommEvent(hIOPort,
  952. // &(pSPCB->dwEventMask),
  953. // &(pSPCB->MonitorDevice)) ;
  954. //Put endpoint in Serial PCB for later use by PortDisconnect
  955. //Find if device type is Pad
  956. GetValueFromFile(pSPCB->szPortName, SER_DEVICETYPE_KEY, szDeviceType, RAS_MAXLINEBUFLEN);
  957. bPadDevice = (_stricmp(szDeviceType, MXS_PAD_TXT) == 0);
  958. // Let the ASYMAC notify us of DCD and DSR change
  959. //
  960. //DbgPrint("PortConnect: Setting mask to 0\n");
  961. if (!SetCommMask(hIOPort, 0)) // Set mask to stop monitoring DCD
  962. return(GetLastError());
  963. //Open AsyncMac (Hand off port to AsyncMac)
  964. AsyMacOpen.hNdisEndpoint = INVALID_HANDLE_VALUE ;
  965. AsyMacOpen.LinkSpeed = (atoi(pSPCB->szCarrierBPS) == 0) ?
  966. 14400 :
  967. atoi(pSPCB->szCarrierBPS) ;
  968. AsyMacOpen.FileHandle = hIOPort;
  969. if (bPadDevice || pSPCB->bErrorControlOn)
  970. AsyMacOpen.QualOfConnect = (UINT)NdisWanErrorControl;
  971. else
  972. AsyMacOpen.QualOfConnect = (UINT)NdisWanRaw;
  973. if (!DeviceIoControl(pSPCB->hAsyMac,
  974. IOCTL_ASYMAC_OPEN,
  975. &AsyMacOpen,
  976. sizeof(AsyMacOpen),
  977. &AsyMacOpen,
  978. sizeof(AsyMacOpen),
  979. &dwBytesReturned,
  980. &overlapped))
  981. {
  982. // Clear the stored end point, so that if it failed to open
  983. // no attempt will be made to close it.
  984. pSPCB->uRasEndpoint = INVALID_HANDLE_VALUE;
  985. return(GetLastError());
  986. } else
  987. pSPCB->uRasEndpoint = AsyMacOpen.hNdisEndpoint;
  988. *pRasEndpoint = AsyMacOpen.hNdisEndpoint ;
  989. //DbgPrint("PortConnect: RasEndpoint = 0x%x\n", *pRasEndpoint);
  990. A.hNdisEndpoint = (HANDLE) *pRasEndpoint ;
  991. A.MacAdapter = NULL ;
  992. if (!DeviceIoControl(pSPCB->hAsyMac,
  993. IOCTL_ASYMAC_DCDCHANGE,
  994. &A,
  995. sizeof(A),
  996. &A,
  997. sizeof(A),
  998. &dwBytesReturned,
  999. (LPOVERLAPPED)&(pSPCB->MonitorDevice)))
  1000. {
  1001. ;//DbgPrint("PortConnect: DeviceIoControl (IOCTL_ASYMAC_DCDCHANGE) failed. %d\n",
  1002. // GetLastError());
  1003. }
  1004. PortClearStatistics(hIOPort);
  1005. // if (!(dwModemStatus & MS_RLSD_ON))
  1006. // return(PENDING); //DCD is down
  1007. // else
  1008. return(SUCCESS);
  1009. }
  1010. except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH)
  1011. {
  1012. return(gLastError);
  1013. }
  1014. }
  1015. //* PortDisconnect ---------------------------------------------------------
  1016. //
  1017. // Function: This API is called to drop a connection and close AsyncMac.
  1018. //
  1019. // Returns: SUCCESS
  1020. // PENDING
  1021. // ERROR_PORT_NOT_OPEN
  1022. //
  1023. //*
  1024. DWORD APIENTRY
  1025. PortDisconnect(HANDLE hIOPort)
  1026. {
  1027. ASYMAC_CLOSE AsyMacClose;
  1028. SERIALPCB *pSPCB;
  1029. DWORD dwModemStatus, dwBytesReturned;
  1030. DWORD retcode ;
  1031. DWORD dwSetMask = 0;
  1032. DWORD fdwAction = PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR;
  1033. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  1034. try
  1035. {
  1036. DebugPrintf(("PortDisconnect\n"));
  1037. //Signal other end of link that connection is being dropped
  1038. if (!EscapeCommFunction(hIOPort, CLRDTR))
  1039. {
  1040. ;//DbgPrint("PortDisconnect: EscapeCommFunction Failed. %d\n", GetLastError());
  1041. }
  1042. //
  1043. // Apparently, DTR isn't really down
  1044. // yet, even though this call is supposed
  1045. // to be synchronous to the serial driver.
  1046. // We sleep here for a while to make sure
  1047. // DTR drops.
  1048. //
  1049. Sleep(100);
  1050. //Find port in list
  1051. if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL)
  1052. {
  1053. gLastError = ERROR_PORT_NOT_OPEN;
  1054. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  1055. }
  1056. if (pSPCB->uRasEndpoint != INVALID_HANDLE_VALUE)
  1057. {
  1058. // Update statistics before closing Asyncmac
  1059. if ((retcode = UpdateStatistics(pSPCB)) != SUCCESS)
  1060. {
  1061. gLastError = retcode;
  1062. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  1063. }
  1064. //Close AsynacMac
  1065. AsyMacClose.MacAdapter = NULL;
  1066. AsyMacClose.hNdisEndpoint = (HANDLE) pSPCB->uRasEndpoint;
  1067. DeviceIoControl(pSPCB->hAsyMac,
  1068. IOCTL_ASYMAC_CLOSE,
  1069. &AsyMacClose,
  1070. sizeof(AsyMacClose),
  1071. &AsyMacClose,
  1072. sizeof(AsyMacClose),
  1073. &dwBytesReturned,
  1074. &overlapped);
  1075. pSPCB->uRasEndpoint = INVALID_HANDLE_VALUE;
  1076. }
  1077. PurgeComm(hIOPort, fdwAction) ; // flush the ports
  1078. //Check whether DCD has dropped yet
  1079. GetCommModemStatus(hIOPort, &dwModemStatus);
  1080. if (dwModemStatus & MS_RLSD_ON) {
  1081. //DbgPrint("PortDisconnect: DCD hasn't dropped yet!\n");
  1082. dwSetMask = EV_RLSD ;
  1083. retcode = PENDING ; // not yet dropped.
  1084. } else
  1085. retcode = SUCCESS ;
  1086. // UPDATE the DSR monitoring: this restores the DCR to what it was when
  1087. // the port was opened.
  1088. //
  1089. pSPCB->dwMonitorDSRMask = pSPCB->dwActiveDSRMask ;
  1090. dwSetMask |= (pSPCB->dwMonitorDSRMask) ;
  1091. if (dwSetMask != 0) { // set only if mask is not 0
  1092. //DbgPrint("PortDisconnect: Setting mask to 0x%x\n", dwSetMask);
  1093. SetCommMask (hIOPort, dwSetMask);
  1094. if (!WaitCommEvent(hIOPort,
  1095. &(pSPCB->dwEventMask),
  1096. (LPOVERLAPPED)&(pSPCB->MonitorDevice)))
  1097. {
  1098. //DbgPrint("PortDisconnect: WaitCommEvent. %d\n", GetLastError());
  1099. }
  1100. }
  1101. //Since DCD may have dropped after GetCommModemStatus and
  1102. // before WaitCommEvent, check it again.
  1103. if (retcode != SUCCESS)
  1104. {
  1105. GetCommModemStatus(hIOPort, &dwModemStatus);
  1106. if (dwModemStatus & MS_RLSD_ON)
  1107. {
  1108. //DbgPrint("PortDisconnect: DCD hasn't dropped yet. 2\n");
  1109. retcode = PENDING ; // not yet dropped.
  1110. }
  1111. else
  1112. retcode = SUCCESS ;
  1113. }
  1114. // Set the default connect baud
  1115. //
  1116. SetCommDefaults(pSPCB->hIOPort, pSPCB->szPortName);
  1117. }
  1118. except(exception_code()==EXCEPT_RAS_MEDIA ? HANDLE_EXCEPTION:CONTINUE_SEARCH)
  1119. {
  1120. return(gLastError);
  1121. }
  1122. return retcode ;
  1123. }
  1124. //* PortInit ---------------------------------------------------------------
  1125. //
  1126. // Function: This API re-initializes the com port after use.
  1127. //
  1128. // Returns: SUCCESS
  1129. // ERROR_PORT_NOT_CONFIGURED
  1130. // ERROR_DEVICE_NOT_READY
  1131. //
  1132. //*
  1133. DWORD APIENTRY
  1134. PortInit(HANDLE hIOPort)
  1135. {
  1136. DWORD fdwAction = PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR;
  1137. DWORD dwErrors;
  1138. SERIALPCB *pSPCB;
  1139. DebugPrintf(("PortInit\n"));
  1140. pSPCB = FindPortInList(hIOPort, NULL) ;
  1141. // Raise DTR
  1142. if (!EscapeCommFunction(hIOPort, SETDTR))
  1143. return(GetLastError());
  1144. if (!PurgeComm(hIOPort, fdwAction))
  1145. return(GetLastError());
  1146. if (!ClearCommError(hIOPort, &dwErrors, NULL))
  1147. return(GetLastError());
  1148. // Reset szCarrierBPS to MAXCARRIERBPS from ini file
  1149. //
  1150. InitCarrierBps(pSPCB->szPortName, pSPCB->szCarrierBPS);
  1151. return(SUCCESS);
  1152. }
  1153. //* PortSend ---------------------------------------------------------------
  1154. //
  1155. // Function: This API sends a buffer to the port. This API is
  1156. // asynchronous and normally returns PENDING; however, if
  1157. // WriteFile returns synchronously, the API will return
  1158. // SUCCESS.
  1159. //
  1160. // Returns: SUCCESS
  1161. // PENDING
  1162. // Return code from GetLastError
  1163. //
  1164. //*
  1165. DWORD
  1166. PortSend(HANDLE hIOPort, BYTE *pBuffer, DWORD dwSize)
  1167. {
  1168. SERIALPCB *pSPCB;
  1169. DWORD dwRC, pdwBytesWritten;
  1170. BOOL bIODone;
  1171. DebugPrintf(("PortSend\n"));
  1172. // Find the SerialPCB which contains hIOPOrt
  1173. pSPCB = FindPortInList(hIOPort, NULL);
  1174. if (pSPCB == NULL)
  1175. return(ERROR_PORT_NOT_OPEN);
  1176. // Send Buffer to Port
  1177. bIODone = WriteFile(hIOPort,
  1178. pBuffer,
  1179. dwSize,
  1180. &pdwBytesWritten, //pdwBytesWritten is not used
  1181. (LPOVERLAPPED)&(pSPCB->SendReceive));
  1182. if (bIODone)
  1183. return(PENDING);
  1184. else if ((dwRC = GetLastError()) == ERROR_IO_PENDING)
  1185. return(PENDING);
  1186. else
  1187. return(dwRC);
  1188. }
  1189. //* PortReceive ------------------------------------------------------------
  1190. //
  1191. // Function: This API reads from the port. This API is
  1192. // asynchronous and normally returns PENDING; however, if
  1193. // ReadFile returns synchronously, the API will return
  1194. // SUCCESS.
  1195. //
  1196. // Returns: SUCCESS
  1197. // PENDING
  1198. // Return code from GetLastError
  1199. //
  1200. //*
  1201. DWORD
  1202. PortReceive(HANDLE hIOPort,
  1203. BYTE *pBuffer,
  1204. DWORD dwSize,
  1205. DWORD dwTimeOut)
  1206. {
  1207. COMMTIMEOUTS CT;
  1208. SERIALPCB *pSPCB;
  1209. DWORD dwRC, pdwBytesRead;
  1210. BOOL bIODone;
  1211. DebugPrintf(("PortReceive\n"));
  1212. // Find the SerialPCB which contains hIOPOrt
  1213. pSPCB = FindPortInList(hIOPort, NULL);
  1214. if (pSPCB == NULL)
  1215. return(ERROR_PORT_NOT_OPEN);
  1216. // Set Read Timeouts
  1217. CT.ReadIntervalTimeout = 0;
  1218. CT.ReadTotalTimeoutMultiplier = 0;
  1219. CT.ReadTotalTimeoutConstant = dwTimeOut;
  1220. if ( ! SetCommTimeouts(hIOPort, &CT))
  1221. return(GetLastError());
  1222. // Read from Port
  1223. bIODone = ReadFile(hIOPort,
  1224. pBuffer,
  1225. dwSize,
  1226. &pdwBytesRead, //pdwBytesRead is not used
  1227. (LPOVERLAPPED)&(pSPCB->SendReceive));
  1228. if (bIODone) {
  1229. return(PENDING);
  1230. }
  1231. else if ((dwRC = GetLastError()) == ERROR_IO_PENDING)
  1232. return(PENDING);
  1233. else
  1234. return(dwRC);
  1235. }
  1236. //* PortReceiveComplete ------------------------------------------------------
  1237. //
  1238. // Function: Completes a read - if still PENDING it cancels it - else it returns the bytes read.
  1239. // PortClearStatistics.
  1240. //
  1241. // Returns: SUCCESS
  1242. // ERROR_PORT_NOT_OPEN
  1243. //*
  1244. DWORD
  1245. PortReceiveComplete (HANDLE hIOPort, PDWORD bytesread)
  1246. {
  1247. SERIALPCB *pSPCB;
  1248. // Find the SerialPCB which contains hIOPOrt
  1249. pSPCB = FindPortInList(hIOPort, NULL);
  1250. if (pSPCB == NULL)
  1251. return(ERROR_PORT_NOT_OPEN);
  1252. if (!GetOverlappedResult(hIOPort,
  1253. (LPOVERLAPPED)&(pSPCB->SendReceive),
  1254. bytesread,
  1255. FALSE))
  1256. {
  1257. #if DBG
  1258. DbgPrint("PortReceiveComplete: GetOverlappedResult failed. %d", GetLastError());
  1259. #endif
  1260. PurgeComm (hIOPort, PURGE_RXABORT) ;
  1261. *bytesread = 0 ;
  1262. }
  1263. return SUCCESS ;
  1264. }
  1265. //* PortCompressionSetInfo -------------------------------------------------
  1266. //
  1267. // Function: This API selects Asyncmac compression mode by setting
  1268. // Asyncmac's compression bits.
  1269. //
  1270. // Returns: SUCCESS
  1271. // Return code from GetLastError
  1272. //
  1273. //*
  1274. DWORD
  1275. PortCompressionSetInfo(HANDLE hIOPort)
  1276. {
  1277. // Not supported anymore -
  1278. return(SUCCESS);
  1279. }
  1280. //* PortClearStatistics ----------------------------------------------------
  1281. //
  1282. // Function: This API is used to mark the beginning of the period for which
  1283. // statistics will be reported. The current numbers are copied
  1284. // from the MAC and stored in the Serial Port Control Block. At
  1285. // the end of the period PortGetStatistics will be called to
  1286. // compute the difference.
  1287. //
  1288. // Returns: SUCCESS
  1289. // ERROR_PORT_NOT_OPEN
  1290. //*
  1291. DWORD
  1292. PortClearStatistics(HANDLE hIOPort)
  1293. {
  1294. #if 0
  1295. ASYMAC_GETSTATS A;
  1296. int i;
  1297. DWORD dwBytesReturned;
  1298. SERIALPCB *pSPCB;
  1299. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  1300. DebugPrintf(("PortClearStatistics\n"));
  1301. // Find port in list
  1302. if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL)
  1303. return(ERROR_PORT_NOT_OPEN);
  1304. // Check whether Asyncmac is open
  1305. if (pSPCB->uRasEndpoint == INVALID_RASENDPOINT)
  1306. for (i=0; i<NUM_RAS_SERIAL_STATS; i++) // Asymac is closed
  1307. pSPCB->Stats[i] = 0;
  1308. else // Asyncmac is open
  1309. {
  1310. // Fill in GetStats struct
  1311. A.MacAdapter = NULL;
  1312. A.hNdisEndpoint = pSPCB->uRasEndpoint;
  1313. // Call Asymac
  1314. if (!DeviceIoControl(pSPCB->hAsyMac,
  1315. IOCTL_ASYMAC_GETSTATS,
  1316. &A,
  1317. sizeof(A),
  1318. &A,
  1319. sizeof(A),
  1320. &dwBytesReturned,
  1321. &overlapped))
  1322. return(GetLastError());
  1323. // Update Stats in Serial Port Control Block
  1324. pSPCB->Stats[BYTES_XMITED] = A.AsyMacStats.GenericStats.BytesTransmitted;
  1325. pSPCB->Stats[BYTES_RCVED] = A.AsyMacStats.GenericStats.BytesReceived;
  1326. pSPCB->Stats[FRAMES_XMITED] = A.AsyMacStats.GenericStats.FramesTransmitted;
  1327. pSPCB->Stats[FRAMES_RCVED] = A.AsyMacStats.GenericStats.FramesReceived;
  1328. pSPCB->Stats[CRC_ERR] = A.AsyMacStats.SerialStats.CRCErrors;
  1329. pSPCB->Stats[TIMEOUT_ERR] = A.AsyMacStats.SerialStats.TimeoutErrors;
  1330. pSPCB->Stats[ALIGNMENT_ERR] = A.AsyMacStats.SerialStats.AlignmentErrors;
  1331. pSPCB->Stats[SERIAL_OVERRUN_ERR]
  1332. = A.AsyMacStats.SerialStats.SerialOverrunErrors;
  1333. pSPCB->Stats[FRAMING_ERR] = A.AsyMacStats.SerialStats.FramingErrors;
  1334. pSPCB->Stats[BUFFER_OVERRUN_ERR]
  1335. = A.AsyMacStats.SerialStats.BufferOverrunErrors;
  1336. pSPCB->Stats[BYTES_XMITED_UNCOMP]
  1337. = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed;
  1338. pSPCB->Stats[BYTES_RCVED_UNCOMP]
  1339. = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed;
  1340. pSPCB->Stats[BYTES_XMITED_COMP]
  1341. = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed;
  1342. pSPCB->Stats[BYTES_RCVED_COMP]
  1343. = A.AsyMacStats.CompressionStats.BytesReceivedCompressed;
  1344. }
  1345. #endif
  1346. return(SUCCESS);
  1347. }
  1348. //* PortGetStatistics ------------------------------------------------------
  1349. //
  1350. // Function: This API reports MAC statistics since the last call to
  1351. // PortClearStatistics.
  1352. //
  1353. // Returns: SUCCESS
  1354. // ERROR_PORT_NOT_OPEN
  1355. //*
  1356. DWORD
  1357. PortGetStatistics(HANDLE hIOPort, RAS_STATISTICS *pStat)
  1358. {
  1359. #if 0
  1360. ASYMAC_GETSTATS A;
  1361. DWORD dwBytesReturned;
  1362. SERIALPCB *pSPCB;
  1363. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  1364. DebugPrintf(("PortGetStatistics\n"));
  1365. // Find port in list
  1366. if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL)
  1367. return(ERROR_PORT_NOT_OPEN);
  1368. // Check whether Asyncmac is open
  1369. if (pSPCB->uRasEndpoint == INVALID_RASENDPOINT)
  1370. {
  1371. // Asyncmac is closed
  1372. // Report current counts
  1373. pStat->S_NumOfStatistics = NUM_RAS_SERIAL_STATS;
  1374. pStat->S_Statistics[BYTES_XMITED] = pSPCB->Stats[BYTES_XMITED];
  1375. pStat->S_Statistics[BYTES_RCVED] = pSPCB->Stats[BYTES_RCVED];
  1376. pStat->S_Statistics[FRAMES_XMITED] = pSPCB->Stats[FRAMES_XMITED];
  1377. pStat->S_Statistics[FRAMES_RCVED] = pSPCB->Stats[FRAMES_RCVED];
  1378. pStat->S_Statistics[CRC_ERR] = pSPCB->Stats[CRC_ERR];
  1379. pStat->S_Statistics[TIMEOUT_ERR] = pSPCB->Stats[TIMEOUT_ERR];
  1380. pStat->S_Statistics[ALIGNMENT_ERR] = pSPCB->Stats[ALIGNMENT_ERR];
  1381. pStat->S_Statistics[SERIAL_OVERRUN_ERR] = pSPCB->Stats[SERIAL_OVERRUN_ERR];
  1382. pStat->S_Statistics[FRAMING_ERR] = pSPCB->Stats[FRAMING_ERR];
  1383. pStat->S_Statistics[BUFFER_OVERRUN_ERR] = pSPCB->Stats[BUFFER_OVERRUN_ERR];
  1384. pStat->S_Statistics[BYTES_XMITED_UNCOMP]= pSPCB->Stats[BYTES_XMITED_UNCOMP];
  1385. pStat->S_Statistics[BYTES_RCVED_UNCOMP] = pSPCB->Stats[BYTES_RCVED_UNCOMP];
  1386. pStat->S_Statistics[BYTES_XMITED_COMP] = pSPCB->Stats[BYTES_XMITED_COMP];
  1387. pStat->S_Statistics[BYTES_RCVED_COMP] = pSPCB->Stats[BYTES_RCVED_COMP];
  1388. }
  1389. else
  1390. {
  1391. // Asyncmac is open
  1392. // Fill in GetStats struct
  1393. A.MacAdapter = NULL;
  1394. A.hNdisEndpoint = pSPCB->uRasEndpoint;
  1395. // Call Asymac to get current MAC statistics counts
  1396. if (!DeviceIoControl(pSPCB->hAsyMac,
  1397. IOCTL_ASYMAC_GETSTATS,
  1398. &A,
  1399. sizeof(A),
  1400. &A,
  1401. sizeof(A),
  1402. &dwBytesReturned,
  1403. &overlapped))
  1404. return(GetLastError());
  1405. // Find difference between last PortClearStatistics and current counts
  1406. pStat->S_NumOfStatistics = NUM_RAS_SERIAL_STATS;
  1407. pStat->S_Statistics[BYTES_XMITED]
  1408. = A.AsyMacStats.GenericStats.BytesTransmitted
  1409. - pSPCB->Stats[BYTES_XMITED];
  1410. pStat->S_Statistics[BYTES_RCVED]
  1411. = A.AsyMacStats.GenericStats.BytesReceived
  1412. - pSPCB->Stats[BYTES_RCVED];
  1413. pStat->S_Statistics[FRAMES_XMITED]
  1414. = A.AsyMacStats.GenericStats.FramesTransmitted
  1415. - pSPCB->Stats[FRAMES_XMITED];
  1416. pStat->S_Statistics[FRAMES_RCVED]
  1417. = A.AsyMacStats.GenericStats.FramesReceived
  1418. - pSPCB->Stats[FRAMES_RCVED];
  1419. pStat->S_Statistics[CRC_ERR]
  1420. = A.AsyMacStats.SerialStats.CRCErrors
  1421. - pSPCB->Stats[CRC_ERR];
  1422. pStat->S_Statistics[TIMEOUT_ERR]
  1423. = A.AsyMacStats.SerialStats.TimeoutErrors
  1424. - pSPCB->Stats[TIMEOUT_ERR];
  1425. pStat->S_Statistics[ALIGNMENT_ERR]
  1426. = A.AsyMacStats.SerialStats.AlignmentErrors
  1427. - pSPCB->Stats[ALIGNMENT_ERR];
  1428. pStat->S_Statistics[SERIAL_OVERRUN_ERR]
  1429. = A.AsyMacStats.SerialStats.SerialOverrunErrors
  1430. - pSPCB->Stats[SERIAL_OVERRUN_ERR];
  1431. pStat->S_Statistics[FRAMING_ERR]
  1432. = A.AsyMacStats.SerialStats.FramingErrors
  1433. - pSPCB->Stats[FRAMING_ERR];
  1434. pStat->S_Statistics[BUFFER_OVERRUN_ERR]
  1435. = A.AsyMacStats.SerialStats.BufferOverrunErrors
  1436. - pSPCB->Stats[BUFFER_OVERRUN_ERR];
  1437. pStat->S_Statistics[BYTES_XMITED_UNCOMP]
  1438. = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed
  1439. - pSPCB->Stats[BYTES_XMITED_UNCOMP];
  1440. pStat->S_Statistics[BYTES_RCVED_UNCOMP]
  1441. = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed
  1442. - pSPCB->Stats[BYTES_RCVED_UNCOMP];
  1443. pStat->S_Statistics[BYTES_XMITED_COMP]
  1444. = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed
  1445. - pSPCB->Stats[BYTES_XMITED_COMP];
  1446. pStat->S_Statistics[BYTES_RCVED_COMP]
  1447. = A.AsyMacStats.CompressionStats.BytesReceivedCompressed
  1448. - pSPCB->Stats[BYTES_RCVED_COMP];
  1449. }
  1450. #endif
  1451. return(SUCCESS);
  1452. }
  1453. //* PortSetFraming -------------------------------------------------------
  1454. //
  1455. // Function: Sets the framing type with the mac
  1456. //
  1457. // Returns: SUCCESS
  1458. //
  1459. //*
  1460. DWORD APIENTRY
  1461. PortSetFraming(HANDLE hIOPort, DWORD SendFeatureBits, DWORD RecvFeatureBits,
  1462. DWORD SendBitMask, DWORD RecvBitMask)
  1463. {
  1464. #if 0
  1465. ASYMAC_STARTFRAMING A;
  1466. DWORD dwBytesReturned;
  1467. SERIALPCB *pSPCB;
  1468. memset (&overlapped, 0, sizeof (OVERLAPPED)) ;
  1469. // Find port in list
  1470. if ((pSPCB = FindPortInList(hIOPort, NULL)) == NULL)
  1471. return(ERROR_PORT_NOT_OPEN);
  1472. A.MacAdapter = NULL ;
  1473. A.hNdisEndpoint = pSPCB->uRasEndpoint;
  1474. A.SendFeatureBits = SendFeatureBits;
  1475. A.RecvFeatureBits = RecvFeatureBits;
  1476. A.SendBitMask = SendBitMask;
  1477. A.RecvBitMask = RecvBitMask;
  1478. if (!DeviceIoControl(pSPCB->hAsyMac,
  1479. IOCTL_ASYMAC_STARTFRAMING,
  1480. &A,
  1481. sizeof(A),
  1482. &A,
  1483. sizeof(A),
  1484. &dwBytesReturned,
  1485. &overlapped))
  1486. return(GetLastError());
  1487. #endif
  1488. return(SUCCESS);
  1489. }
  1490. //* PortGetPortState -------------------------------------------------------
  1491. //
  1492. // Function: This API is used in MS-DOS only.
  1493. //
  1494. // Returns: SUCCESS
  1495. //
  1496. //*
  1497. DWORD APIENTRY
  1498. PortGetPortState(char *pszPortName, DWORD *pdwUsage)
  1499. {
  1500. DebugPrintf(("PortGetPortState\n"));
  1501. return(SUCCESS);
  1502. }
  1503. //* PortChangeCallback -----------------------------------------------------
  1504. //
  1505. // Function: This API is used in MS-DOS only.
  1506. //
  1507. // Returns: SUCCESS
  1508. //
  1509. //*
  1510. DWORD APIENTRY
  1511. PortChangeCallback(HANDLE hIOPort)
  1512. {
  1513. DebugPrintf(("PortChangeCallback\n"));
  1514. return(SUCCESS);
  1515. }
  1516. DWORD APIENTRY
  1517. PortSetINetCfg(PVOID pvINetCfg)
  1518. {
  1519. ((void) pvINetCfg);
  1520. return SUCCESS;
  1521. }
  1522. DWORD APIENTRY
  1523. PortSetIoCompletionPort ( HANDLE hIoCompletionPort)
  1524. {
  1525. ((void) hIoCompletionPort);
  1526. return SUCCESS;
  1527. }