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.

1647 lines
43 KiB

  1. #include "precomp.h"
  2. #include "call.h"
  3. #include "callto.h"
  4. #include "conf.h"
  5. #include "confroom.h"
  6. #include "confpolicies.h"
  7. #include "confutil.h"
  8. #include "nmldap.h"
  9. const int CCallto::s_iMaxCalltoLength = 255;
  10. const int CCallto::s_iMaxAddressLength = 255;
  11. //--------------------------------------------------------------------------//
  12. // CCallto::CCallto. //
  13. //--------------------------------------------------------------------------//
  14. CCallto::CCallto(void):
  15. m_bUnescapedAddressOnly( false ),
  16. m_ulDestination( INADDR_NONE ),
  17. m_bGatekeeperEnabled( false ),
  18. m_pszGatekeeperName( NULL ),
  19. m_ulGatekeeperAddress( INADDR_NONE ),
  20. m_bGatewayEnabled( false ),
  21. m_pszGatewayName( NULL ),
  22. m_ulGatewayAddress( INADDR_NONE ),
  23. m_pszDefaultIlsServerName( NULL ),
  24. m_pszCalltoBuffer( NULL ),
  25. m_pszDisplayName( NULL )
  26. {
  27. } // End of CCallto::CCallto.
  28. //--------------------------------------------------------------------------//
  29. // CCallto::~CCallto. //
  30. //--------------------------------------------------------------------------//
  31. CCallto::~CCallto(void)
  32. {
  33. delete [] m_pszGatekeeperName;
  34. delete [] m_pszGatewayName;
  35. delete [] m_pszDefaultIlsServerName;
  36. delete [] m_pszCalltoBuffer;
  37. delete [] m_pszDisplayName;
  38. } // End of CCallto::~CCallto.
  39. //--------------------------------------------------------------------------//
  40. // CCallto::Callto. //
  41. //--------------------------------------------------------------------------//
  42. HRESULT CCallto::Callto
  43. (
  44. const TCHAR * const pszCallto, // pointer to the callto url to try to place the call with...
  45. const TCHAR * const pszDisplayName, // pointer to the display name to use...
  46. const NM_ADDR_TYPE nmType, // callto type to resolve this callto as...
  47. const bool bAddressOnly, // the pszCallto parameter is to be interpreted as a pre-unescaped addressing component vs a full callto...
  48. const bool * const pbSecurityPreference, // pointer to security preference, NULL for none. must be "compatible" with secure param if present...
  49. const bool bAddToMru, // whether or not save in mru...
  50. const bool bUIEnabled, // whether or not to perform user interaction on errors...
  51. const HWND hwndParent, // if bUIEnabled is true this is the window to parent error/status windows to...
  52. INmCall ** const ppInternalCall // out pointer to INmCall * to receive INmCall * generated by placing call...
  53. ){
  54. ASSERT( pszCallto != NULL );
  55. ASSERT( (hwndParent == NULL) || IsWindow( hwndParent ) );
  56. HRESULT hrResult;
  57. // These members need to be reset at the beginning of every call...
  58. m_bUIEnabled = bUIEnabled;
  59. m_hwndParent = hwndParent;
  60. m_ulDestination = INADDR_NONE;
  61. m_bUnescapedAddressOnly = bAddressOnly;
  62. m_pszDisplayName = PszAlloc( pszDisplayName );
  63. m_Parameters.SetParams( NULL ); // Need to reset all parameter settings too...
  64. // Process the callto...
  65. if( (hrResult = Parse( pszCallto )) == S_OK )
  66. {
  67. // Validate that the security specified (if any) is compatible with current NM state.
  68. bool bValidatedSecurity;
  69. if( (hrResult = GetValidatedSecurity( pbSecurityPreference, bValidatedSecurity )) == S_OK )
  70. {
  71. if( (hrResult = Resolve( nmType )) == S_OK )
  72. {
  73. hrResult = PlaceCall( pszCallto, bAddToMru, bValidatedSecurity, ppInternalCall );
  74. }
  75. }
  76. }
  77. if( FAILED( hrResult ) && m_bUIEnabled )
  78. {
  79. DisplayCallError( hrResult, (pszDisplayName != NULL)? pszDisplayName: pszCallto );
  80. }
  81. delete [] m_pszCalltoBuffer;
  82. delete [] m_pszDisplayName;
  83. m_pszCalltoBuffer = NULL;
  84. m_pszDisplayName = NULL;
  85. return( hrResult );
  86. } // End of CCallto::Callto.
  87. //--------------------------------------------------------------------------//
  88. // CCallto::Parse. //
  89. //--------------------------------------------------------------------------//
  90. HRESULT CCallto::Parse
  91. (
  92. const TCHAR * const pszCallto // pointer to the callto url to parse...
  93. ){
  94. ASSERT( pszCallto != NULL );
  95. ASSERT( m_ulDestination == INADDR_NONE );
  96. HRESULT hrResult;
  97. if( (m_pszCalltoBuffer = PszAlloc( pszCallto )) == NULL ) // Make a copy that we can modify in place...
  98. {
  99. hrResult = E_OUTOFMEMORY;
  100. }
  101. else if( TrimSzCallto( m_pszCalltoBuffer ) == 0 ) // Remove any leading/trailing blanks...
  102. {
  103. hrResult = NM_CALLERR_PARAM_ERROR; // Entire string was blanks...
  104. }
  105. else
  106. {
  107. hrResult = S_OK;
  108. m_pszParsePos = m_pszCalltoBuffer;
  109. if( !m_bUnescapedAddressOnly )
  110. {
  111. // Skip over "callto:" or "callto://" which mean nothing to us now...
  112. static const TCHAR pszCallto[] = TEXT( "callto:" );
  113. static const TCHAR pszDoubleSlash[] = TEXT( "//" );
  114. if( StrCmpNI_literal( m_pszCalltoBuffer, pszCallto ) )
  115. {
  116. m_pszParsePos = m_pszCalltoBuffer + strlen_literal( pszCallto );
  117. if( StrCmpNI_literal( m_pszParsePos, pszDoubleSlash ) )
  118. {
  119. m_pszParsePos += strlen_literal( pszDoubleSlash );
  120. }
  121. }
  122. int iLength = lstrlen( m_pszCalltoBuffer );
  123. if( m_pszCalltoBuffer[ iLength - 1 ] == '/' )
  124. {
  125. m_pszCalltoBuffer[ iLength - 1 ] = '\0'; // The shell seems to add a trailing slash before calling us...
  126. }
  127. }
  128. // Break the callto into two pieces at the start of the parameters (if any)...
  129. m_pszParameters = StrChr( m_pszCalltoBuffer, '+' );
  130. if( m_pszParameters != NULL )
  131. {
  132. if( m_bUnescapedAddressOnly )
  133. {
  134. // Sorry but '+' not allowed in addressing component...
  135. hrResult = NM_CALLERR_INVALID_ADDRESS;
  136. }
  137. else
  138. {
  139. *m_pszParameters++ = '\0';
  140. }
  141. }
  142. if( hrResult == S_OK )
  143. {
  144. // Make sure we have something left before going on...
  145. if( m_pszParsePos[ 0 ] == '\0' )
  146. {
  147. hrResult = NM_CALLERR_NO_ADDRESS;
  148. }
  149. else
  150. {
  151. // Not really a parsing thing but what we have at this point is conveiniently
  152. // exactly what we want to use for a display name if one wasn't specified so
  153. // save a copy of it before ParseAddress breaks it up into pieces...
  154. if( m_pszDisplayName == NULL )
  155. {
  156. m_pszDisplayName = PszAlloc( m_pszParsePos );
  157. }
  158. if( m_pszParameters != NULL )
  159. {
  160. // Send the parameters off to be parsed...
  161. hrResult = m_Parameters.SetParams( m_pszParameters );
  162. }
  163. if( hrResult == S_OK )
  164. {
  165. // Go parse the addressing component...
  166. hrResult = ParseAddress();
  167. }
  168. }
  169. }
  170. }
  171. return( hrResult );
  172. } // End of CCallto::Parse.
  173. //--------------------------------------------------------------------------//
  174. // CCallto::ParseAddress. //
  175. //--------------------------------------------------------------------------//
  176. HRESULT CCallto::ParseAddress(void)
  177. {
  178. ASSERT( m_pszCalltoBuffer != NULL );
  179. HRESULT hrResult = NM_CALLERR_INVALID_ADDRESS;
  180. if( m_Parameters.GetBooleanParam( TEXT( "h323" ), true ) && inGatekeeperMode() )
  181. {
  182. m_pszAddress = m_pszParsePos;
  183. hrResult = S_OK; // Bless you gatekeeper...
  184. }
  185. else if( StrChr( m_pszParsePos, '=' ) == NULL ) // We're not going to allow the address component to contain an '='...
  186. {
  187. // The address is allowed to be one of these formats...
  188. // (1) string
  189. // (2) server/email
  190. // (3) server:port/email
  191. // This means it may contain at most one ':', at most one '/',
  192. // and given a ':', there must be a following '/'...
  193. TCHAR * const pszColon = StrChr( m_pszParsePos, ':' );
  194. TCHAR * const pszSlash = StrChr( m_pszParsePos, '/' );
  195. if( (pszSlash == NULL) && (pszColon == NULL) )
  196. {
  197. // It's a valid simple (1) string format...
  198. m_pszAddress = m_pszParsePos;
  199. m_pszIlsServer = NULL;
  200. m_uiIlsPort = DEFAULT_LDAP_PORT;
  201. m_pszEmail = m_pszParsePos;
  202. if( m_bUnescapedAddressOnly )
  203. {
  204. hrResult = S_OK; // Done...
  205. }
  206. else
  207. {
  208. // Need to unescape m_pszAddress but not m_pszEmail because it points to the same place...
  209. hrResult = Unescape( m_pszAddress );
  210. }
  211. }
  212. else if( (pszSlash != NULL) && (pszColon == NULL) )
  213. {
  214. if( StrChr( pszSlash + 1, '/' ) == NULL )
  215. {
  216. // No colon and only one slash so it's a valid (2) format
  217. // as long as each side is non zero length...
  218. if( (pszSlash > m_pszParsePos) && (lstrlen( pszSlash ) > 1) )
  219. {
  220. m_pszAddress = TEXT( "" );
  221. m_pszIlsServer = m_pszParsePos;
  222. m_uiIlsPort = DEFAULT_LDAP_PORT;
  223. m_pszEmail = pszSlash + 1;
  224. *pszSlash = '\0';
  225. if( m_bUnescapedAddressOnly )
  226. {
  227. hrResult = S_OK; // Done...
  228. }
  229. else
  230. {
  231. if( (hrResult = Unescape( m_pszIlsServer )) == S_OK )
  232. {
  233. hrResult = Unescape( m_pszEmail );
  234. }
  235. }
  236. }
  237. }
  238. }
  239. else if( (pszSlash != NULL) && (pszColon != NULL) )
  240. {
  241. // Make sure the ':' preceeds the '/' and there's only one of each...
  242. if( (pszColon < pszSlash) && (StrChr( pszSlash + 1, '/') == NULL) && (StrChr( pszColon + 1, ':' ) == NULL) )
  243. {
  244. // One colon and one slash in the correct order so it's a valid (3) format as long
  245. // as all three pieces are non zero length and the port piece is a number...
  246. if( (pszColon > m_pszParsePos) && (pszSlash > pszColon + 1) && (lstrlen( pszSlash ) > 1) )
  247. {
  248. // We're not in gatekeeper mode so break it up into server, port, and email...
  249. m_pszAddress = TEXT( "" );
  250. m_pszIlsServer = m_pszParsePos;
  251. m_pszEmail = pszSlash + 1;
  252. *pszColon = '\0';
  253. *pszSlash = '\0';
  254. if( m_bUnescapedAddressOnly )
  255. {
  256. hrResult = DecimalStringToUINT( pszColon + 1, m_uiIlsPort );
  257. }
  258. else
  259. {
  260. if( (hrResult = Unescape( m_pszIlsServer )) == S_OK )
  261. {
  262. if( (hrResult = Unescape( m_pszEmail )) == S_OK )
  263. {
  264. if( (hrResult = Unescape( pszColon + 1 )) == S_OK )
  265. {
  266. hrResult = DecimalStringToUINT( pszColon + 1, m_uiIlsPort );
  267. }
  268. }
  269. }
  270. }
  271. }
  272. }
  273. }
  274. }
  275. return( hrResult );
  276. } // End of CCallto::ParseAddress.
  277. //--------------------------------------------------------------------------//
  278. // CCallto::Resolve. //
  279. //--------------------------------------------------------------------------//
  280. HRESULT CCallto::Resolve
  281. (
  282. const NM_ADDR_TYPE nmType // callto type to resolve this callto as...
  283. ){
  284. HRESULT hrResult;
  285. // First set our address type...
  286. if( (nmType != NM_ADDR_UNKNOWN) && (nmType != NM_ADDR_CALLTO) )
  287. {
  288. m_nmAddressType = nmType;
  289. }
  290. else
  291. {
  292. const TCHAR * const pszType = m_Parameters.GetParam( TEXT( "type" ), NULL );
  293. if( lstrcmpi( pszType, TEXT( "phone" ) ) == 0 )
  294. {
  295. m_nmAddressType = NM_ADDR_ALIAS_E164;
  296. }
  297. else if( lstrcmpi( pszType, TEXT( "ip" ) ) == 0 )
  298. {
  299. m_nmAddressType = NM_ADDR_IP;
  300. }
  301. else if( lstrcmpi( pszType, TEXT( "host" ) ) == 0 )
  302. {
  303. m_nmAddressType = NM_ADDR_MACHINENAME;
  304. }
  305. else if( lstrcmpi( pszType, TEXT( "directory" ) ) == 0 )
  306. {
  307. m_nmAddressType = NM_ADDR_ULS;
  308. }
  309. else
  310. {
  311. m_nmAddressType = NM_ADDR_UNKNOWN;
  312. }
  313. }
  314. // Then see what we should do with it...
  315. if( m_Parameters.GetBooleanParam( TEXT( "h323" ), true ) && inGatekeeperMode() )
  316. {
  317. if (!IsGatekeeperLoggedOn() && !IsGatekeeperLoggingOn())
  318. {
  319. hrResult = NM_CALLERR_NOT_REGISTERED;
  320. }
  321. else
  322. {
  323. // We can always send anything to the gatekeeper for actual resolution...
  324. if( (hrResult = GetGatekeeperIpAddress( m_ulDestination )) == S_OK )
  325. {
  326. if( m_nmAddressType == NM_ADDR_ALIAS_E164 ) // should this also check for NM_ADDR_H323_GATEWAY???
  327. {
  328. CleanupE164StringEx( m_pszAddress );
  329. }
  330. else
  331. {
  332. m_nmAddressType = NM_ADDR_ALIAS_ID;
  333. }
  334. }
  335. }
  336. }
  337. else
  338. {
  339. switch( m_nmAddressType )
  340. {
  341. case NM_ADDR_ALIAS_ID:
  342. {
  343. hrResult = NM_CALLERR_NO_GATEKEEPER;
  344. }
  345. break;
  346. case NM_ADDR_ALIAS_E164:
  347. case NM_ADDR_H323_GATEWAY:
  348. {
  349. if( inGatewayMode() )
  350. {
  351. if( (hrResult = GetGatewayIpAddress( m_ulDestination )) == S_OK )
  352. {
  353. // Explicit phone types are also still resolvable in gateway mode...
  354. CleanupE164StringEx( m_pszAddress );
  355. }
  356. }
  357. else
  358. {
  359. hrResult = NM_CALLERR_NO_PHONE_SUPPORT;
  360. }
  361. }
  362. break;
  363. case NM_ADDR_IP:
  364. {
  365. if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) != S_OK )
  366. {
  367. hrResult = NM_CALLERR_INVALID_IPADDRESS;
  368. }
  369. }
  370. break;
  371. case NM_ADDR_MACHINENAME:
  372. {
  373. if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) != S_OK )
  374. {
  375. hrResult = NM_CALLERR_HOST_RESOLUTION_FAILED;
  376. }
  377. }
  378. break;
  379. case NM_ADDR_ULS:
  380. {
  381. // Ils types need to be resolved against an ils...
  382. hrResult = GetIpAddressFromIls( m_ulDestination );
  383. }
  384. break;
  385. default:
  386. {
  387. // If we get here the type was unspecified (Automatic or 2.xx)...
  388. // Our order of precedence is ipaddress,hostname,ils,fail...
  389. // We will not try phone since it didn't explicitly have a phone type...
  390. if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) == S_OK )
  391. {
  392. m_nmAddressType = NM_ADDR_IP;
  393. }
  394. else
  395. {
  396. // It's not a valid ip address so try it next as a host name...
  397. if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) == S_OK )
  398. {
  399. m_nmAddressType = NM_ADDR_MACHINENAME;
  400. }
  401. else
  402. {
  403. // It's not a valid host name either so try it finally as an ils lookup...
  404. if ( (hrResult = GetIpAddressFromIls( m_ulDestination )) == S_OK )
  405. {
  406. m_nmAddressType = NM_ADDR_ULS;
  407. }
  408. }
  409. }
  410. }
  411. }
  412. }
  413. return( hrResult );
  414. } // End of CCallto::Resolve.
  415. //--------------------------------------------------------------------------//
  416. // CCallto::PlaceCall. //
  417. //--------------------------------------------------------------------------//
  418. HRESULT CCallto::PlaceCall
  419. (
  420. const TCHAR * const pszCallto, // pointer to the original callto...
  421. const bool bAddToMru, // whether or not save in mru...
  422. const bool bSecure, // whether or not to place the call securely...
  423. INmCall ** const ppInternalCall // out pointer to INmCall * to receive INmCall * generated by placing call...
  424. ){
  425. ASSERT( m_ulDestination != INADDR_NONE );
  426. const TCHAR * const pszConferenceName = m_Parameters.GetParam( TEXT( "conference" ), NULL );
  427. const TCHAR * const pszPassword = m_Parameters.GetParam( TEXT( "password" ), NULL );
  428. const bool bH323 = m_Parameters.GetBooleanParam( TEXT( "h323" ), true );
  429. const bool bAV = m_Parameters.GetBooleanParam( TEXT( "av" ), true );
  430. const bool bData = m_Parameters.GetBooleanParam( TEXT( "data" ), true );
  431. const TCHAR * const pszAlias = NULL;
  432. const TCHAR * const pszE164 = NULL;
  433. HRESULT hrResult;
  434. if( IsLocalIpAddress( m_ulDestination ) )
  435. {
  436. // We don't want to go any further if we are attempting to call ourselves...
  437. hrResult = NM_CALLERR_LOOPBACK;
  438. }
  439. else
  440. {
  441. // Map to old style call flags...
  442. DWORD dwCallFlags = 0;
  443. if( pszConferenceName != NULL )
  444. {
  445. dwCallFlags |= CRPCF_JOIN;
  446. }
  447. if( bH323 )
  448. {
  449. dwCallFlags |= CRPCF_H323CC;
  450. }
  451. if( bSecure )
  452. {
  453. dwCallFlags |= CRPCF_SECURE;
  454. }
  455. else if( bAV )
  456. {
  457. if( g_uMediaCaps & (CAPFLAG_RECV_AUDIO | CAPFLAG_SEND_AUDIO) )
  458. {
  459. dwCallFlags |= CRPCF_AUDIO;
  460. }
  461. if( g_uMediaCaps & (CAPFLAG_RECV_VIDEO | CAPFLAG_SEND_VIDEO) )
  462. {
  463. dwCallFlags |= CRPCF_VIDEO;
  464. }
  465. }
  466. if( bData )
  467. {
  468. dwCallFlags |= CRPCF_DATA | CRPCF_T120;
  469. }
  470. if (((CRPCF_T120 | CRPCF_DATA) != (dwCallFlags & (CRPCF_T120 | CRPCF_DATA))) &&
  471. ((CRPCF_H323CC | CRPCF_AUDIO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_AUDIO))) &&
  472. ((CRPCF_H323CC | CRPCF_VIDEO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_VIDEO))))
  473. {
  474. hrResult = NM_CALLERR_UNKNOWN;
  475. }
  476. CConfRoom * pConfRoom = ::GetConfRoom();
  477. ASSERT(pConfRoom);
  478. if (_Module.IsUIActive())
  479. {
  480. pConfRoom->BringToFront();
  481. }
  482. if( !(pConfRoom->GetMeetingPermissions() & NM_PERMIT_OUTGOINGCALLS) )
  483. {
  484. ERROR_OUT( ("CCallto::PlaceCall: meeting setting permissions do not permit outgoing calls...") );
  485. }
  486. else
  487. {
  488. CCall * pCall = new CCall( pszCallto, m_pszDisplayName, m_nmAddressType, bAddToMru, FALSE );
  489. if( pCall == NULL )
  490. {
  491. ERROR_OUT( ("CCallto::PlaceCall: CCall object not created...") );
  492. hrResult = E_OUTOFMEMORY;
  493. }
  494. else
  495. {
  496. pCall->AddRef(); // Protect against another thread canceling this call
  497. IncrementBusyOperations();
  498. {
  499. const TCHAR * pszCallAlias = (m_nmAddressType == NM_ADDR_ULS)? m_pszEmail: m_pszAddress;
  500. const char * const pszDestination = inet_ntoa( *reinterpret_cast<in_addr *>(&m_ulDestination) );
  501. hrResult = pCall->PlaceCall( dwCallFlags, // call flags bit mask, is there a good reason why they're not named?
  502. m_nmAddressType, // address type.
  503. pszDestination, // setup address.
  504. pszDestination, // destination address.
  505. pszCallAlias, // alias.
  506. NULL, // callto url.
  507. pszConferenceName, // conference name.
  508. pszPassword, // conference password.
  509. NULL ); // user data.
  510. }
  511. DecrementBusyOperations();
  512. if( FAILED( hrResult ) && (pCall->GetState() == NM_CALL_INVALID) )
  513. {
  514. // just release the call to free the data
  515. // otherwise wait for the call state to be changed
  516. pCall->Release();
  517. }
  518. if( ppInternalCall )
  519. {
  520. *ppInternalCall = pCall->GetINmCall();
  521. (*ppInternalCall)->AddRef();
  522. }
  523. pCall->Release();
  524. }
  525. }
  526. }
  527. return( hrResult );
  528. } // End of CCallto::PlaceCall.
  529. //--------------------------------------------------------------------------//
  530. // CCallto::GetValidatedSecurity. //
  531. //--------------------------------------------------------------------------//
  532. HRESULT CCallto::GetValidatedSecurity
  533. (
  534. const bool * const pbSecurityPreference, // pointer to security preference, NULL for none. must be "compatible" with secure param if present...
  535. bool & bValidatedSecurity // out bool reference to recieve validated security setting
  536. ){
  537. HRESULT hrResult;
  538. // First figure out what security setting is desired...
  539. if( pbSecurityPreference != NULL )
  540. {
  541. // A preference was specified so use it.
  542. bValidatedSecurity = *pbSecurityPreference;
  543. }
  544. else
  545. {
  546. // No preference was specified either so check for secure param
  547. // passing the current system settings to use as the default.
  548. bool bUserAlterable;
  549. bool bDefaultSecurity;
  550. CConfRoom::get_securitySettings( bUserAlterable, bDefaultSecurity );
  551. bValidatedSecurity = m_Parameters.GetBooleanParam( TEXT( "secure" ), bDefaultSecurity );
  552. }
  553. // And then validate that the desired setting is allowed...
  554. int iSecurityPolicy = ConfPolicies::GetSecurityLevel();
  555. if( (bValidatedSecurity && (iSecurityPolicy == DISABLED_POL_SECURITY)) ||
  556. ((!bValidatedSecurity) && (iSecurityPolicy == REQUIRED_POL_SECURITY)) )
  557. {
  558. // There was a mismatch between what they want and what they can have...
  559. // Set security to what they can have and return mismatch error...
  560. bValidatedSecurity = (iSecurityPolicy == REQUIRED_POL_SECURITY);
  561. hrResult = NM_CALLERR_SECURITY_MISMATCH;
  562. }
  563. else
  564. {
  565. hrResult = S_OK;
  566. }
  567. return( hrResult );
  568. } // End of CCallto::GetValidatedSecurity.
  569. //--------------------------------------------------------------------------//
  570. // CCallto::inGatekeeperMode. //
  571. //--------------------------------------------------------------------------//
  572. bool CCallto::inGatekeeperMode(void)
  573. {
  574. return(ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() );
  575. } // End of CCallto::inGatekeeperMode.
  576. //--------------------------------------------------------------------------//
  577. // CCallto::SetGatekeeperEnabled. //
  578. //--------------------------------------------------------------------------//
  579. void CCallto::SetGatekeeperEnabled
  580. (
  581. const bool bEnabled // new Gatekeeper state
  582. ){
  583. m_bGatekeeperEnabled = bEnabled;
  584. } // End of CCallto::SetGatekeeperEnabled.
  585. //--------------------------------------------------------------------------//
  586. // CCallto::SetGatekeeperName. //
  587. //--------------------------------------------------------------------------//
  588. HRESULT CCallto::SetGatekeeperName
  589. (
  590. const TCHAR * const pszGatekeeperName // pointer to new Gatekeeper name
  591. ){
  592. if( lstrcmpi( pszGatekeeperName, m_pszGatekeeperName ) != 0 )
  593. {
  594. delete [] m_pszGatekeeperName;
  595. m_pszGatekeeperName = PszAlloc( pszGatekeeperName );
  596. m_ulGatekeeperAddress = INADDR_NONE; // We reset this cached value when the name changes...
  597. }
  598. ASSERT( (m_pszGatekeeperName != NULL) || (pszGatekeeperName == NULL) );
  599. return( ((pszGatekeeperName != NULL) && (m_pszGatekeeperName == NULL))? E_OUTOFMEMORY: S_OK );
  600. } // End of CCallto::SetGatekeeperName.
  601. //--------------------------------------------------------------------------//
  602. // CCallto::GetGatekeeperIpAddress. //
  603. //--------------------------------------------------------------------------//
  604. HRESULT CCallto::GetGatekeeperIpAddress
  605. (
  606. unsigned long & ulIpAddress // out unsigned long reference to receive gatekeeper IP address
  607. ){
  608. ASSERT( m_pszGatekeeperName != NULL );
  609. if( m_ulGatekeeperAddress == INADDR_NONE )
  610. {
  611. GetIpAddressFromHostName( m_pszGatekeeperName, m_ulGatekeeperAddress );
  612. }
  613. ulIpAddress = m_ulGatekeeperAddress;
  614. return( (m_ulGatekeeperAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEKEEPER );
  615. } // End of CCallto::GetGatekeeperIpAddress.
  616. //--------------------------------------------------------------------------//
  617. // CCallto::inGatewayMode. //
  618. //--------------------------------------------------------------------------//
  619. bool CCallto::inGatewayMode(void)
  620. {
  621. return( (m_bGatewayEnabled && (m_pszGatewayName != NULL)) || (m_Parameters.GetParam( TEXT( "gateway" ), NULL ) != NULL) );
  622. } // End of CCallto::inGatewayMode.
  623. //--------------------------------------------------------------------------//
  624. // CCallto::SetGatewayEnabled. //
  625. //--------------------------------------------------------------------------//
  626. void CCallto::SetGatewayEnabled
  627. (
  628. const bool bEnabled // new Gateway state
  629. ){
  630. m_bGatewayEnabled = bEnabled;
  631. } // End of CCallto::SetGatewayEnabled.
  632. //--------------------------------------------------------------------------//
  633. // CCallto::SetGatewayName. //
  634. //--------------------------------------------------------------------------//
  635. HRESULT CCallto::SetGatewayName
  636. (
  637. const TCHAR * const pszGatewayName // pointer to new Gateway name
  638. ){
  639. if( lstrcmpi( pszGatewayName, m_pszGatewayName ) != 0 )
  640. {
  641. delete [] m_pszGatewayName;
  642. m_pszGatewayName = PszAlloc( pszGatewayName );
  643. m_ulGatewayAddress = INADDR_NONE; // We reset this cached value when the name changes...
  644. }
  645. ASSERT( (m_pszGatewayName != NULL) || (pszGatewayName == NULL) );
  646. return( ((pszGatewayName != NULL) && (m_pszGatewayName == NULL))? E_OUTOFMEMORY: S_OK );
  647. } // End of CCallto::SetGatewayName.
  648. //--------------------------------------------------------------------------//
  649. // CCallto::GetGatewayIpAddress. //
  650. //--------------------------------------------------------------------------//
  651. HRESULT CCallto::GetGatewayIpAddress
  652. (
  653. unsigned long & ulIpAddress // out unsigned long reference to receive gateway IP address
  654. ){
  655. const TCHAR * const pszGateway = m_Parameters.GetParam( TEXT( "gateway" ), NULL );
  656. if( pszGateway != NULL )
  657. {
  658. // A non-default gateway was specified with this callto...
  659. GetIpAddressFromHostName( pszGateway, ulIpAddress );
  660. }
  661. else
  662. {
  663. if( m_ulGatewayAddress == INADDR_NONE )
  664. {
  665. GetIpAddressFromHostName( m_pszGatewayName, m_ulGatewayAddress );
  666. }
  667. ulIpAddress = m_ulGatewayAddress;
  668. }
  669. return( (ulIpAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEWAY );
  670. } // End of CCallto::GetGatewayIpAddress.
  671. //--------------------------------------------------------------------------//
  672. // CCallto::SetIlsServerName. //
  673. //--------------------------------------------------------------------------//
  674. HRESULT CCallto::SetIlsServerName
  675. (
  676. const TCHAR * const pszServerName // pointer to new default Ils server name
  677. ){
  678. delete [] m_pszDefaultIlsServerName;
  679. m_pszDefaultIlsServerName = PszAlloc( pszServerName );
  680. ASSERT( (m_pszDefaultIlsServerName != NULL) || (pszServerName == NULL) );
  681. return( ((pszServerName != NULL) && (m_pszDefaultIlsServerName == NULL))? E_OUTOFMEMORY: S_OK );
  682. } // End of CCallto::SetIlsServerName.
  683. //--------------------------------------------------------------------------//
  684. // CCallto::GetIpAddressFromIls. //
  685. //--------------------------------------------------------------------------//
  686. HRESULT CCallto::GetIpAddressFromIls
  687. (
  688. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  689. ){
  690. ASSERT( m_pszEmail != NULL );
  691. HRESULT hrResult;
  692. const TCHAR * const pszActiveIlsServer = (m_pszIlsServer != NULL)? m_pszIlsServer: m_pszDefaultIlsServerName;
  693. if( pszActiveIlsServer == NULL )
  694. {
  695. hrResult = NM_CALLERR_NO_ILS;
  696. }
  697. if( g_pLDAP == NULL )
  698. {
  699. g_pLDAP = new CNmLDAP;
  700. }
  701. ASSERT( g_pLDAP != NULL );
  702. if( g_pLDAP == NULL )
  703. {
  704. hrResult = E_OUTOFMEMORY;
  705. }
  706. else
  707. {
  708. TCHAR szIpAddress[ 64 ];
  709. hrResult = g_pLDAP->ResolveUser( m_pszEmail, pszActiveIlsServer, szIpAddress, ARRAY_ELEMENTS( szIpAddress ), m_uiIlsPort );
  710. if( hrResult == S_OK )
  711. {
  712. // Verify that it gave back a good IP address...
  713. hrResult = GetIpAddress( szIpAddress, ulIpAddress );
  714. }
  715. if( hrResult != S_OK )
  716. {
  717. hrResult = NM_CALLERR_ILS_RESOLUTION_FAILED;
  718. }
  719. }
  720. return( hrResult );
  721. } // End of CCallto::GetIpAddressFromIls.
  722. //--------------------------------------------------------------------------//
  723. // CCallto::DoUserValidation //
  724. //--------------------------------------------------------------------------//
  725. bool CCallto::DoUserValidation(const TCHAR * const pszCallto)
  726. {
  727. bool bRet = false;
  728. CCallto callto;
  729. TCHAR szCaption[MAX_PATH];
  730. TCHAR *pszText = NULL;
  731. // Parse input string to retrieve display name
  732. if(FAILED(callto.Parse(pszCallto)))
  733. goto Exit;
  734. // Verify we have a valid display name
  735. if(NULL == callto.m_pszDisplayName)
  736. goto Exit;
  737. // Allocate message buffer. MAX_PATH represents max format string size
  738. pszText = new TCHAR[_tcslen(callto.m_pszDisplayName) + MAX_PATH];
  739. if(NULL == pszText)
  740. goto Exit;
  741. // Compose message string
  742. if(!FLoadString1(IDS_JOIN_PERMISSION, pszText, callto.m_pszDisplayName))
  743. goto Exit;
  744. if(!FLoadString(IDS_MSGBOX_TITLE, szCaption, CCHMAX(szCaption)))
  745. goto Exit;
  746. // Display message box
  747. if(IDOK != MessageBox(NULL, pszText, szCaption, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST))
  748. goto Exit;
  749. bRet = true;
  750. Exit:
  751. // Free allocated buffer
  752. if(NULL != pszText)
  753. {
  754. delete [] pszText;
  755. }
  756. return bRet;
  757. }
  758. //--------------------------------------------------------------------------//
  759. // CCalltoParams::CCalltoParams. //
  760. //--------------------------------------------------------------------------//
  761. CCalltoParams::CCalltoParams(void):
  762. m_chNameDelimiter( '+' ),
  763. m_chValueDelimiter( '=' ),
  764. m_pszParams( NULL ),
  765. m_iCount( 0 )
  766. {
  767. } // End of CCalltoParams::CCalltoParams.
  768. //--------------------------------------------------------------------------//
  769. // CCalltoParams::CCalltoParams. //
  770. //--------------------------------------------------------------------------//
  771. CCalltoParams::~CCalltoParams()
  772. {
  773. delete [] m_pszParams;
  774. } // End of CCalltoParams::~CCalltoParams.
  775. //--------------------------------------------------------------------------//
  776. // CCalltoParams::SetParams. //
  777. //--------------------------------------------------------------------------//
  778. HRESULT
  779. CCalltoParams::SetParams
  780. (
  781. const TCHAR * const pszParams
  782. ){
  783. HRESULT hrResult;
  784. delete [] m_pszParams;
  785. m_pszParams = NULL;
  786. m_iCount = 0;
  787. if( pszParams == NULL )
  788. {
  789. hrResult = S_OK;
  790. }
  791. else if( (m_pszParams = new TCHAR [ lstrlen( pszParams ) + 1 ]) == NULL )
  792. {
  793. hrResult = E_OUTOFMEMORY;
  794. }
  795. else
  796. {
  797. hrResult = S_OK;
  798. lstrcpy( m_pszParams, pszParams );
  799. TCHAR * pszPos = m_pszParams;
  800. TCHAR * pszEnd;
  801. while( (*pszPos != '\0') && (m_iCount < ARRAY_ELEMENTS( m_pszNames )) )
  802. {
  803. m_pszNames[ m_iCount ] = pszPos;
  804. m_pszValues[ m_iCount ] = NULL;
  805. while( *pszPos != '\0' )
  806. {
  807. if( (*pszPos == '+') || (*pszPos == '=') )
  808. {
  809. break;
  810. }
  811. pszPos = CharNext( pszPos );
  812. }
  813. if( *pszPos != '=' )
  814. {
  815. // Valueless param...
  816. if( m_pszNames[ m_iCount ] == pszPos )
  817. {
  818. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have zero length param names...
  819. break;
  820. }
  821. pszEnd = pszPos;
  822. pszPos = CharNext( pszPos );
  823. if( (pszPos != pszEnd) && (*pszPos == '\0') )
  824. {
  825. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
  826. break;
  827. }
  828. *pszEnd = '\0';
  829. m_iCount++;
  830. }
  831. else
  832. {
  833. // Value follows...
  834. pszEnd = pszPos;
  835. pszPos = CharNext( pszPos );
  836. *pszEnd = '\0';
  837. m_pszValues[ m_iCount ] = pszPos;
  838. while( *pszPos != '\0' )
  839. {
  840. if( (*pszPos == '+') || (*pszPos == '=') )
  841. {
  842. break;
  843. }
  844. pszPos = CharNext( pszPos );
  845. }
  846. if( (*pszPos == '=') || (m_pszValues[ m_iCount ] == pszPos) )
  847. {
  848. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have '=' or zero length param names...
  849. break;
  850. }
  851. pszEnd = pszPos;
  852. pszPos = CharNext( pszPos );
  853. if( (pszPos != pszEnd) && (*pszPos == '\0') )
  854. {
  855. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
  856. break;
  857. }
  858. *pszEnd = '\0';
  859. m_iCount++;
  860. }
  861. }
  862. if( hrResult == S_OK )
  863. {
  864. if( m_iCount == ARRAY_ELEMENTS( m_pszNames ) )
  865. {
  866. hrResult = NM_CALLERR_PARAM_ERROR; // Too many params...
  867. }
  868. else
  869. {
  870. for( int nn = 0; nn < m_iCount; nn++ )
  871. {
  872. if( (hrResult = Unescape( m_pszNames[ nn ] )) != S_OK )
  873. {
  874. break;
  875. }
  876. if( m_pszValues[ nn ] != NULL )
  877. {
  878. if( (hrResult = Unescape( m_pszValues[ nn ] )) != S_OK )
  879. {
  880. break;
  881. }
  882. }
  883. }
  884. }
  885. }
  886. }
  887. return( hrResult );
  888. } // End of CCalltoParams::SetParams.
  889. //--------------------------------------------------------------------------//
  890. // CCalltoParams::GetParam. //
  891. //--------------------------------------------------------------------------//
  892. const TCHAR * const
  893. CCalltoParams::GetParam
  894. (
  895. const TCHAR * const pszName,
  896. const TCHAR * const pszDefaultValue
  897. ) const
  898. {
  899. ASSERT( pszName != NULL );
  900. TCHAR * pszValue = NULL;
  901. if( m_pszParams != NULL )
  902. {
  903. for( int nn = 0; nn < m_iCount; nn++ )
  904. {
  905. if( lstrcmpi( pszName, m_pszNames[ nn ] ) == 0 )
  906. {
  907. pszValue = m_pszValues[ nn ];
  908. break;
  909. }
  910. }
  911. }
  912. return( (pszValue == NULL)? pszDefaultValue: pszValue );
  913. } // End of CCalltoParams::GetParam.
  914. //--------------------------------------------------------------------------//
  915. // CCalltoParams::GetBooleanParam. //
  916. //--------------------------------------------------------------------------//
  917. bool
  918. CCalltoParams::GetBooleanParam
  919. (
  920. const TCHAR * const pszParamName,
  921. const bool bDefaultValue
  922. ) const
  923. {
  924. ASSERT( pszParamName != NULL );
  925. const TCHAR * const pszValue = GetParam( pszParamName, NULL );
  926. bool bResult;
  927. if( pszValue == NULL ) // this parameter wasn't specified...
  928. {
  929. bResult = bDefaultValue;
  930. }
  931. else if( *pszValue == 0 ) // this parameter was specified but with no value...
  932. {
  933. bResult = true;
  934. }
  935. else if( (lstrcmpi( pszValue, TEXT( "1" ) ) == 0) ||
  936. (lstrcmpi( pszValue, TEXT( "true" ) ) == 0) ||
  937. (lstrcmpi( pszValue, TEXT( "y" ) ) == 0) ||
  938. (lstrcmpi( pszValue, TEXT( "yes" ) ) == 0) ||
  939. (lstrcmpi( pszValue, TEXT( "on" ) ) == 0) )
  940. {
  941. bResult = true;
  942. }
  943. else if( (lstrcmpi( pszValue, TEXT( "0" ) ) == 0) ||
  944. (lstrcmpi( pszValue, TEXT( "false" ) ) == 0) ||
  945. (lstrcmpi( pszValue, TEXT( "n" ) ) == 0) ||
  946. (lstrcmpi( pszValue, TEXT( "no" ) ) == 0) ||
  947. (lstrcmpi( pszValue, TEXT( "off" ) ) == 0) )
  948. {
  949. bResult = false;
  950. }
  951. else
  952. {
  953. bResult = bDefaultValue;
  954. }
  955. return( bResult );
  956. } // End of CCalltoParams::GetBooleanParam.
  957. //--------------------------------------------------------------------------//
  958. // IsLocalIpAddress. //
  959. //--------------------------------------------------------------------------//
  960. bool IsLocalIpAddress
  961. (
  962. const unsigned long ulIpAddress // IP Address to verify is not local
  963. ){
  964. bool bResult = (ulIpAddress == INADDR_LOOPBACK); // First check right away if it's the prefined loop back ip address...
  965. if( !bResult )
  966. {
  967. char szHostName[ MAX_PATH ];
  968. // Get our own local hostname...
  969. if( gethostname( szHostName, ARRAY_ELEMENTS( szHostName ) ) == SOCKET_ERROR )
  970. {
  971. WARNING_OUT( ("IsLocalIpAddress: gethostname() failed with error=%s", PszWSALastError()) );
  972. }
  973. else
  974. {
  975. // Now find out which IP addresses are associated with it...
  976. HOSTENT * pHostEnt = gethostbyname( szHostName );
  977. if( pHostEnt == NULL )
  978. {
  979. WARNING_OUT( ("IsLocalIpAddress: gethostbyname() failed with error=%s", PszWSALastError()) );
  980. }
  981. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  982. {
  983. WARNING_OUT( ("IsLocalIpAddress: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  984. }
  985. else
  986. {
  987. ASSERT( reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list) != NULL );
  988. // Compare all the IP addresses associated with this machine to see if any of them match the one specified...
  989. for( unsigned long ** ppIpAddress = reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list); *ppIpAddress != NULL; ppIpAddress++ )
  990. {
  991. if( **ppIpAddress == ulIpAddress )
  992. {
  993. bResult = true;
  994. break;
  995. }
  996. }
  997. }
  998. }
  999. }
  1000. return( bResult );
  1001. } // End of IsLocalIpAddress.
  1002. //--------------------------------------------------------------------------//
  1003. // DecimalStringToUINT. //
  1004. //--------------------------------------------------------------------------//
  1005. HRESULT DecimalStringToUINT
  1006. (
  1007. const TCHAR * const pszDecimalString, // Pointer to string to convert...
  1008. unsigned int & uiValue // out unsigned int reference to receive converted value...
  1009. ){
  1010. ASSERT( pszDecimalString != NULL );
  1011. HRESULT hrResult;
  1012. if( lstrlen( pszDecimalString ) > 10 )
  1013. {
  1014. hrResult = E_INVALIDARG; // Limit it to billions....
  1015. }
  1016. else
  1017. {
  1018. hrResult = S_OK;
  1019. const TCHAR * pszDigit;
  1020. for( pszDigit = pszDecimalString, uiValue = 0; *pszDigit != '\0'; pszDigit = CharNext( pszDigit ) )
  1021. {
  1022. if( (*pszDigit < '0') || (*pszDigit > '9') )
  1023. {
  1024. // There's a non digit character in the string so fail...
  1025. hrResult = E_INVALIDARG;
  1026. break;
  1027. }
  1028. uiValue = (uiValue * 10) + *pszDigit - '0';
  1029. }
  1030. }
  1031. return( hrResult );
  1032. } // End of DecimalStringToUINT.
  1033. //--------------------------------------------------------------------------//
  1034. // TrimSzCallto. //
  1035. //--------------------------------------------------------------------------//
  1036. int TrimSzCallto
  1037. (
  1038. TCHAR * const pszSrc // Pointer to string to trim blanks from in place...
  1039. ){
  1040. ASSERT( pszSrc != NULL );
  1041. TCHAR * pszFirst;
  1042. int iResult;
  1043. for( pszFirst = pszSrc; *pszFirst == ' '; pszFirst = CharNext( pszFirst ) ){};
  1044. if( *pszFirst == '\0' )
  1045. {
  1046. *pszSrc = '\0';
  1047. iResult = 0;
  1048. }
  1049. else
  1050. {
  1051. TCHAR * pszLast;
  1052. TCHAR * psz;
  1053. for( pszLast = pszFirst, psz = pszFirst; *psz != '\0'; psz = CharNext( psz ) )
  1054. {
  1055. if( *psz != ' ' )
  1056. {
  1057. pszLast = psz;
  1058. }
  1059. }
  1060. pszLast = CharNext( pszLast );
  1061. *pszLast = '\0';
  1062. lstrcpy( pszSrc, pszFirst );
  1063. iResult = lstrlen( pszSrc );
  1064. }
  1065. return( iResult );
  1066. } // End of TrimSzCallto.
  1067. //--------------------------------------------------------------------------//
  1068. // GetIpAddress. //
  1069. //--------------------------------------------------------------------------//
  1070. HRESULT GetIpAddress
  1071. (
  1072. const TCHAR * const pszIpAddress, // pointer to dotted IP address string
  1073. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  1074. ){
  1075. ASSERT( pszIpAddress != NULL );
  1076. ulIpAddress = INADDR_NONE;
  1077. int ipByte = 0;
  1078. int parts = 0;
  1079. const TCHAR * ptr = pszIpAddress;
  1080. bool newPart = true;
  1081. bool result = true;
  1082. while( result && (*ptr != NULL) && (parts <= 4) )
  1083. {
  1084. if( (*ptr >= '0') && (*ptr <= '9') )
  1085. {
  1086. if( newPart )
  1087. {
  1088. parts++;
  1089. newPart = false;
  1090. }
  1091. ipByte = (ipByte * 10) + (*ptr - '0');
  1092. if( ipByte > 255 )
  1093. {
  1094. result = false;
  1095. }
  1096. }
  1097. else if( *ptr == '.' )
  1098. {
  1099. newPart = true;
  1100. ipByte = 0;
  1101. }
  1102. else
  1103. {
  1104. result = false;
  1105. }
  1106. ptr++;
  1107. }
  1108. if( result && (parts == 4) )
  1109. {
  1110. #if !defined( UNICODE )
  1111. ulIpAddress = inet_addr( pszIpAddress );
  1112. #else
  1113. char * ansiIPAddress;
  1114. int size;
  1115. size = WideCharToMultiByte( CP_ACP, // code page
  1116. 0, // performance and mapping flags
  1117. ipAddress, // address of wide-character string
  1118. -1, // number of characters in string
  1119. NULL, // address of buffer for new string
  1120. 0, // size of buffer
  1121. NULL, // address of default for unmappable characters
  1122. NULL ); // address of flag set when default char. used
  1123. if( (ansiIPAddress = new char [ size ]) != NULL )
  1124. {
  1125. size = WideCharToMultiByte( CP_ACP, // code page
  1126. 0, // performance and mapping flags
  1127. pszIpAddress, // address of wide-character string
  1128. -1, // number of characters in string
  1129. ansiIPAddress, // address of buffer for new string
  1130. size, // size of buffer
  1131. NULL, // address of default for unmappable characters
  1132. NULL ); // address of flag set when default char. used
  1133. if( size != 0 )
  1134. {
  1135. ulIpAddress = inet_addr( ansiIPAddress );
  1136. }
  1137. delete [] ansiIPAddress;
  1138. }
  1139. #endif // !defined( UNICODE )
  1140. }
  1141. return( (ulIpAddress != INADDR_NONE)? S_OK: E_FAIL );
  1142. } // End of GetIpAddress.
  1143. //--------------------------------------------------------------------------//
  1144. // GetIpAddressFromHostName. //
  1145. //--------------------------------------------------------------------------//
  1146. HRESULT GetIpAddressFromHostName
  1147. (
  1148. const TCHAR * const pszName, // pointer to host name to get IP address of
  1149. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  1150. ){
  1151. ASSERT( pszName != NULL );
  1152. HRESULT hrResult = E_FAIL;
  1153. if( pszName[ 0 ] == '\0' )
  1154. {
  1155. ulIpAddress = INADDR_NONE;
  1156. }
  1157. else if( (hrResult = GetIpAddress( pszName, ulIpAddress )) != S_OK )
  1158. {
  1159. // Wasn't already in dotted IP address form...
  1160. HOSTENT * pHostEnt;
  1161. #if !defined( UNICODE )
  1162. TCHAR * pszOemName = new TCHAR [ lstrlen( pszName ) + 1 ];
  1163. if( pszOemName == NULL )
  1164. {
  1165. hrResult = E_OUTOFMEMORY;
  1166. }
  1167. else
  1168. {
  1169. lstrcpy( pszOemName, pszName );
  1170. CharUpper ( pszOemName );
  1171. CharToOem( pszOemName, pszOemName );
  1172. pHostEnt = gethostbyname( pszOemName );
  1173. if( pHostEnt == NULL )
  1174. {
  1175. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
  1176. }
  1177. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  1178. {
  1179. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  1180. }
  1181. else
  1182. {
  1183. if( pHostEnt->h_addr_list[ 0 ] != NULL )
  1184. {
  1185. ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
  1186. hrResult = S_OK;
  1187. }
  1188. }
  1189. delete [] pszOemName;
  1190. }
  1191. #else
  1192. // Need to figure out OEM'ing the name...
  1193. char * pszMultiByteName;
  1194. int iSize;
  1195. iSize = WideCharToMultiByte( CP_ACP, // code page
  1196. 0, // performance and mapping flags
  1197. pszName, // address of wide-character string
  1198. -1, // number of characters in string
  1199. NULL, // address of buffer for new string
  1200. 0, // size of buffer
  1201. NULL, // address of default for unmappable characters
  1202. NULL ); // address of flag set when default char. used
  1203. if( (pszMultiByteName = new char [ iSize ]) == NULL )
  1204. {
  1205. hrResult = E_OUTOFMEMORY;
  1206. }
  1207. else
  1208. {
  1209. iSize = WideCharToMultiByte( CP_ACP, // code page
  1210. 0, // performance and mapping flags
  1211. pszName, // address of wide-character string
  1212. -1, // number of characters in string
  1213. pszMultiByteName, // address of buffer for new string
  1214. iSize, // size of buffer
  1215. NULL, // address of default for unmappable characters
  1216. NULL ); // address of flag set when default char. used
  1217. if( iSize != 0 )
  1218. {
  1219. pHostEnt = gethostbyname( ansiHost );
  1220. if( pHostEnt == NULL )
  1221. {
  1222. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
  1223. }
  1224. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  1225. {
  1226. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  1227. }
  1228. else
  1229. {
  1230. if( pHostEnt->h_addr_list[ 0 ] != NULL )
  1231. {
  1232. ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
  1233. hrResult = S_OK;
  1234. }
  1235. }
  1236. }
  1237. delete [] pszMultiByteName;
  1238. }
  1239. #endif // !defined( UNICODE )
  1240. }
  1241. return( hrResult );
  1242. } // End of GetIpAddressFromHostName.
  1243. //--------------------------------------------------------------------------//
  1244. // IsPhoneNumber. //
  1245. //--------------------------------------------------------------------------//
  1246. bool IsPhoneNumber
  1247. (
  1248. const TCHAR * pszPhone // string to check for invalid phone number characters
  1249. ){
  1250. ASSERT( pszPhone != NULL );
  1251. ASSERT( pszPhone[ 0 ] != '\0' );
  1252. bool bResult = true;
  1253. while( pszPhone[ 0 ] != '\0' )
  1254. {
  1255. switch( pszPhone[ 0 ] )
  1256. {
  1257. case '0':
  1258. case '1':
  1259. case '2':
  1260. case '3':
  1261. case '4':
  1262. case '5':
  1263. case '6':
  1264. case '7':
  1265. case '8':
  1266. case '9':
  1267. case '(':
  1268. case ')':
  1269. case '#':
  1270. case '*':
  1271. case '-':
  1272. case ',':
  1273. case ' ':
  1274. break;
  1275. default:
  1276. bResult = false;
  1277. break;
  1278. }
  1279. pszPhone++;
  1280. }
  1281. return( bResult );
  1282. } // End of IsPhoneNumber.
  1283. //--------------------------------------------------------------------------//
  1284. // bCanCallAsPhoneNumber. //
  1285. //--------------------------------------------------------------------------//
  1286. bool bCanCallAsPhoneNumber
  1287. (
  1288. const TCHAR * const pszPhone
  1289. ){
  1290. ASSERT( pszPhone != NULL );
  1291. ASSERT( pszPhone[ 0 ] != '\0' );
  1292. bool bResult = FALSE;
  1293. if( IsPhoneNumber( pszPhone ) )
  1294. {
  1295. if( ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() )
  1296. {
  1297. bResult = true;
  1298. }
  1299. else
  1300. {
  1301. RegEntry reConf( CONFERENCING_KEY, HKEY_CURRENT_USER );
  1302. bResult = (reConf.GetNumber( REGVAL_USE_H323_GATEWAY ) != 0);
  1303. }
  1304. }
  1305. return( bResult );
  1306. } // End of bCanCallAsPhoneNumber.
  1307. //--------------------------------------------------------------------------//
  1308. // unescape. //
  1309. //--------------------------------------------------------------------------//
  1310. HRESULT Unescape
  1311. (
  1312. TCHAR * const pszSrc // pointer to string to unescape in place
  1313. ){
  1314. ASSERT( pszSrc != NULL );
  1315. TCHAR * pszPercentSign;
  1316. HRESULT hrResult;
  1317. for( hrResult = S_OK, pszPercentSign = pszSrc; pszPercentSign != NULL; )
  1318. {
  1319. if( (pszPercentSign = StrChr( pszPercentSign, '%' )) != NULL )
  1320. {
  1321. TCHAR chHighNibble = pszPercentSign[ 1 ];
  1322. if( ((chHighNibble >= '0') && (chHighNibble <= '9')) ||
  1323. ((chHighNibble >= 'a') && (chHighNibble <= 'f')) ||
  1324. ((chHighNibble >= 'A') && (chHighNibble <= 'F')) )
  1325. {
  1326. TCHAR chLowNibble = pszPercentSign[ 2 ];
  1327. if( ((chLowNibble >= '0') && (chLowNibble <= '9')) ||
  1328. ((chLowNibble >= 'a') && (chLowNibble <= 'f')) ||
  1329. ((chLowNibble >= 'A') && (chLowNibble <= 'F')) )
  1330. {
  1331. chHighNibble = ((chHighNibble >= '0') && (chHighNibble <= '9'))? chHighNibble - '0':
  1332. ((chHighNibble >= 'a') && (chHighNibble <= 'f'))? chHighNibble - 'a' + 10: chHighNibble - 'A' + 10;
  1333. chLowNibble = ((chLowNibble >= '0') && (chLowNibble <= '9'))? chLowNibble - '0':
  1334. ((chLowNibble >= 'a') && (chLowNibble <= 'f'))? chLowNibble - 'a' + 10: chLowNibble - 'A' + 10;
  1335. *pszPercentSign++ = (chHighNibble << 4) | chLowNibble;
  1336. lstrcpy( pszPercentSign, &pszPercentSign[ 2 ] );
  1337. }
  1338. else
  1339. {
  1340. hrResult = NM_CALLERR_UNESCAPE_ERROR;
  1341. break;
  1342. }
  1343. }
  1344. else
  1345. {
  1346. hrResult = NM_CALLERR_UNESCAPE_ERROR;
  1347. break;
  1348. }
  1349. }
  1350. }
  1351. return( hrResult );
  1352. } // End of Unescape.