|
|
/*++
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"
#include "migmainp.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; }
|