Leaked source code of windows server 2003
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.

1810 lines
48 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Utils.cpp
  6. * Content: Serial service provider utility functions
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 11/25/98 jtk Created
  13. ***************************************************************************/
  14. #include "dnmdmi.h"
  15. //**********************************************************************
  16. // Constant definitions
  17. //**********************************************************************
  18. #define DEFAULT_WIN9X_THREADS 1
  19. static const WCHAR g_RegistryBase[] = L"SOFTWARE\\Microsoft\\DirectPlay8";
  20. static const WCHAR g_RegistryKeyThreadCount[] = L"ThreadCount";
  21. //
  22. // default buffer size for getting TAPI device caps
  23. //
  24. static const DWORD g_dwDefaultTAPIDevCapsSize = 512;
  25. //
  26. // TAPI module name
  27. //
  28. static const TCHAR g_TAPIModuleName[] = TEXT("TAPI32.DLL");
  29. //**********************************************************************
  30. // Macro definitions
  31. //**********************************************************************
  32. //**********************************************************************
  33. // Structure definitions
  34. //**********************************************************************
  35. //**********************************************************************
  36. // Variable definitions
  37. //**********************************************************************
  38. //
  39. // global variables that are unique for the process
  40. //
  41. #ifndef DPNBUILD_ONLYONETHREAD
  42. static DNCRITICAL_SECTION g_InterfaceGlobalsLock;
  43. #endif // !DPNBUILD_ONLYONETHREAD
  44. static volatile LONG g_iThreadPoolRefCount = 0;
  45. static CModemThreadPool *g_pThreadPool = NULL;
  46. static volatile LONG g_iTAPIRefCount = 0;
  47. static HMODULE g_hTAPIModule = NULL;
  48. //**********************************************************************
  49. // Function prototypes
  50. //**********************************************************************
  51. static void ReadSettingsFromRegistry( void );
  52. static BYTE GetAddressEncryptionKey( void );
  53. //**********************************************************************
  54. // Function definitions
  55. //**********************************************************************
  56. //**********************************************************************
  57. // ------------------------------
  58. // ModemInitProcessGlobals - initialize the global items needed for the SP to operate
  59. //
  60. // Entry: Nothing
  61. //
  62. // Exit: Boolean indicating success
  63. // TRUE = success
  64. // FALSE = failure
  65. // ------------------------------
  66. #undef DPF_MODNAME
  67. #define DPF_MODNAME "ModemInitProcessGlobals"
  68. BOOL ModemInitProcessGlobals( void )
  69. {
  70. BOOL fReturn;
  71. BOOL fCriticalSectionInitialized;
  72. DWORD iIndex;
  73. //
  74. // initialize
  75. //
  76. fReturn = TRUE;
  77. fCriticalSectionInitialized = FALSE;
  78. #ifdef DBG
  79. g_blDPNModemCritSecsHeld.Initialize();
  80. #endif // DBG
  81. ReadSettingsFromRegistry();
  82. if ( DNInitializeCriticalSection( &g_InterfaceGlobalsLock ) == FALSE )
  83. {
  84. fReturn = FALSE;
  85. goto Failure;
  86. }
  87. DebugSetCriticalSectionGroup( &g_InterfaceGlobalsLock, &g_blDPNModemCritSecsHeld ); // separate dpnmodem CSes from the rest of DPlay's CSes
  88. fCriticalSectionInitialized = TRUE;
  89. if ( ModemInitializePools() == FALSE )
  90. {
  91. fReturn = FALSE;
  92. goto Failure;
  93. }
  94. // Load localized string from resources //////////////////////////////////////////////////////////////
  95. for (iIndex = 0; iIndex < g_dwBaudRateCount; iIndex++)
  96. {
  97. if (!LoadString(g_hModemDLLInstance, IDS_BAUD_9600 + iIndex, g_BaudRate[iIndex].szLocalizedKey, 256))
  98. {
  99. fReturn = FALSE;
  100. goto Failure;
  101. }
  102. }
  103. for (iIndex = 0; iIndex < g_dwStopBitsCount; iIndex++)
  104. {
  105. if (!LoadString(g_hModemDLLInstance, IDS_STOPBITS_ONE + iIndex, g_StopBits[iIndex].szLocalizedKey, 256))
  106. {
  107. fReturn = FALSE;
  108. goto Failure;
  109. }
  110. }
  111. for (iIndex = 0; iIndex < g_dwParityCount; iIndex++)
  112. {
  113. if (!LoadString(g_hModemDLLInstance, IDS_PARITY_EVEN + iIndex, g_Parity[iIndex].szLocalizedKey, 256))
  114. {
  115. fReturn = FALSE;
  116. goto Failure;
  117. }
  118. }
  119. for (iIndex = 0; iIndex < g_dwFlowControlCount; iIndex++)
  120. {
  121. if (!LoadString(g_hModemDLLInstance, IDS_FLOW_NONE + iIndex, g_FlowControl[iIndex].szLocalizedKey, 256))
  122. {
  123. fReturn = FALSE;
  124. goto Failure;
  125. }
  126. }
  127. DNASSERT( g_pThreadPool == NULL );
  128. Exit:
  129. return fReturn;
  130. Failure:
  131. ModemDeinitializePools();
  132. if ( fCriticalSectionInitialized != FALSE )
  133. {
  134. DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
  135. fCriticalSectionInitialized = FALSE;
  136. }
  137. goto Exit;
  138. }
  139. //**********************************************************************
  140. //**********************************************************************
  141. // ------------------------------
  142. // ModemDeinitProcessGlobals - deinitialize the global items
  143. //
  144. // Entry: Nothing
  145. //
  146. // Exit: Nothing
  147. // ------------------------------
  148. #undef DPF_MODNAME
  149. #define DPF_MODNAME "ModemDeinitProcessGlobals"
  150. void ModemDeinitProcessGlobals( void )
  151. {
  152. DNASSERT( g_pThreadPool == NULL );
  153. DNASSERT( g_iThreadPoolRefCount == 0 );
  154. ModemDeinitializePools();
  155. DNDeleteCriticalSection( &g_InterfaceGlobalsLock );
  156. }
  157. //**********************************************************************
  158. //**********************************************************************
  159. // ------------------------------
  160. // InitializeInterfaceGlobals - perform global initialization for an interface.
  161. // This entails starting the thread pool and RSIP (if applicable).
  162. //
  163. // Entry: Pointer to SPData
  164. //
  165. // Exit: Error code
  166. // ------------------------------
  167. #undef DPF_MODNAME
  168. #define DPF_MODNAME "InitializeInterfaceGlobals"
  169. HRESULT InitializeInterfaceGlobals( CModemSPData *const pSPData )
  170. {
  171. HRESULT hr;
  172. DNASSERT( pSPData != NULL );
  173. //
  174. // initialize
  175. //
  176. hr = DPN_OK;
  177. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  178. if ( g_pThreadPool == NULL )
  179. {
  180. DNASSERT( g_iThreadPoolRefCount == 0 );
  181. g_pThreadPool = (CModemThreadPool*)g_ModemThreadPoolPool.Get();
  182. if ( g_pThreadPool == NULL )
  183. {
  184. hr = DPNERR_OUTOFMEMORY;
  185. goto Failure;
  186. }
  187. else
  188. {
  189. if (!g_pThreadPool->Initialize())
  190. {
  191. hr = DPNERR_OUTOFMEMORY;
  192. g_ModemThreadPoolPool.Release(g_pThreadPool);
  193. g_pThreadPool = NULL;
  194. goto Failure;
  195. }
  196. g_iThreadPoolRefCount++;
  197. }
  198. }
  199. else
  200. {
  201. DNASSERT( g_iThreadPoolRefCount != 0 );
  202. g_iThreadPoolRefCount++;
  203. g_pThreadPool->AddRef();
  204. }
  205. Exit:
  206. pSPData->SetThreadPool( g_pThreadPool );
  207. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  208. return hr;
  209. Failure:
  210. goto Exit;
  211. }
  212. //**********************************************************************
  213. //**********************************************************************
  214. // ------------------------------
  215. // DeinitializeInterfaceGlobals - deinitialize thread pool and Rsip
  216. //
  217. // Entry: Pointer to service provider
  218. //
  219. // Exit: Nothing
  220. // ------------------------------
  221. #undef DPF_MODNAME
  222. #define DPF_MODNAME "DeinitializeInterfaceGlobals"
  223. void DeinitializeInterfaceGlobals( CModemSPData *const pSPData )
  224. {
  225. CModemThreadPool *pThreadPool;
  226. BOOL fCleanUp;
  227. DNASSERT( pSPData != NULL );
  228. //
  229. // initialize
  230. //
  231. pThreadPool = NULL;
  232. fCleanUp = FALSE;
  233. //
  234. // Process as little as possible inside the lock. If any of the items
  235. // need to be released, pointers to them will be set.
  236. //
  237. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  238. DNASSERT( g_pThreadPool != NULL );
  239. DNASSERT( g_iThreadPoolRefCount != 0 );
  240. DNASSERT( g_pThreadPool == pSPData->GetThreadPool() );
  241. pThreadPool = pSPData->GetThreadPool();
  242. //
  243. // remove thread pool reference
  244. //
  245. g_iThreadPoolRefCount--;
  246. if ( g_iThreadPoolRefCount == 0 )
  247. {
  248. g_pThreadPool = NULL;
  249. fCleanUp = TRUE;
  250. }
  251. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  252. //
  253. // now that we're outside of the lock, clean up the thread pool if this
  254. // was the last reference to it
  255. //
  256. DNASSERT( pThreadPool != NULL );
  257. if ( fCleanUp != FALSE )
  258. {
  259. pThreadPool->Deinitialize();
  260. }
  261. }
  262. //**********************************************************************
  263. //**********************************************************************
  264. // ------------------------------
  265. // LoadTAPILibrary - load TAPI library
  266. //
  267. // Entry: Nothing
  268. //
  269. // Exit: Error code
  270. // ------------------------------
  271. #undef DPF_MODNAME
  272. #define DPF_MODNAME "LoadTAPILibrary"
  273. HRESULT LoadTAPILibrary( void )
  274. {
  275. HRESULT hr;
  276. //
  277. // initialize
  278. //
  279. hr = DPN_OK;
  280. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  281. if ( g_iTAPIRefCount != 0 )
  282. {
  283. DNASSERT( p_lineAnswer != NULL );
  284. DNASSERT( p_lineClose != NULL );
  285. DNASSERT( p_lineConfigDialog != NULL );
  286. DNASSERT( p_lineDeallocateCall != NULL );
  287. DNASSERT( p_lineDrop != NULL );
  288. DNASSERT( p_lineGetDevCaps != NULL );
  289. DNASSERT( p_lineGetID != NULL );
  290. DNASSERT( p_lineGetMessage != NULL );
  291. DNASSERT( p_lineInitializeEx != NULL );
  292. DNASSERT( p_lineMakeCall != NULL );
  293. DNASSERT( p_lineNegotiateAPIVersion != NULL );
  294. DNASSERT( p_lineOpen != NULL );
  295. DNASSERT( p_lineShutdown != NULL );
  296. }
  297. else
  298. {
  299. DNASSERT( g_hTAPIModule == NULL );
  300. DNASSERT( p_lineAnswer == NULL );
  301. DNASSERT( p_lineClose == NULL );
  302. DNASSERT( p_lineConfigDialog == NULL );
  303. DNASSERT( p_lineDeallocateCall == NULL );
  304. DNASSERT( p_lineDrop == NULL );
  305. DNASSERT( p_lineGetDevCaps == NULL );
  306. DNASSERT( p_lineGetID == NULL );
  307. DNASSERT( p_lineGetMessage == NULL );
  308. DNASSERT( p_lineInitializeEx == NULL );
  309. DNASSERT( p_lineMakeCall == NULL );
  310. DNASSERT( p_lineNegotiateAPIVersion == NULL );
  311. DNASSERT( p_lineOpen == NULL );
  312. DNASSERT( p_lineShutdown == NULL );
  313. g_hTAPIModule = LoadLibrary( g_TAPIModuleName );
  314. if ( g_hTAPIModule == NULL )
  315. {
  316. DWORD dwError;
  317. dwError = GetLastError();
  318. DPFX(DPFPREP, 0, "Failed to load TAPI!" );
  319. DisplayErrorCode( 0, dwError );
  320. goto Failure;
  321. }
  322. p_lineAnswer = reinterpret_cast<TAPI_lineAnswer*>( GetProcAddress( g_hTAPIModule, "lineAnswer" ) );
  323. if ( p_lineAnswer == NULL )
  324. {
  325. DWORD dwError;
  326. dwError = GetLastError();
  327. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineAnswer" );
  328. DisplayErrorCode( 0, dwError );
  329. goto Failure;
  330. }
  331. p_lineClose = reinterpret_cast<TAPI_lineClose*>( GetProcAddress( g_hTAPIModule, "lineClose" ) );
  332. if ( p_lineClose == NULL )
  333. {
  334. DWORD dwError;
  335. dwError = GetLastError();
  336. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineClose" );
  337. DisplayErrorCode( 0, dwError );
  338. goto Failure;
  339. }
  340. p_lineConfigDialog = reinterpret_cast<TAPI_lineConfigDialog*>( GetProcAddress( g_hTAPIModule, "lineConfigDialog" TAPI_APPEND_LETTER ) );
  341. if ( p_lineConfigDialog == NULL )
  342. {
  343. DWORD dwError;
  344. dwError = GetLastError();
  345. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineConfigDialog" );
  346. DisplayErrorCode( 0, dwError );
  347. goto Failure;
  348. }
  349. p_lineDeallocateCall = reinterpret_cast<TAPI_lineDeallocateCall*>( GetProcAddress( g_hTAPIModule, "lineDeallocateCall" ) );
  350. if ( p_lineDeallocateCall == NULL )
  351. {
  352. DWORD dwError;
  353. dwError = GetLastError();
  354. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineDeallocateCall" );
  355. DisplayErrorCode( 0, dwError );
  356. goto Failure;
  357. }
  358. p_lineDrop = reinterpret_cast<TAPI_lineDrop*>( GetProcAddress( g_hTAPIModule, "lineDrop" ) );
  359. if ( p_lineDrop == NULL )
  360. {
  361. DWORD dwError;
  362. dwError = GetLastError();
  363. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineDrop" );
  364. DisplayErrorCode( 0, dwError );
  365. goto Failure;
  366. }
  367. p_lineGetDevCaps = reinterpret_cast<TAPI_lineGetDevCaps*>( GetProcAddress( g_hTAPIModule, "lineGetDevCaps" TAPI_APPEND_LETTER ) );
  368. if ( p_lineGetDevCaps == NULL )
  369. {
  370. DWORD dwError;
  371. dwError = GetLastError();
  372. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineGetDevCaps" );
  373. DisplayErrorCode( 0, dwError );
  374. goto Failure;
  375. }
  376. p_lineGetID = reinterpret_cast<TAPI_lineGetID*>( GetProcAddress( g_hTAPIModule, "lineGetID" TAPI_APPEND_LETTER ) );
  377. if ( p_lineGetID == NULL )
  378. {
  379. DWORD dwError;
  380. dwError = GetLastError();
  381. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineGetID" );
  382. DisplayErrorCode( 0, dwError );
  383. goto Failure;
  384. }
  385. p_lineGetMessage = reinterpret_cast<TAPI_lineGetMessage*>( GetProcAddress( g_hTAPIModule, "lineGetMessage" ) );
  386. if ( p_lineGetMessage == NULL )
  387. {
  388. DWORD dwError;
  389. dwError = GetLastError();
  390. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineGetMessage" );
  391. DisplayErrorCode( 0, dwError );
  392. goto Failure;
  393. }
  394. p_lineInitializeEx = reinterpret_cast<TAPI_lineInitializeEx*>( GetProcAddress( g_hTAPIModule, "lineInitializeEx" TAPI_APPEND_LETTER ) );
  395. if ( p_lineInitializeEx == NULL )
  396. {
  397. DWORD dwError;
  398. dwError = GetLastError();
  399. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineInitializeEx" );
  400. DisplayErrorCode( 0, dwError );
  401. goto Failure;
  402. }
  403. p_lineMakeCall = reinterpret_cast<TAPI_lineMakeCall*>( GetProcAddress( g_hTAPIModule, "lineMakeCall" TAPI_APPEND_LETTER ) );
  404. if ( p_lineMakeCall == NULL )
  405. {
  406. DWORD dwError;
  407. dwError = GetLastError();
  408. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineMakeCall" );
  409. DisplayErrorCode( 0, dwError );
  410. goto Failure;
  411. }
  412. p_lineNegotiateAPIVersion = reinterpret_cast<TAPI_lineNegotiateAPIVersion*>( GetProcAddress( g_hTAPIModule, "lineNegotiateAPIVersion" ) );
  413. if ( p_lineNegotiateAPIVersion == NULL )
  414. {
  415. DWORD dwError;
  416. dwError = GetLastError();
  417. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineNegotiateAPIVersion" );
  418. DisplayErrorCode( 0, dwError );
  419. goto Failure;
  420. }
  421. p_lineOpen = reinterpret_cast<TAPI_lineOpen*>( GetProcAddress( g_hTAPIModule, "lineOpen" TAPI_APPEND_LETTER ) );
  422. if ( p_lineOpen == NULL )
  423. {
  424. DWORD dwError;
  425. dwError = GetLastError();
  426. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineOpen" );
  427. DisplayErrorCode( 0, dwError );
  428. goto Failure;
  429. }
  430. p_lineShutdown = reinterpret_cast<TAPI_lineShutdown*>( GetProcAddress( g_hTAPIModule, "lineShutdown" ) );
  431. if ( p_lineShutdown == NULL )
  432. {
  433. DWORD dwError;
  434. dwError = GetLastError();
  435. DPFX(DPFPREP, 0, "Failed to GetProcAddress for lineShutdown" );
  436. DisplayErrorCode( 0, dwError );
  437. goto Failure;
  438. }
  439. }
  440. DNASSERT( g_iTAPIRefCount != -1 );
  441. g_iTAPIRefCount++;
  442. Exit:
  443. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  444. return hr;
  445. Failure:
  446. hr = DPNERR_OUTOFMEMORY;
  447. p_lineAnswer = NULL;
  448. p_lineClose = NULL;
  449. p_lineConfigDialog = NULL;
  450. p_lineDeallocateCall = NULL;
  451. p_lineDrop = NULL;
  452. p_lineGetDevCaps = NULL;
  453. p_lineGetID = NULL;
  454. p_lineGetMessage = NULL;
  455. p_lineInitializeEx = NULL;
  456. p_lineMakeCall = NULL;
  457. p_lineNegotiateAPIVersion = NULL;
  458. p_lineOpen = NULL;
  459. p_lineShutdown = NULL;
  460. if ( g_hTAPIModule != NULL )
  461. {
  462. if ( FreeLibrary( g_hTAPIModule ) == FALSE )
  463. {
  464. DWORD dwError;
  465. dwError = GetLastError();
  466. DPFX(DPFPREP, 0, "Problem unloading TAPI module on failed load!" );
  467. DisplayErrorCode( 0, dwError );
  468. }
  469. g_hTAPIModule = NULL;
  470. }
  471. goto Exit;
  472. }
  473. //**********************************************************************
  474. //**********************************************************************
  475. // ------------------------------
  476. // UnloadTAPILibrary - unload TAPI library
  477. //
  478. // Entry: Nothing
  479. //
  480. // Exit: Nothing
  481. // ------------------------------
  482. #undef DPF_MODNAME
  483. #define DPF_MODNAME "UnloadTAPILibrary"
  484. void UnloadTAPILibrary( void )
  485. {
  486. DNEnterCriticalSection( &g_InterfaceGlobalsLock );
  487. DNASSERT( g_iTAPIRefCount != 0 );
  488. g_iTAPIRefCount--;
  489. if ( g_iTAPIRefCount == 0 )
  490. {
  491. DNASSERT( g_hTAPIModule != NULL );
  492. DNASSERT( p_lineAnswer != NULL );
  493. DNASSERT( p_lineClose != NULL );
  494. DNASSERT( p_lineConfigDialog != NULL );
  495. DNASSERT( p_lineDeallocateCall != NULL );
  496. DNASSERT( p_lineDrop != NULL );
  497. DNASSERT( p_lineGetDevCaps != NULL );
  498. DNASSERT( p_lineGetID != NULL );
  499. DNASSERT( p_lineGetMessage != NULL );
  500. DNASSERT( p_lineInitializeEx != NULL );
  501. DNASSERT( p_lineMakeCall != NULL );
  502. DNASSERT( p_lineNegotiateAPIVersion != NULL );
  503. DNASSERT( p_lineOpen != NULL );
  504. DNASSERT( p_lineShutdown != NULL );
  505. if ( FreeLibrary( g_hTAPIModule ) == FALSE )
  506. {
  507. DWORD dwError;
  508. dwError = GetLastError();
  509. DPFX(DPFPREP, 0, "Problem unloading TAPI module on failed load!" );
  510. DisplayErrorCode( 0, dwError );
  511. }
  512. g_hTAPIModule = NULL;
  513. p_lineAnswer = NULL;
  514. p_lineClose = NULL;
  515. p_lineConfigDialog = NULL;
  516. p_lineDeallocateCall = NULL;
  517. p_lineDrop = NULL;
  518. p_lineGetDevCaps = NULL;
  519. p_lineGetID = NULL;
  520. p_lineGetMessage = NULL;
  521. p_lineInitializeEx = NULL;
  522. p_lineMakeCall = NULL;
  523. p_lineNegotiateAPIVersion = NULL;
  524. p_lineOpen = NULL;
  525. p_lineShutdown = NULL;
  526. }
  527. DNLeaveCriticalSection( &g_InterfaceGlobalsLock );
  528. }
  529. //**********************************************************************
  530. //**********************************************************************
  531. // ------------------------------
  532. // IsSerialGUID - is a GUID a serial GUID?
  533. //
  534. // Entry: Pointer to GUID
  535. //
  536. // Exit: Boolean inficating whether the GUID is a serial GUID
  537. // ------------------------------
  538. #undef DPF_MODNAME
  539. #define DPF_MODNAME "IsSerialGUID"
  540. BOOL IsSerialGUID( const GUID *const pGuid )
  541. {
  542. BOOL fReturn;
  543. DNASSERT( pGuid != NULL );
  544. //
  545. // assume guid is serial
  546. //
  547. fReturn = TRUE;
  548. //
  549. // is this modem or serial?
  550. //
  551. if ( IsEqualCLSID( *pGuid, CLSID_DP8SP_MODEM ) == FALSE )
  552. {
  553. if ( IsEqualCLSID( *pGuid, CLSID_DP8SP_SERIAL ) == FALSE )
  554. {
  555. // not a known GUID
  556. fReturn = FALSE;
  557. }
  558. }
  559. return fReturn;
  560. }
  561. //**********************************************************************
  562. //**********************************************************************
  563. // ------------------------------
  564. // StringToValue - convert a string to an enumerated value
  565. //
  566. // Entry: Pointer to string
  567. // Length of string
  568. // Pointer to destination enum
  569. // Pointer to string/enum pairs
  570. // Count of string/enum pairs
  571. //
  572. // Exit: Boolean indicating success
  573. // TRUE = value found
  574. // FALSE = value not found
  575. // ------------------------------
  576. #undef DPF_MODNAME
  577. #define DPF_MODNAME "StringToValue"
  578. BOOL StringToValue( const WCHAR *const pString,
  579. const DWORD dwStringLength,
  580. VALUE_ENUM_TYPE *const pEnum,
  581. const STRING_BLOCK *const pStringBlock,
  582. const DWORD dwPairCount )
  583. {
  584. BOOL fFound;
  585. DWORD dwCount;
  586. // initialize
  587. fFound = FALSE;
  588. dwCount = dwPairCount;
  589. // loop through list
  590. while ( ( dwCount > 0 ) && ( fFound == FALSE ) )
  591. {
  592. // make array index
  593. dwCount--;
  594. // are the strings the same length?
  595. if ( pStringBlock[ dwCount ].dwWCHARKeyLength == dwStringLength )
  596. {
  597. // is this what we were looking for?
  598. if ( memcmp( pString, pStringBlock[ dwCount ].pWCHARKey, dwStringLength ) == 0 )
  599. {
  600. // found it
  601. fFound = TRUE;
  602. *pEnum = pStringBlock[ dwCount ].dwEnumValue;
  603. }
  604. }
  605. }
  606. return fFound;
  607. }
  608. //**********************************************************************
  609. //**********************************************************************
  610. // ------------------------------
  611. // ValueToString - split extra info into components
  612. //
  613. // Entry: Pointer to pointer to string
  614. // Length of string
  615. // Enumerated value
  616. // Pointer to string-enum pairs
  617. // Count of string-enum pairs
  618. //
  619. // Exit: Boolean indicating success
  620. // TRUE = value was converted
  621. // FALSE = value was not converted
  622. // ------------------------------
  623. #undef DPF_MODNAME
  624. #define DPF_MODNAME "ValueToString"
  625. BOOL ValueToString( const WCHAR **const ppString,
  626. DWORD *const pdwStringLength,
  627. const DWORD Enum,
  628. const STRING_BLOCK *const pStringBlock,
  629. const DWORD dwPairCount )
  630. {
  631. BOOL fFound;
  632. DWORD dwCount;
  633. // initialize
  634. fFound = FALSE;
  635. dwCount = dwPairCount;
  636. // loop through strings
  637. while ( ( dwCount > 0 ) && ( fFound == FALSE ))
  638. {
  639. // make array index
  640. dwCount--;
  641. // is this the enum?
  642. if ( pStringBlock[ dwCount ].dwEnumValue == Enum )
  643. {
  644. // note that we found the value
  645. *ppString = pStringBlock[ dwCount ].pWCHARKey;
  646. *pdwStringLength = pStringBlock[ dwCount ].dwWCHARKeyLength;
  647. fFound = TRUE;
  648. }
  649. }
  650. return fFound;
  651. }
  652. //**********************************************************************
  653. //**********************************************************************
  654. // ------------------------------
  655. // ReadSettingsFromRegistry - read custom registry keys
  656. //
  657. // Entry: Nothing
  658. //
  659. // Exit: Nothing
  660. // ------------------------------
  661. #undef DPF_MODNAME
  662. #define DPF_MODNAME "ReadSettingsFromRegistry"
  663. static void ReadSettingsFromRegistry( void )
  664. {
  665. CRegistry RegObject;
  666. if ( RegObject.Open( HKEY_LOCAL_MACHINE, g_RegistryBase ) != FALSE )
  667. {
  668. DWORD dwRegValue;
  669. //
  670. // read default threads
  671. //
  672. if ( RegObject.ReadDWORD( g_RegistryKeyThreadCount, &dwRegValue ) != FALSE )
  673. {
  674. g_iThreadCount = dwRegValue;
  675. }
  676. //
  677. // if thread count is zero, use the 'default' for the system
  678. //
  679. if ( g_iThreadCount == 0 )
  680. {
  681. #ifdef WIN95
  682. g_iThreadCount = DEFAULT_WIN9X_THREADS;
  683. #else // WINNT
  684. SYSTEM_INFO SystemInfo;
  685. //
  686. // as suggested by 'Multithreading Applications in Win32' book:
  687. // dwNTThreadCount = ( ( processors * 2 ) + 2 )
  688. //
  689. memset( &SystemInfo, 0x00, sizeof( SystemInfo ) );
  690. GetSystemInfo( &SystemInfo );
  691. g_iThreadCount = ( ( 2 * SystemInfo.dwNumberOfProcessors ) + 2 );
  692. #endif // WIN95
  693. }
  694. RegObject.Close();
  695. }
  696. }
  697. //**********************************************************************
  698. //**********************************************************************
  699. // ------------------------------
  700. // GetAddressEncryptionKey - get a key used to encrypt device GUIDs
  701. //
  702. // Entry: Nothing
  703. //
  704. // Exit: Byte key
  705. // ------------------------------
  706. #undef DPF_MODNAME
  707. #define DPF_MODNAME "GetAddressEncryptionKey"
  708. static BYTE GetAddressEncryptionKey( void )
  709. {
  710. BYTE bReturn;
  711. UINT_PTR ProcessID;
  712. bReturn = 0;
  713. ProcessID = GetCurrentProcessId();
  714. while ( ProcessID > 0 )
  715. {
  716. bReturn ^= ProcessID;
  717. ProcessID >>= ( sizeof( bReturn ) * 8 );
  718. }
  719. return bReturn;
  720. }
  721. //**********************************************************************
  722. //**********************************************************************
  723. // ------------------------------
  724. // DeviceIDToGuid - convert a device ID to an adapter GUID
  725. //
  726. // Entry: Reference of Guid to fill
  727. // Device ID
  728. //
  729. // Exit: Nothing
  730. // ------------------------------
  731. #undef DPF_MODNAME
  732. #define DPF_MODNAME "DeviceIDToGuid"
  733. void DeviceIDToGuid( GUID *const pGuid, const UINT_PTR DeviceID, const GUID *const pEncryptionGuid )
  734. {
  735. DNASSERT( DeviceID < MAX_DATA_PORTS );
  736. DNASSERT( sizeof( *pGuid ) == sizeof( *pEncryptionGuid ) );
  737. memset( pGuid, 0x00, sizeof( *pGuid ) );
  738. reinterpret_cast<BYTE*>( pGuid )[ 0 ] = static_cast<BYTE>( DeviceID );
  739. ModemEncryptGuid( pGuid, pGuid, pEncryptionGuid );
  740. }
  741. //**********************************************************************
  742. //**********************************************************************
  743. // ------------------------------
  744. // GuidToDeviceID - convert an adapter GUID to a device ID
  745. //
  746. // Entry: Reference of Guid
  747. //
  748. //
  749. // Exit: Device ID
  750. // ------------------------------
  751. #undef DPF_MODNAME
  752. #define DPF_MODNAME "GuidToDeviceID"
  753. DWORD GuidToDeviceID( const GUID *const pGuid, const GUID *const pEncryptionGuid )
  754. {
  755. GUID DecryptedGuid;
  756. DNASSERT( pGuid != NULL );
  757. DNASSERT( pEncryptionGuid != NULL );
  758. ModemDecryptGuid( pGuid, &DecryptedGuid, pEncryptionGuid );
  759. return reinterpret_cast<const BYTE*>( &DecryptedGuid )[ 0 ];
  760. }
  761. //**********************************************************************
  762. //**********************************************************************
  763. // ------------------------------
  764. // ComDeviceIDToString - convert a COM device ID to a string
  765. //
  766. // Entry: Pointer to destination string (assumed to be large enough)
  767. // Device ID
  768. //
  769. // Exit: Nothing
  770. // ------------------------------
  771. #undef DPF_MODNAME
  772. #define DPF_MODNAME "ComDeviceIDToString"
  773. void ComDeviceIDToString( TCHAR *const pString, const UINT_PTR uDeviceID )
  774. {
  775. UINT_PTR uTemp;
  776. DNASSERT( uDeviceID < MAX_DATA_PORTS );
  777. uTemp = uDeviceID;
  778. memcpy( pString, TEXT("COM000"), COM_PORT_STRING_LENGTH * sizeof(TCHAR) );
  779. pString[ 5 ] = ( static_cast<char>( uTemp % 10 ) ) + TEXT('0');
  780. uTemp /= 10;
  781. pString[ 4 ] = ( static_cast<char>( uTemp % 10 ) ) + TEXT('0');
  782. uTemp /= 10;
  783. pString[ 3 ] = ( static_cast<char>( uTemp % 10 ) ) + TEXT('0');
  784. DNASSERT( uTemp < 10 );
  785. if ( uDeviceID < 100 )
  786. {
  787. if ( uDeviceID < 10 )
  788. {
  789. DNASSERT( pString[ 3 ] == TEXT('0') );
  790. DNASSERT( pString[ 4 ] == TEXT('0') );
  791. pString[ 3 ] = pString[ 5 ];
  792. pString[ 4 ] = TEXT('\0');
  793. pString[ 5 ] = TEXT('\0');
  794. }
  795. else
  796. {
  797. DNASSERT( pString[ 3 ] == TEXT('0') );
  798. pString[ 3 ] = pString[ 4 ];
  799. pString[ 4 ] = pString[ 5 ];
  800. pString[ 5 ] = TEXT('\0');
  801. }
  802. }
  803. }
  804. //**********************************************************************
  805. //**********************************************************************
  806. // ------------------------------
  807. // WideToANSI - convert a wide string to an ANSI string
  808. //
  809. // Entry: Pointer to source wide string
  810. // Size of source string (in WCHAR units, -1 implies NULL-terminated)
  811. // Pointer to ANSI string destination
  812. // Pointer to size of ANSI destination
  813. //
  814. // Exit: Error code:
  815. // DPNERR_GENERIC = operation failed
  816. // DPN_OK = operation succeded
  817. // DPNERR_BUFFERTOOSMALL = destination buffer too small
  818. // ------------------------------
  819. #undef DPF_MODNAME
  820. #define DPF_MODNAME "WideToAnsi"
  821. HRESULT WideToAnsi( const WCHAR *const pWCHARString, const DWORD dwWCHARStringLength, char *const pString, DWORD *const pdwStringLength )
  822. {
  823. HRESULT hr;
  824. int iReturn;
  825. BOOL fDefault;
  826. DNASSERT( pWCHARString != NULL );
  827. DNASSERT( pdwStringLength != NULL );
  828. DNASSERT( ( pString != NULL ) || ( &pdwStringLength == 0 ) );
  829. hr = DPN_OK;
  830. fDefault = FALSE;
  831. iReturn = WideCharToMultiByte( CP_ACP, // code page (default ANSI)
  832. 0, // flags (none)
  833. pWCHARString, // pointer to WCHAR string
  834. dwWCHARStringLength, // size of WCHAR string
  835. pString, // pointer to destination ANSI string
  836. *pdwStringLength, // size of destination string
  837. NULL, // pointer to default for unmappable characters (none)
  838. &fDefault // pointer to flag indicating that default was used
  839. );
  840. if ( iReturn == 0 )
  841. {
  842. hr = DPNERR_GENERIC;
  843. }
  844. else
  845. {
  846. if ( *pdwStringLength == 0 )
  847. {
  848. hr = DPNERR_BUFFERTOOSMALL;
  849. }
  850. else
  851. {
  852. DNASSERT( hr == DPN_OK );
  853. }
  854. *pdwStringLength = iReturn;
  855. }
  856. //
  857. // if you hit this ASSERT it's because you've probably got ASCII text as your
  858. // input WCHAR string. Double-check your input!!
  859. //
  860. DNASSERT( fDefault == FALSE );
  861. return hr;
  862. }
  863. //**********************************************************************
  864. //**********************************************************************
  865. // ------------------------------
  866. // ANSIToWide - convert an ANSI string to a wide string
  867. //
  868. // Entry: Pointer to source multi-byte (ANSI) string
  869. // Size of source string (-1 imples NULL-terminated)
  870. // Pointer to multi-byte string destination
  871. // Pointer to size of multi-byte destination (in WCHAR units)
  872. //
  873. // Exit: Error code:
  874. // ERR_FAIL - operation failed
  875. // ERR_NONE - operation succeded
  876. // ERR_BUFFER_TOO_SMALL - destination buffer too small
  877. // ------------------------------
  878. #undef DPF_MODNAME
  879. #define DPF_MODNAME "AnsiToWide"
  880. HRESULT AnsiToWide( const char *const pString, const DWORD dwStringLength, WCHAR *const pWCHARString, DWORD *const pdwWCHARStringLength )
  881. {
  882. HRESULT hr;
  883. int iReturn;
  884. DNASSERT( pdwWCHARStringLength != 0 );
  885. DNASSERT( ( pWCHARString != NULL ) || ( pdwWCHARStringLength == 0 ) );
  886. DNASSERT( pString != NULL );
  887. hr = DPN_OK;
  888. iReturn = MultiByteToWideChar( CP_ACP, // code page (default ANSI)
  889. 0, // flags (none)
  890. pString, // pointer to multi-byte string
  891. dwStringLength, // size of string (assume null-terminated)
  892. pWCHARString, // pointer to destination wide-char string
  893. *pdwWCHARStringLength // size of destination in WCHARs
  894. );
  895. if ( iReturn == 0 )
  896. {
  897. hr = DPNERR_GENERIC;
  898. }
  899. else
  900. {
  901. if ( *pdwWCHARStringLength == 0 )
  902. {
  903. hr = DPNERR_BUFFERTOOSMALL;
  904. }
  905. else
  906. {
  907. DNASSERT( hr == DPN_OK );
  908. }
  909. *pdwWCHARStringLength = iReturn;
  910. }
  911. return hr;
  912. }
  913. //**********************************************************************
  914. //**********************************************************************
  915. // ------------------------------
  916. // CreateSPData - create instance data for SP
  917. //
  918. // Entry: Pointer to pointer to SPData
  919. // Pionter to class GUID
  920. // Interface type
  921. // Pointer to COM interface vtable
  922. //
  923. // Exit: Error code
  924. // ------------------------------
  925. #undef DPF_MODNAME
  926. #define DPF_MODNAME "CreateSPData"
  927. HRESULT CreateSPData( CModemSPData **const ppSPData,
  928. const SP_TYPE SPType,
  929. IDP8ServiceProviderVtbl *const pVtbl )
  930. {
  931. HRESULT hr;
  932. CModemSPData *pSPData;
  933. DNASSERT( ppSPData != NULL );
  934. DNASSERT( pVtbl != NULL );
  935. //
  936. // initialize
  937. //
  938. hr = DPN_OK;
  939. *ppSPData = NULL;
  940. pSPData = NULL;
  941. //
  942. // create data
  943. //
  944. pSPData = new CModemSPData;
  945. if ( pSPData == NULL )
  946. {
  947. hr = DPNERR_OUTOFMEMORY;
  948. DPFX(DPFPREP, 0, "Cannot create data for interface!" );
  949. goto Failure;
  950. }
  951. pSPData->AddRef();
  952. hr = pSPData->Initialize( SPType, pVtbl );
  953. if ( hr != DPN_OK )
  954. {
  955. DPFX(DPFPREP, 0, "Failed to intialize SP data!" );
  956. DisplayDNError( 0, hr );
  957. goto Failure;
  958. }
  959. Exit:
  960. if ( hr != DPN_OK )
  961. {
  962. DPFX(DPFPREP, 0, "Problem with CreateSPData!" );
  963. DisplayDNError( 0, hr );
  964. }
  965. *ppSPData = pSPData;
  966. return hr;
  967. Failure:
  968. if ( pSPData != NULL )
  969. {
  970. pSPData->DecRef();
  971. pSPData = NULL;
  972. }
  973. goto Exit;
  974. }
  975. //**********************************************************************
  976. //**********************************************************************
  977. // ------------------------------
  978. // GenerateAvailableComPortList - generate a list of available com ports
  979. //
  980. // Entry: Pointer to list of Booleans to indicate availablility
  981. // Maximum index of comport to enumerate
  982. // Pointer to number of com ports found
  983. //
  984. // Exit: Error code
  985. //
  986. // Note: This function will fill in indicies 1 through uMaxDeviceIndex.
  987. // ------------------------------
  988. #undef DPF_MODNAME
  989. #define DPF_MODNAME "GenerateAvailableComPortList"
  990. HRESULT GenerateAvailableComPortList( BOOL *const pfPortAvailable,
  991. const UINT_PTR uMaxDeviceIndex,
  992. DWORD *const pdwPortCount )
  993. {
  994. HRESULT hr;
  995. UINT_PTR uIndex;
  996. UINT_PTR uPortCount;
  997. DNASSERT( pfPortAvailable != NULL );
  998. DNASSERT( uMaxDeviceIndex != 0 );
  999. DNASSERT( pdwPortCount != NULL );
  1000. //
  1001. // initialize
  1002. //
  1003. hr = DPN_OK;
  1004. uPortCount = 0;
  1005. memset( pfPortAvailable, 0x00, ( sizeof( *pfPortAvailable ) * ( uMaxDeviceIndex + 1 ) ) );
  1006. *pdwPortCount = 0;
  1007. //
  1008. // attempt to open all COM ports in the specified range
  1009. //
  1010. uIndex = uMaxDeviceIndex;
  1011. while ( uIndex != 0 )
  1012. {
  1013. DNHANDLE hComFile;
  1014. TCHAR ComTemplate[ (COM_PORT_STRING_LENGTH+1) ];
  1015. DWORD dwError;
  1016. ComDeviceIDToString( ComTemplate, uIndex );
  1017. hComFile = DNCreateFile( ComTemplate, // comm port name
  1018. GENERIC_READ | GENERIC_WRITE, // read/write access
  1019. 0, // don't share file with others
  1020. NULL, // default sercurity descriptor
  1021. OPEN_EXISTING, // comm port must exist to be opened
  1022. FILE_FLAG_OVERLAPPED, // use overlapped I/O
  1023. NULL // no handle for template file
  1024. );
  1025. if ( hComFile == DNINVALID_HANDLE_VALUE )
  1026. {
  1027. dwError = GetLastError();
  1028. if ( dwError != ERROR_ACCESS_DENIED )
  1029. {
  1030. //
  1031. // Don't bother displaying ERROR_FILE_NOT_FOUND, that's the usual
  1032. // error when you try to open a bogus COM port.
  1033. //
  1034. if ( dwError != ERROR_FILE_NOT_FOUND )
  1035. {
  1036. DPFX(DPFPREP, 9, "Couldn't open COM%u while enumerating com port adapters, err = %u.", uIndex, dwError );
  1037. DisplayErrorCode( 9, dwError );
  1038. }
  1039. goto SkipComPort;
  1040. }
  1041. DPFX(DPFPREP, 1, "Couldn't open COM%u, it is probably already in use.", uIndex );
  1042. //
  1043. // Consider the port as possibly available, continue.
  1044. //
  1045. }
  1046. //
  1047. // We found a valid COM port (it may be in use), note which COM port
  1048. // this is and then close our handle
  1049. //
  1050. pfPortAvailable[ uIndex ] = TRUE;
  1051. uPortCount++;
  1052. if ( hComFile != DNINVALID_HANDLE_VALUE )
  1053. {
  1054. if ( DNCloseHandle( hComFile ) == FALSE )
  1055. {
  1056. dwError = GetLastError();
  1057. DPFX(DPFPREP, 0, "Problem closing COM%u while enumerating com port adapters, err = %u!",
  1058. uIndex, dwError );
  1059. DisplayErrorCode( 0, dwError );
  1060. }
  1061. }
  1062. SkipComPort:
  1063. uIndex--;
  1064. }
  1065. DNASSERT( uPortCount <= UINT32_MAX );
  1066. DBG_CASSERT( sizeof( *pdwPortCount ) == sizeof( DWORD ) );
  1067. *pdwPortCount = static_cast<DWORD>( uPortCount );
  1068. return hr;
  1069. }
  1070. //**********************************************************************
  1071. //**********************************************************************
  1072. // ------------------------------
  1073. // GenerateAvailableModemList - generate list of available modems
  1074. //
  1075. // Entry: Pointer to TAPI data
  1076. // Pointer to modem count
  1077. // Pointer to data block
  1078. // Pointer to size of data block
  1079. //
  1080. // Exit: Error code
  1081. // ------------------------------
  1082. #undef DPF_MODNAME
  1083. #define DPF_MODNAME "GenerateAvailableModemList"
  1084. HRESULT GenerateAvailableModemList( const TAPI_INFO *const pTAPIInfo,
  1085. DWORD *const pdwModemCount,
  1086. MODEM_NAME_DATA *const pModemNameData,
  1087. DWORD *const pdwModemNameDataSize )
  1088. {
  1089. HRESULT hr;
  1090. LONG lLineReturn;
  1091. DWORD dwDeviceID;
  1092. DWORD dwDevCapsSize;
  1093. DWORD dwAPIVersion;
  1094. LINEDEVCAPS *pDevCaps;
  1095. LINEEXTENSIONID LineExtensionID;
  1096. DWORD dwRequiredBufferSize;
  1097. TCHAR *pOutputModemName;
  1098. DNASSERT( pdwModemCount != NULL );
  1099. DNASSERT( pdwModemNameDataSize != NULL );
  1100. DNASSERT( ( pModemNameData != NULL ) || ( *pdwModemNameDataSize == 0 ) );
  1101. //
  1102. // initialize
  1103. //
  1104. hr = DPN_OK;
  1105. dwRequiredBufferSize = 0;
  1106. *pdwModemCount = 0;
  1107. pDevCaps = NULL;
  1108. if ( pModemNameData != NULL )
  1109. {
  1110. pOutputModemName = &(reinterpret_cast<TCHAR*>( pModemNameData )[ *pdwModemNameDataSize / sizeof(TCHAR) ]);
  1111. memset( pModemNameData, 0x00, *pdwModemNameDataSize );
  1112. }
  1113. else
  1114. {
  1115. pOutputModemName = NULL;
  1116. }
  1117. dwDevCapsSize = g_dwDefaultTAPIDevCapsSize;
  1118. pDevCaps = static_cast<LINEDEVCAPS*>( DNMalloc( dwDevCapsSize ) );
  1119. if ( pDevCaps == NULL )
  1120. {
  1121. hr = DPNERR_OUTOFMEMORY;
  1122. goto Failure;
  1123. }
  1124. dwDeviceID = pTAPIInfo->dwLinesAvailable;
  1125. if ( dwDeviceID > ( MAX_DATA_PORTS - 2 ) )
  1126. {
  1127. dwDeviceID = MAX_DATA_PORTS - 2;
  1128. DPFX(DPFPREP, 0, "Truncating to %d devices!", dwDeviceID );
  1129. }
  1130. Reloop:
  1131. while ( dwDeviceID != 0 )
  1132. {
  1133. dwDeviceID--;
  1134. memset( &LineExtensionID, 0x00, sizeof( LineExtensionID ) );
  1135. DNASSERT( p_lineNegotiateAPIVersion != NULL );
  1136. lLineReturn = p_lineNegotiateAPIVersion( pTAPIInfo->hApplicationInstance, // handle to TAPI instance
  1137. dwDeviceID, // device ID
  1138. 0,
  1139. pTAPIInfo->dwVersion, // maximum TAPI version
  1140. &dwAPIVersion, // pointer to negotiated line version
  1141. &LineExtensionID // pointer to line extension infromation (none)
  1142. );
  1143. if ( lLineReturn != LINEERR_NONE )
  1144. {
  1145. //
  1146. // let this slide, just return no name string
  1147. //
  1148. switch ( lLineReturn )
  1149. {
  1150. //
  1151. // this TAPI device isn't up to our standards, ignore it
  1152. //
  1153. case LINEERR_INCOMPATIBLEAPIVERSION:
  1154. {
  1155. DPFX(DPFPREP, 0, "Rejecting TAPI device 0x%x because of API version!", dwDeviceID );
  1156. goto Reloop;
  1157. break;
  1158. }
  1159. //
  1160. // Device is not present. I don't know what causes
  1161. // this, but I saw it on one of my dev machines after
  1162. // I switched the modem from COM2 to COM1.
  1163. //
  1164. case LINEERR_NODEVICE:
  1165. {
  1166. DPFX(DPFPREP, 0, "Rejecting TAPI device 0x%x because it's not there!", dwDeviceID );
  1167. goto Reloop;
  1168. break;
  1169. }
  1170. //
  1171. // This was seen in PnP stress.
  1172. //
  1173. case LINEERR_UNINITIALIZED:
  1174. {
  1175. DPFX(DPFPREP, 0, "Rejecting TAPI device 0x%x because it is not initialized!", dwDeviceID );
  1176. goto Reloop;
  1177. break;
  1178. }
  1179. //
  1180. // other, stop and see what happened
  1181. //
  1182. default:
  1183. {
  1184. DPFX(DPFPREP, 0, "Problem getting line API version for device: %d", dwDeviceID );
  1185. DisplayTAPIError( 0, lLineReturn );
  1186. goto Reloop;
  1187. break;
  1188. }
  1189. }
  1190. }
  1191. //
  1192. // ask for device caps
  1193. //
  1194. pDevCaps->dwTotalSize = dwDevCapsSize;
  1195. pDevCaps->dwNeededSize = dwDevCapsSize;
  1196. lLineReturn = LINEERR_STRUCTURETOOSMALL;
  1197. while ( lLineReturn == LINEERR_STRUCTURETOOSMALL )
  1198. {
  1199. DNASSERT( pDevCaps != NULL );
  1200. dwDevCapsSize = pDevCaps->dwNeededSize;
  1201. DNFree( pDevCaps );
  1202. pDevCaps = (LINEDEVCAPS*) DNMalloc( dwDevCapsSize );
  1203. if ( pDevCaps == NULL )
  1204. {
  1205. hr = DPNERR_OUTOFMEMORY;
  1206. DPFX(DPFPREP, 0, "GetAvailableModemList: Failed to realloc memory on device %d!", dwDeviceID );
  1207. goto Failure;
  1208. }
  1209. pDevCaps->dwTotalSize = dwDevCapsSize;
  1210. pDevCaps->dwNeededSize = 0;
  1211. DNASSERT( p_lineGetDevCaps != NULL );
  1212. lLineReturn = p_lineGetDevCaps( pTAPIInfo->hApplicationInstance, // TAPI instance handle
  1213. dwDeviceID, // TAPI device ID
  1214. dwAPIVersion, // negotiated API version
  1215. 0, // extended data version (none)
  1216. pDevCaps // pointer to device caps data
  1217. );
  1218. //
  1219. // TAPI lies about structures being too small!
  1220. // Double check the structure size ourselves.
  1221. //
  1222. if ( pDevCaps->dwNeededSize > dwDevCapsSize )
  1223. {
  1224. lLineReturn = LINEERR_STRUCTURETOOSMALL;
  1225. }
  1226. }
  1227. //
  1228. // If caps have been gotten, process them. Otherwise skip this device.
  1229. //
  1230. if ( lLineReturn == LINEERR_NONE )
  1231. {
  1232. //
  1233. // is this really a modem?
  1234. //
  1235. if ( ( pDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM ) != 0 )
  1236. {
  1237. //
  1238. // is this the modem name information accerptable?
  1239. //
  1240. if ( ( pDevCaps->dwLineNameSize != 0 ) &&
  1241. ( pDevCaps->dwLineNameOffset != 0 ) )
  1242. {
  1243. //
  1244. // get the name of the device
  1245. //
  1246. DBG_CASSERT( sizeof( pDevCaps ) == sizeof( char* ) );
  1247. DWORD dwSize;
  1248. switch (pDevCaps->dwStringFormat)
  1249. {
  1250. case STRINGFORMAT_ASCII:
  1251. {
  1252. char* pLineName;
  1253. pLineName = &( reinterpret_cast<char*>( pDevCaps )[ pDevCaps->dwLineNameOffset ] );
  1254. //
  1255. // Note the required storage size and only copy it to the output
  1256. // if there's enough room. TAPI drivers are inconsistent. Some
  1257. // drivers return NULL terminated strings and others return strings
  1258. // with no NULL termination. Be paranoid and reserve space for an
  1259. // extra NULL for termination so we can always guarantee termination.
  1260. // This may waste a byte or two, but the user will never notice.
  1261. //
  1262. dwRequiredBufferSize += sizeof( *pModemNameData ) + (pDevCaps->dwLineNameSize * sizeof(TCHAR)) + sizeof( g_NullToken );
  1263. if ( dwRequiredBufferSize <= *pdwModemNameDataSize )
  1264. {
  1265. pModemNameData[ *pdwModemCount ].dwModemID = ModemIDFromTAPIID( dwDeviceID );
  1266. pModemNameData[ *pdwModemCount ].dwModemNameSize = pDevCaps->dwLineNameSize * sizeof(TCHAR);
  1267. pOutputModemName = &pOutputModemName[ - (static_cast<INT_PTR>( ((pDevCaps->dwLineNameSize * sizeof(TCHAR)) + sizeof( g_NullToken ) ) / sizeof(TCHAR))) ];
  1268. #ifndef UNICODE
  1269. memcpy( pOutputModemName, pLineName, pDevCaps->dwLineNameSize );
  1270. #else
  1271. dwSize = pDevCaps->dwLineNameSize * sizeof(TCHAR);
  1272. AnsiToWide(pLineName, pDevCaps->dwLineNameSize, pOutputModemName, &dwSize);
  1273. #endif // UNICODE
  1274. pModemNameData[ *pdwModemCount ].pModemName = pOutputModemName;
  1275. //
  1276. // Be paranoid about NULL termination. We've accounted for enough
  1277. // space to add a terminating NULL to the TAPI device name if one
  1278. // wasn't provided.
  1279. //
  1280. if ( pOutputModemName[ ((pDevCaps->dwLineNameSize * sizeof(TCHAR)) - sizeof( g_NullToken )) / sizeof(TCHAR) ] != g_NullToken )
  1281. {
  1282. pOutputModemName[ pDevCaps->dwLineNameSize ] = g_NullToken;
  1283. pModemNameData[ *pdwModemCount ].dwModemNameSize += sizeof( g_NullToken );
  1284. }
  1285. }
  1286. else
  1287. {
  1288. //
  1289. // Note that the output buffer is too small, but still keep
  1290. // processing modem names.
  1291. //
  1292. hr = DPNERR_BUFFERTOOSMALL;
  1293. }
  1294. (*pdwModemCount)++;
  1295. DPFX(DPFPREP, 2, "Accepting modem device: 0x%x (ASCII)", dwDeviceID );
  1296. }
  1297. break;
  1298. case STRINGFORMAT_UNICODE:
  1299. {
  1300. WCHAR* pLineName;
  1301. pLineName = &( reinterpret_cast<WCHAR*>( pDevCaps )[ pDevCaps->dwLineNameOffset / sizeof(WCHAR)] );
  1302. //
  1303. // Note the required storage size and only copy it to the output
  1304. // if there's enough room. TAPI drivers are inconsistent. Some
  1305. // drivers return NULL terminated strings and others return strings
  1306. // with no NULL termination. Be paranoid and reserve space for an
  1307. // extra NULL for termination so we can always guarantee termination.
  1308. // This may waste a byte or two, but the user will never notice.
  1309. //
  1310. dwRequiredBufferSize += sizeof( *pModemNameData ) + ((pDevCaps->dwLineNameSize * sizeof(TCHAR)) / sizeof(WCHAR)) + sizeof( g_NullToken );
  1311. if ( dwRequiredBufferSize <= *pdwModemNameDataSize )
  1312. {
  1313. pModemNameData[ *pdwModemCount ].dwModemID = ModemIDFromTAPIID( dwDeviceID );
  1314. pModemNameData[ *pdwModemCount ].dwModemNameSize = pDevCaps->dwLineNameSize * (sizeof(TCHAR) / sizeof(WCHAR));
  1315. pOutputModemName = &pOutputModemName[ - (static_cast<INT_PTR>( (((pDevCaps->dwLineNameSize * sizeof(TCHAR)) / sizeof(WCHAR)) + sizeof( g_NullToken ) ) / sizeof(TCHAR))) ];
  1316. #ifdef UNICODE
  1317. memcpy( pOutputModemName, pLineName, pDevCaps->dwLineNameSize );
  1318. #else
  1319. dwSize = pDevCaps->dwLineNameSize / sizeof(TCHAR);
  1320. WideToAnsi(pLineName, pDevCaps->dwLineNameSize / sizeof(WCHAR), pOutputModemName, &dwSize);
  1321. #endif // UNICODE
  1322. pModemNameData[ *pdwModemCount ].pModemName = pOutputModemName;
  1323. //
  1324. // Be paranoid about NULL termination. We've accounted for enough
  1325. // space to add a terminating NULL to the TAPI device name if one
  1326. // wasn't provided.
  1327. //
  1328. if ( pOutputModemName[ (((pDevCaps->dwLineNameSize*sizeof(TCHAR))/sizeof(WCHAR)) - sizeof( g_NullToken )) / sizeof(TCHAR) ] != g_NullToken )
  1329. {
  1330. pOutputModemName[ pDevCaps->dwLineNameSize / sizeof(WCHAR) ] = g_NullToken;
  1331. pModemNameData[ *pdwModemCount ].dwModemNameSize += sizeof( g_NullToken );
  1332. }
  1333. }
  1334. else
  1335. {
  1336. //
  1337. // Note that the output buffer is too small, but still keep
  1338. // processing modem names.
  1339. //
  1340. hr = DPNERR_BUFFERTOOSMALL;
  1341. }
  1342. (*pdwModemCount)++;
  1343. DPFX(DPFPREP, 2, "Accepting modem device: 0x%x (Unicode)", dwDeviceID );
  1344. }
  1345. break;
  1346. default:
  1347. {
  1348. hr = DPNERR_GENERIC;
  1349. DPFX(DPFPREP, 0, "Problem with modem name for device: 0x%x!", dwDeviceID );
  1350. DNASSERT( FALSE );
  1351. }
  1352. }
  1353. }
  1354. else
  1355. {
  1356. hr = DPNERR_GENERIC;
  1357. DPFX(DPFPREP, 0, "Problem with modem name for device: 0x%x!", dwDeviceID );
  1358. DNASSERT( FALSE );
  1359. }
  1360. }
  1361. else
  1362. {
  1363. DPFX(DPFPREP, 1, "Ignoring non-datamodem device: 0x%x", dwDeviceID );
  1364. }
  1365. }
  1366. else
  1367. {
  1368. DPFX(DPFPREP, 0, "Failed to get device caps. Ignoring device: 0x%x", dwDeviceID );
  1369. }
  1370. }
  1371. *pdwModemNameDataSize = dwRequiredBufferSize;
  1372. Exit:
  1373. if ( pDevCaps != NULL )
  1374. {
  1375. DNFree( pDevCaps );
  1376. pDevCaps = NULL;
  1377. }
  1378. return hr;
  1379. Failure:
  1380. goto Exit;
  1381. }
  1382. //**********************************************************************
  1383. //**********************************************************************
  1384. // ------------------------------
  1385. // PhoneNumberToWCHAR - convert a phone number to WCHAR
  1386. //
  1387. // Entry: Pointer to phone number
  1388. // Pointer to WCHAR destination
  1389. // Pointer to size of WCHAR destintion
  1390. //
  1391. // Exit: Error code
  1392. // ------------------------------
  1393. #ifndef UNICODE
  1394. HRESULT PhoneNumberToWCHAR( const char *const pPhoneNumber,
  1395. WCHAR *const pWCHARPhoneNumber,
  1396. DWORD *const pdwWCHARPhoneNumberSize )
  1397. {
  1398. HRESULT hr;
  1399. char *pOutput;
  1400. DWORD dwInputIndex;
  1401. DWORD dwOutputIndex;
  1402. DNASSERT( pPhoneNumber != NULL );
  1403. DNASSERT( pWCHARPhoneNumber != NULL );
  1404. DNASSERT( pdwWCHARPhoneNumberSize != NULL );
  1405. //
  1406. // initialize
  1407. //
  1408. hr = DPN_OK;
  1409. pOutput = reinterpret_cast<char*>( pWCHARPhoneNumber );
  1410. dwInputIndex = 0;
  1411. dwOutputIndex = 0;
  1412. memset( pWCHARPhoneNumber, 0, ( (*pdwWCHARPhoneNumberSize) * sizeof( *pWCHARPhoneNumber ) ) );
  1413. while ( pPhoneNumber[ dwInputIndex ] != '\0' )
  1414. {
  1415. if ( dwInputIndex < ( *pdwWCHARPhoneNumberSize ) )
  1416. {
  1417. pOutput[ dwOutputIndex ] = pPhoneNumber[ dwInputIndex ];
  1418. }
  1419. dwOutputIndex += sizeof( *pWCHARPhoneNumber );
  1420. dwInputIndex += sizeof( *pPhoneNumber );
  1421. }
  1422. *pdwWCHARPhoneNumberSize = dwInputIndex + 1;
  1423. return hr;
  1424. }
  1425. #endif // !UNICODE
  1426. //**********************************************************************
  1427. //**********************************************************************
  1428. // ------------------------------
  1429. // PhoneNumberFromWCHAR - convert a phone number from WCHAR
  1430. //
  1431. // Entry: Pointer to WCHAR phone number
  1432. // Pointer to phone number destination
  1433. // Pointer to phone destination size
  1434. //
  1435. // Exit: Error code
  1436. // ------------------------------
  1437. #ifndef UNICODE
  1438. HRESULT PhoneNumberFromWCHAR( const WCHAR *const pWCHARPhoneNumber,
  1439. char *const pPhoneNumber,
  1440. DWORD *const pdwPhoneNumberSize )
  1441. {
  1442. HRESULT hr;
  1443. const char *pInput;
  1444. DWORD dwInputIndex;
  1445. DWORD dwOutputIndex;
  1446. DNASSERT( pWCHARPhoneNumber != NULL );
  1447. DNASSERT( pPhoneNumber != NULL );
  1448. DNASSERT( pdwPhoneNumberSize != NULL );
  1449. //
  1450. // initialize
  1451. //
  1452. hr = DPN_OK;
  1453. pInput = reinterpret_cast<const char*>( pWCHARPhoneNumber );
  1454. dwInputIndex = 0;
  1455. dwOutputIndex = 0;
  1456. memset( pPhoneNumber, 0x00, *pdwPhoneNumberSize );
  1457. while ( pInput[ dwInputIndex ] != '\0' )
  1458. {
  1459. if ( dwOutputIndex < *pdwPhoneNumberSize )
  1460. {
  1461. pPhoneNumber[ dwOutputIndex ] = pInput[ dwInputIndex ];
  1462. }
  1463. dwInputIndex += sizeof( *pWCHARPhoneNumber );
  1464. dwOutputIndex += sizeof( *pPhoneNumber );
  1465. }
  1466. *pdwPhoneNumberSize = dwOutputIndex + 1;
  1467. return hr;
  1468. }
  1469. #endif // !UNICODE
  1470. //**********************************************************************
  1471. //**********************************************************************
  1472. // ------------------------------
  1473. // ModemEncryptGuid - encrypt a guid
  1474. //
  1475. // Entry: Pointer to source guid
  1476. // Pointer to destination guid
  1477. // Pointer to encryption key
  1478. //
  1479. // Exit: Nothing
  1480. // ------------------------------
  1481. #undef DPF_MODNAME
  1482. #define DPF_MODNAME "ModemEncryptGuid"
  1483. void ModemEncryptGuid( const GUID *const pSourceGuid,
  1484. GUID *const pDestinationGuid,
  1485. const GUID *const pEncryptionKey )
  1486. {
  1487. const char *pSourceBytes;
  1488. char *pDestinationBytes;
  1489. const char *pEncryptionBytes;
  1490. DWORD_PTR dwIndex;
  1491. DNASSERT( pSourceGuid != NULL );
  1492. DNASSERT( pDestinationGuid != NULL );
  1493. DNASSERT( pEncryptionKey != NULL );
  1494. DBG_CASSERT( sizeof( pSourceBytes ) == sizeof( pSourceGuid ) );
  1495. pSourceBytes = reinterpret_cast<const char*>( pSourceGuid );
  1496. DBG_CASSERT( sizeof( pDestinationBytes ) == sizeof( pDestinationGuid ) );
  1497. pDestinationBytes = reinterpret_cast<char*>( pDestinationGuid );
  1498. DBG_CASSERT( sizeof( pEncryptionBytes ) == sizeof( pEncryptionKey ) );
  1499. pEncryptionBytes = reinterpret_cast<const char*>( pEncryptionKey );
  1500. DBG_CASSERT( ( sizeof( *pSourceGuid ) == sizeof( *pEncryptionKey ) ) &&
  1501. ( sizeof( *pDestinationGuid ) == sizeof( *pEncryptionKey ) ) );
  1502. dwIndex = sizeof( *pSourceGuid );
  1503. while ( dwIndex != 0 )
  1504. {
  1505. dwIndex--;
  1506. pDestinationBytes[ dwIndex ] = pSourceBytes[ dwIndex ] ^ pEncryptionBytes[ dwIndex ];
  1507. }
  1508. }
  1509. //**********************************************************************