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.

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