|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: I S D N R E G . C P P
//
// Contents: ISDN Wizard/PropertySheet registry functions
//
// Notes:
//
// Author: VBaliga 14 Jun 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include <ncxbase.h>
#include "isdncfg.h"
#include "ncreg.h"
#define NUM_D_CHANNELS_ALLOWED 16
#define NUM_B_CHANNELS_ALLOWED 50
// Reg key value names
// For each ISDN card instance
static const WCHAR c_szWanEndpoints[] = L"WanEndpoints"; static const WCHAR c_szIsdnNumDChannels[] = L"IsdnNumDChannels"; static const WCHAR c_szIsdnSwitchTypes[] = L"IsdnSwitchTypes";
// For each D-channel
static const WCHAR c_szIsdnSwitchType[] = L"IsdnSwitchType"; static const WCHAR c_szIsdnNumBChannels[] = L"IsdnNumBChannels";
// For each B-channel
static const WCHAR c_szIsdnSpid[] = L"IsdnSpid"; static const WCHAR c_szIsdnPhoneNumber[] = L"IsdnPhoneNumber"; static const WCHAR c_szIsdnSubaddress[] = L"IsdnSubaddress"; static const WCHAR c_szIsdnMultiNumbers[] = L"IsdnMultiSubscriberNumbers";
/*
Function: HrReadNthDChannelInfo
Returns: HRESULT
Description: Read the information for the dwIndex'th D-channel into pDChannel. If this function succeeds, it allocates pDChannel->pBChannel, which has to be freed by calling LocalFree().
If there is an error in reading IsdnSwitchType, this function returns S_FALSE.
If there is an error in opening the a B-channel key, or there is an error in reading IsdnSpid or IsdnPhoneNumber, this function returns S_FALSE, but with empty strings in pBChannel->szSpid and pBChannel->szPhoneNumber for that B-channel.
*/
HRESULT HrReadNthDChannelInfo( HKEY hKeyIsdnBase, DWORD dwDChannelIndex, PISDN_D_CHANNEL pDChannel ) { WCHAR szKeyName[20]; // _itow() uses only 17 wchars
HKEY hKeyDChannel = NULL; HKEY hKeyBChannel = NULL; DWORD dwBChannelIndex; PISDN_B_CHANNEL pBChannel; HRESULT hr = E_FAIL; BOOL fReturnSFalse = FALSE; DWORD cbData;
Assert(NULL == pDChannel->pBChannel);
_itow(dwDChannelIndex, szKeyName, 10 /* radix */);
hr = HrRegOpenKeyEx(hKeyIsdnBase, szKeyName, KEY_READ, &hKeyDChannel);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error opening D-channel %d. hr: %d", dwDChannelIndex, hr); goto LDone; }
hr = HrRegQueryMultiSzWithAlloc(hKeyDChannel, c_szIsdnMultiNumbers, &pDChannel->mszMsnNumbers);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d. hr: %d", c_szIsdnMultiNumbers, dwDChannelIndex, hr);
// Initialize to empty string
//
pDChannel->mszMsnNumbers = new WCHAR[1];
if (pDChannel->mszMsnNumbers == NULL) { return(ERROR_NOT_ENOUGH_MEMORY); }
*pDChannel->mszMsnNumbers = 0;
// May not be present
hr = S_OK; }
hr = HrRegQueryDword(hKeyDChannel, c_szIsdnNumBChannels, &(pDChannel->dwNumBChannels));
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d. hr: %d", c_szIsdnNumBChannels, dwDChannelIndex, hr); goto LDone; }
if (NUM_B_CHANNELS_ALLOWED < pDChannel->dwNumBChannels || 0 == pDChannel->dwNumBChannels) { // Actually, dwNumBChannels <= 23. We are protecting ourselves from
// a corrupt registry.
TraceTag(ttidISDNCfg, "%S in D-channel %d has invalid value: %d", c_szIsdnNumBChannels, dwDChannelIndex, pDChannel->dwNumBChannels);
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); goto LDone; }
pDChannel->pBChannel = (PISDN_B_CHANNEL) LocalAlloc(LPTR, sizeof(ISDN_B_CHANNEL) * pDChannel->dwNumBChannels);
if (NULL == pDChannel->pBChannel) { hr = HrFromLastWin32Error(); TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr); goto LDone; }
ZeroMemory(pDChannel->pBChannel, sizeof(ISDN_B_CHANNEL) * pDChannel->dwNumBChannels);
for (dwBChannelIndex = 0; dwBChannelIndex < pDChannel->dwNumBChannels; dwBChannelIndex++) { pBChannel = pDChannel->pBChannel + dwBChannelIndex; _itow(dwBChannelIndex, szKeyName, 10 /* radix */);
hr = HrRegOpenKeyEx(hKeyDChannel, szKeyName, KEY_READ, &hKeyBChannel);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error opening B-channel %d in D-channel " "%d. hr: %d", dwBChannelIndex, dwDChannelIndex, hr); goto LForEnd; }
cbData = sizeof(pBChannel->szSpid);
hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnSpid, pBChannel->szSpid, &cbData);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnSpid, dwDChannelIndex, dwBChannelIndex, hr);
// May not be present
hr = S_OK; }
cbData = sizeof(pBChannel->szPhoneNumber);
hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnPhoneNumber, pBChannel->szPhoneNumber, &cbData);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnPhoneNumber, dwDChannelIndex, dwBChannelIndex, hr);
// May not be present
hr = S_OK; }
cbData = sizeof(pBChannel->szSubaddress);
hr = HrRegQuerySzBuffer(hKeyBChannel, c_szIsdnSubaddress, pBChannel->szSubaddress, &cbData);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnSubaddress, dwDChannelIndex, dwBChannelIndex, hr);
// May not be present
hr = S_OK; }
LForEnd:
if (FAILED(hr)) { fReturnSFalse = TRUE; hr = S_OK; pBChannel->szSpid[0] = L'\0'; pBChannel->szPhoneNumber[0] = L'\0'; }
RegSafeCloseKey(hKeyBChannel); }
LDone:
RegSafeCloseKey(hKeyDChannel);
if (FAILED(hr)) { LocalFree(pDChannel->pBChannel); pDChannel->pBChannel = NULL; }
if (SUCCEEDED(hr) && fReturnSFalse) { TraceTag(ttidISDNCfg, "HrReadNthDChannelInfo(%d) returning S_FALSE", dwDChannelIndex); hr = S_FALSE; }
TraceError("HrReadNthDChannelInfo", (S_FALSE == hr) ? S_OK: hr); return(hr); }
/*
Function: HrReadDChannelsInfo
Returns: HRESULT
Description: Read the D-channel information into *ppDChannel. If the function fails, *ppDChannel will be NULL.
*/
HRESULT HrReadDChannelsInfo( HKEY hKeyISDNBase, DWORD dwNumDChannels, PISDN_D_CHANNEL* ppDChannel ) { HRESULT hr = E_FAIL; BOOL fReturnSFalse = FALSE; PISDN_D_CHANNEL pDChannel; DWORD dwIndex;
pDChannel = (PISDN_D_CHANNEL) LocalAlloc(LPTR, sizeof(ISDN_D_CHANNEL) * dwNumDChannels);
if (NULL == pDChannel) { hr = HrFromLastWin32Error(); TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr); goto LDone; }
// If there is an error, we will free these variables if they are not NULL.
for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++) { Assert(NULL == pDChannel[dwIndex].pBChannel); }
for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++) { hr = HrReadNthDChannelInfo(hKeyISDNBase, dwIndex, pDChannel + dwIndex);
if (FAILED(hr)) { goto LDone; }
if (S_FALSE == hr) { fReturnSFalse = TRUE; } }
LDone:
if (FAILED(hr)) { if (NULL != pDChannel) { for (dwIndex = 0; dwIndex < dwNumDChannels; dwIndex++) { LocalFree(pDChannel[dwIndex].pBChannel); }
LocalFree(pDChannel);
*ppDChannel = NULL; } } else { *ppDChannel = pDChannel; }
if (SUCCEEDED(hr) && fReturnSFalse) { TraceTag(ttidISDNCfg, "HrReadDChannelsInfo() returning S_FALSE"); hr = S_FALSE; }
TraceError("HrReadDChannelsInfo", (S_FALSE == hr) ? S_OK : hr); return(hr); }
/*
Function: HrReadISDNPropertiesInfo
Returns: HRESULT
Description: Read the ISDN registry structure into the config info. If the function fails, *ppISDNConfig will be NULL. Else, *ppISDNConfig has to be freed by calling FreeISDNPropertiesInfo().
*/
HRESULT HrReadIsdnPropertiesInfo( HKEY hKeyIsdnBase, HDEVINFO hdi, PSP_DEVINFO_DATA pdeid, PISDN_CONFIG_INFO* ppIsdnConfig ) { HRESULT hr = E_FAIL; PISDN_CONFIG_INFO pIsdnConfig; DWORD dwIndex;
pIsdnConfig = (PISDN_CONFIG_INFO) LocalAlloc(LPTR, sizeof(ISDN_CONFIG_INFO));
if (NULL == pIsdnConfig) { hr = HrFromLastWin32Error(); TraceTag(ttidISDNCfg, "Couldn't allocate memory. hr: %d", hr); goto LDone; }
ZeroMemory(pIsdnConfig, sizeof(ISDN_CONFIG_INFO));
pIsdnConfig->hdi = hdi; pIsdnConfig->pdeid = pdeid;
// If there is an error, we will free these variables if they are not NULL.
Assert(NULL == pIsdnConfig->pDChannel);
hr = HrRegQueryDword(hKeyIsdnBase, c_szWanEndpoints, &(pIsdnConfig->dwWanEndpoints));
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szWanEndpoints, hr); goto LDone; }
hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnNumDChannels, &(pIsdnConfig->dwNumDChannels));
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szIsdnNumDChannels, hr); goto LDone; }
if (NUM_D_CHANNELS_ALLOWED < pIsdnConfig->dwNumDChannels || 0 == pIsdnConfig->dwNumDChannels) { // Actually, dwNumDChannels <= 8. We are protecting ourselves from
// a corrupt registry.
TraceTag(ttidISDNCfg, "%S has invalid value: %d", c_szIsdnNumDChannels, pIsdnConfig->dwNumDChannels);
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
// Setting dwNumDChannels to 0 will help us when we try to free the
// allocated ISDN_B_CHANNEL's
pIsdnConfig->dwNumDChannels = 0;
goto LDone; }
hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnSwitchTypes, &pIsdnConfig->dwSwitchTypes);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error reading %S. hr: %d", c_szIsdnSwitchTypes, hr); goto LDone; }
hr = HrReadDChannelsInfo(hKeyIsdnBase, pIsdnConfig->dwNumDChannels, &(pIsdnConfig->pDChannel));
if (FAILED(hr)) { goto LDone; }
// A PRI adapter is one that has more than 2 B channels per D channel.
// Since all D channels should have the same number of B channels, the
// safest thing to do is pick the first D channel
//
pIsdnConfig->fIsPri = (pIsdnConfig->pDChannel[0].dwNumBChannels > 2);
#if DBG
if (pIsdnConfig->fIsPri) { TraceTag(ttidISDNCfg, "This is a PRI adapter!"); } #endif
hr = HrRegQueryDword(hKeyIsdnBase, c_szIsdnSwitchType, &(pIsdnConfig->dwCurSwitchType));
if (FAILED(hr)) { Assert(ISDN_SWITCH_NONE == pIsdnConfig->dwCurSwitchType);
TraceTag(ttidISDNCfg, "Error reading %S. If this is a new install, " "then this is expected. hr: %d", c_szIsdnSwitchType, hr);
// Switch type won't exist on a new install of the card so this is ok
hr = S_OK; }
LDone:
if (FAILED(hr)) { if (NULL != pIsdnConfig) { if (NULL != pIsdnConfig->pDChannel) { for (dwIndex = 0; dwIndex < pIsdnConfig->dwNumDChannels; dwIndex++) { LocalFree(pIsdnConfig->pDChannel[dwIndex].pBChannel); }
LocalFree(pIsdnConfig->pDChannel); }
LocalFree(pIsdnConfig); *ppIsdnConfig = NULL; } } else { *ppIsdnConfig = pIsdnConfig; }
TraceError("HrReadIsdnPropertiesInfo", hr); return(hr); }
/*
Function: HrWriteIsdnPropertiesInfo
Returns: HRESULT
Description: Write the ISDN config info back into the registry.
*/
HRESULT HrWriteIsdnPropertiesInfo( HKEY hKeyIsdnBase, PISDN_CONFIG_INFO pIsdnConfig ) { WCHAR szKeyName[20]; // _itow() uses only 17 wchars
HRESULT hr = E_FAIL; HKEY hKeyDChannel = NULL; HKEY hKeyBChannel = NULL; DWORD dwDChannelIndex; DWORD dwBChannelIndex; PISDN_D_CHANNEL pDChannel; PISDN_B_CHANNEL pBChannel;
Assert(NUM_D_CHANNELS_ALLOWED >= pIsdnConfig->dwNumDChannels);
hr = HrRegSetDword(hKeyIsdnBase, c_szIsdnSwitchType, pIsdnConfig->dwCurSwitchType); if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error writing %S. hr: %d", c_szIsdnSwitchType, hr); goto LOuterForEnd; }
for (dwDChannelIndex = 0; dwDChannelIndex < pIsdnConfig->dwNumDChannels; dwDChannelIndex++) { pDChannel = pIsdnConfig->pDChannel + dwDChannelIndex; _itow(dwDChannelIndex, szKeyName, 10 /* radix */);
hr = HrRegOpenKeyEx(hKeyIsdnBase, szKeyName, KEY_WRITE, &hKeyDChannel);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error opening D-channel %d. hr: %d", dwDChannelIndex, hr); goto LOuterForEnd; }
hr = HrRegSetMultiSz(hKeyDChannel, c_szIsdnMultiNumbers, pDChannel->mszMsnNumbers);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error writing %S. hr: %d", c_szIsdnMultiNumbers, hr); goto LOuterForEnd; }
Assert(NUM_B_CHANNELS_ALLOWED >= pDChannel->dwNumBChannels);
for (dwBChannelIndex = 0; dwBChannelIndex < pDChannel->dwNumBChannels; dwBChannelIndex++) { pBChannel = pDChannel->pBChannel + dwBChannelIndex; _itow(dwBChannelIndex, szKeyName, 10 /* radix */);
hr = HrRegCreateKeyEx(hKeyDChannel, szKeyName, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKeyBChannel, NULL);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error opening B-channel %d in " "D-channel %d. hr: %d", dwBChannelIndex, dwDChannelIndex, hr); goto LInnerForEnd; }
hr = HrRegSetSz(hKeyBChannel, c_szIsdnSpid, pBChannel->szSpid);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnSpid, dwDChannelIndex, dwBChannelIndex, hr); goto LInnerForEnd; }
hr = HrRegSetSz(hKeyBChannel, c_szIsdnPhoneNumber, pBChannel->szPhoneNumber);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnPhoneNumber, dwDChannelIndex, dwBChannelIndex, hr); goto LInnerForEnd; }
hr = HrRegSetSz(hKeyBChannel, c_szIsdnSubaddress, pBChannel->szSubaddress);
if (FAILED(hr)) { TraceTag(ttidISDNCfg, "Error writing %S in D-channel %d, " "B-channel %d. hr: %d", c_szIsdnSubaddress, dwDChannelIndex, dwBChannelIndex, hr); goto LInnerForEnd; }
LInnerForEnd:
RegSafeCloseKey(hKeyBChannel);
if (FAILED(hr)) { goto LOuterForEnd; } }
LOuterForEnd:
RegSafeCloseKey(hKeyDChannel);
if (FAILED(hr)) { goto LDone; } }
LDone:
TraceError("HrWriteIsdnPropertiesInfo", hr); return(hr); }
/*
Function: FreeIsdnPropertiesInfo
Returns: HRESULT
Description: Free the structure allocated by HrReadIsdnPropertiesInfo.
*/
VOID FreeIsdnPropertiesInfo( PISDN_CONFIG_INFO pIsdnConfig ) { DWORD dwIndex;
if (NULL == pIsdnConfig) { return; }
if (NULL != pIsdnConfig->pDChannel) { for (dwIndex = 0; dwIndex < pIsdnConfig->dwNumDChannels; dwIndex++) { LocalFree(pIsdnConfig->pDChannel[dwIndex].pBChannel); delete [] pIsdnConfig->pDChannel[dwIndex].mszMsnNumbers; }
LocalFree(pIsdnConfig->pDChannel); }
LocalFree(pIsdnConfig); }
|