/*++ Copyright (C) 1994-98 Microsft Corporation. All rights reserved. Module Name: diag.c Abstract: This file contains helper routines to get the callerid/calledid and connect response. Author: Rao salapaka (raos) 23-Feb-1998 Revision History: --*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rastapi.h" #include "reghelp.h" #include /*++ Routine Description: Extract CallerID and CalledID information if available. Arguments: port - The tapi port on which the call was made / on which the call came in pLineCallInfo - the LINECALLINFO associated with this call pdwRequiredSize - pointer to buffer to receive the size of buffer required to hold the callerid and called id info. pConnectInfo - pointer to the RASTAPI_CONNECT_INFO struct where the information about the callerid and called id will be filledin. If this is not NULL then it is assumed that the buffer is big enough to store the callerid and called id iformation. Return Value: ERROR_SUCCESS if successful --*/ DWORD DwGetIDInformation( TapiPortControlBlock *port, LINECALLINFO *pLineCallInfo, DWORD *pdwRequiredSize, RASTAPI_CONNECT_INFO *pConnectInfo ) { DWORD dwRequiredSize = 0; DWORD dwErr = ERROR_SUCCESS; RasTapiTrace("DwGetIDInformation"); #if DBG RasTapiTrace ("RasTapiCallback: connected on %s", port->TPCB_Name ); RasTapiTrace("RasTapiCallback: CallerIDFlags=0x%x", pLineCallInfo->dwCallerIDFlags); RasTapiTrace("RasTapiCallback: CalledIDFlags=0x%x", pLineCallInfo->dwCalledIDFlags); RasTapiTrace("RasTapiCallback: dwNeededSize=%d", pLineCallInfo->dwNeededSize); RasTapiTrace("RasTapiCallback: dwUsedSize=%d", pLineCallInfo->dwUsedSize); RasTapiTrace("RasTapiCallback: dwCallerIDOffset=%d", pLineCallInfo->dwCallerIDOffset); RasTapiTrace("RasTapiCallback: dwCalledIdOffset=%d", pLineCallInfo->dwCalledIDOffset); RasTapiTrace("RasTapiCallback: dwCallerIdSize=%d", pLineCallInfo->dwCallerIDSize); RasTapiTrace("RasTapiCallback: dwCalledIdSize=%d", pLineCallInfo->dwCalledIDSize); RasTapiTrace("RasTapiCallback: dwCallerIdNameSize=%d", pLineCallInfo->dwCallerIDNameSize); RasTapiTrace("RasTapiCallback: dwCallerIdNameOffset=%d", pLineCallInfo->dwCallerIDNameOffset); #endif // // Find the size of the buffer to allocate // if(pLineCallInfo->dwCallerIDFlags & LINECALLPARTYID_ADDRESS) { // // Add one byte to allocate for NULL char // dwRequiredSize += RASMAN_ALIGN8(pLineCallInfo->dwCallerIDSize + 1); } if(pLineCallInfo->dwCalledIDFlags & LINECALLPARTYID_ADDRESS) { // // Add one byte to allocate for NULL char // dwRequiredSize += RASMAN_ALIGN8(pLineCallInfo->dwCalledIDSize + 1); } if( (NULL == pConnectInfo) || (0 == dwRequiredSize)) { goto done; } // // If pConnectInfo is != NULL it is assumed // that the buffer is large enough to put // the CALLER/CALLED ID information in it. // if( ( pLineCallInfo->dwCallerIDFlags & LINECALLPARTYID_ADDRESS ) && pLineCallInfo->dwCallerIDSize) { // // Copy the caller id information. Note that abdata // is already aligned at 8byte boundary // pConnectInfo->dwCallerIdSize = pLineCallInfo->dwCallerIDSize; pConnectInfo->dwCallerIdOffset = FIELD_OFFSET(RASTAPI_CONNECT_INFO, abdata); ZeroMemory( pConnectInfo->abdata, pLineCallInfo->dwCallerIDSize + 1); memcpy( pConnectInfo->abdata, (PBYTE) ((PBYTE) pLineCallInfo + pLineCallInfo->dwCallerIDOffset), pLineCallInfo->dwCallerIDSize); RasTapiTrace("GetIDInformation: CallerID=%s", (CHAR *) pConnectInfo->abdata); // // for the NULL char // pConnectInfo->dwCallerIdSize += 1; } else { RasTapiTrace("RasTapiCallback: caller id " "info. not avail"); } if( ( pLineCallInfo->dwCalledIDFlags & LINECALLPARTYID_ADDRESS) && pLineCallInfo->dwCalledIDSize) { // // Copy the called id information // pConnectInfo->dwCalledIdSize = pLineCallInfo->dwCalledIDSize; pConnectInfo->dwCalledIdOffset = FIELD_OFFSET(RASTAPI_CONNECT_INFO, abdata) + RASMAN_ALIGN8(pConnectInfo->dwCallerIdSize); ZeroMemory((PBYTE) ((PBYTE) pConnectInfo + pConnectInfo->dwCalledIdOffset), pLineCallInfo->dwCalledIDSize + 1); memcpy( (PBYTE) ((PBYTE) pConnectInfo + pConnectInfo->dwCalledIdOffset), (PBYTE) ((PBYTE) pLineCallInfo + pLineCallInfo->dwCalledIDOffset), pLineCallInfo->dwCalledIDSize); // // For the calledID // pConnectInfo->dwCalledIdSize += 1; } else { RasTapiTrace("RasTapiCallback: called id " "info. not avail"); } done: if(pdwRequiredSize) { *pdwRequiredSize = dwRequiredSize; } RasTapiTrace("DwGetIDInformation. %d", dwErr); return dwErr; } /*++ Routine Description: Extract the connect responses from lpLineDiagnostics(see MODEM_KEYTYPE_AT_COMMAND_RESPONSE,MODEMDIAGKEY_ATRESP_CONNECT) and copy them in lpBuffer Arguments: lpLineDiagnostics - diagnostic structure lpBuffer - destination buffer (can be NULL), upon return contains null terminated ASCII strings dwBufferSize - size in bytes of the buffer pointed by lpBuffer lpdwNeededSize - pointer (can be NULL) to a dword to receive the needed size Return Value: Returns the number of bytes copied into lpBuffer --*/ DWORD DwGetConnectResponses( LINEDIAGNOSTICS *lpLineDiagnostics, LPBYTE lpBuffer, DWORD dwBufferSize, LPDWORD lpdwNeededSize ) { DWORD dwBytesCopied; DWORD dwNeededSize; LINEDIAGNOSTICS *lpstructDiagnostics; RasTapiTrace("DwGetConnectresponses"); dwBytesCopied = 0; dwNeededSize = 0; lpstructDiagnostics = lpLineDiagnostics; while (NULL != lpstructDiagnostics) { LINEDIAGNOSTICS_PARSEREC *lpParsedDiagnostics; LINEDIAGNOSTICSOBJECTHEADER *lpParsedHeader; DWORD dwNumItems; DWORD dwIndex; // // check the signature for modem diagnostics // lpParsedHeader = PARSEDDIAGNOSTICS_HDR(lpstructDiagnostics); if ( (lpstructDiagnostics->hdr.dwSig != LDSIG_LINEDIAGNOSTICS) || (lpstructDiagnostics->dwDomainID != DOMAINID_MODEM) || !IS_VALID_PARSEDDIAGNOSTICS_HDR(lpParsedHeader)) { goto NextStructure; } // // get parsed structure info // dwNumItems = PARSEDDIAGNOSTICS_NUM_ITEMS(lpParsedHeader); lpParsedDiagnostics = PARSEDDIAGNOSTICS_DATA(lpstructDiagnostics); // // iterate the array of LINEDIAGNOSTICS_PARSERECs // for (dwIndex = 0; dwIndex < dwNumItems; dwIndex++) { DWORD dwThisLength; LPSTR lpszThisString; // // check is a connect response // if ( (lpParsedDiagnostics[dwIndex].dwKeyType != MODEM_KEYTYPE_AT_COMMAND_RESPONSE) || (lpParsedDiagnostics[dwIndex].dwKey != MODEMDIAGKEY_ATRESP_CONNECT) || !(lpParsedDiagnostics[dwIndex].dwFlags & fPARSEKEYVALUE_ASCIIZ_STRING)) { continue; } // // get the string, dwValue offset from the beginning // of lpParsedDiagnostics // lpszThisString = (LPSTR) ( (LPBYTE) lpParsedHeader + lpParsedDiagnostics[dwIndex].dwValue); dwThisLength = strlen(lpszThisString) + 1; if (dwThisLength == 1) { continue; } // // update needed size // dwNeededSize += dwThisLength; // // copy to buffer, if large enough // if ( NULL != lpBuffer && dwBytesCopied < dwBufferSize - 1) { DWORD dwBytesToCopy; // // dwThisLength includes null char, so // does dwBytesToCopy // dwBytesToCopy = min(dwThisLength, dwBufferSize - 1 - dwBytesCopied); if (dwBytesToCopy > 1) { memcpy(lpBuffer + dwBytesCopied, lpszThisString, dwBytesToCopy - 1); lpBuffer[dwBytesCopied + dwBytesToCopy - 1] = 0; dwBytesCopied += dwBytesToCopy; } } } NextStructure: if (lpstructDiagnostics->hdr.dwNextObjectOffset != 0) { lpstructDiagnostics = (LINEDIAGNOSTICS *) (((LPBYTE) lpstructDiagnostics) + lpstructDiagnostics->hdr.dwNextObjectOffset); } else { lpstructDiagnostics = NULL; } } // // the final null only if data is not empty // if (dwNeededSize > 0) { dwNeededSize++; if ( lpBuffer != NULL && dwBytesCopied < dwBufferSize) { lpBuffer[dwBytesCopied] = 0; dwBytesCopied++; } } if (lpdwNeededSize != NULL) { *lpdwNeededSize = dwNeededSize; } RasTapiTrace("DwGetConnectResponses done"); return dwBytesCopied; } /*++ Routine Description: Extract the connect response information Arguments: pLineCallInfo - the LINECALLINFO associated with this call hCall - handle to call pdwRequiredSize - This is in/out parameter. As IN it specifies the size of pBuffer. As OUT it contains the size required to store the connect response. pBuffer - buffer to receive the connect response. This can be NULL. Return Value: ERROR_SUCCESS if successful --*/ DWORD DwGetConnectResponseInformation( LINECALLINFO *pLineCallInfo, HCALL hCall, DWORD *pdwRequiredSize, BYTE *pBuffer ) { LONG lr = ERROR_SUCCESS; BYTE bvar[100]; LPVARSTRING pvar = (LPVARSTRING) bvar; LINEDIAGNOSTICS *pLineDiagnostics; DWORD dwConnectResponseSize = 0; RasTapiTrace("DwGetConnectResponseInformation"); // // Get the diagnostics information // ZeroMemory (pvar, sizeof(*pvar)); pvar->dwTotalSize = sizeof(bvar); lr = lineGetID( pLineCallInfo->hLine, pLineCallInfo->dwAddressID, hCall, LINECALLSELECT_CALL, pvar, szUMDEVCLASS_TAPI_LINE_DIAGNOSTICS); if( (LINEERR_STRUCTURETOOSMALL == lr) || pvar->dwNeededSize > sizeof(bvar)) { DWORD dwNeededSize = pvar->dwNeededSize; // // Allocate the required size // pvar = LocalAlloc( LPTR, dwNeededSize); if(NULL == pvar) { lr = (LONG) GetLastError(); goto done; } ZeroMemory (pvar, sizeof(*pvar)); pvar->dwTotalSize = dwNeededSize; lr = lineGetID( pLineCallInfo->hLine, pLineCallInfo->dwAddressID, hCall, LINECALLSELECT_CALL, pvar, szUMDEVCLASS_TAPI_LINE_DIAGNOSTICS); if(ERROR_SUCCESS != lr) { goto done; } } else if(ERROR_SUCCESS != lr) { goto done; } pLineDiagnostics = (LINEDIAGNOSTICS *) ((LPBYTE) pvar + pvar->dwStringOffset); (void) DwGetConnectResponses( pLineDiagnostics, pBuffer, *pdwRequiredSize, &dwConnectResponseSize); done: if(bvar != (LPBYTE) pvar) { LocalFree(pvar); } *pdwRequiredSize = dwConnectResponseSize; RasTapiTrace("DwGetConnectResponseInformation. 0x%x", lr); return (DWORD) lr; } /*++ Routine Description: Extract the connection information. This includes extracing the caller id / called id information and the connect response information for modems. Arguments: port - pointer to the rastapi port on which the call came in / was made hCall - handle to call pLineCallInfo - pointer to the LINECALLINFO structure associated with this call. Return Value: ERROR_SUCCESS if succcessful --*/ DWORD DwGetConnectInfo( TapiPortControlBlock *port, HCALL hCall, LINECALLINFO *pLineCallInfo ) { DWORD dwErr = ERROR_SUCCESS; DWORD dwRequiredSize = 0; DWORD dwConnectResponseSize = 0; RASTAPI_CONNECT_INFO *pConnectInfo = NULL; RasTapiTrace("DwGetConnectInfo"); // // Get the size required to store the // caller/called id information // dwErr = DwGetIDInformation(port, pLineCallInfo, &dwRequiredSize, NULL); if(ERROR_SUCCESS != dwErr) { goto done; } RasTapiTrace("SizeRequired for CallID=%d", dwRequiredSize); if(0 == _stricmp(port->TPCB_DeviceType, "modem")) { // // Get the size required to store connect // response if this is a modem // dwErr = DwGetConnectResponseInformation( pLineCallInfo, hCall, &dwConnectResponseSize, NULL); if(NO_ERROR != dwErr) { goto done; } RasTapiTrace("SizeRequired for ConnectResponse=%d", dwConnectResponseSize); } if(0 == (dwRequiredSize + dwConnectResponseSize)) { // // None of the information is available. // bail. // RasTapiTrace("CallIDSize=ConnectResponseSize=0"); goto done; } dwRequiredSize += ( RASMAN_ALIGN8(dwConnectResponseSize) + sizeof(RASTAPI_CONNECT_INFO)); // // Allocate the buffer // pConnectInfo = (RASTAPI_CONNECT_INFO *) LocalAlloc( LPTR, dwRequiredSize); if(NULL == pConnectInfo) { dwErr = GetLastError(); goto done; } // // Get the actual information // dwErr = DwGetIDInformation( port, pLineCallInfo, NULL, pConnectInfo); if(NO_ERROR != dwErr) { goto done; } // // Get Connect response if its a modem // if(0 == _stricmp(port->TPCB_DeviceType, "modem")) { pConnectInfo->dwConnectResponseOffset = FIELD_OFFSET(RASTAPI_CONNECT_INFO, abdata) + RASMAN_ALIGN8(pConnectInfo->dwCallerIdSize) + RASMAN_ALIGN8(pConnectInfo->dwCalledIdSize); pConnectInfo->dwConnectResponseSize = dwConnectResponseSize; dwErr = DwGetConnectResponseInformation( pLineCallInfo, hCall, &dwConnectResponseSize, (PBYTE) ((PBYTE) pConnectInfo + pConnectInfo->dwConnectResponseOffset)); if(ERROR_SUCCESS != dwErr) { goto done; } } port->TPCB_pConnectInfo = pConnectInfo; done: if( NO_ERROR != dwErr && NULL != pConnectInfo) { LocalFree(pConnectInfo); } RasTapiTrace("DwGetConnectInfo. 0x%x", dwErr); return dwErr; }