3

У меня есть старый Windows XP Mode, резервная копия VHD из моей предыдущей системы, но у меня возникают трудности с его запуском на новой системе.

VHD - это разностный диск, а его родительский элемент - стандартная база режима Windows XP; У меня все еще есть старый родитель, и я убедился, что он является двоичным идентичным базе XP Mode в моей новой установке XP Mode.

Но в новой системе путь к родительскому элементу разностного диска отличается от старого.

Когда я открываю настройки для .vmcx для моего старого режима XP и выбираю "Жесткий диск 1", "Файл виртуального жесткого диска" устанавливается правильно, но поле «Родительский диск:» указывает на неверный путь, и я не вижу способа отредактировать его.

Кто-нибудь знает как?

2 ответа2

2

В качестве альтернативы, если вы предпочитаете не писать код C++ для манипулирования.VHD файл:

... из Virtual PC, выберите «Virtual Disk Wizard», «Edit существующий виртуальный диск» и выберите неисправный разностный диск, вы получите следующее сообщение:

Msgstr "Родительский виртуальный жесткий диск был удалён или был перемещён из предыдущего места. Пожалуйста, выберите новое местоположение родительского виртуального жесткого диска. "

Нажмите [Изменить ...] и найдите родительский диск.

2

Хорошо, я решил эту проблему сам, но это было неоправданно сложно.

Путь к родителю жестко закодирован в .vhd в нескольких различных форматах; в моем случае как относительные, так и абсолютные пути, как в ASCII, так и в UTF-16, для 4 полных путей. Вы можете получить спецификацию формата файла .vhd от Microsoft.

Но быстрое сканирование со строками или аналогичная утилита (я использую Cygwin здесь), которая ищет строковые данные, может найти эти смещения легче, чем обход структур VHD:

$ strings -t x Windows\ XP\ Mode-X.vhd | head -200 | grep vhd
40000 ..\..\..\..\..\..\..\other\xp-mode\Windows XP Mode base.vhd
40200 C:\other\xp-mode\Windows XP Mode base.vhd
$ strings -t x -e l Windows\ XP\ Mode-X.vhd | head -200 | grep vhd
40400 ..\..\..\..\..\..\..\other\xp-mode\Windows XP Mode base.vhd
40600 C:\other\xp-mode\Windows XP Mode base.vhd

Эти строки хранятся с большим количеством пустых байтов; Я использовал шестнадцатеричный редактор, чтобы обновить пути к новым местам.

Но это не сработало; пути были показаны усеченными в редакторе настроек Virtual PC. Длина строки кодируется в другом месте; в моем случае 0x4AB, 0x4C3 и т. д. (Я сделал шестнадцатеричный поиск старых путей). Я обновил эти длины, но тогда редактор VHD считал недействительным VHD. Я решил, что теперь включена контрольная сумма, скачал спецификацию VHD, установил средство просмотра документов Word, чтобы я мог прочитать .doc, а затем я написал программу ниже. Его вывод, когда передается путь к VHD, является обновленной контрольной суммой и местоположением контрольной суммы; пример вывода:

opening Windows XP Mode-X.vhd
dynamic header seems to be at 0x200
new checksum: ffffda30 at 0x224

Ввод этой новой контрольной суммы с помощью шестнадцатеричного редактора заставил VHD работать, и старый режим XP успешно загрузился.

Программа расчета контрольной суммы:

#include <fcntl.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <unistd.h>

const int checksum_offset = 36;

long long flip_endian_ll(long long x)
{
    return ((x & 0x00000000000000FFULL) << 56)
        |  ((x & 0x000000000000FF00ULL) << 40)
        |  ((x & 0x0000000000FF0000ULL) << 24)
        |  ((x & 0x00000000FF000000ULL) << 8)
        |  ((x & 0x000000FF00000000ULL) >> 8)
        |  ((x & 0x0000FF0000000000ULL) >> 24)
        |  ((x & 0x00FF000000000000ULL) >> 40)
        |  ((x & 0xFF00000000000000ULL) >> 56);
}

int die(const char *msg)
{
    fprintf(stderr, "error: %s\n", msg);
    exit(1);
}

int main(int argc, const char *const *args)
{
    int f, r;
    long long dyn_ofs;
    unsigned char dyn_header[1024];

    if (argc != 2)
    {
        fprintf(stderr, "expected: .vhd argument\n");
        return 1;
    }

    printf("opening %s\n", args[1]);
    f = open(args[1], O_RDONLY | O_BINARY);
    if (f < 0)
        die("failed open");
    r = lseek(f, 0x10, SEEK_SET);
    if (r < 0)
        die("seek failed");
    r = read(f, &dyn_ofs, sizeof(dyn_ofs));
    if (r != 8)
        die("failed read");
    dyn_ofs = flip_endian_ll(dyn_ofs);
    printf("dynamic header seems to be at 0x%llx\n", dyn_ofs);

    r = lseek(f, dyn_ofs, SEEK_SET);
    if (r < 0)
        die("seek failed");
    r = read(f, dyn_header, sizeof(dyn_header));
    if (r != sizeof(dyn_header))
        die("read of dynamic header failed");

    if (memcmp("cxsparse", dyn_header, 8) != 0)
        die("dynamic header didn't start with cxsparse");

    {
        unsigned long sum = 0;
        int i;

        for (i = checksum_offset; i < checksum_offset + 4; ++i)
            dyn_header[i] = 0;
        for (i = 0; i < sizeof(dyn_header); ++i)
            sum += dyn_header[i];
        sum = ~sum; // flip_endian_l(~sum);
        printf("new checksum: %.8x at 0x%llx\n", sum, dyn_ofs + checksum_offset);
    }
    return 0;
}

Это стоило мне нескольких часов, но в итоге я справился. Я уверен, что кто-то в конечном итоге выложит VHD-редактор, который сделает это проще, но, по крайней мере, я снова попал в свой старый режим XP.

Обновление: есть гораздо более простой способ сделать это, используя PowerShell для создания сценариев некоторых COM-объектов: https://obligatorymoniker.wordpress.com/2010/08/21/how-to-rebase-differencing-disk-vhds-or-how -в-изменение-The-родитель-о-а-разностного-VHD-когда-The-родитель-имеет-переместил /

По сути:

$vpc=new-object -com VirtualPC.Application
$VHDChild = $vpc.GetHardDisk("C:\NAV2010.06.10_Diff")
$VHDParent = $vpc.GetHardDisk("\\devnas\Data_Backups SQLCluster1\NAV2010.06.10.vhd")
$VHDChild.Parent = $VHDParent

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .