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.

2010 lines
47 KiB

  1. //****************************************************************************
  2. // *
  3. // Microsoft NT Remote Access Service
  4. //
  5. // Copyright (C) 1992-93 Microsft Corporation. All rights reserved.
  6. //
  7. // Filename: mxsutils.c
  8. //
  9. // Revision History
  10. //
  11. // Jun 10, 1992 J. Perry Hannah Created
  12. //
  13. //
  14. // Description: This file contains utility functions used by RASMXS.DLL.
  15. //
  16. //****************************************************************************
  17. #include <nt.h> //These first five headers are used by media.h
  18. #include <ntrtl.h> //The first three(?) are used by DbgUserBreakPoint
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <wanpub.h>
  22. #include <asyncpub.h>
  23. #include <string.h>
  24. #include <malloc.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <rasman.h>
  28. #include <raserror.h>
  29. #include <rasfile.h>
  30. #include <media.h>
  31. #include <serial.h>
  32. #include <mprlog.h>
  33. #include <rtutils.h>
  34. #include <rasmxs.h>
  35. #include <mxsint.h>
  36. #include <mxspriv.h>
  37. #include "mxswrap.h" // inf file wrapper
  38. //* Global Variables *******************************************************
  39. //
  40. extern RESPSECTION ResponseSection ; //Shared response section
  41. extern DEVICE_CB *pDeviceList; //Points to DCB linked list
  42. extern HANDLE *pDeviceListMutex ; //Mutex for above list
  43. extern PortGetInfo_t PortGetInfo; //API typedef defined in media.h
  44. extern PortSetInfo_t PortSetInfo; //API typedef defined in media.h
  45. extern BOOL gbLogDeviceDialog; //Indicates logging is on if TRUE
  46. extern HANDLE ghLogFile; //Handle of device log file
  47. extern SavedSections *gpSavedSections ; // Pointer to cached sections
  48. #define NUM_INTERNAL_MACROS 21
  49. TCHAR *gszInternalMacroNames[] =
  50. {
  51. MXS_CARRIERBPS_KEY,
  52. MXS_CONNECTBPS_KEY,
  53. MXS_MESSAGE_KEY,
  54. MXS_PHONENUMBER_KEY,
  55. MXS_DIAGNOSTICS_KEY,
  56. MXS_FACILITIES_KEY,
  57. MXS_USERDATA_KEY,
  58. MXS_X25PAD_KEY,
  59. MXS_X25ADDRESS_KEY,
  60. MXS_COMPRESSION_OFF_KEY,
  61. MXS_COMPRESSION_ON_KEY,
  62. MXS_HDWFLOWCONTROL_OFF_KEY,
  63. MXS_HDWFLOWCONTROL_ON_KEY,
  64. MXS_PROTOCOL_OFF_KEY,
  65. MXS_PROTOCOL_ON_KEY,
  66. MXS_SPEAKER_OFF_KEY,
  67. MXS_SPEAKER_ON_KEY,
  68. MXS_AUTODIAL_OFF_KEY,
  69. MXS_AUTODIAL_ON_KEY,
  70. MXS_USERNAME_KEY,
  71. MXS_PASSWORD_KEY,
  72. };
  73. //* Utility Functions ******************************************************
  74. //
  75. //* GetDeviceCB ------------------------------------------------------------
  76. //
  77. // Function: Looks for a Device Control Block in the global Device linked
  78. // list. If no DCB is found that contains an hIOPort matching
  79. // the input parameter, one is created, initalized, and added
  80. // to the list.
  81. //
  82. // Returns: Pointer to the DEVICE_CB which contains an hIOPort matching the
  83. // the second input parameter.
  84. //*
  85. DWORD
  86. GetDeviceCB(HANDLE hIOPort,
  87. char *pszDeviceType,
  88. char *pszDeviceName,
  89. DEVICE_CB **ppDev)
  90. {
  91. DWORD dRC = SUCCESS ;
  92. *ppDev = FindDeviceInList(pDeviceList, hIOPort, pszDeviceType, pszDeviceName);
  93. if (*ppDev == NULL)
  94. {
  95. dRC = AddDeviceToList(&pDeviceList,
  96. hIOPort,
  97. pszDeviceType,
  98. pszDeviceName,
  99. ppDev);
  100. if (dRC != SUCCESS)
  101. goto getdcbend ;
  102. dRC = CreateInfoTable(*ppDev);
  103. if (dRC != SUCCESS)
  104. goto getdcbend ;
  105. dRC = CreateAttributes(*ppDev) ;
  106. }
  107. getdcbend:
  108. return (dRC);
  109. }
  110. //* FindDeviceInList -------------------------------------------------------
  111. //
  112. // Function: Finds the Device Control Block in the global Device linked
  113. // list which contains the hIOPort handle, device type, and
  114. // device name.
  115. //
  116. // Returns: Pointer to the DEVICE_CB which contains matches for the second,
  117. // third, and fourth parameters, or NULL if no such DEVICE_CB
  118. // is found.
  119. //*
  120. DEVICE_CB*
  121. FindDeviceInList(DEVICE_CB *pDev,
  122. HANDLE hIOPort,
  123. TCHAR *pszDeviceType,
  124. TCHAR *pszDeviceName)
  125. {
  126. while (pDev != NULL)
  127. {
  128. pDev = FindPortInList(pDev, hIOPort, NULL);
  129. if (pDev == NULL)
  130. break;
  131. if (_stricmp(pDev->szDeviceType, pszDeviceType) == 0 &&
  132. _stricmp(pDev->szDeviceName, pszDeviceName) == 0)
  133. break;
  134. pDev = pDev->pNextDeviceCB;
  135. }
  136. return(pDev);
  137. }
  138. //* FindPortInList ---------------------------------------------------------
  139. //
  140. // Function: Finds the first Device Control Block in the global Device linked
  141. // list which contains the hIOPort handle.
  142. //
  143. // If pPrevDev is not NULL on input, then on output it *pPrevDev
  144. // points to the DCB just prior to the "found" DCB pointed to by
  145. // the returned pointer. If the function return value is not NULL
  146. // *pPrevDev will be valid.
  147. //
  148. // NOTE: If the found DCB is at the head of the list, pPrevDev
  149. // will be the same as the return value.
  150. //
  151. // Returns: Pointer to the DEVICE_CB which contains an hIOPort matching the
  152. // the second input parameter, or NULL if no such DEVICE_CB is found.
  153. //*
  154. DEVICE_CB*
  155. FindPortInList(DEVICE_CB *pDeviceList, HANDLE hIOPort, DEVICE_CB **pPrevDev)
  156. {
  157. DEVICE_CB *pDev;
  158. pDev = pDeviceList; //Allow for case of only one DCB on list
  159. while(pDeviceList != NULL && pDeviceList->hPort != hIOPort)
  160. {
  161. pDev = pDeviceList;
  162. pDeviceList = pDeviceList->pNextDeviceCB;
  163. }
  164. if (pPrevDev != NULL)
  165. *pPrevDev = pDev;
  166. return(pDeviceList);
  167. }
  168. //* AddDeviceToList --------------------------------------------------------
  169. //
  170. // Function: Creates a Device Control Block and adds it to the head of the
  171. // global Device linked list.
  172. //
  173. // Returns: SUCCESS
  174. // ERROR_UNKNOWN_DEVICE_TYPE
  175. // ERROR_ALLOCATING_MEMORY
  176. //*
  177. DWORD
  178. AddDeviceToList(DEVICE_CB **ppDeviceList,
  179. HANDLE hIOPort,
  180. LPTSTR lpszDeviceType,
  181. LPTSTR lpszDeviceName,
  182. DEVICE_CB **ppDevice)
  183. {
  184. DEVICE_CB *pDev;
  185. DEVICETYPE eDeviceType;
  186. DWORD dRC;
  187. TCHAR szFileName[MAX_PATH];
  188. DEVICE_CB *origpDeviceList ;
  189. origpDeviceList = *ppDeviceList ; // save this pointer since it may be restored later
  190. // Check input
  191. eDeviceType = DeviceTypeStrToEnum(lpszDeviceType);
  192. if (eDeviceType == DT_UNKNOWN)
  193. return(ERROR_UNKNOWN_DEVICE_TYPE);
  194. // INF file sections are opened before the DCB is created because the
  195. // open/close count must be kept balanced even when errors occur. (If
  196. // OpenResponseSection fails it does not increment the count, and because
  197. // the DCB does not exist DeviceWork does not decrement the count.)
  198. // Open global response section for modems
  199. *szFileName = TEXT('\0');
  200. GetInfFileName(lpszDeviceType, szFileName, sizeof(szFileName));
  201. if (eDeviceType == DT_MODEM) {
  202. dRC = OpenResponseSection (szFileName) ;
  203. if (dRC != SUCCESS)
  204. return dRC ;
  205. }
  206. // Put new DCB at head of list
  207. pDev = *ppDeviceList;
  208. GetMem(sizeof(DEVICE_CB), (BYTE **)ppDeviceList);
  209. if (*ppDeviceList == NULL)
  210. return(ERROR_ALLOCATING_MEMORY);
  211. *ppDevice = *ppDeviceList;
  212. (*ppDevice)->pNextDeviceCB = pDev;
  213. // Initialize New Device Control Block
  214. pDev = *ppDevice;
  215. pDev->hPort = hIOPort;
  216. strcpy(pDev->szDeviceName, lpszDeviceName);
  217. strcpy(pDev->szDeviceType, lpszDeviceType);
  218. pDev->eDeviceType = eDeviceType;
  219. pDev->pInfoTable = NULL;
  220. pDev->pMacros = NULL;
  221. pDev->hInfFile = INVALID_HRASFILE;
  222. pDev->fPartialResponse = FALSE;
  223. pDev->bErrorControlOn = FALSE;
  224. pDev->Overlapped.RO_Overlapped.Internal = 0;
  225. pDev->Overlapped.RO_Overlapped.InternalHigh = 0;
  226. pDev->Overlapped.RO_Overlapped.Offset = 0;
  227. pDev->Overlapped.RO_Overlapped.OffsetHigh = 0;
  228. pDev->Overlapped.RO_Overlapped.hEvent = NULL;
  229. pDev->Overlapped.RO_EventType = OVEVT_DEV_ASYNCOP;
  230. pDev->dwRetries = 1;
  231. // Initialize State variables
  232. pDev->eDevNextAction = SEND; // DeviceStateMachine() State
  233. pDev->eCmdType = CT_GENERIC; // Used by DeviceStateMachine()
  234. pDev->eNextCmdType = CT_GENERIC; // Used by DeviceStateMachine()
  235. pDev->fEndOfSection = FALSE; // Used by DeviceStateMachine()
  236. pDev->eRcvState = GETECHO; // ReceiveStateMachine() State
  237. // Open device section of INF file
  238. if (FindOpenDevSection (szFileName, lpszDeviceName, &(pDev->hInfFile)) == TRUE)
  239. return SUCCESS ;
  240. dRC = RasDevOpen(szFileName, lpszDeviceName, &(pDev->hInfFile));
  241. if (dRC != SUCCESS) {
  242. // restore the pointers
  243. //
  244. *ppDeviceList = origpDeviceList ;
  245. *ppDevice = NULL ;
  246. free (pDev) ;
  247. return(dRC);
  248. } else
  249. AddOpenDevSection (szFileName, lpszDeviceName, pDev->hInfFile) ; // Add to the opened list
  250. return(SUCCESS);
  251. }
  252. //* CreateInfoTable --------------------------------------------------------
  253. //
  254. // Function: Creates an InfoTable and initalizes it by reading the variables
  255. // and macros found in the INF file into it. The InfoTable is
  256. // attached to the Device Control Block pointed to by the input
  257. // parameter.
  258. //
  259. // This function allocates memory.
  260. //
  261. // Returns: SUCCESS
  262. // ERROR_ALLOCATING_MEMORY
  263. // Return value from RasDevOpen() or RasDevGetParams().
  264. //*
  265. DWORD
  266. CreateInfoTable(DEVICE_CB *pDevice)
  267. {
  268. DWORD dRC, dSize = 0;
  269. RASMAN_DEVICEINFO *pInfoTable = NULL ;
  270. // Read variables and macros into InfoTable from INF file
  271. dRC = RasDevGetParams(pDevice->hInfFile, (BYTE *)(pInfoTable), &dSize);
  272. if (dRC == ERROR_BUFFER_TOO_SMALL)
  273. {
  274. dSize += sizeof(RAS_PARAMS) * NUM_INTERNAL_MACROS;
  275. GetMem(dSize, (BYTE **)&pInfoTable);
  276. if (pInfoTable == NULL)
  277. return(ERROR_ALLOCATING_MEMORY);
  278. dRC = RasDevGetParams(pDevice->hInfFile, (BYTE *)(pInfoTable), &dSize);
  279. }
  280. if (dRC != SUCCESS)
  281. {
  282. free(pInfoTable);
  283. return(dRC);
  284. }
  285. if ((dRC = AddInternalMacros(pDevice, pInfoTable)) != SUCCESS)
  286. {
  287. free(pInfoTable);
  288. return(dRC);
  289. }
  290. // Attach InfoTable to Device Control Block
  291. pDevice->pInfoTable = pInfoTable;
  292. return(SUCCESS);
  293. }
  294. //* AddInternalMacros ------------------------------------------------------
  295. //
  296. // Function: Adds internal macros to existing InfoTable.
  297. //
  298. // Asumptions: The InfoTable buffer was created with room enough for
  299. // the internal macros.
  300. //
  301. // Returns: SUCCESS
  302. // ERROR_ALLOCATING_MEMORY
  303. //*
  304. DWORD
  305. AddInternalMacros(DEVICE_CB *pDev, RASMAN_DEVICEINFO *pDI)
  306. {
  307. WORD i;
  308. RAS_PARAMS *pParam;
  309. // Get pointer to next unused param
  310. pParam = &(pDI->DI_Params[pDI->DI_NumOfParams]);
  311. // Fill in params for internal macros
  312. for (i=0; i<NUM_INTERNAL_MACROS; i++)
  313. {
  314. strcpy(pParam->P_Key, gszInternalMacroNames[i]);
  315. pParam->P_Type = String;
  316. pParam->P_Attributes = 0;
  317. pParam->P_Value.String.Length = 0;
  318. GetMem(1, &(pParam->P_Value.String.Data));
  319. if (pParam->P_Value.String.Data == NULL)
  320. return(ERROR_ALLOCATING_MEMORY);
  321. *(pParam->P_Value.String.Data) = '\0';
  322. pParam++;
  323. }
  324. pDI->DI_NumOfParams += NUM_INTERNAL_MACROS;
  325. return(SUCCESS);
  326. }
  327. //* CreateAttributes -------------------------------------------------------
  328. //
  329. // Function: This function is used to set attributes for the first time
  330. // when the InfoTable is created. UpdateInfoTable() is used
  331. // to later change attributes.
  332. //
  333. // First, all attributes are set according to the parameter
  334. // key with all binary macros being enabled. Then the
  335. // DEFAULTOFF variable is parsed, and macros listed there are
  336. // disabled.
  337. //
  338. // Assumptions: - The ATTRIB_VARIABLE attribute bit has already been set
  339. // by RasDevGetParams().
  340. // - Parameters in InfoTable are sorted by P_Key.
  341. // - Both parts of binary macros are present.
  342. // These assumptions imply that if somename_off is in InfoTable
  343. // somename_on is also present and is adjacent to somename_off.
  344. //
  345. // Returns: SUCCESS
  346. // ERROR_DEFAULTOFF_MACRO_NOT_FOUND
  347. // ERROR_ALLOCATING_MEMORY
  348. // Return codes from PortGetInfo
  349. //*
  350. DWORD
  351. CreateAttributes(DEVICE_CB *pDevice)
  352. {
  353. int iDefaultOff = -1;
  354. DWORD i, dwMemSize;
  355. DWORD dwRC;
  356. BOOL fFound;
  357. TCHAR *lpszDefaultOff, *lpszEOS, szCoreName[MAX_PARAM_KEY_SIZE];
  358. RAS_PARAMS *pParam;
  359. RASMAN_DEVICEINFO *pInfo = pDevice->pInfoTable;
  360. RASMAN_PORTINFO *pPortInfo;
  361. //DebugPrintf(("mxsutils CreateAttributes\n"));
  362. // Set attributes according to Keyword type,
  363. // defaulting user settable parameters to enabled.
  364. for (i=0; i < pInfo->DI_NumOfParams; i++)
  365. {
  366. pParam = &(pInfo->DI_Params[i]);
  367. //DebugPrintf(("%32s %s\n", pParam, pParam->P_Value.String.Data));
  368. if (IsVariable(*pParam))
  369. pParam->P_Attributes = ATTRIB_VARIABLE;
  370. else if (IsBinaryMacro(pParam->P_Key))
  371. pParam->P_Attributes = ATTRIB_BINARYMACRO |
  372. ATTRIB_USERSETTABLE |
  373. ATTRIB_ENABLED;
  374. else
  375. pParam->P_Attributes = ATTRIB_ENABLED;
  376. // Remember location of DEFAULTOFF variable
  377. if (_stricmp(pInfo->DI_Params[i].P_Key, MXS_DEFAULTOFF_KEY) == 0)
  378. iDefaultOff = i;
  379. }
  380. // Call PortGetInfo (first loading the rasser.dll if necessary)
  381. if (PortGetInfo == NULL)
  382. {
  383. if ((dwRC = LoadRasserDll(&PortGetInfo, &PortSetInfo)) != SUCCESS)
  384. return(dwRC);
  385. }
  386. dwMemSize = 256;
  387. GetMem(dwMemSize, (BYTE **)&pPortInfo);
  388. if (pPortInfo == NULL)
  389. return(ERROR_ALLOCATING_MEMORY);
  390. dwRC = PortGetInfo(pDevice->hPort, NULL, (BYTE *)pPortInfo, &dwMemSize);
  391. if (dwRC == ERROR_BUFFER_TOO_SMALL)
  392. {
  393. free(pPortInfo);
  394. GetMem(dwMemSize, (BYTE **)&pPortInfo);
  395. if (pPortInfo == NULL)
  396. return(ERROR_ALLOCATING_MEMORY);
  397. PortGetInfo(pDevice->hPort, NULL, (BYTE *)pPortInfo, &dwMemSize);
  398. }
  399. else if ( dwRC )
  400. {
  401. dwRC = SUCCESS;
  402. return dwRC;
  403. }
  404. dwRC = SUCCESS ;
  405. // Save the Port name in the DCB
  406. GetPcbString(pPortInfo, SER_PORTNAME_KEY, pDevice->szPortName);
  407. // Get the current Bps of the port.
  408. // If the modem does not report the connect bps we will use this one.
  409. GetPcbString(pPortInfo, SER_CONNECTBPS_KEY, pDevice->szPortBps);
  410. // Does serial.ini file contain a DEFAULTOFF variable?
  411. if (!GetPortDefaultOff(pPortInfo, &lpszDefaultOff))
  412. {
  413. // No DEFAULTOFF in port INI file
  414. // Check that DEFAULTOFF variable was found in device Info table
  415. if (iDefaultOff == -1) //DEFAULTOFF not found
  416. { //Assume none are to be disabled
  417. free(pPortInfo);
  418. return(SUCCESS);
  419. }
  420. lpszDefaultOff = pInfo->DI_Params[iDefaultOff].P_Value.String.Data;
  421. }
  422. // Prepare DEFALULTOFF string
  423. InitParameterStr(lpszDefaultOff, &lpszEOS);
  424. // Disable parameters listed in DEFAULTOFF variable.
  425. while (lpszDefaultOff < lpszEOS)
  426. {
  427. fFound = FALSE;
  428. for (i=0; i < pInfo->DI_NumOfParams; i++)
  429. {
  430. if (IsBinaryMacro(pInfo->DI_Params[i].P_Key))
  431. {
  432. GetCoreMacroName(pInfo->DI_Params[i].P_Key, szCoreName);
  433. if (_stricmp(lpszDefaultOff, szCoreName) == 0)
  434. {
  435. pInfo->DI_Params[i].P_Attributes &= ~ATTRIB_ENABLED; //One suffix
  436. pInfo->DI_Params[i+1].P_Attributes &= ~ATTRIB_ENABLED; //Other suffix
  437. fFound = TRUE;
  438. break;
  439. }
  440. }
  441. }
  442. if (!fFound)
  443. {
  444. free(pPortInfo);
  445. return(ERROR_DEFAULTOFF_MACRO_NOT_FOUND);
  446. }
  447. GetNextParameter(&lpszDefaultOff, lpszEOS);
  448. }
  449. free(pPortInfo);
  450. return(SUCCESS);
  451. }
  452. //* GetPortDefaultOff ------------------------------------------------------
  453. //
  454. // Function: This function finds the DEFAULTOFF key in the RASMAN_PORTINFO
  455. // table supplied by the first parameter. A pointer to the value
  456. // string is the output in the second parameter.
  457. //
  458. // If the DEFAULTOFF key is not found, the function returns FALSE,
  459. // and the second parameter is undefined.
  460. //
  461. // Arguments:
  462. // pPortInfo IN Pointer to Port Info Table from PortGetInfo()
  463. // lpszValue OUT DEFAULTOFF value string
  464. //
  465. // Returns: TRUE if DEFAULTOFF key is found, otherwise FALSE
  466. //
  467. //*
  468. BOOL
  469. GetPortDefaultOff(RASMAN_PORTINFO *pPortInfo, TCHAR **lpszValue)
  470. {
  471. WORD i;
  472. for (i=0; i<pPortInfo->PI_NumOfParams; i++)
  473. if (_stricmp(SER_DEFAULTOFFSTR_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
  474. break;
  475. if (i >= pPortInfo->PI_NumOfParams)
  476. return(FALSE);
  477. *lpszValue = pPortInfo->PI_Params[i].P_Value.String.Data;
  478. return(TRUE);
  479. }
  480. //* GetPcbString -----------------------------------------------------------
  481. //
  482. // Funciton: Searches a RASMAN_PORTINFO struct for a P_Key that matches
  483. // the second parameter, pszPcbKey. The P_Value.String.Data
  484. // is copied to the third parameter, pszDest which is the
  485. // output parameter.
  486. //
  487. // Note: This function may only be called for keys that have
  488. // P_Type String values (and never for P_Type Number values).
  489. //
  490. // Assumptions: The first parameter has been initalize by a call to
  491. // PortGetInfo.
  492. //
  493. // Returns: nothing.
  494. //
  495. //*
  496. void
  497. GetPcbString(RASMAN_PORTINFO *pPortInfo, char *pszPcbKey, char *pszDest)
  498. {
  499. WORD i;
  500. for (i=0; i<pPortInfo->PI_NumOfParams; i++)
  501. if (_stricmp(pszPcbKey, pPortInfo->PI_Params[i].P_Key) == 0)
  502. break;
  503. if (i >= pPortInfo->PI_NumOfParams ||
  504. pPortInfo->PI_Params[i].P_Type != String)
  505. return;
  506. strncpy(pszDest,
  507. pPortInfo->PI_Params[i].P_Value.String.Data,
  508. pPortInfo->PI_Params[i].P_Value.String.Length);
  509. *(pszDest + pPortInfo->PI_Params[i].P_Value.String.Length) = '\0';
  510. }
  511. //* UpdateInfoTable --------------------------------------------------------
  512. //
  513. // Function: This function is used to update attributes when DeviceSetInfo()
  514. // is called. The nested for loops search the Info Table for each
  515. // input param to be set.
  516. //
  517. // If the full macro name (including _off or _on for binary macros)
  518. // is given in the input P_Key, the P_Value is copied and the
  519. // Enable bit in P_Attributes is copied. If the core name
  520. // is given for binary macros, only the Enable bit is copied.
  521. //
  522. // Assumptions: - Parameters in InfoTable are sorted by P_Key.
  523. // - Both parts of binary macros are present in the InfoTable.
  524. // These assumptions imply that if somename_off is in InfoTable
  525. // somename_on is also present and is adjacent to somename_off.
  526. //
  527. // Pseudo Code: for (each input param to be set)
  528. // for (each item in InfoTable)
  529. // if (P_Keys match && !IsVariable)
  530. // copy P_Value
  531. // copy Enable Attribute bit
  532. // else if (P_Keys binary macro core names match)
  533. // copy Enable Attribute bit
  534. //
  535. // Returns: SUCCESS
  536. // ERROR_WRONG_KEY_SPECIFIED
  537. //
  538. //*
  539. DWORD
  540. UpdateInfoTable(DEVICE_CB *pDevice, RASMAN_DEVICEINFO *pNewInfo)
  541. {
  542. WORD i, j;
  543. BOOL fFound;
  544. DWORD dwRC, dwSrcLen, dwNumber;
  545. TCHAR *pszSrc, szNumberStr[MAX_LEN_STR_FROM_NUMBER + 1];
  546. RASMAN_DEVICEINFO *pInfoTable = pDevice->pInfoTable;
  547. for (i=0; i < pNewInfo->DI_NumOfParams; i++) //For each param to set,
  548. {
  549. fFound = FALSE;
  550. for (j=0; j < pInfoTable->DI_NumOfParams; j++) //check InfoTable entries
  551. {
  552. // Check for unary macro match
  553. if (IsUnaryMacro(pInfoTable->DI_Params[j]) &&
  554. _stricmp(pNewInfo->DI_Params[i].P_Key,
  555. pInfoTable->DI_Params[j].P_Key) == 0)
  556. {
  557. // Check format of P_Value field; convert to string if necessary
  558. if (pNewInfo->DI_Params[i].P_Type == String)
  559. {
  560. pszSrc = pNewInfo->DI_Params[i].P_Value.String.Data;
  561. dwSrcLen = pNewInfo->DI_Params[i].P_Value.String.Length;
  562. }
  563. else
  564. { //P_Type == Number
  565. _itoa(pNewInfo->DI_Params[i].P_Value.Number,
  566. szNumberStr,
  567. 10);
  568. pszSrc = szNumberStr;
  569. dwSrcLen = strlen(szNumberStr);
  570. }
  571. // Copy P_Value (allocating more memory as necessary)
  572. dwRC = UpdateParamString(&(pInfoTable->DI_Params[j]),
  573. pszSrc,
  574. dwSrcLen);
  575. if (dwRC != SUCCESS)
  576. return(dwRC);
  577. fFound = TRUE;
  578. break;
  579. }
  580. // Check for Binary Macro match
  581. else if(CoreMacroNameMatch(pNewInfo->DI_Params[i].P_Key,
  582. pInfoTable->DI_Params[j].P_Key))
  583. {
  584. // Convert string to number, if necessary
  585. if (pNewInfo->DI_Params[i].P_Type == String)
  586. {
  587. strncpy(szNumberStr,
  588. pNewInfo->DI_Params[i].P_Value.String.Data,
  589. pNewInfo->DI_Params[i].P_Value.String.Length);
  590. szNumberStr[pNewInfo->DI_Params[i].P_Value.String.Length] = '\0';
  591. dwNumber = atoi(szNumberStr);
  592. }
  593. else
  594. dwNumber = pNewInfo->DI_Params[i].P_Value.Number;
  595. // Set macro enabled bit in Attributes field
  596. if (dwNumber == 0)
  597. {
  598. pInfoTable->DI_Params[j].P_Attributes &= ~ATTRIB_ENABLED; //Clear bit
  599. pInfoTable->DI_Params[j+1].P_Attributes &= ~ATTRIB_ENABLED;
  600. }
  601. else
  602. {
  603. pInfoTable->DI_Params[j].P_Attributes |= ATTRIB_ENABLED; //Set bit
  604. pInfoTable->DI_Params[j+1].P_Attributes |= ATTRIB_ENABLED;
  605. }
  606. fFound = TRUE;
  607. break;
  608. }
  609. }
  610. if (!fFound)
  611. return(ERROR_WRONG_KEY_SPECIFIED);
  612. }
  613. return(SUCCESS);
  614. }
  615. //* DeviceAttachedToPort ---------------------------------------------------
  616. //
  617. // Funciton: Searched through a port info block for DeviceType and
  618. // DeviceName and compares the found strings to the second
  619. // and third input parameters.
  620. //
  621. // Assumptions: The first parameter has been initalize by a call to
  622. // PortGetInfo.
  623. // SER_DEVCIETYPE_KEY and SER_DEVICENAME_KEY each appear
  624. // only once in the RASMAN_PORTINFO block.
  625. //
  626. // Returns: TRUE if pszDeviceType and pszDeviceName are found in
  627. // pPortInfo, else FALSE.
  628. //*
  629. BOOL
  630. DeviceAttachedToPort(RASMAN_PORTINFO *pPortInfo,
  631. char *pszDeviceType,
  632. char *pszDeviceName)
  633. {
  634. WORD i;
  635. BOOL bTypeMatch = FALSE, bNameMatch = FALSE;
  636. for (i=0; i<pPortInfo->PI_NumOfParams; i++)
  637. {
  638. if (_stricmp(SER_DEVICETYPE_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
  639. {
  640. if ( strlen(pszDeviceType) ==
  641. pPortInfo->PI_Params[i].P_Value.String.Length
  642. &&
  643. _strnicmp(pszDeviceType,
  644. pPortInfo->PI_Params[i].P_Value.String.Data,
  645. pPortInfo->PI_Params[i].P_Value.String.Length) == 0)
  646. bTypeMatch = TRUE;
  647. else
  648. break;
  649. }
  650. if (_stricmp(SER_DEVICENAME_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
  651. {
  652. if ( strlen(pszDeviceName) ==
  653. pPortInfo->PI_Params[i].P_Value.String.Length
  654. &&
  655. _strnicmp(pszDeviceName,
  656. pPortInfo->PI_Params[i].P_Value.String.Data,
  657. pPortInfo->PI_Params[i].P_Value.String.Length) == 0)
  658. bNameMatch = TRUE;
  659. else
  660. break;
  661. }
  662. if (bTypeMatch && bNameMatch)
  663. break;
  664. }
  665. return(bTypeMatch && bNameMatch);
  666. }
  667. //* CreateDefaultOffString -------------------------------------------------
  668. //
  669. // Funciton:
  670. // DeviceName and compares the found strings to the second
  671. // and third input parameters.
  672. //
  673. // Assumptions: Buffer pointed to by pszDefaultOff is large enough for
  674. // all DefaultOff macros.
  675. //
  676. // Returns: Nothing
  677. //*
  678. void
  679. CreateDefaultOffString(DEVICE_CB *pDev, char *pszDefaultOff)
  680. {
  681. WORD i, k, wLen;
  682. char *szDefaultOffMacros[] = { MXS_SPEAKER_KEY ,
  683. MXS_HDWFLOWCONTROL_KEY ,
  684. MXS_PROTOCOL_KEY ,
  685. MXS_COMPRESSION_KEY };
  686. *pszDefaultOff = '\0';
  687. // Find each macro and if it is off then add its name to DefaultOff string
  688. for (i=0; i < sizeof(szDefaultOffMacros)/sizeof(char *); i++)
  689. {
  690. k = (WORD) FindTableEntry(pDev->pInfoTable, szDefaultOffMacros[i]);
  691. if (k == INVALID_INDEX)
  692. continue;
  693. // If macro is turned off then copy its key to the DefaultOff string
  694. if ( ! (pDev->pInfoTable->DI_Params[k].P_Attributes & ATTRIB_ENABLED))
  695. {
  696. strcat(pszDefaultOff, szDefaultOffMacros[i]);
  697. strcat(pszDefaultOff, " "); //Add deliminting space
  698. }
  699. }
  700. // Remove last delimiting space
  701. wLen = (WORD)strlen(pszDefaultOff);
  702. if (wLen > 0)
  703. pszDefaultOff[wLen - 1] = '\0';
  704. }
  705. //* BuildOutputTable -------------------------------------------------------
  706. //
  707. // Function: Copies macros from internal InfoTable to the caller's buffer.
  708. // For Parameter: Function copies:
  709. // Variable Entire RASMAN_DEVICEINFO struct
  710. // Unary Macro Entire RASMAN_DEVICEINFO struct
  711. // Binary Macro Everything except P_Value field
  712. //
  713. // Assumptions: - Output buffer will ALWAYS be large enough.
  714. // - Parameters in InfoTable are sorted by P_Key (except
  715. // internal macros).
  716. // - Both parts of binary macros are present.
  717. // These assumptions imply that if somename_off is in InfoTable
  718. // somename_on is also present and is adjacent to somename_off.
  719. //
  720. // Returns: SUCCESS
  721. // ERROR_BUFFER_TOO_SMALL
  722. //
  723. //*
  724. DWORD
  725. BuildOutputTable(DEVICE_CB *pDevice, BYTE *pInfo, DWORD *pdwSize)
  726. {
  727. WORD i, j;
  728. DWORD cOutputParams = 0;
  729. LPTCH pValue;
  730. TCHAR szCoreName[MAX_PARAM_KEY_SIZE];
  731. RASMAN_DEVICEINFO *pInfoTable = pDevice->pInfoTable,
  732. *pOutputTable = (RASMAN_DEVICEINFO *)pInfo;
  733. // Compute location of first value string (follows RAS_PARAMS)
  734. cOutputParams =
  735. pInfoTable->DI_NumOfParams - MacroCount(pInfoTable, BINARY_MACROS);
  736. *pdwSize =
  737. sizeof(RASMAN_DEVICEINFO) + sizeof(RAS_PARAMS) * (cOutputParams - 1);
  738. pValue = pInfo + *pdwSize;
  739. // Set NumOfParams
  740. pOutputTable->DI_NumOfParams = cOutputParams;
  741. // Copy macros
  742. for (i=0, j=0; i < pInfoTable->DI_NumOfParams; i++)
  743. {
  744. if (IsBinaryMacro(pInfoTable->DI_Params[i].P_Key))
  745. {
  746. // copy core macro name, Type, and Attributes, but not Value
  747. GetCoreMacroName(pInfoTable->DI_Params[i].P_Key, szCoreName);
  748. strcpy(pOutputTable->DI_Params[j].P_Key, szCoreName);
  749. pOutputTable->DI_Params[j].P_Type = pInfoTable->DI_Params[i].P_Type;
  750. pOutputTable->DI_Params[j].P_Attributes =
  751. pInfoTable->DI_Params[i].P_Attributes;
  752. pOutputTable->DI_Params[j].P_Value.String.Data = pValue;
  753. *pValue++ = '\0';
  754. pOutputTable->DI_Params[j].P_Value.String.Length = 0;
  755. i++;
  756. j++;
  757. }
  758. else // Is Unary Macro or Variable
  759. {
  760. // copy everything including Value
  761. pOutputTable->DI_Params[j] = pInfoTable->DI_Params[i];
  762. pOutputTable->DI_Params[j].P_Value.String.Data = pValue;
  763. strncpy(pValue, pInfoTable->DI_Params[i].P_Value.String.Data,
  764. pInfoTable->DI_Params[i].P_Value.String.Length);
  765. pOutputTable->DI_Params[j].P_Value.String.Length
  766. = pInfoTable->DI_Params[i].P_Value.String.Length;
  767. pValue += pInfoTable->DI_Params[i].P_Value.String.Length;
  768. *pValue++ = '\0';
  769. j++;
  770. }
  771. }
  772. *pdwSize = (DWORD) (pValue - pInfo);
  773. return(SUCCESS);
  774. }
  775. //* ConnectListen() --------------------------------------------------------
  776. //
  777. // Function: Worker routine for DeviceConnect and DeviceListen.
  778. //
  779. // Returns: ERROR_NO_COMMAND_FOUND
  780. // ERROR_STATE_MACHINES_ALREADY_STARTED
  781. // and codes returned by DeviceStateMachine()
  782. //*
  783. DWORD
  784. ConnectListen(HANDLE hIOPort,
  785. char *pszDeviceType,
  786. char *pszDeviceName,
  787. CMDTYPE eCmd)
  788. {
  789. DWORD dRC;
  790. DEVICE_CB *pDevice;
  791. // Get Device Control Block for this hIOPort
  792. dRC = GetDeviceCB(hIOPort, pszDeviceType, pszDeviceName, &pDevice);
  793. if (dRC != SUCCESS)
  794. return(dRC);
  795. // Check that DeviceStateMachine is not started (but is reset)
  796. if (pDevice->eDevNextAction != SEND)
  797. return(ERROR_STATE_MACHINES_ALREADY_STARTED);
  798. // Create Macro Translation Table for use by RasDevAPIs
  799. if ((dRC = BuildMacroXlationTable(pDevice)) != SUCCESS)
  800. return(dRC);
  801. // Do the next block only once for most devices,
  802. // but retry a few times when getting modem hardware errors
  803. do
  804. {
  805. // Initialize command types
  806. switch(RasDevIdFirstCommand(pDevice->hInfFile))
  807. {
  808. case CT_INIT:
  809. pDevice->eCmdType = CT_INIT;
  810. pDevice->eNextCmdType = eCmd;
  811. break;
  812. case CT_DIAL: //If 1st cmd is DIAL or LISTEN assume
  813. case CT_LISTEN: //the other is also present
  814. pDevice->eCmdType = eCmd;
  815. break;
  816. case CT_GENERIC:
  817. pDevice->eCmdType = CT_GENERIC;
  818. break;
  819. default:
  820. return(ERROR_NO_COMMAND_FOUND);
  821. }
  822. // Reseting state variables and purging com ports are not needed on
  823. // first time through loop, but are need on subsequent loops.
  824. // Reset state variables to initial values
  825. pDevice->eDevNextAction = SEND;
  826. pDevice->eRcvState = GETECHO;
  827. // Cancel any pending com port action and purge com buffers
  828. PurgeComm(hIOPort,
  829. PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  830. // Start state machine
  831. dRC = DeviceStateMachine(pDevice, hIOPort);
  832. } while(dRC == ERROR_PORT_OR_DEVICE &&
  833. pDevice->eDeviceType == DT_MODEM &&
  834. pDevice->dwRetries++ < MODEM_RETRIES );
  835. return(dRC);
  836. }
  837. //* DeviceTypeStrToEnum ----------------------------------------------------
  838. //
  839. // Function: Converts a device type string into a device type enum.
  840. //
  841. // Returns: The device type code.
  842. //
  843. //*
  844. DEVICETYPE
  845. DeviceTypeStrToEnum(LPTSTR lpszDeviceType)
  846. {
  847. if (_strnicmp(lpszDeviceType, MXS_NULL_TXT, MAX_DEVICETYPE_NAME) == 0)
  848. return(DT_NULL);
  849. if (_strnicmp(lpszDeviceType, MXS_MODEM_TXT, MAX_DEVICETYPE_NAME) == 0)
  850. return(DT_MODEM);
  851. if (_strnicmp(lpszDeviceType, MXS_PAD_TXT, MAX_DEVICETYPE_NAME) == 0)
  852. return(DT_PAD);
  853. if (_strnicmp(lpszDeviceType, MXS_SWITCH_TXT, MAX_DEVICETYPE_NAME) == 0)
  854. return(DT_SWITCH);
  855. return(DT_UNKNOWN);
  856. }
  857. //* GetInfFileName ---------------------------------------------------------
  858. //
  859. // Function: Converts a device type string into the full path name for the
  860. // appropriate INF file.
  861. //
  862. // The RAS_PATH define contains leading and trailin backslashes.
  863. // It looks like "\\RAS\\".
  864. //
  865. // Returns: Nothing.
  866. //
  867. //*
  868. void
  869. GetInfFileName(LPTSTR pszDeviceType, LPTSTR pszFileName, DWORD dwFileNameLen)
  870. {
  871. UINT uLen;
  872. uLen = GetSystemDirectory(pszFileName, dwFileNameLen);
  873. strcat(pszFileName, RAS_PATH);
  874. switch(DeviceTypeStrToEnum(pszDeviceType))
  875. {
  876. case DT_NULL:
  877. case DT_MODEM:
  878. strcat(pszFileName, MODEM_INF_FILENAME);
  879. break;
  880. case DT_PAD:
  881. strcat(pszFileName, PAD_INF_FILENAME);
  882. break;
  883. case DT_SWITCH:
  884. strcat(pszFileName, SWITCH_INF_FILENAME);
  885. break;
  886. default:
  887. strcat(pszFileName, "");
  888. }
  889. }
  890. //* IsVariable -------------------------------------------------------------
  891. //
  892. // Function: Returns TRUE if parameter's "Variable" attribute bit is set.
  893. // Note that FALSE implies that the paramater is a macro.
  894. //
  895. //*
  896. BOOL
  897. IsVariable(RAS_PARAMS Param)
  898. {
  899. return(ATTRIB_VARIABLE & Param.P_Attributes);
  900. }
  901. //* IsUnaryMacro -----------------------------------------------------------
  902. //
  903. // Function: Returns TRUE if param is a unary macro, otherwise FALSE.
  904. //
  905. //*
  906. BOOL
  907. IsUnaryMacro(RAS_PARAMS Param)
  908. {
  909. return(!IsVariable(Param) && !IsBinaryMacro(Param.P_Key));
  910. }
  911. //* IsBinaryMacro ----------------------------------------------------------
  912. //
  913. // Function: Returns TRUE if the string ends with off suffix or on suffix.
  914. //
  915. // FALSE inmplies that the string is a unary macro or a variable
  916. // name.
  917. //
  918. //*
  919. BOOL
  920. IsBinaryMacro(TCHAR *pch)
  921. {
  922. return((BOOL)BinarySuffix(pch));
  923. }
  924. //* BinarySuffix -----------------------------------------------------------
  925. //
  926. // Function: This function indicates whether the input string ends in
  927. // _off or _on.
  928. //
  929. // Returns: ON_SUFFIX, OFF_SUFFIX, or FALSE if neither is the case
  930. //
  931. //*
  932. WORD
  933. BinarySuffix(TCHAR *pch)
  934. {
  935. while (*pch != '\0')
  936. pch++;
  937. pch -= strlen(MXS_ON_SUFX);
  938. if (_stricmp(pch, MXS_ON_SUFX) == 0)
  939. return(ON_SUFFIX);
  940. while (*pch != '\0')
  941. pch++;
  942. pch -= strlen(MXS_OFF_SUFX);
  943. if (_stricmp(pch, MXS_OFF_SUFX) == 0)
  944. return(OFF_SUFFIX);
  945. return(FALSE);
  946. }
  947. //* GetCoreMacroName -------------------------------------------------------
  948. //
  949. // Function: Copies FullName to CoreName, but omits the angle brackets, <>,
  950. // for all macros, and omits the "_ON" or "_OFF" suffix for binary
  951. // macros.
  952. //
  953. // Returns: SUCCESS
  954. // ERROR_NOT_BINARY_MACRO
  955. //
  956. //*
  957. DWORD
  958. GetCoreMacroName(LPTSTR lpszFullName, LPTSTR lpszCoreName)
  959. {
  960. LPTCH lpch;
  961. strcpy(lpszCoreName, lpszFullName); // Copy FullName
  962. lpch = lpszCoreName;
  963. while (*lpch != '\0') // Check for _ON suffix
  964. lpch++;
  965. lpch -= strlen(MXS_ON_SUFX);
  966. if (_stricmp(lpch, MXS_ON_SUFX) == 0)
  967. {
  968. *lpch = '\0';
  969. return(SUCCESS);
  970. }
  971. while (*lpch != '\0') // Check for _OFF suffix
  972. lpch++;
  973. lpch -= strlen(MXS_OFF_SUFX);
  974. if (_stricmp(lpch, MXS_OFF_SUFX) == 0)
  975. {
  976. *lpch = '\0';
  977. return(SUCCESS);
  978. }
  979. return(ERROR_NOT_BINARY_MACRO);
  980. }
  981. //* CoreMacroNameMatch -----------------------------------------------------
  982. //
  983. // Function: Assumes that lpszShortName is in the form of a unary macro
  984. // name, <macro>, and that lpszFullName is a binary macro.
  985. // If either assumption is false the function returns FALSE.
  986. // Only if the names (without the angle brackets, <>, and without
  987. // the _on or _off suffixes) match exactly is TRUE returned.
  988. //
  989. // <speaker> will match <speaker_off> or <speaker_on>, but
  990. // will not match <speakers_off>.
  991. //
  992. // Returns: TRUE/FALSE
  993. //
  994. //*
  995. BOOL
  996. CoreMacroNameMatch(LPTSTR lpszShortName, LPTSTR lpszFullName)
  997. {
  998. TCHAR szCoreName[MAX_PARAM_KEY_SIZE];
  999. DWORD dRC;
  1000. dRC = GetCoreMacroName(lpszFullName, szCoreName);
  1001. if (dRC != SUCCESS)
  1002. return(FALSE);
  1003. return(_stricmp(lpszShortName, szCoreName) == 0);
  1004. }
  1005. //* InitParameterStr -------------------------------------------------------
  1006. //
  1007. // Function: Changes all spaces in the first parameter to NULL characters.
  1008. // On return the second parameter is a pointer to the NULL
  1009. // character at the end of the input string.
  1010. //
  1011. // This function converts space separated parameters into NULL
  1012. // terminated strings. GetNextParameter() is then used to move
  1013. // a pointer from one string to the next.
  1014. //
  1015. // Caution: This function alters the input string.
  1016. //
  1017. // Returns: Nothing.
  1018. //
  1019. //*
  1020. void
  1021. InitParameterStr(TCHAR *pch, TCHAR **ppchEnd)
  1022. {
  1023. while (*pch != '\0')
  1024. {
  1025. if ((*pch == ' ') || (*pch == ','))
  1026. *pch = '\0';
  1027. pch++;
  1028. }
  1029. *ppchEnd = pch;
  1030. }
  1031. //* GetNextParameter -------------------------------------------------------
  1032. //
  1033. // Function: If the first parameter points to a consecutive series of null
  1034. // terminated strings, this function advances the first parameter
  1035. // to the beginning of the next null terminated string.
  1036. // It will not move past the second parameter which is a pointer
  1037. // to the end of the consecutive series.
  1038. //
  1039. // Returns: Nothing.
  1040. //
  1041. //*
  1042. void
  1043. GetNextParameter(TCHAR **ppch, TCHAR *pchEnd)
  1044. {
  1045. while (**ppch != '\0') //Move to next zero character
  1046. (*ppch)++;
  1047. while (*ppch < pchEnd && **ppch == '\0') //Move to 1st char of next substr
  1048. (*ppch)++;
  1049. }
  1050. //* MacroCount -------------------------------------------------------------
  1051. //
  1052. // Function: This function returns a count of macros in the RASMAN_DEVICEINFO
  1053. // struct that the input parameter points to.
  1054. // ALL_MACROS: Unary and binary macros are counted.
  1055. // BINARY_MACRO: Only binary macros are counted.
  1056. // In either case the ON and OFF parts of a binary macro
  1057. // together count as one macro (not two).
  1058. //
  1059. // Returns: Count of macros in *pInfo.
  1060. //
  1061. //*
  1062. WORD
  1063. MacroCount(RASMAN_DEVICEINFO *pInfo, WORD wType)
  1064. {
  1065. WORD i, cMacros;
  1066. for(i=0, cMacros=0; i < pInfo->DI_NumOfParams; i++)
  1067. {
  1068. if (IsVariable(pInfo->DI_Params[i]))
  1069. ;
  1070. else if (IsBinaryMacro(pInfo->DI_Params[i].P_Key))
  1071. {
  1072. i++; // Step thru each part of a binary macro
  1073. cMacros++; // But count only once
  1074. }
  1075. else // Unary macro
  1076. if (wType == ALL_MACROS)
  1077. cMacros++;
  1078. }
  1079. return(cMacros);
  1080. }
  1081. //* CmdTypeToStr -----------------------------------------------------------
  1082. //
  1083. // Function: This function takes an enum CMDTYPE and converts it to a
  1084. // zero terminated ASCII string which it places in the buffer
  1085. // passed in the first parameter.
  1086. //
  1087. // Returns: Pointer to first parameter
  1088. //
  1089. //*
  1090. PTCH
  1091. CmdTypeToStr(PTCH pszStr, CMDTYPE eCmdType)
  1092. {
  1093. switch(eCmdType)
  1094. {
  1095. case CT_GENERIC:
  1096. *pszStr = '\0';
  1097. break;
  1098. case CT_INIT:
  1099. strcpy(pszStr, "_INIT");
  1100. break;
  1101. case CT_DIAL:
  1102. strcpy(pszStr, "_DIAL");
  1103. break;
  1104. case CT_LISTEN:
  1105. strcpy(pszStr, "_LISTEN");
  1106. break;
  1107. }
  1108. return(pszStr);
  1109. }
  1110. //* IsLoggingOn -----------------------------------------------------------
  1111. //
  1112. // Funciton: Reads the registry to determine if the device dialog is to
  1113. // be logged in a file.
  1114. //
  1115. // Returns: TRUE if logging is to take place; otherwise FALSE
  1116. //
  1117. //*
  1118. BOOL
  1119. IsLoggingOn(void)
  1120. {
  1121. HKEY hKey;
  1122. LONG lRC;
  1123. DWORD dwType, dwValue, dwValueSize = sizeof(dwValue);
  1124. lRC = RegOpenKey(HKEY_LOCAL_MACHINE, RASMAN_REGISTRY_PATH, &hKey);
  1125. if (lRC != ERROR_SUCCESS)
  1126. return(FALSE);
  1127. lRC = RegQueryValueEx(hKey,
  1128. RASMAN_LOGGING_VALUE,
  1129. NULL,
  1130. &dwType,
  1131. (LPBYTE)&dwValue,
  1132. &dwValueSize);
  1133. RegCloseKey(hKey);
  1134. if (lRC != ERROR_SUCCESS)
  1135. return(FALSE);
  1136. if (dwType != REG_DWORD)
  1137. return(FALSE);
  1138. return(dwValue ? TRUE : FALSE);
  1139. }
  1140. //* InitLog ---------------------------------------------------------------
  1141. //
  1142. // Funciton: Opens the log file in overwrite mode and writes a header
  1143. // which includes date and time.
  1144. //
  1145. // Returns: Nothing.
  1146. //
  1147. //*
  1148. void
  1149. InitLog(void)
  1150. {
  1151. TCHAR szBuffer[MAX_CMD_BUF_LEN];
  1152. int iSize;
  1153. DWORD dwBytesWritten;
  1154. SYSTEMTIME st;
  1155. // Create log file path
  1156. GetSystemDirectory(szBuffer, sizeof(szBuffer));
  1157. strcat(szBuffer, RAS_PATH);
  1158. strcat(szBuffer, LOG_FILENAME);
  1159. ghLogFile = CreateFile(szBuffer,
  1160. GENERIC_WRITE,
  1161. FILE_SHARE_READ,
  1162. NULL,
  1163. CREATE_ALWAYS,
  1164. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  1165. NULL);
  1166. if (ghLogFile == INVALID_HANDLE_VALUE)
  1167. {
  1168. gbLogDeviceDialog = FALSE;
  1169. return;
  1170. }
  1171. // Create header
  1172. GetLocalTime(&st);
  1173. iSize = sprintf(szBuffer,
  1174. "Remote Access Service Device Log %02d/%02d/%d %02d:%02d:%02d\r\n",
  1175. st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);
  1176. WriteFile(ghLogFile, szBuffer, (DWORD)iSize, &dwBytesWritten, NULL);
  1177. strcpy(szBuffer,
  1178. "---------------------------------------------------------------\r\n\r\n");
  1179. WriteFile(ghLogFile, szBuffer, strlen(szBuffer), &dwBytesWritten, NULL);
  1180. }
  1181. //* LogString -------------------------------------------------------------
  1182. //
  1183. // Funciton: Writes label and string to the Device Log file.
  1184. //
  1185. // Assumptions: Total length of labels and port handle string will be < 80
  1186. // characters.
  1187. //
  1188. // Returns: nothing.
  1189. //
  1190. //*
  1191. void
  1192. LogString(DEVICE_CB *pDev, TCHAR *pszLabel, TCHAR *psString, DWORD dwStringLen)
  1193. {
  1194. TCHAR sBuffer[MAX_CMD_BUF_LEN + 80];
  1195. TCHAR szPortLabel[] = "Port:";
  1196. DWORD dwBytesWritten, dwTotalLen;
  1197. // If file is getting large, start over with new file
  1198. if (GetFileSize(ghLogFile, NULL) > 100000)
  1199. {
  1200. CloseHandle(ghLogFile);
  1201. InitLog();
  1202. }
  1203. strcpy(sBuffer, szPortLabel);
  1204. dwTotalLen = strlen(szPortLabel);
  1205. strcpy(sBuffer + dwTotalLen, pDev->szPortName);
  1206. dwTotalLen += strlen(pDev->szPortName);
  1207. strcpy(sBuffer + dwTotalLen, " ");
  1208. dwTotalLen++;
  1209. strcpy(sBuffer + dwTotalLen, pszLabel);
  1210. dwTotalLen += strlen(pszLabel);
  1211. memcpy(sBuffer + dwTotalLen, psString, dwStringLen);
  1212. dwTotalLen += dwStringLen;
  1213. strcpy(sBuffer + dwTotalLen, "\r\n");
  1214. dwTotalLen += 2;
  1215. WriteFile(ghLogFile, sBuffer, dwTotalLen, &dwBytesWritten, NULL);
  1216. }
  1217. //* CheckForOverruns -------------------------------------------------------
  1218. //
  1219. // Funciton: Checks for com port overrun errors.
  1220. //
  1221. // Assumptions: Com port errors have been cleared before rasmxs dll APIs
  1222. // are called, that is, serial dll API PortInit was called
  1223. // prior to using the port, or PortClose and PortOpen were
  1224. // called.
  1225. //
  1226. // Returns: TRUE if an overrun error has occured; otherwise FALSE.
  1227. //
  1228. //*
  1229. BOOL
  1230. CheckForOverruns(HANDLE hIOPort)
  1231. {
  1232. DWORD dwErrors = 0;
  1233. ClearCommError(hIOPort, &dwErrors, NULL);
  1234. return((dwErrors & CE_OVERRUN) ? TRUE : FALSE);
  1235. }
  1236. //* LoadRasserDll ---------------------------------------------------------
  1237. //
  1238. // Funciton: Loads rasser.dll and gets entry points for two APIs.
  1239. //
  1240. // Returns: SUCCESS
  1241. // ERROR_PORT_NOT_CONFIGURED
  1242. //*
  1243. DWORD
  1244. LoadRasserDll(PortGetInfo_t *pPortGetInfo, PortSetInfo_t *pPortSetInfo)
  1245. {
  1246. HANDLE hLib;
  1247. // Load DLL
  1248. hLib = LoadLibrary(SERIAL_DLL_FILENAME);
  1249. if (hLib == NULL)
  1250. {
  1251. LogError(ROUTERLOG_CANNOT_LOAD_SERIAL_DLL, 0, NULL, NO_ERROR);
  1252. return(ERROR_PORT_NOT_CONFIGURED);
  1253. }
  1254. // Get entry points
  1255. // Note: Create a new, more appropriate error code to use here,
  1256. // such as, ERROR_CORRUPT_DLL.
  1257. PortSetInfo = (PortSetInfo_t) GetProcAddress(hLib, "PortSetInfo");
  1258. if (PortSetInfo == NULL)
  1259. return(ERROR_PORT_NOT_CONFIGURED);
  1260. PortGetInfo = (PortGetInfo_t) GetProcAddress(hLib, "PortGetInfo");
  1261. if (PortGetInfo == NULL)
  1262. return(ERROR_PORT_NOT_CONFIGURED);
  1263. return(SUCCESS);
  1264. }
  1265. //* OpenResponseSection ---------------------------------------------------
  1266. //
  1267. // Funciton: This function is only called if the device is a modem.
  1268. //
  1269. // 7-9-93 We now open the modem response section when a DCB
  1270. // is created for the first modem. Then we leave it open
  1271. // (while the RASMXS DLL is in memory).
  1272. //
  1273. // Returns: Error values from RasDevOpen.
  1274. //
  1275. //*
  1276. DWORD
  1277. OpenResponseSection (PCHAR szFileName)
  1278. {
  1279. DWORD dRC = SUCCESS ;
  1280. // **** Exclusion Begin ****
  1281. WaitForSingleObject(ResponseSection.Mutex, INFINITE) ;
  1282. if (ResponseSection.UseCount == 0)
  1283. dRC = RasDevOpen(szFileName,
  1284. RESPONSES_SECTION_NAME,
  1285. &ResponseSection.Handle) ;
  1286. if (dRC == SUCCESS)
  1287. ResponseSection.UseCount = 1 ; //This used to be an increment.
  1288. // *** Exclusion End ***
  1289. ReleaseMutex(ResponseSection.Mutex);
  1290. return dRC ;
  1291. }
  1292. //* OpenResponseSection ---------------------------------------------------
  1293. //
  1294. // Funciton: This function should never be called.
  1295. //
  1296. // 7-9-93 We now open the modem response section when a DCB
  1297. // is created for the first modem. Then we leave it open
  1298. // (while the RASMXS DLL is in memory).
  1299. //
  1300. // Returns: nothing.
  1301. //
  1302. //*
  1303. /***
  1304. VOID
  1305. CloseResponseSection ()
  1306. {
  1307. // **** Exclusion Begin ****
  1308. WaitForSingleObject(ResponseSection.Mutex, INFINITE) ;
  1309. ResponseSection.UseCount-- ;
  1310. if (ResponseSection.UseCount == 0)
  1311. RasDevClose (ResponseSection.Handle) ;
  1312. // *** Exclusion End ***
  1313. ReleaseMutex(ResponseSection.Mutex);
  1314. }
  1315. ***/
  1316. //* FindOpenDevSection
  1317. //
  1318. //
  1319. // Returns: TRUE if found, FALSE if not.
  1320. //*
  1321. BOOL
  1322. FindOpenDevSection (PTCH lpszFileName, PTCH lpszSectionName, HRASFILE *hFile)
  1323. {
  1324. SavedSections* temp ;
  1325. for (temp = gpSavedSections; temp; temp=temp->Next) {
  1326. if (!_strcmpi (temp->FileName, lpszFileName) &&
  1327. !_strcmpi (temp->SectionName, lpszSectionName) &&
  1328. !temp->InUse) {
  1329. *hFile = temp->hFile ;
  1330. temp->InUse = TRUE ;
  1331. RasDevResetCommand (*hFile) ;
  1332. return TRUE ;
  1333. }
  1334. }
  1335. return FALSE ;
  1336. }
  1337. //*
  1338. //
  1339. //
  1340. //
  1341. //*
  1342. VOID
  1343. AddOpenDevSection (PTCH lpszFileName, PTCH lpszSectionName, HRASFILE hFile)
  1344. {
  1345. SavedSections *temp ;
  1346. GetMem(sizeof(SavedSections), (char **)&temp) ;
  1347. if (temp == NULL)
  1348. return ; // section not saved - no problem
  1349. strcpy (temp->FileName, lpszFileName) ;
  1350. strcpy (temp->SectionName, lpszSectionName) ;
  1351. temp->InUse = TRUE ;
  1352. temp->hFile = hFile ;
  1353. if (gpSavedSections)
  1354. temp->Next = gpSavedSections ;
  1355. else
  1356. temp->Next = NULL ;
  1357. gpSavedSections = temp ;
  1358. }
  1359. //*
  1360. //
  1361. //
  1362. //
  1363. //*
  1364. VOID
  1365. CloseOpenDevSection (HRASFILE hFile)
  1366. {
  1367. SavedSections* temp ;
  1368. for (temp = gpSavedSections; temp; temp=temp->Next) {
  1369. if (temp->hFile == hFile) {
  1370. temp->InUse = FALSE ;
  1371. return ;
  1372. }
  1373. }
  1374. }
  1375. //* DbgPrntf --------------------------------------------------------------
  1376. //
  1377. // Funciton: DbgPrntf -- printf to the debugger console
  1378. // Takes printf style arguments.
  1379. // Expects newline characters at the end of the string.
  1380. // Written by BruceK.
  1381. //
  1382. // Returns: nothing
  1383. //
  1384. //*
  1385. #ifdef DEBUG
  1386. #include <stdarg.h>
  1387. #include <stdio.h>
  1388. void DbgPrntf(const char * format, ...) {
  1389. va_list marker;
  1390. char String[512];
  1391. va_start(marker, format);
  1392. vsprintf(String, format, marker);
  1393. OutputDebugString(String);
  1394. }
  1395. #endif //DEBUG
  1396. //* DbgStr ----------------------------------------------------------------
  1397. //
  1398. // Funciton: Writes an unterminated string to the debugger.
  1399. //
  1400. // Returns: nothing
  1401. //
  1402. //*
  1403. #ifdef DEBUG
  1404. void DbgStr(char Str[], DWORD StrLen)
  1405. {
  1406. DWORD i;
  1407. char Char[] = " ";
  1408. for (i=0; i<StrLen; i++)
  1409. {
  1410. Char[0] = Str[i];
  1411. OutputDebugString(Char);
  1412. }
  1413. if (StrLen > 0)
  1414. OutputDebugString("\n");
  1415. }
  1416. #endif //DEBUG
  1417. //* ConPrintf -------------------------------------------------------------
  1418. //
  1419. // Funciton: Writes debug information to the process's console window.
  1420. // Written by StefanS.
  1421. //
  1422. // Returns: nothing
  1423. //
  1424. //*
  1425. #ifdef DBGCON
  1426. VOID
  1427. ConPrintf ( char *Format, ... )
  1428. {
  1429. va_list arglist;
  1430. char OutputBuffer[1024];
  1431. DWORD length;
  1432. va_start( arglist, Format );
  1433. vsprintf( OutputBuffer, Format, arglist );
  1434. va_end( arglist );
  1435. length = strlen( OutputBuffer );
  1436. WriteFile( GetStdHandle(STD_OUTPUT_HANDLE),
  1437. (LPVOID )OutputBuffer,
  1438. length,
  1439. &length,
  1440. NULL );
  1441. }
  1442. #endif //DBGCON