Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

735 lines
15 KiB

  1. //****************************************************************************
  2. //
  3. // Microsoft NT Remote Access Service
  4. //
  5. // Copyright (C) 1992-93 Microsft Corporation. All rights reserved.
  6. //
  7. // Filename: serutil.c
  8. //
  9. // Revision History
  10. //
  11. // Sep 3, 1992 J. Perry Hannah Created
  12. //
  13. //
  14. // Description: This file contains utility functions which are used by
  15. // the serial DLL APIs.
  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 <rasmxs.h>
  26. #include <serial.h>
  27. #include <serialpr.h>
  28. #include <stdlib.h>
  29. #include <malloc.h>
  30. #include <string.h>
  31. //* Global Variables *******************************************************
  32. //
  33. extern SERIALPCB *gpSerialPCB; // Points to Serial PCB linked list
  34. extern HANDLE *ghRasfileMutex; // Mutex used to protect access to Rasfile
  35. extern HRASFILE ghIniFile; // Handle to Serial.ini memory image
  36. extern HANDLE ghAsyMac; // Handle to AsyncMac driver
  37. extern DWORD gLastError;
  38. //* Utility Funcitons ******************************************************
  39. //
  40. //* GetIniFileName --------------------------------------------------------
  41. //
  42. // Funciton: Puts the full path file name of the serial.ini file in the
  43. // first parameter. dwBufferLen is the size of the array
  44. // referenced by the first parameter.
  45. //
  46. // Returns: nothing
  47. //
  48. //*
  49. void
  50. GetIniFileName(char *pszFileName, DWORD dwBufferLen)
  51. {
  52. UINT uLen;
  53. uLen = GetSystemDirectory(pszFileName, dwBufferLen);
  54. strcat(pszFileName, RAS_PATH);
  55. strcat(pszFileName, SERIAL_INI_FILENAME);
  56. }
  57. //* AddPortToList ----------------------------------------------------------
  58. //
  59. // Function: Adds a Serial Port Control Block to the head of the linked
  60. // list in the DLL's global memory.
  61. //
  62. // Returns: Nothing
  63. //
  64. // Exceptions: ERROR_ALLOCATING_MEMORY
  65. //
  66. //*
  67. void
  68. AddPortToList(HANDLE hIOPort, char *pszPortName)
  69. {
  70. SERIALPCB *pSPCB;
  71. // Add new Serial Port Control Block to head of list
  72. pSPCB = gpSerialPCB;
  73. GetMem(sizeof(SERIALPCB), (BYTE **)&gpSerialPCB);
  74. gpSerialPCB->pNextSPCB = pSPCB;
  75. // Set ID values in Serial Port Control Block
  76. gpSerialPCB->hIOPort = hIOPort;
  77. gpSerialPCB->uRasEndpoint = INVALID_HANDLE_VALUE;
  78. strcpy(gpSerialPCB->szPortName, pszPortName);
  79. //
  80. // Initialize overlapped structures.
  81. //
  82. gpSerialPCB->MonitorDevice.RO_EventType = OVEVT_DEV_STATECHANGE;
  83. gpSerialPCB->SendReceive.RO_EventType = OVEVT_DEV_ASYNCOP;
  84. // From Serial.ini file get info on the device attached to this port
  85. GetValueFromFile(gpSerialPCB->szPortName,
  86. SER_DEVICETYPE_KEY,
  87. gpSerialPCB->szDeviceType);
  88. GetValueFromFile(gpSerialPCB->szPortName,
  89. SER_DEVICENAME_KEY,
  90. gpSerialPCB->szDeviceName);
  91. }
  92. //* FindPortInList ---------------------------------------------------------
  93. //
  94. // Function: Finds the Serial Port Control Block in the linked list in
  95. // the DLL's global memory which contains the first parameter.
  96. // If the second parameter is not NULL on input, a pointer to
  97. // the previous PCB is returned in the second parameter.
  98. //
  99. // NOTE: If the found PCB is at the head of the list, ppPrevSPCB
  100. // will be the same as the return value.
  101. //
  102. // Returns: Pointer to found PCB, or NULL if PCB is not found.
  103. //
  104. // Exceptions: ERROR_PORT_NOT_OPEN
  105. //
  106. //*
  107. SERIALPCB *
  108. FindPortInList(HANDLE hIOPort, SERIALPCB **ppPrevSPCB)
  109. {
  110. SERIALPCB *pSPCB, *pPrev;
  111. pSPCB = pPrev = gpSerialPCB;
  112. while(pSPCB != NULL && pSPCB->hIOPort != hIOPort)
  113. {
  114. pPrev = pSPCB;
  115. pSPCB = pSPCB->pNextSPCB;
  116. }
  117. if (pSPCB == NULL)
  118. gLastError = ERROR_PORT_NOT_OPEN;
  119. else if (ppPrevSPCB != NULL)
  120. *ppPrevSPCB = pPrev;
  121. return(pSPCB);
  122. }
  123. //* FindPortNameInList -----------------------------------------------------
  124. //
  125. // Function: Finds the Serial Port Control Block in the linked list in
  126. // the DLL's global memory which contains the Port name.
  127. //
  128. // Returns: Pointer to found PCB, or NULL if not found.
  129. //
  130. //*
  131. SERIALPCB *
  132. FindPortNameInList(TCHAR *pszPortName)
  133. {
  134. SERIALPCB *pSPCB;
  135. pSPCB = gpSerialPCB;
  136. while(pSPCB != NULL && _stricmp(pSPCB->szPortName, pszPortName) != 0)
  137. pSPCB = pSPCB->pNextSPCB;
  138. return(pSPCB);
  139. }
  140. //* InitCarrierBps ---------------------------------------------------------
  141. //
  142. // Function: Sets szCarrierBps in Serial Port Control Block to the
  143. // MAXCARRIERBPS value in serial.ini.
  144. //
  145. // Returns: Nothing
  146. //
  147. //*
  148. DWORD
  149. InitCarrierBps(char *pszPortName, char *pszMaxCarrierBps)
  150. {
  151. // Find section for pszPortName
  152. // Begin Exclusion
  153. if(INVALID_HRASFILE == ghIniFile)
  154. {
  155. return SUCCESS;
  156. }
  157. WaitForSingleObject(ghRasfileMutex, INFINITE);
  158. #if DBG
  159. ASSERT( INVALID_HRASFILE != ghIniFile );
  160. #endif
  161. if (!RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE))
  162. {
  163. // End Exclusion
  164. ReleaseMutex(ghRasfileMutex);
  165. return(ERROR_READING_SECTIONNAME);
  166. }
  167. // Get Device Type
  168. if(!(RasfileFindNextKeyLine(ghIniFile, SER_MAXCARRIERBPS_KEY, RFS_SECTION) &&
  169. RasfileGetKeyValueFields(ghIniFile, NULL, pszMaxCarrierBps)))
  170. {
  171. // End Exclusion
  172. ReleaseMutex(ghRasfileMutex);
  173. return(ERROR_READING_INI_FILE);
  174. }
  175. // End Exclusion
  176. ReleaseMutex(ghRasfileMutex);
  177. return(SUCCESS);
  178. }
  179. //* SetCommDefaults --------------------------------------------------------
  180. //
  181. // Function: Adds a Serial Port Control Block to the head of the linked
  182. // list in the DLL's global memory. Two fields are initialized:
  183. // hIOPort, from the first parameter, and eCmdType, from the
  184. // serial.ini file.
  185. //
  186. // Returns: Nothing
  187. //
  188. // Exceptions: ERROR_READING_INI_FILE
  189. // ERROR_UNKNOWN_DEVICE_TYPE
  190. //
  191. //*
  192. void
  193. SetCommDefaults(HANDLE hIOPort, char *pszPortName)
  194. {
  195. DCB DCB;
  196. char szInitialBPS[MAX_BPS_STR_LEN];
  197. // Get a Device Control Block with current port values
  198. if (!GetCommState(hIOPort, &DCB))
  199. {
  200. gLastError = GetLastError();
  201. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  202. }
  203. strcpy(szInitialBPS, "28800");
  204. // Read Max Connect BPS from Serial.ini
  205. GetValueFromFile(pszPortName, SER_INITBPS_KEY, szInitialBPS);
  206. // Set RAS default values in the DCB
  207. SetDcbDefaults(&DCB);
  208. DCB.BaudRate = atoi(szInitialBPS);
  209. // Send DCB to Port
  210. if (!SetCommState(hIOPort, &DCB))
  211. {
  212. gLastError = GetLastError();
  213. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  214. }
  215. }
  216. //* SetDcbDefaults ----------------------------------------------------------
  217. //
  218. // Function: Sets DCB values (except BaudRate) to RAS default values.
  219. //
  220. // Returns: Nothing.
  221. //
  222. //*
  223. void
  224. SetDcbDefaults(DCB *pDCB)
  225. {
  226. pDCB->fBinary = TRUE;
  227. pDCB->fParity = FALSE;
  228. pDCB->fOutxCtsFlow = TRUE;
  229. pDCB->fOutxDsrFlow = FALSE;
  230. pDCB->fDtrControl = DTR_CONTROL_ENABLE;
  231. pDCB->fDsrSensitivity = FALSE;
  232. pDCB->fOutX = FALSE;
  233. pDCB->fInX = FALSE;
  234. pDCB->fNull = FALSE;
  235. pDCB->fRtsControl = RTS_CONTROL_HANDSHAKE;
  236. pDCB->fAbortOnError = FALSE;
  237. pDCB->ByteSize = 8;
  238. pDCB->Parity = NOPARITY;
  239. pDCB->StopBits = ONESTOPBIT;
  240. }
  241. //* StrToUsage -------------------------------------------------------------
  242. //
  243. // Function: Converts string in first parameter to enum RASMAN_USAGE.
  244. // If string does not map to one of the enum values, the
  245. // function returns FALSE.
  246. //
  247. // Returns: TRUE if successful.
  248. //
  249. //*
  250. BOOL
  251. StrToUsage(char *pszStr, RASMAN_USAGE *peUsage)
  252. {
  253. if (_stricmp(pszStr, SER_USAGE_VALUE_NONE) == 0)
  254. *peUsage = CALL_NONE;
  255. else {
  256. if (strstr(pszStr, SER_USAGE_VALUE_CLIENT))
  257. *peUsage |= CALL_OUT;
  258. if (strstr(pszStr, SER_USAGE_VALUE_SERVER))
  259. *peUsage |= CALL_IN;
  260. if (strstr(pszStr, SER_USAGE_VALUE_ROUTER))
  261. *peUsage |= CALL_ROUTER;
  262. }
  263. return(TRUE);
  264. }
  265. //* GetMem -----------------------------------------------------------------
  266. //
  267. // Function: Allocates memory.
  268. //
  269. // Returns: Nothing. Raises exception on error.
  270. //
  271. //*
  272. void
  273. GetMem(DWORD dSize, BYTE **ppMem)
  274. {
  275. if ((*ppMem = (BYTE *) calloc(dSize, 1)) == NULL )
  276. {
  277. gLastError = ERROR_ALLOCATING_MEMORY;
  278. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  279. }
  280. }
  281. //* GetValueFromFile -------------------------------------------------------
  282. //
  283. // Function: Finds the szKey for the pszPortName and copies its value
  284. // string to pszValue.
  285. //
  286. // Assumptions: ghIniFile has been initalized.
  287. //
  288. // Returns: Nothing. Raises exception on error.
  289. //
  290. //*
  291. void
  292. GetValueFromFile(TCHAR *pszPortName, TCHAR szKey[], TCHAR *pszValue)
  293. {
  294. // Begin Exclusion
  295. if(INVALID_HRASFILE == ghIniFile)
  296. {
  297. return;
  298. }
  299. #if DBG
  300. ASSERT( INVALID_HRASFILE != ghIniFile );
  301. #endif
  302. WaitForSingleObject(ghRasfileMutex, INFINITE);
  303. if (!(RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE) &&
  304. RasfileFindNextKeyLine(ghIniFile, szKey, RFS_SECTION) &&
  305. RasfileGetKeyValueFields(ghIniFile, NULL, pszValue)))
  306. {
  307. // End Exclusion
  308. ReleaseMutex(ghRasfileMutex);
  309. gLastError = ERROR_READING_INI_FILE;
  310. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  311. }
  312. // End Exclusion
  313. ReleaseMutex(ghRasfileMutex);
  314. }
  315. //* GetDefaultOffStr -------------------------------------------------------
  316. //
  317. // Function: Copies the DefaultOff value string from serial.ini to the
  318. // first Serial Port Control Block. If there is no DefaultOff=
  319. // in serial.ini a string containing a not printable character
  320. // used as a flag is copied to the SPCB.
  321. //
  322. // Assumptions: The first SPCB on the list is the current one. This
  323. // function *must* be called only from PortOpen.
  324. //
  325. // Returns: Nothing. Raises exception on error.
  326. //
  327. //*
  328. void
  329. GetDefaultOffStr(HANDLE hIOPort, TCHAR *pszPortName)
  330. {
  331. if(INVALID_HRASFILE == ghIniFile)
  332. {
  333. return;
  334. }
  335. #if DBG
  336. ASSERT(INVALID_HRASFILE != ghIniFile );
  337. #endif
  338. // Begin Exclusion
  339. WaitForSingleObject(ghRasfileMutex, INFINITE);
  340. if (!(RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE)))
  341. {
  342. // End Exclusion
  343. ReleaseMutex(ghRasfileMutex);
  344. gLastError = ERROR_READING_INI_FILE;
  345. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  346. }
  347. if (!(RasfileFindNextKeyLine(ghIniFile, SER_DEFAULTOFFSTR_KEY, RFS_SECTION)))
  348. {
  349. // End Exclusion
  350. ReleaseMutex(ghRasfileMutex);
  351. *(gpSerialPCB->szDefaultOff) = USE_DEVICE_INI_DEFAULT;
  352. return;
  353. }
  354. if (!(RasfileGetKeyValueFields(ghIniFile, NULL, gpSerialPCB->szDefaultOff)))
  355. {
  356. // End Exclusion
  357. ReleaseMutex(ghRasfileMutex);
  358. gLastError = ERROR_READING_INI_FILE;
  359. RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL);
  360. }
  361. // End Exclusion
  362. ReleaseMutex(ghRasfileMutex);
  363. }
  364. //* ValueToNum -------------------------------------------------------------
  365. //
  366. // Function: Converts a RAS_PARAMS P_Value, which may be either a DWORD or
  367. // a string, to a DWORD.
  368. //
  369. // Returns: The numeric value of the input as a DWORD.
  370. //
  371. //*
  372. DWORD ValueToNum(RAS_PARAMS *p)
  373. {
  374. TCHAR szStr[RAS_MAXLINEBUFLEN];
  375. if (p->P_Type == String)
  376. {
  377. strncpy(szStr, p->P_Value.String.Data, p->P_Value.String.Length);
  378. szStr[p->P_Value.String.Length] = '\0';
  379. return(atol(szStr));
  380. }
  381. else
  382. return(p->P_Value.Number);
  383. }
  384. //* ValueToBool -------------------------------------------------------------
  385. //
  386. // Function: Converts a RAS_PARAMS P_Value, which may be either a DWORD or
  387. // a string, to a BOOL.
  388. //
  389. // Returns: The boolean value of the input.
  390. //
  391. //*
  392. BOOL ValueToBool(RAS_PARAMS *p)
  393. {
  394. TCHAR szStr[RAS_MAXLINEBUFLEN];
  395. if (p->P_Type == String)
  396. {
  397. strncpy(szStr, p->P_Value.String.Data, p->P_Value.String.Length);
  398. szStr[p->P_Value.String.Length] = '\0';
  399. return(atol(szStr) ? TRUE : FALSE);
  400. }
  401. else
  402. return(p->P_Value.Number ? TRUE : FALSE);
  403. }
  404. //* UpdateStatistics -------------------------------------------------------
  405. //
  406. // Function: Updates the statistics when PortDisconnect is called so that
  407. // if PortGetStatistics is called while asyncmac is closed the
  408. // last good statistics will be reported.
  409. //
  410. // Returns: SUCCESS
  411. // Values from GetLastError()
  412. //
  413. //*
  414. DWORD
  415. UpdateStatistics(SERIALPCB *pSPCB)
  416. {
  417. #if 0
  418. ASYMAC_GETSTATS A;
  419. DWORD dwBytesReturned;
  420. // Fill in GetStats struct
  421. A.MacAdapter = NULL;
  422. A.hRasEndpoint = pSPCB->uRasEndpoint;
  423. // Call Asymac to get current MAC statistics counts
  424. if (!DeviceIoControl(ghAsyMac,
  425. IOCTL_ASYMAC_GETSTATS,
  426. &A,
  427. sizeof(A),
  428. &A,
  429. sizeof(A),
  430. &dwBytesReturned,
  431. NULL))
  432. return(GetLastError());
  433. // Find difference between last PortClearStatistics and current counts
  434. pSPCB->Stats[BYTES_XMITED]
  435. = A.AsyMacStats.GenericStats.BytesTransmitted
  436. - pSPCB->Stats[BYTES_XMITED];
  437. pSPCB->Stats[BYTES_RCVED]
  438. = A.AsyMacStats.GenericStats.BytesReceived
  439. - pSPCB->Stats[BYTES_RCVED];
  440. pSPCB->Stats[FRAMES_XMITED]
  441. = A.AsyMacStats.GenericStats.FramesTransmitted
  442. - pSPCB->Stats[FRAMES_XMITED];
  443. pSPCB->Stats[FRAMES_RCVED]
  444. = A.AsyMacStats.GenericStats.FramesReceived
  445. - pSPCB->Stats[FRAMES_RCVED];
  446. pSPCB->Stats[CRC_ERR]
  447. = A.AsyMacStats.SerialStats.CRCErrors
  448. - pSPCB->Stats[CRC_ERR];
  449. pSPCB->Stats[TIMEOUT_ERR]
  450. = A.AsyMacStats.SerialStats.TimeoutErrors
  451. - pSPCB->Stats[TIMEOUT_ERR];
  452. pSPCB->Stats[ALIGNMENT_ERR]
  453. = A.AsyMacStats.SerialStats.AlignmentErrors
  454. - pSPCB->Stats[ALIGNMENT_ERR];
  455. pSPCB->Stats[SERIAL_OVERRUN_ERR]
  456. = A.AsyMacStats.SerialStats.SerialOverrunErrors
  457. - pSPCB->Stats[SERIAL_OVERRUN_ERR];
  458. pSPCB->Stats[FRAMING_ERR]
  459. = A.AsyMacStats.SerialStats.FramingErrors
  460. - pSPCB->Stats[FRAMING_ERR];
  461. pSPCB->Stats[BUFFER_OVERRUN_ERR]
  462. = A.AsyMacStats.SerialStats.BufferOverrunErrors
  463. - pSPCB->Stats[BUFFER_OVERRUN_ERR];
  464. pSPCB->Stats[BYTES_XMITED_UNCOMP]
  465. = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed
  466. - pSPCB->Stats[BYTES_XMITED_UNCOMP];
  467. pSPCB->Stats[BYTES_RCVED_UNCOMP]
  468. = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed
  469. - pSPCB->Stats[BYTES_RCVED_UNCOMP];
  470. pSPCB->Stats[BYTES_XMITED_COMP]
  471. = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed
  472. - pSPCB->Stats[BYTES_XMITED_COMP];
  473. pSPCB->Stats[BYTES_RCVED_COMP]
  474. = A.AsyMacStats.CompressionStats.BytesReceivedCompressed
  475. - pSPCB->Stats[BYTES_RCVED_COMP];
  476. #endif
  477. return(SUCCESS);
  478. }
  479. //* DbgPrntf --------------------------------------------------------------
  480. //
  481. // Funciton: DbgPrntf -- printf to the debugger console
  482. // Takes printf style arguments.
  483. // Expects newline characters at the end of the string.
  484. // Written by BruceK.
  485. //
  486. // Returns: nothing
  487. //
  488. //*
  489. #ifdef DEBUG
  490. #include <stdarg.h>
  491. #include <stdio.h>
  492. void DbgPrntf(const char * format, ...) {
  493. va_list marker;
  494. char String[512];
  495. va_start(marker, format);
  496. vsprintf(String, format, marker);
  497. OutputDebugString(String);
  498. }
  499. #endif // DEBUG