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.

833 lines
25 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <time.h>
  7. #include <windows.h>
  8. #define QuadAlign(n) (((n) + (sizeof(LONGLONG) - 1)) & ~(sizeof(LONGLONG) - 1))
  9. #define DwordAlign(n)(((n) + (sizeof(ULONG) - 1)) & ~(sizeof(ULONG) - 1))
  10. #define STRUCT_COUNT(n, type, name_length) \
  11. ((((n) * QuadAlign(sizeof(type)) + ((name_length) * sizeof(WCHAR))) + \
  12. sizeof(type) - 1) / \
  13. sizeof(type))
  14. #define SID_MAX_LENGTH \
  15. (FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES)
  16. #define DISK_EVENT_MODULE "System"
  17. #define IO_FILE_QUOTA_THRESHOLD ((NTSTATUS)0x40040024L)
  18. #define IO_FILE_QUOTA_LIMIT ((NTSTATUS)0x80040025L)
  19. VOID
  20. DumpQuota (
  21. IN PFILE_QUOTA_INFORMATION pfqi,
  22. IN PCHAR SeverName
  23. );
  24. CHAR *
  25. FileTimeToString(
  26. FILETIME *pft
  27. );
  28. VOID
  29. PrintError(
  30. ULONG ErrorCode
  31. );
  32. VOID
  33. Usage();
  34. BOOLEAN QuickSid;
  35. VOID
  36. STDMETHODVCALLTYPE
  37. main(
  38. int Argc,
  39. char *Argv[]
  40. )
  41. {
  42. HANDLE FileHandle;
  43. NTSTATUS Status;
  44. OBJECT_ATTRIBUTES ObjectAttributes;
  45. ANSI_STRING DiskName;
  46. UNICODE_STRING NameString;
  47. IO_STATUS_BLOCK IoStatus;
  48. ULONG BufferSize;
  49. ULONG SidListLength;
  50. LONG i;
  51. PWCHAR Wstr;
  52. PEVENTLOGRECORD EventLogRecord;
  53. FILE_QUOTA_INFORMATION QuotaInfo[STRUCT_COUNT(10, FILE_QUOTA_INFORMATION, 4)];
  54. FILE_QUOTA_INFORMATION TempQuotaInfo[STRUCT_COUNT(1, FILE_QUOTA_INFORMATION, 32)];
  55. FILE_GET_QUOTA_INFORMATION SidList[STRUCT_COUNT(10, FILE_GET_QUOTA_INFORMATION, 4)];
  56. PFILE_GET_QUOTA_INFORMATION SidListPtr;
  57. PFILE_QUOTA_INFORMATION QuotaInfoPtr;
  58. FILE_FS_CONTROL_INFORMATION ControlInfo;
  59. FILE_FS_CONTROL_INFORMATION TempControlInfo;
  60. PCHAR ServerName = NULL;
  61. SID_NAME_USE SidNameUse;
  62. LARGE_INTEGER TempLargeInt;
  63. ULONG ErrorCode;
  64. ULONG DomainLength;
  65. CHAR Domain[100];
  66. PCHAR TempPtr;
  67. BOOLEAN UserGiven = 0;
  68. BOOLEAN DriveLetter = 0;
  69. BOOLEAN EventLog = 0;
  70. BOOLEAN SettingDefault = 0;
  71. BOOLEAN DefaultGiven = 0;
  72. BOOLEAN DeletingUser = 0;
  73. struct {
  74. UCHAR DefaultLimit : 1;
  75. UCHAR DefaultThreshold : 1;
  76. UCHAR Flags : 1;
  77. } DefaultFlags = { 0, 0, 0 };
  78. if (Argc < 2) {
  79. printf ( "Processor feature is %d\n", IsProcessorFeaturePresent(0));
  80. Usage();
  81. exit(1);
  82. }
  83. RtlZeroMemory(&QuotaInfo, sizeof(QuotaInfo));
  84. QuotaInfoPtr = QuotaInfo;
  85. RtlZeroMemory(&SidList, sizeof(SidList));
  86. SidListPtr = SidList;
  87. RtlInitString( &DiskName, "\\DosDevices\\d:\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION" );
  88. RtlAnsiStringToUnicodeString( &NameString, &DiskName, TRUE );
  89. // Look for the d and repleace it with the requested Argument.
  90. for (Wstr = NameString.Buffer; *Wstr != L'd'; Wstr++);
  91. for (i = 1; i < Argc; i++) {
  92. if (*Argv[i] != '-') {
  93. if (DriveLetter || !isalpha(*Argv[i])) {
  94. Usage();
  95. exit(1);
  96. }
  97. TempPtr = Argv[i];
  98. *Wstr = RtlAnsiCharToUnicodeChar( &TempPtr );
  99. DriveLetter++;
  100. continue;
  101. }
  102. switch (Argv[i][1]) {
  103. case 'd':
  104. DefaultGiven = 1;
  105. SettingDefault = 1;
  106. break;
  107. case 'e':
  108. if (EventLog) {
  109. Usage();
  110. exit(1);
  111. }
  112. if (Argv[i][2] == '\0') {
  113. i++;
  114. if (i < Argc && Argv[i][0] == '\\') {
  115. ServerName = Argv[i];
  116. }
  117. } else {
  118. ServerName = &Argv[i][2];
  119. }
  120. EventLog++;
  121. break;
  122. case 'u':
  123. QuotaInfoPtr = (PFILE_QUOTA_INFORMATION) ((PCHAR) QuotaInfoPtr +
  124. QuotaInfoPtr->NextEntryOffset);
  125. SidListPtr = (PFILE_GET_QUOTA_INFORMATION) ((PCHAR) SidListPtr +
  126. SidListPtr->NextEntryOffset);
  127. if (Argv[i][2] == '\0') {
  128. i++;
  129. if (i >= Argc) {
  130. printf("%s: Missing user name\n", Argv[0] );
  131. exit(1);
  132. }
  133. TempPtr = Argv[i];
  134. } else {
  135. TempPtr = Argv[i];
  136. TempPtr += 2;
  137. }
  138. QuotaInfoPtr->SidLength = SID_MAX_LENGTH;
  139. DomainLength = sizeof(Domain);
  140. if (!LookupAccountName( NULL,
  141. TempPtr,
  142. &QuotaInfoPtr->Sid,
  143. &QuotaInfoPtr->SidLength,
  144. Domain,
  145. &DomainLength,
  146. &SidNameUse)) {
  147. printf("%s: Bad acccount name %s. Error = %d\n",
  148. Argv[0],
  149. TempPtr,
  150. ErrorCode = GetLastError());
  151. PrintError( ErrorCode );
  152. exit(1);
  153. }
  154. //
  155. // Initialize the values to something resonable.
  156. //
  157. QuotaInfoPtr->QuotaThreshold.QuadPart = ~0I64;
  158. QuotaInfoPtr->QuotaLimit.QuadPart = ~0I64;
  159. QuotaInfoPtr->SidLength = RtlLengthSid( &QuotaInfoPtr->Sid);
  160. QuotaInfoPtr->NextEntryOffset =
  161. FIELD_OFFSET( FILE_QUOTA_INFORMATION, Sid ) +
  162. QuadAlign(QuotaInfoPtr->SidLength);
  163. memcpy( &SidListPtr->Sid, &QuotaInfoPtr->Sid, QuotaInfoPtr->SidLength);
  164. SidListPtr->SidLength = QuotaInfoPtr->SidLength;
  165. SidListPtr->NextEntryOffset =
  166. FIELD_OFFSET( FILE_GET_QUOTA_INFORMATION, Sid ) +
  167. QuadAlign(SidListPtr->SidLength);
  168. SettingDefault = 0;
  169. UserGiven++;
  170. break;
  171. case 't':
  172. if (Argv[i][2] == '\0') {
  173. i++;
  174. if (i >= Argc) {
  175. printf("%s: Missing Argument\n", Argv[0] );
  176. exit(1);
  177. }
  178. TempPtr = Argv[i];
  179. } else {
  180. TempPtr = Argv[i];
  181. TempPtr += 2;
  182. }
  183. if (!sscanf( TempPtr, "%I64i", &TempLargeInt)) {
  184. printf("%s: Missing threshold value\n", Argv[0] );
  185. exit(1);
  186. }
  187. if (SettingDefault) {
  188. ControlInfo.DefaultQuotaThreshold = TempLargeInt;
  189. DefaultFlags.DefaultThreshold = TRUE;
  190. } else {
  191. QuotaInfoPtr->QuotaThreshold = TempLargeInt;
  192. }
  193. break;
  194. case 'l':
  195. if (Argv[i][2] == '\0') {
  196. i++;
  197. if (i >= Argc) {
  198. printf("%s: Missing limit value\n", Argv[0] );
  199. exit(1);
  200. }
  201. TempPtr = Argv[i];
  202. } else {
  203. TempPtr = Argv[i];
  204. TempPtr += 2;
  205. }
  206. if (!sscanf( TempPtr, "%I64i", &TempLargeInt)) {
  207. printf("%s: Missing value\n", Argv[0] );
  208. exit(1);
  209. }
  210. if (SettingDefault) {
  211. ControlInfo.DefaultQuotaLimit = TempLargeInt;
  212. DefaultFlags.DefaultLimit = TRUE;
  213. } else {
  214. QuotaInfoPtr->QuotaLimit = TempLargeInt;
  215. if (TempLargeInt.QuadPart == -2i64) {
  216. DeletingUser = TRUE;
  217. }
  218. }
  219. break;
  220. case 'q':
  221. QuickSid++;
  222. break;
  223. case 'f':
  224. if (Argv[i][2] == '\0') {
  225. i++;
  226. if (i >= Argc) {
  227. printf("%s: Missing flag setting\n", Argv[0] );
  228. exit(1);
  229. }
  230. TempPtr = Argv[i];
  231. } else {
  232. TempPtr = Argv[i];
  233. TempPtr += 2;
  234. }
  235. switch (*TempPtr) {
  236. case 'e':
  237. ControlInfo.FileSystemControlFlags |= FILE_VC_QUOTA_ENFORCE;
  238. break;
  239. case 't':
  240. ControlInfo.FileSystemControlFlags |= FILE_VC_QUOTA_TRACK;
  241. break;
  242. case 'd':
  243. ControlInfo.FileSystemControlFlags &= ~(FILE_VC_QUOTA_MASK |
  244. FILE_VC_LOG_QUOTA_LIMIT |
  245. FILE_VC_LOG_QUOTA_THRESHOLD);
  246. break;
  247. default:
  248. printf("%s: Invalid or missing flag setting.\n", Argv[0] );
  249. Usage();
  250. exit(1);
  251. }
  252. while (*++TempPtr != '\0') {
  253. switch (*TempPtr) {
  254. case 'l':
  255. ControlInfo.FileSystemControlFlags |= FILE_VC_LOG_QUOTA_LIMIT;
  256. break;
  257. case 't':
  258. ControlInfo.FileSystemControlFlags |= FILE_VC_LOG_QUOTA_THRESHOLD;
  259. break;
  260. default:
  261. printf("%s: Invalid flag setting.\n", Argv[0] );
  262. Usage();
  263. exit(1);
  264. }
  265. }
  266. DefaultGiven = 1;
  267. DefaultFlags.Flags = TRUE;
  268. break;
  269. default:
  270. printf("%s: Invalid or missing flag setting.\n", Argv[0] );
  271. case '?':
  272. Usage();
  273. exit(1);
  274. break;
  275. }
  276. }
  277. if (DriveLetter == 0 && EventLog == 0 ) {
  278. printf("%s: Missing drive-letter\n", Argv[0] );
  279. }
  280. if (EventLog &&
  281. (DriveLetter || UserGiven)) {
  282. Usage();
  283. exit(1);
  284. }
  285. if (EventLog) {
  286. //
  287. // Open the event log and read andy events.
  288. //
  289. FileHandle = OpenEventLog( ServerName, DISK_EVENT_MODULE );
  290. if (FileHandle == NULL) {
  291. printf("%s: Event log open failed. %s. Error = %d\n",
  292. Argv[0],
  293. ServerName == NULL ? "Local machine" : ServerName,
  294. ErrorCode = GetLastError());
  295. PrintError( ErrorCode );
  296. exit(1);
  297. }
  298. while (ReadEventLog( FileHandle,
  299. EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ,
  300. 0,
  301. QuotaInfo,
  302. sizeof(QuotaInfo),
  303. &BufferSize,
  304. &i )) {
  305. if (BufferSize == 0) {
  306. break;
  307. }
  308. for (EventLogRecord = (PEVENTLOGRECORD) QuotaInfo;
  309. (PCHAR) EventLogRecord < (PCHAR) QuotaInfo + BufferSize;
  310. EventLogRecord = (PEVENTLOGRECORD)((PCHAR) EventLogRecord +
  311. EventLogRecord->Length)) {
  312. if (EventLogRecord->EventID == IO_FILE_QUOTA_THRESHOLD) {
  313. printf( "Quota threshold event at: %s",
  314. ctime( &EventLogRecord->TimeGenerated ));
  315. } else if (EventLogRecord->EventID == IO_FILE_QUOTA_LIMIT) {
  316. printf( "Quota limit event at: %s",
  317. ctime( &EventLogRecord->TimeGenerated ));
  318. } else {
  319. continue;
  320. }
  321. //
  322. // Look for the device name. It is the second string.
  323. //
  324. TempPtr = ((PCHAR) EventLogRecord +
  325. EventLogRecord->StringOffset);
  326. printf( " on device %s\n", TempPtr );
  327. TempPtr = ((PCHAR) EventLogRecord +
  328. EventLogRecord->DataOffset +
  329. FIELD_OFFSET( IO_ERROR_LOG_PACKET, DumpData ));
  330. //
  331. // Need to align the buffer.
  332. //
  333. RtlCopyMemory( TempQuotaInfo,
  334. TempPtr,
  335. EventLogRecord->DataLength -
  336. FIELD_OFFSET( IO_ERROR_LOG_PACKET, DumpData ));
  337. DumpQuota( TempQuotaInfo, ServerName );
  338. }
  339. }
  340. ErrorCode = GetLastError();
  341. if (ErrorCode =! ERROR_HANDLE_EOF) {
  342. printf("%s: Event log read failed. Error = %d\n",
  343. Argv[0],
  344. ErrorCode);
  345. PrintError( ErrorCode );
  346. }
  347. CloseEventLog( FileHandle );
  348. exit(0);
  349. }
  350. //
  351. // Terminate the list.
  352. //
  353. BufferSize = (PCHAR) QuotaInfoPtr - (PCHAR) QuotaInfo +
  354. QuotaInfoPtr->NextEntryOffset;
  355. QuotaInfoPtr->NextEntryOffset = 0;
  356. SidListLength = (PCHAR) SidListPtr - (PCHAR) SidList +
  357. SidListPtr->NextEntryOffset;
  358. SidListPtr->NextEntryOffset = 0;
  359. SidListPtr = SidList;
  360. InitializeObjectAttributes( &ObjectAttributes,
  361. &NameString,
  362. OBJ_CASE_INSENSITIVE,
  363. NULL,
  364. NULL );
  365. Status = NtOpenFile( &FileHandle,
  366. FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
  367. &ObjectAttributes,
  368. &IoStatus,
  369. FILE_SHARE_READ | FILE_SHARE_WRITE,
  370. FILE_SYNCHRONOUS_IO_ALERT | FILE_OPEN_FOR_BACKUP_INTENT);
  371. if (!NT_SUCCESS( Status )) {
  372. printf( "Error opening input file %S; error was: %lx\n", NameString.Buffer, Status );
  373. PrintError( Status );
  374. exit(1);
  375. }
  376. if (DefaultGiven) {
  377. Status = NtQueryVolumeInformationFile( FileHandle,
  378. &IoStatus,
  379. &TempControlInfo,
  380. sizeof( FILE_FS_CONTROL_INFORMATION ),
  381. FileFsControlInformation );
  382. if (!NT_SUCCESS( Status )) {
  383. printf( "Error NtQueryVolumeInformationFile; error was %lx\n", Status );
  384. PrintError( Status );
  385. exit(1);
  386. }
  387. if (DefaultFlags.Flags) {
  388. TempControlInfo.FileSystemControlFlags &= ~FILE_VC_QUOTA_MASK;
  389. TempControlInfo.FileSystemControlFlags |=
  390. ControlInfo.FileSystemControlFlags;
  391. }
  392. if (DefaultFlags.DefaultLimit) {
  393. TempControlInfo.DefaultQuotaLimit = ControlInfo.DefaultQuotaLimit;
  394. }
  395. if (DefaultFlags.DefaultThreshold) {
  396. TempControlInfo.DefaultQuotaThreshold = ControlInfo.DefaultQuotaThreshold;
  397. }
  398. Status = NtSetVolumeInformationFile( FileHandle,
  399. &IoStatus,
  400. &TempControlInfo,
  401. sizeof( FILE_FS_CONTROL_INFORMATION ),
  402. FileFsControlInformation );
  403. if (!NT_SUCCESS( Status )) {
  404. printf( "Error NtSetVolumeInformationFile; error was %lx\n", Status );
  405. PrintError( Status );
  406. exit(1);
  407. }
  408. }
  409. Status = NtQueryVolumeInformationFile( FileHandle,
  410. &IoStatus,
  411. &TempControlInfo,
  412. sizeof( FILE_FS_CONTROL_INFORMATION ),
  413. FileFsControlInformation );
  414. printf( "FileSystemControlFlags = %8lx\n", TempControlInfo.FileSystemControlFlags);
  415. if ((TempControlInfo.FileSystemControlFlags & FILE_VC_QUOTA_MASK) ==
  416. FILE_VC_QUOTA_NONE) {
  417. TempPtr = "Quotas are disabled on this volume";
  418. } else if ((TempControlInfo.FileSystemControlFlags & FILE_VC_QUOTA_MASK) ==
  419. FILE_VC_QUOTA_TRACK) {
  420. TempPtr = "Quota tracking is enabled on this volume";
  421. }else if (TempControlInfo.FileSystemControlFlags & FILE_VC_QUOTA_ENFORCE) {
  422. TempPtr = "Quota tracking and enforment is enabled on this volume";
  423. }
  424. printf("%s.\n", TempPtr);
  425. switch (TempControlInfo.FileSystemControlFlags &
  426. (FILE_VC_LOG_QUOTA_LIMIT | FILE_VC_LOG_QUOTA_THRESHOLD)) {
  427. case FILE_VC_LOG_QUOTA_LIMIT:
  428. printf("Logging enable for quota limits.\n");
  429. break;
  430. case FILE_VC_LOG_QUOTA_THRESHOLD:
  431. printf("Logging enable for quota thresholds.\n");
  432. break;
  433. case FILE_VC_LOG_QUOTA_LIMIT | FILE_VC_LOG_QUOTA_THRESHOLD:
  434. printf("Logging enable for quota limits and threshold.\n");
  435. break;
  436. case 0:
  437. printf("Logging for quota events is not enabled.\n");
  438. break;
  439. }
  440. if (TempControlInfo.FileSystemControlFlags & FILE_VC_QUOTA_MASK) {
  441. if (TempControlInfo.FileSystemControlFlags & FILE_VC_QUOTAS_INCOMPLETE) {
  442. TempPtr = "The quota values are incomplete.\n";
  443. } else
  444. {
  445. TempPtr = "The quota values are up to date.\n";
  446. }
  447. printf(TempPtr);
  448. }
  449. printf("Default Quota Threshold = %16I64x\n", TempControlInfo.DefaultQuotaThreshold.QuadPart);
  450. printf("Default Quota Limit = %16I64x\n\n", TempControlInfo.DefaultQuotaLimit.QuadPart);
  451. if (UserGiven) {
  452. Status = NtSetQuotaInformationFile( FileHandle,
  453. &IoStatus,
  454. QuotaInfo,
  455. BufferSize );
  456. if (!NT_SUCCESS( Status )) {
  457. printf( "Error NtSetVolumeInformationFile; error was %lx\n", Status );
  458. PrintError( Status );
  459. exit(1);
  460. }
  461. }
  462. if (!UserGiven || DeletingUser) {
  463. SidListPtr = NULL;
  464. SidListLength = 0;
  465. }
  466. do {
  467. Status = NtQueryQuotaInformationFile( FileHandle,
  468. &IoStatus,
  469. QuotaInfo,
  470. sizeof(QuotaInfo),
  471. FALSE,
  472. SidListPtr,
  473. SidListLength,
  474. NULL,
  475. FALSE );
  476. if (!NT_SUCCESS( Status ) && Status != STATUS_NO_MORE_ENTRIES) {
  477. printf( "Error NtQueryVolumeInformationFile; error was %lx\n", Status );
  478. PrintError( Status );
  479. exit(1);
  480. }
  481. QuotaInfoPtr = QuotaInfo;
  482. while (TRUE) {
  483. DumpQuota( QuotaInfoPtr, ServerName );
  484. if (QuotaInfoPtr->NextEntryOffset == 0) {
  485. break;
  486. }
  487. QuotaInfoPtr = (PFILE_QUOTA_INFORMATION) ((PCHAR) QuotaInfoPtr +
  488. QuotaInfoPtr->NextEntryOffset);
  489. }
  490. } while ( Status != STATUS_NO_MORE_ENTRIES );
  491. NtClose( FileHandle );
  492. }
  493. VOID
  494. DumpQuota (
  495. IN PFILE_QUOTA_INFORMATION FileQuotaInfo,
  496. IN PCHAR ServerName
  497. )
  498. {
  499. SID_NAME_USE SidNameUse;
  500. ULONG AccountLength, DomainLength;
  501. ULONG ErrorCode;
  502. char AccountName[128];
  503. char DomainName[128];
  504. UNICODE_STRING String;
  505. NTSTATUS Status;
  506. AccountLength = sizeof(AccountName) - 1;
  507. DomainLength = sizeof(DomainName) - 1;
  508. if (FileQuotaInfo->SidLength == 0) {
  509. printf( "Default quota values \n" );
  510. } else if (QuickSid) {
  511. String.Buffer = (PWCHAR) AccountName;
  512. String.MaximumLength = sizeof( AccountName );
  513. String.Length = 0;
  514. Status = RtlConvertSidToUnicodeString( &String,
  515. &FileQuotaInfo->Sid,
  516. FALSE );
  517. if (!NT_SUCCESS(Status)) {
  518. printf("DumpQuota: RtlConvertSidToUnicodeString failed. Error = %d\n",
  519. Status);
  520. PrintError( Status );
  521. } else {
  522. printf( "SID Value = %S\n", String.Buffer );
  523. }
  524. } else if (LookupAccountSidA(
  525. ServerName,
  526. &FileQuotaInfo->Sid,
  527. AccountName,
  528. &AccountLength,
  529. DomainName,
  530. &DomainLength,
  531. &SidNameUse))
  532. {
  533. char *String;
  534. AccountName[AccountLength] = '\0';
  535. DomainName[DomainLength] = '\0';
  536. switch (SidNameUse)
  537. {
  538. case SidTypeUser: String = "User"; break;
  539. case SidTypeGroup: String = "Group"; break;
  540. case SidTypeDomain: String = "Domain"; break;
  541. case SidTypeAlias: String = "Alias"; break;
  542. case SidTypeWellKnownGroup: String = "WellKnownGroup"; break;
  543. case SidTypeDeletedAccount: String = "DeletedAccount"; break;
  544. case SidTypeInvalid: String = "Invalid"; break;
  545. default: String = "Unknown"; break;
  546. }
  547. printf(
  548. "SID Name = %s\\%s (%s)\n",
  549. DomainName,
  550. AccountName,
  551. String);
  552. } else {
  553. printf("DumpQuota: Bad acccount SID. Error = %d\n",
  554. ErrorCode = GetLastError());
  555. PrintError( ErrorCode );
  556. }
  557. printf("Change time = %s\n", FileTimeToString((PFILETIME) &FileQuotaInfo->ChangeTime));
  558. printf("Quota Used = %16I64x\n", FileQuotaInfo->QuotaUsed.QuadPart);
  559. printf("Quota Threshold = %16I64x\n", FileQuotaInfo->QuotaThreshold.QuadPart);
  560. printf("Quota Limit = %16I64x\n\n", FileQuotaInfo->QuotaLimit.QuadPart);
  561. }
  562. char *Days[] =
  563. {
  564. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  565. };
  566. char *Months[] =
  567. {
  568. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  569. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  570. };
  571. CHAR *
  572. FileTimeToString(FILETIME *FileTime)
  573. {
  574. FILETIME LocalFileTime;
  575. SYSTEMTIME SystemTime;
  576. static char Buffer[32];
  577. Buffer[0] = '\0';
  578. if (FileTime->dwHighDateTime != 0 || FileTime->dwLowDateTime != 0)
  579. {
  580. if (!FileTimeToLocalFileTime(FileTime, &LocalFileTime) ||
  581. !FileTimeToSystemTime(&LocalFileTime, &SystemTime))
  582. {
  583. return("Time???");
  584. }
  585. sprintf(
  586. Buffer,
  587. "%s %s %2d %2d:%02d:%02d %4d",
  588. Days[SystemTime.wDayOfWeek],
  589. Months[SystemTime.wMonth - 1],
  590. SystemTime.wDay,
  591. SystemTime.wHour,
  592. SystemTime.wMinute,
  593. SystemTime.wSecond,
  594. SystemTime.wYear);
  595. }
  596. return(Buffer);
  597. }
  598. VOID
  599. PrintError(ULONG ErrorCode)
  600. {
  601. UCHAR ErrorBuffer[80];
  602. ULONG Count;
  603. HMODULE FileHandle = NULL;
  604. ULONG Flags = FORMAT_MESSAGE_FROM_SYSTEM;
  605. if (ErrorCode > MAXLONG) {
  606. Flags = FORMAT_MESSAGE_FROM_HMODULE;
  607. FileHandle = LoadLibrary( "ntdll" );
  608. if (FileHandle == NULL) {
  609. ULONG ErrorCode;
  610. printf("PrintError: LoadLibrary filed. Error = %d\n",
  611. ErrorCode = GetLastError());
  612. PrintError( ErrorCode );
  613. }
  614. }
  615. Count = FormatMessage(Flags,
  616. FileHandle,
  617. ErrorCode,
  618. 0,
  619. ErrorBuffer,
  620. sizeof(ErrorBuffer),
  621. NULL
  622. );
  623. if (Count != 0) {
  624. printf("Error was: %s\n", ErrorBuffer);
  625. } else {
  626. printf("Format message failed. Error: %d\n", GetLastError());
  627. }
  628. if (FileHandle != NULL) {
  629. FreeLibrary( FileHandle );
  630. }
  631. }
  632. VOID
  633. Usage()
  634. {
  635. printf( "Usage: %s -e [\\ServerName] | drive-letter [-q ] [ -f e|t|d [lt] ] [-d | -u account-name -t Threshold -l Limit] \n", __argv[0] );
  636. printf( " -e [\\ServerName] Print quota events from specified server default is local.\n");
  637. printf( " [-q] Quick print Sids. \n");
  638. printf( " [-f e|t|d[lt] ] Set volume quota flags (For example -f elt ): \n");
  639. printf( " [e]nforce quota limits.\n" );
  640. printf( " [t]rack quota usage.\n" );
  641. printf( " [d]isable quotas.\n" );
  642. printf( " [l]imit events should be logged.\n" );
  643. printf( " [t]threhold events should be logged.\n" );
  644. printf( " [-d] Set default user quota values.\n");
  645. printf( " [-u AccountName] Set quota values for user. \n");
  646. printf( " [-l Limit] Set 64-Bit limit value preivously specified user. \n");
  647. printf( " A limit of -2 indicates a defunct user can be removed. \n");
  648. printf( " [-t Threshold] Set 64-Bit threshold value preivously specified user. \n\n");
  649. printf( " Example:\n %s d -f elt -d -t 4194304 -l 5242880 -u administrators -l 0xffffffffffffffff -t 0xffffffffffffffff\n", __argv[0] );
  650. }