1175 lines
33 KiB
C++
1175 lines
33 KiB
C++
|
/*--------------------------------------------------------------------------*\
|
||
|
Module: drv.cpp
|
||
|
|
||
|
Purpose: routines for dealing with drivers and their configuration
|
||
|
|
||
|
Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
|
||
|
History:
|
||
|
8/11/93 CBB - Hack-o-rama from NickH's stuff
|
||
|
10/15/98 ToddB - Major rewrite of ancient crap
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
|
||
|
#include "cplPreComp.h"
|
||
|
#include "drv.h"
|
||
|
#include "tlnklist.h"
|
||
|
|
||
|
#include <windowsx.h>
|
||
|
#include <shlwapi.h>
|
||
|
|
||
|
#define DBG_ASSERT(x,y)
|
||
|
|
||
|
#define CPL_SUCCESS 0
|
||
|
#define CPL_APP_ERROR 100
|
||
|
#define CPL_BAD_DRIVER 108
|
||
|
|
||
|
#define CPL_MAX_STRING 132 // biggest allowed string
|
||
|
|
||
|
|
||
|
//----------
|
||
|
// Externs
|
||
|
//----------
|
||
|
|
||
|
typedef BOOL ( APIENTRY PGETFILEVERSIONINFO(
|
||
|
LPTSTR lptstrFilename, // pointer to filename string
|
||
|
DWORD dwHandle, // ignored
|
||
|
DWORD dwLen, // size of buffer
|
||
|
LPVOID lpData // pointer to buffer to receive file-version info.
|
||
|
));
|
||
|
PGETFILEVERSIONINFO *gpGetFileVersionInfo;
|
||
|
|
||
|
typedef DWORD ( APIENTRY PGETFILEVERSIONINFOSIZE(
|
||
|
LPTSTR lptstrFilename, // pointer to filename string
|
||
|
LPDWORD lpdwHandle // pointer to variable to receive zero
|
||
|
));
|
||
|
PGETFILEVERSIONINFOSIZE *gpGetFileVersionInfoSize;
|
||
|
|
||
|
|
||
|
//------------
|
||
|
// Public Data
|
||
|
//------------
|
||
|
LPLINEPROVIDERLIST glpProviderList;
|
||
|
|
||
|
|
||
|
//-------------
|
||
|
// Private Data
|
||
|
//-------------
|
||
|
static TCHAR gszVarFileInfo[] = TEXT("\\VarFileInfo\\Translation");
|
||
|
static TCHAR gszStringFileInfo[] = TEXT("\\StringFileInfo\\%04x%04x\\FileDescription");
|
||
|
static TCHAR gszDriverFiles[] = TEXT("\\*.tsp");
|
||
|
|
||
|
// These are proc names passed to GetProcAddress and are therefore ANSI strings
|
||
|
static CHAR gszProviderInstall[] = "TSPI_providerInstall";
|
||
|
static CHAR gszProviderRemove[] = "TSPI_providerRemove";
|
||
|
static CHAR gszProviderSetup[] = "TSPI_providerConfig";
|
||
|
|
||
|
TCHAR gszHelpFile[] = TEXT("tapi.hlp");
|
||
|
|
||
|
|
||
|
//----------------------------
|
||
|
// Private Function Prototypes
|
||
|
//----------------------------
|
||
|
BOOL VerifyProcExists( LPTSTR lpszFile, LPSTR lpszProcName );
|
||
|
UINT GetProviderFileDesc( LPTSTR lpszFile, LPTSTR lpszDesc, int cchDesc );
|
||
|
BOOL FillAddDriverList( HWND hwndParent, HWND hwndList );
|
||
|
BOOL AddProvider( HWND hwndParent, HWND hwndList, LPTSTR lpszDriverFile );
|
||
|
LPTSTR ProviderIDToFilename( DWORD dwProviderID );
|
||
|
BOOL RefreshProviderList();
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: VerifyProcExists
|
||
|
|
||
|
Purpose: Verifies that the specified proceedure exists in the
|
||
|
specified service provider
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL VerifyProcExists( LPTSTR lpszFile, LPSTR lpszProcName )
|
||
|
{
|
||
|
BOOL fResult = TRUE;
|
||
|
HINSTANCE hProviderInst;
|
||
|
|
||
|
SetLastError(0);
|
||
|
|
||
|
hProviderInst = LoadLibrary( lpszFile );
|
||
|
|
||
|
if ( hProviderInst == NULL )
|
||
|
{
|
||
|
|
||
|
#ifdef MEMPHIS
|
||
|
// return TRUE for now - assume it is a 16 bit
|
||
|
// service provider. thunk sp can handle the
|
||
|
// failure cases.
|
||
|
|
||
|
fResult = TRUE;
|
||
|
#else
|
||
|
fResult = FALSE;
|
||
|
#endif
|
||
|
|
||
|
goto done;
|
||
|
} // end if
|
||
|
|
||
|
#ifdef MEMPHIS
|
||
|
if (GetLastError() == ERROR_BAD_EXE_FORMAT)
|
||
|
{
|
||
|
// 16 bit DLL
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
if (GetProcAddress( hProviderInst, lpszProcName ) == NULL)
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetProcAddress for \"%hs\" failed on file %s", lpszProcName, lpszFile ));
|
||
|
fResult = FALSE;
|
||
|
goto done;
|
||
|
} // end if
|
||
|
|
||
|
done:
|
||
|
|
||
|
if ( hProviderInst != NULL )
|
||
|
FreeLibrary( hProviderInst );
|
||
|
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: FillDriverList
|
||
|
|
||
|
Purpose: Use lineGetProviderList to retrieve provider list and
|
||
|
insert into listbox.
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL FillDriverList( HWND hwndList )
|
||
|
{
|
||
|
BOOL uResult;
|
||
|
UINT uIndex;
|
||
|
UINT uListIndex;
|
||
|
LPLINEPROVIDERENTRY lpProviderEntry;
|
||
|
|
||
|
if (!RefreshProviderList())
|
||
|
{
|
||
|
LOG((TL_ERROR, "Failing FillDriverList because RefreshProviderList returned FALSE"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DBG_ASSERT( glpProviderList, "Uninitialized Provider List after refresh" );
|
||
|
|
||
|
SendMessage( hwndList, WM_SETREDRAW, FALSE, 0 );
|
||
|
SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
|
||
|
|
||
|
// loop through the provider list
|
||
|
//-------------------------------
|
||
|
lpProviderEntry = (LPLINEPROVIDERENTRY)((LPBYTE)glpProviderList +
|
||
|
glpProviderList->dwProviderListOffset);
|
||
|
|
||
|
//
|
||
|
// Provider list integrity check
|
||
|
//
|
||
|
DBG_ASSERT( glpProviderList->dwTotalSize >= (glpProviderList->dwNumProviders * sizeof( LINEPROVIDERENTRY )),
|
||
|
"TAPI returned lineProviderList structure that is too small for number of providers" );
|
||
|
|
||
|
for ( uIndex = 0; uIndex < glpProviderList->dwNumProviders; uIndex++ )
|
||
|
{
|
||
|
LPTSTR lpszProviderFilename;
|
||
|
TCHAR szFriendlyName[CPL_MAX_STRING];
|
||
|
|
||
|
//
|
||
|
// Another provider list integrity check
|
||
|
//
|
||
|
DBG_ASSERT( lpProviderEntry[uIndex].dwProviderFilenameOffset +
|
||
|
lpProviderEntry[uIndex].dwProviderFilenameSize <=
|
||
|
glpProviderList->dwTotalSize,
|
||
|
"TAPI LINEPROVIDERLIST too small to hold provider filename" );
|
||
|
|
||
|
// Get an entry to put in the list box
|
||
|
//------------------------------------
|
||
|
lpszProviderFilename = (LPTSTR)((LPBYTE)glpProviderList +
|
||
|
lpProviderEntry[uIndex].dwProviderFilenameOffset);
|
||
|
|
||
|
// Determine the user-friendly name
|
||
|
//---------------------------------
|
||
|
|
||
|
#ifdef MEMPHIS
|
||
|
// if it's the thunk sp, don't show it in the list
|
||
|
if (!lstrcmpi(lpszProviderFilename, "tsp3216l.tsp"))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
uResult = GetProviderFileDesc( lpszProviderFilename, szFriendlyName, ARRAYSIZE(szFriendlyName) );
|
||
|
|
||
|
LOG((TL_INFO, "Provider friendly name: %s", szFriendlyName));
|
||
|
|
||
|
if (uResult != CPL_SUCCESS && uResult != CPL_BAD_DRIVER) // just leave bad driver in list
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uResult = TRUE;
|
||
|
}
|
||
|
|
||
|
// slam it into the list box
|
||
|
//--------------------------
|
||
|
uListIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szFriendlyName );
|
||
|
|
||
|
LOG((TL_INFO, "Setting item for index %ld, value=0x%08lx", (DWORD)uListIndex,
|
||
|
(DWORD)(lpProviderEntry[uIndex].dwPermanentProviderID) ));
|
||
|
|
||
|
SendMessage( hwndList, LB_SETITEMDATA, uListIndex,
|
||
|
(LPARAM)(lpProviderEntry[uIndex].dwPermanentProviderID) );
|
||
|
}
|
||
|
|
||
|
if (glpProviderList->dwNumProviders == 0)
|
||
|
{
|
||
|
// no providers, add in default string!
|
||
|
//-------------------------------------
|
||
|
|
||
|
TCHAR szText[CPL_MAX_STRING];
|
||
|
LoadString(GetUIInstance(),IDS_NOSERVICEPROVIDER,szText,ARRAYSIZE(szText));
|
||
|
|
||
|
uListIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szText);
|
||
|
SendMessage( hwndList, LB_SETITEMDATA, uListIndex, 0 );
|
||
|
}
|
||
|
|
||
|
uResult = TRUE;
|
||
|
|
||
|
done:
|
||
|
|
||
|
SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
|
||
|
SendMessage( hwndList, WM_SETREDRAW, TRUE, 0 );
|
||
|
|
||
|
return uResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: SetupDriver
|
||
|
|
||
|
Purpose: Calls lineConfigProvider
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL SetupDriver( HWND hwndParent, HWND hwndList )
|
||
|
{
|
||
|
LRESULT lResult;
|
||
|
LRESULT dwProviderID;
|
||
|
LONG res;
|
||
|
|
||
|
// get the id and tell tapi to configure the provider
|
||
|
//---------------------------------------------------
|
||
|
lResult = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
|
||
|
dwProviderID = SendMessage( hwndList, LB_GETITEMDATA, (WPARAM)lResult, 0L );
|
||
|
|
||
|
if ((dwProviderID == (LRESULT)LB_ERR) || (!dwProviderID))
|
||
|
{
|
||
|
LOG((TL_WARN, "Warning: strange... dwProviderID= 0x%08lx (uResult=0x%08lx)", (DWORD)dwProviderID, (DWORD)lResult));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
lResult = lineConfigProvider( hwndParent, (DWORD)dwProviderID );
|
||
|
|
||
|
if (lResult)
|
||
|
{
|
||
|
LOG((TL_WARN, "Warning: lineConfigProvider failure %#08lx", lResult ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: RemoveSelectedDriver
|
||
|
|
||
|
Purpose: Calls lineRemoveProvider
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL RemoveSelectedDriver( HWND hwndParent, HWND hwndList )
|
||
|
{
|
||
|
UINT uResult;
|
||
|
LRESULT lResult;
|
||
|
LRESULT lrListIndex;
|
||
|
LRESULT lrProviderID;
|
||
|
|
||
|
// find the one we should remove
|
||
|
//------------------------------
|
||
|
lrListIndex = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
|
||
|
lrProviderID = SendMessage( hwndList, LB_GETITEMDATA, lrListIndex, 0 );
|
||
|
|
||
|
LOG((TL_TRACE, "Removing provider ID = %#08lx", (DWORD)lrProviderID ));
|
||
|
|
||
|
if ((lrProviderID == (LRESULT)LB_ERR) || (!lrProviderID))
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// ask TAPI to remove this provider
|
||
|
//---------------------------------
|
||
|
lResult = lineRemoveProvider( (DWORD)lrProviderID, hwndParent );
|
||
|
|
||
|
if (lResult)
|
||
|
{
|
||
|
LOG((TL_WARN, "Warning: lineRemoveProvider failure %#08lx", lResult ));
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// remove him from the list box
|
||
|
//-----------------------------
|
||
|
lResult = SendMessage( hwndList, LB_DELETESTRING, lrListIndex, 0 );
|
||
|
|
||
|
if (lResult == LB_ERR )
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if ( lResult == 0 )
|
||
|
{
|
||
|
// no providers, add in default string!
|
||
|
//-------------------------------------
|
||
|
TCHAR szText[CPL_MAX_STRING];
|
||
|
LoadString(GetUIInstance(),IDS_NOSERVICEPROVIDER,szText,ARRAYSIZE(szText));
|
||
|
|
||
|
lResult = SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szText);
|
||
|
SendMessage( hwndList, LB_SETITEMDATA, (WPARAM)lResult, 0 ); // mark!
|
||
|
}
|
||
|
|
||
|
uResult = TRUE;
|
||
|
|
||
|
done:
|
||
|
|
||
|
SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
|
||
|
UpdateDriverDlgButtons(hwndParent);
|
||
|
|
||
|
return uResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: GetProviderFileDesc
|
||
|
|
||
|
Purpose: Reads the driver description from it's version info stuff
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
UINT GetProviderFileDesc( LPTSTR lpszFile, LPTSTR lpszDesc, int cchDesc)
|
||
|
{
|
||
|
UINT uResult;
|
||
|
UINT uItemSize;
|
||
|
DWORD dwSize;
|
||
|
DWORD dwVerHandle;
|
||
|
LPTSTR lpszBuffer;
|
||
|
LPBYTE lpbVerData;
|
||
|
TCHAR szItem[1000];
|
||
|
|
||
|
lpbVerData = NULL;
|
||
|
lstrcpyn( lpszDesc, lpszFile, cchDesc ); // returns filename as description if we have any errors
|
||
|
|
||
|
{
|
||
|
HINSTANCE hVersion = NULL;
|
||
|
|
||
|
if ( NULL == gpGetFileVersionInfo )
|
||
|
{
|
||
|
hVersion = LoadLibrary( TEXT("Version.dll") );
|
||
|
if ( NULL == hVersion )
|
||
|
{
|
||
|
LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
gpGetFileVersionInfo = (PGETFILEVERSIONINFO *)GetProcAddress(
|
||
|
hVersion,
|
||
|
#ifdef UNICODE
|
||
|
"GetFileVersionInfoW"
|
||
|
#else
|
||
|
"GetFileVersionInfoA"
|
||
|
#endif
|
||
|
);
|
||
|
if ( NULL == gpGetFileVersionInfo )
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'GetFileVersionInfo') failed! err=0x%08lx", GetLastError() ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( NULL == gpGetFileVersionInfoSize )
|
||
|
{
|
||
|
if ( NULL == hVersion )
|
||
|
{
|
||
|
hVersion = LoadLibrary( TEXT("Version.dll") );
|
||
|
}
|
||
|
|
||
|
if ( NULL == hVersion ) // Is it _STILL_ NULL?
|
||
|
{
|
||
|
LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
gpGetFileVersionInfoSize = (PGETFILEVERSIONINFOSIZE *)GetProcAddress(
|
||
|
hVersion,
|
||
|
#ifdef UNICODE
|
||
|
"GetFileVersionInfoSizeW"
|
||
|
#else
|
||
|
"GetFileVersionInfoSizeA"
|
||
|
#endif
|
||
|
);
|
||
|
|
||
|
if ( NULL == gpGetFileVersionInfoSize )
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'GetFileVersionInfoSize') failed! err=0x%08lx", GetLastError() ));
|
||
|
gpGetFileVersionInfo = NULL;
|
||
|
FreeLibrary( hVersion );
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((dwSize = gpGetFileVersionInfoSize( lpszFile, &dwVerHandle )) == 0)
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetFileVersionInfoSize failure for %s", lpszFile ));
|
||
|
uResult = CPL_BAD_DRIVER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
lpbVerData = (LPBYTE)GlobalAllocPtr( GPTR, dwSize + 10 );
|
||
|
if ( lpbVerData == NULL )
|
||
|
{
|
||
|
uResult = CPL_APP_ERROR;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if ( gpGetFileVersionInfo( lpszFile, dwVerHandle, dwSize, lpbVerData ) == FALSE )
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetFileVersionInfo failure for %s", lpszFile ));
|
||
|
uResult = CPL_BAD_DRIVER;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
lstrcpy( szItem, gszVarFileInfo ); // bug in VerQueryValue, can't handle static CS based str
|
||
|
|
||
|
{
|
||
|
HINSTANCE hVersion;
|
||
|
typedef BOOL ( APIENTRY PVERQUERYVALUE(
|
||
|
const LPVOID pBlock, // address of buffer for version resource
|
||
|
LPTSTR lpSubBlock, // address of value to retrieve
|
||
|
LPVOID *lplpBuffer, // address of buffer for version pointer
|
||
|
PUINT puLen // address of version-value length buffer
|
||
|
));
|
||
|
PVERQUERYVALUE *pVerQueryValue = NULL;
|
||
|
|
||
|
|
||
|
hVersion = LoadLibrary( TEXT("Version.dll") );
|
||
|
if ( NULL == hVersion )
|
||
|
{
|
||
|
LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pVerQueryValue = (PVERQUERYVALUE *)GetProcAddress(
|
||
|
hVersion,
|
||
|
#ifdef UNICODE
|
||
|
"VerQueryValueW"
|
||
|
#else
|
||
|
"VerQueryValueA"
|
||
|
#endif
|
||
|
);
|
||
|
|
||
|
if ( NULL == pVerQueryValue )
|
||
|
{
|
||
|
LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'VerQueryValue') failed! err=0x%08lx", GetLastError() ));
|
||
|
FreeLibrary( hVersion );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ((pVerQueryValue( lpbVerData, szItem, (void**)&lpszBuffer, (LPUINT)&uItemSize ) == FALSE) || (uItemSize == 0))
|
||
|
{
|
||
|
LOG((TL_ERROR, "ERROR: VerQueryValue failure for %s on file %s", szItem, lpszFile ));
|
||
|
uResult = CPL_SUCCESS; // does not matter if this did not work!
|
||
|
FreeLibrary( hVersion );
|
||
|
goto done;
|
||
|
} // end if
|
||
|
|
||
|
|
||
|
wsprintf( szItem, gszStringFileInfo, (WORD)*(LPWORD)lpszBuffer, (WORD)*(((LPWORD)lpszBuffer)+1) );
|
||
|
|
||
|
if ((pVerQueryValue( lpbVerData, szItem, (void**)&lpszBuffer, (LPUINT)&uItemSize ) == FALSE) || (uItemSize == 0))
|
||
|
{
|
||
|
LOG((TL_ERROR, "ERROR: VerQueryValue failure for %s on file %s", szItem, lpszFile ));
|
||
|
uResult = CPL_SUCCESS; // does not matter if this did not work!
|
||
|
FreeLibrary( hVersion );
|
||
|
goto done;
|
||
|
} // end if
|
||
|
|
||
|
FreeLibrary( hVersion );
|
||
|
}
|
||
|
|
||
|
lstrcpyn( lpszDesc, lpszBuffer, cchDesc );
|
||
|
|
||
|
uResult = CPL_SUCCESS;
|
||
|
|
||
|
done:
|
||
|
|
||
|
if ( lpbVerData )
|
||
|
GlobalFreePtr( lpbVerData );
|
||
|
|
||
|
return uResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#define MAX_PROVIDER_NAME 14
|
||
|
#define PROVIDERS_KEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers")
|
||
|
#define NUM_PROVIDERS TEXT("NumProviders")
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
LIST_ENTRY Entry;
|
||
|
TCHAR szName[MAX_PROVIDER_NAME];
|
||
|
} INSTALLED_PROVIDER, *PINSTALLED_PROVIDER;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
LIST_ENTRY Head;
|
||
|
DWORD dwEntries;
|
||
|
} LIST_HEAD, *PLIST_HEAD;
|
||
|
|
||
|
void BuildInstalledProviderList (PLIST_HEAD pListHead)
|
||
|
{
|
||
|
PINSTALLED_PROVIDER pProvider;
|
||
|
HKEY hKeyProviders;
|
||
|
DWORD dwNumProviders;
|
||
|
DWORD cbData;
|
||
|
DWORD i;
|
||
|
TCHAR szValueName[24]=TEXT("ProviderFileName");
|
||
|
TCHAR *pNumber = &szValueName[16];
|
||
|
|
||
|
InitializeListHead (&pListHead->Head);
|
||
|
pListHead->dwEntries = 0;
|
||
|
|
||
|
if (ERROR_SUCCESS !=
|
||
|
RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROVIDERS_KEY, 0, KEY_READ, &hKeyProviders))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cbData = sizeof (dwNumProviders);
|
||
|
if (ERROR_SUCCESS !=
|
||
|
RegQueryValueEx (hKeyProviders, NUM_PROVIDERS, NULL, NULL, (PBYTE)&dwNumProviders, &cbData) ||
|
||
|
0 == dwNumProviders)
|
||
|
{
|
||
|
goto CloseKeyAndReturn;
|
||
|
}
|
||
|
|
||
|
pProvider = (PINSTALLED_PROVIDER)ClientAlloc (sizeof (INSTALLED_PROVIDER));
|
||
|
if (NULL == pProvider)
|
||
|
{
|
||
|
goto CloseKeyAndReturn;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < dwNumProviders; i++)
|
||
|
{
|
||
|
wsprintf (pNumber, TEXT("%d"), i);
|
||
|
cbData = sizeof(pProvider->szName);
|
||
|
if (ERROR_SUCCESS ==
|
||
|
RegQueryValueEx (hKeyProviders, szValueName, NULL, NULL, (PBYTE)pProvider->szName, &cbData))
|
||
|
{
|
||
|
InsertHeadList (&pListHead->Head, &pProvider->Entry);
|
||
|
pListHead->dwEntries ++;
|
||
|
pProvider = (PINSTALLED_PROVIDER)ClientAlloc (sizeof (INSTALLED_PROVIDER));
|
||
|
if (NULL == pProvider)
|
||
|
{
|
||
|
goto CloseKeyAndReturn;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ClientFree (pProvider);
|
||
|
|
||
|
CloseKeyAndReturn:
|
||
|
RegCloseKey (hKeyProviders);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: FillAddDriverList
|
||
|
|
||
|
Purpose:
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL FillAddDriverList( HWND hwndParent, HWND hwndList )
|
||
|
{
|
||
|
UINT uIndex;
|
||
|
UINT uResult;
|
||
|
LPTSTR lpszDrvFile;
|
||
|
HANDLE hFindFile;
|
||
|
WIN32_FIND_DATA ftFileInfo;
|
||
|
TCHAR szFullPath[MAX_PATH+sizeof(gszDriverFiles)/sizeof(TCHAR)];
|
||
|
TCHAR szDrvDescription[CPL_MAX_STRING];
|
||
|
LIST_HEAD InstalledProvidersList;
|
||
|
PINSTALLED_PROVIDER pProvider;
|
||
|
|
||
|
SendMessage( hwndList, WM_SETREDRAW, FALSE, 0 );
|
||
|
SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
|
||
|
|
||
|
// build a list of installed providers,
|
||
|
// so that we don't allow the user to install them again
|
||
|
//------------------------------------------------------
|
||
|
BuildInstalledProviderList (&InstalledProvidersList);
|
||
|
|
||
|
// get full path to windows/system dir
|
||
|
//------------------------------------
|
||
|
uIndex = GetSystemDirectory( szFullPath, MAX_PATH);
|
||
|
if ((0 == uIndex) || (MAX_PATH < uIndex))
|
||
|
{
|
||
|
// Either the function failed,
|
||
|
// or the path is greater than MAX_PATH
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
uIndex = (UINT)lstrlen( szFullPath );
|
||
|
|
||
|
if ((uIndex > 0) && (szFullPath[uIndex-1] != '\\'))
|
||
|
lstrcat( szFullPath, gszDriverFiles ); // add the '\'
|
||
|
else
|
||
|
lstrcat( szFullPath, gszDriverFiles + 1 ); // ignore the '\' (root dir)
|
||
|
|
||
|
// find all the entries in the system dir
|
||
|
//---------------------------------------
|
||
|
|
||
|
hFindFile = FindFirstFile( szFullPath, &ftFileInfo );
|
||
|
uResult = TRUE;
|
||
|
if (hFindFile == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
LOG((TL_ERROR, "FindFirstFile failed, 0x%08lx", GetLastError() ));
|
||
|
uResult = FALSE;
|
||
|
}
|
||
|
|
||
|
while ( uResult )
|
||
|
{
|
||
|
// alloc and set the file name to be assocated with each driver
|
||
|
//-------------------------------------------------------------
|
||
|
lpszDrvFile = (LPTSTR)ClientAlloc((lstrlen(ftFileInfo.cFileName)+1)*sizeof(TCHAR));
|
||
|
if (NULL == lpszDrvFile)
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
lstrcpy( lpszDrvFile, ftFileInfo.cFileName );
|
||
|
|
||
|
LOG((TL_ERROR, "Examining file %s", lpszDrvFile ));
|
||
|
|
||
|
#ifdef MEMPHIS
|
||
|
|
||
|
if (!lstrcmpi(lpszDrvFile, "tsp3216l.tsp"))
|
||
|
{
|
||
|
ClientFree (lpszDrvFile);
|
||
|
goto next_driver;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// if the provider is already installed, skip it
|
||
|
//----------------------------------------------
|
||
|
for (pProvider = (PINSTALLED_PROVIDER)InstalledProvidersList.Head.Flink, uIndex = 0;
|
||
|
uIndex < InstalledProvidersList.dwEntries;
|
||
|
pProvider = (PINSTALLED_PROVIDER)pProvider->Entry.Flink, uIndex++)
|
||
|
{
|
||
|
if (!lstrcmpi (lpszDrvFile, pProvider->szName))
|
||
|
{
|
||
|
RemoveEntryList (&pProvider->Entry);
|
||
|
InstalledProvidersList.dwEntries --;
|
||
|
ClientFree (pProvider);
|
||
|
ClientFree (lpszDrvFile);
|
||
|
goto next_driver;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// cbb, should we make a full path???
|
||
|
uResult = GetProviderFileDesc( lpszDrvFile, szDrvDescription, ARRAYSIZE(szDrvDescription) );
|
||
|
if ( uResult != CPL_SUCCESS )
|
||
|
{
|
||
|
LOG((TL_ERROR, "No description for %s. Default to filename.", lpszDrvFile ));
|
||
|
|
||
|
/* Filename will have to suffice */
|
||
|
lstrcpy( szDrvDescription, lpszDrvFile );
|
||
|
uResult = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uResult = TRUE;
|
||
|
}
|
||
|
|
||
|
// Verify that provider has install routine
|
||
|
//-----------------------------------------
|
||
|
if (!VerifyProcExists( lpszDrvFile, gszProviderInstall ))
|
||
|
{
|
||
|
LOG((TL_ERROR, "No Install Proc"));
|
||
|
goto next_driver;
|
||
|
}
|
||
|
|
||
|
// slam it into the list box
|
||
|
//--------------------------
|
||
|
uIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szDrvDescription );
|
||
|
if ( uIndex == CB_ERR )
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if ( SendMessage( hwndList, LB_SETITEMDATA, uIndex, (LPARAM)lpszDrvFile ) == CB_ERR )
|
||
|
{
|
||
|
uResult = FALSE;
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
next_driver:
|
||
|
|
||
|
uResult = FALSE;
|
||
|
if (FindNextFile( hFindFile, &ftFileInfo ))
|
||
|
{
|
||
|
uResult = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while (InstalledProvidersList.dwEntries > 0)
|
||
|
{
|
||
|
pProvider = (PINSTALLED_PROVIDER)RemoveHeadList (&InstalledProvidersList.Head);
|
||
|
InstalledProvidersList.dwEntries --;
|
||
|
ClientFree (pProvider);
|
||
|
}
|
||
|
|
||
|
uResult = TRUE;
|
||
|
|
||
|
done:
|
||
|
if (0 == SendMessage (hwndList, LB_GETCOUNT, 0, 0))
|
||
|
{
|
||
|
if (0 < LoadString (GetUIInstance(), IDS_NO_PROVIDERS, szDrvDescription, ARRAYSIZE(szDrvDescription)))
|
||
|
{
|
||
|
SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szDrvDescription );
|
||
|
}
|
||
|
EnableWindow (GetDlgItem (hwndParent, IDC_ADD), FALSE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
|
||
|
UpdateDriverDlgButtons( hwndParent );
|
||
|
}
|
||
|
|
||
|
SendMessage( hwndList, WM_SETREDRAW, TRUE, 0 );
|
||
|
|
||
|
return uResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: AddProvider
|
||
|
|
||
|
Purpose: Call lineAddProvider
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
BOOL AddProvider( HWND hwndParent, HWND hwndList, LPTSTR lpszDriverFile )
|
||
|
{
|
||
|
UINT uIndex;
|
||
|
LONG lResult;
|
||
|
DWORD dwProviderID;
|
||
|
|
||
|
if ( lpszDriverFile == NULL )
|
||
|
{
|
||
|
DBG_ASSERT( hWnd, "Simultaneously NULL pointer & hwnd" );
|
||
|
|
||
|
// get the stuff from the list box
|
||
|
//--------------------------------
|
||
|
uIndex = (UINT)SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
|
||
|
lpszDriverFile = (LPTSTR)SendMessage( hwndList, LB_GETITEMDATA, uIndex, 0 );
|
||
|
|
||
|
if (lpszDriverFile == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lResult = lineAddProvider( lpszDriverFile, hwndParent, &dwProviderID );
|
||
|
|
||
|
if (lResult)
|
||
|
{
|
||
|
LOG((TL_ERROR, "Error: lineAddProvider failure %#08lx", lResult ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsUserAdmin()
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determine if current user is a member of the local admin's group
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
True if member
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
BOOL foundEntry = FALSE;
|
||
|
HANDLE hToken = NULL;
|
||
|
DWORD dwInfoSize = 0;
|
||
|
PTOKEN_GROUPS ptgGroups = NULL;
|
||
|
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
|
||
|
PSID pSid = NULL;
|
||
|
DWORD i;
|
||
|
|
||
|
//
|
||
|
// Get user thread or process token
|
||
|
//
|
||
|
|
||
|
if (!OpenThreadToken(
|
||
|
GetCurrentThread(),
|
||
|
TOKEN_QUERY,
|
||
|
FALSE,
|
||
|
&hToken))
|
||
|
{
|
||
|
if(!OpenProcessToken(
|
||
|
GetCurrentProcess(),
|
||
|
TOKEN_QUERY,
|
||
|
&hToken
|
||
|
))
|
||
|
{
|
||
|
goto ExitHere;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get user group SIDs
|
||
|
//
|
||
|
|
||
|
if (!GetTokenInformation(
|
||
|
hToken,
|
||
|
TokenGroups,
|
||
|
NULL,
|
||
|
0,
|
||
|
&dwInfoSize
|
||
|
))
|
||
|
{
|
||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
goto ExitHere;
|
||
|
}
|
||
|
}
|
||
|
ptgGroups = (PTOKEN_GROUPS) ClientAlloc (dwInfoSize);
|
||
|
if (ptgGroups == NULL)
|
||
|
{
|
||
|
goto ExitHere;
|
||
|
}
|
||
|
if (!GetTokenInformation(
|
||
|
hToken,
|
||
|
TokenGroups,
|
||
|
ptgGroups,
|
||
|
dwInfoSize,
|
||
|
&dwInfoSize
|
||
|
))
|
||
|
{
|
||
|
goto ExitHere;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the local admin group SID
|
||
|
//
|
||
|
|
||
|
if(!AllocateAndInitializeSid(
|
||
|
&sia,
|
||
|
2,
|
||
|
SECURITY_BUILTIN_DOMAIN_RID,
|
||
|
DOMAIN_ALIAS_RID_ADMINS,
|
||
|
0, 0, 0, 0, 0, 0,
|
||
|
&pSid
|
||
|
))
|
||
|
{
|
||
|
goto ExitHere;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Compare to see if the user is in admin group
|
||
|
//
|
||
|
for (i = 0; i < ptgGroups->GroupCount; ++i)
|
||
|
{
|
||
|
if (EqualSid (ptgGroups->Groups[i].Sid, pSid))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i < ptgGroups->GroupCount)
|
||
|
{
|
||
|
foundEntry = TRUE;
|
||
|
}
|
||
|
|
||
|
ExitHere:
|
||
|
if (pSid)
|
||
|
{
|
||
|
FreeSid (pSid);
|
||
|
}
|
||
|
if (ptgGroups)
|
||
|
{
|
||
|
ClientFree (ptgGroups);
|
||
|
}
|
||
|
if (hToken)
|
||
|
{
|
||
|
CloseHandle (hToken);
|
||
|
}
|
||
|
return foundEntry;
|
||
|
}
|
||
|
|
||
|
VOID UpdateDriverDlgButtons( HWND hwnd )
|
||
|
{
|
||
|
//
|
||
|
// Enable/disable the Remove & Config buttons as appropriate
|
||
|
//
|
||
|
|
||
|
UINT uResult;
|
||
|
LPTSTR lpszProviderFilename;
|
||
|
DWORD dwProviderID;
|
||
|
BOOL bAdmin = IsUserAdmin ();
|
||
|
|
||
|
uResult = (UINT) SendDlgItemMessage(
|
||
|
hwnd,
|
||
|
IDC_LIST,
|
||
|
LB_GETCURSEL,
|
||
|
0,
|
||
|
0
|
||
|
);
|
||
|
|
||
|
dwProviderID = (DWORD) SendDlgItemMessage(
|
||
|
hwnd,
|
||
|
IDC_LIST,
|
||
|
LB_GETITEMDATA,
|
||
|
uResult, 0
|
||
|
);
|
||
|
|
||
|
lpszProviderFilename = ProviderIDToFilename (dwProviderID);
|
||
|
|
||
|
EnableWindow(
|
||
|
GetDlgItem (hwnd, IDC_ADD),
|
||
|
bAdmin
|
||
|
);
|
||
|
|
||
|
EnableWindow(
|
||
|
GetDlgItem (hwnd, IDC_REMOVE),
|
||
|
bAdmin &&
|
||
|
(lpszProviderFilename != NULL) &&
|
||
|
VerifyProcExists (lpszProviderFilename, gszProviderRemove)
|
||
|
);
|
||
|
|
||
|
EnableWindow(
|
||
|
GetDlgItem( hwnd, IDC_EDIT),
|
||
|
bAdmin &&
|
||
|
(lpszProviderFilename != NULL) &&
|
||
|
VerifyProcExists (lpszProviderFilename, gszProviderSetup)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*\
|
||
|
|
||
|
Function: AddDriver_DialogProc
|
||
|
|
||
|
Purpose:
|
||
|
|
||
|
\*--------------------------------------------------------------------------*/
|
||
|
INT_PTR AddDriver_DialogProc( HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( wMessage )
|
||
|
{
|
||
|
case WM_HELP:
|
||
|
// Process clicks on controls after Context Help mode selected
|
||
|
WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a114HelpIDs);
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
// Process right-clicks on controls
|
||
|
WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a114HelpIDs);
|
||
|
break;
|
||
|
|
||
|
case WM_INITDIALOG:
|
||
|
// initalize all the fields
|
||
|
//-------------------------
|
||
|
if ( !FillAddDriverList(hWnd, GetDlgItem(hWnd, IDC_DRIVER_LIST)) )
|
||
|
{
|
||
|
EndDialog( hWnd, IDCANCEL );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if ( SendDlgItemMessage( hWnd, IDC_DRIVER_LIST, LB_GETCOUNT, 0, 0 ) <= 0 )
|
||
|
EnableWindow( GetDlgItem( hWnd, IDC_ADD ), FALSE );
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
// do some work with the buttons
|
||
|
//------------------------------
|
||
|
switch ( GET_WM_COMMAND_ID(wParam, lParam) )
|
||
|
{
|
||
|
case IDC_DRIVER_LIST:
|
||
|
|
||
|
// do the list stuff
|
||
|
//------------------
|
||
|
if ((GET_WM_COMMAND_CMD( wParam, lParam ) != LBN_DBLCLK) || (SendDlgItemMessage( hWnd, IDC_DRIVER_LIST, LB_GETCOUNT, 0, 0 ) <= 0 ))
|
||
|
break; // done
|
||
|
// fall through, threat the double click like an add message
|
||
|
|
||
|
case IDC_ADD:
|
||
|
|
||
|
// add a new driver
|
||
|
//-----------------
|
||
|
|
||
|
if ( !AddProvider(hWnd, GetDlgItem(hWnd, IDC_DRIVER_LIST), NULL) )
|
||
|
{
|
||
|
wParam = IDCANCEL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wParam = IDOK;
|
||
|
}
|
||
|
|
||
|
// fall through, exit the dialog
|
||
|
|
||
|
case IDOK:
|
||
|
case IDCANCEL:
|
||
|
{
|
||
|
UINT uIndex, uCount;
|
||
|
LPTSTR lpszDriverFile;
|
||
|
HWND hwndList = GetDlgItem(hWnd, IDC_DRIVER_LIST);
|
||
|
|
||
|
uCount = (UINT)SendMessage( hwndList, LB_GETCOUNT, 0, 0 );
|
||
|
for (uIndex = 0; uIndex < uCount; uIndex++)
|
||
|
{
|
||
|
lpszDriverFile = (LPTSTR)SendMessage( hwndList, LB_GETITEMDATA, uIndex, 0 );
|
||
|
if (NULL != lpszDriverFile)
|
||
|
{
|
||
|
ClientFree (lpszDriverFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EndDialog( hWnd, wParam );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
//---------------------------------------------------------------------------
|
||
|
BOOL RefreshProviderList()
|
||
|
{
|
||
|
LONG lResult;
|
||
|
|
||
|
|
||
|
if (!glpProviderList)
|
||
|
{
|
||
|
// Initialize data structure
|
||
|
|
||
|
glpProviderList = (LPLINEPROVIDERLIST)GlobalAllocPtr(GPTR, INITIAL_PROVIDER_LIST_SIZE);
|
||
|
}
|
||
|
|
||
|
if (!glpProviderList)
|
||
|
{
|
||
|
LOG((TL_ERROR, " RefreshProviderList - glpProviderList is NULL - returning CPL_ERR_MEMORY"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
glpProviderList->dwTotalSize = INITIAL_PROVIDER_LIST_SIZE;
|
||
|
|
||
|
lResult = lineGetProviderList( TAPI_VERSION, glpProviderList );
|
||
|
|
||
|
if (lResult)
|
||
|
{
|
||
|
LOG((TL_ERROR, "Error: lineGetProviderList failure %#08lx", lResult ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
while (glpProviderList->dwNeededSize > glpProviderList->dwTotalSize)
|
||
|
{
|
||
|
// Expand data structure as necessary
|
||
|
LOG((TL_ERROR, " RefreshProviderList - expanding glpProviderList."));
|
||
|
|
||
|
LPLINEPROVIDERLIST lpTemp =
|
||
|
(LPLINEPROVIDERLIST)GlobalReAllocPtr( glpProviderList,
|
||
|
(size_t)(glpProviderList->dwNeededSize),
|
||
|
GPTR);
|
||
|
|
||
|
if (!lpTemp)
|
||
|
return FALSE;
|
||
|
|
||
|
glpProviderList = lpTemp;
|
||
|
glpProviderList->dwTotalSize = glpProviderList->dwNeededSize;
|
||
|
lResult = lineGetProviderList( TAPI_VERSION, glpProviderList );
|
||
|
|
||
|
if (lResult)
|
||
|
{
|
||
|
LOG((TL_ERROR, "Error: lineGetProviderList failure %#08lx", lResult ));
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOG((TL_ERROR, "%d providers", glpProviderList->dwNumProviders ));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LPTSTR ProviderIDToFilename( DWORD dwProviderID )
|
||
|
{
|
||
|
UINT uIndex;
|
||
|
LPLINEPROVIDERENTRY lpProviderEntry;
|
||
|
|
||
|
// loop through the provider list
|
||
|
//-------------------------------
|
||
|
|
||
|
lpProviderEntry = (LPLINEPROVIDERENTRY)((LPBYTE)glpProviderList +
|
||
|
glpProviderList->dwProviderListOffset);
|
||
|
|
||
|
for ( uIndex = 0; uIndex < glpProviderList->dwNumProviders; uIndex++ )
|
||
|
{
|
||
|
if (lpProviderEntry[uIndex].dwPermanentProviderID == dwProviderID)
|
||
|
{
|
||
|
// Get an entry to put in the list box
|
||
|
//------------------------------------
|
||
|
return (LPTSTR)((LPBYTE)glpProviderList +
|
||
|
lpProviderEntry[uIndex].dwProviderFilenameOffset);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOG((TL_ERROR, "Provider ID %d not found in list", dwProviderID ));
|
||
|
return NULL;
|
||
|
}
|
||
|
|