mirror of
https://github.com/reactos/reactos.git
synced 2025-04-22 05:00:27 +00:00
[SETUP:REACTOS] Adapt the 1st-stage GUI setup to compile with the setuplib.
svn path=/branches/setup_improvements/; revision=75544 [SETUP:REACTOS] More interfacing of the 1st-stage GUI installer with the setuplib. - Add a ConvertNtPathToWin32Path() helper function that allows converting NT paths like: \Device\CdRom0\i386\txtsetup.sif file into a Win32 path that the Win32 versions of the SetupApi functions (e.g. SetupOpenInfFileW) can accept. Note that RtlNtPathNameToDosPathName() cannot be used here because this function only works for NT paths within the \DosDevices\ (or \??\) NTObj directory, and not in other directories. - Use this helper function in the implementation of SetupOpenInfFileExW. Now the txtsetup.sif function can be loaded by setuplib *when being used* by the 1st-stage GUI installer! - Remove deprecated code. svn path=/branches/setup_improvements/; revision=75668 svn path=/branches/setup_improvements/; revision=75721 svn path=/branches/setup_improvements/; revision=75750
This commit is contained in:
parent
9c64b57dc9
commit
82117d2192
5 changed files with 313 additions and 155 deletions
|
@ -1,14 +1,22 @@
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../lib
|
||||||
|
# ${REACTOS_SOURCE_DIR}/base/setup/lib
|
||||||
|
${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib
|
||||||
|
${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
drivepage.c
|
drivepage.c
|
||||||
|
inffile.c
|
||||||
reactos.c
|
reactos.c
|
||||||
reactos.h)
|
reactos.h)
|
||||||
|
|
||||||
file(GLOB reactos_rc_deps res/*.*)
|
file(GLOB reactos_rc_deps res/*.*)
|
||||||
add_rc_deps(reactos.rc ${reactos_rc_deps})
|
add_rc_deps(reactos.rc ${reactos_rc_deps})
|
||||||
add_executable(reactos ${SOURCE} reactos.rc)
|
add_executable(reactos ${SOURCE} reactos.rc)
|
||||||
add_pch(reactos reactos.h SOURCE)
|
|
||||||
target_link_libraries(reactos uuid)
|
|
||||||
set_module_type(reactos win32gui UNICODE)
|
set_module_type(reactos win32gui UNICODE)
|
||||||
|
add_pch(reactos reactos.h SOURCE)
|
||||||
|
target_link_libraries(reactos uuid setuplib ext2lib vfatlib btrfslib)
|
||||||
add_importlibs(reactos advapi32 gdi32 user32 comctl32 setupapi msvcrt kernel32 ntdll)
|
add_importlibs(reactos advapi32 gdi32 user32 comctl32 setupapi msvcrt kernel32 ntdll)
|
||||||
add_cd_file(TARGET reactos DESTINATION reactos NO_CAB FOR bootcd)
|
add_cd_file(TARGET reactos DESTINATION reactos NO_CAB FOR bootcd)
|
||||||
|
|
|
@ -57,7 +57,7 @@ MoreOptDlgProc(HWND hwndDlg,
|
||||||
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
|
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
|
||||||
WM_SETTEXT,
|
WM_SETTEXT,
|
||||||
(WPARAM)0,
|
(WPARAM)0,
|
||||||
(LPARAM)pSetupData->InstallDir);
|
(LPARAM)pSetupData->USetupData.InstallationDirectory);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
|
@ -66,8 +66,8 @@ MoreOptDlgProc(HWND hwndDlg,
|
||||||
case IDOK:
|
case IDOK:
|
||||||
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
|
SendMessage(GetDlgItem(hwndDlg, IDC_PATH),
|
||||||
WM_GETTEXT,
|
WM_GETTEXT,
|
||||||
(WPARAM)sizeof(pSetupData->InstallDir) / sizeof(TCHAR),
|
(WPARAM)sizeof(pSetupData->USetupData.InstallationDirectory) / sizeof(TCHAR),
|
||||||
(LPARAM)pSetupData->InstallDir);
|
(LPARAM)pSetupData->USetupData.InstallationDirectory);
|
||||||
|
|
||||||
EndDialog(hwndDlg, IDOK);
|
EndDialog(hwndDlg, IDOK);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
89
base/setup/reactos/inffile.c
Normal file
89
base/setup/reactos/inffile.c
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS text-mode setup
|
||||||
|
* FILE: base/setup/usetup/inffile.c
|
||||||
|
* PURPOSE: .inf files support functions
|
||||||
|
* PROGRAMMERS: Hervé Poussineau
|
||||||
|
* Hermes Belusca-Maito (hermes.belusca@sfr.fr)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
|
#include "reactos.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* SETUP* API COMPATIBILITY FUNCTIONS ****************************************/
|
||||||
|
|
||||||
|
/* Functions from the INFLIB library */
|
||||||
|
|
||||||
|
/* SetupOpenInfFileW with support for a user-provided LCID */
|
||||||
|
HINF
|
||||||
|
WINAPI
|
||||||
|
SetupOpenInfFileExW(
|
||||||
|
IN PCWSTR FileName,
|
||||||
|
IN PCWSTR InfClass,
|
||||||
|
IN DWORD InfStyle,
|
||||||
|
IN LCID LocaleId,
|
||||||
|
OUT PUINT ErrorLine)
|
||||||
|
{
|
||||||
|
WCHAR Win32FileName[MAX_PATH];
|
||||||
|
|
||||||
|
UNREFERENCED_PARAMETER(LocaleId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SetupOpenInfFileExW is called within setuplib with NT paths, however
|
||||||
|
* the Win32 SetupOpenInfFileW API only takes Win32 paths. We therefore
|
||||||
|
* map the NT path to Win32 path and then call the Win32 API.
|
||||||
|
*/
|
||||||
|
if (!ConvertNtPathToWin32Path(Win32FileName,
|
||||||
|
_countof(Win32FileName),
|
||||||
|
FileName))
|
||||||
|
{
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SetupOpenInfFileW(Win32FileName,
|
||||||
|
InfClass,
|
||||||
|
InfStyle,
|
||||||
|
ErrorLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* HELPER FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
HINF WINAPI
|
||||||
|
INF_OpenBufferedFileA(
|
||||||
|
IN PSTR FileBuffer,
|
||||||
|
IN ULONG FileSize,
|
||||||
|
IN PCSTR InfClass,
|
||||||
|
IN DWORD InfStyle,
|
||||||
|
IN LCID LocaleId,
|
||||||
|
OUT PUINT ErrorLine)
|
||||||
|
{
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
HINF hInf = NULL;
|
||||||
|
ULONG ErrorLineUL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
Status = InfOpenBufferedFile(&hInf,
|
||||||
|
FileBuffer,
|
||||||
|
FileSize,
|
||||||
|
LANGIDFROMLCID(LocaleId),
|
||||||
|
&ErrorLineUL);
|
||||||
|
*ErrorLine = (UINT)ErrorLineUL;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
return hInf;
|
||||||
|
#else
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
#endif /* !__REACTOS__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -27,13 +27,20 @@
|
||||||
#include "reactos.h"
|
#include "reactos.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
/* GLOBALS ******************************************************************/
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
|
HANDLE ProcessHeap;
|
||||||
|
BOOLEAN IsUnattendedSetup = FALSE;
|
||||||
|
SETUPDATA SetupData;
|
||||||
|
|
||||||
LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context);
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context);
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
CenterWindow(HWND hWnd)
|
CenterWindow(HWND hWnd)
|
||||||
{
|
{
|
||||||
|
@ -82,6 +89,19 @@ CreateTitleFont(VOID)
|
||||||
return hFont;
|
return hFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INT DisplayError(
|
||||||
|
IN HWND hParentWnd OPTIONAL,
|
||||||
|
IN UINT uIDTitle,
|
||||||
|
IN UINT uIDMessage)
|
||||||
|
{
|
||||||
|
WCHAR message[512], caption[64];
|
||||||
|
|
||||||
|
LoadStringW(SetupData.hInstance, uIDMessage, message, ARRAYSIZE(message));
|
||||||
|
LoadStringW(SetupData.hInstance, uIDTitle, caption, ARRAYSIZE(caption));
|
||||||
|
|
||||||
|
return MessageBoxW(hParentWnd, message, caption, MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
|
||||||
static INT_PTR CALLBACK
|
static INT_PTR CALLBACK
|
||||||
StartDlgProc(HWND hwndDlg,
|
StartDlgProc(HWND hwndDlg,
|
||||||
UINT uMsg,
|
UINT uMsg,
|
||||||
|
@ -498,37 +518,15 @@ RestartDlgProc(HWND hwndDlg,
|
||||||
BOOL LoadSetupData(
|
BOOL LoadSetupData(
|
||||||
PSETUPDATA pSetupData)
|
PSETUPDATA pSetupData)
|
||||||
{
|
{
|
||||||
WCHAR szPath[MAX_PATH];
|
BOOL ret = TRUE;
|
||||||
TCHAR tmp[10];
|
|
||||||
WCHAR *ch;
|
|
||||||
HINF hTxtsetupSif = INVALID_HANDLE_VALUE;
|
|
||||||
INFCONTEXT InfContext;
|
INFCONTEXT InfContext;
|
||||||
|
TCHAR tmp[10];
|
||||||
//TCHAR szValue[MAX_PATH];
|
//TCHAR szValue[MAX_PATH];
|
||||||
DWORD LineLength;
|
DWORD LineLength;
|
||||||
LONG Count;
|
LONG Count;
|
||||||
BOOL ret = TRUE;
|
|
||||||
|
|
||||||
GetModuleFileNameW(NULL,szPath,MAX_PATH);
|
|
||||||
ch = strrchrW(szPath,L'\\');
|
|
||||||
if (ch != NULL)
|
|
||||||
*ch = L'\0';
|
|
||||||
|
|
||||||
wcscat(szPath, L"\\txtsetup.sif");
|
|
||||||
hTxtsetupSif = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
|
|
||||||
if (hTxtsetupSif == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
TCHAR message[512], caption[64];
|
|
||||||
|
|
||||||
// txtsetup.sif cannot be found
|
|
||||||
LoadString(pSetupData->hInstance, IDS_NO_TXTSETUP_SIF, message, sizeof(message)/sizeof(TCHAR));
|
|
||||||
LoadString(pSetupData->hInstance, IDS_CAPTION, caption, sizeof(caption)/sizeof(TCHAR));
|
|
||||||
|
|
||||||
MessageBox(NULL, message, caption, MB_OK | MB_ICONERROR);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get language list
|
// get language list
|
||||||
pSetupData->LangCount = SetupGetLineCount(hTxtsetupSif, _T("Language"));
|
pSetupData->LangCount = SetupGetLineCount(pSetupData->SetupInf, _T("Language"));
|
||||||
if (pSetupData->LangCount > 0)
|
if (pSetupData->LangCount > 0)
|
||||||
{
|
{
|
||||||
pSetupData->pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * pSetupData->LangCount);
|
pSetupData->pLanguages = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LANG) * pSetupData->LangCount);
|
||||||
|
@ -539,7 +537,7 @@ BOOL LoadSetupData(
|
||||||
}
|
}
|
||||||
|
|
||||||
Count = 0;
|
Count = 0;
|
||||||
if (SetupFindFirstLine(hTxtsetupSif, _T("Language"), NULL, &InfContext))
|
if (SetupFindFirstLine(pSetupData->SetupInf, _T("Language"), NULL, &InfContext))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -561,7 +559,7 @@ BOOL LoadSetupData(
|
||||||
}
|
}
|
||||||
|
|
||||||
// get keyboard layout list
|
// get keyboard layout list
|
||||||
pSetupData->KbLayoutCount = SetupGetLineCount(hTxtsetupSif, _T("KeyboardLayout"));
|
pSetupData->KbLayoutCount = SetupGetLineCount(pSetupData->SetupInf, _T("KeyboardLayout"));
|
||||||
if (pSetupData->KbLayoutCount > 0)
|
if (pSetupData->KbLayoutCount > 0)
|
||||||
{
|
{
|
||||||
pSetupData->pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * pSetupData->KbLayoutCount);
|
pSetupData->pKbLayouts = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KBLAYOUT) * pSetupData->KbLayoutCount);
|
||||||
|
@ -572,7 +570,7 @@ BOOL LoadSetupData(
|
||||||
}
|
}
|
||||||
|
|
||||||
Count = 0;
|
Count = 0;
|
||||||
if (SetupFindFirstLine(hTxtsetupSif, _T("KeyboardLayout"), NULL, &InfContext))
|
if (SetupFindFirstLine(pSetupData->SetupInf, _T("KeyboardLayout"), NULL, &InfContext))
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -598,7 +596,7 @@ BOOL LoadSetupData(
|
||||||
pSetupData->DefaultLang = -1;
|
pSetupData->DefaultLang = -1;
|
||||||
|
|
||||||
// TODO: get defaults from underlaying running system
|
// TODO: get defaults from underlaying running system
|
||||||
if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLayout"), &InfContext))
|
if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLayout"), &InfContext))
|
||||||
{
|
{
|
||||||
SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
|
SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
|
||||||
for (Count = 0; Count < pSetupData->KbLayoutCount; Count++)
|
for (Count = 0; Count < pSetupData->KbLayoutCount; Count++)
|
||||||
|
@ -611,7 +609,7 @@ BOOL LoadSetupData(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetupFindFirstLine(hTxtsetupSif, _T("NLS"), _T("DefaultLanguage"), &InfContext))
|
if (SetupFindFirstLine(pSetupData->SetupInf, _T("NLS"), _T("DefaultLanguage"), &InfContext))
|
||||||
{
|
{
|
||||||
SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
|
SetupGetStringField(&InfContext, 1, tmp, sizeof(tmp) / sizeof(TCHAR), &LineLength);
|
||||||
for (Count = 0; Count < pSetupData->LangCount; Count++)
|
for (Count = 0; Count < pSetupData->LangCount; Count++)
|
||||||
|
@ -625,21 +623,21 @@ BOOL LoadSetupData(
|
||||||
}
|
}
|
||||||
|
|
||||||
// get computers list
|
// get computers list
|
||||||
pSetupData->CompCount = LoadGenentry(hTxtsetupSif,_T("Computer"),&pSetupData->pComputers,&InfContext);
|
pSetupData->CompCount = LoadGenentry(pSetupData->SetupInf,_T("Computer"),&pSetupData->pComputers,&InfContext);
|
||||||
|
|
||||||
// get display list
|
// get display list
|
||||||
pSetupData->DispCount = LoadGenentry(hTxtsetupSif,_T("Display"),&pSetupData->pDisplays,&InfContext);
|
pSetupData->DispCount = LoadGenentry(pSetupData->SetupInf,_T("Display"),&pSetupData->pDisplays,&InfContext);
|
||||||
|
|
||||||
// get keyboard list
|
// get keyboard list
|
||||||
pSetupData->KeybCount = LoadGenentry(hTxtsetupSif, _T("Keyboard"),&pSetupData->pKeyboards,&InfContext);
|
pSetupData->KeybCount = LoadGenentry(pSetupData->SetupInf, _T("Keyboard"),&pSetupData->pKeyboards,&InfContext);
|
||||||
|
|
||||||
// get install directory
|
// get install directory
|
||||||
if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
|
if (SetupFindFirstLine(pSetupData->SetupInf, _T("SetupData"), _T("DefaultPath"), &InfContext))
|
||||||
{
|
{
|
||||||
SetupGetStringField(&InfContext,
|
SetupGetStringField(&InfContext,
|
||||||
1,
|
1,
|
||||||
pSetupData->InstallDir,
|
pSetupData->USetupData.InstallationDirectory,
|
||||||
sizeof(pSetupData->InstallDir) / sizeof(TCHAR),
|
sizeof(pSetupData->USetupData.InstallationDirectory) / sizeof(TCHAR),
|
||||||
&LineLength);
|
&LineLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,9 +657,6 @@ done:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hTxtsetupSif != INVALID_HANDLE_VALUE)
|
|
||||||
SetupCloseInfFile(hTxtsetupSif);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,89 +697,83 @@ LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY *gen,PINFCONTEXT context)
|
||||||
return TotalCount;
|
return TotalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL isUnattendSetup(VOID)
|
/*
|
||||||
|
* Attempts to convert a pure NT file path into a corresponding Win32 path.
|
||||||
|
* Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
ConvertNtPathToWin32Path(
|
||||||
|
OUT PWSTR pwszPath,
|
||||||
|
IN DWORD cchPathMax,
|
||||||
|
IN PCWSTR pwszNTPath)
|
||||||
{
|
{
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR wszDrives[512];
|
||||||
WCHAR *ch;
|
WCHAR wszNTPath[512]; // MAX_PATH ?
|
||||||
HINF hUnattendedInf;
|
DWORD cchDrives;
|
||||||
INFCONTEXT InfContext;
|
PWCHAR pwszDrive;
|
||||||
TCHAR szValue[MAX_PATH];
|
|
||||||
DWORD LineLength;
|
|
||||||
//HKEY hKey;
|
|
||||||
BOOL result = 0;
|
|
||||||
|
|
||||||
GetModuleFileNameW(NULL, szPath, MAX_PATH);
|
*pwszPath = UNICODE_NULL;
|
||||||
ch = strrchrW(szPath, L'\\');
|
|
||||||
if (ch != NULL)
|
|
||||||
*ch = L'\0';
|
|
||||||
|
|
||||||
wcscat(szPath, L"\\unattend.inf");
|
cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
|
||||||
hUnattendedInf = SetupOpenInfFileW(szPath, NULL, INF_STYLE_OLDNT, NULL);
|
if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
|
||||||
|
|
||||||
if (hUnattendedInf != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
{
|
||||||
if (SetupFindFirstLine(hUnattendedInf, _T("Unattend"), _T("UnattendSetupEnabled"),&InfContext))
|
/* Buffer too small or failure */
|
||||||
{
|
DPRINT1("GetLogicalDriveStringsW failed\n");
|
||||||
if (SetupGetStringField(&InfContext,
|
return FALSE;
|
||||||
1,
|
|
||||||
szValue,
|
|
||||||
sizeof(szValue) / sizeof(TCHAR),
|
|
||||||
&LineLength) && (_tcsicmp(szValue, _T("yes")) == 0))
|
|
||||||
{
|
|
||||||
result = 1; // unattendSetup enabled
|
|
||||||
// read values and store in SetupData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetupCloseInfFile(hUnattendedInf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
|
||||||
|
{
|
||||||
|
/* Retrieve the NT path corresponding to the current Win32 DOS path */
|
||||||
|
pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash
|
||||||
|
QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
|
||||||
|
pwszDrive[2] = L'\\'; // Restore the backslash
|
||||||
|
|
||||||
|
wcscat(wszNTPath, L"\\"); // Concat a backslash
|
||||||
|
|
||||||
|
DPRINT1("Testing '%S' --> '%S'\n", pwszDrive, wszNTPath);
|
||||||
|
|
||||||
|
/* Check whether the NT path corresponds to the NT installation source path */
|
||||||
|
if (!_wcsnicmp(wszNTPath, pwszNTPath, wcslen(wszNTPath)))
|
||||||
|
{
|
||||||
|
/* Found it! */
|
||||||
|
wsprintf(pwszPath, L"%s%s", // cchPathMax
|
||||||
|
pwszDrive, pwszNTPath + wcslen(wszNTPath));
|
||||||
|
DPRINT1("ConvertNtPathToWin32Path: %S\n", pwszPath);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/* Used to enable and disable the shutdown privilege */
|
||||||
static
|
/* static */ BOOL
|
||||||
VOID
|
EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
|
||||||
EnableShutdownPrivilege(VOID)
|
|
||||||
{
|
{
|
||||||
HANDLE hToken = NULL;
|
BOOL Success;
|
||||||
TOKEN_PRIVILEGES Privileges;
|
HANDLE hToken;
|
||||||
|
TOKEN_PRIVILEGES tp;
|
||||||
|
|
||||||
/* Get shutdown privilege */
|
Success = OpenProcessToken(GetCurrentProcess(),
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
|
TOKEN_ADJUST_PRIVILEGES,
|
||||||
{
|
&hToken);
|
||||||
// FatalError("OpenProcessToken() failed!");
|
if (!Success) return Success;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValue(NULL,
|
Success = LookupPrivilegeValueW(NULL,
|
||||||
SE_SHUTDOWN_NAME,
|
lpszPrivilegeName,
|
||||||
&Privileges.Privileges[0].Luid))
|
&tp.Privileges[0].Luid);
|
||||||
{
|
if (!Success) goto Quit;
|
||||||
// FatalError("LookupPrivilegeValue() failed!");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
Privileges.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
|
||||||
|
|
||||||
if (AdjustTokenPrivileges(hToken,
|
Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
|
||||||
FALSE,
|
|
||||||
&Privileges,
|
|
||||||
0,
|
|
||||||
(PTOKEN_PRIVILEGES)NULL,
|
|
||||||
NULL) == 0)
|
|
||||||
{
|
|
||||||
// FatalError("AdjustTokenPrivileges() failed!");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
Quit:
|
||||||
if (hToken != NULL)
|
|
||||||
CloseHandle(hToken);
|
CloseHandle(hToken);
|
||||||
|
return Success;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int WINAPI
|
int WINAPI
|
||||||
_tWinMain(HINSTANCE hInst,
|
_tWinMain(HINSTANCE hInst,
|
||||||
|
@ -792,40 +781,75 @@ _tWinMain(HINSTANCE hInst,
|
||||||
LPTSTR lpszCmdLine,
|
LPTSTR lpszCmdLine,
|
||||||
int nCmdShow)
|
int nCmdShow)
|
||||||
{
|
{
|
||||||
PSETUPDATA pSetupData = NULL;
|
NTSTATUS Status;
|
||||||
|
ULONG Error;
|
||||||
PROPSHEETHEADER psh;
|
PROPSHEETHEADER psh;
|
||||||
HPROPSHEETPAGE ahpsp[8];
|
HPROPSHEETPAGE ahpsp[8];
|
||||||
PROPSHEETPAGE psp = {0};
|
PROPSHEETPAGE psp = {0};
|
||||||
UINT nPages = 0;
|
UINT nPages = 0;
|
||||||
|
|
||||||
pSetupData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SETUPDATA));
|
ProcessHeap = GetProcessHeap();
|
||||||
if (pSetupData == NULL)
|
|
||||||
|
/* Initialize global unicode strings */
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.SourcePath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.SourceRootPath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.SourceRootDir, NULL);
|
||||||
|
// RtlInitUnicodeString(&InstallPath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.DestinationPath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.DestinationArcPath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.DestinationRootPath, NULL);
|
||||||
|
RtlInitUnicodeString(&SetupData.USetupData.SystemRootPath, NULL);
|
||||||
|
|
||||||
|
/* Get the source path and source root path */
|
||||||
|
//
|
||||||
|
// NOTE: Sometimes the source path may not be in SystemRoot !!
|
||||||
|
// (and this is the case when using the 1st-stage GUI setup!)
|
||||||
|
//
|
||||||
|
Status = GetSourcePaths(&SetupData.USetupData.SourcePath,
|
||||||
|
&SetupData.USetupData.SourceRootPath,
|
||||||
|
&SetupData.USetupData.SourceRootDir);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return 1;
|
DPRINT1("GetSourcePaths() failed (Status 0x%08lx)", Status);
|
||||||
|
// MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
|
||||||
|
MessageBoxW(NULL, L"GetSourcePaths failed!", L"Error", MB_ICONERROR);
|
||||||
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
DPRINT1("SourcePath: '%wZ'\n", &SetupData.USetupData.SourcePath);
|
||||||
|
DPRINT1("SourceRootPath: '%wZ'\n", &SetupData.USetupData.SourceRootPath);
|
||||||
|
DPRINT1("SourceRootDir: '%wZ'\n", &SetupData.USetupData.SourceRootDir);
|
||||||
|
|
||||||
pSetupData->hInstance = hInst;
|
/* Load 'txtsetup.sif' from the installation media */
|
||||||
pSetupData->bUnattend = isUnattendSetup();
|
Error = LoadSetupInf(&SetupData.SetupInf, &SetupData.USetupData);
|
||||||
|
if (Error != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
|
||||||
|
DisplayError(NULL, IDS_CAPTION, IDS_NO_TXTSETUP_SIF);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
/* Load extra setup data (HW lists etc...) */
|
||||||
|
if (!LoadSetupData(&SetupData))
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
LoadString(hInst,IDS_ABORTSETUP, pSetupData->szAbortMessage, sizeof(pSetupData->szAbortMessage)/sizeof(TCHAR));
|
SetupData.hInstance = hInst;
|
||||||
LoadString(hInst,IDS_ABORTSETUP2, pSetupData->szAbortTitle, sizeof(pSetupData->szAbortTitle)/sizeof(TCHAR));
|
|
||||||
|
CheckUnattendedSetup(&SetupData.USetupData);
|
||||||
|
SetupData.bUnattend = IsUnattendedSetup;
|
||||||
|
|
||||||
|
LoadStringW(hInst, IDS_ABORTSETUP, SetupData.szAbortMessage, ARRAYSIZE(SetupData.szAbortMessage));
|
||||||
|
LoadStringW(hInst, IDS_ABORTSETUP2, SetupData.szAbortTitle, ARRAYSIZE(SetupData.szAbortTitle));
|
||||||
|
|
||||||
/* Create title font */
|
/* Create title font */
|
||||||
pSetupData->hTitleFont = CreateTitleFont();
|
SetupData.hTitleFont = CreateTitleFont();
|
||||||
|
|
||||||
if (!pSetupData->bUnattend)
|
if (!SetupData.bUnattend)
|
||||||
{
|
{
|
||||||
if (!LoadSetupData(pSetupData))
|
|
||||||
{
|
|
||||||
HeapFree(GetProcessHeap(), 0, pSetupData);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the Start page, until setup is working */
|
/* Create the Start page, until setup is working */
|
||||||
|
// NOTE: What does "until setup is working" mean??
|
||||||
psp.dwSize = sizeof(PROPSHEETPAGE);
|
psp.dwSize = sizeof(PROPSHEETPAGE);
|
||||||
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
|
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = StartDlgProc;
|
psp.pfnDlgProc = StartDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -836,7 +860,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
|
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE);
|
||||||
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
|
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE);
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = TypeDlgProc;
|
psp.pfnDlgProc = TypeDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -847,7 +871,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
|
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE);
|
||||||
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
|
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE);
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = DeviceDlgProc;
|
psp.pfnDlgProc = DeviceDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -858,7 +882,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
|
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE);
|
||||||
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
|
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE);
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = DriveDlgProc;
|
psp.pfnDlgProc = DriveDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -869,7 +893,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
|
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE);
|
||||||
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
|
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE);
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = SummaryDlgProc;
|
psp.pfnDlgProc = SummaryDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -881,7 +905,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
|
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
|
||||||
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
|
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = ProcessDlgProc;
|
psp.pfnDlgProc = ProcessDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -890,7 +914,7 @@ _tWinMain(HINSTANCE hInst,
|
||||||
psp.dwSize = sizeof(PROPSHEETPAGE);
|
psp.dwSize = sizeof(PROPSHEETPAGE);
|
||||||
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
|
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
|
||||||
psp.hInstance = hInst;
|
psp.hInstance = hInst;
|
||||||
psp.lParam = (LPARAM)pSetupData;
|
psp.lParam = (LPARAM)&SetupData;
|
||||||
psp.pfnDlgProc = RestartDlgProc;
|
psp.pfnDlgProc = RestartDlgProc;
|
||||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE);
|
||||||
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
ahpsp[nPages++] = CreatePropertySheetPage(&psp);
|
||||||
|
@ -909,14 +933,17 @@ _tWinMain(HINSTANCE hInst,
|
||||||
/* Display the wizard */
|
/* Display the wizard */
|
||||||
PropertySheet(&psh);
|
PropertySheet(&psh);
|
||||||
|
|
||||||
if (pSetupData->hTitleFont)
|
if (SetupData.hTitleFont)
|
||||||
DeleteObject(pSetupData->hTitleFont);
|
DeleteObject(SetupData.hTitleFont);
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, pSetupData);
|
SetupCloseInfFile(SetupData.SetupInf);
|
||||||
|
|
||||||
#if 0
|
Quit:
|
||||||
EnableShutdownPrivilege();
|
|
||||||
|
#if 0 // NOTE: Disabled for testing purposes only!
|
||||||
|
EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
|
||||||
ExitWindowsEx(EWX_REBOOT, 0);
|
ExitWindowsEx(EWX_REBOOT, 0);
|
||||||
|
EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -27,16 +27,34 @@
|
||||||
#ifndef _REACTOS_PCH_
|
#ifndef _REACTOS_PCH_
|
||||||
#define _REACTOS_PCH_
|
#define _REACTOS_PCH_
|
||||||
|
|
||||||
|
/* C Headers */
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
/* PSDK/NDK */
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
#include <windef.h>
|
#include <windef.h>
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <winreg.h>
|
#include <winreg.h>
|
||||||
#include <wingdi.h>
|
#include <wingdi.h>
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
#include <tchar.h>
|
|
||||||
#include <setupapi.h>
|
#include <commctrl.h>
|
||||||
|
/**/#include <setupapi.h>/**/
|
||||||
#include <devguid.h>
|
#include <devguid.h>
|
||||||
#include <wine/unicode.h>
|
// #include <wine/unicode.h>
|
||||||
|
|
||||||
|
#define NTOS_MODE_USER
|
||||||
|
#include <ndk/cmtypes.h> // For CM_DISK stuff
|
||||||
|
#include <ndk/iofuncs.h> // For NtCreate/OpenFile
|
||||||
|
#include <ndk/rtlfuncs.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup library headers */
|
||||||
|
// #include <reactos/rosioctl.h>
|
||||||
|
#include <../lib/setuplib.h>
|
||||||
|
// #include "errorcode.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct _LANG
|
typedef struct _LANG
|
||||||
|
@ -71,20 +89,22 @@ typedef struct _SETUPDATA
|
||||||
TCHAR szAbortMessage[512];
|
TCHAR szAbortMessage[512];
|
||||||
TCHAR szAbortTitle[64];
|
TCHAR szAbortTitle[64];
|
||||||
|
|
||||||
|
USETUP_DATA USetupData;
|
||||||
|
HINF SetupInf;
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
LONG DestDiskNumber; // physical disk
|
|
||||||
LONG DestPartNumber; // partition on disk
|
|
||||||
LONG DestPartSize; // if partition doesn't exist, size of partition
|
LONG DestPartSize; // if partition doesn't exist, size of partition
|
||||||
LONG FSType; // file system type on partition
|
LONG FSType; // file system type on partition
|
||||||
LONG MBRInstallType; // install bootloader
|
|
||||||
LONG FormatPart; // type of format the partition
|
LONG FormatPart; // type of format the partition
|
||||||
|
|
||||||
LONG SelectedLangId; // selected language (table index)
|
LONG SelectedLangId; // selected language (table index)
|
||||||
LONG SelectedKBLayout; // selected keyboard layout (table index)
|
LONG SelectedKBLayout; // selected keyboard layout (table index)
|
||||||
TCHAR InstallDir[MAX_PATH]; // installation directory on hdd
|
|
||||||
LONG SelectedComputer; // selected computer type (table index)
|
LONG SelectedComputer; // selected computer type (table index)
|
||||||
LONG SelectedDisplay; // selected display type (table index)
|
LONG SelectedDisplay; // selected display type (table index)
|
||||||
LONG SelectedKeyboard; // selected keyboard type (table index)
|
LONG SelectedKeyboard; // selected keyboard type (table index)
|
||||||
BOOLEAN RepairUpdateFlag; // flag for update/repair an installed reactos
|
BOOLEAN RepairUpdateFlag; // flag for update/repair an installed reactos
|
||||||
|
|
||||||
|
|
||||||
// txtsetup.sif data
|
// txtsetup.sif data
|
||||||
LONG DefaultLang; // default language (table index)
|
LONG DefaultLang; // default language (table index)
|
||||||
PLANG pLanguages;
|
PLANG pLanguages;
|
||||||
|
@ -100,6 +120,9 @@ typedef struct _SETUPDATA
|
||||||
LONG KeybCount;
|
LONG KeybCount;
|
||||||
} SETUPDATA, *PSETUPDATA;
|
} SETUPDATA, *PSETUPDATA;
|
||||||
|
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
extern BOOLEAN IsUnattendedSetup;
|
||||||
|
|
||||||
typedef struct _IMGINFO
|
typedef struct _IMGINFO
|
||||||
{
|
{
|
||||||
HBITMAP hBitmap;
|
HBITMAP hBitmap;
|
||||||
|
@ -109,6 +132,17 @@ typedef struct _IMGINFO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempts to convert a pure NT file path into a corresponding Win32 path.
|
||||||
|
* Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
ConvertNtPathToWin32Path(
|
||||||
|
OUT PWSTR pwszPath,
|
||||||
|
IN DWORD cchPathMax,
|
||||||
|
IN PCWSTR pwszNTPath);
|
||||||
|
|
||||||
|
|
||||||
/* drivepage.c */
|
/* drivepage.c */
|
||||||
INT_PTR
|
INT_PTR
|
||||||
CALLBACK
|
CALLBACK
|
||||||
|
|
Loading…
Reference in a new issue