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.

1175 lines
23 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. util.cxx
  5. Abstract:
  6. Utility routines
  7. Author:
  8. Cliff Van Dyke (cliffv) 11-Apr-2001
  9. --*/
  10. #include "pch.hxx"
  11. #if DBG
  12. //
  13. // List of all allocated blocks
  14. // AccessSerialized by AzGlAllocatorCritSect
  15. LIST_ENTRY AzGlAllocatedBlocks;
  16. CRITICAL_SECTION AzGlAllocatorCritSect;
  17. #endif // DBG
  18. PVOID
  19. AzpAllocateHeap(
  20. IN SIZE_T Size
  21. )
  22. /*++
  23. Routine Description
  24. Memory allocator
  25. Arguments
  26. Size - Size (in bytes) to allocate
  27. Return Value
  28. Returns a pointer to the allocated memory.
  29. NULL - Not enough memory
  30. --*/
  31. {
  32. #if DBG
  33. ULONG HeaderSize = ROUND_UP_COUNT( sizeof(LIST_ENTRY), ALIGN_WORST );
  34. PLIST_ENTRY RealBlock;
  35. //
  36. // Allocate a block with a header
  37. //
  38. RealBlock = (PLIST_ENTRY) LocalAlloc( 0, HeaderSize + Size );
  39. if ( RealBlock == NULL ) {
  40. return NULL;
  41. }
  42. //
  43. // Link the block since we're nosey.
  44. //
  45. EnterCriticalSection( &AzGlAllocatorCritSect );
  46. InsertHeadList( &AzGlAllocatedBlocks, RealBlock );
  47. LeaveCriticalSection( &AzGlAllocatorCritSect );
  48. return (PVOID)(((LPBYTE)RealBlock)+HeaderSize);
  49. #else // DBG
  50. return LocalAlloc( 0, Size );
  51. #endif // DBG
  52. }
  53. VOID
  54. AzpFreeHeap(
  55. IN PVOID Buffer
  56. )
  57. /*++
  58. Routine Description
  59. Memory de-allocator
  60. Arguments
  61. Buffer - address of buffer to free
  62. Return Value
  63. None
  64. --*/
  65. {
  66. #if DBG
  67. ULONG HeaderSize = ROUND_UP_COUNT( sizeof(LIST_ENTRY), ALIGN_WORST );
  68. PLIST_ENTRY RealBlock;
  69. RealBlock = (PLIST_ENTRY)(((LPBYTE)Buffer)-HeaderSize);
  70. EnterCriticalSection( &AzGlAllocatorCritSect );
  71. RemoveEntryList( RealBlock );
  72. LeaveCriticalSection( &AzGlAllocatorCritSect );
  73. LocalFree( RealBlock );
  74. #else // DBG
  75. LocalFree( Buffer );
  76. #endif // DBG
  77. }
  78. VOID
  79. AzpInitString(
  80. OUT PAZP_STRING AzpString,
  81. IN LPWSTR String OPTIONAL
  82. )
  83. /*++
  84. Routine Description
  85. Initialize our private string structure to point to a passed in string.
  86. Arguments
  87. AzpString - Initialized string
  88. String - zero terminated string to be reference
  89. If NULL, AzpString will be initialized to empty.
  90. Return Value
  91. None
  92. --*/
  93. {
  94. //
  95. // Initialization
  96. //
  97. if ( String == NULL ) {
  98. AzpString->String = NULL;
  99. AzpString->StringSize = 0;
  100. } else {
  101. AzpString->String = String;
  102. AzpString->StringSize = (ULONG) ((wcslen(String)+1)*sizeof(WCHAR));
  103. }
  104. }
  105. DWORD
  106. AzpCaptureString(
  107. OUT PAZP_STRING AzpString,
  108. IN LPCWSTR String,
  109. IN ULONG MaximumLength,
  110. IN BOOLEAN NullOk
  111. )
  112. /*++
  113. Routine Description
  114. Capture the passed in string.
  115. Arguments
  116. AzpString - Captured copy of the passed in string.
  117. On success, string must be freed using AzpFreeString
  118. String - zero terminated string to capture
  119. MaximumLength - Maximum length of the string (in characters).
  120. NullOk - if TRUE, a NULL string or zero length string is OK.
  121. Return Value
  122. NO_ERROR - The operation was successful
  123. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  124. Other exception status codes
  125. --*/
  126. {
  127. ULONG WinStatus;
  128. ULONG StringSize;
  129. //
  130. // Initialization
  131. //
  132. AzpInitString( AzpString, NULL );
  133. if ( String == NULL ) {
  134. if ( !NullOk ) {
  135. AzPrint(( AZD_INVPARM, "AzpCaptureString: NULL not ok\n" ));
  136. return ERROR_INVALID_PARAMETER;
  137. }
  138. return NO_ERROR;
  139. }
  140. __try {
  141. //
  142. // Validate a passed in LPWSTR
  143. //
  144. ULONG StringLength;
  145. StringLength = (ULONG) wcslen( String );
  146. if ( StringLength == 0 ) {
  147. if ( !NullOk ) {
  148. AzPrint(( AZD_INVPARM, "AzpCaptureString: zero length not ok\n" ));
  149. return ERROR_INVALID_PARAMETER;
  150. }
  151. return NO_ERROR;
  152. }
  153. if ( StringLength > MaximumLength ) {
  154. AzPrint(( AZD_INVPARM, "AzpCaptureString: string too long %ld %ld %ws\n", StringLength, MaximumLength, String ));
  155. return ERROR_INVALID_PARAMETER;
  156. }
  157. StringSize = (StringLength+1)*sizeof(WCHAR);
  158. //
  159. // Allocate and copy the string
  160. //
  161. AzpString->String = (LPWSTR) AzpAllocateHeap( StringSize );
  162. if ( AzpString->String == NULL ) {
  163. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  164. } else {
  165. RtlCopyMemory( AzpString->String,
  166. String,
  167. StringSize );
  168. AzpString->StringSize = StringSize;
  169. WinStatus = NO_ERROR;
  170. }
  171. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  172. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  173. AzpFreeString( AzpString );
  174. }
  175. return WinStatus;
  176. }
  177. DWORD
  178. AzpCaptureSid(
  179. OUT PAZP_STRING AzpString,
  180. IN PSID Sid
  181. )
  182. /*++
  183. Routine Description
  184. Capture the passed in SID
  185. Arguments
  186. AzpString - Captured copy of the passed in sid.
  187. On success, string must be freed using AzpFreeString
  188. Sid - Sid to capture
  189. Return Value
  190. NO_ERROR - The operation was successful
  191. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  192. Other exception status codes
  193. --*/
  194. {
  195. ULONG WinStatus;
  196. ULONG StringSize;
  197. //
  198. // Initialization
  199. //
  200. AzpInitString( AzpString, NULL );
  201. __try {
  202. //
  203. // Validate a passed in SID
  204. //
  205. if ( !RtlValidSid( Sid ) ) {
  206. AzPrint(( AZD_INVPARM, "AzpCaptureString: SID not valid\n" ));
  207. return ERROR_INVALID_PARAMETER;
  208. }
  209. StringSize = RtlLengthSid( Sid );
  210. //
  211. // Allocate and copy the SID
  212. //
  213. AzpString->String = (LPWSTR) AzpAllocateHeap( StringSize );
  214. if ( AzpString->String == NULL ) {
  215. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  216. } else {
  217. RtlCopyMemory( AzpString->String,
  218. Sid,
  219. StringSize );
  220. AzpString->StringSize = StringSize;
  221. WinStatus = NO_ERROR;
  222. }
  223. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  224. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  225. AzpFreeString( AzpString );
  226. }
  227. return WinStatus;
  228. }
  229. DWORD
  230. AzpCaptureUlong(
  231. IN PVOID PropertyValue,
  232. OUT PULONG UlongValue
  233. )
  234. /*++
  235. Routine Description
  236. Support routine for the SetProperty API.
  237. Capture a parameter for the user application.
  238. Arguments
  239. PropertyValue - Specifies a pointer to the property.
  240. UlongValue - Value to return to make a copy of.
  241. Return Value
  242. NO_ERROR - The operation was successful
  243. Other exception status codes
  244. --*/
  245. {
  246. DWORD WinStatus;
  247. __try {
  248. *UlongValue = *(PULONG)PropertyValue;
  249. WinStatus = NO_ERROR;
  250. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  251. WinStatus = RtlNtStatusToDosError( GetExceptionCode());
  252. }
  253. return WinStatus;
  254. }
  255. DWORD
  256. AzpDuplicateString(
  257. OUT PAZP_STRING AzpOutString,
  258. IN PAZP_STRING AzpInString
  259. )
  260. /*++
  261. Routine Description
  262. Make a duplicate of the passed in string
  263. Arguments
  264. AzpOutString - Returns a copy of the passed in string.
  265. On success, string must be freed using AzpFreeString.
  266. AzpInString - Specifies a string to make a copy of.
  267. Return Value
  268. NO_ERROR - The operation was successful
  269. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  270. --*/
  271. {
  272. ULONG WinStatus;
  273. //
  274. // Initialization
  275. //
  276. AzpInitString( AzpOutString, NULL );
  277. //
  278. // Handle an empty string
  279. //
  280. if ( AzpInString->StringSize == 0 || AzpInString->String == NULL ) {
  281. WinStatus = NO_ERROR;
  282. //
  283. // Allocate and copy the string
  284. //
  285. } else {
  286. AzpOutString->String = (LPWSTR) AzpAllocateHeap( AzpInString->StringSize );
  287. if ( AzpOutString->String == NULL ) {
  288. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  289. } else {
  290. RtlCopyMemory( AzpOutString->String,
  291. AzpInString->String,
  292. AzpInString->StringSize );
  293. AzpOutString->StringSize = AzpInString->StringSize;
  294. WinStatus = NO_ERROR;
  295. }
  296. }
  297. return WinStatus;
  298. }
  299. BOOL
  300. AzpEqualStrings(
  301. IN PAZP_STRING AzpString1,
  302. IN PAZP_STRING AzpString2
  303. )
  304. /*++
  305. Routine Description
  306. Does a case insensitive comparison of two strings
  307. Arguments
  308. AzpString1 - First string to compare
  309. AzpString2 - Second string to compare
  310. Return Value
  311. TRUE: the strings are equal
  312. FALSE: the strings are not equal
  313. --*/
  314. {
  315. //
  316. // Simply compare the strings
  317. //
  318. return (AzpCompareStrings( AzpString1, AzpString2 ) == CSTR_EQUAL);
  319. }
  320. LONG
  321. AzpCompareStrings(
  322. IN PAZP_STRING AzpString1,
  323. IN PAZP_STRING AzpString2
  324. )
  325. /*++
  326. Routine Description
  327. Does a case insensitive comparison of two strings
  328. Arguments
  329. AzpString1 - First string to compare
  330. AzpString2 - Second string to compare
  331. Return Value
  332. 0: An error ocurred. Call GetLastError();
  333. CSTR_LESS_THAN: String 1 is less than string 2
  334. CSTR_EQUAL: String 1 is equal to string 2
  335. CSTR_GREATER_THAN: String 1 is greater than string 2
  336. --*/
  337. {
  338. //
  339. // Handle NULL
  340. //
  341. if ( AzpString1->String == NULL ) {
  342. if ( AzpString2->String == NULL ) {
  343. return CSTR_EQUAL;
  344. }else {
  345. return CSTR_LESS_THAN;
  346. }
  347. } else {
  348. if ( AzpString2->String == NULL ) {
  349. return CSTR_GREATER_THAN;
  350. }
  351. }
  352. //
  353. // Compare the Unicode strings
  354. // Don't compare the trailing zero character.
  355. // (Some callers pass in strings where the trailing character isn't a zero.)
  356. //
  357. return CompareStringW( LOCALE_SYSTEM_DEFAULT,
  358. NORM_IGNORECASE,
  359. AzpString1->String,
  360. (AzpString1->StringSize/sizeof(WCHAR))-1,
  361. AzpString2->String,
  362. (AzpString2->StringSize/sizeof(WCHAR))-1 );
  363. }
  364. VOID
  365. AzpSwapStrings(
  366. IN OUT PAZP_STRING AzpString1,
  367. IN OUT PAZP_STRING AzpString2
  368. )
  369. /*++
  370. Routine Description
  371. Swap two strings
  372. Arguments
  373. AzpString1 - First string to swap
  374. AzpString2 - Second string to swap
  375. Return Value
  376. None
  377. --*/
  378. {
  379. AZP_STRING TempString;
  380. TempString = *AzpString1;
  381. *AzpString1 = *AzpString2;
  382. *AzpString2 = TempString;
  383. }
  384. VOID
  385. AzpFreeString(
  386. IN PAZP_STRING AzpString
  387. )
  388. /*++
  389. Routine Description
  390. Free the specified string
  391. Arguments
  392. AzpString - String to be freed.
  393. Return Value
  394. None
  395. --*/
  396. {
  397. if ( AzpString->String != NULL ) {
  398. AzpFreeHeap( AzpString->String );
  399. }
  400. AzpInitString( AzpString, NULL );
  401. }
  402. DWORD
  403. AzpAddPtr(
  404. IN PAZP_PTR_ARRAY AzpPtrArray,
  405. IN PVOID Pointer,
  406. IN ULONG Index
  407. )
  408. /*++
  409. Routine Description
  410. Inserts a pointer into the array of pointers.
  411. The array will be automatically expanded to be large enough to contain the new pointer.
  412. All existing pointers from slot # 'Index' through the end of the existing array will
  413. be shifted to later slots.
  414. Arguments
  415. AzpPtrArray - Array that the pointer will be inserted into.
  416. Pointer - Pointer to be inserted.
  417. Index - Index into the array where the 'Pointer' will be inserted
  418. If Index is larger than the current size of the array or AZP_ADD_ENDOFLIST,
  419. 'Pointer' will be inserted after the existing elements of the array.
  420. Return Value
  421. NO_ERROR - The operation was successful
  422. ERROR_NOT_ENOUGH_MEMORY - not enough memory
  423. --*/
  424. {
  425. //
  426. // Ensure Index isn't too large
  427. //
  428. if ( Index > AzpPtrArray->UsedCount ) {
  429. Index = AzpPtrArray->UsedCount;
  430. }
  431. //
  432. // If the array isn't large enough, make it bigger
  433. //
  434. if ( AzpPtrArray->UsedCount >= AzpPtrArray->AllocatedCount ) {
  435. PVOID *TempArray;
  436. //
  437. // Allocate a new array
  438. //
  439. TempArray = (PVOID *) AzpAllocateHeap(
  440. (AzpPtrArray->AllocatedCount + AZP_PTR_ARRAY_INCREMENT) * sizeof(PVOID) );
  441. if ( TempArray == NULL ) {
  442. return ERROR_NOT_ENOUGH_MEMORY;
  443. }
  444. //
  445. // Copy the data into the new array and free the old array
  446. //
  447. if ( AzpPtrArray->Array != NULL ) {
  448. RtlCopyMemory( TempArray,
  449. AzpPtrArray->Array,
  450. AzpPtrArray->AllocatedCount * sizeof(PVOID) );
  451. AzpFreeHeap( AzpPtrArray->Array );
  452. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Free old array\n", AzpPtrArray, AzpPtrArray->Array ));
  453. }
  454. //
  455. // Grab the pointer to the new array and clear the new part of the array
  456. //
  457. AzpPtrArray->Array = TempArray;
  458. AzPrint(( AZD_OBJLIST, "0x%lx: 0x%lx: Allocate array\n", AzpPtrArray, AzpPtrArray->Array ));
  459. RtlZeroMemory( &TempArray[AzpPtrArray->UsedCount],
  460. AZP_PTR_ARRAY_INCREMENT * sizeof(PVOID) );
  461. AzpPtrArray->AllocatedCount += AZP_PTR_ARRAY_INCREMENT;
  462. }
  463. //
  464. // Shift any old data
  465. //
  466. if ( Index != AzpPtrArray->UsedCount ) {
  467. RtlMoveMemory( &(AzpPtrArray->Array[Index+1]),
  468. &(AzpPtrArray->Array[Index]),
  469. (AzpPtrArray->UsedCount-Index) * sizeof(PVOID) );
  470. }
  471. //
  472. // Insert the new element
  473. //
  474. AzpPtrArray->Array[Index] = Pointer;
  475. AzpPtrArray->UsedCount ++;
  476. return NO_ERROR;
  477. }
  478. VOID
  479. AzpRemovePtrByIndex(
  480. IN PAZP_PTR_ARRAY AzpPtrArray,
  481. IN ULONG Index
  482. )
  483. /*++
  484. Routine Description
  485. Remove a pointer from the array of pointers.
  486. All existing pointers from slot # 'Index' through the end of the existing array will
  487. be shifted to earlier slots.
  488. Arguments
  489. AzpPtrArray - Array that the pointer will be removed into.
  490. Index - Index into the array where the 'Pointer' will be removed from.
  491. Return Value
  492. None
  493. --*/
  494. {
  495. //
  496. // Ensure Index isn't too large
  497. //
  498. ASSERT( Index < AzpPtrArray->UsedCount );
  499. //
  500. // Shift any old data
  501. //
  502. if ( Index+1 != AzpPtrArray->UsedCount ) {
  503. RtlMoveMemory( &(AzpPtrArray->Array[Index]),
  504. &(AzpPtrArray->Array[Index+1]),
  505. (AzpPtrArray->UsedCount-Index-1) * sizeof(PVOID) );
  506. }
  507. //
  508. // Clear the last element
  509. //
  510. AzpPtrArray->UsedCount--;
  511. AzpPtrArray->Array[AzpPtrArray->UsedCount] = NULL;
  512. }
  513. VOID
  514. AzpRemovePtrByPtr(
  515. IN PAZP_PTR_ARRAY AzpPtrArray,
  516. IN PVOID Pointer
  517. )
  518. /*++
  519. Routine Description
  520. Removed a pointer from the array of pointers.
  521. All existing pointers following the specified pointer will
  522. be shifted to earlier slots.
  523. Arguments
  524. AzpPtrArray - Array that the pointer will be removed into.
  525. Pointer - Pointer to be removed
  526. Return Value
  527. None
  528. --*/
  529. {
  530. ULONG i;
  531. BOOLEAN FoundIt = FALSE;
  532. for ( i=0; i<AzpPtrArray->UsedCount; i++ ) {
  533. if ( Pointer == AzpPtrArray->Array[i] ) {
  534. AzpRemovePtrByIndex( AzpPtrArray, i );
  535. FoundIt = TRUE;
  536. break;
  537. }
  538. }
  539. ASSERT( FoundIt );
  540. }
  541. PVOID
  542. AzpGetStringProperty(
  543. IN PAZP_STRING AzpString
  544. )
  545. /*++
  546. Routine Description
  547. Support routine for the GetProperty API. Convert an AzpString to the form
  548. supported by GetProperty.
  549. Empty string are returned as Zero length string instead of NULL
  550. Arguments
  551. AzpString - Specifies a string to make a copy of.
  552. Return Value
  553. Pointer to allocated string.
  554. String should be freed using AzFreeMemory.
  555. NULL - Not enough memory was available to allocate the string
  556. --*/
  557. {
  558. LPWSTR String;
  559. ULONG AllocatedSize;
  560. //
  561. // Allocate and copy the string
  562. //
  563. AllocatedSize = AzpString->StringSize ? AzpString->StringSize : sizeof(WCHAR);
  564. String = (LPWSTR) AzpAllocateHeap( AllocatedSize );
  565. if ( String != NULL ) {
  566. //
  567. // Convert NULL strings to zero length strings
  568. //
  569. if ( AzpString->StringSize == 0 ) {
  570. *String = L'\0';
  571. } else {
  572. RtlCopyMemory( String,
  573. AzpString->String,
  574. AzpString->StringSize );
  575. }
  576. }
  577. return String;
  578. }
  579. PVOID
  580. AzpGetUlongProperty(
  581. IN ULONG UlongValue
  582. )
  583. /*++
  584. Routine Description
  585. Support routine for the GetProperty API. Convert a ULONG to the form
  586. supported by GetProperty.
  587. Arguments
  588. UlongValue - Value to return to make a copy of.
  589. Return Value
  590. Pointer to allocated string.
  591. String should be freed using AzFreeMemory.
  592. NULL - Not enough memory was available to allocate the string
  593. --*/
  594. {
  595. PULONG RetValue;
  596. //
  597. // Allocate and copy the string
  598. //
  599. RetValue = (PULONG) AzpAllocateHeap( sizeof(ULONG) );
  600. if ( RetValue != NULL ) {
  601. *RetValue = UlongValue;
  602. }
  603. return RetValue;
  604. }
  605. //
  606. // Debugging support
  607. //
  608. #ifdef AZROLESDBG
  609. #include <stdio.h>
  610. CRITICAL_SECTION AzGlLogFileCritSect;
  611. ULONG AzGlDbFlag;
  612. // HANDLE AzGlLogFile;
  613. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  614. VOID
  615. AzpPrintRoutineV(
  616. IN DWORD DebugFlag,
  617. IN LPSTR Format,
  618. va_list arglist
  619. )
  620. /*++
  621. Routine Description
  622. Debug routine for azroles
  623. Arguments
  624. DebugFlag - Flag to indicating the functionality being debugged
  625. --- Other printf parameters
  626. Return Value
  627. --*/
  628. {
  629. static LPSTR AzGlLogFileOutputBuffer = NULL;
  630. ULONG length;
  631. int lengthTmp;
  632. // DWORD BytesWritten;
  633. static BeginningOfLine = TRUE;
  634. static LineCount = 0;
  635. static TruncateLogFileInProgress = FALSE;
  636. static LogProblemWarned = FALSE;
  637. //
  638. // If we aren't debugging this functionality, just return.
  639. //
  640. if ( DebugFlag != 0 && (AzGlDbFlag & DebugFlag) == 0 ) {
  641. return;
  642. }
  643. //
  644. // Allocate a buffer to build the line in.
  645. // If there isn't already one.
  646. //
  647. length = 0;
  648. if ( AzGlLogFileOutputBuffer == NULL ) {
  649. AzGlLogFileOutputBuffer = (LPSTR) LocalAlloc( 0, MAX_PRINTF_LEN + 1 );
  650. if ( AzGlLogFileOutputBuffer == NULL ) {
  651. return;
  652. }
  653. }
  654. //
  655. // Handle the beginning of a new line.
  656. //
  657. //
  658. if ( BeginningOfLine ) {
  659. //
  660. // Never print empty lines.
  661. //
  662. if ( Format[0] == '\n' && Format[1] == '\0' ) {
  663. return;
  664. }
  665. #if 0
  666. //
  667. // If the log file is getting huge,
  668. // truncate it.
  669. //
  670. if ( AzGlLogFile != INVALID_HANDLE_VALUE &&
  671. !TruncateLogFileInProgress ) {
  672. //
  673. // Only check every 50 lines,
  674. //
  675. LineCount++;
  676. if ( LineCount >= 50 ) {
  677. DWORD FileSize;
  678. LineCount = 0;
  679. //
  680. // Is the log file too big?
  681. //
  682. FileSize = GetFileSize( AzGlLogFile, NULL );
  683. if ( FileSize == 0xFFFFFFFF ) {
  684. (void) DbgPrint( "[NETLOGON] Cannot GetFileSize %ld\n",
  685. GetLastError );
  686. } else if ( FileSize > AzGlParameters.LogFileMaxSize ) {
  687. TruncateLogFileInProgress = TRUE;
  688. LeaveCriticalSection( &AzGlLogFileCritSect );
  689. NlOpenDebugFile( TRUE );
  690. NlPrint(( NL_MISC,
  691. "Logfile truncated because it was larger than %ld bytes\n",
  692. AzGlParameters.LogFileMaxSize ));
  693. EnterCriticalSection( &AzGlLogFileCritSect );
  694. TruncateLogFileInProgress = FALSE;
  695. }
  696. }
  697. }
  698. //
  699. // If we're writing to the debug terminal,
  700. // indicate this is a azroles message.
  701. //
  702. if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
  703. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[AZROLES] " );
  704. }
  705. //
  706. // Put the timestamp at the begining of the line.
  707. //
  708. {
  709. SYSTEMTIME SystemTime;
  710. GetLocalTime( &SystemTime );
  711. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length],
  712. "%02u/%02u %02u:%02u:%02u ",
  713. SystemTime.wMonth,
  714. SystemTime.wDay,
  715. SystemTime.wHour,
  716. SystemTime.wMinute,
  717. SystemTime.wSecond );
  718. }
  719. #endif // 0
  720. //
  721. // Indicate the type of message on the line
  722. //
  723. {
  724. char *Text;
  725. switch (DebugFlag) {
  726. case AZD_HANDLE:
  727. Text = "HANDLE"; break;
  728. case AZD_OBJLIST:
  729. Text = "OBJLIST"; break;
  730. case AZD_INVPARM:
  731. Text = "INVPARM"; break;
  732. case AZD_PERSIST:
  733. case AZD_PERSIST_MORE:
  734. Text = "PERSIST"; break;
  735. case AZD_REF:
  736. Text = "REF"; break;
  737. default:
  738. Text = "UNKNOWN"; break;
  739. case 0:
  740. Text = NULL;
  741. }
  742. if ( Text != NULL ) {
  743. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[%s] ", Text );
  744. }
  745. }
  746. }
  747. //
  748. // Put a the information requested by the caller onto the line
  749. //
  750. lengthTmp = (ULONG) _vsnprintf( &AzGlLogFileOutputBuffer[length],
  751. MAX_PRINTF_LEN - length - 1,
  752. Format,
  753. arglist );
  754. if ( lengthTmp < 0 ) {
  755. length = MAX_PRINTF_LEN - 1;
  756. // always end the line which cannot fit into the buffer
  757. AzGlLogFileOutputBuffer[length-1] = '\n';
  758. } else {
  759. length += lengthTmp;
  760. }
  761. BeginningOfLine = (length > 0 && AzGlLogFileOutputBuffer[length-1] == '\n' );
  762. if ( BeginningOfLine ) {
  763. AzGlLogFileOutputBuffer[length-1] = '\r';
  764. AzGlLogFileOutputBuffer[length] = '\n';
  765. AzGlLogFileOutputBuffer[length+1] = '\0';
  766. length++;
  767. }
  768. #if 0
  769. //
  770. // If the log file isn't open,
  771. // just output to the debug terminal
  772. //
  773. if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
  774. #if DBG
  775. if ( !LogProblemWarned ) {
  776. (void) DbgPrint( "[NETLOGON] Cannot write to log file [Invalid Handle]\n" );
  777. LogProblemWarned = TRUE;
  778. }
  779. #endif // DBG
  780. //
  781. // Write the debug info to the log file.
  782. //
  783. } else {
  784. if ( !WriteFile( AzGlLogFile,
  785. AzGlLogFileOutputBuffer,
  786. length,
  787. &BytesWritten,
  788. NULL ) ) {
  789. #if DBG
  790. if ( !LogProblemWarned ) {
  791. (void) DbgPrint( "[NETLOGON] Cannot write to log file %ld\n", GetLastError() );
  792. LogProblemWarned = TRUE;
  793. }
  794. #endif // DBG
  795. }
  796. }
  797. #else // 0
  798. printf( "%s", AzGlLogFileOutputBuffer );
  799. #endif // 0
  800. }
  801. VOID
  802. AzpPrintRoutine(
  803. IN DWORD DebugFlag,
  804. IN LPSTR Format,
  805. ...
  806. )
  807. {
  808. va_list arglist;
  809. //
  810. // vsprintf isn't multithreaded + we don't want to intermingle output
  811. // from different threads.
  812. //
  813. EnterCriticalSection( &AzGlLogFileCritSect );
  814. //
  815. // Simply change arguments to va_list form and call NlPrintRoutineV
  816. //
  817. va_start(arglist, Format);
  818. AzpPrintRoutineV( DebugFlag, Format, arglist );
  819. va_end(arglist);
  820. LeaveCriticalSection( &AzGlLogFileCritSect );
  821. } // AzPrintRoutine
  822. #endif // AZROLESDBG