Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
861 changes: 431 additions & 430 deletions Ext2Mgr/Ext2Mgr.vcxproj

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions Ext2Mgr/IMPROVEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Ext2Mgr / Ext2Srv — classic stack improvements

Fixes and service changes that apply to the **regular** MFC **Ext2 Volume Manager** (`Ext2Mgr/`) and/or **Ext2Srv**, independent of the Iced port.

Rebuild Ext2Mgr / reinstall Ext2Srv (`Scripts\build.ps1`, `Scripts\install_driver.ps1`) to pick these up. Optional Iced GUI comparisons live on the `ext2mgr-iced` branch under `ext2mgr_iced/PORT_IMPROVEMENTS.md`.

---

## Ext2Mgr (`Ext2Mgr/`)

### Change Drive Letters — crash on non-EXT / Session Manager

**Symptom:** Choosing **Session Manager DOS Devices** (or temporary DOS devices) for an NTFS/FAT partition could crash Ext2Mgr.

**Cause:** `CMountPoints::AddMountPoint` in `MountPoints.cpp`:

1. On successful Session Manager registry write it called `EndDialog(0)` **without returning**, so execution continued.
2. It always ran `Ext2QueryExt2Property(Handle, EVP)` to store Ext2Fsd automount properties.
3. For a **partition-selected** native volume, `EVP` stayed **NULL** (only set from `m_Volume` or an EXT `m_Part->Volume` branch) → null dereference.

**Fix:**

- `return TRUE` immediately after a successful Session Manager assign + `EndDialog`.
- If `EVP` is NULL, **skip** the Ext2 property IOCTL path and only assign the DOS letter (`Ext2AssignDrvLetter`), then update letter masks / notify.

**Note:** Classic assign remains `DefineDosDevice` to `\Device\HarddiskVolumeN` (same path Session Manager uses). This fix is **crash safety** only.

---

## Ext2Srv (`Ext2Srv/`)

These pipe-server changes help **both** Ext2Mgr and `ext2mgr_iced` (temporary EXT letter ops via `\\.\pipe\EXT2MGR_PSRV`).

| Change | File | What |
|--------|------|------|
| Dual idle pipe listeners | `Ext2Pipe.cpp` (`Ext2StartPipeSrv`) | Second `Ext2PipeEngine` thread so reconnect / overlap rarely hits `ERROR_PIPE_BUSY` |
| Soft create retries | `Ext2Pipe.cpp` (`Ext2PipeEngine`) | Cap create failures at 3×50ms (+ short sleep) instead of long backoff storms |
| No `FILE_FLAG_WRITE_THROUGH` | `Ext2Pipe.cpp` (`Ext2CreatePipe`) | Dropped on tiny IPC messages; measured after reinstall (2026-07-28): cold connect median ~0.7 ms, burst reconnect ~0.2 ms, `QUERY_DRV` ~0.1 ms (query-only probe) |

---

## Intentionally not changed here

| Topic | Status |
|-------|--------|
| Mount Manager for NTFS in classic Ext2Mgr | Not needed for Explorer when Session Manager / DosDevice targets `\Device\HarddiskVolumeN`. Classic UI still forces DosDev (`#if TRUE` in `MountPoints.cpp`). |
| EXT-only “Assign Drive Letter” gating | Iced-only (classic still offers assign more broadly and can wait on Ext2Srv). |
| Dead-letter detection breadth | Iced lists more orphans; classic logic unchanged. |

---

## Related docs

- [`../README.md`](../README.md) — fork build/install scripts and driver changelog
- `ext2mgr_iced/` on branch `ext2mgr-iced` — optional Iced GUI port
38 changes: 37 additions & 1 deletion Ext2Mgr/MountPoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ CMountPoints::AddMountPoint(
if (Ext2SetRegistryMountPoint(&drvChar, devPath, bRegistry)) {
Ext2AssignDrvLetter(drvLetter, devPath, FALSE);
EndDialog(0);
return TRUE;
} else {
str.Format("Failed to modify registry: SYSTEM\\CurrentControlSet\\Control\\Session Manager\\DOS Devices\n");
AfxMessageBox(str, MB_OK|MB_ICONWARNING);
Expand Down Expand Up @@ -152,7 +153,42 @@ CMountPoints::AddMountPoint(
}
}

/* create an entry in regisgtry */
/* Ext2 property IOCTL — only for EXT volumes (EVP non-NULL).
NTFS/FAT hit this path via Change Drive Letters and used to crash
on Ext2QueryExt2Property(NULL). Assign the DOS letter only. */
if (!EVP) {
rc = Ext2AssignDrvLetter(drvLetter, devPath, bMountMgr);
if (!rc && !bMountMgr) {
CString str;
str.Format("Failed to assign new drive letter %c:\n", drvChar);
AfxMessageBox(str, MB_OK|MB_ICONWARNING);
return FALSE;
}
if (rc) {
m_bUpdated = TRUE;
if (m_Part) {
m_Part->DrvLetters |= letterMask;
if (m_Part->Volume) {
m_Part->Volume->DrvLetters |= letterMask;
}
InitializeList(m_Part->DrvLetters);
}
if (m_Volume) {
m_Volume->DrvLetters |= letterMask;
InitializeList(m_Volume->DrvLetters);
}
if (m_Cdrom) {
m_Cdrom->DrvLetters |= letterMask;
InitializeList(m_Cdrom->DrvLetters);
}
m_MainDlg->SendMessage(
WM_MOUNTPOINT_NOTIFY,
'DA', (LPARAM)drvLetter->Letter);
}
return rc;
}

/* create an entry in registry (EXT only) */
{

NT::NTSTATUS status;
Expand Down
17 changes: 11 additions & 6 deletions Ext2Srv/Ext2Pipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ Ext2CreatePipe()

sa = Ext2CreateSA();

ap->p = CreateNamedPipe( _T(EXT2_MGR_SRV), PIPE_ACCESS_DUPLEX |
FILE_FLAG_WRITE_THROUGH /* | ACCESS_SYSTEM_SECURITY */,
ap->p = CreateNamedPipe( _T(EXT2_MGR_SRV), PIPE_ACCESS_DUPLEX,
/* no WRITE_THROUGH: tiny IPC messages; measure if needed */
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
PIPE_WAIT /* PIPE_REJECT_REMOTE_CLIENTS */ ,
PIPE_UNLIMITED_INSTANCES,
Expand Down Expand Up @@ -429,21 +429,23 @@ Ext2PipeEngine(VOID *arg)
/* create named pipe */
ap = Ext2CreatePipe();
if (NULL == ap) {
if (times++ < 10) {
Sleep(250 * times);
if (times++ < 3) {
Sleep(50);
goto retry;
}
Sleep(100);
continue;
}

/* ASSD_PIPE is valid or not */
if (!ap->p || ap->p == INVALID_HANDLE_VALUE ||
!ap->e || ap->e == INVALID_HANDLE_VALUE) {
Ext2DestroyPipe(ap);
if (times++ < 10) {
Sleep(500);
if (times++ < 3) {
Sleep(50);
goto retry;
}
Sleep(100);
continue;
}

Expand Down Expand Up @@ -498,6 +500,9 @@ DWORD Ext2StartPipeSrv()
rc = WaitForSingleObject(g_wait, 1000*1);
} while (rc == WAIT_TIMEOUT);

/* Second idle listener so a reconnect/overlap rarely hits PIPE_BUSY. */
_beginthread(Ext2PipeEngine, 0, NULL);

return 0;
}

Expand Down
5 changes: 3 additions & 2 deletions Ext2Srv/Ext2Srv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,14 @@ Ext2SetupService(BOOL bInstall)
if (bInstall) {

// now create service entry for Ext2Mgr
// Note: SERVICE_INTERACTIVE_PROCESS removed - interactive services are deprecated
// and don't work on modern Windows (can't create named pipes accessible to user sessions)
hService = CreateService(
hManager, // SCManager database
_T("Ext2Srv"), // name of service
_T("Ext2Fsd Service Manager"), // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS | // service type
SERVICE_INTERACTIVE_PROCESS,
SERVICE_WIN32_OWN_PROCESS, // service type (removed SERVICE_INTERACTIVE_PROCESS)
SERVICE_AUTO_START, // start type
SERVICE_ERROR_NORMAL, // error control type
Target, // service's binary
Expand Down
8 changes: 4 additions & 4 deletions Ext2Srv/Ext2Srv.rc
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,71,1
PRODUCTVERSION 1,4,71,1
FILEVERSION 1,4,71,2
PRODUCTVERSION 1,4,71,2
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -85,12 +85,12 @@ BEGIN
VALUE "Comments", "Bo Branten <bosse@accum.se>"
VALUE "CompanyName", "Ext2Fsd Group (www.ext2fsd.com)"
VALUE "FileDescription", "Ext2Fsd Service"
VALUE "FileVersion", "1.4.71.1"
VALUE "FileVersion", "1.4.71.2"
VALUE "InternalName", "Ext2Srv"
VALUE "LegalCopyright", "Copyright (C) 2002-2017 Matt Wu <matt@ext2fsd.com>"
VALUE "OriginalFilename", "Ext2Srv.exe"
VALUE "ProductName", "Ext2Fsd Service"
VALUE "ProductVersion", "1.4.71.1"
VALUE "ProductVersion", "1.4.71.2"
END
END
BLOCK "VarFileInfo"
Expand Down
Loading