Leaked source code of windows server 2003
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.
 
 
 
 
 
 

18323 lines
434 KiB

/*++ BUILD Version: 0000 // Increment this if a change has global effects
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
client.c
Abstract:
This module contains the tapi.dll implementation (client-side tapi)
Author:
Dan Knudson (DanKn) 01-Apr-1995
Revision History:
Notes:
1. Make all funcArg structs STATIC, & just do whatever mov's necessary
for the params (saves mov's for flags, pfnPostProcess, funcName, &
argTypes)
--*/
#include "windows.h"
#include "wownt32.h"
#include "stdarg.h"
#include "stdio.h"
#include "tapi.h"
#include "tspi.h"
#include "utils.h"
#include "client.h"
#include "clntprivate.h"
#include "tapsrv.h"
#include "loc_comn.h"
#include "prsht.h"
#include "shellapi.h"
#include "tapiperf.h"
#include "tlnklist.h"
#include "tapihndl.h"
#include "resource.h"
#include "tchar.h"
#include "shfusion.h"
#include <shlwapi.h>
#include <shlwapip.h> // from private\inc
#include <MMSYSTEM.H>
#include <mmddk.h>
#include "tregupr2.h"
#undef lineBlindTransfer
#undef lineConfigDialog
#undef lineConfigDialogEdit
#undef lineDial
#undef lineForward
#undef lineGatherDigits
#undef lineGenerateDigits
#undef lineGetAddressCaps
#undef lineGetAddressID
#undef lineGetAddressStatus
#undef lineGetCallInfo
#undef lineGetDevCaps
#undef lineGetDevConfig
#undef lineGetIcon
#undef lineGetID
#undef lineGetLineDevStatus
#undef lineGetRequest
#undef lineGetTranslateCaps
#undef lineHandoff
#undef lineMakeCall
#undef lineOpen
#undef linePark
#undef linePickup
#undef linePrepareAddToConference
#undef lineRedirect
#undef lineSetDevConfig
#undef lineSetTollList
#undef lineSetupConference
#undef lineSetupTransfer
#undef lineTranslateAddress
#undef lineUnpark
#undef phoneConfigDialog
#undef phoneGetButtonInfo
#undef phoneGetDevCaps
#undef phoneGetIcon
#undef phoneGetID
#undef phoneGetStatus
#undef phoneSetButtonInfo
#undef tapiGetLocationInfo
#undef tapiRequestMakeCall
#undef tapiRequestMediaCall
#undef lineAddProvider
#undef lineGetAppPriority
#undef lineGetCountry
#undef lineGetProviderList
#undef lineSetAppPriority
#undef lineTranslateDialog
//
//
//
#define HUB_MONITOR_LINE_CONTEXT_BASE 0xc0000000
#define ASNYC_MSG_BUF_SIZE 1024
typedef struct _ASYNC_EVENTS_THREAD_PARAMS
{
BOOL bExitThread;
DWORD dwBufSize;
HANDLE hTapi32;
HANDLE hWow32;
LPBYTE pBuf;
} ASYNC_EVENTS_THREAD_PARAMS, *PASYNC_EVENTS_THREAD_PARAMS;
#if DBG
//
// N.B. This structure MUST be a multiple of 8 bytes in size.
//
typedef struct _MYMEMINFO
{
struct _MYMEMINFO * pNext;
struct _MYMEMINFO * pPrev;
DWORD dwSize;
DWORD dwLine;
PSTR pszFile;
DWORD dwAlign;
// LPTSTR pName;
} MYMEMINFO, *PMYMEMINFO;
PMYMEMINFO gpMemFirst = NULL, gpMemLast = NULL;
CRITICAL_SECTION csMemoryList;
BOOL gbBreakOnLeak = FALSE;
void
DumpMemoryList();
#endif
//
// Global vars
//
BOOL gbHiddenWndClassRegistered = FALSE;
BOOL gbNTVDMClient = FALSE;
DWORD gdwRpcRefCount = 0;
BOOL gbDisableGetTranslateCapsHack = FALSE;
DWORD gdwNumInits = 0;
DWORD gdwTlsIndex;
DWORD gdwTlsIndexRpcCtx;
DWORD gdwNumLineDevices = 0;
DWORD gdwNumPhoneDevices = 0;
DWORD gdwInitialTickCount;
HANDLE ghAsyncEventsEvent = NULL;
HANDLE ghInitMutex;
#if DBG
DWORD gdwDebugLevel = 0;
#endif
TCHAR gszLCRDLL[] = TEXT("LeastCostRoutingDLL");
TCHAR gszRemoteSP[] = TEXT("RemoteSP.TSP");
LONG
(WINAPI
*pfnLineOpenWLCR)(
HLINEAPP hLineApp,
DWORD dwDeviceID,
LPHLINE lphLine,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivileges,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
);
LONG
(WINAPI
*pfnLineOpenALCR)(
HLINEAPP hLineApp,
DWORD dwDeviceID,
LPHLINE lphLine,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivileges,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
);
LONG
(WINAPI
*pfnLineTranslateAddressWLCR)(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
LPCWSTR lpszAddressIn,
DWORD dwCard,
DWORD dwTranslateOptions,
LPLINETRANSLATEOUTPUT lpTranslateOutput
);
LONG EnsureOneLocation (HWND hwnd);
extern BOOL gbTranslateSimple;
extern BOOL gbTranslateSilent;
HINSTANCE g_hInst;
PASYNC_EVENTS_THREAD_PARAMS gpAsyncEventsThreadParams = NULL;
#if DBG
const TCHAR gszTapi32DebugLevel[] = TEXT("Tapi32DebugLevel");
#endif
const TCHAR gszTapi32MaxNumRequestRetries[] = TEXT("Tapi32MaxNumRequestRetries");
const TCHAR gszTapi32RequestRetryTimeout[] = TEXT("Tapi32RequestRetryTimeout");
extern TCHAR gszTelephonyKey[];
DWORD gdwMaxNumRequestRetries;
DWORD gdwRequestRetryTimeout;
const TCHAR szTapi32WndClass[] = TEXT("Tapi32WndClass");
// These all get passed to GetProcAddress so they stay as ANSI
const CHAR gszTUISPI_providerConfig[] = "TUISPI_providerConfig";
const CHAR gszTUISPI_providerGenericDialog[] = "TUISPI_providerGenericDialog";
const CHAR gszTUISPI_providerGenericDialogData[] = "TUISPI_providerGenericDialogData";
const CHAR gszTUISPI_providerInstall[] = "TUISPI_providerInstall";
const CHAR gszTUISPI_providerRemove[] = "TUISPI_providerRemove";
const CHAR gszTUISPI_lineConfigDialog[] = "TUISPI_lineConfigDialog";
const CHAR gszTUISPI_lineConfigDialogEdit[] = "TUISPI_lineConfigDialogEdit";
const CHAR gszTUISPI_phoneConfigDialog[] = "TUISPI_phoneConfigDialog";
extern TCHAR gszLocations[];
HANDLE ghHandleTable;
HINSTANCE ghWow32Dll = NULL;
FARPROC gpfnWOWGetVDMPointer = NULL;
static FARPROC gpPostQueuedCompletionStatus = NULL;
PUITHREADDATA gpUIThreadInstances = NULL;
CRITICAL_SECTION gCriticalSection;
CRITICAL_SECTION gUICriticalSection;
PCONTEXT_HANDLE_TYPE gphCx = (PCONTEXT_HANDLE_TYPE) NULL;
LIST_ENTRY gTlsListHead;
CRITICAL_SECTION gTlsCriticalSection;
#if DBG
// All the debug only stuff stays as ANSI (just because it was easier than chagning it).
const char *aszMsgs[] =
{
"LINE_ADDRESSSTATE",
"LINE_CALLINFO",
"LINE_CALLSTATE",
"LINE_CLOSE",
"LINE_DEVSPECIFIC",
"LINE_DEVSPECIFICFEATURE",
"LINE_GATHERDIGITS",
"LINE_GENERATE",
"LINE_LINEDEVSTATE",
"LINE_MONITORDIGITS",
"LINE_MONITORMEDIA",
"LINE_MONITORTONE",
"LINE_REPLY",
"LINE_REQUEST",
"PHONE_BUTTON",
"PHONE_CLOSE",
"PHONE_DEVSPECIFIC",
"PHONE_REPLY",
"PHONE_STATE",
"LINE_CREATE",
"PHONE_CREATE",
"LINE_AGENTSPECIFIC",
"LINE_AGENTSTATUS",
"LINE_APPNEWCALL",
"LINE_PROXYREQUEST",
"LINE_REMOVE",
"PHONE_REMOVE"
};
#endif
LONG gaNoMemErrors[3] =
{
TAPIERR_REQUESTFAILED,
LINEERR_NOMEM,
PHONEERR_NOMEM
};
LONG gaInvalHwndErrors[3] =
{
TAPIERR_INVALWINDOWHANDLE,
LINEERR_INVALPARAM,
PHONEERR_INVALPARAM
};
LONG gaInvalPtrErrors[3] =
{
TAPIERR_INVALPOINTER,
LINEERR_INVALPOINTER,
PHONEERR_INVALPOINTER
};
LONG gaOpFailedErrors[3] =
{
TAPIERR_REQUESTFAILED,
LINEERR_OPERATIONFAILED,
PHONEERR_OPERATIONFAILED
};
LONG gaStructTooSmallErrors[3] =
{
TAPIERR_REQUESTFAILED,
LINEERR_STRUCTURETOOSMALL,
PHONEERR_STRUCTURETOOSMALL
};
LONG gaServiceNotRunningErrors[3] =
{
TAPIERR_REQUESTFAILED,
LINEERR_SERVICE_NOT_RUNNING,
PHONEERR_SERVICE_NOT_RUNNING
};
#define AllInitExOptions2_0 \
(LINEINITIALIZEEXOPTION_USEHIDDENWINDOW | \
LINEINITIALIZEEXOPTION_USEEVENT | \
LINEINITIALIZEEXOPTION_USECOMPLETIONPORT)
//
// Function prototypes
//
void
PASCAL
lineMakeCallPostProcess(
PASYNCEVENTMSG pMsg
);
LONG
WINAPI
AllocClientResources(
DWORD dwErrorClass
);
LONG
WINAPI
ReAllocClientResources(
DWORD dwErrorClass
);
BOOL
WINAPI
_CRT_INIT(
HINSTANCE hDLL,
DWORD dwReason,
LPVOID lpReserved
);
LONG
CreateHiddenWindow(
HWND *lphwnd,
DWORD dwErrorClass
);
void
FreeInitData(
PINIT_DATA pInitData
);
LONG
WINAPI
FreeClientResources(
void
);
LONG
CALLBACK
TUISPIDLLCallback(
DWORD dwObjectID,
DWORD dwObjectType,
LPVOID lpParams,
DWORD dwSize
);
BOOL
CALLBACK
TranslateDlgProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
);
void
UIThread(
LPVOID pParams
);
char *
PASCAL
MapResultCodeToText(
LONG lResult,
char *pszResult
);
void
PASCAL
lineDevSpecificPostProcess(
PASYNCEVENTMSG pMsg
);
BOOL
WaveStringIdToDeviceId(
LPWSTR pwszStringID,
LPCWSTR pwszDeviceType,
LPDWORD pdwDeviceId
);
LONG
PASCAL
xxxShutdown(
HLINEAPP hXXXApp,
BOOL bLineShutdown
);
LONG
PASCAL
xxxGetMessage(
BOOL bLine,
HLINEAPP hLineApp,
LPLINEMESSAGE pMsg,
DWORD dwTimeout
);
void
PASCAL
lineGetAgentActivityListAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineCompleteCallPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGatherDigitsPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGatherDigitsWPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGetAgentCapsAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGetAgentGroupListAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGetQueueListAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineGetAgentStatusAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineParkAPostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
lineSetupConferencePostProcess(
PASYNCEVENTMSG pMsg
);
void
PASCAL
phoneDevSpecificPostProcess(
PASYNCEVENTMSG pMsg
);
POSTPROCESSPROC gPostProcessingFunctions[] =
{
NULL,
lineGetAgentActivityListAPostProcess,
lineCompleteCallPostProcess,
lineDevSpecificPostProcess,
lineGatherDigitsPostProcess,
lineGatherDigitsWPostProcess,
lineGetAgentCapsAPostProcess,
lineGetAgentGroupListAPostProcess,
lineGetAgentStatusAPostProcess,
lineGetQueueListAPostProcess,
lineMakeCallPostProcess,
lineParkAPostProcess,
lineSetupConferencePostProcess,
phoneDevSpecificPostProcess
};
//
// The code...
//
/////////////////////////////////////
//
// GetFunctionIndex
//
// find the array index of the function.
//
// returns 0 if the function was not found in the array
//
DWORD GetFunctionIndex(POSTPROCESSPROC Function)
{
int i;
const int nArraySize =
sizeof(gPostProcessingFunctions)/sizeof(POSTPROCESSPROC);
for (i = 0; i < nArraySize; i++)
{
if (Function == gPostProcessingFunctions[i])
{
break;
}
}
//
// the function that is passed in had better be in the array. if not -- this should be caught in testing!
//
#if DBG
if (0 == i)
{
DebugBreak ();
}
#endif
if (i == nArraySize)
{
LOG((TL_ERROR,
"GetFunctionIndex: function %p is not found in the array of functions!",
Function));
i = 0;
}
LOG((TL_ERROR,
"GetFunctionIndex: function %p mapped to index %d.", Function, i));
return i;
}
PWSTR
PASCAL
NotSoWideStringToWideString(
LPCSTR lpStr,
DWORD dwLength
)
{
DWORD dwSize;
PWSTR pwStr;
if (IsBadStringPtrA (lpStr, dwLength))
{
return NULL;
}
dwSize = MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpStr,
dwLength,
NULL,
0
);
pwStr = ClientAlloc( dwSize * sizeof(WCHAR) );
if (NULL != pwStr)
{
MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpStr,
dwLength,
pwStr,
dwSize
);
}
return pwStr;
}
//
//NOTE: This function requires that lpBase is a pointer to the start of
// a TAPI struct that has dwTotalSize as the first DWORD
//
void
PASCAL
WideStringToNotSoWideString(
LPBYTE lpBase,
LPDWORD lpdwXxxSize
)
{
DWORD dwSize;
DWORD dwNewSize;
DWORD dwOffset;
DWORD dwTotalSize;
DWORD dwUsedSize;
PWSTR pString;
char szStackBuf[64];
PSTR lpszStringA;
if ((dwSize = *lpdwXxxSize) != 0)
{
dwTotalSize = *((LPDWORD) lpBase);
dwUsedSize = *(((LPDWORD) lpBase)+2);
dwOffset = *(lpdwXxxSize + 1);
pString = (PWSTR)(lpBase + dwOffset);
if (TAPIIsBadStringPtrW (pString, dwSize))
{
LOG((TL_ERROR,
"The service provider returned an invalid field " \
"in the structure 0x%p : 0x%p",
lpBase,
lpdwXxxSize
));
*lpdwXxxSize = 0;
*(lpdwXxxSize+1) = 0;
return;
}
//
// Did we get enough chars?
//
if (dwUsedSize > dwOffset )
{
dwNewSize = WideCharToMultiByte(
GetACP(),
0,
pString,
( dwUsedSize >= (dwOffset+dwSize)) ?
(dwSize/sizeof(WCHAR)) :
(dwUsedSize - dwOffset) / sizeof(WCHAR),
NULL,
0,
NULL,
NULL
);
lpszStringA = (dwNewSize <= sizeof (szStackBuf) ?
(PSTR) szStackBuf : ClientAlloc (dwNewSize) );
if ( NULL == lpszStringA )
{
*lpdwXxxSize = 0;
*(lpdwXxxSize+1) = 0;
return;
}
WideCharToMultiByte(
GetACP(),
0,
pString,
// dwSize,
( dwUsedSize >= (dwOffset+dwSize)) ?
(dwSize/sizeof(WCHAR)) :
(dwUsedSize - dwOffset) / sizeof(WCHAR),
lpszStringA,
dwNewSize,
NULL,
NULL
);
//
// Copy the new ANSI string back to where the Unicode string was
// // and write out NULL terminator if possible.
//
CopyMemory ( (LPBYTE) pString,
lpszStringA,
dwNewSize // + (
// ((dwNewSize + dwOffset) < dwUsedSize ) ?
// 1 :
// 0
// )
);
if (lpszStringA != (PSTR) szStackBuf)
{
ClientFree (lpszStringA);
}
//
// Update the number of bytes
//
*lpdwXxxSize = dwNewSize;
}
}
}
VOID
CALLBACK
FreeContextCallback(
LPVOID Context,
LPVOID Context2
)
{
//ClientFree (Context);
}
BOOL
WINAPI
DllMain(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
static DWORD dwInitFlags;
const DWORD dwInitgCriticalSection = 0x1;
const DWORD dwInitgUICriticalSection = 0x2;
const DWORD dwInitgTlsCriticalSection = 0x4;
const DWORD dwInitcsMemoryList = 0x8;
const DWORD dwInitTapiCrypt = 0x10;
const DWORD dwInitFusion = 0x20;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
dwInitFlags = 0;
g_hInst = hDLL;
InitializeListHead (&gTlsListHead);
if (!SHFusionInitializeFromModuleID (hDLL,124))
{
return FALSE;
}
dwInitFlags |= dwInitFusion;
gdwInitialTickCount = GetTickCount();
ghHandleTable = CreateHandleTable(
GetProcessHeap(),
FreeContextCallback,
0x80000000,
0x8fffffff
);
if (NULL == ghHandleTable)
{
return FALSE;
}
//
// Init CRT
//
if (!_CRT_INIT (hDLL, dwReason, lpReserved))
{
return FALSE;
}
{
HKEY hKey;
#if DBG
gdwDebugLevel = 0;
#endif
gdwMaxNumRequestRetries = 40;
gdwRequestRetryTimeout = 250; // milliseconds
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_READ,
&hKey
) == ERROR_SUCCESS)
{
DWORD dwDataSize = sizeof(DWORD), dwDataType;
#if DBG
RegQueryValueEx(
hKey,
gszTapi32DebugLevel,
0,
&dwDataType,
(LPBYTE) &gdwDebugLevel,
&dwDataSize
);
dwDataSize = sizeof(DWORD);
#endif
RegQueryValueEx(
hKey,
gszTapi32MaxNumRequestRetries,
0,
&dwDataType,
(LPBYTE) &gdwMaxNumRequestRetries,
&dwDataSize
);
RegQueryValueEx(
hKey,
gszTapi32RequestRetryTimeout,
0,
&dwDataType,
(LPBYTE) &gdwRequestRetryTimeout,
&dwDataSize
);
RegCloseKey (hKey);
}
}
//
// Alloc a Tls index
//
if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff ||
(gdwTlsIndexRpcCtx = TlsAlloc()) == 0xffffffff)
{
return FALSE;
}
//
// Initialize Tls to NULL for this thread
//
TlsSetValue (gdwTlsIndex, NULL);
TlsSetValue (gdwTlsIndexRpcCtx, NULL);
//
//
//
ghInitMutex = CreateMutex (NULL, FALSE, NULL);
try
{
InitializeCriticalSection (&gCriticalSection);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
dwInitFlags |= dwInitgCriticalSection;
try
{
InitializeCriticalSection (&gUICriticalSection);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
dwInitFlags |= dwInitgUICriticalSection;
try
{
InitializeCriticalSection (&gTlsCriticalSection);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
dwInitFlags |= dwInitgTlsCriticalSection;
#if DBG
try
{
InitializeCriticalSection( &csMemoryList);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
dwInitFlags |= dwInitcsMemoryList;
#endif
ListNodePoolsInitialize();
if (ERROR_SUCCESS != TapiCryptInit())
{
return FALSE;
}
dwInitFlags |= dwInitTapiCrypt;
break;
}
case DLL_PROCESS_DETACH:
{
PCLIENT_THREAD_INFO pTls;
//
// Clean up any Tls (no need to enter crit sec since process detaching)
//
while (!IsListEmpty (&gTlsListHead))
{
LIST_ENTRY *pEntry = RemoveHeadList (&gTlsListHead);
pTls = CONTAINING_RECORD (pEntry, CLIENT_THREAD_INFO, TlsList);
ClientFree (pTls->pBuf);
ClientFree (pTls);
}
//
// If gpAsyncEventsThreadParams is non-NULL it means the AsyncEventsThread
// is still running (an ill-behaved app is trying to unload us
// without calling shutdown) so go thru the motions of getting
// the thread to terminate (like we do in xxxShutdown)
//
// Otherwise close our handle to the shared event
//
if (gpAsyncEventsThreadParams)
{
gpAsyncEventsThreadParams->bExitThread = TRUE;
SetEvent (ghAsyncEventsEvent);
gpAsyncEventsThreadParams = NULL;
gdwNumInits = 0;
}
else if (gphCx && ghAsyncEventsEvent)
{
CloseHandle (ghAsyncEventsEvent);
ghAsyncEventsEvent = NULL;
}
//
// Free up any other resources we were using
//
if (ghWow32Dll)
{
FreeLibrary (ghWow32Dll);
ghWow32Dll = NULL;
}
TlsFree (gdwTlsIndex);
TlsFree (gdwTlsIndexRpcCtx);
_CRT_INIT (hDLL, dwReason, lpReserved);
if (ghInitMutex) CloseHandle (ghInitMutex);
if (dwInitFlags & dwInitgCriticalSection)
DeleteCriticalSection (&gCriticalSection);
if (dwInitFlags & dwInitgUICriticalSection)
DeleteCriticalSection (&gUICriticalSection);
if (dwInitFlags & dwInitgTlsCriticalSection)
DeleteCriticalSection (&gTlsCriticalSection);
#if DBG
DumpMemoryList();
if (dwInitFlags & dwInitcsMemoryList)
DeleteCriticalSection( &csMemoryList);
#endif
if (dwInitFlags & dwInitTapiCrypt)
TapiCryptShutdown();
ListNodePoolsUninitialize();
DeleteHandleTable (ghHandleTable);
if (dwInitFlags & dwInitFusion)
SHFusionUninitialize();
break;
}
case DLL_THREAD_ATTACH:
//
// First must init CRT
//
if (!_CRT_INIT (hDLL, dwReason, lpReserved))
{
return FALSE;
}
//
// 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)))
{
EnterCriticalSection (&gTlsCriticalSection);
RemoveEntryList (&pTls->TlsList);
LeaveCriticalSection (&gTlsCriticalSection);
if (pTls->pBuf)
{
ClientFree (pTls->pBuf);
}
ClientFree (pTls);
}
//
// Finally, alert CRT
//
_CRT_INIT (hDLL, dwReason, lpReserved);
break;
}
} // switch
return TRUE;
}
BOOL
IsLeastCostRoutingEnabled(
void
)
{
static BOOL bInited = FALSE, bEnabled = FALSE;
HKEY hKey;
TCHAR szPath[MAX_PATH];
DWORD dwDataSize, dwDataType;
HANDLE hDll;
if (!bInited)
{
//
// Check the registry to see if there's an LCR DLL registered
//
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_QUERY_VALUE,
&hKey
) == ERROR_SUCCESS)
{
dwDataSize = sizeof (szPath);
szPath[0] = 0;
if (RegQueryValueEx(
hKey,
gszLCRDLL,
0,
&dwDataType,
(LPBYTE) szPath,
&dwDataSize
) == ERROR_SUCCESS)
{
//
// Try to load the LCR DLL.
//
// Note that we will never explicitly free the DLL,
// since there is no well-defined time at which we'd
// know to free it. (Apps can can lineTranslateAddress
// without having done a lineInitialize(Ex), so that
// could happen at any time between us being loaded
// & unloaded, and doing Load/FreeLibrary from within
// a DLLEntryPoint is not a good idea)
//
if ((hDll = LoadLibrary (szPath)))
{
//
// Get the hook addresses & increment our own ref
// count (via LoadLibrary) so we'll never get
// unloaded (since we never unload the LCR DLL
// it might call back in to us at any time, & if
// an app unloaded us that would be a problem)
//
if (hDll)
{
(FARPROC) pfnLineOpenWLCR = GetProcAddress(
hDll,
"lineOpenW"
);
(FARPROC) pfnLineOpenALCR = GetProcAddress(
hDll,
"lineOpenA"
);
(FARPROC) pfnLineTranslateAddressWLCR = GetProcAddress(
hDll,
"lineTranslateAddressW"
);
if (pfnLineOpenWLCR ||
pfnLineOpenALCR ||
pfnLineTranslateAddressWLCR)
{
LoadLibrary (TEXT("tapi32"));
bEnabled = TRUE;
}
}
}
else
{
LOG((TL_ERROR,
"IsLeastCostRoutingEnabled: LoadLibrary() " \
"failed, err=%d",
GetLastError()
));
}
}
RegCloseKey (hKey);
}
bInited = TRUE;
}
return bEnabled;
}
void
AsyncEventsThread(
PASYNC_EVENTS_THREAD_PARAMS pAsyncEventsThreadParams
);
void NonAsyncEventThread( void )
{
if ( gpAsyncEventsThreadParams )
AsyncEventsThread( (LPVOID) gpAsyncEventsThreadParams );
}
void
AsyncEventsThread(
PASYNC_EVENTS_THREAD_PARAMS pAsyncEventsThreadParams
)
{
BOOL *pbExitThread = &pAsyncEventsThreadParams->bExitThread,
bRetry;
DWORD dwBufSize = pAsyncEventsThreadParams->dwBufSize;
LPBYTE pBuf = pAsyncEventsThreadParams->pBuf;
PTAPI32_MSG pMsg = (PTAPI32_MSG) pBuf;
LOG((TL_TRACE, "AsyncEventsThread: enter"));
//
// Just loop reading async events/completions from server &
// handling them
//
while (1)
{
DWORD dwUsedSize, dwNeededSize;
ASYNC_EVENT_PARAMS AsyncEventParams;
PASYNCEVENTMSG pAsyncEventMsg;
HANDLE hAsyncEvents = NULL;
HANDLE hProcess = GetCurrentProcess();
//
// Check to see if xxxShutdown or DllMain
// is signaling us to exit
// Also we need to deal with an event setting/resetting
// race condition between FreeClientResources & Tapisrv)
//
EnterCriticalSection (&gCriticalSection);
if (*pbExitThread)
{
LeaveCriticalSection (&gCriticalSection);
break;
}
LeaveCriticalSection (&gCriticalSection);
// Acquire ghInitMutex to serialize with FreeClientResources and ReallocClientResources
WaitForSingleObject (ghInitMutex, INFINITE);
if (*pbExitThread)
{
ReleaseMutex (ghInitMutex);
break;
}
// if here, ghAsyncEventsEvent should not be NULL
if (!DuplicateHandle (
hProcess,
ghAsyncEventsEvent,
hProcess,
&hAsyncEvents,
0,
FALSE,
DUPLICATE_SAME_ACCESS
))
{
LOG((TL_ERROR, "DuplicateHandle failed with 0x%x", GetLastError()));
}
ReleaseMutex (ghInitMutex);
//
// Block until tapisrv signals us that it has some event data for us
//
if (hAsyncEvents)
{
WaitForSingleObject (hAsyncEvents, INFINITE);
CloseHandle (hAsyncEvents);
}
//
// Check to see if xxxShutdown or DllMain
// is signaling us to exit
//
if (*pbExitThread)
{
break;
}
//
// Retrieve the data from tapisrv
//
AsyncEventsThread_clientRequest:
do
{
pMsg->u.Req_Func = xGetAsyncEvents;
pMsg->Params[0] = dwBufSize - sizeof (TAPI32_MSG);
dwUsedSize = sizeof (TAPI32_MSG);
// Acquire ghInitMutex to serialize with FreeClientResources so we prevent
// the RPC Context handle from being destroyed while the request is in progress
WaitForSingleObject (ghInitMutex, INFINITE);
RpcTryExcept
{
ClientRequest (gphCx, (char *) pMsg, dwBufSize, &dwUsedSize);
bRetry = FALSE;
}
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
{
bRetry = !(*pbExitThread);
LOG((TL_INFO,
"AsyncEventsThread: rpc exception %d handled",
RpcExceptionCode()
));
Sleep (10);
}
RpcEndExcept
ReleaseMutex (ghInitMutex);
} while (bRetry);
#if DBG
if (
( dwUsedSize > dwBufSize )
||
( pMsg->Params[2] > dwBufSize )
)
{
LOG((TL_ERROR, "OVERFLOW!!!"));
LOG((TL_ERROR, "Watch this..."));
ClientFree( ClientAlloc( 0x10000 ) );
}
#endif
if ((dwUsedSize = (DWORD) pMsg->Params[2]) == 0 &&
(dwNeededSize = (DWORD) pMsg->Params[1]) != 0)
{
//
// There's a msg waiting for us that is bigger than our buffer,
// so alloc a larger buffer & try again
//
LPBYTE pNewBuf;
LOG((TL_INFO,
"AsyncEventsThread: allocating larger event buf (size=x%x)",
dwNeededSize
));
dwNeededSize += sizeof (TAPI32_MSG) + 128;
if (!(pNewBuf = ClientAlloc (dwNeededSize)))
{
goto AsyncEventsThread_clientRequest;
}
dwBufSize = dwNeededSize;
ClientFree (pBuf);
pBuf = pNewBuf;
pMsg = (PTAPI32_MSG) pBuf;
goto AsyncEventsThread_clientRequest;
}
//
// Handle the events
//
pAsyncEventMsg = (PASYNCEVENTMSG) (pBuf + sizeof (TAPI32_MSG));
while (dwUsedSize)
{
PINIT_DATA pInitData = (PINIT_DATA)ReferenceObject (ghHandleTable, pAsyncEventMsg->InitContext, INITDATA_KEY);
if (NULL == pInitData)
{
// There is something very wrong with this
// message. Skip to the next one.
goto AsyncEventsThread_nextMessage;
}
#ifdef _WIN64
// For win64 we need to convert DWORDs to ULONG_PTRs (64 bit values)
AsyncEventParams.hDevice = pAsyncEventMsg->hDevice;
AsyncEventParams.dwMsg = pAsyncEventMsg->Msg;
AsyncEventParams.dwCallbackInstance = pAsyncEventMsg->OpenContext;
AsyncEventParams.dwParam1 = pAsyncEventMsg->Param1;
AsyncEventParams.dwParam2 = pAsyncEventMsg->Param2;
AsyncEventParams.dwParam3 = pAsyncEventMsg->Param3;
#else // not _WIN64
CopyMemory (&AsyncEventParams.hDevice,
&pAsyncEventMsg->hDevice,
sizeof (ASYNC_EVENT_PARAMS));
#endif // _WIN64
switch (pAsyncEventMsg->Msg)
{
case LINE_REMOVE:
case PHONE_REMOVE:
case LINE_CREATE:
case LINE_REQUEST:
case PHONE_CREATE:
// For all messages EXCEPT these, pAsyncEventMsg is a handle
// to the callbackInstance value passed in line/phoneOpen.
// For these messages, do nothing!
break;
default:
// We need to get the CallbackInstance value back.
if (0 != pAsyncEventMsg->OpenContext)
{
AsyncEventParams.dwCallbackInstance = (ULONG_PTR)
ReferenceObject (ghHandleTable, pAsyncEventMsg->OpenContext, 0);
DereferenceObject (ghHandleTable, pAsyncEventMsg->OpenContext, 1);
if (LINE_CLOSE == pAsyncEventMsg->Msg ||
PHONE_CLOSE == pAsyncEventMsg->Msg)
{
// for these messages, we need to get rid of
// the handle to the callback instance, so
// dereference it once more.
DereferenceObject (ghHandleTable, pAsyncEventMsg->OpenContext, 1);
}
}
}
LOG((TL_INFO,
"AsyncEventsThread: msg=%d, hDev=x%x, p1=x%x, p2=x%x, p3=x%x",
AsyncEventParams.dwMsg,
AsyncEventParams.hDevice,
AsyncEventParams.dwParam1,
AsyncEventParams.dwParam2,
AsyncEventParams.dwParam3
));
//
// Special case for UI msgs (not fwd'd to client)
//
switch (pAsyncEventMsg->Msg)
{
case LINE_CREATEDIALOGINSTANCE:
{
DWORD dwThreadID,
dwDataOffset = pAsyncEventMsg->Param1,
dwDataSize = pAsyncEventMsg->Param2,
dwUIDllNameOffset = pAsyncEventMsg->Param3;
PUITHREADDATA pUIThreadData;
if (!(pUIThreadData = ClientAlloc (sizeof (UITHREADDATA))))
{
goto LINE_CREATEDIALOGINSTANCE_error;
}
if ((pUIThreadData->dwSize = dwDataSize) != 0)
{
if (!(pUIThreadData->pParams = ClientAlloc (dwDataSize)))
{
goto LINE_CREATEDIALOGINSTANCE_error;
}
CopyMemory(
pUIThreadData->pParams,
((LPBYTE)pAsyncEventMsg) + dwDataOffset,
dwDataSize
);
}
if (!(pUIThreadData->hUIDll = TAPILoadLibraryW(
(PWSTR)(((LPBYTE) pAsyncEventMsg) +
dwUIDllNameOffset)
)))
{
LOG((TL_ERROR,
"LoadLibraryW(%ls) failed, err=%d",
((LPBYTE)pAsyncEventMsg + dwUIDllNameOffset),
GetLastError()
));
goto LINE_CREATEDIALOGINSTANCE_error;
}
if (!(pUIThreadData->pfnTUISPI_providerGenericDialog =
(TUISPIPROC) GetProcAddress(
pUIThreadData->hUIDll,
(LPCSTR) gszTUISPI_providerGenericDialog
)))
{
LOG((TL_ERROR,
"GetProcAddr(TUISPI_providerGenericDialog) failed"
));
goto LINE_CREATEDIALOGINSTANCE_error;
}
pUIThreadData->pfnTUISPI_providerGenericDialogData =
(TUISPIPROC) GetProcAddress(
pUIThreadData->hUIDll,
(LPCSTR) gszTUISPI_providerGenericDialogData
);
if (!(pUIThreadData->hEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) NULL,
TRUE, // manual reset
FALSE, // non-signaled
NULL // unnamed
)))
{
goto LINE_CREATEDIALOGINSTANCE_error;
}
pUIThreadData->htDlgInst = (HTAPIDIALOGINSTANCE)
pAsyncEventMsg->hDevice;
//
// Safely add this instance to the global list
// (check if gdwNumInits == 0, & if so fail)
//
EnterCriticalSection (&gCriticalSection);
if (gdwNumInits != 0)
{
if ((pUIThreadData->pNext = gpUIThreadInstances))
{
pUIThreadData->pNext->pPrev = pUIThreadData;
}
gpUIThreadInstances = pUIThreadData;
LeaveCriticalSection (&gCriticalSection);
}
else
{
LeaveCriticalSection (&gCriticalSection);
goto LINE_CREATEDIALOGINSTANCE_error;
}
if ((pUIThreadData->hThread = CreateThread(
(LPSECURITY_ATTRIBUTES) NULL,
0,
(LPTHREAD_START_ROUTINE) UIThread,
(LPVOID) pUIThreadData,
0,
&dwThreadID
)))
{
goto AsyncEventsThread_decrUsedSize;
}
//
// If here an error occured, so safely remove the ui
// thread data struct from the global list
//
EnterCriticalSection (&gCriticalSection);
if (pUIThreadData->pNext)
{
pUIThreadData->pNext->pPrev = pUIThreadData->pPrev;
}
if (pUIThreadData->pPrev)
{
pUIThreadData->pPrev->pNext = pUIThreadData->pNext;
}
else
{
gpUIThreadInstances = pUIThreadData->pNext;
}
LeaveCriticalSection (&gCriticalSection);
LINE_CREATEDIALOGINSTANCE_error:
if (pUIThreadData)
{
if (pUIThreadData->pParams)
{
ClientFree (pUIThreadData->pParams);
}
if (pUIThreadData->hUIDll)
{
FreeLibrary (pUIThreadData->hUIDll);
}
if (pUIThreadData->hEvent)
{
CloseHandle (pUIThreadData->hEvent);
}
ClientFree (pUIThreadData);
}
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, xFreeDialogInstance),
{
(DWORD) pAsyncEventMsg->hDevice
},
{
Dword
}
};
DOFUNC (&funcArgs, "FreeDialogInstance");
}
goto AsyncEventsThread_decrUsedSize;
}
case LINE_SENDDIALOGINSTANCEDATA:
{
PUITHREADDATA pUIThreadData = gpUIThreadInstances;
HTAPIDIALOGINSTANCE htDlgInst = (HTAPIDIALOGINSTANCE)
pAsyncEventMsg->hDevice;
EnterCriticalSection (&gCriticalSection);
while (pUIThreadData)
{
if (pUIThreadData->htDlgInst == htDlgInst)
{
WaitForSingleObject (pUIThreadData->hEvent, INFINITE);
(*pUIThreadData->pfnTUISPI_providerGenericDialogData)(
htDlgInst,
((LPBYTE) pAsyncEventMsg) +
pAsyncEventMsg->Param1, // data offset
pAsyncEventMsg->Param2 // data size
);
break;
}
pUIThreadData = pUIThreadData->pNext;
}
LeaveCriticalSection (&gCriticalSection);
goto AsyncEventsThread_decrUsedSize;
}
}
//
// Enter the critical section so we've exclusive access
// to the init data, & verify it
//
EnterCriticalSection (&gCriticalSection);
try
{
#if defined(_M_IX86) && _MSC_FULL_VER <= 13008806
DWORD dw= pInitData->dwKey; // workaround compiler bug.
if (dw != INITDATA_KEY)
#else
if (pInitData->dwKey != INITDATA_KEY)
#endif
{
LOG((TL_ERROR, "Bad pInitInst, discarding msg"));
goto AsyncEventsThread_leaveCritSec;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
goto AsyncEventsThread_leaveCritSec;
}
//
// Special case for PROXYREQUEST
//
if (pAsyncEventMsg->Msg == LINE_PROXYREQUEST)
{
PPROXYREQUESTHEADER pProxyRequestHeader;
LPLINEPROXYREQUEST pProxyRequest = (LPLINEPROXYREQUEST)
(pAsyncEventMsg + 1),
pProxyRequestApp;
switch (pProxyRequest->dwRequestType)
{
case LINEPROXYREQUEST_SETAGENTGROUP:
case LINEPROXYREQUEST_SETAGENTSTATE:
case LINEPROXYREQUEST_SETAGENTACTIVITY:
case LINEPROXYREQUEST_AGENTSPECIFIC:
case LINEPROXYREQUEST_CREATEAGENT:
case LINEPROXYREQUEST_CREATEAGENTSESSION:
case LINEPROXYREQUEST_SETAGENTMEASUREMENTPERIOD:
case LINEPROXYREQUEST_SETAGENTSESSIONSTATE:
case LINEPROXYREQUEST_SETQUEUEMEASUREMENTPERIOD:
case LINEPROXYREQUEST_SETAGENTSTATEEX:
//
// For these msgs the proxy request as received from
// the tapisrv already contains the exact bits we want
// to pass on to the app, so we just alloc a buffer of
// the same size (plus a little extra for the key at
// the head of the buffer) and copy the data to it
//
if (!(pProxyRequestHeader = ClientAlloc(
sizeof (PROXYREQUESTHEADER) + pProxyRequest->dwSize
)))
{
// Could not allocate memory;
// skip this...
goto AsyncEventsThread_leaveCritSec;
}
pProxyRequestApp = (LPLINEPROXYREQUEST)
(pProxyRequestHeader + 1);
CopyMemory(
pProxyRequestApp,
pProxyRequest,
pProxyRequest->dwSize
);
break;
case LINEPROXYREQUEST_GETAGENTCAPS:
case LINEPROXYREQUEST_GETAGENTSTATUS:
case LINEPROXYREQUEST_GETAGENTACTIVITYLIST:
case LINEPROXYREQUEST_GETAGENTGROUPLIST:
case LINEPROXYREQUEST_GETQUEUEINFO:
case LINEPROXYREQUEST_GETGROUPLIST:
case LINEPROXYREQUEST_GETQUEUELIST:
case LINEPROXYREQUEST_GETAGENTINFO:
case LINEPROXYREQUEST_GETAGENTSESSIONINFO:
case LINEPROXYREQUEST_GETAGENTSESSIONLIST:
{
DWORD dwSizeToCopy = 0;
//
// For these msgs tapisrv only embedded the dwTotalSize
// field of the corresponding structure (to save having
// to send us a bunch of unused bits), so we want to
// increase the pProxyRequest->dwSize by the dwTotalSize
// - sizeof (DWORD), alloc a buffer (including a little
// extra space for the key at the head of the buffer),
// and rebuild the request
//
if ( pProxyRequest->dwRequestType ==
LINEPROXYREQUEST_GETGROUPLIST )
{
pProxyRequest->dwSize +=
(pProxyRequest->GetGroupList.GroupList.dwTotalSize)&TALIGN_MASK;
dwSizeToCopy = 8 * sizeof(DWORD);
}
else if ( pProxyRequest->dwRequestType ==
LINEPROXYREQUEST_GETQUEUELIST )
{
pProxyRequest->dwSize +=
(pProxyRequest->GetQueueList.QueueList.dwTotalSize)&TALIGN_MASK;
dwSizeToCopy = 8 * sizeof(DWORD) + sizeof(GUID);
}
else
{
//
// all of the rest of the structures have the
// same format
//
pProxyRequest->dwSize +=
(pProxyRequest->GetAgentCaps.AgentCaps.dwTotalSize)&TALIGN_MASK;
dwSizeToCopy = 9 * sizeof(DWORD);
}
if (!(pProxyRequestHeader = ClientAlloc(
sizeof (PROXYREQUESTHEADER) + pProxyRequest->dwSize
+ sizeof(DWORD) + sizeof(DWORD)
)))
{
// Could not allocate memory;
// skip this...
goto AsyncEventsThread_leaveCritSec;
}
pProxyRequestApp = (LPLINEPROXYREQUEST)
(pProxyRequestHeader + 1);
//
// The following will copy the non-union fields in the
// proxy message, as well as the first two DWORD in the
// union (which currently are the dwAddressID and the
// dwTotalSize field of the corresponding structure)
//
CopyMemory(
pProxyRequestApp,
pProxyRequest,
dwSizeToCopy
);
//
// Relocate the machine & user names to the end of the
// structure
//
pProxyRequestApp->dwClientMachineNameOffset =
pProxyRequest->dwSize -
pProxyRequest->dwClientMachineNameSize;
wcscpy(
(WCHAR *)(((LPBYTE) pProxyRequestApp) +
pProxyRequestApp->dwClientMachineNameOffset),
(WCHAR *)(((LPBYTE) pProxyRequest) +
pProxyRequest->dwClientMachineNameOffset)
);
pProxyRequestApp->dwClientUserNameOffset =
pProxyRequestApp->dwClientMachineNameOffset -
pProxyRequest->dwClientUserNameSize;
wcscpy(
(WCHAR *)(((LPBYTE) pProxyRequestApp) +
pProxyRequestApp->dwClientUserNameOffset),
(WCHAR *)(((LPBYTE) pProxyRequest) +
pProxyRequest->dwClientUserNameOffset)
);
break;
}
}
pProxyRequestHeader->dwKey = TPROXYREQUESTHEADER_KEY;
pProxyRequestHeader->dwInstance = pAsyncEventMsg->Param1;
AsyncEventParams.dwParam1 = (ULONG_PTR) pProxyRequestApp;
}
//
// Call the post processing proc if there is one
//
if (pAsyncEventMsg->fnPostProcessProcHandle)
{
(*(gPostProcessingFunctions[
pAsyncEventMsg->fnPostProcessProcHandle]))(pAsyncEventMsg);
}
//
// If this init instance is using a completion port then
// alloc msg struct & post the msg to the completion port,
// then jump down below to exit the critsec, etc
//
if ((pInitData->dwInitOptions & 0x3) ==
LINEINITIALIZEEXOPTION_USECOMPLETIONPORT)
{
LPLINEMESSAGE pMsg;
if ((pMsg = LocalAlloc (LMEM_FIXED, sizeof(LINEMESSAGE))))
{
CopyMemory (pMsg, &AsyncEventParams, sizeof(LINEMESSAGE));
if (gpPostQueuedCompletionStatus &&
!gpPostQueuedCompletionStatus(
pInitData->hCompletionPort,
sizeof (LINEMESSAGE),
pInitData->dwCompletionKey,
(LPOVERLAPPED) pMsg
))
{
LocalFree (pMsg);
LOG((TL_ERROR,
"AsyncEventsThread: PostQueuedCompletionStatus " \
"failed, err=%d",
GetLastError()
));
}
else
{
LOG((TL_INFO,
"AsyncEventsThread: posted complPort msg\n",
"\thDev=x%x, ctx=x%x, p1=x%x, p2=x%x, p3=x%x",
AsyncEventParams.hDevice,
AsyncEventParams.dwCallbackInstance,
AsyncEventParams.dwParam1,
AsyncEventParams.dwParam2,
AsyncEventParams.dwParam3
));
}
}
goto AsyncEventsThread_leaveCritSec;
}
//
// See if we need to increase the msg queue size, and if
// so alloc a new buf, copy the existing msgs over (careful
// to preserve order in a wrapped buffer), free the old buf
// and reset the appropriate fields in the init data struct
//
if (pInitData->dwNumTotalEntries ==
pInitData->dwNumUsedEntries)
{
DWORD dwNumTotalEntries =
pInitData->dwNumTotalEntries;
PASYNC_EVENT_PARAMS pNewEventBuffer;
if ((pNewEventBuffer = ClientAlloc(
2 * dwNumTotalEntries * sizeof (ASYNC_EVENT_PARAMS)
)))
{
DWORD dwNumWrappedEntries = (DWORD)
(pInitData->pValidEntry -
pInitData->pEventBuffer);
CopyMemory(
pNewEventBuffer,
pInitData->pValidEntry,
(dwNumTotalEntries - dwNumWrappedEntries)
* sizeof (ASYNC_EVENT_PARAMS)
);
if (dwNumWrappedEntries)
{
CopyMemory(
pNewEventBuffer +
(dwNumTotalEntries - dwNumWrappedEntries),
pInitData->pEventBuffer,
dwNumWrappedEntries * sizeof (ASYNC_EVENT_PARAMS)
);
}
ClientFree (pInitData->pEventBuffer);
pInitData->pEventBuffer =
pInitData->pValidEntry = pNewEventBuffer;
pInitData->pFreeEntry =
pNewEventBuffer + dwNumTotalEntries;
pInitData->dwNumTotalEntries *= 2;
}
else
{
// Could not allocate memory,
// skip this message...
goto AsyncEventsThread_leaveCritSec;
}
}
//
// Copy the msg to the hidden window's msg queue,
// and update that queue's pointers
//
CopyMemory(
pInitData->pFreeEntry,
&AsyncEventParams,
sizeof (ASYNC_EVENT_PARAMS)
);
pInitData->dwNumUsedEntries++;
pInitData->pFreeEntry++;
if (pInitData->pFreeEntry >= (pInitData->pEventBuffer +
pInitData->dwNumTotalEntries))
{
pInitData->pFreeEntry = pInitData->pEventBuffer;
}
//
// If this init instance is using events for msg notification
// then see if we need to signal the app that there's an
// event waiting for it
//
// Else, post a msg to the hidden window (if there's not
// already one outstanding) to alert it that there's some
// events it needs to pass on to the app's callback
//
if ((pInitData->dwInitOptions & 0x3)
== LINEINITIALIZEEXOPTION_USEEVENT)
{
if (pInitData->dwNumUsedEntries > 0)
{
SetEvent (pInitData->hEvent);
}
}
else // HIDDENWINDOW
{
if (pInitData->bPendingAsyncEventMsg == FALSE)
{
LOG((TL_INFO,
"AsyncEventsThread: posting msg, hwnd=x%lx",
pInitData->hwnd
));
PostMessage(
pInitData->hwnd,
WM_ASYNCEVENT,
0,
(LPARAM) pInitData
);
pInitData->bPendingAsyncEventMsg = TRUE;
}
}
AsyncEventsThread_leaveCritSec:
LeaveCriticalSection (&gCriticalSection);
AsyncEventsThread_decrUsedSize:
DereferenceObject (ghHandleTable, pAsyncEventMsg->InitContext, 1);
AsyncEventsThread_nextMessage:
dwUsedSize -= (DWORD) pAsyncEventMsg->TotalSize;
pAsyncEventMsg = (PASYNCEVENTMSG)
((LPBYTE) pAsyncEventMsg + pAsyncEventMsg->TotalSize);
if ( (LONG)dwUsedSize < 0 )
{
LOG((TL_ERROR, "dwUsedSize went negative!!!"));
}
}
}
{
//
// Free our resources, and then exit
//
HANDLE hTapi32 = pAsyncEventsThreadParams->hTapi32;
if (pAsyncEventsThreadParams->hWow32)
{
FreeLibrary (pAsyncEventsThreadParams->hWow32);
}
ClientFree (pBuf);
ClientFree (pAsyncEventsThreadParams);
LOG((TL_TRACE, "AsyncEventsThread: exit"));
FreeLibraryAndExitThread (hTapi32, 0);
}
}
BOOL
PASCAL
IsBadDwordPtr(
LPDWORD p
)
{
//
// Since IsBadWritePtr won't tell us if "p" is not DWORD-aligned (an
// issue on non-x86 platforms), we use the following to determine
// if the pointer is good. Note that DWORD p points at will get
// overwritten on successful completion of the request anyway, so
// preserving the original value is not important.
//
DWORD dwError;
BOOL bRet = FALSE;
try
{
*p = *p + 1;
*p = *p - 1;
}
except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
bRet = TRUE;
}
return bRet;
}
BOOL
WINAPI
GrowBuf(
LPBYTE *ppBuf,
LPDWORD pdwBufSize,
DWORD dwCurrValidBytes,
DWORD dwBytesToAdd
)
{
DWORD dwCurrBufSize, dwNewBufSize;
LPBYTE pNewBuf;
//
// Try to get a new buffer big enough to hold everything
//
for(
dwNewBufSize = 2 * (dwCurrBufSize = *pdwBufSize);
dwNewBufSize < (dwCurrBufSize + dwBytesToAdd);
dwNewBufSize *= 2
);
if (!(pNewBuf = ClientAlloc (dwNewBufSize)))
{
return FALSE;
}
//
// Copy the "valid" bytes in the old buf to the new buf,
// then free the old buf
//
CopyMemory (pNewBuf, *ppBuf, dwCurrValidBytes);
ClientFree (*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)
ClientAlloc (sizeof(CLIENT_THREAD_INFO));
if (!pClientThreadInfo)
{
return NULL;
}
pClientThreadInfo->pBuf = ClientAlloc (INITIAL_CLIENT_THREAD_BUF_SIZE);
if (!pClientThreadInfo->pBuf)
{
ClientFree (pClientThreadInfo);
return NULL;
}
pClientThreadInfo->dwBufSize = INITIAL_CLIENT_THREAD_BUF_SIZE;
TlsSetValue (gdwTlsIndex, (LPVOID) pClientThreadInfo);
EnterCriticalSection (&gTlsCriticalSection);
InsertHeadList (&gTlsListHead, &pClientThreadInfo->TlsList);
LeaveCriticalSection (&gTlsCriticalSection);
}
return pClientThreadInfo;
}
PCONTEXT_HANDLE_TYPE
WINAPI
GetTlsPCtxHandle(
void
)
{
return TlsGetValue (gdwTlsIndexRpcCtx);
}
BOOL
WINAPI
SetTlsPCtxHandle(
PCONTEXT_HANDLE_TYPE phCtxHandle
)
{
return TlsSetValue(gdwTlsIndexRpcCtx, phCtxHandle);
}
#if DBG
LONG
WINAPI
DoFunc(
PFUNC_ARGS pFuncArgs,
char *pszFuncName
)
#else
LONG
WINAPI
DoFunc(
PFUNC_ARGS pFuncArgs
)
#endif
{
DWORD dwFuncClassErrorIndex = (pFuncArgs->Flags & 0x00000030) >> 4;
LONG lResult;
BOOL bCopyOnSuccess = FALSE;
BOOL bResAllocated = FALSE;
DWORD i, j, dwUsedSize, dwNeededSize;
ULONG_PTR value;
PCONTEXT_HANDLE_TYPE phCtx;
PCLIENT_THREAD_INFO pTls;
#if DBG
LOG((TL_TRACE, "About to call %hs", pszFuncName));
#else
LOG((TL_TRACE, "DoFunc -- enter"));
#endif
//
// Check to make sure resources allocated
// (TAPISRV started, pipes opened, etc.)
//
if ( (lResult = AllocClientResources (dwFuncClassErrorIndex))
!= TAPI_SUCCESS)
{
goto DoFunc_return;
}
bResAllocated = TRUE;
//
// Get the tls
//
if (!(pTls = GetTls()))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
//
// The first arg of all async msg blocks is a remote request id; set
// this to zero to indicate that we are a local client (not remotesp)
//
if (pFuncArgs->Flags & ASYNC)
{
((PTAPI32_MSG) pTls->pBuf)->Params[0] = 0;
}
//
// Validate all the func args
//
dwNeededSize = dwUsedSize = ALIGN(sizeof (TAPI32_MSG));
for(
i = 0, j = (pFuncArgs->Flags & ASYNC ? 1 : 0);
i < (pFuncArgs->Flags & NUM_ARGS_MASK);
i++, j++
)
{
value = /*((PTAPI32_MSG) pTls->pBuf)->Params[j] =*/ pFuncArgs->Args[i];
switch (pFuncArgs->ArgTypes[i])
{
case Dword:
((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST(pFuncArgs->Args[i],__FILE__,__LINE__);
continue;
case hXxxApp_NULLOK:
case hXxxApp:
{
//
// Verify that the hXxxApp is a pointer to a valid InitData
// struct, then retrieve the real hXxxApp from that struct.
// If the hXxxApp is bad, pass the server 0xffffffff so that
// it can figure out whether to return an UNINITIALIZED error
// or a INVALAPPHANDLE error.
//
DWORD dwError;
PINIT_DATA pInitData;
if ((0 == pFuncArgs->Args[i]) &&
(hXxxApp_NULLOK == pFuncArgs->ArgTypes[i]))
{
//
// Looks good to me...
//
((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0;
continue;
}
if ((pInitData = (PINIT_DATA) ReferenceObject(
ghHandleTable,
DWORD_CAST(pFuncArgs->Args[i],__FILE__,__LINE__),
INITDATA_KEY
)))
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = pInitData->hXxxApp;
DereferenceObject (ghHandleTable, DWORD_CAST(pFuncArgs->Args[i],__FILE__,__LINE__), 1);
}
else
{
//
// Fill in with a bogus hXxxApp so tapisrv can decide which
// error it wants to return
//
((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0xffffffff;
}
continue;
}
case Hwnd:
if (!IsWindow ((HWND) value))
{
LOG((TL_ERROR, "Bad hWnd in dofunc"));
lResult = gaInvalHwndErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
// The only functions that pass in Hwnd are
// tapiRequestDrop and tapiRequestMediaCall;
// both of these are non functional on the server side
// (correctly noted by the documentation). Parameters
// are not checked. Simply passing in 0 for the Hwnd will
// not affect functionality in any way, and will save a lot
// of grief coming from the 32 / 64 bit conversions (hwnd are
// 64 bits on 64 bit system, and the params we're using over
// the wire are only 32 bits).
((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0;
continue;
case lpDword:
if (IsBadDwordPtr ((LPDWORD) value))
{
LOG((TL_ERROR, "Bad lpdword in dofunc"));
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
bCopyOnSuccess = TRUE;
continue;
case lpszW:
//
// Check if value is a valid string ptr and if so
// copy the contents of the string to the extra data
// buffer passed to the server
//
try
{
DWORD n = (lstrlenW((WCHAR *) value) + 1) * sizeof(WCHAR),
nAligned = ALIGN(n);
if ((nAligned + dwUsedSize) > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
nAligned
))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
}
CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) value, 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;
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
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))
{
LOG((TL_ERROR,
"DoFunc: error, lpGet_SizeToFollow !followed by Size"
));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
#endif
dwSize = DWORD_CAST(pFuncArgs->Args[i + 1],__FILE__,__LINE__);
}
else
{
DWORD dwError;
try
{
dwSize = *((LPDWORD) value);
}
except ((((dwError = GetExceptionCode())
== EXCEPTION_ACCESS_VIOLATION) ||
dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
LOG((TL_ERROR, "Bad get struct/size in dofunc"));
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
}
if (IsBadWritePtr ((LPVOID) value, dwSize))
{
LOG((TL_ERROR, "Bad get size/struct2 in dofunc"));
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
if (bSizeToFollow)
{
((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
++j;++i;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST(pFuncArgs->Args[i],__FILE__,__LINE__);
}
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 += ALIGN(dwSize);
continue;
}
case lpSet_Struct:
case lpSet_SizeToFollow:
{
BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
DWORD dwSize, dwError, 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)))
{
LOG((TL_ERROR,
"DoFunc: error, lpSet_SizeToFollow !followed by Size"
));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
#endif
try
{
//
// First determine the data size & if the ptr is bad
//
dwSize = (bSizeToFollow ? DWORD_CAST(pFuncArgs->Args[i + 1],__FILE__,__LINE__) :
*((LPDWORD) value));
if (IsBadReadPtr ((LPVOID) value, dwSize))
{
LOG((TL_ERROR, "Bad set size/struct in dofunc"));
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
dwSizeAligned = ALIGN(dwSize);
//
// Special case if the size isn't even big enough to pass
// over a complete DWORD for the dwTotalSize field
//
if (!bSizeToFollow && (dwSize < sizeof (DWORD)))
{
static DWORD dwZeroTotalSize = 0;
dwSize = dwSizeAligned = sizeof (DWORD);
value = (ULONG_PTR) &dwZeroTotalSize;
// LOG((TL_ERROR, TEXT("Bad set size/struct2 in dofunc")));
// lResult = gaStructTooSmallErrors[dwFuncClassErrorIndex];
// goto DoFunc_return;
}
//
// Grow the buffer if necessary, & do the copy
//
if ((dwSizeAligned + dwUsedSize) > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
dwSizeAligned
))
{
LOG((TL_ERROR, "Nomem set size/struct in dofunc"));
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
}
CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) value, dwSize);
}
except ((((dwError = GetExceptionCode())
== EXCEPTION_ACCESS_VIOLATION) ||
dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
LOG((TL_ERROR, "Bad pointer in get size/struct in dofunc"));
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
//
// 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)
{
++i;++j;
((PTAPI32_MSG) pTls->pBuf)->Params[j] = DWORD_CAST(pFuncArgs->Args[i],__FILE__,__LINE__);
}
continue;
}
#if DBG
case Size:
LOG((TL_ERROR, "DoFunc: error, hit case Size"));
continue;
default:
LOG((TL_ERROR, "DoFunc: error, unknown arg type"));
continue;
#endif
} // switch
} // for
//
// Now make the request
//
if (dwNeededSize > pTls->dwBufSize)
{
if (!GrowBuf(
&pTls->pBuf,
&pTls->dwBufSize,
dwUsedSize,
dwNeededSize - pTls->dwBufSize
))
{
lResult = gaNoMemErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
}
((PTAPI32_MSG) pTls->pBuf)->u.Req_Func = (DWORD)HIWORD(pFuncArgs->Flags);
{
DWORD dwRetryCount = 0;
BOOL bReinitResource;
PCONTEXT_HANDLE_TYPE phCtxTmp = GetTlsPCtxHandle();
do
{
phCtx = (phCtxTmp != NULL)?phCtxTmp : gphCx;
bReinitResource = FALSE;
RpcTryExcept
{
ClientRequest (phCtx, pTls->pBuf, dwNeededSize, &dwUsedSize);
lResult = (LONG) ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
if (lResult == TAPIERR_INVALRPCCONTEXT)
{
if (dwRetryCount ++ >= gdwMaxNumRequestRetries)
{
bReinitResource = FALSE;
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
dwRetryCount = 0;
}
else
{
((PTAPI32_MSG) pTls->pBuf)->u.Req_Func =
(DWORD)HIWORD(pFuncArgs->Flags);
bReinitResource = TRUE;
}
}
else
{
bReinitResource = FALSE;
dwRetryCount = 0;
}
}
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
{
unsigned long rpcException = RpcExceptionCode();
if (rpcException == RPC_S_SERVER_TOO_BUSY)
{
if (dwRetryCount++ < gdwMaxNumRequestRetries)
{
Sleep (gdwRequestRetryTimeout);
}
else
{
dwRetryCount = 0;
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
}
}
else if ((rpcException == RPC_S_SERVER_UNAVAILABLE) ||
(rpcException == RPC_S_CALL_FAILED_DNE) ||
(rpcException == RPC_S_UNKNOWN_IF) ||
(rpcException == ERROR_INVALID_HANDLE))
{
if (dwRetryCount ++ >= gdwMaxNumRequestRetries)
{
bReinitResource = FALSE;
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
dwRetryCount = 0;
}
else
{
bReinitResource = TRUE;
}
}
else
{
LOG((TL_ERROR, "DoFunc: rpcException # %d", rpcException));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
dwRetryCount = 0;
}
}
RpcEndExcept
if (bReinitResource)
{
if (ReAllocClientResources(dwFuncClassErrorIndex) != TAPI_SUCCESS)
{
LOG((TL_ERROR, "DoFunc: ReAllocClientResources failed"));
lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
dwRetryCount = 0;
bResAllocated = FALSE;
}
}
} while (dwRetryCount != 0);
}
// note: 99.99% of the time this result dump will == the one at end of the
// func (only when ptrs have gone bad will the result differ), no reason
// to dump 2x unless doing internal dbgging
//
LOG((TL_TRACE, "DoFunc: back from srv- return code=0x%08lx", lResult));
//
// 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 Hwnd:
// case lpsz:
case lpszW:
case lpSet_Struct:
continue;
case lpDword:
try
{
//
// Fill in the pointer with the return value
//
*((LPDWORD) pFuncArgs->Args[i]) = (DWORD) pMsg->Params[j];
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
continue;
case lpGet_SizeToFollow:
try
{
//
// Fill in the pointer with the return value
//
CopyMemory(
(LPBYTE) pFuncArgs->Args[i],
pTls->pBuf + (DWORD)pMsg->Params[j] + sizeof(TAPI32_MSG),
pMsg->Params[j+1]
);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
//
// 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:
try
{
//
// 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 ((DWORD)pMsg->Params[j] != TAPI_NO_DATA)
{
LPDWORD pStruct;
pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
(DWORD)pMsg->Params[j]);
CopyMemory(
(LPBYTE) pFuncArgs->Args[i],
(LPBYTE) pStruct,
*(pStruct + 2) // ptr to dwUsedSize field
);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
goto DoFunc_return;
}
continue;
default:
continue;
}
}
}
DoFunc_return:
if (bResAllocated)
{
FreeClientResources();
}
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"%hs: result = %hs",
pszFuncName,
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
"DoFunc: result = x%x",
lResult
));
#endif
return lResult;
}
LONG
LoadUIDll(
HWND hwndOwner,
DWORD dwWidgetID,
DWORD dwWidgetType,
HANDLE *phDll,
LPCSTR pszTUISPI_xxx, // use for GetProcAddress, leave as ANSI
TUISPIPROC *ppfnTUISPI_xxx
)
{
LONG lResult;
HANDLE hDll = NULL;
WCHAR szUIDllName[MAX_PATH];
HANDLE hProvidersMutex;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, xGetUIDllName),
{
(ULONG_PTR) dwWidgetID,
(ULONG_PTR) dwWidgetType,
(ULONG_PTR) szUIDllName,
(ULONG_PTR) MAX_PATH
},
{
Dword,
Dword,
lpGet_SizeToFollow,
Size
}
};
if (hwndOwner && !IsWindow (hwndOwner))
{
lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
PHONEERR_INVALPARAM : LINEERR_INVALPARAM);
goto LoadUIDll_return;
}
hProvidersMutex = CreateMutex (
NULL,
FALSE,
TEXT("TapisrvProviderListMutex")
);
if (NULL == hProvidersMutex)
{
lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
goto LoadUIDll_return;
}
WaitForSingleObject (hProvidersMutex, INFINITE);
if ((lResult = DOFUNC (&funcArgs, "GetUIDllName")) == 0)
{
if (hDll = TAPILoadLibraryW(szUIDllName))
{
if ((*ppfnTUISPI_xxx = (TUISPIPROC) GetProcAddress(
hDll,
pszTUISPI_xxx
)))
{
*phDll = hDll;
lResult = 0;
}
else
{
LOG((TL_ERROR,
"LoadUIDll: GetProcAddress(%ls,%hs) failed, err=%d",
szUIDllName,
pszTUISPI_xxx,
GetLastError()
));
FreeLibrary (hDll);
lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
PHONEERR_OPERATIONUNAVAIL : LINEERR_OPERATIONUNAVAIL);
}
}
else
{
LOG((TL_ERROR,
"LoadLibraryW(%ls) failed, err=%d",
szUIDllName,
GetLastError()
));
lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
}
}
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
LoadUIDll_return:
return lResult;
}
LONG
PASCAL
lineXxxProvider(
LPCSTR pszTUISPI_providerXxx,
LPCSTR lpszProviderFilename,
HWND hwndOwner,
DWORD dwPermProviderID,
LPDWORD lpdwPermProviderID
)
{
BOOL bAddProvider = (pszTUISPI_providerXxx ==
gszTUISPI_providerInstall);
WCHAR szUIDllName[MAX_PATH];
LONG lResult;
HINSTANCE hDll;
TUISPIPROC pfnTUISPI_providerXxx;
HTAPIDIALOGINSTANCE htDlgInst;
LPTSTR tszProviderFilename;
#ifdef UNICODE
WCHAR wszProviderFilename[255];
HANDLE hProvidersMutex;
if (lpszProviderFilename)
{
MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpszProviderFilename,
lstrlenA (lpszProviderFilename) + 1,
wszProviderFilename,
sizeof(wszProviderFilename) / sizeof(WCHAR)
);
}
else
{
wszProviderFilename[0] = 0;
}
tszProviderFilename = wszProviderFilename;
#else
tszProviderFilename = lpszProviderFilename;
#endif
hProvidersMutex = CreateMutex (
NULL,
FALSE,
TEXT("TapisrvProviderListMutex")
);
if (NULL == hProvidersMutex)
{
return LINEERR_OPERATIONFAILED;
}
lResult = AllocClientResources(0);
if (lResult)
{
return lResult;
}
WaitForSingleObject (hProvidersMutex, INFINITE);
if (bAddProvider && IsBadDwordPtr (lpdwPermProviderID))
{
LOG((TL_ERROR, "Bad lpdwPermProviderID pointer"));
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
FreeClientResources ();
return LINEERR_INVALPOINTER;
}
else if (hwndOwner && !IsWindow (hwndOwner))
{
LOG((TL_ERROR, "hwndOwner is not a window"));
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
FreeClientResources ();
return LINEERR_INVALPARAM;
}
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, xGetUIDllName),
{
(bAddProvider ? (ULONG_PTR) &dwPermProviderID :
(ULONG_PTR) dwPermProviderID),
(ULONG_PTR) TUISPIDLL_OBJECT_PROVIDERID,
(ULONG_PTR) szUIDllName,
(ULONG_PTR) MAX_PATH,
(bAddProvider ? (ULONG_PTR) tszProviderFilename :
(ULONG_PTR) TAPI_NO_DATA),
(ULONG_PTR) (pszTUISPI_providerXxx==gszTUISPI_providerRemove ?
1 : 0),
(ULONG_PTR) &htDlgInst
},
{
(bAddProvider ? lpDword : Dword),
Dword,
lpGet_SizeToFollow,
Size,
(bAddProvider ? lpszW : Dword),
Dword,
lpDword
}
};
if ((lResult = DOFUNC (&funcArgs,"lineXxxProvider/GetUIDllName")) != 0)
{
if (lResult == TAPI16BITSUCCESS)
{
// 16 bit sp success
// set result correctly, and return here
lResult = 0;
}
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
FreeClientResources ();
return lResult;
}
}
if ((hDll = TAPILoadLibraryW(szUIDllName)))
{
if ((pfnTUISPI_providerXxx = (TUISPIPROC) GetProcAddress(
hDll,
pszTUISPI_providerXxx
)))
{
LOG((TL_TRACE, "Calling %hs...", pszTUISPI_providerXxx));
lResult = (*pfnTUISPI_providerXxx)(
TUISPIDLLCallback,
hwndOwner,
dwPermProviderID
);
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"%hs: result = %hs",
pszTUISPI_providerXxx,
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
": result = x%x",
lResult
));
#endif
}
else
{
LOG((TL_ERROR,
"lineXxxProvider: GetProcAddr(%ls,%hs) failed, err=%d",
szUIDllName,
pszTUISPI_providerXxx,
GetLastError()
));
//
// HACK ALERT !
// Even though remotesp.tsp does not have the add/remove/config
// provider function, we silently allow it to be added from
// tcmsetup.exe
//
if (lstrcmpi (gszRemoteSP, szUIDllName) != 0)
{
lResult = LINEERR_OPERATIONUNAVAIL;
}
}
FreeLibrary (hDll);
}
else
{
LOG((TL_ERROR,
"lineXxxProvider: LoadLibraryW('%ls') failed, err=%d",
szUIDllName,
GetLastError()
));
lResult = LINEERR_OPERATIONFAILED;
}
{
LONG lResult2;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, xFreeDialogInstance),
{
(ULONG_PTR) htDlgInst,
(ULONG_PTR) (ULONG)lResult
},
{
Dword,
Dword
}
};
//
// If TUISPI_providerXxx failed then we want to pass that error back
// to the app, else if it succeeded & FreeDlgInst failed then pass
// that error back to the app
//
if ((lResult2 = DOFUNC(
&funcArgs,
"lineXxxProvider/FreeDialogInstance"
)) == 0)
{
if (bAddProvider)
{
*lpdwPermProviderID = dwPermProviderID;
}
}
else if (lResult == 0)
{
lResult = lResult2;
}
}
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
FreeClientResources ();
return lResult;
}
LONG
PASCAL
ValidateXxxInitializeParams(
DWORD dwAPIVersion,
BOOL bLine,
LPLINEINITIALIZEEXPARAMS pXxxInitExParams,
LINECALLBACK pfnCallback
)
{
DWORD dwError;
try
{
DWORD dwTotalSize = pXxxInitExParams->dwTotalSize;
if (dwTotalSize < sizeof (LINEINITIALIZEEXPARAMS))
{
return (bLine ? LINEERR_STRUCTURETOOSMALL :
PHONEERR_STRUCTURETOOSMALL);
}
if (IsBadWritePtr (pXxxInitExParams, dwTotalSize))
{
return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
}
//
// When checking the dwOptions field be careful about compatibility
// with future vers, so we only look at the currently valid bits
//
switch ((pXxxInitExParams->dwOptions & 0xf))
{
case 0:
case LINEINITIALIZEEXOPTION_USEHIDDENWINDOW:
if (IsBadCodePtr ((FARPROC) pfnCallback))
{
return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
}
break;
case LINEINITIALIZEEXOPTION_USECOMPLETIONPORT:
if ( !gpPostQueuedCompletionStatus )
{
HINSTANCE hInst;
hInst = GetModuleHandle( TEXT("Kernel32.dll") );
{
gpPostQueuedCompletionStatus = GetProcAddress(
hInst,
"PostQueuedCompletionStatus"
);
if ( NULL == gpPostQueuedCompletionStatus )
{
LOG((TL_ERROR,
"GetProcAddr(PostQueuedCompletionStatus) failed"
));
return (bLine ?
LINEERR_INVALFEATURE : PHONEERR_OPERATIONFAILED);
}
}
}
break;
case LINEINITIALIZEEXOPTION_USEEVENT:
break;
default:
if ((TAPI_VERSION2_2 == dwAPIVersion) ||
(TAPI_VERSION2_1 == dwAPIVersion) ||
(TAPI_VERSION2_0 == dwAPIVersion))
{
//
// Invalid parameter for these versions
//
return (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
}
else
{
//
// This app is asking for something we can't do.
//
return (bLine ? LINEERR_INCOMPATIBLEAPIVERSION :
PHONEERR_INCOMPATIBLEAPIVERSION);
}
}
pXxxInitExParams->dwNeededSize =
pXxxInitExParams->dwUsedSize = sizeof (LINEINITIALIZEEXPARAMS);
}
except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
}
return 0;
}
LONG
WINAPI
xxxInitialize(
BOOL bLine,
LPVOID phXxxApp,
HINSTANCE hInstance,
LINECALLBACK pfnCallback,
LPCWSTR pszAppName,
LPDWORD pdwNumDevs,
LPDWORD pdwAPIVersion,
LPLINEINITIALIZEEXPARAMS pXxxInitExParams
#if DBG
,char *pszFuncName
#endif
)
{
FUNC_ARGS funcArgs =
{
MAKELONG ((bLine ? LINE_FUNC : PHONE_FUNC) | SYNC | 7,
(bLine ? lInitialize : pInitialize)),
{
(ULONG_PTR) phXxxApp,
(ULONG_PTR) 0, // hInstance is ignored by tapisrv, so pass 0,
// to save ourselves grief over HINSTANCE -> DWORD conversion
(ULONG_PTR) 0, // pfnCallback, we subst pInitData in here
(ULONG_PTR) pszAppName,
(ULONG_PTR) pdwNumDevs,
(ULONG_PTR) 0, // pszModuleName
(ULONG_PTR) TAPI_VERSION1_0
},
{
lpDword,
Dword,
Dword,
lpszW,
lpDword,
lpszW,
Dword
}
};
WCHAR *pszModuleNamePathW = NULL;
WCHAR *pszModuleNameW = NULL;
LONG lResult;
BOOL bReleaseMutex = FALSE;
BOOL bResAllocated = FALSE;
PINIT_DATA pInitData = (PINIT_DATA) NULL;
BOOL fIs16bitCaller = FALSE;
DWORD dwAllInitExOptions;
EnterCriticalSection (&gCriticalSection);
if (gdwNumInits == 0)
{
TRACELOGREGISTER (_T("tapi32"));
}
LeaveCriticalSection (&gCriticalSection);
if (phXxxApp == (LPVOID) pdwNumDevs)
{
#if DBG
LOG((TL_TRACE, "%hs: error, lphApp == lpdwNumDevs", pszFuncName));
#else
LOG((TL_TRACE, ": error, lphApp == lpdwNumDevs"));
#endif
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxInitialize_return;
}
if (pdwAPIVersion)
{
if (phXxxApp == (LPVOID) pdwAPIVersion ||
phXxxApp == (LPVOID) pXxxInitExParams ||
pdwNumDevs == pdwAPIVersion ||
pdwNumDevs == (LPDWORD) pXxxInitExParams ||
pdwAPIVersion == (LPDWORD) pXxxInitExParams)
{
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxInitialize_return;
}
//
// line- & phoneInitializeEx both require a valid lpdwAPIVersion
// pointer parameter, and the value it points to on the way in
// must be >= 0x00020000. (Careful to allow for future vers of TAPI.)
//
if (*pdwAPIVersion < TAPI_VERSION2_0)
{
LOG((TL_ERROR,
"%InitializeEx: error, *lpdwAPIVersion = x%x, " \
"must be set >= 0x20000",
*pdwAPIVersion,
(bLine ? "line" : "phone")
));
lResult = (bLine ? LINEERR_INCOMPATIBLEAPIVERSION :
PHONEERR_INCOMPATIBLEAPIVERSION);
goto xxxInitialize_return;
}
//
// Validate the InitEx params, or if the pointer is NULL (implying
// that app wants to use "old" hidden window scheme) validate
// the pfnCallback
//
if (pXxxInitExParams)
{
if ((lResult = ValidateXxxInitializeParams(
(*pdwAPIVersion),
bLine,
pXxxInitExParams,
pfnCallback
)) != 0)
{
goto xxxInitialize_return;
}
}
else if (IsBadCodePtr ((FARPROC) pfnCallback))
{
#if DBG
LOG((TL_ERROR, "%hs: bad lpfnCallback", pszFuncName));
#else
LOG((TL_ERROR, ": bad lpfnCallback"));
#endif
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxInitialize_return;
}
//
// Now fill in *pdwAPIVersion with the version # we support, and
// also indicate this in the params we pass to tapisrv.exe (so
// it knows it can start sending us 2.0 msgs right away)
//
// bug #69742. don't assume version 2.0
if ( (*pdwAPIVersion == TAPI_VERSION2_2) ||
(*pdwAPIVersion == TAPI_VERSION2_1) ||
(*pdwAPIVersion == TAPI_VERSION2_0))
{
funcArgs.Args[6] = *pdwAPIVersion;
}
else
{
//
// the app is at least 2.0 if they are calling lineIntializeEx,
// but they passed in a bogus tapi version, so set it correctly.
//
funcArgs.Args[6] = *pdwAPIVersion = TAPI_CURRENT_VERSION;
}
}
#ifndef _WIN64
else if ((((DWORD) pfnCallback) & 0xffff0000) == 0xffff0000)
{
//
// This is a 16-bit client going through the thunk. The
// pfnCallback var is actually a window handle.
//
// Note: On NT, 32-bit code can talk to 16-bit HWNDs
// by setting the hi-word to 0xffff.
//
// On Win95, 32-bit can talk to 16-bit HWNDs
// by setting the hi-word to 0x0000.
//
//<! ((DWORD) pfnCallback) = HWND_32( pfnCallback );
//<!
//<!
if (!IsWindow ((HWND) pfnCallback))
{
//
// If here chances are it's a 32-bit app passing in a bad
// pfnCallback
//
#if DBG
LOG((TL_ERROR, "%hs: bad lpfnCallback", pszFuncName));
#else
LOG((TL_ERROR, ": bad lpfnCallback"));
#endif
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxInitialize_return;
}
if (!ghWow32Dll &&
!(ghWow32Dll = LoadLibrary (TEXT("wow32.dll"))))
{
#if DBG
LOG((TL_ERROR,
"%hs: LoadLib(wow32.dll) failed, err=%d",
pszFuncName,
GetLastError()
));
#else
LOG((TL_ERROR,
": LoadLib(wow32.dll) failed, err=%d",
GetLastError()
));
#endif
lResult =
(bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
goto xxxInitialize_return;
}
if (!gpfnWOWGetVDMPointer &&
!(gpfnWOWGetVDMPointer = GetProcAddress(
ghWow32Dll,
"WOWGetVDMPointer"
)))
{
#if DBG
LOG((TL_ERROR,
"%hs: GetProcAddr(WOWGetVDMPointer) failed, err=%d",
pszFuncName,
GetLastError()
));
#else
LOG((TL_ERROR,
": GetProcAddr(WOWGetVDMPointer) failed, err=%d",
GetLastError()
));
#endif
lResult =
(bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
goto xxxInitialize_return;
}
gbNTVDMClient = TRUE;
//
// For 16-bit clients the module name will follow the app name
//
// HACK ALERT!
//
// Since the lpszAppName pointer was already converted to a
// unicode string by the calling function, the following
// module name part was lost. So, we pass the original
// (16->32 mapped) lpszAppName pointer in pXxxInitExParams
// so we can discover the module name
//
{
char *pszAppName2 = (char *) pXxxInitExParams;
pXxxInitExParams = NULL; // so we don't blow up below
pszModuleNamePathW = NotSoWideStringToWideString(
pszAppName2 + lstrlenA (pszAppName2) + 1,
(DWORD) -1
);
funcArgs.Args[5] = (ULONG_PTR) pszModuleNamePathW;
LOG((TL_INFO,
"FName='%ls', MName='%ls'",
pszAppName,
funcArgs.Args[5]
));
}
}
#endif
else if (IsBadCodePtr ((FARPROC) pfnCallback))
{
//
// If here a 32-bit app is call line/phoneInitialize
//
#if DBG
LOG((TL_ERROR, "%hs: bad lpfnCallback", pszFuncName));
#else
LOG((TL_ERROR, ": bad lpfnCallback"));
#endif
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxInitialize_return;
}
//
// Check to see if hInstance is bad by getting the module name
//
// Note: We now allow a NULL hInstance (16-bit TAPI didn't)
//
if (gbNTVDMClient == FALSE)
{
DWORD dwSize = MAX_PATH, dwLength;
alloc_module_name_buf:
if (!(pszModuleNamePathW = ClientAlloc (dwSize*sizeof(WCHAR))))
{
lResult = (bLine ? LINEERR_NOMEM : PHONEERR_NOMEM);
goto xxxInitialize_return;
}
//
// We're on WinNT - do Unicode
//
if ((dwLength = GetModuleFileNameW(
hInstance,
pszModuleNamePathW,
dwSize
)) == 0)
{
#if DBG
LOG((TL_ERROR,
"%hs: GetModuleFileNameW(x%p, ...) failed, err=%d",
pszFuncName,
hInstance,
GetLastError()
));
#else
LOG((TL_ERROR,
": GetModuleFileNameW(x%p, ...) failed, err=%d",
hInstance,
GetLastError()
));
#endif
lResult = (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
goto xxxInitialize_cleanup;
}
else if (dwLength >= dwSize)
{
ClientFree (pszModuleNamePathW);
dwSize *= 2;
goto alloc_module_name_buf;
}
pszModuleNameW = wcsrchr (pszModuleNamePathW, '\\') + 1;
// For MSWORKS.EXE, the behavior of lineGetTranslateCaps
// will be different
if(0 == _wcsicmp(pszModuleNameW, L"MSWORKS.EXE"))
{
LOG((TL_ERROR, "MSWORKS detected..."));
gbDisableGetTranslateCapsHack = TRUE;
}
else
{
gbDisableGetTranslateCapsHack = FALSE;
}
funcArgs.Args[5] = (ULONG_PTR) pszModuleNameW;
if (!pszAppName)
{
funcArgs.Args[3] = funcArgs.Args[5];
}
}
if (!(pInitData = ClientAlloc (sizeof(INIT_DATA))) ||
!(pInitData->pEventBuffer = ClientAlloc(
DEF_NUM_EVENT_BUFFER_ENTRIES * sizeof (ASYNC_EVENT_PARAMS))) ||
!(pInitData->hInitData = NewObject (ghHandleTable, pInitData, NULL)))
{
lResult = (bLine ? LINEERR_NOMEM : PHONEERR_NOMEM);
goto xxxInitialize_cleanup;
}
//
// When checking the dwOptions field be careful about compatibility
// with future vers, so we only look at the currently valid bits
// (The ExOptions are currently ordinals, but we track bits here just
// in case we wanna use high bits later.)
//
dwAllInitExOptions = AllInitExOptions2_0;
pInitData->dwInitOptions = (pXxxInitExParams ?
(pXxxInitExParams->dwOptions & dwAllInitExOptions) :
LINEINITIALIZEEXOPTION_USEHIDDENWINDOW);
switch (pInitData->dwInitOptions & 0xf)
{
case LINEINITIALIZEEXOPTION_USECOMPLETIONPORT:
//
// Be libertarian- if the app wants to hose itself by passing
// a bad hCompletionPort then so be it
//
pInitData->hCompletionPort =
pXxxInitExParams->Handles.hCompletionPort;
pInitData->dwCompletionKey = pXxxInitExParams->dwCompletionKey;
break;
case LINEINITIALIZEEXOPTION_USEEVENT:
if ((pInitData->hEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) NULL,
TRUE, // manual reset
FALSE, // unsignaled
NULL // unnamed
)) == NULL)
{
lResult = (bLine ? LINEERR_OPERATIONFAILED :
PHONEERR_OPERATIONFAILED);
goto xxxInitialize_cleanup;
}
pXxxInitExParams->Handles.hEvent = pInitData->hEvent;
break;
default: // case LINEINITIALIZEEXOPTION_USEHIDDENWINDOW:
pInitData->dwInitOptions |= LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
if (gbNTVDMClient == FALSE)
{
if ((lResult = CreateHiddenWindow(
&pInitData->hwnd,
(bLine ? 1 : 2)
)) != 0)
{
goto xxxInitialize_cleanup;
}
}
else
{
pInitData->hwnd = (HWND) pfnCallback;
}
pInitData->lpfnCallback = pfnCallback;
pInitData->bPendingAsyncEventMsg = FALSE;
break;
}
pInitData->dwKey = INITDATA_KEY;
pInitData->dwNumTotalEntries = DEF_NUM_EVENT_BUFFER_ENTRIES;
pInitData->dwNumUsedEntries = 0;
pInitData->pValidEntry =
pInitData->pFreeEntry = pInitData->pEventBuffer;
pInitData->bLine = bLine;
pInitData->dwThreadID = GetCurrentThreadId();
//
// We want to pass TAPISRV pInitData so that later when it does async
// completion/event notification it can pass pInitData along too so
// we know which init instance to talk to
//
funcArgs.Args[2] = (ULONG_PTR) pInitData->hInitData;
WaitForSingleObject (ghInitMutex, INFINITE);
bReleaseMutex = TRUE;
//
// Need to hold a reference of the Rpc connection
// so we don't close it until lineShutdown
//
bResAllocated = (0 == AllocClientResources(bLine ? 1 : 2));
if (bResAllocated)
{
lResult = DOFUNC (&funcArgs, pszFuncName);
}
else
{
lResult = (bLine ? LINEERR_OPERATIONFAILED :
PHONEERR_OPERATIONFAILED);
}
xxxInitialize_cleanup:
if (pszModuleNamePathW)
{
ClientFree (pszModuleNamePathW);
}
if (lResult == 0)
{
//
// If total number of init instances is 0 we need to start a
// new async events thread
//
EnterCriticalSection (&gCriticalSection);
if (gdwNumInits == 0)
{
DWORD dwThreadID;
HANDLE hThread;
//
// Alloc resources for a new async events thread, then
// create the thread
//
if ((gpAsyncEventsThreadParams = ClientAlloc(
sizeof (ASYNC_EVENTS_THREAD_PARAMS)
)))
{
//
// Load ourself to increment our usage count. This is
// done to give the AsyncEventThread a chance to
// terminate cleanly if an app thread calls xxxShutdown
// and then immediately unloads tapi32.dll.
//
// (For a while we were doing a Wait on this thread's
// handle in xxxShutdown waiting for it to terminate,
// but if xxxShutdown was being called from another DLL's
// DllEntryPoint then deadlock occured, because
// DllEntryPoint's aren't reentrant.)
//
if ((gpAsyncEventsThreadParams->hTapi32 = LoadLibrary(
TEXT("tapi32.dll")
)))
{
//
// If we're supporting a 16-bit client we want to inc
// the usage count for wow32 too
//
if (ghWow32Dll == NULL ||
(gpAsyncEventsThreadParams->hWow32 = LoadLibrary(
TEXT("wow32.dll")
)))
{
//
// Create the initial buffer the thread will use for
// retreiving async events
//
gpAsyncEventsThreadParams->dwBufSize =
ASNYC_MSG_BUF_SIZE;
if ((gpAsyncEventsThreadParams->pBuf = ClientAlloc(
gpAsyncEventsThreadParams->dwBufSize
)))
{
//
// Now that we've all the resources try to exec
// the thread
//
if ((hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) AsyncEventsThread,
(LPVOID) gpAsyncEventsThreadParams,
0,
&dwThreadID
)) != NULL)
{
CloseHandle (hThread);
gdwNumInits++;
LeaveCriticalSection(&gCriticalSection);
goto xxxInitialize_releaseMutex;
}
ClientFree (gpAsyncEventsThreadParams->pBuf);
#if DBG
LOG((TL_ERROR,
"%hs: CreateThread(AsyncEventsThread) " \
"failed, err=%d",
pszFuncName,
GetLastError()
));
#else
LOG((TL_ERROR,
": CreateThread(AsyncEventsThread) " \
"failed, err=%d",
GetLastError()
));
#endif
}
if (ghWow32Dll)
{
FreeLibrary (gpAsyncEventsThreadParams->hWow32);
}
}
FreeLibrary (gpAsyncEventsThreadParams->hTapi32);
}
else
{
#if DBG
LOG((TL_ERROR,
"%hs: LoadLibrary('tapi32.dll') failed, err=%d",
pszFuncName,
GetLastError()
));
#else
LOG((TL_ERROR,
": LoadLibrary('tapi32.dll') failed, err=%d",
GetLastError()
));
#endif
}
ClientFree (gpAsyncEventsThreadParams);
}
gpAsyncEventsThreadParams = NULL;
lResult =
(bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
}
else
{
gdwNumInits++;
}
LeaveCriticalSection(&gCriticalSection);
}
if (lResult != 0)
{
if (gbNTVDMClient && pInitData)
{
pInitData->hwnd = (HWND) NULL;
}
FreeInitData (pInitData);
}
xxxInitialize_releaseMutex:
if (bReleaseMutex)
{
ReleaseMutex (ghInitMutex);
}
if (lResult == 0)
{
//
// Save the hLineApp returned by TAPISRV in our InitData struct,
// and give the app back a unique handle
//
pInitData->hXxxApp = *((LPHLINEAPP) phXxxApp);
*((LPHLINEAPP) phXxxApp) = pInitData->hInitData;
}
xxxInitialize_return:
//
// if we failed, we need to release the RPC ref count,
// nobody will call lineShutdown
//
if (bResAllocated &&
lResult !=0)
{
FreeClientResources();
}
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"%hs: exit, result=%hs",
pszFuncName,
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
": exit, result=x%x",
lResult
));
#endif
return lResult;
}
//
// --------------------------------- lineXxx ----------------------------------
//
LONG
WINAPI
lineAccept(
HCALL hCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lAccept),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpsUserUserInfo,
dwSize
},
{
Dword,
lpSet_SizeToFollow,
Size
}
};
if (!lpsUserUserInfo)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineAccept"));
}
LONG
WINAPI
lineAddProviderA(
LPCSTR lpszProviderFilename,
HWND hwndOwner,
LPDWORD lpdwPermanentProviderID
)
{
LONG lResult;
LOG((TL_TRACE, "lineAddProviderA: enter"));
LOG((TL_INFO, " lpszProviderFilename=0x%p", lpszProviderFilename));
#if DBG
if (!IsBadStringPtrA(lpszProviderFilename, (UINT)-1) )
{
LOG((TL_INFO, " *lpszProviderFilename=[%hs]", lpszProviderFilename));
}
#endif
LOG((TL_INFO, " hwndOwner=0x%p", hwndOwner));
LOG((TL_INFO, " lpdwPermanentProviderID=0x%p", lpdwPermanentProviderID));
if ( IsBadStringPtrA(lpszProviderFilename, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszProviderFilename (0x%p)", lpszProviderFilename));
return LINEERR_INVALPOINTER;
}
lResult = lineXxxProvider(
gszTUISPI_providerInstall, // funcName
lpszProviderFilename, // lpszProviderFilename
hwndOwner, // hwndOwner
0, // dwPermProviderID
lpdwPermanentProviderID // lpdwPermProviderID
);
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"lineAddProvider: result = %hs",
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
"lineAddProvider: result = x%x",
lResult
));
#endif
return lResult;
}
LONG
WINAPI
lineAddProviderW(
LPCWSTR lpszProviderFilename,
HWND hwndOwner,
LPDWORD lpdwPermanentProviderID
)
{
LONG lResult;
LPBYTE pszTempPtr;
DWORD dwSize;
LOG((TL_TRACE, "Entering lineAddProvider"));
LOG((TL_INFO, " lpszProviderFilename=0x%p", lpszProviderFilename));
if ( TAPIIsBadStringPtrW(lpszProviderFilename, (UINT)-1) )
{
LOG((TL_ERROR,
"Bad lpszProviderFilename [0x%p] passed to lineAddProviderW",
lpszProviderFilename
));
return( LINEERR_INVALPOINTER );
}
LOG((TL_INFO, " *lpszProviderFilename=[%ls]", lpszProviderFilename));
LOG((TL_INFO, " hwndOwner=0x%p", hwndOwner));
LOG((TL_INFO, " lpdwPermanentProviderID=0x%p", lpdwPermanentProviderID));
dwSize = lstrlenW(lpszProviderFilename) + 1;
pszTempPtr = ClientAlloc(dwSize * sizeof (WCHAR));
if (NULL == pszTempPtr)
{
return LINEERR_NOMEM;
}
// can't use this because this is for strings
// embedded in structures.
// WideStringToNotSoWideString (pszTempPtr, &dwSize);
WideCharToMultiByte(
GetACP(),
0,
lpszProviderFilename,
-1,
pszTempPtr,
dwSize * sizeof(WCHAR),
NULL,
NULL
);
lResult = lineAddProviderA(
(LPCSTR) pszTempPtr,
hwndOwner,
lpdwPermanentProviderID
);
ClientFree(pszTempPtr);
return lResult;
}
LONG
WINAPI
lineAddProvider(
LPCSTR lpszProviderFilename,
HWND hwndOwner,
LPDWORD lpdwPermanentProviderID
)
{
return lineAddProviderA(
lpszProviderFilename,
hwndOwner,
lpdwPermanentProviderID
);
}
LONG
WINAPI
lineAddToConference(
HCALL hConfCall,
HCALL hConsultCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lAddToConference),
{
(ULONG_PTR) hConfCall ,
(ULONG_PTR) hConsultCall
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineAddToConference"));
}
LONG
WINAPI
lineAgentSpecific(
HLINE hLine,
DWORD dwAddressID,
DWORD dwAgentExtensionIDIndex,
LPVOID lpParams,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lAgentSpecific),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwAgentExtensionIDIndex,
(ULONG_PTR) lpParams,
(ULONG_PTR) lpParams,
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !hLine )
{
return LINEERR_INVALLINEHANDLE;
}
if ( 0 == dwSize)
{
return LINEERR_INVALPARAM;
}
if ( !lpParams )
{
return LINEERR_INVALPOINTER;
}
// Since we're passing lpParams twice, once a handle to it
// and another time unchanged, we rely on DoFunc to test it.
hPointer = NewObject (ghHandleTable, (PVOID)lpParams, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
if (0 > (lResult = DOFUNC (&funcArgs, "lineAgentSpecific")))
{
// There was an error, free the handle...
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineAnswer(
HCALL hCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lAnswer),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpsUserUserInfo,
dwSize
},
{
Dword,
lpSet_SizeToFollow,
Size
}
};
if (!lpsUserUserInfo)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineAnswer"));
}
LONG
WINAPI
lineBlindTransferW(
HCALL hCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lBlindTransfer),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpszDestAddress,
dwCountryCode
},
{
Dword,
lpszW,
Dword
}
};
if ( TAPIIsBadStringPtrW( lpszDestAddress, (UINT)-1 ) )
{
LOG((TL_ERROR,
"lineBlindTransferW: bad lpszDestAddress: 0x%p",
lpszDestAddress
));
return(LINEERR_INVALPOINTER);
}
return (DOFUNC (&funcArgs, "lineBlindTransfer"));
}
LONG
WINAPI
lineBlindTransferA(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
LONG lResult;
PWSTR szTempPtr;
if ( IsBadStringPtrA( lpszDestAddress, (UINT)-1 ) )
{
LOG((TL_ERROR,
"lineBlindTransferA: bad lpszDestAddress: 0x%08lx",
lpszDestAddress
));
return(LINEERR_INVALPOINTER);
}
szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
if ( !szTempPtr )
{
LOG((TL_ERROR,
"lineBlindTransferA: NotSoWideStringToWideString returned NULL"
));
return(LINEERR_INVALPOINTER);
}
lResult = lineBlindTransferW (hCall, szTempPtr, dwCountryCode);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
lineBlindTransfer(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
return lineBlindTransferA(
hCall,
lpszDestAddress,
dwCountryCode
);
}
LONG
WINAPI
lineClose(
HLINE hLine
)
{
LONG lResult;
DWORD Handle = 0;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lClose),
{
(ULONG_PTR) hLine,
(ULONG_PTR) &Handle
},
{
Dword,
lpDword
}
};
lResult = DOFUNC (&funcArgs, "lineClose");
if (0 == lResult &&
0 != Handle)
{
DereferenceObject (ghHandleTable, Handle, 1);
}
return lResult;
}
void
PASCAL
lineCompleteCallPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineCompleteCallPostProcess: enter"));
LOG((TL_INFO,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwCompletionID = (DWORD) pMsg->Param3;
LPDWORD lpdwCompletionID = (LPDWORD) ReferenceObject (ghHandleTable, pMsg->Param4, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param4, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPDWORD lpdwCompletionIDVDM = (LPDWORD) gpfnWOWGetVDMPointer (
(DWORD) lpdwCompletionID,
sizeof(DWORD),
TRUE // fProtectedMode
);
if (lpdwCompletionIDVDM)
{
*lpdwCompletionIDVDM = dwCompletionID;
}
else
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
#endif
}
else
{
*lpdwCompletionID = dwCompletionID;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineCompleteCall(
HCALL hCall,
LPDWORD lpdwCompletionID,
DWORD dwCompletionMode,
DWORD dwMessageID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteCall),
{
(ULONG_PTR) GetFunctionIndex(lineCompleteCallPostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) lpdwCompletionID,
(ULONG_PTR) dwCompletionMode,
(ULONG_PTR) dwMessageID
},
{
Dword,
Dword,
Dword,
Dword,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lpdwCompletionID))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpdwCompletionID, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineCompleteCall");
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineCompleteTransfer(
HCALL hCall,
HCALL hConsultCall,
LPHCALL lphConfCall,
DWORD dwTransferMode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteTransfer),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) hConsultCall,
(ULONG_PTR) lphConfCall,
(ULONG_PTR) dwTransferMode,
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
}
};
DWORD hPointer = 0;
LONG lResult;
if (dwTransferMode == LINETRANSFERMODE_TRANSFER)
{
//
// lphCall should be ignored
//
funcArgs.Args[0] = 0; // (POSTPROCESSPROC) NULL;
}
else if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConfCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConfCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineCompleteTransfer");
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineConfigDialogW(
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass
)
{
LONG lResult;
HANDLE hDll;
TUISPIPROC pfnTUISPI_lineConfigDialog;
if (lpszDeviceClass && TAPIIsBadStringPtrW (lpszDeviceClass, 256))
{
return LINEERR_INVALPOINTER;
}
if ((lResult = LoadUIDll(
hwndOwner,
dwDeviceID,
TUISPIDLL_OBJECT_LINEID,
&hDll,
gszTUISPI_lineConfigDialog,
&pfnTUISPI_lineConfigDialog
)) == 0)
{
LOG((TL_TRACE, "Calling TUISPI_lineConfigDialog..."));
lResult = (*pfnTUISPI_lineConfigDialog)(
TUISPIDLLCallback,
dwDeviceID,
hwndOwner,
lpszDeviceClass
);
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"TUISPI_lineConfigDialog: result = %hs",
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
"TUISPI_lineConfigDialog: result = x%x",
lResult
));
#endif
FreeLibrary (hDll);
}
return lResult;
}
LONG
WINAPI
lineConfigDialogA(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass
)
{
PWSTR szTempString = NULL;
LONG lResult;
if (lpszDeviceClass && IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
szTempString = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
lResult = lineConfigDialogW (dwDeviceID, hwndOwner, szTempString);
if (szTempString)
{
ClientFree (szTempString);
}
return lResult;
}
LONG
WINAPI
lineConfigDialog(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass
)
{
return lineConfigDialogA(
dwDeviceID,
hwndOwner,
lpszDeviceClass
);
}
LONG
WINAPI
lineConfigDialogEditW(
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass,
LPVOID const lpDeviceConfigIn,
DWORD dwSize,
LPVARSTRING lpDeviceConfigOut
)
{
LONG lResult;
HANDLE hDll;
TUISPIPROC pfnTUISPI_lineConfigDialogEdit;
if (lpszDeviceClass && TAPIIsBadStringPtrW (lpszDeviceClass, (UINT) -1))
{
return LINEERR_INVALPOINTER;
}
if (IsBadReadPtr (lpDeviceConfigIn, dwSize))
{
return LINEERR_INVALPOINTER;
}
if (IsBadWritePtr (lpDeviceConfigOut, sizeof (VARSTRING)))
{
return LINEERR_INVALPOINTER;
}
if (lpDeviceConfigOut->dwTotalSize < sizeof (VARSTRING))
{
return LINEERR_STRUCTURETOOSMALL;
}
if (IsBadWritePtr (lpDeviceConfigOut, lpDeviceConfigOut->dwTotalSize))
{
return LINEERR_INVALPOINTER;
}
if ((lResult = LoadUIDll(
hwndOwner,
dwDeviceID,
TUISPIDLL_OBJECT_LINEID,
&hDll,
gszTUISPI_lineConfigDialogEdit,
&pfnTUISPI_lineConfigDialogEdit
)) == 0)
{
LOG((TL_TRACE, "Calling TUISPI_lineConfigDialogEdit..."));
lResult = (*pfnTUISPI_lineConfigDialogEdit)(
TUISPIDLLCallback,
dwDeviceID,
hwndOwner,
lpszDeviceClass,
lpDeviceConfigIn,
dwSize,
lpDeviceConfigOut
);
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"TUISPI_lineConfigDialogEdit: result = %hs",
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
"TUISPI_lineConfigDialogEdit: result = x%x",
lResult
));
#endif
FreeLibrary (hDll);
}
return lResult;
}
LONG
WINAPI
lineConfigDialogEditA(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass,
LPVOID const lpDeviceConfigIn,
DWORD dwSize,
LPVARSTRING lpDeviceConfigOut
)
{
PWSTR szTempString;
LONG lResult;
if (lpszDeviceClass && IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
szTempString = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
lResult = lineConfigDialogEditW(
dwDeviceID,
hwndOwner,
szTempString,
lpDeviceConfigIn,
dwSize,
lpDeviceConfigOut
);
if (szTempString)
{
ClientFree (szTempString);
}
return lResult;
}
LONG
WINAPI
lineConfigDialogEdit(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass,
LPVOID const lpDeviceConfigIn,
DWORD dwSize,
LPVARSTRING lpDeviceConfigOut
)
{
return lineConfigDialogEditA(
dwDeviceID,
hwndOwner,
lpszDeviceClass,
lpDeviceConfigIn,
dwSize,
lpDeviceConfigOut
);
}
LONG
WINAPI
lineConfigProvider(
HWND hwndOwner,
DWORD dwPermanentProviderID
)
{
return (lineXxxProvider(
gszTUISPI_providerConfig, // func name
NULL, // lpszProviderFilename
hwndOwner, // hwndOwner
dwPermanentProviderID, // dwPermProviderID
NULL // lpdwPermProviderID
));
}
LONG
WINAPI
lineCreateAgentW(
HLINE hLine,
LPWSTR lpszAgentID,
LPWSTR lpszAgentPIN,
LPHAGENT lphAgent
)
{
DWORD hPointer = 0;
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lCreateAgent),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lpszAgentID,
(ULONG_PTR) lpszAgentPIN,
(ULONG_PTR) lphAgent
},
{
Dword,
Dword,
lpszAgentID?lpszW:Dword,
lpszAgentPIN?lpszW:Dword,
Dword,
}
};
if ( NULL == lpszAgentID )
{
funcArgs.Args[2] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
else if ( TAPIIsBadStringPtrW(lpszAgentID, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentID in lineCreateAgentW"));
return( LINEERR_INVALPOINTER );
}
if ( NULL == lpszAgentPIN )
{
funcArgs.Args[3] = TAPI_NO_DATA;
funcArgs.ArgTypes[3] = Dword;
}
else if ( TAPIIsBadStringPtrW(lpszAgentPIN, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentPIN in lineCreateAgentW"));
return( LINEERR_INVALPOINTER );
}
if (IsBadDwordPtr (lphAgent))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphAgent, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineCreateAgentW");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineCreateAgentA(
HLINE hLine,
LPSTR lpszAgentID,
LPSTR lpszAgentPIN,
LPHAGENT lphAgent
)
{
PWSTR pwAgentID;
PWSTR pwAgentPIN;
LONG lResult;
if (lpszAgentID)
{
if ( IsBadStringPtrA(lpszAgentID, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentID in lineCreateAgentA"));
return( LINEERR_INVALPOINTER );
}
pwAgentID = NotSoWideStringToWideString (lpszAgentID, (DWORD) -1);
}
else
{
pwAgentID = NULL;
}
if (lpszAgentPIN)
{
if ( IsBadStringPtrA(lpszAgentPIN, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentPIN in lineCreateAgentA"));
return( LINEERR_INVALPOINTER );
}
pwAgentPIN = NotSoWideStringToWideString (lpszAgentPIN, (DWORD) -1);
}
else
{
pwAgentPIN = NULL;
}
lResult = lineCreateAgentW (hLine, pwAgentID, pwAgentPIN, lphAgent);
if (pwAgentPIN)
{
ClientFree (pwAgentPIN);
}
if (pwAgentID)
{
ClientFree (pwAgentID);
}
return lResult;
}
LONG
WINAPI
lineCreateAgentSessionW(
HLINE hLine,
HAGENT hAgent,
LPWSTR lpszAgentPIN,
DWORD dwWorkingAddressID,
LPGUID lpGroupID,
LPHAGENTSESSION lphAgentSession
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lCreateAgentSession),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) hAgent,
(ULONG_PTR) lpszAgentPIN,
(ULONG_PTR) dwWorkingAddressID,
(ULONG_PTR) lpGroupID,
(ULONG_PTR) sizeof( GUID ),
(ULONG_PTR) lphAgentSession
},
{
Dword,
Dword,
Dword,
lpszAgentPIN?lpszW:Dword,
Dword,
lpSet_SizeToFollow,
Size,
Dword,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( NULL == lpszAgentPIN )
{
funcArgs.Args[3] = TAPI_NO_DATA;
funcArgs.ArgTypes[3] = Dword;
}
else if ( TAPIIsBadStringPtrW(lpszAgentPIN, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentPIN in lineCreateAgentSessionW"));
return( LINEERR_INVALPOINTER );
}
if (IsBadDwordPtr (lphAgentSession))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphAgentSession, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[7] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineCreateAgentSessionW");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineCreateAgentSessionA(
HLINE hLine,
HAGENT hAgent,
LPSTR lpszAgentPIN,
DWORD dwWorkingAddressID,
LPGUID lpGroupID,
LPHAGENTSESSION lphAgentSession
)
{
LONG lResult;
PWSTR pwAgentPIN;
if (lpszAgentPIN)
{
if ( IsBadStringPtrA(lpszAgentPIN, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszAgentPIN in lineCreateAgentSessionA"));
return( LINEERR_INVALPOINTER );
}
pwAgentPIN = NotSoWideStringToWideString (lpszAgentPIN, (DWORD) -1);
}
else
{
pwAgentPIN = NULL;
}
lResult = lineCreateAgentSessionW(
hLine,
hAgent,
pwAgentPIN,
dwWorkingAddressID,
lpGroupID,
lphAgentSession
);
if (pwAgentPIN)
{
ClientFree (pwAgentPIN);
}
return lResult;
}
LONG
WINAPI
lineDeallocateCall(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
{
(ULONG_PTR) hCall
},
{
Dword
}
};
LOG((TL_TRACE,
"lineDeallocateCall: enter on thread: 0x%08lx",
GetCurrentThreadId()
));
LOG((TL_INFO, " hCall = 0x%08lx", hCall));
return (DOFUNC (&funcArgs, "lineDeallocateCall"));
}
void
PASCAL
lineDevSpecificPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineDevSpecificPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
if (dwSize != 0)
{
LPBYTE pParams = (LPBYTE) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPBYTE pParamsVDM = (LPBYTE) gpfnWOWGetVDMPointer(
(DWORD) pParams,
dwSize,
TRUE // fProtectedMode
);
if (pParamsVDM)
{
CopyMemory (pParamsVDM, (LPBYTE) (pMsg + 1), dwSize);
}
else
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
#endif
}
else
{
CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
}
LONG
WINAPI
lineDevSpecific(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
LPVOID lpParams,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecific),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) hCall,
(ULONG_PTR) lpParams, // pass the actual pointer (for post proc'g)
(ULONG_PTR) lpParams, // pass data
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size,
}
};
DWORD hPointer = 0;
LONG lResult;
if (gbNTVDMClient)
{
#ifndef _WIN64
if (!gpfnWOWGetVDMPointer ||
!(funcArgs.Args[5] = gpfnWOWGetVDMPointer(
(DWORD) lpParams,
dwSize,
TRUE // fProtectedMode
)))
#endif
{
return LINEERR_OPERATIONFAILED;
}
}
if ( !lpParams && dwSize > 0)
{
return LINEERR_INVALPOINTER;
}
if (dwSize > 0)
{
hPointer = NewObject (ghHandleTable, (PVOID)lpParams, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineDevSpecific");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineDevSpecificFeature(
HLINE hLine,
DWORD dwFeature,
LPVOID lpParams,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lDevSpecificFeature),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwFeature,
(ULONG_PTR) lpParams, // pass the actual pointer (for post processing)
(ULONG_PTR) lpParams, // pass data
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
DWORD hPointer = 0;
LONG lResult;
if (gbNTVDMClient)
{
#ifndef _WIN64
if (!gpfnWOWGetVDMPointer ||
!(funcArgs.Args[4] = gpfnWOWGetVDMPointer(
(DWORD) lpParams,
dwSize,
TRUE // fProtectedMode
)))
#endif
{
return LINEERR_OPERATIONFAILED;
}
}
if ( !lpParams && dwSize > 0)
{
return LINEERR_INVALPOINTER;
}
if (dwSize > 0)
{
hPointer = NewObject (ghHandleTable, (PVOID)lpParams, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineDevSpecificFeature");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineDialW(
HCALL hCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lDial),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) dwCountryCode
},
{
Dword,
lpszW,
Dword
}
};
if ( TAPIIsBadStringPtrW(lpszDestAddress, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineDialW"));
return( LINEERR_INVALPOINTER );
}
return (DOFUNC (&funcArgs, "lineDial"));
}
LONG
WINAPI
lineDialA(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
LONG lResult;
PWSTR szTempPtr;
if ( IsBadStringPtrA(lpszDestAddress, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineDialA"));
return( LINEERR_INVALPOINTER );
}
szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
if ( !szTempPtr )
{
LOG((TL_ERROR, "lineDialA: NotSoWideStringToWideString returned NULL"));
return( LINEERR_INVALPOINTER );
}
lResult = lineDialW (hCall, szTempPtr, dwCountryCode);
ClientFree (szTempPtr);
return lResult;
}
LONG
WINAPI
lineDial(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
return lineDialA(
hCall,
lpszDestAddress,
dwCountryCode
);
}
LONG
WINAPI
lineDrop(
HCALL hCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lDrop),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpsUserUserInfo,
(ULONG_PTR) dwSize
},
{
Dword,
lpSet_SizeToFollow,
Size
}
};
if (!lpsUserUserInfo)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineDrop"));
}
LONG
WINAPI
lineForwardW(
HLINE hLine,
DWORD bAllAddresses,
DWORD dwAddressID,
LPLINEFORWARDLIST const lpForwardList,
DWORD dwNumRingsNoAnswer,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 9, lForward),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) bAllAddresses,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpForwardList,
(ULONG_PTR) dwNumRingsNoAnswer,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpForwardList)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[4] = Dword;
funcArgs.Args[4] = TAPI_NO_DATA;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[7] = Dword;
funcArgs.Args[7] = TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[6] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineForwardW");
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
// void
// LayDownNewString(
// LPBYTE pOldBase,
// LPDWORD pdwOldSizeOffset,
// LPBYTE pNewBase,
// LPDWORD pdwNewSizeOffset,
// LPDWORD pdwNewOffset
// )
// {
// LPBYTE pOldString;
// DWORD dwNewStringSize;
//
//
// pOldString = pOldBase + *(pdwOldSizeOffset + 1);
//
// *(pdwNewSizeOffset + 1) = *pdwNewOffset;
//
// if ( IsBadStringPtr( pOldString, 256) )
// {
// return;
// }
//
// dwNewStringSize = sizeof(WCHAR) * MultiByteToWideChar(
// GetACP(),
// MB_PRECOMPOSED,
// pOldString,
// *pdwOldSizeOffset,
// (PWSTR)(pNewBase + *(pdwNewSizeOffset + 1)),
// *pdwOldSizeOffset
// );
//
// *pdwNewSizeOffset = dwNewStringSize;
//
// *pdwNewOffset = (*pdwNewOffset + dwNewStringSize + 3) & 0xfffffffc;
// }
LONG
WINAPI
lineForwardA(
HLINE hLine,
DWORD bAllAddresses,
DWORD dwAddressID,
LPLINEFORWARDLIST const lpForwardList,
DWORD dwNumRingsNoAnswer,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 9, lForward),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) bAllAddresses,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpForwardList,
(ULONG_PTR) dwNumRingsNoAnswer,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP() // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpForwardList)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[4] = Dword;
funcArgs.Args[4] = TAPI_NO_DATA;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[7] = Dword;
funcArgs.Args[7] = TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[6] = (ULONG_PTR)hPointer;
}
lResult = DOFUNC (&funcArgs, "lineForward");
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineForward(
HLINE hLine,
DWORD bAllAddresses,
DWORD dwAddressID,
LPLINEFORWARDLIST const lpForwardList,
DWORD dwNumRingsNoAnswer,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
return lineForwardA(
hLine,
bAllAddresses,
dwAddressID,
lpForwardList,
dwNumRingsNoAnswer,
lphConsultCall,
lpCallParams
);
}
void
PASCAL
lineGatherDigitsWPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGatherDigitsWPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param1 & (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
{
LPSTR lpsDigits = (LPSTR) ReferenceObject (ghHandleTable, pMsg->Param2, 0);
DWORD dwNumDigits = (DWORD) pMsg->Param4;
#if NEWTAPI32
LPBYTE lpBuf = (LPBYTE)(((ULONG_PTR *)(pMsg + 1)) + 2);
#endif
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param2, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPSTR lpsDigitsVDM = (LPSTR) gpfnWOWGetVDMPointer(
(DWORD) lpsDigits,
dwNumDigits * sizeof(WCHAR),
TRUE // fProtectedMode
);
if (lpsDigitsVDM)
{
#if NEWTAPI32
CopyMemory(
lpsDigitsVDM,
lpBuf,
dwNumDigits * sizeof (WCHAR)
);
#else
CopyMemory(
lpsDigitsVDM,
pMsg + 1,
dwNumDigits * sizeof (WCHAR)
);
#endif
}
else
{
}
#endif
}
else
{
CopyMemory (lpsDigits, lpBuf, dwNumDigits * sizeof(WCHAR));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
//
// Don't do anything if we GPF
//
}
}
pMsg->Param2 = 0;
}
LONG
WINAPI
lineGatherDigitsW(
HCALL hCall,
DWORD dwDigitModes,
LPWSTR lpsDigits,
DWORD dwNumDigits,
LPCWSTR lpszTerminationDigits,
DWORD dwFirstDigitTimeout,
DWORD dwInterDigitTimeout
)
{
FUNC_ARGS funcArgs =
{
#if NEWTAPI32
MAKELONG (LINE_FUNC | SYNC | 9, lGatherDigits),
#else
MAKELONG (LINE_FUNC | SYNC | 8, lGatherDigits),
#endif
{
(ULONG_PTR) GetFunctionIndex(lineGatherDigitsWPostProcess),
(ULONG_PTR) hCall,
#if NEWTAPI32
(ULONG_PTR) 0, // this is the dwendtoendid for remotesp
#endif
(ULONG_PTR) dwDigitModes,
(ULONG_PTR) lpsDigits,
(ULONG_PTR) dwNumDigits,
(ULONG_PTR) lpszTerminationDigits,
(ULONG_PTR) dwFirstDigitTimeout,
(ULONG_PTR) dwInterDigitTimeout
},
{
Dword,
Dword,
#if NEWTAPI32
Dword,
#endif
Dword,
Dword,
Dword,
lpszW,
Dword,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
//
// Note: we do the ptr check here rather than in DOFUNC because we're
// not passing any digits data within the context of this func
//
if (lpsDigits && IsBadWritePtr (lpsDigits, dwNumDigits * sizeof (WCHAR)))
{
return LINEERR_INVALPOINTER;
}
if (lpszTerminationDigits == (LPCWSTR) NULL)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
#if NEWTAPI32
funcArgs.ArgTypes[6] = Dword;
funcArgs.Args[6] = TAPI_NO_DATA;
#else
funcArgs.ArgTypes[5] = Dword;
funcArgs.Args[5] = TAPI_NO_DATA;
#endif
}
else
{
if ( TAPIIsBadStringPtrW(lpszTerminationDigits, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGatherDigitsW"));
return( LINEERR_INVALPOINTER );
}
}
if ( lpsDigits )
{
hPointer = NewObject (ghHandleTable, (PVOID)lpsDigits, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
}
else
{
funcArgs.Args[4] = (ULONG_PTR) 0;
}
lResult = DOFUNC (&funcArgs, "lineGatherDigits");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGatherDigitsPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGatherDigitsPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param1 & (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
{
LPSTR lpsDigits = (LPSTR) ReferenceObject (ghHandleTable, pMsg->Param2, 0);
DWORD dwNumDigits = (DWORD) pMsg->Param4;
LPWSTR pBuffer = (LPWSTR) (((ULONG_PTR *)(pMsg + 1)) + 2);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param2, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPSTR lpsDigitsVDM = (LPSTR) gpfnWOWGetVDMPointer(
(DWORD) lpsDigits,
dwNumDigits * sizeof(WCHAR),
TRUE // fProtectedMode
);
if (lpsDigitsVDM)
{
WideCharToMultiByte(
GetACP(),
0,
#if NEWTAPI32
pBuffer,
#else
(LPCWSTR)(pMsg + 1),
#endif
dwNumDigits,
lpsDigitsVDM,
dwNumDigits,
NULL,
NULL
);
}
else
{
}
#endif
}
else
{
WideCharToMultiByte(
GetACP(),
0,
#if NEWTAPI32
pBuffer,
#else
(LPCWSTR)(pMsg + 1),
#endif
dwNumDigits,
lpsDigits,
dwNumDigits,
NULL,
NULL
);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
//
// Don't do anything if we GPF
//
}
}
pMsg->Param2 = 0;
}
LONG
WINAPI
lineGatherDigitsA(
HCALL hCall,
DWORD dwDigitModes,
LPSTR lpsDigits,
DWORD dwNumDigits,
LPCSTR lpszTerminationDigits,
DWORD dwFirstDigitTimeout,
DWORD dwInterDigitTimeout
)
{
LONG lResult;
DWORD hPointer = 0;
FUNC_ARGS funcArgs =
{
#if NEWTAPI32
MAKELONG (LINE_FUNC | SYNC | 9, lGatherDigits),
#else
MAKELONG (LINE_FUNC | SYNC | 8, lGatherDigits),
#endif
{
(ULONG_PTR) GetFunctionIndex(lineGatherDigitsPostProcess),
(ULONG_PTR) hCall,
#if NEWTAPI32
(ULONG_PTR) 0, // dw end to end id for remotesp
#endif
(ULONG_PTR) dwDigitModes,
(ULONG_PTR) lpsDigits,
(ULONG_PTR) dwNumDigits,
//BJM 06/04/97 what was this? 0, // (DWORD) lpszTerminationDigits,
(ULONG_PTR) lpszTerminationDigits,
(ULONG_PTR) dwFirstDigitTimeout,
(ULONG_PTR) dwInterDigitTimeout
},
{
Dword,
Dword,
#if NEWTAPI32
Dword,
#endif
Dword,
Dword,
Dword,
lpszW,
Dword,
Dword
}
};
//
// Note: we do the ptr check here rather than in DOFUNC because we're
// not passing any digits data within the context of this func
//
if (gbNTVDMClient == FALSE)
{
if (lpsDigits && IsBadWritePtr (lpsDigits, dwNumDigits))
{
return LINEERR_INVALPOINTER;
}
}
if (lpszTerminationDigits == (LPCSTR) NULL)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
#if NEWTAPI32
funcArgs.ArgTypes[6] = Dword;
funcArgs.Args[6] = TAPI_NO_DATA;
#else
funcArgs.ArgTypes[5] = Dword;
funcArgs.Args[5] = TAPI_NO_DATA;
#endif
}
else
{
if ( IsBadStringPtrA(lpszTerminationDigits, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGatherDigitsA"));
return( LINEERR_INVALPOINTER );
}
#if NEWTAPI32
funcArgs.Args[6] = (ULONG_PTR) NotSoWideStringToWideString(
lpszTerminationDigits,
(DWORD) -1
);
#else
funcArgs.Args[5] = (ULONG_PTR) NotSoWideStringToWideString(
lpszTerminationDigits,
(DWORD) -1
);
#endif
}
if ( lpsDigits )
{
hPointer = NewObject (ghHandleTable, (PVOID)lpsDigits, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
}
else
{
funcArgs.Args[4] = (ULONG_PTR) 0;
}
lResult = (DOFUNC (&funcArgs, "lineGatherDigits"));
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
#if NEWTAPI32
if ( funcArgs.Args[6] && (funcArgs.Args[6] != TAPI_NO_DATA) )
{
ClientFree( (LPVOID)funcArgs.Args[6] );
}
#else
if ( funcArgs.Args[5] && (funcArgs.Args[5] != TAPI_NO_DATA) )
{
ClientFree( (LPVOID)funcArgs.Args[5] );
}
#endif
return lResult;
}
LONG
WINAPI
lineGatherDigits(
HCALL hCall,
DWORD dwDigitModes,
LPSTR lpsDigits,
DWORD dwNumDigits,
LPCSTR lpszTerminationDigits,
DWORD dwFirstDigitTimeout,
DWORD dwInterDigitTimeout
)
{
return lineGatherDigitsA(
hCall,
dwDigitModes,
lpsDigits,
dwNumDigits,
lpszTerminationDigits,
dwFirstDigitTimeout,
dwInterDigitTimeout
);
}
LONG
WINAPI
lineGenerateDigitsW(
HCALL hCall,
DWORD dwDigitMode,
LPCWSTR lpszDigits,
DWORD dwDuration
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwDigitMode,
(ULONG_PTR) lpszDigits,
(ULONG_PTR) dwDuration,
(ULONG_PTR) 0 // dwEndToEndID, remotesp only
},
{
Dword,
Dword,
lpszW,
Dword,
Dword
}
};
if (!lpszDigits)
{
funcArgs.Args[2] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineGenerateDigits"));
}
LONG
WINAPI
lineGenerateDigitsA(
HCALL hCall,
DWORD dwDigitMode,
LPCSTR lpszDigits,
DWORD dwDuration
)
{
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGenerateDigits),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwDigitMode,
(ULONG_PTR) 0, // (DWORD) lpszDigits,
(ULONG_PTR) dwDuration,
(ULONG_PTR) 0 // dwEndToEndID, remotesp only
},
{
Dword,
Dword,
lpszW,
Dword,
Dword
}
};
if (lpszDigits)
{
if (IsBadStringPtrA (lpszDigits, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
else if (!(funcArgs.Args[2] = (ULONG_PTR) NotSoWideStringToWideString(
lpszDigits,
(DWORD) -1
)))
{
return LINEERR_NOMEM;
}
}
else
{
funcArgs.Args[2] = TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
lResult = (DOFUNC (&funcArgs, "lineGenerateDigits"));
if (funcArgs.Args[2] != TAPI_NO_DATA)
{
ClientFree ((LPVOID) funcArgs.Args[2]);
}
return lResult;
}
LONG
WINAPI
lineGenerateDigits(
HCALL hCall,
DWORD dwDigitMode,
LPCSTR lpszDigits,
DWORD dwDuration
)
{
return lineGenerateDigitsA(
hCall,
dwDigitMode,
lpszDigits,
dwDuration
);
}
LONG
WINAPI
lineGenerateTone(
HCALL hCall,
DWORD dwToneMode,
DWORD dwDuration,
DWORD dwNumTones,
LPLINEGENERATETONE const lpTones
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lGenerateTone),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwToneMode,
(ULONG_PTR) dwDuration,
(ULONG_PTR) dwNumTones,
(ULONG_PTR) TAPI_NO_DATA, // (DWORD) lpTones,
(ULONG_PTR) 0, // dwNumTones * sizeof(LINEGENERATETONE)
(ULONG_PTR) 0 // dwEndToEndID, remotesp only
},
{
Dword,
Dword,
Dword,
Dword,
Dword, // lpSet_SizeToFollow,
Dword, // Size
Dword
}
};
if (dwToneMode == LINETONEMODE_CUSTOM)
{
//
// Set lpTones (& following Size arg) since in this case
// they are valid args
//
funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
funcArgs.Args[4] = (ULONG_PTR) lpTones;
funcArgs.ArgTypes[5] = Size;
funcArgs.Args[5] = dwNumTones * sizeof(LINEGENERATETONE);
}
return (DOFUNC (&funcArgs, "lineGenerateTone"));
}
LONG
WINAPI
lineGetAddressCapsW(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lGetAddressCaps),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) lpAddressCaps
},
{
hXxxApp,
Dword,
Dword,
Dword,
Dword,
lpGet_Struct
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "lineGetAddressCaps"));
}
LONG
WINAPI
lineGetAddressCapsA(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps
)
{
LONG lResult;
lResult = lineGetAddressCapsW(
hLineApp,
dwDeviceID,
dwAddressID,
dwAPIVersion,
dwExtVersion,
lpAddressCaps
);
if (lResult == 0)
{
WideStringToNotSoWideString(
(LPBYTE)lpAddressCaps,
&lpAddressCaps->dwAddressSize
);
//
// WideChar to multibyte translation of the completion message
// array is somewhat problematic in that we can't be sure
// the msgs will all be the same size after translation. So
// we'll translate them, pad the remainder of each msg entry
// with 0's, and not bother touching any of the size or
// offset values.
//
if (lpAddressCaps->dwNumCompletionMessages &&
lpAddressCaps->dwCompletionMsgTextEntrySize)
{
PWSTR pStrW;
PSTR pStrA;
DWORD dwMsgSize = lpAddressCaps->dwCompletionMsgTextEntrySize,
dwNewSize, i;
if ((pStrA = ClientAlloc (dwMsgSize)))
{
pStrW = (PWSTR) (((LPBYTE) lpAddressCaps) +
lpAddressCaps->dwCompletionMsgTextOffset);
for (i = 0; i < lpAddressCaps->dwNumCompletionMessages; i++)
{
dwNewSize = WideCharToMultiByte(
GetACP(),
0,
pStrW,
dwMsgSize / sizeof(WCHAR),
pStrA,
dwMsgSize,
NULL,
NULL
);
CopyMemory (pStrW, pStrA, dwNewSize);
ZeroMemory(
((LPBYTE) pStrW) + dwNewSize,
dwMsgSize - dwNewSize
);
pStrW = (PWSTR) (((LPBYTE) pStrW) + dwMsgSize);
}
ClientFree (pStrA);
}
else
{
lpAddressCaps->dwNumCompletionMessages =
lpAddressCaps->dwCompletionMsgTextEntrySize =
lpAddressCaps->dwCompletionMsgTextSize =
lpAddressCaps->dwCompletionMsgTextOffset = 0;
}
}
if (dwAPIVersion >= 0x00020000)
{
WideStringToNotSoWideString(
(LPBYTE)lpAddressCaps,
&lpAddressCaps->dwDeviceClassesSize
);
}
}
return lResult;
}
LONG
WINAPI
lineGetAddressCaps(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps
)
{
return lineGetAddressCapsA(
hLineApp,
dwDeviceID,
dwAddressID,
dwAPIVersion,
dwExtVersion,
lpAddressCaps
);
}
LONG
WINAPI
lineGetAddressIDW(
HLINE hLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCWSTR lpsAddress,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGetAddressID),
{
(ULONG_PTR) hLine,
(ULONG_PTR) lpdwAddressID,
(ULONG_PTR) dwAddressMode,
(ULONG_PTR) lpsAddress,
(ULONG_PTR) dwSize
},
{
Dword,
lpDword,
Dword,
lpSet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "lineGetAddressID"));
}
LONG
WINAPI
lineGetAddressIDA(
HLINE hLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCSTR lpsAddress,
DWORD dwSize
)
{
LONG lResult;
DWORD dwNumChars;
PWSTR szTempPtr;
//
// Special case for dwSize = -1 (implies a NULL-terminated string as
// far as IsBadStringPtrA is concerned)
//
if (dwSize == 0 || IsBadReadPtr (lpsAddress, dwSize))
{
LOG((TL_ERROR, "lineGetAddressID: Bad lpsAddress or dwSize"));
return LINEERR_INVALPOINTER;
}
dwNumChars = MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpsAddress,
dwSize,
NULL,
0
);
if (!(szTempPtr = ClientAlloc (dwNumChars * sizeof (WCHAR))))
{
return LINEERR_NOMEM;
}
MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpsAddress,
dwSize,
szTempPtr,
dwNumChars
);
lResult = lineGetAddressIDW(
hLine,
lpdwAddressID,
dwAddressMode,
szTempPtr,
dwNumChars * sizeof (WCHAR)
);
ClientFree (szTempPtr);
return lResult;
}
LONG
WINAPI
lineGetAddressID(
HLINE hLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCSTR lpsAddress,
DWORD dwSize
)
{
return lineGetAddressIDA(
hLine,
lpdwAddressID,
dwAddressMode,
lpsAddress,
dwSize
);
}
LONG
WINAPI
lineGetAddressStatusW(
HLINE hLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetAddressStatus),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAddressStatus
},
{
Dword,
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetAddressStatus"));
}
LONG
WINAPI
lineGetAddressStatusA(
HLINE hLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus
)
{
LONG lResult;
PWSTR szTempPtr = NULL;
if ( IsBadWritePtr(lpAddressStatus, sizeof(LINEADDRESSSTATUS)) )
{
LOG((TL_ERROR, "lineGetAddressStatus: Bad lpAddressStatus pointer"));
return LINEERR_INVALPOINTER;
}
lResult = lineGetAddressStatusW(
hLine,
dwAddressID,
lpAddressStatus
);
if (lResult == 0)
{
DWORD i;
LPLINEFORWARD lplf;
lplf = (LPLINEFORWARD) (((LPBYTE)lpAddressStatus) +
lpAddressStatus->dwForwardOffset);
for (i = 0; i < lpAddressStatus->dwForwardNumEntries; i++, lplf++)
{
WideStringToNotSoWideString(
(LPBYTE) lpAddressStatus,
&(lplf->dwCallerAddressSize)
);
WideStringToNotSoWideString(
(LPBYTE) lpAddressStatus,
&(lplf->dwDestAddressSize)
);
}
}
return lResult;
}
LONG
WINAPI
lineGetAddressStatus(
HLINE hLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus
)
{
return lineGetAddressStatusA(
hLine,
dwAddressID,
lpAddressStatus
);
}
LONG
WINAPI
lineGetAgentActivityListW(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTACTIVITYLIST lpAgentActivityList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentActivityList),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentActivityList,// pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentActivityList // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentActivityList || IsBadWritePtr(lpAgentActivityList, sizeof(LINEAGENTACTIVITYLIST)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentActivityList->dwTotalSize < sizeof(LINEAGENTACTIVITYLIST))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentActivityList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetAgentActivityListW"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGetAgentActivityListAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGetAgentActivityListAPostProcess: enter"));
LOG((TL_INFO,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPLINEAGENTACTIVITYLIST lpAgentActivityList = (LPLINEAGENTACTIVITYLIST)
ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
DWORD dw, dwNumEntries;
LPLINEAGENTACTIVITYENTRY lplaae;
//
// Note: the agent APIs are not exposed to 16-bit apps, so
// there's no reason to special case on gbNTVDMClient like
// lineDevSpecificPostProcess does
//
CopyMemory (lpAgentActivityList, (LPBYTE) (pMsg + 1), dwSize);
//
// Now some unicode->ascii post processing on embedded strings
//
lplaae = (LPLINEAGENTACTIVITYENTRY)(((LPBYTE)lpAgentActivityList) +
lpAgentActivityList->dwListOffset);
dwNumEntries = lpAgentActivityList->dwNumEntries;
for (dw = 0; dw < dwNumEntries; dw++, lplaae++)
{
WideStringToNotSoWideString(
(LPBYTE) lpAgentActivityList,
&(lplaae->dwNameSize)
);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineGetAgentActivityListA(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTACTIVITYLIST lpAgentActivityList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentActivityList),
{
(ULONG_PTR) GetFunctionIndex(lineGetAgentActivityListAPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentActivityList,// pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentActivityList // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentActivityList )
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentActivityList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentActivityListA");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentCapsW(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwAppAPIVersion,
LPLINEAGENTCAPS lpAgentCaps
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwAppAPIVersion,
(ULONG_PTR) lpAgentCaps, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentCaps // pass data
},
{
Dword,
hXxxApp,
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentCaps || IsBadWritePtr(lpAgentCaps, sizeof(LINEAGENTCAPS)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentCaps->dwTotalSize < sizeof(LINEAGENTCAPS))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentCaps, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[5] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentCapsW");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGetAgentCapsAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGetAgentCapsAPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPLINEAGENTCAPS lpAgentCaps = (LPLINEAGENTCAPS) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
//
// Note: the agent APIs are not exposed to 16-bit apps, so
// there's no reason to special case on gbNTVDMClient like
// lineDevSpecificPostProcess does
//
CopyMemory (lpAgentCaps, (LPBYTE) (pMsg + 1), dwSize);
//
// Now some unicode->ascii post processing on embedded strings
//
WideStringToNotSoWideString(
(LPBYTE) lpAgentCaps,
&lpAgentCaps->dwAgentHandlerInfoSize
);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineGetAgentCapsA(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwAppAPIVersion,
LPLINEAGENTCAPS lpAgentCaps
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
{
(ULONG_PTR) GetFunctionIndex(lineGetAgentCapsAPostProcess),
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwAppAPIVersion,
(ULONG_PTR) lpAgentCaps, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentCaps // pass data
},
{
Dword,
hXxxApp,
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentCaps )
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentCaps, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[5] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentCapsA");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentGroupListW(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTGROUPLIST lpAgentGroupList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentGroupList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentGroupList // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentGroupList || IsBadWritePtr(lpAgentGroupList, sizeof(LINEAGENTGROUPLIST)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentGroupList->dwTotalSize < sizeof(LINEAGENTGROUPLIST))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentGroupList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentGroupListW");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGetAgentGroupListAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGetAgentGroupListAPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPLINEAGENTGROUPLIST lpAgentGroupList = (LPLINEAGENTGROUPLIST)
ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
DWORD dw, dwNumEntries;
LPLINEAGENTGROUPENTRY lplage;
//
// Note: the agent APIs are not exposed to 16-bit apps, so
// there's no reason to special case on gbNTVDMClient like
// lineDevSpecificPostProcess does
//
CopyMemory (lpAgentGroupList, (LPBYTE) (pMsg + 1), dwSize);
//
// Now some unicode->ascii post processing on embedded strings
//
lplage = (LPLINEAGENTGROUPENTRY)(((LPBYTE) lpAgentGroupList) +
lpAgentGroupList->dwListOffset);
dwNumEntries = lpAgentGroupList->dwNumEntries;
for (dw = 0; dw < dwNumEntries; dw++, lplage++)
{
WideStringToNotSoWideString(
(LPBYTE) lpAgentGroupList,
&(lplage->dwNameSize)
);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineGetAgentGroupListA(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTGROUPLIST lpAgentGroupList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
{
(ULONG_PTR) GetFunctionIndex(lineGetAgentGroupListAPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentGroupList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentGroupList // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentGroupList )
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentGroupList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentGroupListA");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentInfo(
HLINE hLine,
HAGENT hAgent,
LPLINEAGENTINFO lpAgentInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentInfo),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) hAgent,
(ULONG_PTR) lpAgentInfo, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentInfo // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentInfo || IsBadWritePtr(lpAgentInfo, sizeof(LINEAGENTINFO)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentInfo->dwTotalSize < sizeof(LINEAGENTINFO))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentInfo, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentInfo");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentSessionInfo(
HLINE hLine,
HAGENTSESSION hAgentSession,
LPLINEAGENTSESSIONINFO lpAgentSessionInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionInfo),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) hAgentSession,
(ULONG_PTR) lpAgentSessionInfo, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentSessionInfo // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentSessionInfo || IsBadWritePtr(lpAgentSessionInfo, sizeof(LINEAGENTSESSIONINFO)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentSessionInfo->dwTotalSize < sizeof(LINEAGENTSESSIONINFO))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentSessionInfo, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentSessionInfo");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentSessionList(
HLINE hLine,
HAGENT hAgent,
LPLINEAGENTSESSIONLIST lpAgentSessionList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentSessionList),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) hAgent,
(ULONG_PTR) lpAgentSessionList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentSessionList // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentSessionList || IsBadWritePtr(lpAgentSessionList, sizeof(LINEAGENTSESSIONLIST)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentSessionList->dwTotalSize < sizeof(LINEAGENTSESSIONLIST))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentSessionList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentSessionList");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAgentStatusW(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTSTATUS lpAgentStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentStatus, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentStatus // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpAgentStatus || IsBadWritePtr(lpAgentStatus, sizeof(LINEAGENTSTATUS)) )
{
return LINEERR_INVALPOINTER;
}
if (lpAgentStatus->dwTotalSize < sizeof(LINEAGENTSTATUS))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentStatus, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = DOFUNC (&funcArgs, "lineGetAgentStatusW");
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGetAgentStatusAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGetAgentStatusAPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPLINEAGENTSTATUS lpAgentStatus = (LPLINEAGENTSTATUS) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
DWORD dw, dwNumEntries;
LPLINEAGENTGROUPENTRY lplage;
//
// Note: the agent APIs are not exposed to 16-bit apps, so
// there's no reason to special case on gbNTVDMClient like
// lineDevSpecificPostProcess does
//
CopyMemory (lpAgentStatus, (LPBYTE) (pMsg + 1), dwSize);
//
// Now some unicode->ascii post processing on embedded strings
//
lplage = (LPLINEAGENTGROUPENTRY) (((LPBYTE) lpAgentStatus) +
lpAgentStatus->dwGroupListOffset);
dwNumEntries = lpAgentStatus->dwNumEntries;
for (dw = 0; dw < dwNumEntries; dw++, lplage++)
{
WideStringToNotSoWideString(
(LPBYTE)lpAgentStatus,
&(lplage->dwNameSize)
);
}
WideStringToNotSoWideString(
(LPBYTE)lpAgentStatus,
&lpAgentStatus->dwActivitySize
);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineGetAgentStatusA(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTSTATUS lpAgentStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
{
(ULONG_PTR) GetFunctionIndex(lineGetAgentStatusAPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentStatus, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpAgentStatus // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
hPointer = NewObject (ghHandleTable, (PVOID)lpAgentStatus, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetAgentStatusA"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetAppPriorityW(
LPCWSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPVARSTRING lpExtensionName,
LPDWORD lpdwPriority
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lGetAppPriority),
{
(ULONG_PTR) lpszAppName,
(ULONG_PTR) dwMediaMode,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) 0,
(ULONG_PTR) lpdwPriority
},
{
lpszW, // app name
Dword, // media mode
Dword, // ext id (offset)
Dword, // ext id (size)
Dword, // request mode
Dword, // ext name total size
lpDword // lp pri
}
};
if (dwMediaMode & 0xff000000)
{
if ((LPVOID) lpExtensionName == (LPVOID) lpdwPriority)
{
return LINEERR_INVALPOINTER;
}
//
// We have to do some arg list munging here (adding an extra arg)
//
//
// Set lpExtensionID, the following Size arg,
// lpExtensionName, and the following MinSize
// Type's and Value appropriately since they're
// valid args in this case
//
funcArgs.ArgTypes[2] = lpSet_SizeToFollow;
funcArgs.Args[2] = (ULONG_PTR) lpExtensionID;
funcArgs.ArgTypes[3] = Size;
funcArgs.Args[3] = (ULONG_PTR) sizeof (LINEEXTENSIONID);
funcArgs.ArgTypes[5] = lpGet_Struct;
funcArgs.Args[5] = (ULONG_PTR) lpExtensionName;
}
if ( TAPIIsBadStringPtrW(lpszAppName, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGetAppPriorityW"));
return( LINEERR_INVALPOINTER );
}
return (DOFUNC (&funcArgs, "lineGetAppPriority"));
}
LONG
WINAPI
lineGetAppPriorityA(
LPCSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPVARSTRING lpExtensionName,
LPDWORD lpdwPriority
)
{
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lGetAppPriority),
{
(ULONG_PTR) 0, // (DWORD) lpszAppName,
(ULONG_PTR) dwMediaMode,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) 0,
(ULONG_PTR) lpdwPriority
},
{
lpszW, // app name
Dword, // media mode
Dword, // ext id (offset)
Dword, // ext id (size)
Dword, // request mode
Dword, // ext name total size
lpDword // lp pri
}
};
if (dwMediaMode & 0xff000000)
{
//
// We have to do some arg list munging here (adding an extra arg)
//
//
// Set lpExtensionID, the following Size arg,
// lpExtensionName, and the following MinSize
// Type's and Value appropriately since they're
// valid args in this case
//
funcArgs.ArgTypes[2] = lpSet_SizeToFollow;
funcArgs.Args[2] = (ULONG_PTR) lpExtensionID;
funcArgs.ArgTypes[3] = Size;
funcArgs.Args[3] = (ULONG_PTR) sizeof (LINEEXTENSIONID);
funcArgs.ArgTypes[5] = lpGet_Struct;
funcArgs.Args[5] = (ULONG_PTR) lpExtensionName;
}
if ( IsBadStringPtrA(lpszAppName, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGetAppPriorityA"));
return( LINEERR_INVALPOINTER );
}
funcArgs.Args[0] = (ULONG_PTR) NotSoWideStringToWideString(
lpszAppName,
(DWORD) -1
);
lResult = (DOFUNC (&funcArgs, "lineGetAppPriority"));
if (funcArgs.Args[0])
{
ClientFree ((LPVOID) funcArgs.Args[0]);
}
return lResult;
}
LONG
WINAPI
lineGetAppPriority(
LPCSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPVARSTRING lpExtensionName,
LPDWORD lpdwPriority
)
{
return lineGetAppPriorityA(
lpszAppName,
dwMediaMode,
lpExtensionID,
dwRequestMode,
lpExtensionName,
lpdwPriority
);
}
LONG
WINAPI
lineGetCallInfoW(
HCALL hCall,
LPLINECALLINFO lpCallInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetCallInfo),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpCallInfo
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetCallInfo"));
}
LONG
WINAPI
lineGetCallInfoA(
HCALL hCall,
LPLINECALLINFO lpCallInfo
)
{
LONG lResult;
lResult = lineGetCallInfoW(
hCall,
lpCallInfo
);
if ( 0 == lResult )
{
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCallerIDSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCallerIDNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCalledIDSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCalledIDNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwConnectedIDSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwConnectedIDNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwRedirectionIDSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwRedirectionIDNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwRedirectingIDSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwRedirectingIDNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwAppNameSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwDisplayableAddressSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCalledPartySize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwCommentSize)
);
/*
//
// Note: per TNixon (3/21/96), none of the following are guaranteed
// to be in ascii format, so we don't want to convert them
//
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwDisplaySize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwHighLevelCompSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwLowLevelCompSize)
);
WideStringToNotSoWideString(
(LPBYTE)lpCallInfo,
&(lpCallInfo->dwChargingInfoSize)
);
*/
}
return lResult;
}
LONG
WINAPI
lineGetCallInfo(
HCALL hCall,
LPLINECALLINFO lpCallInfo
)
{
return lineGetCallInfoA(
hCall,
lpCallInfo
);
}
LONG
WINAPI
lineGetCallStatus(
HCALL hCall,
LPLINECALLSTATUS lpCallStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetCallStatus),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpCallStatus
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetCallStatus"));
}
LONG
WINAPI
lineGetConfRelatedCalls(
HCALL hCall,
LPLINECALLLIST lpCallList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC| 2, lGetConfRelatedCalls),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpCallList
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetConfRelatedCalls"));
}
LONG
WINAPI
lineGetCountryW(
DWORD dwCountryID,
DWORD dwAPIVersion,
LPLINECOUNTRYLIST lpLineCountryList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lGetCountry),
{
(ULONG_PTR) dwCountryID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) 0,
(ULONG_PTR) lpLineCountryList
},
{
Dword,
Dword,
Dword,
lpGet_Struct
}
};
if (
( TAPI_CURRENT_VERSION != dwAPIVersion )
&&
( 0x00020001 != dwAPIVersion )
&&
( 0x00020000 != dwAPIVersion )
&&
( 0x00010004 != dwAPIVersion )
&&
( 0x00010003 != dwAPIVersion )
)
{
LOG((TL_ERROR, "lineGetCountryW - bad API version 0x%08lx", dwAPIVersion));
return LINEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "lineGetCountry"));
}
LONG
WINAPI
lineGetCountryA(
DWORD dwCountryID,
DWORD dwAPIVersion,
LPLINECOUNTRYLIST lpLineCountryList
)
{
LONG lResult;
DWORD n;
lResult = lineGetCountryW (dwCountryID, dwAPIVersion, lpLineCountryList);
if (lResult == 0)
{
//
// Go through the list of countries and change from Unicode to ANSI
//
LPLINECOUNTRYENTRY lpce;
lpce = (LPLINECOUNTRYENTRY) (((LPBYTE) lpLineCountryList) +
lpLineCountryList->dwCountryListOffset);
for (n = 0; n < lpLineCountryList->dwNumCountries; n++, lpce++)
{
WideStringToNotSoWideString(
(LPBYTE)lpLineCountryList,
&lpce->dwCountryNameSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineCountryList,
&lpce->dwSameAreaRuleSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineCountryList,
&lpce->dwLongDistanceRuleSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineCountryList,
&lpce->dwInternationalRuleSize
);
}
}
return lResult;
}
LONG
WINAPI
lineGetCountry(
DWORD dwCountryID,
DWORD dwAPIVersion,
LPLINECOUNTRYLIST lpLineCountryList
)
{
LPLINECOUNTRYLIST pTempList;
LONG lResult;
DWORD dwSize;
if ( IsBadWritePtr(lpLineCountryList, sizeof(LINECOUNTRYLIST)) )
{
LOG((TL_ERROR,
"lineGetCountry - bad pointer: lpLineCountryList [0x%p]",
lpLineCountryList
));
return LINEERR_INVALPOINTER;
}
if ( lpLineCountryList->dwTotalSize < sizeof(LINECOUNTRYLIST) )
{
LOG((TL_ERROR,
"lineGetCountry - dwTotalSize less than sizeof(LINECOUNTRYLIST)"
));
return LINEERR_INVALPOINTER;
}
dwSize = lpLineCountryList->dwTotalSize * 2;
while (TRUE)
{
pTempList = ClientAlloc( dwSize );
if (NULL == pTempList)
{
LOG((TL_ERROR,
"lineGetCountry - alloc failed for [x%lx] bytes",
dwSize
));
return( LINEERR_NOMEM );
}
pTempList->dwTotalSize = dwSize;
lResult = lineGetCountryA(
dwCountryID,
dwAPIVersion,
pTempList
);
// hack - if the structure isn't big enough
// realloc ourselves.
if (pTempList->dwNeededSize <= pTempList->dwTotalSize)
{
break;
}
dwSize = pTempList->dwNeededSize;
ClientFree( pTempList );
pTempList = NULL;
} // while
if ( 0 == lResult )
{
DWORD dwNewUsedSize = 0; // = sizeof(LINECOUNTRYLIST);
DWORD i;
DWORD dwCurrentOffset = sizeof(LINECOUNTRYLIST) +
(sizeof(LINECOUNTRYENTRY) * pTempList->dwNumCountries);
LPLINECOUNTRYENTRY pOldCountryEntry;
LPLINECOUNTRYENTRY pNewCountryEntry;
for (
i=0;
(i < pTempList->dwNumCountries);
i++
)
{
pOldCountryEntry = (LPLINECOUNTRYENTRY)
((PBYTE)(lpLineCountryList + 1) +
(i * sizeof(LINECOUNTRYENTRY)));
pNewCountryEntry = (LPLINECOUNTRYENTRY)
((PBYTE)(pTempList + 1) + (i * sizeof(LINECOUNTRYENTRY)));
// check to see if there is enough space in the buffer.
// add 1 because we're starting with an offset, and we
// need to convert it to a size.
dwNewUsedSize = dwCurrentOffset +
pNewCountryEntry->dwCountryNameSize +
pNewCountryEntry->dwSameAreaRuleSize +
pNewCountryEntry->dwLongDistanceRuleSize +
pNewCountryEntry->dwInternationalRuleSize +
1;
if (lpLineCountryList->dwTotalSize < dwNewUsedSize)
{
// i is checked at the end, so
// subtract one here, because we're
// not actually copying this entry
// i--;
break;
}
pOldCountryEntry->dwCountryID =
pNewCountryEntry->dwCountryID;
pOldCountryEntry->dwCountryCode =
pNewCountryEntry->dwCountryCode;
pOldCountryEntry->dwNextCountryID =
pNewCountryEntry->dwNextCountryID;
pOldCountryEntry->dwCountryNameSize =
pNewCountryEntry->dwCountryNameSize;
pOldCountryEntry->dwSameAreaRuleSize =
pNewCountryEntry->dwSameAreaRuleSize;
pOldCountryEntry->dwLongDistanceRuleSize =
pNewCountryEntry->dwLongDistanceRuleSize;
pOldCountryEntry->dwInternationalRuleSize =
pNewCountryEntry->dwInternationalRuleSize;
//
// Copy Country name
//
CopyMemory(
(PBYTE)lpLineCountryList + dwCurrentOffset,
(PBYTE)pTempList + pNewCountryEntry->dwCountryNameOffset,
pNewCountryEntry->dwCountryNameSize
);
pOldCountryEntry->dwCountryNameOffset = dwCurrentOffset;
dwCurrentOffset += pNewCountryEntry->dwCountryNameSize;
//
// Copy same area rule
//
CopyMemory(
(PBYTE)lpLineCountryList + dwCurrentOffset,
(PBYTE)pTempList + pNewCountryEntry->dwSameAreaRuleOffset,
pNewCountryEntry->dwSameAreaRuleSize
);
pOldCountryEntry->dwSameAreaRuleOffset = dwCurrentOffset;
dwCurrentOffset += pNewCountryEntry->dwSameAreaRuleSize;
//
// Copy long distance rule
//
CopyMemory(
(PBYTE)lpLineCountryList + dwCurrentOffset,
(PBYTE)pTempList + pNewCountryEntry->dwLongDistanceRuleOffset,
pNewCountryEntry->dwLongDistanceRuleSize
);
pOldCountryEntry->dwLongDistanceRuleOffset = dwCurrentOffset;
dwCurrentOffset += pNewCountryEntry->dwLongDistanceRuleSize;
//
// Copy international rule
//
CopyMemory(
(PBYTE)lpLineCountryList + dwCurrentOffset,
(PBYTE)pTempList + pNewCountryEntry->dwInternationalRuleOffset,
pNewCountryEntry->dwInternationalRuleSize
);
pOldCountryEntry->dwInternationalRuleOffset = dwCurrentOffset;
dwCurrentOffset += pNewCountryEntry->dwInternationalRuleSize;
// dwNewUsedSize += sizeof(LINECOUNTRYENTRY) +
// pOldCountryEntry->dwCountryNameSize +
// pOldCountryEntry->dwSameAreaRuleSize +
// pOldCountryEntry->dwLongDistanceRuleSize +
// pOldCountryEntry->dwInternationalRuleSize ;
}
//
// Did we stop short?
//
if ( i < pTempList->dwNumCountries )
{
lpLineCountryList->dwNeededSize = pTempList->dwNeededSize;
}
else
{
lpLineCountryList->dwNeededSize = dwNewUsedSize;
lpLineCountryList->dwUsedSize = dwNewUsedSize;
lpLineCountryList->dwNumCountries = pTempList->dwNumCountries;
lpLineCountryList->dwCountryListSize =
pTempList->dwNumCountries * sizeof(LINECOUNTRYENTRY);
lpLineCountryList->dwCountryListOffset = sizeof(LINECOUNTRYLIST);
}
}
ClientFree( pTempList );
return lResult;
}
LONG
WINAPI
lineGetDevCapsW(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) lpLineDevCaps
},
{
hXxxApp,
Dword,
Dword,
Dword,
lpGet_Struct
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
lResult = LINEERR_INCOMPATIBLEAPIVERSION;
goto ExitHere;
}
lResult = (DOFUNC (&funcArgs, "lineGetDevCaps"));
if ( 0 == lResult )
{
lpLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
}
ExitHere:
return lResult;
}
LONG
WINAPI
lineGetDevCapsA(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
LONG lResult;
lResult = lineGetDevCapsW(
hLineApp,
dwDeviceID,
dwAPIVersion,
dwExtVersion,
lpLineDevCaps
);
if (lResult == 0)
{
lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
WideStringToNotSoWideString(
(LPBYTE)lpLineDevCaps,
&lpLineDevCaps->dwProviderInfoSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineDevCaps,
&lpLineDevCaps->dwSwitchInfoSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineDevCaps,
&lpLineDevCaps->dwLineNameSize
);
WideStringToNotSoWideString(
(LPBYTE)lpLineDevCaps,
&lpLineDevCaps->dwTerminalTextSize
);
if (lpLineDevCaps->dwTerminalTextEntrySize)
{
lpLineDevCaps->dwTerminalTextEntrySize /= sizeof(WCHAR);
}
if (dwAPIVersion >= 0x00020000)
{
WideStringToNotSoWideString(
(LPBYTE) lpLineDevCaps,
&lpLineDevCaps->dwDeviceClassesSize
);
}
}
return lResult;
}
LONG
WINAPI
lineGetDevCaps(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps
)
{
return lineGetDevCapsA(
hLineApp,
dwDeviceID,
dwAPIVersion,
dwExtVersion,
lpLineDevCaps
);
}
LONG
WINAPI
lineGetDevConfigW(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCWSTR lpszDeviceClass
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
{
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lpDeviceConfig,
(ULONG_PTR) lpszDeviceClass
},
{
Dword,
lpGet_Struct,
lpszW
}
};
if ( lpszDeviceClass && TAPIIsBadStringPtrW(lpszDeviceClass, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGetDevConfigW"));
return( LINEERR_INVALPOINTER );
}
return (DOFUNC (&funcArgs, "lineGetDevConfig"));
}
LONG
WINAPI
lineGetDevConfigA(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCSTR lpszDeviceClass
)
{
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
{
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lpDeviceConfig,
0 // (DWORD) lpszDeviceClass
},
{
Dword,
lpGet_Struct,
lpszW
}
};
if ( lpszDeviceClass && IsBadStringPtrA(lpszDeviceClass, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDestAddress in lineGetDevConfigA"));
return( LINEERR_INVALPOINTER );
}
funcArgs.Args[2] = (ULONG_PTR) NotSoWideStringToWideString(
lpszDeviceClass,
(DWORD) -1
);
lResult = (DOFUNC (&funcArgs, "lineGetDevConfig"));
if ((LPVOID)funcArgs.Args[2])
{
ClientFree ((LPVOID)funcArgs.Args[2]);
}
return lResult;
}
LONG
WINAPI
lineGetDevConfig(
DWORD dwDeviceID,
LPVARSTRING lpDeviceConfig,
LPCSTR lpszDeviceClass
)
{
return lineGetDevConfigA(
dwDeviceID,
lpDeviceConfig,
lpszDeviceClass
);
}
LONG
WINAPI
lineGetGroupListA(
HLINE hLine,
LPLINEAGENTGROUPLIST lpGroupList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lGetGroupList),
{
(ULONG_PTR) GetFunctionIndex(lineGetAgentGroupListAPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lpGroupList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpGroupList // pass data
},
{
Dword,
Dword,
Dword,
lpGet_Struct
}
};
DWORD hPointer = 0;
LONG lResult;
hPointer = NewObject (ghHandleTable, (PVOID)lpGroupList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetGroupListA"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetGroupListW(
HLINE hLine,
LPLINEAGENTGROUPLIST lpGroupList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lGetGroupList),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lpGroupList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpGroupList // pass data
},
{
Dword,
Dword,
Dword,
lpGet_Struct
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpGroupList || IsBadWritePtr(lpGroupList, sizeof(LINEAGENTGROUPLIST)) )
{
return LINEERR_INVALPOINTER;
}
if (lpGroupList->dwTotalSize < sizeof(LINEAGENTGROUPLIST))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpGroupList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetAgentGroupListW"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetIconW(
DWORD dwDeviceID,
LPCWSTR lpszDeviceClass,
LPHICON lphIcon
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetIcon),
{
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lpszDeviceClass,
(ULONG_PTR) lphIcon
},
{
Dword,
lpszW,
lpDword
}
};
if (IsBadDwordPtr ((LPDWORD) lphIcon))
{
LOG((TL_ERROR, "lphIcon is an invalid pointer [0x%p]!", lphIcon));
return LINEERR_INVALPOINTER;
}
if (lpszDeviceClass == (LPCWSTR) NULL)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = TAPI_NO_DATA;
}
return DOFUNC (&funcArgs, "lineGetIcon");
}
LONG
WINAPI
lineGetIconA(
DWORD dwDeviceID,
LPCSTR lpszDeviceClass,
LPHICON lphIcon
)
{
LONG lResult;
PWSTR szTempPtr;
if (lpszDeviceClass && IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
{
LOG((TL_ERROR,
"Bad class name pointer passed into lineGetIconA [0x%p]",
lpszDeviceClass
));
return LINEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
lResult = lineGetIconW (dwDeviceID, szTempPtr, lphIcon);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
lineGetIcon(
DWORD dwDeviceID,
LPCSTR lpszDeviceClass,
LPHICON lphIcon
)
{
return (lineGetIconA (dwDeviceID, lpszDeviceClass, lphIcon));
}
LONG
WINAPI
lineGetIDW(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCWSTR lpszDeviceClass
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lGetID),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) hCall,
(ULONG_PTR) dwSelect,
(ULONG_PTR) lpDeviceID,
(ULONG_PTR) lpszDeviceClass
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct,
lpszW
}
};
LPVARSTRING lpDeviceIDTemp = NULL;
DWORD dwNumDevices;
DWORD dwBufSize;
DWORD dwResult;
DWORD dwDeviceId1, dwDeviceId2;
BOOL bDoItAgain = FALSE;
if (TAPIIsBadStringPtrW (lpszDeviceClass, (UINT)-1) ||
lstrlenW(lpszDeviceClass) == 0)
{
LOG((TL_ERROR, "Bad lpszDeviceClass in lineGetIDW"));
return( LINEERR_INVALPOINTER);
}
if ( IsBadWritePtr(lpDeviceID, sizeof(VARSTRING)) )
{
LOG((TL_ERROR, "Bad lpDeviceID in lineGetIDW"));
return( LINEERR_INVALPOINTER);
}
//
// if the request is for a wave device, call LGetIDEx
//
if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
!_wcsicmp(lpszDeviceClass, L"wave/out") ||
!_wcsicmp(lpszDeviceClass, L"midi/in") ||
!_wcsicmp(lpszDeviceClass, L"midi/out") ||
!_wcsicmp(lpszDeviceClass, L"wave/in/out")
)
{
dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
dwBufSize = lpDeviceID->dwTotalSize + dwNumDevices * WAVE_STRING_ID_BUFFER_SIZE;
do
{
//
// Allocate additional memory for the device string ID
//
lpDeviceIDTemp = (LPVARSTRING)ClientAlloc (dwBufSize);
if (!lpDeviceIDTemp)
{
LOG((TL_ERROR, "Failed to allocate memory"));
return( LINEERR_NOMEM );
}
lpDeviceIDTemp->dwTotalSize = dwBufSize;
funcArgs.Flags = MAKELONG (LINE_FUNC | SYNC | 6, lGetIDEx);
funcArgs.Args[4] = (ULONG_PTR)lpDeviceIDTemp;
//
// Call LGetIDEx
//
dwResult = DOFUNC (&funcArgs, "lineGetIDEx");
if (dwResult)
{
LOG((TL_ERROR, "lineGetIDEx failed with x%x", dwResult));
ClientFree (lpDeviceIDTemp);
return dwResult;
}
if (lpDeviceIDTemp->dwNeededSize > lpDeviceIDTemp->dwTotalSize && !bDoItAgain)
{
LOG((TL_INFO,
"lineGetIDEx returned needed size (%d) bigger than total size (%d) -> need to realloc",
lpDeviceIDTemp->dwNeededSize,
lpDeviceIDTemp->dwTotalSize ));
dwBufSize = lpDeviceIDTemp->dwNeededSize;
ClientFree ( lpDeviceIDTemp );
bDoItAgain = TRUE;
}
else
{
bDoItAgain = FALSE;
}
} while (bDoItAgain);
if (lpDeviceIDTemp->dwNeededSize > lpDeviceIDTemp->dwTotalSize)
{
LOG((TL_ERROR, "needed size (%d) still bigger than total size (%d)",
lpDeviceIDTemp->dwNeededSize,
lpDeviceIDTemp->dwTotalSize ));
ClientFree (lpDeviceIDTemp);
return LINEERR_OPERATIONFAILED;
}
//
// Get the device ID from string ID
//
if (dwNumDevices == 1)
{
if (!WaveStringIdToDeviceId (
(LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset),
lpszDeviceClass,
&dwDeviceId1)
)
{
LOG((TL_ERROR, "WaveStringIdToDeviceId failed"));
ClientFree (lpDeviceIDTemp);
return LINEERR_OPERATIONFAILED;
}
// check if the client buffer is big enough
if (lpDeviceID->dwTotalSize < sizeof(VARSTRING) + sizeof(DWORD))
{
lpDeviceID->dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
lpDeviceID->dwUsedSize = sizeof(VARSTRING);
}
else
{
lpDeviceID->dwNeededSize = lpDeviceID->dwUsedSize = sizeof(VARSTRING) + sizeof(DWORD);
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = sizeof(DWORD);
lpDeviceID->dwStringOffset = sizeof(VARSTRING);
*(DWORD *)(lpDeviceID + 1) = dwDeviceId1;
}
}
else
{
LPWSTR szString1 = (LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset);
if (!WaveStringIdToDeviceId (
szString1,
L"wave/in",
&dwDeviceId1) ||
!WaveStringIdToDeviceId (
(LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset + wcslen(szString1)),
L"wave/out",
&dwDeviceId2)
)
{
LOG((TL_ERROR, "WaveStringIdToDeviceId failed"));
ClientFree (lpDeviceIDTemp);
return LINEERR_OPERATIONFAILED;
}
// check if the client buffer is big enough
if (lpDeviceID->dwTotalSize < sizeof(VARSTRING) + 2 * sizeof(DWORD))
{
lpDeviceID->dwNeededSize = sizeof(VARSTRING) + 2 * sizeof(DWORD);
lpDeviceID->dwUsedSize = sizeof(VARSTRING);
}
else
{
lpDeviceID->dwNeededSize = lpDeviceID->dwUsedSize = sizeof(VARSTRING) + 2 * sizeof(DWORD);
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = 2 * sizeof(DWORD);
lpDeviceID->dwStringOffset = sizeof(VARSTRING);
*(DWORD *)(lpDeviceID + 1) = dwDeviceId1;
*((DWORD *)(lpDeviceID + 1) + 1) = dwDeviceId2;
}
}
ClientFree (lpDeviceIDTemp);
return NO_ERROR;
}
else
{
return (DOFUNC (&funcArgs, "lineGetID"));
}
}
LONG
WINAPI
lineGetIDA(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass
)
{
LONG lResult;
PWSTR szTempPtr;
if (IsBadStringPtrA (lpszDeviceClass, (UINT)-1) ||
lstrlenA(lpszDeviceClass) == 0)
{
LOG((TL_ERROR, "Bad lpszDeviceClass in lineGetIDA"));
return( LINEERR_INVALPOINTER);
}
szTempPtr = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
if (NULL == szTempPtr)
{
return LINEERR_NOMEM;
}
lResult = lineGetIDW(
hLine,
dwAddressID,
hCall,
dwSelect,
lpDeviceID,
szTempPtr
);
ClientFree (szTempPtr);
return lResult;
}
LONG
WINAPI
lineGetID(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass
)
{
return lineGetIDA(
hLine,
dwAddressID,
hCall,
dwSelect,
lpDeviceID,
lpszDeviceClass
);
}
LONG
WINAPI
lineGetLineDevStatusW(
HLINE hLine,
LPLINEDEVSTATUS lpLineDevStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetLineDevStatus),
{
(ULONG_PTR) hLine,
(ULONG_PTR) lpLineDevStatus
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetLineDevStatus"));
}
LONG
WINAPI
lineGetLineDevStatusA(
HLINE hLine,
LPLINEDEVSTATUS lpLineDevStatus
)
{
DWORD dwAPIVersion;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetLineDevStatus),
{
(ULONG_PTR) hLine,
(ULONG_PTR) lpLineDevStatus,
(ULONG_PTR) &dwAPIVersion
},
{
Dword,
lpGet_Struct,
lpDword
}
};
LONG lResult;
if ((lResult = DOFUNC (&funcArgs, "lineGetLineDevStatus")) == 0)
{
if (dwAPIVersion >= 0x00020000)
{
DWORD i;
LPLINEAPPINFO lplai;
lplai = (LPLINEAPPINFO) (((LPBYTE)lpLineDevStatus) +
lpLineDevStatus->dwAppInfoOffset);
for (i = 0; i < lpLineDevStatus->dwNumOpens; i++, lplai++)
{
WideStringToNotSoWideString(
(LPBYTE) lpLineDevStatus,
&lplai->dwMachineNameSize
);
WideStringToNotSoWideString(
(LPBYTE) lpLineDevStatus,
&lplai->dwUserNameSize
);
WideStringToNotSoWideString(
(LPBYTE) lpLineDevStatus,
&lplai->dwModuleFilenameSize
);
WideStringToNotSoWideString(
(LPBYTE) lpLineDevStatus,
&lplai->dwFriendlyNameSize
);
}
}
}
return lResult;
}
LONG
WINAPI
lineGetLineDevStatus(
HLINE hLine,
LPLINEDEVSTATUS lpLineDevStatus
)
{
return lineGetLineDevStatusA (hLine, lpLineDevStatus);
}
LONG
WINAPI
lineGetMessage(
HLINEAPP hLineApp,
LPLINEMESSAGE lpMessage,
DWORD dwTimeout
)
{
return (xxxGetMessage (TRUE, hLineApp, lpMessage, dwTimeout));
}
LONG
WINAPI
lineGetNewCalls(
HLINE hLine,
DWORD dwAddressID,
DWORD dwSelect,
LPLINECALLLIST lpCallList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lGetNewCalls),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwSelect,
(ULONG_PTR) lpCallList
},
{
Dword,
Dword,
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "lineGetNewCalls"));
}
LONG
WINAPI
lineGetNumRings(
HLINE hLine,
DWORD dwAddressID,
LPDWORD lpdwNumRings
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetNumRings),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpdwNumRings
},
{
Dword,
Dword,
lpDword
}
};
return (DOFUNC (&funcArgs, "lineGetNumRings"));
}
LONG
WINAPI
lineGetProviderListW(
DWORD dwAPIVersion,
LPLINEPROVIDERLIST lpProviderList
)
{
HANDLE hProvidersMutex;
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lGetProviderList),
{
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) lpProviderList
},
{
Dword,
lpGet_Struct
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
hProvidersMutex = CreateMutex (
NULL,
FALSE,
TEXT ("TapisrvProviderListMutex")
);
if (NULL == hProvidersMutex)
{
return LINEERR_OPERATIONFAILED;
}
WaitForSingleObject (hProvidersMutex, INFINITE);
lResult = DOFUNC (&funcArgs, "lineGetProviderList");
if (hProvidersMutex)
{
ReleaseMutex (hProvidersMutex);
CloseHandle (hProvidersMutex);
}
return lResult;
}
LONG
WINAPI
lineGetProviderListA(
DWORD dwAPIVersion,
LPLINEPROVIDERLIST lpProviderList
)
{
LONG lResult;
lResult = lineGetProviderListW (dwAPIVersion, lpProviderList);
if (lResult == 0)
{
DWORD i;
LPLINEPROVIDERENTRY lplpe;
lplpe = (LPLINEPROVIDERENTRY) (((LPBYTE)lpProviderList) +
lpProviderList->dwProviderListOffset);
for (i = 0; i < lpProviderList->dwNumProviders; i++, lplpe++)
{
WideStringToNotSoWideString(
(LPBYTE)lpProviderList,
&(lplpe->dwProviderFilenameSize)
);
}
}
return lResult;
}
LONG
WINAPI
lineGetProviderList(
DWORD dwAPIVersion,
LPLINEPROVIDERLIST lpProviderList
)
{
return lineGetProviderListA (dwAPIVersion, lpProviderList);
}
LONG
WINAPI
lineGetProxyStatus(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAppAPIVersion,
LPLINEPROXYREQUESTLIST lpLineProxyReqestList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lGetProxyStatus),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAppAPIVersion,
(ULONG_PTR) lpLineProxyReqestList
},
{
hXxxApp,
Dword,
Dword,
lpGet_Struct
}
};
if (dwAppAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "lineGetProxyStatus"));
}
LONG
WINAPI
lineGetQueueInfo(
HLINE hLine,
DWORD dwQueueID,
LPLINEQUEUEINFO lpLineQueueInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lGetQueueInfo),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwQueueID,
(ULONG_PTR) lpLineQueueInfo, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpLineQueueInfo // pass data
},
{
Dword,
Dword,
Dword,
Dword,
lpGet_Struct
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpLineQueueInfo || IsBadWritePtr(lpLineQueueInfo, sizeof(LINEQUEUEINFO)) )
{
return LINEERR_INVALPOINTER;
}
if (lpLineQueueInfo->dwTotalSize < sizeof(LINEQUEUEINFO))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpLineQueueInfo, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetQueueInfo"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
void
PASCAL
lineGetQueueListAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineGetQueueListAPostProcess: enter"));
LOG((TL_INFO,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPLINEQUEUELIST lpQueueList = (LPLINEQUEUELIST) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
DWORD dw, dwNumEntries;
LPLINEQUEUEENTRY lpqe;
//
// Note: the agent APIs are not exposed to 16-bit apps, so
// there's no reason to special case on gbNTVDMClient like
// lineDevSpecificPostProcess does
//
CopyMemory (lpQueueList, (LPBYTE) (pMsg + 1), dwSize);
//
// Now some unicode->ascii post processing on embedded strings
//
lpqe = (LPLINEQUEUEENTRY)(((LPBYTE)lpQueueList) +
lpQueueList->dwListOffset);
dwNumEntries = lpQueueList->dwNumEntries;
for (dw = 0; dw < dwNumEntries; dw++, lpqe++)
{
WideStringToNotSoWideString(
(LPBYTE) lpQueueList,
&(lpqe->dwNameSize)
);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineGetQueueListA(
HLINE hLine,
LPGUID lpGroupID,
LPLINEQUEUELIST lpQueueList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lGetQueueList),
{
(ULONG_PTR) GetFunctionIndex(lineGetQueueListAPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lpGroupID,
(ULONG_PTR) sizeof( GUID ),
(ULONG_PTR) lpQueueList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpQueueList // pass data
},
{
Dword,
Dword,
lpSet_SizeToFollow,
Size,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
hPointer = NewObject (ghHandleTable, (PVOID)lpQueueList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetQueueListA"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetQueueListW(
HLINE hLine,
LPGUID lpGroupID,
LPLINEQUEUELIST lpQueueList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lGetQueueList),
{
(ULONG_PTR) GetFunctionIndex(lineDevSpecificPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lpGroupID,
(ULONG_PTR) sizeof( GUID ),
(ULONG_PTR) lpQueueList, // pass the actual ptr (for ppproc)
(ULONG_PTR) lpQueueList // pass data
},
{
Dword,
Dword,
lpSet_SizeToFollow,
Size,
Dword,
lpGet_Struct,
}
};
DWORD hPointer = 0;
LONG lResult;
if ( !lpQueueList || IsBadWritePtr(lpQueueList, sizeof(LINEQUEUELIST)) )
{
return LINEERR_INVALPOINTER;
}
if (lpQueueList->dwTotalSize < sizeof(LINEQUEUELIST))
{
return LINEERR_STRUCTURETOOSMALL;
}
hPointer = NewObject (ghHandleTable, (PVOID)lpQueueList, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
lResult = (DOFUNC (&funcArgs, "lineGetQueueList"));
if (0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineGetRequestW(
HLINEAPP hLineApp,
DWORD dwRequestMode,
LPVOID lpRequestBuffer
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) lpRequestBuffer,
(ULONG_PTR) 0
},
{
hXxxApp,
Dword,
lpGet_SizeToFollow,
Size
}
};
if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
{
//
// Set the size param appropriately
//
funcArgs.Args[3] = (ULONG_PTR) sizeof(LINEREQMAKECALLW);
}
else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
{
//
// Set the size param appropriately
//
funcArgs.Args[3] = (ULONG_PTR) sizeof(LINEREQMEDIACALLW);
}
return (DOFUNC (&funcArgs, "lineGetRequest"));
}
LONG
WINAPI
lineGetRequestA(
HLINEAPP hLineApp,
DWORD dwRequestMode,
LPVOID lpRequestBuffer
)
{
LONG lResult;
LPVOID pszTempPtr = NULL;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) 0, // (DWORD) lpRequestBuffer,
(ULONG_PTR) 0
},
{
hXxxApp,
Dword,
lpGet_SizeToFollow,
Size
}
};
if (IsBadWritePtr(
lpRequestBuffer,
(dwRequestMode == LINEREQUESTMODE_MAKECALL ?
sizeof (LINEREQMAKECALL) : sizeof (LINEREQMEDIACALL))
))
{
return LINEERR_INVALPOINTER;
}
if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
{
//
// Set the size param appropriately
//
funcArgs.Args[3] = (ULONG_PTR) sizeof(LINEREQMAKECALLW);
pszTempPtr = ClientAlloc( sizeof(LINEREQMAKECALLW) );
if (NULL == pszTempPtr)
{
return LINEERR_NOMEM;
}
}
else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
{
//
// Set the size param appropriately
//
funcArgs.Args[3] = (ULONG_PTR) sizeof(LINEREQMEDIACALLW);
pszTempPtr = ClientAlloc( sizeof(LINEREQMEDIACALLW) );
if (NULL == pszTempPtr)
{
return LINEERR_NOMEM;
}
}
funcArgs.Args[2] = (ULONG_PTR) pszTempPtr;
lResult = (DOFUNC (&funcArgs, "lineGetRequest"));
if ( 0 == lResult )
{
if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
{
LPLINEREQMAKECALLW lplrmc = pszTempPtr;
WideCharToMultiByte(
GetACP(),
0,
lplrmc->szDestAddress,
-1,
((LPLINEREQMAKECALL)lpRequestBuffer)->szDestAddress,
TAPIMAXDESTADDRESSSIZE,
NULL,
NULL
);
WideCharToMultiByte(
GetACP(),
0,
lplrmc->szAppName,
-1,
((LPLINEREQMAKECALL)lpRequestBuffer)->szAppName,
TAPIMAXAPPNAMESIZE,
NULL,
NULL
);
WideCharToMultiByte(
GetACP(),
0,
lplrmc->szCalledParty,
-1,
((LPLINEREQMAKECALL)lpRequestBuffer)->szCalledParty,
TAPIMAXCALLEDPARTYSIZE,
NULL,
NULL
);
WideCharToMultiByte(
GetACP(),
0,
lplrmc->szComment,
-1,
((LPLINEREQMAKECALL)lpRequestBuffer)->szComment,
TAPIMAXCOMMENTSIZE,
NULL,
NULL
);
}
else
{
// We don't currently support this...
//typedef struct linereqmediacallW_tag
//{
// HWND hWnd;
// WPARAM wRequestID;
// WCHAR szDeviceClass[TAPIMAXDEVICECLASSSIZE];
// unsigned char ucDeviceID[TAPIMAXDEVICEIDSIZE];
// DWORD dwSize;
// DWORD dwSecure;
// WCHAR szDestAddress[TAPIMAXDESTADDRESSSIZE];
// WCHAR szAppName[TAPIMAXAPPNAMESIZE];
// WCHAR szCalledParty[TAPIMAXCALLEDPARTYSIZE];
// WCHAR szComment[TAPIMAXCOMMENTSIZE];
//}
}
}
if ( pszTempPtr )
{
ClientFree( pszTempPtr );
}
return lResult;
}
LONG
WINAPI
lineGetRequest(
HLINEAPP hLineApp,
DWORD dwRequestMode,
LPVOID lpRequestBuffer
)
{
return lineGetRequestA (hLineApp, dwRequestMode, lpRequestBuffer);
}
LONG
WINAPI
lineGetStatusMessages(
HLINE hLine,
LPDWORD lpdwLineStates,
LPDWORD lpdwAddressStates
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lGetStatusMessages),
{
(ULONG_PTR) hLine,
(ULONG_PTR) lpdwLineStates,
(ULONG_PTR) lpdwAddressStates
},
{
Dword,
lpDword,
lpDword
}
};
if (lpdwLineStates == lpdwAddressStates)
{
return LINEERR_INVALPOINTER;
}
return (DOFUNC (&funcArgs, "lineGetStatusMessages"));
}
LONG
WINAPI
lineHandoffW(
HCALL hCall,
LPCWSTR lpszFileName,
DWORD dwMediaMode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lHandoff),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpszFileName,
(ULONG_PTR) dwMediaMode
},
{
Dword,
lpszW,
Dword
}
};
if (lpszFileName == (LPCWSTR) NULL)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
}
return (DOFUNC (&funcArgs, "lineHandoff"));
}
LONG
WINAPI
lineHandoffA(
HCALL hCall,
LPCSTR lpszFileName,
DWORD dwMediaMode
)
{
LONG lResult;
LPWSTR pTempPtr;
if (lpszFileName)
{
if (IsBadStringPtrA (lpszFileName, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
else if (!(pTempPtr = NotSoWideStringToWideString(
lpszFileName,
(DWORD) -1
)))
{
return LINEERR_NOMEM;
}
}
else
{
pTempPtr = NULL;
}
lResult = lineHandoffW (hCall, pTempPtr, dwMediaMode);
if (pTempPtr)
{
ClientFree (pTempPtr);
}
return lResult;
}
LONG
WINAPI
lineHandoff(
HCALL hCall,
LPCSTR lpszFileName,
DWORD dwMediaMode
)
{
return lineHandoffA (hCall, lpszFileName, dwMediaMode);
}
LONG
WINAPI
lineHold(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 1, lHold),
{
(ULONG_PTR) hCall
},
{
Dword
}
};
return (DOFUNC (&funcArgs, "lineHold"));
}
PWSTR
PASCAL
MultiToWide(
LPCSTR lpStr
)
{
DWORD dwSize;
PWSTR szTempPtr;
dwSize = MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpStr,
-1,
NULL,
0
);
if ((szTempPtr = ClientAlloc ((dwSize + 1) * sizeof (WCHAR))))
{
MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
lpStr,
-1,
szTempPtr,
dwSize + 1
);
}
return szTempPtr;
}
// Don't need this 'cause 2.0 apps must use lineInitializeEx()
//
//LONG
//WINAPI
//lineInitializeW(
// LPHLINEAPP lphLineApp,
// HINSTANCE hInstance,
// LINECALLBACK lpfnCallback,
// LPCWSTR lpszAppName,
// LPDWORD lpdwNumDevs
// )
//{
// return (xxxInitialize(
// TRUE,
// (LPVOID) lphLineApp,
// hInstance,
// lpfnCallback,
// lpszAppName,
// lpdwNumDevs,
// NULL,
// NULL
//#if DBG
// ,"lineInitializeW"
//#endif
// ));
//}
LONG
WINAPI
lineInitialize(
LPHLINEAPP lphLineApp,
HINSTANCE hInstance,
LINECALLBACK lpfnCallback,
LPCSTR lpszAppName,
LPDWORD lpdwNumDevs
)
{
LONG lResult;
PWSTR szTempPtr;
if (lpszAppName )
{
if ( IsBadStringPtrA (lpszAppName, (DWORD) -1))
{
LOG((TL_ERROR, "lineInitialize: Bad lpszAddName pointer"));
return LINEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
}
else
{
szTempPtr = NULL;
}
//
// NOTE: the hack below for the lpInitExParam is for 16-bit apps,
// since the lpszAppName really points at a
// <friendly name>\0<module name>\0 string and we need the
// module name in xxxInitialize()
//
lResult = (xxxInitialize(
TRUE,
(LPVOID) lphLineApp,
hInstance,
lpfnCallback,
szTempPtr,
lpdwNumDevs,
NULL,
#ifdef _WIN64
NULL
#else
(LPLINEINITIALIZEEXPARAMS)
(((DWORD) lpfnCallback & 0xffff0000) == 0xffff0000 ?
lpszAppName : NULL)
#endif
#if DBG
,"lineInitialize"
#endif
));
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
lineInitializeExW(
LPHLINEAPP lphLineApp,
HINSTANCE hInstance,
LINECALLBACK lpfnCallback,
LPCWSTR lpszFriendlyAppName,
LPDWORD lpdwNumDevs,
LPDWORD lpdwAPIVersion,
LPLINEINITIALIZEEXPARAMS lpLineInitializeExParams
)
{
if (IsBadDwordPtr (lpdwAPIVersion))
{
LOG((TL_ERROR,
"lineInitializeExW: bad lpdwAPIVersion pointer (x%p)",
lpdwAPIVersion
));
return LINEERR_INVALPOINTER;
}
return (xxxInitialize(
TRUE,
(LPVOID) lphLineApp,
hInstance,
lpfnCallback,
lpszFriendlyAppName,
lpdwNumDevs,
lpdwAPIVersion,
(LPVOID) lpLineInitializeExParams
#if DBG
,"lineInitializeExW"
#endif
));
}
LONG
WINAPI
lineInitializeExA(
LPHLINEAPP lphLineApp,
HINSTANCE hInstance,
LINECALLBACK lpfnCallback,
LPCSTR lpszFriendlyAppName,
LPDWORD lpdwNumDevs,
LPDWORD lpdwAPIVersion,
LPLINEINITIALIZEEXPARAMS lpLineInitializeExParams
)
{
LONG lResult;
WCHAR *pszFriendlyAppNameW;
if (lpszFriendlyAppName)
{
if (IsBadStringPtrA (lpszFriendlyAppName, (DWORD) -1))
{
LOG((TL_ERROR,
"lineInitializeEx: bad lpszFriendlyAppName (x%p)",
lpszFriendlyAppName
));
return LINEERR_INVALPOINTER;
}
if (!(pszFriendlyAppNameW = MultiToWide (lpszFriendlyAppName)))
{
return LINEERR_INVALPOINTER;
}
}
else
{
pszFriendlyAppNameW = NULL;
}
lResult = lineInitializeExW(
lphLineApp,
hInstance,
lpfnCallback,
pszFriendlyAppNameW,
lpdwNumDevs,
lpdwAPIVersion,
lpLineInitializeExParams
);
if (pszFriendlyAppNameW)
{
ClientFree (pszFriendlyAppNameW);
}
return lResult;
}
void
PASCAL
lineMakeCallPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineMakeCallPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
HCALL hCall = (HCALL) pMsg->Param3;
LPHCALL lphCall = (LPDWORD) ReferenceObject (ghHandleTable, pMsg->Param4, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param4, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPHCALL lphCallVDM = (LPHCALL) gpfnWOWGetVDMPointer (
(DWORD) lphCall,
sizeof(HCALL),
TRUE // fProtectedMode
);
if (lphCallVDM)
{
*lphCallVDM = hCall;
}
else
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
#endif
}
else
{
*lphCall = hCall;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineMakeCallW(
HLINE hLine,
LPHCALL lphCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lMakeCall),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lphCall,
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) dwCountryCode,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpszW,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
if (!lpszDestAddress)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[5] = Dword;
funcArgs.Args[5] = (ULONG_PTR) TAPI_NO_DATA;
}
lResult = (DOFUNC (&funcArgs, "lineMakeCall"));
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineMakeCallA(
HLINE hLine,
LPHCALL lphCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams
)
{
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lMakeCall),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) lphCall,
(ULONG_PTR) 0,
(ULONG_PTR) dwCountryCode,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP() // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpszW,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LOG((TL_TRACE, "Entering lineMakeCallA"));
LOG((TL_INFO, " hLine= 0x%08lx", hLine));
if (!lpszDestAddress)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
else if (IsBadStringPtrA (lpszDestAddress, (DWORD) -1))
{
LOG((TL_ERROR, "lineMakeCall: Bad lpszDestAddress pointer"));
return LINEERR_INVALPOINTER;
}
else if (!(funcArgs.Args[3] = (ULONG_PTR) NotSoWideStringToWideString(
lpszDestAddress,
(DWORD) -1
)))
{
return LINEERR_OPERATIONFAILED; // really either NOMEM. INVALPOINTER
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphCall, NULL);
if (0 == hPointer)
{
lResult = LINEERR_NOMEM;
goto _return;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[5] = Dword;
funcArgs.Args[5] = (ULONG_PTR) TAPI_NO_DATA;
}
lResult = DOFUNC (&funcArgs, "lineMakeCall");
if (hPointer && 0 > lResult)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
_return:
if (funcArgs.Args[3] != (ULONG_PTR) TAPI_NO_DATA)
{
ClientFree ((LPVOID) funcArgs.Args[3]);
}
return lResult;
}
LONG
WINAPI
lineMakeCall(
HLINE hLine,
LPHCALL lphCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams
)
{
return lineMakeCallA(
hLine,
lphCall,
lpszDestAddress,
dwCountryCode,
lpCallParams
);
}
LONG
WINAPI
lineMonitorDigits(
HCALL hCall,
DWORD dwDigitModes
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lMonitorDigits),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwDigitModes
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineMonitorDigits"));
}
LONG
WINAPI
lineMonitorMedia(
HCALL hCall,
DWORD dwMediaModes
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwMediaModes
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineMonitorMedia"));
}
LONG
WINAPI
lineMonitorTones(
HCALL hCall,
LPLINEMONITORTONE const lpToneList,
DWORD dwNumEntries
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lMonitorTones),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpToneList,
(ULONG_PTR) dwNumEntries * sizeof(LINEMONITORTONE),
(ULONG_PTR) 0 // dwToneListID, remotesp only
},
{
Dword,
lpSet_SizeToFollow,
Size,
Dword
}
};
if (!lpToneList)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineMonitorTones"));
}
LONG
WINAPI
lineNegotiateAPIVersion(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPILowVersion,
DWORD dwAPIHighVersion,
LPDWORD lpdwAPIVersion,
LPLINEEXTENSIONID lpExtensionID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lNegotiateAPIVersion),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPILowVersion,
(ULONG_PTR) dwAPIHighVersion,
(ULONG_PTR) lpdwAPIVersion,
(ULONG_PTR) lpExtensionID,
(ULONG_PTR) sizeof(LINEEXTENSIONID)
},
{
hXxxApp,
Dword,
Dword,
Dword,
lpDword,
lpGet_SizeToFollow,
Size
}
};
if (dwAPIHighVersion > TAPI_CURRENT_VERSION)
{
funcArgs.Args[3] = TAPI_CURRENT_VERSION;
}
if ((LPVOID) lpdwAPIVersion == (LPVOID) lpExtensionID)
{
return LINEERR_INVALPOINTER;
}
return (DOFUNC (&funcArgs, "lineNegotiateAPIVersion"));
}
LONG
WINAPI
lineNegotiateExtVersion(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtLowVersion,
DWORD dwExtHighVersion,
LPDWORD lpdwExtVersion
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lNegotiateExtVersion),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtLowVersion,
(ULONG_PTR) dwExtHighVersion,
(ULONG_PTR) lpdwExtVersion
},
{
hXxxApp,
Dword,
Dword,
Dword,
Dword,
lpDword
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "lineNegotiateExtVersion"));
}
LONG
WINAPI
lineOpenW(
HLINEAPP hLineApp,
DWORD dwDeviceID,
LPHLINE lphLine,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivileges,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
)
{
LONG lResult;
DWORD hCallbackInstance = 0;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 12, lOpen),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lphLine,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) dwCallbackInstance,
(ULONG_PTR) dwPrivileges,
(ULONG_PTR) dwMediaModes,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA, // dwAsciiCallParamsCodePage
(ULONG_PTR) 0,
(ULONG_PTR) 0 // LINEOPEN_PARAMS.hRemoteLine
},
{
hXxxApp,
Dword,
lpDword,
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword,
Dword,
Dword
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
if (dwDeviceID != LINEMAPPER &&
!(dwPrivileges &
(LINEOPENOPTION_PROXY|LINEOPENOPTION_SINGLEADDRESS)))
{
//
// Reset Arg & ArgType so no inval ptr err,
// & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[8] = Dword;
funcArgs.Args[8] = (ULONG_PTR) TAPI_NO_DATA;
}
if (0 != dwCallbackInstance)
{
hCallbackInstance = NewObject (ghHandleTable, (PVOID)dwCallbackInstance, (PVOID)UIntToPtr(hLineApp));
if (0 == hCallbackInstance)
{
return LINEERR_NOMEM;
}
funcArgs.Args[5] = hCallbackInstance;
}
lResult = (DOFUNC (&funcArgs, "lineOpen"));
//
// If we we managed a successful LINEMAPPER & there's an LCR hook
// for this function then call it to allow it to override our
// results if it wants to. (One good thing about calling it after
// the fact is that we leverage our param checking.)
//
if (dwDeviceID == LINEMAPPER &&
lResult == 0 &&
IsLeastCostRoutingEnabled() &&
pfnLineOpenWLCR)
{
lResult = (*pfnLineOpenWLCR)(
hLineApp,
dwDeviceID,
lphLine,
dwAPIVersion,
dwExtVersion,
dwCallbackInstance,
dwPrivileges,
dwMediaModes,
lpCallParams
);
}
#if DBG
if ( !IsBadWritePtr( (LPBYTE)lphLine, 4 ) )
{
LOG((TL_TRACE,
"Returning from lineOpenW, *lphLine = 0x%08lx",
*lphLine
));
}
LOG((TL_TRACE, "Returning from lineOpenW, retcode = 0x%08lx", lResult));
#endif
if (lResult && 0 != hCallbackInstance)
{
DereferenceObject (ghHandleTable, hCallbackInstance, 1);
}
return( lResult );
}
LONG
WINAPI
lineOpenA(
HLINEAPP hLineApp,
DWORD dwDeviceID,
LPHLINE lphLine,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivileges,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
)
{
LONG lResult;
DWORD hCallbackInstance = 0;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 12, lOpen),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lphLine,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) dwCallbackInstance,
(ULONG_PTR) dwPrivileges,
(ULONG_PTR) dwMediaModes,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP(), // dwAsciiCallParamsCodePage
(ULONG_PTR) 0,
(ULONG_PTR) 0 // LINEOPEN_PARAMS.hRemoteLine
},
{
hXxxApp,
Dword,
lpDword,
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword,
Dword,
Dword
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return LINEERR_INCOMPATIBLEAPIVERSION;
}
if (dwDeviceID != LINEMAPPER &&
!(dwPrivileges & (LINEOPENOPTION_PROXY|LINEOPENOPTION_SINGLEADDRESS)))
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[8] = Dword;
funcArgs.Args[8] = (ULONG_PTR) TAPI_NO_DATA;
}
if (0 != dwCallbackInstance)
{
hCallbackInstance = NewObject (ghHandleTable, (PVOID)dwCallbackInstance, (PVOID)UIntToPtr(hLineApp));
if (0 == hCallbackInstance)
{
return LINEERR_NOMEM;
}
funcArgs.Args[5] = hCallbackInstance;
}
lResult = (DOFUNC (&funcArgs, "lineOpen"));
//
// If we we managed a successful LINEMAPPER & there's an LCR hook
// for this function then call it to allow it to override our
// results if it wants to. (One good thing about calling it after
// the fact is that we leverage our param checking.)
//
if (dwDeviceID == LINEMAPPER &&
lResult == 0 &&
IsLeastCostRoutingEnabled() &&
pfnLineOpenALCR)
{
lResult = (*pfnLineOpenALCR)(
hLineApp,
dwDeviceID,
lphLine,
dwAPIVersion,
dwExtVersion,
dwCallbackInstance,
dwPrivileges,
dwMediaModes,
lpCallParams
);
}
#if DBG
if ( !IsBadWritePtr( (LPBYTE)lphLine, 4 ) )
{
LOG((TL_TRACE,
"Returning from lineOpenA, *lphLine = 0x%08lx",
*lphLine
));
}
LOG((TL_TRACE, "Returning from lineOpenA, retcode = 0x%08lx", lResult));
#endif
if (lResult && 0 != hCallbackInstance)
{
DereferenceObject (ghHandleTable, hCallbackInstance, 1);
}
return( lResult );
}
LONG
WINAPI
lineOpen(
HLINEAPP hLineApp,
DWORD dwDeviceID,
LPHLINE lphLine,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivileges,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams
)
{
return lineOpenA(
hLineApp,
dwDeviceID,
lphLine,
dwAPIVersion,
dwExtVersion,
dwCallbackInstance,
dwPrivileges,
dwMediaModes,
lpCallParams
);
}
void
PASCAL
lineParkAPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineParkAPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
LPVARSTRING pNonDirAddress = (LPVARSTRING) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPVARSTRING pNonDirAddressVDM = (LPVARSTRING)
gpfnWOWGetVDMPointer(
(DWORD) pNonDirAddress,
dwSize,
TRUE // fProtectedMode
);
if (pNonDirAddressVDM)
{
CopyMemory(
pNonDirAddressVDM,
(LPBYTE) (pMsg + 1),
dwSize
);
if (pNonDirAddressVDM->dwUsedSize >= sizeof (VARSTRING) &&
pNonDirAddressVDM->dwStringSize != 0)
{
TCHAR *p;
DWORD dwStringSize =
pNonDirAddressVDM->dwStringSize /
sizeof (WCHAR);
if ((p = ClientAlloc(pNonDirAddressVDM->dwStringSize)))
{
pNonDirAddressVDM->dwStringFormat =
STRINGFORMAT_ASCII;
pNonDirAddressVDM->dwStringSize =
dwStringSize;
WideCharToMultiByte(
GetACP(),
0,
(LPCWSTR) (((LPBYTE) pNonDirAddressVDM) +
pNonDirAddressVDM->dwStringOffset),
dwStringSize,
(LPSTR) p,
dwStringSize,
NULL,
NULL
);
CopyMemory(
(((LPBYTE) pNonDirAddressVDM) +
pNonDirAddressVDM->dwStringOffset),
p,
dwStringSize
);
ClientFree (p);
}
}
}
else
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
#endif
}
else
{
CopyMemory (pNonDirAddress, (LPBYTE) (pMsg + 1), dwSize);
if (pNonDirAddress->dwUsedSize >= sizeof (VARSTRING) &&
pNonDirAddress->dwStringSize != 0)
{
TCHAR *p;
DWORD dwStringSize = pNonDirAddress->dwStringSize /
sizeof (WCHAR);
if ((p = ClientAlloc (pNonDirAddress->dwStringSize)))
{
pNonDirAddress->dwStringFormat = STRINGFORMAT_ASCII;
pNonDirAddress->dwStringSize = dwStringSize;
WideCharToMultiByte(
GetACP(),
0,
(LPCWSTR) (((LPBYTE) pNonDirAddress) +
pNonDirAddress->dwStringOffset),
dwStringSize,
(LPSTR) p,
dwStringSize,
NULL,
NULL
);
CopyMemory(
(((LPBYTE) pNonDirAddress) +
pNonDirAddress->dwStringOffset),
p,
dwStringSize
);
ClientFree (p);
}
}
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineParkW(
HCALL hCall,
DWORD dwParkMode,
LPCWSTR lpszDirAddress,
LPVARSTRING lpNonDirAddress
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
{
(ULONG_PTR) 0, // post process proc
(ULONG_PTR) hCall,
(ULONG_PTR) dwParkMode,
(ULONG_PTR) TAPI_NO_DATA, // lpszDirAddress,
(ULONG_PTR) lpNonDirAddress, // pass ptr as Dword for post proc
(ULONG_PTR) TAPI_NO_DATA, // lpNonDirAddress, pass ptr as
// lpGet_Xx for IsValPtr chk
},
{
Dword,
Dword,
Dword,
Dword, // lpszW,
Dword,
Dword, // lpGet_Struct
}
};
DWORD hPointer = 0;
LONG lResult;
if (dwParkMode == LINEPARKMODE_DIRECTED)
{
funcArgs.ArgTypes[3] = lpszW;
funcArgs.Args[3] = (ULONG_PTR) lpszDirAddress;
}
else if (dwParkMode == LINEPARKMODE_NONDIRECTED)
{
if ( !lpNonDirAddress || IsBadWritePtr(lpNonDirAddress, sizeof(VARSTRING)) )
{
return LINEERR_INVALPOINTER;
}
if (lpNonDirAddress->dwTotalSize < sizeof(VARSTRING))
{
return LINEERR_STRUCTURETOOSMALL;
}
//
// Set post process proc
//
hPointer = NewObject (ghHandleTable, (PVOID)lpNonDirAddress, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
funcArgs.Args[0] = (ULONG_PTR)
GetFunctionIndex(lineDevSpecificPostProcess);
funcArgs.ArgTypes[5] = lpGet_Struct;
funcArgs.Args[5] = (ULONG_PTR) lpNonDirAddress;
}
lResult = (DOFUNC (&funcArgs, "linePark"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineParkA(
HCALL hCall,
DWORD dwParkMode,
LPCSTR lpszDirAddress,
LPVARSTRING lpNonDirAddress
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
{
(ULONG_PTR) 0, // post process proc
(ULONG_PTR) hCall,
(ULONG_PTR) dwParkMode,
(ULONG_PTR) TAPI_NO_DATA, // lpszDirAddress,
(ULONG_PTR) lpNonDirAddress, // pass ptr as Dword for post proc
(ULONG_PTR) TAPI_NO_DATA, // lpNonDirAddress, pass ptr as
// lpGet_Xx for IsValPtr chk
},
{
Dword,
Dword,
Dword,
Dword, // lpszW,
Dword,
Dword, // lpGet_Struct
}
};
LONG lResult;
PWSTR szTempPtr = NULL;
DWORD hPointer = 0;
switch (dwParkMode)
{
case LINEPARKMODE_DIRECTED:
{
if (IsBadStringPtrA (lpszDirAddress, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszDirAddress, (DWORD) -1);
funcArgs.ArgTypes[3] = lpszW;
funcArgs.Args[3] = (ULONG_PTR) szTempPtr;
break;
}
case LINEPARKMODE_NONDIRECTED:
{
if ( !lpNonDirAddress )
{
return LINEERR_INVALPOINTER;
}
//
// Set post process proc
//
hPointer = NewObject (ghHandleTable, (PVOID)lpNonDirAddress, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[4] = (ULONG_PTR)hPointer;
funcArgs.Args[0] = (ULONG_PTR)
GetFunctionIndex(lineParkAPostProcess);
funcArgs.ArgTypes[5] = lpGet_Struct;
if (gbNTVDMClient == FALSE)
{
funcArgs.Args[5] = (ULONG_PTR) lpNonDirAddress;
}
else
{
#ifndef _WIN64
if (!gpfnWOWGetVDMPointer ||
!(funcArgs.Args[5] = (ULONG_PTR) gpfnWOWGetVDMPointer(
(DWORD) lpNonDirAddress,
sizeof (VARSTRING), // what if it's > sizeof(VARS)?
TRUE // fProtectedMode
)))
#endif
{
return LINEERR_OPERATIONFAILED;
}
}
break;
}
default:
return LINEERR_INVALPARKMODE;
}
lResult = (DOFUNC (&funcArgs, "linePark"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
linePark(
HCALL hCall,
DWORD dwParkMode,
LPCSTR lpszDirAddress,
LPVARSTRING lpNonDirAddress
)
{
return lineParkA (hCall, dwParkMode, lpszDirAddress, lpNonDirAddress);
}
LONG
WINAPI
linePickupW(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCWSTR lpszDestAddress,
LPCWSTR lpszGroupID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lPickup),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lphCall,
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) lpszGroupID
},
{
Dword,
Dword,
Dword,
Dword,
lpszW,
lpszW
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpszDestAddress)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[4] = Dword;
funcArgs.Args[4] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpszGroupID)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[5] = Dword;
funcArgs.Args[5] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "linePickup"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
linePickupA(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCSTR lpszDestAddress,
LPCSTR lpszGroupID
)
{
LONG lResult;
PWSTR szTempPtr;
PWSTR szTempPtr2;
if ((lpszDestAddress && IsBadStringPtrA (lpszDestAddress, (DWORD) -1)) ||
(lpszGroupID && IsBadStringPtrA (lpszGroupID, (DWORD) -1)))
{
return LINEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
szTempPtr2 = NotSoWideStringToWideString (lpszGroupID, (DWORD) -1);
lResult = linePickupW (hLine, dwAddressID, lphCall, szTempPtr, szTempPtr2);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
if (szTempPtr2)
{
ClientFree (szTempPtr2);
}
return lResult;
}
LONG
WINAPI
linePickup(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCSTR lpszDestAddress,
LPCSTR lpszGroupID
)
{
return linePickupA(
hLine,
dwAddressID,
lphCall,
lpszDestAddress,
lpszGroupID
);
}
LONG
WINAPI
linePrepareAddToConferenceW(
HCALL hConfCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lPrepareAddToConference),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hConfCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "linePrepareAddToConferenceW"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
linePrepareAddToConferenceA(
HCALL hConfCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lPrepareAddToConference),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hConfCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP() // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "linePrepareAddToConference"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
linePrepareAddToConference(
HCALL hConfCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
return linePrepareAddToConferenceA(
hConfCall,
lphConsultCall,
lpCallParams
);
}
LONG
WINAPI
lineProxyMessage(
HLINE hLine,
HCALL hCall,
DWORD dwMsg,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, lProxyMessage),
{
(ULONG_PTR) hLine,
(ULONG_PTR) hCall,
(ULONG_PTR) dwMsg,
(ULONG_PTR) dwParam1,
(ULONG_PTR) dwParam2,
(ULONG_PTR) dwParam3
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
}
};
return (DOFUNC (&funcArgs, "lineProxyMessage"));
}
LONG
WINAPI
lineProxyResponse(
HLINE hLine,
LPLINEPROXYREQUEST lpProxyRequest,
DWORD dwResult
)
{
LONG lResult = 0;
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lProxyResponse),
{
(ULONG_PTR) hLine,
(ULONG_PTR) 0,
(ULONG_PTR) lpProxyRequest,
(ULONG_PTR) dwResult
},
{
Dword,
Dword,
lpSet_Struct,
Dword
}
};
PPROXYREQUESTHEADER pProxyRequestHeader;
//
// The following is not the most thorough checking, but it's close
// enough that a client app won't get a totally unexpected value
// back
//
if (dwResult != 0 &&
(dwResult < LINEERR_ALLOCATED ||
dwResult > LINEERR_DIALVOICEDETECT))
{
return LINEERR_INVALPARAM;
}
//
// Backtrack a little bit to get the pointer to what ought to be
// the proxy header, and then make sure we're dealing with a valid
// proxy request
//
pProxyRequestHeader = (PPROXYREQUESTHEADER)
(((LPBYTE) lpProxyRequest) - sizeof (PROXYREQUESTHEADER));
try
{
//
// Make sure we've a valid pProxyRequestHeader, then invalidate
// the key so subsequent attempts to call lineProxyResponse with
// the same lpProxyRequest fail
//
if (pProxyRequestHeader->dwKey != TPROXYREQUESTHEADER_KEY)
{
lResult = LINEERR_INVALPOINTER;
}
pProxyRequestHeader->dwKey = 0xefefefef;
funcArgs.Args[1] = (ULONG_PTR) pProxyRequestHeader->dwInstance;
//
// See if this is one of the requests that don't require
// any data to get passed back & reset the appropriate
// params if so
//
switch (lpProxyRequest->dwRequestType)
{
case LINEPROXYREQUEST_SETAGENTGROUP:
case LINEPROXYREQUEST_SETAGENTSTATE:
case LINEPROXYREQUEST_SETAGENTACTIVITY:
case LINEPROXYREQUEST_SETAGENTMEASUREMENTPERIOD:
case LINEPROXYREQUEST_SETAGENTSESSIONSTATE:
case LINEPROXYREQUEST_SETQUEUEMEASUREMENTPERIOD:
case LINEPROXYREQUEST_SETAGENTSTATEEX:
funcArgs.Args[2] = (ULONG_PTR) TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
break;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
lResult = LINEERR_INVALPOINTER;
}
if (lResult == 0)
{
lResult = DOFUNC (&funcArgs, "lineProxyResponse");
//
// If we've gotten this far we want to free the buffer
// unconditionally
//
ClientFree (pProxyRequestHeader);
}
return lResult;
}
LONG
WINAPI
lineRedirectW(
HCALL hCall,
LPCWSTR lpszDestAddress,
DWORD dwCountryCode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lRedirect),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) dwCountryCode
},
{
Dword,
lpszW,
Dword
}
};
return (DOFUNC (&funcArgs, "lineRedirect"));
}
LONG
WINAPI
lineRedirectA(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
LONG lResult;
PWSTR szTempPtr;
if (IsBadStringPtrA (lpszDestAddress, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
lResult = lineRedirectW (hCall, szTempPtr, dwCountryCode);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
lineRedirect(
HCALL hCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode
)
{
return lineRedirectA (hCall, lpszDestAddress, dwCountryCode);
}
LONG
WINAPI
lineRegisterRequestRecipient(
HLINEAPP hLineApp,
DWORD dwRegistrationInstance,
DWORD dwRequestMode,
DWORD bEnable
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lRegisterRequestRecipient),
{
(ULONG_PTR) hLineApp,
(ULONG_PTR) dwRegistrationInstance,
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) bEnable
},
{
hXxxApp,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineRegisterRequestRecipient"));
}
LONG
WINAPI
lineReleaseUserUserInfo(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 1, lReleaseUserUserInfo),
{
(ULONG_PTR) hCall
},
{
Dword,
}
};
return (DOFUNC (&funcArgs, "lineReleaseUserUserInfo"));
}
LONG
WINAPI
lineRemoveFromConference(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 1, lRemoveFromConference),
{
(ULONG_PTR) hCall
},
{
Dword
}
};
return (DOFUNC (&funcArgs, "lineRemoveFromConference"));
}
LONG
WINAPI
lineRemoveProvider(
DWORD dwPermanentProviderID,
HWND hwndOwner
)
{
return (lineXxxProvider(
gszTUISPI_providerRemove, // func name
NULL, // lpszProviderFilename
hwndOwner, // hwndOwner
dwPermanentProviderID, // dwPermProviderID
NULL // lpdwPermProviderID
));
}
LONG
WINAPI
lineSecureCall(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 1, lSecureCall),
{
(ULONG_PTR) hCall
},
{
Dword
}
};
return (DOFUNC (&funcArgs, "lineSecureCall"));
}
LONG
WINAPI
lineSendUserUserInfo(
HCALL hCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSendUserUserInfo),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpsUserUserInfo,
(ULONG_PTR) dwSize
},
{
Dword,
lpSet_SizeToFollow,
Size
}
};
if (!lpsUserUserInfo)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineSendUserUserInfo"));
}
LONG
WINAPI
lineSetAgentActivity(
HLINE hLine,
DWORD dwAddressID,
DWORD dwActivityID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentActivity),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwActivityID
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAgentActivity"));
}
LONG
WINAPI
lineSetAgentGroup(
HLINE hLine,
DWORD dwAddressID,
LPLINEAGENTGROUPLIST lpAgentGroupList
)
{
static LINEAGENTGROUPLIST EmptyGroupList =
{
sizeof (LINEAGENTGROUPLIST), // dwTotalSize
sizeof (LINEAGENTGROUPLIST), // dwNeededSize
sizeof (LINEAGENTGROUPLIST), // dwUsedSize
0, // dwNumEntries
0, // dwListSize
0 // dwListOffset
};
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentGroup),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lpAgentGroupList
},
{
Dword,
Dword,
lpSet_Struct
}
};
if (!lpAgentGroupList)
{
funcArgs.Args[2] = (ULONG_PTR) &EmptyGroupList;
}
return (DOFUNC (&funcArgs, "lineSetAgentGroup"));
}
LONG
WINAPI
lineSetAgentMeasurementPeriod(
HLINE hLine,
HAGENT hAgent,
DWORD dwMeasurementPeriod
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentMeasurementPeriod),
{
(ULONG_PTR) hLine,
(ULONG_PTR) hAgent,
(ULONG_PTR) dwMeasurementPeriod
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAgentMeasurementPeriod"));
}
LONG
WINAPI
lineSetAgentSessionState(
HLINE hLine,
HAGENTSESSION hAgentSession,
DWORD dwSessionState,
DWORD dwNextSessionState
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentSessionState),
{
(ULONG_PTR) hLine,
(ULONG_PTR) hAgentSession,
(ULONG_PTR) dwSessionState,
(ULONG_PTR) dwNextSessionState
},
{
Dword,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAgentSessionState"));
}
LONG
WINAPI
lineSetAgentState(
HLINE hLine,
DWORD dwAddressID,
DWORD dwAgentState,
DWORD dwNextAgentState
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentState),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwAgentState,
(ULONG_PTR) dwNextAgentState
},
{
Dword,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAgentState"));
}
LONG
WINAPI
lineSetAgentStateEx(
HLINE hLine,
HAGENT hAgent,
DWORD dwAgentState,
DWORD dwNextAgentState
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentStateEx),
{
(ULONG_PTR) hLine,
(ULONG_PTR) hAgent,
(ULONG_PTR) dwAgentState,
(ULONG_PTR) dwNextAgentState
},
{
Dword,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAgentStateEx"));
}
LONG
WINAPI
lineSetAppPriorityW(
LPCWSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPCWSTR lpszExtensionName,
DWORD dwPriority
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 7, lSetAppPriority),
{
(ULONG_PTR) lpszAppName,
(ULONG_PTR) dwMediaMode,
(ULONG_PTR) TAPI_NO_DATA, // (DWORD) lpExtensionID,
(ULONG_PTR) 0, // (DWORD) sizeof(LINEEXTENSIONID),
(ULONG_PTR) dwRequestMode,
(ULONG_PTR) TAPI_NO_DATA, // (DWORD) lpszExtensionName,
(ULONG_PTR) dwPriority
},
{
lpszW,
Dword,
Dword, // lpSet_SizeToFollow,
Dword, // Size,
Dword,
Dword, // lpsz,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAppPriority"));
}
LONG
WINAPI
lineSetAppPriorityA(
LPCSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPCSTR lpszExtensionName,
DWORD dwPriority
)
{
LONG lResult;
PWSTR szTempPtr;
szTempPtr = NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
lResult = lineSetAppPriorityW(
szTempPtr,
dwMediaMode,
lpExtensionID,
dwRequestMode,
NULL, //szTempPtr2,
dwPriority
);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
lineSetAppPriority(
LPCSTR lpszAppName,
DWORD dwMediaMode,
LPLINEEXTENSIONID lpExtensionID,
DWORD dwRequestMode,
LPCSTR lpszExtensionName,
DWORD dwPriority
)
{
return lineSetAppPriorityA(
lpszAppName,
dwMediaMode,
lpExtensionID,
dwRequestMode,
lpszExtensionName,
dwPriority
);
}
LONG
WINAPI
lineSetAppSpecific(
HCALL hCall,
DWORD dwAppSpecific
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetAppSpecific),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwAppSpecific
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetAppSpecific"));
}
LONG
WINAPI
lineSetCallData(
HCALL hCall,
LPVOID lpCallData,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetCallData),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpCallData,
(ULONG_PTR) dwSize
},
{
Dword,
lpSet_SizeToFollow,
Size
}
};
if (dwSize == 0)
{
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
funcArgs.ArgTypes[1] =
funcArgs.ArgTypes[2] = Dword;
}
return (DOFUNC (&funcArgs, "lineSetCallData"));
}
LONG
WINAPI
lineSetCallParams(
HCALL hCall,
DWORD dwBearerMode,
DWORD dwMinRate,
DWORD dwMaxRate,
LPLINEDIALPARAMS const lpDialParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 6, lSetCallParams),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwBearerMode,
(ULONG_PTR) dwMinRate,
(ULONG_PTR) dwMaxRate,
(ULONG_PTR) lpDialParams,
(ULONG_PTR) sizeof(LINEDIALPARAMS)
},
{
Dword,
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
if (!lpDialParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[4] = Dword;
funcArgs.Args[4] = (ULONG_PTR) TAPI_NO_DATA;
funcArgs.ArgTypes[5] = Dword;
}
return (DOFUNC (&funcArgs, "lineSetCallParams"));
}
LONG
WINAPI
lineSetCallPrivilege(
HCALL hCall,
DWORD dwCallPrivilege
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetCallPrivilege),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwCallPrivilege
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetCallPrivilege"));
}
LONG
WINAPI
lineSetCallQualityOfService(
HCALL hCall,
LPVOID lpSendingFlowspec,
DWORD dwSendingFlowspecSize,
LPVOID lpReceivingFlowspec,
DWORD dwReceivingFlowspecSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lSetCallQualityOfService),
{
(ULONG_PTR) hCall,
(ULONG_PTR) lpSendingFlowspec,
(ULONG_PTR) dwSendingFlowspecSize,
(ULONG_PTR) lpReceivingFlowspec,
(ULONG_PTR) dwReceivingFlowspecSize
},
{
Dword,
lpSet_SizeToFollow,
Size,
lpSet_SizeToFollow,
Size,
}
};
return (DOFUNC (&funcArgs, "lineSetCallQualityOfService"));
}
LONG
WINAPI
lineSetCallTreatment(
HCALL hCall,
DWORD dwTreatment
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lSetCallTreatment),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwTreatment
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetCallTreatment"));
}
LONG
WINAPI
lineSetDevConfigW(
DWORD dwDeviceID,
LPVOID const lpDeviceConfig,
DWORD dwSize,
LPCWSTR lpszDeviceClass
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 4, lSetDevConfig),
{
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lpDeviceConfig,
(ULONG_PTR) dwSize,
(ULONG_PTR) lpszDeviceClass
},
{
Dword,
lpSet_SizeToFollow,
Size,
lpszW
}
};
return (DOFUNC (&funcArgs, "lineSetDevConfig"));
}
LONG
WINAPI
lineSetDevConfigA(
DWORD dwDeviceID,
LPVOID const lpDeviceConfig,
DWORD dwSize,
LPCSTR lpszDeviceClass
)
{
LONG lResult;
PWSTR szTempPtr;
if (IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
else if (!(szTempPtr = NotSoWideStringToWideString(
lpszDeviceClass,
(DWORD) -1
)))
{
return LINEERR_NOMEM;
}
lResult = lineSetDevConfigW(
dwDeviceID,
lpDeviceConfig,
dwSize,
szTempPtr
);
ClientFree (szTempPtr);
return lResult;
}
LONG
WINAPI
lineSetDevConfig(
DWORD dwDeviceID,
LPVOID const lpDeviceConfig,
DWORD dwSize,
LPCSTR lpszDeviceClass
)
{
return lineSetDevConfigA(
dwDeviceID,
lpDeviceConfig,
dwSize,
lpszDeviceClass
);
}
LONG
WINAPI
lineSetLineDevStatus(
HLINE hLine,
DWORD dwStatusToChange,
DWORD fStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetLineDevStatus),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwStatusToChange,
(ULONG_PTR) fStatus
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetLineDevStatus"));
}
LONG
WINAPI
lineSetMediaControl(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
DWORD dwSelect,
LPLINEMEDIACONTROLDIGIT const lpDigitList,
DWORD dwDigitNumEntries,
LPLINEMEDIACONTROLMEDIA const lpMediaList,
DWORD dwMediaNumEntries,
LPLINEMEDIACONTROLTONE const lpToneList,
DWORD dwToneNumEntries,
LPLINEMEDIACONTROLCALLSTATE const lpCallStateList,
DWORD dwCallStateNumEntries
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 12, lSetMediaControl),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) hCall,
(ULONG_PTR) dwSelect,
(ULONG_PTR) TAPI_NO_DATA,
(ULONG_PTR) dwDigitNumEntries * sizeof(LINEMEDIACONTROLDIGIT),
(ULONG_PTR) TAPI_NO_DATA,
(ULONG_PTR) dwMediaNumEntries * sizeof(LINEMEDIACONTROLMEDIA),
(ULONG_PTR) TAPI_NO_DATA,
(ULONG_PTR) dwToneNumEntries * sizeof(LINEMEDIACONTROLTONE),
(ULONG_PTR) TAPI_NO_DATA,
(ULONG_PTR) dwCallStateNumEntries * sizeof(LINEMEDIACONTROLCALLSTATE)
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword
}
};
//
// If lpXxxList is non-NULL reset Arg & ArgType, and check
// to see that dwXxxNumEntries is not unacceptably large
//
if (lpDigitList)
{
if (dwDigitNumEntries >
(0x1000000 / sizeof (LINEMEDIACONTROLDIGIT)))
{
return LINEERR_INVALPOINTER;
}
funcArgs.ArgTypes[4] = lpSet_SizeToFollow;
funcArgs.Args[4] = (ULONG_PTR) lpDigitList;
funcArgs.ArgTypes[5] = Size;
}
if (lpMediaList)
{
if (dwMediaNumEntries >
(0x1000000 / sizeof (LINEMEDIACONTROLMEDIA)))
{
return LINEERR_INVALPOINTER;
}
funcArgs.ArgTypes[6] = lpSet_SizeToFollow;
funcArgs.Args[6] = (ULONG_PTR) lpMediaList;
funcArgs.ArgTypes[7] = Size;
}
if (lpToneList)
{
if (dwToneNumEntries >
(0x1000000 / sizeof (LINEMEDIACONTROLTONE)))
{
return LINEERR_INVALPOINTER;
}
funcArgs.ArgTypes[8] = lpSet_SizeToFollow;
funcArgs.Args[8] = (ULONG_PTR) lpToneList;
funcArgs.ArgTypes[9] = Size;
}
if (lpCallStateList)
{
if (dwCallStateNumEntries >
(0x1000000 / sizeof (LINEMEDIACONTROLCALLSTATE)))
{
return LINEERR_INVALPOINTER;
}
funcArgs.ArgTypes[10] = lpSet_SizeToFollow;
funcArgs.Args[10] = (ULONG_PTR) lpCallStateList;
funcArgs.ArgTypes[11] = Size;
}
return (DOFUNC (&funcArgs, "lineSetMediaControl"));
}
LONG
WINAPI
lineSetMediaMode(
HCALL hCall,
DWORD dwMediaModes
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, lSetMediaMode),
{
(ULONG_PTR) hCall,
(ULONG_PTR) dwMediaModes
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetMediaMode"));
}
LONG
WINAPI
lineSetNumRings(
HLINE hLine,
DWORD dwAddressID,
DWORD dwNumRings
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lSetNumRings),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) dwNumRings
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetNumRings"));
}
LONG
WINAPI
lineSetQueueMeasurementPeriod(
HLINE hLine,
DWORD dwQueueID,
DWORD dwMeasurementPeriod
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 3, lSetQueueMeasurementPeriod),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwQueueID,
(ULONG_PTR) dwMeasurementPeriod
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetQueueMeasurementPeriod"));
}
LONG
WINAPI
lineSetStatusMessages(
HLINE hLine,
DWORD dwLineStates,
DWORD dwAddressStates
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwLineStates,
(ULONG_PTR) dwAddressStates
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetStatusMessages"));
}
LONG
WINAPI
lineSetTerminal(
HLINE hLine,
DWORD dwAddressID,
HCALL hCall,
DWORD dwSelect,
DWORD dwTerminalModes,
DWORD dwTerminalID,
DWORD bEnable
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 7, lSetTerminal),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) hCall,
(ULONG_PTR) dwSelect,
(ULONG_PTR) dwTerminalModes,
(ULONG_PTR) dwTerminalID,
(ULONG_PTR) bEnable
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSetTerminal"));
}
void
PASCAL
lineSetupConferencePostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "lineSetupConfPostProcess: enter"));
LOG((TL_INFO,
"\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
HCALL hConfCall = (HCALL) pMsg->Param3,
hConsultCall = (HCALL) *(&pMsg->Param4 + 1);
LPHCALL lphConfCall = (LPHCALL) ReferenceObject (ghHandleTable, pMsg->Param4, 0),
lphConsultCall = (LPHCALL) ReferenceObject (ghHandleTable, *(&pMsg->Param4 + 2), 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param4, 2);
DereferenceObject (ghHandleTable, *(&pMsg->Param4 + 2), 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPHCALL lphConfCallVDM = (LPHCALL) gpfnWOWGetVDMPointer(
(DWORD) lphConfCall,
sizeof (HCALL),
TRUE // fProtectedMode
),
lphConsultCallVDM = (LPHCALL) gpfnWOWGetVDMPointer(
(DWORD) lphConsultCall,
sizeof (HCALL),
TRUE // fProtectedMode
);
if (lphConfCallVDM && lphConsultCallVDM)
{
*lphConfCallVDM = hConfCall;
*lphConsultCallVDM = hConsultCall;
}
else
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
#endif
}
else
{
*lphConfCall = hConfCall;
*lphConsultCall = hConsultCall;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = LINEERR_INVALPOINTER;
}
}
}
LONG
WINAPI
lineSetupConferenceW(
HCALL hCall,
HLINE hLine,
LPHCALL lphConfCall,
LPHCALL lphConsultCall,
DWORD dwNumParties,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lSetupConference),
{
(ULONG_PTR) GetFunctionIndex(lineSetupConferencePostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) hLine,
(ULONG_PTR) lphConfCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) dwNumParties,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer1 = 0, hPointer2 = 0;
LONG lResult;
if (lphConfCall == lphConsultCall)
{
return LINEERR_INVALPOINTER;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[6] = Dword;
funcArgs.Args[6] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConfCall) ||
IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer1 = NewObject (ghHandleTable, (PVOID)lphConfCall, NULL);
if (0 == hPointer1)
{
return LINEERR_NOMEM;
}
hPointer2 = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer2)
{
DereferenceObject (ghHandleTable, hPointer1, 1);
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer1;
funcArgs.Args[4] = (ULONG_PTR)hPointer2;
}
lResult = (DOFUNC (&funcArgs, "lineSetupConferenceW"));
if (0 > lResult && hPointer1)
{
DereferenceObject (ghHandleTable, hPointer1, 1);
DereferenceObject (ghHandleTable, hPointer2, 1);
}
return lResult;
}
LONG
WINAPI
lineSetupConferenceA(
HCALL hCall,
HLINE hLine,
LPHCALL lphConfCall,
LPHCALL lphConsultCall,
DWORD dwNumParties,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 8, lSetupConference),
{
(ULONG_PTR) GetFunctionIndex(lineSetupConferencePostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) hLine,
(ULONG_PTR) lphConfCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) dwNumParties,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP() // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer1 = 0, hPointer2 = 0;
LONG lResult;
if (lphConfCall == lphConsultCall)
{
return LINEERR_INVALPOINTER;
}
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[6] = Dword;
funcArgs.Args[6] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConfCall) ||
IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer1 = NewObject (ghHandleTable, (PVOID)lphConfCall, NULL);
if (0 == hPointer1)
{
return LINEERR_NOMEM;
}
hPointer2 = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer2)
{
DereferenceObject (ghHandleTable, hPointer1, 1);
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer1;
funcArgs.Args[4] = (ULONG_PTR)hPointer2;
}
lResult = (DOFUNC (&funcArgs, "lineSetupConference"));
if (0 > lResult && hPointer1)
{
DereferenceObject (ghHandleTable, hPointer1, 1);
DereferenceObject (ghHandleTable, hPointer2, 1);
}
return lResult;
}
LONG
WINAPI
lineSetupConference(
HCALL hCall,
HLINE hLine,
LPHCALL lphConfCall,
LPHCALL lphConsultCall,
DWORD dwNumParties,
LPLINECALLPARAMS const lpCallParams
)
{
return lineSetupConferenceA(
hCall,
hLine,
lphConfCall,
lphConsultCall,
dwNumParties,
lpCallParams
);
}
LONG
WINAPI
lineSetupTransferW(
HCALL hCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lSetupTransfer),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) TAPI_NO_DATA // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "lineSetupTransferW"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineSetupTransferA(
HCALL hCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lSetupTransfer),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hCall,
(ULONG_PTR) lphConsultCall,
(ULONG_PTR) lpCallParams,
(ULONG_PTR) GetACP() // dwAsciiCallParamsCodePage
},
{
Dword,
Dword,
Dword,
lpSet_Struct,
Dword
}
};
DWORD hPointer = 0;
LONG lResult;
if (!lpCallParams)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphConsultCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphConsultCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "lineSetupTransferW"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineSetupTransfer(
HCALL hCall,
LPHCALL lphConsultCall,
LPLINECALLPARAMS const lpCallParams
)
{
return lineSetupTransferA (hCall, lphConsultCall, lpCallParams);
}
LONG
WINAPI
lineShutdown(
HLINEAPP hLineApp
)
{
return (xxxShutdown (hLineApp, TRUE));
}
LONG
WINAPI
lineSwapHold(
HCALL hActiveCall,
HCALL hHeldCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lSwapHold),
{
(ULONG_PTR) hActiveCall,
(ULONG_PTR) hHeldCall
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineSwapHold"));
}
LONG
WINAPI
lineUncompleteCall(
HLINE hLine,
DWORD dwCompletionID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 2, lUncompleteCall),
{
(ULONG_PTR) hLine,
(ULONG_PTR) dwCompletionID
},
{
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "lineUncompleteCall"));
}
LONG
WINAPI
lineUnhold(
HCALL hCall
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 1, lUnhold),
{
(ULONG_PTR) hCall
},
{
Dword
}
};
return (DOFUNC (&funcArgs, "lineUnhold"));
}
LONG
WINAPI
lineUnparkW(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCWSTR lpszDestAddress
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | ASYNC | 5, lUnpark),
{
(ULONG_PTR) GetFunctionIndex(lineMakeCallPostProcess),
(ULONG_PTR) hLine,
(ULONG_PTR) dwAddressID,
(ULONG_PTR) lphCall,
(ULONG_PTR) lpszDestAddress
},
{
Dword,
Dword,
Dword,
Dword,
lpszW
}
};
DWORD hPointer = 0;
LONG lResult;
if (!gbNTVDMClient)
{
if (IsBadDwordPtr (lphCall))
{
return LINEERR_INVALPOINTER;
}
hPointer = NewObject (ghHandleTable, (PVOID)lphCall, NULL);
if (0 == hPointer)
{
return LINEERR_NOMEM;
}
funcArgs.Args[3] = (ULONG_PTR)hPointer;
}
lResult = (DOFUNC (&funcArgs, "lineUnpark"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
lineUnparkA(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCSTR lpszDestAddress
)
{
LONG lResult;
PWSTR szTempPtr;
if (IsBadStringPtrA (lpszDestAddress, (DWORD) -1))
{
return LINEERR_INVALPOINTER;
}
else if (!(szTempPtr = NotSoWideStringToWideString(
lpszDestAddress,
(DWORD) -1
)))
{
return LINEERR_NOMEM;
}
lResult = lineUnparkW (hLine, dwAddressID, lphCall, szTempPtr);
ClientFree (szTempPtr);
return lResult;
}
LONG
WINAPI
lineUnpark(
HLINE hLine,
DWORD dwAddressID,
LPHCALL lphCall,
LPCSTR lpszDestAddress
)
{
return lineUnparkA (hLine, dwAddressID, lphCall, lpszDestAddress);
}
//
// ------------------------------- phoneXxx -----------------------------------
//
LONG
WINAPI
phoneClose(
HPHONE hPhone
)
{
LONG lResult;
DWORD Handle = 0;
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pClose),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) &Handle
},
{
Dword,
lpDword
}
};
lResult = DOFUNC (&funcArgs, "phoneClose");
if (0 == lResult &&
0 != Handle)
{
DereferenceObject (ghHandleTable, Handle, 1);
}
return lResult;
}
LONG
WINAPI
phoneConfigDialogW(
DWORD dwDeviceID,
HWND hwndOwner,
LPCWSTR lpszDeviceClass
)
{
LONG lResult;
HANDLE hDll;
TUISPIPROC pfnTUISPI_phoneConfigDialog;
if (lpszDeviceClass && TAPIIsBadStringPtrW (lpszDeviceClass, (UINT) -1))
{
LOG((TL_ERROR, "Bad lpszDeviceClass in phoneConfigDialogW [%p]",
lpszDeviceClass ));
return PHONEERR_INVALPOINTER;
}
if ((lResult = LoadUIDll(
hwndOwner,
dwDeviceID,
TUISPIDLL_OBJECT_PHONEID,
&hDll,
gszTUISPI_phoneConfigDialog,
&pfnTUISPI_phoneConfigDialog
)) == 0)
{
LOG((TL_TRACE, "Calling TUISPI_phoneConfigDialog..."));
lResult = (*pfnTUISPI_phoneConfigDialog)(
TUISPIDLLCallback,
dwDeviceID,
hwndOwner,
lpszDeviceClass
);
#if DBG
{
char szResult[32];
LOG((TL_TRACE,
"TUISPI_phoneConfigDialog: result = %hs",
MapResultCodeToText (lResult, szResult)
));
}
#else
LOG((TL_TRACE,
"TUISPI_phoneConfigDialog: result = x%x",
lResult
));
#endif
FreeLibrary (hDll);
}
return lResult;
}
LONG
WINAPI
phoneConfigDialogA(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass
)
{
LONG lResult;
PWSTR szTempString;
if (lpszDeviceClass && IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
{
return PHONEERR_INVALPOINTER;
}
szTempString = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
lResult = phoneConfigDialogW (dwDeviceID, hwndOwner, szTempString);
if (szTempString)
{
ClientFree (szTempString);
}
return lResult;
}
LONG
WINAPI
phoneConfigDialog(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass
)
{
return phoneConfigDialogA (dwDeviceID, hwndOwner, lpszDeviceClass);
}
void
PASCAL
phoneDevSpecificPostProcess(
PASYNCEVENTMSG pMsg
)
{
LOG((TL_TRACE, "phoneDevSpecificPostProcess: enter"));
LOG((TL_INFO,
"\t\tp1=x%lx, p2=x%lx, p3=x%lx, p4=x%lx",
pMsg->Param1,
pMsg->Param2,
pMsg->Param3,
pMsg->Param4
));
if (pMsg->Param2 == 0)
{
DWORD dwSize = (DWORD) pMsg->Param4;
if (dwSize > 0)
{
LPBYTE pParams = (LPBYTE) ReferenceObject (ghHandleTable, pMsg->Param3, 0);
// We don't need the handle to the pointer any more...
DereferenceObject (ghHandleTable, pMsg->Param3, 2);
try
{
if (gbNTVDMClient)
{
#ifndef _WIN64
LPVARSTRING pParamsVDM = (LPVARSTRING) gpfnWOWGetVDMPointer(
(DWORD) pParams,
dwSize,
TRUE // fProtectedMode
);
if (pParamsVDM)
{
CopyMemory (pParamsVDM, (LPBYTE) (pMsg + 1), dwSize);
}
else
{
pMsg->Param2 = PHONEERR_INVALPOINTER;
}
#endif
}
else
{
CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
pMsg->Param2 = PHONEERR_INVALPOINTER;
}
}
}
}
LONG
WINAPI
phoneDevSpecific(
HPHONE hPhone,
LPVOID lpParams,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 5, pDevSpecific),
{
(ULONG_PTR) GetFunctionIndex(phoneDevSpecificPostProcess),
(ULONG_PTR) hPhone,
(ULONG_PTR) lpParams, // passed as Dword for post processing
(ULONG_PTR) lpParams, // passed as LpSet_Xxx for IsValidPtr chk
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
DWORD hPointer = 0;
LONG lResult;
if (gbNTVDMClient)
{
#ifndef _WIN64
if (!gpfnWOWGetVDMPointer ||
!(funcArgs.Args[3] = (ULONG_PTR) gpfnWOWGetVDMPointer(
(DWORD) lpParams,
dwSize,
TRUE // fProtectedMode
)))
#endif
{
return PHONEERR_OPERATIONFAILED;
}
}
if (!gbNTVDMClient)
{
if ( !lpParams && dwSize > 0 )
{
return PHONEERR_INVALPOINTER;
}
if (lpParams)
{
hPointer = NewObject (ghHandleTable, (PVOID)lpParams, NULL);
if (0 == hPointer)
{
return PHONEERR_NOMEM;
}
funcArgs.Args[2] = (ULONG_PTR)hPointer;
}
}
lResult = (DOFUNC (&funcArgs, "phoneDevSpecific"));
if (0 > lResult && hPointer)
{
DereferenceObject (ghHandleTable, hPointer, 1);
}
return lResult;
}
LONG
WINAPI
phoneGetButtonInfoW(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO lpButtonInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwButtonLampID,
(ULONG_PTR) lpButtonInfo
},
{
Dword,
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "phoneGetButtonInfo"));
}
LONG
WINAPI
phoneGetButtonInfoA(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO lpButtonInfo
)
{
LONG lResult;
lResult = phoneGetButtonInfoW (hPhone, dwButtonLampID, lpButtonInfo);
if ( 0 == lResult )
{
WideStringToNotSoWideString(
(LPBYTE)lpButtonInfo,
&lpButtonInfo->dwButtonTextSize
);
}
return lResult;
}
LONG
WINAPI
phoneGetButtonInfo(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO lpButtonInfo
)
{
return phoneGetButtonInfoA (hPhone, dwButtonLampID, lpButtonInfo);
}
LONG
WINAPI
phoneGetData(
HPHONE hPhone,
DWORD dwDataID,
LPVOID lpData,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 4, pGetData),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwDataID,
(ULONG_PTR) lpData,
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
lpGet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "phoneGetData"));
}
LONG
WINAPI
phoneGetDevCapsW(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPPHONECAPS lpPhoneCaps
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 5, pGetDevCaps),
{
(ULONG_PTR) hPhoneApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) lpPhoneCaps
},
{
hXxxApp,
Dword,
Dword,
Dword,
lpGet_Struct
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return PHONEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "phoneGetDevCaps"));
}
LONG
WINAPI
phoneGetDevCapsA(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPPHONECAPS lpPhoneCaps
)
{
LONG lResult;
lResult = phoneGetDevCapsW(
hPhoneApp,
dwDeviceID,
dwAPIVersion,
dwExtVersion,
lpPhoneCaps
);
if (lResult == 0)
{
lpPhoneCaps->dwStringFormat = STRINGFORMAT_ASCII;
WideStringToNotSoWideString(
(LPBYTE) lpPhoneCaps,
&lpPhoneCaps->dwProviderInfoSize
);
WideStringToNotSoWideString(
(LPBYTE) lpPhoneCaps,
&lpPhoneCaps->dwPhoneInfoSize
);
WideStringToNotSoWideString(
(LPBYTE) lpPhoneCaps,
&lpPhoneCaps->dwPhoneNameSize
);
if (dwAPIVersion >= 0x00020000)
{
WideStringToNotSoWideString(
(LPBYTE) lpPhoneCaps,
&lpPhoneCaps->dwDeviceClassesSize
);
}
}
return lResult;
}
LONG
WINAPI
phoneGetDevCaps(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtVersion,
LPPHONECAPS lpPhoneCaps
)
{
return phoneGetDevCapsA(
hPhoneApp,
dwDeviceID,
dwAPIVersion,
dwExtVersion,
lpPhoneCaps
);
}
LONG
WINAPI
phoneGetDisplay(
HPHONE hPhone,
LPVARSTRING lpDisplay
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetDisplay),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpDisplay
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "phoneGetDisplay"));
}
LONG
WINAPI
phoneGetGain(
HPHONE hPhone,
DWORD dwHookSwitchDev,
LPDWORD lpdwGain
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetGain),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwHookSwitchDev,
(ULONG_PTR) lpdwGain
},
{
Dword,
Dword,
lpDword
}
};
return (DOFUNC (&funcArgs, "phoneGetGain"));
}
LONG
WINAPI
phoneGetHookSwitch(
HPHONE hPhone,
LPDWORD lpdwHookSwitchDevs
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpdwHookSwitchDevs
},
{
Dword,
lpDword
}
};
return (DOFUNC (&funcArgs, "phoneGetHookSwitch"));
}
LONG
WINAPI
phoneGetIconW(
DWORD dwDeviceID,
LPCWSTR lpszDeviceClass,
LPHICON lphIcon
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetIcon),
{
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lpszDeviceClass,
(ULONG_PTR) lphIcon
},
{
Dword,
lpszW,
lpDword
}
};
if (IsBadDwordPtr ((LPDWORD) lphIcon))
{
LOG((TL_ERROR,
"Bad icon pointer passed into PhoneGetIconA [0x%p]",
lphIcon
));
return PHONEERR_INVALPOINTER;
}
if (lpszDeviceClass == (LPCWSTR) NULL)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
}
return DOFUNC (&funcArgs, "phoneGetIcon");
}
LONG
WINAPI
phoneGetIconA(
DWORD dwDeviceID,
LPCSTR lpszDeviceClass,
LPHICON lphIcon
)
{
LONG lResult;
PWSTR szTempPtr;
if (lpszDeviceClass)
{
if (IsBadStringPtrA (lpszDeviceClass, (DWORD) (DWORD) -1))
{
return PHONEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
}
else
{
szTempPtr = NULL;
}
lResult = phoneGetIconW (dwDeviceID, szTempPtr, lphIcon);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
phoneGetIcon(
DWORD dwDeviceID,
LPCSTR lpszDeviceClass,
LPHICON lphIcon
)
{
return (phoneGetIconA (dwDeviceID, lpszDeviceClass, lphIcon));
}
LONG
WINAPI
phoneGetIDW(
HPHONE hPhone,
LPVARSTRING lpDeviceID,
LPCWSTR lpszDeviceClass
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetID),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpDeviceID,
(ULONG_PTR) lpszDeviceClass
},
{
Dword,
lpGet_Struct,
lpszW
}
};
LPVARSTRING lpDeviceIDTemp = NULL;
DWORD dwNumDevices;
DWORD dwBufSize;
DWORD dwResult;
DWORD dwDeviceId1, dwDeviceId2;
BOOL bDoItAgain = FALSE;
if ( TAPIIsBadStringPtrW(lpszDeviceClass, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDeviceClass in phoneGetIDW"));
return( PHONEERR_INVALPOINTER );
}
if ( IsBadWritePtr(lpDeviceID, sizeof(VARSTRING)) )
{
LOG((TL_ERROR, "Bad lpDeviceID in lineGetIDW"));
return( PHONEERR_INVALPOINTER);
}
//
// if the request is for a wave device, call LGetIDEx
//
if (!_wcsicmp(lpszDeviceClass, L"wave/in") ||
!_wcsicmp(lpszDeviceClass, L"wave/out") ||
!_wcsicmp(lpszDeviceClass, L"midi/in") ||
!_wcsicmp(lpszDeviceClass, L"midi/out") ||
!_wcsicmp(lpszDeviceClass, L"wave/in/out")
)
{
dwNumDevices = _wcsicmp(lpszDeviceClass, L"wave/in/out") ? 1 : 2;
dwBufSize = lpDeviceID->dwTotalSize + dwNumDevices * WAVE_STRING_ID_BUFFER_SIZE;
do
{
//
// Allocate additional memory for the device string ID
//
lpDeviceIDTemp = (LPVARSTRING)ClientAlloc (dwBufSize);
if (!lpDeviceIDTemp)
{
LOG((TL_ERROR, "Failed to allocate memory"));
return( PHONEERR_NOMEM );
}
lpDeviceIDTemp->dwTotalSize = dwBufSize;
funcArgs.Flags = MAKELONG (PHONE_FUNC | SYNC | 3, pGetIDEx);
funcArgs.Args[1] = (ULONG_PTR)lpDeviceIDTemp;
//
// Call LGetIDEx
//
dwResult = DOFUNC (&funcArgs, "phoneGetIDEx");
if (dwResult)
{
LOG((TL_ERROR, "phoneGetIDEx failed with x%x", dwResult));
ClientFree (lpDeviceIDTemp);
return dwResult;
}
if (lpDeviceIDTemp->dwNeededSize > lpDeviceIDTemp->dwTotalSize && !bDoItAgain)
{
LOG((TL_INFO,
"phoneGetIDEx returned needed size (%d) bigger than total size (%d) -> need to realloc",
lpDeviceIDTemp->dwNeededSize,
lpDeviceIDTemp->dwTotalSize ));
dwBufSize = lpDeviceIDTemp->dwNeededSize;
ClientFree ( lpDeviceIDTemp );
bDoItAgain = TRUE;
}
else
{
bDoItAgain = FALSE;
}
} while (bDoItAgain);
if (lpDeviceIDTemp->dwNeededSize > lpDeviceIDTemp->dwTotalSize)
{
LOG((TL_ERROR, "needed size (%d) still bigger than total size (%d)",
lpDeviceIDTemp->dwNeededSize,
lpDeviceIDTemp->dwTotalSize ));
ClientFree (lpDeviceIDTemp);
return PHONEERR_OPERATIONFAILED;
}
//
// Get the device ID from string ID
//
if (dwNumDevices == 1)
{
if (!WaveStringIdToDeviceId (
(LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset),
lpszDeviceClass,
&dwDeviceId1)
)
{
LOG((TL_ERROR, "WaveStringIdToDeviceId failed"));
ClientFree (lpDeviceIDTemp);
return PHONEERR_OPERATIONFAILED;
}
// check if the client buffer is big enough
if (lpDeviceID->dwTotalSize < sizeof(VARSTRING) + sizeof(DWORD))
{
lpDeviceID->dwNeededSize = sizeof(VARSTRING) + sizeof(DWORD);
lpDeviceID->dwUsedSize = sizeof(VARSTRING);
}
else
{
lpDeviceID->dwNeededSize = lpDeviceID->dwUsedSize = sizeof(VARSTRING) + sizeof(DWORD);
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = sizeof(DWORD);
lpDeviceID->dwStringOffset = sizeof(VARSTRING);
*(DWORD *)(lpDeviceID + 1) = dwDeviceId1;
}
}
else
{
LPWSTR szString1 = (LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset);
if (!WaveStringIdToDeviceId (
szString1,
L"wave/in",
&dwDeviceId1) ||
!WaveStringIdToDeviceId (
(LPWSTR)((LPBYTE)lpDeviceIDTemp + lpDeviceIDTemp->dwStringOffset + wcslen(szString1)),
L"wave/out",
&dwDeviceId2)
)
{
LOG((TL_ERROR, "WaveStringIdToDeviceId failed"));
ClientFree (lpDeviceIDTemp);
return PHONEERR_OPERATIONFAILED;
}
// check if the client buffer is big enough
if (lpDeviceID->dwTotalSize < sizeof(VARSTRING) + 2 * sizeof(DWORD))
{
lpDeviceID->dwNeededSize = sizeof(VARSTRING) + 2 * sizeof(DWORD);
lpDeviceID->dwUsedSize = sizeof(VARSTRING);
}
else
{
lpDeviceID->dwNeededSize = lpDeviceID->dwUsedSize = sizeof(VARSTRING) + 2 * sizeof(DWORD);
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = 2 * sizeof(DWORD);
lpDeviceID->dwStringOffset = sizeof(VARSTRING);
*(DWORD *)(lpDeviceID + 1) = dwDeviceId1;
*((DWORD *)(lpDeviceID + 1) + 1) = dwDeviceId2;
}
}
ClientFree (lpDeviceIDTemp);
return NO_ERROR;
}
else
{
return (DOFUNC (&funcArgs, "phoneGetID"));
}
}
LONG
WINAPI
phoneGetIDA(
HPHONE hPhone,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass
)
{
LONG lResult;
PWSTR szTempPtr;
if ( IsBadStringPtrA(lpszDeviceClass, (UINT)-1) )
{
LOG((TL_ERROR, "Bad lpszDeviceClass in phoneGetIDA"));
return( PHONEERR_INVALPOINTER );
}
szTempPtr = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
lResult = phoneGetIDW (hPhone, lpDeviceID, szTempPtr);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
phoneGetID(
HPHONE hPhone,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass
)
{
return phoneGetIDA (hPhone, lpDeviceID, lpszDeviceClass);
}
LONG
WINAPI
phoneGetLamp(
HPHONE hPhone,
DWORD dwButtonLampID,
LPDWORD lpdwLampMode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetLamp),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwButtonLampID,
(ULONG_PTR) lpdwLampMode
},
{
Dword,
Dword,
lpDword
}
};
return (DOFUNC (&funcArgs, "phoneGetLamp"));
}
LONG
WINAPI
phoneGetMessage(
HPHONEAPP hPhoneApp,
LPPHONEMESSAGE lpMessage,
DWORD dwTimeout
)
{
return (xxxGetMessage(
FALSE,
(HLINEAPP) hPhoneApp,
(LPLINEMESSAGE) lpMessage,
dwTimeout
));
}
LONG
WINAPI
phoneGetRing(
HPHONE hPhone,
LPDWORD lpdwRingMode,
LPDWORD lpdwVolume
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpdwRingMode,
(ULONG_PTR) lpdwVolume
},
{
Dword,
lpDword,
lpDword
}
};
if (lpdwRingMode == lpdwVolume)
{
return PHONEERR_INVALPOINTER;
}
return (DOFUNC (&funcArgs, "phoneGetRing"));
}
LONG
WINAPI
phoneGetStatusW(
HPHONE hPhone,
LPPHONESTATUS lpPhoneStatus
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 2, pGetStatus),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpPhoneStatus
},
{
Dword,
lpGet_Struct
}
};
return (DOFUNC (&funcArgs, "phoneGetStatus"));
}
LONG
WINAPI
phoneGetStatusA(
HPHONE hPhone,
LPPHONESTATUS lpPhoneStatus
)
{
LONG lResult;
lResult = phoneGetStatusW (hPhone, lpPhoneStatus);
if (lResult == 0)
{
WideStringToNotSoWideString(
(LPBYTE)lpPhoneStatus,
&lpPhoneStatus->dwOwnerNameSize
);
}
return lResult;
}
LONG
WINAPI
phoneGetStatus(
HPHONE hPhone,
LPPHONESTATUS lpPhoneStatus
)
{
return phoneGetStatusA (hPhone, lpPhoneStatus);
}
LONG
WINAPI
phoneGetStatusMessages(
HPHONE hPhone,
LPDWORD lpdwPhoneStates,
LPDWORD lpdwButtonModes,
LPDWORD lpdwButtonStates
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 4, pGetStatusMessages),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) lpdwPhoneStates,
(ULONG_PTR) lpdwButtonModes,
(ULONG_PTR) lpdwButtonStates
},
{
Dword,
lpDword,
lpDword,
lpDword
}
};
if (lpdwPhoneStates == lpdwButtonModes ||
lpdwPhoneStates == lpdwButtonStates ||
lpdwButtonModes == lpdwButtonStates)
{
return PHONEERR_INVALPOINTER;
}
return (DOFUNC (&funcArgs, "phoneGetStatusMessages"));
}
LONG
WINAPI
phoneGetVolume(
HPHONE hPhone,
DWORD dwHookSwitchDev,
LPDWORD lpdwVolume
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 3, pGetVolume),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwHookSwitchDev,
(ULONG_PTR) lpdwVolume
},
{
Dword,
Dword,
lpDword
}
};
return (DOFUNC (&funcArgs, "phoneGetVolume"));
}
LONG
WINAPI
phoneInitialize(
LPHPHONEAPP lphPhoneApp,
HINSTANCE hInstance,
PHONECALLBACK lpfnCallback,
LPCSTR lpszFriendlyAppName,
LPDWORD lpdwNumDevs
)
{
LONG lResult;
PWSTR szTempPtr;
if (lpszFriendlyAppName)
{
if (IsBadStringPtrA (lpszFriendlyAppName, (DWORD) -1))
{
LOG((TL_ERROR,
"phoneInitialize: bad lpszFriendlyAppName (x%p)",
lpszFriendlyAppName
));
return PHONEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString(
lpszFriendlyAppName,
(DWORD) -1
);
}
else
{
szTempPtr = NULL;
}
//
// NOTE: the hack below for the lpInitExParam is for 16-bit apps,
// since the lpszAppName really points at a
// <friendly name>\0<module name>\0 string and we need the
// module name in xxxInitialize()
//
lResult = (xxxInitialize(
FALSE,
(LPVOID) lphPhoneApp,
hInstance,
lpfnCallback,
szTempPtr,
lpdwNumDevs,
NULL,
#ifdef _WIN64
NULL
#else
(LPLINEINITIALIZEEXPARAMS)
(((DWORD) lpfnCallback & 0xffff0000) == 0xffff0000 ?
lpszFriendlyAppName : NULL)
#endif
#if DBG
,"phoneInitialize"
#endif
));
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
phoneInitializeExW(
LPHPHONEAPP lphPhoneApp,
HINSTANCE hInstance,
PHONECALLBACK lpfnCallback,
LPCWSTR lpszFriendlyAppName,
LPDWORD lpdwNumDevs,
LPDWORD lpdwAPIVersion,
LPPHONEINITIALIZEEXPARAMS lpPhoneInitializeExParams
)
{
if (IsBadDwordPtr (lpdwAPIVersion))
{
LOG((TL_ERROR,
"phoneInitializeExW: bad lpdwAPIVersion (x%p)",
lpdwAPIVersion
));
return PHONEERR_INVALPOINTER;
}
return (xxxInitialize(
FALSE,
(LPVOID) lphPhoneApp,
hInstance,
lpfnCallback,
lpszFriendlyAppName,
lpdwNumDevs,
lpdwAPIVersion,
(LPVOID) lpPhoneInitializeExParams
#if DBG
,"phoneInitializeExW"
#endif
));
}
LONG
WINAPI
phoneInitializeExA(
LPHPHONEAPP lphPhoneApp,
HINSTANCE hInstance,
PHONECALLBACK lpfnCallback,
LPCSTR lpszFriendlyAppName,
LPDWORD lpdwNumDevs,
LPDWORD lpdwAPIVersion,
LPPHONEINITIALIZEEXPARAMS lpPhoneInitializeExParams
)
{
LONG lResult;
PWSTR szTempPtr = NULL;
if (lpszFriendlyAppName)
{
if (IsBadStringPtrA (lpszFriendlyAppName, (DWORD) -1))
{
LOG((TL_ERROR,
"phoneInitializeExA: bad lpszFriendlyAppName (x%p)",
lpszFriendlyAppName
));
return PHONEERR_INVALPOINTER;
}
szTempPtr = NotSoWideStringToWideString(
lpszFriendlyAppName,
(DWORD) -1
);
}
else
{
szTempPtr = NULL;
}
lResult = phoneInitializeExW(
lphPhoneApp,
hInstance,
lpfnCallback,
szTempPtr,
lpdwNumDevs,
lpdwAPIVersion,
lpPhoneInitializeExParams
);
if (szTempPtr)
{
ClientFree (szTempPtr);
}
return lResult;
}
LONG
WINAPI
phoneNegotiateAPIVersion(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
DWORD dwAPILowVersion,
DWORD dwAPIHighVersion,
LPDWORD lpdwAPIVersion,
LPPHONEEXTENSIONID lpExtensionID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 7, pNegotiateAPIVersion),
{
(ULONG_PTR) hPhoneApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPILowVersion,
(ULONG_PTR) dwAPIHighVersion,
(ULONG_PTR) lpdwAPIVersion,
(ULONG_PTR) lpExtensionID,
(ULONG_PTR) sizeof(PHONEEXTENSIONID)
},
{
hXxxApp,
Dword,
Dword,
Dword,
lpDword,
lpGet_SizeToFollow,
Size
}
};
if (dwAPIHighVersion > TAPI_CURRENT_VERSION)
{
funcArgs.Args[3] = TAPI_CURRENT_VERSION;
}
if ((LPVOID) lpdwAPIVersion == (LPVOID) lpExtensionID)
{
return PHONEERR_INVALPOINTER;
}
return (DOFUNC (&funcArgs, "phoneNegotiateAPIVersion"));
}
LONG
WINAPI
phoneNegotiateExtVersion(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
DWORD dwExtLowVersion,
DWORD dwExtHighVersion,
LPDWORD lpdwExtVersion
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 6, pNegotiateExtVersion),
{
(ULONG_PTR) hPhoneApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtLowVersion,
(ULONG_PTR) dwExtHighVersion,
(ULONG_PTR) lpdwExtVersion
},
{
hXxxApp,
Dword,
Dword,
Dword,
Dword,
lpDword
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return PHONEERR_INCOMPATIBLEAPIVERSION;
}
return (DOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
}
LONG
WINAPI
phoneOpen(
HPHONEAPP hPhoneApp,
DWORD dwDeviceID,
LPHPHONE lphPhone,
DWORD dwAPIVersion,
DWORD dwExtVersion,
DWORD_PTR dwCallbackInstance,
DWORD dwPrivilege
)
{
DWORD hCallbackInstance = 0;
LONG lResult;
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
{
(ULONG_PTR) hPhoneApp,
(ULONG_PTR) dwDeviceID,
(ULONG_PTR) lphPhone,
(ULONG_PTR) dwAPIVersion,
(ULONG_PTR) dwExtVersion,
(ULONG_PTR) dwCallbackInstance,
(ULONG_PTR) dwPrivilege,
(ULONG_PTR) 0, // PHONEOPEN_PARAMS.hRemotePhone
},
{
hXxxApp,
Dword,
lpDword,
Dword,
Dword,
Dword,
Dword,
Dword
}
};
if (dwAPIVersion > TAPI_CURRENT_VERSION)
{
return PHONEERR_INCOMPATIBLEAPIVERSION;
}
if (0 != dwCallbackInstance)
{
hCallbackInstance = NewObject (ghHandleTable, (PVOID)dwCallbackInstance, (PVOID)UIntToPtr(hPhoneApp));
if (0 == hCallbackInstance)
{
return PHONEERR_NOMEM;
}
funcArgs.Args[5] = hCallbackInstance;
}
lResult = DOFUNC (&funcArgs, "phoneOpen");
if (lResult && 0 != hCallbackInstance)
{
DereferenceObject (ghHandleTable, hCallbackInstance, 1);
}
return lResult;
}
LONG
WINAPI
phoneSetButtonInfoW(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO const lpButtonInfo
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetButtonInfo),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwButtonLampID,
(ULONG_PTR) lpButtonInfo
},
{
Dword,
Dword,
lpSet_Struct
}
};
return (DOFUNC (&funcArgs, "phoneSetButtonInfo"));
}
LONG
WINAPI
phoneSetButtonInfoA(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO const lpButtonInfo
)
{
LONG lResult;
LPPHONEBUTTONINFO lppbi;
if (IsBadReadPtr( lpButtonInfo, sizeof(PHONEBUTTONINFO)) ||
IsBadReadPtr( lpButtonInfo, lpButtonInfo->dwTotalSize))
{
LOG((TL_ERROR, "Bad lpButtonInfo - not at least sizeof(PHONEBUTTONINFO)"));
return PHONEERR_INVALPOINTER;
}
//
// See if there's a need to do this, first
//
if ( lpButtonInfo->dwButtonTextSize )
{
DWORD dwNewStringSize,
dwOffset = lpButtonInfo->dwButtonTextOffset,
dwSize = lpButtonInfo->dwButtonTextSize,
dwTotalSize = lpButtonInfo->dwTotalSize;
//
// Check to see if dwButtonTextSize/Offset is valid before
// conversion (check against size of 1.0 PHONEBUTTONINFO here
// (9*DWORD), tapisrv will check again for the appropriate version)
//
if ((dwOffset < (9 * sizeof (DWORD))) ||
(dwOffset >= dwTotalSize) ||
((dwOffset + dwSize) > dwTotalSize) ||
((dwOffset + dwSize) < dwOffset))
{
LOG((TL_ERROR, "phoneSetButtonInfo: dwButtonTextSize/Offset invalid"));
return PHONEERR_OPERATIONFAILED;
}
//
// Assume the worst for size...
//
if (!(lppbi = ClientAlloc (lpButtonInfo->dwTotalSize * sizeof(WCHAR))))
{
return PHONEERR_NOMEM;
}
CopyMemory( lppbi, lpButtonInfo, lpButtonInfo->dwTotalSize );
//
// We _KNOW_ that the old structure was as big as the dwTotalSize
// so we can put our rebuilt string starting there. Make sure
// to align new wide string on WORD boundary.
//
dwNewStringSize = sizeof(WCHAR) * MultiByteToWideChar(
GetACP(),
MB_PRECOMPOSED,
(LPBYTE)lpButtonInfo + lpButtonInfo->dwButtonTextOffset,
lpButtonInfo->dwButtonTextSize,
(PWSTR)((LPBYTE)lppbi + ((dwTotalSize + 1) & 0xfffffffe)),
lpButtonInfo->dwButtonTextSize
);
lppbi->dwTotalSize += dwNewStringSize;
lppbi->dwButtonTextSize = dwNewStringSize;
lppbi->dwButtonTextOffset = (dwTotalSize + 1) & 0xfffffffe;
}
else
{
lppbi = NULL;
}
lResult = phoneSetButtonInfoW(
hPhone,
dwButtonLampID,
lppbi ? lppbi : lpButtonInfo
);
if (lppbi)
{
ClientFree (lppbi);
}
return lResult;
}
LONG
WINAPI
phoneSetButtonInfo(
HPHONE hPhone,
DWORD dwButtonLampID,
LPPHONEBUTTONINFO const lpButtonInfo
)
{
return phoneSetButtonInfoA (hPhone, dwButtonLampID, lpButtonInfo);
}
LONG
WINAPI
phoneSetData(
HPHONE hPhone,
DWORD dwDataID,
LPVOID const lpData,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 4, pSetData),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwDataID,
(ULONG_PTR) lpData,
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "phoneSetData"));
}
LONG
WINAPI
phoneSetDisplay(
HPHONE hPhone,
DWORD dwRow,
DWORD dwColumn,
LPCSTR lpsDisplay,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 5, pSetDisplay),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwRow,
(ULONG_PTR) dwColumn,
(ULONG_PTR) lpsDisplay,
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
Dword,
lpSet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "phoneSetDisplay"));
}
LONG
WINAPI
phoneSetGain(
HPHONE hPhone,
DWORD dwHookSwitchDev,
DWORD dwGain
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetGain),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwHookSwitchDev,
(ULONG_PTR) dwGain
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "phoneSetGain"));
}
LONG
WINAPI
phoneSetHookSwitch(
HPHONE hPhone,
DWORD dwHookSwitchDevs,
DWORD dwHookSwitchMode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetHookSwitch),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwHookSwitchDevs,
(ULONG_PTR) dwHookSwitchMode
},
{
Dword,
Dword,
Dword
}
};
if (!(dwHookSwitchDevs & AllHookSwitchDevs) ||
(dwHookSwitchDevs & (~AllHookSwitchDevs)))
{
return PHONEERR_INVALHOOKSWITCHDEV;
}
if (!IsOnlyOneBitSetInDWORD (dwHookSwitchMode) ||
(dwHookSwitchMode & ~AllHookSwitchModes))
{
return PHONEERR_INVALHOOKSWITCHMODE;
}
return (DOFUNC (&funcArgs, "phoneSetHookSwitch"));
}
LONG
WINAPI
phoneSetLamp(
HPHONE hPhone,
DWORD dwButtonLampID,
DWORD dwLampMode
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetLamp),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwButtonLampID,
(ULONG_PTR) dwLampMode
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "phoneSetLamp"));
}
LONG
WINAPI
phoneSetRing(
HPHONE hPhone,
DWORD dwRingMode,
DWORD dwVolume
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetRing),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwRingMode,
(ULONG_PTR) dwVolume
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "phoneSetRing"));
}
LONG
WINAPI
phoneSetStatusMessages(
HPHONE hPhone,
DWORD dwPhoneStates,
DWORD dwButtonModes,
DWORD dwButtonStates
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | SYNC | 4, pSetStatusMessages),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwPhoneStates,
(ULONG_PTR) dwButtonModes,
(ULONG_PTR) dwButtonStates
},
{
Dword,
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "phoneSetStatusMessages"));
}
LONG
WINAPI
phoneSetVolume(
HPHONE hPhone,
DWORD dwHookSwitchDev,
DWORD dwVolume
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (PHONE_FUNC | ASYNC | 3, pSetVolume),
{
(ULONG_PTR) hPhone,
(ULONG_PTR) dwHookSwitchDev,
(ULONG_PTR) dwVolume
},
{
Dword,
Dword,
Dword
}
};
return (DOFUNC (&funcArgs, "phoneSetVolume"));
}
LONG
WINAPI
phoneShutdown(
HPHONEAPP hPhoneApp
)
{
return (xxxShutdown ((HLINEAPP) hPhoneApp, FALSE));
}
//
// ------------------------------- tapiXxx ------------------------------------
//
LONG
WINAPI
tapiRequestDrop(
HWND hWnd,
WPARAM wRequestID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (TAPI_FUNC | SYNC | 2, tRequestDrop),
{
(ULONG_PTR) hWnd,
(ULONG_PTR) wRequestID
},
{
Hwnd,
Dword
}
};
return (DOFUNC (&funcArgs, "tapiRequestDrop"));
}
LONG
WINAPI
tapiRequestMakeCallW(
LPCWSTR lpszDestAddress,
LPCWSTR lpszAppName,
LPCWSTR lpszCalledParty,
LPCWSTR lpszComment
)
{
LONG lResult;
DWORD hRequestMakeCallAttempted, dwProxyListSize = 512;
LPVARSTRING pProxyList;
FUNC_ARGS funcArgs =
{
MAKELONG (TAPI_FUNC | SYNC | 7, tRequestMakeCall),
{
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) lpszAppName,
(ULONG_PTR) lpszCalledParty,
(ULONG_PTR) lpszComment,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) &hRequestMakeCallAttempted
},
{
lpszW,
lpszW,
lpszW,
lpszW,
lpGet_Struct,
Dword,
lpDword
}
};
if (TAPIIsBadStringPtrW (lpszDestAddress, (DWORD) -1) ||
(lstrlenW (lpszDestAddress) + 1) > TAPIMAXDESTADDRESSSIZE)
{
return TAPIERR_INVALDESTADDRESS;
}
if (!lpszAppName)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[1] = Dword;
funcArgs.Args[1] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpszCalledParty)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[2] = Dword;
funcArgs.Args[2] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpszComment)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[3] = Dword;
funcArgs.Args[3] = (ULONG_PTR) TAPI_NO_DATA;
}
//
//
//
if (!(pProxyList = ClientAlloc (dwProxyListSize)))
{
return TAPIERR_NOREQUESTRECIPIENT;
}
pProxyList->dwTotalSize = dwProxyListSize;
funcArgs.Args[4] = (ULONG_PTR) pProxyList;
if ((lResult = DOFUNC (&funcArgs, "tapiRequestMakeCall")) == 0)
{
//
//
//
if (hRequestMakeCallAttempted != 0)
{
WCHAR *pszProxyName, *pszNextProxyName;
BOOL bLastAppInList = FALSE, bStartedProxy = FALSE;
pszProxyName =
pszNextProxyName =
(WCHAR *)(((LPBYTE) pProxyList) + pProxyList->dwStringOffset);
while (!bLastAppInList)
{
while (1)
{
if (*pszNextProxyName == 0)
{
bLastAppInList = TRUE;
break;
}
else if (*pszNextProxyName == L'"')
{
*pszNextProxyName = 0;
pszNextProxyName++;
break;
}
pszNextProxyName++;
}
//
// Fake layer to get a local struct
//
{
FARPROC pShellExecuteEx = NULL;
HINSTANCE hInst;
LPTSTR pszBuffer;
DWORD dwSize = lstrlenW(pszProxyName)+1;
SHELLEXECUTEINFO sei =
{
sizeof(SHELLEXECUTEINFO),
0,
0, // hWnd
NULL, //"Open"
NULL, // lpFile
NULL,
NULL, //Directory
SW_MINIMIZE,
NULL //hProcess - huh?
};
pszBuffer = (LPTSTR)ClientAlloc(dwSize*sizeof(TCHAR));
SHUnicodeToTChar(pszProxyName, pszBuffer, dwSize );
sei.lpFile = pszBuffer;
hInst = LoadLibrary( TEXT("shell32.dll") );
if (NULL != hInst)
{
pShellExecuteEx = GetProcAddress(
hInst,
#ifdef UNICODE
"ShellExecuteExW"
#else
"ShellExecuteEx"
#endif
);
if (pShellExecuteEx && pShellExecuteEx(&sei) == TRUE)
{
bStartedProxy = TRUE;
ClientFree(pszBuffer);
break;
}
else
#if DBG
{
LOG((TL_ERROR,
"tapiRequestMakeCall: ShellExecuteExW(%ls) error - x%x",
pszProxyName,
GetLastError()
));
}
#else
LOG((TL_ERROR,
"tapiRequestMakeCall: ShellExecuteExW error - x%x",
GetLastError()
));
#endif
ClientFree(pszBuffer);
FreeLibrary( hInst );
}
else
{
LOG((TL_ERROR,
"tapiRequestMakeCall: LoadLibrary(shell32.dll) failed - x%x",
GetLastError()
));
}
}
pszProxyName = pszNextProxyName;
}
if (bStartedProxy == FALSE)
{
//
// Alert tapisrv that it needs to free the ReqMakeCall inst
//
FUNC_ARGS funcArgs =
{
MAKELONG (TAPI_FUNC | SYNC | 7, tRequestMakeCall),
{
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) 0,
(ULONG_PTR) hRequestMakeCallAttempted,
(ULONG_PTR) 0
},
{
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
Dword,
}
};
LOG((TL_ERROR,
"tapiRequestMakeCall: failed to start proxy, deleting request"
));
lResult = DOFUNC (&funcArgs, "tapiRequestMakeCall_cleanup");
}
}
}
ClientFree (pProxyList);
return lResult;
}
LONG
WINAPI
tapiRequestMakeCallA(
LPCSTR lpszDestAddress,
LPCSTR lpszAppName,
LPCSTR lpszCalledParty,
LPCSTR lpszComment
)
{
LONG lResult;
PWSTR szTempPtr1;
PWSTR szTempPtr2;
PWSTR szTempPtr3;
PWSTR szTempPtr4;
if (IsBadStringPtrA (lpszDestAddress, (DWORD) -1) ||
(lstrlenA (lpszDestAddress) + 1) > TAPIMAXDESTADDRESSSIZE)
{
return TAPIERR_INVALDESTADDRESS;
}
if ((lpszAppName && IsBadStringPtrA (lpszAppName, (DWORD) -1)) ||
(lpszCalledParty && IsBadStringPtrA (lpszCalledParty, (DWORD) -1)) ||
(lpszComment && IsBadStringPtrA (lpszComment, (DWORD) -1)))
{
return TAPIERR_INVALPOINTER;
}
szTempPtr1= NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
if ( !szTempPtr1 )
{
return TAPIERR_INVALPOINTER;
}
szTempPtr2= NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
szTempPtr3= NotSoWideStringToWideString (lpszCalledParty, (DWORD) -1);
szTempPtr4= NotSoWideStringToWideString (lpszComment, (DWORD) -1);
lResult = tapiRequestMakeCallW(
szTempPtr1,
szTempPtr2,
szTempPtr3,
szTempPtr4
);
ClientFree (szTempPtr1);
if (szTempPtr2)
{
ClientFree (szTempPtr2);
}
if (szTempPtr3)
{
ClientFree (szTempPtr3);
}
if (szTempPtr4)
{
ClientFree (szTempPtr4);
}
return lResult;
}
LONG
WINAPI
tapiRequestMakeCall(
LPCSTR lpszDestAddress,
LPCSTR lpszAppName,
LPCSTR lpszCalledParty,
LPCSTR lpszComment
)
{
return tapiRequestMakeCallA(
lpszDestAddress,
lpszAppName,
lpszCalledParty,
lpszComment
);
}
LONG
WINAPI
tapiRequestMediaCallW(
HWND hWnd,
WPARAM wRequestID,
LPCWSTR lpszDeviceClass,
LPCWSTR lpDeviceID,
DWORD dwSize,
DWORD dwSecure,
LPCWSTR lpszDestAddress,
LPCWSTR lpszAppName,
LPCWSTR lpszCalledParty,
LPCWSTR lpszComment
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (TAPI_FUNC | SYNC | 10, tRequestMediaCall),
{
(ULONG_PTR) hWnd,
(ULONG_PTR) wRequestID,
(ULONG_PTR) lpszDeviceClass,
(ULONG_PTR) lpDeviceID,
(ULONG_PTR) dwSize,
(ULONG_PTR) dwSecure,
(ULONG_PTR) lpszDestAddress,
(ULONG_PTR) lpszAppName,
(ULONG_PTR) lpszCalledParty,
(ULONG_PTR) lpszComment,
},
{
Hwnd,
Dword,
lpszW,
lpGet_SizeToFollow,
Size,
Dword,
lpszW,
lpszW,
lpszW,
lpszW
}
};
if (TAPIIsBadStringPtrW (lpszDeviceClass, (UINT) -1) ||
(lstrlenW (lpszDeviceClass) + 1) > TAPIMAXDEVICECLASSSIZE)
{
return TAPIERR_INVALDEVICECLASS;
}
if (IsBadWritePtr ((LPVOID) lpDeviceID, dwSize) ||
dwSize > (TAPIMAXDEVICEIDSIZE * sizeof (WCHAR)))
{
return TAPIERR_INVALDEVICEID;
}
if (TAPIIsBadStringPtrW (lpszDestAddress, (UINT) -1) ||
(lstrlenW (lpszDestAddress) + 1) > TAPIMAXDESTADDRESSSIZE)
{
return TAPIERR_INVALDESTADDRESS;
}
if (!lpszAppName)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[7] = Dword;
funcArgs.Args[7] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpszCalledParty)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[8] = Dword;
funcArgs.Args[8] = (ULONG_PTR) TAPI_NO_DATA;
}
if (!lpszComment)
{
//
// Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
//
funcArgs.ArgTypes[9] = Dword;
funcArgs.Args[9] = (ULONG_PTR) TAPI_NO_DATA;
}
return (DOFUNC (&funcArgs, "tapiRequestMediaCall"));
}
LONG
WINAPI
tapiRequestMediaCallA(
HWND hWnd,
WPARAM wRequestID,
LPCSTR lpszDeviceClass,
LPCSTR lpDeviceID,
DWORD dwSize,
DWORD dwSecure,
LPCSTR lpszDestAddress,
LPCSTR lpszAppName,
LPCSTR lpszCalledParty,
LPCSTR lpszComment
)
{
LONG lResult;
PWSTR szTempPtr1 = NULL, szTempPtr2 = NULL, szTempPtr3 = NULL,
szTempPtr4 = NULL, szTempPtr5 = NULL, szTempPtr6 = NULL;
if (IsBadStringPtrA (lpszDeviceClass, (UINT) -1) ||
(lstrlenA (lpszDeviceClass) + 1) > TAPIMAXDEVICECLASSSIZE)
{
lResult = TAPIERR_INVALDEVICECLASS;
goto ExitHere;
}
else
{
szTempPtr1 = NotSoWideStringToWideString(
lpszDeviceClass,
(DWORD) -1
);
}
if (IsBadWritePtr ((LPVOID) lpDeviceID, dwSize) ||
dwSize > TAPIMAXDEVICEIDSIZE)
{
lResult = TAPIERR_INVALDEVICEID;
goto ExitHere;
}
else
{
dwSize *= 2;
szTempPtr2 = ClientAlloc (dwSize);
}
if (IsBadStringPtrA (lpszDestAddress, (UINT) -1) ||
(lstrlenA (lpszDestAddress) + 1) > TAPIMAXDESTADDRESSSIZE)
{
lResult = TAPIERR_INVALDESTADDRESS;
goto ExitHere;
}
else
{
szTempPtr3 = NotSoWideStringToWideString(
lpszDestAddress,
(DWORD) -1
);
}
if ((lpszAppName && IsBadStringPtrA (lpszAppName, (UINT) -1)) ||
(lpszCalledParty && IsBadStringPtrA (lpszCalledParty, (UINT) -1)) ||
(lpszComment && IsBadStringPtrA (lpszComment, (UINT) -1)))
{
lResult = TAPIERR_INVALPOINTER;
goto ExitHere;
}
szTempPtr4 = NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
szTempPtr5 = NotSoWideStringToWideString (lpszCalledParty, (DWORD) -1);
szTempPtr6 = NotSoWideStringToWideString (lpszComment, (DWORD) -1);
lResult = tapiRequestMediaCallW(
hWnd,
wRequestID,
szTempPtr1,
szTempPtr2,
dwSize,
dwSecure,
szTempPtr3,
szTempPtr4,
szTempPtr5,
szTempPtr6
);
ExitHere:
if (szTempPtr1)
{
ClientFree (szTempPtr1);
}
if (szTempPtr2)
{
ClientFree (szTempPtr2);
}
if (szTempPtr3)
{
ClientFree (szTempPtr3);
}
if (szTempPtr4)
{
ClientFree (szTempPtr4);
}
if (szTempPtr5)
{
ClientFree (szTempPtr5);
}
if (szTempPtr6)
{
ClientFree (szTempPtr6);
}
return lResult;
}
LONG
WINAPI
tapiRequestMediaCall(
HWND hWnd,
WPARAM wRequestID,
LPCSTR lpszDeviceClass,
LPCSTR lpDeviceID,
DWORD dwSize,
DWORD dwSecure,
LPCSTR lpszDestAddress,
LPCSTR lpszAppName,
LPCSTR lpszCalledParty,
LPCSTR lpszComment
)
{
return tapiRequestMediaCallA(
hWnd,
wRequestID,
lpszDeviceClass,
lpDeviceID,
dwSize,
dwSecure,
lpszDestAddress,
lpszAppName,
lpszCalledParty,
lpszComment
);
}
//
// ----------------------------------------------------------------------------
//
LONG
WINAPI
GetTapi16CallbackMsg(
PINIT_DATA pInitData,
LPDWORD pMsg
)
{
LONG lResult = 0;
LOG((TL_TRACE, "GetTapi16CallbackMsg: enter"));
EnterCriticalSection (&gCriticalSection);
try
{
if (pInitData->dwKey != INITDATA_KEY)
{
goto GetTapi16CallbackMsg_leaveCritSec;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
goto GetTapi16CallbackMsg_leaveCritSec;
}
if (pInitData->dwNumUsedEntries > 0)
{
CopyMemory(
pMsg,
pInitData->pValidEntry,
sizeof(ASYNC_EVENT_PARAMS)
);
pInitData->pValidEntry++;
if (pInitData->pValidEntry >= (pInitData->pEventBuffer +
pInitData->dwNumTotalEntries))
{
pInitData->pValidEntry = pInitData->pEventBuffer;
}
pInitData->dwNumUsedEntries--;
if (pInitData->dwNumUsedEntries == 0)
{
pInitData->bPendingAsyncEventMsg = FALSE;
}
lResult = 1;
}
GetTapi16CallbackMsg_leaveCritSec:
LeaveCriticalSection (&gCriticalSection);
LOG((TL_TRACE, "GetTapi16CallbackMsg: exit (result=x%x)", lResult));
return lResult;
}
//
// ----------------------- Private support routines ---------------------------
//
void
FreeInitData(
PINIT_DATA pInitData
)
{
EnterCriticalSection (&gCriticalSection);
if (pInitData && ( pInitData->dwKey != 0xefefefef ) )
{
pInitData->dwKey = 0xefefefef;
LeaveCriticalSection (&gCriticalSection);
if ((pInitData->dwInitOptions & 0x3) ==
LINEINITIALIZEEXOPTION_USEEVENT)
{
if (pInitData->hEvent)
{
//
// Signal the event to release any threads which might
// be waiting on it, then close the handle
//
SetEvent (pInitData->hEvent);
CloseHandle (pInitData->hEvent);
}
}
else if ((pInitData->dwInitOptions & 0x3) ==
LINEINITIALIZEEXOPTION_USEHIDDENWINDOW)
{
// NOTE: let thunk destroy it's own window
if (pInitData->hwnd && !gbNTVDMClient)
{
//
// If this is the thread which created the window
// then we can destroy the window in line. Otherwise,
// post a message telling the window to destroy itself.
//
if (pInitData->dwThreadID == GetCurrentThreadId())
{
DestroyWindow (pInitData->hwnd);
}
else
{
PostMessage(
pInitData->hwnd,
WM_ASYNCEVENT,
(WPARAM) gdwInitialTickCount,
(LPARAM) 0xffffffff
);
}
}
}
if (pInitData->pEventBuffer)
{
ClientFree (pInitData->pEventBuffer);
}
DereferenceObject (ghHandleTable, pInitData->hInitData, 1);
ClientFree (pInitData);
}
else
{
LeaveCriticalSection (&gCriticalSection);
}
}
INT_PTR
CALLBACK
TAPIWndProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
switch (msg)
{
case WM_ASYNCEVENT:
{
BOOL bFirstPass = TRUE, bPostMsg = FALSE;
PINIT_DATA pInitData = (PINIT_DATA) lParam;
LOG((TL_TRACE, "TAPIWndProc: received WM_ASYNCEVENT, hwnd=x%p", hwnd));
if (lParam == (LPARAM) 0xffffffff)
{
if (wParam == (WPARAM) gdwInitialTickCount)
{
DestroyWindow (hwnd);
}
return FALSE;
}
while (1)
{
//
// Enter the critical section, verify the pInitData, and
// see if there are any events in in the queue to process.
// If so, remove an event from the queue, adjust the
// ptrs & count, leave the critical section, and call
// the callback.
//
// Note that there is some tricky stuff below to insure
// that there is always another outstanding WM_ASYNCEVENT
// msg prior to calling the app's callback (if there are)
// any more events inthe queue. This is necessary because
// some ill-behaved apps have msg loops (to synchronously
// wait for async request results, etc) within their
// callbacks, and we don't want to block sending any msgs
// to them.
//
EnterCriticalSection (&gCriticalSection);
try
{
if (pInitData->dwKey != INITDATA_KEY)
{
LOG((TL_ERROR, "TAPIWndProc: bad pInitInst (x%p)", pInitData));
LeaveCriticalSection (&gCriticalSection);
break;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
LOG((TL_ERROR, "TAPIWndProc: bad pInitInst (x%p)", pInitData));
LeaveCriticalSection (&gCriticalSection);
break;
}
if (bFirstPass)
{
pInitData->bPendingAsyncEventMsg = FALSE;
bFirstPass = FALSE;
}
if (pInitData->dwNumUsedEntries != 0)
{
ASYNC_EVENT_PARAMS event;
LINECALLBACK lpfnCallback;
CopyMemory(
&event,
pInitData->pValidEntry,
sizeof (ASYNC_EVENT_PARAMS)
);
pInitData->pValidEntry++;
if (pInitData->pValidEntry >= (pInitData->pEventBuffer +
pInitData->dwNumTotalEntries))
{
pInitData->pValidEntry = pInitData->pEventBuffer;
}
pInitData->dwNumUsedEntries--;
if (pInitData->dwNumUsedEntries != 0 &&
pInitData->bPendingAsyncEventMsg == FALSE)
{
bPostMsg = TRUE;
pInitData->bPendingAsyncEventMsg = TRUE;
}
lpfnCallback = pInitData->lpfnCallback;
LeaveCriticalSection (&gCriticalSection);
LOG((TL_INFO,
"Calling app's callback, hDev=x%x, "\
"Msg=%d, dwInst=x%lx P1=x%lx, P2=x%x P3=x%lx",
event.hDevice,
event.dwMsg,
event.dwCallbackInstance,
event.dwParam1,
event.dwParam2,
event.dwParam3
));
if (bPostMsg)
{
PostMessage (hwnd, WM_ASYNCEVENT, wParam, lParam);
}
(*lpfnCallback)(
event.hDevice,
event.dwMsg,
event.dwCallbackInstance,
event.dwParam1,
event.dwParam2,
event.dwParam3
);
}
else
{
LOG((TL_TRACE, "No entries - spurious entry."));
LeaveCriticalSection (&gCriticalSection);
break;
}
}
return FALSE;
}
default:
break;
}
return (DefWindowProc (hwnd, msg, wParam, lParam));
}
LONG
CreateHiddenWindow(
HWND *lphwnd,
DWORD dwErrorClass
)
{
LONG lResult = 0;
//
// Register the hidden window class
//
if (!gbHiddenWndClassRegistered)
{
DWORD dwError;
WNDCLASS wndclass;
ZeroMemory(&wndclass, sizeof(WNDCLASS));
wndclass.lpfnWndProc = TAPIWndProc;
wndclass.hInstance = g_hInst;
wndclass.lpszClassName = szTapi32WndClass;
if (!RegisterClass (&wndclass) &&
((dwError = GetLastError()) != ERROR_CLASS_ALREADY_EXISTS))
{
LOG((TL_ERROR,
"CreateHiddenWindow: RegisterClass failed, err=%d",
dwError
));
}
else
{
gbHiddenWndClassRegistered = TRUE;
}
}
if (!(*lphwnd = CreateWindow(
szTapi32WndClass, // class name
NULL, // title
WS_OVERLAPPED | WS_MINIMIZE, // 0, // dwStyle
0, // x
0, // y
0, // width
0, // height
(HWND) NULL, // parent wnd
(HMENU) NULL, // menu
g_hInst, // instance
NULL // params
)))
{
LOG((TL_ERROR, "CreateWindow failed, err=%ld", GetLastError()));
lResult = gaOpFailedErrors[dwErrorClass];
}
return lResult;
}
void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
{
LOG((TL_TRACE, "midl_user_allocate: enter, size=x%x", len));
return (ClientAlloc (len));
}
void __RPC_API midl_user_free(void __RPC_FAR * ptr)
{
LOG((TL_TRACE, "midl_user_free: enter, p=x%p", ptr));
ClientFree (ptr);
}
LONG
WINAPI
ReAllocClientResources(
DWORD dwErrorClass
)
{
LONG lResult;
DWORD dwRefCountTemp;
LOG((TL_TRACE, "AllocClientResources: enter"));
WaitForSingleObject (ghInitMutex, INFINITE);
if (0 == gdwRpcRefCount)
{
ReleaseMutex (ghInitMutex);
return TAPIERR_REQUESTFAILED;
}
dwRefCountTemp = gdwRpcRefCount;
gdwRpcRefCount = 1;
FreeClientResources ();
lResult = AllocClientResources(dwErrorClass);
if (TAPI_SUCCESS == lResult)
{
gdwRpcRefCount = dwRefCountTemp;
}
else
{
gdwRpcRefCount = 0;
}
ReleaseMutex (ghInitMutex);
return lResult;
}
LONG
WINAPI
AllocClientResources(
DWORD dwErrorClass
)
{
DWORD dwExceptionCount = 0;
DWORD dwError = 0;
LONG lResult = gaOpFailedErrors[dwErrorClass];
SC_HANDLE hSCMgr = NULL, hTapiSrv = NULL;
OSVERSIONINFOEX OsVersionEx = { 0 };
BOOL bSbsSku = FALSE;
LOG((TL_TRACE, "AllocClientResources: enter"));
// See if we're running on
if ((GetVersionEx ((LPOSVERSIONINFO) &OsVersionEx)) &&
(OsVersionEx.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
{
bSbsSku = TRUE;
}
//
// If we're in safeboot mode, tapisrv won't start;
// fail initialization. Don't do this check if we're running on SBS.
//
if (!bSbsSku &&
(0 != GetSystemMetrics (SM_CLEANBOOT)))
{
lResult = gaOpFailedErrors[dwErrorClass];
goto AllocClientResources_return;
}
//
// Serialize the following init code
//
WaitForSingleObject (ghInitMutex, INFINITE);
if (0 != gdwRpcRefCount)
{
gdwRpcRefCount++;
lResult = TAPI_SUCCESS;
goto AllocClientResources_return;
}
//
// Start the TAPISRV.EXE service
//
if ((hSCMgr = OpenSCManager(
NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_CONNECT // desired access
)) == NULL)
{
dwError = GetLastError();
LOG((TL_ERROR, "OpenSCManager failed, err=%d", dwError ));
if ( ERROR_ACCESS_DENIED == dwError ||
ERROR_NOACCESS == dwError
)
{
// if OpenSCManager fails with ACCESS_DENIED,
// we still need to try to attach to TAPISRV
goto AllocClientResources_attachToServer;
}
else
{
goto AllocClientResources_return;
}
}
if ((hTapiSrv = OpenService(
hSCMgr, // SC mgr handle
TEXT("TAPISRV"), // name of service to open
SERVICE_START | // desired access
SERVICE_QUERY_STATUS
)) == NULL)
{
dwError = GetLastError();
LOG((TL_ERROR, "OpenService failed, err=%d", dwError));
if ( ERROR_ACCESS_DENIED == dwError ||
ERROR_NOACCESS == dwError
)
{
// if OpenService fails with ACCESS_DENIED,
// we still need to try to attach to TAPISRV
goto AllocClientResources_attachToServer;
}
else
{
goto AllocClientResources_cleanup1;
}
}
AllocClientResources_queryServiceStatus:
{
#define MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV 180
DWORD dwNumSecondsSleptStartPending = 0,
dwNumSecondsSleptStopPending = 0;
while (1)
{
SERVICE_STATUS status;
QueryServiceStatus (hTapiSrv, &status);
switch (status.dwCurrentState)
{
case SERVICE_RUNNING:
LOG((TL_INFO, "Tapisrv running"));
goto AllocClientResources_attachToServer;
case SERVICE_START_PENDING:
Sleep (1000);
if (++dwNumSecondsSleptStartPending >
MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
{
LOG((TL_ERROR,
"ERROR: Tapisrv stuck SERVICE_START_PENDING"
));
goto AllocClientResources_cleanup2;
}
break;
case SERVICE_STOP_PENDING:
Sleep (1000);
if (++dwNumSecondsSleptStopPending >
MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
{
LOG((TL_ERROR,
"ERROR: Tapisrv stuck SERVICE_STOP_PENDING"
));
goto AllocClientResources_cleanup2;
}
break;
case SERVICE_STOPPED:
LOG((TL_TRACE, "Starting tapisrv (NT)..."));
if (!StartService(
hTapiSrv, // service handle
0, // num args
NULL // args
))
{
DWORD dwLastError = GetLastError();
if (dwLastError != ERROR_SERVICE_ALREADY_RUNNING)
{
LOG((TL_ERROR,
"StartService(TapiSrv) failed, err=%d",
dwLastError
));
goto AllocClientResources_cleanup2;
}
}
break;
default:
LOG((TL_ERROR,
"error, service status=%d",
status.dwCurrentState
));
goto AllocClientResources_cleanup2;
}
}
}
//
// Init the RPC connection
//
AllocClientResources_attachToServer:
{
#define CNLEN 25 // computer name length
#define UNCLEN CNLEN+2 // \\computername
#define PATHLEN 260 // Path
#define MAXPROTSEQ 20 // protocol sequence "ncacn_np"
BOOL bException = FALSE;
RPC_STATUS status;
TCHAR pszNetworkAddress[UNCLEN+1];
LPTSTR pszUuid = NULL;
LPTSTR pszOptions = NULL;
LPTSTR pszStringBinding = NULL;
LPTSTR pszBuffer;
DWORD dwProcessID = GetCurrentProcessId(), dwSize = 256;
WCHAR *pszUserName = ClientAlloc (dwSize * sizeof(WCHAR) );
WCHAR *pszComputerName = ClientAlloc(
(MAX_COMPUTERNAME_LENGTH+1) * sizeof(WCHAR)
);
pszNetworkAddress[0] = TEXT('\0');
status = RpcStringBindingCompose(
pszUuid,
TEXT("ncalrpc"),
pszNetworkAddress,
TEXT("tapsrvlpc"),
pszOptions,
&pszStringBinding
);
if (status)
{
LOG((TL_ERROR,
"RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
status,
pszNetworkAddress
));
lResult = gaOpFailedErrors[dwErrorClass];
ClientFree (pszUserName);
ClientFree (pszComputerName);
goto AllocClientResources_cleanup2;
}
status = RpcBindingFromStringBinding(
pszStringBinding,
&hTapSrv
);
if (status)
{
LOG((TL_ERROR,
"RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
status,
pszStringBinding
));
lResult = gaOpFailedErrors[dwErrorClass];
RpcStringFree(&pszStringBinding);
ClientFree (pszUserName);
ClientFree (pszComputerName);
goto AllocClientResources_cleanup2;
}
pszBuffer = (LPTSTR)ClientAlloc( (dwSize>(MAX_COMPUTERNAME_LENGTH+1)?dwSize:(MAX_COMPUTERNAME_LENGTH+1) ) * sizeof(TCHAR));
if ( NULL == pszBuffer )
{
LOG((TL_ERROR, "Mem alloc of 0x%lx bytes failed(ca1)", dwSize ));
lResult = gaOpFailedErrors[dwErrorClass];
RpcStringFree(&pszStringBinding);
ClientFree (pszUserName);
ClientFree (pszComputerName);
goto AllocClientResources_cleanup2;
}
GetUserName(pszBuffer, &dwSize);
SHTCharToUnicode(pszBuffer, pszUserName, 256);
dwSize = (MAX_COMPUTERNAME_LENGTH+1);
GetComputerName( pszBuffer, &dwSize );
SHTCharToUnicode(pszBuffer, pszComputerName, MAX_COMPUTERNAME_LENGTH+1);
ClientFree(pszBuffer);
RpcTryExcept
{
LOG((TL_TRACE, "AllocCliRes: calling ClientAttach..."));
lResult = ClientAttach(
(PCONTEXT_HANDLE_TYPE *) &gphCx,
dwProcessID,
(long *) &ghAsyncEventsEvent,
pszUserName,
pszComputerName
);
LOG((TL_TRACE, "AllocCliRes: ClientAttach returned x%x", lResult));
}
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
{
LOG((TL_ERROR,
"AllocCliRes: ClientAttach caused except=%d",
RpcExceptionCode()
));
bException = TRUE;
}
RpcEndExcept
ClientFree (pszUserName);
ClientFree (pszComputerName);
RpcBindingFree (&hTapSrv);
RpcStringFree(&pszStringBinding);
if (bException)
{
//
// Make sure we don't leak the handle duplicated in ClientAttach
//
if (ghAsyncEventsEvent)
{
CloseHandle (ghAsyncEventsEvent);
ghAsyncEventsEvent = NULL;
}
//
// If here chances are that we started the service and it's
// not ready to receive rpc requests. So we'll give it a
// little time to get rolling and then try again.
//
if (dwExceptionCount < gdwMaxNumRequestRetries)
{
Sleep ((++dwExceptionCount > 1 ? gdwRequestRetryTimeout : 0));
if (hTapiSrv) // Win NT && successful OpenService()
{
goto AllocClientResources_queryServiceStatus;
}
else
{
goto AllocClientResources_attachToServer;
}
}
else
{
LOG((TL_ERROR,
"AllocCliRes: ClientAttach failed, result=x%x",
gaServiceNotRunningErrors[dwErrorClass]
));
lResult = gaServiceNotRunningErrors[dwErrorClass];
}
}
}
if (lResult == 0)
{
gdwRpcRefCount++;
}
AllocClientResources_cleanup2:
if (hTapiSrv)
{
CloseServiceHandle (hTapiSrv);
}
AllocClientResources_cleanup1:
if (hSCMgr)
{
CloseServiceHandle (hSCMgr);
}
AllocClientResources_return:
ReleaseMutex (ghInitMutex);
LOG((TL_TRACE, "AllocClientResources: exit, returning x%x", lResult));
return lResult;
}
LONG
PASCAL
xxxShutdown(
HLINEAPP hXXXApp,
BOOL bLineShutdown
)
{
//NOTE NOTE NOTE NOTE NOTE NOTE
//NOTE NOTE NOTE NOTE NOTE NOTE
// There is "identical" code in lineShutdownInt - if this changes that should
// probably change as well!!!!!
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, (bLineShutdown ? lShutdown:pShutdown)),
{
(ULONG_PTR) hXXXApp
},
{
hXxxApp
}
};
LONG lResult;
WaitForSingleObject (ghInitMutex, INFINITE);
lResult = DOFUNC(
&funcArgs,
(bLineShutdown ? "lineShutdown" : "phoneShutdown")
);
if (lResult == 0)
{
PINIT_DATA pInitData;
ReleaseAllHandles (ghHandleTable, (PVOID)UIntToPtr(hXXXApp));
if ((pInitData = ReferenceObject (ghHandleTable, hXXXApp, 0)))
{
DereferenceObject (ghHandleTable, hXXXApp, 1);
FreeInitData (pInitData);
}
EnterCriticalSection (&gCriticalSection);
gdwNumInits--;
if (gdwNumInits == 0)
{
//
// Tell the async events thread to quit
//
gpAsyncEventsThreadParams->bExitThread = TRUE;
SetEvent (ghAsyncEventsEvent);
gpAsyncEventsThreadParams = NULL;
//
// Safely close any existing generic dialog instances
//
if (gpUIThreadInstances)
{
PUITHREADDATA pUIThreadData, pNextUIThreadData;
pUIThreadData = gpUIThreadInstances;
while (pUIThreadData)
{
//
// Grab a ptr to the next UIThreadData while it's still
// safe, wait until the ui dll has indicated that it
// is will to receive generic dlg data, then pass it
// NULL/0 to tell it to shutdown the dlg inst
//
pNextUIThreadData = pUIThreadData->pNext;
WaitForSingleObject (pUIThreadData->hEvent, INFINITE);
LOG((TL_TRACE,
"xxxShutdown: calling " \
"TUISPI_providerGenericDialogData..."
));
(*pUIThreadData->pfnTUISPI_providerGenericDialogData)(
pUIThreadData->htDlgInst,
NULL,
0
);
LOG((TL_TRACE,
"xxxShutdown: " \
"TUISPI_providerGenericDialogData returned"
));
pUIThreadData = pNextUIThreadData;
}
}
//
// Free up any other resources we were using
//
if (ghWow32Dll)
{
FreeLibrary (ghWow32Dll);
ghWow32Dll = NULL;
}
// Disable tracing after last line shutdown
TRACELOGDEREGISTER();
}
LeaveCriticalSection (&gCriticalSection);
//
// Remove the RPC ref count added in lineInitialize
//
FreeClientResources();
}
ReleaseMutex (ghInitMutex);
return lResult;
}
LONG
PASCAL
xxxGetMessage(
BOOL bLine,
HLINEAPP hXxxApp,
LPLINEMESSAGE pMsg,
DWORD dwTimeout
)
{
LONG lResult;
BOOL bInCriticalSection = FALSE;
PINIT_DATA pInitData;
if (IsBadWritePtr (pMsg, sizeof (LINEMESSAGE)))
{
lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
goto xxxGetMessage_return2;
}
if (!(pInitData = (PINIT_DATA) ReferenceObject(
ghHandleTable,
hXxxApp,
INITDATA_KEY
)))
{
LOG((TL_ERROR, "xxxGetMessage: hXxxApp=x%x invalid", hXxxApp));
lResult = (bLine ? LINEERR_INVALAPPHANDLE :
PHONEERR_INVALAPPHANDLE);
goto xxxGetMessage_return2;
}
try
{
if ((pInitData->dwInitOptions & 0x3) !=
LINEINITIALIZEEXOPTION_USEEVENT)
{
LOG((TL_ERROR,
"GetMessage: This app did not call initex with _USEEVENT"
));
lResult = (bLine ? LINEERR_INVALAPPHANDLE :
PHONEERR_INVALAPPHANDLE);
goto xxxGetMessage_return;
}
if (pInitData->dwNumUsedEntries)
{
EnterCriticalSection (&gCriticalSection);
bInCriticalSection = TRUE;
if (pInitData->dwKey == INITDATA_KEY)
{
if (pInitData->dwNumUsedEntries)
{
CopyMemory(
pMsg,
pInitData->pValidEntry,
sizeof (ASYNC_EVENT_PARAMS)
);
pInitData->pValidEntry++;
if (pInitData->pValidEntry >= (pInitData->pEventBuffer +
pInitData->dwNumTotalEntries))
{
pInitData->pValidEntry = pInitData->pEventBuffer;
}
pInitData->dwNumUsedEntries--;
//
// If the buffer is empty then reset the event
// to nonsignaled
//
if (pInitData->dwNumUsedEntries == 0)
{
ResetEvent (pInitData->hEvent);
}
lResult = 0;
}
else
{
lResult = (bLine ? LINEERR_OPERATIONFAILED :
PHONEERR_OPERATIONFAILED);
}
}
else
{
LOG((TL_ERROR, "GetMessage: bad key2"));
lResult = (bLine ? LINEERR_INVALAPPHANDLE :
PHONEERR_INVALAPPHANDLE);
}
LeaveCriticalSection (&gCriticalSection);
bInCriticalSection = FALSE;
}
else
{
lResult = (bLine ? LINEERR_OPERATIONFAILED :
PHONEERR_OPERATIONFAILED);
}
if (dwTimeout != 0 && lResult != 0)
{
xxxGetMessage_wait:
switch (WaitForSingleObject (pInitData->hEvent, dwTimeout))
{
case WAIT_OBJECT_0:
EnterCriticalSection (&gCriticalSection);
bInCriticalSection = TRUE;
if (pInitData->dwKey == INITDATA_KEY)
{
if (pInitData->dwNumUsedEntries)
{
CopyMemory(
pMsg,
pInitData->pValidEntry,
sizeof (ASYNC_EVENT_PARAMS)
);
pInitData->pValidEntry++;
if (pInitData->pValidEntry >= (pInitData->pEventBuffer+
pInitData->dwNumTotalEntries))
{
pInitData->pValidEntry = pInitData->pEventBuffer;
}
pInitData->dwNumUsedEntries--;
//
// If the buffer is empty then reset the event
// to nonsignaled
//
if (pInitData->dwNumUsedEntries == 0)
{
ResetEvent (pInitData->hEvent);
}
//
// Everything looks good, now.
//
lResult = 0;
}
else if (dwTimeout == INFINITE)
{
LeaveCriticalSection (&gCriticalSection);
bInCriticalSection = FALSE;
goto xxxGetMessage_wait;
}
}
else
{
LOG((TL_ERROR, "GetMessage: bad key1"));
lResult = (bLine ? LINEERR_INVALAPPHANDLE :
PHONEERR_INVALAPPHANDLE);
}
LeaveCriticalSection (&gCriticalSection);
bInCriticalSection = FALSE;
break;
case WAIT_TIMEOUT:
default:
lResult = (bLine ? LINEERR_OPERATIONFAILED :
PHONEERR_OPERATIONFAILED);
}
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
LOG((TL_ERROR, "GetMessage: exception"));
if (bInCriticalSection)
{
LeaveCriticalSection (&gCriticalSection);
}
lResult = (bLine ? LINEERR_INVALAPPHANDLE : PHONEERR_INVALAPPHANDLE);
}
xxxGetMessage_return:
DereferenceObject (ghHandleTable, hXxxApp, 1);
xxxGetMessage_return2:
{
char szResult[32],
*pszFuncName = (bLine ? "lineGetMessage" : "phoneGetMessage");
#if DBG
if (lResult == 0)
{
LOG((TL_TRACE,
"%hs: exit, returning msg=%hs\n" \
"\thDev=x%01lx, ctx=x%01lx, p1=x%01lx, " \
"p2=x%01lx, p3=x%01lx",
pszFuncName,
aszMsgs[pMsg->dwMessageID],
(DWORD)pMsg->hDevice,
pMsg->dwCallbackInstance,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
));
}
else
{
LOG((TL_TRACE,
"%hs: exit, result=%hs",
pszFuncName,
MapResultCodeToText (lResult, szResult)
));
}
#else
if (lResult == 0)
{
LOG((TL_TRACE,
"%hs: exit, returning msgID=x%x\n" \
"\thDev=x%01lx, ctx=x%01lx, p1=x%01lx, " \
"p2=x%01lx, p3=x%01lx",
pszFuncName,
pMsg->dwMessageID,
(DWORD)pMsg->hDevice,
pMsg->dwCallbackInstance,
pMsg->dwParam1,
pMsg->dwParam2,
pMsg->dwParam3
));
}
else
{
LOG((TL_TRACE,
"%hs: exit, result=x%x",
pszFuncName,
lResult
));
}
#endif
}
return lResult;
}
/*
#if DBG
LPVOID
WINAPI
ClientAllocReal(
DWORD dwSize,
DWORD dwLine,
PSTR pszFile
)
#else
LPVOID
WINAPI
ClientAllocReal(
DWORD dwSize
)
#endif
{
LPVOID p;
#if DBG
dwSize += sizeof (MYMEMINFO);
#endif
p = LocalAlloc (LPTR, dwSize);
#if DBG
if (p)
{
((PMYMEMINFO) p)->dwLine = dwLine;
((PMYMEMINFO) p)->pszFile = pszFile;
p = (LPVOID) (((PMYMEMINFO) p) + 1);
}
#endif
return p;
}
VOID
WINAPI
ClientFree(
LPVOID p
)
{
if (!p)
{
return;
}
#if DBG
//
// Fill the buffer (but not the MYMEMINFO header) with 0xa1's
// to facilitate debugging
//
{
LPVOID p2 = p;
p = (LPVOID) (((PMYMEMINFO) p) - 1);
FillMemory(
p2,
LocalSize (p) - sizeof (MYMEMINFO),
0xa1
);
}
#endif
LocalFree (p);
}
*/
#if DBG
LPVOID
WINAPI
ClientAllocReal(
DWORD dwSize,
DWORD dwLine,
PSTR pszFile
)
#else
LPVOID
WINAPI
ClientAllocReal(
DWORD dwSize
)
#endif
{
//
// Alloc 16 extra bytes so we can make sure the pointer we pass back
// is 64-bit aligned & have space to store the original pointer
//
#if DBG
PMYMEMINFO pHold;
PDWORD_PTR pAligned;
PBYTE p;
if (0 == dwSize)
{
return NULL;
}
p = (PBYTE)LocalAlloc(LPTR, dwSize + sizeof(MYMEMINFO) + 16);
if (p == NULL)
{
return NULL;
}
// note note note - this only works because mymeminfo is
// a 16 bit multiple in size. if it wasn't, this
// align stuff would cause problems.
pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
*pAligned = (DWORD_PTR) p;
pHold = (PMYMEMINFO)((DWORD_PTR)pAligned + 8);
pHold->dwSize = dwSize;
pHold->dwLine = dwLine;
pHold->pszFile = pszFile;
EnterCriticalSection(&csMemoryList);
if (gpMemLast != NULL)
{
gpMemLast->pNext = pHold;
pHold->pPrev = gpMemLast;
gpMemLast = pHold;
}
else
{
gpMemFirst = gpMemLast = pHold;
}
LeaveCriticalSection(&csMemoryList);
return (LPVOID)(pHold + 1);
#else
LPBYTE p;
PDWORD_PTR pAligned;
if (0 == dwSize)
{
return NULL;
}
if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
{
pAligned = (PDWORD_PTR) (p + 8 - (((DWORD_PTR) p) & (DWORD_PTR)0x7));
*pAligned = (DWORD_PTR) p;
pAligned = (PDWORD_PTR)((DWORD_PTR)pAligned + 8);
}
else
{
pAligned = NULL;
}
return ((LPVOID) pAligned);
#endif
}
void
WINAPI
ClientFree(
LPVOID p
)
{
#if DBG
PMYMEMINFO pHold;
if (p == NULL)
{
return;
}
pHold = (PMYMEMINFO)(((LPBYTE)p) - sizeof(MYMEMINFO));
EnterCriticalSection(&csMemoryList);
if (pHold->pPrev)
{
pHold->pPrev->pNext = pHold->pNext;
}
else
{
gpMemFirst = pHold->pNext;
}
if (pHold->pNext)
{
pHold->pNext->pPrev = pHold->pPrev;
}
else
{
gpMemLast = pHold->pPrev;
}
LeaveCriticalSection(&csMemoryList);
{
LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)pHold - 8));
LocalFree (pOrig);
}
// LocalFree(pHold);
return;
#else
if (p != NULL)
{
LPVOID pOrig = (LPVOID) *((PDWORD_PTR)((DWORD_PTR)p - 8));
LocalFree (pOrig);
}
#endif
}
#if DBG
void
DumpMemoryList()
{
PMYMEMINFO pHold;
if (gpMemFirst == NULL)
{
LOG((TL_INFO, "DumpMemoryList: ALL MEMORY DEALLOCATED"));
return;
}
pHold = gpMemFirst;
while (pHold)
{
LOG((TL_ERROR, "DumpMemoryList: %p not freed - LINE %d FILE %hs!", pHold+1, pHold->dwLine, pHold->pszFile));
pHold = pHold->pNext;
}
if (gbBreakOnLeak)
{
DebugBreak();
}
}
#endif
SIZE_T
WINAPI
ClientSize(
LPVOID p
)
{
if (p != NULL)
{
#if DBG
p = (LPVOID)(((LPBYTE)p) - sizeof(MYMEMINFO));
#endif
p = (LPVOID)*((PDWORD_PTR)((DWORD_PTR)p - 8));
return (LocalSize (p) - 16);
}
return 0;
}
LONG
WINAPI
FreeClientResources(
void
)
{
//
// Serialize the following code
//
WaitForSingleObject (ghInitMutex, INFINITE);
if (0 == gdwRpcRefCount)
{
ReleaseMutex (ghInitMutex);
return TAPIERR_REQUESTFAILED;
}
gdwRpcRefCount--;
if (0 == gdwRpcRefCount)
{
//
// If we've made an rpc connection with tapisrv then cleanly detach
//
if (gphCx)
{
RpcTryExcept
{
ClientDetach (&gphCx);
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
// do something?
}
RpcEndExcept
gphCx = NULL;
//
// we also need to close the handle to ghAsyncEventsEvent
//
if (ghAsyncEventsEvent)
{
SetEvent (ghAsyncEventsEvent);
CloseHandle(ghAsyncEventsEvent);
ghAsyncEventsEvent = NULL;
}
}
}
ReleaseMutex (ghInitMutex);
return 0;
}
#if DBG
VOID
DbgPrt(
IN DWORD dwDbgLevel,
IN LPTSTR 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)
{
TCHAR buf[1280] = TEXT("TAPI32 (xxxxxxxx): ");
va_list ap;
wsprintf( &buf[8], TEXT("%08lx"), GetCurrentThreadId() );
buf[16] = TEXT(')');
va_start(ap, lpszFormat);
wvsprintf(&buf[19],
lpszFormat,
ap
);
lstrcat (buf, TEXT("\n"));
OutputDebugString (buf);
va_end(ap);
}
}
#endif
LONG
CALLBACK
TUISPIDLLCallback(
DWORD dwObjectID,
DWORD dwObjectType,
LPVOID lpParams,
DWORD dwSize
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, xUIDLLCallback),
{
(ULONG_PTR) dwObjectID,
(ULONG_PTR) dwObjectType,
(ULONG_PTR) lpParams,
(ULONG_PTR) dwSize,
(ULONG_PTR) lpParams,
(ULONG_PTR) dwSize
},
{
Dword,
Dword,
lpSet_SizeToFollow,
Size,
lpGet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "UIDLLCallback"));
}
void
UIThread(
LPVOID pParams
)
{
DWORD dwThreadID = GetCurrentThreadId();
HANDLE hTapi32;
PUITHREADDATA pUIThreadData = (PUITHREADDATA) pParams;
LOG((TL_TRACE, "UIThread: enter (tid=%d)", dwThreadID));
//
// Call LoadLibrary to increment the reference count in case this
// thread is still running when this dll gets unloaded
//
hTapi32 = LoadLibrary (TEXT("tapi32.dll"));
LOG((TL_TRACE, "UIThread: calling TUISPI_providerGenericDialog..."));
(*pUIThreadData->pfnTUISPI_providerGenericDialog)(
TUISPIDLLCallback,
pUIThreadData->htDlgInst,
pUIThreadData->pParams,
pUIThreadData->dwSize,
pUIThreadData->hEvent
);
LOG((TL_TRACE,
"UIThread: TUISPI_providerGenericDialog returned (tid=%d)",
dwThreadID
));
//
// Remove the ui thread data struct from the global list
//
EnterCriticalSection (&gCriticalSection);
if (pUIThreadData->pNext)
{
pUIThreadData->pNext->pPrev = pUIThreadData->pPrev;
}
if (pUIThreadData->pPrev)
{
pUIThreadData->pPrev->pNext = pUIThreadData->pNext;
}
else
{
gpUIThreadInstances = pUIThreadData->pNext;
}
LeaveCriticalSection (&gCriticalSection);
//
// Free the library & buffers, then alert tapisrv
//
FreeLibrary (pUIThreadData->hUIDll);
CloseHandle (pUIThreadData->hThread);
CloseHandle (pUIThreadData->hEvent);
if (pUIThreadData->pParams)
{
ClientFree (pUIThreadData->pParams);
}
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 1, xFreeDialogInstance),
{
(ULONG_PTR) pUIThreadData->htDlgInst
},
{
Dword
}
};
DOFUNC (&funcArgs, "FreeDialogInstance");
}
ClientFree (pUIThreadData);
LOG((TL_TRACE, "UIThread: exit (tid=%d)", dwThreadID));
FreeLibraryAndExitThread (hTapi32, 0);
}
LONG
//WINAPI
CALLBACK
LAddrParamsInited(
LPDWORD lpdwInited
)
{
HKEY hKey;
HKEY hKey2;
//
// Default to 0, i.e. not initialized
//
*lpdwInited = 0;
//
// This is called by the modem setup wizard to determine
// whether they should put up TAPI's Wizard page.
//
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
gszTelephonyKey,
0,
KEY_READ,
&hKey2
) == ERROR_SUCCESS)
{
if (RegOpenKeyEx(
hKey2,
gszLocations,
0,
KEY_READ,
&hKey
) == ERROR_SUCCESS)
{
// query the Locations key for number of locations (subkeys)
if (RegQueryInfoKey(hKey,
NULL,
NULL,
NULL,
lpdwInited,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
) == ERROR_SUCCESS)
{
//
// Make sure we return a "proper" code
//
if ( *lpdwInited > 1 )
{
*lpdwInited = 1;
}
}
RegCloseKey (hKey);
}
RegCloseKey (hKey2);
}
return 0;
}
LONG
WINAPI
lineTranslateDialogA(
HLINEAPP hLineApp,
DWORD dwDeviceID,
DWORD dwAPIVersion,
HWND hwndOwner,
LPCSTR lpszAddressIn
);
LONG
CALLBACK
//WINAPI
LOpenDialAsst(
HWND hwnd,
LPCSTR lpszAddressIn,
BOOL fSimple,
BOOL fSilentInstall
)
{
TCHAR szBuf[256];
TCHAR szWinlogon[64];
DWORD dwLengthNeeded;
HDESK hDesk;
// lineTranslateDialog(hLineApp, 0, 0x00020000, hwnd, lpszAddressIn );
gbTranslateSimple = fSimple;
gbTranslateSilent = fSilentInstall;
//
// Check to see if we are called from LOGON desktop, if so, simply
// make sure we have at least one location
//
hDesk = GetThreadDesktop (GetCurrentThreadId ());
if (hDesk == NULL ||
!GetUserObjectInformation (
hDesk,
UOI_NAME,
(PVOID)szBuf,
sizeof(szBuf),
&dwLengthNeeded
) ||
LoadString (
g_hInst,
IDS_LOGONDESKNAME,
szWinlogon,
sizeof(szWinlogon)/sizeof(TCHAR)
) == 0 ||
_tcsicmp (szBuf, szWinlogon) == 0)
{
return EnsureOneLocation (hwnd);
}
return lineTranslateDialogA( 0, 0, 0x00020000, hwnd, lpszAddressIn );
}
/////////////////////////////////////////////////////////////////////
// internalPerformance
// tapiperf.dll calls this function to get performance data
// this just calls into tapisrv
/////////////////////////////////////////////////////////////////////
LONG
WINAPI
internalPerformance(
PPERFBLOCK pPerfBlock
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, tPerformance),
{
(ULONG_PTR) pPerfBlock,
(ULONG_PTR) sizeof(PERFBLOCK)
},
{
lpGet_SizeToFollow,
Size
}
};
return (DOFUNC (&funcArgs, "PerfDataCall"));
}
BOOL
WaveStringIdToDeviceId(
LPWSTR pwszStringID,
LPCWSTR pwszDeviceType,
LPDWORD pdwDeviceId
)
{
if (!pwszDeviceType || !pwszStringID)
return FALSE;
// get the device id, based on string id and device class
if ( !_wcsicmp(pwszDeviceType, L"wave/in") ||
!_wcsicmp(pwszDeviceType, L"wave/in/out")
)
{
return (MMSYSERR_NOERROR == waveInMessage(
NULL,
DRV_QUERYIDFROMSTRINGID,
(DWORD_PTR)pwszStringID,
(DWORD_PTR)pdwDeviceId));
} else if (!_wcsicmp(pwszDeviceType, L"wave/out"))
{
return (MMSYSERR_NOERROR == waveOutMessage(
NULL,
DRV_QUERYIDFROMSTRINGID,
(DWORD_PTR)pwszStringID,
(DWORD_PTR)pdwDeviceId));
} else if (!_wcsicmp(pwszDeviceType, L"midi/in"))
{
return (MMSYSERR_NOERROR == midiInMessage(
NULL,
DRV_QUERYIDFROMSTRINGID,
(DWORD_PTR)pwszStringID,
(DWORD_PTR)pdwDeviceId));
} else if (!_wcsicmp(pwszDeviceType, L"midi/out"))
{
return (MMSYSERR_NOERROR == midiOutMessage(
NULL,
DRV_QUERYIDFROMSTRINGID,
(DWORD_PTR)pwszStringID,
(DWORD_PTR)pdwDeviceId));
}
return FALSE;
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
#if DBG
// Debug only stuff was left as ANSI
char *aszLineErrors[] =
{
NULL,
"ALLOCATED",
"BADDEVICEID",
"BEARERMODEUNAVAIL",
"inval err value (0x80000004)", // 0x80000004 isn't valid err code
"CALLUNAVAIL",
"COMPLETIONOVERRUN",
"CONFERENCEFULL",
"DIALBILLING",
"DIALDIALTONE",
"DIALPROMPT",
"DIALQUIET",
"INCOMPATIBLEAPIVERSION",
"INCOMPATIBLEEXTVERSION",
"INIFILECORRUPT",
"INUSE",
"INVALADDRESS", // 0x80000010
"INVALADDRESSID",
"INVALADDRESSMODE",
"INVALADDRESSSTATE",
"INVALAPPHANDLE",
"INVALAPPNAME",
"INVALBEARERMODE",
"INVALCALLCOMPLMODE",
"INVALCALLHANDLE",
"INVALCALLPARAMS",
"INVALCALLPRIVILEGE",
"INVALCALLSELECT",
"INVALCALLSTATE",
"INVALCALLSTATELIST",
"INVALCARD",
"INVALCOMPLETIONID",
"INVALCONFCALLHANDLE", // 0x80000020
"INVALCONSULTCALLHANDLE",
"INVALCOUNTRYCODE",
"INVALDEVICECLASS",
"INVALDEVICEHANDLE",
"INVALDIALPARAMS",
"INVALDIGITLIST",
"INVALDIGITMODE",
"INVALDIGITS",
"INVALEXTVERSION",
"INVALGROUPID",
"INVALLINEHANDLE",
"INVALLINESTATE",
"INVALLOCATION",
"INVALMEDIALIST",
"INVALMEDIAMODE",
"INVALMESSAGEID", // 0x80000030
"inval err value (0x80000031)", // 0x80000031 isn't valid err code
"INVALPARAM",
"INVALPARKID",
"INVALPARKMODE",
"INVALPOINTER",
"INVALPRIVSELECT",
"INVALRATE",
"INVALREQUESTMODE",
"INVALTERMINALID",
"INVALTERMINALMODE",
"INVALTIMEOUT",
"INVALTONE",
"INVALTONELIST",
"INVALTONEMODE",
"INVALTRANSFERMODE",
"LINEMAPPERFAILED", // 0x80000040
"NOCONFERENCE",
"NODEVICE",
"NODRIVER",
"NOMEM",
"NOREQUEST",
"NOTOWNER",
"NOTREGISTERED",
"OPERATIONFAILED",
"OPERATIONUNAVAIL",
"RATEUNAVAIL",
"RESOURCEUNAVAIL",
"REQUESTOVERRUN",
"STRUCTURETOOSMALL",
"TARGETNOTFOUND",
"TARGETSELF",
"UNINITIALIZED", // 0x80000050
"USERUSERINFOTOOBIG",
"REINIT",
"ADDRESSBLOCKED",
"BILLINGREJECTED",
"INVALFEATURE",
"NOMULTIPLEINSTANCE",
"INVALAGENTID",
"INVALAGENTGROUP",
"INVALPASSWORD",
"INVALAGENTSTATE",
"INVALAGENTACTIVITY",
"DIALVOICEDETECT"
};
char *aszPhoneErrors[] =
{
"SUCCESS",
"ALLOCATED",
"BADDEVICEID",
"INCOMPATIBLEAPIVERSION",
"INCOMPATIBLEEXTVERSION",
"INIFILECORRUPT",
"INUSE",
"INVALAPPHANDLE",
"INVALAPPNAME",
"INVALBUTTONLAMPID",
"INVALBUTTONMODE",
"INVALBUTTONSTATE",
"INVALDATAID",
"INVALDEVICECLASS",
"INVALEXTVERSION",
"INVALHOOKSWITCHDEV",
"INVALHOOKSWITCHMODE", // 0x90000010
"INVALLAMPMODE",
"INVALPARAM",
"INVALPHONEHANDLE",
"INVALPHONESTATE",
"INVALPOINTER",
"INVALPRIVILEGE",
"INVALRINGMODE",
"NODEVICE",
"NODRIVER",
"NOMEM",
"NOTOWNER",
"OPERATIONFAILED",
"OPERATIONUNAVAIL",
"inval err value (0x9000001e)", // 0x9000001e isn't valid err code
"RESOURCEUNAVAIL",
"REQUESTOVERRUN", // 0x90000020
"STRUCTURETOOSMALL",
"UNINITIALIZED",
"REINIT"
};
char *aszTapiErrors[] =
{
"SUCCESS",
"DROPPED",
"NOREQUESTRECIPIENT",
"REQUESTQUEUEFULL",
"INVALDESTADDRESS",
"INVALWINDOWHANDLE",
"INVALDEVICECLASS",
"INVALDEVICEID",
"DEVICECLASSUNAVAIL",
"DEVICEIDUNAVAIL",
"DEVICEINUSE",
"DESTBUSY",
"DESTNOANSWER",
"DESTUNAVAIL",
"UNKNOWNWINHANDLE",
"UNKNOWNREQUESTID",
"REQUESTFAILED",
"REQUESTCANCELLED",
"INVALPOINTER"
};
char *
PASCAL
MapResultCodeToText(
LONG lResult,
char *pszResult
)
{
if (lResult == 0)
{
wsprintfA (pszResult, "SUCCESS");
}
else if (lResult > 0)
{
wsprintfA (pszResult, "x%x (completing async)", lResult);
}
else if (((DWORD) lResult) <= LINEERR_DIALVOICEDETECT)
{
lResult &= 0x0fffffff;
wsprintfA (pszResult, "LINEERR_%s", aszLineErrors[lResult]);
}
else if (((DWORD) lResult) <= PHONEERR_REINIT)
{
if (((DWORD) lResult) >= PHONEERR_ALLOCATED)
{
lResult &= 0x0fffffff;
wsprintfA (pszResult, "PHONEERR_%s", aszPhoneErrors[lResult]);
}
else
{
goto MapResultCodeToText_badErrorCode;
}
}
else if (((DWORD) lResult) <= ((DWORD) TAPIERR_DROPPED) &&
((DWORD) lResult) >= ((DWORD) TAPIERR_INVALPOINTER))
{
lResult = ~lResult + 1;
wsprintfA (pszResult, "TAPIERR_%s", aszTapiErrors[lResult]);
}
else
{
MapResultCodeToText_badErrorCode:
wsprintfA (pszResult, "inval error value (x%x)");
}
return pszResult;
}
#endif