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.

518 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. LSAWMI.C
  5. Abstract:
  6. Implement LSA Server event tracing by using WMI trace infrastructure.
  7. Author:
  8. 16-March-1999 kumarp
  9. Revision History:
  10. --*/
  11. #include <lsapch2.h>
  12. #include <wmistr.h>
  13. #define INITGUID
  14. #include <lsawmi.h>
  15. //
  16. // Globals
  17. //
  18. ULONG LsapEventTraceFlag = FALSE;
  19. TRACEHANDLE LsapTraceRegistrationHandle = (TRACEHANDLE) 0;
  20. TRACEHANDLE LsapTraceLoggerHandle = (TRACEHANDLE) 0;
  21. //
  22. // Forward declaration
  23. //
  24. ULONG
  25. LsapTraceControlCallBack(
  26. IN WMIDPREQUESTCODE RequestCode,
  27. IN PVOID RequestContext,
  28. IN OUT ULONG *InOutBufferSize,
  29. IN OUT PVOID Buffer
  30. );
  31. LPWSTR
  32. LsapMakeNullTerminatedString(
  33. IN PUNICODE_STRING u
  34. );
  35. //
  36. // before you change the elements of the following structure,
  37. // read notes in lsawmi.h file
  38. //
  39. TRACE_GUID_REGISTRATION LsapTraceGuids[] =
  40. {
  41. {&LsapTraceEventGuid_QuerySecret, NULL},
  42. {&LsaTraceEventGuid_Close, NULL},
  43. {&LsaTraceEventGuid_OpenPolicy, NULL},
  44. {&LsaTraceEventGuid_QueryInformationPolicy, NULL},
  45. {&LsaTraceEventGuid_SetInformationPolicy, NULL},
  46. {&LsaTraceEventGuid_EnumerateTrustedDomains, NULL},
  47. {&LsaTraceEventGuid_LookupNames, NULL},
  48. {&LsaTraceEventGuid_LookupSids, NULL},
  49. {&LsaTraceEventGuid_OpenTrustedDomain, NULL},
  50. {&LsaTraceEventGuid_QueryInfoTrustedDomain, NULL},
  51. {&LsaTraceEventGuid_SetInformationTrustedDomain, NULL},
  52. {&LsaTraceEventGuid_QueryTrustedDomainInfoByName, NULL},
  53. {&LsaTraceEventGuid_SetTrustedDomainInfoByName, NULL},
  54. {&LsaTraceEventGuid_EnumerateTrustedDomainsEx, NULL},
  55. {&LsaTraceEventGuid_CreateTrustedDomainEx, NULL},
  56. {&LsaTraceEventGuid_QueryDomainInformationPolicy, NULL},
  57. {&LsaTraceEventGuid_SetDomainInformationPolicy, NULL},
  58. {&LsaTraceEventGuid_OpenTrustedDomainByName, NULL},
  59. {&LsaTraceEventGuid_QueryForestTrustInformation, NULL},
  60. {&LsaTraceEventGuid_SetForestTrustInformation, NULL},
  61. {&LsaTraceEventGuid_LookupIsolatedNameInTrustedDomains, NULL},
  62. };
  63. #define LsapTraceGuidCount (sizeof(LsapTraceGuids) / sizeof(TRACE_GUID_REGISTRATION))
  64. ULONG
  65. _stdcall
  66. LsapInitializeWmiTrace( LPVOID ThreadParams )
  67. /*++
  68. Routine Description:
  69. Register WMI Trace Guids.
  70. This routine is called during LSA initialization. LSA gets initialized
  71. before WMI therefore we call this from a seaprate thread. This
  72. thread can then wait on WMI.
  73. Parameters:
  74. ThreadParams - Currently ignored.
  75. Reture Values:
  76. NTSTATUS - Standard Nt Result Code
  77. --*/
  78. {
  79. ULONG Status = ERROR_SUCCESS;
  80. HMODULE hModule;
  81. TCHAR FileName[MAX_PATH+1];
  82. DWORD nLen = 0;
  83. #define RESOURCE_NAME TEXT("LsaMofResource")
  84. #define IMAGE_PATH TEXT("lsass.exe")
  85. LsapEnterFunc("LsapInitializeWmiTrace");
  86. hModule = GetModuleHandle(IMAGE_PATH);
  87. if (hModule != NULL) {
  88. nLen = GetModuleFileName(hModule, FileName, MAX_PATH);
  89. }
  90. if (nLen == 0) {
  91. lstrcpy(FileName, IMAGE_PATH);
  92. }
  93. //
  94. // Register Trace GUIDs
  95. //
  96. Status = RegisterTraceGuids(
  97. LsapTraceControlCallBack,
  98. NULL,
  99. &LsapTraceControlGuid,
  100. LsapTraceGuidCount,
  101. LsapTraceGuids,
  102. FileName,
  103. RESOURCE_NAME,
  104. &LsapTraceRegistrationHandle);
  105. #if DBG
  106. if (Status != ERROR_SUCCESS)
  107. {
  108. DebugLog(( DEB_ERROR, "LsapInitializeWmiTrace failed: 0x%x\n", Status));
  109. }
  110. #endif // DBG
  111. return Status;
  112. }
  113. ULONG
  114. LsapTraceControlCallBack(
  115. IN WMIDPREQUESTCODE RequestCode,
  116. IN PVOID RequestContext,
  117. IN OUT ULONG *InOutBufferSize,
  118. IN OUT PVOID Buffer
  119. )
  120. /*++
  121. Routine Description:
  122. Call back function called by the WMI module to enable or
  123. disable LSA tracing.
  124. Arguments:
  125. RequestCode - WMI_ENABLE_EVENTS or WMI_DISABLE_EVENTS
  126. RequestContext - currently ignored
  127. InOutBufferSize - size of data returned by this call back.
  128. Currently always set to 0.
  129. Buffer - pointer to data received. In case of WMI_ENABLE_EVENTS,
  130. this is a pointer to the trace handle.
  131. Return Value:
  132. Win32 error code.
  133. Notes:
  134. --*/
  135. {
  136. ULONG Status = ERROR_SUCCESS;
  137. LsapEnterFunc("LsapTraceControlCallBack");
  138. switch (RequestCode)
  139. {
  140. case WMI_ENABLE_EVENTS:
  141. {
  142. LsapTraceLoggerHandle = GetTraceLoggerHandle(Buffer);
  143. LsapEventTraceFlag = TRUE; // enable flag
  144. break;
  145. }
  146. case WMI_DISABLE_EVENTS:
  147. {
  148. LsapTraceLoggerHandle = (TRACEHANDLE) 0;
  149. LsapEventTraceFlag = FALSE; // disable flag
  150. break;
  151. }
  152. default:
  153. {
  154. Status = ERROR_INVALID_PARAMETER;
  155. break;
  156. }
  157. }
  158. *InOutBufferSize = 0;
  159. return Status;
  160. }
  161. NTSTATUS
  162. LsapStartWmiTraceInitThread(void)
  163. /*++
  164. Routine Description:
  165. Start the thread that registers WMI trace guids.
  166. Parameters:
  167. None
  168. Return Values:
  169. NTSTATUS - Standard Nt Result Code
  170. --*/
  171. {
  172. NTSTATUS Status=STATUS_SUCCESS;
  173. HANDLE ThreadHandle;
  174. ULONG ThreadId = 0;
  175. ULONG WinError;
  176. ThreadHandle = CreateThread(NULL,
  177. 0,
  178. LsapInitializeWmiTrace,
  179. NULL,
  180. 0,
  181. &ThreadId);
  182. if (NULL == ThreadHandle)
  183. {
  184. Status = STATUS_UNSUCCESSFUL;
  185. WinError = GetLastError();
  186. DebugLog((DEB_ERROR, "Failed to create thread for LsapInitializeWmiTrace: 0x%x", WinError));
  187. }
  188. else
  189. {
  190. CloseHandle(ThreadHandle);
  191. }
  192. return Status;
  193. }
  194. VOID
  195. LsapTraceEvent(
  196. IN ULONG WmiEventType,
  197. IN LSA_TRACE_EVENT_TYPE LsaTraceEventType
  198. )
  199. /*++
  200. Routine Description:
  201. This routine will do a WMI event trace.
  202. Parameters:
  203. WmiEventType - Event Type, valid values are:
  204. EVENT_TRACE_TYPE_START
  205. EVENT_TRACE_TYPE_END
  206. TraceGuid - Index in LsapTraceGuids[]
  207. Return Values:
  208. None.
  209. --*/
  210. {
  211. LsapTraceEventWithData(WmiEventType,
  212. LsaTraceEventType,
  213. 0,
  214. NULL);
  215. }
  216. VOID
  217. LsapTraceEventWithData(
  218. IN ULONG WmiEventType,
  219. IN LSA_TRACE_EVENT_TYPE LsaTraceEventType,
  220. IN ULONG ItemCount,
  221. IN PUNICODE_STRING Items OPTIONAL
  222. )
  223. /*++
  224. Routine Description:
  225. This routine will do a WMI event trace.
  226. Parameters:
  227. WmiEventType - Event Type, valid values are:
  228. EVENT_TRACE_TYPE_START
  229. EVENT_TRACE_TYPE_END
  230. EVENT_TRACE_TYPE_INFO
  231. TraceGuid - Index in LsapTraceGuids[]
  232. ItemCount - the number of elements in Items
  233. Items - an array of information. The unicode strings don't have
  234. to represent strings -- can be binary data whose length
  235. is denoted by the Length field.
  236. Return Values:
  237. None.
  238. --*/
  239. {
  240. #if DBG
  241. ULONG WinError;
  242. #endif
  243. WCHAR NullChar = UNICODE_NULL;
  244. PVOID BuffersToFree[10];
  245. ULONG BuffersToFreeCount = 0;
  246. ULONG i;
  247. struct
  248. {
  249. EVENT_TRACE_HEADER EventTrace;
  250. MOF_FIELD EventInfo[2];
  251. } Event;
  252. //
  253. // Theoretically, only test LsapEventTraceFlag would be enough, since
  254. // LsapEventTraceFlag will remain FALSE in Registry Mode, because
  255. // LsapInitializeTrace() will never been called in Registry Mode.
  256. // Thus nobody will change the value of LsapEventTraceFlag
  257. //
  258. if (!LsapEventTraceFlag) {
  259. return;
  260. }
  261. //
  262. // Fill the event information.
  263. //
  264. ZeroMemory(&Event, sizeof(Event));
  265. Event.EventTrace.GuidPtr = (ULONGLONG) LsapTraceGuids[LsaTraceEventType].Guid;
  266. Event.EventTrace.Class.Type = (UCHAR) WmiEventType;
  267. Event.EventTrace.Flags |= (WNODE_FLAG_USE_GUID_PTR | // GUID is actually a pointer
  268. WNODE_FLAG_TRACED_GUID); // denotes a trace
  269. Event.EventTrace.Size = sizeof(Event.EventTrace); // no other parameters/information
  270. if ( (LsaTraceEventType == LsaTraceEvent_LookupIsolatedNameInTrustedDomains) ) {
  271. //
  272. // Add the flag that indicates that there is more data
  273. //
  274. Event.EventTrace.Flags |= WNODE_FLAG_USE_MOF_PTR;
  275. //
  276. // Make sure enough space has been allocated on the stack for us
  277. //
  278. ASSERT(sizeof(Event.EventInfo) >= (sizeof(MOF_FIELD) * 2));
  279. ASSERT( (ItemCount == 2) && (Items != NULL) );
  280. //
  281. // Fill in the data requested
  282. //
  283. for (i = 0; i < ItemCount; i++) {
  284. LPWSTR String = NULL;
  285. ULONG Length;
  286. //
  287. // Re'alloc to get a NULL terminated string
  288. //
  289. String = LsapMakeNullTerminatedString(&Items[i]);
  290. if (NULL == String) {
  291. String = &NullChar;
  292. Length = sizeof(NullChar);
  293. } else {
  294. Length = Items[i].Length + sizeof(WCHAR);
  295. }
  296. Event.EventInfo[i].Length = Length;
  297. Event.EventInfo[i].DataPtr = (ULONGLONG)String;
  298. Event.EventTrace.Size += sizeof(Event.EventInfo[i]);
  299. if (&NullChar != String) {
  300. ASSERT(BuffersToFreeCount < sizeof(BuffersToFree)/sizeof(BuffersToFree[0]));
  301. BuffersToFree[BuffersToFreeCount++] = String;
  302. }
  303. }
  304. }
  305. #if DBG
  306. WinError =
  307. #endif
  308. TraceEvent(LsapTraceLoggerHandle, (PEVENT_TRACE_HEADER) &Event);
  309. #if DBG
  310. if (WinError != ERROR_SUCCESS)
  311. {
  312. DebugLog(( DEB_ERROR, "WMI TraceEvent failed, status %x\n", WinError));
  313. }
  314. #endif
  315. for (i = 0; i < BuffersToFreeCount; i++) {
  316. LsapFreeLsaHeap(BuffersToFree[i]);
  317. }
  318. }
  319. LPWSTR
  320. LsapGetClientNetworkAddress(
  321. VOID
  322. )
  323. /*++
  324. Routine Description:
  325. This routine returns a NULL terminated string that represents the network
  326. address of the client. If the address cannot be obtained, NULL is returned.
  327. If the return value is non-NULL, the string must be freed with
  328. RpcStringFreeW.
  329. Parameters:
  330. None.
  331. Return Values:
  332. See description.
  333. --*/
  334. {
  335. ULONG RpcStatus;
  336. RPC_BINDING_HANDLE ServerBinding = NULL;
  337. PWSTR StringBinding = NULL;
  338. LPWSTR NetworkAddr = NULL;
  339. RpcStatus = RpcBindingServerFromClient(NULL, &ServerBinding);
  340. if (RPC_S_OK == RpcStatus) {
  341. RpcStatus = RpcBindingToStringBindingW(ServerBinding, &StringBinding);
  342. if (RPC_S_OK == RpcStatus) {
  343. RpcStatus = RpcStringBindingParseW(StringBinding,
  344. NULL,
  345. NULL,
  346. &NetworkAddr,
  347. NULL,
  348. NULL
  349. );
  350. RpcStringFreeW(&StringBinding);
  351. }
  352. RpcBindingFree(&ServerBinding);
  353. }
  354. return NetworkAddr;
  355. }
  356. LPWSTR
  357. LsapMakeNullTerminatedString(
  358. IN PUNICODE_STRING u
  359. )
  360. /*++
  361. Routine Description:
  362. This routine returns a NULL terminated string composed of the data in
  363. u. The string must be freed with LsapFreeLsaHeap().
  364. If u->Length is 0, a non-NULL string with the NULL character as the first
  365. character is returned.
  366. Parameters:
  367. u -- a unicode string
  368. Return Values:
  369. See description.
  370. --*/
  371. {
  372. LPWSTR String = NULL;
  373. ULONG Length;
  374. if (u) {
  375. Length = u->Length + sizeof(WCHAR);
  376. String = LsapAllocateLsaHeap(Length);
  377. if (String != NULL) {
  378. RtlCopyMemory(String, u->Buffer, u->Length);
  379. String[u->Length / sizeof(WCHAR)] = UNICODE_NULL;
  380. }
  381. }
  382. return String;
  383. }