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.

189 lines
6.1 KiB

  1. #include <windows.h>
  2. #include <winioctl.h>
  3. #include <ntddsnap.h>
  4. #include <stdio.h>
  5. #include <objbase.h>
  6. typedef struct _VSP_CONTEXT {
  7. HANDLE Handle;
  8. PVOLSNAP_FLUSH_AND_HOLD_INPUT FlushInput;
  9. } VSP_CONTEXT, *PVSP_CONTEXT;
  10. DWORD
  11. FlushAndHoldRoutine(
  12. PVOID Context
  13. )
  14. {
  15. PVSP_CONTEXT context = Context;
  16. BOOL b;
  17. DWORD bytes;
  18. b = DeviceIoControl(context->Handle, IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES,
  19. context->FlushInput,
  20. sizeof(VOLSNAP_FLUSH_AND_HOLD_INPUT), NULL, 0, &bytes,
  21. NULL);
  22. if (!b) {
  23. printf("Flush and hold failed with %d\n", GetLastError());
  24. return GetLastError();
  25. }
  26. return 0;
  27. }
  28. void __cdecl
  29. main(
  30. int argc,
  31. char** argv
  32. )
  33. {
  34. WCHAR driveName[10];
  35. HANDLE handle[100];
  36. VOLSNAP_PREPARE_INFO prepareInfo;
  37. BOOL b, persistent;
  38. DWORD bytes;
  39. int i, j;
  40. VOLSNAP_FLUSH_AND_HOLD_INPUT flushInput;
  41. PVOLSNAP_NAME name;
  42. WCHAR buffer[100];
  43. HANDLE threads[100];
  44. DWORD threadid;
  45. VSP_CONTEXT context[100];
  46. if (argc < 2) {
  47. printf("usage: %s [/p] drive: drive: ...\n", argv[0]);
  48. return;
  49. }
  50. if (argv[1][0] == '/' && (argv[1][1] == 'p' || argv[1][1] == 'P')) {
  51. persistent = TRUE;
  52. if (argc < 3) {
  53. printf("usage: %s /p drive: drive: ...\n", argv[0]);
  54. return;
  55. }
  56. } else {
  57. persistent = FALSE;
  58. }
  59. for (i = persistent ? 2 : 1; i < argc; i++) {
  60. swprintf(driveName, L"\\\\?\\%c:", toupper(argv[i][0]));
  61. handle[i] = CreateFile(driveName, GENERIC_READ | GENERIC_WRITE,
  62. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  63. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  64. INVALID_HANDLE_VALUE);
  65. if (handle[i] == INVALID_HANDLE_VALUE) {
  66. printf("Could not open volume %c:, error = %d\n", argv[i][0],
  67. GetLastError());
  68. break;
  69. }
  70. if (persistent) {
  71. prepareInfo.Attributes = 1;
  72. } else {
  73. prepareInfo.Attributes = 0;
  74. }
  75. prepareInfo.InitialDiffAreaAllocation = 100*1024*1024;
  76. b = DeviceIoControl(handle[i], IOCTL_VOLSNAP_PREPARE_FOR_SNAPSHOT,
  77. &prepareInfo, sizeof(prepareInfo), NULL, 0, &bytes,
  78. NULL);
  79. if (!b) {
  80. printf("Prepare failed with %d\n", GetLastError());
  81. break;
  82. }
  83. CloseHandle(handle[i]);
  84. handle[i] = CreateFile(driveName, GENERIC_READ | GENERIC_WRITE,
  85. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  86. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  87. INVALID_HANDLE_VALUE);
  88. if (handle == INVALID_HANDLE_VALUE) {
  89. printf("Could not open volume %c:, error = %d\n", argv[i][0],
  90. GetLastError());
  91. break;
  92. }
  93. }
  94. if (i < argc) {
  95. for (j = persistent ? 2 : 1; j < i; j++) {
  96. b = DeviceIoControl(handle[j],
  97. IOCTL_VOLSNAP_ABORT_PREPARED_SNAPSHOT,
  98. NULL, 0, NULL, 0, &bytes, NULL);
  99. if (!b) {
  100. printf("Abort of Prepared snapshot failed with %d\n", GetLastError());
  101. }
  102. }
  103. return;
  104. }
  105. CoCreateGuid(&flushInput.InstanceId);
  106. flushInput.NumberOfVolumesToFlush = argc - (persistent ? 2 : 1);
  107. flushInput.SecondsToHoldFileSystemsTimeout = 60;
  108. flushInput.SecondsToHoldIrpsTimeout = 10;
  109. for (i = persistent ? 2 : 1; i < argc; i++) {
  110. context[i].Handle = handle[i];
  111. context[i].FlushInput = &flushInput;
  112. threads[i] = CreateThread(NULL, 0, FlushAndHoldRoutine, &context[i],
  113. 0, &threadid);
  114. }
  115. WaitForMultipleObjects(argc - (persistent ? 2 : 1),
  116. &threads[persistent ? 2 : 1], TRUE, INFINITE);
  117. for (i = persistent ? 2 : 1; i < argc; i++) {
  118. b = DeviceIoControl(handle[i], IOCTL_VOLSNAP_COMMIT_SNAPSHOT, NULL, 0,
  119. NULL, 0, &bytes, NULL);
  120. if (!b) {
  121. printf("Commit failed with %d\n", GetLastError());
  122. break;
  123. }
  124. }
  125. name = (PVOLSNAP_NAME) buffer;
  126. if (i < argc) {
  127. for (j = persistent ? 2 : 1; j < argc; j++) {
  128. b = DeviceIoControl(handle[j], IOCTL_VOLSNAP_RELEASE_WRITES,
  129. NULL, 0, NULL, 0, &bytes, NULL);
  130. }
  131. for (j = persistent ? 2 : 1; j < i; j++) {
  132. b = DeviceIoControl(handle[j], IOCTL_VOLSNAP_END_COMMIT_SNAPSHOT,
  133. NULL, 0, name, 200, &bytes, NULL);
  134. }
  135. for (; j < argc; j++) {
  136. b = DeviceIoControl(handle[j],
  137. IOCTL_VOLSNAP_ABORT_PREPARED_SNAPSHOT,
  138. NULL, 0, NULL, 0, &bytes, NULL);
  139. }
  140. return;
  141. }
  142. for (i = persistent ? 2 : 1; i < argc; i++) {
  143. b = DeviceIoControl(handle[i], IOCTL_VOLSNAP_RELEASE_WRITES, NULL, 0, NULL,
  144. 0, &bytes, NULL);
  145. if (!b) {
  146. printf("Release writes failed with %d\n", GetLastError());
  147. }
  148. }
  149. for (i = persistent ? 2 : 1; i < argc; i++) {
  150. b = DeviceIoControl(handle[i], IOCTL_VOLSNAP_END_COMMIT_SNAPSHOT, NULL, 0,
  151. name, 200, &bytes, NULL);
  152. if (!b) {
  153. printf("End commit failed with %d\n", GetLastError());
  154. } else {
  155. name->Name[name->NameLength/sizeof(WCHAR)] = 0;
  156. printf("%ws created.\n", name->Name);
  157. }
  158. }
  159. }