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.

458 lines
13 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. HCApiLib.cpp
  5. Abstract:
  6. This file contains the implementation of the HCApi Library.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 04/15/2000
  9. created
  10. ******************************************************************************/
  11. #include "StdAfx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. static const WCHAR c_HelpCtr[] = HC_ROOT_HELPSVC_BINARIES L"\\HelpCtr.exe";
  14. ////////////////////////////////////////////////////////////////////////////////
  15. HCAPI::CmdData::CmdData()
  16. {
  17. // BUILD BREAK m_clsidCaller = CLSID_PCHHelpCenterIPC; // CLSID m_clsidCaller;
  18. //
  19. m_fSize = false; // bool m_fSize;
  20. m_lX = 0; // LONG m_lX;
  21. m_lY = 0; // LONG m_lY;
  22. m_lWidth = 0; // LONG m_lWidth;
  23. m_lHeight = 0; // LONG m_lHeight;
  24. //
  25. m_fMode = false; // bool m_fMode;
  26. m_dwFlags = 0; // DWORD m_dwFlags;
  27. //
  28. m_fWindow = false; // bool m_fWindow;
  29. m_hwndParent = NULL; // HWND m_hwndParent;
  30. //
  31. m_fCtx = false; // bool m_fCtx;
  32. // CComBSTR m_bstrCtx;
  33. //
  34. m_fURL = false; // bool m_fURL;
  35. // CComBSTR m_bstrURL;
  36. //
  37. m_fError = false; // bool m_fError;
  38. m_clsidError = CLSID_NULL; // CLSID m_clsidError;
  39. }
  40. HRESULT HCAPI::CmdData::Serialize( /*[out]*/ CComBSTR& bstrBLOB )
  41. {
  42. __HCP_FUNC_ENTRY( "HCAPI::CmdData::Serialize" );
  43. HRESULT hr;
  44. MPC::Serializer_Memory streamMem;
  45. MPC::Serializer& stream = streamMem;
  46. HGLOBAL hg = NULL;
  47. //
  48. // Dump the state of the object into the serializer.
  49. //
  50. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_clsidCaller );
  51. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fMode );
  52. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_dwFlags );
  53. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fWindow );
  54. __MPC_EXIT_IF_METHOD_FAILS(hr, stream.HWND_write( m_hwndParent ));
  55. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fSize );
  56. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_lX );
  57. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_lY );
  58. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_lWidth );
  59. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_lHeight );
  60. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fCtx );
  61. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrCtxName );
  62. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrCtxInfo );
  63. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fURL );
  64. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrURL );
  65. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fError );
  66. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_clsidError );
  67. //
  68. // Copy data into an HGLOBAL.
  69. //
  70. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (hg = ::GlobalAlloc( GMEM_FIXED, streamMem.GetSize() )));
  71. ::CopyMemory( hg, streamMem.GetData(), streamMem.GetSize() );
  72. //
  73. // Convert to string.
  74. //
  75. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertHGlobalToHex( hg, bstrBLOB ));
  76. hr = S_OK;
  77. __HCP_FUNC_CLEANUP;
  78. if(hg) ::GlobalFree( hg );
  79. __HCP_FUNC_EXIT(hr);
  80. }
  81. HRESULT HCAPI::CmdData::Unserialize( /*[in]*/ const CComBSTR& bstrBLOB )
  82. {
  83. __HCP_FUNC_ENTRY( "HCAPI::CmdData::Unserialize" );
  84. HRESULT hr;
  85. MPC::Serializer_Memory streamMem;
  86. MPC::Serializer& stream = streamMem;
  87. HGLOBAL hg = NULL;
  88. //
  89. // Convert from string.
  90. //
  91. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertHexToHGlobal( bstrBLOB, hg ));
  92. //
  93. // Copy data from an HGLOBAL.
  94. //
  95. __MPC_EXIT_IF_METHOD_FAILS(hr, streamMem.SetSize( ::GlobalSize( hg ) ));
  96. __MPC_EXIT_IF_METHOD_FAILS(hr, streamMem.write ( ::GlobalLock( hg ), ::GlobalSize( hg ) ));
  97. //
  98. // Read the state of the object from the serializer.
  99. //
  100. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_clsidCaller );
  101. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fMode );
  102. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_dwFlags );
  103. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fWindow );
  104. __MPC_EXIT_IF_METHOD_FAILS(hr, stream.HWND_read( m_hwndParent ));
  105. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fSize );
  106. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_lX );
  107. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_lY );
  108. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_lWidth );
  109. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_lHeight );
  110. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fCtx );
  111. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrCtxName );
  112. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrCtxInfo );
  113. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fURL );
  114. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrURL );
  115. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fError );
  116. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_clsidError );
  117. hr = S_OK;
  118. __HCP_FUNC_CLEANUP;
  119. if(hg) ::GlobalFree( hg );
  120. __HCP_FUNC_EXIT(hr);
  121. }
  122. ////////////////////////////////////////////////////////////////////////////////
  123. ////////////////////////////////////////////////////////////////////////////////
  124. ////////////////////////////////////////////////////////////////////////////////
  125. HCAPI::Locator::Locator()
  126. {
  127. // CComPtr<IPCHHelpCenterIPC> m_ipc;
  128. // CComPtr<IRunningObjectTable> m_rt;
  129. // CComPtr<IMoniker> m_moniker;
  130. m_dwRegister = 0; // DWORD m_dwRegister;
  131. }
  132. HCAPI::Locator::~Locator()
  133. {
  134. Cleanup();
  135. }
  136. ////////////////////
  137. void HCAPI::Locator::Cleanup()
  138. {
  139. if(m_rt)
  140. {
  141. if(m_dwRegister)
  142. {
  143. (void)m_rt->Revoke( m_dwRegister );
  144. m_dwRegister = NULL;
  145. }
  146. }
  147. m_ipc .Release();
  148. m_rt .Release();
  149. m_moniker.Release();
  150. }
  151. HRESULT HCAPI::Locator::Init( /*[in]*/ REFCLSID clsid, /*[in]*/ IPCHHelpCenterIPC* ipc )
  152. {
  153. __HCP_FUNC_ENTRY( "HCAPI::Locator::Init" );
  154. HRESULT hr;
  155. Cleanup();
  156. //
  157. // Get a pointer to the ROT and create a class moniker.
  158. //
  159. __MPC_EXIT_IF_METHOD_FAILS(hr, ::GetRunningObjectTable( 0, &m_rt ));
  160. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateClassMoniker( clsid, &m_moniker ));
  161. //
  162. // If IPC != NULL, register as provider, otherwise look for a provider.
  163. //
  164. if(ipc)
  165. {
  166. __MPC_EXIT_IF_METHOD_FAILS(hr, m_rt->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE, ipc, m_moniker, &m_dwRegister ));
  167. }
  168. else
  169. {
  170. CComPtr<IUnknown> obj;
  171. if(SUCCEEDED(m_rt->GetObject( m_moniker, &obj )) && obj)
  172. {
  173. // BUILD BREAK __MPC_EXIT_IF_METHOD_FAILS(hr, obj->QueryInterface( IID_IPCHHelpCenterIPC, (void**)&m_ipc ));
  174. }
  175. }
  176. hr = S_OK;
  177. __HCP_FUNC_CLEANUP;
  178. __HCP_FUNC_EXIT(hr);
  179. }
  180. ////////////////////////////////////////
  181. HRESULT HCAPI::Locator::IsOpen( /*[out]*/ bool& fOpen, /*[in]*/ CLSID* pclsid )
  182. {
  183. __HCP_FUNC_ENTRY( "HCAPI::Locator::IsOpen" );
  184. HRESULT hr;
  185. fOpen = false;
  186. if(m_ipc == NULL)
  187. {
  188. // BUILD BREAK __MPC_EXIT_IF_METHOD_FAILS(hr, Init( pclsid ? *pclsid : CLSID_PCHHelpCenterIPC ));
  189. }
  190. // BUILD BREAK if(m_ipc && SUCCEEDED(m_ipc->Ping()))
  191. // BUILD BREAK {
  192. // BUILD BREAK fOpen = true;
  193. // BUILD BREAK }
  194. hr = S_OK;
  195. // BUILD BREAK __HCP_FUNC_CLEANUP;
  196. __HCP_FUNC_EXIT(hr);
  197. }
  198. HRESULT HCAPI::Locator::ExecCommand( /*[out]*/ CmdData& cd )
  199. {
  200. __HCP_FUNC_ENTRY( "HCAPI::Locator::ExecCommand" );
  201. HRESULT hr;
  202. PROCESS_INFORMATION piProcessInformation;
  203. STARTUPINFOW siStartupInfo;
  204. MPC::NamedMutex nm( L"PCH_COMSERVER" );
  205. CComBSTR bstrBLOB;
  206. bool fOpen;
  207. ::ZeroMemory( (PVOID)&piProcessInformation, sizeof( piProcessInformation ) );
  208. ::ZeroMemory( (PVOID)&siStartupInfo , sizeof( siStartupInfo ) ); siStartupInfo.cb = sizeof( siStartupInfo );
  209. __MPC_EXIT_IF_METHOD_FAILS(hr, cd.Serialize( bstrBLOB ));
  210. //
  211. // Before entrying this section, let's acquire the shared mutex, so only one instance of HelpCtr at a time will execute it.
  212. //
  213. __MPC_EXIT_IF_METHOD_FAILS(hr, nm.Acquire( 0 ));
  214. if(cd.m_fMode)
  215. {
  216. if(cd.m_dwFlags & HCAPI_MODE_NEW_INSTANCE)
  217. {
  218. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateGuid( &cd.m_clsidCaller ));
  219. }
  220. }
  221. __MPC_EXIT_IF_METHOD_FAILS(hr, IsOpen( fOpen, &cd.m_clsidCaller ));
  222. if(fOpen)
  223. {
  224. // __MPC_EXIT_IF_METHOD_FAILS(hr, m_ipc->Navigate( bstrBLOB ));
  225. }
  226. else
  227. {
  228. MPC::wstring strExe( c_HelpCtr ); MPC::SubstituteEnvVariables( strExe );
  229. int iRetries = 100;
  230. strExe += L" -cmd ";
  231. strExe += SAFEBSTR( bstrBLOB );
  232. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::CreateProcessW( NULL ,
  233. (LPWSTR)strExe.c_str() ,
  234. NULL ,
  235. NULL ,
  236. FALSE ,
  237. NORMAL_PRIORITY_CLASS,
  238. NULL ,
  239. NULL ,
  240. &siStartupInfo ,
  241. &piProcessInformation ));
  242. while(iRetries--)
  243. {
  244. ::Sleep( 100 );
  245. if(SUCCEEDED(Init( cd.m_clsidCaller ))) break;
  246. }
  247. __MPC_EXIT_IF_METHOD_FAILS(hr, IsOpen( fOpen, &cd.m_clsidCaller ));
  248. }
  249. //
  250. // If successful, clean the command, but not the caller, it's used to located the same instance of the Help Center.
  251. //
  252. cd.m_fSize = false;
  253. cd.m_fMode = false;
  254. cd.m_fWindow = false;
  255. cd.m_fCtx = false;
  256. cd.m_fURL = false;
  257. cd.m_fError = false;
  258. hr = S_OK;
  259. __HCP_FUNC_CLEANUP;
  260. if(piProcessInformation.hProcess) ::CloseHandle( piProcessInformation.hProcess );
  261. if(piProcessInformation.hThread ) ::CloseHandle( piProcessInformation.hThread );
  262. __HCP_FUNC_EXIT(hr);
  263. }
  264. HRESULT HCAPI::Locator::PopUp()
  265. {
  266. __HCP_FUNC_ENTRY( "HCAPI::Locator::PopUp" );
  267. HRESULT hr;
  268. bool fOpen;
  269. __MPC_EXIT_IF_METHOD_FAILS(hr, IsOpen( fOpen ));
  270. if(fOpen == false)
  271. {
  272. CmdData cd;
  273. __MPC_EXIT_IF_METHOD_FAILS(hr, ExecCommand( cd ));
  274. }
  275. // BUILD BREAK __MPC_EXIT_IF_METHOD_FAILS(hr, m_ipc->Popup());
  276. hr = S_OK;
  277. __HCP_FUNC_CLEANUP;
  278. __HCP_FUNC_EXIT(hr);
  279. }
  280. HRESULT HCAPI::Locator::Close()
  281. {
  282. __HCP_FUNC_ENTRY( "HCAPI::Locator::Close" );
  283. HRESULT hr;
  284. bool fOpen;
  285. __MPC_EXIT_IF_METHOD_FAILS(hr, IsOpen( fOpen ));
  286. if(fOpen)
  287. {
  288. // BUILD BREAK __MPC_EXIT_IF_METHOD_FAILS(hr, m_ipc->Close());
  289. m_ipc.Release();
  290. }
  291. hr = S_OK;
  292. __HCP_FUNC_CLEANUP;
  293. __HCP_FUNC_EXIT(hr);
  294. }
  295. HRESULT HCAPI::Locator::WaitForTermination( /*[in]*/ DWORD dwTimeout )
  296. {
  297. __HCP_FUNC_ENTRY( "HCAPI::Locator::WaitForTermination" );
  298. HRESULT hr;
  299. bool fOpen;
  300. //
  301. // Polling implementation...
  302. //
  303. while(1)
  304. {
  305. DWORD dwWait;
  306. __MPC_EXIT_IF_METHOD_FAILS(hr, IsOpen( fOpen ));
  307. if(fOpen == false) break;
  308. if(dwTimeout == 0)
  309. {
  310. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_TIMEOUT);
  311. }
  312. if(dwTimeout == INFINITE)
  313. {
  314. ::Sleep( 100 );
  315. }
  316. else
  317. {
  318. dwWait = min( dwTimeout, 10 );
  319. ::Sleep( dwWait );
  320. dwTimeout -= dwWait;
  321. }
  322. }
  323. hr = S_OK;
  324. __HCP_FUNC_CLEANUP;
  325. __HCP_FUNC_EXIT(hr);
  326. }