Source code of Windows XP (NT5)
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.

418 lines
10 KiB

  1. //+==========================================================================
  2. //
  3. // File: CDir.cxx
  4. //
  5. // Purpose: Define the CDirectory class.
  6. //
  7. // This class is used to represent a directory name.
  8. // Along with maintaining the name, it can determine
  9. // the type of FileSystem.
  10. //
  11. //+==========================================================================
  12. // --------
  13. // Includes
  14. // --------
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <wchar.h>
  19. #include <wtypes.h>
  20. #include "CFMEx.hxx"
  21. #include "CDir.hxx"
  22. //+------------------------------------------------------------------------------
  23. //
  24. // Function: CDirectory::Initialize (no arguments)
  25. //
  26. // Synopsis: Generate a directory name, using the TEMP environment
  27. // variable, and use it to initialize this object.
  28. //
  29. // Inputs: None.
  30. //
  31. // Outputs: TRUE if the function succeeds, FALSE otherwise.
  32. //
  33. //+------------------------------------------------------------------------------
  34. BOOL CDirectory::Initialize()
  35. {
  36. // ---------------
  37. // Local Variables
  38. // ---------------
  39. // Assume failure for now.
  40. BOOL bSuccess = FALSE;
  41. // The TEMP environment variable.
  42. WCHAR wszSystemTempPath[ MAX_PATH + sizeof( L'\0' )];
  43. // Reset the error code.
  44. m_lError = 0L;
  45. // ----------
  46. // Get %TEMP%
  47. // ----------
  48. if( !GetTempPath( MAX_PATH,
  49. wszSystemTempPath )
  50. )
  51. {
  52. m_lError = GetLastError();
  53. EXIT( L"GetTempPath() failed (%d)" );
  54. }
  55. // ----------------------
  56. // Initialize this object
  57. // ----------------------
  58. // Initialize using the temporary path. We must never pass a NULL here,
  59. // or we'll cause an infinite recursion.
  60. if( wszSystemTempPath == NULL )
  61. EXIT( L"Invalid temporary path" );
  62. bSuccess = Initialize( wszSystemTempPath );
  63. // ----
  64. // Exit
  65. // ----
  66. Exit:
  67. return( bSuccess );
  68. }
  69. //+-----------------------------------------------------------------------
  70. //
  71. // Function: CDirectory::Initialize (with an ANSI string)
  72. //
  73. // Synopsis: This function converts the ANSI string to a Unicode
  74. // string, then initializes the object with it.
  75. //
  76. // Inputs: A Unicode string.
  77. //
  78. // Outputs: TRUE if the function succeeds, FALSE otherwise.
  79. //
  80. //+-----------------------------------------------------------------------
  81. BOOL CDirectory::Initialize( LPCSTR szDirectory )
  82. {
  83. // ---------------
  84. // Local Variables
  85. // ---------------
  86. // Assume failure.
  87. BOOL bSuccess = FALSE;
  88. // A buffer for the Unicode path
  89. WCHAR wszDirectory[ MAX_UNICODE_PATH + sizeof( L'\0' )];
  90. // -----
  91. // Begin
  92. // -----
  93. // Initialize the error code.
  94. m_lError = 0L;
  95. // If we were givin a NULL path, use the version of Initialize
  96. // that requires no path.
  97. if( szDirectory == NULL )
  98. {
  99. bSuccess = Initialize();
  100. goto Exit;
  101. }
  102. // Convert the Ansi name to Unicode.
  103. if( m_lError = (long) AnsiToUnicode( szDirectory,
  104. wszDirectory,
  105. strlen( szDirectory )
  106. )
  107. )
  108. {
  109. EXIT( L"Unable to convert directory to Unicode" );
  110. }
  111. // Initialize using the temporary path. We must never pass a NULL here,
  112. // or we'll cause an infinite recursion.
  113. if( wszDirectory == NULL )
  114. EXIT( L"Invalid Directory (internal error)" );
  115. bSuccess = Initialize( wszDirectory );
  116. // ----
  117. // Exit
  118. // ----
  119. Exit:
  120. return( bSuccess );
  121. }
  122. //+-----------------------------------------------------------------------
  123. //
  124. // Function: CDirectory::Initialize (with a Unicode string)
  125. //
  126. // Synopsis: This function is the only form of Initialize
  127. // (there are several variations of the Initialize member)
  128. // which really initializes the object. It stores the
  129. // directory name, and determines the type of filesystem
  130. // on which it resides.
  131. //
  132. // Inputs: A Unicode string.
  133. //
  134. // Outputs: TRUE if the function succeeds, FALSE otherwise.
  135. //
  136. //+-----------------------------------------------------------------------
  137. BOOL CDirectory::Initialize( LPCWSTR wszDirectory )
  138. {
  139. // ---------------
  140. // Local Variables
  141. // ---------------
  142. // Assume failure.
  143. BOOL bSuccess = FALSE;
  144. // Buffers for the root of the path and for the volume name.
  145. WCHAR wszDirectoryRoot[ MAX_PATH + sizeof( L'\0' )];
  146. WCHAR wszVolumeName[ MAX_PATH + sizeof( L'\0' )];
  147. // Parameters to GetVolumeInformation which we won't use.
  148. DWORD dwMaxComponentLength = 0L;
  149. DWORD dwFileSystemFlags = 0L;
  150. // -----
  151. // Begin
  152. // -----
  153. // Initialize the error code.
  154. m_lError = 0L;
  155. // If we were given a NULL path, use the variation of Initialization()
  156. // which does not require one. Note that we will then be called again,
  157. // but this time with a path.
  158. if( wszDirectory == NULL )
  159. {
  160. bSuccess = Initialize();
  161. goto Exit;
  162. }
  163. // Validate the path.
  164. if( wcslen( wszDirectory ) > MAX_PATH )
  165. {
  166. m_lError = wcslen( wszDirectory );
  167. EXIT( L"Input path is too long (%d)\n" );
  168. }
  169. // Save the path to our member buffer
  170. wcscpy( m_wszDirectory, wszDirectory );
  171. // ------------------------
  172. // Get the file system name
  173. // ------------------------
  174. // Get the root path to the directory.
  175. wcscpy( wszDirectoryRoot, wszDirectory );
  176. MakeRoot( wszDirectoryRoot );
  177. // Get the volume information, which will include the filesystem name.
  178. if( !GetVolumeInformation( wszDirectoryRoot, // Root path name.
  179. wszVolumeName, // Buffer for volume name
  180. MAX_PATH, // Length of the above buffer
  181. NULL, // Buffer for serial number
  182. // Longest filename length.
  183. &dwMaxComponentLength,
  184. &dwFileSystemFlags, // Compression, etc.
  185. m_wszFileSystemName,// Buffer for the FS name.
  186. MAX_PATH ) // Length of above buffer
  187. )
  188. {
  189. m_lError = GetLastError();
  190. EXIT( L"GetVolumeInformation() failed" );
  191. }
  192. // Determine the file system type from the name.
  193. if( !wcscmp( m_wszFileSystemName, L"FAT" ))
  194. m_FileSystemType = fstFAT;
  195. else if( !wcscmp( m_wszFileSystemName, L"NTFS" ))
  196. m_FileSystemType = fstNTFS;
  197. else if( !wcscmp( m_wszFileSystemName, L"OFS" ))
  198. m_FileSystemType = fstOFS;
  199. else
  200. m_FileSystemType = fstUnknown;
  201. bSuccess = TRUE;
  202. // ----
  203. // Exit
  204. // ----
  205. Exit:
  206. DisplayErrors( bSuccess, L"CDirectory::Initialize( wszDirectory )" );
  207. return( bSuccess );
  208. }
  209. //
  210. // GetRootLength
  211. //
  212. // This routine was simply copied from private\windows\shell\shelldll\tracker.cxx,
  213. // and should not be modified here.
  214. //
  215. unsigned
  216. CDirectory::GetRootLength(const WCHAR *pwszPath)
  217. {
  218. ULONG cwcRoot = 0;
  219. m_lError = 0L;
  220. if (pwszPath == 0)
  221. pwszPath = L"";
  222. if (*pwszPath == L'\\')
  223. {
  224. // If the first character is a path separator (backslash), this
  225. // must be a UNC drive designator which must be of the form:
  226. // <path-separator><path-separator>(<alnum>+)
  227. // <path-separator>(<alnum>+)<path-separator>
  228. //
  229. // This covers drives like these: \\worf\scratch\ and
  230. // \\savik\win4dev\.
  231. //
  232. pwszPath++;
  233. cwcRoot++;
  234. BOOL fMachine = FALSE;
  235. BOOL fShare = FALSE;
  236. if (*pwszPath == L'\\')
  237. {
  238. cwcRoot++;
  239. pwszPath++;
  240. while (*pwszPath != '\0' && *pwszPath != L'\\')
  241. {
  242. cwcRoot++;
  243. pwszPath++;
  244. fMachine = TRUE;
  245. }
  246. if (*pwszPath == L'\\')
  247. {
  248. cwcRoot++;
  249. pwszPath++;
  250. while (*pwszPath != '\0' && *pwszPath != L'\\')
  251. {
  252. cwcRoot++;
  253. pwszPath++;
  254. fShare = TRUE;
  255. }
  256. // If there weren't any characters in the machine or
  257. // share portions of the UNC name, then the drive
  258. // designator is bogus.
  259. //
  260. if (!fMachine || !fShare)
  261. {
  262. cwcRoot = 0;
  263. }
  264. }
  265. else
  266. {
  267. cwcRoot = 0;
  268. }
  269. }
  270. else
  271. {
  272. cwcRoot = 0;
  273. }
  274. }
  275. else
  276. if (iswalpha(*pwszPath))
  277. {
  278. // If the first character is an alphanumeric, we must have
  279. // a drive designator of this form:
  280. // (<alnum>)+<drive-separator><path-separator>
  281. //
  282. // This covers drives like these: a:\, c:\, etc
  283. //
  284. pwszPath++;
  285. cwcRoot++;
  286. if (*pwszPath == L':')
  287. {
  288. cwcRoot++;
  289. pwszPath++;
  290. }
  291. else
  292. {
  293. cwcRoot = 0;
  294. }
  295. }
  296. // If we have counted one or more characters in the root and these
  297. // are followed by a component separator, we need to add the separator
  298. // to the root length. Otherwise this is not a valid root and we need
  299. // to return a length of zero.
  300. //
  301. if ((cwcRoot > 0) && (*pwszPath == L'\\'))
  302. {
  303. cwcRoot++;
  304. }
  305. else
  306. {
  307. cwcRoot = 0;
  308. }
  309. return (cwcRoot);
  310. }
  311. //
  312. // MakeRoot
  313. //
  314. // This routine was simply copied from private\windows\shell\shelldll\tracker.cxx,
  315. // and should not be modified here.
  316. //
  317. VOID
  318. CDirectory::MakeRoot(WCHAR *pwszPath)
  319. {
  320. unsigned rootlength = GetRootLength(pwszPath);
  321. m_lError = 0L;
  322. if (rootlength)
  323. {
  324. pwszPath[rootlength] = L'\0';
  325. }
  326. }