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.

571 lines
16 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows 2000 Active Directory Service domain trust verification WMI provider
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: trustmon.cpp
  9. //
  10. // Contents: Implementation of worker thread class and DLL Exports.
  11. //
  12. // Classes: CAsyncCallWorker
  13. //
  14. // History: 22-Mar-00 EricB created
  15. //
  16. //-----------------------------------------------------------------------------
  17. #include "stdafx.h"
  18. #include "resource.h"
  19. #include <initguid.h>
  20. CComModule _Module;
  21. DEFINE_GUID(CLSID_TrustMonProvider,0x8065652F,0x4C29,0x4908,0xAA,0xE5,0x20,0x1C,0x89,0x19,0x04,0xC5);
  22. BEGIN_OBJECT_MAP(ObjectMap)
  23. OBJECT_ENTRY(CLSID_TrustMonProvider, CTrustPrv)
  24. END_OBJECT_MAP()
  25. WCHAR g_wzMofPath[] = L"\\system32\\wbem\\ADStatus\\TrustMon.mof";
  26. //+----------------------------------------------------------------------------
  27. //
  28. // Class: CAsyncCallWorker
  29. //
  30. //-----------------------------------------------------------------------------
  31. CAsyncCallWorker::CAsyncCallWorker(CTrustPrv * pTrustPrv,
  32. long lFlags,
  33. IWbemClassObject * pClassDef,
  34. IWbemObjectSink * pResponseHandler,
  35. LPWSTR pwzInstanceName) :
  36. m_lFlags(lFlags),
  37. m_pwzInstanceName(pwzInstanceName)
  38. {
  39. TRACE(L"CAsyncCallWorker::CAsyncCallWorker(0x%08x)\n", this);
  40. m_sipTrustPrv.p = pTrustPrv; pTrustPrv->AddRef(); // ATL CComPtr is broken!
  41. m_sipClassDef = pClassDef;
  42. m_sipResponseHandler = pResponseHandler;
  43. }
  44. CAsyncCallWorker::~CAsyncCallWorker()
  45. {
  46. TRACE(L"CAsyncCallWorker::~CAsyncCallWorker\n\n");
  47. if (m_pwzInstanceName)
  48. {
  49. delete m_pwzInstanceName;
  50. }
  51. }
  52. //+----------------------------------------------------------------------------
  53. //
  54. // Method: CAsyncCallWorker::CreateInstEnum
  55. //
  56. // Synopsis: Provides the worker thread function for
  57. // IWbemServices::CreateInstanceEnumAsync
  58. //
  59. //-----------------------------------------------------------------------------
  60. void __cdecl
  61. CAsyncCallWorker::CreateInstEnum(PVOID pParam)
  62. {
  63. TRACE(L"CAsyncCallWorker::CreateInstEnum\n");
  64. HRESULT hr = WBEM_S_NO_ERROR;
  65. DWORD dwWaitResult;
  66. CAsyncCallWorker * pWorker = (CAsyncCallWorker *)pParam;
  67. CDomainInfo * pDomain = &(pWorker->m_sipTrustPrv->m_DomainInfo);
  68. CoInitializeEx(NULL, COINIT_MULTITHREADED);
  69. do
  70. {
  71. BREAK_ON_NULL(pWorker);
  72. //
  73. // Try to get the mutex first without a wait. It is in the signalled state if
  74. // not owned.
  75. //
  76. dwWaitResult = WaitForSingleObject(pWorker->m_sipTrustPrv->m_hMutex, 0);
  77. if (WAIT_TIMEOUT == dwWaitResult)
  78. {
  79. // Mutex is owned by another thread. Rewait.
  80. dwWaitResult = WaitForSingleObject(pWorker->m_sipTrustPrv->m_hMutex,
  81. 6000000); // timeout set to 10 minutes
  82. switch(dwWaitResult)
  83. {
  84. case WAIT_TIMEOUT:
  85. // mutex continues to be non-signalled (owned by another thread).
  86. hr = WBEM_E_SERVER_TOO_BUSY; // BUGBUG: returning an error.
  87. // BUGBUG: should the timeout be parameterized?
  88. break;
  89. case WAIT_OBJECT_0:
  90. // This thread now owns the mutex.
  91. break;
  92. case WAIT_ABANDONED: // this means the owning thread terminated without releasing the mutex.
  93. TRACE(L"Another thread didn't release the mutex!\n");
  94. break;
  95. }
  96. }
  97. BREAK_ON_FAIL;
  98. CoImpersonateClient();
  99. //
  100. // Re-read all the trust information if stale.
  101. // The trust list is not re-enumerated on every call because trusts are
  102. // rarely modified.
  103. //
  104. if (pDomain->IsTrustListStale(pWorker->m_sipTrustPrv->m_liTrustEnumMaxAge))
  105. {
  106. hr = pDomain->EnumerateTrusts();
  107. BREAK_ON_FAIL;
  108. }
  109. size_t cTrusts = pDomain->Size();
  110. for (size_t i = 0; i < cTrusts; i++)
  111. {
  112. if ((long)WBEM_FLAG_SEND_STATUS & pWorker->m_lFlags)
  113. {
  114. hr = pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_PROGRESS,
  115. MAKELONG(i, cTrusts),
  116. NULL, NULL);
  117. BREAK_ON_FAIL;
  118. }
  119. CTrustInfo * pTrust;
  120. //
  121. // Get trust Info
  122. //
  123. pTrust = pDomain->GetTrustByIndex(i);
  124. BREAK_ON_NULL_(pTrust, hr, WBEM_E_INVALID_OBJECT_PATH);
  125. //
  126. // Verify the trust if stale.
  127. //
  128. if (pTrust->IsVerificationStale(pWorker->m_sipTrustPrv->m_liVerifyMaxAge))
  129. {
  130. pTrust->Verify(pWorker->m_sipTrustPrv->GetTrustCheckLevel());
  131. }
  132. CoRevertToSelf();
  133. //
  134. // Create a new instance of the object if the trust is outbound or if
  135. // return-all is true.
  136. //
  137. if (pTrust->IsTrustOutbound() || pWorker->m_sipTrustPrv->GetReturnAll())
  138. {
  139. hr = CreateAndSendTrustInst(*pTrust, pWorker->m_sipClassDef,
  140. pWorker->m_sipResponseHandler);
  141. }
  142. BREAK_ON_FAIL;
  143. CoImpersonateClient();
  144. }
  145. } while (FALSE);
  146. CoRevertToSelf();
  147. //
  148. // Set status
  149. //
  150. pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
  151. ReleaseMutex(pWorker->m_sipTrustPrv->m_hMutex);
  152. delete pWorker;
  153. CoUninitialize();
  154. _endthread();
  155. }
  156. //+----------------------------------------------------------------------------
  157. //
  158. // Method: CAsyncCallWorker::GetObj
  159. //
  160. // Synopsis: Provides the worker thread function for
  161. // IWbemServices::GetObjectAsync
  162. //
  163. //-----------------------------------------------------------------------------
  164. void __cdecl
  165. CAsyncCallWorker::GetObj(PVOID pParam)
  166. {
  167. TRACE(L"CAsyncCallWorker::GetObj\n");
  168. HRESULT hr = WBEM_S_NO_ERROR;
  169. CAsyncCallWorker * pWorker = (CAsyncCallWorker *)pParam;
  170. CoInitializeEx(NULL, COINIT_MULTITHREADED);
  171. CoImpersonateClient();
  172. do
  173. {
  174. } while (FALSE);
  175. CoRevertToSelf();
  176. //
  177. // Set status
  178. //
  179. pWorker->m_sipResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
  180. delete pWorker;
  181. CoUninitialize();
  182. _endthread();
  183. }
  184. //+----------------------------------------------------------------------------
  185. //
  186. // Function: CreateAndSendTrustInst
  187. //
  188. // Purpose: Creates a new instance and sets the inital values of the
  189. // properties.
  190. //
  191. //-----------------------------------------------------------------------------
  192. HRESULT
  193. CreateAndSendTrustInst(CTrustInfo & Trust, IWbemClassObject * pClassDef,
  194. IWbemObjectSink * pResponseHandler)
  195. {
  196. TRACE(L"CreateAndSendTrustInst\n");
  197. HRESULT hr = WBEM_S_NO_ERROR;
  198. do
  199. {
  200. CComPtr<IWbemClassObject> ipNewInst;
  201. CComVariant var;
  202. //
  203. // Create a new instance of the WMI class object
  204. //
  205. hr = pClassDef->SpawnInstance(0, &ipNewInst);
  206. BREAK_ON_FAIL;
  207. // Set the key property value (TrustedDomain)
  208. var = Trust.GetTrustedDomain();
  209. hr = ipNewInst->Put(CSTR_PROP_TRUSTED_DOMAIN, 0, &var, 0);
  210. TRACE(L"\tCreating instance %s\n", var.bstrVal);
  211. BREAK_ON_FAIL;
  212. //Flat Name
  213. var = Trust.GetFlatName();
  214. hr = ipNewInst->Put(CSTR_PROP_FLAT_NAME, 0, &var, 0);
  215. BREAK_ON_FAIL;
  216. //Sid
  217. var = Trust.GetSid();
  218. hr = ipNewInst->Put(CSTR_PROP_SID, 0, &var, 0);
  219. BREAK_ON_FAIL;
  220. //Trust Direction
  221. var = (long)Trust.GetTrustDirection();
  222. hr = ipNewInst->Put(CSTR_PROP_TRUST_DIRECTION, 0, &var, 0);
  223. BREAK_ON_FAIL;
  224. //Trust Type
  225. var = (long)Trust.GetTrustType();
  226. hr = ipNewInst->Put(CSTR_PROP_TRUST_TYPE, 0, &var, 0);
  227. BREAK_ON_FAIL;
  228. //Trust Attributes
  229. var = (long)Trust.GetTrustAttributes();
  230. hr = ipNewInst->Put(CSTR_PROP_TRUST_ATTRIBUTES, 0, &var, 0);
  231. BREAK_ON_FAIL;
  232. // Set the TrustStatus value.
  233. var = (long)Trust.GetTrustStatus();
  234. hr = ipNewInst->Put(CSTR_PROP_TRUST_STATUS, 0, &var, 0);
  235. BREAK_ON_FAIL;
  236. var = Trust.GetTrustStatusString();
  237. hr = ipNewInst->Put(CSTR_PROP_TRUST_STATUS_STRING, 0, &var, 0);
  238. BREAK_ON_FAIL;
  239. // Set the Trust Is OK value.
  240. var = Trust.IsTrustOK();
  241. hr = ipNewInst->Put(CSTR_PROP_TRUST_IS_OK, 0, &var, 0);
  242. BREAK_ON_FAIL;
  243. //Trusted DC Name
  244. var = Trust.GetTrustedDCName();
  245. hr = ipNewInst->Put(CSTR_PROP_TRUSTED_DC_NAME, 0, &var, 0);
  246. BREAK_ON_FAIL;
  247. //
  248. // Send the object to the caller
  249. //
  250. // [In] param, no need to addref.
  251. IWbemClassObject * pNewInstance = ipNewInst;
  252. hr = pResponseHandler->Indicate(1, &pNewInstance);
  253. BREAK_ON_FAIL;
  254. } while(FALSE);
  255. return hr;
  256. }
  257. //+----------------------------------------------------------------------------
  258. //
  259. // Function: DllMain
  260. //
  261. // Purpose: DLL Entry Point
  262. //
  263. //-----------------------------------------------------------------------------
  264. extern "C" BOOL WINAPI
  265. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  266. {
  267. if (dwReason == DLL_PROCESS_ATTACH)
  268. {
  269. _Module.Init(ObjectMap, hInstance);
  270. DisableThreadLibraryCalls(hInstance);
  271. }
  272. else if (dwReason == DLL_PROCESS_DETACH)
  273. _Module.Term();
  274. return TRUE;
  275. }
  276. //+----------------------------------------------------------------------------
  277. //
  278. // Function: DllCanUnloadNow
  279. //
  280. // Purpose: Used to determine whether the DLL can be unloaded by OLE
  281. //
  282. //-----------------------------------------------------------------------------
  283. STDAPI DllCanUnloadNow(void)
  284. {
  285. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  286. }
  287. //+----------------------------------------------------------------------------
  288. //
  289. // Function: DllGetClassObject
  290. //
  291. // Purpose: Returns a class factory to create an object of the requested type
  292. //
  293. //-----------------------------------------------------------------------------
  294. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  295. {
  296. return _Module.GetClassObject(rclsid, riid, ppv);
  297. }
  298. //+----------------------------------------------------------------------------
  299. //
  300. // Function: DllRegisterServer
  301. //
  302. // Purpose: Adds Class entries to the system registry
  303. //
  304. //-----------------------------------------------------------------------------
  305. STDAPI DllRegisterServer(void)
  306. {
  307. // Add TrustMon to the registry as an event source.
  308. //
  309. HKEY hk;
  310. DWORD dwData;
  311. WCHAR wzFilePath[2*MAX_PATH];
  312. GetModuleFileName(_Module.GetModuleInstance(), wzFilePath, 2*MAX_PATH);
  313. if (RegCreateKey(HKEY_LOCAL_MACHINE,
  314. L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" TM_PROV_NAME,
  315. &hk))
  316. {
  317. TRACE(L"Could not create the registry key.");
  318. }
  319. else
  320. {
  321. // Set the name of the message file.
  322. //
  323. TRACE(L"Adding path %s to the registry\n", wzFilePath);
  324. // Add the name to the EventMessageFile subkey.
  325. if (RegSetValueEx(hk,
  326. L"EventMessageFile",
  327. 0,
  328. REG_EXPAND_SZ,
  329. (LPBYTE)wzFilePath,
  330. (ULONG)(wcslen(wzFilePath) + 1) * sizeof(WCHAR)))
  331. {
  332. TRACE(L"Could not set the event message file.");
  333. }
  334. else
  335. {
  336. // Set the supported event types in the TypesSupported subkey.
  337. dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
  338. EVENTLOG_INFORMATION_TYPE;
  339. if (RegSetValueEx(hk,
  340. L"TypesSupported",
  341. 0,
  342. REG_DWORD,
  343. (LPBYTE)&dwData,
  344. sizeof(DWORD)))
  345. {
  346. TRACE(L"Could not set the supported types.");
  347. }
  348. }
  349. RegCloseKey(hk);
  350. }
  351. // Add a RunOnce value to do the MOF compile.
  352. //
  353. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  354. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
  355. 0,
  356. KEY_WRITE,
  357. &hk))
  358. {
  359. TRACE(L"Could not open the registry key.");
  360. }
  361. else
  362. {
  363. CString csCmd = L"rundll32.exe ";
  364. csCmd += wzFilePath;
  365. csCmd += L",DoMofComp";
  366. if (RegSetValueEx(hk,
  367. L"TrustMon",
  368. 0,
  369. REG_SZ,
  370. (LPBYTE)csCmd.GetBuffer(0),
  371. csCmd.GetLength() * sizeof(WCHAR)))
  372. {
  373. TRACE(L"Could not set the runonce value.");
  374. }
  375. RegCloseKey(hk);
  376. }
  377. return _Module.RegisterServer();
  378. }
  379. //+----------------------------------------------------------------------------
  380. //
  381. // Function: DllUnregisterServer
  382. //
  383. // Purpose: Removes Class entries from the system registry
  384. //
  385. //-----------------------------------------------------------------------------
  386. STDAPI DllUnregisterServer(void)
  387. {
  388. return _Module.UnregisterServer();
  389. }
  390. //+----------------------------------------------------------------------------
  391. //
  392. // Function: DoMofComp
  393. //
  394. // Purpose: Adds the provider classes to the WMI repository. Note that the
  395. // function signature is that required by rundll32.exe.
  396. //
  397. //-----------------------------------------------------------------------------
  398. VOID WINAPI DoMofComp(HWND hWndParent,
  399. HINSTANCE hModule,
  400. PCTSTR ptzCommandLine,
  401. INT nShowCmd)
  402. {
  403. TRACE(L"DoMofComp\n");
  404. UNREFERENCED_PARAMETER(hWndParent);
  405. UNREFERENCED_PARAMETER(hModule);
  406. UNREFERENCED_PARAMETER(ptzCommandLine);
  407. UNREFERENCED_PARAMETER(nShowCmd);
  408. HRESULT hr;
  409. CComPtr<IMofCompiler> pmc;
  410. CoInitialize(NULL);
  411. hr = CoCreateInstance(CLSID_MofCompiler, NULL, CLSCTX_INPROC_SERVER,
  412. IID_IMofCompiler, (PVOID *)&pmc);
  413. CHECK_HRESULT(hr, return);
  414. WCHAR wzFilePath[2*MAX_PATH];
  415. UINT nLen = GetSystemWindowsDirectory(wzFilePath, 2*MAX_PATH);
  416. if (nLen == 0)
  417. {
  418. ASSERT(FALSE);
  419. return;
  420. }
  421. CString csMofPath = wzFilePath;
  422. csMofPath += g_wzMofPath;
  423. WBEM_COMPILE_STATUS_INFO Info;
  424. TRACE(L"Compiling MOF file %s\n", csMofPath.GetBuffer(0));
  425. hr = pmc->CompileFile(csMofPath.GetBuffer(0), NULL, NULL, NULL, NULL,
  426. WBEM_FLAG_AUTORECOVER, 0, 0, &Info);
  427. HANDLE hEvent = RegisterEventSource(NULL, TM_PROV_NAME);
  428. if (!hEvent)
  429. {
  430. TRACE(L"RegisterEventSource failed with error %d\n", GetLastError());
  431. return;
  432. }
  433. if (WBEM_S_NO_ERROR != hr)
  434. {
  435. TRACE(L"MofCompile failed with error 0x%08x (WMI error 0x%08x), line: %d, phase: %d\n",
  436. hr, Info.hRes, Info.FirstLine, Info.lPhaseError);
  437. //
  438. // Send failure to EventLog.
  439. //
  440. CString csHr, csLine;
  441. HMODULE hm = LoadLibrary(L"mofd.dll");
  442. if (hm)
  443. {
  444. WCHAR wzBuf[MAX_PATH];
  445. LoadString(hm, Info.hRes, wzBuf, MAX_PATH);
  446. csHr = wzBuf;
  447. FreeLibrary(hm);
  448. }
  449. else
  450. {
  451. csHr.Format(L"%d", Info.hRes);
  452. }
  453. csLine.Format(L"%d", Info.FirstLine);
  454. const PWSTR rgArgs[3] = {csHr.GetBuffer(0), csLine.GetBuffer(0), csMofPath.GetBuffer(0)};
  455. ReportEvent(hEvent,
  456. EVENTLOG_ERROR_TYPE,
  457. 0, // wCategory
  458. TRUSTMON_MOFCOMP_FAILED, // dwEventID
  459. NULL, // lpUserSID
  460. 3, // wNumStrings
  461. 0, // dwDataSize
  462. (PCWSTR *)rgArgs, // lpStrings
  463. NULL); // lpRawData
  464. }
  465. else
  466. {
  467. // Send success notice to EventLog.
  468. //
  469. ReportEvent(hEvent,
  470. EVENTLOG_INFORMATION_TYPE,
  471. 0, // wCategory
  472. TRUSTMON_MOFCOMP_SUCCESS, // dwEventID
  473. NULL, // lpUserSID
  474. 0, // wNumStrings
  475. 0, // dwDataSize
  476. NULL, // lpStrings
  477. NULL); // lpRawData
  478. }
  479. DeregisterEventSource(hEvent);
  480. return;
  481. }