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.

517 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. eventlog.c
  6. Abstract:
  7. This module provides all functions that the Local Print Providor
  8. uses to write to the Event Log.
  9. InitializeEventLogging
  10. DisableEventLogging
  11. LogEvent
  12. GetUserSid
  13. Author:
  14. Dave Snipp (DaveSn) 15-Mar-1991
  15. Revision History:
  16. Matthew Felton ( MattFe ) 15-Mar-1995
  17. Change defaults on Workstation to not log information messages
  18. Also add regsitry key to allow user to filter some types of call
  19. --*/
  20. #include <precomp.h>
  21. #pragma hdrstop
  22. #include "clusspl.h"
  23. #define MAX_MERGE_STRINGS 7
  24. HANDLE hEventSource = NULL;
  25. #if DBG
  26. BOOL EventLogFull = FALSE;
  27. #endif
  28. BOOL
  29. GetUserSid(
  30. PTOKEN_USER *ppTokenUser,
  31. PDWORD pcbTokenUser
  32. );
  33. DWORD
  34. InitializeEventLogging(
  35. PINISPOOLER pIniSpooler
  36. )
  37. {
  38. DWORD Status;
  39. HKEY hkey;
  40. DWORD dwData;
  41. DWORD dwDisposition;
  42. DWORD Flags;
  43. NT_PRODUCT_TYPE NtProductType;
  44. //
  45. // Initialize defaults.
  46. //
  47. pIniSpooler->dwEventLogging = LOG_DEFAULTS_WORKSTATION_EVENTS;
  48. //
  49. // Default is no NetPopup. 0 - Disable NetPopup, 1 - Enable
  50. //
  51. pIniSpooler->bEnableNetPopups = 0;
  52. //
  53. // Caching Providers Might not require Event Logging
  54. //
  55. if ( ( pIniSpooler->SpoolerFlags & SPL_LOG_EVENTS ) == FALSE ) return TRUE;
  56. //
  57. // Turn on logging if we are a server.
  58. //
  59. if (RtlGetNtProductType(&NtProductType)) {
  60. if (NtProductType != NtProductWinNt) {
  61. pIniSpooler->dwEventLogging = LOG_ALL_EVENTS;
  62. }
  63. }
  64. //
  65. // If we aren't event logging or we are a cluster reg, then
  66. // don't initialize per-machine resources.
  67. //
  68. if( pIniSpooler != pLocalIniSpooler ){
  69. return NO_ERROR;
  70. }
  71. Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  72. pIniSpooler->pszRegistryEventLog,
  73. 0,
  74. NULL,
  75. 0,
  76. KEY_WRITE,
  77. NULL,
  78. &hkey,
  79. &dwDisposition);
  80. if( Status == NO_ERROR )
  81. {
  82. // Add the Event-ID message-file name to the subkey.
  83. Status = RegSetValueEx( hkey,
  84. L"EventMessageFile",
  85. 0,
  86. REG_EXPAND_SZ,
  87. (LPBYTE)pIniSpooler->pszEventLogMsgFile,
  88. wcslen( pIniSpooler->pszEventLogMsgFile ) * sizeof( WCHAR )
  89. + sizeof( WCHAR ) );
  90. if( Status != NO_ERROR )
  91. {
  92. DBGMSG( DBG_ERROR, ( "Could not set event message file: Error %d\n",
  93. Status ) );
  94. }
  95. dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE
  96. | EVENTLOG_INFORMATION_TYPE;
  97. if( Status == NO_ERROR )
  98. {
  99. Status = RegSetValueEx( hkey,
  100. L"TypesSupported",
  101. 0,
  102. REG_DWORD,
  103. (LPBYTE)&dwData,
  104. sizeof dwData );
  105. if( Status != NO_ERROR )
  106. {
  107. DBGMSG( DBG_ERROR, ( "Could not set supported types: Error %d\n",
  108. Status ) );
  109. }
  110. }
  111. RegCloseKey(hkey);
  112. }
  113. else
  114. {
  115. DBGMSG( DBG_ERROR, ( "Could not create registry key for event logging: Error %d\n",
  116. Status ) );
  117. }
  118. if( Status == NO_ERROR )
  119. {
  120. if( !( hEventSource = RegisterEventSource( NULL, L"Print" ) ) )
  121. Status = GetLastError( );
  122. }
  123. return Status;
  124. }
  125. VOID
  126. SplLogEventWorker(
  127. IN PINISPOOLER pIniSpooler,
  128. IN WORD EventType,
  129. IN NTSTATUS EventID,
  130. IN BOOL bInSplSem,
  131. IN LPWSTR pFirstString,
  132. IN va_list vargs
  133. )
  134. /*++
  135. Function Description:
  136. This provides a common entry point to support event logging. This is now
  137. called by the print processor and Win32spl.
  138. Parameters:
  139. EventType - E.g. LOG_ERROR (defined in local.h)
  140. EventID - Constant as defined in messages.h. This refers to a string
  141. resource located in the event-log message DLL specified in
  142. InitializeEventLogging (which currently is localspl.dll itself).
  143. bInSplSem - flag to indicate if the call was made from inside SplSem
  144. pFirstString- The first of up to MAX_MERGE_STRINGS. This may be NULL,
  145. if no strings are to be inserted. If strings are passed to this
  146. routine, the last one must be followed by NULL.
  147. Don't rely on the fact that the argument copying stops when it
  148. reaches MAX_MERGE_STRINGS, because this could change if future
  149. messages are found to need more replaceable parameters.
  150. vargs - The remaining strings to be passed in.
  151. Return Values: NONE
  152. --*/
  153. {
  154. PTOKEN_USER pTokenUser = NULL;
  155. DWORD cbTokenUser;
  156. PSID pSid = NULL;
  157. LPWSTR pMergeStrings[MAX_MERGE_STRINGS];
  158. WORD cMergeStrings = 0, index;
  159. DWORD LastError = GetLastError();
  160. if (!hEventSource)
  161. return;
  162. //
  163. // If the Inispooler is NULL, don't check whether to log an event, just log one,
  164. // This allows us to log events when failing to start up spooler.
  165. //
  166. if ( pIniSpooler )
  167. {
  168. if (( pIniSpooler->dwEventLogging & EventType ) == FALSE )
  169. return;
  170. if ( ( pIniSpooler->SpoolerFlags & SPL_LOG_EVENTS ) == FALSE )
  171. return;
  172. }
  173. if( GetUserSid( &pTokenUser, &cbTokenUser ) )
  174. pSid = pTokenUser->User.Sid;
  175. // Put the strings into a format accepted by ReportEvent,
  176. // by picking off each non-null argument, and storing it in the array
  177. // of merge strings. Continue till we hit a NULL, or MAX_MERGE_STRINGS.
  178. if( pFirstString )
  179. {
  180. LPWSTR pszInsert;
  181. if (pMergeStrings[cMergeStrings] = AllocSplStr(pFirstString))
  182. {
  183. cMergeStrings++;
  184. }
  185. else
  186. {
  187. goto CleanUp;
  188. }
  189. while ((cMergeStrings < MAX_MERGE_STRINGS) &&
  190. (pszInsert = va_arg(vargs, LPWSTR))) {
  191. if (pMergeStrings[cMergeStrings] = AllocSplStr(pszInsert))
  192. {
  193. cMergeStrings++;
  194. }
  195. else
  196. {
  197. goto CleanUp;
  198. }
  199. }
  200. }
  201. //
  202. // Leave the semaphore before calling into the event logging service
  203. //
  204. if (bInSplSem)
  205. {
  206. LeaveSplSem();
  207. SplOutSem();
  208. }
  209. if ( !ReportEvent(hEventSource, // handle returned by RegisterEventSource
  210. EventType, // event type to log
  211. 0, // event category
  212. EventID, // event identifier
  213. pSid, // user security identifier (optional)
  214. cMergeStrings, // number of strings to merge with message
  215. 0, // size of raw data (in bytes)
  216. pMergeStrings, // array of strings to merge with message
  217. NULL) ) { // address of raw data
  218. #if DBG
  219. if( GetLastError() == ERROR_LOG_FILE_FULL ) {
  220. // Put out a warning message only the first time this happens:
  221. if( !EventLogFull ) {
  222. DBGMSG( DBG_WARNING, ( "The Event Log is full\n" ) );
  223. EventLogFull = TRUE;
  224. }
  225. } else {
  226. DBGMSG( DBG_WARNING, ( "ReportEvent failed: Error %d\n", GetLastError( ) ));
  227. }
  228. #endif // DBG
  229. }
  230. //
  231. // Reenter the semaphore after logging the event
  232. //
  233. if (bInSplSem)
  234. {
  235. EnterSplSem();
  236. }
  237. CleanUp:
  238. // Free the strings
  239. for (index = 0; index < cMergeStrings ; index++) {
  240. FreeSplStr(pMergeStrings[index]);
  241. }
  242. if( pTokenUser ) {
  243. FreeSplMem( pTokenUser );
  244. }
  245. // GetUserSid() wipes out the Last Error, so restore it before returning
  246. SetLastError(LastError);
  247. }
  248. VOID
  249. SplLogEvent(
  250. PINISPOOLER pIniSpooler,
  251. WORD EventType,
  252. NTSTATUS EventID,
  253. BOOL bInSplSem,
  254. LPWSTR pFirstString,
  255. ...
  256. )
  257. /*++
  258. Function Description: Writes to the event log with up to MAX_MERGE_STRINGS parameter strings.
  259. Parameters: EventType - E.g. LOG_ERROR (defined in local.h)
  260. EventID - Constant as defined in messages.h. This refers to a string
  261. resource located in the event-log message DLL specified in
  262. InitializeEventLogging (which currently is localspl.dll itself).
  263. bInSplSem - flag to indicate if the call was made from inside SplSem
  264. pFirstString - The first of up to MAX_MERGE_STRINGS. This may be NULL,
  265. if no strings are to be inserted. If strings are passed to this
  266. routine, the last one must be followed by NULL.
  267. Don't rely on the fact that the argument copying stops when it
  268. reaches MAX_MERGE_STRINGS, because this could change if future
  269. messages are found to need more replaceable parameters.
  270. Return Values: NONE
  271. --*/
  272. {
  273. va_list vargs;
  274. va_start(vargs, pFirstString);
  275. SplLogEventWorker(pIniSpooler, EventType, EventID, bInSplSem, pFirstString, vargs);
  276. va_end(vargs);
  277. }
  278. VOID
  279. PrintProcLogEvent(
  280. WORD EventType,
  281. NTSTATUS EventID,
  282. LPWSTR pLog
  283. )
  284. /*++
  285. Function Description: This is an export for the print processor to log errors.
  286. Parameters: EventType - E.g. LOG_ERROR (defined in local.h)
  287. EventID - Constant as defined in messages.h
  288. pLog - string containg the log message
  289. Return Values: NONE
  290. --*/
  291. {
  292. // Ensure that the last parameter is NULL
  293. if (pLog == NULL)
  294. {
  295. SplLogEvent(pLocalIniSpooler, EventType, EventID, FALSE, NULL);
  296. }
  297. else
  298. {
  299. SplLogEvent(pLocalIniSpooler, EventType, EventID, FALSE, pLog, NULL);
  300. }
  301. return;
  302. }
  303. VOID
  304. SplLogEventExternal(
  305. IN WORD EventType,
  306. IN DWORD EventID,
  307. IN LPWSTR pFirstString,
  308. ...
  309. )
  310. /*++
  311. Function Description:
  312. This is an export for external components to log an event. (It is currently
  313. used for Win32spl). It supports variable arguments, unlike PrintProcLogEvent.
  314. Parameters:
  315. EventType - E.g. LOG_ERROR (defined in local.h)
  316. EventID - Constant as defined in messages.h
  317. pFirstString - The first string supplied by the system in the log message.
  318. ... - The remaining strings, must be NULL terminated.
  319. Return Values: NONE
  320. --*/
  321. {
  322. va_list vargs;
  323. va_start(vargs, pFirstString);
  324. //
  325. // It might not seem logical to use the local inispooler. However, win32spl's
  326. // inispooler's explicitely turn off event logging. So, this is necessary.
  327. // Passing in NULL seems worse since this would mean you could not tone down
  328. // event logging for those events.
  329. //
  330. SplLogEventWorker(pLocalIniSpooler, EventType, (NTSTATUS)EventID, FALSE, pFirstString, vargs);
  331. va_end(vargs);
  332. }
  333. // GetUserSid
  334. //
  335. // Well, actually it gets a pointer to a newly allocated TOKEN_USER,
  336. // which contains a SID, somewhere.
  337. // Caller must remember to free it when it's been used.
  338. BOOL
  339. GetUserSid(
  340. PTOKEN_USER *ppTokenUser,
  341. PDWORD pcbTokenUser
  342. )
  343. {
  344. HANDLE TokenHandle;
  345. HANDLE ImpersonationToken;
  346. PTOKEN_USER pTokenUser = NULL;
  347. DWORD cbTokenUser = 0;
  348. DWORD cbNeeded;
  349. BOOL bRet = FALSE;
  350. if ( !GetTokenHandle( &TokenHandle) ) {
  351. return FALSE;
  352. }
  353. ImpersonationToken = RevertToPrinterSelf();
  354. bRet = GetTokenInformation( TokenHandle,
  355. TokenUser,
  356. pTokenUser,
  357. cbTokenUser,
  358. &cbNeeded);
  359. // We've passed a NULL pointer and 0 for the amount of memory
  360. // allocated. We expect to fail with bRet = FALSE and
  361. // GetLastError = ERROR_INSUFFICIENT_BUFFER. If we do not
  362. // have these conditions we will return FALSE
  363. if ( !bRet && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) {
  364. pTokenUser = AllocSplMem( cbNeeded );
  365. if ( pTokenUser == NULL ) {
  366. goto GetUserSidDone;
  367. }
  368. cbTokenUser = cbNeeded;
  369. bRet = GetTokenInformation( TokenHandle,
  370. TokenUser,
  371. pTokenUser,
  372. cbTokenUser,
  373. &cbNeeded );
  374. } else {
  375. //
  376. // Any other case -- return FALSE
  377. //
  378. bRet = FALSE;
  379. }
  380. GetUserSidDone:
  381. if ( bRet == TRUE ) {
  382. *ppTokenUser = pTokenUser;
  383. *pcbTokenUser = cbTokenUser;
  384. } else if ( pTokenUser ) {
  385. FreeSplMem( pTokenUser );
  386. }
  387. if (!ImpersonatePrinterClient( ImpersonationToken ))
  388. {
  389. bRet = FALSE;
  390. }
  391. CloseHandle( TokenHandle );
  392. return bRet;
  393. }