Como definir o caminho do pai de diferenciação de disco rígido do Virtual PC

3

Eu tenho um antigo vhd do Windows XP Mode com backup do meu sistema anterior, mas estou com dificuldades para executá-lo no novo sistema.

O vhd é um disco diferencial e seu pai é a base padrão do Windows XP Mode; Eu ainda tenho o antigo pai, e verifiquei que é binário idêntico ao XP Mode na minha nova instalação do XP Mode.

Mas no novo sistema, o caminho para o pai do disco diferencial é diferente do antigo.

Quando abro as configurações do .vmcx para o meu antigo modo XP e seleciono "Disco Rígido 1", o "Arquivo do disco rígido virtual" está definido corretamente, mas o campo "Disco principal:" está apontando para o caminho errado, e não consigo ver como editá-lo.

Alguém sabe como?

    
por Barry Kelly 09.06.2012 / 23:49

2 respostas

2

OK, eu mesmo resolvi esse problema, mas foi extremamente difícil.

O caminho para o pai é codificado dentro do .vhd, em vários formatos diferentes; no meu caso, ambos os caminhos relativo e absoluto, em ASCII e UTF-16, para 4 caminhos totais. Você pode obter a especificação de formato de arquivo .vhd da Microsoft .

Mas uma verificação rápida com strings ou um utilitário semelhante (estou usando o Cygwin aqui) pesquisas por dados de string podem encontrar esses deslocamentos mais facilmente do que percorrer as estruturas de 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

Essas cadeias são armazenadas com muitos preenchimentos de bytes nulos; Eu usei um editor hexadecimal para atualizar os caminhos para novos locais.

Mas não funcionou; os caminhos foram mostrados truncados no editor de configurações do Virtual PC. Os comprimentos de string são codificados em outro lugar; no meu caso em 0x4AB, 0x4C3, etc. (Eu fiz uma pesquisa hexadecimal para os comprimentos do caminho antigo). Eu atualizei esses comprimentos, mas o vhd foi considerado inválido pelo editor de configurações do Virtual PC. Eu percebi que uma soma de verificação agora estava envolvida, baixei a especificação VHD, instalei o visualizador de documentos do Word para que eu pudesse ler o arquivo .doc, e então eu escrevi o programa abaixo. Sua saída, quando entregue o caminho para o vhd, é a soma de verificação atualizada e a localização da soma de verificação; exemplo de saída:

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

A inserção dessa nova soma de verificação com um editor hexadecimal fez o vhd funcionar e o modo XP antigo foi inicializado com êxito.

Programa de cálculo da soma de verificação:

#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;
}

Isso me custou algumas horas, mas eu passei no final. Tenho certeza de que alguém acabará postando um editor de VHD que faz isso mais facilmente, mas pelo menos eu passei para o meu antigo modo XP mais uma vez.

Atualização: Há uma maneira muito mais fácil de fazer isso, usando o PowerShell para criar scripts de alguns objetos COM: link

Em essência:

$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
    
por 10.06.2012 / 03:16
2

Alternativamente, se você preferir não escrever código C ++ para manipular o arquivo .VHD:

... do Virtual PC, selecione 'Virtual Disk Wizard', 'Edite um disco virtual existente' e selecione o disco diferencial com falha, você receberá a seguinte mensagem:

"The parent virtual hard disk has been deleted or has been moved from its previous location. Please select the new location of the parent virtual hard disk."

Clique em [Alterar ...] e localize o disco pai.

    
por 31.01.2013 / 17:26