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.

608 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. errlog.c
  5. Abstract:
  6. Routines to handle error log information
  7. Author:
  8. Jin Huang (jinhuang) 9-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "headers.h"
  12. #include "serverp.h"
  13. #include <winnls.h>
  14. #include <alloca.h>
  15. #pragma hdrstop
  16. #define SCESRV_LOG_PATH L"\\security\\logs\\scesrv.log"
  17. extern HINSTANCE MyModuleHandle;
  18. HANDLE Thread hMyLogFile=INVALID_HANDLE_VALUE;
  19. BOOL
  20. ScepCheckLogging(
  21. IN INT ErrLevel,
  22. IN DWORD rc
  23. );
  24. SCESTATUS
  25. ScepSetVerboseLog(
  26. IN INT dbgLevel
  27. )
  28. {
  29. DWORD dValue;
  30. if ( dbgLevel > 0 ) {
  31. gDebugLevel = dbgLevel;
  32. } else {
  33. //
  34. // load value from registry
  35. //
  36. if ( ScepRegQueryIntValue(
  37. HKEY_LOCAL_MACHINE,
  38. SCE_ROOT_PATH,
  39. L"DebugLevel",
  40. &dValue
  41. ) == SCESTATUS_SUCCESS )
  42. gDebugLevel = (INT)dValue;
  43. else
  44. gDebugLevel = 1;
  45. }
  46. return(SCESTATUS_SUCCESS);
  47. }
  48. SCESTATUS
  49. ScepEnableDisableLog(
  50. IN BOOL bOnOff
  51. )
  52. {
  53. bLogOn = bOnOff;
  54. if ( INVALID_HANDLE_VALUE != hMyLogFile ) {
  55. CloseHandle( hMyLogFile );
  56. }
  57. //
  58. // Reset the LogFileName buffer and return
  59. //
  60. hMyLogFile = INVALID_HANDLE_VALUE;
  61. return(SCESTATUS_SUCCESS);
  62. }
  63. SCESTATUS
  64. ScepLogInitialize(
  65. IN PCWSTR logname
  66. )
  67. /* ++
  68. Routine Description:
  69. Open the log file specified and save the name and its handle in global
  70. variables.
  71. Arguments:
  72. logname - log file name
  73. Return value:
  74. SCESTATUS error code
  75. -- */
  76. {
  77. DWORD rc=NO_ERROR;
  78. if ( !bLogOn ) {
  79. return(rc);
  80. }
  81. if ( logname && wcslen(logname) > 3 ) {
  82. hMyLogFile = CreateFile(logname,
  83. GENERIC_WRITE,
  84. FILE_SHARE_READ,
  85. NULL,
  86. OPEN_ALWAYS,
  87. FILE_ATTRIBUTE_NORMAL,
  88. NULL);
  89. if ( INVALID_HANDLE_VALUE != hMyLogFile ) {
  90. DWORD dwBytesWritten;
  91. SetFilePointer (hMyLogFile, 0, NULL, FILE_BEGIN);
  92. CHAR TmpBuf[3];
  93. TmpBuf[0] = (CHAR)0xFF;
  94. TmpBuf[1] = (CHAR)0xFE;
  95. TmpBuf[2] = '\0';
  96. WriteFile (hMyLogFile, (LPCVOID)TmpBuf, 2,
  97. &dwBytesWritten,
  98. NULL);
  99. SetFilePointer (hMyLogFile, 0, NULL, FILE_END);
  100. }
  101. } else {
  102. hMyLogFile = INVALID_HANDLE_VALUE;
  103. }
  104. BOOL bOpenGeneral = FALSE;
  105. if ( INVALID_HANDLE_VALUE == hMyLogFile ) {
  106. //
  107. // use the general server log
  108. //
  109. LPTSTR dName=NULL;
  110. DWORD dirSize=0;
  111. DWORD rc = ScepGetNTDirectory(
  112. &dName,
  113. &dirSize,
  114. SCE_FLAG_WINDOWS_DIR
  115. );
  116. if ( ERROR_SUCCESS == rc && dName ) {
  117. LPTSTR windirName = (LPTSTR)ScepAlloc(0, (dirSize+wcslen(SCESRV_LOG_PATH)+1)*sizeof(TCHAR));
  118. if ( windirName ) {
  119. wcscpy(windirName, dName);
  120. wcscat(windirName, SCESRV_LOG_PATH);
  121. //
  122. // only keep current log transaction. if other threads are holding
  123. // on this log, it won't be deleted. It's ok (will be deleted later).
  124. //
  125. DeleteFile(windirName);
  126. hMyLogFile = CreateFile(windirName,
  127. GENERIC_WRITE,
  128. FILE_SHARE_READ,
  129. NULL,
  130. OPEN_ALWAYS,
  131. FILE_ATTRIBUTE_NORMAL,
  132. NULL);
  133. if ( hMyLogFile != INVALID_HANDLE_VALUE ) {
  134. DWORD dwBytesWritten;
  135. SetFilePointer (hMyLogFile, 0, NULL, FILE_BEGIN);
  136. CHAR TmpBuf[3];
  137. TmpBuf[0] = (CHAR)0xFF;
  138. TmpBuf[1] = (CHAR)0xFE;
  139. TmpBuf[2] = '\0';
  140. WriteFile (hMyLogFile, (LPCVOID)TmpBuf, 2,
  141. &dwBytesWritten,
  142. NULL);
  143. SetFilePointer (hMyLogFile, 0, NULL, FILE_END);
  144. }
  145. ScepFree(windirName);
  146. bOpenGeneral = TRUE;
  147. }
  148. }
  149. if ( dName ) {
  150. ScepFree(dName);
  151. }
  152. }
  153. if ( hMyLogFile == INVALID_HANDLE_VALUE ) {
  154. //
  155. // Open file fails. return error
  156. //
  157. if (logname != NULL)
  158. rc = ERROR_INVALID_NAME;
  159. }
  160. //
  161. // log a separator to the file
  162. //
  163. ScepLogOutput3(0, 0, SCEDLL_SEPARATOR);
  164. if ( bOpenGeneral && logname ) {
  165. //
  166. // the log file provided is not valid, log it
  167. //
  168. ScepLogOutput3(0, 0, IDS_ERROR_OPEN_LOG, logname);
  169. }
  170. //
  171. // Write date/time information to the begining of the log file or to screen
  172. //
  173. TCHAR pvBuffer[100];
  174. pvBuffer[0] = L'\0';
  175. rc = ScepGetTimeStampString(pvBuffer);
  176. if ( pvBuffer[0] != L'\0' )
  177. ScepLogOutput(0, pvBuffer);
  178. return(rc);
  179. }
  180. SCESTATUS
  181. ScepLogOutput2(
  182. IN INT ErrLevel,
  183. IN DWORD rc,
  184. IN PWSTR fmt,
  185. ...
  186. )
  187. /* ++
  188. Routine Description:
  189. This routine adds the information (variable arguments) to the end of the log file or
  190. prints to screen
  191. Arguments:
  192. ErrLevel - the error level of this error (to determine if the error needs to be outputted)
  193. rc - Win32 error code
  194. fmt - the format of the error information
  195. ... - variable argument list
  196. Return value:
  197. SCESTATUS error code
  198. -- */
  199. {
  200. PWSTR buf=NULL;
  201. va_list args;
  202. if ( !ScepCheckLogging(ErrLevel, rc) ) {
  203. //
  204. // no log
  205. //
  206. return(SCESTATUS_SUCCESS);
  207. }
  208. //
  209. // check arguments
  210. //
  211. if ( !fmt )
  212. return(SCESTATUS_SUCCESS);
  213. //
  214. // safely allocate the buffer on stack (or heap)
  215. //
  216. SafeAllocaAllocate( buf, SCE_BUF_LEN*sizeof(WCHAR) );
  217. if ( buf == NULL ) {
  218. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  219. }
  220. va_start( args, fmt );
  221. _vsnwprintf( buf, SCE_BUF_LEN - 1, fmt, args );
  222. va_end( args );
  223. SCESTATUS rCode = ScepLogOutput(rc, buf);
  224. SafeAllocaFree( buf );
  225. return rCode;
  226. }
  227. SCESTATUS
  228. ScepLogOutput(
  229. IN DWORD rc,
  230. IN LPTSTR buf
  231. )
  232. {
  233. if ( !buf ) {
  234. return(SCESTATUS_SUCCESS);
  235. }
  236. LPVOID lpMsgBuf=NULL;
  237. TCHAR strLevel[32];
  238. INT idLevel=0;
  239. if ( rc != NO_ERROR ) {
  240. //
  241. // determine if this is warning, or error
  242. //
  243. if ( rc == ERROR_FILE_NOT_FOUND ||
  244. rc == ERROR_PATH_NOT_FOUND ||
  245. rc == ERROR_ACCESS_DENIED ||
  246. rc == ERROR_CANT_ACCESS_FILE ||
  247. rc == ERROR_SHARING_VIOLATION ||
  248. rc == ERROR_INVALID_OWNER ||
  249. rc == ERROR_INVALID_PRIMARY_GROUP ||
  250. rc == ERROR_INVALID_HANDLE ||
  251. rc == ERROR_INVALID_SECURITY_DESCR ||
  252. rc == ERROR_INVALID_ACL ||
  253. rc == ERROR_SOME_NOT_MAPPED ) {
  254. //
  255. // this is warning
  256. //
  257. idLevel = IDS_WARNING;
  258. } else {
  259. //
  260. // this is error
  261. //
  262. idLevel = IDS_ERROR;
  263. }
  264. strLevel[0] = L'\0';
  265. if ( idLevel > 0 ) {
  266. LoadString( MyModuleHandle,
  267. idLevel,
  268. strLevel,
  269. 31
  270. );
  271. }
  272. //
  273. // get error description of rc
  274. //
  275. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  276. NULL,
  277. rc,
  278. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  279. (LPTSTR)&lpMsgBuf,
  280. 0,
  281. NULL
  282. );
  283. }
  284. if ( hMyLogFile != INVALID_HANDLE_VALUE ) {
  285. //
  286. // The log file is initialized
  287. //
  288. if ( rc != NO_ERROR ) {
  289. if ( lpMsgBuf != NULL )
  290. ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %d: %s %s",
  291. strLevel, rc, (PWSTR)lpMsgBuf, buf );
  292. else
  293. ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %d: %s",
  294. strLevel, rc, buf );
  295. } else {
  296. if ( lpMsgBuf != NULL )
  297. ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %s",
  298. (PWSTR)lpMsgBuf, buf );
  299. else
  300. ScepWriteSingleUnicodeLog( hMyLogFile, TRUE, buf );
  301. }
  302. }
  303. if ( lpMsgBuf != NULL )
  304. LocalFree(lpMsgBuf);
  305. return(SCESTATUS_SUCCESS);
  306. }
  307. BOOL
  308. ScepCheckLogging(
  309. IN INT ErrLevel,
  310. IN DWORD rc
  311. )
  312. {
  313. DWORD dValue;
  314. if ( rc )
  315. gWarningCode = rc;
  316. if ( !bLogOn ) {
  317. return(FALSE);
  318. }
  319. if ( gDebugLevel < 0 ) {
  320. //
  321. // load value from registry
  322. //
  323. if ( ScepRegQueryIntValue(
  324. HKEY_LOCAL_MACHINE,
  325. SCE_ROOT_PATH,
  326. L"DebugLevel",
  327. &dValue
  328. ) == SCESTATUS_SUCCESS )
  329. gDebugLevel = (INT)dValue;
  330. else
  331. gDebugLevel = 1;
  332. }
  333. //
  334. // return if the error level is higher than required
  335. //
  336. if ( ErrLevel > gDebugLevel ) {
  337. return(FALSE);
  338. } else {
  339. return(TRUE);
  340. }
  341. }
  342. SCESTATUS
  343. ScepLogOutput3(
  344. IN INT ErrLevel,
  345. IN DWORD rc,
  346. IN UINT nId,
  347. ...
  348. )
  349. /* ++
  350. Routine Description:
  351. This routine load resource and adds error info (variable arguments)
  352. to the end of the log file or prints to screen
  353. Arguments:
  354. ErrLevel - the error level of this error (to determine if the error needs to be outputted)
  355. rc - Win32 error code
  356. nId - the resource string ID
  357. ... - variable argument list
  358. Return value:
  359. SCESTATUS error code
  360. -- */
  361. {
  362. WCHAR szTempString[256];
  363. PWSTR buf=NULL;
  364. va_list args;
  365. if ( !ScepCheckLogging(ErrLevel, rc) ) {
  366. //
  367. // no log
  368. //
  369. return(SCESTATUS_SUCCESS);
  370. }
  371. if ( nId > 0 ) {
  372. szTempString[0] = L'\0';
  373. LoadString( MyModuleHandle,
  374. nId,
  375. szTempString,
  376. 256
  377. );
  378. //
  379. // safely allocate the buffer on stack (or heap)
  380. //
  381. SafeAllocaAllocate( buf, SCE_BUF_LEN*sizeof(WCHAR) );
  382. if ( buf == NULL ) {
  383. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  384. }
  385. //
  386. // get the arguments
  387. //
  388. va_start( args, nId );
  389. _vsnwprintf( buf, SCE_BUF_LEN - 1, szTempString, args );
  390. va_end( args );
  391. //
  392. // log it and free
  393. //
  394. SCESTATUS rCode = ScepLogOutput(rc, buf);
  395. SafeAllocaFree( buf );
  396. return rCode;
  397. }
  398. return(SCESTATUS_SUCCESS);
  399. }
  400. SCESTATUS
  401. ScepLogWriteError(
  402. IN PSCE_ERROR_LOG_INFO pErrlog,
  403. IN INT ErrLevel
  404. )
  405. /* ++
  406. Routine Description:
  407. This routine outputs the error message in each node of the SCE_ERROR_LOG_INFO
  408. list to the log file
  409. Arguments:
  410. pErrlog - the error list
  411. Return value:
  412. None
  413. -- */
  414. {
  415. PSCE_ERROR_LOG_INFO pErr;
  416. if ( !bLogOn ) {
  417. return(SCESTATUS_SUCCESS);
  418. }
  419. for ( pErr=pErrlog; pErr != NULL; pErr = pErr->next )
  420. if ( pErr->buffer != NULL )
  421. ScepLogOutput2( ErrLevel, pErr->rc, pErr->buffer );
  422. return(SCESTATUS_SUCCESS);
  423. }
  424. SCESTATUS
  425. ScepLogClose()
  426. /* ++
  427. Routine Description:
  428. Close the log file if there is one opened. Clear the log varialbes
  429. Arguments:
  430. None
  431. Return value:
  432. None
  433. --*/
  434. {
  435. if ( !bLogOn ) {
  436. return(SCESTATUS_SUCCESS);
  437. }
  438. if ( hMyLogFile != INVALID_HANDLE_VALUE ) {
  439. CloseHandle( hMyLogFile );
  440. }
  441. //
  442. // Reset the log handle
  443. //
  444. hMyLogFile = INVALID_HANDLE_VALUE;
  445. return(SCESTATUS_SUCCESS);
  446. }