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.

533 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. brutil.c
  5. Abstract:
  6. This module contains miscellaneous utility routines used by the
  7. Browser service.
  8. Author:
  9. Rita Wong (ritaw) 01-Mar-1991
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //-------------------------------------------------------------------//
  15. // //
  16. // Local function prototypes //
  17. // //
  18. //-------------------------------------------------------------------//
  19. //-------------------------------------------------------------------//
  20. // //
  21. // Global variables //
  22. // //
  23. //-------------------------------------------------------------------//
  24. NET_API_STATUS
  25. BrMapStatus(
  26. IN NTSTATUS NtStatus
  27. )
  28. /*++
  29. Routine Description:
  30. This function takes an NT status code and maps it to the appropriate
  31. error code expected from calling a LAN Man API.
  32. Arguments:
  33. NtStatus - Supplies the NT status.
  34. Return Value:
  35. Returns the appropriate LAN Man error code for the NT status.
  36. --*/
  37. {
  38. //
  39. // A small optimization for the most common case.
  40. //
  41. if (NT_SUCCESS(NtStatus)) {
  42. return NERR_Success;
  43. }
  44. switch (NtStatus) {
  45. case STATUS_OBJECT_NAME_COLLISION:
  46. return ERROR_ALREADY_ASSIGNED;
  47. case STATUS_OBJECT_NAME_NOT_FOUND:
  48. return NERR_UseNotFound;
  49. case STATUS_REDIRECTOR_STARTED:
  50. return NERR_ServiceInstalled;
  51. default:
  52. return NetpNtStatusToApiStatus(NtStatus);
  53. }
  54. }
  55. ULONG
  56. BrCurrentSystemTime()
  57. {
  58. NTSTATUS Status;
  59. SYSTEM_TIMEOFDAY_INFORMATION TODInformation;
  60. LARGE_INTEGER CurrentTime;
  61. ULONG TimeInSecondsSince1980 = 0; // happy prefix 112576
  62. ULONG BootTimeInSecondsSince1980 = 0; // ""
  63. Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
  64. &TODInformation,
  65. sizeof(TODInformation),
  66. NULL);
  67. if (!NT_SUCCESS(Status)) {
  68. return(0);
  69. }
  70. Status = NtQuerySystemTime(&CurrentTime);
  71. if (!NT_SUCCESS(Status)) {
  72. return(0);
  73. }
  74. RtlTimeToSecondsSince1980(&CurrentTime, &TimeInSecondsSince1980);
  75. RtlTimeToSecondsSince1980(&TODInformation.BootTime, &BootTimeInSecondsSince1980);
  76. return(TimeInSecondsSince1980 - BootTimeInSecondsSince1980);
  77. }
  78. VOID
  79. BrLogEvent(
  80. IN ULONG MessageId,
  81. IN ULONG ErrorCode,
  82. IN ULONG NumberOfSubStrings,
  83. IN LPWSTR *SubStrings
  84. )
  85. {
  86. DWORD Severity;
  87. WORD Type;
  88. PVOID RawData;
  89. ULONG RawDataSize;
  90. //
  91. // Log the error code specified
  92. //
  93. Severity = (MessageId & 0xc0000000) >> 30;
  94. if (Severity == STATUS_SEVERITY_WARNING) {
  95. Type = EVENTLOG_WARNING_TYPE;
  96. } else if (Severity == STATUS_SEVERITY_SUCCESS) {
  97. Type = EVENTLOG_SUCCESS;
  98. } else if (Severity == STATUS_SEVERITY_INFORMATIONAL) {
  99. Type = EVENTLOG_INFORMATION_TYPE;
  100. } else if (Severity == STATUS_SEVERITY_ERROR) {
  101. Type = EVENTLOG_ERROR_TYPE;
  102. } else {
  103. // prefix uninit var consistency.
  104. ASSERT(!"Unknown event log type!!");
  105. return;
  106. }
  107. if (ErrorCode == NERR_Success) {
  108. RawData = NULL;
  109. RawDataSize = 0;
  110. } else {
  111. RawData = &ErrorCode;
  112. RawDataSize = sizeof(DWORD);
  113. }
  114. //
  115. // Use netlogon's routine to write eventlog messages.
  116. // (It ditches duplicate events.)
  117. //
  118. NetpEventlogWrite (
  119. BrGlobalEventlogHandle,
  120. MessageId,
  121. Type,
  122. RawData,
  123. RawDataSize,
  124. SubStrings,
  125. NumberOfSubStrings );
  126. }
  127. #if DBG
  128. #define TRACE_FILE_SIZE 256
  129. VOID
  130. BrResetTraceLogFile(
  131. VOID
  132. );
  133. CRITICAL_SECTION
  134. BrowserTraceLock = {0};
  135. HANDLE
  136. BrowserTraceLogHandle = NULL;
  137. DWORD
  138. BrTraceLogFileSize = 0;
  139. BOOLEAN BrowserTraceInitialized = {0};
  140. VOID
  141. BrowserTrace(
  142. ULONG DebugFlag,
  143. PCHAR FormatString,
  144. ...
  145. )
  146. #define LAST_NAMED_ARGUMENT FormatString
  147. {
  148. CHAR OutputString[4096];
  149. ULONG length;
  150. ULONG BytesWritten;
  151. static BeginningOfLine = TRUE;
  152. va_list ParmPtr; // Pointer to stack parms.
  153. if (!BrowserTraceInitialized) {
  154. return;
  155. }
  156. //
  157. // If we aren't debugging this functionality, just return.
  158. //
  159. if ( DebugFlag != 0 && (BrInfo.BrowserDebug & DebugFlag) == 0 ) {
  160. return;
  161. }
  162. EnterCriticalSection(&BrowserTraceLock);
  163. length = 0;
  164. try {
  165. if (BrowserTraceLogHandle == NULL) {
  166. //
  167. // We've not opened the trace log file yet, so open it.
  168. //
  169. BrOpenTraceLogFile();
  170. }
  171. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  172. LeaveCriticalSection(&BrowserTraceLock);
  173. return;
  174. }
  175. //
  176. // Attempt to catch bad trace.
  177. //
  178. for (BytesWritten = 0; BytesWritten < strlen(FormatString) ; BytesWritten += 1) {
  179. if (FormatString[BytesWritten] > 0x7f) {
  180. DbgBreakPoint();
  181. }
  182. }
  183. //
  184. // Handle the beginning of a new line.
  185. //
  186. //
  187. if ( BeginningOfLine ) {
  188. SYSTEMTIME SystemTime;
  189. //
  190. // Put the timestamp at the begining of the line.
  191. //
  192. GetLocalTime( &SystemTime );
  193. length += (ULONG) sprintf( &OutputString[length],
  194. "%02u/%02u %02u:%02u:%02u ",
  195. SystemTime.wMonth,
  196. SystemTime.wDay,
  197. SystemTime.wHour,
  198. SystemTime.wMinute,
  199. SystemTime.wSecond );
  200. //
  201. // Indicate the type of message on the line
  202. //
  203. {
  204. char *Text;
  205. switch (DebugFlag) {
  206. case BR_CRITICAL:
  207. Text = "[CRITICAL]"; break;
  208. case BR_INIT:
  209. Text = "[INIT] "; break;
  210. case BR_SERVER_ENUM:
  211. Text = "[ENUM] "; break;
  212. case BR_UTIL:
  213. Text = "[UTIL] "; break;
  214. case BR_CONFIG:
  215. Text = "[CONFIG] "; break;
  216. case BR_MAIN:
  217. Text = "[MAIN] "; break;
  218. case BR_BACKUP:
  219. Text = "[BACKUP] "; break;
  220. case BR_MASTER:
  221. Text = "[MASTER] "; break;
  222. case BR_DOMAIN:
  223. Text = "[DOMAIN] "; break;
  224. case BR_NETWORK:
  225. Text = "[NETWORK]"; break;
  226. case BR_TIMER:
  227. Text = "[TIMER]"; break;
  228. case BR_QUEUE:
  229. Text = "[QUEUE]"; break;
  230. case BR_LOCKS:
  231. Text = "[LOCKS]"; break;
  232. default:
  233. Text = "[UNKNOWN]"; break;
  234. }
  235. length += (ULONG) sprintf( &OutputString[length], "%s ", Text );
  236. }
  237. }
  238. //
  239. // Put a the information requested by the caller onto the line
  240. //
  241. va_start(ParmPtr, FormatString);
  242. length += (ULONG) vsprintf(&OutputString[length], FormatString, ParmPtr);
  243. BeginningOfLine = (length > 0 && OutputString[length-1] == '\n' );
  244. if ( BeginningOfLine ) {
  245. OutputString[length-1] = '\r';
  246. OutputString[length] = '\n';
  247. OutputString[length+1] = '\0';
  248. length++;
  249. }
  250. va_end(ParmPtr);
  251. ASSERT(length <= sizeof(OutputString));
  252. //
  253. // Actually write the bytes.
  254. //
  255. if (!WriteFile(BrowserTraceLogHandle, OutputString, length, &BytesWritten, NULL)) {
  256. KdPrint(("Error writing to Browser log file: %ld\n", GetLastError()));
  257. KdPrint(("%s", OutputString));
  258. return;
  259. }
  260. if (BytesWritten != length) {
  261. KdPrint(("Error writing time to Browser log file: %ld\n", GetLastError()));
  262. KdPrint(("%s", OutputString));
  263. return;
  264. }
  265. //
  266. // If the file has grown too large,
  267. // truncate it.
  268. //
  269. BrTraceLogFileSize += BytesWritten;
  270. if (BrTraceLogFileSize > BrInfo.BrowserDebugFileLimit) {
  271. BrResetTraceLogFile();
  272. }
  273. } finally {
  274. LeaveCriticalSection(&BrowserTraceLock);
  275. }
  276. }
  277. VOID
  278. BrInitializeTraceLog()
  279. {
  280. try {
  281. InitializeCriticalSection(&BrowserTraceLock);
  282. BrowserTraceInitialized = TRUE;
  283. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  284. #if DBG
  285. KdPrint( ("[Browser.dll]: Exception <%lu>. Failed to initialize trace log\n",
  286. _exception_code() ) );
  287. #endif
  288. }
  289. }
  290. VOID
  291. BrGetTraceLogRoot(
  292. IN PWCHAR TraceFile
  293. )
  294. {
  295. PSHARE_INFO_502 ShareInfo;
  296. //
  297. // If the DEBUG share exists, put the log file in that directory,
  298. // otherwise, use the system root.
  299. //
  300. // This way, if the browser is running on an NTAS server, we can always
  301. // get access to the log file.
  302. //
  303. if (NetShareGetInfo(NULL, L"DEBUG", 502, (PCHAR *)&ShareInfo) != NERR_Success) {
  304. if (GetSystemDirectory(TraceFile, TRACE_FILE_SIZE*sizeof(WCHAR)) == 0) {
  305. KdPrint(("Unable to get system directory: %ld\n", GetLastError()));
  306. }
  307. if (TraceFile[wcslen(TraceFile)] != L'\\') {
  308. TraceFile[wcslen(TraceFile)+1] = L'\0';
  309. TraceFile[wcslen(TraceFile)] = L'\\';
  310. }
  311. } else {
  312. //
  313. // Seed the trace file buffer with the local path of the netlogon
  314. // share if it exists.
  315. //
  316. wcscpy(TraceFile, ShareInfo->shi502_path);
  317. TraceFile[wcslen(ShareInfo->shi502_path)] = L'\\';
  318. TraceFile[wcslen(ShareInfo->shi502_path)+1] = L'\0';
  319. NetApiBufferFree(ShareInfo);
  320. }
  321. }
  322. VOID
  323. BrResetTraceLogFile(
  324. VOID
  325. )
  326. {
  327. WCHAR OldTraceFile[TRACE_FILE_SIZE];
  328. WCHAR NewTraceFile[TRACE_FILE_SIZE];
  329. if (BrowserTraceLogHandle != NULL) {
  330. CloseHandle(BrowserTraceLogHandle);
  331. }
  332. BrowserTraceLogHandle = NULL;
  333. BrGetTraceLogRoot(OldTraceFile);
  334. wcscpy(NewTraceFile, OldTraceFile);
  335. wcscat(OldTraceFile, L"Browser.Log");
  336. wcscat(NewTraceFile, L"Browser.Bak");
  337. //
  338. // Delete the old log
  339. //
  340. DeleteFile(NewTraceFile);
  341. //
  342. // Rename the current log to the new log.
  343. //
  344. MoveFile(OldTraceFile, NewTraceFile);
  345. BrOpenTraceLogFile();
  346. }
  347. VOID
  348. BrOpenTraceLogFile(
  349. VOID
  350. )
  351. {
  352. WCHAR TraceFile[TRACE_FILE_SIZE];
  353. BrGetTraceLogRoot(TraceFile);
  354. wcscat(TraceFile, L"Browser.Log");
  355. BrowserTraceLogHandle = CreateFile(TraceFile,
  356. GENERIC_WRITE,
  357. FILE_SHARE_READ,
  358. NULL,
  359. OPEN_ALWAYS,
  360. FILE_ATTRIBUTE_NORMAL,
  361. NULL);
  362. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  363. KdPrint(("Error creating trace file %ws: %ld\n", TraceFile, GetLastError()));
  364. return;
  365. }
  366. BrTraceLogFileSize = SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_END);
  367. if (BrTraceLogFileSize == 0xffffffff) {
  368. KdPrint(("Error setting trace file pointer: %ld\n", GetLastError()));
  369. return;
  370. }
  371. }
  372. VOID
  373. BrUninitializeTraceLog()
  374. {
  375. DeleteCriticalSection(&BrowserTraceLock);
  376. if (BrowserTraceLogHandle != NULL) {
  377. CloseHandle(BrowserTraceLogHandle);
  378. }
  379. BrowserTraceLogHandle = NULL;
  380. BrowserTraceInitialized = FALSE;
  381. }
  382. NET_API_STATUS
  383. BrTruncateLog()
  384. {
  385. if (BrowserTraceLogHandle == NULL) {
  386. BrOpenTraceLogFile();
  387. }
  388. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  389. return ERROR_GEN_FAILURE;
  390. }
  391. if (SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_BEGIN) == 0xffffffff) {
  392. return GetLastError();
  393. }
  394. if (!SetEndOfFile(BrowserTraceLogHandle)) {
  395. return GetLastError();
  396. }
  397. return NO_ERROR;
  398. }
  399. #endif