windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upgnt/migmain/tapi.c
2020-09-26 16:20:57 +08:00

949 lines
21 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
tapi.c
Abstract:
This file implements WindowsNT side functionality for TAPI migration.
Author:
Marc R. Whitten (marcw) 21-Nov-1997
Revision History:
--*/
#include "pch.h"
typedef struct {
PTSTR Name;
PTSTR AreaCode;
DWORD Country;
PTSTR DisableCallWaiting;
DWORD Flags;
DWORD Id;
PTSTR LongDistanceAccess;
DWORD PulseDial;
PTSTR OutsideAccess;
DWORD CallingCard;
TCHAR EntryName[40];
} LOCATION, * PLOCATION;
typedef struct {
PTSTR Name;
TCHAR EntryName[60];
DWORD Id;
PTSTR Pin;
PTSTR Locale;
PTSTR LongDistance;
PTSTR International;
DWORD Flags;
} CALLINGCARD, * PCALLINGCARD;
#define DBG_TAPI "TAPI"
#define DEFAULT_LOCATION_FLAGS 1
#define NO_CURRENT_LOCATION_FOUND -1
GROWLIST g_LocationsList = GROWLIST_INIT;
GROWLIST g_CallingCardList = GROWLIST_INIT;
BOOL g_LocationsRead = FALSE;
UINT g_CurrentLocation = 0;
POOLHANDLE g_TapiPool;
//
// Location flags to set.
//
#define LOCATION_USETONEDIALING 0x01
#define LOCATION_USECALLINGCARD 0x02
#define LOCATION_HASCALLWAITING 0x04
//
// CallingCard flags to set.
//
#define CALLINGCARD_BUILTIN 0x01
#define CALLINGCARD_HIDE 0x02
//
// Location key field specifiers (in telephon.ini)
//
enum {
FIELD_ID = 1,
FIELD_NAME = 2,
FIELD_OUTSIDEACCESS = 3,
FIELD_LONGDISTANCEACCESS = 4,
FIELD_AREACODE = 5,
FIELD_COUNTRY = 6,
FIELD_CALLINGCARD = 7,
FIELD_PULSEDIAL = 11,
FIELD_DISABLECALLWAITING = 12
};
enum {
FIELD_CC_ID = 1,
FIELD_CC_NAME = 2,
FIELD_CC_PIN = 3,
FIELD_CC_LOCALE = 4,
FIELD_CC_LONGDISTANCE = 5,
FIELD_CC_INTERNATIONAL = 6,
FIELD_CC_FLAGS = 7
};
#define S_USERLOCATIONSKEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations")
#define S_USERCALLINGCARDSKEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards")
#define S_LOCALRULE TEXT("LocalRule")
#define S_LDRULE TEXT("LDRule")
#define S_INTERNATIONALRULE TEXT("InternationalRule")
#define S_PIN TEXT("Pin")
#define S_CALLINGCARD TEXT("CallingCard")
#define S_CARDS TEXT("Cards")
BOOL
pReadCardFromIniFile (
IN PINFSTRUCT Is,
OUT PCALLINGCARD Card
)
{
BOOL rSuccess = TRUE;
PTSTR p;
MYASSERT(Is);
MYASSERT(Card);
p = InfGetStringField (Is, FIELD_CC_NAME);
if (p) {
Card->Name = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
if (!InfGetIntField (Is, FIELD_CC_ID, &Card->Id)) {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_CC_LOCALE);
if (p) {
Card->Locale = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_CC_LONGDISTANCE);
if (p) {
Card->LongDistance = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_CC_INTERNATIONAL);
if (p) {
Card->International = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_CC_PIN);
if (p) {
Card->Pin = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
if (!InfGetIntField (Is, FIELD_CC_FLAGS, &Card->Flags)) {
rSuccess = FALSE;
}
return rSuccess;
}
/*++
Routine Description:
pReadLocationFromIniFile reads the data located at the line in the ini file
referenced by the InfStruct passed in and parses that information into a
LOCATION structure.
Arguments:
Is - Initialized InfStruct pointing to a location line in an ini
file.
Location - Pointer to a location struct that recieves the parsed data.
Return Value:
TRUE if the line was successfully parsed, FALSE otherwise.
--*/
BOOL
pReadLocationFromIniFile (
IN PINFSTRUCT Is,
OUT PLOCATION Location
)
{
BOOL rSuccess = TRUE;
PTSTR p;
MYASSERT(Is);
MYASSERT(Location);
ZeroMemory(Location,sizeof(LOCATION));
p = InfGetStringField (Is, FIELD_NAME);
if (p) {
Location -> Name = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_AREACODE);
if (p) {
Location -> AreaCode = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
if (!InfGetIntField(Is,FIELD_COUNTRY,&(Location -> Country))) {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_DISABLECALLWAITING);
if (p) {
Location -> DisableCallWaiting = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_LONGDISTANCEACCESS);
if (p) {
Location -> LongDistanceAccess = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
p = InfGetStringField (Is, FIELD_OUTSIDEACCESS);
if (p) {
Location -> OutsideAccess = PoolMemDuplicateString (g_TapiPool, p);
}
else {
rSuccess = FALSE;
}
if (!InfGetIntField(Is,FIELD_ID, &(Location -> Id))) {
rSuccess = FALSE;
}
if (!InfGetIntField(Is,FIELD_PULSEDIAL, &(Location -> PulseDial))) {
rSuccess = FALSE;
}
if (!InfGetIntField(Is,FIELD_CALLINGCARD, &(Location -> CallingCard))) {
rSuccess = FALSE;
}
//
// Set TAPI flags for this location.
//
if (Location->CallingCard) {
//
// Non-zero calling card indicates this user calls using a card.
//
Location->Flags |= LOCATION_USECALLINGCARD;
}
if (Location->DisableCallWaiting &&
*Location->DisableCallWaiting &&
*Location->DisableCallWaiting != TEXT(' ')) {
//
// Non-empty disable string means the user has call waiting.
//
Location->Flags |= LOCATION_HASCALLWAITING;
}
if (!Location->PulseDial) {
Location->Flags |= LOCATION_USETONEDIALING;
}
return rSuccess;
}
/*++
Routine Description:
pSetStringRegValue is a simplification wrapper for RegSetValueEx. It is
used to set a string value in a currently opened key.
Arguments:
Key - a valid handle to a registry key.
Name - The name of the value to set
Data - The data to set in the value.
Return Value:
TRUE if the value was set successfully, FALSE otherwise.
--*/
BOOL
pSetStringRegValue (
IN HKEY Key,
IN PTSTR Name,
IN PTSTR Data
)
{
BOOL rSuccess = TRUE;
MYASSERT(Key);
MYASSERT(Name);
MYASSERT(Data);
if (ERROR_SUCCESS != RegSetValueEx(Key,Name,0,REG_SZ,(PBYTE) Data,SizeOfString(Data))) {
rSuccess = FALSE;
LOG ((LOG_ERROR,"SetStringRegValue failed! Value name: %s Value Data: %s",Name,Data));
}
return rSuccess;
}
/*++
Routine Description:
pSetDwordRegValue is a simplification wrapper for RegSetValueEx. It is
used to set a DWORD value in a currently opened key.
Arguments:
Key - a valid handle to a registry key.
Name - The name of the value to set
Data - The data to set in the value.
Return Value:
TRUE if the value was set successfully, FALSE otherwise.
--*/
BOOL
pSetDwordRegValue (
IN HKEY Key,
IN PTSTR Name,
IN DWORD Data
)
{
BOOL rSuccess = TRUE;
MYASSERT(Key);
MYASSERT(Name);
if (ERROR_SUCCESS != RegSetValueEx(Key,Name,0,REG_DWORD,(PBYTE) &Data,sizeof(DWORD))) {
rSuccess = FALSE;
LOG ((LOG_ERROR,"SetDwordRegValue failed! Value name: %s Value Data: %u",Name,Data));
}
return rSuccess;
}
/*++
Routine Description:
pWriteLocationToRegistry is responsible for saving a LOCATION structure
away into the NT 5.0 Registry.
Arguments:
DialingLocation - The name of the dialing location to create in the NT
registry.
LocationData - The LOCATION structure containing the data to write into
the NT 5 registry.
Return Value:
TRUE if the the function successfully saved the Dialing Location Data into
the NT 5 Registry, FALSE otherwise.
--*/
BOOL
pWriteLocationToRegistry (
IN PLOCATION LocationData
)
{
BOOL rSuccess = TRUE;
PTSTR regKeyString = NULL;
HKEY regKey = NULL;
MYASSERT(LocationData);
//
// Create %CURRENTVERSION%\Telephony\Locations\Location<n> Key
//
regKeyString = JoinPaths(S_LOCATIONS_REGKEY, LocationData->EntryName);
regKey = CreateRegKeyStr(regKeyString);
if (regKey) {
//
// Create Name String
//
rSuccess &= pSetStringRegValue(regKey,S_NAME,LocationData -> Name);
//
// Create AreaCode String
//
rSuccess &= pSetStringRegValue(regKey,S_AREACODE,LocationData -> AreaCode);
//
// Create Country Value
//
rSuccess &= pSetDwordRegValue(regKey,S_COUNTRY,LocationData -> Country);
//
// Create DisableCallWating String
//
rSuccess &= pSetStringRegValue(regKey,S_DISABLECALLWAITING,LocationData -> DisableCallWaiting);
//
// Create LongDistanceAccess String
//
rSuccess &= pSetStringRegValue(regKey,S_LONGDISTANCEACCESS,LocationData -> LongDistanceAccess);
//
// Create OutSideAccessString
//
rSuccess &= pSetStringRegValue(regKey,S_OUTSIDEACCESS,LocationData -> OutsideAccess);
//
// Create Flags Value
//
rSuccess &= pSetDwordRegValue(regKey,S_FLAGS,LocationData -> Flags);
//
// Create ID Value
//
rSuccess &= pSetDwordRegValue(regKey,S_ID,LocationData -> Id);
CloseRegKey(regKey);
}
else {
rSuccess = FALSE;
LOG ((LOG_ERROR,"Migrate Location: Error creating registry key %s.",regKeyString));
}
FreePathString(regKeyString);
if (!rSuccess) {
LOG ((
LOG_ERROR,
"Error creating Location registry entries for location %s.",
LocationData->EntryName
));
}
return rSuccess;
}
/*++
Routine Description:
pMigrateDialingLocations migrates all dialing locations from
%windir%\telephon.ini and into the NT registry.
Arguments:
None.
Return Value:
TRUE if dialing locations were successfully migrated, FALSE otherwise.
--*/
BOOL
pMigrateDialingLocations (
VOID
)
{
BOOL rSuccess = TRUE;
HKEY locationsKey = NULL;
PLOCATION location;
UINT i;
UINT count = GrowListGetSize (&g_LocationsList);
//
// Migrate individual locations.
//
for (i = 0; i < count; i++) {
location = (PLOCATION) GrowListGetItem (&g_LocationsList, i);
if (!pWriteLocationToRegistry (location)) {
rSuccess = FALSE;
DEBUGMSG ((DBG_ERROR, "Error writing TAPI location %s (%s) to the registry.", location->Name, location->EntryName));
}
}
if (count) {
locationsKey = OpenRegKeyStr(S_LOCATIONS_REGKEY);
if (locationsKey) {
//
// Update %CURRENTVERSION%\Telephony\Locations\[CurrentID]
//
if (!pSetDwordRegValue (locationsKey, S_CURRENTID, g_CurrentLocation)) {
rSuccess = FALSE;
}
//
// Update %CURRENTVERSION%\Telephony\Locations\[NextID]
//
if (!pSetDwordRegValue (locationsKey, S_NEXTID, count + 1)) {
rSuccess = FALSE;
}
//
// Update %CURRENTVERSION%\Telephony\Locations\[NumEntries]
//
if (!pSetDwordRegValue (locationsKey, S_NUMENTRIES, count)) {
rSuccess = FALSE;
}
CloseRegKey(locationsKey);
}
else {
rSuccess = FALSE;
LOG ((LOG_ERROR,"Tapi: Error opening %s key.",S_LOCATIONS_REGKEY));
}
}
return rSuccess;
}
VOID
pGatherLocationsData (
VOID
)
{
HINF hTelephonIni = INVALID_HANDLE_VALUE;
INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
BOOL rSuccess = TRUE;
PCTSTR telephonIniPath = NULL;
PTSTR curKey = NULL;
LOCATION location;
CALLINGCARD card;
HKEY locationsKey = NULL;
PCTSTR tempPath = NULL;
g_LocationsRead = TRUE;
//
// Open %windir%\telephon.ini
//
telephonIniPath = JoinPaths(g_WinDir,S_TELEPHON_INI);
tempPath = GetTemporaryLocationForFile (telephonIniPath);
if (tempPath) {
//
// telephon ini is in a temporary location. Use that.
//
DEBUGMSG ((DBG_TAPI, "Using %s for %s.", tempPath, telephonIniPath));
FreePathString (telephonIniPath);
telephonIniPath = tempPath;
}
hTelephonIni = InfOpenInfFile(telephonIniPath);
if (hTelephonIni) {
//
// For each location in [locations],
//
if (InfFindFirstLine(hTelephonIni,S_LOCATIONS,NULL,&is)) {
do {
curKey = InfGetStringField(&is,0);
if (!curKey) {
continue;
}
if (StringIMatch(curKey,S_LOCATIONS)) {
DEBUGMSG((DBG_TAPI,"From %s: Locations = %s",telephonIniPath,InfGetLineText(&is)));
//
// Nothing to do here right now..
//
}
else if (StringIMatch (curKey, S_CURRENTLOCATION)) {
if (!InfGetIntField (&is, 1, &g_CurrentLocation)) {
rSuccess = FALSE;
LOG((LOG_ERROR,"TAPI: Error retrieving current location information."));
}
}
else if (IsPatternMatch(TEXT("Location*"),curKey)) {
//
// Add this location to the list of locations.
//
if (!pReadLocationFromIniFile (&is, &location)) {
rSuccess = FALSE;
LOG ((LOG_ERROR,"TAPI: Error migrating location %s.",curKey));
}
StringCopy (location.EntryName, curKey);
GrowListAppend (&g_LocationsList, (PBYTE) &location, sizeof (LOCATION));
}
else if (StringIMatch(curKey,TEXT("Inited"))) {
DEBUGMSG((DBG_TAPI,"Inited key unused during migration."));
}
ELSE_DEBUGMSG((DBG_WHOOPS,"TAPI Dialing Location Migration: Ingored or Unknown key: %s",curKey));
InfResetInfStruct (&is);
} while (InfFindNextLine(&is));
//
// Read in all the calling card information.
//
if (InfFindFirstLine(hTelephonIni,S_CARDS,NULL,&is)) {
do {
curKey = InfGetStringField(&is,0);
if (!StringIMatch (curKey, S_CARDS) && IsPatternMatch (TEXT("Card*"),curKey)) {
ZeroMemory (&card, sizeof (CALLINGCARD));
StringCopy (card.EntryName, curKey);
if (!pReadCardFromIniFile (&is, &card)) {
rSuccess = FALSE;
LOG ((LOG_ERROR,"TAPI: Error migrating location %s.",curKey));
}
GrowListAppend (&g_CallingCardList, (PBYTE) &card, sizeof (CALLINGCARD));
}
InfResetInfStruct (&is);
} while (InfFindNextLine(&is));
}
}
DEBUGMSG((DBG_TAPI,"%u dialing locations found in telephon.ini.",GrowListGetSize (&g_LocationsList)));
InfCloseInfFile(hTelephonIni);
}
ELSE_DEBUGMSG((DBG_TAPI,"No telephon.ini file found, or, telephon.ini coudl not be opened."));
FreePathString(telephonIniPath);
InfCleanUpInfStruct(&is);
}
BOOL
Tapi_MigrateUser (
IN PCTSTR UserName,
IN HKEY UserRoot
)
{
BOOL rSuccess = TRUE;
UINT i;
UINT count;
HKEY hKey;
PTSTR keyString;
PLOCATION location;
PCALLINGCARD card;
if (!g_LocationsRead) {
pGatherLocationsData ();
}
//
// First, migrate user specific location information into the user
// registry..
//
count = GrowListGetSize (&g_LocationsList);
for (i = 0; i < count; i++) {
location = (PLOCATION) GrowListGetItem (&g_LocationsList, i);
keyString = JoinPaths (S_USERLOCATIONSKEY, location->EntryName);
hKey = CreateRegKey (UserRoot, keyString);
if (hKey) {
rSuccess &= pSetDwordRegValue (hKey, S_CALLINGCARD, location->CallingCard);
CloseRegKey (hKey);
}
FreePathString (keyString);
}
count = GrowListGetSize (&g_CallingCardList);
for (i = 0; i < count; i++) {
card = (PCALLINGCARD) GrowListGetItem (&g_CallingCardList, i);
keyString = JoinPaths (S_USERCALLINGCARDSKEY, card->EntryName);
hKey = CreateRegKey (UserRoot, keyString);
if (hKey) {
rSuccess &= pSetDwordRegValue (hKey, S_ID, card->Id);
rSuccess &= pSetStringRegValue (hKey, S_NAME, card->Name);
rSuccess &= pSetStringRegValue (hKey, S_LOCALRULE, card->Locale);
rSuccess &= pSetStringRegValue (hKey, S_LDRULE, card->LongDistance);
rSuccess &= pSetStringRegValue (hKey, S_INTERNATIONALRULE, card->International);
rSuccess &= pSetStringRegValue (hKey, S_PIN, card->Pin);
rSuccess &= pSetDwordRegValue (hKey, S_FLAGS, card->Flags);
CloseRegKey (hKey);
}
ELSE_DEBUGMSG ((DBG_ERROR, "TAPI: Could not open key %s for user %s.", card->EntryName, UserName));
FreePathString (keyString);
hKey = CreateRegKey (UserRoot, S_USERCALLINGCARDSKEY);
if (hKey) {
rSuccess &= pSetDwordRegValue (hKey, S_NEXTID, count);
rSuccess &= pSetDwordRegValue (hKey, S_NUMENTRIES, count);
CloseRegKey (hKey);
}
ELSE_DEBUGMSG ((DBG_ERROR, "TAPI: Could not open key %s for user %s.", S_USERCALLINGCARDSKEY, UserName));
}
//
// Next, we need to create calling card entries
//
if (!pMigrateDialingLocations()) {
ERROR_NONCRITICAL;
LOG ((LOG_ERROR, (PCSTR)MSG_UNABLE_TO_MIGRATE_TAPI_DIALING_LOCATIONS));
}
return rSuccess;
}
/*++
Routine Description:
Tapi_MigrateSystem is responsible for migrating all system-wide TAPI
settings from 95 to Windows NT5.
Arguments:
None.
Return Value:
TRUE if TAPI settings were successfully migrated, FALSE otherwise.
--*/
BOOL
Tapi_MigrateSystem (
VOID
)
{
BOOL rSuccess = TRUE;
if (!g_LocationsRead) {
pGatherLocationsData ();
}
if (!pMigrateDialingLocations()) {
ERROR_NONCRITICAL;
LOG ((LOG_ERROR, (PCSTR)MSG_UNABLE_TO_MIGRATE_TAPI_DIALING_LOCATIONS));
}
return rSuccess;
}
BOOL
Tapi_Entry (
IN HINSTANCE Instance,
IN DWORD Reason,
IN PVOID Reserved
)
{
BOOL rSuccess = TRUE;
switch (Reason)
{
case DLL_PROCESS_ATTACH:
//
// Initialize Memory pool.
//
g_TapiPool = PoolMemInitNamedPool ("Tapi");
if (!g_TapiPool) {
DEBUGMSG((DBG_ERROR,"Ras Migration: Pool Memory failed to initialize..."));
rSuccess = FALSE;
}
break;
case DLL_PROCESS_DETACH:
//
// Free memory pool.
//
FreeGrowList (&g_CallingCardList);
FreeGrowList (&g_LocationsList);
if (g_TapiPool) {
PoolMemDestroyPool(g_TapiPool);
}
break;
}
return rSuccess;
}
DWORD
DeleteSysTapiSettings (
IN DWORD Request
)
{
//
// Delete previous TAPI settings (OCM initiated.)
//
if (Request == REQUEST_QUERYTICKS) {
return TICKS_DELETESYSTAPI;
}
pSetupRegistryDelnode (HKEY_LOCAL_MACHINE, TEXT("software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations"));
return ERROR_SUCCESS;
}
DWORD
DeleteUserTapiSettings (
IN DWORD Request,
IN PMIGRATE_USER_ENUM EnumPtr
)
{
if (Request == REQUEST_QUERYTICKS) {
return TICKS_DELETEUSERTAPI;
}
pSetupRegistryDelnode (g_hKeyRootNT, TEXT("software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards"));
pSetupRegistryDelnode (g_hKeyRootNT, TEXT("software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations"));
return ERROR_SUCCESS;
}