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.

1654 lines
45 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 pszCallto2[] = TEXT( "callto:" );
  113. static const TCHAR pszDoubleSlash[] = TEXT( "//" );
  114. if( StrCmpNI_literal( m_pszCalltoBuffer, pszCallto2 ) )
  115. {
  116. m_pszParsePos = m_pszCalltoBuffer + strlen_literal( pszCallto2 );
  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(NULL != pszType)
  294. {
  295. if( lstrcmpi( pszType, TEXT( "phone" ) ) == 0 )
  296. {
  297. m_nmAddressType = NM_ADDR_ALIAS_E164;
  298. }
  299. else if( lstrcmpi( pszType, TEXT( "ip" ) ) == 0 )
  300. {
  301. m_nmAddressType = NM_ADDR_IP;
  302. }
  303. else if( lstrcmpi( pszType, TEXT( "host" ) ) == 0 )
  304. {
  305. m_nmAddressType = NM_ADDR_MACHINENAME;
  306. }
  307. else if( lstrcmpi( pszType, TEXT( "directory" ) ) == 0 )
  308. {
  309. m_nmAddressType = NM_ADDR_ULS;
  310. }
  311. else
  312. {
  313. m_nmAddressType = NM_ADDR_UNKNOWN;
  314. }
  315. }
  316. else
  317. {
  318. m_nmAddressType = NM_ADDR_UNKNOWN;
  319. }
  320. }
  321. // Then see what we should do with it...
  322. if( m_Parameters.GetBooleanParam( TEXT( "h323" ), true ) && inGatekeeperMode() )
  323. {
  324. if (!IsGatekeeperLoggedOn() && !IsGatekeeperLoggingOn())
  325. {
  326. hrResult = NM_CALLERR_NOT_REGISTERED;
  327. }
  328. else
  329. {
  330. // We can always send anything to the gatekeeper for actual resolution...
  331. if( (hrResult = GetGatekeeperIpAddress( m_ulDestination )) == S_OK )
  332. {
  333. if( m_nmAddressType == NM_ADDR_ALIAS_E164 ) // should this also check for NM_ADDR_H323_GATEWAY???
  334. {
  335. CleanupE164StringEx( m_pszAddress );
  336. }
  337. else
  338. {
  339. m_nmAddressType = NM_ADDR_ALIAS_ID;
  340. }
  341. }
  342. }
  343. }
  344. else
  345. {
  346. switch( m_nmAddressType )
  347. {
  348. case NM_ADDR_ALIAS_ID:
  349. {
  350. hrResult = NM_CALLERR_NO_GATEKEEPER;
  351. }
  352. break;
  353. case NM_ADDR_ALIAS_E164:
  354. case NM_ADDR_H323_GATEWAY:
  355. {
  356. if( inGatewayMode() )
  357. {
  358. if( (hrResult = GetGatewayIpAddress( m_ulDestination )) == S_OK )
  359. {
  360. // Explicit phone types are also still resolvable in gateway mode...
  361. CleanupE164StringEx( m_pszAddress );
  362. }
  363. }
  364. else
  365. {
  366. hrResult = NM_CALLERR_NO_PHONE_SUPPORT;
  367. }
  368. }
  369. break;
  370. case NM_ADDR_IP:
  371. {
  372. if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) != S_OK )
  373. {
  374. hrResult = NM_CALLERR_INVALID_IPADDRESS;
  375. }
  376. }
  377. break;
  378. case NM_ADDR_MACHINENAME:
  379. {
  380. if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) != S_OK )
  381. {
  382. hrResult = NM_CALLERR_HOST_RESOLUTION_FAILED;
  383. }
  384. }
  385. break;
  386. case NM_ADDR_ULS:
  387. {
  388. // Ils types need to be resolved against an ils...
  389. hrResult = GetIpAddressFromIls( m_ulDestination );
  390. }
  391. break;
  392. default:
  393. {
  394. // If we get here the type was unspecified (Automatic or 2.xx)...
  395. // Our order of precedence is ipaddress,hostname,ils,fail...
  396. // We will not try phone since it didn't explicitly have a phone type...
  397. if( (hrResult = GetIpAddress( m_pszAddress, m_ulDestination )) == S_OK )
  398. {
  399. m_nmAddressType = NM_ADDR_IP;
  400. }
  401. else
  402. {
  403. // It's not a valid ip address so try it next as a host name...
  404. if( (hrResult = GetIpAddressFromHostName( m_pszAddress, m_ulDestination )) == S_OK )
  405. {
  406. m_nmAddressType = NM_ADDR_MACHINENAME;
  407. }
  408. else
  409. {
  410. // It's not a valid host name either so try it finally as an ils lookup...
  411. if ( (hrResult = GetIpAddressFromIls( m_ulDestination )) == S_OK )
  412. {
  413. m_nmAddressType = NM_ADDR_ULS;
  414. }
  415. }
  416. }
  417. }
  418. }
  419. }
  420. return( hrResult );
  421. } // End of CCallto::Resolve.
  422. //--------------------------------------------------------------------------//
  423. // CCallto::PlaceCall. //
  424. //--------------------------------------------------------------------------//
  425. HRESULT CCallto::PlaceCall
  426. (
  427. const TCHAR * const pszCallto, // pointer to the original callto...
  428. const bool bAddToMru, // whether or not save in mru...
  429. const bool bSecure, // whether or not to place the call securely...
  430. INmCall ** const ppInternalCall // out pointer to INmCall * to receive INmCall * generated by placing call...
  431. ){
  432. ASSERT( m_ulDestination != INADDR_NONE );
  433. const TCHAR * const pszConferenceName = m_Parameters.GetParam( TEXT( "conference" ), NULL );
  434. const TCHAR * const pszPassword = m_Parameters.GetParam( TEXT( "password" ), NULL );
  435. const bool bH323 = m_Parameters.GetBooleanParam( TEXT( "h323" ), true );
  436. const bool bAV = m_Parameters.GetBooleanParam( TEXT( "av" ), true );
  437. const bool bData = m_Parameters.GetBooleanParam( TEXT( "data" ), true );
  438. const TCHAR * const pszAlias = NULL;
  439. const TCHAR * const pszE164 = NULL;
  440. HRESULT hrResult;
  441. if( IsLocalIpAddress( m_ulDestination ) )
  442. {
  443. // We don't want to go any further if we are attempting to call ourselves...
  444. hrResult = NM_CALLERR_LOOPBACK;
  445. }
  446. else
  447. {
  448. // Map to old style call flags...
  449. DWORD dwCallFlags = 0;
  450. if( pszConferenceName != NULL )
  451. {
  452. dwCallFlags |= CRPCF_JOIN;
  453. }
  454. if( bH323 )
  455. {
  456. dwCallFlags |= CRPCF_H323CC;
  457. }
  458. if( bSecure )
  459. {
  460. dwCallFlags |= CRPCF_SECURE;
  461. }
  462. else if( bAV )
  463. {
  464. if( g_uMediaCaps & (CAPFLAG_RECV_AUDIO | CAPFLAG_SEND_AUDIO) )
  465. {
  466. dwCallFlags |= CRPCF_AUDIO;
  467. }
  468. if( g_uMediaCaps & (CAPFLAG_RECV_VIDEO | CAPFLAG_SEND_VIDEO) )
  469. {
  470. dwCallFlags |= CRPCF_VIDEO;
  471. }
  472. }
  473. if( bData )
  474. {
  475. dwCallFlags |= CRPCF_DATA | CRPCF_T120;
  476. }
  477. if (((CRPCF_T120 | CRPCF_DATA) != (dwCallFlags & (CRPCF_T120 | CRPCF_DATA))) &&
  478. ((CRPCF_H323CC | CRPCF_AUDIO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_AUDIO))) &&
  479. ((CRPCF_H323CC | CRPCF_VIDEO) != ( dwCallFlags & (CRPCF_H323CC | CRPCF_VIDEO))))
  480. {
  481. hrResult = NM_CALLERR_UNKNOWN;
  482. }
  483. CConfRoom * pConfRoom = ::GetConfRoom();
  484. ASSERT(pConfRoom);
  485. if (_Module.IsUIActive())
  486. {
  487. pConfRoom->BringToFront();
  488. }
  489. if( !(pConfRoom->GetMeetingPermissions() & NM_PERMIT_OUTGOINGCALLS) )
  490. {
  491. ERROR_OUT( ("CCallto::PlaceCall: meeting setting permissions do not permit outgoing calls...") );
  492. }
  493. else
  494. {
  495. CCall * pCall = new CCall( pszCallto, m_pszDisplayName, m_nmAddressType, bAddToMru, FALSE );
  496. if( pCall == NULL )
  497. {
  498. ERROR_OUT( ("CCallto::PlaceCall: CCall object not created...") );
  499. hrResult = E_OUTOFMEMORY;
  500. }
  501. else
  502. {
  503. pCall->AddRef(); // Protect against another thread canceling this call
  504. IncrementBusyOperations();
  505. {
  506. const TCHAR * pszCallAlias = (m_nmAddressType == NM_ADDR_ULS)? m_pszEmail: m_pszAddress;
  507. const char * const pszDestination = inet_ntoa( *reinterpret_cast<in_addr *>(&m_ulDestination) );
  508. hrResult = pCall->PlaceCall( dwCallFlags, // call flags bit mask, is there a good reason why they're not named?
  509. m_nmAddressType, // address type.
  510. pszDestination, // setup address.
  511. pszDestination, // destination address.
  512. pszCallAlias, // alias.
  513. NULL, // callto url.
  514. pszConferenceName, // conference name.
  515. pszPassword, // conference password.
  516. NULL ); // user data.
  517. }
  518. DecrementBusyOperations();
  519. if( FAILED( hrResult ) && (pCall->GetState() == NM_CALL_INVALID) )
  520. {
  521. // just release the call to free the data
  522. // otherwise wait for the call state to be changed
  523. pCall->Release();
  524. }
  525. if( ppInternalCall )
  526. {
  527. *ppInternalCall = pCall->GetINmCall();
  528. (*ppInternalCall)->AddRef();
  529. }
  530. pCall->Release();
  531. }
  532. }
  533. }
  534. return( hrResult );
  535. } // End of CCallto::PlaceCall.
  536. //--------------------------------------------------------------------------//
  537. // CCallto::GetValidatedSecurity. //
  538. //--------------------------------------------------------------------------//
  539. HRESULT CCallto::GetValidatedSecurity
  540. (
  541. const bool * const pbSecurityPreference, // pointer to security preference, NULL for none. must be "compatible" with secure param if present...
  542. bool & bValidatedSecurity // out bool reference to recieve validated security setting
  543. ){
  544. HRESULT hrResult;
  545. // First figure out what security setting is desired...
  546. if( pbSecurityPreference != NULL )
  547. {
  548. // A preference was specified so use it.
  549. bValidatedSecurity = *pbSecurityPreference;
  550. }
  551. else
  552. {
  553. // No preference was specified either so check for secure param
  554. // passing the current system settings to use as the default.
  555. bool bUserAlterable;
  556. bool bDefaultSecurity;
  557. CConfRoom::get_securitySettings( bUserAlterable, bDefaultSecurity );
  558. bValidatedSecurity = m_Parameters.GetBooleanParam( TEXT( "secure" ), bDefaultSecurity );
  559. }
  560. // And then validate that the desired setting is allowed...
  561. int iSecurityPolicy = ConfPolicies::GetSecurityLevel();
  562. if( (bValidatedSecurity && (iSecurityPolicy == DISABLED_POL_SECURITY)) ||
  563. ((!bValidatedSecurity) && (iSecurityPolicy == REQUIRED_POL_SECURITY)) )
  564. {
  565. // There was a mismatch between what they want and what they can have...
  566. // Set security to what they can have and return mismatch error...
  567. bValidatedSecurity = (iSecurityPolicy == REQUIRED_POL_SECURITY);
  568. hrResult = NM_CALLERR_SECURITY_MISMATCH;
  569. }
  570. else
  571. {
  572. hrResult = S_OK;
  573. }
  574. return( hrResult );
  575. } // End of CCallto::GetValidatedSecurity.
  576. //--------------------------------------------------------------------------//
  577. // CCallto::inGatekeeperMode. //
  578. //--------------------------------------------------------------------------//
  579. bool CCallto::inGatekeeperMode(void)
  580. {
  581. return(ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() );
  582. } // End of CCallto::inGatekeeperMode.
  583. //--------------------------------------------------------------------------//
  584. // CCallto::SetGatekeeperEnabled. //
  585. //--------------------------------------------------------------------------//
  586. void CCallto::SetGatekeeperEnabled
  587. (
  588. const bool bEnabled // new Gatekeeper state
  589. ){
  590. m_bGatekeeperEnabled = bEnabled;
  591. } // End of CCallto::SetGatekeeperEnabled.
  592. //--------------------------------------------------------------------------//
  593. // CCallto::SetGatekeeperName. //
  594. //--------------------------------------------------------------------------//
  595. HRESULT CCallto::SetGatekeeperName
  596. (
  597. const TCHAR * const pszGatekeeperName // pointer to new Gatekeeper name
  598. ){
  599. if( lstrcmpi( pszGatekeeperName, m_pszGatekeeperName ) != 0 )
  600. {
  601. delete [] m_pszGatekeeperName;
  602. m_pszGatekeeperName = PszAlloc( pszGatekeeperName );
  603. m_ulGatekeeperAddress = INADDR_NONE; // We reset this cached value when the name changes...
  604. }
  605. ASSERT( (m_pszGatekeeperName != NULL) || (pszGatekeeperName == NULL) );
  606. return( ((pszGatekeeperName != NULL) && (m_pszGatekeeperName == NULL))? E_OUTOFMEMORY: S_OK );
  607. } // End of CCallto::SetGatekeeperName.
  608. //--------------------------------------------------------------------------//
  609. // CCallto::GetGatekeeperIpAddress. //
  610. //--------------------------------------------------------------------------//
  611. HRESULT CCallto::GetGatekeeperIpAddress
  612. (
  613. unsigned long & ulIpAddress // out unsigned long reference to receive gatekeeper IP address
  614. ){
  615. ASSERT( m_pszGatekeeperName != NULL );
  616. if( m_ulGatekeeperAddress == INADDR_NONE )
  617. {
  618. GetIpAddressFromHostName( m_pszGatekeeperName, m_ulGatekeeperAddress );
  619. }
  620. ulIpAddress = m_ulGatekeeperAddress;
  621. return( (m_ulGatekeeperAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEKEEPER );
  622. } // End of CCallto::GetGatekeeperIpAddress.
  623. //--------------------------------------------------------------------------//
  624. // CCallto::inGatewayMode. //
  625. //--------------------------------------------------------------------------//
  626. bool CCallto::inGatewayMode(void)
  627. {
  628. return( (m_bGatewayEnabled && (m_pszGatewayName != NULL)) || (m_Parameters.GetParam( TEXT( "gateway" ), NULL ) != NULL) );
  629. } // End of CCallto::inGatewayMode.
  630. //--------------------------------------------------------------------------//
  631. // CCallto::SetGatewayEnabled. //
  632. //--------------------------------------------------------------------------//
  633. void CCallto::SetGatewayEnabled
  634. (
  635. const bool bEnabled // new Gateway state
  636. ){
  637. m_bGatewayEnabled = bEnabled;
  638. } // End of CCallto::SetGatewayEnabled.
  639. //--------------------------------------------------------------------------//
  640. // CCallto::SetGatewayName. //
  641. //--------------------------------------------------------------------------//
  642. HRESULT CCallto::SetGatewayName
  643. (
  644. const TCHAR * const pszGatewayName // pointer to new Gateway name
  645. ){
  646. if( lstrcmpi( pszGatewayName, m_pszGatewayName ) != 0 )
  647. {
  648. delete [] m_pszGatewayName;
  649. m_pszGatewayName = PszAlloc( pszGatewayName );
  650. m_ulGatewayAddress = INADDR_NONE; // We reset this cached value when the name changes...
  651. }
  652. ASSERT( (m_pszGatewayName != NULL) || (pszGatewayName == NULL) );
  653. return( ((pszGatewayName != NULL) && (m_pszGatewayName == NULL))? E_OUTOFMEMORY: S_OK );
  654. } // End of CCallto::SetGatewayName.
  655. //--------------------------------------------------------------------------//
  656. // CCallto::GetGatewayIpAddress. //
  657. //--------------------------------------------------------------------------//
  658. HRESULT CCallto::GetGatewayIpAddress
  659. (
  660. unsigned long & ulIpAddress // out unsigned long reference to receive gateway IP address
  661. ){
  662. const TCHAR * const pszGateway = m_Parameters.GetParam( TEXT( "gateway" ), NULL );
  663. if( pszGateway != NULL )
  664. {
  665. // A non-default gateway was specified with this callto...
  666. GetIpAddressFromHostName( pszGateway, ulIpAddress );
  667. }
  668. else
  669. {
  670. if( m_ulGatewayAddress == INADDR_NONE )
  671. {
  672. GetIpAddressFromHostName( m_pszGatewayName, m_ulGatewayAddress );
  673. }
  674. ulIpAddress = m_ulGatewayAddress;
  675. }
  676. return( (ulIpAddress != INADDR_NONE)? S_OK: NM_CALLERR_NO_GATEWAY );
  677. } // End of CCallto::GetGatewayIpAddress.
  678. //--------------------------------------------------------------------------//
  679. // CCallto::SetIlsServerName. //
  680. //--------------------------------------------------------------------------//
  681. HRESULT CCallto::SetIlsServerName
  682. (
  683. const TCHAR * const pszServerName // pointer to new default Ils server name
  684. ){
  685. delete [] m_pszDefaultIlsServerName;
  686. m_pszDefaultIlsServerName = PszAlloc( pszServerName );
  687. ASSERT( (m_pszDefaultIlsServerName != NULL) || (pszServerName == NULL) );
  688. return( ((pszServerName != NULL) && (m_pszDefaultIlsServerName == NULL))? E_OUTOFMEMORY: S_OK );
  689. } // End of CCallto::SetIlsServerName.
  690. //--------------------------------------------------------------------------//
  691. // CCallto::GetIpAddressFromIls. //
  692. //--------------------------------------------------------------------------//
  693. HRESULT CCallto::GetIpAddressFromIls
  694. (
  695. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  696. ){
  697. ASSERT( m_pszEmail != NULL );
  698. HRESULT hrResult;
  699. const TCHAR * const pszActiveIlsServer = (m_pszIlsServer != NULL)? m_pszIlsServer: m_pszDefaultIlsServerName;
  700. if( pszActiveIlsServer == NULL )
  701. {
  702. hrResult = NM_CALLERR_NO_ILS;
  703. }
  704. if( g_pLDAP == NULL )
  705. {
  706. g_pLDAP = new CNmLDAP;
  707. }
  708. ASSERT( g_pLDAP != NULL );
  709. if( g_pLDAP == NULL )
  710. {
  711. hrResult = E_OUTOFMEMORY;
  712. }
  713. else
  714. {
  715. TCHAR szIpAddress[ 64 ];
  716. hrResult = g_pLDAP->ResolveUser( m_pszEmail, pszActiveIlsServer, szIpAddress, ARRAY_ELEMENTS( szIpAddress ), m_uiIlsPort );
  717. if( hrResult == S_OK )
  718. {
  719. // Verify that it gave back a good IP address...
  720. hrResult = GetIpAddress( szIpAddress, ulIpAddress );
  721. }
  722. if( hrResult != S_OK )
  723. {
  724. hrResult = NM_CALLERR_ILS_RESOLUTION_FAILED;
  725. }
  726. }
  727. return( hrResult );
  728. } // End of CCallto::GetIpAddressFromIls.
  729. //--------------------------------------------------------------------------//
  730. // CCallto::DoUserValidation //
  731. //--------------------------------------------------------------------------//
  732. bool CCallto::DoUserValidation(const TCHAR * const pszCallto)
  733. {
  734. bool bRet = false;
  735. CCallto callto;
  736. TCHAR szCaption[MAX_PATH];
  737. TCHAR *pszText = NULL;
  738. // Parse input string to retrieve display name
  739. if(FAILED(callto.Parse(pszCallto)))
  740. goto Exit;
  741. // Verify we have a valid display name
  742. if(NULL == callto.m_pszDisplayName)
  743. goto Exit;
  744. // Allocate message buffer. MAX_PATH represents max format string size
  745. pszText = new TCHAR[_tcslen(callto.m_pszDisplayName) + MAX_PATH];
  746. if(NULL == pszText)
  747. goto Exit;
  748. // Compose message string
  749. if(!FLoadString1(IDS_JOIN_PERMISSION, pszText, callto.m_pszDisplayName))
  750. goto Exit;
  751. if(!FLoadString(IDS_MSGBOX_TITLE, szCaption, CCHMAX(szCaption)))
  752. goto Exit;
  753. // Display message box
  754. if(IDOK != MessageBox(NULL, pszText, szCaption, MB_ICONWARNING | MB_OKCANCEL | MB_TOPMOST))
  755. goto Exit;
  756. bRet = true;
  757. Exit:
  758. // Free allocated buffer
  759. if(NULL != pszText)
  760. {
  761. delete [] pszText;
  762. }
  763. return bRet;
  764. }
  765. //--------------------------------------------------------------------------//
  766. // CCalltoParams::CCalltoParams. //
  767. //--------------------------------------------------------------------------//
  768. CCalltoParams::CCalltoParams(void):
  769. m_chNameDelimiter( '+' ),
  770. m_chValueDelimiter( '=' ),
  771. m_pszParams( NULL ),
  772. m_iCount( 0 )
  773. {
  774. } // End of CCalltoParams::CCalltoParams.
  775. //--------------------------------------------------------------------------//
  776. // CCalltoParams::CCalltoParams. //
  777. //--------------------------------------------------------------------------//
  778. CCalltoParams::~CCalltoParams()
  779. {
  780. delete [] m_pszParams;
  781. } // End of CCalltoParams::~CCalltoParams.
  782. //--------------------------------------------------------------------------//
  783. // CCalltoParams::SetParams. //
  784. //--------------------------------------------------------------------------//
  785. HRESULT
  786. CCalltoParams::SetParams
  787. (
  788. const TCHAR * const pszParams
  789. ){
  790. HRESULT hrResult;
  791. delete [] m_pszParams;
  792. m_pszParams = NULL;
  793. m_iCount = 0;
  794. if( pszParams == NULL )
  795. {
  796. hrResult = S_OK;
  797. }
  798. else if( (m_pszParams = new TCHAR [ lstrlen( pszParams ) + 1 ]) == NULL )
  799. {
  800. hrResult = E_OUTOFMEMORY;
  801. }
  802. else
  803. {
  804. hrResult = S_OK;
  805. lstrcpy( m_pszParams, pszParams );
  806. TCHAR * pszPos = m_pszParams;
  807. TCHAR * pszEnd;
  808. while( (*pszPos != '\0') && (m_iCount < ARRAY_ELEMENTS( m_pszNames )) )
  809. {
  810. m_pszNames[ m_iCount ] = pszPos;
  811. m_pszValues[ m_iCount ] = NULL;
  812. while( *pszPos != '\0' )
  813. {
  814. if( (*pszPos == '+') || (*pszPos == '=') )
  815. {
  816. break;
  817. }
  818. pszPos = CharNext( pszPos );
  819. }
  820. if( *pszPos != '=' )
  821. {
  822. // Valueless param...
  823. if( m_pszNames[ m_iCount ] == pszPos )
  824. {
  825. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have zero length param names...
  826. break;
  827. }
  828. pszEnd = pszPos;
  829. pszPos = CharNext( pszPos );
  830. if( (pszPos != pszEnd) && (*pszPos == '\0') )
  831. {
  832. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
  833. break;
  834. }
  835. *pszEnd = '\0';
  836. m_iCount++;
  837. }
  838. else
  839. {
  840. // Value follows...
  841. pszEnd = pszPos;
  842. pszPos = CharNext( pszPos );
  843. *pszEnd = '\0';
  844. m_pszValues[ m_iCount ] = pszPos;
  845. while( *pszPos != '\0' )
  846. {
  847. if( (*pszPos == '+') || (*pszPos == '=') )
  848. {
  849. break;
  850. }
  851. pszPos = CharNext( pszPos );
  852. }
  853. if( (*pszPos == '=') || (m_pszValues[ m_iCount ] == pszPos) )
  854. {
  855. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have '=' or zero length param names...
  856. break;
  857. }
  858. pszEnd = pszPos;
  859. pszPos = CharNext( pszPos );
  860. if( (pszPos != pszEnd) && (*pszPos == '\0') )
  861. {
  862. hrResult = NM_CALLERR_PARAM_ERROR; // Can't have trailing + or =...
  863. break;
  864. }
  865. *pszEnd = '\0';
  866. m_iCount++;
  867. }
  868. }
  869. if( hrResult == S_OK )
  870. {
  871. if( m_iCount == ARRAY_ELEMENTS( m_pszNames ) )
  872. {
  873. hrResult = NM_CALLERR_PARAM_ERROR; // Too many params...
  874. }
  875. else
  876. {
  877. for( int nn = 0; nn < m_iCount; nn++ )
  878. {
  879. if( (hrResult = Unescape( m_pszNames[ nn ] )) != S_OK )
  880. {
  881. break;
  882. }
  883. if( m_pszValues[ nn ] != NULL )
  884. {
  885. if( (hrResult = Unescape( m_pszValues[ nn ] )) != S_OK )
  886. {
  887. break;
  888. }
  889. }
  890. }
  891. }
  892. }
  893. }
  894. return( hrResult );
  895. } // End of CCalltoParams::SetParams.
  896. //--------------------------------------------------------------------------//
  897. // CCalltoParams::GetParam. //
  898. //--------------------------------------------------------------------------//
  899. const TCHAR * const
  900. CCalltoParams::GetParam
  901. (
  902. const TCHAR * const pszName,
  903. const TCHAR * const pszDefaultValue
  904. ) const
  905. {
  906. ASSERT( pszName != NULL );
  907. TCHAR * pszValue = NULL;
  908. if( m_pszParams != NULL )
  909. {
  910. for( int nn = 0; nn < m_iCount; nn++ )
  911. {
  912. if( lstrcmpi( pszName, m_pszNames[ nn ] ) == 0 )
  913. {
  914. pszValue = m_pszValues[ nn ];
  915. break;
  916. }
  917. }
  918. }
  919. return( (pszValue == NULL)? pszDefaultValue: pszValue );
  920. } // End of CCalltoParams::GetParam.
  921. //--------------------------------------------------------------------------//
  922. // CCalltoParams::GetBooleanParam. //
  923. //--------------------------------------------------------------------------//
  924. bool
  925. CCalltoParams::GetBooleanParam
  926. (
  927. const TCHAR * const pszParamName,
  928. const bool bDefaultValue
  929. ) const
  930. {
  931. ASSERT( pszParamName != NULL );
  932. const TCHAR * const pszValue = GetParam( pszParamName, NULL );
  933. bool bResult;
  934. if( pszValue == NULL ) // this parameter wasn't specified...
  935. {
  936. bResult = bDefaultValue;
  937. }
  938. else if( *pszValue == 0 ) // this parameter was specified but with no value...
  939. {
  940. bResult = true;
  941. }
  942. else if( (lstrcmpi( pszValue, TEXT( "1" ) ) == 0) ||
  943. (lstrcmpi( pszValue, TEXT( "true" ) ) == 0) ||
  944. (lstrcmpi( pszValue, TEXT( "y" ) ) == 0) ||
  945. (lstrcmpi( pszValue, TEXT( "yes" ) ) == 0) ||
  946. (lstrcmpi( pszValue, TEXT( "on" ) ) == 0) )
  947. {
  948. bResult = true;
  949. }
  950. else if( (lstrcmpi( pszValue, TEXT( "0" ) ) == 0) ||
  951. (lstrcmpi( pszValue, TEXT( "false" ) ) == 0) ||
  952. (lstrcmpi( pszValue, TEXT( "n" ) ) == 0) ||
  953. (lstrcmpi( pszValue, TEXT( "no" ) ) == 0) ||
  954. (lstrcmpi( pszValue, TEXT( "off" ) ) == 0) )
  955. {
  956. bResult = false;
  957. }
  958. else
  959. {
  960. bResult = bDefaultValue;
  961. }
  962. return( bResult );
  963. } // End of CCalltoParams::GetBooleanParam.
  964. //--------------------------------------------------------------------------//
  965. // IsLocalIpAddress. //
  966. //--------------------------------------------------------------------------//
  967. bool IsLocalIpAddress
  968. (
  969. const unsigned long ulIpAddress // IP Address to verify is not local
  970. ){
  971. bool bResult = (ulIpAddress == INADDR_LOOPBACK); // First check right away if it's the prefined loop back ip address...
  972. if( !bResult )
  973. {
  974. char szHostName[ MAX_PATH ];
  975. // Get our own local hostname...
  976. if( gethostname( szHostName, ARRAY_ELEMENTS( szHostName ) ) == SOCKET_ERROR )
  977. {
  978. WARNING_OUT( ("IsLocalIpAddress: gethostname() failed with error=%s", PszWSALastError()) );
  979. }
  980. else
  981. {
  982. // Now find out which IP addresses are associated with it...
  983. HOSTENT * pHostEnt = gethostbyname( szHostName );
  984. if( pHostEnt == NULL )
  985. {
  986. WARNING_OUT( ("IsLocalIpAddress: gethostbyname() failed with error=%s", PszWSALastError()) );
  987. }
  988. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  989. {
  990. WARNING_OUT( ("IsLocalIpAddress: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  991. }
  992. else
  993. {
  994. ASSERT( reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list) != NULL );
  995. // Compare all the IP addresses associated with this machine to see if any of them match the one specified...
  996. for( unsigned long ** ppIpAddress = reinterpret_cast<unsigned long **>(pHostEnt->h_addr_list); *ppIpAddress != NULL; ppIpAddress++ )
  997. {
  998. if( **ppIpAddress == ulIpAddress )
  999. {
  1000. bResult = true;
  1001. break;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. return( bResult );
  1008. } // End of IsLocalIpAddress.
  1009. //--------------------------------------------------------------------------//
  1010. // DecimalStringToUINT. //
  1011. //--------------------------------------------------------------------------//
  1012. HRESULT DecimalStringToUINT
  1013. (
  1014. const TCHAR * const pszDecimalString, // Pointer to string to convert...
  1015. unsigned int & uiValue // out unsigned int reference to receive converted value...
  1016. ){
  1017. ASSERT( pszDecimalString != NULL );
  1018. HRESULT hrResult;
  1019. if( lstrlen( pszDecimalString ) > 10 )
  1020. {
  1021. hrResult = E_INVALIDARG; // Limit it to billions....
  1022. }
  1023. else
  1024. {
  1025. hrResult = S_OK;
  1026. const TCHAR * pszDigit;
  1027. for( pszDigit = pszDecimalString, uiValue = 0; *pszDigit != '\0'; pszDigit = CharNext( pszDigit ) )
  1028. {
  1029. if( (*pszDigit < '0') || (*pszDigit > '9') )
  1030. {
  1031. // There's a non digit character in the string so fail...
  1032. hrResult = E_INVALIDARG;
  1033. break;
  1034. }
  1035. uiValue = (uiValue * 10) + *pszDigit - '0';
  1036. }
  1037. }
  1038. return( hrResult );
  1039. } // End of DecimalStringToUINT.
  1040. //--------------------------------------------------------------------------//
  1041. // TrimSzCallto. //
  1042. //--------------------------------------------------------------------------//
  1043. int TrimSzCallto
  1044. (
  1045. TCHAR * const pszSrc // Pointer to string to trim blanks from in place...
  1046. ){
  1047. ASSERT( pszSrc != NULL );
  1048. TCHAR * pszFirst;
  1049. int iResult;
  1050. for( pszFirst = pszSrc; *pszFirst == ' '; pszFirst = CharNext( pszFirst ) ){};
  1051. if( *pszFirst == '\0' )
  1052. {
  1053. *pszSrc = '\0';
  1054. iResult = 0;
  1055. }
  1056. else
  1057. {
  1058. TCHAR * pszLast;
  1059. TCHAR * psz;
  1060. for( pszLast = pszFirst, psz = pszFirst; *psz != '\0'; psz = CharNext( psz ) )
  1061. {
  1062. if( *psz != ' ' )
  1063. {
  1064. pszLast = psz;
  1065. }
  1066. }
  1067. pszLast = CharNext( pszLast );
  1068. *pszLast = '\0';
  1069. lstrcpy( pszSrc, pszFirst );
  1070. iResult = lstrlen( pszSrc );
  1071. }
  1072. return( iResult );
  1073. } // End of TrimSzCallto.
  1074. //--------------------------------------------------------------------------//
  1075. // GetIpAddress. //
  1076. //--------------------------------------------------------------------------//
  1077. HRESULT GetIpAddress
  1078. (
  1079. const TCHAR * const pszIpAddress, // pointer to dotted IP address string
  1080. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  1081. ){
  1082. ASSERT( pszIpAddress != NULL );
  1083. ulIpAddress = INADDR_NONE;
  1084. int ipByte = 0;
  1085. int parts = 0;
  1086. const TCHAR * ptr = pszIpAddress;
  1087. bool newPart = true;
  1088. bool result = true;
  1089. while( result && (*ptr != NULL) && (parts <= 4) )
  1090. {
  1091. if( (*ptr >= '0') && (*ptr <= '9') )
  1092. {
  1093. if( newPart )
  1094. {
  1095. parts++;
  1096. newPart = false;
  1097. }
  1098. ipByte = (ipByte * 10) + (*ptr - '0');
  1099. if( ipByte > 255 )
  1100. {
  1101. result = false;
  1102. }
  1103. }
  1104. else if( *ptr == '.' )
  1105. {
  1106. newPart = true;
  1107. ipByte = 0;
  1108. }
  1109. else
  1110. {
  1111. result = false;
  1112. }
  1113. ptr++;
  1114. }
  1115. if( result && (parts == 4) )
  1116. {
  1117. #if !defined( UNICODE )
  1118. ulIpAddress = inet_addr( pszIpAddress );
  1119. #else
  1120. char * ansiIPAddress;
  1121. int size;
  1122. size = WideCharToMultiByte( CP_ACP, // code page
  1123. 0, // performance and mapping flags
  1124. ipAddress, // address of wide-character string
  1125. -1, // number of characters in string
  1126. NULL, // address of buffer for new string
  1127. 0, // size of buffer
  1128. NULL, // address of default for unmappable characters
  1129. NULL ); // address of flag set when default char. used
  1130. if( (ansiIPAddress = new char [ size ]) != NULL )
  1131. {
  1132. size = WideCharToMultiByte( CP_ACP, // code page
  1133. 0, // performance and mapping flags
  1134. pszIpAddress, // address of wide-character string
  1135. -1, // number of characters in string
  1136. ansiIPAddress, // address of buffer for new string
  1137. size, // size of buffer
  1138. NULL, // address of default for unmappable characters
  1139. NULL ); // address of flag set when default char. used
  1140. if( size != 0 )
  1141. {
  1142. ulIpAddress = inet_addr( ansiIPAddress );
  1143. }
  1144. delete [] ansiIPAddress;
  1145. }
  1146. #endif // !defined( UNICODE )
  1147. }
  1148. return( (ulIpAddress != INADDR_NONE)? S_OK: E_FAIL );
  1149. } // End of GetIpAddress.
  1150. //--------------------------------------------------------------------------//
  1151. // GetIpAddressFromHostName. //
  1152. //--------------------------------------------------------------------------//
  1153. HRESULT GetIpAddressFromHostName
  1154. (
  1155. const TCHAR * const pszName, // pointer to host name to get IP address of
  1156. unsigned long & ulIpAddress // out unsigned long reference to receive IP address
  1157. ){
  1158. ASSERT( pszName != NULL );
  1159. HRESULT hrResult = E_FAIL;
  1160. if( pszName[ 0 ] == '\0' )
  1161. {
  1162. ulIpAddress = INADDR_NONE;
  1163. }
  1164. else if( (hrResult = GetIpAddress( pszName, ulIpAddress )) != S_OK )
  1165. {
  1166. // Wasn't already in dotted IP address form...
  1167. HOSTENT * pHostEnt;
  1168. #if !defined( UNICODE )
  1169. TCHAR * pszOemName = new TCHAR [ lstrlen( pszName ) + 1 ];
  1170. if( pszOemName == NULL )
  1171. {
  1172. hrResult = E_OUTOFMEMORY;
  1173. }
  1174. else
  1175. {
  1176. lstrcpy( pszOemName, pszName );
  1177. CharUpper ( pszOemName );
  1178. CharToOem( pszOemName, pszOemName );
  1179. pHostEnt = gethostbyname( pszOemName );
  1180. if( pHostEnt == NULL )
  1181. {
  1182. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
  1183. }
  1184. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  1185. {
  1186. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  1187. }
  1188. else
  1189. {
  1190. if( pHostEnt->h_addr_list[ 0 ] != NULL )
  1191. {
  1192. ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
  1193. hrResult = S_OK;
  1194. }
  1195. }
  1196. delete [] pszOemName;
  1197. }
  1198. #else
  1199. // Need to figure out OEM'ing the name...
  1200. char * pszMultiByteName;
  1201. int iSize;
  1202. iSize = WideCharToMultiByte( CP_ACP, // code page
  1203. 0, // performance and mapping flags
  1204. pszName, // address of wide-character string
  1205. -1, // number of characters in string
  1206. NULL, // address of buffer for new string
  1207. 0, // size of buffer
  1208. NULL, // address of default for unmappable characters
  1209. NULL ); // address of flag set when default char. used
  1210. if( (pszMultiByteName = new char [ iSize ]) == NULL )
  1211. {
  1212. hrResult = E_OUTOFMEMORY;
  1213. }
  1214. else
  1215. {
  1216. iSize = WideCharToMultiByte( CP_ACP, // code page
  1217. 0, // performance and mapping flags
  1218. pszName, // address of wide-character string
  1219. -1, // number of characters in string
  1220. pszMultiByteName, // address of buffer for new string
  1221. iSize, // size of buffer
  1222. NULL, // address of default for unmappable characters
  1223. NULL ); // address of flag set when default char. used
  1224. if( iSize != 0 )
  1225. {
  1226. pHostEnt = gethostbyname( ansiHost );
  1227. if( pHostEnt == NULL )
  1228. {
  1229. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() failed with error=%s", PszWSALastError()) );
  1230. }
  1231. else if( (pHostEnt->h_addrtype != AF_INET) || (pHostEnt->h_length != sizeof( ulIpAddress )) )
  1232. {
  1233. WARNING_OUT( ("GetIpAddressFromHostName: gethostbyname() returned unexpected address type: 0x%08X (%d)", pHostEnt->h_addrtype, pHostEnt->h_addrtype) );
  1234. }
  1235. else
  1236. {
  1237. if( pHostEnt->h_addr_list[ 0 ] != NULL )
  1238. {
  1239. ulIpAddress = *reinterpret_cast<unsigned long *>(pHostEnt->h_addr_list[ 0 ]); // Just use the first IP address
  1240. hrResult = S_OK;
  1241. }
  1242. }
  1243. }
  1244. delete [] pszMultiByteName;
  1245. }
  1246. #endif // !defined( UNICODE )
  1247. }
  1248. return( hrResult );
  1249. } // End of GetIpAddressFromHostName.
  1250. //--------------------------------------------------------------------------//
  1251. // IsPhoneNumber. //
  1252. //--------------------------------------------------------------------------//
  1253. bool IsPhoneNumber
  1254. (
  1255. const TCHAR * pszPhone // string to check for invalid phone number characters
  1256. ){
  1257. ASSERT( pszPhone != NULL );
  1258. ASSERT( pszPhone[ 0 ] != '\0' );
  1259. bool bResult = true;
  1260. while( pszPhone[ 0 ] != '\0' )
  1261. {
  1262. switch( pszPhone[ 0 ] )
  1263. {
  1264. case '0':
  1265. case '1':
  1266. case '2':
  1267. case '3':
  1268. case '4':
  1269. case '5':
  1270. case '6':
  1271. case '7':
  1272. case '8':
  1273. case '9':
  1274. case '(':
  1275. case ')':
  1276. case '#':
  1277. case '*':
  1278. case '-':
  1279. case ',':
  1280. case ' ':
  1281. break;
  1282. default:
  1283. bResult = false;
  1284. break;
  1285. }
  1286. pszPhone++;
  1287. }
  1288. return( bResult );
  1289. } // End of IsPhoneNumber.
  1290. //--------------------------------------------------------------------------//
  1291. // bCanCallAsPhoneNumber. //
  1292. //--------------------------------------------------------------------------//
  1293. bool bCanCallAsPhoneNumber
  1294. (
  1295. const TCHAR * const pszPhone
  1296. ){
  1297. ASSERT( pszPhone != NULL );
  1298. ASSERT( pszPhone[ 0 ] != '\0' );
  1299. bool bResult = FALSE;
  1300. if( IsPhoneNumber( pszPhone ) )
  1301. {
  1302. if( ConfPolicies::CallingMode_GateKeeper == ConfPolicies::GetCallingMode() )
  1303. {
  1304. bResult = true;
  1305. }
  1306. else
  1307. {
  1308. RegEntry reConf( CONFERENCING_KEY, HKEY_CURRENT_USER );
  1309. bResult = (reConf.GetNumber( REGVAL_USE_H323_GATEWAY ) != 0);
  1310. }
  1311. }
  1312. return( bResult );
  1313. } // End of bCanCallAsPhoneNumber.
  1314. //--------------------------------------------------------------------------//
  1315. // unescape. //
  1316. //--------------------------------------------------------------------------//
  1317. HRESULT Unescape
  1318. (
  1319. TCHAR * const pszSrc // pointer to string to unescape in place
  1320. ){
  1321. ASSERT( pszSrc != NULL );
  1322. TCHAR * pszPercentSign;
  1323. HRESULT hrResult;
  1324. for( hrResult = S_OK, pszPercentSign = pszSrc; pszPercentSign != NULL; )
  1325. {
  1326. if( (pszPercentSign = StrChr( pszPercentSign, '%' )) != NULL )
  1327. {
  1328. TCHAR chHighNibble = pszPercentSign[ 1 ];
  1329. if( ((chHighNibble >= '0') && (chHighNibble <= '9')) ||
  1330. ((chHighNibble >= 'a') && (chHighNibble <= 'f')) ||
  1331. ((chHighNibble >= 'A') && (chHighNibble <= 'F')) )
  1332. {
  1333. TCHAR chLowNibble = pszPercentSign[ 2 ];
  1334. if( ((chLowNibble >= '0') && (chLowNibble <= '9')) ||
  1335. ((chLowNibble >= 'a') && (chLowNibble <= 'f')) ||
  1336. ((chLowNibble >= 'A') && (chLowNibble <= 'F')) )
  1337. {
  1338. chHighNibble = ((chHighNibble >= '0') && (chHighNibble <= '9'))? chHighNibble - '0':
  1339. ((chHighNibble >= 'a') && (chHighNibble <= 'f'))? chHighNibble - 'a' + 10: chHighNibble - 'A' + 10;
  1340. chLowNibble = ((chLowNibble >= '0') && (chLowNibble <= '9'))? chLowNibble - '0':
  1341. ((chLowNibble >= 'a') && (chLowNibble <= 'f'))? chLowNibble - 'a' + 10: chLowNibble - 'A' + 10;
  1342. *pszPercentSign++ = (chHighNibble << 4) | chLowNibble;
  1343. lstrcpy( pszPercentSign, &pszPercentSign[ 2 ] );
  1344. }
  1345. else
  1346. {
  1347. hrResult = NM_CALLERR_UNESCAPE_ERROR;
  1348. break;
  1349. }
  1350. }
  1351. else
  1352. {
  1353. hrResult = NM_CALLERR_UNESCAPE_ERROR;
  1354. break;
  1355. }
  1356. }
  1357. }
  1358. return( hrResult );
  1359. } // End of Unescape.