//51CTO首发此文,转载请保留完整信息
本工程主要由vhd2img.cpp layout.h组成,C代码实现。
vhd2img.cpp:
- // vhd2img.cpp : 定义控制台应用程序的入口点。
- //by www.frombyte.cn zhangyu
- //北亚数据恢复中心(www.sjhf.net)张宇 2012/1/6 发表于51cto
- #include "stdafx.h"
- #include <windows.h>
- #include "layout.h"
- #define VHD_OPENED 1
- #define VHD_UNOPEN 0
- #define BIT_MASK 0x80
- static inline int test_bit (byte *addr, u32 nr)
- {
- return ((addr[nr >> 3] << (nr & 7)) & BIT_MASK) != 0;
- };
- static inline void set_bit (byte *addr, u32 nr)
- {
- addr[nr >> 3] |= (BIT_MASK >> (nr & 7));
- }
- HANDLE hIn,hOut;
- struct vhd_info
- {
- u64 uSize;
- u32 *bat;
- byte *batmap;
- u64 uBlkSize;
- u64 uBatNum;
- u32 spb; //secters per block
- u32 log2spb;
- u32 vhd_status;
- bool is_have_batmap;
- };
- int open_vhd(TCHAR *name,vhd_info &vhd)
- {
- hd_ftr vhd_head;
- hIn = CreateFile(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
- if(hIn == INVALID_HANDLE_VALUE)
- {
- _tprintf(_T("ERROR%d:source VHD file open error!\n"),GetLastError());
- return -1;
- }
- DWORD bRead;
- ReadFile(hIn,(char*)&vhd_head,sizeof(hd_ftr),&bRead,NULL);
- if(bRead != sizeof(hd_ftr))
- return -2;
- if(strncmp(vhd_head.cookie,HD_COOKIE,8) != 0)
- {
- _tprintf(_T("the source file is not a valid VHD format!\n"));
- return -3;
- }
- if( (LE32(vhd_head.type) != HD_TYPE_DYNAMIC) && (LE32(vhd_head.type) != HD_TYPE_DIFF) )
- return -4;
- dd_hdr vhd_sparce;
- ReadFile(hIn,(char*)&vhd_sparce,sizeof(dd_hdr),&bRead,NULL);
- if(bRead != sizeof(dd_hdr))
- return -5;
- if(strncmp(vhd_sparce.cookie,DD_COOKIE,8) != 0)
- return -6;
- vhd.uBlkSize = LE32(vhd_sparce.block_size);
- vhd.uBatNum = LE32(vhd_sparce.max_bat_size);
- vhd.bat = new u32 [vhd.uBatNum];
- LARGE_INTEGER liPoi,liNew;
- liPoi.QuadPart = LE64(vhd_sparce.table_offset);
- SetFilePointerEx(hIn,liPoi,&liNew,FILE_BEGIN);
- ReadFile(hIn,vhd.bat,vhd.uBatNum * sizeof(u32),&bRead,NULL);
- if(bRead != vhd.uBatNum * sizeof(u32))
- return -7;
- dd_batmap_hdr batmap_head;
- ReadFile(hIn,(char*)&batmap_head,sizeof(dd_batmap_hdr),&bRead,NULL);
- if(bRead != sizeof(dd_batmap_hdr))
- return -8;
- if(strncmp(batmap_head.cookie,VHD_BATMAP_COOKIE,8) != 0)
- vhd.is_have_batmap = FALSE;
- else
- vhd.is_have_batmap = TRUE;
- vhd.spb = vhd.uBlkSize >> VHD_SECTOR_SHIFT;
- vhd.vhd_status = VHD_OPENED;
- return 1;
- }
- int read_vhd(vhd_info &vhd,byte* buf,u32 blkno)
- {
- byte spb_bitmap[VHD_SECTOR_SIZE];
- DWORD bRead;
- if(vhd.bat[blkno] == 0xFFFFFFFF)
- return 2;
- byte *tbuf = new byte [vhd.uBlkSize];
- LARGE_INTEGER liPoi,liNew;
- liPoi.QuadPart = (u64)(LE32(vhd.bat[blkno])) << VHD_SECTOR_SHIFT;
- SetFilePointerEx(hIn,liPoi,&liNew,FILE_BEGIN);
- ReadFile(hIn,spb_bitmap,VHD_SECTOR_SIZE,&bRead,NULL);
- if(bRead != VHD_SECTOR_SIZE)
- {
- delete [] tbuf;
- return -2;
- }
- ReadFile(hIn,tbuf,vhd.uBlkSize,&bRead,NULL);
- if(bRead != vhd.uBlkSize)
- {
- delete [] tbuf;
- return -3;
- }
- for(u32 i=0;i<vhd.spb;i++)
- {
- if(test_bit(spb_bitmap,i)) //位为1,表示磁盘上有数据,需要拷贝
- {
- memcpy(buf + i * VHD_SECTOR_SIZE,tbuf + i*VHD_SECTOR_SIZE,VHD_SECTOR_SIZE);
- }
- }
- delete [] tbuf;
- return 1;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- if(argc != 3)
- {
- _tprintf(_T("vhd2img.exe <input vhd name> <output file/disk name>\n"));
- _tprintf(_T("eg. vhd2img.exe my.vhd d:\\my.img \n"));
- _tprintf(_T(" vhd2img.exe my.vhd \"\\\\.\\physicaldrive1\" (write to hardisk 1)\n"));
- return 0;
- }
- vhd_info vhd;
- //打开输入vhd
- if(open_vhd(argv[1],vhd) != 1)
- return -1;
- //生成目标文件
- HANDLE hOut = CreateFile(argv[2],GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
- if(hOut == INVALID_HANDLE_VALUE)
- {
- hOut = CreateFile(argv[2],GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,0,NULL);
- if(hOut == INVALID_HANDLE_VALUE)
- {
- _tprintf(_T("ERROR%d:the dest disk/file open error!\n"),GetLastError());
- return -1;
- }
- }
- //u32 nBlkSize = vhd.uBlkSize;
- byte* buf = new byte [vhd.uBlkSize];
- u32 nBitmapSize = (vhd.spb >> 3 );
- byte* bitmap = new byte [nBitmapSize];
- DWORD bWrite;
- LARGE_INTEGER liPos,liNew;
- for(int i=0;i<vhd.uBatNum;i++)
- {
- memset(buf,0,vhd.uBlkSize);
- memset(bitmap,0,nBitmapSize);
- if(read_vhd(vhd,buf,i) != 1) //读错误或属于稀疏空间
- continue;
- liPos.QuadPart = (u64)i * (u64)vhd.uBlkSize;
- SetFilePointerEx(hOut,liPos,&liNew,FILE_BEGIN);
- WriteFile(hOut,buf,vhd.uBlkSize,&bWrite,NULL);
- if(bWrite != vhd.uBlkSize)
- {
- _tprintf(_T("ERROR%d:#%dblk (2MB) write error!\n\n"),GetLastError(),i);
- return -1;
- }
- }
- liPos.QuadPart = (u64)vhd.uBatNum * (u64)vhd.uBlkSize;
- SetFilePointerEx(hOut,liPos,&liNew,FILE_BEGIN);
- SetEndOfFile(hOut);
- //释放
- delete [] buf;
- delete [] bitmap;
- CloseHandle(hIn);
- CloseHandle(hOut);
- return 1;
- }
layout.h:
- /* Copyright (c) 2008, XenSource Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of XenSource Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- typedef UINT32 u32;
- typedef UINT64 u64;
- typedef unsigned char vhd_uuid_t[16];
- #ifndef __VHD_H__
- #define __VHD_H__
- #define DEBUG 1
- /* ---------------------------------------------------------------------- */
- /* General definitions. */
- /* ---------------------------------------------------------------------- */
- #define VHD_SECTOR_SIZE 512
- #define VHD_SECTOR_SHIFT 9
- /* ---------------------------------------------------------------------- */
- /* This is the generic disk footer, used by all disks. */
- /* ---------------------------------------------------------------------- */
- struct hd_ftr {
- char cookie[8]; /* Identifies original creator of the disk */
- u32 features; /* Feature Support -- see below */
- u32 ff_version; /* (major,minor) version of disk file */
- u64 data_offset; /* Abs. offset from SOF to next structure */
- u32 timestamp; /* Creation time. secs since 1/1/2000GMT */
- char crtr_app[4]; /* Creator application */
- u32 crtr_ver; /* Creator version (major,minor) */
- u32 crtr_os; /* Creator host OS */
- u64 orig_size; /* Size at creation (bytes) */
- u64 curr_size; /* Current size of disk (bytes) */
- u32 geometry; /* Disk geometry */
- u32 type; /* Disk type */
- u32 checksum; /* 1's comp sum of this struct. */
- vhd_uuid_t uuid; /* Unique disk ID, used for naming parents */
- char saved; /* one-bit -- is this disk/VM in a saved state? */
- char hidden; /* tapdisk-specific field: is this vdi hidden? */
- char reserved[426]; /* padding */
- };
- /* VHD cookie string. */
- static const char HD_COOKIE[9] = "conectix";
- /* Feature fields in hd_ftr */
- #define HD_NO_FEATURES 0x00000000
- #define HD_TEMPORARY 0x00000001 /* disk can be deleted on shutdown */
- #define HD_RESERVED 0x00000002 /* NOTE: must always be set */
- /* Version field in hd_ftr */
- #define HD_FF_VERSION 0x00010000
- /* Known creator OS type fields in hd_ftr.crtr_os */
- #define HD_CR_OS_WINDOWS 0x5769326B /* (Wi2k) */
- #define HD_CR_OS_MACINTOSH 0x4D616320 /* (Mac ) */
- /*
- * version 0.1: little endian bitmaps
- * version 1.1: big endian bitmaps; batmap
- * version 1.2: libvhd
- * version 1.3: batmap version bump to 1.2
- */
- #define VHD_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
- #define VHD_CURRENT_VERSION VHD_VERSION(1, 3)
- /* Disk geometry accessor macros. */
- /* Geometry is a triple of (cylinders (2 bytes), tracks (1 byte), and
- * secotrs-per-track (1 byte))
- */
- #define GEOM_GET_CYLS(_g) (((_g) >> 16) & 0xffff)
- #define GEOM_GET_HEADS(_g) (((_g) >> 8) & 0xff)
- #define GEOM_GET_SPT(_g) ((_g) & 0xff)
- #define GEOM_ENCODE(_c, _h, _s) (((_c) << 16) | ((_h) << 8) | (_s))
- /* type field in hd_ftr */
- #define HD_TYPE_NONE 0
- #define HD_TYPE_FIXED 2 /* fixed-allocation disk */
- #define HD_TYPE_DYNAMIC 3 /* dynamic disk */
- #define HD_TYPE_DIFF 4 /* differencing disk */
- /* String table for hd.type */
- static const char *HD_TYPE_STR[7] = {
- "None", /* 0 */
- "Reserved (deprecated)", /* 1 */
- "Fixed hard disk", /* 2 */
- "Dynamic hard disk", /* 3 */
- "Differencing hard disk", /* 4 */
- "Reserved (deprecated)", /* 5 */
- "Reserved (deprecated)" /* 6 */
- };
- #define HD_TYPE_MAX 6
- struct prt_loc {
- u32 code; /* Platform code -- see defines below. */
- u32 data_space; /* Number of 512-byte sectors to store locator */
- u32 data_len; /* Actual length of parent locator in bytes */
- u32 res; /* Must be zero */
- u64 data_offset; /* Absolute offset of locator data (bytes) */
- };
- /* Platform Codes */
- #define PLAT_CODE_NONE 0x0
- #define PLAT_CODE_WI2R 0x57693272 /* deprecated */
- #define PLAT_CODE_WI2K 0x5769326B /* deprecated */
- #define PLAT_CODE_W2RU 0x57327275 /* Windows relative path (UTF-16) */
- #define PLAT_CODE_W2KU 0x57326B75 /* Windows absolute path (UTF-16) */
- #define PLAT_CODE_MAC 0x4D616320 /* MacOS alias stored as a blob. */
- #define PLAT_CODE_MACX 0x4D616358 /* File URL (UTF-8), see RFC 2396. */
- /* ---------------------------------------------------------------------- */
- /* This is the dynamic disk header. */
- /* ---------------------------------------------------------------------- */
- struct dd_hdr {
- char cookie[8]; /* Should contain "cxsparse" */
- u64 data_offset; /* Byte offset of next record. (Unused) 0xffs */
- u64 table_offset; /* Absolute offset to the BAT. */
- u32 hdr_ver; /* Version of the dd_hdr (major,minor) */
- u32 max_bat_size; /* Maximum number of entries in the BAT */
- u32 block_size; /* Block size in bytes. Must be power of 2. */
- u32 checksum; /* Header checksum. 1's comp of all fields. */
- vhd_uuid_t prt_uuid; /* ID of the parent disk. */
- u32 prt_ts; /* Modification time of the parent disk */
- u32 res1; /* Reserved. */
- char prt_name[512]; /* Parent unicode name. */
- struct prt_loc loc[8]; /* Parent locator entries. */
- char res2[256]; /* Reserved. */
- };
- /* VHD cookie string. */
- static const char DD_COOKIE[9] = "cxsparse";
- /* Version field in hd_ftr */
- #define DD_VERSION 0x00010000
- /* Default blocksize is 2 meg. */
- #define DD_BLOCKSIZE_DEFAULT 0x00200000
- #define DD_BLK_UNUSED 0xFFFFFFFF
- struct dd_batmap_hdr {
- char cookie[8]; /* should contain "tdbatmap" */
- u64 batmap_offset; /* byte offset to batmap */
- u32 batmap_size; /* batmap size in sectors */
- u32 batmap_version; /* version of batmap */
- u32 checksum; /* batmap checksum -- 1's complement of batmap */
- };
- static const char VHD_BATMAP_COOKIE[9] = "tdbatmap";
- /*
- * version 1.1: signed char checksum
- */
- #define VHD_BATMAP_VERSION(major, minor) (((major) << 16) | ((minor) & 0x0000FFFF))
- #define VHD_BATMAP_CURRENT_VERSION VHD_BATMAP_VERSION(1, 2)
- /* Layout of a dynamic disk:
- *
- * +-------------------------------------------------+
- * | Mirror image of HD footer (hd_ftr) (512 bytes) |
- * +-------------------------------------------------+
- * | Sparse drive header (dd_hdr) (1024 bytes) |
- * +-------------------------------------------------+
- * | BAT (Block allocation table) |
- * | - Array of absolute sector offsets into the |
- * | file (u32). |
- * | - Rounded up to a sector boundary. |
- * | - Unused entries are marked as 0xFFFFFFFF |
- * | - max entries in dd_hdr->max_bat_size |
- * +-------------------------------------------------+
- * | Data Block 0 |
- * | Bitmap (padded to 512 byte sector boundary) |
- * | - each bit indicates whether the associated |
- * | sector within this block is used. |
- * | Data |
- * | - power-of-two multiple of sectors. |
- * | - default 2MB (4096 * 512) |
- * | - Any entries with zero in bitmap should be |
- * | zero on disk |
- * +-------------------------------------------------+
- * | Data Block 1 |
- * +-------------------------------------------------+
- * | ... |
- * +-------------------------------------------------+
- * | Data Block n |
- * +-------------------------------------------------+
- * | HD Footer (511 bytes) |
- * +-------------------------------------------------+
- */
- #define LE32(x) (( (u32)x >>24) ^ ((u32)x <<8 >>24 <<8) ^ ((u32)x <<16 >>24 <<16) ^ ((u32)x <<24))
- #define LE64(x) (((u64)LE32((u32)x)) <<32 ) ^ ( LE32((u32)((u64)x >>32)) )
- #endif
本文转自 张宇 51CTO博客,原文链接:http://blog.51cto.com/zhangyu/1109742,如需转载请自行联系原作者