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.

2620 lines
73 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #if !defined(lint)
  4. #include "lsaptmp.h"
  5. #include "adttest.h"
  6. LUID AuditPrivilege = { SE_AUDIT_PRIVILEGE, 0 };
  7. NTSTATUS
  8. LsapGetLogonSessionAccountInfo(
  9. IN PLUID Value,
  10. OUT PUNICODE_STRING AccountName,
  11. OUT PUNICODE_STRING AuthorityName
  12. );
  13. NTSTATUS
  14. LsapRtlConvertSidToString(
  15. IN PSID Sid,
  16. OUT PWSTR szString,
  17. IN OUT DWORD *pdwRequiredSize
  18. )
  19. {
  20. NTSTATUS Status = STATUS_SUCCESS;
  21. PWSTR szBufPtr = szString;
  22. ULONG ulNumChars;
  23. UCHAR i;
  24. ULONG Tmp;
  25. PISID iSid = (PISID)Sid;
  26. if ( *pdwRequiredSize < 256 )
  27. {
  28. Status = STATUS_BUFFER_OVERFLOW;
  29. *pdwRequiredSize = 256;
  30. goto Cleanup;
  31. }
  32. ulNumChars = wsprintf(szBufPtr, L"S-%u-", (USHORT)iSid->Revision );
  33. szBufPtr += ulNumChars;
  34. if ( (iSid->IdentifierAuthority.Value[0] != 0) ||
  35. (iSid->IdentifierAuthority.Value[1] != 0) )
  36. {
  37. ulNumChars = wsprintf(szBufPtr, L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  38. (USHORT)iSid->IdentifierAuthority.Value[0],
  39. (USHORT)iSid->IdentifierAuthority.Value[1],
  40. (USHORT)iSid->IdentifierAuthority.Value[2],
  41. (USHORT)iSid->IdentifierAuthority.Value[3],
  42. (USHORT)iSid->IdentifierAuthority.Value[4],
  43. (USHORT)iSid->IdentifierAuthority.Value[5] );
  44. }
  45. else
  46. {
  47. Tmp = (ULONG)iSid->IdentifierAuthority.Value[5] +
  48. (ULONG)(iSid->IdentifierAuthority.Value[4] << 8) +
  49. (ULONG)(iSid->IdentifierAuthority.Value[3] << 16) +
  50. (ULONG)(iSid->IdentifierAuthority.Value[2] << 24);
  51. ulNumChars = wsprintf(szBufPtr, L"%lu", Tmp);
  52. }
  53. szBufPtr += ulNumChars;
  54. for (i=0;i<iSid->SubAuthorityCount ;i++ )
  55. {
  56. ulNumChars = wsprintf(szBufPtr, L"-%lu", iSid->SubAuthority[i]);
  57. szBufPtr += ulNumChars;
  58. }
  59. Cleanup:
  60. return(Status);
  61. }
  62. PVOID NTAPI
  63. LsapAllocateLsaHeap(
  64. IN ULONG cbMemory
  65. )
  66. {
  67. return(RtlAllocateHeap(
  68. RtlProcessHeap(),
  69. HEAP_ZERO_MEMORY,
  70. cbMemory
  71. ));
  72. }
  73. void NTAPI
  74. LsapFreeLsaHeap(
  75. IN PVOID pvMemory
  76. )
  77. {
  78. RtlFreeHeap(RtlProcessHeap(), 0, pvMemory);
  79. }
  80. NTSTATUS
  81. LsapAdtDemarshallAuditInfo(
  82. IN PSE_ADT_PARAMETER_ARRAY AuditParameters
  83. )
  84. /*++
  85. Routine Description:
  86. This routine will walk down a marshalled audit parameter
  87. array and unpack it so that its information may be passed
  88. into the event logging service.
  89. Three parallel data structures are maintained:
  90. StringArray - Array of Unicode string structures. This array
  91. is used primarily as temporary storage for returned string
  92. structures.
  93. StringPointerArray - Array of pointers to Unicode string structures.
  94. FreeWhenDone - Array of booleans describing how to dispose of each
  95. of the strings pointed to by the StringPointerArray.
  96. Note that entries in the StringPointerArray are contiguous, but that
  97. there may be gaps in the StringArray structure. For each entry in the
  98. StringPointerArray there will be a corresponding entry in the FreeWhenDone
  99. array. If the entry for a particular string is TRUE, the storage for
  100. the string buffer will be released to the process heap.
  101. StringArray
  102. Other strings
  103. +----------------+
  104. | |<-----------+ +----------------+
  105. | | | | |<-------------------+
  106. +----------------+ | | | |
  107. | UNUSED | | +----------------+ |
  108. | | | |
  109. +----------------+ | |
  110. | |<------+ | +----------------+ |
  111. | | | | | |<-----------+ |
  112. +----------------+ | | | | | |
  113. | UNUSED | | | +----------------+ | |
  114. | | | | | |
  115. +----------------+ | | | |
  116. | |<--+ | | | |
  117. | | | | | | |
  118. +----------------+ | | | | |
  119. | | | | | | |
  120. | | | | | StringPointerArray | |
  121. .... | | | | |
  122. | | | +----------------+ | |
  123. | | +-----| | | |
  124. | | +----------------+ | |
  125. | | | |---------+ |
  126. | | +----------------+ |
  127. | +----------| | |
  128. | +----------------+ |
  129. | | |-----------------+
  130. | +----------------+
  131. +--------------| |
  132. +----------------+
  133. | |
  134. +----------------+
  135. | |
  136. +----------------+
  137. | |
  138. ....
  139. Arguments:
  140. AuditParameters - Receives a pointer to an audit
  141. parameters array in self-relative form.
  142. Return Value:
  143. --*/
  144. {
  145. ULONG ParameterCount;
  146. USHORT i;
  147. PUNICODE_STRING StringPointerArray[SE_MAX_AUDIT_PARAM_STRINGS];
  148. UNICODE_STRING NewObjectTypeName;
  149. ULONG NewObjectTypeStringIndex = 0;
  150. BOOLEAN FreeWhenDone[SE_MAX_AUDIT_PARAM_STRINGS];
  151. UNICODE_STRING StringArray[SE_MAX_AUDIT_PARAM_STRINGS];
  152. USHORT StringIndexArray[SE_MAX_AUDIT_PARAM_STRINGS];
  153. USHORT StringIndex = 0;
  154. UNICODE_STRING DashString;
  155. BOOLEAN FreeDash;
  156. NTSTATUS Status;
  157. PUNICODE_STRING SourceModule;
  158. PSID UserSid;
  159. //
  160. // Initialization.
  161. //
  162. RtlInitUnicodeString( &NewObjectTypeName, NULL );
  163. Status= LsapAdtBuildDashString(
  164. &DashString,
  165. &FreeDash
  166. );
  167. if ( !NT_SUCCESS( Status )) {
  168. return( Status );
  169. }
  170. ParameterCount = AuditParameters->ParameterCount;
  171. //
  172. // Parameter 0 will always be the user SID. Convert the
  173. // offset to the SID into a pointer.
  174. //
  175. ASSERT( AuditParameters->Parameters[0].Type == SeAdtParmTypeSid );
  176. UserSid = (PSID)AuditParameters->Parameters[0].Address;
  177. //
  178. // Parameter 1 will always be the Source Module (or Subsystem Name).
  179. // Unpack this now.
  180. //
  181. ASSERT( AuditParameters->Parameters[1].Type == SeAdtParmTypeString );
  182. SourceModule = (PUNICODE_STRING)AuditParameters->Parameters[1].Address;
  183. for (i=2; i<ParameterCount; i++) {
  184. StringIndexArray[i] = StringIndex;
  185. switch ( AuditParameters->Parameters[i].Type ) {
  186. case SeAdtParmTypeNone:
  187. {
  188. StringPointerArray[StringIndex] = &DashString;
  189. FreeWhenDone[StringIndex] = FALSE;
  190. StringIndex++;
  191. break;
  192. }
  193. case SeAdtParmTypeString:
  194. {
  195. StringPointerArray[StringIndex] =
  196. (PUNICODE_STRING)AuditParameters->Parameters[i].Address;
  197. FreeWhenDone[StringIndex] = FALSE;
  198. StringIndex++;
  199. break;
  200. }
  201. case SeAdtParmTypeFileSpec:
  202. {
  203. //
  204. // Same as a string, except we must attempt to replace
  205. // device information with a drive letter.
  206. //
  207. StringPointerArray[StringIndex] =
  208. (PUNICODE_STRING)AuditParameters->Parameters[i].Address;
  209. //
  210. // This may not do anything, in which case just audit what
  211. // we have.
  212. //
  213. //LsapAdtSubstituteDriveLetter( StringPointerArray[StringIndex] );
  214. FreeWhenDone[StringIndex] = FALSE;
  215. StringIndex++;
  216. break;
  217. }
  218. case SeAdtParmTypeUlong:
  219. {
  220. ULONG Data;
  221. Data = (ULONG) AuditParameters->Parameters[i].Data[0];
  222. Status = LsapAdtBuildUlongString(
  223. Data,
  224. &StringArray[StringIndex],
  225. &FreeWhenDone[StringIndex]
  226. );
  227. if ( NT_SUCCESS( Status )) {
  228. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  229. } else {
  230. //
  231. // Couldn't allocate memory for that string,
  232. // use the Dash string that we've already created.
  233. //
  234. StringPointerArray[StringIndex] = &DashString;
  235. FreeWhenDone[StringIndex] = FALSE;
  236. }
  237. StringIndex++;
  238. break;
  239. }
  240. case SeAdtParmTypeHexUlong:
  241. {
  242. ULONG Data;
  243. Data = (ULONG) AuditParameters->Parameters[i].Data[0];
  244. Status = LsapAdtBuildHexUlongString(
  245. Data,
  246. &StringArray[StringIndex],
  247. &FreeWhenDone[StringIndex]
  248. );
  249. if ( NT_SUCCESS( Status )) {
  250. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  251. } else {
  252. //
  253. // Couldn't allocate memory for that string,
  254. // use the Dash string that we've already created.
  255. //
  256. StringPointerArray[StringIndex] = &DashString;
  257. FreeWhenDone[StringIndex] = FALSE;
  258. }
  259. StringIndex++;
  260. break;
  261. }
  262. case SeAdtParmTypeSid:
  263. {
  264. PSID Sid;
  265. Sid = (PSID)AuditParameters->Parameters[i].Address;
  266. Status = LsapAdtBuildSidString(
  267. Sid,
  268. &StringArray[StringIndex],
  269. &FreeWhenDone[StringIndex]
  270. );
  271. if ( NT_SUCCESS( Status )) {
  272. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  273. } else {
  274. //
  275. // Couldn't allocate memory for that string,
  276. // use the Dash string that we've already created.
  277. //
  278. StringPointerArray[StringIndex] = &DashString;
  279. FreeWhenDone[StringIndex] = FALSE;
  280. }
  281. StringIndex++;
  282. break;
  283. }
  284. case SeAdtParmTypeLogonId:
  285. {
  286. PLUID LogonId;
  287. ULONG j;
  288. LogonId = (PLUID)(&AuditParameters->Parameters[i].Data[0]);
  289. Status = LsapAdtBuildLogonIdStrings(
  290. LogonId,
  291. &StringArray [ StringIndex ],
  292. &FreeWhenDone[ StringIndex ],
  293. &StringArray [ StringIndex + 1 ],
  294. &FreeWhenDone[ StringIndex + 1 ],
  295. &StringArray [ StringIndex + 2 ],
  296. &FreeWhenDone[ StringIndex + 2 ]
  297. );
  298. if ( NT_SUCCESS( Status )) {
  299. for (j=0; j<3; j++) {
  300. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  301. StringIndex++;
  302. }
  303. //
  304. // Finished, break out to surrounding loop.
  305. //
  306. break;
  307. } else {
  308. //
  309. // Do nothing, fall through to the NoLogonId case
  310. //
  311. }
  312. }
  313. case SeAdtParmTypeNoLogonId:
  314. {
  315. ULONG j;
  316. //
  317. // Create three "-" strings.
  318. //
  319. for (j=0; j<3; j++) {
  320. StringPointerArray[ StringIndex ] = &DashString;
  321. FreeWhenDone[ StringIndex ] = FALSE;
  322. StringIndex++;
  323. }
  324. break;
  325. }
  326. case SeAdtParmTypeAccessMask:
  327. {
  328. PUNICODE_STRING ObjectTypeName;
  329. ULONG ObjectTypeNameIndex;
  330. ACCESS_MASK Accesses;
  331. ObjectTypeNameIndex = (ULONG) AuditParameters->Parameters[i].Data[1];
  332. ObjectTypeName = AuditParameters->Parameters[ObjectTypeNameIndex].Address;
  333. Accesses= (ACCESS_MASK) AuditParameters->Parameters[i].Data[0];
  334. //
  335. // We can determine the index to the ObjectTypeName
  336. // parameter since it was stored away in the Data[1]
  337. // field of this parameter.
  338. //
  339. Status = LsapAdtBuildAccessesString(
  340. SourceModule,
  341. ObjectTypeName,
  342. Accesses,
  343. TRUE,
  344. &StringArray [ StringIndex ],
  345. &FreeWhenDone[ StringIndex ]
  346. );
  347. if ( NT_SUCCESS( Status )) {
  348. StringPointerArray[ StringIndex ] = &StringArray[ StringIndex ];
  349. } else {
  350. //
  351. // That didn't work, use the Dash string instead.
  352. //
  353. StringPointerArray[ StringIndex ] = &DashString;
  354. FreeWhenDone [ StringIndex ] = FALSE;
  355. }
  356. StringIndex++;
  357. break;
  358. }
  359. case SeAdtParmTypePrivs:
  360. {
  361. PPRIVILEGE_SET Privileges = (PPRIVILEGE_SET)AuditParameters->Parameters[i].Address;
  362. Status = LsapBuildPrivilegeAuditString(
  363. Privileges,
  364. &StringArray [ StringIndex ],
  365. &FreeWhenDone[ StringIndex ]
  366. );
  367. if ( NT_SUCCESS( Status )) {
  368. StringPointerArray[ StringIndex ] = &StringArray[ StringIndex ];
  369. } else {
  370. //
  371. // That didn't work, use the Dash string instead.
  372. //
  373. StringPointerArray[ StringIndex ] = &DashString;
  374. FreeWhenDone [ StringIndex ] = FALSE;
  375. }
  376. StringIndex++;
  377. break;
  378. }
  379. case SeAdtParmTypeObjectTypes:
  380. {
  381. PUNICODE_STRING ObjectTypeName;
  382. ULONG ObjectTypeNameIndex;
  383. PSE_ADT_OBJECT_TYPE ObjectTypeList;
  384. ULONG ObjectTypeCount;
  385. ULONG j;
  386. ObjectTypeNameIndex = (ULONG) AuditParameters->Parameters[i].Data[1];
  387. NewObjectTypeStringIndex = StringIndexArray[ObjectTypeNameIndex];
  388. ObjectTypeName = AuditParameters->Parameters[ObjectTypeNameIndex].Address;
  389. ObjectTypeList = AuditParameters->Parameters[i].Address;
  390. ObjectTypeCount = AuditParameters->Parameters[i].Length / sizeof(SE_ADT_OBJECT_TYPE);
  391. //
  392. // Will Fill in 10 entries.
  393. Status = LsapAdtBuildObjectTypeStrings(
  394. SourceModule,
  395. ObjectTypeName,
  396. ObjectTypeList,
  397. ObjectTypeCount,
  398. &StringArray [ StringIndex ],
  399. &FreeWhenDone[ StringIndex ],
  400. &NewObjectTypeName
  401. );
  402. for (j=0; j<10; j++) {
  403. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  404. StringIndex++;
  405. }
  406. //
  407. //
  408. // &StringArray [ StringIndexArray[ObjectTypeNameIndex]],
  409. // &FreeWhenDone[ StringIndexArray[ObjectTypeNameIndex]],
  410. //
  411. // Finished, break out to surrounding loop.
  412. //
  413. break;
  414. }
  415. case SeAdtParmTypePtr:
  416. {
  417. PVOID Data;
  418. Data = (PVOID) AuditParameters->Parameters[i].Data[0];
  419. Status = LsapAdtBuildPtrString(
  420. Data,
  421. &StringArray[StringIndex],
  422. &FreeWhenDone[StringIndex]
  423. );
  424. if ( NT_SUCCESS( Status )) {
  425. StringPointerArray[StringIndex] = &StringArray[StringIndex];
  426. } else {
  427. //
  428. // Couldn't allocate memory for that string,
  429. // use the Dash string that we've already created.
  430. //
  431. StringPointerArray[StringIndex] = &DashString;
  432. FreeWhenDone[StringIndex] = FALSE;
  433. }
  434. StringIndex++;
  435. break;
  436. }
  437. }
  438. }
  439. //
  440. // If the generic object type name has been converted to something
  441. // specific to this audit,
  442. // substitute it now.
  443. //
  444. if ( NewObjectTypeName.Length != 0 ) {
  445. //
  446. // Free the previous object type name.
  447. //
  448. if ( FreeWhenDone[NewObjectTypeStringIndex] ) {
  449. LsapFreeLsaHeap( StringPointerArray[NewObjectTypeStringIndex]->Buffer );
  450. }
  451. //
  452. // Save the new object type name.
  453. //
  454. FreeWhenDone[NewObjectTypeStringIndex] = TRUE;
  455. StringPointerArray[NewObjectTypeStringIndex] = &NewObjectTypeName;
  456. }
  457. //
  458. // Probably have to do this from somewhere else eventually, but for now
  459. // do it from here.
  460. //
  461. Status = kElfReportEventW (
  462. NULL, //LsapAdtLogHandle,
  463. AuditParameters->Type,
  464. (USHORT)AuditParameters->CategoryId,
  465. AuditParameters->AuditId,
  466. UserSid,
  467. StringIndex,
  468. 0,
  469. StringPointerArray,
  470. NULL,
  471. 0,
  472. NULL,
  473. NULL
  474. );
  475. //
  476. // cleanup
  477. //
  478. for (i=0; i<StringIndex; i++) {
  479. if (FreeWhenDone[i]) {
  480. LsapFreeLsaHeap( StringPointerArray[i]->Buffer );
  481. }
  482. }
  483. //
  484. // If we are shutting down and we got an expected error back from the
  485. // eventlog, don't worry about it. This prevents bugchecking from an
  486. // audit failure while shutting down.
  487. //
  488. if ( ( (Status == RPC_NT_UNKNOWN_IF) || (Status == STATUS_UNSUCCESSFUL)) &&
  489. TRUE /*LsapState.SystemShutdownPending*/ ) {
  490. Status = STATUS_SUCCESS;
  491. }
  492. return( Status );
  493. }
  494. // ======================================================================
  495. // adtbuild.c
  496. // ======================================================================
  497. ////////////////////////////////////////////////////////////////////////
  498. // //
  499. // Local Macro definitions and local function prototypes //
  500. // //
  501. ////////////////////////////////////////////////////////////////////////
  502. #ifdef LSAP_ADT_UMTEST
  503. //
  504. // Define all external routines that we won't pick up in a user mode test
  505. //
  506. // NTSTATUS
  507. // LsapGetLogonSessionAccountInfo(
  508. // IN PLUID Value,
  509. // OUT PUNICODE_STRING AccountName,
  510. // OUT PUNICODE_STRING AuthorityName
  511. // );
  512. #endif
  513. ////////////////////////////////////////////////////////////////////////
  514. // //
  515. // Data types used within this module //
  516. // //
  517. ////////////////////////////////////////////////////////////////////////
  518. ////////////////////////////////////////////////////////////////////////
  519. // //
  520. // Variables global within this module //
  521. // //
  522. ////////////////////////////////////////////////////////////////////////
  523. ////////////////////////////////////////////////////////////////////////
  524. // //
  525. // Services exported by this module. //
  526. // //
  527. ////////////////////////////////////////////////////////////////////////
  528. NTSTATUS
  529. LsapAdtBuildUlongString(
  530. IN ULONG Value,
  531. OUT PUNICODE_STRING ResultantString,
  532. OUT PBOOLEAN FreeWhenDone
  533. )
  534. /*++
  535. Routine Description:
  536. This function builds a unicode string representing the passed value.
  537. The resultant string will be formatted as a decimal value with not
  538. more than 10 digits.
  539. Arguments:
  540. Value - The value to be transformed to printable format (Unicode string).
  541. ResultantString - Points to the unicode string header. The body of this
  542. unicode string will be set to point to the resultant output value
  543. if successful. Otherwise, the Buffer field of this parameter
  544. will be set to NULL.
  545. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  546. must be freed to process heap when no longer needed.
  547. Return Values:
  548. STATUS_NO_MEMORY - indicates memory could not be allocated
  549. for the string body.
  550. All other Result Codes are generated by called routines.
  551. --*/
  552. {
  553. NTSTATUS Status;
  554. //
  555. // Maximum length is 10 wchar characters plus a null termination character.
  556. //
  557. ResultantString->Length = 0;
  558. ResultantString->MaximumLength = 11 * sizeof(WCHAR); // 10 digits & null termination
  559. ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  560. ResultantString->MaximumLength);
  561. if (ResultantString->Buffer == NULL) {
  562. return(STATUS_NO_MEMORY);
  563. }
  564. Status = RtlIntegerToUnicodeString( Value, 10, ResultantString );
  565. ASSERT(NT_SUCCESS(Status));
  566. (*FreeWhenDone) = TRUE;
  567. return(STATUS_SUCCESS);
  568. }
  569. NTSTATUS
  570. LsapAdtBuildHexUlongString(
  571. IN ULONG Value,
  572. OUT PUNICODE_STRING ResultantString,
  573. OUT PBOOLEAN FreeWhenDone
  574. )
  575. /*++
  576. Routine Description:
  577. This function builds a unicode string representing the passed value.
  578. The resultant string will be formatted as a hexidecimal value with not
  579. more than 10 digits.
  580. Arguments:
  581. Value - The value to be transformed to printable format (Unicode string).
  582. ResultantString - Points to the unicode string header. The body of this
  583. unicode string will be set to point to the resultant output value
  584. if successful. Otherwise, the Buffer field of this parameter
  585. will be set to NULL.
  586. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  587. must be freed to process heap when no longer needed.
  588. Return Values:
  589. STATUS_NO_MEMORY - indicates memory could not be allocated
  590. for the string body.
  591. All other Result Codes are generated by called routines.
  592. --*/
  593. {
  594. NTSTATUS Status;
  595. //
  596. // Maximum length is 10 wchar characters plus a null termination character.
  597. //
  598. ResultantString->Length = 0;
  599. ResultantString->MaximumLength = 11 * sizeof(WCHAR); // 8 digits, a 0x, & null termination
  600. ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  601. ResultantString->MaximumLength);
  602. if (ResultantString->Buffer == NULL) {
  603. return(STATUS_NO_MEMORY);
  604. }
  605. ResultantString->Buffer[0] = L'0';
  606. ResultantString->Buffer[1] = L'x';
  607. ResultantString->Buffer += 2;
  608. Status = RtlIntegerToUnicodeString( Value, 16, ResultantString );
  609. ASSERT(NT_SUCCESS(Status));
  610. //
  611. // Subtract off the two
  612. //
  613. ResultantString->Buffer -= 2;
  614. ResultantString->Length += 2 * sizeof(WCHAR);
  615. (*FreeWhenDone) = TRUE;
  616. return(STATUS_SUCCESS);
  617. }
  618. NTSTATUS
  619. LsapAdtBuildPtrString(
  620. IN PVOID Value,
  621. OUT PUNICODE_STRING ResultantString,
  622. OUT PBOOLEAN FreeWhenDone
  623. )
  624. /*++
  625. Routine Description:
  626. This function builds a unicode string representing the passed pointer.
  627. The resultant string will be formatted as a hexidecimal value.
  628. Arguments:
  629. Value - The value to be transformed to printable format (Unicode string).
  630. ResultantString - Points to the unicode string header. The body of this
  631. unicode string will be set to point to the resultant output value
  632. if successful. Otherwise, the Buffer field of this parameter
  633. will be set to NULL.
  634. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  635. must be freed to process heap when no longer needed.
  636. Return Values:
  637. STATUS_NO_MEMORY - indicates memory could not be allocated
  638. for the string body.
  639. All other Result Codes are generated by called routines.
  640. --*/
  641. {
  642. NTSTATUS Status = STATUS_SUCCESS;
  643. USHORT NumChars;
  644. ResultantString->Length = 0;
  645. //
  646. // Maximum length: 0x + 16 digit hex + null + 1 bonus == 20 chars
  647. //
  648. ResultantString->MaximumLength = 20 * sizeof(WCHAR);
  649. ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  650. ResultantString->MaximumLength);
  651. if (ResultantString->Buffer == NULL) {
  652. Status = STATUS_NO_MEMORY;
  653. } else {
  654. NumChars = (USHORT) wsprintf( ResultantString->Buffer, L"0x%p", Value );
  655. ResultantString->Length = NumChars * sizeof(WCHAR);
  656. (*FreeWhenDone) = TRUE;
  657. }
  658. return Status;
  659. }
  660. NTSTATUS
  661. LsapAdtBuildLuidString(
  662. IN PLUID Value,
  663. OUT PUNICODE_STRING ResultantString,
  664. OUT PBOOLEAN FreeWhenDone
  665. )
  666. /*++
  667. Routine Description:
  668. This function builds a unicode string representing the passed LUID.
  669. The resultant string will be formatted as follows:
  670. (0x00005678,0x12340000)
  671. Arguments:
  672. Value - The value to be transformed to printable format (Unicode string).
  673. ResultantString - Points to the unicode string header. The body of this
  674. unicode string will be set to point to the resultant output value
  675. if successful. Otherwise, the Buffer field of this parameter
  676. will be set to NULL.
  677. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  678. must be freed to process heap when no longer needed.
  679. Return Values:
  680. STATUS_NO_MEMORY - indicates memory could not be allocated
  681. for the string body.
  682. All other Result Codes are generated by called routines.
  683. --*/
  684. {
  685. NTSTATUS Status;
  686. UNICODE_STRING IntegerString;
  687. ULONG Buffer[(16*sizeof(WCHAR))/sizeof(ULONG)];
  688. IntegerString.Buffer = (PWCHAR)&Buffer[0];
  689. IntegerString.MaximumLength = 16*sizeof(WCHAR);
  690. //
  691. // Length (in WCHARS) is 3 for (0x
  692. // 10 for 1st hex number
  693. // 3 for ,0x
  694. // 10 for 2nd hex number
  695. // 1 for )
  696. // 1 for null termination
  697. //
  698. ResultantString->Length = 0;
  699. ResultantString->MaximumLength = 28 * sizeof(WCHAR);
  700. ResultantString->Buffer = RtlAllocateHeap( RtlProcessHeap(), 0,
  701. ResultantString->MaximumLength);
  702. if (ResultantString->Buffer == NULL) {
  703. return(STATUS_NO_MEMORY);
  704. }
  705. Status = RtlAppendUnicodeToString( ResultantString, L"(0x" );
  706. ASSERT(NT_SUCCESS(Status));
  707. Status = RtlIntegerToUnicodeString( Value->HighPart, 16, &IntegerString );
  708. ASSERT(NT_SUCCESS(Status));
  709. Status = RtlAppendUnicodeToString( ResultantString, IntegerString.Buffer );
  710. ASSERT(NT_SUCCESS(Status));
  711. Status = RtlAppendUnicodeToString( ResultantString, L",0x" );
  712. ASSERT(NT_SUCCESS(Status));
  713. Status = RtlIntegerToUnicodeString( Value->LowPart, 16, &IntegerString );
  714. ASSERT(NT_SUCCESS(Status));
  715. Status = RtlAppendUnicodeToString( ResultantString, IntegerString.Buffer );
  716. ASSERT(NT_SUCCESS(Status));
  717. Status = RtlAppendUnicodeToString( ResultantString, L")" );
  718. ASSERT(NT_SUCCESS(Status));
  719. (*FreeWhenDone) = TRUE;
  720. return(STATUS_SUCCESS);
  721. }
  722. NTSTATUS
  723. LsapAdtBuildSidString(
  724. IN PSID Value,
  725. OUT PUNICODE_STRING ResultantString,
  726. OUT PBOOLEAN FreeWhenDone
  727. )
  728. /*++
  729. Routine Description:
  730. This function builds a unicode string representing the passed LUID.
  731. The resultant string will be formatted as follows:
  732. S-1-281736-12-72-9-110
  733. ^ ^^ ^^ ^ ^^^
  734. | | | | |
  735. +-----+--+-+--+---- Decimal
  736. Arguments:
  737. Value - The value to be transformed to printable format (Unicode string).
  738. ResultantString - Points to the unicode string header. The body of this
  739. unicode string will be set to point to the resultant output value
  740. if successful. Otherwise, the Buffer field of this parameter
  741. will be set to NULL.
  742. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  743. must be freed to process heap when no longer needed.
  744. Return Values:
  745. STATUS_NO_MEMORY - indicates memory could not be allocated
  746. for the string body.
  747. All other Result Codes are generated by called routines.
  748. --*/
  749. {
  750. NTSTATUS Status=STATUS_NO_MEMORY;
  751. LPWSTR UniBuffer=NULL;
  752. USHORT Len;
  753. USHORT MaxLen;
  754. *FreeWhenDone = FALSE;
  755. //
  756. // Note: RtlConvertSidToUnicodeString also uses a hard-coded const 256
  757. // to generate the string SID.
  758. //
  759. MaxLen = (256+3) * sizeof(WCHAR);
  760. UniBuffer = LsapAllocateLsaHeap(MaxLen);
  761. if (UniBuffer)
  762. {
  763. ResultantString->Buffer = UniBuffer+2;
  764. ResultantString->MaximumLength = MaxLen;
  765. Status = RtlConvertSidToUnicodeString( ResultantString, Value, FALSE );
  766. if (Status == STATUS_SUCCESS)
  767. {
  768. *FreeWhenDone = TRUE;
  769. UniBuffer[0] = L'%';
  770. UniBuffer[1] = L'{';
  771. Len = ResultantString->Length / sizeof(WCHAR);
  772. UniBuffer[Len+2] = L'}';
  773. UniBuffer[Len+3] = UNICODE_NULL;
  774. ResultantString->Buffer = UniBuffer;
  775. ResultantString->Length = (Len+3)*sizeof(WCHAR);
  776. }
  777. else
  778. {
  779. LsapFreeLsaHeap(UniBuffer);
  780. }
  781. }
  782. return(Status);
  783. }
  784. NTSTATUS
  785. LsapAdtBuildDashString(
  786. OUT PUNICODE_STRING ResultantString,
  787. OUT PBOOLEAN FreeWhenDone
  788. )
  789. /*++
  790. Routine Description:
  791. This function returns a string containing a dash ("-").
  792. This is commonly used to represent "No value" in audit records.
  793. Arguments:
  794. ResultantString - Points to the unicode string header. The body of this
  795. unicode string will be set to point to the resultant output value
  796. if successful. Otherwise, the Buffer field of this parameter
  797. will be set to NULL.
  798. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  799. must be freed to process heap when no longer needed.
  800. Return Values:
  801. STATUS_SUCCESS only.
  802. --*/
  803. {
  804. RtlInitUnicodeString(ResultantString, L"-");
  805. (*FreeWhenDone) = FALSE;
  806. return STATUS_SUCCESS;
  807. }
  808. NTSTATUS
  809. LsapAdtBuildFilePathString(
  810. IN PUNICODE_STRING Value,
  811. OUT PUNICODE_STRING ResultantString,
  812. OUT PBOOLEAN FreeWhenDone
  813. )
  814. /*++
  815. Routine Description:
  816. This function builds a unicode string representing the passed file
  817. path name. If possible, the string will be generated using drive
  818. letters instead of object architecture namespace.
  819. Arguments:
  820. Value - The original file path name. This is expected (but does not
  821. have to be) a standard NT object architecture name-space pathname.
  822. ResultantString - Points to the unicode string header. The body of this
  823. unicode string will be set to point to the resultant output value
  824. if successful. Otherwise, the Buffer field of this parameter
  825. will be set to NULL.
  826. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  827. must be freed to process heap when no longer needed.
  828. Return Values:
  829. STATUS_NO_MEMORY - indicates memory could not be allocated
  830. for the string body.
  831. All other Result Codes are generated by called routines.
  832. --*/
  833. {
  834. NTSTATUS Status = STATUS_SUCCESS;
  835. //
  836. // For now, don't do the conversion.
  837. // Do this if we have time before we ship.
  838. //
  839. ResultantString->Length = Value->Length;
  840. ResultantString->Buffer = Value->Buffer;
  841. ResultantString->MaximumLength = Value->MaximumLength;
  842. (*FreeWhenDone) = FALSE;
  843. return(Status);
  844. }
  845. NTSTATUS
  846. LsapAdtBuildLogonIdStrings(
  847. IN PLUID LogonId,
  848. OUT PUNICODE_STRING ResultantString1,
  849. OUT PBOOLEAN FreeWhenDone1,
  850. OUT PUNICODE_STRING ResultantString2,
  851. OUT PBOOLEAN FreeWhenDone2,
  852. OUT PUNICODE_STRING ResultantString3,
  853. OUT PBOOLEAN FreeWhenDone3
  854. )
  855. /*++
  856. Routine Description:
  857. This function builds a 3 unicode strings representing the specified
  858. logon ID. These strings will contain the username, domain, and
  859. LUID string of the specified logon session (respectively).
  860. Arguments:
  861. Value - The logon ID.
  862. ResultantString1 - Points to the unicode string header. The body of this
  863. unicode string will be set to point to the resultant output value
  864. if successful. Otherwise, the Buffer field of this parameter
  865. will be set to NULL.
  866. This parameter will contain the username.
  867. FreeWhenDone1 - If TRUE, indicates that the body of ResultantString1
  868. must be freed to process heap when no longer needed.
  869. ResultantString2 - Points to the unicode string header. The body of this
  870. unicode string will be set to point to the resultant output value
  871. if successful. Otherwise, the Buffer field of this parameter
  872. will be set to NULL.
  873. This parameter will contain the username.
  874. FreeWhenDone2 - If TRUE, indicates that the body of ResultantString2
  875. must be freed to process heap when no longer needed.
  876. ResultantString3 - Points to the unicode string header. The body of this
  877. unicode string will be set to point to the resultant output value
  878. if successful. Otherwise, the Buffer field of this parameter
  879. will be set to NULL.
  880. This parameter will contain the username.
  881. FreeWhenDone3 - If TRUE, indicates that the body of ResultantString3
  882. must be freed to process heap when no longer needed.
  883. Return Values:
  884. STATUS_NO_MEMORY - indicates memory could not be allocated
  885. for the string body.
  886. All other Result Codes are generated by called routines.
  887. --*/
  888. {
  889. NTSTATUS Status;
  890. UNICODE_STRING DashString;
  891. BOOLEAN FreeDash;
  892. //
  893. // Try to convert the LUID first.
  894. //
  895. Status= LsapAdtBuildDashString(
  896. &DashString,
  897. &FreeDash
  898. );
  899. if ( !NT_SUCCESS( Status )) {
  900. return( Status );
  901. }
  902. Status = LsapAdtBuildLuidString( LogonId, ResultantString3, FreeWhenDone3 );
  903. if (NT_SUCCESS(Status)) {
  904. // *ResultantString1 = DashString;
  905. // *ResultantString2 = DashString;
  906. *FreeWhenDone1 = FALSE;
  907. *FreeWhenDone2 = FALSE;
  908. //
  909. // Now get the username and domain names
  910. //
  911. Status = LsapGetLogonSessionAccountInfo( LogonId,
  912. ResultantString1,
  913. ResultantString2
  914. );
  915. if (NT_SUCCESS(Status)) {
  916. // (*FreeWhenDone1) = TRUE;
  917. // (*FreeWhenDone2) = TRUE;
  918. } else {
  919. //
  920. // The LUID may be the system LUID
  921. //
  922. LUID SystemLuid = SYSTEM_LUID;
  923. if ( RtlEqualLuid( LogonId, &SystemLuid )) {
  924. RtlInitUnicodeString(ResultantString1, L"SYSTEM");
  925. RtlInitUnicodeString(ResultantString2, L"SYSTEM");
  926. (*FreeWhenDone1) = FALSE;
  927. (*FreeWhenDone2) = FALSE;
  928. Status = STATUS_SUCCESS;
  929. } else {
  930. //
  931. // We have no clue what this is, just free what we've
  932. // allocated.
  933. //
  934. if ((FreeWhenDone3)) {
  935. LsapFreeLsaHeap( ResultantString3->Buffer );
  936. }
  937. }
  938. }
  939. }
  940. return(Status);
  941. }
  942. ////////////////////////////////////////////////////////////////////////
  943. // //
  944. // Services private to this module. //
  945. // //
  946. ////////////////////////////////////////////////////////////////////////
  947. //
  948. // Define this routine only for user mode test
  949. //
  950. NTSTATUS
  951. LsapGetLogonSessionAccountInfo(
  952. IN PLUID Value,
  953. OUT PUNICODE_STRING AccountName,
  954. OUT PUNICODE_STRING AuthorityName
  955. )
  956. {
  957. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  958. HRESULT hr;
  959. SECURITY_USER_DATA* pUserData;
  960. hr = GetSecurityUserInfo( Value, 0, &pUserData );
  961. if (SUCCEEDED(hr))
  962. {
  963. Status = STATUS_SUCCESS;
  964. *AccountName = pUserData->UserName;
  965. *AuthorityName = pUserData->LogonDomainName;
  966. }
  967. return(Status);
  968. }
  969. // ======================================================================
  970. // from adtobjs.c
  971. // ======================================================================
  972. #define LSAP_ADT_OBJECT_TYPE_STRINGS 10
  973. #define LSAP_ADT_ACCESS_NAME_FORMATTING L"\r\n\t\t\t"
  974. #define LSAP_ADT_ACCESS_NAME_FORMATTING_TAB L"\t"
  975. #define LSAP_ADT_ACCESS_NAME_FORMATTING_NL L"\r\n"
  976. UNICODE_STRING LsapAdtEventIdStringDelete,
  977. LsapAdtEventIdStringReadControl,
  978. LsapAdtEventIdStringWriteDac,
  979. LsapAdtEventIdStringWriteOwner,
  980. LsapAdtEventIdStringSynchronize,
  981. LsapAdtEventIdStringAccessSysSec,
  982. LsapAdtEventIdStringMaxAllowed,
  983. LsapAdtEventIdStringSpecific[16];
  984. #define LsapAdtSourceModuleLock() 0
  985. #define LsapAdtSourceModuleUnlock() 0
  986. //
  987. // Each event source is represented by a source module descriptor.
  988. // These are kept on a linked list (LsapAdtSourceModules).
  989. //
  990. typedef struct _LSAP_ADT_OBJECT {
  991. //
  992. // Pointer to next source module descriptor
  993. // This is assumed to be the first field in the structure.
  994. //
  995. struct _LSAP_ADT_OBJECT *Next;
  996. //
  997. // Name of object
  998. //
  999. UNICODE_STRING Name;
  1000. //
  1001. // Base offset of specific access types
  1002. //
  1003. ULONG BaseOffset;
  1004. } LSAP_ADT_OBJECT, *PLSAP_ADT_OBJECT;
  1005. //
  1006. // Each event source is represented by a source module descriptor.
  1007. // These are kept on a linked list (LsapAdtSourceModules).
  1008. //
  1009. typedef struct _LSAP_ADT_SOURCE {
  1010. //
  1011. // Pointer to next source module descriptor
  1012. // This is assumed to be the first field in the structure.
  1013. //
  1014. struct _LSAP_ADT_SOURCE *Next;
  1015. //
  1016. // Name of source module
  1017. //
  1018. UNICODE_STRING Name;
  1019. //
  1020. // list of objects
  1021. //
  1022. PLSAP_ADT_OBJECT Objects;
  1023. } LSAP_ADT_SOURCE, *PLSAP_ADT_SOURCE;
  1024. PLSAP_ADT_SOURCE LsapAdtSourceModules;
  1025. NTSTATUS
  1026. LsapDsGuidToString(
  1027. IN GUID *ObjectType,
  1028. IN PUNICODE_STRING UnicodeString
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This routine converts a GUID to a string. The GUID is one of the following:
  1033. Class Guid indicating the class of an object.
  1034. Property Set Guid identifying a property set.
  1035. Property Guid identifying a property.
  1036. In each case, the routine returns a text string naming the object/property
  1037. set or property.
  1038. If the passed in GUID is cannot be found in the schema,
  1039. the GUID will simply be converted to a text string.
  1040. Arguments:
  1041. ObjectType - Specifies the GUID to translate.
  1042. UnicodeString - Returns the text string.
  1043. Return Values:
  1044. STATUS_NO_MEMORY - Not enough memory to allocate string.
  1045. --*/
  1046. {
  1047. NTSTATUS Status;
  1048. RPC_STATUS RpcStatus;
  1049. LPWSTR GuidString = NULL;
  1050. ULONG GuidStringSize;
  1051. ULONG GuidStringLen;
  1052. LPWSTR LocalGuidString;
  1053. //
  1054. // Convert the GUID to text
  1055. //
  1056. RpcStatus = UuidToStringW( ObjectType,
  1057. &GuidString );
  1058. if ( RpcStatus != RPC_S_OK ) {
  1059. Status = STATUS_NO_MEMORY;
  1060. goto Cleanup;
  1061. }
  1062. GuidStringLen = wcslen( GuidString );
  1063. GuidStringSize = (GuidStringLen + 4) * sizeof(WCHAR);
  1064. LocalGuidString = LsapAllocateLsaHeap( GuidStringSize );
  1065. if ( LocalGuidString == NULL ) {
  1066. Status = STATUS_NO_MEMORY;
  1067. goto Cleanup;
  1068. }
  1069. LocalGuidString[0] = L'%';
  1070. LocalGuidString[1] = L'{';
  1071. RtlCopyMemory( &LocalGuidString[2], GuidString, GuidStringLen*sizeof(WCHAR) );
  1072. LocalGuidString[GuidStringLen+2] = L'}';
  1073. LocalGuidString[GuidStringLen+3] = L'\0';
  1074. RtlInitUnicodeString( UnicodeString, LocalGuidString );
  1075. Status = STATUS_SUCCESS;
  1076. Cleanup:
  1077. if ( GuidString != NULL ) {
  1078. RpcStringFreeW( &GuidString );
  1079. }
  1080. return Status;
  1081. }
  1082. NTSTATUS
  1083. LsapAdtAppendString(
  1084. OUT PUNICODE_STRING ResultantString,
  1085. OUT PBOOLEAN FreeWhenDone,
  1086. IN PUNICODE_STRING StringToAppend,
  1087. IN PULONG StringIndex
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. This function appends a string to the next available of the LSAP_ADT_OBJECT_TYPE_STRINGS unicode
  1092. output strings.
  1093. Arguments:
  1094. ResultantString - Points to an array of LSAP_ADT_OBJECT_TYPE_STRINGS unicode string headers. The body of this
  1095. unicode string will be set to point to the resultant output value
  1096. if successful. Otherwise, the Buffer field of this parameter
  1097. will be set to NULL.
  1098. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  1099. must be freed to process heap when no longer needed.
  1100. StringToAppend - String to be appended to ResultantString.
  1101. StringIndex - Index to the current ResultantString to be used.
  1102. Passes in an index to the resultant string to use.
  1103. Passes out the index to the resultant string being used.
  1104. Return Values:
  1105. STATUS_NO_MEMORY - indicates memory could not be allocated
  1106. to store the object information.
  1107. All other Result Codes are generated by called routines.
  1108. --*/
  1109. {
  1110. NTSTATUS Status;
  1111. UNICODE_STRING SourceString;
  1112. ULONG Index;
  1113. // Must be multiple of sizeof(WCHAR)
  1114. #define ADT_MAX_STRING 0xFFFE
  1115. //
  1116. // Initialization.
  1117. //
  1118. SourceString = *StringToAppend;
  1119. Index = *StringIndex;
  1120. //
  1121. // If all of the strings are already full,
  1122. // early out.
  1123. //
  1124. if ( Index >= LSAP_ADT_OBJECT_TYPE_STRINGS ) {
  1125. return STATUS_SUCCESS;
  1126. }
  1127. //
  1128. // Loop until the source string is completely appended.
  1129. //
  1130. while ( SourceString.Length ) {
  1131. //
  1132. // If the destination string has room,
  1133. // append to it.
  1134. //
  1135. if ( FreeWhenDone[Index] && ResultantString[Index].Length != ADT_MAX_STRING ){
  1136. UNICODE_STRING SubString;
  1137. USHORT RoomLeft;
  1138. //
  1139. // If the Source String is a replacement string,
  1140. // make sure we don't split it across a ResultantString boundary
  1141. //
  1142. RoomLeft = ResultantString[Index].MaximumLength -
  1143. ResultantString[Index].Length;
  1144. if ( SourceString.Buffer[0] != L'%' ||
  1145. RoomLeft >= SourceString.Length ) {
  1146. //
  1147. // Compute the substring that fits.
  1148. //
  1149. SubString.Length = min( RoomLeft, SourceString.Length );
  1150. SubString.Buffer = SourceString.Buffer;
  1151. SourceString.Length -= SubString.Length;
  1152. SourceString.Buffer = (LPWSTR)(((LPBYTE)SourceString.Buffer) + SubString.Length);
  1153. //
  1154. // Append the substring onto the destination.
  1155. //
  1156. Status = RtlAppendUnicodeStringToString(
  1157. &ResultantString[Index],
  1158. &SubString );
  1159. ASSERT(NT_SUCCESS(Status));
  1160. }
  1161. }
  1162. //
  1163. // If there's more to copy,
  1164. // grow the buffer.
  1165. //
  1166. if ( SourceString.Length ) {
  1167. ULONG NewSize;
  1168. LPWSTR NewBuffer;
  1169. //
  1170. // If the current buffer is full,
  1171. // move to the next buffer.
  1172. //
  1173. if ( ResultantString[Index].Length == ADT_MAX_STRING ) {
  1174. //
  1175. // If ALL of the buffers are full,
  1176. // silently return to the caller.
  1177. //
  1178. Index ++;
  1179. if ( Index >= LSAP_ADT_OBJECT_TYPE_STRINGS ) {
  1180. *StringIndex = Index;
  1181. return STATUS_SUCCESS;
  1182. }
  1183. }
  1184. //
  1185. // Allocate a buffer suitable for both the old string and the new one.
  1186. //
  1187. // Allocate the buffer at least large enough for the new string.
  1188. // Always grow the buffer in 1Kb chunks.
  1189. // Don't allocate larger than the maximum allowed size.
  1190. //
  1191. NewSize = max( ResultantString[Index].MaximumLength + 1024,
  1192. SourceString.Length );
  1193. NewSize = min( NewSize, ADT_MAX_STRING );
  1194. NewBuffer = LsapAllocateLsaHeap( NewSize );
  1195. if ( NewBuffer == NULL ) {
  1196. *StringIndex = Index;
  1197. return STATUS_NO_MEMORY;
  1198. }
  1199. //
  1200. // Copy the old buffer into the new buffer.
  1201. //
  1202. if ( ResultantString[Index].Buffer != NULL ) {
  1203. RtlCopyMemory( NewBuffer,
  1204. ResultantString[Index].Buffer,
  1205. ResultantString[Index].Length );
  1206. if ( FreeWhenDone[Index] ) {
  1207. LsapFreeLsaHeap( ResultantString[Index].Buffer );
  1208. }
  1209. }
  1210. ResultantString[Index].Buffer = NewBuffer;
  1211. ResultantString[Index].MaximumLength = (USHORT) NewSize;
  1212. FreeWhenDone[Index] = TRUE;
  1213. }
  1214. }
  1215. *StringIndex = Index;
  1216. return STATUS_SUCCESS;
  1217. }
  1218. NTSTATUS
  1219. LsapAdtAppendZString(
  1220. OUT PUNICODE_STRING ResultantString,
  1221. OUT PBOOLEAN FreeWhenDone,
  1222. IN LPWSTR StringToAppend,
  1223. IN PULONG StringIndex
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. Same as LsapAdpAppendString but takes a zero terminated string.
  1228. Arguments:
  1229. Same as LsapAdpAppendString but takes a zero terminated string.
  1230. Return Values:
  1231. STATUS_NO_MEMORY - indicates memory could not be allocated
  1232. to store the object information.
  1233. All other Result Codes are generated by called routines.
  1234. --*/
  1235. {
  1236. UNICODE_STRING UnicodeString;
  1237. RtlInitUnicodeString( &UnicodeString, StringToAppend );
  1238. return LsapAdtAppendString( ResultantString,
  1239. FreeWhenDone,
  1240. &UnicodeString,
  1241. StringIndex );
  1242. }
  1243. ULONG
  1244. __cdecl
  1245. CompareObjectTypes(
  1246. const void * Param1,
  1247. const void * Param2
  1248. )
  1249. /*++
  1250. Routine Description:
  1251. Qsort comparison routine for sorting an object type array by access mask.
  1252. --*/
  1253. {
  1254. const SE_ADT_OBJECT_TYPE *ObjectType1 = Param1;
  1255. const SE_ADT_OBJECT_TYPE *ObjectType2 = Param2;
  1256. return ObjectType1->AccessMask - ObjectType2->AccessMask;
  1257. }
  1258. NTSTATUS
  1259. LsapAdtBuildObjectTypeStrings(
  1260. IN PUNICODE_STRING SourceModule,
  1261. IN PUNICODE_STRING ObjectTypeName,
  1262. IN PSE_ADT_OBJECT_TYPE ObjectTypeList,
  1263. IN ULONG ObjectTypeCount,
  1264. OUT PUNICODE_STRING ResultantString,
  1265. OUT PBOOLEAN FreeWhenDone,
  1266. OUT PUNICODE_STRING NewObjectTypeName
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. This function builds a LSAP_ADT_OBJECT_TYPE_STRINGS unicode strings containing parameter
  1271. file replacement parameters (e.g. %%1043) and Object GUIDs separated by carriage
  1272. return and tab characters suitable for display via the event viewer.
  1273. The buffers returned by this routine must be deallocated when no
  1274. longer needed if FreeWhenDone is true.
  1275. Arguments:
  1276. SourceModule - The module (ala event viewer modules) defining the
  1277. object type.
  1278. ObjectTypeName - The type of object to which the access mask applies.
  1279. ObjectTypeList - List of objects being granted access.
  1280. ObjectTypeCount - Number of objects in ObjectTypeList.
  1281. ResultantString - Points to an array of LSAP_ADT_OBJECT_TYPE_STRINGS unicode string headers. The body of this
  1282. unicode string will be set to point to the resultant output value
  1283. if successful. Otherwise, the Buffer field of this parameter
  1284. will be set to NULL.
  1285. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  1286. must be freed to process heap when no longer needed.
  1287. NewObjectTypeName - Returns a new name for the object type if one is
  1288. available.
  1289. Return Values:
  1290. STATUS_NO_MEMORY - indicates memory could not be allocated
  1291. to store the object information.
  1292. All other Result Codes are generated by called routines.
  1293. --*/
  1294. {
  1295. NTSTATUS Status;
  1296. UNICODE_STRING LocalString;
  1297. LPWSTR GuidString;
  1298. UNICODE_STRING DsSourceName;
  1299. UNICODE_STRING DsObjectTypeName;
  1300. BOOLEAN LocalFreeWhenDone;
  1301. ULONG ResultantStringIndex = 0;
  1302. ULONG i;
  1303. ACCESS_MASK PreviousAccessMask;
  1304. ULONG Index;
  1305. BOOLEAN IsDs;
  1306. USHORT IndentLevel;
  1307. static LPWSTR Tabs[] =
  1308. {
  1309. L"\t",
  1310. L"\t\t",
  1311. L"\t\t\t",
  1312. L"\t\t\t\t"
  1313. };
  1314. USHORT cTabs = sizeof(Tabs) / sizeof(LPWSTR);
  1315. //
  1316. // Initialize all LSAP_ADT_OBJECT_TYPE_STRINGS buffers to empty strings
  1317. //
  1318. for ( i=0; i<LSAP_ADT_OBJECT_TYPE_STRINGS; i++ ) {
  1319. RtlInitUnicodeString( &ResultantString[i], L"" );
  1320. FreeWhenDone[i] = FALSE;
  1321. }
  1322. //
  1323. // If there are no objects,
  1324. // we're done.
  1325. //
  1326. if ( ObjectTypeCount == 0 ) {
  1327. return STATUS_SUCCESS;
  1328. }
  1329. //
  1330. // Determine if this entry is for the DS.
  1331. //
  1332. RtlInitUnicodeString( &DsSourceName, ACCESS_DS_SOURCE_W );
  1333. RtlInitUnicodeString( &DsObjectTypeName, ACCESS_DS_OBJECT_TYPE_NAME_W );
  1334. IsDs = RtlEqualUnicodeString( SourceModule, &DsSourceName, TRUE) &&
  1335. RtlEqualUnicodeString( ObjectTypeName, &DsObjectTypeName, TRUE);
  1336. //
  1337. // Group the objects with like access masks together.
  1338. // (Simply sort them).
  1339. //
  1340. qsort( ObjectTypeList,
  1341. ObjectTypeCount,
  1342. sizeof(SE_ADT_OBJECT_TYPE),
  1343. CompareObjectTypes );
  1344. //
  1345. // Loop through the objects outputting a line for each one.
  1346. //
  1347. PreviousAccessMask = ObjectTypeList[0].AccessMask -1;
  1348. for ( Index=0; Index<ObjectTypeCount; Index++ ) {
  1349. if ( IsDs &&
  1350. ObjectTypeList[Index].Level == ACCESS_OBJECT_GUID &&
  1351. NewObjectTypeName->Length == 0 ) {
  1352. (VOID) LsapDsGuidToString( &ObjectTypeList[Index].ObjectType,
  1353. NewObjectTypeName );
  1354. }
  1355. //
  1356. // If this entry simply represents the object itself,
  1357. // skip it.
  1358. if ( ObjectTypeList[Index].Flags & SE_ADT_OBJECT_ONLY ) {
  1359. continue;
  1360. }
  1361. //
  1362. // If this access mask is different than the one for the previous
  1363. // object,
  1364. // output a new copy of the access mask.
  1365. //
  1366. if ( ObjectTypeList[Index].AccessMask != PreviousAccessMask ) {
  1367. PreviousAccessMask = ObjectTypeList[Index].AccessMask;
  1368. if ( ObjectTypeList[Index].AccessMask == 0 ) {
  1369. RtlInitUnicodeString( &LocalString,
  1370. L"---" LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1371. LocalFreeWhenDone = FALSE;
  1372. } else {
  1373. //
  1374. // Build a string with the access mask in it.
  1375. //
  1376. Status = LsapAdtBuildAccessesString(
  1377. SourceModule,
  1378. ObjectTypeName,
  1379. ObjectTypeList[Index].AccessMask,
  1380. FALSE,
  1381. &LocalString,
  1382. &LocalFreeWhenDone );
  1383. if ( !NT_SUCCESS(Status) ) {
  1384. goto Cleanup;
  1385. }
  1386. }
  1387. //
  1388. // Append it to the output string.
  1389. //
  1390. Status = LsapAdtAppendString(
  1391. ResultantString,
  1392. FreeWhenDone,
  1393. &LocalString,
  1394. &ResultantStringIndex );
  1395. if ( LocalFreeWhenDone ) {
  1396. LsapFreeLsaHeap( LocalString.Buffer );
  1397. }
  1398. if ( !NT_SUCCESS(Status) ) {
  1399. goto Cleanup;
  1400. }
  1401. }
  1402. IndentLevel = ObjectTypeList[Index].Level;
  1403. if (IndentLevel >= cTabs) {
  1404. IndentLevel = cTabs-1;
  1405. }
  1406. //
  1407. // Indent the GUID.
  1408. //
  1409. Status = LsapAdtAppendZString(
  1410. ResultantString,
  1411. FreeWhenDone,
  1412. Tabs[IndentLevel],
  1413. &ResultantStringIndex );
  1414. if ( !NT_SUCCESS(Status) ) {
  1415. goto Cleanup;
  1416. }
  1417. //
  1418. // If this is the DS,
  1419. // convert the GUID to a name from the schema.
  1420. //
  1421. Status = LsapDsGuidToString( &ObjectTypeList[Index].ObjectType,
  1422. &LocalString );
  1423. if ( !NT_SUCCESS(Status) ) {
  1424. goto Cleanup;
  1425. }
  1426. //
  1427. // Append the GUID string to the output strings.
  1428. //
  1429. Status = LsapAdtAppendString(
  1430. ResultantString,
  1431. FreeWhenDone,
  1432. &LocalString,
  1433. &ResultantStringIndex );
  1434. LsapFreeLsaHeap( LocalString.Buffer );
  1435. if ( !NT_SUCCESS(Status) ) {
  1436. goto Cleanup;
  1437. }
  1438. //
  1439. // Put the GUID on a line by itself.
  1440. //
  1441. Status = LsapAdtAppendZString(
  1442. ResultantString,
  1443. FreeWhenDone,
  1444. LSAP_ADT_ACCESS_NAME_FORMATTING_NL,
  1445. &ResultantStringIndex );
  1446. if ( !NT_SUCCESS(Status) ) {
  1447. goto Cleanup;
  1448. }
  1449. }
  1450. Status = STATUS_SUCCESS;
  1451. Cleanup:
  1452. return Status;
  1453. }
  1454. NTSTATUS
  1455. LsapAdtBuildAccessesString(
  1456. IN PUNICODE_STRING SourceModule,
  1457. IN PUNICODE_STRING ObjectTypeName,
  1458. IN ACCESS_MASK Accesses,
  1459. IN BOOLEAN Indent,
  1460. OUT PUNICODE_STRING ResultantString,
  1461. OUT PBOOLEAN FreeWhenDone
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. This function builds a unicode string containing parameter
  1466. file replacement parameters (e.g. %%1043) separated by carriage
  1467. return and tab characters suitable for display via the event viewer.
  1468. The buffer returned by this routine must be deallocated when no
  1469. longer needed if FreeWhenDone is true.
  1470. NOTE: To enhance performance, each time a target source module
  1471. descriptor is found, it is moved to the beginning of the
  1472. source module list. This ensures frequently accessed source
  1473. modules are always near the front of the list.
  1474. Similarly, target object descriptors are moved to the front
  1475. of their lists when found. This further ensures high performance
  1476. by quicly locating
  1477. Arguments:
  1478. SourceModule - The module (ala event viewer modules) defining the
  1479. object type.
  1480. ObjectTypeName - The type of object to which the access mask applies.
  1481. Accesses - The access mask to be used in building the display string.
  1482. Indent - Access Mask should be indented.
  1483. ResultantString - Points to the unicode string header. The body of this
  1484. unicode string will be set to point to the resultant output value
  1485. if successful. Otherwise, the Buffer field of this parameter
  1486. will be set to NULL.
  1487. FreeWhenDone - If TRUE, indicates that the body of the ResultantString
  1488. must be freed to process heap when no longer needed.
  1489. Return Values:
  1490. STATUS_NO_MEMORY - indicates memory could not be allocated
  1491. to store the object information.
  1492. All other Result Codes are generated by called routines.
  1493. --*/
  1494. {
  1495. NTSTATUS Status = STATUS_SUCCESS;
  1496. ULONG AccessCount = 0;
  1497. ULONG BaseOffset;
  1498. ULONG i;
  1499. ACCESS_MASK Mask;
  1500. PLSAP_ADT_SOURCE Source;
  1501. PLSAP_ADT_SOURCE FoundSource = NULL;
  1502. PLSAP_ADT_OBJECT Object;
  1503. PLSAP_ADT_OBJECT FoundObject = NULL;
  1504. BOOLEAN Found;
  1505. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1506. printf("Module:\t%wS\n", SourceModule);
  1507. printf("\t Object:\t%wS\n", ObjectTypeName);
  1508. printf("\t Accesses:\t0x%lx\n", Accesses);
  1509. #endif
  1510. //
  1511. // If we have no accesses, return "-"
  1512. //
  1513. if (Accesses == 0) {
  1514. RtlInitUnicodeString( ResultantString, L"-" );
  1515. (*FreeWhenDone) = FALSE;
  1516. return(STATUS_SUCCESS);
  1517. }
  1518. //
  1519. // First figure out how large a buffer we need
  1520. //
  1521. Mask = Accesses;
  1522. //
  1523. // Count the number of set bits in the
  1524. // passed access mask.
  1525. //
  1526. while ( Mask != 0 ) {
  1527. Mask = Mask & (Mask - 1);
  1528. AccessCount++;
  1529. }
  1530. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1531. printf("\t \t%d bits set in mask.\n", AccessCount);
  1532. #endif
  1533. //
  1534. // We have accesses, allocate a string large enough to deal
  1535. // with them all. Strings will be of the format:
  1536. //
  1537. // %%nnnnnnnnnn\n\r\t\t%%nnnnnnnnnn\n\r\t\t ... %nnnnnnnnnn\n\r\t\t
  1538. //
  1539. // where nnnnnnnnnn - is a decimal number 10 digits long or less.
  1540. //
  1541. // So, a typical string will look like:
  1542. //
  1543. // %%601\n\r\t\t%%1604\n\r\t\t%%1608\n
  1544. //
  1545. // Since each such access may use at most:
  1546. //
  1547. // 10 (for the nnnnnnnnnn digit)
  1548. // + 2 (for %%)
  1549. // + 8 (for \n\t\t)
  1550. // --------------------------------
  1551. // 20 wide characters
  1552. //
  1553. // The total length of the output string will be:
  1554. //
  1555. // AccessCount (number of accesses)
  1556. // x 20 (size of each entry)
  1557. // -------------------------------------
  1558. // wchars
  1559. //
  1560. // Throw in 1 more WCHAR for null termination, and we are all set.
  1561. //
  1562. ResultantString->Length = 0;
  1563. ResultantString->MaximumLength = (USHORT)AccessCount * (20 * sizeof(WCHAR)) +
  1564. sizeof(WCHAR); //for the null termination
  1565. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1566. printf("\t \t%d byte buffer allocated.\n", ResultantString->MaximumLength);
  1567. #endif
  1568. ResultantString->Buffer = LsapAllocateLsaHeap( ResultantString->MaximumLength );
  1569. if (ResultantString->Buffer == NULL) {
  1570. return(STATUS_NO_MEMORY);
  1571. }
  1572. (*FreeWhenDone) = TRUE;
  1573. //
  1574. // Special case standard and special access types.
  1575. // Walk the lists for specific access types.
  1576. //
  1577. if (Accesses & STANDARD_RIGHTS_ALL) {
  1578. if (Accesses & DELETE) {
  1579. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1580. ASSERT( NT_SUCCESS( Status ));
  1581. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringDelete);
  1582. ASSERT( NT_SUCCESS( Status ));
  1583. if ( Indent ) {
  1584. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1585. } else {
  1586. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1587. }
  1588. ASSERT( NT_SUCCESS( Status ));
  1589. }
  1590. if (Accesses & READ_CONTROL) {
  1591. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1592. ASSERT( NT_SUCCESS( Status ));
  1593. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringReadControl);
  1594. ASSERT( NT_SUCCESS( Status ));
  1595. if ( Indent ) {
  1596. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1597. } else {
  1598. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1599. }
  1600. ASSERT( NT_SUCCESS( Status ));
  1601. }
  1602. if (Accesses & WRITE_DAC) {
  1603. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1604. ASSERT( NT_SUCCESS( Status ));
  1605. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringWriteDac);
  1606. ASSERT( NT_SUCCESS( Status ));
  1607. if ( Indent ) {
  1608. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1609. } else {
  1610. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1611. }
  1612. ASSERT( NT_SUCCESS( Status ));
  1613. }
  1614. if (Accesses & WRITE_OWNER) {
  1615. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1616. ASSERT( NT_SUCCESS( Status ));
  1617. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringWriteOwner);
  1618. ASSERT( NT_SUCCESS( Status ));
  1619. if ( Indent ) {
  1620. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1621. } else {
  1622. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1623. }
  1624. ASSERT( NT_SUCCESS( Status ));
  1625. }
  1626. if (Accesses & SYNCHRONIZE) {
  1627. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1628. ASSERT( NT_SUCCESS( Status ));
  1629. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringSynchronize);
  1630. ASSERT( NT_SUCCESS( Status ));
  1631. if ( Indent ) {
  1632. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1633. } else {
  1634. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1635. }
  1636. ASSERT( NT_SUCCESS( Status ));
  1637. }
  1638. }
  1639. if (Accesses & ACCESS_SYSTEM_SECURITY) {
  1640. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1641. ASSERT( NT_SUCCESS( Status ));
  1642. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringAccessSysSec);
  1643. ASSERT( NT_SUCCESS( Status ));
  1644. if ( Indent ) {
  1645. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1646. } else {
  1647. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1648. }
  1649. ASSERT( NT_SUCCESS( Status ));
  1650. }
  1651. if (Accesses & MAXIMUM_ALLOWED) {
  1652. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1653. ASSERT( NT_SUCCESS( Status ));
  1654. Status = RtlAppendUnicodeStringToString( ResultantString, &LsapAdtEventIdStringMaxAllowed);
  1655. ASSERT( NT_SUCCESS( Status ));
  1656. if ( Indent ) {
  1657. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1658. } else {
  1659. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1660. }
  1661. ASSERT( NT_SUCCESS( Status ));
  1662. }
  1663. //
  1664. // If there are any specific access bits set, then get
  1665. // the appropriate source module and object type base
  1666. // message ID offset. If there is no module-specific
  1667. // object definition, then use SE_ACCESS_NAME_SPECIFIC_0
  1668. // as the base.
  1669. //
  1670. if ((Accesses & SPECIFIC_RIGHTS_ALL) == 0) {
  1671. return(Status);
  1672. }
  1673. LsapAdtSourceModuleLock();
  1674. Source = (PLSAP_ADT_SOURCE)&LsapAdtSourceModules;
  1675. Found = FALSE;
  1676. while ((Source->Next != NULL) && !Found) {
  1677. if (RtlEqualUnicodeString(&Source->Next->Name, SourceModule, TRUE)) {
  1678. Found = TRUE;
  1679. FoundSource = Source->Next;
  1680. //
  1681. // Move to front of list of source modules.
  1682. //
  1683. Source->Next = FoundSource->Next; // Remove from list
  1684. FoundSource->Next = LsapAdtSourceModules; // point to first element
  1685. LsapAdtSourceModules = FoundSource; // Make it the first element
  1686. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1687. printf("\t \tModule Found.\n");
  1688. #endif
  1689. } else {
  1690. Source = Source->Next;
  1691. }
  1692. }
  1693. if (Found == TRUE) {
  1694. //
  1695. // Find the object
  1696. //
  1697. Object = (PLSAP_ADT_OBJECT)&(FoundSource->Objects);
  1698. Found = FALSE;
  1699. while ((Object->Next != NULL) && !Found) {
  1700. if (RtlEqualUnicodeString(&Object->Next->Name, ObjectTypeName, TRUE)) {
  1701. Found = TRUE;
  1702. FoundObject = Object->Next;
  1703. //
  1704. // Move to front of list of soure modules.
  1705. //
  1706. Object->Next = FoundObject->Next; // Remove from list
  1707. FoundObject->Next = FoundSource->Objects; // point to first element
  1708. FoundSource->Objects = FoundObject; // Make it the first element
  1709. } else {
  1710. Object = Object->Next;
  1711. }
  1712. }
  1713. }
  1714. //
  1715. // We are done playing with link fields of the source modules
  1716. // and objects. Free the lock.
  1717. //
  1718. LsapAdtSourceModuleUnlock();
  1719. //
  1720. // If we have found an object, use it as our base message
  1721. // ID. Otherwise, use SE_ACCESS_NAME_SPECIFIC_0.
  1722. //
  1723. if (Found) {
  1724. BaseOffset = FoundObject->BaseOffset;
  1725. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1726. printf("\t \tObject Found. Base Offset: 0x%lx\n", BaseOffset);
  1727. #endif
  1728. } else {
  1729. BaseOffset = SE_ACCESS_NAME_SPECIFIC_0;
  1730. #ifdef LSAP_ADT_TEST_DUMP_SOURCES
  1731. printf("\t \tObject NOT Found. Base Offset: 0x%lx\n", BaseOffset);
  1732. #endif
  1733. }
  1734. //
  1735. // At this point, we have a base offset (even if we had to use our
  1736. // default).
  1737. //
  1738. // Now cycle through the specific access bits and see which ones need
  1739. // to be added to ResultantString.
  1740. //
  1741. {
  1742. UNICODE_STRING IntegerString;
  1743. WCHAR IntegerStringBuffer[10]; //must be 10 wchar bytes long
  1744. ULONG NextBit;
  1745. IntegerString.Buffer = (PWSTR)IntegerStringBuffer;
  1746. IntegerString.MaximumLength = 10*sizeof(WCHAR);
  1747. IntegerString.Length = 0;
  1748. for ( i=0, NextBit=1 ; i<16 ; i++, NextBit <<= 1 ) {
  1749. //
  1750. // specific access flags are in the low-order bits of the mask
  1751. //
  1752. if ((NextBit & Accesses) != 0) {
  1753. //
  1754. // Found one - add it to ResultantString
  1755. //
  1756. Status = RtlIntegerToUnicodeString (
  1757. (BaseOffset + i),
  1758. 10, //Base
  1759. &IntegerString
  1760. );
  1761. if (NT_SUCCESS(Status)) {
  1762. Status = RtlAppendUnicodeToString( ResultantString, L"%%" );
  1763. ASSERT( NT_SUCCESS( Status ));
  1764. Status = RtlAppendUnicodeStringToString( ResultantString, &IntegerString);
  1765. ASSERT( NT_SUCCESS( Status ));
  1766. if ( Indent ) {
  1767. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING );
  1768. } else {
  1769. Status = RtlAppendUnicodeToString( ResultantString, LSAP_ADT_ACCESS_NAME_FORMATTING_NL );
  1770. }
  1771. ASSERT( NT_SUCCESS( Status ));
  1772. }
  1773. }
  1774. }
  1775. }
  1776. return(Status);
  1777. //ErrorAfterAlloc:
  1778. //
  1779. // LsapFreeLsaHeap( ResultantString->Buffer );
  1780. // ResultantString->Buffer = NULL;
  1781. // (*FreeWhenDone) = FALSE;
  1782. // return(Status);
  1783. }
  1784. // ======================================================================
  1785. // dbpriv.c
  1786. // ======================================================================
  1787. NTSTATUS
  1788. LsapBuildPrivilegeAuditString(
  1789. IN PPRIVILEGE_SET PrivilegeSet,
  1790. OUT PUNICODE_STRING ResultantString,
  1791. OUT PBOOLEAN FreeWhenDone
  1792. )
  1793. {
  1794. NTSTATUS Status = STATUS_SUCCESS;
  1795. UNICODE_STRING DashString;
  1796. BOOLEAN FreeDash;
  1797. Status= LsapAdtBuildDashString(
  1798. &DashString,
  1799. &FreeDash
  1800. );
  1801. if ( !NT_SUCCESS( Status )) {
  1802. return( Status );
  1803. }
  1804. *ResultantString = DashString;
  1805. *FreeWhenDone = FALSE;
  1806. return Status;
  1807. }
  1808. NTSTATUS
  1809. LsapAdtWriteLog(
  1810. IN PSE_ADT_PARAMETER_ARRAY AuditParameters OPTIONAL,
  1811. IN ULONG Options
  1812. )
  1813. {
  1814. return LsapAdtDemarshallAuditInfo( AuditParameters );
  1815. }
  1816. BOOLEAN
  1817. LsapAdtIsAuditingEnabledForCategory(
  1818. IN POLICY_AUDIT_EVENT_TYPE AuditCategory,
  1819. IN UINT AuditEventType
  1820. )
  1821. {
  1822. return TRUE;
  1823. }
  1824. VOID
  1825. LsapAuditFailed(
  1826. IN NTSTATUS AuditStatus
  1827. )
  1828. {
  1829. UNREFERENCED_PARAMETER(AuditStatus);
  1830. }
  1831. #endif // !defined(lint)