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.

699 lines
15 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. SAFE_CRITICAL_SECTION AzGlAllocatorCritSect;
  17. GUID AzGlZeroGuid;
  18. //
  19. // Force C++ to use our allocator
  20. //
  21. void * __cdecl operator new(size_t s) {
  22. return AzpAllocateHeap( s, NULL );
  23. }
  24. void __cdecl operator delete(void *pv) {
  25. AzpFreeHeap( pv );
  26. }
  27. #endif // DBG
  28. PVOID
  29. AzpAllocateHeap(
  30. IN SIZE_T Size,
  31. IN LPSTR pDescr OPTIONAL
  32. )
  33. /*++
  34. Routine Description
  35. Memory allocator. The pDescr field is ignored for Free builds
  36. Arguments
  37. Size - Size (in bytes) to allocate
  38. pDescr - Optional string identifying the block of not more than 8 chars.
  39. Return Value
  40. Returns a pointer to the allocated memory.
  41. NULL - Not enough memory
  42. --*/
  43. {
  44. DBG_UNREFERENCED_PARAMETER( pDescr ); //ignore
  45. return LocalAlloc( 0, Size );
  46. }
  47. VOID
  48. AzpFreeHeap(
  49. IN PVOID Buffer
  50. )
  51. /*++
  52. Routine Description
  53. Memory de-allocator.
  54. Arguments
  55. Buffer - address of buffer to free
  56. Return Value
  57. None
  58. --*/
  59. {
  60. LocalFree( Buffer );
  61. }
  62. DWORD
  63. AzpHresultToWinStatus(
  64. HRESULT hr
  65. )
  66. /*++
  67. Routine Description
  68. Convert an Hresult to a WIN 32 status code
  69. Arguments
  70. hr - Hresult to convert
  71. Return Value
  72. --*/
  73. {
  74. DWORD WinStatus = ERROR_INTERNAL_ERROR;
  75. //
  76. // Success is still success
  77. //
  78. if ( hr == NO_ERROR ) {
  79. WinStatus = NO_ERROR;
  80. //
  81. // If the facility is WIN32,
  82. // the translation is easy.
  83. //
  84. } else if ((HRESULT_FACILITY(hr) == FACILITY_WIN32) && (FAILED(hr))) {
  85. WinStatus = HRESULT_CODE(hr);
  86. if ( WinStatus == ERROR_SUCCESS ) {
  87. WinStatus = ERROR_INTERNAL_ERROR;
  88. }
  89. //
  90. // All others should be left intact
  91. //
  92. } else {
  93. WinStatus = hr;
  94. }
  95. return WinStatus;
  96. }
  97. //
  98. // Debugging support
  99. //
  100. #ifdef AZROLESDBG
  101. #include <stdio.h>
  102. SAFE_CRITICAL_SECTION AzGlLogFileCritSect;
  103. ULONG AzGlDbFlag;
  104. // HANDLE AzGlLogFile;
  105. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  106. VOID
  107. AzpDumpGuid(
  108. IN DWORD DebugFlag,
  109. IN GUID *Guid OPTIONAL
  110. )
  111. /*++
  112. Routine Description:
  113. Dumps a GUID to the debugger output.
  114. Arguments:
  115. DebugFlag: Debug flag to pass on to AzPrintRoutine
  116. Guid: Guid to print
  117. Return Value:
  118. none
  119. --*/
  120. {
  121. RPC_STATUS RpcStatus;
  122. unsigned char *StringGuid;
  123. //
  124. // If we aren't debugging this functionality, just return.
  125. //
  126. if ( DebugFlag != 0 && (AzGlDbFlag & DebugFlag) == 0 ) {
  127. return;
  128. }
  129. if ( Guid == NULL ) {
  130. AzPrint(( DebugFlag, "(null)" ));
  131. } else {
  132. RpcStatus = UuidToStringA( Guid, &StringGuid );
  133. if ( RpcStatus != RPC_S_OK ) {
  134. return;
  135. }
  136. AzPrint(( DebugFlag, "%s", StringGuid ));
  137. RpcStringFreeA( &StringGuid );
  138. }
  139. }
  140. DWORD
  141. AzpConvertSelfRelativeToAbsoluteSD(
  142. IN PSECURITY_DESCRIPTOR pSelfRelativeSd,
  143. OUT PSECURITY_DESCRIPTOR *ppAbsoluteSD,
  144. OUT PACL *ppDacl,
  145. OUT PACL *ppSacl
  146. )
  147. /*++
  148. Routine Description:
  149. This routine returns an absolute form SD for a passed
  150. in self-relative form SD. The returned SD and all of its required
  151. component(s) need to be freed using AzFreeMemory routine.
  152. Arguments:
  153. pSelfRelativeSd - Passed in self-relative form SD
  154. ppAbsoluteSD - Returned absolute form SD
  155. ppDacl - Returned Dacl component if needed
  156. ppSacl - Returned Sacl component if needed
  157. Return Values:
  158. NO_ERROR - The absolute form SD was created successfully
  159. Other status codes
  160. --*/
  161. {
  162. DWORD WinStatus = 0;
  163. DWORD dAbsoluteSDLen = 0;
  164. DWORD dDaclLen = 0;
  165. DWORD dSaclLen = 0;
  166. DWORD dOwnerLen = 0;
  167. DWORD dGroupLen = 0;
  168. PSID pOwner = NULL;
  169. PSID pGroup = NULL;
  170. //
  171. // We first need to get the size for each of its fields
  172. //
  173. if ( !MakeAbsoluteSD(
  174. pSelfRelativeSd, NULL,
  175. &dAbsoluteSDLen,
  176. NULL, &dDaclLen,
  177. NULL, &dSaclLen,
  178. NULL, &dOwnerLen,
  179. NULL, &dGroupLen
  180. ) ) {
  181. *ppAbsoluteSD = (PSECURITY_DESCRIPTOR) AzpAllocateHeap( dAbsoluteSDLen, NULL );
  182. if ( *ppAbsoluteSD == NULL ) {
  183. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  184. goto Cleanup;
  185. }
  186. if ( ppDacl ) {
  187. *ppDacl = (PACL) AzpAllocateHeap( dDaclLen, NULL );
  188. if ( *ppDacl == NULL ) {
  189. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  190. goto Cleanup;
  191. }
  192. }
  193. if ( ppSacl ) {
  194. *ppSacl = (PACL) AzpAllocateHeap( dSaclLen, NULL );
  195. if ( *ppSacl == NULL ) {
  196. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  197. goto Cleanup;
  198. }
  199. }
  200. if ( dOwnerLen > 0 ) {
  201. pOwner = (PSID) AzpAllocateHeap( dOwnerLen, NULL );
  202. if ( pOwner == NULL ) {
  203. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  204. goto Cleanup;
  205. }
  206. }
  207. if ( dGroupLen > 0 ) {
  208. pGroup = (PSID) AzpAllocateHeap( dGroupLen, NULL );
  209. if ( pGroup == NULL ) {
  210. WinStatus = ERROR_NOT_ENOUGH_MEMORY;
  211. goto Cleanup;
  212. }
  213. }
  214. //
  215. // Now do the conversion
  216. //
  217. if ( !MakeAbsoluteSD(
  218. pSelfRelativeSd, *ppAbsoluteSD,
  219. &dAbsoluteSDLen,
  220. *ppDacl, &dDaclLen,
  221. NULL, &dSaclLen,
  222. pOwner, &dOwnerLen,
  223. pGroup, &dGroupLen ) ) {
  224. WinStatus = GetLastError();
  225. goto Cleanup;
  226. }
  227. } else {
  228. WinStatus = GetLastError();
  229. goto Cleanup;
  230. }
  231. WinStatus = NO_ERROR;
  232. Cleanup:
  233. if ( pOwner != NULL ) {
  234. AzpFreeHeap( pOwner );
  235. }
  236. if ( pGroup != NULL ) {
  237. AzpFreeHeap( pGroup );
  238. }
  239. return WinStatus;
  240. }
  241. #if 0 //
  242. VOID
  243. AzpDumpGoRef(
  244. IN LPSTR Text,
  245. IN struct _GENERIC_OBJECT *GenericObject
  246. )
  247. /*++
  248. Routine Description:
  249. Dumps the ref count for a generic object
  250. Arguments:
  251. Text - Description of why the ref count is changing
  252. GenericObject - a pointer to the object being ref counted
  253. Return Value:
  254. none
  255. --*/
  256. {
  257. LPWSTR StringSid = NULL;
  258. LPWSTR StringToPrint;
  259. //
  260. // If we aren't debugging this functionality, just return.
  261. //
  262. if ( (AzGlDbFlag & AZD_REF) == 0 ) {
  263. return;
  264. }
  265. //
  266. // Convert the sid to a string
  267. //
  268. if ( GenericObject->ObjectName == NULL ) {
  269. StringToPrint = NULL;
  270. } else if ( GenericObject->ObjectName->ObjectName.IsSid ) {
  271. if ( ConvertSidToStringSid( (PSID)GenericObject->ObjectName->ObjectName.String, &StringSid)) {
  272. StringToPrint = StringSid;
  273. } else {
  274. StringToPrint = L"<Invalid Sid>";
  275. }
  276. } else {
  277. StringToPrint = GenericObject->ObjectName->ObjectName.String;
  278. }
  279. AzPrint(( AZD_REF, "0x%lx %ld (%ld) %ws: %s\n", GenericObject, GenericObject->ObjectType, GenericObject->ReferenceCount, StringToPrint, Text ));
  280. if ( StringSid != NULL ) {
  281. LocalFree( StringSid );
  282. }
  283. }
  284. #endif // 0
  285. VOID
  286. AzpPrintRoutineV(
  287. IN DWORD DebugFlag,
  288. IN LPSTR Format,
  289. va_list arglist
  290. )
  291. /*++
  292. Routine Description
  293. Debug routine for azroles
  294. Arguments
  295. DebugFlag - Flag to indicating the functionality being debugged
  296. --- Other printf parameters
  297. Return Value
  298. --*/
  299. {
  300. static LPSTR AzGlLogFileOutputBuffer = NULL;
  301. ULONG length;
  302. int lengthTmp;
  303. // DWORD BytesWritten;
  304. static BeginningOfLine = TRUE;
  305. static LineCount = 0;
  306. static TruncateLogFileInProgress = FALSE;
  307. static LogProblemWarned = FALSE;
  308. //
  309. // If we aren't debugging this functionality, just return.
  310. //
  311. if ( DebugFlag != 0 && (AzGlDbFlag & DebugFlag) == 0 ) {
  312. return;
  313. }
  314. //
  315. // Allocate a buffer to build the line in.
  316. // If there isn't already one.
  317. //
  318. length = 0;
  319. if ( AzGlLogFileOutputBuffer == NULL ) {
  320. AzGlLogFileOutputBuffer = (LPSTR) LocalAlloc( 0, MAX_PRINTF_LEN + 1 );
  321. if ( AzGlLogFileOutputBuffer == NULL ) {
  322. return;
  323. }
  324. }
  325. //
  326. // Handle the beginning of a new line.
  327. //
  328. //
  329. if ( BeginningOfLine ) {
  330. //
  331. // Never print empty lines.
  332. //
  333. if ( Format[0] == '\n' && Format[1] == '\0' ) {
  334. return;
  335. }
  336. #if 0
  337. //
  338. // If the log file is getting huge,
  339. // truncate it.
  340. //
  341. if ( AzGlLogFile != INVALID_HANDLE_VALUE &&
  342. !TruncateLogFileInProgress ) {
  343. //
  344. // Only check every 50 lines,
  345. //
  346. LineCount++;
  347. if ( LineCount >= 50 ) {
  348. DWORD FileSize;
  349. LineCount = 0;
  350. //
  351. // Is the log file too big?
  352. //
  353. FileSize = GetFileSize( AzGlLogFile, NULL );
  354. if ( FileSize == 0xFFFFFFFF ) {
  355. (void) DbgPrint( "[NETLOGON] Cannot GetFileSize %ld\n",
  356. GetLastError );
  357. } else if ( FileSize > AzGlParameters.LogFileMaxSize ) {
  358. TruncateLogFileInProgress = TRUE;
  359. SafeLeaveCriticalSection( &AzGlLogFileCritSect );
  360. NlOpenDebugFile( TRUE );
  361. NlPrint(( NL_MISC,
  362. "Logfile truncated because it was larger than %ld bytes\n",
  363. AzGlParameters.LogFileMaxSize ));
  364. SafeEnterCriticalSection( &AzGlLogFileCritSect );
  365. TruncateLogFileInProgress = FALSE;
  366. }
  367. }
  368. }
  369. //
  370. // If we're writing to the debug terminal,
  371. // indicate this is a azroles message.
  372. //
  373. if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
  374. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[AZROLES] " );
  375. }
  376. //
  377. // Put the timestamp at the begining of the line.
  378. //
  379. {
  380. SYSTEMTIME SystemTime;
  381. GetLocalTime( &SystemTime );
  382. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length],
  383. "%02u/%02u %02u:%02u:%02u ",
  384. SystemTime.wMonth,
  385. SystemTime.wDay,
  386. SystemTime.wHour,
  387. SystemTime.wMinute,
  388. SystemTime.wSecond );
  389. }
  390. #endif // 0
  391. //
  392. // Indicate the type of message on the line
  393. //
  394. {
  395. char *Text;
  396. switch (DebugFlag) {
  397. case AZD_HANDLE:
  398. Text = "HANDLE"; break;
  399. case AZD_OBJLIST:
  400. Text = "OBJLIST"; break;
  401. case AZD_INVPARM:
  402. Text = "INVPARM"; break;
  403. case AZD_PERSIST:
  404. case AZD_PERSIST_MORE:
  405. Text = "PERSIST"; break;
  406. case AZD_REF:
  407. Text = "OBJREF"; break;
  408. case AZD_DISPATCH:
  409. Text = "DISPATCH"; break;
  410. case AZD_ACCESS:
  411. case AZD_ACCESS_MORE:
  412. Text = "ACCESS"; break;
  413. case AZD_DOMREF:
  414. Text = "DOMREF"; break;
  415. case AZD_XML:
  416. Text = "XML"; break;
  417. case AZD_SCRIPT:
  418. case AZD_SCRIPT_MORE:
  419. Text = "SCRIPT"; break;
  420. case AZD_CRITICAL:
  421. Text = "CRITICAL"; break;
  422. default:
  423. Text = "UNKNOWN"; break;
  424. case 0:
  425. Text = NULL;
  426. }
  427. if ( Text != NULL ) {
  428. length += (ULONG) sprintf( &AzGlLogFileOutputBuffer[length], "[%s] ", Text );
  429. }
  430. }
  431. }
  432. //
  433. // Put a the information requested by the caller onto the line
  434. //
  435. lengthTmp = (ULONG) _vsnprintf( &AzGlLogFileOutputBuffer[length],
  436. MAX_PRINTF_LEN - length - 1,
  437. Format,
  438. arglist );
  439. if ( lengthTmp < 0 ) {
  440. length = MAX_PRINTF_LEN - 1;
  441. // always end the line which cannot fit into the buffer
  442. AzGlLogFileOutputBuffer[length-1] = '\n';
  443. } else {
  444. length += lengthTmp;
  445. }
  446. BeginningOfLine = (length > 0 && AzGlLogFileOutputBuffer[length-1] == '\n' );
  447. if ( BeginningOfLine ) {
  448. AzGlLogFileOutputBuffer[length-1] = '\r';
  449. AzGlLogFileOutputBuffer[length] = '\n';
  450. AzGlLogFileOutputBuffer[length+1] = '\0';
  451. length++;
  452. }
  453. #if 0
  454. //
  455. // If the log file isn't open,
  456. // just output to the debug terminal
  457. //
  458. if ( AzGlLogFile == INVALID_HANDLE_VALUE ) {
  459. #if DBG
  460. if ( !LogProblemWarned ) {
  461. (void) DbgPrint( "[NETLOGON] Cannot write to log file [Invalid Handle]\n" );
  462. LogProblemWarned = TRUE;
  463. }
  464. #endif // DBG
  465. //
  466. // Write the debug info to the log file.
  467. //
  468. } else {
  469. if ( !WriteFile( AzGlLogFile,
  470. AzGlLogFileOutputBuffer,
  471. length,
  472. &BytesWritten,
  473. NULL ) ) {
  474. #if DBG
  475. if ( !LogProblemWarned ) {
  476. (void) DbgPrint( "[NETLOGON] Cannot write to log file %ld\n", GetLastError() );
  477. LogProblemWarned = TRUE;
  478. }
  479. #endif // DBG
  480. }
  481. }
  482. #else // 0
  483. printf( "%s", AzGlLogFileOutputBuffer );
  484. #endif // 0
  485. }
  486. VOID
  487. AzpPrintRoutine(
  488. IN DWORD DebugFlag,
  489. IN LPSTR Format,
  490. ...
  491. )
  492. {
  493. va_list arglist;
  494. //
  495. // vsprintf isn't multithreaded + we don't want to intermingle output
  496. // from different threads.
  497. //
  498. SafeEnterCriticalSection( &AzGlLogFileCritSect );
  499. //
  500. // Simply change arguments to va_list form and call NlPrintRoutineV
  501. //
  502. va_start(arglist, Format);
  503. AzpPrintRoutineV( DebugFlag, Format, arglist );
  504. va_end(arglist);
  505. SafeLeaveCriticalSection( &AzGlLogFileCritSect );
  506. } // AzPrintRoutine
  507. #endif // AZROLESDBG