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.

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