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.

545 lines
13 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. #define TRACE_FILE_SIZE MAX_PATH+1
  128. VOID
  129. BrResetTraceLogFile(
  130. VOID
  131. );
  132. CRITICAL_SECTION
  133. BrowserTraceLock = {0};
  134. HANDLE
  135. BrowserTraceLogHandle = NULL;
  136. DWORD
  137. BrTraceLogFileSize = 0;
  138. BOOLEAN BrowserTraceInitialized = {0};
  139. VOID
  140. BrowserTrace(
  141. ULONG DebugFlag,
  142. PCHAR FormatString,
  143. ...
  144. )
  145. #define LAST_NAMED_ARGUMENT FormatString
  146. {
  147. CHAR OutputString[4096];
  148. ULONG length;
  149. ULONG BytesWritten;
  150. static BeginningOfLine = TRUE;
  151. BOOL browserTraceLockHeld = FALSE;
  152. va_list ParmPtr; // Pointer to stack parms.
  153. if ( (BrInfo.BrowserDebug == 0) || (!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. browserTraceLockHeld = TRUE;
  164. length = 0;
  165. try {
  166. if (BrowserTraceLogHandle == NULL) {
  167. //
  168. // We've not opened the trace log file yet, so open it.
  169. //
  170. BrOpenTraceLogFile();
  171. }
  172. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  173. if (browserTraceLockHeld) {
  174. LeaveCriticalSection(&BrowserTraceLock);
  175. browserTraceLockHeld = FALSE;
  176. }
  177. return;
  178. }
  179. //
  180. // Attempt to catch bad trace.
  181. //
  182. for (BytesWritten = 0; BytesWritten < strlen(FormatString) ; BytesWritten += 1) {
  183. if (FormatString[BytesWritten] > 0x7f) {
  184. DbgBreakPoint();
  185. }
  186. }
  187. //
  188. // Handle the beginning of a new line.
  189. //
  190. //
  191. if ( BeginningOfLine ) {
  192. SYSTEMTIME SystemTime;
  193. //
  194. // Put the timestamp at the begining of the line.
  195. //
  196. GetLocalTime( &SystemTime );
  197. length += (ULONG) sprintf( &OutputString[length],
  198. "%02u/%02u %02u:%02u:%02u ",
  199. SystemTime.wMonth,
  200. SystemTime.wDay,
  201. SystemTime.wHour,
  202. SystemTime.wMinute,
  203. SystemTime.wSecond );
  204. //
  205. // Indicate the type of message on the line
  206. //
  207. {
  208. char *Text;
  209. switch (DebugFlag) {
  210. case BR_CRITICAL:
  211. Text = "[CRITICAL]"; break;
  212. case BR_INIT:
  213. Text = "[INIT] "; break;
  214. case BR_SERVER_ENUM:
  215. Text = "[ENUM] "; break;
  216. case BR_UTIL:
  217. Text = "[UTIL] "; break;
  218. case BR_CONFIG:
  219. Text = "[CONFIG] "; break;
  220. case BR_MAIN:
  221. Text = "[MAIN] "; break;
  222. case BR_BACKUP:
  223. Text = "[BACKUP] "; break;
  224. case BR_MASTER:
  225. Text = "[MASTER] "; break;
  226. case BR_DOMAIN:
  227. Text = "[DOMAIN] "; break;
  228. case BR_NETWORK:
  229. Text = "[NETWORK]"; break;
  230. case BR_CLIENT_OP:
  231. Text = "[CLNT OP]"; break;
  232. case BR_TIMER:
  233. Text = "[TIMER]"; break;
  234. case BR_QUEUE:
  235. Text = "[QUEUE]"; break;
  236. case BR_LOCKS:
  237. Text = "[LOCKS]"; break;
  238. default:
  239. Text = "[UNKNOWN]"; break;
  240. }
  241. length += (ULONG) sprintf( &OutputString[length], "%s ", Text );
  242. }
  243. }
  244. //
  245. // Put a the information requested by the caller onto the line
  246. //
  247. va_start(ParmPtr, FormatString);
  248. length += (ULONG) vsprintf(&OutputString[length], FormatString, ParmPtr);
  249. BeginningOfLine = (length > 0 && OutputString[length-1] == '\n' );
  250. if ( BeginningOfLine ) {
  251. OutputString[length-1] = '\r';
  252. OutputString[length] = '\n';
  253. OutputString[length+1] = '\0';
  254. length++;
  255. }
  256. va_end(ParmPtr);
  257. ASSERT(length <= sizeof(OutputString));
  258. //
  259. // Actually write the bytes.
  260. //
  261. if (!WriteFile(BrowserTraceLogHandle, OutputString, length, &BytesWritten, NULL)) {
  262. KdPrint(("Error writing to Browser log file: %ld\n", GetLastError()));
  263. KdPrint(("%s", OutputString));
  264. return;
  265. }
  266. if (BytesWritten != length) {
  267. KdPrint(("Error writing time to Browser log file: %ld\n", GetLastError()));
  268. KdPrint(("%s", OutputString));
  269. return;
  270. }
  271. //
  272. // If the file has grown too large,
  273. // truncate it.
  274. //
  275. BrTraceLogFileSize += BytesWritten;
  276. if (BrTraceLogFileSize > BrInfo.BrowserDebugFileLimit) {
  277. BrResetTraceLogFile();
  278. }
  279. } finally {
  280. if (browserTraceLockHeld) {
  281. LeaveCriticalSection(&BrowserTraceLock);
  282. browserTraceLockHeld = FALSE;
  283. }
  284. }
  285. }
  286. VOID
  287. BrInitializeTraceLog()
  288. {
  289. try {
  290. InitializeCriticalSection(&BrowserTraceLock);
  291. BrowserTraceInitialized = TRUE;
  292. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  293. #if DBG
  294. KdPrint( ("[Browser.dll]: Exception <%lu>. Failed to initialize trace log\n",
  295. _exception_code() ) );
  296. #endif
  297. }
  298. }
  299. VOID
  300. BrGetTraceLogRoot(
  301. IN PWCHAR TraceFile
  302. )
  303. {
  304. PSHARE_INFO_502 ShareInfo;
  305. //
  306. // If the DEBUG share exists, put the log file in that directory,
  307. // otherwise, use the system root.
  308. //
  309. // This way, if the browser is running on an NTAS server, we can always
  310. // get access to the log file.
  311. //
  312. if (NetShareGetInfo(NULL, L"DEBUG", 502, (PCHAR *)&ShareInfo) != NERR_Success) {
  313. if (GetSystemDirectory(TraceFile, TRACE_FILE_SIZE) == 0) {
  314. KdPrint(("Unable to get system directory: %ld\n", GetLastError()));
  315. }
  316. if (TraceFile[wcslen(TraceFile)] != L'\\') {
  317. TraceFile[wcslen(TraceFile)+1] = L'\0';
  318. TraceFile[wcslen(TraceFile)] = L'\\';
  319. }
  320. } else {
  321. //
  322. // Seed the trace file buffer with the local path of the netlogon
  323. // share if it exists.
  324. //
  325. wcscpy(TraceFile, ShareInfo->shi502_path);
  326. TraceFile[wcslen(ShareInfo->shi502_path)] = L'\\';
  327. TraceFile[wcslen(ShareInfo->shi502_path)+1] = L'\0';
  328. NetApiBufferFree(ShareInfo);
  329. }
  330. }
  331. VOID
  332. BrResetTraceLogFile(
  333. VOID
  334. )
  335. {
  336. WCHAR OldTraceFile[TRACE_FILE_SIZE];
  337. WCHAR NewTraceFile[TRACE_FILE_SIZE];
  338. if (BrowserTraceLogHandle != NULL) {
  339. CloseHandle(BrowserTraceLogHandle);
  340. }
  341. BrowserTraceLogHandle = NULL;
  342. BrGetTraceLogRoot(OldTraceFile);
  343. wcscpy(NewTraceFile, OldTraceFile);
  344. wcscat(OldTraceFile, L"Browser.Log");
  345. wcscat(NewTraceFile, L"Browser.Bak");
  346. //
  347. // Delete the old log
  348. //
  349. DeleteFile(NewTraceFile);
  350. //
  351. // Rename the current log to the new log.
  352. //
  353. MoveFile(OldTraceFile, NewTraceFile);
  354. BrOpenTraceLogFile();
  355. }
  356. VOID
  357. BrOpenTraceLogFile(
  358. VOID
  359. )
  360. {
  361. WCHAR TraceFile[TRACE_FILE_SIZE];
  362. BrGetTraceLogRoot(TraceFile);
  363. wcscat(TraceFile, L"Browser.Log");
  364. BrowserTraceLogHandle = CreateFile(TraceFile,
  365. GENERIC_WRITE,
  366. FILE_SHARE_READ,
  367. NULL,
  368. OPEN_ALWAYS,
  369. FILE_ATTRIBUTE_NORMAL,
  370. NULL);
  371. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  372. KdPrint(("Error creating trace file %ws: %ld\n", TraceFile, GetLastError()));
  373. return;
  374. }
  375. BrTraceLogFileSize = SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_END);
  376. if (BrTraceLogFileSize == 0xffffffff) {
  377. KdPrint(("Error setting trace file pointer: %ld\n", GetLastError()));
  378. return;
  379. }
  380. }
  381. VOID
  382. BrUninitializeTraceLog()
  383. {
  384. if (!BrowserTraceInitialized) {
  385. return;
  386. }
  387. DeleteCriticalSection(&BrowserTraceLock);
  388. if (BrowserTraceLogHandle != NULL) {
  389. CloseHandle(BrowserTraceLogHandle);
  390. }
  391. BrowserTraceLogHandle = NULL;
  392. BrowserTraceInitialized = FALSE;
  393. }
  394. NET_API_STATUS
  395. BrTruncateLog()
  396. {
  397. if (BrowserTraceLogHandle == NULL) {
  398. BrOpenTraceLogFile();
  399. }
  400. if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
  401. return ERROR_GEN_FAILURE;
  402. }
  403. if (SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_BEGIN) == 0xffffffff) {
  404. return GetLastError();
  405. }
  406. if (!SetEndOfFile(BrowserTraceLogHandle)) {
  407. return GetLastError();
  408. }
  409. return NO_ERROR;
  410. }