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.

359 lines
12 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. cntxtlog.h
  5. Abstract:
  6. This module implements more logging for setupapi
  7. Author:
  8. Gabe Schaffer (t-gabes) 7-Jul-1998
  9. Revision History:
  10. Jamie Hunter (jamiehun) 26-Aug-1998
  11. --*/
  12. /*
  13. There are two log levels. One is set in the registry, which determines
  14. what is logged and how. The other is passed as a parameter, and indicates
  15. under what conditions the entry should be logged. For example, the registry
  16. would say that all errors and warnings should be logged, while the call to
  17. WriteLogEntry would specify in the LogLevel parameter that some string
  18. should be logged as a warning.
  19. The 24 least-significant bits specify flags which indicate the type of
  20. message when passed as a parameter, or the type of messages to logged
  21. when set in the registry.
  22. The 4 most-significant bits are flags:
  23. SETUP_LOG_DEBUGOUT - when specified in the registry, indicates that all
  24. log output should be sent to the debugger as well as the logfile.
  25. This flag is currently not supported as a parameter to WriteLogEntry.
  26. SETUP_LOG_SIMPLE - when specified in the registry, indicates that all
  27. logfile entries should be appended to the logfile in chronological
  28. order, rather than grouped by section name. This flag is not
  29. currently supported as a parameter.
  30. SETUP_LOG_BUFFER - when specified as a parameter, indicates that the
  31. message to be logged will be buffered until such time as a call to
  32. WriteLogEntry with the same LogContext but this flag is not specified.
  33. When an entry is to be logged without this flag set, the latest
  34. message will be added to the buffer, and the buffer will be flushed to
  35. the logfile.
  36. This allows you to build up a string to log without having to do
  37. buffer management everywhere.
  38. This flag does not make sense in the registry.
  39. NOTE: for proper functioning, do not mix log levels while buffering
  40. output.
  41. NOTE: if this flag is NOT specified, the string to be logged MUST
  42. end in a newline, otherwise bad stuff will happen if another log
  43. context writes to the logfile immediately afterward.
  44. SETUP_LOG_IS_CONTEXT - when specified in the registry, indicates that
  45. all context messages should be immediately logged to the logfile,
  46. rather than buffered in the LogContext.
  47. This flag should never appear in a file other than cntxtlog.*;
  48. that is, as a parameter it only makes sense if added to a multiple
  49. of SETUP_FIRST_LOG_CONTEXT.
  50. NOTE: the context buffering mechanism is explained below where
  51. ContextInfo is defined in SETUP_LOG_CONTEXT.
  52. */
  53. //
  54. // These registry/filename strings should probably belong elsewhere
  55. //
  56. #define SP_REGKEY_LOGLEVEL TEXT("LogLevel")
  57. #define SP_REGKEY_LOGPATH TEXT("LogPath")
  58. #define SP_REGKEY_APPLOGLEVEL TEXT("AppLogLevels")
  59. #define SP_LOG_FILENAME TEXT("setupapi.log")
  60. //
  61. // these are for general setup log entries
  62. //
  63. #define SETUP_LOG_SHIFT (0)
  64. #define SETUP_LOG_LEVELMASK 0x000000FF
  65. #define SETUP_LOG_NOLOG 0x00000001 // indicates no-logging (remember 0 is default)
  66. #define SETUP_LOG_ERROR 0x00000010 // 10-1f is varying levels of errors
  67. #define SETUP_LOG_WARNING 0x00000020 // 20-2f is varying levels of warnings
  68. #define SETUP_LOG_INFO 0x00000030 // 30-3f is varying levels of info
  69. #define SETUP_LOG_VERBOSE 0x00000040 // 40-4f is varying levels of verbose
  70. #define SETUP_LOG_TIME 0x00000050 // 50+ allow logging of time-stamped enties
  71. #define SETUP_LOG_TIMEALL 0x00000060 // 60+ turns on time-stamping of all entries
  72. #define SETUP_LOG_VVERBOSE 0x00000070 // 70-7f is very-verbose - reserved for stuff that logging really slows down
  73. #define SETUP_LOG_DEFAULT 0x00000020
  74. //
  75. // these are for driver-only log entries
  76. //
  77. #define DRIVER_LOG_SHIFT (8)
  78. #define DRIVER_LOG_LEVELMASK 0x0000FF00
  79. #define DRIVER_LOG_NOLOG 0x00000100 // indicates no-logging (remember 0 is default)
  80. #define DRIVER_LOG_ERROR 0x00001000
  81. #define DRIVER_LOG_WARNING 0x00002000
  82. #define DRIVER_LOG_INFO 0x00003000
  83. #define DRIVER_LOG_INFO1 0x00003100
  84. #define DRIVER_LOG_VERBOSE 0x00004000
  85. #define DRIVER_LOG_VERBOSE1 0x00004100
  86. #define DRIVER_LOG_TIME 0x00005000
  87. #define DRIVER_LOG_TIMEALL 0x00006000
  88. #define DRIVER_LOG_VVERBOSE 0x00007000 // 70-7f is very-verbose - reserved for stuff that logging really slows down
  89. #define DRIVER_LOG_DEFAULT 0x00003000
  90. //
  91. // Calling AllocLogInfoSlot will return an index with SETUP_LOG_IS_CONTEXT set
  92. // this index represents a nested stack entry for logging information
  93. // that will get dumped if an actual log entry is dumped
  94. // thus providing more information
  95. // note that lower 16 bits are used for index, re-using above Log level bits
  96. //
  97. #define SETUP_LOG_IS_CONTEXT 0x10000000
  98. #define SETUP_LOG_CONTEXTMASK 0x0000ffff
  99. //
  100. // pass this flag to WriteLogEntry to have the entry stored in a buffer,
  101. // to be spit out the next time the flag is *not* specified
  102. //
  103. #define SETUP_LOG_BUFFER 0x20000000
  104. //
  105. // pass this flag to registry to have output sent to debugger
  106. //
  107. #define SETUP_LOG_DEBUGOUT 0x80000000
  108. //
  109. // pass this flag to registry to have entries simply appended to the log
  110. //
  111. #define SETUP_LOG_SIMPLE 0x40000000
  112. //
  113. // pass this flag to registry to speed up logging
  114. //
  115. #define SETUP_LOG_NOFLUSH 0x20000000
  116. //
  117. // pass this flag to registry to indicate we want to always log SETUP_LOG_ISCONTEXT
  118. //
  119. #define SETUP_LOG_ALL_CONTEXT 0x10000000
  120. //
  121. // pass this flag to registry to indicate we always want to log timestamp
  122. //
  123. #define SETUP_LOG_TIMESTAMP 0x08000000
  124. //
  125. // for validating registry log value
  126. //
  127. #define SETUP_LOG_VALIDREGBITS (SETUP_LOG_DEBUGOUT|SETUP_LOG_SIMPLE|SETUP_LOG_NOFLUSH|SETUP_LOG_ALL_CONTEXT|SETUP_LOG_TIMESTAMP|DRIVER_LOG_LEVELMASK|SETUP_LOG_LEVELMASK)
  128. //
  129. // for validating non-context log value
  130. //
  131. #define SETUP_LOG_VALIDLOGBITS (SETUP_LOG_DEBUGOUT|SETUP_LOG_BUFFER|DRIVER_LOG_LEVELMASK|SETUP_LOG_LEVELMASK)
  132. //
  133. // for validating context log value
  134. //
  135. #define SETUP_LOG_VALIDCONTEXTBITS (SETUP_LOG_IS_CONTEXT | SETUP_LOG_CONTEXTMASK)
  136. //
  137. // timeouts when waiting for log acquired by another process
  138. //
  139. #define MAX_LOG_INTERVAL (1000) // 1s
  140. #define MAX_LOG_WAIT (10 * MAX_LOG_INTERVAL)
  141. //
  142. // This is the structure that holds all of the data required to persist logging
  143. // information. It is not to be confused with the SETUPLOG_CONTEXT struct that
  144. // is used elsewhere in setup.
  145. //
  146. typedef struct _SETUP_LOG_CONTEXT {
  147. //
  148. // Pointer to allocated name of section to be used.
  149. // If NULL, a section name will be generated on first use.
  150. //
  151. PTSTR SectionName;
  152. //
  153. // Multiple structures may simultaneously have pointers to
  154. // this struct, so a ref count is needed. CreateLogContext()
  155. // will set this to 1, and DeleteLogContext() will decrement
  156. // this until it reaches 0 (at which point the structure is
  157. // actually freed).
  158. //
  159. UINT RefCount;
  160. //
  161. // This is the number of entries that have been logged in this
  162. // context. If timestamp is used for the section name, this will
  163. // allow us to use the time of the first error, rather than the
  164. // time the log context was created.
  165. //
  166. UINT LoggedEntries;
  167. //
  168. // These fields are for implementation of
  169. // AllocLogSlot and ReleaseLogSlot functions
  170. // ContextInfo is a list of strings indexable via SETUP_LOG_CONTEXTMASK
  171. // bits of a context slot returned by AllocLogSlot (ie, the slot)
  172. // it is also enumeratable via the link list headed by ContextFirstUsed
  173. // ContextFirstUsed points to first slot currently in use (bottom of stack)
  174. // ContextIndexes[ContextFirstUsed] points to next and so on
  175. // ContextLastUnused points to last slot that was released
  176. // -1 is used as end of list value
  177. // An entry may disappear in the middle of the stack if the context is used in
  178. // more than one thread
  179. //
  180. PTSTR *ContextInfo; // pointer to array of strings
  181. int *ContextIndexes; // by mark, is either index to ContextInfo, or to next unused mark
  182. int ContextLastUnused; // LIFO linked list of unused marks
  183. int ContextBufferSize; // items allocated for
  184. int ContextFirstUsed; // FIFO linked list of used marks
  185. int ContextFirstAuto; // FIFO linked list of auto-release used marks
  186. //
  187. // Sometimes multiple strings need to be logged as one entry, which
  188. // requires making multiple calls to WriteLogEntry. If SETUP_LOG_BUFFER
  189. // is specified, the text will be accumulated in the buffer until such
  190. // time as SETUP_LOG_BUFFER is not specified, in which case the
  191. // contents of Buffer is output together with the current string.
  192. //
  193. PTSTR Buffer;
  194. //
  195. // In case multiple threads access this struct simultaneously,
  196. // access to ContextInfo must be serialized. Also, we
  197. // don't want this to be deleted while another thread is using it.
  198. //
  199. } SETUP_LOG_CONTEXT, *PSETUP_LOG_CONTEXT;
  200. //
  201. // TLS data used by logging
  202. //
  203. typedef struct _SETUP_LOG_TLS {
  204. //
  205. // stack of context's
  206. //
  207. PSETUP_LOG_CONTEXT ThreadLogContext;
  208. } SETUP_LOG_TLS, *PSETUP_LOG_TLS;
  209. //
  210. // Convenient macro for determining whether a deletion failure should be
  211. // considered an error or a verbose entry.
  212. //
  213. #define DEL_ERR_LOG_LEVEL(Err) ((((Err) == ERROR_FILE_NOT_FOUND) || ((Err) == ERROR_PATH_NOT_FOUND)) \
  214. ? SETUP_LOG_VERBOSE : SETUP_LOG_ERROR)
  215. DWORD
  216. CreateLogContext(
  217. IN PCTSTR SectionName, OPTIONAL
  218. IN BOOL UseDefault,
  219. OUT PSETUP_LOG_CONTEXT *LogContext
  220. );
  221. VOID
  222. DeleteLogContext(
  223. IN PSETUP_LOG_CONTEXT LogContext
  224. );
  225. DWORD
  226. RefLogContext( // increment reference count
  227. IN PSETUP_LOG_CONTEXT LogContext
  228. );
  229. VOID
  230. SetLogSectionName(
  231. IN PSETUP_LOG_CONTEXT LogContext,
  232. IN PCTSTR SectionName
  233. );
  234. DWORD
  235. InheritLogContext(
  236. IN TRACK_ARG_DECLARE TRACK_ARG_COMMA
  237. IN PSETUP_LOG_CONTEXT Source,
  238. OUT PSETUP_LOG_CONTEXT *Dest
  239. );
  240. DWORD
  241. ShareLogContext(
  242. IN OUT PSETUP_LOG_CONTEXT *Primary,
  243. IN OUT PSETUP_LOG_CONTEXT *Secondary
  244. );
  245. DWORD
  246. pSetupWriteLogEntry(
  247. IN PSETUP_LOG_CONTEXT LogContext, OPTIONAL
  248. IN DWORD Level,
  249. IN DWORD MessageId,
  250. IN PCTSTR MessageStr, OPTIONAL
  251. ... OPTIONAL
  252. );
  253. VOID
  254. pSetupWriteLogError(
  255. IN PSETUP_LOG_CONTEXT LogContext, OPTIONAL
  256. IN DWORD Level,
  257. IN DWORD Error
  258. );
  259. #define WriteLogEntry pSetupWriteLogEntry
  260. #define WriteLogError pSetupWriteLogError
  261. DWORD
  262. MakeUniqueName(
  263. IN PCTSTR Component, OPTIONAL
  264. OUT PTSTR * UniqueString
  265. );
  266. DWORD
  267. AllocLogInfoSlot(
  268. IN PSETUP_LOG_CONTEXT LogContext,
  269. IN BOOL AutoRelease
  270. );
  271. DWORD
  272. AllocLogInfoSlotOrLevel(
  273. IN PSETUP_LOG_CONTEXT LogContext,
  274. IN DWORD Level,
  275. IN BOOL AutoRelease
  276. );
  277. VOID
  278. ReleaseLogInfoSlot(
  279. IN PSETUP_LOG_CONTEXT LogContext,
  280. DWORD Slot
  281. );
  282. BOOL
  283. InitializeContextLogging(
  284. IN BOOL Attach
  285. );
  286. BOOL
  287. ContextLoggingTlsInit(
  288. IN BOOL Init
  289. );
  290. BOOL
  291. SetThreadLogContext(
  292. IN PSETUP_LOG_CONTEXT LogContext,
  293. OUT PSETUP_LOG_CONTEXT *PrevContext OPTIONAL
  294. );
  295. PSETUP_LOG_CONTEXT
  296. GetThreadLogContext(
  297. );