* Implement drive checking dialog with fmifs library
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 14 Aug 2008 14:47:31 +0000 (14:47 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Thu, 14 Aug 2008 14:47:31 +0000 (14:47 +0000)
svn path=/trunk/; revision=35337

reactos/dll/win32/shell32/drive.c

index 5bc61a3..8f963fc 100644 (file)
@@ -92,6 +92,20 @@ VOID
        IN PFMIFSCALLBACK Callback\r
 );\r
 \r
+typedef\r
+VOID \r
+(NTAPI *CHKDSK)(\r
+       IN PWCHAR DriveRoot,\r
+       IN PWCHAR Format,\r
+       IN BOOLEAN CorrectErrors,\r
+       IN BOOLEAN Verbose,\r
+       IN BOOLEAN CheckOnlyIfDirty,\r
+       IN BOOLEAN ScanDrive,\r
+       IN PVOID Unused2,\r
+       IN PVOID Unused3,\r
+       IN PFMIFSCALLBACK Callback\r
+);\r
+\r
 \r
 typedef struct\r
 {\r
@@ -101,9 +115,13 @@ typedef struct
     QUERY_AVAILABLEFSFORMAT QueryAvailableFileSystemFormat;\r
     FORMAT_EX FormatEx;\r
     ENABLEVOLUMECOMPRESSION EnableVolumeCompression;\r
+    CHKDSK Chkdsk;\r
     UINT Result;\r
 }FORMAT_DRIVE_CONTEXT, *PFORMAT_DRIVE_CONTEXT;\r
 \r
+BOOL InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext);\r
+BOOL GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes);\r
+\r
 HWND WINAPI\r
 DeviceCreateHardwarePageEx(HWND hWndParent,\r
                            LPGUID lpGuids,\r
@@ -116,6 +134,172 @@ HPROPSHEETPAGE SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPARAM
 \r
 extern HINSTANCE shell32_hInstance;\r
 \r
+VOID\r
+GetDriveNameWithLetter(LPWSTR szText, UINT Length, WCHAR Drive)\r
+{\r
+   WCHAR szDrive[] = {'C',':','\\', 0};\r
+   DWORD dwMaxComp, dwFileSys, TempLength = 0;\r
+\r
+    szDrive[0] = Drive;\r
+    if (GetVolumeInformationW(szDrive, szText, Length, NULL, &dwMaxComp, &dwFileSys, NULL, 0))\r
+    {\r
+        szText[Length-1] = L'\0';\r
+        TempLength = wcslen(szText);\r
+        if (!TempLength)\r
+        {\r
+            /* load default volume label */\r
+            TempLength = LoadStringW(shell32_hInstance, IDS_DRIVE_FIXED, &szText[Length+1], (sizeof(szText)/sizeof(WCHAR))- Length - 2);\r
+        }\r
+    }\r
+    if (TempLength + 4 < Length)\r
+    {\r
+        szText[TempLength] = L' ';\r
+        szText[TempLength+1] = L'(';\r
+        szText[TempLength+2] = szDrive[0];\r
+        szText[TempLength+3] = L')';\r
+        TempLength +=4;\r
+    }\r
+\r
+    if (TempLength < Length)\r
+        szText[TempLength] = L'\0';\r
+    else\r
+        szText[Length-1] = L'\0';\r
+}\r
+\r
+\r
+VOID\r
+InitializeChkDskDialog(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)\r
+{\r
+    WCHAR szText[100];\r
+    UINT Length;\r
+    SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pContext);\r
+\r
+    Length = GetWindowTextW(hwndDlg, szText, sizeof(szText)/sizeof(WCHAR));\r
+\r
+    GetDriveNameWithLetter(&szText[Length +1], (sizeof(szText)/sizeof(WCHAR))-Length-1, pContext->Drive);\r
+    szText[Length] = L' ';\r
+    szText[(sizeof(szText)/sizeof(WCHAR))-1] = L'\0';\r
+    SetWindowText(hwndDlg, szText);\r
+}\r
+\r
+HWND ChkdskDrvDialog = NULL;\r
+BOOLEAN bChkdskSuccess = FALSE;\r
+\r
+BOOLEAN\r
+NTAPI\r
+ChkdskCallback(\r
+       IN CALLBACKCOMMAND Command,\r
+       IN ULONG SubAction,\r
+       IN PVOID ActionInfo)\r
+{\r
+    PDWORD Progress;\r
+    PBOOLEAN pSuccess;\r
+    switch(Command)\r
+    {\r
+        case PROGRESS:\r
+            Progress = (PDWORD)ActionInfo;\r
+            SendDlgItemMessageW(ChkdskDrvDialog, 14002, PBM_SETPOS, (WPARAM)*Progress, 0);\r
+            break;\r
+        case DONE:\r
+            pSuccess = (PBOOLEAN)ActionInfo;\r
+            bChkdskSuccess = (*pSuccess);\r
+            break;\r
+\r
+        case VOLUMEINUSE:\r
+        case INSUFFICIENTRIGHTS:\r
+        case FSNOTSUPPORTED:\r
+        case CLUSTERSIZETOOSMALL:\r
+            bChkdskSuccess = FALSE;\r
+            FIXME("\n");\r
+            break;\r
+\r
+        default:\r
+            break;\r
+    }\r
+\r
+    return TRUE;\r
+}\r
+\r
+VOID\r
+ChkDskNow(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)\r
+{\r
+    DWORD ClusterSize = 0, dwMaxComponentLength, FileSystemFlags;\r
+    WCHAR szFs[30];\r
+    WCHAR szDrive[] = {'C',':','\\', 0};\r
+    WCHAR szVolumeLabel[40];\r
+    ULARGE_INTEGER TotalNumberOfFreeBytes, FreeBytesAvailableUser;\r
+    BOOLEAN bCorrectErrors = FALSE, bScanDrive = FALSE;\r
+\r
+    szDrive[0] = pContext->Drive;\r
+    if(!GetVolumeInformationW(szDrive, szVolumeLabel, sizeof(szVolumeLabel)/sizeof(WCHAR), NULL, &dwMaxComponentLength, &FileSystemFlags, szFs, sizeof(szFs)/sizeof(WCHAR)))\r
+    {\r
+        FIXME("failed to get drive fs type\n");\r
+        return;\r
+    }\r
+\r
+    if (!GetDiskFreeSpaceExW(szDrive, &FreeBytesAvailableUser, &TotalNumberOfFreeBytes, NULL))\r
+    {\r
+        FIXME("failed to get drive space type\n");\r
+        return;\r
+    }\r
+\r
+    if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfFreeBytes))\r
+    {\r
+        FIXME("invalid cluster size\n");\r
+        return;\r
+    }\r
+\r
+    if (SendDlgItemMessageW(hwndDlg, 14000, BM_GETCHECK, 0, 0) == BST_CHECKED)\r
+        bCorrectErrors = TRUE;\r
+\r
+    if (SendDlgItemMessageW(hwndDlg, 14001, BM_GETCHECK, 0, 0) == BST_CHECKED)\r
+        bScanDrive = TRUE;\r
+\r
+    ChkdskDrvDialog = hwndDlg;\r
+    bChkdskSuccess = FALSE;\r
+    SendDlgItemMessageW(hwndDlg, 14002, PBM_SETRANGE, 0, MAKELPARAM(0, 100));\r
+    pContext->Chkdsk(szDrive, szFs, bCorrectErrors, TRUE, FALSE, bScanDrive, NULL, NULL, ChkdskCallback);\r
+    \r
+    ChkdskDrvDialog = NULL;\r
+    pContext->Result = bChkdskSuccess;\r
+    bChkdskSuccess = FALSE;\r
+\r
+}\r
+\r
+INT_PTR\r
+CALLBACK\r
+ChkDskDlg(\r
+    HWND hwndDlg,\r
+    UINT uMsg,\r
+    WPARAM wParam,\r
+    LPARAM lParam\r
+)\r
+{\r
+    PFORMAT_DRIVE_CONTEXT pContext;\r
+    switch(uMsg)\r
+    {\r
+        case WM_INITDIALOG:\r
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lParam);\r
+            InitializeChkDskDialog(hwndDlg, (PFORMAT_DRIVE_CONTEXT)lParam);\r
+            return TRUE;\r
+       case WM_COMMAND:\r
+            switch(LOWORD(wParam))\r
+            {\r
+                case IDCANCEL:\r
+                    EndDialog(hwndDlg, 0);\r
+                    break;\r
+                case IDOK:\r
+                    pContext = (PFORMAT_DRIVE_CONTEXT) GetWindowLongPtr(hwndDlg, DWLP_USER);\r
+                    ChkDskNow(hwndDlg, pContext);\r
+                    break;\r
+            }\r
+            break;\r
+    }\r
+\r
+    return FALSE;\r
+}\r
+\r
+\r
 static\r
 LARGE_INTEGER\r
 GetFreeBytesShare(LARGE_INTEGER TotalNumberOfFreeBytes, LARGE_INTEGER TotalNumberOfBytes)\r
@@ -365,11 +549,12 @@ DriveExtraDlg(
 {\r
    STARTUPINFOW si;\r
    PROCESS_INFORMATION pi;\r
-   WCHAR szPath[MAX_PATH];\r
+   WCHAR szPath[MAX_PATH + 10];\r
    WCHAR szArg[MAX_PATH];\r
    WCHAR * szDrive;\r
-   UINT length;\r
    LPPROPSHEETPAGEW ppsp;\r
+   DWORD dwSize;\r
+   FORMAT_DRIVE_CONTEXT Context;\r
 \r
    switch (uMsg)\r
    {\r
@@ -381,38 +566,58 @@ DriveExtraDlg(
       ZeroMemory( &si, sizeof(si) );\r
       si.cb = sizeof(si);\r
       ZeroMemory( &pi, sizeof(pi) );\r
-      if (!GetSystemDirectoryW(szPath, MAX_PATH))\r
-          break;\r
+\r
       szDrive = (WCHAR*)GetWindowLongPtr(hwndDlg, DWLP_USER);\r
       switch(LOWORD(wParam))\r
       {\r
          case 14000:\r
-            ///\r
-            /// FIXME\r
-            /// show checkdsk dialog\r
-            ///\r
+            if (InitializeFmifsLibrary(&Context))\r
+            {\r
+                Context.Drive = szDrive[0];\r
+                DialogBoxParamW(shell32_hInstance, L"CHKDSK_DLG", hwndDlg, ChkDskDlg, (LPARAM)&Context);\r
+                FreeLibrary(Context.hLibrary);\r
+            }\r
             break;\r
          case 14001:\r
-            szArg[0] = L'"';\r
-            wcscpy(&szArg[1], szPath);\r
-            wcscat(szPath, L"\\mmc.exe");\r
-            wcscat(szArg, L"\\dfrg.msc\" ");\r
-            length = wcslen(szArg);\r
-            szArg[length] = szDrive[0];\r
-            szArg[length+1] = L':';\r
-            szArg[length+2] = L'\0';\r
-            if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))\r
+            dwSize = sizeof(szPath);\r
+            if (RegGetValueW(HKEY_LOCAL_MACHINE, \r
+                             L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\DefragPath",\r
+                             NULL,\r
+                             RRF_RT_REG_EXPAND_SZ,\r
+                             NULL,\r
+                             (PVOID)szPath,\r
+                             &dwSize) == S_OK)\r
             {\r
-               CloseHandle(pi.hProcess);\r
-               CloseHandle(pi.hThread);\r
+                swprintf(szArg, szPath, szDrive[0]);\r
+               if (!GetSystemDirectoryW(szPath, MAX_PATH))\r
+                   break;\r
+               szDrive = PathAddBackslashW(szPath);\r
+               if (!szDrive)\r
+                   break;\r
+\r
+               wcscat(szDrive, L"mmc.exe");\r
+               if (CreateProcessW(szPath, szArg, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))\r
+               {\r
+                  CloseHandle(pi.hProcess);\r
+                  CloseHandle(pi.hThread);\r
+               }\r
             }\r
             break;\r
          case 14002:\r
-            wcscat(szPath, L"\\ntbackup.exe");\r
-            if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))\r
+            dwSize = sizeof(szPath);\r
+            if (RegGetValueW(HKEY_LOCAL_MACHINE, \r
+                             L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\BackupPath",\r
+                             NULL,\r
+                             RRF_RT_REG_EXPAND_SZ,\r
+                             NULL,\r
+                             (PVOID)szPath,\r
+                             &dwSize) == S_OK)\r
             {\r
-               CloseHandle(pi.hProcess);\r
-               CloseHandle(pi.hThread);\r
+               if (CreateProcessW(szPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))\r
+               {\r
+                  CloseHandle(pi.hProcess);\r
+                  CloseHandle(pi.hThread);\r
+               }\r
             }\r
       }\r
       break;\r
@@ -542,15 +747,76 @@ SH_ShowDriveProperties(WCHAR * drive)
        return TRUE;\r
 }\r
 \r
+BOOL\r
+GetDefaultClusterSize(LPWSTR szFs, PDWORD pClusterSize, PULARGE_INTEGER TotalNumberOfBytes)\r
+{\r
+    DWORD ClusterSize;\r
 \r
+    if (!wcsicmp(szFs, L"FAT16") ||\r
+        !wcsicmp(szFs, L"FAT")) //REACTOS HACK\r
+    {\r
+        if (TotalNumberOfBytes->QuadPart <= (16 * 1024 * 1024))\r
+            ClusterSize = 2048;\r
+        else if (TotalNumberOfBytes->QuadPart <= (32 * 1024 * 1024))\r
+            ClusterSize = 512;\r
+        else if (TotalNumberOfBytes->QuadPart <= (64 * 1024 * 1024))\r
+            ClusterSize = 1024;\r
+        else if (TotalNumberOfBytes->QuadPart <= (128 * 1024 * 1024))\r
+            ClusterSize = 2048;\r
+        else if (TotalNumberOfBytes->QuadPart <= (256 * 1024 * 1024))\r
+            ClusterSize = 4096;\r
+        else if (TotalNumberOfBytes->QuadPart <= (512 * 1024 * 1024))\r
+            ClusterSize = 8192;\r
+        else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))\r
+            ClusterSize = 16384;\r
+        else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))\r
+            ClusterSize = 32768;\r
+        else if (TotalNumberOfBytes->QuadPart <= (4096LL * 1024LL * 1024LL))\r
+            ClusterSize = 8192;\r
+        else \r
+            return FALSE;\r
+    }\r
+    else if (!wcsicmp(szFs, L"FAT32"))\r
+    {\r
+        if (TotalNumberOfBytes->QuadPart <=(64 * 1024 * 1024))\r
+            ClusterSize = 512;\r
+        else if (TotalNumberOfBytes->QuadPart <= (128   * 1024 * 1024))\r
+            ClusterSize = 1024;\r
+        else if (TotalNumberOfBytes->QuadPart <= (256   * 1024 * 1024))\r
+            ClusterSize = 2048;\r
+        else if (TotalNumberOfBytes->QuadPart <= (8192LL  * 1024LL * 1024LL))\r
+            ClusterSize = 2048;\r
+        else if (TotalNumberOfBytes->QuadPart <= (16384LL * 1024LL * 1024LL))\r
+            ClusterSize = 8192;\r
+        else if (TotalNumberOfBytes->QuadPart <= (32768LL * 1024LL * 1024LL))\r
+            ClusterSize = 16384;\r
+        else \r
+            return FALSE;\r
+   }\r
+    else if (!wcsicmp(szFs, L"NTFS"))\r
+    {\r
+        if (TotalNumberOfBytes->QuadPart <=(512 * 1024 * 1024))\r
+            ClusterSize = 512;\r
+        else if (TotalNumberOfBytes->QuadPart <= (1024 * 1024 * 1024))\r
+            ClusterSize = 1024;\r
+        else if (TotalNumberOfBytes->QuadPart <= (2048LL * 1024LL * 1024LL))\r
+            ClusterSize = 2048;\r
+        else\r
+            ClusterSize = 2048;\r
+   }\r
+   else\r
+        return FALSE;\r
 \r
+   *pClusterSize = ClusterSize;\r
+   return TRUE;\r
+}\r
 \r
 \r
 VOID\r
 InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)\r
 {\r
     WCHAR szFs[100] = {0};\r
-       WCHAR szDrive[4] = { L'C', ':', '\\', 0 };\r
+    WCHAR szDrive[4] = { L'C', ':', '\\', 0 };\r
     INT iSelIndex;\r
     ULARGE_INTEGER FreeBytesAvailableUser, TotalNumberOfBytes;\r
     DWORD ClusterSize;\r
@@ -574,30 +840,13 @@ InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
     if (!wcsicmp(szFs, L"FAT16") ||\r
         !wcsicmp(szFs, L"FAT")) //REACTOS HACK\r
     {\r
-        if (TotalNumberOfBytes.QuadPart <= (16 * 1024 * 1024))\r
-            ClusterSize = 2048;\r
-        else if (TotalNumberOfBytes.QuadPart <= (32 * 1024 * 1024))\r
-            ClusterSize = 512;\r
-        else if (TotalNumberOfBytes.QuadPart <= (64 * 1024 * 1024))\r
-            ClusterSize = 1024;\r
-        else if (TotalNumberOfBytes.QuadPart <= (128 * 1024 * 1024))\r
-            ClusterSize = 2048;\r
-        else if (TotalNumberOfBytes.QuadPart <= (256 * 1024 * 1024))\r
-            ClusterSize = 4096;\r
-        else if (TotalNumberOfBytes.QuadPart <= (512 * 1024 * 1024))\r
-            ClusterSize = 8192;\r
-        else if (TotalNumberOfBytes.QuadPart <= (1024 * 1024 * 1024))\r
-            ClusterSize = 16384;\r
-        else if (TotalNumberOfBytes.QuadPart <= (2048LL * 1024LL * 1024LL))\r
-            ClusterSize = 32768;\r
-        else if (TotalNumberOfBytes.QuadPart <= (4096LL * 1024LL * 1024LL))\r
-            ClusterSize = 8192;\r
-        else \r
+        if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))\r
         {\r
             TRACE("FAT16 is not supported on hdd larger than 4G current %lu\n", TotalNumberOfBytes.QuadPart);\r
             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);\r
             return;\r
         }\r
+\r
         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))\r
         {\r
             hDlgCtrl = GetDlgItem(hwndDlg, 28680);\r
@@ -611,19 +860,7 @@ InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
     }\r
     else if (!wcsicmp(szFs, L"FAT32"))\r
     {\r
-        if (TotalNumberOfBytes.QuadPart <=(64 * 1024 * 1024))\r
-            ClusterSize = 512;\r
-        else if (TotalNumberOfBytes.QuadPart <= (128   * 1024 * 1024))\r
-            ClusterSize = 1024;\r
-        else if (TotalNumberOfBytes.QuadPart <= (256   * 1024 * 1024))\r
-            ClusterSize = 2048;\r
-        else if (TotalNumberOfBytes.QuadPart <= (8192LL  * 1024LL * 1024LL))\r
-            ClusterSize = 2048;\r
-        else if (TotalNumberOfBytes.QuadPart <= (16384LL * 1024LL * 1024LL))\r
-            ClusterSize = 8192;\r
-        else if (TotalNumberOfBytes.QuadPart <= (32768LL * 1024LL * 1024LL))\r
-            ClusterSize = 16384;\r
-        else \r
+        if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))\r
         {\r
             TRACE("FAT32 is not supported on hdd larger than 32G current %lu\n", TotalNumberOfBytes.QuadPart);\r
             SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);\r
@@ -643,14 +880,12 @@ InsertDefaultClusterSizeForFs(HWND hwndDlg, PFORMAT_DRIVE_CONTEXT pContext)
     }\r
     else if (!wcsicmp(szFs, L"NTFS"))\r
     {\r
-        if (TotalNumberOfBytes.QuadPart <=(512 * 1024 * 1024))\r
-            ClusterSize = 512;\r
-        else if (TotalNumberOfBytes.QuadPart <= (1024 * 1024 * 1024))\r
-            ClusterSize = 1024;\r
-        else if (TotalNumberOfBytes.QuadPart <= (2048LL * 1024LL * 1024LL))\r
-            ClusterSize = 2048;\r
-        else\r
-            ClusterSize = 2048;\r
+        if (!GetDefaultClusterSize(szFs, &ClusterSize, &TotalNumberOfBytes))\r
+        {\r
+            TRACE("NTFS is not supported on hdd larger than 2TB current %lu\n", TotalNumberOfBytes.QuadPart);\r
+            SendMessageW(hDlgCtrl, CB_DELETESTRING, iSelIndex, 0);\r
+            return;\r
+        }\r
 \r
         hDlgCtrl = GetDlgItem(hwndDlg, 28680);\r
         if (LoadStringW(shell32_hInstance, IDS_DEFAULT_CLUSTER_SIZE, szFs, sizeof(szFs)/sizeof(WCHAR)))\r
@@ -1016,6 +1251,14 @@ InitializeFmifsLibrary(PFORMAT_DRIVE_CONTEXT pContext)
         return FALSE;\r
     }\r
 \r
+    pContext->Chkdsk = (CHKDSK) GetProcAddress(hLibrary, "Chkdsk");\r
+    if (!pContext->Chkdsk)\r
+    {\r
+        ERR("Chkdsk export is missing\n");\r
+        FreeLibrary(hLibrary);\r
+        return FALSE;\r
+    }\r
+\r
     return TRUE;\r
 }\r
 \r