summaryrefslogtreecommitdiffstats
path: root/private/tapi/dev/client/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/tapi/dev/client/client.c')
-rw-r--r--private/tapi/dev/client/client.c14345
1 files changed, 14345 insertions, 0 deletions
diff --git a/private/tapi/dev/client/client.c b/private/tapi/dev/client/client.c
new file mode 100644
index 000000000..ec2db25b3
--- /dev/null
+++ b/private/tapi/dev/client/client.c
@@ -0,0 +1,14345 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+Copyright (c) 1996 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 "client.h"
+#include "private.h"
+#include "tapsrv.h"
+#include "clientr.h"
+#include "prsht.h"
+#include "shellapi.h"
+#include "..\perfdll\tapiperf.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 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;
+
+
+//
+// Global vars
+//
+
+BOOL gbNTVDMClient = FALSE;
+BOOL gbResourcesAllocated = FALSE;
+DWORD gdwNumInits = 0;
+DWORD gdwTlsIndex;
+DWORD gdwNumLineDevices = 0;
+DWORD gdwNumPhoneDevices = 0;
+HANDLE ghAsyncEventsEvent = NULL;
+HANDLE ghInitMutex;
+
+extern BOOL gbTranslateSimple;
+extern BOOL gbTranslateSilent;
+
+HINSTANCE ghInst;
+
+PASYNC_EVENTS_THREAD_PARAMS gpAsyncEventsThreadParams = NULL;
+
+#if DBG
+WCHAR gszTapi32DebugLevel[] = L"Tapi32DebugLevel";
+#endif
+WCHAR gszTapi32MaxNumRequestRetries[] = L"Tapi32MaxNumRequestRetries";
+WCHAR gszTapi32RequestRetryTimeout[] = L"Tapi32RequestRetryTimeout";
+extern WCHAR gszTelephonyKey[];
+
+DWORD gdwMaxNumRequestRetries;
+DWORD gdwRequestRetryTimeout;
+
+char szTapi32WndClass[] = "Tapi32WndClass";
+
+CHAR gszTUISPI_providerConfig[] = "TUISPI_providerConfig";
+CHAR gszTUISPI_providerGenericDialog[] = "TUISPI_providerGenericDialog";
+CHAR gszTUISPI_providerGenericDialogData[] = "TUISPI_providerGenericDialogData";
+CHAR gszTUISPI_providerInstall[] = "TUISPI_providerInstall";
+CHAR gszTUISPI_providerRemove[] = "TUISPI_providerRemove";
+CHAR gszTUISPI_lineConfigDialog[] = "TUISPI_lineConfigDialog";
+CHAR gszTUISPI_lineConfigDialogEdit[] = "TUISPI_lineConfigDialogEdit";
+CHAR gszTUISPI_phoneConfigDialog[] = "TUISPI_phoneConfigDialog";
+
+//extern WCHAR gszLocationKeyW[];
+extern WCHAR gszLocationsW[];
+extern WCHAR gszNumEntriesW[];
+
+
+HINSTANCE ghWow32Dll = NULL;
+FARPROC gpfnWOWGetVDMPointer = NULL;
+
+PUITHREADDATA gpUIThreadInstances = NULL;
+
+CRITICAL_SECTION gCriticalSection;
+CRITICAL_SECTION gUICriticalSection;
+PCONTEXT_HANDLE_TYPE gphCx = (PCONTEXT_HANDLE_TYPE) NULL;
+
+#if DBG
+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
+};
+
+
+#define AllInitExOptions2_0 \
+ (LINEINITIALIZEEXOPTION_USEHIDDENWINDOW | \
+ LINEINITIALIZEEXOPTION_USEEVENT | \
+ LINEINITIALIZEEXOPTION_USECOMPLETIONPORT)
+
+
+//
+// Function prototypes
+//
+
+void
+PASCAL
+lineMakeCallPostProcess(
+ PASYNCEVENTMSG pMsg
+ );
+
+LONG
+WINAPI
+AllocClientResources(
+ 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
+ );
+
+LONG
+PASCAL
+xxxShutdown(
+ DWORD hXXXApp,
+ BOOL bLineShutdown
+ );
+
+LONG
+PASCAL
+xxxGetMessage(
+ BOOL bLine,
+ PINIT_DATA pInitData,
+ LPLINEMESSAGE pMsg,
+ DWORD dwTimeout
+ );
+
+
+//
+// The code...
+//
+
+
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+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) );
+
+ 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;
+ PSTR lpszStringA;
+
+
+ if ((dwSize = *lpdwXxxSize) != 0)
+ {
+ dwTotalSize = *((LPDWORD) lpBase);
+
+ dwUsedSize = *(((LPDWORD) lpBase)+2);
+
+ dwOffset = *(lpdwXxxSize + 1);
+
+ pString = (PWSTR)(lpBase + dwOffset);
+
+
+ if (IsBadStringPtrW (pString, dwSize))
+ {
+ DBGOUT((1, "The service provider returned an invalid field in the structure 0x08lx : 0x08lx",
+ 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 = ClientAlloc( dwNewSize + 1 );
+
+ if ( NULL == lpszStringA )
+ {
+ DBGOUT((1, "Memory alloc failed - alloc(0x%08lx)",
+ dwSize));
+ DBGOUT((1, "The service provider returned an invalid field size in the structure 0x08lx : 0x08lx",
+ dwSize));
+
+ *lpdwXxxSize = 0;
+ *(lpdwXxxSize+1) = 0;
+
+ return;
+ }
+
+ lpszStringA[dwNewSize] = '\0';
+
+ 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
+ )
+ );
+
+ ClientFree (lpszStringA);
+
+
+ //
+ // Update the number of bytes
+ //
+
+ *lpdwXxxSize = dwNewSize;
+ }
+ }
+}
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+BOOL
+WINAPI
+DllMain(
+ HANDLE hDLL,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ ghInst = hDLL;
+
+
+ //
+ // Init CRT
+ //
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ OutputDebugString(
+ "TAPI32.DLL: DLL_PROCESS_ATTACH, _CRT_INIT() failed\n"
+ );
+
+ return FALSE;
+ }
+
+ {
+ HKEY hKey;
+
+
+#if DBG
+ gdwDebugLevel = 0;
+#endif
+ gdwMaxNumRequestRetries = 40;
+ gdwRequestRetryTimeout = 250; // milliseconds
+
+ if (RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey
+
+ ) == ERROR_SUCCESS)
+ {
+ DWORD dwDataSize = sizeof(DWORD), dwDataType;
+
+#if DBG
+ RegQueryValueExW(
+ hKey,
+ gszTapi32DebugLevel,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwDebugLevel,
+ &dwDataSize
+ );
+
+ dwDataSize = sizeof(DWORD);
+#endif
+
+ RegQueryValueExW(
+ hKey,
+ gszTapi32MaxNumRequestRetries,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwMaxNumRequestRetries,
+ &dwDataSize
+ );
+
+ RegQueryValueExW(
+ hKey,
+ gszTapi32RequestRetryTimeout,
+ 0,
+ &dwDataType,
+ (LPBYTE) &gdwRequestRetryTimeout,
+ &dwDataSize
+ );
+
+ RegCloseKey (hKey);
+ }
+ }
+
+ DBGOUT((2, "DLL_PROCESS_ATTACH, pid = %ld", GetCurrentProcessId()));
+
+
+ //
+ // Alloc a Tls index
+ //
+
+ if ((gdwTlsIndex = TlsAlloc()) == 0xffffffff)
+ {
+ DBGOUT((1, "DLL_PROCESS_ATTACH, TlsAlloc() failed"));
+
+ return FALSE;
+ }
+
+
+ //
+ // Initialize Tls to NULL for this thread
+ //
+
+ TlsSetValue (gdwTlsIndex, NULL);
+
+
+ //
+ //
+ //
+
+ ghInitMutex = CreateMutex (NULL, FALSE, NULL);
+
+ InitializeCriticalSection (&gCriticalSection);
+ InitializeCriticalSection (&gUICriticalSection);
+
+
+ break;
+ }
+ case DLL_PROCESS_DETACH:
+ {
+ PCLIENT_THREAD_INFO pTls;
+
+
+ DBGOUT((2, "DLL_PROCESS_DETACH, pid = %ld", GetCurrentProcessId()));
+
+
+ //
+ // Clean up any Tls
+ //
+
+ if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
+ {
+ if (pTls->pBuf)
+ {
+ ClientFree (pTls->pBuf);
+ }
+
+ ClientFree (pTls);
+ }
+
+
+ FreeClientResources();
+
+ TlsFree (gdwTlsIndex);
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ DBGOUT((1, "_CRT_INIT() failed"));
+ }
+
+ DeleteCriticalSection (&gCriticalSection);
+ DeleteCriticalSection (&gUICriticalSection);
+
+ break;
+ }
+ case DLL_THREAD_ATTACH:
+
+ //
+ // First must init CRT
+ //
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ DBGOUT((1, "_CRT_INIT() failed"));
+
+ return FALSE;
+ }
+
+ DBGOUT((
+ 3,
+ "DLL_THREAD_ATTACH, pid = %ld, tid = %ld",
+ GetCurrentProcessId(),
+ GetCurrentThreadId()
+ ));
+
+
+ //
+ // Initialize Tls to NULL for this thread
+ //
+
+ TlsSetValue (gdwTlsIndex, NULL);
+
+ break;
+
+ case DLL_THREAD_DETACH:
+ {
+ PCLIENT_THREAD_INFO pTls;
+
+
+ DBGOUT((
+ 3,
+ "DLL_THREAD_DETACH, pid = %ld, tid = %ld",
+ GetCurrentProcessId(),
+ GetCurrentThreadId()
+ ));
+
+
+ //
+ // Clean up any Tls
+ //
+
+ if ((pTls = (PCLIENT_THREAD_INFO) TlsGetValue (gdwTlsIndex)))
+ {
+ if (pTls->pBuf)
+ {
+ ClientFree (pTls->pBuf);
+ }
+
+ ClientFree (pTls);
+ }
+
+
+ //
+ // Finally, alert CRT
+ //
+
+ if (!_CRT_INIT (hDLL, dwReason, lpReserved))
+ {
+ DBGOUT((1, "_CRT_INIT() failed"));
+ }
+
+ break;
+ }
+
+ } // switch
+
+ return TRUE;
+}
+
+
+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;
+ static FARPROC pPostQueuedCompletionStatus = NULL;
+
+
+ DBGOUT((3, "AsyncEventsThread: enter"));
+
+
+ //
+ // Just loop reading async events/completions from server &
+ // handling them
+ //
+
+ while (1)
+ {
+ DWORD dwUsedSize, dwNeededSize;
+ PASYNCEVENTMSG pAsyncEventMsg;
+
+
+ //
+ // Check to see if xxxShutdown or FreeClientResources
+ // is signaling us to exit (we need to check both before
+ // & after the wait to dela with a event setting/resetting
+ // race condition between FreeClientResources & Tapisrv)
+ //
+
+ if (*pbExitThread)
+ {
+ break;
+ }
+
+
+ //
+ // Block until tapisrv signals us that it has some event data for us
+ //
+
+ WaitForSingleObject (ghAsyncEventsEvent, INFINITE);
+
+
+ //
+ // Check to see if xxxShutdown or FreeClientResources
+ // 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 = 3 * sizeof (DWORD);
+
+ RpcTryExcept
+ {
+ ClientRequest (gphCx, (char *) pMsg, dwBufSize, &dwUsedSize);
+ bRetry = FALSE;
+ }
+ RpcExcept (1)
+ {
+ bRetry = !(*pbExitThread);
+ DBGOUT((
+ 2,
+ "AsyncEventsThread: rpc exception %d handled",
+ RpcExceptionCode()
+ ));
+ Sleep (10);
+ }
+ RpcEndExcept
+
+ } while (bRetry);
+
+#if DBG
+// DBGOUT((
+// 84,
+// "AsyncEventsThread: CliReq ret'd, dwBufSize=0x%08lx usedSize=0x%08lx other=0x%08lx",
+// dwBufSize,
+// dwUsedSize,
+// pMsg->Params[2]
+// dwUsedSize
+// ));
+ if (
+ ( dwUsedSize > dwBufSize )
+ ||
+ ( pMsg->Params[2] > dwBufSize )
+ )
+ {
+ DBGOUT((1, "OVERFLOW!!!"));
+
+ DBGOUT((1, "Watch this..."));
+ ClientFree( ClientAlloc( 0x10000 ) );
+ }
+#endif
+
+ if ((dwUsedSize = pMsg->Params[2]) == 0 &&
+ (dwNeededSize = 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;
+
+
+ DBGOUT((
+ 2,
+ "AsyncEventsThread: allocating larger event buf (size=x%x)",
+ dwNeededSize
+ ));
+
+ if (!(pNewBuf = ClientAlloc (dwNeededSize)))
+ {
+// BUGBUG AsyncEventsThread: handle larger event buf alloc failure
+ 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) pAsyncEventMsg->pInitData;
+
+
+ DBGOUT((
+ 3,
+ "AsyncEventsThread: msg=%d, hDev=x%x, p1=x%x, p2=x%x, p3=x%x",
+ pAsyncEventMsg->dwMsg,
+ pAsyncEventMsg->hDevice,
+ pAsyncEventMsg->dwParam1,
+ pAsyncEventMsg->dwParam2,
+ pAsyncEventMsg->dwParam3
+ ));
+
+
+ //
+ // Special case for UI msgs (not fwd'd to client)
+ //
+
+ switch (pAsyncEventMsg->dwMsg)
+ {
+ case LINE_CREATEDIALOGINSTANCE:
+ {
+ DWORD dwThreadID,
+ dwDataOffset = pAsyncEventMsg->dwParam1,
+ dwDataSize = pAsyncEventMsg->dwParam2,
+ dwUIDllNameOffset = pAsyncEventMsg->dwParam3;
+ 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 = LoadLibraryW(
+ (PWSTR)(((LPBYTE) pAsyncEventMsg) +
+ dwUIDllNameOffset)
+ )))
+ {
+ DBGOUT((
+ 2,
+ "LoadLibraryW(%ls) failed, err=%d",
+ ((LPBYTE) pAsyncEventMsg) + dwUIDllNameOffset,
+ GetLastError()
+ ));
+
+ goto LINE_CREATEDIALOGINSTANCE_error;
+ }
+
+ if (!(pUIThreadData->pfnTUISPI_providerGenericDialog =
+ (TUISPIPROC) GetProcAddress(
+ pUIThreadData->hUIDll,
+ (LPCSTR) gszTUISPI_providerGenericDialog
+ )))
+ {
+ DBGOUT((
+ 2,
+ "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->dwParam1, // data offset
+ pAsyncEventMsg->dwParam2 // 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
+ //
+
+ DBGOUT((11, "Trying to grab critical section (0x%08lx)", gCriticalSection));
+ EnterCriticalSection (&gCriticalSection);
+ DBGOUT((11, "Got critical section (0x%08lx)", gCriticalSection));
+
+ try
+ {
+ if ((DWORD) pInitData & 0x7 ||
+ pInitData->dwKey != INITDATA_KEY)
+ {
+ DBGOUT((4, "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->dwMsg == 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:
+
+ //
+ // 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
+ )))
+ {
+// BUGBUG AsyncEventsThread: handle proxyRequestBuf alloc failure
+ }
+
+ pProxyRequestApp = (LPLINEPROXYREQUEST)
+ (pProxyRequestHeader + 1);
+
+ CopyMemory(
+ pProxyRequestApp,
+ pProxyRequest,
+ pProxyRequest->dwSize
+ );
+
+ break;
+
+ case LINEPROXYREQUEST_GETAGENTCAPS:
+ case LINEPROXYREQUEST_GETAGENTSTATUS:
+ case LINEPROXYREQUEST_GETAGENTACTIVITYLIST:
+ case LINEPROXYREQUEST_GETAGENTGROUPLIST:
+
+ //
+ // 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
+ //
+
+ pProxyRequest->dwSize +=
+ pProxyRequest->GetAgentCaps.AgentCaps.dwTotalSize;
+
+ if (!(pProxyRequestHeader = ClientAlloc(
+ sizeof (PROXYREQUESTHEADER) + pProxyRequest->dwSize
+ )))
+ {
+// BUGBUG AsyncEventsThread: handle proxyRequestBuf alloc failure
+ }
+
+ 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,
+ 9 * sizeof (DWORD)
+ );
+
+
+ //
+ // Relocate the machine & user names to the end of the
+ // structure
+ //
+
+ pProxyRequestApp->dwClientMachineNameOffset =
+ pProxyRequest->dwSize -
+ pProxyRequest->dwClientMachineNameSize;
+
+ lstrcpyW(
+ (WCHAR *)(((LPBYTE) pProxyRequestApp) +
+ pProxyRequestApp->dwClientMachineNameOffset),
+ (WCHAR *)(((LPBYTE) pProxyRequest) +
+ pProxyRequest->dwClientMachineNameOffset)
+ );
+
+ pProxyRequestApp->dwClientUserNameOffset =
+ pProxyRequestApp->dwClientMachineNameOffset -
+ pProxyRequest->dwClientUserNameSize;
+
+ lstrcpyW(
+ (WCHAR *)(((LPBYTE) pProxyRequestApp) +
+ pProxyRequestApp->dwClientUserNameOffset),
+ (WCHAR *)(((LPBYTE) pProxyRequest) +
+ pProxyRequest->dwClientUserNameOffset)
+ );
+
+ break;
+ }
+
+ pProxyRequestHeader->dwKey = TPROXYREQUESTHEADER_KEY;
+ pProxyRequestHeader->dwInstance = pAsyncEventMsg->dwParam1;
+
+ pAsyncEventMsg->dwParam1 = (DWORD) pProxyRequestApp;
+ }
+
+
+ //
+ // Call the post processing proc if there is one
+ //
+
+ if (pAsyncEventMsg->pfnPostProcessProc)
+ {
+ (*((POSTPROCESSPROC) pAsyncEventMsg->pfnPostProcessProc))(
+ 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 ==
+ LINEINITIALIZEEXOPTION_USECOMPLETIONPORT)
+ {
+ LPLINEMESSAGE pMsg;
+
+
+ if (!(pMsg = LocalAlloc (LMEM_FIXED, sizeof (LINEMESSAGE))))
+ {
+// BUGBUG AsyncEventsThread: handle LocalAlloc failure nicely
+ }
+
+ CopyMemory(
+ pMsg,
+ &pAsyncEventMsg->hDevice,
+ sizeof (LINEMESSAGE)
+ );
+
+ if ( !pPostQueuedCompletionStatus )
+ {
+ HINSTANCE hInst;
+
+ hInst = GetModuleHandle( "Kernel32.dll" );
+
+ pPostQueuedCompletionStatus = GetProcAddress(
+ hInst,
+ "PostQueuedCompletionStatus"
+ );
+ }
+
+
+ if (pPostQueuedCompletionStatus && !pPostQueuedCompletionStatus(
+ pInitData->hCompletionPort,
+ sizeof (LINEMESSAGE),
+ pInitData->dwCompletionKey,
+ (LPOVERLAPPED) pMsg
+ ))
+ {
+// BUGBUG AsyncEventsThread: handle PostQueuedCompletionStatus failure nicely
+
+ LocalFree (pMsg);
+
+ DBGOUT((
+ 1,
+ "AsyncEventsThread: PostQueuedCompletionStatus " \
+ "failed, err=%d",
+ GetLastError()
+ ));
+ }
+#if DBG
+ else
+ {
+ DBGOUT((
+ 3,
+ "AsyncEventsThread: posted complPort msg\n",
+ "\thDev=x%x, dwInst=x%x, p1=x%x, p2=x%x, p3=x%x",
+ aszMsgs[pAsyncEventMsg->dwMsg],
+ pAsyncEventMsg->hDevice,
+ pAsyncEventMsg->dwCallbackInst,
+ pAsyncEventMsg->dwParam1,
+ pAsyncEventMsg->dwParam2,
+ pAsyncEventMsg->dwParam3
+ ));
+ }
+#endif
+ 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 = 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
+ {
+// BUGBUG AsyncEventsThread: handle event buf alloc failure
+ }
+ }
+
+
+ //
+ // Copy the msg to the hidden window's msg queue,
+ // and update that queue's pointers
+ //
+
+ CopyMemory(
+ pInitData->pFreeEntry,
+ &pAsyncEventMsg->hDevice,
+ 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 == LINEINITIALIZEEXOPTION_USEEVENT)
+ {
+ if (pInitData->dwNumUsedEntries == 1)
+ {
+ SetEvent (pInitData->hEvent);
+ }
+ }
+ else // HIDDENWINDOW
+ {
+ if (pInitData->bPendingAsyncEventMsg == FALSE)
+ {
+ DBGOUT((
+ 4,
+ "AsyncEventsThread: posting msg, hwnd=x%lx",
+ pInitData->hwnd
+ ));
+
+ PostMessage(
+ pInitData->hwnd,
+ WM_ASYNCEVENT,
+ 0,
+ (LPARAM) pInitData
+ );
+
+ pInitData->bPendingAsyncEventMsg = TRUE;
+ }
+ }
+
+AsyncEventsThread_leaveCritSec:
+
+ DBGOUT((11, "releasing critical section (0x%08lx)", gCriticalSection));
+ LeaveCriticalSection (&gCriticalSection);
+
+AsyncEventsThread_decrUsedSize:
+
+ dwUsedSize -= pAsyncEventMsg->dwTotalSize;
+
+ pAsyncEventMsg = (PASYNCEVENTMSG)
+ ((LPBYTE) pAsyncEventMsg + pAsyncEventMsg->dwTotalSize);
+#if DBG
+ if ( (LONG)dwUsedSize < 0 )
+ {
+ DBGOUT((1, "dwUsedSize went negative!!!"));
+ }
+#endif
+ }
+ }
+
+ {
+ //
+ // Free our resources, and then exit
+ //
+
+ HANDLE hTapi32 = pAsyncEventsThreadParams->hTapi32;
+
+
+ if (pAsyncEventsThreadParams->hWow32)
+ {
+ FreeLibrary (pAsyncEventsThreadParams->hWow32);
+ }
+
+ ClientFree (pBuf);
+ ClientFree (pAsyncEventsThreadParams);
+
+ DBGOUT((3, "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;
+
+
+ try
+ {
+ *p = *p + 1;
+ }
+ except ((((dwError = GetExceptionCode()) == EXCEPTION_ACCESS_VIOLATION) ||
+ dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+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);
+ }
+
+ return pClientThreadInfo;
+}
+
+#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;
+ DWORD i, j, dwValue, dwUsedSize, dwNeededSize;
+
+ PCLIENT_THREAD_INFO pTls;
+
+
+ DBGOUT((11, "About to call %s", pszFuncName));
+
+ //
+ // Check to make sure resources allocated
+ // (TAPISRV started, pipes opened, etc.)
+ //
+
+ if (!gbResourcesAllocated &&
+ ((lResult = AllocClientResources (dwFuncClassErrorIndex))
+ != TAPI_SUCCESS))
+ {
+ goto DoFunc_return;
+ }
+
+
+ //
+ // 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 = sizeof (TAPI32_MSG);
+
+ for(
+ i = 0, j = (pFuncArgs->Flags & ASYNC ? 1 : 0);
+ i < (pFuncArgs->Flags & NUM_ARGS_MASK);
+ i++, j++
+ )
+ {
+ dwValue = ((PTAPI32_MSG) pTls->pBuf)->Params[j] = pFuncArgs->Args[i];
+
+ switch (pFuncArgs->ArgTypes[i])
+ {
+ case Dword:
+
+ //
+ // Nothing to check, just continue
+ //
+
+ continue;
+
+ case lpDword:
+
+ if (IsBadDwordPtr ((LPDWORD) dwValue))
+ {
+ DBGOUT((1, "Bad lpdword in dofunc"));
+ lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+ bCopyOnSuccess = TRUE;
+
+ 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;
+
+
+ if (
+ (0 == pFuncArgs->Args[i])
+ &&
+ (hXxxApp_NULLOK == pFuncArgs->ArgTypes[i])
+ )
+ {
+ //
+ // Looks good to me...
+ //
+ continue;
+ }
+
+ try
+ {
+ PINIT_DATA pInitData = (PINIT_DATA) dwValue;
+
+
+ if (pInitData->dwKey != INITDATA_KEY)
+ {
+ DBGOUT((1, "Bad hxxxapp in dofunc"));
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0xffffffff;
+ }
+ else
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
+ (DWORD) pInitData->hXxxApp;
+ }
+ }
+ except ((((dwError = GetExceptionCode())
+ == EXCEPTION_ACCESS_VIOLATION) ||
+ dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ DBGOUT((1, "Bad hxxxapp2 in dofunc (0x%08lx)", dwError));
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = 0xffffffff;
+ }
+
+ continue;
+ }
+ case Hwnd:
+
+ if (!IsWindow ((HWND) dwValue))
+ {
+ DBGOUT((1, "Bad hWnd in dofunc"));
+ lResult = gaInvalHwndErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+ continue;
+
+
+// case lpsz:
+ case lpszW:
+
+ //
+ // Check if dwValue is a valid string ptr and if so
+ // copy the contents of the string to the extra data
+ // buffer passed to the server
+ //
+
+ try
+ {
+ DWORD n = (lstrlenW((WCHAR *) dwValue) + 1) * sizeof(WCHAR),
+ nAligned = (n + 3) & 0xfffffffc;
+
+
+ if ((nAligned + dwUsedSize) > pTls->dwBufSize)
+ {
+ if (!GrowBuf(
+ &pTls->pBuf,
+ &pTls->dwBufSize,
+ dwUsedSize,
+ nAligned
+ ))
+ {
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+ }
+
+ CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, n);
+
+
+ //
+ // Pass the server the offset of the string in the var data
+ // portion of the buffer
+ //
+
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] =
+ dwUsedSize - sizeof (TAPI32_MSG);
+
+
+ //
+ // Increment the total number of data bytes
+ //
+
+ dwUsedSize += nAligned;
+ dwNeededSize += nAligned;
+ }
+ 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))
+ {
+ DBGOUT((
+ 2,
+ "DoFunc: error, lpGet_SizeToFollow !followed by Size"
+ ));
+
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+#endif
+ dwSize = pFuncArgs->Args[i + 1];
+ }
+ else
+ {
+ DWORD dwError;
+
+ try
+ {
+ dwSize = *((LPDWORD) dwValue);
+ }
+ except ((((dwError = GetExceptionCode())
+ == EXCEPTION_ACCESS_VIOLATION) ||
+ dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ DBGOUT((1, "Bad get struct/size in dofunc"));
+ lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+ }
+
+ if (IsBadWritePtr ((LPVOID) dwValue, dwSize))
+ {
+ DBGOUT((1, "Bad get size/struct2 in dofunc"));
+ lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+
+ if (bSizeToFollow)
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = TAPI_NO_DATA;
+ ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
+ }
+ else
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[j] = dwSize;
+ }
+
+
+ //
+ // Now set the bCopyOnSuccess flag to indicate that we've data
+ // to copy back on successful completion, and add to the
+ // dwNeededSize field
+ //
+
+ bCopyOnSuccess = TRUE;
+
+ dwNeededSize += dwSize;
+
+ continue;
+ }
+ case lpSet_Struct:
+ case lpSet_SizeToFollow:
+ {
+ BOOL bSizeToFollow = (pFuncArgs->ArgTypes[i]==lpSet_SizeToFollow);
+ DWORD dwSize, 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)))
+ {
+ DBGOUT((
+ 2,
+ "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 ? pFuncArgs->Args[i + 1] :
+ *((LPDWORD) dwValue));
+
+ if (IsBadReadPtr ((LPVOID) dwValue, dwSize))
+ {
+ DBGOUT((1, "Bad set size/struct in dofunc"));
+ lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+ dwSizeAligned = (dwSize + 3) & 0xfffffffc;
+
+
+ //
+ // 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);
+ dwValue = (DWORD) &dwZeroTotalSize;
+
+// DBGOUT((1, "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
+ ))
+ {
+ DBGOUT((1, "Nomem set size/struct in dofunc"));
+ lResult = gaNoMemErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+ }
+
+ CopyMemory (pTls->pBuf + dwUsedSize, (LPBYTE) dwValue, dwSize);
+ }
+ except ((((dwError = GetExceptionCode())
+ == EXCEPTION_ACCESS_VIOLATION) ||
+ dwError == EXCEPTION_DATATYPE_MISALIGNMENT) ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ DBGOUT((1, "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)
+ {
+ ((PTAPI32_MSG) pTls->pBuf)->Params[++j] = pFuncArgs->Args[++i];
+ }
+
+ continue;
+ }
+#if DBG
+ case Size:
+
+ DBGOUT((2, "DoFunc: error, hit case Size"));
+
+ continue;
+
+ default:
+
+ DBGOUT((2, "DoFunc: error, unknown arg type"));
+
+ continue;
+#endif
+ } // switch
+
+ } // for
+
+
+ //
+ // 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;
+
+
+ do
+ {
+ RpcTryExcept
+ {
+ ClientRequest (gphCx, pTls->pBuf, dwNeededSize, &dwUsedSize);
+ lResult = ((PTAPI32_MSG) pTls->pBuf)->u.Ack_ReturnValue;
+ dwRetryCount = 0;
+ }
+ RpcExcept (1)
+ {
+ unsigned long rpcException = RpcExceptionCode();
+
+ if (rpcException == RPC_S_SERVER_TOO_BUSY)
+ {
+ if (dwRetryCount++ < gdwMaxNumRequestRetries)
+ {
+ Sleep (gdwRequestRetryTimeout);
+ }
+ else
+ {
+ dwRetryCount = 0;
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ }
+ }
+ else
+ {
+ DBGOUT((1, "DoFunc: rpcException # %d", rpcException));
+ lResult = gaOpFailedErrors[dwFuncClassErrorIndex];
+ dwRetryCount = 0;
+ }
+ }
+ RpcEndExcept
+
+ } 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
+//
+ DBGOUT((11, "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]) = pMsg->Params[j];
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ // BUGBUG for certain funcs want to lineShutdown, etc.
+
+ 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 + pMsg->Params[j] + sizeof(TAPI32_MSG),
+ pMsg->Params[j+1]
+ );
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ // BUGBUG for certain funcs want to lineShutdown, etc.
+
+ 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 (pMsg->Params[j] != TAPI_NO_DATA)
+ {
+
+ LPDWORD pStruct;
+
+
+ pStruct = (LPDWORD) (pTls->pBuf + sizeof(TAPI32_MSG) +
+ pMsg->Params[j]);
+
+ CopyMemory(
+ (LPBYTE) pFuncArgs->Args[i],
+ (LPBYTE) pStruct,
+ *(pStruct + 2) // ptr to dwUsedSize field
+ );
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ // BUGBUG for certain funcs want to lineShutdown, etc.
+
+ lResult = gaInvalPtrErrors[dwFuncClassErrorIndex];
+ goto DoFunc_return;
+ }
+
+ continue;
+
+ default:
+
+ continue;
+ }
+ }
+ }
+// else if ((pFuncArgs->Flags & ASYNC) && (lResult < TAPI_SUCCESS))
+// {
+// }
+
+DoFunc_return:
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "%s: result = %s",
+ pszFuncName,
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#endif
+
+ return lResult;
+}
+
+
+LONG
+LoadUIDll(
+ HWND hwndOwner,
+ DWORD dwWidgetID,
+ DWORD dwWidgetType,
+ HANDLE *phDll,
+ CHAR *pszTUISPI_xxx,
+ TUISPIPROC *ppfnTUISPI_xxx
+ )
+{
+ LONG lResult;
+ HANDLE hDll;
+ WCHAR szUIDllName[MAX_PATH];
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, xGetUIDllName),
+
+ {
+ (DWORD) dwWidgetID,
+ (DWORD) dwWidgetType,
+ (DWORD) szUIDllName,
+ (DWORD) MAX_PATH
+ },
+
+ {
+ Dword,
+ Dword,
+ lpGet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ if (hwndOwner && !IsWindow (hwndOwner))
+ {
+ lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
+ PHONEERR_INVALPARAM : LINEERR_INVALPARAM);
+
+ goto LoadUIDll_return;
+ }
+
+ if ((lResult = DOFUNC (&funcArgs, "GetUIDllName")) == 0)
+ {
+ if ((hDll = LoadLibraryW(szUIDllName)))
+ {
+ if ((*ppfnTUISPI_xxx = (TUISPIPROC) GetProcAddress(
+ hDll,
+ pszTUISPI_xxx
+ )))
+ {
+ *phDll = hDll;
+ lResult = 0;
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "LoadUIDll: GetProcAddress(%ls,%s) failed, err=%d",
+ szUIDllName,
+ pszTUISPI_xxx,
+ GetLastError()
+ ));
+
+ FreeLibrary (hDll);
+ lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
+ PHONEERR_OPERATIONUNAVAIL : LINEERR_OPERATIONUNAVAIL);
+ }
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "LoadLibraryW(%ls) failed, err=%d",
+ szUIDllName,
+ GetLastError()
+ ));
+
+ lResult = (dwWidgetType == TUISPIDLL_OBJECT_PHONEID ?
+ PHONEERR_OPERATIONFAILED : LINEERR_OPERATIONFAILED);
+ }
+ }
+
+LoadUIDll_return:
+
+ return lResult;
+}
+
+
+LONG
+PASCAL
+lineXxxProvider(
+ CHAR *pszTUISPI_providerXxx,
+ LPCWSTR 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;
+
+
+ if (bAddProvider && IsBadDwordPtr (lpdwPermProviderID))
+ {
+ DBGOUT((1, "Bad lpdwPermProviderID pointer"));
+ return LINEERR_INVALPOINTER;
+ }
+ else if (hwndOwner && !IsWindow (hwndOwner))
+ {
+ DBGOUT((1, "hwndOwner is not a window"));
+ return LINEERR_INVALPARAM;
+ }
+
+ {
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 7, xGetUIDllName),
+
+ {
+ (DWORD) (bAddProvider ? (DWORD) &dwPermProviderID :
+ dwPermProviderID),
+ (DWORD) TUISPIDLL_OBJECT_PROVIDERID,
+ (DWORD) szUIDllName,
+ (DWORD) MAX_PATH,
+ (DWORD) (bAddProvider ? (DWORD) lpszProviderFilename :
+ TAPI_NO_DATA),
+ (DWORD) (pszTUISPI_providerXxx==gszTUISPI_providerRemove ?1:0),
+ (DWORD) &htDlgInst
+ },
+
+ {
+ (bAddProvider ? lpDword : Dword),
+ Dword,
+ lpGet_SizeToFollow,
+ Size,
+ (bAddProvider ? lpszW : Dword),
+ Dword,
+ lpDword
+ }
+ };
+
+
+ if ((lResult = DOFUNC (&funcArgs,"lineXxxProvider/GetUIDllName")) != 0)
+ {
+ return lResult;
+ }
+ }
+
+ if ((hDll = LoadLibraryW(szUIDllName)))
+ {
+ if ((pfnTUISPI_providerXxx = (TUISPIPROC) GetProcAddress(
+ hDll,
+ pszTUISPI_providerXxx
+ )))
+ {
+ DBGOUT((3, "Calling %ls...", pszTUISPI_providerXxx));
+
+ lResult = (*pfnTUISPI_providerXxx)(
+ TUISPIDLLCallback,
+ hwndOwner,
+ dwPermProviderID
+ );
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "%ls: result = %s",
+ pszTUISPI_providerXxx,
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#endif
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "lineXxxProvider: GetProcAddr(%ls,%ls) failed, err=%d",
+ szUIDllName,
+ pszTUISPI_providerXxx,
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONUNAVAIL;
+ }
+
+ FreeLibrary (hDll);
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "lineXxxProvider: LoadLibraryW('%ls') failed, err=%d",
+ szUIDllName,
+ GetLastError()
+ ));
+
+ lResult = LINEERR_OPERATIONFAILED;
+ }
+
+ {
+ LONG lResult2;
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, xFreeDialogInstance),
+
+ {
+ (DWORD) htDlgInst,
+ (DWORD) 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;
+ }
+ }
+
+ 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);
+ }
+
+ case LINEINITIALIZEEXOPTION_USEEVENT:
+ case LINEINITIALIZEEXOPTION_USECOMPLETIONPORT:
+
+ break;
+
+ default:
+
+ if ( TAPI_VERSION2_0 == dwAPIVersion )
+ {
+ //
+ // This 2.0 app is nuts.
+ //
+ return (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
+ }
+ else
+ {
+ //
+ // This >2.0 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)),
+
+ {
+ (DWORD) phXxxApp,
+ (DWORD) hInstance,
+ (DWORD) 0, // pfnCallback, we subst pInitData in here
+ (DWORD) pszAppName,
+ (DWORD) pdwNumDevs,
+ (DWORD) 0, // pszModuleName
+ (DWORD) TAPI_VERSION1_0
+ },
+
+ {
+ lpDword,
+ Dword,
+ Dword,
+ lpszW,
+ lpDword,
+ lpszW,
+ Dword
+ }
+ };
+ WCHAR *pszModuleNamePathW = NULL;
+ LONG lResult;
+ BOOL bReleaseMutex = FALSE;
+ PINIT_DATA pInitData = (PINIT_DATA) NULL;
+
+
+ if (phXxxApp == (LPVOID) pdwNumDevs)
+ {
+ DBGOUT((3, "%s: error, lphApp == lpdwNumDevs", pszFuncName));
+ 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)
+ {
+ DBGOUT((
+ 1,
+ "%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) - 1, //local IsBadDwordPtr() hoses it
+ bLine,
+ pXxxInitExParams,
+ pfnCallback
+
+ )) != 0)
+ {
+ goto xxxInitialize_return;
+ }
+ }
+ else if (IsBadCodePtr ((FARPROC) pfnCallback))
+ {
+ DBGOUT((1, "%s: bad lpfnCallback", pszFuncName));
+ 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)
+ //
+
+ *pdwAPIVersion = funcArgs.Args[6] = TAPI_VERSION2_0;
+ }
+
+#pragma message("*** *** ***BUGBUG: Use MapHandle()...")
+ 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 );
+//<!
+//<! //#pragma message("*** *** ***BUGBUG: Use MapHandle()...")
+//<! // if (GetVersion() & 0x80000000)
+//<! // {
+//<! // //
+//<! // // We're on Win95 so zero the hi-word
+//<! // //
+//<! //
+//<! // ((DWORD) pfnCallback) &= 0x0000ffff;
+//<! // }
+//<!
+ if (GetVersion() & 0x80000000)
+ {
+ //
+ // We're on Win95 so zero the hi-word
+ //
+
+ ((DWORD) pfnCallback) &= 0x0000ffff;
+ }
+
+ if (!IsWindow ((HWND) pfnCallback))
+ {
+ //
+ // If here chances are it's a 32-bit app passing in a bad
+ // pfnCallback
+ //
+
+ DBGOUT((1, "%s: bad lpfnCallback", pszFuncName));
+ lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
+ goto xxxInitialize_return;
+ }
+
+ if (!ghWow32Dll &&
+
+ !(ghWow32Dll = LoadLibrary ("wow32.dll")))
+ {
+ DBGOUT((
+ 1,
+ "%s: LoadLib(wow32.dll) failed, err=%d",
+ pszFuncName,
+ GetLastError()
+ ));
+
+ lResult =
+ (bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
+ goto xxxInitialize_return;
+ }
+
+ if (!gpfnWOWGetVDMPointer &&
+
+ !(gpfnWOWGetVDMPointer = GetProcAddress(
+ ghWow32Dll,
+ "WOWGetVDMPointer"
+ )))
+ {
+ DBGOUT((
+ 1,
+ "%s: GetProcAddr(WOWGetVDMPointer) failed, err=%d",
+ pszFuncName,
+ GetLastError()
+ ));
+
+ lResult =
+ (bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
+ goto xxxInitialize_return;
+ }
+
+ gbNTVDMClient = TRUE;
+
+
+ //
+ // For 16-bit clients the module name will follow the app name
+ //
+
+ {
+// char *pszAppName2 = (char *) pszAppName;
+//
+//
+// for (; *pszAppName2; pszAppName2++);
+//
+// pszAppName2++;
+//
+// funcArgs.Args[5] = (DWORD) pszAppName2;
+
+ funcArgs.Args[5] = (DWORD) &(pszAppName[wcslen(pszAppName)+1]);
+
+ DBGOUT((
+ 11,
+ "FName='%ls', MName='%ls'",
+ pszAppName,
+ funcArgs.Args[5]
+ ));
+
+ }
+ }
+ else if (IsBadCodePtr ((FARPROC) pfnCallback))
+ {
+ //
+ // If here a 32-bit app is call line/phoneInitialize
+ //
+
+ DBGOUT((1, "%s: bad lpfnCallback", pszFuncName));
+ 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;
+ }
+
+ if ((dwLength = GetModuleFileNameW(
+ hInstance,
+ pszModuleNamePathW,
+ dwSize
+
+ )) == 0)
+ {
+ DBGOUT((
+ 3,
+ "%s: GetModuleFileName(x%x, ...) failed, err=%d",
+ pszFuncName,
+ hInstance,
+ GetLastError()
+ ));
+
+ lResult = (bLine ? LINEERR_INVALPARAM : PHONEERR_INVALPARAM);
+ goto xxxInitialize_cleanup;
+ }
+ else if (dwLength >= dwSize)
+ {
+ ClientFree (pszModuleNamePathW);
+ dwSize *= 2;
+ goto alloc_module_name_buf;
+ }
+
+ funcArgs.Args[5] = (DWORD) wcsrchr (pszModuleNamePathW, '\\') +
+ sizeof(WCHAR);
+
+ 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)
+ )))
+ {
+ 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.)
+ //
+
+ pInitData->dwInitOptions = (pXxxInitExParams ?
+ (pXxxInitExParams->dwOptions & AllInitExOptions2_0) :
+ LINEINITIALIZEEXOPTION_USEHIDDENWINDOW);
+
+
+ switch (pInitData->dwInitOptions)
+ {
+ 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;
+
+
+ //
+ // 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] = (DWORD) pInitData;
+
+
+ //
+ // BUGBUG Serialize all inits/shutdowns for now so we don't run in
+ // to problems w/ nuking the wrong AsyncEventsThread, losing
+ // async msgs, etc
+ //
+
+ WaitForSingleObject (ghInitMutex, INFINITE);
+
+ bReleaseMutex = TRUE;
+
+ lResult = DOFUNC (&funcArgs, pszFuncName);
+
+ // BUGBUG if we AV on var fill-in then we should call lineShutdown
+
+xxxInitialize_cleanup:
+
+ if (pszModuleNamePathW)
+ {
+ ClientFree (pszModuleNamePathW);
+ }
+
+ if (lResult == 0)
+ {
+ //
+ // Save the hLineApp returned by TAPISRV in our InitData struct,
+ // and give the app back a pointer to the InitData struct instead
+ //
+
+ pInitData->hXxxApp = *((HANDLE *) phXxxApp);
+
+ *((PINIT_DATA *) phXxxApp) = pInitData;
+
+
+ //
+ // If total number of init instances is 0 we need to start a
+ // new async events thread
+ //
+
+ 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(
+ "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(
+ "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++;
+ goto xxxInitialize_releaseMutex;
+ }
+
+ ClientFree (gpAsyncEventsThreadParams->pBuf);
+
+ DBGOUT((
+ 1,
+ "%s: CreateThread(AsyncEventsThread) " \
+ "failed, err=%d",
+ pszFuncName,
+ GetLastError()
+ ));
+ }
+
+ if (ghWow32Dll)
+ {
+ FreeLibrary (gpAsyncEventsThreadParams->hWow32);
+ }
+ }
+
+ FreeLibrary (gpAsyncEventsThreadParams->hTapi32);
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "%s: LoadLibrary('tapi32.dll') failed, err=%d",
+ pszFuncName,
+ GetLastError()
+ ));
+ }
+
+ ClientFree (gpAsyncEventsThreadParams);
+ }
+
+ gpAsyncEventsThreadParams = NULL;
+
+ lResult =
+ (bLine ? LINEERR_OPERATIONFAILED : PHONEERR_OPERATIONFAILED);
+ }
+ else
+ {
+ gdwNumInits++;
+ }
+ }
+
+ if (lResult != 0)
+ {
+ if (gbNTVDMClient && pInitData)
+ {
+ pInitData->hwnd = (HWND) NULL;
+ }
+
+ FreeInitData (pInitData);
+ }
+
+xxxInitialize_releaseMutex:
+
+ if (bReleaseMutex)
+ {
+ ReleaseMutex (ghInitMutex);
+ }
+
+xxxInitialize_return:
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "%s: exit, result=%s",
+ pszFuncName,
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#endif
+
+ return lResult;
+}
+
+
+//
+// --------------------------------- lineXxx ----------------------------------
+//
+
+LONG
+WINAPI
+lineAccept(
+ HCALL hCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lAccept),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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
+lineAddProviderW(
+ LPCWSTR lpszProviderFilename,
+ HWND hwndOwner,
+ LPDWORD lpdwPermanentProviderID
+ )
+{
+ DBGOUT((10, "Entering lineAddProvider"));
+ DBGOUT((11, " lpszProviderFilename=0x%08lx", lpszProviderFilename));
+
+ if ( IsBadStringPtrW(lpszProviderFilename, (UINT)-1) )
+ {
+ DBGOUT((1, "Bad lpszProviderFilename [0x%lx] passed to lineAddProviderW", lpszProviderFilename));
+ return( LINEERR_INVALPOINTER );
+ }
+
+ DBGOUT((12, " *lpszProviderFilename=[%ls]", lpszProviderFilename));
+ DBGOUT((11, " hwndOwner=0x%08lx", hwndOwner));
+ DBGOUT((11, " lpdwPermanentProviderID=0x%08lx", lpdwPermanentProviderID));
+
+
+
+ return (lineXxxProvider(
+ gszTUISPI_providerInstall, // funcName
+ lpszProviderFilename, // lpszProviderFilename
+ hwndOwner, // hwndOwner
+ 0, // dwPermProviderID
+ lpdwPermanentProviderID // lpdwPermProviderID
+ ));
+}
+
+
+LONG
+WINAPI
+lineAddProviderA(
+ LPCSTR lpszProviderFilename,
+ HWND hwndOwner,
+ LPDWORD lpdwPermanentProviderID
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+ DBGOUT((3, "lineAddProviderA: enter"));
+ DBGOUT((11, " lpszProviderFilename=0x%08lx", lpszProviderFilename));
+
+#if DBG
+ if (!IsBadStringPtrA(lpszProviderFilename, (UINT)-1) )
+ {
+ DBGOUT((12, " *lpszProviderFilename=[%s]", lpszProviderFilename));
+ }
+#endif
+
+ DBGOUT((11, " hwndOwner=0x%08lx", hwndOwner));
+ DBGOUT((11, " lpdwPermanentProviderID=0x%08lx", lpdwPermanentProviderID));
+
+
+ szTempPtr = NotSoWideStringToWideString (lpszProviderFilename, (DWORD) -1);
+
+ lResult = lineAddProviderW (szTempPtr, hwndOwner, lpdwPermanentProviderID);
+
+ if (szTempPtr)
+ {
+ ClientFree (szTempPtr);
+ }
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "lineAddProvider: result = %s",
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#endif
+
+ 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),
+
+ {
+ (DWORD) hConfCall ,
+ (DWORD) 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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) dwAgentExtensionIDIndex,
+ (DWORD) lpParams,
+ (DWORD) lpParams,
+ (DWORD) dwSize
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineAgentSpecific"));
+}
+
+
+LONG
+WINAPI
+lineAnswer(
+ HCALL hCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lAnswer),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpszDestAddress,
+ dwCountryCode
+ },
+
+ {
+ Dword,
+ lpszW,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineBlindTransfer"));
+}
+
+
+LONG
+WINAPI
+lineBlindTransferA(
+ HCALL hCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+
+ szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
+
+ 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
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 1, lClose),
+
+ {
+ (DWORD) hLine
+ },
+
+ {
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineClose"));
+}
+
+
+void
+PASCAL
+lineCompleteCallPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineCompleteCallPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwCompletionID = (DWORD) pMsg->dwParam3;
+ LPDWORD lpdwCompletionID = (LPDWORD) pMsg->dwParam4;
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPDWORD lpdwCompletionIDVDM = (LPDWORD) gpfnWOWGetVDMPointer (
+ (DWORD) lpdwCompletionID,
+ sizeof(DWORD),
+ TRUE // fProtectedMode
+ );
+
+
+ if (lpdwCompletionIDVDM)
+ {
+ *lpdwCompletionIDVDM = dwCompletionID;
+ }
+ else
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ *lpdwCompletionID = dwCompletionID;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineCompleteCall(
+ HCALL hCall,
+ LPDWORD lpdwCompletionID,
+ DWORD dwCompletionMode,
+ DWORD dwMessageID
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteCall),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineCompleteCallPostProcess),
+ (DWORD) hCall,
+ (DWORD) lpdwCompletionID,
+ dwCompletionMode,
+ dwMessageID
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineCompleteCall"));
+}
+
+
+LONG
+WINAPI
+lineCompleteTransfer(
+ HCALL hCall,
+ HCALL hConsultCall,
+ LPHCALL lphConfCall,
+ DWORD dwTransferMode
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lCompleteTransfer),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hCall,
+ (DWORD) hConsultCall,
+ (DWORD) lphConfCall,
+ (DWORD) dwTransferMode,
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword: lpDword),
+ Dword,
+ }
+ };
+
+
+ if (dwTransferMode == LINETRANSFERMODE_TRANSFER)
+ {
+ //
+ // lphCall should be ignored
+ //
+
+ funcArgs.Args[0] = 0; // (POSTPROCESSPROC) NULL;
+ funcArgs.ArgTypes[3] = Dword;
+ }
+
+ return (DOFUNC (&funcArgs, "lineCompleteTransfer"));
+}
+
+
+LONG
+WINAPI
+lineConfigDialogW(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ HANDLE hDll;
+ TUISPIPROC pfnTUISPI_lineConfigDialog;
+
+
+ if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, 256))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ if ((lResult = LoadUIDll(
+ hwndOwner,
+ dwDeviceID,
+ TUISPIDLL_OBJECT_LINEID,
+ &hDll,
+ gszTUISPI_lineConfigDialog,
+ &pfnTUISPI_lineConfigDialog
+
+ )) == 0)
+ {
+ DBGOUT((3, "Calling TUISPI_lineConfigDialog..."));
+
+ lResult = (*pfnTUISPI_lineConfigDialog)(
+ TUISPIDLLCallback,
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass
+ );
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "TUISPI_lineConfigDialog: result = %s",
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#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 && IsBadStringPtrW (lpszDeviceClass, (DWORD) -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)
+ {
+ DBGOUT((3, "Calling TUISPI_lineConfigDialogEdit..."));
+
+ lResult = (*pfnTUISPI_lineConfigDialogEdit)(
+ TUISPIDLLCallback,
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass,
+ lpDeviceConfigIn,
+ dwSize,
+ lpDeviceConfigOut
+ );
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "TUISPI_lineConfigDialogEdit: result = %s",
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#endif
+ FreeLibrary (hDll);
+ }
+
+lineConfigDialogEdit_return:
+
+ 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
+lineDeallocateCall(
+ HCALL hCall
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 1, lDeallocateCall),
+
+ {
+ (DWORD) hCall
+ },
+
+ {
+ Dword
+ }
+ };
+
+ DBGOUT((3, "lineDeallocateCall: enter on thread: 0x%08lx", GetCurrentThreadId()));
+ DBGOUT((4, " hCall = 0x%08lx", hCall));
+
+ return (DOFUNC (&funcArgs, "lineDeallocateCall"));
+}
+
+
+void
+PASCAL
+lineDevSpecificPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineDevSpecificPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPBYTE pParamsVDM = (LPBYTE) gpfnWOWGetVDMPointer(
+ (DWORD) pParams,
+ dwSize,
+ TRUE // fProtectedMode
+ );
+
+
+ if (pParamsVDM)
+ {
+ CopyMemory (pParamsVDM, (LPBYTE) (pMsg + 1), dwSize);
+ }
+ else
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineDevSpecific(
+ HLINE hLine,
+ DWORD dwAddressID,
+ HCALL hCall,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lDevSpecific),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ dwAddressID,
+ (DWORD) hCall,
+ (DWORD) lpParams, // pass the actual pointer (for post processing)
+ (DWORD) lpParams, // pass data
+ dwSize
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size,
+ }
+ };
+
+
+ if (gbNTVDMClient)
+ {
+ if (!gpfnWOWGetVDMPointer ||
+
+ !(funcArgs.Args[5] = gpfnWOWGetVDMPointer(
+ (DWORD) lpParams,
+ dwSize,
+ TRUE // fProtectedMode
+ )))
+ {
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ return (DOFUNC (&funcArgs, "lineDevSpecific"));
+}
+
+
+LONG
+WINAPI
+lineDevSpecificFeature(
+ HLINE hLine,
+ DWORD dwFeature,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lDevSpecificFeature),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ dwFeature,
+ (DWORD) lpParams, // pass the actual pointer (for post processing)
+ (DWORD) lpParams, // pass data
+ dwSize
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ if (gbNTVDMClient)
+ {
+ if (!gpfnWOWGetVDMPointer ||
+
+ !(funcArgs.Args[4] = gpfnWOWGetVDMPointer(
+ (DWORD) lpParams,
+ dwSize,
+ TRUE // fProtectedMode
+ )))
+ {
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+
+ return (DOFUNC (&funcArgs, "lineDevSpecificFeature"));
+}
+
+
+LONG
+WINAPI
+lineDialW(
+ HCALL hCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lDial),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpszDestAddress,
+ dwCountryCode
+ },
+
+ {
+ Dword,
+ lpszW,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineDial"));
+}
+
+
+LONG
+WINAPI
+lineDialA(
+ HCALL hCall,
+ LPCSTR lpszDestAddress,
+ DWORD dwCountryCode
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+
+ szTempPtr = NotSoWideStringToWideString (lpszDestAddress, (DWORD) -1);
+
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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, "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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ bAllAddresses,
+ dwAddressID,
+ (DWORD) lpForwardList,
+ dwNumRingsNoAnswer,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_Struct,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ 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;
+ }
+
+ return (DOFUNC (&funcArgs, "lineForwardW"));
+}
+
+
+// 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
+ )
+{
+ LPLINEFORWARDLIST lplfl;
+ LONG lResult;
+ DWORD n;
+ DWORD dwNewOffset;
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 9, lForward),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ (DWORD) bAllAddresses,
+ (DWORD) dwAddressID,
+ (DWORD) lpForwardList,
+ (DWORD) dwNumRingsNoAnswer,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP() // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_Struct,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ 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;
+ }
+
+
+ return (DOFUNC (&funcArgs, "lineForward"));
+}
+
+
+
+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
+ )
+{
+ DBGOUT((3, "lineGatherDigitsWPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam1 & (LINEGATHERTERM_BUFFERFULL | LINEGATHERTERM_CANCEL |
+ LINEGATHERTERM_TERMDIGIT | LINEGATHERTERM_INTERTIMEOUT))
+ {
+ LPSTR lpsDigits = (LPSTR) pMsg->dwParam2;
+ DWORD dwNumDigits = pMsg->dwParam4;
+
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPSTR lpsDigitsVDM = (LPSTR) gpfnWOWGetVDMPointer(
+ (DWORD) lpsDigits,
+ dwNumDigits * sizeof(WCHAR),
+ TRUE // fProtectedMode
+ );
+
+
+ if (lpsDigitsVDM)
+ {
+ CopyMemory(
+ lpsDigitsVDM,
+ pMsg + 1,
+ dwNumDigits * sizeof (WCHAR)
+ );
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ CopyMemory (lpsDigits, pMsg + 1, dwNumDigits * sizeof(WCHAR));
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ //
+ // Don't do anything if we GPF
+ //
+ }
+ }
+
+ pMsg->dwParam2 = pMsg->dwParam3 = 0;
+}
+
+
+LONG
+WINAPI
+lineGatherDigitsW(
+ HCALL hCall,
+ DWORD dwDigitModes,
+ LPWSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCWSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 8, lGatherDigits),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGatherDigitsWPostProcess),
+ (DWORD) hCall,
+ dwDigitModes,
+ (DWORD) lpsDigits,
+ dwNumDigits,
+ (DWORD) lpszTerminationDigits,
+ dwFirstDigitTimeout,
+ dwInterDigitTimeout
+ },
+
+ {
+ Dword,
+ Dword,
+ 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 (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
+ //
+
+ funcArgs.ArgTypes[5] = Dword;
+ funcArgs.Args[5] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineGatherDigits"));
+}
+
+
+void
+PASCAL
+lineGatherDigitsPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineGatherDigitsPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ {
+ LPSTR lpsDigits = (LPSTR) pMsg->dwParam2;
+ DWORD dwNumDigits = pMsg->dwParam4;
+
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPSTR lpsDigitsVDM = (LPSTR) gpfnWOWGetVDMPointer(
+ (DWORD) lpsDigits,
+ dwNumDigits * sizeof(WCHAR),
+ TRUE // fProtectedMode
+ );
+
+
+ if (lpsDigitsVDM)
+ {
+ WideCharToMultiByte(
+ GetACP(),
+ 0,
+ (LPCWSTR)(pMsg + 1),
+ dwNumDigits,
+ lpsDigitsVDM,
+ dwNumDigits,
+ NULL,
+ NULL
+ );
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ WideCharToMultiByte(
+ GetACP(),
+ 0,
+ (LPCWSTR)(pMsg + 1),
+ dwNumDigits,
+ lpsDigits,
+ dwNumDigits,
+ NULL,
+ NULL
+ );
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ //
+ // Don't do anything if we GPF
+ //
+ }
+ }
+
+ pMsg->dwParam2 = pMsg->dwParam2 = 0;
+}
+
+
+LONG
+WINAPI
+lineGatherDigitsA(
+ HCALL hCall,
+ DWORD dwDigitModes,
+ LPSTR lpsDigits,
+ DWORD dwNumDigits,
+ LPCSTR lpszTerminationDigits,
+ DWORD dwFirstDigitTimeout,
+ DWORD dwInterDigitTimeout
+ )
+{
+ LONG lResult;
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 8, lGatherDigits),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGatherDigitsPostProcess),
+ (DWORD) hCall,
+ dwDigitModes,
+ (DWORD) lpsDigits,
+ dwNumDigits,
+ 0, // (DWORD) lpszTerminationDigits,
+ dwFirstDigitTimeout,
+ dwInterDigitTimeout
+ },
+
+ {
+ Dword,
+ Dword,
+ 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
+ //
+
+ funcArgs.ArgTypes[5] = Dword;
+ funcArgs.Args[5] = TAPI_NO_DATA;
+ }
+ else
+ {
+ funcArgs.Args[5] = (DWORD) NotSoWideStringToWideString(
+ lpszTerminationDigits,
+ (DWORD) -1
+ );
+ }
+
+ lResult = (DOFUNC (&funcArgs, "lineGatherDigits"));
+
+ if ( funcArgs.Args[5] && (funcArgs.Args[5] != TAPI_NO_DATA) )
+ {
+ ClientFree( (LPVOID)funcArgs.Args[5] );
+ }
+
+ 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),
+
+ {
+ (DWORD) hCall,
+ dwDigitMode,
+ (DWORD) lpszDigits,
+ dwDuration,
+ 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),
+
+ {
+ (DWORD) hCall,
+ dwDigitMode,
+ 0, // (DWORD) lpszDigits,
+ dwDuration,
+ 0 // dwEndToEndID, remotesp only
+ },
+
+ {
+ Dword,
+ Dword,
+ lpszW,
+ Dword,
+ Dword
+ }
+ };
+
+
+ if (lpszDigits)
+ {
+ if (IsBadStringPtrA (lpszDigits, (DWORD) -1))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+ else if (!(funcArgs.Args[2] = (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ dwToneMode,
+ dwDuration,
+ dwNumTones,
+ TAPI_NO_DATA, // (DWORD) lpTones,
+ 0, // dwNumTones * sizeof(LINEGENERATETONE)
+ 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] = (DWORD) 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),
+
+ {
+ (DWORD) hLineApp,
+ dwDeviceID,
+ dwAddressID,
+ dwAPIVersion,
+ dwExtVersion,
+ (DWORD) lpAddressCaps
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+ if (
+ (IsBadWritePtr( lpAddressCaps, 4))
+ ||
+ (IsBadWritePtr( lpAddressCaps, lpAddressCaps->dwTotalSize))
+ )
+ {
+ DBGOUT((1, "lineGetAddressCaps: Bad lpAddressCaps: 0x%08lx",
+ lpAddressCaps));
+
+ return LINEERR_INVALPOINTER;
+ }
+
+ 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
+ );
+/*
+ BUGBUG Hold off on converting this, since the conversion to
+ multibyte of the various completion msgs may not yield
+ consistent sizes
+
+// WideStringToNotSoWideString(
+// (LPBYTE)lpAddressCaps,
+// &lpAddressCaps->dwCompletionMsgTextSize
+// );
+//
+// if (lpAddressCaps->dwCompletionMsgTextEntrySize)
+// {
+// lpAddressCaps->dwCompletionMsgTextEntrySize /= 2; // BUGBUG???
+// }
+*/
+ 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) lpdwAddressID,
+ dwAddressMode,
+ (DWORD) lpsAddress,
+ 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))
+ {
+ DBGOUT((1, "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),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ (DWORD) 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)) )
+ {
+ DBGOUT((1, "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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentActivityList, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentActivityList // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentActivityListW"));
+}
+
+
+void
+PASCAL
+lineGetAgentActivityListAPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineGetAgentActivityListAPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPLINEAGENTACTIVITYLIST lpAgentActivityList = (LPLINEAGENTACTIVITYLIST)
+ pMsg->dwParam3;
+
+
+ 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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineGetAgentActivityListA(
+ HLINE hLine,
+ DWORD dwAddressID,
+ LPLINEAGENTACTIVITYLIST lpAgentActivityList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentActivityList),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGetAgentActivityListAPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentActivityList, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentActivityList // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentActivityListA"));
+}
+
+
+LONG
+WINAPI
+lineGetAgentCapsW(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwAppAPIVersion,
+ LPLINEAGENTCAPS lpAgentCaps
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwAddressID,
+ (DWORD) dwAppAPIVersion,
+ (DWORD) lpAgentCaps, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentCaps // pass data
+ },
+
+ {
+ Dword,
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentCapsW"));
+}
+
+
+void
+PASCAL
+lineGetAgentCapsAPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineGetAgentCapsAPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPLINEAGENTCAPS lpAgentCaps = (LPLINEAGENTCAPS) pMsg->dwParam3;
+
+
+ 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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineGetAgentCapsA(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ DWORD dwAddressID,
+ DWORD dwAppAPIVersion,
+ LPLINEAGENTCAPS lpAgentCaps
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lGetAgentCaps),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGetAgentCapsAPostProcess),
+ (DWORD) hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) dwAddressID,
+ (DWORD) dwAppAPIVersion,
+ (DWORD) lpAgentCaps, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentCaps // pass data
+ },
+
+ {
+ Dword,
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentCapsA"));
+}
+
+
+LONG
+WINAPI
+lineGetAgentGroupListW(
+ HLINE hLine,
+ DWORD dwAddressID,
+ LPLINEAGENTGROUPLIST lpAgentGroupList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentGroupList, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentGroupList // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentGroupListW"));
+}
+
+
+void
+PASCAL
+lineGetAgentGroupListAPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineGetAgentGroupListAPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPLINEAGENTGROUPLIST lpAgentGroupList = (LPLINEAGENTGROUPLIST)
+ pMsg->dwParam3;
+
+
+ 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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineGetAgentGroupListA(
+ HLINE hLine,
+ DWORD dwAddressID,
+ LPLINEAGENTGROUPLIST lpAgentGroupList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentGroupList),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGetAgentGroupListAPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentGroupList, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentGroupList // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentGroupListA"));
+}
+
+
+LONG
+WINAPI
+lineGetAgentStatusW(
+ HLINE hLine,
+ DWORD dwAddressID,
+ LPLINEAGENTSTATUS lpAgentStatus
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineDevSpecificPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentStatus, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentStatus // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentStatusW"));
+}
+
+
+void
+PASCAL
+lineGetAgentStatusAPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineGetAgentStatusAPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPLINEAGENTSTATUS lpAgentStatus = (LPLINEAGENTSTATUS) pMsg->dwParam3;
+
+
+ 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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineGetAgentStatusA(
+ HLINE hLine,
+ DWORD dwAddressID,
+ LPLINEAGENTSTATUS lpAgentStatus
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lGetAgentStatus),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineGetAgentStatusAPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentStatus, // pass the actual ptr (for ppproc)
+ (DWORD) lpAgentStatus // pass data
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetAgentStatusA"));
+}
+
+
+LONG
+WINAPI
+lineGetAppPriorityW(
+ LPCWSTR lpszAppName,
+ DWORD dwMediaMode,
+ LPLINEEXTENSIONID lpExtensionID,
+ DWORD dwRequestMode,
+ LPVARSTRING lpExtensionName,
+ LPDWORD lpdwPriority
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 7, lGetAppPriority),
+
+ {
+ (DWORD) lpszAppName,
+ dwMediaMode,
+ 0,
+ 0,
+ dwRequestMode,
+ 0,
+ (DWORD) 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] = (DWORD) lpExtensionID;
+ funcArgs.ArgTypes[3] = Size;
+ funcArgs.Args[3] = sizeof (LINEEXTENSIONID);
+ funcArgs.ArgTypes[5] = lpGet_Struct;
+ funcArgs.Args[5] = (DWORD) lpExtensionName;
+ }
+
+ 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),
+
+ {
+ 0, // (DWORD) lpszAppName,
+ dwMediaMode,
+ 0,
+ 0,
+ dwRequestMode,
+ 0,
+ (DWORD) 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] = (DWORD) lpExtensionID;
+ funcArgs.ArgTypes[3] = Size;
+ funcArgs.Args[3] = sizeof (LINEEXTENSIONID);
+ funcArgs.ArgTypes[5] = lpGet_Struct;
+ funcArgs.Args[5] = (DWORD) lpExtensionName;
+ }
+
+ funcArgs.Args[0] = (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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->dwRedirectionIDSize)
+ );
+
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpCallStatus
+ },
+
+ {
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetCallStatus"));
+}
+
+
+LONG
+WINAPI
+lineGetConfRelatedCalls(
+ HCALL hCall,
+ LPLINECALLLIST lpCallList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC| 2, lGetConfRelatedCalls),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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),
+
+ {
+ dwCountryID,
+ dwAPIVersion,
+ 0,
+ (DWORD) lpLineCountryList
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+
+ if (
+ ( TAPI_CURRENT_VERSION != dwAPIVersion )
+ &&
+ ( 0x00010004 != dwAPIVersion )
+ &&
+ ( 0x00010003 != dwAPIVersion )
+ )
+ {
+ DBGOUT((1, "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
+ )
+{
+ return lineGetCountryA(
+ dwCountryID,
+ dwAPIVersion,
+ lpLineCountryList
+ );
+}
+
+
+LONG
+WINAPI
+lineGetDevCapsW(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ DWORD dwAPIVersion,
+ DWORD dwExtVersion,
+ LPLINEDEVCAPS lpLineDevCaps
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 5, lGetDevCaps),
+
+ {
+ (DWORD) hLineApp,
+ dwDeviceID,
+ dwAPIVersion,
+ dwExtVersion,
+ (DWORD) lpLineDevCaps
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetDevCaps"));
+}
+
+
+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)
+ {
+ 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); // BUGBUG???
+ }
+
+ 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),
+
+ {
+ dwDeviceID,
+ (DWORD) lpDeviceConfig,
+ (DWORD) lpszDeviceClass
+ },
+
+ {
+ Dword,
+ lpGet_Struct,
+ lpszW
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetDevConfig"));
+}
+
+
+LONG
+WINAPI
+lineGetDevConfigA(
+ DWORD dwDeviceID,
+ LPVARSTRING lpDeviceConfig,
+ LPCSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lGetDevConfig),
+
+ {
+ dwDeviceID,
+ (DWORD) lpDeviceConfig,
+ 0 // (DWORD) lpszDeviceClass
+ },
+
+ {
+ Dword,
+ lpGet_Struct,
+ lpszW
+ }
+ };
+
+
+ funcArgs.Args[2] = (DWORD) 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
+lineGetIconW(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ HICON hIcon;
+ LONG lResult;
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lGetIcon),
+
+ {
+ dwDeviceID,
+ (DWORD) lpszDeviceClass,
+ (DWORD) &hIcon
+ },
+
+ {
+ Dword,
+ lpszW,
+ lpDword
+ }
+ };
+
+
+ if (IsBadDwordPtr ((LPDWORD) lphIcon))
+ {
+ DBGOUT((1, "lphIcon is an invalid pointer!"));
+ 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;
+ }
+
+ if ((lResult = DOFUNC (&funcArgs, "lineGetIcon")) == 0)
+ {
+ if (gbNTVDMClient == FALSE)
+ {
+ *lphIcon = hIcon;
+ }
+ else
+ {
+// BUGBUG lineGetIcon: map 32-bit hIcon to 16-bit
+ }
+ }
+
+ return lResult;
+}
+
+
+
+LONG
+WINAPI
+lineGetIconA(
+ DWORD dwDeviceID,
+ LPCSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+
+ if (lpszDeviceClass && IsBadStringPtrA (lpszDeviceClass, (DWORD) -1))
+ {
+ 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),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ (DWORD) hCall,
+ dwSelect,
+ (DWORD) lpDeviceID,
+ (DWORD) lpszDeviceClass
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct,
+ lpszW
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetID"));
+}
+
+
+LONG
+WINAPI
+lineGetIDA(
+ HLINE hLine,
+ DWORD dwAddressID,
+ HCALL hCall,
+ DWORD dwSelect,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+
+ szTempPtr = NotSoWideStringToWideString (lpszDeviceClass, (DWORD) -1);
+
+ lResult = lineGetIDW(
+ hLine,
+ dwAddressID,
+ hCall,
+ dwSelect,
+ lpDeviceID,
+ szTempPtr
+ );
+
+ if (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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) lpLineDevStatus,
+ (DWORD) &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, (PINIT_DATA) hLineApp, lpMessage, dwTimeout));
+}
+
+
+LONG
+WINAPI
+lineGetNewCalls(
+ HLINE hLine,
+ DWORD dwAddressID,
+ DWORD dwSelect,
+ LPLINECALLLIST lpCallList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, lGetNewCalls),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ dwSelect,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ (DWORD) lpdwNumRings
+ },
+
+ {
+ Dword,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetNumRings"));
+}
+
+
+LONG
+WINAPI
+lineGetProviderListW(
+ DWORD dwAPIVersion,
+ LPLINEPROVIDERLIST lpProviderList
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lGetProviderList),
+
+ {
+ dwAPIVersion,
+ (DWORD) lpProviderList
+ },
+
+ {
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineGetProviderList"));
+}
+
+
+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
+lineGetRequestW(
+ HLINEAPP hLineApp,
+ DWORD dwRequestMode,
+ LPVOID lpRequestBuffer
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
+
+ {
+ (DWORD) hLineApp,
+ dwRequestMode,
+ (DWORD) lpRequestBuffer,
+ 0
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ lpGet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
+ {
+ //
+ // Set the size param appropriately
+ //
+
+ funcArgs.Args[3] = sizeof(LINEREQMAKECALLW);
+ }
+ else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
+ {
+ //
+ // Set the size param appropriately
+ //
+
+ funcArgs.Args[3] = sizeof(LINEREQMEDIACALLW);
+ }
+
+ return (DOFUNC (&funcArgs, "lineGetRequest"));
+}
+
+
+LONG
+WINAPI
+lineGetRequestA(
+ HLINEAPP hLineApp,
+ DWORD dwRequestMode,
+ LPVOID lpRequestBuffer
+ )
+{
+ LONG lResult;
+ LPVOID szTempPtr;
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 4, lGetRequest),
+
+ {
+ (DWORD) hLineApp,
+ dwRequestMode,
+ 0, // (DWORD) lpRequestBuffer,
+ 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] = sizeof(LINEREQMAKECALLW);
+
+ szTempPtr = ClientAlloc( sizeof(LINEREQMAKECALLW) );
+ }
+ else if (dwRequestMode == LINEREQUESTMODE_MEDIACALL)
+ {
+ //
+ // Set the size param appropriately
+ //
+
+ funcArgs.Args[3] = sizeof(LINEREQMEDIACALLW);
+
+ szTempPtr = ClientAlloc( sizeof(LINEREQMEDIACALLW) );
+ }
+
+ funcArgs.Args[2] = (DWORD)szTempPtr;
+
+
+ lResult = (DOFUNC (&funcArgs, "lineGetRequest"));
+
+
+ if ( 0 == lResult )
+ {
+ if (dwRequestMode == LINEREQUESTMODE_MAKECALL)
+ {
+ LPLINEREQMAKECALLW lplrmc = szTempPtr;
+
+ 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];
+//}
+
+ }
+ }
+
+
+ ClientFree( (LPVOID)funcArgs.Args[2] );
+
+ 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) lpdwLineStates,
+ (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpszFileName,
+ 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] = 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),
+
+ {
+ (DWORD) 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))
+ {
+ DBGOUT((1, "lineInitialize: Bad lpszAddName pointer"));
+ return LINEERR_INVALPOINTER;
+ }
+
+ szTempPtr = NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
+ }
+ else
+ {
+ szTempPtr = NULL;
+ }
+
+
+ lResult = (xxxInitialize(
+ TRUE,
+ (LPVOID) lphLineApp,
+ hInstance,
+ lpfnCallback,
+ szTempPtr,
+ lpdwNumDevs,
+ NULL,
+ NULL
+#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))
+ {
+ DBGOUT((
+ 1,
+ "lineInitializeExW: bad lpdwAPIVersion pointer (x%x)",
+ 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))
+ {
+ DBGOUT((
+ 1,
+ "lineInitializeEx: bad lpszFriendlyAppName (x%x)",
+ 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
+ )
+{
+ DBGOUT((3, "lineMakeCallPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ HCALL hCall = (HCALL) pMsg->dwParam3;
+ LPHCALL lphCall = (LPHCALL) pMsg->dwParam4;
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPHCALL lphCallVDM = (LPHCALL) gpfnWOWGetVDMPointer (
+ (DWORD) lphCall,
+ sizeof(HCALL),
+ TRUE // fProtectedMode
+ );
+
+
+ if (lphCallVDM)
+ {
+ *lphCallVDM = hCall;
+ }
+ else
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ *lphCall = hCall;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+
+ // BUGBUG drop/dealloc
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineMakeCallW(
+ HLINE hLine,
+ LPHCALL lphCall,
+ LPCWSTR lpszDestAddress,
+ DWORD dwCountryCode,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 7, lMakeCall),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ (DWORD) lphCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) dwCountryCode,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpszW,
+ Dword,
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpszDestAddress)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineMakeCall"));
+}
+
+
+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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ (DWORD) lphCall,
+ (DWORD) 0,
+ (DWORD) dwCountryCode,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP() // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpszW,
+ Dword,
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpszDestAddress)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = TAPI_NO_DATA;
+ }
+ else if (IsBadStringPtrA (lpszDestAddress, (DWORD) -1))
+ {
+ DBGOUT((1, "lineMakeCall: Bad lpszDestAddress pointer"));
+ return LINEERR_INVALPOINTER;
+ }
+ else if (!(funcArgs.Args[3] = (DWORD) NotSoWideStringToWideString(
+ lpszDestAddress,
+ (DWORD) -1
+ )))
+ {
+ return LINEERR_OPERATIONFAILED; // really either NOMEM. INVALPOINTER
+ }
+
+ if (!lpCallParams)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[5] = Dword;
+ funcArgs.Args[5] = TAPI_NO_DATA;
+ }
+
+ lResult = DOFUNC (&funcArgs, "lineMakeCall");
+
+ if (funcArgs.Args[3] != 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),
+
+ {
+ (DWORD) hCall,
+ dwDigitModes
+ },
+
+ {
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineMonitorDigits"));
+}
+
+
+LONG
+WINAPI
+lineMonitorMedia(
+ HCALL hCall,
+ DWORD dwMediaModes
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 2, lMonitorMedia),
+
+ {
+ (DWORD) hCall,
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpToneList,
+ dwNumEntries * sizeof(LINEMONITORTONE),
+ 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] = 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),
+
+ {
+ (DWORD) hLineApp,
+ dwDeviceID,
+ dwAPILowVersion,
+ dwAPIHighVersion,
+ (DWORD) lpdwAPIVersion,
+ (DWORD) lpExtensionID,
+ (DWORD) sizeof(LINEEXTENSIONID)
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ lpDword,
+ lpGet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ 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),
+
+ {
+ (DWORD) hLineApp,
+ dwDeviceID,
+ dwAPIVersion,
+ dwExtLowVersion,
+ dwExtHighVersion,
+ (DWORD) lpdwExtVersion
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineNegotiateExtVersion"));
+}
+
+
+LONG
+WINAPI
+lineOpenW(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ LPHLINE lphLine,
+ DWORD dwAPIVersion,
+ DWORD dwExtVersion,
+ DWORD dwCallbackInstance,
+ DWORD dwPrivileges,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
+
+ {
+ (DWORD) hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) lphLine,
+ (DWORD) dwAPIVersion,
+ (DWORD) dwExtVersion,
+ (DWORD) dwCallbackInstance,
+ (DWORD) dwPrivileges,
+ (DWORD) dwMediaModes,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff, // dwAsciiCallParamsCodePage
+ 0 // LINEOPEN_PARAMS.hRemoteLine
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ lpDword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_Struct,
+ Dword,
+ Dword
+ }
+ };
+
+
+ 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineOpen"));
+}
+
+
+LONG
+WINAPI
+lineOpenA(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ LPHLINE lphLine,
+ DWORD dwAPIVersion,
+ DWORD dwExtVersion,
+ DWORD dwCallbackInstance,
+ DWORD dwPrivileges,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 11, lOpen),
+
+ {
+ (DWORD) hLineApp,
+ (DWORD) dwDeviceID,
+ (DWORD) lphLine,
+ (DWORD) dwAPIVersion,
+ (DWORD) dwExtVersion,
+ (DWORD) dwCallbackInstance,
+ (DWORD) dwPrivileges,
+ (DWORD) dwMediaModes,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP(), // dwAsciiCallParamsCodePage
+ (DWORD) 0 // LINEOPEN_PARAMS.hRemoteLine
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ lpDword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpSet_Struct,
+ Dword,
+ Dword
+ }
+ };
+
+
+ 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineOpen"));
+}
+
+
+LONG
+WINAPI
+lineOpen(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ LPHLINE lphLine,
+ DWORD dwAPIVersion,
+ DWORD dwExtVersion,
+ DWORD dwCallbackInstance,
+ DWORD dwPrivileges,
+ DWORD dwMediaModes,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ return lineOpenA(
+ hLineApp,
+ dwDeviceID,
+ lphLine,
+ dwAPIVersion,
+ dwExtVersion,
+ dwCallbackInstance,
+ dwPrivileges,
+ dwMediaModes,
+ lpCallParams
+ );
+}
+
+
+void
+PASCAL
+lineParkAPostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineParkAPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPVARSTRING pNonDirAddress = (LPVARSTRING) pMsg->dwParam3;
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ 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)
+ {
+ char *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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ CopyMemory (pNonDirAddress, (LPBYTE) (pMsg + 1), dwSize);
+
+ if (pNonDirAddress->dwUsedSize >= sizeof (VARSTRING) &&
+ pNonDirAddress->dwStringSize != 0)
+ {
+ char *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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+lineParkW(
+ HCALL hCall,
+ DWORD dwParkMode,
+ LPCWSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
+
+ {
+ (DWORD) 0, // post process proc
+ (DWORD) hCall,
+ (DWORD) dwParkMode,
+ (DWORD) TAPI_NO_DATA, //lpszDirAddress,
+ (DWORD) lpNonDirAddress, // pass ptr as Dword for post processing
+ (DWORD) TAPI_NO_DATA, //lpNonDirAddress // pass ptr as lpGet_Xx for IsValPtr chk
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword, // lpszW,
+ Dword,
+ Dword, // lpGet_Struct
+ }
+ };
+
+
+ if (dwParkMode == LINEPARKMODE_DIRECTED)
+ {
+ funcArgs.ArgTypes[3] = lpszW;
+ funcArgs.Args[3] = (DWORD) lpszDirAddress;
+ }
+ else if (dwParkMode == LINEPARKMODE_NONDIRECTED)
+ {
+ //
+ // Set post process proc
+ //
+
+ funcArgs.Args[0] = (DWORD)
+ ((POSTPROCESSPROC) lineDevSpecificPostProcess);
+
+ funcArgs.ArgTypes[5] = lpGet_Struct;
+ funcArgs.Args[5] = (DWORD) lpNonDirAddress;
+ }
+
+ return (DOFUNC (&funcArgs, "linePark"));
+}
+
+
+LONG
+WINAPI
+lineParkA(
+ HCALL hCall,
+ DWORD dwParkMode,
+ LPCSTR lpszDirAddress,
+ LPVARSTRING lpNonDirAddress
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 6, lPark),
+
+ {
+ (DWORD) 0, // post process proc
+ (DWORD) hCall,
+ (DWORD) dwParkMode,
+ (DWORD) TAPI_NO_DATA, // lpszDirAddress,
+ (DWORD) lpNonDirAddress, // pass ptr as Dword for post processing
+ (DWORD) 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;
+
+
+ if (dwParkMode == LINEPARKMODE_DIRECTED)
+ {
+ if (IsBadStringPtrA (lpszDirAddress, (DWORD) -1))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ szTempPtr = NotSoWideStringToWideString (lpszDirAddress, (DWORD) -1);
+ funcArgs.ArgTypes[3] = lpszW;
+ funcArgs.Args[3] = (DWORD) szTempPtr;
+ }
+ else
+ {
+ if (dwParkMode == LINEPARKMODE_NONDIRECTED)
+ {
+ //
+ // Set post process proc
+ //
+
+ funcArgs.Args[0] = (DWORD)((POSTPROCESSPROC) lineParkAPostProcess);
+ funcArgs.ArgTypes[5] = lpGet_Struct;
+
+ if (gbNTVDMClient == FALSE)
+ {
+ funcArgs.Args[5] = (DWORD) lpNonDirAddress;
+ }
+ else
+ {
+ if (!gpfnWOWGetVDMPointer ||
+
+ !(funcArgs.Args[5] = gpfnWOWGetVDMPointer(
+ (DWORD) lpNonDirAddress,
+ sizeof (VARSTRING), // what if it's > sizeof(VARS)?
+ TRUE // fProtectedMode
+ )))
+ {
+ return LINEERR_OPERATIONFAILED;
+ }
+ }
+ }
+
+ szTempPtr = NULL;
+ }
+
+ lResult = (DOFUNC (&funcArgs, "linePark"));
+
+ 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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lphCall,
+ (DWORD) lpszDestAddress,
+ (DWORD) lpszGroupID
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpszW,
+ lpszW
+ }
+ };
+
+
+ if (!lpszDestAddress)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[4] = Dword;
+ funcArgs.Args[4] = 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "linePickup"));
+}
+
+
+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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hConfCall,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpCallParams)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "linePrepareAddToConferenceW"));
+}
+
+
+LONG
+WINAPI
+linePrepareAddToConferenceA(
+ HCALL hConfCall,
+ LPHCALL lphConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lPrepareAddToConference),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hConfCall,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP() // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpCallParams)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "linePrepareAddToConference"));
+}
+
+
+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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) hCall,
+ (DWORD) dwMsg,
+ (DWORD) dwParam1,
+ (DWORD) dwParam2,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) 0,
+ (DWORD) lpProxyRequest,
+ (DWORD) 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 ((DWORD) pProxyRequestHeader & 0x7 ||
+ pProxyRequestHeader->dwKey != TPROXYREQUESTHEADER_KEY)
+ {
+ lResult = LINEERR_INVALPOINTER;
+ }
+
+ pProxyRequestHeader->dwKey = 0xefefefef;
+
+ funcArgs.Args[1] = 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:
+
+ funcArgs.Args[2] = TAPI_NO_DATA;
+ funcArgs.ArgTypes[2] = Dword;
+
+ break;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpszDestAddress,
+ 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),
+
+ {
+ (DWORD) hLineApp,
+ dwRegistrationInstance,
+ dwRequestMode,
+ bEnable
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineRegisterRequestRecipient"));
+}
+
+
+LONG
+WINAPI
+lineReleaseUserUserInfo(
+ HCALL hCall
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 1, lReleaseUserUserInfo),
+
+ {
+ (DWORD) hCall
+ },
+
+ {
+ Dword,
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineReleaseUserUserInfo"));
+}
+
+
+LONG
+WINAPI
+lineRemoveFromConference(
+ HCALL hCall
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 1, lRemoveFromConference),
+
+ {
+ (DWORD) 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),
+
+ {
+ (DWORD) hCall
+ },
+
+ {
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineSecureCall"));
+}
+
+
+LONG
+WINAPI
+lineSendUserUserInfo(
+ HCALL hCall,
+ LPCSTR lpsUserUserInfo,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lSendUserUserInfo),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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, "lineSendUserUserInfo"));
+}
+
+
+LONG
+WINAPI
+lineSetAgentActivity(
+ HLINE hLine,
+ DWORD dwAddressID,
+ DWORD dwActivityID
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 3, lSetAgentActivity),
+
+ {
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lpAgentGroupList
+ },
+
+ {
+ Dword,
+ Dword,
+ lpSet_Struct
+ }
+ };
+
+
+ if (!lpAgentGroupList)
+ {
+ funcArgs.Args[2] = (DWORD) &EmptyGroupList;
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetAgentGroup"));
+}
+
+
+LONG
+WINAPI
+lineSetAgentState(
+ HLINE hLine,
+ DWORD dwAddressID,
+ DWORD dwAgentState,
+ DWORD dwNextAgentState
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 4, lSetAgentState),
+
+ {
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) dwAgentState,
+ (DWORD) dwNextAgentState
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineSetAgentState"));
+}
+
+
+LONG
+WINAPI
+lineSetAppPriorityW(
+ LPCWSTR lpszAppName,
+ DWORD dwMediaMode,
+ LPLINEEXTENSIONID lpExtensionID,
+ DWORD dwRequestMode,
+ LPCWSTR lpszExtensionName,
+ DWORD dwPriority
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 7, lSetAppPriority),
+
+ {
+ (DWORD) lpszAppName,
+ dwMediaMode,
+ (DWORD) TAPI_NO_DATA, // (DWORD) lpExtensionID,
+ 0, // (DWORD) sizeof(LINEEXTENSIONID),
+ dwRequestMode,
+ (DWORD) TAPI_NO_DATA, // (DWORD) lpszExtensionName,
+ dwPriority
+ },
+
+ {
+ lpszW,
+ Dword,
+ Dword, // lpSet_SizeToFollow,
+ Dword, // Size,
+ Dword,
+ Dword, // lpsz,
+ Dword
+ }
+ };
+
+
+ if (dwMediaMode & 0xff000000)
+ {
+ //
+ // Reset lpExtensionID (& following Size) Arg & ArgType
+ // since it's a valid param in this case
+ //
+
+ funcArgs.ArgTypes[2] = lpSet_SizeToFollow;
+ funcArgs.Args[2] = (DWORD) lpExtensionID;
+ funcArgs.ArgTypes[3] = Size;
+ funcArgs.Args[3] = sizeof(LINEEXTENSIONID);
+
+ if (lpszExtensionName)
+ {
+ //
+ // Reset lpszExtensionName Arg & ArgType since it's
+ // a valid param in this case
+ //
+
+ funcArgs.ArgTypes[5] = lpszW;
+ funcArgs.Args[5] = (DWORD) lpszExtensionName;
+ }
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetAppPriority"));
+}
+
+
+LONG
+WINAPI
+lineSetAppPriorityA(
+ LPCSTR lpszAppName,
+ DWORD dwMediaMode,
+ LPLINEEXTENSIONID lpExtensionID,
+ DWORD dwRequestMode,
+ LPCSTR lpszExtensionName,
+ DWORD dwPriority
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+ PWSTR szTempPtr2;
+
+
+ if (IsBadStringPtrA (lpszAppName, (DWORD) -1) ||
+ ((dwMediaMode & 0xff000000) && lpszExtensionName &&
+ IsBadStringPtrA (lpszExtensionName, (DWORD) -1)))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ szTempPtr = NotSoWideStringToWideString (lpszAppName, (DWORD) -1);
+ szTempPtr2 = NotSoWideStringToWideString (lpszExtensionName, (DWORD) -1);
+
+ lResult = lineSetAppPriorityW(
+ szTempPtr,
+ dwMediaMode,
+ lpExtensionID,
+ dwRequestMode,
+ szTempPtr2,
+ dwPriority
+ );
+
+ if (szTempPtr)
+ {
+ ClientFree (szTempPtr);
+ }
+
+ if (szTempPtr2)
+ {
+ ClientFree (szTempPtr2);
+ }
+
+ 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),
+
+ {
+ (DWORD) hCall,
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpCallData,
+ (DWORD) dwSize
+ },
+
+ {
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ if (dwSize == 0)
+ {
+ funcArgs.Args[1] = 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),
+
+ {
+ (DWORD) hCall,
+ dwBearerMode,
+ dwMinRate,
+ dwMaxRate,
+ (DWORD) lpDialParams,
+ 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] = 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),
+
+ {
+ (DWORD) hCall,
+ 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) lpSendingFlowspec,
+ (DWORD) dwSendingFlowspecSize,
+ (DWORD) lpReceivingFlowspec,
+ (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ (DWORD) 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),
+
+ {
+ dwDeviceID,
+ (DWORD) lpDeviceConfig,
+ dwSize,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) dwStatusToChange,
+ (DWORD) 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),
+
+ {
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) hCall,
+ (DWORD) dwSelect,
+ (DWORD) TAPI_NO_DATA,
+ (DWORD) dwDigitNumEntries * sizeof(LINEMEDIACONTROLDIGIT),
+ (DWORD) TAPI_NO_DATA,
+ (DWORD) dwMediaNumEntries * sizeof(LINEMEDIACONTROLMEDIA),
+ (DWORD) TAPI_NO_DATA,
+ (DWORD) dwToneNumEntries * sizeof(LINEMEDIACONTROLTONE),
+ (DWORD) TAPI_NO_DATA,
+ (DWORD) 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] = (DWORD) lpDigitList;
+ funcArgs.ArgTypes[5] = Size;
+ }
+
+ if (lpMediaList)
+ {
+ if (dwMediaNumEntries >
+ (0x1000000 / sizeof (LINEMEDIACONTROLMEDIA)))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ funcArgs.ArgTypes[6] = lpSet_SizeToFollow;
+ funcArgs.Args[6] = (DWORD) lpMediaList;
+ funcArgs.ArgTypes[7] = Size;
+ }
+
+ if (lpToneList)
+ {
+ if (dwToneNumEntries >
+ (0x1000000 / sizeof (LINEMEDIACONTROLTONE)))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ funcArgs.ArgTypes[8] = lpSet_SizeToFollow;
+ funcArgs.Args[8] = (DWORD) lpToneList;
+ funcArgs.ArgTypes[9] = Size;
+ }
+
+ if (lpCallStateList)
+ {
+ if (dwCallStateNumEntries >
+ (0x1000000 / sizeof (LINEMEDIACONTROLCALLSTATE)))
+ {
+ return LINEERR_INVALPOINTER;
+ }
+
+ funcArgs.ArgTypes[10] = lpSet_SizeToFollow;
+ funcArgs.Args[10] = (DWORD) 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),
+
+ {
+ (DWORD) hCall,
+ 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),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ dwNumRings
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineSetNumRings"));
+}
+
+
+LONG
+WINAPI
+lineSetStatusMessages(
+ HLINE hLine,
+ DWORD dwLineStates,
+ DWORD dwAddressStates
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 3, lSetStatusMessages),
+
+ {
+ (DWORD) hLine,
+ dwLineStates,
+ 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),
+
+ {
+ (DWORD) hLine,
+ dwAddressID,
+ (DWORD) hCall,
+ dwSelect,
+ dwTerminalModes,
+ dwTerminalID,
+ bEnable
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineSetTerminal"));
+}
+
+
+void
+PASCAL
+lineSetupConferencePostProcess(
+ PASYNCEVENTMSG pMsg
+ )
+{
+ DBGOUT((3, "lineSetupConfPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ HCALL hConfCall = (HCALL) pMsg->dwParam3,
+ hConsultCall = (HCALL) *(&pMsg->dwParam4 + 1);
+ LPHCALL lphConfCall = (LPHCALL) pMsg->dwParam4,
+ lphConsultCall = (LPHCALL) *(&pMsg->dwParam4 + 2);
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ 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->dwParam2 = LINEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ *lphConfCall = hConfCall;
+ *lphConsultCall = hConsultCall;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ pMsg->dwParam2 = LINEERR_INVALPOINTER;
+
+ // BUGBUG drop/dealloc
+ }
+ }
+}
+
+
+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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineSetupConferencePostProcess),
+ (DWORD) hCall,
+ (DWORD) hLine,
+ (DWORD) lphConfCall,
+ (DWORD) lphConsultCall,
+ (DWORD) dwNumParties,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ (gbNTVDMClient ? Dword : lpDword),
+ Dword,
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetupConferenceW"));
+}
+
+
+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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineSetupConferencePostProcess),
+ (DWORD) hCall,
+ (DWORD) hLine,
+ (DWORD) lphConfCall,
+ (DWORD) lphConsultCall,
+ (DWORD) dwNumParties,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP() // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ (gbNTVDMClient ? Dword : lpDword),
+ Dword,
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ 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] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetupConference"));
+}
+
+
+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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hCall,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) 0xffffffff // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpCallParams)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetupTransferW"));
+}
+
+
+LONG
+WINAPI
+lineSetupTransferA(
+ HCALL hCall,
+ LPHCALL lphConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 5, lSetupTransfer),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hCall,
+ (DWORD) lphConsultCall,
+ (DWORD) lpCallParams,
+ (DWORD) GetACP() // dwAsciiCallParamsCodePage
+ },
+
+ {
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpSet_Struct,
+ Dword
+ }
+ };
+
+
+ if (!lpCallParams)
+ {
+ //
+ // Reset Arg & ArgType so no inval ptr err, & TAPI_NO_DATA is indicated
+ //
+
+ funcArgs.ArgTypes[3] = Dword;
+ funcArgs.Args[3] = TAPI_NO_DATA;
+ }
+
+ return (DOFUNC (&funcArgs, "lineSetupTransferW"));
+}
+
+
+LONG
+WINAPI
+lineSetupTransfer(
+ HCALL hCall,
+ LPHCALL lphConsultCall,
+ LPLINECALLPARAMS const lpCallParams
+ )
+{
+ return lineSetupTransferA(
+ hCall,
+ lphConsultCall,
+ lpCallParams
+ );
+}
+
+
+LONG
+WINAPI
+lineShutdown(
+ HLINEAPP hLineApp
+ )
+{
+ return (xxxShutdown ((DWORD) hLineApp, TRUE));
+}
+
+
+LONG
+WINAPI
+lineSwapHold(
+ HCALL hActiveCall,
+ HCALL hHeldCall
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lSwapHold),
+
+ {
+ (DWORD) hActiveCall,
+ (DWORD) hHeldCall
+ },
+
+ {
+ Dword,
+ Dword
+ }
+ };
+
+ return (DOFUNC (&funcArgs, "lineSwapHold"));
+}
+
+
+LONG
+WINAPI
+lineUncompleteCall(
+ HLINE hLine,
+ DWORD dwCompletionID
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 2, lUncompleteCall),
+
+ {
+ (DWORD) hLine,
+ dwCompletionID
+ },
+
+ {
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineUncompleteCall"));
+}
+
+
+LONG
+WINAPI
+lineUnhold(
+ HCALL hCall
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | ASYNC | 1, lUnhold),
+
+ {
+ (DWORD) 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),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) lineMakeCallPostProcess),
+ (DWORD) hLine,
+ (DWORD) dwAddressID,
+ (DWORD) lphCall,
+ (DWORD) lpszDestAddress
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ (gbNTVDMClient ? Dword : lpDword),
+ lpszW
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "lineUnpark"));
+}
+
+
+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
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 1, pClose),
+
+ {
+ (DWORD) hPhone
+ },
+
+ {
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneClose"));
+}
+
+
+LONG
+WINAPI
+phoneConfigDialogW(
+ DWORD dwDeviceID,
+ HWND hwndOwner,
+ LPCWSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ HANDLE hDll;
+ TUISPIPROC pfnTUISPI_phoneConfigDialog;
+
+
+ if (lpszDeviceClass && IsBadStringPtrW (lpszDeviceClass, (DWORD) -1))
+ {
+ return PHONEERR_INVALPOINTER;
+ }
+
+ if ((lResult = LoadUIDll(
+ hwndOwner,
+ dwDeviceID,
+ TUISPIDLL_OBJECT_PHONEID,
+ &hDll,
+ gszTUISPI_phoneConfigDialog,
+ &pfnTUISPI_phoneConfigDialog
+
+ )) == 0)
+ {
+ DBGOUT((3, "Calling TUISPI_phoneConfigDialog..."));
+
+ lResult = (*pfnTUISPI_phoneConfigDialog)(
+ TUISPIDLLCallback,
+ dwDeviceID,
+ hwndOwner,
+ lpszDeviceClass
+ );
+
+#if DBG
+ {
+ char szResult[32];
+
+
+ DBGOUT((
+ 3,
+ "TUISPI_phoneConfigDialog: result = %s",
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+#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
+ )
+{
+ DBGOUT((3, "phoneDevSpecificPostProcess: enter"));
+ DBGOUT((
+ 3,
+ "\t\tdwP1=x%lx, dwP2=x%lx, dwP3=x%lx, dwP4=x%lx",
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3,
+ pMsg->dwParam4
+ ));
+
+ if (pMsg->dwParam2 == 0)
+ {
+ DWORD dwSize = pMsg->dwParam4;
+ LPBYTE pParams = (LPBYTE) pMsg->dwParam3;
+
+ try
+ {
+ if (gbNTVDMClient)
+ {
+ //
+ // BUGBUG For Win9x compatibility we probably ought to
+ // use WOWGetVDMPointerFix & WOWGetVDMPointerUnfix
+ //
+
+ LPVARSTRING pParamsVDM = (LPVARSTRING) gpfnWOWGetVDMPointer(
+ (DWORD) pParams,
+ dwSize,
+ TRUE // fProtectedMode
+ );
+
+
+ if (pParamsVDM)
+ {
+ CopyMemory (pParamsVDM, (LPBYTE) (pMsg + 1), dwSize);
+ }
+ else
+ {
+ pMsg->dwParam2 = PHONEERR_INVALPOINTER;
+ }
+ }
+ else
+ {
+ CopyMemory (pParams, (LPBYTE) (pMsg + 1), dwSize);
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ pMsg->dwParam2 = PHONEERR_INVALPOINTER;
+ }
+ }
+}
+
+
+LONG
+WINAPI
+phoneDevSpecific(
+ HPHONE hPhone,
+ LPVOID lpParams,
+ DWORD dwSize
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 5, pDevSpecific),
+
+ {
+ (DWORD) ((POSTPROCESSPROC) phoneDevSpecificPostProcess),
+ (DWORD) hPhone,
+ (DWORD) lpParams, // passed as Dword for post processing
+ (DWORD) lpParams, // passed as LpSet_Xxx for IsValidPtr chk
+ (DWORD) dwSize
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ lpSet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ if (gbNTVDMClient)
+ {
+ if (!gpfnWOWGetVDMPointer ||
+
+ !(funcArgs.Args[3] = gpfnWOWGetVDMPointer(
+ (DWORD) lpParams,
+ dwSize,
+ TRUE // fProtectedMode
+ )))
+ {
+ return PHONEERR_OPERATIONFAILED;
+ }
+ }
+
+ return (DOFUNC (&funcArgs, "phoneDevSpecific"));
+}
+
+
+LONG
+WINAPI
+phoneGetButtonInfoW(
+ HPHONE hPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO lpButtonInfo
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetButtonInfo),
+
+ {
+ (DWORD) hPhone,
+ dwButtonLampID,
+ (DWORD) 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),
+
+ {
+ (DWORD) hPhone,
+ dwDataID,
+ (DWORD) lpData,
+ 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),
+
+ {
+ (DWORD) hPhoneApp,
+ dwDeviceID,
+ dwAPIVersion,
+ dwExtVersion,
+ (DWORD) lpPhoneCaps
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ lpGet_Struct
+ }
+ };
+
+
+ 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)
+ {
+ 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),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) 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),
+
+ {
+ (DWORD) hPhone,
+ dwHookSwitchDev,
+ (DWORD) lpdwGain
+ },
+
+ {
+ Dword,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneGetGain"));
+}
+
+
+LONG
+WINAPI
+phoneGetHookSwitch(
+ HPHONE hPhone,
+ LPDWORD lpdwHookSwitchDevs
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 2, pGetHookSwitch),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) lpdwHookSwitchDevs
+ },
+
+ {
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneGetHookSwitch"));
+}
+
+
+LONG
+WINAPI
+phoneGetIconW(
+ DWORD dwDeviceID,
+ LPCWSTR lpszDeviceClass,
+ LPHICON lphIcon
+ )
+{
+ HICON hIcon;
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetIcon),
+
+ {
+ dwDeviceID,
+ (DWORD) lpszDeviceClass,
+ (DWORD) &hIcon
+ },
+
+ {
+ Dword,
+ lpszW,
+ lpDword
+ }
+ };
+ LONG lResult;
+
+
+ if (IsBadDwordPtr ((LPDWORD) 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] = TAPI_NO_DATA;
+ }
+
+ if ((lResult = DOFUNC (&funcArgs, "phoneGetIcon")) == 0)
+ {
+ if (gbNTVDMClient == FALSE)
+ {
+ *lphIcon = hIcon;
+ }
+ else
+ {
+// BUGBUG phoneGetIcon: need to convert 32-bit HICON to 16-bit HICON
+ }
+ }
+ return lResult;
+}
+
+
+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),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) lpDeviceID,
+ (DWORD) lpszDeviceClass
+ },
+
+ {
+ Dword,
+ lpGet_Struct,
+ lpszW
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneGetID"));
+}
+
+
+LONG
+WINAPI
+phoneGetIDA(
+ HPHONE hPhone,
+ LPVARSTRING lpDeviceID,
+ LPCSTR lpszDeviceClass
+ )
+{
+ LONG lResult;
+ PWSTR szTempPtr;
+
+
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwButtonLampID,
+ (DWORD) lpdwLampMode
+ },
+
+ {
+ Dword,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneGetLamp"));
+}
+
+
+
+LONG
+WINAPI
+phoneGetMessage(
+ HPHONEAPP hPhoneApp,
+ LPPHONEMESSAGE lpMessage,
+ DWORD dwTimeout
+ )
+{
+ return (xxxGetMessage(
+ FALSE,
+ (PINIT_DATA) hPhoneApp,
+ (LPLINEMESSAGE) lpMessage,
+ dwTimeout
+ ));
+}
+
+
+LONG
+WINAPI
+phoneGetRing(
+ HPHONE hPhone,
+ LPDWORD lpdwRingMode,
+ LPDWORD lpdwVolume
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 3, pGetRing),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) lpdwRingMode,
+ (DWORD) 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),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) 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),
+
+ {
+ (DWORD) hPhone,
+ (DWORD) lpdwPhoneStates,
+ (DWORD) lpdwButtonModes,
+ (DWORD) 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),
+
+ {
+ (DWORD) hPhone,
+ dwHookSwitchDev,
+ (DWORD) 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))
+ {
+ DBGOUT((
+ 1,
+ "phoneInitialize: bad lpszFriendlyAppName (x%x)",
+ lpszFriendlyAppName
+ ));
+
+ return PHONEERR_INVALPOINTER;
+ }
+
+ szTempPtr = NotSoWideStringToWideString(
+ lpszFriendlyAppName,
+ (DWORD) -1
+ );
+ }
+ else
+ {
+ szTempPtr = NULL;
+ }
+
+ lResult = (xxxInitialize(
+ FALSE,
+ (LPVOID) lphPhoneApp,
+ hInstance,
+ lpfnCallback,
+ szTempPtr,
+ lpdwNumDevs,
+ NULL,
+ NULL
+#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))
+ {
+ DBGOUT((
+ 1,
+ "phoneInitializeExW: bad lpdwAPIVersion (x%x)",
+ 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))
+ {
+ DBGOUT((
+ 1,
+ "phoneInitializeExA: bad lpszFriendlyAppName (x%x)",
+ 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),
+
+ {
+ (DWORD) hPhoneApp,
+ dwDeviceID,
+ dwAPILowVersion,
+ dwAPIHighVersion,
+ (DWORD) lpdwAPIVersion,
+ (DWORD) lpExtensionID,
+ sizeof(PHONEEXTENSIONID)
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ lpDword,
+ lpGet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ 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),
+
+ {
+ (DWORD) hPhoneApp,
+ dwDeviceID,
+ dwAPIVersion,
+ dwExtLowVersion,
+ dwExtHighVersion,
+ (DWORD) lpdwExtVersion
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneNegotiateExtVersion"));
+}
+
+
+LONG
+WINAPI
+phoneOpen(
+ HPHONEAPP hPhoneApp,
+ DWORD dwDeviceID,
+ LPHPHONE lphPhone,
+ DWORD dwAPIVersion,
+ DWORD dwExtVersion,
+ DWORD dwCallbackInstance,
+ DWORD dwPrivilege
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | SYNC | 8, pOpen),
+
+ {
+ (DWORD) hPhoneApp,
+ dwDeviceID,
+ (DWORD) lphPhone,
+ dwAPIVersion,
+ dwExtVersion,
+ dwCallbackInstance,
+ dwPrivilege,
+ 0, // PHONEOPEN_PARAMS.hRemotePhone
+ },
+
+ {
+ hXxxApp,
+ Dword,
+ lpDword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "phoneOpen"));
+}
+
+
+LONG
+WINAPI
+phoneSetButtonInfoW(
+ HPHONE hPhone,
+ DWORD dwButtonLampID,
+ LPPHONEBUTTONINFO const lpButtonInfo
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (PHONE_FUNC | ASYNC | 3, pSetButtonInfo),
+
+ {
+ (DWORD) hPhone,
+ dwButtonLampID,
+ (DWORD) 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))
+ {
+ DBGOUT((1, "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;
+
+ //
+ // Assume the worst for size...
+ //
+
+ lppbi = ClientAlloc( lpButtonInfo->dwTotalSize * sizeof(WCHAR) );
+
+ 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.
+ //
+
+ dwNewStringSize = sizeof(WCHAR) * MultiByteToWideChar(
+ GetACP(),
+ MB_PRECOMPOSED,
+ (LPBYTE)lpButtonInfo + lpButtonInfo->dwButtonTextOffset,
+ lpButtonInfo->dwButtonTextSize,
+ (PWSTR)((LPBYTE)lppbi + lpButtonInfo->dwTotalSize),
+ lpButtonInfo->dwButtonTextSize
+ );
+
+ lppbi->dwTotalSize += dwNewStringSize;
+
+ lppbi->dwButtonTextSize = dwNewStringSize;
+ lppbi->dwButtonTextOffset = lpButtonInfo->dwTotalSize;
+ }
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwDataID,
+ (DWORD) lpData,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwRow,
+ dwColumn,
+ (DWORD) lpsDisplay,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwHookSwitchDev,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwHookSwitchDevs,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwButtonLampID,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwRingMode,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwPhoneStates,
+ dwButtonModes,
+ 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),
+
+ {
+ (DWORD) hPhone,
+ dwHookSwitchDev,
+ dwVolume
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword
+ }
+ };
+
+return (DOFUNC (&funcArgs, "phoneSetVolume"));
+}
+
+
+LONG
+WINAPI
+phoneShutdown(
+ HPHONEAPP hPhoneApp
+ )
+{
+ return (xxxShutdown ((DWORD) hPhoneApp, FALSE));
+}
+
+
+//
+// ------------------------------- tapiXxx ------------------------------------
+//
+
+LONG
+WINAPI
+tapiRequestDrop(
+ HWND hWnd,
+ WPARAM wRequestID
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (TAPI_FUNC | SYNC | 2, tRequestDrop),
+
+ {
+ (DWORD) hWnd,
+ (DWORD) 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),
+
+ {
+ (DWORD) lpszDestAddress,
+ (DWORD) lpszAppName,
+ (DWORD) lpszCalledParty,
+ (DWORD) lpszComment,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) &hRequestMakeCallAttempted
+ },
+
+ {
+ lpszW,
+ lpszW,
+ lpszW,
+ lpszW,
+ lpGet_Struct,
+ Dword,
+ lpDword
+ }
+ };
+
+
+ // BUGBUG some of the err codes here need to be tweeked
+
+ if (IsBadStringPtrW (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] = 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] = 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] = TAPI_NO_DATA;
+ }
+
+
+ //
+ //
+ //
+
+ if (!(pProxyList = ClientAlloc (dwProxyListSize)))
+ {
+ return TAPIERR_NOREQUESTRECIPIENT;
+ }
+
+ pProxyList->dwTotalSize = dwProxyListSize;
+
+ funcArgs.Args[4] = (DWORD) 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 == ',')
+ {
+ *pszNextProxyName = 0;
+ pszNextProxyName++;
+ break;
+ }
+
+ pszNextProxyName++;
+ }
+
+ //
+ // Fake layer to get a local struct
+ //
+ {
+ FARPROC pShellExecuteExW = NULL;
+ HINSTANCE hInst;
+
+ SHELLEXECUTEINFOW sei =
+ {
+ sizeof(SHELLEXECUTEINFOW),
+ 0,
+ 0, // hWnd!!! BUGBUG: Should it be GetFocus() ???
+ NULL, //"Open"
+ pszProxyName,
+ NULL,
+ NULL, //Directory
+ SW_MINIMIZE,
+ NULL //hProcess - huh?
+ };
+
+
+ hInst = LoadLibrary( "shell32.dll" );
+ pShellExecuteExW = GetProcAddress( hInst, "ShellExecuteExW" );
+
+ if (pShellExecuteExW && pShellExecuteExW (&sei) == TRUE)
+ {
+ bStartedProxy = TRUE;
+ break;
+ }
+#if DBG
+ else
+ {
+ DBGOUT((
+ 3,
+ "tapiRequestMakeCall: ShellExecuteExW(%ls) error - x%x",
+ pszProxyName,
+ GetLastError()
+ ));
+ }
+#endif
+ FreeLibrary( hInst );
+ }
+
+ pszProxyName = pszNextProxyName;
+ }
+
+ if (bStartedProxy == FALSE)
+ {
+ //
+ // Alert tapisrv that it needs to free the ReqMakeCall inst
+ //
+
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (TAPI_FUNC | SYNC | 7, tRequestMakeCall),
+
+ {
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) 0,
+ (DWORD) hRequestMakeCallAttempted,
+ (DWORD) 0
+ },
+
+ {
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ Dword,
+ }
+ };
+
+
+ DBGOUT((
+ 1,
+ "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);
+ 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),
+
+ {
+ (DWORD) hWnd,
+ (DWORD) wRequestID,
+ (DWORD) lpszDeviceClass,
+ (DWORD) lpDeviceID,
+ dwSize,
+ dwSecure,
+ (DWORD) lpszDestAddress,
+ (DWORD) lpszAppName,
+ (DWORD) lpszCalledParty,
+ (DWORD) lpszComment,
+ },
+
+ {
+ Hwnd,
+ Dword,
+ lpszW,
+ lpGet_SizeToFollow,
+ Size,
+ Dword,
+ lpszW,
+ lpszW,
+ lpszW,
+ lpszW
+ }
+ };
+
+
+ if (IsBadStringPtrW (lpszDeviceClass, (UINT) -1) ||
+ (lstrlenW (lpszDeviceClass) + 1) > TAPIMAXDEVICECLASSSIZE)
+ {
+ return TAPIERR_INVALDEVICECLASS;
+ }
+
+ if (IsBadWritePtr ((LPVOID) lpDeviceID, dwSize) ||
+ dwSize > (TAPIMAXDEVICEIDSIZE * sizeof (WCHAR)))
+ {
+ return TAPIERR_INVALDEVICEID;
+ }
+
+ if (IsBadStringPtrW (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] = 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] = 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] = 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, szTempPtr2, szTempPtr3,
+ szTempPtr4, szTempPtr5, szTempPtr6;
+
+
+ if (IsBadStringPtrA (lpszDeviceClass, (UINT) -1) ||
+ (lstrlenA (lpszDeviceClass) + 1) > TAPIMAXDEVICECLASSSIZE)
+ {
+ return TAPIERR_INVALDEVICECLASS;
+ }
+ else
+ {
+ szTempPtr1 = NotSoWideStringToWideString(
+ lpszDeviceClass,
+ (DWORD) -1
+ );
+ }
+
+ if (IsBadWritePtr ((LPVOID) lpDeviceID, dwSize) ||
+ dwSize > TAPIMAXDEVICEIDSIZE)
+ {
+ return TAPIERR_INVALDEVICEID;
+ }
+ else
+ {
+ dwSize *= 2;
+ szTempPtr2 = ClientAlloc (dwSize);
+ }
+
+ if (IsBadStringPtrA (lpszDestAddress, (UINT) -1) ||
+ (lstrlenA (lpszDestAddress) + 1) > TAPIMAXDESTADDRESSSIZE)
+ {
+ return TAPIERR_INVALDESTADDRESS;
+ }
+ else
+ {
+ szTempPtr3 = NotSoWideStringToWideString(
+ lpszDestAddress,
+ (DWORD) -1
+ );
+ }
+
+ if ((lpszAppName && IsBadStringPtrA (lpszAppName, (UINT) -1)) ||
+ (lpszCalledParty && IsBadStringPtrA (lpszCalledParty, (UINT) -1)) ||
+ (lpszComment && IsBadStringPtrA (lpszComment, (UINT) -1)))
+ {
+ return TAPIERR_INVALPOINTER;
+ }
+
+ 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
+ );
+
+ 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;
+
+
+ DBGOUT((3, "GetTapi16CallbackMsg: enter"));
+
+ EnterCriticalSection (&gCriticalSection);
+
+ try
+ {
+ if ((DWORD) pInitData & 0x7 || 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);
+
+ DBGOUT((3, "GetTapi16CallbackMsg: exit (result=x%x)", lResult));
+
+ return lResult;
+}
+
+
+
+
+//
+// ----------------------- Private support routines ---------------------------
+//
+
+void
+FreeInitData(
+ PINIT_DATA pInitData
+ )
+{
+ if (pInitData)
+ {
+ EnterCriticalSection (&gCriticalSection);
+
+ pInitData->dwKey = 0xefefefef;
+
+ LeaveCriticalSection (&gCriticalSection);
+
+ if (pInitData->dwInitOptions == 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 ==
+ LINEINITIALIZEEXOPTION_USEHIDDENWINDOW)
+ {
+ // NOTE: let thunk destroy it's own window
+
+ if (pInitData->hwnd && !gbNTVDMClient)
+ {
+ DestroyWindow (pInitData->hwnd);
+ }
+ }
+
+ if (pInitData->pEventBuffer)
+ {
+ ClientFree (pInitData->pEventBuffer);
+ }
+
+ ClientFree (pInitData);
+ }
+}
+
+
+LONG
+CreateHiddenWindow(
+ HWND *lphwnd,
+ DWORD dwErrorClass
+ )
+{
+ LONG lResult = 0;
+
+
+ if (!gbResourcesAllocated)
+ {
+ if ((lResult = AllocClientResources (dwErrorClass)) != 0)
+ {
+ return lResult;
+ }
+ }
+
+ if (!(*lphwnd = CreateWindow(
+ szTapi32WndClass, // class name
+ gszNullString, // title
+ 0, // style
+ 0, // x
+ 0, // y
+ 0, // width
+ 0, // height
+ (HWND) NULL, // parent wnd
+ (HMENU) NULL, // menu
+ ghInst, // instance
+ NULL // params
+ )))
+ {
+ DBGOUT((1, "CreateWindow failed, err=%ld", GetLastError()));
+
+ lResult = gaOpFailedErrors[dwErrorClass];
+ }
+
+ return lResult;
+}
+
+
+BOOL
+CALLBACK
+TAPIWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_ASYNCEVENT:
+ {
+ BOOL bFirstPass = TRUE, bPostMsg;
+ PINIT_DATA pInitData = (PINIT_DATA) lParam;
+
+
+ DBGOUT((3, "TAPIWndProc: received WM_ASYNCEVENT, hwnd=x%lx", hwnd));
+
+ 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.
+ //
+
+ DBGOUT((11, "Trying to grab critical section (0x%08lx) in wndproc", gCriticalSection));
+ EnterCriticalSection (&gCriticalSection);
+ DBGOUT((11, "Got critical section (0x%08lx) in wndproc", gCriticalSection));
+
+ try
+ {
+ if (pInitData->dwKey != INITDATA_KEY)
+ {
+ DBGOUT((4, "TAPIWndProc: bad pInitInst (x%x)", pInitData));
+ DBGOUT((11, "releasing critical section (0x%08lx) in wndproc1", gCriticalSection));
+ LeaveCriticalSection (&gCriticalSection);
+ break;
+ }
+ }
+ except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ DBGOUT((4, "TAPIWndProc: bad pInitInst (x%x)", pInitData));
+ DBGOUT((11, "releasing critical section (0x%08lx) in wndproc2", gCriticalSection));
+ LeaveCriticalSection (&gCriticalSection);
+ break;
+ }
+
+ if (bFirstPass)
+ {
+ pInitData->bPendingAsyncEventMsg = FALSE;
+ bFirstPass = FALSE;
+ }
+
+ if (pInitData->dwNumUsedEntries != 0)
+ {
+ ASYNC_EVENT_PARAMS event;
+
+
+ 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;
+ }
+
+ DBGOUT((11, "releasing critical section (0x%08lx) in wndproc3", gCriticalSection));
+ LeaveCriticalSection (&gCriticalSection);
+
+ DBGOUT((
+ 3,
+ "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);
+ }
+
+ (*pInitData->lpfnCallback)(
+ event.hDevice,
+ event.dwMsg,
+ event.dwCallbackInstance,
+ event.dwParam1,
+ event.dwParam2,
+ event.dwParam3
+ );
+ }
+ else
+ {
+ DBGOUT((11, "No entries - spurious entry."));
+ DBGOUT((11, "releasing critical section (0x%08lx) in wndproc4", gCriticalSection));
+
+ LeaveCriticalSection (&gCriticalSection);
+
+ break;
+ }
+ }
+
+ return FALSE;
+ }
+ default:
+
+ break;
+ }
+
+ return (DefWindowProc (hwnd, msg, wParam, lParam));
+}
+
+
+void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
+{
+ DBGOUT((11, "midl_user_allocate: enter, size=x%x", len));
+
+ return (ClientAlloc (len));
+}
+
+
+void __RPC_API midl_user_free(void __RPC_FAR * ptr)
+{
+ DBGOUT((11, "midl_user_free: enter, p=x%x", ptr));
+
+ ClientFree (ptr);
+}
+
+
+
+LONG
+WINAPI
+AllocClientResources(
+ DWORD dwErrorClass
+ )
+{
+ DWORD dwExceptionCount = 0;
+ LONG lResult = gaOpFailedErrors[dwErrorClass];
+ SC_HANDLE hSCMgr, hTapiSrv;
+
+
+// DBGOUT((3, "AllocClientResources: enter"));
+
+
+ if (gbResourcesAllocated)
+ {
+ return TAPI_SUCCESS;
+ }
+
+
+ //
+ // Serialize the following init code
+ //
+
+ WaitForSingleObject (ghInitMutex, INFINITE);
+
+ if (gbResourcesAllocated)
+ {
+ lResult = TAPI_SUCCESS;
+
+ goto AllocClientResources_return;
+ }
+
+
+ //
+ // Register the hidden window class
+ //
+
+ {
+ DWORD dwError;
+ WNDCLASS wndclass;
+
+
+ ZeroMemory(&wndclass, sizeof(WNDCLASS));
+
+ wndclass.lpfnWndProc = (WNDPROC) TAPIWndProc;
+ wndclass.hInstance = ghInst;
+ wndclass.lpszClassName = szTapi32WndClass;
+
+ if (!RegisterClass (&wndclass) &&
+ ((dwError = GetLastError()) != ERROR_CLASS_ALREADY_EXISTS))
+ {
+ DBGOUT((
+ 3,
+ "AllocClientResources: RegisterClass failed, err=%d",
+ dwError
+ ));
+ }
+ }
+
+
+ //
+ // Start the TAPISRV.EXE service
+ //
+
+ if (!(GetVersion() & 0x80000000)) // Win NT
+ {
+ if ((hSCMgr = OpenSCManager(
+ NULL, // local machine
+ NULL, // ServicesActive database
+ SC_MANAGER_CONNECT // desired access
+ )) == NULL)
+ {
+ DBGOUT((1, "OpenSCManager failed, err=%d", GetLastError()));
+
+ goto AllocClientResources_return;
+ }
+
+ if ((hTapiSrv = OpenService(
+ hSCMgr, // SC mgr handle
+ (LPCTSTR) "TAPISRV", // name of service to open
+ SERVICE_START | // desired access
+ SERVICE_QUERY_STATUS
+ )) == NULL)
+ {
+ DBGOUT((1, "OpenService failed, err=%d", GetLastError()));
+
+ 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:
+
+ DBGOUT((3, "Tapisrv running"));
+ goto AllocClientResources_attachToServer;
+
+ case SERVICE_START_PENDING:
+
+ Sleep (1000);
+
+ if (++dwNumSecondsSleptStartPending >
+ MAX_NUM_SECONDS_TO_WAIT_FOR_TAPISRV)
+ {
+ DBGOUT((
+ 1,
+ "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)
+ {
+ DBGOUT((
+ 1,
+ "ERROR: Tapisrv stuck SERVICE_STOP_PENDING"
+ ));
+
+ goto AllocClientResources_cleanup2;
+ }
+
+ break;
+
+ case SERVICE_STOPPED:
+
+ DBGOUT((3, "Starting tapisrv (NT)..."));
+
+ if (!StartService(
+ hTapiSrv, // service handle
+ 0, // num args
+ NULL // args
+ ))
+ {
+ DWORD dwLastError = GetLastError();
+
+
+ if (dwLastError != ERROR_SERVICE_ALREADY_RUNNING)
+ {
+ DBGOUT((
+ 1,
+ "StartService(TapiSrv) failed, err=%d",
+ dwLastError
+ ));
+
+ goto AllocClientResources_cleanup2;
+ }
+ }
+
+ break;
+
+ default:
+
+ DBGOUT((
+ 1,
+ "error, service status=%d",
+ status.dwCurrentState
+ ));
+
+ goto AllocClientResources_cleanup2;
+ }
+ }
+ }
+ }
+ else // Win95
+ {
+ HANDLE hMutex, hEvent;
+
+
+ //
+ // First grab the global mutex that serializes the following
+ // across all instances of tapi32.dll
+ //
+
+ if (!(hMutex = CreateMutex (NULL, FALSE, "StartTapiSrv")))
+ {
+ DBGOUT((
+ 3,
+ "CreateMutex ('StartTapiSrv') failed, err=%d",
+ GetLastError()
+ ));
+ }
+
+ WaitForSingleObject (hMutex, INFINITE);
+
+
+ //
+ // Try to open the event that tells us tapisrv has inited
+ //
+
+ if (!(hEvent = OpenEvent (EVENT_ALL_ACCESS, TRUE, "TapiSrvInited")))
+ {
+ //
+ // OpenEvent failed, so tapisrv hasn't been started yet. Start
+ // tapisrv, and then get the event handle.
+ //
+
+ STARTUPINFO startupInfo;
+ PROCESS_INFORMATION processInfo;
+
+
+ DBGOUT((
+ 3,
+ "OpenEvent ('TapiSrvInited') failed, err=%d",
+ GetLastError()
+ ));
+
+ ZeroMemory(&startupInfo, sizeof (STARTUPINFO));
+
+ startupInfo.cb = sizeof (STARTUPINFO);
+
+ DBGOUT((4, "Starting tapisrv (Win95)..."));
+
+ if (!CreateProcess(
+ NULL, // image name
+ "tapisrv.exe", // cmd line
+ NULL, // process security attrs
+ NULL, // thread security attrs
+ FALSE, // inherit handles
+ NORMAL_PRIORITY_CLASS, // create opts
+ NULL, // environment
+ NULL, // curr dir
+ &startupInfo,
+ &processInfo
+ ))
+ {
+ DBGOUT((
+ 1,
+ "CreateProcess('tapisrv.exe') failed, err=%d",
+ GetLastError()
+ ));
+ }
+ else
+ {
+ CloseHandle (processInfo.hProcess);
+ CloseHandle (processInfo.hThread);
+ }
+
+ if (!(hEvent = CreateEvent (NULL, TRUE, FALSE, "TapiSrvInited")))
+ {
+ DBGOUT((
+ 1,
+ "CreateEvent ('TapiSrvInited') failed, err=%d",
+ GetLastError()
+ ));
+ }
+
+ }
+
+
+ //
+ // Now wait on the event (it's will be signaled when tapisrv has
+ // completed it's initialization). Then clean up.
+ //
+
+ WaitForSingleObject (hEvent, INFINITE);
+ CloseHandle (hEvent);
+
+ ReleaseMutex (hMutex);
+ CloseHandle (hMutex);
+ }
+
+
+ //
+ // 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;
+ unsigned char pszNetworkAddress[UNCLEN+1];
+ unsigned char *pszUuid = NULL;
+ unsigned char *pszOptions = NULL;
+ unsigned char *pszStringBinding = NULL;
+ DWORD dwProcessID = GetCurrentProcessId(), dwSize = 256;
+ WCHAR *pszUserName = ClientAlloc (dwSize * sizeof(WCHAR) );
+
+
+ pszNetworkAddress[0] = '\0';
+
+ status = RpcStringBindingCompose(
+ pszUuid,
+ "ncalrpc",
+ pszNetworkAddress,
+ "tapsrvlpc",
+ pszOptions,
+ &pszStringBinding
+ );
+
+ if (status)
+ {
+ DBGOUT((
+ 1,
+ "RpcStringBindingCompose failed: err=%d, szNetAddr='%s'",
+ status,
+ pszNetworkAddress
+ ));
+ }
+
+ status = RpcBindingFromStringBinding(
+ pszStringBinding,
+ &hTapSrv
+ );
+
+ if (status)
+ {
+ DBGOUT((
+ 1,
+ "RpcBindingFromStringBinding failed, err=%d, szBinding='%s'",
+ status,
+ pszStringBinding
+ ));
+ }
+
+ GetUserNameW(pszUserName, &dwSize);
+
+ RpcTryExcept
+ {
+ DBGOUT((4, "AllocCliRes: calling ClientAttach..."));
+
+ lResult = ClientAttach(
+ (PCONTEXT_HANDLE_TYPE *) &gphCx,
+ dwProcessID,
+ (long *) &ghAsyncEventsEvent,
+ pszUserName,
+ L""
+ );
+
+ DBGOUT((4, "AllocCliRes: ClientAttach returned x%x", lResult));
+ }
+ RpcExcept (1)
+ {
+ DBGOUT((
+ 4,
+ "AllocCliRes: ClientAttach caused except=%d",
+ RpcExceptionCode()
+ ));
+ bException = TRUE;
+ }
+ RpcEndExcept
+
+ ClientFree (pszUserName);
+
+ RpcBindingFree (&hTapSrv);
+
+// DBGOUT((
+// 3,
+// "AllocCliRes: gphCx=x%x, PID=x%x, hAEEvent=x%x",
+// gphCx,
+// dwProcessID,
+// ghAsyncEventsEvent
+// ));
+
+ RpcStringFree(&pszStringBinding);
+
+ if (bException)
+ {
+ //
+ // 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));
+ goto AllocClientResources_queryServiceStatus;
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "AllocCliRes: ClientAttach failed, result=x%x",
+ gaOpFailedErrors[dwErrorClass]
+ ));
+
+ lResult = gaOpFailedErrors[dwErrorClass];
+ }
+ }
+ }
+
+ if (lResult == 0)
+ {
+ gbResourcesAllocated = TRUE;
+ }
+
+
+AllocClientResources_cleanup2:
+
+ if (!(GetVersion() & 0x80000000)) // Win NT
+ {
+ CloseServiceHandle (hTapiSrv);
+ }
+
+AllocClientResources_cleanup1:
+
+ if (!(GetVersion() & 0x80000000)) // Win NT
+ {
+ CloseServiceHandle (hSCMgr);
+ }
+
+AllocClientResources_return:
+
+ ReleaseMutex (ghInitMutex);
+
+// DBGOUT((3, "AllocClientResources: exit, returning x%x", lResult));
+
+ return lResult;
+}
+
+
+LONG
+PASCAL
+xxxShutdown(
+ DWORD hXXXApp,
+ BOOL bLineShutdown
+ )
+{
+ FUNC_ARGS funcArgs =
+ {
+ MAKELONG (LINE_FUNC | SYNC | 1, (bLineShutdown ? lShutdown: pShutdown)),
+
+ {
+ hXXXApp
+ },
+
+ {
+ hXxxApp
+ }
+ };
+ LONG lResult;
+
+
+ //
+ // BUGBUG Sync all inits & shutdowns for now (so we don't have problems
+ // with the async msgs thread going away)
+ //
+
+ WaitForSingleObject (ghInitMutex, INFINITE);
+
+ lResult = DOFUNC(
+ &funcArgs,
+ (bLineShutdown ? "lineShutdown" : "phoneShutdown")
+ );
+
+ if (lResult == 0)
+ {
+ FreeInitData ((PINIT_DATA) hXXXApp);
+
+ 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
+ //
+
+ EnterCriticalSection (&gCriticalSection);
+
+ 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);
+
+ DBGOUT((
+ 3,
+ "xxxShutdown: calling " \
+ "TUISPI_providerGenericDialogData..."
+ ));
+
+ (*pUIThreadData->pfnTUISPI_providerGenericDialogData)(
+ pUIThreadData->htDlgInst,
+ NULL,
+ 0
+ );
+
+ DBGOUT((
+ 3,
+ "xxxShutdown: " \
+ "TUISPI_providerGenericDialogData returned"
+ ));
+
+ pUIThreadData = pNextUIThreadData;
+ }
+ }
+
+ LeaveCriticalSection (&gCriticalSection);
+ }
+ }
+
+ ReleaseMutex (ghInitMutex);
+
+ return lResult;
+}
+
+
+LONG
+PASCAL
+xxxGetMessage(
+ BOOL bLine,
+ PINIT_DATA pInitData,
+ LPLINEMESSAGE pMsg,
+ DWORD dwTimeout
+ )
+{
+ LONG lResult;
+ BOOL bInCriticalSection = FALSE;
+
+
+// BUGBUG xxxGetMessage: spec a new TIMEOUT error?
+// BUGBUG xxxGetMessage: no difference in keys between lineApp & phoneApp
+
+ if (IsBadWritePtr (pMsg, sizeof (LINEMESSAGE)))
+ {
+ lResult = (bLine ? LINEERR_INVALPOINTER : PHONEERR_INVALPOINTER);
+ goto xxxGetMessage_return;
+ }
+
+ try
+ {
+ if (((DWORD) pInitData) & 0x7 || pInitData->dwKey != INITDATA_KEY)
+ {
+ lResult = (bLine ? LINEERR_INVALAPPHANDLE :
+ PHONEERR_INVALAPPHANDLE);
+ goto xxxGetMessage_return;
+ }
+
+ if (pInitData->dwInitOptions != LINEINITIALIZEEXOPTION_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
+ {
+ 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)
+ {
+// BUGBUG xxxGetMessage: might want to decr dwTimeout in non-INFINITE case
+
+ LeaveCriticalSection (&gCriticalSection);
+ bInCriticalSection = FALSE;
+ goto xxxGetMessage_wait;
+ }
+ }
+ else
+ {
+ 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)
+ {
+ if (bInCriticalSection)
+ {
+ LeaveCriticalSection (&gCriticalSection);
+ }
+
+ lResult = (bLine ? LINEERR_INVALAPPHANDLE : PHONEERR_INVALAPPHANDLE);
+ }
+
+xxxGetMessage_return:
+
+#if DBG
+ {
+ char szResult[32],
+ *pszFuncName = (bLine ? "lineGetMessage" : "phoneGetMessage");
+
+
+ if (lResult == 0)
+ {
+ DBGOUT((
+ 3,
+ "%s: exit, returning msg=%s\n",
+ "\thDev=x%x, dwInst=x%x, p1=x%x, p2=x%x, p3=x%x",
+ aszMsgs[pMsg->dwMessageID],
+ pMsg->hDevice,
+ pMsg->dwCallbackInstance,
+ pMsg->dwParam1,
+ pMsg->dwParam2,
+ pMsg->dwParam3
+ ));
+ }
+ else
+ {
+ DBGOUT((
+ 3,
+ "%s: exit, result=%s",
+ pszFuncName,
+ MapResultCodeToText (lResult, szResult)
+ ));
+ }
+ }
+#endif
+
+ return lResult;
+}
+
+
+LPVOID
+WINAPI
+ClientAlloc(
+ DWORD dwSize
+ )
+{
+ LPBYTE p;
+ LPDWORD pAligned;
+
+
+ //
+ // Alloc 16 extra bytes so we can make sure the pointer we pass back
+ // is 64-bit aligned & have space to store the original pointer
+ //
+
+ if ((p = (LPBYTE) LocalAlloc (LPTR, dwSize + 16)))
+ {
+ pAligned = (LPDWORD) (p + 8 - (((DWORD) p) & 0x7));
+ *pAligned = (DWORD) p;
+ pAligned++;
+ pAligned++;
+ }
+ else
+ {
+ DBGOUT((
+ 1,
+ "ClientAlloc: LocalAlloc (x%lx) failed, err=x%lx",
+ dwSize,
+ GetLastError())
+ );
+
+ pAligned = NULL;
+ }
+
+ return ((LPVOID) pAligned);
+}
+
+
+void
+WINAPI
+ClientFree(
+ LPVOID p
+ )
+{
+ if (p != NULL)
+ {
+ LPVOID pOrig = (LPVOID) *(((LPDWORD) p) - 2);
+
+
+ LocalFree (pOrig);
+ }
+#if DBG
+ else
+ {
+ DBGOUT((4,"----- ClientFree: ptr = NULL!"));
+ }
+#endif
+}
+
+
+UINT
+WINAPI
+ClientSize(
+ LPVOID p
+ )
+{
+ if (p != NULL)
+ {
+ return (LocalSize ((LPVOID) *(((LPDWORD) p) - 2)) - 16);
+ }
+
+ DBGOUT((4,"----- ClientSize: ptr = NULL!"));
+ return 0;
+}
+
+
+LONG
+WINAPI
+FreeClientResources(
+ void
+ )
+{
+ //
+ // If ghTapi32 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;
+
+// BUGBUG FreeCliRes: clean up cli-side resources (list of xApps?)
+
+ }
+ else if (gphCx)
+ {
+ CloseHandle (ghAsyncEventsEvent);
+ }
+
+
+ //
+ // If we've made an rpc connection with tapisrv then cleanly detach
+ //
+
+ if (gphCx)
+ {
+ RpcTryExcept
+ {
+ ClientDetach (&gphCx);
+ }
+ RpcExcept(1)
+ {
+ // do something?
+ }
+ RpcEndExcept
+
+ gphCx = NULL;
+ }
+
+
+ //
+ // Free up any other resources we were using
+ //
+
+ CloseHandle (ghInitMutex);
+
+ if (ghWow32Dll)
+ {
+ FreeLibrary (ghWow32Dll);
+ ghWow32Dll = NULL;
+ }
+
+ return 0;
+}
+
+
+#if DBG
+VOID
+DbgPrt(
+ IN DWORD dwDbgLevel,
+ IN PUCHAR lpszFormat,
+ IN ...
+ )
+/*++
+
+Routine Description:
+
+ Formats the incoming debug message & calls DbgPrint
+
+Arguments:
+
+ DbgLevel - level of message verboseness
+
+ DbgMessage - printf-style format string, followed by appropriate
+ list of arguments
+
+Return Value:
+
+
+--*/
+{
+ if (dwDbgLevel <= gdwDebugLevel)
+ {
+ char buf[1280] = "TAPI32: ";
+ va_list ap;
+
+
+ va_start(ap, lpszFormat);
+
+ wvsprintf (&buf[8],
+ lpszFormat,
+ ap
+ );
+
+ lstrcat (buf, "\n");
+
+ OutputDebugStringA (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),
+
+ {
+ (DWORD) dwObjectID,
+ (DWORD) dwObjectType,
+ (DWORD) lpParams,
+ (DWORD) dwSize,
+ (DWORD) lpParams,
+ (DWORD) 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;
+
+
+ DBGOUT((3, "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 ("tapi32.dll");
+
+ DBGOUT((3, "UIThread: calling TUISPI_providerGenericDialog..."));
+
+ (*pUIThreadData->pfnTUISPI_providerGenericDialog)(
+ TUISPIDLLCallback,
+ pUIThreadData->htDlgInst,
+ pUIThreadData->pParams,
+ pUIThreadData->dwSize,
+ pUIThreadData->hEvent
+ );
+
+ DBGOUT((
+ 3,
+ "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),
+
+ {
+ (DWORD) pUIThreadData->htDlgInst
+ },
+
+ {
+ Dword
+ }
+ };
+
+
+ DOFUNC (&funcArgs, "FreeDialogInstance");
+ }
+
+ ClientFree (pUIThreadData);
+
+ DBGOUT((3, "UIThread: exit (tid=%d)", dwThreadID));
+
+ FreeLibraryAndExitThread (hTapi32, 0);
+}
+
+
+LONG
+//WINAPI
+CALLBACK
+LAddrParamsInited(
+ LPDWORD lpdwInited
+ )
+{
+ HKEY hKey;
+ HKEY hKey2;
+ DWORD dwDataSize;
+ DWORD dwDataType;
+
+
+ //
+ // This is called by the modem setup wizard to determine
+ // whether they should put up TAPI's Wizard page.
+ //
+
+ RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ gszTelephonyKey,
+ 0,
+ KEY_READ,
+ &hKey2
+ );
+
+ RegOpenKeyExW(
+ hKey2,
+ gszLocationsW,
+ 0,
+ KEY_READ,
+ &hKey
+ );
+
+ dwDataSize = sizeof(DWORD);
+ *lpdwInited=0;
+
+ RegQueryValueExW(
+ hKey,
+ gszNumEntriesW,
+ 0,
+ &dwDataType,
+ (LPBYTE)lpdwInited,
+ &dwDataSize
+ );
+
+ RegCloseKey( hKey );
+ RegCloseKey( hKey2);
+
+ //
+ // Return a "proper" code
+ //
+ if ( *lpdwInited > 1 )
+ {
+ *lpdwInited = 1;
+ }
+
+ return 0;
+}
+
+
+LONG
+WINAPI
+lineTranslateDialogA(
+ HLINEAPP hLineApp,
+ DWORD dwDeviceID,
+ DWORD dwAPIVersion,
+ HWND hwndOwner,
+ LPCSTR lpszAddressIn
+ );
+
+
+LONG
+CALLBACK
+//WINAPI
+//BUGBUG MAKE THIS A UNICODE ENTRY POINT! (LOpenDialAsst)
+LOpenDialAsst(
+ HWND hwnd,
+ LPCSTR lpszAddressIn,
+ BOOL fSimple,
+ BOOL fSilentInstall
+ )
+{
+
+// lineTranslateDialog(hLineApp, 0, 0x00020000, hwnd, lpszAddressIn );
+
+ gbTranslateSimple = fSimple;
+ gbTranslateSilent = fSilentInstall;
+
+ return lineTranslateDialogA( NULL, 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),
+
+ {
+ (DWORD)pPerfBlock,
+ sizeof(PERFBLOCK)
+ },
+
+ {
+ lpGet_SizeToFollow,
+ Size
+ }
+ };
+
+
+ return (DOFUNC (&funcArgs, "PerfDataCall"));
+}
+
+
+
+//***************************************************************************
+//***************************************************************************
+//***************************************************************************
+#if DBG
+
+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)
+ {
+ wsprintf (pszResult, "SUCCESS");
+ }
+ else if (lResult > 0)
+ {
+ wsprintf (pszResult, "x%x (completing async)", lResult);
+ }
+ else if (((DWORD) lResult) <= LINEERR_DIALVOICEDETECT)
+ {
+ lResult &= 0x0fffffff;
+
+ wsprintf (pszResult, "LINEERR_%s", aszLineErrors[lResult]);
+ }
+ else if (((DWORD) lResult) <= PHONEERR_REINIT)
+ {
+ if (((DWORD) lResult) >= PHONEERR_ALLOCATED)
+ {
+ lResult &= 0x0fffffff;
+
+ wsprintf (pszResult, "PHONEERR_%s", aszPhoneErrors[lResult]);
+ }
+ else
+ {
+ goto MapResultCodeToText_badErrorCode;
+ }
+ }
+ else if (((DWORD) lResult) <= ((DWORD) TAPIERR_DROPPED) &&
+ ((DWORD) lResult) >= ((DWORD) TAPIERR_INVALPOINTER))
+ {
+ lResult = ~lResult + 1;
+
+ wsprintf (pszResult, "TAPIERR_%s", aszTapiErrors[lResult]);
+ }
+ else
+ {
+
+MapResultCodeToText_badErrorCode:
+
+ wsprintf (pszResult, "inval error value (x%x)");
+ }
+
+ return pszResult;
+}
+
+#endif