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.

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