您的位置:首页 > 编程语言 > C语言/C++

vhd 转换为img源码,由VS2010 C++编译

2017-08-14 00:00 495 查看
//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


本文出自 “张宇(数据恢复)” 博客,转载请与作者联系!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  源码 vhd xen
相关文章推荐