web-dev-qa-db-ja.com

親と異なるVirtualPCハードディスクのパスを設定する方法

以前のシステムからバックアップされた古いWindows XP Mode vhdがありますが、新しいシステムで実行するのに問題があります。

Vhdは差分ディスクであり、その親は標準のWindows XPモードベースです。まだ古い親があり、XP XPモードの新しいインストールのモードベース。

ただし、新しいシステムでは、差分ディスクの親へのパスが古いシステムとは異なります。

古いXPモード)の.vmcxの設定を開き、[ハードディスク1]を選択すると、[仮想ハードディスクファイル]は正しく設定されますが、[親ディスク: 「フィールドが間違ったパスを指していて、編集する方法がわかりません。

誰かが方法を知っていますか?

3
Barry Kelly

OK、私はこの問題を自分で解決しましたが、それは不当に困難でした。

親へのパスは、.vhd内にいくつかの異なる形式でハードコードされています。私の場合、相対パスと絶対パスの両方、ASCIIとUTF-16の両方で、合計4つのパス。vhdファイル形式の仕様を取得できます Microsoftから

ただし、文字列データを検索する strings または同様のユーティリティ(ここでは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

これらの文字列は、多くのnullバイトパディングで格納されます。 16進エディターを使用して、新しい場所へのパスを更新しました。

しかし、それは機能しませんでした。パスは、VirtualPC設定エディターで切り捨てられて表示されました。文字列の長さは他の場所でエンコードされます。私の場合、0x4AB、0x4C3などです(古いパスの長さを16進検索しました)。これらの長さを更新しましたが、VirtualPC設定エディターによってvhdが無効と見なされました。チェックサムが含まれていることを理解し、VHD仕様をダウンロードし、.docを読み取れるようにWord文書ビューアーをインストールしてから、以下のプログラムを作成しました。 vhdへのパスが渡されると、その出力は更新されたチェックサムとチェックサムの場所になります。出力例:

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

16進エディターでこの新しいチェックサムを入力すると、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-to-change-the-parent-of-a-differencing-vhd-when-the-parent-has-moved /

本質的に:

$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
2
Barry Kelly

または、.VHDファイルを操作するためのC++コードを記述したくない場合は次のようにします。

... Virtual PCから、[仮想ディスクウィザード]、[既存の仮想ディスクの編集]を選択し、障害のある差分ディスクを選択すると、次のメッセージが表示されます。

親仮想ハードディスクが削除されたか、以前の場所から移動されました。親仮想ハードディスクの新しい場所を選択してください。」

[変更...]をクリックして、親ディスクを見つけます。

2
Oli B