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.

422 lines
12 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. hres = StringCchCopy(pszName, cchName, szDriveLabel);
  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. hres = StringCchCopy(pszName, cchName, psz);
  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. #define REG_TEMPLATE_ICON TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultIcon")
  201. #define REG_TEMPLATE2_ICON TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultIcon")
  202. #define REG_TEMPLATE_LABEL TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultLabel")
  203. #define REG_TEMPLATE2_LABEL TEXT("Applications\\Explorer.exe\\Drives\\%c\\DefaultLabel")
  204. void CMountPoint::_InitLegacyRegIconAndLabel(BOOL fUseAutorunIcon,
  205. BOOL fUseAutorunLabel)
  206. {
  207. // No Autorun icon, load the legacy reg icon if any
  208. if (!fUseAutorunIcon && _IsMountedOnDriveLetter())
  209. {
  210. WCHAR szSubKey[MAX_PATH];
  211. ASSERT(ARRAYSIZE(szSubKey) >= ARRAYSIZE(REG_TEMPLATE_ICON) &&
  212. ARRAYSIZE(szSubKey) >= ARRAYSIZE(REG_TEMPLATE2_ICON) &&
  213. ARRAYSIZE(szSubKey) >= ARRAYSIZE(REG_TEMPLATE_LABEL) &&
  214. ARRAYSIZE(szSubKey) >= ARRAYSIZE(REG_TEMPLATE2_LABEL)); // make sure printfs won't fail
  215. WCHAR szIconLocation[MAX_PATH + 12];
  216. StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey),
  217. REG_TEMPLATE_ICON, _GetNameFirstCharUCase());
  218. szIconLocation[0] = 0;
  219. if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szIconLocation,
  220. ARRAYSIZE(szIconLocation) * sizeof(TCHAR)))
  221. {
  222. // Let's try second location
  223. StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey),
  224. REG_TEMPLATE2_ICON, _GetNameFirstCharUCase());
  225. RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szIconLocation,
  226. ARRAYSIZE(szIconLocation) * sizeof(TCHAR));
  227. }
  228. if (szIconLocation[0])
  229. {
  230. AssertMsg(!_pszLegacyRegIcon, TEXT("_InitLegacyRegIconAndLabel: called twice"));
  231. _pszLegacyRegIcon = StrDup(szIconLocation);
  232. }
  233. }
  234. if (!fUseAutorunLabel && _IsMountedOnDriveLetter())
  235. {
  236. WCHAR szSubKey[MAX_PATH];
  237. WCHAR szLabel[MAX_LABEL];
  238. StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey),
  239. REG_TEMPLATE_LABEL, _GetNameFirstCharUCase());
  240. szLabel[0] = 0;
  241. if (!RegGetValueString(HKEY_LOCAL_MACHINE, szSubKey, NULL, szLabel,
  242. ARRAYSIZE(szLabel) * sizeof(TCHAR)))
  243. {
  244. // Let's try second location
  245. StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey),
  246. REG_TEMPLATE2_LABEL, _GetNameFirstCharUCase());
  247. RegGetValueString(HKEY_CLASSES_ROOT, szSubKey, NULL, szLabel,
  248. ARRAYSIZE(szLabel) * sizeof(TCHAR));
  249. }
  250. if (szLabel[0])
  251. {
  252. AssertMsg(!_pszLegacyRegLabel, TEXT("_InitLegacyRegIconAndLabel: called twice"));
  253. _pszLegacyRegLabel = StrDup(szLabel);
  254. }
  255. }
  256. }
  257. BOOL CMountPoint::_GetLegacyRegLabel(LPTSTR pszLabel, DWORD cchLabel)
  258. {
  259. BOOL fRet;
  260. if (_pszLegacyRegLabel &&
  261. SUCCEEDED(StringCchCopy(pszLabel, cchLabel, _pszLegacyRegLabel)))
  262. {
  263. fRet = TRUE;
  264. }
  265. else
  266. {
  267. *pszLabel = 0;
  268. fRet = FALSE;
  269. }
  270. return fRet;
  271. }
  272. LPCTSTR CMountPoint::_GetNameForFctCall()
  273. {
  274. return _szName;
  275. }
  276. // the first character in the name, and convert it to upper case
  277. // the first character is generally the drive letter
  278. TCHAR CMountPoint::_GetNameFirstCharUCase()
  279. {
  280. return (TCHAR) CharUpper((LPTSTR) _szName[0]);
  281. }
  282. LPTSTR CMountPoint::_GetNameFirstXChar(LPTSTR pszBuffer, int c)
  283. {
  284. StringCchCopy(pszBuffer, c, _szName);
  285. return pszBuffer;
  286. }
  287. LPCTSTR CMountPoint::_GetNameDebug()
  288. {
  289. return _szName;
  290. }
  291. LPCTSTR CMountPoint::_GetName()
  292. {
  293. return _szName;
  294. }
  295. ///////////////////////////////////////////////////////////////////////////////
  296. // Misc
  297. ///////////////////////////////////////////////////////////////////////////////
  298. //
  299. // External API for use by non-CPP modules.
  300. //
  301. HRESULT MountPoint_RegisterChangeNotifyAlias(int iDrive)
  302. {
  303. HRESULT hr = E_FAIL;
  304. CMountPoint* pMtPt = CMountPoint::GetMountPoint(iDrive);
  305. if (pMtPt)
  306. {
  307. pMtPt->ChangeNotifyRegisterAlias();
  308. pMtPt->Release();
  309. hr = NOERROR;
  310. }
  311. return hr;
  312. }
  313. HRESULT CMountPoint::GetComment(LPTSTR pszComment, DWORD cchComment)
  314. {
  315. RSGetTextValue(NULL, TEXT("_CommentFromDesktopINI"), pszComment, &cchComment);
  316. return *pszComment ? S_OK : E_FAIL;
  317. }
  318. BOOL CMountPoint::GetFileSystemName(LPTSTR pszFileSysName, DWORD cchFileSysName)
  319. {
  320. return _GetFileSystemName(pszFileSysName, cchFileSysName);
  321. }
  322. BOOL CMountPoint::_GetLabelFromReg(LPWSTR psz, DWORD cch)
  323. {
  324. *psz = 0;
  325. return (RSGetTextValue(NULL, TEXT("_LabelFromReg"), psz, &cch) && *psz);
  326. }
  327. BOOL CMountPoint::_GetLabelFromDesktopINI(LPWSTR psz, DWORD cch)
  328. {
  329. *psz = 0;
  330. return (RSGetTextValue(NULL, TEXT("_LabelFromDesktopINI"), psz, &cch) && *psz);
  331. }
  332. DWORD CMountPoint::GetAttributes()
  333. {
  334. DWORD dwAttrib;
  335. _GetFileAttributes(&dwAttrib);
  336. return dwAttrib;
  337. }
  338. CMountPoint::CMountPoint() : _cRef(1)
  339. {
  340. }
  341. ULONG CMountPoint::AddRef()
  342. {
  343. return InterlockedIncrement(&_cRef);
  344. }
  345. ULONG CMountPoint::Release()
  346. {
  347. ASSERT( 0 != _cRef );
  348. ULONG cRef = InterlockedDecrement(&_cRef);
  349. if ( 0 == cRef )
  350. {
  351. delete this;
  352. }
  353. return cRef;
  354. }