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.

1030 lines
22 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. LPTSTR url = NULL;
  415. HRESULT result = E_INVALIDARG;
  416. if(m_pszAddress)
  417. {
  418. if( m_dwTransport == NAMETYPE_CALLTO )
  419. {
  420. result = shellCallto( m_pszAddress, IS_FLAG_SET( pclici->dwFlags, ICL_INVOKECOMMAND_FL_ALLOW_UI ) );
  421. }
  422. else
  423. {
  424. long lMax = lstrlen(STR_CALLTO) +
  425. lstrlen(STR_CONFERENCE) +
  426. lstrlen(STR_GATEWAY) +
  427. lstrlen(STR_PHONE) +
  428. lstrlen(STR_SECURE) +
  429. lstrlen(STR_NO_AV) +
  430. lstrlen(STR_NO_DATA) +
  431. lstrlen(m_pszAddress) +
  432. (m_pszRemoteConfName ? lstrlen(m_pszRemoteConfName) : 0) +
  433. 1;
  434. url = (TCHAR*) new BYTE[(lMax)];
  435. if(!url)
  436. {
  437. goto Cleanup;
  438. }
  439. lstrcpy( url, STR_CALLTO );
  440. if( m_dwTransport != NAMETYPE_H323GTWY )
  441. {
  442. lstrcat( url, m_pszAddress );
  443. }
  444. else
  445. {
  446. TCHAR * const pSlash = (TCHAR * const) _StrChr( m_pszAddress, '/' );
  447. if( pSlash != NULL )
  448. {
  449. *pSlash = '\0';
  450. lstrcat( url, pSlash + 1 );
  451. lstrcat( url, STR_GATEWAY );
  452. }
  453. lstrcat( url, m_pszAddress );
  454. lstrcat( url, STR_PHONE );
  455. }
  456. if( m_pszRemoteConfName != NULL )
  457. {
  458. lstrcat( url, STR_CONFERENCE );
  459. lstrcat( url, m_pszRemoteConfName );
  460. }
  461. if( IS_FLAG_SET( m_dwCallFlags, CRPCF_SECURE ) )
  462. {
  463. lstrcat( url, STR_SECURE );
  464. }
  465. if( IS_FLAG_CLEAR( m_dwCallFlags, (CRPCF_AUDIO | CRPCF_VIDEO) ) )
  466. {
  467. lstrcat( url, STR_NO_AV );
  468. }
  469. if( IS_FLAG_CLEAR( m_dwCallFlags, CRPCF_DATA) )
  470. {
  471. lstrcat( url, STR_NO_DATA );
  472. }
  473. result = shellCallto( url, IS_FLAG_SET( pclici->dwFlags, ICL_INVOKECOMMAND_FL_ALLOW_UI ) );
  474. }
  475. ASSERT( IS_VALID_STRUCT_PTR( this, CConfLink ) );
  476. DebugExitHRESULT( CConfLink::InvokeCommand, result );
  477. }
  478. Cleanup:
  479. delete [] url;
  480. return( result );
  481. } // End of CConfLink::InvokeCommand.
  482. //--------------------------------------------------------------------------//
  483. // shellCallto. //
  484. //--------------------------------------------------------------------------//
  485. HRESULT
  486. shellCallto
  487. (
  488. const TCHAR * const url,
  489. const bool notifyOnError
  490. ){
  491. ASSERT( url != NULL );
  492. ASSERT( url[ 0 ] != '\0' );
  493. TRACE_OUT( ("shellCallto: url:\"%s\"", url) );
  494. HRESULT result;
  495. if( url == NULL )
  496. {
  497. result = E_POINTER;
  498. }
  499. else if( url[ 0 ] == '\0' )
  500. {
  501. result = E_INVALIDARG;
  502. }
  503. else
  504. {
  505. result = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  506. if( SUCCEEDED( result ) )
  507. {
  508. IInternalConfExe * internalConf;
  509. result = CoCreateInstance( CLSID_NmManager, NULL, CLSCTX_ALL, IID_IInternalConfExe, (LPVOID *) &internalConf );
  510. if( SUCCEEDED( result ) && (internalConf != NULL) )
  511. {
  512. result = internalConf->ShellCalltoProtocolHandler( CComBSTR( url ), FALSE );
  513. internalConf->Release();
  514. }
  515. ::CoUninitialize();
  516. }
  517. if( FAILED( result ) && notifyOnError )
  518. {
  519. TCHAR message[ MAX_PATH ];
  520. TCHAR title[ MAX_PATH ];
  521. ::LoadString( g_hInst, // handle to module containing string resource
  522. IDS_COULD_NOT_CALL, // resource identifier
  523. message, // pointer to buffer for resource
  524. ARRAY_ELEMENTS( message ) ); // size of buffer
  525. ::LoadString( g_hInst, // handle to module containing string resource
  526. IDS_LAUNCH_ERROR, // resource identifier
  527. title, // pointer to buffer for resource
  528. ARRAY_ELEMENTS( title ) ); // size of buffer
  529. ::MessageBox( NULL, message, title, MB_ICONERROR | MB_OK );
  530. }
  531. }
  532. return( result );
  533. } // End of shellCallto.
  534. ULONG STDMETHODCALLTYPE CConfLink::AddRef(void)
  535. {
  536. ULONG ulcRef;
  537. DebugEntry(CConfLink::AddRef);
  538. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  539. ulcRef = RefCount::AddRef();
  540. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  541. DebugExitULONG(CConfLink::AddRef, ulcRef);
  542. return(ulcRef);
  543. }
  544. ULONG STDMETHODCALLTYPE CConfLink::Release(void)
  545. {
  546. ULONG ulcRef;
  547. DebugEntry(CConfLink::Release);
  548. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  549. ulcRef = RefCount::Release();
  550. DebugExitULONG(CConfLink::Release, ulcRef);
  551. return(ulcRef);
  552. }
  553. HRESULT STDMETHODCALLTYPE CConfLink::QueryInterface(REFIID riid,
  554. PVOID *ppvObject)
  555. {
  556. HRESULT hr = S_OK;
  557. DebugEntry(CConfLink::QueryInterface);
  558. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  559. ASSERT(IsValidREFIID(riid));
  560. ASSERT(IS_VALID_WRITE_PTR(ppvObject, PVOID));
  561. if (riid == IID_IDataObject)
  562. {
  563. *ppvObject = (PIDataObject)this;
  564. TRACE_OUT(("CConfLink::QueryInterface(): Returning IDataObject."));
  565. }
  566. #if 0 // These are currently unsupported interfaces:
  567. else if (riid == IID_IExtractIcon)
  568. {
  569. *ppvObject = NULL;
  570. hr = E_NOINTERFACE;
  571. // *ppvObject = (PIExtractIcon)this;
  572. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IExtractIcon!"));
  573. }
  574. else if (riid == IID_INewShortcutHook)
  575. {
  576. *ppvObject = NULL;
  577. hr = E_NOINTERFACE;
  578. // *ppvObject = (PINewShortcutHook)this;
  579. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning INewShortcutHook!"));
  580. }
  581. else if (riid == IID_IShellExecuteHook)
  582. {
  583. *ppvObject = NULL;
  584. hr = E_NOINTERFACE;
  585. // *ppvObject = (PIShellExecuteHook)this;
  586. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IShellExecuteHook!"));
  587. }
  588. else if (riid == IID_IShellLink)
  589. {
  590. *ppvObject = NULL;
  591. hr = E_NOINTERFACE;
  592. // *ppvObject = (PIShellLink)this;
  593. TRACE_OUT(("CConfLink::QueryInterface(): NOT Returning IShellLink!"));
  594. }
  595. #endif /* DEBUG */
  596. // Supported interfaces:
  597. else if (riid == IID_IShellExtInit)
  598. {
  599. *ppvObject = (PIShellExtInit)this;
  600. TRACE_OUT(("CConfLink::QueryInterface(): Returning IShellExtInit."));
  601. }
  602. else if (riid == IID_IShellPropSheetExt)
  603. {
  604. *ppvObject = (PIShellPropSheetExt)this;
  605. TRACE_OUT(("CConfLink::QueryInterface(): Returning IShellPropSheetExt."));
  606. }
  607. else if (riid == IID_IPersist)
  608. {
  609. *ppvObject = (PIPersist)(PIPersistStream)this;
  610. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersist."));
  611. }
  612. else if (riid == IID_IPersistFile)
  613. {
  614. *ppvObject = (PIPersistFile)this;
  615. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersistFile."));
  616. }
  617. else if (riid == IID_IPersistStream)
  618. {
  619. *ppvObject = (PIPersistStream)this;
  620. TRACE_OUT(("CConfLink::QueryInterface(): Returning IPersistStream."));
  621. }
  622. else if (riid == IID_IConferenceLink)
  623. {
  624. *ppvObject = (PIConferenceLink)this;
  625. TRACE_OUT(("CConfLink::QueryInterface(): Returning IConferenceLink."));
  626. }
  627. else if (riid == IID_IUnknown)
  628. {
  629. *ppvObject = (PIUnknown) (PIConferenceLink) this;
  630. TRACE_OUT(("CConfLink::QueryInterface(): Returning IUnknown."));
  631. }
  632. else
  633. {
  634. TRACE_OUT(("CConfLink::QueryInterface(): Called on unknown interface."));
  635. *ppvObject = NULL;
  636. hr = E_NOINTERFACE;
  637. }
  638. if (hr == S_OK)
  639. {
  640. AddRef();
  641. }
  642. ASSERT(IS_VALID_STRUCT_PTR(this, CConfLink));
  643. DebugExitHRESULT(CConfLink::QueryInterface, hr);
  644. return(hr);
  645. }
  646. /* O P E N C O N F L I N K */
  647. /*-------------------------------------------------------------------------
  648. %%Function: OpenConfLink
  649. -------------------------------------------------------------------------*/
  650. void WINAPI OpenConfLink(HWND hwndParent, HINSTANCE hinst,
  651. PSTR pszCmdLine, int nShowCmd)
  652. {
  653. HRESULT hr;
  654. CConfLink conflink(NULL);
  655. // int nResult;
  656. DebugEntry(OpenConfLink);
  657. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  658. ASSERT(IS_VALID_HANDLE(hinst, INSTANCE));
  659. ASSERT(IS_VALID_STRING_PTR(pszCmdLine, STR));
  660. ASSERT(IsValidShowCmd(nShowCmd));
  661. // Assume the entire command line is a Conference Link file path.
  662. // TrimWhiteSpace(pszCmdLine);
  663. TRACE_OUT(("OpenConfLink(): Trying to open Conference Link %s.",
  664. pszCmdLine));
  665. #if 0
  666. TCHAR szBuf[256];
  667. wsprintf(szBuf, "Launching conference link %s", pszCmdLine);
  668. ::MessageBox( NULL,
  669. szBuf,
  670. "Conference Link Extension",
  671. MB_ICONINFORMATION);
  672. #endif
  673. hr = conflink.LoadFromFile(pszCmdLine, TRUE);
  674. if (hr == S_OK)
  675. {
  676. CLINVOKECOMMANDINFO clici;
  677. clici.dwcbSize = sizeof(clici);
  678. clici.hwndParent = hwndParent;
  679. clici.pcszVerb = NULL;
  680. clici.dwFlags = ( ICL_INVOKECOMMAND_FL_ALLOW_UI |
  681. ICL_INVOKECOMMAND_FL_USE_DEFAULT_VERB);
  682. hr = conflink.InvokeCommand(&clici);
  683. }
  684. else
  685. {
  686. // BUGBUG: need resource here INTL
  687. ::MessageBox( hwndParent,
  688. _TEXT("There was an error while identifying the conference"),
  689. _TEXT("Conference Shortcut Error"),
  690. MB_ICONINFORMATION);
  691. // if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  692. // MAKEINTRESOURCE(IDS_LOADFROMFILE_FAILED),
  693. // (MB_OK | MB_ICONEXCLAMATION), &nResult, pszCmdLine))
  694. //
  695. // ASSERT(nResult == IDOK);
  696. }
  697. DebugExitVOID(OpenConfLink);
  698. return;
  699. }
  700. /* A N Y M E A T */
  701. /*-------------------------------------------------------------------------
  702. %%Function: AnyMeat
  703. Return TRUE if the string has any non-whitespace characters
  704. -------------------------------------------------------------------------*/
  705. BOOL AnyMeat(PCSTR pcsz)
  706. {
  707. TCHAR ch;
  708. ASSERT((!pcsz) || IS_VALID_STRING_PTR(pcsz, CSTR));
  709. if (NULL == pcsz)
  710. return FALSE;
  711. while (0 != (ch = *pcsz++))
  712. {
  713. switch (ch)
  714. {
  715. case _T(' '): // Space
  716. case _T('\t'): // Tab
  717. case 0x00A0: // Non-breaking space
  718. break;
  719. default:
  720. return TRUE; // found a non-whitespace character
  721. }
  722. }
  723. return FALSE;
  724. }
  725. HRESULT MyReleaseStgMedium(PSTGMEDIUM pstgmed)
  726. {
  727. HRESULT hr;
  728. ASSERT(IS_VALID_STRUCT_PTR(pstgmed, CSTGMEDIUM));
  729. if (pstgmed->pUnkForRelease)
  730. hr = pstgmed->pUnkForRelease->Release();
  731. else
  732. {
  733. switch(pstgmed->tymed)
  734. {
  735. case TYMED_HGLOBAL:
  736. hr = (! GlobalFree(pstgmed->hGlobal)) ? S_OK : E_HANDLE;
  737. break;
  738. #if 0 /* Only TYMED_HGLOBAL is ever used */
  739. case TYMED_ISTREAM:
  740. hr = pstgmed->pstm->Release();
  741. break;
  742. case TYMED_ISTORAGE:
  743. hr = pstgmed->pstm->Release();
  744. break;
  745. case TYMED_FILE:
  746. {
  747. PIMalloc pMalloc = NULL;
  748. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  749. {
  750. pMalloc->Free(pstgmed->lpszFileName);
  751. pMalloc->Release();
  752. pMalloc = NULL;
  753. pstgmed->lpszFileName = NULL;
  754. }
  755. hr = S_OK;
  756. break;
  757. }
  758. case TYMED_GDI:
  759. hr = (DeleteObject(pstgmed->hBitmap)) ? S_OK : E_HANDLE;
  760. break;
  761. case TYMED_MFPICT:
  762. hr = (DeleteMetaFile((HMETAFILE)(pstgmed->hMetaFilePict)) &&
  763. ! GlobalFree(pstgmed->hMetaFilePict)) ? S_OK : E_HANDLE;
  764. break;
  765. case TYMED_ENHMF:
  766. hr = (DeleteEnhMetaFile(pstgmed->hEnhMetaFile)) ? S_OK : E_HANDLE;
  767. break;
  768. #endif // 0
  769. default:
  770. ASSERT(pstgmed->tymed == TYMED_NULL);
  771. hr = S_OK;
  772. break;
  773. }
  774. }
  775. return(hr);
  776. }