//**************************************************************************** // // Microsoft NT Remote Access Service // // Copyright (C) 1992-93 Microsft Corporation. All rights reserved. // // Filename: serutil.c // // Revision History // // Sep 3, 1992 J. Perry Hannah Created // // // Description: This file contains utility functions which are used by // the serial DLL APIs. // //**************************************************************************** #include #include #include #include #include #include #include #include #include #include #include #include #include //* Global Variables ******************************************************* // extern SERIALPCB *gpSerialPCB; // Points to Serial PCB linked list extern HANDLE *ghRasfileMutex; // Mutex used to protect access to Rasfile extern HRASFILE ghIniFile; // Handle to Serial.ini memory image extern HANDLE ghAsyMac; // Handle to AsyncMac driver extern DWORD gLastError; //* Utility Funcitons ****************************************************** // //* GetIniFileName -------------------------------------------------------- // // Funciton: Puts the full path file name of the serial.ini file in the // first parameter. dwBufferLen is the size of the array // referenced by the first parameter. // // Returns: nothing // //* void GetIniFileName(char *pszFileName, DWORD dwBufferLen) { UINT uLen; uLen = GetSystemDirectory(pszFileName, dwBufferLen); strcat(pszFileName, RAS_PATH); strcat(pszFileName, SERIAL_INI_FILENAME); } //* AddPortToList ---------------------------------------------------------- // // Function: Adds a Serial Port Control Block to the head of the linked // list in the DLL's global memory. // // Returns: Nothing // // Exceptions: ERROR_ALLOCATING_MEMORY // //* void AddPortToList(HANDLE hIOPort, char *pszPortName) { SERIALPCB *pSPCB; // Add new Serial Port Control Block to head of list pSPCB = gpSerialPCB; GetMem(sizeof(SERIALPCB), (BYTE **)&gpSerialPCB); gpSerialPCB->pNextSPCB = pSPCB; // Set ID values in Serial Port Control Block gpSerialPCB->hIOPort = hIOPort; gpSerialPCB->uRasEndpoint = INVALID_HANDLE_VALUE; strcpy(gpSerialPCB->szPortName, pszPortName); // // Initialize overlapped structures. // gpSerialPCB->MonitorDevice.RO_EventType = OVEVT_DEV_STATECHANGE; gpSerialPCB->SendReceive.RO_EventType = OVEVT_DEV_ASYNCOP; // From Serial.ini file get info on the device attached to this port GetValueFromFile(gpSerialPCB->szPortName, SER_DEVICETYPE_KEY, gpSerialPCB->szDeviceType); GetValueFromFile(gpSerialPCB->szPortName, SER_DEVICENAME_KEY, gpSerialPCB->szDeviceName); } //* FindPortInList --------------------------------------------------------- // // Function: Finds the Serial Port Control Block in the linked list in // the DLL's global memory which contains the first parameter. // If the second parameter is not NULL on input, a pointer to // the previous PCB is returned in the second parameter. // // NOTE: If the found PCB is at the head of the list, ppPrevSPCB // will be the same as the return value. // // Returns: Pointer to found PCB, or NULL if PCB is not found. // // Exceptions: ERROR_PORT_NOT_OPEN // //* SERIALPCB * FindPortInList(HANDLE hIOPort, SERIALPCB **ppPrevSPCB) { SERIALPCB *pSPCB, *pPrev; pSPCB = pPrev = gpSerialPCB; while(pSPCB != NULL && pSPCB->hIOPort != hIOPort) { pPrev = pSPCB; pSPCB = pSPCB->pNextSPCB; } if (pSPCB == NULL) gLastError = ERROR_PORT_NOT_OPEN; else if (ppPrevSPCB != NULL) *ppPrevSPCB = pPrev; return(pSPCB); } //* FindPortNameInList ----------------------------------------------------- // // Function: Finds the Serial Port Control Block in the linked list in // the DLL's global memory which contains the Port name. // // Returns: Pointer to found PCB, or NULL if not found. // //* SERIALPCB * FindPortNameInList(TCHAR *pszPortName) { SERIALPCB *pSPCB; pSPCB = gpSerialPCB; while(pSPCB != NULL && _stricmp(pSPCB->szPortName, pszPortName) != 0) pSPCB = pSPCB->pNextSPCB; return(pSPCB); } //* InitCarrierBps --------------------------------------------------------- // // Function: Sets szCarrierBps in Serial Port Control Block to the // MAXCARRIERBPS value in serial.ini. // // Returns: Nothing // //* DWORD InitCarrierBps(char *pszPortName, char *pszMaxCarrierBps) { // Find section for pszPortName // Begin Exclusion if(INVALID_HRASFILE == ghIniFile) { return SUCCESS; } WaitForSingleObject(ghRasfileMutex, INFINITE); #if DBG ASSERT( INVALID_HRASFILE != ghIniFile ); #endif if (!RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE)) { // End Exclusion ReleaseMutex(ghRasfileMutex); return(ERROR_READING_SECTIONNAME); } // Get Device Type if(!(RasfileFindNextKeyLine(ghIniFile, SER_MAXCARRIERBPS_KEY, RFS_SECTION) && RasfileGetKeyValueFields(ghIniFile, NULL, pszMaxCarrierBps))) { // End Exclusion ReleaseMutex(ghRasfileMutex); return(ERROR_READING_INI_FILE); } // End Exclusion ReleaseMutex(ghRasfileMutex); return(SUCCESS); } //* SetCommDefaults -------------------------------------------------------- // // Function: Adds a Serial Port Control Block to the head of the linked // list in the DLL's global memory. Two fields are initialized: // hIOPort, from the first parameter, and eCmdType, from the // serial.ini file. // // Returns: Nothing // // Exceptions: ERROR_READING_INI_FILE // ERROR_UNKNOWN_DEVICE_TYPE // //* void SetCommDefaults(HANDLE hIOPort, char *pszPortName) { DCB DCB; char szInitialBPS[MAX_BPS_STR_LEN]; // Get a Device Control Block with current port values if (!GetCommState(hIOPort, &DCB)) { gLastError = GetLastError(); RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } strcpy(szInitialBPS, "28800"); // Read Max Connect BPS from Serial.ini GetValueFromFile(pszPortName, SER_INITBPS_KEY, szInitialBPS); // Set RAS default values in the DCB SetDcbDefaults(&DCB); DCB.BaudRate = atoi(szInitialBPS); // Send DCB to Port if (!SetCommState(hIOPort, &DCB)) { gLastError = GetLastError(); RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } } //* SetDcbDefaults ---------------------------------------------------------- // // Function: Sets DCB values (except BaudRate) to RAS default values. // // Returns: Nothing. // //* void SetDcbDefaults(DCB *pDCB) { pDCB->fBinary = TRUE; pDCB->fParity = FALSE; pDCB->fOutxCtsFlow = TRUE; pDCB->fOutxDsrFlow = FALSE; pDCB->fDtrControl = DTR_CONTROL_ENABLE; pDCB->fDsrSensitivity = FALSE; pDCB->fOutX = FALSE; pDCB->fInX = FALSE; pDCB->fNull = FALSE; pDCB->fRtsControl = RTS_CONTROL_HANDSHAKE; pDCB->fAbortOnError = FALSE; pDCB->ByteSize = 8; pDCB->Parity = NOPARITY; pDCB->StopBits = ONESTOPBIT; } //* StrToUsage ------------------------------------------------------------- // // Function: Converts string in first parameter to enum RASMAN_USAGE. // If string does not map to one of the enum values, the // function returns FALSE. // // Returns: TRUE if successful. // //* BOOL StrToUsage(char *pszStr, RASMAN_USAGE *peUsage) { if (_stricmp(pszStr, SER_USAGE_VALUE_NONE) == 0) *peUsage = CALL_NONE; else { if (strstr(pszStr, SER_USAGE_VALUE_CLIENT)) *peUsage |= CALL_OUT; if (strstr(pszStr, SER_USAGE_VALUE_SERVER)) *peUsage |= CALL_IN; if (strstr(pszStr, SER_USAGE_VALUE_ROUTER)) *peUsage |= CALL_ROUTER; } return(TRUE); } //* GetMem ----------------------------------------------------------------- // // Function: Allocates memory. // // Returns: Nothing. Raises exception on error. // //* void GetMem(DWORD dSize, BYTE **ppMem) { if ((*ppMem = (BYTE *) calloc(dSize, 1)) == NULL ) { gLastError = ERROR_ALLOCATING_MEMORY; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } } //* GetValueFromFile ------------------------------------------------------- // // Function: Finds the szKey for the pszPortName and copies its value // string to pszValue. // // Assumptions: ghIniFile has been initalized. // // Returns: Nothing. Raises exception on error. // //* void GetValueFromFile(TCHAR *pszPortName, TCHAR szKey[], TCHAR *pszValue) { // Begin Exclusion if(INVALID_HRASFILE == ghIniFile) { return; } #if DBG ASSERT( INVALID_HRASFILE != ghIniFile ); #endif WaitForSingleObject(ghRasfileMutex, INFINITE); if (!(RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE) && RasfileFindNextKeyLine(ghIniFile, szKey, RFS_SECTION) && RasfileGetKeyValueFields(ghIniFile, NULL, pszValue))) { // End Exclusion ReleaseMutex(ghRasfileMutex); gLastError = ERROR_READING_INI_FILE; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } // End Exclusion ReleaseMutex(ghRasfileMutex); } //* GetDefaultOffStr ------------------------------------------------------- // // Function: Copies the DefaultOff value string from serial.ini to the // first Serial Port Control Block. If there is no DefaultOff= // in serial.ini a string containing a not printable character // used as a flag is copied to the SPCB. // // Assumptions: The first SPCB on the list is the current one. This // function *must* be called only from PortOpen. // // Returns: Nothing. Raises exception on error. // //* void GetDefaultOffStr(HANDLE hIOPort, TCHAR *pszPortName) { if(INVALID_HRASFILE == ghIniFile) { return; } #if DBG ASSERT(INVALID_HRASFILE != ghIniFile ); #endif // Begin Exclusion WaitForSingleObject(ghRasfileMutex, INFINITE); if (!(RasfileFindSectionLine(ghIniFile, pszPortName, FROM_TOP_OF_FILE))) { // End Exclusion ReleaseMutex(ghRasfileMutex); gLastError = ERROR_READING_INI_FILE; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } if (!(RasfileFindNextKeyLine(ghIniFile, SER_DEFAULTOFFSTR_KEY, RFS_SECTION))) { // End Exclusion ReleaseMutex(ghRasfileMutex); *(gpSerialPCB->szDefaultOff) = USE_DEVICE_INI_DEFAULT; return; } if (!(RasfileGetKeyValueFields(ghIniFile, NULL, gpSerialPCB->szDefaultOff))) { // End Exclusion ReleaseMutex(ghRasfileMutex); gLastError = ERROR_READING_INI_FILE; RaiseException(EXCEPT_RAS_MEDIA, EXCEPTION_NONCONTINUABLE, 0, NULL); } // End Exclusion ReleaseMutex(ghRasfileMutex); } //* ValueToNum ------------------------------------------------------------- // // Function: Converts a RAS_PARAMS P_Value, which may be either a DWORD or // a string, to a DWORD. // // Returns: The numeric value of the input as a DWORD. // //* DWORD ValueToNum(RAS_PARAMS *p) { TCHAR szStr[RAS_MAXLINEBUFLEN]; if (p->P_Type == String) { strncpy(szStr, p->P_Value.String.Data, p->P_Value.String.Length); szStr[p->P_Value.String.Length] = '\0'; return(atol(szStr)); } else return(p->P_Value.Number); } //* ValueToBool ------------------------------------------------------------- // // Function: Converts a RAS_PARAMS P_Value, which may be either a DWORD or // a string, to a BOOL. // // Returns: The boolean value of the input. // //* BOOL ValueToBool(RAS_PARAMS *p) { TCHAR szStr[RAS_MAXLINEBUFLEN]; if (p->P_Type == String) { strncpy(szStr, p->P_Value.String.Data, p->P_Value.String.Length); szStr[p->P_Value.String.Length] = '\0'; return(atol(szStr) ? TRUE : FALSE); } else return(p->P_Value.Number ? TRUE : FALSE); } //* UpdateStatistics ------------------------------------------------------- // // Function: Updates the statistics when PortDisconnect is called so that // if PortGetStatistics is called while asyncmac is closed the // last good statistics will be reported. // // Returns: SUCCESS // Values from GetLastError() // //* DWORD UpdateStatistics(SERIALPCB *pSPCB) { #if 0 ASYMAC_GETSTATS A; DWORD dwBytesReturned; // Fill in GetStats struct A.MacAdapter = NULL; A.hRasEndpoint = pSPCB->uRasEndpoint; // Call Asymac to get current MAC statistics counts if (!DeviceIoControl(ghAsyMac, IOCTL_ASYMAC_GETSTATS, &A, sizeof(A), &A, sizeof(A), &dwBytesReturned, NULL)) return(GetLastError()); // Find difference between last PortClearStatistics and current counts pSPCB->Stats[BYTES_XMITED] = A.AsyMacStats.GenericStats.BytesTransmitted - pSPCB->Stats[BYTES_XMITED]; pSPCB->Stats[BYTES_RCVED] = A.AsyMacStats.GenericStats.BytesReceived - pSPCB->Stats[BYTES_RCVED]; pSPCB->Stats[FRAMES_XMITED] = A.AsyMacStats.GenericStats.FramesTransmitted - pSPCB->Stats[FRAMES_XMITED]; pSPCB->Stats[FRAMES_RCVED] = A.AsyMacStats.GenericStats.FramesReceived - pSPCB->Stats[FRAMES_RCVED]; pSPCB->Stats[CRC_ERR] = A.AsyMacStats.SerialStats.CRCErrors - pSPCB->Stats[CRC_ERR]; pSPCB->Stats[TIMEOUT_ERR] = A.AsyMacStats.SerialStats.TimeoutErrors - pSPCB->Stats[TIMEOUT_ERR]; pSPCB->Stats[ALIGNMENT_ERR] = A.AsyMacStats.SerialStats.AlignmentErrors - pSPCB->Stats[ALIGNMENT_ERR]; pSPCB->Stats[SERIAL_OVERRUN_ERR] = A.AsyMacStats.SerialStats.SerialOverrunErrors - pSPCB->Stats[SERIAL_OVERRUN_ERR]; pSPCB->Stats[FRAMING_ERR] = A.AsyMacStats.SerialStats.FramingErrors - pSPCB->Stats[FRAMING_ERR]; pSPCB->Stats[BUFFER_OVERRUN_ERR] = A.AsyMacStats.SerialStats.BufferOverrunErrors - pSPCB->Stats[BUFFER_OVERRUN_ERR]; pSPCB->Stats[BYTES_XMITED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesTransmittedUncompressed - pSPCB->Stats[BYTES_XMITED_UNCOMP]; pSPCB->Stats[BYTES_RCVED_UNCOMP] = A.AsyMacStats.CompressionStats.BytesReceivedUncompressed - pSPCB->Stats[BYTES_RCVED_UNCOMP]; pSPCB->Stats[BYTES_XMITED_COMP] = A.AsyMacStats.CompressionStats.BytesTransmittedCompressed - pSPCB->Stats[BYTES_XMITED_COMP]; pSPCB->Stats[BYTES_RCVED_COMP] = A.AsyMacStats.CompressionStats.BytesReceivedCompressed - pSPCB->Stats[BYTES_RCVED_COMP]; #endif return(SUCCESS); } //* DbgPrntf -------------------------------------------------------------- // // Funciton: DbgPrntf -- printf to the debugger console // Takes printf style arguments. // Expects newline characters at the end of the string. // Written by BruceK. // // Returns: nothing // //* #ifdef DEBUG #include #include void DbgPrntf(const char * format, ...) { va_list marker; char String[512]; va_start(marker, format); vsprintf(String, format, marker); OutputDebugString(String); } #endif // DEBUG