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.

595 lines
19 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dllmain.cpp
  5. Abstract:
  6. Implementation of DLL Exports.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 04/15/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. CComModule _Module;
  13. ////////////////////////////////////////////////////////////////////////////////
  14. HRESULT CreateObject_RemoteDesktopSession( /*[in] */ REMOTE_DESKTOP_SHARING_CLASS sharingClass ,
  15. /*[in] */ long lTimeout ,
  16. /*[in] */ BSTR bstrConnectionParms ,
  17. /*[in] */ BSTR bstrUserHelpBlob ,
  18. /*[out, retval]*/ ISAFRemoteDesktopSession* *ppRCS );
  19. HRESULT ConnectToExpert(/* [in] */ BSTR bstrExpertConnectParm,
  20. /* [in] */ LONG lTimeout,
  21. /* [retval][out] */ LONG *lSafErrorCode);
  22. HRESULT SwitchDesktopMode(/* [in]*/ int nMode,
  23. /* [in]*/ int nRAType);
  24. ////////////////////////////////////////////////////////////////////////////////
  25. #ifdef DEBUG
  26. #define LAUNCH_TIMEOUT (600) // 1 minute.
  27. #else
  28. #define LAUNCH_TIMEOUT (300) // 10 seconds.
  29. #endif
  30. ////////////////////////////////////////////////////////////////////////////////
  31. static const CLSID* pCLSID_PCHUpdate = &__uuidof( PCHUpdate );
  32. static const CLSID* pCLSID_PCHUpdateReal = &__uuidof( PCHUpdateReal );
  33. static const CLSID* pCLSID_PCHService = &__uuidof( PCHService );
  34. static const CLSID* pCLSID_PCHServiceReal = &__uuidof( PCHServiceReal );
  35. #ifndef NOJETBLUECOM
  36. static const CLSID* pCLSID_PCHDBSession = &__uuidof( PCHDBSession );
  37. static const CLSID* pCLSID_PCHDBSessionReal = &__uuidof( PCHDBSessionReal );
  38. #endif
  39. static const CLSID* pCLSID_MPCConnection = &__uuidof( MPCConnection );
  40. static const CLSID* pCLSID_MPCConnectionReal = &__uuidof( MPCConnectionReal );
  41. static const CLSID* pCLSID_MPCUpload = &__uuidof( MPCUpload );
  42. static const CLSID* pCLSID_MPCUploadReal = &__uuidof( MPCUploadReal );
  43. static const IID* pIID_IPCHService = &__uuidof( IPCHService );
  44. static const WCHAR s_szRegKey [] = L"SOFTWARE\\Microsoft\\PCHealth\\PchSvc\\Profile";
  45. ////////////////////////////////////////////////////////////////////////////////
  46. ////////////////////////////////////////////////////////////////////////////////
  47. static const WCHAR s_szCmd_HelpSvc [] = L"\"%WINDIR%\\PCHealth\\HelpCtr\\Binaries\\HelpSvc.exe\" /Embedding";
  48. static const WCHAR s_szCmd_UploadMgr [] = L"\"%WINDIR%\\PCHealth\\UploadLB\\Binaries\\UploadM.exe\" /Embedding";
  49. static CComRedirectorFactory s_HelpSvc[] =
  50. {
  51. CComRedirectorFactory( pCLSID_PCHService, pCLSID_PCHServiceReal, pIID_IPCHService, s_szCmd_HelpSvc ),
  52. CComRedirectorFactory( pCLSID_PCHUpdate , pCLSID_PCHUpdateReal , NULL , s_szCmd_HelpSvc ),
  53. #ifndef NOJETBLUECOM
  54. CComRedirectorFactory( pCLSID_PCHDBSession , pCLSID_PCHDBSessionReal , NULL , s_szCmd_HelpSvc ),
  55. #endif
  56. CComRedirectorFactory( NULL , NULL , NULL , NULL ),
  57. };
  58. static CComRedirectorFactory s_UploadMgr[] =
  59. {
  60. CComRedirectorFactory( pCLSID_MPCUpload , pCLSID_MPCUploadReal , NULL, s_szCmd_UploadMgr ),
  61. CComRedirectorFactory( pCLSID_MPCConnection, pCLSID_MPCConnectionReal, NULL, s_szCmd_UploadMgr ),
  62. CComRedirectorFactory( NULL , NULL , NULL, NULL ),
  63. };
  64. static ServiceHandler* s_Services[2];
  65. ////////////////////////////////////////////////////////////////////////////////
  66. static const WCHAR s_szCmd_RDSHost [] = L"\"%WINDIR%\\system32\\RDSHOST.exe\"";
  67. static CComRedirectorFactory g_RDSHost( NULL, &CLSID_SAFRemoteDesktopServerHost, &IID_ISAFRemoteDesktopServerHost, s_szCmd_RDSHost );
  68. HRESULT RDSHost_HACKED_CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
  69. {
  70. return g_RDSHost.CreateInstance( pUnkOuter, riid, ppvObj );
  71. }
  72. ////////////////////////////////////////////////////////////////////////////////
  73. CComRedirectorFactory::CComRedirectorFactory( const CLSID* pclsid ,
  74. const CLSID* pclsidReal ,
  75. const IID* piidDirecty ,
  76. LPCWSTR szExecutable )
  77. {
  78. m_pclsid = pclsid;
  79. m_pclsidReal = pclsidReal;
  80. m_piidDirecty = piidDirecty;
  81. m_szExecutable = szExecutable;
  82. m_dwRegister = 0;
  83. }
  84. ////////////////////
  85. STDMETHODIMP_(ULONG) CComRedirectorFactory::AddRef()
  86. {
  87. return 1;
  88. }
  89. STDMETHODIMP_(ULONG) CComRedirectorFactory::Release()
  90. {
  91. return 1;
  92. }
  93. STDMETHODIMP CComRedirectorFactory::QueryInterface(REFIID iid, void ** ppvObject)
  94. {
  95. if(ppvObject == NULL) return E_POINTER;
  96. *ppvObject = NULL;
  97. if(InlineIsEqualGUID( IID_IUnknown , iid ) ||
  98. InlineIsEqualGUID( IID_IClassFactory, iid ) )
  99. {
  100. *ppvObject = (IClassFactory*)this; // No AddRef, these objects are static...
  101. return S_OK;
  102. }
  103. else if(InlineIsEqualGUID( IID_IDispatch , iid ) ||
  104. InlineIsEqualGUID( IID_IPCHUtility, iid ) )
  105. {
  106. *ppvObject = (IPCHUtility*)this; // No AddRef, these objects are static...
  107. return S_OK;
  108. }
  109. else if(m_piidDirecty && InlineIsEqualGUID( *m_piidDirecty, iid ))
  110. {
  111. return GetServer( NULL, iid, ppvObject );
  112. }
  113. return E_NOINTERFACE;
  114. }
  115. ////////////////////
  116. STDMETHODIMP CComRedirectorFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
  117. {
  118. return StartServer( pUnkOuter, riid, ppvObj );
  119. }
  120. STDMETHODIMP CComRedirectorFactory::LockServer(BOOL fLock)
  121. {
  122. return S_OK;
  123. }
  124. ////////////////////
  125. STDMETHODIMP CComRedirectorFactory::CreateObject_RemoteDesktopSession( /*[in] */ REMOTE_DESKTOP_SHARING_CLASS sharingClass ,
  126. /*[in] */ long lTimeout ,
  127. /*[in] */ BSTR bstrConnectionParms ,
  128. /*[in] */ BSTR bstrUserHelpBlob ,
  129. /*[out, retval]*/ ISAFRemoteDesktopSession* *ppRCS )
  130. {
  131. return ::CreateObject_RemoteDesktopSession( sharingClass ,
  132. lTimeout ,
  133. bstrConnectionParms ,
  134. bstrUserHelpBlob ,
  135. ppRCS );
  136. }
  137. ////////////////////
  138. STDMETHODIMP CComRedirectorFactory::ConnectToExpert(/* [in] */ BSTR bstrExpertConnectParm,
  139. /* [in] */ LONG lTimeout,
  140. /* [retval][out] */ LONG *lSafErrorCode)
  141. {
  142. return ::ConnectToExpert( bstrExpertConnectParm,
  143. lTimeout,
  144. lSafErrorCode);
  145. }
  146. ////////////////////
  147. STDMETHODIMP CComRedirectorFactory::SwitchDesktopMode(/* [in]*/ int nMode,
  148. /* [in]*/ int nRAType)
  149. {
  150. return ::SwitchDesktopMode(nMode, nRAType);
  151. }
  152. ////////////////////
  153. HRESULT CComRedirectorFactory::GetServer( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
  154. {
  155. return ::CoCreateInstance( *m_pclsidReal, pUnkOuter, CLSCTX_LOCAL_SERVER, riid, ppvObj );
  156. }
  157. bool CComRedirectorFactory::GetCommandLine( /*[out]*/ WCHAR* rgCommandLine, /*[in]*/ DWORD dwSize, /*[out]*/ bool& fProfiling )
  158. {
  159. fProfiling = false;
  160. //
  161. // If there's a string value in the registry for this CLSID, prepend the command line with it.
  162. //
  163. {
  164. WCHAR rgGUID[128];
  165. if(::StringFromGUID2 ( *m_pclsid, rgGUID, MAXSTRLEN(rgGUID) ) > 0)
  166. {
  167. HKEY hKey;
  168. if(::RegOpenKeyExW( HKEY_LOCAL_MACHINE, s_szRegKey, 0, KEY_READ, &hKey ) == ERROR_SUCCESS)
  169. {
  170. WCHAR rgVALUE[MAX_PATH*3];
  171. DWORD dwVALUE = sizeof(rgVALUE)-1;
  172. DWORD dwType;
  173. if(::RegQueryValueExW( hKey, rgGUID, NULL, &dwType, (BYTE*)rgVALUE, &dwVALUE ) == ERROR_SUCCESS && dwType == REG_SZ)
  174. {
  175. rgVALUE[dwVALUE/sizeof(WCHAR)] = 0;
  176. if((dwVALUE = ::ExpandEnvironmentStringsW( rgVALUE, rgCommandLine, dwSize )))
  177. {
  178. rgCommandLine[dwVALUE-1] = ' '; // Padding space.
  179. rgCommandLine += dwVALUE;
  180. dwSize -= dwVALUE;
  181. fProfiling = true;
  182. }
  183. }
  184. ::RegCloseKey( hKey );
  185. }
  186. }
  187. }
  188. //
  189. // Prepare the command line.
  190. //
  191. if(::ExpandEnvironmentStringsW( m_szExecutable, rgCommandLine, dwSize ))
  192. {
  193. return true;
  194. }
  195. return false;
  196. }
  197. HRESULT CComRedirectorFactory::StartServer( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj )
  198. {
  199. HRESULT hr;
  200. if(FAILED(hr = GetServer( pUnkOuter, riid, ppvObj )))
  201. {
  202. WCHAR rgCommandLine[MAX_PATH*3];
  203. bool fProfiling;
  204. ::EnterCriticalSection( &m_sec );
  205. //
  206. // Prepare the command line.
  207. //
  208. if(GetCommandLine( rgCommandLine, MAXSTRLEN(rgCommandLine), fProfiling ))
  209. {
  210. PROCESS_INFORMATION piProcessInformation;
  211. STARTUPINFOW siStartupInfo;
  212. BOOL fStarted;
  213. ::ZeroMemory( (PVOID)&piProcessInformation, sizeof( piProcessInformation ) );
  214. ::ZeroMemory( (PVOID)&siStartupInfo , sizeof( siStartupInfo ) ); siStartupInfo.cb = sizeof( siStartupInfo );
  215. //
  216. // Start the process, changing the WinStation to the console one in case of profiling.
  217. //
  218. {
  219. if(fProfiling)
  220. {
  221. // siStartupInfo.lpDesktop = L"WinSta0\\Default";
  222. }
  223. fStarted = ::CreateProcessW( NULL ,
  224. rgCommandLine ,
  225. NULL ,
  226. NULL ,
  227. FALSE ,
  228. NORMAL_PRIORITY_CLASS ,
  229. NULL ,
  230. NULL ,
  231. &siStartupInfo ,
  232. &piProcessInformation );
  233. }
  234. if(fStarted)
  235. {
  236. int iCount = LAUNCH_TIMEOUT;
  237. if(fProfiling) iCount *= 10; // Give more time to start.
  238. while(iCount-- > 0)
  239. {
  240. if(::WaitForSingleObject( piProcessInformation.hProcess, 100 ) != WAIT_TIMEOUT) break; // Process bailed out.
  241. if(SUCCEEDED(hr = GetServer( pUnkOuter, riid, ppvObj ))) break;
  242. }
  243. if(FAILED(hr))
  244. {
  245. ::TerminateProcess( piProcessInformation.hProcess, 0 );
  246. }
  247. }
  248. if(piProcessInformation.hProcess) ::CloseHandle( piProcessInformation.hProcess );
  249. if(piProcessInformation.hThread ) ::CloseHandle( piProcessInformation.hThread );
  250. }
  251. ::LeaveCriticalSection( &m_sec );
  252. }
  253. return hr;
  254. }
  255. HRESULT CComRedirectorFactory::Register()
  256. {
  257. ::InitializeCriticalSection( &m_sec );
  258. if(!m_pclsid) return S_OK;
  259. return ::CoRegisterClassObject( *m_pclsid ,
  260. (IClassFactory*)this ,
  261. CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER ,
  262. REGCLS_MULTIPLEUSE ,
  263. &m_dwRegister );
  264. }
  265. void CComRedirectorFactory::Unregister()
  266. {
  267. if(m_dwRegister)
  268. {
  269. ::CoRevokeClassObject( m_dwRegister );
  270. m_dwRegister = 0;
  271. }
  272. ::DeleteCriticalSection( &m_sec );
  273. }
  274. ////////////////////////////////////////////////////////////////////////////////
  275. ServiceHandler::ServiceHandler( /*[in]*/ LPCWSTR szServiceName, /*[in]*/ CComRedirectorFactory* rgClasses )
  276. {
  277. m_szServiceName = szServiceName; // LPCWSTR m_szServiceName;
  278. m_rgClasses = rgClasses; // CComRedirectorFactory* m_rgClasses;
  279. //
  280. m_fComInitialized = false; // bool m_fComInitialized;
  281. //
  282. m_hShutdownEvent = NULL; // HANDLE m_hShutdownEvent;
  283. //
  284. // SERVICE_STATUS_HANDLE m_hServiceStatus;
  285. // SERVICE_STATUS m_status;
  286. ::ZeroMemory( &m_status, sizeof( m_status ) );
  287. m_status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  288. m_status.dwCurrentState = SERVICE_STOPPED;
  289. m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  290. m_status.dwWin32ExitCode = 0;
  291. m_status.dwServiceSpecificExitCode = 0;
  292. m_status.dwCheckPoint = 0;
  293. m_status.dwWaitHint = 0;
  294. }
  295. /////////////////////////////////////////////////////////////////////////////
  296. // DLL Entry Point
  297. extern "C"
  298. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  299. {
  300. if(dwReason == DLL_PROCESS_ATTACH)
  301. {
  302. _Module.Init( NULL, hInstance, NULL );
  303. DisableThreadLibraryCalls( hInstance );
  304. s_Services[0] = new ServiceHandler_HelpSvc( L"HelpSvc" , s_HelpSvc );
  305. s_Services[1] = new ServiceHandler ( L"UploadMgr", s_UploadMgr );
  306. g_RDSHost.Register();
  307. }
  308. else if(dwReason == DLL_PROCESS_DETACH)
  309. {
  310. delete s_Services[0];
  311. delete s_Services[1];
  312. g_RDSHost.Unregister();
  313. _Module.Term();
  314. }
  315. return TRUE; // ok
  316. }
  317. DWORD WINAPI _HandlerEx( DWORD dwControl , // requested control code
  318. DWORD dwEventType , // event type
  319. LPVOID lpEventData , // event data
  320. LPVOID lpContext ) // user-defined context data
  321. {
  322. ServiceHandler* handler = static_cast<ServiceHandler*>(lpContext);
  323. return handler->HandlerEx( dwControl , // requested control code
  324. dwEventType , // event type
  325. lpEventData ); // user-defined context data
  326. }
  327. void WINAPI ServiceMain( DWORD dwArgc, LPWSTR* lpszArgv )
  328. {
  329. #if 0
  330. BOOL fWait = true;
  331. while(fWait)
  332. {
  333. Sleep(1000);
  334. }
  335. #endif
  336. LPWSTR szName = lpszArgv[0];
  337. ServiceHandler** ph = s_Services;
  338. int i;
  339. for(i=0; i<ARRAYSIZE(s_Services); i++)
  340. {
  341. ServiceHandler* h = *ph++;
  342. if(h && !_wcsicmp( h->m_szServiceName, szName ))
  343. {
  344. h->Run(); break;
  345. }
  346. }
  347. }
  348. ////////////////////////////////////////////////////////////////////////////////
  349. DWORD ServiceHandler::HandlerEx( DWORD dwControl , // requested control code
  350. DWORD dwEventType , // event type
  351. LPVOID lpEventData ) // event data
  352. {
  353. switch(dwControl)
  354. {
  355. case SERVICE_CONTROL_STOP:
  356. SetServiceStatus( SERVICE_STOP_PENDING );
  357. if(m_hShutdownEvent) ::SetEvent( m_hShutdownEvent );
  358. break;
  359. case SERVICE_CONTROL_PAUSE:
  360. break;
  361. case SERVICE_CONTROL_CONTINUE:
  362. break;
  363. case SERVICE_CONTROL_INTERROGATE:
  364. break;
  365. case SERVICE_CONTROL_SHUTDOWN:
  366. break;
  367. default:
  368. return ERROR_CALL_NOT_IMPLEMENTED;
  369. }
  370. return NO_ERROR;
  371. }
  372. HRESULT ServiceHandler::Initialize()
  373. {
  374. __MPC_FUNC_ENTRY( COMMONID, "ServiceHandler::Initialize" );
  375. HRESULT hr;
  376. m_status.dwWin32ExitCode = S_OK;
  377. m_status.dwCheckPoint = 0;
  378. m_status.dwWaitHint = 0;
  379. try
  380. {
  381. CComRedirectorFactory* classes;
  382. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (m_hServiceStatus = ::RegisterServiceCtrlHandlerExW( m_szServiceName, _HandlerEx, this )));
  383. SetServiceStatus( SERVICE_START_PENDING );
  384. ////////////////////
  385. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CoInitializeEx( NULL, COINIT_MULTITHREADED ));
  386. m_fComInitialized = true;
  387. for(classes=m_rgClasses; SUCCEEDED(hr) && classes->m_pclsid; classes++)
  388. {
  389. __MPC_EXIT_IF_METHOD_FAILS(hr, classes->Register());
  390. }
  391. ////////////////////
  392. __MPC_EXIT_IF_CALL_RETURNS_NULL(hr, (m_hShutdownEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL )));
  393. SetServiceStatus( SERVICE_RUNNING );
  394. }
  395. catch(...)
  396. {
  397. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  398. }
  399. hr = S_OK;
  400. __MPC_FUNC_CLEANUP;
  401. __MPC_FUNC_EXIT(hr);
  402. }
  403. void ServiceHandler::WaitUntilStopped()
  404. {
  405. if(m_hShutdownEvent) ::WaitForSingleObject( m_hShutdownEvent, INFINITE );
  406. }
  407. void ServiceHandler::Cleanup()
  408. {
  409. if(m_hShutdownEvent)
  410. {
  411. ::CloseHandle( m_hShutdownEvent );
  412. m_hShutdownEvent = NULL;
  413. }
  414. try
  415. {
  416. if(m_fComInitialized)
  417. {
  418. CComRedirectorFactory* classes;
  419. for(classes=m_rgClasses; classes->m_pclsid; classes++)
  420. {
  421. classes->Unregister();
  422. }
  423. ::CoUninitialize();
  424. m_fComInitialized = false;
  425. }
  426. }
  427. catch(...)
  428. {
  429. }
  430. if(m_hServiceStatus)
  431. {
  432. SetServiceStatus( SERVICE_STOPPED );
  433. m_hServiceStatus = NULL;
  434. }
  435. }
  436. void ServiceHandler::Run()
  437. {
  438. //
  439. // When the Run function returns, the service has been stopped.
  440. //
  441. if(SUCCEEDED(Initialize()))
  442. {
  443. WaitUntilStopped();
  444. }
  445. Cleanup();
  446. }
  447. void ServiceHandler::SetServiceStatus( DWORD dwState )
  448. {
  449. m_status.dwCurrentState = dwState;
  450. ::SetServiceStatus( m_hServiceStatus, &m_status );
  451. }