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.
 
 
 
 
 
 

7677 lines
161 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
remotesp.c
Abstract:
This module contains
Author:
Dan Knudson (DanKn) 09-Aug-1995
Revision History:
Notes:
In a nutshell, this service provider connects to tapisrv.exe on remote
pc's via the same rpc interface used by tapi32, and sends the remote
tapisrv's the same kinds of requests (as defined in \dev\server\line.h
& phone.h).
This service provider also acts as an rpc server, receiving async event
notifications from the remote tapisrv's. Remote tapisrv's call our
RemoteSPAttach() function at init time (during our call to their
ClientAttach() proc) to establish a binding instance, and then can call
RemoteSPEventProc() to send async events. Since we don't want to block
the servers for any length of time, we immediately queue the events they
send us, and a dedicated thread (EventHandlerThread) services this
queue.
Now a brief note on handle resolution. When we open a line or a phone,
we alloc our own DRVXXX structure to represent this widget, and pass
tapisrv a pointer to this widget in the open request (see the
hRemoteLine field in LINEOPEN_PARAMS in line.h). Then, when remote
tapisrv's send us events on those lines/phones, they pass us the
widget pointer we passed them (instead of the normal hLine/hPhone).
This allows us to easily find and reference our data structure
associated with this widget. Dealing with calls is a little more
problematic, since remote tapisrv's can present incoming calls, and
there is no clean way to initially specify our own handle to the call
as with lines or phones. (A RemoteSPNewCall() function which would
allow for this handle swapping was considered, but not implemented due
to possible blocking problems on the remote server.) The solution
is to maintain a list of calls in each line structure, and when call
events are parsed we resolve the hCall by walking the list of calls in
the corresponding line (tapisrv is nice enough to indicate our line
pointer in dwParam4 of the relevant messages). Since we expect client
machines using remotesp to have a relatively low call bandwidth, this
look up method should be pretty fast.
BUGBUG when an rpc exception is hit we may want to check the return
value instead of just blindly doing retries (may be a fatal error
that a retry wouldn't help, like server_not_found)
--*/
#include "remotesp.h"
#include "rmotsp.h"
const TCHAR gszTelephonyKey[] =
"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
BOOL
WINAPI
DllMain(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
#if DBG
{
HKEY hTelephonyKey;
DWORD dwDataSize, dwDataType;
TCHAR szRemotespDebugLevel[] = "RemotespDebugLevel";
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_ALL_ACCESS,
&hTelephonyKey
);
dwDataSize = sizeof (DWORD);
gdwDebugLevel=0;
RegQueryValueEx(
hTelephonyKey,
szRemotespDebugLevel,
0,
&dwDataType,
(LPBYTE) &gdwDebugLevel,
&dwDataSize
);
RegCloseKey (hTelephonyKey);
}
#endif
//
//
//
// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
// {
// }
DBGOUT((2, "DLL_PROCESS_ATTACH"));
ghInst = hDLL;
//
// Alloc a Tls index
//
if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
{
DBGOUT((1, "DLL_PROCESS_ATTACH, TlsAlloc() failed"));
return FALSE;
}
//
// Initialize Tls to NULL for this thread
//
TlsSetValue (gdwTlsIndex, NULL);
//
// Init a couple of critical sections for serializing
// access to resources
//
InitializeCriticalSection (&gEventBufferCriticalSection);
InitializeCriticalSection (&gCallListCriticalSection);
//
// Load the device icons
//
ghLineIcon = LoadIcon (hDLL, MAKEINTRESOURCE(IDI_ICON3));
ghPhoneIcon = LoadIcon (hDLL, MAKEINTRESOURCE(IDI_ICON2));
break;
}
case DLL_PROCESS_DETACH:
{
PCLIENT_THREAD_INFO pTls;
DBGOUT((2, "DLL_PROCESS_DETACH"));
//
// Clean up any Tls
//
if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
{
if (pTls->pBuf)
{
DrvFree (pTls->pBuf);
}
DrvFree (pTls);
}
TlsFree (gdwTlsIndex);
// _CRT_INIT (hDLL, dwReason, lpReserved);
//
// Free the critical sections & icons
//
DeleteCriticalSection (&gEventBufferCriticalSection);
DeleteCriticalSection (&gCallListCriticalSection);
DestroyIcon (ghLineIcon);
DestroyIcon (ghPhoneIcon);
break;
}
case DLL_THREAD_ATTACH:
// if (!_CRT_INIT (hDLL, dwReason, lpReserved))
// {
// }
//
// Initialize Tls to NULL for this thread
//
TlsSetValue (gdwTlsIndex, NULL);
break;
case DLL_THREAD_DETACH:
{
PCLIENT_THREAD_INFO pTls;
//
// Clean up any Tls
//
if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
{
if (pTls->pBuf)
{
DrvFree (pTls->pBuf);
}
DrvFree (pTls);
}
// _CRT_INIT (hDLL, dwReason, lpReserved);
break;
}
} // switch
return TRUE;
}
PASYNCEVENTMSG
GetEventFromQueue(
void
)
{
DWORD dwUsedSize, dwMoveSize, dwMoveSizeWrapped;
PASYNCEVENTMSG pMsg = gEventHandlerThreadParams.pMsg;
//
// Enter the critical section to serialize access to the event
// queue, and grab an event from the queue. Copy it to our local
// event buf so that we can leave the critical section asap and
// not block other threads writing to the queue.
//
EnterCriticalSection (&gEventBufferCriticalSection);
//
// If there are no events in the queue return NULL
//
if (gEventHandlerThreadParams.dwEventBufferUsedSize == 0)
{
pMsg = NULL;
goto GetEventFromQueue_done;
}
//
// Copy the fixed portion of the msg to the local buf
//
dwUsedSize = (gEventHandlerThreadParams.pEventBuffer +
gEventHandlerThreadParams.dwEventBufferTotalSize) -
gEventHandlerThreadParams.pDataOut;
if (dwUsedSize >= sizeof (ASYNCEVENTMSG))
{
dwMoveSize = sizeof (ASYNCEVENTMSG);
dwMoveSizeWrapped = 0;
}
else
{
dwMoveSize = dwUsedSize;
dwMoveSizeWrapped = sizeof (ASYNCEVENTMSG) - dwUsedSize;
}
CopyMemory (pMsg, gEventHandlerThreadParams.pDataOut, dwMoveSize);
if (dwMoveSizeWrapped)
{
CopyMemory(
((LPBYTE) pMsg) + dwMoveSize,
gEventHandlerThreadParams.pEventBuffer,
dwMoveSizeWrapped
);
gEventHandlerThreadParams.pDataOut =
gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
}
else
{
gEventHandlerThreadParams.pDataOut += dwMoveSize;
}
//
// See if there's any extra data in this msg
//
if (pMsg->dwTotalSize > sizeof (ASYNCEVENTMSG))
{
BOOL bCopy = TRUE;
//
// See if we need to grow the msg buffer
//
if (pMsg->dwTotalSize > gEventHandlerThreadParams.dwMsgSize)
{
DWORD dwNewMsgSize = pMsg->dwTotalSize + 256;
if ((pMsg = DrvAlloc (dwNewMsgSize)))
{
CopyMemory(
pMsg,
gEventHandlerThreadParams.pMsg,
sizeof(ASYNCEVENTMSG)
);
DrvFree (gEventHandlerThreadParams.pMsg);
gEventHandlerThreadParams.pMsg = pMsg;
gEventHandlerThreadParams.dwMsgSize = dwNewMsgSize;
}
else
{
//
// Couldn't alloc a bigger buf, so try to complete this
// msg as gracefully as possible
//
bCopy = FALSE;
switch (pMsg->dwMsg)
{
case LINE_REPLY:
pMsg->dwParam2 = LINEERR_NOMEM;
break;
case PHONE_REPLY:
pMsg->dwParam2 = PHONEERR_NOMEM;
break;
default: // BUGBUG any other msgs to special case?
break;
}
}
}
dwUsedSize = (gEventHandlerThreadParams.pEventBuffer +
gEventHandlerThreadParams.dwEventBufferTotalSize) -
gEventHandlerThreadParams.pDataOut;
if (dwUsedSize >= (pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG)))
{
dwMoveSize = pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG);
dwMoveSizeWrapped = 0;
}
else
{
dwMoveSize = dwUsedSize;
dwMoveSizeWrapped = (pMsg->dwTotalSize - sizeof (ASYNCEVENTMSG)) -
dwUsedSize;
}
if (bCopy)
{
CopyMemory(
pMsg + 1,
gEventHandlerThreadParams.pDataOut,
dwMoveSize
);
}
if (dwMoveSizeWrapped)
{
if (bCopy)
{
CopyMemory(
((LPBYTE) (pMsg + 1)) + dwMoveSize,
gEventHandlerThreadParams.pEventBuffer,
dwMoveSizeWrapped
);
}
gEventHandlerThreadParams.pDataOut =
gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
}
else
{
gEventHandlerThreadParams.pDataOut += dwMoveSize;
}
}
gEventHandlerThreadParams.dwEventBufferUsedSize -= pMsg->dwTotalSize;
GetEventFromQueue_done:
LeaveCriticalSection (&gEventBufferCriticalSection);
ResetEvent (gEventHandlerThreadParams.hEvent);
return pMsg;
}
void
EventHandlerThread(
LPVOID pParams
)
{
//
// NOTES:
//
// 1. depending on server side implementation, we may experience race
// conditions where msgs that we expect to show up in a certain
// sequence show up out of sequence (i.e. call state msgs that show
// up before make call completion msgs), which could present problems.
//
// one solution is to to queue call state/info msgs to incomplete
// calls (to be sent after call is completed). another is not to send
// any call state msgs after the idle is received
//
PASYNCEVENTMSG pMsg;
DBGOUT((3, "EventHandlerThread: enter"));
while (1)
{
//
// Wait for an event to show up in the queue
//
WaitForSingleObject (gEventHandlerThreadParams.hEvent, INFINITE);
if (gEventHandlerThreadParams.bExit)
{
break;
}
//
// Process the events in the queue
//
while ((pMsg = GetEventFromQueue()))
{
switch (pMsg->dwMsg)
{
case LINE_ADDRESSSTATE:
//assert (((PDRVLINE)(pMsg->hDevice))->dwKey == DRVLINE_KEY);
(*gpfnLineEventProc)(
((PDRVLINE)(pMsg->hDevice))->htLine,
NULL,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
case LINE_CALLINFO:
case LINE_CALLSTATE:
case LINE_GENERATE:
case LINE_MONITORDIGITS:
case LINE_MONITORMEDIA:
case LINE_MONITORTONE:
{
//
// For all the msgs where hDevice refers to a call tapisrv
// will pass us the pLine (hRemoteLine) for that call in
// dwParam4 to make the lookup of the corresponding pCall
// easier
//
HCALL hCall = (HCALL) pMsg->hDevice;
PDRVCALL pCall;
PDRVLINE pLine = (PDRVLINE) pMsg->dwParam4;
HTAPICALL htCall;
//assert (pLine->dwKey == DRVLINE_KEY);
EnterCriticalSection (&gCallListCriticalSection);
pCall = (PDRVCALL) pLine->pCalls;
while (pCall && (pCall->hCall != hCall))
{
pCall = pCall->pNext;
}
htCall = (pCall ? pCall->htCall : NULL);
LeaveCriticalSection (&gCallListCriticalSection);
if (!pCall)
{
continue;
}
(*gpfnLineEventProc)(
pLine->htLine,
htCall,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
}
case LINE_DEVSPECIFIC:
case LINE_DEVSPECIFICFEATURE:
{
//
// For all the msgs where hDevice refers to a call tapisrv
// will pass us the pLine (hRemoteLine) for that call in
// dwParam4 to make the lookup of the corresponding pCall
// easier
//
HTAPICALL htCall;
PDRVLINE pLine;
if (pMsg->dwParam4)
{
HCALL hCall = (HCALL) pMsg->hDevice;
PDRVCALL pCall;
pLine = (PDRVLINE) pMsg->dwParam4;
//assert (pLine->dwKey == DRVLINE_KEY);
EnterCriticalSection (&gCallListCriticalSection);
pCall = (PDRVCALL) pLine->pCalls;
while (pCall && (pCall->hCall != hCall))
{
pCall = pCall->pNext;
}
htCall = (pCall ? pCall->htCall : NULL);
LeaveCriticalSection (&gCallListCriticalSection);
if (pCall)
{
pMsg->dwMsg = (pMsg->dwMsg == LINE_DEVSPECIFIC ?
LINE_CALLDEVSPECIFIC :
LINE_CALLDEVSPECIFICFEATURE);
}
else
{
continue;
}
}
else
{
pLine = (PDRVLINE) pMsg->hDevice;
//assert (pLine->dwKey == DRVLINE_KEY);
htCall = NULL;
}
(*gpfnLineEventProc)(
pLine->htLine,
htCall,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
}
case PHONE_BUTTON:
case PHONE_DEVSPECIFIC:
//assert (((PDRVPHONE)(pMsg->hDevice))->dwKey == DRVPHONE_KEY);
(*gpfnPhoneEventProc)(
((PDRVPHONE)(pMsg->hDevice))->htPhone,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
case LINE_LINEDEVSTATE:
if (pMsg->dwParam1 & LINEDEVSTATE_REINIT)
{
//
// Be on our best behavior and immediately shutdown
// our init instances on the server
//
Shutdown ((PDRVSERVER) pMsg->pInitData);
}
//assert (((PDRVLINE)(pMsg->hDevice))->dwKey == DRVLINE_KEY);
(*gpfnLineEventProc)(
((PDRVLINE)(pMsg->hDevice))->htLine,
NULL,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
case PHONE_STATE:
if (pMsg->dwParam1 & PHONESTATE_REINIT)
{
//
// Be on our best behavior and immediately shutdown
// our init instances on the server
//
Shutdown ((PDRVSERVER) pMsg->pInitData);
}
//assert (((PDRVPHONE)(pMsg->hDevice))->dwKey == DRVPHONE_KEY);
(*gpfnPhoneEventProc)(
((PDRVPHONE)(pMsg->hDevice))->htPhone,
pMsg->dwMsg,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
);
break;
case LINE_CLOSE:
{
PDRVCALL pCall;
PDRVLINE pLine = (PDRVLINE) pMsg->hDevice;
//assert (pLine->dwKey == DRVLINE_KEY);
//
// Nullify the hLine field so that when TSPI_Close
// is called we know not to call the server
//
pLine->hLine = NULL;
//
// Safely walk the call list for this line & nullify
// each call's hCall field so that when TSPI_CloseCall
// is called we know not to call the server
//
EnterCriticalSection (&gCallListCriticalSection);
pCall = pLine->pCalls;
while (pCall)
{
pCall->hCall = NULL;
pCall = pCall->pNext;
}
LeaveCriticalSection (&gCallListCriticalSection);
(*gpfnLineEventProc)(pLine->htLine, NULL, LINE_CLOSE, 0, 0, 0);
break;
}
case PHONE_CLOSE:
{
PDRVPHONE pPhone = (PDRVPHONE) pMsg->hDevice;
//assert (pPhone->dwKey == DRVPHONE_KEY);
//
// Nullify the hPhone field so that when TSPI_Close
// is called we know not to call the server
//
pPhone->hPhone = NULL;
(*gpfnPhoneEventProc)(pPhone->htPhone, PHONE_CLOSE, 0, 0, 0);
break;
}
case LINE_GATHERDIGITS: // BUGBUG
break;
case LINE_REPLY:
case PHONE_REPLY:
{
if (pMsg->pfnPostProcessProc)
{
(*((POSTPROCESSPROC)(pMsg->pfnPostProcessProc)))(pMsg);
}
(*gpfnCompletionProc)(pMsg->dwParam1, pMsg->dwParam2);
break;
}
case LINE_CREATE:
// BUGBUG AddLine((PDRVSERVER) pMsg->pInitData, locDevID, srvDevID, FALSE);
// (*gpfnLineCreateProc)()
break;
case PHONE_CREATE:
// BUGBUG AddPhone((PDRVSERVER) pMsg->pInitData, locDevID, srvDevID, FALSE);
// (*gpfnPhoneCreateProc)()
break;
case LINE_APPNEWCALL:
{
PDRVLINE pLine = (PDRVLINE) pMsg->hDevice;
PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
if (pCall)
{
AddCallToList (pLine, pCall);
pCall->hCall = (HCALL) pMsg->dwParam2;
pCall->dwAddressID = pMsg->dwParam1;
(*gpfnLineEventProc)(
pLine->htLine,
NULL,
LINE_NEWCALL,
(DWORD) pCall,
(DWORD) (&pCall->htCall),
(DWORD) 0
);
}
else
{
// BUGBUG LINE_APPNEWCALL: err case (pCall == NULL)
}
break;
}
} // switch (pMsg->dwMsg)
} // while ((pMsg = GetEventFromQueue()))
} // while (1)
DBGOUT((3, "EventHandlerThread: exit"));
ExitThread (0);
}
PDRVLINE
GetLineFromID(
DWORD dwDeviceID
)
{
PDRVLINE pLine;
//
// First check to see if it's a "static" device, i.e. a device
// that we knew about at start up time, in which case we know
// it's exact location in the lookup table
//
if (dwDeviceID < (gdwLineDeviceIDBase + gdwInitialNumLineDevices))
{
pLine = gpLineLookup->aEntries + dwDeviceID - gdwLineDeviceIDBase;
}
//
// If here, the id references a "dynamic" device, i.e. one that
// we found out about on the fly via a CREATE msg, so we need to
// walk the lookup table(s) to find it
//
// TODO: the for loop down below is not the most efficient
//
else
{
PDRVLINELOOKUP pLookup = gpLineLookup;
while (pLookup->aEntries[pLookup->dwUsedEntries - 1].
dwDeviceIDLocal < dwDeviceID)
{
pLookup = pLookup->pNext;
}
for(
pLine = pLookup->aEntries;
pLine->dwDeviceIDLocal != dwDeviceID;
pLine++
);
}
return pLine;
}
PDRVPHONE
GetPhoneFromID(
DWORD dwDeviceID
)
{
PDRVPHONE pPhone;
//
// First check to see if it's a "static" device, i.e. a device
// that we knew about at start up time, in which case we know
// it's exact location in the lookup table
//
if (dwDeviceID < (gdwPhoneDeviceIDBase + gdwInitialNumPhoneDevices))
{
pPhone = gpPhoneLookup->aEntries + dwDeviceID - gdwPhoneDeviceIDBase;
}
//
// If here, the id references a "dynamic" device, i.e. one that
// we found out about on the fly via a CREATE msg, so we need to
// walk the lookup table(s) to find it
//
// TODO: the for loop down below is not the most efficient
//
else
{
PDRVPHONELOOKUP pLookup = gpPhoneLookup;
while (pLookup->aEntries[pLookup->dwUsedEntries - 1].
dwDeviceIDLocal < dwDeviceID)
{
pLookup = pLookup->pNext;
}
for(
pPhone = pLookup->aEntries;
pPhone->dwDeviceIDLocal != dwDeviceID;
pPhone++
);
}
return pPhone;
}
BOOL
WINAPI
GrowBuf(
LPBYTE *ppBuf,
LPDWORD pdwBufSize,
DWORD dwCurrValidBytes,
DWORD dwBytesToAdd
)
{
DWORD dwNewBufSize = *pdwBufSize * 2;
LPBYTE pNewBuf;
//
// Try to get a new buffer big enough to hold
// (dwCurrValidBytes + dwBytesToAdd)
//
while (dwNewBufSize < (dwCurrValidBytes + dwBytesToAdd))
{
dwNewBufSize *= 2;
}
if (!(pNewBuf = DrvAlloc (dwNewBufSize)))
{
return FALSE;
}
//
// Copy the "valid" bytes in the old buf to the new buf,
// then free the old buf
//
CopyMemory (pNewBuf, *ppBuf, dwCurrValidBytes);
DrvFree (*ppBuf);
//
// Reset the pointers to the new buf & buf size
//
*ppBuf = pNewBuf;
*pdwBufSize = dwNewBufSize;
return TRUE;
}
PCLIENT_THREAD_INFO
WINAPI
GetTls(
void
)
{
PCLIENT_THREAD_INFO pClientThreadInfo;
if (!(pClientThreadInfo = TlsGetValue (gdwTlsIndex)))
{
pClientThreadInfo = (PCLIENT_THREAD_INFO)
DrvAlloc (sizeof(CLIENT_THREAD_INFO));
if (!pClientThreadInfo)
{
return NULL;
}
pClientThreadInfo->pBuf = DrvAlloc (INITIAL_CLIENT_THREAD_BUF_SIZE);
if (!pClientThreadInfo->pBuf)
{
DrvFree (pClientThreadInfo);
return NULL;
}
pClientThreadInfo->dwBufSize = INITIAL_CLIENT_THREAD_BUF_SIZE;
TlsSetValue (gdwTlsIndex, (LPVOID) pClientThreadInfo);
}
return pClientThreadInfo;
}
#if DBG
LONG
WINAPI
RemoteDoFunc(
PREMOTE_FUNC_ARGS pFuncArgs,
char *pszFuncName
)
#else
LONG
WINAPI
RemoteDoFunc(
PREMOTE_FUNC_ARGS pFuncArgs
)
#endif
{
DWORD dwFuncClassErrorIndex = (pFuncArgs->Flags & 0x00000030) >> 4;
LONG lResult;
BOOL bCopyOnSuccess = FALSE;
DWORD i, j, dwValue, dwUsedSize, dwNeededSize;
PDRVSERVER pServer;
PCLIENT_THREAD_INFO pTls;
//
// Get the tls
//
if (!(pTls = GetTls()))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
//
// Validate all the func args
//
dwNeededSize = dwUsedSize = sizeof (TAPI32_MSG);
for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
{
dwValue = ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pFuncArgs->Args[i];
switch (pFuncArgs->ArgTypes[i])
{
case Dword:
//
// Nothing to check, just continue
//
continue;
case LineID:
{
PDRVLINE pLine = GetLineFromID (dwValue);
pServer = pLine->pServer;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = pLine->dwDeviceIDServer;
continue;
}
case PhoneID:
{
PDRVPHONE pPhone = GetPhoneFromID (dwValue);
pServer = pPhone->pServer;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = pPhone->dwDeviceIDServer;
continue;
}
case Hdcall:
//
// Save the pServer & adjust the call handle as understood by
// the server
//
pServer = ((PDRVCALL) dwValue)->pServer;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
((PDRVCALL) dwValue)->hCall;
continue;
case Hdline:
//
// Save the pServer & adjust the line handle as understood by
// the server
//
pServer = ((PDRVLINE) dwValue)->pServer;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
((PDRVLINE) dwValue)->hLine;
continue;
case Hdphone:
//
// Save the pServer & adjust the phone handle as understood by
// the server
//
pServer = ((PDRVPHONE) dwValue)->pServer;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = (DWORD)
((PDRVPHONE) dwValue)->hPhone;
continue;
case lpDword:
bCopyOnSuccess = TRUE;
continue;
case lpsz:
//
// Check if dwValue is a valid string ptr and if so
// copy the contents of the string to the extra data
// buffer passed to the server, else indicate no data
//
if (dwValue)
{
DWORD n = (lstrlenW ((WCHAR *) dwValue) + 1) *
sizeof (WCHAR),
nAligned = (n + 3) & 0xfffffffc;
if ((nAligned + dwUsedSize) > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
nAligned
))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
}
CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, n);
//
// Pass the server the offset of the string in the var data
// portion of the buffer
//
((PTAPI32_MSG) pTls->pBuf)->Params[j] =
dwUsedSize - sizeof (TAPI32_MSG);
//
// Increment the total number of data bytes
//
dwUsedSize += nAligned;
dwNeededSize += nAligned;
}
else
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
}
continue;
case lpGet_Struct:
case lpGet_SizeToFollow:
{
BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpGet_SizeToFollow);
DWORD dwSize;
if (bSizeToFollow)
{
#if DBG
//
// Check to make sure the following arg is of type Size
//
if ((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
(pFuncArgs->ArgTypes[i + 1] != Size))
{
DBGOUT((
2,
"DoFunc: error, lpGet_SizeToFollow !followed by Size"
));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
#endif
dwSize = pFuncArgs->Args[i + 1];
}
else
{
dwSize = *((LPDWORD) dwValue); // lpXxx->dwTotalSize
}
if (bSizeToFollow)
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
}
else
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = dwSize;
}
//
// Now set the bCopyOnSuccess flag to indicate that we've data
// to copy back on successful completion, and add to the
// dwNeededSize field
//
bCopyOnSuccess = TRUE;
dwNeededSize += dwSize;
continue;
}
case lpSet_Struct:
case lpSet_SizeToFollow:
{
BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
DWORD dwSize, dwSizeAligned;
#if DBG
//
// Check to make sure the following arg is of type Size
//
if (bSizeToFollow &&
((i == ((pFuncArgs->Flags & NUM_ARGS_MASK) - 1)) ||
(pFuncArgs->ArgTypes[i + 1] != Size)))
{
DBGOUT((
2,
"DoFunc: error, lpSet_SizeToFollow !followed by Size"
));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
#endif
if (bSizeToFollow)
{
dwSize = (dwValue ? pFuncArgs->Args[i + 1] : 0);
}
else
{
dwSize = (dwValue ? *((LPDWORD) dwValue) : 0);
}
if (dwSize)
{
//
// Grow the buffer if necessary, & do the copy
//
dwSizeAligned = (dwSize + 3) & 0xfffffffc;
if ((dwSizeAligned + dwUsedSize) > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
dwSizeAligned
))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
}
CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, dwSize);
}
else
{
dwSizeAligned = 0;
}
//
// Pass the server the offset of the data in the var data
// portion of the buffer
//
if (dwSize)
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] =
dwUsedSize - sizeof (TAPI32_MSG);
}
else
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
}
//
// Increment the dwXxxSize vars appropriately
//
dwUsedSize += dwSizeAligned;
dwNeededSize += dwSizeAligned;
//
// Since we already know the next arg (Size) just handle
// it here so we don't have to run thru the loop again
//
if (bSizeToFollow)
{
((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
}
continue;
}
#if DBG
case Size:
DBGOUT((2, "DoFunc: error, hit case Size"));
continue;
default:
DBGOUT((2, "DoFunc: error, unknown arg type"));
continue;
#endif
} // switch
} // for
//
//
//
if (pServer->bDisconnected)
{
lResult = gaServerDisconnectedErrors[dwFuncClassErrorIndex];
}
//
// Now make the request
//
if (dwNeededSize > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
dwNeededSize - pTls->dwBufSize
))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto RemoteDoFunc_return;
}
}
((PTAPI32_MSG) pTls->pBuf)->u.Req_Func = (DWORD)HIWORD(pFuncArgs->Flags);
{
DWORD dwRetryCount = 0;
do
{
RpcTryExcept
{
ClientRequest(
pServer->phContext,
pTls->pBuf,
dwNeededSize,
&dwUsedSize
);
lResult = ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
dwRetryCount = gdwRetryCount;
//
// If this is an async func & success, then munge the result to
// be the local async request id
//
if ((pFuncArgs->Flags & ASYNC) && (lResult > 0))
{
lResult = pFuncArgs->Args[0];
}
}
RpcExcept (1)
{
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
else
{
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
//
// If request completed successfully and the bCopyOnSuccess flag
// is set then we need to copy data back to client buffer(s)
//
if ((lResult == TAPI_SUCCESS) && bCopyOnSuccess)
{
for (i = 0, j = 0; i < (pFuncArgs->Flags & NUM_ARGS_MASK); i++, j++)
{
PTAPI32_MSG pMsg = (PTAPI32_MSG) pTls->pBuf;
switch (pFuncArgs->ArgTypes[i])
{
case Dword:
case LineID:
case PhoneID:
case Hdcall:
case Hdline:
case Hdphone:
case lpsz:
case lpSet_Struct:
continue;
case lpDword:
//
// Fill in the pointer with the return value
//
*((LPDWORD) pFuncArgs->Args[i]) = pMsg->Params[j];
continue;
case lpGet_SizeToFollow:
//
// Fill in the buf with the return data
//
CopyMemory(
(LPBYTE) pFuncArgs->Args[i],
pTls->pBuf + pMsg->Params[j] + sizeof(TAPI32_MSG),
pMsg->Params[j+1]
);
//
// Increment i (and j, since Size passed as arg in msg)
// to skip following Size arg in pFuncArgs->Args
//
i++;
j++;
continue;
case lpSet_SizeToFollow:
//
// Increment i (and j, since Size passed as arg in msg)
// to skip following Size arg in pFuncArgs->Args
//
i++;
j++;
continue;
case lpGet_Struct:
//
// Params[j] contains the offset in the var data
// portion of pTls->pBuf of some TAPI struct.
// Get the dwUsedSize value from this struct &
// copy that many bytes from pTls->pBuf to client buf
//
if (pMsg->Params[j] != TAPI_NO_DATA)
{
LPDWORD pStruct;
pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
pMsg->Params[j]);
CopyMemory(
(LPBYTE) pFuncArgs->Args[i],
(LPBYTE) pStruct,
*(pStruct + 2) // ptr to dwUsedSize field
);
}
continue;
default:
continue;
}
}
}
RemoteDoFunc_return:
DBGOUT((3, "%s: exit, returning x%x", pszFuncName, lResult));
return lResult;
}
//
// --------------------------- TAPI_lineXxx funcs -----------------------------
//
LONG
TSPIAPI
TSPI_lineAccept(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpsUserUserInfo,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lAccept),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineAccept"));
}
LONG
TSPIAPI
TSPI_lineAddToConference(
DRV_REQUESTID dwRequestID,
HDRVCALL hdConfCall,
HDRVCALL hdConsultCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdConfCall,
(DWORD) hdConsultCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lAddToConference),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineAddToConference"));
}
LONG
TSPIAPI
TSPI_lineAnswer(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpsUserUserInfo,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lAnswer),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineAnswer"));
}
LONG
TSPIAPI
TSPI_lineBlindTransfer(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpsz,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpszDestAddress,
(DWORD) dwCountryCode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lBlindTransfer),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineBlindTransfer"));
}
LONG
TSPIAPI
TSPI_lineClose(
HDRVLINE hdLine
)
{
//
// Check if the hLine is still valid (could have been zeroed
// out on LINE_CLOSE, so no need to call server)
//
if (((PDRVLINE) hdLine)->hLine)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, lClose),
(LPDWORD) &hdLine,
argTypes
};
REMOTEDOFUNC (&funcArgs, "lineClose");
}
//assert (((PDRVLINE) hdLine)->pCalls == NULL);
return 0;
}
LONG
TSPIAPI
TSPI_lineCloseCall(
HDRVCALL hdCall
)
{
//
// Check if the hCall is still valid (could have been zeroed
// out on LINE_CLOSE, so no need to call server)
//
if (((PDRVCALL) hdCall)->hCall)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall), // API differs
(LPDWORD) &hdCall,
argTypes
};
REMOTEDOFUNC (&funcArgs, "lineCloseCall");
}
RemoveCallFromList ((PDRVCALL) hdCall);
DrvFree ((LPVOID) hdCall);
return 0;
}
LONG
TSPIAPI
TSPI_lineCompleteCall(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPDWORD lpdwCompletionID,
DWORD dwCompletionMode,
DWORD dwMessageID
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdcall,
Dword, // BUGBUG? should be lpDword?
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) 0, // BUGBUG ppproc
(DWORD) hdCall,
(DWORD) lpdwCompletionID,
(DWORD) dwCompletionMode,
(DWORD) dwMessageID
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lCompleteCall),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineCompleteCall"));
}
LONG
TSPIAPI
TSPI_lineCompleteTransfer(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
HDRVCALL hdConsultCall,
HTAPICALL htConfCall,
LPHDRVCALL lphdConfCall,
DWORD dwTransferMode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdcall,
Hdcall,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) 0,
(DWORD) hdCall,
(DWORD) hdConsultCall,
(DWORD) 0,
(DWORD) dwTransferMode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lCompleteTransfer),
args,
argTypes
};
LONG lResult;
PDRVCALL pConfCall;
if (dwTransferMode == LINETRANSFERMODE_CONFERENCE)
{
if (!(pConfCall = DrvAlloc (sizeof (DRVCALL))))
{
return LINEERR_NOMEM;
}
//
// Assume success & add the call to the line's list before we
// even make the request. This makes cleanup alot easier if
// the server goes down or some such uncooth event.
//
AddCallToList ((PDRVLINE) ((PDRVCALL) hdCall)->pLine, pConfCall);
pConfCall->htCall = htConfCall;
*lphdConfCall = (HDRVCALL) pConfCall;
args[1] = (DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess);
args[4] = (DWORD) pConfCall;
}
else
{
pConfCall = NULL;
}
if ((lResult = REMOTEDOFUNC (&funcArgs, "lineCompleteTransfer")) < 0)
{
if (pConfCall)
{
RemoveCallFromList (pConfCall);
DrvFree (pConfCall);
}
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineConditionalMediaDetection(
HDRVLINE hdLine,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
)
{
// BUGBUG TSPI_lineConditionalMediaDetection
// try an open on the specified line w/ the specified media modes
return LINEERR_OPERATIONFAILED;
}
void
PASCAL
TSPI_lineDevSpecific_PostProcess(
PASYNCEVENTMSG pMsg
)
{
DBGOUT((3, "lineDevSpecificPostProcess: enter"));
DBGOUT((
3,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3,
pMsg->dwParam4
));
if (pMsg->dwParam2 == 0)
{
DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
}
}
LONG
TSPIAPI
TSPI_lineDevSpecific(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
LPVOID lpParams,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdline,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineDevSpecific_PostProcess),
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) hdCall,
(DWORD) lpParams, // pass the actual pointer (for post processing)
(DWORD) lpParams, // pass data
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lDevSpecific),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineDevSpecific"));
}
LONG
TSPIAPI
TSPI_lineDevSpecificFeature(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwFeature,
LPVOID lpParams,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdline,
Dword,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineDevSpecific_PostProcess),
(DWORD) hdLine,
(DWORD) dwFeature,
(DWORD) lpParams, // pass the actual pointer (for post processing)
(DWORD) lpParams, // pass data
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecificFeature),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineDevSpecificFeature"));
}
LONG
TSPIAPI
TSPI_lineDial(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpsz,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpszDestAddress,
(DWORD) dwCountryCode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lDial),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineDial"));
}
LONG
TSPIAPI
TSPI_lineDrop(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpsUserUserInfo,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lDrop),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineDrop"));
}
/*
LONG
TSPIAPI
TSPI_lineDropOnClose(
HDRVCALL hdCall
)
{
// BUGBUG TSPI_lineDropOnClose (how about not exporting this?)
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_lineDropNoOwner(
HDRVCALL hdCall
)
{
// BUGBUG TSPI_lineDropNoOwner (how about not exporting this?)
return LINEERR_OPERATIONFAILED;
}
*/
LONG
TSPIAPI
TSPI_lineForward(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD bAllAddresses,
DWORD dwAddressID,
LPLINEFORWARDLIST const lpForwardList,
DWORD dwNumRingsNoAnswer,
HTAPICALL htConsultCall,
LPHDRVCALL lphdConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
// BUGBUG TSPI_lineForward
// remember to use ppproc param
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_lineGatherDigits(
HDRVCALL hdCall,
DWORD dwEndToEndID,
DWORD dwDigitModes,
LPWSTR lpsDigits,
DWORD dwNumDigits,
LPCWSTR lpszTerminationDigits,
DWORD dwFirstDigitTimeout,
DWORD dwInterDigitTimeout
)
{
// BUGBUG TSPI_lineGatherDigits
// remember to use ppproc param, the dwEndToEndID presents a problem
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_lineGenerateDigits(
HDRVCALL hdCall,
DWORD dwEndToEndID,
DWORD dwDigitMode,
LPCWSTR lpszDigits,
DWORD dwDuration
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword,
lpsz,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwDigitMode,
(DWORD) lpszDigits,
(DWORD) dwDuration,
(DWORD) dwEndToEndID,
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGenerateDigits"));
}
LONG
TSPIAPI
TSPI_lineGenerateTone(
HDRVCALL hdCall,
DWORD dwEndToEndID,
DWORD dwToneMode,
DWORD dwDuration,
DWORD dwNumTones,
LPLINEGENERATETONE const lpTones
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwToneMode,
(DWORD) dwDuration,
(DWORD) dwNumTones,
(DWORD) TAPI_NO_DATA,
(DWORD) 0,
(DWORD) dwEndToEndID
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
args,
argTypes
};
if (dwToneMode == LINETONEMODE_CUSTOM)
{
argTypes[4] = lpSet_SizeToFollow;
args[4] = (DWORD) lpTones;
argTypes[5] = Size;
args[5] = dwNumTones * sizeof(LINEGENERATETONE);
}
return (REMOTEDOFUNC (&funcArgs, "lineGenerateTone"));
}
LONG
TSPIAPI
TSPI_lineGetAddressCaps(
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
LineID,
Dword,
Dword,
Dword,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
(DWORD) dwDeviceID,
(DWORD) dwAddressID,
(DWORD) dwTSPIVersion,
(DWORD) dwExtVersion,
(DWORD) lpAddressCaps,
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetAddressCaps"));
}
LONG
TSPIAPI
TSPI_lineGetAddressID(
HDRVLINE hdLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCWSTR lpsAddress,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
lpDword,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) lpdwAddressID,
(DWORD) dwAddressMode,
(DWORD) lpsAddress,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetAddressID"));
}
LONG
TSPIAPI
TSPI_lineGetAddressStatus(
HDRVLINE hdLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
Dword,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) lpAddressStatus
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetAddressStatus"));
}
LONG
TSPIAPI
TSPI_lineGetCallAddressID(
HDRVCALL hdCall,
LPDWORD lpdwAddressID
)
{
*lpdwAddressID = ((PDRVCALL) hdCall)->dwAddressID;
return 0;
}
LONG
TSPIAPI
TSPI_lineGetCallInfo(
HDRVCALL hdCall,
LPLINECALLINFO lpCallInfo
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) lpCallInfo
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetCallInfo"));
}
LONG
TSPIAPI
TSPI_lineGetCallStatus(
HDRVCALL hdCall,
LPLINECALLSTATUS lpCallStatus
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) lpCallStatus
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetCallStatus"));
}
LONG
TSPIAPI
TSPI_lineGetDevCaps(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
LineID,
Dword,
Dword,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
(DWORD) dwDeviceID,
(DWORD) dwTSPIVersion,
(DWORD) dwExtVersion,
(DWORD) lpLineDevCaps
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetDevCaps"));
}
LONG
TSPIAPI
TSPI_lineGetDevConfig(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCWSTR lpszDeviceClass
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
LineID,
lpGet_Struct,
lpsz
};
DWORD args[] =
{
(DWORD) dwDeviceID,
(DWORD) lpDeviceConfig,
(DWORD) lpszDeviceClass
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetDevConfig"));
}
LONG
TSPIAPI
TSPI_lineGetExtensionID(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
LPLINEEXTENSIONID lpExtensionID
)
{
CopyMemory(
lpExtensionID,
&(GetLineFromID (dwDeviceID))->ExtensionID,
sizeof (LINEEXTENSIONID)
);
return 0;
}
LONG
TSPIAPI
TSPI_lineGetIcon(
DWORD dwDeviceID,
LPCWSTR lpszDeviceClass,
LPHICON lphIcon
)
{
*lphIcon = ghLineIcon;
return 0;
}
LONG
TSPIAPI
TSPI_lineGetID(
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCWSTR lpszDeviceClass,
HANDLE hTargetProcess
)
{
if (lstrcmpiW (lpszDeviceClass, L"tapi/line") != 0)
{
REMOTE_ARG_TYPES argTypes[] =
{
(dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
Dword,
(dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
Dword,
lpGet_Struct,
lpsz
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) hdCall,
(DWORD) dwSelect,
(DWORD) lpDeviceID,
(DWORD) lpszDeviceClass
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetID"));
}
if (lpDeviceID->dwTotalSize <
(lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD)))
{
lpDeviceID->dwUsedSize = 3 * sizeof (DWORD);
}
else
{
lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = sizeof (DWORD);
lpDeviceID->dwStringOffset = sizeof (VARSTRING);
if (dwSelect == LINECALLSELECT_CALL)
{
*((LPDWORD)(lpDeviceID + 1)) =
((PDRVCALL) hdCall)->pLine->dwDeviceIDLocal;
}
else
{
*((LPDWORD)(lpDeviceID + 1)) =
((PDRVLINE) hdLine)->dwDeviceIDLocal;
}
}
return 0;
}
LONG
TSPIAPI
TSPI_lineGetLineDevStatus(
HDRVLINE hdLine,
LPLINEDEVSTATUS lpLineDevStatus
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) lpLineDevStatus
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetLineDevStatus"));
}
LONG
TSPIAPI
TSPI_lineGetNumAddressIDs(
HDRVLINE hdLine,
LPDWORD lpdwNumAddressIDs
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
lpDword
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) lpdwNumAddressIDs
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetNumAddressIDs),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineGetNumAddressIDs"));
}
LONG
TSPIAPI
TSPI_lineHold(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lHold),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineHold"));
}
void
PASCAL
TSPI_lineMakeCall_PostProcess(
PASYNCEVENTMSG pMsg
)
{
PDRVCALL pCall = (PDRVCALL) pMsg->dwParam4;
DBGOUT((3, "TSPI_lineMakeCall_PostProcess: enter"));
DBGOUT((
3,
"\t\tdwP1=x%x, dwP2=x%x, dwP3=x%x, dwP4=x%x",
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3,
pMsg->dwParam4
));
if (pMsg->dwParam2 == 0)
{
pCall->hCall = (HCALL) pMsg->dwParam3;
}
else
{
RemoveCallFromList (pCall);
DrvFree (pCall);
}
}
LONG
TSPIAPI
TSPI_lineMakeCall(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdline,
Dword,
lpsz,
Dword,
lpSet_Struct,
Dword
};
PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
(DWORD) hdLine,
(DWORD) pCall,
(DWORD) lpszDestAddress,
(DWORD) dwCountryCode,
(DWORD) lpCallParams,
(DWORD) 0xffffffff // dwCallParamsCodePage
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lMakeCall),
args,
argTypes
};
LONG lResult;
if (pCall)
{
//
// Assume success & add the call to the line's list before we
// even make the request. This makes cleanup alot easier if
// the server goes down or some such uncooth event.
//
AddCallToList ((PDRVLINE) hdLine, pCall);
pCall->htCall = htCall;
*lphdCall = (HDRVCALL) pCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "lineMakeCall")) < 0)
{
RemoveCallFromList (pCall);
DrvFree (pCall);
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineMonitorDigits(
HDRVCALL hdCall,
DWORD dwDigitModes
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwDigitModes
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineMonitorDigits"));
}
LONG
TSPIAPI
TSPI_lineMonitorMedia(
HDRVCALL hdCall,
DWORD dwMediaModes
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwMediaModes
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineMonitorMedia"));
}
LONG
TSPIAPI
TSPI_lineMonitorTones(
HDRVCALL hdCall,
DWORD dwToneListID,
LPLINEMONITORTONE const lpToneList,
DWORD dwNumEntries
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
lpSet_SizeToFollow,
Size,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) lpToneList,
(DWORD) dwNumEntries * sizeof (LINEMONITORTONE),
(DWORD) dwToneListID
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
args,
argTypes
};
if (!lpToneList)
{
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (REMOTEDOFUNC (&funcArgs, "lineMonitorTones"));
}
LONG
TSPIAPI
TSPI_lineNegotiateExtVersion(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwExtVersion
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
LineID,
Dword,
Dword,
Dword,
lpDword
};
DWORD args[] =
{
(DWORD) (GetLineFromID (dwDeviceID))->pServer->hLineApp,
(DWORD) dwDeviceID,
(DWORD) dwTSPIVersion,
(DWORD) dwLowVersion,
(DWORD) dwHighVersion,
(DWORD) lpdwExtVersion,
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineNegotiateExtVersion"));
}
LONG
TSPIAPI
TSPI_lineNegotiateTSPIVersion(
DWORD dwDeviceID,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwTSPIVersion
)
{
if (dwDeviceID == INITIALIZE_NEGOTIATION)
{
*lpdwTSPIVersion = TAPI_VERSION_CURRENT;
}
else
{
*lpdwTSPIVersion = (GetLineFromID (dwDeviceID))->dwXPIVersion;
}
return 0;
}
LONG
TSPIAPI
TSPI_lineOpen(
DWORD dwDeviceID,
HTAPILINE htLine,
LPHDRVLINE lphdLine,
DWORD dwTSPIVersion,
LINEEVENT lpfnEventProc
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword, // hLineApp
LineID, // dev id
lpDword, // lphLine
Dword, // API version
Dword, // ext version
Dword, // callback inst
Dword, // privileges
Dword, // dw media modes
Dword, // call params
Dword, // dwAsciiCallParamsCodePage
Dword // remote hLine
};
PDRVLINE pLine = GetLineFromID (dwDeviceID);
DWORD args[] =
{
(DWORD) pLine->pServer->hLineApp,
(DWORD) dwDeviceID,
(DWORD) &pLine->hLine,
(DWORD) dwTSPIVersion,
(DWORD) 0,
(DWORD) 0,
(DWORD) LINECALLPRIVILEGE_NONE,
(DWORD) 0,
(DWORD) 0,
(DWORD) 0xffffffff,
(DWORD) pLine
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
args,
argTypes
};
pLine->dwKey = DRVLINE_KEY;
pLine->htLine = htLine;
*lphdLine = (HDRVLINE) pLine;
#if DBG
{
LONG lResult = REMOTEDOFUNC (&funcArgs, "lineOpen");
return lResult;
}
#else
return (REMOTEDOFUNC (&funcArgs, "lineOpen"));
#endif
}
void
PASCAL
TSPI_linePark_PostProcess(
PASYNCEVENTMSG pMsg
)
{
DBGOUT((3, "lineParkPostProcess: enter"));
DBGOUT((
3,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3,
pMsg->dwParam4
));
if (pMsg->dwParam2 == 0)
{
DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
LPVARSTRING pNonDirAddress = (LPVARSTRING) pMsg->dwParam3;
CopyMemory (pNonDirAddress, (LPBYTE) (pMsg + 1), dwSize);
}
}
LONG
TSPIAPI
TSPI_linePark(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
DWORD dwParkMode,
LPCWSTR lpszDirAddress,
LPVARSTRING lpNonDirAddress
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdcall,
Dword,
lpsz,
Dword, // pass ptr as Dword for post processing
lpGet_Struct // pass ptr as lpGet_Xx to retrieve dwTotalSize
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_linePark_PostProcess),
(DWORD) hdCall,
(DWORD) dwParkMode,
(DWORD) lpszDirAddress,
(DWORD) lpNonDirAddress,
(DWORD) lpNonDirAddress
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lPark),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "linePark"));
}
LONG
TSPIAPI
TSPI_linePickup(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCWSTR lpszDestAddress,
LPCWSTR lpszGroupID
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdline,
Dword,
Dword,
lpsz,
lpsz
};
PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) pCall,
(DWORD) lpszDestAddress,
(DWORD) lpszGroupID
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lPickup),
args,
argTypes
};
LONG lResult;
if (pCall)
{
AddCallToList ((PDRVLINE) hdLine, pCall);
pCall->htCall = htCall;
*lphdCall = (HDRVCALL) pCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "linePickup")) < 0)
{
RemoveCallFromList (pCall);
DrvFree (pCall);
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
LONG
TSPIAPI
TSPI_linePrepareAddToConference(
DRV_REQUESTID dwRequestID,
HDRVCALL hdConfCall,
HTAPICALL htConsultCall,
LPHDRVCALL lphdConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdcall,
Dword,
lpSet_Struct,
Dword
};
PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
(DWORD) hdConfCall,
(DWORD) pConsultCall,
(DWORD) lpCallParams,
(DWORD) 0xffffffff // dwAsciiCallParamsCodePage
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lPrepareAddToConference),
args,
argTypes
};
LONG lResult;
if (pConsultCall)
{
AddCallToList (((PDRVCALL) hdConfCall)->pLine, pConsultCall);
pConsultCall->htCall = htConsultCall;
*lphdConsultCall = (HDRVCALL) pConsultCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "linePrepareAddToConference"))
< 0)
{
RemoveCallFromList (pConsultCall);
DrvFree (pConsultCall);
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineRedirect(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpsz,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpszDestAddress,
(DWORD) dwCountryCode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lRedirect),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineRedirect"));
}
LONG
TSPIAPI
TSPI_lineReleaseUserUserInfo(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lReleaseUserUserInfo),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineReleaseUserUserInfo"));
}
LONG
TSPIAPI
TSPI_lineRemoveFromConference(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lRemoveFromConference),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineRemoveFromConference"));
}
LONG
TSPIAPI
TSPI_lineSecureCall(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lSecureCall),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSecureCall"));
}
LONG
TSPIAPI
TSPI_lineSelectExtVersion(
HDRVLINE hdLine,
DWORD dwExtVersion
)
{
// BUGBUG TSPI_lineSelectExtVersion
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_lineSendUserUserInfo(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpsUserUserInfo,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSendUserUserInfo),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSendUserUserInfo"));
}
/* BUGBUG wait 'til spec is complete for agent SPIs
LONG
TSPIAPI
TSPI_lineSetAgent(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
LPLINEAGENTLIST lpAgentList
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdline,
Dword,
lpSet_Struct
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) lpAgentList
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgent),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetAgent"));
}
LONG
TSPIAPI
TSPI_lineSetAgentActivity(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
LPCSTR lpszAgentActivity
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdline,
Dword,
lpsz
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwAdressID,
(DWORD) lpszAgentActivity
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentActivity),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetAgentActivity"));
}
TSPIAPI
TSPI_lineSetAgentState(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
DWORD dwAgentState,
DWORD dwNextAgentState
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdline,
Dword,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwAdressID,
(DWORD) dwAgentState,
(DWORD) dwNextAgentState
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lSetAgentState),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetAgentState"));
}
*/
LONG
TSPIAPI
TSPI_lineSetAppSpecific(
HDRVCALL hdCall,
DWORD dwAppSpecific
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwAppSpecific
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetAppSpecific"));
}
LONG
TSPIAPI
TSPI_lineSetCallData(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPVOID lpCallData,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpCallData,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetCallData),
(LPDWORD) args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetCallData"));
}
LONG
TSPIAPI
TSPI_lineSetCallParams(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
DWORD dwBearerMode,
DWORD dwMinRate,
DWORD dwMaxRate,
LPLINEDIALPARAMS const lpDialParams
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) dwBearerMode,
(DWORD) dwMinRate,
(DWORD) dwMaxRate,
(DWORD) lpDialParams,
(DWORD) (lpDialParams ? sizeof (LINEDIALPARAMS) : 0)
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lSetCallParams),
(LPDWORD) args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetCallParams"));
}
LONG
TSPIAPI
TSPI_lineSetCallQualityOfService(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPVOID lpSendingFlowspec,
DWORD dwSendingFlowspecSize,
LPVOID lpReceivingFlowspec,
DWORD dwReceivingFlowspecSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
lpSet_SizeToFollow,
Size,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) lpSendingFlowspec,
(DWORD) dwSendingFlowspecSize,
(DWORD) lpReceivingFlowspec,
(DWORD) dwReceivingFlowspecSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallQualityOfService),
(LPDWORD) args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetCallQualityOfService"));
}
LONG
TSPIAPI
TSPI_lineSetCallTreatment(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
DWORD dwTreatment
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall,
(DWORD) dwTreatment
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallTreatment),
(LPDWORD) args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetCallTreatment"));
}
LONG
TSPIAPI
TSPI_lineSetCurrentLocation(
DWORD dwLocation
)
{
// BUGBUG TSPI_lineSetCurrentLocation
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_lineSetDefaultMediaDetection(
HDRVLINE hdLine,
DWORD dwMediaModes
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
Dword
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) dwMediaModes,
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetDefaultMediaDetection),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetDefaultMediaDetection"));
}
LONG
TSPIAPI
TSPI_lineSetDevConfig(
DWORD dwDeviceID,
LPVOID const lpDeviceConfig,
DWORD dwSize,
LPCWSTR lpszDeviceClass
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
LineID,
lpSet_SizeToFollow,
Size,
lpsz
};
DWORD args[] =
{
(DWORD) dwDeviceID,
(DWORD) lpDeviceConfig,
(DWORD) dwSize,
(DWORD) lpszDeviceClass
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetDevConfig"));
}
LONG
TSPIAPI
TSPI_lineSetLineDevStatus(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwStatusToChange,
DWORD fStatus
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdline,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwStatusToChange,
(DWORD) fStatus
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetLineDevStatus),
(LPDWORD) args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetLineDevStatus"));
}
LONG
TSPIAPI
TSPI_lineSetMediaControl(
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
LPLINEMEDIACONTROLDIGIT const lpDigitList,
DWORD dwDigitNumEntries,
LPLINEMEDIACONTROLMEDIA const lpMediaList,
DWORD dwMediaNumEntries,
LPLINEMEDIACONTROLTONE const lpToneList,
DWORD dwToneNumEntries,
LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
DWORD dwCallStateNumEntries
)
{
REMOTE_ARG_TYPES argTypes[] =
{
(dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
Dword,
(dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
Dword,
lpSet_SizeToFollow,
Size,
lpSet_SizeToFollow,
Size,
lpSet_SizeToFollow,
Size,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) hdCall,
(DWORD) dwSelect,
(DWORD) lpDigitList,
(DWORD) dwDigitNumEntries,
(DWORD) lpMediaList,
(DWORD) dwMediaNumEntries,
(DWORD) lpToneList,
(DWORD) dwToneNumEntries,
(DWORD) lpCallStateList,
(DWORD) dwCallStateNumEntries
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
args,
argTypes
};
dwDigitNumEntries *= sizeof (LINEMEDIACONTROLDIGIT);
dwMediaNumEntries *= sizeof (LINEMEDIACONTROLMEDIA);
dwToneNumEntries *= sizeof (LINEMEDIACONTROLTONE);
dwCallStateNumEntries *= sizeof (LINEMEDIACONTROLCALLSTATE);
return (REMOTEDOFUNC (&funcArgs, "lineSetMediaControl"));
}
LONG
TSPIAPI
TSPI_lineSetMediaMode(
HDRVCALL hdCall,
DWORD dwMediaMode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) hdCall,
(DWORD) dwMediaMode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetMediaMode"));
}
LONG
TSPIAPI
TSPI_lineSetStatusMessages(
HDRVLINE hdLine,
DWORD dwLineStates,
DWORD dwAddressStates
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdline,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) hdLine,
(DWORD) dwLineStates,
(DWORD) dwAddressStates
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetStatusMessages"));
}
LONG
TSPIAPI
TSPI_lineSetTerminal(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
DWORD dwTerminalModes,
DWORD dwTerminalID,
DWORD bEnable
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Dword,
(dwSelect == LINECALLSELECT_CALL ? Dword : Hdline),
Dword,
(dwSelect == LINECALLSELECT_CALL ? Hdcall : Dword),
Dword,
Dword,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) hdCall,
(DWORD) dwSelect,
(DWORD) dwTerminalModes,
(DWORD) dwTerminalID,
(DWORD) bEnable
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lSetTerminal),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSetTerminal"));
}
void
PASCAL
TSPI_lineSetupConference_PostProcess(
PASYNCEVENTMSG pMsg
)
{
PDRVCALL pConfCall = (PDRVCALL) pMsg->dwParam4,
pConsultCall = (PDRVCALL) *(&pMsg->dwParam4 + 2);
DBGOUT((3, "TSPI_lineSetupConference_PostProcess: enter"));
DBGOUT((
3,
"\t\tdwP1=x%x, dwP2=x%x, dwP3=x%x",
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
));
DBGOUT((
3,
"\t\tdwP4=x%x, dwP5=x%x, dwP6=x%x",
pMsg->dwParam4,
*(&pMsg->dwParam4 + 1),
pConsultCall
));
if (pMsg->dwParam2 == 0)
{
HCALL hConfCall = (HCALL) pMsg->dwParam3,
hConsultCall = (HCALL) *(&pMsg->dwParam4 + 1);
pConfCall->hCall = hConfCall;
pConsultCall->hCall = hConsultCall;
}
else
{
RemoveCallFromList (pConfCall);
RemoveCallFromList (pConsultCall);
DrvFree (pConfCall);
DrvFree (pConsultCall);
}
}
LONG
TSPIAPI
TSPI_lineSetupConference(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
HDRVLINE hdLine,
HTAPICALL htConfCall,
LPHDRVCALL lphdConfCall,
HTAPICALL htConsultCall,
LPHDRVCALL lphdConsultCall,
DWORD dwNumParties,
LPLINECALLPARAMS const lpCallParams
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
(hdCall ? Hdcall : Dword),
(hdCall ? Dword : Hdline),
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
};
PDRVCALL pConfCall = DrvAlloc (sizeof (DRVCALL)),
pConsultCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineSetupConference_PostProcess),
(DWORD) hdCall,
(DWORD) hdLine,
(DWORD) pConfCall,
(DWORD) pConsultCall,
(DWORD) dwNumParties,
(DWORD) lpCallParams,
(DWORD) 0xffffffff // dwAsciiCallParamsCodePage
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 9, lSetupConference),
args,
argTypes
};
LONG lResult;
if (pConfCall)
{
if (pConsultCall)
{
PDRVLINE pLine;
pLine = (hdCall ? ((PDRVCALL) hdCall)->pLine : (PDRVLINE) hdLine);
AddCallToList (pLine, pConfCall);
AddCallToList (pLine, pConsultCall);
pConfCall->htCall = htConfCall;
pConsultCall->htCall = htConsultCall;
*lphdConfCall = (HDRVCALL) pConfCall;
*lphdConsultCall = (HDRVCALL) pConsultCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupConference"))
< 0)
{
RemoveCallFromList (pConfCall);
RemoveCallFromList (pConsultCall);
DrvFree (pConfCall);
DrvFree (pConsultCall);
}
}
else
{
DrvFree (pConfCall);
lResult = LINEERR_NOMEM;
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSetupTransfer(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
HTAPICALL htConsultCall,
LPHDRVCALL lphdConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdcall,
Dword,
lpSet_Struct,
Dword
};
PDRVCALL pConsultCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
(DWORD) hdCall,
(DWORD) pConsultCall,
(DWORD) lpCallParams,
(DWORD) 0xffffffff, // dwAsciiCallParamsCodePage
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lSetupTransfer),
args,
argTypes
};
LONG lResult;
if (pConsultCall)
{
AddCallToList (((PDRVCALL) hdCall)->pLine, pConsultCall);
pConsultCall->htCall = htConsultCall;
*lphdConsultCall = (HDRVCALL) pConsultCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "lineSetupTransfer")) < 0)
{
RemoveCallFromList (pConsultCall);
DrvFree (pConsultCall);
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
LONG
TSPIAPI
TSPI_lineSwapHold(
DRV_REQUESTID dwRequestID,
HDRVCALL hdActiveCall,
HDRVCALL hdHeldCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdActiveCall,
(DWORD) hdHeldCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSwapHold),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineSwapHold"));
}
LONG
TSPIAPI
TSPI_lineUncompleteCall(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwCompletionID
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdline,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdLine,
(DWORD) dwCompletionID
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lUncompleteCall),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineUncompleteCall"));
}
LONG
TSPIAPI
TSPI_lineUnhold(
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdcall
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdCall
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lUnhold),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "lineUnhold"));
}
LONG
TSPIAPI
TSPI_lineUnpark(
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
DWORD dwAddressID,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCWSTR lpszDestAddress
)
{
REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdline,
Dword,
Dword,
lpsz
};
PDRVCALL pCall = DrvAlloc (sizeof (DRVCALL));
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_lineMakeCall_PostProcess),
(DWORD) hdLine,
(DWORD) dwAddressID,
(DWORD) pCall,
(DWORD) lpszDestAddress
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lUnpark),
args,
argTypes
};
LONG lResult;
if (pCall)
{
AddCallToList ((PDRVLINE) hdLine, pCall);
pCall->htCall = htCall;
*lphdCall = (HDRVCALL) pCall;
if ((lResult = REMOTEDOFUNC (&funcArgs, "lineUnpark")) < 0)
{
RemoveCallFromList (pCall);
DrvFree (pCall);
}
}
else
{
lResult = LINEERR_NOMEM;
}
return lResult;
}
//
// -------------------------- TSPI_phoneXxx funcs -----------------------------
//
LONG
TSPIAPI
TSPI_phoneClose(
HDRVPHONE hdPhone
)
{
//
// Check if the hPhone is still valid (could have been zeroed
// out on PHONE_CLOSE, so no need to call server)
//
if (((PDRVPHONE) hdPhone)->hPhone)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
(LPDWORD) &hdPhone,
argTypes
};
REMOTEDOFUNC (&funcArgs, "phoneClose");
}
return 0;
}
void
PASCAL
TSPI_phoneDevSpecific_PostProcess(
PASYNCEVENTMSG pMsg
)
{
DBGOUT((3, "phoneDevSpecificPostProcess: enter"));
DBGOUT((
3,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3,
pMsg->dwParam4
));
if (pMsg->dwParam2 == 0)
{
DWORD dwSize = pMsg->dwTotalSize - sizeof (TAPI32_MSG);
LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
}
}
LONG
TSPIAPI
TSPI_phoneDevSpecific(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
LPVOID lpParams,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Dword,
Hdphone,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) ((POSTPROCESSPROC) TSPI_phoneDevSpecific_PostProcess),
(DWORD) hdPhone,
(DWORD) lpParams, // pass the actual pointer (for post processing)
(DWORD) lpParams, // pass data
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 6, pDevSpecific),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneDevSpecific"));
}
LONG
TSPIAPI
TSPI_phoneGetButtonInfo(
HDRVPHONE hdPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO lpButtonInfo
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwButtonLampID,
(DWORD) lpButtonInfo
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetButtonInfo"));
}
LONG
TSPIAPI
TSPI_phoneGetData(
HDRVPHONE hdPhone,
DWORD dwDataID,
LPVOID lpData,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
lpGet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwDataID,
(DWORD) lpData,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetData"));
}
LONG
TSPIAPI
TSPI_phoneGetDevCaps(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPPHONECAPS lpPhoneCaps
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
PhoneID,
Dword,
Dword,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) (GetPhoneFromID (dwDeviceID))->pServer->hPhoneApp,
(DWORD) dwDeviceID,
(DWORD) dwTSPIVersion,
(DWORD) dwExtVersion,
(DWORD) lpPhoneCaps
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, pGetDevCaps),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetDevCaps"));
}
LONG
TSPIAPI
TSPI_phoneGetDisplay(
HDRVPHONE hdPhone,
LPVARSTRING lpDisplay
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) lpDisplay
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetDisplay"));
}
LONG
TSPIAPI
TSPI_phoneGetExtensionID(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
LPPHONEEXTENSIONID lpExtensionID
)
{
CopyMemory(
lpExtensionID,
&(GetPhoneFromID (dwDeviceID))->ExtensionID,
sizeof (PHONEEXTENSIONID)
);
return 0;
}
LONG
TSPIAPI
TSPI_phoneGetGain(
HDRVPHONE hdPhone,
DWORD dwHookSwitchDev,
LPDWORD lpdwGain
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
lpDword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwHookSwitchDev,
(DWORD) lpdwGain
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetGain"));
}
LONG
TSPIAPI
TSPI_phoneGetHookSwitch(
HDRVPHONE hdPhone,
LPDWORD lpdwHookSwitchDevs
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
lpDword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) lpdwHookSwitchDevs
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetHookSwitch"));
}
LONG
TSPIAPI
TSPI_phoneGetIcon(
DWORD dwDeviceID,
LPCWSTR lpszDeviceClass,
LPHICON lphIcon
)
{
*lphIcon = ghPhoneIcon;
return 0;
}
LONG
TSPIAPI
TSPI_phoneGetID(
HDRVPHONE hdPhone,
LPVARSTRING lpDeviceID,
LPCWSTR lpszDeviceClass,
HANDLE hTargetProcess
)
{
if (lstrcmpiW (lpszDeviceClass, L"tapi/phone") != 0)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
lpGet_Struct,
lpsz
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) lpDeviceID,
(DWORD) lpszDeviceClass
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetID"));
}
if (lpDeviceID->dwTotalSize <
(lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD)))
{
lpDeviceID->dwUsedSize = 3 * sizeof (DWORD);
}
else
{
lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = sizeof (DWORD);
lpDeviceID->dwStringOffset = sizeof (VARSTRING);
*((LPDWORD)(lpDeviceID + 1)) =
((PDRVPHONE) hdPhone)->dwDeviceIDLocal;
}
return 0;
}
LONG
TSPIAPI
TSPI_phoneGetLamp(
HDRVPHONE hdPhone,
DWORD dwButtonLampID,
LPDWORD lpdwLampMode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
lpDword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwButtonLampID,
(DWORD) lpdwLampMode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetLamp"));
}
LONG
TSPIAPI
TSPI_phoneGetRing(
HDRVPHONE hdPhone,
LPDWORD lpdwRingMode,
LPDWORD lpdwVolume
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
lpDword,
lpDword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) lpdwRingMode,
(DWORD) lpdwVolume
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetRing"));
}
LONG
TSPIAPI
TSPI_phoneGetStatus(
HDRVPHONE hdPhone,
LPPHONESTATUS lpPhoneStatus
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
lpGet_Struct
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) lpPhoneStatus
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetStatus"));
}
LONG
TSPIAPI
TSPI_phoneGetVolume(
HDRVPHONE hdPhone,
DWORD dwHookSwitchDev,
LPDWORD lpdwVolume
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
lpDword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwHookSwitchDev,
(DWORD) lpdwVolume
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneGetVolume"));
}
LONG
TSPIAPI
TSPI_phoneNegotiateExtVersion(
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwExtVersion
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
PhoneID,
Dword,
Dword,
Dword,
lpDword
};
DWORD args[] =
{
(DWORD) (GetPhoneFromID (dwDeviceID))->pServer->hPhoneApp,
(DWORD) dwDeviceID,
(DWORD) dwTSPIVersion,
(DWORD) dwLowVersion,
(DWORD) dwHighVersion,
(DWORD) lpdwExtVersion,
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, pNegotiateExtVersion),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
}
LONG
TSPIAPI
TSPI_phoneNegotiateTSPIVersion(
DWORD dwDeviceID,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwTSPIVersion
)
{
if (dwDeviceID == INITIALIZE_NEGOTIATION)
{
*lpdwTSPIVersion = TAPI_VERSION_CURRENT;
}
else
{
*lpdwTSPIVersion = (GetPhoneFromID (dwDeviceID))->dwXPIVersion;
}
return 0;
}
LONG
TSPIAPI
TSPI_phoneOpen(
DWORD dwDeviceID,
HTAPIPHONE htPhone,
LPHDRVPHONE lphdPhone,
DWORD dwTSPIVersion,
PHONEEVENT lpfnEventProc
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword, // hPhoneApp
PhoneID, // dev id
lpDword, // lphPhone
Dword, // API version
Dword, // ext version
Dword, // callback inst
Dword, // privilege
Dword // remote hPhone
};
PDRVPHONE pPhone = GetPhoneFromID (dwDeviceID);
DWORD args[] =
{
(DWORD) pPhone->pServer->hPhoneApp,
(DWORD) dwDeviceID,
(DWORD) &pPhone->hPhone,
(DWORD) dwTSPIVersion,
(DWORD) 0, // BUGBUG
(DWORD) 0,
(DWORD) PHONEPRIVILEGE_OWNER,
(DWORD) pPhone
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
args,
argTypes
};
pPhone->htPhone = htPhone;
*lphdPhone = (HDRVPHONE) pPhone;
return (REMOTEDOFUNC (&funcArgs, "phoneOpen"));
}
LONG
TSPIAPI
TSPI_phoneSelectExtVersion(
HDRVPHONE hdPhone,
DWORD dwExtVersion
)
{
// BUGBUG TSPI_phoneSelectExtVersion
return PHONEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_phoneSetButtonInfo(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO const lpButtonInfo
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
lpSet_Struct
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwButtonLampID,
(DWORD) lpButtonInfo
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetButtonInfo),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetButtonInfo"));
}
LONG
TSPIAPI
TSPI_phoneSetData(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwDataID,
LPVOID const lpData,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwDataID,
(DWORD) lpData,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 5, pSetData),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetData"));
}
LONG
TSPIAPI
TSPI_phoneSetDisplay(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwRow,
DWORD dwColumn,
LPCWSTR lpsDisplay,
DWORD dwSize
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword,
lpSet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwRow,
(DWORD) dwColumn,
(DWORD) lpsDisplay,
(DWORD) dwSize
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 6, pSetDisplay),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetDisplay"));
}
LONG
TSPIAPI
TSPI_phoneSetGain(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwHookSwitchDev,
DWORD dwGain
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwHookSwitchDev,
(DWORD) dwGain
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetGain),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetGain"));
}
LONG
TSPIAPI
TSPI_phoneSetHookSwitch(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwHookSwitchDevs,
DWORD dwHookSwitchMode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwHookSwitchDevs,
(DWORD) dwHookSwitchMode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetHookSwitch),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetHookswitch"));
}
LONG
TSPIAPI
TSPI_phoneSetLamp(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwButtonLampID,
DWORD dwLampMode
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwButtonLampID,
(DWORD) dwLampMode
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetLamp),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetLamp"));
}
LONG
TSPIAPI
TSPI_phoneSetRing(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwRingMode,
DWORD dwVolume
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwRingMode,
(DWORD) dwVolume
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetRing),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetRing"));
}
LONG
TSPIAPI
TSPI_phoneSetStatusMessages(
HDRVPHONE hdPhone,
DWORD dwPhoneStates,
DWORD dwButtonModes,
DWORD dwButtonStates
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Hdphone,
Dword,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) hdPhone,
(DWORD) dwPhoneStates,
(DWORD) dwButtonModes,
(DWORD) dwButtonStates
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetStatusMessages"));
}
LONG
TSPIAPI
TSPI_phoneSetVolume(
DRV_REQUESTID dwRequestID,
HDRVPHONE hdPhone,
DWORD dwHookSwitchDev,
DWORD dwVolume
)
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
Hdphone,
Dword,
Dword
};
DWORD args[] =
{
(DWORD) dwRequestID,
(DWORD) hdPhone,
(DWORD) dwHookSwitchDev,
(DWORD) dwVolume
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetVolume),
args,
argTypes
};
return (REMOTEDOFUNC (&funcArgs, "phoneSetVolume"));
}
//
// ------------------------- TSPI_providerXxx funcs ---------------------------
//
LONG
TSPIAPI
TSPI_providerConfig(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
//
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can configure this provider via lineConfigProvider(),
// otherwise Telephon.cpl will not consider it configurable
//
return 0;
}
LONG
TSPIAPI
TSPI_providerCreateLineDevice(
DWORD dwTempID,
DWORD dwDeviceID
)
{
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_providerCreatePhoneDevice(
DWORD dwTempID,
DWORD dwDeviceID
)
{
return LINEERR_OPERATIONFAILED;
}
LONG
TSPIAPI
TSPI_providerEnumDevices(
DWORD dwPermanentProviderID,
LPDWORD lpdwNumLines,
LPDWORD lpdwNumPhones,
HPROVIDER hProvider,
LINEEVENT lpfnLineCreateProc,
PHONEEVENT lpfnPhoneCreateProc
)
{
char szProviderN[16];
char *pszServerName;
DWORD hClientInst, dwNumServers, i;
RPC_BINDING_HANDLE hBindingInst;
HKEY hTelephonyKey;
HKEY hProviderNKey;
DWORD dwDataSize;
DWORD dwDataType;
RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_ALL_ACCESS,
&hTelephonyKey
);
//
// BUGBUG The following is a cheesy hack to allow us access to net
// since tapisrv is currently running on LocalSystem
//
// Once the service acct stuff is worked out we can nuke this
// (still need the GetMachineName code tho')
//
{
// char szProviders[] = "Providers";
char szUserName[32], szDomainName[32], szPassword[32];
HKEY hProvidersKey;
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
RegOpenKeyEx(
hTelephonyKey,
"Providers",
0,
KEY_ALL_ACCESS,
&hProvidersKey
);
dwDataSize = sizeof(szUserName);
RegQueryValueEx(
hProvidersKey,
"User",
0,
&dwDataType,
(LPBYTE) szUserName,
&dwDataSize
);
szUserName[dwDataSize] = '\0';
dwDataSize = sizeof(szDomainName);
RegQueryValueEx(
hProvidersKey,
"Domain",
0,
&dwDataType,
(LPBYTE) szDomainName,
&dwDataSize
);
szDomainName[dwDataSize] = '\0';
dwDataSize = sizeof(szPassword);
RegQueryValueEx(
hProvidersKey,
"Password",
0,
&dwDataType,
(LPBYTE) szPassword,
&dwDataSize
);
szPassword[dwDataSize] = '\0';
RegCloseKey (hProvidersKey);
if (LogonUser(
szUserName,
szDomainName,
szPassword,
LOGON32_LOGON_SERVICE,
LOGON32_PROVIDER_DEFAULT,
&hToken
))
{
DBGOUT((3, "LogonUser() succeeded"));
wsprintf (gszDomainUser, "%s\\%s", szDomainName, szUserName);
GetComputerNameW (gszMachineName, &dwSize);
DBGOUT((
3,
"\tdomainUser='%s', machine='%ws'",
gszDomainUser,
gszMachineName
));
}
else
{
hToken = NULL;
DBGOUT((1, ""));
DBGOUT((1, "LogonUser() failed, err=%d", GetLastError()));
DBGOUT((1, "\tuserName='%s'", szUserName));
DBGOUT((1, "\tdomainName='%s'", szDomainName));
DBGOUT((1, "\tpassword='%s'", szPassword));
DBGOUT((1, ""));
RegCloseKey (hTelephonyKey);
return LINEERR_OPERATIONFAILED;
}
}
//
// Init gEventHandlerThreadParams & start EventHandlerThread
//
gEventHandlerThreadParams.dwEventBufferTotalSize = 1024;
gEventHandlerThreadParams.dwEventBufferUsedSize = 0;
if (!(gEventHandlerThreadParams.pEventBuffer = DrvAlloc(
gEventHandlerThreadParams.dwEventBufferTotalSize
)))
{
}
gEventHandlerThreadParams.pDataIn =
gEventHandlerThreadParams.pDataOut =
gEventHandlerThreadParams.pEventBuffer;
gEventHandlerThreadParams.dwMsgSize = 512;
if (!(gEventHandlerThreadParams.pMsg = DrvAlloc(
gEventHandlerThreadParams.dwMsgSize
)))
{
}
if (!(gEventHandlerThreadParams.hEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) NULL, // no security attrs
TRUE, // manual reset
FALSE, // initially non-signaled
NULL // unnamed
)))
{
}
gEventHandlerThreadParams.bExit = FALSE;
{
DWORD dwTID;
if (!(gEventHandlerThreadParams.hThread = CreateThread(
(LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) EventHandlerThread,
NULL,
0,
&dwTID
)))
{
DBGOUT((
1,
"CreateThread('EventHandlerThread') failed, err=%d",
GetLastError()
));
RegCloseKey (hTelephonyKey);
return LINEERR_OPERATIONFAILED;
}
}
//
// Register the Rpc interface (leverage tapisrv's rpc server thread)
//
{
RPC_STATUS status;
unsigned char * pszSecurity = NULL;
unsigned int cMaxCalls = 20;
status = RpcServerUseProtseqEp(
"ncacn_np",
cMaxCalls,
"\\pipe\\remotesp",
pszSecurity // Security descriptor
);
DBGOUT((3, "RpcServerUseProtseqEp(np) ret'd %d", status));
if (status)
{
}
status = RpcServerRegisterIf(
remotesp_ServerIfHandle, // interface to register
NULL, // MgrTypeUuid
NULL // MgrEpv; null means use default
);
DBGOUT((3, "RpcServerRegisterIf ret'd %d", status));
if (status)
{
}
}
//
// Init globals
//
// NOTE: tapi's xxxEvent & xxxCreate procs are currently one in the same
//
wsprintf (szProviderN, "Provider%d", dwPermanentProviderID);
gdwPermanentProviderID = dwPermanentProviderID;
gpfnLineEventProc = lpfnLineCreateProc;
gpfnPhoneEventProc = lpfnPhoneCreateProc;
gpServers = (PDRVSERVER) NULL;
gpLineLookup = (PDRVLINELOOKUP) NULL;
gpPhoneLookup = (PDRVPHONELOOKUP) NULL;
RegOpenKeyEx(
hTelephonyKey,
szProviderN,
0,
KEY_ALL_ACCESS,
&hProviderNKey
);
dwDataSize = sizeof(dwNumServers);
dwNumServers = 0;
RegQueryValueEx(
hProviderNKey,
"NumServers",
0,
&dwDataType,
(LPBYTE) &dwNumServers,
&dwDataSize
);
dwDataSize = sizeof(gdwRetryCount);
gdwRetryCount = 0;
RegQueryValueEx(
hProviderNKey,
"RetryCount",
0,
&dwDataType,
(LPBYTE) &gdwRetryCount,
&dwDataSize
);
dwDataSize = sizeof(gdwRetryTimeout);
gdwRetryTimeout = 0;
RegQueryValueEx(
hProviderNKey,
"RetryTimeout",
0,
&dwDataType,
(LPBYTE) &gdwRetryTimeout,
&dwDataSize
);
DBGOUT((
4,
"TSPI_ProviderEnumDevices: pN='%s', numSrvs=%d",
szProviderN,
dwNumServers
));
if (!ImpersonateLoggedOnUser (hToken)) // BUGBUG local system hack
{
DBGOUT((1, "ImpersonateLoggedOnUser failed, err=%d", GetLastError()));
RegCloseKey (hProviderNKey);
RegCloseKey (hTelephonyKey);
return LINEERR_OPERATIONFAILED;
}
//
// Initialize all the servers
//
for (i = 0; i < dwNumServers; i++)
{
char szServerN[32];
DWORD dwNumLineDevices, dwNumPhoneDevices;
HLINEAPP hLineApp;
HPHONEAPP hPhoneApp;
PCONTEXT_HANDLE_TYPE phContext = NULL;
wsprintf (szServerN, "Server%d", i);
pszServerName = DrvAlloc (64);
dwDataSize = 64;
RegQueryValueEx(
hProviderNKey,
szServerN,
0,
&dwDataType,
(LPBYTE) pszServerName,
&dwDataSize
);
pszServerName[dwDataSize] = '\0';
DBGOUT((1, "init: srvNam='%s'", pszServerName));
if (!pszServerName[0])
{
continue;
}
//
// Init the RPC connection
//
gpServer = DrvAlloc (sizeof (DRVSERVER));
{
DWORD dwUsedSize, dwBufSize;
RPC_STATUS status;
TAPI32_MSG msg[2];
unsigned char * pszStringBinding = NULL;
status = RpcStringBindingCompose(
NULL, // uuid
"ncacn_np", // prot
pszServerName, // server name
"\\pipe\\tapsrv", // interface name
NULL, // options
&pszStringBinding
);
if (status)
{
DBGOUT((
0,
"RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
status,
pszServerName
));
}
status = RpcBindingFromStringBinding(
pszStringBinding,
&hTapSrv
);
if (status)
{
DBGOUT((
0,
"RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
status,
pszStringBinding
));
}
{
DWORD dwRetryCount = 0;
do
{
WCHAR szDomainUser[32];
MultiByteToWideChar(
CP_ACP,
MB_PRECOMPOSED,
(LPCSTR) gszDomainUser,
-1,
szDomainUser,
32
);
RpcTryExcept
{
long lUnused;
ClientAttach(
(PCONTEXT_HANDLE_TYPE *) &phContext,
0xffffffff, // dwProcessID, -1 implies remotesp
(long *) &lUnused,
szDomainUser,
gszMachineName
);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
else
{
// BUGBUG gracefully handle cliAttach except error
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
RpcBindingFree (&hTapSrv);
RpcStringFree (&pszStringBinding);
//
//
//
{
PLINEINITIALIZE_PARAMS pParams;
BOOL bExit = FALSE;
msg[0].u.Req_Func = lInitialize;
pParams = (PLINEINITIALIZE_PARAMS) msg;
//
// NOTE: we pass the pServer in place of the lpfnCallback
// so the we always know which server is sending us
// async events
//
pParams->hInstance = 0;
pParams->lpfnCallback = (LINECALLBACK) ((LPVOID) gpServer);
pParams->dwFriendlyNameOffset =
pParams->dwModuleNameOffset = 0;
pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
lstrcpyW ((WCHAR *) (msg + 1), gszMachineName);
dwBufSize =
dwUsedSize = sizeof (TAPI32_MSG) +
(lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
{
DWORD dwRetryCount = 0;
do
{
RpcTryExcept
{
ClientRequest(
phContext,
(char *) &msg,
dwBufSize,
&dwUsedSize
);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
DBGOUT((1, "init: xcpt in lInit"));
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
else
{
// BUGBUG need graceful cleanup
bExit = TRUE;
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
if (bExit)
{
// BUGBUG check the result of lineInit
}
hLineApp = pParams->hLineApp;
dwNumLineDevices = pParams->dwNumDevs;
}
//
//
//
{
PPHONEINITIALIZE_PARAMS pParams;
msg[0].u.Req_Func = pInitialize;
pParams = (PPHONEINITIALIZE_PARAMS) msg;
//
// NOTE: we pass the pServer in place of the lpfnCallback
// so the we always know which server is sending us
// async events
//
pParams->hInstance = 0;
pParams->lpfnCallback = (PHONECALLBACK) ((LPVOID) gpServer);
pParams->dwFriendlyNameOffset =
pParams->dwModuleNameOffset = 0;
pParams->dwAPIVersion = TAPI_VERSION_CURRENT;
lstrcpyW ((WCHAR *) (msg + 1), gszMachineName);
dwBufSize =
dwUsedSize = sizeof (TAPI32_MSG) +
(lstrlenW (gszMachineName) + 1) * sizeof (WCHAR);
{
DWORD dwRetryCount = 0;
do
{
RpcTryExcept
{
ClientRequest(
phContext,
(char *) &msg,
dwBufSize,
&dwUsedSize
);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
else
{
// BUGBUG gracefully handle phoneInit except error
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
// BUGBUG check the result of phoneInit
hPhoneApp = pParams->hPhoneApp;
dwNumPhoneDevices = pParams->dwNumDevs;
}
}
//
//
//
DBGOUT((
1,
"TSPI_providerEnumDevices: srv='%s', lines=%d, phones=%d",
pszServerName,
dwNumLineDevices,
dwNumPhoneDevices
));
{
DWORD j;
gpServer->pServerName = pszServerName;
gpServer->phContext = phContext;
gpServer->hLineApp = hLineApp;
gpServer->hPhoneApp = hPhoneApp;
gpServer->pNext = gpServers;
gpServers = gpServer;
for (j = 0; j < dwNumLineDevices; j++)
{
AddLine (gpServer, j, j, TRUE);
}
for (j = 0; j < dwNumPhoneDevices; j++)
{
AddPhone (gpServer, j, j, TRUE);
}
}
} // for (i = 0; i < iNumServers; i++)
RevertToSelf(); // BUGBUG LocalSystem hack
gdwInitialNumLineDevices =
*lpdwNumLines = (gpLineLookup ? gpLineLookup->dwUsedEntries : 0);
gdwInitialNumPhoneDevices =
*lpdwNumPhones = (gpPhoneLookup ? gpPhoneLookup->dwUsedEntries : 0);
// BUGBUG TSPI_provEnumDev: we ought really do alot of error clean up here
RegCloseKey (hProviderNKey);
RegCloseKey (hTelephonyKey);
return 0;
}
LONG
TSPIAPI
TSPI_providerFreeDialogInstance(
HDRVDIALOGINSTANCE hdDlgInst
)
{
// BUGBUG TSPI_providerFreeDialogInstance: implement
return 0;
}
LONG
TSPIAPI
TSPI_providerGenericDialogData(
DWORD dwObjectID,
DWORD dwObjectType,
LPVOID lpParams,
DWORD dwSize
)
{
// BUGBUG TSPI_providerGenericDialogData: implement
return 0;
}
LONG
TSPIAPI
TSPI_providerInit(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID,
DWORD dwLineDeviceIDBase,
DWORD dwPhoneDeviceIDBase,
DWORD dwNumLines,
DWORD dwNumPhones,
ASYNC_COMPLETION lpfnCompletionProc,
LPDWORD lpdwTSPIOptions
)
{
if (!hToken)
{
return LINEERR_OPERATIONFAILED;
}
gdwLineDeviceIDBase = dwLineDeviceIDBase;
gdwPhoneDeviceIDBase = dwPhoneDeviceIDBase;
gpfnCompletionProc = lpfnCompletionProc;
*lpdwTSPIOptions = 0;
return 0;
}
LONG
TSPIAPI
TSPI_providerInstall(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
//
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can add this provider via lineAddProvider(), otherwise
// Telephon.cpl will not consider it installable
//
//
return 0;
}
LONG
TSPIAPI
TSPI_providerRemove(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
//
// Although this func is never called by TAPI v2.0, we export
// it so that the Telephony Control Panel Applet knows that it
// can remove this provider via lineRemoveProvider(), otherwise
// Telephon.cpl will not consider it removable
//
return 0;
}
LONG
TSPIAPI
TSPI_providerShutdown(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID
)
{
PDRVSERVER pServer;
RPC_STATUS status;
//
// Set the flag instructing the EventHandlerThread to terminate
//
gEventHandlerThreadParams.bExit = TRUE;
//
// Send detach to each server, then wait for the async event threads
// to terminate and free the resources
//
if (!ImpersonateLoggedOnUser (hToken)) // BUGBUG LocalSystem hack
{
DBGOUT((1, "ImpersonateLoggedOnUser failed, err=%d", GetLastError()));
// fall thru
}
pServer = gpServers;
while (pServer)
{
DWORD dwRetryCount = 0;
PDRVSERVER pNextServer = pServer->pNext;
do
{
RpcTryExcept
{
ClientDetach (&pServer->phContext);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
DrvFree (pServer->pServerName);
DrvFree (pServer);
pServer = pNextServer;
}
RevertToSelf(); // BUGBUG LocalSystem hack
CloseHandle (hToken);
//
// Unregister out rpc server interface
//
status = RpcServerUnregisterIf(
remotesp_ServerIfHandle, // interface to register
NULL, // MgrTypeUuid
0 // wait for calls to complete
);
DBGOUT((3, "RpcServerUntegisterIf ret'd %d", status));
//
// Wait for the EventHandlerThread to terminate, then clean up
// the related resources
//
while (WaitForSingleObject (gEventHandlerThreadParams.hThread, 0) !=
WAIT_OBJECT_0)
{
SetEvent (gEventHandlerThreadParams.hEvent);
Sleep (0);
}
CloseHandle (gEventHandlerThreadParams.hThread);
CloseHandle (gEventHandlerThreadParams.hEvent);
DrvFree (gEventHandlerThreadParams.pEventBuffer);
DrvFree (gEventHandlerThreadParams.pMsg);
//
// Free the lookup tables
//
while (gpLineLookup)
{
PDRVLINELOOKUP pNextLineLookup = gpLineLookup->pNext;
DrvFree (gpLineLookup);
gpLineLookup = pNextLineLookup;
}
while (gpPhoneLookup)
{
PDRVPHONELOOKUP pNextPhoneLookup = gpPhoneLookup->pNext;
DrvFree (gpPhoneLookup);
gpPhoneLookup = pNextPhoneLookup;
}
return 0;
}
LONG
TSPIAPI
TSPI_providerUIIdentify(
LPWSTR lpszUIDLLName
)
{
wcscpy (lpszUIDLLName, L"remotesp.tsp");
return 0;
}
//
// ---------------------------- TUISPI_xxx funcs ------------------------------
//
LONG
TSPIAPI
TUISPI_lineConfigDialog(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass
)
{
char buf[128];
wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_lineConfigDialog", MB_OK);
return 0;
}
LONG
TSPIAPI
TUISPI_lineConfigDialogEdit(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass,
LPVOID const lpDeviceConfigIn,
DWORD dwSize,
LPVARSTRING lpDeviceConfigOut
)
{
char buf[128];
wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_lineConfigDialogEdit",MB_OK);
return 0;
}
LONG
TSPIAPI
TUISPI_phoneConfigDialog(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass
)
{
char buf[128];
wsprintf (buf, "devID=%d, devClass='%ws'", dwDeviceID, lpszDeviceClass);
MessageBox (hwndOwner, buf, "REMOTESP: TUISPI_phoneConfigDialog", MB_OK);
return 0;
}
LONG
TSPIAPI
TUISPI_providerConfig(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
DialogBoxParam(
ghInst,
MAKEINTRESOURCE(100),
hwndOwner,
(DLGPROC) ConfigDlgProc,
(LPARAM) dwPermanentProviderID
);
return 0;
}
LONG
TSPIAPI
TUISPI_providerGenericDialog(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
HTAPIDIALOGINSTANCE htDlgInst,
LPVOID lpParams,
DWORD dwSize,
HANDLE hEvent
)
{
char buf[128];
SetEvent (hEvent);
wsprintf (buf, "htDlgInst=x%x", htDlgInst);
MessageBox (NULL, buf,"REMOTESP: TUISPI_providerGenericDialog",MB_OK);
return 0;
}
LONG
TSPIAPI
TUISPI_providerGenericDialogData(
HTAPIDIALOGINSTANCE htDlgInst,
LPVOID lpParams,
DWORD dwSize
)
{
DBGOUT((
3,
"TUISPI_providerGenericDialogData: enter (lpParams=x%x, dwSize=x%x)",
lpParams,
dwSize
));
return 0;
}
LONG
TSPIAPI
TUISPI_providerInstall(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
char buf[32];
LONG lResult = LINEERR_OPERATIONFAILED;
HKEY hTelephonyKey, hProviderNKey;
DWORD dwDataType, dwDataSize, dwTemp, dwDisposition;
if (ProviderInstall ("remotesp.tsp", TRUE) == 0)
{
//
// Initialize our ProviderN section
//
wsprintf (buf, "Provider%d", dwPermanentProviderID);
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
(LPSECURITY_ATTRIBUTES) NULL,
&hTelephonyKey,
&dwDisposition
) == ERROR_SUCCESS)
{
if (RegCreateKeyEx(
hTelephonyKey,
buf,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
(LPSECURITY_ATTRIBUTES) NULL,
&hProviderNKey,
&dwDisposition
) == ERROR_SUCCESS)
{
dwTemp = 0;
RegSetValueEx(
hProviderNKey,
gszNumServers,
0,
REG_DWORD,
(LPBYTE) &dwTemp,
sizeof(dwTemp)
);
RegCloseKey (hProviderNKey);
RegCloseKey (hTelephonyKey);
DialogBoxParam(
ghInst,
MAKEINTRESOURCE(100),
hwndOwner,
(DLGPROC) ConfigDlgProc,
(LPARAM) dwPermanentProviderID
);
lResult = 0;
}
else
{
RegCloseKey (hTelephonyKey);
}
}
}
return lResult;
}
LONG
TSPIAPI
TUISPI_providerRemove(
TUISPIDLLCALLBACK lpfnUIDLLCallback,
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
char buf[32];
LONG lResult;
HKEY hTelephonyKey;
//
// Clean up our ProviderN section
//
wsprintf (buf, "Provider%d", dwPermanentProviderID);
if (RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_ALL_ACCESS,
&hTelephonyKey
) == ERROR_SUCCESS)
{
RegDeleteKey (hTelephonyKey, buf);
RegCloseKey (hTelephonyKey);
lResult = 0;
}
else
{
lResult = LINEERR_OPERATIONFAILED;
}
return lResult;
}
//
// ------------------------ Private support routines --------------------------
//
#if DBG
VOID
DbgPrt(
IN DWORD dwDbgLevel,
IN PUCHAR lpszFormat,
IN ...
)
/*++
Routine Description:
Formats the incoming debug message & calls DbgPrint
Arguments:
DbgLevel - level of message verboseness
DbgMessage - printf-style format string, followed by appropriate
list of arguments
Return Value:
--*/
{
if (dwDbgLevel <= gdwDebugLevel)
{
char buf[128] = "REMOTESP: ";
va_list ap;
va_start(ap, lpszFormat);
wvsprintf (&buf[10], lpszFormat, ap);
lstrcatA (buf, "\n");
OutputDebugStringA (buf);
va_end(ap);
}
}
#endif
LONG
AddLine(
PDRVSERVER pServer,
DWORD dwDeviceIDLocal,
DWORD dwDeviceIDServer,
BOOL bInit
)
{
PDRVLINE pLine;
PDRVLINELOOKUP pLineLookup;
if (!gpLineLookup)
{
if (!(gpLineLookup = DrvAlloc(
sizeof(DRVLINELOOKUP) +
(DEF_NUM_LINE_ENTRIES-1) * sizeof (DRVLINE)
)))
{
return LINEERR_NOMEM;
}
gpLineLookup->dwTotalEntries = DEF_NUM_LINE_ENTRIES;
}
pLineLookup = gpLineLookup;
while (pLineLookup->pNext)
{
pLineLookup = pLineLookup->pNext;
}
if (pLineLookup->dwUsedEntries == pLineLookup->dwTotalEntries)
{
PDRVLINELOOKUP pNewLineLookup;
if (!(pNewLineLookup = DrvAlloc(
sizeof(DRVLINELOOKUP) +
(2 * pLineLookup->dwTotalEntries - 1) * sizeof(DRVLINE)
)))
{
return LINEERR_NOMEM;
}
pNewLineLookup->dwTotalEntries = 2 * pLineLookup->dwTotalEntries;
if (bInit)
{
pNewLineLookup->dwUsedEntries = pLineLookup->dwTotalEntries;
CopyMemory(
pNewLineLookup->aEntries,
pLineLookup->aEntries,
pLineLookup->dwTotalEntries * sizeof (DRVLINE)
);
DrvFree (pLineLookup);
gpLineLookup = pNewLineLookup;
}
pLineLookup = pNewLineLookup;
}
pLine = pLineLookup->aEntries + pLineLookup->dwUsedEntries;
pLine->pServer = pServer;
pLine->dwDeviceIDLocal = dwDeviceIDLocal;
pLine->dwDeviceIDServer = dwDeviceIDServer;
pLineLookup->dwUsedEntries++;
//
// Negotiate the API/SPI version
//
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
LineID,
Dword,
Dword,
lpDword,
lpGet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) pServer->hLineApp,
(DWORD) dwDeviceIDLocal,
(DWORD) TAPI_VERSION1_0,
(DWORD) TAPI_VERSION_CURRENT,
(DWORD) &pLine->dwXPIVersion,
(DWORD) &pLine->ExtensionID,
(DWORD) sizeof (LINEEXTENSIONID),
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
args,
argTypes
};
REMOTEDOFUNC (&funcArgs, "lineNegotiateAPIVersion");
}
return 0;
}
LONG
AddPhone(
PDRVSERVER pServer,
DWORD dwDeviceIDLocal,
DWORD dwDeviceIDServer,
BOOL bInit
)
{
PDRVPHONE pPhone;
PDRVPHONELOOKUP pPhoneLookup;
if (!gpPhoneLookup)
{
if (!(gpPhoneLookup = DrvAlloc(
sizeof(DRVPHONELOOKUP) +
(DEF_NUM_PHONE_ENTRIES-1) * sizeof (DRVPHONE)
)))
{
return (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
}
gpPhoneLookup->dwTotalEntries = DEF_NUM_PHONE_ENTRIES;
}
pPhoneLookup = gpPhoneLookup;
while (pPhoneLookup->pNext)
{
pPhoneLookup = pPhoneLookup->pNext;
}
if (pPhoneLookup->dwUsedEntries == pPhoneLookup->dwTotalEntries)
{
PDRVPHONELOOKUP pNewPhoneLookup;
if (!(pNewPhoneLookup = DrvAlloc(
sizeof(DRVPHONELOOKUP) +
(2 * pPhoneLookup->dwTotalEntries - 1) * sizeof(DRVPHONE)
)))
{
return (bInit ? LINEERR_NOMEM : PHONEERR_NOMEM);
}
pNewPhoneLookup->dwTotalEntries = 2 * pPhoneLookup->dwTotalEntries;
if (bInit)
{
pNewPhoneLookup->dwUsedEntries = pPhoneLookup->dwTotalEntries;
CopyMemory(
pNewPhoneLookup->aEntries,
pPhoneLookup->aEntries,
pPhoneLookup->dwTotalEntries * sizeof (DRVPHONE)
);
DrvFree (pPhoneLookup);
gpPhoneLookup = pNewPhoneLookup;
}
pPhoneLookup = pNewPhoneLookup;
}
pPhone = pPhoneLookup->aEntries + pPhoneLookup->dwUsedEntries;
pPhone->pServer = pServer;
pPhone->dwDeviceIDLocal = dwDeviceIDLocal;
pPhone->dwDeviceIDServer = dwDeviceIDServer;
pPhoneLookup->dwUsedEntries++;
//
// Negotiate the API/SPI version
//
{
static REMOTE_ARG_TYPES argTypes[] =
{
Dword,
PhoneID,
Dword,
Dword,
lpDword,
lpGet_SizeToFollow,
Size
};
DWORD args[] =
{
(DWORD) pServer->hPhoneApp,
(DWORD) dwDeviceIDLocal,
(DWORD) TAPI_VERSION1_0,
(DWORD) TAPI_VERSION_CURRENT,
(DWORD) &pPhone->dwXPIVersion,
(DWORD) &pPhone->ExtensionID,
(DWORD) sizeof (PHONEEXTENSIONID),
};
REMOTE_FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
args,
argTypes
};
REMOTEDOFUNC (&funcArgs, "phoneNegotiateAPIVersion");
}
return 0;
}
LPVOID
DrvAlloc(
DWORD dwSize
)
{
return (LocalAlloc (LPTR, dwSize));
}
void
DrvFree(
LPVOID p
)
{
LocalFree (p);
}
void
__RPC_FAR *
__RPC_API
midl_user_allocate(
size_t len
)
{
return (DrvAlloc (len));
}
void
__RPC_API
midl_user_free(
void __RPC_FAR * ptr
)
{
DrvFree (ptr);
}
LONG
RemoteSPAttach(
PCONTEXT_HANDLE_TYPE2 *pphContext
)
{
//
// This func is called by TapiSrv.exe on a remote machine as a
// result of the call to ClientAttach in TSPI_providerEnumDevices.
// The gpServer variable contains a pointer to the DRVSERVER
// structure we are currently initializing for this tapi server,
// so we'll use this as the context value.
//
DBGOUT((3, "RemoteSPAttach: enter"));
*pphContext = (PCONTEXT_HANDLE_TYPE) gpServer;
return 0;
}
void
RemoteSPEventProc(
PCONTEXT_HANDLE_TYPE2 phContext,
unsigned char *pBuffer,
long lSize
)
{
//
// This func is called by tapisrv on a remote machine. We want to do
// things as quickly as possible here and return so we don't block the
// calling server thread.
//
DWORD dwMoveSize = (DWORD) lSize, dwMoveSizeWrapped = 0;
//
// Enter the critical section to sync access to gEventHandlerThreadParams
//
EnterCriticalSection (&gEventBufferCriticalSection);
//
// Check to see if there's enough room for this msg in the event buffer.
// If not, then alloc a new event buffer, copy contents of existing buffer
// to new buffer (careful to preserve ordering of valid data), free the
// existing buffer, and reset the pointers.
//
if ((gEventHandlerThreadParams.dwEventBufferUsedSize + lSize) >
gEventHandlerThreadParams.dwEventBufferTotalSize)
{
DWORD dwMoveSize2, dwMoveSizeWrapped2, dwNewEventBufferTotalSize;
LPBYTE pNewEventBuffer;
//
// Alloc a few more bytes than actually needed in the hope that we
// won't have to do this again soon (we don't want to go overboard
// & alloc a whole bunch since we don't currently free the buffer
// until provider shutdown)
//
dwNewEventBufferTotalSize =
gEventHandlerThreadParams.dwEventBufferUsedSize + lSize + 512;
if (!(pNewEventBuffer = DrvAlloc (dwNewEventBufferTotalSize)))
{
// BUGBUG we're hosed, blow off the msg (send a REINIT?)
LeaveCriticalSection (&gEventBufferCriticalSection);
return;
}
if (gEventHandlerThreadParams.dwEventBufferUsedSize != 0)
{
if (gEventHandlerThreadParams.pDataIn >
gEventHandlerThreadParams.pDataOut)
{
dwMoveSize2 = (DWORD) (gEventHandlerThreadParams.pDataIn -
gEventHandlerThreadParams.pDataOut);
dwMoveSizeWrapped2 = 0;
}
else
{
dwMoveSize2 = (DWORD) ((gEventHandlerThreadParams.pEventBuffer
+ gEventHandlerThreadParams.dwEventBufferTotalSize)
- gEventHandlerThreadParams.pDataOut);
dwMoveSizeWrapped2 = (DWORD) (gEventHandlerThreadParams.pDataIn
- gEventHandlerThreadParams.pEventBuffer);
}
CopyMemory(
pNewEventBuffer,
gEventHandlerThreadParams.pDataOut,
dwMoveSize2
);
if (dwMoveSizeWrapped2)
{
CopyMemory(
pNewEventBuffer + dwMoveSize2,
gEventHandlerThreadParams.pEventBuffer,
dwMoveSizeWrapped2
);
}
DrvFree (gEventHandlerThreadParams.pEventBuffer);
gEventHandlerThreadParams.pDataIn = pNewEventBuffer + dwMoveSize2 +
dwMoveSizeWrapped2;
}
else
{
gEventHandlerThreadParams.pDataIn = pNewEventBuffer;
}
gEventHandlerThreadParams.pDataOut =
gEventHandlerThreadParams.pEventBuffer = pNewEventBuffer;
gEventHandlerThreadParams.dwEventBufferTotalSize =
dwNewEventBufferTotalSize;
}
//
// Write the msg data to the buffer
//
if (gEventHandlerThreadParams.pDataIn >=
gEventHandlerThreadParams.pDataOut)
{
DWORD dwFreeSize;
dwFreeSize = gEventHandlerThreadParams.dwEventBufferTotalSize -
(gEventHandlerThreadParams.pDataIn -
gEventHandlerThreadParams.pEventBuffer);
if (dwMoveSize > dwFreeSize)
{
dwMoveSizeWrapped = dwMoveSize - dwFreeSize;
dwMoveSize = dwFreeSize;
}
}
CopyMemory (gEventHandlerThreadParams.pDataIn, pBuffer, dwMoveSize);
if (dwMoveSizeWrapped != 0)
{
CopyMemory(
gEventHandlerThreadParams.pEventBuffer,
pBuffer + dwMoveSize,
dwMoveSizeWrapped
);
gEventHandlerThreadParams.pDataIn =
gEventHandlerThreadParams.pEventBuffer + dwMoveSizeWrapped;
}
else
{
gEventHandlerThreadParams.pDataIn += dwMoveSize;
}
gEventHandlerThreadParams.dwEventBufferUsedSize += (DWORD) lSize;
//
// Tell the EventHandlerThread there's another event to handle by
// signaling the event
//
SetEvent (gEventHandlerThreadParams.hEvent);
//
// We're done...
//
LeaveCriticalSection (&gEventBufferCriticalSection);
DBGOUT((3, "WriteEventBuffer: bytesWritten=x%x", lSize));
}
void
__RPC_USER
PCONTEXT_HANDLE_TYPE2_rundown(
PCONTEXT_HANDLE_TYPE2 phContext
)
{
//
// This func is called when a server dies. We need to close any open
// lines/phones associated with the server, complete pending reqs, and...
//
// BUGBUG PCONTEXT_HANDLE_TYPE2_rundown
//
}
void
RemoteSPDetach(
PCONTEXT_HANDLE_TYPE2 *pphContext
)
{
DBGOUT((3, "RemoteSPDetach: enter"));
PCONTEXT_HANDLE_TYPE2_rundown (*pphContext);
*pphContext = (PCONTEXT_HANDLE_TYPE) NULL;
DBGOUT((3, "RemoteSPDetach: exit"));
}
LONG
AddCallToList(
PDRVLINE pLine,
PDRVCALL pCall
)
{
//
// Initialize some common fields in the call
//
pCall->pServer = pLine->pServer;
pCall->pLine = pLine;
//
// Safely add the call to the line's list
//
EnterCriticalSection (&gCallListCriticalSection);
if ((pCall->pNext = (PDRVCALL) pLine->pCalls))
{
pCall->pNext->pPrev = pCall;
}
pLine->pCalls = pCall;
LeaveCriticalSection (&gCallListCriticalSection);
return 0;
}
LONG
RemoveCallFromList(
PDRVCALL pCall
)
{
//
// Safely remove the call from the line's list
//
EnterCriticalSection (&gCallListCriticalSection);
if (pCall->pNext)
{
pCall->pNext->pPrev = pCall->pPrev;
}
if (pCall->pPrev)
{
pCall->pPrev->pNext = pCall->pNext;
}
else
{
pCall->pLine->pCalls = pCall->pNext;
}
LeaveCriticalSection (&gCallListCriticalSection);
return 0;
}
void
Shutdown(
PDRVSERVER pServer
)
{
//
// Do a lineShutdown
//
{
DWORD dwSize;
TAPI32_MSG msg;
PLINESHUTDOWN_PARAMS pParams;
msg.u.Req_Func = lShutdown;
pParams = (PLINESHUTDOWN_PARAMS) &msg;
pParams->hLineApp = pServer->hLineApp;
dwSize = sizeof (TAPI32_MSG);
{
DWORD dwRetryCount = 0;
do
{
RpcTryExcept
{
ClientRequest(
pServer->phContext,
(char *) &msg,
dwSize,
&dwSize
);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
// TODO may want to increase the retry count here since we
// have to do this, & a million other clients may be
// trying to do the same thing at the same time
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
}
//
// Do a phoneShutdown
//
{
DWORD dwSize;
TAPI32_MSG msg;
PPHONESHUTDOWN_PARAMS pParams;
msg.u.Req_Func = pShutdown;
pParams = (PPHONESHUTDOWN_PARAMS) &msg;
pParams->hPhoneApp = pServer->hPhoneApp;
dwSize = sizeof (TAPI32_MSG);
{
DWORD dwRetryCount = 0;
do
{
RpcTryExcept
{
ClientRequest(
pServer->phContext,
(char *) &msg,
dwSize,
&dwSize
);
dwRetryCount = gdwRetryCount;
}
RpcExcept (1)
{
// TODO may want to increase the retry count here since we
// have to do this, & a million other clients may be
// trying to do the same thing at the same time
if (dwRetryCount++ < gdwRetryCount)
{
Sleep (gdwRetryTimeout);
}
}
RpcEndExcept
} while (dwRetryCount < gdwRetryCount);
}
}
//
// Mark the server as disconnected (so no more requests will be sent)
//
pServer->bDisconnected = TRUE;
//
// Walk the line lookup tables & send a CLOSE msg for each open line
// associated with the server
//
{
PDRVLINELOOKUP pLookup = gpLineLookup;
while (pLookup)
{
DWORD i;
PDRVLINE pLine;
for(
i = 0, pLine = pLookup->aEntries;
i < pLookup->dwUsedEntries;
i++, pLine++
)
{
if (pLine->pServer == pServer)
{
pLine->pServer = NULL;
if (pLine->htLine)
{
PDRVCALL pCall;
pLine->hLine = NULL;
EnterCriticalSection (&gCallListCriticalSection);
pCall = pLine->pCalls;
while (pCall)
{
pCall->hCall = NULL;
pCall = pCall->pNext;
}
LeaveCriticalSection (&gCallListCriticalSection);
(*gpfnLineEventProc)(
pLine->htLine,
NULL,
LINE_CLOSE,
0,
0,
0
);
}
}
}
pLookup = pLookup->pNext;
}
}
//
// Walk the phone lookup tables & send a CLOSE msg for each open phone
// associated with the server
//
{
PDRVPHONELOOKUP pLookup = gpPhoneLookup;
while (pLookup)
{
DWORD i;
PDRVPHONE pPhone;
for(
i = 0, pPhone = pLookup->aEntries;
i < pLookup->dwUsedEntries;
i++, pPhone++
)
{
if (pPhone->pServer == pServer)
{
pPhone->pServer = NULL;
if (pPhone->htPhone)
{
pPhone->hPhone = NULL;
(*gpfnPhoneEventProc)(
pPhone->htPhone,
PHONE_CLOSE,
0,
0,
0
);
}
}
}
pLookup = pLookup->pNext;
}
}
}
BOOL
CALLBACK
ConfigDlgProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
static HKEY hTelephonyKey, hProviderNKey;
DWORD dwDataType, dwDataSize;
switch (msg)
{
case WM_INITDIALOG:
{
char buf[32], szProviderN[16], szServerN[16];
BOOL bReadOnly;
DWORD i, iNumServers;
DWORD dwPermanentProviderID = (DWORD) lParam;
//
// First try to open the Telephony key with read/write access.
// If that fails, disable any controls that could cause a chg
// in config & try opening again with read only access.
//
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_ALL_ACCESS,
&hTelephonyKey
) != ERROR_SUCCESS)
{
EnableWindow (GetDlgItem (hwnd, IDC_ADD), FALSE);
EnableWindow (GetDlgItem (hwnd, IDC_REMOVE), FALSE);
EnableWindow (GetDlgItem (hwnd, IDOK), FALSE);
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_READ,
&hTelephonyKey
) != ERROR_SUCCESS)
{
EndDialog (hwnd, 0);
return FALSE;
}
bReadOnly = TRUE;
}
else
{
bReadOnly = FALSE;
}
wsprintf (szProviderN, "%s%d", gszProvider, dwPermanentProviderID);
RegOpenKeyEx(
hTelephonyKey,
szProviderN,
0,
(bReadOnly ? KEY_READ : KEY_ALL_ACCESS),
&hProviderNKey
);
dwDataSize = sizeof(iNumServers);
RegQueryValueEx(
hProviderNKey,
gszNumServers,
0,
&dwDataType,
(LPBYTE) &iNumServers,
&dwDataSize
);
for (i = 0; i < iNumServers; i++)
{
wsprintf (szServerN, "%s%d", gszServer, i);
dwDataSize = sizeof(buf);
RegQueryValueEx(
hProviderNKey,
szServerN,
0,
&dwDataType,
(LPBYTE) buf,
&dwDataSize
);
buf[dwDataSize] = '\0';
SendDlgItemMessage(
hwnd,
IDC_LIST1,
LB_ADDSTRING,
0,
(LPARAM) buf
);
}
SetWindowLong (hwnd, GWL_USERDATA, dwPermanentProviderID);
break;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_ADD:
{
char buf[32];
GetDlgItemText (hwnd, IDC_EDIT1, buf, 31);
if (buf[0])
{
SendDlgItemMessage(
hwnd,
IDC_LIST1,
LB_ADDSTRING,
0,
(LPARAM) buf
);
}
SetDlgItemText (hwnd, IDC_EDIT1, "");
break;
}
case IDC_REMOVE:
{
char buf[32];
LONG lSel;
if ((lSel = SendDlgItemMessage(
hwnd,
IDC_LIST1,
LB_GETCURSEL,
0,
0
)) != LB_ERR)
{
SendDlgItemMessage(
hwnd,
IDC_LIST1,
LB_GETTEXT,
lSel,
(LPARAM) buf
);
SendDlgItemMessage (hwnd, IDC_LIST1, LB_DELETESTRING, lSel, 0);
SetDlgItemText (hwnd, IDC_EDIT1, buf);
}
break;
}
case IDOK:
{
char buf[32], szServerN[16], szProviderN[16];
DWORD i, lCount;
wsprintf(
szProviderN,
"%s%d",
gszProvider,
GetWindowLong (hwnd, GWL_USERDATA)
);
lCount = SendDlgItemMessage (hwnd, IDC_LIST1, LB_GETCOUNT, 0, 0);
RegSetValueEx(
hProviderNKey,
gszNumServers,
0,
REG_DWORD,
(LPBYTE) &lCount,
sizeof(lCount)
);
for (i = 0; i < lCount; i++)
{
SendDlgItemMessage(
hwnd,
IDC_LIST1,
LB_GETTEXT,
i,
(LPARAM) buf
);
wsprintf (szServerN, "%s%d", gszServer, i);
RegSetValueEx(
hProviderNKey,
szServerN,
0,
REG_SZ,
(LPBYTE) buf,
lstrlenA (buf) + 1
);
}
// fall thru to below
}
case IDCANCEL:
RegCloseKey (hProviderNKey);
RegCloseKey (hTelephonyKey);
EndDialog (hwnd, 0);
break;
} // switch (LOWORD(wParam))
break;
/* don't want to bring in another lib just yet
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint (hwnd, &ps);
FillRect (ps.hdc, &ps.rcPaint, GetStockObject (LTGRAY_BRUSH));
EndPaint (hwnd, &ps);
break;
} */
} // switch (msg)
return FALSE;
}
LONG
PASCAL
ProviderInstall(
char *pszProviderName,
BOOL bNoMultipleInstance
)
{
LONG lResult;
//
// If only one installation instance of this provider is
// allowed then we want to check the provider list to see
// if the provider is already installed
//
if (bNoMultipleInstance)
{
LONG (WINAPI *pfnGetProviderList)();
DWORD dwTotalSize, i;
HINSTANCE hTapi32;
LPLINEPROVIDERLIST pProviderList;
LPLINEPROVIDERENTRY pProviderEntry;
//
// Load Tapi32.dll & get a pointer to the lineGetProviderList
// func. We don't want to statically link because this module
// plays the part of both core SP & UI DLL, and we don't want
// to incur the performance hit of automatically loading
// Tapi32.dll when running as a core SP within Tapisrv.exe's
// context.
//
if (!(hTapi32 = LoadLibrary ("tapi32.dll")))
{
DBGOUT((
1,
"LoadLibrary(tapi32.dll) failed, err=%d",
GetLastError()
));
lResult = LINEERR_OPERATIONFAILED;
goto ProviderInstall_return;
}
if (!((FARPROC) pfnGetProviderList = GetProcAddress(
hTapi32,
(LPCSTR) "lineGetProviderList"
)))
{
DBGOUT((
1,
"GetProcAddr(lineGetProviderList) failed, err=%d",
GetLastError()
));
lResult = LINEERR_OPERATIONFAILED;
goto ProviderInstall_unloadTapi32;
}
//
// Loop until we get the full provider list
//
dwTotalSize = sizeof (LINEPROVIDERLIST);
goto ProviderInstall_allocProviderList;
ProviderInstall_getProviderList:
if ((lResult = (*pfnGetProviderList)(0x00020000, pProviderList)) != 0)
{
goto ProviderInstall_freeProviderList;
}
if (pProviderList->dwNeededSize > pProviderList->dwTotalSize)
{
dwTotalSize = pProviderList->dwNeededSize;
LocalFree (pProviderList);
ProviderInstall_allocProviderList:
if (!(pProviderList = LocalAlloc (LPTR, dwTotalSize)))
{
lResult = LINEERR_NOMEM;
goto ProviderInstall_unloadTapi32;
}
pProviderList->dwTotalSize = dwTotalSize;
goto ProviderInstall_getProviderList;
}
//
// Inspect the provider list entries to see if this provider
// is already installed
//
pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) +
pProviderList->dwProviderListOffset);
for (i = 0; i < pProviderList->dwNumProviders; i++)
{
char *pszInstalledProviderName = ((char *) pProviderList) +
pProviderEntry->dwProviderFilenameOffset,
*p;
//
// Make sure pszInstalledProviderName points at <filename>
// and not <path>\filename by walking backeards thru the
// string searching for last '\\'
//
p = pszInstalledProviderName +
lstrlen (pszInstalledProviderName) - 1;
for (; *p != '\\' && p != pszInstalledProviderName; p--);
pszInstalledProviderName =
(p == pszInstalledProviderName ? p : p + 1);
if (lstrcmpiA (pszInstalledProviderName, pszProviderName) == 0)
{
lResult = LINEERR_NOMULTIPLEINSTANCE;
goto ProviderInstall_freeProviderList;
}
pProviderEntry++;
}
//
// If here then the provider isn't currently installed,
// so do whatever configuration stuff is necessary and
// indicate SUCCESS
//
lResult = 0;
ProviderInstall_freeProviderList:
LocalFree (pProviderList);
ProviderInstall_unloadTapi32:
FreeLibrary (hTapi32);
}
else
{
//
// Do whatever configuration stuff is necessary and return SUCCESS
//
lResult = 0;
}
ProviderInstall_return:
return lResult;
}