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.

333 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. vs_vol.hxx
  5. Abstract:
  6. Various defines for volume name management
  7. Author:
  8. Adi Oltean [aoltean] 10/10/1999
  9. Revision History:
  10. Name Date Comments
  11. aoltean 10/10/1999 Created
  12. aoltean 11/23/1999 Renamed to vs_vol.hxx from snap_vol.hxx
  13. --*/
  14. #ifndef __VSS_VOL_GEN_HXX__
  15. #define __VSS_VOL_GEN_HXX__
  16. #if _MSC_VER > 1000
  17. #pragma once
  18. #endif
  19. #include <vss.h>
  20. ////////////////////////////////////////////////////////////////////////
  21. // Standard foo for file name aliasing. This code block must be after
  22. // all includes of VSS header files.
  23. //
  24. #ifdef VSS_FILE_ALIAS
  25. #undef VSS_FILE_ALIAS
  26. #endif
  27. #define VSS_FILE_ALIAS "INCVOLH"
  28. //
  29. ////////////////////////////////////////////////////////////////////////
  30. /////////////////////////////////////////////////////////////////////////////
  31. // Defines
  32. // Number of array elements
  33. #define ARRAY_LEN(A) (sizeof(A)/sizeof((A)[0]))
  34. // Size of strings, excepting the zero character
  35. #define STRING_SIZE(S) (sizeof(S) - sizeof((S)[0]))
  36. // String length (number of characters, excepting the zero character)
  37. #define STRING_LEN(S) (ARRAY_LEN(S) - 1)
  38. /////////////////////////////////////////////////////////////////////////////
  39. // Constants
  40. // guid def
  41. const WCHAR wszGuidDefinition[] = L"{00000000-0000-0000-0000-000000000000}";
  42. // Kernel volume name "\\??\\Volume{00000000-0000-0000-0000-000000000000}"
  43. const WCHAR wszWinObjVolumeDefinition[] = L"\\??\\Volume";
  44. const WCHAR wszWinObjEndOfVolumeName[] = L"";
  45. const WCHAR wszWinObjDosPathDefinition[] = L"\\??\\";
  46. // string size, without the L'\0' character
  47. const nSizeOfWinObjVolumeName = STRING_SIZE(wszWinObjVolumeDefinition) +
  48. STRING_SIZE(wszGuidDefinition) + STRING_SIZE(wszWinObjEndOfVolumeName);
  49. // string length, without the L'\0' character
  50. const nLengthOfWinObjVolumeName = STRING_LEN(wszWinObjVolumeDefinition) +
  51. STRING_LEN(wszGuidDefinition) + STRING_LEN(wszWinObjEndOfVolumeName);
  52. // Vol Mgmt volume name "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"
  53. const WCHAR wszVolMgmtVolumeDefinition[] = L"\\\\?\\Volume";
  54. const WCHAR wszVolMgmtEndOfVolumeName[] = L"\\";
  55. // string size without the L'\0' character ( = 62 )
  56. const nSizeOfVolMgmtVolumeName = STRING_SIZE(wszVolMgmtVolumeDefinition) +
  57. STRING_SIZE(wszGuidDefinition) + STRING_SIZE(wszWinObjEndOfVolumeName);
  58. // string length, without the L'\0' character ( = 31)
  59. const nLengthOfVolMgmtVolumeName = STRING_LEN(wszVolMgmtVolumeDefinition) +
  60. STRING_LEN(wszGuidDefinition) + STRING_LEN(wszVolMgmtEndOfVolumeName);
  61. // Number of characters in an empty multisz string.
  62. const nEmptyVssMultiszLen = 2;
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Inlines
  65. inline bool GetVolumeGuid( IN LPWSTR pwszVolMgmtVolumeName, GUID& VolumeGuid )
  66. /*
  67. Routine description:
  68. Return the guid that corresponds to a mount manager volume name
  69. The volume is in the following format:
  70. \\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\
  71. */
  72. {
  73. BS_ASSERT(pwszVolMgmtVolumeName);
  74. // test the length
  75. if (::wcslen(pwszVolMgmtVolumeName) != nLengthOfVolMgmtVolumeName)
  76. return false;
  77. // test the definition
  78. if (::wcsncmp(pwszVolMgmtVolumeName,
  79. wszVolMgmtVolumeDefinition,
  80. STRING_LEN(wszVolMgmtVolumeDefinition) ) != 0)
  81. return false;
  82. pwszVolMgmtVolumeName += STRING_LEN(wszVolMgmtVolumeDefinition); // go to the GUID
  83. // test the end
  84. if(::wcsncmp(pwszVolMgmtVolumeName + STRING_LEN(wszGuidDefinition),
  85. wszVolMgmtEndOfVolumeName, ARRAY_LEN(wszVolMgmtEndOfVolumeName)) != 0)
  86. return false;
  87. // test the guid. If W2OLE fails, a SE exception is thrown.
  88. WCHAR wszGuid[ARRAY_LEN(wszGuidDefinition)];
  89. ::wcsncpy(wszGuid, pwszVolMgmtVolumeName, STRING_LEN(wszGuidDefinition));
  90. wszGuid[STRING_LEN(wszGuidDefinition)] = L'\0';
  91. BOOL bRes = ::CLSIDFromString(W2OLE(wszGuid), &VolumeGuid) == S_OK;
  92. return !!bRes;
  93. }
  94. inline bool GetVolumeGuid2( IN LPWSTR pwszWinObjVolumeName, GUID& VolumeGuid )
  95. /*
  96. Routine description:
  97. Return the guid that corresponds to a mount manager volume name
  98. The format:
  99. \\??\\Volume{00000000-0000-0000-0000-000000000000}
  100. */
  101. {
  102. BS_ASSERT(pwszWinObjVolumeName);
  103. // test the length
  104. if (::wcslen(pwszWinObjVolumeName) != nLengthOfWinObjVolumeName)
  105. return false;
  106. // test the definition
  107. if (::wcsncmp(pwszWinObjVolumeName,
  108. wszWinObjVolumeDefinition,
  109. STRING_LEN(wszWinObjVolumeDefinition) ) != 0)
  110. return false;
  111. pwszWinObjVolumeName += STRING_LEN(wszWinObjVolumeDefinition); // go to the GUID
  112. // test the end
  113. if(::wcsncmp(pwszWinObjVolumeName + STRING_LEN(wszGuidDefinition),
  114. wszWinObjEndOfVolumeName, ARRAY_LEN(wszWinObjEndOfVolumeName)) != 0)
  115. return false;
  116. // test the guid. If W2OLE fails, a SE exception is thrown.
  117. WCHAR wszGuid[ARRAY_LEN(wszGuidDefinition)];
  118. ::wcsncpy(wszGuid, pwszWinObjVolumeName, STRING_LEN(wszGuidDefinition));
  119. wszGuid[STRING_LEN(wszGuidDefinition)] = L'\0';
  120. BOOL bRes = ::CLSIDFromString(W2OLE(wszGuid), &VolumeGuid) == S_OK;
  121. return !!bRes;
  122. }
  123. inline bool IsVolMgmtVolumeName( IN LPWSTR pwszVolMgmtVolumeName )
  124. /*
  125. Routine description:
  126. Return true if the given name is a mount manager volume name, in format
  127. "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"
  128. */
  129. {
  130. GUID VolumeGuid;
  131. BS_ASSERT(pwszVolMgmtVolumeName);
  132. return ::GetVolumeGuid(pwszVolMgmtVolumeName, VolumeGuid);
  133. }
  134. inline bool ConvertVolMgmtVolumeNameIntoKernelObject( IN LPWSTR pwszVolMgmtVolumeName )
  135. /*
  136. Routine description:
  137. Converts a mount manager volume name
  138. "\\\\?\\Volume{00000000-0000-0000-0000-000000000000}\\"
  139. into the kernel mode format
  140. "\\??\\Volume{00000000-0000-0000-0000-000000000000}"
  141. */
  142. {
  143. // Check if the volume name is in teh proper format
  144. if (!IsVolMgmtVolumeName(pwszVolMgmtVolumeName))
  145. return false;
  146. // Eliminate the last backslash from the volume name.
  147. BS_ASSERT(pwszVolMgmtVolumeName[0] != L'\0');
  148. BS_ASSERT(::wcslen(pwszVolMgmtVolumeName) == nLengthOfVolMgmtVolumeName);
  149. BS_ASSERT(pwszVolMgmtVolumeName[nLengthOfVolMgmtVolumeName - 1] == L'\\');
  150. pwszVolMgmtVolumeName[nLengthOfVolMgmtVolumeName - 1] = L'\0';
  151. // Put the '?' sign
  152. BS_ASSERT(pwszVolMgmtVolumeName[1] == L'\\');
  153. pwszVolMgmtVolumeName[1] = L'?';
  154. return true;
  155. }
  156. #pragma warning(push)
  157. #pragma warning(disable:4296)
  158. inline void CopyVolumeName(
  159. PBYTE pDestination,
  160. LPWSTR pwszVolumeName
  161. ) throw(HRESULT)
  162. /*
  163. Routine description:
  164. Take the volume name as a Vol Mgmt volume name and copy it to the destination buffer as a
  165. WinObj volume name
  166. */
  167. {
  168. // Copy the volume definition part
  169. ::CopyMemory( pDestination, wszWinObjVolumeDefinition, STRING_SIZE(wszWinObjVolumeDefinition) );
  170. pDestination += STRING_SIZE(wszWinObjVolumeDefinition);
  171. BS_ASSERT(::wcslen(pwszVolumeName) == nSizeOfVolMgmtVolumeName/sizeof(WCHAR));
  172. BS_ASSERT(::wcsncmp(pwszVolumeName, wszVolMgmtVolumeDefinition,
  173. STRING_LEN(wszVolMgmtVolumeDefinition) ) == 0);
  174. pwszVolumeName += STRING_LEN(wszVolMgmtVolumeDefinition); // go directly to the GUID
  175. // Copy the guid
  176. ::CopyMemory( pDestination, pwszVolumeName, STRING_SIZE(wszGuidDefinition) );
  177. // Copy the end of volume name
  178. if (STRING_SIZE(wszWinObjEndOfVolumeName) > 0)
  179. {
  180. pDestination += STRING_SIZE(wszGuidDefinition);
  181. ::CopyMemory( pDestination, wszWinObjEndOfVolumeName, STRING_SIZE(wszWinObjEndOfVolumeName) );
  182. }
  183. }
  184. #pragma warning(pop)
  185. inline void VerifyVolumeIsSupportedByVSS(
  186. IN LPWSTR pwszVolumeName
  187. ) throw( HRESULT )
  188. /*
  189. Routine description:
  190. Verify if a volume can be snapshotted.
  191. This is a check to be performed before invoking provider's IsVolumeSupported.
  192. Throws:
  193. VSS_E_VOLUME_NOT_SUPPORTED
  194. - if the volume is not supported by VSS.
  195. VSS_E_OBJECT_NOT_FOUND
  196. - The volume was not found
  197. */
  198. {
  199. CVssFunctionTracer ft( VSSDBG_COORD, L"VerifyVolumeIsSupportedByVSS" );
  200. // Check to make sure the volume is fixed (i.e. no CD-ROM, no removable)
  201. UINT uDriveType = ::GetDriveTypeW( pwszVolumeName );
  202. if ( uDriveType != DRIVE_FIXED) {
  203. ft.Throw( VSSDBG_COORD, VSS_E_VOLUME_NOT_SUPPORTED,
  204. L"Encountered a non-fixed volumes (%s) - %ud, not supported by VSS",
  205. pwszVolumeName, uDriveType );
  206. }
  207. DWORD dwFileSystemFlags = 0;
  208. if (!::GetVolumeInformationW(
  209. pwszVolumeName,
  210. NULL, // lpVolumeNameBuffer
  211. 0, // nVolumeNameSize
  212. NULL, // lpVolumeSerialNumber
  213. NULL, // lpMaximumComponentLength
  214. &dwFileSystemFlags,
  215. NULL,
  216. 0
  217. )) {
  218. // Check if the volume was found
  219. if ((GetLastError() == ERROR_NOT_READY) ||
  220. (GetLastError() == ERROR_DEVICE_NOT_CONNECTED))
  221. ft.Throw( VSSDBG_COORD, VSS_E_OBJECT_NOT_FOUND,
  222. L"Volume not found: error calling GetVolumeInformation on volume '%s' : %u",
  223. pwszVolumeName, GetLastError() );
  224. // RAW volumes are supported by VSS (bug 209059)
  225. if (GetLastError() != ERROR_UNRECOGNIZED_VOLUME)
  226. ft.Throw( VSSDBG_COORD, VSS_E_VOLUME_NOT_SUPPORTED,
  227. L"Error calling GetVolumeInformation on volume '%s' : %u",
  228. pwszVolumeName, GetLastError() );
  229. }
  230. // Read-only volumes are not supported
  231. if (dwFileSystemFlags & FILE_READ_ONLY_VOLUME) {
  232. ft.Throw( VSSDBG_COORD, VSS_E_VOLUME_NOT_SUPPORTED,
  233. L"Encountered a read-only volume (%s), not supported by VSS",
  234. pwszVolumeName);
  235. }
  236. }
  237. #endif // __VSS_VOL_GEN_HXX__