Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Li Keqing committed Feb 11, 2023
0 parents commit 957b12c
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.vscode/
*.o
*.res
*.exe
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ARCH:=x86_64
CC=$(ARCH)-w64-mingw32-gcc
WINDRES=$(ARCH)-w64-mingw32-windres
CFLAGS=-municode -O2
LDFLAGS=$(CFLAGS) -mconsole -lwinmm -ldismapi

all: enabler

%.res: %.rc
$(WINDRES) -o $@ -i $<

%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)

enabler: main.o resource.res
$(CC) -o enabler.exe main.o resource.res $(LDFLAGS)

clean:
$(RM) resource.res
$(RM) main.o
$(RM) enabler.exe

.PHONY: all
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# ReFS Enabler (Untested)
Patch `boot.wim` to enable Windows 11 or Windows Server vNext to be able to install on ReFS partitions natively.
## Usage
1. Extract or copy `boot.wim` from installation media(ISO or USB drive).
2. Download latest prebuilt package from [Releases](https://github.com/QianNangong/ReFS-Enabler/releases) page.
3. Drop `boot.wim` into `enabler.exe`.
4. Copy `boot.wim` back into the installation media.
5. Done!
## System requirements
Any Windows OS from Windows 7.
## Suitable image version
- Windows 11 build 25281
- Windows Server vNext build 25284
21 changes: 21 additions & 0 deletions admin.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="ReFS Enabler"
type="win32"/>

<description>Description of your application</description>

<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
173 changes: 173 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <windows.h>
#include <dismapi.h>

#include <stdio.h>
#include <string.h>

static const WCHAR CHARSET[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

UINT WINAPI GenerateRandomString(PWSTR lpBuffer, UINT* dwLength)
{
if (*dwLength == 0)
{
*dwLength = 8;
}
for (UINT i = 0; i < *dwLength; ++i)
{
lpBuffer[i] = CHARSET[rand() % (sizeof(CHARSET) / sizeof(WCHAR))];
}
return *dwLength;
}

PWSTR WINAPI GetTempMountPath(void)
{
static WCHAR szTempMountPath[32767] = { 0 };
if (szTempMountPath[0] != L'\0')
{
return szTempMountPath;
}
WCHAR szSysTempPath[MAX_PATH];
GetTempPathW(MAX_PATH, szSysTempPath);
WCHAR szTempBuf[9] = { 0 };
UINT nCount = 8;
GenerateRandomString(szTempBuf, &nCount);
snwprintf(szTempMountPath, 32767, L"\\\\?\\%s\\%s", szSysTempPath, szTempBuf);
if (!CreateDirectoryW(szTempMountPath, NULL))
{
szTempMountPath[0] = '\0';
return GetTempMountPath();
}
return szTempMountPath;
}

PWSTR WINAPI MountImage(PCWSTR pWimFile, UINT nIndex)
{
if (FAILED(DismMountImage(pWimFile, GetTempMountPath(), nIndex, NULL, DismImageIndex, DISM_MOUNT_READWRITE, NULL, NULL, NULL)))
{
return NULL;
}
return GetTempMountPath();
}

BOOL WINAPI EnableReFSInRegistry(PCWSTR pMountPath)
{
HKEY hSystemRootKey = INVALID_HANDLE_VALUE;
HKEY hFeatureKey = INVALID_HANDLE_VALUE;
WCHAR szRegistryKeyFile[32768] = { 0 };
snwprintf(szRegistryKeyFile, 32767, L"%s\\Windows\\System32\\config\\SYSTEM");
LRESULT lr = RegLoadAppKeyW(szRegistryKeyFile, &hSystemRootKey, KEY_ALL_ACCESS, REG_PROCESS_APPKEY, 0);
if (lr != ERROR_SUCCESS || hSystemRootKey == INVALID_HANDLE_VALUE)
{

return FALSE;
}
lr = RegCreateKeyExW(hSystemRootKey, L"ControlSet001\\Control\\FeatureManagement\\Overrides\\8\\3689412748", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hFeatureKey, NULL);
if (lr != ERROR_SUCCESS || hFeatureKey == INVALID_HANDLE_VALUE)
{
RegCloseKey(hSystemRootKey);
return FALSE;
}
const DWORD dwEnabledState = 2;
const DWORD dwEnabledStateOptions = 0;
RegSetKeyValueW(hFeatureKey, NULL, L"EnabledState", REG_DWORD, &dwEnabledState, sizeof(DWORD));
RegSetKeyValueW(hFeatureKey, NULL, L"EnabledStateOptions", REG_DWORD, &dwEnabledStateOptions, sizeof(DWORD));
RegCloseKey(hFeatureKey);
RegCloseKey(hFeatureKey);
return TRUE;
}

BOOL WINAPI UnmountImage(PCWSTR pMountPath)
{
return SUCCEEDED(DismUnmountImage(pMountPath, DISM_COMMIT_IMAGE, NULL, NULL, NULL));
}

UINT WINAPI EnableReFS(PCWSTR pWimFile)
{
UINT nImgCount = 0;
DismImageInfo* pImgInfo = NULL;
if (FAILED(DismGetImageInfo(pWimFile, &pImgInfo, &nImgCount)))
{
fwprintf(stderr, L"Failed to open wim file %s. HRESULT = 0x%08lX", pWimFile, GetLastError());
return 0;
}
if (nImgCount == 0)
{
fwprintf(stderr, L"No suitable image found in %s.", pWimFile);
return 0;
}
UINT nEnabled = 0;
for (UINT i = 0; i < nImgCount; ++i)
{
BOOL bSuccess = TRUE;
DismImageInfo info = pImgInfo[i];
if (info.MajorVersion < 10 || info.Build < 25281 || !lstrcmpW(L"WindowsPE", info.EditionId) || !lstrcmpW(L"WindowsPE", info.InstallationType))
{
continue;
}
fwprintf(stdout, L"Enable ReFS Installation on image \"%s\" #%u...\r\n", info.ImageName, info.ImageIndex);
PWSTR pszMountPath = MountImage(pWimFile, i);
if (pszMountPath == NULL)
{
fwprintf(stderr, L"[#%u] Failed to mount image. HRESULT = 0x%08lX\r\n", info.ImageIndex, GetLastError());
continue;
}
else
{
fwprintf(stdout, L"[#%u] Image mounted.\r\n", info.ImageIndex);
}
if (!EnableReFSInRegistry(pszMountPath))
{
fwprintf(stderr, L"[#%u] Failed to enable ReFS in registry. HRESULT = 0x%08lx\r\n", info.ImageIndex, GetLastError());
bSuccess = FALSE;
}
else
{
fwprintf(stdout, L"[#%u] Feature 42189933 enabled.\r\n", info.ImageIndex);
}
if (!UnmountImage(pszMountPath))
{
fwprintf(stderr, L"[#%u] Failed to unmount image. HRESULT = 0x%08lx\r\n", info.ImageIndex, GetLastError());
continue;
}
else
{
fwprintf(stdout, L"[#%u] Image committed and unmounted.\r\n", info.ImageIndex);
}
if (bSuccess)
{
++nEnabled;
}
}
DismDelete(pImgInfo);
RemoveDirectoryW(GetTempMountPath());
return nEnabled;
}

int wmain(int argc, const wchar_t* argv[])
{
if (argc != 2)
{
fwprintf(stderr, L"Usage:\r\n\t%s path\\to\\boot.wim", argv[0]);
return 0;
}

if (FAILED(DismInitialize(DismLogErrorsWarnings, NULL, NULL)))
{
fwprintf(stderr, L"Failed to initialize Dism. HRESULT = 0x%08lX", GetLastError());
return 0;
}
srand((unsigned int)timeGetTime());
WCHAR szWimFile[32768] = { 0 };
snwprintf(szWimFile, 32767, L"\\\\?\\%s", argv[1]);
UINT nEnabled = EnableReFS(szWimFile);
if (nEnabled != 0)
{
fwprintf(stdout, L"Done! %d image%s enabled.", nEnabled, nEnabled == 1 ? L"": L"s");
}
else
{
fwprintf(stderr, L"No suitable image found in %s.", argv[1]);
}
DismShutdown();
return 0;
}
2 changes: 2 additions & 0 deletions resource.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include <windows.h>
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "admin.manifest"

0 comments on commit 957b12c

Please sign in to comment.