summaryrefslogtreecommitdiffstats
path: root/private/utils/windisk
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/utils/windisk/clear/clear.cxx105
-rw-r--r--private/utils/windisk/clear/makefile1
-rw-r--r--private/utils/windisk/clear/sources11
-rw-r--r--private/utils/windisk/controls/bmp.cxx219
-rw-r--r--private/utils/windisk/controls/bmppriv.hxx20
-rw-r--r--private/utils/windisk/controls/box.cxx186
-rw-r--r--private/utils/windisk/controls/boxpriv.hxx20
-rw-r--r--private/utils/windisk/controls/controls.cxx45
-rw-r--r--private/utils/windisk/controls/controls.hxx79
-rw-r--r--private/utils/windisk/controls/headers.hxx28
-rw-r--r--private/utils/windisk/controls/line.cxx159
-rw-r--r--private/utils/windisk/controls/linepriv.hxx20
-rw-r--r--private/utils/windisk/controls/makefile1
-rw-r--r--private/utils/windisk/controls/sources22
-rw-r--r--private/utils/windisk/debug/assert.cxx340
-rw-r--r--private/utils/windisk/debug/debug.h284
-rw-r--r--private/utils/windisk/debug/makefile9
-rw-r--r--private/utils/windisk/debug/sources12
-rw-r--r--private/utils/windisk/dirs33
-rw-r--r--private/utils/windisk/diskinfo/diskinfo.cxx273
-rw-r--r--private/utils/windisk/diskinfo/makefile1
-rw-r--r--private/utils/windisk/diskinfo/sources14
-rw-r--r--private/utils/windisk/doc/adskman.docbin0 -> 44990 bytes
-rw-r--r--private/utils/windisk/doc/adskman2.docbin0 -> 99840 bytes
-rw-r--r--private/utils/windisk/doc/demo.txt112
-rw-r--r--private/utils/windisk/doc/dlls.txt81
-rw-r--r--private/utils/windisk/doc/extend.txt24
-rw-r--r--private/utils/windisk/doc/misc.txt51
-rw-r--r--private/utils/windisk/doc/progmgmt.bmpbin0 -> 166518 bytes
-rw-r--r--private/utils/windisk/doc/select.txt75
-rw-r--r--private/utils/windisk/doc/testing.txt48
-rw-r--r--private/utils/windisk/doc/thecode.txt212
-rw-r--r--private/utils/windisk/doc/todo.txt104
-rw-r--r--private/utils/windisk/doc/wddev.docbin0 -> 53248 bytes
-rw-r--r--private/utils/windisk/doc/why.txt154
-rw-r--r--private/utils/windisk/doc/windisk.pptbin0 -> 13321 bytes
-rw-r--r--private/utils/windisk/hard/chard.cxx265
-rw-r--r--private/utils/windisk/hard/chardmnu.cxx271
-rw-r--r--private/utils/windisk/hard/dialogs.dlg8
-rw-r--r--private/utils/windisk/hard/dialogs.h3
-rw-r--r--private/utils/windisk/hard/global.hxx22
-rw-r--r--private/utils/windisk/hard/hard.cxx199
-rw-r--r--private/utils/windisk/hard/hard.def11
-rw-r--r--private/utils/windisk/hard/hard.hxx103
-rw-r--r--private/utils/windisk/hard/hard.rc28
-rw-r--r--private/utils/windisk/hard/hardmenu.cxx192
-rw-r--r--private/utils/windisk/hard/hardmenu.hxx104
-rw-r--r--private/utils/windisk/hard/headers.hxx19
-rw-r--r--private/utils/windisk/hard/libinit.cxx144
-rw-r--r--private/utils/windisk/hard/makefile1
-rw-r--r--private/utils/windisk/hard/makefile.inc6
-rw-r--r--private/utils/windisk/hard/sources40
-rw-r--r--private/utils/windisk/inc/dacommon.h80
-rw-r--r--private/utils/windisk/readme.txt4
-rw-r--r--private/utils/windisk/src/cdpage.cxx348
-rw-r--r--private/utils/windisk/src/cdpage.hxx76
-rw-r--r--private/utils/windisk/src/cdr.bmpbin0 -> 13918 bytes
-rw-r--r--private/utils/windisk/src/cdrom.cxx955
-rw-r--r--private/utils/windisk/src/cdrom.hxx65
-rw-r--r--private/utils/windisk/src/chkdsk.cxx2050
-rw-r--r--private/utils/windisk/src/chkdsk.hxx27
-rw-r--r--private/utils/windisk/src/cm.cxx888
-rw-r--r--private/utils/windisk/src/cm.hxx37
-rw-r--r--private/utils/windisk/src/commit.cxx1849
-rw-r--r--private/utils/windisk/src/commit.hxx101
-rw-r--r--private/utils/windisk/src/const.h146
-rw-r--r--private/utils/windisk/src/data.cxx288
-rw-r--r--private/utils/windisk/src/dblspace.cxx1662
-rw-r--r--private/utils/windisk/src/dblspace.dlg115
-rw-r--r--private/utils/windisk/src/dblspace.h91
-rw-r--r--private/utils/windisk/src/dblspace.hxx59
-rw-r--r--private/utils/windisk/src/dblspace.resbin0 -> 3092 bytes
-rw-r--r--private/utils/windisk/src/dialogs.dlg126
-rw-r--r--private/utils/windisk/src/dialogs.h263
-rw-r--r--private/utils/windisk/src/dialogs.resbin0 -> 3836 bytes
-rw-r--r--private/utils/windisk/src/dispinfo.cxx126
-rw-r--r--private/utils/windisk/src/dispinfo.hxx65
-rw-r--r--private/utils/windisk/src/dlgs.cxx1372
-rw-r--r--private/utils/windisk/src/dlgs.hxx88
-rw-r--r--private/utils/windisk/src/drives.cxx871
-rw-r--r--private/utils/windisk/src/drives.hxx88
-rw-r--r--private/utils/windisk/src/dskmgr.icobin0 -> 766 bytes
-rw-r--r--private/utils/windisk/src/engine.cxx4086
-rw-r--r--private/utils/windisk/src/engine.hxx311
-rw-r--r--private/utils/windisk/src/extend.cxx636
-rw-r--r--private/utils/windisk/src/extend.hxx87
-rw-r--r--private/utils/windisk/src/fill.cxx867
-rw-r--r--private/utils/windisk/src/fill.hxx24
-rw-r--r--private/utils/windisk/src/fmifs.cxx644
-rw-r--r--private/utils/windisk/src/fmifs.hxx183
-rw-r--r--private/utils/windisk/src/format.cxx65
-rw-r--r--private/utils/windisk/src/format.hxx38
-rw-r--r--private/utils/windisk/src/fs.cxx96
-rw-r--r--private/utils/windisk/src/fs.hxx93
-rw-r--r--private/utils/windisk/src/ft.cxx1685
-rw-r--r--private/utils/windisk/src/ft.hxx67
-rw-r--r--private/utils/windisk/src/ftreg.cxx1329
-rw-r--r--private/utils/windisk/src/ftreg.dlg22
-rw-r--r--private/utils/windisk/src/ftreg.h22
-rw-r--r--private/utils/windisk/src/ftreg.hxx34
-rw-r--r--private/utils/windisk/src/genlpage.cxx726
-rw-r--r--private/utils/windisk/src/genlpage.hxx98
-rw-r--r--private/utils/windisk/src/global.hxx233
-rw-r--r--private/utils/windisk/src/graph.cxx793
-rw-r--r--private/utils/windisk/src/graph.hxx32
-rw-r--r--private/utils/windisk/src/hard.bmpbin0 -> 13918 bytes
-rw-r--r--private/utils/windisk/src/headers.hxx95
-rw-r--r--private/utils/windisk/src/help.cxx312
-rw-r--r--private/utils/windisk/src/help.hxx45
-rw-r--r--private/utils/windisk/src/help2.cxx506
-rw-r--r--private/utils/windisk/src/help2.hxx39
-rw-r--r--private/utils/windisk/src/helpid.h220
-rw-r--r--private/utils/windisk/src/init.cxx949
-rw-r--r--private/utils/windisk/src/init.hxx32
-rw-r--r--private/utils/windisk/src/label.cxx216
-rw-r--r--private/utils/windisk/src/label.hxx22
-rw-r--r--private/utils/windisk/src/listbox.cxx1113
-rw-r--r--private/utils/windisk/src/listbox.hxx85
-rw-r--r--private/utils/windisk/src/log.cxx1289
-rw-r--r--private/utils/windisk/src/makefile1
-rw-r--r--private/utils/windisk/src/makefile.inc24
-rw-r--r--private/utils/windisk/src/mem.cxx92
-rw-r--r--private/utils/windisk/src/mem.hxx38
-rw-r--r--private/utils/windisk/src/menudict.cxx201
-rw-r--r--private/utils/windisk/src/menudict.hxx113
-rw-r--r--private/utils/windisk/src/messages.mc617
-rw-r--r--private/utils/windisk/src/misc.cxx1404
-rw-r--r--private/utils/windisk/src/network.cxx184
-rw-r--r--private/utils/windisk/src/network.hxx33
-rw-r--r--private/utils/windisk/src/nt.cxx1187
-rw-r--r--private/utils/windisk/src/nt.hxx115
-rw-r--r--private/utils/windisk/src/ntlow.cxx1134
-rw-r--r--private/utils/windisk/src/ntlow.hxx134
-rw-r--r--private/utils/windisk/src/oleclass.cxx84
-rw-r--r--private/utils/windisk/src/oleclass.hxx29
-rw-r--r--private/utils/windisk/src/ops.cxx2823
-rw-r--r--private/utils/windisk/src/ops.hxx114
-rw-r--r--private/utils/windisk/src/popup.cxx96
-rw-r--r--private/utils/windisk/src/popup.hxx29
-rw-r--r--private/utils/windisk/src/print.cxx338
-rw-r--r--private/utils/windisk/src/print.hxx23
-rw-r--r--private/utils/windisk/src/profile.cxx598
-rw-r--r--private/utils/windisk/src/profile.hxx32
-rw-r--r--private/utils/windisk/src/proto.hxx468
-rw-r--r--private/utils/windisk/src/ps.cxx205
-rw-r--r--private/utils/windisk/src/ps.hxx22
-rw-r--r--private/utils/windisk/src/rect.cxx310
-rw-r--r--private/utils/windisk/src/rectpriv.hxx50
-rw-r--r--private/utils/windisk/src/resids.h514
-rw-r--r--private/utils/windisk/src/rmdisk.bmpbin0 -> 190 bytes
-rw-r--r--private/utils/windisk/src/scdrom.icobin0 -> 318 bytes
-rw-r--r--private/utils/windisk/src/scsi.h77
-rw-r--r--private/utils/windisk/src/select.cxx1845
-rw-r--r--private/utils/windisk/src/select.hxx108
-rw-r--r--private/utils/windisk/src/shard.icobin0 -> 318 bytes
-rw-r--r--private/utils/windisk/src/smcdrom.bmpbin0 -> 190 bytes
-rw-r--r--private/utils/windisk/src/smdisk.bmpbin0 -> 190 bytes
-rw-r--r--private/utils/windisk/src/sources79
-rw-r--r--private/utils/windisk/src/stleg.cxx534
-rw-r--r--private/utils/windisk/src/stleg.hxx50
-rw-r--r--private/utils/windisk/src/tb.h129
-rw-r--r--private/utils/windisk/src/tbar.cxx701
-rw-r--r--private/utils/windisk/src/tbar.hxx52
-rw-r--r--private/utils/windisk/src/tool16.bmpbin0 -> 1910 bytes
-rw-r--r--private/utils/windisk/src/trffc14.icobin0 -> 766 bytes
-rw-r--r--private/utils/windisk/src/types.hxx489
-rw-r--r--private/utils/windisk/src/unused/startup.cxx166
-rw-r--r--private/utils/windisk/src/unused/startup.hxx27
-rw-r--r--private/utils/windisk/src/unused/time.cxx599
-rw-r--r--private/utils/windisk/src/unused/time.hxx39
-rw-r--r--private/utils/windisk/src/volview.cxx400
-rw-r--r--private/utils/windisk/src/volview.hxx36
-rw-r--r--private/utils/windisk/src/windisk.cxx5753
-rw-r--r--private/utils/windisk/src/windisk.hxx140
-rw-r--r--private/utils/windisk/src/windisk.rc563
-rw-r--r--private/utils/windisk/src/xtra16.bmpbin0 -> 630 bytes
-rw-r--r--private/utils/windisk/types/daexts.idl233
-rw-r--r--private/utils/windisk/types/dahard.idl39
-rw-r--r--private/utils/windisk/types/damenu.idl42
-rw-r--r--private/utils/windisk/types/davol.idl39
-rw-r--r--private/utils/windisk/types/guids.h24
-rw-r--r--private/utils/windisk/types/readme.txt2
-rw-r--r--private/utils/windisk/util/debug.cxx95
-rw-r--r--private/utils/windisk/util/headers.hxx32
-rw-r--r--private/utils/windisk/util/makefile1
-rw-r--r--private/utils/windisk/util/sources17
-rw-r--r--private/utils/windisk/util/util.cxx427
-rw-r--r--private/utils/windisk/util/util.hxx100
-rw-r--r--private/utils/windisk/windisk.mk9
189 files changed, 56952 insertions, 0 deletions
diff --git a/private/utils/windisk/clear/clear.cxx b/private/utils/windisk/clear/clear.cxx
new file mode 100644
index 000000000..6f12bcf86
--- /dev/null
+++ b/private/utils/windisk/clear/clear.cxx
@@ -0,0 +1,105 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clear.cxx
+//
+// Contents: Disk Administrator: utility to clear the registry to make it
+// appear that this is the first time Disk Administrator has been
+// run.
+//
+//
+// The following need to be deleted:
+//
+// The registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\windisk.ini
+//
+// The registry key: HKEY_CURRENT_USER\Software\Microsoft\Disk Administrator
+//
+// The registry value: HKEY_CURRENT_MACHINE\System\CurrentControlSet\Control\Lsa : Protect System Partition
+//
+// History: 8-Jun-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+char* program;
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s\n",program);
+ exit(1);
+}
+
+void _CRTAPI1
+main(int argc, char* argv[])
+{
+ char* psz;
+
+ program = argv[0];
+
+ if (argc != 1)
+ {
+ usage();
+ }
+
+ LONG ec;
+ HKEY hkey;
+
+ ec = RegDeleteKeyA( HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\windisk.ini"
+ );
+
+ psz = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\windisk.ini";
+
+ if (ec != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "Couldn't delete %s\n", psz);
+ }
+ else
+ {
+ fprintf(stdout, "Deleted %s\n", psz);
+ }
+
+ ec = RegDeleteKeyA( HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Disk Administrator"
+ );
+
+ psz = "HKEY_CURRENT_USER\\Software\\Microsoft\\Disk Administrator";
+
+ if (ec != ERROR_SUCCESS)
+ {
+ fprintf(stderr, "Couldn't delete %s\n", psz);
+ }
+ else
+ {
+ fprintf(stdout, "Deleted %s\n", psz);
+ }
+
+ //
+ // get rid of the Registry entry concerning a protected system partition
+ //
+
+ ec = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Control\\Lsa"),
+ 0,
+ KEY_SET_VALUE,
+ &hkey
+ );
+
+ if(ec == NO_ERROR)
+ {
+ ec = RegDeleteValue(hkey, TEXT("Protect System Partition"));
+
+ // ignore errors: if we couldn't delete it, it probably wasn't there
+
+ RegCloseKey(hkey);
+ }
+
+
+ exit(0);
+}
diff --git a/private/utils/windisk/clear/makefile b/private/utils/windisk/clear/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/clear/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/clear/sources b/private/utils/windisk/clear/sources
new file mode 100644
index 000000000..39c7f28d0
--- /dev/null
+++ b/private/utils/windisk/clear/sources
@@ -0,0 +1,11 @@
+!include ..\windisk.mk
+
+MINORCOMP= daclear
+
+TARGETNAME= daclear
+TARGETTYPE= PROGRAM
+TARGETPATH= obj
+
+UMTYPE= console
+
+SOURCES= clear.cxx
diff --git a/private/utils/windisk/controls/bmp.cxx b/private/utils/windisk/controls/bmp.cxx
new file mode 100644
index 000000000..b0bca8902
--- /dev/null
+++ b/private/utils/windisk/controls/bmp.cxx
@@ -0,0 +1,219 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: bmp.cxx
+//
+// Contents: Bitmap custom control for use on dialog box.
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "bmppriv.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+#define BITMAP_CONTROL_WNDEXTRA 8
+
+#define GWL_BMPCTL_BITMAP 0
+#define GWL_BMPCTL_HDC 4
+
+////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK
+BitmapControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BitmapControlWndProc
+//
+// Synopsis: The bitmap custom control window procedure
+//
+// Arguments: standard WndProc
+//
+// Returns: standard WndProc
+//
+// History: 26-Jan-94 BruceFo Created (derived from Cairo System
+// Management forms bitmap control)
+//
+//--------------------------------------------------------------------------
+
+LRESULT CALLBACK
+BitmapControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_CREATE:
+ {
+ HDC hdc = GetDC(hwnd);
+ HDC hdcMem = CreateCompatibleDC(hdc);
+ ReleaseDC(hwnd, hdc);
+ SetWindowLong(hwnd, GWL_BMPCTL_HDC, (LONG)hdcMem);
+
+ SetWindowLong(hwnd, GWL_BMPCTL_BITMAP, (LONG)NULL);
+ break;
+ }
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint(hwnd,&ps);
+
+ if (!IsIconic(hwnd))
+ {
+ HBITMAP hbmp = (HBITMAP)GetWindowLong(hwnd, GWL_BMPCTL_BITMAP);
+
+ if (NULL != hbmp)
+ {
+ HDC hdcMem = (HDC)GetWindowLong(hwnd, GWL_BMPCTL_HDC);
+ HBITMAP hbmpOld = SelectBitmap(hdcMem, hbmp);
+
+ BITMAP bmp;
+ GetObject(hbmp, sizeof(bmp), &bmp);
+
+ BitBlt(
+ ps.hdc,
+ 0,
+ 0,
+ bmp.bmWidth,
+ bmp.bmHeight,
+ hdcMem,
+ 0,
+ 0,
+ SRCCOPY
+ );
+
+ SelectBitmap(hdcMem, hbmpOld);
+ }
+ }
+
+ EndPaint(hwnd,&ps);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ HBITMAP hbmp = (HBITMAP)GetWindowLong(hwnd, GWL_BMPCTL_BITMAP);
+ if (NULL != hbmp)
+ {
+ DeleteBitmap(hbmp);
+ }
+
+ HDC hdcMem = (HDC)GetWindowLong(hwnd, GWL_BMPCTL_HDC);
+ ReleaseDC(hwnd, hdcMem);
+
+ break;
+ }
+
+ case BMPCTL_SETBITMAP:
+ {
+ // wParam = hBitmap
+
+ HBITMAP hbmp = (HBITMAP)GetWindowLong(hwnd, GWL_BMPCTL_BITMAP);
+
+ if (NULL != hbmp)
+ {
+ DeleteBitmap(hbmp);
+ }
+
+ SetWindowLong(hwnd, GWL_BMPCTL_BITMAP, (LONG)wParam);
+
+ InvalidateRect(hwnd, NULL, TRUE); // force a repaint
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+ }
+
+ return 1;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UseBitmapControl
+//
+// Synopsis: Initializes the bitmap custom control. Registers its
+// window class.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: 0 on success, else Win32 error
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+DWORD
+UseBitmapControl(
+ IN HINSTANCE hInstance
+ )
+{
+ WNDCLASS wc;
+
+ wc.style = 0;
+ wc.lpfnWndProc = BitmapControlWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = BITMAP_CONTROL_WNDEXTRA;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = BITMAP_CONTROL_STRING;
+
+ if (0 == RegisterClass(&wc))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseBitmapControl
+//
+// Synopsis:
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: 0 on success, else Win32 error
+//
+// History: 7-Oct-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+ReleaseBitmapControl(
+ IN HINSTANCE hInstance
+ )
+{
+ if (!UnregisterClass(BITMAP_CONTROL_STRING, hInstance))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
diff --git a/private/utils/windisk/controls/bmppriv.hxx b/private/utils/windisk/controls/bmppriv.hxx
new file mode 100644
index 000000000..eb83461e1
--- /dev/null
+++ b/private/utils/windisk/controls/bmppriv.hxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: bmp.hxx
+//
+// Contents: Declarations for the bitmap custom control
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+#ifndef __BMP_HXX__
+#define __BMP_HXX__
+
+DWORD UseBitmapControl(IN HINSTANCE hInstance);
+DWORD ReleaseBitmapControl(IN HINSTANCE hInstance);
+
+#endif // __BMP_HXX__
diff --git a/private/utils/windisk/controls/box.cxx b/private/utils/windisk/controls/box.cxx
new file mode 100644
index 000000000..a1244ef2c
--- /dev/null
+++ b/private/utils/windisk/controls/box.cxx
@@ -0,0 +1,186 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: box.cxx
+//
+// Contents: Color box custom control for use on dialog box.
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "boxpriv.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+#define COLORBOX_CONTROL_WNDEXTRA 4
+
+#define GWL_BOXCTL_COLOR 0
+
+#define ILLEGAL_COLOR ((COLORREF)-1)
+
+////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK
+BoxControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BoxControlWndProc
+//
+// Synopsis: The color box custom control window procedure
+//
+// Arguments: standard WndProc
+//
+// Returns: standard WndProc
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+LRESULT CALLBACK
+BoxControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_CREATE:
+ {
+ SetWindowLong(hwnd, GWL_BOXCTL_COLOR, (LONG)ILLEGAL_COLOR);
+ break;
+ }
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rc;
+
+ BeginPaint(hwnd,&ps);
+
+ COLORREF color = (COLORREF)GetWindowLong(hwnd, GWL_BOXCTL_COLOR);
+
+ if (color != ILLEGAL_COLOR)
+ {
+ HBRUSH BlackBrush = GetStockBrush(BLACK_BRUSH);
+ HBRUSH ColorBrush = CreateSolidBrush(color);
+ GetClientRect(hwnd, &rc);
+ FrameRect(ps.hdc,&rc,BlackBrush);
+ InflateRect(&rc,-1,-1);
+ SetBrushOrgEx(ps.hdc,rc.left,rc.top,NULL);
+ UnrealizeObject(ColorBrush);
+ FillRect(ps.hdc, &rc, ColorBrush);
+ DeleteBrush(ColorBrush);
+ }
+
+ EndPaint(hwnd,&ps);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ // don't need to destroy color in GWL_BOXCTL_COLOR
+
+ break;
+ }
+
+ case BOXCTL_SETCOLOR:
+ {
+ // wParam = COLORREF
+
+ SetWindowLong(hwnd, GWL_BOXCTL_COLOR, (LONG)wParam);
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+ }
+
+ return 1;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UseColorBoxControl
+//
+// Synopsis: Initializes the color box custom control. Registers its
+// window class.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: 0 on success, else Win32 error
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+UseColorBoxControl(
+ IN HINSTANCE hInstance
+ )
+{
+ WNDCLASS wc;
+
+ wc.style = 0;
+ wc.lpfnWndProc = BoxControlWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = COLORBOX_CONTROL_WNDEXTRA;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = COLORBOX_CONTROL_STRING;
+
+ if (0 == RegisterClass(&wc))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseColorBoxControl
+//
+// Synopsis:
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: 0 on success, else Win32 error
+//
+// History: 7-Oct-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+ReleaseColorBoxControl(
+ IN HINSTANCE hInstance
+ )
+{
+ if (!UnregisterClass(COLORBOX_CONTROL_STRING, hInstance))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
diff --git a/private/utils/windisk/controls/boxpriv.hxx b/private/utils/windisk/controls/boxpriv.hxx
new file mode 100644
index 000000000..cd8c0924e
--- /dev/null
+++ b/private/utils/windisk/controls/boxpriv.hxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: box.hxx
+//
+// Contents: Declarations for the color box custom control
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __BOX_HXX__
+#define __BOX_HXX__
+
+DWORD UseColorBoxControl(IN HINSTANCE hInstance);
+DWORD ReleaseColorBoxControl(IN HINSTANCE hInstance);
+
+#endif // __BOX_HXX__
diff --git a/private/utils/windisk/controls/controls.cxx b/private/utils/windisk/controls/controls.cxx
new file mode 100644
index 000000000..60832f5f4
--- /dev/null
+++ b/private/utils/windisk/controls/controls.cxx
@@ -0,0 +1,45 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: controls.cxx
+//
+// Contents:
+//
+// History: 7-Oct-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "bmppriv.hxx"
+#include "boxpriv.hxx"
+#include "linepriv.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+BOOL
+UseWindiskControls(
+ IN HINSTANCE hInstance
+ )
+{
+ return (
+ 0 == UseBitmapControl(hInstance)
+ && 0 == UseColorBoxControl(hInstance)
+ && 0 == UseLineControl(hInstance)
+ );
+}
+
+BOOL
+ReleaseWindiskControls(
+ IN HINSTANCE hInstance
+ )
+{
+ return (
+ 0 == ReleaseBitmapControl(hInstance)
+ && 0 == ReleaseColorBoxControl(hInstance)
+ && 0 == ReleaseLineControl(hInstance)
+ );
+}
diff --git a/private/utils/windisk/controls/controls.hxx b/private/utils/windisk/controls/controls.hxx
new file mode 100644
index 000000000..5f0472016
--- /dev/null
+++ b/private/utils/windisk/controls/controls.hxx
@@ -0,0 +1,79 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: controls.hxx
+//
+// Contents: Public declarations for Disk Administrator custom controls
+//
+// History: 7-Oct-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __CONTROLS_HXX__
+#define __CONTROLS_HXX__
+
+//
+// Initialize all the controls
+//
+
+BOOL
+UseWindiskControls(
+ IN HINSTANCE hInstance
+ );
+
+BOOL
+ReleaseWindiskControls(
+ IN HINSTANCE hInstance
+ );
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap control
+//
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef RC_INVOKED
+
+#define BITMAP_CONTROL_STRING TEXT("WinDiskBitmapControl")
+#define BMPCTL_SETBITMAP WM_USER
+
+#endif // RC_INVOKED
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+// Box control
+//
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef RC_INVOKED
+
+#define COLORBOX_CONTROL_STRING TEXT("WinDiskColorBoxControl")
+#define BOXCTL_SETCOLOR WM_USER
+
+#endif // RC_INVOKED
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+// Line control.
+//
+// This simply draws a line from its left to right side a single pixel high.
+//
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef RC_INVOKED
+
+#define WC_LINECONTROLCLASS TEXT("SmLineControl")
+
+#endif // RC_INVOKED
+
+#endif // __CONTROLS_HXX__
diff --git a/private/utils/windisk/controls/headers.hxx b/private/utils/windisk/controls/headers.hxx
new file mode 100644
index 000000000..2ed466dab
--- /dev/null
+++ b/private/utils/windisk/controls/headers.hxx
@@ -0,0 +1,28 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: headers.hxx
+//
+// Contents:
+//
+// History: 7-Oct-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef UNICODE
+#error Disk Administrator MUST build with UNICODE defined!
+#endif // UNICODE
+
+////////////////////////////////////////////////////////////////////////////
+
+#include <windows.h>
+#include <windowsx.h>
+
+#include <stdlib.h>
+#include <math.h>
+#include <debug.h>
+#include <dacommon.h> // Common header file for Disk Administrator code
+
+#include "controls.hxx"
diff --git a/private/utils/windisk/controls/line.cxx b/private/utils/windisk/controls/line.cxx
new file mode 100644
index 000000000..f48f80599
--- /dev/null
+++ b/private/utils/windisk/controls/line.cxx
@@ -0,0 +1,159 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: line.cxx
+//
+// Contents: Line custom control for use on dialog box.
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "linepriv.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+#define LINE_CONTROL_WNDEXTRA 0
+
+////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK
+LineControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: LineControlWndProc
+//
+// Synopsis: The line custom control window procedure
+//
+// Arguments: standard WndProc
+//
+// Returns: standard WndProc
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+LRESULT CALLBACK
+LineControlWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rc;
+ HBRUSH ColorBrush;
+ HBRUSH BlackBrush;
+
+ BeginPaint(hwnd,&ps);
+
+#if (WINVER >= 0x0400)
+ ColorBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+#else
+ ColorBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+#endif
+ BlackBrush = GetStockBrush(BLACK_BRUSH);
+ GetClientRect(hwnd,&rc);
+ FillRect(ps.hdc, &rc, ColorBrush);
+ rc.bottom = rc.top + 1;
+ FillRect(ps.hdc, &rc, BlackBrush);
+ DeleteBrush(ColorBrush);
+
+ EndPaint(hwnd,&ps);
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+ }
+
+ return 1;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UseLineControl
+//
+// Synopsis: Initializes the line custom control.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: Win32 error, 0 on success
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+UseLineControl(
+ IN HINSTANCE hInstance
+ )
+{
+ WNDCLASS wc;
+
+ wc.style = CS_GLOBALCLASS;
+ wc.lpfnWndProc = LineControlWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = LINE_CONTROL_WNDEXTRA;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = WC_LINECONTROLCLASS;
+
+ if (0 == RegisterClass(&wc))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseLineControl
+//
+// Synopsis: Releases the line custom control.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: Win32 error, 0 on success
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+ReleaseLineControl(
+ IN HINSTANCE hInstance
+ )
+{
+ if (!UnregisterClass(WC_LINECONTROLCLASS, hInstance))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
diff --git a/private/utils/windisk/controls/linepriv.hxx b/private/utils/windisk/controls/linepriv.hxx
new file mode 100644
index 000000000..338b066d4
--- /dev/null
+++ b/private/utils/windisk/controls/linepriv.hxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: linepriv.hxx
+//
+// Contents: Line control private header file.
+//
+// History: 21-Jul-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __LINEPRIV_HXX__
+#define __LINEPRIV_HXX__
+
+DWORD UseLineControl(IN HINSTANCE hInstance);
+DWORD ReleaseLineControl(IN HINSTANCE hInstance);
+
+#endif // __LINEPRIV_HXX__
diff --git a/private/utils/windisk/controls/makefile b/private/utils/windisk/controls/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/controls/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/controls/sources b/private/utils/windisk/controls/sources
new file mode 100644
index 000000000..eade903ae
--- /dev/null
+++ b/private/utils/windisk/controls/sources
@@ -0,0 +1,22 @@
+!include ..\windisk.mk
+
+MINORCOMP= controls
+
+TARGETNAME= controls
+TARGETPATH= obj
+TARGETTYPE= LIBRARY
+
+UMTYPE= windows
+
+INCLUDES=\
+ ..\inc; \
+ $(INCLUDES)
+
+SOURCES=\
+ controls.cxx \
+ bmp.cxx \
+ box.cxx \
+ line.cxx
+
+PRECOMPILED_INCLUDE=headers.hxx
+PRECOMPILED_CXX=1
diff --git a/private/utils/windisk/debug/assert.cxx b/private/utils/windisk/debug/assert.cxx
new file mode 100644
index 000000000..9ab24ed36
--- /dev/null
+++ b/private/utils/windisk/debug/assert.cxx
@@ -0,0 +1,340 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991-1994, Microsoft Corporation.
+//
+// File: assert.cxx
+//
+// Contents: Debugging output routines
+//
+// History: 23-Jul-91 KyleP Created.
+// 09-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich moved debug print routines out
+// 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
+// 30-Sep-93 KyleP DEVL obsolete
+// 7-Oct-94 BruceFo Ripped out all kernel, non-FLAT,
+// DLL-specific, non-Win32 functionality.
+// Now it's basically "print to the
+// debugger" code.
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "debug.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+unsigned long Win4InfoLevel = DEF_INFOLEVEL;
+unsigned long Win4InfoMask = 0xffffffff;
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
+
+//////////////////////////////////////////////////////////////////////////////
+
+static int _cdecl w4dprintf(const char *format, ...);
+static int _cdecl w4vdprintf(const char *format, va_list arglist);
+
+//////////////////////////////////////////////////////////////////////////////
+
+static CRITICAL_SECTION s_csMessageBuf;
+static char g_szMessageBuf[500]; // this is the message buffer
+
+static int _cdecl w4dprintf(const char *format, ...)
+{
+ int ret;
+
+ va_list va;
+ va_start(va, format);
+ ret = w4vdprintf(format, va);
+ va_end(va);
+
+ return ret;
+}
+
+
+static int _cdecl w4vdprintf(const char *format, va_list arglist)
+{
+ int ret;
+
+ EnterCriticalSection(&s_csMessageBuf);
+ ret = vsprintf(g_szMessageBuf, format, arglist);
+ OutputDebugStringA(g_szMessageBuf);
+ LeaveCriticalSection(&s_csMessageBuf);
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: _asdprintf
+//
+// Synopsis: Calls vdprintf to output a formatted message.
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+inline void _CRTAPI1
+_asdprintf(
+ char const *pszfmt, ...)
+{
+ va_list va;
+ va_start(va, pszfmt);
+
+ vdprintf(DEB_FORCE, "Assert", pszfmt, va);
+
+ va_end(va);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Win4AssertEx, private
+//
+// Synopsis: Display assertion information
+//
+// Effects: Called when an assertion is hit.
+//
+//----------------------------------------------------------------------------
+
+EXPORTIMP void APINOT
+Win4AssertEx(
+ char const * szFile,
+ int iLine,
+ char const * szMessage)
+{
+ if (Win4AssertLevel & ASSRT_MESSAGE)
+ {
+ DWORD tid = GetCurrentThreadId();
+
+ _asdprintf("%s File: %s Line: %u, thread id %d\n",
+ szMessage, szFile, iLine, tid);
+ }
+
+ if (Win4AssertLevel & ASSRT_POPUP)
+ {
+ int id = PopUpError(szMessage,iLine,szFile);
+
+ if (id == IDCANCEL)
+ {
+ DebugBreak();
+ }
+ }
+ else if (Win4AssertLevel & ASSRT_BREAK)
+ {
+ DebugBreak();
+ }
+}
+
+
+//+------------------------------------------------------------
+// Function: SetWin4InfoLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global info level for debugging output
+// Returns: Old info level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4InfoLevel;
+ Win4InfoLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: SetWin4InfoMask(unsigned long ulNewMask)
+//
+// Synopsis: Sets the global info mask for debugging output
+// Returns: Old info mask
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoMask(
+ unsigned long ulNewMask)
+{
+ unsigned long ul;
+
+ ul = Win4InfoMask;
+ Win4InfoMask = ulNewMask;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: SetWin4AssertLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global assert level for debugging output
+// Returns: Old assert level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4AssertLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4AssertLevel;
+ Win4AssertLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: PopUpError
+//
+// Synopsis: Displays a dialog box using provided text,
+// and presents the user with the option to
+// continue or cancel.
+//
+// Arguments:
+// szMsg -- The string to display in main body of dialog
+// iLine -- Line number of file in error
+// szFile -- Filename of file in error
+//
+// Returns:
+// IDCANCEL -- User selected the CANCEL button
+// IDOK -- User selected the OK button
+//-------------------------------------------------------------
+
+EXPORTIMP int APINOT
+PopUpError(
+ char const *szMsg,
+ int iLine,
+ char const *szFile)
+{
+ int id;
+ static char szAssertCaption[128];
+ static char szModuleName[128];
+
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ char * pszModuleName;
+
+ if (GetModuleFileNameA(NULL, szModuleName, 128))
+ {
+ pszModuleName = strrchr(szModuleName, '\\');
+ if (!pszModuleName)
+ {
+ pszModuleName = szModuleName;
+ }
+ else
+ {
+ pszModuleName++;
+ }
+ }
+ else
+ {
+ pszModuleName = "Unknown";
+ }
+
+ sprintf(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
+ pszModuleName, szFile, iLine, pid, tid);
+
+ id = MessageBoxA(NULL,
+ szMsg,
+ szAssertCaption,
+ MB_SETFOREGROUND
+ | MB_DEFAULT_DESKTOP_ONLY
+ | MB_TASKMODAL
+ | MB_ICONEXCLAMATION
+ | MB_OKCANCEL);
+
+ //
+ // If id == 0, then an error occurred. There are two possibilities
+ // that can cause the error: Access Denied, which means that this
+ // process does not have access to the default desktop, and everything
+ // else (usually out of memory).
+ //
+
+ if (0 == id)
+ {
+ if (GetLastError() == ERROR_ACCESS_DENIED)
+ {
+ //
+ // Retry this one with the SERVICE_NOTIFICATION flag on. That
+ // should get us to the right desktop.
+ //
+ id = MessageBoxA(NULL,
+ szMsg,
+ szAssertCaption,
+ MB_SETFOREGROUND
+ | MB_SERVICE_NOTIFICATION
+ | MB_TASKMODAL
+ | MB_ICONEXCLAMATION
+ | MB_OKCANCEL);
+ }
+ }
+
+ return id;
+}
+
+
+//+------------------------------------------------------------
+// Function: vdprintf
+//
+// Synopsis: Prints debug output using a pointer to the
+// variable information. Used primarily by the
+// xxDebugOut macros
+//
+// Arguements:
+// ulCompMask -- Component level mask used to determine
+// output ability
+// pszComp -- String const of component prefix.
+// ppszfmt -- Pointer to output format and data
+//
+//-------------------------------------------------------------
+
+static CRITICAL_SECTION s_csDebugPrint;
+
+EXPORTIMP void APINOT
+vdprintf(
+ unsigned long ulCompMask,
+ char const *pszComp,
+ char const *ppszfmt,
+ va_list pargs)
+{
+ if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
+ ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
+ {
+ EnterCriticalSection(&s_csDebugPrint);
+
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+ w4dprintf("%d.%03d> %s: ", pid, tid, pszComp);
+ }
+ w4vdprintf(ppszfmt, pargs);
+ }
+
+ if (Win4InfoLevel & DEB_STDOUT)
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+ printf("%d.%03d> %s: ", pid, tid, pszComp);
+ }
+ vprintf(ppszfmt, pargs);
+ }
+
+ LeaveCriticalSection(&s_csDebugPrint);
+ }
+}
+
+void InitializeDebugging(void)
+{
+ InitializeCriticalSection(&s_csMessageBuf);
+ InitializeCriticalSection(&s_csDebugPrint);
+}
+
+#endif // DBG == 1
diff --git a/private/utils/windisk/debug/debug.h b/private/utils/windisk/debug/debug.h
new file mode 100644
index 000000000..66e823a03
--- /dev/null
+++ b/private/utils/windisk/debug/debug.h
@@ -0,0 +1,284 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: debug.h
+//
+// Contents: Debugging macros. Stolen from old Cairo debnot.h with the
+// following history...
+//
+// History: 23-Jul-91 KyleP Created.
+// 15-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich Consolidated win4p.hxx
+// 22-Oct-91 SatoNa Added SHLSTRICT
+// 29-Apr-92 BartoszM Moved from win4p.h
+// 3-Jun-92 BruceFo Added SMUISTRICT
+// 17-Dec-92 AlexT Moved UN..._PARM out of DEVL==1
+// 30-Sep-93 KyleP DEVL obsolete
+// 18-Jun-94 AlexT Make Assert a better statement
+// 7-Oct-94 BruceFo Stole and ripped out everything except
+// debug prints and asserts.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DEBUG_H__
+#define __DEBUG_H__
+
+#include <stdarg.h>
+
+//----------------------------------------------------------------------------
+// Parameter Macros
+//
+// To avoid compiler warnings for unimplemented functions, use
+// UNIMPLEMENTED_PARM(x) for each unreferenced parameter. This will
+// later be defined to nul to reveal functions that we forgot to implement.
+//
+// For functions which will never use a parameter, use
+// UNREFERENCED_PARM(x).
+//
+
+#define UNIMPLEMENTED_PARM(x) (x)
+
+#define UNREFERENCED_PARM(x) (x)
+
+
+#if DBG == 1
+
+//
+// DEBUG -- DEBUG -- DEBUG -- DEBUG -- DEBUG
+//
+
+//
+// Debug print functions.
+//
+
+#ifdef __cplusplus
+extern "C" {
+# define EXTRNC "C"
+#else
+# define EXTRNC
+#endif
+
+#ifndef EXPORTDEF
+ #define EXPORTDEF
+#endif
+#ifndef EXPORTIMP
+ #define EXPORTIMP
+#endif
+#ifndef EXPORTED
+ #define EXPORTED _cdecl
+#endif
+#ifndef APINOT
+#ifdef _X86_
+ #define APINOT _stdcall
+#else
+ #define APINOT _cdecl
+#endif
+#endif
+
+
+// vdprintf should only be called from xxDebugOut()
+
+ EXPORTDEF void APINOT
+ vdprintf(
+ unsigned long ulCompMask,
+ char const *pszComp,
+ char const *ppszfmt,
+ va_list ArgList);
+
+ EXPORTDEF void APINOT
+ Win4AssertEx(
+ char const *pszFile,
+ int iLine,
+ char const *pszMsg);
+
+ EXPORTDEF int APINOT
+ PopUpError(
+ char const *pszMsg,
+ int iLine,
+ char const *pszFile);
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4InfoLevel(
+ unsigned long ulNewLevel);
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4InfoMask(
+ unsigned long ulNewMask);
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4AssertLevel(
+ unsigned long ulNewLevel);
+
+ EXPORTDEF void APINOT
+ InitializeDebugging(
+ void);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+# define Win4Assert(x) \
+ (void)((x) || (Win4AssertEx(__FILE__, __LINE__, #x),0))
+
+# define Win4Verify(x) Win4Assert(x)
+
+
+//
+// Debug print macros
+//
+
+# define DEB_ERROR 0x00000001 // exported error paths
+# define DEB_WARN 0x00000002 // exported warnings
+# define DEB_TRACE 0x00000004 // exported trace messages
+
+# define DEB_DBGOUT 0x00000010 // Output to debugger
+# define DEB_STDOUT 0x00000020 // Output to stdout
+
+# define DEB_IERROR 0x00000100 // internal error paths
+# define DEB_IWARN 0x00000200 // internal warnings
+# define DEB_ITRACE 0x00000400 // internal trace messages
+
+# define DEB_USER1 0x00010000 // User defined
+# define DEB_USER2 0x00020000 // User defined
+# define DEB_USER3 0x00040000 // User defined
+# define DEB_USER4 0x00080000 // User defined
+# define DEB_USER5 0x00100000 // User defined
+# define DEB_USER6 0x00200000 // User defined
+# define DEB_USER7 0x00400000 // User defined
+# define DEB_USER8 0x00800000 // User defined
+# define DEB_USER9 0x01000000 // User defined
+# define DEB_USER10 0x02000000 // User defined
+# define DEB_USER11 0x04000000 // User defined
+# define DEB_USER12 0x08000000 // User defined
+# define DEB_USER13 0x10000000 // User defined
+# define DEB_USER14 0x20000000 // User defined
+# define DEB_USER15 0x40000000 // User defined
+
+# define DEB_NOCOMPNAME 0x80000000 // suppress component name
+
+# define DEB_FORCE 0x7fffffff // force message
+
+# define ASSRT_MESSAGE 0x00000001 // Output a message
+# define ASSRT_BREAK 0x00000002 // Int 3 on assertion
+# define ASSRT_POPUP 0x00000004 // And popup message
+
+
+//+----------------------------------------------------------------------
+//
+// DECLARE_DEBUG(comp)
+// DECLARE_INFOLEVEL(comp)
+//
+// This macro defines xxDebugOut where xx is the component prefix
+// to be defined. This declares a static variable 'xxInfoLevel', which
+// can be used to control the type of xxDebugOut messages printed to
+// the terminal. For example, xxInfoLevel may be set at the debug terminal.
+// This will enable the user to turn debugging messages on or off, based
+// on the type desired. The predefined types are defined below. Component
+// specific values should use the upper 24 bits
+//
+// To Use:
+//
+// 1) In your components main include file, include the line
+// DECLARE_DEBUG(comp)
+// where comp is your component prefix
+//
+// 2) In one of your components source files, include the line
+// DECLARE_INFOLEVEL(comp)
+// where comp is your component prefix. This will define the
+// global variable that will control output.
+//
+// It is suggested that any component define bits be combined with
+// existing bits. For example, if you had a specific error path that you
+// wanted, you might define DEB_<comp>_ERRORxxx as being
+//
+// (0x100 | DEB_ERROR)
+//
+// This way, we can turn on DEB_ERROR and get the error, or just 0x100
+// and get only your error.
+//
+//-----------------------------------------------------------------------
+
+# ifndef DEF_INFOLEVEL
+# define DEF_INFOLEVEL (DEB_ERROR | DEB_WARN)
+# endif
+
+
+# define DECLARE_INFOLEVEL(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel = DEF_INFOLEVEL;\
+ extern EXTRNC char* comp##InfoLevelString = #comp;
+
+
+# ifdef __cplusplus
+
+# define DECLARE_DEBUG(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel; \
+ extern EXTRNC char *comp##InfoLevelString; \
+ _inline void \
+ comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \
+ { \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ va_list va; \
+ va_start (va, pszfmt); \
+ vdprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\
+ va_end(va); \
+ } \
+ } \
+ \
+ class comp##CDbgTrace\
+ {\
+ private:\
+ unsigned long _ulFlags;\
+ char const * const _pszName;\
+ public:\
+ comp##CDbgTrace(unsigned long ulFlags, char const * const pszName);\
+ ~comp##CDbgTrace();\
+ };\
+ \
+ inline comp##CDbgTrace::comp##CDbgTrace(\
+ unsigned long ulFlags,\
+ char const * const pszName)\
+ : _ulFlags(ulFlags), _pszName(pszName)\
+ {\
+ comp##InlineDebugOut(_ulFlags, "Entering %s\n", _pszName);\
+ }\
+ \
+ inline comp##CDbgTrace::~comp##CDbgTrace()\
+ {\
+ comp##InlineDebugOut(_ulFlags, "Exiting %s\n", _pszName);\
+ }
+
+# else // ! __cplusplus
+
+# define DECLARE_DEBUG(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel; \
+ extern EXTRNC char *comp##InfoLevelString; \
+ _inline void \
+ comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \
+ { \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ va_list va; \
+ va_start (va, pszfmt); \
+ vdprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\
+ va_end(va); \
+ } \
+ }
+
+# endif // ! __cplusplus
+
+#else // DBG == 0
+
+//
+// NO DEBUG -- NO DEBUG -- NO DEBUG -- NO DEBUG -- NO DEBUG
+//
+
+# define Win4Assert(x) NULL
+# define Win4Verify(x) (x)
+
+# define DECLARE_DEBUG(comp)
+# define DECLARE_INFOLEVEL(comp)
+
+#endif // DBG == 0
+
+#endif // __DEBUG_H__
diff --git a/private/utils/windisk/debug/makefile b/private/utils/windisk/debug/makefile
new file mode 100644
index 000000000..60482ff11
--- /dev/null
+++ b/private/utils/windisk/debug/makefile
@@ -0,0 +1,9 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/debug/sources b/private/utils/windisk/debug/sources
new file mode 100644
index 000000000..030cf571c
--- /dev/null
+++ b/private/utils/windisk/debug/sources
@@ -0,0 +1,12 @@
+MAJORCOMP= cmn
+MINORCOMP= misc
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+UMTYPE= windows
+
+TARGETNAME= debug
+TARGETPATH= obj
+TARGETTYPE= LIBRARY
+
+SOURCES= assert.cxx
diff --git a/private/utils/windisk/dirs b/private/utils/windisk/dirs
new file mode 100644
index 000000000..b262a2701
--- /dev/null
+++ b/private/utils/windisk/dirs
@@ -0,0 +1,33 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Isaac Heizer (IsaacHe) 28-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# The build follows the order in which the subdirectories are specified.
+#
+
+DIRS= debug util controls src
+
+#
+# This is a list of all subdirectories that build optional components.
+# The build follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= hard clear diskinfo
diff --git a/private/utils/windisk/diskinfo/diskinfo.cxx b/private/utils/windisk/diskinfo/diskinfo.cxx
new file mode 100644
index 000000000..236f77389
--- /dev/null
+++ b/private/utils/windisk/diskinfo/diskinfo.cxx
@@ -0,0 +1,273 @@
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntddnfs.h>
+}
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ntdddfs.h>
+
+#define MAXBUF 200
+
+#define wstrEqual(a,b) (0 == wcscmp((a),(b)))
+
+char* program;
+
+void
+fatal(char* pszMsg)
+{
+ fprintf(stderr,"Fatal error: %s\n",pszMsg);
+ exit(1);
+}
+
+void
+usage()
+{
+ fprintf(stderr,"Usage: %s\n",program);
+ exit(1);
+}
+
+BOOL GetDeviceObject(
+ WCHAR wcDrive, // drive letter to get info about
+ LPWSTR lpTargetBuffer, // where to put the NT device path
+ DWORD nTargetBuffer) // length of device path buffer in characters
+{
+ NTSTATUS Status;
+
+ HANDLE hSymbolicLink;
+ WCHAR wszLinkName[_MAX_DRIVE+1]; // the +1 is for a backslash
+ UNICODE_STRING ustrLinkName;
+ UNICODE_STRING ustrLinkTarget;
+ OBJECT_ATTRIBUTES LinkAttributes;
+
+ wszLinkName[0] = wcDrive;
+ wszLinkName[1] = L':';
+ wszLinkName[2] = L'\\';
+ wszLinkName[3] = L'\0'; // wszLinkName = L"X:\"
+ _wcsupr(wszLinkName);
+
+ //
+ // Construct the link name by calling RtlDosPathNameToNtPathName, and
+ // strip of the trailing backslash. At the end of this, ustrLinkName
+ // should be of the form \DosDevices\X:
+ //
+
+ RtlDosPathNameToNtPathName_U(wszLinkName, &ustrLinkName, NULL, NULL);
+ ustrLinkName.Length -= sizeof(WCHAR);
+
+ InitializeObjectAttributes(
+ &LinkAttributes,
+ &ustrLinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+ NULL,
+ NULL);
+
+ Status = NtOpenSymbolicLinkObject(
+ &hSymbolicLink,
+ GENERIC_READ,
+ &LinkAttributes
+ );
+ if (!NT_SUCCESS(Status))
+ {
+ // No Link
+ return(FALSE);
+ }
+
+
+ //
+ // Find out if the device specified is DFS DeviceObject
+ //
+
+ ustrLinkTarget.Length = 0;
+ ustrLinkTarget.MaximumLength = (USHORT)nTargetBuffer * sizeof(WCHAR);
+ ustrLinkTarget.Buffer = lpTargetBuffer;
+
+ Status = NtQuerySymbolicLinkObject(
+ hSymbolicLink,
+ &ustrLinkTarget, // Name of Link's Target obj.
+ NULL
+ );
+ NtClose(hSymbolicLink);
+
+ if (NT_SUCCESS(Status))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void _cdecl
+main(int argc, char* argv[])
+{
+ program = argv[0];
+
+ printf("Disk information:\n");
+
+ WCHAR wszBuf[MAXBUF];
+ DWORD cchBuf = MAXBUF;
+ DWORD r;
+ WCHAR* p;
+ UINT dt;
+
+ BOOL f;
+ DWORD SectorsPerCluster;
+ DWORD BytesPerSector;
+ DWORD FreeClusters;
+ DWORD Clusters;
+
+ WCHAR wszPath[MAXBUF];
+
+ r = GetLogicalDriveStrings(cchBuf, wszBuf);
+ if (0 == r || r > cchBuf)
+ {
+ fatal("GetLogicalDriveStrings() failed.");
+ }
+
+ p = wszBuf;
+ while (*p)
+ {
+ printf("%ws: ",p);
+
+ dt = GetDriveType(p);
+ switch (dt)
+ {
+ case 0:
+ printf("undetermined type");
+ break;
+ case 1:
+ printf("no root directory!");
+ break;
+ case DRIVE_REMOVABLE:
+ printf("removable");
+ break;
+ case DRIVE_FIXED:
+ printf("fixed");
+ break;
+ case DRIVE_REMOTE:
+ printf("remote");
+ break;
+ case DRIVE_CDROM:
+ printf("cd-rom");
+ break;
+ case DRIVE_RAMDISK:
+ printf("RAM disk");
+ break;
+ default:
+ printf("HUH?");
+ break;
+ }
+ printf(", ");
+
+ if (dt == DRIVE_REMOVABLE)
+ {
+ f = FALSE;
+ }
+ else
+ {
+ f = GetDiskFreeSpace(
+ p,
+ &SectorsPerCluster,
+ &BytesPerSector,
+ &FreeClusters,
+ &Clusters);
+ }
+
+ if (f)
+ {
+ DWORD BytesPerCluster = SectorsPerCluster * BytesPerSector;
+ DWORD OneMB = 1024*1024;
+
+ printf("s/c=%d, b/s=%d, free=%d(%d MB), total=%d(%d MB)",
+ SectorsPerCluster,
+ BytesPerSector,
+ FreeClusters,
+ (FreeClusters * BytesPerCluster) / OneMB,
+ Clusters,
+ (Clusters * BytesPerCluster)/OneMB);
+ }
+
+ printf("\n");
+ p = p + wcslen(p) + 1;
+ }
+
+ printf("\n");
+
+ WCHAR wszVolName[MAXBUF];
+ DWORD volSerialNumber;
+ DWORD volMaxCompLen;
+ DWORD volFlags;
+ WCHAR wszVolFSName[MAXBUF];
+
+ p = wszBuf;
+ while (*p)
+ {
+ printf("%ws, ",p);
+
+ if (wstrEqual(p,L"A:\\") ||
+ wstrEqual(p,L"B:\\"))
+ {
+ f = FALSE;
+ }
+ else
+ {
+ f = GetVolumeInformation(
+ p,
+ wszVolName,
+ MAXBUF,
+ &volSerialNumber,
+ &volMaxCompLen,
+ &volFlags,
+ wszVolFSName,
+ MAXBUF);
+ }
+
+ if (f)
+ {
+ printf("%ws, serial # 0x%x, max comp len %d, ",
+ wszVolName,
+ volSerialNumber,
+ volMaxCompLen);
+
+ if (volFlags & FS_CASE_IS_PRESERVED)
+ {
+ printf("case preserved, ");
+ }
+
+ if (volFlags & FS_CASE_SENSITIVE)
+ {
+ printf("case sensitive, ");
+ }
+
+ if (volFlags & FS_UNICODE_STORED_ON_DISK)
+ {
+ printf("UNICODE, ");
+ }
+
+ printf("%ws, ", wszVolFSName);
+ }
+
+ f = GetDeviceObject(*p, wszPath, sizeof(wszPath)/sizeof(WCHAR));
+ if (f)
+ {
+ printf("%ws",wszPath);
+ }
+ else
+ {
+ printf("Error getting NT path");
+ }
+
+ printf("\n");
+
+ p = p + wcslen(p) + 1;
+ }
+
+ printf("\n");
+}
diff --git a/private/utils/windisk/diskinfo/makefile b/private/utils/windisk/diskinfo/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/diskinfo/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/diskinfo/sources b/private/utils/windisk/diskinfo/sources
new file mode 100644
index 000000000..e1de308ce
--- /dev/null
+++ b/private/utils/windisk/diskinfo/sources
@@ -0,0 +1,14 @@
+!include ..\windisk.mk
+
+MINORCOMP= diskinfo
+
+TARGETNAME= diskinfo
+TARGETTYPE= PROGRAM
+TARGETPATH= obj
+
+UMTYPE= console
+
+SOURCES= diskinfo.cxx
+
+TARGETLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
diff --git a/private/utils/windisk/doc/adskman.doc b/private/utils/windisk/doc/adskman.doc
new file mode 100644
index 000000000..acd6397bf
--- /dev/null
+++ b/private/utils/windisk/doc/adskman.doc
Binary files differ
diff --git a/private/utils/windisk/doc/adskman2.doc b/private/utils/windisk/doc/adskman2.doc
new file mode 100644
index 000000000..3a6e1a44d
--- /dev/null
+++ b/private/utils/windisk/doc/adskman2.doc
Binary files differ
diff --git a/private/utils/windisk/doc/demo.txt b/private/utils/windisk/doc/demo.txt
new file mode 100644
index 000000000..d3aed16e8
--- /dev/null
+++ b/private/utils/windisk/doc/demo.txt
@@ -0,0 +1,112 @@
+This note describes the functionality of format and chkdsk in the
+Disk Administrator.
+=================================================================
+
+
+
+Format
+------
+
+Select a volume and choose "Change Format" from the context menu. You
+can specify the new format as any of FAT, HPFS, NTFS, or OFS, and choose
+a label. You can specify whether or not to "quick format" the volume.
+
+If you've selected a fault-tolerant volume (stripe with parity or
+mirror), then "quick format" is disabled.
+
+When formatting, a "thermometer" displays the percentage of formatting
+completed. A "Stop" button allows you to cancel the formatting.
+
+If "Stop" is chosen, a confirmation dialog appears. A message informs
+the user that stopping formatting early is inadvisable. The user can
+choose "Stop" to confirm the original "stop" desire, "continue"
+(the default) to continue formatting where formatting left off, or
+help.
+
+Cancelling format is disabled when quick formatting.
+
+After formatting completes, a summary is printed detailing the amount of
+disk space is on the volume, and the available disk space (with
+thousands separators!).
+
+
+
+Chkdsk
+------
+
+Select a volume and choose "Check for Errors..." from the context menu. You
+can choose one of three levels of operation: (1) read-only, or don't
+fix; (2) fix (i.e., chkdsk /F); or (3) scan for bad sectors (i.e.,
+chkdsk /R).
+
+If the user hits "OK" and the current level of operation choice is
+"don't fix", then a confirmation dialog is displayed, warning the user
+that no error repair actions will be taken, and the reported actions describe
+what would be done in a "fix" case.
+
+When checking a volume, a "thermometer" displays the percentage of checking
+that has been completed in a particular phase. Note that this percentage
+is not the percentage of all checking completed, which is usually
+difficult or impossible information to determine before checking
+begins. Above the thermometer appears a title stating what is currently
+being checked. The thermometer is implemented to not update more than
+10 times a second (unless the value is 0% or 100%). This is done to avoid
+having the UI thread fall very far behind the worker thread which may
+generate many more messages than that.
+
+Note that % done information is currently only implemented for NTFS and
+FAT, not for OFS. (Implementation note: Bob Duke, who originally wrote
+chkdsk for OFS, strongly resisted adding % done information due to the
+incredible complexity of OFS and the lack of an easy means to predetermine
+the total amount of work.)
+
+For the "Do not fix errors" case, a "Stop" button allows you to cancel
+the formatting. If "Stop" is chosen, a confirmation dialog appears. A
+message informs the user that stopping checking early is inadvisable. The
+user can choose "Stop" to confirm the original "stop" desire, "continue"
+(the default) to continue checking where checking left off, or help.
+
+For the other cases, there is no "stop" button; the volume check engines
+don't support stopping in the "fix" cases. (Note that for chkdsk.exe,
+Ctrl-C --- the "stop" mechanism for the command line --- is disabled in
+the fix cases.)
+
+After a successful, complete volume check, a "results" dialog appears.
+Within this dialog is an edit control with any interesting information
+generated by the volume check. For successful checks, this is simply a
+summary of total disk space, the space in user files, the space used by
+the system, etc. Buttons exist to allow this information to be printed
+or logged to a file. The title to this dialog is different in the "don't
+fix" and "fix" cases. In particular, in the "don't fix" case the message
+makes clear that any error repair actions only describe what *would be*
+done, not what *was* done.
+
+This dialog is resizable, to allow the user to easily use more screen
+space where necessary to view the results data, instead of forcing the
+user to use scrollbars (which also are available).
+
+Any number of copies---collated or not---can be printed to the default
+printer. The common Print dialog is used, so the printer can be set up
+before printing, if necessary. Printing can be cancelled, as well.
+
+The results of the check can also be saved to a file by choosing the
+"Log..." button. The common "Save As" dialog is used. The suggested file
+name is "check-X.log" where "X:" is the volume that was checked, and the
+directory that is suggested is the system directory, e.g. "c:\winnt". As
+this is a common dialog, the user can choose a network drive (and even
+connect to one).
+
+Since a standard edit control is used to display the results information,
+the user can select text there via either the keyboard or a mouse, and
+copy it to the clipboard. It can then be pasted in an application like
+notepad when writing a report, for example.
+
+If a volume is to be checked in a "fix" mode, then the volume must be
+opened for exclusive access. If this cannot occur due to the volume
+being in use, then a message appears asking whether the user would like
+to schedule the check for the next system reboot. (For instance, a
+volume can be locked by simply opening a command window and setting the
+current drive to it). The user can choose either yes or no. If the user
+chooses "no", then the check simply ends without performing any work. If
+the user chooses "yes", then a confirmation message box appears stating
+that the check has been scheduled (or could not be scheduled).
diff --git a/private/utils/windisk/doc/dlls.txt b/private/utils/windisk/doc/dlls.txt
new file mode 100644
index 000000000..d78909c8e
--- /dev/null
+++ b/private/utils/windisk/doc/dlls.txt
@@ -0,0 +1,81 @@
+A description of the DLLs used in the Cairo Disk Administrator
+==============================================================
+
+There are several EXEs and DLLs integral to the operation of
+the Disk Administrator. This note discusses those executables,
+their interrelationship, why they are necessary, and why the
+functionality is broken up so.
+
+windisk.exe -- the guts, including partitioning, fault tolerance configuration,
+and file system operations (format, chkdsk, label).
+
+A note on the NT file and disk utilities: All the NT file and disk
+utilities---chkdsk, format, comp, attrib, etc---heavily utilize C++:
+most everything of interest is a class---command-line arguments,
+buffers, strings, stacks, disk drives, HPFS & FAT file system information,
+etc. Much common code, including classes for the examples just
+given, reside in ulib.dll.
+
+fmifs.dll -- a small utitilty converting between NT utility DLL APIs
+and callback functions. This DLL was originally written for use by File
+Manager, for floppy disk formatting and volume label changing. It
+isolates its clients from the vagaries of the utilities library classes,
+namely the message feedback class. All feedback from chkdsk, format, etc,
+is normally reported by a Display() method being called on a MESSAGE
+class, a pointer to which is passed to the file system Format(),
+Chkdsk(), etc. API. The fmifs.dll code converts this message into a
+function callback, passing along any relevant information. To use the
+file system utility APIs directly would force clients to compile in the
+utilities environment, incorporating lots of undesirable C++ stuff.
+
+ifsutil.dll -- installable file system utilities. C++ classes
+providing low-level file system and disk abstractions for the
+NT installable file system interface.
+
+uofs.dll, untfs.dll, uhpfs.dll, ufat.dll -- the file system
+utilities (chkdsk, format, label, etc) for each file system. Note that
+the code incorporated into these DLLs is used in several distinct and
+diverse environments. These are the setup environment, as autochk in
+the boot environment, and from the chkdsk, format, label, etc., front
+ends. And now, from Disk Administrator. Note that these are amazingly
+different. For example, in the boot environment there is no virtual
+memory! Message feedback requirements are obviously different in the
+character-based and GUI environments.
+
+ulib.dll -- a library for the utilities. Includes various common-code
+helper classes, as described above.
+
+
+
+Here are the dependencies (ignoring ntdll.dll, kernel32.dll, etc):
+
+windisk.exe depends on fmifs.dll
+
+fmifs.dll: depends on ulib.dll, ifsutil.dll
+
+ifsutil.dll: depends on ulib.dll
+
+uofs.dll ufat.dll, untfs.dll, uhpfs.dll: depend on ulib.dll, ifsutil.dll
+
+ulib.dll: no dependencies of note
+
+
+
+Here's the *approximate* tree (DAG, actually): things above depend on
+things below. Same level means no dependencies.
+
+
+ windisk.exe
+
+ fmifs.dll
+
+ ufat.dll uhpfs.dll untfs.dll uofs.dll
+
+ ifsutil.dll
+
+ ulib.dll
+
+
+
+Note that windisk lazy-loads fmifs.dll: only when an operation requiring
+file system operations is to be performed does windisk load this dll.
diff --git a/private/utils/windisk/doc/extend.txt b/private/utils/windisk/doc/extend.txt
new file mode 100644
index 000000000..1bb7dcf2c
--- /dev/null
+++ b/private/utils/windisk/doc/extend.txt
@@ -0,0 +1,24 @@
+Disk Administrator Extension Interfaces
+=======================================
+
+The extension interfaces have been commented (#ifdef'ed) out. The interfaces
+are defined in the "types" subdirectory.
+
+This file contains some information on their design and implementation.
+
+-----------------------------Volume Claiming
+
+During initialization, all the extension classes are enumerated. Then,
+the following happens:
+
+1. for each pre-existing volume, determine all the volume extension
+classes that claim it.
+
+2. for each pre-existing formatted volume, determine all the file system
+extension classes that claim it.
+
+3. for each hard drive, determine all the hard disk extension classes
+that claim it.
+
+For now, this will all be done at start-up time, and not dynamically as
+we need it.
diff --git a/private/utils/windisk/doc/misc.txt b/private/utils/windisk/doc/misc.txt
new file mode 100644
index 000000000..b4de21141
--- /dev/null
+++ b/private/utils/windisk/doc/misc.txt
@@ -0,0 +1,51 @@
+Documents
+=========
+
+In \\worf\src\src\cairodwb\sysman\old:
+
+ wddev.doc -- "Cairo Disk Administrator Development Plan". A reasonably
+ up-to-date description of what work items we had in mind to complete
+ windisk. This document is also checked in locally, just in case.
+
+In \\kayak\design\docs:
+
+ windisk.doc -- KevinSch UI design document
+
+Right here (of marginal interest):
+
+ adskman2.doc -- "Architecture of the Cairo Disk Administrator". old. Mainly
+ discusses the extension architecture.
+
+ adskman.doc -- "Cairo Disk Administration". ancient. Purely historical
+ interest.
+
+
+Prototype
+=========
+
+The prototype (originally written by KevinP, munged by BruceFo) is under
+\\kayak\design. I don't know which one is up-to-date, but probably either
+proto\dskman.exe or protos\diskman\dskman.exe.
+
+
+
+Random notes:
+=============
+
+People who have worked on windisk:
+
+ Development
+ TedM -- original writer ?
+ BillMc -- ?
+ BobRi -- NT 3.5, NT 3.51
+ BruceFo -- Cairo version, concurrent with NT 3.5, 3.51
+
+ User Ed:
+ Peget -- UserEd for Daytona windisk
+
+ Program Management
+ KevinP -- original
+ DanPl -- ?
+ KevinSch
+
+Windows 95 "Disks" tool (Windisk): \\tal\msdos\src\win\core\shell\cpls\windisk
diff --git a/private/utils/windisk/doc/progmgmt.bmp b/private/utils/windisk/doc/progmgmt.bmp
new file mode 100644
index 000000000..153f4affa
--- /dev/null
+++ b/private/utils/windisk/doc/progmgmt.bmp
Binary files differ
diff --git a/private/utils/windisk/doc/select.txt b/private/utils/windisk/doc/select.txt
new file mode 100644
index 000000000..c70b77819
--- /dev/null
+++ b/private/utils/windisk/doc/select.txt
@@ -0,0 +1,75 @@
+Selection & Focus
+=================
+
+This section describes the design for selection and focus in the Disk
+Administrator.
+
+The two DA views have different selection and focus characteristics.
+The disks view displays a superset of the information provided in the
+volumes view, by showing free space and the actual breakdown of
+partitions in a volume.
+
+The focus is a pure UI concept that doesn't affect the selection. Thus,
+we don't maintain the focus. We determine a reasonable focus for the
+new view when a view change occurs.
+
+The selection, however, must be maintained. The UI selection is reflected
+in the internal data structures and is what commands operate on. We also
+maintain the visual selection in both views.
+
+The selection in the disks view consists of a set of volumes and a set
+of free spaces. It is impossible to select only one partition of a
+multi-paritition (FT) volume; the entire volume is selected. In the volumes
+view, we only allow a single item to be selected, as we don't support any
+operations on multiple volume selections. In addition, the volumes view doesn't
+display any free space regions, so we must deselect free space when switching
+to the volumes view.
+
+The following analyzes the different cases:
+
+Disks view
+
+ -- mouse select:
+ The subclassed window proc catches the mouse click.
+
+ First, if this isn't a ctrl-click (multiple select), then all
+ regions are cleared of any existing selection. If it is a
+ multiple selection, then no selection is cleared.
+
+ The region is determined, if the click corresponds to a region, and
+ selected. The focus is given to the selected region.
+
+ -- keyboard select:
+ Approximately the same as above, except it is easier to
+ determine what region we are operating on.
+
+Volumes view
+
+ -- mouse select:
+ -- keyboard select:
+
+ In both cases, we only do things when we get a LVN_ITEMCHANGED
+ notification message. The cases we handle:
+
+ volume loses selection:
+ deselect all regions of this volume.
+
+ volume gets selection:
+ select all regions of this volume.
+
+Things to do when switching from disks view to volumes view:
+ -- set the focus. If the disks view focus is on free space, then
+ put the focus on the first volume in the volumes view.
+ -- adjust the selection: deselect all free space.
+
+Things to do when switching from volumes view to disks view:
+ -- set the focus. Pick a random region from the volume that has the
+ focus. For instance, if volume "F:" has the focus, then pick any of
+ its component regions---e.g., it doesn't matter which region of a volume
+ set gets the focus.
+
+Things to do when we initialize Disk Administrator:
+ -- set no selection
+ -- set the focus:
+ -- if disks view: first region on first disk
+ -- if volumes view: first volume
diff --git a/private/utils/windisk/doc/testing.txt b/private/utils/windisk/doc/testing.txt
new file mode 100644
index 000000000..3a0d235e5
--- /dev/null
+++ b/private/utils/windisk/doc/testing.txt
@@ -0,0 +1,48 @@
+Testing scenarios
+=================
+
+What if you break a mirror with no drive letters left?
+
+What about if there is very little space available and the status bar &
+toolbar overlap?
+
+Does "Refresh" reload the format & label? E.g., format a volume in a
+command window, then refresh windisk. does the new label/etc show up?
+
+anything with volumes that don't have drive letters. You can create
+such volumes by creating more than 24 volumes, thereby using up all
+available drive letters.
+
+test that toolbar state is remembered. i.e., if we allow customization,
+then that customization should be saved.
+
+partition a disk, turn off the machine, detach the disk, run windisk to
+change something on another disk, turn off the machine, reattach the old
+disk, re-run windisk. windisk should remember the FT registry settings
+of the old disk even though it didn't exist during one session.
+
+force a disk to be off-line and test how windisk displays it.
+
+out of memory
+
+corrupt or non-existent FT registry data?
+
+entire disk as extended partition w/ some logical volumes?
+
+no extended partition. Try creating too many partitions.
+
+test with a removable hard drive; a Bernoulli box
+
+context menus on formatted volumes (and perhaps disks)
+
+format
+------
+Try all combinations of the following:
+ -- file system: FAT, OFS, HPFS, NTFS
+ -- volume type: simple, volume set, mirror, stripe set, stripe with parity
+
+chkdsk
+------
+Try all combinations of the following:
+ -- file system: FAT, OFS, HPFS, NTFS
+ -- volume type: simple, volume set, mirror, stripe set, stripe with parity
diff --git a/private/utils/windisk/doc/thecode.txt b/private/utils/windisk/doc/thecode.txt
new file mode 100644
index 000000000..73fab8b60
--- /dev/null
+++ b/private/utils/windisk/doc/thecode.txt
@@ -0,0 +1,212 @@
+Notes on the Cairo Disk Administrator source
+-------------------------------------------------------------------------
+
+The Cairo Disk Administrator (windisk) started with the code for
+NT windisk, and evolved from there.
+
+Here is a short overview of the internal architecture of windisk:
+
+Windisk is basically a front-end to the disk partitioning back-end that
+exists in engine.cxx. The back-end was originally used in two places:
+windisk, and in the ARC install program. There are a number of things in
+windisk, particularly data structures, which reflect this structure.
+
+The back-end interface provides an array of regions for each disk, where
+a region is a primary partition or a logical volume. An extended
+partition is actually a type of primary partition. Free space may be
+either primary or logical. The back-end provides methods to create and
+delete partitions, and query various properties of the disks and
+partitions.
+
+The main structure in windisk is a DISKSTATE. There is an array: one for each
+disk. This structure contains various properties of the disk, but
+mainly contains the region array gathered from the partitioning
+back-end, and several parallel arrays holding information about each
+region (such as whether the region is selected).
+
+Each element of the region array for non-freespace regions has something
+called "persistent data". This is a pointer to a PERSISTENT_REGION_DATA
+structure, holding information such as the region's drive volume label,
+file system type, and drive letter. This information is "persistent" in
+that it persists across partition creation and deletion. When a
+partition is created or deleted, windisk notifies the back-end, and then
+throws away its region information for the disk and asks the back-end
+for a new region array. This new region array has all the old
+"persistent" data, attached to the proper regions.
+
+When a volume is composed of more than one region, handling it becomes a
+bit trickier than handling single-partition volumes. There is no data
+structure maintained that maps volumes to regions, thus it is necessary
+to search all the regions to determine which regions belong to a
+multi-partition volume (e.g., volume set, stripe set, mirror). The
+regions for a multi-partition volume have a pointer to an "FT object"
+structure in their persistent data, where it is possible to find
+information about the volume as a whole.
+
+Cairo windisk also supports CD-ROMs in the main view. This is accomplished
+by an array of CDROM_DESCRIPTOR items. CD-ROMs always display after all the
+disks.
+
+
+The UI
+------
+
+The two views are implemented as follows:
+
+ disks view: a subclassed Windows owner-draw listbox where each element
+ in the listbox is a single disk bar.
+
+ volumes view: a Windows 95 common control listview in "report view"
+ mode. Each element represents a volume (something with a drive letter).
+
+The toolbar is a common control toolbar (in comctl32.dll).
+
+The status bar and legend are simply drawn.
+
+
+The file system operations
+--------------------------
+
+Format and Chkdsk are multi-threaded, to allow one (or more) thread(s)
+to display UI while one performs the actual operation. This works as
+follows:
+
+Format: A dialog box is created with a "cancel" button and a "percent
+full" bar. On creation, a thread is created to do the actual
+formatting. Formatting is done by calling the FMIFS.dll Format()
+entrypoint, which takes as an argument a callback function. This
+callback is called for any feedback event, such as a "percent complete"
+message, or a "amount of free space" message. When the callback gets an
+interesting message, it sends a Windows message to the dialog box procedure
+in the other thread, which gets it and interprets it. When the format
+is finished, a "done" message is posted to the dialog, and it goes away.
+If the user presses "cancel" in the dialog, then a state variable is set
+that is checked on the next callback. If the variable has been set,
+then the callback immediately returns and the caller (the actual file
+system format routine) cleans up and exits.
+
+Chkdsk: very similar to format
+
+
+
+A Reader's Guide to the Windisk Code
+====================================
+
+Note that the NT and Cairo coding conventions are different. I have
+used Cairo function headers on all my new functions, and have converted some
+NT headers to Cairo headers where the difference was too glaring. Many
+Cairo-style headers have the history date "16-Aug-93" because that was
+when I put the header on, not necessarily when I wrote the function!
+
+Note that "IN" and "OUT" are only for function documentation: they
+expand to nothing during preprocessing.
+
+
+Source file translation
+=======================
+
+old file name new file name
+------------- -------------
+arrowin.c not used -- Win95 up/down common control used instead
+cdrom.c cdrom.cxx
+commit.c commit.cxx
+dblspace.c dblspace.cxx
+dskmgr.ico <same>
+fd_nt.c nt.cxx
+fdconst.h const.h
+fddata.c data.cxx
+fddlgs.c dlgs.cxx
+fdengine.c engine.cxx
+fdft.c ft.cxx
+fdft.h ft.hxx
+fdglob.h global.hxx
+fdhelp.c help.cxx
+fdhelpid.h helpid.h
+fdinit.c init.cxx
+fdisk.dlg dialogs.dlg
+fdisk.h headers.hxx (master, precompiled header)
+fdisk.rc windisk.rc
+fdiskmsg.mc messages.mc
+fdlistbx.c listbox.cxx
+fdmem.c mem.cxx
+fdmisc.c misc.cxx
+fdprof.c profile.cxx
+fdproto.h proto.hxx
+fdres.h resids.h
+fdstleg.c stleg.cxx
+fdtypes.h types.hxx
+fmifs.c fmifs.cxx
+ftreg.c ftreg.cxx
+ftreg.dlg ftreg.dlg
+ftreg.res ftreg.res
+ftregres.h ftreg.h
+makefile <same>
+makefile.inc <same>
+network.c network.cxx
+ntlow.c ntlow.cxx
+rmdisk.bmp <same>
+scsi.h <same>
+smdisk.bmp <same>
+sources <same>
+windisk.c windisk.cxx, ops.cxx
+
+
+new files
+---------
+cdpage.cxx, cdpage.hxx -- CD-ROM property page
+cdr.bmp -- bitmap of CD-ROM for property page
+cdrom.hxx -- cdrom.cxx declarations
+chkdsk.cxx, chkdsk.hxx -- chkdsk support
+cm.cxx, cm.hxx -- context-menus
+commit.hxx -- commit.cxx declarations
+dblspace.dlg, dblspace.h, dblspace.res -- dialogs for DoubleSpace support
+dblspace.hxx -- dblspace.cxx declarations
+dialogs.h, dialogs.res -- most dialogs (also, dialogs.dlg)
+dispinfo.cxx, dispinfo.hxx -- display information class for volumes view
+dlgs.hxx -- declarations for dlgs.cxx
+drives.cxx, drives.hxx -- all drive-letter code
+engine.hxx -- declarations for engine.cxx
+extend.cxx, extend.hxx -- Disk Administrator extension support (currently
+ not used)
+fill.cxx, fill.hxx -- fills the volume view with data
+fmifs.hxx -- declarations for fmifs.cxx
+format.cxx, format.hxx -- format support
+fs.cxx, fs.hxx -- database of information on supported file
+ systems
+genlpage.cxx, genlpage.hxx -- "General" property page
+graph.cxx, graph.hxx -- Draws a %used/%free graph on property pages
+hard.bmp -- bitmap of hard disk for property page
+help.hxx -- declarations for help.cxx
+help2.cxx, help2.hxx -- "menu item" help, tooltip help
+init.hxx -- declarations for init.cxx
+label.cxx, label.hxx -- support for changing volume label
+listbox.hxx -- declarations for listbox.cxx
+log.cxx -- support for debug logging
+mem.hxx -- declarations for mem.cxx
+menudict.cxx, menudict.hxx -- dictionary of menu ids for use in allocating
+ extensions context-menu slots. (currently not
+ used)
+network.hxx -- declarations for network.cxx
+nt.hxx -- declarations for nt.cxx
+ntlow.hxx -- declarations for ntlow.cxx
+oleclass.cxx, oleclass.hxx -- OLE support for Disk Administrator extensions
+ (currently not used)
+ops.cxx, ops.hxx -- all partition and fault-tolerance configuration
+ occurs here.
+popup.cxx, popup.hxx -- context-menu support
+print.cxx, print.hxx -- support for printing the results of chkdsk
+profile.hxx -- declarations for profile.cxx
+ps.cxx, ps.hxx -- property sheet support
+rect.cxx, rectpriv.hxx -- the Disk Administrator rectangle control (used
+ in the "colors & patterns" dialog)
+scdrom.ico -- icon of CD-ROMs for volumes view
+select.cxx, select.hxx -- all selection handling code
+shard.ico -- icon of hard disks for volumes view
+smcdrom.bmp -- image of CD-ROM for disks view
+stleg.hxx -- declarations for stleg.cxx
+tb.h -- helper macros for the toolbar code
+tbar.cxx, tbar.hxx -- support for the toolbar
+tool16.bmp, xtra16.bmp -- bitmaps for the toolbar
+trffc14.ico -- "stop" icon for chkdsk stop dialog
+volview.cxx, volview.hxx -- main code for volumes view
+windisk.hxx -- declarations for windisk.cxx
diff --git a/private/utils/windisk/doc/todo.txt b/private/utils/windisk/doc/todo.txt
new file mode 100644
index 000000000..642e8e2c1
--- /dev/null
+++ b/private/utils/windisk/doc/todo.txt
@@ -0,0 +1,104 @@
+A very detailed description of Disk Administrator work items can be
+found in wddev.doc. Things found here are
+more detailed or unrelated notes.
+
+Visual/UI improvements for windisk:
+===================================
+
+The columns in volumes view should be sorted when a column header is clicked,
+and sorted in the opposite order when the column is clicked again. There is
+some code in place to support this, but it doesn't work, due to a problem with
+the list control.
+
+When we start using Cairo/Chicago visuals, there are some tweaks to consider:
+(1) highlight at the top of the toolbar, (2) drop the current spin button; use
+the comctl32.dll spin button (which looks really bad unless next to a sunken
+edit field).
+
+The "properties" menu item should possibly be on the "View" menu instead of
+the "Tools" menu.
+
+The comctl32.dll toolbar sits at the left edge of the window, which looks bad
+with NT visuals (i.e., non-bevelled window edges). Either fix this or wait
+for new visuals.
+
+Allow a user to select a printer to print chkdsk results to. Currently, it
+always uses the default printer. If the default printer doesn't exist, it
+pops up a "no default printer; use Print Manager to choose one" message box.
+
+Display what is loaded from a saved configuration, and allow changes,
+etc, before committing. And only commit the saved config if the user
+chooses to after a confirmation. Currently, a "configuration load" loads up
+the saved configuration and saves it: you get what you saved, no changes
+allowed.
+
+Don't regenerate the listview unless it changes. Also, if only one line
+changes, fix that line instead of regenerating the entire view.
+
+Have an option on the "Drive letter" dialog that allows setting all
+drive letters on the system to their default. Essentially, it would set
+everything to "do not assign a drive letter" except FT sets, which don't
+support non-persistent drive letters. So, after all the default ones
+were assigned, all the FT ones would be assigned.
+
+Allow setting a drive letter to something used by a network redirected drive.
+This would require doing the equivalent of a "net use x: /d" before affecting
+the change, and would require user confirmation before doing so.
+
+More columns in volumes view. There is likely more useful information that
+could be placed in the view, such as which volumes have active net sessions,
+which volumes are shared on the network in any way, an "activity" measurement
+so an admin can ask the question "which disks get the most use", etc. The set
+of displayed columns should be configurable, and stored with the user profile.
+
+Visually distinguish formatted & unformatted (i.e., newly created)
+volumes more strongly than now. For example, two volumes (one
+formatted, one not) that both have no label look exactly alike, except
+one has a "file system" named "Unknown". Could we gray the text? Shade
+the volume boxes? Use a different font?
+
+If you try to delete the primary/boot partition on drive 0, you get a
+message that "Windisk can't delete this partition" (similar, anyway).
+DOS Fdisk says the same, but pointed out to me that it was because there
+was an extended partition. After I deleted the extended partition, I
+could delete the primary partition. Windisk should give a better
+error message in this case?
+
+When Disk Administrator is starting, display a "splash screen" pop-up until we
+are ready to go.
+
+Put CD-ROMs in volumes view.
+
+
+
+Functional improvements for windisk:
+====================================
+
+One or more standard disk property sheets should be created that display
+SCSI/IDE adapter info, physical drive info, possibly some performance
+measurements, hardware FT information, etc. There could be one property sheet
+per disk, with any number of pages. Or, if we only need one page per disk, we
+could have a sheet where each page is titled "disk N".
+
+Since we now have on-the-fly partitioning, we should ask the user
+immediately after creating a partition whether or not they wish to format the
+volume, and send them directly into that dialog if they do.
+
+The profile information should use registry calls, not *PrivateProfileString
+APIs.
+
+Q: when does the "Configuration information not available" message get
+displayed in an empty disk box?
+
+I have hard-coded FmMediaFixed in the Format call. What about removable
+hard drives?
+
+Windisk saves information to the registry for every disk that it's ever
+seen. Should we have some kind of "advanced" option that allows an admin to
+purge unused registry information?
+
+
+Other:
+======
+
+Check all BUGBUGs before shipping.
diff --git a/private/utils/windisk/doc/wddev.doc b/private/utils/windisk/doc/wddev.doc
new file mode 100644
index 000000000..e1c2799f8
--- /dev/null
+++ b/private/utils/windisk/doc/wddev.doc
Binary files differ
diff --git a/private/utils/windisk/doc/why.txt b/private/utils/windisk/doc/why.txt
new file mode 100644
index 000000000..41783a646
--- /dev/null
+++ b/private/utils/windisk/doc/why.txt
@@ -0,0 +1,154 @@
+An overview of the Cairo Disk Administrator
+-------------------------------------------
+
+The Cairo Disk Administrator is an evolutionary improvement to the NT
+Disk Administrator. It differs from the NT version as follows:
+
+-- There are now two views: the volumes view and the disks view.
+The disks view is what exists in the current NT Disk Administrator.
+The volumes view is a columnar view filled with information about each
+volume (as opposed to each disk). It is intended to provide a quick
+summary of the volumes on a machine from a logical, as opposed to physical
+perspective. The columns include: (1) volume label, (2) capacity in MB,
+(3) free space in MB, (4) % free space, (5) file system type, (6) whether or
+not the volume is fault tolerant, (7) what type of volume: mirror, stripe,
+parity set, volume set, or simple, (8) the fault tolerance overhead in MB,
+(9) the FT status. The items can be sorted based on a particular column
+by clicking on the column header. Note that this makes it easy for an
+administrator to ask "what volumes have the most free space?" and similar
+questions.
+
+-- Right-button context menus on free space and volumes. A context menu
+displays the full set of allowable operations, even for multiple selections.
+(perhaps none, in which case the context menu indicates there are no valid
+operations). Also, there is a context menu on the legend.
+ Context menus are very valuable in this tool; they surface all the
+operations available in the tool in a simple-to-use manner. For instance, to
+create a volume from free space, you do the following:
+ 1. Right-click on a free space region. This both selects the region and
+ brings up the context menu,
+ 2. Choose "Create..."
+ 3. Pick the size and hit "OK"
+ 4. Choose "Commit Changes..." on any context menu.
+ 5. Right-click again to get a context menu
+ 6. Choose "format".
+ 7. Choose the file system and type a label, hit "OK"
+ 8. You've got a new volume.
+Note that you can also create FT sets by multiply selecting free space (or
+free space + non-free space for mirrors) and using the context menu.
+
+-- CD-ROM devices are displayed in the main view; you don't need to find a
+menu item to do CD-ROM operations. You change a CD-ROM drive letter just as
+you would choose any other volume's drive letter: select the volume (by
+clicking on the CD-ROM "bar"), and invoke the "Drive Letter..." function,
+either from the "Tools" menu or the context menu.
+
+-- "Chkdsk" is supported. The visualization is a %done graph. After it is
+done, a resizeable dialog showing error, warning, and informational messages
+is shown. These messages can be copy-and-pasted, saved to a file, or printed.
+
+-- Property sheets on volumes. The only page is a "General" page. The
+information displayed is similar to that in the volumes view, but
+is formatted for easier consumption. The volume operations are also available
+from the property sheet, namely format, chkdsk, and label (where label
+changing happens by simply editing the label in an edit control, not invoking
+a supplemental "label" dialog).
+
+
+
+Extensibility enhancements
+--------------------------
+
+-- There is a mechanism in place for 3rd parties to write extensions to
+the Disk Administrator using OLE interfaces. An extension provides menu items
+and property sheets. There are two types of extensions: volume and disk.
+During startup, Disk Administrator finds all the extensions (this set is
+currently hard-coded), and determines which extension is interested in which
+volume or disk. An extension may "claim" more than one volume or disk. Then,
+all the menu items and property pages provided by the extension are added
+when a user selects a particular volume or disk.
+
+NOTE: The extension architecture is currently "#ifdef"ed out, due to recent
+changes in the property sheet model (from OLE forms to Chicago common
+controls). The extension interface needs serious attention if it is to be
+useful.
+
+
+
+Basic usability enhancements
+----------------------------
+
+-- A toolbar with tooltips. (It will be customizable.)
+
+-- The width of disk bars in the disks view is set proportional to the
+Disk Administrator *window*, not the *display*, and are resized on window
+resizing. This eliminates the effect of "losing" a partition visually,
+when really all that's happened is that it's off the right edge of the screen.
+
+-- The status bar resizes instead of being clipped.
+
+-- Menu help: the status bar area displays a short help string based
+on the current menu selection
+
+-- The legend only displays the colors that appear in the disks view. For
+instance, the legend item for "Stripe set" doesn't appear if there are no
+stripe sets on the machine.
+
+-- A "stripe set with parity" gets a different legend color, which can be
+changed independent of the "stripe set" color, and is stored to the profile
+separately
+
+-- If the window isn't wide enough for a single-row legend, it wraps to use
+two or more rows.
+
+-- There is a "disk display" option which allows disk bars in the disks view
+to be sized (for width) either proportional to the capacity of the disk or all
+equally. This helps with the problem of hugely disproportionately sized
+disks in the system making the small disk bars hard to use. This value is
+stored to the profile.
+
+-- The "region display" option (which allows partitions in the disks view
+to be sized based on actual size, all equally (on this particular disk), or
+automatically based on Disk Administrator criteria) applies to only a single
+selected disk in standard NT. In the Cairo version, there is an option to
+apply the option choice to all disks. This option is the default. In
+addition, the automatic criteria was improved so Disk Administrator makes a
+much better default choice.
+
+
+
+Other enhancements
+------------------
+
+-- The source code compiles with the C++ compiler for better static checking.
+Few language constructs specific to C++ are used.
+
+-- The source is completely UNICODE
+
+-- Precompiled headers are used for better compilation speed
+
+
+
+What is left to implement before the Cairo version is finished
+--------------------------------------------------------------
+
+-- %done visualization in chkdsk is based on %done messages sent by the
+file system utilities. OFS doesn't send these messages.
+
+-- The extensibility system should be updated and fleshed out, or dropped.
+
+-- There is code to allow context menus on disks. If we don't have any
+interesting items (like property sheets), the code should be ripped out.
+
+-- The toolbar customization needs to be enabled and finished: the full set
+of operations is not available as toolbar buttons.
+
+-- It needs to be thoroughly tested.
+
+
+
+What else?
+----------
+
+-- The wddev.doc document describes a work program for more Disk Administrator
+improvements, including remoting, etc.
diff --git a/private/utils/windisk/doc/windisk.ppt b/private/utils/windisk/doc/windisk.ppt
new file mode 100644
index 000000000..24758aaf9
--- /dev/null
+++ b/private/utils/windisk/doc/windisk.ppt
Binary files differ
diff --git a/private/utils/windisk/hard/chard.cxx b/private/utils/windisk/hard/chard.cxx
new file mode 100644
index 000000000..df1702d44
--- /dev/null
+++ b/private/utils/windisk/hard/chard.cxx
@@ -0,0 +1,265 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: chard.cxx
+//
+// Contents: Disk Administrator volume extension class for hard disks
+//
+// Classes: CHard
+//
+// History: 10-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.hxx>
+#pragma hdrstop
+
+#include "hard.hxx"
+#include "hardmenu.hxx"
+#include "dialogs.h"
+#include "global.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+static MenuItemType hard_menu[] =
+{
+ {
+ TEXT("&Configure RAID..."),
+ TEXT("Configure the fault tolerance characteristics of this logical disk"),
+ 0,
+ NULL //filled in later
+ }
+};
+
+static HardDiskInfoType hard_info =
+{
+ TEXT("Microsoft SCSI/RAID configuration"),
+ TEXT("MS RAID"),
+ DA_HD_FAULT_TOLERANT,
+
+ // menu items:
+ { ARRAYLEN(hard_menu), hard_menu },
+
+ // property pages:
+ { 0, NULL }
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHard::CHard
+//
+// Synopsis: constructor
+//
+// Effects:
+//
+// Arguments: [pUnk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 10-May-93 BruceFo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CHard::CHard(
+ IN IUnknown* pUnk
+ )
+ :
+ m_IUnknown(pUnk)
+{
+ HRESULT hr = CoCreateInstance(
+ CLSID_KDA_HardMenu,
+ NULL,
+ CLSCTX_ALL,
+ (REFIID)IID_IDAMenuDispatch,
+ (void**)&_pmenu);
+ if (SUCCEEDED(hr))
+ {
+ daDebugOut((DEB_TRACE, "Found IDAMenuDispatch\n"));
+ }
+ else
+ {
+ daDebugOut((DEB_ERROR, "Couldn't get IDAMenuDispatch\n"));
+
+ _pmenu = NULL;
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHard::~CHard
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 10-May-93 BruceFo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CHard::~CHard()
+{
+ if (_pmenu)
+ {
+ _pmenu->Release();
+ }
+}
+
+STDMETHODIMP
+CHard::QueryInterface(
+ IN REFIID riid,
+ OUT LPVOID* ppvObj
+ )
+{
+ return m_IUnknown->QueryInterface(riid, ppvObj);
+}
+
+STDMETHODIMP_(ULONG)
+CHard::AddRef(
+ VOID
+ )
+{
+ return m_IUnknown->AddRef();
+}
+
+STDMETHODIMP_(ULONG)
+CHard::Release(
+ VOID
+ )
+{
+ return m_IUnknown->Release();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHard::Claim
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-Jul-93 BruceFo Created
+//
+// Notes: BUGBUG: a mock-up: the first disk gets it, the others don't
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+CHard::Claim(
+ IN HardDiskInfoBlockType* pInfo,
+ OUT BOOL* pfInterested
+ )
+{
+ daDebugOut((DEB_TRACE,
+ "IDAHardDiskInfo::Claim(%d,...) called\n",
+ pInfo->ulDiskNumber
+ ));
+
+ BOOL fInterested;
+
+ if (0 == pInfo->ulDiskNumber)
+ {
+ fInterested = TRUE;
+ }
+ else
+ {
+ fInterested = FALSE;
+ }
+
+ *pfInterested = fInterested;
+
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHard::QueryInfo
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: ppInfo
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 10-May-93 BruceFo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+CHard::QueryInfo(
+ OUT HardDiskInfoType** ppInfo
+ )
+{
+ daDebugOut((DEB_TRACE,"IDAHardDiskInfo::QueryInfo() called\n"));
+
+ hard_info.mnuOps.aMenuItems[0].pMenuDispatch = _pmenu;
+
+ *ppInfo = &hard_info;
+ return S_OK;
+}
diff --git a/private/utils/windisk/hard/chardmnu.cxx b/private/utils/windisk/hard/chardmnu.cxx
new file mode 100644
index 000000000..f56d33da6
--- /dev/null
+++ b/private/utils/windisk/hard/chardmnu.cxx
@@ -0,0 +1,271 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: chardmnu.cxx
+//
+// Contents: Disk Administrator extension class for hard disks: menu ops
+//
+// Classes: CHardMenu
+//
+// History: 10-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.hxx>
+#pragma hdrstop
+
+#include "hardmenu.hxx"
+#include "dialogs.h"
+#include "global.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+DoConfigureRAID(
+ IN HWND hwndParent,
+ IN PWSTR DeviceName
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHardMenu::CHardMenu
+//
+// Synopsis: constructor
+//
+// Effects:
+//
+// Arguments: [pUnk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 10-May-93 BruceFo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CHardMenu::CHardMenu(
+ IN IUnknown* pUnk
+ )
+ :
+ m_IUnknown(pUnk)
+{
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CHardMenu::~CHardMenu
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 10-May-93 BruceFo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CHardMenu::~CHardMenu()
+{
+}
+
+STDMETHODIMP
+CHardMenu::QueryInterface(
+ IN REFIID riid,
+ OUT LPVOID* ppvObj
+ )
+{
+ return m_IUnknown->QueryInterface(riid, ppvObj);
+}
+
+STDMETHODIMP_(ULONG)
+CHardMenu::AddRef(
+ VOID
+ )
+{
+ return m_IUnknown->AddRef();
+}
+
+STDMETHODIMP_(ULONG)
+CHardMenu::Release(
+ VOID
+ )
+{
+ return m_IUnknown->Release();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CHardMenu::MenuDispatch
+//
+// Synopsis: Dispatch routine for Hard disk menu items
+//
+// Arguments: [hwndParent] -- parent HWND for any UI
+// [DeviceName] -- The NT object for the drive, e.g.
+// "\Device\Harddisk0"
+// [Item] -- Item number of invoked menu. This is the item
+// number associated with the menu in the information
+// passed to the Disk Administrator in the QueryInfo call.
+//
+// Returns: HRESULT
+//
+// History: 11-Jan-94 BruceFo Created
+//
+// Notes:
+//
+// item menu choice
+// ---- -----------
+// 0 Configure RAID
+//
+//--------------------------------------------------------------------------
+
+HRESULT
+CHardMenu::MenuDispatch(
+ IN HWND hwndParent,
+ IN LPWSTR DeviceName,
+ IN UINT Item
+ )
+{
+ switch (Item)
+ {
+ case 0:
+ daDebugOut((DEB_TRACE, "Configure RAID for %ws\n", DeviceName));
+ DoConfigureRAID(hwndParent, DeviceName);
+ break;
+
+ default:
+ daDebugOut((DEB_ERROR,
+ "Unknown hard disk extension, drive: %ws, menu item: %d\n",
+ DeviceName,
+ Item));
+ break;
+ }
+
+ return S_OK;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+BOOL CALLBACK ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+
+VOID
+DoConfigureRAID(
+ IN HWND hwndParent,
+ IN PWSTR DeviceName
+ )
+{
+ HINSTANCE hInstanceSpin = LoadLibrary(L"spincube.dll");
+
+ int iRet = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CONFIG),
+ hwndParent,
+ ConfigDlgProc,
+ (LPARAM) g_hInstance
+ );
+
+ if (-1 == iRet)
+ {
+ daDebugOut((DEB_ERROR, "Couldn't create the dialog!\n"));
+ }
+
+ FreeLibrary(hInstanceSpin);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ConfigDlgProc, public
+//
+// Synopsis: Dialog procedure for the mocked-up "Configure RAID" dialog.
+//
+// Arguments: [hWnd] -- Window handle of the dialog box.
+// [wMsg] -- Window message.
+// [wParam] -- Message parameter.
+// [lParam] -- Message parameter.
+//
+// Returns: TRUE if message completely processed; FALSE to cause default
+// processing.
+//
+//--------------------------------------------------------------------------
+
+BOOL CALLBACK
+ConfigDlgProc( HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch (wMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ //
+ // Center dialog on screen.
+ //
+
+ RECT rc;
+
+ GetWindowRect(hWnd, &rc);
+ SetWindowPos(
+ hWnd,
+ NULL,
+ (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2,
+ (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2,
+ 0,
+ 0,
+ SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
+ {
+ switch (GET_WM_COMMAND_ID(wParam, lParam))
+ {
+ case IDOK:
+ EndDialog(hWnd, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hWnd,0);
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/private/utils/windisk/hard/dialogs.dlg b/private/utils/windisk/hard/dialogs.dlg
new file mode 100644
index 000000000..6f19c545c
--- /dev/null
+++ b/private/utils/windisk/hard/dialogs.dlg
@@ -0,0 +1,8 @@
+IDD_CONFIG DIALOG 60, 24, 190, 161
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Microsoft SCSI/RAID Config"
+BEGIN
+ DEFPUSHBUTTON "OK", IDOK, 68, 138, 50, 14
+ CONTROL "", IDC_PICTURE, "Spincube", 0x0003, 20, 16, 152, 110
+END
diff --git a/private/utils/windisk/hard/dialogs.h b/private/utils/windisk/hard/dialogs.h
new file mode 100644
index 000000000..39b56efdc
--- /dev/null
+++ b/private/utils/windisk/hard/dialogs.h
@@ -0,0 +1,3 @@
+#define IDD_CONFIG 100
+#define IDC_PICTURE 101
+
diff --git a/private/utils/windisk/hard/global.hxx b/private/utils/windisk/hard/global.hxx
new file mode 100644
index 000000000..d48da8fe0
--- /dev/null
+++ b/private/utils/windisk/hard/global.hxx
@@ -0,0 +1,22 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: global.hxx
+//
+// Contents: global variable definitions
+//
+// History: 11-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __GLOBAL_HXX__
+#define __GLOBAL_HXX__
+
+extern HINSTANCE g_hInstance;
+
+extern ULONG g_ulcInstancesHard;
+extern ULONG g_ulcInstancesHardMenu;
+
+#endif // __GLOBAL_HXX__
diff --git a/private/utils/windisk/hard/hard.cxx b/private/utils/windisk/hard/hard.cxx
new file mode 100644
index 000000000..12e2adb43
--- /dev/null
+++ b/private/utils/windisk/hard/hard.cxx
@@ -0,0 +1,199 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hard.cxx
+//
+// Contents: Disk Administrator volume extension class for hard disks
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-May-93 BruceFo Created from kevinro event report code
+//
+// Note: Eventually, this code will be generated by tools. Therefore, the
+// comments and cleanliness is not up to par.
+//
+//----------------------------------------------------------------------------
+
+#include <headers.hxx>
+#pragma hdrstop
+
+#include "hard.hxx"
+#include "global.hxx"
+
+
+CHardIUnknown::CHardIUnknown()
+ : m_pClass(NULL),
+ m_uRefs(1)
+{
+ InterlockedIncrement((LONG*)&g_ulcInstancesHard);
+}
+
+
+CHardIUnknown::~CHardIUnknown()
+{
+ InterlockedDecrement((LONG*)&g_ulcInstancesHard);
+ delete m_pClass;
+}
+
+STDMETHODIMP
+CHardIUnknown::QueryInterface(REFIID riid, LPVOID* ppvObj)
+{
+ *ppvObj = NULL;
+
+ IUnknown *pUnkTemp = NULL;
+ SCODE sc = S_OK;
+
+ if (IsEqualIID(IID_IUnknown, riid))
+ {
+ pUnkTemp = (IUnknown*) this;
+ }
+ else
+ if (IsEqualIID(IID_IDAHardDiskInfo, riid))
+ {
+ pUnkTemp = (IDAHardDiskInfo*) m_pClass;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (pUnkTemp != NULL)
+ {
+ pUnkTemp->AddRef();
+ }
+
+ *ppvObj = pUnkTemp;
+
+ return sc;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardIUnknown::AddRef()
+{
+ InterlockedIncrement((LONG*)&m_uRefs);
+ return m_uRefs;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardIUnknown::Release()
+{
+ ULONG cRef;
+
+ if (0 == (cRef=InterlockedDecrement((LONG*)&m_uRefs)))
+ {
+ delete this;
+ }
+
+ return cRef;
+}
+
+
+STDMETHODIMP
+CHardCF::QueryInterface(REFIID riid, LPVOID* ppvObj)
+{
+ *ppvObj = NULL;
+
+ IUnknown* pUnkTemp = NULL;
+ SCODE sc = S_OK;
+
+ if ( IsEqualIID(IID_IUnknown, riid)
+ || IsEqualIID(IID_IClassFactory, riid))
+ {
+ pUnkTemp = (CHardCF *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (pUnkTemp != NULL)
+ {
+ pUnkTemp->AddRef();
+ }
+
+ *ppvObj = pUnkTemp;
+
+ return sc;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardCF::AddRef()
+{
+ InterlockedIncrement((LONG*)&g_ulcInstancesHard);
+ return g_ulcInstancesHard;
+}
+
+STDMETHODIMP_(ULONG)
+CHardCF::Release()
+{
+ InterlockedDecrement((LONG*)&g_ulcInstancesHard);
+ return g_ulcInstancesHard;
+}
+
+
+
+//
+// IClassFactory Overide
+//
+STDMETHODIMP
+CHardCF::CreateInstance(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObj)
+{
+ HRESULT hr = S_OK;
+ CHardIUnknown* pIUnk = NULL;
+
+ pIUnk = new CHardIUnknown();
+
+ if (pUnkOuter == NULL)
+ {
+ pIUnk->m_pClass = new CHard(pIUnk);
+
+ hr = pIUnk->m_pClass->QueryInterface(riid, ppvObj);
+ pIUnk->Release();
+
+ if (FAILED(hr))
+ {
+ //
+ // BUGBUG: Whats the error code?
+ //
+
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ if ( ! IsEqualIID(riid, IID_IUnknown) )
+ {
+ hr = E_NOINTERFACE;
+ }
+ else
+ {
+ pIUnk->m_pClass = new CHard(pUnkOuter);
+ *ppvObj = (IUnknown *)pIUnk;
+ pIUnk->AddRef();
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ delete pIUnk;
+ }
+
+ return hr;
+}
+
+
+STDMETHODIMP
+CHardCF::LockServer(BOOL fLock)
+{
+ //
+ // BUGBUG: Whats supposed to happen here?
+ //
+ return S_OK;
+}
diff --git a/private/utils/windisk/hard/hard.def b/private/utils/windisk/hard/hard.def
new file mode 100644
index 000000000..acf804dea
--- /dev/null
+++ b/private/utils/windisk/hard/hard.def
@@ -0,0 +1,11 @@
+#include "..\..\sysmgmt.def"
+
+LIBRARY DAHARD
+DESCRIPTION 'Microsoft Windows NT Disk Administrator Extension Class for Hard Disks'
+
+EXPORTS
+
+ PRIVATESYMBOL( DllGetClassObject, 12 )
+ PRIVATESYN( DllGetClassObject, 12 )
+ PRIVATESYMBOL( DllCanUnloadNow, 0 )
+ PRIVATESYN( DllCanUnloadNow, 0 )
diff --git a/private/utils/windisk/hard/hard.hxx b/private/utils/windisk/hard/hard.hxx
new file mode 100644
index 000000000..b5780dade
--- /dev/null
+++ b/private/utils/windisk/hard/hard.hxx
@@ -0,0 +1,103 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hard.hxx
+//
+// Contents: Disk Administrator volume extension class for Hard Disks
+//
+// Classes:
+// CHardIUnknown
+// CHardCF
+// CHard
+//
+// History: 10-May-93 BruceFo Created from kevinro event report code
+//
+//----------------------------------------------------------------------------
+
+class CHardIUnknown;
+class CHardCF;
+class CHard;
+
+class CHard : public IDAHardDiskInfo
+{
+public:
+ CHard(IUnknown* pUnk);
+ ~CHard();
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ //
+ // IDAHardDiskInfo methods
+ //
+
+ STDMETHOD(Claim)(HardDiskInfoBlockType* pInfo, BOOL* pfInterested);
+ STDMETHOD(QueryInfo)(HardDiskInfoType** ppInfo);
+
+private:
+ friend CHardCF;
+ friend CHardIUnknown;
+ IUnknown* m_IUnknown;
+
+ //
+ // Class variables
+ //
+
+ CLSID m_cidClass;
+
+ IDAMenuDispatch* _pmenu;
+};
+
+class CHardIUnknown : public IUnknown
+{
+public:
+ CHardIUnknown();
+ ~CHardIUnknown();
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+private:
+ friend CHardCF;
+
+ CHard * m_pClass;
+ unsigned long m_uRefs;
+};
+
+
+
+class CHardCF : public IClassFactory
+{
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ //
+ // IClassFactory methods
+ //
+
+ STDMETHOD(CreateInstance)(
+ IUnknown* pUnkOuter,
+ REFIID riid,
+ LPVOID* ppvObj);
+
+ STDMETHOD(LockServer)(BOOL fLock);
+};
diff --git a/private/utils/windisk/hard/hard.rc b/private/utils/windisk/hard/hard.rc
new file mode 100644
index 000000000..dc53a2f55
--- /dev/null
+++ b/private/utils/windisk/hard/hard.rc
@@ -0,0 +1,28 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hard.rc
+//
+// Contents: Resources for Disk Administrator Hard Disk extension class
+//
+// History: 27-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include "dialogs.h"
+#include "dialogs.dlg"
+
+////////////////////////////////////////////////////////////////////////////
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Disk Administrator Hard Disk Extension Class"
+#define VER_INTERNALNAME_STR "dahard\0"
+#define VER_ORIGINALFILENAME_STR "DAHARD.DLL"
+
+#include "common.ver"
diff --git a/private/utils/windisk/hard/hardmenu.cxx b/private/utils/windisk/hard/hardmenu.cxx
new file mode 100644
index 000000000..0d219ebb1
--- /dev/null
+++ b/private/utils/windisk/hard/hardmenu.cxx
@@ -0,0 +1,192 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hardmenu.cxx
+//
+// Contents: Disk Administrator extension class for hard disks: menu ops
+//
+// History: 11-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.hxx>
+#pragma hdrstop
+
+#include "hardmenu.hxx"
+#include "global.hxx"
+
+
+CHardMenuIUnknown::CHardMenuIUnknown()
+ : m_pClass(NULL),
+ m_uRefs(1)
+{
+ InterlockedIncrement((LONG*)&g_ulcInstancesHardMenu);
+}
+
+
+CHardMenuIUnknown::~CHardMenuIUnknown()
+{
+ InterlockedDecrement((LONG*)&g_ulcInstancesHardMenu);
+ delete m_pClass;
+}
+
+STDMETHODIMP
+CHardMenuIUnknown::QueryInterface(REFIID riid, LPVOID* ppvObj)
+{
+ *ppvObj = NULL;
+
+ IUnknown *pUnkTemp = NULL;
+ SCODE sc = S_OK;
+
+ if (IsEqualIID(IID_IUnknown, riid))
+ {
+ pUnkTemp = (IUnknown*) this;
+ }
+ else
+ if (IsEqualIID(IID_IDAMenuDispatch, riid))
+ {
+ pUnkTemp = (IDAMenuDispatch*) m_pClass;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (pUnkTemp != NULL)
+ {
+ pUnkTemp->AddRef();
+ }
+
+ *ppvObj = pUnkTemp;
+
+ return sc;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardMenuIUnknown::AddRef()
+{
+ InterlockedIncrement((LONG*)&m_uRefs);
+ return m_uRefs;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardMenuIUnknown::Release()
+{
+ ULONG cRef;
+
+ if (0 == (cRef=InterlockedDecrement((LONG*)&m_uRefs)))
+ {
+ delete this;
+ }
+
+ return cRef;
+}
+
+
+STDMETHODIMP
+CHardMenuCF::QueryInterface(REFIID riid, LPVOID* ppvObj)
+{
+ *ppvObj = NULL;
+
+ IUnknown* pUnkTemp = NULL;
+ SCODE sc = S_OK;
+
+ if ( IsEqualIID(IID_IUnknown, riid)
+ || IsEqualIID(IID_IClassFactory, riid))
+ {
+ pUnkTemp = (CHardMenuCF *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (pUnkTemp != NULL)
+ {
+ pUnkTemp->AddRef();
+ }
+
+ *ppvObj = pUnkTemp;
+
+ return sc;
+}
+
+
+STDMETHODIMP_(ULONG)
+CHardMenuCF::AddRef()
+{
+ InterlockedIncrement((LONG*)&g_ulcInstancesHardMenu);
+ return g_ulcInstancesHardMenu;
+}
+
+STDMETHODIMP_(ULONG)
+CHardMenuCF::Release()
+{
+ InterlockedDecrement((LONG*)&g_ulcInstancesHardMenu);
+ return g_ulcInstancesHardMenu;
+}
+
+
+
+//
+// IClassFactory Overide
+//
+STDMETHODIMP
+CHardMenuCF::CreateInstance(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObj)
+{
+ HRESULT hr = S_OK;
+ CHardMenuIUnknown* pIUnk = NULL;
+
+ pIUnk = new CHardMenuIUnknown();
+
+ if (pUnkOuter == NULL)
+ {
+ pIUnk->m_pClass = new CHardMenu(pIUnk);
+
+ hr = pIUnk->m_pClass->QueryInterface(riid, ppvObj);
+ pIUnk->Release();
+
+ if (FAILED(hr))
+ {
+ //
+ // BUGBUG: Whats the error code?
+ //
+
+ hr = E_NOINTERFACE;
+ }
+ }
+ else
+ {
+ if ( ! IsEqualIID(riid, IID_IUnknown) )
+ {
+ hr = E_NOINTERFACE;
+ }
+ else
+ {
+ pIUnk->m_pClass = new CHardMenu(pUnkOuter);
+ *ppvObj = (IUnknown *)pIUnk;
+ pIUnk->AddRef();
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ delete pIUnk;
+ }
+
+ return hr;
+}
+
+
+STDMETHODIMP
+CHardMenuCF::LockServer(BOOL fLock)
+{
+ //
+ // BUGBUG: Whats supposed to happen here?
+ //
+ return S_OK;
+}
diff --git a/private/utils/windisk/hard/hardmenu.hxx b/private/utils/windisk/hard/hardmenu.hxx
new file mode 100644
index 000000000..cb92caa89
--- /dev/null
+++ b/private/utils/windisk/hard/hardmenu.hxx
@@ -0,0 +1,104 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hardmenu.hxx
+//
+// Contents: Disk Administrator extension class for Hard Disks: menu ops
+//
+// Classes:
+// CHardMenuIUnknown
+// CHardMenuCF
+// CHardMenu
+//
+// History: 11-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+class CHardMenuIUnknown;
+class CHardMenuCF;
+class CHardMenu;
+
+class CHardMenu : public IDAMenuDispatch
+{
+public:
+ CHardMenu(IUnknown* pUnk);
+ ~CHardMenu();
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ //
+ // IDAMenuDispatch methods
+ //
+
+ STDMETHOD(MenuDispatch)(
+ HWND hwndParent,
+ LPWSTR DriveName,
+ UINT Item
+ );
+
+private:
+ friend CHardMenuCF;
+ friend CHardMenuIUnknown;
+ IUnknown* m_IUnknown;
+
+ //
+ // Class variables
+ //
+
+ CLSID m_cidClass;
+};
+
+class CHardMenuIUnknown : public IUnknown
+{
+public:
+ CHardMenuIUnknown();
+ ~CHardMenuIUnknown();
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+private:
+ friend CHardMenuCF;
+
+ CHardMenu * m_pClass;
+ unsigned long m_uRefs;
+};
+
+
+
+class CHardMenuCF : public IClassFactory
+{
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ //
+ // IClassFactory methods
+ //
+
+ STDMETHOD(CreateInstance)(
+ IUnknown* pUnkOuter,
+ REFIID riid,
+ LPVOID* ppvObj);
+
+ STDMETHOD(LockServer)(BOOL fLock);
+};
diff --git a/private/utils/windisk/hard/headers.hxx b/private/utils/windisk/hard/headers.hxx
new file mode 100644
index 000000000..6e5fb0448
--- /dev/null
+++ b/private/utils/windisk/hard/headers.hxx
@@ -0,0 +1,19 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.hxx
+//
+// Contents: Headers for hard disk extension class
+//
+// History: 11-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+#include <windowsx.h>
+#include <ole2.h>
+#include <debug.h>
+
+#include <dacommon.h>
diff --git a/private/utils/windisk/hard/libinit.cxx b/private/utils/windisk/hard/libinit.cxx
new file mode 100644
index 000000000..da059962e
--- /dev/null
+++ b/private/utils/windisk/hard/libinit.cxx
@@ -0,0 +1,144 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: libinit.cxx
+//
+// Contents: DLL initialization code
+//
+// Functions:
+// DllMain
+//
+// History: 9-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.hxx>
+#pragma hdrstop
+
+#include <util.hxx>
+
+#include "hard.hxx"
+#include "hardmenu.hxx"
+#include "global.hxx"
+
+DECLARE_INFOLEVEL(da)
+
+HINSTANCE g_hInstance = NULL;
+
+ULONG g_ulcInstancesHard;
+ULONG g_ulcInstancesHardMenu;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: DllMain
+//
+// Synopsis: Performs initialization of the DLL.
+//
+// Arguments: hInstance - Handle to this dll
+// dwReason - Reason this function was called. Can be
+// Process/Thread Attach/Detach.
+//
+// Returns: BOOL - TRUE if no error. FALSE otherwise
+//
+// History: 15-May-92 BryanT Created
+//
+//--------------------------------------------------------------------
+
+extern "C" BOOL
+DllMain(
+ HINSTANCE hInstance,
+ DWORD dwReason,
+ LPVOID lpReserved
+ )
+{
+ BOOL fRc = TRUE;
+
+ UNREFERENCED_PARM(lpReserved);
+ UNREFERENCED_PARM(hInstance);
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+
+#ifdef DA_PRIVATE_BUILD
+ daInfoLevel =
+ DEB_ERROR
+ | DEB_WARN
+ | DEB_TRACE
+ | DEB_IERROR
+ | DEB_IWARN
+ | DEB_ITRACE
+ ;
+#endif
+
+ g_hInstance = hInstance;
+
+ //
+ // Disable thread notification from OS
+ //
+ DisableThreadLibraryCalls(hInstance);
+
+ daDebugOut((DEB_ITRACE,"dahard.dll attach\n"));
+ break;
+
+ case DLL_PROCESS_DETACH:
+ daDebugOut((DEB_ITRACE,"dahard.dll detach\n"));
+ break;
+
+ }
+
+ return(fRc);
+}
+
+
+
+STDAPI
+DllCanUnloadNow(
+ VOID
+ )
+{
+ daDebugOut((DEB_ITRACE,"--> enter dahard.dll DllCanUnloadNow\n"));
+
+ if ( 0 == g_ulcInstancesHard
+ && 0 == g_ulcInstancesHardMenu)
+ {
+ return S_OK;
+ }
+ else
+ {
+ return S_FALSE;
+ }
+}
+
+
+CHardCF cfHard;
+CHardMenuCF cfHardMenu;
+
+STDAPI
+DllGetClassObject(
+ REFCLSID cid,
+ REFIID iid,
+ LPVOID* ppvObj
+ )
+{
+#if DBG == 1
+ daDebugOut((DEB_ITRACE,"--> enter dahard.dll DllGetClassObject\n"));
+ DumpGuid(DEB_ITRACE|DEB_NOCOMPNAME, L" clsid = ", cid);
+ DumpGuid(DEB_ITRACE|DEB_NOCOMPNAME, L" iid = ", iid);
+#endif // DBG == 1
+
+ HRESULT hr = E_NOINTERFACE;
+
+ if (IsEqualCLSID(cid, CLSID_KDA_Hard))
+ {
+ hr = cfHard.QueryInterface(iid, ppvObj);
+ }
+ else if (IsEqualCLSID(cid, CLSID_KDA_HardMenu))
+ {
+ hr = cfHardMenu.QueryInterface(iid, ppvObj);
+ }
+ return hr;
+}
diff --git a/private/utils/windisk/hard/makefile b/private/utils/windisk/hard/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/hard/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/hard/makefile.inc b/private/utils/windisk/hard/makefile.inc
new file mode 100644
index 000000000..67ad41348
--- /dev/null
+++ b/private/utils/windisk/hard/makefile.inc
@@ -0,0 +1,6 @@
+obj\$(TARGET_DIRECTORY)\hard.res: \
+ $(BASEDIR)\public\sdk\inc\windows.h \
+ $(BASEDIR)\public\sdk\inc\common.ver \
+ $(BASEDIR)\public\sdk\inc\ntverp.h \
+ dialogs.h \
+ dialogs.dlg
diff --git a/private/utils/windisk/hard/sources b/private/utils/windisk/hard/sources
new file mode 100644
index 000000000..f6f71c4bb
--- /dev/null
+++ b/private/utils/windisk/hard/sources
@@ -0,0 +1,40 @@
+!include ..\windisk.mk
+
+MINORCOMP= dahard
+
+TARGETNAME= dahard
+TARGETPATH= obj
+TARGETTYPE= DYNLINK
+
+UMTYPE= windows
+UMRES= obj\*\hard.res
+
+TARGETLIBS=\
+ ..\util\obj\*\util.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+DLLDEF= obj\*\hard.def
+DLLENTRY= _DllMainCRTStartup
+DLLBASE= @$(BASEDIR)\public\sdk\lib\coffbase.txt,dahard
+
+INCLUDES=\
+ ..\inc; \
+ ..\util; \
+ $(INCLUDES)
+
+SOURCES=\
+ chard.cxx \
+ hard.cxx \
+ chardmnu.cxx \
+ hardmenu.cxx \
+ libinit.cxx \
+ hard.rc
+
+PRECOMPILED_CXX=1
+PRECOMPILED_INCLUDE=headers.hxx
+
+NTTARGETFILE1= obj\*\hard.res
diff --git a/private/utils/windisk/inc/dacommon.h b/private/utils/windisk/inc/dacommon.h
new file mode 100644
index 000000000..2769ec947
--- /dev/null
+++ b/private/utils/windisk/inc/dacommon.h
@@ -0,0 +1,80 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dacommon.h
+//
+// Contents: Miscellaneous macros for use by the Disk Administrator
+//
+// History: 9-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DACOMMON_H_
+#define _DACOMMON_H_
+
+//
+// Fix the warning levels
+
+#pragma warning(3:4092) // sizeof returns 'unsigned long'
+#pragma warning(3:4121) // structure is sensitive to alignment
+#pragma warning(3:4125) // decimal digit in octal sequence
+#pragma warning(3:4130) // logical operation on address of string constant
+#pragma warning(3:4132) // const object should be initialized
+#pragma warning(4:4200) // nonstandard zero-sized array extension
+#pragma warning(4:4206) // Source File is empty
+#pragma warning(3:4208) // delete[exp] - exp evaluated but ignored
+#pragma warning(3:4212) // function declaration used ellipsis
+#pragma warning(3:4220) // varargs matched remaining parameters
+#pragma warning(4:4509) // SEH used in function w/ _trycontext
+#pragma warning(error:4700) // Local used w/o being initialized
+
+#if DBG == 0
+// in the debug build, constant assertions (e.g., FDASSERT(1=2)) cause
+// unreachable code. Only display unreachable code warning in the retail case
+#pragma warning(3:4702) // Unreachable code
+#endif // DBG == 0
+
+#pragma warning(3:4706) // assignment w/i conditional expression
+#pragma warning(3:4709) // command operator w/o index expression
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// NOTE: ntsd is stupid about static global symbols, so don't have any
+// for debug builds
+//
+
+#if DBG == 1
+#define LOCAL
+#else // DBG == 1
+#define LOCAL static
+#endif // DBG == 1
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define ARRAYLEN(a) (sizeof(a)/sizeof((a)[0]))
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// Debugging flags
+//
+
+#define DEB_SEL DEB_USER1 // selection & focus information
+
+//
+// Debugging macros
+//
+
+#if DBG == 1 ////////////////////////////////////////////////////////
+ DECLARE_DEBUG(da)
+# define daDebugOut(x) daInlineDebugOut x
+# define daAssert(e) Win4Assert( e )
+#else // DBG == 1 ////////////////////////////////////////////////////////
+# define daDebugOut(x)
+# define daAssert(e)
+#endif // DBG == 1 ////////////////////////////////////////////////////////
+
+#endif // _DACOMMON_H_
diff --git a/private/utils/windisk/readme.txt b/private/utils/windisk/readme.txt
new file mode 100644
index 000000000..711ce2f70
--- /dev/null
+++ b/private/utils/windisk/readme.txt
@@ -0,0 +1,4 @@
+The source tree rooted here contains source to the Cairo Disk
+Administrator. To build this, you must:
+ be enlisted in the utils project, with at least utils\fmifs\inc
+ unghosted
diff --git a/private/utils/windisk/src/cdpage.cxx b/private/utils/windisk/src/cdpage.cxx
new file mode 100644
index 000000000..4c7a64202
--- /dev/null
+++ b/private/utils/windisk/src/cdpage.cxx
@@ -0,0 +1,348 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cdpage.cxx
+//
+// Contents: Implementation of CD-ROM property page in Disk
+// Administrator applet
+//
+// History: 3-Mar-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <controls.hxx>
+#include <util.hxx>
+
+#include "cdrom.hxx"
+#include "cdpage.hxx"
+#include "graph.hxx"
+#include "ops.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+RefreshCdPageData(
+ IN HWND hdlg
+ );
+
+VOID
+SetChangeableData(
+ IN HWND hdlg,
+ IN PCDROM_DESCRIPTOR cdrom
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_DLGPROC
+//
+// Synopsis: Property page dialog procedure
+//
+//--------------------------------------------------------------------------
+
+BOOL CALLBACK
+PAGE_DLGPROC(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ PAGE_CLASS* pPropPage;
+
+ if (msg == WM_INITDIALOG)
+ {
+ pPropPage = new PAGE_CLASS(hwnd);
+ SetWindowLong(hwnd, GWL_USERDATA, (LPARAM)pPropPage);
+ }
+ else
+ {
+ pPropPage = (PAGE_CLASS*) GetWindowLong(hwnd, GWL_USERDATA);
+ }
+
+ if (pPropPage != NULL)
+ {
+ return (pPropPage->_DlgProc(hwnd, msg, wParam, lParam));
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::_DlgProc, private
+//
+// Synopsis: Dialog Procedure for the CD-ROM property page
+//
+// Arguments: standard Windows DlgProc
+//
+// Returns: standard Windows DlgProc
+//
+// History: 28-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::_DlgProc(
+ HWND hdlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ return InitPage(hdlg, wParam, lParam);
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_Refresh:
+ //
+ // Note that this "Refresh" option refreshes everything for a
+ // single CD-ROM (the one we're looking at), but nothing else. In
+ // particular, it doesn't refresh volume data.
+ //
+ RefreshCdPageData(hdlg);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ NMHDR* phdr = (NMHDR*)lParam;
+
+ switch (phdr->code)
+ {
+ case PSN_SETACTIVE:
+ break;
+
+ case PSN_KILLACTIVE:
+ SetWindowLong(hdlg, DWL_MSGRESULT, FALSE); //ok to leave
+ break;
+
+ case PSN_QUERYCANCEL:
+ case PSN_RESET: // cancel
+ return FALSE;
+
+ case PSN_HELP:
+ NoHelp(hdlg);
+ return FALSE;
+
+ case PSN_APPLY:
+ SetWindowLong(hdlg, DWL_MSGRESULT, FALSE); // changes ok
+ return TRUE;
+
+ }
+
+ return FALSE;
+ }
+
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSTATIC:
+ {
+ HDC hdc = (HDC)wParam;
+ SetBkColor(hdc, GetSysColor(COLOR_3DFACE));
+ return (LRESULT)GetStockBrush(LTGRAY_BRUSH);
+ }
+
+ case WM_DESTROY:
+ DeleteFont(_hDlgFont);
+ SetWindowLong(hdlg, GWL_USERDATA, NULL);
+ delete this;
+ break;
+ }
+
+ return FALSE; // not processed
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::InitPage, private
+//
+// Synopsis: Initialize the data displayed on the CD-ROM property
+// page based on the current Disk Administrator selection
+//
+// Arguments: DlgProc stuff
+//
+// Returns: DlgProc stuff for WM_INITDIALOG
+//
+// History: 11-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::InitPage(
+ IN HWND hdlg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static UINT s_idTextControls[] =
+ {
+ IDC_DriveStatus,
+ IDC_FileSystem,
+ IDC_DriveLetter,
+ IDC_GENL_Label,
+
+ IDC_GENL_1,
+ IDC_GENL_2,
+ IDC_GENL_3,
+ IDC_GENL_4,
+
+ 0
+ };
+
+ _hDlgFont = KillBold(hdlg, s_idTextControls);
+
+ PCDROM_DESCRIPTOR cdrom;
+
+ ULONG i;
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+
+ if (cdrom->Selected)
+ {
+ break;
+ }
+ }
+ // if we get out, it better be because we found the right device
+
+ //
+ // Set data that doesn't depend on drive status
+ //
+
+ //
+ // Set the "drive letter" static control
+ //
+
+ WCHAR driveName[3];
+ driveName[0] = cdrom->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+ SetDlgItemText(hdlg, IDC_DriveLetter, driveName);
+
+ //
+ // Now set data that depends on drive status
+ //
+
+ SetChangeableData(hdlg, cdrom);
+
+ return TRUE; // didn't set focus to any control
+}
+
+
+VOID
+RefreshCdPageData(
+ IN HWND hdlg
+ )
+{
+ SetCursor(g_hCurWait);
+
+ PCDROM_DESCRIPTOR cdrom;
+
+ ULONG i;
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+
+ if (cdrom->Selected)
+ {
+ break; // this is it: only one CD-ROM can be selected
+ }
+ }
+ // if we get out, it better be because we found the right device
+
+ RefreshCdRomData(cdrom);
+ SetChangeableData(hdlg, cdrom);
+ RefreshBothViews(); // refresh the main view as well
+
+ SetCursor(g_hCurNormal);
+}
+
+
+VOID
+SetChangeableData(
+ IN HWND hdlg,
+ IN PCDROM_DESCRIPTOR cdrom
+ )
+{
+ WCHAR buffer[100];
+ HBITMAP hBigBitmap;
+
+ if (0 != lstrcmp(cdrom->TypeName, wszUnknown))
+ {
+ //
+ // Set drive status
+ //
+
+ //BUGBUG: status is always "ready"
+ LoadString(g_hInstance, IDS_READY, buffer, ARRAYLEN(buffer));
+ SetDlgItemText(hdlg, IDC_DriveStatus, buffer);
+
+ //
+ // Set drive label.
+ //
+
+ SetDlgItemText(hdlg, IDC_GENL_Label, cdrom->VolumeLabel);
+
+ //
+ // Set file system type
+ //
+
+ SetDlgItemText(hdlg, IDC_FileSystem, cdrom->TypeName);
+
+ hBigBitmap = CreateGraphBitmap(
+ g_hInstance,
+ GetDlgItem(hdlg, IDC_Graph),
+ DRIVE_CDROM,
+ STATUS_OK,
+ 1000); // assume full
+ }
+ else
+ {
+ LoadString(g_hInstance, IDS_NOTREADY, buffer, ARRAYLEN(buffer));
+ SetDlgItemText(hdlg, IDC_DriveStatus, buffer);
+
+ buffer[0] = L'\0';
+
+ SetDlgItemText(hdlg, IDC_GENL_Label, buffer);
+ SetDlgItemText(hdlg, IDC_FileSystem, buffer);
+
+ hBigBitmap = CreateGraphBitmap(
+ g_hInstance,
+ GetDlgItem(hdlg, IDC_Graph),
+ DRIVE_CDROM,
+ STATUS_OK, //BUGBUG
+ 1000); // assume full
+ }
+
+ //
+ // Set the graph
+ //
+
+ SendDlgItemMessage(
+ hdlg,
+ IDC_Graph,
+ BMPCTL_SETBITMAP,
+ (WPARAM)hBigBitmap,
+ 0);
+}
diff --git a/private/utils/windisk/src/cdpage.hxx b/private/utils/windisk/src/cdpage.hxx
new file mode 100644
index 000000000..5091d59b2
--- /dev/null
+++ b/private/utils/windisk/src/cdpage.hxx
@@ -0,0 +1,76 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cdpage.hxx
+//
+// Contents: CD-ROM property page of volumes in
+// Disk Administrator applet
+//
+// History: 28-Jul-93 BruceFo Created from WilliamW's sharing applet
+//
+//--------------------------------------------------------------------------
+
+#ifndef __CDPAGE_HXX__
+#define __CDPAGE_HXX__
+
+#include "resids.h"
+#include "dialogs.h"
+
+#undef PAGE_DLGPROC
+#undef PAGE_CLASS
+
+#define PAGE_DLGPROC CdRomPageDlgProc
+#define PAGE_CLASS CCdRomPage
+
+class PAGE_CLASS
+{
+public:
+
+ PAGE_CLASS(
+ IN HWND hwndPage
+ )
+ :
+ _hwndPage(hwndPage),
+ _hDlgFont(NULL)
+ {
+ }
+
+ ~PAGE_CLASS()
+ {
+ }
+
+ BOOL
+ _DlgProc(
+ IN HWND hWnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+private:
+
+ friend BOOL CALLBACK
+ PAGE_DLGPROC(
+ HWND hWnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+ BOOL
+ InitPage(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+ //
+ // Data
+ //
+
+ HFONT _hDlgFont;
+ HWND _hwndPage;
+};
+
+#endif // __CDPAGE_HXX__
diff --git a/private/utils/windisk/src/cdr.bmp b/private/utils/windisk/src/cdr.bmp
new file mode 100644
index 000000000..006c498f4
--- /dev/null
+++ b/private/utils/windisk/src/cdr.bmp
Binary files differ
diff --git a/private/utils/windisk/src/cdrom.cxx b/private/utils/windisk/src/cdrom.cxx
new file mode 100644
index 000000000..16421588f
--- /dev/null
+++ b/private/utils/windisk/src/cdrom.cxx
@@ -0,0 +1,955 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cdrom.cxx
+//
+// Contents: This module contains the set of routines that display and
+// control the drive letters for CdRom devices.
+//
+// History: 9-Dec-93 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "dialogs.h"
+#include "drives.hxx"
+#include "help.hxx"
+#include "nt.hxx"
+#include "ntlow.hxx"
+
+
+WCHAR g_SourcePathLetter = L'\0';
+WCHAR g_SourcePathKeyName[80];
+WCHAR g_SourcePathValueName[30];
+
+
+PCDROM_DESCRIPTOR
+CdRomFindSelectedDevice(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Find the selected CD-ROM. There should only be one.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to the correct structure, or NULL if it doesn't exist
+
+--*/
+
+{
+ FDASSERT(1 == CdRomSelectionCount);
+
+ ULONG i;
+
+ for (i = 0; i < CdRomCount; i++)
+ {
+ if (CdRomArray[i].Selected)
+ {
+ return &CdRomArray[i];
+ }
+ }
+
+ FDASSERT(FALSE);
+ return NULL;
+}
+
+
+
+
+PCDROM_DESCRIPTOR
+CdRomFindDevice(
+ IN ULONG CdRomNumber
+ )
+
+/*++
+
+Routine Description:
+
+ Find the correct CD-ROM
+
+Arguments:
+
+ CdRomNumber - the device number
+
+Return Value:
+
+ Pointer to the correct structure, or NULL if it doesn't exist
+
+--*/
+
+{
+ FDASSERT(0 <= CdRomNumber && CdRomNumber < CdRomCount);
+ return &CdRomArray[CdRomNumber];
+}
+
+
+
+ULONG
+CdRomFindDeviceNumber(
+ IN WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Find the correct CD-ROM
+
+Arguments:
+
+ CdRomNumber - the device number
+
+Return Value:
+
+ Pointer to the correct structure, or NULL if it doesn't exist
+
+--*/
+
+{
+ FDASSERT(DriveLetter >= L'C' && DriveLetter <= L'Z');
+ ULONG i;
+
+ for (i = 0; i < CdRomCount; i++)
+ {
+ if (CdRomArray[i].DriveLetter == DriveLetter)
+ {
+ return i;
+ }
+ }
+
+ FDASSERT(FALSE);
+ return 0xffffffff;
+}
+
+
+PCDROM_DESCRIPTOR
+CdRomFindDriveLetter(
+ IN WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Find the CD-ROM with the drive letter
+
+Arguments:
+
+ DriveLetter - the drive letter to find
+
+Return Value:
+
+ Pointer to the correct structure, or NULL if it doesn't exist
+
+--*/
+
+{
+ FDASSERT(DriveLetter >= L'C' && DriveLetter <= L'Z');
+ ULONG i;
+
+ for (i = 0; i < CdRomCount; i++)
+ {
+ if (CdRomArray[i].DriveLetter == DriveLetter)
+ {
+ return &CdRomArray[i];
+ }
+ }
+
+ FDASSERT(FALSE);
+ return NULL;
+}
+
+
+
+
+BOOL
+CdRomUsingDriveLetter(
+ IN WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Determine if a CD-ROM device is using the drive letter
+
+Arguments:
+
+ DriveLetter - the drive letter to find
+
+Return Value:
+
+ TRUE if one is using the letter
+
+--*/
+
+{
+ FDASSERT(DriveLetter >= L'C' && DriveLetter <= L'Z');
+ ULONG i;
+
+ for (i = 0; i < CdRomCount; i++)
+ {
+ if (CdRomArray[i].DriveLetter == DriveLetter)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+VOID
+CdRomChangeDriveLetter(
+ IN PCDROM_DESCRIPTOR Cdrom,
+ IN WCHAR NewDriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Change a CD-ROM drive letter
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ DWORD action;
+ WCHAR deviceName[40];
+ WCHAR driveName[10];
+ OBJECT_ATTRIBUTES oa;
+ HANDLE handle;
+ NTSTATUS status;
+ IO_STATUS_BLOCK statusBlock;
+ UNICODE_STRING unicodeName;
+ UINT errorMode;
+
+ action = ConfirmationDialog(
+ MSG_DRIVE_RENAME_WARNING,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
+
+ if (action == IDNO)
+ {
+ return;
+ }
+
+ // Attempt to open and lock the cdrom.
+
+ wsprintf(deviceName, TEXT("\\Device\\CdRom%d"), Cdrom->DeviceNumber);
+
+ RtlInitUnicodeString(&unicodeName, deviceName);
+
+ memset(&oa, 0, sizeof(OBJECT_ATTRIBUTES));
+ oa.Length = sizeof(OBJECT_ATTRIBUTES);
+ oa.ObjectName = &unicodeName;
+ oa.Attributes = OBJ_CASE_INSENSITIVE;
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ status = NtOpenFile(&handle,
+ SYNCHRONIZE | FILE_READ_DATA,
+ &oa,
+ &statusBlock,
+ FILE_SHARE_READ,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ SetErrorMode(errorMode);
+
+ if (!NT_SUCCESS(status))
+ {
+ ErrorDialog(MSG_CANNOT_LOCK_CDROM);
+ return;
+ }
+
+ // Lock the drive to insure that no other access is occurring
+ // to the volume. This is done via the "Low" routine for
+ // convenience
+
+ status = LowLockDrive(handle);
+
+ if (!NT_SUCCESS(status))
+ {
+ LowCloseDisk(handle);
+ ErrorDialog(MSG_CANNOT_LOCK_CDROM);
+ return;
+ }
+
+ // Before attempting to move the name, see if the letter
+ // is currently in use - could be a new network connection
+ // or a partition that is scheduled for deletion.
+
+ DWORD ec;
+ WCHAR dosName[MAX_PATH];
+ PWSTR linkTarget;
+
+ //
+ // No need to look if anyone is using the no-drive letter.
+ //
+
+ if (NewDriveLetter != NO_DRIVE_LETTER_EVER) {
+
+ wsprintfW(dosName, L"\\DosDevices\\%wc:", NewDriveLetter);
+ ec = GetDriveLetterLinkTarget(dosName, &linkTarget);
+ if (ec == NO_ERROR)
+ {
+ // Something is using this letter.
+
+ LowCloseDisk(handle);
+ ErrorDialog(MSG_CANNOT_MOVE_CDROM);
+ return;
+ }
+
+ }
+
+ //
+ // If it didn't used to have a letter, no point in trying
+ // to remove it.
+ //
+
+ if (Cdrom->DriveLetter != NO_DRIVE_LETTER_EVER) {
+
+ wsprintf(driveName, TEXT("%c:"), Cdrom->DriveLetter);
+ if (!DefineDosDevice(DDD_REMOVE_DEFINITION, driveName, NULL))
+ {
+ LowCloseDisk(handle);
+ ErrorDialog(MSG_CDROM_LETTER_ERROR);
+ return;
+ }
+
+ }
+
+ status = DiskRegistryAssignCdRomLetter(
+ Cdrom->DeviceName,
+ NewDriveLetter);
+
+ if (Cdrom->DriveLetter != NO_DRIVE_LETTER_EVER) {
+
+ MarkDriveLetterFree(Cdrom->DriveLetter);
+
+ // See if this was the device used to install NT
+
+ if (L'\0' != g_SourcePathLetter)
+ {
+ if (g_SourcePathLetter == Cdrom->DriveLetter)
+ {
+ LONG error;
+ HKEY keyHandle;
+ DWORD valueType;
+ ULONG size;
+ PWSTR string;
+
+ // Update the source path
+
+ error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ g_SourcePathKeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &keyHandle);
+ if (error == NO_ERROR)
+ {
+ error = RegQueryValueEx(keyHandle,
+ g_SourcePathValueName,
+ NULL,
+ &valueType,
+ NULL,
+ &size);
+ if (error == NO_ERROR)
+ {
+ string = (PWSTR) LocalAlloc(LMEM_FIXED, size);
+ if (NULL != string)
+ {
+ error = RegQueryValueEx(keyHandle,
+ g_SourcePathValueName,
+ NULL,
+ &valueType,
+ (LPBYTE)string,
+ &size);
+ if (error == NO_ERROR)
+ {
+ *string = g_SourcePathLetter = NewDriveLetter;
+ RegSetValueEx(keyHandle,
+ g_SourcePathValueName,
+ 0,
+ REG_SZ,
+ (LPBYTE)string,
+ size);
+ }
+ }
+ LocalFree(string);
+ }
+ RegCloseKey(keyHandle);
+ }
+ }
+ }
+ }
+
+ // set up new device letter - name is already set up, take care not to
+ // assign the no drive letter.
+
+ if (NewDriveLetter != NO_DRIVE_LETTER_EVER) {
+
+ wsprintf(driveName, TEXT("%c:"), NewDriveLetter);
+ if (DefineDosDevice(DDD_RAW_TARGET_PATH, driveName, deviceName))
+ {
+ Cdrom->DriveLetter = NewDriveLetter;
+ MarkDriveLetterUsed(Cdrom->DriveLetter);
+ }
+ else
+ {
+ RegistryChanged = TRUE;
+ }
+ } else {
+
+ Cdrom->DriveLetter = NO_DRIVE_LETTER_EVER;
+
+ }
+ LowCloseDisk(handle);
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeCdRomInfo
+//
+// Synopsis: Initialize all information about CD-ROMs
+//
+// Arguments: (none)
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 2-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+InitializeCdRomInfo(
+ VOID
+ )
+{
+ WCHAR driveLetter;
+ PWSTR linkTarget;
+ WCHAR dosDevicesName[sizeof(L"\\DosDevices\\A:")];
+ DWORD ec;
+ ULONG count;
+ PCDROM_DESCRIPTOR cdrom;
+ LONG error;
+ DWORD valueType;
+ HKEY keyHandle;
+ ULONG size;
+ PWSTR string;
+
+ //
+ // Get the CD-ROM source path
+ //
+
+ LoadString(g_hInstance,
+ IDS_SOURCE_PATH,
+ g_SourcePathKeyName,
+ ARRAYLEN(g_SourcePathKeyName));
+ LoadString(g_hInstance,
+ IDS_SOURCE_PATH_NAME,
+ g_SourcePathValueName,
+ ARRAYLEN(g_SourcePathValueName));
+
+ error = RegOpenKey(HKEY_LOCAL_MACHINE, g_SourcePathKeyName, &keyHandle);
+ if (error == NO_ERROR)
+ {
+ error = RegQueryValueEx(keyHandle,
+ g_SourcePathValueName,
+ NULL,
+ &valueType,
+ NULL,
+ &size);
+ if (error == NO_ERROR)
+ {
+ string = (PWSTR) LocalAlloc(LMEM_FIXED, size);
+ if (NULL != string)
+ {
+ error = RegQueryValueEx(keyHandle,
+ g_SourcePathValueName,
+ NULL,
+ &valueType,
+ (LPBYTE)string,
+ &size);
+ if (error == NO_ERROR)
+ {
+ g_SourcePathLetter = *string;
+ }
+ }
+ LocalFree(string);
+ }
+ RegCloseKey(keyHandle);
+ }
+
+ //
+ // First, count how many CD-ROM devices there are
+ //
+
+ wsprintf(dosDevicesName, L"\\DosDevices\\A:");
+
+ CdRomCount = 0;
+
+ {
+
+ NTSTATUS ntStatus;
+ SYSTEM_DEVICE_INFORMATION deviceInformationData;
+
+ ntStatus = NtQuerySystemInformation(
+ SystemDeviceInformation,
+ &deviceInformationData,
+ sizeof(SYSTEM_DEVICE_INFORMATION),
+ NULL
+ );
+
+ if (NT_SUCCESS(ntStatus)) {
+
+ CdRomCount = deviceInformationData.NumberOfCdRoms;
+
+ }
+
+ }
+
+ if (0 == CdRomCount)
+ {
+ return TRUE;
+ }
+
+ g_AllowCdRom = TRUE;
+
+ //
+ // First we find all the cd rom devices that have an actual drive
+ // letter. Afterwards, we will look for those that have have
+ // no letter.
+ //
+
+ CdRomArray = (PCDROM_DESCRIPTOR)Malloc(CdRomCount * sizeof(CDROM_DESCRIPTOR));
+
+ count = 0;
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ dosDevicesName[12] = driveLetter;
+
+ if ((ec = GetDriveLetterLinkTarget(dosDevicesName, &linkTarget)) == NO_ERROR)
+ {
+ if (_wcsnicmp(linkTarget, L"\\Device\\CdRom", 13) == 0)
+ {
+ cdrom = &CdRomArray[count];
+
+ cdrom->DeviceName = (PWSTR)Malloc((lstrlen(linkTarget)+1) * sizeof(WCHAR));
+ lstrcpy(cdrom->DeviceName, linkTarget);
+
+ //
+ // Get the device number
+ //
+
+ PWCHAR cp;
+
+ cp = cdrom->DeviceName;
+ while (*cp)
+ {
+ if (iswdigit(*cp))
+ {
+ break;
+ }
+ cp++;
+ }
+
+ if (*cp)
+ {
+ cdrom->DeviceNumber = wcstoul(cp, NULL, 10);
+ }
+ else
+ {
+ // error: no device number! Don't add this one
+ Free(cdrom->DeviceName);
+ --CdRomCount;
+ continue;
+ }
+
+ cdrom->hDCMem = NULL;
+ cdrom->hbmMem = NULL;
+ cdrom->Selected = FALSE;
+ cdrom->LeftRight.Left = 0;
+ cdrom->LeftRight.Right = 0;
+ cdrom->DriveLetter = driveLetter;
+
+ cdrom->VolumeLabel = NULL;
+ cdrom->TypeName = NULL;
+
+ RefreshCdRomData(cdrom);
+
+ ++count;
+ }
+ }
+ }
+
+ //
+ // if the count is equal to the number of cdroms in the system
+ // then the're aren't any without a drive letter.
+ //
+ // Keep going until we found all of the Cdroms.
+ //
+
+ DWORD potentialDeviceNumber;
+ WCHAR ntDeviceName[MAX_PATH];
+ UNICODE_STRING ntDeviceNameString;
+
+
+ potentialDeviceNumber = 0;
+ for (
+ potentialDeviceNumber = 0;
+ count != CdRomCount;
+ potentialDeviceNumber++
+ ) {
+
+ DWORD i;
+ HANDLE ntDeviceHandle;
+ OBJECT_ATTRIBUTES deviceObjectAttributes;
+ NTSTATUS openStatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ //
+ // BUG BUG This is very piggish. Look to see if the potential
+ // cdrom device "number" is already in the list of devices we
+ // know about. If it is, go on to the next one.
+ //
+ //
+
+ for (
+ i = 0;
+ i < count;
+ i++
+ ) {
+
+ if (potentialDeviceNumber == CdRomArray[i].DeviceNumber) {
+
+ goto bottomOfPotential;
+
+ }
+
+ }
+
+ //
+ // Form a name based on the number
+ //
+
+ wsprintf(ntDeviceName,L"\\Device\\CdRom%d",potentialDeviceNumber);
+ RtlInitUnicodeString(
+ &ntDeviceNameString,
+ &ntDeviceName[0]
+ );
+
+ InitializeObjectAttributes(
+ &deviceObjectAttributes,
+ &ntDeviceNameString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ //
+ // See if it's there.
+ //
+
+ openStatus = NtOpenFile(
+ &ntDeviceHandle,
+ (ACCESS_MASK)SYNCHRONIZE,
+ &deviceObjectAttributes,
+ &ioStatusBlock,
+ FILE_SHARE_READ,
+ 0UL
+ );
+ if ( !NT_SUCCESS(openStatus) ) {
+
+ continue;
+
+ }
+
+ //
+ // We have the device open. Close it right away. Fill
+ // in the cd rom structure. The refresh cdrom code will
+ // know how do deal with a cdrom with no drive letter.
+ // size
+ //
+
+ NtClose(ntDeviceHandle);
+
+ cdrom = &CdRomArray[count];
+
+ cdrom->DeviceName = (PWSTR)Malloc((ntDeviceNameString.Length+1) * sizeof(WCHAR));
+ lstrcpy(cdrom->DeviceName, ntDeviceNameString.Buffer);
+
+ cdrom->DeviceNumber = potentialDeviceNumber;
+ cdrom->hDCMem = NULL;
+ cdrom->hbmMem = NULL;
+ cdrom->Selected = FALSE;
+ cdrom->LeftRight.Left = 0;
+ cdrom->LeftRight.Right = 0;
+ cdrom->DriveLetter = NO_DRIVE_LETTER_EVER;
+
+ cdrom->VolumeLabel = NULL;
+ cdrom->TypeName = NULL;
+
+ RefreshCdRomData(cdrom);
+
+ ++count;
+
+bottomOfPotential:;
+
+ }
+
+
+ return TRUE;
+}
+
+
+VOID
+RefreshCdRomData(
+ PCDROM_DESCRIPTOR Cdrom
+ )
+{
+ WCHAR rootPath[4];
+ rootPath[0] = Cdrom->DriveLetter;
+ rootPath[1] = L':';
+ rootPath[2] = L'\\';
+ rootPath[3] = L'\0';
+
+ WCHAR volumeLabel[100];
+ WCHAR typeName[100];
+
+ // Free old stuff first
+
+ if (NULL != Cdrom->VolumeLabel)
+ {
+ Free(Cdrom->VolumeLabel);
+ }
+
+ if (NULL != Cdrom->TypeName)
+ {
+ Free(Cdrom->TypeName);
+ }
+
+ Cdrom->TotalSpaceInMB = 0;
+ Cdrom->TypeName = NULL;
+ Cdrom->VolumeLabel = NULL;
+
+ UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ HANDLE ntDeviceHandle;
+ OBJECT_ATTRIBUTES deviceObjectAttributes;
+ UNICODE_STRING ntDeviceNameString;
+ NTSTATUS ioStatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+ FILE_FS_SIZE_INFORMATION sizeInformation;
+ PFILE_FS_ATTRIBUTE_INFORMATION attributeInformation;
+ PFILE_FS_VOLUME_INFORMATION volumeInformation;
+ DWORD volumeInformationLength;
+ DWORD attributeInformationLength;
+
+
+ //
+ // Allocate two strings. The first to hold the file system name. The
+ // second to hold the volume name. After we get them both back we will
+ // allocate new memory just big enough to hold them.
+ //
+
+ attributeInformationLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
+ ((MAX_PATH+1)*sizeof(WCHAR));
+ volumeInformationLength = sizeof(FILE_FS_VOLUME_INFORMATION) +
+ ((MAX_PATH+1)*sizeof(WCHAR));
+
+ attributeInformation = (PFILE_FS_ATTRIBUTE_INFORMATION)Malloc(attributeInformationLength);
+
+ if (!attributeInformation) {
+
+ SetErrorMode(errorMode);
+ return;
+
+ }
+
+ volumeInformation = (PFILE_FS_VOLUME_INFORMATION)Malloc(volumeInformationLength);
+
+ if (!volumeInformation) {
+
+ Free(attributeInformation);
+ SetErrorMode(errorMode);
+ return;
+
+ }
+
+
+ RtlInitUnicodeString(
+ &ntDeviceNameString,
+ Cdrom->DeviceName
+ );
+
+ InitializeObjectAttributes(
+ &deviceObjectAttributes,
+ &ntDeviceNameString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ //
+ // Open the file
+ //
+
+ ioStatus = NtOpenFile(
+ &ntDeviceHandle,
+ (ACCESS_MASK)FILE_LIST_DIRECTORY | SYNCHRONIZE,
+ &deviceObjectAttributes,
+ &ioStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE
+ );
+
+ if ( !NT_SUCCESS(ioStatus) ) {
+
+ Free(attributeInformation);
+ Free(volumeInformation);
+ SetErrorMode(errorMode);
+ return;
+
+ }
+
+ //
+ // Try to get the volume label
+ //
+
+ ioStatus = NtQueryVolumeInformationFile(
+ ntDeviceHandle,
+ &ioStatusBlock,
+ volumeInformation,
+ volumeInformationLength,
+ FileFsVolumeInformation
+ );
+
+ if (NT_SUCCESS(ioStatus)) {
+
+
+ Cdrom->VolumeLabel = (PWCHAR)Malloc(volumeInformation->VolumeLabelLength
+ + sizeof(WCHAR));
+ if (Cdrom->VolumeLabel) {
+
+ RtlZeroMemory(
+ Cdrom->VolumeLabel,
+ volumeInformation->VolumeLabelLength+sizeof(WCHAR)
+ );
+ RtlMoveMemory(
+ Cdrom->VolumeLabel,
+ volumeInformation->VolumeLabel,
+ volumeInformation->VolumeLabelLength
+ );
+
+
+ }
+
+ }
+
+ Free(volumeInformation);
+
+ ioStatus = NtQueryVolumeInformationFile(
+ ntDeviceHandle,
+ &ioStatusBlock,
+ attributeInformation,
+ attributeInformationLength,
+ FileFsAttributeInformation
+ );
+
+ if (NT_SUCCESS(ioStatus)) {
+
+ Cdrom->TypeName = (PWCHAR)Malloc(attributeInformation->FileSystemNameLength
+ + sizeof(WCHAR));
+
+ if (Cdrom->TypeName) {
+
+ RtlZeroMemory(
+ Cdrom->TypeName,
+ attributeInformation->FileSystemNameLength+
+ sizeof(WCHAR)
+ );
+ RtlMoveMemory(
+ Cdrom->TypeName,
+ attributeInformation->FileSystemName,
+ attributeInformation->FileSystemNameLength
+ );
+
+ }
+
+ }
+
+ Free(attributeInformation);
+
+ //
+ // Determine the size parameters of the volume.
+ //
+
+ ioStatus = NtQueryVolumeInformationFile(
+ ntDeviceHandle,
+ &ioStatusBlock,
+ &sizeInformation,
+ sizeof(sizeInformation),
+ FileFsSizeInformation
+ );
+ NtClose(ntDeviceHandle);
+ SetErrorMode(errorMode);
+ if ( !NT_SUCCESS(ioStatus) ) {
+
+ Cdrom->TotalSpaceInMB = 0;
+
+ } else {
+
+ LONGLONG temp;
+
+ if (sizeInformation.TotalAllocationUnits.HighPart) {
+ sizeInformation.TotalAllocationUnits.LowPart = (ULONG)-1;
+ }
+ temp = UInt32x32To64(
+ sizeInformation.TotalAllocationUnits.LowPart,
+ sizeInformation.SectorsPerAllocationUnit
+ );
+
+ temp *= sizeInformation.BytesPerSector;
+ temp /= (1024*1024);
+ Cdrom->TotalSpaceInMB = (ULONG)temp;
+
+ }
+}
+
+
+VOID
+RefreshAllCdRomData(
+ VOID
+ )
+{
+ PCDROM_DESCRIPTOR cdrom;
+ ULONG i;
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+ RefreshCdRomData(cdrom);
+ }
+}
diff --git a/private/utils/windisk/src/cdrom.hxx b/private/utils/windisk/src/cdrom.hxx
new file mode 100644
index 000000000..3065416c4
--- /dev/null
+++ b/private/utils/windisk/src/cdrom.hxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cdrom.hxx
+//
+// Contents: Declarations for CD-ROM support
+//
+// History: 9-Dec-93 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CDROM_HXX__
+#define __CDROM_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+PCDROM_DESCRIPTOR
+CdRomFindSelectedDevice(
+ VOID
+ );
+
+PCDROM_DESCRIPTOR
+CdRomFindDevice(
+ IN ULONG CdRomNumber
+ );
+
+ULONG
+CdRomFindDeviceNumber(
+ IN WCHAR DriveLetter
+ );
+
+PCDROM_DESCRIPTOR
+CdRomFindDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+BOOL
+CdRomUsingDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+VOID
+CdRomChangeDriveLetter(
+ IN PCDROM_DESCRIPTOR Cdrom,
+ IN WCHAR NewDriveLetter
+ );
+
+BOOL
+InitializeCdRomInfo(
+ VOID
+ );
+
+VOID
+RefreshCdRomData(
+ PCDROM_DESCRIPTOR Cdrom
+ );
+
+VOID
+RefreshAllCdRomData(
+ VOID
+ );
+
+#endif // __CDROM_HXX__
diff --git a/private/utils/windisk/src/chkdsk.cxx b/private/utils/windisk/src/chkdsk.cxx
new file mode 100644
index 000000000..897acd4bd
--- /dev/null
+++ b/private/utils/windisk/src/chkdsk.cxx
@@ -0,0 +1,2050 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: chkdsk.cxx
+//
+// Contents: Disk Administrator file system extension class. Chkdsk.
+//
+// History: 2-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <util.hxx>
+
+#include "resids.h"
+#include "dialogs.h"
+#include "fs.hxx"
+#include "print.hxx"
+#include "fmifs.hxx"
+#include "chkdsk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define CHK_PROGRESSUPDATE (WM_USER + 0)
+#define CHK_PROGRESSEND (WM_USER + 1)
+#define CHK_PROGRESSCANCEL (WM_USER + 2)
+#define CHK_PROGRESSUNCANCEL (WM_USER + 3)
+#define CHK_PROGRESSTITLE (WM_USER + 4)
+
+#define MIN_TIME_DELTA 100
+
+#define MESSAGE_CHUNK 512
+
+#define MAX_PATH 260
+#define MAX_FILTER 100
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Fix:
+// if IDC_CHKDSK_DontFix, then no flags
+// if IDC_CHKDSK_Fix, then /F
+// if IDC_CHKDSK_FixAll, then /R
+
+#define CHKDSK_SLASH_F(x) ( ((x)==IDC_CHKDSK_Fix) || ((x)==IDC_CHKDSK_FixAll) )
+#define CHKDSK_SLASH_R(x) ((x) == IDC_CHKDSK_FixAll)
+
+typedef struct _CHKDSK_PARAMS
+{
+ //
+ // 'hWorkerThread' is the thread handle of the worker thread. This is used
+ // for synchronization: we wait on it when waiting for it to exit.
+ //
+
+ HANDLE hWorkerThread;
+
+ //
+ // 'AllowCancel' is set by the chkdsk invoker to indicate whether
+ // cancelling the operation is allowed.
+ //
+
+ BOOL AllowCancel;
+
+ //
+ // 'Cancel' is set by the UI thread to indicate the user has chosen
+ // to cancel the operation.
+ //
+
+ BOOL Cancel;
+
+ //
+ // 'Cancelled' is set by the worker thread to indicate a cancel
+ // is in progress, and to ignore all future callback messages.
+ //
+
+ BOOL Cancelled;
+
+ //
+ // 'Final' is set by the worker thread to indicate the a "final"
+ // message has been received. "Final" messages are displayed in a
+ // message box. All other messages are discarded.
+ //
+
+ BOOL Final;
+
+ //
+ // Window handles set by UI thread and used by both UI and chkdsk
+ // threads. The chkdsk thread uses hDlg to send messages; thus the
+ // Windows message queue is used as an IPC mechanism.
+ //
+
+ HWND hwndParent;
+ HWND hDlg; // handle to progress dialog
+
+ //
+ // Volume info used by the Chkdsk dialog box
+ //
+
+ WCHAR Label[MAXLABELLEN];
+
+ //
+ // IN parameters set by the UI thread for use by the chkdsk routine
+ //
+
+ BOOL noPercentDone; // TRUE if the file system doesn't support %done
+ FILE_SYSTEM FileSys;
+ PWSTR FileSystem;
+ PWSTR DriveName;
+
+ //
+ // OUT parameters set by the chkdsk callback routine
+ //
+
+ BOOL fmifsSuccess;
+ UINT Fix;
+ UINT Result;
+
+ PSTR Messages; // all the messages concatenated
+ UINT NumMessageChunks; // # of MESSAGE_CHUNKs allocated
+ UINT NumCharacters; // # characters in the buffer
+
+ //
+ // Parameters specific to a file system, set prior to calling
+ // chkdsk, and used by the callback routine
+ //
+
+ //
+ // The last time a %done message was seen. If < 1/10 second, then
+ // we ignore it (unless it is 0% or 100%). This avoids overloading
+ // the %done thermometer.
+ //
+
+ DWORD lasttime;
+
+} CHKDSK_PARAMS, *PCHKDSK_PARAMS;
+
+//////////////////////////////////////////////////////////////////////////////
+
+LOCAL PCHKDSK_PARAMS ParamsForChkdskCallBack;
+
+LOCAL WCHAR szMessageWindowClass[] = TEXT("MessageWindow");
+
+//////////////////////////////////////////////////////////////////////////////
+
+DWORD
+GetTime(
+ VOID
+ );
+
+BOOL CALLBACK
+StopChkDlgProc(
+ IN HWND hDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+UINT
+GetFileFilterString(
+ OUT PWSTR szFilter,
+ IN INT cchFilter
+ );
+
+BOOL
+GetSaveName(
+ IN HWND hwndOwner,
+ OUT PWSTR pszFile,
+ IN UINT nMaxFile
+ );
+
+VOID
+SaveResults(
+ IN HWND hwndOwner,
+ IN PCHKDSK_PARAMS chkdskParams
+ );
+
+VOID
+PrintResults(
+ IN HWND hwndOwner,
+ IN PCHKDSK_PARAMS chkdskParams
+ );
+
+LOCAL LRESULT CALLBACK
+MessageWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+VOID
+OnFinalMessage(
+ IN HWND hwndOwner,
+ IN PSTR Message
+ );
+
+LOCAL BOOLEAN
+ChkdskCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ );
+
+LOCAL DWORD WINAPI
+ChkdskVolume(
+ IN LPVOID ThreadParameter
+ );
+
+VOID
+SetChkdskProgressTitle(
+ IN HWND hDlg,
+ IN PCHKDSK_PARAMS chkdskParams
+ );
+
+LOCAL BOOL CALLBACK
+ChkdskProgressDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+int
+FindCheckedRadioButton(
+ HWND hDlg,
+ int wIdFirst,
+ int wIdLast
+ );
+
+LOCAL BOOL CALLBACK
+ChkdskDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetTime
+//
+// Synopsis: Returns a time value in milliseconds that wraps
+// approximately every minute.
+//
+// Arguments: none
+//
+// Returns: an integer time that increases every millisecond
+//
+// History: 10-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+GetTime(
+ VOID
+ )
+{
+ SYSTEMTIME st;
+
+ GetSystemTime(&st);
+ return MIN_TIME_DELTA + (st.wSecond * 1000) + st.wMilliseconds;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StopChkDlgProc, private
+//
+// Synopsis: Dialog procedure for the modal "Stop Formatting" dialog
+//
+// Arguments: standard Windows dialog procedure
+//
+// Returns: standard Windows dialog procedure
+//
+// History: 7-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL CALLBACK
+StopChkDlgProc(
+ IN HWND hDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ UNREFERENCED_PARM(lParam);
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ //
+ // Set the text
+ //
+
+ TCHAR text[300];
+
+ RetrieveAndFormatMessage(
+ MSG_CHK_CANCELMESSAGE,
+ text,
+ ARRAYLEN(text),
+ NULL
+ );
+
+ SetDlgItemText(hDlg, IDC_StopChk_Text, text);
+
+ SetFocus(GetDlgItem(hDlg, IDC_StopChk_Continue));
+
+ return 0; // called SetFocus
+ }
+
+ case WM_COMMAND:
+
+ switch (GET_WM_COMMAND_ID(wParam, lParam))
+ {
+ case IDC_StopChk_Stop:
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case IDC_StopChk_Continue:
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDHELP:
+ Unimplemented(hDlg);
+ break;
+ }
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// Code for the thread handling the error message window
+//
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegisterMessageWindowClass
+//
+// Synopsis: Registers the window classes used by menu feedback code
+//
+// Arguments: (none)
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+RegisterMessageWindowClass(
+ VOID
+ )
+{
+ WNDCLASS wc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = MessageWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = DLGWINDOWEXTRA;
+ wc.hInstance = g_hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL,IDC_ARROW);
+ wc.hbrBackground = GetStockBrush(LTGRAY_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szMessageWindowClass;
+
+ return (0 != RegisterClass(&wc));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetFileFilterString
+//
+// Synopsis: Gets the filter string to use with the common save
+// dialog from the resource file, and massages it into the
+// correct form.
+//
+// Arguments: [szFilter] -- where the string is put
+// [cchFilter] -- number of characters in the buffer.
+//
+// Returns: size of loaded string, or 0 on failure
+//
+// History: 8-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+UINT
+GetFileFilterString(
+ OUT PWSTR szFilter,
+ IN INT cchFilter
+ )
+{
+ UINT i, cchString;
+ WCHAR wcReplace;
+
+ if (0 == (cchString =
+ LoadString(g_hInstance, IDS_CHK_FILTERSTRING, szFilter, cchFilter)))
+ {
+ return 0;
+ }
+
+ wcReplace = szFilter[cchString - 1];
+ for (i=0; szFilter[i] != TEXT('\0'); i++)
+ {
+ if (szFilter[i] == wcReplace)
+ {
+ szFilter[i] = TEXT('\0');
+ }
+ }
+ return cchString;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetSaveName
+//
+// Synopsis: Calls the common "Save As" dialog to get a filename for
+// the log file.
+//
+// Arguments: [hwndOwner] -- handle to parent window
+// [pszFile] -- the filename that is retrieved
+// [nMaxFile] -- maximum size of file name
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 8-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+GetSaveName(
+ IN HWND hwndOwner,
+ OUT PWSTR pszFile,
+ IN UINT nMaxFile
+ )
+{
+ OPENFILENAME ofn = {0};
+ WCHAR szFilter[MAX_FILTER];
+
+ if (0 == GetFileFilterString(szFilter, ARRAYLEN(szFilter)))
+ {
+ return FALSE;
+ }
+
+ WCHAR WindowsDir[MAX_PATH];
+ GetWindowsDirectory(WindowsDir, ARRAYLEN(WindowsDir));
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = hwndOwner;
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrFile = pszFile;
+ ofn.nMaxFile = nMaxFile;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = WindowsDir;
+ ofn.Flags = OFN_PATHMUSTEXIST
+ | OFN_HIDEREADONLY
+ | OFN_OVERWRITEPROMPT;
+
+ return GetSaveFileName(&ofn);
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SaveResults
+//
+// Synopsis: Saves the results of a chkdsk to a file: gets a filename
+// to use, then writes out the data.
+//
+// Arguments: [hwndOwner] -- handle to owner window
+// [chkdskParams] -- various chkdsk parameters, including
+// a pointer to the results strings
+//
+// Returns: nothing
+//
+// History: 8-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SaveResults(
+ IN HWND hwndOwner,
+ IN PCHKDSK_PARAMS chkdskParams
+ )
+{
+ WCHAR szFile[MAX_PATH];
+ WCHAR filenameProto[MAX_PATH];
+
+ LoadString(
+ g_hInstance,
+ IDS_CHK_DONE_FILENAME,
+ filenameProto,
+ ARRAYLEN(filenameProto));
+
+ wsprintf(szFile, filenameProto, *(chkdskParams->DriveName));
+
+ if (GetSaveName(hwndOwner, szFile, ARRAYLEN(szFile)))
+ {
+ //
+ // user chose to save, so do it:
+ //
+ // 1. open the file
+ // 2. write it out
+ // 3. close the file
+ //
+
+ HANDLE hFile = CreateFile(
+ szFile,
+ GENERIC_WRITE,
+ 0, // prevent sharing
+ NULL, // default security
+ CREATE_ALWAYS, // overwrite old files
+ FILE_ATTRIBUTE_NORMAL,
+ NULL // no template file
+ );
+
+ if (INVALID_HANDLE_VALUE != hFile)
+ {
+ DWORD NumberOfBytesWritten;
+
+ CHAR HeaderProto[256];
+ CHAR Header[256];
+
+ LoadStringA(
+ g_hInstance,
+ IDS_CHK_DONE_FILE_HEADER,
+ HeaderProto,
+ ARRAYLEN(HeaderProto));
+
+ wsprintfA(Header, HeaderProto, chkdskParams->DriveName);
+
+ if (!WriteFile(
+ hFile,
+ Header,
+ lstrlenA(Header) * sizeof(CHAR),
+ &NumberOfBytesWritten,
+ NULL // not overlapped I/O
+ )
+ || !WriteFile(
+ hFile,
+ chkdskParams->Messages,
+ (chkdskParams->NumCharacters - 1) * sizeof(CHAR),
+ &NumberOfBytesWritten,
+ NULL // not overlapped I/O
+ ))
+ {
+ MyMessageBox(
+ g_hInstance,
+ hwndOwner,
+ IDS_CHK_SAVE_ERROR_NOWRITE,
+ IDS_CHK_SAVE_ERROR_TITLE,
+ MB_ICONINFORMATION | MB_OK
+ );
+ }
+
+ CloseHandle(hFile);
+ }
+ else
+ {
+ daDebugOut((DEB_IERROR,"CreateFile failed!\n"));
+
+ MyMessageBox(
+ g_hInstance,
+ hwndOwner,
+ IDS_CHK_SAVE_ERROR_NOFILE,
+ IDS_CHK_SAVE_ERROR_TITLE,
+ MB_ICONEXCLAMATION | MB_OK
+ );
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintResults
+//
+// Synopsis: Prints the results of a chkdsk to a printer
+//
+// Arguments: [hwndOwner] -- handle to owner window
+// [chkdskParams] -- various chkdsk parameters, including
+// a pointer to the results strings
+//
+// Returns: nothing
+//
+// History: 8-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PrintResults(
+ IN HWND hwndOwner,
+ IN PCHKDSK_PARAMS chkdskParams
+ )
+{
+ PrintString(hwndOwner, chkdskParams->Messages);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MessageWndProc
+//
+// Synopsis: Window procedure for the chkdsk summary info dialog box.
+// This is a resizable modal dialog box. Thus, the dialog
+// template has an associated window class which specifies
+// this procedure as the window procedure.
+//
+// Arguments: standard Windows procedure
+//
+// Returns: standard Windows procedure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL LRESULT CALLBACK
+MessageWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static HBRUSH hbrStaticBrush;
+ static PCHKDSK_PARAMS chkdskParams;
+ static BOOL EverythingCreated;
+ static HFONT hFontText;
+
+ switch (msg)
+ {
+ case WM_CREATE:
+ {
+ // hide the window until all the controls are created and
+ // correctly placed
+ ShowWindow(hwnd, FALSE);
+
+ chkdskParams = ParamsForChkdskCallBack;
+ hbrStaticBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+ EverythingCreated = FALSE;
+
+ HMENU hmenuSystem = GetSystemMenu(hwnd, FALSE);
+ EnableMenuItem(hmenuSystem, SC_MINIMIZE, MF_BYCOMMAND | MF_DISABLED);
+ EnableMenuItem(hmenuSystem, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED);
+ EnableMenuItem(hmenuSystem, SC_TASKLIST, MF_BYCOMMAND | MF_DISABLED);
+
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ {
+ //
+ // when we get the WM_CREATE, the controls haven't been created.
+ // So, this just happens to be a reasonable place to hook in after
+ // the controls have been created.
+ //
+
+ if (!EverythingCreated)
+ {
+ EverythingCreated = TRUE;
+
+ TCHAR titleText[MAX_RESOURCE_STRING_LEN];
+
+ LoadString(
+ g_hInstance,
+ (chkdskParams->Fix == IDC_CHKDSK_DontFix)
+ ? IDS_CHK_RESULTS_READONLY
+ : IDS_CHK_RESULTS
+ ,
+ titleText,
+ ARRAYLEN(titleText));
+
+ SetWindowText(
+ GetDlgItem(hwnd,IDC_CHKDONE_TITLE),
+ titleText);
+
+ //
+ // Set the font for the edit control. Get a fixed-width font.
+ //
+
+ hFontText = CreateFont(
+ GetHeightFromPoints(8),
+ 0,
+ 0,
+ 0,
+ FW_NORMAL, // default weight
+ FALSE, // not italic
+ FALSE, // not underlined
+ FALSE, // not strikeout
+ ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ FIXED_PITCH | FF_MODERN,
+ TEXT("Courier")
+ );
+
+ if (NULL == hFontText)
+ {
+ daDebugOut((DEB_ERROR,
+ "CreateFont failed, error %d\n",
+ GetLastError()));
+ }
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_CHKDONE_Messages,
+ WM_SETFONT,
+ (WPARAM)hFontText,
+ MAKELPARAM(FALSE, 0)
+ );
+
+ //
+ // After the font is changed, set the text
+ //
+
+ SetWindowTextA(
+ GetDlgItem(hwnd,IDC_CHKDONE_Messages),
+ chkdskParams->Messages
+ );
+
+ // force a size message & redraw, since by now all the controls
+ // have been created
+
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SetWindowPos(
+ hwnd,
+ NULL,
+ 0, 0,
+ rc.right, rc.bottom,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW);
+
+ SetFocus(GetDlgItem(hwnd,IDC_CHKDONE_Close));
+ }
+
+ return 1; // message not processed
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
+
+ //
+ // Don't allow resizing too small
+ //
+
+ lpmmi->ptMinTrackSize.x = 400;
+ lpmmi->ptMinTrackSize.y = 150;
+
+ return 0; // message processed
+ }
+
+ case WM_COMMAND:
+ {
+ WORD wNotifyCode = HIWORD(wParam);
+ WORD wID = LOWORD(wParam);
+ HWND hwndCtrl = (HWND)lParam;
+
+ switch (wID)
+ {
+ case IDOK: // sent by <Enter>
+ case IDCANCEL: // sent by <Esc>
+ case IDC_CHKDONE_Close:
+ EndDialog(hwnd, 0);
+ break;
+
+ case IDC_CHKDONE_Print:
+ PrintResults(hwnd, chkdskParams);
+ break;
+
+ case IDC_CHKDONE_Save:
+ SaveResults(hwnd, chkdskParams);
+ break;
+
+ case IDHELP:
+ NoHelp(hwnd);
+ break;
+ }
+
+ return 0;
+ }
+
+ case WM_NEXTDLGCTL:
+ {
+ BOOL fHandle = (BOOL)LOWORD(lParam);
+ UINT wCtlFocus = wParam;
+
+ if (fHandle)
+ {
+ SetFocus(GetDlgItem(hwnd,wCtlFocus));
+ }
+ else
+ {
+ if (0 == wCtlFocus)
+ {
+ SetFocus(GetDlgItem(hwnd,IDC_CHKDONE_Close));
+ }
+ else
+ {
+ SetFocus(GetDlgItem(hwnd,IDHELP));
+ }
+ }
+ }
+
+ case WM_CTLCOLORSTATIC:
+ {
+ HDC hdcStatic = (HDC)wParam;
+ SetBkColor(hdcStatic, GetSysColor(COLOR_3DFACE));
+
+ UnrealizeObject(hbrStaticBrush);
+ POINT pt;
+ pt.x = pt.y = 0;
+ ClientToScreen(hwnd, &pt);
+ SetBrushOrgEx(hdcStatic, pt.x, pt.y, NULL);
+
+ return (LRESULT)hbrStaticBrush;
+ }
+
+ case WM_SIZE:
+ {
+ if (EverythingCreated)
+ {
+ //
+ // move the controls:
+ //
+ // 1. text control: ?,? : x,?
+ // 2. edit control: ?,? : x,y
+ // 3. "Close": z,M : ?,?
+ // 4. "Save": z,M + (by + bb) : ?,?
+ // 5. "Help": z,M + 2*by + 3*bb : ?,? // extra spacing above
+ //
+ // where dx = width, dy = height of window, bx = button width,
+ // by = button height, M = margin = 7,
+ // bb = inter-button spacing = 6, ? = no change
+ // x = dx - M [left] - M [right] - bx - M [spacing between],
+ // y = dy - M [bottom] - TopPosition
+ // z = dx - bx - M
+ //
+
+ DWORD Width = (DWORD)(LOWORD(lParam));
+ DWORD Height = (DWORD)(HIWORD(lParam));
+ DWORD SideMargin = 7;
+ DWORD InterButtonMargin = 4;
+ DWORD TextBoxHeight = 50;
+ DWORD ButtonWidth = 70;
+ DWORD ButtonHeight = 23;
+ DWORD TopOfEditBox = TextBoxHeight + SideMargin + 2 * SideMargin;
+ DWORD x = Width - ButtonWidth - 4*SideMargin;
+ BOOL f;
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDC_CHKDONE_TITLE),
+ NULL,
+ SideMargin,
+ SideMargin,
+ x,
+ TextBoxHeight,
+ SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(title) failed, %d\n",GetLastError())); }
+
+ DWORD y = Height - SideMargin - TopOfEditBox;
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDC_CHKDONE_Messages),
+ NULL,
+ SideMargin,
+ TopOfEditBox,
+ x,
+ y,
+ SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(message) failed, %d\n",GetLastError())); }
+
+ DWORD z = Width - ButtonWidth - SideMargin;
+ DWORD t = ButtonHeight + InterButtonMargin;
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDC_CHKDONE_Close),
+ NULL,
+ z,
+ SideMargin,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(close) failed, %d\n",GetLastError())); }
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDC_CHKDONE_Print),
+ NULL,
+ z,
+ SideMargin + t,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(print) failed, %d\n",GetLastError())); }
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDC_CHKDONE_Save),
+ NULL,
+ z,
+ SideMargin + 2 * t,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(save) failed, %d\n",GetLastError())); }
+
+ f = SetWindowPos(
+ GetDlgItem(hwnd,IDHELP),
+ NULL,
+ z,
+ SideMargin + 3 * t + InterButtonMargin, // a bit extra
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOREDRAW);
+
+ if (!f) { daDebugOut((DEB_ERROR,"SetWindowPos(help) failed, %d\n",GetLastError())); }
+
+ InvalidateRect(hwnd, NULL, FALSE);
+ UpdateWindow(hwnd);
+ }
+
+ return 0;
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ UINT uCmdType = (wParam & 0xfff0);
+
+ if ( SC_CLOSE == uCmdType
+ || SC_MINIMIZE == uCmdType
+ || SC_TASKLIST == uCmdType)
+ {
+ daDebugOut((DEB_ITRACE,"Ignoring a disallowed operation\n"));
+
+ return 0; // disallow these.
+ }
+
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ EndDialog(hwnd, 0);
+ return 0;
+ }
+
+ case WM_DESTROY:
+ {
+ DeleteBrush(hbrStaticBrush);
+ DeleteFont(hFontText);
+ return 0;
+ }
+
+ default:
+ break;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// Code for the thread handling invocation of Chkdsk()
+//
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OnFinalMessage
+//
+// Synopsis: Put a message in a message box after the final chkdsk message
+//
+// Arguments: [hwndOwner] -- handle to owner window
+// [Message] -- message to display
+//
+// Returns: nothing
+//
+// History: 6-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+OnFinalMessage(
+ IN HWND hwndOwner,
+ IN PSTR Message
+ )
+{
+ CHAR title[100];
+
+ LoadStringA(
+ g_hInstance,
+ IDS_CHK_TITLE,
+ title,
+ ARRAYLEN(title));
+
+ MessageBoxA(
+ hwndOwner,
+ Message,
+ title,
+ MB_OK | MB_ICONINFORMATION
+ );
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChkdskCallback
+//
+// Synopsis: This routine gets callbacks from fmifs.dll regarding
+// progress and status of the ongoing chkdsk. It runs in the
+// same thread as the chkdsk, which is a separate thread from
+// the "cancel" button and the error message window (if
+// any). If the user hits "cancel", this routine
+// notices on the next callback and cancels the chkdsk.
+//
+// Arguments: [PacketType] -- an fmifs packet type
+// [PacketLength] -- length of the packet data
+// [PacketData] -- data associated with the packet
+//
+// Returns: TRUE if the fmifs activity should continue, FALSE if the
+// activity should halt immediately. Thus, we return FALSE if
+// the user has hit "cancel" and we wish fmifs to clean up and
+// return from the Chkdsk() entrypoint call.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+LOCAL BOOLEAN
+ChkdskCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ )
+{
+ UNREFERENCED_PARM(PacketLength);
+
+ PCHKDSK_PARAMS chkdskParams = ParamsForChkdskCallBack;
+
+ if (chkdskParams->Cancel)
+ {
+ if (!chkdskParams->Cancelled)
+ {
+ //
+ // if we haven't got a cancelled callback yet (that is, we
+ // haven't yet been called here with Cancel set to TRUE), then
+ // send a Cancel message to the dialog.
+ //
+ // we will actually get up to two callbacks with Cancel set to
+ // TRUE: one for the first message following the time when we
+ // set Cancel to TRUE. This can be any message. The second
+ // will be for the FmIfsFinished message.
+ //
+
+ int fOk = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_StopChk),
+ chkdskParams->hDlg,
+ StopChkDlgProc,
+ (LPARAM)chkdskParams
+ );
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBoxParam() failed!\n"));
+ return FALSE;
+ }
+
+ if (fOk)
+ {
+ // stop it!
+
+ PostMessage(chkdskParams->hDlg, CHK_PROGRESSCANCEL, 0, 0);
+
+ chkdskParams->Cancelled = TRUE;
+
+ return FALSE;
+ }
+ else
+ {
+ // user changed mind; doesn't want to stop it
+
+ chkdskParams->Cancel = FALSE;
+
+ // re-enable the cancel button
+
+ PostMessage(chkdskParams->hDlg, CHK_PROGRESSUNCANCEL, 0, 0);
+
+ // now, drop through and perform work on the message...
+ }
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE, "ChkdskCallback called after cancelled\n"));
+ return FALSE;
+ }
+ }
+
+ switch (PacketType)
+ {
+
+ case FmIfsPercentCompleted:
+ {
+ DWORD currentTime = GetTime();
+ DWORD timeDelta = currentTime - chkdskParams->lasttime;
+
+ ULONG PercentCompleted = ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted;
+
+ if ( 0 == PercentCompleted
+ || 100 == PercentCompleted
+ || timeDelta >= MIN_TIME_DELTA)
+ {
+ chkdskParams->lasttime = currentTime;
+
+ PostMessage(
+ chkdskParams->hDlg,
+ CHK_PROGRESSUPDATE,
+ PercentCompleted,
+ 0
+ );
+ }
+
+ return TRUE;
+ }
+
+ case FmIfsCheckOnReboot:
+ {
+ PFMIFS_CHECKONREBOOT_INFORMATION pMess =
+ (PFMIFS_CHECKONREBOOT_INFORMATION)PacketData;
+
+ //
+ // we only query the user if we are in "fix" mode.
+ // Otherwise, we answer the default since nothing really
+ // happens anyway.
+ //
+
+ pMess->QueryResult =
+ (IDYES == MyMessageBox(
+ g_hInstance,
+ chkdskParams->hwndParent,
+ IDS_CHK_ON_REBOOT,
+ IDS_CHK_TITLE,
+ MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1
+ ));
+
+ daDebugOut((DEB_TRACE,
+ "Callback: reboot query returns \"%s\"\n",
+ pMess->QueryResult ? "yes" : "no"
+ ));
+
+ return TRUE;
+ }
+
+ case FmIfsTextMessage:
+ {
+ PFMIFS_TEXT_MESSAGE pMess = (PFMIFS_TEXT_MESSAGE)PacketData;
+
+ switch (pMess->MessageType)
+ {
+ case MESSAGE_TYPE_RESULTS:
+ {
+ daDebugOut((DEB_TRACE,
+ "Callback: results message \"%s\"\n",
+ pMess->Message
+ ));
+
+ chkdskParams->fmifsSuccess = FALSE;
+
+ //
+ // Append the message to the edit control
+ //
+
+ UINT Length = lstrlenA(pMess->Message);
+
+ while (chkdskParams->NumCharacters + Length
+ > chkdskParams->NumMessageChunks * MESSAGE_CHUNK)
+ {
+ //
+ // need to allocate more memory
+ //
+
+ ++ chkdskParams->NumMessageChunks;
+ PSTR temp = new CHAR[chkdskParams->NumMessageChunks * MESSAGE_CHUNK];
+ lstrcpyA(temp, chkdskParams->Messages);
+ delete[] chkdskParams->Messages;
+ chkdskParams->Messages = temp;
+ }
+
+ lstrcatA(chkdskParams->Messages, pMess->Message);
+ chkdskParams->NumCharacters += Length;
+
+ break;
+ }
+
+ case MESSAGE_TYPE_PROGRESS:
+ {
+ //
+ // I need to send the message from this thread (the worker
+ // thread) to the other thread (the UI thread), so it can be put
+ // in the progress dialog. However, I can't just send the passed-in
+ // pointer, because it points to a static buffer in fmifs that will
+ // get munged before the UI thread does anything. So, allocate a
+ // buffer, copy the string, and pass that pointer in the message.
+ // Then, the UI thread must de-allocate it.
+ //
+
+ daDebugOut((DEB_TRACE,
+ "Callback: progress message \"%s\"\n",
+ pMess->Message
+ ));
+
+ PSTR Message = new CHAR[(lstrlenA(pMess->Message) + 1) * sizeof(CHAR)];
+ lstrcpyA(Message, pMess->Message);
+ PostMessage(chkdskParams->hDlg, CHK_PROGRESSTITLE, (WPARAM)Message, 0);
+
+ break;
+ }
+
+ case MESSAGE_TYPE_FINAL:
+ {
+ daDebugOut((DEB_TRACE,
+ "Callback: final message \"%s\"\n",
+ pMess->Message));
+
+ OnFinalMessage(chkdskParams->hDlg, pMess->Message);
+
+ // now, make sure this is the final message...
+
+ chkdskParams->Final = TRUE;
+
+ break;
+ }
+
+ default:
+ {
+ daDebugOut((DEB_TRACE,
+ "Callback: Unknown message, type %d, \"%s\"\n",
+ pMess->MessageType,
+ pMess->Message
+ ));
+
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ case FmIfsFinished:
+
+ daDebugOut((DEB_TRACE,"Callback: Finished\n"));
+// chkdskParams->fmifsSuccess =
+// ((PFMIFS_FINISHED_INFORMATION)PacketData)->Success;
+
+ PostMessage(chkdskParams->hDlg, CHK_PROGRESSEND, 0, 0);
+
+ return TRUE;
+
+ default:
+
+ daDebugOut((DEB_ERROR,
+ "Chkdsk callback: unexpected message: %d\n",
+ PacketType));
+ return FALSE;
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChkdskVolume
+//
+// Synopsis: Thread procedure that invokes Chkdsk on a volume.
+//
+// Arguments: [ThreadParameter] -- a PCHKDSK_PARAMS pointer
+//
+// Returns: 0
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL DWORD WINAPI
+ChkdskVolume(
+ IN LPVOID ThreadParameter
+ )
+{
+ PCHKDSK_PARAMS chkdskParams = (PCHKDSK_PARAMS)ThreadParameter;
+
+ daDebugOut((DEB_TRACE,
+ "Calling Chkdsk(%ws,%ws,/f? %s,/r? %s...)\n",
+ chkdskParams->DriveName,
+ chkdskParams->FileSystem,
+ CHKDSK_SLASH_F(chkdskParams->Fix) ? "yes" : "no",
+ CHKDSK_SLASH_R(chkdskParams->Fix) ? "yes" : "no"
+ ));
+
+ //
+ // The fmifs interface doesn't allow for a context parameter
+ // therefore the chkdskparams must be passed through a global.
+ //
+
+ chkdskParams->lasttime = 0; // force first
+ ParamsForChkdskCallBack = chkdskParams;
+
+ (*lpfnChkdsk)(
+ chkdskParams->DriveName,
+ chkdskParams->FileSystem,
+ CHKDSK_SLASH_F(chkdskParams->Fix), // fix?
+ FALSE, // not verbose
+ FALSE, // not only if dirty (i.e., force a check)
+ CHKDSK_SLASH_R(chkdskParams->Fix), // recover? (i.e. sector check)
+ NULL, // don't check a specific path
+ FALSE, // don't try to extend volume
+ &ChkdskCallback
+ );
+
+ daDebugOut((DEB_TRACE,"Leaving Chkdsk() worker thread\n"));
+ return 0;
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// Code for the thread handling the "working..." (i.e. cancel) dialog
+// as well as preceeding dialogs (the initial chkdsk choices (fix/no
+// fix) dialog, and the initial invocation of this extension option.
+//
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetChkdskProgressTitle
+//
+// Synopsis: Sets the title in the chkdsk progress dialog
+//
+// Arguments: [hDlg] -- handle to dialog window
+// [chkdskParams] -- chkdsk parameters
+//
+// Returns: nothing
+//
+// History: 7-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+SetChkdskProgressTitle(
+ IN HWND hDlg,
+ IN PCHKDSK_PARAMS chkdskParams
+ )
+{
+ //
+ // Set the title, e.g. "Checking Volume D:"
+ //
+
+ TCHAR title[100];
+ TCHAR titleProto[100];
+
+ LoadString(
+ g_hInstance,
+ IDS_CHK_PROGRESS_TITLE,
+ titleProto,
+ ARRAYLEN(titleProto));
+
+ wsprintf(
+ title,
+ titleProto,
+ chkdskParams->DriveName);
+
+ SetDlgItemText(hDlg, IDC_CHKPROG_Title, title);
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChkdskProgressDlgProc
+//
+// Synopsis: Dialog procedure for "cancel" dialog for Chkdsk
+//
+// Arguments: standard Windows dialog procedure
+//
+// Returns: standard Windows dialog procedure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+// Note: If the user chooses "cancel", we need to stop the Chkdsk
+// operation, which is running in a separate thread. That
+// thread, in turn, needs to destroy the error message window
+// (if any), and the associated error message window thread.
+//
+//----------------------------------------------------------------------------
+
+LOCAL BOOL CALLBACK
+ChkdskProgressDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static DWORD percentDrawn;
+ static PCHKDSK_PARAMS chkdskParams;
+ static BOOL noPercentDone;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ chkdskParams = (PCHKDSK_PARAMS)lParam;
+
+ chkdskParams->hDlg = hDlg;
+ chkdskParams->fmifsSuccess = TRUE;
+ chkdskParams->Result = 0;
+
+ chkdskParams->NumMessageChunks = 1; // initially allocate one
+ chkdskParams->NumCharacters = 1; // NULL character
+ chkdskParams->Messages = new CHAR[MESSAGE_CHUNK];
+ chkdskParams->Messages[0] = '\0';
+
+ CenterWindow(hDlg, chkdskParams->hwndParent);
+
+ SetChkdskProgressTitle(hDlg, chkdskParams);
+
+ //
+ // Create the formatting thread
+ //
+
+ DWORD threadId; // ignored
+ chkdskParams->hWorkerThread = CreateThread(
+ NULL,
+ 0,
+ ChkdskVolume,
+ (LPVOID)chkdskParams,
+ 0,
+ &threadId
+ );
+
+ if (NULL == chkdskParams->hWorkerThread)
+ {
+ daDebugOut((DEB_ERROR,"Error creating chkdsk worker thread\n"));
+
+ chkdskParams->Result = MSG_COULDNT_CREATE_THREAD;
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+
+ noPercentDone = chkdskParams->noPercentDone;
+
+ //
+ // Initialize the gas gauge
+ //
+
+ if (!noPercentDone)
+ {
+ percentDrawn = 0;
+ InitDrawGasGauge(GetDlgItem(hDlg, IDC_CHKPROG_GasGauge));
+ }
+
+ SetDlgItemTextA(hDlg, IDC_CHKPROG_GasGaugeCaption, "");
+
+ return 1; // didn't call SetFocus
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ if (chkdskParams->AllowCancel)
+ {
+ MySetDlgItemText(g_hInstance, hDlg, IDC_CHKPROG_Title, IDS_CANCELPENDING);
+ SetDlgItemText(hDlg, IDC_CHKPROG_GasGaugeCaption, TEXT(""));
+
+ // disable the "stop" button if it's already been pushed.
+
+ EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
+
+ // leave result at 0, so no pop-up
+ chkdskParams->Cancel = TRUE;
+
+ // only exit after final message: see CHK_PROGRESSCANCEL
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hDlg, &ps);
+
+ if (!noPercentDone)
+ {
+ DrawGasGauge(
+ GetDlgItem(hDlg, IDC_CHKPROG_GasGauge),
+ hDlg,
+ hDC,
+ percentDrawn,
+ NULL);
+ }
+
+ EndPaint(hDlg, &ps);
+
+ return TRUE;
+ }
+
+ case CHK_PROGRESSUPDATE:
+ {
+ // wParam = % completed
+
+ if (noPercentDone)
+ {
+ daDebugOut((DEB_TRACE,
+ "ChkdskProgressDlgProc: Got an unexpected progress message\n"));
+ return TRUE;
+ }
+
+ percentDrawn = (INT)wParam;
+
+ RECT rcGauge;
+ HWND hwndGauge = GetDlgItem(hDlg, IDC_CHKPROG_GasGauge);
+
+ GetClientRect(hwndGauge, &rcGauge);
+
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.left);
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.right);
+ ScreenToClient(hDlg, (LPPOINT)&rcGauge.left);
+ ScreenToClient(hDlg, (LPPOINT)&rcGauge.right);
+
+ InvalidateRect(hDlg, &rcGauge, FALSE);
+ UpdateWindow(hDlg);
+
+ return TRUE;
+ }
+
+ case CHK_PROGRESSEND:
+ {
+ daDebugOut((DEB_TRACE,
+ "ChkdskProgressDlgProc: got CHK_PROGRESSEND message\n"));
+
+ //
+ // Wait 15 seconds for it to finish
+ //
+ daDebugOut((DEB_TRACE,"Waiting for worker thread to terminate\n"));
+ DWORD ret = WaitForSingleObject(chkdskParams->hWorkerThread, 15000);
+ if (WAIT_TIMEOUT == ret)
+ {
+ daDebugOut((DEB_ERROR,"Timeout waiting for worker thread to terminate\n"));
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE,"Worker thread terminated\n"));
+ }
+ CloseHandle(chkdskParams->hWorkerThread);
+ EndDialog(hDlg, TRUE);
+
+ return TRUE;
+ }
+
+ case CHK_PROGRESSCANCEL:
+ {
+ //
+ // Wait 15 seconds for it to finish
+ //
+ daDebugOut((DEB_TRACE,"Waiting for worker thread to terminate\n"));
+ DWORD ret = WaitForSingleObject(chkdskParams->hWorkerThread, 15000);
+ if (WAIT_TIMEOUT == ret)
+ {
+ daDebugOut((DEB_ERROR,"Timeout waiting for worker thread to terminate\n"));
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE,"Worker thread terminated\n"));
+ }
+ CloseHandle(chkdskParams->hWorkerThread);
+
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+ }
+
+ case CHK_PROGRESSUNCANCEL:
+ {
+ //
+ // Reset the dialog text/titles/captions
+ //
+
+ SetChkdskProgressTitle(hDlg, chkdskParams);
+
+ //
+ // Re-enable the "stop" button, and set focus to it
+ //
+
+ HWND hwndCancelButton = GetDlgItem(hDlg, IDCANCEL);
+ EnableWindow(hwndCancelButton, TRUE);
+ SetFocus(hwndCancelButton);
+
+ return TRUE;
+ }
+
+ case CHK_PROGRESSTITLE:
+ {
+ PSTR message = (PSTR)wParam;
+ SetDlgItemTextA(hDlg, IDC_CHKPROG_GasGaugeCaption, message);
+ delete[] message;
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE; // message not processed
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindCheckedRadioButton
+//
+// Synopsis: Search for which radio button is checked. Returns the
+// first one checked from a sequential set of IDs.
+//
+// Arguments: [hDlg] -- dialog with the radio buttons
+// [wIdFirst] -- first radio button
+// [wIdLast] -- last radio button
+//
+// Returns: the ID or the checked button, or -1 if none
+//
+// History: 4-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+int
+FindCheckedRadioButton(
+ HWND hDlg,
+ int wIdFirst,
+ int wIdLast
+ )
+{
+ for (int i = wIdFirst; i <= wIdLast; i++)
+ {
+ if (IsDlgButtonChecked(hDlg, i))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChkdskDlgProc
+//
+// Synopsis: Dialog procedure for Chkdsk UI. Allows user to choose
+// Chkdsk options.
+//
+// Arguments: standard Windows dialog procedure
+//
+// Returns: standard Windows dialog procedure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL BOOL CALLBACK
+ChkdskDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static PCHKDSK_PARAMS chkdskParams;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ chkdskParams = (PCHKDSK_PARAMS)lParam;
+
+ CenterWindow(hDlg, chkdskParams->hwndParent);
+
+ //
+ // set the initial data: the radio button and the label
+ //
+
+ TCHAR volumeInfo[100];
+ TCHAR titleProto[100];
+
+ if (TEXT('\0') != chkdskParams->Label[0])
+ {
+ LoadString(
+ g_hInstance,
+ IDS_CHK_VOLWITHLABEL,
+ titleProto,
+ ARRAYLEN(titleProto));
+
+ wsprintf(
+ volumeInfo,
+ titleProto,
+ chkdskParams->DriveName,
+ chkdskParams->Label);
+ }
+ else
+ {
+ LoadString(
+ g_hInstance,
+ IDS_CHK_VOLNOLABEL,
+ titleProto,
+ ARRAYLEN(titleProto));
+
+ wsprintf(
+ volumeInfo,
+ titleProto,
+ chkdskParams->DriveName);
+ }
+
+ SetDlgItemText(hDlg, IDC_CHKDSK_VolumeToCheck, volumeInfo);
+
+ //
+ // Do filesystem-specific initialization, namely, whether /R is
+ // supported or not.
+ //
+
+ CheckRadioButton(
+ hDlg,
+ IDC_CHKDSK_DontFix,
+ IDC_CHKDSK_FixAll,
+ IDC_CHKDSK_Fix // initially, set to "fix"
+ );
+
+ return 1; // didn't call SetFocus
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ int ret = IDYES; // by default, hitting OK means exit the dialog
+
+ chkdskParams->Fix = FindCheckedRadioButton(
+ hDlg,
+ IDC_CHKDSK_DontFix,
+ IDC_CHKDSK_FixAll
+ );
+
+ if (IDC_CHKDSK_DontFix == chkdskParams->Fix)
+ {
+ //
+ // if the choice is "don't fix", then make sure
+ //
+
+ TCHAR szTitle[100];
+ TCHAR szMessage[400];
+
+ LoadString(
+ g_hInstance,
+ IDS_CHK_TITLE,
+ szTitle,
+ ARRAYLEN(szTitle));
+
+ RetrieveAndFormatMessage(
+ MSG_CHK_READONLY_WARNING,
+ szMessage,
+ ARRAYLEN(szMessage),
+ NULL
+ );
+
+ ret = MessageBox(
+ hDlg,
+ szMessage,
+ szTitle,
+ MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1
+ );
+ }
+
+ if (ret == IDYES)
+ {
+ EndDialog(hDlg, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDHELP:
+ NoHelp(hDlg);
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE; // message not processed
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoChkdsk
+//
+// Synopsis: Perform UI to get user options for the Chkdsk, and then
+// actually perform a chkdsk on a volume.
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoChkdsk(
+ IN HWND hwndParent
+ )
+{
+ if (!LoadFmifs())
+ {
+ return; // can't load fmifs.dll, so bail
+ }
+
+ static CHKDSK_PARAMS chkdskParams; // This can't be on the stack:
+ // it is passed to other threads
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(regionDescriptor);
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(regionData);
+
+ PWSTR typeName = regionData->TypeName;
+
+ lstrcpy(chkdskParams.Label, regionData->VolumeLabel);
+ chkdskParams.Cancel = FALSE;
+ chkdskParams.Cancelled = FALSE;
+ chkdskParams.Final = FALSE;
+ chkdskParams.hwndParent = hwndParent;
+ chkdskParams.FileSystem = typeName;
+
+ FileSystemInfoType* pFSInfo = FindFileSystemInfo(typeName);
+ if (NULL == pFSInfo)
+ {
+ chkdskParams.FileSys = FS_UNKNOWN;
+ }
+ else
+ {
+ chkdskParams.FileSys = pFSInfo->FileSystemType;
+ }
+ chkdskParams.Messages = NULL;
+
+ WCHAR driveName[3];
+ driveName[0] = regionData->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+ chkdskParams.DriveName = driveName;
+
+ int fOk = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CHKDSK),
+ hwndParent,
+ ChkdskDlgProc,
+ (LPARAM)&chkdskParams
+ );
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBoxParam() failed!\n"));
+ return;
+ }
+
+ if (fOk)
+ {
+ EnsureSameDevice(regionDescriptor);
+
+ LPTSTR lpszTemplate;
+
+ chkdskParams.noPercentDone = FALSE; //by default, we have %done info
+
+#ifdef SUPPORT_OFS
+ if (chkdskParam.FileSys == FS_OFS)
+ {
+ chkdskParams.noPercentDone = TRUE;
+ }
+#endif // SUPPORT_OFS
+
+ if ( (chkdskParams.Fix == IDC_CHKDSK_Fix)
+ || (chkdskParams.Fix == IDC_CHKDSK_FixAll) )
+ {
+ chkdskParams.AllowCancel = FALSE;
+#ifdef SUPPORT_OFS
+ if (chkdskParams.noPercentDone)
+ {
+ lpszTemplate = MAKEINTRESOURCE(IDD_CHKDSKPROGRESS_NOSTOP_NOPERCENT);
+ }
+ else
+ {
+#endif // SUPPORT_OFS
+ lpszTemplate = MAKEINTRESOURCE(IDD_CHKDSKPROGRESS_NOSTOP);
+#ifdef SUPPORT_OFS
+ }
+#endif // SUPPORT_OFS
+ }
+ else
+ {
+ chkdskParams.AllowCancel = TRUE;
+#ifdef SUPPORT_OFS
+ if (chkdskParams.noPercentDone)
+ {
+ lpszTemplate = MAKEINTRESOURCE(IDD_CHKDSKPROGRESS_NOPERCENT);
+ }
+ else
+ {
+#endif // SUPPORT_OFS
+ lpszTemplate = MAKEINTRESOURCE(IDD_CHKDSKPROGRESS);
+#ifdef SUPPORT_OFS
+ }
+#endif // SUPPORT_OFS
+ }
+
+ fOk = DialogBoxParam(
+ g_hInstance,
+ lpszTemplate,
+ hwndParent,
+ ChkdskProgressDlgProc,
+ (LPARAM)&chkdskParams);
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBoxParam() failed!\n"));
+ }
+ else if (chkdskParams.Cancel)
+ {
+ // operation was cancelled
+ }
+ else if (! chkdskParams.Final)
+ {
+ daDebugOut((DEB_TRACE,"Chkdsk terminated normally\n"));
+
+ //
+ // Chkdsk wasn't cancelled; it finished normally
+ //
+
+ if (chkdskParams.NumCharacters > 1) //more than just a NULL char.
+ {
+ //
+ // If there were no messages, we don't display anything. If
+ // there were messages, so show the results box.
+ //
+
+ //
+ // bad variable name. I can't figure out how to send a
+ // context parameters to a dialog box with a separate class.
+ // DialogBoxParam sends the last param to a dialog procedure's
+ // WM_INITDIALOG message. But, we don't get that message with
+ // our own dialog class.
+ //
+
+ ParamsForChkdskCallBack = &chkdskParams;
+
+ fOk = DialogBox(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CHKDONE),
+ hwndParent,
+ NULL
+ );
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBoxParam() failed!\n"));
+ }
+ }
+ }
+
+ if (NULL != chkdskParams.Messages)
+ {
+ delete[] chkdskParams.Messages;
+ }
+ }
+}
diff --git a/private/utils/windisk/src/chkdsk.hxx b/private/utils/windisk/src/chkdsk.hxx
new file mode 100644
index 000000000..80d628a05
--- /dev/null
+++ b/private/utils/windisk/src/chkdsk.hxx
@@ -0,0 +1,27 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: chkdsk.hxx
+//
+// Contents: Chkdsk APIs
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CHKDSK_HXX__
+#define __CHKDSK_HXX__
+
+BOOL
+RegisterMessageWindowClass(
+ VOID
+ );
+
+VOID
+DoChkdsk(
+ IN HWND hwndParent
+ );
+
+#endif // __CHKDSK_HXX__
diff --git a/private/utils/windisk/src/cm.cxx b/private/utils/windisk/src/cm.cxx
new file mode 100644
index 000000000..031b188da
--- /dev/null
+++ b/private/utils/windisk/src/cm.cxx
@@ -0,0 +1,888 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cm.cxx
+//
+// Contents: Context menu functions
+//
+// History: 24-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cm.hxx"
+#include "listbox.hxx"
+#include "menudict.hxx"
+#include "popup.hxx"
+#include "select.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef WINDISK_EXTENSIONS
+INT
+AddExtensionItemsToContextMenu(
+ IN HMENU hmenuContext,
+ IN MenuType* pMenu,
+ IN BOOL fFlags
+ );
+#endif // WINDISK_EXTENSIONS
+
+BOOL
+MyAppendMenu(
+ IN HMENU hmenu,
+ IN UINT idNewItem
+ );
+
+INT
+DoContextMenu(
+ IN HMENU hmenu,
+ IN PPOINT ppt
+ );
+
+VOID
+VolumeContextMenu(
+ IN PPOINT ppt
+ );
+
+VOID
+NewVolumeContextMenu(
+ IN PPOINT ppt
+ );
+
+VOID
+FreeSpaceContextMenu(
+ IN PPOINT ppt
+ );
+
+VOID
+ExtendedFreeSpaceContextMenu(
+ IN PPOINT ppt
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define MAXMENUTEXTLEN 50
+
+UINT aFileSystemCommands[] =
+{
+ IDM_VOL_FORMAT,
+ IDM_VOL_LETTER,
+ IDM_VOL_EJECT
+};
+
+
+
+UINT aContextMenuCommands[] =
+{
+
+//
+// Tools menu
+//
+
+ IDM_VOL_DBLSPACE ,
+
+//
+// Partition menu
+//
+
+ IDM_PARTITIONCREATE ,
+ IDM_PARTITIONCREATEEX ,
+ IDM_PARTITIONDELETE ,
+#if i386
+ IDM_PARTITIONACTIVE ,
+#endif
+
+//
+// Fault tolerance menu (Advanced Server only)
+//
+
+ IDM_FTESTABLISHMIRROR ,
+ IDM_FTBREAKMIRROR ,
+ IDM_FTCREATESTRIPE ,
+ IDM_FTCREATEVOLUMESET ,
+ IDM_FTRECOVERSTRIPE ,
+ IDM_FTCREATEPSTRIPE ,
+ IDM_FTEXTENDVOLUMESET
+
+};
+
+
+UINT aFinalCommands[] =
+{
+ IDM_PARTITIONCOMMIT,
+ IDM_VOL_PROPERTIES
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef WINDISK_EXTENSIONS
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddExtensionItemsToContextMenu
+//
+// Synopsis: Adds an extension menu item to both the menu bar and the
+// given context menu.
+//
+// Arguments: [hmenuContext] -- context menu to add item to
+// [pMenu] -- pointer to extension menu item
+// [fFlags] -- standard menu flags (probably
+// MF_ENABLED or MF_GRAYED)
+//
+// Returns: Count of items added
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+AddExtensionItemsToContextMenu(
+ IN HMENU hmenuContext,
+ IN MenuType* pMenu,
+ IN BOOL fFlags
+ )
+{
+ INT i;
+
+ for (i=0; i<pMenu->cMenuItems; i++)
+ {
+ MenuItemType* pItem = &(pMenu->aMenuItems[i]);
+
+ INT id = MenuItems.LookupMenuId(pItem); //get the ID
+
+ if (-1 == id)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't add '%ws' to context menu\n",
+ pItem->pszMenu
+ ));
+ }
+ else
+ {
+ BOOL f = AppendMenu(
+ hmenuContext,
+ MF_STRING | fFlags,
+ (UINT)id,
+ pItem->pszMenu);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+ }
+
+ return pMenu->cMenuItems;
+}
+
+#endif // WINDISK_EXTENSIONS
+
+//+---------------------------------------------------------------------------
+//
+// Function: MyAppendMenu
+//
+// Synopsis: Append to a context menu. The string to use as the menu item
+// content is derived from the frame window menu. Thus,
+// the context menu so added must be a normal menu command of
+// the frame window.
+//
+// Arguments: [hmenu] -- handle of menu to append to
+// [idNewItem] -- ID of new menu item, e.g. IDM_VOL_FORMAT
+//
+// Returns: TRUE if success
+//
+// History: 19-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+MyAppendMenu(
+ IN HMENU hmenu,
+ IN UINT idNewItem
+ )
+{
+ TCHAR szText[MAXMENUTEXTLEN];
+ BOOL f = FALSE;
+
+ if (0 != GetMenuString(
+ g_hmenuFrame,
+ idNewItem,
+ szText,
+ ARRAYLEN(szText),
+ MF_BYCOMMAND))
+ {
+ f = AppendMenu(
+ hmenu,
+ MF_STRING | GetMenuState(g_hmenuFrame, idNewItem, MF_BYCOMMAND),
+ idNewItem,
+ szText
+ );
+ }
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+
+ return f;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DoContextMenu, public
+//
+// Synopsis: Create a context menu
+//
+// Arguments: [hmenu] -- The pop-up context menu to display
+// [ppt] -- pointer to a point (in screen coordinates) for
+// the upper-left corner of the menu
+//
+// Returns: -1 if nothing chosen, or the 0-based index of the item selected
+//
+// History: 24-May-93 BruceFo Created
+//
+// Notes: The owner window for the context menu is the Disk
+// Administrator frame window. It receives a WM_COMMAND based
+// on the menu selection.
+//
+//--------------------------------------------------------------------------
+
+INT
+DoContextMenu(
+ IN HMENU hmenu,
+ IN PPOINT ppt
+ )
+{
+ if (0 == GetMenuItemCount(hmenu))
+ {
+ // nothing in the menu!
+
+ return -1;
+ }
+
+ INT ret = TrackModalPopupMenu(
+ hmenu,
+ TPM_LEFTALIGN | TPM_RIGHTBUTTON,
+ ppt->x,
+ ppt->y,
+ 0,
+ NULL
+ );
+
+ return (ret < 0) ? -1 : ret;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: VolumeContextMenu, public
+//
+// Synopsis: Create a context menu for a selection in the volume view
+//
+// Arguments: [ppt] -- ptr to screen coordinates of point to put
+// context menu at
+//
+// Returns: nothing?
+//
+// History: 24-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+VolumeContextMenu(
+ IN PPOINT ppt
+ )
+{
+ INT cVolumeCommands = 0;
+ INT cExtensionCommands = 0;
+ INT cPartitionCommands = 0;
+ INT cFinalCommands = 0;
+ INT cSeparators = 0;
+ INT i;
+
+ BOOL f;
+
+ //
+ // Create the menu
+ //
+
+ HMENU hmenuVol = CreatePopupMenu();
+
+ if (NULL == hmenuVol)
+ {
+ daDebugOut((DEB_ERROR,"CreatePopupMenu failed!\n"));
+ return;
+ }
+
+ for (i=0; i<ARRAYLEN(aFileSystemCommands); i++)
+ {
+
+ if (aFileSystemCommands[i] == IDM_VOL_LETTER ||
+ aFileSystemCommands[i] == IDM_VOL_EJECT ||
+ !(MF_GRAYED & GetMenuState(
+ g_hmenuFrame,
+ aFileSystemCommands[i],
+ MF_BYCOMMAND))
+ )
+ {
+ MyAppendMenu(hmenuVol, aFileSystemCommands[i]);
+ ++cVolumeCommands;
+ }
+ }
+
+#ifdef WINDISK_EXTENSIONS
+
+ if (AllowExtensionItems)
+ {
+ //
+ // Determine if there are any context menu items drawn from extension
+ // classes (based on previous claiming). Only allow extension items on
+ // pre-existing volumes or disks, for single selection.
+ //
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ WCHAR driveLetter = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+ unsigned driveIndex = (unsigned)DriveLetterToIndex(driveLetter);
+
+ if (NULL != VolumeInfo[driveIndex].VolClaims)
+ {
+ //
+ // add the volume extension items
+ //
+
+ PVOL_CLAIM_LIST volClaims = VolumeInfo[driveIndex].VolClaims;
+ while (NULL != volClaims)
+ {
+ AddExtensionItemsToContextMenu(
+ hmenuVol,
+ &(volClaims->pClaimer->pInfo->mnuOps),
+ MF_ENABLED
+ );
+
+ ++cExtensionCommands;
+
+ volClaims = volClaims->pNext;
+ }
+ }
+ }
+
+#endif // WINDISK_EXTENSIONS
+
+ for (i=0; i<ARRAYLEN(aContextMenuCommands); i++)
+ {
+ if (!(MF_GRAYED & GetMenuState(g_hmenuFrame,
+ aContextMenuCommands[i],
+ MF_BYCOMMAND))
+ )
+ {
+ MyAppendMenu(hmenuVol, aContextMenuCommands[i]);
+ ++cPartitionCommands;
+ }
+ }
+
+ for (i = 0; i < ARRAYLEN(aFinalCommands); i++)
+ {
+ if (aFinalCommands[i] == IDM_VOL_PROPERTIES ||
+ !(MF_GRAYED & GetMenuState(
+ g_hmenuFrame,
+ aFinalCommands[i],
+ MF_BYCOMMAND))
+ )
+ {
+ MyAppendMenu(hmenuVol, aFinalCommands[i]);
+ ++cFinalCommands;
+ }
+ }
+
+ //
+ // Now, add separators if needed
+ //
+
+ if ( cVolumeCommands > 0
+ && (cExtensionCommands + cPartitionCommands + cFinalCommands) > 0)
+ {
+ f = InsertMenu(
+ hmenuVol,
+ cVolumeCommands,
+ MF_BYPOSITION | MF_SEPARATOR,
+ 0,
+ NULL);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"InsertMenu failed!\n"));
+ }
+ else
+ {
+ ++cSeparators;
+ }
+ }
+
+#ifdef WINDISK_EXTENSIONS
+
+ if ( cExtensionCommands > 0
+ && (cPartitionCommands + cFinalCommands) > 0)
+ {
+ f = InsertMenu(
+ hmenuVol,
+ cVolumeCommands
+ + cExtensionCommands
+ + cSeparators,
+ MF_BYPOSITION | MF_SEPARATOR,
+ 0,
+ NULL);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"InsertMenu failed!\n"));
+ }
+ else
+ {
+ ++cSeparators;
+ }
+ }
+
+#endif // WINDISK_EXTENSIONS
+
+ if ( cPartitionCommands > 0
+ && cFinalCommands > 0)
+ {
+ f = InsertMenu(
+ hmenuVol,
+ cVolumeCommands
+ + cExtensionCommands
+ + cPartitionCommands
+ + cSeparators,
+ MF_BYPOSITION | MF_SEPARATOR,
+ 0,
+ NULL);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"InsertMenu failed!\n"));
+ }
+ else
+ {
+ ++cSeparators;
+ }
+ }
+
+
+ //
+ // Now check if the menu is empty. If it is, use a "<<No operations
+ // allowed>>" string
+ //
+
+ if (0 == GetMenuItemCount(hmenuVol))
+ {
+ TCHAR Buffer[MAX_RESOURCE_STRING_LEN];
+
+ LoadString(
+ g_hInstance,
+ IDS_NOOPERATIONS,
+ Buffer,
+ ARRAYLEN(Buffer));
+
+ f = AppendMenu(hmenuVol, MF_STRING, IDM_NOVALIDOPERATION, Buffer);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+
+ //
+ // Display the menu
+ //
+
+ DoContextMenu(hmenuVol, ppt);
+
+ //
+ // Destroy the menu
+ //
+
+ f = DestroyMenu(hmenuVol);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"DestroyMenu failed!\n"));
+ }
+}
+
+
+#ifdef WINDISK_EXTENSIONS
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddExtensionItemsToDiskMenu
+//
+// Synopsis: Adds an extension menu item to both the menu bar and the
+// given context menu.
+//
+// Arguments: [hmenuContext] -- context menu to add item to
+// [pMenu] -- pointer to extension menu item
+// [fFlags] -- standard menu flags (probably
+// MF_ENABLED or MF_GRAYED)
+//
+// Returns: Count of items added
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+AddExtensionItemsToDiskMenu(
+ IN HMENU hmenuContext,
+ IN MenuType* pMenu,
+ IN BOOL fFlags
+ )
+{
+ INT i;
+
+ for (i=0; i<pMenu->cMenuItems; i++)
+ {
+ MenuItemType* pItem = &(pMenu->aMenuItems[i]);
+
+ INT id = ContextMenuItems.AllocateId(pItem); //get the ID
+
+ if (-1 == id)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't add '%ws' to context menu\n",
+ pItem->pszMenu
+ ));
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE,
+ "Add '%ws' to context menu as item %d\n",
+ pItem->pszMenu,
+ (UINT)id
+ ));
+
+ BOOL f = AppendMenu(
+ hmenuContext,
+ MF_STRING | fFlags,
+ (UINT)id,
+ pItem->pszMenu);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+ }
+
+ return pMenu->cMenuItems;
+}
+
+#endif // WINDISK_EXTENSIONS
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DiskContextMenu, public
+//
+// Synopsis: Create a context menu for a disk selection
+//
+// Arguments: [ppt] -- ptr to screen coordinates of point to put
+// context menu at
+//
+// Returns: nothing?
+//
+// History: 24-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+DiskContextMenu(
+ IN PPOINT ppt
+ )
+{
+ //BUGBUG: no disk context menu will be allowed until we have an
+ // interesting operation to perform
+ return;
+
+//BUGBUG!!!!!!!!!!!!!!!!!
+#if 0
+
+ ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+
+ daDebugOut((DEB_ITRACE,"Disk context menu for disk %d\n", LBIndexToDiskNumber(g_MouseLBIndex)));
+
+#ifdef WINDISK_EXTENSIONS
+ ContextMenuItems.DeAllocateMenuIds(); // get rid of what we had last time
+#endif // WINDISK_EXTENSIONS
+
+ BOOL f;
+ BOOL fAnyHardDiskExtensionItems = FALSE;
+
+ //
+ // Create the menu
+ //
+
+ HMENU hmenuDisk = CreatePopupMenu();
+
+ if (NULL == hmenuDisk)
+ {
+ daDebugOut((DEB_ERROR,"CreatePopupMenu failed!\n"));
+ return;
+ }
+
+ // add the hard disk specific items
+
+////////////////////////////////////////////////////////////////////////
+
+#ifdef WINDISK_EXTENSIONS
+
+ //
+ // Add hard disk operations
+ //
+
+ PHARDDISK_CLAIM_LIST hdclaims = DiskArray[LBIndexToDiskNumber(g_MouseLBIndex)]->pClaims;
+
+ if (NULL != hdclaims)
+ {
+ fAnyHardDiskExtensionItems = TRUE;
+ }
+
+ while (NULL != hdclaims)
+ {
+ AddExtensionItemsToDiskMenu(
+ hmenuDisk,
+ &(hdclaims->pClaimer->pInfo->mnuOps),
+ MF_ENABLED
+ );
+
+ hdclaims = hdclaims->pNext;
+ }
+
+#endif // WINDISK_EXTENSIONS
+
+ //
+ // append the "Properties..." entry
+ //
+
+ TCHAR szText[MAXMENUTEXTLEN];
+
+ if (0 != LoadString(
+ g_hInstance,
+ IDS_PROPERTIES,
+ szText,
+ ARRAYLEN(szText)))
+ {
+ if (fAnyHardDiskExtensionItems)
+ {
+ f = AppendMenu(hmenuDisk, MF_SEPARATOR, 0, NULL);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+
+ f = AppendMenu(
+ hmenuDisk,
+ MF_STRING | MF_DISABLED, //BUGBUG: disable disk property sheet
+ IDM_PROPERTIES,
+ szText
+ );
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+
+ //
+ // if there's nothing on the menu, say "<< no operations >>"
+ //
+
+ if (0 == GetMenuItemCount(hmenuDisk))
+ {
+ TCHAR Buffer[MAX_RESOURCE_STRING_LEN];
+
+ LoadString(
+ g_hInstance,
+ IDS_NOOPERATIONS,
+ Buffer,
+ ARRAYLEN(Buffer));
+
+ f = AppendMenu(hmenuDisk, MF_STRING | MF_DISABLED, 0, Buffer);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+ }
+
+ //
+ // Display the menu
+ //
+
+ DoContextMenu(hmenuDisk, ppt);
+
+ //
+ // Destroy the menu
+ //
+
+ f = DestroyMenu(hmenuDisk);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"DestroyMenu failed!\n"));
+ }
+
+//BUGBUG!!!!!!!!!!
+#endif //0
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: HitTestLegend
+//
+// Synopsis: See if the point is in the legend space
+//
+// Arguments: [ppt] -- ptr to client coordinates of point
+//
+// Returns: TRUE if point is in legend area
+//
+// History: 31-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+HitTestLegend(
+ IN PPOINT ppt
+ )
+{
+ if (!g_Legend || (g_WhichView == VIEW_VOLUMES))
+ {
+ return FALSE;
+ }
+
+ POINT pt = *ppt;
+
+ RECT rc;
+ GetClientRect(g_hwndFrame,&rc);
+
+ if (g_StatusBar)
+ {
+ rc.bottom -= g_dyStatus;
+ }
+
+ rc.top = rc.bottom - g_dyLegend;
+
+ return PtInRect(&rc, pt);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: LegendContextMenu, public
+//
+// Synopsis: Create a context menu to invoke the colors and patterns
+// options menu
+//
+// Arguments: [ppt] -- ptr to screen coordinates of point to put
+// context menu at
+//
+// Returns: nothing?
+//
+// History: 31-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+LegendContextMenu(
+ IN PPOINT ppt
+ )
+{
+ BOOL f;
+
+ //
+ // Create the menu
+ //
+
+ HMENU hmenu = CreatePopupMenu();
+
+ if (NULL == hmenu)
+ {
+ daDebugOut((DEB_ERROR,"CreatePopupMenu failed!\n"));
+ return;
+ }
+
+ f = MyAppendMenu(hmenu, IDM_OPTIONSCOLORS);
+
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"AppendMenu failed!\n"));
+ }
+
+ //
+ // Display the menu
+ //
+
+ DoContextMenu(hmenu, ppt);
+
+ //
+ // Destroy the menu
+ //
+
+ f = DestroyMenu(hmenu);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,"DestroyMenu failed!\n"));
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ContextMenu, public
+//
+// Synopsis: Create a context menu. Determines which type of context
+// menu should be displayed, based on the current selection.
+// The selection variables (SelectionCount, SelectDS, SelectRG)
+// must be valid.
+//
+// Arguments: [ppt] -- pointer to a point (in screen coordinates) for
+// the upper-left corner of the menu
+//
+// Returns: -1 if nothing chosen, or the 0-based index of the item selected
+//
+// History: 22-Jun-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+ContextMenu(
+ IN PPOINT ppt
+ )
+{
+ //
+ // At this point, the selection state is already determined. Use
+ // the selection to determine which context menu is appropriate to
+ // invoke.
+ //
+
+ if (0 == SelectionCount + CdRomCount)
+ {
+ return; // nothing selected, so no context menu
+ }
+
+ VolumeContextMenu(ppt);
+}
diff --git a/private/utils/windisk/src/cm.hxx b/private/utils/windisk/src/cm.hxx
new file mode 100644
index 000000000..329a3512d
--- /dev/null
+++ b/private/utils/windisk/src/cm.hxx
@@ -0,0 +1,37 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cm.hxx
+//
+// Contents: Context menu headers
+//
+// History: 31-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CM_HXX__
+#define __CM_HXX__
+
+VOID
+DiskContextMenu(
+ IN PPOINT ppt
+ );
+
+VOID
+LegendContextMenu(
+ IN PPOINT ppt
+ );
+
+BOOL
+HitTestLegend(
+ IN PPOINT ppt
+ );
+
+VOID
+ContextMenu(
+ IN PPOINT ppt
+ );
+
+#endif // __CM_HXX__
diff --git a/private/utils/windisk/src/commit.cxx b/private/utils/windisk/src/commit.cxx
new file mode 100644
index 000000000..8ca57df8c
--- /dev/null
+++ b/private/utils/windisk/src/commit.cxx
@@ -0,0 +1,1849 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: commit.cxx
+//
+// Contents: This module contains the set of routines that support
+// the commitment of changes to disk without rebooting.
+//
+// History: 15-Nov-93 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+extern "C"
+{
+#include <ntddcdrm.h>
+
+#pragma warning(4:4091)
+#include <ntddscsi.h>
+#pragma warning(default:4091)
+}
+
+#include "commit.hxx"
+#include "drives.hxx"
+#include "ft.hxx"
+#include "init.hxx"
+#include "nt.hxx"
+#include "fill.hxx"
+#include "network.hxx"
+#include "ntlow.hxx"
+#include "ops.hxx"
+#include "scsi.h"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN CommitDueToDelete = FALSE;
+BOOLEAN CommitDueToMirror = FALSE;
+BOOLEAN CommitDueToExtended = FALSE;
+BOOLEAN CommitDueToCreate = FALSE;
+
+// If a mirror is made of the boot partition, this will become
+// non-zero and indicate which disk should get some boot code in
+// the MBR.
+
+ULONG UpdateMbrOnDisk = 0;
+
+// Lock list chain head for deleted partitions.
+
+PDRIVE_LOCKLIST DriveLockListHead = NULL;
+
+PASSIGN_LIST AssignDriveLetterListHead = NULL;
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern HANDLE DisplayMutex;
+extern ULONG DisplayUpdateCount;
+extern DWORD RefreshAllowed;
+
+VOID
+CommitToAssignLetterList(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN BOOLEAN MoveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Remember this region for assigning a drive letter to it upon commit.
+
+Arguments:
+
+ RegionDescriptor - the region to watch
+ MoveLetter - indicate that the region letter is already
+ assigned to a different partition, therefore
+ it must be "moved".
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PASSIGN_LIST newListEntry;
+ PPERSISTENT_REGION_DATA regionData;
+
+ regionData = PERSISTENT_DATA(RegionDescriptor);
+ FDASSERT(NULL != regionData);
+
+ newListEntry = (PASSIGN_LIST) Malloc(sizeof(ASSIGN_LIST));
+
+ newListEntry->OriginalLetter = regionData->DriveLetter;
+ newListEntry->DriveLetter = regionData->DriveLetter;
+ newListEntry->DiskNumber = RegionDescriptor->Disk;
+ newListEntry->MoveLetter = MoveLetter;
+
+ // place it at the front of the chain.
+
+ newListEntry->Next = AssignDriveLetterListHead;
+ AssignDriveLetterListHead = newListEntry;
+}
+
+VOID
+CommitAssignLetterList(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Walk the assign drive letter list and make all drive letter assignments
+ expected. The regions data structures are moved around, so no pointer
+ can be maintained to look at them. To determine the partition number
+ for a new partition in this list, the Disks[] structure must be searched
+ to find a match on the partition for the drive letter. Then the partition
+ number will be known.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+ PDISKSTATE diskState;
+ PASSIGN_LIST assignList,
+ prevEntry;
+ WCHAR newDriveName[3];
+ WCHAR targetPath[100];
+ ULONG partitionNumber;
+ ULONG index;
+
+ assignList = AssignDriveLetterListHead;
+ AssignDriveLetterListHead = NULL;
+ while (NULL != assignList)
+ {
+ diskState = DiskArray[assignList->DiskNumber];
+ partitionNumber = 0;
+ for (index = 0; index < diskState->RegionCount; index++)
+ {
+ regionDescriptor = &diskState->RegionArray[index];
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (NULL != regionData)
+ {
+ if (regionData->DriveLetter == assignList->DriveLetter)
+ {
+ partitionNumber = regionDescriptor->Reserved->Partition->PartitionNumber;
+ regionDescriptor->PartitionNumber = partitionNumber;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!IsExtraDriveLetter(assignList->DriveLetter)) {
+
+ if (0 != partitionNumber)
+ {
+ HANDLE handle;
+ ULONG status;
+
+ // first, fix up drive letter data structures
+
+ if (assignList->MoveLetter)
+ {
+ MarkDriveLetterFree(assignList->OriginalLetter);
+ }
+
+ NewDriveLetter(
+ assignList->DriveLetter,
+ assignList->DiskNumber,
+ partitionNumber);
+
+ // now, do the NT object stuff
+
+ // set up the new NT path.
+
+ wsprintf(targetPath,
+ TEXT("%hs\\Partition%d"),
+ GetDiskName(assignList->DiskNumber),
+ partitionNumber);
+
+ newDriveName[1] = L':';
+ newDriveName[2] = L'\0';
+
+ if (assignList->MoveLetter)
+ {
+ // The letter must be removed before it can be assigned.
+
+ newDriveName[0] = assignList->OriginalLetter;
+ NetworkRemoveShare(newDriveName);
+ DefineDosDevice(DDD_REMOVE_DEFINITION, newDriveName, NULL);
+ }
+
+ newDriveName[0] = assignList->DriveLetter;
+
+ // Assign the name - don't worry about errors for now.
+
+ DefineDosDevice(DDD_RAW_TARGET_PATH, newDriveName, targetPath);
+ NetworkShare(newDriveName);
+
+ // Some of the file systems do not actually dismount
+ // when requested. Instead, they set a verification
+ // bit in the device object. Due to dynamic partitioning
+ // this bit may get cleared by the process of the
+ // repartitioning and the file system will then
+ // assume it is still mounted on a new access.
+ // To get around this problem, new drive letters
+ // are always locked and dismounted on creation.
+
+ status = LowOpenDriveLetter(assignList->DriveLetter,
+ &handle);
+
+ if (NT_SUCCESS(status))
+ {
+ // Lock the drive to insure that no other access is occurring
+ // to the volume.
+
+ status = LowLockDrive(handle);
+
+ if (NT_SUCCESS(status))
+ {
+ LowUnlockDrive(handle);
+ }
+ LowCloseDisk(handle);
+ }
+ }
+ else
+ {
+ ErrorDialog(MSG_INTERNAL_LETTER_ASSIGN_ERROR);
+ }
+ }
+
+ prevEntry = assignList;
+ assignList = assignList->Next;
+ Free(prevEntry);
+ }
+}
+
+
+LONG
+CommitInternalLockDriveLetter(
+ IN PDRIVE_LOCKLIST LockListEntry
+ )
+
+/*++
+
+Routine Description:
+
+ Support routine to perform the locking of a drive letter based on
+ the locklist entry given.
+
+Arguments:
+
+ LockListEntry - The information about what to lock.
+
+Return Values:
+
+ zero - success
+ non-zero failure
+
+--*/
+
+{
+ ULONG status;
+
+ // Lock the disk and save the handle.
+
+ status = LowOpenDriveLetter(LockListEntry->DriveLetter, &LockListEntry->LockHandle);
+
+ if (!NT_SUCCESS(status))
+ {
+ return 1;
+ }
+
+
+ // Lock the drive to insure that no other access is occurring
+ // to the volume.
+
+ status = LowLockDrive(LockListEntry->LockHandle);
+
+ if (!NT_SUCCESS(status))
+ {
+ LowCloseDisk(LockListEntry->LockHandle);
+ return 1;
+ }
+
+ LockListEntry->CurrentlyLocked = TRUE;
+ return 0;
+}
+
+
+VOID
+CommitNewRegions(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This converts all regions to be non-new regions after a commit. It
+ redraws the screen to reflect the commit.
+
+Arguments:
+
+ None.
+
+Return Values:
+
+ None.
+
+--*/
+
+{
+ ULONG diskNum;
+ ULONG regionNum;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+
+ for (diskNum = 0; diskNum < DiskCount; diskNum++)
+ {
+ diskState = DiskArray[diskNum];
+
+ for (regionNum = 0; regionNum < diskState->RegionCount; regionNum++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionNum];
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (NULL != regionDescriptor->Reserved)
+ {
+ if (NULL != regionDescriptor->Reserved->Partition)
+ {
+ regionDescriptor->Reserved->Partition->CommitMirrorBreakNeeded = FALSE;
+ }
+ }
+
+ if (NULL != regionData)
+ {
+ if (regionData->NewRegion)
+ {
+ regionData->NewRegion = FALSE;
+ }
+ }
+ }
+ }
+
+ //
+ // Now, refresh the views. The visualization of non-new regions is
+ // different from that of new regions, so we need to redraw.
+ //
+
+ RefreshBothViews();
+}
+
+
+LONG
+CommitToLockList(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN BOOL RemoveDriveLetter,
+ IN BOOL LockNow,
+ IN BOOL FailOk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds the given drive into the lock list for processing
+ when a commit occurs. If the LockNow flag is set it indicates that
+ the drive letter is to be immediately locked if it is to go in the
+ lock letter list. If this locking fails an error is returned.
+
+Arguments:
+
+ RegionDescriptor - the region for the drive to lock.
+ RemoveDriveLetter - remove the letter when performing the unlock.
+ LockNow - If the letter is inserted in the list - lock it now.
+ FailOk - It is ok to fail the lock - used for disabled FT sets.
+
+Return Values:
+
+ non-zero - failure to add to list.
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ PDRIVE_LOCKLIST lockListEntry;
+ WCHAR driveLetter;
+ ULONG diskNumber;
+
+ if (NULL == regionData)
+ {
+ // without region data there is no need to be on the lock list.
+
+ return 0;
+ }
+
+ // See if this drive letter is already in the lock list.
+
+ driveLetter = regionData->DriveLetter;
+
+ if (IsExtraDriveLetter(driveLetter))
+ {
+ // There is no drive letter to lock.
+
+ CommitDueToDelete = RemoveDriveLetter;
+ return 0;
+ }
+
+ if (regionData->NewRegion)
+ {
+ PASSIGN_LIST assignList, prevEntry;
+
+ // This item has never been created so no need to put it in the
+ // lock list. But it does need to be removed from the assign
+ // letter list.
+
+ prevEntry = NULL;
+ assignList = AssignDriveLetterListHead;
+ while (NULL != assignList)
+ {
+ // If a match is found remove it from the list.
+
+ if (assignList->DriveLetter == driveLetter)
+ {
+
+ //
+ // Free up the drive letter to be used. (Normally done
+ // in the final commit code.)
+ //
+
+ MarkDriveLetterFree(driveLetter);
+
+ if (NULL != prevEntry)
+ {
+ prevEntry->Next = assignList->Next;
+ }
+ else
+ {
+ AssignDriveLetterListHead = assignList->Next;
+ }
+
+ Free(assignList);
+ assignList = NULL;
+ }
+ else
+ {
+ prevEntry = assignList;
+ assignList = assignList->Next;
+ }
+ }
+ return 0;
+ }
+
+ diskNumber = RegionDescriptor->Disk;
+ lockListEntry = DriveLockListHead;
+ while (NULL != lockListEntry)
+ {
+ if (lockListEntry->DriveLetter == driveLetter)
+ {
+ // Already in the list -- update when to lock and unlock
+
+ if (diskNumber < lockListEntry->LockOnDiskNumber)
+ {
+ lockListEntry->LockOnDiskNumber = diskNumber;
+ }
+
+ if (diskNumber > lockListEntry->UnlockOnDiskNumber)
+ {
+ lockListEntry->UnlockOnDiskNumber = diskNumber;
+ }
+
+ // Already in the lock list and information for locking set up.
+ // Check to see if this should be a LockNow request.
+
+ if (LockNow)
+ {
+ if (!lockListEntry->CurrentlyLocked)
+ {
+ // Need to perform the lock.
+
+ if (CommitInternalLockDriveLetter(lockListEntry))
+ {
+ // Leave the element in the list
+
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+ }
+ lockListEntry = lockListEntry->Next;
+ }
+
+ // set up the lock list entry.
+
+ lockListEntry = (PDRIVE_LOCKLIST) Malloc(sizeof(DRIVE_LOCKLIST));
+
+ lockListEntry->LockHandle = NULL;
+ lockListEntry->PartitionNumber = RegionDescriptor->PartitionNumber;
+ lockListEntry->DriveLetter = driveLetter;
+ lockListEntry->RemoveOnUnlock = RemoveDriveLetter;
+ lockListEntry->FailOk = FailOk;
+ lockListEntry->CurrentlyLocked = FALSE;
+ lockListEntry->DiskNumber
+ = lockListEntry->UnlockOnDiskNumber
+ = lockListEntry->LockOnDiskNumber
+ = diskNumber;
+
+ if (LockNow)
+ {
+ if (CommitInternalLockDriveLetter(lockListEntry))
+ {
+ // Do not add this to the list.
+
+ Free(lockListEntry);
+ return 1;
+ }
+ }
+
+ // place it at the front of the chain.
+
+ lockListEntry->Next = DriveLockListHead;
+ DriveLockListHead = lockListEntry;
+ return 0;
+}
+
+LONG
+CommitLockVolumes(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will go through any drive letters inserted in the lock list
+ for the given disk number and attempt to lock the volumes.
+
+ Currently, this routine locks all of the drives letters in the lock list
+ when called the first time (i.e. when Disk == 0).
+
+Arguments:
+
+ Disk - the index into the disk table.
+
+Return Values:
+
+ non-zero - failure to lock the items in the list.
+
+--*/
+
+{
+ PDRIVE_LOCKLIST lockListEntry;
+
+ if (0 != Disk)
+ {
+ return 0;
+ }
+
+ for (lockListEntry = DriveLockListHead;
+ NULL != lockListEntry;
+ lockListEntry = lockListEntry->Next)
+ {
+ // Lock the disk. Return on any failure if that is the
+ // requested action for the entry. It is the responsibility
+ // of the caller to release any successful locks.
+
+ if (!lockListEntry->CurrentlyLocked)
+ {
+ if (CommitInternalLockDriveLetter(lockListEntry))
+ {
+ if (!lockListEntry->FailOk)
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+LONG
+CommitUnlockVolumes(
+ IN ULONG Disk,
+ IN BOOLEAN FreeList
+ )
+
+/*++
+
+Routine Description:
+
+ Go through and unlock any locked volumes in the locked list for the
+ given disk.
+
+ Currently this routine waits until the last disk has been processed,
+ then unlocks all disks.
+
+Arguments:
+
+ Disk - the index into the disk table.
+ FreeList - Clean up the list as unlocks are performed or don't
+
+Return Values:
+
+ non-zero - failure to lock the items in the list.
+
+--*/
+
+{
+ PDRIVE_LOCKLIST lockListEntry,
+ previousLockListEntry;
+ WCHAR driveName[3];
+
+ if (Disk != GetDiskCount())
+ {
+ return 0;
+ }
+
+ lockListEntry = DriveLockListHead;
+ if (FreeList)
+ {
+ DriveLockListHead = NULL;
+ }
+
+ while (NULL != lockListEntry)
+ {
+ // Unlock the disk.
+
+ if (lockListEntry->CurrentlyLocked)
+ {
+ if (FreeList && lockListEntry->RemoveOnUnlock)
+ {
+ // set up the new dos name and NT path.
+
+ driveName[0] = lockListEntry->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ NetworkRemoveShare(driveName);
+ if (!DefineDosDevice(DDD_REMOVE_DEFINITION, driveName, NULL))
+ {
+ // could not remove name!!?
+ } else {
+
+ //
+ // We only mark the drive letter free after everything has
+ // been committed.
+ //
+
+ MarkDriveLetterFree(lockListEntry->DriveLetter);
+ }
+ }
+
+ LowUnlockDrive(lockListEntry->LockHandle);
+ LowCloseDisk(lockListEntry->LockHandle);
+ }
+
+ // Move to the next entry. If requested free this entry.
+
+ previousLockListEntry = lockListEntry;
+ lockListEntry = lockListEntry->Next;
+ if (FreeList)
+ {
+ Free(previousLockListEntry);
+ }
+ }
+ return 0;
+}
+
+
+BOOL
+CommitDriveLetter(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN WCHAR OldLetter,
+ IN WCHAR NewLetter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will update the drive letter information in the registry and
+ (if the update works) it will attempt to move the current drive letter
+ to the new one via DefineDosDevice()
+
+Arguments:
+
+ RegionDescriptor - the region that should get the letter.
+ OldLetter - the old drive letter for the volume.
+ NewLetter - the new drive letter for the volume.
+
+Return Value:
+
+ TRUE - if the assigning of the letter and the update of the
+ registry succeed.
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData;
+ PDRIVE_LOCKLIST lockListEntry;
+ PASSIGN_LIST assignList;
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ WCHAR driveName[3];
+ WCHAR targetPath[100];
+ int doIt;
+ BOOL result = FALSE;
+ STATUS_CODE status = ERROR_SEVERITY_ERROR;
+ BOOL changingBootDir = FALSE;
+ BOOL changingSystemDir = FALSE;
+
+ //
+ // Check if the old drive letter is the boot drive and the
+ // new drive letter is nothing. If it is, don't allow
+ // them to do that.
+ //
+
+ if ((OldLetter == BootDir) &&
+ (NewLetter == NO_DRIVE_LETTER_EVER)) {
+
+ ErrorDialog(MSG_BOOT_NEEDS_LETTER);
+ return FALSE;
+
+ }
+
+ //
+ // Check if the old drive letter points to the systemdir and
+ // the new drive letter is nothing. Don't let them do that.
+ //
+ // On x86 it is 99% certain to have been caught above.
+ //
+
+ if ((OldLetter == SystemDir) &&
+ (NewLetter == NO_DRIVE_LETTER_EVER)) {
+
+ ErrorDialog(MSG_SYS_NEEDS_LETTER);
+ return FALSE;
+
+ }
+
+
+
+ //
+ // Check if the old drive letter is the system drive. If it
+ // is put up a popup that says we don't think this is a very
+ // good idea.
+ //
+
+ if (OldLetter == SystemDir) {
+
+ doIt = ConfirmationDialog(
+ MSG_SYS_LETTER_CHANGE,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
+
+ if (doIt != IDYES) {
+
+ return FALSE;
+
+ }
+ changingSystemDir = TRUE;
+ }
+
+ changingBootDir = OldLetter == BootDir;
+
+
+ regionData = PERSISTENT_DATA(RegionDescriptor);
+ FDASSERT(NULL != regionData);
+
+ // check the assign letter list for a match.
+ // If the letter is there, then just update the list
+ // otherwise continue on with the action.
+
+ assignList = AssignDriveLetterListHead;
+ while (NULL != assignList)
+ {
+ if (assignList->DriveLetter == OldLetter)
+ {
+ assignList->DriveLetter = NewLetter;
+
+ // Change the drive letter data
+
+ MarkDriveLetterFree(OldLetter);
+ NewDriveLetter(
+ NewLetter,
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber);
+ WaitForSingleObject(DisplayMutex,INFINITE);
+ RefreshAllowed = 1;
+ ReleaseMutex(DisplayMutex);
+ DrawDiskBar(DiskArray[RegionDescriptor->Disk]);
+ return TRUE;
+ }
+ assignList = assignList->Next;
+ }
+
+// daDebugOut((DEB_ERROR,
+// "A new region didn't appear in the 'assign drive letter' list\n"));
+
+ //
+ // Search to see if the drive is currently locked.
+ //
+
+ for (lockListEntry = DriveLockListHead;
+ lockListEntry;
+ lockListEntry = lockListEntry->Next)
+ {
+ if ( (lockListEntry->DiskNumber == RegionDescriptor->Disk)
+ && (lockListEntry->PartitionNumber == RegionDescriptor->PartitionNumber))
+ {
+ if (lockListEntry->CurrentlyLocked)
+ {
+ status = 0;
+ }
+
+ // found the match no need to continue searching.
+
+ break;
+ }
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ // See if the drive can be locked.
+
+ status = LowOpenPartition(GetDiskName(RegionDescriptor->Disk),
+ RegionDescriptor->PartitionNumber,
+ &handle);
+
+ if (!NT_SUCCESS(status))
+ {
+ return FALSE;
+ }
+
+ // Lock the drive to insure that no other access is occurring
+ // to the volume.
+
+ status = LowLockDrive(handle);
+
+ if (!NT_SUCCESS(status))
+ {
+ LowCloseDisk(handle);
+
+ if (IsPagefileOnDrive(OldLetter))
+ {
+ ErrorDialog(MSG_CANNOT_LOCK_PAGEFILE);
+ }
+ else
+ {
+ ErrorDialog(MSG_CANNOT_LOCK_TRY_AGAIN);
+ }
+
+ doIt = ConfirmationDialog(
+ MSG_SCHEDULE_REBOOT,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
+
+ if (doIt == IDYES)
+ {
+ RegistryChanged = TRUE;
+ RestartRequired = TRUE;
+
+ // mark the new letter as used, but don't mark the old letter
+ // as free (since it is still currently in use)
+
+ NewDriveLetter(
+ NewLetter,
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ // This drive was found in the lock list and is already
+ // in the locked state. It is safe to continue with
+ // the drive letter assignment.
+
+ //
+ // Note that we DON'T have a valid handle. So if things
+ // don't go well, DON'T try to free it.
+ //
+
+ }
+
+ if (!RegionDescriptor->PartitionNumber) {
+
+ ErrorDialog(MSG_INTERNAL_LETTER_ASSIGN_ERROR);
+ if (handle != INVALID_HANDLE_VALUE) {
+
+ LowUnlockDrive(handle);
+ LowCloseDisk(handle);
+
+ }
+ return FALSE;
+
+ }
+
+ // Warn the user that the rename will happen immediately, and confirm
+ // that it is ok to perform the rename.
+
+ doIt = ConfirmationDialog(
+ MSG_DRIVE_RENAME_WARNING,
+ MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2);
+
+ if (doIt != IDYES)
+ {
+ if (handle != INVALID_HANDLE_VALUE) {
+
+ LowUnlockDrive(handle);
+ LowCloseDisk(handle);
+ return FALSE;
+
+ }
+ }
+
+ // Update the registry first. This way if something goes wrong
+ // the new letter will arrive on reboot.
+
+ if (!DiskRegistryAssignDriveLetter(
+ DiskArray[RegionDescriptor->Disk]->Signature,
+ FdGetExactOffset(RegionDescriptor),
+ FdGetExactSize(RegionDescriptor, FALSE),
+ (NewLetter == NO_DRIVE_LETTER_EVER)
+ ? (UCHAR)' '
+ : (UCHAR)NewLetter))
+ {
+ // Registry update failed.
+
+ return FALSE;
+ }
+
+ // It is safe to change the drive letter. First, remove the
+ // existing letter.
+
+ driveName[0] = OldLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ NetworkRemoveShare(driveName);
+ if (!DefineDosDevice(DDD_REMOVE_DEFINITION, driveName, NULL))
+ {
+
+ if (handle != INVALID_HANDLE_VALUE) {
+
+ LowUnlockDrive(handle);
+ LowCloseDisk(handle);
+
+ }
+ RegistryChanged = TRUE;
+ return FALSE;
+ }
+
+ MarkDriveLetterFree(OldLetter);
+
+ result = FALSE;
+
+ if (NewLetter != NO_DRIVE_LETTER_EVER)
+ {
+ // set up the new dos name and NT path.
+
+ wsprintf(targetPath,
+ TEXT("%hs\\Partition%d"),
+ GetDiskName(RegionDescriptor->Disk),
+ RegionDescriptor->PartitionNumber);
+
+ driveName[0] = NewLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ if (DefineDosDevice(DDD_RAW_TARGET_PATH, driveName, targetPath))
+ {
+ result = TRUE;
+
+ if (changingSystemDir) {
+
+ SystemDir = NewLetter;
+
+ }
+
+ if (changingBootDir) {
+
+ WCHAR driveLetterBuffer[MAX_PATH+1] = {(WCHAR)0};
+ UNICODE_STRING driveLetterString;
+
+ RTL_QUERY_REGISTRY_TABLE driveLetterTable[2] = {0};
+
+ driveLetterString.Length = 0;
+ driveLetterString.MaximumLength = sizeof(WCHAR)*MAX_PATH;
+ driveLetterString.Buffer = (PWCHAR)&driveLetterBuffer[0];
+ driveLetterTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
+ RTL_QUERY_REGISTRY_REQUIRED;
+ driveLetterTable[0].Name = L"BootDir";
+ driveLetterTable[0].EntryContext = &driveLetterString;
+
+ if (NT_SUCCESS(RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ L"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\SETUP",
+ &driveLetterTable[0],
+ NULL,
+ NULL
+ ))) {
+
+ driveLetterBuffer[0] = NewLetter;
+
+ RtlWriteRegistryValue(
+ RTL_REGISTRY_ABSOLUTE,
+ L"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\SETUP",
+ L"BootDir",
+ REG_SZ,
+ &driveLetterBuffer[0],
+ driveLetterString.Length+sizeof(WCHAR)
+ );
+
+ BootDir = NewLetter;
+ }
+ }
+ }
+ else
+ {
+ RegistryChanged = TRUE;
+ }
+ NetworkShare(driveName);
+
+ NewDriveLetter(
+ NewLetter,
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber);
+ }
+ else
+ {
+ //
+ // If we don't need to assign a drive letter, then don't do anything
+ //
+
+ result = TRUE;
+ }
+
+ // Force the file system to dismount
+
+ if (handle != INVALID_HANDLE_VALUE) {
+
+ LowUnlockDrive(handle);
+ LowCloseDisk(handle);
+
+ }
+ return result;
+}
+
+
+DWORD
+CommitChanges(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine updates the disks to reflect changes made by the user
+ the partitioning scheme, or to stamp signatures on disks.
+
+ If the partitioning scheme on a disk has changed at all, a check will
+ first be made for a valid signature on the mbr in sector 0. If the
+ signature is not valid, x86 boot code will be written to the sector.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Windows error code
+
+--*/
+
+{
+ UINT i;
+ DWORD ec;
+ DWORD rc = NO_ERROR;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ if (HavePartitionsBeenChanged(i))
+ {
+ ec = MasterBootCode(i, 0, TRUE, FALSE);
+
+ // MasterBootCode has already translated the NT error
+ // status into a Windows error status.
+
+ if (rc == NO_ERROR)
+ {
+ rc = ec; // save first non-success return code
+ }
+
+ ec = CommitPartitionChanges(i);
+
+ // CommitPartitionChanges returns a native NT error, it
+ // must be translated before it can be saved.
+
+ if (ec != NO_ERROR) {
+ ec = RtlNtStatusToDosError(ec);
+ }
+ if (rc == NO_ERROR)
+ {
+ rc = ec; // save first non-success return code
+ }
+ }
+ }
+ if (rc != NO_ERROR)
+ {
+ // If CommitPartitionChanges returns an error, it will be
+ // an NT status, which needs to be converted to a DOS status.
+ //
+ rc = RtlNtStatusToDosError(rc);
+
+ if (rc == ERROR_MR_MID_NOT_FOUND)
+ {
+ ErrorDialog(MSG_ERROR_DURING_COMMIT);
+ }
+ else
+ {
+ ErrorDialog(rc);
+ }
+ }
+
+ return rc;
+}
+
+
+UINT
+CommitAllChanges(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will go through all of the region descriptors and commit
+ any changes that have occurred to disk. Then it "re-initializes"
+ Disk Administrator and start the display/work process over again.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ 0 -- the user chose to cancel the commit operation
+ 1 -- the commit operation happened (either things were committed or the
+ user chose not to save changes) and the profile was written, but
+ we couldn't reboot
+ 2 -- the commit operation happened (either things were committed or the
+ user chose not to save changes) and the profile was NOT written
+
+--*/
+
+{
+ DWORD action,
+ errorCode;
+ ULONG diskNum,
+ diskCount;
+ BOOL profileWritten,
+ changesMade,
+ mustReboot,
+ configureFt;
+
+ // Determine whether any disks have been changed, and whether
+ // the system must be rebooted. The system must be rebooted
+ // if the registry has changed, if any non-removable disk has
+ // changed, or if any removable disk that was not originally
+ // unpartitioned has changed.
+
+ configureFt = FALSE;
+ changesMade = FALSE;
+ mustReboot = RestartRequired;
+ diskCount = GetDiskCount();
+
+ for (diskNum = 0; diskNum < diskCount; diskNum++)
+ {
+ if (HavePartitionsBeenChanged(diskNum))
+ {
+ changesMade = TRUE;
+ break;
+ }
+ }
+
+ profileWritten = FALSE;
+
+ // Determine if the commit can be done without a reboot.
+
+ // If FT is in the system then it must be notified to
+ // reconfigure if a reboot is not performed. If it is
+ // not in the system, but the new disk information requires
+ // it, then a reboot must be forced.
+
+ if (FtInstalled())
+ {
+ configureFt = TRUE;
+ }
+
+ if (NewConfigurationRequiresFt())
+ {
+ if (!configureFt)
+ {
+ // The FT driver is not loaded currently.
+
+ mustReboot = TRUE;
+ }
+ else
+ {
+ // If the system is going to be rebooted, don't
+ // have FT reconfigure prior to shutdown.
+
+ if (mustReboot)
+ {
+ configureFt = FALSE;
+ }
+ }
+ }
+
+ if (RegistryChanged || changesMade || RestartRequired)
+ {
+ //
+ // BUGBUG: if we must reboot, then say so.
+ //
+
+ if (RestartRequired)
+ {
+ action = IDYES;
+ }
+ else
+ {
+ action = ConfirmationDialog(
+ MSG_CONFIRM_EXIT,
+ MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON2);
+ }
+
+ if (action == IDYES)
+ {
+ errorCode = CommitLockVolumes(0);
+ if (errorCode)
+ {
+ // could not lock all volumes
+
+ ErrorDialog(MSG_CANNOT_LOCK_FOR_COMMIT);
+ CommitUnlockVolumes(diskCount, FALSE);
+ return 0;
+ }
+
+ if (mustReboot)
+ {
+ if (!RestartRequired)
+ {
+ action = ConfirmationDialog(
+ MSG_REQUIRE_REBOOT,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
+ if (action == IDNO)
+ {
+ CommitUnlockVolumes(diskCount, FALSE);
+ return 0;
+ }
+ }
+ }
+
+ SetCursor(g_hCurWait);
+ errorCode = CommitChanges();
+ CommitUnlockVolumes(diskCount, TRUE);
+ SetCursor(g_hCurNormal);
+
+ if (errorCode != NO_ERROR)
+ {
+ ErrorDialog(MSG_BAD_CONFIG_SET);
+ PostQuitMessage(0);
+ }
+ else
+ {
+ ULONG oldBootPartitionNumber;
+ ULONG newBootPartitionNumber;
+ DWORD msgCode;
+
+ // Update the configuration registry
+
+ errorCode = SaveFt();
+
+ // Check if FTDISK driver should reconfigure.
+
+ if (configureFt)
+ {
+ // Issue device control to ftdisk driver to reconfigure.
+
+ FtConfigure();
+ }
+
+ // Register autochk to fix up file systems
+ // in newly extended volume sets, if necessary
+
+ if (RegisterFileSystemExtend())
+ {
+ mustReboot = TRUE;
+ }
+
+ // Determine if the FT driver must be enabled.
+
+ if (DiskRegistryRequiresFt())
+ {
+ if (!FtInstalled())
+ {
+ mustReboot = TRUE;
+ }
+ DiskRegistryEnableFt();
+ }
+ else
+ {
+ DiskRegistryDisableFt();
+ }
+
+ if (errorCode == NO_ERROR)
+ {
+ InfoDialog(MSG_OK_COMMIT);
+ }
+ else
+ {
+ ErrorDialog(MSG_BAD_CONFIG_SET);
+ }
+
+ // Has the partition number of the boot partition changed?
+
+ if (BootPartitionNumberChanged(
+ &oldBootPartitionNumber,
+ &newBootPartitionNumber))
+ {
+ WCHAR oldNumberString[8];
+ WCHAR newNumberString[8];
+#if i386
+ msgCode = MSG_BOOT_PARTITION_CHANGED_X86;
+#else
+ msgCode = MSG_BOOT_PARTITION_CHANGED_ARC;
+#endif
+ wsprintf(oldNumberString, L"%d", oldBootPartitionNumber);
+ wsprintf(newNumberString, L"%d", newBootPartitionNumber);
+ InfoDialog(msgCode, oldNumberString, newNumberString);
+ }
+
+ ClearCommittedDiskInformation();
+
+ if (0 != UpdateMbrOnDisk)
+ {
+ UpdateMasterBootCode(UpdateMbrOnDisk);
+ UpdateMbrOnDisk = 0;
+ }
+
+ // Reboot if necessary.
+
+ if (mustReboot)
+ {
+ SetCursor(g_hCurWait);
+ Sleep(5000);
+ SetCursor(g_hCurNormal);
+ FdShutdownTheSystem();
+
+ // If we get here, then the system couldn't be shut
+ // down. However, the profile has already been written,
+ // so don't bother writing it again.
+
+ profileWritten = TRUE;
+ }
+
+ CommitAssignLetterList();
+ CommitNewRegions();
+
+ //
+ // reset this flag: we've committed registry changes
+ //
+
+ RegistryChanged = FALSE;
+
+ CommitDueToDelete = FALSE;
+ CommitDueToMirror = FALSE;
+ CommitDueToExtended = FALSE;
+ CommitDueToCreate = FALSE;
+ }
+ }
+ else if (action == IDCANCEL)
+ {
+ return 0;
+ }
+ else
+ {
+ FDASSERT(action == IDNO);
+ }
+ }
+
+ return (profileWritten ? 1 : 2);
+}
+
+VOID
+FtConfigure(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calls the FTDISK driver to ask it to reconfigure as changes
+ have been made in the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ STRING ntFtName;
+ IO_STATUS_BLOCK statusBlock;
+ UNICODE_STRING unicodeDeviceName;
+ NTSTATUS status;
+ HANDLE handle;
+
+ // Open ft control object.
+
+ RtlInitString(&ntFtName, "\\Device\\FtControl");
+ RtlAnsiStringToUnicodeString(&unicodeDeviceName, &ntFtName, TRUE);
+ InitializeObjectAttributes(&objectAttributes,
+ &unicodeDeviceName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = DmOpenFile(&handle,
+ SYNCHRONIZE | FILE_ANY_ACCESS,
+ &objectAttributes,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ RtlFreeUnicodeString(&unicodeDeviceName);
+
+ if (!NT_SUCCESS(status))
+ {
+ return;
+ }
+
+ // Issue device control to reconfigure FT.
+
+ NtDeviceIoControlFile(handle,
+ NULL,
+ NULL,
+ NULL,
+ &statusBlock,
+ FT_CONFIGURE,
+ NULL,
+ 0L,
+ NULL,
+ 0L);
+
+ DmClose(handle);
+ return;
+}
+
+
+
+BOOL
+CommitAllowed(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determine if it is ok to perform a commit.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if it is ok to commit and there is something to commit
+ FALSE otherwise
+
+--*/
+
+{
+ if ( NULL != DriveLockListHead
+ || NULL != AssignDriveLetterListHead
+ || CommitDueToDelete
+ || CommitDueToMirror
+ || CommitDueToExtended
+ || CommitDueToCreate)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+VOID
+RescanDevices(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs all actions necessary to dynamically rescan
+ device buses (i.e. SCSI) and get the appropriate driver support loaded.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ #define SCSI_INFO_BUFFER_SIZE 0x4000
+
+ PSCSI_ADAPTER_BUS_INFO adapterInfo;
+ PSCSI_BUS_DATA busData;
+ PSCSI_INQUIRY_DATA inquiryData;
+ WCHAR deviceName[32];
+ WCHAR physicalName[32];
+ HANDLE volumeHandle;
+ UNICODE_STRING unicodeString;
+ UNICODE_STRING physicalString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK statusBlock;
+ BOOLEAN diskFound = FALSE;
+ BOOLEAN cdromFound = FALSE;
+ ULONG bytesTransferred;
+ ULONG i, j;
+ ULONG deviceNumber;
+ ULONG currentPort;
+ ULONG numberOfPorts = 0;
+ ULONG percentComplete = 0;
+ ULONG portNumber = 0;
+
+ while (TRUE)
+ {
+ wsprintf(deviceName, TEXT("\\\\.\\Scsi%d:"), portNumber);
+
+ // Open the SCSI port with the DOS name.
+
+ volumeHandle = CreateFile(deviceName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0);
+
+ if (volumeHandle == INVALID_HANDLE_VALUE)
+ {
+ break;
+ }
+
+ CloseHandle(volumeHandle);
+ ++numberOfPorts;
+ ++portNumber;
+ }
+
+ currentPort = 1;
+ portNumber = 0;
+
+ // Perform the scsi bus rescan
+
+ while (TRUE)
+ {
+ wsprintf(deviceName, TEXT("\\\\.\\Scsi%d:"), portNumber);
+
+ // Open the SCSI port with the DOS name.
+
+ volumeHandle = CreateFile(deviceName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0);
+
+ if (volumeHandle == INVALID_HANDLE_VALUE)
+ {
+ break;
+ }
+
+ // Issue rescan device control.
+
+ if (!DeviceIoControl(volumeHandle,
+ IOCTL_SCSI_RESCAN_BUS,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &bytesTransferred,
+ NULL))
+ {
+ CloseHandle(volumeHandle);
+
+ break;
+ }
+
+ percentComplete = (currentPort * 100) / numberOfPorts;
+
+ if (percentComplete < 100)
+ {
+ PostMessage(g_InitDlg, WM_STARTUP_UPDATE, percentComplete, 0);
+ }
+
+ ++currentPort;
+
+ // Get a big chuck of memory to store the SCSI bus data.
+
+ adapterInfo = (PSCSI_ADAPTER_BUS_INFO)(Malloc(SCSI_INFO_BUFFER_SIZE));
+
+ if (adapterInfo == NULL)
+ {
+ CloseHandle(volumeHandle);
+ goto finish;
+ }
+
+ // Issue device control to get configuration information.
+
+ if (!DeviceIoControl(volumeHandle,
+ IOCTL_SCSI_GET_INQUIRY_DATA,
+ NULL,
+ 0,
+ adapterInfo,
+ SCSI_INFO_BUFFER_SIZE,
+ &bytesTransferred,
+ NULL))
+ {
+ CloseHandle(volumeHandle);
+ goto finish;
+ }
+
+ // Search for unclaimed disk and cdrom drives.
+
+ for (i=0; i < adapterInfo->NumberOfBuses; i++)
+ {
+ busData = &adapterInfo->BusData[i];
+ inquiryData =
+ (PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + busData->InquiryDataOffset);
+
+ for (j=0; j<busData->NumberOfLogicalUnits; j++)
+ {
+ // Check if device is claimed.
+
+ if (!inquiryData->DeviceClaimed)
+ {
+ // Determine the perpherial type.
+
+ switch (inquiryData->InquiryData[0] & 0x1f)
+ {
+ case DIRECT_ACCESS_DEVICE:
+ diskFound = TRUE;
+ break;
+
+ case READ_ONLY_DIRECT_ACCESS_DEVICE:
+ cdromFound = TRUE;
+ break;
+
+ case OPTICAL_DEVICE:
+ diskFound = TRUE;
+ break;
+ }
+ }
+
+ // Get next device data.
+
+ inquiryData =
+ (PSCSI_INQUIRY_DATA)((PUCHAR)adapterInfo + inquiryData->NextInquiryDataOffset);
+ }
+ }
+
+ Free(adapterInfo);
+ CloseHandle(volumeHandle);
+
+ portNumber++;
+ }
+
+ if (diskFound)
+ {
+ // Send IOCTL_DISK_FIND_NEW_DEVICES commands to each existing disk.
+
+ deviceNumber = 0;
+ while (TRUE)
+ {
+ wsprintf(deviceName, L"\\Device\\Harddisk%d\\Partition0", deviceNumber);
+ RtlInitUnicodeString(&unicodeString, deviceName);
+
+ InitializeObjectAttributes(&objectAttributes,
+ &unicodeString,
+ 0,
+ NULL,
+ NULL);
+
+ ntStatus = DmOpenFile(&volumeHandle,
+ FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
+ &objectAttributes,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ break;
+ }
+
+ // Issue find device device control.
+
+ if (!DeviceIoControl(volumeHandle,
+ IOCTL_DISK_FIND_NEW_DEVICES,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &bytesTransferred,
+ NULL))
+ {
+ // nothing?
+ }
+
+ DmClose(volumeHandle);
+
+ // see if the PhysicalDrive# symbolic link is present
+
+ wsprintf(physicalName, TEXT("\\DosDevices\\PhysicalDrive%d"), deviceNumber);
+ deviceNumber++;
+
+ RtlInitUnicodeString(&physicalString, physicalName);
+ InitializeObjectAttributes(&objectAttributes,
+ &physicalString,
+ 0,
+ NULL,
+ NULL);
+ ntStatus = DmOpenFile(&volumeHandle,
+ FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
+ &objectAttributes,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ // Name is not there - create it.
+
+ DefineDosDevice(
+ DDD_RAW_TARGET_PATH,
+ &physicalName[ARRAYLEN("\\DosDevices\\") - 1], // skip prefix
+ deviceName);
+ }
+ else
+ {
+ DmClose(volumeHandle);
+ }
+ }
+ }
+
+ if (cdromFound)
+ {
+ // Send IOCTL_CDROM_FIND_NEW_DEVICES commands to each existing cdrom.
+
+ deviceNumber = 0;
+ while (TRUE)
+ {
+ wsprintf(deviceName, L"\\Device\\Cdrom%d", deviceNumber);
+ RtlInitUnicodeString(&unicodeString, deviceName);
+
+ InitializeObjectAttributes(&objectAttributes,
+ &unicodeString,
+ 0,
+ NULL,
+ NULL);
+
+ ntStatus = DmOpenFile(&volumeHandle,
+ FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE,
+ &objectAttributes,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ break;
+ }
+
+ // Issue find device device control.
+
+ if (!DeviceIoControl(volumeHandle,
+ IOCTL_CDROM_FIND_NEW_DEVICES,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &bytesTransferred,
+ NULL))
+ {
+ // nothing?
+ }
+
+ CloseHandle(volumeHandle);
+ deviceNumber++;
+ }
+ }
+
+finish:
+ PostMessage(g_InitDlg, WM_STARTUP_UPDATE, 100, 0);
+}
diff --git a/private/utils/windisk/src/commit.hxx b/private/utils/windisk/src/commit.hxx
new file mode 100644
index 000000000..52aea23a5
--- /dev/null
+++ b/private/utils/windisk/src/commit.hxx
@@ -0,0 +1,101 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: commit.hxx
+//
+// Contents: Declarations for no-reboot changes
+//
+// History: 15-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __COMMIT_HXX__
+#define __COMMIT_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Commit flag for case where a partition is deleted that has no drive letter
+
+extern BOOLEAN CommitDueToDelete;
+extern BOOLEAN CommitDueToMirror;
+extern BOOLEAN CommitDueToExtended;
+extern BOOLEAN CommitDueToCreate;
+extern ULONG UpdateMbrOnDisk;
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+CommitAssignLetterList(
+ VOID
+ );
+
+VOID
+CommitNewRegions(
+ VOID
+ );
+
+VOID
+CommitToAssignLetterList(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN BOOLEAN MoveLetter
+ );
+
+DWORD
+CommitChanges(
+ VOID
+ );
+
+UINT
+CommitAllChanges(
+ VOID
+ );
+
+VOID
+CommitDeleteLockLetter(
+ IN WCHAR DriveLetter
+ );
+
+BOOL
+CommitAllowed(
+ VOID
+ );
+
+VOID
+RescanDevices(
+ VOID
+ );
+
+BOOL
+CommitDriveLetter(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN WCHAR OldDriveLetter,
+ IN WCHAR NewDriveLetter
+ );
+
+LONG
+CommitToLockList(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN BOOL RemoveDriveLetter,
+ IN BOOL LockNow,
+ IN BOOL FailOk
+ );
+
+LONG
+CommitLockVolumes(
+ IN ULONG Disk
+ );
+
+LONG
+CommitUnlockVolumes(
+ IN ULONG Disk,
+ IN BOOLEAN FreeList
+ );
+
+VOID
+FtConfigure(
+ VOID
+ );
+
+#endif // __COMMIT_HXX__
diff --git a/private/utils/windisk/src/const.h b/private/utils/windisk/src/const.h
new file mode 100644
index 000000000..63437d881
--- /dev/null
+++ b/private/utils/windisk/src/const.h
@@ -0,0 +1,146 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: const.h
+//
+// Contents: Global constants
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CONST_H__
+#define __CONST_H__
+
+
+//
+// The maximum length of a string in a listview column
+//
+
+#define MAX_LV_ITEM_LEN 200
+
+#define MAX_RESOURCE_STRING_LEN 256
+
+#define MAXTITLELEN 256
+#define MAXMESSAGELEN 256
+#define MAXERRORLEN 256
+#define MAXLABELLEN 32 + 1
+
+//
+// This is the number of entries in a partition table, and is fixed for
+// all time
+//
+
+#define PARTITION_TABLE_SIZE 4
+
+//
+// This is the maximum number of members that WinDisk will support
+// in an FT Set.
+//
+#define MAX_MEMBERS_IN_FT_SET 32
+
+#define STATUS_TEXT_SIZE 250
+
+#define NUM_AVAILABLE_COLORS 16
+#define NUM_AVAILABLE_HATCHES 6
+
+
+#define LEGEND_STRING_COUNT 6
+
+//
+// indices into g_Brushes[], for brushes for drawing legend rectangles
+//
+#define BRUSH_USEDPRIMARY 0
+#define BRUSH_USEDLOGICAL 1
+#define BRUSH_STRIPESET 2
+#define BRUSH_PARITYSET 3
+#define BRUSH_MIRROR 4
+#define BRUSH_VOLUMESET 5
+#define BRUSH_ARRAY_SIZE LEGEND_STRING_COUNT
+
+//
+// indices into AvailableHatches[] (see data.cxx)
+//
+#define DEFAULT_HATCH_USEDPRIMARY 5
+#define DEFAULT_HATCH_USEDLOGICAL 5
+#define DEFAULT_HATCH_STRIPESET 5
+#define DEFAULT_HATCH_MIRROR 5
+#define DEFAULT_HATCH_VOLUMESET 5
+#define DEFAULT_HATCH_PARITYSET 5
+
+//
+// indices into AvailableColors[] (see data.cxx)
+//
+#define DEFAULT_COLOR_USEDPRIMARY 9
+#define DEFAULT_COLOR_USEDLOGICAL 15
+#define DEFAULT_COLOR_STRIPESET 14
+#define DEFAULT_COLOR_MIRROR 5
+#define DEFAULT_COLOR_VOLUMESET 10
+#define DEFAULT_COLOR_PARITYSET 13
+
+//
+// my own hatch identifiers
+//
+
+#define MY_HS_FDIAGONAL 0 /* \\\\\ */
+#define MY_HS_BDIAGONAL 1 // /////
+#define MY_HS_CROSS 2 // +++++
+#define MY_HS_DIAGCROSS 3 // xxxxx
+#define MY_HS_VERTICAL 4 // |||||
+#define MY_HS_SOLIDCLR 5 // solid
+
+
+
+#define MESSAGE_BUFFER_SIZE 4096
+
+#define PEN_WIDTH 1
+
+
+// thickness of the border indicating selection of a region
+
+#define SELECTION_THICKNESS 2
+
+
+//
+// define constants for use with drive letter assignments.
+// use arbitrary symbols that won't ever be drive letters themselves.
+
+#define NO_DRIVE_LETTER_YET L'#'
+#define NO_DRIVE_LETTER_EVER L'%'
+
+
+
+
+// custom windows message for F1 key
+
+#define WM_F1DOWN (WM_USER + 0x17a)
+
+
+
+#define MBOOT_CODE_SIZE 0x1b8
+#define MBOOT_SIG_OFFSET 0x1fe
+#define MBOOT_SIG1 0x55
+#define MBOOT_SIG2 0xaa
+
+
+
+#define UNINIT_FT_TYPE ((FT_TYPE)-1)
+
+// toolbar constants
+
+#define TOOLBAR_HEIGHT 27
+
+
+//
+// Indices into the GraphColors[] array. These are colors used in the neato
+// %free/%used graph in the Volume general property page
+//
+
+#define I_USEDCOLOR 0
+#define I_FREECOLOR 1
+#define I_USEDSHADOW 2
+#define I_FREESHADOW 3
+
+#endif // __CONST_H__
diff --git a/private/utils/windisk/src/data.cxx b/private/utils/windisk/src/data.cxx
new file mode 100644
index 000000000..163a31852
--- /dev/null
+++ b/private/utils/windisk/src/data.cxx
@@ -0,0 +1,288 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: data.cxx
+//
+// Contents: Global data
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+
+DECLARE_INFOLEVEL(da)
+
+
+HINSTANCE g_hInstance;
+
+//
+// IsDiskRemovable is an array of BOOLEANs each of which indicates
+// whether the corresponding physical disk is removable.
+//
+
+PBOOLEAN IsDiskRemovable = NULL;
+
+//
+// RemovableDiskReservedDriveLetters is an array of WCHARs which
+// shows the reserved drive letter for each disk if that disk is
+// removable.
+//
+
+PWCHAR RemovableDiskReservedDriveLetters;
+
+//
+// This will be an array of pointers to DISKSTATE structures, indexed
+// by disk number.
+//
+
+PDISKSTATE* DiskArray;
+
+//
+// BootDiskNumber is the number of the disk on which the boot partition
+// (ie. the disk with the WinNt files) resides. BootPartitionNumber is
+// the original partition number of this partition.
+//
+
+ULONG BootDiskNumber;
+ULONG BootPartitionNumber;
+
+
+// window handles
+
+HWND g_hwndFrame;
+HWND g_hwndList;
+HWND g_hwndToolbar;
+
+HMENU g_hmenuFrame; // the frame window's hmenu
+
+// GDI objects
+
+HBITMAP g_hBitmapSmallDisk;
+HBITMAP g_hBitmapRemovableDisk;
+HBITMAP g_hBitmapSmallCdRom;
+HFONT g_hFontGraph;
+HFONT g_hFontGraphBold;
+HFONT g_hFontStatus;
+HFONT g_hFontLegend;
+
+HBRUSH g_Brushes[BRUSH_ARRAY_SIZE];
+HBRUSH g_hBrushFreeLogical;
+HBRUSH g_hBrushFreePrimary;
+HPEN g_hPenNull;
+HPEN g_hPenThinSolid;
+HCURSOR g_hCurWait;
+HCURSOR g_hCurNormal;
+
+
+// initial stuff for the disk graphs, used when there is
+// no info in win.ini.
+
+int BrushHatches[BRUSH_ARRAY_SIZE] =
+{
+ DEFAULT_HATCH_USEDPRIMARY,
+ DEFAULT_HATCH_USEDLOGICAL,
+ DEFAULT_HATCH_STRIPESET,
+ DEFAULT_HATCH_PARITYSET,
+ DEFAULT_HATCH_MIRROR,
+ DEFAULT_HATCH_VOLUMESET
+};
+
+int BrushColors[BRUSH_ARRAY_SIZE] =
+{
+ DEFAULT_COLOR_USEDPRIMARY,
+ DEFAULT_COLOR_USEDLOGICAL,
+ DEFAULT_COLOR_STRIPESET,
+ DEFAULT_COLOR_PARITYSET,
+ DEFAULT_COLOR_MIRROR,
+ DEFAULT_COLOR_VOLUMESET
+};
+
+// colors and patterns available for the disk graphs
+
+COLORREF AvailableColors[NUM_AVAILABLE_COLORS] =
+{
+ RGB(0,0,0), // 0: black
+ RGB(128,128,128), // 1: dark gray
+ RGB(192,192,192), // 2: light gray
+ RGB(255,255,255), // 3: white
+ RGB(128,128,0), // 4: dark yellow
+ RGB(128,0,128), // 5: violet
+ RGB(128,0,0), // 6: dark red
+ RGB(0,128,128), // 7: dark cyan
+ RGB(0,128,0), // 8: dark green
+ RGB(0,0,128), // 9: dark blue
+ RGB(255,255,0), // 10: yellow
+ RGB(255,0,255), // 11: light violet
+ RGB(255,0,0), // 12: red
+ RGB(0,255,255), // 13: cyan
+ RGB(0,255,0), // 14: green
+ RGB(0,0,255) // 15: blue
+};
+
+int AvailableHatches[NUM_AVAILABLE_HATCHES] =
+{
+ MY_HS_FDIAGONAL, /* \\\\\ */
+ MY_HS_BDIAGONAL, // /////
+ MY_HS_CROSS, // +++++
+ MY_HS_DIAGCROSS, // xxxxx
+ MY_HS_VERTICAL, // |||||
+ MY_HS_SOLIDCLR // solid
+};
+
+
+
+// positions for various items in a disk graph
+
+DWORD GraphWidth = 0;
+
+DWORD GraphHeight;
+DWORD BarTopYOffset;
+DWORD BarBottomYOffset;
+DWORD BarHeight;
+
+DWORD dxDriveLetterStatusArea;
+
+DWORD dxBarTextMargin;
+DWORD dyBarTextLine;
+DWORD BarLeftX;
+DWORD BarWidth;
+DWORD BarWidthMargin;
+DWORD BarWidthMinimum;
+
+DWORD MinimumWindowWidth;
+
+DWORD xSmallDisk;
+DWORD ySmallDisk;
+DWORD dxSmallDisk;
+DWORD dySmallDisk;
+
+DWORD xRemovableDisk;
+DWORD yRemovableDisk;
+DWORD dxRemovableDisk;
+DWORD dyRemovableDisk;
+
+DWORD xSmallCdRom;
+DWORD ySmallCdRom;
+DWORD dxSmallCdRom;
+DWORD dySmallCdRom;
+
+ULONG g_MinimumRegionSize;
+
+//
+// various measurement metrics
+//
+
+DWORD g_wLegendItem; // width of a legend item
+DWORD g_dyLegendSep; // separation between legend items
+
+DWORD g_dyBorder;
+DWORD g_dyToolbar;
+DWORD g_dyStatus;
+DWORD g_dyLegend;
+
+
+// if a single disk region is selected, these vars describe the selection.
+
+PDISKSTATE SingleSel;
+DWORD SingleSelIndex;
+
+// name of the help file
+
+PWSTR g_HelpFile;
+
+
+// number of hard disks and CD-ROMs attached to the system
+
+ULONG DiskCount = 0;
+
+ULONG CdRomCount = 0;
+PCDROM_DESCRIPTOR CdRomArray;
+
+// "Disk %u", "CdRom %u"
+
+LPTSTR DiskN;
+LPTSTR CdRomN;
+
+PWSTR wszUnformatted;
+PWSTR wszUnknown;
+
+//
+// If the following is TRUE, the registry needs to be updated and the user will
+// be prompted to save changed just as if he had made changes to any partitions.
+//
+
+BOOL RegistryChanged = FALSE;
+
+//
+// Restart required to make changes work.
+//
+
+BOOL RestartRequired = FALSE;
+
+//
+// If the following is TRUE, the main window will pass WM_ENTERIDLE
+// messages on to the child dialog box; this will trigger the
+// configuration search.
+//
+
+BOOL ConfigurationSearchIdleTrigger = FALSE;
+
+//
+// This flag indicates whether this is a Server
+// or just regular Windows NT Workstation.
+//
+
+BOOL g_IsLanmanNt = FALSE;
+
+//
+// Whether or not a CD-ROM is present in the system
+//
+
+BOOL g_AllowCdRom = FALSE;
+
+//
+// g_WhichView indicates which view is currently being displayed
+//
+
+VIEW_TYPE g_WhichView;
+
+//
+// listview data
+//
+
+HWND g_hwndLV;
+
+//
+// set this to TRUE if you are programmatically setting listview state,
+// and want to ignore the resulting notification messages.
+//
+
+BOOL g_SettingListviewState = FALSE;
+
+// whether status bar and legend are currently shown
+
+BOOL g_Toolbar = TRUE;
+BOOL g_StatusBar = TRUE;
+BOOL g_Legend = TRUE;
+
+
+
+DISK_TYPE g_DiskDisplayType = DiskProportional;
+
+//
+// Colors used in the %used/%free graph in the volume general property page.
+//
+// DO NOT change the order of these defines (see I_*)
+//
+COLORREF GraphColors[] =
+{
+ RGB( 0, 0, 255), // (I_USEDCOLOR) Used: Blue
+ RGB(255, 0, 255), // (I_FREECOLOR) Free: Red-Blue
+ RGB( 0, 0, 128), // (I_USEDSHADOW) Used shadow: 1/2 Blue
+ RGB(128, 0, 128) // (I_FREESHADOW) Free shadow: 1/2 Red-Blue
+};
diff --git a/private/utils/windisk/src/dblspace.cxx b/private/utils/windisk/src/dblspace.cxx
new file mode 100644
index 000000000..24e9a6202
--- /dev/null
+++ b/private/utils/windisk/src/dblspace.cxx
@@ -0,0 +1,1662 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dblspace.cxx
+//
+// Contents: This module contains the set of routines that deal with
+// DoubleSpace dialogs and support.
+//
+// History: 15-Nov-93 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#if defined( DBLSPACE_ENABLED )
+
+#include <util.hxx>
+
+#include "dblspace.h"
+#include "dblspace.hxx"
+#include "dialogs.h"
+#include "dlgs.hxx"
+#include "drives.hxx"
+#include "fmifs.hxx"
+#include "help.hxx"
+#include "listbox.hxx"
+#include "format.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define MAX_IFS_NAME_LENGTH 200
+
+WCHAR DblSpaceWildCardFileName[] = TEXT("%c:\\dblspace.*");
+
+// All DoubleSpace structures are chained into the base chain
+// this allows for ease in initialization to determine which are
+// mounted. This chain is only used for initialization.
+
+PDBLSPACE_DESCRIPTOR DblChainBase = NULL;
+PDBLSPACE_DESCRIPTOR DblChainLast = NULL;
+
+#define DblSpaceMountDrive(REGDESC, DBLSPACE) \
+ DblSpaceChangeState(REGDESC, DBLSPACE, TRUE)
+#define DblSpaceDismountDrive(REGDESC, DBLSPACE) \
+ DblSpaceChangeState(REGDESC, DBLSPACE, FALSE)
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+DblSpaceUpdateIniFile(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is left around in case this code must update DOS
+ based .ini files. Currently it does nothing.
+
+Arguments:
+
+ The region with the DoubleSpace volumes.
+
+Return Value
+
+ None
+
+--*/
+
+{
+}
+
+ULONG
+DblSpaceChangeState(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PDBLSPACE_DESCRIPTOR DblSpacePtr,
+ IN BOOL Mount
+ )
+
+/*++
+
+Routine Description:
+
+ Based on the value of Mount, either mount the volume or
+ dismount the DoubleSpace volume
+
+Arguments:
+
+ RegionDescriptor - The region containing the DoubleSpace volume
+ DblSpacePtr - The DoubleSpace structure involved.
+ Mount - TRUE == perform a mount function
+ FALSE == dismount the volume
+
+Return Value:
+
+ 0 for success
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ WCHAR dblSpaceUniqueName[32];
+ ULONG index;
+ ULONG result = 0;
+
+ SetCursor(g_hCurWait);
+
+ if (Mount)
+ {
+ // Call fmifs mount routine.
+
+ result = FmIfsMountDblspace(DblSpacePtr->FileName,
+ regionData->DriveLetter,
+ DblSpacePtr->NewDriveLetter);
+ }
+ else
+ {
+ // Call fmifs dismount routine.
+
+ result = FmIfsDismountDblspace(DblSpacePtr->DriveLetter);
+ }
+
+ if (0 == result)
+ {
+ DblSpacePtr->Mounted = Mount;
+ if (Mount)
+ {
+ DblSpacePtr->DriveLetter = DblSpacePtr->NewDriveLetter;
+ MarkDriveLetterUsed(DblSpacePtr->DriveLetter);
+ }
+ else
+ {
+ WCHAR driveName[3];
+
+ // remove the drive letter.
+
+ driveName[0] = DblSpacePtr->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ DefineDosDevice(DDD_REMOVE_DEFINITION, driveName, NULL);
+
+ // Now update the internal structures.
+
+ MarkDriveLetterFree(DblSpacePtr->DriveLetter);
+ DblSpacePtr->DriveLetter = L' ';
+ }
+
+ if (!IsDiskRemovable[RegionDescriptor->Disk])
+ {
+ dblSpaceUniqueName[0] = regionData->DriveLetter;
+ dblSpaceUniqueName[1] = L':';
+ dblSpaceUniqueName[2] = L'\\';
+
+ index = 0;
+ while (NULL != (dblSpaceUniqueName[index + 3] = DblSpacePtr->FileName[index]))
+ {
+ index++;
+ }
+
+ result = DiskRegistryAssignDblSpaceLetter(dblSpaceUniqueName,
+ DblSpacePtr->DriveLetter);
+ }
+ }
+
+ SetCursor(g_hCurNormal);
+ return result;
+}
+
+PDBLSPACE_DESCRIPTOR
+DblSpaceCreateInternalStructure(
+ IN WCHAR DriveLetter,
+ IN ULONG Size,
+ IN PWSTR Name,
+ IN BOOLEAN ChainIt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine constructs the internal data structure that represents a
+ DoubleSpace volume.
+
+Arguments:
+
+ DriveLetter - drive letter for new internal structure
+ Size - size of the actual volume
+ Name - name of the containing DoubleSpace file (i.e. dblspace.xxx)
+ ChainIt -
+
+Return Value:
+
+ Pointer to the new structure if created.
+ NULL if it couldn't be created.
+
+--*/
+
+{
+ PDBLSPACE_DESCRIPTOR dblSpace;
+
+ dblSpace = (PDBLSPACE_DESCRIPTOR)Malloc(sizeof(DBLSPACE_DESCRIPTOR));
+
+ if (DriveLetter != L' ')
+ {
+ MarkDriveLetterUsed(DriveLetter);
+ }
+ dblSpace->DblChainNext = NULL;
+ dblSpace->Next = NULL;
+ dblSpace->DriveLetter = DriveLetter;
+ dblSpace->NewDriveLetter = L'\0';
+ dblSpace->ChangeDriveLetter = FALSE;
+ dblSpace->Mounted = FALSE;
+ dblSpace->ChangeMountState = FALSE;
+ dblSpace->AllocatedSize = Size;
+ dblSpace->FileName = (PWSTR)Malloc((lstrlen(Name) + 4) * sizeof(WCHAR));
+
+ // Copy the name.
+
+ lstrcpy(dblSpace->FileName, Name);
+ if (ChainIt)
+ {
+ if (DblChainBase)
+ {
+ DblChainLast->DblChainNext = dblSpace;
+ }
+ else
+ {
+ DblChainBase = dblSpace;
+ }
+ DblChainLast = dblSpace;
+ }
+
+ return dblSpace;
+}
+
+VOID
+DblSpaceDetermineMounted(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine walks through all of the system drive letters to see
+ if any are mounted DoubleSpace volumes. If a mounted DoubleSpace
+ volume is located it updates the state of that volume in the internal
+ data structures for the DoubleSpace volumes.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PDBLSPACE_DESCRIPTOR dblSpace;
+ WCHAR driveLetter[4],
+ ntDriveName[MAX_IFS_NAME_LENGTH],
+ cvfName[MAX_IFS_NAME_LENGTH],
+ hostDriveName[MAX_IFS_NAME_LENGTH];
+ UINT errorMode;
+ BOOLEAN removable,
+ floppy,
+ compressed,
+ error;
+
+ driveLetter[1] = L':';
+ driveLetter[2] = L'\0';
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ for (driveLetter[0] = L'C'; driveLetter[0] < L'Z'; driveLetter[0]++)
+ {
+ if (DriveLetterIsAvailable(driveLetter[0]))
+ {
+ // No sense calling this stuff for something that doesn't exist
+
+ continue;
+ }
+
+ compressed = FALSE;
+ if (FmIfsQueryInformation(&driveLetter[0],
+ &removable,
+ &floppy,
+ &compressed,
+ &error,
+ &ntDriveName[0],
+ MAX_IFS_NAME_LENGTH,
+ &cvfName[0],
+ MAX_IFS_NAME_LENGTH,
+ &hostDriveName[0],
+ MAX_IFS_NAME_LENGTH))
+ {
+ // call worked, see if it is a DoubleSpace volume
+
+ if (compressed)
+ {
+ // now need to find this volume in the chain and
+ // update it mounted state.
+
+ for (dblSpace = DblChainBase;
+ NULL != dblSpace;
+ dblSpace = dblSpace->DblChainNext)
+ {
+ if (0 == lstrcmp(dblSpace->FileName, cvfName))
+ {
+ // found a match.
+
+ dblSpace->Mounted = TRUE;
+ dblSpace->DriveLetter = driveLetter[0];
+ }
+ }
+ }
+ }
+ }
+ SetErrorMode(errorMode);
+}
+
+VOID
+DblSpaceInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine goes through the disk table and searches for FAT format
+ partitions. When one is found, it checks for the presense of DoubleSpace
+ volumes and initializes the DoubleSpace support structures inside
+ Disk Administrator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDesc;
+ PPERSISTENT_REGION_DATA regionData;
+ PDBLSPACE_DESCRIPTOR dblSpace,
+ prevDblSpace;
+ WCHAR fileName[50];
+ unsigned diskIndex,
+ regionIndex;
+
+ for (diskIndex = 0; diskIndex < DiskCount; diskIndex++)
+ {
+ diskState = DiskArray[diskIndex];
+ regionDesc = diskState->RegionArray;
+ for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++)
+ {
+ regionData = PERSISTENT_DATA(&regionDesc[regionIndex]);
+
+ // region may be free or something that isn't recognized by NT
+
+ if (!regionData)
+ {
+ continue;
+ }
+
+ // region may not be formatted yet.
+
+ if (!regionData->TypeName)
+ {
+ continue;
+ }
+
+ // DoubleSpace volumes are only allowed on FAT non-FT partitions.
+
+ if (regionData->FtObject)
+ {
+ continue;
+ }
+
+ if (0 == lstrcmp(regionData->TypeName, L"FAT"))
+ {
+ WIN32_FIND_DATA findInformation;
+ HANDLE findHandle;
+
+ // it is possible to have a DoubleSpace volume here.
+ // Search the root directory of the driver for files with
+ // the name "dblspace.xxx". These are potentially dblspace
+ // volumes.
+
+ prevDblSpace = NULL;
+ wsprintf(fileName, DblSpaceWildCardFileName, regionData->DriveLetter);
+ findHandle = FindFirstFile(fileName, &findInformation);
+ while (findHandle != INVALID_HANDLE_VALUE)
+ {
+ TCHAR* cp;
+ int i;
+ int save;
+
+ // There is at least one dblspace volume. Insure that
+ // the name is of the proper form.
+
+ save = TRUE;
+ cp = &findInformation.cFileName[0];
+
+ while (*cp)
+ {
+ if (*cp == TEXT('.'))
+ {
+ break;
+ }
+ cp++;
+ }
+
+ if (*cp != TEXT('.'))
+ {
+ // not a proper dblspace volume name.
+
+ save = FALSE;
+ }
+ else
+ {
+ cp++;
+
+ for (i = 0; i < 3; i++, cp++)
+ {
+ if ((*cp < TEXT('0')) || (*cp > TEXT('9')))
+ {
+ break;
+ }
+ }
+
+ if (i != 3)
+ {
+ // not a proper dblspace volume name.
+
+ save = FALSE;
+ }
+ }
+
+ if (save)
+ {
+ // save the information and search for more.
+
+ dblSpace =
+ DblSpaceCreateInternalStructure(
+ TEXT(' '),
+ ((findInformation.nFileSizeHigh << 16) |
+ (findInformation.nFileSizeLow)
+ / (1024 * 1024)),
+ &findInformation.cFileName[0],
+ TRUE);
+ if (dblSpace)
+ {
+ // Assume volume is not mounted.
+
+ dblSpace->Mounted = FALSE;
+ dblSpace->ChangeMountState = FALSE;
+
+ // Chain in this description.
+
+ if (prevDblSpace)
+ {
+ prevDblSpace->Next = dblSpace;
+ }
+ else
+ {
+ regionData->DblSpace = dblSpace;
+ }
+
+ // Keep the pointer to this one for the chain.
+
+ prevDblSpace = dblSpace;
+ }
+ else
+ {
+ // no memory
+
+ break;
+ }
+ }
+
+ if (!FindNextFile(findHandle, &findInformation))
+ {
+ // Technically this should double check and call
+ // GetLastError to see that it is ERROR_NO_MORE_FILES
+ // but this code doesn't do that.
+
+ FindClose(findHandle);
+
+ // Get out of the search loop.
+
+ findHandle = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+ }
+ }
+
+ // Now that all volumes have been located determine which volumes
+ // are mounted by chasing down the drive letters.
+
+ DblSpaceDetermineMounted();
+}
+
+PDBLSPACE_DESCRIPTOR
+DblSpaceGetNextVolume(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will check the RegionDescriptor to walk the DoubleSpace
+ volume chain located from the persistent data.
+
+Arguments:
+
+ RegionDescriptor - pointer to the region on the disk that is to be
+ searched for a DoubleSpace volume.
+
+ DblSpace - pointer to the last DoubleSpace volume located on the region.
+
+Return Value:
+
+ pointer to the next DoubleSpace volume if found
+ NULL if no volume found.
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData;
+
+ // If a previous DoubleSpace location was past, simply walk the chain to the next.
+
+ if (DblSpace)
+ {
+ return DblSpace->Next;
+ }
+
+ // no previous DoubleSpace location, just get the first one and return it.
+ // Could get a NULL RegionDescriptor. If so, return NULL.
+
+ if (RegionDescriptor)
+ {
+ regionData = PERSISTENT_DATA(RegionDescriptor);
+ if (!regionData)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+ return regionData->DblSpace;
+}
+
+VOID
+DblSpaceLinkNewVolume(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ )
+
+/*++
+
+Routine Description:
+
+ Chain the new DoubleSpace volume on the list of DoubleSpace volumes
+ for the region.
+
+Arguments:
+
+ RegionDescriptor - the region the DoubleSpace volume has been added to.
+ DblSpace - the new volume internal data structure.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ PDBLSPACE_DESCRIPTOR prevDblSpace;
+
+ // if this is the first one, chain it first
+
+ if (!regionData->DblSpace)
+ {
+ regionData->DblSpace = DblSpace;
+ return;
+ }
+
+ for (prevDblSpace = regionData->DblSpace;
+ NULL != prevDblSpace->Next;
+ prevDblSpace = prevDblSpace->Next)
+ {
+ // all the work is in the for
+ }
+
+ // found the last one. Add the new one to the chain
+
+ prevDblSpace->Next = DblSpace;
+}
+
+BOOL
+DblSpaceVolumeExists(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ Indicate to the caller if the input region contains a DoubleSpace volume.
+
+Arguments:
+
+ RegionDescriptor - a pointer to the region in question.
+
+Return Value:
+
+ TRUE if this region contains DoubleSpace volume(s).
+ FALSE if not
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ if (regionData)
+ {
+ return (regionData->DblSpace ? TRUE : FALSE);
+ }
+ return FALSE;
+}
+
+BOOL
+DblSpaceDismountedVolumeExists(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ Indicate to the caller if the input region contains a DoubleSpace volume
+ that is not mounted.
+
+Arguments:
+
+ RegionDescriptor - a pointer to the region in question.
+
+Return Value:
+
+ TRUE if this region contains DoubleSpace volume(s).
+ FALSE if not
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ PDBLSPACE_DESCRIPTOR dblSpace;
+
+ if (regionData)
+ {
+ if (NULL != (dblSpace = regionData->DblSpace))
+ {
+ while (NULL != dblSpace)
+ {
+ if (!dblSpace->Mounted)
+ {
+ return TRUE;
+ }
+ dblSpace = dblSpace->Next;
+ }
+ }
+ }
+ return FALSE;
+}
+
+PDBLSPACE_DESCRIPTOR
+DblSpaceFindVolume(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PWSTR Name
+ )
+
+/*++
+
+Routine Description:
+
+ Given a region and a name, locate the DoubleSpace data structure.
+
+Arguments:
+
+ RegionDescriptor - the region to search
+ Name - the filename wanted.
+
+Return Value:
+
+ A pointer to a DoubleSpace descriptor if found.
+ NULL if not found.
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ PDBLSPACE_DESCRIPTOR dblSpace = NULL;
+
+ if (NULL != regionData)
+ {
+ for (dblSpace = regionData->DblSpace;
+ NULL != dblSpace;
+ dblSpace = dblSpace->Next)
+ {
+ if (0 == lstrcmp(Name, dblSpace->FileName))
+ {
+ // found the desired DoubleSpace volume
+
+ break;
+ }
+ }
+ }
+ return dblSpace;
+}
+
+
+BOOL
+DblSpaceDetermineUniqueFileName(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PWSTR FileName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will search the actual partition to determine what
+ valid DoubleSpace file name to use (i.e. dblspace.xxx where xxx
+ is a unique number).
+
+Arguments:
+
+ RegionDescriptor - the region to search and determine what DoubleSpace
+ file names are in use.
+ FileName - a pointer to a character buffer for the name.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ DWORD uniqueNumber = 0;
+
+ do
+ {
+ wsprintf(FileName, TEXT("dblspace.%03d"), uniqueNumber++);
+ if (uniqueNumber > 999)
+ {
+ return FALSE;
+ }
+ } while (DblSpaceFindVolume(RegionDescriptor, FileName));
+ return TRUE;
+}
+
+VOID
+DblSpaceRemoveVolume(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Find the drive letter provided and unlink it from the chain.
+ Currently this also removes the volume for the scaffolding file.
+
+Arguments:
+
+ RegionDescriptor - region containing the DoubleSpace volume.
+ DriveLetter - the drive letter to remove.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ PDBLSPACE_DESCRIPTOR dblSpace,
+ prevDblSpace = NULL;
+
+ // Clean up the internal structures.
+
+ if (NULL != regionData)
+ {
+ for (dblSpace = regionData->DblSpace;
+ NULL != dblSpace;
+ dblSpace = dblSpace->Next)
+ {
+ if (dblSpace->DriveLetter == DriveLetter)
+ {
+ // This is the one to delete
+
+ if (NULL != prevDblSpace)
+ {
+ prevDblSpace->Next = dblSpace->Next;
+ }
+ else
+ {
+ regionData->DblSpace = dblSpace->Next;
+ }
+ Free(dblSpace);
+ break;
+ }
+ prevDblSpace = dblSpace;
+ }
+ }
+}
+
+BOOL CALLBACK
+CreateDblSpaceDlgProc(
+ IN HWND hDlg,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine manages the dialog for the creation of a new double
+ space volume.
+
+Arguments:
+
+ hDlg - the dialog box handle.
+ wMsg - the message.
+ wParam - the windows parameter.
+ lParam - depends on message type.
+
+Return Value:
+
+ TRUE is returned back through windows if the create is successful
+ FALSE otherwise
+
+--*/
+{
+ static FORMAT_PARAMS formatParams; // this is passed to other threads
+ // it cannot be located on the stack
+ static DWORD sizeMB = 0,
+ maxSizeMB = 600,
+ minSizeMB = 10;
+
+ PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ PDBLSPACE_DESCRIPTOR dblSpace;
+ WCHAR outputString[50];
+ WCHAR driveLetter;
+ WCHAR driveLetterString[3]; // big enough for "x:" string.
+ DWORD selection;
+ BOOL validNumber;
+ HWND hwndCombo;
+
+ switch (wMsg)
+ {
+ case WM_INITDIALOG:
+
+ // limit the size of string that may be entered for the label
+
+ Edit_LimitText(GetDlgItem(hDlg, IDC_DBLCREATE_NAME), 11);
+
+ // set up to watch all characters that go thru the size dialog
+ // to allow only decimal numbers.
+
+ OldSizeDlgProc = (WNDPROC) SetWindowLong(
+ GetDlgItem(hDlg, IDC_DBLCREATE_SIZE),
+ GWL_WNDPROC,
+ (LONG)&SizeDlgProc);
+
+ // Add each available drive letter to the list of available
+ // drive letters and set the default letter to the first available.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLCREATE_LETTER_CHOICES);
+
+ driveLetterString[1] = TEXT(':');
+ driveLetterString[2] = TEXT('\0');
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ if (DriveLetterIsAvailable(driveLetter))
+ {
+ driveLetterString[0] = driveLetter;
+ ComboBox_AddString(hwndCombo, driveLetterString);
+ }
+ }
+ ComboBox_SetCurSel(hwndCombo, 0);
+
+ // Setup the min/max values and the size box.
+
+ wsprintf(outputString, TEXT("%u"), minSizeMB);
+ SetDlgItemText(hDlg, IDC_MINMAX_MIN, outputString);
+ wsprintf(outputString, TEXT("%u"), maxSizeMB);
+ SetDlgItemText(hDlg, IDC_MINMAX_MAX, outputString);
+
+ // set up/down control range
+
+ SendDlgItemMessage(
+ hwnd,
+ IDC_DBLCREATE_ALLOCATED,
+ UDM_SETRANGE,
+ 0,
+ MAKELONG(maxSizeMB, minSizeMB));
+
+ // let the spin control set the edit control
+
+ SendDlgItemMessage(hwnd, IDC_DBLCREATE_ALLOCATED, UDM_SETPOS, 0, MAKELONG(maxSizeMB, 0));
+ SendDlgItemMessage(hwnd, IDC_DBLCREATE_SIZE, EM_SETSEL, 0, -1);
+
+ CenterDialogInFrame(hDlg);
+ return TRUE;
+
+ case WM_VSCROLL:
+ // The up/down control changed the edit control: select it again
+ SendDlgItemMessage(hwnd, IDC_DBLCREATE_SIZE, EM_SETSEL, 0, (LPARAM)-1);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDHELP:
+ break;
+
+ case IDCANCEL:
+
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDOK:
+ {
+ int fOk;
+
+ // can only do this if the fmifs dll supports DoubleSpace.
+
+ if (!g_DoubleSpaceSupported)
+ {
+ // could not load the dll
+
+ ErrorDialog(MSG_CANT_LOAD_FMIFS);
+ EndDialog(hDlg, FALSE);
+ break;
+ }
+
+ // Get the current size for this volume.
+
+ sizeMB = GetDlgItemInt(hDlg, IDC_DBLCREATE_SIZE, &validNumber, FALSE);
+ if ( !validNumber
+ || !sizeMB
+ || (sizeMB > maxSizeMB)
+ || (sizeMB < minSizeMB))
+ {
+ ErrorDialog(MSG_INVALID_SIZE);
+ EndDialog(hDlg, FALSE);
+ break;
+ }
+
+ // Get the currently selected item in the listbox for drive letter
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLCREATE_LETTER_CHOICES);
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, driveLetterString);
+
+ formatParams.RegionDescriptor = regionDescriptor;
+ formatParams.FileSystemIndex = -1;
+ formatParams.DblspaceFileName = NULL;
+ formatParams.QuickFormat = FALSE;
+ formatParams.Cancel = FALSE;
+ formatParams.DoubleSpace = TRUE;
+ formatParams.TotalSpace = 0;
+ formatParams.SpaceAvailable = sizeMB;
+
+ // get the label
+
+ GetDlgItemText(
+ hDlg,
+ IDC_DBLCREATE_NAME,
+ formatParams.Label,
+ ARRAYLEN(formatParams.Label));
+
+ fOk = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_DBLSPACE_CANCEL),
+ hDlg,
+ FormatProgressDlgProc,
+ (LPARAM)&formatParams);
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBoxParam() failed!\n"));
+ }
+
+ if (formatParams.Result)
+ {
+ // the format failed.
+
+ ErrorDialog(formatParams.Result);
+ EndDialog(hDlg, FALSE);
+ }
+ else if (formatParams.Cancel)
+ {
+ // cancelled
+ }
+ else
+ {
+ WCHAR message[300];
+ WCHAR msgProto[300];
+ WCHAR title[200];
+
+ // save the name
+
+ if (NULL != formatParams.DblspaceFileName)
+ {
+ lstrcpy(message, formatParams.DblspaceFileName);
+ }
+ else
+ {
+ message[0] = L'\0';
+ }
+ Free(formatParams.DblspaceFileName);
+
+ dblSpace = DblSpaceCreateInternalStructure(*driveLetterString,
+ sizeMB,
+ message,
+ FALSE);
+ if (dblSpace)
+ {
+ DblSpaceLinkNewVolume(regionDescriptor, dblSpace);
+ MarkDriveLetterUsed(dblSpace->DriveLetter);
+ dblSpace->Mounted = TRUE;
+ }
+
+ LoadString(g_hInstance,
+ IDS_DBLSPACECOMPLETE,
+ title,
+ ARRAYLEN(title));
+
+ LoadString(g_hInstance,
+ IDS_FMT_STATS,
+ msgProto,
+ ARRAYLEN(msgProto));
+
+ TCHAR totalSpace[100];
+ TCHAR spaceAvailable[100];
+
+ wsprintf(totalSpace, L"%lu", formatParams.TotalSpace);
+ wsprintf(spaceAvailable, L"%lu", formatParams.SpaceAvailable);
+
+ InsertSeparators(totalSpace);
+ InsertSeparators(spaceAvailable);
+
+ wsprintf(
+ message,
+ msgProto,
+ totalSpace,
+ spaceAvailable
+ );
+
+ MessageBox(
+ g_hwndFrame,
+ message,
+ title,
+ MB_ICONINFORMATION | MB_OK);
+
+ EndDialog(hDlg, TRUE);
+ }
+
+ break;
+ }
+
+ default:
+
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ // The size value has changed. Update the compressed
+ // size value displayed to the user.
+
+ sizeMB = GetDlgItemInt(hDlg, IDC_DBLCREATE_SIZE, &validNumber, FALSE);
+ if (!validNumber)
+ {
+ sizeMB = 0;
+ }
+
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+
+ // restore original subclass to window.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLCREATE_SIZE);
+ SetWindowLong(hwndCombo, GWL_WNDPROC, (LONG) OldSizeDlgProc);
+ break;
+
+ }
+ return FALSE;
+}
+
+VOID
+DblSpaceDelete(
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ )
+
+/*++
+
+Routine Description:
+
+ Start the dialog box for the deletion of a DoubleSpace volume.
+
+Arguments:
+
+ Param - not currently used.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+
+ if (IDYES == ConfirmationDialog(
+ MSG_CONFIRM_DBLSPACE_DELETE,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ // Delete the drive from view
+
+ DblSpaceRemoveVolume(regionDescriptor, DblSpace->DriveLetter);
+ DblSpaceUpdateIniFile(regionDescriptor);
+ DrawDiskBar(SingleSel);
+ ForceLBRedraw();
+ }
+}
+
+BOOLEAN
+DblSpaceCreate(
+ IN HWND hwndOwner
+ )
+
+/*++
+
+Routine Description:
+
+ Start the dialog box for the creation of a DoubleSpace volume.
+
+Arguments:
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ int result = DialogBox(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_DBLSPACE_CREATE),
+ hwndOwner,
+ CreateDblSpaceDlgProc);
+ if (result)
+ {
+ DrawDiskBar(SingleSel);
+ ForceLBRedraw();
+ }
+ return (result > 0) ? TRUE : FALSE;
+}
+
+BOOL CALLBACK
+DblSpaceMountDlgProc(
+ IN HWND hDlg,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Handle the dialog for DoubleSpace.
+
+Arguments:
+
+ Standard Windows dialog procedure.
+
+Return Value:
+
+ TRUE if something was deleted.
+ FALSE otherwise.
+
+--*/
+
+{
+ static PDBLSPACE_DESCRIPTOR dblSpace;
+
+ HWND hwndCombo;
+ DWORD selection;
+ WCHAR driveLetter;
+ WCHAR driveLetterString[3];
+
+ switch (wMsg)
+ {
+ case WM_INITDIALOG:
+
+ dblSpace = (PDBLSPACE_DESCRIPTOR) lParam;
+
+ // Update the drive letter selections.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLDRIVELET_LETTER_CHOICES);
+
+ // Add all other available letters. Keep track of current
+ // letters offset to set the cursor correctly
+
+ driveLetterString[1] = TEXT(':');
+ driveLetterString[2] = TEXT('\0');
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ if (DriveLetterIsAvailable(driveLetter)
+ || (driveLetter == dblSpace->DriveLetter))
+ {
+ driveLetterString[0] = driveLetter;
+ ComboBox_AddString(hwndCombo, driveLetterString);
+ }
+ }
+
+ // set the current selection to the appropriate index
+
+ ComboBox_SetCurSel(hwndCombo, 0);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDHELP:
+
+ DialogHelp(HC_DM_DLG_DOUBLESPACE_MOUNT);
+ break;
+
+ case IDCANCEL:
+
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDOK:
+
+ // User has selected the drive letter and wants the mount to occur.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLDRIVELET_LETTER_CHOICES);
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, driveLetterString);
+ dblSpace->NewDriveLetter = driveLetterString[0];
+ EndDialog(hDlg, TRUE);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+VOID
+DblSpaceSetDialogState(
+ IN HWND hDlg,
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ )
+
+/*++
+
+Routine Description:
+
+ Given a DoubleSpace volume this routine will update the buttons
+ in the dialog box to reflect they meaning.
+
+Arguments:
+
+ hDlg - dialog handle
+ DblSpace - The DoubleSpace volume selection for determining dialog state.
+
+Return Value
+
+ None
+
+--*/
+
+{
+ TCHAR outputString[200];
+
+ if (DblSpace->Mounted)
+ {
+ LoadString(g_hInstance,
+ IDS_DBLSPACE_MOUNTED,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
+ LoadString(g_hInstance,
+ IDS_DISMOUNT,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_OR_DISMOUNT, outputString);
+
+ outputString[0] = DblSpace->DriveLetter;
+ outputString[1] = TEXT(':');
+ outputString[2] = TEXT('\0');
+ SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
+ }
+ else
+ {
+ LoadString(g_hInstance,
+ IDS_DBLSPACE_DISMOUNTED,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
+ LoadString(g_hInstance,
+ IDS_MOUNT,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_OR_DISMOUNT, outputString);
+
+ outputString[0] = TEXT(' ');
+ outputString[1] = TEXT(' ');
+ outputString[2] = TEXT('\0');
+ SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
+ }
+}
+
+
+BOOL CALLBACK
+DblSpaceDlgProc(
+ IN HWND hDlg,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Handle the dialog for DoubleSpace.
+
+Arguments:
+
+Return Value:
+
+ TRUE if something was deleted.
+ FALSE otherwise.
+
+--*/
+
+{
+ static PREGION_DESCRIPTOR regionDescriptor;
+ static PPERSISTENT_REGION_DATA regionData;
+ static PDBLSPACE_DESCRIPTOR firstDblSpace;
+
+ PDBLSPACE_DESCRIPTOR dblSpace;
+ WCHAR outputString[200];
+ DWORD selection;
+ BOOLEAN result;
+ ULONG errorMessage;
+ HWND hwndCombo;
+ HWND hwndMountButton;
+ HWND hwndDeleteButton;
+
+ switch (wMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
+
+ // place all DoubleSpace file names in the selection
+ // box and remember the first name.
+
+ for (firstDblSpace
+ = dblSpace
+ = DblSpaceGetNextVolume(regionDescriptor, NULL);
+ NULL != dblSpace;
+ dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace))
+ {
+ wsprintf(outputString, TEXT("%s"), dblSpace->FileName);
+ ComboBox_AddString(hwndCombo, outputString);
+ }
+ ComboBox_SetCurSel(hwndCombo, 0);
+
+ // add the drive letter
+
+ hwndMountButton = GetDlgItem(hDlg, IDC_MOUNT_OR_DISMOUNT);
+ hwndDeleteButton = GetDlgItem(hDlg, IDC_DBLSPACE_DELETE);
+
+ if (firstDblSpace)
+ {
+ // update the allocated size.
+
+ wsprintf(outputString, TEXT("%u"), firstDblSpace->AllocatedSize);
+ SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
+
+ // update mount state
+
+ DblSpaceSetDialogState(hDlg, firstDblSpace);
+ EnableWindow(hwndMountButton, TRUE);
+ EnableWindow(hwndDeleteButton, TRUE);
+ }
+ else
+ {
+ // update the Mount/Dismount button to say mount and grey it
+
+ LoadString(g_hInstance,
+ IDS_MOUNT,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_OR_DISMOUNT, outputString);
+ EnableWindow(hwndMountButton, FALSE);
+ EnableWindow(hwndDeleteButton, FALSE);
+ }
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (wParam)
+ {
+ case IDHELP:
+
+ DialogHelp(HC_DM_DLG_DOUBLESPACE);
+ break;
+
+ case IDCANCEL:
+
+ // Run the dblspace change and forget about any changes.
+
+ for (dblSpace = firstDblSpace;
+ NULL != dblSpace;
+ dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace))
+ {
+ dblSpace->ChangeMountState = FALSE;
+ dblSpace->NewDriveLetter = TEXT('\0');
+ }
+ EndDialog(hDlg, FALSE);
+ break;
+
+ case IDOK:
+
+ EndDialog(hDlg, TRUE);
+ break;
+
+ case IDC_DBLSPACE_ADD:
+
+ DblSpaceCreate(hDlg);
+ break;
+
+ case IDC_DBLSPACE_DELETE:
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, outputString);
+
+ // relate the name to a DoubleSpace volume
+
+ dblSpace = DblSpaceFindVolume(regionDescriptor, outputString);
+ if (NULL == dblSpace)
+ {
+ break;
+ }
+
+ DblSpaceDelete(dblSpace);
+ break;
+
+ case IDC_MOUNT_OR_DISMOUNT:
+
+ // The state of something in the dialog changed.
+ // Determine which DoubleSpace volume is involved.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, outputString);
+
+ // relate the name to a DoubleSpace volume
+
+ dblSpace = DblSpaceFindVolume(regionDescriptor, outputString);
+ if (NULL == dblSpace)
+ {
+ break;
+ }
+
+ if (dblSpace->Mounted)
+ {
+ // dismount the volume
+
+ errorMessage = DblSpaceDismountDrive(regionDescriptor,
+ dblSpace);
+
+ if (errorMessage)
+ {
+ ErrorDialog(errorMessage);
+ }
+ else
+ {
+ // Update the dialog
+
+ DblSpaceSetDialogState(hDlg, dblSpace);
+ DblSpaceUpdateIniFile(regionDescriptor);
+ }
+ }
+ else
+ {
+ // mount the volume unless the user cancels out
+
+ result = DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_DBLSPACE_DRIVELET),
+ hDlg,
+ DblSpaceMountDlgProc,
+ (LPARAM)dblSpace);
+ if (result)
+ {
+ errorMessage = DblSpaceMountDrive(regionDescriptor, dblSpace);
+
+ if (errorMessage)
+ {
+ ErrorDialog(errorMessage);
+ }
+ else
+ {
+ // Update the dialog
+
+ DblSpaceSetDialogState(hDlg, dblSpace);
+ DblSpaceUpdateIniFile(regionDescriptor);
+ }
+ }
+ }
+ DrawDiskBar(SingleSel);
+ ForceLBRedraw();
+ break;
+
+ default:
+
+ // The state of something in the dialog changed.
+ // Determine which DoubleSpace volume is involved.
+
+ hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, outputString);
+
+ // relate the name to a DoubleSpace volume
+
+ hwndMountButton = GetDlgItem(hDlg, IDC_MOUNT_OR_DISMOUNT);
+ hwndDeleteButton = GetDlgItem(hDlg, IDC_DBLSPACE_DELETE);
+
+ dblSpace = DblSpaceFindVolume(regionDescriptor, outputString);
+ if (NULL == dblSpace)
+ {
+ // update the Mount/Dismount button to say mount and grey it
+
+ LoadString(g_hInstance,
+ IDS_MOUNT,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hDlg, IDC_MOUNT_OR_DISMOUNT, outputString);
+ EnableWindow(hwndMountButton, FALSE);
+ EnableWindow(hwndDeleteButton, FALSE);
+ break;
+ }
+ else
+ {
+ EnableWindow(hwndMountButton, TRUE);
+ EnableWindow(hwndDeleteButton, TRUE);
+ }
+
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ // update the allocated/compressed size items
+
+ wsprintf(outputString, TEXT("%u"), dblSpace->AllocatedSize);
+ SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
+
+ // update mount state
+
+ DblSpaceSetDialogState(hDlg, dblSpace);
+ }
+
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+VOID
+DblSpace(
+ IN HWND hwndParent
+ )
+
+/*++
+
+Routine Description:
+
+ Start the dialog box for DoubleSpace.
+
+Arguments:
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ int result;
+
+ if (g_IsFullDoubleSpace)
+ {
+ result = DialogBox(g_hInstance,
+ MAKEINTRESOURCE(IDD_DBLSPACE_FULL),
+ hwndParent,
+ DblSpaceDlgProc);
+
+ }
+ else
+ {
+ result = DialogBox(g_hInstance,
+ MAKEINTRESOURCE(IDD_DBLSPACE),
+ hwndParent,
+ DblSpaceDlgProc);
+ }
+ if (result)
+ {
+ DrawDiskBar(SingleSel);
+ ForceLBRedraw();
+ }
+}
+
+#endif // DBLSPACE_ENABLED
diff --git a/private/utils/windisk/src/dblspace.dlg b/private/utils/windisk/src/dblspace.dlg
new file mode 100644
index 000000000..7b0b382ec
--- /dev/null
+++ b/private/utils/windisk/src/dblspace.dlg
@@ -0,0 +1,115 @@
+1 DLGINCLUDE "dblspace.H"
+
+IDD_ADDDBL DIALOG 5, 17, 212, 57
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Add DoubleSpace Drive"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Drive appears as:", -1, 7, 8, 68, 12
+ LTEXT "Drive label:", -1, 8, 23, 68, 12, NOT WS_GROUP
+ LTEXT "Size of drive (MB):", -1, 7, 37, 68, 12, NOT WS_GROUP
+ COMBOBOX IDC_ADDDBL_DRIVELETTER, 80, 6, 33, 35, CBS_DROPDOWNLIST |
+ CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ EDITTEXT IDC_ADDDBL_LABEL, 80, 22, 77, 12, ES_AUTOHSCROLL
+ EDITTEXT IDC_ADDDBL_SIZE, 80, 37, 55, 12, ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK", IDOK, 166, 3, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 166, 20, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 166, 39, 40, 14
+END
+
+IDD_DBLSPACE_CANCEL DIALOG 7, 18, 160, 65
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Create DoubleSpace Volume"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CTEXT "", IDC_DBLPROG_Title, 15, 36, 131, 8
+ CONTROL "", IDC_DBLPROG_GasGauge, "Static", SS_BLACKFRAME, 15,
+ 10, 131, 22
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 60, 45, 40, 14
+END
+
+IDD_DBLSPACE DIALOG 10, 28, 180, 115
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "DoubleSpace Volumes"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Volume Names", -1, 10, 15, 90, 8
+ COMBOBOX IDC_DBLSPACE_VOLUME, 10, 25, 100, 45, CBS_SIMPLE |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Allocated Size:", -1, 10, 80, 55, 8
+ LTEXT "", IDC_DBLSPACE_ALLOCATED, 70, 80, 19, 8
+ LTEXT "MB", -1, 90, 80, 15, 8
+ LTEXT "", IDC_MOUNT_STATE, 10, 92, 140, 8
+ LTEXT "", IDC_DBLSPACE_LETTER, 155, 92, 22, 8
+ DEFPUSHBUTTON "", IDC_MOUNT_OR_DISMOUNT, 130, 5, 40, 14
+ DEFPUSHBUTTON "&Done", IDOK, 130, 24, 40, 14
+ DEFPUSHBUTTON "&Help", IDHELP, 130, 43, 40, 14
+END
+
+IDD_DBLSPACE_FULL DIALOG 11, 28, 180, 125
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "DoubleSpace Volumes"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Volume Names", -1, 10, 15, 90, 8
+ COMBOBOX IDC_DBLSPACE_VOLUME, 10, 25, 100, 45, CBS_SIMPLE |
+ WS_VSCROLL | WS_TABSTOP
+ LTEXT "Allocated Size:", -1, 10, 75, 54, 8
+ LTEXT "", IDC_DBLSPACE_ALLOCATED, 75, 75, 14, 8
+ LTEXT "MB", -1, 90, 75, 15, 8
+ LTEXT "", IDC_MOUNT_STATE, 10, 85, 83, 8
+ LTEXT "", IDC_DBLSPACE_LETTER, 99, 85, 22, 8
+ DEFPUSHBUTTON "Create", IDC_DBLSPACE_ADD, 130, 5, 40, 14
+ DEFPUSHBUTTON "Delete", IDC_DBLSPACE_DELETE, 130, 24, 40, 14
+ DEFPUSHBUTTON "", IDC_MOUNT_OR_DISMOUNT, 130, 43, 40, 14
+ DEFPUSHBUTTON "&Done", IDOK, 130, 62, 40, 14
+ DEFPUSHBUTTON "&Help", IDHELP, 130, 80, 40, 14
+END
+
+IDD_DBLSPACE_CREATE DIALOG 10, 28, 183, 102
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Create DoubleSpace Volume"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Minimum Size", IDC_MINMAX_MINLABEL, 10, 8, 70, 8
+ LTEXT "Maximum Size", IDC_MINMAX_MAXLABEL, 10, 18, 70, 8
+ RTEXT "", IDC_MINMAX_MIN, 75, 8, 25, 8
+ RTEXT "", IDC_MINMAX_MAX, 75, 18, 25, 8
+ LTEXT "MB", -1, 112, 8, 11, 8
+ LTEXT "MB", -1, 112, 18, 11, 8
+ LTEXT "&Allocated size:", -1, 10, 35, 62, 8
+ EDITTEXT IDC_DBLCREATE_SIZE, 75, 35, 35, 12, ES_AUTOHSCROLL
+ CONTROL "", IDC_DBLCREATE_ALLOCATED, "msctls_updown32", 0x0000,
+ 103, 35, 7, 12
+ LTEXT "MB", -1, 112, 35, 11, 8
+ LTEXT "Compressed size:", -1, 10, 50, 70, 8
+ RTEXT "", IDC_DBLCREATE_COMPRESSED, 75, 50, 25, 8
+ LTEXT "MB", -1, 112, 50, 11, 8
+ LTEXT "&Drive Letter", IDC_DBLCREATE_LETTER, 10, 65, 50, 8
+ COMBOBOX IDC_DBLCREATE_LETTER_CHOICES, 60, 65, 22, 51,
+ CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Label", -1, 10, 85, 50, 8
+ EDITTEXT IDC_DBLCREATE_NAME, 60, 85, 63, 12
+ DEFPUSHBUTTON "OK", IDOK, 135, 10, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 135, 30, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 135, 50, 40, 14
+END
+
+IDD_DBLSPACE_DRIVELET DIALOG 11, 28, 140, 68
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Mount DoubleSpace Volume as..."
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK", IDOK, 90, 6, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 90, 23, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 90, 43, 40, 14
+ LTEXT "&Drive Letter", IDC_DBLDRIVELET_LETTER, 10, 10, 50, 8
+ COMBOBOX IDC_DBLDRIVELET_LETTER_CHOICES, 60, 10, 22, 51,
+ CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
diff --git a/private/utils/windisk/src/dblspace.h b/private/utils/windisk/src/dblspace.h
new file mode 100644
index 000000000..d74a63871
--- /dev/null
+++ b/private/utils/windisk/src/dblspace.h
@@ -0,0 +1,91 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dblspace.h
+//
+// Contents: Constants for Disk Administrator dialogs
+//
+// History: 16-Aug-93 BruceFo Created
+//
+// Notes: These values are in the range 7000 to 8999, with every
+// 100 being a separate dialog.
+//
+//----------------------------------------------------------------------------
+
+//
+// This IDHELP definition is redundant with windows.h, but makes dlgedit
+// happy.
+//
+
+#ifndef IDHELP
+#define IDHELP 9
+#endif
+
+
+//
+// Min/Max dialog
+//
+
+#define IDC_MINMAX_MINLABEL 7801
+#define IDC_MINMAX_MAXLABEL 7802
+#define IDC_MINMAX_MIN 7804
+#define IDC_MINMAX_MAX 7805
+
+//
+// "Add DoubleSpace Drive" dialog
+//
+
+#define IDD_ADDDBL 9100
+
+#define IDC_ADDDBL_LABEL 9101
+#define IDC_ADDDBL_SIZE 9102
+#define IDC_ADDDBL_DRIVELETTER 9103
+
+//
+//
+//
+
+#define IDD_DBLSPACE 9300
+#define IDD_DBLSPACE_FULL 9301
+
+#define IDC_DBLSPACE_VOLUME 9302
+#define IDC_DBLSPACE_ALLOCATED 9303
+#define IDC_DBLSPACE_LETTER 9305
+#define IDC_MOUNT_STATE 9306
+#define IDC_MOUNT_OR_DISMOUNT 9307
+#define IDC_DBLSPACE_ADD 9308
+#define IDC_DBLSPACE_DELETE 9309
+
+//
+// Create DoubleSpace volume dialog. Uses Min/Max control ids.
+//
+
+#define IDD_DBLSPACE_CREATE 9400
+
+#define IDC_DBLCREATE_SIZE 9401
+#define IDC_DBLCREATE_ALLOCATED 9402
+#define IDC_DBLCREATE_COMPRESSED 9403
+#define IDC_DBLCREATE_LETTER 9404
+#define IDC_DBLCREATE_LETTER_CHOICES 9405
+#define IDC_DBLCREATE_NAME 9406
+
+
+//
+//
+//
+
+#define IDD_DBLSPACE_DRIVELET 9800
+
+#define IDC_DBLDRIVELET_LETTER 9801
+#define IDC_DBLDRIVELET_LETTER_CHOICES 9802
+
+//
+//
+//
+
+#define IDD_DBLSPACE_CANCEL 9900
+
+#define IDC_DBLPROG_GasGauge 9901
+#define IDC_DBLPROG_Title 9902
diff --git a/private/utils/windisk/src/dblspace.hxx b/private/utils/windisk/src/dblspace.hxx
new file mode 100644
index 000000000..0859321ff
--- /dev/null
+++ b/private/utils/windisk/src/dblspace.hxx
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dblspace.hxx
+//
+// Contents: Declarations for DoubleSpace support
+//
+// History: 15-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DBLSPACE_HXX__
+#define __DBLSPACE_HXX__
+
+#if defined( DBLSPACE_ENABLED )
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+DblSpaceVolumeExists(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+BOOL
+DblSpaceDismountedVolumeExists(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+BOOLEAN
+DblSpaceCreate(
+ IN HWND hwndOwner
+ );
+
+VOID
+DblSpaceDelete(
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ );
+
+VOID
+DblSpaceInitialize(
+ VOID
+ );
+
+VOID
+DblSpace(
+ IN HWND hwndParent
+ );
+
+PDBLSPACE_DESCRIPTOR
+DblSpaceGetNextVolume(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ IN PDBLSPACE_DESCRIPTOR DblSpace
+ );
+
+#endif // DBLSPACE_ENABLED
+
+#endif // __DBLSPACE_HXX__
diff --git a/private/utils/windisk/src/dblspace.res b/private/utils/windisk/src/dblspace.res
new file mode 100644
index 000000000..1db90bf6c
--- /dev/null
+++ b/private/utils/windisk/src/dblspace.res
Binary files differ
diff --git a/private/utils/windisk/src/dialogs.dlg b/private/utils/windisk/src/dialogs.dlg
new file mode 100644
index 000000000..6389a8b2c
--- /dev/null
+++ b/private/utils/windisk/src/dialogs.dlg
@@ -0,0 +1,126 @@
+1 DLGINCLUDE "dialogs.h"
+
+IDD_DISPLAYOPTIONS DIALOG 6, 18, 211, 156
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Region Display Options"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ COMBOBOX IDC_DISK_COMBOBOX, 65, 51, 30, 40, CBS_DROPDOWNLIST |
+ CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Reset All", IDC_RESETALL, 146, 25, 48, 16, WS_GROUP
+ AUTORADIOBUTTON "Size regions based on &actual size", IDC_RBPROPORTIONAL,
+ 18, 84, 158, 10, WS_GROUP | WS_TABSTOP
+ AUTORADIOBUTTON "Size all regions &equally", IDC_RBEQUAL, 18, 96, 158,
+ 10
+ AUTORADIOBUTTON "&Let Disk Administrator decide how to size regions",
+ IDC_RBAUTO, 18, 108, 173, 10
+ DEFPUSHBUTTON "OK", IDOK, 29, 135, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 85, 135, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 141, 135, 40, 14
+ GROUPBOX "Which disk", -1, 17, 19, 115, 53
+ AUTORADIOBUTTON "&All disks", IDC_AllDisks, 24, 33, 101, 10
+ AUTORADIOBUTTON "For &disk", IDC_OneDisk, 24, 51, 40, 10
+END
+
+IDD_DISKOPTIONS DIALOG 6, 18, 211, 61
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Disk Display Options"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ AUTORADIOBUTTON "&Size disks based on actual size", IDC_DISKPROPORTIONAL,
+ 23, 8, 158, 10, WS_GROUP | WS_TABSTOP
+ AUTORADIOBUTTON "Size all disks &equally", IDC_DISKEQUAL, 23, 20, 158,
+ 10
+ DEFPUSHBUTTON "OK", IDOK, 25, 41, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 81, 41, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 137, 41, 40, 14
+END
+
+IDD_MINMAX DIALOG 3, 15, 221, 131
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "", IDC_MINMAX_MINLABEL, 10, 18, 136, 8
+ LTEXT "", IDC_MINMAX_MAXLABEL, 10, 30, 136, 8
+ LTEXT "", IDC_MINMAX_SIZLABEL, 10, 54, 136, 8
+ LTEXT "MB", -1, 202, 18, 11, 8
+ LTEXT "MB", -1, 202, 30, 11, 8
+ LTEXT "MB", -1, 202, 54, 11, 8
+ RTEXT "", IDC_MINMAX_MIN, 151, 18, 46, 8
+ RTEXT "", IDC_MINMAX_MAX, 151, 30, 46, 8
+ EDITTEXT IDC_MINMAX_SIZE, 161, 52, 37, 12, ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK", IDOK, 35, 111, 40, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 91, 111, 40, 14
+ PUSHBUTTON "&Help", IDHELP, 147, 111, 40, 14
+END
+
+IDD_DRIVELET DIALOG 6, 18, 180, 124
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Assign Drive Letter"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "", IDC_DRIVELET_DESCR, 14, 12, 152, 16
+ GROUPBOX "", -1, 19, 30, 142, 58
+ AUTORADIOBUTTON "&Assign drive letter", IDC_DRIVELET_RBASSIGN, 36, 46,
+ 70, 10
+ AUTORADIOBUTTON "Do &not assign a drive letter", IDC_DRIVELET_RBNOASSIGN,
+ 36, 64, 100, 10
+ COMBOBOX IDC_DRIVELET_COMBOBOX, 109, 46, 24, 77, CBS_DROPDOWNLIST |
+ CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 15, 101, 40, 17
+ PUSHBUTTON "Cancel", IDCANCEL, 70, 101, 40, 17
+ PUSHBUTTON "&Help", IDHELP, 125, 101, 40, 17
+END
+
+IDD_COLORS DIALOG 4, 16, 289, 131
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Colors and Patterns"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Color &and pattern for:", -1, 10, 8, 229, 8
+ COMBOBOX IDC_COLORDLGCOMBO, 10, 21, 267, 65, CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "&Colors", -1, 10, 39, 106, 80, WS_GROUP
+ CONTROL "", IDC_COLOR1, "RectControl", 0x0002, 27, 55, 15, 11
+ CONTROL "", IDC_COLOR2, "RectControl", 0x0002, 27, 69, 15, 11
+ CONTROL "", IDC_COLOR3, "RectControl", 0x0002, 27, 83, 15, 11
+ CONTROL "", IDC_COLOR4, "RectControl", 0x0002, 27, 97, 15, 11
+ CONTROL "", IDC_COLOR5, "RectControl", 0x0002, 46, 55, 15, 11
+ CONTROL "", IDC_COLOR6, "RectControl", 0x0002, 46, 69, 15, 11
+ CONTROL "", IDC_COLOR7, "RectControl", 0x0002, 46, 83, 15, 11
+ CONTROL "", IDC_COLOR8, "RectControl", 0x0002, 46, 97, 15, 11
+ CONTROL "", IDC_COLOR9, "RectControl", 0x0002, 65, 55, 15, 11
+ CONTROL "", IDC_COLOR10, "RectControl", 0x0002, 65, 69, 15, 11
+ CONTROL "", IDC_COLOR11, "RectControl", 0x0002, 65, 83, 15, 11
+ CONTROL "", IDC_COLOR12, "RectControl", 0x0002, 65, 97, 15, 11
+ CONTROL "", IDC_COLOR13, "RectControl", 0x0002, 84, 55, 15, 11
+ CONTROL "", IDC_COLOR14, "RectControl", 0x0002, 84, 69, 15, 11
+ CONTROL "", IDC_COLOR15, "RectControl", 0x0002, 84, 83, 15, 11
+ CONTROL "", IDC_COLOR16, "RectControl", 0x0002, 84, 97, 15, 11
+ GROUPBOX "&Patterns", -1, 127, 39, 94, 80, WS_GROUP
+ CONTROL "", IDC_PATTERN1, "RectControl", 0x0001, 142, 55, 27, 15
+ CONTROL "", IDC_PATTERN2, "RectControl", 0x0001, 142, 74, 27, 15
+ CONTROL "", IDC_PATTERN3, "RectControl", 0x0001, 142, 93, 27, 15
+ CONTROL "", IDC_PATTERN4, "RectControl", 0x0001, 179, 55, 27, 15
+ CONTROL "", IDC_PATTERN5, "RectControl", 0x0001, 179, 74, 27, 15
+ CONTROL "", IDC_PATTERN6, "RectControl", 0x0001, 179, 93, 27, 15
+ DEFPUSHBUTTON "OK", IDOK, 233, 44, 44, 18, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 233, 71, 44, 18
+ PUSHBUTTON "&Help", IDHELP, 233, 98, 44, 18
+END
+
+IDD_STARTUP DIALOG 4, 15, 160, 45
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "Disk Administrator is initializing"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CTEXT "", IDC_TEXT, 0, 32, 160, 8
+ CONTROL "", IDC_GASGAUGE, "Static", SS_BLACKFRAME, 12, 7, 136,
+ 22
+END
diff --git a/private/utils/windisk/src/dialogs.h b/private/utils/windisk/src/dialogs.h
new file mode 100644
index 000000000..04e1d84ae
--- /dev/null
+++ b/private/utils/windisk/src/dialogs.h
@@ -0,0 +1,263 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dialogs.h
+//
+// Contents: Constants for Disk Administrator dialogs
+//
+// History: 16-Aug-93 BruceFo Created
+//
+// Notes: These values are in the range 7000 to 8999, with every
+// 100 being a separate dialog.
+//
+//----------------------------------------------------------------------------
+
+//
+// This IDHELP definition is redundant with windows.h, but makes dlgedit
+// happy.
+//
+
+#ifndef IDHELP
+#define IDHELP 9
+#endif
+
+//
+// The first 100 are reserved for common ids
+//
+
+#define IDC_Label_Text 7000
+#define IDC_Label 7001
+
+//
+// The rest are specific to various dialogs
+//
+
+//
+// Format dialog
+//
+
+#define IDD_FORMAT 7100
+
+#define IDC_FormatType_Text 7101
+#define IDC_FormatType 7102
+#define IDC_QuickFormat 7103
+
+//
+// Format progress dialog (w/ %done thermometer)
+//
+
+#define IDD_FORMATPROGRESS 7200
+#define IDD_FORMATPROGRESS_NOSTOP 7201
+
+#define IDC_FMTPROG_GasGauge 7202
+#define IDC_FMTPROG_Title 7203
+
+//
+// "Are you sure you want to stop formatting?" dialog
+//
+
+#define IDD_StopFmt 7300
+
+#define IDC_StopFmt_Stop 7301
+#define IDC_StopFmt_Continue 7302
+#define IDC_StopFmt_Text 7303
+
+//
+// Property sheet "general" page dialog
+//
+
+#define IDD_GENLPAGE 7400
+
+#define IDC_DriveStatus 7401
+#define IDC_FileSystem 7402
+#define IDC_DriveLetter 7403
+#define IDC_FreeColor 7404
+#define IDC_FreeSpace 7405
+#define IDC_FreeSpaceMB 7406
+#define IDC_UsedColor 7407
+#define IDC_UsedSpace 7408
+#define IDC_UsedSpaceMB 7409
+#define IDC_Capacity 7410
+#define IDC_CapacityMB 7411
+#define IDC_Refresh 7412
+#define IDC_Graph 7413
+#define IDC_CheckNow 7415
+#define IDC_Format 7416
+#define IDC_Line1 7417
+#define IDC_Line2 7418
+#define IDC_Line3 7419
+#define IDC_GENL_Label 7420
+
+#define IDC_GENL_1 7430
+#define IDC_GENL_2 7431
+#define IDC_GENL_3 7432
+#define IDC_GENL_4 7433
+#define IDC_GENL_5 7434
+#define IDC_GENL_6 7435
+#define IDC_GENL_7 7436
+
+
+//
+// Options dialog
+//
+
+#define IDD_DISPLAYOPTIONS 7600
+
+#define IDC_DISK_COMBOBOX 7601
+#define IDC_RESETALL 7602
+#define IDC_RBPROPORTIONAL 7603
+#define IDC_RBEQUAL 7604
+#define IDC_RBAUTO 7605
+
+// NOTE: IDC_AllDisks & IDC_OneDisk must be sequential, in that order
+
+#define IDC_AllDisks 7606
+#define IDC_OneDisk 7607
+
+//
+// Disk display dialog
+//
+
+#define IDD_DISKOPTIONS 7700
+
+// NOTE: IDC_DISKPROPORTIONAL & IDC_DISKEQUAL must be sequential, in
+// that order
+
+#define IDC_DISKPROPORTIONAL 7701
+#define IDC_DISKEQUAL 7702
+
+//
+// Min/Max dialog
+//
+
+#define IDD_MINMAX 7800
+
+#define IDC_MINMAX_MINLABEL 7801
+#define IDC_MINMAX_MAXLABEL 7802
+#define IDC_MINMAX_SIZLABEL 7803
+#define IDC_MINMAX_MIN 7804
+#define IDC_MINMAX_MAX 7805
+#define IDC_MINMAX_SIZE 7806
+#define IDC_MINMAX_SCROLL 7807
+
+//
+// Drive letter dialog
+//
+
+#define IDD_DRIVELET 7900
+
+#define IDC_DRIVELET_RBASSIGN 7901
+#define IDC_DRIVELET_RBNOASSIGN 7902
+#define IDC_DRIVELET_DESCR 7903
+#define IDC_DRIVELET_COMBOBOX 7904
+
+//
+// Colors & patters dialog
+//
+
+#define IDD_COLORS 8000
+
+#define IDC_COLORDLGCOMBO 8001
+#define IDC_COLOR1 8002
+#define IDC_COLOR2 8003
+#define IDC_COLOR3 8004
+#define IDC_COLOR4 8005
+#define IDC_COLOR5 8006
+#define IDC_COLOR6 8007
+#define IDC_COLOR7 8008
+#define IDC_COLOR8 8009
+#define IDC_COLOR9 8010
+#define IDC_COLOR10 8011
+#define IDC_COLOR11 8012
+#define IDC_COLOR12 8013
+#define IDC_COLOR13 8014
+#define IDC_COLOR14 8015
+#define IDC_COLOR15 8016
+#define IDC_COLOR16 8017
+#define IDC_PATTERN1 8018
+#define IDC_PATTERN2 8019
+#define IDC_PATTERN3 8020
+#define IDC_PATTERN4 8021
+#define IDC_PATTERN5 8022
+#define IDC_PATTERN6 8023
+
+//
+// "chkdsk" dialog
+//
+
+#define IDD_CHKDSK 8500
+
+#define IDC_CHKDSK_VolumeToCheck 8501
+
+// note: the following 3 are radio buttons, in order
+
+#define IDC_CHKDSK_DontFix 8502
+#define IDC_CHKDSK_Fix 8503
+#define IDC_CHKDSK_FixAll 8504
+
+//
+// Chkdsk progress dialog, w/ %done thermometer
+//
+
+#define IDD_CHKDSKPROGRESS 8600
+#define IDD_CHKDSKPROGRESS_NOSTOP 8601
+#define IDD_CHKDSKPROGRESS_NOPERCENT 9200
+#define IDD_CHKDSKPROGRESS_NOSTOP_NOPERCENT 9700
+
+#define IDC_CHKPROG_Title 8602
+#define IDC_CHKPROG_GasGauge 8603
+#define IDC_CHKPROG_GasGaugeCaption 8604
+
+//
+// "Are you sure you want to stop checking" dialog
+//
+
+#define IDD_StopChk 8700
+
+#define IDC_StopChk_Text 8701
+#define IDC_StopChk_Stop 8702
+#define IDC_StopChk_Continue 8703
+
+//
+// "printing chkdsk results" dialog
+//
+
+#define IDD_CHKPRINT 8800
+
+//
+// Chkdsk results dialog
+//
+
+#define IDD_CHKDONE 8900
+
+#define IDC_CHKDONE_Messages 8901
+#define IDC_CHKDONE_Close 8902
+#define IDC_CHKDONE_TITLE 8903
+#define IDC_CHKDONE_Save 8904
+#define IDC_CHKDONE_Print 8905
+
+//
+// "label" dialog
+//
+
+#define IDD_LABEL 9000
+
+#define IDC_LABEL 9001
+
+//
+// Startup dialog
+//
+
+#define IDD_STARTUP 11000
+
+//
+// CD-ROM property page
+//
+
+#define IDD_CDROMPAGE 200
+#define IDC_TEXT 11001
+#define IDC_GASGAUGE 11002
+
+#define IDI_STOP_SIGN 3002
diff --git a/private/utils/windisk/src/dialogs.res b/private/utils/windisk/src/dialogs.res
new file mode 100644
index 000000000..18152dd1d
--- /dev/null
+++ b/private/utils/windisk/src/dialogs.res
Binary files differ
diff --git a/private/utils/windisk/src/dispinfo.cxx b/private/utils/windisk/src/dispinfo.cxx
new file mode 100644
index 000000000..1028cd3fe
--- /dev/null
+++ b/private/utils/windisk/src/dispinfo.cxx
@@ -0,0 +1,126 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dispinfo.cxx
+//
+// Contents: Encapsulates display information for windisk
+//
+// History: 27-Oct-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdio.h>
+#include "dispinfo.hxx"
+
+CDispInfo::CDispInfo(
+ VOID
+ )
+{
+ for (int i = 0; i < g_cColumns; i++)
+ {
+ apsz[i] = NULL;
+ }
+}
+
+CDispInfo::~CDispInfo()
+{
+ for (int i = 0; i < g_cColumns; i++)
+ {
+ delete[] apsz[i];
+ }
+}
+
+BOOL
+CDispInfo::SetText(
+ IN int column,
+ IN PWSTR pszString
+ )
+{
+ if (column < 0 || column > g_cColumns - 1)
+ {
+ return FALSE; // this should really be an assertion
+ }
+
+ if (NULL != apsz[column])
+ {
+ delete[] apsz[column];
+ }
+
+ int cchLen = wcslen(pszString);
+ apsz[column] = new WCHAR[cchLen + 1];
+ if (NULL == apsz[column])
+ {
+ return FALSE; // BUGBUG: out of memory!
+ }
+
+ wcscpy(apsz[column], pszString);
+ return TRUE;
+}
+
+BOOL
+CDispInfo::SetNumber(
+ IN int column,
+ IN LONG lNum
+ )
+{
+ if (column < 0 || column > g_cColumns - 1)
+ {
+ return FALSE; // this should really be an assertion
+ }
+
+ if (NULL != apsz[column])
+ {
+ delete[] apsz[column];
+ }
+
+ WCHAR szNum[50];
+ wsprintf(szNum, L"%ld", lNum);
+ int cchLen = wcslen(szNum);
+ apsz[column] = new WCHAR[cchLen + 1];
+ if (NULL == apsz[column])
+ {
+ return FALSE; // BUGBUG: out of memory!
+ }
+
+ wcscpy(apsz[column], szNum);
+ return TRUE;
+}
+
+PWSTR
+CDispInfo::GetText(
+ IN int column
+ )
+{
+ if (column < 0 || column > g_cColumns - 1)
+ {
+ return NULL; // this should really be an assertion
+ }
+
+ return apsz[column];
+}
+
+LONG
+CDispInfo::GetNumber(
+ IN int column
+ )
+{
+ if (column < 0 || column > g_cColumns - 1)
+ {
+ return NULL; // this should really be an assertion
+ }
+
+ if (NULL == apsz[column])
+ {
+ return -1L; // better error code?
+ }
+
+ LONG lResult;
+ swscanf(apsz[column], L"%ld", &lResult);
+
+ return lResult;
+}
diff --git a/private/utils/windisk/src/dispinfo.hxx b/private/utils/windisk/src/dispinfo.hxx
new file mode 100644
index 000000000..dbfbe462e
--- /dev/null
+++ b/private/utils/windisk/src/dispinfo.hxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dispinfo.hxx
+//
+// Contents: Encapsulates display information for windisk
+//
+// History: 27-Oct-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DISPINFO_HXX__
+#define __DISPINFO_HXX__
+
+#include <volview.hxx>
+
+class CDispInfo
+{
+public:
+
+ CDispInfo(
+ VOID
+ );
+
+ ~CDispInfo();
+
+ //
+ // Set the data
+ //
+
+ BOOL
+ SetText(
+ IN int column,
+ IN PWSTR pszString
+ );
+
+ BOOL
+ SetNumber(
+ IN int column,
+ IN LONG lNum
+ );
+
+ //
+ // Retrieve the data
+ //
+
+ PWSTR
+ GetText(
+ IN int column
+ );
+
+ LONG
+ GetNumber(
+ IN int column
+ );
+
+private:
+
+ PWSTR apsz[g_cColumns];
+
+};
+
+#endif // __DISPINFO_HXX__
diff --git a/private/utils/windisk/src/dlgs.cxx b/private/utils/windisk/src/dlgs.cxx
new file mode 100644
index 000000000..b7e5afdfe
--- /dev/null
+++ b/private/utils/windisk/src/dlgs.cxx
@@ -0,0 +1,1372 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dlgs.cxx
+//
+// Contents: Dialog routines and dialog support subroutines.
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "dialogs.h"
+#include "dlgs.hxx"
+#include "drives.hxx"
+#include "help.hxx"
+#include "rectpriv.hxx"
+#include "windisk.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+// used in color dialog to indicate what the user has chosen for
+// the various graph element types
+
+DWORD SelectedColor[LEGEND_STRING_COUNT];
+DWORD SelectedHatch[LEGEND_STRING_COUNT];
+
+// used in color dialog, contains element (ie, partition, logical volume,
+// etc) we're selecting for (ie, which item is diaplyed in static text of
+// combo box).
+
+DWORD CurrentElement;
+
+// hold old dialog proc for subclassed size control
+
+WNDPROC OldSizeDlgProc;
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+BOOL CALLBACK
+DisplayOptionsDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+BOOL CALLBACK
+DiskOptionsDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+HBRUSH
+MyCreateHatchBrush(
+ int fnStyle,
+ COLORREF clrref
+ )
+
+/*++
+
+Routine Description:
+
+ Same as Windows CreateHatchBrush, except you need to use MY_HS_*
+ identifiers, and I support solid "hatch" brushes.
+
+Arguments:
+
+ same as CreateHatchBrush
+
+Return Value:
+
+ same as CreateHatchBrush
+
+--*/
+
+{
+ int fnWindowsStyle;
+
+ switch (fnStyle)
+ {
+ case MY_HS_FDIAGONAL:
+ fnWindowsStyle = HS_FDIAGONAL;
+ goto tagDoHatch;
+
+ case MY_HS_BDIAGONAL:
+ fnWindowsStyle = HS_BDIAGONAL;
+ goto tagDoHatch;
+
+ case MY_HS_CROSS:
+ fnWindowsStyle = HS_CROSS;
+ goto tagDoHatch;
+
+ case MY_HS_DIAGCROSS:
+ fnWindowsStyle = HS_DIAGCROSS;
+ goto tagDoHatch;
+
+ case MY_HS_VERTICAL:
+ fnWindowsStyle = HS_VERTICAL;
+
+tagDoHatch:
+ return CreateHatchBrush(fnWindowsStyle, clrref);
+
+ case MY_HS_SOLIDCLR:
+ return CreateSolidBrush(clrref);
+
+ default:
+ daDebugOut((DEB_IERROR, "Internal error: bad hatch style!\n"));
+ return NULL;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+VOID
+CenterDialog(
+ HWND hwndToCenter,
+ HWND hwndContext
+ )
+
+/*++
+
+Routine Description:
+
+ Centers a dialog relative to hwndContext
+
+Arguments:
+
+ hwndToCenter - window handle of dialog to center
+ hwndContext - window handle of window to center with respect to
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ POINT point;
+ RECT rcContext, rcWindow;
+ LONG x, y, w, h;
+ LONG sx = GetSystemMetrics(SM_CXSCREEN);
+ LONG sy = GetSystemMetrics(SM_CYSCREEN);
+
+ point.x = point.y = 0;
+ if (hwndContext)
+ {
+ ClientToScreen(hwndContext, &point);
+ GetClientRect (hwndContext, &rcContext);
+ }
+ else
+ {
+ rcContext.top = rcContext.left = 0;
+ rcContext.right = sx;
+ rcContext.bottom = sy;
+ }
+ GetWindowRect (hwndToCenter, &rcWindow);
+
+ w = rcWindow.right - rcWindow.left + 1;
+ h = rcWindow.bottom - rcWindow.top + 1;
+ x = point.x + ((rcContext.right - rcContext.left + 1 - w) / 2);
+ y = point.y + ((rcContext.bottom - rcContext.top + 1 - h) / 2);
+
+ if (x + w > sx)
+ {
+ x = sx - w;
+ }
+ else if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (y + h > sy)
+ {
+ y = sy - h;
+ }
+ else if (y < 0)
+ {
+ y = 0;
+ }
+
+ if (FALSE == MoveWindow(hwndToCenter, x, y, w, h, FALSE))
+ {
+ daDebugOut((DEB_TRACE, "MoveWindow failed\n"));
+ }
+}
+
+
+
+VOID
+CenterDialogInFrame(
+ HWND hwnd
+ )
+
+/*++
+
+Routine Description:
+
+ Centers a dialog relative to the app's main window
+
+Arguments:
+
+ hwnd - window handle of dialog to center
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CenterDialog(hwnd, g_hwndFrame);
+}
+
+
+INT
+SizeDlgProc(
+ IN HWND hDlg,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine keeps non-numeric keystrokes out of the dialog
+ for the size of a volume.
+
+Arguments:
+
+ Windows dialog parameters.
+
+Return Value:
+
+ Windows dialog return values.
+ Returns FALSE for any characters that are not numeric.
+
+--*/
+
+{
+ WCHAR letter;
+
+ switch (wMsg)
+ {
+ case WM_CHAR:
+
+ letter = (WCHAR)wParam;
+ if ((letter == TEXT('\t')) || (letter == TEXT('\b')))
+ {
+ break;
+ }
+
+ if (letter >= TEXT('0') && letter <= TEXT('9'))
+ {
+ // do nothing
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ break;
+ }
+
+ return CallWindowProc(OldSizeDlgProc, hDlg, wMsg, wParam, lParam);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: SizeWndProc, public
+//
+// Synopsis: edit window subclass proc to disallow non-numeric characters.
+//
+// History: 5-Apr-95 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+LRESULT CALLBACK
+SizeWndProc(
+ IN HWND hwnd,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (wMsg)
+ {
+ case WM_CHAR:
+ {
+ WCHAR chCharCode = (WCHAR)wParam;
+ if ( (chCharCode == TEXT('\t'))
+ || (chCharCode == TEXT('\b'))
+ || (chCharCode == TEXT('\n'))
+ )
+ {
+ break;
+ }
+
+ if (chCharCode < TEXT('0') || chCharCode > TEXT('9'))
+ {
+ // bad key: ignore it
+ return FALSE;
+ }
+
+ break;
+ }
+ } // end of switch
+
+ WNDPROC pfnProc = (WNDPROC)GetWindowLong(hwnd,GWL_USERDATA);
+ return CallWindowProc(pfnProc, hwnd, wMsg, wParam, lParam);
+}
+
+
+BOOL CALLBACK
+MinMaxDlgProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog procedure for the enter size dialog box. This dialog
+ allows the user to enter a size for a partition, or use
+ spin controls (a tiny scroll bar) to select the size.
+ Possible outcomes are cancel or OK. In the latter case the
+ EndDialog code is the size. In the former it is 0.
+
+Arguments:
+
+ hwnd - window handle of dialog box
+
+ msg - message #
+
+ wParam - msg specific data
+
+ lParam - msg specific data
+
+Return Value:
+
+ msg dependent
+
+--*/
+
+{
+ static DWORD minSizeMB;
+ static DWORD maxSizeMB;
+ static DWORD helpContextId;
+
+ TCHAR outputString[MESSAGE_BUFFER_SIZE];
+ PMINMAXDLG_PARAMS params;
+ BOOL validNumber;
+ DWORD sizeMB;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ CenterDialogInFrame(hwnd);
+ params = (PMINMAXDLG_PARAMS)lParam;
+
+ // Subclass edit control to disallow non-positive numbers
+ WNDPROC pfnProc = (WNDPROC)SetWindowLong(
+ GetDlgItem(hwnd, IDC_MINMAX_SIZE),
+ GWL_WNDPROC,
+ (LONG)&SizeWndProc);
+ SetWindowLong(GetDlgItem(hwnd, IDC_MINMAX_SIZE), GWL_USERDATA, (LONG)pfnProc);
+
+ // set up caption
+
+ LoadString(
+ g_hInstance,
+ params->CaptionStringID,
+ outputString,
+ ARRAYLEN(outputString));
+ SetWindowText(hwnd, outputString);
+
+ // set up minimum/maximum text
+
+ LoadString(
+ g_hInstance,
+ params->MinimumStringID,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hwnd, IDC_MINMAX_MINLABEL, outputString);
+ LoadString(
+ g_hInstance,
+ params->MaximumStringID,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hwnd, IDC_MINMAX_MAXLABEL, outputString);
+ LoadString(
+ g_hInstance,
+ params->SizeStringID,
+ outputString,
+ ARRAYLEN(outputString));
+ SetDlgItemText(hwnd, IDC_MINMAX_SIZLABEL, outputString);
+
+ minSizeMB = params->MinSizeMB;
+ maxSizeMB = params->MaxSizeMB;
+ helpContextId = params->HelpContextId;
+
+ wsprintf(outputString, TEXT("%u"), minSizeMB);
+ SetDlgItemText(hwnd, IDC_MINMAX_MIN, outputString);
+ wsprintf(outputString, TEXT("%u"), maxSizeMB);
+ SetDlgItemText(hwnd, IDC_MINMAX_MAX, outputString);
+
+ SetDlgItemInt(hwnd, IDC_MINMAX_SIZE, maxSizeMB, FALSE);
+ SendDlgItemMessage(hwnd, IDC_MINMAX_SIZE, EM_SETSEL, 0, -1);
+
+ SetFocus(GetDlgItem(hwnd, IDC_MINMAX_SIZE));
+ return FALSE; // indicate focus set to a control
+ }
+
+ case WM_DESTROY:
+ {
+ // restore original subclass to window.
+ WNDPROC pfnProc = (WNDPROC)GetWindowLong(
+ GetDlgItem(hwnd, IDC_MINMAX_SIZE),
+ GWL_USERDATA);
+ SetWindowLong(GetDlgItem(hwnd, IDC_MINMAX_SIZE), GWL_WNDPROC, (LONG)pfnProc);
+ return FALSE;
+ }
+
+ case WM_VSCROLL:
+ // The up/down control changed the edit control: select it again
+ SendDlgItemMessage(hwnd, IDC_MINMAX_SIZE, EM_SETSEL, 0, (LPARAM)-1);
+ return TRUE;
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ sizeMB = GetDlgItemInt(hwnd, IDC_MINMAX_SIZE, &validNumber, FALSE);
+ if ( !validNumber
+ || !sizeMB
+ || (sizeMB > maxSizeMB)
+ || (sizeMB < minSizeMB))
+ {
+ ErrorDialog(MSG_INVALID_SIZE);
+ SendDlgItemMessage(hwnd, IDC_MINMAX_SIZE, EM_SETSEL, 0, -1);
+ SetFocus(GetDlgItem(hwnd, IDC_MINMAX_SIZE));
+ }
+ else
+ {
+ EndDialog(hwnd, sizeMB);
+ }
+ return TRUE;
+
+ case IDCANCEL:
+
+ EndDialog(hwnd, 0);
+ return TRUE;
+
+ case IDHELP:
+
+ DialogHelp( helpContextId );
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ default:
+ return FALSE;
+ }
+}
+
+
+
+BOOL CALLBACK
+DriveLetterDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog for allowing the user to select a drive letter for a
+ partition, logical drive, volume set, or stripe set.
+
+ The EndDialog codes are as follows:
+
+ FALSE - user cancelled
+ TRUE - user accepted a new drive letter choice, which was put in
+ the NewDriveLetter field of the parameter
+
+Arguments:
+
+ hdlg - window handle of dialog box
+
+ msg - message #
+
+ wParam - msg specific data
+
+ lParam - msg specific data
+
+Return Value:
+
+ msg dependent
+
+--*/
+
+{
+ static HWND hwndCombo;
+ static DWORD currentSelection;
+ static PDRIVELET_DLG_PARAMS params;
+
+ WCHAR driveLetterString[3];
+ DWORD selection;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ WCHAR driveLetter;
+ DWORD defRadioButton;
+
+ params = (PDRIVELET_DLG_PARAMS)lParam;
+ FDASSERT(NULL != params);
+
+ hwndCombo = GetDlgItem(hdlg, IDC_DRIVELET_COMBOBOX);
+
+ CenterDialogInFrame(hdlg);
+
+ //
+ // Add each available drive letter to the list of available
+ // drive letters.
+ //
+
+ driveLetterString[1] = L':';
+ driveLetterString[2] = L'\0';
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ if (DriveLetterIsAvailable(driveLetter))
+ {
+ driveLetterString[0] = driveLetter;
+ ComboBox_AddString(hwndCombo, driveLetterString);
+ }
+ }
+
+ SetWindowText(GetDlgItem(hdlg, IDC_DRIVELET_DESCR), params->Description);
+
+ driveLetter = params->DriveLetter;
+
+ if (!IsExtraDriveLetter(driveLetter))
+ {
+ DWORD itemIndex;
+
+ //
+ // There is a default drive letter. Place it on the list,
+ // check the correct radio button, and set the correct default
+ // in the combo box.
+ //
+
+ driveLetterString[0] = driveLetter;
+ itemIndex = ComboBox_AddString(hwndCombo, driveLetterString);
+ ComboBox_SetCurSel(hwndCombo, itemIndex);
+ defRadioButton = IDC_DRIVELET_RBASSIGN;
+ SetFocus(hwndCombo);
+ currentSelection = itemIndex;
+ }
+ else
+ {
+ //
+ // Default is no drive letter. Disable the combo box. Select
+ // the correct radio button.
+ //
+
+ EnableWindow(hwndCombo, FALSE);
+ defRadioButton = IDC_DRIVELET_RBNOASSIGN;
+ ComboBox_SetCurSel(hwndCombo, -1);
+ SetFocus(GetDlgItem(hdlg, IDC_DRIVELET_RBNOASSIGN));
+ currentSelection = 0;
+ }
+
+ CheckRadioButton(
+ hdlg,
+ IDC_DRIVELET_RBASSIGN,
+ IDC_DRIVELET_RBNOASSIGN,
+ defRadioButton
+ );
+
+ return FALSE; // focus set to control
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ //
+ // If the 'no letter' button is checked, return NO_DRIVE_LETTER_EVER
+ //
+
+ if (IsDlgButtonChecked(hdlg, IDC_DRIVELET_RBNOASSIGN))
+ {
+ params->NewDriveLetter = NO_DRIVE_LETTER_EVER;
+ EndDialog(hdlg, TRUE);
+ }
+ else
+ {
+ //
+ // Otherwise, get the currently selected item in the listbox.
+ //
+
+ selection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_GetLBText(hwndCombo, selection, driveLetterString);
+ params->NewDriveLetter = *driveLetterString;
+ EndDialog(hdlg, TRUE);
+ }
+ break;
+
+ case IDCANCEL:
+
+ EndDialog(hdlg, FALSE);
+ break;
+
+ case IDHELP:
+
+ DialogHelp(HC_DM_DLG_DRIVELETTER);
+ break;
+
+ case IDC_DRIVELET_RBASSIGN:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ EnableWindow(hwndCombo, TRUE);
+ ComboBox_SetCurSel(hwndCombo, currentSelection);
+ SetFocus(hwndCombo);
+ }
+ break;
+
+ case IDC_DRIVELET_RBNOASSIGN:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ currentSelection = ComboBox_GetCurSel(hwndCombo);
+ ComboBox_SetCurSel(hwndCombo, -1);
+ EnableWindow(hwndCombo, FALSE);
+ }
+ break;
+
+ default:
+
+ return FALSE;
+ }
+ break;
+
+ default:
+
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+BOOL CALLBACK
+DisplayOptionsDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog procedure for display options. Currently the only display option
+ is to alter the graph type (proportional/equal) on each disk.
+
+ For this dialog, lParam on creation must point to a buffer into which
+ this dialog procedure will place the user's new choices for the graph
+ display type for each disk.
+
+Arguments:
+
+ hdlg - window handle of dialog box
+
+ msg - message #
+
+ wParam - msg specific data
+
+ lParam - msg specific data
+
+Return Value:
+
+ msg dependent
+
+--*/
+
+{
+ static PBAR_TYPE newBarTypes;
+ static HWND hwndCombo;
+
+ DWORD selection;
+ DWORD i;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+
+ CenterDialogInFrame(hdlg);
+ newBarTypes = (PBAR_TYPE)lParam;
+ hwndCombo = GetDlgItem(hdlg, IDC_DISK_COMBOBOX);
+
+ CheckRadioButton(hdlg, IDC_AllDisks, IDC_OneDisk, IDC_AllDisks);
+ EnableWindow(GetDlgItem(hdlg, IDC_DISK_COMBOBOX), FALSE);
+
+ //
+ // Add each disk to the combo box.
+ //
+
+ for (i=0; i<DiskCount; i++)
+ {
+ TCHAR diskNumberString[10];
+
+ wsprintf(diskNumberString, TEXT("%u"), i);
+ ComboBox_AddString(hwndCombo, diskNumberString);
+ }
+
+ // select the zeroth item in the combobox
+ ComboBox_SetCurSel(hwndCombo, 0);
+ SendMessage(
+ hdlg,
+ WM_COMMAND,
+ MAKEWPARAM(IDC_DISK_COMBOBOX, CBN_SELCHANGE),
+ 0
+ );
+
+ SetFocus(GetDlgItem(hdlg, IDC_AllDisks));
+
+ return FALSE; // I already set the focus
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ EndDialog(hdlg, IDOK);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hdlg, IDCANCEL);
+ break;
+
+ case IDHELP:
+ DialogHelp( HC_DM_DLG_DISPLAYOPTION );
+ break;
+
+ case IDC_AllDisks:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ CheckRadioButton(hdlg, IDC_AllDisks, IDC_OneDisk, IDC_AllDisks);
+ EnableWindow(GetDlgItem(hdlg, IDC_DISK_COMBOBOX), FALSE);
+ }
+ break;
+
+ case IDC_OneDisk:
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ CheckRadioButton(hdlg, IDC_AllDisks, IDC_OneDisk, IDC_OneDisk);
+ EnableWindow(GetDlgItem(hdlg, IDC_DISK_COMBOBOX), TRUE);
+ }
+ break;
+
+ case IDC_DISK_COMBOBOX:
+
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ int rb;
+
+ //
+ // Selection in the combobox has changed; update the radio buttons
+ //
+
+ selection = ComboBox_GetCurSel(hwndCombo);
+
+ switch (newBarTypes[selection])
+ {
+ case BarProportional:
+ rb = IDC_RBPROPORTIONAL;
+ break;
+ case BarEqual:
+ rb = IDC_RBEQUAL;
+ break;
+ case BarAuto:
+ rb = IDC_RBAUTO;
+ break;
+ default:
+ FDASSERT(FALSE);
+ }
+
+ CheckRadioButton(hdlg, IDC_RBPROPORTIONAL, IDC_RBAUTO, rb);
+ }
+ break;
+
+ case IDC_RESETALL:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ for (i=0; i<DiskCount; i++)
+ {
+ newBarTypes[i] = BarAuto;
+ }
+ CheckRadioButton(hdlg, IDC_RBPROPORTIONAL, IDC_RBAUTO, IDC_RBAUTO);
+ }
+ break;
+
+ case IDC_RBPROPORTIONAL:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (IsDlgButtonChecked(hdlg, IDC_AllDisks))
+ {
+ for (i=0; i<DiskCount; i++)
+ {
+ newBarTypes[i] = BarProportional;
+ }
+ }
+ else
+ {
+ selection = ComboBox_GetCurSel(hwndCombo);
+ newBarTypes[selection] = BarProportional;
+ }
+ }
+ break;
+
+ case IDC_RBEQUAL:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (IsDlgButtonChecked(hdlg, IDC_AllDisks))
+ {
+ for (i=0; i<DiskCount; i++)
+ {
+ newBarTypes[i] = BarEqual;
+ }
+ }
+ else
+ {
+ selection = ComboBox_GetCurSel(hwndCombo);
+ newBarTypes[selection] = BarEqual;
+ }
+ }
+ break;
+
+ case IDC_RBAUTO:
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (IsDlgButtonChecked(hdlg, IDC_AllDisks))
+ {
+ for (i=0; i<DiskCount; i++)
+ {
+ newBarTypes[i] = BarAuto;
+ }
+ }
+ else
+ {
+ selection = ComboBox_GetCurSel(hwndCombo);
+ newBarTypes[selection] = BarAuto;
+ }
+ }
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ break;
+
+ default:
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoRegionDisplayDialog
+//
+// Synopsis: Invoke the region display (region sizing) dialog
+//
+// Arguments: [hwndParent] -- the parent window
+//
+// Returns: nothing
+//
+// History: 29-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoRegionDisplayDialog(
+ IN HWND hwndParent
+ )
+{
+ unsigned i;
+
+ PBAR_TYPE newBarTypes = (PBAR_TYPE)Malloc(DiskCount * sizeof(BAR_TYPE));
+
+ for (i=0; i<DiskCount; i++)
+ {
+ newBarTypes[i] = DiskArray[i]->BarType;
+ }
+
+ switch (
+ DialogBoxParam( g_hInstance,
+ MAKEINTRESOURCE(IDD_DISPLAYOPTIONS),
+ hwndParent,
+ DisplayOptionsDlgProc,
+ (DWORD)newBarTypes
+ )
+ )
+ {
+ case IDOK:
+ SetCursor(g_hCurWait);
+ for (i=0; i<DiskCount; i++)
+ {
+ DiskArray[i]->BarType = newBarTypes[i];
+ }
+ TotalRedrawAndRepaint();
+ SetCursor(g_hCurNormal);
+ break;
+
+ case IDCANCEL:
+ break;
+
+ case -1:
+ ErrorDialog(ERROR_NOT_ENOUGH_MEMORY);
+ break;
+
+ default:
+ FDASSERT(0);
+ }
+
+ Free(newBarTypes);
+}
+
+
+BOOL CALLBACK
+ColorDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog for the select colors/patterns dialog box. Note that this dialog
+ uses a rectangle custom control, defined below.
+
+Arguments:
+
+ hwnd - window handle of dialog box
+
+ msg - message #
+
+ wParam - msg specific data
+
+ lParam - msg specific data
+
+Return Value:
+
+ msg dependent
+
+--*/
+
+{
+ unsigned i;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ unsigned i;
+ LONG ec;
+ HWND hwndCombo = GetDlgItem(hdlg, IDC_COLORDLGCOMBO);
+
+ CenterDialogInFrame(hdlg);
+
+ for (i=0; i<LEGEND_STRING_COUNT; i++)
+ {
+ ec = ComboBox_AddString(hwndCombo, LegendLabels[i]);
+ if ((ec == CB_ERR) || (ec == CB_ERRSPACE))
+ {
+ EndDialog(hdlg, -1);
+ return FALSE;
+ }
+ SelectedColor[i] = IDC_COLOR1 + BrushColors[i];
+ SelectedHatch[i] = IDC_PATTERN1 + BrushHatches[i];
+ }
+ CurrentElement = 0;
+ ComboBox_SetCurSel(hwndCombo, CurrentElement);
+ SendMessage(
+ hdlg,
+ WM_COMMAND,
+ MAKEWPARAM(GetDlgCtrlID(hwndCombo), CBN_SELCHANGE),
+ (LPARAM)hwndCombo);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ for (i=0; i<LEGEND_STRING_COUNT; i++)
+ {
+ SelectedColor[i] -= IDC_COLOR1;
+ SelectedHatch[i] -= IDC_PATTERN1;
+ }
+ EndDialog(hdlg, IDOK);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hdlg, IDCANCEL);
+ break;
+
+ case IDHELP:
+ DialogHelp( HC_DM_COLORSANDPATTERNS );
+ break;
+
+ case IDC_COLORDLGCOMBO:
+ switch (HIWORD(wParam))
+ {
+ case CBN_SELCHANGE:
+ // deselect previous color
+ SendMessage(GetDlgItem(hdlg, SelectedColor[CurrentElement]),
+ RM_SELECT,
+ FALSE,
+ 0
+ );
+ // deselect previous pattern
+ SendMessage(GetDlgItem(hdlg, SelectedHatch[CurrentElement]),
+ RM_SELECT,
+ FALSE,
+ 0
+ );
+ CurrentElement = ComboBox_GetCurSel((HWND)lParam);
+ SendMessage(
+ hdlg,
+ WM_COMMAND,
+ MAKEWPARAM(SelectedColor[CurrentElement], RN_CLICKED),
+ 0);
+ SendMessage(
+ hdlg,
+ WM_COMMAND,
+ MAKEWPARAM(SelectedHatch[CurrentElement], RN_CLICKED),
+ 0);
+ break;
+
+ default:
+ return FALSE;
+ }
+ break;
+
+ case IDC_COLOR1:
+ case IDC_COLOR2:
+ case IDC_COLOR3:
+ case IDC_COLOR4:
+ case IDC_COLOR5:
+ case IDC_COLOR6:
+ case IDC_COLOR7:
+ case IDC_COLOR8:
+ case IDC_COLOR9:
+ case IDC_COLOR10:
+ case IDC_COLOR11:
+ case IDC_COLOR12:
+ case IDC_COLOR13:
+ case IDC_COLOR14:
+ case IDC_COLOR15:
+ case IDC_COLOR16:
+ {
+ if (HIWORD(wParam) == RN_CLICKED)
+ {
+ // deselect previous color
+ SendMessage(GetDlgItem(hdlg, SelectedColor[CurrentElement]),
+ RM_SELECT,
+ FALSE,
+ 0
+ );
+ SendMessage(GetDlgItem(hdlg, LOWORD(wParam)),
+ RM_SELECT,
+ TRUE,
+ 0
+ );
+
+ SelectedColor[CurrentElement] = LOWORD(wParam);
+
+ // now force patterns to be redrawn in selected color
+
+ for (i = IDC_PATTERN1; i <= IDC_PATTERN6; i++)
+ {
+ InvalidateRect(GetDlgItem(hdlg, i), NULL, FALSE);
+ }
+ }
+
+ break;
+ }
+
+ case IDC_PATTERN1:
+ case IDC_PATTERN2:
+ case IDC_PATTERN3:
+ case IDC_PATTERN4:
+ case IDC_PATTERN5:
+ case IDC_PATTERN6:
+ {
+ if (HIWORD(wParam) == RN_CLICKED)
+ {
+ // deselect previous pattern
+ SendMessage(GetDlgItem(hdlg, SelectedHatch[CurrentElement]),
+ RM_SELECT,
+ FALSE,
+ 0
+ );
+ SendMessage(GetDlgItem(hdlg, LOWORD(wParam)),
+ RM_SELECT,
+ TRUE,
+ 0
+ );
+
+ SelectedHatch[CurrentElement] = LOWORD(wParam);
+ break;
+ }
+
+ break;
+ }
+
+ } // end of WM_COMMAND switch
+
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoColorsDialog
+//
+// Synopsis: Invoke the colors dialog
+//
+// Arguments: [hwndParent] -- the parent window
+//
+// Returns: nothing
+//
+// History: 1-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoColorsDialog(
+ IN HWND hwndParent
+ )
+{
+ UINT i;
+
+ switch (
+ DialogBox(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_COLORS),
+ hwndParent,
+ ColorDlgProc)
+ )
+ {
+ case IDOK:
+ for (i=0; i<BRUSH_ARRAY_SIZE; i++)
+ {
+ DeleteBrush(g_Brushes[i]);
+ g_Brushes[i] = MyCreateHatchBrush(
+ AvailableHatches[BrushHatches[i] = SelectedHatch[i]],
+ AvailableColors[BrushColors[i] = SelectedColor[i]]
+ );
+ }
+ SetCursor(g_hCurWait);
+ TotalRedrawAndRepaint();
+ if (g_Legend)
+ {
+ InvalidateRect(g_hwndFrame, NULL, FALSE);
+ }
+ SetCursor(g_hCurNormal);
+ break;
+
+ case IDCANCEL:
+ break;
+
+ case -1:
+ ErrorDialog(ERROR_NOT_ENOUGH_MEMORY);
+ break;
+
+ default:
+ FDASSERT(0);
+ }
+}
+
+
+BOOL CALLBACK
+DiskOptionsDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Dialog procedure for disk options.
+
+Arguments:
+
+ hdlg - window handle of dialog box
+
+ msg - message #
+
+ wParam - msg specific data
+
+ lParam - msg specific data
+
+Return Value:
+
+ msg dependent
+
+--*/
+
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+
+ CenterDialogInFrame(hdlg);
+
+ int idButton = (g_DiskDisplayType == DiskProportional)
+ ? IDC_DISKPROPORTIONAL
+ : IDC_DISKEQUAL
+ ;
+
+ CheckRadioButton(
+ hdlg,
+ IDC_DISKPROPORTIONAL,
+ IDC_DISKEQUAL,
+ idButton
+ );
+
+ SetFocus(GetDlgItem(hdlg, IDC_DISKPROPORTIONAL));
+
+ return FALSE; // I already set the focus
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ g_DiskDisplayType = IsDlgButtonChecked(hdlg, IDC_DISKPROPORTIONAL)
+ ? DiskProportional
+ : DiskEqual
+ ;
+
+ EndDialog(hdlg, IDOK);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hdlg, IDCANCEL);
+ break;
+
+ case IDHELP:
+ DialogHelp( HC_DM_DLG_DISKDISPLAY );
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ break;
+
+ default:
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDiskOptionsDialog
+//
+// Synopsis: Invoke the disk sizing dialog
+//
+// Arguments: [hwndParent] -- the parent window
+//
+// Returns: nothing
+//
+// History: 29-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoDiskOptionsDialog(
+ IN HWND hwndParent
+ )
+{
+ switch (
+ DialogBox( g_hInstance,
+ MAKEINTRESOURCE(IDD_DISKOPTIONS),
+ hwndParent,
+ DiskOptionsDlgProc
+ )
+ )
+ {
+ case IDOK:
+ SetCursor(g_hCurWait);
+ TotalRedrawAndRepaint();
+ SetCursor(g_hCurNormal);
+ break;
+
+ case IDCANCEL:
+ break;
+
+ case -1:
+ ErrorDialog(ERROR_NOT_ENOUGH_MEMORY);
+ break;
+
+ default:
+ FDASSERT(0);
+ }
+
+}
diff --git a/private/utils/windisk/src/dlgs.hxx b/private/utils/windisk/src/dlgs.hxx
new file mode 100644
index 000000000..5f3b0e7d3
--- /dev/null
+++ b/private/utils/windisk/src/dlgs.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dlgs.hxx
+//
+// Contents: Declarations for dialog routines
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DLGS_HXX__
+#define __DLGS_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+HBRUSH
+MyCreateHatchBrush(
+ int fnStyle,
+ COLORREF clrref
+ );
+
+VOID
+CenterDialog(
+ IN HWND hwndToCenter,
+ IN HWND hwndContext
+ );
+
+VOID
+CenterDialogInFrame(
+ IN HWND hwnd
+ );
+
+VOID
+SubclassListBox(
+ IN HWND hwnd
+ );
+
+BOOL CALLBACK
+MinMaxDlgProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+BOOL CALLBACK
+DriveLetterDlgProc(
+ IN HWND hdlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+VOID
+DoColorsDialog(
+ IN HWND hwndParent
+ );
+
+VOID
+DoRegionDisplayDialog(
+ IN HWND hwndParent
+ );
+
+BOOL CALLBACK
+CreateDlgProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+VOID
+DoDiskOptionsDialog(
+ IN HWND hwndParent
+ );
+
+INT
+SizeDlgProc(
+ IN HWND hDlg,
+ IN UINT wMsg,
+ IN WPARAM wParam,
+ IN LONG lParam
+ );
+
+#endif // __DLGS_HXX__
diff --git a/private/utils/windisk/src/drives.cxx b/private/utils/windisk/src/drives.cxx
new file mode 100644
index 000000000..8b661b6ed
--- /dev/null
+++ b/private/utils/windisk/src/drives.cxx
@@ -0,0 +1,871 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: drives.cxx
+//
+// Contents: Routines dealing with drive letters
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "drives.hxx"
+#include "nt.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+LOCAL WCHAR
+LocateDriveLetterFromDiskAndPartition(
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber
+ );
+
+LOCAL WCHAR
+LocateDriveLetterFromRegion(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define IsDigitW(digit) (((digit) >= L'0') && ((digit) <= L'9'))
+
+//
+// For each drive letter, these arrays hold the disk and partition number
+// the the drive letter is linked to. These are (well, SHOULD BE) used SOLELY
+// for initialization of the drive letter persistent data. They are determined
+// by scanning the NT object namespace and decoding which drives and
+// partitions a \DosDevices\X: link points to.
+//
+
+#define UNINIT ((unsigned)(-1))
+
+LOCAL unsigned
+DriveLetterDiskNumbers[24] =
+{
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT
+};
+
+LOCAL unsigned
+DriveLetterPartitionNumbers[24] =
+{
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT,
+ UNINIT, UNINIT, UNINIT, UNINIT, UNINIT, UNINIT
+};
+
+
+//
+// Drive letter usage map. Bit n (0 <= n <= 24) set means that drive
+// letter 'C'+n is in use.
+//
+
+LOCAL ULONG DriveLetterUsageMap = 0;
+
+
+/////////////////////////////////////////////////////////////////////////
+
+//
+// The following macro APIs take a single ASCII character x, where
+// 'C' <= x <= 'Z'
+//
+
+#define DRIVELETTERBIT(DriveLetter) (1 << (unsigned)((UCHAR)(DriveLetter)-(UCHAR)'C'))
+
+//
+// VOID
+// SetDriveLetterUsed(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define SetDriveLetterUsed(DriveLetter) DriveLetterUsageMap |= DRIVELETTERBIT(DriveLetter)
+
+//
+// VOID
+// SetDriveLetterFree(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define SetDriveLetterFree(DriveLetter) DriveLetterUsageMap &= (~DRIVELETTERBIT(DriveLetter))
+
+//
+// BOOL
+// IsDriveLetterUsed(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define IsDriveLetterUsed(DriveLetter) (DriveLetterUsageMap & DRIVELETTERBIT(DriveLetter))
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetAvailableDriveLetter
+//
+// Synopsis: Scan the drive letter usage bitmap and return the next
+// available drive letter.
+//
+// Arguments: (none)
+//
+// Returns: The next available drive letter, or 0 if all are used.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+WCHAR
+GetAvailableDriveLetter(
+ VOID
+ )
+{
+ WCHAR driveLetter;
+
+ FDASSERT(!(DriveLetterUsageMap & 0xff000000));
+
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ if (!IsDriveLetterUsed(driveLetter))
+ {
+ return driveLetter;
+ }
+ }
+ return 0;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MarkDriveLetterUsed
+//
+// Synopsis: Set the state of a drive letter to 'used'
+//
+// Arguments: [DriveLetter] -- The drive letter to change the state of
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+MarkDriveLetterUsed(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT(!(DriveLetterUsageMap & 0xff000000));
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!IsExtraDriveLetter(DriveLetter))
+ {
+ SetDriveLetterUsed(DriveLetter);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: NewDriveLetter
+//
+// Synopsis: Handle a new drive letter: set the drive letter to
+// "used", and set a region & partition # (any one for FT
+// objects)
+//
+// Arguments: [DriveLetter] -- The drive letter to change the state of
+// [DiskNum] -- a disk number of part of the volume
+// [PartNum] -- a partition number of part of the volume
+//
+// Returns: nothing
+//
+// History: 24-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+NewDriveLetter(
+ IN WCHAR DriveLetter,
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber
+ )
+{
+ MarkDriveLetterUsed(DriveLetter);
+ DriveLetterDiskNumbers [ DriveLetterToIndex(DriveLetter) ] = DiskNumber;
+ DriveLetterPartitionNumbers[ DriveLetterToIndex(DriveLetter) ] = PartitionNumber;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MarkDriveLetterFree
+//
+// Synopsis: Set the state of a drive letter to 'free'
+//
+// Arguments: [DriveLetter] -- The drive letter to change the state of
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+MarkDriveLetterFree(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT(!(DriveLetterUsageMap & 0xff000000));
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!IsExtraDriveLetter(DriveLetter))
+ {
+ SetDriveLetterFree(DriveLetter);
+ DriveLetterDiskNumbers [ DriveLetterToIndex(DriveLetter) ] = UNINIT;
+ DriveLetterPartitionNumbers[ DriveLetterToIndex(DriveLetter) ] = UNINIT;
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DriveLetterIsAvailable
+//
+// Synopsis: Determine if a particular drive letter is available for use
+//
+// Arguments: [DriveLetter] -- The drive letter to check
+//
+// Returns: TRUE if the drive letter is available
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+DriveLetterIsAvailable(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT(!(DriveLetterUsageMap & 0xff000000));
+ FDASSERT(DriveLetter >= L'C' && DriveLetter <= L'Z');
+
+ return !IsDriveLetterUsed(DriveLetter);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: AllDriveLettersAreUsed
+//
+// Synopsis: Determine if all possible drive letters are in use
+//
+// Arguments: (none)
+//
+// Returns: TRUE if all possible drive letters are in use
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+AllDriveLettersAreUsed(
+ VOID
+ )
+{
+ FDASSERT(!(DriveLetterUsageMap & 0xff000000));
+
+ return (DriveLetterUsageMap == 0x00ffffff);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDiskNumberFromDriveLetter
+//
+// Synopsis: Find the disk number on which the volume resides that is
+// assigned a particular drive letter
+//
+// Arguments: [DriveLetter] -- The drive letter in question
+//
+// Returns: A 0-based disk number, or -1 if the drive letter is either
+// illegal or not assigned.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+GetDiskNumberFromDriveLetter(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!IsExtraDriveLetter(DriveLetter))
+ {
+ return DriveLetterDiskNumbers[ DriveLetterToIndex(DriveLetter) ];
+ }
+ else
+ {
+ return (ULONG)(-1);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetPartitionNumberFromDriveLetter
+//
+// Synopsis: Find the partition number on a disk on which the volume resides
+// that is assigned a particular drive letter
+//
+// Arguments: [DriveLetter] -- The drive letter in question
+//
+// Returns: A partition number, or -1 if the drive letter is either
+// illegal or not assigned.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+GetPartitionNumberFromDriveLetter(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!IsExtraDriveLetter(DriveLetter))
+ {
+ return DriveLetterPartitionNumbers[ DriveLetterToIndex(DriveLetter) ];
+ }
+ else
+ {
+ return (ULONG)(-1);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LocateDriveLetterFromDiskAndPartition
+//
+// Synopsis: Given a disk number and a partition number, return the drive
+// letter associated with that region/volume.
+// NOTE: This code assumes there is no persistent data yet!
+//
+// Arguments: [DiskNum] -- disk number of interest
+// [PartNum] -- partition number of interest
+//
+// Returns: drive letter of region, or NO_DRIVE_LETTER_YET
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL WCHAR
+LocateDriveLetterFromDiskAndPartition(
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber
+ )
+{
+ unsigned i;
+
+ for (i=0; i<24; i++)
+ {
+ if (DiskNumber == DriveLetterDiskNumbers[i] &&
+ PartitionNumber == DriveLetterPartitionNumbers[i])
+ {
+ return L'C' + (WCHAR)i;
+ }
+ }
+
+ return NO_DRIVE_LETTER_YET;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LocateDriveLetterFromRegion
+//
+// Synopsis: Given a disk region, return the drive letter associated with it
+// NOTE: This code assumes there is no persistent data yet!
+//
+// Arguments: [RegionDescriptor] -- the region of interest
+//
+// Returns: drive letter of the region, or NO_DRIVE_LETTER_YET
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL WCHAR
+LocateDriveLetterFromRegion(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ if (NULL != regionData)
+ {
+ if (NULL != regionData->FtObject)
+ {
+ if (regionData->DriveLetter)
+ {
+ return regionData->DriveLetter;
+ }
+ }
+ }
+
+ return LocateDriveLetterFromDiskAndPartition(
+ RegionDescriptor->Disk,
+ RegionDescriptor->OriginalPartitionNumber
+ );
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegionFromDiskAndPartitionNumbers
+//
+// Synopsis: Given a disk number and a partition number, return the
+// associated region
+//
+// Arguments: [DiskNum] -- disk number of interest
+// [PartNum] -- partition number of interest
+//
+// Returns: a pointer to a region descriptor for the region
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+PREGION_DESCRIPTOR
+RegionFromDiskAndPartitionNumbers(
+ IN ULONG DiskNumber,
+ IN ULONG PartitionNumber
+ )
+{
+ PREGION_DESCRIPTOR regionDescriptor;
+ PDISKSTATE diskState;
+ ULONG regionIndex;
+
+ diskState = DiskArray[DiskNumber];
+
+ for (regionIndex=0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionIndex];
+
+ if (DmSignificantRegion(regionDescriptor)
+ && regionDescriptor->PartitionNumber == PartitionNumber)
+ {
+ return regionDescriptor;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegionFromDriveLetter
+//
+// Synopsis: Given a drive letter, return a pointer to a region descriptor
+// of a volume with that drive letter
+//
+// Arguments: [DriveLetter] -- drive letter of interest
+//
+// Returns: a pointer to a region descriptor for the region
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+PREGION_DESCRIPTOR
+RegionFromDriveLetter(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!DriveLetterIsAvailable(DriveLetter))
+ {
+ ULONG DiskNum = DriveLetterDiskNumbers[ DriveLetterToIndex(DriveLetter) ];
+ ULONG PartNum = DriveLetterPartitionNumbers[ DriveLetterToIndex(DriveLetter) ];
+
+ if (-1 != DiskNum && -1 != PartNum)
+ {
+ return RegionFromDiskAndPartitionNumbers(DiskNum, PartNum);
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SignificantDriveLetter
+//
+// Synopsis: Determine if a drive letter is sigificant. A drive letter is
+// significant if is is used, and is associated with a
+// local volume. It can't be a network volume or a floppy
+// drive.
+//
+// Arguments: [DriveLetter] -- the drive letter in question
+//
+// Returns: TRUE if the drive letter is significant
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+SignificantDriveLetter(
+ IN WCHAR DriveLetter
+ )
+{
+ FDASSERT((DriveLetter >= L'C' && DriveLetter <= L'Z')
+ || (DriveLetter == NO_DRIVE_LETTER_YET)
+ || (DriveLetter == NO_DRIVE_LETTER_EVER));
+
+ if (!IsExtraDriveLetter(DriveLetter) && IsDriveLetterUsed(DriveLetter))
+ {
+ PREGION_DESCRIPTOR regionDescriptor = RegionFromDriveLetter(DriveLetter);
+ if (NULL != regionDescriptor)
+ {
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ return NULL != regionData
+ && !regionData->NewRegion
+ && DmSignificantRegion(regionDescriptor);
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetInfoFromDriveLetter
+//
+// Synopsis: From a drive letter, find a pointer to a disk state
+// representing a volume assigned that drive letter.
+//
+// Arguments: [DriveLetter] -- the drive letter in question
+// [DiskStateOut] -- set to the disk state of the disk with a
+// volume with the argument drive letter
+// [RegionIndexOut] -- set to the region index of the region of
+// interest on the disk
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+GetInfoFromDriveLetter(
+ IN WCHAR DriveLetter,
+ OUT PDISKSTATE* DiskStateOut,
+ OUT int* RegionIndexOut
+ )
+{
+ DWORD diskNumber;
+ DWORD regionIndex;
+
+ for (diskNumber = 0; diskNumber < DiskCount; diskNumber++)
+ {
+ PDISKSTATE diskState = DiskArray[diskNumber];
+
+ for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex ++)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &diskState->RegionArray[regionIndex];
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (regionData->DriveLetter == DriveLetter)
+ {
+ *DiskStateOut = diskState;
+ *RegionIndexOut = regionIndex;
+ return;
+ }
+ }
+ }
+ }
+
+ daDebugOut((DEB_ITRACE,
+ "Couldn't find disk state structure with drive letter %wc\n",
+ DriveLetter));
+
+ *DiskStateOut = NULL;
+ *RegionIndexOut = 0;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeDriveLetterInfo
+//
+// Synopsis: Initialize all information about drive letters by reading
+// through the NT object namespace and parsing out used drive
+// letters. Assigns drive letters to all volumes.
+//
+// Arguments: (none)
+//
+// Returns: TRUE on success
+//
+// Modifies: all drive letter state information
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+InitializeDriveLetterInfo(
+ VOID
+ )
+{
+ WCHAR driveLetter;
+ PWSTR linkTarget;
+ WCHAR dosDevicesName[ARRAYLEN(L"\\DosDevices\\A:")];
+ unsigned diskNumber;
+ int partitionNumber;
+ PWSTR pattern;
+ PWSTR string;
+ DWORD x;
+ DWORD ec;
+
+ //
+ // For each drive letter c-z, query the symbolic link.
+ //
+
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ wsprintf(dosDevicesName, L"\\DosDevices\\%c:", driveLetter);
+
+ if ((ec = GetDriveLetterLinkTarget(dosDevicesName, &linkTarget)) == NO_ERROR)
+ {
+ //
+ // The drive letter is used because it is linked to something,
+ // even if we can't figure out what. So mark it used here.
+ //
+
+ SetDriveLetterUsed(driveLetter);
+
+ CharUpper(linkTarget);
+
+ pattern = L"\\DEVICE\\HARDDISK";
+ string = linkTarget;
+
+ //
+ // Attempt to match the '\device\harddisk' part
+ //
+
+ for (x=0; x < (sizeof(L"\\DEVICE\\HARDDISK") / sizeof(WCHAR)) - 1; x++)
+ {
+ if (*pattern++ != *string++)
+ {
+ goto next_letter;
+ }
+ }
+
+ //
+ // Now get the hard disk #
+ //
+
+ if (!IsDigitW(*string))
+ {
+ goto next_letter;
+ }
+
+ diskNumber = 0;
+ while (IsDigitW(*string))
+ {
+ diskNumber = (diskNumber * 10) + (*string - L'0');
+ *string++;
+ }
+
+ //
+ // Attempt to match the '\partition' part
+ //
+
+ pattern = L"\\PARTITION";
+ for (x=0; x < (sizeof(L"\\PARTITION") / sizeof(WCHAR)) - 1; x++)
+ {
+ if (*pattern++ != *string++)
+ {
+ goto next_letter;
+ }
+ }
+
+ //
+ // Now get the partition #, which cannot be 0
+ //
+
+ partitionNumber = 0;
+ while (IsDigitW(*string))
+ {
+ partitionNumber = (partitionNumber * 10) + (*string - L'0');
+ *string++;
+ }
+
+ if (0 == partitionNumber)
+ {
+ goto next_letter;
+ }
+
+ //
+ // Make sure there is nothing left in the link target's name
+ //
+
+ if (*string)
+ {
+ goto next_letter;
+ }
+
+ //
+ // We understand the link target. Store the disk and partition.
+ //
+
+ DriveLetterDiskNumbers[driveLetter - L'C'] = diskNumber;
+ DriveLetterPartitionNumbers[driveLetter - L'C'] = partitionNumber;
+ }
+ else
+ {
+ if (ec == ERROR_ACCESS_DENIED)
+ {
+ ErrorDialog(MSG_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+next_letter: {}
+ }
+
+
+ //
+ // Now for each non-ft, significant region on each disk, figure out its
+ // drive letter.
+ //
+
+ PFT_OBJECT ftObject;
+ PFT_OBJECT_SET ftSet;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PDISKSTATE diskState;
+ UINT regionIndex;
+
+ for (diskNumber = 0; diskNumber < DiskCount; diskNumber++)
+ {
+ diskState = DiskArray[diskNumber];
+
+ for (regionIndex=0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionIndex];
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ //
+ // Handle drive letters for FT sets specially.
+ //
+
+ if (NULL == GET_FT_OBJECT(regionDescriptor))
+ {
+ PERSISTENT_DATA(regionDescriptor)->DriveLetter =
+ LocateDriveLetterFromRegion(regionDescriptor);
+ }
+ }
+ }
+
+ // If this is a removable disk, record the reserved drive
+ // letter for that disk.
+ //
+ if (IsDiskRemovable[diskNumber])
+ {
+ RemovableDiskReservedDriveLetters[diskNumber] =
+ LocateDriveLetterFromDiskAndPartition(diskNumber, 1);
+ }
+ else
+ {
+ RemovableDiskReservedDriveLetters[diskNumber] = NO_DRIVE_LETTER_YET;
+ }
+ }
+
+ //
+ // Now handle ft sets. For each set, loop through the objects twice.
+ // On the first pass, figure out which object actually is linked to the
+ // drive letter. On the second pass, assign the drive letter found to
+ // each of the objects in the set.
+ //
+
+ for (ftSet = FtObjectList; NULL != ftSet; ftSet = ftSet->Next)
+ {
+ for (ftObject = ftSet->Members; NULL != ftObject; ftObject = ftObject->Next)
+ {
+ regionDescriptor = ftObject->Region;
+
+ if (regionDescriptor)
+ {
+ if ((driveLetter = LocateDriveLetterFromRegion(regionDescriptor))
+ != NO_DRIVE_LETTER_YET)
+ {
+ break;
+ }
+ }
+ }
+
+ for (ftObject = ftSet->Members; NULL != ftObject; ftObject = ftObject->Next)
+ {
+ regionDescriptor = ftObject->Region;
+
+ if (regionDescriptor)
+ {
+ PERSISTENT_DATA(regionDescriptor)->DriveLetter = driveLetter;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+#undef UNINIT
diff --git a/private/utils/windisk/src/drives.hxx b/private/utils/windisk/src/drives.hxx
new file mode 100644
index 000000000..e5a893994
--- /dev/null
+++ b/private/utils/windisk/src/drives.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: drives.hxx
+//
+// Contents: Routines dealing with drive letters
+//
+// History: 24-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DRIVES_HXX__
+#define __DRIVES_HXX__
+
+WCHAR
+GetAvailableDriveLetter(
+ VOID
+ );
+
+VOID
+MarkDriveLetterUsed(
+ IN WCHAR DriveLetter
+ );
+
+VOID
+NewDriveLetter(
+ IN WCHAR DriveLetter,
+ IN ULONG DiskNum,
+ IN ULONG PartNum
+ );
+
+VOID
+MarkDriveLetterFree(
+ IN WCHAR DriveLetter
+ );
+
+BOOL
+DriveLetterIsAvailable(
+ IN WCHAR DriveLetter
+ );
+
+BOOL
+AllDriveLettersAreUsed(
+ VOID
+ );
+
+ULONG
+GetDiskNumberFromDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+ULONG
+GetPartitionNumberFromDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+PREGION_DESCRIPTOR
+RegionFromDiskAndPartitionNumbers(
+ IN ULONG DiskNum,
+ IN ULONG PartNum
+ );
+
+PREGION_DESCRIPTOR
+RegionFromDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+BOOL
+SignificantDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+VOID
+GetInfoFromDriveLetter(
+ IN WCHAR DriveLetter,
+ OUT PDISKSTATE* DiskState,
+ OUT int* RegionIndex
+ );
+
+BOOL
+InitializeDriveLetterInfo(
+ VOID
+ );
+
+
+#endif // __DRIVES_HXX__
diff --git a/private/utils/windisk/src/dskmgr.ico b/private/utils/windisk/src/dskmgr.ico
new file mode 100644
index 000000000..f0fa6bfe5
--- /dev/null
+++ b/private/utils/windisk/src/dskmgr.ico
Binary files differ
diff --git a/private/utils/windisk/src/engine.cxx b/private/utils/windisk/src/engine.cxx
new file mode 100644
index 000000000..4262b2b3e
--- /dev/null
+++ b/private/utils/windisk/src/engine.cxx
@@ -0,0 +1,4086 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1994.
+//
+// File: engine.cxx
+//
+// Contents: The disk partitioning engine, formerly in the arcinst project.
+//
+// History:
+//
+// Ted Miller (tedm) Nov-1991
+//
+// Bob Rinne (bobri) Feb-1994
+// Moved as actual part of Disk Administrator enlistment instead of being
+// copied from ArcInst. This is due to dynamic partition changes. Removed
+// string table that made this an internationalized file.
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "engine.hxx"
+#include "ntlow.hxx"
+#include "nt.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+#define ENTRIES_PER_BOOTSECTOR 4
+
+////////////////////////////////////////////////////////////////////////////
+
+// Attached disk devices.
+
+ULONG CountOfDisks;
+PCHAR* DiskNames;
+
+// Information about attached disks.
+
+DISKGEOM* DiskGeometryArray;
+
+PPARTITION* PrimaryPartitions;
+PPARTITION* LogicalVolumes;
+
+//
+// A 'signature' is a unique 4-byte value immediately preceeding the
+// partition table in the MBR.
+//
+
+PULONG Signatures;
+
+//
+// Array keeping track of whether each disk is off line.
+//
+PBOOLEAN OffLine;
+
+// Keeps track of whether changes have been requested
+// to each disk's partition structure.
+
+PBOOLEAN ChangesRequested;
+PBOOLEAN ChangesCommitted;
+
+
+//
+// Value used to indicate that the partition entry has changed but in a non-
+// destructive way (ie, made active/inactive).
+//
+#define CHANGED_DONT_ZAP ((BOOLEAN)(5))
+
+////////////////////////////////////////////////////////////////////////////
+
+
+STATUS_CODE
+OpenDisks(
+ VOID
+ );
+
+VOID
+CloseDisks(
+ VOID
+ );
+
+STATUS_CODE
+GetGeometry(
+ VOID
+ );
+
+BOOLEAN
+CheckIfDiskIsOffLine(
+ IN ULONG Disk
+ );
+
+STATUS_CODE
+InitializePartitionLists(
+ VOID
+ );
+
+STATUS_CODE
+GetRegions(
+ IN ULONG Disk,
+ IN PPARTITION p,
+ IN BOOLEAN WantUsedRegions,
+ IN BOOLEAN WantFreeRegions,
+ IN BOOLEAN WantLogicalRegions,
+ OUT PREGION_DESCRIPTOR* Region,
+ OUT PULONG RegionCount,
+ IN REGION_TYPE RegionType
+ );
+
+BOOLEAN
+AddRegionEntry(
+ IN OUT PREGION_DESCRIPTOR* Regions,
+ IN OUT PULONG RegionCount,
+ IN ULONG SizeMB,
+ IN REGION_TYPE RegionType,
+ IN PPARTITION Partition,
+ IN LARGE_INTEGER AlignedRegionOffset,
+ IN LARGE_INTEGER AlignedRegionSize
+ );
+
+VOID
+AddPartitionToLinkedList(
+ IN PARTITION** Head,
+ IN PARTITION* p
+ );
+
+BOOLEAN
+IsInLinkedList(
+ IN PPARTITION p,
+ IN PPARTITION List
+ );
+
+BOOLEAN
+IsInLogicalList(
+ IN ULONG Disk,
+ IN PPARTITION p
+ );
+
+BOOLEAN
+IsInPartitionList(
+ IN ULONG Disk,
+ IN PPARTITION p
+ );
+
+LARGE_INTEGER
+AlignTowardsDiskStart(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset
+ );
+
+LARGE_INTEGER
+AlignTowardsDiskEnd(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset
+ );
+
+VOID
+FreeLinkedPartitionList(
+ IN PARTITION** q
+ );
+
+VOID
+MergeFreePartitions(
+ IN PPARTITION p
+ );
+
+VOID
+FreePartitionInfoLinkedLists(
+ IN PARTITION** ListHeadArray
+ );
+
+LARGE_INTEGER
+DiskLengthBytes(
+ IN ULONG Disk
+ );
+
+PPARTITION
+AllocatePartitionStructure(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset,
+ IN LARGE_INTEGER Length,
+ IN PPARTITION_INFORMATION OriginalPartitionInformation,
+ IN ULONG LayoutSlot,
+ IN UCHAR SysID,
+ IN BOOLEAN Update,
+ IN BOOLEAN Active,
+ IN BOOLEAN Recognized
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+
+STATUS_CODE
+FdiskInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the partitioning engine, including allocating
+ arrays, determining attached disk devices, and reading their
+ partition tables.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ STATUS_CODE status;
+ ULONG i;
+
+ if ((status = LowQueryFdiskPathList(&DiskNames, &CountOfDisks)) != OK_STATUS)
+ {
+ return status;
+ }
+
+ DiskGeometryArray = NULL;
+ PrimaryPartitions = NULL;
+ LogicalVolumes = NULL;
+
+ if (((DiskGeometryArray = (PDISKGEOM) AllocateMemory(CountOfDisks * sizeof(DISKGEOM ))) == NULL)
+ || ((ChangesRequested = (PBOOLEAN) AllocateMemory(CountOfDisks * sizeof(BOOLEAN ))) == NULL)
+ || ((ChangesCommitted = (PBOOLEAN) AllocateMemory(CountOfDisks * sizeof(BOOLEAN ))) == NULL)
+ || ((PrimaryPartitions = (PPARTITION*) AllocateMemory(CountOfDisks * sizeof(PPARTITION))) == NULL)
+ || ((Signatures = (PULONG) AllocateMemory(CountOfDisks * sizeof(ULONG ))) == NULL)
+ || ((OffLine = (PBOOLEAN) AllocateMemory(CountOfDisks * sizeof(BOOLEAN ))) == NULL)
+ || ((LogicalVolumes = (PPARTITION*) AllocateMemory(CountOfDisks * sizeof(PPARTITION))) == NULL))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ for (i=0; i<CountOfDisks; i++)
+ {
+ PrimaryPartitions[i] = NULL;
+ LogicalVolumes[i] = NULL;
+ ChangesRequested[i] = FALSE;
+ ChangesCommitted[i] = FALSE;
+ OffLine[i] = CheckIfDiskIsOffLine(i);
+ }
+
+ if ( ((status = GetGeometry() ) != OK_STATUS)
+ || ((status = InitializePartitionLists()) != OK_STATUS))
+ {
+ return status;
+ }
+
+ return OK_STATUS;
+}
+
+
+VOID
+FdiskCleanUp(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deallocates storage used by the partitioning engine.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LowFreeFdiskPathList(DiskNames, CountOfDisks);
+
+ if (DiskGeometryArray != NULL)
+ {
+ FreeMemory(DiskGeometryArray);
+ }
+ if (PrimaryPartitions != NULL)
+ {
+ FreePartitionInfoLinkedLists(PrimaryPartitions);
+ FreeMemory(PrimaryPartitions);
+ }
+ if (LogicalVolumes != NULL)
+ {
+ FreePartitionInfoLinkedLists(LogicalVolumes);
+ FreeMemory(LogicalVolumes);
+ }
+ if (ChangesRequested != NULL)
+ {
+ FreeMemory(ChangesRequested);
+ }
+ if (ChangesCommitted != NULL)
+ {
+ FreeMemory(ChangesCommitted);
+ }
+ if (OffLine != NULL)
+ {
+ FreeMemory(OffLine);
+ }
+ if (Signatures != NULL)
+ {
+ FreeMemory(Signatures);
+ }
+}
+
+
+BOOLEAN
+CheckIfDiskIsOffLine(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ Determine whether a disk is off-line by attempting to open it.
+ If this is diskman, also attempt to read from it.
+
+Arguments:
+
+ Disk - supplies number of the disk to check
+
+Return Value:
+
+ TRUE if disk is off-line, FALSE is disk is on-line.
+
+--*/
+
+{
+ HANDLE_T handle;
+ UINT errorMode;
+ BOOLEAN isOffLine = TRUE;
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ if (LowOpenDisk(GetDiskName(Disk), &handle) == OK_STATUS)
+ {
+ ULONG dummy;
+ ULONG bps;
+ PVOID unalignedBuffer;
+ PVOID buffer;
+
+ isOffLine = TRUE;
+
+ //
+ // The open might succeed even if the disk is off line. So to be
+ // sure, read the first sector from the disk.
+ //
+
+ if (NT_SUCCESS(LowGetDriveGeometry(GetDiskName(Disk), &dummy, &bps, &dummy, &dummy)))
+ {
+ unalignedBuffer = Malloc(2*bps);
+ buffer = (PVOID)(((ULONG)unalignedBuffer+bps) & ~(bps-1));
+
+ if (NT_SUCCESS(LowReadSectors(handle, bps, 0, 1, buffer)))
+ {
+ isOffLine = FALSE;
+ }
+
+ Free(unalignedBuffer);
+ }
+ else
+ {
+ // It is possible this is a removable drive.
+
+ if (IsRemovable(Disk))
+ {
+ isOffLine = FALSE;
+ }
+ }
+
+ LowCloseDisk(handle);
+ }
+ SetErrorMode(errorMode);
+
+ return isOffLine;
+}
+
+
+STATUS_CODE
+GetGeometry(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines disk geometry for each disk device.
+ Disk geometry includes heads, sectors per track, cylinder count,
+ and bytes per sector. It also includes bytes per track and
+ bytes per cylinder, which are calculated from the other values
+ for the convenience of the rest of this module.
+
+ Geometry information is placed in the DiskGeometryArray global variable.
+
+ Geometry information is undefined for an off-line disk.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ ULONG i;
+ STATUS_CODE status;
+ ULONG totalSectorCount,
+ sectorSize,
+ sectorsPerTrack,
+ heads;
+
+ for (i=0; i<CountOfDisks; i++)
+ {
+ if (OffLine[i])
+ {
+ continue;
+ }
+
+ status = LowGetDriveGeometry(
+ DiskNames[i],
+ &totalSectorCount,
+ &sectorSize,
+ &sectorsPerTrack,
+ &heads);
+
+ if (status != OK_STATUS)
+ {
+
+ if (IsRemovable(i)) {
+
+ //
+ // Assume that the media has been removed. Null out the
+ // sizes.
+ //
+ status = OK_STATUS;
+ sectorSize = 0;
+ sectorsPerTrack = 0;
+ heads = 0;
+ totalSectorCount = 0;
+
+ } else {
+ return status;
+ }
+ }
+
+ DiskGeometryArray[i].BytesPerSector = sectorSize;
+ DiskGeometryArray[i].SectorsPerTrack = sectorsPerTrack;
+ DiskGeometryArray[i].Heads = heads;
+ if (sectorsPerTrack && heads) {
+ DiskGeometryArray[i].Cylinders.QuadPart = totalSectorCount / (sectorsPerTrack * heads);
+ } else {
+ DiskGeometryArray[i].Cylinders.QuadPart = 0;
+ }
+ DiskGeometryArray[i].BytesPerTrack = sectorsPerTrack * sectorSize;
+ DiskGeometryArray[i].BytesPerCylinder = sectorsPerTrack * sectorSize * heads;
+ }
+ return OK_STATUS;
+}
+
+
+VOID
+SetPartitionActiveFlag(
+ IN PREGION_DESCRIPTOR Region,
+ IN UCHAR value
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPARTITION p = ((PREGION_DATA)Region->Reserved)->Partition;
+
+ if ((UCHAR)p->Active != value)
+ {
+ //
+ // Unfortuneately, the Update flag becomes the RewritePartition flag
+ // at commit time. This causes us to zap the boot sector. To avoid
+ // this, we use a spacial non-boolean value that can be checked for
+ // at commit time and that will cause us NOT to zap the bootsector
+ // even though RewritePartition will be TRUE.
+ //
+
+ p->Active = value;
+ if (!p->Update)
+ {
+ p->Update = CHANGED_DONT_ZAP;
+ }
+ ChangesRequested[p->Disk] = TRUE;
+ }
+}
+
+
+VOID
+DetermineCreateSizeAndOffset(
+ IN PREGION_DESCRIPTOR Region,
+ IN LARGE_INTEGER MinimumSize,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE Type,
+ OUT PLARGE_INTEGER CreationStart,
+ OUT PLARGE_INTEGER CreationSize
+ )
+
+/*++
+
+Routine Description:
+
+ Determine the actual offset and size of the partition, given the
+ size in megabytes.
+
+Arguments:
+
+ Region - a region descriptor returned by GetDiskRegions(). Must
+ be an unused region.
+
+ MinimumSize - if non-0, this is the minimum size that the partition
+ or logical drive can be.
+
+ CreationSizeMB - If MinimumSize is 0, size of partition to create, in MB.
+
+ Type - REGION_PRIMARY, REGION_EXTENDED, or REGION_LOGICAL, for
+ creating a primary partition, extended partition, or
+ logical volume, respectively.
+
+ CreationStart - receives the offset where the partition should be placed.
+
+ CreationSize - receives the exact size for the partition.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PREGION_DATA createData = Region->Reserved;
+ LARGE_INTEGER cSize;
+ LARGE_INTEGER cStart;
+ LARGE_INTEGER mod;
+ ULONG bpc = DiskGeometryArray[Region->Disk].BytesPerCylinder;
+ ULONG bpt = DiskGeometryArray[Region->Disk].BytesPerTrack;
+
+ FDASSERT(Region->SysID == PARTITION_ENTRY_UNUSED);
+
+ //
+ // If we are creating a partition at offset 0, adjust the aligned region
+ // offset and the aligned region size, because no partition can actually
+ // start at offset 0.
+ //
+
+ if (0 == createData->AlignedRegionOffset.QuadPart)
+ {
+ LARGE_INTEGER delta;
+
+ if (Type == REGION_EXTENDED)
+ {
+ delta.QuadPart = bpc;
+ }
+ else
+ {
+ delta.QuadPart = bpt;
+ }
+
+ createData->AlignedRegionOffset = delta;
+ createData->AlignedRegionSize.QuadPart -= delta.QuadPart;
+ }
+
+ cStart = createData->AlignedRegionOffset;
+ if (0 == MinimumSize.QuadPart)
+ {
+ cSize.QuadPart = UInt32x32To64(CreationSizeMB, ONE_MEG);
+ }
+ else
+ {
+ cSize = MinimumSize;
+ if (Type == REGION_LOGICAL)
+ {
+ cSize.QuadPart += bpt;
+ }
+ }
+
+ //
+ // Decide whether to align the ending cylinder up or down.
+ // If the offset of end of the partition is more than half way into the
+ // final cylinder, align towrds the disk end. Otherwise align toward
+ // the disk start.
+ //
+
+ mod.QuadPart = (cStart.QuadPart + cSize.QuadPart) % bpc;
+
+ if (0 != mod.QuadPart)
+ {
+ if ( (0 != MinimumSize.QuadPart) || (mod.QuadPart > (bpc / 2)) )
+ {
+ cSize.QuadPart += ((LONGLONG)bpc - mod.QuadPart);
+ }
+ else
+ {
+ cSize.QuadPart -= mod.QuadPart; // snap downwards tp cyl boundary
+ }
+ }
+
+ if (cSize.QuadPart > createData->AlignedRegionSize.QuadPart)
+ {
+ //
+ // Space available in the free space isn't large enough to accomodate
+ // the request; just use the entire free space.
+ //
+
+ cSize = createData->AlignedRegionSize;
+ }
+
+ *CreationStart = cStart;
+ *CreationSize = cSize;
+}
+
+
+STATUS_CODE
+CreatePartitionEx(
+ IN PREGION_DESCRIPTOR Region,
+ IN LARGE_INTEGER MinimumSize,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE Type,
+ IN UCHAR SysId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates a partition from a free region on the disk. The
+ partition is always created at the beginning of the free space, and any
+ left over space at the end is kept on the free space list.
+
+Arguments:
+
+ Region - a region descriptor returned by GetDiskRegions(). Must
+ be an unused region.
+
+ CreationSizeMB - size of partition to create, in MB.
+
+ Type - REGION_PRIMARY, REGION_EXTENDED, or REGION_LOGICAL, for
+ creating a primary partition, extended partition, or
+ logical volume, respectively.
+
+ SysId - system ID byte to be assigned to the partition
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ PPARTITION p1;
+ PPARTITION p2;
+ PPARTITION p3;
+ PREGION_DATA createData = Region->Reserved;
+ LARGE_INTEGER creationStart;
+ LARGE_INTEGER creationSize;
+ LARGE_INTEGER leftOver;
+ LARGE_INTEGER offset;
+ LARGE_INTEGER length;
+ PPARTITION* partitionList;
+ PARTITION_INFORMATION t = {0};
+
+ DetermineCreateSizeAndOffset(Region,
+ MinimumSize,
+ CreationSizeMB,
+ Type,
+ &creationStart,
+ &creationSize);
+
+ // now we've got the start and size of the partition to be created.
+ // If there's left-over at the beginning of the free space (after
+ // alignment), make a new PARTITION structure.
+
+ p1 = NULL;
+ offset = createData->Partition->Offset;
+ length = createData->Partition->Length;
+ leftOver.QuadPart = creationStart.QuadPart - offset.QuadPart;
+
+ if (leftOver.QuadPart > 0)
+ {
+ p1 = AllocatePartitionStructure(Region->Disk,
+ createData->Partition->Offset,
+ leftOver,
+ NULL,
+ 0,
+ PARTITION_ENTRY_UNUSED,
+ FALSE,
+ FALSE,
+ FALSE);
+ if (p1 == NULL)
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+ }
+
+ // make a new partition structure for space being left free as
+ // a result of this creation.
+
+ p2 = NULL;
+ leftOver.QuadPart = (offset.QuadPart + length.QuadPart)
+ - (creationStart.QuadPart + creationSize.QuadPart);
+
+
+ if (0 != leftOver.QuadPart)
+ {
+ LARGE_INTEGER temp;
+
+ temp.QuadPart = creationStart.QuadPart + creationSize.QuadPart;
+ p2 = AllocatePartitionStructure(Region->Disk,
+ temp,
+ leftOver,
+ NULL,
+ 0,
+ PARTITION_ENTRY_UNUSED,
+ FALSE,
+ FALSE,
+ FALSE);
+ if (p2 == NULL)
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+ }
+
+ // adjust the free partition's fields.
+
+ createData->Partition->Offset = creationStart;
+ createData->Partition->Length = creationSize;
+ createData->Partition->SysID = SysId;
+ createData->Partition->Update = TRUE;
+ createData->Partition->Recognized = TRUE;
+ createData->Partition->EntryCameFromLayout = FALSE;
+ createData->Partition->OriginalLayoutEntrySlot = 0;
+ createData->Partition->OriginalPartitionInformation = t;
+
+ // if we just created an extended partition, show the whole thing
+ // as one free logical region.
+
+ if (Type == REGION_EXTENDED)
+ {
+
+ FDASSERT(LogicalVolumes[Region->Disk] == NULL);
+
+ p3 = AllocatePartitionStructure(Region->Disk,
+ creationStart,
+ creationSize,
+ NULL,
+ 0,
+ PARTITION_ENTRY_UNUSED,
+ FALSE,
+ FALSE,
+ FALSE);
+ if (p3 == NULL)
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+ AddPartitionToLinkedList(&LogicalVolumes[Region->Disk], p3);
+ }
+
+ partitionList = (Type == REGION_LOGICAL)
+ ? &LogicalVolumes[Region->Disk]
+ : &PrimaryPartitions[Region->Disk];
+
+ if (NULL != p1)
+ {
+ AddPartitionToLinkedList(partitionList, p1);
+ }
+ if (NULL != p2)
+ {
+ AddPartitionToLinkedList(partitionList, p2);
+ }
+
+ MergeFreePartitions(*partitionList);
+ ChangesRequested[Region->Disk] = TRUE;
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+CreatePartition(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE Type
+ )
+/*++
+
+Routine Description:
+
+ Create a partition.
+
+Arguments:
+
+ Region - A region descriptor pointer.
+ CreationSizeMB - the size for the new region.
+ Type - the type of region being created.
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ LARGE_INTEGER zero;
+
+ zero.QuadPart = 0;
+ return CreatePartitionEx(Region,
+ zero,
+ CreationSizeMB,
+ Type,
+ (UCHAR)((Type == REGION_EXTENDED) ? PARTITION_EXTENDED
+ : PARTITION_HUGE));
+}
+
+
+
+STATUS_CODE
+DeletePartition(
+ IN PREGION_DESCRIPTOR Region
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deletes a partition, returning its space to the
+ free space on the disk. If deleting the extended partition,
+ all logical volumes within it are also deleted.
+
+Arguments:
+
+ Region - a region descriptor returned by GetDiskRegions(). Must
+ be a used region.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ PREGION_DATA regionData = Region->Reserved;
+ PPARTITION* partitionList;
+ PARTITION_INFORMATION t = {0};
+
+
+ FDASSERT( IsInPartitionList(Region->Disk, regionData->Partition)
+ || IsInLogicalList (Region->Disk, regionData->Partition));
+
+ if (IsExtended(Region->SysID))
+ {
+ FDASSERT(IsInPartitionList(Region->Disk, regionData->Partition));
+
+ // Deleting extended partition. Also delete all logical volumes.
+
+ FreeLinkedPartitionList(&LogicalVolumes[Region->Disk]);
+ }
+
+ regionData->Partition->SysID = PARTITION_ENTRY_UNUSED;
+ regionData->Partition->Update = TRUE;
+ regionData->Partition->Active = FALSE;
+ regionData->Partition->OriginalPartitionNumber = 0;
+ regionData->Partition->EntryCameFromLayout = FALSE;
+ regionData->Partition->OriginalLayoutEntrySlot = 0;
+ regionData->Partition->OriginalPartitionInformation = t;
+
+ partitionList = (Region->RegionType == REGION_LOGICAL)
+ ? &LogicalVolumes[Region->Disk]
+ : &PrimaryPartitions[Region->Disk];
+
+ MergeFreePartitions(*partitionList);
+ ChangesRequested[Region->Disk] = TRUE;
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+GetDiskRegions(
+ IN ULONG Disk,
+ IN BOOLEAN WantUsedRegions,
+ IN BOOLEAN WantFreeRegions,
+ IN BOOLEAN WantPrimaryRegions,
+ IN BOOLEAN WantLogicalRegions,
+ OUT PREGION_DESCRIPTOR* Region,
+ OUT PULONG RegionCount
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns an array of region descriptors to the caller.
+ A region desscriptor describes a space on the disk, either used
+ or free. The caller can control which type of regions are returned.
+
+ The caller must free the returned array via FreeRegionArray().
+
+Arguments:
+
+ Disk - index of disk whose regions are to be returned
+
+ WantUsedRegions - whether to return used disk regions
+
+ WantFreeRegions - whether to return free disk regions
+
+ WantPrimaryRegions - whether to return regions not in the
+ extended partition
+
+ WantLogicalRegions - whether to return regions within the
+ extended partition
+
+ Region - where to put a pointer to the array of regions
+
+ RegionCount - where to put the number of items in the returned
+ Region array
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+
+ STATUS_CODE status = OK_STATUS;
+ *Region = (PREGION_DESCRIPTOR)AllocateMemory(0);
+ *RegionCount = 0;
+
+ if (WantPrimaryRegions)
+ {
+ status = GetRegions(Disk,
+ PrimaryPartitions[Disk],
+ WantUsedRegions,
+ WantFreeRegions,
+ WantLogicalRegions,
+ Region,
+ RegionCount,
+ REGION_PRIMARY);
+
+ if ((status != OK_STATUS) || (*RegionCount == 0)) {
+
+ FreeMemory(*Region);
+ *Region = NULL;
+
+ }
+ }
+ else if (WantLogicalRegions)
+ {
+ status = GetRegions(Disk,
+ LogicalVolumes[Disk],
+ WantUsedRegions,
+ WantFreeRegions,
+ FALSE,
+ Region,
+ RegionCount,
+ REGION_LOGICAL);
+
+ if ((status != OK_STATUS) || (*RegionCount == 0)) {
+
+ FreeMemory(*Region);
+ *Region = NULL;
+
+ }
+ }
+ return status;
+}
+
+
+// workers for GetDiskRegions
+
+STATUS_CODE
+GetRegions(
+ IN ULONG Disk,
+ IN PPARTITION p,
+ IN BOOLEAN WantUsedRegions,
+ IN BOOLEAN WantFreeRegions,
+ IN BOOLEAN WantLogicalRegions,
+ OUT PREGION_DESCRIPTOR* Region,
+ OUT PULONG RegionCount,
+ IN REGION_TYPE RegionType
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ STATUS_CODE status;
+ LARGE_INTEGER alignedOffset;
+ LARGE_INTEGER alignedSize;
+ LARGE_INTEGER temp;
+ ULONG sizeMB;
+
+ while (p)
+ {
+ if (p->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ if (WantFreeRegions)
+ {
+ alignedOffset = AlignTowardsDiskEnd(p->Disk, p->Offset);
+ temp.QuadPart = p->Offset.QuadPart + p->Length.QuadPart;
+ temp = AlignTowardsDiskStart(p->Disk, temp);
+ alignedSize.QuadPart = temp.QuadPart - alignedOffset.QuadPart;
+ sizeMB = SIZEMB(alignedSize);
+
+ // Show the space free if it is greater than 1 meg, AND
+ // it is not a space starting at the beginning of the disk
+ // and of length <= 1 cylinder.
+ // This prevents the user from seeing the first cylinder
+ // of the disk as free (could otherwise happen with an
+ // extended partition starting on cylinder 1 and cylinders
+ // of 1 megabyte or larger).
+
+ if ( (alignedSize.QuadPart > 0)
+ && (0 != sizeMB)
+ && ( (0 != p->Offset.QuadPart)
+ || (p->Length.QuadPart >
+ DiskGeometryArray[p->Disk].BytesPerCylinder)))
+ {
+ if (!AddRegionEntry(Region,
+ RegionCount,
+ sizeMB,
+ RegionType,
+ p,
+ alignedOffset,
+ alignedSize))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (WantUsedRegions)
+ {
+ alignedOffset = p->Offset;
+ alignedSize = p->Length;
+ sizeMB = SIZEMB(alignedSize);
+
+ if (!AddRegionEntry(Region,
+ RegionCount,
+ sizeMB,
+ RegionType,
+ p,
+ alignedOffset,
+ alignedSize))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+ }
+
+ if (IsExtended(p->SysID) && WantLogicalRegions)
+ {
+ status = GetRegions(Disk,
+ LogicalVolumes[Disk],
+ WantUsedRegions,
+ WantFreeRegions,
+ FALSE,
+ Region,
+ RegionCount,
+ REGION_LOGICAL);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+ }
+ }
+ p = p->Next;
+ }
+ return OK_STATUS;
+}
+
+
+BOOLEAN
+AddRegionEntry(
+ OUT PREGION_DESCRIPTOR* Regions,
+ OUT PULONG RegionCount,
+ IN ULONG SizeMB,
+ IN REGION_TYPE RegionType,
+ IN PPARTITION Partition,
+ IN LARGE_INTEGER AlignedRegionOffset,
+ IN LARGE_INTEGER AlignedRegionSize
+ )
+
+/*++
+
+Routine Description:
+
+ Allocate space for the region descriptor and copy the provided data.
+
+Arguments:
+
+ Regions - return the pointer to the new region
+ RegionCount - number of regions on the disk so far
+ SizeMB - size of the region
+ RegionType - type of the region
+ Partition - partition structure with other related information
+ AlignedRegionOffset - region starting location
+ AlignedRegionSize - region size.
+
+Return Value:
+
+ TRUE - The region was added successfully
+ FALSE - it wasn't
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionDescriptor;
+ PREGION_DATA data;
+
+ //BUGBUG: what is 20?
+ regionDescriptor = (PREGION_DESCRIPTOR)ReallocateMemory(*Regions, (((*RegionCount) + 1) * sizeof(REGION_DESCRIPTOR)) + 20);
+ if (regionDescriptor == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ *Regions = regionDescriptor;
+ (*RegionCount)++;
+ }
+
+ regionDescriptor = &(*Regions)[(*RegionCount)-1];
+
+ if (!(regionDescriptor->Reserved = (PREGION_DATA)AllocateMemory(sizeof(REGION_DATA))))
+ {
+ return FALSE;
+ }
+
+ regionDescriptor->Disk = Partition->Disk;
+ regionDescriptor->SysID = Partition->SysID;
+ regionDescriptor->SizeMB = SizeMB;
+ regionDescriptor->Active = Partition->Active;
+ regionDescriptor->Recognized = Partition->Recognized;
+ regionDescriptor->PartitionNumber = Partition->PartitionNumber;
+ regionDescriptor->OriginalPartitionNumber = Partition->OriginalPartitionNumber;
+ regionDescriptor->RegionType = RegionType;
+ regionDescriptor->PersistentData = Partition->PersistentData;
+
+ data = regionDescriptor->Reserved;
+
+ data->Partition = Partition;
+ data->AlignedRegionOffset = AlignedRegionOffset;
+ data->AlignedRegionSize = AlignedRegionSize;
+
+ return TRUE;
+}
+
+
+VOID
+FreeRegionArray(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG RegionCount
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees a region array returned by GetDiskRegions().
+
+Arguments:
+
+ Region - pointer to the array of regions to be freed
+
+ RegionCount - number of items in the Region array
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+
+ for (i=0; i<RegionCount; i++)
+ {
+ if (Region[i].Reserved)
+ {
+ FreeMemory(Region[i].Reserved);
+ }
+ }
+ FreeMemory(Region);
+}
+
+
+
+VOID
+AddPartitionToLinkedList(
+ IN OUT PARTITION** Head,
+ IN PARTITION* p
+ )
+
+/*++
+
+Routine Description:
+
+ This routine adds a PARTITION structure to a doubly-linked
+ list, sorted by the Offset field in ascending order.
+
+Arguments:
+
+ Head - pointer to pointer to first element in list
+
+ p - pointer to item to be added to list
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PARTITION *cur, *prev;
+
+ if ((cur = *Head) == NULL)
+ {
+ *Head = p;
+ return;
+ }
+
+ if (p->Offset.QuadPart < cur->Offset.QuadPart)
+ {
+ p->Next = cur;
+ cur->Prev = p;
+ *Head = p;
+ return;
+ }
+
+ prev = *Head;
+ cur = cur->Next;
+
+ while (cur)
+ {
+ if (p->Offset.QuadPart < cur->Offset.QuadPart)
+ {
+ p->Next = cur;
+ p->Prev = prev;
+ prev->Next = p;
+ cur->Prev = p;
+ return;
+ }
+ prev = cur;
+ cur = cur->Next;
+ }
+
+ prev->Next = p;
+ p->Prev = prev;
+ return;
+}
+
+
+BOOLEAN
+IsInLinkedList(
+ IN PPARTITION p,
+ IN PPARTITION List
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether a PARTITION element is in
+ a given linked list of PARTITION elements.
+
+Arguments:
+
+ p - pointer to element to be checked for
+
+ List - first element in list to be scanned
+
+Return Value:
+
+ true if p found in List, false otherwise
+
+--*/
+
+{
+ while (List)
+ {
+ if (p == List)
+ {
+ return TRUE;
+ }
+ List = List->Next;
+ }
+ return FALSE;
+}
+
+
+BOOLEAN
+IsInLogicalList(
+ IN ULONG Disk,
+ IN PPARTITION p
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether a PARTITION element is in
+ the logical volume list for a given disk.
+
+Arguments:
+
+ Disk - index of disk to be checked
+
+ p - pointer to element to be checked for
+
+Return Value:
+
+ true if p found in Disk's logical volume list, false otherwise
+
+--*/
+
+{
+ return IsInLinkedList(p, LogicalVolumes[Disk]);
+}
+
+
+BOOLEAN
+IsInPartitionList(
+ IN ULONG Disk,
+ IN PPARTITION p
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether a PARTITION element is in
+ the primary partition list for a given disk.
+
+Arguments:
+
+ Disk - index of disk to be checked
+
+ p - pointer to element to be checked for
+
+Return Value:
+
+ true if p found in Disk's primary partition list, false otherwise
+
+--*/
+
+{
+ return IsInLinkedList(p, PrimaryPartitions[Disk]);
+}
+
+
+VOID
+MergeFreePartitions(
+ IN PPARTITION p
+ )
+
+/*++
+
+Routine Description:
+
+ This routine merges adjacent free space elements in the
+ given linked list of PARTITION elements. It is designed
+ to be called after adding or deleting a partition.
+
+Arguments:
+
+ p - pointer to first item in list whose free elements are to
+ be merged.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPARTITION next;
+
+ while (p && p->Next)
+ {
+ if ((p->SysID == PARTITION_ENTRY_UNUSED) && (p->Next->SysID == PARTITION_ENTRY_UNUSED))
+ {
+ next = p->Next;
+
+ p->Length.QuadPart = (next->Offset.QuadPart + next->Length.QuadPart) - p->Offset.QuadPart;
+
+ if (NULL != (p->Next = next->Next))
+ {
+ next->Next->Prev = p;
+ }
+
+ FreeMemory(next);
+ }
+ else
+ {
+ p = p->Next;
+ }
+ }
+}
+
+
+PPARTITION
+FindPartitionElement(
+ IN ULONG Disk,
+ IN ULONG Partition
+ )
+
+/*++
+
+Routine Description:
+
+ This routine locates a PARTITION element for a disk/partition
+ number pair. The partition number is the number that the
+ system assigns to the partition.
+
+Arguments:
+
+ Disk - index of relevent disk
+
+ Partition - partition number of partition to find
+
+Return Value:
+
+ pointer to PARTITION element, or NULL if not found.
+
+--*/
+
+{
+ PPARTITION p;
+
+ FDASSERT(Partition);
+
+ p = PrimaryPartitions[Disk];
+ while (NULL != p)
+ {
+ if ( (p->SysID != PARTITION_ENTRY_UNUSED)
+ && !IsExtended(p->SysID)
+ && (p->PartitionNumber == Partition))
+ {
+ return p;
+ }
+ p = p->Next;
+ }
+ p = LogicalVolumes[Disk];
+ while (NULL != p)
+ {
+ if ( (p->SysID != PARTITION_ENTRY_UNUSED)
+ && (p->PartitionNumber == Partition))
+ {
+ return p;
+ }
+ p = p->Next;
+ }
+ return NULL;
+}
+
+
+VOID
+SetSysID(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ IN UCHAR SysID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the system id of the given partition
+ on the given disk.
+
+Arguments:
+
+ Disk - index of relevent disk
+
+ Partition - partition number of relevent partition
+
+ SysID - new system ID for Partition on Disk
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPARTITION p = FindPartitionElement(Disk, Partition);
+
+ FDASSERT(p);
+
+ if (NULL != p)
+ {
+ p->SysID = SysID;
+ if (!p->Update)
+ {
+ p->Update = CHANGED_DONT_ZAP;
+ }
+ ChangesRequested[p->Disk] = TRUE;
+ }
+}
+
+
+VOID
+SetSysID2(
+ IN PREGION_DESCRIPTOR Region,
+ IN UCHAR SysID
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPARTITION p = ((PREGION_DATA)(Region->Reserved))->Partition;
+
+ p->SysID = SysID;
+ if (!p->Update)
+ {
+ p->Update = CHANGED_DONT_ZAP;
+ }
+ ChangesRequested[p->Disk] = TRUE;
+}
+
+
+
+VOID
+FreeLinkedPartitionList(
+ IN OUT PPARTITION *q
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees a linked list of PARTITION elements. The head
+ pointer is set to NULL.
+
+Arguments:
+
+ p - pointer to pointer to first element of list to free.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PARTITION *n;
+ PARTITION *p = *q;
+
+ while (p)
+ {
+ n = p->Next;
+ FreeMemory(p);
+ p = n;
+ }
+ *q = NULL;
+}
+
+
+VOID
+FreePartitionInfoLinkedLists(
+ IN PPARTITION* ListHeadArray
+ )
+
+/*++
+
+Routine Description:
+
+ This routine frees the linked lists of PARTITION elements
+ for each disk.
+
+Arguments:
+
+ ListHeadArray - pointer to array of pointers to first elements of
+ PARTITION element lists.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+
+ for (i=0; i<CountOfDisks; i++)
+ {
+ FreeLinkedPartitionList(&ListHeadArray[i]);
+ }
+}
+
+
+PPARTITION
+AllocatePartitionStructure(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset,
+ IN LARGE_INTEGER Length,
+ IN PPARTITION_INFORMATION OriginalPartitionInformation,
+ IN ULONG LayoutSlot,
+ IN UCHAR SysID,
+ IN BOOLEAN Update,
+ IN BOOLEAN Active,
+ IN BOOLEAN Recognized
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates space for, and initializes a PARTITION
+ structure.
+
+Arguments:
+
+ Disk - index of disk, one of whose regions the new PARTITION
+ strucure describes.
+
+ Offset - byte offset of region on the disk
+
+ Length - length in bytes of the region
+
+ OriginalPartitionInfromation - If the partition spec came from a drive layout
+ structure retrieved from the disk, save off these values. We will
+ use them to make sure we don't recalculate any values.
+
+ LayoutSlot - The original slot entry that this originalPartitionInformation
+ came from. We use this so that when recreating the disklayout structure
+ we can determine whether the partition info is moved.
+
+ SysID - system id of region, of PARTITION_ENTRY_UNUSED of this PARTITION
+ is actually a free space.
+
+ Update - whether this PARTITION is dirty, ie, has changed and needs
+ to be written to disk.
+
+ Active - flag for the BootIndicator field in a partition table entry,
+ indicates to the x86 master boot program which partition
+ is active.
+
+ Recognized - whether the partition is a type recognized by NT
+
+Return Value:
+
+ NULL if allocation failed, or new initialized PARTITION strucure.
+
+--*/
+
+{
+ PPARTITION p = (PPARTITION)AllocateMemory(sizeof(PARTITION));
+ PARTITION_INFORMATION t = {0};
+
+ if (NULL != p)
+ {
+ p->Next = NULL;
+ p->Prev = NULL;
+ p->Offset = Offset;
+ p->Length = Length;
+ p->Disk = Disk;
+ p->Update = Update;
+ p->Active = Active;
+ p->Recognized = Recognized;
+ p->SysID = SysID;
+ p->OriginalPartitionNumber = 0;
+ p->PartitionNumber = 0;
+ p->PersistentData = 0;
+ p->CommitMirrorBreakNeeded = FALSE;
+ if (OriginalPartitionInformation) {
+ p->OriginalPartitionInformation = *OriginalPartitionInformation;
+ p->OriginalLayoutEntrySlot = LayoutSlot;
+ p->EntryCameFromLayout = TRUE;
+ } else {
+ p->OriginalPartitionInformation = t;
+ p->OriginalLayoutEntrySlot = 0;
+ p->EntryCameFromLayout = FALSE;
+ }
+ }
+ return p;
+}
+
+
+STATUS_CODE
+InitializeFreeSpace(
+ IN ULONG Disk,
+ IN PPARTITION* PartitionList, // list the free space goes in
+ IN LARGE_INTEGER StartOffset,
+ IN LARGE_INTEGER Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines all the free spaces within a given area
+ on a disk, allocates PARTITION structures to describe them,
+ and adds these structures to the relevent partition list
+ (primary partitions or logical volumes).
+
+ No rounding or alignment is performed here. Spaces of even one
+ byte will be counted and inserted in the partition list.
+
+Arguments:
+
+ Disk - index of disk whose free spaces are being sought.
+
+ PartitionList - pointer to first element on PARTITION list that
+ the free spaces will go in.
+
+ StartOffset - start offset of area on disk to consider (ie, 0 for
+ primary spaces or the first byte of the extended
+ partition for logical spaces).
+
+ Length - length of area on disk to consider (ie, size of disk
+ for primary spaces or size of extended partition for
+ logical spaces).
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ PPARTITION p = *PartitionList,
+ q;
+ LARGE_INTEGER start,
+ size;
+
+ start = StartOffset;
+
+ while (p)
+ {
+ size.QuadPart = p->Offset.QuadPart - start.QuadPart;
+
+ if (size.QuadPart > 0)
+ {
+ if (!(q = AllocatePartitionStructure(Disk,
+ start,
+ size,
+ NULL,
+ 0,
+ PARTITION_ENTRY_UNUSED,
+ FALSE,
+ FALSE,
+ FALSE)))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ AddPartitionToLinkedList(PartitionList, q);
+ }
+
+ start.QuadPart = p->Offset.QuadPart + p->Length.QuadPart;
+ p = p->Next;
+ }
+
+ size.QuadPart = (StartOffset.QuadPart + Length.QuadPart) - start.QuadPart;
+
+ if (size.QuadPart > 0)
+ {
+ if (!(q = AllocatePartitionStructure(Disk,
+ start,
+ size,
+ NULL,
+ 0,
+ PARTITION_ENTRY_UNUSED,
+ FALSE,
+ FALSE,
+ FALSE)))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ AddPartitionToLinkedList(PartitionList, q);
+ }
+
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+InitializeLogicalVolumeList(
+ IN ULONG Disk,
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates the logical volume linked list of
+ PARTITION structures for the given disk.
+
+Arguments:
+
+ Disk - index of disk
+
+ DriveLayout - pointer to structure describing the raw partition
+ layout of the disk.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ PPARTITION p,
+ q;
+ ULONG i,
+ j;
+ PPARTITION_INFORMATION d;
+ LARGE_INTEGER hiddenBytes;
+ ULONG bytesPerSector = DiskGeometryArray[Disk].BytesPerSector;
+
+ FreeLinkedPartitionList(&LogicalVolumes[Disk]);
+
+ p = PrimaryPartitions[Disk];
+ while (p)
+ {
+ if (IsExtended(p->SysID))
+ {
+ break;
+ }
+ p = p->Next;
+ }
+
+ if (p)
+ {
+ for (i=ENTRIES_PER_BOOTSECTOR; i<DriveLayout->PartitionCount; i+=ENTRIES_PER_BOOTSECTOR)
+ {
+ for (j=i; j<i+ENTRIES_PER_BOOTSECTOR; j++)
+ {
+ d = &DriveLayout->PartitionEntry[j];
+
+ if ((d->PartitionType != PARTITION_ENTRY_UNUSED) && !IsContainerPartition(d->PartitionType))
+ {
+ LARGE_INTEGER t1, t2;
+
+ hiddenBytes.QuadPart = (LONGLONG)d->HiddenSectors * (LONGLONG)bytesPerSector;
+
+ t1.QuadPart = d->StartingOffset.QuadPart - hiddenBytes.QuadPart;
+ t2.QuadPart = d->PartitionLength.QuadPart + hiddenBytes.QuadPart;
+ if (!(q = AllocatePartitionStructure(
+ Disk,
+ t1,
+ t2,
+ d,
+ j,
+ d->PartitionType,
+ FALSE,
+ d->BootIndicator,
+ d->RecognizedPartition)))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ q->PartitionNumber
+ = q->OriginalPartitionNumber
+ = d->PartitionNumber;
+ AddPartitionToLinkedList(&LogicalVolumes[Disk], q);
+
+ break;
+ }
+ }
+ }
+ return InitializeFreeSpace(Disk,
+ &LogicalVolumes[Disk],
+ p->Offset,
+ p->Length);
+ }
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+InitializePrimaryPartitionList(
+ IN ULONG Disk,
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates the primary partition linked list of
+ PARTITION structures for the given disk.
+
+Arguments:
+
+ Disk - index of disk
+
+ DriveLayout - pointer to structure describing the raw partition
+ layout of the disk.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ ULONG i;
+ PPARTITION p;
+ PPARTITION_INFORMATION d;
+ LARGE_INTEGER zero;
+
+ zero.QuadPart = 0;
+
+ FreeLinkedPartitionList(&PrimaryPartitions[Disk]);
+
+ for (i=0; i<DriveLayout->PartitionCount && i<ENTRIES_PER_BOOTSECTOR; i++)
+ {
+ d = &DriveLayout->PartitionEntry[i];
+
+ if (d->PartitionType != PARTITION_ENTRY_UNUSED)
+ {
+ if (!(p = AllocatePartitionStructure(
+ Disk,
+ d->StartingOffset,
+ d->PartitionLength,
+ d,
+ i,
+ d->PartitionType,
+ FALSE,
+ d->BootIndicator,
+ d->RecognizedPartition)))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ p->PartitionNumber
+ = p->OriginalPartitionNumber
+ = (IsExtended(p->SysID) ? 0 : d->PartitionNumber);
+
+ AddPartitionToLinkedList(&PrimaryPartitions[Disk], p);
+ }
+ }
+ return InitializeFreeSpace(Disk,
+ &PrimaryPartitions[Disk],
+ zero,
+ DiskLengthBytes(Disk));
+}
+
+VOID
+ReconcilePartitionNumbers(
+ ULONG Disk,
+ PDRIVE_LAYOUT_INFORMATION DriveLayout
+ )
+
+/*++
+
+Routine Description:
+
+ With dynamic partitioning, the partitions on the disk will no longer
+ follow sequencial numbering schemes. It will be possible for a disk
+ to have a partition #1 that is the last partition on the disk and a
+ partition #3 that is the first. This routine runs through the NT
+ namespace for harddisks to resolve this inconsistency.
+
+ This routine has the problem that it will not locate partitions that
+ are part of an FT set because the partition information for these
+ partitions will be modified to reflect the size of the set, not the
+ size of the partition.
+
+Arguments:
+
+ Disk - the disk number
+ DriveLayout - the partitioning information
+
+Return Value:
+
+ None
+
+--*/
+
+{
+#define BUFFERSIZE 1024
+
+ NTSTATUS status;
+ IO_STATUS_BLOCK statusBlock;
+ HANDLE directoryHandle,
+ partitionHandle;
+ CLONG continueProcessing;
+ ULONG context = 0,
+ returnedLength,
+ index;
+ POBJECT_DIRECTORY_INFORMATION dirInfo;
+ PARTITION_INFORMATION partitionInfo;
+ PPARTITION_INFORMATION partitionInfoPtr;
+ OBJECT_ATTRIBUTES attributes;
+ UNICODE_STRING unicodeString;
+ ANSI_STRING ansiName;
+ PUCHAR deviceName;
+ PUCHAR buffer;
+
+ deviceName = (PUCHAR)Malloc(100);
+ if (!deviceName)
+ {
+ return;
+ }
+
+ buffer = (PUCHAR)Malloc(BUFFERSIZE);
+ if (!buffer)
+ {
+ Free(deviceName);
+ return;
+ }
+
+ sprintf((PCHAR)deviceName, "\\Device\\Harddisk%d", Disk);
+ RtlInitAnsiString(&ansiName, (PCHAR)deviceName);
+ status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiName, TRUE);
+
+ if (!NT_SUCCESS(status))
+ {
+ Free(deviceName);
+ Free(buffer);
+ return;
+ }
+ InitializeObjectAttributes(&attributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ status = NtOpenDirectoryObject(&directoryHandle,
+ DIRECTORY_QUERY,
+ &attributes);
+ if (!NT_SUCCESS(status))
+ {
+ Free(deviceName);
+ Free(buffer);
+ return;
+ }
+
+ // Query the entire directory in one sweep
+
+ continueProcessing = 1;
+ while (continueProcessing)
+ {
+ RtlZeroMemory(buffer, BUFFERSIZE);
+ status = NtQueryDirectoryObject(directoryHandle,
+ buffer,
+ BUFFERSIZE,
+ FALSE,
+ FALSE,
+ &context,
+ &returnedLength);
+
+ // Check the status of the operation.
+
+ if (!NT_SUCCESS(status))
+ {
+ if (status != STATUS_NO_MORE_FILES)
+ {
+ break;
+ }
+ continueProcessing = 0;
+ }
+
+ // For every record in the buffer check for partition name
+
+
+ for (dirInfo = (POBJECT_DIRECTORY_INFORMATION) buffer;
+ TRUE;
+ dirInfo = (POBJECT_DIRECTORY_INFORMATION) (((PUCHAR) dirInfo) +
+ sizeof(OBJECT_DIRECTORY_INFORMATION)))
+ {
+ // Check if there is another record. If there isn't, then get out
+ // of the loop now
+
+ if (dirInfo->Name.Length == 0)
+ {
+ break;
+ }
+
+ // compare the name to see if it is a Partition
+
+ if (0 == _wcsnicmp(dirInfo->Name.Buffer, L"Partition", 9))
+ {
+ UCHAR digits[3];
+ ULONG partitionNumber;
+
+ // Located a partition. This restricts the # of partitions
+ // to 99.
+
+ digits[0] = (UCHAR)dirInfo->Name.Buffer[9];
+ digits[1] = (UCHAR)dirInfo->Name.Buffer[10];
+ digits[2] = 0;
+ partitionNumber = atoi((PCHAR)digits);
+
+ if (partitionNumber <= 0)
+ {
+ // less than zero is really an error...
+ // partition zero is always the same.
+
+ continue;
+ }
+
+ // Have a numbered partition -- match it to the drive layout
+
+ status = LowOpenPartition((PCHAR)deviceName, partitionNumber, &partitionHandle);
+ if (!NT_SUCCESS(status))
+ {
+ // If it cannot be opened perhaps it isn't really a partition
+ continue;
+ }
+
+ status = NtDeviceIoControlFile(partitionHandle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_PARTITION_INFO,
+ NULL,
+ 0,
+ &partitionInfo,
+ sizeof(PARTITION_INFORMATION));
+
+ if (!NT_SUCCESS(status))
+ {
+ LowCloseDisk(partitionHandle);
+ continue;
+ }
+
+ // match partition information with drive layout.
+
+ for (index = 0; index < DriveLayout->PartitionCount; index++)
+ {
+ partitionInfoPtr = &DriveLayout->PartitionEntry[index];
+ if ((partitionInfoPtr->StartingOffset.QuadPart == partitionInfo.StartingOffset.QuadPart) &&
+ (partitionInfoPtr->PartitionLength.QuadPart == partitionInfo.PartitionLength.QuadPart))
+ {
+ // This is a match.
+
+ partitionInfoPtr->PartitionNumber = partitionNumber;
+ break;
+ }
+ }
+ LowCloseDisk(partitionHandle);
+ }
+ }
+ }
+
+ // Now close the directory object
+
+ Free(deviceName);
+ Free(buffer);
+ (VOID) NtClose(directoryHandle);
+ return;
+}
+
+
+VOID
+CheckForOldDrivers(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines if an old release 3.1 drive is in the
+ system. If so, it calculates the partition number for each region
+ on a disk. For a used region, the partition number is the number
+ that the system will assign to the partition. All partitions
+ (except the extended partition) are numbered first starting at 1,
+ and then all logical volumes in the extended partition.
+ For a free region, the partition number is the number that the
+ system WOULD assign to the partition if the space were to be
+ converted to a partition and all other regions on the disk were
+ left as is.
+
+ The partition numbers are stored in the PARTITION elements.
+
+Arguments:
+
+ Disk - index of disk whose partitions are to be renumbered.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPARTITION p = PrimaryPartitions[Disk];
+ ULONG n = 1;
+
+ while (NULL != p)
+ {
+ if (p->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ if ((!IsExtended(p->SysID)) && (IsRecognizedPartition(p->SysID)))
+ {
+ // If there is already a partition number, nothing need be
+ // done here.
+
+ if (p->PartitionNumber)
+ {
+ return;
+ }
+ else
+ {
+ RestartRequired = TRUE;
+ }
+ p->PartitionNumber = n;
+ if (p->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ n++;
+ }
+ }
+ }
+ p = p->Next;
+ }
+
+ p = LogicalVolumes[Disk];
+ while (NULL != p)
+ {
+ if (p->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ if (p->PartitionNumber)
+ {
+ return;
+ }
+ else
+ {
+ RestartRequired = TRUE;
+ }
+ p->PartitionNumber = n;
+ n++;
+ }
+ p = p->Next;
+ }
+}
+
+
+
+STATUS_CODE
+InitializePartitionLists(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scans the PARTITION_INFO array returned for each disk
+ by the OS. A linked list of PARTITION structures is layered on top
+ of each array; the net result is a sorted list that covers an entire
+ disk, because free spaces are also factored in as 'dummy' partitions.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ STATUS_CODE status;
+ ULONG disk;
+ PDRIVE_LAYOUT_INFORMATION driveLayout;
+
+ for (disk = 0; disk < CountOfDisks; disk++)
+ {
+ if (OffLine[disk])
+ {
+ continue;
+ }
+
+ if ((status = LowGetDiskLayout(DiskNames[disk], &driveLayout)) != OK_STATUS)
+ {
+
+ if (IsRemovable(disk)) {
+
+ status = OK_STATUS;
+ continue;
+
+ }
+ return status;
+ }
+
+ // ReconcilePartitionNumbers(disk, driveLayout);
+
+ status = InitializePrimaryPartitionList(disk, driveLayout);
+ if (status == OK_STATUS)
+ {
+ status = InitializeLogicalVolumeList(disk, driveLayout);
+ }
+
+ if (status != OK_STATUS)
+ {
+ FreeMemory(driveLayout);
+ return status;
+ }
+
+ Signatures[disk] = driveLayout->Signature;
+ FreeMemory(driveLayout);
+ CheckForOldDrivers(disk);
+ }
+ return OK_STATUS;
+}
+
+
+
+LARGE_INTEGER
+DiskLengthBytes(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines the disk length in bytes. This value
+ is calculated from the disk geometry information.
+
+Arguments:
+
+ Disk - index of disk whose size is desired
+
+Return Value:
+
+ Size of Disk.
+
+--*/
+
+{
+ LARGE_INTEGER result;
+
+ result.QuadPart = DiskGeometryArray[Disk].Cylinders.QuadPart *
+ DiskGeometryArray[Disk].BytesPerCylinder;
+ return result;
+}
+
+
+ULONG
+SIZEMB(
+ IN LARGE_INTEGER ByteCount
+ )
+
+/*++
+
+Routine Description:
+
+ Calculate the size in megabytes of a given byte count. The value is
+ properly rounded (ie, not merely truncated).
+
+ This function replaces a macro of the same name that was truncating
+ instead of rounding.
+
+Arguments:
+
+ ByteCount - supplies number of bytes
+
+Return Value:
+
+ Size in MB equivalent to ByteCount.
+
+--*/
+
+{
+ ULONG Remainder;
+ ULONG SizeMB;
+
+ SizeMB = RtlExtendedLargeIntegerDivide(ByteCount,
+ ONE_MEG,
+ &Remainder).LowPart;
+
+ if (Remainder >= ONE_MEG/2)
+ {
+ SizeMB++;
+ }
+
+ return SizeMB;
+}
+
+ULONG
+DiskSizeMB(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines the disk length in megabytes. The returned
+ value is rounded down after division by 1024*1024.
+
+Arguments:
+
+ Disk - index of disk whose size is desired
+
+Return Value:
+
+ Size of Disk.
+
+--*/
+
+{
+ return SIZEMB(DiskLengthBytes(Disk));
+}
+
+
+LARGE_INTEGER
+AlignTowardsDiskStart(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This routine snaps a byte offset to a cylinder boundary, towards
+ the start of the disk.
+
+Arguments:
+
+ Disk - index of disk whose offset is to be snapped
+
+ Offset - byte offset to be aligned (snapped to cylinder boundary)
+
+Return Value:
+
+ Aligned offset.
+
+--*/
+
+{
+ LARGE_INTEGER mod, result;
+
+ mod.QuadPart = Offset.QuadPart % DiskGeometryArray[Disk].BytesPerCylinder;
+ result.QuadPart = Offset.QuadPart - mod.QuadPart;
+
+ return result;
+}
+
+
+LARGE_INTEGER
+AlignTowardsDiskEnd(
+ IN ULONG Disk,
+ IN LARGE_INTEGER Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This routine snaps a byte offset to a cylinder boundary, towards
+ the end of the disk.
+
+Arguments:
+
+ Disk - index of disk whose offset is to be snapped
+
+ Offset - byte offset to be aligned (snapped to cylinder boundary)
+
+Return Value:
+
+ Aligned offset.
+
+--*/
+
+{
+ LARGE_INTEGER mod, temp;
+
+ mod.QuadPart = Offset.QuadPart % DiskGeometryArray[Disk].BytesPerCylinder;
+
+ if (0 != mod.QuadPart)
+ {
+ temp.QuadPart = Offset.QuadPart + DiskGeometryArray[Disk].BytesPerCylinder;
+ Offset = AlignTowardsDiskStart(Disk, temp);
+ }
+ return Offset;
+}
+
+
+BOOLEAN
+IsExtended(
+ IN UCHAR SysID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether a given system id is for an
+ extended type (ie, link) entry.
+
+Arguments:
+
+ SysID - system id to be tested.
+
+Return Value:
+
+ true/false based on whether SysID is for an extended type.
+
+--*/
+
+{
+ return (BOOLEAN)(IsContainerPartition(SysID));
+}
+
+
+STATUS_CODE
+IsAnyCreationAllowed(
+ IN ULONG Disk,
+ IN BOOLEAN AllowMultiplePrimaries,
+ OUT PBOOLEAN AnyAllowed,
+ OUT PBOOLEAN PrimaryAllowed,
+ OUT PBOOLEAN ExtendedAllowed,
+ OUT PBOOLEAN LogicalAllowed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether any partition may be created on a
+ given disk, based on three sub-queries -- whether creation is allowed
+ of a primary partition, an extended partition, or a logical volume.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ AllowMultiplePrimaries - whether to allow multiple primary partitions
+
+ AnyAllowed - returns whether any creation is allowed
+
+ PrimaryAllowed - returns whether creation of a primary partition
+ is allowed
+
+ ExtendedAllowed - returns whether creation of an extended partition
+ is allowed
+
+ Logical Allowed - returns whether creation of a logical volume is allowed.
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ STATUS_CODE status;
+
+ if ((status = IsCreationOfPrimaryAllowed(Disk, AllowMultiplePrimaries, PrimaryAllowed)) != OK_STATUS)
+ {
+ return status;
+ }
+ if ((status = IsCreationOfExtendedAllowed(Disk, ExtendedAllowed)) != OK_STATUS)
+ {
+ return status;
+ }
+ if ((status = IsCreationOfLogicalAllowed(Disk, LogicalAllowed)) != OK_STATUS)
+ {
+ return status;
+ }
+ *AnyAllowed = (BOOLEAN)(*PrimaryAllowed || *ExtendedAllowed || *LogicalAllowed);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+IsCreationOfPrimaryAllowed(
+ IN ULONG Disk,
+ IN BOOLEAN AllowMultiplePrimaries,
+ OUT PBOOLEAN Allowed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether creation of a primary partition is
+ allowed. This is true when there is a free entry in the MBR and
+ there is free primary space on the disk. If multiple primaries
+ are not allowed, then there must also not exist any primary partitions
+ in order for a primary creation to be allowed.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ AllowMultiplePrimaries - whether existnace of primary partition
+ disallows creation of a primary partition
+
+ Allowed - returns whether creation of a primary partition
+ is allowed
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionArray;
+ ULONG regionCount;
+ ULONG usedCount;
+ ULONG recogCount;
+ ULONG i;
+ STATUS_CODE status;
+ BOOLEAN freeSpace = FALSE;
+
+ status = GetPrimaryDiskRegions(Disk, &regionArray, &regionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ for (usedCount = recogCount = i = 0; i<regionCount; i++)
+ {
+ FDASSERT(regionArray[i].RegionType != REGION_LOGICAL);
+ if (regionArray[i].SysID == PARTITION_ENTRY_UNUSED)
+ {
+ freeSpace = TRUE;
+ }
+ else
+ {
+ usedCount++;
+ if (!IsExtended(regionArray[i].SysID) && regionArray[i].Recognized)
+ {
+ recogCount++;
+ }
+ }
+ }
+ FDASSERT(usedCount <= ENTRIES_PER_BOOTSECTOR);
+ FDASSERT(recogCount <= ENTRIES_PER_BOOTSECTOR);
+ FDASSERT(recogCount <= usedCount);
+
+ if ( (usedCount < ENTRIES_PER_BOOTSECTOR)
+ && freeSpace
+ && (!recogCount || AllowMultiplePrimaries))
+ {
+ *Allowed = TRUE;
+ }
+ else
+ {
+ *Allowed = FALSE;
+ }
+
+ FreeRegionArray(regionArray, regionCount);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+IsCreationOfExtendedAllowed(
+ IN ULONG Disk,
+ OUT BOOLEAN *Allowed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether creation of an extended partition is
+ allowed. This is true when there is a free entry in the MBR,
+ there is free primary space on the disk, and there is no existing
+ extended partition.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ Allowed - returns whether creation of an extended partition
+ is allowed
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionArray;
+ ULONG regionCount;
+ ULONG usedCount;
+ ULONG freeCount;
+ ULONG i;
+ STATUS_CODE status;
+
+ status = GetPrimaryDiskRegions(Disk, &regionArray, &regionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ for (usedCount = freeCount = i = 0; i<regionCount; i++)
+ {
+ FDASSERT(regionArray[i].RegionType != REGION_LOGICAL);
+ if (regionArray[i].SysID == PARTITION_ENTRY_UNUSED)
+ {
+ // BUGBUG should adjust the size here and see if it's non0 first
+ // (ie, take into account that the extended partition can't
+ // start on cyl 0).
+ freeCount++;
+ }
+ else
+ {
+ usedCount++;
+ if (IsExtended(regionArray[i].SysID))
+ {
+ FreeRegionArray(regionArray, regionCount);
+ *Allowed = FALSE;
+ return OK_STATUS;
+ }
+ }
+ }
+ *Allowed = (BOOLEAN)((usedCount < ENTRIES_PER_BOOTSECTOR) && freeCount);
+ FreeRegionArray(regionArray, regionCount);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+IsCreationOfLogicalAllowed(
+ IN ULONG Disk,
+ OUT BOOLEAN *Allowed
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether creation of a logical volume is
+ allowed. This is true when there is an extended partition and
+ free space within it.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ Allowed - returns whether creation of a logical volume is allowed
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR Regions;
+ ULONG RegionCount;
+ ULONG i;
+ STATUS_CODE status;
+ BOOLEAN ExtendedExists;
+
+ *Allowed = FALSE;
+
+ status = DoesExtendedExist(Disk, &ExtendedExists);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+ if (!ExtendedExists)
+ {
+ return OK_STATUS;
+ }
+
+ status = GetLogicalDiskRegions(Disk, &Regions, &RegionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ for (i = 0; i<RegionCount; i++)
+ {
+ FDASSERT(Regions[i].RegionType == REGION_LOGICAL);
+ if (Regions[i].SysID == PARTITION_ENTRY_UNUSED)
+ {
+ *Allowed = TRUE;
+ break;
+ }
+ }
+ FreeRegionArray(Regions, RegionCount);
+ return OK_STATUS;
+}
+
+
+
+STATUS_CODE
+DoesAnyPartitionExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN AnyExists,
+ OUT PBOOLEAN PrimaryExists,
+ OUT PBOOLEAN ExtendedExists,
+ OUT PBOOLEAN LogicalExists
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether any partition exists on a given disk.
+ This is based on three sub queries: whether there are any primary or
+ extended partitions, or logical volumes on the disk.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ AnyExists - returns whether any partitions exist on Disk
+
+ PrimaryExists - returns whether any primary partitions exist on Disk
+
+ ExtendedExists - returns whether there is an extended partition on Disk
+
+ LogicalExists - returns whether any logical volumes exist on Disk
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ STATUS_CODE status;
+
+ if ((status = DoesAnyPrimaryExist(Disk, PrimaryExists )) != OK_STATUS)
+ {
+ return status;
+ }
+ if ((status = DoesExtendedExist (Disk, ExtendedExists)) != OK_STATUS)
+ {
+ return status;
+ }
+ if ((status = DoesAnyLogicalExist(Disk, LogicalExists )) != OK_STATUS)
+ {
+ return status;
+ }
+ *AnyExists = (BOOLEAN)(*PrimaryExists || *ExtendedExists || *LogicalExists);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+DoesAnyPrimaryExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether any non-extended primary partition exists
+ on a given disk.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ Exists - returns whether any primary partitions exist on Disk
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionArray;
+ ULONG regionCount;
+ ULONG i;
+ STATUS_CODE status;
+
+ status = GetUsedPrimaryDiskRegions(Disk, &regionArray, &regionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ *Exists = FALSE;
+
+ for (i=0; i<regionCount; i++)
+ {
+ FDASSERT(regionArray[i].RegionType != REGION_LOGICAL);
+ FDASSERT(regionArray[i].SysID != PARTITION_ENTRY_UNUSED);
+ if (!IsExtended(regionArray[i].SysID))
+ {
+ *Exists = TRUE;
+ break;
+ }
+ }
+ FreeRegionArray(regionArray, regionCount);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+DoesExtendedExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether an extended partition exists
+ on a given disk.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ Exists - returns whether an extended partition exists on Disk
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionArray;
+ ULONG regionCount;
+ ULONG i;
+ STATUS_CODE status;
+
+ status = GetUsedPrimaryDiskRegions(Disk, &regionArray, &regionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ *Exists = FALSE;
+
+ for (i=0; i<regionCount; i++)
+ {
+ FDASSERT(regionArray[i].RegionType != REGION_LOGICAL);
+ FDASSERT(regionArray[i].SysID != PARTITION_ENTRY_UNUSED);
+ if (IsExtended(regionArray[i].SysID))
+ {
+ *Exists = TRUE;
+ break;
+ }
+ }
+ FreeRegionArray(regionArray, regionCount);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+DoesAnyLogicalExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines whether any logical volumes exist
+ on a given disk.
+
+Arguments:
+
+ Disk - index of disk to check
+
+ Exists - returns whether any logical volumes exist on Disk
+
+Return Value:
+
+ OK_STATUS or error code
+
+--*/
+
+{
+ PREGION_DESCRIPTOR regionArray;
+ ULONG regionCount;
+ STATUS_CODE status;
+
+ status = GetUsedLogicalDiskRegions(Disk, &regionArray, &regionCount);
+ if (status != OK_STATUS)
+ {
+ return status;
+ }
+
+ *Exists = (BOOLEAN)(regionCount != 0);
+ FreeRegionArray(regionArray, regionCount);
+ return OK_STATUS;
+}
+
+
+ULONG
+GetDiskCount(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the number of attached partitionable disk
+ devices. The returned value is one greater than the maximum index
+ allowed for Disk parameters to partitioning engine routines.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Count of disks.
+
+--*/
+
+{
+ return CountOfDisks;
+}
+
+
+PCHAR
+GetDiskName(
+ ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the system name for the disk device whose
+ index is given.
+
+Arguments:
+
+ Disk - index of disk whose name is desired.
+
+Return Value:
+
+ System name for the disk device. The caller must not attempt to
+ free this buffer or modify it.
+
+--*/
+
+{
+ return DiskNames[Disk];
+}
+
+
+// worker routines for WriteDriveLayout
+
+VOID
+UnusedEntryFill(
+ IN PPARTITION_INFORMATION pInfo,
+ IN ULONG EntryCount
+ )
+
+/*++
+
+Routine Description:
+
+ Initialize a partition information structure.
+
+Arguments:
+
+ pInfo - the partition information structure to fill in.
+ EntryCount - the number of entries in the structure to fill.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+ LARGE_INTEGER zero;
+
+ zero.QuadPart = 0;
+
+ for (i=0; i<EntryCount; i++)
+ {
+ pInfo[i].StartingOffset = zero;
+ pInfo[i].PartitionLength = zero;
+ pInfo[i].HiddenSectors = 0;
+ pInfo[i].PartitionType = PARTITION_ENTRY_UNUSED;
+ pInfo[i].BootIndicator = FALSE;
+ pInfo[i].RewritePartition = TRUE;
+ }
+}
+
+
+LARGE_INTEGER
+MakeBootRec(
+ ULONG Disk,
+ PPARTITION_INFORMATION pInfo,
+ PPARTITION pLogical,
+ PPARTITION pNextLogical,
+ ULONG TargetSlotEntry
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ Disk - the disk number
+ pInfo - the partition information for the disk.
+ pLogical
+ pNextLogical,
+ TargetSlotEntry - Where in the drive layout the entry will go. Need
+ this so we can detect if an entry moves.
+
+Return Value:
+
+ The starting offset.
+
+--*/
+
+{
+ ULONG entry = 0;
+ LARGE_INTEGER bytesPerTrack;
+ LARGE_INTEGER sectorsPerTrack;
+ LARGE_INTEGER startingOffset;
+
+ bytesPerTrack.QuadPart = DiskGeometryArray[Disk].BytesPerTrack;
+ sectorsPerTrack.QuadPart = DiskGeometryArray[Disk].SectorsPerTrack;
+ startingOffset.QuadPart = 0;
+
+ if (pLogical)
+ {
+
+ if (pLogical->EntryCameFromLayout) {
+
+ pInfo[entry] = pLogical->OriginalPartitionInformation;
+
+ } else {
+
+ pInfo[entry].StartingOffset.QuadPart = pLogical->Offset.QuadPart + bytesPerTrack.QuadPart;
+ pInfo[entry].PartitionLength.QuadPart = pLogical->Length.QuadPart - bytesPerTrack.QuadPart;
+ pInfo[entry].HiddenSectors = sectorsPerTrack.LowPart;
+
+ }
+
+ pInfo[entry].RewritePartition = pLogical->Update;
+ pInfo[entry].BootIndicator = pLogical->Active;
+ pInfo[entry].PartitionType = pLogical->SysID;
+
+ if (pLogical->EntryCameFromLayout &&
+ (TargetSlotEntry != pLogical->OriginalLayoutEntrySlot)) {
+
+ pInfo[entry].RewritePartition = TRUE;
+ pLogical->OriginalLayoutEntrySlot = TargetSlotEntry;
+
+ }
+
+ if (pInfo[entry].RewritePartition)
+ {
+ startingOffset = pInfo[entry].StartingOffset;
+ }
+
+ //
+ // Since the data will shortly be going ondisk we need to mark this
+ // entry as being from the disk layout and we should propagate
+ // back the information into the original partition info.
+ //
+
+ pLogical->EntryCameFromLayout = TRUE;
+ pLogical->OriginalLayoutEntrySlot = entry;
+ pLogical->OriginalPartitionInformation = pInfo[entry];
+ pLogical->OriginalPartitionInformation.RewritePartition = FALSE;
+ entry++;
+ }
+
+ if (pNextLogical)
+ {
+ pInfo[entry].StartingOffset = pNextLogical->Offset;
+ pInfo[entry].PartitionLength = pNextLogical->Length;
+ pInfo[entry].HiddenSectors = 0;
+ pInfo[entry].RewritePartition = TRUE;
+ pInfo[entry].BootIndicator = FALSE;
+ pInfo[entry].PartitionType = PARTITION_EXTENDED;
+
+ entry++;
+ }
+
+ UnusedEntryFill(pInfo+entry, ENTRIES_PER_BOOTSECTOR-entry);
+ return startingOffset;
+}
+
+
+STATUS_CODE
+ZapSector(
+ ULONG Disk,
+ LARGE_INTEGER Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes zeros into a sector at a given offset. This is
+ used to clear out a new partition's filesystem boot record, so that
+ no previous filesystem appears in a new partition; or to clear out the
+ first EBR in the extended partition if there are to be no logical vols.
+
+Arguments:
+
+ Disk - disk to write to
+
+ Offset - byte offset to a newly created partition on Disk
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ ULONG sectorSize = DiskGeometryArray[Disk].BytesPerSector;
+ ULONG i;
+ PCHAR sectorBuffer;
+ PCHAR alignedSectorBuffer;
+ STATUS_CODE status;
+ HANDLE_T handle;
+ LARGE_INTEGER temp;
+
+ if ((sectorBuffer = (PCHAR)AllocateMemory(2*sectorSize)) == NULL)
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ alignedSectorBuffer = (PCHAR)(((ULONG)sectorBuffer+sectorSize) & ~(sectorSize-1));
+
+ for (i=0; i<sectorSize; i++)
+ {
+ alignedSectorBuffer[i] = 0;
+ }
+
+ if ((status = LowOpenDisk(GetDiskName(Disk), &handle)) != OK_STATUS)
+ {
+ FreeMemory(sectorBuffer);
+ return status;
+ }
+
+ temp.QuadPart = Offset.QuadPart / sectorSize;
+ status = LowWriteSectors(handle,
+ sectorSize,
+ temp.LowPart,
+ 1,
+ alignedSectorBuffer);
+
+ LowCloseDisk(handle);
+
+ // Now to make sure the file system really did a dismount,
+ // force a mount/verify of the partition. This avoids a
+ // problem where HPFS doesn't dismount when asked, but instead
+ // marks the volume for verify.
+
+ if ((status = LowOpenDisk(GetDiskName(Disk),&handle)) == OK_STATUS)
+ {
+ LowCloseDisk(handle);
+ }
+
+ FreeMemory(sectorBuffer);
+
+ return status;
+}
+
+
+STATUS_CODE
+WriteDriveLayout(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the current partition layout for a given disk
+ out to disk. The high-level PARTITION lists are transformed into
+ a DRIVE_LAYOUT_INFORMATION structure before being passed down
+ to the low-level partition table writing routine.
+
+Arguments:
+
+ Disk - index of disk whose on-disk partition structure is to be updated.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+#define MAX_DISKS 250
+
+ PDRIVE_LAYOUT_INFORMATION driveLayout;
+ PPARTITION_INFORMATION pInfo;
+ ULONG entryCount;
+ ULONG sectorSize;
+ STATUS_CODE status;
+ LARGE_INTEGER startingOffset,
+ extendedStartingOffset;
+ PPARTITION nextPartition,
+ partition,
+ partitionHash[MAX_DISKS];
+
+ extendedStartingOffset.QuadPart = 0;
+ memset(partitionHash, 0, sizeof(partitionHash));
+
+ // allocate a huge buffer now to avoid complicated dynamic
+ // reallocation schemes later.
+
+ if (!(driveLayout = (PDRIVE_LAYOUT_INFORMATION)AllocateMemory((MAX_DISKS + 1) * sizeof(PARTITION_INFORMATION))))
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ pInfo = &driveLayout->PartitionEntry[0];
+
+ // first do the mbr.
+
+ entryCount=0;
+ partition = PrimaryPartitions[Disk];
+ sectorSize = DiskGeometryArray[Disk].BytesPerSector;
+
+ while (NULL != partition)
+ {
+ if (partition->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ FDASSERT(entryCount < ENTRIES_PER_BOOTSECTOR);
+
+ if (IsExtended(partition->SysID))
+ {
+ extendedStartingOffset = partition->Offset;
+ }
+ else
+ {
+ partitionHash[entryCount] = partition;
+ }
+
+ //
+ // Check to see if the drive layout information here came
+ // from on-disk. If so, then use that instead of our generated.
+ // Note that we have to set rewrite IF the slot we are going into
+ // isn't the slot we originally were from. If it isn't make
+ // sure we reset the slot entry to where we are going.
+ //
+
+ if (partition->EntryCameFromLayout) {
+
+ pInfo[entryCount] = partition->OriginalPartitionInformation;
+
+ } else {
+
+ pInfo[entryCount].StartingOffset = partition->Offset;
+ pInfo[entryCount].PartitionLength = partition->Length;
+ pInfo[entryCount].HiddenSectors = (ULONG)(partition->Offset.QuadPart / sectorSize);
+
+ }
+
+ pInfo[entryCount].PartitionType = partition->SysID;
+ pInfo[entryCount].BootIndicator = partition->Active;
+ pInfo[entryCount].RewritePartition = partition->Update;
+
+ if (partition->EntryCameFromLayout &&
+ (entryCount != partition->OriginalLayoutEntrySlot)) {
+
+ pInfo[entryCount].RewritePartition = TRUE;
+ partition->OriginalLayoutEntrySlot = entryCount;
+
+ }
+
+ //
+ // Since the data will shortly be going ondisk we need to mark this
+ // entry as being from the disk layout and we should propagate
+ // back the information into the original partition info.
+ //
+
+ partition->EntryCameFromLayout = TRUE;
+ partition->OriginalLayoutEntrySlot = entryCount;
+ partition->OriginalPartitionInformation = pInfo[entryCount];
+ partition->OriginalPartitionInformation.RewritePartition = FALSE;
+
+ // if we're creating this partition, clear out the
+ // filesystem boot sector.
+
+ if ( pInfo[entryCount].RewritePartition
+ && partition->Update
+ && (partition->Update != CHANGED_DONT_ZAP)
+ && !IsExtended(pInfo[entryCount].PartitionType))
+ {
+ status = ZapSector(Disk, pInfo[entryCount].StartingOffset);
+ if (status != OK_STATUS)
+ {
+ FreeMemory(driveLayout);
+ return status;
+ }
+ }
+
+ entryCount++;
+ }
+ partition = partition->Next;
+ }
+
+ // fill the remainder of the MBR with unused entries.
+ // NOTE that there will thus always be an MBR even if there
+ // are no partitions defined.
+
+ UnusedEntryFill(pInfo+entryCount, ENTRIES_PER_BOOTSECTOR - entryCount);
+ entryCount = ENTRIES_PER_BOOTSECTOR;
+
+ //
+ // now handle the logical volumes.
+ // first check to see whether we need a dummy EBR at the beginning
+ // of the extended partition. This is the case when there is
+ // free space at the beginning of the extended partition.
+#if 0
+ // Also handle the case where we are creating an empty extended
+ // partition -- need to zap the first sector to eliminate any residue
+ // that might start an EBR chain.
+#else
+ // BUGBUG 4/24/92 tedm: Currently the io subsystem returns an error
+ // status (status_bad_master_boot_record) if any mbr or ebr is bad.
+ // Zeroing the first sector of the extended partition therefore causes
+ // the whole disk to be seen as empty. So create a blank, but valid,
+ // EBR in the 'empty extended partition' case. Code is in the 'else'
+ // part of the #if 0, below.
+#endif
+ //
+
+ if ( (NULL != (partition = LogicalVolumes[Disk]))
+ && (partition->SysID == PARTITION_ENTRY_UNUSED))
+ {
+ if (partition->Next)
+ {
+ partitionHash[entryCount] = partition;
+ MakeBootRec(Disk, pInfo+entryCount, NULL, partition->Next,entryCount);
+ entryCount += ENTRIES_PER_BOOTSECTOR;
+ partition = partition->Next;
+ }
+ else
+ {
+#if 0
+ status = ZapSector(Disk, extendedStartingOffset);
+ if (status != OK_STATUS)
+ {
+ FreeMemory(driveLayout);
+ return status;
+ }
+#else
+ MakeBootRec(Disk, pInfo+entryCount, NULL, NULL,entryCount);
+ entryCount += ENTRIES_PER_BOOTSECTOR;
+#endif
+ }
+ }
+
+ while (NULL != partition)
+ {
+ if (partition->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ // find the next logical volume.
+
+ nextPartition = partition->Next;
+ while (NULL != nextPartition)
+ {
+ if (nextPartition->SysID != PARTITION_ENTRY_UNUSED)
+ {
+ break;
+ }
+ nextPartition = nextPartition->Next;
+ }
+
+ partitionHash[entryCount] = partition;
+ startingOffset = MakeBootRec(Disk, pInfo+entryCount, partition, nextPartition,entryCount);
+
+ // if we're creating a volume, clear out its filesystem
+ // boot sector so it starts out fresh.
+
+ if ((0 != startingOffset.QuadPart) && partition->Update &&
+ (partition->Update != CHANGED_DONT_ZAP))
+ {
+ status = ZapSector(Disk, startingOffset);
+ if (status != OK_STATUS)
+ {
+ FreeMemory(driveLayout);
+ return status;
+ }
+ }
+
+ entryCount += ENTRIES_PER_BOOTSECTOR;
+ }
+ partition = partition->Next;
+ }
+
+ driveLayout->PartitionCount = entryCount;
+ driveLayout->Signature = Signatures[Disk];
+ status = LowSetDiskLayout(DiskNames[Disk], driveLayout);
+
+ if (NT_SUCCESS(status))
+ {
+ // Update the partition numbers in the region structures.
+
+ // ReconcilePartitionNumbers(Disk, driveLayout);
+
+ for (entryCount = 0; entryCount < MAX_DISKS; entryCount++)
+ {
+ if (NULL != (partition = partitionHash[entryCount]))
+ {
+ if (partition->Update)
+ {
+ pInfo = &driveLayout->PartitionEntry[entryCount];
+ partition->PartitionNumber = pInfo->PartitionNumber;
+ }
+ }
+ }
+ }
+
+ FreeMemory(driveLayout);
+ return status;
+}
+
+
+STATUS_CODE
+CommitPartitionChanges(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the entry point for updating the on-disk partition
+ structures of a disk. The disk is only written to if the partition
+ structure has been changed by adding or deleting partitions.
+
+Arguments:
+
+ Disk - index of disk whose on-disk partition structure is to be updated.
+
+Return Value:
+
+ OK_STATUS or error code.
+
+--*/
+
+{
+ PPARTITION p;
+ STATUS_CODE status;
+
+ FDASSERT(!OffLine[Disk]);
+
+ if (!HavePartitionsBeenChanged(Disk))
+ {
+ return OK_STATUS;
+ }
+
+ if ((status = WriteDriveLayout(Disk)) != OK_STATUS)
+ {
+ return status;
+ }
+
+ // BUGBUG for ARC and NT MIPS, update NVRAM vars so partitions are right.
+ // Do that here, before partition numbers are reassigned.
+
+ p = PrimaryPartitions[Disk];
+ while (NULL != p)
+ {
+ p->Update = FALSE;
+ p->OriginalPartitionNumber = p->PartitionNumber;
+ p = p->Next;
+ }
+ p = LogicalVolumes[Disk];
+ while (NULL != p)
+ {
+ p->Update = FALSE;
+ p->OriginalPartitionNumber = p->PartitionNumber;
+ p = p->Next;
+ }
+
+ ChangesRequested[Disk] = FALSE;
+ ChangesCommitted[Disk] = TRUE;
+ return OK_STATUS;
+}
+
+
+BOOLEAN
+IsRegionCommitted(
+ PREGION_DESCRIPTOR RegionDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ Given a region descriptor, return TRUE if it actually exists on disk,
+ FALSE otherwise.
+
+Arguments:
+
+ RegionDescriptor - the region to check
+
+Return Value:
+
+ TRUE - if the region actually exists on disk
+ FALSE otherwise.
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData;
+
+ regionData = PERSISTENT_DATA(RegionDescriptor);
+ return (NULL == regionData) ? NULL : !regionData->NewRegion;
+}
+
+
+BOOLEAN
+HavePartitionsBeenChanged(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns TRUE if the given disk's partition structures
+ have been modified by adding or deleting partitions, since the
+ on-disk structures were last written by a call to CommitPartitionChanges
+ (or first read).
+
+Arguments:
+
+ Disk - index of disk to check
+
+Return Value:
+
+ true if Disk's partition structure has changed.
+
+--*/
+
+{
+ return ChangesRequested[Disk];
+}
+
+BOOLEAN
+ChangeCommittedOnDisk(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will inform the caller if a change was actually committed
+ to the disk given.
+
+Arguments:
+
+ Disk - index of disk to check
+
+Return Value:
+
+ TRUE if disk was changed
+ FALSE otherwise.
+
+--*/
+
+{
+ return ChangesCommitted[Disk];
+}
+
+
+VOID
+ClearCommittedDiskInformation(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Clear all knowledge about any changes that have occurred to the
+ disks.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG i;
+
+ for (i=0; i<CountOfDisks; i++)
+ {
+ ChangesCommitted[i] = FALSE;
+ }
+}
+
+
+VOID
+FdMarkDiskDirty(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ Remember that this disk has had some partitioning changes.
+
+Arguments:
+
+ Disk - the disk number
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ChangesRequested[Disk] = TRUE;
+}
+
+
+VOID
+FdSetPersistentData(
+ IN PREGION_DESCRIPTOR Region,
+ IN PPERSISTENT_REGION_DATA Data
+ )
+
+/*++
+
+Routine Description:
+
+ Set the persistent data area for the specified region.
+
+Arguments:
+
+ Region - the region for which the persistent data is to be set
+ Data - the persistent data for the region.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ Region->Reserved->Partition->PersistentData = Data;
+}
+
+
+ULONG
+FdGetMinimumSizeMB(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ Return the minimum size for a partition on a given disk.
+
+ This is the rounded size of one cylinder or 1, whichever is greater.
+
+Arguments:
+
+ Region - region describing the partition to check.
+
+Return Value:
+
+ Actual offset
+
+--*/
+
+{
+ LARGE_INTEGER temp;
+
+ temp.QuadPart = DiskGeometryArray[Disk].BytesPerCylinder;
+ return max(SIZEMB(temp), 1);
+}
+
+
+ULONG
+FdGetMaximumSizeMB(
+ IN PREGION_DESCRIPTOR Region,
+ IN REGION_TYPE CreationType
+ )
+
+/*++
+
+Routine Description:
+
+ Given a region of disk determine how much of it may be used to
+ create the specified partition type. This code take into consideration
+ the many alignment restrictions imposed by early DOS software versions.
+
+Arguments:
+
+ Region - The affected region
+ CreationType - What is being created
+ (extended partition/primary partition)
+
+Return Value:
+
+ The maximum size that a partition of the specified type can be
+ to fit within the space available in the region.
+
+--*/
+
+{
+ PREGION_DATA createData = Region->Reserved;
+ LARGE_INTEGER maxSize;
+
+ maxSize.QuadPart = createData->AlignedRegionSize.QuadPart;
+
+ if (0 == createData->AlignedRegionOffset.QuadPart)
+ {
+ ULONG delta;
+
+ delta = (CreationType == REGION_EXTENDED)
+ ? DiskGeometryArray[Region->Disk].BytesPerCylinder
+ : DiskGeometryArray[Region->Disk].BytesPerTrack;
+
+ maxSize.QuadPart -= delta;
+ }
+
+ return SIZEMB(maxSize);
+}
+
+
+LARGE_INTEGER
+FdGetExactSize(
+ IN PREGION_DESCRIPTOR Region,
+ IN BOOLEAN ForExtended
+ )
+{
+ PREGION_DATA regionData = Region->Reserved;
+ LARGE_INTEGER largeSize = regionData->AlignedRegionSize;
+ LARGE_INTEGER bytesPerTrack;
+ LARGE_INTEGER bytesPerCylinder;
+
+ bytesPerTrack.QuadPart = DiskGeometryArray[Region->Disk].BytesPerTrack;
+ bytesPerCylinder.QuadPart = DiskGeometryArray[Region->Disk].BytesPerCylinder;
+
+ if (Region->RegionType == REGION_LOGICAL)
+ {
+ //
+ // The region is within the extended partition. It doesn't matter
+ // whether it's free space or used -- in either case, we need to
+ // account for the reserved EBR track.
+ //
+
+ largeSize.QuadPart -= bytesPerTrack.QuadPart;
+ }
+ else if (Region->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ //
+ // The region is unused space not inside the extended partition.
+ // We must know whether the caller will put a primary or extended
+ // partition there -- a primary partition can use all the space, but
+ // a logical volume in the extended partition won't include the first
+ // track. If the free space starts at offset 0 on the disk, a special
+ // calculation must be used to move the start of the partition to
+ // skip a track for a primary or a cylinder and a track for an
+ // extended+logical.
+ //
+
+ if ((0 == regionData->AlignedRegionOffset.QuadPart) || ForExtended)
+ {
+ largeSize.QuadPart -= bytesPerTrack.QuadPart;
+ }
+
+ if ((0 == regionData->AlignedRegionOffset.QuadPart) && ForExtended)
+ {
+ largeSize.QuadPart -= bytesPerCylinder.QuadPart;
+ }
+ }
+
+ return largeSize;
+}
+
+
+LARGE_INTEGER
+FdGetExactOffset(
+ IN PREGION_DESCRIPTOR Region
+ )
+
+/*++
+
+Routine Description:
+
+ Determine where a given partition _actually_ starts, which may be
+ different than where is appears because of EBR reserved tracks, etc.
+
+ NOTE: This routine is not meant to operate on unused regions or
+ extended partitions. In these cases, it just returns the apparant offset.
+
+Arguments:
+
+ Region - region describing the partition to check.
+
+Return Value:
+
+ Actual offset
+
+--*/
+
+{
+ LARGE_INTEGER offset = ((PREGION_DATA)(Region->Reserved))->Partition->Offset;
+
+ if ((Region->SysID != PARTITION_ENTRY_UNUSED) && (Region->RegionType == REGION_LOGICAL))
+ {
+ //
+ // The region is a logical volume.
+ // Account for the reserved EBR track.
+ //
+
+ offset.QuadPart += DiskGeometryArray[Region->Disk].BytesPerTrack;
+ }
+
+ return offset;
+}
+
+
+BOOLEAN
+FdCrosses1024Cylinder(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE RegionType
+ )
+
+/*++
+
+Routine Description:
+
+ Determine whether a used region corsses the 1024th cylinder, or whether
+ a partition created within a free space will cross the 1024th cylinder.
+
+Arguments:
+
+ Region - region describing the partition to check.
+
+ CreationSizeMB - if the Region is for a free space, this is the size of
+ the partition to be checked.
+
+ RegionType - one of REGION_PRIMARY, REGION_EXTENDED, or REGION_LOGICAL
+
+Return Value:
+
+ TRUE if the end cylinder >= 1024.
+
+--*/
+
+{
+ LARGE_INTEGER start, size, end, zero;
+
+ if (Region->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ //
+ // Determine the exact size and offset of the partition, according
+ // to how CreatePartitionEx() will do it.
+ //
+
+ zero.QuadPart = 0;
+ DetermineCreateSizeAndOffset(Region,
+ zero,
+ CreationSizeMB,
+ RegionType,
+ &start,
+ &size);
+ }
+ else
+ {
+ start = ((PREGION_DATA)(Region->Reserved))->Partition->Offset;
+ size = ((PREGION_DATA)(Region->Reserved))->Partition->Length;
+ }
+
+ end.QuadPart = (start.QuadPart + size.QuadPart) - 1;
+
+ //
+ // end is the last byte in the partition. Divide by the number of
+ // bytes in a cylinder and see whether the result is > 1023.
+ //
+
+ end.QuadPart = end.QuadPart / DiskGeometryArray[Region->Disk].BytesPerCylinder;
+ return (end.QuadPart > 1023);
+}
+
+
+BOOLEAN
+IsDiskOffLine(
+ IN ULONG Disk
+ )
+{
+ return OffLine[Disk];
+}
+
+ULONG
+FdGetDiskSignature(
+ IN ULONG Disk
+ )
+{
+ return Signatures[Disk];
+}
+
+VOID
+FdSetDiskSignature(
+ IN ULONG Disk,
+ IN ULONG Signature
+ )
+{
+ Signatures[Disk] = Signature;
+}
+
+
+BOOLEAN
+SignatureIsUniqueToSystem(
+ IN ULONG Disk,
+ IN ULONG Signature
+ )
+{
+ ULONG index;
+
+ for (index = 0; index < Disk; index++)
+ {
+ if (Signatures[index] == Signature)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
diff --git a/private/utils/windisk/src/engine.hxx b/private/utils/windisk/src/engine.hxx
new file mode 100644
index 000000000..e44a2e351
--- /dev/null
+++ b/private/utils/windisk/src/engine.hxx
@@ -0,0 +1,311 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: engine.hxx
+//
+// Contents: Partitioning engine declarations
+//
+// History: 2-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ENGINE_HXX__
+#define __ENGINE_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+ULONG
+GetDiskCount(
+ VOID
+ );
+
+PCHAR
+GetDiskName(
+ ULONG Disk
+ );
+
+ULONG
+DiskSizeMB(
+ IN ULONG Disk
+ );
+
+STATUS_CODE
+GetDiskRegions(
+ IN ULONG Disk,
+ IN BOOLEAN WantUsedRegions,
+ IN BOOLEAN WantFreeRegions,
+ IN BOOLEAN WantPrimaryRegions,
+ IN BOOLEAN WantLogicalRegions,
+ OUT PREGION_DESCRIPTOR* Region,
+ OUT PULONG RegionCount
+ );
+
+#define GetAllDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,TRUE,TRUE,TRUE,regions,count)
+
+#define GetFreeDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,FALSE,TRUE,TRUE,TRUE,regions,count)
+
+#define GetUsedDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,FALSE,TRUE,TRUE,regions,count)
+
+#define GetPrimaryDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,TRUE,TRUE,FALSE,regions,count)
+
+#define GetLogicalDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,TRUE,FALSE,TRUE,regions,count)
+
+#define GetUsedPrimaryDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,FALSE,TRUE,FALSE,regions,count)
+
+#define GetUsedLogicalDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,TRUE,FALSE,FALSE,TRUE,regions,count)
+
+#define GetFreePrimaryDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,FALSE,TRUE,TRUE,FALSE,regions,count)
+
+#define GetFreeLogicalDiskRegions(disk,regions,count) \
+ GetDiskRegions(disk,FALSE,TRUE,FALSE,TRUE,regions,count)
+
+VOID
+FreeRegionArray(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG RegionCount
+ );
+
+STATUS_CODE
+IsAnyCreationAllowed(
+ IN ULONG Disk,
+ IN BOOLEAN AllowMultiplePrimaries,
+ OUT PBOOLEAN AnyAllowed,
+ OUT PBOOLEAN PrimaryAllowed,
+ OUT PBOOLEAN ExtendedAllowed,
+ OUT PBOOLEAN LogicalAllowed
+ );
+
+STATUS_CODE
+IsCreationOfPrimaryAllowed(
+ IN ULONG Disk,
+ IN BOOLEAN AllowMultiplePrimaries,
+ OUT PBOOLEAN Allowed
+ );
+
+STATUS_CODE
+IsCreationOfExtendedAllowed(
+ IN ULONG Disk,
+ OUT PBOOLEAN Allowed
+ );
+
+STATUS_CODE
+IsCreationOfLogicalAllowed(
+ IN ULONG Disk,
+ OUT PBOOLEAN Allowed
+ );
+
+STATUS_CODE
+DoesAnyPartitionExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN AnyExists,
+ OUT PBOOLEAN PrimaryExists,
+ OUT PBOOLEAN ExtendedExists,
+ OUT PBOOLEAN LogicalExists
+ );
+
+STATUS_CODE
+DoesAnyPrimaryExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ );
+
+STATUS_CODE
+DoesExtendedExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ );
+
+STATUS_CODE
+DoesAnyLogicalExist(
+ IN ULONG Disk,
+ OUT PBOOLEAN Exists
+ );
+
+BOOLEAN
+IsExtended(
+ IN UCHAR SysID
+ );
+
+VOID
+SetPartitionActiveFlag(
+ IN PREGION_DESCRIPTOR Region,
+ IN UCHAR value
+ );
+
+STATUS_CODE
+CreatePartition(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE Type
+ );
+
+STATUS_CODE
+CreatePartitionEx(
+ IN PREGION_DESCRIPTOR Region,
+ IN LARGE_INTEGER MinimumSize,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE Type,
+ IN UCHAR SysId
+ );
+
+STATUS_CODE
+DeletePartition(
+ IN PREGION_DESCRIPTOR Region
+ );
+
+ULONG
+GetHiddenSectorCount(
+ ULONG Disk,
+ ULONG Partition
+ );
+
+VOID
+SetSysID(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ IN UCHAR SysID
+ );
+
+VOID
+SetSysID2(
+ IN PREGION_DESCRIPTOR Region,
+ IN UCHAR SysID
+ );
+
+PCHAR
+GetSysIDName(
+ UCHAR SysID
+ );
+
+STATUS_CODE
+CommitPartitionChanges(
+ IN ULONG Disk
+ );
+
+BOOLEAN
+IsRegionCommitted(
+ PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+BOOLEAN
+HavePartitionsBeenChanged(
+ IN ULONG Disk
+ );
+
+BOOLEAN
+ChangeCommittedOnDisk(
+ IN ULONG Disk
+ );
+
+VOID
+ClearCommittedDiskInformation(
+ VOID
+ );
+
+VOID
+FdMarkDiskDirty(
+ IN ULONG Disk
+ );
+
+VOID
+FdSetPersistentData(
+ IN PREGION_DESCRIPTOR Region,
+ IN PPERSISTENT_REGION_DATA Data
+ );
+
+ULONG
+FdGetMinimumSizeMB(
+ IN ULONG Disk
+ );
+
+ULONG
+FdGetMaximumSizeMB(
+ IN PREGION_DESCRIPTOR Region,
+ IN REGION_TYPE CreationType
+ );
+
+LARGE_INTEGER
+FdGetExactSize(
+ IN PREGION_DESCRIPTOR Region,
+ IN BOOLEAN ForExtended
+ );
+
+LARGE_INTEGER
+FdGetExactOffset(
+ IN PREGION_DESCRIPTOR Region
+ );
+
+BOOLEAN
+FdCrosses1024Cylinder(
+ IN PREGION_DESCRIPTOR Region,
+ IN ULONG CreationSizeMB,
+ IN REGION_TYPE RegionType
+ );
+
+ULONG
+FdGetDiskSignature(
+ IN ULONG Disk
+ );
+
+VOID
+FdSetDiskSignature(
+ IN ULONG Disk,
+ IN ULONG Signature
+ );
+
+BOOLEAN
+IsDiskOffLine(
+ IN ULONG Disk
+ );
+
+
+STATUS_CODE
+FdiskInitialize(
+ VOID
+ );
+
+VOID
+FdiskCleanUp(
+ VOID
+ );
+
+VOID
+ConfigureSystemPartitions(
+ VOID
+ );
+
+
+VOID
+ConfigureOSPartitions(
+ VOID
+ );
+
+BOOLEAN
+SignatureIsUniqueToSystem(
+ IN ULONG Disk,
+ IN ULONG Signature
+ );
+
+//
+// Items below used to be in fdenginp.h -- have been moved here to
+// remove dependency on ArcInst project.
+//
+
+#define ONE_MEG (1024*1024)
+
+ULONG
+SIZEMB(
+ IN LARGE_INTEGER ByteCount
+ );
+
+#endif // __ENGINE_HXX__
diff --git a/private/utils/windisk/src/extend.cxx b/private/utils/windisk/src/extend.cxx
new file mode 100644
index 000000000..036ebe2fc
--- /dev/null
+++ b/private/utils/windisk/src/extend.cxx
@@ -0,0 +1,636 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: extend.cxx
+//
+// Contents: Code to handle disk and volume extensions in windisk
+//
+// History: 28-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#ifdef WINDISK_EXTENSIONS
+
+// #include <guids.h>
+
+#include "extend.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+ExtensionType Extensions[EX_NUM_EXTENSION_TYPES];
+
+VOLUME_INFO VolumeInfo[24] = { 0 }; // 24 drive letters: no A or B
+
+HARDDISK_INFO* HardDiskExtensions;
+INT cHardDiskExtensions;
+
+VOL_CLAIM_LIST* VolClaims;
+VOL_INFO* VolExtensions;
+INT cVolExtensions;
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetNewObj
+//
+// Synopsis: Creates and initializes a new object of the specified class
+//
+// Arguments: [clsid] -- the class ID of the object to initialize
+// [ppUnk] -- returned IUnknown pointer to the object
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 6-Jun-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+GetNewObj(
+ IN CLSID clsid,
+ OUT IUnknown** ppUnk
+ )
+{
+#if DBG == 1
+ daDebugOut((DEB_ITRACE,"GetNewObj, clsid = "));
+ DumpGuid(DEB_ITRACE|DEB_NOCOMPNAME, L"", clsid);
+#endif // DBG == 1
+
+ IUnknown* pUnk = NULL;
+
+ HRESULT hr = CoCreateInstance(
+ clsid,
+ NULL,
+ CLSCTX_ALL,
+ (REFIID)IID_IUnknown,
+ (void**)&pUnk);
+ if (SUCCEEDED(hr))
+ {
+ *ppUnk = pUnk;
+ return TRUE;
+ }
+ else
+ {
+ *ppUnk = NULL;
+ return FALSE;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// BUGBUG: for now, all the enumerations are hard-coded
+//
+
+
+CLSID* HardDiskClasses[] =
+{
+// (CLSID*)&CLSID_KDA_SCSI //BUGBUG
+ (CLSID*)&CLSID_KDA_Hard
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EnumVolumeClasses, public
+//
+// Synopsis: Enumerates the set of Disk Administrator Volume
+// extension classes available.
+//
+// Arguments: [pExtension] -- where to put the extension list
+//
+// Returns: TRUE if succeeded, FALSE if failed
+//
+// History: 19-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+EnumVolumeClasses(
+ OUT ExtensionType* pExtension
+ )
+{
+ pExtension->pcls = NULL;
+ pExtension->cClasses = 0; //BUGBUG
+ return TRUE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EnumHardDiskClasses, public
+//
+// Synopsis: Enumerates the set of Disk Administrator Hard Disk
+// extension classes available.
+//
+// Arguments: [pExtension] -- where to put the extension list
+//
+// Returns: TRUE if succeeded, FALSE if failed
+//
+// History: 19-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+EnumHardDiskClasses(
+ OUT ExtensionType* pExtension
+ )
+{
+ pExtension->pcls = HardDiskClasses;
+ pExtension->cClasses = ARRAYLEN(HardDiskClasses);
+
+ return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateVolume
+//
+// Synopsis: Set the volume information for a volume
+//
+// Arguments: [DriveLetter] -- drive letter of volume
+// [VolClaims] -- the volume claimers
+// [DiskState] -- the disk state the volume resides on
+// [RegionIndex] -- the region index of the volume
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CreateVolume(
+ IN WCHAR DriveLetter,
+ IN PVOL_CLAIM_LIST VolClaims,
+ IN PDISKSTATE DiskState,
+ IN INT RegionIndex
+ )
+{
+ unsigned i = (unsigned)DriveLetterToIndex(DriveLetter);
+
+ VolumeInfo[i].VolClaims = VolClaims;
+ VolumeInfo[i].DiskState = DiskState;
+ VolumeInfo[i].RegionIndex = RegionIndex;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClaimVolume
+//
+// Synopsis: Find all the claimers of a volume
+//
+// Arguments: [DriveLetter] -- drive letter of the volume in question
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ClaimVolume(
+ IN WCHAR DriveLetter
+ )
+{
+ PDISKSTATE diskState;
+ INT regionIndex;
+ INT i;
+
+ VolClaims = NULL;
+
+ GetInfoFromDriveLetter(DriveLetter, &diskState, &regionIndex);
+
+ if (NULL != diskState)
+ {
+ for (i=0; i<cVolExtensions; i++)
+ {
+ if (NULL != VolExtensions[i].pExtension)
+ {
+ //
+ // Now, test if extension #i is used on the volume identified
+ // by DriveLetter
+ //
+
+ BOOL fInterested = FALSE;
+ VolumeInfoBlockType vi = { DriveLetter };
+
+ VolExtensions[i].pExtension->Claim(
+ &vi,
+ &fInterested
+ );
+
+ if (fInterested)
+ {
+ daDebugOut((DEB_TRACE,
+ "Adding %ws to extensions for %wc:\n",
+ VolExtensions[i].pInfo->pwszShortName,
+ DriveLetter
+ ));
+
+ //
+ // add this extension to the claim list
+ //
+ PVOL_CLAIM_LIST tmp = VolClaims;
+ VolClaims = (VOL_CLAIM_LIST*)Malloc(sizeof(VOL_CLAIM_LIST));
+ VolClaims->pNext = tmp;
+ VolClaims->pClaimer = &VolExtensions[i];
+ }
+ }
+ }
+ }
+
+ CreateVolume(DriveLetter, VolClaims, diskState, regionIndex);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClaimDisk
+//
+// Synopsis: Find all the claimers of a disk
+//
+// Arguments: [DiskNum] -- disk number of disk in question
+//
+// Returns: nothing
+//
+// History: 7-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ClaimDisk(
+ IN ULONG DiskNum
+ )
+{
+ PHARDDISK_CLAIM_LIST* ppClaims = &DiskArray[DiskNum]->pClaims;
+
+ *ppClaims = NULL;
+
+ for (INT i=0; i<cHardDiskExtensions; i++)
+ {
+ if (NULL != HardDiskExtensions[i].pExtension)
+ {
+ //
+ // Now, test if extension #i is used on the disk identified
+ // by DiskNum
+ //
+
+ BOOL fInterested = FALSE;
+ HardDiskInfoBlockType di = { DiskNum };
+
+ HardDiskExtensions[i].pExtension->Claim(
+ &di,
+ &fInterested
+ );
+
+ if (fInterested)
+ {
+ daDebugOut((DEB_TRACE,
+ "Adding %ws to extensions for disk %d\n",
+ HardDiskExtensions[i].pInfo->pwszShortName,
+ DiskNum
+ ));
+
+ //
+ // add this extension to the claim list
+ //
+
+ PHARDDISK_CLAIM_LIST NewClaim;
+ NewClaim = (PHARDDISK_CLAIM_LIST)Malloc(sizeof(HARDDISK_CLAIM_LIST));
+ NewClaim->pNext = *ppClaims;
+ NewClaim->pClaimer = &HardDiskExtensions[i];
+ *ppClaims = NewClaim;
+ }
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetExtensions
+//
+// Synopsis: Finds and activates all extensions and claims all significant
+// volumes
+//
+// Arguments: (none)
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+GetExtensions(
+ VOID
+ )
+{
+ BOOL f;
+ HRESULT hr;
+
+ f = EnumVolumeClasses(&Extensions[EX_VOLUME]);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,
+ "Failed to enumerate volume extension classes\n"));
+ return f;
+ }
+
+ f = EnumHardDiskClasses(&Extensions[EX_DISK]);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR,
+ "Failed to enumerate hard disk extension classes\n"));
+ return f;
+ }
+
+ //
+ // At this point, all the extension classes have been found. Call
+ // the Claim() functions to determine who wants to deal with what
+ // volumes/disks/etc. This involves activating all the extension
+ // classes.
+ //
+
+ daDebugOut((DEB_TRACE, "Extensions loaded\n"));
+
+ IUnknown* pUnk;
+ int i;
+
+ //
+ // Activate volume extensions
+ //
+
+ cVolExtensions = Extensions[EX_VOLUME].cClasses;
+ VolExtensions = (VOL_INFO*)Malloc(cVolExtensions * sizeof(VOL_INFO));
+
+ for (i=0; i<cVolExtensions; i++)
+ {
+ f = GetNewObj(*(Extensions[EX_VOLUME].pcls[i]), &pUnk);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR, "GetNewObj failed on volume extension #%d\n", i));
+ VolExtensions[i].pExtension = NULL;
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE, "Activated volume extension #%d\n", i));
+
+ hr = pUnk->QueryInterface(
+ IID_IDAVolumeInfo,
+ (void**)(&VolExtensions[i].pExtension)
+ );
+ pUnk->Release();
+
+ if (FAILED(hr))
+ {
+ daDebugOut((DEB_ERROR, "QueryInterface failed on #%d\n", i));
+ VolExtensions[i].pExtension = NULL;
+ }
+ else
+ {
+ hr = VolExtensions[i].pExtension->QueryInfo(&VolExtensions[i].pInfo);
+ if (FAILED(hr))
+ {
+ VolExtensions[i].pExtension->Release();
+ VolExtensions[i].pExtension = NULL;
+ }
+ }
+ }
+ }
+
+ //
+ // Activate hard disk extensions
+ //
+
+ cHardDiskExtensions = Extensions[EX_DISK].cClasses;
+ HardDiskExtensions = (HARDDISK_INFO*)Malloc(cHardDiskExtensions * sizeof(HARDDISK_INFO));
+
+ for (i=0; i<cHardDiskExtensions; i++)
+ {
+ f = GetNewObj(*(Extensions[EX_DISK].pcls[i]), &pUnk);
+ if (!f)
+ {
+ daDebugOut((DEB_ERROR, "GetNewObj failed on hard disk extension #%d\n", i));
+ HardDiskExtensions[i].pExtension = NULL;
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE, "Activated Hard Disk extension #%d\n", i));
+
+ hr = pUnk->QueryInterface(
+ IID_IDAHardDiskInfo,
+ (void**)(&HardDiskExtensions[i].pExtension)
+ );
+ pUnk->Release();
+
+ if (FAILED(hr))
+ {
+ daDebugOut((DEB_ERROR, "QueryInterface failed on #%d\n", i));
+ HardDiskExtensions[i].pExtension = NULL;
+ }
+ else
+ {
+ hr = HardDiskExtensions[i].pExtension->QueryInfo(&HardDiskExtensions[i].pInfo);
+ if (FAILED(hr))
+ {
+ HardDiskExtensions[i].pExtension->Release();
+ HardDiskExtensions[i].pExtension = NULL;
+ }
+ }
+ }
+ }
+
+ daDebugOut((DEB_TRACE, "Extensions activated\n"));
+
+ //
+ // With all the extensions activated, perform claiming:
+ //
+ // Extension Item claimed
+ // --------- ------------
+ // file system formatted volume
+ // volume any pre-existing volume
+ // hard disk hard disk
+ //
+ // Note that no extension claims free space.
+ //
+
+ WCHAR driveLetter;
+
+ // for each pre-existing, formatted volume...
+
+ for (driveLetter = L'C'; driveLetter <= L'Z'; driveLetter++)
+ {
+ ClaimVolume(driveLetter);
+ }
+
+ // do hard disk claiming
+
+ for (ULONG DiskNum = 0; DiskNum<DiskCount; DiskNum++)
+ {
+ ClaimDisk(DiskNum);
+ }
+
+#if DBG == 1
+ PrintClaims();
+#endif // DBG == 1
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DeactivateExtensions
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 28-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DeactivateExtensions(
+ VOID
+ )
+{
+ INT i;
+
+ //
+ // Deactivate volume extensions
+ //
+
+ for (i=0; i<cVolExtensions; i++)
+ {
+ if (NULL != VolExtensions[i].pExtension)
+ {
+ daDebugOut((DEB_TRACE,
+ "Releasing %ws\n",
+ VolExtensions[i].pInfo->pwszShortName
+ ));
+
+ ULONG cRefs = VolExtensions[i].pExtension->Release();
+
+ daDebugOut((DEB_TRACE, " ... had %s references\n",
+ cRefs > 0 ? ">0" : (cRefs < 0 ? "<0" : "0")
+ ));
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE, "Extension %d didn't exist\n", i));
+ }
+
+ // BUGBUG: MemFree VolExtensions[i].pInfo
+ }
+
+ Free(VolExtensions);
+
+ //
+ // Activate hard disk extensions
+ //
+
+ for (i=0; i<cHardDiskExtensions; i++)
+ {
+ if (NULL != HardDiskExtensions[i].pExtension)
+ {
+ daDebugOut((DEB_TRACE,
+ "Releasing %ws\n",
+ HardDiskExtensions[i].pInfo->pwszShortName
+ ));
+
+ ULONG cRefs = HardDiskExtensions[i].pExtension->Release();
+
+ daDebugOut((DEB_TRACE, " ... had %s references\n",
+ cRefs > 0 ? ">0" : (cRefs < 0 ? "<0" : "0")
+ ));
+ }
+ else
+ {
+ daDebugOut((DEB_TRACE, "Extension %d didn't exist\n", i));
+ }
+
+ // BUGBUG MemFree HardDiskExtensions[i].pInfo
+ }
+
+ Free(HardDiskExtensions);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddExtensionItemsToMenu
+//
+// Synopsis: Adds an extension menu item to both the menu bar and the
+// given context menu.
+//
+// Arguments: [hmenuBar] -- menu bar menu to add item to
+// [pMenu] -- pointer to extension menu item
+// [fFlags] -- standard menu flags (probably
+// MF_ENABLED or MF_GRAYED)
+//
+// Modifies: g_uItemInsertHere
+//
+// Returns: count of items added
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+AddExtensionItemsToMenu(
+ IN HMENU hmenuBar,
+ IN MenuType* pMenu,
+ IN BOOL fFlags
+ )
+{
+ for (int i=0; i<pMenu->cMenuItems; i++)
+ {
+ MenuItemType* pItem = &(pMenu->aMenuItems[i]);
+
+ UINT id = MenuItems.AllocateId(pItem); //get an ID
+
+ if ((UINT)-1 == id)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't add '%ws' to menu\n",
+ pItem->pszMenu
+ ));
+ }
+ else
+ {
+ InsertMenu(
+ hmenuBar,
+ g_uItemInsertHere++,
+ MF_BYPOSITION | MF_STRING | fFlags,
+ id,
+ pItem->pszMenu
+ );
+ }
+ }
+
+ return pMenu->cMenuItems;
+}
+
+
+#endif // WINDISK_EXTENSIONS
diff --git a/private/utils/windisk/src/extend.hxx b/private/utils/windisk/src/extend.hxx
new file mode 100644
index 000000000..6d944d384
--- /dev/null
+++ b/private/utils/windisk/src/extend.hxx
@@ -0,0 +1,87 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: extend.hxx
+//
+// Contents: Code to handle disk and volume extensions in windisk
+//
+// History: 28-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __EXTEND_HXX__
+#define __EXTEND_HXX__
+
+#ifdef WINDISK_EXTENSIONS
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern ExtensionType Extensions[];
+
+extern VOLUME_INFO VolumeInfo[];
+
+extern HARDDISK_INFO* HardDiskExtensions;
+extern INT cHardDiskExtensions;
+
+extern VOL_CLAIM_LIST* VolClaims;
+extern VOL_INFO* VolExtensions;
+extern INT cVolExtensions;
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+GetNewObj(
+ IN CLSID clsid,
+ OUT IUnknown** ppUnk
+ );
+
+BOOL
+EnumVolumeClasses(
+ OUT ExtensionType* pExtension
+ );
+
+BOOL
+EnumHardDiskClasses(
+ OUT ExtensionType* pExtension
+ );
+
+VOID
+CreateVolume(
+ IN WCHAR DriveLetter,
+ IN PVOL_CLAIM_LIST VolClaims,
+ IN PDISKSTATE DiskState,
+ IN INT RegionIndex
+ );
+
+VOID
+ClaimVolume(
+ IN WCHAR DriveLetter
+ );
+
+VOID
+ClaimDisk(
+ IN ULONG DiskNum
+ );
+
+BOOL
+GetExtensions(
+ VOID
+ );
+
+VOID
+DeactivateExtensions(
+ VOID
+ );
+
+INT
+AddExtensionItemsToMenu(
+ IN HMENU hmenuBar,
+ IN MenuType* pMenu,
+ IN BOOL fFlags
+ );
+
+#endif // WINDISK_EXTENSIONS
+
+#endif // __EXTEND_HXX__
diff --git a/private/utils/windisk/src/fill.cxx b/private/utils/windisk/src/fill.cxx
new file mode 100644
index 000000000..42c19f91a
--- /dev/null
+++ b/private/utils/windisk/src/fill.cxx
@@ -0,0 +1,867 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fill.cxx
+//
+// Contents: Routines to fill the volumes view with data from the Disk
+// Administrator internal state.
+//
+// History: 20-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "dispinfo.hxx"
+#include "drives.hxx"
+#include "fill.hxx"
+#include "select.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern int IconIndexSmall[];
+
+// indices into Icon* arrays
+
+#define I_HARD 0
+#define I_CDROM 1
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+-------------------------------------------------------------------------
+//
+// Function: AddVolumeToListview, public
+//
+// Synopsis: Add a region to the listview
+//
+// Arguments:
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+AddVolumeToListview(
+ IN int item,
+ IN WCHAR DriveLetter
+ )
+{
+ //
+ // First, get all the data into the CDispInfo class. If any of this fails,
+ // then ignore the item. After that, then do the listview insertions.
+ //
+
+ CDispInfo* pDispInfo = new CDispInfo();
+ if (NULL == pDispInfo)
+ {
+ return; //BUGBUG: out of memory
+ }
+
+ UINT wId; // resource ID to load & use
+ INT columnIndex;
+ PWSTR pszTemp;
+ WCHAR wszTemp[MAX_LV_ITEM_LEN];
+ DWORD capacityInMB;
+ DWORD overheadInMB;
+ PWSTR volumeLabel;
+ PWSTR typeName;
+ WCHAR driveLetterW;
+
+ BOOL spaceInfoOK = TRUE; // assume no trouble getting data
+ BOOL capacityOK = TRUE;
+
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+
+ WCHAR mbBuffer[16];
+ WCHAR unavailableDataBuffer[16];
+
+ WCHAR freeSpaceInMBString[30];
+ ULONG percentageFree = 0L;
+
+ //
+ // Before setting any columns, get all the data
+ //
+
+ //
+ // Load resource strings:
+ // unavailableDataBuffer -- ?
+ // mbBuffer -- MB
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_UNAVAILABLE_DATA,
+ unavailableDataBuffer,
+ ARRAYLEN(unavailableDataBuffer)
+ );
+
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer)
+ );
+
+ //
+ // Get data
+ //
+
+ regionDescriptor = RegionFromDriveLetter(DriveLetter);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+
+ //
+ // Get the file system type name and volume label from persistent data
+ //
+
+ DetermineRegionInfo(
+ regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetterW // just get it again...
+ );
+
+ //
+ // Calculate capacity and fault tolerance overhead
+ //
+
+ // For non-new volumes, use the TotalSpaceInBytes field from
+ // persistent region data?
+
+ if (ftObject)
+ {
+ //
+ // This volume is part of an FT set
+ //
+
+ PFT_OBJECT ftObj;
+ overheadInMB = capacityInMB = 0;
+
+ ftSet = ftObject->Set;
+
+ for (ftObj = ftSet->Members; NULL != ftObj; ftObj = ftObj->Next)
+ {
+ PREGION_DESCRIPTOR componentRegion = ftObj->Region;
+ if (NULL == componentRegion)
+ {
+ // An FT set has a missing component!
+
+ capacityInMB = 0;
+ capacityOK = FALSE;
+ break;
+ }
+
+ capacityInMB += componentRegion->SizeMB;
+ }
+
+ if (capacityOK)
+ {
+ switch (ftSet->Type)
+ {
+ case Mirror:
+ case StripeWithParity:
+ //
+ // Fault tolerant volumes use one region of the set for
+ // redundancy information
+ //
+ overheadInMB = regionDescriptor->SizeMB;
+ break;
+
+ default:
+ //
+ // Simple stripes and volume sets can use all the space
+ // they are given, for user data.
+ //
+ overheadInMB = 0;
+ break;
+ }
+ }
+
+ //
+ // subtract off the overhead from the total amount of space
+ // taken up by the volume; this is what the user gets back when
+ // doing a "dir" or "du" on the volume.
+ //
+
+ capacityInMB -= overheadInMB;
+ }
+ else
+ {
+ //
+ // A simple, non-FT volume
+ //
+
+ capacityInMB = regionDescriptor->SizeMB;
+ overheadInMB = 0;
+ }
+
+ //
+ // Calculate free space and percentage free
+ //
+
+ if (capacityOK && !regionData->NewRegion)
+ {
+ LARGE_INTEGER freeSpaceInMB;
+
+ freeSpaceInMB.QuadPart = regionData->FreeSpaceInBytes.QuadPart
+ / 1048576; // One MB
+
+ LargeIntegerToUnicodeChar(
+ &freeSpaceInMB,
+ 10,
+ ARRAYLEN(freeSpaceInMBString),
+ freeSpaceInMBString
+ );
+
+ if (0 == regionData->TotalSpaceInBytes.QuadPart)
+ {
+ // avoid divide by zero for volumes with no space data
+ percentageFree = 0;
+ }
+ else
+ {
+// percentageFree = 100 * FreeSpaceInBytes / TotalSpaceInBytes;
+
+ percentageFree = (ULONG)(regionData->FreeSpaceInBytes.QuadPart
+ * 100
+ / regionData->TotalSpaceInBytes.QuadPart);
+ }
+ }
+ else
+ {
+ //
+ // new regions don't have any free space info
+ //
+
+ spaceInfoOK = FALSE;
+ }
+
+ columnIndex = 0;
+
+ //
+ // column: drive letter
+ //
+
+ wsprintf(wszTemp, TEXT("%c:"), DriveLetter);
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: volume label
+ //
+
+ if (!pDispInfo->SetText(columnIndex++, volumeLabel))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: capacity in MB
+ //
+
+ if (capacityOK)
+ {
+ wsprintf(wszTemp, TEXT("%lu %s"), capacityInMB, mbBuffer);
+ }
+ else
+ {
+ wsprintf(wszTemp, unavailableDataBuffer);
+ }
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: free space in MB
+ //
+
+ if (spaceInfoOK)
+ {
+ wsprintf(wszTemp, TEXT("%s %s"), freeSpaceInMBString, mbBuffer);
+ }
+ else
+ {
+ LoadString(
+ g_hInstance,
+ IDS_UNKNOWNTYPE,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+ }
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: % free space
+ //
+
+ if (spaceInfoOK)
+ {
+ wsprintf(wszTemp, TEXT("%d %%"), percentageFree);
+
+ pszTemp = wszTemp;
+ }
+ else
+ {
+ pszTemp = unavailableDataBuffer;
+ }
+
+ if (!pDispInfo->SetText(columnIndex++, pszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: format (file system type)
+ //
+
+ if (!pDispInfo->SetText(columnIndex++, typeName))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: fault tolerant?
+ //
+
+ if (IsFaultTolerantRegion(regionDescriptor))
+ {
+ wId = IDS_FT_YES;
+ }
+ else
+ {
+ wId = IDS_FT_NO;
+ }
+
+ LoadString(
+ g_hInstance,
+ wId,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: volume type
+ //
+
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+
+ switch (ftObject ? ftObject->Set->Type : -1)
+ {
+ case Mirror:
+ wId = IDS_VOLTYPE_MIRROR;
+ break;
+
+ case Stripe:
+ wId = IDS_VOLTYPE_STRIPE;
+ break;
+
+ case StripeWithParity:
+ wId = IDS_VOLTYPE_PARITY;
+ break;
+
+ case VolumeSet:
+ wId = IDS_VOLTYPE_VOLSET;
+ break;
+
+ default:
+ wId = IDS_VOLTYPE_SIMPLE;
+ break;
+ }
+
+ LoadString(
+ g_hInstance,
+ wId,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: fault tolerance overhead in MB
+ //
+
+ if (capacityOK)
+ {
+ if (overheadInMB != 0)
+ {
+ wsprintf(
+ wszTemp,
+ TEXT("%lu %s (%lu%%)"),
+ overheadInMB,
+ mbBuffer,
+ (ULONG)(100 * overheadInMB / capacityInMB));
+ }
+ else
+ {
+ wsprintf(wszTemp, TEXT(""));
+ }
+ }
+ else
+ {
+ wsprintf(wszTemp, unavailableDataBuffer);
+ }
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: status
+ //
+
+ switch (ftObject ? ftSet->Status : -1)
+ {
+ case FtSetHealthy:
+ wId = IDS_FTSTATUS_HEALTHY;
+ break;
+
+ case FtSetNew:
+ case FtSetNewNeedsInitialization:
+ wId = IDS_FTSTATUS_NEW;
+ break;
+
+ case FtSetBroken:
+ wId = IDS_FTSTATUS_BROKEN;
+ break;
+
+ case FtSetRecoverable:
+ wId = IDS_FTSTATUS_RECOVERABLE;
+ break;
+
+ case FtSetRecovered:
+ wId = IDS_FTSTATUS_REGENERATED;
+ break;
+
+ case FtSetInitializing:
+ wId = IDS_FTSTATUS_INITIALIZING;
+ break;
+
+ case FtSetRegenerating:
+ wId = IDS_FTSTATUS_REGENERATING;
+ break;
+
+ default:
+ wId = IDS_FTSTATUS_NONE;
+ break;
+ }
+
+ LoadString(
+ g_hInstance,
+ wId,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // Insert the data into the listview
+ //
+
+ LV_ITEM lvi;
+ lvi.iItem = item;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.cchTextMax = 0; // ignored when setting data
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.iImage = IconIndexSmall[I_HARD]; //BUGBUG: CD-ROMs?
+ lvi.lParam = (LPARAM)pDispInfo;
+
+ if (ListView_InsertItem(g_hwndLV, &lvi) == -1)
+ {
+ //BUGBUG: why would it fail?
+ delete pDispInfo;
+ return;
+ }
+
+ for (int iSubItem = 1; iSubItem < g_cColumns; iSubItem++)
+ {
+ ListView_SetItemText(
+ g_hwndLV,
+ item,
+ iSubItem,
+ LPSTR_TEXTCALLBACK);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AddCdRomToListview, public
+//
+// Synopsis: Add a region to the listview
+//
+// Arguments:
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+AddCdRomToListview(
+ IN int item,
+ IN WCHAR DriveLetter
+ )
+{
+ //
+ // First, get all the data into the CDispInfo class. If any of this fails,
+ // then ignore the item. After that, then do the listview insertions.
+ //
+
+ CDispInfo* pDispInfo = new CDispInfo();
+ if (NULL == pDispInfo)
+ {
+ return; //BUGBUG: out of memory
+ }
+
+ INT columnIndex;
+ WCHAR wszTemp[MAX_LV_ITEM_LEN];
+ WCHAR mbBuffer[16];
+
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDriveLetter(DriveLetter);
+
+ //
+ // Before setting any columns, get all the data
+ //
+
+ //
+ // Load resource strings:
+ // mbBuffer -- MB
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer)
+ );
+
+ columnIndex = 0;
+
+ //
+ // column: drive letter
+ //
+
+ wsprintf(wszTemp, TEXT("%c:"), DriveLetter);
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: volume label
+ //
+
+ if (cdrom->VolumeLabel) {
+ if (!pDispInfo->SetText(columnIndex++, cdrom->VolumeLabel))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+ } else {
+
+ columnIndex++;
+
+ }
+
+ //
+ // column: capacity in MB
+ //
+
+ if (cdrom->TypeName && cdrom->TotalSpaceInMB) {
+ wsprintf(wszTemp, TEXT("%lu%s"), cdrom->TotalSpaceInMB, mbBuffer);
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: free space in MB
+ //
+
+ wsprintf(wszTemp, TEXT("0 %s"), mbBuffer);
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: % free space
+ //
+
+ if (!pDispInfo->SetText(columnIndex++, TEXT("0 %")))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ } else {
+
+ columnIndex += 3;
+
+ }
+
+
+ //
+ // column: format (file system type)
+ //
+
+ if (cdrom->TypeName) {
+ if (!pDispInfo->SetText(columnIndex++, cdrom->TypeName))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+ } else {
+
+ columnIndex++;
+
+ }
+
+ //
+ // column: fault tolerant?
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_FT_NO,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: volume type
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_VOLTYPE_SIMPLE,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: fault tolerance overhead in MB
+ //
+
+ if (!pDispInfo->SetText(columnIndex++, TEXT("")))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // column: status
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_FTSTATUS_NONE,
+ wszTemp,
+ ARRAYLEN(wszTemp)
+ );
+
+ if (!pDispInfo->SetText(columnIndex++, wszTemp))
+ {
+ daDebugOut((DEB_ITRACE, "SetText failed\n"));
+ }
+
+ //
+ // Insert the data into the listview
+ //
+
+ LV_ITEM lvi;
+ lvi.iItem = item;
+ lvi.iSubItem = 0;
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.cchTextMax = 0; // ignored when setting data
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.iImage = IconIndexSmall[I_CDROM];
+ lvi.lParam = (LPARAM)pDispInfo;
+
+ if (ListView_InsertItem(g_hwndLV, &lvi) == -1)
+ {
+ //BUGBUG: why would it fail?
+ delete pDispInfo;
+ return;
+ }
+
+ for (int iSubItem = 1; iSubItem < g_cColumns; iSubItem++)
+ {
+ ListView_SetItemText(
+ g_hwndLV,
+ item,
+ iSubItem,
+ LPSTR_TEXTCALLBACK);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FillListView
+//
+// Synopsis: Fill the listview with data from internal state
+//
+// Arguments:
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+FillListView(
+ IN BOOL bSetDefaultSelection
+ )
+{
+ WCHAR DriveLetter;
+ int item;
+
+ //
+ // Save the current selection, if one exists
+ //
+
+ WCHAR saveDriveLetter = NO_DRIVE_LETTER_EVER;
+ int itemOld = ListView_GetNextItem(g_hwndLV, -1, LVNI_SELECTED);
+ if (-1 != itemOld)
+ {
+ saveDriveLetter = GetListviewDriveLetter(itemOld);
+ }
+
+ //
+ // Get rid of everything
+ //
+
+ ListView_DeleteAllItems(g_hwndLV);
+
+ //
+ // Next, using the data available to us, fill the listview
+ //
+
+ daDebugOut((DEB_ITRACE, "Adding: "));
+
+ for (item = 0, DriveLetter = L'C';
+ DriveLetter <= L'Z';
+ ++DriveLetter)
+ {
+ if (SignificantDriveLetter(DriveLetter))
+ {
+ daDebugOut((DEB_ITRACE | DEB_NOCOMPNAME, "%wc:, ", DriveLetter));
+ AddVolumeToListview(item++, DriveLetter);
+ }
+ else
+ {
+ // might be a CD-ROM, unused or a network connection.
+ if (!DriveLetterIsAvailable(DriveLetter))
+ {
+ // it is in use. See if it's a CD-ROM.
+ if (CdRomUsingDriveLetter(DriveLetter))
+ {
+ daDebugOut((DEB_ITRACE | DEB_NOCOMPNAME, "%wc:, ", DriveLetter));
+ AddCdRomToListview(item++, DriveLetter);
+ }
+ }
+ }
+ }
+
+ daDebugOut((DEB_ITRACE | DEB_NOCOMPNAME, "\n"));
+
+ if (bSetDefaultSelection)
+ {
+ if (ListView_GetItemCount(g_hwndLV) > 0)
+ {
+ int itemNew = 0;
+ BOOL bChangeDiskViewSelection = FALSE;
+
+ // give the first element the focus and selection, by default
+
+ g_SettingListviewState = TRUE; // no notifications
+
+ if (NO_DRIVE_LETTER_EVER != saveDriveLetter)
+ {
+ itemNew = GetLVIndexFromDriveLetter(saveDriveLetter);
+ if (-1 == itemNew)
+ {
+ bChangeDiskViewSelection = TRUE;
+ itemNew = 0;
+ }
+ }
+
+ // Give the item both the focus *and* the selection, since we only
+ // allow a single listview selection
+
+ ListView_SetItemState(
+ g_hwndLV,
+ itemNew,
+ LVIS_FOCUSED | LVIS_SELECTED,
+ LVIS_FOCUSED | LVIS_SELECTED);
+ ListView_EnsureVisible(g_hwndLV, itemNew, FALSE);
+
+ g_SettingListviewState = FALSE; // accept notifications
+
+ if (bChangeDiskViewSelection)
+ {
+ DeselectSelectedDiskViewRegions(); // visual selection in disk view
+ DeselectSelectedRegions(); // actual selection state
+
+ SetVolumeSelection(itemNew, TRUE); // reflect in disks view
+ }
+ }
+ }
+ else
+ {
+ DeselectSelectedDiskViewRegions(); // visual selection in disk view
+ DeselectSelectedRegions(); // actual selection state
+ }
+}
diff --git a/private/utils/windisk/src/fill.hxx b/private/utils/windisk/src/fill.hxx
new file mode 100644
index 000000000..d52aa58d5
--- /dev/null
+++ b/private/utils/windisk/src/fill.hxx
@@ -0,0 +1,24 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fill.hxx
+//
+// Contents: Declarations for routines to fill the volumes view with data
+//
+// History: 20-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILL_HXX__
+#define __FILL_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+FillListView(
+ IN BOOL bSetDefaultSelection
+ );
+
+#endif // __FILL_HXX__
diff --git a/private/utils/windisk/src/fmifs.cxx b/private/utils/windisk/src/fmifs.cxx
new file mode 100644
index 000000000..b5ee60061
--- /dev/null
+++ b/private/utils/windisk/src/fmifs.cxx
@@ -0,0 +1,644 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fmifs.cxx
+//
+// Contents: Routines that work with fmifs.dll
+//
+// History: 7-Jan-94 BruceFo Adapted from BobRi's Daytona code
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "drives.hxx"
+#include "fmifs.hxx"
+#include "nt.hxx"
+#include "format.hxx"
+#include "windisk.hxx"
+
+//
+// Externals needed for IFS Dll support (format and label)
+//
+
+
+TCHAR szFmifsDll[] = TEXT("fmifs.dll");
+HMODULE g_hFmifsDll = NULL;
+
+PFMIFS_FORMAT_ROUTINE lpfnFormat = NULL;
+PFMIFS_CHKDSK_ROUTINE lpfnChkdsk = NULL;
+PFMIFS_SETLABEL_ROUTINE lpfnSetLabel = NULL;
+
+#if defined( DBLSPACE_ENABLED )
+
+PFMIFS_DOUBLESPACE_CREATE_ROUTINE DblSpaceCreateRoutine = NULL;
+PFMIFS_DOUBLESPACE_MOUNT_ROUTINE DblSpaceMountRoutine = NULL;
+PFMIFS_DOUBLESPACE_DELETE_ROUTINE DblSpaceDeleteRoutine = NULL;
+PFMIFS_DOUBLESPACE_DISMOUNT_ROUTINE DblSpaceDismountRoutine = NULL;
+PFMIFS_DOUBLESPACE_QUERY_INFO_ROUTINE DblSpaceQueryInfoRoutine = NULL;
+
+BOOL g_DoubleSpaceSupported = TRUE;
+BOOL g_IsFullDoubleSpace = FALSE;
+
+#endif // DBLSPACE_ENABLED
+
+BOOL g_ChkdskSupported = TRUE;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: LoadFmifs
+//
+// Synopsis: If the fmifs DLL is not already loaded, then load it.
+//
+// Arguments: none
+//
+// Returns: TRUE if the load was successful, FALSE otherwise
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+LoadFmifs(
+ VOID
+ )
+{
+ if (NULL == g_hFmifsDll)
+ {
+ SetCursor(g_hCurWait);
+ g_hFmifsDll = LoadLibrary(szFmifsDll);
+ SetCursor(g_hCurNormal);
+
+ if (NULL == g_hFmifsDll)
+ {
+ daDebugOut((DEB_ERROR,"Couldn't load %ws: error 0x%x\n",
+ szFmifsDll,
+ GetLastError()
+ ));
+
+ ErrorDialog(MSG_NOFMIFS);
+ return FALSE;
+ }
+ else
+ {
+#if defined( DBLSPACE_ENABLED )
+ g_DoubleSpaceSupported = TRUE;
+ g_IsFullDoubleSpace = FALSE;
+#endif // DBLSPACE_ENABLED
+
+ g_ChkdskSupported = TRUE;
+
+ daDebugOut((DEB_ITRACE,"Loaded %ws: handle 0x%x\n",
+ szFmifsDll,
+ g_hFmifsDll));
+
+ lpfnFormat = (PFMIFS_FORMAT_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "Format");
+
+ if (!lpfnFormat)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't get 'Format', 0x%x, 0x%x\n",
+ lpfnFormat,
+ GetLastError()));
+ }
+
+ lpfnSetLabel = (PFMIFS_SETLABEL_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "SetLabel");
+
+ if (!lpfnSetLabel)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't get 'SetLabel', 0x%x, 0x%x\n",
+ lpfnSetLabel,
+ GetLastError()));
+ }
+
+ if ( !lpfnFormat
+ || !lpfnSetLabel)
+ {
+ //
+ // If we didn't get at least Format and SetLabel, there
+ // is something seriously wrong.
+ //
+
+ FreeLibrary(g_hFmifsDll);
+ g_hFmifsDll = NULL;
+ ErrorDialog(MSG_NOFMIFS);
+ return FALSE;
+ }
+
+ lpfnChkdsk = (PFMIFS_CHKDSK_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "Chkdsk");
+
+ if (!lpfnChkdsk)
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't get 'Chkdsk', 0x%x, 0x%x\n",
+ lpfnChkdsk,
+ GetLastError()));
+ }
+
+ if (!lpfnChkdsk)
+ {
+ // Might be 3.1 or Daytona w/o this entrypoint
+
+ g_ChkdskSupported = FALSE;
+ }
+
+#if defined( DBLSPACE_ENABLED )
+
+ DblSpaceMountRoutine = (PFMIFS_DOUBLESPACE_MOUNT_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "DoubleSpaceMount");
+
+ DblSpaceDismountRoutine = (PFMIFS_DOUBLESPACE_DISMOUNT_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "DoubleSpaceDismount");
+
+ DblSpaceQueryInfoRoutine = (PFMIFS_DOUBLESPACE_QUERY_INFO_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "FmifsQueryDriveInformation");
+
+ if ( !DblSpaceMountRoutine
+ || !DblSpaceDismountRoutine
+ || !DblSpaceQueryInfoRoutine)
+ {
+ // didn't get all of the DoubleSpace support routines
+ // Allow format and label, just don't do DoubleSpace
+
+ g_DoubleSpaceSupported = FALSE;
+ }
+
+ DblSpaceCreateRoutine = (PFMIFS_DOUBLESPACE_CREATE_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "DoubleSpaceCreate");
+
+ DblSpaceDeleteRoutine = (PFMIFS_DOUBLESPACE_DELETE_ROUTINE)
+ GetProcAddress(g_hFmifsDll, "DoubleSpaceDelete");
+
+ if (DblSpaceCreateRoutine && DblSpaceDeleteRoutine)
+ {
+ // Everything is there for read/write double space support.
+ // This will change certain dialogs to allow creation and
+ // deletion of double space volumes.
+
+ g_IsFullDoubleSpace = TRUE;
+ }
+
+#endif // DBLSPACE_ENABLED
+
+ }
+ }
+ return TRUE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnloadFmifs
+//
+// Synopsis: If the fmifs DLL is loaded, then unload it.
+//
+// Arguments: none
+//
+// Returns: TRUE if the unload was successful, FALSE otherwise
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+UnloadFmifs(
+ VOID
+ )
+{
+ if (NULL != g_hFmifsDll)
+ {
+ FreeLibrary(g_hFmifsDll);
+
+ g_hFmifsDll = NULL;
+
+ lpfnFormat = NULL;
+ lpfnChkdsk = NULL;
+ lpfnSetLabel = NULL;
+
+#if defined( DBLSPACE_ENABLED )
+
+ DblSpaceDismountRoutine = NULL;
+ DblSpaceMountRoutine = NULL;
+ DblSpaceCreateRoutine = NULL;
+ DblSpaceDeleteRoutine = NULL;
+ DblSpaceQueryInfoRoutine = NULL;
+
+#endif // DBLSPACE_ENABLED
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EnsureSameDevice
+//
+// Synopsis: If a disk is removable, check that it is the same one we
+// thought it was.
+//
+// Arguments: [RegionDescriptor] -- region of interest
+//
+// Returns:
+//
+// History: 9-Feb-94 BruceFo Taken from Daytona
+//
+//--------------------------------------------------------------------------
+
+VOID
+EnsureSameDevice(
+ PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ if (IsDiskRemovable[RegionDescriptor->Disk])
+ {
+ PWSTR tempName;
+ PWSTR tempLabel;
+ PWSTR typeName;
+ PWSTR volumeLabel;
+ ULONG diskSize;
+ BOOL volumeChanged = FALSE;
+
+ if (!RegionDescriptor->PartitionNumber)
+ {
+ // TODO: something has changed where the code gets to this
+ // point with an incorrect partition number - This happens
+ // when a partition is deleted and added to removable media.
+ // For removable media the partition number is always 1.
+
+ RegionDescriptor->PartitionNumber = 1;
+ }
+
+ if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber,
+ &volumeLabel,
+ &typeName,
+ &diskSize))
+ {
+ // Verify that this is still the same device.
+
+ if (NULL != typeName)
+ {
+ if (0 == lstrcmpi(typeName, L"raw"))
+ {
+ Free(typeName);
+ typeName = (PWSTR)Malloc((wcslen(wszUnknown) + 1) * sizeof(WCHAR));
+ lstrcpy(typeName, wszUnknown);
+ }
+ }
+ else
+ {
+ typeName = (PWSTR)Malloc((wcslen(wszUnknown) + 1) * sizeof(WCHAR));
+ lstrcpy(typeName, wszUnknown);
+ }
+
+ if (regionData)
+ {
+ if (regionData->VolumeLabel)
+ {
+ if (0 != lstrcmp(regionData->VolumeLabel, volumeLabel))
+ {
+ volumeChanged = TRUE;
+ }
+ }
+ if (NULL != regionData->TypeName)
+ {
+ // It is possible the region has no type or is of type
+ // "Unformatted". This says it is ok to format
+
+ if (L'\0' == *regionData->TypeName)
+ {
+ if (0 != lstrcmp(regionData->TypeName, wszUnformatted))
+ {
+ // It has a type and it isn't unformatted - see if
+ // it is the same as before.
+
+ if (0 != lstrcmp(regionData->TypeName, typeName))
+ {
+ volumeChanged = TRUE;
+ }
+ }
+ }
+ }
+ }
+ Free(volumeLabel);
+ Free(typeName);
+
+ if (DiskArray[RegionDescriptor->Disk]->DiskSizeMB != diskSize)
+ {
+ volumeChanged = TRUE;
+ }
+ }
+ if (volumeChanged)
+ {
+ ErrorDialog(MSG_VOLUME_CHANGED);
+
+ // since the user was told the volume changed,
+ // update the display.
+
+ SetCursor(g_hCurWait);
+ if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber,
+ &tempLabel,
+ &tempName,
+ &diskSize) == OK_STATUS)
+ {
+ Free(typeName);
+ typeName = tempName;
+ Free(volumeLabel);
+ volumeLabel = tempLabel;
+ }
+ if (regionData->VolumeLabel)
+ {
+ Free(regionData->VolumeLabel);
+ }
+ regionData->VolumeLabel = volumeLabel;
+ if (regionData->TypeName)
+ {
+ Free(regionData->TypeName);
+ }
+ regionData->TypeName = typeName;
+ SetCursor(g_hCurNormal);
+ TotalRedrawAndRepaint();
+ }
+ else
+ {
+ if (volumeLabel)
+ {
+ Free(volumeLabel);
+ }
+ if (typeName)
+ {
+ Free(typeName);
+ }
+ }
+ }
+}
+
+#if defined( DBLSPACE_ENABLED )
+
+ULONG MountDismountResult;
+#define MOUNT_DISMOUNT_SUCCESS 0
+
+BOOLEAN
+FmIfsMountDismountCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets callbacks from fmifs.dll regarding
+ progress and status of the ongoing format or doublespace
+
+Arguments:
+
+ [PacketType] -- an fmifs packet type
+ [PacketLength] -- length of the packet data
+ [PacketData] -- data associated with the packet
+
+Return Value:
+
+ TRUE if the fmifs activity should continue, FALSE if the
+ activity should halt immediately. Thus, we return FALSE if
+ the user has hit "cancel" and we wish fmifs to clean up and
+ return from the Format() entrypoint call.
+
+--*/
+
+{
+#if defined( DBLSPACE_ENABLED )
+ switch (PacketType)
+ {
+ case FmIfsDblspaceMounted:
+ MountDismountResult = MOUNT_DISMOUNT_SUCCESS;
+ break;
+ }
+#endif // DBLSPACE_ENABLED
+ return TRUE;
+}
+
+DWORD WINAPI
+FmIfsCreateDblspace(
+ IN LPVOID ThreadParameter
+ )
+
+/*++
+
+Routine Description:
+
+ This routine converts the strings in the formatParams structure
+ and calls the fmifs routines to perform the double space create.
+
+ It assumes it is called by a separate thread and will exit the
+ thread on completion of the create.
+
+Arguments:
+
+ ThreadParameter - a pointer to the FORMAT_PARAMS structure
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PFORMAT_PARAMS formatParams = (PFORMAT_PARAMS) ThreadParameter;
+ PPERSISTENT_REGION_DATA regionData;
+ WCHAR letter;
+ WCHAR newDriveName[4],
+ hostDriveName[4];
+
+ // The fmifs interface doesn't allow for a context parameter
+ // therefore the formatparams must be passed through an external.
+
+ ParamsForFormatCallBack = formatParams;
+
+ // set up a unicode drive letter.
+
+ regionData = PERSISTENT_DATA(formatParams->RegionDescriptor);
+
+ hostDriveName[0] = regionData->DriveLetter;
+ hostDriveName[1] = L':';
+ hostDriveName[2] = L'\0';
+
+ // set up the new letter
+
+ newDriveName[1] = L':';
+ newDriveName[2] = L'\0';
+
+ // Choose the first available. BUGBUG: This should come from the dialog
+ // newDriveName[0] = (WCHAR) formatParams->NewLetter;
+
+ for (letter = L'C'; letter <= L'Z'; letter++)
+ {
+ if (DriveLetterIsAvailable(letter))
+ {
+ newDriveName[0] = letter;
+ break;
+ }
+ }
+
+ (*DblSpaceCreateRoutine)(hostDriveName,
+ formatParams->SpaceAvailable * 1024 * 1024,
+ formatParams->Label,
+ newDriveName,
+ &FormatCallback);
+ return 0;
+}
+
+
+ULONG
+FmIfsDismountDblspace(
+ IN WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Convert the name provided into unicode and call the
+ FmIfs support routine.
+
+Arguments:
+
+ DriveLetter - the drive letter to dismount.
+
+Return Value:
+
+ 0 for success
+
+--*/
+
+{
+ WCHAR driveName[3];
+
+ driveName[0] = DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ // The only way to communicate with the fmifs callback
+ // is through global externals.
+
+ MountDismountResult = MSG_CANT_DISMOUNT_DBLSPACE;
+
+ (*DblSpaceDismountRoutine)(driveName, &FmIfsMountDismountCallback);
+
+ return MountDismountResult;
+}
+
+
+ULONG
+FmIfsMountDblspace(
+ IN PWSTR FileName,
+ IN WCHAR HostDriveLetter,
+ IN WCHAR NewDriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Call the FmIfs support routine to mount the DoubleSpace volume.
+
+Arguments:
+
+ FileName - file name (i.e. dblspace.xxx)
+ HostDriveLetter - Drive drive letter containing double space volume
+ NewDriveLetter - Drive letter to be assigned to the volume
+
+Return Value:
+
+ TRUE it worked.
+
+--*/
+
+{
+ WCHAR hostDriveName[3];
+ WCHAR newDriveName[3];
+
+ newDriveName[0] = NewDriveLetter;
+ hostDriveName[0] = HostDriveLetter;
+
+ newDriveName[1] = hostDriveName[1] = L':';
+ newDriveName[2] = hostDriveName[2] = L'\0';
+
+ // The only way to communicate with the fmifs callback
+ // is through global externals.
+
+ MountDismountResult = MSG_CANT_MOUNT_DBLSPACE;
+
+ (*DblSpaceMountRoutine)(hostDriveName,
+ FileName,
+ newDriveName,
+ &FmIfsMountDismountCallback);
+ return MountDismountResult;
+}
+
+
+
+BOOLEAN
+FmIfsQueryInformation(
+ IN PWSTR DosDriveName,
+ OUT PBOOLEAN IsRemovable,
+ OUT PBOOLEAN IsFloppy,
+ OUT PBOOLEAN IsCompressed,
+ OUT PBOOLEAN Error,
+ OUT PWSTR NtDriveName,
+ IN ULONG MaxNtDriveNameLength,
+ OUT PWSTR CvfFileName,
+ IN ULONG MaxCvfFileNameLength,
+ OUT PWSTR HostDriveName,
+ IN ULONG MaxHostDriveNameLength
+ )
+
+/*++
+
+Routine Description:
+
+ Call through the pointer to the routine in the fmifs dll.
+
+Arguments:
+
+ Same as the Fmifs routine in the DLL.
+
+Return Value:
+
+--*/
+
+{
+ if (!DblSpaceQueryInfoRoutine)
+ {
+ return FALSE;
+ }
+
+ return (*DblSpaceQueryInfoRoutine)(DosDriveName,
+ IsRemovable,
+ IsFloppy,
+ IsCompressed,
+ Error,
+ NtDriveName,
+ MaxNtDriveNameLength,
+ CvfFileName,
+ MaxCvfFileNameLength,
+ HostDriveName,
+ MaxHostDriveNameLength);
+}
+
+#endif // DBLSPACE_ENABLED
diff --git a/private/utils/windisk/src/fmifs.hxx b/private/utils/windisk/src/fmifs.hxx
new file mode 100644
index 000000000..8ded9e8c9
--- /dev/null
+++ b/private/utils/windisk/src/fmifs.hxx
@@ -0,0 +1,183 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fmifs.hxx
+//
+// Contents: Routines that work with fmifs.dll
+//
+// History: 7-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FMIFS_HXX__
+#define __FMIFS_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define FMT_PROGRESSUPDATE (WM_USER + 0)
+#define FMT_PROGRESSEND (WM_USER + 1)
+#define FMT_PROGRESSCANCEL (WM_USER + 2)
+#define FMT_PROGRESSUNCANCEL (WM_USER + 3)
+
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _FORMAT_PARAMS
+{
+ PREGION_DESCRIPTOR RegionDescriptor;
+
+ //
+ // 'AllowCancel' is set by the format invoker to indicate whether
+ // cancelling the operation is allowed.
+ //
+
+ BOOL AllowCancel;
+
+ //
+ // 'Cancel' is set by the UI thread to indicate the user has chosen
+ // to cancel the operation.
+ //
+
+ BOOL Cancel;
+
+ //
+ // 'Cancelled' is set by the formatting thread to indicate a cancel
+ // is in progress, and to ignore all future callback messages.
+ //
+
+ BOOL Cancelled;
+
+ //
+ // 'Result' is set by the formatting thread to the message id
+ // (currently a resource string id) of the error message, for an error
+ // return. On successful formatting, it remains zero.
+ //
+
+ UINT Result;
+
+ //
+ // Window handles set by UI thread and used by both UI and formatting
+ // threads. The formatting thread uses hDlg to send messages; thus the
+ // Windows message queue is used as an IPC mechanism.
+ //
+
+ HWND hdlgProgress;
+
+ //
+ // Values passed to the format setup dialog proc.
+ //
+
+ BOOL QuickAllowed; // whether or not quick format is allowed
+
+ //
+ // IN parameters set by the UI thread for use by the Format routine
+ //
+
+ PWSTR Label;
+ INT FileSystemIndex;
+
+ BOOL QuickFormat;
+
+ //
+ // OUT parameters set by the format routine
+ //
+
+ ULONG TotalSpace;
+ ULONG SpaceAvailable;
+
+#if defined( DBLSPACE_ENABLED )
+ //
+ // Parameters for DoubleSpace
+ //
+
+ BOOL DoubleSpace; // formatting a DoubleSpace volume?
+ PWSTR DblspaceFileName; // host filename for DoubleSpace volume
+#endif // DBLSPACE_ENABLED
+
+} FORMAT_PARAMS, *PFORMAT_PARAMS;
+
+extern PFORMAT_PARAMS ParamsForFormatCallBack;
+
+
+extern PFMIFS_FORMAT_ROUTINE lpfnFormat;
+extern PFMIFS_CHKDSK_ROUTINE lpfnChkdsk;
+extern PFMIFS_SETLABEL_ROUTINE lpfnSetLabel;
+
+#if defined( DBLSPACE_ENABLED )
+
+extern PFMIFS_DOUBLESPACE_CREATE_ROUTINE DblSpaceCreateRoutine;
+extern PFMIFS_DOUBLESPACE_MOUNT_ROUTINE DblSpaceMountRoutine;
+extern PFMIFS_DOUBLESPACE_DELETE_ROUTINE DblSpaceDeleteRoutine;
+extern PFMIFS_DOUBLESPACE_DISMOUNT_ROUTINE DblSpaceDismountRoutine;
+extern PFMIFS_DOUBLESPACE_QUERY_INFO_ROUTINE DblSpaceQueryInfoRoutine;
+
+extern BOOL g_DoubleSpaceSupported;
+extern BOOL g_IsFullDoubleSpace;
+
+#endif // DBLSPACE_ENABLED
+
+extern BOOL g_ChkdskSupported;
+
+BOOL
+LoadFmifs(
+ VOID
+ );
+
+VOID
+UnloadFmifs(
+ VOID
+ );
+
+VOID
+EnsureSameDevice(
+ PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+BOOLEAN
+FmIfsCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ );
+
+BOOLEAN
+FmIfsMountDismountCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ );
+
+DWORD WINAPI
+FmIfsCreateDblspace(
+ IN LPVOID ThreadParameter
+ );
+
+ULONG
+FmIfsDismountDblspace(
+ IN WCHAR DriveLetter
+ );
+
+ULONG
+FmIfsMountDblspace(
+ IN PWSTR FileName,
+ IN WCHAR HostDriveLetter,
+ IN WCHAR NewDriveLetter
+ );
+
+BOOLEAN
+FmIfsQueryInformation(
+ IN PWSTR DosDriveName,
+ OUT PBOOLEAN IsRemovable,
+ OUT PBOOLEAN IsFloppy,
+ OUT PBOOLEAN IsCompressed,
+ OUT PBOOLEAN Error,
+ OUT PWSTR NtDriveName,
+ IN ULONG MaxNtDriveNameLength,
+ OUT PWSTR CvfFileName,
+ IN ULONG MaxCvfFileNameLength,
+ OUT PWSTR HostDriveName,
+ IN ULONG MaxHostDriveNameLength
+ );
+
+#endif // __FMIFS_HXX__
diff --git a/private/utils/windisk/src/format.cxx b/private/utils/windisk/src/format.cxx
new file mode 100644
index 000000000..3e6c12589
--- /dev/null
+++ b/private/utils/windisk/src/format.cxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: format.cxx
+//
+// Contents: Disk Administrator format dialog
+//
+// History: 10-Jun-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "windisk.hxx"
+#include "ops.hxx"
+#include "shlobj.h"
+#include "shsemip.h"
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoFormat
+//
+// Synopsis: Display and handle the Disk Administrator portion of
+// formatting, i.e., the dialog box that allows users to choose
+// a file system and quick/non-quick.
+//
+// Arguments: [FormatReport] -- TRUE if we want a format report
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoFormat(
+ IN HWND hwndParent,
+ IN BOOL FormatReport
+ )
+{
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(regionDescriptor);
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(regionData);
+
+ if (DeletionIsAllowed(regionDescriptor) != NO_ERROR)
+ {
+ ErrorDialog(MSG_CANT_FORMAT_WINNT);
+ return;
+ }
+
+ if ('\0' == regionData->DriveLetter)
+ {
+ ErrorDialog(MSG_CANT_FORMAT_NO_LETTER);
+ return;
+ }
+
+ SHFormatDrive(hwndParent, regionData->DriveLetter - 'A',
+ SHFMT_ID_DEFAULT, 0);
+
+ DoRefresh();
+}
diff --git a/private/utils/windisk/src/format.hxx b/private/utils/windisk/src/format.hxx
new file mode 100644
index 000000000..420e2b9f5
--- /dev/null
+++ b/private/utils/windisk/src/format.hxx
@@ -0,0 +1,38 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: format.hxx
+//
+// Contents: Change volume format.
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FORMAT_HXX__
+#define __FORMAT_HXX__
+
+BOOLEAN
+FormatCallback(
+ IN FMIFS_PACKET_TYPE PacketType,
+ IN DWORD PacketLength,
+ IN PVOID PacketData
+ );
+
+BOOL CALLBACK
+FormatProgressDlgProc(
+ IN HWND hDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+VOID
+DoFormat(
+ IN HWND hwndParent,
+ IN BOOL FormatReport
+ );
+
+#endif // __FORMAT_HXX__
diff --git a/private/utils/windisk/src/fs.cxx b/private/utils/windisk/src/fs.cxx
new file mode 100644
index 000000000..380f18733
--- /dev/null
+++ b/private/utils/windisk/src/fs.cxx
@@ -0,0 +1,96 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fs.cxx
+//
+// Contents: Disk Administrator file system information
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "fs.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define MAX_FAT_LABEL 11
+#define MAX_NTFS_LABEL 32
+
+#ifdef SUPPORT_OFS
+#define MAX_OFS_LABEL 32
+#endif // SUPPORT_OFS
+
+//////////////////////////////////////////////////////////////////////////////
+
+// NOTE: DEFAULT_FILE_SYSTEM defined in fs.hxx is an index into this array!
+
+FileSystemInfoType FileSystems[] =
+{
+ {
+ L"FAT", // not localized
+ IDS_LONG_FAT,
+ FS_FAT,
+ DA_FS_FLOPPY_CAPABLE,
+ MAX_FAT_LABEL
+ }
+ ,
+ {
+ L"NTFS", // not localized
+ IDS_LONG_NTFS,
+ FS_NTFS,
+ DA_FS_EXTENDABLE,
+ MAX_NTFS_LABEL
+ }
+#ifdef SUPPORT_OFS
+ ,
+ {
+ L"OFS", // not localized
+ IDS_LONG_OFS,
+ FS_OFS,
+ DA_FS_FLOPPY_CAPABLE | DA_FS_EXTENDABLE,
+ MAX_OFS_LABEL
+ }
+#endif // SUPPORT_OFS
+};
+
+UINT g_NumKnownFileSystems = ARRAYLEN(FileSystems);
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindFileSystemInfo
+//
+// Synopsis: Find information about a file system type based on its name
+//
+// Arguments: [FileSystem] -- name of the file system
+//
+// Returns: pointer to a file system information structure, or NULL
+// on failure
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+FileSystemInfoType*
+FindFileSystemInfo(
+ IN PWSTR FileSystem
+ )
+{
+ INT i;
+
+ for (i=0; i<ARRAYLEN(FileSystems); i++)
+ {
+ if (0 == lstrcmp(FileSystem, FileSystems[i].pwszShortName))
+ {
+ return &(FileSystems[i]);
+ }
+ }
+
+ return NULL;
+}
diff --git a/private/utils/windisk/src/fs.hxx b/private/utils/windisk/src/fs.hxx
new file mode 100644
index 000000000..994975805
--- /dev/null
+++ b/private/utils/windisk/src/fs.hxx
@@ -0,0 +1,93 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fs.hxx
+//
+// Contents: Disk Administrator file system information
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FS_HXX__
+#define __FS_HXX__
+
+#define DEFAULT_FILE_SYSTEM 1 // NTFS: 0-based index into FileSystems[]
+
+//
+// FileSystemInfoType:
+//
+// FileSystemInfoType encapsulates all interesting file system
+// information for the Disk Administrator. The data:
+//
+// pwszShortName: A short name for the file system, e.g. ``FAT''
+// (not localized).
+//
+// idsDescriptive: Resource table string id of a descriptive name for the
+// file system, e.g. ``FAT (File Allocation Table: DOS, OS/2, NT)''
+//
+// fCapabilities: A bitmask of capabilities:
+// DA_FS_NONE: no extra capabilities
+// DA_FS_FLOPPY_CAPABLE: if set, floppies can be formatted with
+// this file system. Note that NT file system u*.sys code
+// determines during a ``format'' operation if the user is
+// trying to format a floppy. If so, and this file system
+// doesn't support floppies, then a message is displayed,
+// and the format operation fails. The messages displayed
+// look a bit weird, given their order.
+// DA_FS_EXTENDABLE: if set, a volume can be extended by adding
+// partitions to make a multi-partition volume. This will be
+// set by OFS and NTFS.
+//
+// cMaxLabelLen: Maximum length of a volume label for the file system.
+// If -1, then there is no maximum.
+//
+// propPages: Information about property sheet pages specific to
+// this format.
+//
+
+//
+// Note: The below enum must be in ssync with the array in fs.cxx.
+// FS_UNKOWN must begin at -1 so that real file system info begins
+// at index 0.
+//
+
+enum FILE_SYSTEM
+{
+ FS_UNKNOWN = -1,
+ FS_FAT,
+ FS_NTFS,
+#ifdef SUPPORT_OFS
+ FS_OFS,
+#endif // SUPPORT_OFS
+ FS_CDFS
+};
+
+#define DA_FS_NONE 0x0
+#define DA_FS_FLOPPY_CAPABLE 0x1
+#define DA_FS_EXTENDABLE 0x2
+
+typedef struct _FileSystemInfoType
+{
+ PWSTR pwszShortName; // file system name isn't localized
+ UINT idsDescriptive; //resource ID of string
+ FILE_SYSTEM FileSystemType;
+ ULONG fCapabilities;
+ INT cMaxLabelLen;
+} FileSystemInfoType;
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern FileSystemInfoType FileSystems[];
+extern UINT g_NumKnownFileSystems;
+
+//////////////////////////////////////////////////////////////////////////////
+
+FileSystemInfoType*
+FindFileSystemInfo(
+ IN PWSTR FileSystem
+ );
+
+#endif // __FS_HXX__
diff --git a/private/utils/windisk/src/ft.cxx b/private/utils/windisk/src/ft.cxx
new file mode 100644
index 000000000..20649e999
--- /dev/null
+++ b/private/utils/windisk/src/ft.cxx
@@ -0,0 +1,1685 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ft.cxx
+//
+// Contents: This module contains FT support routines for Disk Administrator
+//
+// History: 15-Nov-91 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "ft.hxx"
+#include "nt.hxx"
+#include "ntlow.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// This variable heads a linked list of ft object sets.
+//
+PFT_OBJECT_SET FtObjectList = NULL;
+
+//
+// Array of pointers to registry disk descriptors that we
+// remember, ie, save for later use when a disk is not physically
+// present on the machine.
+//
+
+PDISK_DESCRIPTION* RememberedDiskArray;
+ULONG RememberedDiskCount;
+
+PULONG DiskHadRegistryEntry;
+
+
+#define MAX_FT_SET_TYPES 4
+
+ULONG OrdinalToAllocate[MAX_FT_SET_TYPES] =
+{
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+ULONG
+FdpDetermineDiskDescriptionSize(
+ PDISKSTATE DiskState
+ );
+
+ULONG
+FdpConstructDiskDescription(
+ IN PDISKSTATE DiskState,
+ OUT PDISK_DESCRIPTION DiskDescription
+ );
+
+VOID
+FdpRememberDisk(
+ IN PDISK_DESCRIPTION DiskDescription
+ );
+
+VOID
+FdpInitializeMirrors(
+ VOID
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+VOID
+MaintainOrdinalTables(
+ IN FT_TYPE FtType,
+ IN ULONG Ordinal
+ )
+
+/*++
+
+Routine Description:
+
+ Maintain the minimum and maximum Ordinal value recorded.
+
+Arguments:
+
+ FtType - the type of the FT set.
+ Ordinal - the in use FtGroup (or ordinal) number
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ if (Ordinal > OrdinalToAllocate[FtType])
+ {
+ OrdinalToAllocate[FtType] = Ordinal;
+ }
+}
+
+
+
+DWORD
+FdftNextOrdinal(
+ IN FT_TYPE FtType
+ )
+
+/*++
+
+Routine Description:
+
+ Allocate a number that will uniquely identify the FT set
+ from other sets of the same type. This number must be unique
+ from any given or used by FT sets of the same type due to
+ requirements of FT dynamic partitioning.
+
+Arguments:
+
+ FtType - The type of the FT set.
+
+Return Value:
+
+ The FtGroup number -- called an "ordinal" in the internal
+ structures.
+
+--*/
+
+{
+ DWORD ordinal;
+ PFT_OBJECT_SET ftSet;
+ BOOL looping;
+
+ // The Ordinal value is going to be used as an FtGroup number
+ // FtGroups are USHORTs so don't wrap on the Ordinal. Try
+ // to keep the next ordinal in the largest opening range, that
+ // is if the minimum found is > half way through a USHORT, start
+ // the ordinals over at zero.
+
+ if (OrdinalToAllocate[FtType] > 0x7FFE)
+ {
+ OrdinalToAllocate[FtType] = 0;
+ }
+
+ ordinal = OrdinalToAllocate[FtType];
+ ++ordinal;
+
+ do
+ {
+ looping = FALSE;
+ ftSet = FtObjectList;
+ while (NULL != ftSet)
+ {
+ if ((ftSet->Type == FtType) && (ftSet->Ordinal == ordinal))
+ {
+ ordinal++;
+ looping = TRUE;
+ break;
+ }
+ ftSet = ftSet->Next;
+ }
+ } while (looping);
+
+ OrdinalToAllocate[FtType] = (ordinal + 1);
+ return ordinal;
+}
+
+
+
+VOID
+FdftCreateFtObjectSet(
+ IN FT_TYPE FtType,
+ IN PREGION_DESCRIPTOR* RegionArray,
+ IN DWORD RegionCount,
+ IN FT_SET_STATUS FtStatus
+ )
+
+/*++
+
+Routine Description:
+
+ Create the FT set structures for the give collection of
+ region pointers.
+
+Arguments:
+
+ FtType
+ Regions
+ RegionCount
+ Status
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ DWORD regionIndex;
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+
+ ftSet = (PFT_OBJECT_SET)Malloc(sizeof(FT_OBJECT_SET));
+
+ //
+ // Figure out an ordinal for the new object set.
+ //
+
+ ftSet->Ordinal = FdftNextOrdinal(FtType);
+ ftSet->Type = FtType;
+ ftSet->Members = NULL;
+ ftSet->Member0 = NULL;
+ ftSet->Status = FtStatus;
+
+ //
+ // Link the new object set into the list.
+
+ ftSet->Next = FtObjectList;
+ FtObjectList = ftSet;
+
+ //
+ // For each region in the set, associate the ft info with it.
+ //
+
+ for (regionIndex=0; regionIndex<RegionCount; regionIndex++)
+ {
+ ftObject = (PFT_OBJECT)Malloc(sizeof(FT_OBJECT));
+
+ //
+ // If this is a creation of a stripe set with parity, then
+ // we must mark the 0th item 'Initializing' instead of 'Healthy'.
+ //
+
+ if ((regionIndex == 0)
+ && (FtType == StripeWithParity)
+ && (FtStatus == FtSetNewNeedsInitialization))
+ {
+ ftObject->State = Initializing;
+ }
+ else
+ {
+ ftObject->State = Healthy;
+ }
+
+ if (0 == regionIndex)
+ {
+ ftSet->Member0 = ftObject;
+ }
+
+ ftObject->Set = ftSet;
+ ftObject->MemberIndex = regionIndex;
+ ftObject->Next = ftSet->Members;
+ ftSet->Members = ftObject;
+
+ SET_FT_OBJECT(RegionArray[regionIndex], ftObject);
+ }
+}
+
+
+
+BOOL
+FdftUpdateFtObjectSet(
+ IN PFT_OBJECT_SET FtSet,
+ IN FT_SET_STATUS SetState
+ )
+
+/*++
+
+Routine Description:
+
+ Given an FT set, go back to the registry information and
+ update the state of the members with the state in the registry.
+
+ NOTE: The following condition may exist. It is possible for
+ the FtDisk driver to return that the set is in an initializing
+ or regenerating state and not have this fact reflected in the
+ registry. This can happen when the system has crashed and
+ on restart the FtDisk driver started the regeneration of the
+ check data (parity).
+
+Arguments:
+
+ FtSet - the set to update.
+
+Return Value:
+
+ TRUE if the set state provided has a strong likelyhood of being correct
+ FALSE if the NOTE condition above is occuring.
+
+--*/
+
+{
+ BOOLEAN allHealthy = TRUE;
+ PFT_OBJECT ftObject;
+ PDISK_REGISTRY diskRegistry;
+ PDISK_PARTITION partition;
+ PDISK_DESCRIPTION diskDescription;
+ DWORD ec;
+ ULONG diskIndex,
+ partitionIndex;
+
+ ec = MyDiskRegistryGet(&diskRegistry);
+ if (ec != NO_ERROR)
+ {
+ // No registry information.
+
+ return TRUE;
+ }
+
+ diskDescription = diskRegistry->Disks;
+ for (diskIndex=0; diskIndex<diskRegistry->NumberOfDisks; diskIndex++)
+ {
+ for (partitionIndex=0;
+ partitionIndex < diskDescription->NumberOfPartitions;
+ partitionIndex++)
+ {
+ partition = &diskDescription->Partitions[partitionIndex];
+ if ( (partition->FtType == FtSet->Type)
+ && (partition->FtGroup == (USHORT) FtSet->Ordinal))
+ {
+ // Have a match for a partition within this set.
+ // Find the region descriptor for this partition and
+ // update its state accordingly.
+
+ for (ftObject = FtSet->Members;
+ NULL != ftObject;
+ ftObject = ftObject->Next)
+ {
+ if (ftObject->MemberIndex == (ULONG) partition->FtMember)
+ {
+ ftObject->State = partition->FtState;
+ break;
+ }
+
+ if (partition->FtState != Healthy)
+ {
+ allHealthy = FALSE;
+ }
+ }
+ }
+ }
+
+ diskDescription = (PDISK_DESCRIPTION)&diskDescription->Partitions[diskDescription->NumberOfPartitions];
+ }
+
+ Free(diskRegistry);
+
+ if ((allHealthy) && (SetState != FtSetHealthy))
+ {
+ // This is a condition where the system must be
+ // updating the check data for redundant sets.
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+VOID
+FdftDeleteFtObjectSet(
+ IN PFT_OBJECT_SET FtSet,
+ IN BOOL OffLineDisksOnly
+ )
+
+/*++
+
+Routine Description:
+
+ Delete an ft set, or rather its internal representation as a linked
+ list of ft member structures.
+
+Arguments:
+
+ FtSet - supplies pointer to ft set structure for set to delete.
+
+ OffLineDisksOnly - if TRUE, then do not delete the set but instead
+ scan remembered disks for members of the set and remove such members.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PFT_OBJECT ftObject = FtSet->Members;
+ PFT_OBJECT nextFtObject;
+ PFT_OBJECT_SET ftSetTemp;
+ PDISK_DESCRIPTION diskDescription;
+ PDISK_PARTITION diskPartition;
+ ULONG partitionCount;
+ ULONG size;
+ ULONG i;
+ ULONG j;
+
+ //
+ // Locate any members of the ft set on remembered disks and
+ // remove the entries for such partitions.
+ //
+
+ for (i=0; i<RememberedDiskCount; i++)
+ {
+ diskDescription = RememberedDiskArray[i];
+ partitionCount = diskDescription->NumberOfPartitions;
+
+ for (j=0; j<partitionCount; j++)
+ {
+ diskPartition = &diskDescription->Partitions[j];
+
+ if ( (diskPartition->FtType == FtSet->Type)
+ && (diskPartition->FtGroup == (USHORT)FtSet->Ordinal))
+ {
+ //
+ // Found a member of the ft set being deleted on a
+ // remembered disk. Remove the partition from the
+ // remembered disk.
+ //
+
+ RtlMoveMemory( diskPartition,
+ diskPartition+1,
+ (partitionCount - j - 1) * sizeof(DISK_PARTITION)
+ );
+
+ partitionCount--;
+ j--;
+ }
+ }
+
+ if (partitionCount != diskDescription->NumberOfPartitions)
+ {
+ diskDescription->NumberOfPartitions = (USHORT)partitionCount;
+
+ size = sizeof(DISK_DESCRIPTION);
+ if (partitionCount > 1)
+ {
+ size += (partitionCount - 1) * sizeof(DISK_PARTITION);
+ }
+ RememberedDiskArray[i] = (PDISK_DESCRIPTION)Realloc(RememberedDiskArray[i], size);
+ }
+ }
+
+ if (OffLineDisksOnly)
+ {
+ return;
+ }
+
+ //
+ // First, free all members of the set
+ //
+
+ while (NULL != ftObject)
+ {
+ nextFtObject = ftObject->Next;
+ Free(ftObject);
+ ftObject = nextFtObject;
+ }
+
+ //
+ // now, remove the set from the linked list of sets.
+ //
+
+ if (FtObjectList == FtSet)
+ {
+ FtObjectList = FtSet->Next;
+ }
+ else
+ {
+ ftSetTemp = FtObjectList;
+ while (1)
+ {
+ FDASSERT(ftSetTemp);
+ if (ftSetTemp == NULL)
+ {
+ break;
+ }
+ if (ftSetTemp->Next == FtSet)
+ {
+ ftSetTemp->Next = FtSet->Next;
+ break;
+ }
+ ftSetTemp = ftSetTemp->Next;
+ }
+ }
+ Free(FtSet);
+}
+
+VOID
+FdftExtendFtObjectSet(
+ IN OUT PFT_OBJECT_SET FtSet,
+ IN OUT PREGION_DESCRIPTOR* RegionArray,
+ IN DWORD RegionCount
+ )
+/*++
+
+Routine Description:
+
+ This function adds regions to an existing FT-set.
+
+Arguments:
+
+ FtSet -- Supplies the set to extend.
+ RegionArray -- Supplies the regions to add to the set. Note
+ that these regions are updated with the FT
+ information.
+ RegionCount -- Supplies the number of regions to add.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PFT_OBJECT ftObject;
+ DWORD i;
+ DWORD startingIndex;
+
+ // Determine the starting member index for the new regions.
+ // It is the greatest of the existing member indices plus one.
+ //
+ startingIndex = 0;
+
+ for (ftObject = FtSet->Members;
+ NULL != ftObject;
+ ftObject = ftObject->Next)
+ {
+ if (ftObject->MemberIndex > startingIndex)
+ {
+ startingIndex = ftObject->MemberIndex;
+ }
+ }
+
+ startingIndex++;
+
+ // Associate the ft-set's information with each of the
+ // new regions.
+ //
+ for (i = 0; i < RegionCount; i++)
+ {
+ ftObject = (PFT_OBJECT)Malloc(sizeof(FT_OBJECT));
+
+ ftObject->Set = FtSet;
+ ftObject->MemberIndex = startingIndex + i;
+ ftObject->Next = FtSet->Members;
+ ftObject->State = Healthy;
+ FtSet->Members = ftObject;
+
+ SET_FT_OBJECT(RegionArray[i], ftObject);
+ }
+
+ FtSet->Status = FtSetExtended;
+}
+
+
+ULONG
+ActualPartitionCount(
+ IN PDISKSTATE DiskState
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk, this routine counts the number of partitions on it.
+ The number of partitions is the number of regions that appear in
+ the NT name space (ie, the maximum value of <x> in
+ \device\harddiskn\partition<x>).
+
+Arguments:
+
+ DiskState - descriptor for the disk in question.
+
+Return Value:
+
+ Partition count (may be 0).
+
+--*/
+
+{
+ ULONG i;
+ ULONG partitionCount = 0;
+ PREGION_DESCRIPTOR region;
+
+ for (i=0; i<DiskState->RegionCount; i++)
+ {
+ region = &DiskState->RegionArray[i];
+ if ((region->SysID != PARTITION_ENTRY_UNUSED)
+ && !IsExtended(region->SysID)
+ && IsRecognizedPartition(region->SysID))
+ {
+ partitionCount++;
+ }
+ }
+ return partitionCount;
+}
+
+
+PDISKSTATE
+LookUpDiskBySignature(
+ IN ULONG Signature
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will look through the disk descriptors created by the
+ fdisk back end looking for a disk with a particular signature.
+
+Arguments:
+
+ Signature - signature of disk to locate
+
+Return Value:
+
+ Pointer to disk descriptor or NULL if no disk with the given signature
+ was found.
+
+--*/
+
+{
+ ULONG diskNumber;
+ PDISKSTATE diskState;
+
+ for (diskNumber = 0; diskNumber < DiskCount; diskNumber++)
+ {
+ diskState = DiskArray[diskNumber];
+ if (diskState->Signature == Signature)
+ {
+ return diskState;
+ }
+ }
+ return NULL;
+}
+
+
+PREGION_DESCRIPTOR
+LookUpPartition(
+ IN PDISKSTATE DiskState,
+ IN LARGE_INTEGER Offset,
+ IN LARGE_INTEGER Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will look through a region descriptor array for a
+ partition with a particular length and starting offset.
+
+Arguments:
+
+ DiskState - disk on which to locate the partition
+ Offset - offset of partition on the disk to find
+ Length - size of the partition to find
+
+Return Value:
+
+ Pointer to region descriptor or NULL if no such partition on that disk
+
+--*/
+
+{
+ ULONG regionIndex;
+ ULONG maxRegion = DiskState->RegionCount;
+ PREGION_DESCRIPTOR regionDescriptor;
+ LARGE_INTEGER offset;
+ LARGE_INTEGER length;
+
+ for (regionIndex = 0; regionIndex < maxRegion; regionIndex++)
+ {
+ regionDescriptor = &DiskState->RegionArray[regionIndex];
+
+ if ((regionDescriptor->SysID != PARTITION_ENTRY_UNUSED)
+ && !IsExtended(regionDescriptor->SysID))
+ {
+ offset = FdGetExactOffset(regionDescriptor);
+ length = FdGetExactSize(regionDescriptor, FALSE);
+
+ if ( (offset.LowPart == Offset.LowPart)
+ && (offset.HighPart == Offset.HighPart)
+ && (length.LowPart == Length.LowPart)
+ && (length.HighPart == Length.HighPart))
+ {
+ return regionDescriptor;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+VOID
+AddObjectToSet(
+ IN PFT_OBJECT FtObjectToAdd,
+ IN FT_TYPE FtType,
+ IN USHORT FtGroup
+ )
+
+/*++
+
+Routine Description:
+
+ Find the FtSet for that this object belongs to and insert
+ it into the chain of members. If the set cannot be found
+ in the existing collection of sets, create a new one.
+
+Arguments:
+
+ FtObjectToAdd - the object point to be added.
+ FtType - the type of the FT set.
+ FtGroup - group for this object.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PFT_OBJECT_SET ftSet = FtObjectList;
+
+ while (NULL != ftSet)
+ {
+ if ((ftSet->Type == FtType) && (ftSet->Ordinal == FtGroup))
+ {
+ break;
+ }
+ ftSet = ftSet->Next;
+ }
+
+ if (NULL == ftSet)
+ {
+ //
+ // There is no such existing ft set. Create one.
+ //
+
+ ftSet = (PFT_OBJECT_SET)Malloc(sizeof(FT_OBJECT_SET));
+
+ ftSet->Status = FtSetHealthy;
+ ftSet->Type = FtType;
+ ftSet->Ordinal = FtGroup;
+ ftSet->Members = NULL;
+ ftSet->Next = FtObjectList;
+ ftSet->Member0 = NULL;
+ ftSet->NumberOfMembers = 0;
+
+ FtObjectList = ftSet;
+ }
+
+ FDASSERT(NULL != ftSet);
+
+ FtObjectToAdd->Next = ftSet->Members;
+ ftSet->Members = FtObjectToAdd;
+ ++ftSet->NumberOfMembers;
+ FtObjectToAdd->Set = ftSet;
+
+ if (FtObjectToAdd->MemberIndex == 0)
+ {
+ ftSet->Member0 = FtObjectToAdd;
+ }
+
+ if (FtType == StripeWithParity || FtType == Mirror)
+ {
+ // Update the set's state based on the state of the new member:
+ //
+ switch (FtObjectToAdd->State)
+ {
+ case Healthy:
+ // Doesn't change state of set.
+ break;
+
+ case Regenerating:
+ ftSet->Status = (ftSet->Status == FtSetHealthy ||
+ ftSet->Status == FtSetRegenerating)
+ ? FtSetRegenerating
+ : FtSetBroken;
+ break;
+
+ case Initializing:
+ ftSet->Status = (ftSet->Status == FtSetHealthy ||
+ ftSet->Status == FtSetInitializing)
+ ? FtSetInitializing
+ : FtSetBroken;
+ break;
+
+ default:
+ // If only one member is bad, the set is recoverable;
+ // otherwise, it's broken.
+ //
+ ftSet->Status = (ftSet->Status == FtSetHealthy)
+ ? FtSetRecoverable
+ : FtSetDisabled;
+ break;
+ }
+ }
+}
+
+
+ULONG
+InitializeFt(
+ IN BOOL DiskSignaturesCreated
+ )
+
+/*++
+
+Routine Description:
+
+ Search the disk registry information to construct the FT
+ relationships in the system.
+
+Arguments:
+
+ DiskSignaturesCreated - boolean to indicate that new disks
+ were located in the system.
+
+Return Value:
+
+ An error code if the disk registry could not be obtained.
+
+--*/
+
+{
+ ULONG disk;
+ ULONG partitionIndex;
+ ULONG partitionCount;
+ PDISK_REGISTRY diskRegistry;
+ PDISK_PARTITION diskPartition;
+ PDISK_DESCRIPTION diskDescription;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PFT_OBJECT ftObject;
+ DWORD ec;
+ BOOL configDiskChanged = FALSE;
+ BOOL configMissingDisk = FALSE;
+ BOOL configExtraDisk = FALSE;
+ BOOL anyDisksOffLine;
+
+
+ RememberedDiskArray = (PDISK_DESCRIPTION*)Malloc(0);
+ RememberedDiskCount = 0;
+
+ ec = MyDiskRegistryGet(&diskRegistry);
+ if (ec != NO_ERROR)
+ {
+ FDLOG((0, "InitializeFt: Error %u from MyDiskRegistryGet\n", ec));
+
+ return ec;
+ }
+
+ DiskHadRegistryEntry = (PULONG)Malloc(DiskCount * sizeof(ULONG));
+ memset(DiskHadRegistryEntry, 0, DiskCount * sizeof(ULONG));
+
+ diskDescription = diskRegistry->Disks;
+
+ for (disk = 0; disk < diskRegistry->NumberOfDisks; disk++)
+ {
+ //
+ // For the disk described in the registry, look up the
+ // corresponding actual disk found by the fdisk init code.
+ //
+
+ diskState = LookUpDiskBySignature(diskDescription->Signature);
+
+ if (NULL != diskState)
+ {
+ FDLOG(( 2,
+ "InitializeFt: disk w/ signature %08lx is disk #%u\n",
+ diskDescription->Signature,
+ diskState->Disk
+ ));
+
+ DiskHadRegistryEntry[diskState->Disk]++;
+
+ partitionCount = ActualPartitionCount(diskState);
+
+ if (partitionCount != diskDescription->NumberOfPartitions)
+ {
+ FDLOG(( 1,
+ "InitializeFt: partition counts for disk %08lx don't match:\n",
+ diskState->Signature));
+
+ FDLOG((1, " Count from actual disk: %u\n", partitionCount));
+ FDLOG((1, " Count from registry : %u\n", diskDescription->NumberOfPartitions));
+
+ configDiskChanged = TRUE;
+ }
+ }
+ else
+ {
+ //
+ // there's an entry in the registry that does not have a
+ // real disk to match. Remember this disk; if it has any
+ // FT partitions, we also want to display a message telling
+ // the user that something's missing.
+ //
+ FDLOG((1, "InitializeFt: Entry for disk w/ signature %08lx has no matching real disk\n", diskDescription->Signature));
+
+ for (partitionIndex = 0;
+ partitionIndex < diskDescription->NumberOfPartitions;
+ partitionIndex++)
+ {
+ diskPartition = &diskDescription->Partitions[partitionIndex];
+ if (diskPartition->FtType != NotAnFtMember)
+ {
+ // This disk has an FT partition, so Windisk will
+ // want to tell the user that some disks are missing.
+ //
+ configMissingDisk = TRUE;
+ break;
+ }
+ }
+
+ FdpRememberDisk(diskDescription);
+ }
+
+ for (partitionIndex = 0;
+ partitionIndex < diskDescription->NumberOfPartitions;
+ partitionIndex++)
+ {
+ diskPartition = &diskDescription->Partitions[partitionIndex];
+
+ regionDescriptor = NULL;
+
+ if (NULL != diskState)
+ {
+ regionDescriptor = LookUpPartition(diskState,
+ diskPartition->StartingOffset,
+ diskPartition->Length
+ );
+ }
+
+ //
+ // At this point one of three conditions exists.
+ //
+ // 1. There is no disk related to this registry information
+ // diskState == NULL && regionDescriptor == NULL
+ // 2. There is a disk, but no partition related to this information
+ // diskState != NULL && regionDescriptor == NULL
+ // 3. There is a disk and a partition related to this information
+ // diskState != NULL && regionDescriptor != NULL
+ //
+ // In any of these conditions, if the registry entry is part
+ // of an FT set and FT object must be created.
+ //
+ // that corresponds to a partition's entry in the
+ // disk registry database.
+ //
+
+ if (diskPartition->FtType != NotAnFtMember)
+ {
+ ftObject = (PFT_OBJECT)Malloc(sizeof(FT_OBJECT));
+ ftObject->Next = NULL;
+ ftObject->Set = NULL;
+ ftObject->MemberIndex = diskPartition->FtMember;
+ ftObject->State = diskPartition->FtState;
+
+ // if a partition was actually found there will be a
+ // regionDescriptor that needs to be updated.
+
+ if (regionDescriptor && regionDescriptor->PersistentData)
+ {
+ FT_SET_STATUS setState;
+ ULONG numberOfMembers;
+
+ SET_FT_OBJECT(regionDescriptor, ftObject);
+
+ // Before the drive letter is moved into the region
+ // data, be certain that the FT volume exists at this
+ // drive letter.
+
+ LowFtVolumeStatusByLetter(diskPartition->DriveLetter,
+ &setState,
+ &numberOfMembers);
+
+ // If the numberOfMembers gets set to 1 then
+ // this letter is not the letter for the FT set,
+ // but rather a default letter assigned because the
+ // FT sets letter could not be assigned.
+
+ if (numberOfMembers > 1)
+ {
+ PERSISTENT_DATA(regionDescriptor)->DriveLetter = diskPartition->DriveLetter;
+ }
+ }
+ else
+ {
+ // There is no region for this partition
+ // so update the set state.
+
+ ftObject->State = Orphaned;
+ }
+
+ //
+ // Now place the ft object in the correct set,
+ // creating the set if necessary.
+ //
+
+ AddObjectToSet(
+ ftObject,
+ diskPartition->FtType,
+ diskPartition->FtGroup);
+
+ MaintainOrdinalTables(
+ diskPartition->FtType,
+ (ULONG) diskPartition->FtGroup);
+ }
+ }
+
+ diskDescription = (PDISK_DESCRIPTION)&diskDescription->Partitions[diskDescription->NumberOfPartitions];
+ }
+
+ Free(diskRegistry);
+
+ //
+ // Check to see if every disk found by the fdisk back end has a
+ // corresponding registry entry.
+ //
+
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ if (DiskArray[disk]->OffLine)
+ {
+ continue;
+ }
+
+ if (!DiskHadRegistryEntry[disk] && !IsRemovable(disk))
+ {
+ //
+ // a real disk does not have a matching registry entry.
+ //
+
+ FDLOG((1, "InitializeFt: Disk %u does not have a registry entry (disk sig = %08lx)\n", disk, DiskArray[disk]->Signature));
+
+ configExtraDisk = TRUE;
+ }
+ }
+
+ //
+ // Determine whether any disks are off line
+ //
+
+ anyDisksOffLine = FALSE;
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ if (DiskArray[disk]->OffLine)
+ {
+ anyDisksOffLine = TRUE;
+ break;
+ }
+ }
+
+ if (configMissingDisk || anyDisksOffLine)
+ {
+ WarningDialog(MSG_CONFIG_MISSING_DISK);
+ }
+
+ if (configDiskChanged)
+ {
+ RegistryChanged = TRUE;
+ WarningDialog(MSG_CONFIG_DISK_CHANGED);
+ }
+
+ if (configExtraDisk || DiskSignaturesCreated)
+ {
+ BOOL badConfigSet = FALSE;
+
+ WarningDialog(MSG_CONFIG_EXTRA_DISK);
+
+ //
+ // Update ft signature on each disk for which a new signature
+ // was created. and update registry for each disk with
+ // DiskHadRegistryEntry[Disk] == 0.
+ //
+
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ BOOL b1 = TRUE;
+ BOOL b2 = TRUE;
+
+ if (DiskArray[disk]->OffLine)
+ {
+ continue;
+ }
+
+ if (DiskArray[disk]->SigWasCreated)
+ {
+ TCHAR name[100];
+ wsprintf(name, DiskN, disk);
+ if (IDYES == ConfirmationDialog(
+ MSG_NO_SIGNATURE,
+ MB_ICONEXCLAMATION | MB_YESNO,
+ name))
+ {
+ b1 = (MasterBootCode(disk, DiskArray[disk]->Signature, TRUE, TRUE) == NO_ERROR);
+ }
+ else
+ {
+ DiskArray[disk]->OffLine = TRUE;
+ continue;
+ }
+ }
+
+ if (!DiskHadRegistryEntry[disk])
+ {
+ ULONG size;
+
+ size = FdpDetermineDiskDescriptionSize(DiskArray[disk]);
+
+ diskDescription = (PDISK_DESCRIPTION)Malloc(size);
+
+ FdpConstructDiskDescription(DiskArray[disk], diskDescription);
+
+ FDLOG((2,
+ "InitializeFt: Adding new disk %08lx to registry.\n",
+ diskDescription->Signature));
+ LOG_ONE_DISK_REGISTRY_DISK_ENTRY("InitializeFt", diskDescription);
+
+ b2 = (EC(DiskRegistryAddNewDisk(diskDescription)) == NO_ERROR);
+
+ Free(diskDescription);
+ }
+
+ if (!(b1 && b2))
+ {
+ badConfigSet = TRUE;
+ }
+ }
+
+ if (badConfigSet)
+ {
+ ErrorDialog(MSG_BAD_CONFIG_SET);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+
+BOOLEAN
+NewConfigurationRequiresFt(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Search the diskstate and region arrays to determine if a single
+ FtDisk element (i.e. stripe, stripe set with parity, mirror or
+ volume set) is contained in the configuration.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the new configuration requires the FtDisk driver.
+ FALSE otherwise.
+
+--*/
+
+{
+ ULONG disk,
+ region;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+
+ // Look at all disks in the system.
+
+ for (disk = 0; disk < DiskCount; disk++)
+ {
+ diskState = DiskArray[disk];
+ if (diskState->OffLine || IsDiskRemovable[disk])
+ {
+ continue;
+ }
+
+ // Check each region on the disk.
+
+ for (region = 0; region < diskState->RegionCount; region++)
+ {
+ regionDescriptor = &diskState->RegionArray[region];
+ if ( (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED)
+ && !IsExtended(regionDescriptor->SysID)
+ && IsRecognizedPartition(regionDescriptor->SysID))
+ {
+ // If a single region has an FT Object, then FT
+ // is required and the search may be stopped.
+
+ if (NULL != GET_FT_OBJECT(regionDescriptor))
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ // no FtObject was found.
+
+ return FALSE;
+}
+
+
+
+ULONG
+SaveFt(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine walks all of the internal structures and creates the
+ interface structure for the DiskRegistry interface.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ success/failure code. NO_ERROR is success.
+
+--*/
+
+{
+ ULONG i;
+ ULONG disk;
+ ULONG partitionIndex;
+ ULONG size;
+ PDISK_REGISTRY diskRegistry;
+ PDISK_DESCRIPTION diskDescription;
+ PBYTE start, end;
+ DWORD ec;
+ ULONG offLineDiskCount;
+ ULONG removableDiskCount;
+
+ //
+ // First count partitions and disks so we can allocate a structure
+ // of the correct size.
+ //
+
+ size = sizeof(DISK_REGISTRY) - sizeof(DISK_DESCRIPTION);
+ offLineDiskCount = 0;
+ removableDiskCount = 0;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ if (DiskArray[i]->OffLine)
+ {
+ offLineDiskCount++;
+ }
+ else if (IsDiskRemovable[i])
+ {
+ removableDiskCount++;
+ }
+ else
+ {
+ size += FdpDetermineDiskDescriptionSize(DiskArray[i]);
+ }
+ }
+
+ //
+ // Account for remembered disks.
+ //
+
+ size += RememberedDiskCount * sizeof(DISK_DESCRIPTION);
+ for (i=0; i<RememberedDiskCount; i++)
+ {
+ if (RememberedDiskArray[i]->NumberOfPartitions > 1)
+ {
+ size += (RememberedDiskArray[i]->NumberOfPartitions - 1) * sizeof(DISK_PARTITION);
+ }
+ }
+
+ diskRegistry = (PDISK_REGISTRY)Malloc(size);
+
+ diskRegistry->NumberOfDisks = (USHORT)( DiskCount
+ + RememberedDiskCount
+ - offLineDiskCount
+ - removableDiskCount
+ );
+ diskRegistry->ReservedShort = 0;
+
+ diskDescription = diskRegistry->Disks;
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ if (DiskArray[disk]->OffLine || IsDiskRemovable[disk])
+ {
+ continue;
+ }
+
+ partitionIndex = FdpConstructDiskDescription(DiskArray[disk], diskDescription);
+
+ diskDescription = (PDISK_DESCRIPTION)&diskDescription->Partitions[partitionIndex];
+ }
+
+ //
+ // Toss in remembered disks.
+ //
+
+ for (i=0; i<RememberedDiskCount; i++)
+ {
+ // Compute the beginning and end of this remembered disk's
+ // Disk Description:
+ //
+ partitionIndex = RememberedDiskArray[i]->NumberOfPartitions;
+ start = (PBYTE)RememberedDiskArray[i];
+ end = (PBYTE)&(RememberedDiskArray[i]->Partitions[partitionIndex]);
+
+ RtlMoveMemory(diskDescription, RememberedDiskArray[i], end - start);
+
+ diskDescription = (PDISK_DESCRIPTION)&diskDescription->Partitions[partitionIndex];
+ }
+
+ LOG_DISK_REGISTRY("SaveFt", diskRegistry);
+
+ ec = EC(DiskRegistrySet(diskRegistry));
+
+ Free(diskRegistry);
+
+ if (ec == NO_ERROR)
+ {
+ FdpInitializeMirrors();
+ }
+
+ return ec;
+}
+
+
+ULONG
+FdpDetermineDiskDescriptionSize(
+ PDISKSTATE DiskState
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes a pointer to a disk and determines how much
+ memory is needed to contain the description of the disk by
+ counting the number of partitions on the disk and multiplying
+ the appropriate counts by the appropriate size of the structures.
+
+Arguments:
+
+ DiskState - the disk in question.
+
+Return Value:
+
+ The memory size needed to contain all of the information on the disk.
+
+--*/
+
+{
+ ULONG partitionCount;
+ ULONG size;
+
+ if (DiskState->OffLine)
+ {
+ return 0;
+ }
+
+ size = sizeof(DISK_DESCRIPTION);
+ partitionCount = ActualPartitionCount(DiskState);
+ size += (partitionCount ? partitionCount-1 : 0) * sizeof(DISK_PARTITION);
+
+ return size;
+}
+
+
+ULONG
+FdpConstructDiskDescription(
+ IN PDISKSTATE DiskState,
+ OUT PDISK_DESCRIPTION DiskDescription
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk state pointer as input, construct the FtRegistry
+ structure to describe the partitions on the disk.
+
+Arguments:
+
+ DiskState - the disk for which to construct the information
+ DiskDescription - the memory location where the registry
+ structure is to be created.
+
+Return Value:
+
+ The number of partitions described in the DiskDescription.
+
+--*/
+
+{
+ ULONG partitionIndex;
+ ULONG regionIndex;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PDISK_PARTITION diskPartition;
+ WCHAR driveLetter;
+ BOOLEAN assignDriveLetter;
+ PFT_OBJECT ftObject;
+ PFT_OBJECT_SET ftSet;
+
+ partitionIndex = 0;
+
+ for (regionIndex = 0; regionIndex < DiskState->RegionCount; regionIndex++)
+ {
+ regionDescriptor = &DiskState->RegionArray[regionIndex];
+
+ if ( (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED)
+ && !IsExtended(regionDescriptor->SysID)
+ && IsRecognizedPartition(regionDescriptor->SysID))
+ {
+ diskPartition = &DiskDescription->Partitions[partitionIndex++];
+
+ diskPartition->StartingOffset = FdGetExactOffset(regionDescriptor);
+ diskPartition->Length = FdGetExactSize(regionDescriptor, FALSE);
+ diskPartition->LogicalNumber = (USHORT)regionDescriptor->PartitionNumber;
+
+ driveLetter = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+ switch (driveLetter)
+ {
+ case NO_DRIVE_LETTER_YET:
+ assignDriveLetter = TRUE;
+ driveLetter = L'\0';
+ break;
+
+ case NO_DRIVE_LETTER_EVER:
+ assignDriveLetter = FALSE;
+ driveLetter = L'\0';
+ break;
+
+ default:
+ assignDriveLetter = TRUE;
+ break;
+ }
+
+ diskPartition->DriveLetter = (UCHAR)driveLetter;
+ diskPartition->FtLength.LowPart = 0;
+ diskPartition->FtLength.HighPart = 0;
+ diskPartition->ReservedTwoLongs[0] = 0;
+ diskPartition->ReservedTwoLongs[1] = 0;
+ diskPartition->Modified = TRUE;
+ diskPartition->ReservedChars[0] = 0;
+ diskPartition->ReservedChars[1] = 0;
+ diskPartition->ReservedChars[2] = 0;
+
+ if (NULL != (ftObject = GET_FT_OBJECT(regionDescriptor)))
+ {
+ ftSet = ftObject->Set;
+
+#if 0
+
+// need to do something here, but currently this does not work.
+
+ PREGION_DESCRIPTOR tmpDescriptor;
+ STATUS_CODE status;
+ FT_SET_STATUS setState;
+ ULONG numberOfMembers;
+
+ tmpDescriptor = LocateRegionForFtObject(ftSet->Member0);
+
+ // Only update status if member zero is present.
+ // otherwise the status is know to be Orphaned or
+ // needs regeneration.
+
+ if (tmpDescriptor)
+ {
+ // If the partition number is zero, then this set
+ // has not been committed to the disk yet. Only
+ // update status for existing sets.
+
+ if ( (0 != tmpDescriptor->PartitionNumber)
+ && (ftSet->Status != FtSetNew)
+ && (ftSet->Status != FtSetNewNeedsInitialization))
+ {
+ status = LowFtVolumeStatus(tmpDescriptor->Disk,
+ tmpDescriptor->PartitionNumber,
+ &setState,
+ &numberOfMembers);
+ if (status == OK_STATUS)
+ {
+ if (ftSet->Status != setState)
+ {
+ // Problem here - the FT driver has
+ // updated the status of the set after
+ // windisk last got the status. Need
+ // to restart the process of building
+ // the FT information after updating
+ // the set to the new state.
+
+ FdftUpdateFtObjectSet(ftSet, setState);
+
+ // now recurse and start over
+
+ status = FdpConstructDiskDescription(
+ DiskState,
+ DiskDescription);
+ return status;
+ }
+ }
+ }
+ }
+#endif
+
+ diskPartition->FtState = ftObject->State;
+ diskPartition->FtType = ftSet->Type;
+ diskPartition->FtGroup = (USHORT)ftSet->Ordinal;
+ diskPartition->FtMember = (USHORT)ftObject->MemberIndex;
+ if (assignDriveLetter && (ftObject == ftObject->Set->Member0))
+ {
+ diskPartition->AssignDriveLetter = TRUE;
+ }
+ else
+ {
+ diskPartition->AssignDriveLetter = FALSE;
+ }
+ }
+ else
+ {
+ diskPartition->FtState = Healthy;
+ diskPartition->FtType = NotAnFtMember;
+ diskPartition->FtGroup = (USHORT)(-1);
+ diskPartition->FtMember = 0;
+ diskPartition->AssignDriveLetter = assignDriveLetter;
+ }
+ }
+ }
+
+ DiskDescription->NumberOfPartitions = (USHORT)partitionIndex;
+ DiskDescription->Signature = DiskState->Signature;
+ DiskDescription->ReservedShort = 0;
+
+ return partitionIndex;
+}
+
+
+VOID
+FdpRememberDisk(
+ IN PDISK_DESCRIPTION DiskDescription
+ )
+
+/*++
+
+Routine Description:
+
+ Make a copy of a registry disk description structure for later use.
+
+Arguments:
+
+ DiskDescription - supplies pointer to the registry descriptor for
+ the disk in question.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PDISK_DESCRIPTION diskDescription;
+ ULONG size;
+
+ // Only bother remembering disks with at least one partition.
+ //
+ if (DiskDescription->NumberOfPartitions == 0)
+ {
+ return;
+ }
+
+ //
+ // Compute the size of the structure
+ //
+
+ size = sizeof(DISK_DESCRIPTION);
+ if (DiskDescription->NumberOfPartitions > 1)
+ {
+ size += (DiskDescription->NumberOfPartitions - 1) * sizeof(DISK_PARTITION);
+ }
+
+ diskDescription = (PDISK_DESCRIPTION)Malloc(size);
+ RtlMoveMemory(diskDescription, DiskDescription, size);
+
+ RememberedDiskArray = (PDISK_DESCRIPTION*)Realloc(
+ RememberedDiskArray,
+ (RememberedDiskCount+1) * sizeof(PDISK_DESCRIPTION)
+ );
+
+ RememberedDiskArray[RememberedDiskCount++] = diskDescription;
+
+ FDLOG((2,
+ "FdpRememberDisk: remembered disk %08lx, remembered count = %u\n",
+ diskDescription->Signature,
+ RememberedDiskCount));
+}
+
+
+VOID
+FdpInitializeMirrors(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ For each existing partition that was mirrored by the user during this
+ Disk Administrator session, call the FT driver to register initialization
+ of the mirror (ie, cause the primary to be copied to the secondary).
+ Perform a similar initialization for each stripe set with parity created
+ by the user.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+
+ //
+ // Look through the list of FT sets for mirrored pairs and parity stripes
+ //
+
+ for (ftSet = FtObjectList; NULL != ftSet; ftSet = ftSet->Next)
+ {
+ //
+ // If the set needs initialization, or was recovered,
+ // call the FT driver.
+ //
+
+ switch (ftSet->Status)
+ {
+ case FtSetNewNeedsInitialization:
+
+ DiskRegistryInitializeSet((USHORT)ftSet->Type,
+ (USHORT)ftSet->Ordinal);
+ ftSet->Status = FtSetInitializing;
+ break;
+
+ case FtSetRecovered:
+
+ //
+ // Find the member that needs to be addressed.
+ //
+
+ for (ftObject = ftSet->Members;
+ NULL != ftObject;
+ ftObject=ftObject->Next)
+ {
+ if (ftObject->State == Regenerating)
+ {
+ break;
+ }
+ }
+
+ DiskRegistryRegenerateSet((USHORT)ftSet->Type,
+ (USHORT)ftSet->Ordinal,
+ (USHORT)ftObject->MemberIndex);
+ ftSet->Status = FtSetRegenerating;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
diff --git a/private/utils/windisk/src/ft.hxx b/private/utils/windisk/src/ft.hxx
new file mode 100644
index 000000000..30094ecc2
--- /dev/null
+++ b/private/utils/windisk/src/ft.hxx
@@ -0,0 +1,67 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ft.hxx
+//
+// Contents: Declarations for FT support routines for Disk Administrator
+//
+// History: 15-Nov-91 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FT_HXX__
+#define __FT_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+DWORD
+FdftNextOrdinal(
+ IN FT_TYPE FtType
+ );
+
+ULONG
+InitializeFt(
+ IN BOOL DiskSignaturesCreated
+ );
+
+BOOLEAN
+NewConfigurationRequiresFt(
+ VOID
+ );
+
+ULONG
+SaveFt(
+ VOID
+ );
+
+VOID
+FdftCreateFtObjectSet(
+ IN FT_TYPE FtType,
+ IN PREGION_DESCRIPTOR* RegionArray,
+ IN DWORD RegionCount,
+ IN FT_SET_STATUS Status
+ );
+
+BOOL
+FdftUpdateFtObjectSet(
+ IN PFT_OBJECT_SET FtSet,
+ IN FT_SET_STATUS SetState
+ );
+
+VOID
+FdftDeleteFtObjectSet(
+ IN PFT_OBJECT_SET FtSet,
+ IN BOOL OffLineDisksOnly
+ );
+
+
+VOID
+FdftExtendFtObjectSet(
+ IN OUT PFT_OBJECT_SET FtSet,
+ IN OUT PREGION_DESCRIPTOR* RegionArray,
+ IN DWORD RegionCount
+ );
+
+#endif // __FT_HXX__
diff --git a/private/utils/windisk/src/ftreg.cxx b/private/utils/windisk/src/ftreg.cxx
new file mode 100644
index 000000000..20f83d29c
--- /dev/null
+++ b/private/utils/windisk/src/ftreg.cxx
@@ -0,0 +1,1329 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ftreg.cxx
+//
+// Contents: Registry calls related to fault tolerance
+//
+// History: 2-Jan-92 TedM Created
+// 1-Feb-94 BobRi Handle missing floppy disk on registry
+// save/restore
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdlib.h>
+#include <util.hxx>
+
+#include "dlgs.hxx"
+#include "ftreg.h"
+#include "ftreg.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+// attempt to avoid conflict
+
+#define TEMP_KEY_NAME TEXT("xzss3___$$Temp$Hive$$___")
+
+#define DISK_KEY_NAME TEXT("DISK")
+#define DISK_VALUE_NAME TEXT("Information")
+
+
+
+LONG
+FdpLoadHiveIntoRegistry(
+ IN LPTSTR HiveFilename
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the contents of a given hive file into the registry,
+ rooted at a temporary key in HKEY_LOCAL_MACHINE.
+
+Arguments:
+
+ HiveFilename - supplies filename of the hive to be loaded into
+ the registry
+
+Return Value:
+
+ Windows error code.
+
+--*/
+
+{
+ NTSTATUS status;
+ BOOLEAN oldPrivState;
+ LONG ec;
+
+ //
+ // Attempt to get restore privilege
+ //
+
+ status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
+ TRUE,
+ FALSE,
+ &oldPrivState);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError(status);
+ }
+
+ //
+ // Load the hive into our registry
+ //
+
+ ec = RegLoadKey(HKEY_LOCAL_MACHINE, TEMP_KEY_NAME, HiveFilename);
+
+ //
+ // Restore old privilege if necessary
+ //
+
+ if (!oldPrivState)
+ {
+ RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
+ FALSE,
+ FALSE,
+ &oldPrivState);
+ }
+
+ return ec;
+}
+
+
+LONG
+FdpUnloadHiveFromRegistry(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine removes a tree (previously loaded with
+ FdpLoadHiveIntoRegistry) from the temporary key in HKEY_LOCAL_MACHINE.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Windows error code.
+
+--*/
+
+{
+ NTSTATUS status;
+ BOOLEAN oldPrivState;
+ LONG ec;
+
+ //
+ // Attempt to get restore privilege
+ //
+
+ status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
+ TRUE,
+ FALSE,
+ &oldPrivState);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError(status);
+ }
+
+ //
+ // Unload the hive from our registry
+ //
+
+ ec = RegUnLoadKey(HKEY_LOCAL_MACHINE, TEMP_KEY_NAME);
+
+ //
+ // Restore old privilege if necessary
+ //
+
+ if (!oldPrivState)
+ {
+ RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE,
+ FALSE,
+ FALSE,
+ &oldPrivState);
+ }
+
+ return ec;
+}
+
+
+
+LONG
+FdpGetDiskInfoFromKey(
+ IN LPTSTR RootKeyName,
+ OUT PVOID* DiskInfo,
+ OUT PULONG DiskInfoSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine pulls the binary blob containing disk ft, drive letter,
+ and layout information out of a given registry key.
+
+ The info is found in HKEY_LOCAL_MACHINE, <RootKeyName>\DISK:Information.
+
+Arguments:
+
+ RootKeyName - name of the subkey of HKEY_LOCAL_MACHINE that is to
+ contain the DISK key.
+
+ DiskInfo - receives a pointer to a buffer containing the disk info.
+
+ DiskInfoSize - receives size of the disk buffer.
+
+Return Value:
+
+ Windows error code. If NO_ERROR, DiskInfo and DiskInfoSize are
+ filled in, and it is the caller's responsibility to free the buffer
+ when it is finished (via LocalFree()).
+
+--*/
+
+{
+ LONG ec;
+ HKEY hkeyDisk;
+ ULONG bufferSize;
+ ULONG valueType;
+ PBYTE buffer;
+ LPTSTR diskKeyName;
+
+ //
+ // Form the name of the DISK key
+ //
+
+ diskKeyName = (LPTSTR)LocalAlloc( LMEM_FIXED,
+ ( lstrlen(RootKeyName)
+ + lstrlen(DISK_KEY_NAME)
+ + 2 // the \ and nul
+ )
+ * sizeof(TCHAR)
+ );
+
+ if (diskKeyName == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ lstrcpy(diskKeyName, RootKeyName);
+ lstrcat(diskKeyName, TEXT("\\"));
+ lstrcat(diskKeyName, DISK_KEY_NAME);
+
+ //
+ // Open the DISK key.
+ //
+
+ ec = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ diskKeyName,
+ REG_OPTION_RESERVED,
+ KEY_READ,
+ &hkeyDisk);
+
+ if (ec != NO_ERROR)
+ {
+ goto CleanUp2;
+ }
+
+ //
+ // Determine how large we need the buffer to be
+ //
+
+ ec = RegQueryValueEx(hkeyDisk,
+ DISK_VALUE_NAME,
+ NULL,
+ &valueType,
+ NULL,
+ &bufferSize);
+
+ if ((ec != NO_ERROR) && (ec != ERROR_MORE_DATA))
+ {
+ goto CleanUp1;
+ }
+
+ //
+ // Allocate a buffer of appropriate size
+ //
+
+ buffer = (PBYTE)LocalAlloc(LMEM_FIXED, bufferSize);
+ if (buffer == NULL)
+ {
+ ec = ERROR_NOT_ENOUGH_MEMORY;
+ goto CleanUp1;
+ }
+
+ //
+ // Query the data
+ //
+
+ ec = RegQueryValueEx(hkeyDisk,
+ DISK_VALUE_NAME,
+ NULL,
+ &valueType,
+ buffer,
+ &bufferSize);
+ if (ec != NO_ERROR)
+ {
+ LocalFree(buffer);
+ goto CleanUp1;
+ }
+
+ *DiskInfo = (PVOID)buffer;
+ *DiskInfoSize = bufferSize;
+
+ CleanUp1:
+
+ RegCloseKey(hkeyDisk);
+
+ CleanUp2:
+
+ LocalFree(diskKeyName);
+
+ return ec;
+}
+
+
+LONG
+FdpGetDiskInfoFromHive(
+ IN LPTSTR HiveFilename,
+ OUT PVOID *DiskInfo,
+ OUT PULONG DiskInfoSize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine pulls the binary blob containing disk ft, drive letter,
+ and layout information out of a given registry hive, which must be
+ a file in an alternate NT tree (ie, can't be an active hive).
+
+ The info is found in \DISK:Information within the hive.
+
+Arguments:
+
+ HiveFilename - supplies filename of hive
+
+ DiskInfo - receives a pointer to a buffer containing the disk info.
+
+ DiskInfoSize - receives size of the disk buffer.
+
+Return Value:
+
+ Windows error code. If NO_ERROR, DiskInfo and DiskInfoSize are
+ filled in, and it is the caller's responsibility to free the buffer
+ when it is finished (via LocalFree()).
+
+--*/
+
+{
+ ULONG windowsError;
+
+ windowsError = FdpLoadHiveIntoRegistry(HiveFilename);
+ if (windowsError == NO_ERROR)
+ {
+ windowsError = FdpGetDiskInfoFromKey(TEMP_KEY_NAME,DiskInfo,DiskInfoSize);
+ FdpUnloadHiveFromRegistry();
+ }
+
+ return windowsError;
+}
+
+
+
+
+LONG
+FdTransferOldDiskInfoToRegistry(
+ IN LPTSTR HiveFilename
+ )
+
+/*++
+
+Routine Description:
+
+ This routine transfers disk configuration from a given hive file
+ (which should be an inactive system hive) to the current registry.
+
+Arguments:
+
+ HiveFilename - supplies filename of source hive
+
+Return Value:
+
+ Windows error code.
+
+--*/
+
+{
+ LONG ec;
+ PVOID diskInfo;
+ ULONG diskInfoSize;
+ HKEY hkeyDisk;
+
+
+ //
+ // Load up the hive and pull the disk info from it.
+ //
+
+ ec = FdpGetDiskInfoFromHive(HiveFilename, &diskInfo, &diskInfoSize);
+ if (ec != NO_ERROR)
+ {
+ return ec;
+ }
+
+ //
+ // Propogate the disk info into the current registry.
+ //
+ // Start by opening HKEY_LOCAL_MACHINE, System\DISK
+ //
+
+ ec = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("System\\") DISK_KEY_NAME,
+ REG_OPTION_RESERVED,
+ KEY_WRITE,
+ &hkeyDisk);
+
+ if (ec != NO_ERROR)
+ {
+ LocalFree(diskInfo);
+ return ec;
+ }
+
+ //
+ // Set the Information value in the DISK key.
+ //
+
+ ec = RegSetValueEx(hkeyDisk,
+ DISK_VALUE_NAME,
+ 0,
+ REG_BINARY,
+ (PBYTE)diskInfo,
+ diskInfoSize);
+
+ RegCloseKey(hkeyDisk);
+
+ LocalFree(diskInfo);
+
+ return ec;
+}
+
+
+typedef struct _STRING_LIST_NODE
+{
+ struct _STRING_LIST_NODE *Next;
+ LPTSTR String;
+} STRING_LIST_NODE, *PSTRING_LIST_NODE;
+
+PSTRING_LIST_NODE FoundDirectoryList;
+ULONG FoundDirectoryCount;
+TCHAR Pattern[MAX_PATH + 1];
+CHAR AnsiPattern[MAX_PATH + 1];
+WIN32_FIND_DATA FindData;
+HWND hwndStatus;
+BOOLEAN ScanDrive[26];
+BOOLEAN UserCancelled;
+
+typedef
+BOOL
+(*PFOUND_HIVE_ROUTINE)(
+ IN LPTSTR Directory
+ );
+
+VOID
+ProcessPendingMessages(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Preprocess messages.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ MSG msg;
+
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ DispatchMessage(&msg);
+ }
+}
+
+
+TCHAR ConfigRegistryPath[] = TEXT("\\system32\\config\\system");
+
+
+BOOL
+FdpSearchTreeForSystemHives(
+ IN LPTSTR CurrentDirectory,
+ IN PFOUND_HIVE_ROUTINE FoundHiveRoutine,
+ IN HWND hdlg
+ )
+
+/*++
+
+Routine Description:
+
+ Search an entire directory tree for system and system.alt hive files.
+ When found, call a callback function with the directory in which
+ system32\config\system[.alt] was found, and the full path of the hive
+ file.
+
+ The root directory is not included in the search.
+
+ The top-level call to this function should have a current directory
+ like "C:." (ie, no slash for the root directory).
+
+Arguments:
+
+ CurrentDirectory - supplies current directory search path
+
+Return Value:
+
+ FALSE if error (callback function returned FALSE when we found an entry).
+
+--*/
+
+{
+ HANDLE findHandle;
+ TCHAR newDirectory[MAX_PATH+1];
+ BOOL found = FALSE;
+
+ //
+ // Iterate through the current directory, looking for subdirectories.
+ //
+
+ lstrcpy(Pattern, CurrentDirectory);
+ lstrcat(Pattern, TEXT("\\*"));
+ findHandle = FindFirstFile(Pattern, &FindData);
+
+ if (findHandle != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ ProcessPendingMessages();
+ if (UserCancelled)
+ {
+ return FALSE;
+ }
+
+ //
+ // If the current match is not a directory then skip it.
+ //
+
+ if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ || !lstrcmp(FindData.cFileName, TEXT("."))
+ || !lstrcmp(FindData.cFileName, TEXT("..")))
+ {
+ continue;
+ }
+
+ found = FALSE;
+
+ //
+ // Form the name of the file we are looking for
+ // [<currentdirectory>\<match>\system32\config\system]
+ //
+
+ lstrcpy(Pattern, CurrentDirectory);
+ lstrcat(Pattern, TEXT("\\"));
+ lstrcat(Pattern, FindData.cFileName);
+
+ lstrcpy(newDirectory, Pattern);
+
+ // Don't decend into the directory unless the path to the
+ // hive.alt name is within MAX_PATH length.
+
+ if (lstrlen(newDirectory) + lstrlen(ConfigRegistryPath) + 4
+ < MAX_PATH)
+ // 4 = length of ".alt"
+ {
+ SetDlgItemText(hdlg, IDC_SIMPLE_TEXT_LINE, newDirectory);
+
+ lstrcat(Pattern, ConfigRegistryPath);
+
+ if (GetFileAttributes(Pattern) != -1)
+ {
+ found = TRUE;
+ }
+
+ //
+ // Also check for a system.alt file there
+ //
+
+ lstrcat(Pattern, TEXT(".alt"));
+
+ if (GetFileAttributes(Pattern) != -1)
+ {
+ found = TRUE;
+ }
+
+ if (found)
+ {
+ if (!FoundHiveRoutine(newDirectory))
+ {
+ return FALSE;
+ }
+ }
+
+ //
+ // Descend into the directory we just found
+ //
+
+ if (!FdpSearchTreeForSystemHives(newDirectory, FoundHiveRoutine, hdlg))
+ {
+ return FALSE;
+ }
+ }
+ } while (FindNextFile(findHandle, &FindData));
+
+ FindClose(findHandle);
+ }
+
+ return TRUE;
+}
+
+
+BOOL
+FdpFoundHiveCallback(
+ IN LPTSTR Directory
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called when a directory containing a system hive
+ has been located. If all goes well (allocate memory and the like)
+ this routine will save the directory name in a list for later use.
+ NOTE: No checks are made on the directory name being greater in
+ length than MAX_PATH. It is the responsibility of the caller to
+ insure that this is true.
+
+Arguments:
+
+ Directory - the pointer to the character string for the directory
+ where a hive has been located.
+
+Return Value:
+
+ TRUE - did something with it.
+ FALSE - did not save the directory.
+
+--*/
+
+{
+ TCHAR windowsDir[MAX_PATH + 1];
+ PSTRING_LIST_NODE dirItem;
+ LPTSTR p;
+
+ //
+ // If this is the current windows directory, skip it.
+ //
+
+ GetWindowsDirectory(windowsDir, ARRAYLEN(windowsDir));
+
+ if (0 == lstrcmpi(Directory, windowsDir))
+ {
+ return TRUE;
+ }
+
+ //
+ // Save the directory away in a linked list
+ //
+
+ dirItem = (PSTRING_LIST_NODE)LocalAlloc(
+ LMEM_FIXED | LMEM_ZEROINIT,
+ sizeof(STRING_LIST_NODE));
+ if (dirItem == NULL)
+ {
+ return FALSE;
+ }
+
+ p = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(Directory)+1) * sizeof(TCHAR));
+ if (p == NULL)
+ {
+ LocalFree(dirItem);
+ return FALSE;
+ }
+
+ dirItem->String = p;
+ lstrcpy(p, Directory);
+
+ // Update the global chain of found directories
+
+ dirItem->Next = FoundDirectoryList;
+ FoundDirectoryList = dirItem;
+
+ FoundDirectoryCount++;
+
+ return TRUE;
+}
+
+
+VOID
+FdpFreeDirectoryList(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Go through the list of directories containing system hives and
+ free the entries.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PSTRING_LIST_NODE n;
+ PSTRING_LIST_NODE p = FoundDirectoryList;
+
+ while (p)
+ {
+ n = p->Next;
+ if (p->String)
+ {
+ LocalFree(p->String);
+ }
+ LocalFree(p);
+ p = n;
+ }
+
+ FoundDirectoryCount = 0;
+ FoundDirectoryList = NULL;
+}
+
+
+BOOL CALLBACK
+FdpScanningDirsDlgProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Display the "scanning" dialog, then when the IDLE message arrives
+ process all drive letters and search for system hives.
+
+Arguments:
+
+ Windows dialog proc
+
+Return Value:
+
+ Windows dialog proc
+
+--*/
+
+{
+ TCHAR letterColon[3];
+ TCHAR letter;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+
+ CenterDialogInFrame(hwnd);
+ break;
+
+ case WM_ENTERIDLE:
+
+ //
+ // Sent to us by the main window after the dialog is displayed.
+ // Perform the search here.
+ //
+ ConfigurationSearchIdleTrigger = FALSE;
+
+ UserCancelled = FALSE;
+
+ lstrcpy(letterColon, TEXT("?:"));
+ for (letter = TEXT('A'); letter <= TEXT('Z'); letter++)
+ {
+ if (!ScanDrive[letter - TEXT('A')])
+ {
+ continue;
+ }
+
+ letterColon[0] = letter;
+
+ if (!FdpSearchTreeForSystemHives(letterColon,
+ FdpFoundHiveCallback,
+ hwnd))
+ {
+ EndDialog(hwnd, IDCANCEL);
+ return TRUE;
+ }
+
+ }
+
+ EndDialog(hwnd, IDOK);
+ break;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+
+ UserCancelled = TRUE;
+ break;
+
+ default:
+
+ return FALSE;
+ }
+ break;
+
+ default:
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL CALLBACK
+FdpSelectDirDlgProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Using the list of directories containing system hives, display the
+ selections to the user and save the selected item if the user so
+ chooses.
+
+Arguments:
+
+ Windows dialog proc.
+
+Return Value:
+
+ Windows dialog proc.
+
+--*/
+
+{
+ static HWND hwndListBox;
+
+ PSTRING_LIST_NODE stringNode;
+ LONG i;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+
+ CenterDialogInFrame(hwnd);
+
+ //
+ // Add each item in the directory list to the listbox
+ //
+
+ hwndListBox = GetDlgItem(hwnd, IDC_LISTBOX);
+
+ for (stringNode = FoundDirectoryList;
+ NULL != stringNode;
+ stringNode = stringNode->Next)
+ {
+ i = SendMessage(hwndListBox, LB_ADDSTRING , 0, (LONG)stringNode->String);
+ SendMessage(hwndListBox, LB_SETITEMDATA, i, (LONG)stringNode );
+ }
+
+ // select the zeroth item
+ SendMessage(hwndListBox, LB_SETCURSEL, 0, 0);
+
+ break;
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+
+ //
+ // Get the index of the current list box selection and the
+ // pointer to the string node associated with it.
+ //
+
+ i = SendMessage(hwndListBox, LB_GETCURSEL, 0, 0);
+ EndDialog(hwnd, SendMessage(hwndListBox, LB_GETITEMDATA, i, 0));
+ break;
+
+ case IDCANCEL:
+
+ EndDialog(hwnd, (int)NULL);
+ break;
+
+ default:
+
+ return FALSE;
+ }
+ break;
+
+ default:
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL
+DoMigratePreviousFtConfig(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Allow the user to move the disk config info from a different Windows NT
+ installation into the current registry.
+
+ For each fixed disk volume, scan it for system hives and present the
+ results to the user so he can select the installation to migrate.
+
+ Then load the system hive from that instllation (system.alt if the system
+ hive is corrupt, etc) and transfer the DISK:Information binary blob.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE if error or user cancelled, TRUE if info was migrated and reboot
+ is required.
+
+--*/
+
+{
+ LONG ec;
+ LONG ret;
+ TCHAR letter;
+ TCHAR letterColon[4];
+ PSTRING_LIST_NODE stringNode;
+
+ //
+ // Tell the user what this will do and prompt for confirmation
+ //
+
+ if (IDYES != ConfirmationDialog(
+ MSG_CONFIRM_MIGRATE_CONFIG,
+ MB_ICONEXCLAMATION | MB_YESNO))
+ {
+ return FALSE;
+ }
+
+ ProcessPendingMessages();
+
+ //
+ // Figure out which drives are relevent
+ //
+
+ SetCursor(g_hCurWait);
+
+ RtlZeroMemory(ScanDrive, sizeof(ScanDrive));
+ lstrcpy(letterColon, TEXT("?:\\"));
+ for (letter = TEXT('A'); letter <= TEXT('Z'); letter++)
+ {
+ letterColon[0] = letter;
+
+ if (GetDriveType(letterColon) == DRIVE_FIXED)
+ {
+ ScanDrive[letter - TEXT('A')] = TRUE;
+ }
+ }
+
+ SetCursor(g_hCurNormal);
+
+ //
+ // Create a window that will list the directories being scanned, to
+ // keep the user entertained.
+ //
+ ConfigurationSearchIdleTrigger = TRUE;
+
+ ret = DialogBox(g_hInstance,
+ MAKEINTRESOURCE(IDD_SIMPLETEXT),
+ g_hwndFrame,
+ FdpScanningDirsDlgProc);
+
+ if (ret == IDCANCEL)
+ {
+ FdpFreeDirectoryList();
+ return FALSE;
+ }
+
+ ProcessPendingMessages();
+
+ if (0 == FoundDirectoryCount)
+ {
+ InfoDialog(MSG_NO_OTHER_NTS);
+ return FALSE;
+ }
+
+ //
+ // Display a dialog box that allows the user to select one of the
+ // directories we found.
+ //
+
+ stringNode = (PSTRING_LIST_NODE)DialogBox(g_hInstance,
+ MAKEINTRESOURCE(IDD_SELDIR),
+ g_hwndFrame,
+ FdpSelectDirDlgProc);
+
+ if (stringNode == NULL)
+ {
+ FdpFreeDirectoryList();
+ return FALSE;
+ }
+
+ //
+ // User made a selection. One last confirmation.
+ //
+
+ if (IDYES != ConfirmationDialog(
+ MSG_ABSOLUTELY_SURE,
+ MB_ICONEXCLAMATION | MB_YESNO))
+ {
+ FdpFreeDirectoryList();
+ return FALSE;
+ }
+
+ ProcessPendingMessages();
+
+ SetCursor(g_hCurWait);
+
+ lstrcpy(Pattern, stringNode->String);
+ lstrcat(Pattern, ConfigRegistryPath);
+
+ ec = FdTransferOldDiskInfoToRegistry(Pattern);
+ if (ec != NO_ERROR)
+ {
+ lstrcat(Pattern, TEXT(".alt"));
+ ec = FdTransferOldDiskInfoToRegistry(Pattern);
+ }
+ FdpFreeDirectoryList();
+ SetCursor(g_hCurNormal);
+
+ if (ec != NO_ERROR)
+ {
+ if (ec == ERROR_FILE_NOT_FOUND)
+ {
+ ErrorDialog(MSG_NO_DISK_INFO);
+ }
+ else if (ec == ERROR_SHARING_VIOLATION)
+ {
+ ErrorDialog(MSG_DISK_INFO_BUSY);
+ }
+ else
+ {
+ ErrorDialog(ec);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+
+BOOL
+DoRestoreFtConfig(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Restore previously saved disk configuration information into the
+ active registry.
+
+ The saved config info will come from a floppy that the user is
+ prompted to insert.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE if error or user cancelled, TRUE if info was restored and reboot
+ is required.
+
+--*/
+
+{
+ LONG ec;
+ TCHAR caption[256];
+ UINT errorMode;
+
+ //
+ // Get confirmation
+ //
+
+ if (IDYES != ConfirmationDialog(
+ MSG_CONFIRM_RESTORE_CONFIG,
+ MB_ICONEXCLAMATION | MB_YESNO))
+ {
+ return FALSE;
+ }
+
+ //
+ // Get the diskette into A:.
+ //
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ LoadString(g_hInstance, IDS_INSERT_DISK, caption, ARRAYLEN(caption));
+ if (CommonDialogNoArglist(
+ MSG_INSERT_REGSAVEDISK,
+ caption,
+ MB_OKCANCEL | MB_TASKMODAL)
+ != IDOK)
+ {
+ return FALSE;
+ }
+
+ ProcessPendingMessages();
+
+ SetCursor(g_hCurWait);
+
+ //
+ // If there is no file called SYSTEM on a:\, it appears that the registry
+ // creates one and then keeps it open. To avoid this, check to see
+ // whether there is one first.
+ //
+
+ if (GetFileAttributes(TEXT("A:\\SYSTEM")) == -1)
+ {
+ ec = ERROR_FILE_NOT_FOUND;
+ }
+ else
+ {
+ ec = FdTransferOldDiskInfoToRegistry(TEXT("A:\\SYSTEM"));
+ }
+
+ SetErrorMode(errorMode);
+ SetCursor(g_hCurNormal);
+
+ if (ec != NO_ERROR)
+ {
+ ErrorDialog(ec);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+VOID
+DoSaveFtConfig(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Allow the user to update the registry save diskette with the currently
+ defined disk configuration. The saved info excludes any changes made
+ during this session of disk manager.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LONG err;
+ LONG errAlt;
+ LPTSTR systemHiveName = TEXT("a:\\system");
+ HKEY hkey;
+ TCHAR caption[256];
+ DWORD disposition;
+ UINT errorMode;
+
+ //
+ // Get a diskette into A:.
+ //
+
+ LoadString(g_hInstance, IDS_INSERT_DISK, caption, ARRAYLEN(caption));
+ if (CommonDialogNoArglist(
+ MSG_INSERT_REGSAVEDISK2,
+ caption,
+ MB_OKCANCEL | MB_TASKMODAL)
+ != IDOK)
+ {
+ return;
+ }
+
+ //
+ // Decide what to do based on the presence of a a:\system. If that file
+ // is present, just update the DISK entry in it. If it is not present,
+ // then blast out the entire system hive.
+ //
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ ProcessPendingMessages();
+
+ SetCursor(g_hCurWait);
+
+ if (GetFileAttributes(systemHiveName) == -1)
+ {
+ BOOLEAN oldPrivState;
+ NTSTATUS status;
+
+ //
+ // Blast the entire system hive out to the floppy.
+ // Start by attempting to get backup privilege.
+ //
+
+ status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
+ TRUE,
+ FALSE,
+ &oldPrivState);
+
+ err = RtlNtStatusToDosError(status);
+ if (err == NO_ERROR)
+ {
+ err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("system"),
+ REG_OPTION_RESERVED,
+ KEY_READ,
+ &hkey);
+
+ if (err == NO_ERROR)
+ {
+ err = RegSaveKey(hkey, systemHiveName, NULL);
+
+ RegCloseKey(hkey);
+ }
+
+ if (!oldPrivState)
+ {
+ RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, FALSE, FALSE, &oldPrivState);
+ }
+ }
+ }
+ else
+ {
+ PVOID diskInfo;
+ ULONG diskInfoSize;
+
+ //
+ // Load up the saved system hive
+ //
+
+ err = FdpLoadHiveIntoRegistry(systemHiveName);
+ if (err == NO_ERROR)
+ {
+ //
+ // Get the current DISK information
+ //
+
+ err = FdpGetDiskInfoFromKey(TEXT("system"), &diskInfo, &diskInfoSize);
+ if (err == NO_ERROR)
+ {
+ //
+ // Place the current disk information into the saved hive
+ //
+ err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+ TEMP_KEY_NAME TEXT("\\") DISK_KEY_NAME,
+ 0,
+ TEXT("Disk and fault tolerance information."),
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &hkey,
+ &disposition);
+
+ if (err == NO_ERROR)
+ {
+ err = RegSetValueEx(hkey,
+ DISK_VALUE_NAME,
+ REG_OPTION_RESERVED,
+ REG_BINARY,
+ (PBYTE)diskInfo,
+ diskInfoSize);
+
+ RegFlushKey(hkey);
+ RegCloseKey(hkey);
+ }
+
+ LocalFree(diskInfo);
+ }
+
+ errAlt = FdpUnloadHiveFromRegistry();
+
+ if (err == NO_ERROR && errAlt != NO_ERROR)
+ {
+ err = errAlt;
+ }
+ }
+ }
+
+ SetCursor(g_hCurNormal);
+ SetErrorMode(errorMode);
+
+ if (err == NO_ERROR)
+ {
+ InfoDialog(MSG_CONFIG_SAVED_OK);
+ }
+ else
+ {
+ ErrorDialog(err);
+ }
+
+ return;
+}
diff --git a/private/utils/windisk/src/ftreg.dlg b/private/utils/windisk/src/ftreg.dlg
new file mode 100644
index 000000000..bb2528128
--- /dev/null
+++ b/private/utils/windisk/src/ftreg.dlg
@@ -0,0 +1,22 @@
+IDD_SELDIR DIALOG 6, 18, 154, 127
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Get Previous Disk Configuration"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LISTBOX IDC_LISTBOX, 16, 28, 122, 66, LBS_SORT | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "Select a Windows NT installation:", 102, 10, 10, 118, 8
+ PUSHBUTTON "OK", IDOK, 29, 107, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 85, 107, 40, 14
+END
+
+IDD_SIMPLETEXT DIALOG 6, 18, 270, 54
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+STYLE WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION
+CAPTION "Searching for Windows NT Installations"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "", IDC_SIMPLE_TEXT_LINE, 10, 10, 250, 8
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 114, 31, 40, 14, WS_GROUP
+END
diff --git a/private/utils/windisk/src/ftreg.h b/private/utils/windisk/src/ftreg.h
new file mode 100644
index 000000000..76bfe95e0
--- /dev/null
+++ b/private/utils/windisk/src/ftreg.h
@@ -0,0 +1,22 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ftreg.h
+//
+// Contents: Resource constants
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FTREG_H__
+#define __FTREG_H__
+
+#define IDC_LISTBOX 101
+#define IDD_SELDIR 100
+#define IDC_SIMPLE_TEXT_LINE 201
+#define IDD_SIMPLETEXT 300
+
+#endif // __FTREG_H__
diff --git a/private/utils/windisk/src/ftreg.hxx b/private/utils/windisk/src/ftreg.hxx
new file mode 100644
index 000000000..334fb55e6
--- /dev/null
+++ b/private/utils/windisk/src/ftreg.hxx
@@ -0,0 +1,34 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ftreg.hxx
+//
+// Contents: Declarations for registry calls related to fault tolerance
+//
+// History: 2-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FTREG_HXX__
+#define __FTREG_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+DoMigratePreviousFtConfig(
+ VOID
+ );
+
+BOOL
+DoRestoreFtConfig(
+ VOID
+ );
+
+VOID
+DoSaveFtConfig(
+ VOID
+ );
+
+#endif // __FTREG_HXX__
diff --git a/private/utils/windisk/src/genlpage.cxx b/private/utils/windisk/src/genlpage.cxx
new file mode 100644
index 000000000..16aad58fa
--- /dev/null
+++ b/private/utils/windisk/src/genlpage.cxx
@@ -0,0 +1,726 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: genlpage.cxx
+//
+// Contents: Implementation of General property page of volumes in Disk
+// Administrator applet
+//
+// History: 28-Jul-93 BruceFo Created from WilliamW's sharing applet
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <controls.hxx>
+#include <util.hxx>
+
+#include "graph.hxx"
+#include "drives.hxx"
+#include "fs.hxx"
+#include "fmifs.hxx"
+#include "format.hxx"
+#include "chkdsk.hxx"
+
+#include "genlpage.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+SetNumber(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl,
+ IN UINT widDecoration
+ );
+
+VOID
+SetBytes(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl
+ );
+
+VOID
+SetMB(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_DLGPROC
+//
+// Synopsis: Property page dialog procedure
+//
+//--------------------------------------------------------------------------
+
+BOOL CALLBACK
+PAGE_DLGPROC(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ PAGE_CLASS* pPropPage;
+
+ if (msg == WM_INITDIALOG)
+ {
+ pPropPage = new PAGE_CLASS(hwnd);
+ SetWindowLong(hwnd, GWL_USERDATA, (LPARAM)pPropPage);
+ }
+ else
+ {
+ pPropPage = (PAGE_CLASS*) GetWindowLong(hwnd, GWL_USERDATA);
+ }
+
+ if (pPropPage != NULL)
+ {
+ return (pPropPage->_DlgProc(hwnd, msg, wParam, lParam));
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::IsDirty, public
+//
+// Synopsis:
+//
+// Arguments: none
+//
+// Returns: TRUE if page is dirty, FALSE if not
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::IsDirty(
+ VOID
+ )
+{
+ return _fDirty;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::OnApply, public
+//
+// Synopsis: Apply changes to the object's persistent properties
+//
+// Arguments: none
+//
+// Returns: TRUE to allow, FALSE to abort
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::OnApply(
+ VOID
+ )
+{
+ if (IsDirty())
+ {
+ if (!LoadFmifs())
+ {
+ return TRUE; // can't load fmifs.dll, so bail
+ }
+
+ // then apply it!
+
+ WCHAR label[MAXLABELLEN];
+ Edit_GetText(GetDlgItem(_hwndPage, IDC_GENL_Label), label, ARRAYLEN(label));
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ WCHAR driveName[3];
+ driveName[0] = regionData->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ if ( (*lpfnSetLabel)(driveName, label) )
+ {
+ RefreshVolumeData();
+ DisplaySpaceValues(_hwndPage);
+ SetDirty(FALSE);
+ }
+ else
+ {
+ // BUGBUG: better message
+ daDebugOut((DEB_ERROR, "Couldn't set label\n"));
+ }
+ }
+
+ return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::_DlgProc, private
+//
+// Synopsis: Dialog Procedure for the general property page
+//
+// Arguments: standard Windows DlgProc
+//
+// Returns: standard Windows DlgProc
+//
+// History: 28-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::_DlgProc(
+ HWND hdlg,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ return InitGeneralPage(hdlg, wParam, lParam);
+
+ case WM_COMMAND:
+ {
+ HWND hwndPropertyFrame = GetParent(hdlg);
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_Refresh:
+ //
+ // Note that this "Refresh" option refreshes everything for a
+ // single volume (the one we're looking at), but nothing else. In
+ // particular, it doesn't refresh CD-ROM or other volume data.
+ //
+ RefreshVolumeData(); // refresh the data, redisplay the current view
+ DisplaySpaceValues(hdlg);
+ SetDirty(FALSE);
+ break;
+
+ case IDC_Format:
+ DoFormat(hwndPropertyFrame, FALSE);
+ DisplaySpaceValues(hdlg);
+ SetDirty(FALSE);
+ break;
+
+ case IDC_CheckNow:
+ DoChkdsk(hwndPropertyFrame);
+ DisplaySpaceValues(hdlg);
+ SetDirty(FALSE);
+ break;
+
+ case IDC_GENL_Label:
+ {
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ SetDirty(TRUE);
+ }
+ }
+
+ default:
+
+ return FALSE; // not processed
+ }
+
+ return TRUE; // processed
+ }
+
+ case WM_NOTIFY:
+ {
+ NMHDR* phdr = (NMHDR*)lParam;
+
+ switch (phdr->code)
+ {
+ case PSN_SETACTIVE:
+ break;
+
+ case PSN_KILLACTIVE:
+ SetWindowLong(hdlg, DWL_MSGRESULT, FALSE); //ok to leave
+ break;
+
+ case PSN_QUERYCANCEL:
+ case PSN_RESET: // cancel
+ return FALSE;
+
+ case PSN_HELP:
+ NoHelp(hdlg);
+ return FALSE;
+
+ case PSN_APPLY:
+ if (OnApply())
+ {
+ SetWindowLong(hdlg, DWL_MSGRESULT, FALSE); // changes ok
+ }
+ else
+ {
+ SetWindowLong(hdlg, DWL_MSGRESULT, TRUE); // reject changes
+ }
+ return TRUE;
+
+ }
+
+ return FALSE;
+ }
+
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORMSGBOX:
+ case WM_CTLCOLORSTATIC:
+ {
+ HDC hdc = (HDC)wParam;
+ SetBkColor(hdc, GetSysColor(COLOR_3DFACE));
+ return (LRESULT)GetStockBrush(LTGRAY_BRUSH);
+ }
+
+ case WM_DESTROY:
+ DeleteFont(_hDlgFont);
+ SetWindowLong(hdlg, GWL_USERDATA, NULL);
+ delete this;
+ break;
+ }
+
+ return FALSE; // not processed
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::SetDirty, private
+//
+// Synopsis: Set the dirty bit
+//
+// Arguments: [fDirty] -- what to set it to
+//
+// Returns: nothing
+//
+// Derivation: none
+//
+// History: 28-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+PAGE_CLASS::SetDirty(
+ BOOL fDirty
+ )
+{
+ if (_fDirty != fDirty)
+ {
+ _fDirty = fDirty;
+
+ if (_fDirty)
+ {
+ PropSheet_Changed(GetParent(_hwndPage),_hwndPage);
+ }
+ else
+ {
+ PropSheet_UnChanged(GetParent(_hwndPage),_hwndPage);
+ }
+ }
+ // else, no change
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::DisplaySpaceValues, private
+//
+// Synopsis: Calculate and display the space values in the page
+//
+// Arguments: [hdlg] -- handle to property page window
+//
+// Returns: nothing
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PAGE_CLASS::DisplaySpaceValues(
+ IN HWND hdlg
+ )
+{
+ UINT driveStatus;
+ ULONG percentUsedTimes10;
+ WCHAR buffer[100];
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(NULL != regionDescriptor);
+
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if ( 0 == SelectedFreeSpaces
+ && NULL != regionData
+ && !regionData->NewRegion)
+ {
+ driveStatus = STATUS_OK;
+
+ //
+ // Set drive status
+ //
+
+ //BUGBUG: status is always "ready"
+ LoadString(g_hInstance, IDS_READY, buffer, ARRAYLEN(buffer));
+ SetDlgItemText(hdlg, IDC_DriveStatus, buffer);
+
+ //
+ // Set drive label. Set maximum label limit, clear the
+ // "modified" flag, and select the label.
+ //
+
+ HWND hctlLabel = GetDlgItem(hdlg, IDC_GENL_Label);
+ Edit_SetText(hctlLabel, regionData->VolumeLabel);
+ Edit_Enable(hctlLabel, TRUE);
+ FileSystemInfoType* pFSInfo = FindFileSystemInfo(regionData->TypeName);
+ if (NULL == pFSInfo)
+ {
+ Edit_LimitText(hctlLabel, MAXLABELLEN-1);
+ }
+ else
+ {
+ Edit_LimitText(hctlLabel, pFSInfo->cMaxLabelLen);
+ }
+
+ Edit_SetSel(hctlLabel, 0, (LPARAM)-1);
+ Edit_SetModify(GetDlgItem(hdlg, IDC_GENL_Label), FALSE);
+
+ //
+ // Set file system type
+ //
+
+ SetDlgItemText(hdlg, IDC_FileSystem, regionData->TypeName);
+
+ //
+ // Set the "drive letter" static control
+ //
+
+ WCHAR driveName[3];
+ driveName[0] = regionData->DriveLetter;
+
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+ SetDlgItemText(hdlg, IDC_DriveLetter, driveName);
+
+ //
+ // Set the free/used/capacity values, including the graph
+ //
+
+ LARGE_INTEGER freeSpaceInBytes;
+ LARGE_INTEGER usedSpaceInBytes;
+ LARGE_INTEGER capacityInBytes;
+
+ freeSpaceInBytes = regionData->FreeSpaceInBytes;
+ capacityInBytes = regionData->TotalSpaceInBytes;
+ usedSpaceInBytes.QuadPart = capacityInBytes.QuadPart - freeSpaceInBytes.QuadPart;
+
+ SetBytes(hdlg, freeSpaceInBytes, IDC_FreeSpace);
+ SetBytes(hdlg, usedSpaceInBytes, IDC_UsedSpace);
+ SetBytes(hdlg, capacityInBytes, IDC_Capacity);
+
+ LONGLONG oneMeg = UInt32x32To64(1024,1024);
+
+ if (capacityInBytes.QuadPart > oneMeg)
+ {
+ LARGE_INTEGER freeSpaceInMB;
+ LARGE_INTEGER usedSpaceInMB;
+ LARGE_INTEGER capacityInMB;
+
+ freeSpaceInMB.QuadPart = freeSpaceInBytes.QuadPart / oneMeg;
+ capacityInMB.QuadPart = capacityInBytes.QuadPart / oneMeg;
+ usedSpaceInMB.QuadPart = usedSpaceInBytes.QuadPart / oneMeg;
+
+ SetMB(hdlg, freeSpaceInMB, IDC_FreeSpaceMB);
+ SetMB(hdlg, usedSpaceInMB, IDC_UsedSpaceMB);
+ SetMB(hdlg, capacityInMB, IDC_CapacityMB);
+ }
+ else
+ {
+ //
+ // Clear the "(n MB)" strings if the capacity of the drive is < 1MB
+ //
+ buffer[0] = L'\0';
+ SetDlgItemText(hdlg, IDC_FreeSpaceMB, buffer);
+ SetDlgItemText(hdlg, IDC_UsedSpaceMB, buffer);
+ SetDlgItemText(hdlg, IDC_CapacityMB, buffer);
+ }
+
+ percentUsedTimes10 = (ULONG)((usedSpaceInBytes.QuadPart * (LONGLONG)1000) / capacityInBytes.QuadPart);
+ }
+ else
+ {
+ driveStatus = STATUS_UNKNOWN;
+
+ //
+ // No info: clear the number fields
+ //
+
+ LoadString(g_hInstance, IDS_NOTREADY, buffer, ARRAYLEN(buffer));
+ SetDlgItemText(hdlg, IDC_DriveStatus, buffer);
+
+ buffer[0] = L'\0';
+
+ SetDlgItemText(hdlg, IDC_GENL_Label, buffer);
+ Edit_Enable(GetDlgItem(hdlg, IDC_GENL_Label), FALSE);
+
+ SetDlgItemText(hdlg, IDC_DriveLetter, buffer);
+ SetDlgItemText(hdlg, IDC_FileSystem, buffer);
+ SetDlgItemText(hdlg, IDC_FreeSpace, buffer);
+ SetDlgItemText(hdlg, IDC_FreeSpaceMB, buffer);
+ SetDlgItemText(hdlg, IDC_UsedSpace, buffer);
+ SetDlgItemText(hdlg, IDC_UsedSpaceMB, buffer);
+ SetDlgItemText(hdlg, IDC_Capacity, buffer);
+ SetDlgItemText(hdlg, IDC_CapacityMB, buffer);
+
+ EnableWindow(GetDlgItem(hdlg, IDC_Refresh), FALSE);
+ EnableWindow(GetDlgItem(hdlg, IDC_Format), FALSE);
+ EnableWindow(GetDlgItem(hdlg, IDC_CheckNow), FALSE);
+
+ percentUsedTimes10 = 0;
+ }
+
+ //
+ // Now set the graph
+ //
+
+ UINT driveType = DRIVE_FIXED; // GetDriveType(driveName);
+
+ HBITMAP hBigBitmap = CreateGraphBitmap(
+ g_hInstance,
+ GetDlgItem(hdlg, IDC_Graph),
+ driveType,
+ driveStatus,
+ percentUsedTimes10
+ );
+
+ SendDlgItemMessage(
+ hdlg,
+ IDC_Graph,
+ BMPCTL_SETBITMAP,
+ (WPARAM)hBigBitmap,
+ 0);
+
+ SetDirty(FALSE);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: PAGE_CLASS::InitGeneralPage, private
+//
+// Synopsis: Initialize the data displayed on the General property
+// page based on the current Disk Administrator selection
+//
+// Arguments: DlgProc stuff
+//
+// Returns: DlgProc stuff for WM_INITDIALOG
+//
+// History: 11-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+PAGE_CLASS::InitGeneralPage(
+ IN HWND hdlg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static UINT s_idTextControls[] =
+ {
+ IDC_DriveStatus,
+ IDC_FileSystem,
+ IDC_DriveLetter,
+ IDC_FreeSpace,
+ IDC_FreeSpaceMB,
+ IDC_UsedSpace,
+ IDC_UsedSpaceMB,
+ IDC_Capacity,
+ IDC_CapacityMB,
+ IDC_Refresh,
+ IDC_CheckNow,
+ IDC_Format,
+ IDC_GENL_Label,
+
+ IDC_GENL_1,
+ IDC_GENL_2,
+ IDC_GENL_3,
+ IDC_GENL_4,
+ IDC_GENL_5,
+ IDC_GENL_6,
+ IDC_GENL_7,
+
+ 0
+ };
+
+ _hDlgFont = KillBold(hdlg, s_idTextControls);
+
+ //
+ // Set the legend for the graph
+ //
+
+ SendDlgItemMessage(
+ hdlg,
+ IDC_UsedColor,
+ BOXCTL_SETCOLOR,
+ (WPARAM)GraphColors[I_USEDCOLOR],
+ 0);
+
+ SendDlgItemMessage(
+ hdlg,
+ IDC_FreeColor,
+ BOXCTL_SETCOLOR,
+ (WPARAM)GraphColors[I_FREECOLOR],
+ 0);
+
+ //
+ // Disable chkdsk if we can't chkdsk (e.g., fmifs.dll doesn't support it)
+ //
+
+ if (MF_GRAYED & GetMenuState(g_hmenuFrame, IDM_VOL_CHKDSK, MF_BYCOMMAND))
+ {
+ EnableWindow(GetDlgItem(hdlg, IDC_CheckNow), FALSE);
+ }
+
+ //
+ // Fill the space numbers, and display the graph
+ //
+
+ DisplaySpaceValues(hdlg);
+
+ return TRUE; // didn't set focus to any control
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetNumber
+//
+// Synopsis: Helper function: set a control to a number.
+//
+// Arguments: [hwnd] -- handle of property page
+// [Value] -- number to set
+// [idControl] -- control ID to put number in
+// [widDecoration] -- a resource ID for a 'printf' string with
+// one %s element that will be replaced by the string
+// representation of the number, before being set to the
+// control.
+//
+// Returns: nothing
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetNumber(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl,
+ IN UINT widDecoration
+ )
+{
+ WCHAR decoration[100];
+ WCHAR buffer[100]; // buffer for numbers
+ WCHAR buf2[100]; // buffer for final text
+
+ LoadString(g_hInstance, widDecoration, decoration, ARRAYLEN(decoration));
+
+ NTSTATUS status = LargeIntegerToUnicodeChar(
+ &Value,
+ 10,
+ ARRAYLEN(buffer),
+ buffer
+ );
+ InsertSeparators(buffer);
+ wsprintf(buf2, decoration, buffer);
+ SetDlgItemText(hwnd, idControl, buf2);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetBytes
+//
+// Synopsis: Set a bytes control
+//
+// Arguments: [hwnd] -- handle of property page
+// [Value] -- number to set
+// [idControl] -- control ID to put number in
+//
+// Returns: nothing
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetBytes(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl
+ )
+{
+ SetNumber(hwnd, Value, idControl, IDS_BYTES_DECORATION);
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetMB
+//
+// Synopsis: Set a MB control
+//
+// Arguments: [hwnd] -- handle of property page
+// [Value] -- number to set
+// [idControl] -- control ID to put number in
+//
+// Returns: nothing
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetMB(
+ IN HWND hwnd,
+ IN LARGE_INTEGER Value,
+ IN int idControl
+ )
+{
+ SetNumber(hwnd, Value, idControl, IDS_MEG_DECORATION);
+}
diff --git a/private/utils/windisk/src/genlpage.hxx b/private/utils/windisk/src/genlpage.hxx
new file mode 100644
index 000000000..25a3daa47
--- /dev/null
+++ b/private/utils/windisk/src/genlpage.hxx
@@ -0,0 +1,98 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: genlpage.hxx
+//
+// Contents: General property page of volumes in
+// Disk Administrator applet
+//
+// History: 28-Jul-93 BruceFo Created from WilliamW's sharing applet
+//
+//--------------------------------------------------------------------------
+
+#ifndef __GENLPAGE_HXX__
+#define __GENLPAGE_HXX__
+
+#include "resids.h"
+#include "dialogs.h"
+
+#undef PAGE_DLGPROC
+#undef PAGE_CLASS
+
+#define PAGE_DLGPROC GeneralPageDlgProc
+#define PAGE_CLASS CGeneralPage
+
+
+class PAGE_CLASS
+{
+public:
+
+ PAGE_CLASS(
+ IN HWND hwndPage
+ )
+ :
+ _hwndPage(hwndPage),
+ _hDlgFont(NULL)
+ {
+ }
+
+ ~PAGE_CLASS()
+ {
+ }
+
+ friend BOOL CALLBACK
+ PAGE_DLGPROC(
+ HWND hWnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam);
+
+ BOOL
+ IsDirty(
+ VOID
+ );
+
+ BOOL
+ OnApply(
+ VOID
+ );
+
+private:
+
+ BOOL
+ _DlgProc(
+ IN HWND hWnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+ VOID
+ SetDirty(
+ BOOL fDirty
+ );
+
+ VOID
+ DisplaySpaceValues(
+ IN HWND hwnd
+ );
+
+ BOOL
+ InitGeneralPage(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+ //
+ // Data
+ //
+
+ BOOL _fDirty;
+ HFONT _hDlgFont;
+ HWND _hwndPage;
+};
+
+#endif // __GENLPAGE_HXX__
diff --git a/private/utils/windisk/src/global.hxx b/private/utils/windisk/src/global.hxx
new file mode 100644
index 000000000..f6191a33b
--- /dev/null
+++ b/private/utils/windisk/src/global.hxx
@@ -0,0 +1,233 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: global.hxx
+//
+// Contents: Global data declarations
+//
+// History: 7-Jan-92 TedM Created
+// 7-Jan-94 BruceFo Incorporated BobRi's DoubleSpace and Commit
+// changes
+//
+//----------------------------------------------------------------------------
+
+#ifndef __GLOBAL_HXX__
+#define __GLOBAL_HXX__
+
+//
+// from data.cxx
+//
+
+extern HINSTANCE g_hInstance;
+extern HWND g_hwndFrame;
+extern HWND g_hwndList;
+extern HWND g_hwndToolbar;
+
+extern HMENU g_hmenuFrame; // the frame window's hmenu
+
+extern HBITMAP g_hBitmapSmallDisk;
+extern HBITMAP g_hBitmapRemovableDisk;
+extern HBITMAP g_hBitmapSmallCdRom;
+extern HFONT g_hFontGraph;
+extern HFONT g_hFontGraphBold;
+extern HFONT g_hFontStatus;
+extern HFONT g_hFontLegend;
+
+extern HBRUSH g_Brushes[BRUSH_ARRAY_SIZE];
+extern HBRUSH g_hBrushFreeLogical;
+extern HBRUSH g_hBrushFreePrimary;
+extern HPEN g_hPenNull;
+extern HPEN g_hPenThinSolid;
+extern HCURSOR g_hCurWait;
+extern HCURSOR g_hCurNormal;
+
+extern PBOOLEAN IsDiskRemovable;
+extern PWCHAR RemovableDiskReservedDriveLetters;
+extern PDISKSTATE* DiskArray;
+extern ULONG BootDiskNumber;
+extern ULONG BootPartitionNumber;
+
+extern int BrushHatches[BRUSH_ARRAY_SIZE];
+extern int BrushColors[BRUSH_ARRAY_SIZE];
+
+extern COLORREF AvailableColors[NUM_AVAILABLE_COLORS];
+extern int AvailableHatches[NUM_AVAILABLE_HATCHES];
+
+extern DWORD GraphWidth;
+extern DWORD GraphHeight;
+extern DWORD BarTopYOffset;
+extern DWORD BarBottomYOffset;
+extern DWORD BarHeight;
+
+extern DWORD dxDriveLetterStatusArea;
+
+extern DWORD dxBarTextMargin;
+extern DWORD dyBarTextLine;
+extern DWORD BarLeftX;
+extern DWORD BarWidth;
+extern DWORD BarWidthMargin;
+extern DWORD BarWidthMinimum;
+
+extern DWORD MinimumWindowWidth;
+
+extern DWORD xSmallDisk;
+extern DWORD ySmallDisk;
+extern DWORD dxSmallDisk;
+extern DWORD dySmallDisk;
+
+extern DWORD xRemovableDisk;
+extern DWORD yRemovableDisk;
+extern DWORD dxRemovableDisk;
+extern DWORD dyRemovableDisk;
+
+extern DWORD xSmallCdRom;
+extern DWORD ySmallCdRom;
+extern DWORD dxSmallCdRom;
+extern DWORD dySmallCdRom;
+
+extern ULONG g_MinimumRegionSize;
+
+extern PDISKSTATE SingleSel;
+extern DWORD SingleSelIndex;
+
+extern PWSTR g_HelpFile;
+
+extern ULONG DiskCount;
+
+extern ULONG CdRomCount;
+extern PCDROM_DESCRIPTOR CdRomArray;
+
+extern LPTSTR DiskN;
+extern LPTSTR CdRomN;
+extern PWSTR wszUnformatted;
+extern PWSTR wszUnknown;
+
+extern BOOL RegistryChanged;
+extern BOOL RestartRequired;
+
+extern BOOL ConfigurationSearchIdleTrigger;
+extern BOOL g_IsLanmanNt;
+extern BOOL g_AllowCdRom;
+
+extern VIEW_TYPE g_WhichView;
+extern HWND g_hwndLV;
+
+extern BOOL g_SettingListviewState;
+
+extern DWORD g_wLegendItem;
+extern DWORD g_dyLegendSep;
+
+extern DWORD g_dyBorder;
+extern DWORD g_dyToolbar;
+extern DWORD g_dyStatus;
+extern DWORD g_dyLegend;
+
+extern BOOL g_Toolbar;
+extern BOOL g_StatusBar;
+extern BOOL g_Legend;
+
+extern DISK_TYPE g_DiskDisplayType;
+
+extern COLORREF GraphColors[];
+
+//
+// from stleg.cxx
+//
+
+extern PWSTR LegendLabels[LEGEND_STRING_COUNT];
+
+extern WCHAR StatusTextStat[STATUS_TEXT_SIZE];
+extern WCHAR StatusTextSize[STATUS_TEXT_SIZE];
+extern WCHAR StatusTextDrlt[3];
+extern WCHAR StatusTextType[STATUS_TEXT_SIZE];
+extern WCHAR StatusTextVoll[STATUS_TEXT_SIZE];
+
+//
+// from windisk.cxx
+//
+
+extern DWORD SelectionCount;
+extern PDISKSTATE SelectedDS[];
+extern ULONG SelectedRG[];
+extern ULONG SelectedFreeSpaces;
+extern ULONG SelectedNonFtPartitions;
+extern PULONG DiskSeenCountArray;
+extern BOOL FtSetSelected;
+extern FT_TYPE FtSelectionType;
+extern BOOL NonFtItemSelected;
+extern BOOL MultipleItemsSelected;
+extern BOOL VolumeSetAndFreeSpaceSelected;
+extern BOOL PartitionAndFreeSpaceSelected;
+extern BOOL PossibleRecover;
+extern ULONG FreeSpaceIndex;
+
+extern BOOL DiskSelected;
+extern BOOL PartitionSelected;
+extern BOOL CdRomSelected;
+extern DWORD CdRomSelectionCount;
+
+extern BOOL AllowFormat;
+extern BOOL AllowVolumeOperations;
+
+extern WCHAR BootDir;
+extern WCHAR SystemDir;
+
+#ifdef WINDISK_EXTENSIONS
+extern BOOL AllowExtensionItems;
+#endif // WINDISK_EXTENSIONS
+
+//
+// from listbox.cxx
+//
+
+extern DWORD LBCursorListBoxItem;
+extern DWORD LBCursorRegion;
+
+//
+// from profile.cxx
+//
+
+extern int ProfileWindowX;
+extern int ProfileWindowY;
+extern int ProfileWindowW;
+extern int ProfileWindowH;
+
+extern int deltaProfileWindowX;
+extern int deltaProfileWindowY;
+extern int deltaProfileWindowW;
+extern int deltaProfileWindowH;
+
+extern BOOL ProfileIsMaximized;
+extern BOOL ProfileIsIconic;
+
+//
+// from dlgs.cxx
+//
+
+extern DWORD SelectedColor[LEGEND_STRING_COUNT];
+extern DWORD SelectedHatch[LEGEND_STRING_COUNT];
+extern WNDPROC OldSizeDlgProc;
+
+//
+// from ft.cxx
+//
+
+extern PFT_OBJECT_SET FtObjectList;
+
+//
+// from help2.cxx
+//
+
+extern BOOL g_fDoingMenuHelp;
+
+//
+// from init.cxx
+//
+
+extern HWND g_InitDlg;
+extern BOOLEAN g_StartedAsIcon;
+extern BOOLEAN g_InitDlgComplete;
+
+#endif // __GLOBAL_HXX__
diff --git a/private/utils/windisk/src/graph.cxx b/private/utils/windisk/src/graph.cxx
new file mode 100644
index 000000000..b91b70eb8
--- /dev/null
+++ b/private/utils/windisk/src/graph.cxx
@@ -0,0 +1,793 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: graph.cxx
+//
+// Contents: Code to generate a nice %free/%used graph on a disk/CD-ROM/
+// memory chip bitmap
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "graph.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Bits of DrawFlags
+ */
+#define DF_USEBARH 0x0001
+#define DF_USEBARV 0x0002
+#define DF_NEVERFREE 0x0004
+
+typedef struct
+{
+ WORD DrawFlags;
+ int ThreeDHgt;
+ RECT EllipsRect;
+ RECT BarRect;
+
+} DRIVEINFO, *PDRIVEINFO;
+
+
+/*
+ * the following define defines the color in the drive bitmaps
+ * which is mapped to COLOR_MSGBOX to define the "background"
+ * part of the bitmap.
+ */
+#define COLORCHNGTOSCREEN RGB(0,0,255)
+
+////////////////////////////////////////////////////////////////////////////
+
+HBITMAP
+LoadDriveBitmap(
+ IN HINSTANCE hInstance,
+ IN ULONG driveType,
+ IN ULONG driveStatus,
+ OUT PDRIVEINFO pdi
+ );
+
+ULONG
+IntSqrt(
+ IN ULONG Number
+ );
+
+VOID
+DrawPie(
+ IN HDC hDC,
+ IN LPRECT prcItem,
+ IN ULONG uPctX10,
+ IN ULONG uOffset,
+ IN COLORREF* pGraphColors
+ );
+
+BOOL
+ModifyDriveBitmap(
+ IN HWND hwndParent,
+ IN HBITMAP hBigBitmap,
+ IN ULONG driveStatus,
+ IN ULONG percentUsedTimes10,
+ IN PDRIVEINFO pdi
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: LoadDriveBitmap
+//
+// Synopsis: Given a drive type and flags, load a drive bitmap from the
+// resource file.
+//
+// Arguments: [hInstance] -- instance handle of binary with drive bitmap
+// resources
+// [driveType] -- DRIVE_FIXED, etc (see Win32 GetDriveType())
+// [driveStatus] -- STATUS_OK or STATUS_UNKNOWN
+// [pdi] -- Various information about the bitmap is loaded into
+// this structure
+//
+// Returns: handle to the loaded bitmap
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+HBITMAP
+LoadDriveBitmap(
+ IN HINSTANCE hInstance,
+ IN ULONG driveType,
+ IN ULONG driveStatus,
+ OUT PDRIVEINFO pdi
+ )
+{
+ HRSRC mhand = NULL;
+ HGLOBAL mhandMem;
+ LPWORD hPtr;
+ HBITMAP retbm = 0;
+ WORD retSty = 0;
+ COLORMAP bmColMap;
+
+ bmColMap.from = COLORCHNGTOSCREEN;
+ bmColMap.to = GetSysColor(COLOR_BTNFACE);
+
+ if (driveType == DRIVE_FIXED)
+ {
+ if (driveStatus == STATUS_OK)
+ {
+ mhand = FindResource(
+ hInstance,
+ MAKEINTRESOURCE(ELLIPRESOURCE),
+ MAKEINTRESOURCE(IDB_HARDDISK));
+ retbm = CreateMappedBitmap(hInstance, IDB_HARDDISK, 0, &bmColMap, 1);
+ }
+ }
+ else if (driveType == DRIVE_CDROM)
+ {
+ if (driveStatus == STATUS_OK)
+ {
+ mhand = FindResource(
+ hInstance,
+ MAKEINTRESOURCE(ELLIPRESOURCE),
+ MAKEINTRESOURCE(IDB_CDROM));
+ retbm = CreateMappedBitmap(hInstance, IDB_CDROM, 0, &bmColMap, 1);
+ }
+ }
+
+ mhandMem = LoadResource(hInstance, mhand);
+ if (mhandMem)
+ {
+ hPtr = (LPWORD)LockResource(mhandMem);
+ if (hPtr)
+ {
+ retSty = hPtr[0];
+ if (hPtr[0] == USETYPE_BARH)
+ {
+ pdi->DrawFlags |= DF_USEBARH;
+ }
+ else if (hPtr[0] == USETYPE_BARV)
+ {
+ pdi->DrawFlags |= DF_USEBARV;
+ }
+ else if (hPtr[0] == USETYPE_NONE)
+ {
+ pdi->DrawFlags |= DF_NEVERFREE;
+ }
+ pdi->ThreeDHgt = hPtr[1];
+ pdi->EllipsRect.left = hPtr[2];
+ pdi->EllipsRect.top = hPtr[3];
+ pdi->EllipsRect.right = hPtr[4];
+ pdi->EllipsRect.bottom = hPtr[5];
+ pdi->BarRect.left = hPtr[6];
+ pdi->BarRect.top = hPtr[7];
+ pdi->BarRect.right = hPtr[8];
+ pdi->BarRect.bottom = hPtr[9];
+ UnlockResource(mhandMem);
+ }
+ else
+ {
+ pdi->ThreeDHgt = 0;
+ pdi->EllipsRect.left = 0;
+ pdi->EllipsRect.top = 0;
+ pdi->EllipsRect.right = 0;
+ pdi->EllipsRect.bottom = 0;
+ pdi->BarRect.left = 0;
+ pdi->BarRect.top = 0;
+ pdi->BarRect.right = 0;
+ pdi->BarRect.bottom = 0;
+ }
+ }
+
+ return retbm;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IntSqrt
+//
+// Synopsis: Integer square root of a number
+//
+// Arguments: [Number] -- number to take the square root of
+//
+// Returns: The largest integer <= the actual square root of the number
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+// BUGBUG: better algorithm?
+//
+//--------------------------------------------------------------------------
+
+ULONG
+IntSqrt(
+ IN ULONG Number
+ )
+{
+ for (ULONG i = 1; i*i <= Number; i++)
+ {
+ // nothing
+ }
+
+ return i-1;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DrawPie
+//
+// Synopsis: Draws an elliptical pie chart
+//
+// Arguments: [hDC] -- where to draw it
+// [prcItem] -- ?
+// [uPctX10] -- ?
+// [uOffset] -- ?
+// [pGraphColors] -- ?
+//
+// Returns: nothing
+//
+// Modifies: the pie is drawn on the argument DC
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+VOID
+DrawPie(
+ IN HDC hDC,
+ IN LPRECT prcItem,
+ IN ULONG uPctX10,
+ IN ULONG uOffset,
+ IN COLORREF* pGraphColors
+ )
+{
+ int cx, cy; // center of arc
+ int rx, ry; // "radius" length of ellipse in x & y directions
+ int x, y;
+ int width, height;
+ int uQPctX10;
+ RECT rcItem;
+ HRGN hEllRect, hEllipticRgn, hRectRgn;
+ HBRUSH hBrush, hOldBrush;
+ HPEN hPen, hOldPen;
+
+ width = prcItem->right - prcItem->left;
+ height = (prcItem->bottom - uOffset) - prcItem->top;
+
+ rx = width / 2;
+ cx = prcItem->left + rx - 1;
+ ry = height / 2;
+ cy = prcItem->top + ry - 1;
+ if (rx <= 10 || ry <= 10)
+ {
+ return;
+ }
+
+ rcItem.left = prcItem->left;
+ rcItem.top = prcItem->top;
+ rcItem.right = prcItem->right;
+ rcItem.bottom = prcItem->bottom - uOffset;
+
+ if (uPctX10 > 1000)
+ {
+ uPctX10 = 1000;
+ }
+
+ /* Translate to first quadrant of a Cartesian system
+ */
+ uQPctX10 = (uPctX10 % 500) - 250;
+ if (uQPctX10 < 0)
+ {
+ uQPctX10 = -uQPctX10;
+ }
+
+ /* Calc x and y. I am trying to make the area be the right percentage.
+ ** I don't know how to calculate the area of an elliptical pie slice
+ ** exactly, so I approximate it by using the triangle area instead.
+ */
+ if (uQPctX10 < 120)
+ {
+ x = IntSqrt(
+ ((DWORD)rx * (DWORD)rx * (DWORD)uQPctX10 * (DWORD)uQPctX10)
+ /
+ ((DWORD)uQPctX10 * (DWORD)uQPctX10 + (250L - (DWORD)uQPctX10) * (250L - (DWORD)uQPctX10))
+ );
+
+ y = IntSqrt(
+ ((DWORD)rx * (DWORD)rx - (DWORD)x * (DWORD)x) * (DWORD)ry * (DWORD)ry
+ /
+ ((DWORD)rx * (DWORD)rx)
+ );
+ }
+ else
+ {
+ y = IntSqrt(
+ (DWORD)ry * (DWORD)ry * (250L - (DWORD)uQPctX10) * (250L - (DWORD)uQPctX10)
+ /
+ ((DWORD)uQPctX10 * (DWORD)uQPctX10 + (250L - (DWORD)uQPctX10) * (250L - (DWORD)uQPctX10))
+ );
+
+ x = IntSqrt(
+ ((DWORD)ry * (DWORD)ry - (DWORD)y * (DWORD)y) * (DWORD)rx * (DWORD)rx
+ /
+ ((DWORD)ry * (DWORD)ry)
+ );
+ }
+
+ /* Switch on the actual quadrant
+ */
+ switch (uPctX10 / 250)
+ {
+ case 1:
+ y = -y;
+ break;
+
+ case 2:
+ break;
+
+ case 3:
+ x = -x;
+ break;
+
+ default: // case 0 and case 4
+ x = -x;
+ y = -y;
+ break;
+ }
+
+ /* Now adjust for the center.
+ */
+ x += cx;
+ y += cy;
+
+ /* Draw the shadows using regions (to reduce flicker).
+ */
+ hEllipticRgn = CreateEllipticRgnIndirect(&rcItem);
+ OffsetRgn(hEllipticRgn, 0, uOffset);
+ hEllRect = CreateRectRgn(rcItem.left, cy, rcItem.right, cy+uOffset);
+ hRectRgn = CreateRectRgn(0, 0, 0, 0);
+ CombineRgn(hRectRgn, hEllipticRgn, hEllRect, RGN_OR);
+ OffsetRgn(hEllipticRgn, 0, -(int)uOffset);
+ CombineRgn(hEllRect, hRectRgn, hEllipticRgn, RGN_DIFF);
+
+ /* Always draw the whole area in the free shadow
+ */
+ hBrush = CreateSolidBrush(pGraphColors[I_FREESHADOW]);
+ if (NULL != hBrush)
+ {
+ FillRgn(hDC, hEllRect, hBrush);
+ DeleteBrush(hBrush);
+ }
+
+ /* Draw the used shadow only if the disk is at least half used.
+ */
+ if (uPctX10 > 500
+ && (NULL != (hBrush = CreateSolidBrush(pGraphColors[I_USEDSHADOW])))
+ )
+ {
+ DeleteRgn(hRectRgn);
+ hRectRgn = CreateRectRgn(x, cy, rcItem.right, prcItem->bottom);
+ CombineRgn(hEllipticRgn, hEllRect, hRectRgn, RGN_AND);
+ FillRgn(hDC, hEllipticRgn, hBrush);
+ DeleteBrush(hBrush);
+ }
+
+ DeleteRgn(hRectRgn);
+ DeleteRgn(hEllipticRgn);
+ DeleteObject(hEllRect);
+
+ hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
+ hOldPen = SelectPen(hDC, hPen);
+
+ if ((uPctX10 < 100) && (cy == y))
+ {
+ // Less than 10% full, and only a single line of the used color
+ // will be visible.
+
+ hBrush = CreateSolidBrush(pGraphColors[I_FREECOLOR]);
+ hOldBrush = SelectBrush(hDC, hBrush);
+ Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
+ SelectBrush(hDC, hOldBrush);
+ DeleteBrush(hBrush);
+
+ if (uPctX10 != 0)
+ {
+ // There is something there! Draw a single "used" line.
+
+ MoveToEx(hDC, rcItem.left, cy, NULL);
+ LineTo(hDC, cx, cy);
+ }
+ }
+ else if ((uPctX10 > (1000 - 100)) && (cy == y))
+ {
+ // greater than 90% full, and only a single line of the free color
+ // will be visible.
+
+ hBrush = CreateSolidBrush(pGraphColors[I_USEDCOLOR]);
+ hOldBrush = SelectBrush(hDC, hBrush);
+ Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
+ SelectBrush(hDC, hOldBrush);
+ DeleteBrush(hBrush);
+
+ if (uPctX10 != 1000)
+ {
+ // There is something there! Draw a single "free" line.
+
+ MoveToEx(hDC, rcItem.left, cy, NULL);
+ LineTo(hDC, cx, cy);
+ }
+ }
+ else
+ {
+ hBrush = CreateSolidBrush(pGraphColors[I_USEDCOLOR]);
+ hOldBrush = SelectBrush(hDC, hBrush);
+ Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
+ SelectBrush(hDC, hOldBrush);
+ DeleteBrush(hBrush);
+
+ hBrush = CreateSolidBrush(pGraphColors[I_FREECOLOR]);
+ hOldBrush = SelectBrush(hDC, hBrush);
+ Pie(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
+ rcItem.left, cy, x, y);
+ SelectBrush(hDC, hOldBrush);
+ DeleteBrush(hBrush);
+ }
+
+ /* Do not draw the lines if the percentage is truely 0 or 100 (completely
+ ** empty disk or completly full disk)
+ */
+ if ((uPctX10 != 0) && (uPctX10 != 1000))
+ {
+ Arc(hDC,
+ rcItem.left,
+ rcItem.top + uOffset,
+ rcItem.right,
+ rcItem.bottom + uOffset,
+ rcItem.left,
+ cy + uOffset,
+ rcItem.right,
+ cy + uOffset - 1);
+
+ // Draw the lines on the left and right side that connect the top
+ // ellipse with the bottom, "highlight" ellipse.
+ MoveToEx(hDC, rcItem.left, cy, NULL);
+ LineTo(hDC, rcItem.left, cy + uOffset);
+ MoveToEx(hDC, rcItem.right - 1, cy, NULL);
+ LineTo(hDC, rcItem.right - 1, cy + uOffset);
+
+ if (uPctX10 > 500)
+ {
+ MoveToEx(hDC, x, y, NULL);
+ LineTo(hDC, x, y + uOffset);
+ }
+ }
+ SelectPen(hDC, hOldPen);
+ DeletePen(hPen);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ModifyDriveBitmap
+//
+// Synopsis: Given a drive bitmap, draw a %used/%free indicator on top
+//
+// Arguments: [hwndParent] -- handle to window of parent of bitmap
+// [hBigBitmap] -- handle of bitmap to alter
+// [driveStatus] -- drive status
+// [percentUsedTimes10] -- % used space times 10 (i.e. one decimal
+// point of accuracy)
+// [pdi] -- drawing parameters
+//
+// Returns: TRUE if successful
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+BOOL
+ModifyDriveBitmap(
+ IN HWND hwndParent,
+ IN HBITMAP hBigBitmap,
+ IN ULONG driveStatus,
+ IN ULONG percentUsedTimes10,
+ IN PDRIVEINFO pdi
+ )
+{
+ HDC hDCWnd;
+ HDC hDCMem;
+ HBITMAP hOrgBm;
+ HBRUSH hOrgBrsh;
+ HBRUSH hUsedBrsh;
+ HBRUSH hUsedSBrsh;
+ HBRUSH hFreeBrsh;
+ HBRUSH hFreeSBrsh;
+ HBRUSH hBlkBrsh;
+ HPEN hBlkPen;
+ LPPOINT lpPnt;
+ POINT Pnt[4];
+
+ // No chart if never writable or drive currently not ready
+
+ if ((pdi->DrawFlags & DF_NEVERFREE) || (driveStatus == STATUS_UNKNOWN))
+ {
+ return TRUE;
+ }
+
+ hDCWnd = GetDC(hwndParent);
+ if (NULL == hDCWnd)
+ {
+ return FALSE;
+ }
+
+ hDCMem = CreateCompatibleDC(hDCWnd);
+ if (NULL == hDCMem)
+ {
+ ReleaseDC(hwndParent,hDCWnd);
+ return FALSE;
+ }
+
+ ReleaseDC(hwndParent,hDCWnd);
+ hBlkPen = GetStockPen(BLACK_PEN);
+ hBlkBrsh = GetStockBrush(BLACK_BRUSH);
+
+ hUsedBrsh = CreateSolidBrush(GraphColors[I_USEDCOLOR]);
+ if (NULL == hUsedBrsh)
+ {
+ return FALSE;
+ }
+
+ hUsedSBrsh = CreateSolidBrush(GraphColors[I_USEDSHADOW]);
+ if (NULL == hUsedSBrsh)
+ {
+ DeleteBrush(hUsedBrsh);
+ return FALSE;
+ }
+
+ hFreeBrsh = CreateSolidBrush(GraphColors[I_FREECOLOR]);
+ if (NULL == hFreeBrsh)
+ {
+ DeleteBrush(hUsedBrsh);
+ DeleteBrush(hUsedSBrsh);
+ return FALSE;
+ }
+
+ hFreeSBrsh = CreateSolidBrush(GraphColors[I_FREESHADOW]);
+ if (NULL == hFreeSBrsh)
+ {
+ DeleteBrush(hUsedBrsh);
+ DeleteBrush(hUsedSBrsh);
+ DeleteBrush(hFreeBrsh);
+ return FALSE;
+ }
+
+ hOrgBm = SelectBitmap(hDCMem,hBigBitmap);
+ hOrgBrsh = SelectBrush(hDCMem,hUsedBrsh);
+
+ if ((pdi->DrawFlags & DF_USEBARH) || (pdi->DrawFlags & DF_USEBARV))
+ {
+ lpPnt = (LPPOINT)&pdi->EllipsRect;
+ SelectPen(hDCMem,hBlkPen);
+
+ if (percentUsedTimes10 == 1000)
+ {
+ SelectBrush(hDCMem,hUsedBrsh);
+ }
+ else
+ {
+ SelectBrush(hDCMem,hFreeBrsh);
+ }
+
+ Polygon(hDCMem,lpPnt,4);
+
+ if (percentUsedTimes10 == 1000)
+ {
+ SelectBrush(hDCMem,hUsedSBrsh);
+ }
+ else
+ {
+ SelectBrush(hDCMem,hFreeSBrsh);
+ }
+
+ if (pdi->DrawFlags & DF_USEBARH)
+ {
+ Pnt[0].x = lpPnt[0].x;
+ Pnt[0].y = lpPnt[0].y;
+ Pnt[1].x = lpPnt[3].x;
+ Pnt[1].y = lpPnt[3].y;
+ Pnt[2].x = lpPnt[3].x;
+ Pnt[2].y = lpPnt[3].y;
+ Pnt[3].x = lpPnt[0].x;
+ Pnt[3].y = lpPnt[0].y;
+ Pnt[2].y += pdi->ThreeDHgt;
+ Pnt[3].y += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ Pnt[0].x = lpPnt[3].x;
+ Pnt[0].y = lpPnt[3].y;
+ Pnt[1].x = lpPnt[2].x;
+ Pnt[1].y = lpPnt[2].y;
+ Pnt[2].x = lpPnt[2].x;
+ Pnt[2].y = lpPnt[2].y;
+ Pnt[3].x = lpPnt[3].x;
+ Pnt[3].y = lpPnt[3].y;
+ Pnt[2].y += pdi->ThreeDHgt;
+ Pnt[3].y += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ }
+ else
+ {
+ Pnt[0].x = lpPnt[3].x;
+ Pnt[0].y = lpPnt[3].y;
+ Pnt[1].x = lpPnt[2].x;
+ Pnt[1].y = lpPnt[2].y;
+ Pnt[2].x = lpPnt[2].x;
+ Pnt[2].y = lpPnt[2].y;
+ Pnt[3].x = lpPnt[3].x;
+ Pnt[3].y = lpPnt[3].y;
+ Pnt[0].x += pdi->ThreeDHgt;
+ Pnt[1].x += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ Pnt[0].x = lpPnt[1].x;
+ Pnt[0].y = lpPnt[1].y;
+ Pnt[1].x = lpPnt[2].x;
+ Pnt[1].y = lpPnt[2].y;
+ Pnt[2].x = lpPnt[2].x;
+ Pnt[2].y = lpPnt[2].y;
+ Pnt[3].x = lpPnt[1].x;
+ Pnt[3].y = lpPnt[1].y;
+ Pnt[2].x += pdi->ThreeDHgt;
+ Pnt[3].x += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ }
+
+ if ((percentUsedTimes10 != 0) && (percentUsedTimes10 != 1000))
+ {
+ SelectBrush(hDCMem,hUsedBrsh);
+ Pnt[0].x = lpPnt[0].x;
+ Pnt[0].y = lpPnt[0].y;
+ Pnt[1].x = lpPnt[1].x;
+ Pnt[1].y = lpPnt[1].y;
+ Pnt[2].x = lpPnt[2].x;
+ Pnt[2].y = lpPnt[2].y;
+ Pnt[3].x = lpPnt[3].x;
+ Pnt[3].y = lpPnt[3].y;
+ if (pdi->DrawFlags & DF_USEBARH)
+ {
+ Pnt[1].x = Pnt[0].x + (int)(((DWORD)(Pnt[1].x - Pnt[0].x) * (DWORD)percentUsedTimes10) / 1000L);
+ Pnt[2].x = Pnt[3].x + (int)(((DWORD)(Pnt[2].x - Pnt[3].x) * (DWORD)percentUsedTimes10) / 1000L);
+ }
+ else
+ {
+ Pnt[0].y = Pnt[3].y - (int)(((DWORD)(Pnt[3].y - Pnt[0].y) * (DWORD)percentUsedTimes10) / 1000L);
+ Pnt[1].y = Pnt[2].y - (int)(((DWORD)(Pnt[2].y - Pnt[1].y) * (DWORD)percentUsedTimes10) / 1000L);
+ }
+ Polygon(hDCMem,&Pnt[0],4);
+ SelectBrush(hDCMem,hUsedSBrsh);
+
+ if (pdi->DrawFlags & DF_USEBARH)
+ {
+ Pnt[0].x = Pnt[3].x;
+ Pnt[0].y = Pnt[3].y;
+ Pnt[1].x = Pnt[2].x;
+ Pnt[1].y = Pnt[2].y;
+ Pnt[2].y += pdi->ThreeDHgt;
+ Pnt[3].y += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ Pnt[0].x = lpPnt[0].x;
+ Pnt[0].y = lpPnt[0].y;
+ Pnt[1].x = lpPnt[3].x;
+ Pnt[1].y = lpPnt[3].y;
+ Pnt[2].x = lpPnt[3].x;
+ Pnt[2].y = lpPnt[3].y;
+ Pnt[3].x = lpPnt[0].x;
+ Pnt[3].y = lpPnt[0].y;
+ Pnt[2].y += pdi->ThreeDHgt;
+ Pnt[3].y += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ }
+ else
+ {
+ Pnt[0].x = Pnt[1].x;
+ Pnt[0].y = Pnt[1].y;
+ Pnt[3].x = Pnt[2].x;
+ Pnt[3].y = Pnt[2].y;
+ Pnt[1].x += pdi->ThreeDHgt;
+ Pnt[2].x += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ Pnt[0].x = lpPnt[3].x;
+ Pnt[0].y = lpPnt[3].y;
+ Pnt[1].x = lpPnt[2].x;
+ Pnt[1].y = lpPnt[2].y;
+ Pnt[2].x = lpPnt[2].x;
+ Pnt[2].y = lpPnt[2].y;
+ Pnt[3].x = lpPnt[3].x;
+ Pnt[3].y = lpPnt[3].y;
+ Pnt[0].x += pdi->ThreeDHgt;
+ Pnt[1].x += pdi->ThreeDHgt;
+ Polygon(hDCMem,&Pnt[0],4);
+ }
+ }
+ }
+ else
+ {
+ DrawPie(
+ hDCMem,
+ &pdi->EllipsRect,
+ percentUsedTimes10,
+ pdi->ThreeDHgt,
+ GraphColors
+ );
+ }
+
+ SelectBrush(hDCMem,hOrgBrsh);
+ SelectBitmap(hDCMem,hOrgBm);
+ DeleteBrush(hUsedBrsh);
+ DeleteBrush(hUsedSBrsh);
+ DeleteBrush(hFreeBrsh);
+ DeleteBrush(hFreeSBrsh);
+ DeleteDC(hDCMem);
+
+ return TRUE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateGraphBitmap
+//
+// Synopsis: Creates a %free/%used bitmap to be used in a volume property
+// page
+//
+// Arguments: [hInstance] -- handle to application instance
+// [hwndParent] -- parent window
+// [driveType] -- DRIVE_FIXED, etc (see Win32 GetDriveType())
+// [driveStatus] -- STATUS_OK or STATUS_UNKNOWN
+// [percentUsedTimes10] -- % used space times 10 (i.e. one decimal
+// point of accuracy)
+//
+// Returns: the created bitmap
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+HBITMAP
+CreateGraphBitmap(
+ IN HINSTANCE hInstance,
+ IN HWND hwndParent,
+ IN ULONG driveType,
+ IN ULONG driveStatus,
+ IN ULONG percentUsedTimes10
+ )
+{
+ DRIVEINFO di = {0};
+
+ HBITMAP hBigBitmap = LoadDriveBitmap(
+ hInstance,
+ driveType,
+ driveStatus,
+ &di);
+
+ if (hBigBitmap)
+ {
+ ModifyDriveBitmap(
+ hwndParent,
+ hBigBitmap,
+ driveStatus,
+ percentUsedTimes10,
+ &di);
+ }
+
+ return hBigBitmap;
+}
diff --git a/private/utils/windisk/src/graph.hxx b/private/utils/windisk/src/graph.hxx
new file mode 100644
index 000000000..39b074ab1
--- /dev/null
+++ b/private/utils/windisk/src/graph.hxx
@@ -0,0 +1,32 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: graph.hxx
+//
+// Contents: Declarations for the %free/%used graph creation code
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+#ifndef __GRAPH_HXX__
+#define __GRAPH_HXX__
+
+//
+// Status values
+//
+#define STATUS_OK 1
+#define STATUS_UNKNOWN 2
+
+HBITMAP
+CreateGraphBitmap(
+ HINSTANCE hInstance,
+ HWND hwndParent,
+ ULONG driveType,
+ ULONG driveStatus,
+ ULONG percentUsedTimes10
+ );
+
+#endif // __GRAPH_HXX__
diff --git a/private/utils/windisk/src/hard.bmp b/private/utils/windisk/src/hard.bmp
new file mode 100644
index 000000000..7e0cd6e3e
--- /dev/null
+++ b/private/utils/windisk/src/hard.bmp
Binary files differ
diff --git a/private/utils/windisk/src/headers.hxx b/private/utils/windisk/src/headers.hxx
new file mode 100644
index 000000000..623d33731
--- /dev/null
+++ b/private/utils/windisk/src/headers.hxx
@@ -0,0 +1,95 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: headers.hxx
+//
+// Contents: Main include file for Disk Administrator
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef UNICODE
+#error Disk Administrator MUST build with UNICODE defined!
+#endif // UNICODE
+
+////////////////////////////////////////////////////////////////////////////
+
+extern "C"
+{
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#pragma warning(4:4091)
+#include <ntdddisk.h>
+#pragma warning(default:4091)
+
+#include <ntdskreg.h>
+#include <ntddft.h>
+}
+
+#include <fmifs.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <shellapi.h>
+
+#ifdef WINDISK_EXTENSIONS
+// #include <ole2.h>
+// #include <oleext.h>
+// #include <prividl.h> // Windisk interfaces
+#endif // WINDISK_EXTENSIONS
+
+#include <commdlg.h>
+#include <debug.h> // my debnot.h replacement
+#include <commctrl.h>
+
+#include <dacommon.h> // Common header file for Disk Administrator code
+
+//
+// The constants...
+//
+
+#include "const.h"
+#include "helpid.h"
+#include "resids.h"
+
+#include "messages.h"
+
+//
+// The types...
+//
+
+#include "types.hxx"
+
+//
+// The globals...
+//
+
+#include "global.hxx"
+
+//
+// The function prototypes...
+//
+
+#include "mem.hxx"
+#include "proto.hxx"
+
+//
+// These defines are for virtualized types in engine.cxx, ntlow.cxx
+//
+#define STATUS_CODE NTSTATUS
+#define OK_STATUS STATUS_SUCCESS
+#define RETURN_OUT_OF_MEMORY return STATUS_NO_MEMORY;
+#define HANDLE_T HANDLE
+#define HANDLE_PT PHANDLE
+#define AllocateMemory Malloc
+#define ReallocateMemory Realloc
+#define FreeMemory Free
+
+#include "engine.hxx"
diff --git a/private/utils/windisk/src/help.cxx b/private/utils/windisk/src/help.cxx
new file mode 100644
index 000000000..3cfba9089
--- /dev/null
+++ b/private/utils/windisk/src/help.cxx
@@ -0,0 +1,312 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: help.cxx
+//
+// Contents: Routines to support context-sensitive help in the disk manager.
+//
+// History: 18-Mar-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "help.hxx"
+#include "help2.hxx"
+#include "stleg.hxx"
+
+
+//
+// Define macro to convert between a menu id and its corresponding
+// context-sensitive help id, in a switch statement.
+//
+
+#define MENUID_TO_HELPID(name) case IDM_##name : \
+ HelpContext = HC_DM_MENU_##name; \
+ break;
+
+
+//
+// Current help context
+//
+
+DWORD HelpContext = (DWORD)(-1);
+
+
+//
+// Handle to windows hook for F1 key
+//
+HHOOK hHook;
+
+
+
+LRESULT CALLBACK
+HookProc(
+ IN int nCode,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Hook proc to detect F1 key presses.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PMSG pmsg = (PMSG)lParam;
+
+ if (nCode < 0)
+ {
+ return CallNextHookEx(hHook, nCode, wParam, lParam);
+ }
+
+ if ( ((nCode == MSGF_DIALOGBOX) || (nCode == MSGF_MENU))
+ && (pmsg->message == WM_KEYDOWN)
+ && (LOWORD(pmsg->wParam) == VK_F1))
+ {
+ PostMessage(g_hwndFrame, WM_F1DOWN, nCode, 0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+VOID
+Help(
+ IN LONG Code
+ )
+
+/*++
+
+Routine Description:
+
+ Display context-sensitive help.
+
+Arguments:
+
+ Code - supplies type of message (MSGF_DIALOGBOX, MSGF_MENU, etc).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (HelpContext != -1)
+ {
+ WinHelp(g_hwndFrame, g_HelpFile, HELP_CONTEXT, HelpContext);
+ DrawMenuBar(g_hwndFrame);
+ }
+}
+
+
+
+VOID
+DialogHelp(
+ IN DWORD HelpId
+ )
+/*++
+
+Routine Description:
+
+ Display help on a specific item.
+
+Arguments:
+
+ HelpId -- Supplies the help item to display.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ WinHelp(g_hwndFrame, g_HelpFile, HELP_CONTEXT, HelpId);
+ DrawMenuBar(g_hwndFrame);
+}
+
+
+
+VOID
+SetMenuItemHelpContext(
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ Routine to set help context based on which menu item is currently
+ selected.
+
+Arguments:
+
+ wParam, lParam - params to window proc in WM_MENUSELECT case
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UINT uItem = (UINT)LOWORD(wParam);
+ UINT fuFlags = (UINT)HIWORD(wParam);
+ HMENU hmenu = (HMENU)lParam;
+
+ if (fuFlags == 0xFFFF && hmenu == NULL) // menu closed
+ {
+ HelpContext = (DWORD)(-1);
+
+ //
+ // restore status bar display
+ //
+
+ g_fDoingMenuHelp = FALSE;
+ UpdateStatusBarDisplay();
+ }
+ else if (fuFlags & MF_POPUP) // popup selected
+ {
+ HelpContext = (DWORD)(-1);
+
+ DrawMenuHelpItem(
+ hmenu, // menu of selection
+ uItem, // menu item
+ fuFlags // flags
+ );
+ }
+ else // regular old menu item
+ {
+ switch (uItem)
+ {
+
+//
+// Volume menu
+//
+
+// MENUID_TO_HELPID(PARTITIONLETTER) //BUGBUG
+ MENUID_TO_HELPID(QUIT)
+
+//
+// Partition menu
+//
+
+ MENUID_TO_HELPID(PARTITIONCREATE)
+ MENUID_TO_HELPID(PARTITIONCREATEEX)
+ MENUID_TO_HELPID(PARTITIONDELETE)
+#if i386
+ MENUID_TO_HELPID(PARTITIONACTIVE)
+#else
+ MENUID_TO_HELPID(SECURESYSTEM)
+#endif
+
+ MENUID_TO_HELPID(PARTITIONCOMMIT)
+
+//
+// Configuration sub-menu
+//
+
+ MENUID_TO_HELPID(CONFIGMIGRATE)
+ MENUID_TO_HELPID(CONFIGSAVE)
+ MENUID_TO_HELPID(CONFIGRESTORE)
+
+//
+// Fault-tolerance menu
+//
+
+ MENUID_TO_HELPID(FTESTABLISHMIRROR)
+ MENUID_TO_HELPID(FTBREAKMIRROR)
+ MENUID_TO_HELPID(FTCREATESTRIPE)
+ MENUID_TO_HELPID(FTCREATEPSTRIPE)
+ MENUID_TO_HELPID(FTCREATEVOLUMESET)
+ MENUID_TO_HELPID(FTEXTENDVOLUMESET)
+ MENUID_TO_HELPID(FTRECOVERSTRIPE)
+
+//
+// Tools Menu
+//
+ MENUID_TO_HELPID(VOL_FORMAT)
+ MENUID_TO_HELPID(VOL_LETTER)
+ MENUID_TO_HELPID(VOL_EJECT)
+ MENUID_TO_HELPID(VOL_PROPERTIES)
+
+//
+// View menu
+//
+
+ MENUID_TO_HELPID(VIEWVOLUMES)
+ MENUID_TO_HELPID(VIEWDISKS)
+ MENUID_TO_HELPID(VIEW_REFRESH)
+
+//
+// Options menu
+//
+
+ MENUID_TO_HELPID(OPTIONSTOOLBAR)
+ MENUID_TO_HELPID(OPTIONSSTATUS)
+ MENUID_TO_HELPID(OPTIONSLEGEND)
+ MENUID_TO_HELPID(OPTIONSCOLORS)
+ MENUID_TO_HELPID(OPTIONSDISK)
+ MENUID_TO_HELPID(OPTIONSDISPLAY)
+ MENUID_TO_HELPID(OPTIONSCUSTTOOLBAR)
+
+//
+// Help menu
+//
+
+ MENUID_TO_HELPID(HELPCONTENTS)
+ MENUID_TO_HELPID(HELPSEARCH)
+ MENUID_TO_HELPID(HELPHELP)
+ MENUID_TO_HELPID(HELPABOUT)
+
+ default:
+ HelpContext = (DWORD)(-1);
+ }
+
+ //
+ // Set the status bar text
+ //
+
+ DrawMenuHelpItem(
+ hmenu, // menu of selection
+ uItem, // menu item
+ fuFlags // flags
+ );
+ }
+}
+
+
+VOID
+InitHelp(
+ VOID
+ )
+{
+ hHook = SetWindowsHookEx(
+ WH_MSGFILTER,
+ HookProc,
+ NULL,
+ GetCurrentThreadId());
+}
+
+
+VOID
+TermHelp(
+ VOID
+ )
+{
+ UnhookWindowsHookEx(hHook);
+}
diff --git a/private/utils/windisk/src/help.hxx b/private/utils/windisk/src/help.hxx
new file mode 100644
index 000000000..b1db28843
--- /dev/null
+++ b/private/utils/windisk/src/help.hxx
@@ -0,0 +1,45 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: help.hxx
+//
+// Contents: Declarations for routines to support context-sensitive help
+//
+// History: 18-Mar-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __HELP_HXX__
+#define __HELP_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+InitHelp(
+ VOID
+ );
+
+VOID
+TermHelp(
+ VOID
+ );
+
+VOID
+Help(
+ IN LONG Code
+ );
+
+VOID
+DialogHelp(
+ IN DWORD HelpId
+ );
+
+VOID
+SetMenuItemHelpContext(
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+#endif // __HELP_HXX__
diff --git a/private/utils/windisk/src/help2.cxx b/private/utils/windisk/src/help2.cxx
new file mode 100644
index 000000000..07ebce841
--- /dev/null
+++ b/private/utils/windisk/src/help2.cxx
@@ -0,0 +1,506 @@
+//----------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: help2.cxx
+//
+// Contents: Status bar help for toolbar & menu bar items
+//
+// History: 15-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "resids.h"
+#include "stleg.hxx"
+#include "menudict.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+GetMenuHelp(
+ IN HMENU hmenu,
+ IN UINT uItem,
+ IN UINT fuFlags,
+ OUT PWSTR Buffer,
+ IN UINT cchBuf
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+// the Partition menu is the first menu on the menu bar (0 in 0-based counting)
+
+#define PARTITION_MENU_INDEX 0
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL g_fDoingMenuHelp;
+
+struct MENU_HELP
+{
+ UINT uItem; // menu id
+ UINT uID; // string id of help text
+};
+
+
+MENU_HELP MenuHelpArray[] =
+{
+//
+// Partition menu
+//
+
+ IDM_PARTITIONCREATE, IDS_HELP_CREATE,
+ IDM_PARTITIONCREATEEX, IDS_HELP_CREATEEX,
+ IDM_PARTITIONDELETE, IDS_HELP_DELETE,
+ IDM_FTCREATEVOLUMESET, IDS_HELP_CREATEVOLSET,
+ IDM_FTEXTENDVOLUMESET, IDS_HELP_EXTENDVOLSET,
+ IDM_FTCREATESTRIPE, IDS_HELP_CREATESTRIPE,
+#if i386
+ IDM_PARTITIONACTIVE, IDS_HELP_MARKACTIVE,
+#else
+ IDM_SECURESYSTEM, IDS_HELP_SECURE,
+#endif
+
+ //
+ // Configuration sub-menu
+ //
+
+ IDM_CONFIGSAVE, IDS_HELP_SAVECONFIG,
+ IDM_CONFIGRESTORE, IDS_HELP_RESTORECONFIG,
+ IDM_CONFIGMIGRATE, IDS_HELP_SEARCHCONFIG,
+
+ IDM_PARTITIONCOMMIT, IDS_HELP_PARTITIONCOMMIT,
+ IDM_QUIT, IDS_HELP_QUIT,
+
+//
+// Fault-tolerance menu
+//
+
+ IDM_FTESTABLISHMIRROR, IDS_HELP_ESTABLISHMIRROR,
+ IDM_FTBREAKMIRROR, IDS_HELP_BREAKMIRROR,
+ IDM_FTCREATEPSTRIPE, IDS_HELP_CREATEPSET,
+ IDM_FTRECOVERSTRIPE, IDS_HELP_REGENSTRIPE,
+
+//
+// Tools menu
+//
+
+ IDM_VOL_FORMAT, IDS_HELP_FORMAT,
+ IDM_VOL_LETTER, IDS_HELP_DRIVELET,
+#if defined( DBLSPACE_ENABLED )
+ IDM_VOL_DBLSPACE, IDS_HELP_DBLSPACE,
+ IDM_VOL_AUTOMOUNT, IDS_HELP_AUTOMOUNT,
+#endif // DBLSPACE_ENABLED
+ IDM_VOL_PROPERTIES, IDS_HELP_PROPERTIES,
+
+
+//
+// View menu
+//
+
+ IDM_VIEWVOLUMES, IDS_HELP_VOLUMESVIEW,
+ IDM_VIEWDISKS, IDS_HELP_DISKSVIEW,
+ IDM_VIEW_REFRESH, IDS_HELP_REFRESH,
+
+//
+// Options menu
+//
+
+ IDM_OPTIONSTOOLBAR, IDS_HELP_TOOLBAR,
+ IDM_OPTIONSSTATUS, IDS_HELP_STATUSBAR,
+ IDM_OPTIONSLEGEND, IDS_HELP_LEGEND,
+ IDM_OPTIONSCOLORS, IDS_HELP_COLORS,
+ IDM_OPTIONSDISK, IDS_HELP_OPTIONSDISK,
+ IDM_OPTIONSDISPLAY, IDS_HELP_REGIONDISPLAY,
+ IDM_OPTIONSCUSTTOOLBAR, IDS_HELP_CUSTTOOLBAR,
+
+//
+// Help menu
+//
+
+ IDM_HELPCONTENTS, IDS_HELP_HELPCONTENTS,
+ IDM_HELPSEARCH, IDS_HELP_HELPSEARCH,
+ IDM_HELPHELP, IDS_HELP_HELPHELP,
+ IDM_HELPABOUT, IDS_HELP_HELPABOUT,
+
+//
+// Debug menu (only for debug builds)
+//
+
+#if DBG == 1
+ IDM_DEBUGALLOWDELETES, IDS_HELP_DELETEALL,
+ IDM_DEBUGLOG, IDS_HELP_LOG,
+ IDM_RAID, IDS_HELP_RAID,
+#endif // DBG == 1
+
+//
+// Menu items that don't appear in the top-level menu (i.e. context-menu only)
+//
+
+ IDM_PROPERTIES, IDS_HELP_PROPERTIES,
+ IDM_NOVALIDOPERATION, IDS_HELP_NOVALIDOPERATION,
+
+//
+// End-of-data sentinel
+//
+
+ 0, 0
+};
+
+
+//
+// This is an array where the index is the 0-based index of the top-level
+// popup menu and the value is the resource string id.
+//
+// There are two arrays: one for the normal NT, one for advanced server, which
+// has an extra menu item.
+//
+
+UINT PopupMenuHelpArray[] =
+{
+ IDS_HELP_MENU_PARTITION,
+ IDS_HELP_MENU_VOLUMES,
+ IDS_HELP_MENU_VIEW,
+ IDS_HELP_MENU_OPTIONS,
+ IDS_HELP_MENU_HELP
+};
+
+UINT AdvancedServerPopupMenuHelpArray[] =
+{
+ IDS_HELP_MENU_PARTITION,
+ IDS_HELP_MENU_FT,
+ IDS_HELP_MENU_VOLUMES,
+ IDS_HELP_MENU_VIEW,
+ IDS_HELP_MENU_OPTIONS,
+ IDS_HELP_MENU_HELP
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitMenuHelp
+//
+// Synopsis: Initialize menu help: determine all menu bar menu handles
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+InitMenuHelp(
+ VOID
+ )
+{
+ g_fDoingMenuHelp = FALSE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetMenuHelp
+//
+// Synopsis: Gets the help string for a particular menu and item
+//
+// Arguments: [hmenu] -- menu handle of menu to get help for
+// [uItem] -- menu item index
+// [fuFlags] -- menu item flags
+// [Buffer] -- a buffer to write the help string to
+// [cchBuf] -- number of characters in the buffer
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+GetMenuHelp(
+ IN HMENU hmenu,
+ IN UINT uItem,
+ IN UINT fuFlags,
+ OUT PWSTR Buffer,
+ IN UINT cchBuf
+ )
+{
+ UINT i;
+
+ if (cchBuf == 0)
+ {
+ return;
+ }
+
+ Buffer[0] = TEXT('\0');
+
+ if (fuFlags & MF_SEPARATOR) // display nothing for a separator
+ {
+ return;
+ }
+
+ if (fuFlags & MF_POPUP) // a popup selected
+ {
+ HMENU hmenuFrame = GetMenu(g_hwndFrame);
+
+ //
+ // It is a menu, not an item in itself
+ //
+
+ if (hmenu == hmenuFrame)
+ {
+ UINT resID;
+
+ if (g_IsLanmanNt)
+ {
+ if (uItem >= ARRAYLEN(AdvancedServerPopupMenuHelpArray))
+ {
+ daDebugOut((DEB_ERROR,"Illegal WinNT AS menu id %d!\n",uItem));
+ return; // illegal uItem!
+ }
+
+ resID = AdvancedServerPopupMenuHelpArray[uItem];
+ }
+ else
+ {
+ if (uItem >= ARRAYLEN(PopupMenuHelpArray))
+ {
+ daDebugOut((DEB_ERROR,"Illegal WinNT menu id %d!\n",uItem));
+ return; // illegal uItem!
+ }
+
+ resID = PopupMenuHelpArray[uItem];
+ }
+
+ LoadString(
+ g_hInstance,
+ resID,
+ Buffer,
+ cchBuf);
+ return;
+ }
+ else if (hmenu == GetSubMenu(hmenuFrame, PARTITION_MENU_INDEX))
+ {
+ //
+ // the "Configuration ->" sub-menu is the only sub-menu on
+ // the "Partition" menu, so ignore the index and just load the
+ // configuration menu help
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_HELP_MENU_CONFIG,
+ Buffer,
+ cchBuf);
+ return;
+ }
+#if DBG == 1
+ else if (hmenu == GetSubMenu(hmenuFrame, g_IsLanmanNt ? 5 : 4))
+ {
+ //
+ // the "Debug ->" sub-menu is the only sub-menu on the "Help"
+ // menu, so ignore the index and just load the debug menu help
+ //
+
+ LoadString(
+ g_hInstance,
+ IDS_HELP_MENU_DEBUG,
+ Buffer,
+ cchBuf);
+ return;
+ }
+#endif // DBG == 1
+ else
+ {
+ daDebugOut((DEB_IERROR,
+ "Unknown menu! hmenu = 0x%x, uItem = %d, flags = 0x%x\n",
+ hmenu,
+ uItem,
+ fuFlags));
+
+ return;
+ }
+ }
+
+ //
+ // It is an actual item
+ //
+
+#ifdef WINDISK_EXTENSIONS
+
+ if (MenuItems.IsExtensionId(uItem)) // an extension item?
+ {
+ MenuItemType* pMenu = MenuItems.LookupMenuItem(uItem);
+
+ UINT cchItem = lstrlen(pMenu->pszMenuHelp) + 1;
+ UINT cchCopy = min(cchItem, cchBuf);
+ wcsncpy(Buffer, pMenu->pszMenuHelp, cchCopy);
+ return;
+ }
+ else
+ if (ContextMenuItems.IsExtensionId(uItem)) // an extension item?
+ {
+ MenuItemType* pMenu = ContextMenuItems.LookupMenuItem(uItem);
+
+ UINT cchItem = lstrlen(pMenu->pszMenuHelp) + 1;
+ UINT cchCopy = min(cchItem, cchBuf);
+ wcsncpy(Buffer, pMenu->pszMenuHelp, cchCopy);
+ return;
+ }
+ else // a normal, internal (non-extension) item
+ {
+#endif // WINDISK_EXTENSIONS
+
+ for (i=0; 0 != MenuHelpArray[i].uItem; i++)
+ {
+ if (uItem == MenuHelpArray[i].uItem)
+ {
+ LoadString(
+ g_hInstance,
+ MenuHelpArray[i].uID,
+ Buffer,
+ cchBuf);
+ return;
+ }
+ }
+
+#ifdef WINDISK_EXTENSIONS
+ }
+#endif // WINDISK_EXTENSIONS
+
+ daDebugOut((DEB_TRACE, "No help found for item %d\n", uItem));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PaintHelpStatusBar
+//
+// Synopsis: Paint the help bar (space borrowed from the status bar, if any)
+//
+// Arguments: [Text] -- help text to print
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+// BUGBUG: This will write off the right side of the bevelled window
+//
+//----------------------------------------------------------------------------
+
+VOID
+PaintHelpStatusBar(
+ IN LPTSTR Text
+ )
+{
+ RECT rc;
+ HDC hdcFrame = GetDC(g_hwndFrame);
+ HFONT hFontOld;
+ LPTSTR HelpString;
+
+ GetClientRect(g_hwndFrame,&rc);
+ rc.top = rc.bottom - g_dyStatus;
+ rc.left = 8 * g_dyBorder;
+ rc.right = GraphWidth - (8*g_dyBorder);
+
+ hFontOld = SelectFont(hdcFrame, g_hFontStatus);
+
+ if (Text)
+ {
+ HelpString = Text;
+ }
+ else
+ {
+ HelpString = TEXT("");
+ }
+
+ DrawStatusAreaItem(&rc, hdcFrame, HelpString);
+
+ if (hFontOld)
+ {
+ SelectFont(hdcFrame,hFontOld);
+ }
+
+ ReleaseDC(g_hwndFrame,hdcFrame);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DrawMenuHelpItem
+//
+// Synopsis: Draw the menu help for an item
+//
+// Arguments: [hmenu] -- menu handle of menu to get help for
+// [uItem] -- menu item index
+// [fuFlags] -- menu item flags
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DrawMenuHelpItem(
+ IN HMENU hmenu,
+ IN UINT uItem,
+ IN UINT fuFlags
+ )
+{
+ if (g_StatusBar)
+ {
+ //
+ // We use the same space as the status bar, so if the user isn't
+ // viewing the status bar, we don't show any help
+ //
+
+ TCHAR buf[256];
+
+ GetMenuHelp(hmenu, uItem, fuFlags, buf, ARRAYLEN(buf));
+ PaintHelpStatusBar(buf);
+
+ g_fDoingMenuHelp = TRUE;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetTooltip
+//
+// Synopsis: Load a tooltip
+//
+// Arguments: [uItem] -- menu item index
+//
+// Returns: resource id of tooltip string
+//
+// History: 26-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+UINT
+GetTooltip(
+ IN UINT uItem
+ )
+{
+ for (int i=0; 0 != MenuHelpArray[i].uItem; i++)
+ {
+ if (uItem == MenuHelpArray[i].uItem)
+ {
+ return MenuHelpArray[i].uID;
+ }
+ }
+
+ return 0; // error, really
+}
diff --git a/private/utils/windisk/src/help2.hxx b/private/utils/windisk/src/help2.hxx
new file mode 100644
index 000000000..61914a25e
--- /dev/null
+++ b/private/utils/windisk/src/help2.hxx
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: help2.hxx
+//
+// Contents: Status bar help for toolbar & menu bar items
+//
+// History: 15-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __HELP2_HXX__
+#define __HELP2_HXX__
+
+VOID
+InitMenuHelp(
+ VOID
+ );
+
+VOID
+PaintHelpStatusBar(
+ IN LPTSTR Text
+ );
+
+VOID
+DrawMenuHelpItem(
+ IN HMENU hmenu,
+ IN UINT uItem,
+ IN UINT fuFlags
+ );
+
+UINT
+GetTooltip(
+ IN UINT uItem
+ );
+
+#endif // __HELP2_HXX__
diff --git a/private/utils/windisk/src/helpid.h b/private/utils/windisk/src/helpid.h
new file mode 100644
index 000000000..cf64f260c
--- /dev/null
+++ b/private/utils/windisk/src/helpid.h
@@ -0,0 +1,220 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: helpid.h
+//
+// Contents: Context ids for context-sensitive help for the disk manager
+//
+// History: 18-Mar-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __HELPID_H__
+#define __HELPID_H__
+
+//
+// NOTE: if you change the numbers in this file, you must notify User Education
+// NOTE: so they can change the help file sources
+//
+
+//
+// All ids in this file start with HC_DM, as in "Help Context for Disk Manager"
+//
+
+//
+// Menu items. In the form HC_DM_MENU_xxx, where xxx matches the name used
+// in windisk.rc for the menu item (of the form IDM_xxx).
+//
+
+//
+// The volume menu
+//
+
+#define HC_DM_MENU_QUIT 118
+
+//
+// The partition menu
+//
+
+#define HC_DM_MENU_PARTITIONCREATE 110
+#define HC_DM_MENU_PARTITIONCREATEEX 111
+#define HC_DM_MENU_PARTITIONDELETE 112
+#define HC_DM_MENU_FTCREATEVOLUMESET 113
+#define HC_DM_MENU_FTEXTENDVOLUMESET 114
+#define HC_DM_MENU_FTCREATESTRIPE 115
+#if i386
+#define HC_DM_MENU_PARTITIONACTIVE 116
+#else
+#define HC_DM_MENU_SECURESYSTEM 119
+#endif
+#define HC_DM_MENU_VOL_LETTER 117 // really in tools menu
+#define HC_DM_MENU_PARTITIONEXIT 118
+#define HC_DM_MENU_PARTITIONCOMMIT 120
+
+//
+// The configuration menu
+//
+
+#define HC_DM_MENU_CONFIGMIGRATE 210
+#define HC_DM_MENU_CONFIGSAVE 211
+#define HC_DM_MENU_CONFIGRESTORE 212
+#define HC_DM_MENU_CONFIG 213
+
+//
+// The fault tolerance menu
+//
+
+#define HC_DM_MENU_FTESTABLISHMIRROR 310
+#define HC_DM_MENU_FTBREAKMIRROR 311
+#define HC_DM_MENU_FTCREATEPSTRIPE 312
+#define HC_DM_MENU_FTRECOVERSTRIPE 313
+
+//
+// The tools menu
+//
+
+#define HC_DM_MENU_AUTOMOUNT 610
+#if defined( DBLSPACE_ENABLED )
+#define HC_DM_MENU_DBLSPACE 611
+#endif // DBLSPACE_ENABLED
+#define HC_DM_MENU_CDROM 612
+#define HC_DM_MENU_VOL_FORMAT 613
+#define HC_DM_MENU_LABEL 614
+
+
+#define HC_DM_MENU_VOL_EJECT 710
+#define HC_DM_MENU_VOL_PROPERTIES 720
+
+//
+// View Menu
+//
+
+#define HC_DM_MENU_VIEWVOLUMES 810
+#define HC_DM_MENU_VIEWDISKS 820
+#define HC_DM_MENU_VIEW_REFRESH 830
+
+//
+// The options menu
+//
+
+#define HC_DM_MENU_OPTIONSTOOLBAR 416
+#define HC_DM_MENU_OPTIONSSTATUS 410
+#define HC_DM_MENU_OPTIONSLEGEND 411
+#define HC_DM_MENU_OPTIONSCOLORS 412
+#define HC_DM_MENU_OPTIONSDISK 414
+#define HC_DM_MENU_OPTIONSDISPLAY 413
+#define HC_DM_MENU_OPTIONSCUSTTOOLBAR 415
+
+
+//
+// The help menu
+//
+
+#define HC_DM_MENU_HELPCONTENTS 510
+#define HC_DM_MENU_HELPSEARCH 511
+#define HC_DM_MENU_HELPHELP 512
+#define HC_DM_MENU_HELPABOUT 513
+
+
+//
+// The system menu
+//
+
+#define HC_DM_SYSMENU_RESTORE 910
+#define HC_DM_SYSMENU_MOVE 911
+#define HC_DM_SYSMENU_SIZE 912
+#define HC_DM_SYSMENU_MINIMIZE 913
+#define HC_DM_SYSMENU_MAXIMIZE 914
+#define HC_DM_SYSMENU_CLOSE 915
+#define HC_DM_SYSMENU_SWITCHTO 916
+
+//
+// Dialog boxes. In the form HC_DM_DLG_xxx, where xxx is some reasonably
+// descriptive name for the dialog.
+//
+//
+// These dialog boxes do not have help buttons:
+//
+// - About
+// - Searching for Previous Installation
+// - Confirmation dialogs
+
+//
+// Min/Max dialogs for creating various items
+//
+
+#define HC_DM_DLG_CREATEPRIMARY 1010
+#define HC_DM_DLG_CREATEEXTENDED 1011
+#define HC_DM_DLG_CREATELOGICAL 1012
+#define HC_DM_DLG_CREATEVOLUMESET 1013
+#define HC_DM_DLG_EXTENDVOLUMESET 1014
+#define HC_DM_DLG_CREATESTRIPESET 1015
+#define HC_DM_DLG_CREATEPARITYSTRIPE 1016
+
+//
+// Dialog for assigning drive letters
+//
+
+#define HC_DM_DLG_DRIVELETTER 1020
+
+//
+// Dialog for determining region sizing
+//
+
+#define HC_DM_DLG_DISPLAYOPTION 1030
+
+//
+// Dialog for determining disk sizing
+//
+
+#define HC_DM_DLG_DISKDISPLAY 1075
+
+//
+// Configuration migration dialog to select previous installation
+//
+
+#define HC_DM_DLG_SELECTINSTALLATION 1040
+
+//
+// Colors and patterns dialog
+//
+
+#define HC_DM_COLORSANDPATTERNS 1050
+
+#define HC_DM_DLG_CUSTOMIZETOOL 1095
+
+//
+// DoubleSpace dialog
+//
+
+#define HC_DM_DLG_DOUBLESPACE 1060
+#define HC_DM_DLG_DOUBLESPACE_MOUNT 1061
+
+//
+// Format dialog
+//
+
+#define HC_DM_DLG_FORMAT 1070
+
+//
+// Label dialog
+//
+
+#define HC_DM_DLG_LABEL 1080
+
+//
+// CdRom dialog
+//
+
+#define HC_DM_DLG_CDROM 1090
+
+//
+// Chkdsk dialog
+//
+
+#define HC_DM_DLG_CHKDSK 1100
+
+
+#endif // __HELPID_H__
diff --git a/private/utils/windisk/src/init.cxx b/private/utils/windisk/src/init.cxx
new file mode 100644
index 000000000..c7396e2b6
--- /dev/null
+++ b/private/utils/windisk/src/init.cxx
@@ -0,0 +1,949 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: init.cxx
+//
+// Contents: Code for initializing the Disk Administrator
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <controls.hxx>
+#include <util.hxx>
+
+#include "cdrom.hxx"
+#include "chkdsk.hxx"
+#include "dblspace.hxx"
+#include "dialogs.h"
+#include "dlgs.hxx"
+#include "drives.hxx"
+#include "fmifs.hxx"
+#include "ft.hxx"
+#include "init.hxx"
+#include "help2.hxx"
+#include "listbox.hxx"
+#include "network.hxx"
+#include "nt.hxx"
+#include "oleclass.hxx"
+#include "profile.hxx"
+#include "rectpriv.hxx"
+#include "stleg.hxx"
+#include "tbar.hxx"
+#include "volview.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+HWND g_InitDlg;
+BOOLEAN g_StartedAsIcon = FALSE;
+BOOLEAN g_InitDlgComplete = FALSE;
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+CreateDiskState(
+ OUT PDISKSTATE *DiskState,
+ IN DWORD Disk,
+ OUT PBOOL SignatureCreated
+ );
+
+BOOL
+InitializeWindowData(
+ VOID
+ );
+
+DWORD
+InitializeDiskData(
+ VOID
+ );
+
+LPTSTR
+LoadOneString(
+ IN DWORD StringID
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+// class name for frame window
+
+TCHAR g_szFrame[] = TEXT("fdFrame");
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeApp
+//
+// Synopsis: Main initialization routine for Disk Administrator.
+//
+// Arguments: (none)
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// Modifies: lots and lots of state variables
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+InitializeApp(
+ VOID
+ )
+{
+ HDC hdcScreen = GetDC(NULL);
+
+ ReadProfile();
+
+ if (!InitOle())
+ {
+ daDebugOut((DEB_ERROR, "Failed to initialize OLE\n"));
+ return FALSE;
+ }
+
+ if (!InitializeWindowData())
+ {
+ daDebugOut((DEB_ERROR, "Failed to initialize Windows data\n"));
+ return FALSE;
+ }
+
+ if (InitializeDiskData() != NO_ERROR)
+ {
+ return FALSE;
+ }
+
+ DetermineExistence();
+
+ //
+ // Fill the listbox with bogus data, and draw the items. Set the
+ // initial list box selection cursor (don't allow to fall on an
+ // extended partition).
+ //
+ InitializeListBox(g_hwndList);
+ LBCursorListBoxItem = 0;
+ ResetLBCursorRegion();
+
+ //
+ // Initialize the listview control (volumes view)
+ //
+
+ InitializeListview();
+
+#ifdef WINDISK_EXTENSIONS
+
+ //
+ // Load the extension code
+ //
+
+ if (!GetExtensions())
+ {
+ daDebugOut((DEB_ERROR, "Failed to get the extension classes\n"));
+ return FALSE;
+ }
+
+#endif // WINDISK_EXTENSIONS
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LPTSTR
+LoadOneString(
+ IN DWORD StringID
+ )
+
+/*++
+
+Routine Description:
+
+ Loads a string from the resource file and allocates a buffer of exactly
+ the right size to hold it.
+
+Arguments:
+
+ StringID - resource ID of string to load
+
+Return Value:
+
+ pointer to buffer. If string is not found, the first
+ (and only) char in the returned buffer will be 0.
+
+--*/
+
+{
+ TCHAR text[500];
+ LPTSTR buffer;
+
+ text[0] = TEXT('\0');
+ LoadString(g_hInstance, StringID, text, ARRAYLEN(text));
+ buffer = (LPTSTR)Malloc((lstrlen(text)+1)*sizeof(TCHAR));
+ lstrcpy(buffer, text);
+ return buffer;
+}
+
+
+
+BOOL
+InitializeWindowData(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes Windows data. It registers the frame window
+ class, creates the frame window, initializes all controls, and determines
+ all the global constant drawing metrics.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ boolean value indicating success or failure.
+
+--*/
+
+{
+ WNDCLASS wc;
+ TCHAR titleString[80];
+ HDC hdcScreen = GetDC(NULL);
+ TEXTMETRIC tm;
+ BITMAP bitmap;
+ HFONT hfontT;
+ unsigned i;
+
+ //
+ // Load cursors
+ //
+
+ g_hCurWait = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
+ g_hCurNormal = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
+
+ // fonts
+
+#ifdef JAPAN
+ g_hFontGraph = CreateFont(
+ GetHeightFromPoints(10),
+ 0,
+ 0,
+ 0,
+ 400,
+ FALSE,
+ FALSE,
+ FALSE,
+ SHIFTJIS_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ VARIABLE_PITCH | FF_SWISS,
+ TEXT("System")
+ );
+#else
+ g_hFontGraph = CreateFont(
+ GetHeightFromPoints(8),
+ 0,
+ 0,
+ 0,
+ 400,
+ FALSE,
+ FALSE,
+ FALSE,
+ ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ VARIABLE_PITCH | FF_SWISS,
+ TEXT("Helv")
+ );
+#endif
+
+ g_hFontLegend = g_hFontGraph;
+ g_hFontStatus = g_hFontGraph;
+
+#ifdef JAPAN
+ g_hFontGraphBold = CreateFont(
+ GetHeightFromPoints(10),
+ 0,
+ 0,
+ 0,
+ 700,
+ FALSE,
+ FALSE,
+ FALSE,
+ SHIFTJIS_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ VARIABLE_PITCH | FF_SWISS,
+ TEXT("System")
+ );
+#else
+ g_hFontGraphBold = CreateFont(
+ GetHeightFromPoints(8),
+ 0,
+ 0,
+ 0,
+ 700,
+ FALSE,
+ FALSE,
+ FALSE,
+ ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ VARIABLE_PITCH | FF_SWISS,
+ TEXT("Helv")
+ );
+#endif
+
+ //
+ // get the text metrics
+ //
+
+ hfontT = SelectFont(hdcScreen, g_hFontGraph);
+ GetTextMetrics(hdcScreen, &tm);
+ if (hfontT)
+ {
+ SelectFont(hdcScreen, hfontT);
+ }
+
+ g_hPenNull = CreatePen(PS_NULL , 0, 0);
+ g_hPenThinSolid = CreatePen(PS_SOLID, PEN_WIDTH, RGB(0, 0, 0));
+
+ GraphHeight = 25 * tm.tmHeight / 4; // 6.25 x font height
+
+ g_dyBorder = GetSystemMetrics(SM_CYBORDER);
+ g_dyStatus = tm.tmHeight + tm.tmExternalLeading + 7 * g_dyBorder;
+
+ g_wLegendItem = GetSystemMetrics(SM_CXHTHUMB);
+ g_dyLegendSep = 2*g_dyBorder; // used to be g_wLegendItem / 2, but that's too much
+
+ // set up brushes
+
+ for (i=0; i<BRUSH_ARRAY_SIZE; i++)
+ {
+ g_Brushes[i] = MyCreateHatchBrush(
+ AvailableHatches[BrushHatches[i]],
+ AvailableColors[BrushColors[i]]
+ );
+ }
+
+ g_hBrushFreeLogical = CreateHatchBrush(HS_FDIAGONAL, RGB(128, 128, 128));
+ g_hBrushFreePrimary = CreateHatchBrush(HS_BDIAGONAL, RGB(128, 128, 128));
+
+ // load legend strings
+
+ for (i = IDS_LEGEND_FIRST; i <= IDS_LEGEND_LAST; i++)
+ {
+ if (NULL == (LegendLabels[i-IDS_LEGEND_FIRST] = LoadOneString(i)))
+ {
+ return FALSE;
+ }
+ }
+
+ if ( ((wszUnformatted = LoadOneString(IDS_UNFORMATTED)) == NULL)
+ || ((wszUnknown = LoadOneString(IDS_UNKNOWN)) == NULL))
+ {
+ return FALSE;
+ }
+
+ BarTopYOffset = tm.tmHeight;
+ BarHeight = 21 * tm.tmHeight / 4;
+ BarBottomYOffset = BarTopYOffset + BarHeight;
+ dxBarTextMargin = 5*tm.tmAveCharWidth/4;
+ dyBarTextLine = tm.tmHeight;
+
+ dxDriveLetterStatusArea = 5 * tm.tmAveCharWidth / 2
+ + 8 * g_dyBorder // margin on either side
+ ;
+
+ //
+ // Get the small disk bitmap that goes to the left of the disk bar
+ //
+
+ g_hBitmapSmallDisk = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_SMALLDISK));
+ GetObject(g_hBitmapSmallDisk, sizeof(BITMAP), &bitmap);
+ dxSmallDisk = bitmap.bmWidth;
+ dySmallDisk = bitmap.bmHeight;
+
+ xSmallDisk = dxSmallDisk / 2;
+ ySmallDisk = BarTopYOffset + (2*dyBarTextLine) - dySmallDisk - tm.tmDescent;
+
+ //
+ // Get the removable disk bitmap
+ //
+
+ g_hBitmapRemovableDisk = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_REMOVABLEDISK));
+ GetObject(g_hBitmapRemovableDisk, sizeof(BITMAP), &bitmap);
+ dxRemovableDisk = bitmap.bmWidth;
+ dyRemovableDisk = bitmap.bmHeight;
+
+ xRemovableDisk = dxRemovableDisk / 2;
+ yRemovableDisk = BarTopYOffset + (2*dyBarTextLine) - dyRemovableDisk - tm.tmDescent;
+
+ //
+ // Get the small CD-ROM bitmap
+ //
+
+ g_hBitmapSmallCdRom = LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_SMALLCDROM));
+ GetObject(g_hBitmapSmallCdRom, sizeof(BITMAP), &bitmap);
+ dxSmallCdRom = bitmap.bmWidth;
+ dySmallCdRom = bitmap.bmHeight;
+
+ xSmallCdRom = xSmallDisk;
+ ySmallCdRom = ySmallDisk;
+
+
+ //
+ // Now, some numbers for drawing the bars
+ //
+
+ BarLeftX = 7 * dxSmallDisk;
+
+ // BarWidthMargin: the total amount of space that must exist
+ // excepting the bar itself
+ BarWidthMargin = BarLeftX + (5 * tm.tmAveCharWidth);
+
+ // BarWidthMinimum: the smallest allowable bar width
+ BarWidthMinimum = BarWidthMargin;
+
+ MinimumWindowWidth = BarWidthMargin + BarWidthMinimum;
+
+ DiskN = LoadOneString(IDS_DISKN);
+ CdRomN = LoadOneString(IDS_CDROMN);
+
+ //
+ // calculate the minimum region size
+ //
+
+ TCHAR szDrive[] = TEXT("A:");
+ SIZE size = {0};
+
+ hfontT = SelectFont(hdcScreen, g_hFontGraphBold);
+ if (!GetTextExtentPoint32(hdcScreen, szDrive, ARRAYLEN(szDrive) - 1, &size))
+ {
+ daDebugOut((DEB_ERROR,
+ "GetTextExtentPoint32 failed, error = 0x%08lx\n",
+ GetLastError()
+ ));
+ }
+ SelectFont(hdcScreen, hfontT);
+
+ ReleaseDC(NULL, hdcScreen);
+
+ g_MinimumRegionSize = size.cx + 2 * dxBarTextMargin;
+
+ // register the frame class
+
+ wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
+ wc.lpfnWndProc = MyFrameWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = g_hInstance;
+ wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDFDISK));
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockBrush(LTGRAY_BRUSH);
+ wc.lpszMenuName = MAKEINTRESOURCE(IDFDISK);
+ wc.lpszClassName = g_szFrame;
+
+ if (!RegisterClass(&wc))
+ {
+ return FALSE;
+ }
+
+ LoadString(g_hInstance, IDS_APPNAME, titleString, ARRAYLEN(titleString));
+
+ // create the frame window. Note that this also creates the listbox
+ // and the listview (volumes view), and the toolbar.
+
+ g_hwndFrame = CreateWindowEx(
+ 0,
+// WS_EX_WINDOWEDGE, //BUGBUG: not in Daytona USER
+ g_szFrame,
+ titleString,
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ ProfileWindowX,
+ ProfileWindowY,
+ ProfileWindowW,
+ ProfileWindowH,
+ NULL,
+ NULL,
+ g_hInstance,
+ NULL
+ );
+
+ if (NULL == g_hwndFrame)
+ {
+ return FALSE;
+ }
+
+ InitToolbarButtons();
+
+ //
+ // Initialize the menu help
+ //
+
+ InitMenuHelp();
+
+ //
+ // Initialize the custom controls
+ //
+
+ UseRectControl(g_hInstance);
+ UseWindiskControls(g_hInstance);
+
+ return TRUE;
+}
+
+
+
+VOID
+CreateDiskState(
+ OUT PDISKSTATE* DiskState,
+ IN DWORD Disk,
+ OUT PBOOL SignatureCreated
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is designed to be called once, at initialization time,
+ per disk. It creates and initializes a disk state -- which includes
+ creating a memory DC and compatible bitmap for drawing the disk's
+ graph, and getting some information that is static in nature about
+ the disk (ie, its total size.)
+
+Arguments:
+
+ DiskState - structure whose fields are to be intialized
+
+ Disk - number of disk
+
+ SignatureCreated - received boolean indicating whether an FT signature was created for
+ the disk.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PDISKSTATE diskState = (PDISKSTATE)Malloc(sizeof(DISKSTATE));
+
+ diskState->LeftRight = (PLEFTRIGHT)Malloc(0);
+ diskState->Selected = (PBOOLEAN)Malloc(0);
+ diskState->Disk = Disk;
+
+ // the memory DC and bitmap are created after a resize event
+
+ diskState->hDCMem = NULL;
+ diskState->hbmMem = NULL;
+
+ diskState->RegionArray = NULL;
+ diskState->RegionCount = 0;
+ diskState->BarType = BarAuto;
+ diskState->OffLine = IsDiskOffLine(Disk);
+
+ if (diskState->OffLine)
+ {
+ FDLOG((1, "CreateDiskState: Disk %u is off-line\n", Disk));
+
+ diskState->DiskSizeMB = 0;
+ diskState->SigWasCreated = FALSE;
+ diskState->Signature = 0;
+ }
+ else
+ {
+ diskState->DiskSizeMB = DiskSizeMB(Disk);
+
+ if (0 != (diskState->Signature = FdGetDiskSignature(Disk)))
+ {
+ if (SignatureIsUniqueToSystem(Disk, diskState->Signature))
+ {
+ FDLOG((2,
+ "CreateDiskState: Found signature %08lx on disk %u\n",
+ diskState->Signature,
+ Disk));
+
+ diskState->SigWasCreated = FALSE;
+ }
+ else
+ {
+ goto createSignature;
+ }
+ }
+ else
+ {
+
+createSignature:
+
+ if (!IsRemovable(Disk)) {
+ diskState->Signature = FormDiskSignature();
+ FdSetDiskSignature(Disk, diskState->Signature);
+ diskState->SigWasCreated = TRUE;
+
+ FDLOG((1,
+ "CreateDiskState: disk %u has either no signature or a non-unique signature; created signature %08lx\n",
+ Disk,
+ diskState->Signature));
+
+ }
+ }
+ }
+
+ *SignatureCreated = (BOOL)diskState->SigWasCreated;
+ *DiskState = diskState;
+}
+
+
+
+
+DWORD
+InitializeDiskData(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine creates the disk state structures, and determines the initial
+ volume labels and type names for all significant partitions.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Windows error code (esp. out of memory)
+
+--*/
+
+{
+ PPERSISTENT_REGION_DATA regionData;
+ TCHAR windowsDir[MAX_PATH];
+ unsigned i;
+ PDISKSTATE diskState;
+ DWORD ec;
+ ULONG regionIndex;
+ BOOL diskSignaturesCreated;
+ BOOL signatureCreated;
+
+ //
+ // First, create the array that will hold the diskstates,
+ // the IsDiskRemovable array and the RemovableDiskReservedDriveLetters
+ // array.
+ //
+
+ DiskArray = (PDISKSTATE*)Malloc(DiskCount * sizeof(PDISKSTATE));
+ DiskSeenCountArray = (PULONG)Malloc(DiskCount * sizeof(ULONG));
+
+ IsDiskRemovable = (PBOOLEAN)Malloc(DiskCount * sizeof(BOOLEAN));
+
+ RemovableDiskReservedDriveLetters = (PWCHAR)Malloc(DiskCount * sizeof(WCHAR));
+
+ //
+ // Determine which disks are removable and which are unpartitioned.
+ //
+ for (i=0; i<DiskCount; i++)
+ {
+ IsDiskRemovable[i] = IsRemovable(i);
+ }
+
+ // next, create all disk states
+
+ FDASSERT(DiskCount>0);
+ diskSignaturesCreated = FALSE;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ // first create the disk state structure
+
+ CreateDiskState(&diskState, i, &signatureCreated);
+ diskSignaturesCreated = diskSignaturesCreated || signatureCreated;
+
+ DiskArray[i] = diskState;
+
+ // next determine the state of the disk's partitioning scheme
+
+ DeterminePartitioningState(diskState);
+
+ //
+ // Next create a blank logical disk structure for each region.
+ //
+
+ for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++)
+ {
+ if (DmSignificantRegion(&diskState->RegionArray[regionIndex]))
+ {
+ regionData = (PPERSISTENT_REGION_DATA)
+ Malloc(sizeof(PERSISTENT_REGION_DATA));
+
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+
+ DmInitPersistentRegionData(
+ regionData,
+ NULL,
+ NULL,
+ NULL,
+ NO_DRIVE_LETTER_YET,
+ FALSE,
+ zero,
+ zero
+ );
+ }
+ else
+ {
+ regionData = NULL;
+ }
+ DmSetPersistentRegionData(&diskState->RegionArray[regionIndex], regionData);
+ }
+ }
+
+ //
+ // Read the configuration registry
+ //
+
+ if ((ec = InitializeFt(diskSignaturesCreated)) != NO_ERROR)
+ {
+ ErrorDialog(ec);
+ return ec;
+ }
+
+ //
+ // Now, the correct FT persistent data is set based on the registry.
+ //
+
+ SetFTObjectBackPointers();
+
+ //
+ // Construct list of drives with pagefiles
+ //
+
+ LoadExistingPageFileInfo();
+
+ //
+ // Determine drive letter mappings
+ //
+
+ if (!InitializeDriveLetterInfo())
+ {
+ return ERROR_ACCESS_DENIED; //anything but NO_ERROR
+ }
+
+ // Initialize network information
+
+ NetworkInitialize();
+
+ if (!InitializeCdRomInfo())
+ {
+ return ERROR_ACCESS_DENIED; //anything but NO_ERROR
+ }
+
+ //
+ // Determine volume labels and type names.
+ //
+
+ InitVolumeInformation();
+
+ //
+ // Determine which disk is the boot disk.
+ //
+ if (GetWindowsDirectory(windowsDir, ARRAYLEN(windowsDir)) < 2
+ || windowsDir[1] != TEXT(':'))
+ {
+ BootDiskNumber = (ULONG)-1;
+ BootPartitionNumber = (ULONG)-1;
+ }
+ else
+ {
+ BootDiskNumber = GetDiskNumberFromDriveLetter(windowsDir[0]);
+ BootPartitionNumber = GetPartitionNumberFromDriveLetter(windowsDir[0]);
+ }
+
+#if defined( DBLSPACE_ENABLED )
+ //
+ // Locate and create data structures for any DoubleSpace volumes
+ //
+
+ DblSpaceInitialize();
+#endif // DBLSPACE_ENABLED
+
+ return NO_ERROR;
+}
+
+
+
+BOOL
+InitializationDlgProc(
+ IN HWND hDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ standard Windows dialog procedure
+
+Return Values:
+
+ standard Windows dialog procedure
+
+--*/
+
+{
+ static DWORD percentDrawn;
+ static BOOL captionIsLoaded;
+ static PFORMAT_PARAMS formatParams;
+ TCHAR title[100],
+ templateString[100];
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ g_InitDlg = hDlg;
+ percentDrawn = 0;
+ g_StartedAsIcon = IsIconic(hDlg);
+ return TRUE;
+ }
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hDlg, &ps);
+ DrawGasGauge(
+ GetDlgItem(hDlg, IDC_GASGAUGE),
+ hDlg,
+ hDC,
+ percentDrawn,
+ NULL);
+ EndPaint(hDlg, &ps);
+
+ if (percentDrawn == 100)
+ {
+ g_InitDlgComplete = TRUE;
+ }
+ return TRUE;
+ }
+
+ case WM_STARTUP_UPDATE:
+ {
+ // wParam = % completed
+
+ percentDrawn = (INT)wParam;
+
+ RECT rcGauge;
+ HWND hwndGauge = GetDlgItem(hDlg, IDC_GASGAUGE);
+
+ GetClientRect(hwndGauge, &rcGauge);
+
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.left);
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.right);
+ ScreenToClient(hDlg, (LPPOINT)&rcGauge.left);
+ ScreenToClient(hDlg, (LPPOINT)&rcGauge.right);
+
+ InvalidateRect(hDlg, &rcGauge, FALSE);
+ UpdateWindow(hDlg);
+
+ return TRUE;
+ }
+
+ case WM_STARTUP_END:
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+DWORD WINAPI
+InitializationMessageThread(
+ LPVOID ThreadParameter
+ )
+
+/*++
+
+Routine Description:
+
+ This is the entry for the initialization message thread. It creates
+ a dialog that simply tells the user to be patient.
+
+Arguments:
+
+ ThreadParameter - not used.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ DialogBox(g_hInstance,
+ MAKEINTRESOURCE(IDD_STARTUP),
+ g_hwndFrame,
+ InitializationDlgProc);
+ g_InitDlg = NULL;
+ ExitThread(0L);
+ return 0L;
+}
+
+
+VOID
+DisplayInitializationMessage(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Create a 2nd thread to display an initialization message.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ HANDLE threadHandle;
+ DWORD threadId;
+
+ threadHandle = CreateThread(NULL,
+ 0,
+ InitializationMessageThread,
+ NULL,
+ 0,
+ &threadId);
+ if (NULL != threadHandle)
+ {
+ CloseHandle(threadHandle);
+ }
+}
diff --git a/private/utils/windisk/src/init.hxx b/private/utils/windisk/src/init.hxx
new file mode 100644
index 000000000..2586b6212
--- /dev/null
+++ b/private/utils/windisk/src/init.hxx
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: init.hxx
+//
+// Contents: Declarations for initializing the Disk Administrator
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __INIT_HXX__
+#define __INIT_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define WM_STARTUP_UPDATE (WM_USER)
+#define WM_STARTUP_END (WM_USER + 1)
+
+BOOL
+InitializeApp(
+ VOID
+ );
+
+VOID
+DisplayInitializationMessage(
+ VOID
+ );
+
+#endif // __INIT_HXX__
diff --git a/private/utils/windisk/src/label.cxx b/private/utils/windisk/src/label.cxx
new file mode 100644
index 000000000..1ed79f9ab
--- /dev/null
+++ b/private/utils/windisk/src/label.cxx
@@ -0,0 +1,216 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: label.cxx
+//
+// Contents: Change volume label.
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <util.hxx>
+
+#include "dialogs.h"
+#include "fmifs.hxx"
+#include "fs.hxx"
+#include "help.hxx"
+#include "label.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+LOCAL BOOL CALLBACK
+SetLabelDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+typedef struct _LABEL_PARAMS
+{
+ INT MaxLabelLen;
+ WCHAR Label[MAXLABELLEN];
+
+ HWND hwndParent;
+
+} LABEL_PARAMS, *PLABEL_PARAMS;
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetLabelDlgProc
+//
+// Synopsis: Dialog procedure for Set Label UI.
+//
+// Arguments: standard Windows dialog procedure
+//
+// Returns: standard Windows dialog procedure
+//
+// History: 27-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL BOOL CALLBACK
+SetLabelDlgProc(
+ IN HWND hDlg,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ static PLABEL_PARAMS labelParams;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ labelParams = (PLABEL_PARAMS)lParam;
+
+ CenterWindow(hDlg, labelParams->hwndParent);
+
+ SendDlgItemMessage(
+ hDlg,
+ IDC_LABEL,
+ EM_LIMITTEXT,
+ labelParams->MaxLabelLen,
+ 0L);
+
+ // set the label to the current label, and select it
+
+ SetDlgItemText(hDlg, IDC_LABEL, labelParams->Label);
+ SendDlgItemMessage(hDlg, IDC_LABEL, EM_SETSEL, 0, (LPARAM)-1);
+
+ SetFocus(GetDlgItem(hDlg, IDC_LABEL));
+
+ return 0; // called SetFocus
+ }
+
+ case WM_COMMAND:
+
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ GetDlgItemText(
+ hDlg,
+ IDC_LABEL,
+ labelParams->Label,
+ ARRAYLEN(labelParams->Label));
+
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hDlg, FALSE);
+ return TRUE;
+
+ case IDHELP:
+ DialogHelp(HC_DM_DLG_LABEL);
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE; // message not processed
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoLabel
+//
+// Synopsis: Get a volume label from the user, and set the volume label
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 27-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoLabel(
+ IN HWND hwndParent
+ )
+{
+ if (!LoadFmifs())
+ {
+ return; // can't load fmifs.dll, so bail
+ }
+
+ DWORD ec;
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(regionDescriptor);
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(regionData);
+
+ LABEL_PARAMS labelParams;
+
+ FileSystemInfoType* pFSInfo = FindFileSystemInfo(regionData->TypeName);
+
+ labelParams.hwndParent = hwndParent;
+ lstrcpy(labelParams.Label, regionData->VolumeLabel);
+
+ if (NULL == pFSInfo)
+ {
+ labelParams.MaxLabelLen = MAXLABELLEN - 1;
+ }
+ else
+ {
+ labelParams.MaxLabelLen = pFSInfo->cMaxLabelLen;
+ }
+
+ int fOk = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_LABEL),
+ hwndParent,
+ SetLabelDlgProc,
+ (LPARAM)&labelParams
+ );
+
+ if (-1 == fOk)
+ {
+ // error creating dialog
+ daDebugOut((DEB_ERROR, "DialogBox() failed!\n"));
+ return;
+ }
+
+ if (fOk)
+ {
+ EnsureSameDevice(regionDescriptor);
+
+ WCHAR DriveName[3];
+ DriveName[0] = regionData->DriveLetter;
+ DriveName[1] = L':';
+ DriveName[2] = L'\0';
+
+ SetLastError(NO_ERROR);
+ (*lpfnSetLabel)(DriveName, labelParams.Label);
+ ec = GetLastError();
+
+ if (ec != NO_ERROR)
+ {
+ ErrorDialog(ec);
+ }
+ else
+ {
+ RefreshVolumeData();
+ }
+ }
+}
diff --git a/private/utils/windisk/src/label.hxx b/private/utils/windisk/src/label.hxx
new file mode 100644
index 000000000..8b3bdda3d
--- /dev/null
+++ b/private/utils/windisk/src/label.hxx
@@ -0,0 +1,22 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: label.hxx
+//
+// Contents: Change volume label.
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LABEL_HXX__
+#define __LABEL_HXX__
+
+VOID
+DoLabel(
+ IN HWND hwndParent
+ );
+
+#endif // __LABEL_HXX__
diff --git a/private/utils/windisk/src/listbox.cxx b/private/utils/windisk/src/listbox.cxx
new file mode 100644
index 000000000..798d72912
--- /dev/null
+++ b/private/utils/windisk/src/listbox.cxx
@@ -0,0 +1,1113 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: listbox.cxx
+//
+// Contents: Routines for handling the subclassed owner-draw listbox
+// used for the disks view display.
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "cm.hxx"
+#include "listbox.hxx"
+#include "select.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*
+
+ Notes on the disks view implementation.
+
+ The disks view is a subclassed, owner-draw, Windows listbox control.
+ The listbox items are irrelevant: it is only the number of items
+ that is important. Both disks (including off-line disks) and CD-ROMs
+ are shown in this view, as follows:
+
+ Disk 0
+ Disk 1
+ ...
+ Disk N
+ CD-ROM 0
+ CD-ROM 1
+ ...
+ CD-ROM N
+
+ So, the CD-ROMs follow all the disks. What this means is that the
+ listbox index can be used as an index into the DiskArray array. The
+ listbox index minus DiskCount is the CD-ROM DeviceNumber. The
+ number of CD-ROMs and Disks in the system is constant after the SCSI
+ bus is rescanned upon Windisk startup.
+
+*/
+
+//////////////////////////////////////////////////////////////////////////////
+
+// constants used when listbox or its focus rectangle is
+// scrolled/moved.
+
+#define DIR_NONE 0
+#define DIR_UP 1
+#define DIR_DN 2
+
+//////////////////////////////////////////////////////////////////////////////
+
+// original window procedure for our subclassed listbox
+
+WNDPROC OldListBoxProc;
+
+// item which has focus
+
+DWORD LBCursorListBoxItem;
+DWORD LBCursorRegion;
+BOOL LBCursorOn = FALSE;
+
+ULONG g_MouseLBIndex; // listbox index of mouse click
+ULONG g_MouseRegion;
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+IsItemUnderCursorSelected(
+ IN PPOINT ppt
+ );
+
+BOOL
+ContextMenuSelection(
+ IN PPOINT ppt
+ );
+
+ULONG
+CalcBarIndex(
+ IN PPOINT ppt
+ );
+
+VOID
+ToggleLBCursor(
+ IN HDC hdc
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBIsDisk
+//
+// Synopsis: returns TRUE if the listbox index is for a disk
+//
+// Arguments: [itemIndex] -- a listbox index
+//
+// Returns: TRUE if the item is a disk
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+LBIsDisk(
+ IN ULONG itemIndex
+ )
+{
+ return (itemIndex < DiskCount);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBIsCdRom
+//
+// Synopsis: returns TRUE if the listbox index is for a CD-ROM
+//
+// Arguments: [itemIndex] -- a listbox index
+//
+// Returns: TRUE if the item is a CD-ROM
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+LBIsCdRom(
+ IN ULONG itemIndex
+ )
+{
+ return (DiskCount <= itemIndex) && (itemIndex < DiskCount + CdRomCount);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBIndexToDiskNumber
+//
+// Synopsis: returns the disk number of a listbox index
+//
+// Arguments: [ItemIndex] -- a listbox index
+//
+// Returns: A disk number
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+LBIndexToDiskNumber(
+ IN ULONG ItemIndex
+ )
+{
+ FDASSERT(LBIsDisk(ItemIndex));
+ return ItemIndex;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBIndexToCdRomNumber
+//
+// Synopsis: returns the CD-ROM number of a listbox index
+//
+// Arguments: [ItemIndex] -- a listbox index
+//
+// Returns: A CD-ROM number
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+LBIndexToCdRomNumber(
+ IN ULONG ItemIndex
+ )
+{
+ FDASSERT(LBIsCdRom(ItemIndex));
+ return ItemIndex - DiskCount;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBDiskNumberToIndex
+//
+// Synopsis: returns the listbox index of a disk
+//
+// Arguments: [DiskNumber] -- the number of the disk
+//
+// Returns: A listbox index
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+LBDiskNumberToIndex(
+ IN ULONG DiskNumber
+ )
+{
+ FDASSERT(0 <= DiskNumber && DiskNumber < DiskCount);
+ return DiskNumber;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LBCdRomNumberToIndex
+//
+// Synopsis: returns the listbox index of a CD-ROM
+//
+// Arguments: [CdRomNumber] -- a CD-ROM number
+//
+// Returns: A listbox index
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+LBCdRomNumberToIndex(
+ IN ULONG CdRomNumber
+ )
+{
+ FDASSERT(0 <= CdRomNumber && CdRomNumber < CdRomCount);
+ return CdRomNumber + DiskCount;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsItemUnderCursorSelected
+//
+// Synopsis:
+//
+// Arguments: [ppt] -- point in screen coordinates of point to check
+//
+// Returns: TRUE if the item under the point is selected
+//
+// Modifies: g_MouseLBIndex, g_MouseRegion
+//
+// History: 26-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+IsItemUnderCursorSelected(
+ IN PPOINT ppt
+ )
+{
+ DWORD x, y;
+ DWORD i;
+ RECT rc;
+ POINT pt = *ppt;
+
+ g_MouseLBIndex = (ULONG)-1;
+ g_MouseRegion = (ULONG)-1;
+
+ ScreenToClient(g_hwndList, &pt);
+
+ x = pt.x;
+ y = pt.y;
+ GetClientRect(g_hwndList, &rc);
+
+ // first make sure that the click was within a bar and not in space
+ // between two bars
+
+ for (i = rc.top; i <= (DWORD)rc.bottom; i += GraphHeight)
+ {
+ if ((y >= i+BarTopYOffset) && (y <= i+BarBottomYOffset))
+ {
+ break;
+ }
+ }
+ if (i > (DWORD)rc.bottom)
+ {
+ return FALSE;
+ }
+
+ g_MouseLBIndex = CalcBarIndex(ppt);
+
+ if (-1 == g_MouseLBIndex)
+ {
+ return FALSE;
+ }
+
+ if (LBIsDisk(g_MouseLBIndex))
+ {
+ PDISKSTATE diskState = DiskArray[LBIndexToDiskNumber(g_MouseLBIndex)];
+
+ for (i=0; i<diskState->RegionCount; i++)
+ {
+ if ( (x >= (unsigned)diskState->LeftRight[i].Left)
+ && (x <= (unsigned)diskState->LeftRight[i].Right))
+ {
+ //
+ // found the region, now is it selected?
+ //
+ g_MouseRegion = i;
+ return diskState->Selected[i];
+ }
+ }
+ }
+ else if (LBIsCdRom(g_MouseLBIndex))
+ {
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(LBIndexToCdRomNumber(g_MouseLBIndex));
+ if ( (x >= (unsigned)cdrom->LeftRight.Left)
+ && (x <= (unsigned)cdrom->LeftRight.Right))
+ {
+ return cdrom->Selected;
+ }
+ }
+ else
+ {
+ FDASSERT(FALSE);
+ }
+
+ return FALSE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ContextMenuSelection
+//
+// Synopsis: Determines whether there is a valid context menu to display
+// at a particular point, and set state variables to indicate
+// which one is legal.
+//
+// Arguments: [ppt] -- point in screen coordinates of location of right-mouse
+// click
+//
+// Returns: TRUE if there may is valid context menu selection, FALSE if
+// there is no possible context menu
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+ContextMenuSelection(
+ IN PPOINT ppt
+ )
+{
+ DiskSelected = FALSE;
+
+ PartitionSelected = IsItemUnderCursorSelected(ppt);
+
+ if (-1 != g_MouseLBIndex)
+ {
+ // user has clicked on a list box item.
+
+ if (LBIsDisk(g_MouseLBIndex))
+ {
+ PDISKSTATE diskState;
+ DWORD x, y;
+ POINT pt = *ppt;
+
+ diskState = DiskArray[LBIndexToDiskNumber(g_MouseLBIndex)];
+
+ //
+ // Ignore clicks on off-line disks.
+ //
+
+ if (diskState->OffLine)
+ {
+ return FALSE; //BUGBUG: what to do with off-line disks?
+ }
+
+ ScreenToClient(g_hwndList, &pt);
+
+ x = pt.x;
+ y = pt.y;
+
+ if (x >= 0 && x < (unsigned)diskState->LeftRight[0].Left)
+ {
+ //
+ // select the disk by right-clicking to the left of the disk bar
+ // BUGBUG: only allow selecting the disk context menu by
+ // clicking the mini-icon
+ //
+
+ DiskSelected = TRUE;
+ }
+ }
+ else if (LBIsCdRom(g_MouseLBIndex))
+ {
+ //BUGBUG: context menu on CD-ROM?
+ }
+ else
+ {
+ FDASSERT(FALSE);
+ }
+ }
+
+ return (PartitionSelected || DiskSelected);
+}
+
+
+
+
+
+LPARAM CALLBACK
+ListBoxSubProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the window procedure used for our subclassed listbox.
+ We subclass the listbox so that we can handle keyboard input processing.
+ All other messages are passed through to the original listbox procedure.
+
+ Significant keys are arrows, pageup/dn, tab, space, return, home, and end.
+ Control may be used to modify space and return.
+ Shift may be used to modify tab.
+
+Arguments:
+
+ hwnd - window handle of listbox
+
+ msg - message #
+
+ wParam - user param # 1
+
+ lParam - user param # 2
+
+Return Value:
+
+ see below
+
+--*/
+
+{
+ USHORT vKey;
+ DWORD maxRegionIndex;
+ DWORD maxLBIndex;
+ PDISKSTATE diskState;
+ int focusDirection = DIR_NONE;
+ LONG topItem;
+ LONG bottomWholeItem;
+ LONG visibleItems;
+ RECT rc;
+
+ switch (msg)
+ {
+ case WM_RBUTTONDOWN:
+ {
+ BOOL fCtrl = GetKeyState(VK_CONTROL) & ~1; // strip toggle bit
+ DWORD pos = GetMessagePos();
+ POINT pt;
+ pt.x = LOWORD(pos);
+ pt.y = HIWORD(pos);
+
+ if (fCtrl || !IsItemUnderCursorSelected(&pt))
+ {
+ //
+ // Select the region under the mouse. Do this by setting
+ // the selected listbox item then setting the region selection.
+ //
+
+ ULONG lbIndex = CalcBarIndex(&pt);
+ if (SendMessage(hwnd, LB_SETCURSEL, lbIndex, 0) == LB_ERR)
+ {
+ return FALSE;
+ }
+
+ MouseSelection(fCtrl, &pt);
+ }
+
+ break;
+ }
+
+ case WM_RBUTTONUP:
+ {
+ POINT pt;
+ DWORD pos = GetMessagePos();
+ pt.x = LOWORD(pos);
+ pt.y = HIWORD(pos);
+
+ //
+ // Then, pop up an appropriate context menu
+ //
+
+ if (ContextMenuSelection(&pt))
+ {
+ if (DiskSelected)
+ {
+ DiskContextMenu(&pt);
+ }
+ else if (PartitionSelected)
+ {
+ ContextMenu(&pt); // volume or free space
+ }
+ // else, no context menu, but this shouldn't happen inside the
+ // ContextMenuSelection() true case
+ }
+
+ break;
+ }
+
+ case WM_CHAR:
+
+ break;
+
+ case WM_KEYDOWN:
+
+ switch (vKey = LOWORD(wParam))
+ {
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_UP:
+ case VK_DOWN:
+
+ ToggleLBCursor(NULL);
+ switch (vKey)
+ {
+ case VK_LEFT:
+ if (LBCursorRegion > 0)
+ {
+ LBCursorRegion--;
+ }
+ break;
+
+ case VK_RIGHT:
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ maxRegionIndex = DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)]->RegionCount - 1;
+ }
+ else if (LBIsCdRom(LBCursorListBoxItem))
+ {
+ maxRegionIndex = 0;
+ }
+
+ if (LBCursorRegion < maxRegionIndex)
+ {
+ LBCursorRegion++;
+ }
+ break;
+
+ case VK_UP:
+ if (LBCursorListBoxItem > 0)
+ {
+ LBCursorListBoxItem--;
+ LBCursorRegion = 0;
+ focusDirection = DIR_UP;
+ }
+ break;
+
+ case VK_DOWN:
+ maxLBIndex = SendMessage(hwnd, LB_GETCOUNT, 0, 0) - 1;
+
+ if (LBCursorListBoxItem < maxLBIndex)
+ {
+ LBCursorListBoxItem++;
+ LBCursorRegion = 0;
+ focusDirection = DIR_DN;
+ }
+ break;
+ }
+
+ // don't allow list box cursor to fall on extended partition
+
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ diskState = DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)];
+
+ if (diskState->RegionCount) {
+ maxRegionIndex = diskState->RegionCount - 1;
+ if (IsExtended(diskState->RegionArray[LBCursorRegion].SysID))
+ {
+ if (LBCursorRegion
+ && ((vKey == VK_LEFT) || (LBCursorRegion == maxRegionIndex)))
+ {
+ LBCursorRegion--;
+ }
+ else
+ {
+ LBCursorRegion++;
+ }
+ }
+ }
+ }
+
+ ToggleLBCursor(NULL);
+ break;
+
+ case VK_TAB:
+
+ ToggleLBCursor(NULL);
+
+ if (GetKeyState(VK_SHIFT) & ~1) // shift-tab
+ {
+ LBCursorListBoxItem--;
+ focusDirection = DIR_UP;
+ }
+ else
+ {
+ LBCursorListBoxItem++;
+ focusDirection = DIR_DN;
+ }
+
+ maxLBIndex = SendMessage(hwnd, LB_GETCOUNT, 0, 0) - 1;
+
+ if (LBCursorListBoxItem == (DWORD)(-1))
+ {
+ LBCursorListBoxItem = maxLBIndex;
+ focusDirection = DIR_DN;
+ }
+ else if (LBCursorListBoxItem == maxLBIndex + 1)
+ {
+ LBCursorListBoxItem = 0;
+ focusDirection = DIR_UP;
+ }
+
+ ResetLBCursorRegion();
+ ToggleLBCursor(NULL);
+ break;
+
+ case VK_HOME:
+ case VK_END:
+
+ ToggleLBCursor(NULL);
+ maxLBIndex = SendMessage(hwnd, LB_GETCOUNT, 0, 0) - 1;
+ topItem = (vKey == VK_HOME) ? 0 : maxLBIndex;
+ SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)topItem, 0);
+ LBCursorListBoxItem = topItem;
+ ResetLBCursorRegion();
+ ToggleLBCursor(NULL);
+ break;
+
+ case VK_PRIOR:
+ case VK_NEXT:
+
+ ToggleLBCursor(NULL);
+ topItem = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ maxLBIndex = SendMessage(hwnd, LB_GETCOUNT, 0, 0) - 1;
+ GetClientRect(hwnd, &rc);
+ visibleItems = (rc.bottom - rc.top) / GraphHeight;
+ if (0 == visibleItems)
+ {
+ visibleItems = 1;
+ }
+ topItem = (vKey == VK_PRIOR)
+ ? max(topItem - visibleItems, 0)
+ : min(topItem + visibleItems, (LONG)maxLBIndex);
+ SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)topItem, 0);
+ LBCursorListBoxItem = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ ResetLBCursorRegion();
+ ToggleLBCursor(NULL);
+ break;
+
+ case VK_RETURN:
+ case VK_SPACE:
+
+ // Select the region that currently has the list box selection cursor.
+
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ if (!DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)]->OffLine)
+ {
+ SelectDiskRegion(
+ GetKeyState(VK_CONTROL) & ~1, // strip toggle bit
+ DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)],
+ LBCursorRegion
+ );
+ }
+ }
+ else if (LBIsCdRom(LBCursorListBoxItem))
+ {
+ SelectCdRom(
+ GetKeyState(VK_CONTROL) & ~1, // strip toggle bit
+ LBIndexToCdRomNumber(LBCursorListBoxItem)
+ );
+ }
+ break;
+ }
+
+ // now scroll the newly focused item into view if necessary
+
+ switch (focusDirection)
+ {
+ case DIR_UP:
+ if (LBCursorListBoxItem < (DWORD)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0))
+ {
+ SendMessage(hwnd, LB_SETTOPINDEX, LBCursorListBoxItem, 0);
+ }
+ break;
+
+ case DIR_DN:
+ GetClientRect(hwnd, &rc);
+ topItem = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ bottomWholeItem = topItem + ((rc.bottom - rc.top) / GraphHeight) - 1;
+ if (bottomWholeItem < topItem)
+ {
+ bottomWholeItem = topItem;
+ }
+
+ if ((DWORD)bottomWholeItem > DiskCount - 1)
+ {
+ bottomWholeItem = DiskCount-1;
+ }
+
+ if (LBCursorListBoxItem > (DWORD)bottomWholeItem)
+ {
+ SendMessage(hwnd,
+ LB_SETTOPINDEX,
+ topItem + LBCursorListBoxItem - bottomWholeItem,
+ 0
+ );
+ }
+ break;
+ }
+ break;
+
+ default:
+ return CallWindowProc(OldListBoxProc, hwnd, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CalcBarIndex
+//
+// Synopsis: Given a point (in screen coordinates), return what bar index
+// corresponds to it.
+//
+// Arguments: [ppt] -- point in screen coordinates
+//
+// Returns: Index of bar in disks listbox, -1 if no disk
+//
+// History: 26-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+CalcBarIndex(
+ IN PPOINT ppt
+ )
+{
+ ULONG barDelta;
+ POINT pt = *ppt;
+
+ ScreenToClient(g_hwndList, &pt);
+
+ barDelta = SendMessage(g_hwndList, LB_GETTOPINDEX, 0, 0)
+ + (pt.y / GraphHeight);
+
+ if (barDelta >= (ULONG)SendMessage(g_hwndList, LB_GETCOUNT, 0, 0))
+ {
+ barDelta = (ULONG)-1;
+ }
+
+ return barDelta;
+}
+
+
+
+
+LONG
+CalcBarTop(
+ DWORD Bar
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calculates the current top y coord of a given bar.
+ The value is in listbox client coords.
+
+Arguments:
+
+ Bar - # of bar whose position is desired
+
+Return Value:
+
+ Y-coord, or -1 if bar is not visible.
+
+--*/
+
+{
+ RECT rc;
+ LONG barDelta = (LONG)Bar - SendMessage(g_hwndList, LB_GETTOPINDEX, 0, 0);
+ LONG pos = -1;
+
+ if (barDelta >= 0) // BUGBUG check bottom too
+ {
+ GetClientRect(g_hwndList, &rc);
+ pos = rc.top + (barDelta * GraphHeight);
+ }
+ return pos;
+}
+
+
+
+
+VOID
+ResetLBCursorRegion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the list box focus cursor to the 0th (leftmost)
+ region on the current disk. If the 0th region is the extended
+ partition, focus is set to the first logical volume or free space
+ with the extended partition instead.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LBCursorRegion = 0;
+
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ PDISKSTATE diskState = DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)];
+ unsigned i;
+
+ if (!diskState->OffLine) {
+ if (IsExtended(diskState->RegionArray[LBCursorRegion].SysID))
+ {
+ for (i=0; i<diskState->RegionCount; i++)
+ {
+ if (diskState->RegionArray[i].RegionType == REGION_LOGICAL)
+ {
+ LBCursorRegion = i;
+ return;
+ }
+ }
+ FDASSERT(FALSE); //shouldn't ever get here
+ }
+ }
+ }
+}
+
+
+
+
+VOID
+ToggleLBCursor(
+ IN HDC hdc
+ )
+
+/*++
+
+Routine Description:
+
+ This routine visually toggles the focus state of the disk region
+ described by the LBCursorListBoxItem and LBCursorRegion globals.
+
+Arguments:
+
+ hdc - If non-NULL, device context to use for drawing. If NULL,
+ we'll first get a DC via GetDC().
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ LONG barTop = CalcBarTop(LBCursorListBoxItem);
+
+ if (barTop != -1)
+ {
+ PLEFTRIGHT leftRight;
+ PDISKSTATE LBCursorDisk = DiskArray[LBCursorListBoxItem];
+
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ leftRight = &DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)]->LeftRight[LBCursorRegion];
+ }
+ else if (LBIsCdRom(LBCursorListBoxItem))
+ {
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(LBIndexToCdRomNumber(LBCursorListBoxItem));
+ leftRight = &cdrom->LeftRight;
+ }
+ else
+ {
+ FDASSERT(FALSE);
+ }
+
+ RECT rc;
+ HDC hdcActual = hdc ? hdc : GetDC(g_hwndList);
+
+ LBCursorOn = !LBCursorOn;
+
+ rc.left = leftRight->Left;
+ rc.right = leftRight->Right;
+ rc.top = barTop + BarTopYOffset;
+ rc.bottom = barTop + BarBottomYOffset;
+
+ FrameRect(hdcActual,
+ &rc,
+ GetStockBrush(LBCursorOn ? WHITE_BRUSH : BLACK_BRUSH));
+
+ if (LBCursorOn)
+ {
+ DrawFocusRect(hdcActual, &rc);
+ }
+
+ if (NULL == hdc)
+ {
+ ReleaseDC(g_hwndList, hdcActual);
+ }
+ }
+}
+
+
+
+
+VOID
+ForceLBRedraw(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine forces redraw of the listbox by invalidating its
+ entire client area.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InvalidateRect(g_hwndList, NULL, TRUE);
+ UpdateWindow(g_hwndList);
+}
+
+
+
+BOOL
+WMDrawItem(
+ IN PDRAWITEMSTRUCT pDrawItem
+ )
+{
+ if ( (pDrawItem->itemID != (DWORD)(-1))
+ && (pDrawItem->itemAction == ODA_DRAWENTIRE))
+ {
+ DWORD regionIndex;
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+ HDC hDCMem;
+
+ if (LBIsDisk(pDrawItem->itemID))
+ {
+ diskState = DiskArray[LBIndexToDiskNumber(pDrawItem->itemID)];
+ hDCMem = diskState->hDCMem;
+ }
+ else if (LBIsCdRom(pDrawItem->itemID))
+ {
+ cdrom = CdRomFindDevice(LBIndexToCdRomNumber(pDrawItem->itemID));
+ hDCMem = cdrom->hDCMem;
+ }
+
+ // blt the disk's bar from the off-screen bitmap to the screen
+
+ BitBlt(pDrawItem->hDC,
+ pDrawItem->rcItem.left,
+ pDrawItem->rcItem.top,
+ pDrawItem->rcItem.right - pDrawItem->rcItem.left + 1,
+ pDrawItem->rcItem.bottom - pDrawItem->rcItem.top + 1,
+ hDCMem,
+ 0,
+ 0,
+ SRCCOPY
+ );
+
+ // if we just overwrote the focus cursor, redraw it
+
+ if (pDrawItem->itemID == LBCursorListBoxItem)
+ {
+ LBCursorOn = FALSE;
+ ToggleLBCursor(pDrawItem->hDC);
+ }
+
+ // select any items selected in this bar
+
+ if (LBIsDisk(pDrawItem->itemID))
+ {
+ for (regionIndex = 0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ if (diskState->Selected[regionIndex])
+ {
+ PaintDiskRegion(diskState, regionIndex, pDrawItem->hDC);
+ }
+ }
+ }
+ else if (LBIsCdRom(pDrawItem->itemID))
+ {
+ if (cdrom->Selected)
+ {
+ PaintCdRom(LBIndexToCdRomNumber(pDrawItem->itemID), pDrawItem->hDC);
+ }
+ }
+
+ return TRUE; // message handled
+ }
+
+ return FALSE; // message NOT handled
+}
+
+
+
+VOID
+SubclassListBox(
+ IN HWND hwnd
+ )
+{
+ OldListBoxProc = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG)ListBoxSubProc);
+
+ //
+ // There is a scantily documented 'feature' of a listbox wherein it will
+ // use its parent's DC. This means that drawing is not always clipped to
+ // the client area of the listbox. Seeing as we're subclassing listboxes
+ // anyway, take care of this here.
+ //
+ SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE) & ~CS_PARENTDC);
+}
+
+
+
+
+
+VOID
+InitializeListBox(
+ IN HWND hwndListBox
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the list box. The disk state structures must
+ have been previously created.
+
+Arguments:
+
+ hwndListBox - handle of the list box that will hold the disk graphs
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ ULONG i;
+ DWORD ec;
+ ULONG count;
+
+ FDASSERT(DiskCount>0);
+
+ count = DiskCount + CdRomCount;
+
+ for (i=0; i<count; i++)
+ {
+ while (((ec = SendMessage(hwndListBox, LB_ADDSTRING, 0, 0)) == LB_ERR)
+ || (ec == LB_ERRSPACE))
+ {
+ ConfirmOutOfMemory();
+ }
+ }
+
+ TotalRedrawAndRepaint();
+}
diff --git a/private/utils/windisk/src/listbox.hxx b/private/utils/windisk/src/listbox.hxx
new file mode 100644
index 000000000..68ff96f1b
--- /dev/null
+++ b/private/utils/windisk/src/listbox.hxx
@@ -0,0 +1,85 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: listbox.hxx
+//
+// Contents: Declarations for handling the subclassed owner-draw listbox
+// used for the disks view display.
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LISTBOX_HXX__
+#define __LISTBOX_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+LBIsDisk(
+ IN ULONG itemIndex
+ );
+
+BOOL
+LBIsCdRom(
+ IN ULONG itemIndex
+ );
+
+BOOL
+LBIndexToDiskNumber(
+ IN ULONG ItemIndex
+ );
+
+BOOL
+LBIndexToCdRomNumber(
+ IN ULONG ItemIndex
+ );
+
+ULONG
+LBDiskNumberToIndex(
+ IN ULONG DiskNumber
+ );
+
+ULONG
+LBCdRomNumberToIndex(
+ IN ULONG CdRomNumber
+ );
+
+LONG
+CalcBarTop(
+ DWORD Bar
+ );
+
+VOID
+ResetLBCursorRegion(
+ VOID
+ );
+
+VOID
+ToggleLBCursor(
+ IN HDC hdc
+ );
+
+VOID
+ForceLBRedraw(
+ VOID
+ );
+
+BOOL
+WMDrawItem(
+ IN PDRAWITEMSTRUCT pDrawItem
+ );
+
+VOID
+SubclassListBox(
+ IN HWND hwnd
+ );
+
+VOID
+InitializeListBox(
+ IN HWND hwndListBox
+ );
+
+#endif // __LISTBOX_HXX__
diff --git a/private/utils/windisk/src/log.cxx b/private/utils/windisk/src/log.cxx
new file mode 100644
index 000000000..f064b12e8
--- /dev/null
+++ b/private/utils/windisk/src/log.cxx
@@ -0,0 +1,1289 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: log.cxx
+//
+// Contents: Logging routines used only in debug builds
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#if DBG == 1
+
+#include <stdio.h>
+
+#include "drives.hxx"
+#include "engine.hxx"
+#include "windisk.hxx"
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// stuff internal to the fdisk engine that I want to look at:
+//
+
+extern ULONG CountOfDisks;
+extern PCHAR* DiskNames;
+extern DISKGEOM* DiskGeometryArray;
+extern PPARTITION* PrimaryPartitions;
+extern PPARTITION* LogicalVolumes;
+extern PBOOLEAN OffLine;
+extern BOOLEAN* ChangesRequested;
+extern BOOLEAN* ChangesCommitted;
+
+//
+// stuff internal to commit.cxx:
+//
+
+extern PDRIVE_LOCKLIST DriveLockListHead;
+extern PASSIGN_LIST AssignDriveLetterListHead;
+
+//
+// Locals
+//
+
+FILE* LogFile = NULL;
+int LoggingLevel = 1000;
+
+//////////////////////////////////////////////////////////////////////////////
+
+PCHAR
+GetFtType(
+ IN FT_TYPE ty
+ );
+
+PCHAR
+GetSysId(
+ IN UCHAR SysID
+ );
+
+PCHAR
+IsSysIdFT(
+ IN UCHAR SysID
+ );
+
+PCHAR
+GetRegionType(
+ IN REGION_TYPE RegionType
+ );
+
+VOID
+LOG_PERSISTENT(
+ IN PSTR pszPrefix,
+ IN PSTR pszWhitespace,
+ IN PPERSISTENT_REGION_DATA p
+ );
+
+VOID
+LOG_ONE_DISK(
+ PPARTITION p
+ );
+
+VOID
+LOG_REGION_DESCRIPTOR(
+ IN PREGION_DESCRIPTOR reg
+ );
+
+VOID
+LOG_ENGINE_DATA(
+ VOID
+ );
+
+VOID
+LOG_FTOBJECTSET(
+ VOID
+ );
+
+VOID
+LOG_DISKSTATE(
+ VOID
+ );
+
+VOID
+LOG_DRIVELETTERS(
+ VOID
+ );
+
+VOID
+LOG_WINDOWSTATE(
+ VOID
+ );
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+PCHAR
+GetFtType(
+ IN FT_TYPE ty
+ )
+{
+ switch (ty)
+ {
+ case Mirror: return "Mirror";
+ case Stripe: return "Stripe";
+ case StripeWithParity: return "Parity";
+ case VolumeSet: return "VolSet";
+ case NotAnFtMember: return "Not FT";
+ case WholeDisk: return "Whole ";
+ default: return "HUH? ";
+ }
+}
+
+
+PCHAR
+GetFtStatus(
+ IN FT_SET_STATUS Status
+ )
+{
+ switch (Status)
+ {
+ case FtSetHealthy: return "Healthy ";
+ case FtSetBroken: return "Broken ";
+ case FtSetRecoverable: return "Recoverable ";
+ case FtSetRecovered: return "Recovered ";
+ case FtSetNew: return "New ";
+ case FtSetNewNeedsInitialization: return "NewNeedsInit";
+ case FtSetExtended: return "Extended ";
+ case FtSetInitializing: return "Initializing";
+ case FtSetRegenerating: return "Regenerating";
+ default: return "HUH? ";
+ }
+}
+
+
+
+PCHAR
+GetSysId(
+ IN UCHAR SysID
+ )
+{
+ switch (SysID & (~PARTITION_NTFT))
+ {
+ case PARTITION_ENTRY_UNUSED: return "Unused";
+ case PARTITION_FAT_12: return "Fat-12";
+ case PARTITION_XENIX_1: return "Xenix1";
+ case PARTITION_XENIX_2: return "Xenix2";
+ case PARTITION_FAT_16: return "Fat-16";
+ case PARTITION_EXTENDED: return "Extend";
+ case PARTITION_HUGE: return "FAT ";
+ case PARTITION_IFS: return "IFS ";
+ case PARTITION_XINT13: return "xFAT ";
+ case PARTITION_XINT13_EXTENDED: return "xExtnd";
+ case PARTITION_PREP: return "PPC ";
+ case PARTITION_UNIX: return "Unix ";
+ default: return "Huh? ";
+ }
+}
+
+PCHAR
+IsSysIdFT(
+ IN UCHAR SysID
+ )
+{
+ if (SysID & PARTITION_NTFT)
+ {
+ return "yes";
+ }
+ else
+ {
+ return "no ";
+ }
+}
+
+PCHAR
+GetRegionType(
+ IN REGION_TYPE RegionType
+ )
+{
+ switch (RegionType)
+ {
+ case REGION_PRIMARY: return "Primary ";
+ case REGION_EXTENDED: return "Extended";
+ case REGION_LOGICAL: return "Logical ";
+ default: return "Huh? ";
+ }
+}
+
+
+
+VOID
+FdiskAssertFailedRoutine(
+ IN char *Expression,
+ IN char *FileName,
+ IN int LineNumber
+ )
+
+/*++
+
+Routine Description:
+
+ Routine that is called when an assertion fails in the debug version.
+ Throw up a list box giving appriopriate information and terminate
+ the program.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ char text[500];
+
+ wsprintfA(text,
+ "Line #%u in File '%hs'\n[%hs]\n\nClick OK to exit.",
+ LineNumber,
+ FileName,
+ Expression
+ );
+
+ MessageBoxA(NULL,text,"Assertion Failure",MB_TASKMODAL | MB_OK);
+ exit(1);
+}
+
+
+
+VOID
+InitLogging(
+ VOID
+ )
+{
+ LogFile = fopen("c:\\windisk.log","wt");
+ if (LogFile == NULL)
+ {
+ MessageBox(GetActiveWindow(),
+ TEXT("Can't open log file; logging turned off"),
+ TEXT("DEBUG"),
+ MB_SYSTEMMODAL|MB_OK);
+ LoggingLevel = -1;
+ }
+}
+
+
+
+VOID
+EndLogging(
+ VOID
+ )
+{
+ if (LogFile != NULL)
+ {
+ fclose(LogFile);
+ }
+}
+
+
+VOID
+FDLOG_WORK(
+ IN int Level,
+ IN PCHAR FormatString,
+ ...
+ )
+{
+ if (Level <= LoggingLevel)
+ {
+ va_list arglist;
+ va_start(arglist,FormatString);
+
+ if (vfprintf(LogFile,FormatString,arglist) < 0)
+ {
+ LoggingLevel = -1;
+ MessageBox(GetActiveWindow(),
+ TEXT("Error writing to log file; logging turned off"),
+ TEXT("DEBUG"),
+ MB_SYSTEMMODAL|MB_OK);
+ fclose(LogFile);
+ }
+ else
+ {
+ fflush(LogFile);
+ }
+
+ va_end(arglist);
+ }
+}
+
+
+VOID
+LOG_DISK_REGISTRY(
+ IN PCHAR RoutineName,
+ IN PDISK_REGISTRY DiskRegistry
+ )
+{
+ ULONG i;
+ PDISK_DESCRIPTION diskDesc;
+
+ FDLOG_WORK(2,"%hs: %u disks; registry info follows:\n",RoutineName,DiskRegistry->NumberOfDisks);
+
+ diskDesc = DiskRegistry->Disks;
+
+ for (i=0; i<DiskRegistry->NumberOfDisks; i++)
+ {
+ LOG_ONE_DISK_REGISTRY_DISK_ENTRY(NULL,diskDesc);
+ diskDesc = (PDISK_DESCRIPTION)&diskDesc->Partitions[diskDesc->NumberOfPartitions];
+ }
+}
+
+
+VOID
+LOG_ONE_DISK_REGISTRY_DISK_ENTRY(
+ IN PCHAR RoutineName OPTIONAL,
+ IN PDISK_DESCRIPTION DiskDescription
+ )
+{
+ USHORT j;
+ PDISK_PARTITION partDesc;
+ PDISK_DESCRIPTION diskDesc = DiskDescription;
+
+ if (ARGUMENT_PRESENT(RoutineName))
+ {
+ FDLOG_WORK(2,"%hs: disk registry entry follows:\n",RoutineName);
+ }
+
+ FDLOG_WORK(2," Disk signature : %08lx\n",diskDesc->Signature);
+ FDLOG_WORK(2," Partition count: %u\n",diskDesc->NumberOfPartitions);
+ if (diskDesc->NumberOfPartitions)
+ {
+ FDLOG_WORK(2," # Dr FtType FtGrp FtMem Start Length\n");
+ }
+
+ for (j=0; j<diskDesc->NumberOfPartitions; j++)
+ {
+ CHAR dr1,dr2;
+
+ partDesc = &diskDesc->Partitions[j];
+
+ if (partDesc->AssignDriveLetter)
+ {
+ if (partDesc->DriveLetter)
+ {
+ dr1 = partDesc->DriveLetter;
+ dr2 = ':';
+ }
+ else
+ {
+ dr1 = dr2 = ' ';
+ }
+ }
+ else
+ {
+ dr1 = 'n';
+ dr2 = 'o';
+ }
+
+ PCHAR pType = GetFtType(partDesc->FtType);
+
+ FDLOG_WORK( 2,
+ " %02u %c%c %hs %-5u %-5u %08lx:%08lx %08lx:%08lx\n",
+ partDesc->LogicalNumber,
+ dr1,dr2,
+ pType,
+ partDesc->FtGroup,
+ partDesc->FtMember,
+ partDesc->StartingOffset.HighPart,
+ partDesc->StartingOffset.LowPart,
+ partDesc->Length.HighPart,
+ partDesc->Length.LowPart
+ );
+ }
+}
+
+
+VOID
+LOG_DRIVE_LAYOUT(
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ )
+{
+ ULONG i;
+
+ FDLOG_WORK(2," Disk signature : %08lx\n",DriveLayout->Signature);
+ FDLOG_WORK(2," Partition count: %u\n",DriveLayout->PartitionCount);
+
+ FDLOG_WORK(2,
+" ID FT? Active Recog Start Size Hidden\n");
+
+ for (i=0; i<DriveLayout->PartitionCount; i++)
+ {
+ PPARTITION_INFORMATION p = &(DriveLayout->PartitionEntry[i]);
+
+ PCHAR pType;
+ switch (p->PartitionType & (~VALID_NTFT))
+ {
+ case PARTITION_ENTRY_UNUSED:
+ pType = "Unused ";
+ break;
+
+ case PARTITION_FAT_12:
+ pType = "FAT 12 ";
+ break;
+
+ case PARTITION_XENIX_1:
+ pType = "Xenix 1 ";
+ break;
+
+ case PARTITION_XENIX_2:
+ pType = "Xenix 2 ";
+ break;
+
+ case PARTITION_FAT_16:
+ pType = "FAT 16 ";
+ break;
+
+ case PARTITION_EXTENDED:
+ pType = "Extended";
+ break;
+
+ case PARTITION_HUGE:
+ pType = "FAT Huge";
+ break;
+
+ case PARTITION_IFS:
+ pType = "IFS ";
+ break;
+
+ case PARTITION_XINT13:
+ pType = "xFAT ";
+ break;
+
+ case PARTITION_XINT13_EXTENDED:
+ pType = "xExtend ";
+ break;
+
+ case PARTITION_PREP:
+ pType = "PowerPC ";
+ break;
+
+ case PARTITION_UNIX:
+ pType = "Unix ";
+ break;
+
+ default:
+ pType = "Huh? ";
+ break;
+ }
+
+ FDLOG_WORK( 2,
+ " %02x(%hs) %hs %hs %hs %08lx:%08lx %08lx:%08lx %08lx\n",
+ p->PartitionType,
+ pType,
+ (p->PartitionType & VALID_NTFT) ? "yes" : "no ",
+ p->BootIndicator ? "yes" : "no ",
+ p->RecognizedPartition ? "yes" : "no ",
+ p->StartingOffset.HighPart,
+ p->StartingOffset.LowPart,
+ p->PartitionLength.HighPart,
+ p->PartitionLength.LowPart,
+ p->HiddenSectors
+ );
+ }
+
+}
+
+
+VOID
+LOG_PERSISTENT(
+ IN PSTR pszPrefix,
+ IN PSTR pszWhitespace,
+ IN PPERSISTENT_REGION_DATA p
+ )
+{
+ if (NULL != p)
+ {
+ FDLOG_WORK(2, "%hs", pszPrefix);
+ FDLOG_WORK(2, "FT obj: 0x%08lx; %lc:[%ls], Type: %ls, New Region? %hs\n",
+ p->FtObject,
+ p->DriveLetter,
+ p->VolumeLabel,
+ p->TypeName,
+ p->NewRegion ? "yes" : "no"
+ );
+
+#if defined( DBLSPACE_ENABLED )
+
+ PDBLSPACE_DESCRIPTOR pd = p->DblSpace;
+
+ if (NULL != pd)
+ {
+ FDLOG_WORK(2,
+ "%hs DblSpace: 0x%08lx\n", pszWhitespace, p->DblSpace);
+ FDLOG_WORK(2,
+ "%hs size MB mounted? chg state? new letter chg? volume\n",
+ pszWhitespace);
+
+ while (NULL != pd)
+ {
+ FDLOG_WORK(2,
+ "%hs %7lu %hs %hs %lc: %hs %lc: %ls\n",
+ pszWhitespace,
+ pd->AllocatedSize,
+ pd->Mounted ? "yes" : "no ",
+ pd->ChangeMountState ? "yes" : "no ",
+ pd->NewDriveLetter,
+ pd->ChangeDriveLetter ? "yes" : "no ",
+ pd->DriveLetter,
+ pd->FileName
+ );
+
+ pd = pd->Next;
+ }
+ }
+
+#endif // DBLSPACE_ENABLED
+
+ }
+}
+
+
+
+VOID
+LOG_ONE_DISK(
+ PPARTITION p
+ )
+{
+ LARGE_INTEGER tmp;
+
+ for (; NULL != p; p = p->Next)
+ {
+ tmp.QuadPart = p->Offset.QuadPart + p->Length.QuadPart;
+
+ FDLOG_WORK(2," %1d %08lx:%08lx %08lx:%08lx %08lx:%08lx %4d %5d 0x%08lx %hs %hs %hs %2d:%hs %hs\n",
+ p->Disk,
+ p->Offset.HighPart,
+ p->Offset.LowPart,
+ p->Length.HighPart,
+ p->Length.LowPart,
+ tmp.HighPart,
+ tmp.LowPart,
+ p->OriginalPartitionNumber,
+ p->PartitionNumber,
+ p->PersistentData,
+ p->Update ? "Yes " : "No ",
+ p->Active ? "Yes " : "No ",
+ p->Recognized ? "Yes " : "No ",
+ (UINT)p->SysID,
+ GetSysId(p->SysID),
+ IsSysIdFT(p->SysID)
+ );
+
+ LOG_PERSISTENT(
+ " == persistent: ",
+ " ",
+ (PPERSISTENT_REGION_DATA)(p->PersistentData)
+ );
+ }
+}
+
+VOID
+LOG_ENGINE_DATA(
+ VOID
+ )
+{
+ ULONG Disk;
+
+ FDLOG_WORK(2,"\nFdisk engine data\n");
+ FDLOG_WORK(2, "=================\n");
+
+ FDLOG_WORK(2,"# of disks: %d\n",CountOfDisks);
+ for (Disk=0; Disk<CountOfDisks; Disk++)
+ {
+ FDLOG_WORK(2," Disk %d = %hs\n",Disk,DiskNames[Disk]);
+ }
+
+ FDLOG_WORK(2,"\n"
+"Disk Cylinder Heads Sectors/Track Bytes/Sector Bytes/Cylinder Bytes/Track OffLine ChangesRequested ChangesCommitted\n"
+ );
+
+ for (Disk=0; Disk<CountOfDisks; Disk++)
+ {
+ FDLOG_WORK(2,"%-4d %08lx:%08lx %-5d %-13d %-12d %-14d %-11d %hs %2d:%hs %2d:%hs\n",
+ Disk,
+ DiskGeometryArray[Disk].Cylinders.HighPart,
+ DiskGeometryArray[Disk].Cylinders.LowPart,
+ DiskGeometryArray[Disk].Heads,
+ DiskGeometryArray[Disk].SectorsPerTrack,
+ DiskGeometryArray[Disk].BytesPerSector,
+ DiskGeometryArray[Disk].BytesPerCylinder,
+ DiskGeometryArray[Disk].BytesPerTrack,
+ OffLine[Disk] ? "yes " : "no ",
+ ChangesRequested[Disk],
+ ChangesRequested[Disk] ? "yes " : "no ",
+ ChangesCommitted[Disk],
+ ChangesCommitted[Disk] ? "yes " : "no "
+ );
+ }
+
+ FDLOG_WORK(2,"\n");
+
+ for (Disk=0; Disk<CountOfDisks; Disk++)
+ {
+ FDLOG_WORK(2,"Disk %d\n",Disk);
+ FDLOG_WORK(2," D Offset Length End Orig Part# Persistent Upd? Act? Rec? SysID FT?\n");
+
+ FDLOG_WORK(2," == Primary Partitions:\n");
+ LOG_ONE_DISK(PrimaryPartitions[Disk]);
+ FDLOG_WORK(2," == Logical Volumes:\n");
+ LOG_ONE_DISK(LogicalVolumes[Disk]);
+ }
+
+ FDLOG_WORK(2,"\n");
+}
+
+
+VOID
+LOG_REGION_DESCRIPTOR(
+ IN PREGION_DESCRIPTOR reg
+ )
+{
+ FDLOG_WORK(2," Persist D Part# Orig# SizeMB Type Act? Rec? SysID FT?\n");
+
+ FDLOG_WORK(2," 0x%08lx %1d %-5d %-5d %-6d %hs %hs %hs %2d:%hs %hs\n",
+ reg->PersistentData,
+ reg->Disk,
+ reg->PartitionNumber,
+ reg->OriginalPartitionNumber,
+ reg->SizeMB,
+ GetRegionType(reg->RegionType),
+ reg->Active ? "yes " : "no ",
+ reg->Recognized ? "yes " : "no ",
+ (UINT)reg->SysID,
+ GetSysId(reg->SysID),
+ IsSysIdFT(reg->SysID)
+ );
+
+ LOG_PERSISTENT(
+ " persistent: ",
+ " ",
+ (PPERSISTENT_REGION_DATA)(reg->PersistentData)
+ );
+
+ FDLOG_WORK(2,"\n");
+}
+
+
+VOID
+LOG_DISKSTATE(
+ VOID
+ )
+{
+ ULONG i;
+ ULONG Disk;
+ PDISKSTATE p;
+
+ FDLOG_WORK(2,"\nDisk state data, %d disks\n",DiskCount);
+ FDLOG_WORK(2, "=========================\n");
+
+ for (Disk=0; Disk<DiskCount; Disk++)
+ {
+ FDLOG_WORK(2,
+" Create: Exist:\n"
+" D SizeMB Any? Prim? Ext? Log? Any? Prim? Ext? Log? Signatur Cre? Offline? BarType\n"
+ );
+
+ PCHAR pBarType;
+
+ p = DiskArray[Disk];
+
+ if (NULL == p) // Disks hasn't been initialized yet for this disk!
+ {
+ FDLOG_WORK(2," %1d --- NO info!\n",Disk);
+ continue;
+ }
+
+ switch (p->BarType)
+ {
+ case BarProportional:
+ pBarType = "Propor";
+ break;
+
+ case BarEqual:
+ pBarType = "Equal";
+ break;
+
+ case BarAuto:
+ pBarType = "Auto";
+ break;
+
+ default:
+ pBarType = "HUH?";
+ break;
+
+ }
+
+ FDLOG_WORK(2," %1d %6d %hs %hs %hs %hs %hs %hs %hs %hs %08lx %hs %hs %hs\n",
+ p->Disk,
+ p->DiskSizeMB,
+ p->CreateAny ? "yes " : "no ",
+ p->CreatePrimary ? "yes " : "no ",
+ p->CreateExtended ? "yes " : "no ",
+ p->CreateLogical ? "yes " : "no ",
+ p->ExistAny ? "yes " : "no ",
+ p->ExistPrimary ? "yes " : "no ",
+ p->ExistExtended ? "yes " : "no ",
+ p->ExistLogical ? "yes " : "no ",
+ p->Signature,
+ p->SigWasCreated ? "yes " : "no ",
+ p->OffLine ? "yes " : "no ",
+ pBarType
+ );
+
+ FDLOG_WORK(2," == Region Descriptor Selected? left right\n");
+
+ for (i=0; i<p->RegionCount; i++)
+ {
+ FDLOG_WORK(2, " %-6d 0x%08lx %hs %08lx %08lx\n",
+ i,
+ &(p->RegionArray[i]),
+ p->Selected[i] ? "yes" : "no ",
+ p->LeftRight[i].Left,
+ p->LeftRight[i].Right
+ );
+
+ LOG_REGION_DESCRIPTOR(&(p->RegionArray[i]));
+ }
+ }
+}
+
+
+VOID
+LOG_FTOBJECTSET(
+ VOID
+ )
+{
+ PFT_OBJECT_SET p;
+ PFT_OBJECT q;
+
+ FDLOG_WORK(2,"\nFT objects data\n");
+ FDLOG_WORK(2, "===============\n");
+
+ FDLOG_WORK(2,
+" Address Type Ordinal &Mem0 Status Flag\n\n"
+ );
+
+ for (p = FtObjectList; NULL != p; p = p->Next)
+ {
+ PCHAR pSetStatus, pType, pFlag;
+
+ pType = GetFtType(p->Type);
+ pSetStatus = GetFtStatus(p->Status);
+
+ if (p->Flag)
+ {
+ pFlag = "TRUE ";
+ }
+ else
+ {
+ pFlag = "FALSE";
+ }
+
+ FDLOG_WORK(2," 0x%08lx %hs %-7d 0x%08lx %hs %hs\n",
+ p,
+ pType,
+ p->Ordinal,
+ p->Member0,
+ pSetStatus,
+ pFlag
+ );
+
+ FDLOG_WORK(2,
+" == Elements:\n"
+" Address Set Address Index State Region\n"
+ );
+
+ for (q = p->Members; NULL != q; q = q->Next)
+ {
+ PCHAR pMemberState;
+
+ switch (q->State)
+ {
+ case Healthy:
+ pMemberState = "Healthy ";
+ break;
+
+ case Orphaned:
+ pMemberState = "Orphaned ";
+ break;
+
+ case Initializing:
+ pMemberState = "Initializing";
+ break;
+
+ default:
+ pMemberState = "HUH? ";
+ break;
+
+ }
+
+ FDLOG_WORK(2," 0x%08x 0x%08x %-5d %hs 0x%08x\n",
+ q,
+ q->Set,
+ q->MemberIndex,
+ pMemberState,
+ q->Region
+ );
+ }
+
+ FDLOG_WORK(2,"\n");
+ }
+}
+
+
+
+VOID
+LOG_DRIVELETTERS(
+ VOID
+ )
+{
+ WCHAR DriveLetter;
+
+ FDLOG_WORK(2,"\nDrive letters\n");
+ FDLOG_WORK(2, "===============\n");
+
+ FDLOG_WORK(2, " used: ");
+
+ for (DriveLetter = L'C'; DriveLetter <= L'Z'; DriveLetter++)
+ {
+ if (!DriveLetterIsAvailable(DriveLetter))
+ {
+ FDLOG_WORK(2, "%lc ", DriveLetter);
+ }
+ }
+
+ FDLOG_WORK(2, "\n free: ");
+
+ for (DriveLetter = L'C'; DriveLetter <= L'Z'; DriveLetter++)
+ {
+ if (DriveLetterIsAvailable(DriveLetter))
+ {
+ FDLOG_WORK(2, "%lc ", DriveLetter);
+ }
+ }
+
+ FDLOG_WORK(2, "\n");
+
+ FDLOG_WORK(2, " Drive disk part region1(letter) region2(drive,part) Significant?\n");
+
+ for (DriveLetter = L'C'; DriveLetter <= L'Z'; DriveLetter++)
+ {
+ if (!DriveLetterIsAvailable(DriveLetter))
+ {
+ ULONG DiskNum = GetDiskNumberFromDriveLetter(DriveLetter);
+ ULONG PartNum = GetPartitionNumberFromDriveLetter(DriveLetter);
+ PREGION_DESCRIPTOR Region1 = NULL;
+ if (-1 != DiskNum && -1 != PartNum)
+ {
+ Region1 = RegionFromDiskAndPartitionNumbers(
+ DiskNum,
+ PartNum);
+ }
+ PREGION_DESCRIPTOR Region2 = RegionFromDriveLetter(DriveLetter);
+ BOOL f = SignificantDriveLetter(DriveLetter);
+
+ FDLOG_WORK(2,
+ " %lc: %-4d %-4d 0x%08lx 0x%08lx %hs\n",
+ DriveLetter,
+ DiskNum,
+ PartNum,
+ Region1,
+ Region2,
+ f ? "yes" : "no "
+ );
+ }
+ }
+}
+
+
+VOID
+LOG_CDROM(
+ VOID
+ )
+{
+ FDLOG_WORK(2,"\nCD-ROM data\n");
+ FDLOG_WORK(2, "===========\n");
+
+ if (0 == CdRomCount)
+ {
+ FDLOG_WORK(2, "None!\n");
+ }
+ else
+ {
+ FDLOG_WORK(2, "%d CD-ROMs\n\n", CdRomCount);
+
+ FDLOG_WORK(2, "Drive Letter Device # Device Name\n");
+
+ for (ULONG i = 0; i < CdRomCount; i++)
+ {
+ FDLOG_WORK(2, "%lc: %8ld %ls\n",
+ CdRomArray[i].DriveLetter,
+ CdRomArray[i].DeviceNumber,
+ CdRomArray[i].DeviceName
+ );
+ }
+ }
+}
+
+
+VOID
+LOG_LOCKLIST(
+ VOID
+ )
+{
+ FDLOG_WORK(2,"\nLOCKLIST data\n");
+ FDLOG_WORK(2, "=============\n");
+
+ PDRIVE_LOCKLIST p = DriveLockListHead;
+
+ if (NULL == p)
+ {
+ FDLOG_WORK(2, "None!\n");
+ }
+ else
+ {
+ FDLOG_WORK(2,
+ "Handle D# P# LockDisk UnlockDisk Drive Remove? FailOK? Locked?\n");
+
+ while (NULL != p)
+ {
+ FDLOG_WORK(2,
+ "0x%08lx %3d %3d %8d %10d %lc: %hs %hs %hs\n",
+ p->LockHandle,
+ p->DiskNumber,
+ p->PartitionNumber,
+ p->LockOnDiskNumber,
+ p->UnlockOnDiskNumber,
+ p->DriveLetter,
+ p->RemoveOnUnlock ? "yes" : "no ",
+ p->FailOk ? "yes" : "no ",
+ p->CurrentlyLocked ? "yes" : "no "
+ );
+
+ p = p->Next;
+ }
+ }
+}
+
+
+VOID
+LOG_ASSIGNLIST(
+ VOID
+ )
+{
+ FDLOG_WORK(2,"\nASSIGNLIST data\n");
+ FDLOG_WORK(2, "===============\n");
+
+ PASSIGN_LIST p = AssignDriveLetterListHead;
+
+ if (NULL == p)
+ {
+ FDLOG_WORK(2, "None!\n");
+ }
+ else
+ {
+ FDLOG_WORK(2, " D# Drive\n");
+
+ while (NULL != p)
+ {
+ FDLOG_WORK(2, "%3d %lc:\n",
+ p->DiskNumber,
+ p->DriveLetter
+ );
+
+ p = p->Next;
+ }
+ }
+}
+
+
+
+
+
+VOID
+LOG_WINDOWSTATE(
+ VOID
+ )
+{
+ FDLOG_WORK(2,"\nWindow state data\n");
+ FDLOG_WORK(2, "=================\n");
+
+ FDLOG_WORK(2,
+"\n"
+"g_WhichView = "
+ );
+
+ if (VIEW_VOLUMES == g_WhichView)
+ {
+ FDLOG_WORK(2, "Volumes\n");
+ }
+ else
+ if (VIEW_DISKS == g_WhichView)
+ {
+ FDLOG_WORK(2, "Disks\n");
+ }
+ else
+ {
+ FDLOG_WORK(2, "HUH????\n");
+ }
+
+ FDLOG_WORK(2,
+"\n"
+"GraphWidth = %d, GraphHeight = %d\n"
+"BarTopYOffset = %d, BarBottomYOffset = %d\n"
+"dxDriveLetterStatusArea = %d\n"
+"dxBarTextMargin = %d, dyBarTextLine = %d\n"
+"BarLeftX = %d, BarWidth = %d\n"
+"xSmallDisk = %d, ySmallDisk = %d, dxSmallDisk = %d, dySmallDisk = %d\n"
+"g_wLegendItem = %d, g_dyLegendSep = %d\n"
+"g_dyBorder = %d, g_dyToolbar = %d, g_dyLegend = %d, g_dyStatus = %d\n"
+"g_Toolbar? %hs, g_StatusBar? %hs, g_Legend? %hs\n"
+,
+GraphWidth, GraphHeight,
+BarTopYOffset, BarBottomYOffset,
+dxDriveLetterStatusArea,
+dxBarTextMargin, dyBarTextLine,
+BarLeftX, BarWidth,
+xSmallDisk, ySmallDisk, dxSmallDisk, dySmallDisk,
+g_wLegendItem, g_dyLegendSep,
+g_dyBorder, g_dyToolbar, g_dyLegend, g_dyStatus,
+g_Toolbar ? "yes" : "no", g_StatusBar ? "yes" : "no", g_Legend ? "yes" : "no"
+ );
+
+ FDLOG_WORK(2,
+"\n"
+"RegistryChanged? %hs\n"
+,
+RegistryChanged ? "yes" : "no"
+ );
+
+ FDLOG_WORK(2,
+"\n"
+"SelectionCount = %d\n"
+"SelectedFreeSpaces = %d\n"
+"SelectedNonFtPartitions = %d\n"
+"FreeSpaceIndex = %d\n"
+"FtSelectionType = %d\n"
+"FtSetSelected? %hs\n"
+"NonFtItemSelected? %hs\n"
+"MultipleItemsSelected? %hs\n"
+"VolumeSetAndFreeSpaceSelected? %hs\n"
+"PartitionAndFreeSpaceSelected? %hs\n"
+"PossibleRecover? %hs\n"
+"DiskSelected? %hs\n"
+"PartitionSelected? %hs\n"
+"LBCursorListBoxItem = %d\n"
+"LBCursorRegion = %d\n"
+,
+SelectionCount,
+SelectedFreeSpaces,
+SelectedNonFtPartitions,
+FreeSpaceIndex,
+(INT)FtSelectionType,
+FtSetSelected ? "yes" : "no",
+NonFtItemSelected ? "yes" : "no",
+MultipleItemsSelected ? "yes" : "no",
+VolumeSetAndFreeSpaceSelected ? "yes" : "no",
+PartitionAndFreeSpaceSelected ? "yes" : "no",
+PossibleRecover ? "yes" : "no",
+DiskSelected ? "yes" : "no",
+PartitionSelected ? "yes" : "no",
+LBCursorListBoxItem,
+LBCursorRegion
+ );
+
+ FDLOG_WORK(2, "\n");
+
+ for (DWORD i = 0; i < SelectionCount; i++)
+ {
+ FDLOG_WORK(2,
+ "SelectedRG[%d] = %d\n",
+ i,
+ SelectedRG[i]
+ );
+ }
+
+ FDLOG_WORK(2, "\n");
+
+ for (ULONG j = 0; j < DiskCount; j++)
+ {
+ FDLOG_WORK(2,
+ "DiskSeenCountArray[%d] = %d\n",
+ j,
+ DiskSeenCountArray[j]
+ );
+ }
+
+ FDLOG_WORK(2,
+"\n"
+"ProfileWindowX = %d\n"
+"ProfileWindowY = %d\n"
+"ProfileWindowW = %d\n"
+"ProfileWindowH = %d\n"
+"ProfileIsMaximized? %hs\n"
+"ProfileIsIconic? %hs\n"
+,
+ProfileWindowX,
+ProfileWindowY,
+ProfileWindowW,
+ProfileWindowH,
+ProfileIsMaximized ? "yes" : "no",
+ProfileIsIconic ? "yes" : "no"
+ );
+}
+
+
+VOID
+LOG_ALL(
+ VOID
+ )
+{
+ daDebugOut((DEB_ITRACE,"Logging...\n"));
+
+ FDLOG_WORK(2,"\n\nLogging...........................................\n");
+ FDLOG_WORK(2, "==================================================\n\n");
+
+ LOG_ENGINE_DATA();
+ LOG_FTOBJECTSET();
+ LOG_DISKSTATE();
+ LOG_DRIVELETTERS();
+ LOG_CDROM();
+ LOG_LOCKLIST();
+ LOG_ASSIGNLIST();
+ LOG_WINDOWSTATE();
+}
+
+
+#ifdef WINDISK_EXTENSIONS
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintVolumeClaims
+//
+// Synopsis: Print the extension claims for a drive letter to the debugger
+// (if DEB_TRACE is set in daInfoLevel)
+//
+// Arguments: [DriveLetter] -- the drive letter
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PrintVolumeClaims(
+ IN WCHAR DriveLetter
+ )
+{
+ unsigned i = (unsigned)DriveLetterToIndex(DriveLetter);
+
+ // if drive DriveLetter is used...
+ if (NULL != VolumeInfo[i].DiskState)
+ {
+ PVOL_CLAIM_LIST volClaims = VolumeInfo[i].VolClaims;
+
+ if (NULL != volClaims)
+ {
+ daDebugOut((DEB_TRACE,
+ "Volume extensions: Drive %lc, Disk %d, Region %d: ",
+ DriveLetter,
+ VolumeInfo[i].DiskState->Disk,
+ VolumeInfo[i].RegionIndex
+ ));
+
+ while (NULL != volClaims)
+ {
+ daDebugOut((DEB_TRACE | DEB_NOCOMPNAME,
+ "%ls, ",
+ volClaims->pClaimer->pInfo->pwszShortName));
+
+ volClaims = volClaims->pNext;
+ }
+
+ daDebugOut((DEB_TRACE | DEB_NOCOMPNAME, "\n"));
+ }
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintDiskClaims
+//
+// Synopsis: Print the extension claims for a disk to the debugger
+// (if DEB_TRACE is set in daInfoLevel)
+//
+// Arguments: [DiskNum] --
+//
+// Returns: nothing
+//
+// History: 7-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PrintDiskClaims(
+ IN ULONG DiskNum
+ )
+{
+ PHARDDISK_CLAIM_LIST pClaims = DiskArray[DiskNum]->pClaims;
+
+ if (NULL != pClaims)
+ {
+ daDebugOut((DEB_TRACE, "Disk extensions, Disk %d: ", DiskNum));
+
+ while (NULL != pClaims)
+ {
+ daDebugOut((DEB_TRACE | DEB_NOCOMPNAME,
+ "%ls, ",
+ pClaims->pClaimer->pInfo->pwszShortName));
+
+ pClaims = pClaims->pNext;
+ }
+ daDebugOut((DEB_TRACE | DEB_NOCOMPNAME, "\n"));
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintClaims
+//
+// Synopsis: Dump all claims
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PrintClaims(
+ VOID
+ )
+{
+ for (WCHAR DriveLetter = L'C'; DriveLetter <= L'Z'; DriveLetter++)
+ {
+ PrintVolumeClaims(DriveLetter);
+ }
+
+ for (ULONG DiskNum = 0; DiskNum<DiskCount; DiskNum++)
+ {
+ PrintDiskClaims(DiskNum);
+ }
+}
+
+#endif // WINDISK_EXTENSIONS
+
+#endif // DBG == 1
diff --git a/private/utils/windisk/src/makefile b/private/utils/windisk/src/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/src/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/src/makefile.inc b/private/utils/windisk/src/makefile.inc
new file mode 100644
index 000000000..4686e9ef8
--- /dev/null
+++ b/private/utils/windisk/src/makefile.inc
@@ -0,0 +1,24 @@
+obj\$(TARGET_DIRECTORY)\windisk.res: \
+ $(BASEDIR)\public\sdk\inc\windows.h \
+ $(BASEDIR)\public\sdk\inc\common.ver \
+ $(BASEDIR)\public\sdk\inc\ntverp.h \
+ resids.h \
+ dialogs.h \
+ dialogs.dlg \
+ dblspace.h \
+ dblspace.dlg \
+ ftreg.h \
+ ftreg.dlg \
+ dskmgr.ico \
+ trffc14.ico \
+ shard.ico \
+ scdrom.ico \
+ tool16.bmp \
+ xtra16.bmp \
+ smdisk.bmp \
+ smcdrom.bmp \
+ rmdisk.bmp \
+ cdr.bmp \
+ hard.bmp \
+ obj\messages.h \
+ obj\messages.rc
diff --git a/private/utils/windisk/src/mem.cxx b/private/utils/windisk/src/mem.cxx
new file mode 100644
index 000000000..fa1dff75e
--- /dev/null
+++ b/private/utils/windisk/src/mem.cxx
@@ -0,0 +1,92 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mem.cxx
+//
+// Contents: Memory management routines. These are used by the fdisk
+// engine fdengine.c as well as the rest of Disk Administrator.
+// Since fdengine.c is a C file, these must by C entrypoints,
+// even though they must compile in a C++ file so they can access
+// the CommonDialog() API.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+//////////////////////////////////////////////////////////////////////////////
+
+PVOID
+Malloc(
+ IN ULONG Size
+ )
+{
+ PVOID p;
+
+ while (NULL == (p = malloc(Size)))
+ {
+ ConfirmOutOfMemory();
+ }
+ return p;
+}
+
+
+PVOID
+Realloc(
+ IN PVOID Block,
+ IN ULONG NewSize
+ )
+{
+ PVOID p;
+
+ if (0 != NewSize)
+ {
+ while (NULL == (p = realloc(Block, NewSize)))
+ {
+ ConfirmOutOfMemory();
+ }
+ }
+ else
+ {
+ //
+ // realloc with a size of 0 is the same as free,
+ // so special case that here.
+ //
+
+ free(Block);
+ while (NULL == (p = malloc(0)))
+ {
+ ConfirmOutOfMemory();
+ }
+ }
+ return p;
+}
+
+
+VOID
+Free(
+ IN PVOID Block
+ )
+{
+ free(Block);
+}
+
+
+
+VOID
+ConfirmOutOfMemory(
+ VOID
+ )
+{
+ if (IDRETRY != CommonDialogNoArglist(
+ MSG_OUT_OF_MEMORY,
+ NULL,
+ MB_ICONHAND | MB_RETRYCANCEL | MB_SYSTEMMODAL))
+ {
+ exit(1);
+ }
+}
diff --git a/private/utils/windisk/src/mem.hxx b/private/utils/windisk/src/mem.hxx
new file mode 100644
index 000000000..b3d37878b
--- /dev/null
+++ b/private/utils/windisk/src/mem.hxx
@@ -0,0 +1,38 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mem.hxx
+//
+// Contents: C++ definitions for memory functions in mem.cxx.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MEM_HXX__
+#define __MEM_HXX__
+
+PVOID
+Malloc(
+ IN ULONG Size
+ );
+
+PVOID
+Realloc(
+ IN PVOID Block,
+ IN ULONG NewSize
+ );
+
+VOID
+Free(
+ IN PVOID Block
+ );
+
+VOID
+ConfirmOutOfMemory(
+ VOID
+ );
+
+#endif // __MEM_HXX__
diff --git a/private/utils/windisk/src/menudict.cxx b/private/utils/windisk/src/menudict.cxx
new file mode 100644
index 000000000..98eddd002
--- /dev/null
+++ b/private/utils/windisk/src/menudict.cxx
@@ -0,0 +1,201 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: menudict.cxx
+//
+// Contents: Dictionary of extension menu IDs
+//
+// History: 2-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#ifdef WINDISK_EXTENSIONS
+
+#include "resids.h"
+#include "menudict.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+CMenuItems
+MenuItems(
+ IDM_EXTENSION_START,
+ IDM_EXTENSION_END
+ );
+
+CMenuItems
+ContextMenuItems(
+ IDM_CONTEXT_EXTENSION_START,
+ IDM_CONTEXT_EXTENSION_END
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMenuItems::AllocateId
+//
+// Synopsis: Given an extension menu item, assign it an unused resource
+// ID, and return it.
+//
+// Arguments: [pItem] -- the extension menu item
+//
+// Returns: The assigned resource ID, or -1 on error (out of memory or no
+// IDs available)
+//
+// Derivation: none
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+CMenuItems::AllocateId(
+ IN MenuItemType* pItem
+ )
+{
+ if (_NextMenuId > _wIdEnd)
+ {
+ daDebugOut((DEB_IERROR,
+ "No extension IDs left! (next = %d, start = %d, end = %d\n",
+ _NextMenuId,
+ _wIdStart,
+ _wIdEnd
+ ));
+
+ return -1; // no IDs left!
+ }
+
+ MenuIDDictType* pElem = (MenuIDDictType*)Malloc(sizeof(MenuIDDictType));
+ if (NULL == pElem)
+ {
+ daDebugOut((DEB_ERROR, "Malloc failed!\n"));
+
+ return -1; // out of memory
+ }
+
+ pElem->pNext = _pHead;
+ pElem->Id = _NextMenuId;
+ pElem->pItem = pItem;
+
+ _pHead = pElem; // the new one is first
+
+ return _NextMenuId++;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMenuItems::LookupMenuItem
+//
+// Synopsis: Given a resource ID, return the associated extension menu item,
+// or NULL if the ID isn't associated with an extension menu item
+//
+// Arguments: [Id] -- a resource ID
+//
+// Returns: The extension menu item, or NULL if no item has the ID
+//
+// Derivation: none
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+MenuItemType*
+CMenuItems::LookupMenuItem(
+ IN UINT Id
+ )
+{
+ MenuIDDictType* pElem = _pHead;
+
+ while (NULL != pElem)
+ {
+ if (Id == pElem->Id)
+ {
+ return pElem->pItem;
+ }
+ pElem = pElem->pNext;
+ }
+ return NULL;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMenuItems::LookupMenuId
+//
+// Synopsis: Given a menu item, return the associated menu ID, if
+// any, or -1
+//
+// Arguments: [pItem] -- the extension menu item
+//
+// Returns: The assigned resource ID, or -1 on error
+//
+// Derivation: none
+//
+// History: 26-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+CMenuItems::LookupMenuId(
+ IN MenuItemType* pItem
+ )
+{
+ MenuIDDictType* pElem = _pHead;
+
+ while (NULL != pElem)
+ {
+ if (pItem == pElem->pItem)
+ {
+ return pElem->Id;
+ }
+ pElem = pElem->pNext;
+ }
+ return -1;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMenuItems::DeAllocateMenuIds
+//
+// Synopsis: Deallocate all the menu IDs
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CMenuItems::DeAllocateMenuIds(
+ VOID
+ )
+{
+ MenuIDDictType* pTmp;
+ MenuIDDictType* pElem = _pHead;
+
+ while (NULL != pElem)
+ {
+ pTmp = pElem->pNext;
+ Free(pElem);
+ pElem = pTmp;
+ }
+ _pHead = NULL;
+
+ _NextMenuId = _wIdStart;
+}
+
+#endif // WINDISK_EXTENSIONS
diff --git a/private/utils/windisk/src/menudict.hxx b/private/utils/windisk/src/menudict.hxx
new file mode 100644
index 000000000..77f489116
--- /dev/null
+++ b/private/utils/windisk/src/menudict.hxx
@@ -0,0 +1,113 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: menudict.hxx
+//
+// Contents: Dictionary of extension menu IDs
+//
+// History: 2-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MENUDICT_HXX__
+#define __MENUDICT_HXX__
+
+#ifdef WINDISK_EXTENSIONS
+
+//
+// The dictionary structure is a linked list:
+//
+
+struct MenuIDDictType
+{
+ MenuIDDictType* pNext;
+ UINT Id;
+ MenuItemType* pItem;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMenuItems
+//
+// Purpose: A dictionary of extension menu IDs
+//
+// Interface: AllocateId -- given an extension menu item,
+// return a Windows menu ID
+// LookupMenuItem -- given a Windows menu ID, lookup the
+// extension menu item
+// LookupMenuId -- given an extension item, find the
+// Windows menu ID already associated with it
+// extension menu item
+// DeAllocateMenuIds -- Deallocate all space associated
+// with the mapping
+//
+// History: 2-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+class CMenuItems
+{
+public:
+
+ CMenuItems(
+ IN UINT wIdStart,
+ IN UINT wIdEnd
+ )
+ :
+ _pHead(NULL),
+ _wIdStart(wIdStart),
+ _wIdEnd(wIdEnd),
+ _NextMenuId(wIdStart)
+ {
+ }
+
+ ~CMenuItems()
+ {
+ DeAllocateMenuIds();
+ }
+
+ INT
+ AllocateId(
+ IN MenuItemType* pItem
+ );
+
+ MenuItemType*
+ LookupMenuItem(
+ IN UINT Id
+ );
+
+ INT
+ LookupMenuId(
+ IN MenuItemType* pItem
+ );
+
+ VOID
+ DeAllocateMenuIds(
+ VOID
+ );
+
+ BOOL
+ IsExtensionId(
+ IN UINT Id
+ )
+ {
+ return (_wIdStart <= Id) && (Id < _NextMenuId);
+ }
+
+private:
+
+ MenuIDDictType* _pHead;
+ UINT _wIdStart;
+ UINT _wIdEnd;
+ UINT _NextMenuId;
+};
+
+extern CMenuItems MenuItems;
+extern CMenuItems ContextMenuItems;
+
+#endif // WINDISK_EXTENSIONS
+
+#endif // __MENUDICT_HXX__
diff --git a/private/utils/windisk/src/messages.mc b/private/utils/windisk/src/messages.mc
new file mode 100644
index 000000000..4900fcb72
--- /dev/null
+++ b/private/utils/windisk/src/messages.mc
@@ -0,0 +1,617 @@
+;/*++
+;
+;Copyright (c) 1991 Microsoft Corporation
+;
+;Module Name:
+;
+; messages.h
+;
+;Abstract:
+;
+; This file contains the message definitions for Disk Administrator
+;
+;Author:
+;
+; Ted Miller (tedm) 5-Dec-1991
+;
+;Revision History:
+;
+;Notes:
+;
+; This file is generated from messages.mc
+;
+;--*/
+;
+;#ifndef ___MESSAGES_H__
+;#define ___MESSAGES_H__
+;
+;
+
+MessageID=9000 SymbolicName=MSG_FIRST_FDISK_MSG
+Language=English
+.
+
+MessageID=9001 SymbolicName=MSG_CANT_INITIALIZE
+Language=English
+Disk Administrator was unable to initialize.
+Click OK to exit.
+.
+
+MessageID=9002 SymbolicName=MSG_NO_DISKS
+Language=English
+Disk Administrator has determined that there are no fixed disks attached to the system, or all such disks are off-line. Click OK to exit.
+.
+
+MessageID=9003 SymbolicName=MSG_ACCESS_DENIED
+Language=English
+Access is denied. You must be logged on with Administrative privilege to run Disk Administrator.
+.
+
+MessageID=9004 SymbolicName=MSG_CONFIRM_DELETE
+Language=English
+All data in the partition or logical drive will be lost!
+
+Are you sure you want to delete the chosen partition or logical drive?
+.
+
+MessageID=9005 SymbolicName=MSG_CREATE_NOT_COMPAT
+Language=English
+This operation will result in a disk whose partition scheme may not be compatible with MS-DOS. Some partitions may not be accessible if the disk is used with MS-DOS in the future.
+
+Do you want to continue and create the partition anyway?
+.
+
+MessageID=9006 SymbolicName=MSG_INVALID_SIZE
+Language=English
+Invalid size.
+.
+
+MessageID=9007 SymbolicName=MSG_ALREADY_RUNNING
+Language=English
+Disk Administrator is already running.
+.
+
+MessageID=9008 SymbolicName=MSG_CONFIRM_EXIT
+Language=English
+Changes have been made to your disk configuration.
+
+Do you want to save the changes?
+.
+
+MessageID=9009 SymbolicName=MSG_OUT_OF_MEMORY
+Language=English
+Disk Administrator has run out of memory. Select Cancel to exit Disk Administrator, or try closing other applications to free memory and then select Retry. If you exit, all changes will be lost.
+.
+
+MessageID=9010 SymbolicName=MSG_OK_COMMIT
+Language=English
+Disks were updated successfully.
+
+It is recommended that you update the emergency repair configuration information and create a new Emergency Repair Disk. You can do this with the system utility RDISK.EXE.
+.
+
+MessageID=9011 SymbolicName=MSG_CANT_DELETE_WINNT
+Language=English
+Disk Administrator cannot delete the partition containing Windows NT system files.
+.
+
+MessageID=9012 SymbolicName=MSG_HELP_ERROR
+Language=English
+Could not invoke help application.
+.
+
+MessageID=9013 SymbolicName=MSG_NO_AVAIL_LETTER
+Language=English
+All available drive letters are already assigned.
+
+You will not be able to access the %1 from Windows NT unless you rearrange drive letter usage.
+
+Do you want to continue and create the %1 anyway?
+.
+
+MessageID=9014 SymbolicName=MSG_BAD_CONFIG_SET
+Language=English
+An error occurred while updating disk configuration.
+
+Drive letter and fault tolerance information may be lost and/or some partitions may be inaccessible.
+.
+
+MessageID=9015 SymbolicName=MSG_CONFIG_MISSING_DISK
+Language=English
+Disk Administrator has determined that one or more disks have been removed from your computer since Disk Administrator was last run, or that one or more disks are off-line.
+
+Configuration information about the missing disk(s) will be retained.
+.
+
+MessageID=9016 SymbolicName=MSG_CONFIG_EXTRA_DISK
+Language=English
+Disk Administrator has determined that this is the first time Disk Administrator has been run, or that one or more disks have been added to your computer since Disk Administrator was last run.
+
+System configuration will now be updated.
+.
+
+MessageID=9017 SymbolicName=MSG_CONFIG_DISK_CHANGED
+Language=English
+Disk Administrator has determined that the configuration of one of more disks has been altered since Disk Administrator was last run.
+
+System configuration will be automatically updated to reflect these changes when you next opt to save changes when exiting Disk Administrator.
+.
+
+MessageID=9018 SymbolicName=MSG_ALL_DRIVE_LETTERS_USED
+Language=English
+All drive letters are already assigned.
+.
+
+MessageID=9019 SymbolicName=MSG_PART_TABLE_FULL
+Language=English
+No more primary partitions can be created on the disk. A disk cannot hold more than four partitions (including the extended partition but not including logical drives).
+.
+
+MessageID=9020 SymbolicName=MSG_EXTENDED_ALREADY_EXISTS
+Language=English
+An extended partition already exists on the disk.
+.
+
+MessageID=9021 SymbolicName=MSG_NO_OTHER_NTS
+Language=English
+No other Windows NT installations were found.
+.
+
+MessageID=9022 SymbolicName=MSG_CONFIRM_MIGRATE_CONFIG
+Language=English
+Warning: This operation will overwrite your disk configuration information with the configuration from a different installation of Windows NT. Currently defined drive letters, volume sets, stripe sets, parity stripes, and mirrors may be lost depending on the disk configuration associated with the Windows NT installation you select.
+
+No partitions will be created or deleted by this operation, but any changes you have made during this session of Disk Administrator will be lost.
+
+Do you want to search for other installations of Windows NT?
+.
+
+MessageID=9023 SymbolicName=MSG_CONFIRM_RESTORE_CONFIG
+Language=English
+Warning: This operation will overwrite your disk configuration information with a previously saved configuration. Currently defined drive letters, volume sets, stripe sets, parity stripes, and mirrors may be lost depending on the previously saved disk configuration.
+
+No partitions will be created or deleted by this operation, but any changes you have made during this session of Disk Administrator will be lost.
+
+Do you want to continue with the restoration?
+.
+
+MessageID=9024 SymbolicName=MSG_INSERT_REGSAVEDISK
+Language=English
+Please insert a disk (which may be the Emergency Repair Disk), onto which you have previously saved disk configuration information, into drive A:.
+
+Press OK when the disk is in the drive.
+.
+
+MessageID=9025 SymbolicName=MSG_INSERT_REGSAVEDISK2
+Language=English
+This operation will save configuration information about currently defined drive letters, volume sets, stripe sets, stripe sets with parity, and mirror sets. The saved configuration information will be placed on a floppy disk.
+
+Please insert a formatted disk into drive A:. Press OK when the disk is in the drive.
+.
+
+MessageID=9026 SymbolicName=MSG_CONFIG_SAVED_OK
+Language=English
+Disk configuration information was saved successfully.
+.
+
+MessageID=9027 SymbolicName=MSG_ABSOLUTELY_SURE
+Language=English
+Current disk configuration information will be overwritten! Are you absolutely sure you want to continue?
+.
+
+MessageID=9028 SymbolicName=MSG_NO_SIGNATURE
+Language=English
+No signature found on %1. Writing a signature is a safe operation and will not affect your ability to access this disk from other operating systems, such as DOS.
+
+If you choose not to write a signature, the disk will be marked OFF-LINE and be inaccessable to the Windows NT Disk Administrator program.
+
+Do you want to write a signature on %1 so that Disk Administrator can access the drive?
+.
+
+MessageID=9029 SymbolicName=MSG_SCHEDULE_REBOOT
+Language=English
+The drive is in use by other programs. The drive letter cannot be changed without either shutting down those programs or restarting the computer.
+
+Do you wish to perform this change and restart the computer upon exiting Disk Administrator?
+.
+
+MessageId=9030 SymbolicName=MSG_REQUIRE_REBOOT
+Language=English
+The changes requested will require you to restart your computer. Do you wish to continue with the changes and restart the computer?
+.
+
+MessageId=9031 SymbolicName=MSG_NOFMIFS
+Language=English
+Disk Administrator could not locate or use the system file FMIFS.DLL, which is necessary to perform this action.
+.
+
+MessageID=9032 SymbolicName=MSG_MUST_COMMIT_BREAK
+Language=English
+You have selected a partition that is still a member of a mirror set. Breaking the mirror set relationship does not actually happen until you quit Disk Administrator or choose the Commit Changes Now command.
+
+Please do one or the other of these actions and then delete the partition.
+.
+
+MessageID=9034 SymbolicName=MSG_TOO_BIG_FOR_FAT
+Language=English
+This volume cannot be formatted to the FAT file system. FAT can only support volumes up to 4GB in size.
+.
+
+MessageID=9035 SymbolicName=MSG_NO_DISK_INFO
+Language=English
+The configuration selected does not contain any disk configuration information. No change will be made to the current configuration.
+.
+
+MessageID=9036 SymbolicName=MSG_DISK_INFO_BUSY
+Language=English
+The configuration selected is currently open by another application. Close the other accesses to this file and try again.
+.
+
+;//////////////// 9037 -> 9050: unused
+
+MessageId=9051 SymbolicName=MSG_CONFIRM_SHUTDOWN_FOR_MIRROR
+Language=English
+The mirror set cannot be locked. To break this mirror relationship the system must be restarted. This restart of the system will occur on exiting Disk Administrator.
+
+Do you wish to continue with this operation?
+.
+
+MessageId=9052 SymbolicName=MSG_EXTEND_VOLSET_MUST_BE_NTFS
+Language=English
+The volume set is not formatted to NTFS; only NTFS volume sets can be extended.
+.
+
+MessageId=9053 SymbolicName=MSG_CONFIRM_BRKANDDEL_MIRROR
+Language=English
+All data in the mirror will be lost!
+
+Are you sure you want to break the selected mirror and delete its component partitions?
+.
+
+MessageID=9054 SymbolicName=MSG_CANT_EXTEND_WINNT
+Language=English
+Disk Administrator cannot extend the partition containing Windows NT system files.
+.
+
+MessageID=9055 SymbolicName=MSG_CONFIRM_PROTECT_SYSTEM
+Language=English
+Are you sure you want to restrict access to the System Partition to System Administrators?
+
+Performing this operation will require a restart of the system.
+.
+
+MessageID=9056 SymbolicName=MSG_CONFIRM_UNPROTECT_SYSTEM
+Language=English
+Are you sure you want to allow all users access to the System Partition?
+
+Performing this operation will require a restart of the system.
+.
+
+MessageID=9057 SymbolicName=MSG_CANT_PROTECT_SYSTEM
+Language=English
+Disk Administrator cannot mark the System Partition secure.
+.
+
+MessageID=9058 SymbolicName=MSG_CANT_UNPROTECT_SYSTEM
+Language=English
+Disk Administrator cannot mark the System Partition as non-secure.
+.
+
+MessageID=9059 SymbolicName=MSG_NO_REMOVABLE_IN_STRIPE
+Language=English
+Stripe sets cannot include partitions on removable media.
+.
+
+MessageID=9060 SymbolicName=MSG_NO_REMOVABLE_IN_VOLUMESET
+Language=English
+Volume sets cannot include partitions on removable media.
+.
+
+MessageID=9061 SymbolicName=MSG_NO_REMOVABLE_IN_MIRROR
+Language=English
+Mirror pairs cannot include partitions on removable media.
+.
+
+MessageID=9062 SymbolicName=MSG_CANT_ASSIGN_LETTER_TO_REMOVABLE
+Language=English
+Disk Administrator cannot assign drive letters to partitions on removable media.
+.
+
+MessageID=9063 SymbolicName=MSG_NO_EXTENDED_ON_REMOVABLE
+Language=English
+Disk Administrator cannot create extended partitions on removable media.
+.
+
+MessageID=9064 SymbolicName=MSG_ONLY_ONE_PARTITION_ON_REMOVABLE
+Language=English
+Disk Administrator can only create one partition on a removable disk.
+.
+
+MessageID=9065 SymbolicName=MSG_REMOVABLE_PARTITION_NOT_FULL_SIZE
+Language=English
+Disk Administrator can only create one partition on a removable disk. Therefore, if you create a partition which does not use the entire disk, you will not be able to use the remaining free space.
+
+Are you sure you want to create this partition?
+.
+
+;//////////////// 9066 -> 9067 : unused
+
+MessageID=9068 SymbolicName=MSG_CANT_FORMAT_WINNT
+Language=English
+Disk Administrator cannot format a volume containing Windows NT system files.
+.
+
+MessageID=9069 SymbolicName=MSG_CANT_DELETE_INITIALIZING_SET
+Language=English
+Disk Administrator cannot delete an FT set while it is initializing or regenerating.
+.
+
+MessageID=9070 SymbolicName=MSG_CANT_BREAK_INITIALIZING_SET
+Language=English
+Disk Administrator cannot break a Mirror set while it is initializing.
+.
+
+MessageID=9071 SymbolicName=MSG_CANT_REGEN_INITIALIZING_SET
+Language=English
+Disk Administrator cannot regenerate a Stripe set with Parity while it is initializing or regenerating.
+.
+
+MessageID=9072 SymbolicName=MSG_MIRROR_OF_BOOT
+Language=English
+This will be a Mirror set of the system boot partition. Please refer to the Windows NT Server Concepts and Planning Guide for information on how to create a Fault Tolerant boot floppy disk.
+.
+
+MessageID=9073 SymbolicName=MSG_CHANGED_BOOT_PARTITION_X86
+Language=English
+This change will modify the partition number of the partition which contains your Windows NT system files.
+
+The old partition number was %1; the new partition number is %2.
+
+Edit BOOT.INI to reflect this change before shutting the system down.
+.
+
+MessageID=9074 SymbolicName=MSG_CHANGED_BOOT_PARTITION_ARC
+Language=English
+This change will modify the partition number of the partition which contains your Windows NT system files.
+
+The old partition number was %1; the new partition number is %2.
+.
+
+MessageID=9075 SymbolicName=MSG_BOOT_PARTITION_CHANGED_X86
+Language=English
+The partition number of the partition which contains your Windows NT system files has changed.
+
+The old partition number was %1; the new partition number is %2.
+
+Edit BOOT.INI to reflect this change before shutting the system down.
+.
+
+MessageID=9076 SymbolicName=MSG_BOOT_PARTITION_CHANGED_ARC
+Language=English
+The partition number of the partition which contains your Windows NT system files has changed.
+
+The old partition number was %1; the new partition number is %2.
+.
+
+;//////////////// 9077 -> 9099: unused
+
+MessageID=9100 SymbolicName=MSG_CONFIRM_DEL_STRP
+Language=English
+All data in the stripe set will be lost!
+
+Are you sure you want to delete the selected stripe set?
+.
+
+MessageID=9101 SymbolicName=MSG_CRTSTRP_FULL
+Language=English
+The disk containing one of the free spaces you have chosen is not able to accept any more partitions.
+.
+
+MessageID=9102 SymbolicName=MSG_CRTMIRROR_BADFREE
+Language=English
+The free space you have chosen is not large enough to contain a mirror of the partition you have chosen.
+.
+
+MessageID=9103 SymbolicName=MSG_CONFIRM_BRK_MIRROR
+Language=English
+This will end mirroring and create two independent partitions.
+
+Are you sure you want to break the selected mirror?
+.
+
+MessageID=9104 SymbolicName=MSG_CONFIRM_DEL_VSET
+Language=English
+All data in the volume set will be lost!
+
+Are you sure you want to delete the selected volume set?
+.
+
+MessageId=9105 SymbolicName=MSG_CANT_INIT_FT
+Language=English
+Disk Administrator was unable to configure the Fault Tolerance Device. Mirrors and stripe sets with parity will not be initialized or regenerated.
+.
+
+MessageId=9106 SymbolicName=MSG_NOT_LARGE_ENOUGH_FOR_STRIPE
+Language=English
+The free space you have chosen is not large enough to contain an element in the stripe set you have chosen for regeneration.
+.
+
+MessageId=9107 SymbolicName=MSG_MUST_REBOOT
+Language=English
+Changes have been made which require you to restart your computer. Click OK to initiate system shutdown.
+.
+
+MessageId=9108 SymbolicName=MSG_COULDNT_REBOOT
+Language=English
+Disk Administrator was unable to restart your computer. To ensure the integrity of your disks and data, you should initiate system shutdown from the Program Manager. Click OK to exit Disk Administrator.
+.
+
+;//////////////// 9109, 9110: unused
+
+MessageID=9120 SymbolicName=MSG_CANT_LOAD_FMIFS
+Language=English
+Disk Administrator cannot locate fmifs.dll.
+.
+
+MessageID=9121 SymbolicName=MSG_CANT_FORMAT_NO_LETTER
+Language=English
+Disk Administrator cannot format a volume that is not assigned a drive letter.
+.
+
+MessageID=9122 SymbolicName=MSG_CONFIRM_FORMAT
+Language=English
+Warning: This operation will overwrite the data contained on this volume. Are you sure you wish to continue with this operation?
+.
+
+MessageID=9123 SymbolicName=MSG_COULDNT_CREATE_THREAD
+Language=English
+Disk Administrator could not create a thread to perform this operation.
+.
+
+MessageID=9124 SymbolicName=MSG_IO_ERROR
+Language=English
+An operation failed while attempting to format the volume.
+.
+
+;//////////////// 9126 -> 9199: unused
+
+MessageID=9200 SymbolicName=MSG_CANNOT_LOCK_TRY_AGAIN
+Language=English
+The drive cannot be locked for exclusive use.
+
+Please check to see if some applications are currently accessing the drive. If so, close them and try again.
+.
+
+MessageID=9201 SymbolicName=MSG_CANNOT_LOCK_FOR_COMMIT
+Language=English
+Disk Administrator could not lock all of the volumes affected by the changes selected. Please exit any applications holding references to the affected volumes and try again.
+.
+
+MessageID=9202 SymbolicName=MSG_NOT_COMMITTED
+Language=English
+The requested partitions and/or volumes have not been committed to disk. Retry this operation after committing this change.
+.
+
+MessageID=9203 SymbolicName=MSG_DRIVE_RENAME_WARNING
+Language=English
+This new drive letter assignment will happen immediately.
+
+Do you wish to continue?
+.
+
+MessageID=9204 SymbolicName=MSG_NO_COMMIT
+Language=English
+Not all of the affected disks can be changed without restarting the Windows NT system.
+.
+
+MessageID=9205 SymbolicName=MSG_VOLUME_CHANGED
+Language=English
+The removable media has changed. Insure the proper media is in the drive and perform the operation again.
+.
+
+MessageID=9206 SymbolicName=MSG_CANNOT_LOCK_PAGEFILE
+Language=English
+The drive letter cannot be changed because a Windows NT paging file is located on this drive.
+
+Relocate the paging file using the control panel system option.
+.
+
+MessageID=9207 SymbolicName=MSG_CDROM_LETTER_ERROR
+Language=English
+An error occurred attempting to change the CD-ROM drive letter.
+
+The drive letter has not been changed.
+.
+
+MessageID=9208 SymbolicName=MSG_CANNOT_LOCK_CDROM
+Language=English
+The CD-ROM cannot be locked for exclusive use.
+
+Please check to see if some applications are currently accessing the drive. If so, close them and try again.
+.
+
+MessageID=9209 SymbolicName=MSG_CANT_BREAK_WHILE_INITIALIZING
+Language=English
+The mirror set cannot be broken at this time.
+.
+
+MessageID=9210 SymbolicName=MSG_INTERNAL_LETTER_ASSIGN_ERROR
+Language=English
+An internal error occurred and some drive letters could not be assigned.
+.
+
+MessageID=9212 SymbolicName=MSG_ERROR_DURING_COMMIT
+Language=English
+Disk Administrator encountered an unknown error while making the requested changes. Some of the requested actions may not have occurred.
+.
+
+MessageID=9213 SymbolicName=MSG_CANNOT_MOVE_CDROM
+Language=English
+The new drive letter for the CD-ROM is still in use. Commit current Disk Administrator changes, verify network drive letter assignments and try again.
+.
+
+MessageID=9214 SymbolicName=MSG_BOOT_NEEDS_LETTER
+Language=English
+The boot drive MUST have a letter.
+.
+
+MessageID=9215 SymbolicName=MSG_SYS_LETTER_CHANGE
+Language=English
+Changing the drive letter for the windows directory may produce unexpected results. Are you sure you want to do this?
+.
+
+MessageID=9216 SymbolicName=MSG_SYS_NEEDS_LETTER
+Language=English
+The drive containing the windows directory MUST have a letter.
+.
+
+;//////////////// 9217 -> 9299: unused
+
+;//////////////////////////////////////////////////////////////////////////////
+;//////////////////////////////////////////////////////////////////////////////
+;/////
+;///// NOTE: the following messages are x86-specific!
+;/////
+;//////////////////////////////////////////////////////////////////////////////
+;//////////////////////////////////////////////////////////////////////////////
+
+MessageID=9300 SymbolicName=MSG_DISK0_ACTIVE
+Language=English
+The requested partition has been marked active.
+When you reboot your computer the operating system on that partition will be started.
+.
+
+MessageID=9301 SymbolicName=MSG_PRI_1024_CYL
+Language=English
+The partition created may not be accessible from other operating systems such as MS-DOS because the start or end cylinder value is too large.
+
+Do you want to create the partition anyway?
+.
+
+MessageID=9302 SymbolicName=MSG_EXT_1024_CYL
+Language=English
+Logical drives created within the extended partition will not be accessible from other operating systems such as MS-DOS because the start or end cylinder value is too large.
+
+Do you want to create the extended partition anyway?
+.
+
+MessageID=9303 SymbolicName=MSG_CANT_DELETE_ACTIVE0
+Language=English
+Disk Administrator cannot delete the active partition on disk 0.
+.
+
+MessageID=9304 SymbolicName=MSG_CANT_EXTEND_ACTIVE0
+Language=English
+Disk Administrator cannot convert the active partition on disk 0 into a volume set.
+.
+
+;//////////////////////////////////////////////////////////////////////////////
+;//////////////////////////////////////////////////////////////////////////////
+;/////
+;///// NOTE: end of x86-specific messages
+;/////
+;//////////////////////////////////////////////////////////////////////////////
+;//////////////////////////////////////////////////////////////////////////////
+
+
+;#endif // __MESSAGES_H__
diff --git a/private/utils/windisk/src/misc.cxx b/private/utils/windisk/src/misc.cxx
new file mode 100644
index 000000000..ff0710d96
--- /dev/null
+++ b/private/utils/windisk/src/misc.cxx
@@ -0,0 +1,1404 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: misc.cxx
+//
+// Contents: Miscellaneous routines
+//
+// History: 7-Jan-90 TedM Created
+// 13-Dec-94 BruceFo Incorporated BobRi's Daytona changes
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <process.h>
+#include <stdlib.h>
+
+#include <util.hxx>
+
+#include "init.hxx"
+#include "nt.hxx"
+#include "profile.hxx"
+#include "stleg.hxx"
+#include "fill.hxx"
+#include "ops.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL
+AllDisksOffLine(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determine whether all hard disks are off line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if all disks off-line, false otherwise.
+
+--*/
+
+{
+ ULONG i;
+
+ FDASSERT(DiskCount);
+
+ for (i=0; i<DiskCount; i++)
+ {
+ if (!IsDiskOffLine(i))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+VOID
+FdShutdownTheSystem(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine attempts to update the caller privilege, then shutdown the
+ Windows NT system. If it fails it prints a warning dialog. If it
+ succeeds then it doesn't return to the caller.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ NTSTATUS status;
+ BOOLEAN previousPriv;
+
+ InfoDialog(MSG_MUST_REBOOT);
+ SetCursor(g_hCurWait);
+ WriteProfile();
+
+ //
+ // Enable shutdown privilege
+ //
+
+ status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
+ TRUE,
+ FALSE,
+ &previousPriv
+ );
+
+#if DBG == 1
+ if (status)
+ {
+ DbgPrint("DISKMAN: status %lx attempting to enable shutdown privilege\n", status);
+ }
+#endif // DBG == 1
+
+ Sleep(3000);
+ if (!ExitWindowsEx(EWX_REBOOT, (DWORD)(-1)))
+ {
+ WarningDialog(MSG_COULDNT_REBOOT);
+ }
+}
+
+
+int
+GetHeightFromPoints(
+ IN int Points
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calculates the height of a font given a point value.
+ The calculation is based on 72 points per inch and the display's
+ pixels/inch device capability.
+
+Arguments:
+
+ Points - number of points
+
+Return Value:
+
+ pixel count (negative and therefore suitable for passing to
+ CreateFont())
+
+--*/
+
+{
+ HDC hdc = GetDC(NULL);
+ int height = MulDiv(-Points, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+
+ ReleaseDC(NULL, hdc);
+
+ return height;
+}
+
+
+VOID
+RetrieveAndFormatMessage(
+ IN DWORD Msg,
+ OUT LPTSTR Buffer,
+ IN DWORD BufferSize,
+ IN va_list* parglist
+ )
+{
+ DWORD x;
+ TCHAR text[MAX_RESOURCE_STRING_LEN];
+
+ // get message from system or app msg file.
+
+ x = FormatMessage( (Msg >= MSG_FIRST_FDISK_MSG)
+ ? FORMAT_MESSAGE_FROM_HMODULE
+ : FORMAT_MESSAGE_FROM_SYSTEM
+ ,
+ NULL,
+ Msg,
+ 0,
+ Buffer,
+ BufferSize,
+ parglist
+ );
+
+ if (!x) // couldn't find message
+ {
+ LoadString(g_hInstance,
+ (Msg >= MSG_FIRST_FDISK_MSG)
+ ? IDS_NOT_IN_APP_MSG_FILE
+ : IDS_NOT_IN_SYS_MSG_FILE,
+ text,
+ ARRAYLEN(text)
+ );
+
+ wsprintf(Buffer, text, Msg);
+ }
+}
+
+
+
+
+DWORD
+CommonDialog(
+ IN DWORD MsgCode,
+ IN LPTSTR Caption,
+ IN DWORD Flags,
+ IN va_list arglist
+ )
+
+/*++
+
+Routine Description:
+
+ Simple dialog routine to get dialogs out of the resource
+ for the program and run them as a message box.
+
+Arguments:
+
+ MsgCode - dialog message code
+ Caption - message box caption
+ Flags - standard message box flags
+ arglist - list to be given when pulling the message text
+
+Return Value:
+
+ The MessageBox() return value
+
+--*/
+
+{
+ // If we're starting up and get an error, make sure the "Starting
+ // Disk Administrator..." dialog goes away
+
+// STARTUP EndStartup();
+
+ TCHAR msgBuf[MESSAGE_BUFFER_SIZE];
+
+ if (NULL != g_InitDlg)
+ {
+ PostMessage(g_InitDlg, WM_STARTUP_END, 0, 0);
+ g_InitDlg = NULL;
+ }
+
+ RetrieveAndFormatMessage(MsgCode, msgBuf, ARRAYLEN(msgBuf), &arglist);
+ return MessageBox(GetActiveWindow(), msgBuf, Caption, Flags);
+}
+
+
+
+
+DWORD
+CommonDialogNoArglist(
+ IN DWORD MsgCode,
+ IN LPTSTR Caption,
+ IN DWORD Flags
+ )
+
+/*++
+
+Routine Description:
+
+ Simple dialog routine to get dialogs out of the resource
+ for the program and run them as a message box.
+
+ There had better not be any FormatMessage "inserts"!
+
+Arguments:
+
+ MsgCode - dialog message code
+ Caption - message box caption
+ Flags - standard message box flags
+
+Return Value:
+
+ The MessageBox() return value
+
+--*/
+
+{
+ // If we're starting up and get an error, make sure the "Starting
+ // Disk Administrator..." dialog goes away
+
+// STARTUP EndStartup();
+
+ TCHAR msgBuf[MESSAGE_BUFFER_SIZE];
+
+ if (NULL != g_InitDlg)
+ {
+ PostMessage(g_InitDlg, WM_STARTUP_END, 0, 0);
+ g_InitDlg = NULL;
+ }
+
+ RetrieveAndFormatMessage(MsgCode, msgBuf, ARRAYLEN(msgBuf), NULL);
+ return MessageBox(GetActiveWindow(), msgBuf, Caption, Flags);
+}
+
+
+
+
+VOID
+ErrorDialog(
+ IN DWORD ErrorCode,
+ ...
+ )
+
+/*++
+
+-Routine Description:
+
+ This routine retreives a message from the app or system message file
+ and displays it in a message box.
+
+Arguments:
+
+ ErrorCode - number of message
+
+ ... - strings for insertion into message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list arglist;
+
+ va_start(arglist, ErrorCode);
+
+ CommonDialog(ErrorCode, NULL, MB_ICONHAND | MB_OK | MB_SYSTEMMODAL, arglist);
+
+ va_end(arglist);
+}
+
+
+
+
+VOID
+WarningDialog(
+ IN DWORD MsgCode,
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ This routine retreives a message from the app or system message file
+ and displays it in a message box.
+
+Arguments:
+
+ MsgCode - number of message
+
+ ... - strings for insertion into message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ TCHAR caption[MAX_RESOURCE_STRING_LEN];
+ va_list arglist;
+
+ va_start(arglist, MsgCode);
+
+ LoadString(g_hInstance, IDS_APPNAME, caption, ARRAYLEN(caption));
+ CommonDialog(MsgCode, caption, MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND, arglist);
+
+ va_end(arglist);
+}
+
+
+
+
+DWORD
+ConfirmationDialog(
+ IN DWORD MsgCode,
+ IN DWORD Flags,
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ Support for a simple confirmation dialog
+
+Arguments:
+
+ MsgCode - resource code for message
+ Flags - dialog flags
+
+Return Value:
+
+ Result from the CommonDialog() performed.
+
+--*/
+
+{
+ TCHAR caption[MAX_RESOURCE_STRING_LEN];
+ DWORD x;
+ va_list arglist;
+
+ va_start(arglist, Flags);
+
+ LoadString(g_hInstance, IDS_CONFIRM, caption, ARRAYLEN(caption));
+ x = CommonDialog(MsgCode, caption, Flags | MB_TASKMODAL, arglist);
+ va_end(arglist);
+ return x;
+}
+
+
+
+VOID
+InfoDialogTitle(
+ IN UINT TitleId,
+ IN DWORD MsgCode,
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ This routine retreives a message from the app or system message file
+ and displays it in a message box.
+
+Arguments:
+
+ MsgCode - number of message
+
+ ... - strings for insertion into message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ TCHAR caption[MAX_RESOURCE_STRING_LEN];
+
+ va_list arglist;
+ va_start(arglist, MsgCode);
+
+ LoadString(g_hInstance, TitleId, caption, ARRAYLEN(caption));
+ CommonDialog(MsgCode, caption, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL, arglist);
+ va_end(arglist);
+}
+
+
+
+
+VOID
+InfoDialog(
+ IN DWORD MsgCode,
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ This routine retreives a message from the app or system message file
+ and displays it in a message box.
+
+Arguments:
+
+ MsgCode - number of message
+
+ ... - strings for insertion into message
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ TCHAR caption[MAX_RESOURCE_STRING_LEN];
+ va_list arglist;
+
+ va_start(arglist, MsgCode);
+
+ LoadString(g_hInstance, IDS_APPNAME, caption, ARRAYLEN(caption));
+ CommonDialog(MsgCode, caption, MB_ICONINFORMATION | MB_OK | MB_TASKMODAL, arglist);
+ va_end(arglist);
+}
+
+
+PREGION_DESCRIPTOR
+LocateRegionForFtObject(
+ IN PFT_OBJECT FtObject
+ )
+
+/*++
+
+Routine Description:
+
+ Given an FtObject, find the associated region descriptor
+
+Arguments:
+
+ FtObject - the ft object to search for.
+
+Return Value:
+
+ NULL - no descriptor found
+ !NULL - a pointer to the region descriptor for the FT object
+
+++*/
+
+{
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ DWORD diskNumber;
+ DWORD regionIndex;
+ PPERSISTENT_REGION_DATA regionData;
+
+ for (diskNumber = 0; diskNumber < DiskCount; diskNumber++)
+ {
+ diskState = DiskArray[diskNumber];
+
+ for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionIndex];
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (NULL != regionData)
+ {
+ if (regionData->FtObject == FtObject)
+ {
+ return regionDescriptor;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClonePersistentData
+//
+// Synopsis: Copies volume label, file system name, drive letter, new
+// region flag, and space information. Doesn't copy
+// FtObject pointer (which is different for every region).
+//
+// Arguments: [RegionFrom] --
+// [RegionTo] --
+//
+// Returns: nothing
+//
+// History: 7-Dec-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+ClonePersistentData(
+ IN PREGION_DESCRIPTOR RegionFrom,
+ OUT PREGION_DESCRIPTOR RegionTo
+ )
+{
+ daDebugOut((DEB_ITRACE,
+ "Cloning data from disk %d TO disk %d ...\n",
+ RegionFrom->Disk,
+ RegionTo->Disk
+ ));
+
+ PWSTR volumeLabel = NULL;
+ PWSTR typeName = NULL;
+
+ PPERSISTENT_REGION_DATA regionDataFrom = PERSISTENT_DATA(RegionFrom);
+ PPERSISTENT_REGION_DATA regionDataTo = PERSISTENT_DATA(RegionTo);
+
+ FDASSERT(NULL != regionDataFrom);
+ FDASSERT(NULL != regionDataTo);
+
+ if (regionDataFrom->VolumeLabel)
+ {
+ volumeLabel = (PWSTR)Malloc((lstrlen(regionDataFrom->VolumeLabel)+1)*sizeof(WCHAR));
+ lstrcpy(volumeLabel, regionDataFrom->VolumeLabel);
+ }
+
+ if (regionDataFrom->TypeName)
+ {
+ typeName = (PWSTR)Malloc((lstrlen(regionDataFrom->TypeName)+1)*sizeof(WCHAR));
+ lstrcpy(typeName, regionDataFrom->TypeName);
+ }
+
+ DmInitPersistentRegionData(
+ regionDataTo,
+ regionDataTo->FtObject, // keep the same FtObject
+ volumeLabel,
+ typeName,
+ regionDataFrom->DriveLetter,
+ regionDataFrom->NewRegion,
+ regionDataFrom->FreeSpaceInBytes,
+ regionDataFrom->TotalSpaceInBytes
+ );
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetPersistentData
+//
+// Synopsis: Loads volume label and file system type name into the
+// persistent data. Frees old data first.
+//
+// Arguments: [RegionDescriptor] -- The region in question
+//
+// Returns: The actual region that data was loaded for.
+//
+// History: 1-Oct-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+PREGION_DESCRIPTOR
+GetPersistentData(
+ IN OUT PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ if (DmSignificantRegion(RegionDescriptor))
+ {
+ WCHAR volumeLabel[100];
+ WCHAR typeName[100];
+ LARGE_INTEGER freeSpaceInBytes;
+ LARGE_INTEGER totalSpaceInBytes;
+
+ //
+ // If the region has a drive letter, use the drive letter
+ // to get the info via the Windows API. Otherwise we'll
+ // have to use the NT API.
+ //
+
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ if (NULL == regionData)
+ {
+ return NULL;
+ }
+
+ if (IsExtraDriveLetter(regionData->DriveLetter))
+ {
+ PWSTR tempLabel;
+ PWSTR tempName;
+
+ //
+ // No drive letter. Use NT API.
+ //
+
+ daDebugOut((DEB_ITRACE,
+ "Getting space info for disk %d, partition %d\n",
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber
+ ));
+
+ // If this is an FT set use the zero member disk for the
+ // call so all members get the right type and label
+
+ if (regionData->FtObject)
+ {
+ PFT_OBJECT searchFtObject;
+
+ // Want to get RegionDescriptor pointing to the zeroth member
+
+ searchFtObject = regionData->FtObject->Set->Member0;
+
+ // Now search regions for this match
+
+ RegionDescriptor = LocateRegionForFtObject(searchFtObject);
+
+ if (NULL == RegionDescriptor)
+ {
+ return NULL;
+ }
+ }
+
+ if (NO_ERROR == GetVolumeLabel(
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber,
+ &tempLabel))
+ {
+ lstrcpy(volumeLabel, tempLabel);
+ Free(tempLabel);
+ }
+ else
+ {
+ volumeLabel[0] = L'\0';
+ }
+
+ if (NO_ERROR == GetTypeName(
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber,
+ &tempName))
+ {
+ lstrcpy(typeName, tempName);
+ Free(tempName);
+ }
+ else
+ {
+ lstrcpy(typeName, wszUnknown);
+ }
+
+ //
+ // get space info
+ //
+
+ if (NO_ERROR != GetSpaceInformation(
+ RegionDescriptor->Disk,
+ RegionDescriptor->PartitionNumber,
+ &freeSpaceInBytes,
+ &totalSpaceInBytes))
+ {
+ freeSpaceInBytes.QuadPart
+ = totalSpaceInBytes.QuadPart
+ = 0
+ ;
+ }
+ }
+ else
+ {
+ //
+ // Use Windows API.
+ //
+
+ WCHAR diskRootPath[4];
+ diskRootPath[0] = regionData->DriveLetter;
+ diskRootPath[1] = L':';
+ diskRootPath[2] = L'\\';
+ diskRootPath[3] = L'\0';
+
+ daDebugOut((DEB_ITRACE,
+ "Getting space info for volume %ws\n",
+ diskRootPath
+ ));
+
+ UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ if (!GetVolumeInformation(
+ diskRootPath,
+ volumeLabel,
+ ARRAYLEN(volumeLabel),
+ NULL,
+ NULL,
+ NULL,
+ typeName,
+ ARRAYLEN(typeName)))
+ {
+ lstrcpy(typeName, wszUnknown);
+ volumeLabel[0] = L'\0';
+ }
+
+ //
+ // Get space info
+ //
+
+ DWORD sectorsPerCluster;
+ DWORD bytesPerSector;
+ DWORD freeClusters;
+ DWORD clusters;
+
+ if (GetDiskFreeSpace(
+ diskRootPath,
+ &sectorsPerCluster,
+ &bytesPerSector,
+ &freeClusters,
+ &clusters))
+ {
+ freeSpaceInBytes.QuadPart = UInt32x32To64(freeClusters, sectorsPerCluster);
+ freeSpaceInBytes.QuadPart *= bytesPerSector;
+
+ totalSpaceInBytes.QuadPart = UInt32x32To64(clusters, sectorsPerCluster);
+ totalSpaceInBytes.QuadPart *= bytesPerSector;
+ }
+ else
+ {
+ freeSpaceInBytes.QuadPart
+ = totalSpaceInBytes.QuadPart
+ = 0
+ ;
+ }
+ SetErrorMode(errorMode);
+ }
+
+ regionData->FreeSpaceInBytes = freeSpaceInBytes;
+ regionData->TotalSpaceInBytes = totalSpaceInBytes;
+
+ if (!lstrcmpi(typeName, L"raw"))
+ {
+ lstrcpy(typeName, wszUnknown);
+ }
+
+ if (NULL != regionData->TypeName)
+ {
+ Free(regionData->TypeName);
+ }
+
+ if (NULL != regionData->VolumeLabel)
+ {
+ Free(regionData->VolumeLabel);
+ }
+
+ regionData->TypeName = (PWSTR)Malloc((lstrlen(typeName) + 1) * sizeof(WCHAR));
+ regionData->VolumeLabel = (PWSTR)Malloc((lstrlen(volumeLabel) + 1) * sizeof(WCHAR));
+
+ lstrcpy(regionData->TypeName, typeName);
+ lstrcpy(regionData->VolumeLabel, volumeLabel);
+ }
+
+ return RegionDescriptor;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RefreshVolumeData
+//
+// Synopsis:
+//
+// Assumes all volume data (persistent data) changed. Reloads it
+// and refreshes the display.
+//
+// Arguments: none
+//
+// Assumes: There is a legal volume selection
+//
+// Returns: nothing
+//
+// History: 11-Jan-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+RefreshVolumeData(
+ VOID
+ )
+{
+ SetCursor(g_hCurWait);
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ regionDescriptor = GetPersistentData(regionDescriptor);
+
+ DWORD i;
+ for (i=1; i<SelectionCount; i++)
+ {
+ //
+ // For an FT set, just clone the volume data for each region
+ //
+
+ ClonePersistentData(regionDescriptor, &SELECTED_REGION(i));
+ }
+
+#ifdef WINDISK_EXTENSIONS
+
+ //
+ // If the format changed, we need a new claim list:
+ //
+
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ ClaimVolume(regionData->DriveLetter);
+
+#endif // WINDISK_EXTENSIONS
+
+ //
+ // Change the menu based on this new format
+ //
+
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+
+ //
+ // refresh the display
+ //
+
+ RefreshBothViews();
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+
+
+
+VOID
+InitVolumeInformation(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Determine the volume information (label, type, size info) for each
+ significant (non-extended, non-free, recognized) partition.
+
+ Assumes that persistent data has already been set up, and drive letters
+ determined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD diskNum;
+ DWORD regionNum;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PFT_OBJECT ftObject;
+ PFT_OBJECT ftObj;
+
+ //
+ // First, set the FT flag to FALSE for all FT regions
+ //
+
+ for (diskNum=0; diskNum<DiskCount; diskNum++)
+ {
+ diskState = DiskArray[diskNum];
+
+ for (regionNum=0; regionNum<diskState->RegionCount; regionNum++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionNum];
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+ if (ftObject)
+ {
+ ftObject->Set->Flag = FALSE;
+ }
+ }
+ }
+
+ //
+ // Now, for all simple regions and all FT regions that don't have their
+ // flag set, get the persistent data. For FT regions, get the data for
+ // one, then clone it for the rest, and set the flag.
+ //
+
+ for (diskNum=0; diskNum<DiskCount; diskNum++)
+ {
+ diskState = DiskArray[diskNum];
+
+ for (regionNum=0; regionNum<diskState->RegionCount; regionNum++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionNum];
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+ if (NULL == ftObject || !ftObject->Set->Flag)
+ {
+ regionDescriptor = GetPersistentData(regionDescriptor);
+
+ if (regionDescriptor == NULL)
+ continue;
+
+ if (ftObject)
+ {
+ ftObject->Set->Flag = TRUE;
+
+ for (ftObj = ftObject->Set->Members;
+ NULL != ftObj;
+ ftObj = ftObj->Next)
+ {
+ PREGION_DESCRIPTOR componentRegion = ftObj->Region;
+ FDASSERT(NULL != componentRegion);
+
+ if ( NULL != componentRegion // off-line
+ && componentRegion != regionDescriptor)
+ {
+ // don't clone to self
+ ClonePersistentData(regionDescriptor, componentRegion);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+VOID
+DetermineRegionInfo(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ OUT PWSTR* TypeName,
+ OUT PWSTR* VolumeLabel,
+ OUT PWCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ For a given region, fetch the persistent data, appropriately modified
+ depending on whether the region is used or free, recognized, etc.
+
+Arguments:
+
+ RegionDescriptor - supplies a pointer to the region whose data is to be fetched.
+
+ TypeName - receives a pointer to the type name. If the region is
+ unrecognized, the type is determined based on the system id of
+ the partition.
+
+ VolumeLabel - receives a pointer to the volume label. If the region is
+ free space or unrecognized, the volume label is "".
+
+ DriveLetter - recieves the drive letter. If the region is free space
+ or unrecognized, the drive letter is ' ' (space).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PWSTR typeName;
+ PWSTR volumeLabel;
+ WCHAR driveLetter;
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ if (DmSignificantRegion(RegionDescriptor))
+ {
+ typeName = regionData->TypeName;
+ volumeLabel = regionData->VolumeLabel;
+ driveLetter = regionData->DriveLetter;
+ if (IsExtraDriveLetter(driveLetter))
+ {
+ driveLetter = L' ';
+ }
+ }
+ else
+ {
+ typeName = GetWideSysIDName(RegionDescriptor->SysID);
+ volumeLabel = L"";
+ driveLetter = L' ';
+ }
+
+ *TypeName = typeName;
+ *VolumeLabel = volumeLabel;
+ *DriveLetter = driveLetter;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsFaultTolerantRegion
+//
+// Synopsis: Determines if a given region is part of a fault tolerant
+// volume, i.e., a mirror set (RAID 1) or a stripe set with
+// parity (RAID 5)
+//
+// Arguments: [RegionDescriptor] -- The region in question
+//
+// Returns: TRUE if the region is part of a fault tolerant volume
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+IsFaultTolerantRegion(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ PFT_OBJECT ftObject = GET_FT_OBJECT(RegionDescriptor);
+
+ if (NULL == ftObject)
+ {
+ return FALSE;
+ }
+
+ FT_TYPE ftType = ftObject->Set->Type;
+
+ return (Mirror == ftType || StripeWithParity == ftType);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MyCheckMenuItem
+//
+// Synopsis: For a range of menu items, uncheck everything but one,
+// which is checked
+//
+// Arguments: [hMenu] -- handle of menu to affect
+// [idFirst] -- menu id of first sequential item
+// [idLast] -- menu id of last sequential item
+// [idCheckItem] -- menu id of the sole item to check
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+MyCheckMenuItem(
+ HMENU hMenu,
+ UINT idFirst,
+ UINT idLast,
+ UINT idCheckItem
+ )
+{
+ CheckMenuRadioItem(hMenu, idFirst, idLast, idCheckItem, MF_BYCOMMAND);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MyEnableMenuItem
+//
+// Synopsis: For a range of menu items, set the menu flags
+//
+// Arguments: [hMenu] -- handle of menu to affect
+// [idFirst] -- menu id of first sequential item
+// [idLast] -- menu id of last sequential item
+// [fItemFlags] -- menu flags to set
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+MyEnableMenuItem(
+ HMENU hMenu,
+ UINT idFirst,
+ UINT idLast,
+ UINT fItemFlags
+ )
+{
+ for (UINT i = idFirst; i <= idLast; i++)
+ {
+ EnableMenuItem(
+ g_hmenuFrame,
+ i,
+ MF_BYCOMMAND | fItemFlags
+ );
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitDrawGasGauge
+//
+// Synopsis: Initializes drawing a gas gauge rectangle
+//
+// Arguments: [hwndGauge] -- handle to the gauge.
+//
+// Returns: nothing
+//
+// History: 12-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+InitDrawGasGauge(
+ IN HWND hwndGauge
+ )
+{
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DrawGasGauge
+//
+// Synopsis: draws a gas gauge rectangle
+//
+// Arguments: [hwndGauge] -- handle to the gauge.
+// [hwndParent] -- handle to the gauge's parent.
+// [hDC] -- hDC to draw with.
+// [PercentDone] -- % finished. if -1, then don't display a
+// percent done. instead, display the caption.
+// [Caption] -- string caption to display in the rectangle,
+// only if PercentDone is -1.
+//
+// Returns: nothing
+//
+// History: 12-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DrawGasGauge(
+ IN HWND hwndGauge,
+ IN HWND hwndParent,
+ IN HDC hDC,
+ IN INT PercentDone,
+ IN PWSTR Caption
+ )
+{
+ // The gas gauge is drawn by drawing a text string stating
+ // what percentage of the job is done into the middle of
+ // the gas gauge rectangle, and by separating that rectangle
+ // into two parts: rectDone (the left part, filled in blue)
+ // and rectLeftToDo(the right part, filled in white).
+ // nDivideRects is the x coordinate that divides these two rects.
+ //
+ // The text in the blue rectangle is drawn white, and vice versa
+ // This is easy to do with ExtTextOut()!
+
+ RECT rcGauge;
+ TCHAR buffer[100];
+ SIZE size;
+ INT xText, yText;
+ INT nDivideRects;
+ RECT rcDone;
+ RECT rcLeftToDo;
+
+ GetClientRect(hwndGauge, &rcGauge);
+
+ INT width = rcGauge.right - rcGauge.left;
+ INT height = rcGauge.bottom - rcGauge.top;
+
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.left);
+ ClientToScreen(hwndGauge, (LPPOINT)&rcGauge.right);
+ ScreenToClient(hwndParent, (LPPOINT)&rcGauge.left);
+ ScreenToClient(hwndParent, (LPPOINT)&rcGauge.right);
+
+ //
+ // We use SS_BLACKFRAME static controls with one pixel borders in
+ // the client area: deflate the rect to avoid drawing over the border
+ //
+ InflateRect(&rcGauge, -1, -1);
+
+ if (-1 == PercentDone)
+ {
+ wsprintf(buffer, TEXT("%s"), Caption);
+
+ nDivideRects = 0;
+ }
+ else
+ {
+ wsprintf(buffer, TEXT("%3d%%"), PercentDone);
+
+ nDivideRects = (width * PercentDone) / 100;
+ }
+
+ UINT bufferLength = lstrlen(buffer);
+ COLORREF blue = RGB(0, 0, 255);
+ COLORREF white = RGB(255, 255, 255);
+
+ GetTextExtentPoint32(hDC, buffer, bufferLength, &size);
+ xText = rcGauge.left + (width - size.cx) / 2;
+ yText = rcGauge.top + (height - size.cy) / 2;
+
+ // Paint in the "done so far" rectangle of the gas
+ // gauge with blue background and white text
+
+ SetRect(
+ &rcDone,
+ rcGauge.left,
+ rcGauge.top,
+ rcGauge.left + nDivideRects,
+ rcGauge.bottom
+ );
+
+ SetTextColor(hDC, white);
+ SetBkColor(hDC, blue);
+
+ ExtTextOut(
+ hDC,
+ xText,
+ yText,
+ ETO_CLIPPED | ETO_OPAQUE,
+ &rcDone,
+ buffer,
+ bufferLength,
+ NULL
+ );
+
+ // Paint in the "still left to do" rectangle of the gas
+ // gauge with white background and blue text
+
+ SetRect(
+ &rcLeftToDo,
+ rcGauge.left + nDivideRects,
+ rcGauge.top,
+ rcGauge.right,
+ rcGauge.bottom
+ );
+
+ SetTextColor(hDC, blue);
+ SetBkColor(hDC, white);
+
+ ExtTextOut(
+ hDC,
+ xText,
+ yText,
+ ETO_CLIPPED | ETO_OPAQUE,
+ &rcLeftToDo,
+ buffer,
+ bufferLength,
+ NULL
+ );
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: KillBold
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+HFONT
+KillBold(
+ IN HWND hdlg,
+ IN PUINT aControls
+ )
+{
+ LOGFONT lFont;
+
+ HFONT hDlgFont = (HFONT)SendMessage(hdlg, WM_GETFONT, 0, 0);
+ if (NULL != hDlgFont)
+ {
+ if (GetObject(hDlgFont, sizeof(LOGFONT), (LPVOID)&lFont))
+ {
+ lFont.lfWeight = FW_NORMAL;
+ hDlgFont = CreateFontIndirect(&lFont);
+ if (NULL != hDlgFont)
+ {
+ for (UINT i = 0; 0 != aControls[i]; i++)
+ {
+ SendDlgItemMessage(
+ hdlg,
+ aControls[i],
+ WM_SETFONT,
+ (WPARAM)hDlgFont,
+ MAKELPARAM(FALSE, 0));
+ }
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE, "Couldn't create font\n"));
+ }
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE, "Couldn't get font object\n"));
+ }
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE, "Couldn't get font handle\n"));
+ }
+
+ return hDlgFont;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: LargeIntegerToUnicodeChar
+//
+// Synopsis: converts a LARGE_INTEGER to a unicode string representation
+//
+// Arguments: Same as RtlLargeIntegerToChar (except takes a UNICODE string)
+//
+// Returns: nothing
+//
+// History: 6-Dec-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+NTSTATUS
+LargeIntegerToUnicodeChar(
+ IN PLARGE_INTEGER Value,
+ IN ULONG Base OPTIONAL,
+ IN LONG OutputLength,
+ OUT PWSTR String
+ )
+{
+ CHAR ansiString[100];
+ NTSTATUS status = RtlLargeIntegerToChar(Value, Base, OutputLength, ansiString);
+ mbstowcs(String, ansiString, OutputLength);
+ return status;
+}
diff --git a/private/utils/windisk/src/network.cxx b/private/utils/windisk/src/network.cxx
new file mode 100644
index 000000000..609a88757
--- /dev/null
+++ b/private/utils/windisk/src/network.cxx
@@ -0,0 +1,184 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: network.cxx
+//
+// Contents: The set of routines that support updating network
+// drive shares when adding and deleting drive letters.
+//
+// History: 12-26-94 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <lm.h>
+
+#include "network.hxx"
+
+// Data area to hold the permissions that are to be assigned to the
+// administrative shares C$, D$, etc. This is obtained during initialization
+// and not changed, just used when a new administrator share needes to
+// be made.
+
+LPBYTE ShareInformationBuffer;
+
+// Only perform network actions if this value is true. This value
+// is set if the initialization of this module completes successfully.
+
+BOOLEAN NetworkEnabled;
+
+
+VOID
+NetworkInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Intialize the permissions constants for any new administrator
+ driver letter shares.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ WCHAR shareName[3];
+ NET_API_STATUS status;
+ PSHARE_INFO_502 info;
+ LPTSTR string;
+
+ shareName[1] = L'$';
+ shareName[2] = L'\0';
+
+ for (shareName[0] = L'C'; shareName[0] <= L'Z'; shareName[0]++)
+ {
+ status = NetShareGetInfo(NULL,
+ shareName,
+ 502,
+ &ShareInformationBuffer);
+ if (status == NERR_Success)
+ {
+ // Update the remarks and password to be NULL.
+
+ info = (PSHARE_INFO_502) ShareInformationBuffer;
+ string = info->shi502_remark;
+ if (string)
+ {
+ *string = L'\0';
+ }
+ string = info->shi502_passwd;
+ if (string)
+ {
+ *string = L'\0';
+ }
+
+ // Network shares are to be updated.
+
+ NetworkEnabled = TRUE;
+ return;
+ }
+ }
+
+ // Can't find any network shares - do not attempt updates
+ // of administrator shares.
+
+ NetworkEnabled = FALSE;
+}
+
+VOID
+NetworkShare(
+ IN LPCTSTR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Given a drive letter, construct the default administrator share
+ for the letter. This is the C$, D$, etc share for the drive.
+
+Arguments:
+
+ DriveLetter - the drive letter to share.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ NET_API_STATUS status;
+ PSHARE_INFO_502 info;
+ LPTSTR string;
+
+ if (NetworkEnabled)
+ {
+ info = (PSHARE_INFO_502) ShareInformationBuffer;
+
+ // Set up the new network name.
+
+ string = info->shi502_netname;
+ *string = *DriveLetter;
+
+ // Set up the path. All that needs be added is the drive letter;
+ // the rest of the path (":\") is already in the structure.
+
+ string = info->shi502_path;
+ *string = *DriveLetter;
+
+ status = NetShareAdd(NULL,
+ 502,
+ ShareInformationBuffer,
+ NULL);
+ }
+}
+
+
+VOID
+NetworkRemoveShare(
+ IN LPCTSTR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Remove the administrator share for the given letter.
+
+Arguments:
+
+ DriveLetter - the drive letter to share.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ NET_API_STATUS status;
+ WCHAR shareName[3];
+
+ if (NetworkEnabled)
+ {
+ shareName[0] = *DriveLetter;
+ shareName[1] = L'$';
+ shareName[2] = L'\0';
+
+ status = NetShareDel(NULL, shareName, 0);
+ }
+}
diff --git a/private/utils/windisk/src/network.hxx b/private/utils/windisk/src/network.hxx
new file mode 100644
index 000000000..bc29c4fe1
--- /dev/null
+++ b/private/utils/windisk/src/network.hxx
@@ -0,0 +1,33 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: network.hxx
+//
+// Contents: The set of routines that support updating network
+// drive shares when adding and deleting drive letters.
+//
+// History: 12-26-94 Bob Rinne Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NETWORK_HXX__
+#define __NETWORK_HXX__
+
+VOID
+NetworkInitialize(
+ VOID
+ );
+
+VOID
+NetworkShare(
+ IN LPCTSTR DriveLetter
+ );
+
+VOID
+NetworkRemoveShare(
+ IN LPCTSTR DriveLetter
+ );
+
+#endif __NETWORK_HXX__
diff --git a/private/utils/windisk/src/nt.cxx b/private/utils/windisk/src/nt.cxx
new file mode 100644
index 000000000..1fad4475f
--- /dev/null
+++ b/private/utils/windisk/src/nt.cxx
@@ -0,0 +1,1187 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: nt.cxx
+//
+// Contents: Functions that wrap fdisk partition engine functions,
+// including functions that manipulate fdisk engine structures
+// (REGIONs, for example).
+//
+// History: 5-Dec-92 TedM Created
+// 22-Jan-94 BobRi Misc cleanup
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <string.h>
+#include <stdio.h>
+
+#include "nt.hxx"
+#include "ntlow.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Pagefile support structures.
+
+typedef struct _PAGEFILE_LOCATION
+{
+ struct _PAGEFILE_LOCATION* Next;
+ WCHAR DriveLetter;
+} PAGEFILE_LOCATION, *PPAGEFILE_LOCATION;
+
+PPAGEFILE_LOCATION PagefileHead = NULL;
+
+// For some reason the file systems don't like being accessed shortly after
+// a format or lock event.
+
+#define SLEEP_TIME (1000*2) // 2 seconds
+
+//
+// These partition ID's are for systems recognized by WINDISK,
+// even though they don't appear in ntdddisk.h.
+//
+#define PARTITION_OS2_BOOT 0xa
+#define PARTITION_EISA 0x12
+
+
+WCHAR SysIdName[100];
+
+PWSTR
+GetWideSysIDName(
+ IN UCHAR SysID
+ )
+{
+ DWORD stringId;
+
+ switch (SysID)
+ {
+ case PARTITION_ENTRY_UNUSED:
+ stringId = IDS_PARTITION_FREE;
+ break;
+
+ case PARTITION_XENIX_1:
+ stringId = IDS_PARTITION_XENIX1;
+ break;
+
+ case PARTITION_XENIX_2:
+ stringId = IDS_PARTITION_XENIX2;
+ break;
+
+ case PARTITION_OS2_BOOT:
+ stringId = IDS_PARTITION_OS2_BOOT;
+ break;
+
+ case PARTITION_EISA:
+ stringId = IDS_PARTITION_EISA;
+ break;
+
+ case PARTITION_UNIX:
+ stringId = IDS_PARTITION_UNIX;
+ break;
+
+ case PARTITION_PREP:
+#ifdef _PPC_
+ stringId = IDS_PARTITION_POWERPC;
+#else
+ // If not on a PPC platform, assume this is Eisa related
+ stringId = IDS_PARTITION_EISA;
+#endif
+ break;
+
+ default:
+ stringId = IDS_UNKNOWN;
+ break;
+ }
+
+ LoadString(
+ g_hInstance,
+ stringId,
+ SysIdName,
+ ARRAYLEN(SysIdName));
+
+ return SysIdName;
+}
+
+
+ULONG
+MyDiskRegistryGet(
+ OUT PDISK_REGISTRY *DiskRegistry
+ )
+
+/*++
+
+Routine Description:
+
+ Allocate memory for the size of the disk registry, obtain
+ the registry contents (if any) and return the pointer to the
+ allocated memory.
+
+Arguments:
+
+ A pointer to a disk registry pointer.
+
+Return Value:
+
+ status indicating success or failure.
+
+--*/
+
+{
+ ULONG length;
+ PDISK_REGISTRY diskRegistry;
+ NTSTATUS status;
+
+ while ( ((status = DiskRegistryGet(NULL, &length)) == STATUS_NO_MEMORY)
+ || (status == STATUS_INSUFFICIENT_RESOURCES))
+ {
+ ConfirmOutOfMemory();
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ return EC(status);
+ }
+
+ diskRegistry = (PDISK_REGISTRY)Malloc(length);
+
+ while ( ((status = DiskRegistryGet(diskRegistry, &length)) == STATUS_NO_MEMORY)
+ || (status == STATUS_INSUFFICIENT_RESOURCES))
+ {
+ ConfirmOutOfMemory();
+ }
+
+ if (NT_SUCCESS(status))
+ {
+ LOG_DISK_REGISTRY("MyDiskRegistryGet", diskRegistry);
+
+ *DiskRegistry = diskRegistry;
+ }
+
+ return EC(status);
+}
+
+
+ULONG
+FormDiskSignature(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Return a ULONG disk signature. This is derived from the current
+ system time.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ A 32-bit signature
+
+--*/
+
+{
+ static ULONG baseSignature = 0;
+
+ LARGE_INTEGER time;
+
+ if (!baseSignature)
+ {
+ NtQuerySystemTime(&time);
+ time.QuadPart = time.QuadPart >> 16;
+ baseSignature = time.LowPart;
+ }
+ return baseSignature++;
+}
+
+
+BOOLEAN
+GetVolumeSizeMB(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PULONG Size
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk and a partition, query the "volume" to get its size.
+ By performing the query on the 1st partition of a potential FT set,
+ the total size of the set will be returned. If the partition isn't
+ an FT set, it will work too.
+
+Arguments:
+
+ Disk - the disk number
+ Partition - the partition number
+ Size - the size of the "volume"
+
+Return Value:
+
+ TRUE - a size was returned.
+ FALSE - something failed in getting the size.
+
+--*/
+
+{
+ BOOLEAN retValue = FALSE;
+ IO_STATUS_BLOCK statusBlock;
+ HANDLE handle;
+ STATUS_CODE sc;
+ PARTITION_INFORMATION partitionInfo;
+ LARGE_INTEGER partitionLength;
+
+ *Size = 0;
+ sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
+ if (sc == OK_STATUS)
+ {
+ sc = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_PARTITION_INFO,
+ NULL,
+ 0,
+ &partitionInfo,
+ sizeof(PARTITION_INFORMATION));
+
+ if (sc == OK_STATUS)
+ {
+ // Convert to MB
+
+ partitionLength.QuadPart = partitionInfo.PartitionLength.QuadPart >> 20;
+ *Size = partitionLength.LowPart;
+ retValue = TRUE;
+ }
+ LowCloseDisk(handle);
+ }
+ return retValue;
+}
+
+
+ULONG
+GetVolumeTypeAndSize(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR *Label,
+ OUT PWSTR *Type,
+ OUT PULONG Size
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk and partition number, determine its size, label and file
+ system type. This routine will allocate the space for label and file
+ system type. It is the responsibility of the caller to free this memory.
+
+Arguments:
+
+ Disk - the disk number
+ Partition - the partition number
+ Label - a pointer to a pointer for a WCHAR string to contain the label
+ Type - a pointer to a pointer for a WCHAR string to contain the file system
+ type.
+ Size - a pointer to a ULONG for the size of the disk in KB.
+
+Return Value:
+
+ OK_STATUS - everything was performed.
+ !OK_STATUS - the error code that was returned in the process of performing
+ this work.
+
+--*/
+
+{
+ IO_STATUS_BLOCK statusBlock;
+ HANDLE handle;
+ UCHAR buffer[256];
+ PWSTR label,
+ name;
+ ULONG length;
+ UINT oldErrorMode;
+ DISK_GEOMETRY diskGeometry;
+ STATUS_CODE sc;
+ BOOLEAN firstTime = TRUE;
+ PFILE_FS_VOLUME_INFORMATION labelInfo = (PFILE_FS_VOLUME_INFORMATION)buffer;
+ PFILE_FS_ATTRIBUTE_INFORMATION info = (PFILE_FS_ATTRIBUTE_INFORMATION)buffer;
+
+ while (1)
+ {
+ oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
+ SetErrorMode(oldErrorMode);
+
+ if (sc == OK_STATUS)
+ {
+ sc = NtQueryVolumeInformationFile(handle,
+ &statusBlock,
+ buffer,
+ sizeof(buffer),
+ FileFsVolumeInformation);
+ if (sc == OK_STATUS)
+ {
+ length = labelInfo->VolumeLabelLength;
+ labelInfo->VolumeLabel[length/sizeof(WCHAR)] = 0;
+ length = (length+1) * sizeof(WCHAR);
+
+ label = (PWSTR)Malloc(length);
+ RtlMoveMemory(label, labelInfo->VolumeLabel, length);
+ }
+ else
+ {
+ label = (PWSTR)Malloc(sizeof(WCHAR));
+ *label = 0;
+ }
+ *Label = label;
+
+ if (sc == OK_STATUS)
+ {
+ sc = NtQueryVolumeInformationFile(handle,
+ &statusBlock,
+ buffer,
+ sizeof(buffer),
+ FileFsAttributeInformation);
+ if (sc == OK_STATUS)
+ {
+ length = info->FileSystemNameLength;
+ info->FileSystemName[length/sizeof(WCHAR)] = 0;
+ length = (length+1)*sizeof(WCHAR);
+ name = (PWSTR)Malloc(length);
+ RtlMoveMemory(name, info->FileSystemName, length);
+ }
+ else
+ {
+ name = (PWSTR)Malloc(sizeof(WCHAR));
+ *name = 0;
+ }
+ *Type = name;
+ }
+
+ if (sc == OK_STATUS)
+ {
+ sc = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ (PVOID)&diskGeometry,
+ sizeof(diskGeometry));
+ if (NT_SUCCESS(sc))
+ {
+ LARGE_INTEGER sizeInBytes;
+ ULONG cylinderBytes;
+
+ cylinderBytes = diskGeometry.TracksPerCylinder *
+ diskGeometry.SectorsPerTrack *
+ diskGeometry.BytesPerSector;
+
+ sizeInBytes.QuadPart = diskGeometry.Cylinders.QuadPart * cylinderBytes;
+
+ // Now convert everything to KB
+
+ sizeInBytes.QuadPart = sizeInBytes.QuadPart >> 10;
+ *Size = (ULONG) sizeInBytes.LowPart;
+ }
+ }
+ DmClose(handle);
+ sc = OK_STATUS;
+ break;
+ }
+ else
+ {
+ if (firstTime)
+ {
+ firstTime = FALSE;
+ }
+ else
+ {
+ *Label = (PWSTR)Malloc(sizeof(WCHAR));
+ if (*Label) {
+
+ *((PWSTR)*Label) = 0;
+
+ }
+ *Type = (PWSTR)Malloc(sizeof(WCHAR));
+ if (*Type) {
+
+ *((PWSTR)*Type) = 0;
+
+ }
+ *Size = 0;
+ break;
+ }
+
+ Sleep(SLEEP_TIME);
+ }
+ }
+
+ return EC(sc);
+}
+
+
+
+ULONG
+GetVolumeLabel(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR *Label
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk number and a partition number return the volume label (if
+ any).
+
+Arguments:
+
+ Disk - the disk number
+ Partition - the partition number
+ Label - a pointer to a pointer for a WCHAR string to contain the label
+
+Return Value:
+
+ OK_STATUS - everything was performed.
+ !OK_STATUS - the error code that was returned in the process of performing
+ this work.
+--*/
+
+{
+ IO_STATUS_BLOCK status_block;
+ HANDLE handle;
+ STATUS_CODE sc;
+ BOOLEAN firstTime = TRUE;
+ unsigned char buffer[256];
+ PFILE_FS_VOLUME_INFORMATION LabelInfo = (PFILE_FS_VOLUME_INFORMATION)buffer;
+ PWSTR label;
+ ULONG length;
+
+ while (1)
+ {
+ sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
+ if (sc == OK_STATUS)
+ {
+ sc = NtQueryVolumeInformationFile(handle,
+ &status_block,
+ buffer,
+ sizeof(buffer),
+ FileFsVolumeInformation);
+ DmClose(handle);
+
+ if (sc == OK_STATUS)
+ {
+ length = LabelInfo->VolumeLabelLength;
+
+ LabelInfo->VolumeLabel[length/sizeof(WCHAR)] = L'\0';
+
+ length = (length+1) * sizeof(WCHAR);
+
+ label = (PWSTR)Malloc(length);
+ RtlMoveMemory(label, LabelInfo->VolumeLabel, length);
+ }
+ else
+ {
+ label = (PWSTR)Malloc(sizeof(WCHAR));
+ sc = OK_STATUS;
+ *label = L'\0';
+ }
+
+ *Label = label;
+ break;
+ }
+ else
+ {
+ if (firstTime)
+ {
+ firstTime = FALSE;
+ }
+ else
+ {
+ *Label = NULL;
+ break;
+ }
+
+ Sleep(SLEEP_TIME);
+ }
+ }
+ return EC(sc);
+}
+
+
+ULONG
+GetTypeName(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR* Name
+ )
+
+/*++
+
+Routine Description:
+
+ Given a disk number and partition number return the file system type
+ string.
+
+Arguments:
+
+ Disk - the disk number
+ Partition - the partition number
+ Name - a pointer to a pointer for a WCHAR string to contain the file system
+ type.
+
+Return Value:
+
+ OK_STATUS - everything was performed.
+ !OK_STATUS - the error code that was returned in the process of performing
+ this work.
+--*/
+
+{
+ PWSTR name;
+ STATUS_CODE sc;
+ HANDLE handle;
+ UCHAR buffer[256];
+ BOOLEAN firstTime = TRUE;
+ PFILE_FS_ATTRIBUTE_INFORMATION info = (PFILE_FS_ATTRIBUTE_INFORMATION)buffer;
+ IO_STATUS_BLOCK status_block;
+ ULONG length;
+
+ // For some reason, the file systems believe they are locked or need
+ // to be verified after formats and the like. Therefore this is attempted
+ // twice before it actually gives up.
+
+ while (1)
+ {
+ sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
+ if (sc == OK_STATUS)
+ {
+ sc = NtQueryVolumeInformationFile(handle,
+ &status_block,
+ buffer,
+ sizeof(buffer),
+ FileFsAttributeInformation);
+ DmClose(handle);
+
+ if (sc == OK_STATUS)
+ {
+ length = info->FileSystemNameLength;
+ info->FileSystemName[length/sizeof(WCHAR)] = L'\0';
+ length = (length+1)*sizeof(WCHAR);
+ name = (PWSTR)Malloc(length);
+ RtlMoveMemory(name, info->FileSystemName, length);
+ }
+ else
+ {
+ name = (PWSTR)Malloc(sizeof(WCHAR));
+ *name = L'\0';
+ sc = OK_STATUS;
+ }
+ *Name = name;
+ break;
+ }
+ else
+ {
+ if (firstTime)
+ {
+ firstTime = FALSE;
+ }
+ else
+ {
+ break;
+ }
+
+ Sleep(SLEEP_TIME);
+ }
+ }
+
+ return EC(sc);
+}
+
+
+ULONG
+GetSpaceInformation(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PLARGE_INTEGER FreeSpaceInBytes,
+ OUT PLARGE_INTEGER TotalSpaceInBytes
+ )
+{
+ STATUS_CODE sc;
+ HANDLE handle;
+ FILE_FS_SIZE_INFORMATION info;
+ IO_STATUS_BLOCK status_block;
+
+ TotalSpaceInBytes->QuadPart = FreeSpaceInBytes->QuadPart = 0;
+
+ sc = LowOpenPartition(GetDiskName(Disk), Partition, &handle);
+ if (sc == OK_STATUS)
+ {
+ sc = NtQueryVolumeInformationFile(handle,
+ &status_block,
+ &info,
+ sizeof(info),
+ FileFsSizeInformation);
+ NtClose(handle);
+
+ if (sc == OK_STATUS)
+ {
+ FreeSpaceInBytes->QuadPart =
+ info.AvailableAllocationUnits.QuadPart *
+ UInt32x32To64(info.SectorsPerAllocationUnit, info.BytesPerSector)
+ ;
+
+ TotalSpaceInBytes->QuadPart =
+ info.TotalAllocationUnits.QuadPart *
+ UInt32x32To64(info.SectorsPerAllocationUnit, info.BytesPerSector)
+ ;
+ }
+ }
+
+ return EC(sc);
+}
+
+
+
+BOOLEAN
+IsRemovable(
+ IN ULONG DiskNumber
+ )
+/*++
+
+Routine Description:
+
+ This function determines whether the specified physical
+ disk is removable.
+
+Arguments:
+
+ DiskNumber -- The Physical Disk Number of the disk in question.
+
+Return Value:
+
+ TRUE if the disk is removable.
+
+--*/
+{
+ STATUS_CODE sc;
+ NTSTATUS status;
+ HANDLE handle;
+ DISK_GEOMETRY diskGeometry;
+ IO_STATUS_BLOCK statusBlock;
+ BOOLEAN result = FALSE;
+ PCHAR name;
+
+ name = GetDiskName(DiskNumber);
+ sc = LowOpenDisk(name, &handle);
+
+ if (sc == OK_STATUS)
+ {
+ status = NtDeviceIoControlFile( handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ (PVOID)&diskGeometry,
+ sizeof(diskGeometry));
+ LowCloseDisk(handle);
+
+ if (NT_SUCCESS(status))
+ {
+ if (diskGeometry.MediaType == RemovableMedia)
+ {
+ char ntDeviceName[100];
+
+ // Do a dismount/force mount sequence to make sure
+ // the media hasn't changed since last mount.
+ // Dismount partition 1 by lock/unlock/close.
+
+ sprintf(ntDeviceName, "%s\\Partition1", name);
+ status= LowOpenNtName(ntDeviceName, &handle);
+ if (NT_SUCCESS(status))
+ {
+ status = LowLockDrive(handle);
+ if (NT_SUCCESS(status)) {
+ LowUnlockDrive(handle);
+ LowCloseDisk(handle);
+
+ // Now force the mount by opening the device with a '\'
+ // This is done on partition 1 of the device.
+
+ sprintf(ntDeviceName, "%s\\Partition1\\", name);
+ status= LowOpenNtName(ntDeviceName, &handle);
+ if (NT_SUCCESS(status))
+ {
+ LowCloseDisk(handle);
+ }
+ }
+ }
+ result = TRUE;
+ }
+ } else if (status == STATUS_NO_MEDIA_IN_DEVICE) {
+
+ //
+ // This is a pretty good indication that this is a removable.
+ //
+
+ result = TRUE;
+
+ }
+ }
+
+ return result;
+}
+
+
+
+
+ULONG
+GetDriveLetterLinkTarget(
+ IN PWSTR SourceNameStr,
+ OUT PWSTR *LinkTarget
+ )
+{
+ static WCHAR targetNameBuffer[50];
+
+ NTSTATUS status;
+ UNICODE_STRING sourceName;
+ UNICODE_STRING targetName;
+ OBJECT_ATTRIBUTES oa;
+ HANDLE handle;
+
+
+ RtlInitUnicodeString(&sourceName, SourceNameStr);
+
+ InitializeObjectAttributes(&oa, &sourceName, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = NtOpenSymbolicLinkObject(&handle, READ_CONTROL | SYMBOLIC_LINK_QUERY, &oa);
+
+ if (NT_SUCCESS(status))
+ {
+ RtlZeroMemory(targetNameBuffer, sizeof(targetNameBuffer));
+ targetName.Buffer = targetNameBuffer;
+ targetName.MaximumLength = sizeof(targetNameBuffer);
+
+ status = NtQuerySymbolicLinkObject(handle, &targetName, NULL);
+ NtClose(handle);
+ }
+
+ if (NT_SUCCESS(status))
+ {
+ *LinkTarget = targetName.Buffer;
+ }
+ else
+ {
+ *LinkTarget = NULL;
+ }
+
+ return EC(status);
+}
+
+
+#include "bootmbr.h"
+
+#if X86BOOTCODE_SIZE < MBOOT_CODE_SIZE
+#error Something is wrong with the boot code (it's too small)!
+#endif
+
+ULONG
+MasterBootCode(
+ IN ULONG Disk,
+ IN ULONG Signature,
+ IN BOOLEAN SetBootCode,
+ IN BOOLEAN SetSignature
+ )
+
+/*++
+
+Routine Description:
+
+ If the zero sector of the disk does not have a valid MBR
+ signature (i.e. AA55), update it such that it has a valid
+ MBR and fill in the disk signature and bootcode in the
+ process.
+
+Arguments:
+
+ Disk - the disk ordinal to be affected
+ SetSignature - if TRUE update the disk signature
+ Signature - the disk signature for the update
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ HANDLE handle;
+ STATUS_CODE status;
+ PCHAR diskName = GetDiskName(Disk);
+ PUCHAR unalignedSectorBuffer;
+ PUCHAR sectorBuffer;
+ ULONG bps;
+ ULONG dummy;
+ ULONG i;
+ BOOLEAN writeIt;
+
+ #ifndef max
+ #define max(a, b) (((a) > (b)) ? (a) : (b))
+ #endif
+
+ if (SetBootCode)
+ {
+ writeIt = FALSE;
+
+ // allocate sector buffer
+
+ status = LowGetDriveGeometry(diskName, &dummy, &bps, &dummy, &dummy);
+ if (status != OK_STATUS)
+ {
+ return EC(status);
+ }
+ if (bps < 512)
+ {
+ bps = 512;
+ }
+ unalignedSectorBuffer = (PUCHAR)Malloc(2*bps);
+ sectorBuffer = (PUCHAR)(((ULONG)unalignedSectorBuffer+bps) & ~(bps-1));
+
+ // open entire disk (partition 0)
+
+ if ((status = LowOpenDisk(diskName, &handle)) != OK_STATUS)
+ {
+ return EC(status);
+ }
+
+ // read (at least) first 512 bytes
+
+ status = LowReadSectors(handle, bps, 0, 1, sectorBuffer);
+ if (status == OK_STATUS)
+ {
+ if ( (sectorBuffer[MBOOT_SIG_OFFSET+0] != MBOOT_SIG1)
+ || (sectorBuffer[MBOOT_SIG_OFFSET+1] != MBOOT_SIG2))
+ {
+ // xfer boot code into sectorBuffer
+
+ for (i=0; i<MBOOT_CODE_SIZE; i++)
+ {
+ sectorBuffer[i] = x86BootCode[i];
+ }
+
+ // wipe partition table
+
+ for (i=MBOOT_CODE_SIZE; i<MBOOT_SIG_OFFSET; i++)
+ {
+ sectorBuffer[i] = 0;
+ }
+
+ // set the signature
+
+ sectorBuffer[MBOOT_SIG_OFFSET+0] = MBOOT_SIG1;
+ sectorBuffer[MBOOT_SIG_OFFSET+1] = MBOOT_SIG2;
+
+ writeIt = TRUE;
+ }
+
+ if (writeIt)
+ {
+ status = LowWriteSectors(handle, bps, 0, 1, sectorBuffer);
+ }
+ }
+
+ LowCloseDisk(handle);
+
+ Free(unalignedSectorBuffer);
+ }
+
+ if (SetSignature)
+ {
+ PDRIVE_LAYOUT_INFORMATION layout;
+
+ // Use the IOCTL to set the signature. This code really does
+ // not know where the MBR exists. (ezDrive extensions).
+
+ status = LowGetDiskLayout(diskName, &layout);
+
+ if (status == OK_STATUS)
+ {
+ layout->Signature = Signature;
+ LowSetDiskLayout(diskName, layout);
+ }
+ }
+
+ return EC(status);
+}
+
+
+ULONG
+UpdateMasterBootCode(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ This routine updates the zero sector of the disk to insure that boot
+ code is present.
+
+Arguments:
+
+ Disk - the disk number onto which to put the boot code.
+
+Return Value:
+
+ status
+
+--*/
+
+{
+ HANDLE handle;
+ STATUS_CODE status;
+ PUCHAR unalignedSectorBuffer,
+ sectorBuffer;
+ ULONG bps,
+ dummy,
+ i;
+ PCHAR diskName = GetDiskName(Disk);
+
+#ifndef max
+#define max(a,b) ((a > b) ? a : b)
+#endif
+
+ // allocate sector buffer
+
+ status = LowGetDriveGeometry(diskName, &dummy, &bps, &dummy, &dummy);
+ if (status != OK_STATUS)
+ {
+ return EC(status);
+ }
+ if (bps < 512)
+ {
+ bps = 512;
+ }
+ unalignedSectorBuffer = (PUCHAR)Malloc(2*bps);
+ sectorBuffer = (PUCHAR)(((ULONG)unalignedSectorBuffer+bps) & ~(bps-1));
+
+ // open entire disk (partition 0)
+
+ if ((status = LowOpenDisk(diskName, &handle)) != OK_STATUS)
+ {
+ return EC(status);
+ }
+
+ // read (at least) first 512 bytes
+
+ status = LowReadSectors(handle, bps, 0, 1, sectorBuffer);
+ if (status == OK_STATUS)
+ {
+ // xfer boot code into sectorBuffer. This avoids changing the
+ // disk signature and the partition table information.
+
+ for (i=0; i<MBOOT_CODE_SIZE; i++)
+ {
+ sectorBuffer[i] = x86BootCode[i];
+ }
+
+ status = LowWriteSectors(handle, bps, 0, 1, sectorBuffer);
+ }
+
+ LowCloseDisk(handle);
+
+ // free the sector buffer
+
+ Free(unalignedSectorBuffer);
+ return EC(status);
+}
+
+
+
+VOID
+MakePartitionActive(
+ IN PREGION_DESCRIPTOR DiskRegionArray,
+ IN ULONG RegionCount,
+ IN ULONG RegionIndex
+ )
+
+/*++
+
+Routine Description:
+
+ Update the information in the internal structures to indicate
+ that the specified partition is active.
+
+Arguments:
+
+ DiskRegionArray
+ RegionCount
+ RegionIndex
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ unsigned i;
+
+ for (i=0; i<RegionCount; i++)
+ {
+ if (DiskRegionArray[i].RegionType == REGION_PRIMARY)
+ {
+ DiskRegionArray[i].Active = FALSE;
+ SetPartitionActiveFlag(&DiskRegionArray[i], FALSE);
+ }
+ }
+ DiskRegionArray[RegionIndex].Active = (BOOLEAN)0x80;
+ SetPartitionActiveFlag(&DiskRegionArray[RegionIndex], 0x80);
+}
+
+
+VOID
+LoadExistingPageFileInfo(
+ IN VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine finds all pagefiles in the system and updates the internal
+ structures.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ None
+
+--*/
+
+{
+ NTSTATUS status;
+ SYSTEM_INFO sysInfo;
+ UCHAR genericBuffer[0x10000];
+ PSYSTEM_PAGEFILE_INFORMATION pageFileInfo;
+ ANSI_STRING ansiPageFileName;
+ PPAGEFILE_LOCATION pageFileListEntry;
+ PCHAR p;
+
+ GetSystemInfo(&sysInfo);
+
+ status = NtQuerySystemInformation(SystemPageFileInformation,
+ genericBuffer,
+ sizeof(genericBuffer),
+ NULL);
+ if (!NT_SUCCESS(status))
+ {
+ // It's possible that this call will fail if the
+ // the system is running without ANY paging files.
+
+ return;
+ }
+
+ pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION) genericBuffer;
+
+ for (;;)
+ {
+ RtlUnicodeStringToAnsiString(&ansiPageFileName,
+ &pageFileInfo->PageFileName,
+ TRUE);
+
+ // Since the format of the pagefile name generally
+ // looks something like "\DosDevices\h:\pagefile.sys",
+ // just use the first character before the colon
+ // and assume that's the drive letter.
+
+ p = strchr(_strlwr(ansiPageFileName.Buffer), ':');
+
+ if ((p-- != NULL) && (*p >= 'a') && (*p <= 'z'))
+ {
+ pageFileListEntry = (PPAGEFILE_LOCATION)Malloc(sizeof(PAGEFILE_LOCATION));
+ if (NULL != pageFileListEntry)
+ {
+ if (NULL != PagefileHead)
+ {
+ pageFileListEntry->Next = PagefileHead;
+ }
+ else
+ {
+ PagefileHead = pageFileListEntry;
+ pageFileListEntry->Next = NULL;
+ }
+ pageFileListEntry->DriveLetter = (WCHAR)(*p);
+ }
+ }
+
+ RtlFreeAnsiString(&ansiPageFileName);
+
+ if (pageFileInfo->NextEntryOffset == 0)
+ {
+ break;
+ }
+
+ pageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((PCHAR) pageFileInfo
+ + pageFileInfo->NextEntryOffset);
+ }
+}
+
+BOOLEAN
+IsPagefileOnDrive(
+ WCHAR DriveLetter
+ )
+
+/*++
+
+Routine Description:
+
+ Walk the page file list and determine if the drive letter given has
+ a paging file. NOTE: The assumption is that drive letters that
+ contain paging files can never get changed during the execution of
+ Disk Administrator. Therefore this list is never updated, but
+ can be used during the execution of Disk Administrator.
+
+Arguments:
+
+ DriveLetter - the drive in question.
+
+Return Value:
+
+ TRUE if this drive contains a page file.
+
+--*/
+
+{
+ PPAGEFILE_LOCATION pageFileListEntry = PagefileHead;
+
+ while (NULL != pageFileListEntry)
+ {
+ if (pageFileListEntry->DriveLetter == DriveLetter)
+ {
+ return TRUE;
+ }
+ pageFileListEntry = pageFileListEntry->Next;
+ }
+ return FALSE;
+}
diff --git a/private/utils/windisk/src/nt.hxx b/private/utils/windisk/src/nt.hxx
new file mode 100644
index 000000000..8ff8c2c84
--- /dev/null
+++ b/private/utils/windisk/src/nt.hxx
@@ -0,0 +1,115 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: nt.hxx
+//
+// Contents: Delcarations for functions that wrap fdisk partition engine
+// functions
+//
+// History: 5-Dec-92 TedM Created
+// 22-Jan-94 BobRi Misc cleanup
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NT_HXX__
+#define __NT_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+ULONG
+GetVolumeTypeAndSize(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR *Label,
+ OUT PWSTR *Type,
+ OUT PULONG Size
+ );
+
+PWSTR
+GetWideSysIDName(
+ IN UCHAR SysID
+ );
+
+ULONG
+MyDiskRegistryGet(
+ OUT PDISK_REGISTRY *DiskRegistry
+ );
+
+ULONG
+MasterBootCode(
+ IN ULONG Disk,
+ IN ULONG Signature,
+ IN BOOLEAN SetBootCode,
+ IN BOOLEAN SetSignature
+ );
+
+ULONG
+FormDiskSignature(
+ VOID
+ );
+
+BOOLEAN
+GetVolumeSizeMB(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PULONG Size
+ );
+
+ULONG
+GetVolumeLabel(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR *Label
+ );
+
+ULONG
+GetTypeName(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PWSTR *Name
+ );
+
+ULONG
+GetSpaceInformation(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ OUT PLARGE_INTEGER FreeSpaceInBytes,
+ OUT PLARGE_INTEGER TotalSpaceInBytes
+ );
+
+BOOLEAN
+IsRemovable(
+ IN ULONG DiskNumber
+ );
+
+ULONG
+GetDriveLetterLinkTarget(
+ IN PWSTR SourceNameStr,
+ OUT PWSTR *LinkTarget
+ );
+
+ULONG
+UpdateMasterBootCode(
+ IN ULONG Disk
+ );
+
+VOID
+MakePartitionActive(
+ IN PREGION_DESCRIPTOR DiskRegionArray,
+ IN ULONG RegionCount,
+ IN ULONG RegionIndex
+ );
+
+BOOLEAN
+IsPagefileOnDrive(
+ WCHAR DriveLetter
+ );
+
+VOID
+LoadExistingPageFileInfo(
+ IN VOID
+ );
+
+#endif // __NT_HXX__
diff --git a/private/utils/windisk/src/ntlow.cxx b/private/utils/windisk/src/ntlow.cxx
new file mode 100644
index 000000000..48e326052
--- /dev/null
+++ b/private/utils/windisk/src/ntlow.cxx
@@ -0,0 +1,1134 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ntlow.cxx
+//
+// Contents: Low-level I/O routines, implemented to run on NT.
+//
+// History: 8-Nov-91 TedM Created
+// 2-Feb-94 BobRi Dynamic partitioning changes
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdio.h>
+#include <string.h>
+
+#include "engine.hxx"
+#include "ntlow.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+STATUS_CODE
+LowQueryFdiskPathList(
+ OUT PCHAR** PathList,
+ OUT PULONG ListLength
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines how many drives are present in the
+ system and returns a list of Ascii strings for the names of
+ each of the drives found.
+
+ When a drive is located, a check is made to insure that the
+ associated DosName for the physical drive is also present in
+ the system.
+
+Arguments:
+
+ PathList - pointer to a pointer for the list
+ ListLength - the number of entries returned in the list
+
+Return Value:
+
+ Error status if there is a problem.
+
+--*/
+
+{
+ HANDLE dummyHandle;
+ STATUS_CODE status;
+ ULONG count = 0;
+ ULONG i;
+ char buffer[100];
+ PCHAR* pathArray;
+ UINT errorMode;
+
+ errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ while (1)
+ {
+ sprintf(buffer,"\\Device\\Harddisk%u",count);
+
+ status = LowOpenDisk(buffer, &dummyHandle);
+
+ //
+ // Only STATUS_OBJECT_PATH_NOT_FOUND can terminate the count.
+ //
+
+ if (NT_SUCCESS(status))
+ {
+ char dosNameBuffer[80];
+
+ LowCloseDisk(dummyHandle);
+
+ // Insure that the physicaldrive name is present
+
+ sprintf(dosNameBuffer, "\\dosdevices\\PhysicalDrive%u", count);
+ status = LowOpenNtName(dosNameBuffer, &dummyHandle);
+ if (NT_SUCCESS(status))
+ {
+ LowCloseDisk(dummyHandle);
+ }
+ else
+ {
+ // Not there, create it.
+
+ char devicePath[50];
+ wsprintfA(devicePath, "\\Device\\Harddisk%u\\Partition0", count);
+ DefineDosDeviceA(DDD_RAW_TARGET_PATH, dosNameBuffer, devicePath);
+ }
+ }
+ else if (status == STATUS_OBJECT_PATH_NOT_FOUND)
+ {
+ break;
+ }
+ else if (status == STATUS_ACCESS_DENIED)
+ {
+ SetErrorMode(errorMode);
+ return status;
+ }
+
+ count++;
+ }
+
+ pathArray = (PCHAR*)Malloc(count * sizeof(PCHAR));
+
+ for (i=0; i<count; i++)
+ {
+ sprintf(buffer,"\\Device\\Harddisk%u",i);
+
+ pathArray[i] = (PCHAR)Malloc(lstrlenA(buffer)+1);
+
+ strcpy(pathArray[i], buffer);
+ }
+
+ *PathList = pathArray;
+ *ListLength = count;
+
+ SetErrorMode(errorMode);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+LowFreeFdiskPathList(
+ IN OUT PCHAR* PathList,
+ IN ULONG ListLength
+ )
+
+/*++
+
+Routine Description:
+
+ Walk the provided list up to its length and free the memory
+ allocated. Upon completion, free the memory for the list
+ itself.
+
+Arguments:
+
+ PathList - pointer to base of path list
+ ListLength - number of entries in the list
+
+Return Value:
+
+ Always OK_STATUS
+
+--*/
+
+{
+ ULONG i;
+
+ for (i=0; i<ListLength; i++)
+ {
+ FreeMemory(PathList[i]);
+ }
+ FreeMemory(PathList);
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+LowOpenNtName(
+ IN PCHAR Name,
+ IN HANDLE_PT Handle
+ )
+
+/*++
+
+Routine Description:
+
+ This is an internal "Low" routine to handle open requests.
+
+Arguments:
+
+ Name - pointer to the NT name for the open.
+ Handle - pointer for the handle returned.
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES oa;
+ NTSTATUS status;
+ IO_STATUS_BLOCK statusBlock;
+ ANSI_STRING ansiName;
+ UNICODE_STRING unicodeName;
+
+ RtlInitAnsiString(&ansiName, Name);
+ status = RtlAnsiStringToUnicodeString(&unicodeName, &ansiName, TRUE);
+
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ memset(&oa, 0, sizeof(OBJECT_ATTRIBUTES));
+ oa.Length = sizeof(OBJECT_ATTRIBUTES);
+ oa.ObjectName = &unicodeName;
+ oa.Attributes = OBJ_CASE_INSENSITIVE;
+
+ status = DmOpenFile(Handle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &oa,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+
+ if (!NT_SUCCESS(status))
+ {
+ FDLOG((1,"LowOpen: 1st open failed with 0x%x\n", status));
+
+ // try a 2nd time to get around an FS glitch or a test
+ // bug where this doesn't work on an attempt to delete a
+ // partition
+
+ Sleep(500);
+ status = DmOpenFile(Handle,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ &oa,
+ &statusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ FDLOG((1,"LowOpen: 2nd open 0x%x\n", status));
+ }
+
+ RtlFreeUnicodeString(&unicodeName);
+ return status;
+}
+
+
+STATUS_CODE
+LowOpenDriveLetter(
+ IN WCHAR DriveLetter,
+ IN HANDLE_PT Handle
+ )
+
+/*++
+
+Routine Description:
+
+ Given a drive letter, open it and return a handle.
+
+Arguments:
+
+ DriveLetter - the letter to open
+ Handle - a pointer to a handle
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ char ntDeviceName[100];
+
+ sprintf(ntDeviceName, "\\DosDevices\\%c:", (CHAR)DriveLetter);
+ return LowOpenNtName(ntDeviceName, Handle);
+}
+
+
+STATUS_CODE
+LowOpenPartition(
+ IN PCHAR DevicePath,
+ IN ULONG Partition,
+ OUT HANDLE_PT Handle
+ )
+
+/*++
+
+Routine Description:
+
+ Construct the NT device name for the Partition value given
+ and perform the NT APIs to open the device.
+
+Arguments:
+
+ DevicePath - the string to the device without the partition
+ portion of the name. This is constructed using
+ the Partition value passed
+ Partition - the partion desired
+ Handle - pointer to a handle pointer for the result
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ char ntDeviceName[100];
+
+ sprintf(ntDeviceName, "%s\\partition%u", DevicePath, Partition);
+ return LowOpenNtName(ntDeviceName, Handle);
+}
+
+
+STATUS_CODE
+LowOpenDisk(
+ IN PCHAR DevicePath,
+ OUT HANDLE_PT DiskId
+ )
+
+/*++
+
+Routine Description:
+
+ Perform the NT actions to open a device.
+
+Arguments:
+
+ DevicePath - Ascii device name
+ DiskId - pointer to a handle pointer for the returned
+ handle value
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ return LowOpenPartition(DevicePath, 0, DiskId);
+}
+
+
+
+STATUS_CODE
+LowCloseDisk(
+ IN HANDLE_T DiskId
+ )
+
+/*++
+
+Routine Description:
+
+ Close a disk handle.
+
+Arguments:
+
+ DiskId - the actual NT handle
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ return DmClose(DiskId);
+}
+
+
+STATUS_CODE
+LowLockDrive(
+ IN HANDLE_T DiskId
+ )
+
+/*++
+
+Routine Description:
+
+ Perform the NT API to cause a volume to be locked.
+ This is a File System device control.
+
+Arguments:
+
+ DiskId - the actual NT handle to the drive
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK statusBlock;
+
+ status = NtFsControlFile(DiskId,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ FSCTL_LOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ if (!NT_SUCCESS(status))
+ {
+ FDLOG((1, "LowLock: failed with 0x%x\n", status));
+ }
+
+ return status;
+}
+
+
+STATUS_CODE
+LowUnlockDrive(
+ IN HANDLE_T DiskId
+ )
+
+/*++
+
+Routine Description:
+
+ Perform the NT API to cause a volume to be unlocked.
+ This is a File System device control.
+
+Arguments:
+
+ DiskId - the actual NT handle to the drive
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK statusBlock;
+
+ status = NtFsControlFile(DiskId,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ FSCTL_DISMOUNT_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0);
+
+ status = NtFsControlFile(DiskId,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ FSCTL_UNLOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ return status;
+}
+
+
+
+STATUS_CODE
+LowGetDriveGeometry(
+ IN PCHAR Path,
+ OUT PULONG TotalSectorCount,
+ OUT PULONG SectorSize,
+ OUT PULONG SectorsPerTrack,
+ OUT PULONG Heads
+ )
+
+/*++
+
+Routine Description:
+
+ Routine collects information concerning the geometry
+ of a specific drive.
+
+Arguments:
+
+ Path - Ascii path name to get to disk object
+ this is not a full path, but rather
+ a path without the Partition indicator
+ \device\harddiskX
+ TotalSectorCount- pointer to ULONG for result
+ SectorSize - pointer to ULONG for result
+ SectorsPerTrack - pointer to ULONG for result
+ Heads - pointer to ULONG for result
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ IO_STATUS_BLOCK statusBlock;
+ DISK_GEOMETRY diskGeometry;
+ STATUS_CODE status;
+ HANDLE handle;
+
+ if ((status = LowOpenDisk(Path, &handle)) != OK_STATUS)
+ {
+ return status;
+ }
+
+ status = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &diskGeometry,
+ sizeof(DISK_GEOMETRY));
+ if (!NT_SUCCESS(status))
+ {
+ return (STATUS_CODE)status;
+ }
+ LowCloseDisk(handle);
+
+ *SectorSize = diskGeometry.BytesPerSector;
+ *SectorsPerTrack = diskGeometry.SectorsPerTrack;
+ *Heads = diskGeometry.TracksPerCylinder;
+ *TotalSectorCount = (RtlExtendedIntegerMultiply(
+ diskGeometry.Cylinders,
+ (*SectorsPerTrack) * (*Heads))).LowPart;
+ return OK_STATUS;
+}
+
+
+
+STATUS_CODE
+LowGetDiskLayout(
+ IN PCHAR Path,
+ OUT PDRIVE_LAYOUT_INFORMATION* DriveLayout
+ )
+
+/*++
+
+Routine Description:
+
+ Perform the necessary NT API calls to get the drive
+ layout from the disk and return it in a memory buffer
+ allocated by this routine.
+
+Arguments:
+
+ Path - Ascii path name to get to disk object
+ this is not a full path, but rather
+ a path without the Partition indicator
+ \device\harddiskX
+
+ DriveLayout - pointer to pointer for the drive layout result
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ PDRIVE_LAYOUT_INFORMATION layout;
+ IO_STATUS_BLOCK statusBlock;
+ STATUS_CODE status;
+ ULONG bufferSize;
+ HANDLE handle;
+
+ bufferSize = sizeof(DRIVE_LAYOUT_INFORMATION)
+ + (500 * sizeof(PARTITION_INFORMATION));
+
+ layout = (PDRIVE_LAYOUT_INFORMATION)AllocateMemory(bufferSize);
+ if (NULL == layout)
+ {
+ RETURN_OUT_OF_MEMORY;
+ }
+
+ if ((status = LowOpenDisk(Path, &handle)) != OK_STATUS)
+ {
+ FreeMemory(layout);
+ return status;
+ }
+
+ status = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_GET_DRIVE_LAYOUT,
+ NULL,
+ 0,
+ layout,
+ bufferSize);
+ LowCloseDisk(handle);
+
+ if (!NT_SUCCESS(status))
+ {
+ if (status == STATUS_BAD_MASTER_BOOT_RECORD)
+ {
+ FDLOG((1,"LowGetDiskLayout: Disk device %s has bad MBR\n",Path));
+
+ // Zero the drive layout information for the fdengine to process.
+
+ RtlZeroMemory(layout, bufferSize);
+ }
+ else
+ {
+ FDLOG((0,"LowGetDiskLayout: Status %lx getting layout for disk device %s\n",status,Path));
+ FreeMemory(layout);
+ return status;
+ }
+ }
+ else
+ {
+
+ FDLOG((2,"LowGetDiskLayout: layout received from ioctl for %s follows:\n",Path));
+ LOG_DRIVE_LAYOUT(layout);
+ }
+
+ // Check to insure that the drive supports dynamic partitioning
+
+ *DriveLayout = layout;
+ return OK_STATUS;
+}
+
+
+STATUS_CODE
+LowSetDiskLayout(
+ IN PCHAR Path,
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ )
+
+/*++
+
+Routine Description:
+
+ Perform the NT API actions of opening Partition0 for
+ the specified drive and setting the drive layout.
+
+Arguments:
+
+ Path - Ascii path name to get to disk object
+ this is not a full path, but rather
+ a path without the Partition indicator
+ \device\harddiskX
+
+ DriveLayout - new layout to set
+
+Return Value:
+
+ NT status
+
+--*/
+
+{
+ IO_STATUS_BLOCK statusBlock;
+ STATUS_CODE status;
+ HANDLE handle;
+ ULONG bufferSize;
+
+ if ((status = LowOpenDisk(Path, &handle)) != OK_STATUS)
+ {
+ return status;
+ }
+ else
+ {
+ FDLOG((2, "LowSetDiskLayout: calling ioctl for %s, layout follows:\n", Path));
+ LOG_DRIVE_LAYOUT(DriveLayout);
+ }
+
+ bufferSize = sizeof(DRIVE_LAYOUT_INFORMATION)
+ + ( (DriveLayout->PartitionCount - 1)
+ * sizeof(PARTITION_INFORMATION));
+ status = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ IOCTL_DISK_SET_DRIVE_LAYOUT,
+ DriveLayout,
+ bufferSize,
+ DriveLayout,
+ bufferSize);
+ LowCloseDisk(handle);
+ return status;
+}
+
+
+STATUS_CODE
+LowWriteSectors(
+ IN HANDLE_T VolumeId,
+ IN ULONG SectorSize,
+ IN ULONG StartingSector,
+ IN ULONG NumberOfSectors,
+ IN PVOID Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ Routine to write to a volume handle. This routine
+ insulates the NT issues concerning the call from the
+ caller.
+
+Arguments:
+
+ VolumeId - actually the NT handle.
+ SectorSize - used to calculate starting byte offset for I/O
+ StartingSector - starting sector for write.
+ NumberOfSectors - size of I/O in sectors
+ Buffer - the location for the data
+
+Return Value:
+
+ Standard NT status values
+
+--*/
+
+{
+ IO_STATUS_BLOCK statusBlock;
+ LARGE_INTEGER byteOffset;
+
+ byteOffset.QuadPart = UInt32x32To64(StartingSector, SectorSize);
+
+ statusBlock.Status = 0;
+ statusBlock.Information = 0;
+ return NtWriteFile(VolumeId,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ Buffer,
+ NumberOfSectors * SectorSize,
+ &byteOffset,
+ NULL);
+}
+
+
+STATUS_CODE
+LowReadSectors(
+ IN HANDLE_T VolumeId,
+ IN ULONG SectorSize,
+ IN ULONG StartingSector,
+ IN ULONG NumberOfSectors,
+ IN PVOID Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ Routine to read from a volume handle. This routine
+ insulates the NT issues concerning the call from the
+ caller.
+
+Arguments:
+
+ VolumeId - actually the NT handle.
+ SectorSize - used to calculate starting byte offset for I/O
+ StartingSector - starting sector for write.
+ NumberOfSectors - size of I/O in sectors
+ Buffer - the location for the data
+
+Return Value:
+
+ Standard NT status values
+
+--*/
+
+{
+ IO_STATUS_BLOCK statusBlock;
+ LARGE_INTEGER byteOffset;
+
+ byteOffset.QuadPart = UInt32x32To64(StartingSector, SectorSize);
+
+ statusBlock.Status = 0;
+ statusBlock.Information = 0;
+ return NtReadFile(VolumeId,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ Buffer,
+ NumberOfSectors * SectorSize,
+ &byteOffset,
+ NULL);
+}
+
+
+STATUS_CODE
+LowFtVolumeStatus(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ IN PFT_SET_STATUS FtStatus,
+ IN PULONG NumberOfMembers
+ )
+
+/*++
+
+Routine Description:
+
+ Open the requested partition and query the FT state.
+
+Arguments:
+
+ DriveLetter - the letter for the current state
+ FtState - a pointer to a location to return state
+ NumberOfMembers - a pointer to a ULONG for number of members
+ in the FT set.
+
+Return Value:
+
+ Standard NT status values
+
+--*/
+
+{
+ HANDLE handle;
+ STATUS_CODE status;
+ IO_STATUS_BLOCK statusBlock;
+ FT_SET_INFORMATION setInfo;
+
+ status = LowOpenPartition(GetDiskName(Disk),
+ Partition,
+ &handle);
+
+ if (status == OK_STATUS)
+ {
+ status = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ FT_QUERY_SET_STATE,
+ NULL,
+ 0,
+ &setInfo,
+ sizeof(setInfo));
+ LowCloseDisk(handle);
+
+ if (status == OK_STATUS)
+ {
+ switch (setInfo.SetState)
+ {
+ case FtStateOk:
+ *FtStatus = FtSetHealthy;
+ break;
+
+ case FtHasOrphan:
+ switch (setInfo.Type)
+ {
+ case Mirror:
+ *FtStatus = FtSetBroken;
+ break;
+ case StripeWithParity:
+ *FtStatus = FtSetRecoverable;
+ break;
+ }
+ break;
+
+ case FtRegenerating:
+ *FtStatus = FtSetRegenerating;
+ break;
+
+ case FtCheckParity:
+ *FtStatus = FtSetInitializationFailed;
+ break;
+
+ case FtInitializing:
+ *FtStatus = FtSetInitializing;
+ break;
+
+ case FtDisabled:
+
+ // This will never happen.
+
+ *FtStatus = FtSetDisabled;
+ break;
+
+ case FtNoCheckData:
+ default:
+
+ // BUGBUG: there is no mapping here.
+
+ *FtStatus = FtSetHealthy;
+ break;
+ }
+ *NumberOfMembers = setInfo.NumberOfMembers;
+ }
+ }
+ else
+ {
+ // If the FT set could not be opened, then it must be
+ // disabled if the return code is "No such device".
+
+ if (status == 0xc000000e)
+ {
+ *FtStatus = FtSetDisabled;
+ status = OK_STATUS;
+ }
+ }
+
+ // Always update the state to the caller.
+
+ return status;
+}
+
+
+STATUS_CODE
+LowFtVolumeStatusByLetter(
+ IN CHAR DriveLetter,
+ IN PFT_SET_STATUS FtStatus,
+ IN PULONG NumberOfMembers
+ )
+
+/*++
+
+Routine Description:
+
+ Open the requested drive letter and query the FT state.
+
+Arguments:
+
+ DriveLetter - the letter for the current state
+ FtState - a pointer to a location to return state
+ NumberOfMembers - a pointer to a ULONG for number of members
+ in the FT set.
+
+Return Value:
+
+ Standard NT status values
+
+--*/
+
+{
+ HANDLE handle;
+ STATUS_CODE status;
+ IO_STATUS_BLOCK statusBlock;
+ FT_SET_INFORMATION setInfo;
+
+ *NumberOfMembers = 1;
+ status = LowOpenDriveLetter(DriveLetter,
+ &handle);
+
+ if (status == OK_STATUS)
+ {
+ status = NtDeviceIoControlFile(handle,
+ 0,
+ NULL,
+ NULL,
+ &statusBlock,
+ FT_QUERY_SET_STATE,
+ NULL,
+ 0,
+ &setInfo,
+ sizeof(setInfo));
+ LowCloseDisk(handle);
+
+ if (status == OK_STATUS)
+ {
+ switch (setInfo.SetState)
+ {
+ case FtStateOk:
+ *FtStatus = FtSetHealthy;
+ break;
+
+ case FtHasOrphan:
+ switch (setInfo.Type)
+ {
+ case Mirror:
+ *FtStatus = FtSetBroken;
+ break;
+ case StripeWithParity:
+ *FtStatus = FtSetRecoverable;
+ break;
+ }
+ break;
+
+ case FtRegenerating:
+ *FtStatus = FtSetRegenerating;
+ break;
+
+ case FtCheckParity:
+ *FtStatus = FtSetInitializationFailed;
+ break;
+
+ case FtInitializing:
+ *FtStatus = FtSetInitializing;
+ break;
+
+ case FtDisabled:
+
+ // This will never happen.
+
+ *FtStatus = FtSetDisabled;
+ break;
+
+ case FtNoCheckData:
+ default:
+
+ // BUGBUG: there is no mapping here.
+
+ *FtStatus = FtSetHealthy;
+ break;
+ }
+ *NumberOfMembers = setInfo.NumberOfMembers;
+ }
+ }
+ else
+ {
+ // If the FT set could not be opened, then it must be
+ // disabled if the return code is "No such device".
+
+ if (status == 0xc000000e)
+ {
+ *FtStatus = FtSetDisabled;
+ status = OK_STATUS;
+ }
+ }
+
+ // Always update the state to the caller.
+
+ return status;
+}
+
+#if DBG == 1
+
+#define NUMBER_OF_HANDLES_TRACKED 500
+HANDLE OpenHandleArray[NUMBER_OF_HANDLES_TRACKED];
+BOOLEAN DmFirstTime = TRUE;
+ULONG HandleHighWaterMark = 0;
+
+NTSTATUS
+DmOpenFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG ShareAccess,
+ IN ULONG OpenOptions
+ )
+
+/*++
+
+Routine Description:
+
+ A debugging aid to track open and closes of partitions.
+
+Arguments:
+
+ Same as for NtOpenFile()
+
+Return Value:
+
+ Same as for NtOpenFile()
+
+--*/
+
+{
+ ULONG index;
+ NTSTATUS status;
+
+ if (DmFirstTime)
+ {
+ DmFirstTime = FALSE;
+ for (index = 0; index < NUMBER_OF_HANDLES_TRACKED; index++)
+ {
+ OpenHandleArray[index] = (HANDLE) 0;
+ }
+ }
+
+ status = NtOpenFile(FileHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ IoStatusBlock,
+ ShareAccess,
+ OpenOptions);
+ if (NT_SUCCESS(status))
+ {
+ for (index = 0; index < NUMBER_OF_HANDLES_TRACKED; index++)
+ {
+ if (OpenHandleArray[index] == (HANDLE) 0)
+ {
+ OpenHandleArray[index] = *FileHandle;
+
+ if (index > HandleHighWaterMark)
+ {
+ HandleHighWaterMark = index;
+ }
+ break;
+ }
+ }
+ }
+ return status;
+}
+
+
+NTSTATUS
+DmClose(
+ IN HANDLE Handle
+ )
+
+/*++
+
+Routine Description:
+
+ A debugging aid for tracking open and closes
+
+Arguments:
+
+ Same as for NtClose()
+
+Return Value:
+
+ Same as for NtClose()
+
+--*/
+
+{
+ ULONG index;
+
+ for (index = 0; index < NUMBER_OF_HANDLES_TRACKED; index++)
+ {
+ if (OpenHandleArray[index] == Handle)
+ {
+ OpenHandleArray[index] = (HANDLE) 0;
+ break;
+ }
+ }
+
+ return NtClose(Handle);
+}
+
+#endif // DBG == 1
diff --git a/private/utils/windisk/src/ntlow.hxx b/private/utils/windisk/src/ntlow.hxx
new file mode 100644
index 000000000..305978e61
--- /dev/null
+++ b/private/utils/windisk/src/ntlow.hxx
@@ -0,0 +1,134 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ntlow.hxx
+//
+// Contents: Low-level I/O routines, implemented to run on NT.
+//
+// History: 8-Nov-91 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NTLOW_HXX__
+#define __NTLOW_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+STATUS_CODE
+LowQueryFdiskPathList(
+ OUT PCHAR** PathList,
+ OUT PULONG ListLength
+ );
+
+STATUS_CODE
+LowFreeFdiskPathList(
+ IN OUT PCHAR* PathList,
+ IN ULONG ListLength
+ );
+
+STATUS_CODE
+LowOpenNtName(
+ IN PCHAR Name,
+ IN HANDLE_PT Handle
+ );
+
+STATUS_CODE
+LowOpenDisk(
+ IN PCHAR DevicePath,
+ OUT HANDLE_PT DiskId
+ );
+
+STATUS_CODE
+LowOpenPartition(
+ IN PCHAR DevicePath,
+ IN ULONG Partition,
+ OUT HANDLE_PT Handle
+ );
+
+STATUS_CODE
+LowCloseDisk(
+ IN HANDLE_T DiskId
+ );
+
+STATUS_CODE
+LowGetDriveGeometry(
+ IN PCHAR DevicePath,
+ OUT PULONG TotalSectorCount,
+ OUT PULONG SectorSize,
+ OUT PULONG SectorsPerTrack,
+ OUT PULONG Heads
+ );
+
+STATUS_CODE
+LowGetDiskLayout(
+ IN PCHAR Path,
+ OUT PDRIVE_LAYOUT_INFORMATION* DriveLayout
+ );
+
+STATUS_CODE
+LowSetDiskLayout(
+ IN PCHAR Path,
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ );
+
+STATUS_CODE
+LowGetPartitionGeometry(
+ IN PCHAR PartitionPath,
+ OUT PULONG TotalSectorCount,
+ OUT PULONG SectorSize,
+ OUT PULONG SectorsPerTrack,
+ OUT PULONG Heads
+ );
+
+STATUS_CODE
+LowReadSectors(
+ IN HANDLE_T VolumeId,
+ IN ULONG SectorSize,
+ IN ULONG StartingSector,
+ IN ULONG NumberOfSectors,
+ OUT PVOID Buffer
+ );
+
+STATUS_CODE
+LowWriteSectors(
+ IN HANDLE_T VolumeId,
+ IN ULONG SectorSize,
+ IN ULONG StartingSector,
+ IN ULONG NumberOfSectors,
+ IN PVOID Buffer
+ );
+
+STATUS_CODE
+LowLockDrive(
+ IN HANDLE_T DiskId
+ );
+
+STATUS_CODE
+LowUnlockDrive(
+ IN HANDLE_T DiskId
+ );
+
+STATUS_CODE
+LowOpenDriveLetter(
+ IN WCHAR DriveLetter,
+ IN HANDLE_PT Handle
+ );
+
+STATUS_CODE
+LowFtVolumeStatus(
+ IN ULONG Disk,
+ IN ULONG Partition,
+ IN PFT_SET_STATUS FtStatus,
+ IN PULONG NumberOfMembers
+ );
+
+STATUS_CODE
+LowFtVolumeStatusByLetter(
+ IN CHAR DriveLetter,
+ IN PFT_SET_STATUS FtStatus,
+ IN PULONG NumberOfMembers
+ );
+
+#endif // __NTLOW_HXX__
diff --git a/private/utils/windisk/src/oleclass.cxx b/private/utils/windisk/src/oleclass.cxx
new file mode 100644
index 000000000..d7b29c033
--- /dev/null
+++ b/private/utils/windisk/src/oleclass.cxx
@@ -0,0 +1,84 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: oleclass.cxx
+//
+// Contents: OLE class code helpers
+//
+// Functions:
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <util.hxx>
+#include "oleclass.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseOle, public
+//
+// Synopsis: Unlink from OLE libraries
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 27-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+ReleaseOle(
+ VOID
+ )
+{
+#ifdef WINDISK_EXTENSIONS
+ OleUninitialize();
+#endif // WINDISK_EXTENSIONS
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitOle, public
+//
+// Synopsis: Link to OLE libraries
+//
+// Arguments: none
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 27-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+InitOle(
+ VOID
+ )
+{
+ BOOL fReturn = TRUE;
+
+#ifdef WINDISK_EXTENSIONS
+ if (OleInitializeEx(NULL, COINIT_MULTITHREADED) != 0)
+ {
+ ReleaseOle();
+ fReturn = FALSE;
+ }
+ else
+ {
+ fReturn = TRUE;
+ }
+#endif // WINDISK_EXTENSIONS
+
+ return fReturn;
+}
diff --git a/private/utils/windisk/src/oleclass.hxx b/private/utils/windisk/src/oleclass.hxx
new file mode 100644
index 000000000..d1c9ba11b
--- /dev/null
+++ b/private/utils/windisk/src/oleclass.hxx
@@ -0,0 +1,29 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: oleclass.hxx
+//
+// Contents: OLE class code helpers
+//
+// Functions:
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __OLECLASS_HXX__
+#define __OLECLASS_HXX__
+
+VOID
+ReleaseOle(
+ VOID
+ );
+
+BOOL
+InitOle(
+ VOID
+ );
+
+#endif // __OLECLASS_HXX__
diff --git a/private/utils/windisk/src/ops.cxx b/private/utils/windisk/src/ops.cxx
new file mode 100644
index 000000000..7ffb127b5
--- /dev/null
+++ b/private/utils/windisk/src/ops.cxx
@@ -0,0 +1,2823 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ops.cxx
+//
+// Contents: Main operations: Create partition, etc.
+//
+// History: 4-Mar-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "commit.hxx"
+#include "dialogs.h"
+#include "dlgs.hxx"
+#include "drives.hxx"
+#include "fill.hxx"
+#include "ft.hxx"
+#include "listbox.hxx"
+#include "nt.hxx"
+#include "ntlow.hxx"
+#include "ops.hxx"
+#include "select.hxx"
+#include "stleg.hxx"
+#include "windisk.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+VOID
+DoDeleteFTSet(
+ IN DWORD ConfirmationMsg
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: CompleteSingleRegionOperation
+//
+// Synopsis: Complete a single region operation: repaint the disks,
+// regenerate the listview, adjust the status area and menus.
+//
+// Arguments: [DiskState] -- disk on which the operation was performed
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CompleteSingleRegionOperation(
+ IN PDISKSTATE DiskState
+ )
+{
+ RECT rc;
+ signed displayOffset;
+
+ EnableMenuItem(GetMenu(g_hwndFrame), IDM_CONFIGSAVE, MF_GRAYED);
+
+ DeterminePartitioningState(DiskState);
+ SetDriveLetterInfo(DiskState->Disk);
+
+ SetFTObjectBackPointers();
+
+ DrawDiskBar(DiskState);
+
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+
+ if (VIEW_DISKS == g_WhichView)
+ {
+ // BUGBUG use of disk# as offset in listbox
+ displayOffset = (signed)DiskState->Disk
+ - (signed)SendMessage(g_hwndList, LB_GETTOPINDEX, 0, 0);
+
+ if (displayOffset > 0) // otherwise it's not visible
+ {
+ // make a thin rectangle to force update
+ rc.left = BarLeftX + 5;
+ rc.right = rc.left + 5;
+ rc.top = (displayOffset * GraphHeight) + BarTopYOffset;
+ rc.bottom = rc.top + 5;
+ InvalidateRect(g_hwndList, &rc, FALSE);
+ }
+
+ ResetLBCursorRegion();
+ ForceLBRedraw();
+ }
+ else if (VIEW_VOLUMES == g_WhichView)
+ {
+ FillListView(TRUE); // refresh it!
+ }
+
+ ClearStatusArea();
+ DetermineExistence();
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CompleteMultiRegionOperation
+//
+// Synopsis: Complete a multiple region operation: redraw and repaint
+// all the disks, regenerate the listview, adjust the status
+// area and menus.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CompleteMultiRegionOperation(
+ VOID
+ )
+{
+ ULONG i;
+
+ EnableMenuItem(GetMenu(g_hwndFrame), IDM_CONFIGSAVE, MF_GRAYED);
+
+ for (i=0; i<DiskCount; i++)
+ {
+ DeterminePartitioningState(DiskArray[i]);
+ SetDriveLetterInfo(i);
+ }
+ SetFTObjectBackPointers();
+
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+
+ if (VIEW_DISKS == g_WhichView)
+ {
+ ResetLBCursorRegion();
+ TotalRedrawAndRepaint();
+ }
+ else if (VIEW_VOLUMES == g_WhichView)
+ {
+ FillListView(TRUE); // refresh it!
+ }
+
+ ClearStatusArea();
+ DetermineExistence();
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CompleteDriveLetterChange
+//
+// Synopsis:
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 2-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CompleteDriveLetterChange(
+ IN WCHAR NewDriveLetter
+ )
+{
+ SetCursor(g_hCurWait);
+
+ //
+ // Change the menu based on this new format
+ //
+
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+
+ //
+ // refresh the display
+ //
+
+ //
+ // for either view, still need to redraw the disks view bars
+ //
+
+// RedrawSelectedBars();
+
+ if (VIEW_DISKS == g_WhichView)
+ {
+// ForceLBRedraw();
+ }
+ else if (VIEW_VOLUMES == g_WhichView)
+ {
+// CheckSelection(); //BUGBUG: why is this necessary to complete a drive letter change?
+ FillListView(FALSE);
+
+ // give the first element the focus and selection, by default
+
+ g_SettingListviewState = TRUE; // no notifications
+
+
+ if (NewDriveLetter != NO_DRIVE_LETTER_EVER) {
+ INT itemNew = GetLVIndexFromDriveLetter(NewDriveLetter);
+
+ // Give the item both the focus *and* the selection, since we only
+ // allow a single listview selection
+
+ ListView_SetItemState(
+ g_hwndLV,
+ itemNew,
+ LVIS_FOCUSED | LVIS_SELECTED,
+ LVIS_FOCUSED | LVIS_SELECTED);
+ ListView_EnsureVisible(g_hwndLV, itemNew, FALSE);
+
+ g_SettingListviewState = FALSE; // accept notifications
+
+ DeselectSelectedDiskViewRegions(); // visual selection in disk view
+ DeselectSelectedRegions(); // actual selection state
+ SetVolumeSelection(itemNew, TRUE); // reflect in disks view
+ }
+ }
+
+ AdjustMenuAndStatus();
+ EnableMenuItem(g_hmenuFrame, IDM_CONFIGSAVE, MF_GRAYED);
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoSetDriveLetter
+//
+// Synopsis: Set the drive letter for the selected volume
+//
+// Arguments: none
+//
+// Requires: A valid selection for creation, as determined by
+// DetermineSelectionState()
+//
+// Returns: nothing
+//
+// History: 1-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoSetDriveLetter(
+ VOID
+ )
+{
+ PCDROM_DESCRIPTOR cdrom;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+ WCHAR description[MAX_RESOURCE_STRING_LEN];
+ DRIVELET_DLG_PARAMS params;
+ ULONG index;
+
+ params.NewDriveLetter = L'\0';
+ params.Description = description;
+
+ if (CdRomSelected)
+ {
+ cdrom = CdRomFindSelectedDevice();
+ FDASSERT(NULL != cdrom);
+
+ params.DriveLetter = cdrom->DriveLetter;
+
+ wsprintf(description, CdRomN, cdrom->DeviceNumber);
+ }
+ else
+ {
+ PFT_OBJECT ftObject;
+
+ regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(NULL != regionDescriptor);
+
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(NULL != regionData);
+
+ ftObject = regionData->FtObject;
+ if (NULL != ftObject)
+ {
+ // Must find the zero member of this set for the
+ // drive letter assignment. Search all of the selected
+ // regions
+
+ index = 0;
+ while (ftObject->MemberIndex)
+ {
+ // search the next selected item if there is one
+
+ index++;
+ if (index >= SelectionCount)
+ {
+ ftObject = NULL;
+ break;
+ }
+
+ regionDescriptor = &SELECTED_REGION(index);
+ FDASSERT(NULL != regionDescriptor);
+
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(NULL != regionData);
+
+ ftObject = regionData->FtObject;
+
+ // must have an FtObject to continue
+
+ if (NULL == ftObject)
+ {
+ break;
+ }
+ }
+
+ FDASSERT(NULL != ftObject);
+
+ // regionDescriptor locates the zero element now.
+ }
+
+ params.DriveLetter = regionData->DriveLetter;
+
+ if (IsDiskRemovable[regionDescriptor->Disk])
+ {
+ ErrorDialog(MSG_CANT_ASSIGN_LETTER_TO_REMOVABLE);
+ return;
+ }
+ else if (AllDriveLettersAreUsed() && IsExtraDriveLetter(params.DriveLetter))
+ {
+ ErrorDialog(MSG_ALL_DRIVE_LETTERS_USED);
+ return;
+ }
+
+ //
+ // Format the description of the partition.
+ //
+
+ if (NULL != (ftObject = GET_FT_OBJECT(regionDescriptor)))
+ {
+ WCHAR descriptionProto[MAX_RESOURCE_STRING_LEN];
+ DWORD resid;
+
+ //
+ // Ft. Description is something like "Stripe set with parity #0"
+ //
+
+ switch (ftObject->Set->Type)
+ {
+ case Mirror:
+ resid = IDS_DLGCAP_MIRROR;
+ break;
+
+ case Stripe:
+ resid = IDS_STATUS_STRIPESET;
+ break;
+
+ case StripeWithParity:
+ resid = IDS_DLGCAP_PARITY;
+ break;
+
+ case VolumeSet:
+ resid = IDS_STATUS_VOLUMESET;
+ break;
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+ LoadString(g_hInstance, resid, descriptionProto, ARRAYLEN(descriptionProto));
+ wsprintf(description, descriptionProto, ftObject->Set->Ordinal);
+ }
+ else
+ {
+ //
+ // Non-ft. description is something like '500 MB Unformatted
+ // logical drive on disk 3' or '400 MB NTFS partition on disk 4'
+ //
+
+ LPTSTR args[4];
+ TCHAR sizeStr[20];
+ TCHAR partTypeStr[100];
+ TCHAR diskNumStr[10];
+ TCHAR typeName[150];
+ TCHAR formatString[MAX_RESOURCE_STRING_LEN];
+
+ args[0] = sizeStr;
+ args[1] = typeName;
+ args[2] = partTypeStr;
+ args[3] = diskNumStr;
+
+ wsprintf(sizeStr, TEXT("%u"), regionDescriptor->SizeMB);
+ wsprintf(typeName, TEXT("%s"), PERSISTENT_DATA(regionDescriptor)->TypeName);
+ LoadString(
+ g_hInstance,
+ (regionDescriptor->RegionType == REGION_LOGICAL)
+ ? IDS_LOGICALVOLUME
+ : IDS_PARTITION,
+ partTypeStr,
+ ARRAYLEN(partTypeStr));
+ wsprintf(diskNumStr, TEXT("%u"), regionDescriptor->Disk);
+
+ LoadString(
+ g_hInstance,
+ IDS_DRIVELET_DESCR,
+ formatString,
+ ARRAYLEN(formatString));
+
+ FormatMessage(
+ FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ formatString,
+ 0,
+ 0,
+ description,
+ sizeof(description),
+ (va_list*)args
+ );
+ }
+ }
+
+ int fOk = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_DRIVELET),
+ g_hwndFrame,
+ DriveLetterDlgProc,
+ (LPARAM)&params
+ );
+
+ if ( (-1 != fOk) // DialogBoxParam error
+ && (FALSE != fOk) ) // user cancelled
+ {
+ if (IsExtraDriveLetter(params.DriveLetter))
+ {
+ // Must insure that driveLetterIn maps to same things
+ // as is returned by the dialog when the user selects
+ // no letter.
+
+ params.DriveLetter = NO_DRIVE_LETTER_EVER;
+ }
+
+ if (params.DriveLetter != params.NewDriveLetter)
+ {
+ //
+ // Something changed: the user isn't just choosing the same drive
+ // letter
+ //
+
+ if (CdRomSelected)
+ {
+ CdRomChangeDriveLetter(cdrom, params.NewDriveLetter);
+ CompleteDriveLetterChange(params.NewDriveLetter);
+ }
+ else
+ {
+ // Assume a disk is selected
+
+ if (CommitDriveLetter(regionDescriptor, params.DriveLetter, params.NewDriveLetter))
+ {
+ //
+ // The following would be more rigorously correct:
+ // if non-ft, just set regionData->DriveLetter. If
+ // ft, scan all regions on all disks for members of
+ // ft set and set their drive letter fields.
+ //
+ // The below is probably correct, though.
+ //
+
+ DWORD i;
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionData = PERSISTENT_DATA(&SELECTED_REGION(i));
+ FDASSERT(NULL != regionData);
+
+ regionData->DriveLetter = params.NewDriveLetter;
+ }
+
+ CompleteDriveLetterChange(params.NewDriveLetter);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoCreate
+//
+// Synopsis: Create a primary or extended partition in the selected
+// free space
+//
+// Arguments: [CreationType] -- REGION_EXTENDED or REGION_PRIMARY
+//
+// Requires: A valid selection for creation, as determined by
+// DetermineSelectionState()
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoCreate(
+ IN REGION_TYPE CreationType
+ )
+{
+ PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+ ULONG diskNumber = regionDescriptor->Disk;
+ PPERSISTENT_REGION_DATA regionData;
+ MINMAXDLG_PARAMS dlgParams;
+ DWORD creationSize;
+ DWORD ec;
+ BOOLEAN isRemovable;
+ WCHAR driveLetter;
+
+ FDASSERT(SingleSel);
+ FDASSERT(regionDescriptor->SysID == PARTITION_ENTRY_UNUSED);
+
+ //
+ // WinDisk can only create a single partition on a removable
+ // disk--no extended partitions and only one primary.
+ //
+ isRemovable = IsDiskRemovable[diskNumber];
+
+ if ( isRemovable )
+ {
+ if ( CreationType == REGION_EXTENDED )
+ {
+ ErrorDialog( MSG_NO_EXTENDED_ON_REMOVABLE );
+ return;
+ }
+
+ if ( DiskArray[diskNumber]->ExistAny )
+ {
+ ErrorDialog( MSG_ONLY_ONE_PARTITION_ON_REMOVABLE );
+ return;
+ }
+ }
+
+
+ //
+ // Make sure the partition table is not full, and that we are allowed to
+ // create the type of partition to be created.
+ //
+
+ if (regionDescriptor->RegionType == REGION_PRIMARY)
+ {
+ if (!SingleSel->CreatePrimary)
+ {
+ ErrorDialog(MSG_PART_TABLE_FULL);
+ return;
+ }
+
+ if ((CreationType == REGION_EXTENDED) && !SingleSel->CreateExtended)
+ {
+ ErrorDialog(MSG_EXTENDED_ALREADY_EXISTS);
+ return;
+ }
+ }
+
+ //
+ // If not creating an extended partition, allocate a drive letter.
+ // If no drive letter is available, warn the user and allow him to cancel.
+ // If the new partition is on a removable disk, use the reserved
+ // drive letter for that removable disk.
+ //
+ if (CreationType != REGION_EXTENDED)
+ {
+ CreationType = regionDescriptor->RegionType; // primary or logical
+
+ if (isRemovable)
+ {
+ driveLetter = RemovableDiskReservedDriveLetters[diskNumber];
+ }
+ else
+ {
+ if (!AssignDriveLetter(
+ TRUE,
+ (CreationType == REGION_LOGICAL)
+ ? IDS_LOGICALVOLUME : IDS_PARTITION,
+ &driveLetter))
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ CommitDueToExtended = TRUE;
+ }
+
+#if i386
+ // if the user is creating a primary partition and there are already
+ // primary partitions, warn him that the scheme he will create may
+ // not be DOS compatible.
+
+ if ((CreationType == REGION_PRIMARY) && SingleSel->ExistPrimary)
+ {
+ if (IDYES != ConfirmationDialog(
+ MSG_CREATE_NOT_COMPAT,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+ }
+#endif
+
+ // now get the size.
+ //
+ dlgParams.MinSizeMB = FdGetMinimumSizeMB(diskNumber);
+ dlgParams.MaxSizeMB = FdGetMaximumSizeMB(regionDescriptor, CreationType);
+
+ switch (CreationType)
+ {
+ case REGION_PRIMARY:
+ dlgParams.CaptionStringID = IDS_CRTPART_CAPTION_P;
+ dlgParams.MinimumStringID = IDS_CRTPART_MIN_P;
+ dlgParams.MaximumStringID = IDS_CRTPART_MAX_P;
+ dlgParams.SizeStringID = IDS_CRTPART_SIZE_P;
+ dlgParams.HelpContextId = HC_DM_DLG_CREATEPRIMARY;
+ break;
+
+ case REGION_EXTENDED:
+ dlgParams.CaptionStringID = IDS_CRTPART_CAPTION_E;
+ dlgParams.MinimumStringID = IDS_CRTPART_MIN_P;
+ dlgParams.MaximumStringID = IDS_CRTPART_MAX_P;
+ dlgParams.SizeStringID = IDS_CRTPART_SIZE_P;
+ dlgParams.HelpContextId = HC_DM_DLG_CREATEEXTENDED;
+ break;
+
+ case REGION_LOGICAL:
+ dlgParams.CaptionStringID = IDS_CRTPART_CAPTION_L;
+ dlgParams.MinimumStringID = IDS_CRTPART_MIN_L;
+ dlgParams.MaximumStringID = IDS_CRTPART_MAX_L;
+ dlgParams.SizeStringID = IDS_CRTPART_SIZE_L;
+ dlgParams.HelpContextId = HC_DM_DLG_CREATELOGICAL;
+ break;
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+ creationSize = DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_MINMAX),
+ g_hwndFrame,
+ MinMaxDlgProc,
+ (LPARAM)&dlgParams);
+
+ if (0 == creationSize) // user cancelled
+ {
+ return;
+ }
+
+ // Since the WinDisk can only create one partition on a removable
+ // disk, if the user requests a size smaller than the maximum
+ // on a removable disk, prompt to confirm:
+ //
+ if (isRemovable
+ && creationSize != FdGetMaximumSizeMB(regionDescriptor, CreationType))
+ {
+ if (IDYES != ConfirmationDialog(
+ MSG_REMOVABLE_PARTITION_NOT_FULL_SIZE,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+ }
+
+#if i386
+
+ //
+ // See whether the partition will cross over the 1024 cylinder boundary
+ // and warn the user if it will.
+ //
+ // Don't warn about creating logical partitions: the user's already
+ // been warned once about creating the extended partition, so they
+ // presumably know the warning. This is different from NT 3.1, which
+ // warned every time.
+ //
+
+ if (CreationType != REGION_LOGICAL)
+ {
+ if (FdCrosses1024Cylinder(regionDescriptor, creationSize, CreationType))
+ {
+ DWORD msgId = (CreationType == REGION_PRIMARY)
+ ? MSG_PRI_1024_CYL
+ : MSG_EXT_1024_CYL
+ ;
+ if (IDYES != ConfirmationDialog(
+ msgId,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+ }
+ }
+
+#endif
+
+ SetCursor(g_hCurWait);
+
+ //
+ // If not creating an extended partition, we need to create a new
+ // persistent region data structure to associate with the new
+ // partition.
+ //
+
+ if (CreationType == REGION_EXTENDED)
+ {
+ regionData = NULL;
+ }
+ else
+ {
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ L"",
+ wszUnformatted,
+ driveLetter,
+ TRUE,
+ zero,
+ zero
+ );
+ }
+
+ ec = CreatePartition(
+ regionDescriptor,
+ creationSize,
+ CreationType
+ );
+
+ if (ec != NO_ERROR)
+ {
+ SetCursor(g_hCurNormal);
+ ErrorDialog(ec);
+ }
+
+ DmSetPersistentRegionData(regionDescriptor, regionData);
+
+ if (CreationType != REGION_EXTENDED)
+ {
+ if (!isRemovable)
+ {
+ MarkDriveLetterUsed(driveLetter);
+ CommitToAssignLetterList(regionDescriptor, FALSE);
+ } else {
+ CommitDueToCreate = TRUE;
+ }
+ }
+
+ // this clears all selections on the disk
+ CompleteSingleRegionOperation(SingleSel);
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDelete
+//
+// Synopsis: Delete a selected volume
+//
+// Arguments: (none)
+//
+// Requires: A selected volume
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoDelete(
+ VOID
+ )
+{
+ PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+ ULONG diskNumber = regionDescriptor->Disk;
+ PPERSISTENT_REGION_DATA regionData;
+ DWORD actualIndex = SingleSelIndex;
+ DWORD i;
+ DWORD ec;
+ BOOL deletingExtended;
+
+ FDASSERT(SingleSel);
+
+ // if deleting a free space in the extended partition, then delete the
+ // extended partition itself.
+
+ if ((regionDescriptor->RegionType == REGION_LOGICAL)
+ && !SingleSel->ExistLogical)
+ {
+ FDASSERT(SingleSel->ExistExtended);
+
+ // find the extended partition
+
+ for (i=0; i<SingleSel->RegionCount; i++)
+ {
+ if (IsExtended(SingleSel->RegionArray[i].SysID))
+ {
+ actualIndex = i;
+ break;
+ }
+ }
+
+ deletingExtended = TRUE;
+ FDASSERT(actualIndex != SingleSelIndex);
+ }
+ else
+ {
+ deletingExtended = FALSE;
+
+ //
+ // Make sure deletion of this partition is allowed. It is not allowed
+ // if it is the boot partition (or sys partition on x86).
+ //
+
+ if (NO_ERROR
+ != (ec = DeletionIsAllowed(&SingleSel->RegionArray[actualIndex])))
+ {
+ ErrorDialog(ec);
+ return;
+ }
+ }
+
+ // If this is a partition that will become the result of a
+ // mirror break, insure that the break has occurred. Otherwise
+ // this delete will have bad results.
+
+ // actualIndex is the thing to delete.
+ regionDescriptor = &SingleSel->RegionArray[actualIndex];
+ if (NULL != regionDescriptor->Reserved)
+ {
+ if (NULL != regionDescriptor->Reserved->Partition)
+ {
+ if (regionDescriptor->Reserved->Partition->CommitMirrorBreakNeeded)
+ {
+ ErrorDialog(MSG_MUST_COMMIT_BREAK);
+ return;
+ }
+ }
+ }
+
+ FDASSERT(regionDescriptor->SysID != PARTITION_ENTRY_UNUSED);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ if (!deletingExtended)
+ {
+ BOOL fNew = FALSE;
+ if (NULL != regionData && regionData->NewRegion)
+ {
+ fNew = TRUE;
+ }
+
+ if (!fNew
+ && (IDYES != ConfirmationDialog(
+ MSG_CONFIRM_DELETE,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2)))
+ {
+ return;
+ }
+ }
+
+ if (NULL != regionData)
+ {
+ // Remember drive letter if there is one in order to lock it for delete
+
+ if (CommitToLockList(
+ regionDescriptor,
+ !IsDiskRemovable[diskNumber],
+ TRUE,
+ FALSE))
+ {
+ // Could not lock exclusively - do not allow delete
+
+ if (IsPagefileOnDrive(regionData->DriveLetter))
+ {
+ ErrorDialog(MSG_CANNOT_LOCK_PAGEFILE);
+ return;
+ }
+ else
+ {
+ if (CommitToLockList(
+ regionDescriptor,
+ !IsDiskRemovable[diskNumber],
+ TRUE,
+ FALSE))
+ {
+ FDLOG((1,"DoDelete: Couldn't lock 2 times - popup shown\n"));
+ ErrorDialog(MSG_CANNOT_LOCK_TRY_AGAIN);
+ return;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Deleting an extended partition - enable commit.
+
+ CommitDueToDelete = TRUE;
+ }
+
+
+ SetCursor(g_hCurWait);
+
+ ec = DeletePartition(regionDescriptor);
+
+ if (ec != NO_ERROR)
+ {
+ SetCursor(g_hCurNormal);
+ ErrorDialog(ec);
+ }
+
+ if (NULL != regionData)
+ {
+
+ //
+ // Note that one might think to free the drive letter here so that it is
+ // available for other drives to use. BUT! we don't. The reason is that
+ // the change isn't actually committed yet. If the changes aren't committed
+ // we don't want to have let the user reassign the drive letter to any other
+ // drive.
+ //
+ DmFreePersistentData(regionData);
+ DmSetPersistentRegionData(regionDescriptor, NULL);
+ }
+
+ // this clears all selections on the disk
+ CompleteSingleRegionOperation(SingleSel);
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+#if i386
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoMakeActive
+//
+// Synopsis: Make the selected volume active
+//
+// Arguments: (none)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoMakeActive(
+ VOID
+ )
+{
+ DWORD i;
+ PREGION_DESCRIPTOR regionDescriptor;
+
+ SetCursor(g_hCurWait);
+
+ if (SelectionCount == 1) {
+
+ FDASSERT(SingleSel);
+ FDASSERT(!SingleSel->RegionArray[SingleSelIndex].Active);
+ FDASSERT(SingleSel->RegionArray[SingleSelIndex].RegionType == REGION_PRIMARY);
+ FDASSERT(SingleSel->RegionArray[SingleSelIndex].SysID != PARTITION_ENTRY_UNUSED);
+
+ MakePartitionActive(SingleSel->RegionArray,
+ SingleSel->RegionCount,
+ SingleSelIndex
+ );
+
+ SetCursor(g_hCurNormal);
+
+ InfoDialog(MSG_DISK0_ACTIVE);
+
+ SetCursor(g_hCurWait);
+
+ CompleteSingleRegionOperation(SingleSel);
+
+
+ } else {
+
+ //
+ // Mirror case.
+ //
+
+ for (i = 0; i < SelectionCount; i++) {
+ regionDescriptor = &SELECTED_REGION(i);
+ if (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED &&
+ regionDescriptor->RegionType == REGION_PRIMARY &&
+ !regionDescriptor->Active) {
+
+ MakePartitionActive(SelectedDS[i]->RegionArray,
+ SelectedDS[i]->RegionCount,
+ SelectedRG[i]);
+ }
+ }
+
+ SetCursor(g_hCurNormal);
+
+ InfoDialog(MSG_DISK0_ACTIVE);
+
+ SetCursor(g_hCurWait);
+
+ CompleteMultiRegionOperation();
+ }
+
+ SetCursor(g_hCurNormal);
+}
+
+#endif
+
+
+#ifndef i386
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoProtectSystemPartition
+//
+// Synopsis: This function toggles the state of the system partition
+// security: if the system partition is secure, it makes it
+// non-secure; if the system partition is not secure, it makes
+// it secure.
+//
+// Arguments: (none)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoProtectSystemPartition(
+ VOID
+ )
+{
+ LONG ec;
+ HKEY hkey;
+ DWORD value;
+ DWORD messageId;
+
+ messageId = SystemPartitionIsSecure ? MSG_CONFIRM_UNPROTECT_SYSTEM :
+ MSG_CONFIRM_PROTECT_SYSTEM;
+
+ if (IDYES != ConfirmationDialog(
+ messageId,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+
+ ec = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Control\\Lsa"),
+ 0,
+ KEY_SET_VALUE,
+ &hkey );
+
+ if (ec != ERROR_SUCCESS)
+ {
+ messageId = SystemPartitionIsSecure ? MSG_CANT_UNPROTECT_SYSTEM :
+ MSG_CANT_PROTECT_SYSTEM;
+ ErrorDialog(messageId);
+ return;
+ }
+
+ // If the system partition is currently secure, change it
+ // to not secure; if it is not secure, make it secure.
+ //
+ value = SystemPartitionIsSecure ? 0 : 1;
+
+ ec = RegSetValueEx( hkey,
+ TEXT("Protect System Partition"),
+ 0,
+ REG_DWORD,
+ (PBYTE)&value,
+ sizeof( DWORD ) );
+
+ RegCloseKey(hkey);
+
+ if (ec != ERROR_SUCCESS)
+ {
+ messageId = SystemPartitionIsSecure ? MSG_CANT_UNPROTECT_SYSTEM :
+ MSG_CANT_PROTECT_SYSTEM;
+ ErrorDialog(messageId);
+ return;
+ }
+
+ SystemPartitionIsSecure = !SystemPartitionIsSecure;
+
+ SetCursor(g_hCurWait);
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+ RestartRequired = TRUE;
+ SetCursor(g_hCurNormal);
+}
+
+#endif // !i386
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoEstablishMirror
+//
+// Synopsis: Establish a mirrored volume from the selection
+//
+// Arguments: (none)
+//
+// Requires: A legal selection for mirror creation (see
+// DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoEstablishMirror(
+ VOID
+ )
+{
+ LARGE_INTEGER partitionSize;
+ LARGE_INTEGER freeSpaceSize;
+ LARGE_INTEGER zero;
+ DWORD i;
+ DWORD partitionIndex = 0;
+ DWORD freeSpaceIndex = 0;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PREGION_DESCRIPTOR freeSpaceRegion = NULL;
+ PREGION_DESCRIPTOR existingRegion = NULL;
+ PREGION_DESCRIPTOR regionArray[MAX_MEMBERS_IN_FT_SET];
+ UCHAR newSysID;
+ PPERSISTENT_REGION_DATA regionData;
+
+ FDASSERT(SelectionCount == 2);
+
+ zero.QuadPart = 0;
+
+ // Make sure that the mirror pair does not include any
+ // partitions on removable media.
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ if (IsDiskRemovable[SELECTED_REGION(i).Disk])
+ {
+ ErrorDialog(MSG_NO_REMOVABLE_IN_MIRROR);
+ return;
+ }
+ }
+
+ for (i=0; i<2; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+ if (regionDescriptor->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ freeSpaceIndex = i;
+ freeSpaceRegion = regionDescriptor;
+ }
+ else
+ {
+ partitionIndex = i;
+ existingRegion = regionDescriptor;
+ }
+ }
+
+ FDASSERT((freeSpaceRegion != NULL) && (existingRegion != NULL));
+
+ //
+ // Make sure that we are allowed to create a partition in the free space.
+ //
+
+ if (!( ((freeSpaceRegion->RegionType == REGION_LOGICAL)
+ && SelectedDS[freeSpaceIndex]->CreateLogical)
+ || ((freeSpaceRegion->RegionType == REGION_PRIMARY)
+ && SelectedDS[freeSpaceIndex]->CreatePrimary)))
+ {
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+
+ //
+ // Make sure that the free space is large enough to hold a mirror of
+ // the existing partition. Do this by getting the EXACT size of
+ // the existing partition and the free space.
+ //
+
+ partitionSize = FdGetExactSize(existingRegion, FALSE);
+ freeSpaceSize = FdGetExactSize(freeSpaceRegion, FALSE);
+
+ if (freeSpaceSize.QuadPart < partitionSize.QuadPart)
+ {
+ ErrorDialog(MSG_CRTMIRROR_BADFREE);
+ return;
+ }
+
+ if (BootDiskNumber != (ULONG)-1)
+ {
+ // If the disk number and original partition number of this
+ // region match the recorded disk number and partition number
+ // of the boot partition, warn the user about mirroring the boot
+ // drive.
+
+ if ( existingRegion->Disk == BootDiskNumber
+ && existingRegion->OriginalPartitionNumber == BootPartitionNumber)
+ {
+ WarningDialog(MSG_MIRROR_OF_BOOT);
+
+ UpdateMbrOnDisk = freeSpaceRegion->Disk;
+ }
+ }
+
+ SetCursor(g_hCurWait);
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ PERSISTENT_DATA(existingRegion)->VolumeLabel,
+ PERSISTENT_DATA(existingRegion)->TypeName,
+ PERSISTENT_DATA(existingRegion)->DriveLetter,
+ TRUE,
+ zero,
+ zero
+ );
+
+ //
+ // Create the new partition.
+ //
+
+ newSysID = (UCHAR)(existingRegion->SysID | (UCHAR)PARTITION_NTFT);
+
+ CreatePartitionEx(freeSpaceRegion,
+ partitionSize,
+ 0,
+ freeSpaceRegion->RegionType,
+ newSysID);
+
+ DmSetPersistentRegionData(freeSpaceRegion, regionData);
+
+ //
+ // Cause the existing partition to be treated as new, to disallow
+ // file system operations
+ //
+
+ PERSISTENT_DATA(existingRegion)->NewRegion = TRUE;
+
+ //
+ // Check if the source partition is active and then mark the shadow
+ // partition active as well.
+ //
+
+ regionDescriptor = &SELECTED_REGION(partitionIndex);
+ if (regionDescriptor->Active) {
+ MakePartitionActive(SelectedDS[freeSpaceIndex]->RegionArray,
+ SelectedDS[freeSpaceIndex]->RegionCount,
+ SelectedRG[freeSpaceIndex]);
+ }
+
+ //
+ // Set the partition type of the existing partition.
+ //
+
+ SetSysID2(existingRegion, newSysID);
+
+ regionArray[0] = existingRegion;
+ regionArray[1] = freeSpaceRegion;
+ FdftCreateFtObjectSet( Mirror,
+ regionArray,
+ 2,
+ FtSetNewNeedsInitialization);
+
+ CompleteMultiRegionOperation();
+ CommitDueToMirror = TRUE;
+
+ EnableMenuItem(g_hmenuFrame, IDM_PARTITIONCOMMIT, MF_ENABLED); //BUGBUG: huh?
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoBreakMirror
+//
+// Synopsis: Using the global selection variables, this routine will break
+// the mirror relationship and modify their region descriptors to
+// describe two non-ft partitions giving either the primary
+// member of the mirror the drive letter for the mirror, or
+// the only healthy member of the mirror the drive letter.
+// The remaining "new" partition will receive the next
+// available drive letter.
+//
+// Arguments: (none)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoBreakMirror(
+ VOID
+ )
+{
+ DWORD i;
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject0;
+ PFT_OBJECT ftObject1;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+ ULONG newDriveLetterRegionIndex;
+ WCHAR driveLetter;
+
+ FDASSERT((SelectionCount == 1) || (SelectionCount == 2));
+
+ ftObject0 = GET_FT_OBJECT(&SELECTED_REGION(0));
+ if (SelectionCount == 2)
+ {
+ ftObject1 = GET_FT_OBJECT(&SELECTED_REGION(1));
+ }
+ else
+ {
+ ftObject1 = NULL;
+ }
+ ftSet = ftObject0->Set;
+
+ // Determine if the action is allowed.
+
+ switch (ftSet->Status)
+ {
+ case FtSetInitializing:
+ case FtSetRegenerating:
+
+ ErrorDialog(MSG_CANT_BREAK_INITIALIZING_SET);
+ return;
+
+ default:
+ break;
+ }
+
+
+ if (IDYES != ConfirmationDialog(
+ MSG_CONFIRM_BRK_MIRROR,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+
+ SetCursor(g_hCurWait);
+
+ //
+ // Figure out which region gets the new drive letter. A complication is
+ // that selection 0 is not necessarily member 0.
+ //
+ // If there is only one selection, then only one part of the mirror set
+ // is present -- no new drive letters are assigned.
+ // Otherwise, if one of the members is orphaned, it gets the new
+ // drive letter. Else the secondary member gets the new drive letter.
+ //
+
+ if (SelectionCount == 2)
+ {
+ if (ftObject0->State == Orphaned)
+ {
+ newDriveLetterRegionIndex = 0;
+ }
+ else
+ {
+ if (ftObject1->State == Orphaned)
+ {
+ newDriveLetterRegionIndex = 1;
+ }
+ else
+ {
+ //
+ // Neither member is orphaned; determine which is
+ // member 0 and give the other one the new drive letter.
+ //
+
+ if (ftObject0->MemberIndex) // secondary member ?
+ {
+ newDriveLetterRegionIndex = 0;
+ }
+ else
+ {
+ newDriveLetterRegionIndex = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ // The one remaining member could be the shadow.
+ // The drive letter must move to locate this partition
+
+ regionDescriptor = &SELECTED_REGION(0);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ if (!regionData->FtObject->MemberIndex)
+ {
+ // The shadow has become the valid partition.
+ // move the current letter there.
+
+ CommitToAssignLetterList(regionDescriptor, TRUE);
+ }
+
+ newDriveLetterRegionIndex = (ULONG)(-1);
+ }
+
+ // if newDriveLetterRegion is -1 this will still work and
+ // select the 0 selected region.
+
+ if (CommitToLockList(
+ &SELECTED_REGION(newDriveLetterRegionIndex ? 0 : 1),
+ FALSE,
+ TRUE,
+ FALSE))
+ {
+ if (IDYES != ConfirmationDialog(
+ MSG_CONFIRM_SHUTDOWN_FOR_MIRROR,
+ MB_ICONQUESTION | MB_YESNO))
+ {
+ return;
+ }
+ RestartRequired = TRUE;
+ }
+
+ if (newDriveLetterRegionIndex != (ULONG)(-1))
+ {
+ if (AssignDriveLetter(FALSE, 0, &driveLetter))
+ {
+ // Got a valid drive letter
+
+ MarkDriveLetterUsed(driveLetter);
+ }
+ else
+ {
+ // didn't get a letter. Instead the magic value
+ // for no drive letter assigned has been returned
+ }
+
+ regionDescriptor = &SELECTED_REGION(newDriveLetterRegionIndex);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ regionData->DriveLetter = driveLetter;
+ CommitToAssignLetterList(regionDescriptor, FALSE);
+
+ if (!regionData->FtObject->MemberIndex)
+ {
+ // The shadow has become the valid partition.
+ // move the current letter there.
+
+ CommitToAssignLetterList(
+ &SELECTED_REGION(newDriveLetterRegionIndex ? 0 : 1),
+ TRUE);
+ }
+ }
+ else
+ {
+ regionDescriptor = &SELECTED_REGION(0);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ if (0 != regionData->FtObject->MemberIndex)
+ {
+ // The shadow is all that is left.
+
+ CommitToAssignLetterList(regionDescriptor, TRUE);
+ }
+ }
+
+
+ FdftDeleteFtObjectSet(ftSet, FALSE);
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+ if (NULL != regionDescriptor->Reserved)
+ {
+ if (NULL != regionDescriptor->Reserved->Partition)
+ {
+ regionDescriptor->Reserved->Partition->CommitMirrorBreakNeeded
+ = TRUE;
+ }
+ }
+ SET_FT_OBJECT(regionDescriptor, 0);
+ SetSysID2(
+ regionDescriptor,
+ (UCHAR)(regionDescriptor->SysID & ~VALID_NTFT));
+ }
+
+ CompleteMultiRegionOperation();
+
+ SetCursor(g_hCurNormal);
+ CommitDueToMirror = TRUE;
+ EnableMenuItem(g_hmenuFrame, IDM_PARTITIONCOMMIT, MF_ENABLED); //BUGBUG: huh?
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoCreateStripe
+//
+// Synopsis: This routine starts the dialog with the user to determine
+// the parameters of the creation of a stripe or stripe set
+// with parity. Based on the user response it creates the
+// internal structures necessary for the creation of a stripe
+// or stripe set with parity.
+//
+// The regions involved in the stripe creation are located via
+// the global parameters for multiple selections.
+//
+// Arguments: [Parity] -- if TRUE, create a stripe set with parity
+// (RAID 5), else create a simple stripe set (RAID 0)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoCreateStripe(
+ IN BOOL Parity
+ )
+{
+ MINMAXDLG_PARAMS params;
+ DWORD smallestSize = (DWORD)(-1);
+ DWORD creationSize;
+ ULONG i;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PREGION_DESCRIPTOR regionArray[MAX_MEMBERS_IN_FT_SET];
+ PPERSISTENT_REGION_DATA regionData;
+ WCHAR driveLetter;
+ LARGE_INTEGER zero;
+
+ zero.QuadPart = 0;
+
+ // Make sure that the volume set does not include any
+ // partitions on removable media.
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ if (IsDiskRemovable[SELECTED_REGION(i).Disk])
+ {
+ ErrorDialog(MSG_NO_REMOVABLE_IN_STRIPE);
+ return;
+ }
+ }
+
+ // Scan the disks to determine the maximum size, which is
+ // the size of the smallest partition times the number of
+ // partitions.
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ FDASSERT(SELECTED_REGION(i).SysID == PARTITION_ENTRY_UNUSED);
+ if (SELECTED_REGION(i).SizeMB < smallestSize)
+ {
+ smallestSize = SELECTED_REGION(i).SizeMB;
+ }
+ }
+
+ //
+ // Figure out a drive letter.
+ //
+
+ if (!AssignDriveLetter(TRUE, IDS_STRIPESET, &driveLetter))
+ {
+ return;
+ }
+
+ params.CaptionStringID = Parity ? IDS_CRTPSTRP_CAPTION : IDS_CRTSTRP_CAPTION;
+ params.MinimumStringID = IDS_CRTSTRP_MIN;
+ params.MaximumStringID = IDS_CRTSTRP_MAX;
+ params.SizeStringID = IDS_CRTSTRP_SIZE;
+ params.MinSizeMB = SelectionCount;
+ params.MaxSizeMB = smallestSize * SelectionCount;
+ if (Parity)
+ {
+ params.HelpContextId = HC_DM_DLG_CREATEPARITYSTRIPE;
+ }
+ else
+ {
+ params.HelpContextId = HC_DM_DLG_CREATESTRIPESET;
+ }
+
+ creationSize = DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_MINMAX),
+ g_hwndFrame,
+ MinMaxDlgProc,
+ (LPARAM)&params);
+
+ if (0 == creationSize) // user cancelled
+ {
+ return;
+ }
+
+ //
+ // Determine how large we have to make each member of the stripe set.
+ //
+
+ creationSize = (creationSize / SelectionCount);
+ FDASSERT(creationSize <= smallestSize);
+ if (creationSize % SelectionCount)
+ {
+ creationSize++; // round up.
+ }
+
+ //
+ // Make sure we are allowed to create all the partitions
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+ FDASSERT(regionDescriptor->RegionType != REGION_EXTENDED);
+
+ if (!( ((regionDescriptor->RegionType == REGION_LOGICAL)
+ && SelectedDS[i]->CreateLogical)
+ || ((regionDescriptor->RegionType == REGION_PRIMARY)
+ && SelectedDS[i]->CreatePrimary)))
+ {
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+
+ SetCursor(g_hCurWait);
+
+ //
+ // Now actually perform the creation.
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+
+ CreatePartitionEx(regionDescriptor,
+ RtlConvertLongToLargeInteger(0L),
+ creationSize,
+ regionDescriptor->RegionType,
+ (UCHAR)(PARTITION_HUGE | PARTITION_NTFT)
+ );
+
+ // Finish setting up the FT set.
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ L"",
+ wszUnformatted,
+ driveLetter,
+ TRUE,
+ zero,
+ zero
+ );
+
+ DmSetPersistentRegionData(regionDescriptor, regionData);
+
+ regionArray[i] = regionDescriptor;
+ }
+
+ // The zeroth element is the one to assign the drive letter to
+
+ CommitToAssignLetterList(&SELECTED_REGION(0), FALSE);
+
+ FdftCreateFtObjectSet(Parity ? StripeWithParity : Stripe,
+ regionArray,
+ SelectionCount,
+ Parity ? FtSetNewNeedsInitialization : FtSetNew
+ );
+
+ MarkDriveLetterUsed(driveLetter);
+ CompleteMultiRegionOperation();
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDeleteFTSet
+//
+// Synopsis: Common code for the deletion of a stripe or volume set.
+// This routine will display a message giving the user a 2nd
+// chance to change their mind, then based on the answer perform
+// the work of deleting the item. This consists of removing
+// the region descriptors (and related information) from the
+// collection of Disk structures.
+//
+// Arguments: [ConfirmationMsg] -- resource ID of message to display
+// to user asking them to confirm this delete (indicating
+// either a stripe or a volume set is to be deleted).
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoDeleteFTSet(
+ IN DWORD ConfirmationMsg
+ )
+{
+ DWORD i;
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+ PREGION_DESCRIPTOR regionDescriptor;
+ WCHAR driveLetter;
+ FT_SET_STATUS setState;
+ ULONG numberOfMembers;
+ BOOL setIsHealthy = TRUE;
+
+ // Attempt to lock this before continuing.
+
+ regionDescriptor = &SELECTED_REGION(0);
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+ ftSet = ftObject->Set;
+
+ LowFtVolumeStatus(regionDescriptor->Disk,
+ regionDescriptor->PartitionNumber,
+ &setState,
+ &numberOfMembers);
+
+ if (ftSet->Status != setState)
+ {
+ ftSet->Status = setState;
+ }
+
+ // Determine if the action is allowed.
+
+ switch (ftSet->Status)
+ {
+ case FtSetDisabled:
+ setIsHealthy = FALSE;
+ break;
+
+ case FtSetInitializing:
+ case FtSetRegenerating:
+
+ ErrorDialog(MSG_CANT_DELETE_INITIALIZING_SET);
+ return;
+
+ default:
+ break;
+ }
+
+ if (CommitToLockList(
+ regionDescriptor,
+ TRUE,
+ setIsHealthy,
+ (ConfirmationMsg == MSG_CONFIRM_BRKANDDEL_MIRROR) // mirror?
+ ? FALSE
+ : TRUE
+ ))
+ {
+ // Could not lock the volume - try again. The file systems
+ // appear to be confused.
+
+ if (CommitToLockList(
+ regionDescriptor,
+ TRUE,
+ setIsHealthy,
+ (ConfirmationMsg == MSG_CONFIRM_BRKANDDEL_MIRROR) // mirror?
+ ? FALSE
+ : TRUE
+ ))
+ {
+ ErrorDialog(MSG_CANNOT_LOCK_TRY_AGAIN);
+ return;
+ }
+ }
+
+ if (IDYES != ConfirmationDialog(
+ ConfirmationMsg,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2))
+ {
+ return;
+ }
+
+ SetCursor(g_hCurWait);
+
+ FdftDeleteFtObjectSet(ftSet, FALSE);
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+
+ if (0 == i)
+ {
+ driveLetter = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+ }
+ else
+ {
+ FDASSERT(PERSISTENT_DATA(regionDescriptor)->DriveLetter == driveLetter);
+ }
+
+ // Free the pieces of the set.
+
+ DmFreePersistentData(PERSISTENT_DATA(regionDescriptor));
+ DmSetPersistentRegionData(regionDescriptor, NULL);
+ DeletePartition(regionDescriptor);
+ }
+
+ //
+ // Note that one might think to free the drive letter here so that it is
+ // available for other drives to use. BUT! we don't. The reason is that
+ // the change isn't actually committed yet. If the changes aren't committed
+ // we don't want to have let the user reassign the drive letter to any other
+ // drive.
+ //
+
+ CompleteMultiRegionOperation();
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDeleteStripe
+//
+// Synopsis: Deletes a stripe set or a stripe set with parity
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoDeleteStripe(
+ VOID
+ )
+{
+ DoDeleteFTSet(MSG_CONFIRM_DEL_STRP);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoBreakAndDeleteMirror
+//
+// Synopsis: Delete both volumes composing a mirror
+//
+// Arguments: (none)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoBreakAndDeleteMirror(
+ VOID
+ )
+{
+ DoDeleteFTSet(MSG_CONFIRM_BRKANDDEL_MIRROR);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDeleteVolumeSet
+//
+// Synopsis: Delete a volume set
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoDeleteVolumeSet(
+ VOID
+ )
+{
+ DoDeleteFTSet(MSG_CONFIRM_DEL_VSET);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoCreateVolumeSet
+//
+// Synopsis: Creates a volume set
+//
+// Arguments: (none)
+//
+// Requires: A legal selection (see DetermineSelectionState())
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoCreateVolumeSet(
+ VOID
+ )
+{
+ MINMAXDLG_PARAMS params;
+ DWORD creationSize;
+ DWORD size;
+ DWORD maxTotalSize = 0;
+ DWORD totalSizeUsed;
+ DWORD sizeArray[MAX_MEMBERS_IN_FT_SET];
+ PULONG primarySpacesToUseOnDisk;
+ UINT i;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PREGION_DESCRIPTOR regionArray[MAX_MEMBERS_IN_FT_SET];
+ PPERSISTENT_REGION_DATA regionData;
+ WCHAR driveLetter;
+
+ // Make sure that the volume set does not include any
+ // partitions on removable media.
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ if (IsDiskRemovable[SELECTED_REGION(i).Disk])
+ {
+ ErrorDialog(MSG_NO_REMOVABLE_IN_VOLUMESET);
+ return;
+ }
+ }
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ FDASSERT(SELECTED_REGION(i).SysID == PARTITION_ENTRY_UNUSED);
+ size = SELECTED_REGION(i).SizeMB;
+ sizeArray[i] = size;
+ maxTotalSize += size;
+ }
+
+ //
+ // Figure out a drive letter.
+ //
+
+ if (!AssignDriveLetter(TRUE, IDS_VOLUMESET, &driveLetter))
+ {
+ return;
+ }
+
+ params.CaptionStringID = IDS_CRTVSET_CAPTION;
+ params.MinimumStringID = IDS_CRTVSET_MIN;
+ params.MaximumStringID = IDS_CRTVSET_MAX;
+ params.SizeStringID = IDS_CRTVSET_SIZE;
+ params.MinSizeMB = SelectionCount;
+ params.MaxSizeMB = maxTotalSize;
+ params.HelpContextId = HC_DM_DLG_CREATEVOLUMESET;
+
+ creationSize = DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_MINMAX),
+ g_hwndFrame,
+ MinMaxDlgProc,
+ (LPARAM)&params
+ );
+
+ if (!creationSize) // user cancelled
+ {
+ return;
+ }
+
+ SetCursor(g_hCurWait);
+
+ //
+ // Determine how large we have to make each member of the volume set.
+ // The percentage of each free space that will be used is the ratio
+ // of the total space he chose to the total free space.
+ //
+ // Example: 2 75 meg free spaces for a total set size of 150 MB.
+ // User chooses a set size of 100 MB. Use 50 MB of each space.
+ //
+ totalSizeUsed = 0;
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ sizeArray[i] = (DWORD)((LONGLONG)sizeArray[i] * creationSize / maxTotalSize);
+ if (((DWORD)((LONGLONG)sizeArray[i] * creationSize % maxTotalSize)))
+ {
+ sizeArray[i]++;
+ }
+
+ if (sizeArray[i] == 0)
+ {
+ sizeArray[i]++;
+ }
+
+ totalSizeUsed += sizeArray[i];
+ }
+
+ // Make sure that the total amount used is not greater than the
+ // maximum amount available. Note that this loop is certain
+ // to terminate because maxTotalSize >= SelectionCount; if
+ // each of the sizes goes down to one, we will exit the loop
+ //
+ while (totalSizeUsed > maxTotalSize)
+ {
+ for (i=0;
+ (i<SelectionCount) && (totalSizeUsed > maxTotalSize);
+ i++)
+ {
+ if (sizeArray[i] > 1)
+ {
+ sizeArray[i]--;
+ totalSizeUsed--;
+ }
+ }
+ }
+
+ //
+ // Make sure that we are allowed to create a partition in the space.
+ //
+ // This is tricky because a volume set could contain more than one
+ // primary partition on a disk -- which means that if we're not careful
+ // we could create a disk with more than 4 primary partitions!
+ //
+
+ primarySpacesToUseOnDisk = (PULONG)Malloc(DiskCount * sizeof(ULONG));
+ RtlZeroMemory(primarySpacesToUseOnDisk, DiskCount * sizeof(ULONG));
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+ FDASSERT(regionDescriptor->RegionType != REGION_EXTENDED);
+
+ if (regionDescriptor->RegionType == REGION_PRIMARY)
+ {
+ primarySpacesToUseOnDisk[SelectedDS[i]->Disk]++;
+ }
+
+ if (!( ((regionDescriptor->RegionType == REGION_LOGICAL)
+ && SelectedDS[i]->CreateLogical)
+ || ((regionDescriptor->RegionType == REGION_PRIMARY)
+ && SelectedDS[i]->CreatePrimary)))
+ {
+ Free(primarySpacesToUseOnDisk);
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+
+ //
+ // Look through the array we built to see whether we are supposed to use
+ // more than one primary partition on a given disk. For each such disk,
+ // make sure that we can actually create that many primary partitions.
+ //
+
+ for (i=0; i<DiskCount; i++)
+ {
+ //
+ // If there are not enough primary partition slots, fail.
+ //
+
+ if ((primarySpacesToUseOnDisk[i] > 1)
+ && (PARTITION_TABLE_SIZE - PartitionCount(i) < primarySpacesToUseOnDisk[i]))
+ {
+ Free(primarySpacesToUseOnDisk);
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+
+ Free(primarySpacesToUseOnDisk);
+
+ //
+ // Now actually perform the creation.
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+ FDASSERT(regionDescriptor->RegionType != REGION_EXTENDED);
+
+ CreatePartitionEx(regionDescriptor,
+ RtlConvertLongToLargeInteger(0L),
+ sizeArray[i],
+ regionDescriptor->RegionType,
+ (UCHAR)(PARTITION_HUGE | PARTITION_NTFT)
+ );
+
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ L"",
+ wszUnformatted,
+ driveLetter,
+ TRUE,
+ zero,
+ zero
+ );
+
+ DmSetPersistentRegionData(regionDescriptor, regionData);
+
+ regionArray[i] = regionDescriptor;
+ }
+
+ // The zeroth element is the one to assign the drive letter to
+
+ FdftCreateFtObjectSet(VolumeSet, regionArray, SelectionCount, FtSetNew);
+ MarkDriveLetterUsed(driveLetter);
+ CommitToAssignLetterList(&SELECTED_REGION(0), FALSE);
+ CompleteMultiRegionOperation();
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoExtendVolumeSet
+//
+// Synopsis: Adds a partition to a volume set
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoExtendVolumeSet(
+ VOID
+ )
+{
+ MINMAXDLG_PARAMS params;
+ DWORD currentSize = 0,
+ freeSize = 0,
+ totalFreeSpaceUsed,
+ freeSpaceUsed,
+ maxTotalSize = 0,
+ newSize = 0,
+ sizeTemp;
+ DWORD sizeArray[MAX_MEMBERS_IN_FT_SET];
+ ULONG nonFtPartitionCount = 0,
+ freeRegionCount = 0;
+ PULONG primarySpacesToUseOnDisk;
+ WCHAR driveLetter = L' ';
+ PWSTR typeName = NULL;
+ PWSTR volumeLabel = NULL;
+ ULONG i;
+ DWORD ec;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PREGION_DESCRIPTOR newRegionArray[MAX_MEMBERS_IN_FT_SET];
+ PREGION_DESCRIPTOR convertedRegion;
+ PPERSISTENT_REGION_DATA regionData;
+ PFT_OBJECT_SET ftSet = NULL;
+
+
+ // Make sure that the volume set does not include any
+ // partitions on removable media.
+ //
+ for (i=0; i<SelectionCount; i++)
+ {
+ if (IsDiskRemovable[SELECTED_REGION(i).Disk])
+ {
+ ErrorDialog(MSG_NO_REMOVABLE_IN_VOLUMESET);
+ return;
+ }
+ }
+
+
+ // First, determine the current size of the volume set,
+ // it's file system type and associated drive letter,
+ // and the size of the selected free space
+ //
+ for (i = 0; i < SelectionCount; i++)
+ {
+ regionDescriptor = &(SELECTED_REGION(i));
+
+ sizeTemp = regionDescriptor->SizeMB;
+ sizeArray[i] = sizeTemp;
+ maxTotalSize += sizeTemp;
+
+ if (regionDescriptor->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ // This region is a chunk of free space; include it
+ // in the free space tallies.
+ //
+ newRegionArray[freeRegionCount] = regionDescriptor;
+ sizeArray[freeRegionCount] = sizeTemp;
+
+ freeRegionCount++;
+ freeSize += sizeTemp;
+
+ }
+ else if (NULL != GET_FT_OBJECT(regionDescriptor))
+ {
+ // This is an element of an existing volume set.
+ //
+ currentSize += sizeTemp;
+
+ if (ftSet == NULL)
+ {
+ DetermineRegionInfo( regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetter
+ );
+
+ ftSet = GET_FT_OBJECT(regionDescriptor)->Set;
+ }
+ }
+ else
+ {
+ // This is a non-FT partition.
+ //
+ nonFtPartitionCount++;
+ DetermineRegionInfo(regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetter);
+ currentSize = sizeTemp;
+ convertedRegion = regionDescriptor;
+ }
+ }
+
+ // Check for consistency: the selection must have either a volume
+ // set or a partition, but not both, and cannot have more than
+ // one non-FT partition.
+ //
+ if ( nonFtPartitionCount > 1
+ || (ftSet != NULL && nonFtPartitionCount != 0)
+ || (ftSet == NULL && nonFtPartitionCount == 0 ) )
+ {
+ return;
+ }
+
+
+ if ( nonFtPartitionCount != 0
+ && NO_ERROR != (ec = DeletionIsAllowed(convertedRegion)) )
+ {
+ // If the error-message is delete-specific, remap it.
+ //
+ switch (ec)
+ {
+#if i386
+ case MSG_CANT_DELETE_ACTIVE0:
+ ec = MSG_CANT_EXTEND_ACTIVE0;
+ break;
+#endif
+ case MSG_CANT_DELETE_WINNT:
+ ec = MSG_CANT_EXTEND_WINNT;
+ break;
+
+ default:
+ break;
+ }
+
+ ErrorDialog(ec);
+ return;
+ }
+
+ if (lstrcmp(typeName, L"NTFS") != 0)
+ {
+ ErrorDialog(MSG_EXTEND_VOLSET_MUST_BE_NTFS);
+ return;
+ }
+
+ params.CaptionStringID = IDS_EXPVSET_CAPTION;
+ params.MinimumStringID = IDS_CRTVSET_MIN;
+ params.MaximumStringID = IDS_CRTVSET_MAX;
+ params.SizeStringID = IDS_CRTVSET_SIZE;
+ params.MinSizeMB = currentSize + freeRegionCount;
+ params.MaxSizeMB = maxTotalSize;
+ params.HelpContextId = HC_DM_DLG_EXTENDVOLUMESET;
+
+ newSize = DialogBoxParam(g_hInstance,
+ MAKEINTRESOURCE(IDD_MINMAX),
+ g_hwndFrame,
+ MinMaxDlgProc,
+ (LPARAM)&params
+ );
+
+ if (!newSize) // user cancelled
+ {
+ return;
+ }
+
+ SetCursor(g_hCurWait);
+
+ // Determine how large to make each new member of the volume
+ // set. The percentage of free space to use is the ratio of
+ // the amount by which the volume set will grow to the total
+ // free space.
+ //
+ freeSpaceUsed = newSize - currentSize;
+ totalFreeSpaceUsed = 0;
+
+ for (i = 0; i < freeRegionCount; i++)
+ {
+ sizeArray[i] = (DWORD)((LONGLONG)sizeArray[i] * freeSpaceUsed/freeSize);
+ if ( (DWORD)(((LONGLONG)sizeArray[i]*freeSpaceUsed) % freeSize) )
+ {
+ sizeArray[i]++;
+ }
+
+ if (sizeArray[i] == 0)
+ {
+ sizeArray[i]++;
+ }
+
+ totalFreeSpaceUsed += sizeArray[i];
+ }
+
+ // Make sure that the total amount of free space used is not
+ // greater than the amount available. Note that this loop is
+ // certain to terminate because the amount of free space used
+ // is >= the number of free regions, so this loop will exit
+ // if one megabyte is used in each free region (the degenerate
+ // case).
+ //
+ while (totalFreeSpaceUsed > freeSize)
+ {
+ for (i = 0;
+ (i < freeRegionCount) && (totalFreeSpaceUsed > freeSize);
+ i++)
+ {
+ if (sizeArray[i] > 1)
+ {
+ sizeArray[i]--;
+ totalFreeSpaceUsed--;
+ }
+ }
+ }
+
+ //
+ // Make sure that we are allowed to create a partition in the space.
+ //
+ // This is tricky because a volume set could contain more than one
+ // primary partition on a disk -- which means that if we're not careful
+ // we could create a disk with more than 4 primary partitions!
+ //
+
+ primarySpacesToUseOnDisk = (PULONG)Malloc(DiskCount * sizeof(ULONG));
+ RtlZeroMemory(primarySpacesToUseOnDisk, DiskCount * sizeof(ULONG));
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &SELECTED_REGION(i);
+
+ if (regionDescriptor->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ FDASSERT(regionDescriptor->RegionType != REGION_EXTENDED);
+
+ if (regionDescriptor->RegionType == REGION_PRIMARY)
+ {
+ primarySpacesToUseOnDisk[SelectedDS[i]->Disk]++;
+ }
+
+ if (!( ((regionDescriptor->RegionType == REGION_LOGICAL)
+ && SelectedDS[i]->CreateLogical)
+ || ((regionDescriptor->RegionType == REGION_PRIMARY)
+ && SelectedDS[i]->CreatePrimary)))
+ {
+ Free(primarySpacesToUseOnDisk);
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+ }
+
+ //
+ // Look through the array we built to see whether we are supposed to use
+ // more than one primary partition on a given disk. For each such disk,
+ // make sure that we can actually create that many primary partitions.
+ //
+
+ for (i=0; i<DiskCount; i++)
+ {
+ //
+ // If there are not enough primary partition slots, fail.
+ //
+
+ if ((primarySpacesToUseOnDisk[i] > 1)
+ && (PARTITION_TABLE_SIZE - PartitionCount(i) < primarySpacesToUseOnDisk[i]))
+ {
+ Free(primarySpacesToUseOnDisk);
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+
+ Free(primarySpacesToUseOnDisk);
+
+ //
+ // Now actually perform the creation.
+ //
+
+ for (i=0; i<freeRegionCount; i++)
+ {
+ regionDescriptor = newRegionArray[i];
+ FDASSERT(regionDescriptor->RegionType != REGION_EXTENDED);
+
+ CreatePartitionEx( regionDescriptor,
+ RtlConvertLongToLargeInteger(0L),
+ sizeArray[i],
+ regionDescriptor->RegionType,
+ (UCHAR)(PARTITION_IFS | PARTITION_NTFT)
+ );
+
+ LARGE_INTEGER zero;
+ zero.QuadPart = 0;
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ volumeLabel,
+ typeName,
+ driveLetter,
+ TRUE,
+ zero,
+ zero
+ );
+
+ DmSetPersistentRegionData(regionDescriptor, regionData);
+ }
+
+ //
+ // Set the "NewRegion" flag of all the existing partitions to TRUE,
+ // so they get grayed out: we can't perform file system operations on
+ // this volume.
+ //
+
+ if (ftSet)
+ {
+ //
+ // An existing FT set is being expanded
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionDescriptor = &(SELECTED_REGION(i));
+
+ if (GET_FT_OBJECT(regionDescriptor))
+ {
+ //
+ // this region is part of an FT volume set
+ //
+
+ PERSISTENT_DATA(regionDescriptor)->NewRegion = TRUE;
+ }
+ }
+ }
+ else
+ {
+ //
+ // A single-partition volume is to be converted to a volume set
+ // before being expanded
+ //
+
+ PERSISTENT_DATA(convertedRegion)->NewRegion = TRUE;
+ }
+
+ if (nonFtPartitionCount != 0)
+ {
+ // Create the volume set so we can extend it
+ //
+ FdftCreateFtObjectSet(VolumeSet, &convertedRegion, 1, FtSetExtended);
+ ftSet = GET_FT_OBJECT(convertedRegion)->Set;
+
+ // Set the converted region's partition System Id to indicate
+ // that it is now part of a volume set.
+ //
+ SetSysID2(convertedRegion, (UCHAR)(convertedRegion->SysID | PARTITION_NTFT));
+ }
+
+ CommitDueToExtended = TRUE;
+ FdftExtendFtObjectSet(ftSet, newRegionArray, freeRegionCount);
+ CompleteMultiRegionOperation();
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoRecoverStripe
+//
+// Synopsis: Using the global selection information this routine will
+// set up a stripe with parity such that a problem member is
+// regenerated. This new member may either be the problem member
+// (i.e. regeneration is "in place") or new free space on a
+// different disk.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoRecoverStripe(
+ VOID
+ )
+{
+ PREGION_DESCRIPTOR freeSpaceRegion = NULL;
+ PREGION_DESCRIPTOR unhealthyRegion = NULL;
+ ULONG freeSpaceIndex = 0;
+ ULONG i;
+ PREGION_DESCRIPTOR regionArray[MAX_MEMBERS_IN_FT_SET];
+ LARGE_INTEGER minimumSize;
+ PFT_OBJECT ftObject;
+
+ // Initialize minimumSize to the maximum possible positive value
+
+ minimumSize.HighPart = 0x7FFFFFFF;
+ minimumSize.LowPart = 0xFFFFFFFF;
+
+ FDASSERT(SelectionCount > 1);
+ FDASSERT(SelectionCount <= MAX_MEMBERS_IN_FT_SET);
+
+ if ( !IsRegionCommitted(&SELECTED_REGION(0))
+ && !IsRegionCommitted(&SELECTED_REGION(1)))
+ {
+ ErrorDialog(MSG_NOT_COMMITTED);
+ return;
+ }
+
+ SetCursor(g_hCurWait);
+
+ //
+ // Determine the exact size of the smallest member of the stripe set.
+ // If the user is regenerating using an additional free space, this
+ // will be the size requirement for the free space.
+ // Also find the free space (if any).
+ // If there is no free space, then we're doing an 'in-place' recover
+ // (ie regnerating into the unhealthy member). If there is a free space,
+ // make sure we are allowed to create a partition or logical drive in it.
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ regionArray[i] = &SELECTED_REGION(i);
+
+ FDASSERT(!IsExtended(regionArray[i]->SysID));
+
+ if (regionArray[i]->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ PDISKSTATE diskState;
+
+ FDASSERT(freeSpaceRegion == NULL);
+
+ freeSpaceRegion = regionArray[i];
+ freeSpaceIndex = i;
+
+ //
+ // Make sure we are allowed to create a partition or logical
+ // drive in the selected free space.
+ //
+
+ diskState = SelectedDS[freeSpaceIndex];
+
+ if (!( ((freeSpaceRegion->RegionType == REGION_LOGICAL)
+ && diskState->CreateLogical)
+ || ((freeSpaceRegion->RegionType == REGION_PRIMARY)
+ && diskState->CreatePrimary)))
+ {
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_CRTSTRP_FULL);
+ return;
+ }
+ }
+ else
+ {
+ LARGE_INTEGER largeTemp;
+
+ largeTemp = FdGetExactSize(regionArray[i], FALSE);
+ if (largeTemp.QuadPart < minimumSize.QuadPart)
+ {
+ minimumSize = largeTemp;
+ }
+
+ if (GET_FT_OBJECT(regionArray[i])->State != Healthy)
+ {
+ FDASSERT(unhealthyRegion == NULL);
+ unhealthyRegion = regionArray[i];
+ }
+ }
+ }
+
+ //
+ // If there is a free space, place it at item 0 of the regionArray array
+ // to simplify processing later.
+ //
+
+ if (NULL != freeSpaceRegion)
+ {
+ PREGION_DESCRIPTOR tempRegion = regionArray[0];
+ regionArray[0] = regionArray[freeSpaceIndex];
+ regionArray[freeSpaceIndex] = tempRegion;
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ //
+ // Get a pointer to the FT object for the broken member. Can't do this
+ // in the loop above because the broken member might be on an off-line
+ // disk.
+ //
+
+ for (ftObject = GET_FT_OBJECT(regionArray[i])->Set->Members;
+ NULL != ftObject;
+ ftObject = ftObject->Next)
+ {
+ if (ftObject->State != Healthy)
+ {
+ break;
+ }
+ }
+ FDASSERT(NULL != ftObject);
+
+ //
+ // Determine if the action is allowed.
+ //
+
+ if (NULL != ftObject->Set)
+ {
+ switch (ftObject->Set->Status)
+ {
+ case FtSetInitializing:
+ case FtSetRegenerating:
+
+ ErrorDialog(MSG_CANT_REGEN_INITIALIZING_SET);
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ if (NULL != freeSpaceRegion)
+ {
+ PPERSISTENT_REGION_DATA regionData, regionDataTemp;
+ LARGE_INTEGER temp;
+
+ //
+ // Make sure the free space region is large enough.
+ //
+
+ temp = FdGetExactSize(freeSpaceRegion, FALSE);
+ if (temp.QuadPart < minimumSize.QuadPart)
+ {
+ SetCursor(g_hCurNormal);
+ ErrorDialog(MSG_NOT_LARGE_ENOUGH_FOR_STRIPE);
+ return;
+ }
+
+ //
+ // Create the new partition.
+ //
+
+ CreatePartitionEx(freeSpaceRegion,
+ minimumSize,
+ 0,
+ freeSpaceRegion->RegionType,
+ regionArray[1]->SysID
+ );
+
+ //
+ // Set up the new partition's persistent data
+ //
+
+ regionDataTemp = PERSISTENT_DATA(regionArray[1]);
+
+ regionData = DmAllocatePersistentData(
+ NULL,
+ regionDataTemp->VolumeLabel,
+ regionDataTemp->TypeName,
+ regionDataTemp->DriveLetter,
+ TRUE,
+ regionDataTemp->FreeSpaceInBytes,
+ regionDataTemp->TotalSpaceInBytes
+ );
+
+ regionData->FtObject = ftObject;
+
+ DmSetPersistentRegionData(freeSpaceRegion, regionData);
+
+ // Check to see if member zero of the set changed and
+ // the drive letter needs to move.
+
+ if (0 == ftObject->MemberIndex)
+ {
+ // Move the drive letter to the new region descriptor.
+
+ CommitToAssignLetterList(freeSpaceRegion, TRUE);
+ }
+
+ //
+ // If the unhealthy member is on-line, delete it.
+ // Otherwise remove it from the off-line disk.
+ //
+
+ if (NULL != unhealthyRegion)
+ {
+ DmFreePersistentData(PERSISTENT_DATA(unhealthyRegion));
+ DmSetPersistentRegionData(unhealthyRegion, NULL);
+ DeletePartition(unhealthyRegion);
+ }
+
+ // Remove any offline disks - this doesn't really delete the set
+
+ FdftDeleteFtObjectSet(ftObject->Set, TRUE);
+ }
+
+ ftObject->Set->Ordinal = FdftNextOrdinal(StripeWithParity);
+ ftObject->State = Regenerating;
+ ftObject->Set->Status = FtSetRecovered;
+ RegistryChanged = TRUE;
+ CompleteMultiRegionOperation();
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoRefresh
+//
+// Synopsis: Reload the persistent volume data for all regions
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 7-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DoRefresh(
+ VOID
+ )
+{
+ SetCursor(g_hCurWait);
+
+ InitVolumeInformation();
+ RefreshAllCdRomData();
+
+ //
+ // Now refresh the view. It is likely that the free space and %free
+ // numbers have changed, so refreshing the listview makes sense.
+ // Refreshing the disks view makes sense if the user has done a
+ // format and wants to see the new label/FS.
+ //
+
+ RefreshBothViews();
+ AdjustMenuAndStatus();
+
+ SetCursor(g_hCurNormal);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RefreshBothViews
+//
+// Synopsis: Redraws both views
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 7-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+RefreshBothViews(
+ VOID
+ )
+{
+ FillListView(TRUE); // Volumes view
+ TotalRedrawAndRepaint(); // Disks view
+ UpdateStatusBarDisplay();
+}
diff --git a/private/utils/windisk/src/ops.hxx b/private/utils/windisk/src/ops.hxx
new file mode 100644
index 000000000..0f5426d3a
--- /dev/null
+++ b/private/utils/windisk/src/ops.hxx
@@ -0,0 +1,114 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ops.hxx
+//
+// Contents: Main operations: Create partition, etc.
+//
+// History: 4-Mar-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __OPS_HXX__
+#define __OPS_HXX__
+
+////////////////////////////////////////////////////////////////////////////
+
+VOID
+CompleteSingleRegionOperation(
+ IN PDISKSTATE DiskState
+ );
+
+VOID
+CompleteMultiRegionOperation(
+ VOID
+ );
+
+VOID
+CompleteDriveLetterChange(
+ IN WCHAR NewDriveLetter
+ );
+
+VOID
+DoSetDriveLetter(
+ VOID
+ );
+
+VOID
+DoCreate(
+ IN REGION_TYPE CreationType
+ );
+
+VOID
+DoDelete(
+ VOID
+ );
+
+VOID
+DoMakeActive(
+ VOID
+ );
+
+VOID
+DoProtectSystemPartition(
+ VOID
+ );
+
+VOID
+DoEstablishMirror(
+ VOID
+ );
+
+VOID
+DoBreakMirror(
+ VOID
+ );
+
+VOID
+DoBreakAndDeleteMirror(
+ VOID
+ );
+
+VOID
+DoCreateStripe(
+ IN BOOL Parity
+ );
+
+VOID
+DoDeleteStripe(
+ VOID
+ );
+
+VOID
+DoCreateVolumeSet(
+ VOID
+ );
+
+VOID
+DoExtendVolumeSet(
+ VOID
+ );
+
+VOID
+DoDeleteVolumeSet(
+ VOID
+ );
+
+VOID
+DoRecoverStripe(
+ VOID
+ );
+
+VOID
+DoRefresh(
+ VOID
+ );
+
+VOID
+RefreshBothViews(
+ VOID
+ );
+
+#endif // __OPS_HXX__
diff --git a/private/utils/windisk/src/popup.cxx b/private/utils/windisk/src/popup.cxx
new file mode 100644
index 000000000..e51767bc7
--- /dev/null
+++ b/private/utils/windisk/src/popup.cxx
@@ -0,0 +1,96 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: popup.cxx
+//
+// Contents: Implementation of popup menu functions.
+//
+// Functions: TrackModalPopupMenu
+//
+// History: 16-Aug-93 BruceFo Created from JohnEls code
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "popup.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrackModalPopupMenu, public
+//
+// Synopsis: Displays a popup menu and returns the user's choice.
+//
+// Arguments: [hMenu] -- The popup menu to display.
+// [dwFlags] -- Flags (see flags for [TrackPopupMenu()].
+// [x], [y] -- Menu position, in screen coordinates.
+// [nReserved] -- Reserved. Must be 0.
+// [lpReserved] -- Reserved. Must be NULL.
+//
+// Returns: The ID corresponding to the menu item chosen by the user.
+// If the user cancels the menu, -1 is returned. If the
+// attempt to display the menu fails, -2 is returned.
+//
+// History: 05-Mar-92 JohnEls Created.
+//
+//--------------------------------------------------------------------------
+
+INT
+TrackModalPopupMenu(
+ HMENU hMenu,
+ UINT dwFlags,
+ int x,
+ int y,
+ int nReserved,
+ LPRECT prc
+ )
+{
+ INT ret;
+
+ if (TrackPopupMenu(
+ hMenu,
+ dwFlags,
+ x,
+ y,
+ nReserved,
+ g_hwndFrame,
+ prc))
+ {
+ MSG msg;
+
+ //
+ // Look for a WM_COMMAND message in the queue. If there is none,
+ // then the user cancelled the menu.
+ //
+
+ if (PeekMessage(
+ &msg,
+ g_hwndFrame,
+ WM_COMMAND,
+ WM_COMMAND,
+ PM_NOREMOVE | PM_NOYIELD))
+ {
+ ret = LOWORD(msg.wParam);
+ }
+ else
+ {
+ ret = -1;
+ }
+ }
+ else
+ {
+ //
+ // Failed to display the menu.
+ //
+
+ ret = -2;
+ }
+
+ return ret;
+}
diff --git a/private/utils/windisk/src/popup.hxx b/private/utils/windisk/src/popup.hxx
new file mode 100644
index 000000000..65e3acbcf
--- /dev/null
+++ b/private/utils/windisk/src/popup.hxx
@@ -0,0 +1,29 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: popup.hxx
+//
+// Contents: Declaration of popup menu functions.
+//
+// History: 16-Aug-93 BruceFo Created from JohnEls code
+//
+//--------------------------------------------------------------------------
+
+#ifndef __POPUP_HXX__
+#define __POPUP_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+INT
+TrackModalPopupMenu(
+ IN HMENU hMenu,
+ IN UINT dwFlags,
+ IN int x,
+ IN int y,
+ IN int nReserved,
+ IN LPRECT prc
+ );
+
+#endif // __POPUP_HXX__
diff --git a/private/utils/windisk/src/print.cxx b/private/utils/windisk/src/print.cxx
new file mode 100644
index 000000000..105cdc515
--- /dev/null
+++ b/private/utils/windisk/src/print.cxx
@@ -0,0 +1,338 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: print.cxx
+//
+// Contents: Disk Administrator file system extension class. Code to
+// print the results of chkdsk.
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <ctype.h>
+#include <commdlg.h>
+
+#include "resids.h"
+#include "dialogs.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL CALLBACK
+PrintDlgProc(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ );
+
+BOOL CALLBACK
+AbortProc(
+ HDC hPrinterDC,
+ int iError
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL bUserAbort ;
+HWND hDlgPrint ;
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintDlgProc
+//
+// Synopsis: the "Printing..." w/ cancel button dialog box
+//
+// Arguments: standard DialogProc
+//
+// Returns: standard DialogProc
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CALLBACK
+PrintDlgProc(
+ HWND hDlg,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+ )
+{
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
+ return TRUE;
+
+ case WM_COMMAND:
+ bUserAbort = TRUE;
+ EnableWindow(GetParent(hDlg), TRUE);
+ DestroyWindow(hDlg);
+ hDlgPrint = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: AbortProc
+//
+// Synopsis: Abort procedure for the print code
+//
+// Arguments: standard AbortProc
+//
+// Returns: standard AbortProc
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CALLBACK
+AbortProc(
+ HDC hPrinterDC,
+ int iError
+ )
+{
+ MSG msg ;
+
+ while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg))
+ {
+ TranslateMessage (&msg) ;
+ DispatchMessage (&msg) ;
+ }
+ }
+ return !bUserAbort ;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrintString
+//
+// Synopsis: Prints a null-terminated string to the printer
+//
+// Arguments: [hwndParent] -- handle to parent window
+// [Buf] -- buffer to print
+//
+// Returns: TRUE on success, FALSE on failure
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+PrintString(
+ HWND hwndParent,
+ LPSTR Buf
+ )
+{
+ static PRINTDLG pd;
+
+ PCHAR pCurrent;
+ PCHAR pCurrentPage;
+ INT nCharsThisLine;
+
+ BOOL bSuccess ;
+ WCHAR szJobName [60] ;
+ PSTR pstrBuffer ;
+ INT yChar, nCharsPerLine, nLinesPerPage, nPage, nLine;
+ TEXTMETRIC tm ;
+ WORD nColCopy, nNonColCopy ;
+ DOCINFO di;
+
+ //////////////////////////////////////////////////////////////////
+
+ pd.lStructSize = sizeof (PRINTDLG) ;
+ pd.hwndOwner = hwndParent ;
+ pd.hDevMode = NULL ;
+ pd.hDevNames = NULL ;
+ pd.hDC = NULL ;
+ pd.Flags = PD_ALLPAGES
+ | PD_DISABLEPRINTTOFILE
+ | PD_NOPAGENUMS
+ | PD_NOSELECTION
+ | PD_COLLATE
+ | PD_RETURNDC
+ ;
+
+ pd.nFromPage = 0 ;
+ pd.nToPage = 0 ;
+ pd.nMinPage = 0 ;
+ pd.nMaxPage = 0 ;
+ pd.nCopies = 1 ;
+ pd.hInstance = NULL ;
+ pd.lCustData = 0L ;
+ pd.lpfnPrintHook = NULL ;
+ pd.lpfnSetupHook = NULL ;
+ pd.lpPrintTemplateName = NULL ;
+ pd.lpSetupTemplateName = NULL ;
+ pd.hPrintTemplate = NULL ;
+ pd.hSetupTemplate = NULL ;
+
+ if (!PrintDlg (&pd))
+ {
+ return FALSE ;
+ }
+
+ //
+ // Now print it
+ //
+
+ GetTextMetrics (pd.hDC, &tm) ;
+ yChar = tm.tmHeight + tm.tmExternalLeading ;
+ nCharsPerLine = GetDeviceCaps (pd.hDC, HORZRES) / tm.tmAveCharWidth ;
+ nLinesPerPage = GetDeviceCaps (pd.hDC, VERTRES) / yChar ;
+
+ pstrBuffer = new CHAR[nCharsPerLine + 1];
+ if (NULL == pstrBuffer)
+ {
+ return FALSE;
+ }
+
+ EnableWindow (hwndParent, FALSE) ;
+
+ bSuccess = TRUE ;
+ bUserAbort = FALSE ;
+
+ hDlgPrint = CreateDialog(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CHKPRINT),
+ hwndParent,
+ PrintDlgProc);
+
+ SetAbortProc(pd.hDC, AbortProc);
+
+ LoadString(g_hInstance, IDS_CHK_TITLE, szJobName, ARRAYLEN(szJobName));
+
+ di.cbSize = sizeof(DOCINFO);
+ di.lpszDocName = szJobName;
+ di.lpszOutput = NULL;
+
+ if (StartDoc(pd.hDC, &di) > 0)
+ {
+ for (nColCopy = 0 ;
+ nColCopy < (pd.Flags & PD_COLLATE ? pd.nCopies : 1) ;
+ nColCopy++)
+ {
+ pCurrentPage = Buf;
+
+ for (nPage = 0 ; '\0' != *pCurrentPage; nPage++)
+ {
+ for (nNonColCopy = 0 ;
+ nNonColCopy < (pd.Flags & PD_COLLATE ? 1 : pd.nCopies);
+ nNonColCopy++)
+ {
+ pCurrent = pCurrentPage;
+
+ if (SP_ERROR == StartPage(pd.hDC))
+ {
+ bSuccess = FALSE ;
+ break ;
+ }
+
+ for (nLine = 0 ;
+ '\0' != *pCurrent && nLine < nLinesPerPage ;
+ nLine++)
+ {
+ nCharsThisLine = 0;
+
+ while ( ('\0' != *pCurrent)
+ && ('\n' != *pCurrent)
+ && (nCharsThisLine < nCharsPerLine)
+ )
+ {
+ if (isprint(*pCurrent)) // only printable chars...
+ {
+ pstrBuffer[nCharsThisLine++] = *pCurrent;
+ }
+
+ pCurrent++;
+ }
+
+ if ('\n' == *pCurrent)
+ {
+ pCurrent++;
+ }
+
+ if (nCharsThisLine > 0)
+ {
+ TextOutA(
+ pd.hDC,
+ 0,
+ yChar * nLine,
+ pstrBuffer,
+ nCharsThisLine
+ );
+ }
+
+ if (bUserAbort)
+ {
+ break ;
+ }
+ }
+
+ if (SP_ERROR == EndPage(pd.hDC))
+ {
+ bSuccess = FALSE ;
+ break ;
+ }
+
+ if (bUserAbort)
+ {
+ break ;
+ }
+ }
+
+ if (!bSuccess || bUserAbort)
+ {
+ break ;
+ }
+
+ pCurrentPage = pCurrent;
+ }
+
+ if (!bSuccess || bUserAbort)
+ {
+ break ;
+ }
+ }
+ }
+ else
+ {
+ bSuccess = FALSE ;
+ }
+
+ if (bSuccess)
+ {
+ EndDoc(pd.hDC);
+ }
+
+ if (!bUserAbort)
+ {
+ EnableWindow (hwndParent, TRUE) ;
+ DestroyWindow (hDlgPrint) ;
+ }
+
+ delete[] pstrBuffer;
+ DeleteDC(pd.hDC);
+
+ return bSuccess && !bUserAbort ;
+}
diff --git a/private/utils/windisk/src/print.hxx b/private/utils/windisk/src/print.hxx
new file mode 100644
index 000000000..487bf5cb6
--- /dev/null
+++ b/private/utils/windisk/src/print.hxx
@@ -0,0 +1,23 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: print.hxx
+//
+// Contents: Print a buffer to the printer
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PRINT_HXX__
+#define __PRINT_HXX__
+
+BOOL
+PrintString(
+ HWND hwnd,
+ LPSTR Buf
+ );
+
+#endif // __PRINT_HXX__
diff --git a/private/utils/windisk/src/profile.cxx b/private/utils/windisk/src/profile.cxx
new file mode 100644
index 000000000..a87b0b458
--- /dev/null
+++ b/private/utils/windisk/src/profile.cxx
@@ -0,0 +1,598 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: profile.cxx
+//
+// Contents: Routines to read and write profile settings. Settings that
+// are saved include the window position, whether it is maximized
+// or not, iconic or not, which view is active, whether the
+// toolbar, status bar, and legend is visible, and the chosen
+// color/pattern scheme.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdio.h>
+
+#include "profile.hxx"
+#include "tb.h"
+#include "tbar.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define CURRENT_VERSION 2
+
+//////////////////////////////////////////////////////////////////////////////
+
+int ProfileWindowX,
+ ProfileWindowY,
+ ProfileWindowW,
+ ProfileWindowH;
+
+//
+// Save the delta values of the workarea, so that we can avoid the task bar.
+//
+int deltaProfileWindowX,
+ deltaProfileWindowY,
+ deltaProfileWindowW,
+ deltaProfileWindowH;
+
+BOOL ProfileIsMaximized;
+BOOL ProfileIsIconic;
+
+CHAR szMainSection[] = "Disk Administrator";
+
+CHAR szVersion[] = "Version";
+CHAR szWindowPosition[] = "WindowPosition";
+CHAR szWindowMaximized[] = "WindowMaximized";
+CHAR szWindowIconic[] = "WindowIconic";
+CHAR szWindowPosFormatString[] = "%d, %d, %d, %d";
+CHAR szWhichView[] = "WhichView";
+CHAR szToolbar[] = "Toolbar";
+CHAR szStatusBar[] = "StatusBar";
+CHAR szLegend[] = "Legend";
+CHAR szDiskSizing[] = "DiskSizing";
+CHAR szElementN[] = "Element %u Color/Pattern";
+
+CHAR szIniFile[] = "windisk.ini";
+WCHAR wszIniFile[] = L"windisk.ini";
+CHAR szIniFilePath[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\windisk.ini";
+CHAR szIniFileMapping[] = "USR:Software\\Microsoft\\Disk Administrator";
+
+CHAR szSectionLocation[] = "Software\\Microsoft\\Disk Administrator";
+
+TCHAR tszToolbarSettings[] = TEXT("Toolbar Settings");
+TCHAR tszSubKey[] = TEXT("Software\\Microsoft\\Disk Administrator");
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// In NT 3.1, NT 3.5, and NT 3.51, there was no "Version" number in the
+// profile. In NT 4.0, we introduced a version entry, which is an integer
+// only used by Disk Administrator. Here is what that version number means:
+//
+// Version # Version of NT
+// --------- -------------
+// non-existent 3.1, 3.5, or 3.51
+// 2 4.0
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// The colors/patterns values are stored in the registry in "Element N
+// Color/Pattern:". In NT before 4.0, there were 5 colors/patterns, identified
+// as follows:
+//
+// registry "element" number / NT 4.0 internal index
+//
+// 0/0 -- used primary partition
+// 1/1 -- logical drive
+// 2/2 -- stripe set
+// 3/4 -- mirror
+// 4/5 -- volume set
+//
+// In NT 4.0, there are 6 values. An additional value exists for
+// "stripe set with parity":
+//
+// 5/3 -- stripe set with parity
+//
+// This appears in the legend after "stripe set". However, to maintain
+// backwards compatibility with the registry layout for NT before 4.0, we must
+// only add element numbers to the end.
+//
+// The mapRegistryToInternal array takes as index the Color/Pattern
+// number used in the registry (from the list above), and returns the
+// internal "brush" number.
+//
+// NOTE: you can only add to the *END* of this array to maintain
+// compatibility.
+//
+
+int mapRegistryToInternal[] =
+{
+ BRUSH_USEDPRIMARY,
+ BRUSH_USEDLOGICAL,
+ BRUSH_STRIPESET,
+ BRUSH_MIRROR,
+ BRUSH_VOLUMESET,
+ BRUSH_PARITYSET
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// In NT 3.5, it was decided to drop support for undocumented hatch styles
+// of which windisk was apparently the only user, including the undocumented
+// solid hatch. However, in NT 3.1 we stored the hatch index in the user
+// profile. To avoid having things show up really weird for the user, we
+// map all stored non-supported hatches to the new solid hatch.
+//
+// The registry basically stores the BrushHatches[] array, which is an
+// array of indices into the AvailableHatches array of hatch numbers.
+//
+// NT 3.1:
+//
+// int AvailableHatches[NUM_AVAILABLE_HATCHES] =
+// {
+// 2, /* \\\\\ */
+// 3, // /////
+// 4, // +++++
+// 5, // xxxxx
+// 16, // dots
+// 14, // mini-plusses
+// 12, // denser plusses
+// 10, // even denser plusses
+// 8 // solid
+// };
+//
+// NT 3.5:
+//
+// int AvailableHatches[NUM_AVAILABLE_HATCHES] =
+// {
+// 2, /* \\\\\ */
+// 3, // /////
+// 4, // +++++
+// 5, // xxxxx
+// 6, // this appears to be solid, but isn't documented
+// };
+//
+// new:
+//
+// int AvailableHatches[NUM_AVAILABLE_HATCHES] =
+// {
+// MY_HS_FDIAGONAL, /* \\\\\ */
+// MY_HS_BDIAGONAL, // /////
+// MY_HS_CROSS, // +++++
+// MY_HS_DIAGCROSS, // xxxxx
+// MY_HS_VERTICAL, // |||||
+// MY_HS_SOLIDCLR // solid
+// };
+//
+// To convert, use the following logic:
+//
+// for hatch 'i':
+// if (there is no "Version" attribute)
+// {
+// if (i >= 4)
+// {
+// i = 5; // current index to MY_HS_SOLIDCLR
+// }
+// }
+//
+// Note that index 4 in NT 3.1 will be magically transformed from dots to
+// solid... oh well.
+//
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+SetupIniFileMapping(
+ VOID
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetupIniFileMapping
+//
+// Synopsis: Ensure the INI-file mapping exists. The mapping is only
+// set up once per session; subsequent calls are no-ops.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetupIniFileMapping(
+ VOID
+ )
+{
+ static BOOL fMappingCreated = FALSE;
+
+ if (!fMappingCreated)
+ {
+ fMappingCreated = TRUE; // don't try again if there are any errors
+
+ DWORD Disposition;
+ HKEY Key1, Key2;
+ LONG Err;
+
+ Err = RegCreateKeyExA( HKEY_LOCAL_MACHINE,
+ szIniFilePath,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &Key1,
+ &Disposition );
+
+ if (Err != ERROR_SUCCESS)
+ {
+ return;
+ }
+
+ if (Disposition == REG_CREATED_NEW_KEY)
+ {
+ //
+ // Set up the registry keys for the INI mapping.
+ //
+ // First, create the "Disk Administrator" value on the windisk.ini
+ // key, which indicates the location of the key which maps
+ // the "Disk Administrator" section.
+ //
+
+ Err = RegSetValueExA(Key1,
+ szMainSection,
+ 0,
+ REG_SZ,
+ (LPBYTE)szIniFileMapping,
+ (lstrlenA(szIniFileMapping) + 1) * sizeof(CHAR));
+
+ if (Err != ERROR_SUCCESS)
+ {
+ RegCloseKey( Key1 );
+ return;
+ }
+
+ //
+ // Now create the key to which the section mapping points:
+ //
+ Err = RegCreateKeyExA(HKEY_CURRENT_USER,
+ szSectionLocation,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_WRITE,
+ NULL,
+ &Key2,
+ &Disposition);
+
+ if (Err != ERROR_SUCCESS)
+ {
+ RegCloseKey(Key1);
+ return;
+ }
+
+ RegCloseKey(Key2);
+ }
+
+ //
+ // Now, we have a windisk.ini INI-file mapping. In Windows NT 3.1
+ // we have a "Disk Administrator" section mapping to
+ // HKEY_CURRENT_USER\Software\Microsoft\Disk Administrator, under
+ // which are a bunch of name/value pairs. We really should have just
+ // mapped the whole file there, which we will do now. Anything with
+ // a section name other than "Disk Administrator" will get a key under
+ // the "Disk Administrator" key, and its values go below that.
+ //
+ // We really only need to do this if the value doesn't already exist
+ // (i.e., for previous installations of NT), but it is cheaper (I think)
+ // to just do it everytime for everybody.
+ //
+
+ Err = RegSetValueExA(Key1,
+ NULL,
+ 0,
+ REG_SZ,
+ (LPBYTE)szIniFileMapping,
+ (strlen(szIniFileMapping) + 1) * sizeof(CHAR));
+
+ if (Err != ERROR_SUCCESS)
+ {
+ RegCloseKey(Key1);
+ return;
+ }
+
+ RegCloseKey(Key1);
+
+ //
+ // Now flush the ini-file mapping cache
+ //
+
+ WritePrivateProfileStringW(NULL, NULL, NULL, wszIniFile);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteProfile
+//
+// Synopsis: Write Disk Administrator settings to the registry
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+WriteProfile(
+ VOID
+ )
+{
+ CHAR text[100], text2[100];
+ int i;
+ UINT version;
+
+ SetupIniFileMapping();
+
+ version = (UINT)GetPrivateProfileIntA(szMainSection, szVersion, 0, szIniFile);
+ if (version > CURRENT_VERSION)
+ {
+ // The user has run a later version of Disk Administrator. Don't save
+ // their profile, for fear of corrupting the later version's
+ // profile structure.
+
+ return;
+ }
+
+ // OK, the registry location is set up. Write the initialization
+ // information.
+ //
+
+ wsprintfA(text, "%u", CURRENT_VERSION);
+ WritePrivateProfileStringA(szMainSection, szVersion, text, szIniFile);
+
+ // write window position
+
+ wsprintfA(text,
+ szWindowPosFormatString,
+ ProfileWindowX,
+ ProfileWindowY,
+ ProfileWindowW,
+ ProfileWindowH
+ );
+ WritePrivateProfileStringA(szMainSection, szWindowPosition, text, szIniFile);
+ wsprintfA(text, "%u", IsZoomed(g_hwndFrame));
+ WritePrivateProfileStringA(szMainSection, szWindowMaximized, text, szIniFile);
+ wsprintfA(text, "%u", IsIconic(g_hwndFrame));
+ WritePrivateProfileStringA(szMainSection, szWindowIconic, text, szIniFile);
+
+ //
+ // Which View
+ //
+ wsprintfA(text, "%u", g_WhichView);
+ WritePrivateProfileStringA(szMainSection, szWhichView, text, szIniFile);
+
+ //
+ // Whether disks are sized equally or proportionally
+ //
+
+ wsprintfA(text, "%u", g_DiskDisplayType);
+ WritePrivateProfileStringA(szMainSection, szDiskSizing, text, szIniFile);
+
+ // toolbar, status bar and legend stuff
+
+ wsprintfA(text, "%u", g_Toolbar);
+ WritePrivateProfileStringA(szMainSection, szToolbar, text, szIniFile);
+
+ wsprintfA(text, "%u", g_StatusBar);
+ WritePrivateProfileStringA(szMainSection, szStatusBar, text, szIniFile);
+
+ wsprintfA(text, "%u", g_Legend);
+ WritePrivateProfileStringA(szMainSection, szLegend, text, szIniFile);
+
+ // disk graph colors/patterns
+
+ for (i=0; i<LEGEND_STRING_COUNT; i++)
+ {
+ wsprintfA(text2, szElementN, i);
+
+ int iInternal = mapRegistryToInternal[i];
+
+ wsprintfA(
+ text,
+ "%u/%u",
+ BrushColors[iInternal],
+ BrushHatches[iInternal]
+ );
+
+ WritePrivateProfileStringA(szMainSection, text2, text, szIniFile);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadProfile
+//
+// Synopsis: Read Disk Administrator settings from the registry
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ReadProfile(
+ VOID
+ )
+{
+ CHAR text[100], text2[100];
+ int i;
+ UINT version;
+
+ version = (UINT)GetPrivateProfileIntA(szMainSection, szVersion, 0, szIniFile);
+ if (version > CURRENT_VERSION)
+ {
+ // The user has run a more recent version of windisk; ignore the
+ // profile, for fear of reading or writing bad values. Set defaults.
+
+ ProfileIsMaximized = FALSE;
+ ProfileIsIconic = FALSE;
+ ProfileWindowX = CW_USEDEFAULT;
+ ProfileWindowY = 0;
+ ProfileWindowW = CW_USEDEFAULT;
+ ProfileWindowH = 0;
+
+ g_WhichView = VIEW_DISKS;
+ g_DiskDisplayType = DiskProportional;
+ g_Toolbar = TRUE;
+ g_StatusBar = TRUE;
+ g_Legend = TRUE;
+
+ // BrushHatches already has a default
+
+ return;
+ }
+
+ // get the window position data
+
+ ProfileIsMaximized = GetPrivateProfileIntA(szMainSection, szWindowMaximized, 0, szIniFile);
+ ProfileIsIconic = GetPrivateProfileIntA(szMainSection, szWindowIconic , 0, szIniFile);
+
+ *text = 0;
+ if (GetPrivateProfileStringA(
+ szMainSection,
+ szWindowPosition,
+ "",
+ text,
+ ARRAYLEN(text),
+ szIniFile)
+ && *text)
+ {
+ sscanf(text,
+ szWindowPosFormatString,
+ &ProfileWindowX,
+ &ProfileWindowY,
+ &ProfileWindowW,
+ &ProfileWindowH
+ );
+
+
+ }
+ else
+ {
+ ProfileWindowX = CW_USEDEFAULT;
+ ProfileWindowY = 0;
+ ProfileWindowW = CW_USEDEFAULT;
+ ProfileWindowH = 0;
+ }
+
+ g_WhichView = (VIEW_TYPE)GetPrivateProfileIntA(szMainSection, szWhichView, VIEW_DISKS, szIniFile);
+ g_DiskDisplayType = (DISK_TYPE)GetPrivateProfileIntA(szMainSection, szDiskSizing, DiskProportional, szIniFile);
+
+ // toolbar, status bar and legend stuff
+
+ g_Toolbar = GetPrivateProfileIntA(szMainSection, szToolbar , TRUE, szIniFile);
+ g_StatusBar = GetPrivateProfileIntA(szMainSection, szStatusBar, TRUE, szIniFile);
+ g_Legend = GetPrivateProfileIntA(szMainSection, szLegend , TRUE, szIniFile);
+
+ // disk graph colors/patterns
+
+ for (i=0; i<LEGEND_STRING_COUNT; i++)
+ {
+ wsprintfA(text2, szElementN, i);
+
+ *text = 0;
+ if (GetPrivateProfileStringA(
+ szMainSection,
+ text2,
+ "",
+ text,
+ ARRAYLEN(text),
+ szIniFile)
+ && *text)
+ {
+ int iInternal = mapRegistryToInternal[i];
+ int registryHatchIndex;
+
+ sscanf(
+ text,
+ "%u/%u",
+ &BrushColors[iInternal],
+ &registryHatchIndex
+ );
+
+ // map registry hatch data as necessary
+ if (version < 2)
+ {
+ if (registryHatchIndex >= 4)
+ {
+ registryHatchIndex = 5;
+ }
+ }
+
+ BrushHatches[iInternal] = registryHatchIndex;
+ }
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SaveRestoreToolbar
+//
+// Synopsis: save or restore the toolbar
+//
+// Arguments: [bSave] -- TRUE to save the toolbar, FALSE to restore it
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SaveRestoreToolbar(
+ BOOL bSave
+ )
+{
+ SetupIniFileMapping();
+
+ TBSAVEPARAMS tbsp;
+ tbsp.hkr = HKEY_CURRENT_USER;
+ tbsp.pszSubKey = TEXT("Software\\Microsoft\\Disk Administrator");
+ tbsp.pszValueName = TEXT("Toolbar Settings");
+
+ BOOL bSuccess = Toolbar_SaveRestore(g_hwndToolbar, bSave, &tbsp);
+
+ if (!bSuccess && !bSave)
+ {
+ ResetToolbar();
+ SaveRestoreToolbar(TRUE);
+ }
+}
diff --git a/private/utils/windisk/src/profile.hxx b/private/utils/windisk/src/profile.hxx
new file mode 100644
index 000000000..ecc29a804
--- /dev/null
+++ b/private/utils/windisk/src/profile.hxx
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: profile.hxx
+//
+// Contents: Routines to load/save the profile
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PROFILE_HXX__
+#define __PROFILE_HXX__
+
+VOID
+WriteProfile(
+ VOID
+ );
+
+VOID
+ReadProfile(
+ VOID
+ );
+
+VOID
+SaveRestoreToolbar(
+ BOOL bSave
+ );
+
+#endif // __PROFILE_HXX__
diff --git a/private/utils/windisk/src/proto.hxx b/private/utils/windisk/src/proto.hxx
new file mode 100644
index 000000000..dea854fce
--- /dev/null
+++ b/private/utils/windisk/src/proto.hxx
@@ -0,0 +1,468 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: proto.hxx
+//
+// Contents: Global macros and function prototypes
+//
+// History: 7-Jan-92 TedM Created
+// 2-Feb-94 BobRi Moved arcinst definitions here
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PROTO_HXX__
+#define __PROTO_HXX__
+
+////////////////////////////////////////////////////////////////////////////
+
+//
+// Returns the i'th selected region, where 0 <= i < SelectionCount
+//
+// REGION_DESCRIPTOR
+// SELECTED_REGION(
+// IN INT i
+// );
+//
+
+#define SELECTED_REGION(i) (SelectedDS[i]->RegionArray[SelectedRG[i]])
+
+//
+// Given a drive letter (from C to Z), calculate a 0-based index to use
+// in array indexing.
+//
+// UINT
+// DriveLetterToIndex(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define DriveLetterToIndex(DriveLetter) ((DriveLetter) - L'C')
+
+//
+// BOOLEAN
+// IsLegalDriveLetter(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define IsLegalDriveLetter(DriveLetter) \
+ ( ((DriveLetter) >= L'C') && ((DriveLetter) <= L'Z') )
+
+//
+// BOOLEAN
+// IsExtraDriveLetter(
+// IN WCHAR DriveLetter
+// );
+//
+
+#define IsExtraDriveLetter(DriveLetter) \
+ ( ((DriveLetter) == NO_DRIVE_LETTER_YET) \
+ || ((DriveLetter) == NO_DRIVE_LETTER_EVER) \
+ )
+
+//
+// BOOLEAN
+// DmSignificantRegion(
+// IN PREGION_DESCRIPTOR RegionDescriptor
+// );
+//
+
+#define DmSignificantRegion(RegionDescriptor) \
+ (((RegionDescriptor)->SysID != PARTITION_ENTRY_UNUSED) \
+ && (!IsExtended((RegionDescriptor)->SysID)) \
+ && (IsRecognizedPartition((RegionDescriptor)->SysID)))
+
+//
+// VOID
+// DmSetPersistentRegionData(
+// IN PREGION_DESCRIPTOR RegionDescriptor,
+// IN PPERSISTENT_REGION_DATA RegionData
+// );
+//
+
+#define DmSetPersistentRegionData(RegionDescriptor,RegionData) \
+ FdSetPersistentData((RegionDescriptor),RegionData); \
+ (RegionDescriptor)->PersistentData = RegionData
+
+
+//
+// VOID
+// DmInitPersistentRegionData(
+// OUT PPERSISTENT_REGION_DATA RegionData,
+// IN PFT_OBJECT ftObject,
+// IN PWSTR volumeLabel,
+// IN PWSTR typeName,
+// IN WCHAR driveLetter,
+// IN BOOL newRegion,
+// IN LARGE_INTEGER freeSpaceInBytes,
+// IN LARGE_INTEGER totalSpaceInBytes
+// );
+//
+
+#if defined( DBLSPACE_ENABLED )
+#define DmInitPersistentRegionData(RegionData,ftObject,volumeLabel,typeName,driveLetter,newRegion,freeSpaceInBytes,totalSpaceInBytes) \
+ RegionData->DblSpace = NULL; \
+ RegionData->FtObject = ftObject; \
+ RegionData->VolumeLabel = volumeLabel; \
+ RegionData->TypeName = typeName; \
+ RegionData->DriveLetter = driveLetter; \
+ RegionData->NewRegion = newRegion; \
+ RegionData->FreeSpaceInBytes = freeSpaceInBytes; \
+ RegionData->TotalSpaceInBytes = totalSpaceInBytes
+#else
+#define DmInitPersistentRegionData(RegionData,ftObject,volumeLabel,typeName,driveLetter,newRegion,freeSpaceInBytes,totalSpaceInBytes) \
+ RegionData->FtObject = ftObject; \
+ RegionData->VolumeLabel = volumeLabel; \
+ RegionData->TypeName = typeName; \
+ RegionData->DriveLetter = driveLetter; \
+ RegionData->NewRegion = newRegion; \
+ RegionData->FreeSpaceInBytes = freeSpaceInBytes; \
+ RegionData->TotalSpaceInBytes = totalSpaceInBytes
+#endif // DBLSPACE_ENABLED
+
+//
+// PPERSISTENT_REGION_DATA
+// PERSISTENT_DATA(
+// IN PREGION_DESCRIPTOR RegionDescriptor
+// );
+//
+
+#define PERSISTENT_DATA(RegionDescriptor) ((PPERSISTENT_REGION_DATA)((RegionDescriptor)->PersistentData))
+
+//
+// PFT_OBJECT
+// GET_FT_OBJECT(
+// IN PREGION_DESCRIPTOR RegionDescriptor
+// );
+//
+
+#define GET_FT_OBJECT(RegionDescriptor) ((RegionDescriptor)->PersistentData ? PERSISTENT_DATA(RegionDescriptor)->FtObject : NULL)
+
+//
+// VOID
+// SET_FT_OBJECT(
+// IN PREGION_DESCRIPTOR RegionDescriptor,
+// IN PFT_OBJECT ftObject
+// );
+//
+
+#define SET_FT_OBJECT(RegionDescriptor,ftObject) (PERSISTENT_DATA(RegionDescriptor)->FtObject = ftObject)
+
+//
+// ULONG
+// EC(
+// IN NTSTATUS Status
+// );
+//
+
+#define EC(Status) RtlNtStatusToDosError(Status)
+
+#if 0
+
+//
+// Macros to convert between WCHARs and CHARs for a specific range.
+// These are used to handle drive letters. For both APIs, the argument
+// character must be in the range of ASCII characters.
+//
+
+//
+// CHAR
+// WcharToChar(
+// IN WCHAR wch
+// );
+//
+
+#define WcharToChar(wch) ((CHAR)(wch))
+
+//
+// WCHAR
+// CharToWchar(
+// IN CHAR ch
+// );
+//
+
+#define CharToWchar(ch) ((WCHAR)(UCHAR)(ch))
+
+#endif // 0
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// stuff in misc.cxx
+//
+
+BOOL
+AllDisksOffLine(
+ VOID
+ );
+
+VOID
+FdShutdownTheSystem(
+ VOID
+ );
+
+int
+GetHeightFromPoints(
+ IN int Points
+ );
+
+VOID
+RetrieveAndFormatMessage(
+ IN DWORD Msg,
+ OUT LPTSTR Buffer,
+ IN DWORD BufferSize,
+ IN va_list* parglist
+ );
+
+DWORD
+CommonDialog(
+ IN DWORD MsgCode,
+ IN LPTSTR Caption,
+ IN DWORD Flags,
+ IN va_list arglist
+ );
+
+
+DWORD
+CommonDialogNoArglist(
+ IN DWORD MsgCode,
+ IN LPTSTR Caption,
+ IN DWORD Flags
+ );
+
+VOID
+ErrorDialog(
+ IN DWORD ErrorCode,
+ ...
+ );
+
+VOID
+WarningDialog(
+ IN DWORD MsgCode,
+ ...
+ );
+
+DWORD
+ConfirmationDialog(
+ IN DWORD MsgCode,
+ IN DWORD Flags,
+ ...
+ );
+
+VOID
+InfoDialogTitle(
+ IN UINT TitleId,
+ IN DWORD MsgCode,
+ ...
+ );
+
+VOID
+InfoDialog(
+ IN DWORD MsgCode,
+ ...
+ );
+
+PREGION_DESCRIPTOR
+LocateRegionForFtObject(
+ IN PFT_OBJECT FtObject
+ );
+
+VOID
+ClonePersistentData(
+ IN PREGION_DESCRIPTOR RegionFrom,
+ OUT PREGION_DESCRIPTOR RegionTo
+ );
+
+PREGION_DESCRIPTOR
+GetPersistentData(
+ IN OUT PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+VOID
+RefreshVolumeData(
+ VOID
+ );
+
+VOID
+InitVolumeInformation(
+ VOID
+ );
+
+VOID
+DetermineRegionInfo(
+ IN PREGION_DESCRIPTOR RegionDescriptor,
+ OUT PWSTR* TypeName,
+ OUT PWSTR* VolumeLabel,
+ OUT PWCHAR DriveLetter
+ );
+
+BOOL
+IsFaultTolerantRegion(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+VOID
+MyCheckMenuItem(
+ IN HMENU hMenu,
+ IN UINT idFirst,
+ IN UINT idLast,
+ IN UINT idCheckItem
+ );
+
+VOID
+MyEnableMenuItem(
+ IN HMENU hMenu,
+ IN UINT idFirst,
+ IN UINT idLast,
+ IN UINT fItemFlags
+ );
+
+VOID
+InitDrawGasGauge(
+ IN HWND hwndGauge
+ );
+
+VOID
+DrawGasGauge(
+ IN HWND hwndGauge,
+ IN HWND hwndParent,
+ IN HDC hDC,
+ IN INT PercentDone,
+ IN PWSTR Caption
+ );
+
+HFONT
+KillBold(
+ IN HWND hdlg,
+ IN PUINT aControls
+ );
+
+NTSTATUS
+LargeIntegerToUnicodeChar(
+ IN PLARGE_INTEGER Value,
+ IN ULONG Base OPTIONAL,
+ IN LONG OutputLength,
+ OUT PWSTR String
+ );
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// Debugging support for opens
+//
+
+#if DBG == 1
+
+NTSTATUS
+DmOpenFile(
+ OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG ShareAccess,
+ IN ULONG OpenOptions
+ );
+
+NTSTATUS
+DmClose(
+ IN HANDLE Handle
+ );
+
+#else
+
+#define DmOpenFile NtOpenFile
+#define DmClose NtClose
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// assertion checking, logging, from log.cxx
+//
+
+#if DBG == 1
+
+// #define FDASSERT(expr) if (!(expr)) FdiskAssertFailedRoutine(#expr,__FILE__,__LINE__);
+#define FDASSERT(expr) Win4Assert( expr )
+
+VOID
+FdiskAssertFailedRoutine(
+ IN char *Expression,
+ IN char *FileName,
+ IN int LineNumber
+ );
+
+VOID
+FDLOG_WORK(
+ IN int Level,
+ IN PCHAR FormatString,
+ ...
+ );
+
+#define FDLOG(x) FDLOG_WORK x
+
+VOID
+LOG_DISK_REGISTRY(
+ IN PCHAR RoutineName,
+ IN PDISK_REGISTRY DiskRegistry
+ );
+
+VOID
+LOG_ONE_DISK_REGISTRY_DISK_ENTRY(
+ IN PCHAR RoutineName OPTIONAL,
+ IN PDISK_DESCRIPTION DiskDescription
+ );
+
+VOID
+LOG_DRIVE_LAYOUT(
+ IN PDRIVE_LAYOUT_INFORMATION DriveLayout
+ );
+
+VOID
+LOG_ALL(
+ VOID
+ );
+
+VOID
+InitLogging(
+ VOID
+ );
+
+VOID
+EndLogging(
+ VOID
+ );
+
+#ifdef WINDISK_EXTENSIONS
+
+VOID
+PrintVolumeClaims(
+ IN CHAR DriveLetter
+ );
+
+VOID
+PrintClaims(
+ VOID
+ );
+
+#endif // WINDISK_EXTENSIONS
+
+#else // DBG == 1
+
+#define FDASSERT(expr)
+#define FDLOG(x)
+#define LOG_DISK_REGISTRY(x,y)
+#define LOG_ONE_DISK_REGISTRY_DISK_ENTRY(x,y)
+#define LOG_DRIVE_LAYOUT(x)
+#define LOG_ALL()
+
+#endif // DBG == 1
+
+#endif // __PROTO_HXX__
diff --git a/private/utils/windisk/src/ps.cxx b/private/utils/windisk/src/ps.cxx
new file mode 100644
index 000000000..7659109b8
--- /dev/null
+++ b/private/utils/windisk/src/ps.cxx
@@ -0,0 +1,205 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ps.cxx
+//
+// Contents: Property sheet functions.
+//
+// History: 28-Jul-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "genlpage.hxx"
+#include "cdpage.hxx"
+#include "ps.hxx"
+#include "cdrom.hxx"
+#include "windisk.hxx"
+
+#include "shlobj.h"
+#include "shsemip.h"
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+-------------------------------------------------------------------------
+//
+// Function: DiskPropSheet, public
+//
+// Synopsis: Create a property sheet for a disk selection
+//
+// Arguments: (none)
+//
+// Returns: nothing?
+//
+// History: 28-Jul-93 BruceFo Created
+//
+// Notes: UNDONE
+//
+//--------------------------------------------------------------------------
+
+VOID
+DiskPropSheet(
+ VOID
+ )
+{
+#ifndef WINDISK_EXTENSIONS
+ //BUGBUG: we have no default property sheets for disks, so unless there
+ // are extensions, there are no property sheets at all!
+
+ return;
+#endif // !WINDISK_EXTENSIONS
+
+#ifdef WINDISK_EXTENSIONS
+
+ daDebugOut((DEB_ITRACE,"Disk property sheet\n"));
+
+ PAGE_TYPE DiskPages = {0};
+
+ //
+ // First, determine how many pages there will be and allocate
+ // space for them
+ //
+
+ UINT cPages = 0;
+
+ PHARDDISK_CLAIM_LIST hdclaims;
+
+ hdclaims = DiskArray[LBIndexToDiskNumber(g_MouseLBIndex)]->pClaims;
+
+ if (NULL != hdclaims)
+ {
+ while (NULL != hdclaims)
+ {
+ ++cPages;
+ hdclaims = hdclaims->pNext;
+ }
+ }
+
+ if (0 == cPages)
+ {
+ daDebugOut((DEB_ITRACE,"No hard disk extension pages\n"));
+
+ return;
+ }
+
+ DiskPages.cPages = cPages; // the eventual number of pages
+ DiskPages.paPages = new PCLSID[cPages];
+
+ //
+ // add the extension items
+ //
+
+ daDebugOut((DEB_ITRACE,"Add disk pages\n"));
+
+ hdclaims = DiskArray[LBIndexToDiskNumber(g_MouseLBIndex)]->pClaims;
+
+ if (NULL != hdclaims)
+ {
+ while (NULL != hdclaims)
+ {
+ daDebugOut((DEB_ITRACE,"Adding %d pages for %ws\n",
+ hdclaims->pClaimer->pInfo->propPages.cPropPages,
+ hdclaims->pClaimer->pInfo->pwszShortName));
+
+ PropPageSetType* Pages = &hdclaims->pClaimer->pInfo->propPages;
+
+ for (INT i = 0; i < Pages->cPropPages; i++)
+ {
+ DiskPages.paPages[cPages] = Pages->aPropPages[i].pPage;
+ cPages++;
+ }
+
+ hdclaims = hdclaims->pNext;
+ }
+ }
+
+ daDebugOut((DEB_ITRACE,"Create the property sheet\n"));
+
+ DoPropSheet(&DiskPages);
+
+ delete[] DiskPages.paPages;
+
+#endif // WINDISK_EXTENSIONS
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PropSheet, public
+//
+// Synopsis: Create a property sheet. Determines which type of property
+// sheet should be displayed, based on the current selection.
+// The selection variables (SelectionCount, SelectDS, SelectRG)
+// must be valid.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 28-Jul-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+PropSheet(
+ VOID
+ )
+{
+
+ //
+ // The selection is already determined when we call this function
+ //
+
+#ifdef WINDISK_EXTENSIONS
+ if (DiskSelected) {
+ DiskPropSheet();
+ return;
+ }
+#endif // WINDISK_EXTENSIONS
+
+ if (0 == (SelectionCount + CdRomSelectionCount)) {
+ return; // nothing selected, so no property sheet
+ }
+
+ if (CdRomSelected) {
+
+ PCDROM_DESCRIPTOR cdrom;
+ ULONG i;
+ WCHAR rootDirectory[5];
+
+ for (i = 0; i < CdRomCount; i++) {
+ cdrom = CdRomFindDevice(i);
+ if (cdrom->Selected) {
+
+ rootDirectory[0] = cdrom->DriveLetter;
+ rootDirectory[1] = ':';
+ rootDirectory[2] = '\\';
+ rootDirectory[3] = 0;
+
+ SHObjectProperties(g_hwndFrame, SHOP_FILEPATH,
+ rootDirectory, TEXT("General"));
+ break;
+ }
+ }
+
+ } else if (SingleVolumeSelected()) {
+
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ WCHAR driveLetter = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+ WCHAR rootDirectory[5];
+ FDASSERT(NULL != regionDescriptor);
+
+ rootDirectory[0] = driveLetter;
+ rootDirectory[1] = ':';
+ rootDirectory[2] = '\\';
+ rootDirectory[3] = 0;
+
+ SHObjectProperties(g_hwndFrame, SHOP_FILEPATH,
+ rootDirectory, TEXT("General"));
+ }
+}
diff --git a/private/utils/windisk/src/ps.hxx b/private/utils/windisk/src/ps.hxx
new file mode 100644
index 000000000..4f972e24c
--- /dev/null
+++ b/private/utils/windisk/src/ps.hxx
@@ -0,0 +1,22 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ps.hxx
+//
+// Contents: Property sheet functions
+//
+// History: 17-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PS_HXX__
+#define __PS_HXX__
+
+VOID
+PropSheet(
+ VOID
+ );
+
+#endif // __PS_HXX__
diff --git a/private/utils/windisk/src/rect.cxx b/private/utils/windisk/src/rect.cxx
new file mode 100644
index 000000000..9eb265678
--- /dev/null
+++ b/private/utils/windisk/src/rect.cxx
@@ -0,0 +1,310 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rect.cxx
+//
+// Contents: Rectangle custom control: pattern or color
+//
+// History: 7-Oct-94 BruceFo Created from old windisk source
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "dialogs.h"
+#include "dlgs.hxx"
+#include "rectpriv.hxx"
+
+////////////////////////////////////////////////////////////////////////////
+
+#define RECT_CONTROL_WNDEXTRA 4
+#define GWW_SELECTED 0
+
+////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK
+RectWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+////////////////////////////////////////////////////////////////////////////
+
+//+-------------------------------------------------------------------------
+//
+// Function: RectWndProc
+//
+// Synopsis: The rectangle custom control window procedure
+//
+// Arguments: standard WndProc
+//
+// Returns: standard WndProc
+//
+//--------------------------------------------------------------------------
+
+LRESULT CALLBACK
+RectWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (msg)
+ {
+ case WM_CREATE:
+
+ daAssert(GetWindowLong(hwnd, GWL_STYLE) & (RS_PATTERN | RS_COLOR));
+ SetWindowWord(hwnd, GWW_SELECTED, FALSE);
+ break;
+
+ case WM_LBUTTONDOWN:
+
+ SetFocus(hwnd);
+ break;
+
+ case WM_GETDLGCODE:
+ return DLGC_WANTARROWS;
+
+ case WM_KEYDOWN:
+ {
+ INT nVirtKey = (int)wParam;
+ INT rows;
+ INT columns;
+ INT x;
+ INT y;
+ INT ctrlId = GetDlgCtrlID(hwnd);
+ BOOL isColorControl = GetWindowLong(hwnd, GWL_STYLE) & RS_COLOR;
+
+ if (isColorControl)
+ {
+ rows = 4; // 4x4 for colors
+ columns = 4;
+ x = (ctrlId - IDC_COLOR1) / rows;
+ y = (ctrlId - IDC_COLOR1) % rows;
+ }
+ else
+ {
+ rows = 3; // 2x3 for patterns
+ columns = 2;
+ x = (ctrlId - IDC_PATTERN1) / rows;
+ y = (ctrlId - IDC_PATTERN1) % rows;
+ }
+
+ switch (nVirtKey)
+ {
+ case VK_LEFT:
+ if (x > 0)
+ {
+ --x;
+ }
+ break;
+
+ case VK_UP:
+ if (y > 0)
+ {
+ --y;
+ }
+ break;
+
+ case VK_RIGHT:
+ if (x < columns - 1)
+ {
+ ++x;
+ }
+ break;
+
+ case VK_DOWN:
+ if (y < rows - 1)
+ {
+ ++y;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SetFocus(GetDlgItem(
+ GetParent(hwnd),
+ (isColorControl ? IDC_COLOR1 : IDC_PATTERN1)
+ + x * rows + y));
+ break;
+ }
+
+ case WM_SETFOCUS:
+
+ SendMessage(
+ GetParent(hwnd),
+ WM_COMMAND,
+ MAKEWPARAM(GetDlgCtrlID(hwnd), RN_CLICKED),
+ (LPARAM)hwnd);
+ break;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rc;
+ int controlID;
+ HBRUSH hbr, hbrT;
+
+ BeginPaint(hwnd, &ps);
+
+ GetClientRect(hwnd, &rc);
+ controlID = GetDlgCtrlID(hwnd);
+
+#if (WINVER >= 0x0400)
+ DWORD windowColor = GetSysColor(COLOR_BTNFACE);
+#else
+ DWORD windowColor = GetSysColor(COLOR_COLORWINDOW);
+#endif
+
+ hbr = CreateSolidBrush(
+ GetWindowWord(hwnd, GWW_SELECTED)
+ ? (~windowColor) & 0xffffff
+ : windowColor
+ );
+
+ hbrT = SelectBrush(ps.hdc, hbr);
+ SelectPen(ps.hdc, g_hPenNull);
+
+ Rectangle(ps.hdc, rc.left, rc.top, rc.right, rc.bottom);
+
+ if (hbrT)
+ {
+ SelectBrush(ps.hdc, hbrT);
+ }
+ DeleteBrush(hbr);
+
+ InflateRect(&rc, -2, -2);
+ rc.right--;
+ rc.bottom--;
+
+ if (GetWindowLong(hwnd, GWL_STYLE) & RS_COLOR)
+ {
+ hbr = CreateSolidBrush(AvailableColors[controlID-IDC_COLOR1]);
+ }
+ else
+ {
+ DWORD currentSelection = ComboBox_GetCurSel(GetDlgItem(GetParent(hwnd), IDC_COLORDLGCOMBO));
+ hbr = MyCreateHatchBrush(
+ AvailableHatches[controlID - IDC_PATTERN1],
+ AvailableColors[SelectedColor[currentSelection] - IDC_COLOR1]);
+ }
+
+ hbrT = SelectBrush(ps.hdc, hbr);
+ SelectPen(ps.hdc, g_hPenThinSolid);
+
+ Rectangle(ps.hdc, rc.left, rc.top, rc.right, rc.bottom);
+
+ if (hbrT)
+ {
+ SelectBrush(ps.hdc, hbrT);
+ }
+
+ DeleteBrush(hbr);
+
+ EndPaint(hwnd, &ps);
+ break;
+ }
+
+ case RM_SELECT:
+ {
+ DWORD style;
+
+ // wParam = TRUE/FALSE for selected/not selected
+
+ if (GetWindowWord(hwnd, GWW_SELECTED) != (WORD)wParam)
+ {
+ SetWindowWord(hwnd, GWW_SELECTED, (WORD)wParam);
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ // make keyboard interface work correctly
+
+ style = (DWORD)GetWindowLong(hwnd, GWL_STYLE);
+ style = wParam ? style | WS_TABSTOP
+ : style & ~WS_TABSTOP;
+ SetWindowLong(hwnd, GWL_STYLE, (LONG)style);
+ }
+
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return 1;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UseRectControl
+//
+// Synopsis: Uses the Rect custom control.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: Win32 error, 0 on success
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+UseRectControl(
+ IN HINSTANCE hInstance
+ )
+{
+ WNDCLASS wc;
+
+ wc.style = 0;
+ wc.lpfnWndProc = RectWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = RECT_CONTROL_WNDEXTRA;
+ wc.hInstance = hInstance;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = RECT_CONTROL_STRING;
+
+ if (0 == RegisterClass(&wc))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseRectControl
+//
+// Synopsis: Releases the Rect custom control.
+//
+// Arguments: [hInstance] -- instance handle
+//
+// Returns: Win32 error, 0 on success
+//
+// History: 27-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+DWORD
+ReleaseRectControl(
+ IN HINSTANCE hInstance
+ )
+{
+ if (!UnregisterClass(RECT_CONTROL_STRING, hInstance))
+ {
+ return GetLastError();
+ }
+ return 0L;
+}
diff --git a/private/utils/windisk/src/rectpriv.hxx b/private/utils/windisk/src/rectpriv.hxx
new file mode 100644
index 000000000..c050a9d72
--- /dev/null
+++ b/private/utils/windisk/src/rectpriv.hxx
@@ -0,0 +1,50 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rectpriv.hxx
+//
+// Contents: Declarations for the rectangle custom control
+//
+// History: 26-Jan-94 BruceFo Created (derived from Chicago Disks tool)
+//
+//--------------------------------------------------------------------------
+
+#ifndef __RECTPRIV_HXX__
+#define __RECTPRIV_HXX__
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+// Rectangle control.
+//
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef RC_INVOKED
+
+#define RECT_CONTROL_STRING TEXT("RectControl")
+
+// notifications
+
+#define RN_CLICKED 213
+
+#endif // RC_INVOKED
+
+// window messages
+
+#define RM_SELECT WM_USER
+
+// styles (NOTE: these should be used in the
+// dialogs.dlg file, but the dialog editor strips them out and replaces
+// them with constants when it writes its data.
+
+#define RS_PATTERN 0x00000001
+#define RS_COLOR 0x00000002
+
+
+DWORD UseRectControl(IN HINSTANCE hInstance);
+DWORD ReleaseRectControl(IN HINSTANCE hInstance);
+
+#endif // __RECTPRIV_HXX__
diff --git a/private/utils/windisk/src/resids.h b/private/utils/windisk/src/resids.h
new file mode 100644
index 000000000..483a1221c
--- /dev/null
+++ b/private/utils/windisk/src/resids.h
@@ -0,0 +1,514 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: resids.h
+//
+// Contents: Resource file constants
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __RESIDS_H__
+#define __RESIDS_H__
+
+//
+// Miscellaneous: ids 100 to 199
+//
+
+#define IDFDISK 100
+
+#define ID_FRAME_ACCELERATORS 101
+
+// the disks view small disk bitmap
+
+#define IDB_SMALLDISK 102
+#define IDB_REMOVABLEDISK 103
+#define IDB_SMALLCDROM 104
+
+// toolbar buttons (bitmaps in the resource file)
+
+#define IDB_TOOLBAR 105
+#define IDB_EXTRATOOLS 106
+
+#define IDC_TOOLBAR 107
+
+#define ID_LISTBOX 108
+#define ID_LISTVIEW 109
+
+
+//
+// dialogs: ids 1000 to 1999. every 100 is a dialog
+//
+
+
+
+//
+// Menu ids: ids 2000 to 2999. every 100 is a new top-level menu
+//
+// Note: these must be in the correct order for the toolbar customization
+// code to work
+//
+
+#define IDM_FIRST_MENU 2000
+#define IDM_MENU_DELTA 100
+
+//
+// Partition menu
+//
+
+#define IDM_PARTITIONCREATE 2000
+#define IDM_PARTITIONCREATEEX 2001
+#define IDM_PARTITIONDELETE 2002
+#define IDM_FTCREATEVOLUMESET 2003
+#define IDM_FTEXTENDVOLUMESET 2004
+#define IDM_FTCREATESTRIPE 2005
+#if i386
+#define IDM_PARTITIONACTIVE 2006
+#else
+#define IDM_SECURESYSTEM 2007
+#endif
+
+//
+// Configuration sub-menu
+//
+
+#define IDM_CONFIGSAVE 2008
+#define IDM_CONFIGRESTORE 2009
+#define IDM_CONFIGMIGRATE 2010
+
+#define IDM_PARTITIONCOMMIT 2011
+#define IDM_QUIT 2012
+
+
+//
+// Fault tolerance menu (Server only)
+//
+
+#define IDM_FTESTABLISHMIRROR 2100
+#define IDM_FTBREAKMIRROR 2101
+#define IDM_FTCREATEPSTRIPE 2102
+#define IDM_FTRECOVERSTRIPE 2103
+
+//
+// Tools menu
+//
+
+#define IDM_VOL_FORMAT 2200
+#define IDM_VOL_EJECT 2201
+#define IDM_VOL_LETTER 2203
+#define IDM_VOL_DBLSPACE 2204
+#define IDM_VOL_AUTOMOUNT 2205
+#define IDM_VOL_PROPERTIES 2206
+
+//
+// View menu
+//
+
+//
+// IDM_VIEWVOLUMES must immediately precede IDM_VIEWDISKS numerically
+//
+#define IDM_VIEWVOLUMES 2300
+#define IDM_VIEWDISKS 2301
+
+#if IDM_VIEWVOLUMES != (IDM_VIEWDISKS - 1)
+#error IDM_VIEWVOLUMES must be immediately followed by IDM_VIEWDISKS!
+#endif
+
+#define IDM_VIEW_REFRESH 2302
+
+//
+// Options menu
+//
+
+#define IDM_OPTIONSTOOLBAR 2400
+#define IDM_OPTIONSSTATUS 2401
+#define IDM_OPTIONSLEGEND 2402
+#define IDM_OPTIONSCOLORS 2403
+#define IDM_OPTIONSDISK 2404
+#define IDM_OPTIONSDISPLAY 2405
+#define IDM_OPTIONSCUSTTOOLBAR 2406
+
+//
+// Help menu
+//
+
+#define IDM_HELPCONTENTS 2500
+#define IDM_HELPSEARCH 2501
+#define IDM_HELPHELP 2502
+#define IDM_HELPABOUT 2503
+
+//
+// Debug menu (debug builds only)
+//
+
+#if DBG == 1
+#define IDM_DEBUGALLOWDELETES 2600
+#define IDM_DEBUGLOG 2601
+#define IDM_RAID 2602
+#endif // DBG == 1
+
+
+#ifdef WINDISK_EXTENSIONS
+
+//
+// Reserve space for extension menu items
+//
+
+#define IDM_EXTENSION_START 2700
+#define IDM_EXTENSION_END 2799 // some # > IDM_EXTENSION_START
+
+#if IDM_EXTENSION_START > IDM_EXTENSION_END
+#error IDM_EXTENSION_START must be less than IDM_EXTENSION_END!
+#endif
+
+//
+// Reserve space for extension context-menu-only items
+//
+
+#define IDM_CONTEXT_EXTENSION_START 2800
+#define IDM_CONTEXT_EXTENSION_END 2899 // some # > IDM_CONTEXT_EXTENSION_START
+
+#if IDM_CONTEXT_EXTENSION_START > IDM_CONTEXT_EXTENSION_END
+#error IDM_CONTEXT_EXTENSION_START must be less than IDM_CONTEXT_EXTENSION_END!
+#endif
+
+#endif // WINDISK_EXTENSIONS
+
+
+//
+// Menu ids for things on context menus but not the menu bar
+//
+
+#define IDM_PROPERTIES 2900
+#define IDM_NOVALIDOPERATION 2901
+
+
+//
+// Icons: Ids 3000 to 3999
+//
+
+#define IDI_S_HARD 3000
+#define IDI_S_CDROM 3001
+// in dialogs.h: #define IDI_STOP_SIGN 3002
+
+
+//
+// strings (except menu help): Ids 4000 to 4999
+//
+
+#define IDS_APPNAME 4001
+#define IDS_MULTIPLEITEMS 4002
+#define IDS_FREESPACE 4003
+#define IDS_PARTITION 4004
+#define IDS_LOGICALVOLUME 4005
+#define IDS_DISKN 4006
+#define IDS_CONFIRM 4007
+#define IDS_NOT_IN_APP_MSG_FILE 4008
+#define IDS_NOT_IN_SYS_MSG_FILE 4009
+#define IDS_UNFORMATTED 4010
+#define IDS_UNKNOWN 4011
+#define IDS_STRIPESET 4012
+#define IDS_VOLUMESET 4013
+#define IDS_EXTENDEDPARTITION 4014
+#define IDS_FREEEXT 4015
+#define IDS_DRIVELET_DESCR 4016
+#define IDS_HEALTHY 4017
+#define IDS_BROKEN 4018
+#define IDS_RECOVERABLE 4019
+#define IDS_REGENERATED 4020
+#define IDS_NEW 4021
+#define IDS_OFFLINE 4022
+#define IDS_INSERT_DISK 4023
+#define IDS_MEGABYTES_ABBREV 4024
+#define IDS_INITIALIZING 4025
+#define IDS_REGENERATING 4026
+#define IDS_CDROMN 4027
+#define IDS_CDROM 4028
+#define IDS_DISABLED 4029
+
+#define IDS_CRTPART_CAPTION_P 4030
+#define IDS_CRTPART_CAPTION_E 4031
+#define IDS_CRTPART_CAPTION_L 4032
+#define IDS_CRTPART_MIN_P 4033
+#define IDS_CRTPART_MAX_P 4034
+#define IDS_CRTPART_MIN_L 4035
+#define IDS_CRTPART_MAX_L 4036
+#define IDS_CRTPART_SIZE_P 4037
+#define IDS_CRTPART_SIZE_L 4038
+
+#define IDS_CRTSTRP_CAPTION 4039
+#define IDS_CRTSTRP_MIN 4040
+#define IDS_CRTSTRP_MAX 4041
+#define IDS_CRTSTRP_SIZE 4042
+
+#define IDS_CRTVSET_CAPTION 4043
+#define IDS_EXPVSET_CAPTION 4044
+#define IDS_CRTVSET_MIN 4045
+#define IDS_CRTVSET_MAX 4046
+#define IDS_CRTVSET_SIZE 4047
+
+#define IDS_STATUS_STRIPESET 4048
+#define IDS_STATUS_PARITY 4049
+#define IDS_STATUS_VOLUMESET 4050
+#define IDS_STATUS_MIRROR 4051
+#define IDS_CRTPSTRP_CAPTION 4052
+#define IDS_DLGCAP_PARITY 4053
+#define IDS_DLGCAP_MIRROR 4054
+#define IDS_UNKNOWNTYPE 4055
+#define IDS_INIT_FAILED 4056
+
+#define IDS_SOURCE_PATH 4057
+#define IDS_SOURCE_PATH_NAME 4058
+
+// these must be contigous, and kept in sync with BRUSH_xxx constants
+
+#define IDS_LEGEND_FIRST IDS_LEGEND_PRIMARY
+#define IDS_LEGEND_PRIMARY 4100
+#define IDS_LEGEND_LOGICAL 4101
+#define IDS_LEGEND_STRIPESET 4102
+#define IDS_LEGEND_PARITYSET 4103
+#define IDS_LEGEND_MIRROR 4104
+#define IDS_LEGEND_VOLUMESET 4105
+#define IDS_LEGEND_LAST IDS_LEGEND_VOLUMESET
+
+
+//
+// These are the strings for system-names other than those which are
+// meaningful to NT.
+//
+#define IDS_PARTITION_FREE 4120
+#define IDS_PARTITION_XENIX1 4121
+#define IDS_PARTITION_XENIX2 4122
+#define IDS_PARTITION_OS2_BOOT 4123
+#define IDS_PARTITION_EISA 4124
+#define IDS_PARTITION_UNIX 4125
+#define IDS_PARTITION_POWERPC 4126
+
+
+#if i386
+#define IDS_ACTIVEPARTITION 4200
+#endif
+
+#define IDS_MENUANDITEM 4201
+
+//NOTE: space here
+
+#define IDS_CHANGEFORMAT 4204
+#define IDS_FORMAT 4205
+
+#define IDS_NOOPERATIONS 4206
+
+//
+// DoubleSpace support strings
+//
+
+#define IDS_DBLSPACE_DELETE 4207
+#define IDS_WITH_DBLSPACE 4208
+#define IDS_DBLSPACE_MOUNTED 4209
+#define IDS_DBLSPACE_DISMOUNTED 4210
+#define IDS_MOUNT 4211
+#define IDS_DISMOUNT 4212
+#define IDS_CREATING_DBLSPACE 4213
+#define IDS_DBLSPACECOMPLETE 4214
+
+//
+// Volume view column titles
+//
+
+#define IDS_VV_VOLUME 4250
+#define IDS_VV_NAME 4251
+#define IDS_VV_CAPACITY 4252
+#define IDS_VV_FREESPACE 4253
+#define IDS_VV_PCTFREE 4254
+#define IDS_VV_FORMAT 4255
+#define IDS_VV_FT 4256
+#define IDS_VV_VOLTYPE 4257
+#define IDS_VV_OVERHEAD 4258
+#define IDS_VV_STATUS 4259
+
+#define IDS_FMT_TITLEPROTO 4270
+
+//
+// Volume view column data strings
+//
+
+#define IDS_VOLTYPE_MIRROR 4300
+#define IDS_VOLTYPE_STRIPE 4301
+#define IDS_VOLTYPE_PARITY 4302
+#define IDS_VOLTYPE_VOLSET 4303
+#define IDS_VOLTYPE_SIMPLE 4304
+
+#define IDS_FT_YES 4310
+#define IDS_FT_NO 4311
+
+#define IDS_FTSTATUS_HEALTHY 4320
+#define IDS_FTSTATUS_NEW 4321
+#define IDS_FTSTATUS_BROKEN 4322
+#define IDS_FTSTATUS_RECOVERABLE 4323
+#define IDS_FTSTATUS_REGENERATED 4324
+#define IDS_FTSTATUS_INITIALIZING 4325
+#define IDS_FTSTATUS_REGENERATING 4326
+#define IDS_FTSTATUS_NONE 4327
+
+//
+// Miscellaneous
+//
+
+#define IDS_PROPERTIES 4900
+#define IDS_UNAVAILABLE_DATA 4901
+#define IDS_BYTES_DECORATION 4902
+#define IDS_MEG_DECORATION 4903
+#define IDS_READY 4904
+#define IDS_NOTREADY 4905
+#define IDS_NO_CONFIG_INFO 4906
+
+
+//
+// Menu help defines ids 5000 to 6999. every 100 is a new top-level menu
+//
+
+//
+// Volume menu
+//
+
+#define IDS_HELP_FORMAT 5000
+#define IDS_HELP_DRIVELET 5003
+#define IDS_HELP_DBLSPACE 5004
+#define IDS_HELP_AUTOMOUNT 5005
+#define IDS_HELP_PROPERTIES 5006
+#define IDS_HELP_QUIT 5007
+
+//
+// Partition menu
+//
+
+#define IDS_HELP_CREATE 5100
+#define IDS_HELP_CREATEEX 5101
+#define IDS_HELP_DELETE 5102
+#define IDS_HELP_CREATEVOLSET 5103
+#define IDS_HELP_EXTENDVOLSET 5104
+#define IDS_HELP_CREATESTRIPE 5105
+#ifdef i386
+#define IDS_HELP_MARKACTIVE 5106
+#else // i386
+#define IDS_HELP_SECURE 5107
+#endif // i386
+
+//
+// Configuration sub-menu
+//
+
+#define IDS_HELP_SAVECONFIG 5109
+#define IDS_HELP_RESTORECONFIG 5110
+#define IDS_HELP_SEARCHCONFIG 5111
+
+#define IDS_HELP_PARTITIONCOMMIT 5112
+
+//
+// Fault tolerance menu (Advanced Server only)
+//
+
+#define IDS_HELP_ESTABLISHMIRROR 5200
+#define IDS_HELP_BREAKMIRROR 5201
+#define IDS_HELP_CREATEPSET 5202
+#define IDS_HELP_REGENSTRIPE 5203
+
+//
+// View menu
+//
+
+#define IDS_HELP_VOLUMESVIEW 5300
+#define IDS_HELP_DISKSVIEW 5301
+#define IDS_HELP_REFRESH 5302
+
+//
+// Options menu
+//
+
+#define IDS_HELP_TOOLBAR 5400
+#define IDS_HELP_STATUSBAR 5401
+#define IDS_HELP_LEGEND 5402
+#define IDS_HELP_COLORS 5403
+#define IDS_HELP_OPTIONSDISK 5404
+#define IDS_HELP_REGIONDISPLAY 5405
+#define IDS_HELP_CUSTTOOLBAR 5406
+
+//
+// Help menu
+//
+
+#define IDS_HELP_HELPCONTENTS 5500
+#define IDS_HELP_HELPSEARCH 5501
+#define IDS_HELP_HELPHELP 5502
+#define IDS_HELP_HELPABOUT 5503
+
+//
+// Debug menu (debug builds only)
+//
+
+#if DBG == 1
+#define IDS_HELP_DELETEALL 5600
+#define IDS_HELP_LOG 5601
+#define IDS_HELP_RAID 5602
+#endif // DBG == 1
+
+//
+// Miscellaneous
+//
+
+#define IDS_HELP_NOVALIDOPERATION 5700
+
+//
+// For the menus themselves:
+//
+
+#define IDS_HELP_MENU_VOLUMES 5900
+#define IDS_HELP_MENU_PARTITION 5901
+#define IDS_HELP_MENU_FT 5902
+#define IDS_HELP_MENU_VIEW 5903
+#define IDS_HELP_MENU_OPTIONS 5904
+#define IDS_HELP_MENU_HELP 5905
+#define IDS_HELP_MENU_DEBUG 5906
+
+#define IDS_HELP_MENU_CONFIG 5907
+
+//
+// File system descriptions
+//
+
+#define IDS_LONG_FAT 6400
+#define IDS_LONG_NTFS 6401
+
+#ifdef SUPPORT_OFS
+#define IDS_LONG_OFS 6402
+#endif // SUPPORT_OFS
+
+//
+// The following data is used for the %used/%free bitmap
+//
+
+#define USETYPE_NONE 0x0
+#define USETYPE_ELLIPS 0x1
+#define USETYPE_BARH 0x2
+#define USETYPE_BARV 0x4
+
+/*
+ * NOTE that the following values MUST be > 255 because
+ * they are also used as the resource types for the
+ * raw ELLIPRESOURCE resource.
+ */
+#define IDB_HARDDISK 6500
+#define IDB_CDROM 6501
+
+#define ELLIPRESOURCE 6600
+
+
+
+//
+// RESERVED: ids 7000 to 19999 are used by dialogs in the dialogs.h file
+//
+
+#endif // __RESIDS_H__
diff --git a/private/utils/windisk/src/rmdisk.bmp b/private/utils/windisk/src/rmdisk.bmp
new file mode 100644
index 000000000..7dd7d57fb
--- /dev/null
+++ b/private/utils/windisk/src/rmdisk.bmp
Binary files differ
diff --git a/private/utils/windisk/src/scdrom.ico b/private/utils/windisk/src/scdrom.ico
new file mode 100644
index 000000000..8e0b42de5
--- /dev/null
+++ b/private/utils/windisk/src/scdrom.ico
Binary files differ
diff --git a/private/utils/windisk/src/scsi.h b/private/utils/windisk/src/scsi.h
new file mode 100644
index 000000000..92f0d2173
--- /dev/null
+++ b/private/utils/windisk/src/scsi.h
@@ -0,0 +1,77 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: scsi.h
+//
+// Contents: This is a subset of the header file for SCSI definitions that
+// is located in the kernel tree.
+//
+// History: Mike Glass (mglass) Created
+//
+//----------------------------------------------------------------------------
+
+//
+// Inquiry buffer structure. This is the data returned from the target
+// after it receives an inquiry.
+//
+// This structure may be extended by the number of bytes specified
+// in the field AdditionalLength. The defined size constant only
+// includes fields through ProductRevisionLevel.
+//
+// The NT SCSI drivers are only interested in the first 36 bytes of data.
+//
+
+#define INQUIRYDATABUFFERSIZE 36
+
+typedef struct _INQUIRYDATA {
+ UCHAR DeviceType : 5;
+ UCHAR DeviceTypeQualifier : 3;
+ UCHAR DeviceTypeModifier : 7;
+ UCHAR RemovableMedia : 1;
+ UCHAR Versions;
+ UCHAR ResponseDataFormat;
+ UCHAR AdditionalLength;
+ UCHAR Reserved[2];
+ UCHAR SoftReset : 1;
+ UCHAR CommandQueue : 1;
+ UCHAR Reserved2 : 1;
+ UCHAR LinkedCommands : 1;
+ UCHAR Synchronous : 1;
+ UCHAR Wide16Bit : 1;
+ UCHAR Wide32Bit : 1;
+ UCHAR RelativeAddressing : 1;
+ UCHAR VendorId[8];
+ UCHAR ProductId[16];
+ UCHAR ProductRevisionLevel[4];
+ UCHAR VendorSpecific[20];
+ UCHAR Reserved3[40];
+} INQUIRYDATA, *PINQUIRYDATA;
+
+//
+// Inquiry defines. Used to interpret data returned from target as result
+// of inquiry command.
+//
+// DeviceType field
+//
+
+#define DIRECT_ACCESS_DEVICE 0x00 // disks
+#define SEQUENTIAL_ACCESS_DEVICE 0x01 // tapes
+#define PRINTER_DEVICE 0x02 // printers
+#define PROCESSOR_DEVICE 0x03 // scanners, printers, etc
+#define WRITE_ONCE_READ_MULTIPLE_DEVICE 0x04 // worms
+#define READ_ONLY_DIRECT_ACCESS_DEVICE 0x05 // cdroms
+#define SCANNER_DEVICE 0x06 // scanners
+#define OPTICAL_DEVICE 0x07 // optical disks
+#define MEDIUM_CHANGER 0x08 // jukebox
+#define COMMUNICATION_DEVICE 0x09 // network
+#define LOGICAL_UNIT_NOT_PRESENT_DEVICE 0x7F
+#define DEVICE_QUALIFIER_NOT_SUPPORTED 0x03
+
+//
+// DeviceTypeQualifier field
+//
+
+#define DEVICE_CONNECTED 0x00
+
diff --git a/private/utils/windisk/src/select.cxx b/private/utils/windisk/src/select.cxx
new file mode 100644
index 000000000..600063604
--- /dev/null
+++ b/private/utils/windisk/src/select.cxx
@@ -0,0 +1,1845 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: select.cxx
+//
+// Contents: Routines for handling selection and focus in the volumes
+// and disks views.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "cdrom.hxx"
+#include "dblspace.hxx"
+#include "drives.hxx"
+#include "fill.hxx"
+#include "ft.hxx"
+#include "listbox.hxx"
+#include "ntlow.hxx"
+#include "select.hxx"
+#include "stleg.hxx"
+#include "tbar.hxx"
+#include "volview.hxx"
+#include "windisk.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+ToggleCdRomSelection(
+ IN ULONG CdRomNumber
+ );
+
+VOID
+ToggleDiskSelection(
+ IN PDISKSTATE DiskState,
+ IN DWORD RegionIndex
+ );
+
+VOID
+SetFocusFromListview(
+ VOID
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: AdjustMenuAndStatus
+//
+// Synopsis: Adjust the status bar description based on the selection
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+AdjustMenuAndStatus(
+ VOID
+ )
+{
+ TCHAR mbBuffer[16];
+ TCHAR statusBarPartitionString[200];
+#if defined( DBLSPACE_ENABLED )
+ TCHAR dblSpaceString[200];
+#endif // DBLSPACE_ENABLED
+ DWORD selectionCount;
+ DWORD msg;
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+ DWORD regionIndex;
+ PWSTR volumeLabel;
+ PWSTR typeName;
+ WCHAR driveLetter;
+
+ selectionCount = SetUpMenu(&SingleSel, &SingleSelIndex);
+
+ switch (selectionCount)
+ {
+
+ case 0:
+
+ StatusTextDrlt[0]
+ = StatusTextSize[0]
+ = StatusTextStat[0]
+ = StatusTextVoll[0]
+ = StatusTextType[0]
+ = L'\0';
+ break;
+
+ case 1:
+
+ if (CdRomSelected)
+ {
+ cdrom = CdRomFindSelectedDevice();
+
+ WCHAR rootPath[4];
+ WCHAR volumeLabel[100];
+ WCHAR typeName[100];
+
+ if (!cdrom->TypeName) {
+
+ typeName[0] = L'\0';
+ volumeLabel[0] = L'\0';
+
+ } else {
+
+ lstrcpy(typeName,cdrom->TypeName);
+ lstrcpy(volumeLabel,cdrom->VolumeLabel);
+
+ }
+
+ lstrcpy(StatusTextType, typeName);
+ lstrcpy(StatusTextVoll, volumeLabel);
+
+ LoadString(
+ g_hInstance,
+ IDS_CDROM,
+ StatusTextStat,
+ ARRAYLEN(StatusTextStat));
+
+ if (!cdrom->TypeName) {
+
+ StatusTextSize[0] = L'\0';
+
+ } else {
+
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer));
+ wsprintf(
+ StatusTextSize,
+ TEXT("%u %s"),
+ cdrom->TotalSpaceInMB,
+ mbBuffer);
+
+ }
+
+ if (cdrom->DriveLetter == NO_DRIVE_LETTER_EVER) {
+
+ StatusTextDrlt[0] = L'\0';
+ StatusTextDrlt[1] = L'\0';
+
+ } else {
+
+ StatusTextDrlt[0] = cdrom->DriveLetter;
+ StatusTextDrlt[1] = L':';
+
+ }
+ }
+ else
+ {
+ //
+ // Might be part of a partial FT set.
+ //
+
+ if (FtSelectionType != UNINIT_FT_TYPE)
+ {
+ goto tagFtSet;
+ }
+
+ diskState = SingleSel;
+ regionIndex = SingleSelIndex;
+
+ DetermineRegionInfo(
+ &diskState->RegionArray[regionIndex],
+ &typeName,
+ &volumeLabel,
+ &driveLetter
+ );
+
+ lstrcpy(StatusTextType, typeName);
+ lstrcpy(StatusTextVoll, volumeLabel);
+
+ if (diskState->RegionArray[regionIndex].SysID == PARTITION_ENTRY_UNUSED)
+ {
+ if (diskState->RegionArray[regionIndex].RegionType == REGION_LOGICAL)
+ {
+ if (diskState->ExistLogical)
+ {
+ msg = IDS_FREEEXT;
+ }
+ else
+ {
+ msg = IDS_EXTENDEDPARTITION;
+ }
+ }
+ else
+ {
+ msg = IDS_FREESPACE;
+ }
+ driveLetter = L' ';
+ StatusTextType[0] = L'\0';
+ }
+ else
+ {
+ msg = (diskState->RegionArray[regionIndex].RegionType == REGION_LOGICAL)
+ ? IDS_LOGICALVOLUME
+ : IDS_PARTITION
+ ;
+
+#if i386
+ if ( (msg == IDS_PARTITION)
+ && (diskState->Disk == 0)
+ && diskState->RegionArray[regionIndex].Active)
+ {
+ msg = IDS_ACTIVEPARTITION;
+ }
+#endif
+ }
+
+ LoadString(
+ g_hInstance,
+ msg,
+ statusBarPartitionString,
+ ARRAYLEN(statusBarPartitionString));
+
+#if defined( DBLSPACE_ENABLED )
+ if (DblSpaceVolumeExists(&diskState->RegionArray[regionIndex]))
+ {
+ LoadString(
+ g_hInstance,
+ IDS_WITH_DBLSPACE,
+ dblSpaceString,
+ ARRAYLEN(dblSpaceString));
+ }
+ else
+ {
+ dblSpaceString[0] = dblSpaceString[1] = L'\0';
+ }
+ wsprintf(StatusTextStat,
+ TEXT("%s%s"),
+ statusBarPartitionString,
+ dblSpaceString);
+#else // DBLSPACE_ENABLED
+ wsprintf(StatusTextStat,
+ TEXT("%s"),
+ statusBarPartitionString);
+#endif // !DBLSPACE_ENABLED
+
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer));
+ wsprintf(
+ StatusTextSize,
+ TEXT("%u %s"),
+ diskState->RegionArray[regionIndex].SizeMB,
+ mbBuffer);
+
+ StatusTextDrlt[0] = driveLetter;
+ StatusTextDrlt[1] = ((driveLetter == L' ') ? L'\0' : L':');
+ }
+
+ break;
+
+ default:
+
+tagFtSet:
+
+ //
+ // Might be an ft set, might be multiple items
+ //
+
+ if (FtSelectionType == UNINIT_FT_TYPE)
+ {
+ LoadString(
+ g_hInstance,
+ IDS_MULTIPLEITEMS,
+ StatusTextStat,
+ ARRAYLEN(StatusTextStat));
+
+ StatusTextDrlt[0]
+ = StatusTextSize[0]
+ = StatusTextType[0]
+ = StatusTextVoll[0]
+ = L'\0';
+ }
+ else
+ {
+ PREGION_DESCRIPTOR regionDescriptor;
+ DWORD i;
+ DWORD resid;
+ DWORD size = 0;
+ TCHAR textbuf[STATUS_TEXT_SIZE];
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+ WCHAR ftStatusText[65];
+ FT_SET_STATUS setState;
+ ULONG numberOfMembers;
+ STATUS_CODE status;
+
+ DetermineRegionInfo(
+ &SELECTED_REGION(0),
+ &typeName,
+ &volumeLabel,
+ &driveLetter
+ );
+ if (NULL == typeName)
+ {
+ typeName = wszUnknown;
+ volumeLabel = L"";
+ }
+
+ lstrcpy(StatusTextType, typeName);
+ lstrcpy(StatusTextVoll, volumeLabel);
+
+ switch (FtSelectionType)
+ {
+ case Mirror:
+ resid = IDS_STATUS_MIRROR;
+ size = SELECTED_REGION(0).SizeMB;
+ break;
+
+ case Stripe:
+ resid = IDS_STATUS_STRIPESET;
+ goto tagCalcSize;
+
+ case StripeWithParity:
+ resid = IDS_STATUS_PARITY;
+ goto tagCalcSize;
+
+ case VolumeSet:
+ resid = IDS_STATUS_VOLUMESET;
+ goto tagCalcSize;
+
+tagCalcSize:
+ for (i=0; i<selectionCount; i++)
+ {
+ size += SELECTED_REGION(i).SizeMB;
+ }
+ break;
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+
+ {
+
+ //
+ // Loop through trying to find the actual ftset.
+ //
+
+ DWORD j;
+
+ for (j = 0;
+ j<selectionCount;
+ j++
+ ) {
+
+ ftObject = GET_FT_OBJECT(&SELECTED_REGION(j));
+
+ //
+ // If trying to regenerate an FT set the drive
+ // being used to regenerate might be before the
+ // actual ftset. If the ftobject is null, then
+ // try to get the ftobject from the second selected
+ // region. Since we are doing an ftoperation we
+ // will always have at least two.
+ //
+
+ if (ftObject) {
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ ftSet = ftObject->Set;
+
+ if (FtSelectionType != VolumeSet)
+ {
+ regionDescriptor = LocateRegionForFtObject(ftSet->Member0);
+
+ if (NULL == regionDescriptor)
+ {
+ // The zeroth member is off line
+
+ ftObject = ftSet->Members;
+ while (NULL != ftObject)
+ {
+ // Find member 1
+
+ if (ftObject->MemberIndex == 1)
+ {
+ regionDescriptor = LocateRegionForFtObject(ftObject);
+ break;
+ }
+ ftObject = ftObject->Next;
+ }
+ }
+
+ // If the partition number is zero, then this set has
+ // not been committed to the disk yet.
+
+ if ( (NULL != regionDescriptor)
+ && (0 != regionDescriptor->PartitionNumber))
+ {
+ status = LowFtVolumeStatus(regionDescriptor->Disk,
+ regionDescriptor->PartitionNumber,
+ &setState,
+ &numberOfMembers);
+ if (status == OK_STATUS)
+ {
+ if ( (ftSet->Status != FtSetNewNeedsInitialization)
+ && (ftSet->Status != FtSetNew))
+ {
+ if (ftSet->Status != setState)
+ {
+ PFT_OBJECT tempFtObjectPtr;
+
+ ftSet->Status = setState;
+
+ // Determine if each object should be updated.
+
+ switch (setState)
+ {
+ case FtSetHealthy:
+
+ // Each object in the set should have
+ // the partition state updated. Determine
+ // the value for the update and walk
+ // the chain to perform the update.
+
+ for (tempFtObjectPtr = ftSet->Members;
+ NULL != tempFtObjectPtr;
+ tempFtObjectPtr = tempFtObjectPtr->Next)
+ {
+ tempFtObjectPtr->State = Healthy;
+ }
+ TotalRedrawAndRepaint();
+ break;
+
+ case FtSetInitializing:
+ case FtSetRegenerating:
+ case FtSetDisabled:
+
+ FdftUpdateFtObjectSet(ftSet, setState);
+ TotalRedrawAndRepaint();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ LoadString(g_hInstance, resid, textbuf, ARRAYLEN(textbuf));
+
+ switch (resid)
+ {
+ case IDS_STATUS_STRIPESET:
+ case IDS_STATUS_VOLUMESET:
+ wsprintf(StatusTextStat, textbuf, ftSet->Ordinal);
+ break;
+
+ case IDS_STATUS_PARITY:
+ case IDS_STATUS_MIRROR:
+ {
+ switch (ftSet->Status)
+ {
+ case FtSetHealthy:
+ resid = IDS_HEALTHY;
+ break;
+
+ case FtSetNew:
+ case FtSetNewNeedsInitialization:
+ resid = IDS_NEW;
+ break;
+
+ case FtSetBroken:
+ resid = IDS_BROKEN;
+ break;
+
+ case FtSetRecoverable:
+ resid = IDS_RECOVERABLE;
+ break;
+
+ case FtSetRecovered:
+ resid = IDS_REGENERATED;
+ break;
+
+ case FtSetInitializing:
+ resid = IDS_INITIALIZING;
+ break;
+
+ case FtSetRegenerating:
+ resid = IDS_REGENERATING;
+ break;
+
+ case FtSetDisabled:
+ resid = IDS_DISABLED;
+ break;
+
+ case FtSetInitializationFailed:
+ resid = IDS_INIT_FAILED;
+ break;
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+ LoadString(g_hInstance, resid, ftStatusText, ARRAYLEN(ftStatusText));
+ wsprintf(StatusTextStat, textbuf, ftSet->Ordinal, ftStatusText);
+ break;
+ }
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer));
+ wsprintf(StatusTextSize, TEXT("%u %s"), size, mbBuffer);
+
+ StatusTextDrlt[0] = driveLetter;
+ StatusTextDrlt[1] = ((driveLetter == L' ') ? L'\0' : L':');
+ }
+ }
+ UpdateStatusBarDisplay();
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckSelection
+//
+// Synopsis: Check the selection state. Deselect anything which is
+// not a legal selection for the listview. This includes
+// "new" regions, free space, and CD-ROMs.
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 4-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CheckSelection(
+ VOID
+ )
+{
+ ULONG disk;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR region;
+ PPERSISTENT_REGION_DATA regionData;
+ ULONG regionIndex;
+
+ //
+ // Deselect the region if it is not a significant region (Only
+ // significant regions get put in the volumes view)
+ //
+
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ diskState = DiskArray[disk];
+
+ for (regionIndex=0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ region = &diskState->RegionArray[regionIndex];
+
+ if (diskState->Selected[regionIndex])
+ {
+ regionData = PERSISTENT_DATA(region);
+
+ if (NULL == regionData
+ || !SignificantDriveLetter(regionData->DriveLetter))
+ {
+ // NOTE: the previous test is likely to be SLOW!
+
+ daDebugOut((DEB_ITRACE,
+ "Deselecting disk %d, region %d, drive %c:\n",
+ disk,
+ regionIndex,
+ (NULL == regionData)
+ ? '?'
+ : regionData->DriveLetter
+ ));
+
+ diskState->Selected[regionIndex] = FALSE;
+ PaintDiskRegion(diskState, regionIndex, NULL);
+ }
+ }
+ }
+ }
+
+ for (ULONG i=0; i<CdRomCount; i++)
+ {
+ if (CdRomArray[i].Selected)
+ {
+ CdRomArray[i].Selected = FALSE;
+ PaintCdRom(i, NULL);
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetLVIndexFromDriveLetter
+//
+// Synopsis: Given a drive letter, search for the volume in the listview,
+// and return the item's listview index
+//
+// Arguments: [DriveLetter] -- Drive letter of the volume in question
+//
+// Returns: listview index of the volume, or -1 if not found
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+INT
+GetLVIndexFromDriveLetter(
+ IN WCHAR DriveLetter
+ )
+{
+ WCHAR driveName[3];
+ driveName[0] = DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ LV_FINDINFO lvfi = { LVFI_STRING, driveName, 0 };
+ INT index = ListView_FindItem(g_hwndLV, -1, &lvfi); // -1 == from start
+ if (index == -1)
+ {
+ daDebugOut((DEB_IERROR,
+ "Couldn't find volume %ws in the listview!\n",
+ driveName
+ ));
+ }
+
+ return index;
+}
+
+
+
+VOID
+PaintCdRom(
+ IN ULONG CdRomNumber,
+ IN HDC hdc
+ )
+
+/*++
+
+Routine Description:
+
+ This routine visually toggles the selection state of a CD-ROM
+
+Arguments:
+
+ Cdrom - structure for CD-ROM to select
+
+ hdc - if non-NULL, device context to use for drawing. If NULL, we'll
+ first get a device context via GetDC().
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(CdRomNumber);
+ PLEFTRIGHT leftRight = &cdrom->LeftRight;
+ HDC hdcActual;
+ RECT rc;
+ LONG barTop = CalcBarTop(LBCdRomNumberToIndex(CdRomNumber));
+ BOOL selected = (BOOL)cdrom->Selected;
+ int i;
+ HBRUSH hbr = GetStockBrush(BLACK_BRUSH);
+
+ if (barTop != -1)
+ {
+ hdcActual = hdc ? hdc : GetDC(g_hwndList);
+
+ rc.left = leftRight->Left + 1;
+ rc.right = leftRight->Right - 1;
+ rc.top = barTop + BarTopYOffset + 1;
+ rc.bottom = barTop + BarBottomYOffset - 1;
+
+ if (selected)
+ {
+ for (i=0; i<SELECTION_THICKNESS; i++)
+ {
+ FrameRect(hdcActual, &rc, hbr);
+ InflateRect(&rc, -1, -1);
+ }
+ }
+ else
+ {
+ //
+ // Blt the region from the off-screen bitmap onto the
+ // screen. But first exclude the center of the region
+ // from the clip region so we only blt the necessary bits.
+ // This speeds up selections noticably.
+ //
+
+ InflateRect(&rc, -SELECTION_THICKNESS, -SELECTION_THICKNESS);
+ ExcludeClipRect(hdcActual, rc.left, rc.top, rc.right, rc.bottom);
+
+ BitBlt(hdcActual,
+ leftRight->Left,
+ barTop + BarTopYOffset,
+ leftRight->Right - leftRight->Left,
+ barTop + BarBottomYOffset,
+ cdrom->hDCMem,
+ leftRight->Left,
+ BarTopYOffset,
+ SRCCOPY
+ );
+ }
+
+ if (NULL == hdc)
+ {
+ ReleaseDC(g_hwndList, hdcActual);
+ }
+ }
+}
+
+
+
+
+VOID
+PaintDiskRegion(
+ IN PDISKSTATE DiskState,
+ IN DWORD RegionIndex,
+ IN HDC hdc
+ )
+
+/*++
+
+Routine Description:
+
+ This routine visually toggles the selection state of a given disk region.
+
+Arguments:
+
+ DiskState - master structure for disk containing region to select
+
+ RegionIndex - which region on the disk to toggle
+
+ hdc - if non-NULL, device context to use for drawing. If NULL, we'll
+ first get a device context via GetDC().
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PLEFTRIGHT leftRight = &DiskState->LeftRight[RegionIndex];
+ HDC hdcActual;
+ RECT rc;
+ LONG barTop = CalcBarTop(DiskState->Disk);
+ BOOL selected = (BOOL)DiskState->Selected[RegionIndex];
+ int i;
+ HBRUSH hbr = GetStockBrush(BLACK_BRUSH);
+
+ if (barTop != -1)
+ {
+ hdcActual = hdc ? hdc : GetDC(g_hwndList);
+
+ rc.left = leftRight->Left + 1;
+ rc.right = leftRight->Right - 1;
+ rc.top = barTop + BarTopYOffset + 1;
+ rc.bottom = barTop + BarBottomYOffset - 1;
+
+ if (selected)
+ {
+ for (i=0; i<SELECTION_THICKNESS; i++)
+ {
+ FrameRect(hdcActual, &rc, hbr);
+ InflateRect(&rc, -1, -1);
+ }
+ }
+ else
+ {
+
+ //
+ // Blt the region from the off-screen bitmap onto the
+ // screen. But first exclude the center of the region
+ // from the clip region so we only blt the necessary bits.
+ // This speeds up selections noticably.
+ //
+
+ InflateRect(&rc, -SELECTION_THICKNESS, -SELECTION_THICKNESS);
+ ExcludeClipRect(hdcActual, rc.left, rc.top, rc.right, rc.bottom);
+
+ BitBlt(hdcActual,
+ leftRight->Left,
+ barTop + BarTopYOffset,
+ leftRight->Right - leftRight->Left,
+ barTop + BarBottomYOffset,
+ DiskState->hDCMem,
+ leftRight->Left,
+ BarTopYOffset,
+ SRCCOPY
+ );
+ }
+
+ if (NULL == hdc)
+ {
+ ReleaseDC(g_hwndList, hdcActual);
+ }
+ }
+}
+
+
+
+
+VOID
+SetVolumeSelectedState(
+ IN CHAR DriveLetter,
+ IN BOOL Select
+ )
+
+/*++
+
+Routine Description:
+
+ This routine selects or deselects items in the volumes view.
+
+Arguments:
+
+ DriveLetter - indicates the volume to change the selection state of
+
+ Select - TRUE to select the volume, FALSE to deselect it
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Get the listview index of the volume with drive letter DriveLetter
+ //
+
+ INT index = GetLVIndexFromDriveLetter(DriveLetter);
+
+ g_SettingListviewState = TRUE;
+
+ //
+ // Set the state of this item to selected or not, based on the Select
+ // parameter.
+ //
+ ListView_SetItemState(
+ g_hwndLV,
+ index,
+ (Select ? LVIS_SELECTED : 0),
+ LVIS_SELECTED
+ );
+
+// daDebugOut((DEB_ITRACE, "SetVolumeSelectedState: %s %c: (index %d)\n",
+// Select ? "selected" : "deselected",
+// DriveLetter,
+// index
+// ));
+
+ g_SettingListviewState = FALSE;
+}
+
+
+
+VOID
+DeselectSelectedRegions(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine deselects all selected regions.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+//BUGBUG: why not just use the Selected* arrays? so its linear in the
+//number of selected regions?
+
+ DWORD i;
+ DWORD j;
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+ for (j=0; j<diskState->RegionCount; j++)
+ {
+ diskState->Selected[j] = FALSE;
+ }
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+ cdrom->Selected = FALSE;
+ }
+}
+
+
+
+
+VOID
+DeselectSelectedDiskViewRegions(
+ VOID
+ )
+{
+ DWORD i;
+ DWORD j;
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+ for (j=0; j<diskState->RegionCount; j++)
+ {
+ if (diskState->Selected[j])
+ {
+ diskState->Selected[j] = FALSE;
+ PaintDiskRegion(diskState, j, NULL);
+ diskState->Selected[j] = TRUE;
+ }
+ }
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+ if (cdrom->Selected)
+ {
+ cdrom->Selected = FALSE;
+ PaintCdRom(i, NULL);
+ cdrom->Selected = TRUE;
+ }
+ }
+}
+
+
+
+
+VOID
+DeselectSelectedListViewRegions(
+ VOID
+ )
+{
+ g_SettingListviewState = TRUE;
+
+ INT item = -1;
+
+ while ((item = ListView_GetNextItem(g_hwndLV, item, LVNI_SELECTED))
+ != -1)
+ {
+ ListView_SetItemState(
+ g_hwndLV,
+ item,
+ 0,
+ LVIS_SELECTED);
+ }
+
+ g_SettingListviewState = FALSE;
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ToggleCdRomSelection
+//
+// Synopsis: Toggle the selection state of a CD-ROM in the disks view.
+//
+// Arguments: [CdRomNumber] -- the number of the CD-ROM
+//
+// Returns: nothing
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ToggleCdRomSelection(
+ IN ULONG CdRomNumber
+ )
+{
+ PCDROM_DESCRIPTOR cdrom;
+
+ ToggleLBCursor(NULL); // remove previous selection
+
+ cdrom = CdRomFindDevice(CdRomNumber);
+ cdrom->Selected = !cdrom->Selected;
+ PaintCdRom(CdRomNumber, NULL);
+
+ LBCursorListBoxItem = LBCdRomNumberToIndex(CdRomNumber);
+ LBCursorRegion = 0;
+
+ ToggleLBCursor(NULL); // visualize new selection
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ToggleDiskSelection
+//
+// Synopsis: Toggle the selection state of a region in the disks view. If
+// the region is part of a volume, then toggle the state of all
+// regions associated with the volume (which will be >1 for FT
+// sets)
+//
+// Arguments: [DiskState] -- a disk state structure
+// [RegionIndex] -- the region index
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ToggleDiskSelection(
+ IN PDISKSTATE DiskState,
+ IN DWORD RegionIndex
+ )
+{
+ PFT_OBJECT ftObject;
+ PFT_OBJECT ftObj;
+ PFT_OBJECT_SET ftSet;
+ ULONG disk;
+ ULONG regionIndex;
+
+ // remove the list box selection cursor from its previous region
+
+ ToggleLBCursor(NULL);
+
+ //
+ // The selected region might be part of an ft object set. If it is,
+ // scan each region in each disk and select each item in the set.
+ //
+
+ if (NULL != (ftObject = GET_FT_OBJECT(&DiskState->RegionArray[RegionIndex])))
+ {
+ ftSet = ftObject->Set;
+
+ for (disk = 0; disk<DiskCount; disk++)
+ {
+ PDISKSTATE diskState = DiskArray[disk];
+
+ for (regionIndex = 0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &diskState->RegionArray[regionIndex];
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ if (NULL != (ftObj = GET_FT_OBJECT(regionDescriptor)))
+ {
+ if (ftObj->Set == ftSet)
+ {
+ diskState->Selected[regionIndex] = (BOOLEAN)(!diskState->Selected[regionIndex]);
+ PaintDiskRegion(diskState, regionIndex, NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ //
+ // Only a single-partition volume
+ //
+
+ DiskState->Selected[RegionIndex] = (BOOLEAN)(!DiskState->Selected[RegionIndex]);
+ PaintDiskRegion(DiskState, RegionIndex, NULL);
+ }
+
+ LBCursorListBoxItem = LBDiskNumberToIndex(DiskState->Disk);
+ LBCursorRegion = RegionIndex;
+
+ ToggleLBCursor(NULL);
+}
+
+
+
+
+VOID
+SelectCdRom(
+ IN BOOL MultipleSel,
+ IN ULONG CdRomNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles a user selection of a CD-ROM. It is called
+ directly for a keyboard selection or indirectly for a mouse selection.
+ If not a multiple selection, all selected regions are deselected.
+ The focus rectangle is moved to the selected region, which is then
+ visually selected.
+
+Arguments:
+
+ MultipleSel - whether the user has made a multiple selection
+ (ie, control-clicked).
+
+ CdRomNumber - index of selected CD-ROM on the disk
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (!MultipleSel)
+ {
+ // need to deselect all selected regions first.
+
+ DeselectSelectedDiskViewRegions(); // visual selection in disk view
+ DeselectSelectedRegions(); // actual selection state
+ }
+
+ //
+ // select or deselect the region
+ //
+
+ ToggleCdRomSelection(CdRomNumber);
+
+ AdjustMenuAndStatus();
+}
+
+
+
+
+VOID
+SelectDiskRegion(
+ IN BOOL MultipleSel,
+ IN PDISKSTATE DiskState,
+ IN DWORD RegionIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine handles a user selection of a disk region. It is called
+ directly for a keyboard selection or indirectly for a mouse selection.
+ If not a multiple selection, all selected regions are deselected.
+ The focus rectangle is moved to the selected region, which is then
+ visually selected.
+
+Arguments:
+
+ MultipleSel - whether the user has made a multiple selection
+ (ie, control-clicked).
+
+ DiskState - master disk structure for disk containing selected region
+
+ RegionIndex - index of selected region on the disk
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (!MultipleSel)
+ {
+ // need to deselect all selected regions first.
+
+ DeselectSelectedDiskViewRegions(); // visual selection in disk view
+ DeselectSelectedRegions(); // actual selection state
+ }
+
+ //
+ // select or deselect the region
+ //
+
+ ToggleDiskSelection(DiskState, RegionIndex);
+
+ AdjustMenuAndStatus();
+}
+
+
+
+VOID
+MouseSelection(
+ IN BOOL MultipleSel,
+ IN OUT PPOINT ppt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called when the user clicks in the list box. It determines
+ which disk region the user has clicked on before calling the common
+ selection subroutine.
+
+Arguments:
+
+ MultipleSel - whether the user has made a multiple selection
+ (ie, control-clicked).
+
+ ppt - screen coords of the click
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PDISKSTATE diskState;
+ DWORD selectedItem;
+ DWORD x;
+ DWORD y;
+ DWORD i;
+ RECT rc;
+ BOOL Valid;
+ PLEFTRIGHT leftRight;
+
+ if ((selectedItem = SendMessage(g_hwndList, LB_GETCURSEL, 0, 0)) == LB_ERR)
+ {
+ return;
+ }
+
+ // user has clicked on a list box item.
+
+ if (LBIsDisk(selectedItem))
+ {
+ diskState = DiskArray[LBIndexToDiskNumber(selectedItem)];
+
+ //
+ // Ignore clicks on off-line disks.
+ //
+
+ if (diskState->OffLine)
+ {
+ return;
+ }
+ }
+
+ ScreenToClient(g_hwndList, ppt);
+ x = ppt->x;
+ y = ppt->y;
+
+ // Now determine the client rectange of the listbox control
+
+ GetClientRect(g_hwndList, &rc);
+
+ // first make sure that the click was within a bar and not in space
+ // between two bars. This computation doesn't depend on the value
+ // of the horizontal scroll position.
+
+ Valid = FALSE;
+ for (i = rc.top; i <= (DWORD)rc.bottom; i += GraphHeight)
+ {
+ if ((y >= i+BarTopYOffset) && (y <= i+BarBottomYOffset))
+ {
+ Valid = TRUE;
+ break;
+ }
+ }
+ if (!Valid)
+ {
+ return;
+ }
+
+ if (LBIsDisk(selectedItem))
+ {
+ // determine which region was clicked on
+
+ for (i=0; i<diskState->RegionCount; i++)
+ {
+ leftRight = &diskState->LeftRight[i];
+ if ( (x >= (unsigned)leftRight->Left)
+ && (x <= (unsigned)leftRight->Right))
+ {
+ SelectDiskRegion(MultipleSel, diskState, i);
+ break;
+ }
+ }
+ }
+ else if (LBIsCdRom(selectedItem))
+ {
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(LBIndexToCdRomNumber(selectedItem));
+ leftRight = &cdrom->LeftRight;
+
+ if ( (x >= (unsigned)leftRight->Left)
+ && (x <= (unsigned)leftRight->Right))
+ {
+ SelectCdRom(MultipleSel, LBIndexToCdRomNumber(selectedItem));
+ }
+ }
+ else
+ {
+ FDASSERT(FALSE);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetListviewDriveLetter
+//
+// Synopsis: Find the drive letter associated with a listview item
+//
+// Arguments: [Index] -- listview index
+//
+// Returns: Given a listview index, return the drive letter of the volume
+// at that index, or NO_DRIVE_LETTER if no volume is at that index
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+WCHAR
+GetListviewDriveLetter(
+ IN INT Index
+ )
+{
+ INT cch;
+ WCHAR buffer[MAX_LV_ITEM_LEN];
+
+ LV_ITEM lvi;
+ lvi.iSubItem = 0;
+ lvi.pszText = buffer;
+ lvi.cchTextMax = ARRAYLEN(buffer);
+
+ cch = SendMessage(g_hwndLV, LVM_GETITEMTEXT, (WPARAM)Index, (LPARAM)&lvi);
+
+ // the ListView_GetItemText macro doesn't allow you to get the return code
+
+ if (cch < 1)
+ {
+ daDebugOut((DEB_ERROR,
+ "GetListviewDriveLetter: Listview_GetItemText on item %d failed!\n",
+ Index));
+
+ return NO_DRIVE_LETTER_EVER; //BUGBUG: ok?
+ }
+
+ daDebugOut((DEB_ERROR,
+ "GetListviewDriveLetter: got %ws\n",
+ lvi.pszText));
+
+ return lvi.pszText[0];
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetVolumeSelection
+//
+// Synopsis: Given a listview index of the selection, reflect that selection
+// in the disks view.
+//
+// Arguments: [Index] -- listview index
+// [Selected] -- TRUE if the item should be selected
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetVolumeSelection(
+ IN INT Index,
+ IN BOOL Selected
+ )
+{
+ //
+ // Change the stored selection state
+ //
+
+ WCHAR driveLetter = GetListviewDriveLetter(Index);
+
+ if (CdRomUsingDriveLetter(driveLetter))
+ {
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDriveLetter(driveLetter);
+ cdrom->Selected = Selected;
+ }
+ else
+ {
+ DWORD diskNum;
+ DWORD regionIndex;
+
+ for (diskNum = 0; diskNum < DiskCount; diskNum++)
+ {
+ PDISKSTATE diskState = DiskArray[diskNum];
+
+ for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &diskState->RegionArray[regionIndex];
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (regionData->DriveLetter == driveLetter)
+ {
+ diskState->Selected[regionIndex] = Selected;
+
+ // don't break out or return: if this is an FT volume,
+ // there will be more regions.
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChangeToVolumesView
+//
+// Synopsis: Perform tasks necessary to switch the view to the volumes view
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ChangeToVolumesView(
+ VOID
+ )
+{
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR region;
+
+ //
+ // disable the Options: Legend, Colors, Disk Display, Region Display
+ //
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSLEGEND,
+ MF_BYCOMMAND | MF_DISABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSCOLORS,
+ MF_BYCOMMAND | MF_DISABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSDISK,
+ MF_BYCOMMAND | MF_DISABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSDISPLAY,
+ MF_BYCOMMAND | MF_DISABLED
+ );
+
+ //
+ // Put the right stuff in the listview
+ //
+
+// CheckSelection();//BUGBUG: why is this necessary?
+ FillListView(FALSE);
+
+ //
+ // The following is done when changing to the volumes view:
+ // -- the focus is set. If the disks view focus is on free space, then
+ // put the focus on the first volume in the volumes view.
+ // -- adjust the selection: deselect all free space.
+ //
+
+ //
+ // set g_SettingListviewState to avoid handling listview notifications here
+ //
+
+ g_SettingListviewState = TRUE;
+
+ //
+ // determine which item will get the focus, and give it to it
+ //
+
+ INT index = -1;
+ WCHAR driveLetter;
+
+ if (LBIsDisk(LBCursorListBoxItem))
+ {
+ diskState = DiskArray[LBIndexToDiskNumber(LBCursorListBoxItem)];
+ region = &diskState->RegionArray[LBCursorRegion];
+
+ if (DmSignificantRegion(region))
+ {
+ //
+ // Find the volume in the volumes view that has the focus in the
+ // disks view
+ //
+
+ driveLetter = PERSISTENT_DATA(region)->DriveLetter;
+
+ if (!IsExtraDriveLetter(driveLetter))
+ {
+ index = GetLVIndexFromDriveLetter(driveLetter);
+ }
+ }
+ }
+ else if (LBIsCdRom(LBCursorListBoxItem))
+ {
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(LBIndexToCdRomNumber(LBCursorListBoxItem));
+ driveLetter = cdrom->DriveLetter;
+ index = GetLVIndexFromDriveLetter(driveLetter);
+ }
+
+ if (-1 == index)
+ {
+ if (ListView_GetItemCount(g_hwndLV) > 0)
+ {
+ index = 0;
+ }
+ }
+
+ if (index != -1)
+ {
+ daDebugOut((DEB_SEL,
+ "listview focus ==> %wc:(%d)\n",
+ driveLetter,
+ index));
+
+ // Give the item both the focus *and* the selection, since we only
+ // allow a single listview selection
+
+ ListView_SetItemState(
+ g_hwndLV,
+ index,
+ LVIS_FOCUSED | LVIS_SELECTED,
+ LVIS_FOCUSED | LVIS_SELECTED);
+ ListView_EnsureVisible(g_hwndLV, index, FALSE);
+
+ SetVolumeSelection(index, TRUE); // reflect in disks view
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE, "Nobody gets the focus\n"));
+ }
+
+#if 0
+
+ //BUGBUG: this section is commented out. We used to ensure that the
+ // the selection in the list view was exactly the same as in the disks
+ // view, except for items that doen't show up in the volumes view.
+ // Now, we only allow a single selection in the volumes view. So, we've
+ // added code above to make the focus the selection as well. The following
+ // code can probably be deleted, but I'm too much a pack rat to do
+ // it right now.
+
+ //
+ // For every selected volume, select it in the volumes
+ // view. This code unfortunately sends an FT volume "select" messages
+ // once for every region composing the FT set.
+ //
+
+ ULONG disk;
+ PPERSISTENT_REGION_DATA regionData;
+ ULONG regionIndex;
+
+ daDebugOut((DEB_SEL, "selection ==> "));
+
+ for (disk=0; disk<DiskCount; disk++)
+ {
+ diskState = DiskArray[disk];
+
+ for (regionIndex=0; regionIndex<diskState->RegionCount; regionIndex++)
+ {
+ if (diskState->Selected[regionIndex])
+ {
+ region = &diskState->RegionArray[regionIndex];
+ regionData = PERSISTENT_DATA(region);
+
+ if (NULL != regionData)
+ {
+ driveLetter = regionData->DriveLetter;
+
+ index = GetLVIndexFromDriveLetter(driveLetter);
+
+ if (-1 != index)
+ {
+ //
+ // if the volume has a drive letter...
+ //
+
+ daDebugOut((DEB_SEL | DEB_NOCOMPNAME,
+ "%wc:(%d, disk %d, region %d); ",
+ driveLetter,
+ index,
+ disk,
+ regionIndex
+ ));
+
+ ListView_SetItemState(
+ g_hwndLV,
+ index,
+ LVIS_SELECTED,
+ LVIS_SELECTED
+ );
+ }
+ }
+ }
+ }
+ }
+
+ daDebugOut((DEB_SEL | DEB_NOCOMPNAME, "\n"));
+
+#endif // 0
+
+
+ //
+ // we can take notifications again...
+ //
+
+ g_SettingListviewState = FALSE;
+
+ //
+ // Disable the disks view listbox control
+ //
+
+ ShowWindow(g_hwndList, SW_HIDE);
+ ShowWindow(g_hwndLV, SW_SHOW);
+
+ SetFocus(g_hwndLV); // give listview the focus
+
+ //
+ // Initialize listview sorting direction array
+ //
+
+ g_aColumnOrder = 1;
+ g_iLastColumnSorted = -1;
+
+ //
+ // Change the menu
+ //
+
+ AdjustMenuAndStatus();
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetFocusFromListview
+//
+// Synopsis: Using the current listview focus, set the disks view focus
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetFocusFromListview(
+ VOID
+ )
+{
+ //
+ // set the focus. Pick a random region from the volume that has the
+ // focus. For instance, if volume "F:" has the focus, then pick any of
+ // its component regions---e.g., it doesn't matter which region of a volume
+ // set gets the focus.
+ //
+
+#if DBG == 1
+
+ {
+ INT item;
+
+ //
+ // Verify that there is exactly one volume with the focus
+ //
+
+ if (-1 == (item = ListView_GetNextItem(g_hwndLV, -1, LVNI_FOCUSED)))
+ {
+ daDebugOut((DEB_ERROR, "No volume has the focus!\n"));
+ }
+ else if (-1 != ListView_GetNextItem(g_hwndLV, item, LVNI_FOCUSED))
+ {
+ daDebugOut((DEB_ERROR, "More than one volume has the focus!\n"));
+ }
+
+ item = -1;
+ while ((item = ListView_GetNextItem(g_hwndLV, item, LVNI_FOCUSED))
+ != -1)
+ {
+ daDebugOut((DEB_ITRACE, "Listview item %d has the focus\n", item));
+// daDebugOut((DEB_SEL, "Listview item %d has the focus\n", item));
+ }
+ }
+
+#endif // DBG == 1
+
+ INT item = ListView_GetNextItem(g_hwndLV, -1, LVNI_FOCUSED);
+ if (-1 != item)
+ {
+ WCHAR driveLetter = GetListviewDriveLetter(item);
+
+ if (CdRomUsingDriveLetter(driveLetter))
+ {
+ ToggleLBCursor(NULL);
+ LBCursorListBoxItem = LBCdRomNumberToIndex(CdRomFindDeviceNumber(driveLetter));
+ LBCursorRegion = 0;
+ ToggleLBCursor(NULL);
+ }
+ else
+ {
+ PDISKSTATE diskState;
+ INT regionIndex;
+
+ GetInfoFromDriveLetter(driveLetter, &diskState, &regionIndex);
+
+ ToggleLBCursor(NULL);
+ LBCursorListBoxItem = LBDiskNumberToIndex(diskState->Disk);
+ LBCursorRegion = regionIndex;
+ ToggleLBCursor(NULL);
+ }
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChangeToDisksView
+//
+// Synopsis: Perform tasks necessary to switch the view to the disks view
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ChangeToDisksView(
+ VOID
+ )
+{
+ CheckTBButton(IDM_VIEWDISKS);
+
+ //
+ // Enable the disks view listbox control
+ //
+
+ ShowWindow(g_hwndLV, SW_HIDE);
+ ShowWindow(g_hwndList, SW_SHOW);
+
+ SetFocus(g_hwndList); // give listbox the focus
+ ForceLBRedraw();
+
+ //
+ // enable the Options: Legend, Colors, Disk Display, Region Display
+ //
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSLEGEND,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSCOLORS,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSDISK,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+
+ EnableMenuItem(
+ g_hmenuFrame,
+ IDM_OPTIONSDISPLAY,
+ MF_BYCOMMAND | MF_ENABLED
+ );
+
+ SetFocusFromListview();
+}
diff --git a/private/utils/windisk/src/select.hxx b/private/utils/windisk/src/select.hxx
new file mode 100644
index 000000000..6d10926e2
--- /dev/null
+++ b/private/utils/windisk/src/select.hxx
@@ -0,0 +1,108 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: select.hxx
+//
+// Contents: Routines for handling selection and focus in the volumes
+// and disks views.
+//
+// History: 3-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SELECT_HXX__
+#define __SELECT_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+extern ULONG g_MouseLBIndex;
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+AdjustMenuAndStatus(
+ VOID
+ );
+
+INT
+GetLVIndexFromDriveLetter(
+ IN WCHAR DriveLetter
+ );
+
+VOID
+CheckSelection(
+ VOID
+ );
+
+VOID
+PaintCdRom(
+ IN ULONG CdRomNumber,
+ IN HDC hdc
+ );
+
+VOID
+PaintDiskRegion(
+ IN PDISKSTATE DiskState,
+ IN DWORD RegionIndex,
+ IN HDC hdc
+ );
+
+VOID
+SetVolumeSelectedState(
+ IN WCHAR DriveLetter,
+ IN BOOL Select
+ );
+
+VOID
+DeselectSelectedRegions(
+ VOID
+ );
+
+VOID
+DeselectSelectedDiskViewRegions(
+ VOID
+ );
+
+VOID
+SelectCdRom(
+ IN BOOL MultipleSel,
+ IN ULONG CdRomNumber
+ );
+
+VOID
+SelectDiskRegion(
+ IN BOOL MultipleSel,
+ IN PDISKSTATE DiskState,
+ IN DWORD region
+ );
+
+VOID
+MouseSelection(
+ IN BOOL MultipleSel,
+ IN OUT PPOINT ppt
+ );
+
+WCHAR
+GetListviewDriveLetter(
+ IN INT index
+ );
+
+VOID
+SetVolumeSelection(
+ IN INT index,
+ IN BOOL Selected
+ );
+
+VOID
+ChangeToVolumesView(
+ VOID
+ );
+
+VOID
+ChangeToDisksView(
+ VOID
+ );
+
+#endif // __SELECT_HXX__
diff --git a/private/utils/windisk/src/shard.ico b/private/utils/windisk/src/shard.ico
new file mode 100644
index 000000000..d7c0bc280
--- /dev/null
+++ b/private/utils/windisk/src/shard.ico
Binary files differ
diff --git a/private/utils/windisk/src/smcdrom.bmp b/private/utils/windisk/src/smcdrom.bmp
new file mode 100644
index 000000000..b8040e819
--- /dev/null
+++ b/private/utils/windisk/src/smcdrom.bmp
Binary files differ
diff --git a/private/utils/windisk/src/smdisk.bmp b/private/utils/windisk/src/smdisk.bmp
new file mode 100644
index 000000000..db2c6b252
--- /dev/null
+++ b/private/utils/windisk/src/smdisk.bmp
Binary files differ
diff --git a/private/utils/windisk/src/sources b/private/utils/windisk/src/sources
new file mode 100644
index 000000000..7e2e83adc
--- /dev/null
+++ b/private/utils/windisk/src/sources
@@ -0,0 +1,79 @@
+!include ..\windisk.mk
+
+# BUGBUG: name should be just "windisk"
+TARGETNAME= windisk
+#TARGETNAME= windisk2
+
+TARGETTYPE= PROGRAM
+TARGETPATH= obj
+
+UMTYPE= windows
+UMRES= obj\*\windisk.res
+
+TARGETLIBS=\
+ ..\debug\obj\*\debug.lib \
+ ..\util\obj\*\util.lib \
+ ..\controls\obj\*\controls.lib \
+ $(BASEDIR)\public\sdk\lib\*\diskreg.lib \
+ $(BASEDIR)\public\sdk\lib\*\comctl32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib
+
+INCLUDES=\
+ obj; \
+ ..\inc; \
+ ..\util; \
+ ..\controls; \
+ ..\..\fmifs\inc; \
+ $(BASEDIR)\private\windows\inc; \
+ $(BASEDIR)\private\windows\inc16; \
+ $(INCLUDES)
+
+SOURCES=\
+ messages.mc \
+ cdrom.cxx \
+ cm.cxx \
+ commit.cxx \
+ data.cxx \
+ dblspace.cxx \
+ dispinfo.cxx \
+ dlgs.cxx \
+ drives.cxx \
+ engine.cxx \
+ fill.cxx \
+ fmifs.cxx \
+ format.cxx \
+ fs.cxx \
+ ft.cxx \
+ ftreg.cxx \
+ help.cxx \
+ help2.cxx \
+ init.cxx \
+ listbox.cxx \
+ log.cxx \
+ mem.cxx \
+ menudict.cxx \
+ misc.cxx \
+ network.cxx \
+ nt.cxx \
+ ntlow.cxx \
+ oleclass.cxx \
+ ops.cxx \
+ popup.cxx \
+ profile.cxx \
+ ps.cxx \
+ rect.cxx \
+ select.cxx \
+ stleg.cxx \
+ tbar.cxx \
+ volview.cxx \
+ windisk.cxx
+
+PRECOMPILED_INCLUDE=headers.hxx
+PRECOMPILED_CXX=1
+
+NTTARGETFILE1= obj\*\windisk.res
+PASS0_HEADERDIR=obj
+PASS0_SOURCEDIR=obj
diff --git a/private/utils/windisk/src/stleg.cxx b/private/utils/windisk/src/stleg.cxx
new file mode 100644
index 000000000..adc97c646
--- /dev/null
+++ b/private/utils/windisk/src/stleg.cxx
@@ -0,0 +1,534 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stleg.cxx
+//
+// Contents: Routines to support the status bar and legend displays.
+//
+// History: 7-Jan-92 TedM Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "stleg.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+PWSTR LegendLabels[LEGEND_STRING_COUNT];
+
+// text for status area
+
+WCHAR StatusTextStat[STATUS_TEXT_SIZE];
+WCHAR StatusTextSize[STATUS_TEXT_SIZE];
+WCHAR StatusTextDrlt[3];
+WCHAR StatusTextType[STATUS_TEXT_SIZE];
+WCHAR StatusTextVoll[STATUS_TEXT_SIZE];
+
+
+// The following indices apply to the fAnyOfType array. They must
+// parallel the BRUSH_* constants:
+
+#define ANYOF_PRIMARY 0
+#define ANYOF_LOGICAL 1
+#define ANYOF_STRIPE 2
+#define ANYOF_PARITY 3
+#define ANYOF_MIRROR 4
+#define ANYOF_VOLSET 5
+
+BOOL fAnyOfType[LEGEND_STRING_COUNT];
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: UpdateStatusBarDisplay
+//
+// Synopsis: Cause the status bar and legend areas of the display to be
+// invalidated (and hence redrawn).
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+UpdateStatusBarDisplay(
+ VOID
+ )
+{
+ //
+ // The legend can change; we only display legend items for types
+ // that exist on the screen
+ //
+
+ if ( g_StatusBar
+ || (g_Legend && (VIEW_DISKS == g_WhichView)))
+ {
+ RECT rc;
+
+ GetClientRect(g_hwndFrame, &rc);
+ rc.top = rc.bottom;
+
+ if (g_Legend)
+ {
+ rc.top -= g_dyLegend;
+ }
+
+ if (g_StatusBar)
+ {
+ rc.top -= g_dyStatus;
+ }
+
+ InvalidateRect(g_hwndFrame, &rc, FALSE);
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClearStatusArea
+//
+// Synopsis: Clear the status area of any message
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ClearStatusArea(
+ VOID
+ )
+{
+ StatusTextStat[0]
+ = StatusTextSize[0]
+ = StatusTextVoll[0]
+ = StatusTextType[0]
+ = StatusTextDrlt[0]
+ = L'\0';
+
+ UpdateStatusBarDisplay();
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DetermineExistence
+//
+// Synopsis: Determine what types of volumes exist so we know what legend
+// items to show
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// Modifies: [fAnyOfType]
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DetermineExistence(
+ VOID
+ )
+{
+ UINT i, j;
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PFT_OBJECT ftObject;
+ PFT_OBJECT_SET ftSet;
+
+ for (i=0; i<LEGEND_STRING_COUNT; i++)
+ {
+ fAnyOfType[i] = FALSE;
+ }
+
+ for (i=0; i<DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+ for (j=0; j<diskState->RegionCount; j++)
+ {
+ regionDescriptor = &diskState->RegionArray[j];
+ if (NULL != (ftObject = GET_FT_OBJECT(regionDescriptor)))
+ {
+ ftSet = ftObject->Set;
+
+ switch (ftSet->Type)
+ {
+ case Stripe:
+ fAnyOfType[ANYOF_STRIPE] = TRUE;
+ break;
+
+ case StripeWithParity:
+ fAnyOfType[ANYOF_PARITY] = TRUE;
+ break;
+
+ case Mirror:
+ fAnyOfType[ANYOF_MIRROR] = TRUE;
+ break;
+
+ case VolumeSet:
+ fAnyOfType[ANYOF_VOLSET] = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ if (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED
+ && !IsExtended(regionDescriptor->SysID))
+ {
+ if (REGION_PRIMARY == regionDescriptor->RegionType)
+ {
+ fAnyOfType[ANYOF_PRIMARY] = TRUE;
+ }
+ else if (REGION_LOGICAL == regionDescriptor->RegionType)
+ {
+ fAnyOfType[ANYOF_LOGICAL] = TRUE;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+VOID
+CalculateLegendHeight(
+ IN DWORD newGraphWidth
+ )
+
+/*++
+
+Routine Description:
+
+ This routine calculates the legend height. It may be a multi-row
+ legend.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD width = 0;
+ DWORD elementWidth;
+ DWORD allowedWidth = newGraphWidth - 18*g_dyBorder;
+ SIZE size;
+ UINT rows = 1;
+ UINT i;
+ HDC hdc = GetDC(g_hwndFrame);
+ HFONT hfontOld = SelectFont(hdc, g_hFontLegend);
+
+ for (i=0; i<BRUSH_ARRAY_SIZE; i++)
+ {
+ if (fAnyOfType[i])
+ {
+ GetTextExtentPoint32(
+ hdc,
+ LegendLabels[i],
+ lstrlen(LegendLabels[i]),
+ &size
+ );
+
+ elementWidth = (DWORD)size.cx + (5*g_wLegendItem/2);
+
+ if ( width != 0
+ && (width + elementWidth > allowedWidth))
+ {
+ width = 0;
+ ++rows;
+ }
+
+ width += elementWidth;
+ }
+ }
+
+ g_dyLegend = rows * g_wLegendItem // height of a row
+ + (rows + 1) * g_dyLegendSep // separation between rows
+ // + border on top
+ // + border on bottom
+ + 2 * (3*g_dyBorder) // the top & bottom bevelling eat
+ // ... up 3*g_dyBorder each
+ ;
+
+ if (NULL != hfontOld)
+ {
+ SelectFont(hdc, hfontOld);
+ }
+ ReleaseDC(g_hwndFrame, hdc);
+}
+
+
+VOID
+DrawLegend(
+ IN HDC hdc,
+ IN PRECT prc
+ )
+
+/*++
+
+Routine Description:
+
+ This routine draws the legend onto the given device context. The legend
+ lists the brush styles used to indicate various region types in the
+ disk graphs.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD width;
+ DWORD elementWidth;
+ DWORD allowedWidth;
+ DWORD i;
+ DWORD left;
+ DWORD top;
+ DWORD leftMargin;
+ DWORD topMargin;
+ DWORD delta = GraphWidth / BRUSH_ARRAY_SIZE;
+ RECT rc1;
+ RECT rc2;
+ RECT rcClip;
+ HFONT hfontOld;
+ HBRUSH hBrush;
+ SIZE size;
+ COLORREF oldTextColor;
+ COLORREF oldBkColor;
+
+ rc1 = *prc;
+ rc2 = *prc;
+
+ allowedWidth = prc->right - prc->left - 18*g_dyBorder;
+
+ // first draw the background.
+
+ hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+ rc1.right = rc1.left + GraphWidth; // erase it all
+ FillRect(hdc, &rc1, hBrush);
+ DeleteBrush(hBrush);
+
+ // now draw the nice container
+
+ rc2.left += 8 * g_dyBorder;
+ rc2.right -= 8 * g_dyBorder;
+ DrawStatusAreaItem(&rc2, hdc, NULL);
+
+ // now draw the legend items
+
+ leftMargin = rc2.left + (g_wLegendItem / 2);
+ topMargin = prc->top + (g_dyBorder*3) + g_dyLegendSep;
+
+ SelectPen(hdc, g_hPenThinSolid);
+ SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
+ hfontOld = SelectFont(hdc, g_hFontLegend);
+ oldTextColor = SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
+ SetBkMode(hdc, OPAQUE);
+
+ rcClip.left = rc2.left + g_dyBorder;
+ rcClip.top = rc2.top + (3*g_dyBorder);
+ rcClip.right = rc2.right - g_dyBorder;
+ rcClip.bottom = rc2.bottom - (3*g_dyBorder);
+
+ IntersectClipRect(hdc, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
+
+ left = leftMargin;
+ top = topMargin;
+ width = 0;
+ for (i=0; i<BRUSH_ARRAY_SIZE; i++)
+ {
+ if (fAnyOfType[i])
+ {
+ GetTextExtentPoint32(
+ hdc,
+ LegendLabels[i],
+ lstrlen(LegendLabels[i]),
+ &size
+ );
+
+ elementWidth = (DWORD)size.cx + (5*g_wLegendItem/2);
+
+ if ( width != 0
+ && (width + elementWidth > allowedWidth))
+ {
+ top += g_wLegendItem + g_dyLegendSep; // row height + margin
+ left = leftMargin;
+ width = 0;
+ }
+
+ width += elementWidth;
+
+ hBrush = SelectBrush(hdc, g_Brushes[i]);
+
+ oldBkColor = SetBkColor(hdc, RGB(255, 255, 255));
+
+ Rectangle(
+ hdc,
+ left,
+ top,
+ left + g_wLegendItem,
+ top + g_wLegendItem
+ );
+
+ SetBkColor(hdc, oldBkColor);
+
+ ExtTextOut(
+ hdc,
+ left + (3*g_wLegendItem/2),
+ top + ((g_wLegendItem-size.cy)/2), // vertically center it
+ ETO_CLIPPED,
+ &rcClip,
+ LegendLabels[i],
+ lstrlen(LegendLabels[i]),
+ NULL
+ );
+
+ left += elementWidth;
+
+ if (NULL != hBrush)
+ {
+ SelectBrush(hdc, hBrush);
+ }
+ }
+ }
+
+ SelectClipRgn(hdc, NULL); // reset to no clipping region
+
+ if (NULL != hfontOld)
+ {
+ SelectFont(hdc, hfontOld);
+ }
+
+ SetTextColor(hdc, oldTextColor);
+}
+
+
+
+VOID
+DrawStatusAreaItem(
+ IN PRECT prc,
+ IN HDC hdc,
+ IN LPTSTR Text
+ )
+
+/*++
+
+Routine Description:
+
+ This routine draws a status area item into a given dc. This
+ includes drawing the nice shaded button-like container, and
+ then drawing text within it.
+
+Arguments:
+
+ prc - rectangle describing the status area item
+
+ hdc - device context into which to draw
+
+ Text - optional parameter that if present represents text to
+ be placed in the item.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HBRUSH hBrush;
+ RECT rcx;
+
+ // the shadow
+
+ if (NULL != (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW))))
+ {
+ // left edge
+
+ rcx.left = prc->left;
+ rcx.right = prc->left + g_dyBorder;
+ rcx.top = prc->top + (2*g_dyBorder);
+ rcx.bottom = prc->bottom - (2*g_dyBorder);
+ FillRect(hdc, &rcx, hBrush);
+
+ // top edge
+
+ rcx.right = prc->right;
+ rcx.bottom = rcx.top + g_dyBorder;
+ FillRect(hdc, &rcx, hBrush);
+
+ DeleteBrush(hBrush);
+ }
+
+ // the highlight
+
+ if (NULL != (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT))))
+ {
+ // right edge
+
+ rcx.left = prc->right - g_dyBorder;
+ rcx.right = prc->right;
+ rcx.top = prc->top + (2*g_dyBorder);
+ rcx.bottom = prc->bottom - (2*g_dyBorder);
+ FillRect(hdc, &rcx, hBrush);
+
+ // bottom edge
+
+ rcx.left = prc->left;
+ rcx.right = prc->right;
+ rcx.top = prc->bottom - (3*g_dyBorder);
+ rcx.bottom = rcx.top + g_dyBorder;
+ FillRect(hdc, &rcx, hBrush);
+
+ DeleteBrush(hBrush);
+ }
+
+ if (Text)
+ {
+ // draw the text
+
+ SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
+ SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
+
+ rcx.top = prc->top + (3*g_dyBorder);
+ rcx.bottom = prc->bottom - (3*g_dyBorder);
+ rcx.left = prc->left + g_dyBorder;
+ rcx.right = prc->right - g_dyBorder;
+
+ ExtTextOut(
+ hdc,
+ rcx.left+(2*g_dyBorder),
+ rcx.top,
+ ETO_OPAQUE | ETO_CLIPPED,
+ &rcx,
+ Text,
+ lstrlen(Text),
+ NULL
+ );
+ }
+}
diff --git a/private/utils/windisk/src/stleg.hxx b/private/utils/windisk/src/stleg.hxx
new file mode 100644
index 000000000..c3106b959
--- /dev/null
+++ b/private/utils/windisk/src/stleg.hxx
@@ -0,0 +1,50 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stleg.hxx
+//
+// Contents: Routines for handling the status bar and legend
+//
+// History: 26-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STLEG_HXX__
+#define __STLEG_HXX__
+
+VOID
+UpdateStatusBarDisplay(
+ VOID
+ );
+
+VOID
+ClearStatusArea(
+ VOID
+ );
+
+VOID
+DetermineExistence(
+ VOID
+ );
+
+VOID
+CalculateLegendHeight(
+ IN DWORD newGraphWidth
+ );
+
+VOID
+DrawLegend(
+ IN HDC hdc,
+ IN PRECT rc
+ );
+
+VOID
+DrawStatusAreaItem(
+ IN PRECT rc,
+ IN HDC hdc,
+ IN LPTSTR Text
+ );
+
+#endif // __STLEG_HXX__
diff --git a/private/utils/windisk/src/tb.h b/private/utils/windisk/src/tb.h
new file mode 100644
index 000000000..7ef159c6e
--- /dev/null
+++ b/private/utils/windisk/src/tb.h
@@ -0,0 +1,129 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tb.h
+//
+// Contents: Message APIs for the toolbar control
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TB_H__
+#define __TB_H__
+
+// void Toolbar_AddBitmap(HWND hwnd, int nButtons, HINSTANCE hBMInst, UINT nBMID);
+#define Toolbar_AddBitmap(hwnd, nButtons, hBMInst, nBMID) \
+ { TBADDBITMAP _tbBM; \
+ _tbBM.hInst = hBMInst; \
+ _tbBM.nID = nBMID; \
+ (int)SendMessage((hwnd),TB_ADDBITMAP,(WPARAM)(nButtons),(LPARAM)&_tbBM); \
+ }
+
+// BOOL Toolbar_AddButtons(HWND hwnd, int nButtons, LPTBBUTTON lpButtons);
+#define Toolbar_AddButtons(hwnd, nButtons, lpButtons) \
+ (BOOL)SendMessage((hwnd),TB_ADDBUTTONS,(WPARAM)(nButtons),(LPARAM)(LPTBBUTTON)(lpButtons))
+
+// int Toolbar_AddString(HWND hwnd, HINSTANCE hInst, UINT idString);
+#define Toolbar_AddString(hwnd, hInst, idString) \
+ (int)SendMessage((hwnd),TB_ADDSTRING,(WPARAM)(HINSTANCE)(hInst),(LPARAM)(MAKELPARAM((idString),0)))
+
+// void Toolbar_AutoSize(HWND hwnd);
+#define Toolbar_AutoSize(hwnd) \
+ (void)SendMessage((hwnd),TB_AUTOSIZE,(WPARAM)0,(LPARAM)0)
+
+// int Toolbar_ButtonCount(HWND hwnd);
+#define Toolbar_ButtonCount(hwnd) \
+ (int)SendMessage((hwnd),TB_BUTTONCOUNT,(WPARAM)0,(LPARAM)0)
+
+// int Toolbar_ButtonStructSize(HWND hwnd, int cb);
+#define Toolbar_ButtonStructSize(hwnd, cb) \
+ (int)SendMessage((hwnd),TB_BUTTONSTRUCTSIZE,(WPARAM)(cb),(LPARAM)0)
+
+// BOOL Toolbar_CheckButton(HWND hwnd, UINT idButton, BOOL fCheck);
+#define Toolbar_CheckButton(hwnd, idButton, fCheck) \
+ (BOOL)SendMessage((hwnd),TB_CHECKBUTTON,(WPARAM)(idButton),(LPARAM)MAKELPARAM((fCheck),0))
+
+// int Toolbar_CommandToIndex(HWND hwnd, UINT idButton);
+#define Toolbar_CommandToIndex(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_COMMANDTOINDEX,(WPARAM)(idButton),(LPARAM)0)
+
+// void Toolbar_Customize(HWND hwnd);
+#define Toolbar_Customize(hwnd) \
+ (void)SendMessage((hwnd),TB_CUSTOMIZE,(WPARAM)0,(LPARAM)0)
+
+// BOOL Toolbar_DeleteButton(HWND hwnd, UINT idButton);
+#define Toolbar_DeleteButton(hwnd, idButton) \
+ (BOOL)SendMessage((hwnd),TB_DELETEBUTTON,(WPARAM)(idButton),(LPARAM)0)
+
+// BOOL Toolbar_EnableButton(HWND hwnd, UINT idButton, BOOL fEnable);
+#define Toolbar_EnableButton(hwnd, idButton, fEnable) \
+ (BOOL)SendMessage((hwnd),TB_ENABLEBUTTON,(WPARAM)(idButton),(LPARAM)MAKELPARAM((fEnable),0))
+
+// BOOL Toolbar_GetButton(HWND hwnd, UINT iButton, LPTBBUTTON lpButton);
+#define Toolbar_GetButton(hwnd, iButton, lpButton) \
+ (BOOL)SendMessage((hwnd),TB_GETBUTTON,(WPARAM)(iButton),(LPARAM)(LPTBBUTTON)(lpButton))
+
+// BOOL Toolbar_GetItemRect(HWND hwnd, UINT iButton, LPRECT lpRect);
+#define Toolbar_GetItemRect(hwnd, iButton, lpRect) \
+ (BOOL)SendMessage((hwnd),TB_GETITEMRECT,(WPARAM)(iButton),(LPARAM)(LPRECT)(lpRect))
+
+// int Toolbar_GetState(HWND hwnd, UINT iButton);
+#define Toolbar_GetState(hwnd, iButton, lpRect) \
+ (int)SendMessage((hwnd),TB_GETSTATE,(WPARAM)(iButton),(LPARAM)0)
+
+// BOOL Toolbar_HideButton(HWND hwnd, UINT idButton, BOOL fShow);
+#define Toolbar_HideButton(hwnd, idButton, fShow) \
+ (BOOL)SendMessage((hwnd),TB_HIDEBUTTON,(WPARAM)(idButton),(LPARAM)MAKELPARAM((fShow),0))
+
+// BOOL Toolbar_Indeterminate(HWND hwnd, UINT iButton, BOOL fIndeterminate);
+#define Toolbar_Indeterminate(hwnd, iButton, fIndeterminate) \
+ (BOOL)SendMessage((hwnd),TB_INDETERMINATE,(WPARAM)(iButton),(LPARAM)MAKELPARAM((fIndeterminate),0))
+
+// BOOL Toolbar_InsertButton(HWND hwnd, UINT iButton, LPTBBUTTON lpButton);
+#define Toolbar_InsertButton(hwnd, iButton, lpButton) \
+ (BOOL)SendMessage((hwnd),TB_INSERTBUTTON,(WPARAM)(iButton),(LPARAM)(LPTBBUTTON)(lpButton))
+
+// int Toolbar_IsButtonChecked(HWND hwnd, UINT idButton);
+#define Toolbar_IsButtonChecked(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_ISBUTTONCHECKED,(WPARAM)(idButton),(LPARAM)0)
+
+// int Toolbar_IsButtonEnabled(HWND hwnd, UINT idButton);
+#define Toolbar_IsButtonEnabled(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_ISBUTTONENABLED,(WPARAM)(idButton),(LPARAM)0)
+
+// int Toolbar_IsButtonHidden(HWND hwnd, UINT idButton);
+#define Toolbar_IsButtonHidden(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_ISBUTTONHIDDEN,(WPARAM)(idButton),(LPARAM)0)
+
+// int Toolbar_IsButtonIndeterminate(HWND hwnd, UINT idButton);
+#define Toolbar_IsButtonIndeterminate(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_ISBUTTONINDETERMINATE,(WPARAM)(idButton),(LPARAM)0)
+
+// int Toolbar_IsButtonPressed(HWND hwnd, UINT idButton);
+#define Toolbar_IsButtonPressed(hwnd, idButton) \
+ (int)SendMessage((hwnd),TB_ISBUTTONPRESSED,(WPARAM)(idButton),(LPARAM)0)
+
+// BOOL Toolbar_PressButton(HWND hwnd, UINT idButton, BOOL fPress);
+#define Toolbar_PressButton(hwnd, idButton, fPress) \
+ (BOOL)SendMessage((hwnd),TB_PRESSBUTTON,(WPARAM)(idButton),(LPARAM)MAKELPARAM((fPress),0))
+
+// BOOL Toolbar_SaveRestore(HWND hwnd, BOOL fSave, TBSAVEPARAMS* lpSaveRestore);
+#define Toolbar_SaveRestore(hwnd, fSave, lpSaveRestore) \
+ (BOOL)SendMessage((hwnd),TB_SAVERESTORE,(WPARAM)(fSave),(LPARAM)(TBSAVEPARAMS*)(lpSaveRestore))
+
+// BOOL Toolbar_SetBitmapSize(HWND hwnd, WORD dxBitmap, WORD dyBitmap);
+#define Toolbar_SetBitmapSize(hwnd, dxBitmap, dyBitmap) \
+ (BOOL)SendMessage((hwnd),TB_SETBITMAPSIZE,(WPARAM)0,(LPARAM)MAKELPARAM((dxBitmap),(dyBitmap)))
+
+// BOOL Toolbar_SetButtonSize(HWND hwnd, WORD dxButton, WORD dyButton);
+#define Toolbar_SetButtonSize(hwnd, dxButton, dyButton) \
+ (BOOL)SendMessage((hwnd),TB_SETBUTTONSIZE,(WPARAM)0,(LPARAM)MAKELPARAM((dxButton),(dyButton)))
+
+// BOOL Toolbar_SetState(HWND hwnd, UINT idButton, BOOL fState);
+#define Toolbar_SetState(hwnd, idButton, fState) \
+ (BOOL)SendMessage((hwnd),TB_SETSTATE,(WPARAM)(idButton),(LPARAM)MAKELPARAM((fState),0))
+
+#endif // __TB_H__
diff --git a/private/utils/windisk/src/tbar.cxx b/private/utils/windisk/src/tbar.cxx
new file mode 100644
index 000000000..d15f8c86a
--- /dev/null
+++ b/private/utils/windisk/src/tbar.cxx
@@ -0,0 +1,701 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tbar.cxx
+//
+// Contents: Disk Administrator toolbar support routines.
+//
+// History: 7-Jun-93 BruceFo Created from NT winfile
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <util.hxx>
+
+#include "help.hxx"
+#include "help2.hxx"
+#include "profile.hxx"
+#include "stleg.hxx"
+#include "tb.h"
+#include "tbar.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+LRESULT
+Toolbar_OnGetButtonInfo(
+ IN OUT TBNOTIFY* ptbn
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+#define DX_BITMAP 16
+#define DY_BITMAP 16
+
+#define MAXDESCLEN 128
+
+#define TBAR_BITMAP_COUNT 14 /* number of std toolbar bitmaps */
+#define TBAR_EXTRA_BITMAPS 4
+
+/* Note that the idsHelp field is used internally to determine if the
+ * button is "available" or not.
+ */
+static TBBUTTON tbButtons[] =
+{
+ { 2, IDM_VIEWVOLUMES , TBSTATE_ENABLED, TBSTYLE_BUTTON, 0},
+ { 3, IDM_VIEWDISKS , TBSTATE_ENABLED, TBSTYLE_BUTTON, 0},
+ { 0, 0 , TBSTATE_ENABLED, TBSTYLE_SEP , 0},
+ { 11, IDM_VOL_PROPERTIES , TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}
+};
+
+#define TBAR_BUTTON_COUNT ARRAYLEN(tbButtons)
+
+
+struct BUTTON_MAP
+{
+ INT idM; // menu item id
+ INT idB; // button bitmap id
+};
+
+static BUTTON_MAP g_sServerButtons[] =
+{
+
+//
+// Partition menu
+//
+
+ IDM_PARTITIONCREATE, 0,
+ IDM_PARTITIONDELETE, 1,
+#if i386
+ IDM_PARTITIONACTIVE, 8,
+#else
+ IDM_SECURESYSTEM, 17,
+#endif
+
+// IDM_FTCREATEVOLUMESET
+
+ IDM_FTEXTENDVOLUMESET, 5,
+ IDM_QUIT, 15,
+
+//
+// Fault tolerance menu (Advanced Server only)
+//
+
+ IDM_FTESTABLISHMIRROR, 6,
+ IDM_FTBREAKMIRROR, 7,
+ IDM_FTCREATESTRIPE, 16,
+
+// IDM_FTRECOVERSTRIPE
+// IDM_FTCREATEPSTRIPE
+
+//
+// Tools menu
+//
+
+ IDM_VOL_FORMAT, 4,
+ IDM_VOL_PROPERTIES, 11,
+
+//
+// View menu
+//
+
+ IDM_VIEWVOLUMES, 2,
+ IDM_VIEWDISKS, 3,
+
+//
+// Options menu
+//
+
+ IDM_OPTIONSCOLORS, 9,
+ IDM_OPTIONSDISPLAY, 10,
+
+//
+// Help menu
+//
+
+ IDM_HELPCONTENTS, 12
+
+};
+
+
+static BUTTON_MAP g_sWorkstationButtons[] =
+{
+
+//
+// Partition menu
+//
+
+ IDM_PARTITIONCREATE, 0,
+ IDM_PARTITIONDELETE, 1,
+#if i386
+ IDM_PARTITIONACTIVE, 8,
+#else
+ IDM_SECURESYSTEM, 17,
+#endif
+
+// IDM_FTCREATEVOLUMESET
+
+ IDM_FTEXTENDVOLUMESET, 5,
+ IDM_QUIT, 15,
+
+//
+// Tools menu
+//
+
+ IDM_VOL_FORMAT, 4,
+ IDM_VOL_PROPERTIES, 11,
+
+//
+// View menu
+//
+
+ IDM_VIEWVOLUMES, 2,
+ IDM_VIEWDISKS, 3,
+
+//
+// Options menu
+//
+
+ IDM_OPTIONSCOLORS, 9,
+ IDM_OPTIONSDISPLAY, 10,
+
+//
+// Help menu
+//
+
+ IDM_HELPCONTENTS, 12
+
+};
+
+
+static BUTTON_MAP* g_sButtons; // points to the right one based on platform
+static UINT g_cButtons; // correct count based on platform
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetToolbarButtonState
+//
+// Synopsis: set the state of the toolbar buttons based on menu state
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetToolbarButtonState(
+ VOID
+ )
+{
+ UINT i;
+ int idCommand;
+ HMENU hMenu;
+ UINT state;
+
+ // Set the states correctly
+
+ hMenu = GetMenu(g_hwndFrame);
+
+ for (i=0; i<g_cButtons; ++i)
+ {
+ idCommand = g_sButtons[i].idM;
+ state = GetMenuState(hMenu, idCommand, MF_BYCOMMAND);
+
+ if (state != 0xFFFFFFFF)
+ {
+ Toolbar_CheckButton(
+ g_hwndToolbar,
+ idCommand,
+ state & MF_CHECKED);
+
+ Toolbar_EnableButton(
+ g_hwndToolbar,
+ idCommand,
+ !(state & (MF_DISABLED | MF_GRAYED)));
+ }
+ else
+ {
+ Toolbar_HideButton(g_hwndToolbar, idCommand, TRUE);
+ }
+ }
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ResetToolbar
+//
+// Synopsis: resets the toolbar to the standard state
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 2-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ResetToolbar(
+ VOID
+ )
+{
+ INT nItem;
+ INT i, idCommand;
+ HMENU hMenu;
+ UINT state;
+
+ // Remove from back to front as a speed optimization
+
+ for (nItem = Toolbar_ButtonCount(g_hwndToolbar) - 1;
+ nItem >= 0;
+ --nItem)
+ {
+ Toolbar_DeleteButton(g_hwndToolbar, nItem);
+ }
+
+ // Add the default list of buttons
+
+ Toolbar_AddButtons(g_hwndToolbar, TBAR_BUTTON_COUNT, tbButtons);
+
+ // Set the states correctly
+
+ hMenu = GetMenu(g_hwndFrame);
+
+ for (i=0; i<TBAR_BUTTON_COUNT; ++i)
+ {
+ if (tbButtons[i].fsStyle == TBSTYLE_SEP)
+ {
+ continue;
+ }
+
+ idCommand = tbButtons[i].idCommand;
+ state = GetMenuState(hMenu, idCommand, MF_BYCOMMAND);
+
+ Toolbar_CheckButton(
+ g_hwndToolbar,
+ idCommand,
+ state & MF_CHECKED);
+
+ Toolbar_EnableButton(
+ g_hwndToolbar,
+ idCommand,
+ !(state & (MF_DISABLED | MF_GRAYED)));
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LoadDesc
+//
+// Synopsis: Given a menu command identifier, determine its description
+// string
+//
+// Arguments: [uID] -- menu id (e.g., IDM_VOL_PROPERTIES)
+// [pDesc] -- string buffer to fill, with up to MAXDESCLEN
+// characters
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+static VOID
+LoadDesc(
+ IN UINT uID,
+ OUT PWSTR pDesc
+ )
+{
+ HMENU hMenu;
+ WCHAR szFormat[20];
+ WCHAR szMenu[20];
+ WCHAR szItem[MAXDESCLEN - ARRAYLEN(szMenu)];
+ PWSTR pIn;
+ UINT uMenu;
+
+ szItem[0] = *pDesc = TEXT('\0');
+
+ hMenu = GetMenu(g_hwndFrame);
+
+ uMenu = uID;
+ if (!g_IsLanmanNt && (uMenu > IDM_FTRECOVERSTRIPE))
+ {
+ //
+ // In the workstation (non-server) case, we need to remove the FT
+ // menu from consideration. Since we are calculating an index into
+ // the menu by compile-time menu ids, simply subract off one menu
+ // range if the id is greater than the last FT item.
+ //
+
+ uMenu -= IDM_MENU_DELTA;
+ }
+
+ //
+ // generate a 0-based index for GetMenuString
+ //
+ uMenu = (uMenu - IDM_FIRST_MENU) / IDM_MENU_DELTA;
+
+ GetMenuString(hMenu, uMenu, szMenu, ARRAYLEN(szMenu), MF_BYPOSITION);
+
+ if (GetMenuString(hMenu, uID, szItem, ARRAYLEN(szItem), MF_BYCOMMAND) <= 0)
+ {
+ //
+ // unknown menu id
+ //
+
+ return;
+ }
+
+ LoadString(g_hInstance, IDS_MENUANDITEM, szFormat, ARRAYLEN(szFormat));
+ wsprintf(pDesc, szFormat, szMenu, szItem);
+
+ // Remove the ampersands
+
+ for (pIn=pDesc; ; ++pIn, ++pDesc)
+ {
+ WCHAR cTemp;
+
+ cTemp = *pIn;
+ if (cTemp == TEXT('&'))
+ {
+ cTemp = *(++pIn);
+ }
+
+ if (cTemp == TEXT('\t'))
+ {
+ cTemp = TEXT('\0');
+ }
+
+ *pDesc = cTemp;
+ if (cTemp == TEXT('\0'))
+ {
+ break;
+ }
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckTBButton
+//
+// Synopsis: Treat the "volumes view" and "disks view" buttons as
+// mutually exclusive: exactly one must be up at any time.
+//
+// Arguments: [idCommand] -- either IDM_VIEWVOLUMES or IDM_VIEWDISKS
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CheckTBButton(
+ IN DWORD idCommand
+ )
+{
+ UINT i, begin, end;
+
+ //
+ // Make sure to "pop-up" any other buttons in the group.
+ //
+ if ((UINT)(idCommand-IDM_VIEWVOLUMES) <= IDM_VIEWDISKS-IDM_VIEWVOLUMES)
+ {
+ begin = IDM_VIEWVOLUMES;
+ end = IDM_VIEWDISKS;
+ }
+ else
+ {
+ begin = end = (UINT)idCommand;
+ }
+
+ for (i=begin; i<=end; ++i)
+ {
+ Toolbar_CheckButton(g_hwndToolbar, i, i==idCommand);
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDAToolbar
+//
+// Synopsis: Create a toolbar control for the Disk Administrator
+//
+// Arguments: [hwndParent] -- the parent (frame) window
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CreateDAToolbar(
+ IN HWND hwndParent
+ )
+{
+ // We'll start out by adding no buttons; that will be done in
+ // InitToolbarButtons
+
+ g_hwndToolbar = CreateToolbarEx(
+ hwndParent, // parent
+ WS_CHILD
+ | CCS_ADJUSTABLE
+ | TBSTYLE_TOOLTIPS
+ | (g_Toolbar ? WS_VISIBLE : 0)
+ ,
+ IDC_TOOLBAR, // toolbar id
+ TBAR_BITMAP_COUNT, // number of bitmaps
+ g_hInstance, // module instance
+ IDB_TOOLBAR, // resource id for the bitmap
+ tbButtons, // address of buttons
+ TBAR_BUTTON_COUNT, // number of buttons
+ DX_BITMAP, DY_BITMAP, // width & height of the buttons
+ DX_BITMAP, DY_BITMAP, // width & height of the bitmaps
+ sizeof(TBBUTTON)); // structure size
+
+ if (g_hwndToolbar == NULL)
+ {
+ daDebugOut((DEB_ERROR, "Couldn't create toolbar!\n"));
+ return;
+ }
+
+ //
+ // Load up the second bitmap
+ //
+
+ Toolbar_AddBitmap(
+ g_hwndToolbar,
+ TBAR_EXTRA_BITMAPS,
+ g_hInstance,
+ IDB_EXTRATOOLS
+ );
+
+ //
+ // Calculate toolbar height
+ //
+
+ RECT rc;
+ GetWindowRect(g_hwndToolbar, &rc);
+ g_dyToolbar = rc.bottom - rc.top;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitToolbarButtons
+//
+// Synopsis: Initialize the visual state of the buttons on the toolbar.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+InitToolbarButtons(
+ VOID
+ )
+{
+ if (g_IsLanmanNt)
+ {
+ g_sButtons = g_sServerButtons;
+ g_cButtons = ARRAYLEN(g_sServerButtons);
+ }
+ else
+ {
+ g_sButtons = g_sWorkstationButtons;
+ g_cButtons = ARRAYLEN(g_sWorkstationButtons);
+ }
+
+ SaveRestoreToolbar(FALSE);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Toolbar_OnGetButtonInfo
+//
+// Synopsis: Get the information for a button during customization
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 26-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+Toolbar_OnGetButtonInfo(
+ IN OUT TBNOTIFY* ptbn
+ )
+{
+ if (ptbn->iItem < (int)g_cButtons)
+ {
+ daDebugOut((DEB_ITRACE, "Getting button %d\n", ptbn->iItem));
+
+ WCHAR szDescription[MAXDESCLEN];
+
+ ptbn->tbButton.iBitmap = g_sButtons[ptbn->iItem].idB;
+ ptbn->tbButton.idCommand = g_sButtons[ptbn->iItem].idM;
+ ptbn->tbButton.fsState = TBSTATE_ENABLED;
+ ptbn->tbButton.fsStyle = TBSTYLE_BUTTON;
+ ptbn->tbButton.dwData = 0;
+ ptbn->tbButton.iString = 0;
+
+ LoadDesc(ptbn->tbButton.idCommand, szDescription);
+ wcsncpy(ptbn->pszText, szDescription, min(1+lstrlen(szDescription), ptbn->cchText));
+
+ daDebugOut((DEB_ITRACE,
+ "Got button %d, cchText %d, return \"%ws\"\n",
+ ptbn->iItem,
+ ptbn->cchText,
+ ptbn->pszText));
+
+ return (LRESULT)TRUE;
+ }
+ else
+ {
+ daDebugOut((DEB_ITRACE, "Didn't get button %d\n", ptbn->iItem));
+
+ return (LRESULT)FALSE;
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: HandleToolbarNotify
+//
+// Synopsis: Handles toolbar notifications via WM_NOTIFY
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 29-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+HandleToolbarNotify(
+ IN TBNOTIFY* ptbn
+ )
+{
+ switch (ptbn->hdr.code)
+ {
+ case TBN_QUERYINSERT:
+ case TBN_QUERYDELETE:
+ return TRUE; // allow any deletion or insertion
+
+ case TBN_BEGINADJUST:
+ case TBN_ENDADJUST:
+ break; // return value ignored
+
+ case TBN_GETBUTTONINFO:
+ daDebugOut((DEB_ITRACE, "TBN_GETBUTTONINFO\n"));
+ return Toolbar_OnGetButtonInfo(ptbn);
+
+ case TBN_RESET:
+// daDebugOut((DEB_TRACE, "TBN_RESET\n"));
+
+ ResetToolbar();
+ break;
+
+ case TBN_TOOLBARCHANGE:
+// daDebugOut((DEB_TRACE, "TBN_TOOLBARCHANGE\n"));
+
+ SetToolbarButtonState();
+ SaveRestoreToolbar(TRUE);
+ break;
+
+ case TBN_CUSTHELP:
+// daDebugOut((DEB_ITRACE, "TBN_CUSTHELP\n"));
+
+ DialogHelp(HC_DM_DLG_CUSTOMIZETOOL);
+ break;
+
+ case TBN_BEGINDRAG:
+// daDebugOut((DEB_ITRACE, "TBN_BEGINDRAG (command %d)\n",
+// ptbn->iItem)); // actually, the command, not the item!
+
+ //
+ // display help for the item
+ //
+
+ DrawMenuHelpItem(NULL, ptbn->iItem, 0);
+ break;
+
+ case TBN_ENDDRAG:
+// daDebugOut((DEB_ITRACE, "TBN_ENDDRAG\n"));
+
+ //
+ // stop displaying help
+ //
+
+ g_fDoingMenuHelp = FALSE;
+ UpdateStatusBarDisplay();
+
+ break;
+ } // end switch
+
+ return 0L;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: HandleTooltipNotify
+//
+// Synopsis: Handles tool tips notifications via WM_NOTIFY. The only
+// tooltips in windisk are toolbar tips.
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 29-Sep-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+HandleTooltipNotify(
+ IN TOOLTIPTEXT* pttt
+ )
+{
+ pttt->hinst = g_hInstance;
+ pttt->lpszText = MAKEINTRESOURCE(GetTooltip(pttt->hdr.idFrom));
+ // command ID to get tip for
+ return 0L; // ignored
+}
diff --git a/private/utils/windisk/src/tbar.hxx b/private/utils/windisk/src/tbar.hxx
new file mode 100644
index 000000000..be36422aa
--- /dev/null
+++ b/private/utils/windisk/src/tbar.hxx
@@ -0,0 +1,52 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tbar.hxx
+//
+// Contents: Disk Administrator toolbar support routines.
+//
+// History: 2-Sep-93 BruceFo Created from NT winfile
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TBAR_HXX__
+#define __TBAR_HXX__
+
+VOID
+SetToolbarButtonState(
+ VOID
+ );
+
+VOID
+ResetToolbar(
+ VOID
+ );
+
+VOID
+CheckTBButton(
+ IN DWORD idCommand
+ );
+
+VOID
+CreateDAToolbar(
+ IN HWND hwndParent
+ );
+
+VOID
+InitToolbarButtons(
+ VOID
+ );
+
+LRESULT
+HandleToolbarNotify(
+ IN TBNOTIFY* ptbn
+ );
+
+LRESULT
+HandleTooltipNotify(
+ IN TOOLTIPTEXT* pttt
+ );
+
+#endif // __TBAR_HXX__
diff --git a/private/utils/windisk/src/tool16.bmp b/private/utils/windisk/src/tool16.bmp
new file mode 100644
index 000000000..df6d247b5
--- /dev/null
+++ b/private/utils/windisk/src/tool16.bmp
Binary files differ
diff --git a/private/utils/windisk/src/trffc14.ico b/private/utils/windisk/src/trffc14.ico
new file mode 100644
index 000000000..3de105412
--- /dev/null
+++ b/private/utils/windisk/src/trffc14.ico
Binary files differ
diff --git a/private/utils/windisk/src/types.hxx b/private/utils/windisk/src/types.hxx
new file mode 100644
index 000000000..d27d7b213
--- /dev/null
+++ b/private/utils/windisk/src/types.hxx
@@ -0,0 +1,489 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: types.hxx
+//
+// Contents: Type declarations
+//
+// History: 7-Jan-92 TedM Created
+// 16-Aug-93 BruceFo Added Cairo support
+// 11-Nov-93 BobRi DoubleSpace & Commit support
+// 2-Feb-94 BobRi moved arcinst data here
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TYPES_HXX__
+#define __TYPES_HXX__
+
+//
+// Partitioning engine types
+//
+
+//
+// This structure is used to hold the information returned by the
+// get drive geometry call.
+//
+
+typedef struct _DISKGEOM
+{
+ LARGE_INTEGER Cylinders;
+ ULONG Heads;
+ ULONG SectorsPerTrack;
+ ULONG BytesPerSector;
+ // These two are not part of drive geometry info, but calculated from it.
+ ULONG BytesPerCylinder;
+ ULONG BytesPerTrack;
+} DISKGEOM, *PDISKGEOM;
+
+
+
+typedef enum
+{
+ REGION_PRIMARY,
+ REGION_EXTENDED,
+ REGION_LOGICAL
+} REGION_TYPE;
+
+
+// These structures are used in doubly-linked per disk lists that
+// describe the layout of the disk.
+//
+// Free spaces are indicated by entries with a SysID of 0 (note that
+// these entries don't actually appear anywhere on-disk!)
+//
+// The partition number is the number the system will assign to
+// the partition in naming it. For free spaces, this is the number
+// that the system WOULD assign to it if it was a partition.
+// The number is good only for one transaction (create or delete),
+// after which partitions must be renumbered.
+
+struct _PERSISTENT_REGION_DATA;
+
+typedef struct _PARTITION
+{
+ struct _PARTITION* Next;
+ struct _PARTITION* Prev;
+ struct _PERSISTENT_REGION_DATA* PersistentData;
+
+ LARGE_INTEGER Offset;
+ LARGE_INTEGER Length;
+ PARTITION_INFORMATION OriginalPartitionInformation;
+ ULONG Disk;
+ ULONG OriginalPartitionNumber;
+ ULONG PartitionNumber;
+ ULONG OriginalLayoutEntrySlot;
+ BOOLEAN EntryCameFromLayout;
+ BOOLEAN Update;
+ BOOLEAN Active;
+ BOOLEAN Recognized;
+ UCHAR SysID;
+ BOOLEAN CommitMirrorBreakNeeded;
+} PARTITION, *PPARTITION;
+
+
+typedef struct _REGION_DATA
+{
+ PPARTITION Partition;
+ LARGE_INTEGER AlignedRegionOffset;
+ LARGE_INTEGER AlignedRegionSize;
+} REGION_DATA, *PREGION_DATA;
+
+//
+// DoubleSpace support structure. This is tagged off of the persistent data
+// for each region.
+//
+
+typedef struct _DBLSPACE_DESCRIPTOR
+{
+ struct _DBLSPACE_DESCRIPTOR* Next;
+ struct _DBLSPACE_DESCRIPTOR* DblChainNext;
+
+ ULONG AllocatedSize;
+ PWSTR FileName;
+ WCHAR DriveLetter;
+ BOOLEAN Mounted;
+ BOOLEAN ChangeMountState;
+ WCHAR NewDriveLetter;
+ BOOLEAN ChangeDriveLetter;
+} DBLSPACE_DESCRIPTOR, *PDBLSPACE_DESCRIPTOR;
+
+
+//
+// structure that describes an ft object (mirror, stripe component, etc).
+//
+struct _FT_OBJECT_SET;
+struct _REGION_DESCRIPTOR;
+typedef struct _FT_OBJECT
+{
+ struct _FT_OBJECT* Next;
+ struct _FT_OBJECT_SET* Set;
+ ULONG MemberIndex;
+ FT_PARTITION_STATE State;
+ struct _REGION_DESCRIPTOR* Region;
+} FT_OBJECT, *PFT_OBJECT;
+
+
+//
+// Enum for the states in which an ft set can be.
+//
+
+typedef enum _FT_SET_STATUS
+{
+ FtSetHealthy,
+ FtSetBroken,
+ FtSetRecoverable,
+ FtSetRecovered,
+ FtSetNew,
+ FtSetNewNeedsInitialization,
+ FtSetExtended,
+ FtSetInitializing,
+ FtSetRegenerating,
+ FtSetInitializationFailed,
+ FtSetDisabled
+} FT_SET_STATUS, *PFT_SET_STATUS;
+
+
+//
+// structure that describes an ft object set (ie, mirrored pair, stripe set).
+//
+
+typedef struct _FT_OBJECT_SET
+{
+ struct _FT_OBJECT_SET* Next;
+
+ FT_TYPE Type;
+ ULONG Ordinal;
+ PFT_OBJECT Members;
+ PFT_OBJECT Member0;
+ FT_SET_STATUS Status;
+ ULONG NumberOfMembers;
+
+ //
+ // This flag is used when we are iterating over "volumes", and wish
+ // to touch FT regions only once.
+ //
+ BOOL Flag;
+
+} FT_OBJECT_SET, *PFT_OBJECT_SET;
+
+
+
+//
+// Define the structure that is associated with each non-extended, recognized
+// partition. This structure is associated with the partition, and persists
+// across region array free/get from the back end. It is used for logical
+// and ft information.
+//
+
+typedef struct _PERSISTENT_REGION_DATA
+{
+ PFT_OBJECT FtObject;
+
+ PWSTR VolumeLabel;
+ PWSTR TypeName;
+ WCHAR DriveLetter;
+
+ //
+ // NewRegion: TRUE if this region was created during the current session
+ //
+
+ BOOL NewRegion;
+
+ //
+ // Volume space information
+ //
+
+ LARGE_INTEGER FreeSpaceInBytes;
+ LARGE_INTEGER TotalSpaceInBytes;
+
+#if defined( DBLSPACE_ENABLED )
+ //
+ // DoubleSpace information
+ //
+
+ PDBLSPACE_DESCRIPTOR DblSpace;
+#endif // DBLSPACE_ENABLED
+
+} PERSISTENT_REGION_DATA, *PPERSISTENT_REGION_DATA;
+
+
+
+typedef struct _REGION_DESCRIPTOR
+{
+ PPERSISTENT_REGION_DATA PersistentData;
+ PREGION_DATA Reserved;
+ ULONG Disk;
+ ULONG PartitionNumber;
+ ULONG OriginalPartitionNumber;
+ ULONG SizeMB;
+ REGION_TYPE RegionType;
+ BOOLEAN Active;
+ BOOLEAN Recognized;
+ UCHAR SysID;
+} REGION_DESCRIPTOR, *PREGION_DESCRIPTOR;
+
+
+typedef struct _LEFTRIGHT
+{
+ LONG Left;
+ LONG Right;
+} LEFTRIGHT, *PLEFTRIGHT;
+
+
+//
+// Types of views that can be used for a disk bar.
+//
+// Proportional means that the amount of space taken up in the bar is
+// directly proportional to the size of the partition or free space
+// Equal means that all free spaces and partitions are sized equally on
+// screen regardless of their actual size
+//
+
+typedef enum _BAR_TYPE
+{
+ BarProportional,
+ BarEqual,
+ BarAuto
+} BAR_TYPE, *PBAR_TYPE;
+
+
+//
+// Type of display of disks
+//
+
+typedef enum _DISK_TYPE
+{
+ DiskProportional,
+ DiskEqual
+} DISK_TYPE, *PDISK_TYPE;
+
+
+//
+// One DISKSTATE structure is associated with each item in the
+// listbox. The structure is the crux of the implementation.
+//
+
+typedef struct _DISKSTATE
+{
+ ULONG Disk; // number of disk
+ ULONG DiskSizeMB; // size in MB of disk
+ ULONG RegionCount; // # items in region array
+
+ PREGION_DESCRIPTOR RegionArray; // RegionCount-size region array
+ PBOOLEAN Selected; // RegionCount-size array for whether
+ //... each region is selected
+ PLEFTRIGHT LeftRight; // RegionCount-size array for left/
+ //...right coords of boxes in graph
+
+ BOOLEAN CreateAny; // any creations allowed on disk?
+ BOOLEAN CreatePrimary; // allowed to create primary partition?
+ BOOLEAN CreateExtended; // allowed to create extended partition?
+ BOOLEAN CreateLogical; // allowed to create logical volume?
+ BOOLEAN ExistAny; // any partitions/logicals exist?
+ BOOLEAN ExistPrimary; // primary partition(s) exist?
+ BOOLEAN ExistExtended; // extended partition exists?
+ BOOLEAN ExistLogical; // logical volume(s) exist?
+ HDC hDCMem; // for off-screen drawing
+ HBITMAP hbmMem; // for offscreen bitmap
+ ULONG Signature; // unique disk registry index
+ BAR_TYPE BarType; // how to display the disk's bar
+ BOOLEAN SigWasCreated; // whether we had to make up a sig
+ BOOLEAN OffLine; // FALSE if disk is accessible.
+
+#ifdef WINDISK_EXTENSIONS
+ struct HARDDISK_CLAIM_LIST* pClaims; // pointer to extension claim list
+ //... for this disk
+#endif // WINDISK_EXTENSIONS
+
+} DISKSTATE, *PDISKSTATE;
+
+
+
+//
+// CdRom support structures.
+//
+
+typedef struct _CDROM_DESCRIPTOR
+{
+ PWSTR DeviceName;
+ ULONG DeviceNumber;
+ WCHAR DriveLetter;
+
+ HDC hDCMem;
+ HBITMAP hbmMem;
+ BOOLEAN Selected;
+ LEFTRIGHT LeftRight;
+
+ PWSTR VolumeLabel;
+ PWSTR TypeName;
+ ULONG TotalSpaceInMB;
+} CDROM_DESCRIPTOR, *PCDROM_DESCRIPTOR;
+
+
+//
+// Commit support structures
+//
+
+typedef struct _DRIVE_LOCKLIST
+{
+ struct _DRIVE_LOCKLIST* Next;
+
+ HANDLE LockHandle;
+ ULONG DiskNumber;
+ ULONG PartitionNumber;
+ ULONG LockOnDiskNumber;
+ ULONG UnlockOnDiskNumber;
+ WCHAR DriveLetter;
+ BOOLEAN RemoveOnUnlock;
+ BOOLEAN FailOk;
+ BOOLEAN CurrentlyLocked;
+} DRIVE_LOCKLIST, *PDRIVE_LOCKLIST;
+
+
+//
+// List of drive letters to assign
+//
+
+typedef struct _ASSIGN_LIST
+{
+ struct _ASSIGN_LIST* Next;
+
+ ULONG DiskNumber;
+ BOOLEAN MoveLetter;
+ WCHAR OriginalLetter;
+ WCHAR DriveLetter;
+} ASSIGN_LIST, *PASSIGN_LIST;
+
+//
+// The View type
+//
+
+enum VIEW_TYPE
+{
+ VIEW_VOLUMES,
+ VIEW_DISKS
+};
+
+#ifdef WINDISK_EXTENSIONS
+
+/////////////////////////////////////////////////////////////////////////
+
+//
+// Extension types
+//
+
+struct OneExtension
+{
+ CLSID* pcls;
+ IUnknown* pUnk;
+};
+
+struct ExtensionType
+{
+ CLSID** pcls;
+ ULONG cClasses;
+};
+
+enum ExtensionIndices
+{
+ EX_VOLUME = 0,
+ EX_DISK = 1
+};
+
+#define EX_NUM_EXTENSION_TYPES 2
+
+/////////////////////////////////////////////////////////////////////////
+
+struct HARDDISK_INFO
+{
+ IDAHardDiskInfo* pExtension;
+ HardDiskInfoType* pInfo;
+};
+
+struct HARDDISK_CLAIM_LIST
+{
+ HARDDISK_CLAIM_LIST* pNext;
+ HARDDISK_INFO* pClaimer;
+};
+typedef HARDDISK_CLAIM_LIST* PHARDDISK_CLAIM_LIST;
+
+//////////////////////////////////////////////
+
+struct VOL_INFO
+{
+ IDAVolumeInfo* pExtension;
+ VolumeInfoType* pInfo;
+};
+
+struct VOL_CLAIM_LIST
+{
+ VOL_CLAIM_LIST* pNext;
+ VOL_INFO* pClaimer;
+};
+typedef VOL_CLAIM_LIST* PVOL_CLAIM_LIST;
+
+//////////////////////////////////////////////////////////////////////////
+
+//
+// VOLUME_INFO: this structure represents the interesting information
+// for a single volume (i.e., something denoted by a drive letter).
+// There is a list of claimers for file system and volume extension
+// classes. The volume is identified by a PDISKSTATE and region index,
+// which together uniquely identifies a region. This region must be a used
+// (not free) region. If it is an FT set, any of the FT components can be
+// used to identify the volume.
+//
+struct VOLUME_INFO
+{
+ PVOL_CLAIM_LIST VolClaims;
+ PDISKSTATE DiskState;
+ INT RegionIndex;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+#endif // WINDISK_EXTENSIONS
+
+//
+// params for the MinMax dialog -- used at WM_INITDIALOG time
+//
+
+typedef struct _tagMINMAXDLG_PARAMS
+{
+ DWORD CaptionStringID;
+ DWORD MinimumStringID;
+ DWORD MaximumStringID;
+ DWORD SizeStringID;
+ DWORD MinSizeMB;
+ DWORD MaxSizeMB;
+ DWORD HelpContextId;
+} MINMAXDLG_PARAMS, *PMINMAXDLG_PARAMS;
+
+//
+// params for the DriveLetter dialog -- used at WM_INITDIALOG time
+//
+
+typedef struct _DRIVELET_DLG_PARAMS
+{
+ IN PWSTR Description;
+ IN WCHAR DriveLetter;
+ OUT WCHAR NewDriveLetter;
+} DRIVELET_DLG_PARAMS, *PDRIVELET_DLG_PARAMS;
+
+//
+// params for the DoubleSpace dialog -- used at WM_INITDIALOG time
+//
+
+typedef struct _DBLSPACE_PARAMS
+{
+ DWORD CaptionStringID;
+ PVOID RegionDescriptor;
+ PPERSISTENT_REGION_DATA RegionData;
+ PDBLSPACE_DESCRIPTOR DblSpace;
+} DBLSPACE_PARAMS, *PDBLSPACE_PARAMS;
+
+
+
+#endif // __TYPES_HXX__
diff --git a/private/utils/windisk/src/unused/startup.cxx b/private/utils/windisk/src/unused/startup.cxx
new file mode 100644
index 000000000..0f26bd005
--- /dev/null
+++ b/private/utils/windisk/src/unused/startup.cxx
@@ -0,0 +1,166 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: startup.cxx
+//
+// Contents: (Unused) code to provide an "app is starting" dialog.
+// Unfortunately, I haven't been able to figure out all the
+// foreground/background active/inactive window focus problems
+//
+// History: 20-Apr-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+HWND g_hwndStartup;
+#define MYWM_ENDSTARTUP WM_USER
+
+//+-------------------------------------------------------------------------
+//
+// Function: StartupDlgProc, private
+//
+// Synopsis: Dialog procedure for the startup dialog
+//
+// Arguments: standard Windows dialog procedure
+//
+// Returns: standard Windows dialog procedure
+//
+// History: 23-Feb-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL CALLBACK
+StartupDlgProc(
+ IN HWND hDlg,
+ IN UINT uMsg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ g_hwndStartup = hDlg;
+ CenterWindow(hDlg, NULL);
+ return 1; // didn't call SetFocus
+
+ case MYWM_ENDSTARTUP:
+ EndDialog(hDlg, TRUE);
+ return 1;
+
+ default:
+ return 0; // didn't process
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StartupThread
+//
+// Synopsis: Thread routine called for Disk Administrator startup
+//
+// Arguments: [ThreadParameter] -- unused
+//
+// Returns: 0
+//
+// History: 23-Feb-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+LOCAL DWORD WINAPI
+StartupThread(
+ IN LPVOID ThreadParameter
+ )
+{
+ DialogBox(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_STARTUP),
+ NULL,
+ StartupDlgProc
+ );
+ return 0;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BeginStartup
+//
+// Synopsis: Puts up a dialog box indicating that Disk Administrator is
+// initializing
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// Requires: g_hInstance must be set already
+//
+// History: 23-Feb-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+BeginStartup(
+ VOID
+ )
+{
+ DWORD threadId;
+ HANDLE hThread;
+
+ g_hwndStartup = NULL;
+
+ hThread = CreateThread(
+ NULL,
+ 0,
+ StartupThread,
+ NULL,
+ 0,
+ &threadId
+ );
+
+ if (NULL == hThread)
+ {
+ daDebugOut((DEB_ERROR, "Error creating startup thread\n"));
+ return;
+ }
+
+ // No reason to keep handle around
+
+ CloseHandle(hThread);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EndStartup
+//
+// Synopsis: Kills the "startup" dialog box
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 23-Feb-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+EndStartup(
+ VOID
+ )
+{
+ if (NULL != g_hwndStartup)
+ {
+ PostMessage(g_hwndStartup, MYWM_ENDSTARTUP, 0, 0);
+ g_hwndStartup = NULL;
+ }
+}
diff --git a/private/utils/windisk/src/unused/startup.hxx b/private/utils/windisk/src/unused/startup.hxx
new file mode 100644
index 000000000..2f44a98c5
--- /dev/null
+++ b/private/utils/windisk/src/unused/startup.hxx
@@ -0,0 +1,27 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: startup.hxx
+//
+// Contents: (Unused) code to provide an "app is starting" dialog.
+//
+// History: 20-Apr-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STARTUP_HXX__
+#define __STARTUP_HXX__
+
+VOID
+BeginStartup(
+ VOID
+ );
+
+VOID
+EndStartup(
+ VOID
+ );
+
+#endif // __STARTUP_HXX__
diff --git a/private/utils/windisk/src/unused/time.cxx b/private/utils/windisk/src/unused/time.cxx
new file mode 100644
index 000000000..b0de622d7
--- /dev/null
+++ b/private/utils/windisk/src/unused/time.cxx
@@ -0,0 +1,599 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: time.cxx
+//
+// Contents: Functions dealing with time, relating to time stamping
+// chkdsk. All functions will be prefixed by "Ts", meaning
+// "time stamp".
+//
+// Functions:
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include "time.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+WCHAR KeyProto[] = L"\\registry\\machine\\system\\VolumeInfo\\%c:\\%s";
+WCHAR KeyProto1[] = L"\\registry\\machine\\system\\VolumeInfo";
+WCHAR KeyProto2[] = L"\\%c:";
+WCHAR KeyProto3[] = L"\\%s";
+WCHAR KeyProto4[] = L"\\registry\\machine\\system\\VolumeInfo\\%c:";
+WCHAR ClassName[] = L"Volume information";
+WCHAR ValueName[] = L"TimeStamp";
+
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+NTSTATUS
+TspOpenKey(
+ OUT PHANDLE HandlePtr,
+ IN PWSTR KeyName
+ )
+
+/*++
+
+Routine Description:
+
+ Given a null-terminated UNICODE key name, this routine will open the key
+ in the configuration registry and return the HANDLE to the caller.
+
+Arguments:
+
+ HandlePtr - location for HANDLE on success.
+ KeyName - UNICODE string for the key to be opened.
+
+Return Value:
+
+ NTSTATUS - from the config registry calls.
+
+--*/
+
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objectAttributes;
+ UNICODE_STRING keyName;
+
+ RtlInitUnicodeString(&keyName, KeyName);
+
+ memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
+ InitializeObjectAttributes(&objectAttributes,
+ &keyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ status = NtOpenKey(HandlePtr, MAXIMUM_ALLOWED, &objectAttributes);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't open key %ws\n",KeyName));
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+TspCreateKey(
+ OUT PHANDLE HandlePtr,
+ IN PWSTR KeyName,
+ IN PWSTR KeyClass,
+ IN ULONG Index
+ )
+
+/*++
+
+Routine Description:
+
+ Given a UNICODE name, this routine will create a key in the configuration
+ registry.
+
+Arguments:
+
+ HandlePtr - location for HANDLE on success.
+ KeyName - UNICODE string, the name of the key to create.
+ KeyClass - registry class for the new key.
+ Index - registry index value for the new key.
+
+Return Value:
+
+ NTSTATUS - from the config registry calls.
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING keyName;
+ UNICODE_STRING className;
+ OBJECT_ATTRIBUTES objectAttributes;
+ ULONG disposition;
+ HANDLE tempHandle;
+
+ //
+ // Initialize the object for the key.
+ //
+
+ RtlInitUnicodeString(&keyName, KeyName);
+
+ memset(&objectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
+ InitializeObjectAttributes(&objectAttributes,
+ &keyName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ //
+ // Setup the unicode class value.
+ //
+
+ RtlInitUnicodeString(&className, KeyClass);
+
+ //
+ // Create the key.
+ //
+
+ status = NtCreateKey(&tempHandle,
+ KEY_READ | KEY_WRITE,
+ &objectAttributes,
+ Index,
+ &className,
+ REG_OPTION_NON_VOLATILE,
+ &disposition);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't create key %ws\n",keyName));
+ }
+
+ if (HandlePtr != NULL)
+ {
+ *HandlePtr = tempHandle;
+ }
+ else
+ {
+ NtClose(tempHandle);
+ }
+
+ return status;
+}
+
+
+
+NTSTATUS
+TspCreateAllKeys(
+ IN WCHAR DriveLetter,
+ IN PWSTR Category
+ )
+
+/*++
+
+Routine Description:
+
+ Create all keys for the volume information stuff
+
+Arguments:
+
+ none.
+
+Return Value:
+
+ NTSTATUS - from the registry calls.
+
+--*/
+
+{
+ NTSTATUS status;
+ HANDLE keyHandle;
+ WCHAR keyName[200];
+ WCHAR buffer[200];
+
+ wsprintf(keyName, KeyProto1);
+ daDebugOut((DEB_ITRACE,"creating keyName = %ws\n",keyName));
+
+ status = TspCreateKey(
+ &keyHandle,
+ keyName,
+ ClassName,
+ 0);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't create key %ws\n",keyName));
+ return status;
+ }
+
+ wsprintf(buffer, KeyProto2, DriveLetter);
+ lstrcat(keyName, buffer);
+ daDebugOut((DEB_ITRACE,"creating keyName = %ws\n",keyName));
+
+ status = TspCreateKey(
+ &keyHandle,
+ keyName,
+ ClassName,
+ 0);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't create key %ws\n",keyName));
+ return status;
+ }
+
+ wsprintf(buffer, KeyProto3, Category);
+ lstrcat(keyName, buffer);
+ daDebugOut((DEB_ITRACE,"creating keyName = %ws\n",keyName));
+
+ status = TspCreateKey(
+ &keyHandle,
+ keyName,
+ ClassName,
+ 0);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't create key %ws\n",keyName));
+ return status;
+ }
+
+ return status;
+}
+
+
+
+NTSTATUS
+TspDeleteValue(
+ IN HANDLE KeyHandle,
+ IN PWSTR ValueName
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will delete a value within a key.
+
+Arguments:
+
+ KeyHandle - an open HANDLE to the key in the registry containing the value.
+ ValueName - a UNICODE string for the value name to delete.
+
+Return Value:
+
+ NTSTATUS - from the configuration registry.
+
+--*/
+
+{
+ NTSTATUS status;
+ UNICODE_STRING valueName;
+
+ RtlInitUnicodeString(&valueName, ValueName);
+
+ status = NtDeleteValueKey(KeyHandle, &valueName);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,"Couldn't delete value %ws\n",ValueName));
+ }
+
+ return status;
+}
+
+
+
+NTSTATUS
+TspSetValue(
+ IN PWSTR KeyName,
+ IN PWSTR ValueName,
+ IN PVOID DataBuffer,
+ IN ULONG DataLength,
+ IN ULONG Type
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stores a value in the configuration registry.
+
+Arguments:
+
+ KeyName - Name of key of interest
+ ValueName - UNICODE value name.
+ DataBuffer - contents for the value.
+ DataLength - length of the value contents.
+ Type - The type of data (i.e. REG_BINARY, REG_DWORD, etc).
+
+Return Value:
+
+ NTSTATUS - from the configuration registry.
+
+--*/
+
+{
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UNICODE_STRING valueName;
+
+ status = TspOpenKey(&keyHandle, KeyName);
+ if (NT_SUCCESS(status))
+ {
+ RtlInitUnicodeString(&valueName, ValueName);
+ status = NtSetValueKey(
+ keyHandle,
+ &valueName,
+ 0,
+ Type,
+ DataBuffer,
+ DataLength);
+
+ NtClose(keyHandle);
+ }
+
+ return status;
+}
+
+
+NTSTATUS
+TspQueryValue(
+ IN PWSTR KeyName,
+ IN PWSTR ValueName,
+ IN OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG LengthReturned,
+ OUT VOID** Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine opens the specified volume key and gets the contents of the
+ specified value. It returns this contents to the caller.
+
+Arguments:
+
+ KeyName - Name of key of interest
+ ValueName - UNICODE string for the value name to query.
+ Buffer - pointer to buffer for return of value contents.
+ BufferLength - maximum amount of registry information that can be returned.
+ LengthReturned - pointer to location for the size of the contents returned.
+ Data - pointer to returned data
+
+Return Value:
+
+ NTSTATUS - from the configuration registry.
+
+--*/
+
+{
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UNICODE_STRING valueName;
+ PKEY_VALUE_FULL_INFORMATION keyValueInformation;
+
+ *LengthReturned = 0;
+ status = TspOpenKey(&keyHandle, KeyName);
+ if (NT_SUCCESS(status))
+ {
+ RtlInitUnicodeString(&valueName, ValueName);
+ keyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
+ status = NtQueryValueKey(keyHandle,
+ &valueName,
+ KeyValueFullInformation,
+ keyValueInformation,
+ BufferLength,
+ LengthReturned);
+
+ if (NT_SUCCESS(status))
+ {
+ if (keyValueInformation->DataLength == 0)
+ {
+ //
+ // Treat this as if there was not disk information.
+ //
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else
+ {
+ //
+ // Set up the pointers for the caller.
+ //
+
+ *Data = (PVOID)((PUCHAR)keyValueInformation + keyValueInformation->DataOffset);
+ }
+ }
+
+ NtClose(keyHandle);
+ }
+ else
+ {
+ daDebugOut((DEB_ERROR,"Couldn't open key %ws\n",KeyName));
+ }
+
+ return status;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TsChangeDriveLetter
+//
+// Synopsis: If a drive letter changes, adjust the registry time
+// stamps entries.
+//
+// Arguments: [OldDriveLetter] -- Drive letter that was changed
+// [NewDriveLetter] -- New drive letter
+//
+// Returns: nothing
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+TsChangeDriveLetter(
+ IN WCHAR OldDriveLetter,
+ IN WCHAR NewDriveLetter
+ )
+{
+ //BUGBUG: TsChangeDriveLetter is unimplemented
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TsSetTime
+//
+// Synopsis: Set the time for a volume to the current time.
+//
+// Arguments: [DriveLetter] -- indicates the volume of interest
+// [Category] -- type of thing to timestamp, e.g. "Chkdsk",
+// "Format"
+//
+// Returns: nothing
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+TsSetTime(
+ IN WCHAR DriveLetter,
+ IN PWSTR Category
+ )
+{
+ WCHAR keyName[200];
+ LARGE_INTEGER SystemTime;
+ NTSTATUS status;
+ TIME_FIELDS Time; //debug only
+
+ status = NtQuerySystemTime(&SystemTime);
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR, "Couldn't get system time\n"));
+ return;
+ }
+
+ status = TspCreateAllKeys(
+ DriveLetter,
+ Category
+ );
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR, "Couldn't create all keys\n"));
+ return;
+ }
+
+ wsprintf(keyName, KeyProto, DriveLetter, Category);
+ daDebugOut((DEB_ITRACE,"keyName = %ws\n",keyName));
+
+ status = TspSetValue(
+ keyName,
+ ValueName,
+ (PVOID)&SystemTime,
+ sizeof(SystemTime),
+ REG_BINARY
+ );
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't set key %ws, value %ws\n",
+ keyName,
+ ValueName));
+ }
+
+ //
+ // debug only:
+ //
+
+ memset(&Time, 0, sizeof(TIME_FIELDS));
+ RtlTimeToTimeFields(&SystemTime, &Time);
+
+ daDebugOut((DEB_ITRACE,
+ "set time: %d %d %d %d %d %d %d %d\n",
+ Time.Year,
+ Time.Month,
+ Time.Day,
+ Time.Hour,
+ Time.Minute,
+ Time.Second,
+ Time.Milliseconds,
+ Time.Weekday));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TsGetTime
+//
+// Synopsis: Gets the time stamp for a volume
+//
+// Arguments: [DriveLetter] -- indicates the volume of interest
+// [Category] -- type of thing to timestamp, e.g. "Chkdsk",
+// "Format"
+// [Time] -- a time structure to fill in
+//
+// Returns: nothing
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+TsGetTime(
+ IN WCHAR DriveLetter,
+ IN PWSTR Category,
+ OUT PTIME_FIELDS Time
+ )
+{
+ WCHAR Key[200];
+ CHAR Buffer[100];
+ ULONG Ignore;
+ PLARGE_INTEGER SystemTime;
+ NTSTATUS status;
+
+ wsprintf(Key, KeyProto, DriveLetter, Category);
+ daDebugOut((DEB_ITRACE,"key = %ws\n",Key));
+
+ status = TspQueryValue(
+ Key,
+ ValueName,
+ (PVOID)Buffer,
+ sizeof(Buffer),
+ &Ignore,
+ (VOID**)&SystemTime
+ );
+ if (!NT_SUCCESS(status))
+ {
+ daDebugOut((DEB_ERROR,
+ "Couldn't query key %ws, value %ws\n",
+ Key,
+ ValueName));
+ }
+
+ memset(Time, 0, sizeof(TIME_FIELDS));
+ RtlTimeToTimeFields(SystemTime, Time);
+
+ daDebugOut((DEB_ITRACE,
+ "get time: %d %d %d %d %d %d %d %d\n",
+ Time->Year,
+ Time->Month,
+ Time->Day,
+ Time->Hour,
+ Time->Minute,
+ Time->Second,
+ Time->Milliseconds,
+ Time->Weekday));
+}
diff --git a/private/utils/windisk/src/unused/time.hxx b/private/utils/windisk/src/unused/time.hxx
new file mode 100644
index 000000000..612fc3c8a
--- /dev/null
+++ b/private/utils/windisk/src/unused/time.hxx
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: time.hxx
+//
+// Contents: Functions dealing with time, relating to time stamping
+// chkdsk.
+//
+// Functions:
+//
+// History: 31-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TIME_HXX__
+#define __TIME_HXX__
+
+VOID
+TsChangeDriveLetter(
+ IN WCHAR OldDriveLetter,
+ IN WCHAR NewDriveLetter
+ );
+
+VOID
+TsSetTime(
+ IN WCHAR DriveLetter,
+ IN PWSTR Category
+ );
+
+VOID
+TsGetTime(
+ IN WCHAR DriveLetter,
+ IN PWSTR Category,
+ OUT PTIME_FIELDS Time
+ );
+
+#endif // __TIME_HXX__
diff --git a/private/utils/windisk/src/volview.cxx b/private/utils/windisk/src/volview.cxx
new file mode 100644
index 000000000..e186328cc
--- /dev/null
+++ b/private/utils/windisk/src/volview.cxx
@@ -0,0 +1,400 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: volview.cxx
+//
+// Contents: Routines for handling the volumes view
+//
+// History: 18-Jun-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdio.h>
+
+#include "cm.hxx"
+#include "dispinfo.hxx"
+#include "select.hxx"
+#include "volview.hxx"
+
+//////////////////////////////////////////////////////////////////////////////
+
+LRESULT
+OnGetDispInfo(
+ IN LV_DISPINFO* plvdi
+ );
+
+int CALLBACK
+ListViewCompareProc(
+ LPARAM lParam1,
+ LPARAM lParam2,
+ LPARAM lParamSort
+ );
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// BUGBUG: Hardcoded initialization of columns.
+//
+
+LOCAL LV_COLUMN s_aColumnInit[g_cColumns] =
+{
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 50, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 90, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_RIGHT, 70, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_RIGHT, 70, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_RIGHT, 50, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 70, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 110, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 90, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 150, NULL, 0, 0 },
+ { LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM, LVCFMT_LEFT, 90, NULL, 0, 0 }
+};
+
+//
+// The following array exactly parallels the previous array, and must
+// have the same number of entries. It contains resource IDs for column
+// strings
+//
+LOCAL UINT s_aColumnStringID[g_cColumns] =
+{
+ IDS_VV_VOLUME,
+ IDS_VV_NAME,
+ IDS_VV_CAPACITY,
+ IDS_VV_FREESPACE,
+ IDS_VV_PCTFREE,
+ IDS_VV_FORMAT,
+ IDS_VV_FT,
+ IDS_VV_VOLTYPE,
+ IDS_VV_OVERHEAD,
+ IDS_VV_STATUS
+};
+
+// The column order: 1 for ascending, -1 for descending
+int g_aColumnOrder;
+int g_iLastColumnSorted;
+
+WORD IconListSmall[] =
+{
+ IDI_S_HARD,
+ IDI_S_CDROM
+};
+
+int IconIndexSmall[ARRAYLEN(IconListSmall)] = {0};
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitializeListview, public
+//
+// Synopsis: create and test a listview control
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+InitializeListview(
+ VOID
+ )
+{
+ FDASSERT(ARRAYLEN(s_aColumnInit) == ARRAYLEN(s_aColumnStringID));
+
+ int i;
+ int cxSmallIcon, cySmallIcon;
+ HIMAGELIST himlSmall;
+ HICON hIcon;
+
+ //
+ // Set the image lists to have all the icons we need
+ //
+
+ cxSmallIcon = 16; // = GetSystemMetrics(SM_CXSMICON);
+ cySmallIcon = 16; // = GetSystemMetrics(SM_CYSMICON);
+
+ FDASSERT(cxSmallIcon == 16);
+ FDASSERT(cySmallIcon == 16);
+
+ himlSmall = ImageList_Create(cxSmallIcon, cySmallIcon, TRUE, ARRAYLEN(IconListSmall), 0);
+ if (NULL == himlSmall)
+ {
+ daDebugOut((DEB_ERROR, "ImageList_Create failed\n"));
+ }
+
+ for (i=0; i<ARRAYLEN(IconListSmall); i++)
+ {
+ hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconListSmall[i]));
+ IconIndexSmall[i] = ImageList_AddIcon(himlSmall, hIcon);
+ DestroyIcon(hIcon);
+ }
+
+ // now, all needed icons are in the HIMAGELIST
+
+ if (!ListView_SetImageList(g_hwndLV, himlSmall, LVSIL_SMALL))
+ {
+ daDebugOut((DEB_ERROR, "ListView_SetImageList failed\n"));
+ //BUGBUG: comctl32.dll seems to always return false
+ }
+
+ //
+ // Add the default columns
+ //
+
+ LV_COLUMN lvC;
+ TCHAR szColumn[MAX_RESOURCE_STRING_LEN];
+
+ for (i = 0; i<ARRAYLEN(s_aColumnInit); i++)
+ {
+ LoadString(
+ g_hInstance,
+ s_aColumnStringID[i],
+ szColumn,
+ ARRAYLEN(szColumn));
+
+ lvC = s_aColumnInit[i];
+ lvC.pszText = szColumn;
+
+ daDebugOut((DEB_ITRACE, "listview column %d ==> %ws\n", i, szColumn));
+
+ if (-1 == ListView_InsertColumn(g_hwndLV, i, &lvC))
+ {
+ daDebugOut((DEB_ERROR,"ListView_InsertColumn (%d) failed\n",i));
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: HandleListviewNotify
+//
+// Synopsis: Handles WM_NOTIFY message for the listview control
+//
+// Arguments: [pnmlv] -- notification information
+//
+// Returns: standard window procedure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+HandleListviewNotify(
+ IN NM_LISTVIEW* pnmlv
+ )
+{
+ switch (pnmlv->hdr.code)
+ {
+ case LVN_ITEMCHANGING:
+ return FALSE; // allow all changes
+
+ case LVN_ITEMCHANGED:
+ {
+ if (g_SettingListviewState)
+ {
+ //
+ // I'm setting the state because of a disks view change;
+ // don't do normal selection
+ //
+ break;
+ }
+
+ if (!(pnmlv->uChanged & LVIF_STATE))
+ {
+ daDebugOut((DEB_ITRACE,
+" NOT A STATE CHANGE\n\n"));
+ break;
+ }
+
+ if ( (pnmlv->uOldState & LVIS_SELECTED)
+ || (pnmlv->uNewState & LVIS_SELECTED))
+ {
+ //
+ // A selection change: either the item became selected or
+ // lost the selection
+ //
+
+ SetVolumeSelection(pnmlv->iItem, pnmlv->uNewState & LVIS_SELECTED);
+ AdjustMenuAndStatus();
+ }
+
+ break;
+ }
+
+ case LVN_BEGINDRAG:
+ case LVN_BEGINRDRAG:
+ return FALSE; // don't allow any drag/drop
+
+ case LVN_DELETEITEM:
+ {
+ CDispInfo* pdi = (CDispInfo*)pnmlv->lParam;
+ delete pdi;
+ return 0L; //ignored?
+ }
+
+ case LVN_GETDISPINFO:
+ return OnGetDispInfo((LV_DISPINFO *)pnmlv);
+
+ case LVN_COLUMNCLICK:
+ {
+ if (pnmlv->iSubItem != g_iLastColumnSorted)
+ {
+ g_aColumnOrder = 1;
+ g_iLastColumnSorted = pnmlv->iSubItem;
+ }
+
+ // The user clicked on one of the column headings - sort the column.
+ ListView_SortItems( pnmlv->hdr.hwndFrom,
+ ListViewCompareProc,
+ (LPARAM)(pnmlv->iSubItem));
+ g_aColumnOrder = -g_aColumnOrder; //invert
+ return TRUE;
+ }
+
+ case NM_CLICK:
+ case NM_RCLICK:
+ {
+ //
+ // got a button 2 click on a listview item. Bring up a
+ // context menu
+ //
+
+ LV_HITTESTINFO hti;
+ POINT pt;
+
+ GetCursorPos(&pt);
+ hti.pt = pt;
+ ScreenToClient(g_hwndLV, &hti.pt);
+ INT item = ListView_HitTest(g_hwndLV, &hti);
+
+ if (-1 != item)
+ {
+ if ( (NM_RCLICK == pnmlv->hdr.code)
+ && (hti.flags & LVHT_ONITEM))
+ {
+ ContextMenu(&pt);
+ }
+ }
+
+ break;
+ } // end case NM_RCLICK:
+
+ } // end switch (pnmlv->hdr.code)
+
+ return (LRESULT)0;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OnGetDispInfo
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+OnGetDispInfo(
+ IN LV_DISPINFO* plvdi
+ )
+{
+ CDispInfo* pdi = (CDispInfo*)(plvdi->item.lParam);
+ plvdi->item.pszText = pdi->GetText(plvdi->item.iSubItem);
+ return 0L; //ignored?
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ListViewCompareProc
+//
+// Synopsis: Callback function that sorts depending on the column click
+//
+// Arguments:
+//
+// Returns: -, 0, or +, based on order
+//
+//----------------------------------------------------------------------------
+
+int CALLBACK
+ListViewCompareProc(
+ LPARAM lParam1,
+ LPARAM lParam2,
+ LPARAM lParamSort
+ )
+{
+ // string: lstrcmpi(string1, string2);
+ // number: number1 - number2
+
+ CDispInfo* pdi1 = (CDispInfo*)lParam1;
+ CDispInfo* pdi2 = (CDispInfo*)lParam2;
+ int iSubItem = (int)lParamSort;
+ int iResult;
+
+ switch (iSubItem)
+ {
+ case 0: // column 0: drive letter
+ case 1: // column 1: volume label
+ case 5: // column 5: format (file system type)
+ case 6: // column 6: fault tolerant?
+ case 7: // column 7: volume type
+ case 8: // column 8: fault tolerance overhead in MB
+ case 9: // column 9: status
+ {
+ PWSTR psz1 = pdi1->GetText(iSubItem);
+ PWSTR psz2 = pdi2->GetText(iSubItem);
+ iResult = lstrcmpi(psz1, psz2);
+ break;
+ }
+
+ case 2: // column 2: capacity in MB
+ case 3: // column 3: free space in MB
+ case 4: // column 4: % free space
+ {
+ LONG l1 = pdi1->GetNumber(iSubItem);
+ LONG l2 = pdi2->GetNumber(iSubItem);
+
+ if (l1 > l2)
+ {
+ iResult = 1;
+ }
+ else if (l1 < l2)
+ {
+ iResult = -1;
+ }
+ else
+ {
+ iResult = 0;
+ }
+ break;
+ }
+
+ default: // This shouldn't happen!
+ daDebugOut((DEB_ERROR,
+ "ListViewCompareProc: unknown column (%d)",
+ iSubItem));
+
+ iResult = 0;
+ break;
+
+ } // switch (iSubItem)
+
+ return iResult * g_aColumnOrder;
+}
diff --git a/private/utils/windisk/src/volview.hxx b/private/utils/windisk/src/volview.hxx
new file mode 100644
index 000000000..bf83432bc
--- /dev/null
+++ b/private/utils/windisk/src/volview.hxx
@@ -0,0 +1,36 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: volview.hxx
+//
+// Contents: Declarations for the volumes view
+//
+// History: 18-Jun-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __VOLVIEW_HXX__
+#define __VOLVIEW_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+const int g_cColumns = 10;
+
+extern int g_aColumnOrder;
+extern int g_iLastColumnSorted;
+
+//////////////////////////////////////////////////////////////////////////////
+
+VOID
+InitializeListview(
+ VOID
+ );
+
+LRESULT
+HandleListviewNotify(
+ IN NM_LISTVIEW* pnmlv
+ );
+
+#endif // __VOLVIEW_HXX__
diff --git a/private/utils/windisk/src/windisk.cxx b/private/utils/windisk/src/windisk.cxx
new file mode 100644
index 000000000..468cbadec
--- /dev/null
+++ b/private/utils/windisk/src/windisk.cxx
@@ -0,0 +1,5753 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: windisk.cxx
+//
+// Contents: Disk Administrator main Windows routines
+//
+// History: 6-Jun-93 BruceFo Created from NT Disk Administrator
+// 8-Jan-94 BruceFo Added BobRi's Daytona CD-ROM,
+// DoubleSpace, and Commit support
+//
+//--------------------------------------------------------------------------
+
+#include "headers.hxx"
+#pragma hdrstop
+
+#include <stdlib.h>
+#include <string.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <shlobjp.h>
+#include <shsemip.h>
+
+#include <util.hxx>
+
+#include "cdrom.hxx"
+#include "chkdsk.hxx"
+#include "cm.hxx"
+#include "commit.hxx"
+#include "controls.hxx"
+#include "dialogs.h"
+#include "dblspace.hxx"
+#include "dlgs.hxx"
+#include "drives.hxx"
+#include "fill.hxx"
+#include "fmifs.hxx"
+#include "format.hxx"
+#include "ft.hxx"
+#include "ftreg.hxx"
+#include "genlpage.hxx"
+#include "help.hxx"
+#include "help2.hxx"
+#include "init.hxx"
+#include "label.hxx"
+#include "listbox.hxx"
+#include "menudict.hxx"
+#include "nt.hxx"
+#include "ntlow.hxx"
+#include "oleclass.hxx"
+#include "ops.hxx"
+#include "ps.hxx"
+#include "profile.hxx"
+#include "rectpriv.hxx"
+#include "select.hxx"
+#include "stleg.hxx"
+#include "tb.h"
+#include "tbar.hxx"
+#include "volview.hxx"
+#include "windisk.hxx"
+#include "dbt.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+
+//
+// This is the index of the Fault Tolerance menu. It is currently the
+// second menu across the menu bar, so it is index 1 in 0-based numbering
+//
+
+#define FT_MENU_INDEX 1
+
+////////////////////////////////////////////////////////////////////////////
+
+TCHAR WinHelpFile[] = TEXT("windisk.hlp");
+TCHAR LanmanHelpFile[] = TEXT("windiska.hlp");
+
+
+#if DBG == 1
+
+BOOL AllowAllDeletes = FALSE; // whether to allow deleting boot/sys parts
+BOOL BothViews = FALSE; // show both volumes & disks view on same pane?
+
+#endif // DBG == 1
+
+
+//
+// The following vars keep track of the currently selected regions.
+//
+DWORD SelectionCount = 0;
+PDISKSTATE SelectedDS[MAX_MEMBERS_IN_FT_SET];
+ULONG SelectedRG[MAX_MEMBERS_IN_FT_SET];
+
+ULONG SelectedFreeSpaces;
+ULONG SelectedNonFtPartitions;
+PULONG DiskSeenCountArray;
+BOOL FtSetSelected;
+FT_TYPE FtSelectionType;
+BOOL NonFtItemSelected;
+BOOL MultipleItemsSelected;
+BOOL VolumeSetAndFreeSpaceSelected;
+BOOL PartitionAndFreeSpaceSelected;
+BOOL PossibleRecover;
+ULONG FreeSpaceIndex;
+
+BOOL DiskSelected;
+BOOL PartitionSelected;
+BOOL CdRomSelected;
+DWORD CdRomSelectionCount;
+
+BOOL AllowFormat;
+BOOL AllowVolumeOperations;
+
+#ifdef WINDISK_EXTENSIONS
+BOOL AllowExtensionItems;
+#endif // WINDISK_EXTENSIONS
+
+
+HANDLE DisplayMutex;
+ULONG DisplayUpdateCount;
+DWORD RefreshAllowed = 0;
+
+
+#ifndef i386
+
+//
+// This variable tracks whether the system partition is secure.
+//
+BOOL SystemPartitionIsSecure = FALSE;
+
+#endif // !i386
+
+#if defined( DBLSPACE_ENABLED )
+BOOL DoubleSpaceAutomount;
+#endif // DBLSPACE_ENABLED
+
+BOOLEAN g_oneTime = TRUE;
+
+////////////////////////////////////////////////////////////////////////////
+
+//
+// g_uItemInsertHere is an index into the "Volume" menu of where the
+// next extension menu item may be inserted. The UITEM_INSERT_HERE constant
+// points to the initial position, which is currently the 0-based index
+// of the "Format" item, plus one.
+//
+#define UITEM_INSERT_HERE (0 + 1)
+
+UINT g_uItemInsertHere = UITEM_INSERT_HERE;
+
+
+////////////////////////////////////////////////////////////////////////////
+
+VOID _CRTAPI1
+main(
+ IN int argc,
+ IN char* argv[],
+ IN char* envp[]
+ );
+
+#ifndef i386
+BOOL
+IsSystemPartitionSecure(
+ VOID
+ );
+#endif // !i386
+
+VOID
+SetProductType(
+ VOID
+ );
+
+VOID
+CleanUp(
+ VOID
+ );
+
+#if i386
+VOID
+SetUpMenui386(
+ IN HMENU hMenu
+ );
+#endif
+
+VOID
+ChangeView(
+ VOID
+ );
+
+VOID
+AdjustOptionsMenu(
+ VOID
+ );
+
+VOID
+PaintStatusBar(
+ IN HWND hwnd,
+ IN PAINTSTRUCT* pps,
+ IN PRECT prc
+ );
+
+VOID
+PaintLegend(
+ IN HWND hwnd,
+ IN PAINTSTRUCT* pps,
+ IN PRECT prc
+ );
+
+VOID
+PaintVolumesView(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+VOID
+PaintDisksView(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FrameCreateHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FrameResizeHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FramePaintHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FrameCommandHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FrameCloseHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+LRESULT
+FrameDestroyHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+ULONG
+GetLargestDiskSize(
+ VOID
+ );
+
+VOID
+DrawCdRomBar(
+ IN ULONG CdRomNumber
+ );
+
+WCHAR BootDir = (WCHAR)0;
+WCHAR SystemDir = (WCHAR)0;
+////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: main
+//
+// Synopsis: Entrypoint for all Disk Administrator functionality
+//
+// Arguments: standard C/C++ main
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID _CRTAPI1
+main(
+ IN int argc,
+ IN char* argv[],
+ IN char* envp[]
+ )
+{
+ MSG msg;
+ NTSTATUS status;
+ HANDLE mutex;
+ HACCEL hAccel;
+ WCHAR driveLetterBuffer[MAX_PATH];
+ UNICODE_STRING driveLetterString;
+
+ RTL_QUERY_REGISTRY_TABLE driveLetterTable[2] = {0};
+
+#if DBG == 1
+ InitializeDebugging();
+#endif // DBG == 1
+
+ daDebugOut((DEB_TRACE, "Starting Disk Administrator...\n"));
+
+ g_hInstance = GetModuleHandle(NULL);
+
+ mutex = CreateMutex(NULL, FALSE, TEXT("Disk Administrator Is Running"));
+
+ if (mutex == NULL)
+ {
+ // An error (like out of memory) has occurred.
+ return;
+ }
+
+ //
+ // Make sure we are the only process with a handle to our named mutex.
+ //
+
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(mutex);
+ InfoDialog(MSG_ALREADY_RUNNING);
+ return;
+ }
+
+ __try
+ {
+ //
+ // Figure out the product type (Normal WinNT or Server)
+ //
+
+ SetProductType();
+
+#if DBG == 1
+ //
+ // The code below will allow users to run WinDisk in Lanman
+ // mode on WinNt. It should never be enabled in a released
+ // build, but is very useful for internal users.
+ //
+
+ --argc;
+ ++argv;
+ while (argc > 0)
+ {
+ if (0 == _stricmp( *argv, "/both" ))
+ {
+ BothViews = TRUE;
+ }
+ else if (0 == _stricmp( *argv, "/server" ))
+ {
+ g_IsLanmanNt = TRUE;
+ }
+ else if (0 == _stricmp( *argv, "/workstation" ))
+ {
+ g_IsLanmanNt = FALSE;
+ }
+ else if (0 == _stricmp( *argv, "/debug" ))
+ {
+ daInfoLevel =
+ DEB_ERROR
+ | DEB_WARN
+ | DEB_TRACE
+ | DEB_IERROR
+ | DEB_IWARN
+ | DEB_ITRACE
+ ;
+ }
+ else
+ {
+ MessageBox(NULL,
+ L"Disk Administrator command-line usage:\n"
+ L"\t/server\t-- Use the Windows NT Server version\n"
+ L"\t/workstation\t-- Use the Windows NT Workstation version\n"
+ L"\n"
+ L"For debugging:\n"
+ L"\t/both\t-- see both views at once\n"
+ L"\t/debug\t-- see trace and error output on the debugger\n"
+ ,
+
+ L"Disk Administrator",
+ MB_ICONINFORMATION | MB_OK);
+ return;
+ }
+
+ --argc;
+ ++argv;
+ }
+#endif // DBG == 1
+
+ //
+ // Get a handle to the display mutex lock.
+ //
+
+ DisplayMutex = CreateMutex(
+ NULL,
+ FALSE,
+ NULL
+ );
+
+ if (!DisplayMutex) {
+
+ ErrorDialog(MSG_CANT_INITIALIZE);
+ goto xx2;
+
+ }
+
+ DisplayUpdateCount = 0;
+
+
+
+ DisplayInitializationMessage();
+
+ // Set the Help file name to the file appropriate to
+ // the product.
+ //
+ g_HelpFile = g_IsLanmanNt ? LanmanHelpFile : WinHelpFile;
+
+ InitCommonControls();
+
+#ifndef i386
+ //
+ // Determine whether the system partition is protected:
+ //
+ SystemPartitionIsSecure = IsSystemPartitionSecure();
+#endif // !i386
+
+#if DBG == 1
+ InitLogging();
+#endif // DBG == 1
+
+// STARTUP BeginStartup();
+
+ //
+ // Ensure that all drives are present before looking
+ //
+
+ RescanDevices();
+
+ status = FdiskInitialize();
+ if (!NT_SUCCESS(status))
+ {
+ ErrorDialog(status == STATUS_ACCESS_DENIED
+ ? MSG_ACCESS_DENIED
+ : EC(status));
+ goto xx1;
+ }
+
+ if (((DiskCount = GetDiskCount()) == 0) || AllDisksOffLine())
+ {
+ ErrorDialog(MSG_NO_DISKS);
+ goto xx2;
+ }
+
+ if (!InitializeApp())
+ {
+ ErrorDialog(MSG_CANT_INITIALIZE);
+ goto xx2;
+ }
+
+ //
+ // Get the drive letter of the boot drive.
+ //
+
+ driveLetterString.Length = 0;
+ driveLetterString.MaximumLength = sizeof(driveLetterBuffer);
+ driveLetterString.Buffer = (PWCHAR)&driveLetterBuffer[0];
+ driveLetterTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT |
+ RTL_QUERY_REGISTRY_REQUIRED;
+ driveLetterTable[0].Name = L"BootDir";
+ driveLetterTable[0].EntryContext = &driveLetterString;
+
+ if (NT_SUCCESS(RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
+ L"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\SETUP",
+ &driveLetterTable[0],
+ NULL,
+ NULL
+ ))) {
+
+ BootDir = driveLetterBuffer[0];
+
+ }
+
+ {
+ UINT pathSize;
+
+ pathSize = GetWindowsDirectory(
+ &driveLetterBuffer[0],
+ sizeof(driveLetterBuffer)
+ );
+
+ if ((pathSize <= MAX_PATH) && pathSize) {
+
+ SystemDir = driveLetterBuffer[0];
+
+ }
+ }
+
+
+
+ SetUpMenu(&SingleSel, &SingleSelIndex);
+
+#if DBG == 1
+ // All initialization has been done by now
+ LOG_ALL();
+#endif // DBG == 1
+
+ ChangeView();
+ AdjustOptionsMenu();
+
+ InitHelp();
+
+ hAccel = LoadAccelerators(
+ g_hInstance,
+ MAKEINTRESOURCE(ID_FRAME_ACCELERATORS)
+ );
+
+ //
+ // Finally, make the window visible before starting the message pump
+ //
+
+ ShowWindow(
+ g_hwndFrame,
+ ProfileIsIconic ? SW_SHOWMINIMIZED
+ : (ProfileIsMaximized ? SW_SHOWMAXIMIZED
+ : SW_SHOWDEFAULT)
+ );
+ UpdateWindow(g_hwndFrame);
+
+#if DBG == 1
+ // All initialization has been done by now
+ LOG_ALL();
+#endif // DBG == 1
+
+// STARTUP EndStartup();
+// STARTUP SetForegroundWindow(g_hwndFrame);
+
+ //
+ // Start the message pump: this is where everything happens!
+ //
+
+ if (NULL != g_InitDlg)
+ {
+ PostMessage(g_InitDlg, WM_STARTUP_END, 0, 0);
+ g_InitDlg = NULL;
+ }
+
+ while (GetMessage(&msg, NULL, 0, 0))
+ {
+ if (!TranslateAccelerator(g_hwndFrame, hAccel, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ CleanUp();
+
+ xx2:
+
+ FdiskCleanUp();
+
+ xx1:
+
+#if DBG == 1
+ EndLogging();
+#endif // DBG == 1
+
+ ;
+
+ }
+ __finally
+ {
+ // Destroy the mutex.
+
+ CloseHandle(mutex);
+ }
+}
+
+
+#ifndef i386
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsSystemPartitionSecure
+//
+// Synopsis: Determines if the system partition is secure by
+// examining the registry.
+//
+// Arguments: (none)
+//
+// Returns: TRUE if the registry indicates the system partition is secure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+IsSystemPartitionSecure(
+ VOID
+ )
+{
+ LONG ec;
+ HKEY hkey;
+ DWORD type;
+ DWORD size;
+ ULONG value;
+
+ value = FALSE;
+
+ ec = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Control\\Lsa"),
+ 0,
+ KEY_QUERY_VALUE,
+ &hkey
+ );
+
+ if (ec == NO_ERROR)
+ {
+ size = sizeof(ULONG);
+ ec = RegQueryValueEx( hkey,
+ TEXT("Protect System Partition"),
+ NULL,
+ &type,
+ (PBYTE)&value,
+ &size
+ );
+
+ if ((ec != NO_ERROR) || (type != REG_DWORD))
+ {
+ value = FALSE;
+ }
+
+ RegCloseKey(hkey);
+ }
+
+ return value;
+}
+
+#endif // !i386
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetProductType
+//
+// Synopsis: Sets the [g_IsLanmanNt] global variable based on the
+// product type: workstation or advanced server
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// Modifies: [g_IsLanmanNt] -- set to TRUE for an advanced server
+// installation that allows fault tolerance configuration.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetProductType(
+ VOID
+ )
+{
+ //
+ // Determine whether this is LanmanNt or Windows NT by looking at
+ // HKEY_LOCAL_MACHINE, System\CurrentControlSet\Control\ProductOptions.
+ // If the ProductType value therein is "LanmanNt" then this is LanmanNt.
+ //
+
+ LONG ec;
+ HKEY hkey;
+ DWORD type;
+ DWORD size;
+ UCHAR buf[100];
+
+ g_IsLanmanNt = FALSE;
+
+ ec = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Control\\ProductOptions"),
+ 0,
+ KEY_QUERY_VALUE,
+ &hkey
+ );
+
+ if (ec == NO_ERROR)
+ {
+ size = sizeof(buf);
+ ec = RegQueryValueEx(hkey,
+ TEXT("ProductType"),
+ NULL,
+ &type,
+ buf,
+ &size);
+
+ if ((ec == NO_ERROR) && (type == REG_SZ))
+ {
+ if (0 == lstrcmpi((LPTSTR)buf, TEXT("lanmannt")))
+ {
+ g_IsLanmanNt = TRUE;
+ }
+
+ if (0 == lstrcmpi((LPTSTR)buf, TEXT("servernt")))
+ {
+ g_IsLanmanNt = TRUE;
+ }
+ }
+
+ RegCloseKey(hkey);
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanUp
+//
+// Synopsis: Miscellaneous cleanup before exit
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 22-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+CleanUp(
+ VOID
+ )
+{
+ ReleaseRectControl(g_hInstance);
+ ReleaseWindiskControls(g_hInstance);
+ TermHelp();
+ ReleaseOle();
+ UnloadFmifs();
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MyFrameWndProc
+//
+// Synopsis: Window procedure for the frame window
+//
+// Arguments: standard Windows procedure
+//
+// Returns: standard Windows procedure
+//
+// History: 16-Aug-93 BruceFo Created
+//
+// Notes: Creates the listbox control for the disks view, the
+// listview control for the volumes view, the toolbar control.
+//
+//----------------------------------------------------------------------------
+
+LRESULT CALLBACK
+MyFrameWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ RECT rc;
+ UINT oldErrorMode;
+
+ switch (msg)
+ {
+
+ case WM_CREATE:
+
+ return FrameCreateHandler(hwnd, wParam, lParam);
+
+//
+// Toolbar notification
+//
+
+ case WM_NOTIFY:
+ {
+ NMHDR* phdr = (NMHDR*)lParam;
+
+ //
+ // The tooltip notification sends the command id as wParam instead of
+ // a control id such as the toolbar id. Since commctrl notification
+ // codes are disjoint, check for tooltip notifications first, then
+ // the others.
+ //
+
+ switch (phdr->code)
+ {
+ case TTN_NEEDTEXT:
+ return HandleTooltipNotify((TOOLTIPTEXT*)phdr);
+ } // end switch (phdr->code)
+
+ switch (wParam)
+ {
+ case ID_LISTVIEW:
+ return HandleListviewNotify((NM_LISTVIEW*)phdr);
+
+ case IDC_TOOLBAR:
+ return HandleToolbarNotify((TBNOTIFY*)phdr);
+
+ default:
+ daDebugOut((DEB_ITRACE,
+ "WM_NOTIFY: unknown! control %d, idFrom %d, code %d\n",
+ wParam,
+ phdr->idFrom,
+ phdr->code));
+ return 0L; //shouldn't happen!
+
+ } // end switch (wParam)
+ }
+
+ case WM_SETFOCUS:
+
+ PostMessage(hwnd,WM_USER, 0, 0);
+
+ switch (g_WhichView)
+ {
+ case VIEW_VOLUMES:
+ SetFocus(g_hwndLV);
+ break;
+
+ case VIEW_DISKS:
+ SetFocus(g_hwndList);
+ break;
+
+ default:
+ FDASSERT(0);
+ }
+ break;
+
+ case WM_DEVICECHANGE:
+
+ if ((wParam == DBT_DEVICEARRIVAL) ||
+ (wParam == DBT_DEVICEREMOVECOMPLETE)) {
+ WaitForSingleObject(DisplayMutex, INFINITE);
+ RefreshAllowed = 1;
+ ReleaseMutex(DisplayMutex);
+ PostMessage(hwnd, WM_USER, 0, 0);
+ } else {
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ break;
+
+ case WM_WININICHANGE:
+
+ if (((LPTSTR)lParam == NULL)
+ || !lstrcmpi((LPTSTR)lParam, TEXT("colors")))
+ {
+ TotalRedrawAndRepaint();
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmmi = (LPMINMAXINFO)lParam;
+
+ //
+ // Don't allow resizing too small
+ //
+
+ lpmmi->ptMinTrackSize.x = MinimumWindowWidth;
+
+ return 0; // message processed
+ }
+
+ case WM_SIZE:
+
+ FrameResizeHandler(hwnd, wParam, lParam);
+
+ // FALL THROUGH
+
+ case WM_MOVE:
+
+ // if not iconic or minimized, save new position for profile
+
+ if (!IsZoomed(hwnd) && !IsIconic(hwnd))
+ {
+ GetWindowRect(hwnd, &rc);
+ ProfileWindowX = rc.left;
+ ProfileWindowY = rc.top;
+ ProfileWindowW = rc.right - rc.left;
+ ProfileWindowH = rc.bottom - rc.top;
+ }
+ break;
+
+ case WM_ENTERIDLE:
+
+ if (ConfigurationSearchIdleTrigger == TRUE && wParam == MSGF_DIALOGBOX)
+ {
+ PostMessage((HWND)lParam, WM_ENTERIDLE, wParam, lParam);
+ }
+ else
+ {
+ // If we're coming from a dialog box and the F1 key is down,
+ // kick the dialog box and make it spit out help.
+ //
+ if ((wParam == MSGF_DIALOGBOX)
+ && (GetKeyState(VK_F1) & 0x8000)
+ && GetDlgItem((HWND) lParam, IDHELP))
+ {
+ PostMessage((HWND) lParam, WM_COMMAND, IDHELP, 0L);
+ }
+ }
+
+ return 1; // indicate we did not process the message
+
+ case WM_PAINT:
+
+ return FramePaintHandler(hwnd, wParam, lParam);
+
+ case WM_COMMAND: {
+
+ LRESULT localResult;
+
+ WaitForSingleObject(
+ DisplayMutex,
+ INFINITE
+ );
+ DisplayUpdateCount++;
+ ReleaseMutex(DisplayMutex);
+
+ localResult = FrameCommandHandler(hwnd, wParam, lParam);
+
+ WaitForSingleObject(
+ DisplayMutex,
+ INFINITE
+ );
+ DisplayUpdateCount--;
+ ReleaseMutex(DisplayMutex);
+
+ return localResult;
+
+ }
+
+ case WM_RBUTTONUP:
+ {
+ //
+ // Handle context menu on legend
+ //
+
+ POINT pt;
+ pt.x = (LONG)(LOWORD(lParam));
+ pt.y = (LONG)(HIWORD(lParam));
+
+ // pt is now in client coordinates
+
+ if (HitTestLegend(&pt))
+ {
+ ClientToScreen(hwnd, &pt);
+ LegendContextMenu(&pt);
+ }
+
+ break;
+ }
+
+ case WM_MEASUREITEM:
+ {
+ PMEASUREITEMSTRUCT pMeasureItem = (PMEASUREITEMSTRUCT)lParam;
+ pMeasureItem->itemHeight = GraphHeight;
+ break;
+ }
+
+ case WM_DRAWITEM:
+
+ return WMDrawItem((PDRAWITEMSTRUCT)lParam);
+
+ case WM_CTLCOLORLISTBOX:
+
+ if ((HWND)lParam == g_hwndList)
+ {
+ return (LRESULT)GetStockBrush(LTGRAY_BRUSH);
+ }
+ else
+ {
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ case WM_CLOSE:
+
+ return FrameCloseHandler(hwnd, wParam, lParam);
+
+ case WM_DESTROY:
+
+ return FrameDestroyHandler(hwnd, wParam, lParam);
+
+ case WM_INITMENU:
+
+ if (g_StatusBar)
+ {
+ PaintHelpStatusBar(NULL);
+ }
+ break;
+
+ case WM_MENUSELECT:
+
+ SetMenuItemHelpContext(wParam, lParam);
+ break;
+
+ case WM_F1DOWN:
+
+ Help(wParam);
+ break;
+
+ case WM_USER:
+
+
+ WaitForSingleObject(
+ DisplayMutex,
+ INFINITE
+ );
+
+ if (DisplayUpdateCount || !RefreshAllowed) {
+
+ ReleaseMutex(DisplayMutex);
+ break;
+
+ }
+
+ DisplayUpdateCount++;
+
+ ReleaseMutex(DisplayMutex);
+
+ oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+ DoRefresh();
+ SetErrorMode(oldErrorMode);
+
+ WaitForSingleObject(
+ DisplayMutex,
+ INFINITE
+ );
+
+ RefreshAllowed = 0;
+ DisplayUpdateCount--;
+ ReleaseMutex(DisplayMutex);
+
+ break;
+
+ default:
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ return 0;
+}
+
+
+
+#if i386
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetUpMenui386
+//
+// Synopsis: For x86 machines, set up the "Mark active" item
+//
+// Arguments: [hMenu] -- handle to menu with "Mark active" item
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetUpMenui386(
+ IN HMENU hMenu
+ )
+{
+ BOOL allowActive = FALSE;
+ PREGION_DESCRIPTOR regionDescriptor;
+ DWORD i;
+
+ if ((SelectionCount == 1) && (FtSelectionType == UNINIT_FT_TYPE))
+ {
+ regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
+
+ //
+ // allow it to be made active if
+ // - it is not free space
+ // - it is a primary partition
+ // - it is not already active
+ // - it is not part of an ft set
+ //
+
+ if ( (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED)
+ && (regionDescriptor->RegionType == REGION_PRIMARY)
+ && !regionDescriptor->Active
+ && (GET_FT_OBJECT(regionDescriptor) == NULL))
+ {
+ allowActive = TRUE;
+ }
+
+ } else if (SelectionCount == 2 && FtSelectionType == Mirror) {
+
+ //
+ // If either of the two partitions in the mirror is primary
+ // and not active then allow the menu item.
+ //
+
+ for (i = 0; i < SelectionCount; i++) {
+ regionDescriptor = &SELECTED_REGION(i);
+ if (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED &&
+ regionDescriptor->RegionType == REGION_PRIMARY &&
+ !regionDescriptor->Active) {
+
+ allowActive = TRUE;
+ }
+ }
+ }
+
+ EnableMenuItem(hMenu,
+ IDM_PARTITIONACTIVE,
+ allowActive ? MF_ENABLED : MF_GRAYED
+ );
+}
+
+#endif
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsVolumeFormatted, public
+//
+// Synopsis: Returns TRUE if volume represented by the argument
+// region is formatted.
+//
+// Arguments: [RegionDescriptor] -- indicates region
+//
+// Returns: TRUE/FALSE
+//
+// History: 2-Jul-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+IsVolumeFormatted(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+ if (NULL != regionData)
+ {
+ return (0 != lstrcmp(regionData->TypeName, wszUnknown))
+ && (0 != lstrcmp(regionData->TypeName, wszUnformatted))
+ ;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DetermineSelectionState, public
+//
+// Synopsis: Returns TRUE if volume represented by the argument
+// region is formatted.
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// Modifies: lots of selection state variables
+//
+// History: 29-Jul-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+DetermineSelectionState(
+ VOID
+ )
+{
+ ULONG i;
+ ULONG j;
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+ PFT_OBJECT_SET ftSet;
+ PFT_OBJECT ftObject;
+ FT_TYPE ftType;
+ ULONG ordinal;
+ ULONG componentsInFtSet = 0;
+
+ //
+ // Initialize globals
+ //
+
+ FtSetSelected = FALSE;
+ FtSelectionType = UNINIT_FT_TYPE;
+ NonFtItemSelected = FALSE;
+ MultipleItemsSelected = FALSE;
+ VolumeSetAndFreeSpaceSelected = FALSE;
+ PartitionAndFreeSpaceSelected = FALSE;
+ SelectedNonFtPartitions = 0;
+ SelectionCount = 0;
+ CdRomSelectionCount = 0;
+ CdRomSelected = FALSE;
+ RtlZeroMemory(DiskSeenCountArray, DiskCount * sizeof(DiskSeenCountArray[0]));
+
+ for (i=0; i<DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+
+ for (j=0; j<diskState->RegionCount; j++)
+ {
+ if (diskState->Selected[j])
+ {
+ SelectionCount++;
+
+ if (SelectionCount <= MAX_MEMBERS_IN_FT_SET)
+ {
+ SelectedDS[SelectionCount-1] = diskState;
+ SelectedRG[SelectionCount-1] = j;
+ }
+
+ DiskSeenCountArray[diskState->Disk]++;
+
+ if (NULL != (ftObject = GET_FT_OBJECT(&diskState->RegionArray[j])))
+ {
+ ftSet = ftObject->Set;
+ if (componentsInFtSet == 0)
+ {
+ ordinal = ftSet->Ordinal;
+ ftType = ftSet->Type;
+ FtSetSelected = TRUE;
+ componentsInFtSet = 1;
+ }
+ else if ((ftSet->Ordinal == ordinal)
+ && (ftSet->Type == ftType))
+ {
+ componentsInFtSet++;
+ }
+ else
+ {
+ FtSetSelected = FALSE;
+ }
+ }
+ else
+ {
+ NonFtItemSelected = TRUE;
+
+ if (IsRecognizedPartition(diskState->RegionArray[j].SysID))
+ {
+ SelectedNonFtPartitions += 1;
+ }
+ }
+ }
+ }
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+
+ if (cdrom->Selected)
+ {
+ CdRomSelectionCount++;
+ CdRomSelected = TRUE;
+ }
+ }
+
+ //
+ // Determine the number of free-space regions selected:
+ //
+ SelectedFreeSpaces = 0;
+
+ for (i=0; i<SelectionCount && i < MAX_MEMBERS_IN_FT_SET; i++)
+ {
+ if (SELECTED_REGION(i).SysID == PARTITION_ENTRY_UNUSED)
+ {
+ FreeSpaceIndex = i;
+ SelectedFreeSpaces++;
+ }
+ }
+
+ PossibleRecover = FALSE;
+ if (NonFtItemSelected && FtSetSelected)
+ {
+ //
+ // Both FT and Non-FT items have been selected. First,
+ // check to see if a volume set and free space have been
+ // selected; then reset the state to indicate that the
+ // selection does not consists of a mix of FT and non-FT
+ // objects.
+ //
+ if (ftType == VolumeSet
+ && SelectedFreeSpaces + componentsInFtSet == SelectionCount)
+ {
+ VolumeSetAndFreeSpaceSelected = TRUE;
+ }
+
+ FtSelectionType = ftType;
+ FtSetSelected = FALSE;
+ NonFtItemSelected = FALSE;
+ MultipleItemsSelected = TRUE;
+ PossibleRecover = TRUE;
+ }
+
+ if (FtSetSelected)
+ {
+ FtSelectionType = ftType;
+ }
+
+ // the only way to get a disk selected right now is via context-menu
+ // right-mouse click
+
+ DiskSelected = FALSE;
+
+ if (SelectionCount > 0)
+ {
+ PartitionSelected = TRUE;
+ }
+ else
+ {
+ PartitionSelected = FALSE;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SingleVolumeSelected, public
+//
+// Synopsis: Returns TRUE if a single volume is selected. A single volume
+// is either a single, simple partition that isn't unused (i.e.,
+// is used), OR a single fault tolerant set.
+//
+// Arguments: (none)
+//
+// Returns: TRUE/FALSE
+//
+// History: 29-Jul-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+SingleVolumeSelected(
+ VOID
+ )
+{
+ BOOL singleVolume = FALSE;
+
+ if (!CdRomSelected && (SelectionCount == 1) && !FtSetSelected)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+
+ if (DmSignificantRegion(regionDescriptor))
+ {
+ //
+ // single selection, simple (single-partition) volume
+ //
+
+ singleVolume = TRUE;
+ }
+ }
+
+ if (!CdRomSelected && FtSetSelected)
+ {
+ //
+ // single volume selected, but it is a multiple-region FT volume
+ //
+
+ singleVolume = TRUE;
+ }
+
+ if (CdRomSelected && CdRomSelectionCount == 1)
+ {
+ singleVolume = TRUE;
+ }
+
+ return singleVolume;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetUpMenu
+//
+// Synopsis: Set up the menu bar based on the state of the tool and
+// the disks
+//
+// If multiple items are selected, allow neither create nor delete.
+// If a single partition is selected, allow delete.
+// If a single free space is selected, allow create.
+// If the free space is the only free space in the extended partitions,
+// also allow delete. (This is how to delete the extended partition).
+//
+// If a single volume is selected, allow format.
+//
+// Arguments: [SinglySelectedDisk] -- if there is only one selected item,
+// the PDISKSTATE pointed to by this paramater will get a
+// pointer to the selected region's disk structure. If
+// there are multiple selected items (or none), then the value
+// will be set to NULL.
+// [SinglySelectedRegion] -- if there is only one selected item,
+// the DWORD pointed to by this paramater will get the
+// selected region #. Otherwise the DWORD gets -1.
+//
+// Returns: Count of selected regions
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+DWORD
+SetUpMenu(
+ IN PDISKSTATE *SinglySelectedDisk,
+ IN DWORD *SinglySelectedRegion
+ )
+{
+ PFT_OBJECT_SET ftSet = NULL;
+ PFT_OBJECT ftObject = NULL;
+ PDISKSTATE selectedDiskState;
+ DWORD selectedRegion;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PPERSISTENT_REGION_DATA regionData;
+ DWORD i;
+ BOOL onDifferentDisks;
+ WCHAR rootDirectory[5];
+
+ BOOL allowCommit = FALSE,
+ allowCreate = FALSE,
+ allowCreateEx = FALSE,
+#if defined( DBLSPACE_ENABLED )
+ allowDblSpace = FALSE,
+#endif // DBLSPACE_ENABLED
+ allowDelete = FALSE,
+ allowProperties = FALSE,
+ allowCreateMirror = FALSE,
+ allowBreakMirror = FALSE,
+ allowCreateStripe = FALSE,
+ allowCreateVolumeSet = FALSE,
+ allowExtendVolumeSet = FALSE,
+ allowCreatePStripe = FALSE,
+ allowDriveLetter = FALSE,
+ allowRecoverParity = FALSE,
+ allowEject = FALSE;
+
+ WCHAR driveLetter = L' ';
+ PWSTR typeName = NULL;
+ PWSTR volumeLabel = NULL;
+
+ AllowFormat = FALSE;
+ AllowVolumeOperations = FALSE;
+
+#ifdef WINDISK_EXTENSIONS
+ AllowExtensionItems = FALSE;
+#endif // WINDISK_EXTENSIONS
+
+ //
+ // Start by setting a bunch of global variables based on the selection
+ // state.
+ //
+
+ DetermineSelectionState();
+
+ if (CdRomSelected)
+ {
+ if (CdRomSelectionCount == 1 && SelectionCount == 0)
+ {
+ allowDriveLetter = TRUE;
+
+ //
+ // Find (the hard way) the selected drive.
+ //
+
+ for (i=0;i<CdRomCount;i++) {
+
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(i);
+
+ if (cdrom->Selected) {
+
+
+ //
+ // If there is no cdrom, no point in eject.
+ //
+
+ if (cdrom->TotalSpaceInMB) {
+
+ allowEject = TRUE;
+
+ }
+
+ //
+ // If there is no drive letter, nothing to give the properties
+ //
+
+ if (cdrom->DriveLetter != NO_DRIVE_LETTER_EVER) {
+
+ allowProperties = TRUE;
+
+ }
+
+ }
+
+ }
+ }
+ }
+ else if ((SelectionCount == 1) && !FtSetSelected)
+ {
+ selectedDiskState = SelectedDS[0];
+ selectedRegion = SelectedRG[0];
+
+ *SinglySelectedDisk = selectedDiskState;
+ *SinglySelectedRegion = selectedRegion;
+
+ regionDescriptor = &selectedDiskState->RegionArray[selectedRegion];
+
+ if (regionDescriptor && IsDiskRemovable[regionDescriptor->Disk]) {
+ allowEject = TRUE;
+ allowProperties = TRUE;
+ }
+
+ if (regionDescriptor->SysID == PARTITION_ENTRY_UNUSED)
+ {
+ //
+ // Free region. Always allow create; let DoCreate() sort out
+ // details about whether partition table is full, etc.
+ //
+
+ allowCreate = TRUE;
+
+ if (regionDescriptor->RegionType == REGION_PRIMARY)
+ {
+ allowCreateEx = TRUE;
+ }
+
+ // special case -- allow deletion of the extended partition if
+ // there are no logicals in it.
+
+ if ( (regionDescriptor->RegionType == REGION_LOGICAL)
+ && selectedDiskState->ExistExtended
+ && !selectedDiskState->ExistLogical)
+ {
+ FDASSERT(regionDescriptor->SysID == PARTITION_ENTRY_UNUSED);
+ allowDelete = TRUE;
+ }
+ }
+ else
+ {
+ // used region. Delete always allowed.
+
+ allowDelete = TRUE;
+
+ // also allow format of used region, if it has a drive letter, and
+ // is not the system or boot partition.
+
+ regionData = PERSISTENT_DATA(regionDescriptor);
+ if ( NULL != regionData
+ && !regionData->NewRegion
+ && IsLegalDriveLetter(regionData->DriveLetter))
+ {
+ AllowFormat = TRUE;
+
+#ifdef WINDISK_EXTENSIONS
+ if (SingleVolumeSelected())
+ {
+ AllowExtensionItems = TRUE;
+ }
+#endif // WINDISK_EXTENSIONS
+ }
+
+ //
+ // If the region is recognized, then also allow drive letter
+ // manipulation.
+ //
+
+ if (IsRecognizedPartition(regionDescriptor->SysID))
+ {
+
+ //
+ // Not on removables though.
+ //
+
+ if (!IsDiskRemovable[regionDescriptor->Disk]) {
+ allowDriveLetter = TRUE;
+ }
+
+ DetermineRegionInfo(regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetter);
+
+ if (!IsExtraDriveLetter(driveLetter))
+ {
+ if (0 == lstrcmp(typeName, L"FAT"))
+ {
+ AllowVolumeOperations = AllowFormat;
+#if defined( DBLSPACE_ENABLED )
+ // DblSpace volumes are allowed on non-FT, FAT
+ // volumes only
+ allowDblSpace = AllowFormat;
+#endif // DBLSPACE_ENABLED
+ }
+
+ //BUGBUG: better way to determine if file system ops
+ //are allowed?
+ if ( (lstrcmp(typeName, L"NTFS") == 0)
+#ifdef SUPPORT_OFS
+ || (lstrcmp(typeName, L"OFS") == 0)
+#endif // SUPPORT_OFS
+ )
+ {
+ AllowVolumeOperations = AllowFormat;
+ }
+ }
+ }
+ }
+ }
+ else if (0 != SelectionCount)
+ {
+ *SinglySelectedDisk = NULL;
+ *SinglySelectedRegion = (DWORD)(-1);
+
+ //
+ // Multiple regions are selected. This might be an existing ft set,
+ // a set of regions that allow creation of an ft set, or just plain
+ // old multiple items.
+ //
+ // First deal with a selected ft set.
+ //
+
+ if (FtSetSelected)
+ {
+ regionDescriptor = &SELECTED_REGION(0);
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ // Should locate member zero of the set since it may not be
+ // committed yet.
+
+ if (NULL != regionData)
+ {
+ if (!regionData->NewRegion)
+ {
+ if (!IsExtraDriveLetter(regionData->DriveLetter))
+ {
+ // Now check for special cases on FT sets
+
+ ftObject = regionData->FtObject;
+ if (NULL != ftObject)
+ {
+ ftSet = ftObject->Set;
+ if (NULL != ftSet)
+ {
+ FT_SET_STATUS setState = ftSet->Status;
+ ULONG numberOfMembers;
+
+ LowFtVolumeStatus(
+ regionDescriptor->Disk,
+ regionDescriptor->PartitionNumber,
+ &setState,
+ &numberOfMembers);
+
+ if ( (ftSet->Status != FtSetDisabled)
+ && (setState != FtSetDisabled))
+ {
+ AllowFormat = TRUE;
+ }
+ }
+ }
+ }
+
+ //BUGBUG: better way to determine if file system ops
+ //are allowed?
+ if (NULL != regionData->TypeName)
+ {
+ typeName = regionData->TypeName;
+ if ( (lstrcmp(typeName, L"NTFS") == 0)
+#ifdef SUPPORT_OFS
+ || (lstrcmp(typeName, L"OFS") == 0)
+#endif // SUPPORT_OFS
+ || (lstrcmp(typeName, L"FAT") == 0))
+ {
+ AllowVolumeOperations = AllowFormat;
+ }
+ }
+ else
+ {
+ typeName = NULL;
+ DetermineRegionInfo(regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetter);
+ if (NULL == typeName)
+ {
+ if (SelectionCount > 1)
+ {
+ // it is an FT set - try the next member.
+
+ regionDescriptor = &SELECTED_REGION(1);
+ DetermineRegionInfo(regionDescriptor,
+ &typeName,
+ &volumeLabel,
+ &driveLetter);
+ regionDescriptor = &SELECTED_REGION(0);
+ }
+ }
+
+ if ( (lstrcmp(regionData->TypeName, L"NTFS") == 0)
+#ifdef SUPPORT_OFS
+ || (lstrcmp(regionData->TypeName, L"OFS") == 0)
+#endif // SUPPORT_OFS
+ || (lstrcmp(regionData->TypeName, L"FAT") == 0))
+ {
+ AllowVolumeOperations = AllowFormat;
+ }
+ }
+ }
+ }
+
+#ifdef WINDISK_EXTENSIONS
+ if (AllowFormat && !regionData->NewRegion)
+ {
+ AllowExtensionItems = TRUE;
+ }
+#endif // WINDISK_EXTENSIONS
+
+ //
+ // allow the correct type of ft-related delete.
+ //
+
+ switch (FtSelectionType)
+ {
+ case Mirror:
+ allowDelete = TRUE;
+ allowBreakMirror = TRUE;
+ break;
+
+ case StripeWithParity:
+ ftObject = GET_FT_OBJECT(&SELECTED_REGION(0));
+ ftSet = ftObject->Set;
+ if ( SelectionCount == ftSet->NumberOfMembers
+ && (ftSet->Status == FtSetRecoverable))
+ {
+ // Are all members present?
+
+ allowRecoverParity = TRUE;
+ }
+ allowDelete = TRUE;
+ break;
+
+ case Stripe:
+ case VolumeSet:
+ allowDelete = TRUE;
+ break;
+
+ default:
+ FDASSERT(FALSE);
+ }
+
+ if (FtSelectionType == StripeWithParity)
+ {
+ // If the set is disabled, do not allow drive
+ // letter changes - This is done because there are
+ // conditions whereby the drive letter code will
+ // access violate if this is done.
+
+ if (ftSet->Status != FtSetDisabled)
+ {
+ // Must have either member 0 or member 1 for access
+
+ for (ftObject = ftSet->Members;
+ NULL != ftObject;
+ ftObject = ftObject->Next)
+ {
+ if ( (ftObject->MemberIndex == 0)
+ || (ftObject->MemberIndex == 1))
+ {
+ allowDriveLetter = TRUE;
+ break;
+ }
+ }
+
+ // if the drive letter cannot be done, then no live
+ // action can be done.
+
+ if (!allowDriveLetter)
+ {
+ ftSet->Status = FtSetDisabled;
+ AllowFormat = FALSE;
+ AllowVolumeOperations = FALSE;
+ }
+ }
+ }
+ else
+ {
+ allowDriveLetter = TRUE;
+ }
+ }
+ else
+ {
+ //
+ // Next figure out whether some sort of ft object set could
+ // be created out of the selected regions.
+ //
+
+ if (SelectionCount <= MAX_MEMBERS_IN_FT_SET)
+ {
+ //
+ // Determine whether the selected regions are all on
+ // different disks.
+ //
+
+ onDifferentDisks = TRUE;
+ for (i=0; i<DiskCount; i++)
+ {
+ if (DiskSeenCountArray[i] > 1)
+ {
+ onDifferentDisks = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Check for allowing mirror creation. User must have
+ // selected two regions -- one a recognized partition,
+ // the other a free space.
+ //
+
+ if ( onDifferentDisks
+ && (SelectionCount == 2)
+ && ((SELECTED_REGION(0).SysID == PARTITION_ENTRY_UNUSED)
+ != (SELECTED_REGION(1).SysID == PARTITION_ENTRY_UNUSED))
+ && ( IsRecognizedPartition(SELECTED_REGION(0).SysID)
+ || IsRecognizedPartition(SELECTED_REGION(1).SysID))
+ && !GET_FT_OBJECT(&SELECTED_REGION(0))
+ && !GET_FT_OBJECT(&SELECTED_REGION(1)))
+ {
+ allowCreateMirror = TRUE;
+ }
+
+ //
+ // Check for allowing volume set or stripe set
+ //
+
+ if (SelectedFreeSpaces == SelectionCount)
+ {
+ allowCreateVolumeSet = TRUE;
+ if (onDifferentDisks)
+ {
+ allowCreateStripe = TRUE;
+ if (SelectedFreeSpaces > 2)
+ {
+ allowCreatePStripe = TRUE;
+ }
+ }
+ }
+
+ // Check for allowing volume set expansion. If
+ // the selected regions consist of one volume set
+ // and free space, then that volume set can be
+ // extended. If the selection consists of one
+ // recognized non-FT partition and free space,
+ // then we can convert those regions into a
+ // volume set.
+ //
+ if ( VolumeSetAndFreeSpaceSelected
+ || ( SelectionCount > 1
+ && SelectedFreeSpaces == SelectionCount - 1
+ && SelectedNonFtPartitions == 1) )
+ {
+ allowExtendVolumeSet = TRUE;
+ }
+
+ //
+ // If the ftselection type is non-zero then
+ // we have selection of ft partitions. However
+ // since it might not be the 0th one make sure
+ // to try the 1st.
+ //
+
+ if ((FtSelectionType == StripeWithParity) ||
+ (FtSelectionType == Mirror)) {
+
+ ftObject = GET_FT_OBJECT(&SELECTED_REGION(0));
+
+ if (ftObject == NULL) {
+
+ ftObject = GET_FT_OBJECT(&SELECTED_REGION(1));
+
+ }
+
+ }
+
+ //
+ // Check for allowing non-in-place FT recover
+ //
+
+ if ( (SelectionCount > 1)
+ && (SelectedFreeSpaces == 1)
+ && PossibleRecover
+ && (FtSelectionType == StripeWithParity)
+ && (NULL != ftObject)
+ && (NULL != (ftSet = ftObject->Set))
+ && (ftSet->Status == FtSetRecoverable))
+ {
+ BOOL orphanOnSameDiskAsFreeSpace = FALSE;
+
+ if (!onDifferentDisks)
+ {
+ //
+ // Determine whether the orphan is on the same
+ // disk as the free space. First find the orphan.
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ PREGION_DESCRIPTOR reg = &SELECTED_REGION(i);
+
+ if ( (i != FreeSpaceIndex)
+ && (GET_FT_OBJECT(reg)->State == Orphaned))
+ {
+ if (SELECTED_REGION(FreeSpaceIndex).Disk == reg->Disk)
+ {
+ orphanOnSameDiskAsFreeSpace = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ if (onDifferentDisks || orphanOnSameDiskAsFreeSpace)
+ {
+ allowRecoverParity = TRUE;
+ }
+ }
+
+ if ( (SelectionCount == 2)
+ && (SelectedFreeSpaces == 1)
+ && PossibleRecover
+ && (FtSelectionType == Mirror)
+ && (NULL != (ftObject = GET_FT_OBJECT(&SELECTED_REGION(0))))
+ && (NULL != (ftSet = ftObject->Set))
+ && (ftSet->Status == FtSetRecoverable))
+ {
+ BOOL orphanOnSameDiskAsFreeSpace = FALSE;
+
+ if (!onDifferentDisks)
+ {
+ //
+ // Determine whether the orphan is on the same
+ // disk as the free space. First find the orphan.
+ //
+
+ for (i=0; i<SelectionCount; i++)
+ {
+ PREGION_DESCRIPTOR reg = &SELECTED_REGION(i);
+
+ if ( (i != FreeSpaceIndex)
+ && (GET_FT_OBJECT(reg)->State == Orphaned))
+ {
+ if (SELECTED_REGION(FreeSpaceIndex).Disk == reg->Disk)
+ {
+ orphanOnSameDiskAsFreeSpace = TRUE;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Formattabilty is akin to propertibility. (That and explorer lets you see
+ // the properties).
+ //
+
+ if (AllowFormat)
+ {
+ allowProperties = TRUE;
+ }
+
+ if (RegistryChanged || CommitAllowed())
+ {
+ allowCommit = TRUE;
+ }
+
+ //
+ // Now that we've determined whether to allow or disallow all commands,
+ // enable or disable each access method to those commands.
+ //
+
+ HMENU hMenu = GetMenu(g_hwndFrame);
+
+//
+// Volume menu
+//
+ //
+ // Change the "format" entry to be either "format" or "change
+ // format" based on whether the selection is unformatted or not
+ // (respectively)
+ //
+
+ WCHAR formatTextBuffer[MAX_RESOURCE_STRING_LEN];
+
+ if ( AllowFormat
+ && SingleVolumeSelected()
+ && IsVolumeFormatted(&SELECTED_REGION(0)))
+ {
+ LoadString(
+ g_hInstance,
+ IDS_CHANGEFORMAT,
+ formatTextBuffer,
+ ARRAYLEN(formatTextBuffer));
+ }
+ else
+ {
+ LoadString(
+ g_hInstance,
+ IDS_FORMAT,
+ formatTextBuffer,
+ ARRAYLEN(formatTextBuffer));
+ }
+
+ ModifyMenu(
+ hMenu,
+ IDM_VOL_FORMAT,
+ MF_BYCOMMAND | MF_STRING,
+ IDM_VOL_FORMAT,
+ formatTextBuffer);
+
+ EnableMenuItem(hMenu,
+ IDM_VOL_FORMAT,
+ AllowFormat ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu, IDM_VOL_EJECT, allowEject ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_VOL_LETTER,
+ allowDriveLetter ? MF_ENABLED : MF_GRAYED);
+
+#if defined( DBLSPACE_ENABLED )
+ EnableMenuItem(hMenu,
+ IDM_VOL_DBLSPACE,
+ (allowDblSpace && g_DoubleSpaceSupported)
+ ? MF_ENABLED : MF_GRAYED);
+
+ DoubleSpaceAutomount = DiskRegistryAutomountCurrentState();
+
+ if (DoubleSpaceAutomount)
+ {
+ CheckMenuItem(hMenu, IDM_VOL_AUTOMOUNT, MF_BYCOMMAND | MF_CHECKED);
+ }
+
+ EnableMenuItem(hMenu,
+ IDM_VOL_AUTOMOUNT,
+ MF_ENABLED);
+#endif // DBLSPACE_ENABLED
+
+ EnableMenuItem(hMenu,
+ IDM_VOL_PROPERTIES,
+ allowProperties ? MF_ENABLED : MF_GRAYED);
+
+//
+// Partition menu
+//
+
+ EnableMenuItem(hMenu,
+ IDM_PARTITIONCREATE,
+ allowCreate ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_PARTITIONCREATEEX,
+ allowCreateEx ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_PARTITIONDELETE,
+ allowDelete ? MF_ENABLED : MF_GRAYED);
+
+#if i386
+ SetUpMenui386(hMenu);
+#else
+ EnableMenuItem(hMenu,
+ IDM_SECURESYSTEM,
+ MF_ENABLED);
+
+ CheckMenuItem(hMenu,
+ IDM_SECURESYSTEM,
+ SystemPartitionIsSecure ? MF_CHECKED : MF_UNCHECKED);
+#endif
+
+ EnableMenuItem(hMenu,
+ IDM_PARTITIONCOMMIT,
+ allowCommit ? MF_ENABLED : MF_GRAYED);
+
+//
+// Fault Tolerance menu
+//
+
+ EnableMenuItem(hMenu,
+ IDM_FTBREAKMIRROR,
+ allowBreakMirror ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTESTABLISHMIRROR,
+ g_IsLanmanNt &&
+ allowCreateMirror ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTCREATESTRIPE,
+ allowCreateStripe ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTCREATEPSTRIPE,
+ allowCreatePStripe ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTCREATEVOLUMESET,
+ allowCreateVolumeSet ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTEXTENDVOLUMESET,
+ allowExtendVolumeSet ? MF_ENABLED : MF_GRAYED);
+
+ EnableMenuItem(hMenu,
+ IDM_FTRECOVERSTRIPE,
+ g_IsLanmanNt &&
+ allowRecoverParity ? MF_ENABLED : MF_GRAYED);
+
+
+ EnableMenuItem(hMenu,
+ IDM_OPTIONSCOLORS,
+ g_WhichView == VIEW_VOLUMES ? MF_GRAYED : MF_ENABLED);
+
+ EnableMenuItem(hMenu,
+ IDM_OPTIONSDISK,
+ g_WhichView == VIEW_VOLUMES ? MF_GRAYED : MF_ENABLED);
+
+ EnableMenuItem(hMenu,
+ IDM_OPTIONSDISPLAY,
+ g_WhichView == VIEW_VOLUMES ? MF_GRAYED : MF_ENABLED);
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+#ifdef WINDISK_EXTENSIONS
+
+ BOOL fAnyVolExtensionItems = FALSE;
+
+ HMENU hmenuVolume = GetSubMenu(hMenu, 0);
+
+ //
+ // erase the dictionary of context menu command identifiers
+ //
+
+ MenuItems.DeAllocateMenuIds();
+
+ //
+ // Delete the extension items on the menu bar
+ //
+
+ while (g_uItemInsertHere > UITEM_INSERT_HERE)
+ {
+ DeleteMenu(hmenuVolume, --g_uItemInsertHere, MF_BYPOSITION);
+ }
+
+ //
+ // Determine if there are any context menu items drawn from extension
+ // classes (based on previous claiming). Only allow extension items on
+ // pre-existing volumes or disks, for single selection.
+ //
+
+ if (AllowExtensionItems)
+ {
+ regionDescriptor = &SELECTED_REGION(0);
+ WCHAR driveLetter = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+
+ if (IsLegalDriveLetter(driveLetter))
+ {
+ unsigned driveIndex = DriveLetterToIndex(driveLetter);
+
+ //
+ // add the volume extension items
+ //
+
+ if (NULL != VolumeInfo[driveIndex].VolClaims)
+ {
+ fAnyVolExtensionItems = TRUE;
+ }
+
+ if (fAnyVolExtensionItems)
+ {
+ unsigned index = DriveLetterToIndex(driveLetter);
+ PVOL_CLAIM_LIST volClaims = VolumeInfo[index].VolClaims;
+ while (NULL != volClaims)
+ {
+ AddExtensionItemsToMenu(
+ hmenuVolume,
+ &(volClaims->pClaimer->pInfo->mnuOps),
+ AllowExtensionItems ? MF_ENABLED : MF_GRAYED
+ );
+
+ volClaims = volClaims->pNext;
+ }
+ }
+ }
+ }
+
+#endif // WINDISK_EXTENSIONS
+
+ //////////////////////////////////////////////////////////////////////////
+
+ SetToolbarButtonState();
+
+ //////////////////////////////////////////////////////////////////////////
+
+ return SelectionCount + CdRomSelectionCount;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetDriveLetterInfo
+//
+// Synopsis: After we get the partition information for a disk, the
+// partition number might have changed, so reset our Drive Letter
+// knowledge.
+//
+// Arguments: [DiskNum] -- The disk number
+//
+// Returns: nothing
+//
+// History: 24-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetDriveLetterInfo(
+ IN UINT DiskNum
+ )
+{
+ PDISKSTATE diskState = DiskArray[DiskNum];
+
+ for (ULONG i=0; i<diskState->RegionCount; i++)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &diskState->RegionArray[i];
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (regionData && !regionData->NewRegion)
+ {
+ NewDriveLetter(
+ regionData->DriveLetter,
+ DiskNum,
+ regionDescriptor->PartitionNumber
+ );
+ }
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TotalRedraw
+//
+// Synopsis: Redraws the entire disks view
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+TotalRedraw(
+ VOID
+ )
+{
+ ULONG i;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ DrawDiskBar(DiskArray[i]);
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ DrawCdRomBar(i);
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RedrawSelectedBars
+//
+// Synopsis: Redraws bars that form part of the current selection
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 1-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+RedrawSelectedBars(
+ VOID
+ )
+{
+ ULONG i;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ if (DiskSeenCountArray[i] > 0)
+ {
+ DrawDiskBar(DiskArray[i]);
+ }
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ if (CdRomArray[i].Selected)
+ {
+ DrawCdRomBar(i);
+ }
+ }
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TotalRedrawAndRepaint
+//
+// Synopsis: Redraws and repaints the entire disks view
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+TotalRedrawAndRepaint(
+ VOID
+ )
+{
+ TotalRedraw();
+ ForceLBRedraw(); // a repaint
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DmAllocatePersistentData
+//
+// Synopsis: Allocate a structure to hold persistent region data. Fill
+// in the volume label, type name, and drive letter. The volume
+// label and type name are duplicated.
+//
+// Arguments:
+//
+// [FtObject] -- the FT object, or NULL if this region isn't in
+// an FT set.
+//
+// [VolumeLabel] -- volume label to be stored in the the persistent data.
+// The string will be duplicated first and a pointer to the duplicate
+// copy is what is stored in the persistent data. May be NULL.
+//
+// [TypeName] -- name of type of region, ie unformatted, FAT, etc.
+// May be NULL.
+//
+// [DriveLetter] -- drive letter to be stored in persistent data
+//
+// [NewRegion] -- TRUE if this is a newly created region
+//
+// Returns: Pointer to newly allocated persistent data structure. The
+// structure may be freed via DmFreePersistentData(), below.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+PPERSISTENT_REGION_DATA
+DmAllocatePersistentData(
+ IN PFT_OBJECT FtObject,
+ IN PWSTR VolumeLabel,
+ IN PWSTR TypeName,
+ IN WCHAR DriveLetter,
+ IN BOOL NewRegion,
+ IN LARGE_INTEGER FreeSpaceInBytes,
+ IN LARGE_INTEGER TotalSpaceInBytes
+ )
+{
+ PWSTR volumeLabel = NULL;
+ PWSTR typeName = NULL;
+
+ if (VolumeLabel)
+ {
+ volumeLabel = (PWSTR)Malloc((lstrlen(VolumeLabel)+1)*sizeof(WCHAR));
+ lstrcpy(volumeLabel, VolumeLabel);
+ }
+
+ if (TypeName)
+ {
+ typeName = (PWSTR)Malloc((lstrlen(TypeName)+1)*sizeof(WCHAR));
+ lstrcpy(typeName, TypeName);
+ }
+
+ PPERSISTENT_REGION_DATA regionData
+ = (PPERSISTENT_REGION_DATA)Malloc(sizeof(PERSISTENT_REGION_DATA));
+
+ DmInitPersistentRegionData(
+ regionData,
+ FtObject,
+ volumeLabel,
+ typeName,
+ DriveLetter,
+ NewRegion,
+ FreeSpaceInBytes,
+ TotalSpaceInBytes
+ );
+
+ return regionData;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DmFreePersistentData
+//
+// Synopsis: Free a persistent data structure and storage used for
+// volume label and type name (does not free ft objects).
+//
+// Arguments: [RegionData] -- structure to be freed.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DmFreePersistentData(
+ IN OUT PPERSISTENT_REGION_DATA RegionData
+ )
+{
+ if (RegionData->VolumeLabel)
+ {
+ Free(RegionData->VolumeLabel);
+ }
+ if (RegionData->TypeName)
+ {
+ Free(RegionData->TypeName);
+ }
+
+ Free(RegionData);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ChangeView
+//
+// Synopsis: Toggle the view between the volumes and disks view
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+ChangeView(
+ VOID
+ )
+{
+ SetCursor(g_hCurWait);
+
+ //
+ // 'g_WhichView' is set to the new view
+ //
+
+ MyCheckMenuItem(
+ g_hmenuFrame,
+ IDM_VIEWVOLUMES,
+ IDM_VIEWDISKS,
+ (g_WhichView == VIEW_VOLUMES) ? IDM_VIEWVOLUMES : IDM_VIEWDISKS
+ );
+
+ switch (g_WhichView)
+ {
+ case VIEW_VOLUMES:
+ ChangeToVolumesView();
+ break;
+
+ case VIEW_DISKS:
+ ChangeToDisksView();
+ break;
+
+ default:
+ FDASSERT(0);
+ }
+
+#if DBG == 1
+ if (BothViews)
+ {
+ ShowWindow(g_hwndList, SW_SHOW);
+ ShowWindow(g_hwndLV, SW_SHOW);
+ EnableMenuItem(g_hmenuFrame,IDM_OPTIONSLEGEND,MF_BYCOMMAND|MF_ENABLED);
+ }
+#endif // DBG == 1
+
+ RECT rc;
+ GetClientRect(g_hwndFrame, &rc);
+
+ // Send a WM_SIZE message to force recalculation of the size of various
+ // child windows and spaces based on the new view options. E.g., changing
+ // to volumes view from disks view forces legend to disappear.
+
+ SendMessage(g_hwndFrame, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.right, rc.bottom));
+ InvalidateRect(g_hwndFrame, NULL, TRUE);
+
+ SetCursor(g_hCurNormal);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: AdjustOptionsMenu
+//
+// Synopsis: Set the options menu to be consistent with the tool state
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+AdjustOptionsMenu(
+ VOID
+ )
+{
+ CheckMenuItem(g_hmenuFrame,
+ IDM_OPTIONSTOOLBAR,
+ MF_BYCOMMAND | (g_Toolbar ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(g_hmenuFrame,
+ IDM_OPTIONSSTATUS,
+ MF_BYCOMMAND | (g_StatusBar ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ CheckMenuItem(g_hmenuFrame,
+ IDM_OPTIONSLEGEND,
+ MF_BYCOMMAND | (g_Legend ? MF_CHECKED : MF_UNCHECKED)
+ );
+
+ RECT rc;
+ GetClientRect(g_hwndFrame, &rc);
+
+ // Send a WM_SIZE message to force recalculation of the size of various
+ // child windows and spaces based on the new set of options
+
+ SendMessage(g_hwndFrame, WM_SIZE, SIZE_RESTORED, MAKELONG(rc.right, rc.bottom));
+ InvalidateRect(g_hwndFrame, NULL, TRUE);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PaintStatusBar
+//
+// Synopsis: Paint the status bar
+//
+// Arguments: [hwnd] -- window to paint to
+// [pps] -- the paint structure returned by BeginPaint
+// [prc] -- the rectangle for the entire frame. Paint at
+// the bottom of it.
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PaintStatusBar(
+ IN HWND hwnd,
+ IN PAINTSTRUCT* pps,
+ IN PRECT prc
+ )
+{
+ if (g_fDoingMenuHelp)
+ {
+ return; // don't paint the status bar if we're showing menu help
+ }
+
+ HDC hdcTemp, hdcScr;
+ HBITMAP hbmTemp;
+ HBRUSH hBrush;
+ HFONT hFontOld;
+ RECT rcTemp;
+ RECT rc;
+ DWORD dxSeparation;
+
+ rc = *prc;
+ hdcScr = pps->hdc;
+
+ rc.top = rc.bottom - g_dyStatus;
+
+ hdcTemp = CreateCompatibleDC(hdcScr);
+ hbmTemp = CreateCompatibleBitmap(
+ hdcScr,
+ rc.right - rc.left,
+ rc.bottom - rc.top
+ );
+ SelectBitmap(hdcTemp, hbmTemp);
+
+ // adjust position for off-screen bitmap
+
+ rcTemp = rc;
+ rc.bottom -= rc.top;
+ rc.top = 0;
+
+ hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+ if (hBrush)
+ {
+ FillRect(hdcTemp, &rc, hBrush);
+ DeleteBrush(hBrush);
+ }
+
+ // draw the status bar at the bottom of the window
+
+ hFontOld = SelectFont(hdcTemp, g_hFontStatus);
+
+ //
+ // There are 5 status items, drawn in this order:
+ //
+ // description example
+ // ----------- -------
+ // Status text Stripe set #0
+ // size 51 MB
+ // file system type FAT
+ // drive letter F:
+ // volume label MYVOLUME
+ //
+ // All except drive letter are proportional to the window width.
+ //
+
+ // Separation between status elements, and between a status element
+ // and the window border
+ dxSeparation = 8 * g_dyBorder;
+
+ // Status text
+ rc.left = dxSeparation;
+ rc.right = 2 * GraphWidth / 5;
+ DrawStatusAreaItem(&rc, hdcTemp, StatusTextStat);
+
+ // size
+ rc.left = rc.right + dxSeparation;
+ rc.right = rc.left + (GraphWidth / 9);
+ DrawStatusAreaItem(&rc, hdcTemp, StatusTextSize);
+
+ // type
+ rc.left = rc.right + dxSeparation;
+ rc.right = rc.left + (GraphWidth / 5);
+ DrawStatusAreaItem(&rc, hdcTemp, StatusTextType);
+
+ // drive letter
+ rc.left = rc.right + dxSeparation;
+ rc.right = rc.left + dxDriveLetterStatusArea;
+ DrawStatusAreaItem(&rc, hdcTemp, StatusTextDrlt);
+
+ // vol label
+ rc.left = rc.right + dxSeparation;
+ rc.right = GraphWidth - dxSeparation;
+ DrawStatusAreaItem(&rc, hdcTemp, StatusTextVoll);
+
+ BitBlt(hdcScr,
+ rcTemp.left,
+ rcTemp.top,
+ rcTemp.right-rcTemp.left+1,
+ rcTemp.bottom-rcTemp.top+1,
+ hdcTemp,
+ 0,
+ 0,
+ SRCCOPY
+ );
+
+ if (hFontOld)
+ {
+ SelectFont(hdcTemp, hFontOld);
+ }
+ DeleteDC(hdcTemp);
+ DeleteBitmap(hbmTemp);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PaintLegend
+//
+// Synopsis: Paint the legend
+//
+// Arguments: [hwnd] -- window to paint to
+// [pps] -- the paint structure returned by BeginPaint
+// [prc] -- the rectangle for the entire frame. Paint at
+// the bottom of it.
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PaintLegend(
+ IN HWND hwnd,
+ IN PAINTSTRUCT* pps,
+ IN PRECT prc
+ )
+{
+ HDC hdcScr = pps->hdc;
+ RECT rc = *prc;
+
+ // draw the legend onto the screen
+
+ rc.top = rc.bottom - g_dyLegend;
+ DrawLegend(hdcScr, &rc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PaintVolumesView
+//
+// Synopsis: Paint the volumes view: Handle WM_PAINT for the volumes view
+//
+// Arguments: standard Windows procedure arguments for WM_PAINT
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PaintVolumesView(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ HDC hdcScr;
+ PAINTSTRUCT ps;
+ HBRUSH hBrush;
+ RECT rc;
+
+ hdcScr = BeginPaint(hwnd, &ps);
+
+ GetClientRect(hwnd, &rc);
+
+ if (g_Toolbar)
+ {
+ //
+ // The toolbar is a control; it paints itself
+ //
+
+ rc.top += g_dyToolbar;
+ }
+
+ if (g_StatusBar)
+ {
+ PaintStatusBar(hwnd, &ps, &rc);
+ rc.bottom -= g_dyStatus;
+ }
+
+ EndPaint(hwnd, &ps);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PaintDisksView
+//
+// Synopsis: Paint the disks view: Handle WM_PAINT for the disks view
+//
+// Arguments: standard Windows procedure arguments for WM_PAINT
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+PaintDisksView(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ HDC hdcScr;
+ PAINTSTRUCT ps;
+ HBRUSH hBrush;
+ RECT rc;
+
+ hdcScr = BeginPaint(hwnd, &ps);
+
+ GetClientRect(hwnd, &rc);
+
+ if (g_Toolbar)
+ {
+ //
+ // The toolbar is a control; it paints itself
+ //
+
+ rc.top += g_dyToolbar;
+ }
+
+ if (g_StatusBar)
+ {
+ PaintStatusBar(hwnd, &ps, &rc);
+ rc.bottom -= g_dyStatus;
+ }
+
+ if (g_Legend)
+ {
+ PaintLegend(hwnd, &ps, &rc);
+ rc.bottom -= g_dyLegend;
+ }
+
+ //
+ // dark line across top of status/legend area, and across bottom of
+ // toolbar.
+ //
+
+ if (g_StatusBar || g_Legend || g_Toolbar)
+ {
+ if (NULL != (hBrush = CreateSolidBrush(GetSysColor(COLOR_BTNTEXT))))
+ {
+ RECT rcT;
+
+ if (g_StatusBar || g_Legend)
+ {
+ rcT = rc;
+ rcT.top = rcT.bottom - g_dyBorder; // the thickness of the line
+ FillRect(hdcScr, &rcT, hBrush);
+ }
+
+ if (g_Toolbar)
+ {
+ rcT = rc;
+ rcT.bottom = rcT.top + g_dyBorder; // the thickness of the line
+ FillRect(hdcScr, &rcT, hBrush);
+ }
+
+ DeleteBrush(hBrush);
+ }
+ }
+
+ EndPaint(hwnd, &ps);
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FrameCreateHandler
+//
+// Synopsis: Handle WM_CREATE for the frame window
+//
+// Arguments: standard Windows procedure arguments for WM_CREATE
+//
+// Returns: standard Windows procedure arguments for WM_CREATE
+//
+// History: 9-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FrameCreateHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ HMENU hMenu;
+
+ //BUGBUG: huh?
+ if (!g_StartedAsIcon)
+ {
+ g_StartedAsIcon = IsIconic(hwnd);
+ }
+
+ g_hmenuFrame = GetMenu(hwnd);
+
+ g_hwndList = CreateWindow(
+ TEXT("listbox"),
+ NULL,
+ WS_CHILD
+ | WS_VSCROLL
+ | LBS_NOTIFY
+ | LBS_NOINTEGRALHEIGHT
+ | LBS_OWNERDRAWFIXED,
+ 0, 0, 0, 0,
+ hwnd,
+ (HMENU)ID_LISTBOX,
+ g_hInstance,
+ NULL
+ );
+
+ if (NULL == g_hwndList)
+ {
+ daDebugOut((DEB_ERROR,
+ "CreateWindow for listbox failed, error = 0x%x\n",
+ GetLastError()
+ ));
+
+ return -1; // fail window creation & exit Disk Admin
+ }
+
+ // subclass the listbox so we can handle keyboard
+ // input our way.
+
+ SubclassListBox(g_hwndList);
+
+ //
+ // Create the listview (volumes view)
+
+ g_hwndLV = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ WC_LISTVIEW,
+ NULL,
+ WS_CHILD
+ | WS_BORDER //BUGBUG: needed?
+ | LVS_REPORT
+ | LVS_SINGLESEL
+ | LVS_SHOWSELALWAYS
+ | LVS_SHAREIMAGELISTS
+ ,
+ 0, 0, 0, 0,
+ hwnd,
+ (HMENU)ID_LISTVIEW,
+ g_hInstance,
+ NULL
+ );
+
+ if (NULL == g_hwndLV)
+ {
+ daDebugOut((DEB_ERROR,
+ "CreateWindow for listview failed, error = 0x%x\n",
+ GetLastError()
+ ));
+
+ return -1; // fail window creation & exit Disk Admin
+ }
+
+ //
+ // Create the toolbar
+ //
+
+ CreateDAToolbar(hwnd);
+
+ //
+ // If we are not running the LanmanNt version of
+ // Windisk, remove the Fault-Tolerance menu item.
+ //
+ if (!g_IsLanmanNt && (hMenu = GetMenu(hwnd)) != NULL)
+ {
+ DeleteMenu(hMenu, FT_MENU_INDEX, MF_BYPOSITION);
+ DrawMenuBar(hwnd);
+ }
+
+ //
+ // initialize the status bar strings
+ //
+
+ StatusTextDrlt[0]
+ = StatusTextStat[0]
+ = StatusTextSize[0]
+ = StatusTextType[0]
+ = StatusTextVoll[0]
+ = L'\0';
+
+ return 0; // window was created fine
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FrameResizeHandler
+//
+// Synopsis: Handle WM_SIZE for the frame window
+//
+// Arguments: standard Windows procedure arguments for WM_SIZE
+//
+// Returns: standard Windows procedure arguments for WM_SIZE
+//
+// History: 9-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FrameResizeHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ RECT rc, rcT;
+
+ GetClientRect(hwnd, &rc);
+
+ DWORD newGraphWidth = rc.right - rc.left;
+
+ CalculateLegendHeight(newGraphWidth);
+
+#if DBG == 1
+ if (!BothViews)
+ {
+#endif // DBG == 1
+
+ //
+ // resize the listbox (disks view)
+ //
+
+ rcT = rc;
+ rcT.top = rc.top
+ + (g_Toolbar ? g_dyToolbar : 0)
+ + (g_Toolbar ? g_dyBorder : 0)
+ // if tool bar, space for a line
+ ;
+ rcT.bottom = rc.bottom
+ - (g_StatusBar ? g_dyStatus : 0)
+ - (g_Legend ? g_dyLegend : 0)
+ - ( (g_StatusBar || g_Legend) ? g_dyBorder : 0)
+ // if stat bar or legend, space for a line
+ ;
+
+ MoveWindow(
+ g_hwndList,
+ rcT.left,
+ rcT.top,
+ rcT.right - rcT.left,
+ rcT.bottom - rcT.top,
+ TRUE);
+
+ //
+ // resize the listview
+ //
+
+ rcT = rc;
+ rcT.top = rc.top
+ + (g_Toolbar ? g_dyToolbar : 0)
+ ;
+ rcT.bottom = rc.bottom
+ - (g_StatusBar ? g_dyStatus : 0)
+ //note: no legend in volumes view
+ ;
+
+ MoveWindow(
+ g_hwndLV,
+ rcT.left,
+ rcT.top,
+ rcT.right - rcT.left,
+ rcT.bottom - rcT.top,
+ TRUE);
+
+#if DBG == 1
+ }
+#endif // DBG == 1
+
+#if DBG == 1
+ if (BothViews)
+ {
+ // put both disks view and volumes view on same screen
+
+ rcT = rc;
+ rcT.top = rc.top
+ + (g_Toolbar ? g_dyToolbar : 0)
+ + (g_Toolbar ? g_dyBorder : 0)
+ // if tool bar, space for a line
+ ;
+ rcT.bottom = rc.bottom
+ - (g_StatusBar ? g_dyStatus : 0)
+ - (g_Legend ? g_dyLegend : 0)
+ - ( (g_StatusBar || g_Legend) ? g_dyBorder : 0)
+ // if stat bar or legend, space for a line
+ ;
+
+ RECT rcT2;
+
+ rcT2 = rcT;
+ rcT2.bottom -= (rcT.bottom - rcT.top) / 2;
+
+ MoveWindow(
+ g_hwndList,
+ rcT2.left,
+ rcT2.top,
+ rcT2.right - rcT2.left,
+ rcT2.bottom - rcT2.top,
+ TRUE);
+
+ rcT2.top = rcT2.bottom;
+ rcT2.bottom = rcT.bottom;
+
+ MoveWindow(
+ g_hwndLV,
+ rcT2.left,
+ rcT2.top,
+ rcT2.right - rcT2.left,
+ rcT2.bottom - rcT2.top,
+ TRUE);
+ }
+#endif // DBG == 1
+
+ //
+ // resize the toolbar
+ //
+
+ if (g_Toolbar)
+ {
+ // forward the message to the toolbar: it resizes itself
+ SendMessage(g_hwndToolbar, WM_SIZE, wParam, lParam);
+ }
+
+ //
+ // Invalidate status/legend area so that the clipping
+ // rectangle is right for redraws. Also invalidate the line, if it
+ // exists, below the toolbar.
+ //
+
+ // first, do the status/legend
+
+ rcT = rc;
+ rcT.top = rcT.bottom;
+
+ if (g_StatusBar)
+ {
+ rcT.top -= g_dyStatus;
+ }
+
+ if ( g_Legend && (g_WhichView == VIEW_DISKS) )
+ {
+ rcT.top -= g_dyLegend;
+ }
+
+#if DBG == 1
+ if (BothViews)
+ {
+ if ( g_Legend && (g_WhichView != VIEW_DISKS) )
+ {
+ rcT.top -= g_dyLegend;
+ }
+ }
+#endif // DBG == 1
+
+ if (rcT.top != rcT.bottom)
+ {
+ // there was either a status or a legend
+
+ rcT.top -= g_dyBorder; // adjust for the border line
+
+ InvalidateRect(hwnd, &rcT, FALSE); // get WM_PAINT for status/legend
+ }
+
+ // now, do the line under the toolbar
+
+ if (g_Toolbar && (g_WhichView == VIEW_DISKS))
+ {
+ rcT = rc;
+ rcT.top += g_dyToolbar;
+ rcT.bottom = rcT.top + g_dyBorder;
+ InvalidateRect(hwnd, &rcT, FALSE); // get WM_PAINT for toolbar line
+ }
+
+ //
+ // Recalculate the window width, and re-allocate off-screen bitmaps
+ //
+
+ if (GraphWidth != newGraphWidth)
+ {
+ GraphWidth = newGraphWidth;
+
+ BarWidth = GraphWidth - BarWidthMargin;
+
+ // create a memory DC for drawing the bar off-screen,
+ // and the correct bitmap
+
+ PDISKSTATE diskState;
+ PCDROM_DESCRIPTOR cdrom;
+ ULONG i;
+
+ HDC hDCFrame = GetDC(g_hwndFrame);
+ HDC hDCMem;
+
+ for (i=0; i<DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+ if (NULL != diskState->hDCMem)
+ {
+ DeleteDC(diskState->hDCMem);
+ }
+ if (NULL != diskState->hbmMem)
+ {
+ DeleteBitmap(diskState->hbmMem);
+ }
+
+ diskState->hDCMem = hDCMem = CreateCompatibleDC(hDCFrame);
+ diskState->hbmMem = CreateCompatibleBitmap(
+ hDCFrame,
+ GraphWidth,
+ GraphHeight);
+
+ SelectBitmap(hDCMem, diskState->hbmMem);
+
+ //
+ // since the bitmap/DC has changed, we need to redraw it
+ //
+
+ DrawDiskBar(diskState);
+ }
+
+ for (i=0; i<CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+
+ if (NULL != cdrom->hDCMem)
+ {
+ DeleteDC(cdrom->hDCMem);
+ }
+ if (NULL != cdrom->hbmMem)
+ {
+ DeleteBitmap(cdrom->hbmMem);
+ }
+
+ cdrom->hDCMem = hDCMem = CreateCompatibleDC(hDCFrame);
+ cdrom->hbmMem = CreateCompatibleBitmap(
+ hDCFrame,
+ GraphWidth,
+ GraphHeight);
+
+ SelectBitmap(hDCMem, cdrom->hbmMem);
+
+ //
+ // since the bitmap/DC has changed, we need to redraw it
+ //
+
+ DrawCdRomBar(i);
+ }
+ }
+
+ return (LRESULT)0; // message processed
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FramePaintHandler
+//
+// Synopsis: Handle WM_PAINT for the frame window
+//
+// Arguments: standard Windows procedure arguments for WM_PAINT
+//
+// Returns: standard Windows procedure arguments for WM_PAINT
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FramePaintHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ if (IsIconic(hwnd))
+ {
+ return 0; // no painting necessary if we're iconic
+ }
+
+ if ((NULL != g_InitDlg) && g_StartedAsIcon)
+ {
+ return 0; // there is an initialization dialog still visible
+ }
+
+#if DBG == 1
+
+ if (BothViews)
+ {
+ PaintDisksView(hwnd, wParam, lParam);
+ return 0;
+ }
+
+#endif // DBG == 1
+
+ switch (g_WhichView)
+ {
+ case VIEW_VOLUMES:
+
+ PaintVolumesView(hwnd, wParam, lParam);
+ break;
+
+ case VIEW_DISKS:
+
+ PaintDisksView(hwnd, wParam, lParam);
+ break;
+
+ default:
+
+ FDASSERT(0);
+ }
+
+ if (NULL != g_InitDlg)
+ {
+ if (g_InitDlgComplete)
+ {
+ PostMessage(g_InitDlg, WM_STARTUP_END, 0, 0);
+ g_InitDlg = NULL;
+ }
+
+ if (g_oneTime)
+ {
+ if (!g_StartedAsIcon)
+ {
+ SetForegroundWindow(hwnd);
+ }
+ g_oneTime = FALSE;
+ }
+ }
+
+ return 0;
+}
+
+VOID
+DoEject(
+ IN HWND hwnd
+ )
+
+/*++
+
+Routine Description:
+
+ This routine ejects the selected disk.
+
+Arguments:
+
+ hwnd - Supplies a handle to the frame window.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ WCHAR deviceName[100];
+ UINT oldErrorMode;
+
+ if (0 == (SelectionCount + CdRomSelectionCount)) {
+ return; // nothing selected
+ }
+
+ deviceName[0] = '\\';
+ deviceName[1] = '\\';
+ deviceName[2] = '.';
+ deviceName[3] = '\\';
+ deviceName[5] = ':';
+ deviceName[6] = 0;
+
+ oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
+
+ if (CdRomSelected) {
+
+ PCDROM_DESCRIPTOR cdrom;
+ ULONG i;
+ HANDLE handle;
+ DWORD bytes;
+
+ for (i = 0; i < CdRomCount; i++) {
+ cdrom = CdRomFindDevice(i);
+ if (cdrom->Selected) {
+
+ deviceName[4] = cdrom->DriveLetter;
+ handle = CreateFile(deviceName, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ 0, OPEN_EXISTING, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE) {
+ SetErrorMode(oldErrorMode);
+ return;
+ }
+
+ DeviceIoControl(handle, IOCTL_DISK_EJECT_MEDIA, 0, 0, 0, 0,
+ &bytes, 0);
+
+ CloseHandle(handle);
+ break;
+ }
+ }
+
+ } else if (SelectionCount == 1) {
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(regionDescriptor);
+ HANDLE handle;
+ DWORD bytes;
+ PREVENT_MEDIA_REMOVAL pmr;
+
+ if (regionDescriptor->PersistentData) {
+ deviceName[4] = regionDescriptor->PersistentData->DriveLetter;
+ } else {
+ wsprintf(deviceName, L"\\\\.\\PhysicalDrive%d",
+ regionDescriptor->Disk);
+ }
+
+ handle = CreateFile(deviceName, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
+ OPEN_EXISTING, 0, INVALID_HANDLE_VALUE);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+
+ ErrorDialog(GetLastError());
+ SetErrorMode(oldErrorMode);
+ return;
+ }
+
+
+ if (!DeviceIoControl(handle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &bytes,
+ 0) ||
+ !DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0,
+ &bytes, 0)) {
+
+ ErrorDialog(GetLastError());
+ CloseHandle(handle);
+ SetErrorMode(oldErrorMode);
+ return;
+ }
+
+
+ pmr.PreventMediaRemoval = FALSE;
+ if (!DeviceIoControl(handle, IOCTL_DISK_MEDIA_REMOVAL,
+ &pmr, sizeof(pmr), 0, 0, &bytes, 0) ||
+ !DeviceIoControl(handle, IOCTL_DISK_EJECT_MEDIA, 0, 0, 0, 0,
+ &bytes, 0)) {
+
+ ErrorDialog(GetLastError());
+ }
+
+ CloseHandle(handle);
+ }
+
+ DoRefresh();
+
+ SetErrorMode(oldErrorMode);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FrameCommandHandler
+//
+// Synopsis: Handle WM_COMMAND messages for the frame window
+//
+// Arguments: standard Windows procedure arguments for WM_COMMAND
+//
+// Returns: standard Windows procedure arguments for WM_COMMAND
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FrameCommandHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ DWORD helpFlag;
+ WORD wId = LOWORD(wParam);
+
+ switch (wId)
+ {
+
+//
+// Volume menu
+//
+
+ case IDM_VOL_FORMAT:
+
+ DoFormat(hwnd, TRUE);
+ break;
+
+ case IDM_VOL_EJECT:
+
+ DoEject(hwnd);
+ break;
+
+ case IDM_VOL_LETTER:
+
+ if (LoadFmifs())
+ {
+ DoSetDriveLetter();
+ }
+ break;
+
+#if defined( DBLSPACE_ENABLED )
+ case IDM_VOL_DBLSPACE:
+ if (LoadFmifs())
+ {
+ DblSpace(hwnd);
+ }
+ break;
+
+ case IDM_VOL_AUTOMOUNT:
+ {
+ if (LoadFmifs())
+ {
+ DoubleSpaceAutomount = (DoubleSpaceAutomount ? FALSE : TRUE);
+ DiskRegistryDblSpaceRemovable(DoubleSpaceAutomount);
+ CheckMenuItem(GetMenu(hwnd),
+ IDM_VOL_AUTOMOUNT,
+ DoubleSpaceAutomount ? MF_CHECKED : MF_UNCHECKED);
+ }
+ break;
+ }
+#endif // DBLSPACE_ENABLED
+
+ case IDM_PARTITIONCOMMIT:
+ CommitAllChanges();
+ EnableMenuItem(GetMenu(g_hwndFrame), IDM_CONFIGSAVE, MF_ENABLED);
+ AdjustMenuAndStatus();
+ break;
+
+ case IDM_VOL_PROPERTIES:
+ case IDM_PROPERTIES:
+
+ WaitForSingleObject(DisplayMutex, INFINITE);
+ RefreshAllowed = 1;
+ ReleaseMutex(DisplayMutex);
+ PropSheet();
+ break;
+
+ case IDM_NOVALIDOPERATION:
+
+ // nothing to do: it's not a valid operation!
+
+ break;
+
+ case IDM_QUIT:
+
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ break;
+
+//
+// Partition menu
+//
+
+ case IDM_PARTITIONCREATE:
+
+ DoCreate(REGION_PRIMARY);
+ break;
+
+ case IDM_PARTITIONCREATEEX:
+
+ DoCreate(REGION_EXTENDED);
+ break;
+
+ case IDM_PARTITIONDELETE:
+
+ switch (FtSelectionType)
+ {
+ case Mirror:
+
+ DoBreakAndDeleteMirror();
+ break;
+
+ case Stripe:
+ case StripeWithParity:
+
+ DoDeleteStripe();
+ break;
+
+ case VolumeSet:
+
+ DoDeleteVolumeSet();
+ break;
+
+ default:
+
+ DoDelete();
+ break;
+ }
+
+ break;
+
+#if i386
+
+ case IDM_PARTITIONACTIVE:
+
+ DoMakeActive();
+ break;
+
+#else // i386
+
+ case IDM_SECURESYSTEM:
+
+ DoProtectSystemPartition();
+ break;
+
+#endif // i386
+
+ case IDM_CONFIGMIGRATE:
+
+ if (DoMigratePreviousFtConfig())
+ {
+ SetCursor(g_hCurWait);
+
+ //
+ // Determine if the FT driver must be enabled.
+ //
+ Sleep(2000);
+
+ if (DiskRegistryRequiresFt() == TRUE)
+ {
+ DiskRegistryEnableFt();
+ }
+ else
+ {
+ DiskRegistryDisableFt();
+ }
+
+ Sleep(4000);
+ SetCursor(g_hCurNormal);
+ FdShutdownTheSystem();
+ }
+ break;
+
+ case IDM_CONFIGSAVE:
+
+ DoSaveFtConfig();
+ break;
+
+ case IDM_CONFIGRESTORE:
+
+ if (DoRestoreFtConfig())
+ {
+ //
+ // Determine if the FT driver must be enabled.
+ //
+ if (DiskRegistryRequiresFt() == TRUE)
+ {
+ DiskRegistryEnableFt();
+ }
+ else
+ {
+ DiskRegistryDisableFt();
+ }
+
+ SetCursor(g_hCurWait);
+ Sleep(5000);
+ SetCursor(g_hCurNormal);
+ FdShutdownTheSystem();
+ }
+ break;
+
+//
+// Fault tolerance menu (Advanced Server only)
+//
+
+ case IDM_FTESTABLISHMIRROR:
+
+ DoEstablishMirror();
+ break;
+
+ case IDM_FTBREAKMIRROR:
+
+ DoBreakMirror();
+ break;
+
+ case IDM_FTCREATESTRIPE:
+
+ DoCreateStripe(FALSE);
+ break;
+
+ case IDM_FTCREATEPSTRIPE:
+
+ DoCreateStripe(TRUE);
+ break;
+
+ case IDM_FTCREATEVOLUMESET:
+
+ DoCreateVolumeSet();
+ break;
+
+ case IDM_FTEXTENDVOLUMESET:
+
+ DoExtendVolumeSet();
+ break;
+
+ case IDM_FTRECOVERSTRIPE: // BUGBUG: allow mirror recovery also?
+
+ DoRecoverStripe();
+ break;
+
+//
+// View Menu
+//
+
+ case IDM_VIEWVOLUMES:
+
+ if (g_WhichView != VIEW_VOLUMES)
+ {
+ g_WhichView = VIEW_VOLUMES;
+ ChangeView();
+ }
+ break;
+
+ case IDM_VIEWDISKS:
+
+ if (g_WhichView != VIEW_DISKS)
+ {
+ g_WhichView = VIEW_DISKS;
+ ChangeView();
+ }
+ break;
+
+ case IDM_VIEW_REFRESH:
+
+ DoRefresh();
+ break;
+
+//
+// Options menu
+//
+
+ case IDM_OPTIONSTOOLBAR:
+
+ g_Toolbar = !g_Toolbar;
+ ShowWindow(g_hwndToolbar, (g_Toolbar ? SW_SHOW : SW_HIDE));
+ AdjustOptionsMenu();
+ break;
+
+ case IDM_OPTIONSSTATUS:
+
+ g_StatusBar = !g_StatusBar;
+ AdjustOptionsMenu();
+ break;
+
+ case IDM_OPTIONSLEGEND:
+
+ g_Legend = !g_Legend;
+ AdjustOptionsMenu();
+ break;
+
+ case IDM_OPTIONSCOLORS:
+
+ DoColorsDialog(hwnd);
+ break;
+
+ case IDM_OPTIONSDISPLAY:
+
+ DoRegionDisplayDialog(hwnd);
+ break;
+
+ case IDM_OPTIONSDISK:
+
+ DoDiskOptionsDialog(hwnd);
+ break;
+
+ case IDM_OPTIONSCUSTTOOLBAR:
+
+ Toolbar_Customize(g_hwndToolbar);
+ break;
+
+//
+// Help menu
+//
+
+ case IDM_HELPCONTENTS:
+
+ helpFlag = HELP_FINDER;
+ goto CallWinHelp;
+
+ case IDM_HELPSEARCH:
+
+ helpFlag = HELP_PARTIALKEY;
+ goto CallWinHelp;
+
+ case IDM_HELPHELP:
+
+ helpFlag = HELP_HELPONHELP;
+ goto CallWinHelp;
+
+ case IDM_HELPABOUT:
+ {
+ TCHAR title[100];
+
+ LoadString(g_hInstance, IDS_APPNAME, title, ARRAYLEN(title));
+ ShellAbout(
+ hwnd,
+ title,
+ NULL,
+ (HICON)GetClassLong(hwnd, GCL_HICON)
+ );
+ break;
+ }
+
+#if DBG == 1
+
+ case IDM_DEBUGALLOWDELETES:
+
+ AllowAllDeletes = !AllowAllDeletes;
+ CheckMenuItem(GetMenu(hwnd),
+ IDM_DEBUGALLOWDELETES,
+ AllowAllDeletes ? MF_CHECKED : MF_UNCHECKED
+ );
+ break;
+
+ case IDM_DEBUGLOG:
+
+ LOG_ALL();
+ break;
+
+ case IDM_RAID:
+
+ MessageBox(hwnd,
+ L"To file a bug against the Disk Administrator, use:\n"
+ L"\n"
+ L"\tServer:\tntraid\n"
+ L"\tDatabase name:\t\tntbug\n"
+ L"\tComponent:\t\tADMIN\n"
+ L"\tSub-Comp:\t\tDISK_MGR\n"
+ L"\tType:\t\t\tNT2 NOW\n",
+
+ L"RAID Information",
+ MB_ICONINFORMATION | MB_OK);
+ //
+ // OR, Component: SYSMAN, Sub-Comp: DISK MGMT
+ //
+ break;
+
+#endif // DBG == 1
+
+
+//
+// Listbox event
+//
+
+ case ID_LISTBOX:
+
+ switch (HIWORD(wParam))
+ {
+ case LBN_SELCHANGE:
+ {
+ POINT pt;
+ DWORD pos = GetMessagePos();
+
+ pt.x = LOWORD(pos);
+ pt.y = HIWORD(pos);
+ MouseSelection(
+ GetKeyState(VK_CONTROL) & ~1, // strip toggle bit
+ &pt
+ );
+ break;
+ }
+ default:
+ DefWindowProc(hwnd, WM_COMMAND, wParam, lParam);
+ break;
+ }
+ break;
+
+//
+// Default... extension menu items
+//
+
+ default:
+ {
+
+#ifdef WINDISK_EXTENSIONS
+
+ if (MenuItems.IsExtensionId(wId))
+ {
+ daDebugOut((DEB_ITRACE, "Extension menu item %d\n", wId));
+
+ //
+ // BUGBUG: need to invoke the extension menu ONLY if there
+ // is a single selection. Then, need to pass it a drive name
+ //
+
+ PREGION_DESCRIPTOR regionDescriptor = &SELECTED_REGION(0);
+ FDASSERT(regionDescriptor);
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
+ FDASSERT(regionData);
+
+ WCHAR driveName[3];
+ driveName[0] = regionData->DriveLetter;
+ driveName[1] = L':';
+ driveName[2] = L'\0';
+
+ MenuItemType* pMenu = MenuItems.LookupMenuItem(wId);
+
+ // BUGBUG: try/except around extension code. pass hwnd?
+ HRESULT hr = pMenu->pMenuDispatch->MenuDispatch(
+ hwnd,
+ driveName,
+ pMenu->iIndex);
+
+ switch (hr)
+ {
+ case DA_E_VOLUMEINFOCHANGED:
+ RefreshVolumeData();
+ break;
+ }
+ }
+ else if (ContextMenuItems.IsExtensionId(wId))
+ {
+ daDebugOut((DEB_ITRACE,
+ "Context menu extension menu item %d\n",
+ wId));
+
+ WCHAR driveName[256];
+
+ wsprintf(driveName, L"\\Device\\Harddisk%d", LBIndexToDiskNumber(g_MouseLBIndex));
+
+ MenuItemType* pMenu = ContextMenuItems.LookupMenuItem(wId);
+
+ // BUGBUG: try/except around extension code. pass hwnd?
+ HRESULT hr = pMenu->pMenuDispatch->MenuDispatch(
+ hwnd,
+ driveName,
+ pMenu->iIndex);
+
+ switch (hr)
+ {
+ case DA_E_VOLUMEINFOCHANGED:
+ RefreshVolumeData();
+ break;
+ }
+ }
+ else
+ {
+#endif // WINDISK_EXTENSIONS
+
+ return DefWindowProc(hwnd, WM_COMMAND, wParam, lParam);
+
+#ifdef WINDISK_EXTENSIONS
+ }
+#endif // WINDISK_EXTENSIONS
+
+ break;
+ }
+
+ } // end of main WM_COMMAND switch
+
+ return 0;
+
+CallWinHelp:
+
+ if (!WinHelp(hwnd, g_HelpFile, helpFlag, (DWORD)""))
+ {
+ WarningDialog(MSG_HELP_ERROR);
+ }
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FrameCloseHandler
+//
+// Synopsis: Handle WM_CLOSE messages for the frame window.
+//
+// Arguments: standard Windows procedure arguments for WM_CLOSE
+//
+// Returns: standard Windows procedure arguments for WM_CLOSE
+//
+// History: 10-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FrameCloseHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ UINT ret = CommitAllChanges();
+
+ if (0 != ret)
+ {
+ if (1 != ret) // if we haven't written the profile, then do it
+ {
+ WriteProfile();
+ }
+ DestroyWindow(hwnd);
+ }
+
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FrameDestroyHandler
+//
+// Synopsis: Handle WM_DESTROY messages for the frame window. Clean up
+// memory, etc.
+//
+// Arguments: standard Windows procedure arguments for WM_DESTROY
+//
+// Returns: standard Windows procedure arguments for WM_DESTROY
+//
+// History: 22-Oct-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LRESULT
+FrameDestroyHandler(
+ IN HWND hwnd,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ )
+{
+ // BUGBUG clean up here -- release dc's, free DiskStates, etc.
+
+#ifdef WINDISK_EXTENSIONS
+ DeactivateExtensions();
+#endif // WINDISK_EXTENSIONS
+
+ //
+ // Other cleanup
+ //
+
+ WinHelp(hwnd, g_HelpFile, HELP_QUIT, 0);
+
+ PostQuitMessage(0);
+
+ return 0; // message processed
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DeletionIsAllowed
+//
+// Synopsis:
+//
+// This routine makes sure deletion of the partition is allowed. We do
+// not allow the user to delete the Windows NT boot partition or the
+// active partition on disk 0 (x86 only).
+//
+// Note that this routine is also used to determine whether an existing
+// single-partition volume can be extended into a volume set, since the
+// criteria are the same.
+//
+// Arguments: [RegionDescriptor] -- points to region descriptor for the
+// region which the user would like to delete.
+//
+// Returns: NO_ERROR if deletion is allowed; error number for message
+// to display if not.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+DWORD
+DeletionIsAllowed(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ )
+{
+ ULONG ec;
+ PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
+
+ FDASSERT(!IsExtended(RegionDescriptor->SysID)); // can't be extended partition
+ FDASSERT(RegionDescriptor->SysID != PARTITION_ENTRY_UNUSED); // can't be free space
+
+#if DBG == 1
+ if (AllowAllDeletes)
+ {
+ return NO_ERROR;
+ }
+#endif // DBG == 1
+
+ // if this is not an original region, deletion is allowed.
+
+ if (0 == RegionDescriptor->OriginalPartitionNumber)
+ {
+ return NO_ERROR;
+ }
+
+ // if there is no persistent data for this region, allow deletion.
+
+ if (regionData == NULL)
+ {
+ return NO_ERROR;
+ }
+
+ ec = NO_ERROR;
+ if (BootDiskNumber != (ULONG)-1)
+ {
+ // If the disk number and original partition number of this
+ // region match the recorded disk number and partition number
+ // of the boot partition, don't allow deletion.
+ //
+ if (RegionDescriptor->Disk == BootDiskNumber
+ && RegionDescriptor->OriginalPartitionNumber == BootPartitionNumber)
+ {
+ ec = MSG_CANT_DELETE_WINNT;
+ }
+ }
+
+ if (ec == NO_ERROR)
+ {
+ if (regionData->DriveLetter == BootDir)
+ {
+ ec = MSG_CANT_DELETE_ACTIVE0;
+ }
+ }
+
+ return ec;
+}
+
+
+VOID
+CheckForBootNumberChange(
+ IN ULONG Disk
+ )
+
+/*++
+
+Routine Description:
+
+ Determine if the disk that has just changed is the boot disk.
+ If so, determine if the boot partition number changed. If it
+ did, warn the user.
+
+Arguments:
+
+ RegionDescriptor - the region that has just changed.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ULONG newPart;
+ TCHAR oldNumberString[8],
+ newNumberString[8];
+ DWORD msgCode;
+
+ if (Disk == BootDiskNumber)
+ {
+ // Pass a pointer to Disk even though this is just to get the
+ // old partition number back.
+
+ if (BootPartitionNumberChanged(&Disk, &newPart))
+ {
+#if i386
+ msgCode = MSG_CHANGED_BOOT_PARTITION_X86;
+#else
+ msgCode = MSG_CHANGED_BOOT_PARTITION_ARC;
+#endif
+ wsprintf(oldNumberString, L"%d", Disk);
+ wsprintf(newNumberString, L"%d", newPart);
+ InfoDialog(msgCode, oldNumberString, newNumberString);
+ }
+ }
+}
+
+
+
+BOOLEAN
+BootPartitionNumberChanged(
+ PULONG OldNumber,
+ PULONG NewNumber
+ )
+
+/*++
+
+Routine Description
+
+ This function determines whether the partition number of
+ the boot partition has changed during this invocation of
+ Windisk. With dynamic partitioning enabled, the work of
+ this routine increases. This routine must guess what the
+ partition numbers will be when the system is rebooted to
+ determine if the partition number for the boot partition
+ has changed. It does this via the following algorithm:
+
+ 1. Count all primary partitions - These get numbers first
+ starting from 1.
+
+ 2. Count all logical drives - These get numbers second starting
+ from the count of primary partitions plus 1.
+
+ The partition numbers located in the region structures cannot
+ be assumed to be valid. This work must be done from the
+ region array located in the disk state structure for the
+ disk.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ TRUE if the boot partition's partition number has changed.
+
+--*/
+
+{
+ PDISKSTATE bootDisk;
+ PREGION_DESCRIPTOR regionDescriptor,
+ bootDescriptor = NULL;
+ ULONG i,
+ partitionNumber = 0;
+
+ if (BootDiskNumber == (ULONG)(-1) || BootDiskNumber > DiskCount)
+ {
+ // Can't tell--assume it hasn't.
+
+ return FALSE;
+ }
+
+ if (!ChangeCommittedOnDisk(BootDiskNumber))
+ {
+ // disk wasn't changed - no possibility for a problem.
+
+ return FALSE;
+ }
+
+ bootDisk = DiskArray[BootDiskNumber];
+
+ // Find the region descriptor for the boot partition
+
+ for (i = 0; i < bootDisk->RegionCount; i++)
+ {
+ regionDescriptor = &bootDisk->RegionArray[i];
+ if (regionDescriptor->OriginalPartitionNumber == BootPartitionNumber)
+ {
+ bootDescriptor = regionDescriptor;
+ break;
+ }
+ }
+
+ if (!bootDescriptor)
+ {
+ // Can't find boot partition - assume no change
+
+ return FALSE;
+ }
+
+ // No go through the region descriptors and count the partition
+ // numbers as they will be counted during system boot.
+ //
+ // If the boot region is located determine if the partition
+ // number changed.
+
+ for (i = 0; i < bootDisk->RegionCount; i++)
+ {
+ regionDescriptor = &bootDisk->RegionArray[i];
+ if ( regionDescriptor->RegionType == REGION_PRIMARY
+ && !IsExtended(regionDescriptor->SysID)
+ && (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED))
+ {
+ partitionNumber++;
+
+ if (regionDescriptor == bootDescriptor)
+ {
+ if (partitionNumber != regionDescriptor->OriginalPartitionNumber)
+ {
+ *OldNumber = regionDescriptor->OriginalPartitionNumber;
+ *NewNumber = partitionNumber;
+ return TRUE;
+ }
+ else
+ {
+ // Numbers match, no problem.
+
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ // Check the logical drives as well.
+
+ for (i = 0; i < bootDisk->RegionCount; i++)
+ {
+ regionDescriptor = &bootDisk->RegionArray[i];
+
+ if (regionDescriptor->RegionType == REGION_LOGICAL)
+ {
+ partitionNumber++;
+
+ if (regionDescriptor == bootDescriptor)
+ {
+ if (partitionNumber != regionDescriptor->OriginalPartitionNumber)
+ {
+ *OldNumber = regionDescriptor->OriginalPartitionNumber;
+ *NewNumber = partitionNumber;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: AssignDriveLetter
+//
+// Synopsis: Determine the next available drive letter. If no drive
+// letters are available, optionally warn the user and allow
+// him to cancel the operation.
+//
+// Arguments:
+//
+// [WarnIfNoLetter] - whether to warn the user if no drive letters are
+// available and allow him to cancel the operation.
+//
+// [StringId] - resource containing the name of the object being created
+// that will need a drive letter (ie, partition, logical drive, stripe
+// set, volume set).
+//
+// [DriveLetter] - receives the drive letter to assign, or
+// NO_DRIVE_LETTER_YET
+// if no more left.
+//
+// Returns: If there were no more drive letters, returns TRUE if the
+// user wants to create anyway, FALSE if he canceled. If there
+// were drive letters available, the return value is undefined.
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+AssignDriveLetter(
+ IN BOOL WarnIfNoLetter,
+ IN DWORD StringId,
+ OUT PWCHAR DriveLetter
+ )
+{
+ WCHAR driveLetter;
+ TCHAR name[256];
+
+ driveLetter = GetAvailableDriveLetter();
+ if (WarnIfNoLetter && L'\0' == driveLetter)
+ {
+ LoadString(g_hInstance, StringId, name, ARRAYLEN(name));
+ if (IDYES != ConfirmationDialog(
+ MSG_NO_AVAIL_LETTER,
+ MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2,
+ name))
+ {
+ return FALSE;
+ }
+ }
+ if (L'\0' == driveLetter)
+ {
+ driveLetter = NO_DRIVE_LETTER_YET;
+ }
+ *DriveLetter = driveLetter;
+ return TRUE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetFTObjectBackPointers
+//
+// Synopsis: Traverse the regions, setting back-pointers from FT
+// objects to the region they correspond to. This needs to
+// be done at initialization time as well as after region
+// operations.
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 23-Sep-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+SetFTObjectBackPointers(
+ VOID
+ )
+{
+ //
+ // First, clear all the back pointers using the chain of FT sets
+ //
+
+ PFT_OBJECT ftObject;
+ PFT_OBJECT_SET ftSet;
+
+ for (ftSet = FtObjectList; NULL != ftSet; ftSet = ftSet->Next)
+ {
+ for (ftObject = ftSet->Members; NULL != ftObject; ftObject = ftObject->Next)
+ {
+ ftObject->Region = NULL;
+ }
+ }
+
+ //
+ // Now, iterate over all regions. For regions which are members of FT
+ // sets (and hence have a non-NULL FtObjectList member in their persistent
+ // region data), set their FT_OBJECT region backpointer
+ //
+
+ DWORD diskNum;
+ DWORD regionNum;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PDISKSTATE diskState;
+
+ for (diskNum=0; diskNum<DiskCount; diskNum++)
+ {
+ diskState = DiskArray[diskNum];
+
+ for (regionNum=0; regionNum<diskState->RegionCount; regionNum++)
+ {
+ regionDescriptor = &diskState->RegionArray[regionNum];
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+
+ if (NULL != ftObject)
+ {
+ ftObject->Region = regionDescriptor;
+ }
+ }
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DeterminePartitioningState
+//
+// Synopsis:
+//
+// This routine determines the disk's partitioning state (ie, what types
+// of partitions exist and may be created), filling out a DISKSTATE
+// structure with the info. It also allocates the array for the
+// left/right position pairs for each region's on-screen square.
+//
+// Arguments: [DiskState] -- the CreateXXX and ExistXXX fields will be
+// filled in for the disk in the Disk field
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DeterminePartitioningState(
+ IN OUT PDISKSTATE DiskState
+ )
+{
+ DWORD i;
+
+ //
+ // If there's an existing region array there, free it.
+ //
+
+ if (DiskState->RegionArray)
+ {
+ FreeRegionArray(DiskState->RegionArray, DiskState->RegionCount);
+ }
+
+ // get the region array for the disk in question
+
+ GetAllDiskRegions( DiskState->Disk,
+ &DiskState->RegionArray,
+ &DiskState->RegionCount
+ );
+
+ // Allocate the array for the left/right coords for the graph.
+ // This may overallocate by one square (for extended partition).
+
+ DiskState->LeftRight = (PLEFTRIGHT)Realloc( DiskState->LeftRight,
+ DiskState->RegionCount * sizeof(LEFTRIGHT)
+ );
+
+ DiskState->Selected = (PBOOLEAN)Realloc( DiskState->Selected,
+ DiskState->RegionCount * sizeof(BOOLEAN)
+ );
+
+ for (i=0; i<DiskState->RegionCount; i++)
+ {
+ DiskState->Selected[i] = FALSE;
+ }
+
+ // figure out whether various creations are allowed
+
+ IsAnyCreationAllowed( DiskState->Disk,
+ TRUE,
+ &DiskState->CreateAny,
+ &DiskState->CreatePrimary,
+ &DiskState->CreateExtended,
+ &DiskState->CreateLogical
+ );
+
+ // figure out whether various partition types exist
+
+ DoesAnyPartitionExist( DiskState->Disk,
+ &DiskState->ExistAny,
+ &DiskState->ExistPrimary,
+ &DiskState->ExistExtended,
+ &DiskState->ExistLogical
+ );
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetLargestDiskSize
+//
+// Synopsis: Compute the size of the largest disk or CD-ROM
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 4-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+GetLargestDiskSize(
+ VOID
+ )
+{
+ ULONG i;
+ ULONG size;
+ ULONG largestSize = 0L;
+ PCDROM_DESCRIPTOR cdrom;
+
+ for (i = 0; i < DiskCount; i++)
+ {
+ size = DiskArray[i]->DiskSizeMB;
+
+ if (size > largestSize)
+ {
+ largestSize = size;
+ }
+ }
+ for (i = 0; i < CdRomCount; i++)
+ {
+ cdrom = CdRomFindDevice(i);
+ size = cdrom->TotalSpaceInMB;
+
+ if (size > largestSize)
+ {
+ largestSize = size;
+ }
+ }
+
+ return largestSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DrawCdRomBar
+//
+// Synopsis: Draw a CD-ROM bar for the disks view
+//
+// Arguments: [CdRomNumber] -- the number of the CD-ROM to draw
+//
+// Returns: nothing
+//
+// History: 28-Feb-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DrawCdRomBar(
+ IN ULONG CdRomNumber
+ )
+{
+ HDC hDCMem;
+ HPEN hpenT;
+ TCHAR text[100];
+ TCHAR textBold[5];
+ TCHAR mbBuffer[16];
+ RECT rcBar;
+ RECT rcClip;
+ RECT rcText;
+ HFONT hfontT;
+ HDC hdcTemp;
+ HBITMAP hbmOld;
+ DWORD xCdRomText;
+ ULONG largestSize;
+ ULONG cdromSize;
+ ULONG cx;
+
+ //
+ // Figure out the type name and volume label.
+ //
+
+ PCDROM_DESCRIPTOR cdrom = CdRomFindDevice(CdRomNumber);
+ FDASSERT(NULL != cdrom);
+
+ hDCMem = cdrom->hDCMem;
+
+ // erase the graph background
+
+ rcBar.left = 0;
+ rcBar.top = 0;
+ rcBar.right = GraphWidth;
+ rcBar.bottom = GraphHeight;
+ FillRect(hDCMem, &rcBar, GetStockBrush(LTGRAY_BRUSH));
+
+ hpenT = SelectPen(hDCMem, g_hPenThinSolid);
+
+ //
+ // Draw the info area: small bitmap, some text, and a
+ // line across the top.
+ //
+ // First draw the bitmap.
+ //
+
+ hdcTemp = CreateCompatibleDC(hDCMem);
+ hbmOld = SelectBitmap(hdcTemp, g_hBitmapSmallCdRom);
+
+ BitBlt(hDCMem,
+ xSmallCdRom,
+ ySmallCdRom,
+ dxSmallCdRom,
+ dySmallCdRom,
+ hdcTemp,
+ 0,
+ 0,
+ SRCCOPY
+ );
+
+ if (hbmOld)
+ {
+ SelectBitmap(hdcTemp, hbmOld);
+ }
+ DeleteDC(hdcTemp);
+
+ //
+ // Now draw the line.
+ //
+
+ MoveToEx(hDCMem, xSmallCdRom, BarTopYOffset, NULL);
+ LineTo(hDCMem, BarLeftX - xSmallCdRom, BarTopYOffset);
+
+ //
+ // Now draw the text.
+ //
+
+ hfontT = SelectFont(hDCMem, g_hFontGraphBold);
+ SetTextColor(hDCMem, RGB(0, 0, 0));
+ SetBkColor(hDCMem, RGB(192, 192, 192));
+
+ //use the width of the disk bitmap as a buffer width
+ xCdRomText = dxSmallCdRom + dxSmallDisk;
+
+ wsprintf(text, CdRomN, CdRomNumber);
+ TextOut(hDCMem,
+ xCdRomText,
+ BarTopYOffset + dyBarTextLine,
+ text,
+ lstrlen(text)
+ );
+
+ SelectFont(hDCMem, g_hFontGraph);
+
+ LoadString(g_hInstance, IDS_MEGABYTES_ABBREV, mbBuffer, ARRAYLEN(mbBuffer));
+
+ if (cdrom->TypeName) {
+ wsprintf(text, TEXT("%u %s"), cdrom->TotalSpaceInMB, mbBuffer);
+
+ TextOut(hDCMem,
+ xCdRomText,
+ BarTopYOffset + (4*dyBarTextLine),
+ text,
+ lstrlen(text)
+ );
+
+ }
+
+ //
+ // Now draw the bar. First figure out largest size.
+ //
+
+ largestSize = GetLargestDiskSize();
+
+ if (DiskProportional == g_DiskDisplayType)
+ {
+ cdromSize = cdrom->TotalSpaceInMB;
+
+ //
+ // Account for extreme differences in largest to smallest disk
+ //
+
+ if (cdromSize < largestSize / 4)
+ {
+ cdromSize = largestSize / 4;
+ }
+ }
+ else
+ {
+ cdromSize = largestSize;
+ }
+
+ // cx = BarWidth * (cdromSize / largestSize);
+ //
+ // ===>
+ //
+ // cx = (BarWidth * cdromSize) / largestSize;
+
+ cx = (ULONG)(UInt32x32To64(BarWidth, cdromSize) / largestSize) + 1;
+
+ rcClip.left = BarLeftX;
+ rcClip.top = BarTopYOffset;
+ rcClip.right = BarLeftX + cx;
+ rcClip.bottom = BarBottomYOffset;
+
+ cdrom->LeftRight.Left = rcClip.left;
+ cdrom->LeftRight.Right = rcClip.right;
+
+ SelectBrush(hDCMem, GetStockBrush(WHITE_BRUSH));
+
+ Rectangle(
+ hDCMem,
+ rcClip.left,
+ rcClip.top,
+ rcClip.right,
+ rcClip.bottom
+ );
+
+ InflateRect(&rcClip, -PEN_WIDTH, -PEN_WIDTH);
+
+ if (cdrom->TypeName) {
+ wsprintf(text,
+ TEXT("\n%s\n%s\n%u %s"),
+ cdrom->VolumeLabel,
+ cdrom->TypeName,
+ cdrom->TotalSpaceInMB,
+ mbBuffer);
+ }
+
+ *textBold = L'\0';
+ if (cdrom->DriveLetter != NO_DRIVE_LETTER_EVER)
+ {
+ wsprintf(textBold, TEXT("%wc:"), cdrom->DriveLetter);
+ }
+
+ // output the text
+
+ rcText.left = rcClip.left + dxBarTextMargin;
+ rcText.top = BarTopYOffset + dyBarTextLine;
+ rcText.right = rcClip.right - dxBarTextMargin;
+ rcText.bottom = BarBottomYOffset;
+
+ SetBkMode(hDCMem, TRANSPARENT);
+ SetTextColor(hDCMem, RGB(0, 0, 0));
+
+ SelectFont(hDCMem, g_hFontGraphBold);
+ DrawText(hDCMem, textBold, -1, &rcText, DT_LEFT | DT_NOPREFIX);
+
+ if (cdrom->TypeName) {
+
+ SelectFont(hDCMem, g_hFontGraph);
+ DrawText(hDCMem, text, -1, &rcText, DT_LEFT | DT_NOPREFIX);
+
+ }
+
+ SelectPen(hDCMem, hpenT);
+ SelectFont(hDCMem, hfontT);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DrawDiskBar
+//
+// Synopsis: Draw a disk bar for the disks view
+//
+// Arguments: [DiskState] -- the disk state for the disk to draw
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DrawDiskBar(
+ IN PDISKSTATE DiskState
+ )
+{
+ LONGLONG temp1, temp2;
+ ULONG i;
+ HDC hDCMem = DiskState->hDCMem;
+ DWORD leftAdjust = BarLeftX;
+ DWORD cx;
+ DWORD diskWidth;
+ HPEN hpenT;
+ TCHAR text[100];
+ TCHAR textBold[5];
+ TCHAR mbBuffer[16];
+ RECT rc;
+ RECT rcRegion;
+ HFONT hfontT;
+ DWORD brushIndex;
+ COLORREF previousColor;
+ HBRUSH hbr;
+ BOOL isFree;
+ BOOL isLogical;
+ BOOL isNew;
+ HDC hdcTemp;
+ HBITMAP hbmOld;
+ DWORD xDiskText;
+ PWSTR typeName;
+ PWSTR volumeLabel;
+ WCHAR driveLetter;
+ BAR_TYPE barType;
+ ULONG diskSize;
+ ULONG largestSize;
+ PREGION_DESCRIPTOR regionDescriptor;
+
+ // If this is a removable, update to whatever its current
+ // information may be.
+
+ if (IsDiskRemovable[DiskState->Disk])
+ {
+
+ //
+ // We are going to find out the partition type and disk size for
+ // this removable.
+ //
+ // If the disk size is zero we will assume that the drive is empty.
+ //
+ // If the drive is empty we have two cases.
+ //
+ // 1) We may have previously had something in the drive.
+ //
+ // if this is the case then we need to free up its region
+ // structures.
+ //
+ // 2) We didn't previously have something in the drive.
+ //
+ // Nothing really to do in this case. Essentially there was
+ // no change.
+ //
+ // If the drive contains something we have 2 cases.
+ //
+ // 1) The drive didn't contain anything previouly.
+ //
+ // In this case we should build up the region and partition structures
+ // for the drive.
+ //
+ // 2) The drive contained something previously.
+ //
+ // This has two subcases.
+ //
+ // a) The drive contained something with the same label and size
+ //
+ // b) The drive contained something with a different label or size.
+ //
+ //
+ //
+
+ PPERSISTENT_REGION_DATA regionData;
+
+ // Update the information on this disk.
+
+ regionDescriptor = &DiskState->RegionArray[0];
+
+ GetVolumeTypeAndSize(DiskState->Disk,
+ 1,
+ &volumeLabel,
+ &typeName,
+ &diskSize);
+
+ if (!diskSize) {
+
+ //
+ // If we have region data then free it up it's invalid.
+ //
+
+ if (regionDescriptor) {
+
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (regionData) {
+
+ if (regionData->VolumeLabel) {
+
+ Free(regionData->VolumeLabel);
+ regionData->VolumeLabel = NULL;
+
+ }
+
+ if (regionData->TypeName) {
+
+ Free(regionData->TypeName);
+ regionData->TypeName = NULL;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+
+ if (regionDescriptor) {
+ regionData = PERSISTENT_DATA(regionDescriptor);
+
+ if (GetVolumeTypeAndSize(DiskState->Disk,
+ 1,
+ &volumeLabel,
+ &typeName,
+ &diskSize))
+ {
+ // Update the values for the removable.
+
+ if (NULL != regionData)
+ {
+ if (0 == lstrcmpi(typeName, L"raw"))
+ {
+ // Always want RAW file systems to display as "Unknown"
+
+ Free(typeName);
+ typeName = (PWSTR)Malloc((lstrlen(wszUnknown) + 1) * sizeof(WCHAR));
+ lstrcpy(typeName, wszUnknown);
+ }
+
+ if (NULL != regionData->VolumeLabel)
+ {
+ Free(regionData->VolumeLabel);
+ }
+ regionData->VolumeLabel = volumeLabel;
+
+ if (NULL != regionData->TypeName)
+ {
+ Free(regionData->TypeName);
+ }
+ regionData->TypeName = typeName;
+ regionData->TotalSpaceInBytes.LowPart = diskSize;
+
+ }
+
+ DiskState->DiskSizeMB = diskSize;
+ }
+ }
+ }
+
+ largestSize = GetLargestDiskSize();
+
+ // erase the graph background
+
+ rc.left = rc.top = 0;
+ rc.right = GraphWidth;
+ rc.bottom = GraphHeight;
+ FillRect(hDCMem, &rc, GetStockBrush(LTGRAY_BRUSH));
+
+ hpenT = SelectPen(hDCMem, g_hPenThinSolid);
+
+ //
+ // Draw the info area: small disk bitmap, some text, and a
+ // line across the top.
+ //
+ // First draw the bitmap.
+ //
+
+ hdcTemp = CreateCompatibleDC(hDCMem);
+ if (IsDiskRemovable[DiskState->Disk])
+ {
+ hbmOld = SelectBitmap(hdcTemp, g_hBitmapRemovableDisk);
+ BitBlt(hDCMem,
+ xRemovableDisk,
+ yRemovableDisk,
+ dxRemovableDisk,
+ dyRemovableDisk,
+ hdcTemp,
+ 0,
+ 0,
+ SRCCOPY);
+ }
+ else
+ {
+ hbmOld = SelectBitmap(hdcTemp, g_hBitmapSmallDisk);
+ BitBlt(hDCMem,
+ xSmallDisk,
+ ySmallDisk,
+ dxSmallDisk,
+ dySmallDisk,
+ hdcTemp,
+ 0,
+ 0,
+ SRCCOPY);
+ }
+
+ if (hbmOld)
+ {
+ SelectBitmap(hdcTemp, hbmOld);
+ }
+ DeleteDC(hdcTemp);
+
+ //
+ // Now draw the line.
+ //
+
+ if (IsDiskRemovable[DiskState->Disk])
+ {
+ MoveToEx(hDCMem, xRemovableDisk, BarTopYOffset, NULL);
+ LineTo(hDCMem, BarLeftX - xRemovableDisk, BarTopYOffset);
+ xDiskText = 2 * dxRemovableDisk;
+ }
+ else
+ {
+ MoveToEx(hDCMem, xSmallDisk, BarTopYOffset, NULL);
+ LineTo(hDCMem, BarLeftX - xSmallDisk, BarTopYOffset);
+ xDiskText = 2 * dxSmallDisk;
+ }
+
+ //
+ // Now draw the text.
+ //
+
+ hfontT = SelectFont(hDCMem, g_hFontGraphBold);
+ SetTextColor(hDCMem, RGB(0, 0, 0));
+ SetBkColor(hDCMem, RGB(192, 192, 192));
+ wsprintf(text, DiskN, DiskState->Disk);
+ TextOut(hDCMem,
+ xDiskText,
+ BarTopYOffset + dyBarTextLine,
+ text,
+ lstrlen(text)
+ );
+
+ SelectFont(hDCMem, g_hFontGraph);
+ if (DiskState->OffLine)
+ {
+ LoadString(g_hInstance, IDS_OFFLINE, text, ARRAYLEN(text));
+ }
+ else
+ {
+ LoadString(g_hInstance, IDS_MEGABYTES_ABBREV, mbBuffer, ARRAYLEN(mbBuffer));
+
+ if (!DiskState->DiskSizeMB && IsDiskRemovable[DiskState->Disk]) {
+
+ text[0] = L'\0';
+
+ } else {
+ wsprintf(text, TEXT("%u %s"), DiskState->DiskSizeMB, mbBuffer);
+ }
+ }
+
+
+ TextOut(hDCMem,
+ xDiskText,
+ BarTopYOffset + (4*dyBarTextLine),
+ text,
+ lstrlen(text)
+ );
+
+ //
+ // Now draw the disk bar
+ //
+
+ if (DiskState->OffLine)
+ {
+ //
+ // if a disk is offline, just draw an empty box with the text
+ // "configuration information not available" inside
+ //
+
+ SelectBrush(hDCMem, GetStockBrush(LTGRAY_BRUSH));
+
+ RECT rcClip;
+
+ rcClip.left = BarLeftX;
+ rcClip.top = BarTopYOffset;
+ rcClip.right = BarLeftX + BarWidth;
+ rcClip.bottom = BarBottomYOffset;
+
+ Rectangle(
+ hDCMem,
+ rcClip.left,
+ rcClip.top,
+ rcClip.right,
+ rcClip.bottom
+ );
+
+ LoadString(g_hInstance, IDS_NO_CONFIG_INFO, text, ARRAYLEN(text));
+
+ InflateRect(&rcClip, -PEN_WIDTH, -PEN_WIDTH);
+ ExtTextOut(
+ hDCMem,
+ BarLeftX + dxBarTextMargin,
+ BarTopYOffset + (4*dyBarTextLine),
+ ETO_CLIPPED,
+ &rcClip,
+ text,
+ lstrlen(text),
+ NULL
+ );
+ }
+ else
+ {
+ if (DiskProportional == g_DiskDisplayType)
+ {
+ diskSize = DiskState->DiskSizeMB;
+
+ //
+ // Account for extreme differences in largest to smallest disk
+ //
+
+ if (diskSize < largestSize / 4)
+ {
+ diskSize = largestSize / 4;
+ }
+ }
+ else
+ {
+ diskSize = largestSize;
+ }
+
+ //
+ // If user wants WinDisk to decide which type of view to use, do that
+ // here. We'll use a proportional view unless any single region would
+ // have a width less than 3 times the selection thickness plus the
+ // width of a drive letter.
+ //
+
+ barType = DiskState->BarType;
+
+ if (barType == BarAuto)
+ {
+ ULONG regionSize;
+
+ barType = BarProportional;
+
+ for (i=0; i<DiskState->RegionCount; i++)
+ {
+ regionDescriptor = &DiskState->RegionArray[i];
+
+ if (IsExtended(regionDescriptor->SysID))
+ {
+ continue;
+ }
+
+// regionSize = (regionDescriptor->SizeMB * BarWidth * diskSize)
+// / (largestSize * DiskState->DiskSizeMB);
+
+ temp1 = UInt32x32To64(BarWidth, diskSize);
+ temp1 *= regionDescriptor->SizeMB;
+ temp2 = UInt32x32To64(largestSize, (DiskState->DiskSizeMB?DiskState->DiskSizeMB:diskSize));
+ if (!temp2) {
+ temp2 = temp1;
+ }
+ regionSize = (ULONG) (temp1 / temp2);
+
+ if (regionSize < g_MinimumRegionSize)
+ {
+ barType = BarEqual;
+ break;
+ }
+ }
+ }
+
+// diskWidth = BarWidth * (diskSize / largestSize);
+
+ diskWidth = (DWORD)(UInt32x32To64(BarWidth, diskSize) / largestSize);
+
+ if (barType == BarEqual)
+ {
+
+// cx = 1 / (# of regions)
+// // % of the disk for this region
+// * BarWidth * (diskSize / largestSize)
+// // pixels in the disk
+// ;
+//
+// ===>
+//
+// cx = BarWidth * diskSize
+// / ((DiskState->RegionCount - (DiskState->ExistExtended ? 1 : 0)) * largestSize) ;
+
+ temp1 = UInt32x32To64(BarWidth, diskSize);
+ temp2 = UInt32x32To64(
+ (DiskState->RegionCount - (DiskState->ExistExtended ? 1 : 0)),
+ largestSize);
+ if (!temp2) {
+ temp2 = temp1;
+ }
+ cx = (ULONG) (temp1 / temp2);
+ }
+
+ for (i=0; i<DiskState->RegionCount; i++)
+ {
+ PFT_OBJECT ftObject;
+
+ regionDescriptor = &DiskState->RegionArray[i];
+
+ if (!IsExtended(regionDescriptor->SysID))
+ {
+ if (barType == BarProportional)
+ {
+
+// cx = (regionDescriptor->SizeMB / DiskState->DiskSizeMB)
+// // % of the disk for this region
+// * BarWidth * (diskSize / largestSize)
+// // pixels in the disk
+// ;
+//
+// ===>
+//
+// cx = regionDescriptor->SizeMB * BarWidth * diskSize
+// / (largestSize * DiskState->DiskSizeMB);
+
+ temp1 = UInt32x32To64(BarWidth, diskSize);
+ temp1 *= regionDescriptor->SizeMB;
+ temp2 = UInt32x32To64(largestSize, (DiskState->DiskSizeMB?DiskState->DiskSizeMB:diskSize));
+ if (!temp2) {
+ temp2 = temp1;
+ }
+ cx = (ULONG) (temp1 / temp2) + 1;
+ }
+
+ isFree = (regionDescriptor->SysID == PARTITION_ENTRY_UNUSED);
+ isLogical = (regionDescriptor->RegionType == REGION_LOGICAL);
+
+ if (NULL == regionDescriptor->PersistentData)
+ {
+ //
+ // no persistent data: free space or extended partition
+ //
+ isNew = FALSE;
+ }
+ else
+ {
+ isNew = PERSISTENT_DATA(regionDescriptor)->NewRegion;
+ }
+
+ if (!isFree)
+ {
+ //
+ // If we've got a mirror or stripe set, use special colors.
+ //
+
+ ftObject = GET_FT_OBJECT(regionDescriptor);
+ switch (ftObject ? ftObject->Set->Type : -1)
+ {
+ case Mirror:
+ brushIndex = BRUSH_MIRROR;
+ break;
+ case Stripe:
+ brushIndex = BRUSH_STRIPESET;
+ break;
+ case StripeWithParity:
+ brushIndex = BRUSH_PARITYSET;
+ break;
+ case VolumeSet:
+ brushIndex = BRUSH_VOLUMESET;
+ break;
+ default:
+ brushIndex = isLogical ? BRUSH_USEDLOGICAL : BRUSH_USEDPRIMARY;
+ }
+ }
+
+ previousColor = SetBkColor(hDCMem, RGB(255, 255, 255));
+ SetBkMode(hDCMem, OPAQUE);
+
+ rcRegion.left = leftAdjust;
+ rcRegion.top = BarTopYOffset;
+ rcRegion.right = leftAdjust + cx;
+ rcRegion.bottom = BarBottomYOffset;
+
+ if ( (DiskEqual == g_DiskDisplayType)
+ && (i == DiskState->RegionCount - 1) )
+ {
+ // for the last disk, to avoid off-by-one errors,
+ // simply set its right side to a fixed number
+
+ rcRegion.right = BarLeftX + diskWidth;
+ }
+
+ if (isFree)
+ {
+ //
+ // Free space -- cross hatch the whole block.
+ //
+
+ hbr = SelectBrush(
+ hDCMem,
+ isLogical
+ ? g_hBrushFreeLogical
+ : g_hBrushFreePrimary
+ );
+ Rectangle(
+ hDCMem,
+ rcRegion.left,
+ rcRegion.top,
+ rcRegion.right,
+ rcRegion.bottom
+ );
+ }
+ else
+ {
+ //
+ // Used space -- make most of the block white except for
+ // a small strip at the top, which gets an identifying
+ // color. If the partition is not recognized, leave
+ // it all white.
+ //
+
+ hbr = SelectBrush(hDCMem, GetStockBrush(WHITE_BRUSH));
+ Rectangle(
+ hDCMem,
+ rcRegion.left,
+ rcRegion.top,
+ rcRegion.right,
+ rcRegion.bottom
+ );
+
+ if (IsRecognizedPartition(regionDescriptor->SysID))
+ {
+ SelectBrush(hDCMem, g_Brushes[brushIndex]);
+ Rectangle(
+ hDCMem,
+ rcRegion.left,
+ rcRegion.top,
+ rcRegion.right,
+ rcRegion.top + (4 * dyBarTextLine / 5) + 1
+ );
+ }
+ }
+
+ if (hbr)
+ {
+ SelectBrush(hDCMem, hbr);
+ }
+
+ //
+ // Figure out the type name (ie, unformatted, fat, etc) and
+ // volume label.
+ //
+
+ DetermineRegionInfo(regionDescriptor, &typeName, &volumeLabel, &driveLetter);
+ LoadString(
+ g_hInstance,
+ IDS_MEGABYTES_ABBREV,
+ mbBuffer,
+ ARRAYLEN(mbBuffer));
+
+ if (NULL == typeName)
+ {
+ typeName = wszUnknown;
+ }
+
+ if (NULL == volumeLabel)
+ {
+ volumeLabel = L"";
+ }
+
+ wsprintf(text,
+ TEXT("\n%s\n%s\n%u %s"),
+ volumeLabel,
+ typeName,
+ regionDescriptor->SizeMB,
+ mbBuffer);
+
+ *textBold = L'\0';
+ if (driveLetter != L' ')
+ {
+ wsprintf(textBold, TEXT("%wc:"), driveLetter);
+ }
+
+ // output the text
+
+ rc.left = rcRegion.left + dxBarTextMargin;
+ rc.right = rcRegion.right - dxBarTextMargin;
+ rc.top = BarTopYOffset + dyBarTextLine;
+ rc.bottom = BarBottomYOffset;
+
+ SetBkMode(hDCMem, TRANSPARENT);
+
+ SelectFont(hDCMem, g_hFontGraphBold);
+
+ //
+ // If this is an unhealthy ft set member, draw the text in red.
+ //
+
+ if ( !isFree
+ && ftObject
+ && (ftObject->State != Healthy)
+ && (ftObject->State != Initializing))
+ {
+ SetTextColor(hDCMem, RGB(192, 0, 0));
+ }
+ else if (isNew)
+ {
+ //
+ // New volumes have gray text
+ //
+
+ SetTextColor(hDCMem, RGB(100, 100, 100));
+ }
+ else
+ {
+ SetTextColor(hDCMem, RGB(0, 0, 0));
+ }
+
+ DrawText(hDCMem, textBold, -1, &rc, DT_LEFT | DT_NOPREFIX);
+
+ SelectFont(hDCMem, g_hFontGraph);
+
+ DrawText(hDCMem, text, -1, &rc, DT_LEFT | DT_NOPREFIX);
+
+#if i386
+ //
+ // if this guy is active make a mark in the upper left
+ // corner of his rectangle.
+ //
+
+ if ( (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED)
+ && (regionDescriptor->RegionType == REGION_PRIMARY)
+ && regionDescriptor->Active)
+ {
+ TextOut(hDCMem,
+ leftAdjust + dxBarTextMargin,
+ BarTopYOffset + 2,
+ TEXT("*"),
+ 1);
+ }
+#endif
+
+#if defined( DBLSPACE_ENABLED )
+ // Check for DoubleSpace volumes and update display accordingly
+
+ PDBLSPACE_DESCRIPTOR dblSpace;
+ UINT dblSpaceIndex;
+
+ dblSpaceIndex = 0;
+ dblSpace = NULL;
+ while (NULL != (dblSpace = DblSpaceGetNextVolume(
+ regionDescriptor,
+ dblSpace)))
+ {
+ if (dblSpace->Mounted)
+ {
+ SetTextColor(hDCMem, RGB(192, 0, 0));
+ }
+ else
+ {
+ SetTextColor(hDCMem, RGB(0, 0, 0));
+ }
+
+ if (dblSpace->DriveLetter == TEXT(' '))
+ {
+ wsprintf(text,
+ TEXT("%s"),
+ dblSpace->FileName);
+ }
+ else
+ {
+ wsprintf(text,
+ TEXT("%c: %s"),
+ dblSpace->DriveLetter,
+ dblSpace->FileName);
+ }
+
+ rc.left = leftAdjust + dxBarTextMargin + 60;
+ rc.right = leftAdjust + cx - dxBarTextMargin;
+ rc.top = BarTopYOffset + dyBarTextLine + (dblSpaceIndex * 15);
+ rc.bottom = BarBottomYOffset;
+ DrawText(hDCMem, text, -1, &rc, DT_LEFT | DT_NOPREFIX);
+ dblSpaceIndex++;
+ }
+#endif // DBLSPACE_ENABLED
+
+ SetBkColor(hDCMem, previousColor);
+
+ DiskState->LeftRight[i].Left = rcRegion.left;
+ DiskState->LeftRight[i].Right = rcRegion.right;
+
+ // Now, add a delta to move to the next region.
+ // Note that the rectangles overlap: the right edge of a region
+ // is redrawn as the left edge of the following region, to
+ // avoid getting double-width lines between regions.
+
+ leftAdjust = rcRegion.right - 1;
+ }
+ else
+ {
+ DiskState->LeftRight[i].Left = DiskState->LeftRight[i].Right = 0;
+ }
+ }
+ }
+
+ SelectPen(hDCMem, hpenT);
+ SelectFont(hDCMem, hfontT);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PartitionCount
+//
+// Synopsis: Returns a count of used primary partitions on a disk.
+// If =4, then no more primary partitions may be created.
+//
+// Arguments: [Disk] -- 0-based number of the disk of interest
+//
+// Returns: number of partitions
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+ULONG
+PartitionCount(
+ IN ULONG Disk
+ )
+{
+ ULONG i;
+ ULONG partitions = 0;
+
+ for (i=0; i<DiskArray[Disk]->RegionCount; i++)
+ {
+ PREGION_DESCRIPTOR regionDescriptor = &DiskArray[Disk]->RegionArray[i];
+
+ if ( (regionDescriptor->RegionType != REGION_LOGICAL)
+ && (regionDescriptor->SysID != PARTITION_ENTRY_UNUSED))
+ {
+ partitions++;
+ }
+ }
+
+ return partitions;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegisterFileSystemExtend
+//
+// Synopsis: This function adds registry entries to extend the file
+// system structures in volume sets that have been extended.
+//
+// Arguments: (none)
+//
+// Returns: TRUE if a file system was extended
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+BOOL
+RegisterFileSystemExtend(
+ VOID
+ )
+{
+ BYTE buf[1024];
+ PWSTR templateString = L"autochk /x ";
+ PWSTR appendPoint;
+ DWORD templateLength;
+ WCHAR extendedDrives[26];
+ PDISKSTATE diskState;
+ PREGION_DESCRIPTOR regionDescriptor;
+ PFT_OBJECT ftObject;
+ DWORD i;
+ DWORD j;
+ DWORD cExt = 0;
+ DWORD valueType;
+ DWORD size;
+ HKEY hkey;
+ LONG ec;
+
+
+ // Traverse the disks to find any volume sets that have been extended.
+ //
+ for (i = 0; i < DiskCount; i++)
+ {
+ diskState = DiskArray[i];
+
+ for (j = 0; j < diskState->RegionCount; j++)
+ {
+ regionDescriptor = &diskState->RegionArray[j];
+
+ if ( (NULL != (ftObject = GET_FT_OBJECT(regionDescriptor)))
+ && ftObject->MemberIndex == 0
+ && ftObject->Set->Type == VolumeSet
+ && ftObject->Set->Status == FtSetExtended)
+ {
+ extendedDrives[cExt++] = PERSISTENT_DATA(regionDescriptor)->DriveLetter;
+ }
+ }
+ }
+
+ if (0 != cExt)
+ {
+ //
+ // Fetch the BootExecute value of the Session Manager key.
+ //
+ ec = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ TEXT("System\\CurrentControlSet\\Control\\Session Manager"),
+ 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE,
+ &hkey
+ );
+
+ if (ec != NO_ERROR)
+ {
+ return FALSE;
+ }
+
+ size = sizeof(buf);
+ ec = RegQueryValueEx(hkey,
+ TEXT("BootExecute"),
+ NULL,
+ &valueType,
+ buf,
+ &size
+ );
+
+ if (ec != NO_ERROR || valueType != REG_MULTI_SZ)
+ {
+ return FALSE;
+ }
+
+ //
+ // Decrement size to get rid of the extra trailing null
+ //
+ if (0 != size)
+ {
+ size -= sizeof(WCHAR);
+ }
+
+ templateLength = wcslen(templateString);
+ appendPoint = (PWSTR)(buf + size);
+
+ for (i = 0; i < cExt; i++)
+ {
+ //
+ // Add an entry for this drive to the BootExecute value.
+ //
+ wcsncpy( appendPoint, templateString, templateLength );
+ appendPoint += templateLength;
+
+ *appendPoint++ = extendedDrives[i];
+ *appendPoint++ = L':';
+ *appendPoint++ = L'\0';
+ }
+
+ //
+ // Add an additional trailing null at the end
+ //
+ *appendPoint++ = L'\0';
+
+ //
+ // Recalculate the size of the buffer, adding all the new autochk
+ // strings.
+ //
+
+ size += ( (templateLength + 3) * cExt + 1 ) * sizeof(WCHAR);
+
+ //
+ // Save the value.
+ //
+ ec = RegSetValueEx(hkey,
+ TEXT("BootExecute"),
+ 0,
+ REG_MULTI_SZ,
+ buf,
+ size
+ );
+ RegCloseKey(hkey);
+
+ if (ec != NO_ERROR)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/private/utils/windisk/src/windisk.hxx b/private/utils/windisk/src/windisk.hxx
new file mode 100644
index 000000000..82bf15220
--- /dev/null
+++ b/private/utils/windisk/src/windisk.hxx
@@ -0,0 +1,140 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: windisk.hxx
+//
+// Contents: Declarations
+//
+// History: 4-Mar-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __WINDISK_HXX__
+#define __WINDISK_HXX__
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef i386
+
+extern BOOL SystemPartitionIsSecure;
+
+#endif // !i386
+
+//////////////////////////////////////////////////////////////////////////////
+
+LRESULT CALLBACK
+MyFrameWndProc(
+ IN HWND hwnd,
+ IN UINT msg,
+ IN WPARAM wParam,
+ IN LPARAM lParam
+ );
+
+BOOL
+IsVolumeFormatted(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+BOOL
+SingleVolumeSelected(
+ VOID
+ );
+
+VOID
+DetermineSelectionState(
+ VOID
+ );
+
+DWORD
+SetUpMenu(
+ IN PDISKSTATE *SinglySelectedDisk,
+ IN DWORD *SinglySelectedRegion
+ );
+
+VOID
+SetDriveLetterInfo(
+ IN UINT DiskNum
+ );
+
+VOID
+TotalRedraw(
+ VOID
+ );
+
+VOID
+RedrawSelectedBars(
+ VOID
+ );
+
+VOID
+TotalRedrawAndRepaint(
+ VOID
+ );
+
+PPERSISTENT_REGION_DATA
+DmAllocatePersistentData(
+ IN PFT_OBJECT FtObject,
+ IN PWSTR VolumeLabel,
+ IN PWSTR TypeName,
+ IN WCHAR DriveLetter,
+ IN BOOL NewRegion,
+ IN LARGE_INTEGER FreeSpaceInBytes,
+ IN LARGE_INTEGER TotalSpaceInBytes
+ );
+
+VOID
+DmFreePersistentData(
+ IN OUT PPERSISTENT_REGION_DATA RegionData
+ );
+
+DWORD
+DeletionIsAllowed(
+ IN PREGION_DESCRIPTOR RegionDescriptor
+ );
+
+VOID
+CheckForBootNumberChange(
+ IN ULONG Disk
+ );
+
+BOOLEAN
+BootPartitionNumberChanged(
+ PULONG OldNumber,
+ PULONG NewNumber
+ );
+
+BOOL
+AssignDriveLetter(
+ IN BOOL WarnIfNoLetter,
+ IN DWORD StringId,
+ OUT PWCHAR DriveLetter
+ );
+
+VOID
+SetFTObjectBackPointers(
+ VOID
+ );
+
+VOID
+DeterminePartitioningState(
+ IN OUT PDISKSTATE DiskState
+ );
+
+VOID
+DrawDiskBar(
+ IN PDISKSTATE DiskState
+ );
+
+ULONG
+PartitionCount(
+ IN ULONG Disk
+ );
+
+BOOL
+RegisterFileSystemExtend(
+ VOID
+ );
+
+#endif // __WINDISK_HXX__
diff --git a/private/utils/windisk/src/windisk.rc b/private/utils/windisk/src/windisk.rc
new file mode 100644
index 000000000..276f4c509
--- /dev/null
+++ b/private/utils/windisk/src/windisk.rc
@@ -0,0 +1,563 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: windisk.rc
+//
+// Contents: Main Disk Administrator resource definition file
+//
+// History: 6-Jun-93 BruceFo Created from NT Disk Administrator
+//
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+#include "resids.h"
+#include "dialogs.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+
+IDFDISK ICON dskmgr.ico // main icon
+IDB_SMALLDISK BITMAP smdisk.bmp // small disk for disks view
+IDB_REMOVABLEDISK BITMAP rmdisk.bmp // removable disk for disks view
+IDB_SMALLCDROM BITMAP smcdrom.bmp // small CD-ROM for disks view
+
+IDB_TOOLBAR BITMAP tool16.bmp
+IDB_EXTRATOOLS BITMAP xtra16.bmp
+
+IDI_S_HARD ICON shard.ico
+IDI_S_CDROM ICON scdrom.ico
+
+IDI_STOP_SIGN ICON trffc14.ico
+
+
+////////////////////////////////////////////////////////////////////////////
+
+STRINGTABLE BEGIN
+ IDS_APPNAME "Disk Administrator"
+ IDS_MULTIPLEITEMS "Multiple items selected"
+ IDS_FREESPACE "Free space"
+ IDS_PARTITION "Partition"
+ IDS_LOGICALVOLUME "Logical drive"
+ IDS_CDROM "CD-ROM"
+ IDS_DISKN "Disk %u"
+ IDS_CDROMN "CD-ROM %u"
+ IDS_CONFIRM "Confirm"
+ IDS_NOT_IN_APP_MSG_FILE "Could not find message %u in the application message file"
+ IDS_NOT_IN_SYS_MSG_FILE "Could not find message %u in the system message file"
+ IDS_UNFORMATTED "Unformatted"
+ IDS_UNKNOWN "Unknown"
+ IDS_STRIPESET "Stripe set"
+ IDS_VOLUMESET "Volume set"
+ IDS_EXTENDEDPARTITION "Empty extended partition"
+ IDS_FREEEXT "Free space in extended partition"
+ IDS_DRIVELET_DESCR "%1 MB %2 %3 on disk %4"
+ IDS_HEALTHY "HEALTHY"
+ IDS_BROKEN "BROKEN"
+ IDS_RECOVERABLE "RECOVERABLE"
+ IDS_INITIALIZING "INITIALIZING"
+ IDS_REGENERATING "REGENERATING"
+ IDS_REGENERATED "REGENERATED"
+ IDS_NEW "NEW"
+ IDS_OFFLINE "OFF-LINE"
+ IDS_DISABLED "DISABLED"
+ IDS_INIT_FAILED "Initialization Failed"
+ IDS_INSERT_DISK "Insert Disk"
+ IDS_MEGABYTES_ABBREV "MB"
+ IDS_UNAVAILABLE_DATA "?"
+ IDS_BYTES_DECORATION "%s bytes"
+ IDS_MEG_DECORATION "(%s MB)"
+ IDS_READY "Ready"
+ IDS_NOTREADY "Not Ready"
+ IDS_NO_CONFIG_INFO "Configuration information not available"
+
+#if i386
+ IDS_ACTIVEPARTITION "Active partition"
+#endif
+ IDS_CRTPART_CAPTION_P "Create Primary Partition"
+ IDS_CRTPART_CAPTION_E "Create Extended Partition"
+ IDS_CRTPART_CAPTION_L "Create Logical Drive"
+ IDS_CRTPART_MIN_P "Minimum size for the partition is"
+ IDS_CRTPART_MAX_P "Maximum size for the partition is"
+ IDS_CRTPART_MIN_L "Minimum size for the logical drive is"
+ IDS_CRTPART_MAX_L "Maximum size for the logical drive is"
+ IDS_CRTPART_SIZE_P "&Create partition of size"
+ IDS_CRTPART_SIZE_L "&Create logical drive of size"
+
+ IDS_CRTPSTRP_CAPTION "Create Stripe Set With Parity"
+ IDS_CRTSTRP_CAPTION "Create Stripe Set"
+ IDS_CRTSTRP_MIN "Minimum total size for the stripe set is"
+ IDS_CRTSTRP_MAX "Maximum total size for the stripe set is"
+ IDS_CRTSTRP_SIZE "&Create stripe set of total size"
+
+ IDS_CRTVSET_CAPTION "Create Volume Set"
+ IDS_EXPVSET_CAPTION "Extend Volume Set"
+ IDS_CRTVSET_MIN "Minimum total size for the volume set is"
+ IDS_CRTVSET_MAX "Maximum total size for the volume set is"
+ IDS_CRTVSET_SIZE "&Create volume set of total size"
+
+ IDS_STATUS_STRIPESET "Stripe set #%u"
+ IDS_STATUS_PARITY "Stripe set with parity #%u [%s]"
+ IDS_DLGCAP_PARITY "Stripe set with parity #%u"
+ IDS_STATUS_VOLUMESET "Volume set #%u"
+ IDS_STATUS_MIRROR "Mirror set #%u [%s]"
+ IDS_DLGCAP_MIRROR "Mirror set #%u"
+
+ IDS_UNKNOWNTYPE "?"
+
+ // Note: these must be in same order as BRUSH_xxx constants in const.h
+
+ IDS_LEGEND_PRIMARY "Primary partition"
+ IDS_LEGEND_LOGICAL "Logical drive"
+ IDS_LEGEND_STRIPESET "Stripe set"
+ IDS_LEGEND_PARITYSET "Stripe set with parity"
+ IDS_LEGEND_MIRROR "Mirror set"
+ IDS_LEGEND_VOLUMESET "Volume set"
+
+ IDS_PARTITION_FREE "Free Space"
+ IDS_PARTITION_XENIX1 "XENIX1"
+ IDS_PARTITION_XENIX2 "XENIX2"
+ IDS_PARTITION_OS2_BOOT "OS/2 Boot Manager"
+ IDS_PARTITION_EISA "EISA Utilities"
+ IDS_PARTITION_UNIX "Unix"
+ IDS_PARTITION_POWERPC "PowerPC Boot"
+
+ IDS_MENUANDITEM "%s - %s"
+
+ IDS_CHANGEFORMAT "&Format..."
+ IDS_FORMAT "&Format..."
+
+ IDS_NOOPERATIONS "<< No valid operations >>"
+
+ IDS_SOURCE_PATH "\\Software\\Microsoft\\Windows NT\\CurrentVersion"
+ IDS_SOURCE_PATH_NAME "SourcePath"
+
+#if defined( DBLSPACE_ENABLED )
+ //
+ // DoubleSpace support strings
+ //
+
+ IDS_DBLSPACE_DELETE "Delete DoubleSpace Volume"
+ IDS_DBLSPACE_MOUNTED "DoubleSpace Volume currently mounted as drive"
+ IDS_DBLSPACE_DISMOUNTED "DoubleSpace Volume is dismounted"
+ IDS_WITH_DBLSPACE " with DoubleSpace Volumes"
+ IDS_MOUNT "Mount"
+ IDS_DISMOUNT "Dismount"
+ IDS_CREATING_DBLSPACE "Creating DoubleSpace volume..."
+ IDS_DBLSPACECOMPLETE "Creation of DoubleSpace volume is complete"
+#endif // DBLSPACE_ENABLED
+
+
+//
+// Volume view column titles
+//
+
+ IDS_VV_VOLUME "Volume"
+ IDS_VV_NAME "Name"
+ IDS_VV_CAPACITY "Capacity"
+ IDS_VV_FREESPACE "Free Space"
+ IDS_VV_PCTFREE "% Free"
+ IDS_VV_FORMAT "Format"
+ IDS_VV_FT "Fault Tolerant?"
+ IDS_VV_VOLTYPE "Volume Type"
+ IDS_VV_OVERHEAD "Fault Tolerance Overhead"
+ IDS_VV_STATUS "Status"
+
+//
+// Volume view column data strings
+//
+
+ IDS_VOLTYPE_MIRROR "Mirror set"
+ IDS_VOLTYPE_STRIPE "Stripe set"
+ IDS_VOLTYPE_PARITY "Stripe set with parity"
+ IDS_VOLTYPE_VOLSET "Volume set"
+ IDS_VOLTYPE_SIMPLE ""
+
+ IDS_FT_YES "yes"
+ IDS_FT_NO "no"
+
+ IDS_FTSTATUS_HEALTHY "Healthy"
+ IDS_FTSTATUS_BROKEN "Broken"
+ IDS_FTSTATUS_RECOVERABLE "Recoverable"
+ IDS_FTSTATUS_INITIALIZING "Initializing"
+ IDS_FTSTATUS_REGENERATING "Regenerating"
+ IDS_FTSTATUS_REGENERATED "Regenerated"
+ IDS_FTSTATUS_NEW "New"
+ IDS_FTSTATUS_NONE ""
+
+//
+// Miscellaneous
+//
+
+ IDS_PROPERTIES "Properties..."
+
+
+//
+// strings for menu help
+//
+
+//
+// Partition menu
+//
+
+ IDS_HELP_CREATE "Create Partition"
+ IDS_HELP_CREATEEX "Create Extended Partition"
+ IDS_HELP_DELETE "Delete"
+ IDS_HELP_CREATEVOLSET "Create Volume Set"
+ IDS_HELP_EXTENDVOLSET "Extend Volume Set"
+ IDS_HELP_CREATESTRIPE "Create Stripe Set"
+#ifdef i386
+ IDS_HELP_MARKACTIVE "Mark Active"
+#else // i386
+ IDS_HELP_SECURE "Secure System Partition"
+#endif // i386
+
+//
+// Configuration sub-menu
+//
+
+ IDS_HELP_SAVECONFIG "Saves the disk configuration to floppy"
+ IDS_HELP_RESTORECONFIG "Restores the disk configuration from floppy"
+ IDS_HELP_SEARCHCONFIG "Searches for another installation of Windows NT"
+
+ IDS_HELP_PARTITIONCOMMIT "Commit partition changes to disk"
+ IDS_HELP_QUIT "Exit"
+
+//
+// Fault-tolerance menu
+//
+
+ IDS_HELP_ESTABLISHMIRROR "Establish Mirror"
+ IDS_HELP_BREAKMIRROR "Break Mirror"
+ IDS_HELP_CREATEPSET "Creates a fault tolerant stripe set with parity"
+ IDS_HELP_REGENSTRIPE "Regenerates a stripe set"
+
+//
+// Tools menu
+//
+
+ IDS_HELP_FORMAT "Format"
+ IDS_HELP_DRIVELET "Reassigns a volume's drive letter"
+#if defined( DBLSPACE_ENABLED )
+ IDS_HELP_DBLSPACE "Configures DoubleSpace volumes"
+ IDS_HELP_AUTOMOUNT "Toggles whether or not DoubleSpace volumes are mounted"
+#endif // DBLSPACE_ENABLED
+ IDS_HELP_PROPERTIES "Properties"
+
+//
+// View menu
+//
+
+ IDS_HELP_VOLUMESVIEW "Volumes"
+ IDS_HELP_DISKSVIEW "Disk Configuration"
+ IDS_HELP_REFRESH "Reload volume information"
+
+//
+// Options menu
+//
+
+ IDS_HELP_TOOLBAR "Displays or hides the toolbar"
+ IDS_HELP_STATUSBAR "Displays or hides the status bar"
+ IDS_HELP_LEGEND "Displays or hides the legend"
+ IDS_HELP_COLORS "Colors and Patterns"
+ IDS_HELP_OPTIONSDISK "Controls the display of disks in the disk view"
+ IDS_HELP_REGIONDISPLAY "Region Display"
+ IDS_HELP_CUSTTOOLBAR "Customizes the toolbar"
+
+//
+// Help menu
+//
+
+ IDS_HELP_HELPCONTENTS "Help"
+ IDS_HELP_HELPSEARCH "Searches for a topic in Disk Administrator help"
+ IDS_HELP_HELPHELP "Displays information about using help"
+ IDS_HELP_HELPABOUT "Displays information about Disk Administrator"
+
+//
+// Debug menu (only for debug builds)
+//
+
+#if DBG == 1
+ IDS_HELP_DELETEALL "If checked, then all partitions can be deleted"
+ IDS_HELP_LOG "Write internal data structures to c:\\windisk.log"
+ IDS_HELP_RAID "RAID bug database information"
+#endif // DBG == 1
+
+//
+// Things not on top-level menus
+//
+
+ IDS_HELP_NOVALIDOPERATION "No operations are valid with the current selection"
+
+//
+// For the menus themselves:
+//
+
+ IDS_HELP_MENU_PARTITION "Commands for operating on partitions"
+ IDS_HELP_MENU_FT "Commands for NT fault tolerance configuration"
+ IDS_HELP_MENU_VOLUMES "Commands for administering volumes"
+ IDS_HELP_MENU_VIEW "Commands for determining how information is displayed"
+ IDS_HELP_MENU_OPTIONS "Commands for setting options"
+ IDS_HELP_MENU_HELP "Commands for displaying Disk Administrator help"
+
+ IDS_HELP_MENU_CONFIG "Commands to save or restore the disk configuration"
+
+#if DBG == 1
+ IDS_HELP_MENU_DEBUG "Commands to aid debugging"
+#endif // DBG == 1
+
+//
+// File system strings
+//
+
+ IDS_LONG_FAT "FAT (File Allocation Table; Windows NT, Windows, DOS, OS/2)"
+ IDS_LONG_NTFS "NTFS (New Technology File System; Windows NT)"
+#ifdef SUPPORT_OFS
+ IDS_LONG_OFS "OFS (Object File System; Windows Cairo)"
+#endif // SUPPORT_OFS
+
+END
+
+
+////////////////////////////////////////////////////////////////////////////
+
+IDFDISK MENU
+BEGIN
+ POPUP "&Partition"
+ BEGIN
+ MENUITEM "&Create..." ,IDM_PARTITIONCREATE , GRAYED
+ MENUITEM "Create &Extended..." ,IDM_PARTITIONCREATEEX, GRAYED
+ MENUITEM "&Delete" ,IDM_PARTITIONDELETE , GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Create &Volume Set..." ,IDM_FTCREATEVOLUMESET, GRAYED
+ MENUITEM "Ex&tend Volume Set..." ,IDM_FTEXTENDVOLUMESET, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Create &Stripe Set..." ,IDM_FTCREATESTRIPE , GRAYED
+ MENUITEM SEPARATOR
+#if i386
+ MENUITEM "Mark &Active" ,IDM_PARTITIONACTIVE , GRAYED
+#else
+ MENUITEM "Sec&ure System Partition",IDM_SECURESYSTEM
+#endif
+ POPUP "Confi&guration"
+ BEGIN
+ MENUITEM "&Save..." ,IDM_CONFIGSAVE
+ MENUITEM "&Restore..." ,IDM_CONFIGRESTORE
+ MENUITEM "Sear&ch..." ,IDM_CONFIGMIGRATE
+ END
+
+ MENUITEM SEPARATOR
+ MENUITEM "C&ommit Changes Now..." ,IDM_PARTITIONCOMMIT , GRAYED
+ MENUITEM "E&xit" ,IDM_QUIT
+ END
+
+ POPUP "&Fault Tolerance"
+ BEGIN
+ MENUITEM "Establish &Mirror" ,IDM_FTESTABLISHMIRROR, GRAYED
+ MENUITEM "&Break Mirror..." ,IDM_FTBREAKMIRROR , GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Create Stripe Set with &Parity...",IDM_FTCREATEPSTRIPE , GRAYED
+ MENUITEM "&Regenerate" ,IDM_FTRECOVERSTRIPE , GRAYED
+ END
+
+ POPUP "&Tools"
+ BEGIN
+ MENUITEM "&Format..." ,IDM_VOL_FORMAT
+ MENUITEM "Assign Dri&ve Letter...",IDM_VOL_LETTER , GRAYED
+ MENUITEM "Eject" ,IDM_VOL_EJECT , GRAYED
+#if defined( DBLSPACE_ENABLED )
+ MENUITEM SEPARATOR
+ MENUITEM "&DoubleSpace Volumes...",IDM_VOL_DBLSPACE , GRAYED
+ MENUITEM "&Automount DoubleSpace Floppies",IDM_VOL_AUTOMOUNT, GRAYED
+#endif // DBLSPACE_ENABLED
+
+ MENUITEM SEPARATOR
+ MENUITEM "P&roperties" ,IDM_VOL_PROPERTIES
+
+ END
+
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Volumes\tCtrl+V" ,IDM_VIEWVOLUMES
+ MENUITEM "&Disk Configuration\tCtrl+D" ,IDM_VIEWDISKS
+ MENUITEM SEPARATOR
+ MENUITEM "R&efresh\tF5" ,IDM_VIEW_REFRESH
+ END
+
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Toolbar\tCtrl+T" ,IDM_OPTIONSTOOLBAR
+ MENUITEM "&Status Bar\tCtrl+S" ,IDM_OPTIONSSTATUS
+ MENUITEM "&Legend\tCtrl+L" ,IDM_OPTIONSLEGEND
+ MENUITEM SEPARATOR
+ MENUITEM "&Colors and Patterns..." ,IDM_OPTIONSCOLORS
+ MENUITEM "&Disk Display..." ,IDM_OPTIONSDISK
+ MENUITEM "&Region Display..." ,IDM_OPTIONSDISPLAY
+ MENUITEM SEPARATOR
+ MENUITEM "Customize Tool&bar..." ,IDM_OPTIONSCUSTTOOLBAR
+ END
+
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&Contents" ,IDM_HELPCONTENTS
+ MENUITEM "&Search for Help on..." ,IDM_HELPSEARCH
+ MENUITEM "&How to Use Help" ,IDM_HELPHELP
+ MENUITEM SEPARATOR
+ MENUITEM "&About Disk Administrator..." ,IDM_HELPABOUT
+#if DBG == 1
+ MENUITEM SEPARATOR
+ POPUP "&DEBUG"
+ BEGIN
+ MENUITEM "&Allow delete all partitions",IDM_DEBUGALLOWDELETES
+ MENUITEM "&Log partition info" ,IDM_DEBUGLOG
+ END
+ MENUITEM "&RAID Information..." ,IDM_RAID
+#endif // DBG == 1
+ END
+
+END
+
+////////////////////////////////////////////////////////////////////////////
+
+ID_FRAME_ACCELERATORS ACCELERATORS
+{
+ "^V", IDM_VIEWVOLUMES
+ "^D", IDM_VIEWDISKS
+ "^T", IDM_OPTIONSTOOLBAR
+ "^S", IDM_OPTIONSSTATUS
+ "^L", IDM_OPTIONSLEGEND
+ VK_F5, IDM_VIEW_REFRESH, VIRTKEY
+ VK_F1, IDM_HELPCONTENTS, VIRTKEY
+ VK_RETURN,IDM_VOL_PROPERTIES,VIRTKEY,ALT
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+//
+// The following data is used for the nice drive bitmap for the volume
+// property page
+//
+
+IDB_HARDDISK BITMAP LOADONCALL HARD.BMP
+IDB_CDROM BITMAP LOADONCALL CDR.BMP
+
+/*
+ * This resource defines a word flag a word and 8 additional words
+ *
+ * The flag defines whether this drive bitmap uses an ellips or a
+ * parallelogram to represent its free/used space. USETYPE_ELLIPS,
+ * USETYPE_BARH, USETYPE_BARV and USETYPE_NONE are the four defines
+ * for these flag values.
+ *
+ * USETYPE_NONE is for never-writable drives (like CD-ROM).
+ * USETYPE_ELLIPS is for circular type drives (Fixed Floppy).
+ * USETYPE_BARH is a horizontal parallelogram.
+ * USETYPE_BARV is a verticle parallelogram.
+ *
+ * The word is the "3-D effect" height/width for the parallelogram or ellips.
+ * NOTE that the 3-D effect can be disabled by specifying a height/width
+ * value of 0. Also note that with 3-D effect disabled, the parallelogram
+ * can be turned into a rectangle.
+ *
+ * The following 8 words are either one rect for USETYPE_ELLIPS or
+ * four points for USETYPE_BARH or USETYPE_BARV.
+ *
+ * For USETYPE_ELLIPS the first four words form a RECT structure
+ * which specifies the bounding rectangle for the ellips. The other
+ * 4 words must be 0. It is critical that these extra words be 0
+ * as they are reserved for future expansion.
+ *
+ * For USETYPE_BAR? the 8 words form an array of 4 POINT structures.
+ *
+ * USETYPE_BARH (0.y)==(1.y) and (3.y)==(2.y)
+ *
+ * 0 _____________ 1
+ * \ \
+ * 3-D-> \ \
+ * \ \
+ * 3 ------------- 2
+ * ^
+ * 3-D
+ *
+ * USETYPE_BARV (0.x)==(3.x) and (1.x)==(2.x)
+ *
+ * 1
+ * /|
+ * / |
+ * / |
+ * 0 | |
+ * | |
+ * | | <- 3-D
+ * | |
+ * | |
+ * | |
+ * | |
+ * | | 2
+ * | /
+ * | / <- 3-D
+ * |/
+ *
+ * 3
+ *
+ * NOTE that the ellips RECT INCLUDES the 3-D effect but that the
+ * parallelogram points DO NOT.
+ *
+ */
+
+ELLIPRESOURCE IDB_HARDDISK DISCARDABLE LOADONCALL
+BEGIN
+ USETYPE_ELLIPS, /* FLAG */
+ 3, /* 3-D effect height/width */
+ 39, /* Left */
+ 26, /* Top */
+ 145, /* Right */
+ 91, /* Bottom */
+ 0,
+ 0,
+ 0,
+ 0
+END
+
+ELLIPRESOURCE IDB_CDROM DISCARDABLE LOADONCALL
+BEGIN
+ USETYPE_NONE, /* FLAG */
+ 0, /* 3-D effect height/width */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+END
+
+////////////////////////////////////////////////////////////////////////////
+
+#include "dialogs.dlg"
+
+#if defined( DBLSPACE_ENABLED )
+#include "dblspace.h"
+#include "dblspace.dlg"
+#endif // DBLSPACE_ENABLED
+
+#include "ftreg.h"
+#include "ftreg.dlg"
+
+#if 0
+#include "messages.mc" // trick build.exe into this transitive dependency
+#endif // 0
+#include "messages.rc"
+
+////////////////////////////////////////////////////////////////////////////
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Disk Partitioning Utility"
+#define VER_INTERNALNAME_STR "fdisk\0"
+#define VER_ORIGINALFILENAME_STR "WINDISK.EXE"
+
+#include "common.ver"
diff --git a/private/utils/windisk/src/xtra16.bmp b/private/utils/windisk/src/xtra16.bmp
new file mode 100644
index 000000000..e37d7b2d2
--- /dev/null
+++ b/private/utils/windisk/src/xtra16.bmp
Binary files differ
diff --git a/private/utils/windisk/types/daexts.idl b/private/utils/windisk/types/daexts.idl
new file mode 100644
index 000000000..e53d08b94
--- /dev/null
+++ b/private/utils/windisk/types/daexts.idl
@@ -0,0 +1,233 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: daexts.idl
+//
+// Contents: Types for the windisk extension interfaces
+//
+// History: 4-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+LOCAL_INTERFACE(cbf36b48-03e1-101b-b36a-00dd01101592)
+interface DAExtensionTypes
+{
+
+
+// disable "nonstandard extension used : zero-sized array in struct/union"
+// #pragma warning(disable:4200)
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// HRESULT error codes
+//
+
+cpp_quote("#define DA_E_OPERATIONFAILED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1000)")
+cpp_quote("#define DA_E_OPERATIONCANCELLED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1001)")
+cpp_quote("#define DA_E_VOLUMEINFOCHANGED MAKE_SCODE(SEVERITY_SUCCESS,FACILITY_NULL,1002)")
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// VolumeInfoBlockType:
+//
+// This information identifies a volume to volume extension code.
+// It will contain the minimal useful set of information about a
+// volume, preferably only a drive letter. If any information
+// in addition to the drive letter is useful, we'll add it here.
+//
+// A volume can be identified by a Win32/DOS drive letter, if a
+// drive letter is assigned (and all volumes have drive letters),
+// e.g. 'C'. From this, the ISV can call the following Win32 APIs:
+// -- GetDriveType, but in most/all cases it will be a Fixed drive
+// -- GetDiskFreeSpace, to get allocation unit information (sectors
+// per unit, bytes per sector, # free units, total # of units)
+// -- GetVolumeInformation, to get the volume name, serial number,
+// maximum component length of a filename component, a set of
+// flags (case sensitive/insensitive, whether filename case is
+// preserved, whether UNICODE filenames are supported), and the
+// filesystem name
+//
+// Note that you can use GetLogicalDrives() and
+// GetLogicalDriveStrings() to determine which drive letters are
+// in use.
+//
+// An alternate volume identifier is an NT object path, e.g.,
+// \Device\HardDisk0\Partition0. From this the ISV can call
+// NtOpenFile followed by NtQueryVolumeInformationFile. This provides
+// the volume label, volume serial number, volume creation time,
+// allocation information (total units, available units, sectors
+// per unit, bytes per sector), device information, and perhaps more.
+//
+// All the IFS entrypoints (Format, ChkDsk, Convert) take an NT
+// object path.
+//
+// The utility routine GetDeviceObject() converts between a Win32 drive
+// letter and an NT ``\Device\...'' object path by following the
+// ``\DosDevices\X:'' symbolic link.
+//
+// I suppose it is possible to take an NT object path and search
+// the targets of the items in the \DosDevices directory to see if
+// any point to it, and then test if the \DosDevices object has
+// the form of a Win32 drive letter link. Seems ugly, though.
+//
+
+typedef struct _VolumeInfoBlockType
+{
+ WCHAR wcDriveLetter;
+} VolumeInfoBlockType;
+
+
+
+//
+// MenuItemType:
+//
+
+typedef struct _MenuItemType
+{
+ WCHAR* pszMenu; // text of menu item
+ WCHAR* pszMenuHelp; // short menu item help string
+ INT iIndex;
+ IDAMenuDispatch* pMenuDispatch;
+} MenuItemType;
+
+
+//
+// MenuType:
+//
+// A menu is a counted-array of menu items. These menu items will
+// be added to the context-menu of an appropriate item (a FAT
+// volume, for instance), as well as to the menu bar as appropriate.
+//
+
+typedef struct _MenuType
+{
+ INT cMenuItems; // Number of items on the menu
+ MenuItemType* aMenuItems; //BUGBUG: should be counted array???
+ // Array of 'cMenuItems' items, in
+ //... counted-array form.
+} MenuType;
+
+
+//
+// PropPageType:
+//
+// PropPageType describes a property page, by a moniker to the
+// property page. This is required by the property engine. I
+// have no idea what a moniker to a page will ``look'' like.
+//
+
+typedef struct _PropPageType
+{
+ CLSID* pPage;
+} PropPageType;
+
+
+//
+// PropPageSetType:
+//
+// PropPageSetType describes a set of property pages, as a counted
+// array of property pages.
+//
+typedef struct _PropPageSetType
+{
+ INT cPropPages; // Count of property pages
+ PropPageType* aPropPages; //BUGBUG: should be counted array????
+ // Array of 'cPropPages' items, in
+ //... counted-array form.
+} PropPageSetType;
+
+
+
+//
+// VolumeInfoType:
+//
+// VolumeInfoType encapsulates all the data provided by a volume
+// extension class to the Disk Administrator. The data:
+//
+// pwszDescriptiveName: A descriptive name for the extension,
+// e.g. ``Norton Utilities OFS de-fragmentation''
+//
+// pwszShortName: A short name for the extension, e.g. ``Norton
+// De-frag''
+//
+// mnuOps: Information about extension operations that can be
+// put in the ``Volume'' menu of Disk Administrator, as well
+// as on the context-menu for this volume.
+//
+// propPages: Information about property sheet pages specific
+// to this format.
+//
+
+typedef struct _VolumeInfoType
+{
+ LPWSTR pwszDescriptiveName;
+ LPWSTR pwszShortName;
+ MenuType mnuOps;
+ PropPageSetType propPages;
+} VolumeInfoType;
+
+
+
+//
+// HardDiskInfoBlockType:
+//
+// This information identifies a hard disk to hard disk
+// extension code. It will contain the minimal useful
+// set of information about a hard disk, preferably only a
+// disk number. If any additional information is useful,
+// we'll add it here.
+//
+// Disk numbers start at 0, and correspond to the value of
+// N in the NT object path \Device\HardDiskN. From the NT
+// object path, one can send any number of I/O controls to
+// the driver requesting information and operations. See
+// ntdddisk.h for details.
+//
+
+typedef struct _HardDiskInfoBlockType
+{
+ ULONG ulDiskNumber;
+} HardDiskInfoBlockType;
+
+
+
+//
+// HardDiskInfoType:
+//
+// HardDiskInfoType encapsulates all the data provided by a hard
+// disk extension class to the Disk Administrator. The data:
+//
+// pwszDescriptiveName: A descriptive name for the hard disk
+// type, e.g. ``Hard disk''
+//
+// pwszShortName: A short name for the hard disk type, e.g. ``Hard''
+//
+// fCapabilities: A bitmask of capabilities:
+// DA_HD_FAULT_TOLERANT: if set, the ``hard disk'' is fault
+// tolerant. Disk Administrator will (probably) not allow
+// software fault tolerant volumes to span fault tolerant
+// hardware.
+//
+// mnuOps: Information about hard disk type operations that can
+// be put in the ``Volume'' menu of Disk Administrator, as
+// well as on the context-menu for volumes of this hardware type.
+//
+// propPages: Information about property sheet pages specific to this
+// hardware type.
+//
+
+cpp_quote("#define DA_HD_FAULT_TOLERANT 0x1")
+
+typedef struct _HardDiskInfoType
+{
+ LPWSTR pwszDescriptiveName;
+ LPWSTR pwszShortName;
+ ULONG fCapabilities;
+ MenuType mnuOps;
+ PropPageSetType propPages;
+} HardDiskInfoType;
+
+}
diff --git a/private/utils/windisk/types/dahard.idl b/private/utils/windisk/types/dahard.idl
new file mode 100644
index 000000000..bf2c1bb98
--- /dev/null
+++ b/private/utils/windisk/types/dahard.idl
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dahard.idl
+//
+// Contents: IDAHardDiskInfo interface definition
+//
+// History: 4-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+LOCAL_INTERFACE(f2eb2278-3915-101b-ab21-00000b65c03c)
+interface IDAHardDiskInfo : IUnknown
+{
+
+ //
+ // Claim: Sets *pfInterested to TRUE if this extension class
+ // wants to provide information and UI for the hard
+ // disk indicated by pInfo.
+ //
+
+ HRESULT
+ Claim(
+ [in] HardDiskInfoBlockType* pInfo,
+ [out] BOOL* pfInterested
+ );
+
+ //
+ // QueryInfo: The ppInfo pointer is filled in with the address of a
+ // structure with all the information needed when
+ // specifying a hard disk
+ //
+
+ HRESULT
+ QueryInfo(
+ [out] HardDiskInfoType** ppInfo
+ );
+}
diff --git a/private/utils/windisk/types/damenu.idl b/private/utils/windisk/types/damenu.idl
new file mode 100644
index 000000000..6dcf038cd
--- /dev/null
+++ b/private/utils/windisk/types/damenu.idl
@@ -0,0 +1,42 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: damenu.idl
+//
+// Contents: IDAMenuDispatch interface definition
+//
+// History: 7-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+LOCAL_INTERFACE(f2eb2279-3915-101b-ab21-00000b65c03c)
+interface IDAMenuDispatch : IUnknown
+{
+ //
+ // This method is used to handle extension menu operations. The
+ // arguments are as follows:
+ //
+ // hwndParent -- The parent window handle for any UI
+ // DriveName -- DOS device name for the drive, e.g., "C:"
+ // Item -- An integer indicating which menu item was invoked.
+ // The item number is the number assigned to the menu
+ // item by the extension writer, and passed to Disk
+ // Administrator via the QueryInfo method.
+ //
+ // The return value is an HRESULT, one of the following:
+ //
+ // S_OK -- No problems
+ // E_FAIL -- An error occurred. For example, the Item value might
+ // not have been understood (an internal error to the
+ // extension code), or the menu operation may have failed.
+ //
+
+ HRESULT
+ MenuDispatch(
+ [in] HWND hwndParent,
+ [in] LPWSTR DriveName,
+ [in] UINT Item
+ );
+
+}
diff --git a/private/utils/windisk/types/davol.idl b/private/utils/windisk/types/davol.idl
new file mode 100644
index 000000000..7214d7a90
--- /dev/null
+++ b/private/utils/windisk/types/davol.idl
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: davol.idl
+//
+// Contents: IDAVolumeInfo interface definition
+//
+// History: 4-Jan-94 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+LOCAL_INTERFACE(f2eb227a-3915-101b-ab21-00000b65c03c)
+interface IDAVolumeInfo : IUnknown
+{
+
+ //
+ // Claim: Sets *pfInterested to TRUE if this extension class wants
+ // to provide information and UI for the volume indicated by pInfo.
+ //
+
+ HRESULT
+ Claim(
+ [in] VolumeInfoBlockType* pInfo,
+ [out] BOOL* pfInterested
+ );
+
+ //
+ // QueryInfo: The ppInfo pointer is filled in with the address
+ // of a structure with all the information needed when specifying a
+ // volume extension
+ //
+
+ HRESULT
+ QueryInfo(
+ [out] VolumeInfoType** ppInfo
+ );
+}
diff --git a/private/utils/windisk/types/guids.h b/private/utils/windisk/types/guids.h
new file mode 100644
index 000000000..664c02da0
--- /dev/null
+++ b/private/utils/windisk/types/guids.h
@@ -0,0 +1,24 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: guids.h
+//
+// Contents: non-interface GUIDs
+//
+// History: 5-May-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+//
+// Windisk extension classes
+//
+
+DEFINE_GUID(CLSID_KDA_Hard, \
+ 0xf2eb226e, 0x3915, 0x101b, \
+ 0xab, 0x21, 0x00, 0x00, 0x0b, 0x65, 0xc0, 0x3c);
+
+DEFINE_GUID(CLSID_KDA_HardMenu, \
+ 0xf2eb226f, 0x3915, 0x101b, \
+ 0xab, 0x21, 0x00, 0x00, 0x0b, 0x65, 0xc0, 0x3c);
diff --git a/private/utils/windisk/types/readme.txt b/private/utils/windisk/types/readme.txt
new file mode 100644
index 000000000..8871b3f3d
--- /dev/null
+++ b/private/utils/windisk/types/readme.txt
@@ -0,0 +1,2 @@
+This directory contains the "types" information used to define the Disk
+Administrator extension interfaces.
diff --git a/private/utils/windisk/util/debug.cxx b/private/utils/windisk/util/debug.cxx
new file mode 100644
index 000000000..f1a789c68
--- /dev/null
+++ b/private/utils/windisk/util/debug.cxx
@@ -0,0 +1,95 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: debug.cxx
+//
+// Contents: Debug helper routines
+//
+// Functions:
+// FormatGuid
+// DumpGuid
+//
+// History: 20-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#ifdef WINDISK_EXTENSIONS
+
+#include "headers.hxx"
+
+#include <util.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: FormatGuid
+//
+// Synopsis: Format a GUID into a string for possible printing. The
+// string must be GUID_STRING_LEN characters long.
+//
+// Arguments: IN [guid] -- a GUID
+// OUT [wszGuid] -- string representation of GUID
+//
+// Returns: nothing
+//
+// History: 20-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+FormatGuid(
+ IN const GUID& guid,
+ OUT PWSTR GuidString
+ )
+{
+ wsprintf(GuidString,
+ TEXT("%08lx-%04hx-%04hx-%02x%02x%02x%02x%02x%02x%02x%02x"),
+ guid.Data1,
+ guid.Data2,
+ guid.Data3,
+ guid.Data4[0],
+ guid.Data4[1],
+ guid.Data4[2],
+ guid.Data4[3],
+ guid.Data4[4],
+ guid.Data4[5],
+ guid.Data4[6],
+ guid.Data4[7]);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DumpGuid
+//
+// Synopsis: Dump a guid to the debugger
+//
+// Arguments: IN [Level] -- debug level, e.g. DEB_ITRACE
+// IN [Message] -- a message to precede the guid
+// IN [guid] -- the GUID
+//
+// Returns: nothing
+//
+// History: 11-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+DumpGuid(
+ IN UINT Level,
+ IN PWSTR Message,
+ IN const GUID& guid
+ )
+{
+ WCHAR wszGuid[GUID_STRING_LEN];
+
+ FormatGuid(guid, wszGuid);
+ daDebugOut((Level, "%ws%ws\n", Message, wszGuid));
+}
+
+#endif // WINDISK_EXTENSIONS
+
+#endif // DBG == 1
diff --git a/private/utils/windisk/util/headers.hxx b/private/utils/windisk/util/headers.hxx
new file mode 100644
index 000000000..756a6a06c
--- /dev/null
+++ b/private/utils/windisk/util/headers.hxx
@@ -0,0 +1,32 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.hxx
+//
+// Contents: Headers for windisk utilities library.
+//
+// History: 14-Jan-94 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntddnfs.h>
+}
+
+#include <windows.h>
+#include <windowsx.h>
+
+#ifdef WINDISK_EXTENSIONS
+// #include <ole2.h> // GUID definition
+#endif // WINDISK_EXTENSIONS
+
+#include <stdlib.h>
+#include <debug.h>
+
+#include <dacommon.h>
diff --git a/private/utils/windisk/util/makefile b/private/utils/windisk/util/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/utils/windisk/util/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/utils/windisk/util/sources b/private/utils/windisk/util/sources
new file mode 100644
index 000000000..ab12ffb1b
--- /dev/null
+++ b/private/utils/windisk/util/sources
@@ -0,0 +1,17 @@
+!include ..\windisk.mk
+
+MINORCOMP= util
+
+TARGETNAME= util
+TARGETPATH= obj
+TARGETTYPE= LIBRARY
+
+UMTYPE= windows
+
+INCLUDES=\
+ ..\inc; \
+ $(INCLUDES)
+
+SOURCES=\
+ debug.cxx \
+ util.cxx
diff --git a/private/utils/windisk/util/util.cxx b/private/utils/windisk/util/util.cxx
new file mode 100644
index 000000000..ca47cfd09
--- /dev/null
+++ b/private/utils/windisk/util/util.cxx
@@ -0,0 +1,427 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: util.cxx
+//
+// Contents: Utility routines
+//
+// History: 26-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.hxx"
+
+#define MAX_RESOURCE_STRING_LEN 256
+#define MAXLABELLEN 256
+#define MAXTITLELEN 256
+#define MAXMESSAGELEN 350
+#define MAXERRORLEN 256
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MyMessageBox
+//
+// Synopsis: Same as Win32 MessageBox, but takes resource identifiers
+// and loads the strings to display from the resource file.
+// Also, the message box is made task-modal.
+//
+// Arguments: [hInstance] -- the instance to load the strings from
+// [hwndOwner] -- handle of owner window
+// [idTitle] -- resource ID of message box title string
+// [idMessage] -- resource ID of message box message string
+// [fuStyle] -- style of message box (see MessageBox() API)
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+INT
+MyMessageBox(
+ IN HINSTANCE hInstance,
+ IN HWND hwndOwner,
+ IN DWORD idMessage,
+ IN DWORD idTitle,
+ IN UINT fuStyle
+ )
+{
+ TCHAR szTitle[MAXTITLELEN];
+ TCHAR szMessage[MAXMESSAGELEN];
+
+ LoadString(hInstance, idTitle, szTitle, ARRAYLEN(szTitle));
+ LoadString(hInstance, idMessage, szMessage, ARRAYLEN(szMessage));
+
+ return MessageBox(hwndOwner, szMessage, szTitle, fuStyle);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MySetDlgItemText
+//
+// Synopsis: Same as Win32 SetDlgItemText, but takes a resource ID
+// instead of a string pointer.
+//
+// Arguments: [hInstance] -- the instance to load the strings from
+// [hwndDlg] -- handle of dialog box
+// [idControl] -- identifier of control
+// [wID] -- resource identifier
+//
+// Returns: return TRUE on success
+//
+// History: 8-Sep-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+MySetDlgItemText(
+ IN HINSTANCE hInstance,
+ IN HWND hwndDlg,
+ IN int idControl,
+ IN UINT wID
+ )
+{
+ WCHAR szBuf[MAX_RESOURCE_STRING_LEN];
+
+ int cch = LoadString(
+ hInstance,
+ wID,
+ szBuf,
+ ARRAYLEN(szBuf));
+
+ return (0 != cch) && SetDlgItemText(hwndDlg, idControl, szBuf);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FindCenterValues
+//
+// Synopsis: Calculate the values for use in centering a window
+//
+// Arguments: [hwndToCenter] -- the window to center
+// [hwndContext] -- the window to center with respect to.
+// If NULL, center with respect to the screen.
+//
+// [px] -- x value
+// [py] -- y value
+// [pw] -- width value
+// [ph] -- height value
+//
+// Returns: none
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+FindCenterValues(
+ IN HWND hwndToCenter,
+ IN HWND hwndContext,
+ OUT PLONG px,
+ OUT PLONG py,
+ OUT PLONG pw,
+ OUT PLONG ph
+ )
+{
+ RECT rcContext,rcWindow;
+ LONG x,y,w,h;
+ POINT pt;
+ LONG sx = GetSystemMetrics(SM_CXSCREEN);
+ LONG sy = GetSystemMetrics(SM_CYSCREEN);
+
+ pt.x = pt.y = 0;
+ if (hwndContext)
+ {
+ ClientToScreen(hwndContext,&pt);
+ GetClientRect (hwndContext,&rcContext);
+ }
+ else
+ {
+ rcContext.top = rcContext.left = 0;
+ rcContext.right = sx;
+ rcContext.bottom = sy;
+ }
+
+ GetWindowRect(hwndToCenter,&rcWindow);
+
+ w = rcWindow.right - rcWindow.left;
+ h = rcWindow.bottom - rcWindow.top;
+ x = pt.x + ((rcContext.right - rcContext.left - w) / 2);
+ y = pt.y + ((rcContext.bottom - rcContext.top - h) / 2);
+
+ if (x + w > sx)
+ {
+ x = sx - w;
+ }
+ else if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (y + h > sy)
+ {
+ y = sy - h;
+ }
+ else if (y < 0)
+ {
+ y = 0;
+ }
+
+ *px = x;
+ *py = y;
+ *pw = w;
+ *ph = h;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CenterWindow
+//
+// Synopsis: Center a window with respect to a given parent or the screen
+//
+// Arguments: [hwndToCenter] -- the window to center
+// [hwndContext] -- the window to center with respect to.
+// If NULL, center with respect to the screen.
+//
+// Returns: none
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+VOID
+CenterWindow(
+ IN HWND hwndToCenter,
+ IN HWND hwndContext
+ )
+{
+ LONG x,y,w,h;
+
+ FindCenterValues(hwndToCenter, hwndContext, &x, &y, &w, &h);
+
+ if (FALSE == MoveWindow(hwndToCenter,x,y,w,h,FALSE))
+ {
+ daDebugOut((DEB_TRACE,"MoveWindow failed\n"));
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InsertSeparators
+//
+// Synopsis: Insert separators ( ',' or '.', probably ) every three
+// digits in a number (thousands, millions, etc).
+//
+// Arguments: [Number] -- String representation of an integer to
+// insert separators in. The number is assumed to simply
+// be an array of digits. The buffer must be big
+// enough to have separators inserted every third character.
+//
+// Returns: nothing
+//
+// History: 15-Dec-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+InsertSeparators(
+ IN OUT PWCHAR Number
+ )
+{
+ WCHAR szSeparator[10];
+ WCHAR Separator;
+
+ if (0 != GetLocaleInfoW(
+ GetUserDefaultLCID(),
+ LOCALE_STHOUSAND,
+ szSeparator,
+ ARRAYLEN(szSeparator)
+ ))
+ {
+ Separator = szSeparator[0];
+ }
+ else
+ {
+ Separator = L',';
+ }
+
+ WCHAR Buffer[100];
+ ULONG cchNumber = lstrlen(Number);
+ UINT Triples = 0;
+
+ Buffer[99] = L'\0';
+ PWCHAR pch = &Buffer[98];
+
+ while (cchNumber > 0)
+ {
+ *pch-- = Number[--cchNumber];
+
+ ++Triples;
+ if ( (0 == (Triples % 3)) && (cchNumber > 0) )
+ {
+ *pch-- = Separator;
+ }
+ }
+
+ lstrcpy(Number, pch + 1); // the Number buffer better be able to handle it!
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDeviceObject, public
+//
+// Synopsis: Given a drive letter, return the NT object space device
+// path corresponding to that drive letter. Basically,
+// traverse the \DosDevices\<Drive Letter>: symbolic link.
+//
+// Arguments: IN [wcDrive] -- Unicode drive letter
+// OUT [pszDevPath] -- where to put the NT object path
+// IN [cchDevPath] -- length of [pszDevPath] in characters
+//
+// Returns: TRUE if succeeded, FALSE if failed (e.g., the drive letter is
+// unrecognized)
+//
+// History: 19-May-93 BruceFo Created
+//
+//--------------------------------------------------------------------------
+
+BOOL
+GetDeviceObject(
+ IN WCHAR wcDrive,
+ OUT LPWSTR pszDevPath,
+ IN DWORD cchDevPath)
+{
+ NTSTATUS Status;
+ HANDLE hSymbolicLink;
+ WCHAR wszLinkName[_MAX_DRIVE+1]; // the +1 is for a backslash
+ UNICODE_STRING ustrLinkName;
+ UNICODE_STRING ustrLinkTarget;
+ OBJECT_ATTRIBUTES LinkAttributes;
+
+ wszLinkName[0] = wcDrive;
+ wszLinkName[1] = L':';
+ wszLinkName[2] = L'\\';
+ wszLinkName[3] = L'\0'; // wszLinkName = L"X:\"
+ _wcsupr(wszLinkName);
+
+ //
+ // Construct the link name by calling RtlDosPathNameToNtPathName, and
+ // strip of the trailing backslash. At the end of this, ustrLinkName
+ // should be of the form \DosDevices\X:
+ //
+
+ RtlDosPathNameToNtPathName_U(wszLinkName, &ustrLinkName, NULL, NULL);
+ ustrLinkName.Length -= sizeof(WCHAR);
+
+ InitializeObjectAttributes(
+ &LinkAttributes,
+ &ustrLinkName,
+ OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+ NULL,
+ NULL);
+
+ Status = NtOpenSymbolicLinkObject(
+ &hSymbolicLink,
+ GENERIC_READ,
+ &LinkAttributes
+ );
+ if (!NT_SUCCESS(Status))
+ {
+ // No Link
+ return(FALSE);
+ }
+
+ //
+ // Get the link target
+ //
+
+ ustrLinkTarget.Length = 0;
+ ustrLinkTarget.MaximumLength = (USHORT)(cchDevPath * sizeof(WCHAR));
+ // Length & MaximumLength are USHORTs
+
+ ustrLinkTarget.Buffer = pszDevPath;
+
+ Status = NtQuerySymbolicLinkObject(
+ hSymbolicLink,
+ &ustrLinkTarget // Name of Link's Target obj.
+ ,NULL
+ );
+ NtClose(hSymbolicLink);
+
+ return (NT_SUCCESS(Status)) ? TRUE : FALSE;
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Function: BUGBUG: NoHelp
+//
+// Synopsis: until we have help, do this
+//
+// Arguments: [hwndOwner] -- owner window
+//
+// Returns: nothing
+//
+// History: 16-Aug-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+NoHelp(
+ IN HWND hwndOwner
+ )
+{
+ MessageBox(
+ hwndOwner,
+ TEXT("No help available yet"),
+ TEXT("Help"),
+ MB_ICONINFORMATION | MB_OK
+ );
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BUGBUG: Unimplemented
+//
+// Synopsis: for unimplemented features
+//
+// Arguments: [hwndOwner] -- owner window
+//
+// Returns: nothing
+//
+// History: 9-Nov-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+VOID
+Unimplemented(
+ IN HWND hwndOwner
+ )
+{
+ MessageBox(
+ hwndOwner,
+ TEXT("Unimplemented feature"),
+ TEXT("Sorry"),
+ MB_ICONINFORMATION | MB_OK
+ );
+}
diff --git a/private/utils/windisk/util/util.hxx b/private/utils/windisk/util/util.hxx
new file mode 100644
index 000000000..4a764aaff
--- /dev/null
+++ b/private/utils/windisk/util/util.hxx
@@ -0,0 +1,100 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: util.hxx
+//
+// Contents: Utility routines for Cairo Disk Administrator
+//
+// History: 20-May-93 BruceFo Created
+//
+//----------------------------------------------------------------------------
+
+
+//
+// util.cxx functions
+//
+
+INT
+MyMessageBox(
+ IN HINSTANCE hInstance,
+ IN HWND hwndOwner,
+ IN DWORD idMessage,
+ IN DWORD idTitle,
+ IN UINT fuStyle
+ );
+
+BOOL
+MySetDlgItemText(
+ IN HINSTANCE hInstance,
+ IN HWND hwndDlg,
+ IN int idControl,
+ IN UINT wID
+ );
+
+VOID
+FindCenterValues(
+ IN HWND hwndToCenter,
+ IN HWND hwndContext,
+ OUT PLONG px,
+ OUT PLONG py,
+ OUT PLONG pw,
+ OUT PLONG ph
+ );
+
+VOID
+CenterWindow(
+ IN HWND hwndToCenter,
+ IN HWND hwndContext
+ );
+
+VOID
+InsertSeparators(
+ IN OUT PWCHAR Number
+ );
+
+VOID
+NoHelp(
+ IN HWND hwndOwner
+ );
+
+VOID
+Unimplemented(
+ IN HWND hwndOwner
+ );
+
+BOOL
+GetDeviceObject(
+ IN WCHAR wcDrive,
+ OUT LPWSTR pszDevPath,
+ IN DWORD cchDevPath
+ );
+
+
+#if DBG == 1
+
+#ifdef WINDISK_EXTENSIONS
+
+//
+// debug.cxx functions
+//
+
+#define GUID_STRING_LEN 36
+
+VOID
+FormatGuid(
+ IN const GUID& guid,
+ OUT PWSTR GuidString
+ );
+
+VOID
+DumpGuid(
+ IN UINT Level,
+ IN PWSTR Message,
+ IN const GUID& guid
+ );
+
+#endif // WINDISK_EXTENSIONS
+
+#endif // DBG == 1
diff --git a/private/utils/windisk/windisk.mk b/private/utils/windisk/windisk.mk
new file mode 100644
index 000000000..76464ae54
--- /dev/null
+++ b/private/utils/windisk/windisk.mk
@@ -0,0 +1,9 @@
+USE_CRTDLL= 1
+
+MSC_WARNING_LEVEL=/W3 /WX
+C_DEFINES= $(C_DEFINES) -DUNICODE -D_UNICODE -DWINVER=0x0400
+
+MAJORCOMP= windisk
+
+INCLUDES=\
+ ..\debug