1160 lines
29 KiB
C
1160 lines
29 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
provider.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
TAPI Service Provider functions related to provider info.
|
|||
|
|
|||
|
TSPI_providerConfig
|
|||
|
TSPI_providerEnumDevices
|
|||
|
TSPI_providerFreeDialogInstance
|
|||
|
TSPI_providerGenericDialogData
|
|||
|
TSPI_providerInit
|
|||
|
TSPI_providerInstall
|
|||
|
TSPI_providerRemove
|
|||
|
TSPI_providerShutdown
|
|||
|
TSPI_providerUIIdentify
|
|||
|
|
|||
|
TUISPI_providerConfig
|
|||
|
TUISPI_providerInstall
|
|||
|
TUISPI_providerRemove
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Include files //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "globals.h"
|
|||
|
#include "provider.h"
|
|||
|
#include "callback.h"
|
|||
|
#include "registry.h"
|
|||
|
#include "termcaps.h"
|
|||
|
#include "version.h"
|
|||
|
#include "line.h"
|
|||
|
#include "config.h"
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
DWORD g_dwTSPIVersion = UNINITIALIZED;
|
|||
|
DWORD g_dwLineDeviceIDBase = UNINITIALIZED;
|
|||
|
DWORD g_dwPermanentProviderID = UNINITIALIZED;
|
|||
|
ASYNC_COMPLETION g_pfnCompletionProc = NULL;
|
|||
|
LINEEVENT g_pfnLineEventProc = NULL;
|
|||
|
HPROVIDER g_hProvider = (HPROVIDER)NULL;
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Public procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#if defined(DBG) && defined(DEBUG_CRITICAL_SECTIONS)
|
|||
|
|
|||
|
VOID
|
|||
|
H323LockProvider(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Locks service provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"provider about to be locked.\n"
|
|||
|
));
|
|||
|
|
|||
|
// lock service provider
|
|||
|
EnterCriticalSection(&g_GlobalLock);
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"provider locked.\n"
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
H323UnlockProvider(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Unlocks service provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// unlock service provider
|
|||
|
LeaveCriticalSection(&g_GlobalLock);
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"provider unlocked.\n"
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
#endif // DBG && DEBUG_CRITICAL_SECTIONS
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323IsTSPAlreadyInstalled(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Searchs registry for previous instance of H323.TSP.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if TSP already installed.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
HKEY hKey;
|
|||
|
LONG lStatus;
|
|||
|
DWORD dwNumProviders = 0;
|
|||
|
DWORD dwDataSize = sizeof(DWORD);
|
|||
|
DWORD dwDataType = REG_DWORD;
|
|||
|
LPSTR pszProvidersKey = TAPI_REGKEY_PROVIDERS;
|
|||
|
LPSTR pszNumProvidersValue = TAPI_REGVAL_NUMPROVIDERS;
|
|||
|
CHAR szName[H323_MAXPATHNAMELEN+1];
|
|||
|
CHAR szPath[H323_MAXPATHNAMELEN+1];
|
|||
|
|
|||
|
// attempt to open key
|
|||
|
lStatus = RegOpenKeyEx(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
pszProvidersKey,
|
|||
|
0,
|
|||
|
KEY_READ,
|
|||
|
&hKey
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_WARNING,
|
|||
|
"error 0x%08lx opening tapi providers key.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// done
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// see if installed bit set
|
|||
|
lStatus = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
pszNumProvidersValue,
|
|||
|
0,
|
|||
|
&dwDataType,
|
|||
|
(LPBYTE) &dwNumProviders,
|
|||
|
&dwDataSize
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_WARNING,
|
|||
|
"error 0x%08lx determining number of providers.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// done
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// loop through each provider
|
|||
|
for (i = 0; i < dwNumProviders; i++) {
|
|||
|
|
|||
|
// construct path to provider name
|
|||
|
wsprintf(szName, "ProviderFileName%d", i);
|
|||
|
|
|||
|
// reinitialize size
|
|||
|
dwDataSize = sizeof(szPath);
|
|||
|
|
|||
|
// query the next name
|
|||
|
lStatus = RegQueryValueEx(
|
|||
|
hKey,
|
|||
|
szName,
|
|||
|
0,
|
|||
|
&dwDataType,
|
|||
|
szPath,
|
|||
|
&dwDataSize
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus == NOERROR) {
|
|||
|
|
|||
|
// upper case
|
|||
|
_strupr(szPath);
|
|||
|
|
|||
|
// compare path string to h323 provider
|
|||
|
if (strstr(szPath, H323_TSPDLL) != NULL) {
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// done
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_WARNING,
|
|||
|
"error 0x%08lx loading %s.\n",
|
|||
|
lStatus,
|
|||
|
szName
|
|||
|
));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// done
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// TSPI procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerCreateLineDevice(
|
|||
|
DWORD_PTR dwTempID,
|
|||
|
DWORD dwDeviceID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
This function is called by TAPI in response to receipt of a LINE_CREATE
|
|||
|
message from the service provider, which allows the dynamic creation of
|
|||
|
a new line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwTempID - The temporary device identifier that the service provider
|
|||
|
passed to TAPI in the LINE_CREATE message.
|
|||
|
|
|||
|
dwDeviceID - The device identifier that TAPI assigns to this device if
|
|||
|
this function succeeds.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the request is successful or a negative error number if
|
|||
|
an error has occurred. Possible return values are:
|
|||
|
|
|||
|
LINEERR_BADDEVICEID - The specified line device ID is out of range.
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"creating new device %d (hdLine=0x%08lx).\n",
|
|||
|
dwDeviceID,
|
|||
|
dwTempID
|
|||
|
));
|
|||
|
|
|||
|
// lock line device using temporary device id
|
|||
|
if (!H323GetLineFromIDAndLock(&pLine, (DWORD)dwTempID)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"invalid temp device id 0x%08lx.\n",
|
|||
|
dwTempID
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return LINEERR_BADDEVICEID;
|
|||
|
}
|
|||
|
|
|||
|
// initialize new line device
|
|||
|
H323InitializeLine(pLine, dwDeviceID);
|
|||
|
|
|||
|
// unlock line
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerEnumDevices(
|
|||
|
DWORD dwPermanentProviderID,
|
|||
|
PDWORD pdwNumLines,
|
|||
|
PDWORD pdwNumPhones,
|
|||
|
HPROVIDER hProvider,
|
|||
|
LINEEVENT pfnLineCreateProc,
|
|||
|
PHONEEVENT pfnPhoneCreateProc
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
TAPI.DLL calls this function before TSPI_providerInit to determine the
|
|||
|
number of line and phone devices supported by the service provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwPermanentProviderID - Specifies the permanent ID, unique within the
|
|||
|
service providers on this system, of the service provider being
|
|||
|
initialized.
|
|||
|
|
|||
|
pdwNumLines - Specifies a far pointer to a DWORD-sized memory location
|
|||
|
into which the service provider must write the number of line devices
|
|||
|
it is configured to support. TAPI.DLL initializes the value to zero,
|
|||
|
so if the service provider fails to write a different value, the
|
|||
|
value 0 is assumed.
|
|||
|
|
|||
|
pdwNumPhones - Specifies a far pointer to a DWORD-sized memory location
|
|||
|
into which the service provider must write the number of phone devices
|
|||
|
it is configured to support. TAPI.DLL initializes the value to zero,
|
|||
|
so if the service provider fails to write a different value, the
|
|||
|
value 0 is assumed.
|
|||
|
|
|||
|
hProvider - Specifies an opaque DWORD-sized value which uniquely identifies
|
|||
|
this instance of this service provider during this execution of the
|
|||
|
Windows Telephony environment.
|
|||
|
|
|||
|
pfnLineCreateProc - Specifies a far pointer to the LINEEVENT callback
|
|||
|
procedure supplied by TAPI.DLL. The service provider will use this
|
|||
|
function to send LINE_CREATE messages when a new line device needs to
|
|||
|
be created. This function should not be called to send a LINE_CREATE
|
|||
|
message until after the service provider has returned from the
|
|||
|
TSPI_providerInit procedure.
|
|||
|
|
|||
|
pfnPhoneCreateProc - Specifies a far pointer to the PHONEEVENT callback
|
|||
|
procedure supplied by TAPI.DLL. The service provider will use this
|
|||
|
function to send PHONE_CREATE messages when a new phone device needs
|
|||
|
to be created. This function should not be called to send a
|
|||
|
PHONE_CREATE message until after the service provider has returned
|
|||
|
from the TSPI_providerInit procedure.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the request is successful or a negative error number if
|
|||
|
an error has occurred. Possible return values are:
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
WSADATA wsaData;
|
|||
|
WORD wVersionRequested = H323_WINSOCKVERSION;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(pdwNumPhones); // no phone support
|
|||
|
UNREFERENCED_PARAMETER(pfnPhoneCreateProc); // no dynamic phones
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID); // legacy parameter
|
|||
|
|
|||
|
// initialize winsock stack
|
|||
|
WSAStartup(wVersionRequested, &wsaData);
|
|||
|
|
|||
|
// lock provider
|
|||
|
H323LockProvider();
|
|||
|
|
|||
|
// save provider handle
|
|||
|
g_hProvider = hProvider;
|
|||
|
|
|||
|
// save line create tapi callback
|
|||
|
g_pfnLineEventProc = pfnLineCreateProc;
|
|||
|
|
|||
|
// install defaults
|
|||
|
H323SetDefaultConfig();
|
|||
|
|
|||
|
// load registry parameters
|
|||
|
H323GetConfigFromRegistry();
|
|||
|
|
|||
|
// initialize line table
|
|||
|
if (!H323AllocLineTable(&g_pLineTable)) {
|
|||
|
|
|||
|
// shutdown
|
|||
|
WSACleanup();
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// could not create line table
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"service provider supports %d line(s).\n",
|
|||
|
g_pLineTable->dwNumInUse
|
|||
|
));
|
|||
|
|
|||
|
// report number of interfaces
|
|||
|
*pdwNumLines = g_pLineTable->dwNumInUse;
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerInit(
|
|||
|
DWORD dwTSPIVersion,
|
|||
|
DWORD dwPermanentProviderID,
|
|||
|
DWORD dwLineDeviceIDBase,
|
|||
|
DWORD dwPhoneDeviceIDBase,
|
|||
|
DWORD_PTR dwNumLines,
|
|||
|
DWORD_PTR dwNumPhones,
|
|||
|
ASYNC_COMPLETION pfnCompletionProc,
|
|||
|
LPDWORD pdwTSPIOptions
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initializes the service provider, also giving it parameters required for
|
|||
|
subsequent operation.
|
|||
|
|
|||
|
This function is guaranteed to be called before any of the other functions
|
|||
|
prefixed with TSPI_line or TSPI_phone except TSPI_lineNegotiateTSPIVersion.
|
|||
|
It is strictly paired with a subsequent call to TSPI_providerShutdown. It
|
|||
|
is the caller's reponsibility to ensure proper pairing.
|
|||
|
|
|||
|
Note that a service provider should perform as many consistency checks as
|
|||
|
is practical at the time TSPI_providerInit is called to ensure that it is
|
|||
|
ready to run. Some consistency or installation errors, however, may not be
|
|||
|
detectable until the operation is attempted. The error LINEERR_NODRIVER can
|
|||
|
be used to report such non-specific errors at the time they are detected.
|
|||
|
|
|||
|
There is no directly corresponding function at the TAPI level. At that
|
|||
|
level, multiple different usage instances can be outstanding, with an
|
|||
|
"application handle" returned to identify the instance in subsequent
|
|||
|
operations. At the TSPI level, the interface architecture supports only a
|
|||
|
single usage instance for each distinct service provider.
|
|||
|
|
|||
|
A new parameter, lpdwTSPIOptions, is added to this function. This parameter
|
|||
|
allows the service provider to return bits indicating optional behaviors
|
|||
|
desired of TAPI. TAPI sets the options DWORD to 0 before calling
|
|||
|
TSPI_providerInit, so if the service provider doesn't want any of these
|
|||
|
options, it can just leave the DWORD set to 0.
|
|||
|
|
|||
|
At this time, only one bit is defined to be returned through this pointer:
|
|||
|
LINETSPIOPTION_NONREENTRANT. The service provider sets this bit if it is
|
|||
|
not designed for fully pre-emptive, multithreaded, multitasking,
|
|||
|
multiprocessor operation (e.g., updating of global data protected by
|
|||
|
mutexes). When this bit is set, TAPI will only make one call at a time to
|
|||
|
the service provider; it will not call any other entry point, nor that
|
|||
|
entry point again, until the service provider returns from the original
|
|||
|
function call. Without this bit set, TAPI may call into multiple service
|
|||
|
provider entry points, including multiple times to the same entry point,
|
|||
|
simultaneously (actually simultaneously in a multiprocessor system). Note:
|
|||
|
TAPI will not serialize access to TSPI functions that display a dialog
|
|||
|
(TUISPI_lineConfigDialog, TUISPI_lineConfigDialogEdit,
|
|||
|
TUISPI_phoneConfigDialog, TUISPI_providerConfig, TUISPI_providerInstall,
|
|||
|
TUISPI_providerRemove) so that they do not block other TSPI functions
|
|||
|
from being called; the service provider must include internal protection
|
|||
|
on these functions.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwTSPIVersion - Specifies the version of the TSPI definition under which
|
|||
|
this function must operate. The caller may use
|
|||
|
TSPI_lineNegotiateTSPIVersion with the special dwDeviceID
|
|||
|
INITIALIZE_NEGOTIATION to negotiate a version that is guaranteed to be
|
|||
|
acceptible to the service provider.
|
|||
|
|
|||
|
dwPermanentProviderID - Specifies the permanent ID, unique within the
|
|||
|
service providers on this system, of the service provider being
|
|||
|
initialized.
|
|||
|
|
|||
|
dwLineDeviceIDBase - Specifies the lowest device ID for the line devices
|
|||
|
supported by this service provider.
|
|||
|
|
|||
|
dwPhoneDeviceIDBase - Specifies the lowest device ID for the phone devices
|
|||
|
supported by this service provider.
|
|||
|
|
|||
|
dwNumLines - Specifies how many line devices this service provider
|
|||
|
supports.
|
|||
|
|
|||
|
dwNumPhones - Specifies how many line devices this service provider
|
|||
|
supports.
|
|||
|
|
|||
|
pfnCompletionProc - Specifies the procedure the service provider calls to
|
|||
|
report completion of all asynchronously operating procedures on line
|
|||
|
and phone devices.
|
|||
|
|
|||
|
pdwTSPIOptions - A pointer to a DWORD-sized memory location, into which
|
|||
|
the service provider may write a value specifying LINETSPIOPTIONS_
|
|||
|
values.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number if
|
|||
|
an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_INCOMPATIBLEAPIVERSION - The application requested an API
|
|||
|
version or version range that is either incompatible or cannot be
|
|||
|
supported by the Telephony API implementation and/or corresponding
|
|||
|
service provider.
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
LINEERR_RESOURCEUNAVAIL - Insufficient resources to complete the
|
|||
|
operation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(dwNumLines); // legacy parameter
|
|||
|
UNREFERENCED_PARAMETER(dwNumPhones); // legacy parameter
|
|||
|
UNREFERENCED_PARAMETER(dwPhoneDeviceIDBase); // no phone support
|
|||
|
UNREFERENCED_PARAMETER(pdwTSPIOptions); // already thread-safe
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"initializing service provider.\n"
|
|||
|
));
|
|||
|
|
|||
|
// make sure this is a version we support
|
|||
|
if (!H323ValidateTSPIVersion(dwTSPIVersion)) {
|
|||
|
|
|||
|
// incompatible api version
|
|||
|
return LINEERR_INCOMPATIBLEAPIVERSION;
|
|||
|
}
|
|||
|
|
|||
|
// lock provider
|
|||
|
H323LockProvider();
|
|||
|
|
|||
|
// initialize caps
|
|||
|
InitializeTermCaps();
|
|||
|
|
|||
|
// initialize line table using device id base
|
|||
|
if (!H323InitializeLineTable(g_pLineTable, dwLineDeviceIDBase)) {
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// could not update lines
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// start callback thread
|
|||
|
if (!H323StartCallbackThread()) {
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// could not start thread
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// save global service provider info
|
|||
|
g_dwTSPIVersion = dwTSPIVersion;
|
|||
|
g_pfnCompletionProc = pfnCompletionProc;
|
|||
|
g_dwLineDeviceIDBase = dwLineDeviceIDBase;
|
|||
|
g_dwPermanentProviderID = dwPermanentProviderID;
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerShutdown(
|
|||
|
DWORD dwTSPIVersion,
|
|||
|
DWORD dwPermanentProviderID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Shuts down the service provider. The service provider should terminate
|
|||
|
any activities it has in progress and release any resources it has
|
|||
|
allocated.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwTSPIVersion - Specifies the version of the TSPI definition under which
|
|||
|
this function must operate. The caller may use
|
|||
|
TSPI_lineNegotiateTSPIVersion or TSPI_phoneNegotiateTSPIVersion with
|
|||
|
the special dwDeviceID INITIALIZE_NEGOTIATION to negotiate a version
|
|||
|
that is guaranteed to be acceptible to the service provider.
|
|||
|
|
|||
|
dwPermanentProviderID - Specifies the permanent ID, unique within the
|
|||
|
service providers on this system, of the service provider being
|
|||
|
shut down.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number
|
|||
|
if an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_INCOMPATIBLEAPIVERSION - The application requested an API
|
|||
|
version or version range that is either incompatible or cannot be
|
|||
|
supported by the Telephony API implementation and/or corresponding
|
|||
|
service provider.
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID); // legacy parameter
|
|||
|
|
|||
|
// make sure this is a version we support
|
|||
|
if (!H323ValidateTSPIVersion(dwTSPIVersion)) {
|
|||
|
|
|||
|
// failure
|
|||
|
return LINEERR_INCOMPATIBLEAPIVERSION;
|
|||
|
}
|
|||
|
|
|||
|
// lock provider
|
|||
|
H323LockProvider();
|
|||
|
|
|||
|
// close open line devices
|
|||
|
if( g_pLineTable ) {
|
|||
|
if (!H323CloseLineTable(g_pLineTable)) {
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// failure
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// stop callback thread last
|
|||
|
if (!H323StopCallbackThread()) {
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// could not stop thread
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// release memory for line devices
|
|||
|
if (!H323FreeLineTable(g_pLineTable)) {
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// failure
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// shutdown
|
|||
|
WSACleanup();
|
|||
|
|
|||
|
// re-initialize
|
|||
|
g_pLineTable = NULL;
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerInstall(
|
|||
|
HWND hwndOwner,
|
|||
|
DWORD dwPermanentProviderID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The TSPI_providerInstall function is obsolete. TAPI version 1.4
|
|||
|
or earlier service providers can implement this TSPI function.
|
|||
|
TAPI version 2.0 or later TSPs implement TUISPI_providerInstall.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndOwner - The handle of the parent window in which the function
|
|||
|
can create any dialog box windows that are required during
|
|||
|
installation.
|
|||
|
|
|||
|
dwPermanentProviderID - The service provider's permanent provider
|
|||
|
identifier.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Always returns NOERROR.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(hwndOwner);
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerRemove(
|
|||
|
HWND hwndOwner,
|
|||
|
DWORD dwPermanentProviderID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The TSPI_providerRemove function is obsolete. TAPI version 1.4 or
|
|||
|
earlier service providers can implement this TSPI function. TAPI
|
|||
|
version 2.0 or later TSPs implement TUISPI_providerRemove.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwndOwner - The handle of the parent window in which the function
|
|||
|
can create any dialog box windows that are required during
|
|||
|
installation.
|
|||
|
|
|||
|
dwPermanentProviderID - The service provider's permanent provider
|
|||
|
identifier.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Always returns NOERROR.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNREFERENCED_PARAMETER(hwndOwner);
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_providerUIIdentify(
|
|||
|
LPWSTR pwszUIDLLName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The TSPI_providerUIIdentify function extracts from the service
|
|||
|
provider the fully qualified path to load the service provider's
|
|||
|
UI DLL component.
|
|||
|
|
|||
|
Implementation is mandatory if the service provider implements
|
|||
|
any UI DLL functions.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pwszUIDLLName - Pointer to a block of memory at least MAX_PATH
|
|||
|
in length, into which the service provider must copy a NULL-
|
|||
|
terminated string specifying the fully-qualified path for the
|
|||
|
DLL containing the service provider functions which must execute
|
|||
|
in the process of the calling application.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Always returns NOERROR.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// copy name of our dll as ui dll
|
|||
|
lstrcpyW(pwszUIDLLName,H323_UIDLL);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TUISPI_providerInstall(
|
|||
|
TUISPIDLLCALLBACK pfnUIDLLCallback,
|
|||
|
HWND hwndOwner,
|
|||
|
DWORD dwPermanentProviderID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Implementation of the TUISPI_providerInstall function is the
|
|||
|
service provider's opportunity to install any additional
|
|||
|
"pieces" of the provider into the right directories (or at
|
|||
|
least verifying that they're there) and set up registry entries
|
|||
|
the provider needs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pfnUIDLLCallback - Pointer to a function the UI DLL can call to
|
|||
|
communicate with the service provider DLL to obtain information
|
|||
|
needed to display the dialog box.
|
|||
|
|
|||
|
hwndOwner - The handle of the parent window in which the function
|
|||
|
can create any dialog box windows that are required during
|
|||
|
installation.
|
|||
|
|
|||
|
dwPermanentProviderID - The service provider's permanent provider
|
|||
|
identifier.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number
|
|||
|
if an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_NOMULTIPLEINSTANCE - A telephony service provider which
|
|||
|
does not support multiple instances is listed more than once
|
|||
|
in the [Providers] section in the registry. The application
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HKEY hKey;
|
|||
|
HKEY hKeyTSP;
|
|||
|
LONG lStatus;
|
|||
|
LPSTR pszKey;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(pfnUIDLLCallback);
|
|||
|
UNREFERENCED_PARAMETER(hwndOwner);
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID);
|
|||
|
|
|||
|
// check for previous instance
|
|||
|
if (H323IsTSPAlreadyInstalled()) {
|
|||
|
|
|||
|
// cannot be installed twice
|
|||
|
return LINEERR_NOMULTIPLEINSTANCE;
|
|||
|
}
|
|||
|
|
|||
|
// set key to h323
|
|||
|
pszKey = H323_REGKEY_ROOT;
|
|||
|
|
|||
|
// attempt to open key
|
|||
|
lStatus = RegOpenKeyEx(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
pszKey,
|
|||
|
0,
|
|||
|
KEY_READ,
|
|||
|
&hKey
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus == NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"successfully installed H.323 provider.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
// set key to windows
|
|||
|
pszKey = WINDOWS_REGKEY_ROOT;
|
|||
|
|
|||
|
// attempt to open key
|
|||
|
lStatus = RegOpenKeyEx(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
pszKey,
|
|||
|
0,
|
|||
|
KEY_WRITE,
|
|||
|
&hKey
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx opening windows registry key.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// operation failed
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// attempt to create key
|
|||
|
lStatus = RegCreateKey(
|
|||
|
hKey,
|
|||
|
H323_SUBKEY,
|
|||
|
&hKeyTSP
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx creating tsp registry key.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// operation failed
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"successfully installed H.323 provider.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKeyTSP);
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TUISPI_providerRemove(
|
|||
|
TUISPIDLLCALLBACK pfnUIDLLCallback,
|
|||
|
HWND hwndOwner,
|
|||
|
DWORD dwPermanentProviderID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The TUISPI_providerRemove function asks the user to confirm
|
|||
|
elimination of the service provider.
|
|||
|
|
|||
|
It is the responsibility of the service provider to remove any
|
|||
|
registry entries that the service provider added at addProvider
|
|||
|
time, as well as any other modules and files that are no longer
|
|||
|
needed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pfnUIDLLCallback - Pointer to a function the UI DLL can call to
|
|||
|
communicate with the service provider DLL to obtain information
|
|||
|
needed to display the dialog box.
|
|||
|
|
|||
|
hwndOwner - The handle of the parent window in which the function
|
|||
|
can create any dialog box windows that are required during
|
|||
|
removal.
|
|||
|
|
|||
|
dwPermanentProviderID - The service provider's permanent provider
|
|||
|
identifier.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number
|
|||
|
if an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_NOMEM - Unable to allocate or lock memory.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HKEY hKey;
|
|||
|
LONG lStatus;
|
|||
|
LPSTR pszKey;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(pfnUIDLLCallback);
|
|||
|
UNREFERENCED_PARAMETER(hwndOwner);
|
|||
|
UNREFERENCED_PARAMETER(dwPermanentProviderID);
|
|||
|
|
|||
|
// set key to h323
|
|||
|
pszKey = H323_REGKEY_ROOT;
|
|||
|
|
|||
|
// attempt to open key
|
|||
|
lStatus = RegOpenKeyEx(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
pszKey,
|
|||
|
0,
|
|||
|
KEY_READ,
|
|||
|
&hKey
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"successfully removed H.323 provider.\n"
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// set key to windows
|
|||
|
pszKey = WINDOWS_REGKEY_ROOT;
|
|||
|
|
|||
|
// attempt to open key
|
|||
|
lStatus = RegOpenKeyEx(
|
|||
|
HKEY_LOCAL_MACHINE,
|
|||
|
pszKey,
|
|||
|
0,
|
|||
|
KEY_WRITE,
|
|||
|
&hKey
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx opening windows registry key.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// operation failed
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// attempt to delete key
|
|||
|
lStatus = RegDeleteKey(
|
|||
|
hKey,
|
|||
|
H323_SUBKEY
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (lStatus != NOERROR) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx deleting tsp registry key.\n",
|
|||
|
lStatus
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// operation failed
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"successfully removed H.323 provider.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release handle
|
|||
|
RegCloseKey(hKey);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|