2 * Copyright (C) 1998 Transarc Corporation.
9 * Includes _________________________________________________________________
13 #include <afs/param.h>
19 #include "volume_utils.h"
21 #include "partition_utils.h"
25 * Definitions _________________________________________________________________
28 static HWND m_hDriveList = 0;
30 static const UINT MAX_DRIVES = 26;
31 static const UINT DISK_DRIVE_IMAGE = 0;
32 static const UINT DISABLED_DISK_DRIVE_IMAGE = 1;
33 static const UINT DISK_DRIVE_WITH_WARNING_IMAGE = 2;
34 static const UINT AFS_DISK_DRIVE_IMAGE = 3;
39 TCHAR szRootDir[4]; // Drive letter plus colon plus slash, ex: "c:\"
41 TCHAR szSize[32]; // Drive size in megabytes
43 BOOL bDisabled; // Disabled is TRUE if partition not suitable for AFS
44 UINT nImage; // Image to show in the FastList
49 * Prototypes ____________________________________________________________________
55 * Static Functions _________________________________________________________________
58 LPTSTR GetString(UINT nStrID)
60 static TCHAR szText[cchRESOURCE];
62 GetString(szText, nStrID);
67 static BOOL SetupImageLists()
69 HIMAGELIST hiList = ImageList_Create(16, 16, TRUE, 1, 1);
71 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE, FALSE);
72 AfsAppLib_AddToImageList(hiList, IDI_DISABLED_DISK_DRIVE, FALSE);
73 AfsAppLib_AddToImageList(hiList, IDI_DISK_DRIVE_WITH_WARNING, FALSE);
74 AfsAppLib_AddToImageList(hiList, IDI_AGGREGATE, FALSE);
76 FastList_SetImageLists(m_hDriveList, hiList, 0);
81 static void AddColumn(int nWidth, LPCTSTR pszTitle)
86 col.dwFlags = FLCF_JUSTIFY_LEFT;
88 lstrcpy(col.szText, pszTitle);
90 FastList_SetColumn(m_hDriveList, nCol++, &col);
93 static void SetupDriveListCols()
95 // Set width of cols based on width of the list
97 GetClientRect(m_hDriveList, &rect);
99 int nWidth = rect.right - rect.left;
101 // If the width of the list is too small to show all
102 // three cols in a reasonable size that will fit without
103 // scrolling, then set the width to the ideal size and
104 // make the user scroll.
105 if (nWidth < 150) // Minimum we will accept
106 nWidth = 370; // The ideal size
108 AddColumn(50, GetString(IDS_DRIVE));
109 AddColumn(nWidth - 100, GetString(IDS_NAME_OR_ERROR));
110 AddColumn(50, GetString(IDS_SIZE));
113 static LPCTSTR GetDriveSizeAsString(LPCTSTR pszRootDir)
115 _ASSERTE(pszRootDir != 0);
117 ULARGE_INTEGER liDummy;
118 ULARGE_INTEGER liSize;
119 static TCHAR szSize[64];
123 // Get partition size in bytes
124 if (GetDiskFreeSpaceEx(pszRootDir, &liDummy, &liSize, &liDummy)) {
125 // Covert to megabytes
126 ULONG nSize = (ULONG)(liSize.QuadPart / (1024 * 1024));
127 // Convert to a string
128 _ultot(nSize, szSize, 10);
129 lstrcat(szSize, TEXT(" MB"));
135 static BOOL DoesDriveContainData(LPCTSTR pszDriveRootDir)
137 TCHAR szSearchSpec[16];
138 WIN32_FIND_DATA findData;
140 _stprintf(szSearchSpec, TEXT("%s*.*"), pszDriveRootDir);
142 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
143 if (hFind == INVALID_HANDLE_VALUE)
151 static BOOL OnlyHasFolder(LPCTSTR pszRootDir, LPCTSTR pszFolder)
153 TCHAR szSearchSpec[MAX_PATH];
154 WIN32_FIND_DATA findData;
157 _stprintf(szSearchSpec, TEXT("%s*.*"), pszRootDir);
159 // If there is nothing in the root dir, then return FALSE
160 HANDLE hFind = FindFirstFile(szSearchSpec, &findData);
161 if (hFind == INVALID_HANDLE_VALUE)
164 // Is the first thing on the disk the recycle bin? If not
165 // the the recycle bin is not the only thing on the disk.
166 if (_tcsicmp(findData.cFileName, pszFolder) == 0) {
167 // Is anything else on the disk?
168 if (!FindNextFile(hFind, &findData))
177 static BOOL DriveHasRecycleBin(LPCTSTR pszDriveRootDir)
179 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycled")))
182 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycle Bin")))
185 if (OnlyHasFolder(pszDriveRootDir, TEXT("Recycler")))
191 static BOOL DoesDriveContainNT(LPCTSTR pszDriveRootDir)
193 UINT nBufSize = MAX_PATH;
194 LPTSTR pszWinDir = 0;
197 pszWinDir = new TCHAR[nBufSize];
199 UINT nWinDirLen = GetWindowsDirectory(pszWinDir, nBufSize);
201 if (nWinDirLen > nBufSize) {
202 nBufSize = nWinDirLen;
208 BOOL bNT = (_tcsncmp(pszDriveRootDir, pszWinDir, 3) == 0);
215 static BOOL ValidateDrive(BOOL bInvalid, UINT uiErrorMsgID, LPTSTR pszErrorStr)
221 lstrcat(pszErrorStr, GetString(IDS_ERROR_SEP));
222 lstrcat(pszErrorStr, GetString(uiErrorMsgID));
227 static BOOL GetDriveInfo(TCHAR chDrive, DRIVE_INFO& di)
233 _stprintf(di.szRootDir, TEXT("%c:\\"), chDrive);
235 if (GetDriveType(di.szRootDir) != DRIVE_FIXED)
238 if (!GetVolumeInformation(di.szRootDir, di.szVolName, sizeof(di.szVolName), 0, &dwDummy, &dwDriveFlags, szFileSys, sizeof(szFileSys)))
241 TCHAR szError[256] = TEXT("");
243 BOOL bInvalid = FALSE, bHasData = FALSE;
244 BOOL bIsAfs = ValidateDrive(IsAnAfsPartition(di.szRootDir), IDS_ERROR_DRIVE_ALREADY_HAS_AFS, szError);
246 bInvalid |= ValidateDrive(dwDriveFlags & FS_VOL_IS_COMPRESSED, IDS_ERROR_DRIVE_COMPRESSED, szError);
247 bInvalid |= ValidateDrive(lstrcmp(szFileSys, TEXT("NTFS")) != 0, IDS_ERROR_FS_IS_NOT_NTFS, szError);
250 * We are no longer going to require that afs drives be empty; we will give a warning instead.
252 * bInvalid |= ValidateDrive(DoesDriveContainNT(di.szRootDir), IDS_ERROR_DRIVE_CONTAINS_NT, szError);
253 * bRecycle = ValidateDrive(DriveHasRecycleBin(di.szRootDir), IDS_WARNING_DRIVE_HAS_RECYCLE_BIN, szError);
256 bHasData = ValidateDrive(DoesDriveContainData(di.szRootDir), IDS_ERROR_DRIVE_HAS_DATA, szError);
260 lstrcpy(di.szVolName, szError);
263 di.nImage = AFS_DISK_DRIVE_IMAGE;
265 di.nImage = DISK_DRIVE_WITH_WARNING_IMAGE; // Treat this as a warning
267 di.nImage = DISABLED_DISK_DRIVE_IMAGE;
269 if (bIsAfs || bInvalid) {
271 di.dwFlags |= FLIF_DISALLOW_SELECT;
274 di.nImage = DISK_DRIVE_IMAGE;
276 if (lstrlen(di.szVolName) == 0)
277 GetString(di.szVolName, IDS_VOLUME_HAS_NO_NAME);
280 lstrncpy(di.szSize, GetDriveSizeAsString(di.szRootDir), sizeof(di.szSize));
285 static BOOL FillDriveList()
289 TCHAR chDrive = TEXT('A');
290 DWORD dwDrives = GetLogicalDrives();
292 // This failing is not fatal to this function
293 // Make sure the partition table is up to date
294 afs_status_t nStatus;
295 int nResult = ReadPartitionTable(&nStatus);
300 memset(&di, 0, sizeof(di));
302 if (GetDriveInfo(chDrive, di)) {
303 FASTLISTADDITEM ai = { 0, di.nImage, IMAGE_NOIMAGE, di.szRootDir, di.bDisabled, di.dwFlags };
304 HLISTITEM hItem = FastList_AddItem(m_hDriveList, &ai);
305 FastList_SetItemText(m_hDriveList, hItem, 1, di.szVolName);
306 FastList_SetItemText(m_hDriveList, hItem, 2, di.szSize);
317 static int CALLBACK DriveListSortFunc(HWND hList, HLISTITEM hItem1, LPARAM lpItem1, HLISTITEM hItem2, LPARAM lpItem2)
319 _ASSERTE(hList == m_hDriveList);
321 // Ignore the first call which is only used to initialize static data
322 if (!hItem1 && !hItem2)
325 // The lpItem vars contain 1 if the item is disabled, 0 if not
326 // Show enabled items before disabled items
327 if (lpItem1 != lpItem2)
328 return lpItem1 - lpItem2;
330 LPCTSTR pszItem1 = FastList_GetItemText(m_hDriveList, hItem1, 0);
331 LPCTSTR pszItem2 = FastList_GetItemText(m_hDriveList, hItem2, 0);
333 return lstrcmp(pszItem1, pszItem2);
338 * Exported Functions _________________________________________________________________
341 void SetupDriveList(HWND driveList)
343 m_hDriveList = driveList;
347 SetupDriveListCols();
349 FastList_SetSortFunction(m_hDriveList, DriveListSortFunc);
352 BOOL UpdateDriveList()
354 FastList_RemoveAll(m_hDriveList);
356 return FillDriveList();