windows-nt/Source/XPSP1/NT/net/tapi/client/tapimmc.c
2020-09-26 16:20:57 +08:00

1283 lines
29 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
tapimmc.c
Abstract:
Client-side implementation of TAPI MMC support APIs
Author:
Dan Knudson (DanKn) 10-Dec-1997
Revision History:
Notes:
--*/
#include "windows.h"
#include "stdarg.h"
#include "stdio.h"
#include "tapi.h"
#include "tspi.h"
#include "utils.h"
#include "tapimmc.h"
#include "client.h"
#include "clntprivate.h"
#include "tapsrv.h"
#include "lmcons.h"
#include "resource.h"
#define MMCAPP_KEY ((DWORD) 'CmMt')
typedef struct _MMCAPP
{
DWORD dwKey;
BOOL bLocal;
HLINEAPP hLineApp;
DWORD dwAPIVersion;
HANDLE hReinitializeEvent;
PCONTEXT_HANDLE_TYPE phCtx; // RPC handle context
BOOL bNoServiceControl;
} MMCAPP, *PMMCAPP;
LONG
WINAPI
FreeClientResources(
void
);
PMMCAPP
PASCAL
IsValidMmcApp(
HMMCAPP hMmcApp
)
{
PMMCAPP pMmcApp = NULL;
try
{
if (((PMMCAPP) hMmcApp)->dwKey == MMCAPP_KEY)
{
pMmcApp = (PMMCAPP) hMmcApp;
}
}
except (EXCEPTION_EXECUTE_HANDLER)
{
// do nothing
}
return pMmcApp;
}
LONG
WINAPI
MMCAddProvider(
HMMCAPP hMmcApp,
HWND hwndOwner,
LPCWSTR lpszProviderFilename,
LPDWORD lpdwProviderID
)
{
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
lResult = lineAddProviderW(
lpszProviderFilename,
hwndOwner,
lpdwProviderID
);
}
else
{
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = lineAddProviderW(
lpszProviderFilename,
hwndOwner,
lpdwProviderID
);
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCConfigProvider(
HMMCAPP hMmcApp,
HWND hwndOwner,
DWORD dwProviderID
)
{
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
lResult = lineConfigProvider (hwndOwner, dwProviderID);
}
else
{
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = lineConfigProvider (hwndOwner, dwProviderID);
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCGetAvailableProviders(
HMMCAPP hMmcApp,
LPAVAILABLEPROVIDERLIST lpProviderList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mGetAvailableProviders),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpProviderList
},
{
hXxxApp,
lpGet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "GetAvailableProviders");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "GetAvailableProviders");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCGetLineInfo(
HMMCAPP hMmcApp,
LPDEVICEINFOLIST lpDeviceInfoList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mGetLineInfo),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpDeviceInfoList
},
{
hXxxApp,
lpGet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "GetLineInfo");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "GetLineInfo");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
#define MAX_DEFAULT_STATUS 64
extern HINSTANCE g_hInst;
LONG
WINAPI
MMCGetLineStatus(
HMMCAPP hMmcApp,
HWND hwndOwner,
DWORD dwStatusLevel,
DWORD dwProviderID,
DWORD dwPermanentLineID,
LPVARSTRING lpStatusBuffer
)
{
static WCHAR szDefStatus[MAX_DEFAULT_STATUS] = L"";
static int cbCount;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
return LINEERR_INVALAPPHANDLE;
}
if (!lpStatusBuffer ||
IsBadWritePtr (lpStatusBuffer, sizeof (*lpStatusBuffer)))
{
return LINEERR_INVALPOINTER;
}
if (lpStatusBuffer->dwTotalSize < sizeof (*lpStatusBuffer))
{
return LINEERR_STRUCTURETOOSMALL;
}
if (0 == cbCount ||
0 == szDefStatus[0])
{
cbCount = LoadString (g_hInst, IDS_DEFAULT_STATUS, szDefStatus, MAX_DEFAULT_STATUS);
cbCount = (cbCount+1)<<1; // + 1 because LoadString does not count the terminating NULL;
// <<1 because we need the size in bytes, not characters, and WCHAR is 2 bytes.
}
lpStatusBuffer->dwNeededSize = sizeof (*lpStatusBuffer) + cbCount;
if (lpStatusBuffer->dwTotalSize >= lpStatusBuffer->dwNeededSize)
{
lpStatusBuffer->dwStringFormat = STRINGFORMAT_UNICODE;
lpStatusBuffer->dwStringSize = cbCount;
lpStatusBuffer->dwStringOffset = sizeof (*lpStatusBuffer);
wcscpy ((WCHAR *) (lpStatusBuffer + 1), szDefStatus);
}
else
{
lpStatusBuffer->dwUsedSize = sizeof (*lpStatusBuffer);
lpStatusBuffer->dwStringFormat =
lpStatusBuffer->dwStringSize =
lpStatusBuffer->dwStringOffset = 0;
}
return 0;
}
LONG
WINAPI
MMCGetPhoneInfo(
HMMCAPP hMmcApp,
LPDEVICEINFOLIST lpDeviceInfoList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mGetPhoneInfo),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpDeviceInfoList
},
{
hXxxApp,
lpGet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "GetPhoneInfo");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "GetPhoneInfo");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCGetPhoneStatus(
HMMCAPP hMmcApp,
HWND hwndOwner,
DWORD dwStatusLevel,
DWORD dwProviderID,
DWORD dwPermanentLineID,
LPVARSTRING lpStatusBuffer
)
{
static WCHAR szDefStatus[MAX_DEFAULT_STATUS] = L"";
static int cbCount;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
return LINEERR_INVALAPPHANDLE;
}
if (!lpStatusBuffer ||
IsBadWritePtr (lpStatusBuffer, sizeof (*lpStatusBuffer)))
{
return LINEERR_INVALPOINTER;
}
if (lpStatusBuffer->dwTotalSize < sizeof (*lpStatusBuffer))
{
return LINEERR_STRUCTURETOOSMALL;
}
if (0 == cbCount ||
0 == szDefStatus[0])
{
cbCount = LoadString (g_hInst, IDS_DEFAULT_STATUS, szDefStatus, MAX_DEFAULT_STATUS);
cbCount = (cbCount+1)<<1; // + 1 because LoadString does not count the terminating NULL;
// <<1 because we need the size in bytes, not characters, and WCHAR is 2 bytes.
}
lpStatusBuffer->dwNeededSize = sizeof (*lpStatusBuffer) + cbCount;
if (lpStatusBuffer->dwTotalSize >= lpStatusBuffer->dwNeededSize)
{
lpStatusBuffer->dwStringFormat = STRINGFORMAT_UNICODE;
lpStatusBuffer->dwStringSize = cbCount;
lpStatusBuffer->dwStringOffset = sizeof (*lpStatusBuffer);
wcscpy ((WCHAR *) (lpStatusBuffer + 1), szDefStatus);
}
else
{
lpStatusBuffer->dwUsedSize = sizeof (*lpStatusBuffer);
lpStatusBuffer->dwStringFormat =
lpStatusBuffer->dwStringSize =
lpStatusBuffer->dwStringOffset = 0;
}
return 0;
}
LONG
WINAPI
MMCGetProviderList(
HMMCAPP hMmcApp,
LPLINEPROVIDERLIST lpProviderList
)
{
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
lResult = lineGetProviderListW(
pMmcApp->dwAPIVersion,
lpProviderList
);
}
else
{
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = lineGetProviderListW(
pMmcApp->dwAPIVersion,
lpProviderList
);
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCGetServerConfig(
HMMCAPP hMmcApp,
LPTAPISERVERCONFIG lpConfig
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mGetServerConfig),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpConfig
},
{
hXxxApp,
lpGet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "GetServerConfig");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "GetServerConfig");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
if (lpConfig && pMmcApp && pMmcApp->bNoServiceControl)
{
lpConfig->dwFlags |= TAPISERVERCONFIGFLAGS_NOSERVICECONTROL;
}
ExitHere:
return lResult;
}
LONG
WINAPI
EnsureTapiService(LPCWSTR lpszComputerName, DWORD * pdwServiceState)
{
SC_HANDLE hSCMgr = NULL;
SC_HANDLE hTapiSrv = NULL;
LONG lResult = 0;
DWORD dwNumSecondsSleptStartPending = 0,
dwNumSecondsSleptStopPending = 0;
SERVICE_STATUS status;
BOOL bBreakOut = FALSE;
if ((hSCMgr = OpenSCManagerW(
lpszComputerName, // Machine name
NULL, // ServicesActive database
SC_MANAGER_CONNECT // desired access
)) == NULL)
{
lResult = GetLastError();
LOG((TL_ERROR, "OpenSCManager failed, err=%d", lResult));
goto ExitHere;
}
if ((hTapiSrv = OpenServiceW(
hSCMgr, // SC mgr handle
L"TAPISRV", // name of service to open
SERVICE_START | // desired access
SERVICE_QUERY_STATUS |
SERVICE_STOP |
SERVICE_CHANGE_CONFIG
)) == NULL)
{
lResult = GetLastError() | 0x80000000;
LOG((TL_ERROR, "OpenService failed, err=%d", GetLastError()));
goto ExitHere;
}
while (1)
{
QueryServiceStatus (hTapiSrv, &status);
switch (status.dwCurrentState)
{
case SERVICE_RUNNING:
LOG((TL_INFO, "Tapisrv running"));
bBreakOut = TRUE;
break;
case SERVICE_START_PENDING:
Sleep (1000);
if (++dwNumSecondsSleptStartPending > 180)
{
// Wait for no longer than 3 minutes
LOG((TL_ERROR, "ERROR: Tapisrv stuck SERVICE_START_PENDING"));
bBreakOut = TRUE;
}
break;
case SERVICE_STOP_PENDING:
Sleep (1000);
if (++dwNumSecondsSleptStopPending > 180)
{
// Wait for no more than 3 minutes
LOG((TL_ERROR, "ERROR: Tapisrv stuck SERVICE_STOP_PENDING"));
bBreakOut = TRUE;
}
break;
case SERVICE_STOPPED:
LOG((TL_INFO, "Starting tapisrv (NT)..."));
if (!StartService(
hTapiSrv, // service handle
0, // num args
NULL // args
))
{
lResult = GetLastError();
if (lResult != ERROR_SERVICE_ALREADY_RUNNING)
{
LOG((TL_ERROR,
"StartService(TapiSrv) failed, err=%d",
lResult
));
bBreakOut = TRUE;
}
else
{
lResult = 0;
}
}
break;
default:
LOG((TL_ERROR, "error, service status=%d",
status.dwCurrentState));
lResult = GetLastError();
bBreakOut = TRUE;
break;
}
if (bBreakOut)
{
break;
}
}
if (pdwServiceState)
{
*pdwServiceState = status.dwCurrentState;
}
ExitHere:
if (hSCMgr)
CloseServiceHandle(hSCMgr);
if (hTapiSrv)
CloseServiceHandle(hTapiSrv);
return lResult;
}
LONG
WINAPI
MMCInitialize(
LPCWSTR lpszComputerName,
LPHMMCAPP lphMmcApp,
LPDWORD lpdwAPIVersion,
HANDLE hReinitializeEvent
)
{
LONG lResult = 0;
LONG lSrvResult = 0;
DWORD dwSize;
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1] = L"";
PMMCAPP pMmcApp;
if ((lpszComputerName &&
IsBadStringPtrW (lpszComputerName, 0xffffffff)) ||
IsBadWritePtr (lphMmcApp, sizeof (*lphMmcApp)) ||
IsBadWritePtr (lpdwAPIVersion, sizeof (*lpdwAPIVersion)))
{
return LINEERR_INVALPOINTER;
}
if (!(pMmcApp = ClientAlloc (sizeof (*pMmcApp))))
{
return LINEERR_NOMEM;
}
dwSize = sizeof (szComputerName) / sizeof (WCHAR);
GetComputerNameW (szComputerName, &dwSize);
lSrvResult = EnsureTapiService(lpszComputerName, NULL);
if (!lpszComputerName || _wcsicmp (lpszComputerName, szComputerName) == 0)
{
pMmcApp->bLocal = TRUE;
}
else
{
// We need to manage another computer
RPC_STATUS status, status2;
BOOL bRet;
BOOL bException = FALSE;
HANDLE hAsyncEventsEvent = NULL;
LPWSTR pszStringBinding;
WCHAR szUserName[UNLEN + 1];
dwSize = sizeof(szUserName) / sizeof(WCHAR);
bRet = GetUserNameW(szUserName, &dwSize);
if (!bRet)
{
lResult = GetLastError();
LOG((TL_ERROR, "GetUserNameW failed: err=%d", lResult));
goto ExitHere;
}
// Init the RPC connection with the server
status = RpcStringBindingComposeW (
NULL, // ObjUuid
L"ncacn_np", // ProtSeq
(LPWSTR)lpszComputerName, // NetworkAddr
L"\\pipe\\tapsrv", // EndPoint
NULL, // Options
&pszStringBinding); // StringBinding
if (status)
{
LOG((TL_ERROR, "RpcStringBindingCompose failed: err=%d", status));
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
status = RpcBindingFromStringBindingW(
pszStringBinding, // StringBinding
&hTapSrv); // Binding
status2 = RpcStringFreeW(&pszStringBinding);
if (status || status2)
{
LOG((TL_ERROR, "RpcBindingFromStringBinding failed: err=%d", status));
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
status = RpcBindingSetAuthInfoW (
hTapSrv, // hBinding
NULL, // ServerPrincName
RPC_C_AUTHN_LEVEL_DEFAULT, // AuthnLevel
RPC_C_AUTHN_WINNT, // AuthService
NULL, // AuthIdentity
0); // AuthzService
if (status)
{
LOG((TL_ERROR, "RpcBindingSetAuthInfo failed: err=%d", status));
RpcBindingFree(hTapSrv);
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
RpcTryExcept
{
LOG((TL_TRACE, "MMCInitialize: calling ClientAttach..."));
lResult = ClientAttach(
&(pMmcApp->phCtx),
0xfffffffd, // Indicate to the server this is from MMC client
// on another machine
(long *)&hAsyncEventsEvent,
szUserName,
szComputerName
);
LOG((TL_TRACE, "MMCInitialize: ClientAttach returned x%x", lResult));
}
RpcExcept (I_RpcExceptionFilter(RpcExceptionCode()))
{
LOG((TL_TRACE,
"MMCInitialize: ClientAttach caused except=%d",
RpcExceptionCode()
));
bException = TRUE;
}
RpcEndExcept
status = RpcBindingFree(&hTapSrv);
if (status || bException)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
if (lResult)
{
goto ExitHere;
}
pMmcApp->bLocal = FALSE;
}
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!(pMmcApp->bLocal) && !SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
{
DWORD dwNumLines;
LINEINITIALIZEEXPARAMS initExParams;
initExParams.dwTotalSize = sizeof (initExParams);
initExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
lResult = lineInitializeExW(
&pMmcApp->hLineApp,
NULL,
NULL,
NULL,
&dwNumLines,
lpdwAPIVersion,
&initExParams
);
pMmcApp->dwAPIVersion = *lpdwAPIVersion;
}
// Clear the PCONTEXT_TYPE_HANDLE in TLS
if (!(pMmcApp->bLocal) && !SetTlsPCtxHandle(NULL))
{
lResult = LINEERR_OPERATIONUNAVAIL;
}
ExitHere:
if (lResult == 0)
{
pMmcApp->dwKey = MMCAPP_KEY;
*lphMmcApp = (HMMCAPP) pMmcApp;
}
else
{
ClientFree (pMmcApp);
}
if (lSrvResult && (lResult == 0))
{
//
// We have no problem in connecting to the remote computer
// but we can not manipulate its TAPI service, i.e start service
// tell the app about it.
//
pMmcApp->bNoServiceControl = TRUE;
}
return lResult;
}
LONG
WINAPI
MMCRemoveProvider(
HMMCAPP hMmcApp,
HWND hwndOwner,
DWORD dwProviderID
)
{
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
lResult = lineRemoveProvider (dwProviderID, hwndOwner);
}
else
{
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = lineRemoveProvider (dwProviderID, hwndOwner);
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCSetLineInfo(
HMMCAPP hMmcApp,
LPDEVICEINFOLIST lpDeviceInfoList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mSetLineInfo),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpDeviceInfoList
},
{
hXxxApp,
lpSet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "SetLineInfo");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "SetLineInfo");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCSetPhoneInfo(
HMMCAPP hMmcApp,
LPDEVICEINFOLIST lpDeviceInfoList
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mSetPhoneInfo),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpDeviceInfoList
},
{
hXxxApp,
lpSet_Struct
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "SetPhoneInfo");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "SetPhoneInfo");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCSetServerConfig(
HMMCAPP hMmcApp,
LPTAPISERVERCONFIG lpConfig
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 2, mSetServerConfig),
{
(ULONG_PTR) 0,
(ULONG_PTR) lpConfig
},
{
hXxxApp,
lpSet_Struct
}
};
LONG lResult;
DWORD dwFlags;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (lpConfig && pMmcApp)
{
dwFlags = lpConfig->dwFlags;
lpConfig->dwFlags &= (~TAPISERVERCONFIGFLAGS_NOSERVICECONTROL);
}
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "SetServerConfig");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "SetServerConfig");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
if (lpConfig && pMmcApp)
{
lpConfig->dwFlags = dwFlags;
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCGetDeviceFlags(
HMMCAPP hMmcApp,
BOOL bLine,
DWORD dwProviderID,
DWORD dwPermanentDeviceID,
DWORD * pdwFlags,
DWORD * pdwDeviceID
)
{
FUNC_ARGS funcArgs =
{
MAKELONG (LINE_FUNC | SYNC | 6, mGetDeviceFlags),
{
(ULONG_PTR) 0,
(ULONG_PTR) bLine,
(ULONG_PTR) dwProviderID,
(ULONG_PTR) dwPermanentDeviceID,
(ULONG_PTR) pdwFlags,
(ULONG_PTR) pdwDeviceID,
},
{
hXxxApp,
Dword,
Dword,
Dword,
lpDword,
lpDword
}
};
LONG lResult;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
lResult = DOFUNC (&funcArgs, "SetPhoneInfo");
}
else
{
funcArgs.Args[0] = (ULONG_PTR) pMmcApp->hLineApp;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = DOFUNC (&funcArgs, "SetPhoneInfo");
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
}
ExitHere:
return lResult;
}
LONG
WINAPI
MMCShutdown(
HMMCAPP hMmcApp
)
{
LONG lResult = 0;
PMMCAPP pMmcApp = IsValidMmcApp (hMmcApp);
if (!pMmcApp)
{
lResult = LINEERR_INVALAPPHANDLE;
}
else if (pMmcApp->bLocal)
{
pMmcApp->dwKey = 0xfffffffe;
lResult = lineShutdown (pMmcApp->hLineApp);
ClientFree (pMmcApp);
//
// #196350 - After enabling tapi as a server the MMC does a
// FreeLibrary on us, thinking that we'll terminate our rpc
// connection with the tapisrv, so it can shutdown tapisrv
// and restart it w/ different credentials, etc. However,
// the MMC is linked with CSCUI.DLL, who in turn links with
// a RAS DLL, who in turn links with TAPI32.DLL, therefore
// we never actually get unloaded. Since we don't otherwise
// deal with the service going down at this point, we want
// to manually call FreeClientResources() to make it seem
// like we've never been talking to tapisrv.
//
// Not needed anymore, now lineShutdown closes the RPC connection
// FreeClientResources();
}
else if (pMmcApp->phCtx)
{
pMmcApp->dwKey = 0xfffffffe;
// Set the PCONTEXT_TYPE_HANDLE for lineInializeExW to use
if (!SetTlsPCtxHandle(pMmcApp->phCtx))
{
lResult = LINEERR_OPERATIONUNAVAIL;
goto ExitHere;
}
lResult = lineShutdown (pMmcApp->hLineApp);
if (!SetTlsPCtxHandle(NULL) && !lResult)
{
lResult = LINEERR_OPERATIONUNAVAIL;
}
RpcTryExcept
{
ClientDetach (&(pMmcApp->phCtx));
}
RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
{
// do something?
}
RpcEndExcept
pMmcApp->phCtx = NULL;
ClientFree (pMmcApp);
}
ExitHere:
return lResult;
}