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.

683 lines
17 KiB

  1. // KernelTraceProvider.cpp : Implementation of CKernelTraceProvider
  2. #include "precomp.h"
  3. #include "Krnlprov.h"
  4. #include "KernelTraceProvider.h"
  5. #include <GroupsForUser.h>
  6. void Trace(LPCTSTR szFormat, ...)
  7. {
  8. va_list ap;
  9. TCHAR szMessage[512];
  10. va_start(ap, szFormat);
  11. StringCchVPrintf(szMessage,512,szFormat,ap);
  12. va_end(ap);
  13. StringCchCat(szMessage, 512, TEXT("\n"));
  14. OutputDebugString(szMessage);
  15. }
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CKernelTraceProvider
  18. // Because the event trace API won't allow you to get back a user-defined
  19. // value when events are received!
  20. CKernelTraceProvider *g_pThis;
  21. CKernelTraceProvider::CKernelTraceProvider()
  22. : m_bDone(FALSE), m_hProcessTraceThread(NULL)
  23. {
  24. g_pThis = this;
  25. }
  26. void CKernelTraceProvider::FinalRelease()
  27. {
  28. StopTracing();
  29. }
  30. HRESULT STDMETHODCALLTYPE CKernelTraceProvider::Initialize(
  31. /* [in] */ LPWSTR pszUser,
  32. /* [in] */ LONG lFlags,
  33. /* [in] */ LPWSTR pszNamespace,
  34. /* [in] */ LPWSTR pszLocale,
  35. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  36. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  37. /* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink)
  38. {
  39. HRESULT hr = S_OK;
  40. m_pNamespace = pNamespace;
  41. // Tell Windows Management our initialization status.
  42. pInitSink->SetStatus(SUCCEEDED(hr) ? WBEM_S_INITIALIZED : WBEM_E_FAILED, 0);
  43. return hr;
  44. }
  45. #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
  46. HRESULT CKernelTraceProvider::InitEvents()
  47. {
  48. /////////////////////////////////////////////////////////////////////////
  49. // Win32_ProcessStartTrace
  50. LPCWSTR szProcessStartTraceNames[] =
  51. {
  52. L"PageDirectoryBase",
  53. L"ProcessID",
  54. L"ParentProcessID",
  55. L"SessionID",
  56. L"Sid",
  57. L"ProcessName"
  58. };
  59. m_eventProcessStart.Init(
  60. m_pNamespace,
  61. L"Win32_ProcessStartTrace",
  62. szProcessStartTraceNames,
  63. COUNTOF(szProcessStartTraceNames),
  64. CObjAccess::FAILED_PROP_FAIL);
  65. /////////////////////////////////////////////////////////////////////////
  66. // Win32_ProcessStopTrace
  67. LPCWSTR szProcessStopTraceNames[] =
  68. {
  69. L"PageDirectoryBase",
  70. L"ProcessID",
  71. L"ParentProcessID",
  72. L"SessionID",
  73. L"ExitStatus",
  74. L"Sid",
  75. L"ProcessName"
  76. };
  77. m_eventProcessStop.Init(
  78. m_pNamespace,
  79. L"Win32_ProcessStopTrace",
  80. szProcessStopTraceNames,
  81. COUNTOF(szProcessStopTraceNames),
  82. CObjAccess::FAILED_PROP_FAIL);
  83. /////////////////////////////////////////////////////////////////////////
  84. // Win32_ThreadStartTrace
  85. LPCWSTR szThreadStartNames[] =
  86. {
  87. L"StackBase",
  88. L"StackLimit",
  89. L"UserStackBase",
  90. L"UserStackLimit",
  91. L"StartAddr",
  92. L"Win32StartAddr",
  93. L"ProcessID",
  94. L"ThreadID",
  95. L"WaitMode",
  96. };
  97. m_eventThreadStart.Init(
  98. m_pNamespace,
  99. L"Win32_ThreadStartTrace",
  100. szThreadStartNames,
  101. COUNTOF(szThreadStartNames),
  102. CObjAccess::FAILED_PROP_FAIL);
  103. /////////////////////////////////////////////////////////////////////////
  104. // Win32_ThreadStopTrace
  105. LPCWSTR szThreadStopNames[] =
  106. {
  107. L"ProcessID",
  108. L"ThreadID",
  109. };
  110. m_eventThreadStop.Init(
  111. m_pNamespace,
  112. L"Win32_ThreadStopTrace",
  113. szThreadStopNames,
  114. COUNTOF(szThreadStopNames),
  115. CObjAccess::FAILED_PROP_FAIL);
  116. /////////////////////////////////////////////////////////////////////////
  117. // Win32_ModuleLoadTrace
  118. LPCWSTR szModuleNames[] =
  119. {
  120. L"ImageBase",
  121. L"ImageSize",
  122. L"ProcessID",
  123. L"FileName",
  124. };
  125. m_eventModuleLoad.Init(
  126. m_pNamespace,
  127. L"Win32_ModuleLoadTrace",
  128. szModuleNames,
  129. COUNTOF(szModuleNames),
  130. CObjAccess::FAILED_PROP_FAIL);
  131. return S_OK;
  132. }
  133. #define REALTIME
  134. #define BUFFER_SIZE 64
  135. #define MIN_BUFFERS 20
  136. #define MAX_BUFFERS 200
  137. #define FLUSH_TIME 1
  138. //#define USE_KERNEL_GUID
  139. #ifdef USE_KERNEL_GUID
  140. #define LOGGER_NAME L"NT Kernel Logger"
  141. #define WMI_KERNEL_TRACE_GUID guidSystemTrace
  142. #define ENABLE_FLAGS EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_IMAGE_LOAD
  143. #else
  144. #define LOGGER_NAME L"WMI Event Logger"
  145. #define WMI_KERNEL_TRACE_GUID guidWMITrace
  146. #define ENABLE_FLAGS 0
  147. #endif
  148. #ifndef REALTIME
  149. #define MAX_FILE_SIZE 20 // In MB
  150. #define LOGGER_FILE L"c:\\temp\\wmi.etl"
  151. #endif
  152. GUID guidProcess =
  153. // {3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c}
  154. {0x3d6fa8d0, 0xfe05, 0x11d0, 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c};
  155. GUID guidThread =
  156. // {3d6fa8d1-fe05-11d0-9dda-00c04fd7ba7c}
  157. {0x3d6fa8d1, 0xfe05, 0x11d0, 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c};
  158. GUID guidImage =
  159. // {2cb15d1d-5fc1-11d2-abe1-00a0c911f518}
  160. {0x2cb15d1d, 0x5fc1, 0x11d2, 0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18};
  161. GUID guidSystemTrace =
  162. // 9e814aad-3204-11d2-9a82-006008a86939
  163. {0x9e814aad, 0x3204, 0x11d2, 0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39};
  164. GUID guidWMITrace =
  165. // 44608a51-1851-4456-98b2-b300e931ee41
  166. {0x44608a51, 0x1851, 0x4456, 0x98, 0xb2, 0xb3, 0x00, 0xe9, 0x31, 0xee, 0x41};
  167. HRESULT CKernelTraceProvider::InitTracing()
  168. {
  169. DWORD status;
  170. m_bDone = FALSE;
  171. // See if the logger is already running. If not, set it up.
  172. if (QueryTrace(
  173. NULL,
  174. LOGGER_NAME,
  175. &m_properties) != ERROR_SUCCESS)
  176. {
  177. // Initialize property values here.
  178. #ifdef REALTIME
  179. m_properties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  180. StringCchCopy( m_properties.szLoggerName, MAX_PATH, LOGGER_NAME );
  181. #else
  182. m_properties.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;
  183. //properties.LogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR;
  184. // MaximumFileSize is in MB.
  185. m_properties.MaximumFileSize = MAX_FILE_SIZE;
  186. StringCchCopy( m_properties.szLogFileName, MAX_PATH, LOGGER_FILE );
  187. #endif
  188. m_properties.Wnode.Guid = WMI_KERNEL_TRACE_GUID;
  189. // Set the buffer size. BufferSize is in KB.
  190. m_properties.BufferSize = BUFFER_SIZE;
  191. m_properties.MinimumBuffers = MIN_BUFFERS;
  192. m_properties.MaximumBuffers = MAX_BUFFERS;
  193. // Number of seconds before timer is flushed.
  194. m_properties.FlushTimer = FLUSH_TIME;
  195. m_properties.EnableFlags |= ENABLE_FLAGS;
  196. // Start tracing.
  197. status =
  198. StartTrace(
  199. &m_hSession,
  200. LOGGER_NAME,
  201. &m_properties);
  202. if (status != ERROR_SUCCESS)
  203. {
  204. TRACE(L"StartTrace error=%d (GetLastError=0x%x)",
  205. status, GetLastError());
  206. return WBEM_E_FAILED;
  207. }
  208. }
  209. else
  210. m_hSession = NULL;
  211. EVENT_TRACE_LOGFILE eventFile;
  212. ZeroMemory(&eventFile, sizeof(eventFile));
  213. //eventFile.BufferCallback = BufferCallback;
  214. //eventFile.EventCallback = DumpEvent;
  215. eventFile.LoggerName = (LPTSTR) LOGGER_NAME;
  216. #ifdef REALTIME
  217. eventFile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  218. #else
  219. eventFile.LogFileMode = 0;
  220. eventFile.LogFileName = (LPTSTR) LOGGER_FILE;
  221. #endif
  222. SetTraceCallback(&guidProcess, OnProcessEvent);
  223. SetTraceCallback(&guidThread, OnThreadEvent);
  224. SetTraceCallback(&guidImage, OnImageEvent);
  225. m_hTrace = OpenTrace(&eventFile);
  226. TRACE(L"Ready to call ProcessTrace (m_hTrace = %d)...\n", m_hTrace);
  227. DWORD dwID;
  228. m_hProcessTraceThread =
  229. CreateThread(
  230. NULL,
  231. 0,
  232. (LPTHREAD_START_ROUTINE) DoProcessTrace,
  233. this,
  234. 0,
  235. &dwID);
  236. if ( m_hProcessTraceThread == NULL )
  237. {
  238. return HRESULT_FROM_WIN32( GetLastError() );
  239. }
  240. return S_OK;
  241. }
  242. DWORD WINAPI CKernelTraceProvider::DoProcessTrace(CKernelTraceProvider *pThis)
  243. {
  244. #ifndef REALTIME
  245. FILETIME filetime;
  246. GetSystemTimeAsFileTime(&filetime);
  247. #endif
  248. while(!pThis->m_bDone)
  249. {
  250. DWORD status;
  251. status =
  252. ProcessTrace(
  253. &pThis->m_hTrace,
  254. 1,
  255. #ifdef REALTIME
  256. NULL,
  257. #else
  258. &filetime,
  259. #endif
  260. NULL);
  261. #ifndef REALTIME
  262. // Save this off for our next all.
  263. GetSystemTimeAsFileTime(&filetime);
  264. #endif
  265. if (status != ERROR_SUCCESS)
  266. {
  267. TRACE(L"Error processing with status=%dL (GetLastError=0x%x)",
  268. status, GetLastError());
  269. break;
  270. }
  271. else
  272. {
  273. #ifndef REALTIME
  274. TRACE(L"ProcessTrace exited successfully, sleeping...");
  275. Sleep(5000);
  276. #endif
  277. }
  278. }
  279. TRACE(L"Exiting StartTracing.");
  280. return 0;
  281. }
  282. void CKernelTraceProvider::StopTracing()
  283. {
  284. CInCritSec cs(&g_pThis->m_cs);
  285. DWORD status;
  286. m_bDone = TRUE;
  287. RemoveTraceCallback(&guidProcess);
  288. RemoveTraceCallback(&guidThread);
  289. RemoveTraceCallback(&guidImage);
  290. status = CloseTrace(m_hTrace);
  291. status =
  292. StopTrace(
  293. m_hSession,
  294. LOGGER_NAME,
  295. &m_properties);
  296. if (status != ERROR_SUCCESS)
  297. {
  298. TRACE(L"StopTrace error=%d (GetLastError=0x%x)\n",
  299. status, GetLastError());
  300. }
  301. if ( m_hProcessTraceThread != NULL )
  302. {
  303. WaitForSingleObject( m_hProcessTraceThread, INFINITE );
  304. CloseHandle( m_hProcessTraceThread );
  305. }
  306. }
  307. const LPCWSTR szQueries[CKernelTraceProvider::SINK_COUNT] =
  308. {
  309. /////////////////////////////////////////////////////////////////////
  310. // Process queries
  311. L"select * from Win32_ProcessStartTrace",
  312. L"select * from Win32_ProcessStopTrace",
  313. /////////////////////////////////////////////////////////////////////
  314. // Thread queries
  315. L"select * from Win32_ThreadStartTrace",
  316. L"select * from Win32_ThreadStopTrace",
  317. /////////////////////////////////////////////////////////////////////
  318. // Module queries
  319. L"select * from Win32_ModuleLoadTrace"
  320. };
  321. HRESULT STDMETHODCALLTYPE CKernelTraceProvider::ProvideEvents(
  322. /* [in] */ IWbemObjectSink __RPC_FAR *pSink,
  323. /* [in] */ long lFlags)
  324. {
  325. HRESULT hr;
  326. IWbemEventSinkPtr pEventSink;
  327. hr = pSink->QueryInterface(IID_IWbemEventSink, (LPVOID*) &pEventSink);
  328. for (int i = 0; i < SINK_COUNT && SUCCEEDED(hr); i++)
  329. {
  330. hr =
  331. pEventSink->GetRestrictedSink(
  332. 1,
  333. &szQueries[i],
  334. NULL,
  335. &m_pSinks[i]);
  336. }
  337. if (SUCCEEDED(hr))
  338. hr = InitEvents();
  339. if (SUCCEEDED(hr))
  340. hr = InitTracing();
  341. return hr;
  342. }
  343. HRESULT STDMETHODCALLTYPE CKernelTraceProvider::AccessCheck(
  344. /* [in] */ WBEM_CWSTR wszQueryLanguage,
  345. /* [in] */ WBEM_CWSTR wszQuery,
  346. /* [in] */ long lSidLength,
  347. /* [unique][size_is][in] */ const BYTE __RPC_FAR *pSid)
  348. {
  349. if ( NULL == pSid )
  350. {
  351. HRESULT hr = CoImpersonateClient();
  352. if( FAILED( hr ) )
  353. {
  354. return hr;
  355. }
  356. HANDLE hToken;
  357. if( !OpenThreadToken( GetCurrentThread( ), TOKEN_READ, TRUE, &hToken ) )
  358. {
  359. CoRevertToSelf( );
  360. return WBEM_E_FAILED;
  361. }
  362. hr = WBEM_E_ACCESS_DENIED;
  363. BOOL bRet = FALSE;
  364. PSID pRawSid;
  365. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  366. if( AllocateAndInitializeSid( &id, 2,
  367. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  368. 0,0,0,0,0,0,&pRawSid ) )
  369. {
  370. if ( CheckTokenMembership( hToken, pRawSid, &bRet ) && bRet )
  371. {
  372. hr = WBEM_S_NO_ERROR;
  373. }
  374. FreeSid( pRawSid );
  375. }
  376. CloseHandle( hToken );
  377. CoRevertToSelf();
  378. return hr;
  379. }
  380. //
  381. // SID IS NOT NULL HERE
  382. //
  383. if ( IsUserAdministrator( ( PSID )pSid ) )
  384. {
  385. return WBEM_E_ACCESS_DENIED;
  386. }
  387. return WBEM_S_NO_ERROR;
  388. }
  389. #define PROCESS_START 1
  390. #define PROCESS_END 2
  391. struct CProcessTrace
  392. {
  393. DWORD_PTR dwPageDirBase;
  394. DWORD dwProcessID,
  395. dwParentProcessID,
  396. dwSessionID;
  397. DWORD dwExitStatus;
  398. BYTE cSidBegin[1];
  399. };
  400. void WINAPI CKernelTraceProvider::OnProcessEvent(PEVENT_TRACE pEvent)
  401. {
  402. CInCritSec cs(&g_pThis->m_cs);
  403. CObjAccess *pObjEx;
  404. IWbemEventSink *pSink;
  405. if (pEvent->Header.Class.Type == PROCESS_START)
  406. {
  407. pSink = g_pThis->m_pSinks[SINK_PROCESS_START];
  408. if (pSink->IsActive() != WBEM_S_NO_ERROR)
  409. return;
  410. pObjEx = &g_pThis->m_eventProcessStart;
  411. }
  412. else if (pEvent->Header.Class.Type == PROCESS_END)
  413. {
  414. pSink = g_pThis->m_pSinks[SINK_PROCESS_STOP];
  415. if (pSink->IsActive() != WBEM_S_NO_ERROR)
  416. return;
  417. pObjEx = &g_pThis->m_eventProcessStop;
  418. }
  419. else
  420. // Ignore anything else.
  421. return;
  422. CProcessTrace *pProcess = (CProcessTrace*) pEvent->MofData;
  423. // Find out where the SID is.
  424. LPBYTE pCurrent = (LPBYTE) &pProcess->cSidBegin,
  425. pSid;
  426. DWORD nSidLen;
  427. if (*(DWORD*) pCurrent == 0)
  428. {
  429. pSid = NULL;
  430. pCurrent += sizeof(DWORD);
  431. }
  432. else
  433. {
  434. // These numbers were taken from tracedmp.c of the sdktool
  435. // tracedmp.exe. There's no explanation as to how they came up with
  436. // them, but I'm assuming it's documented somewhere in the SDK.
  437. pCurrent += sizeof( TOKEN_USER );
  438. nSidLen = 8 + (4 * pCurrent[1]);
  439. pSid = pCurrent;
  440. pCurrent += nSidLen;
  441. }
  442. _bstr_t strProcess = (LPSTR) pCurrent;
  443. // Extrinsic events
  444. pObjEx->WriteDWORD64(0, pProcess->dwPageDirBase);
  445. pObjEx->WriteDWORD(1, pProcess->dwProcessID);
  446. pObjEx->WriteDWORD(2, pProcess->dwParentProcessID);
  447. pObjEx->WriteDWORD(3, pProcess->dwSessionID);
  448. if (pEvent->Header.Class.Type == PROCESS_END)
  449. {
  450. pObjEx->WriteDWORD(4, pProcess->dwExitStatus);
  451. if (pSid)
  452. pObjEx->WriteNonPackedArrayData(5, pSid, nSidLen, nSidLen);
  453. else
  454. pObjEx->WriteNULL(5);
  455. pObjEx->WriteString(6, (LPCWSTR) strProcess);
  456. }
  457. else
  458. {
  459. if (pSid)
  460. pObjEx->WriteNonPackedArrayData(4, pSid, nSidLen, nSidLen);
  461. else
  462. pObjEx->WriteNULL(4);
  463. pObjEx->WriteString(5, (LPCWSTR) strProcess);
  464. }
  465. pSink->Indicate(1, pObjEx->GetObjForIndicate());
  466. }
  467. struct CThreadStart
  468. {
  469. DWORD dwProcessID,
  470. dwThreadID;
  471. DWORD_PTR dwStackBase,
  472. dwStackLimit,
  473. dwUserStackBase,
  474. dwUserStackLimit,
  475. dwStartAddr,
  476. dwWin32StartAddr;
  477. char cWaitMode;
  478. };
  479. struct CThreadStop
  480. {
  481. DWORD dwProcessID,
  482. dwThreadID;
  483. };
  484. void WINAPI CKernelTraceProvider::OnThreadEvent(PEVENT_TRACE pEvent)
  485. {
  486. CInCritSec cs(&g_pThis->m_cs);
  487. if (pEvent->Header.Class.Type == PROCESS_START)
  488. {
  489. if (g_pThis->m_pSinks[SINK_THREAD_START]->IsActive() != WBEM_S_NO_ERROR)
  490. return;
  491. CObjAccess *pObjEx = &g_pThis->m_eventThreadStart;
  492. CThreadStart *pStart = (CThreadStart*) pEvent->MofData;
  493. pObjEx->WriteDWORD64(0, pStart->dwStackBase);
  494. pObjEx->WriteDWORD64(1, pStart->dwStackLimit);
  495. pObjEx->WriteDWORD64(2, pStart->dwUserStackBase);
  496. pObjEx->WriteDWORD64(3, pStart->dwUserStackLimit);
  497. pObjEx->WriteDWORD64(4, pStart->dwStartAddr);
  498. pObjEx->WriteDWORD64(5, pStart->dwWin32StartAddr);
  499. pObjEx->WriteDWORD(6, pStart->dwProcessID);
  500. pObjEx->WriteDWORD(7, pStart->dwThreadID);
  501. pObjEx->WriteDWORD(8, pStart->cWaitMode);
  502. g_pThis->m_pSinks[SINK_THREAD_START]->
  503. Indicate(1, pObjEx->GetObjForIndicate());
  504. }
  505. else if (pEvent->Header.Class.Type == PROCESS_END)
  506. {
  507. if (g_pThis->m_pSinks[SINK_THREAD_STOP]->IsActive() != WBEM_S_NO_ERROR)
  508. return;
  509. CObjAccess *pObjEx = &g_pThis->m_eventThreadStop;
  510. CThreadStop *pStop = (CThreadStop*) pEvent->MofData;
  511. pObjEx->WriteDWORD(0, pStop->dwProcessID);
  512. pObjEx->WriteDWORD(1, pStop->dwThreadID);
  513. g_pThis->m_pSinks[SINK_THREAD_STOP]->
  514. Indicate(1, pObjEx->GetObjForIndicate());
  515. }
  516. }
  517. struct CImageLoad
  518. {
  519. DWORD_PTR dwImageBase;
  520. DWORD_PTR dwImageSize;
  521. DWORD dwProcessID;
  522. WCHAR szFileName[4];
  523. };
  524. void WINAPI CKernelTraceProvider::OnImageEvent(PEVENT_TRACE pEvent)
  525. {
  526. CInCritSec cs(&g_pThis->m_cs);
  527. if (g_pThis->m_pSinks[SINK_MODULE_LOAD]->IsActive() == WBEM_S_NO_ERROR)
  528. {
  529. CObjAccess *pObjEx = &g_pThis->m_eventModuleLoad;
  530. CImageLoad *pLoad = (CImageLoad*) pEvent->MofData;
  531. LPBYTE pData = (LPBYTE) pEvent->MofData;
  532. // Extrinsic events
  533. pObjEx->WriteDWORD64(0, pLoad->dwImageBase);
  534. pObjEx->WriteDWORD64(1, pLoad->dwImageSize);
  535. pObjEx->WriteDWORD(2, pLoad->dwProcessID);
  536. pObjEx->WriteString(3, pLoad->szFileName);
  537. g_pThis->m_pSinks[SINK_MODULE_LOAD]->Indicate(1, pObjEx->GetObjForIndicate());
  538. }
  539. }