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.

591 lines
17 KiB

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