diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/unimodem/tapisp/umdminit.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/unimodem/tapisp/umdminit.c')
-rw-r--r-- | private/unimodem/tapisp/umdminit.c | 2792 |
1 files changed, 2792 insertions, 0 deletions
diff --git a/private/unimodem/tapisp/umdminit.c b/private/unimodem/tapisp/umdminit.c new file mode 100644 index 000000000..aa4ec1ad5 --- /dev/null +++ b/private/unimodem/tapisp/umdminit.c @@ -0,0 +1,2792 @@ +//**************************************************************************** +// +// Module: Unimdm.tsp +// File: umdminit.c +// Content: This file contains the moudle initialization. +// +// Copyright (c) 1992-1993, Microsoft Corporation, all rights reserved +// +// History: +// Tue 23-Feb-1993 14:08:25 -by- Viroon Touranachun [viroont] +// Ported from TAPI's atsp +// +//**************************************************************************** + +#include "unimdm.h" +#include "umdmspi.h" +#include <regstr.h> + +#include "common.h" + +#define _INC_OLE +#include <ole2.h> + +#define INITGUID +#include <initguid.h> +#include <devguid.h> + +#include <setupapi.h> + +#include <rovdbg.h> + +//**************************************************************************** +// Modem enumeration request +//**************************************************************************** + +typedef struct CountInfo{ + UINT cModem; +} COUNTINFO, FAR* LPCOUNTINFO; + +typedef struct InitInfo{ + DWORD dwBaseID; + UINT cModem; +} INITINFO, FAR* LPINITINFO; + +typedef struct FindInfo{ + LPTSTR lpszDeviceName; + BOOL fFound; + HKEY FAR* lphkey; + LPTSTR lpszID; + UINT cbID; +} FINDINFO, FAR* LPFINDINFO; + + +typedef DWORD APIENTRY +PRIVATEGETDEFCOMMCONFIG( + HKEY hKey, + LPCOMMCONFIG pcc, + LPDWORD pdwSize + ); + + +//**************************************************************************** +// GLOBALS +//**************************************************************************** +struct { + + // Cache for hdevinfo, the handle returned by expensive function + // SetupDiGetClassDevsW. + HDEVINFO hdevinfo; + DWORD dwcRefHDevInfo; + + // Cache for MODEMUI DLL and it's "PrivateDefCommConfig" export. + HINSTANCE hModemUIDLL; + DWORD dwcRefModemUI; + PRIVATEGETDEFCOMMCONFIG + *pfnPrivateDefCommConfig; + + // Cache for whether current process has admin priveleges. + BOOL bAdminUser; + + // Handle of thread that processes cpl notifications. + HANDLE hthrdCplNotif; + + CRITICAL_SECTION crit; + + CRITICAL_SECTION critCplNotif; // Critical section used ONLY to + //serialize launching the tepCplNotif thread. +} gUmdm; + + +// This is declared in unimdm.h, and is accessed by the MCX part as well. +DWORD gRegistryFlags; + +#define USER_IS_ADMIN() (gUmdm.bAdminUser) + +//**************************************************************************** +// Constant Parameters +//**************************************************************************** + +LPGUID g_pguidModem = (LPGUID)&GUID_DEVCLASS_MODEM; + +TCHAR cszFriendlyName[] = TEXT("FriendlyName"); +TCHAR cszDeviceType[] = TEXT("DeviceType"); +#ifdef VOICEVIEW +TCHAR cszVoiceView[] = TEXT("VoiceView"); +#endif // VOICEVIEW +TCHAR cszID[] = TEXT("ID"); +TCHAR cszProperties[] = TEXT("Properties"); +TCHAR cszSettings[] = TEXT("Settings"); +TCHAR cszDialSuffix[] = TEXT("DialSuffix"); +TCHAR cszDevicePrefix[] = TEXT("\\\\.\\"); + +#define HAYES_COMMAND_LENGTH 40 // max size for DialSuffix (from VxD) + +TCHAR cszHWNode[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E96D-E325-11CE-BFC1-08002BE10318}"); + +TCHAR gszTSPFilename[MAX_PATH]; + + +#ifdef WINNT +extern CRITICAL_SECTION ServiceControlerCriticalSection; +#endif // WINNT + + +// Private function prototypes +// + +LONG DevlineGetDefaultConfig(PLINEDEV pLineDev, HKEY hKey); + +BOOL _ProcessAttach(HINSTANCE hDll); +BOOL _ProcessDetach(HINSTANCE hDll); +LONG DevlineEnum(LPDWORD lpdwNumLines); +LONG DevlineInitialize (DWORD dwBaseID, LPDWORD lpdwNumDevs); +LONG DevlineShutdown (); +void CleanupLineDev(PLINEDEV pLineDev); +PLINEDEV CreateLineDev(HKEY hKeyHardware, DWORD dwID, BOOL fReCreate); +BOOL PUBLIC IsAdminUser(void); // common code from ../rovcomm.lib + + +typedef BOOL (*ENUMMDMCALLBACK)(HKEY, LPVOID); + +BOOL CountModemCallback (HKEY hkey, LPVOID lpData); +BOOL InitModemCallback (HKEY hkey, LPVOID lpData); +void FreeHDevInfo(HDEVINFO hdevinfo); +HDEVINFO GetHDevInfo(DWORD dwDIGCF); +BOOL LoadModemUI(void); +void UnloadModemUI(void); +void CplNotifComplete(BOOL fWait); +LONG EnumerateModems (ENUMMDMCALLBACK pfnCallback, LPVOID lpData, BOOL fAll); + +typedef BOOL (*ENUMMDMKEYCALLBACK)(HKEY, LPTSTR, LPVOID); + +BOOL SearchModemCallback (HKEY hkey, LPTSTR szKey, LPVOID lpData); +LONG EnumerateModemKeys (ENUMMDMKEYCALLBACK pfnCallback, LPVOID lpData); + +LONG PASCAL ProviderInstall(LPTSTR pszProviderName, BOOL bNoMultipleInstance); + +void tspInitGlobals(void); +void tspDeInitGlobals(void); + +VOID WINAPI +UI_ProcessAttach( + VOID + ); + +VOID WINAPI +UI_ProcessDetach( + VOID + ); + +LONG WINAPI +StopModemDriver( + VOID + ); + + + +//**************************************************************************** +// BOOL _Processattach (HINSTANCE) +// +// Function: This function is called when a process is attached to the DLL +// +// History: +// Mon 06-Sep-1993 09:20:10 -by- Viroon Touranachun [viroont] +// Ported from Shell. +//**************************************************************************** + +BOOL _ProcessAttach(HINSTANCE hDll) +{ + BOOL fRet; + +#ifdef DEBUG + // We do this simply to load the debug .ini flags + // + RovComm_ProcessIniFile(); + + DEBUG_BREAK(BF_ONPROCESSATT); + TRACE_MSG(TF_GENERAL, "Process Attach (hDll = %lx)", hDll); +#endif + InitializeCriticalSection(&gUmdm.crit); + InitializeCriticalSection(&gUmdm.critCplNotif); + + traceOnProcessAttach(); + + UI_ProcessAttach(); + + // Initialize line device lists + // + fRet = InitCBList(hDll); + if (fRet) + { + // Remember our instance and module name + // + ghInstance = hDll; + GetModuleFileName(hDll, + gszTSPFilename, + sizeof(gszTSPFilename)/sizeof(TCHAR)); + + fRet = OverPoolInit(); + + if (!fRet) + { + DeinitCBList(hDll); + } + + }; + + if (!fRet) + { + traceOnProcessDetach(); + DeleteCriticalSection(&gUmdm.crit); + DeleteCriticalSection(&gUmdm.critCplNotif); + } + + return fRet; +} + +//**************************************************************************** +// BOOL _ProcessDetach (HINSTANCE) +// +// Function: This function is called when a process is detached from the DLL +// +// History: +// Mon 06-Sep-1993 09:20:10 -by- Viroon Touranachun [viroont] +// Ported from Shell. +//**************************************************************************** + +BOOL _ProcessDetach(HINSTANCE hDll) +{ + DEBUG_CODE( TRACE_MSG(TF_GENERAL, "Process Detach (hDll = %lx)", hDll); ) + DEBUG_CODE( DEBUG_BREAK(BF_ONPROCESSDET); ) + + // Clean up the allocated resources + // + DeinitCBList(hDll); + OverPoolDeinit(); + UI_ProcessDetach(); + ghInstance = NULL; + traceOnProcessDetach(); + DeleteCriticalSection(&gUmdm.crit); + DeleteCriticalSection(&gUmdm.critCplNotif); + return TRUE; +} + +//**************************************************************************** +// BOOL APIENTRY LibMain (HINSTANCE, DWORD, LPVOID) +// +// Function: This function is called when the DLL is loaded +// +// History: +// Mon 06-Sep-1993 09:20:10 -by- Viroon Touranachun [viroont] +// Ported from Shell. +//**************************************************************************** + +BOOL APIENTRY DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + switch(dwReason) + { + case DLL_PROCESS_ATTACH: + _ProcessAttach(hDll); + break; + case DLL_PROCESS_DETACH: + _ProcessDetach(hDll); + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + default: + break; + } // end switch() + + return TRUE; + +} + +//**************************************************************************** +//************************** The Initialization Calls************************* +//**************************************************************************** + +//**************************************************************************** +// LONG +// TSPIAPI +// TSPI_providerInstall( +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: Let's telephony CPL know the Remove function is supported. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG +TSPIAPI +TSPI_providerInstall( + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + // + // Although this func is never called by TAPI v2.0, we export + // it so that the Telephony Control Panel Applet knows that it + // can add this provider via lineAddProvider(), otherwise + // Telephon.cpl will not consider it installable + // + // + + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG +// TSPIAPI +// TSPI_providerRemove( +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: Let's telephony CPL know the Install function is supported. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG +TSPIAPI +TSPI_providerRemove( + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + // + // Although this func is never called by TAPI v2.0, we export + // it so that the Telephony Control Panel Applet knows that it + // can remove this provider via lineRemoveProvider(), otherwise + // Telephon.cpl will not consider it removable + // + + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG +// TSPIAPI +// TSPI_providerConfig( +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: Let's telephony CPL know the Config function is supported. +// +// History: +// Thu 21-Dec-1995 18:24:53 -by- Chris Caputo [ccaputo] +// Ported from Win95. +//**************************************************************************** + +LONG +TSPIAPI +TSPI_providerConfig( + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + // + // Although this func is never called by TAPI v2.0, we export + // it so that the Telephony Control Panel Applet knows that it + // can configure this provider via lineConfigProvider(), + // otherwise Telephon.cpl will not consider it configurable + // + + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG +// TSPIAPI +// TUISPI_providerInstall( +// TUISPIDLLCALLBACK lpfnUIDLLCallback, +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: TSPI installation +// +// History: +// Thu 21-Dec-1995 18:24:53 -by- Chris Caputo [ccaputo] +// Ported from TAPI's atsp +//**************************************************************************** + +LONG +TSPIAPI +TUISPI_providerInstall( + TUISPIDLLCALLBACK lpfnUIDLLCallback, + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + return ProviderInstall (TEXT("unimdm.tsp"), TRUE); +} + +//**************************************************************************** +// LONG +// TSPIAPI +// TUISPI_providerRemove( +// TUISPIDLLCALLBACK lpfnUIDLLCallback, +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: TSPI removal +// +// History: +// Thu 21-Dec-1995 18:24:53 -by- Chris Caputo [ccaputo] +// Ported from Win95. +//**************************************************************************** + +LONG +TSPIAPI +TUISPI_providerRemove( + TUISPIDLLCALLBACK lpfnUIDLLCallback, + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG +// TSPIAPI +// TUISPI_providerConfig( +// TUISPIDLLCALLBACK lpfnUIDLLCallback, +// HWND hwndOwner, +// DWORD dwPermanentProviderID +// ) +// +// Function: TUISPI configuration +// +// History: +// Thu 21-Dec-1995 18:24:53 -by- Chris Caputo [ccaputo] +// Ported from Win95. +//**************************************************************************** + +LONG +TSPIAPI +TUISPI_providerConfig( + TUISPIDLLCALLBACK lpfnUIDLLCallback, + HWND hwndOwner, + DWORD dwPermanentProviderID + ) +{ + WinExec("control.exe modem.cpl", SW_SHOW); + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_providerEnumDevices() +// +// Function: TSPI device enumeration entry +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG TSPIAPI TSPI_providerEnumDevices(DWORD dwPermanentProviderID, + LPDWORD lpdwNumLines, + LPDWORD lpdwNumPhones, + HPROVIDER hProvider, + LINEEVENT lpfnLineCreateProc, + PHONEEVENT lpfnPhoneCreateProc) + +{ + DBG_ENTER_UL("TSPI_providerEnumDevices", dwPermanentProviderID); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_providerEnumDevices, + &dwPermanentProviderID + ); + + // Enumerate the number of device + // + DevlineEnum(lpdwNumLines); + *lpdwNumPhones = 0; + + // Initialize the global parameters + // + gfnLineCreateProc = lpfnLineCreateProc; + gdwProviderID = dwPermanentProviderID; + ghProvider = hProvider; + + TRACE4(IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_providerEnumDevices, + &dwPermanentProviderID, + ERROR_SUCCESS); + + DBG_EXIT_UL("TSPI_providerEnumDevices", ERROR_SUCCESS); + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_providerInit(DWORD dwTSPIVersion, DWORD ppid) +// +// Function: Initializes the global data strucutres. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG TSPIAPI TSPI_providerInit(DWORD dwTSPIVersion, + DWORD dwPermanentProviderID, + DWORD dwLineDeviceIDBase, + DWORD dwPhoneDeviceIDBase, + DWORD dwNumLines, + DWORD dwNumPhones, + ASYNC_COMPLETION cbCompletionProc, + LPDWORD lpdwTSPIOptions) +{ + DWORD dwDevicePorts = 0; // Number of modem devices + DWORD retcode ; + BOOL fModemUILoaded=FALSE; + HDEVINFO hdevinfo=NULL; + + DBG_ENTER_UL("TSPI_providerInit", dwPermanentProviderID); + + // Initialize tracing facilities + // + traceInitialize(dwPermanentProviderID); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_providerInit, + &dwTSPIVersion + ); + + ASSERT(gdwProviderID == dwPermanentProviderID); + + + + // Initialize the global parameters + // + tspInitGlobals(); + + // Load MODEMUI.DLL (for private entry points) + fModemUILoaded=TRUE; + if (!LoadModemUI()) + { + fModemUILoaded=FALSE; + goto CleanUp; + } + + + // For the modem device, get the device information + hdevinfo = GetHDevInfo(DIGCF_PRESENT); + if (!hdevinfo) + { + goto CleanUp; + } + + + if (TRACINGENABLED()) + { + cbCompletionProc = traceSetCompletionProc(cbCompletionProc); + } + + gfnCompletionCallback = cbCompletionProc; + + // + // init common modem info list + // + InitializeModemCommonList( + &gCommonList + ); + + InitializeCriticalSection( + &ServiceControlerCriticalSection + ); + + + + // Initialize the line structures + // + retcode = DevlineInitialize(dwLineDeviceIDBase, &dwDevicePorts); + + if (retcode != ERROR_SUCCESS) { + + // + // cleanup common modem info + // + RemoveCommonList( + &gCommonList + ); + + DeleteCriticalSection( + &ServiceControlerCriticalSection + ); + + } + +CleanUp: + + if (hdevinfo != NULL) { + + FreeHDevInfo(hdevinfo); + } + + if(fModemUILoaded) + { + UnloadModemUI(); + } + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_providerInit, + &dwTSPIVersion, + retcode + ); + + if (retcode != ERROR_SUCCESS) + { + // Deinit tracing + // + traceDeinitialize(); + } + + DBG_EXIT_UL("TSPI_providerInit", retcode); + return retcode; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_providerShutdown(DWORD dwTSPIVersion) +// +// Function: Cleans up all the global data structures. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG TSPIAPI TSPI_providerShutdown(DWORD dwTSPIVersion, + DWORD dwPermanentProviderID) +{ + DBG_ENTER_UL("TSPI_providerShutdown", dwTSPIVersion); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_providerShutdown, + &dwTSPIVersion + ); + +#ifdef DYNA_ADDREMOVE + // Complete any re-enumeration that may be in progress.. + // + CplNotifComplete(TRUE); +#endif // DYNA_ADDREMOVE + + // Clean up modem lines + // + DevlineShutdown(); + + + // + // cleanup common modem info + // + RemoveCommonList( + &gCommonList + ); + + // Clean up the global parameters + // + gfnCompletionCallback = NULL; // The async completion callback + gfnLineCreateProc = NULL; + + StopModemDriver(); + + DeleteCriticalSection( + &ServiceControlerCriticalSection + ); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_providerShutdown, + &dwTSPIVersion, + ERROR_SUCCESS + ); + + // DeInit TSP Globals + tspDeInitGlobals(); + + // Deinit tracing + // + traceDeinitialize(); + + DBG_EXIT_UL("TSPI_providerShutdown", ERROR_SUCCESS); + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineNegotiateTSPIVersion() +// +// Function: Negotiates the service provider version. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG TSPIAPI TSPI_lineNegotiateTSPIVersion(DWORD dwDeviceID, + DWORD dwLowVersion, + DWORD dwHighVersion, + LPDWORD lpdwTSPIVersion) +{ + PLINEDEV pLineDev = NULL; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineNegotiateTSPIVersion"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineNegotiateTSPIVersion, + &dwDeviceID + ); + // Check the range of the device ID + // + if((dwDeviceID == INITIALIZE_NEGOTIATION) || + ((pLineDev = GetCBfromID(dwDeviceID)) != NULL)) + { + // Do not use the line device + // + if (pLineDev) + { + RELEASE_LINEDEV(pLineDev); + } + + // Check the version range + // + if((dwLowVersion > MDMSPI_VERSION) || (dwHighVersion < MDMSPI_VERSION)) + { + *lpdwTSPIVersion = 0; + lRet= LINEERR_INCOMPATIBLEAPIVERSION; + goto end; + } + else + { + *lpdwTSPIVersion = MDMSPI_VERSION; + lRet= ERROR_SUCCESS; + goto end; + }; + }; + + // The requested device doesn't exist. + lRet = LINEERR_NODEVICE; + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineNegotiateTSPIVersion, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineNegotiateTSPIVersion", lRet); + + return lRet; + +} + +//**************************************************************************** +// LONG DevlineEnum() +// +// Function: enumerates the current number of modems +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG DevlineEnum(LPDWORD lpdwNumLines) +{ + COUNTINFO ci; + DWORD dwRet; + + ci.cModem = 0; + + if ((dwRet = EnumerateModems(CountModemCallback, (LPVOID)&ci, FALSE)) == ERROR_SUCCESS) + *lpdwNumLines = ci.cModem; + else + *lpdwNumLines = 0; + + return dwRet; +} + +//**************************************************************************** +// LONG DevlineInitialize() +// +// Function: initializes the modem device list +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG DevlineInitialize (DWORD dwBaseID, + LPDWORD lpdwNumDevs) +{ + INITINFO initi; + DWORD dwRet; + + initi.dwBaseID = dwBaseID; + initi.cModem = 0; + + + MdmInitTracing(); + + dwRet = EnumerateModems(InitModemCallback, (LPVOID)&initi, FALSE); + if (dwRet == ERROR_SUCCESS) + { + *lpdwNumDevs = initi.cModem; + // Initialize Timer services + // + if ((dwRet = InitializeMdmTimer()) == ERROR_SUCCESS) + { + // Initialize the asynchronous thread + // + if ((dwRet = InitializeMdmThreads()) != ERROR_SUCCESS) + { + DeinitializeMdmTimer(); + }; + }; + } + else + *lpdwNumDevs = 0; + + if (dwRet!=ERROR_SUCCESS) + { + MdmDeinitTracing(); + } + + return dwRet; +} + +//**************************************************************************** +// LONG DevlineShutdown() +// +// Function: destroys the modem device list and resources +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +//**************************************************************************** + +LONG DevlineShutdown () +{ + PLINEDEV pLineDev; + + // Deinitialize the modem thread + // + DeinitializeMdmThreads(); + DeinitializeMdmTimer(); + + // Destroy the modem line device one at a time. + // + do + { + // If there is another modem to clean up + // + if ((pLineDev = GetFirstCB()) != NULL) + { + // Clean up the allocated resources + // + CleanupLineDev(pLineDev); + RELEASE_LINEDEV(pLineDev); + + // Now delete the modem device + // + DeleteCB(pLineDev); + }; + } + while (pLineDev != NULL); + + MdmDeinitTracing(); + + return ERROR_SUCCESS ; +} + +//**************************************************************************** +// void CleanupLineDev(PLINEDEV) +// +// Function: Frees the resources owned by the modem line device. +// +// Returns: None. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +// +//**************************************************************************** + +void CleanupLineDev(PLINEDEV pLineDev) +{ + int i; + + if (pLineDev->DroppingEvent != NULL) { + + CloseHandle(pLineDev->DroppingEvent); + + pLineDev->DroppingEvent=NULL; + } + + // Clean up the allocated resources + // + if (pLineDev->hIcon != NULL) + { + DestroyIcon(pLineDev->hIcon); + }; + + if (pLineDev->pDevCfg != NULL) { + + LocalFree((HLOCAL)pLineDev->pDevCfg); + + pLineDev->pDevCfg=NULL; + } + +} + +//**************************************************************************** +// PLINEDEV CreateLineDev(HKEY hKey, DWORD dwID, BOOL fReCreate) +// +// Function: Create a new LINEDEV structure and initilaizes it. +// If fReCreate is TRUE, the following happens: +// -- if it exists, it will return NULL, but will set the +// LINEDEVFLAGS_REINIT flag of pLineDev->fdwResources of +// the existing device. +// -- if it does not exist, it will create it, and also set +// the above flag. +// If fReCreate is FALSE, it will not check if the device exists +// and will NOT set the LINEDEVFAGS_REINIT bit. +// +// Returns: a pointer to the new line device CB on success or +// NULL on failure. +// +// History: +// Mon 17-Apr-1995 11:49:53 -by- Viroon Touranachun [viroont] +// Ported from Win95. +// +//**************************************************************************** + +PLINEDEV CreateLineDev(HKEY hKey, DWORD dwID, BOOL fReCreate) +{ + PLINEDEV pLineDev=NULL; + TCHAR rgtchDeviceName[sizeof(pLineDev->szDeviceName)/sizeof(TCHAR)]; + DWORD dwRegSize = sizeof(rgtchDeviceName); + DWORD dwRegType; + DWORD dwRet; + BYTE bDeviceType; + REGDEVCAPS regdevcaps; + HKEY hKeySettings; + int i; + FINDINFO fi; + TCHAR pszTemp[HAYES_COMMAND_LENGTH+1]; + + + // Get the Friendly Name + ASSERT(dwRegSize == sizeof(pLineDev->szDeviceName)); + dwRet = RegQueryValueEx( + hKey, + cszFriendlyName, + NULL, + &dwRegType, + (VOID *) rgtchDeviceName, + &dwRegSize + ); + + if (dwRet != ERROR_SUCCESS || dwRegType != REG_SZ) + { + goto end; + } + +#ifdef DYNA_ADDREMOVE + if (fReCreate) + { + // determine if we've already got this device in our list... + pLineDev = GetCBfromName (rgtchDeviceName); + if (pLineDev) + { + DPRINTF1("ReCreate: Modem exists: %s", rgtchDeviceName); + pLineDev->fdwResources |= LINEDEVFLAGS_REINIT; + pLineDev->fdwResources &= ~LINEDEVFLAGS_OUTOFSERVICE; + RELEASE_LINEDEV(pLineDev); + pLineDev=NULL; + goto end; + } + } +#endif //DYNA_ADDREMOVE + + // New modem! + + if ((pLineDev = AllocateCB(sizeof(LINEDEV))) == NULL) + { + goto end; + } + + pLineDev->DroppingEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (pLineDev->DroppingEvent == NULL) { + + goto FailedExit; + } + + // Initialize its control block + // + // pLineDev->hIcon = NULL; + // pLineDev->pDevCfg = NULL; + // + pLineDev->dwVersion = UMDM_VERSION; + pLineDev->dwID = dwID; + lstrcpy(pLineDev->szDeviceName, rgtchDeviceName); + + // Get the Driver Key + fi.lpszDeviceName = pLineDev->szDeviceName; + fi.fFound = FALSE; + fi.lphkey = NULL; + fi.lpszID = pszTemp; + fi.cbID = sizeof(pszTemp); + EnumerateModemKeys(SearchModemCallback, (LPVOID)&fi); + if (!fi.fFound) + { + goto FailedExit; + } + + lstrcpyn(pLineDev->szDriverKey, cszHWNode, sizeof(pLineDev->szDriverKey)); + lstrcat(pLineDev->szDriverKey, TEXT("\\")); + lstrcat(pLineDev->szDriverKey, pszTemp); + + // Read in the permanent ID + dwRegSize = sizeof(pLineDev->dwPermanentLineID); + if (RegQueryValueEx(hKey, cszID, NULL, &dwRegType, + (VOID *)&pLineDev->dwPermanentLineID, + &dwRegSize) != ERROR_SUCCESS || + dwRegType != REG_BINARY) + { + goto FailedExit; + } + + // Read in the REGDEVCAPS + dwRegSize = sizeof(regdevcaps); + if (RegQueryValueEx(hKey, cszProperties, NULL, &dwRegType, + (VOID *)®devcaps, + &dwRegSize) != ERROR_SUCCESS || + dwRegType != REG_BINARY) + { + goto FailedExit; + } + else + { + // + // We want to make sure the following flags are identical + // + #if (LINEDEVCAPFLAGS_DIALBILLING != DIALOPTION_BILLING) + #error LINEDEVCAPFLAGS_DIALBILLING != DIALOPTION_BILLING (check tapi.h vs. mcx16.h) + #endif + #if (LINEDEVCAPFLAGS_DIALQUIET != DIALOPTION_QUIET) + #error LINEDEVCAPFLAGS_DIALQUIET != DIALOPTION_QUIET (check tapi.h vs. mcx16.h) + #endif + #if (LINEDEVCAPFLAGS_DIALDIALTONE != DIALOPTION_DIALTONE) + #error LINEDEVCAPFLAGS_DIALDIALTONE != DIALOPTION_DIALTONE (check tapi.h vs. mcx16.h) + #endif + // + + // Make sure this is the dwDialOptions DWORD we want. + ASSERT(!(regdevcaps.dwDialOptions & ~(LINEDEVCAPFLAGS_DIALBILLING | + LINEDEVCAPFLAGS_DIALQUIET | + LINEDEVCAPFLAGS_DIALDIALTONE))); + pLineDev->dwDevCapFlags = regdevcaps.dwDialOptions; + + pLineDev->dwMaxDCERate = regdevcaps.dwMaxDCERate; + + pLineDev->dwModemOptions = regdevcaps.dwModemOptions; + } + + // Analyze device type and set mediamodes appropriately + dwRegSize = sizeof(BYTE); + if (RegQueryValueEx(hKey, cszDeviceType, NULL, &dwRegType, + &bDeviceType, &dwRegSize) != ERROR_SUCCESS || + dwRegType != REG_BINARY || + dwRegSize != sizeof(BYTE)) + { + goto FailedExit; + } + else + { + // Remember the type + // + pLineDev->bDeviceType = bDeviceType; + + switch (bDeviceType) + { + case DT_PARALLEL_PORT: + pLineDev->bDeviceType = DT_NULL_MODEM; // Map back to null modem + // FALLTHROUGH + + case DT_NULL_MODEM: + pLineDev->dwDefaultMediaModes = LINEMEDIAMODE_DATAMODEM; + pLineDev->dwBearerModes = LINEBEARERMODE_DATA | LINEBEARERMODE_PASSTHROUGH; + pLineDev->fPartialDialing = FALSE; + break; + + case DT_PARALLEL_MODEM: + pLineDev->bDeviceType = DT_EXTERNAL_MODEM; // Map back to external modem + // FALLTHROUGH + + case DT_EXTERNAL_MODEM: + case DT_INTERNAL_MODEM: + case DT_PCMCIA_MODEM: + pLineDev->dwDefaultMediaModes = LINEMEDIAMODE_DATAMODEM | + LINEMEDIAMODE_INTERACTIVEVOICE; +#ifdef VOICEVIEW + { + BYTE bVoiceView; + + dwRegSize = 1; + if ((RegQueryValueEx(hKeySoftware, cszVoiceView, 0, &dwRegType, &bVoiceView, &dwRegSize) == ERROR_SUCCESS) && + (bVoiceView == 1)) + { + pLineDev->dwDefaultMediaModes |= LINEMEDIAMODE_VOICEVIEW; + } + } +#endif // VOICEVIEW + pLineDev->dwBearerModes = LINEBEARERMODE_VOICE | LINEBEARERMODE_PASSTHROUGH; + + // read in Settings\DialSuffix to check whether we can partial dial + pLineDev->fPartialDialing = FALSE; // assume false + if (RegOpenKey(hKey, cszSettings, &hKeySettings) == ERROR_SUCCESS) + { + dwRegSize = HAYES_COMMAND_LENGTH; + if (RegQueryValueEx(hKeySettings, cszDialSuffix, NULL, &dwRegType, (VOID *)pszTemp, &dwRegSize) == ERROR_SUCCESS && + dwRegSize > sizeof(TCHAR)) + { + pLineDev->fPartialDialing = TRUE; + } + RegCloseKey(hKeySettings); + } + break; + + default: + goto FailedExit; + } + } + + // Init line. + NullifyLineDevice(pLineDev); + + // + // get the default commconfig + // + dwRet = DevlineGetDefaultConfig(pLineDev,hKey); + + if (dwRet != ERROR_SUCCESS) { + + goto FailedExit; + } + + + +#ifdef UNDER_CONSTRUCTION + + // Check the devnode status + // If it does not exist or has a problem, mark it as out of service + // + if (!IsDeviceInService(szID)) + { + pLineDev->fdwResources |= LINEDEVFLAGS_OUTOFSERVICE; + }; + +#endif // UNDER_CONSTRUCTION + + if (fReCreate) + { + pLineDev->fdwResources |= LINEDEVFLAGS_REINIT; + } + + // We made it this far, we're GOLDEN! + goto end; + +FailedExit: + DPRINTF("Modem unusable because of corrupt registry entry."); + + // Cleanup the allocated resource + // + CleanupLineDev(pLineDev); + + // Free the modem CB and its resources + // + DeleteCB(pLineDev); + pLineDev = NULL; + // Fall through... + +end: + + return pLineDev; +} + + +//**************************************************************************** +// LONG DevlineGetDefaultConfig(PLINEDEV) +// +// Function: Get modem default configuratio +// +// Returns: ERROR_SUCCESS if success +// LINEERR_NOMEM if out of memory +// +// Fri 14-Apr-1995 12:47:26 -by- Viroon Touranachun [viroont] +// created +//**************************************************************************** + +LONG DevlineGetDefaultConfig(PLINEDEV pLineDev, HKEY hKey) +{ + PDEVCFG pDevCfg; + COMMCONFIG * pcommconfig; + DWORD dwCCSize; + LONG lResult; + + dwCCSize = sizeof(MODEMSETTINGS)+FIELDOFFSET(COMMCONFIG, wcProviderData); + + pDevCfg = (PDEVCFG)LocalAlloc(LPTR, sizeof(DEVCFGHDR)+(UINT)dwCCSize); + + if (pDevCfg == NULL) { + + return LINEERR_NOMEM; + } + + pcommconfig = (COMMCONFIG *)&(pDevCfg->commconfig); + + // Default setting + // + pDevCfg->dfgHdr.dwSize = sizeof(DEVCFGHDR) + dwCCSize; + pDevCfg->dfgHdr.dwVersion = MDMCFG_VERSION; + SETWAITBONG(pDevCfg, DEF_WAIT_BONG); + SETOPTIONS(pDevCfg, (IS_NULL_MODEM(pLineDev) ? + TERMINAL_NONE : TERMINAL_NONE | LAUNCH_LIGHTS)); + pcommconfig->dwProviderSubType = PST_MODEM; + + ASSERT(gUmdm.pfnPrivateDefCommConfig != NULL); + + lResult=(*gUmdm.pfnPrivateDefCommConfig)(hKey, pcommconfig, &dwCCSize); + + if (ERROR_SUCCESS == lResult) { + + pLineDev->pDevCfg = pDevCfg; + + } else { + + LocalFree( + pDevCfg + ); + } + + + return lResult; + + +} + + + + + + + + + + + +//**************************************************************************** +// BOOL CountModemCallback (HKEY hkey, LPVOID lpData) +// +// Function: Count the enumerated modems. +// +// Returns: TRUE always to continue +// +//**************************************************************************** + +BOOL CountModemCallback (HKEY hkey, LPVOID lpData) +{ + LPCOUNTINFO lpCntInfo = (LPCOUNTINFO)lpData; + + (lpCntInfo->cModem)++; + return TRUE; +} + +//**************************************************************************** +// BOOL InitModemCallback (HKEY hkey, LPVOID lpData) +// +// Function: Initialize the enumerated modems. +// +// Returns: TRUE always to continue +// +//**************************************************************************** + +BOOL InitModemCallback (HKEY hkey, LPVOID lpData) +{ + PLINEDEV pMdmDev; + LPINITINFO lpInitInfo = (LPINITINFO)lpData; + + if ((pMdmDev = CreateLineDev(hkey, + lpInitInfo->dwBaseID + + lpInitInfo->cModem, + FALSE)) != NULL) + { + // Insert into the LINEDEV list + // + AddCBToList(pMdmDev); + (lpInitInfo->cModem)++; + }; + return TRUE; +} + +//**************************************************************************** +// EnumerateModems() +// +// Function: Enumerate the modem. +// +//**************************************************************************** + +LONG NEAR PASCAL EnumerateModems (ENUMMDMCALLBACK pfnCallback, + LPVOID lpData, + BOOL fAll) +{ + HDEVINFO hdevinfo; + SP_DEVINFO_DATA diData; + DWORD iEnum; + BOOL fContinue; + HKEY hkey; + DWORD dwRW = KEY_READ; + // DWORD dwDIGCF = (fAll) ? DIGCF_PROFILE : DIGCF_PRESENT; + BOOL fFreeDevInfo=FALSE; + DWORD dwDIGCF = DIGCF_PRESENT; + if (USER_IS_ADMIN()) dwRW |= KEY_WRITE; + + // Get the device info set + // + hdevinfo = GetHDevInfo(dwDIGCF); + + if (hdevinfo != NULL) + { + // Enumerate each modem + // + fFreeDevInfo=TRUE; + fContinue = TRUE; + iEnum = 0; + diData.cbSize = sizeof(diData); + while(fContinue && SetupDiEnumDeviceInfo(hdevinfo, iEnum, &diData)) + { + // Get the driver key + // + hkey = SetupDiOpenDevRegKey(hdevinfo, &diData, DICS_FLAG_GLOBAL, 0, + DIREG_DRV, dwRW); + if (hkey == INVALID_HANDLE_VALUE) + { + DPRINTF1( + "SetupDiOpenDevRegKeyfailed, err=0x%lx", + GetLastError() + ); + } + else + { + fContinue = (*pfnCallback)(hkey, lpData); + + RegCloseKey(hkey); + }; + + // Find next modem + // + iEnum++; + }; + FreeHDevInfo(hdevinfo); + }; + + + return ERROR_SUCCESS; + +} + +//**************************************************************************** +// BOOL SearchModemCallback (HKEY hkey, LPTSTR szKey, LPVOID lpData) +// +// Function: Search the enumerated modems for a matching modem. +// +// Returns: TRUE if not match and continue searching +// +//**************************************************************************** + +BOOL SearchModemCallback (HKEY hkey, LPTSTR szKey, LPVOID lpData) +{ + LPFINDINFO lpFindInfo = (LPFINDINFO)lpData; + TCHAR szDevice[MAXDEVICENAME+1]; + DWORD dwRegType, dwRegSize; + BOOL fContinue = TRUE; + + // Get the Friendly Name + // + dwRegSize = sizeof(szDevice); + if ((RegQueryValueEx(hkey, cszFriendlyName, NULL, + &dwRegType, (VOID *)szDevice, &dwRegSize) + == ERROR_SUCCESS) && (dwRegType == REG_SZ)) + { + // Is this the device? + // + if (!lstrcmpi(lpFindInfo->lpszDeviceName, szDevice)) + { + // BUG! BUG! the key will be closed + // + if (lpFindInfo->lphkey != NULL) + { + *lpFindInfo->lphkey = hkey; + }; + + // Do we need the Instance ID? + // + if ((lpFindInfo->lpszID != NULL) && + (lpFindInfo->cbID > 0)) + { + // Return the instance ID + // + lstrcpyn(lpFindInfo->lpszID, szKey, + lpFindInfo->cbID); + }; + + // Mark that we found it + lpFindInfo->fFound = TRUE; + fContinue = FALSE; + }; + }; + return fContinue; +} + +//**************************************************************************** +// EnumerateModemKeys() +// +// Function: Enumerate the modem driver key. +// +//**************************************************************************** + +LONG NEAR PASCAL EnumerateModemKeys (ENUMMDMKEYCALLBACK pfnCallback, + LPVOID lpData) +{ + HKEY hkey, hkeyEnumNode; + UINT iEnum; + TCHAR szEnumNode[REGSTR_MAX_VALUE_LENGTH+1]; + BOOL fTerminate; + DWORD dwRegType, dwRegSize; + + // Initialize the global enumeration parameters + // + fTerminate = FALSE; + + // Get the key to the modem hardware node + if (RegOpenKey(HKEY_LOCAL_MACHINE, cszHWNode, &hkey) == ERROR_SUCCESS) + { + // Enumerate the enumerator + iEnum = 0; + while ((!fTerminate) && + (RegEnumKey(hkey, iEnum, szEnumNode, + sizeof(szEnumNode)) == ERROR_SUCCESS )) + { + // Open the modem node for this enumerator + if (RegOpenKey(hkey, szEnumNode, &hkeyEnumNode) == ERROR_SUCCESS) + { + // Allow the callback function to do their stuff + fTerminate = !(*pfnCallback)(hkeyEnumNode, szEnumNode, lpData); + + RegCloseKey(hkeyEnumNode); + }; + iEnum++; + }; + RegCloseKey(hkey); + }; + return ERROR_SUCCESS; +} + +//**************************************************************************** +// LONG +// PASCAL +// ProviderInstall( +// LPTSTR pszProviderName, +// BOOL bNoMultipleInstance +// ) +// +// Function: Check to see if a service provider is already installed. Returns +// appropriate TSPI error code to be passed back from +// TUISPI_providerInstall. +// +// History: +// Thu 21-Dec-1995 18:24:53 -by- Chris Caputo [ccaputo] +// Ported from TAPI's atsp32. Periodically, make sure it is in sync to catch +// any bugs fixed in that code. +//**************************************************************************** + +LONG +PASCAL +ProviderInstall( + LPTSTR pszProviderName, + BOOL bNoMultipleInstance + ) +{ + LONG lResult; + + + // + // If only one installation instance of this provider is + // allowed then we want to check the provider list to see + // if the provider is already installed + // + + if (bNoMultipleInstance) + { + LONG (WINAPI *pfnGetProviderList)(); + DWORD dwTotalSize, i; + HINSTANCE hTapi32; + LPLINEPROVIDERLIST pProviderList; + LPLINEPROVIDERENTRY pProviderEntry; + + + lResult = LINEERR_OPERATIONFAILED; // assume failure + + + // + // Load Tapi32.dll & get a pointer to the lineGetProviderList + // func. We could just statically link with Tapi32.lib and + // avoid the hassle (and this wouldn't have any adverse + // performance effects because of the fact that this + // implementation has a separate ui dll that runs only on the + // client context), but a provider who implemented these funcs + // in it's TSP module would want to do an explicit load like + // we do here to prevent the perf hit of Tapi32.dll always + // getting loaded in Tapisrv.exe's context. + // + + if (!(hTapi32 = LoadLibrary (TEXT("tapi32.dll")))) + { + DPRINTF1( + "LoadLibrary(tapi32.dll) failed, err=%d", + GetLastError() + ); + + goto ProviderInstall_return; + } + + if (!((FARPROC) pfnGetProviderList = GetProcAddress( + hTapi32, +#ifdef UNICODE + (LPCSTR) "lineGetProviderListW" +#else // UNICODE + (LPCSTR) "lineGetProviderList" +#endif // UNICODE + ))) + { + DPRINTF1( + "GetProcAddr(lineGetProviderList) failed, err=%d", + GetLastError() + ); + + goto ProviderInstall_unloadTapi32; + } + + + // + // Loop until we get the full provider list + // + + dwTotalSize = sizeof (LINEPROVIDERLIST); + + goto ProviderInstall_allocProviderList; + +ProviderInstall_getProviderList: + + if ((*pfnGetProviderList)(0x00020000, pProviderList) != 0) + { + goto ProviderInstall_freeProviderList; + } + + if (pProviderList->dwNeededSize > pProviderList->dwTotalSize) + { + dwTotalSize = pProviderList->dwNeededSize; + + LocalFree (pProviderList); + +ProviderInstall_allocProviderList: + + if (!(pProviderList = LocalAlloc (LPTR, dwTotalSize))) + { + lResult = LINEERR_NOMEM; + goto ProviderInstall_unloadTapi32; + } + + pProviderList->dwTotalSize = dwTotalSize; + + goto ProviderInstall_getProviderList; + } + + + // + // Inspect the provider list entries to see if this provider + // is already installed + // + + pProviderEntry = (LPLINEPROVIDERENTRY) (((LPBYTE) pProviderList) + + pProviderList->dwProviderListOffset); + + for (i = 0; i < pProviderList->dwNumProviders; i++) + { + LPTSTR pszInstalledProviderName = + (LPTSTR) ((LPBYTE) pProviderList + + pProviderEntry->dwProviderFilenameOffset); + LPTSTR psz; + + +#ifdef DONT_WANT_C_RUNTIME + if ((psz = strrchr (pszInstalledProviderName, '\\'))) + { + pszInstalledProviderName = psz + 1; + } +#else // DONT_WANT_C_RUNTIME + // The above code was trying to handle the case where a directory + // path gets returned. We need to do this in a way that doesn't + // load the C runtime code. Ie. search for the last '\\'. + { + LPTSTR pchLastWack; + + pchLastWack = NULL; + psz = pszInstalledProviderName; + + // Find the last '\\'. + while (*psz) + { + if (*psz == TEXT('\\')) + { + pchLastWack = psz; + } + psz++; + } + + if (pchLastWack) + { + pszInstalledProviderName = pchLastWack + 1; + } + } +#endif // DONT_WANT_C_RUNTIME + + if (lstrcmpi (pszInstalledProviderName, pszProviderName) == 0) + { + lResult = LINEERR_NOMULTIPLEINSTANCE; + goto ProviderInstall_freeProviderList; + } + + pProviderEntry++; + } + + + // + // If here then the provider isn't currently installed, + // so do whatever configuration stuff is necessary and + // indicate SUCCESS + // + + lResult = 0; + + +ProviderInstall_freeProviderList: + + LocalFree (pProviderList); + +ProviderInstall_unloadTapi32: + + FreeLibrary (hTapi32); + } + else + { + // + // Do whatever configuration stuff is necessary and return SUCCESS + // + + lResult = 0; + } + + + +ProviderInstall_return: + + return lResult; +} + + + +#ifdef UNDER_CONSTRUCT + +TCHAR gszModem[]="Modem"; + +LONG WINAPI +AddModemDependency( + VOID + ) + +{ + + schSCManager=OpenSCManager( + NULL, + NULL, + SC_MANAGER_ALL_ACCESS + ); + + if (schSCManager != NULL) { + // + // now on service + // + schModemSys=OpenService( + schSCManager, + TEXT("tapisrv"), + SERVICE_ALL_ACCESS + ); + + if (schModemSys != NULL) { + + + ServiceConfig=LocalAlloc(lptr, 4096); + + if (ServiceConfig == NULL) { + + goto Fail; + } + + lResult=QueryServiceConfig( + schModemSys, + ServiceConfig, + 4096, + &BytesNeeded + ); + + if (ERROR_SUCCESS != lResult) { + + got Fail; + } + + Length=RemoveModemSys( + ServiceConfig.lpDependencies + ); + + + NewDependList=LocalAlloc(LPTR,Length+sizeof(gszModem)+2); + + if (NewDependList == NULL) { + + goto Fail;; + } + + + AddModemToDepend( + ServiceConfig.lpDependencies, + NewDependList + ); + + ServiceConfig.lpDependencies=NewDependList; + + lResult=ChangeServiceConfig( + schModemSys, + ServiceConfig.dwServiceType, + ServiceConfig.dwStartType, + ServiceConfig.dwErrorControl, + ServiceConfig.lpBinaryPathName, + &TagValue, + ServiceConfig.dwTagId, + NewDependList, + ServiceConfig.lpServiceStartName, + NULL, + ServiceConfig.lpDisplayName + ); + + + + +//**************************************************************************** +// LONG TSPIAPI TSPI_providerCreateLineDevice() +// +// Dynamically creates a new device. +// +//**************************************************************************** + +LONG TSPIAPI TSPI_providerCreateLineDevice(DWORD dwTempID, + DWORD dwDeviceID) +{ + + LONG lResult = LINEERR_OPERATIONFAILED; // assume failure + DBG_DDI_ENTER("TSPI_providerCreateLineDevice"); + + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_providerCreateLineDevice, + &dwTempID + ); + + // Let the device level handle it + // + lResult = DevlineNewDevice(dwTempID, dwDeviceID); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_providerCreateLineDevice, + &dwTempID, + lResult + ); + + DBG_DDI_EXIT("TSPI_providerCreateLineDevice", lResult); + return lResult; +} + +//**************************************************************************** +// IsDeviceInService() +// +// Function: Finds the specified modem in the current modem list +// +//**************************************************************************** + +BOOL NEAR PASCAL IsDeviceInService(LPSTR szID) +{ + DEVNODE dn; + DWORD dwStatus, dwProblem; + BOOL fRet = FALSE; + + // Locate the devnode + // + if (CM_Locate_DevNode(&dn, szID, 0) == ERROR_SUCCESS) + { + // The devnode exists, check the devnode status + // + if (CM_Get_DevNode_Status(&dwStatus, &dwProblem, dn, 0) == ERROR_SUCCESS) + { + // If the device is in service only when it has no problem + // + fRet = ((dwStatus & DN_STARTED) != 0); + }; + }; + + return fRet; +} + +//**************************************************************************** +// FindModemHWKey() +// +// Function: Finds the specified modem's hardware registry key +// +//**************************************************************************** + +DWORD NEAR PASCAL FindModemHWKey (LPSTR pszDeviceName, HKEY FAR* lphkey, + LPSTR pszID, UINT cbID) +{ + FINDINFO fi; + + // Package the enumeration data + // + fi.lpszDeviceName = (LPSTR)pszDeviceName; + fi.fFound = FALSE; + fi.lphkey = lphkey; + fi.lpszID = (LPSTR)pszID; + fi.cbID = cbID; + + // Find the modem + // + return ((EnumerateModemKeys(SearchModemCallback, (LPVOID)&fi) == ERROR_SUCCESS) && + (fi.fFound)) ? ERROR_SUCCESS : ERROR_BAD_DEVICE; +} + +//**************************************************************************** +// lineNewDevice() +// +// Function: Emulate the TAPI lineInitialize call. +// +//**************************************************************************** + +LONG NEAR PASCAL DevlineNewDevice (DWORD dwTempID, + DWORD dwPermID) +{ + HLOCAL hDeviceName; + PSTR pDeviceName; + HKEY hkeyModem; + DWORD dwRet; + char szID[MAXDEVICENAME+1]; + + // Get the name of the device + // + hDeviceName = (HLOCAL)LOWORD(dwTempID); + if ((pDeviceName = (PSTR)LocalLock(hDeviceName)) == NULL) + return LINEERR_BADDEVICEID; + + // Assume failure + // + dwRet = LINEERR_OPERATIONFAILED; + + // if we found the device, create the LINEDEV struct for it + // + if (FindModemHWKey(pDeviceName, &hkeyModem, szID, sizeof(szID)) + == ERROR_SUCCESS) + { + PLINEDEV pLineDev; + + if ((pLineDev = CreateLineDev(hkeyModem, dwPermID, szID)) != NULL) + { + // Insert into the LINEDEV list + // + pLineDev->pNext = gMdmDev; + gMdmDev = pLineDev; + dwRet = SUCCESS; + }; + + RegCloseKey(hkeyModem); + }; + + LocalUnlock(hDeviceName); + LocalFree(hDeviceName); + + return dwRet; +} + +//**************************************************************************** +// lineDisabled() +// +// Function: Remove the LineDev structure. +// +//**************************************************************************** + +LONG NEAR PASCAL DevlineDisabled (PLINEDEV pLineDev) +{ + PLINEDEV pCur, pPrevious; + + // Notify TAPI for device out of service + // + if (pLineDev->lpfnEvent != NULL) + { + (*pLineDev->lpfnEvent)(pLineDev->htLine, NULL, LINE_LINEDEVSTATE, + (pLineDev->fdwResources & LINEDEVFLAGS_REMOVING ? + LINEDEVSTATE_REMOVED : LINEDEVSTATE_OUTOFSERVICE), + 0L, 0L); + (*pLineDev->lpfnEvent)(pLineDev->htLine, NULL, LINE_CLOSE, + 0L, 0L, 0L); + }; + + // If removal, free the resources for this modem + // + if (pLineDev->fdwResources & LINEDEVFLAGS_REMOVING) + { + // Walk the modem list + // + pPrevious = NULL; + pCur = gMdmDev; + while (pCur) + { + if (pCur == pLineDev) + break; + + pPrevious = pCur; + pCur = pCur->pNext; + }; + + // Remove it from the list + // + if (pPrevious != NULL) + pPrevious->pNext = pLineDev->pNext; + else + gMdmDev = pLineDev->pNext; + + // Free linedev's resources + // + CleanupLineDev(pLineDev); + + if (pLineDev->pDevCfg != NULL) + LocalFree((HLOCAL)pLineDev->pDevCfg); + + // Deallocate the port + // + LocalFree((HLOCAL)pLineDev); + }; + + return SUCCESS; +} + +//**************************************************************************** +// MdmDeviceChangeNotify() +// +// Function: Notify a change in modem list. +// +// Returns: SUCCESS +// +//**************************************************************************** + +DWORD NEAR PASCAL MdmDeviceChangeNotify (UINT uEvent, LPSTR szDevice) +{ + HLOCAL hDeviceName; + PSTR pDeviceName; + + // Allocate a local buffer for the device name + // + if ((hDeviceName = LocalAlloc(LMEM_MOVEABLE, + sizeof(TCHAR) * (MAXDEVICENAME+1))) != NULL) + { + if ((pDeviceName = (PSTR)LocalLock(hDeviceName)) != NULL) + { + // Remember the new device name + // + lstrcpyn((LPSTR)pDeviceName, szDevice, MAXDEVICENAME+1); + LocalUnlock(hDeviceName); + + // Signal ourselves to start adding at a better time + // + PostMessage(ghwndMdm, WM_MDMCHANGE, (WPARAM)uEvent, + (LPARAM)MAKELONG(hDeviceName, 0)); + } + else + { + LocalFree(hDeviceName); + }; + }; + return SUCCESS; +} + +//**************************************************************************** +// MdmDeviceChanged() +// +// Function: Handle a device change notification. +// +// Returns: SUCCESS +// +//**************************************************************************** + +DWORD NEAR PASCAL MdmDeviceChanged (UINT uEvent, LPARAM lParam) +{ + HLOCAL hDeviceName; + PSTR pDeviceName; + PLINEDEV pLineDev; + + // Get the name of the modem that is changed + // + hDeviceName = (HLOCAL)LOWORD(lParam); + if ((pDeviceName = (PSTR)LocalLock(hDeviceName)) == NULL) + { + // Excuse me! something is terribly wrong here. + // + ASSERT(0); + return ERROR_INVALID_HANDLE; + }; + + // Search for an existing device + // + pLineDev = GetCBfromName(pDeviceName); + LocalUnlock(hDeviceName); + + // Determine the type of change + // + switch (uEvent) + { + //************************************************************************ + // Notify TAPI of the new device + //************************************************************************ + + case UMDM_ADD: + { + // If not found, it is a new device + // + if (pLineDev == NULL) + { + (*gfnLineCreateProc)(NULL, NULL, LINE_CREATE, (DWORD)ghProvider, + (DWORD)lParam, 0L); + + // Return here so that the device name token is not freed. + // + return ERROR_SUCCESS; + }; + break; + } + + //************************************************************************ + // Enable modem device, i.e. the modem devnode becomes enabled + //************************************************************************ + + case UMDM_ENABLE: + + // If the device exists and is out of service, make it in service. + // + if (pLineDev != NULL) + { + if (pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE) + { + pLineDev->fdwResources &= ~LINEDEVFLAGS_OUTOFSERVICE; + if (pLineDev->lpfnEvent != NULL) + { + (*pLineDev->lpfnEvent)(pLineDev->htLine, NULL, LINE_LINEDEVSTATE, + LINEDEVSTATE_INSERVICE, 0L, 0L); + }; + }; + }; + break; + + //************************************************************************ + // Disable modem device, i.e. the modem devnode becomes disabled, and + // probably remove the modem from the list + //************************************************************************ + + case UMDM_DISABLE: + + // If we found the disabled device + // + if ((pLineDev != NULL) && + (pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE)) + { + break; + } + + //************************************************************************ + // Fall through + //************************************************************************ + + case UMDM_REMOVE: + + // If we found the disabled device + // + if (pLineDev != NULL) + { + pLineDev->fdwResources |= LINEDEVFLAGS_OUTOFSERVICE; + if (uEvent == UMDM_REMOVE) + { + pLineDev->fdwResources |= LINEDEVFLAGS_REMOVING; + }; + + // Is the modem active? + // + if ((pLineDev->dwCall & CALL_ALLOCATED) && + (pLineDev->dwCallState != LINECALLSTATE_DISCONNECTED)) + { + // We need to clean up the active connection first + // + MdmCompleteAsync (pLineDev, MDM_HANGUP, MDM_ID_NULL); + } + else + { + // The modem might be listening, just close the modem + // + if ((pLineDev->DevState == DEVST_PORTLISTENINIT) || + (pLineDev->DevState == DEVST_PORTLISTENING)) + { + // Notify the monitoring application + // + (*pLineDev->lpfnEvent)(pLineDev->htLine, NULL, LINE_CLOSE, + 0L, 0L, 0L); + DevlineClose(pLineDev); + }; + + // disable or remove it immediately + // + DevlineDisabled(pLineDev); + }; + }; + break; + + default: + break; + }; + + // We no longer need the device name token + // + LocalFree(hDeviceName); + return ERROR_SUCCESS; +} + +#endif //UNDER_CONSTRUCT + + +#ifndef DYNA_ADDREMOVE + +LONG TSPIAPI TSPI_providerCreateLineDevice(DWORD dwTempID, + DWORD dwDeviceID) +{ + ASSERT(FALSE); + return LINEERR_OPERATIONFAILED; +} + +#else // DYNA_ADDREMOVE + +BOOL ReInitModemCallback (HKEY hkey, LPVOID lpData); +LONG DevlineNewDevice (DWORD dwTempID, DWORD dwPermID); + + +//**************************************************************************** +// LONG DevlineReInitialize() +// +// Function: Re-initializes the modem device list +// +// History: +// 4/15/96 JosephJ Created +//**************************************************************************** + +LONG DevlineReInitialize (DWORD dwBaseID, + LPDWORD lpdwNumDevs) +{ + INITINFO initi; + DWORD dwRet = LINEERR_OPERATIONFAILED; + BOOL fModemUILoaded; + HDEVINFO hdevinfo=NULL; + + // Load MODEMUI.DLL (for private entry points) + fModemUILoaded=TRUE; + if (!LoadModemUI()) + { + fModemUILoaded=FALSE; + goto end; + } + + // For the modem device, get the device information + hdevinfo = GetHDevInfo(DIGCF_PRESENT); + if (!hdevinfo) + { + goto end; + } + + initi.dwBaseID = dwBaseID; + initi.cModem = 0; + + // We do this enumeration inside the global critical section, because there + // Potentially could be more than one tepCplNotif threads active. + // It's almost impossible to do this manually -- one would have to add/remove + // modems real fast in succession so that the 2nd notification comes in when + // the 1st is still proceeding, but it's possible, and we definitely want to + // serialize the marking of all the modems with the REINIT flag and + // subsequently declaring all the unmarked ones out-of-service. Also there + // is the possibility of both threads deciding that a modem needs to be + // created and creating two instances of them. + EnterCriticalSection(&gUmdm.crit); + dwRet = EnumerateModems(ReInitModemCallback, (LPVOID)&initi, TRUE); + if (dwRet == ERROR_SUCCESS) + { + DisableStaleModems(); + *lpdwNumDevs = initi.cModem; + } + else + *lpdwNumDevs = 0; + LeaveCriticalSection(&gUmdm.crit); + +end: + + if (fModemUILoaded) + { + UnloadModemUI(); + } + if (hdevinfo) + { + FreeHDevInfo(hdevinfo); + } + + return dwRet; +} + +//**************************************************************************** +// BOOL ReInitModemCallback (HKEY hkey, LPVOID lpData) +// +// Function: ReInitializes the enumerated modems. +// +// Returns: TRUE always to continue +// +//**************************************************************************** + +BOOL ReInitModemCallback (HKEY hkey, LPVOID lpData) +{ + PLINEDEV pMdmDev; + LPINITINFO lpInitInfo = (LPINITINFO)lpData; + + pMdmDev = CreateLineDev(hkey, MAXDWORD, TRUE); + if (pMdmDev) + { + // Insert into the LINEDEV list + // + AddCBToList(pMdmDev); + (lpInitInfo->cModem)++; + + // Let's callback the LINE_CREATE function here, passing in pMdmDev + // as the handle. + // Note: we haven't claimed any crit-sections at this time. + if (gfnLineCreateProc) + { + (*gfnLineCreateProc)(NULL, NULL, LINE_CREATE, (DWORD)ghProvider, + (DWORD)pMdmDev, 0L); + } + }; + + return TRUE; +} + + +//**************************************************************************** +// LONG TSPIAPI TSPI_providerCreateLineDevice() +// +// Dynamically creates a new device. +// +//**************************************************************************** + +LONG TSPIAPI TSPI_providerCreateLineDevice(DWORD dwTempID, + DWORD dwDeviceID) +{ + LONG lResult; + + DBG_DDI_ENTER("TSPI_providerCreateLineDevice"); + TRACE3(IDEVENT_TSPFN_ENTER, IDFROM_TSPI_providerCreateLineDevice, &dwTempID); + + // Let the device level handle it + // + lResult = DevlineNewDevice(dwTempID, dwDeviceID); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_providerCreateLineDevice, + &dwTempID, + lResult + ); + DBG_DDI_EXIT("TSPI_providerCreateLineDevice", lResult); + return lResult; +} + + + +//**************************************************************************** +// lineNewDevice() +// +// Function: Emulate the TAPI lineInitialize call. +// +//**************************************************************************** + +LONG DevlineNewDevice (DWORD dwTempID, + DWORD dwPermID) +{ + LPSTR lpDeviceName; + HKEY hkeyModem; + DWORD dwRet; + char szID[MAXDEVICENAME+1]; + PLINEDEV pLineDev; + + DPRINTF2("DevlineNewDevice(%lu,%lu)", dwTempID, dwPermID); + + // Retrieve the device + // + pLineDev = GetCBfromHandle (dwTempID); + if (!pLineDev) + { + dwRet=LINEERR_BADDEVICEID; + goto end; + } + + // Assume failure + // + dwRet = LINEERR_OPERATIONFAILED; + + // if we found the device, we finish initializing it -- specify + // the proper dwPermID, etc... + // + ASSERT(pLineDev->dwID == MAXDWORD); + pLineDev->dwID=dwPermID; + RELEASE_LINEDEV(pLineDev); + dwRet = ERROR_SUCCESS; + +end: + return dwRet; +} +#endif // DYNA_ADDREMOVE + +// +// Thread Entry Point for the thread that processes cpl notifications. +// +DWORD APIENTRY tepCplNotif(DWORD dwParam) +{ + DWORD dwcbNew; + PNOTIFICATION_FRAME pnf = (PNOTIFICATION_FRAME) dwParam; + + ASSERT(pnf && TSP_CPL_FRAME(pnf)); + + if (pnf->dwFlags&fTSPNOTIF_FLAG_CPL_REENUM) + { + DevlineReInitialize (0, &dwcbNew); + } + else if (pnf->dwFlags&fTSPNOTIF_FLAG_CPL_DEFAULT_COMMCONFIG_CHANGE) + { + if (!(pnf->dwFlags&fTSPNOTIF_FLAG_UNICODE)) + { + ASSERT(FALSE); + } + else + { + // Get friendly name and refresh comm config. + LPCTSTR lpctszFriendlyName = (LPCTSTR) pnf->rgb; + UINT uMaxSize = pnf->dwSize - sizeof(NOTIFICATION_FRAME); + UINT u; + + ASSERT(pnf->dwSize > sizeof(NOTIFICATION_FRAME)); + + // verify string is null-terminated. + for(u=0;u<uMaxSize;u++) + { + if (!lpctszFriendlyName[u]) break; + } + + ASSERT(u<uMaxSize); + + if (u<uMaxSize) + { + PLINEDEV pLineDev = GetCBfromName ( + (LPTSTR) lpctszFriendlyName + ); + + if (pLineDev) + { + DPRINTF1( + "CPLNOTIF: Marking device [%s] for refresh", + lpctszFriendlyName + ); + pLineDev->fUpdateDefaultCommConfig=TRUE; + RELEASE_LINEDEV(pLineDev); pLineDev=NULL; + } + } + } + } + + // Our job to free this. + LocalFree(pnf); + + CplNotifComplete(FALSE); + + return ERROR_SUCCESS; +} + + +void cplProcessNotification(PNOTIFICATION_FRAME pnf) +{ + + ASSERT(TSP_CPL_FRAME(pnf)); + { + HANDLE hThread; + DWORD dwTID; + DPRINTF("Processing CPL Notification"); + +#ifdef DYNA_ADDREMOVE + EnterCriticalSection(&gUmdm.critCplNotif); + if (gUmdm.hthrdCplNotif) + { + DPRINTF("cplProcessNotification: Previous CplNotif thread exists. Skipping."); + } + else + { + PNOTIFICATION_FRAME pnfAlloc = + (PNOTIFICATION_FRAME) LocalAlloc + ( + LPTR, + pnf->dwSize + ); + if (pnfAlloc) + { + + CopyMemory(pnfAlloc, pnf, pnf->dwSize); + + // Start the thread to process the notification + // + gUmdm.hthrdCplNotif = CreateThread( + NULL, // default security + 0, // default stack size + (LPTHREAD_START_ROUTINE)tepCplNotif, // thread entry point + pnfAlloc, // parameter + 0, // Start immediately + &dwTID); // thread id + + if (gUmdm.hthrdCplNotif) + { + + DPRINTF2("cplNotification: Created Thread @%lu; TID=0x%lx\n", + GetTickCount(), + dwTID); + } + else + { + DPRINTF1("cplNotification: Created Thread FAILED. Err=%lu\n", + GetLastError()); + LocalFree(pnfAlloc); + pnfAlloc=NULL; + } + } + } + LeaveCriticalSection(&gUmdm.critCplNotif); +#endif // DYNA_ADDREMOVE + } +} + + +#ifdef DYNA_ADDREMOVE +HDEVINFO GetHDevInfo(DWORD dwDIGCF) +{ + HDEVINFO hdevinfo=NULL; + + EnterCriticalSection(&gUmdm.crit); + + if (!gUmdm.dwcRefHDevInfo) + { + gUmdm.hdevinfo = SetupDiGetClassDevsW( + g_pguidModem, + NULL, + NULL, + dwDIGCF); + } + + hdevinfo=gUmdm.hdevinfo; + + if (hdevinfo) + { + gUmdm.dwcRefHDevInfo++; + } + + ASSERT( ( hdevinfo && gUmdm.dwcRefHDevInfo) + ||(!hdevinfo && !gUmdm.dwcRefHDevInfo) ); + + LeaveCriticalSection(&gUmdm.crit); + + return hdevinfo; +} +#endif // DYNA_ADDREMOVE + + + +#ifdef DYNA_ADDREMOVE +void FreeHDevInfo(HDEVINFO hdevinfo) +{ + + EnterCriticalSection(&gUmdm.crit); + + ASSERT(hdevinfo==gUmdm.hdevinfo); + + if (!gUmdm.dwcRefHDevInfo) + { + ASSERT(FALSE); + goto end; + } + if (!--gUmdm.dwcRefHDevInfo) + { + SetupDiDestroyDeviceInfoList(gUmdm.hdevinfo); + gUmdm.hdevinfo=NULL; + } + +end: + + LeaveCriticalSection(&gUmdm.crit); + +} +#endif // DYNA_ADDREMOVE + + +#ifdef DYNA_ADDREMOVE +BOOL LoadModemUI(void) +{ + BOOL fRet=FALSE; + + EnterCriticalSection(&gUmdm.crit); + + if (!gUmdm.dwcRefModemUI) + { + HINSTANCE hlib = LoadLibrary(TEXT("modemui.dll")); + + ASSERT(!gUmdm.hModemUIDLL); + ASSERT(!gUmdm.pfnPrivateDefCommConfig); + + if (hlib) + { + + gUmdm.pfnPrivateDefCommConfig= + (PVOID)GetProcAddress(hlib,"UnimodemGetDefaultCommConfig"); + + if (!gUmdm.pfnPrivateDefCommConfig) + { + FreeLibrary(hlib); + hlib=NULL; + } + } + + gUmdm.hModemUIDLL = hlib; + } + + if (gUmdm.hModemUIDLL) + { + gUmdm.dwcRefModemUI++; + fRet=TRUE; + } + + ASSERT( ( gUmdm.hModemUIDLL && gUmdm.dwcRefModemUI) + ||(!gUmdm.hModemUIDLL && !gUmdm.dwcRefModemUI) ); + + LeaveCriticalSection(&gUmdm.crit); + + return fRet; +} +#endif // DYNA_ADDREMOVE + + +#ifdef DYNA_ADDREMOVE +void UnloadModemUI(void) +{ + + EnterCriticalSection(&gUmdm.crit); + + if (!gUmdm.dwcRefModemUI) + { + ASSERT(FALSE); + goto end; + } + + if (!--gUmdm.dwcRefModemUI) + { + ASSERT(gUmdm.hModemUIDLL && gUmdm.pfnPrivateDefCommConfig); + FreeLibrary(gUmdm.hModemUIDLL); + gUmdm.hModemUIDLL=NULL; + gUmdm.pfnPrivateDefCommConfig=NULL; + } + +end: + + LeaveCriticalSection(&gUmdm.crit); + +} +#endif // DYNA_ADDREMOVE + + +#ifdef DYNA_ADDREMOVE +void CplNotifComplete(BOOL fWait) +{ + HANDLE hthrd; + + EnterCriticalSection(&gUmdm.critCplNotif); + hthrd=gUmdm.hthrdCplNotif; + gUmdm.hthrdCplNotif=0; + LeaveCriticalSection(&gUmdm.critCplNotif); + + if (hthrd) + { + if (fWait) + { + DPRINTF("CplNotifComplete: WARNING -- waiting for re-enum thread to complete"); + WaitForSingleObject(hthrd, INFINITE); + } + CloseHandle(hthrd); + } +} +#endif // DYNA_ADDREMOVE + +// +// Reset the cached CommConfig structure by calling GetDefaultCommConfig. +// +void RefreshDefaultCommConfig(PLINEDEV pLineDev) +{ + + COMMCONFIG * pccCurrent = NULL, * pccNew = NULL; + LPCTSTR lpctszDeviceName = NULL; + + if (pLineDev && pLineDev->pDevCfg) + { + pccCurrent = (COMMCONFIG *)&(pLineDev->pDevCfg->commconfig); + lpctszDeviceName = pLineDev->szDeviceName; + } + + if (!pccCurrent || !lpctszDeviceName) goto end; + + + // Get default comm config. + { + DWORD dwSize = pccCurrent->dwSize; + + DPRINTF1("RefreshDefaultCommConfig: [%s]", lpctszDeviceName); + + pccNew = (COMMCONFIG *)LocalAlloc(LPTR, (UINT)dwSize); + if (pccNew) + { + pccNew->dwProviderSubType = PST_MODEM; + if (!GetDefaultCommConfig(lpctszDeviceName, pccNew, &dwSize)) + { + DPRINTF2 + ( + "RefreshCommComfig: GetDefaultCommConfig(\"%s\"): ERR %08lu", + lpctszDeviceName, + GetLastError() + ); + LocalFree(pccNew); pccNew = NULL; + } + } + } + + if (pccNew) + { + // Similar to what is done by TSPI_lineSetDevConfig. + + ASSERT(pccCurrent->dwSize == pccNew->dwSize); + ASSERT(pccCurrent->wVersion == pccNew->wVersion); + ASSERT(pccCurrent->dwProviderSubType == pccNew->dwProviderSubType); + ASSERT(pccCurrent->dwProviderSize == pccNew->dwProviderSize); + if + ( (pccCurrent->dwSize == pccNew->dwSize) + && (pccCurrent->wVersion == pccNew->wVersion) + && (pccCurrent->dwProviderSubType == pccNew->dwProviderSubType) + && (pccCurrent->dwProviderSize == pccNew->dwProviderSize) + ) + { + + pccCurrent->dcb = pccNew->dcb; + CopyMemory(((LPBYTE)pccCurrent)+pccCurrent->dwProviderOffset, + ((LPBYTE)pccNew)+pccNew->dwProviderOffset, + pccCurrent->dwProviderSize); + + pLineDev->InitStringsAreValid=FALSE; + } + else + { + DPRINTF("RefreshDefaultCommSettings:size/version/prov. mismatch"); + ASSERT(FALSE); + } + } + + +end: + + if (pccNew) {LocalFree(pccNew); pccNew = NULL;} + +} + +// Initialize the global parameters +// +void tspInitGlobals(void) +{ + // Determine if User is Admin + gUmdm.bAdminUser = IsAdminUser(); + + // Determine global registry state flags. + { + TCHAR rgtch[] = szUNIMODEM_REG_PATH TEXT("\\PortSpecific"); + HKEY hKey=NULL; + LONG l; + + gRegistryFlags = 0; + + l=RegOpenKeyEx( + HKEY_LOCAL_MACHINE, // handle of open key + rgtch, // address of name of subkey to open + 0, // reserved + KEY_READ, // desired security access + &hKey // address of buffer for opened handle + ); + + if (l==ERROR_SUCCESS) + { + gRegistryFlags = fGRF_PORTLATENCY; + RegCloseKey(hKey); + } + } +} + +// DeInitialize the global parameters +// +void tspDeInitGlobals(void) +{ + gRegistryFlags = 0; + gUmdm.bAdminUser = FALSE; +} |