Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1174 lines
33 KiB

  1. /*--------------------------------------------------------------------------*\
  2. Module: drv.cpp
  3. Purpose: routines for dealing with drivers and their configuration
  4. Copyright (c) 1998-1999 Microsoft Corporation
  5. History:
  6. 8/11/93 CBB - Hack-o-rama from NickH's stuff
  7. 10/15/98 ToddB - Major rewrite of ancient crap
  8. \*--------------------------------------------------------------------------*/
  9. #include "cplPreComp.h"
  10. #include "drv.h"
  11. #include "tlnklist.h"
  12. #include <windowsx.h>
  13. #include <shlwapi.h>
  14. #define DBG_ASSERT(x,y)
  15. #define CPL_SUCCESS 0
  16. #define CPL_APP_ERROR 100
  17. #define CPL_BAD_DRIVER 108
  18. #define CPL_MAX_STRING 132 // biggest allowed string
  19. //----------
  20. // Externs
  21. //----------
  22. typedef BOOL ( APIENTRY PGETFILEVERSIONINFO(
  23. LPTSTR lptstrFilename, // pointer to filename string
  24. DWORD dwHandle, // ignored
  25. DWORD dwLen, // size of buffer
  26. LPVOID lpData // pointer to buffer to receive file-version info.
  27. ));
  28. PGETFILEVERSIONINFO *gpGetFileVersionInfo;
  29. typedef DWORD ( APIENTRY PGETFILEVERSIONINFOSIZE(
  30. LPTSTR lptstrFilename, // pointer to filename string
  31. LPDWORD lpdwHandle // pointer to variable to receive zero
  32. ));
  33. PGETFILEVERSIONINFOSIZE *gpGetFileVersionInfoSize;
  34. //------------
  35. // Public Data
  36. //------------
  37. LPLINEPROVIDERLIST glpProviderList;
  38. //-------------
  39. // Private Data
  40. //-------------
  41. static TCHAR gszVarFileInfo[] = TEXT("\\VarFileInfo\\Translation");
  42. static TCHAR gszStringFileInfo[] = TEXT("\\StringFileInfo\\%04x%04x\\FileDescription");
  43. static TCHAR gszDriverFiles[] = TEXT("\\*.tsp");
  44. // These are proc names passed to GetProcAddress and are therefore ANSI strings
  45. static CHAR gszProviderInstall[] = "TSPI_providerInstall";
  46. static CHAR gszProviderRemove[] = "TSPI_providerRemove";
  47. static CHAR gszProviderSetup[] = "TSPI_providerConfig";
  48. TCHAR gszHelpFile[] = TEXT("tapi.hlp");
  49. //----------------------------
  50. // Private Function Prototypes
  51. //----------------------------
  52. BOOL VerifyProcExists( LPTSTR lpszFile, LPSTR lpszProcName );
  53. UINT GetProviderFileDesc( LPTSTR lpszFile, LPTSTR lpszDesc, int cchDesc );
  54. BOOL FillAddDriverList( HWND hwndParent, HWND hwndList );
  55. BOOL AddProvider( HWND hwndParent, HWND hwndList, LPTSTR lpszDriverFile );
  56. LPTSTR ProviderIDToFilename( DWORD dwProviderID );
  57. BOOL RefreshProviderList();
  58. /*--------------------------------------------------------------------------*\
  59. Function: VerifyProcExists
  60. Purpose: Verifies that the specified proceedure exists in the
  61. specified service provider
  62. \*--------------------------------------------------------------------------*/
  63. BOOL VerifyProcExists( LPTSTR lpszFile, LPSTR lpszProcName )
  64. {
  65. BOOL fResult = TRUE;
  66. HINSTANCE hProviderInst;
  67. SetLastError(0);
  68. hProviderInst = LoadLibrary( lpszFile );
  69. if ( hProviderInst == NULL )
  70. {
  71. #ifdef MEMPHIS
  72. // return TRUE for now - assume it is a 16 bit
  73. // service provider. thunk sp can handle the
  74. // failure cases.
  75. fResult = TRUE;
  76. #else
  77. fResult = FALSE;
  78. #endif
  79. goto done;
  80. } // end if
  81. #ifdef MEMPHIS
  82. if (GetLastError() == ERROR_BAD_EXE_FORMAT)
  83. {
  84. // 16 bit DLL
  85. return TRUE;
  86. }
  87. #endif
  88. if (GetProcAddress( hProviderInst, lpszProcName ) == NULL)
  89. {
  90. LOG((TL_ERROR, "GetProcAddress for \"%hs\" failed on file %s", lpszProcName, lpszFile ));
  91. fResult = FALSE;
  92. goto done;
  93. } // end if
  94. done:
  95. if ( hProviderInst != NULL )
  96. FreeLibrary( hProviderInst );
  97. return fResult;
  98. }
  99. /*--------------------------------------------------------------------------*\
  100. Function: FillDriverList
  101. Purpose: Use lineGetProviderList to retrieve provider list and
  102. insert into listbox.
  103. \*--------------------------------------------------------------------------*/
  104. BOOL FillDriverList( HWND hwndList )
  105. {
  106. BOOL uResult;
  107. UINT uIndex;
  108. UINT uListIndex;
  109. LPLINEPROVIDERENTRY lpProviderEntry;
  110. if (!RefreshProviderList())
  111. {
  112. LOG((TL_ERROR, "Failing FillDriverList because RefreshProviderList returned FALSE"));
  113. return FALSE;
  114. }
  115. DBG_ASSERT( glpProviderList, "Uninitialized Provider List after refresh" );
  116. SendMessage( hwndList, WM_SETREDRAW, FALSE, 0 );
  117. SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
  118. // loop through the provider list
  119. //-------------------------------
  120. lpProviderEntry = (LPLINEPROVIDERENTRY)((LPBYTE)glpProviderList +
  121. glpProviderList->dwProviderListOffset);
  122. //
  123. // Provider list integrity check
  124. //
  125. DBG_ASSERT( glpProviderList->dwTotalSize >= (glpProviderList->dwNumProviders * sizeof( LINEPROVIDERENTRY )),
  126. "TAPI returned lineProviderList structure that is too small for number of providers" );
  127. for ( uIndex = 0; uIndex < glpProviderList->dwNumProviders; uIndex++ )
  128. {
  129. LPTSTR lpszProviderFilename;
  130. TCHAR szFriendlyName[CPL_MAX_STRING];
  131. //
  132. // Another provider list integrity check
  133. //
  134. DBG_ASSERT( lpProviderEntry[uIndex].dwProviderFilenameOffset +
  135. lpProviderEntry[uIndex].dwProviderFilenameSize <=
  136. glpProviderList->dwTotalSize,
  137. "TAPI LINEPROVIDERLIST too small to hold provider filename" );
  138. // Get an entry to put in the list box
  139. //------------------------------------
  140. lpszProviderFilename = (LPTSTR)((LPBYTE)glpProviderList +
  141. lpProviderEntry[uIndex].dwProviderFilenameOffset);
  142. // Determine the user-friendly name
  143. //---------------------------------
  144. #ifdef MEMPHIS
  145. // if it's the thunk sp, don't show it in the list
  146. if (!lstrcmpi(lpszProviderFilename, "tsp3216l.tsp"))
  147. {
  148. continue;
  149. }
  150. #endif
  151. uResult = GetProviderFileDesc( lpszProviderFilename, szFriendlyName, ARRAYSIZE(szFriendlyName) );
  152. LOG((TL_INFO, "Provider friendly name: %s", szFriendlyName));
  153. if (uResult != CPL_SUCCESS && uResult != CPL_BAD_DRIVER) // just leave bad driver in list
  154. {
  155. uResult = FALSE;
  156. goto done;
  157. }
  158. else
  159. {
  160. uResult = TRUE;
  161. }
  162. // slam it into the list box
  163. //--------------------------
  164. uListIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szFriendlyName );
  165. LOG((TL_INFO, "Setting item for index %ld, value=0x%08lx", (DWORD)uListIndex,
  166. (DWORD)(lpProviderEntry[uIndex].dwPermanentProviderID) ));
  167. SendMessage( hwndList, LB_SETITEMDATA, uListIndex,
  168. (LPARAM)(lpProviderEntry[uIndex].dwPermanentProviderID) );
  169. }
  170. if (glpProviderList->dwNumProviders == 0)
  171. {
  172. // no providers, add in default string!
  173. //-------------------------------------
  174. TCHAR szText[CPL_MAX_STRING];
  175. LoadString(GetUIInstance(),IDS_NOSERVICEPROVIDER,szText,ARRAYSIZE(szText));
  176. uListIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szText);
  177. SendMessage( hwndList, LB_SETITEMDATA, uListIndex, 0 );
  178. }
  179. uResult = TRUE;
  180. done:
  181. SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
  182. SendMessage( hwndList, WM_SETREDRAW, TRUE, 0 );
  183. return uResult;
  184. }
  185. /*--------------------------------------------------------------------------*\
  186. Function: SetupDriver
  187. Purpose: Calls lineConfigProvider
  188. \*--------------------------------------------------------------------------*/
  189. BOOL SetupDriver( HWND hwndParent, HWND hwndList )
  190. {
  191. LRESULT lResult;
  192. LRESULT dwProviderID;
  193. LONG res;
  194. // get the id and tell tapi to configure the provider
  195. //---------------------------------------------------
  196. lResult = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
  197. dwProviderID = SendMessage( hwndList, LB_GETITEMDATA, (WPARAM)lResult, 0L );
  198. if ((dwProviderID == (LRESULT)LB_ERR) || (!dwProviderID))
  199. {
  200. LOG((TL_WARN, "Warning: strange... dwProviderID= 0x%08lx (uResult=0x%08lx)", (DWORD)dwProviderID, (DWORD)lResult));
  201. return FALSE;
  202. }
  203. lResult = lineConfigProvider( hwndParent, (DWORD)dwProviderID );
  204. if (lResult)
  205. {
  206. LOG((TL_WARN, "Warning: lineConfigProvider failure %#08lx", lResult ));
  207. return FALSE;
  208. }
  209. return TRUE;
  210. }
  211. /*--------------------------------------------------------------------------*\
  212. Function: RemoveSelectedDriver
  213. Purpose: Calls lineRemoveProvider
  214. \*--------------------------------------------------------------------------*/
  215. BOOL RemoveSelectedDriver( HWND hwndParent, HWND hwndList )
  216. {
  217. UINT uResult;
  218. LRESULT lResult;
  219. LRESULT lrListIndex;
  220. LRESULT lrProviderID;
  221. // find the one we should remove
  222. //------------------------------
  223. lrListIndex = SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
  224. lrProviderID = SendMessage( hwndList, LB_GETITEMDATA, lrListIndex, 0 );
  225. LOG((TL_TRACE, "Removing provider ID = %#08lx", (DWORD)lrProviderID ));
  226. if ((lrProviderID == (LRESULT)LB_ERR) || (!lrProviderID))
  227. {
  228. uResult = FALSE;
  229. goto done;
  230. }
  231. // ask TAPI to remove this provider
  232. //---------------------------------
  233. lResult = lineRemoveProvider( (DWORD)lrProviderID, hwndParent );
  234. if (lResult)
  235. {
  236. LOG((TL_WARN, "Warning: lineRemoveProvider failure %#08lx", lResult ));
  237. uResult = FALSE;
  238. goto done;
  239. }
  240. // remove him from the list box
  241. //-----------------------------
  242. lResult = SendMessage( hwndList, LB_DELETESTRING, lrListIndex, 0 );
  243. if (lResult == LB_ERR )
  244. {
  245. uResult = FALSE;
  246. goto done;
  247. }
  248. if ( lResult == 0 )
  249. {
  250. // no providers, add in default string!
  251. //-------------------------------------
  252. TCHAR szText[CPL_MAX_STRING];
  253. LoadString(GetUIInstance(),IDS_NOSERVICEPROVIDER,szText,ARRAYSIZE(szText));
  254. lResult = SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szText);
  255. SendMessage( hwndList, LB_SETITEMDATA, (WPARAM)lResult, 0 ); // mark!
  256. }
  257. uResult = TRUE;
  258. done:
  259. SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
  260. UpdateDriverDlgButtons(hwndParent);
  261. return uResult;
  262. }
  263. /*--------------------------------------------------------------------------*\
  264. Function: GetProviderFileDesc
  265. Purpose: Reads the driver description from it's version info stuff
  266. \*--------------------------------------------------------------------------*/
  267. UINT GetProviderFileDesc( LPTSTR lpszFile, LPTSTR lpszDesc, int cchDesc)
  268. {
  269. UINT uResult;
  270. UINT uItemSize;
  271. DWORD dwSize;
  272. DWORD dwVerHandle;
  273. LPTSTR lpszBuffer;
  274. LPBYTE lpbVerData;
  275. TCHAR szItem[1000];
  276. lpbVerData = NULL;
  277. lstrcpyn( lpszDesc, lpszFile, cchDesc ); // returns filename as description if we have any errors
  278. {
  279. HINSTANCE hVersion = NULL;
  280. if ( NULL == gpGetFileVersionInfo )
  281. {
  282. hVersion = LoadLibrary( TEXT("Version.dll") );
  283. if ( NULL == hVersion )
  284. {
  285. LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
  286. return FALSE;
  287. }
  288. gpGetFileVersionInfo = (PGETFILEVERSIONINFO *)GetProcAddress(
  289. hVersion,
  290. #ifdef UNICODE
  291. "GetFileVersionInfoW"
  292. #else
  293. "GetFileVersionInfoA"
  294. #endif
  295. );
  296. if ( NULL == gpGetFileVersionInfo )
  297. {
  298. LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'GetFileVersionInfo') failed! err=0x%08lx", GetLastError() ));
  299. return FALSE;
  300. }
  301. }
  302. if ( NULL == gpGetFileVersionInfoSize )
  303. {
  304. if ( NULL == hVersion )
  305. {
  306. hVersion = LoadLibrary( TEXT("Version.dll") );
  307. }
  308. if ( NULL == hVersion ) // Is it _STILL_ NULL?
  309. {
  310. LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
  311. return FALSE;
  312. }
  313. gpGetFileVersionInfoSize = (PGETFILEVERSIONINFOSIZE *)GetProcAddress(
  314. hVersion,
  315. #ifdef UNICODE
  316. "GetFileVersionInfoSizeW"
  317. #else
  318. "GetFileVersionInfoSizeA"
  319. #endif
  320. );
  321. if ( NULL == gpGetFileVersionInfoSize )
  322. {
  323. LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'GetFileVersionInfoSize') failed! err=0x%08lx", GetLastError() ));
  324. gpGetFileVersionInfo = NULL;
  325. FreeLibrary( hVersion );
  326. return FALSE;
  327. }
  328. }
  329. }
  330. if ((dwSize = gpGetFileVersionInfoSize( lpszFile, &dwVerHandle )) == 0)
  331. {
  332. LOG((TL_ERROR, "GetFileVersionInfoSize failure for %s", lpszFile ));
  333. uResult = CPL_BAD_DRIVER;
  334. goto done;
  335. }
  336. lpbVerData = (LPBYTE)GlobalAllocPtr( GPTR, dwSize + 10 );
  337. if ( lpbVerData == NULL )
  338. {
  339. uResult = CPL_APP_ERROR;
  340. goto done;
  341. }
  342. if ( gpGetFileVersionInfo( lpszFile, dwVerHandle, dwSize, lpbVerData ) == FALSE )
  343. {
  344. LOG((TL_ERROR, "GetFileVersionInfo failure for %s", lpszFile ));
  345. uResult = CPL_BAD_DRIVER;
  346. goto done;
  347. }
  348. lstrcpy( szItem, gszVarFileInfo ); // bug in VerQueryValue, can't handle static CS based str
  349. {
  350. HINSTANCE hVersion;
  351. typedef BOOL ( APIENTRY PVERQUERYVALUE(
  352. const LPVOID pBlock, // address of buffer for version resource
  353. LPTSTR lpSubBlock, // address of value to retrieve
  354. LPVOID *lplpBuffer, // address of buffer for version pointer
  355. PUINT puLen // address of version-value length buffer
  356. ));
  357. PVERQUERYVALUE *pVerQueryValue = NULL;
  358. hVersion = LoadLibrary( TEXT("Version.dll") );
  359. if ( NULL == hVersion )
  360. {
  361. LOG((TL_ERROR, "LoadLibrary('VERSION.DLL') failed! err=0x%08lx", GetLastError() ));
  362. return FALSE;
  363. }
  364. pVerQueryValue = (PVERQUERYVALUE *)GetProcAddress(
  365. hVersion,
  366. #ifdef UNICODE
  367. "VerQueryValueW"
  368. #else
  369. "VerQueryValueA"
  370. #endif
  371. );
  372. if ( NULL == pVerQueryValue )
  373. {
  374. LOG((TL_ERROR, "GetProcAddress('VERSION.DLL', 'VerQueryValue') failed! err=0x%08lx", GetLastError() ));
  375. FreeLibrary( hVersion );
  376. return FALSE;
  377. }
  378. if ((pVerQueryValue( lpbVerData, szItem, (void**)&lpszBuffer, (LPUINT)&uItemSize ) == FALSE) || (uItemSize == 0))
  379. {
  380. LOG((TL_ERROR, "ERROR: VerQueryValue failure for %s on file %s", szItem, lpszFile ));
  381. uResult = CPL_SUCCESS; // does not matter if this did not work!
  382. FreeLibrary( hVersion );
  383. goto done;
  384. } // end if
  385. wsprintf( szItem, gszStringFileInfo, (WORD)*(LPWORD)lpszBuffer, (WORD)*(((LPWORD)lpszBuffer)+1) );
  386. if ((pVerQueryValue( lpbVerData, szItem, (void**)&lpszBuffer, (LPUINT)&uItemSize ) == FALSE) || (uItemSize == 0))
  387. {
  388. LOG((TL_ERROR, "ERROR: VerQueryValue failure for %s on file %s", szItem, lpszFile ));
  389. uResult = CPL_SUCCESS; // does not matter if this did not work!
  390. FreeLibrary( hVersion );
  391. goto done;
  392. } // end if
  393. FreeLibrary( hVersion );
  394. }
  395. lstrcpyn( lpszDesc, lpszBuffer, cchDesc );
  396. uResult = CPL_SUCCESS;
  397. done:
  398. if ( lpbVerData )
  399. GlobalFreePtr( lpbVerData );
  400. return uResult;
  401. }
  402. #define MAX_PROVIDER_NAME 14
  403. #define PROVIDERS_KEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Providers")
  404. #define NUM_PROVIDERS TEXT("NumProviders")
  405. typedef struct
  406. {
  407. LIST_ENTRY Entry;
  408. TCHAR szName[MAX_PROVIDER_NAME];
  409. } INSTALLED_PROVIDER, *PINSTALLED_PROVIDER;
  410. typedef struct
  411. {
  412. LIST_ENTRY Head;
  413. DWORD dwEntries;
  414. } LIST_HEAD, *PLIST_HEAD;
  415. void BuildInstalledProviderList (PLIST_HEAD pListHead)
  416. {
  417. PINSTALLED_PROVIDER pProvider;
  418. HKEY hKeyProviders;
  419. DWORD dwNumProviders;
  420. DWORD cbData;
  421. DWORD i;
  422. TCHAR szValueName[24]=TEXT("ProviderFileName");
  423. TCHAR *pNumber = &szValueName[16];
  424. InitializeListHead (&pListHead->Head);
  425. pListHead->dwEntries = 0;
  426. if (ERROR_SUCCESS !=
  427. RegOpenKeyEx (HKEY_LOCAL_MACHINE, PROVIDERS_KEY, 0, KEY_READ, &hKeyProviders))
  428. {
  429. return;
  430. }
  431. cbData = sizeof (dwNumProviders);
  432. if (ERROR_SUCCESS !=
  433. RegQueryValueEx (hKeyProviders, NUM_PROVIDERS, NULL, NULL, (PBYTE)&dwNumProviders, &cbData) ||
  434. 0 == dwNumProviders)
  435. {
  436. goto CloseKeyAndReturn;
  437. }
  438. pProvider = (PINSTALLED_PROVIDER)ClientAlloc (sizeof (INSTALLED_PROVIDER));
  439. if (NULL == pProvider)
  440. {
  441. goto CloseKeyAndReturn;
  442. }
  443. for (i = 0; i < dwNumProviders; i++)
  444. {
  445. wsprintf (pNumber, TEXT("%d"), i);
  446. cbData = sizeof(pProvider->szName);
  447. if (ERROR_SUCCESS ==
  448. RegQueryValueEx (hKeyProviders, szValueName, NULL, NULL, (PBYTE)pProvider->szName, &cbData))
  449. {
  450. InsertHeadList (&pListHead->Head, &pProvider->Entry);
  451. pListHead->dwEntries ++;
  452. pProvider = (PINSTALLED_PROVIDER)ClientAlloc (sizeof (INSTALLED_PROVIDER));
  453. if (NULL == pProvider)
  454. {
  455. goto CloseKeyAndReturn;
  456. }
  457. }
  458. }
  459. ClientFree (pProvider);
  460. CloseKeyAndReturn:
  461. RegCloseKey (hKeyProviders);
  462. }
  463. /*--------------------------------------------------------------------------*\
  464. Function: FillAddDriverList
  465. Purpose:
  466. \*--------------------------------------------------------------------------*/
  467. BOOL FillAddDriverList( HWND hwndParent, HWND hwndList )
  468. {
  469. UINT uIndex;
  470. UINT uResult;
  471. LPTSTR lpszDrvFile;
  472. HANDLE hFindFile;
  473. WIN32_FIND_DATA ftFileInfo;
  474. TCHAR szFullPath[MAX_PATH+sizeof(gszDriverFiles)/sizeof(TCHAR)];
  475. TCHAR szDrvDescription[CPL_MAX_STRING];
  476. LIST_HEAD InstalledProvidersList;
  477. PINSTALLED_PROVIDER pProvider;
  478. SendMessage( hwndList, WM_SETREDRAW, FALSE, 0 );
  479. SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
  480. // build a list of installed providers,
  481. // so that we don't allow the user to install them again
  482. //------------------------------------------------------
  483. BuildInstalledProviderList (&InstalledProvidersList);
  484. // get full path to windows/system dir
  485. //------------------------------------
  486. uIndex = GetSystemDirectory( szFullPath, MAX_PATH);
  487. if ((0 == uIndex) || (MAX_PATH < uIndex))
  488. {
  489. // Either the function failed,
  490. // or the path is greater than MAX_PATH
  491. uResult = FALSE;
  492. goto done;
  493. }
  494. uIndex = (UINT)lstrlen( szFullPath );
  495. if ((uIndex > 0) && (szFullPath[uIndex-1] != '\\'))
  496. lstrcat( szFullPath, gszDriverFiles ); // add the '\'
  497. else
  498. lstrcat( szFullPath, gszDriverFiles + 1 ); // ignore the '\' (root dir)
  499. // find all the entries in the system dir
  500. //---------------------------------------
  501. hFindFile = FindFirstFile( szFullPath, &ftFileInfo );
  502. uResult = TRUE;
  503. if (hFindFile == INVALID_HANDLE_VALUE)
  504. {
  505. LOG((TL_ERROR, "FindFirstFile failed, 0x%08lx", GetLastError() ));
  506. uResult = FALSE;
  507. }
  508. while ( uResult )
  509. {
  510. // alloc and set the file name to be assocated with each driver
  511. //-------------------------------------------------------------
  512. lpszDrvFile = (LPTSTR)ClientAlloc((lstrlen(ftFileInfo.cFileName)+1)*sizeof(TCHAR));
  513. if (NULL == lpszDrvFile)
  514. {
  515. uResult = FALSE;
  516. goto done;
  517. }
  518. lstrcpy( lpszDrvFile, ftFileInfo.cFileName );
  519. LOG((TL_ERROR, "Examining file %s", lpszDrvFile ));
  520. #ifdef MEMPHIS
  521. if (!lstrcmpi(lpszDrvFile, "tsp3216l.tsp"))
  522. {
  523. ClientFree (lpszDrvFile);
  524. goto next_driver;
  525. }
  526. #endif
  527. // if the provider is already installed, skip it
  528. //----------------------------------------------
  529. for (pProvider = (PINSTALLED_PROVIDER)InstalledProvidersList.Head.Flink, uIndex = 0;
  530. uIndex < InstalledProvidersList.dwEntries;
  531. pProvider = (PINSTALLED_PROVIDER)pProvider->Entry.Flink, uIndex++)
  532. {
  533. if (!lstrcmpi (lpszDrvFile, pProvider->szName))
  534. {
  535. RemoveEntryList (&pProvider->Entry);
  536. InstalledProvidersList.dwEntries --;
  537. ClientFree (pProvider);
  538. ClientFree (lpszDrvFile);
  539. goto next_driver;
  540. }
  541. }
  542. // cbb, should we make a full path???
  543. uResult = GetProviderFileDesc( lpszDrvFile, szDrvDescription, ARRAYSIZE(szDrvDescription) );
  544. if ( uResult != CPL_SUCCESS )
  545. {
  546. LOG((TL_ERROR, "No description for %s. Default to filename.", lpszDrvFile ));
  547. /* Filename will have to suffice */
  548. lstrcpy( szDrvDescription, lpszDrvFile );
  549. uResult = FALSE;
  550. }
  551. else
  552. {
  553. uResult = TRUE;
  554. }
  555. // Verify that provider has install routine
  556. //-----------------------------------------
  557. if (!VerifyProcExists( lpszDrvFile, gszProviderInstall ))
  558. {
  559. LOG((TL_ERROR, "No Install Proc"));
  560. goto next_driver;
  561. }
  562. // slam it into the list box
  563. //--------------------------
  564. uIndex = (UINT)SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szDrvDescription );
  565. if ( uIndex == CB_ERR )
  566. {
  567. uResult = FALSE;
  568. goto done;
  569. }
  570. if ( SendMessage( hwndList, LB_SETITEMDATA, uIndex, (LPARAM)lpszDrvFile ) == CB_ERR )
  571. {
  572. uResult = FALSE;
  573. goto done;
  574. }
  575. next_driver:
  576. uResult = FALSE;
  577. if (FindNextFile( hFindFile, &ftFileInfo ))
  578. {
  579. uResult = TRUE;
  580. }
  581. }
  582. while (InstalledProvidersList.dwEntries > 0)
  583. {
  584. pProvider = (PINSTALLED_PROVIDER)RemoveHeadList (&InstalledProvidersList.Head);
  585. InstalledProvidersList.dwEntries --;
  586. ClientFree (pProvider);
  587. }
  588. uResult = TRUE;
  589. done:
  590. if (0 == SendMessage (hwndList, LB_GETCOUNT, 0, 0))
  591. {
  592. if (0 < LoadString (GetUIInstance(), IDS_NO_PROVIDERS, szDrvDescription, ARRAYSIZE(szDrvDescription)))
  593. {
  594. SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM)szDrvDescription );
  595. }
  596. EnableWindow (GetDlgItem (hwndParent, IDC_ADD), FALSE);
  597. }
  598. else
  599. {
  600. SendMessage( hwndList, LB_SETCURSEL, 0, 0 ); // set focus to the top guy
  601. UpdateDriverDlgButtons( hwndParent );
  602. }
  603. SendMessage( hwndList, WM_SETREDRAW, TRUE, 0 );
  604. return uResult;
  605. }
  606. /*--------------------------------------------------------------------------*\
  607. Function: AddProvider
  608. Purpose: Call lineAddProvider
  609. \*--------------------------------------------------------------------------*/
  610. BOOL AddProvider( HWND hwndParent, HWND hwndList, LPTSTR lpszDriverFile )
  611. {
  612. UINT uIndex;
  613. LONG lResult;
  614. DWORD dwProviderID;
  615. if ( lpszDriverFile == NULL )
  616. {
  617. DBG_ASSERT( hWnd, "Simultaneously NULL pointer & hwnd" );
  618. // get the stuff from the list box
  619. //--------------------------------
  620. uIndex = (UINT)SendMessage( hwndList, LB_GETCURSEL, 0, 0 );
  621. lpszDriverFile = (LPTSTR)SendMessage( hwndList, LB_GETITEMDATA, uIndex, 0 );
  622. if (lpszDriverFile == NULL)
  623. {
  624. return FALSE;
  625. }
  626. }
  627. lResult = lineAddProvider( lpszDriverFile, hwndParent, &dwProviderID );
  628. if (lResult)
  629. {
  630. LOG((TL_ERROR, "Error: lineAddProvider failure %#08lx", lResult ));
  631. return FALSE;
  632. }
  633. return TRUE;
  634. }
  635. BOOL
  636. IsUserAdmin()
  637. /*++
  638. Routine Description:
  639. Determine if current user is a member of the local admin's group
  640. Arguments:
  641. Return Value:
  642. True if member
  643. --*/
  644. {
  645. BOOL foundEntry = FALSE;
  646. HANDLE hToken = NULL;
  647. DWORD dwInfoSize = 0;
  648. PTOKEN_GROUPS ptgGroups = NULL;
  649. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  650. PSID pSid = NULL;
  651. DWORD i;
  652. //
  653. // Get user thread or process token
  654. //
  655. if (!OpenThreadToken(
  656. GetCurrentThread(),
  657. TOKEN_QUERY,
  658. FALSE,
  659. &hToken))
  660. {
  661. if(!OpenProcessToken(
  662. GetCurrentProcess(),
  663. TOKEN_QUERY,
  664. &hToken
  665. ))
  666. {
  667. goto ExitHere;
  668. }
  669. }
  670. //
  671. // Get user group SIDs
  672. //
  673. if (!GetTokenInformation(
  674. hToken,
  675. TokenGroups,
  676. NULL,
  677. 0,
  678. &dwInfoSize
  679. ))
  680. {
  681. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  682. {
  683. goto ExitHere;
  684. }
  685. }
  686. ptgGroups = (PTOKEN_GROUPS) ClientAlloc (dwInfoSize);
  687. if (ptgGroups == NULL)
  688. {
  689. goto ExitHere;
  690. }
  691. if (!GetTokenInformation(
  692. hToken,
  693. TokenGroups,
  694. ptgGroups,
  695. dwInfoSize,
  696. &dwInfoSize
  697. ))
  698. {
  699. goto ExitHere;
  700. }
  701. //
  702. // Get the local admin group SID
  703. //
  704. if(!AllocateAndInitializeSid(
  705. &sia,
  706. 2,
  707. SECURITY_BUILTIN_DOMAIN_RID,
  708. DOMAIN_ALIAS_RID_ADMINS,
  709. 0, 0, 0, 0, 0, 0,
  710. &pSid
  711. ))
  712. {
  713. goto ExitHere;
  714. }
  715. //
  716. // Compare to see if the user is in admin group
  717. //
  718. for (i = 0; i < ptgGroups->GroupCount; ++i)
  719. {
  720. if (EqualSid (ptgGroups->Groups[i].Sid, pSid))
  721. {
  722. break;
  723. }
  724. }
  725. if (i < ptgGroups->GroupCount)
  726. {
  727. foundEntry = TRUE;
  728. }
  729. ExitHere:
  730. if (pSid)
  731. {
  732. FreeSid (pSid);
  733. }
  734. if (ptgGroups)
  735. {
  736. ClientFree (ptgGroups);
  737. }
  738. if (hToken)
  739. {
  740. CloseHandle (hToken);
  741. }
  742. return foundEntry;
  743. }
  744. VOID UpdateDriverDlgButtons( HWND hwnd )
  745. {
  746. //
  747. // Enable/disable the Remove & Config buttons as appropriate
  748. //
  749. UINT uResult;
  750. LPTSTR lpszProviderFilename;
  751. DWORD dwProviderID;
  752. BOOL bAdmin = IsUserAdmin ();
  753. uResult = (UINT) SendDlgItemMessage(
  754. hwnd,
  755. IDC_LIST,
  756. LB_GETCURSEL,
  757. 0,
  758. 0
  759. );
  760. dwProviderID = (DWORD) SendDlgItemMessage(
  761. hwnd,
  762. IDC_LIST,
  763. LB_GETITEMDATA,
  764. uResult, 0
  765. );
  766. lpszProviderFilename = ProviderIDToFilename (dwProviderID);
  767. EnableWindow(
  768. GetDlgItem (hwnd, IDC_ADD),
  769. bAdmin
  770. );
  771. EnableWindow(
  772. GetDlgItem (hwnd, IDC_REMOVE),
  773. bAdmin &&
  774. (lpszProviderFilename != NULL) &&
  775. VerifyProcExists (lpszProviderFilename, gszProviderRemove)
  776. );
  777. EnableWindow(
  778. GetDlgItem( hwnd, IDC_EDIT),
  779. bAdmin &&
  780. (lpszProviderFilename != NULL) &&
  781. VerifyProcExists (lpszProviderFilename, gszProviderSetup)
  782. );
  783. }
  784. /*--------------------------------------------------------------------------*\
  785. Function: AddDriver_DialogProc
  786. Purpose:
  787. \*--------------------------------------------------------------------------*/
  788. INT_PTR AddDriver_DialogProc( HWND hWnd, UINT wMessage, WPARAM wParam, LPARAM lParam )
  789. {
  790. switch( wMessage )
  791. {
  792. case WM_HELP:
  793. // Process clicks on controls after Context Help mode selected
  794. WinHelp ((HWND)((LPHELPINFO)lParam)->hItemHandle, gszHelpFile, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) a114HelpIDs);
  795. break;
  796. case WM_CONTEXTMENU:
  797. // Process right-clicks on controls
  798. WinHelp ((HWND) wParam, gszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID) a114HelpIDs);
  799. break;
  800. case WM_INITDIALOG:
  801. // initalize all the fields
  802. //-------------------------
  803. if ( !FillAddDriverList(hWnd, GetDlgItem(hWnd, IDC_DRIVER_LIST)) )
  804. {
  805. EndDialog( hWnd, IDCANCEL );
  806. return TRUE;
  807. }
  808. if ( SendDlgItemMessage( hWnd, IDC_DRIVER_LIST, LB_GETCOUNT, 0, 0 ) <= 0 )
  809. EnableWindow( GetDlgItem( hWnd, IDC_ADD ), FALSE );
  810. return TRUE;
  811. case WM_COMMAND:
  812. // do some work with the buttons
  813. //------------------------------
  814. switch ( GET_WM_COMMAND_ID(wParam, lParam) )
  815. {
  816. case IDC_DRIVER_LIST:
  817. // do the list stuff
  818. //------------------
  819. if ((GET_WM_COMMAND_CMD( wParam, lParam ) != LBN_DBLCLK) || (SendDlgItemMessage( hWnd, IDC_DRIVER_LIST, LB_GETCOUNT, 0, 0 ) <= 0 ))
  820. break; // done
  821. // fall through, threat the double click like an add message
  822. case IDC_ADD:
  823. // add a new driver
  824. //-----------------
  825. if ( !AddProvider(hWnd, GetDlgItem(hWnd, IDC_DRIVER_LIST), NULL) )
  826. {
  827. wParam = IDCANCEL;
  828. }
  829. else
  830. {
  831. wParam = IDOK;
  832. }
  833. // fall through, exit the dialog
  834. case IDOK:
  835. case IDCANCEL:
  836. {
  837. UINT uIndex, uCount;
  838. LPTSTR lpszDriverFile;
  839. HWND hwndList = GetDlgItem(hWnd, IDC_DRIVER_LIST);
  840. uCount = (UINT)SendMessage( hwndList, LB_GETCOUNT, 0, 0 );
  841. for (uIndex = 0; uIndex < uCount; uIndex++)
  842. {
  843. lpszDriverFile = (LPTSTR)SendMessage( hwndList, LB_GETITEMDATA, uIndex, 0 );
  844. if (NULL != lpszDriverFile)
  845. {
  846. ClientFree (lpszDriverFile);
  847. }
  848. }
  849. EndDialog( hWnd, wParam );
  850. break;
  851. }
  852. }
  853. return TRUE;
  854. }
  855. return FALSE;
  856. }
  857. //---------------------------------------------------------------------------
  858. //---------------------------------------------------------------------------
  859. BOOL RefreshProviderList()
  860. {
  861. LONG lResult;
  862. if (!glpProviderList)
  863. {
  864. // Initialize data structure
  865. glpProviderList = (LPLINEPROVIDERLIST)GlobalAllocPtr(GPTR, INITIAL_PROVIDER_LIST_SIZE);
  866. }
  867. if (!glpProviderList)
  868. {
  869. LOG((TL_ERROR, " RefreshProviderList - glpProviderList is NULL - returning CPL_ERR_MEMORY"));
  870. return FALSE;
  871. }
  872. glpProviderList->dwTotalSize = INITIAL_PROVIDER_LIST_SIZE;
  873. lResult = lineGetProviderList( TAPI_VERSION, glpProviderList );
  874. if (lResult)
  875. {
  876. LOG((TL_ERROR, "Error: lineGetProviderList failure %#08lx", lResult ));
  877. return FALSE;
  878. }
  879. while (glpProviderList->dwNeededSize > glpProviderList->dwTotalSize)
  880. {
  881. // Expand data structure as necessary
  882. LOG((TL_ERROR, " RefreshProviderList - expanding glpProviderList."));
  883. LPLINEPROVIDERLIST lpTemp =
  884. (LPLINEPROVIDERLIST)GlobalReAllocPtr( glpProviderList,
  885. (size_t)(glpProviderList->dwNeededSize),
  886. GPTR);
  887. if (!lpTemp)
  888. return FALSE;
  889. glpProviderList = lpTemp;
  890. glpProviderList->dwTotalSize = glpProviderList->dwNeededSize;
  891. lResult = lineGetProviderList( TAPI_VERSION, glpProviderList );
  892. if (lResult)
  893. {
  894. LOG((TL_ERROR, "Error: lineGetProviderList failure %#08lx", lResult ));
  895. return FALSE;
  896. }
  897. }
  898. LOG((TL_ERROR, "%d providers", glpProviderList->dwNumProviders ));
  899. return TRUE;
  900. }
  901. LPTSTR ProviderIDToFilename( DWORD dwProviderID )
  902. {
  903. UINT uIndex;
  904. LPLINEPROVIDERENTRY lpProviderEntry;
  905. // loop through the provider list
  906. //-------------------------------
  907. lpProviderEntry = (LPLINEPROVIDERENTRY)((LPBYTE)glpProviderList +
  908. glpProviderList->dwProviderListOffset);
  909. for ( uIndex = 0; uIndex < glpProviderList->dwNumProviders; uIndex++ )
  910. {
  911. if (lpProviderEntry[uIndex].dwPermanentProviderID == dwProviderID)
  912. {
  913. // Get an entry to put in the list box
  914. //------------------------------------
  915. return (LPTSTR)((LPBYTE)glpProviderList +
  916. lpProviderEntry[uIndex].dwProviderFilenameOffset);
  917. }
  918. }
  919. LOG((TL_ERROR, "Provider ID %d not found in list", dwProviderID ));
  920. return NULL;
  921. }