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.

593 lines
16 KiB

  1. /*---------------------------------------------------------------------------
  2. File: AgentRpc.cpp
  3. Comments: RPC interface for DCT Agent service
  4. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  5. Proprietary and confidential to Mission Critical Software, Inc.
  6. REVISION LOG ENTRY
  7. Revision By: Christy Boles
  8. Revised on 02/19/99 11:39:58
  9. ---------------------------------------------------------------------------
  10. */
  11. #include <windows.h>
  12. #include <objbase.h>
  13. #include "AgSvc.h"
  14. #include "Common.hpp"
  15. #include "UString.hpp"
  16. #include "Err.hpp"
  17. #include "TEvent.hpp"
  18. #include "EaLen.hpp"
  19. #include "Cipher.hpp"
  20. #include "IsAdmin.hpp"
  21. #include "ResStr.h"
  22. //#import "\bin\McsVarSetMin.tlb" no_namespace, named_guids
  23. //#import "\bin\MCSEADCTAgent.tlb" no_namespace, named_guids
  24. #import "VarSet.tlb" no_namespace, named_guids rename("property", "aproperty")
  25. #import "Engine.tlb" no_namespace, named_guids
  26. #include "TNode.hpp"
  27. #ifdef OFA
  28. #include "atlbase.h"
  29. #endif
  30. extern LPSTREAM pStream;
  31. extern TErrorEventLog err;
  32. extern BOOL gSuicide;
  33. extern BOOL gDebug;
  34. extern BOOL gLocallyInstalled;
  35. extern BOOL gbFinished;
  36. extern BOOL gbIsNt351;
  37. extern StringLoader gString;
  38. DWORD RemoveService();
  39. DWORD UnregisterFiles();
  40. DWORD RemoveFiles();
  41. DWORD RegisterDLL(const WCHAR * filename);
  42. DWORD RegisterExe(const WCHAR * filename);
  43. BOOL IsLocallyInstalled();
  44. DWORD __stdcall
  45. ShutdownService(
  46. /* [in] */ DWORD bFlags
  47. );
  48. TNodeList gJobList;
  49. class TJobNode : public TNode
  50. {
  51. WCHAR guid[LEN_Guid];
  52. public:
  53. TJobNode(WCHAR const * id) { safecopy(guid,id); }
  54. WCHAR const * JobID() { return guid; }
  55. };
  56. // thread entry point, waits for the specified job to end,
  57. // then shuts down the DCTAgentService
  58. DWORD __stdcall
  59. MonitorJob(
  60. void * arg // in - BSTR job ID
  61. )
  62. {
  63. HRESULT hr = CoInitialize(NULL);
  64. _bstr_t jobID = (BSTR)arg;
  65. IDCTAgent * pLocalAgent = NULL;
  66. BOOL bDone = FALSE;
  67. try {
  68. // Get a pointer to the local agent
  69. if ( SUCCEEDED(hr) )
  70. {
  71. hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
  72. if ( SUCCEEDED(hr) )
  73. {
  74. // Reset the stream to the beginning
  75. LARGE_INTEGER offset = { 0,0 };
  76. ULARGE_INTEGER result = { 0,0 };
  77. hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
  78. }
  79. // Get the status of the job
  80. IUnknown * pUnk = NULL;
  81. if ( SUCCEEDED(hr) )
  82. {
  83. do {
  84. hr = pLocalAgent->raw_QueryJobStatus(jobID,&pUnk);
  85. if ( SUCCEEDED(hr) )
  86. {
  87. IVarSetPtr pVarSet = pUnk;
  88. _bstr_t status = pVarSet->get(GET_BSTR(DCTVS_JobStatus));
  89. if ( gDebug )
  90. {
  91. //* err.DbgMsgWrite(0,L"Monitoring job %ls, Status: %ls",(WCHAR*)jobID, (WCHAR*)status);
  92. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONJOBSTAT),(WCHAR*)jobID, (WCHAR*)status);
  93. }
  94. if ( ! UStrICmp(status,GET_STRING(IDS_DCT_Status_Completed)) )
  95. {
  96. bDone = TRUE;
  97. break;
  98. }
  99. }
  100. pUnk->Release();
  101. pUnk = NULL;
  102. Sleep(60*1000); // one minute
  103. }
  104. while ( SUCCEEDED(hr) );
  105. // int x = pLocalAgent->Release();
  106. pLocalAgent->Release();
  107. }
  108. // TODO: make this an option
  109. if ( bDone )
  110. {
  111. hr = ShutdownService(0);
  112. }
  113. CoUninitialize();
  114. }
  115. }
  116. catch ( ... )
  117. {
  118. //* err.DbgMsgWrite(0,L"An exception occurred while monitoring the job. Shutting down the agent service.");
  119. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONERROR));
  120. try {
  121. pLocalAgent->Release();
  122. }
  123. catch ( ... )
  124. {
  125. }
  126. }
  127. if ( gDebug )
  128. //* err.DbgMsgWrite(0,L"MonitorJob exiting, hr = %lx",hr);
  129. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_MONEXIT),hr);
  130. return hr;
  131. }
  132. DWORD
  133. AuthenticateClient(
  134. handle_t hBinding // in - binding for client call
  135. )
  136. {
  137. DWORD rc;
  138. rc = RpcImpersonateClient(hBinding);
  139. if ( rc )
  140. {
  141. err.SysMsgWrite(ErrE,rc,DCT_MSG_FAILED_TO_IMPERSONATE_D,rc);
  142. }
  143. else
  144. {
  145. rc = IsAdminLocal();
  146. if ( rc )
  147. {
  148. err.SysMsgWrite(ErrE,rc,DCT_MSG_CLIENT_NOT_ADMIN_D, rc);
  149. }
  150. RpcRevertToSelf();
  151. }
  152. return rc;
  153. }
  154. DWORD
  155. RegisterPlugInFiles(
  156. IVarSet * pVarSet
  157. )
  158. {
  159. DWORD rc = 0;
  160. WCHAR key[MAX_PATH + 50];
  161. int nFiles = 0;
  162. _bstr_t filename;
  163. do
  164. {
  165. if ( gDebug )
  166. //* err.DbgMsgWrite(0,L"Starting plug-in file registration.");
  167. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_STARTPLUGREG));
  168. swprintf(key,GET_STRING(IDS_DCTVSFmt_PlugIn_RegisterFiles_D),nFiles);
  169. filename = pVarSet->get(key);
  170. if ( filename.length() != 0 )
  171. {
  172. if ( gDebug )
  173. //* err.DbgMsgWrite(0,L"File %ld = %ls",nFiles,(WCHAR*)filename);
  174. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_FILEREG),nFiles,(WCHAR*)filename);
  175. if ( !UStrICmp((WCHAR *)filename + filename.length() - 4,L".DLL") )
  176. {
  177. RegisterDLL(filename);
  178. }
  179. else
  180. {
  181. RegisterExe(filename);
  182. }
  183. nFiles++;
  184. }
  185. } while (filename.length() != 0);
  186. if ( gDebug )
  187. //* err.DbgMsgWrite(0,L"Done Registering plug-in files.");
  188. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_PLUGREGDONE));
  189. return rc;
  190. }
  191. DWORD __stdcall
  192. EaxsSubmitJob(
  193. /* [in] */ handle_t hBinding,
  194. /* [string][in] */ const WCHAR __RPC_FAR *filename,
  195. /* [string][in] */ const WCHAR __RPC_FAR *extra,
  196. /* [size_is][string][out] */ WCHAR __RPC_FAR *jobGUID
  197. )
  198. {
  199. HRESULT hr = 0;
  200. WCHAR filenameW[MAX_PATH];
  201. WCHAR pathW[MAX_PATH];
  202. IDCTAgent * pLocalAgent = NULL;
  203. // BOOL bFileCopied = FALSE;
  204. BOOL gbDeleteOnCompletion = FALSE;
  205. // Make sure the client is an admin on the local machine, otherwise, forget it
  206. hr = AuthenticateClient(hBinding);
  207. if ( hr )
  208. {
  209. return hr;
  210. }
  211. hr = CoInitialize(NULL);
  212. if ( FAILED(hr) )
  213. {
  214. err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
  215. return hr;
  216. }
  217. safecopy(filenameW,filename);
  218. // get the path for our install directory
  219. if ( ! GetModuleFileName(NULL,pathW,DIM(pathW)) )
  220. {
  221. hr = GetLastError();
  222. safecopy(pathW,filenameW);
  223. err.SysMsgWrite(ErrW,hr,DCT_MSG_GET_MODULE_PATH_FAILED_D,hr);
  224. }
  225. else
  226. {
  227. UStrCpy(pathW + UStrLen(pathW) - UStrLen(GET_STRING(IDS_SERVICE_EXE)),filenameW, DIM(pathW));
  228. }
  229. hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
  230. // interface pointer requested in riid);
  231. if ( SUCCEEDED(hr) )
  232. {
  233. // Reset the stream to the beginning
  234. LARGE_INTEGER offset = { 0,0 };
  235. ULARGE_INTEGER result = { 0,0 };
  236. hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
  237. BSTR jobID = NULL;
  238. // Read the varset data from the file
  239. IVarSetPtr pVarSet;
  240. IStoragePtr store = NULL;
  241. // Try to create the COM objects
  242. hr = pVarSet.CreateInstance(CLSID_VarSet);
  243. if ( SUCCEEDED(hr) )
  244. {
  245. // Read the VarSet from the data file
  246. hr = StgOpenStorage(pathW,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,NULL,0,&store);
  247. if ( SUCCEEDED(hr) )
  248. {
  249. // Load the data into a new varset
  250. hr = OleLoad(store,IID_IUnknown,NULL,(void **)&pVarSet);
  251. if ( SUCCEEDED(hr) )
  252. {
  253. _bstr_t text = pVarSet->get(GET_BSTR(DCTVS_Options_DeleteFileAfterLoad));
  254. if ( !UStrICmp(text,GET_STRING(IDS_YES)) )
  255. {
  256. // Free the storage pointer to the file
  257. store = NULL;
  258. if ( DeleteFile(pathW) )
  259. {
  260. if ( gDebug )
  261. //* err.DbgMsgWrite(0,L"Deleted job file %ls",pathW);
  262. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_JOBDEL),pathW);
  263. }
  264. else
  265. {
  266. err.SysMsgWrite(ErrW,GetLastError(),DCT_MSG_JOB_FILE_NOT_DELETED_SD,pathW,GetLastError());
  267. }
  268. }
  269. text = pVarSet->get(GET_BSTR(DCTVS_Options_RemoveAgentOnCompletion));
  270. if ( !UStrICmp(text,GET_STRING(IDS_YES)))
  271. {
  272. gbDeleteOnCompletion = TRUE;
  273. }
  274. text = pVarSet->get(GET_BSTR(DCTVS_AgentService_DebugMode));
  275. if ( !UStrICmp(text,GET_STRING(IDS_YES)))
  276. {
  277. gDebug = TRUE;
  278. }
  279. WCHAR password[LEN_Password];
  280. safecopy(password,extra);
  281. #ifdef OFA
  282. if(!IsLocallyInstalled())
  283. #endif
  284. RegisterPlugInFiles(pVarSet);
  285. pVarSet->put(GET_BSTR(DCTVS_Options_Credentials_Password),password);
  286. hr = pLocalAgent->raw_SubmitJob(pVarSet,&jobID);
  287. if ( SUCCEEDED(hr))
  288. {
  289. TJobNode * pnode = new TJobNode(jobID);
  290. gJobList.InsertBottom(pnode);
  291. err.MsgWrite(0,DCT_MSG_AGENT_JOB_STARTED_SSS,jobID,L"",L"");
  292. }
  293. else
  294. {
  295. err.SysMsgWrite(ErrE,hr,DCT_MSG_SUBMIT_JOB_FAILED_D,hr);
  296. }
  297. if ( gbDeleteOnCompletion )
  298. {
  299. if ( ! gLocallyInstalled )
  300. {
  301. gSuicide = TRUE;
  302. }
  303. if ( SUCCEEDED(hr) )
  304. {
  305. // Start up a thread to monitor this job and initiate a shutdown when it is completed
  306. DWORD threadID = 0;
  307. HANDLE gThread = CreateThread(NULL,0,&MonitorJob,(void*)jobID,0,&threadID);
  308. CloseHandle(gThread);
  309. }
  310. }
  311. UStrCpy(jobGUID,jobID);
  312. }
  313. else
  314. {
  315. err.SysMsgWrite(ErrE,HRESULT_CODE(hr),DCT_MSG_VARSET_LOAD_FAILED_SD,filenameW, hr);
  316. }
  317. }
  318. else
  319. {
  320. err.SysMsgWrite(ErrE,HRESULT_CODE(hr),DCT_MSG_JOBFILE_OPEN_FAILED_SD,filenameW,hr);
  321. }
  322. }
  323. // int x = pLocalAgent->Release();
  324. pLocalAgent->Release();
  325. }
  326. else
  327. {
  328. err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
  329. }
  330. CoUninitialize();
  331. return hr;
  332. }
  333. DWORD __stdcall
  334. EaxsCancelJob(
  335. /* [in] */ handle_t hBinding,
  336. /* [string][in] */ const WCHAR __RPC_FAR *jobGUID
  337. )
  338. {
  339. DWORD rc = 0;
  340. HRESULT hr;
  341. IDCTAgent * pLocalAgent = NULL;
  342. // make sure the client is an admin on the local machine
  343. rc = AuthenticateClient(hBinding);
  344. if ( rc )
  345. {
  346. return rc;
  347. }
  348. hr = CoInitialize(NULL);
  349. if ( FAILED(hr) )
  350. {
  351. err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
  352. return hr;
  353. }
  354. hr = CoUnmarshalInterface( pStream, IID_IDCTAgent,(void**)&pLocalAgent);
  355. // interface pointer requested in riid);
  356. if ( SUCCEEDED(hr) )
  357. {
  358. // Reset the stream to the beginning
  359. LARGE_INTEGER offset = { 0,0 };
  360. ULARGE_INTEGER result = { 0,0};
  361. hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
  362. BSTR jobID;
  363. jobID = SysAllocString(jobGUID);
  364. hr = pLocalAgent->CancelJob(jobID);
  365. if ( SUCCEEDED(hr))
  366. {
  367. err.MsgWrite(0,DCT_MSG_JOB_CANCELLED_S,jobID);
  368. }
  369. pLocalAgent->Release();
  370. rc = hr;
  371. }
  372. else
  373. {
  374. err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
  375. }
  376. CoUninitialize();
  377. return rc;
  378. }
  379. DWORD __stdcall
  380. EaxsQueryInterface(
  381. /* [in] */ handle_t hBinding,
  382. /* [out] */ LPUNKNOWN __RPC_FAR *lpAgentUnknown
  383. )
  384. {
  385. DWORD rc = 0;
  386. HRESULT hr;
  387. IDCTAgent * pLocalAgent = NULL;
  388. (*lpAgentUnknown) = NULL;
  389. // make sure the client is an admin on the local machine
  390. rc = AuthenticateClient(hBinding);
  391. if ( rc )
  392. {
  393. return rc;
  394. }
  395. hr = CoInitialize(NULL);
  396. if ( FAILED(hr) )
  397. {
  398. err.SysMsgWrite(ErrE,hr,DCT_MSG_COINITIALIZE_FAILED_D,hr);
  399. return hr;
  400. }
  401. //E_NOINTERFACE
  402. if ( ! gbIsNt351 )
  403. {
  404. hr = CoUnmarshalInterface( pStream, IID_IUnknown,(void**)&pLocalAgent);
  405. // interface pointer requested in riid);
  406. if ( SUCCEEDED(hr) )
  407. {
  408. // Reset the stream to the beginning
  409. LARGE_INTEGER offset = { 0,0 };
  410. ULARGE_INTEGER result = { 0,0 };
  411. hr = pStream->Seek(offset,STREAM_SEEK_SET,&result);
  412. (*lpAgentUnknown) = pLocalAgent;
  413. }
  414. else
  415. {
  416. err.SysMsgWrite(ErrE,hr,DCT_MSG_UMARSHAL_AGENT_FAILED_D,hr);
  417. (*lpAgentUnknown) = NULL;
  418. }
  419. }
  420. else
  421. {
  422. // NT 3.51 doesn't support DCOM, so there's no point in even trying this
  423. (*lpAgentUnknown) = NULL;
  424. hr = E_NOTIMPL;
  425. }
  426. return hr;
  427. }
  428. #define DCTAgent_Remove 1
  429. DWORD __stdcall
  430. ShutdownService(
  431. /* [in] */ DWORD bFlags
  432. )
  433. {
  434. DWORD rc = 0;
  435. HRESULT hr;
  436. // LPUNKNOWN pLocalAgent = NULL;
  437. hr = CoInitialize(NULL);
  438. if ( bFlags )
  439. {
  440. if ( gDebug )
  441. //* err.DbgMsgWrite(0,L"Set suicide flag.");
  442. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_SETFLAG));
  443. gSuicide = TRUE;
  444. }
  445. else
  446. {
  447. if ( gDebug )
  448. //* err.DbgMsgWrite(0,L"Did not set suicide flag");
  449. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_NOSETFLAG));
  450. }
  451. if ( gSuicide && ! gLocallyInstalled )
  452. {
  453. if ( gDebug )
  454. //* err.DbgMsgWrite(ErrW,L"Removing agent");
  455. err.DbgMsgWrite(ErrW,GET_STRING(IDS_EVENTVW_MSG_REMOVEAGENT));
  456. // Uninstall the service
  457. if ( gDebug )
  458. //* err.DbgMsgWrite(0,L"Unregistering files");
  459. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_UNREGFILES));
  460. UnregisterFiles();
  461. // delete all files
  462. if ( gDebug )
  463. //* err.DbgMsgWrite(0,L"Deleting files");
  464. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_FILEDEL));
  465. RemoveFiles();
  466. if ( gDebug )
  467. //* err.DbgMsgWrite(0,L"Removing service");
  468. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_REMOVESVC));
  469. RemoveService();
  470. }
  471. else
  472. {
  473. if ( gDebug )
  474. //* err.DbgMsgWrite(ErrW,L"Not Removing agent");
  475. err.DbgMsgWrite(ErrW,GET_STRING(IDS_EVENTVW_MSG_NOREMOVEAGENT));
  476. }
  477. if ( ! gbIsNt351 )
  478. {
  479. RpcMgmtStopServerListening( NULL );
  480. }
  481. else
  482. {
  483. gbFinished = TRUE;
  484. }
  485. RpcServerUnregisterIf( NULL, NULL, FALSE );
  486. if ( gDebug )
  487. //* err.DbgMsgWrite(0,L"Stopped listening(%ld)",bFlags);
  488. err.DbgMsgWrite(0,GET_STRING(IDS_EVENTVW_MSG_STOPLISTEN),bFlags);
  489. return rc;
  490. }
  491. DWORD __stdcall
  492. EaxsShutdown(
  493. /* [in] */ handle_t hBinding,
  494. /* [in] */ DWORD bFlags
  495. )
  496. {
  497. DWORD rc = 0;
  498. // make sure the client is an admin on the local machine
  499. rc = AuthenticateClient(hBinding);
  500. if ( rc )
  501. {
  502. return rc;
  503. }
  504. rc = ShutdownService(bFlags);
  505. return rc;
  506. }