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.

1019 lines
21 KiB

  1. // File: conflnk.cpp
  2. #include "precomp.h"
  3. #include <shellapi.h>
  4. #include <shlstock.h>
  5. #include <ConfDir.h>
  6. #include <ConfCli.h>
  7. #include "clCnfLnk.hpp"
  8. #include "resource.h"
  9. #include "atlbase.h"
  10. #include "confevt.h"
  11. #include "sdkInternal.h"
  12. #include "nameres.h"
  13. /////////////////////////////////////////////////////////////////////
  14. // Initialize GUIDs
  15. //
  16. #pragma data_seg(".text")
  17. #define INITGUID
  18. #include <initguid.h>
  19. #include "CLinkId.h"
  20. // from shlguid.h - must keep in sync
  21. DEFINE_SHLGUID(CLSID_ShellLink, 0x00021401L, 0, 0);
  22. #ifndef _UNICODE
  23. DEFINE_SHLGUID(IID_IShellLink, 0x000214EEL, 0, 0);
  24. DEFINE_SHLGUID(IID_IShellExtInit, 0x000214E8L, 0, 0);
  25. DEFINE_SHLGUID(IID_IShellPropSheetExt, 0x000214E9L, 0, 0);
  26. #endif // _UNICODE
  27. #undef INITGUID
  28. #pragma data_seg()
  29. /////////////////////////////////////////////////////////////////////
  30. #ifdef DEBUG
  31. BOOL IsValidPCConfLink(PCCConfLink pcConfLink)
  32. {
  33. return(
  34. IS_VALID_READ_PTR(pcConfLink, CConfLink) &&
  35. FLAGS_ARE_VALID(pcConfLink->m_dwFlags, ALL_CONFLNK_FLAGS) &&
  36. (! pcConfLink->m_pszFile ||
  37. IS_VALID_STRING_PTR(pcConfLink->m_pszFile, STR)) &&
  38. (! pcConfLink->m_pszName ||
  39. IS_VALID_STRING_PTR(pcConfLink->m_pszName, STR)) &&
  40. IS_VALID_STRUCT_PTR((PCRefCount)pcConfLink, CRefCount) &&
  41. IS_VALID_INTERFACE_PTR((PCIDataObject)pcConfLink, IDataObject) &&
  42. IS_VALID_INTERFACE_PTR((PCIPersistFile)pcConfLink, IPersistFile) &&
  43. IS_VALID_INTERFACE_PTR((PCIPersistStream)pcConfLink, IPersistStream) &&
  44. IS_VALID_INTERFACE_PTR((PCIShellExtInit)pcConfLink, IShellExtInit) &&
  45. IS_VALID_INTERFACE_PTR((PCIShellPropSheetExt)pcConfLink, IShellPropSheetExt) &&
  46. IS_VALID_INTERFACE_PTR((PCIConferenceLink)pcConfLink, IConferenceLink));
  47. }
  48. #endif /* DEBUG */
  49. CConfLink::CConfLink(OBJECTDESTROYEDPROC ObjectDestroyed) :
  50. RefCount (ObjectDestroyed),
  51. m_dwFlags (0),
  52. m_dwCallFlags (0),
  53. m_dwTransport (0),
  54. m_pszFile (NULL),
  55. m_pszName (NULL),
  56. m_pszRemoteConfName (NULL),
  57. m_pszAddress (NULL)
  58. {
  59. DebugEntry(CConfLink::CConfLink);
  60. // Don't validate this until after construction.
  61. ASSERT( !ObjectDestroyed ||
  62. IS_VALID_CODE_PTR(ObjectDestroyed, OBJECTDESTROYEDPROC));
  63. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  64. DebugExitVOID(CConfLink::CConfLink);
  65. return;
  66. }
  67. CConfLink::~CConfLink(void)
  68. {
  69. DebugEntry(CConfLink::~CConfLink);
  70. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  71. delete m_pszFile;
  72. m_pszFile = NULL;
  73. delete m_pszName;
  74. m_pszName = NULL;
  75. delete m_pszAddress;
  76. m_pszAddress = NULL;
  77. delete m_pszRemoteConfName;
  78. m_pszRemoteConfName = NULL;
  79. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  80. DebugExitVOID(CConfLink::~CConfLink);
  81. return;
  82. }
  83. HRESULT STDMETHODCALLTYPE CConfLink::SetAddress(PCSTR pcszAddress)
  84. {
  85. HRESULT hr;
  86. PSTR pszNewAddress = NULL;
  87. DebugEntry(CConfLink::SetAddress);
  88. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  89. ASSERT( !pcszAddress ||
  90. IS_VALID_STRING_PTR(pcszAddress, CSTR));
  91. pszNewAddress = new char[lstrlen(pcszAddress) + 1];
  92. if (NULL != pszNewAddress)
  93. {
  94. lstrcpy(pszNewAddress, pcszAddress);
  95. hr = S_OK;
  96. }
  97. else
  98. {
  99. hr = E_OUTOFMEMORY;
  100. }
  101. if (S_OK == hr)
  102. {
  103. if (NULL != m_pszAddress)
  104. {
  105. delete m_pszAddress;
  106. }
  107. m_pszAddress = pszNewAddress;
  108. Dirty(TRUE);
  109. TRACE_OUT(("CConfLink::SetAddress(): Set Address to %s.",
  110. CHECK_STRING(m_pszAddress)));
  111. }
  112. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  113. ASSERT( hr == S_OK ||
  114. hr == E_OUTOFMEMORY);
  115. DebugExitHRESULT(CConfLink::SetAddress, hr);
  116. return(hr);
  117. }
  118. HRESULT STDMETHODCALLTYPE CConfLink::GetAddress(PSTR *ppszAddress)
  119. {
  120. HRESULT hr;
  121. DebugEntry(CConfLink::GetAddress);
  122. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  123. ASSERT(IS_VALID_WRITE_PTR(ppszAddress, PSTR));
  124. *ppszAddress = NULL;
  125. if (NULL != m_pszAddress)
  126. {
  127. *ppszAddress = NULL;
  128. LPMALLOC pMalloc;
  129. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  130. {
  131. // (+ 1) for null terminator.
  132. *ppszAddress = (PSTR) pMalloc->Alloc(lstrlen(m_pszAddress) + 1);
  133. pMalloc->Release();
  134. pMalloc = NULL;
  135. }
  136. if (NULL != *ppszAddress)
  137. {
  138. lstrcpy(*ppszAddress, m_pszAddress);
  139. hr = S_OK;
  140. TRACE_OUT(("CConfLink::GetAddress(): Got Address %s.", *ppszAddress));
  141. }
  142. else
  143. {
  144. hr = E_OUTOFMEMORY;
  145. }
  146. }
  147. else
  148. {
  149. // No Name.
  150. hr = S_FALSE;
  151. }
  152. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  153. ASSERT( (hr == S_OK &&
  154. IS_VALID_STRING_PTR(*ppszAddress, STR)) ||
  155. (( hr == S_FALSE ||
  156. hr == E_OUTOFMEMORY) &&
  157. ! *ppszAddress));
  158. DebugExitHRESULT(CConfLink::GetAddress, hr);
  159. return(hr);
  160. }
  161. HRESULT STDMETHODCALLTYPE CConfLink::SetRemoteConfName(PCSTR pcszRemoteConfName)
  162. {
  163. HRESULT hr;
  164. DebugEntry(CConfLink::SetRemoteConfName);
  165. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  166. ASSERT( !pcszRemoteConfName ||
  167. IS_VALID_STRING_PTR(pcszRemoteConfName, CSTR));
  168. PSTR pszNewRemoteConfName = new char[lstrlen(pcszRemoteConfName) + 1];
  169. if (NULL != pszNewRemoteConfName)
  170. {
  171. lstrcpy(pszNewRemoteConfName, pcszRemoteConfName);
  172. hr = S_OK;
  173. }
  174. else
  175. {
  176. hr = E_OUTOFMEMORY;
  177. }
  178. if (S_OK == hr)
  179. {
  180. if (NULL != m_pszRemoteConfName)
  181. {
  182. delete m_pszRemoteConfName;
  183. }
  184. m_pszRemoteConfName = pszNewRemoteConfName;
  185. Dirty(TRUE);
  186. TRACE_OUT(("CConfLink::SetRemoteConfName(): Set RemoteConfName to %s.",
  187. CHECK_STRING(m_pszRemoteConfName)));
  188. }
  189. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  190. ASSERT( hr == S_OK ||
  191. hr == E_OUTOFMEMORY);
  192. DebugExitHRESULT(CConfLink::SetRemoteConfName, hr);
  193. return(hr);
  194. }
  195. HRESULT STDMETHODCALLTYPE CConfLink::GetRemoteConfName(PSTR *ppszRemoteConfName)
  196. {
  197. HRESULT hr;
  198. DebugEntry(CConfLink::GetRemoteConfName);
  199. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  200. ASSERT(IS_VALID_WRITE_PTR(ppszRemoteConfName, PSTR));
  201. *ppszRemoteConfName = NULL;
  202. if (NULL != m_pszRemoteConfName)
  203. {
  204. *ppszRemoteConfName = NULL;
  205. LPMALLOC pMalloc;
  206. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  207. {
  208. // (+ 1) for null terminator.
  209. *ppszRemoteConfName = (PSTR) pMalloc->Alloc(lstrlen(m_pszRemoteConfName) + 1);
  210. pMalloc->Release();
  211. pMalloc = NULL;
  212. }
  213. if (NULL != *ppszRemoteConfName)
  214. {
  215. lstrcpy(*ppszRemoteConfName, m_pszRemoteConfName);
  216. hr = S_OK;
  217. TRACE_OUT(("CConfLink::GetRemoteConfName(): Got RemoteConfName %s.",
  218. *ppszRemoteConfName));
  219. }
  220. else
  221. {
  222. hr = E_OUTOFMEMORY;
  223. }
  224. }
  225. else
  226. {
  227. // No Name.
  228. hr = S_FALSE;
  229. }
  230. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  231. ASSERT( (hr == S_OK &&
  232. IS_VALID_STRING_PTR(*ppszRemoteConfName, STR)) ||
  233. (( hr == S_FALSE ||
  234. hr == E_OUTOFMEMORY) &&
  235. ! *ppszRemoteConfName));
  236. DebugExitHRESULT(CConfLink::GetRemoteConfName, hr);
  237. return(hr);
  238. }
  239. HRESULT STDMETHODCALLTYPE CConfLink::SetName(PCSTR pcszName)
  240. {
  241. HRESULT hr;
  242. BOOL bChanged;
  243. PSTR pszNewName = NULL;
  244. DebugEntry(CConfLink::SetName);
  245. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  246. ASSERT( !pcszName ||
  247. IS_VALID_STRING_PTR(pcszName, CSTR));
  248. bChanged = ! ((! pcszName && ! m_pszName) ||
  249. (pcszName && m_pszName &&
  250. ! lstrcmp(pcszName, m_pszName)));
  251. if (bChanged && pcszName)
  252. {
  253. pszNewName = new(char[lstrlen(pcszName) + 1]);
  254. if (pszNewName)
  255. {
  256. lstrcpy(pszNewName, pcszName);
  257. hr = S_OK;
  258. }
  259. else
  260. {
  261. hr = E_OUTOFMEMORY;
  262. }
  263. }
  264. else
  265. {
  266. hr = S_OK;
  267. }
  268. if (hr == S_OK)
  269. {
  270. if (bChanged)
  271. {
  272. if (m_pszName)
  273. {
  274. delete m_pszName;
  275. }
  276. m_pszName = pszNewName;
  277. Dirty(TRUE);
  278. TRACE_OUT(("CConfLink::SetName(): Set Name to %s.",
  279. CHECK_STRING(m_pszName)));
  280. }
  281. else
  282. {
  283. TRACE_OUT(("CConfLink::SetName(): Name already %s.",
  284. CHECK_STRING(m_pszName)));
  285. }
  286. }
  287. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  288. ASSERT( hr == S_OK ||
  289. hr == E_OUTOFMEMORY);
  290. DebugExitHRESULT(CConfLink::SetName, hr);
  291. return(hr);
  292. }
  293. HRESULT STDMETHODCALLTYPE CConfLink::GetName(PSTR *ppszName)
  294. {
  295. HRESULT hr;
  296. DebugEntry(CConfLink::GetName);
  297. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  298. ASSERT(IS_VALID_WRITE_PTR(ppszName, PSTR));
  299. *ppszName = NULL;
  300. if (m_pszName)
  301. {
  302. *ppszName = NULL;
  303. LPMALLOC pMalloc;
  304. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  305. {
  306. // (+ 1) for null terminator.
  307. *ppszName = (PSTR) pMalloc->Alloc(lstrlen(m_pszName) + 1);
  308. pMalloc->Release();
  309. pMalloc = NULL;
  310. }
  311. // ChrisPi: I changed this to use the above implementation because
  312. // SHAlloc is not available in the sdk shell32.lib
  313. // *ppszName = (PSTR)SHAlloc(lstrlen(m_pszURL) + 1);
  314. if (*ppszName)
  315. {
  316. lstrcpy(*ppszName, m_pszName);
  317. hr = S_OK;
  318. TRACE_OUT(("CConfLink::GetName(): Got Name %s.", *ppszName));
  319. }
  320. else
  321. {
  322. hr = E_OUTOFMEMORY;
  323. }
  324. }
  325. else
  326. {
  327. // No Name.
  328. hr = S_FALSE;
  329. }
  330. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  331. ASSERT( (hr == S_OK &&
  332. IS_VALID_STRING_PTR(*ppszName, STR)) ||
  333. (( hr == S_FALSE ||
  334. hr == E_OUTOFMEMORY) &&
  335. ! *ppszName));
  336. DebugExitHRESULT(CConfLink::GetName, hr);
  337. return(hr);
  338. }
  339. HRESULT STDMETHODCALLTYPE CConfLink::SetTransport(DWORD dwTransport)
  340. {
  341. HRESULT hr;
  342. DebugEntry(CConfLink::SetTransport);
  343. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  344. m_dwTransport = dwTransport;
  345. Dirty(TRUE);
  346. TRACE_OUT(("CConfLink::SetTransport(): Set Transport to %#8x.",
  347. m_dwTransport));
  348. hr = S_OK;
  349. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  350. DebugExitHRESULT(CConfLink::SetTransport, hr);
  351. return(hr);
  352. }
  353. HRESULT STDMETHODCALLTYPE CConfLink::GetTransport(DWORD *pdwTransport)
  354. {
  355. HRESULT hr;
  356. DebugEntry(CConfLink::GetTransport);
  357. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  358. ASSERT(IS_VALID_WRITE_PTR(pdwTransport, PDWORD));
  359. *pdwTransport = m_dwTransport;
  360. hr = S_OK;
  361. TRACE_OUT(("CConfLink::GetTransport(): Got Transport %#8x.",
  362. *pdwTransport));
  363. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  364. DebugExitHRESULT(CConfLink::GetTransport, hr);
  365. return(hr);
  366. }
  367. HRESULT STDMETHODCALLTYPE CConfLink::SetCallFlags(DWORD dwCallFlags)
  368. {
  369. HRESULT hr;
  370. DebugEntry(CConfLink::SetCallFlags);
  371. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  372. m_dwCallFlags = dwCallFlags;
  373. Dirty(TRUE);
  374. TRACE_OUT(("CConfLink::SetCallFlags(): Set CallFlags to %#8x.",
  375. m_dwCallFlags));
  376. hr = S_OK;
  377. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  378. DebugExitHRESULT(CConfLink::SetCallFlags, hr);
  379. return(hr);
  380. }
  381. HRESULT STDMETHODCALLTYPE CConfLink::GetCallFlags(DWORD *pdwCallFlags)
  382. {
  383. HRESULT hr;
  384. DebugEntry(CConfLink::GetCallFlags);
  385. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  386. ASSERT(IS_VALID_WRITE_PTR(pdwCallFlags, PDWORD));
  387. *pdwCallFlags = m_dwCallFlags;
  388. hr = S_OK;
  389. TRACE_OUT(("CConfLink::GetCallFlags(): Got CallFlags %#8x.",
  390. *pdwCallFlags));
  391. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  392. DebugExitHRESULT(CConfLink::GetCallFlags, hr);
  393. return(hr);
  394. }
  395. #define STR_CALLTO _T("callto:")
  396. #define STR_CONFERENCE _T("+conference=")
  397. #define STR_GATEWAY _T("+gateway=")
  398. #define STR_SECURE _T("+secure=true")
  399. #define STR_PHONE _T("+type=phone")
  400. #define STR_NO_AV _T("+av=false")
  401. #define STR_NO_DATA _T("+data=false")
  402. //--------------------------------------------------------------------------//
  403. // CConfLink::InvokeCommand. //
  404. //--------------------------------------------------------------------------//
  405. HRESULT
  406. STDMETHODCALLTYPE
  407. CConfLink::InvokeCommand
  408. (
  409. PCLINVOKECOMMANDINFO pclici
  410. ){
  411. DebugEntry( CConfLink::InvokeCommand );
  412. ASSERT( IS_VALID_STRUCT_PTR( this, CConfLink ) );
  413. ASSERT( IS_VALID_STRUCT_PTR( pclici, CCLINVOKECOMMANDINFO ) );
  414. HRESULT result = E_INVALIDARG;
  415. if(m_pszAddress)
  416. {
  417. if( m_dwTransport == NAMETYPE_CALLTO )
  418. {
  419. result = shellCallto( m_pszAddress, IS_FLAG_SET( pclici->dwFlags, ICL_INVOKECOMMAND_FL_ALLOW_UI ) );
  420. }
  421. else
  422. {
  423. long lMax = lstrlen(STR_CALLTO) +
  424. lstrlen(STR_CONFERENCE) +
  425. lstrlen(STR_GATEWAY) +
  426. lstrlen(STR_PHONE) +
  427. lstrlen(STR_SECURE) +
  428. lstrlen(STR_NO_AV) +
  429. lstrlen(STR_NO_DATA) +
  430. lstrlen(m_pszAddress) +
  431. (m_pszRemoteConfName ? lstrlen(m_pszRemoteConfName) : 0) +
  432. 1;
  433. LPTSTR url = (TCHAR*) _alloca(lMax);
  434. lstrcpy( url, STR_CALLTO );
  435. if( m_dwTransport != NAMETYPE_H323GTWY )
  436. {
  437. lstrcat( url, m_pszAddress );
  438. }
  439. else
  440. {
  441. TCHAR * const pSlash = (TCHAR * const) _StrChr( m_pszAddress, '/' );
  442. if( pSlash != NULL )
  443. {
  444. *pSlash = '\0';
  445. lstrcat( url, pSlash + 1 );
  446. lstrcat( url, STR_GATEWAY );
  447. }
  448. lstrcat( url, m_pszAddress );
  449. lstrcat( url, STR_PHONE );
  450. }
  451. if( m_pszRemoteConfName != NULL )
  452. {
  453. lstrcat( url, STR_CONFERENCE );
  454. lstrcat( url, m_pszRemoteConfName );
  455. }
  456. if( IS_FLAG_SET( m_dwCallFlags, CRPCF_SECURE ) )
  457. {
  458. lstrcat( url, STR_SECURE );
  459. }
  460. if( IS_FLAG_CLEAR( m_dwCallFlags, (CRPCF_AUDIO | CRPCF_VIDEO) ) )
  461. {
  462. lstrcat( url, STR_NO_AV );
  463. }
  464. if( IS_FLAG_CLEAR( m_dwCallFlags, CRPCF_DATA) )
  465. {
  466. lstrcat( url, STR_NO_DATA );
  467. }
  468. result = shellCallto( url, IS_FLAG_SET( pclici->dwFlags, ICL_INVOKECOMMAND_FL_ALLOW_UI ) );
  469. }
  470. ASSERT( IS_VALID_STRUCT_PTR( this, CConfLink ) );
  471. DebugExitHRESULT( CConfLink::InvokeCommand, result );
  472. }
  473. return( result );
  474. } // End of CConfLink::InvokeCommand.
  475. //--------------------------------------------------------------------------//
  476. // shellCallto. //
  477. //--------------------------------------------------------------------------//
  478. HRESULT
  479. shellCallto
  480. (
  481. const TCHAR * const url,
  482. const bool notifyOnError
  483. ){
  484. ASSERT( url != NULL );
  485. ASSERT( url[ 0 ] != '\0' );
  486. TRACE_OUT( ("shellCallto: url:\"%s\"", url) );
  487. HRESULT result;
  488. if( url == NULL )
  489. {
  490. result = E_POINTER;
  491. }
  492. else if( url[ 0 ] == '\0' )
  493. {
  494. result = E_INVALIDARG;
  495. }
  496. else
  497. {
  498. result = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  499. if( SUCCEEDED( result ) )
  500. {
  501. IInternalConfExe * internalConf;
  502. HRESULT result;
  503. result = CoCreateInstance( CLSID_NmManager, NULL, CLSCTX_ALL, IID_IInternalConfExe, (LPVOID *) &internalConf );
  504. if( SUCCEEDED( result ) && (internalConf != NULL) )
  505. {
  506. result = internalConf->ShellCalltoProtocolHandler( CComBSTR( url ), FALSE );
  507. internalConf->Release();
  508. }
  509. ::CoUninitialize();
  510. }
  511. if( FAILED( result ) && notifyOnError )
  512. {
  513. TCHAR message[ MAX_PATH ];
  514. TCHAR title[ MAX_PATH ];
  515. ::LoadString( g_hInst, // handle to module containing string resource
  516. IDS_COULD_NOT_CALL, // resource identifier
  517. message, // pointer to buffer for resource
  518. ARRAY_ELEMENTS( message ) ); // size of buffer
  519. ::LoadString( g_hInst, // handle to module containing string resource
  520. IDS_LAUNCH_ERROR, // resource identifier
  521. title, // pointer to buffer for resource
  522. ARRAY_ELEMENTS( title ) ); // size of buffer
  523. ::MessageBox( NULL, message, title, MB_ICONERROR | MB_OK );
  524. }
  525. }
  526. return( result );
  527. } // End of shellCallto.
  528. ULONG STDMETHODCALLTYPE CConfLink::AddRef(void)
  529. {
  530. ULONG ulcRef;
  531. DebugEntry(CConfLink::AddRef);
  532. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  533. ulcRef = RefCount::AddRef();
  534. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  535. DebugExitULONG(CConfLink::AddRef, ulcRef);
  536. return(ulcRef);
  537. }
  538. ULONG STDMETHODCALLTYPE CConfLink::Release(void)
  539. {
  540. ULONG ulcRef;
  541. DebugEntry(CConfLink::Release);
  542. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  543. ulcRef = RefCount::Release();
  544. DebugExitULONG(CConfLink::Release, ulcRef);
  545. return(ulcRef);
  546. }
  547. HRESULT STDMETHODCALLTYPE CConfLink::QueryInterface(REFIID riid,
  548. PVOID *ppvObject)
  549. {
  550. HRESULT hr = S_OK;
  551. DebugEntry(CConfLink::QueryInterface);
  552. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  553. ASSERT(IsValidREFIID(riid));
  554. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  555. if (riid == IID_IDataObject)
  556. {
  557. *ppvObject = (PIDataObject)this;
  558. TRACE_OUT(("CConfLink::QueryInterface(): Returning IDataObject."));
  559. }
  560. #if 0 // These are currently unsupported interfaces:
  561. else if (riid == IID_IExtractIcon)
  562. {
  563. *ppvObject = NULL;
  564. hr = E_NOINTERFACE;
  565. // *ppvObject = (PIExtractIcon)this;
  566. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IExtractIcon!"));
  567. }
  568. else if (riid == IID_INewShortcutHook)
  569. {
  570. *ppvObject = NULL;
  571. hr = E_NOINTERFACE;
  572. // *ppvObject = (PINewShortcutHook)this;
  573. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning INewShortcutHook!"));
  574. }
  575. else if (riid == IID_IShellExecuteHook)
  576. {
  577. *ppvObject = NULL;
  578. hr = E_NOINTERFACE;
  579. // *ppvObject = (PIShellExecuteHook)this;
  580. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IShellExecuteHook!"));
  581. }
  582. else if (riid == IID_IShellLink)
  583. {
  584. *ppvObject = NULL;
  585. hr = E_NOINTERFACE;
  586. // *ppvObject = (PIShellLink)this;
  587. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IShellLink!"));
  588. }
  589. #endif /* DEBUG */
  590. // Supported interfaces:
  591. else if (riid == IID_IShellExtInit)
  592. {
  593. *ppvObject = (PIShellExtInit)this;
  594. TRACE_OUT(("CConfLink::QueryInterface(): Returning IShellExtInit."));
  595. }
  596. else if (riid == IID_IShellPropSheetExt)
  597. {
  598. *ppvObject = (PIShellPropSheetExt)this;
  599. TRACE_OUT(("CConfLink::QueryInterface(): Returning IShellPropSheetExt."));
  600. }
  601. else if (riid == IID_IPersist)
  602. {
  603. *ppvObject = (PIPersist)(PIPersistStream)this;
  604. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersist."));
  605. }
  606. else if (riid == IID_IPersistFile)
  607. {
  608. *ppvObject = (PIPersistFile)this;
  609. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersistFile."));
  610. }
  611. else if (riid == IID_IPersistStream)
  612. {
  613. *ppvObject = (PIPersistStream)this;
  614. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersistStream."));
  615. }
  616. else if (riid == IID_IConferenceLink)
  617. {
  618. *ppvObject = (PIConferenceLink)this;
  619. TRACE_OUT(("CConfLink::QueryInterface(): Returning IConferenceLink."));
  620. }
  621. else if (riid == IID_IUnknown)
  622. {
  623. *ppvObject = (PIUnknown) (PIConferenceLink) this;
  624. TRACE_OUT(("CConfLink::QueryInterface(): Returning IUnknown."));
  625. }
  626. else
  627. {
  628. TRACE_OUT(("CConfLink::QueryInterface(): Called on unknown interface."));
  629. *ppvObject = NULL;
  630. hr = E_NOINTERFACE;
  631. }
  632. if (hr == S_OK)
  633. {
  634. AddRef();
  635. }
  636. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  637. DebugExitHRESULT(CConfLink::QueryInterface, hr);
  638. return(hr);
  639. }
  640. /* O P E N C O N F L I N K */
  641. /*-------------------------------------------------------------------------
  642. %%Function: OpenConfLink
  643. -------------------------------------------------------------------------*/
  644. void WINAPI OpenConfLink(HWND hwndParent, HINSTANCE hinst,
  645. PSTR pszCmdLine, int nShowCmd)
  646. {
  647. HRESULT hr;
  648. CConfLink conflink(NULL);
  649. // int nResult;
  650. DebugEntry(OpenConfLink);
  651. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  652. ASSERT(IS_VALID_HANDLE(hinst, INSTANCE));
  653. ASSERT(IS_VALID_STRING_PTR(pszCmdLine, STR));
  654. ASSERT(IsValidShowCmd(nShowCmd));
  655. // Assume the entire command line is a Conference Link file path.
  656. // TrimWhiteSpace(pszCmdLine);
  657. TRACE_OUT(("OpenConfLink(): Trying to open Conference Link %s.",
  658. pszCmdLine));
  659. #if 0
  660. TCHAR szBuf[256];
  661. wsprintf(szBuf, "Launching conference link %s", pszCmdLine);
  662. ::MessageBox( NULL,
  663. szBuf,
  664. "Conference Link Extension",
  665. MB_ICONINFORMATION);
  666. #endif
  667. hr = conflink.LoadFromFile(pszCmdLine, TRUE);
  668. if (hr == S_OK)
  669. {
  670. CLINVOKECOMMANDINFO clici;
  671. clici.dwcbSize = sizeof(clici);
  672. clici.hwndParent = hwndParent;
  673. clici.pcszVerb = NULL;
  674. clici.dwFlags = ( ICL_INVOKECOMMAND_FL_ALLOW_UI |
  675. ICL_INVOKECOMMAND_FL_USE_DEFAULT_VERB);
  676. hr = conflink.InvokeCommand(&clici);
  677. }
  678. else
  679. {
  680. // BUGBUG: need resource here INTL
  681. ::MessageBox( hwndParent,
  682. _TEXT("There was an error while identifying the conference"),
  683. _TEXT("Conference Shortcut Error"),
  684. MB_ICONINFORMATION);
  685. // if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  686. // MAKEINTRESOURCE(IDS_LOADFROMFILE_FAILED),
  687. // (MB_OK | MB_ICONEXCLAMATION), &nResult, pszCmdLine))
  688. //
  689. // ASSERT(nResult == IDOK);
  690. }
  691. DebugExitVOID(OpenConfLink);
  692. return;
  693. }
  694. /* A N Y M E A T */
  695. /*-------------------------------------------------------------------------
  696. %%Function: AnyMeat
  697. Return TRUE if the string has any non-whitespace characters
  698. -------------------------------------------------------------------------*/
  699. BOOL AnyMeat(PCSTR pcsz)
  700. {
  701. TCHAR ch;
  702. ASSERT((!pcsz) || IS_VALID_STRING_PTR(pcsz, CSTR));
  703. if (NULL == pcsz)
  704. return FALSE;
  705. while (0 != (ch = *pcsz++))
  706. {
  707. switch (ch)
  708. {
  709. case _T(' '): // Space
  710. case _T('\t'): // Tab
  711. case 0x00A0: // Non-breaking space
  712. break;
  713. default:
  714. return TRUE; // found a non-whitespace character
  715. }
  716. }
  717. return FALSE;
  718. }
  719. HRESULT MyReleaseStgMedium(PSTGMEDIUM pstgmed)
  720. {
  721. HRESULT hr;
  722. ASSERT(IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM));
  723. if (pstgmed->pUnkForRelease)
  724. hr = pstgmed->pUnkForRelease->Release();
  725. else
  726. {
  727. switch(pstgmed->tymed)
  728. {
  729. case TYMED_HGLOBAL:
  730. hr = (! GlobalFree(pstgmed->hGlobal)) ? S_OK : E_HANDLE;
  731. break;
  732. #if 0 /* Only TYMED_HGLOBAL is ever used */
  733. case TYMED_ISTREAM:
  734. hr = pstgmed->pstm->Release();
  735. break;
  736. case TYMED_ISTORAGE:
  737. hr = pstgmed->pstm->Release();
  738. break;
  739. case TYMED_FILE:
  740. {
  741. PIMalloc pMalloc = NULL;
  742. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  743. {
  744. pMalloc->Free(pstgmed->lpszFileName);
  745. pMalloc->Release();
  746. pMalloc = NULL;
  747. pstgmed->lpszFileName = NULL;
  748. }
  749. hr = S_OK;
  750. break;
  751. }
  752. case TYMED_GDI:
  753. hr = (DeleteObject(pstgmed->hBitmap)) ? S_OK : E_HANDLE;
  754. break;
  755. case TYMED_MFPICT:
  756. hr = (DeleteMetaFile((HMETAFILE)(pstgmed->hMetaFilePict)) &&
  757. ! GlobalFree(pstgmed->hMetaFilePict)) ? S_OK : E_HANDLE;
  758. break;
  759. case TYMED_ENHMF:
  760. hr = (DeleteEnhMetaFile(pstgmed->hEnhMetaFile)) ? S_OK : E_HANDLE;
  761. break;
  762. #endif // 0
  763. default:
  764. ASSERT(pstgmed->tymed == TYMED_NULL);
  765. hr = S_OK;
  766. break;
  767. }
  768. }
  769. return(hr);
  770. }