Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

4792 lines
128 KiB

/*++ BUILD Version: 0000 // Increment this if a change has global effects
Copyright (c) 1995-1996 Microsoft Corporation
Module Name:
kmddsp.c
Abstract:
This module contains
Author:
Dan Knudson (DanKn) 11-Apr-1995
Revision History:
Notes:
1. NdisTapi.sys needs to be modified to support IOCTL_DISCONNECT so we
don't have to close all the driver handles etc each time we get a
providerShutdown request (ideally we ought only have to close handles,
etc on a dll process detach).
2. There's the hack in TSPI_providerInit where tapisrv has to pass in
pointer to dwNumLines & dwNumPhones, becuase we determine the # of
devs when we send the CONNECT IOCTL
3. Ndistapi.h is not in sync w/ tapi.h & tspi.h, so make sure to use
the definitions in ndistapi.h as appropriate (like LINE_DEV_CAPS
instead of LINEDEVCAPS).
4. A slight perf gain might be realized by caching dev caps info for
each line (but can/will it chg on the fly?)
5. To keep bad 2.0 apps from blowing up if they try to look at version
1.4 or 2.0 structure fields we pad the area between the end of the
1.0 structure and the variable-length data with 0's. This is done
in GetAddrCaps, GetCallInfo, GetCallStatus, GetDevCaps, &
GetLineDevStatus.
6. Since TAPI 2.0 service providers are required to be 100% unicode,
kmddsp munge all incoming unicode strings to ascii before passing
them to an underlying driver, and also converts all returned ascii
strings (embedded in structures) to unicode.
--*/
#include "windows.h"
#include "winioctl.h"
#include "stdarg.h"
#include "stdio.h"
#define ULONGLONG DWORDLONG
#include "ntddndis.h"
#include "ndistapi.h"
#include "intrface.h"
//
// Note: the following are defined in both ndistapi.h & tapi.h (or tspi.h)
// and cause (more or less non-interesting) build warnings, so we
// undefine them after the first #include to do away with this
//
#undef LAST_LINEMEDIAMODE
#undef TSPI_MESSAGE_BASE
#undef LINE_NEWCALL
#undef LINE_CALLDEVSPECIFIC
#include "tapi.h"
#include "tspi.h"
#include "kmddsp.h"
#define MYHACK
void
AsyncEventsThread(
LPVOID lpParams
);
LONG
WINAPI
TranslateDriverResult(
ULONG ulResult
);
//BOOL
//WINAPI
//_CRT_INIT(
// HINSTANCE hDLL,
// DWORD dwReason,
// LPVOID lpReserved
// );
#if DBG
#define DBGOUT(arg) DbgPrt arg
VOID
DbgPrt(
IN DWORD dwDbgLevel,
IN PUCHAR DbgMessage,
IN ...
);
DWORD gdwDebugLevel;
#else
#define DBGOUT(arg)
#endif
LPVOID
WINAPI
DrvAlloc(
DWORD dwSize
);
VOID
WINAPI
DrvFree(
LPVOID lp
);
void
WINAPI
ProcessEvent(
PNDIS_TAPI_EVENT pEvent
);
LONG
WINAPI
PrepareSyncRequest(
ULONG Oid,
LPDWORD lphWidget,
DWORD dwWidgetType,
PNDISTAPI_REQUEST *ppNdisTapiRequest,
DWORD dwDataSize
);
LONG
WINAPI
PrepareAsyncRequest(
ULONG Oid,
LPDWORD lphWidget,
DWORD dwWidgetType,
DWORD dwRequestID,
PASYNC_REQUEST_WRAPPER *ppAsyncRequestWrapper,
DWORD dwDataSize
);
LONG
WINAPI
SyncDriverRequest(
DWORD dwIoControlCode,
PNDISTAPI_REQUEST pNdisTapiRequest
);
LONG
WINAPI
AsyncDriverRequest(
DWORD dwIoControlCode,
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper
);
//
// Global vars
//
DWORD gdwTlsIndex, gdwRequestID;
HANDLE ghDriverSync, ghDriverAsync, ghCompletionPort;
LINEEVENT gpfnLineEvent;
ASYNC_COMPLETION gpfnCompletionProc;
PASYNC_EVENTS_THREAD_INFO gpAsyncEventsThreadInfo;
CRITICAL_SECTION gInboundCallsCritSec, gRequestIDCritSec;
BOOL
WINAPI
DllMain(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if DBG
{
HKEY hKey;
DWORD dwDataSize, dwDataType;
TCHAR szTelephonyKey[] =
"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony",
szKmddspDebugLevel[] = "KmddspDebugLevel";
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szTelephonyKey,
0,
KEY_ALL_ACCESS,
&hKey
);
dwDataSize = sizeof (DWORD);
gdwDebugLevel=0;
RegQueryValueEx(
hKey,
szKmddspDebugLevel,
0,
&dwDataType,
(LPBYTE) &gdwDebugLevel,
&dwDataSize
);
RegCloseKey (hKey);
}
#endif
// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
// {
// return FALSE;
// }
DBGOUT((4, "DLL_PROCESS_ATTACH"));
//
// Get a thread local storage entry
//
if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
{
DBGOUT((1, "TlsAlloc() failed"));
return FALSE;
}
//
// Init global sync objects
//
InitializeCriticalSection (&gInboundCallsCritSec);
InitializeCriticalSection (&gRequestIDCritSec);
break;
}
case DLL_PROCESS_DETACH:
{
//
// Free resources
//
PREQUEST_THREAD_INFO pRequestThreadInfo;
DBGOUT((4, "DLL_PROCESS_DETACH"));
if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)))
{
DrvFree (pRequestThreadInfo->pBuf);
DrvFree (pRequestThreadInfo);
}
TlsFree (gdwTlsIndex);
DeleteCriticalSection (&gInboundCallsCritSec);
DeleteCriticalSection (&gRequestIDCritSec);
// _CRT_INIT (hDLL, dwReason, lpReserved);
break;
}
case DLL_THREAD_ATTACH:
{
PREQUEST_THREAD_INFO pRequestThreadInfo;
// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
// {
// DBGOUT((1, "DLL_THREAD_ATTACH, _CRT_INIT failed"));
// }
TlsSetValue (gdwTlsIndex, NULL);
break;
}
case DLL_THREAD_DETACH:
{
//
// Free resources
//
PREQUEST_THREAD_INFO pRequestThreadInfo;
if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)))
{
DrvFree (pRequestThreadInfo->pBuf);
DrvFree (pRequestThreadInfo);
}
// _CRT_INIT (hDLL, dwReason, lpReserved);
break;
}
} // switch
return TRUE;
}
#if DBG
#define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e,f)
void
PASCAL
InsertVarDataString(
LPVOID pStruct,
LPDWORD pdwXxxSize,
LPVOID pNewStruct,
LPDWORD pdwNewXxxSize,
DWORD dwFixedStructSize,
char *pszFieldName
)
#else
#define INSERTVARDATASTRING(a,b,c,d,e,f) InsertVarDataString(a,b,c,d,e)
void
PASCAL
InsertVarDataString(
LPVOID pStruct,
LPDWORD pdwXxxSize,
LPVOID pNewStruct,
LPDWORD pdwNewXxxSize,
DWORD dwFixedStructSize
)
#endif
{
DWORD dwXxxSize, dwTotalSize, dwXxxOffset;
//
// If the dwXxxSize field of the old struct is non-zero, then
// we need to do a ascii->unicode conversion on it. Check to
// make sure that the size/offset are valid (if not set the
// data size/offset in the new struct to 0) and then convert.
//
if ((dwXxxSize = *pdwXxxSize))
{
dwXxxOffset = *(pdwXxxSize + 1);
//#if DBG
dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
dwXxxOffset < dwFixedStructSize ||
dwXxxOffset >= dwTotalSize ||
(dwXxxSize + dwXxxOffset) > dwTotalSize)
{
DBGOUT((
0,
"ERROR! bad %s values, size=x%x, offset=x%x",
pszFieldName,
dwXxxSize,
dwXxxOffset
));
*pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
return;
}
//#endif
MultiByteToWideChar(
CP_ACP,
MB_PRECOMPOSED,
((LPBYTE) pStruct) + dwXxxOffset,
dwXxxSize,
(LPWSTR) (((LPBYTE) pNewStruct) +
((LPVARSTRING) pNewStruct)->dwUsedSize),
dwXxxSize * sizeof (WCHAR)
);
*pdwNewXxxSize = dwXxxSize * sizeof (WCHAR);
*(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
((LPVARSTRING) pNewStruct)->dwUsedSize += (dwXxxSize * sizeof (WCHAR));
}
}
#if DBG
#define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e,f)
void
PASCAL
InsertVarData(
LPVOID pStruct,
LPDWORD pdwXxxSize,
LPVOID pNewStruct,
LPDWORD pdwNewXxxSize,
DWORD dwFixedStructSize,
char *pszFieldName
)
#else
#define INSERTVARDATA(a,b,c,d,e,f) InsertVarData(a,b,c,d,e)
void
PASCAL
InsertVarData(
LPVOID pStruct,
LPDWORD pdwXxxSize,
LPVOID pNewStruct,
LPDWORD pdwNewXxxSize,
DWORD dwFixedStructSize
)
#endif
{
DWORD dwTotalSize, dwXxxSize, dwXxxOffset;
if ((dwXxxSize = *pdwXxxSize))
{
dwXxxOffset = *(pdwXxxSize + 1);
//#if DBG
dwTotalSize = ((LPVARSTRING) pStruct)->dwTotalSize;
if (dwXxxSize > (dwTotalSize - dwFixedStructSize) ||
dwXxxOffset < dwFixedStructSize ||
dwXxxOffset >= dwTotalSize ||
(dwXxxSize + dwXxxOffset) > dwTotalSize)
{
DBGOUT((
0,
"ERROR! bad %s values, size=x%x, offset=x%x",
pszFieldName,
dwXxxSize,
dwXxxOffset
));
*pdwNewXxxSize = *(pdwNewXxxSize + 1) = 0;
return;
}
//#endif
CopyMemory(
((LPBYTE) pNewStruct) + ((LPVARSTRING) pNewStruct)->dwUsedSize,
((LPBYTE) pStruct) + dwXxxOffset,
dwXxxSize
);
*pdwNewXxxSize = dwXxxSize;
*(pdwNewXxxSize + 1) = ((LPVARSTRING) pNewStruct)->dwUsedSize; // offset
((LPVARSTRING) pNewStruct)->dwUsedSize += dwXxxSize;
}
}
//
// TSPI_lineXxx funcs
//
LONG
TSPIAPI
TSPI_lineAccept(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_ACCEPT, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_ACCEPT) + dwSize // size of drv request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_ACCEPT pNdisTapiAccept =
(PNDIS_TAPI_ACCEPT) pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiAccept->hdCall = (HDRV_CALL) hdCall;
if ((pNdisTapiAccept->ulUserUserInfoSize = (ULONG) dwSize))
{
CopyMemory(
pNdisTapiAccept->UserUserInfo,
lpsUserUserInfo,
dwSize
);
}
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineAnswer(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_ANSWER, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_ANSWER) + dwSize // size of drv request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_ANSWER pNdisTapiAnswer =
(PNDIS_TAPI_ANSWER) pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiAnswer->hdCall = (HDRV_CALL) hdCall;
if ((pNdisTapiAnswer->ulUserUserInfoSize = (ULONG) dwSize))
{
CopyMemory(
pNdisTapiAnswer->UserUserInfo,
lpsUserUserInfo,
dwSize
);
}
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineClose(
HDRVLINE hdLine
)
{
LONG lResult;
PDRVLINE pLine = (PDRVLINE) hdLine;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_CLOSE, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_CLOSE) // size of drve req data
)) == TAPI_SUCCESS)
{
//
// Note that this is a command rather than a request, in that
// TAPI considers the line closed regardless of the request result.
//
PNDIS_TAPI_CLOSE pNdisTapiClose =
(PNDIS_TAPI_CLOSE) pNdisTapiRequest->Data;
//
// Mark line as invalid so any related events that show up
// will be discarded
//
pLine->dwKey = INVALID_KEY;
pNdisTapiClose->hdLine = (HDRV_LINE) hdLine;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
//
// Clean up our pLine. Make sure to clean up any calls in the
// inbound list that may not have been explicitly closed
// (i.e. new calls that showed up after TAPI had already
// started closing down this line)
//
EnterCriticalSection (&gInboundCallsCritSec);
{
PDRVCALL pCall;
while ((pCall = pLine->pInboundCalls))
{
pLine->pInboundCalls = pCall->pNext;
DrvFree (pCall);
}
}
LeaveCriticalSection (&gInboundCallsCritSec);
DrvFree (pLine);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineCloseCall(
HDRVCALL hdCall
)
{
LONG lResult;
HDRVCALL hdCallDrop = hdCall;
PDRVCALL pCall = (PDRVCALL) hdCall;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_CLOSE_CALL, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof (NDIS_TAPI_CLOSE_CALL) // size of drve req data
)) == TAPI_SUCCESS)
{
//
// Note that this is a command rather than a request, in that
// TAPI considers the call closed regardless of the request
// result.
//
BOOL bInboundCall;
PNDIS_TAPI_CLOSE_CALL pNdisTapiCloseCall;
//
// Safely determine if call is inbound or outbound, & if the
// latter then if necessary wait until the make call request
// has completed so we don't send a bad hdCall down to the
// driver with the close call request.
//
// We'll just return 0 if the call is bad or we AV (meaning
// a make call request failed & call struct was freed in post
// processing).
//
try
{
bInboundCall = (pCall->dwKey == INBOUND_CALL_KEY ? TRUE : FALSE);
if (bInboundCall == FALSE)
{
while (pCall->dwKey == OUTBOUND_CALL_KEY)
{
if (pCall->bIncomplete == FALSE)
{
hdCall = (HDRVCALL) pCall->hd_Call;
break;
}
else
{
Sleep (0);
}
}
if (pCall->dwKey != OUTBOUND_CALL_KEY)
{
return 0;
}
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
return 0;
}
//
// HACKHACK: the following is for legacy ndis wan isdn miniports
//
// Since there's no more "automatic" call dropping in TAPI when
// an app has closed the line & there are existing non-IDLE calls,
// and legacy NDIS WAN ISDN miniports rely on seeing an OID_TAPI_DROP,
// we need to synthesize this behavior if the call has not previously
// be dropped.
//
// Note: we do a sync rather than an async drop here
//
if (pCall->bDropped == FALSE)
{
HDRVCALL hdCallClose2 = hdCallDrop;
PNDISTAPI_REQUEST pNdisTapiRequestDrop;
if (PrepareSyncRequest(
OID_TAPI_DROP, // opcode
(LPDWORD) &hdCallDrop, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequestDrop, // ptr to ptr to request buffer
sizeof (NDIS_TAPI_DROP) // size of driver request data
) == TAPI_SUCCESS)
{
PNDIS_TAPI_DROP pNdisTapiDrop = (PNDIS_TAPI_DROP)
pNdisTapiRequestDrop->Data;
//
// Mark the call as bad so any events get discarded
//
pCall->dwKey = INVALID_KEY;
pNdisTapiDrop->hdCall = (HDRV_CALL) hdCallDrop;
SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequestDrop
);
}
if ((lResult = PrepareSyncRequest(
OID_TAPI_CLOSE_CALL, // opcode
(LPDWORD) &hdCallClose2, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof (NDIS_TAPI_CLOSE_CALL) // size of drve req data
)) != TAPI_SUCCESS)
{
return lResult;
}
}
//
// Mark the call as bad so any events get discarded
//
pCall->dwKey = INVALID_KEY;
//
// Set up the params & call the driver
//
pNdisTapiCloseCall = (PNDIS_TAPI_CLOSE_CALL) pNdisTapiRequest->Data;
pNdisTapiCloseCall->hdCall = (HDRV_CALL) hdCall;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
//
// Clean up our drv call
//
if (bInboundCall)
{
PDRVLINE pLine = (PDRVLINE) pCall->pLine;
EnterCriticalSection (&gInboundCallsCritSec);
if (pCall->pNext)
{
pCall->pNext->pPrev = pCall->pPrev;
}
if (pCall->pPrev)
{
pCall->pPrev->pNext = pCall->pNext;
}
else
{
pLine->pInboundCalls = pCall->pNext;
}
LeaveCriticalSection (&gInboundCallsCritSec);
}
DrvFree (pCall);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineConditionalMediaDetection(
HDRVLINE hdLine,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_CONDITIONAL_MEDIA_DETECTION, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to req buffer
// size of drv request data
sizeof(NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) +
(lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS))
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION
pNdisTapiConditionalMediaDetection =
(PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION) pNdisTapiRequest->Data;
pNdisTapiConditionalMediaDetection->hdLine = (HDRV_LINE) hdLine;
pNdisTapiConditionalMediaDetection->ulMediaModes = (ULONG)
dwMediaModes;
CopyMemory(
&pNdisTapiConditionalMediaDetection->LineCallParams,
lpCallParams,
lpCallParams->dwTotalSize
);
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
PASCAL
TSPI_lineDevSpecific_postProcess(
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
LONG lResult,
LPDWORD callStateMsgParams
)
{
if (lResult == TAPI_SUCCESS)
{
PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =(PNDIS_TAPI_DEV_SPECIFIC)
pAsyncRequestWrapper->NdisTapiRequest.Data;
CopyMemory(
(LPVOID) pAsyncRequestWrapper->dwRequestSpecific,
pNdisTapiDevSpecific->Params,
pNdisTapiDevSpecific->ulParamsSize
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineDevSpecific(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
LPVOID lpParams,
DWORD dwSize
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
//
// Init the request
//
if ((lResult = PrepareAsyncRequest(
OID_TAPI_DEV_SPECIFIC, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_DEV_SPECIFIC)+ // size of drv request data
(dwSize - 1)
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_DEV_SPECIFIC pNdisTapiDevSpecific =(PNDIS_TAPI_DEV_SPECIFIC)
pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiDevSpecific->hdLine = (HDRV_LINE) hdLine;
pNdisTapiDevSpecific->ulAddressID = (ULONG) dwAddressID;
if (hdCall)
{
LONG lResult = 0;
try
{
pNdisTapiDevSpecific->hdCall = ((PDRVCALL)(hdCall))->hd_Call;
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
lResult = LINEERR_INVALCALLHANDLE;
}
if (lResult)
{
DrvFree (pAsyncRequestWrapper);
return lResult;
}
}
else
{
pNdisTapiDevSpecific->hdCall = (HDRV_CALL) NULL;
}
pNdisTapiDevSpecific->ulParamsSize = (ULONG) dwSize;
CopyMemory (pNdisTapiDevSpecific->Params, lpParams, dwSize);
pAsyncRequestWrapper->dwRequestSpecific = (DWORD) lpParams;
pAsyncRequestWrapper->pfnPostProcess =
TSPI_lineDevSpecific_postProcess;
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineDial(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
LONG lResult;
DWORD dwLength = lstrlenW (lpszDestAddress) + 1;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_DIAL, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_DIAL) + dwLength // size of driver request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_DIAL pNdisTapiDial =
(PNDIS_TAPI_DIAL) pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiDial->hdCall = (HDRV_CALL) hdCall;
pNdisTapiDial->ulDestAddressSize = (ULONG) dwLength;
//
// Note: old miniports expect strings to be ascii
//
WideCharToMultiByte(
CP_ACP,
0,
lpszDestAddress,
-1,
(LPSTR) pNdisTapiDial->szDestAddress,
dwLength,
NULL,
NULL
);
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
PASCAL
TSPI_lineDrop_postProcess(
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
LONG lResult,
LPDWORD callStateMsgParams
)
{
PDRVCALL pCall = (PDRVCALL) pAsyncRequestWrapper->dwRequestSpecific;
HTAPICALL htCall;
HTAPILINE htLine;
//
// HACK ALERT!!!
//
// Some old-style miniports, notably pcimac, don't indicate IDLE msgs
// when they get a drop request- so we synthesize this for them.
//
if (lResult == TAPI_SUCCESS)
{
try
{
htCall = pCall->htCall;
htLine = ((PDRVLINE) pCall->pLine)->htLine;
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
return lResult;
}
(*gpfnLineEvent)(
htLine,
htCall,
LINE_CALLSTATE,
LINECALLSTATE_IDLE,
0,
0
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineDrop(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
LONG lResult;
PDRVCALL pCall = (PDRVCALL) hdCall;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_DROP, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_DROP) + dwSize // size of driver request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_DROP pNdisTapiDrop =
(PNDIS_TAPI_DROP) pAsyncRequestWrapper->NdisTapiRequest.Data;
//
// HACKHACK: the following is for legacy ndis wan isdn miniports
//
// Safely mark the call as dropped so the CloseCall code won't follow
// up with another "automatic" drop
//
try
{
pCall->bDropped = TRUE;
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
lResult = LINEERR_INVALCALLHANDLE;
}
if (lResult == 0)
{
pNdisTapiDrop->hdCall = (HDRV_CALL) hdCall;
if ((pNdisTapiDrop->ulUserUserInfoSize = (ULONG) dwSize))
{
CopyMemory(
pNdisTapiDrop->UserUserInfo,
lpsUserUserInfo,
dwSize
);
}
pAsyncRequestWrapper->dwRequestSpecific = (DWORD) pCall;
pAsyncRequestWrapper->pfnPostProcess = TSPI_lineDrop_postProcess;
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
else
{
DrvFree (pAsyncRequestWrapper);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetAddressCaps(
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_ADDRESS_CAPS, // opcode
&dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_ADDRESS_CAPS) + // size of drv request data
(lpAddressCaps->dwTotalSize - sizeof(LINE_ADDRESS_CAPS))
)) == TAPI_SUCCESS)
{
PLINE_ADDRESS_CAPS pCaps;
PNDIS_TAPI_GET_ADDRESS_CAPS pNdisTapiGetAddressCaps =
(PNDIS_TAPI_GET_ADDRESS_CAPS) pNdisTapiRequest->Data;
pNdisTapiGetAddressCaps->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiGetAddressCaps->ulAddressID = (ULONG) dwAddressID;
pNdisTapiGetAddressCaps->ulExtVersion = (ULONG) dwExtVersion;
pCaps = &pNdisTapiGetAddressCaps->LineAddressCaps;
pCaps->ulTotalSize = lpAddressCaps->dwTotalSize;
pCaps->ulNeededSize =
pCaps->ulUsedSize = sizeof (LINE_ADDRESS_CAPS);
ZeroMemory(
&pCaps->ulLineDeviceID,
sizeof (LINE_ADDRESS_CAPS) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
//
// Do some post processing to the returned data structure
// before passing it back to tapi:
// 1. Pad the area between the fixed 1.0 structure and the
// var data that the miniports pass back with 0's so a
// bad app that disregards the 1.0 version negotiation &
// references new 1.4 or 2.0 structure fields won't blow up
// 2. Convert ascii strings to unicode, & rebase all var data
//
//
// The real needed size is the sum of that requested by the
// underlying driver, plus padding for the new TAPI 1.4/2.0
// structure fields, plus the size of the var data returned
// by the driver to account for the ascii->unicode conversion.
// (Granted, we are very liberal in computing the value for
// this last part, but at least this way it's fast & we'll
// never have too little buffer space.
//
lpAddressCaps->dwNeededSize =
pCaps->ulNeededSize +
(sizeof (LINEADDRESSCAPS) - // v2.0 struct
sizeof (LINE_ADDRESS_CAPS)) + // v1.0 struct
(pCaps->ulNeededSize - sizeof (LINE_ADDRESS_CAPS));
//
// Copy over the fixed fields that don't need changing, i.e.
// everything from dwAddressSharing to dwCallCompletionModes
//
lpAddressCaps->dwLineDeviceID = dwDeviceID;
CopyMemory(
&lpAddressCaps->dwAddressSharing,
&pCaps->ulAddressSharing,
sizeof (LINE_ADDRESS_CAPS) - (12 * sizeof (DWORD))
);
if (lpAddressCaps->dwNeededSize > lpAddressCaps->dwTotalSize)
{
lpAddressCaps->dwUsedSize =
(lpAddressCaps->dwTotalSize < sizeof (LINEADDRESSCAPS) ?
lpAddressCaps->dwTotalSize : sizeof (LINEADDRESSCAPS));
}
else
{
lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
// v2.0 struct
INSERTVARDATASTRING(
pCaps,
&pCaps->ulAddressSize,
lpAddressCaps,
&lpAddressCaps->dwAddressSize,
sizeof (LINE_ADDRESS_CAPS),
"LINE_ADDRESS_CAPS.Address"
);
INSERTVARDATA(
pCaps,
&pCaps->ulDevSpecificSize,
lpAddressCaps,
&lpAddressCaps->dwDevSpecificSize,
sizeof (LINE_ADDRESS_CAPS),
"LINE_ADDRESS_CAPS.DevSpecific"
);
if (pCaps->ulCompletionMsgTextSize != 0)
{
// BUGBUG TSPI_lineGetAddressCaps: convert ComplMsgText to unicode???
INSERTVARDATA(
pCaps,
&pCaps->ulCompletionMsgTextSize,
lpAddressCaps,
&lpAddressCaps->dwCompletionMsgTextSize,
sizeof (LINE_ADDRESS_CAPS),
"LINE_ADDRESS_CAPS.CompletionMsgText"
);
lpAddressCaps->dwNumCompletionMessages =
pCaps->ulNumCompletionMessages;
lpAddressCaps->dwCompletionMsgTextEntrySize =
pCaps->ulCompletionMsgTextEntrySize;
}
}
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetAddressID(
HDRVLINE hdLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCWSTR lpsAddress,
DWORD dwSize
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
// BUGBUG unicode
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_ADDRESS_ID, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_ADDRESS_ID) + // size of drv request data
dwSize/2 - 1
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_GET_ADDRESS_ID pNdisTapiGetAddressID =
(PNDIS_TAPI_GET_ADDRESS_ID) pNdisTapiRequest->Data;
pNdisTapiGetAddressID->hdLine = (HDRV_LINE) hdLine;
pNdisTapiGetAddressID->ulAddressMode = (ULONG) dwAddressMode;
pNdisTapiGetAddressID->ulAddressSize = (ULONG) dwSize/2;
WideCharToMultiByte(
CP_ACP,
0,
lpsAddress,
dwSize,
(LPSTR) pNdisTapiGetAddressID->szAddress,
dwSize/2,
NULL,
NULL
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
*lpdwAddressID = pNdisTapiGetAddressID->ulAddressID;
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetAddressStatus(
HDRVLINE hdLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_ADDRESS_STATUS, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_ADDRESS_STATUS) + // size of drv request data
(lpAddressStatus->dwTotalSize - sizeof(LINE_ADDRESS_STATUS))
)) == TAPI_SUCCESS)
{
PLINE_ADDRESS_STATUS pStatus;
PNDIS_TAPI_GET_ADDRESS_STATUS pNdisTapiGetAddressStatus =
(PNDIS_TAPI_GET_ADDRESS_STATUS) pNdisTapiRequest->Data;
pNdisTapiGetAddressStatus->hdLine = (HDRV_LINE) hdLine;
pNdisTapiGetAddressStatus->ulAddressID = (ULONG) dwAddressID;
pStatus = &pNdisTapiGetAddressStatus->LineAddressStatus;
pStatus->ulTotalSize = (ULONG) lpAddressStatus->dwTotalSize;
pStatus->ulNeededSize =
pStatus->ulUsedSize = sizeof (LINE_ADDRESS_STATUS);
ZeroMemory(
&pStatus->ulNumInUse,
sizeof (LINE_ADDRESS_STATUS) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
CopyMemory(
lpAddressStatus,
&pNdisTapiGetAddressStatus->LineAddressStatus,
pNdisTapiGetAddressStatus->LineAddressStatus.ulUsedSize
);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetCallAddressID(
HDRVCALL hdCall,
LPDWORD lpdwAddressID
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_CALL_ADDRESS_ID, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_CALL_ADDRESS_ID) // size of drv request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_GET_CALL_ADDRESS_ID pNdisTapiGetCallAddressID =
(PNDIS_TAPI_GET_CALL_ADDRESS_ID) pNdisTapiRequest->Data;
pNdisTapiGetCallAddressID->hdCall = (HDRV_CALL) hdCall;
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
*lpdwAddressID = (DWORD) pNdisTapiGetCallAddressID->ulAddressID;
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetCallInfo(
HDRVCALL hdCall,
LPLINECALLINFO lpCallInfo
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_CALL_INFO, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_CALL_INFO) + // size of driver request data
(lpCallInfo->dwTotalSize - sizeof(LINE_CALL_INFO))
)) == TAPI_SUCCESS)
{
PLINE_CALL_INFO pInfo;
PNDIS_TAPI_GET_CALL_INFO pNdisTapiGetCallInfo =
(PNDIS_TAPI_GET_CALL_INFO) pNdisTapiRequest->Data;
pNdisTapiGetCallInfo->hdCall = (HDRV_CALL) hdCall;
pInfo = &pNdisTapiGetCallInfo->LineCallInfo;
pInfo->ulTotalSize = (ULONG) lpCallInfo->dwTotalSize;
pInfo->ulNeededSize =
pInfo->ulUsedSize = sizeof (LINE_CALL_INFO);
ZeroMemory(
&pInfo->hLine,
sizeof (LINE_CALL_INFO) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
//
// Do some post processing to the returned data structure
// before passing it back to tapi:
// 1. Pad the area between the fixed 1.0 structure and the
// var data that the miniports pass back with 0's so a
// bad app that disregards the 1.0 version negotiation &
// references new 1.4 or 2.0 structure fields won't blow up
// 2. Convert ascii strings to unicode, & rebase all var data
//
//
// The real needed size is the sum of that requested by the
// underlying driver, plus padding for the new TAPI 1.4/2.0
// structure fields, plus the size of the var data returned
// by the driver to account for the ascii->unicode conversion.
// (Granted, we are very liberal in computing the value for
// this last part, but at least this way it's fast & we'll
// never have too little buffer space.
//
lpCallInfo->dwNeededSize =
pInfo->ulNeededSize +
(sizeof (LINECALLINFO) - // v2.0 struct
sizeof (LINE_CALL_INFO)) + // v1.0 struct
(pInfo->ulNeededSize - sizeof (LINE_CALL_INFO));
//
// Copy over the fixed fields that don't need changing,
// i.e. everything from dwLineDeviceID to dwTrunk
//
CopyMemory(
&lpCallInfo->dwLineDeviceID,
&pInfo->ulLineDeviceID,
23 * sizeof (DWORD)
);
if (lpCallInfo->dwNeededSize > lpCallInfo->dwTotalSize)
{
lpCallInfo->dwUsedSize =
(lpCallInfo->dwTotalSize < sizeof (LINECALLINFO) ?
lpCallInfo->dwTotalSize : sizeof (LINECALLINFO));
}
else
{
lpCallInfo->dwUsedSize = sizeof (LINECALLINFO); // v2.0 struct
lpCallInfo->dwCallerIDFlags = pInfo->ulCallerIDFlags;
INSERTVARDATASTRING(
pInfo,
&pInfo->ulCallerIDSize,
lpCallInfo,
&lpCallInfo->dwCallerIDSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.CallerID"
);
INSERTVARDATASTRING(
pInfo,
&pInfo->ulCallerIDNameSize,
lpCallInfo,
&lpCallInfo->dwCallerIDNameSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.CallerIDName"
);
lpCallInfo->dwCalledIDFlags = pInfo->ulCalledIDFlags;
INSERTVARDATASTRING(
pInfo,
&pInfo->ulCalledIDSize,
lpCallInfo,
&lpCallInfo->dwCalledIDSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.CalledID"
);
INSERTVARDATASTRING(
pInfo,
&pInfo->ulCalledIDNameSize,
lpCallInfo,
&lpCallInfo->dwCalledIDNameSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.CalledIDName"
);
lpCallInfo->dwConnectedIDFlags = pInfo->ulConnectedIDFlags;
INSERTVARDATASTRING(
pInfo,
&pInfo->ulConnectedIDSize,
lpCallInfo,
&lpCallInfo->dwConnectedIDSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.ConnectID"
);
INSERTVARDATASTRING(
pInfo,
&pInfo->ulConnectedIDNameSize,
lpCallInfo,
&lpCallInfo->dwConnectedIDNameSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.ConnectIDName"
);
lpCallInfo->dwRedirectionIDFlags = pInfo->ulRedirectionIDFlags;
INSERTVARDATASTRING(
pInfo,
&pInfo->ulRedirectionIDSize,
lpCallInfo,
&lpCallInfo->dwRedirectionIDSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.RedirectionID"
);
INSERTVARDATASTRING(
pInfo,
&pInfo->ulRedirectionIDNameSize,
lpCallInfo,
&lpCallInfo->dwRedirectionIDNameSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.RedirectionIDName"
);
lpCallInfo->dwRedirectingIDFlags = pInfo->ulRedirectingIDFlags;
INSERTVARDATASTRING(
pInfo,
&pInfo->ulRedirectingIDSize,
lpCallInfo,
&lpCallInfo->dwRedirectingIDSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.RedirectingID"
);
INSERTVARDATASTRING(
pInfo,
&pInfo->ulRedirectingIDNameSize,
lpCallInfo,
&lpCallInfo->dwRedirectingIDNameSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.RedirectingIDName"
);
INSERTVARDATA(
pInfo,
&pInfo->ulDisplaySize,
lpCallInfo,
&lpCallInfo->dwDisplaySize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.Display"
);
INSERTVARDATA(
pInfo,
&pInfo->ulUserUserInfoSize,
lpCallInfo,
&lpCallInfo->dwUserUserInfoSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.UserUserInfo"
);
INSERTVARDATA(
pInfo,
&pInfo->ulHighLevelCompSize,
lpCallInfo,
&lpCallInfo->dwHighLevelCompSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.HighLevelComp"
);
INSERTVARDATA(
pInfo,
&pInfo->ulLowLevelCompSize,
lpCallInfo,
&lpCallInfo->dwLowLevelCompSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.LowLevelComp"
);
INSERTVARDATA(
pInfo,
&pInfo->ulChargingInfoSize,
lpCallInfo,
&lpCallInfo->dwChargingInfoSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.ChargingInfo"
);
INSERTVARDATA(
pInfo,
&pInfo->ulTerminalModesSize,
lpCallInfo,
&lpCallInfo->dwTerminalModesSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.TerminalModes"
);
INSERTVARDATA(
pInfo,
&pInfo->ulDevSpecificSize,
lpCallInfo,
&lpCallInfo->dwDevSpecificSize,
sizeof (LINE_CALL_INFO),
"LINE_CALL_INFO.DevSpecific"
);
}
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetCallStatus(
HDRVCALL hdCall,
LPLINECALLSTATUS lpCallStatus
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_CALL_STATUS, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_CALL_STATUS) + // size of driver request data
(lpCallStatus->dwTotalSize - sizeof(LINE_CALL_STATUS))
)) == TAPI_SUCCESS)
{
PLINE_CALL_STATUS pStatus;
PNDIS_TAPI_GET_CALL_STATUS pNdisTapiGetCallStatus =
(PNDIS_TAPI_GET_CALL_STATUS) pNdisTapiRequest->Data;
pNdisTapiGetCallStatus->hdCall = (HDRV_CALL) hdCall;
pStatus = &pNdisTapiGetCallStatus->LineCallStatus;
pStatus->ulTotalSize = (ULONG) lpCallStatus->dwTotalSize;
pStatus->ulNeededSize =
pStatus->ulUsedSize = sizeof (LINE_CALL_STATUS);
ZeroMemory(
&pStatus->ulCallState,
sizeof (LINE_CALL_STATUS) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
//
// Do some post processing to the returned data structure
// before passing it back to tapi:
// 1. Pad the area between the fixed 1.0 structure and the
// var data that the miniports pass back with 0's so a
// bad app that disregards the 1.0 version negotiation &
// references new 1.4 or 2.0 structure fields won't blow up
// (no embedded ascii strings to convert to unicode)
//
//
// The real needed size is the sum of that requested by the
// underlying driver, plus padding for the new TAPI 1.4/2.0
// structure fields. (There are no embedded ascii strings to
// convert to unicode, so no extra space needed for that.)
//
lpCallStatus->dwNeededSize =
pStatus->ulNeededSize +
(sizeof (LINECALLSTATUS) - // v2.0 struct
sizeof (LINE_CALL_STATUS)); // v1.0 struct
//
// Copy over the fixed fields that don't need changing,
// i.e. everything from dwLineDeviceID to dwCallCompletionModes
//
CopyMemory(
&lpCallStatus->dwCallState,
&pStatus->ulCallState,
4 * sizeof (DWORD)
);
if (lpCallStatus->dwNeededSize > lpCallStatus->dwTotalSize)
{
lpCallStatus->dwUsedSize =
(lpCallStatus->dwTotalSize < sizeof (LINECALLSTATUS) ?
lpCallStatus->dwTotalSize : sizeof (LINECALLSTATUS));
}
else
{
lpCallStatus->dwUsedSize = sizeof (LINECALLSTATUS);
// v2.0 struct
INSERTVARDATA(
pStatus,
&pStatus->ulDevSpecificSize,
lpCallStatus,
&lpCallStatus->dwDevSpecificSize,
sizeof (LINE_CALL_STATUS),
"LINE_CALL_STATUS.DevSpecific"
);
}
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetDevCaps(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_DEV_CAPS, // opcode
&dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_DEV_CAPS) + // size of driver request data
(lpLineDevCaps->dwTotalSize - sizeof(LINE_DEV_CAPS))
)) == TAPI_SUCCESS)
{
PLINE_DEV_CAPS pCaps;
PNDIS_TAPI_GET_DEV_CAPS pNdisTapiGetDevCaps =
(PNDIS_TAPI_GET_DEV_CAPS) pNdisTapiRequest->Data;
pNdisTapiGetDevCaps->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiGetDevCaps->ulExtVersion = (ULONG) dwExtVersion;
pCaps = &pNdisTapiGetDevCaps->LineDevCaps;
pCaps->ulTotalSize = (ULONG) lpLineDevCaps->dwTotalSize;
pCaps->ulNeededSize =
pCaps->ulUsedSize = sizeof (LINE_DEV_CAPS);
ZeroMemory(
&pCaps->ulProviderInfoSize,
sizeof (LINE_DEV_CAPS) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
//
// Do some post processing to the returned data structure
// before passing it back to tapi:
// 1. Pad the area between the fixed 1.0 structure and the
// var data that the miniports pass back with 0's so a
// bad app that disregards the 1.0 version negotiation &
// references new 1.4 or 2.0 structure fields won't blow up
// 2. Convert ascii strings to unicode, & rebase all var data
//
//
// The real needed size is the sum of that requested by the
// underlying driver, plus padding for the new TAPI 1.4/2.0
// structure fields, plus the size of the var data returned
// by the driver to account for the ascii->unicode conversion.
// (Granted, we are very liberal in computing the value for
// this last part, but at least this way it's fast & we'll
// never have too little buffer space.
//
lpLineDevCaps->dwNeededSize =
pCaps->ulNeededSize +
(sizeof (LINEDEVCAPS) - // v2.0 struct
sizeof (LINE_DEV_CAPS)) + // v1.0 struct
(pCaps->ulNeededSize - sizeof (LINE_DEV_CAPS));
//
// Copy over the fixed fields that don't need changing,
// i.e. everything from dwPermanentLineID to dwNumTerminals
//
CopyMemory(
&lpLineDevCaps->dwPermanentLineID,
&pCaps->ulPermanentLineID,
sizeof (LINE_DEV_CAPS) - (14 * sizeof (DWORD))
);
if (lpLineDevCaps->dwNeededSize > lpLineDevCaps->dwTotalSize)
{
lpLineDevCaps->dwUsedSize =
(lpLineDevCaps->dwTotalSize < sizeof (LINEDEVCAPS) ?
lpLineDevCaps->dwTotalSize : sizeof (LINEDEVCAPS));
lpLineDevCaps->dwLineNameSize =
lpLineDevCaps->dwLineNameOffset = 0;
}
else
{
lpLineDevCaps->dwUsedSize = sizeof (LINEDEVCAPS);
// v2.0 struct
INSERTVARDATASTRING(
pCaps,
&pCaps->ulProviderInfoSize,
lpLineDevCaps,
&lpLineDevCaps->dwProviderInfoSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.ProviderInfo"
);
INSERTVARDATASTRING(
pCaps,
&pCaps->ulSwitchInfoSize,
lpLineDevCaps,
&lpLineDevCaps->dwSwitchInfoSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.SwitchInfo"
);
INSERTVARDATASTRING(
pCaps,
&pCaps->ulLineNameSize,
lpLineDevCaps,
&lpLineDevCaps->dwLineNameSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.LineName"
);
INSERTVARDATA(
pCaps,
&pCaps->ulTerminalCapsSize,
lpLineDevCaps,
&lpLineDevCaps->dwTerminalCapsSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.TerminalCaps"
);
// BUGBUG TSPI_lineGetDevCaps: convert DevCaps.TermText to unicode???
lpLineDevCaps->dwTerminalTextEntrySize =
pCaps->ulTerminalTextEntrySize;
INSERTVARDATA(
pCaps,
&pCaps->ulTerminalTextSize,
lpLineDevCaps,
&lpLineDevCaps->dwTerminalTextSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.TerminalText"
);
INSERTVARDATA(
pCaps,
&pCaps->ulDevSpecificSize,
lpLineDevCaps,
&lpLineDevCaps->dwDevSpecificSize,
sizeof (LINE_DEV_CAPS),
"LINE_DEV_CAPS.DevSpecific"
);
}
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetDevConfig(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCWSTR lpszDeviceClass
)
{
LONG lResult;
DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_DEV_CONFIG, // opcode
&dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_DEV_CONFIG) + // size of driver request data
(lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING)) + dwLength
)) == TAPI_SUCCESS)
{
PVAR_STRING pConfig;
PNDIS_TAPI_GET_DEV_CONFIG pNdisTapiGetDevConfig =
(PNDIS_TAPI_GET_DEV_CONFIG) pNdisTapiRequest->Data;
pNdisTapiGetDevConfig->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiGetDevConfig->ulDeviceClassSize = (ULONG) dwLength;
pNdisTapiGetDevConfig->ulDeviceClassOffset = (ULONG)
sizeof(NDIS_TAPI_GET_DEV_CONFIG) +
(lpDeviceConfig->dwTotalSize - sizeof(VAR_STRING));
pConfig = &pNdisTapiGetDevConfig->DeviceConfig;
pConfig->ulTotalSize = (ULONG) lpDeviceConfig->dwTotalSize;
pConfig->ulNeededSize =
pConfig->ulUsedSize = sizeof (VAR_STRING);
pConfig->ulStringFormat =
pConfig->ulStringSize =
pConfig->ulStringOffset = 0;
//
// Note: old miniports expect strings to be ascii
//
WideCharToMultiByte(
CP_ACP,
0,
lpszDeviceClass,
-1,
(LPSTR) (((LPBYTE) pNdisTapiGetDevConfig) +
pNdisTapiGetDevConfig->ulDeviceClassOffset),
dwLength,
NULL,
NULL
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
CopyMemory(
lpDeviceConfig,
&pNdisTapiGetDevConfig->DeviceConfig,
pNdisTapiGetDevConfig->DeviceConfig.ulUsedSize
);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetExtensionID(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
LPLINEEXTENSIONID lpExtensionID
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_EXTENSION_ID, // opcode
&dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_EXTENSION_ID) // size of driver request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_GET_EXTENSION_ID pNdisTapiGetExtensionID =
(PNDIS_TAPI_GET_EXTENSION_ID) pNdisTapiRequest->Data;
pNdisTapiGetExtensionID->ulDeviceID = (ULONG) dwDeviceID;
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
CopyMemory(
lpExtensionID,
&pNdisTapiGetExtensionID->LineExtensionID,
sizeof(LINE_EXTENSION_ID)
);
}
else
{
//
// Rather than indicating a failure, we'll just zero out the
// ext id (implying driver doesn't support extensions) and
// return success to tapisrv so it'll complete the open ok
//
ZeroMemory(
lpExtensionID,
sizeof(LINE_EXTENSION_ID)
);
lResult = TAPI_SUCCESS;
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetID(
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCWSTR lpszDeviceClass,
HANDLE hTargetProcess
)
{
LONG lResult;
DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_ID, // opcode
(LPDWORD)(dwSelect == LINECALLSELECT_CALL ? // target handle
(LPDWORD) &hdCall : (LPDWORD) &hdLine),
(dwSelect == LINECALLSELECT_CALL ? // target handle type
HT_HDCALL : HT_HDLINE),
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_ID) + // size of driver request data
(lpDeviceID->dwTotalSize - sizeof(VAR_STRING)) + dwLength
)) == TAPI_SUCCESS)
{
PVAR_STRING pID;
PNDIS_TAPI_GET_ID pNdisTapiGetID =
(PNDIS_TAPI_GET_ID) pNdisTapiRequest->Data;
pNdisTapiGetID->hdLine = (HDRV_LINE) hdLine;
pNdisTapiGetID->ulAddressID = (ULONG) dwAddressID;
pNdisTapiGetID->hdCall = (HDRV_CALL) hdCall;
pNdisTapiGetID->ulSelect = (ULONG) dwSelect;
pNdisTapiGetID->ulDeviceClassSize = (ULONG) dwLength;
pNdisTapiGetID->ulDeviceClassOffset = (ULONG)
sizeof(NDIS_TAPI_GET_ID) +
(lpDeviceID->dwTotalSize - sizeof(VAR_STRING));
pID = &pNdisTapiGetID->DeviceID;
pID->ulTotalSize = (ULONG) lpDeviceID->dwTotalSize;
pID->ulNeededSize =
pID->ulUsedSize = sizeof (VAR_STRING);
pID->ulStringFormat =
pID->ulStringSize =
pID->ulStringOffset = 0;
//
// Note: old miniports expect strings to be ascii
//
WideCharToMultiByte(
CP_ACP,
0,
lpszDeviceClass,
-1,
(LPSTR) (((LPBYTE) pNdisTapiGetID) +
pNdisTapiGetID->ulDeviceClassOffset),
dwLength,
NULL,
NULL
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
CopyMemory(
lpDeviceID,
&pNdisTapiGetID->DeviceID,
pNdisTapiGetID->DeviceID.ulUsedSize
);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetLineDevStatus(
HDRVLINE hdLine,
LPLINEDEVSTATUS lpLineDevStatus
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_GET_LINE_DEV_STATUS, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_GET_LINE_DEV_STATUS) + // size of drv request data
(lpLineDevStatus->dwTotalSize - sizeof(LINE_DEV_STATUS))
)) == TAPI_SUCCESS)
{
PLINE_DEV_STATUS pStatus;
PNDIS_TAPI_GET_LINE_DEV_STATUS pNdisTapiGetLineDevStatus =
(PNDIS_TAPI_GET_LINE_DEV_STATUS) pNdisTapiRequest->Data;
pNdisTapiGetLineDevStatus->hdLine = (HDRV_LINE) hdLine;
pStatus = &pNdisTapiGetLineDevStatus->LineDevStatus;
pStatus->ulTotalSize = (ULONG) lpLineDevStatus->dwTotalSize;
pStatus->ulNeededSize =
pStatus->ulUsedSize = sizeof (LINE_DEV_STATUS);
ZeroMemory(
&pStatus->ulNumOpens,
sizeof (LINE_DEV_STATUS) - 3 * sizeof (ULONG)
);
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
//
// Do some post processing to the returned data structure
// before passing it back to tapi:
// 1. Pad the area between the fixed 1.0 structure and the
// var data that the miniports pass back with 0's so a
// bad app that disregards the 1.0 version negotiation &
// references new 1.4 or 2.0 structure fields won't blow up
// (no embedded ascii strings to convert to unicode)
//
//
// The real needed size is the sum of that requested by the
// underlying driver, plus padding for the new TAPI 1.4/2.0
// structure fields. (There are no embedded ascii strings to
// convert to unicode, so no extra space needed for that.)
//
lpLineDevStatus->dwNeededSize =
pStatus->ulNeededSize +
(sizeof (LINEDEVSTATUS) - // v2.0 struct
sizeof (LINE_DEV_STATUS)); // v1.0 struct
//
// Copy over the fixed fields that don't need changing,
// i.e. everything from dwNumActiveCalls to dwDevStatusFlags
//
CopyMemory(
&lpLineDevStatus->dwNumActiveCalls,
&pStatus->ulNumActiveCalls,
sizeof (LINE_DEV_STATUS) - (9 * sizeof (DWORD))
);
if (lpLineDevStatus->dwNeededSize > lpLineDevStatus->dwTotalSize)
{
lpLineDevStatus->dwUsedSize =
(lpLineDevStatus->dwTotalSize < sizeof (LINEDEVSTATUS) ?
lpLineDevStatus->dwTotalSize : sizeof (LINEDEVSTATUS));
}
else
{
lpLineDevStatus->dwUsedSize = sizeof (LINEDEVSTATUS);
// v2.0 struct
INSERTVARDATA(
pStatus,
&pStatus->ulTerminalModesSize,
lpLineDevStatus,
&lpLineDevStatus->dwTerminalModesSize,
sizeof (LINE_DEV_STATUS),
"LINE_DEV_STATUS.TerminalModes"
);
INSERTVARDATA(
pStatus,
&pStatus->ulDevSpecificSize,
lpLineDevStatus,
&lpLineDevStatus->dwDevSpecificSize,
sizeof (LINE_DEV_STATUS),
"LINE_DEV_STATUS.DevSpecific"
);
}
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineGetNumAddressIDs(
HDRVLINE hdLine,
LPDWORD lpdwNumAddressIDs
)
{
//
// Since there isn't an OID_TAPI_GET_NUM_ADDRESS_IDS at this point
// we need to synthesize it by getting the dev caps and looking at
// the dwNumAddresses field of that structure. We first do this
// with a fixed size (+) structure, then if that doesn't cut it
// (i.e. the provider hasn't chg'd the dwNumAddresses field) we
// alloc a larger buffer (as per the returned dwNeededSize field)
// and try again. If we get an error along the way we just return
// 1 address- kludgy, but say "la vee".
//
// Note that we use the (P)LINE_DEV_CAPS types from ndistapi.h.
//
BOOL bTryAgain = TRUE;
DWORD dwTotalSize = sizeof (LINE_DEV_CAPS) + 128;
PDRVLINE pLine = (PDRVLINE) hdLine;
PLINE_DEV_CAPS pLineDevCaps;
TSPI_lineGetNumAddressIDs_allocBuffer:
if ((pLineDevCaps = DrvAlloc (dwTotalSize)))
{
pLineDevCaps->ulTotalSize = dwTotalSize;
pLineDevCaps->ulNeededSize =
pLineDevCaps->ulUsedSize = sizeof (LINE_DEV_CAPS);
if (TSPI_lineGetDevCaps(
pLine->dwDeviceID,
0x10003,
0,
(LPLINEDEVCAPS) pLineDevCaps
) == 0)
{
DWORD dwNumAddresses = (DWORD) pLineDevCaps->ulNumAddresses,
dwNeededSize = (DWORD) pLineDevCaps->ulNeededSize;
DrvFree (pLineDevCaps);
if (dwNumAddresses != 0)
{
*lpdwNumAddressIDs = dwNumAddresses;
return 0;
}
else if (bTryAgain && (dwNeededSize > dwTotalSize))
{
dwTotalSize = dwNeededSize;
bTryAgain = FALSE;
goto TSPI_lineGetNumAddressIDs_allocBuffer;
}
}
else
{
DrvFree (pLineDevCaps);
}
}
*lpdwNumAddressIDs = 1; // if here an error occured, default to 1 addr
return 0;
}
LONG
PASCAL
TSPI_lineMakeCall_postProcess(
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper,
LONG lResult,
LPDWORD callStateMsgParams
)
{
PDRVCALL pCall = (PDRVCALL) pAsyncRequestWrapper->dwRequestSpecific;
if (lResult == TAPI_SUCCESS)
{
PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
pAsyncRequestWrapper->NdisTapiRequest.Data;
//
// Check to see if a call state msg was received before we had
// the chance to process the completion notification, & if so
// fill in the msg params
//
if (pCall->dwPendingCallState)
{
callStateMsgParams[0] = (DWORD) ((PDRVLINE) pCall->pLine)->htLine;
callStateMsgParams[1] = (DWORD) pCall->htCall;
callStateMsgParams[2] = pCall->dwPendingCallState;
callStateMsgParams[3] = pCall->dwPendingCallStateMode;
callStateMsgParams[4] = pCall->dwPendingMediaMode;
}
pCall->hd_Call = pNdisTapiMakeCall->hdCall;
pCall->bIncomplete = FALSE;
}
else
{
pCall->dwKey = INVALID_KEY;
DrvFree (pCall);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineMakeCall(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams
)
{
LONG lResult;
DWORD dwLength;
PDRVCALL pCall;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
//
// First alloc & init a DRVCALL
//
if (!(pCall = DrvAlloc (sizeof(DRVCALL))))
{
return LINEERR_NOMEM;
}
pCall->dwKey = OUTBOUND_CALL_KEY;
pCall->dwDeviceID = ((PDRVLINE) hdLine)->dwDeviceID;
pCall->htCall = htCall;
pCall->pLine = (LPVOID) hdLine;
pCall->bIncomplete = TRUE;
//
// Init the request
//
dwLength = (lpszDestAddress ? lstrlenW (lpszDestAddress) + 1 : 0);
if ((lResult = PrepareAsyncRequest(
OID_TAPI_MAKE_CALL, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_MAKE_CALL) + // size of drv request data
dwLength + (lpCallParams ?
(lpCallParams->dwTotalSize - sizeof(LINE_CALL_PARAMS)) : 0)
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_MAKE_CALL pNdisTapiMakeCall = (PNDIS_TAPI_MAKE_CALL)
pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiMakeCall->hdLine = (HDRV_LINE) hdLine;
pNdisTapiMakeCall->htCall = (HTAPI_CALL) pCall;
pNdisTapiMakeCall->ulDestAddressSize = (ULONG) dwLength;
if (lpszDestAddress)
{
pNdisTapiMakeCall->ulDestAddressOffset =
sizeof(NDIS_TAPI_MAKE_CALL) +
(lpCallParams ? (lpCallParams->dwTotalSize -
sizeof(LINE_CALL_PARAMS)) : 0);
//
// Note: old miniports expect strings to be ascii
//
WideCharToMultiByte(
CP_ACP,
0,
lpszDestAddress,
dwLength,
(LPSTR) (((LPBYTE) pNdisTapiMakeCall) +
pNdisTapiMakeCall->ulDestAddressOffset),
dwLength,
NULL,
NULL
);
}
else
{
pNdisTapiMakeCall->ulDestAddressOffset = 0;
}
if (lpCallParams)
{
pNdisTapiMakeCall->bUseDefaultLineCallParams = FALSE;
CopyMemory(
&pNdisTapiMakeCall->LineCallParams,
lpCallParams,
lpCallParams->dwTotalSize
);
if (lpCallParams->dwOrigAddressSize != 0)
{
WideCharToMultiByte(
CP_ACP,
0,
(LPCWSTR) (((LPBYTE) lpCallParams) +
lpCallParams->dwOrigAddressOffset),
lpCallParams->dwOrigAddressSize / sizeof (WCHAR),
(LPSTR) (((LPBYTE) &pNdisTapiMakeCall->LineCallParams) +
lpCallParams->dwOrigAddressOffset),
lpCallParams->dwOrigAddressSize,
NULL,
NULL
);
pNdisTapiMakeCall->LineCallParams.ulOrigAddressSize /= 2;
}
}
else
{
pNdisTapiMakeCall->bUseDefaultLineCallParams = TRUE;
}
pAsyncRequestWrapper->dwRequestSpecific = (DWORD) pCall;
pAsyncRequestWrapper->pfnPostProcess = TSPI_lineMakeCall_postProcess;
*lphdCall = (HDRVCALL) pCall;
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineNegotiateExtVersion(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwExtVersion
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_NEGOTIATE_EXT_VERSION, // opcode
(LPDWORD) &dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_NEGOTIATE_EXT_VERSION) // size of drv req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNdisTapiNegotiateExtVersion =
(PNDIS_TAPI_NEGOTIATE_EXT_VERSION) pNdisTapiRequest->Data;
pNdisTapiNegotiateExtVersion->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiNegotiateExtVersion->ulLowVersion = (ULONG) dwLowVersion;
pNdisTapiNegotiateExtVersion->ulHighVersion = (ULONG) dwHighVersion;
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
*lpdwExtVersion = pNdisTapiNegotiateExtVersion->ulExtVersion;
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineNegotiateTSPIVersion(
DWORD dwDeviceID,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwTSPIVersion
)
{
*lpdwTSPIVersion = 0x00010003; // until the ndistapi spec widened
return 0;
}
LONG
TSPIAPI
TSPI_lineOpen(
DWORD dwDeviceID,
HTAPILINE htLine,
LPHDRVLINE lphdLine,
DWORD dwTSPIVersion,
LINEEVENT lpfnEventProc
)
{
LONG lResult;
PDRVLINE pLine;
PNDISTAPI_REQUEST pNdisTapiRequest;
//
// First alloc & init a DRVLINE
//
if (!(pLine = DrvAlloc (sizeof(DRVLINE))))
{
return LINEERR_NOMEM;
}
pLine->dwKey = LINE_KEY;
pLine->dwDeviceID = dwDeviceID;
pLine->htLine = htLine;
//
// Init the request
//
if ((lResult = PrepareSyncRequest(
OID_TAPI_OPEN, // opcode
(LPDWORD) &dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_OPEN) // size of drve req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_OPEN pNdisTapiOpen =
(PNDIS_TAPI_OPEN) pNdisTapiRequest->Data;
pNdisTapiOpen->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiOpen->htLine = (HTAPI_LINE) pLine;
if ((lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_QUERY_INFO,
pNdisTapiRequest
)) == TAPI_SUCCESS)
{
pLine->hd_Line = pNdisTapiOpen->hdLine;
*lphdLine = (HDRVLINE) pLine;
}
else
{
DrvFree (pLine);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSecureCall(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_SECURE_CALL, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_SECURE_CALL) // size of drv request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SECURE_CALL pNdisTapiSecureCall =
(PNDIS_TAPI_SECURE_CALL)
pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiSecureCall->hdCall = (HDRV_CALL) hdCall;
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSelectExtVersion(
HDRVLINE hdLine,
DWORD dwExtVersion
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_SELECT_EXT_VERSION, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_SELECT_EXT_VERSION) // size of drve req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SELECT_EXT_VERSION pNdisTapiSelectExtVersion =
(PNDIS_TAPI_SELECT_EXT_VERSION) pNdisTapiRequest->Data;
pNdisTapiSelectExtVersion->hdLine = (HDRV_LINE) hdLine;
pNdisTapiSelectExtVersion->ulExtVersion = (ULONG) dwExtVersion;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSendUserUserInfo(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_SEND_USER_USER_INFO, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_SEND_USER_USER_INFO) + // size of drv request data
dwSize
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SEND_USER_USER_INFO pNdisTapiSendUserUserInfo =
(PNDIS_TAPI_SEND_USER_USER_INFO)
pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiSendUserUserInfo->hdCall = (HDRV_CALL) hdCall;
if ((pNdisTapiSendUserUserInfo->ulUserUserInfoSize = (ULONG) dwSize))
{
CopyMemory(
pNdisTapiSendUserUserInfo->UserUserInfo,
lpsUserUserInfo,
dwSize
);
}
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetAppSpecific(
HDRVCALL hdCall,
DWORD dwAppSpecific
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_SET_APP_SPECIFIC, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_SET_APP_SPECIFIC) // size of driver request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_APP_SPECIFIC pNdisTapiSetAppSpecific =
(PNDIS_TAPI_SET_APP_SPECIFIC) pNdisTapiRequest->Data;
pNdisTapiSetAppSpecific->hdCall = (HDRV_CALL) hdCall;
pNdisTapiSetAppSpecific->ulAppSpecific = (ULONG) dwAppSpecific;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetCallParams(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
DWORD dwBearerMode,
DWORD dwMinRate,
DWORD dwMaxRate,
LPLINEDIALPARAMS const lpDialParams
)
{
LONG lResult;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
if ((lResult = PrepareAsyncRequest(
OID_TAPI_SET_CALL_PARAMS, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
dwRequestID, // request id
&pAsyncRequestWrapper, // ptr to ptr to request buffer
sizeof(NDIS_TAPI_SET_CALL_PARAMS) // size of drv request data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_CALL_PARAMS pNdisTapiSetCallParams =
(PNDIS_TAPI_SET_CALL_PARAMS)
pAsyncRequestWrapper->NdisTapiRequest.Data;
pNdisTapiSetCallParams->hdCall = (HDRV_CALL) hdCall;
pNdisTapiSetCallParams->ulBearerMode = (ULONG) dwBearerMode;
pNdisTapiSetCallParams->ulMinRate = (ULONG) dwMinRate;
pNdisTapiSetCallParams->ulMaxRate = (ULONG) dwMaxRate;
if (lpDialParams)
{
pNdisTapiSetCallParams->bSetLineDialParams = TRUE;
CopyMemory(
&pNdisTapiSetCallParams->LineDialParams,
lpDialParams,
sizeof(LINE_DIAL_PARAMS)
);
}
else
{
pNdisTapiSetCallParams->bSetLineDialParams = FALSE;
}
lResult = AsyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pAsyncRequestWrapper
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetDefaultMediaDetection(
HDRVLINE hdLine,
DWORD dwMediaModes
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult =PrepareSyncRequest(
OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to req buffer
sizeof(NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION) // sizeof req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION
pNdisTapiSetDefaultMediaDetection =
(PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)
pNdisTapiRequest->Data;
pNdisTapiSetDefaultMediaDetection->hdLine = (HDRV_LINE) hdLine;
pNdisTapiSetDefaultMediaDetection->ulMediaModes = (ULONG) dwMediaModes;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetDevConfig(
DWORD dwDeviceID,
LPVOID const lpDeviceConfig,
DWORD dwSize,
LPCWSTR lpszDeviceClass
)
{
LONG lResult;
DWORD dwLength = lstrlenW (lpszDeviceClass) + 1;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult =PrepareSyncRequest(
OID_TAPI_SET_DEV_CONFIG, // opcode
&dwDeviceID, // target handle
HT_DEVICEID, // target handle type
&pNdisTapiRequest, // ptr to ptr to req buffer
sizeof(NDIS_TAPI_SET_DEV_CONFIG) + // sizeof req data
dwLength + dwSize
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_DEV_CONFIG pNdisTapiSetDevConfig =
(PNDIS_TAPI_SET_DEV_CONFIG) pNdisTapiRequest->Data;
pNdisTapiSetDevConfig->ulDeviceID = (ULONG) dwDeviceID;
pNdisTapiSetDevConfig->ulDeviceClassSize = (ULONG) dwLength;
pNdisTapiSetDevConfig->ulDeviceClassOffset =
sizeof(NDIS_TAPI_SET_DEV_CONFIG) + dwSize - 1;
pNdisTapiSetDevConfig->ulDeviceConfigSize = dwSize;
CopyMemory(
pNdisTapiSetDevConfig->DeviceConfig,
lpDeviceConfig,
dwSize
);
//
// Note: old miniports expect strings to be ascii
//
WideCharToMultiByte(
CP_ACP,
0,
lpszDeviceClass,
-1,
(LPSTR) (((LPBYTE) pNdisTapiSetDevConfig) +
pNdisTapiSetDevConfig->ulDeviceClassOffset),
dwLength,
NULL,
NULL
);
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetMediaMode(
HDRVCALL hdCall,
DWORD dwMediaMode
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_SET_MEDIA_MODE, // opcode
(LPDWORD) &hdCall, // target handle
HT_HDCALL, // target handle type
&pNdisTapiRequest, // ptr to ptr to req buffer
sizeof(NDIS_TAPI_SET_MEDIA_MODE) // size of drv req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_MEDIA_MODE pNdisTapiSetMediaMode =
(PNDIS_TAPI_SET_MEDIA_MODE) pNdisTapiRequest->Data;
pNdisTapiSetMediaMode->hdCall = (HDRV_CALL) hdCall;
pNdisTapiSetMediaMode->ulMediaMode = (ULONG) dwMediaMode;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetStatusMessages(
HDRVLINE hdLine,
DWORD dwLineStates,
DWORD dwAddressStates
)
{
LONG lResult;
PNDISTAPI_REQUEST pNdisTapiRequest;
if ((lResult = PrepareSyncRequest(
OID_TAPI_SET_STATUS_MESSAGES, // opcode
(LPDWORD) &hdLine, // target handle
HT_HDLINE, // target handle type
&pNdisTapiRequest, // ptr to ptr to req buffer
sizeof(NDIS_TAPI_SET_STATUS_MESSAGES) // size of drv req data
)) == TAPI_SUCCESS)
{
PNDIS_TAPI_SET_STATUS_MESSAGES pNdisTapiSetStatusMessages =
(PNDIS_TAPI_SET_STATUS_MESSAGES) pNdisTapiRequest->Data;
pNdisTapiSetStatusMessages->hdLine = (HDRV_LINE) hdLine;
pNdisTapiSetStatusMessages->ulLineStates = (ULONG) dwLineStates;
pNdisTapiSetStatusMessages->ulAddressStates = (ULONG) dwAddressStates;
lResult = SyncDriverRequest(
(DWORD) IOCTL_NDISTAPI_SET_INFO,
pNdisTapiRequest
);
}
return lResult;
}
//
// TAPI_providerXxx funcs
//
LONG
TSPIAPI
TSPI_providerEnumDevices(
DWORD dwPermanentProviderID,
LPDWORD lpdwNumLines,
LPDWORD lpdwNumPhones,
HPROVIDER hProvider,
LINEEVENT lpfnLineCreateProc,
PHONEEVENT lpfnPhoneCreateProc
)
{
//
// Note: We really enum devs in providerInit, see the
// special case note there
//
*lpdwNumLines = 0;
*lpdwNumPhones = 0;
gpfnLineEvent = lpfnLineCreateProc;
return 0;
}
LONG
TSPIAPI
TSPI_providerInit(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID,
DWORD dwLineDeviceIDBase,
DWORD dwPhoneDeviceIDBase,
DWORD dwNumLines,
DWORD dwNumPhones,
ASYNC_COMPLETION lpfnCompletionProc,
LPDWORD lpdwTSPIOptions
)
{
LONG lResult= LINEERR_OPERATIONFAILED;
char szDeviceName[] = "NDISTAPI";
char szTargetPath[] = "\\Device\\NdisTapi";
char szCompleteDeviceName[] = "\\\\.\\NDISTAPI";
DWORD cbReturned, dwThreadID;
DBGOUT((3, "TSPI_providerInit: enter"));
//
// Inform tapisrv that we support multiple simultaneous requests
// (the WAN wrapper handles request serialization for miniports)
//
*lpdwTSPIOptions = 0;
//
// Create symbolic link to the kernel-mode driver
//
DefineDosDevice (DDD_RAW_TARGET_PATH, szDeviceName, szTargetPath);
//
// Open driver
//
if ((ghDriverSync = CreateFileA(
szCompleteDeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL // no template file
)) == INVALID_HANDLE_VALUE)
{
DBGOUT((
0,
"CreateFile (%s, non-overlapped) failed, err=%ld",
szCompleteDeviceName,
GetLastError()
));
goto providerInit_error0;
}
if ((ghDriverAsync = CreateFileA(
szCompleteDeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL // no template file
)) == INVALID_HANDLE_VALUE)
{
DBGOUT((
0,
"CreateFile (%s, overlapped) failed, err=%ld",
szCompleteDeviceName,
GetLastError()
));
goto providerInit_error1;
}
//
// Create io completion port
//
if ((ghCompletionPort = CreateIoCompletionPort(
ghDriverAsync,
NULL,
0,
0
)) == INVALID_HANDLE_VALUE)
{
DBGOUT((
0,
"CreateIoCompletionPort failed, err=%ld",
GetLastError()
));
goto providerInit_error2;
}
//
// Connect to driver- we send it a device ID base & it returns
// the number of devices it supports
//
{
DWORD adwConnectInfo[2] = { 1, 1 };
if (!DeviceIoControl(
ghDriverSync,
(DWORD) IOCTL_NDISTAPI_CONNECT,
adwConnectInfo, // BUGBUG
2*sizeof(DWORD),
&dwLineDeviceIDBase, // BUGBUG
sizeof(DWORD),
&cbReturned,
(LPOVERLAPPED) NULL
) ||
(cbReturned < sizeof(DWORD)))
{
DBGOUT((0, "CONNECT failed, err=%ld", GetLastError()));
goto providerInit_error3;
}
}
//
// Alloc the resources needed by the AsyncEventThread, and then
// create the thread
//
if ((gpAsyncEventsThreadInfo = (PASYNC_EVENTS_THREAD_INFO)
DrvAlloc (sizeof(ASYNC_EVENTS_THREAD_INFO))) == NULL)
{
goto providerInit_error4;
}
gpAsyncEventsThreadInfo->dwBufSize = INITIAL_TLS_BUF_SIZE;
if ((gpAsyncEventsThreadInfo->pBuf1 = (PNDISTAPI_EVENT_DATA)
DrvAlloc (INITIAL_TLS_BUF_SIZE)) == NULL)
{
goto providerInit_error5;
}
if ((gpAsyncEventsThreadInfo->pBuf2 = (PNDISTAPI_EVENT_DATA)
DrvAlloc (INITIAL_TLS_BUF_SIZE)) == NULL)
{
goto providerInit_error6;
}
if ((gpAsyncEventsThreadInfo->hThread = CreateThread(
(LPSECURITY_ATTRIBUTES) NULL, // no security attrs
0, // default stack size
(LPTHREAD_START_ROUTINE) // func addr
AsyncEventsThread,
(LPVOID) NULL, // thread param
0, // create flags
&dwThreadID // thread id
)) == NULL)
{
DBGOUT((1, "CreateThread (GetAsyncEventsThread) failed"));
goto providerInit_error7;
}
//
//
//
gdwRequestID = 1;
//
// !!! Special case for KMDDSP.TSP only !!!
//
// For KMDDSP.TSP only, TAPISRV.EXE will pass pointers in the
// dwNumLines/dwNumPhones variables rather than an actual
// number of lines/phones, thereby allowing the driver to tell
// TAPISRV.EXE how many devices are currently registered.
//
// This is really due to a design/interface problem in NDISTAPI.SYS.
// Since the current CONNECT IOCTLS expects both a device ID base &
// returns the num devs, we can't really do this in
// TSPI_providerEnumDevices as the device ID base is unknown
// at that point
//
*((LPDWORD)dwNumLines) = dwLineDeviceIDBase;
*((LPDWORD)dwNumPhones) = 0; // BUGBUG until we get OIDs for phones
//
// If here success
//
gpfnCompletionProc = lpfnCompletionProc;
lResult = TAPI_SUCCESS;
goto providerInit_return;
//
// Clean up resources if an error occured & then return
//
providerInit_error7:
DrvFree (gpAsyncEventsThreadInfo->pBuf2);
providerInit_error6:
DrvFree (gpAsyncEventsThreadInfo->pBuf1);
providerInit_error5:
DrvFree (gpAsyncEventsThreadInfo);
providerInit_error4:
providerInit_error3:
CloseHandle (ghCompletionPort);
providerInit_error2:
CloseHandle (ghDriverAsync);
providerInit_error1:
CloseHandle (ghDriverSync);
providerInit_error0:
DefineDosDevice (DDD_REMOVE_DEFINITION, szDeviceName, NULL);
providerInit_return:
DBGOUT((3, "TSPI_providerInit: exit, result=x%x", lResult));
return lResult;
}
LONG
TSPIAPI
TSPI_providerInstall(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
return TAPI_SUCCESS;
}
LONG
TSPIAPI
TSPI_providerRemove(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
return TAPI_SUCCESS;
}
LONG
TSPIAPI
TSPI_providerShutdown(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID
)
{
char deviceName[] = "NDISTAPI";
LONG lResult = TAPI_SUCCESS;
BOOL bResult;
ASYNC_REQUEST_WRAPPER asyncRequestWrapper;
DBGOUT((3, "TSPI_providerShutdown: enter"));
// BUGBUG all we ought to have to do here is send a DISCONNECT IOCTL
//
// Post an async request that, once completed, will cause the async
// request thread to kill itself. Wait until we're sure the thread
// is gone, then clean it's resources.
//
FillMemory (&asyncRequestWrapper, sizeof (ASYNC_REQUEST_WRAPPER), 0);
asyncRequestWrapper.dwKey = ASYNCREQWRAPPER_KEY;
asyncRequestWrapper.dwRequestID = 0xffffffff;
bResult = PostQueuedCompletionStatus(
ghCompletionPort,
sizeof (ASYNC_REQUEST_WRAPPER),
0,
&asyncRequestWrapper.Overlapped
);
if (bResult== FALSE)
{
//
// Failed to post a completion msg to the async event thread,
// so we have to manually nuke the thread. This is not the
// preferred method since resources can be left lying around
// (i.e. the thread stack isn't freed).
//
DBGOUT((
1,
"TSPI_providerShutdown: ERROR- manually terminating " \
"AsyncEventsThread, err=%d",
GetLastError()
));
TerminateThread (gpAsyncEventsThreadInfo->hThread, 0);
}
else
{
WaitForSingleObject (gpAsyncEventsThreadInfo->hThread, INFINITE);
}
CloseHandle (gpAsyncEventsThreadInfo->hThread);
DrvFree (gpAsyncEventsThreadInfo->pBuf2);
DrvFree (gpAsyncEventsThreadInfo->pBuf1);
DrvFree (gpAsyncEventsThreadInfo);
//
// Close the driver & remove the symbolic link
//
CloseHandle (ghCompletionPort);
CloseHandle (ghDriverSync);
CloseHandle (ghDriverAsync);
DefineDosDevice (DDD_REMOVE_DEFINITION, deviceName, NULL);
DBGOUT((3, "TSPI_providerShutdown: exit, lResult=x%x", lResult));
return lResult;
}
//
// Private support funcs
//
void
AsyncEventsThread(
LPVOID lpParams
)
{
BOOL bReceivedLineEvents;
OVERLAPPED overlapped;
PNDISTAPI_EVENT_DATA pNewEventsBuf, pCurrentEventsBuf;
DBGOUT((3, "AsyncEventsThread: enter"));
// BUGBUG bufsize ought be based on reg setting for drivers
//
// There are 2 event data buffers so we can be getting new line events
// while processing current line events. Mark the current events buf
// (buf2 in this case) as having 0 events the 1st time thru.
//
pNewEventsBuf = gpAsyncEventsThreadInfo->pBuf1;
gpAsyncEventsThreadInfo->pBuf2->ulUsedSize = 0;
pCurrentEventsBuf = gpAsyncEventsThreadInfo->pBuf2;
bReceivedLineEvents = TRUE;
//
// Loop waiting for completed requests and retrieving async events
//
while (1)
{
DWORD i, cbReturned;
LPOVERLAPPED lpOverlapped;
PNDIS_TAPI_EVENT pEvent;
//
// Start an overlapped request to get new events
// (while we're processing the current ones)
//
if (bReceivedLineEvents)
{
//
// Don't need events when using completion ports
//
overlapped.hEvent = NULL;
pNewEventsBuf->ulTotalSize = gpAsyncEventsThreadInfo->dwBufSize -
sizeof(NDISTAPI_EVENT_DATA) + 1;
pNewEventsBuf->ulUsedSize = 0;
DBGOUT((4, "AsyncEventsThread: sending GET_LINE_EVENTS"));
if (DeviceIoControl(
ghDriverAsync,
(DWORD) IOCTL_NDISTAPI_GET_LINE_EVENTS,
pNewEventsBuf,
sizeof(NDISTAPI_EVENT_DATA),
pNewEventsBuf,
gpAsyncEventsThreadInfo->dwBufSize,
&cbReturned,
&overlapped
) == FALSE)
{
}
//
// Handle the current events
//
pEvent = (PNDIS_TAPI_EVENT) pCurrentEventsBuf->Data;
for(i = 0;
i < (pCurrentEventsBuf->ulUsedSize / sizeof(NDIS_TAPI_EVENT));
i++
)
{
ProcessEvent (pEvent);
pEvent++;
}
}
//
// Wait for a request to complete
//
do
{
DWORD dwNumBytesTransferred, dwCompletionKey;
DBGOUT((3, "Calling GetQComplStat"));
if (GetQueuedCompletionStatus(
ghCompletionPort,
&dwNumBytesTransferred,
&dwCompletionKey,
&lpOverlapped,
(DWORD) -1 // infinite wait
) == FALSE && (lpOverlapped == NULL))
{
DBGOUT((
1,
"AsyncEventsThread: GetQComplStat failed, err=%d",
GetLastError()
));
}
} while (lpOverlapped == NULL);
//
// Check the returned overlapped struct to determine if
// we have some events to process or a completed request
//
if (lpOverlapped == &overlapped)
{
bReceivedLineEvents = TRUE;
pNewEventsBuf = pCurrentEventsBuf;
pCurrentEventsBuf =
(pCurrentEventsBuf == gpAsyncEventsThreadInfo->pBuf1 ?
gpAsyncEventsThreadInfo->pBuf2 :
gpAsyncEventsThreadInfo->pBuf1);
}
else
{
LONG lResult;
DWORD dwRequestID, callStateMsgParams[5];
PASYNC_REQUEST_WRAPPER pAsyncReqWrapper = (PASYNC_REQUEST_WRAPPER)
lpOverlapped;
bReceivedLineEvents = FALSE;
//
// Verify that pointer is valid
//
try
{
if (pAsyncReqWrapper->dwKey != ASYNCREQWRAPPER_KEY)
{
DBGOUT((3,
"AsyncEventsThread: bogus pReq x%x completed!",
pAsyncReqWrapper
));
continue;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
DBGOUT((3,
"AsyncEventsThread: bogus pReq x%x completed!",
pAsyncReqWrapper
));
continue;
}
//
//
//
if ((dwRequestID = pAsyncReqWrapper->dwRequestID) == 0xffffffff)
{
DBGOUT((3, "AsyncEventsThread: exit"));
ExitThread (0);
}
lResult = TranslateDriverResult(
pAsyncReqWrapper->NdisTapiRequest.ulReturnValue
);
DBGOUT((3,
"AsyncEventsThread: pReq=x%x completed, reqID=x%x, lResult=x%x",
pAsyncReqWrapper,
dwRequestID,
lResult
));
//
// Call the post processing proc if appropriate
//
callStateMsgParams[0] = 0;
if (pAsyncReqWrapper->pfnPostProcess)
{
(*pAsyncReqWrapper->pfnPostProcess)(
pAsyncReqWrapper,
lResult,
callStateMsgParams
);
}
//
// Free the async request wrapper
//
DrvFree (pAsyncReqWrapper);
//
// Call completion proc
//
(*gpfnCompletionProc)(dwRequestID, lResult);
if (callStateMsgParams[0])
{
(*gpfnLineEvent)(
(HTAPILINE) callStateMsgParams[0],
(HTAPICALL) callStateMsgParams[1],
(DWORD) LINE_CALLSTATE,
(DWORD) callStateMsgParams[2],
(DWORD) callStateMsgParams[3],
(DWORD) callStateMsgParams[4]
);
}
}
} // while
}
LONG
WINAPI
PrepareSyncRequest(
ULONG Oid,
LPDWORD lphWidget,
DWORD dwWidgetType,
PNDISTAPI_REQUEST *ppNdisTapiRequest,
DWORD dwDataSize
)
{
LONG lResult = 0;
PNDISTAPI_REQUEST pNdisTapiRequest;
PREQUEST_THREAD_INFO pRequestThreadInfo;
//
// Retrieve the thread local storage (if there is none then create some)
//
if ((pRequestThreadInfo = TlsGetValue (gdwTlsIndex)) == NULL)
{
if (!(pRequestThreadInfo = DrvAlloc (sizeof(REQUEST_THREAD_INFO))))
{
return LINEERR_NOMEM;
}
pRequestThreadInfo->dwBufSize = INITIAL_TLS_BUF_SIZE;
if (!(pRequestThreadInfo->pBuf = DrvAlloc (INITIAL_TLS_BUF_SIZE)))
{
return LINEERR_NOMEM;
}
TlsSetValue (gdwTlsIndex, (LPVOID) pRequestThreadInfo);
}
//
// Check to make sure our driver request buffer is big enough to
// hold all the data for this request
//
if (pRequestThreadInfo->dwBufSize < (dwDataSize+sizeof(NDISTAPI_REQUEST)))
{
PNDISTAPI_REQUEST pTmpDrvReqBuf;
if (!(pTmpDrvReqBuf = DrvAlloc (dwDataSize+sizeof(NDISTAPI_REQUEST))))
{
return LINEERR_NOMEM;
}
DrvFree (pRequestThreadInfo->pBuf);
pRequestThreadInfo->pBuf = pTmpDrvReqBuf;
pRequestThreadInfo->dwBufSize = dwDataSize;
}
pNdisTapiRequest = pRequestThreadInfo->pBuf;
//
// Safely initialize thie driver request
//
pNdisTapiRequest->Oid = Oid;
pNdisTapiRequest->ulDataSize = (DWORD) dwDataSize;
try
{
switch (dwWidgetType)
{
case HT_HDCALL:
{
PDRVCALL pCall = (PDRVCALL)(*lphWidget);
pNdisTapiRequest->ulDeviceID = pCall->dwDeviceID;
*lphWidget = pCall->hd_Call;
if (pCall->dwKey != INBOUND_CALL_KEY &&
pCall->dwKey != OUTBOUND_CALL_KEY)
{
lResult = LINEERR_INVALCALLHANDLE;
}
break;
}
case HT_HDLINE:
{
PDRVLINE pLine = (PDRVLINE)(*lphWidget);
pNdisTapiRequest->ulDeviceID = pLine->dwDeviceID;
*lphWidget = pLine->hd_Line;
if (pLine->dwKey != LINE_KEY)
{
lResult = LINEERR_INVALLINEHANDLE;
}
break;
}
case HT_DEVICEID:
pNdisTapiRequest->ulDeviceID = *((ULONG *) lphWidget);
break;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
lResult = (dwWidgetType == HT_HDCALL ? LINEERR_INVALCALLHANDLE :
LINEERR_INVALLINEHANDLE);
}
// Note: since request buf is tls we don't have to free it on error
EnterCriticalSection (&gRequestIDCritSec);
if (( *((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID) >= 0x7fffffff)
{
gdwRequestID = 1;
}
LeaveCriticalSection (&gRequestIDCritSec);
*ppNdisTapiRequest = pNdisTapiRequest;
return lResult;
}
LONG
WINAPI
PrepareAsyncRequest(
ULONG Oid,
LPDWORD lphWidget,
DWORD dwWidgetType,
DWORD dwRequestID,
PASYNC_REQUEST_WRAPPER *ppAsyncRequestWrapper,
DWORD dwDataSize
)
{
LONG lResult = 0;
PNDISTAPI_REQUEST pNdisTapiRequest;
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper;
//
// Alloc & init an async request wrapper
//
if (!(pAsyncRequestWrapper = DrvAlloc(
dwDataSize + sizeof(ASYNC_REQUEST_WRAPPER)
)))
{
return LINEERR_NOMEM;
}
//
// Don't need to create an event when using completion ports
//
pAsyncRequestWrapper->Overlapped.hEvent = (HANDLE) NULL;
pAsyncRequestWrapper->dwKey = ASYNCREQWRAPPER_KEY;
pAsyncRequestWrapper->dwRequestID = dwRequestID;
pAsyncRequestWrapper->pfnPostProcess = (POSTPROCESSPROC) NULL;
//
// Safely initialize the driver request
//
pNdisTapiRequest = &(pAsyncRequestWrapper->NdisTapiRequest);
pNdisTapiRequest->Oid = Oid;
pNdisTapiRequest->ulDataSize = (ULONG) dwDataSize;
try
{
if (dwWidgetType == HT_HDCALL)
{
pNdisTapiRequest->ulDeviceID =
((PDRVCALL)(*lphWidget))->dwDeviceID;
*lphWidget = ((PDRVCALL)(*lphWidget))->hd_Call;
}
else // HT_HDLINE
{
pNdisTapiRequest->ulDeviceID =
((PDRVLINE)(*lphWidget))->dwDeviceID;
*lphWidget = ((PDRVLINE)(*lphWidget))->hd_Line;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
lResult = (dwWidgetType == HT_HDCALL ? LINEERR_INVALCALLHANDLE :
LINEERR_INVALLINEHANDLE);
}
if (lResult == 0)
{
EnterCriticalSection (&gRequestIDCritSec);
if (( *((ULONG *)pNdisTapiRequest->Data) = ++gdwRequestID)
>= 0x7fffffff)
{
gdwRequestID = 1;
}
LeaveCriticalSection (&gRequestIDCritSec);
*ppAsyncRequestWrapper = pAsyncRequestWrapper;
}
else
{
DrvFree (pAsyncRequestWrapper);
}
return lResult;
}
#if DBG
static char *pszOidNames[] =
{
"Accept",
"Answer",
"Close",
"CloseCall",
"ConditionalMediaDetection",
"ConfigDialog",
"DevSpecific",
"Dial",
"Drop",
"GetAddressCaps",
"GetAddressID",
"GetAddressStatus",
"GetCallAddressID",
"GetCallInfo",
"GetCallStatus",
"GetDevCaps",
"GetDevConfig",
"GetExtensionID",
"GetID",
"GetLineDevStatus",
"MakeCall",
"NegotiateExtVersion",
"Open",
"ProviderInitialize",
"ProviderShutdown",
"SecureCall",
"SelectExtVersion",
"SendUserUserInfo",
"SetAppSpecific",
"StCallParams",
"StDefaultMediaDetection",
"SetDevConfig",
"SetMediaMode",
"SetStatusMessages"
};
#endif
LONG
WINAPI
SyncDriverRequest(
DWORD dwIoControlCode,
PNDISTAPI_REQUEST pNdisTapiRequest
)
{
//
// This routine makes a non-overlapped request to NdisTapi.sys (so it
// doesn't return until the request is completed)
//
BOOL bResult;
DWORD cbReturned;
DBGOUT((
3,
"SyncDrvReq: Oid=%s, devID=%d, dataSize=%d, reqID=x%x, p1=x%x",
pszOidNames[pNdisTapiRequest->Oid - OID_TAPI_ACCEPT],
pNdisTapiRequest->ulDeviceID,
pNdisTapiRequest->ulDataSize,
*((ULONG *)pNdisTapiRequest->Data),
*(((ULONG *)pNdisTapiRequest->Data) + 1)
));
if (DeviceIoControl(
ghDriverSync,
dwIoControlCode,
pNdisTapiRequest,
(DWORD) (sizeof(NDISTAPI_REQUEST) + pNdisTapiRequest->ulDataSize),
pNdisTapiRequest,
(DWORD) (sizeof(NDISTAPI_REQUEST) + pNdisTapiRequest->ulDataSize),
&cbReturned,
0
) == FALSE)
{
}
//
// The errors returned by NdisTapi.sys don't match the TAPI LINEERR_'s,
// so return the translated value (but preserve the original driver
// return val so it's possible to distinguish between
// NDISTAPIERR_DEVICEOFFLINE & LINEERR_OPERATIONUNAVAIL, etc.)
//
return (TranslateDriverResult (pNdisTapiRequest->ulReturnValue));
}
LONG
WINAPI
AsyncDriverRequest(
DWORD dwIoControlCode,
PASYNC_REQUEST_WRAPPER pAsyncRequestWrapper
)
{
BOOL bResult;
LONG lResult;
DWORD dwRequestSize, cbReturned, dwLastError;
DBGOUT((
3,
"AsyncDrvReq: pReq=x%x, Oid=%s, devID=%d, dataSize=%d, reqID=x%x, ddReqID=x%x, p1=x%x",
pAsyncRequestWrapper,
pszOidNames
[pAsyncRequestWrapper->NdisTapiRequest.Oid - OID_TAPI_ACCEPT],
pAsyncRequestWrapper->NdisTapiRequest.ulDeviceID,
pAsyncRequestWrapper->NdisTapiRequest.ulDataSize,
pAsyncRequestWrapper->dwRequestID,
*((ULONG *)pAsyncRequestWrapper->NdisTapiRequest.Data),
*(((ULONG *)pAsyncRequestWrapper->NdisTapiRequest.Data) + 1)
));
lResult = (LONG) pAsyncRequestWrapper->dwRequestID;
dwRequestSize = sizeof(NDISTAPI_REQUEST) +
(pAsyncRequestWrapper->NdisTapiRequest.ulDataSize - 1);
bResult = DeviceIoControl(
ghDriverAsync,
dwIoControlCode,
&pAsyncRequestWrapper->NdisTapiRequest,
dwRequestSize,
&pAsyncRequestWrapper->NdisTapiRequest,
dwRequestSize,
&cbReturned,
&pAsyncRequestWrapper->Overlapped
);
dwLastError = GetLastError();
if ((bResult == FALSE) && (dwLastError == ERROR_IO_PENDING))
{
//
// Request is pending, just return (async events thread will
// take care of it when it completes)
//
}
else if (bResult == TRUE)
{
//
// Request completed synchronously, so call the completion proc
// & clean up
//
(*gpfnCompletionProc)(
pAsyncRequestWrapper->dwRequestID,
TranslateDriverResult(
pAsyncRequestWrapper->NdisTapiRequest.ulReturnValue
)
);
DrvFree (pAsyncRequestWrapper);
}
else
{
//
// Error
//
DBGOUT((1, "AsyncDrvReq: DevIoCtl failed, err=%d", dwLastError));
}
return lResult;
}
BOOL
WINAPI
ConvertLineAndCallHandles(
HTAPI_LINE *pht_Line,
HTAPI_CALL *pht_Call
)
{
PDRVCALL pCall;
PDRVLINE pLine = (PDRVLINE) *pht_Line;
//
// Check to see that pLine is 64-bit aligned & has a good key
//
{
BOOL bBadLine;
try
{
if (!((DWORD) pLine & 0x7) && pLine->dwKey == LINE_KEY)
{
*pht_Line = (HTAPI_LINE) pLine->htLine;
bBadLine = FALSE;
}
else
{
bBadLine = TRUE;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
bBadLine = TRUE;
}
if (bBadLine)
{
return FALSE;
}
}
//
// Incoming calls will have a pCall with the high bit set (a value
// created by ndistapi), while outgoing calls won't have the high
// bit set (since they're real ptrs in app space [the low 2 gig])
//
pCall = (PDRVCALL) *pht_Call;
if ((DWORD) pCall < 0x80000000)
{
BOOL bResult;
try
{
//
// Check that pCall is 64-bit aligned & has a good key
//
if (!((DWORD) pCall & 0x7) &&
pCall->dwKey == OUTBOUND_CALL_KEY)
{
*pht_Call = (HTAPI_CALL) pCall->htCall;
bResult = TRUE;
}
else
{
bResult = FALSE;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
bResult = FALSE;
}
return bResult;
}
//
// If here it's an inbound call, so we need to walk the list
// of inbound pCalls on this line & find the right one
//
{
BOOL bInCriticalSection;
try
{
HTAPI_CALL ht_Call;
EnterCriticalSection (&gInboundCallsCritSec);
bInCriticalSection = TRUE;
if ((pCall = pLine->pInboundCalls))
{
ht_Call = *pht_Call;
while (pCall && (pCall->ht_Call != ht_Call))
{
pCall = pCall->pNext;
}
}
LeaveCriticalSection (&gInboundCallsCritSec);
bInCriticalSection = FALSE;
*pht_Call = (pCall ? (HTAPI_CALL)pCall->htCall : (HTAPI_CALL)NULL);
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
if (bInCriticalSection)
{
LeaveCriticalSection (&gInboundCallsCritSec);
}
pCall = NULL;
}
}
return (pCall ? TRUE : FALSE);
}
BOOL
WINAPI
ConvertLineHandle(
HTAPI_LINE *pht_Line
)
{
PDRVLINE pLine = (PDRVLINE) *pht_Line;
//
// Check to see that pLine is 64-bit aligned & has a good key
//
try
{
if (!((DWORD) pLine & 0x7) && pLine->dwKey == LINE_KEY)
{
*pht_Line = (HTAPI_LINE) pLine->htLine;
return TRUE;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
// just fall thru
}
DBGOUT((4, "ConvertLineHandle: bad htLine=x%x", *pht_Line));
return FALSE;
}
LPVOID
WINAPI
DrvAlloc(
DWORD dwSize
)
{
LPBYTE p;
LPDWORD pAligned;
//
// Alloc 16 extra bytes so we can make sure the pointer we pass back
// is 64-bit aligned & have space to store the original pointer
//
if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
{
pAligned = (LPDWORD) (p + 8 - (((DWORD) p) & 0x7));
*pAligned = (DWORD) p;
pAligned++;
pAligned++;
}
else
{
// send reinit msg?
DBGOUT((
1,
"ServerAlloc: LocalAlloc (x%lx) failed, err=x%lx",
dwSize,
GetLastError())
);
pAligned = NULL;
}
return ((LPVOID) pAligned);
}
VOID
WINAPI
DrvFree(
LPVOID p
)
{
LPVOID pOrig = (LPVOID) *(((LPDWORD) p) - 2);
LocalFree (pOrig);
}
VOID
WINAPI
ProcessEvent(
PNDIS_TAPI_EVENT pEvent
)
{
ULONG ulMsg = pEvent->ulMsg;
HTAPI_LINE ht_Line = (HTAPI_LINE) pEvent->htLine;
DBGOUT((
4,
"ProcessEvent: enter, msg=x%x, pLine=x%x, ht_call=x%x",
ulMsg,
ht_Line,
pEvent->htCall
));
DBGOUT((
4,
"ProcessEvent: \tp1=x%x, p2=x%x, p3=x%x",
pEvent->ulParam1,
pEvent->ulParam2,
pEvent->ulParam3
));
switch (ulMsg)
{
case LINE_ADDRESSSTATE:
case LINE_CLOSE:
case LINE_DEVSPECIFIC:
case LINE_LINEDEVSTATE:
if (ConvertLineHandle (&ht_Line))
{
(*gpfnLineEvent)(
(HTAPILINE) ht_Line,
(HTAPICALL) NULL,
(DWORD) ulMsg,
(DWORD) pEvent->ulParam1,
(DWORD) pEvent->ulParam2,
(DWORD) pEvent->ulParam3
);
}
break;
case LINE_CALLDEVSPECIFIC:
case LINE_CALLINFO:
if (ConvertLineAndCallHandles (&ht_Line, &pEvent->htCall))
{
(*gpfnLineEvent)(
(HTAPILINE) ht_Line,
(HTAPICALL) pEvent->htCall,
(DWORD) ulMsg,
(DWORD) pEvent->ulParam1,
(DWORD) pEvent->ulParam2,
(DWORD) pEvent->ulParam3
);
}
break;
case LINE_CALLSTATE:
{
//
// For outgoing calls there exists a race condition between
// receiving the first call state msg(s) and receiving the
// make call completion notification (if we pass a call state
// msg on to tapi for a call that hasn't been completed yet
// tapi will just discard the msg since the htCall really
// isn't valid at that point). So if htCall references a
// valid outgoing call which hasn't completed yet, we'll save
// the call state params, and pass them on to tapi after we
// get & indicate a (successful) completion notification.
//
// (Note: incoming calls have high bit turned off)
//
PDRVCALL pCall = (PDRVCALL) pEvent->htCall;
if ((DWORD) pCall < 0x80000000 && !((DWORD) pCall & 0x7))
{
try
{
if (pCall->dwKey == OUTBOUND_CALL_KEY &&
pCall->bIncomplete == TRUE)
{
pCall->dwPendingCallState = pEvent->ulParam1;
pCall->dwPendingCallStateMode = pEvent->ulParam2;
pCall->dwPendingMediaMode = pEvent->ulParam3;
break;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
break;
}
}
if (ConvertLineAndCallHandles (&ht_Line, &pEvent->htCall))
{
(*gpfnLineEvent)(
(HTAPILINE) ht_Line,
(HTAPICALL) pEvent->htCall,
(DWORD) ulMsg,
(DWORD) pEvent->ulParam1,
(DWORD) pEvent->ulParam2,
(DWORD) pEvent->ulParam3
);
//
// For old style miniports we want to indicate an IDLE
// immediately following the disconnected (several of
// the initial NDIS WAN miniports did not indicate an
// IDLE call state due to doc confusion)
//
// BUGBUG make sure we don't do this for new style
// drivers (new style == anything that supports
// OID_TAPI_NEGOTIATE_API_VERSION)
//
if (pEvent->ulParam1 == LINECALLSTATE_DISCONNECTED)
{
(*gpfnLineEvent)(
(HTAPILINE) ht_Line,
(HTAPICALL) pEvent->htCall,
(DWORD) ulMsg,
(DWORD) LINECALLSTATE_IDLE,
(DWORD) 0,
(DWORD) pEvent->ulParam3
);
}
}
break;
}
case LINE_NEWCALL:
{
BOOL bInCriticalSection = FALSE;
PDRVCALL pCall;
PDRVLINE pLine = (PDRVLINE) ht_Line;
if (!(pCall = DrvAlloc (sizeof(DRVCALL))))
{
// BUGBUG LINE_NEWCALL: couldn't alloc drvCall, send drop/dealloc call OIDs
break;
}
pCall->dwKey = INBOUND_CALL_KEY;
pCall->ht_Call = (HTAPI_CALL) pEvent->ulParam2;
pCall->hd_Call = (HDRV_CALL) pEvent->ulParam1;
pCall->pLine = pLine;
//pCall->bIncomplete = FALSE; (already 0'd by alloc)
try
{
pCall->dwDeviceID = pLine->dwDeviceID;
EnterCriticalSection (&gInboundCallsCritSec);
bInCriticalSection = TRUE;
if (pLine->dwKey == LINE_KEY)
{
//
// Insert new call into inbound calls list
//
if ((pCall->pNext = pLine->pInboundCalls))
{
pCall->pNext->pPrev = pCall;
}
pLine->pInboundCalls = pCall;
}
else
{
//
// Line was closed after this msg was sent, so clean up
//
DrvFree (pCall);
pCall = NULL;
}
LeaveCriticalSection (&gInboundCallsCritSec);
bInCriticalSection = FALSE;
if (pCall)
{
(*gpfnLineEvent)(
(HTAPILINE) pLine->htLine,
(HTAPICALL) NULL,
ulMsg,
(DWORD) pCall,
(DWORD) &pCall->htCall,
0
);
}
}
except (EXCEPTION_EXECUTE_HANDLER)
// we expect some AVs and alignment faults
{
if (bInCriticalSection)
{
LeaveCriticalSection (&gInboundCallsCritSec);
}
DrvFree (pCall);
}
// BUGBUG check if pCall->htCall is NULL (tapi couldn't deal w/ newcall)
break;
}
default:
DBGOUT((2, "ProcessEvent: unknown msg, x%x", ulMsg));
break;
} // switch
}
LONG
WINAPI
TranslateDriverResult(
ULONG ulResult
)
{
typedef struct _RESULT_LOOKUP
{
ULONG NdisTapiResult;
LONG TapiResult;
} RESULT_LOOKUP, *PRESULT_LOOKUP;
#ifdef MYHACK
typedef ULONG NDIS_STATUS;
#define NDIS_STATUS_SUCCESS 0x00000000L
#define NDIS_STATUS_RESOURCES 0xC000009AL
#define NDIS_STATUS_FAILURE 0xC0000001L
#endif
static RESULT_LOOKUP aResults[] =
{
//
// Defined in NDIS.H
//
{ NDIS_STATUS_SUCCESS ,0 },
//
// These errors are defined in NDISTAPI.H
//
{ NDIS_STATUS_TAPI_ADDRESSBLOCKED ,LINEERR_ADDRESSBLOCKED },
{ NDIS_STATUS_TAPI_BEARERMODEUNAVAIL ,LINEERR_BEARERMODEUNAVAIL },
{ NDIS_STATUS_TAPI_CALLUNAVAIL ,LINEERR_CALLUNAVAIL },
{ NDIS_STATUS_TAPI_DIALBILLING ,LINEERR_DIALBILLING },
{ NDIS_STATUS_TAPI_DIALDIALTONE ,LINEERR_DIALDIALTONE },
{ NDIS_STATUS_TAPI_DIALPROMPT ,LINEERR_DIALPROMPT },
{ NDIS_STATUS_TAPI_DIALQUIET ,LINEERR_DIALQUIET },
{ NDIS_STATUS_TAPI_INCOMPATIBLEEXTVERSION,LINEERR_INCOMPATIBLEEXTVERSION},
{ NDIS_STATUS_TAPI_INUSE ,LINEERR_INUSE },
{ NDIS_STATUS_TAPI_INVALADDRESS ,LINEERR_INVALADDRESS },
{ NDIS_STATUS_TAPI_INVALADDRESSID ,LINEERR_INVALADDRESSID },
{ NDIS_STATUS_TAPI_INVALADDRESSMODE ,LINEERR_INVALADDRESSMODE },
{ NDIS_STATUS_TAPI_INVALBEARERMODE ,LINEERR_INVALBEARERMODE },
{ NDIS_STATUS_TAPI_INVALCALLHANDLE ,LINEERR_INVALCALLHANDLE },
{ NDIS_STATUS_TAPI_INVALCALLPARAMS ,LINEERR_INVALCALLPARAMS },
{ NDIS_STATUS_TAPI_INVALCALLSTATE ,LINEERR_INVALCALLSTATE },
{ NDIS_STATUS_TAPI_INVALDEVICECLASS ,LINEERR_INVALDEVICECLASS },
{ NDIS_STATUS_TAPI_INVALLINEHANDLE ,LINEERR_INVALLINEHANDLE },
{ NDIS_STATUS_TAPI_INVALLINESTATE ,LINEERR_INVALLINESTATE },
{ NDIS_STATUS_TAPI_INVALMEDIAMODE ,LINEERR_INVALMEDIAMODE },
{ NDIS_STATUS_TAPI_INVALRATE ,LINEERR_INVALRATE },
{ NDIS_STATUS_TAPI_NODRIVER ,LINEERR_NODRIVER },
{ NDIS_STATUS_TAPI_OPERATIONUNAVAIL ,LINEERR_OPERATIONUNAVAIL },
{ NDIS_STATUS_TAPI_RATEUNAVAIL ,LINEERR_RATEUNAVAIL },
{ NDIS_STATUS_TAPI_RESOURCEUNAVAIL ,LINEERR_RESOURCEUNAVAIL },
{ NDIS_STATUS_TAPI_STRUCTURETOOSMALL ,LINEERR_STRUCTURETOOSMALL },
{ NDIS_STATUS_TAPI_USERUSERINFOTOOBIG ,LINEERR_USERUSERINFOTOOBIG },
{ NDIS_STATUS_TAPI_ALLOCATED ,LINEERR_ALLOCATED },
{ NDIS_STATUS_TAPI_INVALADDRESSSTATE ,LINEERR_INVALADDRESSSTATE },
{ NDIS_STATUS_TAPI_INVALPARAM ,LINEERR_INVALPARAM },
{ NDIS_STATUS_TAPI_NODEVICE ,LINEERR_NODEVICE },
//
// These errors are defined in NDIS.H
//
{ NDIS_STATUS_RESOURCES ,LINEERR_NOMEM },
{ NDIS_STATUS_FAILURE ,LINEERR_OPERATIONFAILED },
//
//
//
{ NDISTAPIERR_UNINITIALIZED ,LINEERR_OPERATIONFAILED },
{ NDISTAPIERR_BADDEVICEID ,LINEERR_OPERATIONFAILED },
{ NDISTAPIERR_DEVICEOFFLINE ,LINEERR_OPERATIONFAILED },
//
// The terminating fields
//
{ 0xffffffff, 0xffffffff }
};
int i;
for (i = 0; aResults[i].NdisTapiResult != 0xffffffff; i++)
{
if (ulResult == aResults[i].NdisTapiResult)
{
return (aResults[i].TapiResult);
}
}
DBGOUT((1, "TranslateDriverResult: unknown driver result x%x", ulResult));
return LINEERR_OPERATIONFAILED;
}
#if DBG
VOID
DbgPrt(
IN DWORD dwDbgLevel,
IN PUCHAR lpszFormat,
IN ...
)
/*++
Routine Description:
Formats the incoming debug message & callsOutputDebugStringA
Arguments:
DbgLevel - level of message verboseness
DbgMessage - printf-style format string, followed by appropriate
list of arguments
Return Value:
--*/
{
if (dwDbgLevel <= gdwDebugLevel)
{
int iNumChars;
char buf[192] = "KMDDSP: ";
va_list ap;
va_start(ap, lpszFormat);
iNumChars = wvsprintfA (&buf[8], lpszFormat, ap);
buf[iNumChars] = '\n';
buf[iNumChars + 1] = 0;
OutputDebugStringA (buf);
va_end(ap);
}
}
#endif