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.

796 lines
21 KiB

  1. //--------------------------------------------------------------------------//
  2. // Application Header Files. //
  3. //--------------------------------------------------------------------------//
  4. #include "precomp.h"
  5. #include "callto.h"
  6. #include "calltoContext.h"
  7. #include "calltoResolver.h"
  8. //--------------------------------------------------------------------------//
  9. // CCalltoResolver::CCalltoResolver. //
  10. //--------------------------------------------------------------------------//
  11. CCalltoResolver::CCalltoResolver(void):
  12. m_registeredResolvers( 0 )
  13. {
  14. addResolver( &m_phoneResolver );
  15. addResolver( &m_emailResolver );
  16. addResolver( &m_ipResolver );
  17. addResolver( &m_computerResolver );
  18. addResolver( &m_ilsResolver );
  19. addResolver( &m_unrecognizedTypeResolver );
  20. addResolver( &m_stringResolver );
  21. } // End of CCalltoResolver::CCalltoResolver.
  22. //--------------------------------------------------------------------------//
  23. // CCalltoResolver::~CCalltoResolver. //
  24. //--------------------------------------------------------------------------//
  25. CCalltoResolver::~CCalltoResolver()
  26. {
  27. } // End of CCalltoResolver::~CCalltoResolver.
  28. //--------------------------------------------------------------------------//
  29. // CCalltoResolver::resolve. //
  30. //--------------------------------------------------------------------------//
  31. HRESULT
  32. CCalltoResolver::resolve
  33. (
  34. ICalltoContext * const calltoContext,
  35. CCalltoProperties * const calltoProperties,
  36. CCalltoCollection * const resolvedCalltoCollection,
  37. const TCHAR * url,
  38. const bool strict
  39. ){
  40. HRESULT result;
  41. if( (calltoContext == NULL) || (calltoProperties == NULL) || (resolvedCalltoCollection == NULL) )
  42. {
  43. result = E_POINTER;
  44. }
  45. else
  46. {
  47. TCHAR * params = StrStrI( url, TEXT( "phone:+" ) );
  48. params = StrChr( (params != NULL)? params + strlen_literal( TEXT( "phone:+" ) ): url, '+' );
  49. int paramsLength = (params == NULL)? 0: lstrlen( params );
  50. int urlLength = lstrlen( url ) - paramsLength + 1;
  51. int prefixLength = 0;
  52. if( !StrCmpNI_literal( url, TEXT( "callto:" ) ) )
  53. {
  54. prefixLength = strlen_literal( TEXT( "callto:" ) );
  55. }
  56. else if( StrCmpNI_literal( url, TEXT( "callto://" ) ) )
  57. {
  58. prefixLength = strlen_literal( TEXT( "callto:" ) );
  59. url += strlen_literal( TEXT( "callto://" ) );
  60. urlLength -= strlen_literal( TEXT( "callto://" ) ) - strlen_literal( TEXT( "callto:" ) );
  61. }
  62. TCHAR * urlBuffer = NULL;
  63. if( (urlBuffer = new TCHAR [ urlLength + prefixLength ]) == NULL )
  64. {
  65. result = E_OUTOFMEMORY;
  66. }
  67. else
  68. {
  69. if( paramsLength > 0 )
  70. {
  71. // Save params...
  72. calltoProperties->set_params( params );
  73. }
  74. // Save original callto...
  75. calltoProperties->set_callto( url, urlLength );
  76. result = S_FALSE;
  77. resolvedCalltoCollection->reset();
  78. if( urlLength > 1 )
  79. {
  80. bool strictChecked = !strict;
  81. for( int nn = 0; nn < m_registeredResolvers; nn++ )
  82. {
  83. if( prefixLength > 0 )
  84. {
  85. lstrcpy( urlBuffer, TEXT( "callto:" ) ); // Prepend default of callto: ...
  86. lstrcpyn( urlBuffer + strlen_literal( TEXT( "callto:" ) ), url, urlLength );
  87. }
  88. else
  89. {
  90. lstrcpyn( urlBuffer, url, urlLength );
  91. }
  92. if( !strictChecked )
  93. {
  94. if( !strictCheck( urlBuffer ) )
  95. {
  96. result = E_INVALIDARG;
  97. break;
  98. }
  99. strictChecked = true;
  100. }
  101. HRESULT resolveResult = m_resolvers[ nn ]->resolve( resolvedCalltoCollection, urlBuffer );
  102. if( FAILED( resolveResult ) && (!FAILED( result )) )
  103. {
  104. result = resolveResult;
  105. }
  106. }
  107. if( !FAILED( result ) )
  108. {
  109. result = (resolvedCalltoCollection->get_count() > 0)? S_OK: S_FALSE;
  110. }
  111. }
  112. }
  113. delete [] urlBuffer;
  114. }
  115. return( result );
  116. } // End of class CCalltoResolver::resolve.
  117. //--------------------------------------------------------------------------//
  118. // CCalltoResolver::addResolver. //
  119. //--------------------------------------------------------------------------//
  120. bool
  121. CCalltoResolver::addResolver
  122. (
  123. IResolver * const resolver
  124. ){
  125. //assert( resolver != NULL, TEXT( "attempted to add NULL resolver\r\n" ) );
  126. //assert( m_registeredResolvers < elementsof( m_resolvers ), TEXT( "attempted to add to many resolvers: %d\r\n" ), m_registeredResolvers );
  127. if( (resolver != NULL) && (m_registeredResolvers < elementsof( m_resolvers )) )
  128. {
  129. m_resolvers[ m_registeredResolvers++ ] = resolver;
  130. }
  131. return( (resolver != NULL) && (m_registeredResolvers <= elementsof( m_resolvers )) );
  132. } // End of CCalltoResolver::addResolver.
  133. //--------------------------------------------------------------------------//
  134. // CCalltoResolver::strictCheck. //
  135. //--------------------------------------------------------------------------//
  136. const bool
  137. CCalltoResolver::strictCheck
  138. (
  139. const TCHAR * const url
  140. ) const
  141. {
  142. //assert( url != NULL, TEXT( "attempted to strictCheck NULL url\r\n" ) );
  143. return( (url != NULL) &&
  144. (StrCmpNI_literal( url, TEXT( "callto:phone:" ) ) ||
  145. StrCmpNI_literal( url, TEXT( "callto:email:" ) ) ||
  146. StrCmpNI_literal( url, TEXT( "callto:ip:" ) ) ||
  147. StrCmpNI_literal( url, TEXT( "callto:computer:" ) ) ||
  148. StrCmpNI_literal( url, TEXT( "callto:ils:" ) ) ||
  149. StrCmpNI_literal( url, TEXT( "callto:string:" ) ) ||
  150. (StrStrI( url, TEXT( "|phone:" ) ) != NULL) ||
  151. (StrStrI( url, TEXT( "|email:" ) ) != NULL) ||
  152. (StrStrI( url, TEXT( "|ip:" ) ) != NULL) ||
  153. (StrStrI( url, TEXT( "|computer:" ) ) != NULL) ||
  154. (StrStrI( url, TEXT( "|ils:" ) ) != NULL) ||
  155. (StrStrI( url, TEXT( "|string:" ) ) != NULL)) );
  156. } // End of CCalltoResolver::strictCheck.
  157. //--------------------------------------------------------------------------//
  158. // CPhoneResolver::resolve. //
  159. //--------------------------------------------------------------------------//
  160. HRESULT
  161. CPhoneResolver::resolve
  162. (
  163. IMutableCalltoCollection * const calltoCollection,
  164. TCHAR * const url
  165. ){
  166. HRESULT result = E_INVALIDARG;
  167. if( (calltoCollection != NULL) && (url != NULL) )
  168. {
  169. TCHAR * phoneType;
  170. TCHAR * phoneNumber = NULL;
  171. result = S_FALSE;
  172. if( StrCmpNI_literal( url, TEXT( "callto:phone:" ) ) ) // Check for phone type without gateway...
  173. {
  174. phoneType = url;
  175. phoneNumber = url + strlen_literal( TEXT( "callto:phone:" ) );
  176. }
  177. else if( (phoneType = StrStrI( url, TEXT( "|phone:" ) )) != NULL ) // Check for phone type with gateway...
  178. {
  179. phoneNumber = phoneType + strlen_literal( TEXT( "|phone:" ) );
  180. }
  181. if( phoneNumber != NULL )
  182. {
  183. // phone: type was specified for this callto:...
  184. if( CCalltoContext::toE164( phoneNumber, NULL, 0 ) )
  185. {
  186. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  187. if( resolvedCallto != NULL )
  188. {
  189. CCalltoContext::toE164( phoneNumber, phoneNumber, lstrlen( phoneNumber ) );
  190. resolvedCallto->set_qualifiedName( url );
  191. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  192. result = S_OK;
  193. }
  194. else
  195. {
  196. result = E_OUTOFMEMORY;
  197. }
  198. }
  199. }
  200. else
  201. {
  202. phoneNumber = url + strlen_literal( TEXT( "callto:" ) );
  203. if( CCalltoContext::isPhoneNumber( phoneNumber ) )
  204. {
  205. // It smells like E164...
  206. result = E_OUTOFMEMORY;
  207. CCalltoContext::toE164( phoneNumber, phoneNumber, lstrlen( phoneNumber ) );
  208. TCHAR * buffer = new TCHAR [ lstrlen( phoneNumber ) + strlen_literal( TEXT( "callto:phone:%s" ) ) ];
  209. if( buffer != NULL )
  210. {
  211. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  212. if( resolvedCallto != NULL )
  213. {
  214. wsprintf( buffer, TEXT( "callto:phone:%s" ), phoneNumber );
  215. resolvedCallto->set_qualifiedName( buffer );
  216. resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
  217. result = S_OK;
  218. }
  219. delete [] buffer;
  220. }
  221. }
  222. }
  223. }
  224. return( result );
  225. } // End of CPhoneResolver::resolve.
  226. //--------------------------------------------------------------------------//
  227. // CEMailResolver::resolve. //
  228. //--------------------------------------------------------------------------//
  229. HRESULT
  230. CEMailResolver::resolve
  231. (
  232. IMutableCalltoCollection * const calltoCollection,
  233. TCHAR * const url
  234. ){
  235. HRESULT result = E_INVALIDARG;
  236. if( (calltoCollection != NULL) && (url != NULL) )
  237. {
  238. TCHAR * emailType;
  239. TCHAR * emailAddress = NULL;
  240. result = S_FALSE;
  241. if( StrCmpNI_literal( url, TEXT( "callto:email:" ) ) ) // Check for email type without gateway...
  242. {
  243. emailType = url;
  244. emailAddress = url + strlen_literal( TEXT( "callto:email:" ) );
  245. }
  246. else if( (emailType = StrStrI( url, TEXT( "|email:" ) )) != NULL ) // Check for email type with gateway...
  247. {
  248. emailAddress = emailType + strlen_literal( TEXT( "|email:" ) );
  249. }
  250. if( emailAddress != NULL )
  251. {
  252. // email: type was specified for this callto:...
  253. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  254. if( resolvedCallto != NULL )
  255. {
  256. resolvedCallto->set_qualifiedName( url );
  257. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  258. result = S_OK;
  259. }
  260. else
  261. {
  262. result = E_OUTOFMEMORY;
  263. }
  264. }
  265. else
  266. {
  267. emailAddress = url + strlen_literal( TEXT( "callto:" ) );
  268. if( (StrChr( emailAddress, ':' ) == NULL) && // isn't some other type:...
  269. (StrChr( emailAddress, ' ' ) == NULL) && // doesn't contain spaces...
  270. (StrChr( emailAddress, '|' ) == NULL) && // doesn't contain a bar (gateway)...
  271. (StrChr( emailAddress, '/' ) == NULL) && // isn't an old style ilsserver/email...
  272. ((StrChr( emailAddress, '.' ) == NULL) || // doesn't have a dot unless it also
  273. (StrChr( emailAddress, '@' ) != NULL)) ) // has a @ so it can't be an ip address...
  274. {
  275. // It smells like an email address...
  276. result = E_OUTOFMEMORY;
  277. TCHAR * buffer = new TCHAR [ lstrlen( emailAddress ) + strlen_literal( TEXT( "callto:email:%s" ) ) ];
  278. if( buffer != NULL )
  279. {
  280. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  281. if( resolvedCallto != NULL )
  282. {
  283. wsprintf( buffer, TEXT( "callto:email:%s" ), emailAddress );
  284. resolvedCallto->set_qualifiedName( buffer );
  285. resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
  286. result = S_OK;
  287. }
  288. delete [] buffer;
  289. }
  290. }
  291. }
  292. }
  293. return( result );
  294. } // End of CEMailResolver::resolve.
  295. //--------------------------------------------------------------------------//
  296. // CIPResolver::resolve. //
  297. //--------------------------------------------------------------------------//
  298. HRESULT
  299. CIPResolver::resolve
  300. (
  301. IMutableCalltoCollection * const calltoCollection,
  302. TCHAR * const url
  303. ){
  304. HRESULT result = E_INVALIDARG;
  305. if( (calltoCollection != NULL) && (url != NULL) )
  306. {
  307. TCHAR * ipType;
  308. TCHAR * ipAddress = NULL;
  309. result = S_FALSE;
  310. if( StrCmpNI_literal( url, TEXT( "callto:ip:" ) ) ) // Check for ip type without gateway...
  311. {
  312. ipType = url;
  313. ipAddress = url + strlen_literal( TEXT( "callto:ip:" ) );
  314. }
  315. else if( (ipType = StrStrI( url, TEXT( "|ip:" ) )) != NULL ) // Check for ip type with gateway...
  316. {
  317. ipAddress = ipType + strlen_literal( TEXT( "|ip:" ) );
  318. }
  319. if( (ipAddress != NULL) && CCalltoContext::isIPAddress( ipAddress ) )
  320. {
  321. // ip: type was specified for this callto:...
  322. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  323. if( resolvedCallto != NULL )
  324. {
  325. resolvedCallto->set_qualifiedName( url );
  326. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  327. result = S_OK;
  328. }
  329. else
  330. {
  331. result = E_OUTOFMEMORY;
  332. }
  333. }
  334. else
  335. {
  336. ipAddress = url + strlen_literal( TEXT( "callto:" ) );
  337. if( CCalltoContext::isIPAddress( ipAddress ) )
  338. {
  339. // It smells like an ip address...
  340. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  341. if( resolvedCallto != NULL )
  342. {
  343. TCHAR buffer[ MAX_PATH ];
  344. wsprintf( buffer, TEXT( "callto:ip:%s" ), ipAddress );
  345. resolvedCallto->set_qualifiedName( buffer );
  346. resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
  347. result = S_OK;
  348. }
  349. else
  350. {
  351. result = E_OUTOFMEMORY;
  352. }
  353. }
  354. }
  355. }
  356. return( result );
  357. } // End of CIPResolver::resolve.
  358. //--------------------------------------------------------------------------//
  359. // CComputerResolver::resolve. //
  360. //--------------------------------------------------------------------------//
  361. HRESULT
  362. CComputerResolver::resolve
  363. (
  364. IMutableCalltoCollection * const calltoCollection,
  365. TCHAR * const url
  366. ){
  367. HRESULT result = E_INVALIDARG;
  368. if( (calltoCollection != NULL) && (url != NULL) )
  369. {
  370. TCHAR * computerType;
  371. TCHAR * hostName = NULL;
  372. result = S_FALSE;
  373. if( StrCmpNI_literal( url, TEXT( "callto:computer:" ) ) ) // Check for computer type without gateway...
  374. {
  375. computerType = url;
  376. hostName = url + strlen_literal( TEXT( "callto:computer:" ) );
  377. }
  378. else if( (computerType = StrStrI( url, TEXT( "|computer:" ) )) != NULL ) // Check for computer type with gateway...
  379. {
  380. hostName = computerType + strlen_literal( TEXT( "|computer:" ) );
  381. }
  382. if( hostName != NULL )
  383. {
  384. // host: type was specified for this callto:...
  385. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  386. if( resolvedCallto != NULL )
  387. {
  388. resolvedCallto->set_qualifiedName( url );
  389. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  390. result = S_OK;
  391. }
  392. else
  393. {
  394. result = E_OUTOFMEMORY;
  395. }
  396. }
  397. else
  398. {
  399. hostName = url + strlen_literal( TEXT( "callto:" ) );
  400. TCHAR * slash = hostName;
  401. // Remove any trailing /....
  402. while( (slash = StrChr( slash, '/' )) != NULL )
  403. {
  404. if( slash[ 1 ] == '\0' )
  405. {
  406. slash[ 0 ] = '\0';
  407. break;
  408. }
  409. slash++;
  410. }
  411. if( (StrChr( hostName, ':' ) == NULL) && // isn't some other type:...
  412. (StrChr( hostName, ' ' ) == NULL) && // doesn't contain spaces...
  413. (StrChr( hostName, '|' ) == NULL) && // doesn't contain a bar (gateway)...
  414. (StrChr( hostName, '/' ) == NULL) && // doesn't contain a slash (ils)...
  415. (StrChr( hostName, '@' ) == NULL) ) // doesn't contain an @...
  416. {
  417. // It smells like a dns host name...
  418. result = E_OUTOFMEMORY;
  419. TCHAR * buffer = new TCHAR [ lstrlen( hostName ) + strlen_literal( TEXT( "callto:computer:%s" ) ) ];
  420. if( buffer != NULL )
  421. {
  422. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  423. if( resolvedCallto != NULL )
  424. {
  425. wsprintf( buffer, TEXT( "callto:computer:%s" ), hostName );
  426. resolvedCallto->set_qualifiedName( buffer );
  427. resolvedCallto->set_confidence( StrCmpNI_literal( hostName, TEXT( "\\\\" ) )? S_CONFIDENCE_HIGH: S_CONFIDENCE_MEDIUM );
  428. result = S_OK;
  429. }
  430. delete [] buffer;
  431. }
  432. }
  433. }
  434. }
  435. return( result );
  436. } // End of CComputerResolver::resolve.
  437. //--------------------------------------------------------------------------//
  438. // CILSResolver::resolve. //
  439. //--------------------------------------------------------------------------//
  440. HRESULT
  441. CILSResolver::resolve
  442. (
  443. IMutableCalltoCollection * const calltoCollection,
  444. TCHAR * const url
  445. ){
  446. HRESULT result = E_INVALIDARG;
  447. if( (calltoCollection != NULL) && (url != NULL) )
  448. {
  449. const TCHAR * ilsType;
  450. const TCHAR * emailAddress = NULL;
  451. result = S_FALSE;
  452. if( StrCmpNI_literal( url, TEXT( "callto:ils:" ) ) ) // Check for ils type without gateway...
  453. {
  454. ilsType = url;
  455. emailAddress = url + strlen_literal( TEXT( "callto:ils:" ) );
  456. }
  457. else if( (ilsType = StrStrI( url, TEXT( "|ils:" ) )) != NULL ) // Check for ils type with gateway...
  458. {
  459. emailAddress = ilsType + strlen_literal( TEXT( "|ils:" ) );
  460. }
  461. if( emailAddress != NULL )
  462. {
  463. // ils: type was specified for this callto:...
  464. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  465. if( resolvedCallto != NULL )
  466. {
  467. resolvedCallto->set_qualifiedName( url );
  468. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  469. result = S_OK;
  470. }
  471. else
  472. {
  473. result = E_OUTOFMEMORY;
  474. }
  475. }
  476. else
  477. {
  478. emailAddress = url + strlen_literal( TEXT( "callto:" ) );
  479. if( (StrChr( emailAddress, ' ' ) == NULL) && // doesn't contain spaces...
  480. (StrChr( emailAddress, '|' ) == NULL) && // doesn't contain a bar (gateway)...
  481. (StrChr( emailAddress, '/' ) != NULL) ) // has a /...
  482. {
  483. // It smells like an ilsserver/emailaddress...
  484. result = E_OUTOFMEMORY;
  485. TCHAR * buffer = new TCHAR [ lstrlen( emailAddress ) + strlen_literal( TEXT( "callto:ils:%s" ) ) ];
  486. if( buffer != NULL )
  487. {
  488. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  489. if( resolvedCallto != NULL )
  490. {
  491. wsprintf( buffer, TEXT( "callto:ils:%s" ), emailAddress );
  492. resolvedCallto->set_qualifiedName( buffer );
  493. resolvedCallto->set_confidence( S_CONFIDENCE_MEDIUM );
  494. result = S_OK;
  495. }
  496. delete [] buffer;
  497. }
  498. }
  499. }
  500. }
  501. return( result );
  502. } // End of CILSResolver::resolve.
  503. //--------------------------------------------------------------------------//
  504. // CUnrecognizedTypeResolver::resolve. //
  505. //--------------------------------------------------------------------------//
  506. HRESULT
  507. CUnrecognizedTypeResolver::resolve
  508. (
  509. IMutableCalltoCollection * const calltoCollection,
  510. TCHAR * const url
  511. ){
  512. HRESULT result = E_INVALIDARG;
  513. if( (calltoCollection != NULL) && (url != NULL) )
  514. {
  515. TCHAR * type;
  516. TCHAR * unrecognized = url + strlen_literal( TEXT( "callto:" ) );
  517. TCHAR * gateway = NULL;
  518. TCHAR * value = NULL;
  519. result = S_FALSE;
  520. if( ((type = StrChr( unrecognized, ':' )) != NULL) && // Check for a type, but not a known one...
  521. (!StrCmpNI_literal( url, TEXT( "callto:phone:" ) )) && (StrStrI( url, TEXT( "|phone:" ) ) == NULL) && // isn't a phone: type...
  522. (!StrCmpNI_literal( url, TEXT( "callto:email:" ) )) && (StrStrI( url, TEXT( "|email:" ) ) == NULL) && // isn't an email: type...
  523. (!StrCmpNI_literal( url, TEXT( "callto:computer:" ) )) && (StrStrI( url, TEXT( "|computer:" ) ) == NULL) && // isn't a computer: type...
  524. (!StrCmpNI_literal( url, TEXT( "callto:ils:" ) )) && (StrStrI( url, TEXT( "|ils:" ) ) == NULL) && // isn't an ils: type...
  525. (!StrCmpNI_literal( url, TEXT( "callto:ip:" ) )) && (StrStrI( url, TEXT( "|ip:" ) ) == NULL) && // isn't an ip: type...
  526. (!StrCmpNI_literal( url, TEXT( "callto:string:" ) )) && (StrStrI( url, TEXT( "|string:" ) ) == NULL) ) // isn't an string: type...
  527. {
  528. *type++ = NULL;
  529. value = type;
  530. if( (gateway = StrChr( url, '|' )) != NULL ) // Check for a gateway...
  531. {
  532. *gateway++ = NULL;
  533. type = gateway;
  534. gateway = unrecognized;
  535. }
  536. }
  537. if( value != NULL )
  538. {
  539. // Some unrecognized type was specified...
  540. result = E_OUTOFMEMORY;
  541. int length = strlen_literal( TEXT( "callto:|%s" ) ) + lstrlen( value );
  542. if( gateway == NULL )
  543. {
  544. length += lstrlen( unrecognized );
  545. }
  546. else
  547. {
  548. length += lstrlen( gateway ) + lstrlen( type );
  549. }
  550. TCHAR * buffer = new TCHAR [ length ];
  551. if( buffer != NULL )
  552. {
  553. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  554. if( resolvedCallto != NULL )
  555. {
  556. if( gateway == NULL )
  557. {
  558. wsprintf( buffer, TEXT( "callto:%s:%s" ), unrecognized, value );
  559. }
  560. else
  561. {
  562. wsprintf( buffer, TEXT( "callto:%s|%s:%s" ), gateway, type, value );
  563. }
  564. resolvedCallto->set_qualifiedName( buffer );
  565. resolvedCallto->set_confidence( S_CONFIDENCE_LOW );
  566. result = S_OK;
  567. }
  568. delete [] buffer;
  569. }
  570. }
  571. }
  572. return( result );
  573. } // End of CUnrecognizedTypeResolver::resolve.
  574. //--------------------------------------------------------------------------//
  575. // CStringResolver::resolve. //
  576. //--------------------------------------------------------------------------//
  577. HRESULT
  578. CStringResolver::resolve
  579. (
  580. IMutableCalltoCollection * const calltoCollection,
  581. TCHAR * const url
  582. ){
  583. HRESULT result = E_INVALIDARG;
  584. if( (calltoCollection != NULL) && (url != NULL) )
  585. {
  586. TCHAR * stringType;
  587. TCHAR * string = NULL;
  588. result = S_FALSE;
  589. if( StrCmpNI_literal( url, TEXT( "callto:string:" ) ) ) // Check for string type without gateway...
  590. {
  591. stringType = url;
  592. string = url + strlen_literal( TEXT( "callto:string:" ) );
  593. }
  594. else if( (stringType = StrStrI( url, TEXT( "|string:" ) )) != NULL ) // Check for string type with gateway...
  595. {
  596. string = stringType + strlen_literal( TEXT( "|string:" ) );
  597. }
  598. if( string != NULL )
  599. {
  600. // string: type was specified for this callto:...
  601. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  602. if( resolvedCallto != NULL )
  603. {
  604. resolvedCallto->set_qualifiedName( url );
  605. resolvedCallto->set_confidence( S_CONFIDENCE_HIGH );
  606. result = S_OK;
  607. }
  608. else
  609. {
  610. result = E_OUTOFMEMORY;
  611. }
  612. }
  613. else
  614. {
  615. string = url + strlen_literal( TEXT( "callto:" ) );
  616. if( StrChr( string, ':' ) == NULL )
  617. {
  618. // It doesn't have a type so set it to string...
  619. result = E_OUTOFMEMORY;
  620. TCHAR * slash;
  621. TCHAR * buffer = new TCHAR [ lstrlen( string ) + strlen_literal( TEXT( "callto:%s|string:%s" ) ) ];
  622. if( buffer != NULL )
  623. {
  624. ICallto * const resolvedCallto = calltoCollection->get_nextUnused();
  625. if( resolvedCallto != NULL )
  626. {
  627. if( (slash = StrChr( string, '|' )) == NULL ) // Check for a gateway...
  628. {
  629. wsprintf( buffer, TEXT( "callto:string:%s" ), string );
  630. }
  631. else
  632. {
  633. *slash++ = NULL;
  634. wsprintf( buffer, TEXT( "callto:%s|string:%s" ), string, slash );
  635. }
  636. resolvedCallto->set_qualifiedName( buffer );
  637. resolvedCallto->set_confidence( S_CONFIDENCE_LOW );
  638. result = S_OK;
  639. }
  640. delete [] buffer;
  641. }
  642. }
  643. }
  644. }
  645. return( result );
  646. } // End of CStringResolver::resolve.