diff --git a/base/setup/reactos/CMakeLists.txt b/base/setup/reactos/CMakeLists.txt index 8c58f9e360e..75418ede517 100644 --- a/base/setup/reactos/CMakeLists.txt +++ b/base/setup/reactos/CMakeLists.txt @@ -20,5 +20,5 @@ add_executable(reactos ${SOURCE} reactos.rc) 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 shlwapi setupapi msvcrt kernel32 ntdll) add_cd_file(TARGET reactos DESTINATION reactos NO_CAB FOR bootcd) diff --git a/base/setup/reactos/drivepage.c b/base/setup/reactos/drivepage.c index cf79aa38474..1da5771c473 100644 --- a/base/setup/reactos/drivepage.c +++ b/base/setup/reactos/drivepage.c @@ -25,17 +25,23 @@ */ #include "reactos.h" +#include + +// #include +#include +#include + #include "resource.h" /* GLOBALS ******************************************************************/ #define IDS_LIST_COLUMN_FIRST IDS_PARTITION_NAME -#define IDS_LIST_COLUMN_LAST IDS_PARTITION_TYPE +#define IDS_LIST_COLUMN_LAST IDS_PARTITION_STATUS #define MAX_LIST_COLUMNS (IDS_LIST_COLUMN_LAST - IDS_LIST_COLUMN_FIRST + 1) -static const UINT column_ids[MAX_LIST_COLUMNS] = {IDS_LIST_COLUMN_FIRST, IDS_LIST_COLUMN_FIRST + 1, IDS_LIST_COLUMN_FIRST + 2}; -static const INT column_widths[MAX_LIST_COLUMNS] = {200, 150, 150}; -static const INT column_alignment[MAX_LIST_COLUMNS] = {LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT}; +static const UINT column_ids[MAX_LIST_COLUMNS] = {IDS_LIST_COLUMN_FIRST, IDS_LIST_COLUMN_FIRST + 1, IDS_LIST_COLUMN_FIRST + 2, IDS_LIST_COLUMN_FIRST + 3}; +static const INT column_widths[MAX_LIST_COLUMNS] = {200, 90, 60, 60}; +static const INT column_alignment[MAX_LIST_COLUMNS] = {LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT}; /* FUNCTIONS ****************************************************************/ @@ -59,23 +65,19 @@ MoreOptDlgProc(HWND hwndDlg, SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); CheckDlgButton(hwndDlg, IDC_INSTFREELDR, BST_CHECKED); - SendMessageW(GetDlgItem(hwndDlg, IDC_PATH), - WM_SETTEXT, - (WPARAM)0, - (LPARAM)pSetupData->USetupData.InstallationDirectory); + SetDlgItemTextW(hwndDlg, IDC_PATH, + pSetupData->USetupData.InstallationDirectory); break; } case WM_COMMAND: - switch(LOWORD(wParam)) + switch (LOWORD(wParam)) { case IDOK: { - SendMessageW(GetDlgItem(hwndDlg, IDC_PATH), - WM_GETTEXT, - (WPARAM)ARRAYSIZE(pSetupData->USetupData.InstallationDirectory), - (LPARAM)pSetupData->USetupData.InstallationDirectory); - + GetDlgItemTextW(hwndDlg, IDC_PATH, + pSetupData->USetupData.InstallationDirectory, + ARRAYSIZE(pSetupData->USetupData.InstallationDirectory)); EndDialog(hwndDlg, IDOK); return TRUE; } @@ -100,9 +102,10 @@ PartitionDlgProc(HWND hwndDlg, { case WM_INITDIALOG: break; + case WM_COMMAND: { - switch(LOWORD(wParam)) + switch (LOWORD(wParam)) { case IDOK: EndDialog(hwndDlg, IDOK); @@ -118,38 +121,469 @@ PartitionDlgProc(HWND hwndDlg, BOOL -CreateListViewColumns( +CreateTreeListColumns( IN HINSTANCE hInstance, - IN HWND hWndListView, + IN HWND hWndTreeList, IN const UINT* pIDs, IN const INT* pColsWidth, IN const INT* pColsAlign, IN UINT nNumOfColumns) { UINT i; - LVCOLUMN lvC; + TLCOLUMN tlC; WCHAR szText[50]; /* Create the columns */ - lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvC.pszText = szText; + tlC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + tlC.pszText = szText; /* Load the column labels from the resource file */ for (i = 0; i < nNumOfColumns; i++) { - lvC.iSubItem = i; - lvC.cx = pColsWidth[i]; - lvC.fmt = pColsAlign[i]; + tlC.iSubItem = i; + tlC.cx = pColsWidth[i]; + tlC.fmt = pColsAlign[i]; LoadStringW(hInstance, pIDs[i], szText, ARRAYSIZE(szText)); - if (ListView_InsertColumn(hWndListView, i, &lvC) == -1) + if (TreeList_InsertColumn(hWndTreeList, i, &tlC) == -1) return FALSE; } return TRUE; } +// unused +VOID +DisplayStuffUsingWin32Setup(HWND hwndDlg) +{ + HDEVINFO h; + HWND hList; + SP_DEVINFO_DATA DevInfoData; + DWORD i; + + h = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT); + if (h == INVALID_HANDLE_VALUE) + return; + + hList = GetDlgItem(hwndDlg, IDC_PARTITION); + DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + for (i=0; SetupDiEnumDeviceInfo(h, i, &DevInfoData); i++) + { + DWORD DataT; + LPTSTR buffer = NULL; + DWORD buffersize = 0; + + while (!SetupDiGetDeviceRegistryProperty(h, + &DevInfoData, + SPDRP_DEVICEDESC, + &DataT, + (PBYTE)buffer, + buffersize, + &buffersize)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + if (buffer) LocalFree(buffer); + buffer = LocalAlloc(LPTR, buffersize * 2); + } + else + { + return; + } + } + if (buffer) + { + SendMessageW(hList, LB_ADDSTRING, (WPARAM)0, (LPARAM)buffer); + LocalFree(buffer); + } + } + SetupDiDestroyDeviceInfoList(h); +} + + +HTLITEM +TreeListAddItem(IN HWND hTreeList, + IN HTLITEM hParent, + IN LPWSTR lpText, + IN INT iImage, + IN INT iSelectedImage, + IN LPARAM lParam) +{ + TL_INSERTSTRUCTW Insert; + + ZeroMemory(&Insert, sizeof(Insert)); + + Insert.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + Insert.hInsertAfter = TVI_LAST; + Insert.hParent = hParent; + Insert.item.pszText = lpText; + Insert.item.iImage = iImage; + Insert.item.iSelectedImage = iSelectedImage; + Insert.item.lParam = lParam; + + // Insert.item.mask |= TVIF_STATE; + // Insert.item.stateMask = TVIS_OVERLAYMASK; + // Insert.item.state = INDEXTOOVERLAYMASK(1); + + return TreeList_InsertItem(hTreeList, &Insert); +} + + +VOID +GetPartTypeStringFromPartitionType( + IN UCHAR partitionType, + OUT PCHAR strPartType, + IN ULONG cchPartType) +{ + /* Determine partition type */ + + if (IsContainerPartition(partitionType)) + { + StringCchCopyA(strPartType, cchPartType, "Extended Partition" /* MUIGetString(STRING_EXTENDED_PARTITION) */); + } + else if (partitionType == PARTITION_ENTRY_UNUSED) + { + StringCchCopyA(strPartType, cchPartType, "Unused" /* MUIGetString(STRING_FORMATUNUSED) */); + } + else + { + UINT i; + + /* Do the table lookup */ + for (i = 0; i < ARRAYSIZE(PartitionTypes); i++) + { + if (partitionType == PartitionTypes[i].Type) + { + StringCchCopyA(strPartType, cchPartType, PartitionTypes[i].Description); + return; + } + } + + /* We are here because the partition type is unknown */ + StringCchCopyA(strPartType, cchPartType, "Unknown" /* MUIGetString(STRING_FORMATUNKNOWN) */); + } +} + +static +HTLITEM +PrintPartitionData( + IN HWND hWndList, + IN PPARTLIST List, + IN HTLITEM htiParent, + IN PDISKENTRY DiskEntry, + IN PPARTENTRY PartEntry) +{ + LARGE_INTEGER PartSize; + HTLITEM htiPart; + CHAR PartTypeString[32]; + PCHAR PartType = PartTypeString; + WCHAR LineBuffer[128]; + + /* Volume name */ + if (PartEntry->IsPartitioned == FALSE) + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_UNPSPACE), + L"Unpartitioned space"); + } + else + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDDINFOUNK5), + L"%s (%c%c)", + *PartEntry->VolumeLabel ? PartEntry->VolumeLabel : L"Partition", + (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter, + (PartEntry->DriveLetter == 0) ? L'-' : L':'); + } + + htiPart = TreeListAddItem(hWndList, htiParent, LineBuffer, + 1, 1, + (LPARAM)PartEntry); + + /* Determine partition type */ + *LineBuffer = 0; + if (PartEntry->IsPartitioned) + { + PartTypeString[0] = '\0'; + if (PartEntry->New == TRUE) + { + PartType = "New (Unformatted)"; // MUIGetString(STRING_UNFORMATTED); + } + else if (PartEntry->IsPartitioned == TRUE) + { + GetPartTypeStringFromPartitionType(PartEntry->PartitionType, + PartTypeString, + ARRAYSIZE(PartTypeString)); + PartType = PartTypeString; + } + + if (strcmp(PartType, "Unknown" /* MUIGetString(STRING_FORMATUNKNOWN) */) == 0) + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDDINFOUNK5), + L"Type 0x%02x", + PartEntry->PartitionType); + } + else + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + L"%S", + PartType); + } + } + TreeList_SetItemText(hWndList, htiPart, 1, LineBuffer); + + /* Format the disk size in KBs, MBs, etc... */ + PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + if (StrFormatByteSizeW(PartSize.QuadPart, LineBuffer, ARRAYSIZE(LineBuffer)) == NULL) + { + /* We failed for whatever reason, do the hardcoded way */ + PWCHAR Unit; + +#if 0 + if (PartSize.QuadPart >= 10 * GB) /* 10 GB */ + { + PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, GB); + // Unit = MUIGetString(STRING_GB); + Unit = L"GB"; + } + else +#endif + if (PartSize.QuadPart >= 10 * MB) /* 10 MB */ + { + PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, MB); + // Unit = MUIGetString(STRING_MB); + Unit = L"MB"; + } + else + { + PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, KB); + // Unit = MUIGetString(STRING_KB); + Unit = L"KB"; + } + + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + L"%6lu %s", + PartSize.u.LowPart, + Unit); + } + TreeList_SetItemText(hWndList, htiPart, 2, LineBuffer); + + /* Volume status */ + *LineBuffer = 0; + if (PartEntry->IsPartitioned) + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDDINFOUNK5), + PartEntry->BootIndicator ? L"Active" : L""); + } + TreeList_SetItemText(hWndList, htiPart, 3, LineBuffer); + + return htiPart; +} + +static +VOID +PrintDiskData( + IN HWND hWndList, + IN PPARTLIST List, + IN PDISKENTRY DiskEntry) +{ + BOOL Success; + HANDLE hDevice; + PCHAR DiskName = NULL; + ULONG Length = 0; + PPARTENTRY PrimaryPartEntry, LogicalPartEntry; + PLIST_ENTRY PrimaryEntry, LogicalEntry; + ULARGE_INTEGER DiskSize; + HTLITEM htiDisk, htiPart; + WCHAR LineBuffer[128]; + UCHAR outBuf[512]; + + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // L"\\Device\\Harddisk%lu\\Partition%lu", + L"\\\\.\\PhysicalDrive%lu", + DiskEntry->DiskNumber); + + hDevice = CreateFileW( + LineBuffer, // device interface name + GENERIC_READ /*| GENERIC_WRITE*/, // dwDesiredAccess + FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode + NULL, // lpSecurityAttributes + OPEN_EXISTING, // dwCreationDistribution + 0, // dwFlagsAndAttributes + NULL // hTemplateFile + ); + if (hDevice != INVALID_HANDLE_VALUE) + { + STORAGE_PROPERTY_QUERY Query; + + Query.PropertyId = StorageDeviceProperty; + Query.QueryType = PropertyStandardQuery; + + Success = DeviceIoControl(hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &Query, + sizeof(Query), + &outBuf, + sizeof(outBuf), + &Length, + NULL); + if (Success) + { + PSTORAGE_DEVICE_DESCRIPTOR devDesc = (PSTORAGE_DEVICE_DESCRIPTOR)outBuf; + if (devDesc->ProductIdOffset) + { + DiskName = (PCHAR)&outBuf[devDesc->ProductIdOffset]; + Length -= devDesc->ProductIdOffset; + DiskName[min(Length, strlen(DiskName))] = 0; + // ( i = devDesc->ProductIdOffset; p[i] != 0 && i < Length; i++ ) + } + } + + CloseHandle(hDevice); + } + + if (DiskName && *DiskName) + { + if (DiskEntry->DriverName.Length > 0) + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDINFOPARTSELECT_1), + L"Harddisk %lu (%S) (Port=%hu, Bus=%hu, Id=%hu) on %wZ", + DiskEntry->DiskNumber, + DiskName, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id, + &DiskEntry->DriverName); + } + else + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDINFOPARTSELECT_2), + L"Harddisk %lu (%S) (Port=%hu, Bus=%hu, Id=%hu)", + DiskEntry->DiskNumber, + DiskName, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id); + } + } + else + { + if (DiskEntry->DriverName.Length > 0) + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDINFOPARTSELECT_1), + L"Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ", + DiskEntry->DiskNumber, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id, + &DiskEntry->DriverName); + } + else + { + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + // MUIGetString(STRING_HDINFOPARTSELECT_2), + L"Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)", + DiskEntry->DiskNumber, + DiskEntry->Port, + DiskEntry->Bus, + DiskEntry->Id); + } + } + + htiDisk = TreeListAddItem(hWndList, NULL, LineBuffer, + 0, 0, + (LPARAM)DiskEntry); + + /* Disk type (MBR or GPT) */ + TreeList_SetItemText(hWndList, htiDisk, 1, DiskEntry->NoMbr ? L"GPT" : L"MBR"); + + /* Format the disk size in KBs, MBs, etc... */ + DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; + if (StrFormatByteSizeW(DiskSize.QuadPart, LineBuffer, ARRAYSIZE(LineBuffer)) == NULL) + { + /* We failed for whatever reason, do the hardcoded way */ + PWCHAR Unit; + + if (DiskSize.QuadPart >= 10 * GB) /* 10 GB */ + { + DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, GB); + // Unit = MUIGetString(STRING_GB); + Unit = L"GB"; + } + else + { + DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, MB); + if (DiskSize.QuadPart == 0) + DiskSize.QuadPart = 1; + // Unit = MUIGetString(STRING_MB); + Unit = L"MB"; + } + + StringCchPrintfW(LineBuffer, ARRAYSIZE(LineBuffer), + L"%6lu %s", + DiskSize.u.LowPart, + Unit); + } + TreeList_SetItemText(hWndList, htiDisk, 2, LineBuffer); + + + /* Print partition lines */ + for (PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink; + PrimaryEntry != &DiskEntry->PrimaryPartListHead; + PrimaryEntry = PrimaryEntry->Flink) + { + PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry); + + htiPart = PrintPartitionData(hWndList, List, htiDisk, + DiskEntry, PrimaryPartEntry); + + if (IsContainerPartition(PrimaryPartEntry->PartitionType)) + { + for (LogicalEntry = DiskEntry->LogicalPartListHead.Flink; + LogicalEntry != &DiskEntry->LogicalPartListHead; + LogicalEntry = LogicalEntry->Flink) + { + LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry); + + PrintPartitionData(hWndList, List, htiPart, + DiskEntry, LogicalPartEntry); + } + + /* Expand the extended partition node */ + TreeList_Expand(hWndList, htiPart, TVE_EXPAND); + } + } + + /* Expand the disk node */ + TreeList_Expand(hWndList, htiDisk, TVE_EXPAND); +} + +VOID +DrawPartitionList( + IN HWND hWndList, + IN PPARTLIST List) +{ + PLIST_ENTRY Entry; + PDISKENTRY DiskEntry; + + for (Entry = List->DiskListHead.Flink; + Entry != &List->DiskListHead; + Entry = Entry->Flink) + { + DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry); + + /* Print disk entry */ + PrintDiskData(hWndList, List, DiskEntry); + } +} + + INT_PTR CALLBACK @@ -160,12 +594,8 @@ DriveDlgProc( LPARAM lParam) { PSETUPDATA pSetupData; -#if 1 - HDEVINFO h; HWND hList; - SP_DEVINFO_DATA DevInfoData; - DWORD i; -#endif + HIMAGELIST hSmall; /* Retrieve pointer to the global setup data */ pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); @@ -178,70 +608,70 @@ DriveDlgProc( pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); - CreateListViewColumns(pSetupData->hInstance, - GetDlgItem(hwndDlg, IDC_PARTITION), + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects a valid partition. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); + + hList = GetDlgItem(hwndDlg, IDC_PARTITION); + + TreeList_SetExtendedStyleEx(hList, TVS_EX_FULLROWMARK, TVS_EX_FULLROWMARK); + // TreeList_SetExtendedStyleEx(hList, TVS_EX_FULLROWITEMS, TVS_EX_FULLROWITEMS); + + CreateTreeListColumns(pSetupData->hInstance, + hList, column_ids, column_widths, column_alignment, MAX_LIST_COLUMNS); -#if 1 - h = SetupDiGetClassDevs(&GUID_DEVCLASS_DISKDRIVE, NULL, NULL, DIGCF_PRESENT); - if (h != INVALID_HANDLE_VALUE) - { - hList =GetDlgItem(hwndDlg, IDC_PARTITION); - DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - for (i=0; SetupDiEnumDeviceInfo(h, i, &DevInfoData); i++) - { - DWORD DataT; - LPTSTR buffer = NULL; - DWORD buffersize = 0; + /* Create the ImageList */ + hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + ILC_COLOR32 | ILC_MASK, // ILC_COLOR24 + 1, 1); - while (!SetupDiGetDeviceRegistryProperty(h, - &DevInfoData, - SPDRP_DEVICEDESC, - &DataT, - (PBYTE)buffer, - buffersize, - &buffersize)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - if (buffer) LocalFree(buffer); - buffer = LocalAlloc(LPTR, buffersize * 2); - } - else - break; - } - if (buffer) - { - SendMessageW(hList, LB_ADDSTRING, (WPARAM) 0, (LPARAM) buffer); - LocalFree(buffer); - } - } - SetupDiDestroyDeviceInfoList(h); - } -#endif + /* Add event type icons to the ImageList */ + ImageList_AddIcon(hSmall, LoadIconW(pSetupData->hInstance, MAKEINTRESOURCEW(IDI_DISKDRIVE))); + ImageList_AddIcon(hSmall, LoadIconW(pSetupData->hInstance, MAKEINTRESOURCEW(IDI_PARTITION))); + + /* Assign the ImageList to the List View */ + TreeList_SetImageList(hList, hSmall, TVSIL_NORMAL); + + // DisplayStuffUsingWin32Setup(hwndDlg); + DrawPartitionList(hList, pSetupData->PartitionList); + break; + } + + case WM_DESTROY: + { + hList = GetDlgItem(hwndDlg, IDC_PARTITION); + hSmall = TreeList_GetImageList(hList, TVSIL_NORMAL); + TreeList_SetImageList(hList, NULL, TVSIL_NORMAL); + ImageList_Destroy(hSmall); + return TRUE; } - break; case WM_COMMAND: { - switch(LOWORD(wParam)) + switch (LOWORD(wParam)) { case IDC_PARTMOREOPTS: - DialogBoxParam(pSetupData->hInstance, - MAKEINTRESOURCE(IDD_BOOTOPTIONS), - hwndDlg, - MoreOptDlgProc, - (LPARAM)pSetupData); + DialogBoxParamW(pSetupData->hInstance, + MAKEINTRESOURCEW(IDD_BOOTOPTIONS), + hwndDlg, + MoreOptDlgProc, + (LPARAM)pSetupData); break; + case IDC_PARTCREATE: - DialogBox(pSetupData->hInstance, - MAKEINTRESOURCE(IDD_PARTITION), - hwndDlg, - PartitionDlgProc); + DialogBoxW(pSetupData->hInstance, + MAKEINTRESOURCEW(IDD_PARTITION), + hwndDlg, + PartitionDlgProc); break; + case IDC_PARTDELETE: break; } @@ -252,11 +682,83 @@ DriveDlgProc( { LPNMHDR lpnm = (LPNMHDR)lParam; + // On Vista+ we can use TVN_ITEMCHANGED instead, with NMTVITEMCHANGE* pointer + if (lpnm->idFrom == IDC_PARTITION && lpnm->code == TVN_SELCHANGED) + { + LPNMTREEVIEW pnmv = (LPNMTREEVIEW)lParam; + + // if (pnmv->uChanged & TVIF_STATE) /* The state has changed */ + if (pnmv->itemNew.mask & TVIF_STATE) + { + /* The item has been (de)selected */ + // if (pnmv->uNewState & TVIS_SELECTED) + if (pnmv->itemNew.state & TVIS_SELECTED) + { + HTLITEM hParentItem = TreeList_GetParent(lpnm->hwndFrom, pnmv->itemNew.hItem); + /* May or may not be a PPARTENTRY: this is a PPARTENTRY only when hParentItem != NULL */ + PPARTENTRY PartEntry = (PPARTENTRY)pnmv->itemNew.lParam; + + if (!hParentItem || !PartEntry) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_PARTCREATE), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PARTDELETE), FALSE); + goto DisableWizNext; + } + else // if (hParentItem && PartEntry) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_PARTCREATE), !PartEntry->IsPartitioned); + EnableWindow(GetDlgItem(hwndDlg, IDC_PARTDELETE), PartEntry->IsPartitioned); + + if (PartEntry->IsPartitioned && + !IsContainerPartition(PartEntry->PartitionType) /* alternatively: PartEntry->PartitionNumber != 0 */ && + // !PartEntry->New && + (PartEntry->FormatState == Preformatted /* || PartEntry->FormatState == Formatted */)) + { + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + } + else + { + goto DisableWizNext; + } + } + } + else + { +DisableWizNext: + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects a valid partition. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); + } + } + + break; + } + switch (lpnm->code) - { + { +#if 0 case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + { + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects a valid partition. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); break; + } +#endif + + case PSN_QUERYINITIALFOCUS: + { + /* Give the focus on and select the first item */ + hList = GetDlgItem(hwndDlg, IDC_PARTITION); + // TreeList_SetFocusItem(hList, 1, 1); + TreeList_SelectItem(hList, 1); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)hList); + return TRUE; + } case PSN_QUERYCANCEL: { @@ -274,6 +776,28 @@ DriveDlgProc( return TRUE; } + case PSN_WIZNEXT: /* Set the selected data */ + { + NTSTATUS Status; + + /****/ + // FIXME: This is my test disk encoding! + DISKENTRY DiskEntry; + PARTENTRY PartEntry; + DiskEntry.DiskNumber = 0; + DiskEntry.BiosDiskNumber = 0; + PartEntry.PartitionNumber = 1; // 4; + /****/ + + Status = InitDestinationPaths(&pSetupData->USetupData, + NULL, // pSetupData->USetupData.InstallationDirectory, + &DiskEntry, &PartEntry); + // TODO: Check Status + UNREFERENCED_PARAMETER(Status); + + break; + } + default: break; } @@ -282,7 +806,6 @@ DriveDlgProc( default: break; - } return FALSE; diff --git a/base/setup/reactos/reactos.c b/base/setup/reactos/reactos.c index 230eafa38c9..55b18a227ea 100644 --- a/base/setup/reactos/reactos.c +++ b/base/setup/reactos/reactos.c @@ -124,15 +124,15 @@ StartDlgProc( pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); - /* Center the wizard window */ - CenterWindow(GetParent(hwndDlg)); - /* Set title font */ SendDlgItemMessage(hwndDlg, IDC_STARTTITLE, WM_SETFONT, (WPARAM)pSetupData->hTitleFont, (LPARAM)TRUE); + + /* Center the wizard window */ + CenterWindow(GetParent(hwndDlg)); break; } @@ -212,6 +212,13 @@ TypeDlgProc( PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); break; + case PSN_QUERYINITIALFOCUS: + { + /* Focus on "Install ReactOS" */ + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_INSTALL)); + return TRUE; + } + case PSN_QUERYCANCEL: { if (MessageBoxW(GetParent(hwndDlg), @@ -230,23 +237,40 @@ TypeDlgProc( case PSN_WIZNEXT: /* Set the selected data */ { - pSetupData->RepairUpdateFlag = - !(SendMessageW(GetDlgItem(hwndDlg, IDC_INSTALL), - BM_GETCHECK, - 0, 0) == BST_CHECKED); - /* - * Display the existing NT installations page only - * if we have more than one available NT installations. + * Go update only if we have available NT installations + * and we choose to do so. */ if (pSetupData->NtOsInstallsList && - GetNumberOfListEntries(pSetupData->NtOsInstallsList) > 1) + GetNumberOfListEntries(pSetupData->NtOsInstallsList) != 0 && + IsDlgButtonChecked(hwndDlg, IDC_UPDATE) == BST_CHECKED) { - /* Actually the best would be to dynamically insert the page only when needed */ - SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_UPDATEREPAIRPAGE); + pSetupData->RepairUpdateFlag = TRUE; + + /* + * Display the existing NT installations page only + * if we have more than one available NT installations. + */ + if (GetNumberOfListEntries(pSetupData->NtOsInstallsList) > 1) + { + /* pSetupData->CurrentInstallation will be set from within IDD_UPDATEREPAIRPAGE */ + + /* Actually the best would be to dynamically insert the page only when needed */ + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_UPDATEREPAIRPAGE); + } + else + { + /* Retrieve the current installation */ + pSetupData->CurrentInstallation = + (PNTOS_INSTALLATION)GetListEntryData(GetCurrentListEntry(pSetupData->NtOsInstallsList)); + + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_DEVICEPAGE); + } } else { + pSetupData->CurrentInstallation = NULL; + pSetupData->RepairUpdateFlag = FALSE; SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, IDD_DEVICEPAGE); } @@ -268,6 +292,39 @@ TypeDlgProc( +BOOL +CreateListViewColumns( + IN HINSTANCE hInstance, + IN HWND hWndListView, + IN const UINT* pIDs, + IN const INT* pColsWidth, + IN const INT* pColsAlign, + IN UINT nNumOfColumns) +{ + UINT i; + LVCOLUMN lvC; + WCHAR szText[50]; + + /* Create the columns */ + lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvC.pszText = szText; + + /* Load the column labels from the resource file */ + for (i = 0; i < nNumOfColumns; i++) + { + lvC.iSubItem = i; + lvC.cx = pColsWidth[i]; + lvC.fmt = pColsAlign[i]; + + LoadStringW(hInstance, pIDs[i], szText, ARRAYSIZE(szText)); + + if (ListView_InsertColumn(hWndListView, i, &lvC) == -1) + return FALSE; + } + + return TRUE; +} + typedef VOID (NTAPI *PGET_ENTRY_DESCRIPTION)( IN PGENERIC_LIST_ENTRY Entry, @@ -312,19 +369,17 @@ InitGenericComboList( SendMessageW(hWndList, CB_SETCURSEL, CurrentEntryIndex, 0); } -INT +PVOID GetSelectedComboListItem( IN HWND hWndList) { - LRESULT Index; + INT Index; - Index = SendMessageW(hWndList, CB_GETCURSEL, 0, 0); + Index = ComboBox_GetCurSel(hWndList); if (Index == CB_ERR) - return CB_ERR; + return NULL; - // TODO: Update List->CurrentEntry? - // return SendMessageW(hWndList, CB_GETITEMDATA, (WPARAM)Index, 0); - return Index; + return (PVOID)ComboBox_GetItemData(hWndList, Index); } typedef VOID @@ -366,9 +421,28 @@ InitGenericListView( CurrentEntryIndex = lvItem.iItem; } - SendMessageW(hWndList, LVM_ENSUREVISIBLE, CurrentEntryIndex, FALSE); - ListView_SetItemState(hWndList, CurrentEntryIndex, LVIS_SELECTED, LVIS_SELECTED); - ListView_SetItemState(hWndList, CurrentEntryIndex, LVIS_FOCUSED, LVIS_FOCUSED); + ListView_EnsureVisible(hWndList, CurrentEntryIndex, FALSE); + ListView_SetItemState(hWndList, CurrentEntryIndex, + LVIS_FOCUSED | LVIS_SELECTED, + LVIS_FOCUSED | LVIS_SELECTED); +} + +PVOID +GetSelectedListViewItem( + IN HWND hWndList) +{ + INT Index; + LVITEM item; + + Index = ListView_GetSelectionMark(hWndList); + if (Index == LB_ERR) + return NULL; + + item.mask = LVIF_PARAM; + item.iItem = Index; + ListView_GetItem(hWndList, &item); + + return (PVOID)item.lParam; } @@ -399,7 +473,7 @@ AddNTOSInstallationItem( { /* We have retrieved a partition that is mounted */ StringCchPrintfW(Buffer, cchBufferSize, - L"%C:%s", + L"%c:%s", PartEntry->DriveLetter, NtOsInstall->PathComponent); } @@ -471,8 +545,16 @@ UpgradeRepairDlgProc( pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects an installation to upgrade. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); + hList = GetDlgItem(hwndDlg, IDC_NTOSLIST); + ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + CreateListViewColumns(pSetupData->hInstance, hList, column_ids, @@ -494,7 +576,6 @@ UpgradeRepairDlgProc( ListView_SetImageList(hList, hSmall, LVSIL_SMALL); InitGenericListView(hList, pSetupData->NtOsInstallsList, AddNTOSInstallationItem); - break; } @@ -507,15 +588,70 @@ UpgradeRepairDlgProc( return TRUE; } + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_SKIPUPGRADE: + { + /* Skip the upgrade and do the usual new-installation workflow */ + pSetupData->CurrentInstallation = NULL; + pSetupData->RepairUpdateFlag = FALSE; + PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_DEVICEPAGE); + return TRUE; + } + } + break; + case WM_NOTIFY: { LPNMHDR lpnm = (LPNMHDR)lParam; + if (lpnm->idFrom == IDC_NTOSLIST && lpnm->code == LVN_ITEMCHANGED) + { + LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; + + if (pnmv->uChanged & LVIF_STATE) /* The state has changed */ + { + /* The item has been (de)selected */ + if (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED)) + { + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + } + else + { + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects an installation to upgrade. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); + } + } + + break; + } + switch (lpnm->code) { +#if 0 case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + { + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user selects an installation to upgrade. + */ + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); break; + } +#endif + + case PSN_QUERYINITIALFOCUS: + { + /* Give the focus on and select the first item */ + hList = GetDlgItem(hwndDlg, IDC_NTOSLIST); + ListView_SetItemState(hList, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)hList); + return TRUE; + } case PSN_QUERYCANCEL: { @@ -534,11 +670,31 @@ UpgradeRepairDlgProc( } case PSN_WIZNEXT: /* Set the selected data */ - pSetupData->RepairUpdateFlag = - !(SendMessageW(GetDlgItem(hwndDlg, IDC_INSTALL), - BM_GETCHECK, - 0, 0) == BST_CHECKED); + { + /* + * Go update only if we have available NT installations + * and we choose to do so. + */ + if (!pSetupData->NtOsInstallsList || + GetNumberOfListEntries(pSetupData->NtOsInstallsList) == 0) + { + pSetupData->CurrentInstallation = NULL; + pSetupData->RepairUpdateFlag = FALSE; + break; + } + + hList = GetDlgItem(hwndDlg, IDC_NTOSLIST); + SetCurrentListEntry(pSetupData->NtOsInstallsList, + GetSelectedListViewItem(hList)); + + /* Retrieve the current installation */ + pSetupData->CurrentInstallation = + (PNTOS_INSTALLATION)GetListEntryData(GetCurrentListEntry(pSetupData->NtOsInstallsList)); + + /* We perform an upgrade */ + pSetupData->RepairUpdateFlag = TRUE; return TRUE; + } default: break; @@ -599,6 +755,13 @@ DeviceDlgProc( PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); break; + case PSN_QUERYINITIALFOCUS: + { + /* Focus on "Computer" list */ + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_COMPUTER)); + return TRUE; + } + case PSN_QUERYCANCEL: { if (MessageBoxW(GetParent(hwndDlg), @@ -618,13 +781,20 @@ DeviceDlgProc( case PSN_WIZNEXT: /* Set the selected data */ { hList = GetDlgItem(hwndDlg, IDC_COMPUTER); - pSetupData->SelectedComputer = GetSelectedComboListItem(hList); + SetCurrentListEntry(pSetupData->USetupData.ComputerList, + GetSelectedComboListItem(hList)); hList = GetDlgItem(hwndDlg, IDC_DISPLAY); - pSetupData->SelectedDisplay = GetSelectedComboListItem(hList); + SetCurrentListEntry(pSetupData->USetupData.DisplayList, + GetSelectedComboListItem(hList)); hList = GetDlgItem(hwndDlg, IDC_KEYBOARD); - pSetupData->SelectedKeyboard = GetSelectedComboListItem(hList); + SetCurrentListEntry(pSetupData->USetupData.KeyboardList, + GetSelectedComboListItem(hList)); + + // hList = GetDlgItem(hwndDlg, IDC_KEYBOARD_LAYOUT); + // SetCurrentListEntry(pSetupData->USetupData.LayoutList, + // GetSelectedComboListItem(hList)); return TRUE; } @@ -649,6 +819,8 @@ SummaryDlgProc( IN WPARAM wParam, IN LPARAM lParam) { + static WCHAR szOrgWizNextBtnText[260]; // TODO: Make it dynamic + PSETUPDATA pSetupData; /* Retrieve pointer to the global setup data */ @@ -657,10 +829,24 @@ SummaryDlgProc( switch (uMsg) { case WM_INITDIALOG: + { /* Save pointer to the global setup data */ pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); break; + } + + case WM_COMMAND: + { + if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_CONFIRM_INSTALL) + { + if (IsDlgButtonChecked(hwndDlg, IDC_CONFIRM_INSTALL) == BST_CHECKED) + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + else + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); + } + break; + } case WM_NOTIFY: { @@ -669,8 +855,92 @@ SummaryDlgProc( switch (lpnm->code) { case PSN_SETACTIVE: - PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT); + { + WCHAR CurrentItemText[256]; + + /* Show the current selected settings */ + + // FIXME! Localize + if (pSetupData->RepairUpdateFlag) + { + StringCchPrintfW(CurrentItemText, ARRAYSIZE(CurrentItemText), + L"Upgrading/Repairing \"%s\" from \"%s\"", + pSetupData->CurrentInstallation->InstallationName, + pSetupData->CurrentInstallation->VendorName); + } + else + { + StringCchCopyW(CurrentItemText, ARRAYSIZE(CurrentItemText), + L"New ReactOS installation"); + } + SetDlgItemTextW(hwndDlg, IDC_INSTALLTYPE, CurrentItemText); + + SetDlgItemTextW(hwndDlg, IDC_INSTALLSOURCE, L"n/a"); + SetDlgItemTextW(hwndDlg, IDC_ARCHITECTURE, L"n/a"); + + GetSettingDescription(GetCurrentListEntry(pSetupData->USetupData.ComputerList), + CurrentItemText, + ARRAYSIZE(CurrentItemText)); + SetDlgItemTextW(hwndDlg, IDC_COMPUTER, CurrentItemText); + + GetSettingDescription(GetCurrentListEntry(pSetupData->USetupData.DisplayList), + CurrentItemText, + ARRAYSIZE(CurrentItemText)); + SetDlgItemTextW(hwndDlg, IDC_DISPLAY, CurrentItemText); + + GetSettingDescription(GetCurrentListEntry(pSetupData->USetupData.KeyboardList), + CurrentItemText, + ARRAYSIZE(CurrentItemText)); + SetDlgItemTextW(hwndDlg, IDC_KEYBOARD, CurrentItemText); + + if (L'C') // FIXME! + { + StringCchPrintfW(CurrentItemText, ARRAYSIZE(CurrentItemText), + L"%c: \x2014 %wZ", + L'C', // FIXME! + &pSetupData->USetupData.DestinationRootPath); + } + else + { + StringCchPrintfW(CurrentItemText, ARRAYSIZE(CurrentItemText), + L"%wZ", + &pSetupData->USetupData.DestinationRootPath); + } + SetDlgItemTextW(hwndDlg, IDC_DESTDRIVE, CurrentItemText); + + SetDlgItemTextW(hwndDlg, IDC_PATH, + /*pSetupData->USetupData.InstallationDirectory*/ + pSetupData->USetupData.InstallPath.Buffer); + + + /* Change the "Next" button text to "Install" */ + // PropSheet_SetNextText(GetParent(hwndDlg), ...); + GetDlgItemTextW(GetParent(hwndDlg), ID_WIZNEXT, + szOrgWizNextBtnText, ARRAYSIZE(szOrgWizNextBtnText)); + SetDlgItemTextW(GetParent(hwndDlg), ID_WIZNEXT, L"Install"); // FIXME: Localize! + + /* + * Keep the "Next" button disabled. It will be enabled only + * when the user clicks on the installation approval checkbox. + */ + CheckDlgButton(hwndDlg, IDC_CONFIRM_INSTALL, BST_UNCHECKED); + PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK); break; + } + + case PSN_QUERYINITIALFOCUS: + { + /* Focus on the confirmation check-box */ + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_CONFIRM_INSTALL)); + return TRUE; + } + + case PSN_KILLACTIVE: + { + /* Restore the original "Next" button text */ + SetDlgItemTextW(GetParent(hwndDlg), ID_WIZNEXT, szOrgWizNextBtnText); + break; + } case PSN_QUERYCANCEL: { @@ -691,8 +961,8 @@ SummaryDlgProc( default: break; } + break; } - break; default: break; @@ -832,13 +1102,18 @@ PrepareAndDoCopyThread( /* Retrieve pointer to the global setup data */ pSetupData = (PSETUPDATA)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA); + /* Get the progress handle */ + hWndProgress = GetDlgItem(hwndDlg, IDC_PROCESSPROGRESS); + + + /* + * Preparation of the list of files to be copied + */ + /* Set status text */ SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"Preparing the list of files to be copied, please wait..."); SetDlgItemTextW(hwndDlg, IDC_ITEM, L""); - /* Get the progress handle */ - hWndProgress = GetDlgItem(hwndDlg, IDC_PROCESSPROGRESS); - /* Set progress marquee style */ dwStyle = GetWindowLongPtrW(hWndProgress, GWL_STYLE); SetWindowLongPtrW(hWndProgress, GWL_STYLE, dwStyle | PBS_MARQUEE); @@ -876,8 +1151,14 @@ PrepareAndDoCopyThread( /* Restore progress style */ SetWindowLongPtrW(hWndProgress, GWL_STYLE, dwStyle); + + /* + * Perform the file copy + */ + /* Set status text */ SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L"Copying the files..."); + SetDlgItemTextW(hwndDlg, IDC_ITEM, L""); /* Create context for the copy process */ CopyContext.pSetupData = pSetupData; @@ -932,16 +1213,6 @@ ProcessDlgProc( { case WM_INITDIALOG: { - NTSTATUS Status; - /****/ - // FIXME: This is my disk encoding! - DISKENTRY DiskEntry; - PARTENTRY PartEntry; - DiskEntry.DiskNumber = 1; - DiskEntry.BiosDiskNumber = 1; - PartEntry.PartitionNumber = 4; - /****/ - /* Save pointer to the global setup data */ pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam; SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); @@ -950,10 +1221,6 @@ ProcessDlgProc( SetDlgItemTextW(hwndDlg, IDC_ACTIVITY, L""); SetDlgItemTextW(hwndDlg, IDC_ITEM, L""); - Status = InitDestinationPaths(&pSetupData->USetupData, NULL /*InstallDir*/, &DiskEntry, &PartEntry); - // TODO: Check Status - UNREFERENCED_PARAMETER(Status); - break; } @@ -1069,11 +1336,11 @@ RestartDlgProc( SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pSetupData); /* Set title font */ - /*SendDlgItemMessage(hwndDlg, - IDC_STARTTITLE, - WM_SETFONT, - (WPARAM)hTitleFont, - (LPARAM)TRUE);*/ + SendDlgItemMessage(hwndDlg, + IDC_FINISHTITLE, + WM_SETFONT, + (WPARAM)pSetupData->hTitleFont, + (LPARAM)TRUE); break; case WM_TIMER: @@ -1104,12 +1371,18 @@ RestartDlgProc( switch (lpnm->code) { - case PSN_SETACTIVE: // Only "Finish" for closing the App + case PSN_SETACTIVE: + { + /* Only "Finish" for closing the wizard */ + ShowWindow(GetDlgItem(GetParent(hwndDlg), IDCANCEL), SW_HIDE); PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH); + + /* Set up the reboot progress bar */ SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 300)); SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0); SetTimer(hwndDlg, 1, 50, NULL); break; + } default: break; @@ -1509,6 +1782,55 @@ Quit: return Success; } +/* Copied from HotkeyThread() in dll/win32/syssetup/install.c */ +static DWORD CALLBACK +HotkeyThread(LPVOID Parameter) +{ + ATOM hotkey; + MSG msg; + + DPRINT("HotkeyThread start\n"); + + hotkey = GlobalAddAtomW(L"Setup Shift+F10 Hotkey"); + + if (!RegisterHotKey(NULL, hotkey, MOD_SHIFT, VK_F10)) + DPRINT1("RegisterHotKey failed with %lu\n", GetLastError()); + + while (GetMessageW(&msg, NULL, 0, 0)) + { + if (msg.hwnd == NULL && msg.message == WM_HOTKEY && msg.wParam == hotkey) + { + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi; + + if (CreateProcessW(L"cmd.exe", + NULL, + NULL, + NULL, + FALSE, + CREATE_NEW_CONSOLE, + NULL, + NULL, + &si, + &pi)) + { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + else + { + DPRINT1("Failed to launch command prompt: %lu\n", GetLastError()); + } + } + } + + UnregisterHotKey(NULL, hotkey); + GlobalDeleteAtom(hotkey); + + DPRINT("HotkeyThread terminate\n"); + return 0; +} + int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, @@ -1516,6 +1838,7 @@ _tWinMain(HINSTANCE hInst, int nCmdShow) { ULONG Error; + HANDLE hHotkeyThread; INITCOMMONCONTROLSEX iccx; PROPSHEETHEADER psh; HPROPSHEETPAGE ahpsp[8]; @@ -1556,6 +1879,8 @@ _tWinMain(HINSTANCE hInst, if (!LoadSetupData(&SetupData)) goto Quit; + hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL); + CheckUnattendedSetup(&SetupData.USetupData); SetupData.bUnattend = IsUnattendedSetup; // FIXME :-) @@ -1570,6 +1895,10 @@ _tWinMain(HINSTANCE hInst, iccx.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_PROGRESS_CLASS; InitCommonControlsEx(&iccx); + /* Register the TreeList control */ + // RegisterTreeListClass(hInst); + TreeListRegister(hInst); + /* Create title font */ SetupData.hTitleFont = CreateTitleFont(); @@ -1582,74 +1911,74 @@ _tWinMain(HINSTANCE hInst, psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = StartDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_STARTPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_STARTPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the install type selection page */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_TYPETITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_TYPESUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = TypeDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_TYPEPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_TYPEPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the upgrade/repair selection page */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_TYPETITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_TYPESUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_TYPETITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_TYPESUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = UpgradeRepairDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_UPDATEREPAIRPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_UPDATEREPAIRPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the device settings page */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DEVICETITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DEVICESUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_DEVICETITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_DEVICESUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = DeviceDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_DEVICEPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_DEVICEPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the install device settings page / boot method / install directory */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DRIVETITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DRIVESUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_DRIVETITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_DRIVESUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = DriveDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVEPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_DRIVEPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the summary page */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_SUMMARYTITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_SUMMARYSUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_SUMMARYTITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_SUMMARYSUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = SummaryDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_SUMMARYPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_SUMMARYPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); } /* Create the installation progress page */ psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; - psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE); - psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE); + psp.pszHeaderTitle = MAKEINTRESOURCEW(IDS_PROCESSTITLE); + psp.pszHeaderSubTitle = MAKEINTRESOURCEW(IDS_PROCESSSUBTITLE); psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = ProcessDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_PROCESSPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the finish-and-reboot page */ @@ -1658,7 +1987,7 @@ _tWinMain(HINSTANCE hInst, psp.hInstance = hInst; psp.lParam = (LPARAM)&SetupData; psp.pfnDlgProc = RestartDlgProc; - psp.pszTemplate = MAKEINTRESOURCE(IDD_RESTARTPAGE); + psp.pszTemplate = MAKEINTRESOURCEW(IDD_RESTARTPAGE); ahpsp[nPages++] = CreatePropertySheetPage(&psp); /* Create the property sheet */ @@ -1669,16 +1998,12 @@ _tWinMain(HINSTANCE hInst, psh.nPages = nPages; psh.nStartPage = 0; psh.phpage = ahpsp; - psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK); - psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER); + psh.pszbmWatermark = MAKEINTRESOURCEW(IDB_WATERMARK); + psh.pszbmHeader = MAKEINTRESOURCEW(IDB_HEADER); /* Display the wizard */ PropertySheet(&psh); - if (SetupData.hTitleFont) - DeleteObject(SetupData.hTitleFont); - -Quit: /* Wait for any pending installation */ WaitForSingleObject(SetupData.hInstallThread, INFINITE); CloseHandle(SetupData.hInstallThread); @@ -1686,6 +2011,20 @@ Quit: CloseHandle(SetupData.hHaltInstallEvent); SetupData.hHaltInstallEvent = NULL; + if (SetupData.hTitleFont) + DeleteObject(SetupData.hTitleFont); + + /* Unregister the TreeList control */ + // UnregisterTreeListClass(hInst); + TreeListUnregister(hInst); + + if (hHotkeyThread) + { + PostThreadMessageW(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0); + CloseHandle(hHotkeyThread); + } + +Quit: /* Setup has finished */ FinishSetup(&SetupData.USetupData); diff --git a/base/setup/reactos/reactos.h b/base/setup/reactos/reactos.h index ded1d85f74b..23e23afa132 100644 --- a/base/setup/reactos/reactos.h +++ b/base/setup/reactos/reactos.h @@ -43,6 +43,19 @@ #include #include +#include + +/* These are public names and values determined from MFC, and compatible with Windows */ +// Property Sheet control id's (determined with Spy++) +#define IDC_TAB_CONTROL 0x3020 +#define ID_APPLY_NOW 0x3021 +#define ID_WIZBACK 0x3023 +#define ID_WIZNEXT 0x3024 +#define ID_WIZFINISH 0x3025 + + +#include "treelist.h" + /**/#include /**/ #include @@ -123,17 +136,13 @@ typedef struct _SETUPDATA /* Settings */ LONG DestPartSize; // if partition doesn't exist, size of partition - LONG FSType; // file system type on partition - LONG FormatPart; // type of format the partition + LONG FSType; // file system type on partition + LONG FormatPart; // type of format the partition LONG SelectedLangId; // selected language (table index) - LONG SelectedKBLayout; // selected keyboard layout (table index) - LONG SelectedComputer; // selected computer type (table index) - LONG SelectedDisplay; // selected display type (table index) - LONG SelectedKeyboard; // selected keyboard type (table index) /* txtsetup.sif data */ - // LONG DefaultLang; // default language (table index) + // LONG DefaultLang; // default language (table index) // LONG DefaultKBLayout; // default keyboard layout (table index) PCWSTR SelectedLanguageId; WCHAR DefaultLanguage[20]; // Copy of string inside LanguageList @@ -147,14 +156,6 @@ extern BOOLEAN IsUnattendedSetup; extern SETUPDATA SetupData; -typedef struct _IMGINFO -{ - HBITMAP hBitmap; - INT cxSource; - INT cySource; -} IMGINFO, *PIMGINFO; - - /* * Attempts to convert a pure NT file path into a corresponding Win32 path. * Adapted from GetInstallSourceWin32() in dll/win32/syssetup/wizard.c