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.

414 lines
10 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "mtpt.h"
  4. #include "ids.h"
  5. #include "shitemid.h"
  6. #include "filetbl.h"
  7. #include "shpriv.h"
  8. #include "hwcmmn.h"
  9. #include "apithk.h"
  10. #include <ntddcdrm.h>
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // Public methods
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // get the friendly name for a given drive thing
  15. // for example:
  16. // Floppy (A:)
  17. // Volume Name (D:)
  18. // User on 'Pyrex' (V:)
  19. // Dist on Strike\sys\public (Netware case)
  20. HRESULT CMountPoint::GetDisplayName(LPTSTR pszName, DWORD cchName)
  21. {
  22. HRESULT hres = E_FAIL;
  23. TCHAR szDriveLabel[MAX_DISPLAYNAME];
  24. static BOOL s_fAllDriveLetterFirst = -1;
  25. static BOOL s_fRemoteDriveLetterFirst = -1;
  26. static BOOL s_fNoDriveLetter = -1;
  27. ASSERT(cchName > 0);
  28. *pszName = 0; // handle failure case
  29. // for s_fDriveLetterFirst, see bug 250899, that's a long story.
  30. if (-1 == s_fRemoteDriveLetterFirst)
  31. {
  32. DWORD dw;
  33. DWORD cb = sizeof(dw);
  34. s_fRemoteDriveLetterFirst = FALSE;
  35. s_fAllDriveLetterFirst = FALSE;
  36. s_fNoDriveLetter = FALSE;
  37. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE,
  38. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
  39. TEXT("ShowDriveLettersFirst"), NULL, &dw, &cb))
  40. {
  41. if (1 == dw)
  42. {
  43. s_fRemoteDriveLetterFirst = TRUE;
  44. }
  45. else
  46. {
  47. if (2 == dw)
  48. {
  49. s_fNoDriveLetter = TRUE;
  50. }
  51. else
  52. {
  53. if (4 == dw)
  54. {
  55. s_fAllDriveLetterFirst = TRUE;
  56. }
  57. }
  58. }
  59. }
  60. }
  61. hres = GetLabel(szDriveLabel, ARRAYSIZE(szDriveLabel));
  62. if (SUCCEEDED(hres))
  63. {
  64. if (s_fNoDriveLetter)
  65. {
  66. StrCpyN(pszName, szDriveLabel, cchName);
  67. }
  68. else
  69. {
  70. BOOL fDriveLetterFirst = ((_IsRemote()) && s_fRemoteDriveLetterFirst) ||
  71. s_fAllDriveLetterFirst;
  72. // To return something like: "My Drive (c:)", we need a drive letter.
  73. // Fortunately for us this fct is only called for a drive mounted on a
  74. // letter (from drive implementation of IShellFolder), for volumes mounted
  75. // on folders, the folder impl is called rather than the drive one.
  76. LPTSTR psz = ShellConstructMessageString(HINST_THISDLL,
  77. MAKEINTRESOURCE(fDriveLetterFirst ? IDS_VOL_FORMAT_LETTER_1ST : IDS_VOL_FORMAT),
  78. szDriveLabel, _GetNameFirstCharUCase());
  79. if (psz)
  80. {
  81. StrCpyN(pszName, psz, cchName);
  82. LocalFree(psz);
  83. }
  84. else
  85. {
  86. hres = E_OUTOFMEMORY;
  87. }
  88. }
  89. }
  90. return hres;
  91. }
  92. // { DRIVE_ISCOMPRESSIBLE | DRIVE_COMPRESSED | DRIVE_LFN | DRIVE_SECURITY }
  93. int CMountPoint::GetVolumeFlags()
  94. {
  95. int iFlags = _GetGVIDriveFlags();
  96. // Try to avoid getting the attributes
  97. if (iFlags & DRIVE_ISCOMPRESSIBLE)
  98. {
  99. DWORD dwAttrib = -1;
  100. if (_GetFileAttributes(&dwAttrib))
  101. {
  102. if (dwAttrib & FILE_ATTRIBUTE_COMPRESSED)
  103. {
  104. iFlags |= DRIVE_COMPRESSED;
  105. }
  106. }
  107. }
  108. return iFlags;
  109. }
  110. DWORD CMountPoint::GetClusterSize()
  111. {
  112. DWORD dwSecPerClus, dwBytesPerSec, dwClusters, dwTemp;
  113. // assume this, avoid div by zero
  114. DWORD dwRet = 512;
  115. if (GetDiskFreeSpace(_GetNameForFctCall(), &dwSecPerClus, &dwBytesPerSec, &dwTemp, &dwClusters))
  116. {
  117. dwRet = dwSecPerClus * dwBytesPerSec;
  118. }
  119. return dwRet;
  120. }
  121. //static
  122. void CMountPoint::GetTypeString(int iDrive, LPTSTR pszType, DWORD cchType)
  123. {
  124. *pszType = 0;
  125. CMountPoint* pmtpt = GetMountPoint(iDrive);
  126. if (pmtpt)
  127. {
  128. pmtpt->GetTypeString(pszType, cchType);
  129. pmtpt->Release();
  130. }
  131. }
  132. // static
  133. UINT CMountPoint::GetSuperPlainDriveIcon(LPCWSTR pszDrive, UINT uDriveType)
  134. {
  135. int iIcon;
  136. switch (uDriveType)
  137. {
  138. case DRIVE_REMOVABLE:
  139. {
  140. iIcon = II_DRIVEREMOVE;
  141. if (pszDrive)
  142. {
  143. if ((TEXT('a') == *pszDrive) || (TEXT('A') == *pszDrive))
  144. {
  145. iIcon = II_DRIVE35;
  146. }
  147. else
  148. {
  149. if ((TEXT('b') == *pszDrive) || (TEXT('B') == *pszDrive))
  150. {
  151. iIcon = II_DRIVE35;
  152. }
  153. }
  154. }
  155. break;
  156. }
  157. case DRIVE_FIXED:
  158. {
  159. iIcon = II_DRIVEFIXED;
  160. break;
  161. }
  162. case DRIVE_REMOTE:
  163. {
  164. iIcon = II_DRIVENET;
  165. break;
  166. }
  167. case DRIVE_CDROM:
  168. {
  169. iIcon = II_DRIVECD;
  170. break;
  171. }
  172. case DRIVE_RAMDISK:
  173. {
  174. iIcon = II_DRIVERAM;
  175. break;
  176. }
  177. case DRIVE_UNKNOWN:
  178. case DRIVE_NO_ROOT_DIR:
  179. default:
  180. {
  181. iIcon = -IDI_DRIVEUNKNOWN;
  182. break;
  183. }
  184. }
  185. return iIcon;
  186. }
  187. ///////////////////////////////////////////////////////////////////////////////
  188. // Call Backs
  189. ///////////////////////////////////////////////////////////////////////////////
  190. void CMountPoint::_UpdateCommentFromDesktopINI()
  191. {
  192. WCHAR szCommentFromDesktopINI[MAX_MTPTCOMMENT];
  193. GetShellClassInfoInfoTip(_GetName(), szCommentFromDesktopINI, ARRAYSIZE(szCommentFromDesktopINI));
  194. RSSetTextValue(NULL, TEXT("_CommentFromDesktopINI"),
  195. szCommentFromDesktopINI, REG_OPTION_NON_VOLATILE);
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////
  198. // Default Icon/Label
  199. ///////////////////////////////////////////////////////////////////////////////
  200. void CMountPoint::_InitLegacyRegIconAndLabel(BOOL fUseAutorunIcon,
  201. BOOL fUseAutorunLabel)
  202. {
  203. // No Autorun icon, load the legacy reg icon if any
  204. if (!fUseAutorunIcon && _IsMountedOnDriveLetter())
  205. {
  206. WCHAR szSubKey[MAX_PATH];
  207. WCHAR szIconLocation[MAX_PATH + 12];
  208. wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
  209. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultIcon"),
  210. _GetNameFirstCharUCase());
  211. szIconLocation[0] = 0;
  212. if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szIconLocation,
  213. ARRAYSIZE(szIconLocation) * sizeof(TCHAR)))
  214. {
  215. // Let's try second location
  216. wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
  217. TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultIcon"),
  218. _GetNameFirstCharUCase());
  219. RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szIconLocation,
  220. ARRAYSIZE(szIconLocation) * sizeof(TCHAR));
  221. }
  222. if (szIconLocation[0])
  223. {
  224. AssertMsg(!_pszLegacyRegIcon, TEXT("_InitLegacyRegIconAndLabel: called twice"));
  225. _pszLegacyRegIcon = StrDup(szIconLocation);
  226. }
  227. }
  228. if (!fUseAutorunLabel && _IsMountedOnDriveLetter())
  229. {
  230. WCHAR szSubKey[MAX_PATH];
  231. WCHAR szLabel[MAX_LABEL];
  232. wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
  233. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultLabel"),
  234. _GetNameFirstCharUCase());
  235. szLabel[0] = 0;
  236. if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szLabel,
  237. ARRAYSIZE(szLabel) * sizeof(TCHAR)))
  238. {
  239. // Let's try second location
  240. wnsprintf(szSubKey, ARRAYSIZE(szSubKey),
  241. TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultLabel"),
  242. _GetNameFirstCharUCase());
  243. RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szLabel,
  244. ARRAYSIZE(szLabel) * sizeof(TCHAR));
  245. }
  246. if (szLabel[0])
  247. {
  248. AssertMsg(!_pszLegacyRegLabel, TEXT("_InitLegacyRegIconAndLabel: called twice"));
  249. _pszLegacyRegLabel = StrDup(szLabel);
  250. }
  251. }
  252. }
  253. BOOL CMountPoint::_GetLegacyRegLabel(LPTSTR pszLabel, DWORD cchLabel)
  254. {
  255. BOOL fRet;
  256. if (_pszLegacyRegLabel)
  257. {
  258. StrCpyN(pszLabel, _pszLegacyRegLabel, cchLabel);
  259. fRet = TRUE;
  260. }
  261. else
  262. {
  263. *pszLabel = 0;
  264. fRet = FALSE;
  265. }
  266. return fRet;
  267. }
  268. LPCTSTR CMountPoint::_GetNameForFctCall()
  269. {
  270. return _szName;
  271. }
  272. // the first character in the name, and convert it to upper case
  273. // the first character is generally the drive letter
  274. TCHAR CMountPoint::_GetNameFirstCharUCase()
  275. {
  276. return (TCHAR) CharUpper((LPTSTR) _szName[0]);
  277. }
  278. LPTSTR CMountPoint::_GetNameFirstXChar(LPTSTR pszBuffer, int c)
  279. {
  280. StrCpyN(pszBuffer, _szName, c);
  281. return pszBuffer;
  282. }
  283. LPCTSTR CMountPoint::_GetNameDebug()
  284. {
  285. return _szName;
  286. }
  287. LPCTSTR CMountPoint::_GetName()
  288. {
  289. return _szName;
  290. }
  291. ///////////////////////////////////////////////////////////////////////////////
  292. // Misc
  293. ///////////////////////////////////////////////////////////////////////////////
  294. //
  295. // External API for use by non-CPP modules.
  296. //
  297. HRESULT MountPoint_RegisterChangeNotifyAlias(int iDrive)
  298. {
  299. HRESULT hr = E_FAIL;
  300. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  301. if (pMtPt)
  302. {
  303. pMtPt->ChangeNotifyRegisterAlias();
  304. pMtPt->Release();
  305. hr = NOERROR;
  306. }
  307. return hr;
  308. }
  309. HRESULT CMountPoint::GetComment(LPTSTR pszComment, DWORD cchComment)
  310. {
  311. RSGetTextValue(NULL, TEXT("_CommentFromDesktopINI"), pszComment, &cchComment);
  312. return *pszComment ? S_OK : E_FAIL;
  313. }
  314. BOOL CMountPoint::GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName)
  315. {
  316. return _GetFileSystemName(pszFileSysName, cchFileSysName);
  317. }
  318. BOOL CMountPoint::_GetLabelFromReg(LPWSTR psz, DWORD cch)
  319. {
  320. *psz = 0;
  321. return (RSGetTextValue(NULL, TEXT("_LabelFromReg"), psz, &cch) && *psz);
  322. }
  323. BOOL CMountPoint::_GetLabelFromDesktopINI(LPWSTR psz, DWORD cch)
  324. {
  325. *psz = 0;
  326. return (RSGetTextValue(NULL, TEXT("_LabelFromDesktopINI"), psz, &cch) && *psz);
  327. }
  328. DWORD CMountPoint::GetAttributes()
  329. {
  330. DWORD dwAttrib;
  331. _GetFileAttributes(&dwAttrib);
  332. return dwAttrib;
  333. }
  334. CMountPoint::CMountPoint() : _cRef(1)
  335. {
  336. }
  337. ULONG CMountPoint::AddRef()
  338. {
  339. return InterlockedIncrement(&_cRef);
  340. }
  341. ULONG CMountPoint::Release()
  342. {
  343. if (InterlockedDecrement(&_cRef) > 0)
  344. return _cRef;
  345. delete this;
  346. return 0;
  347. }