1.0.66 release

This commit is contained in:
longpanda
2022-02-13 17:00:39 +08:00
parent c57717aea2
commit ba5978d298
287 changed files with 3349 additions and 226 deletions

271
Vlnk/VentoyVlnk.sh Normal file
View File

@@ -0,0 +1,271 @@
#!/bin/sh
print_usage() {
echo 'Usage: sudo sh VentoyVlnk.sh CMD FILE'
echo ' CMD:'
echo ' -c FILE create vlnk for FILE'
echo ' -l VLNK parse vlnk file'
echo ' -v print verbose info'
echo ' -h print this help'
echo ''
}
verbose_flag=0
vlog() {
if [ $verbose_flag -eq 1 ]; then
echo "$@"
fi
}
vlnk_suffix() {
echo $1 | egrep -q '.*(.vlnk.iso|.vlnk.img|.vlnk.wim|.vlnk.vhd|.vlnk.vhdx|.vlnk.efi|.vlnk.vtoy|.vlnk.dat)$'
}
uid=$(id -u)
if [ $uid -ne 0 ]; then
echo "Please use sudo or run the script as root."
exit 1
fi
#check system tools used bellow
for t in 'mountpoint' 'readlink' 'xzcat'; do
if ! which "$t" > /dev/null 2>&1; then
echo "$t command not found in current system!"
exit 1
fi
done
machine=$(uname -m)
if echo $machine | egrep -q 'aarch64|arm64'; then
TOOLDIR=aarch64
elif echo $machine | egrep -q 'x86_64|amd64'; then
TOOLDIR=x86_64
elif echo $machine | egrep -q 'mips64'; then
TOOLDIR=mips64el
elif echo $machine | egrep -q 'i[3-6]86'; then
TOOLDIR=i386
else
echo "Unsupported machine type $machine"
exit 1
fi
fullsh=$(readlink -f "$0")
vtoydir=${fullsh%/*}
if [ -f "$vtoydir/tool/$TOOLDIR/vlnk.xz" ]; then
xzcat "$vtoydir/tool/$TOOLDIR/vlnk.xz" > "$vtoydir/tool/$TOOLDIR/vlnk"
rm -f "$vtoydir/tool/$TOOLDIR/vlnk.xz"
fi
if [ -f "$vtoydir/tool/$TOOLDIR/vlnk" ]; then
chmod +x "$vtoydir/tool/$TOOLDIR/vlnk"
else
echo "$vtoydir/tool/$TOOLDIR/vlnk does not exist! "
exit 1
fi
PATH="$vtoydir/tool/$TOOLDIR":$PATH
VLNKCMD=vlnk
while [ -n "$1" ]; do
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
print_usage
exit 0
elif [ "$1" = "-c" ]; then
shift
CMD='c'
IMG="$1"
elif [ "$1" = "-o" ]; then
shift
OUT="$1"
elif [ "$1" = "-l" ]; then
shift
CMD='l'
VLNK="$1"
elif [ "$1" = "-v" ]; then
verbose_flag=1
VLNKCMD="vlnk -v"
else
echo "invalid option $1"
exit 1
fi
shift
done
if [ "$CMD" = "c" ]; then
vlog "Create vlnk for $IMG"
if [ ! -f "$IMG" ]; then
echo "$IMG does not exist!"
exit 1
fi
if echo $IMG | egrep -q -i '.*(.iso|.img|.wim|.vhd|.vhdx|.efi|.vtoy|.dat)$'; then
:
else
echo "This file is not supported for vlnk!"
exit 1
fi
if vlnk_suffix "$IMG"; then
echo "This is already a vlnk file!"
exit 1
fi
if $VLNKCMD -t "$IMG"; then
echo "This is already a vlnk file!"
exit 1
fi
FULLIMG=$(readlink -f "$IMG")
if [ ! -f "$FULLIMG" ]; then
echo "$FULLIMG does not exist!"
exit 1
fi
vlog "Full file path is $FULLIMG"
#check img file position is a valid mountpoint
FULLDIR=${FULLIMG%/*}
while [ -n "${FULLDIR}" ]; do
if mountpoint -q "${FULLDIR}"; then
break
fi
FULLDIR="${FULLDIR%/*}"
done
if [ -z "${FULLDIR}" ]; then
FULLDIR=/
IMGPATH="${FULLIMG}"
else
IMGPATH="${FULLIMG#$FULLDIR}"
fi
IMGFILE=$(basename "$IMGPATH")
vlog "IMGPATH=$IMGPATH IMGFILE=$IMGFILE"
mntdev=$(mountpoint -d "${FULLDIR}")
vlog "mountpoint is ${FULLDIR} dev $mntdev"
#check fs
if grep -q " ${FULLDIR} " /proc/mounts; then
FS=$(grep " ${FULLDIR} " /proc/mounts | awk '{print $3}')
vlog "File system is $FS"
if echo $FS | egrep -q "ext2|ext3|ext4|exfat|vfat|fat32|fat16|fat12|ntfs|xfs|udf"; then
vlog "FS OK"
else
echo "$FS is not supported!"
exit 1
fi
else
echo "${FULLDIR} not found in /proc/mounts"
exit 1
fi
Major=$(echo $mntdev | awk -F: '{print $1}')
Minor=$(echo $mntdev | awk -F: '{print $2}')
vlog "Major=$Major Minor=$Minor"
IMGPARTITION=""
while read line; do
M1=$(echo $line | awk '{print $1}')
M2=$(echo $line | awk '{print $2}')
if [ "$Major" = "$M1" -a "$Minor" = "$M2" ]; then
IMGPARTITION=$(echo $line | awk '{print $4}')
vlog "disk partition is $IMGPARTITION"
break
fi
done < /proc/partitions
if [ -z "$IMGPARTITION" ]; then
echo "Disk partition not found for $FULLDIR"
grep " $FULLDIR " /proc/mounts
exit 1
fi
if [ -f "/sys/class/block/$IMGPARTITION/start" ]; then
PARTSTART=$(cat "/sys/class/block/$IMGPARTITION/start")
if echo $IMGPARTITION | egrep -q 'mmc|nbd|nvme'; then
DISK=$(echo /dev/$IMGPARTITION | sed "s/^\(.*\)p[0-9][0-9]*$/\1/")
else
DISK=$(echo /dev/$IMGPARTITION | sed "s/^\(.*[^0-9]\)[0-9][0-9]*$/\1/")
fi
if [ ! -b $DISK ]; then
echo "Device $DISK not exist!"
exit 1
fi
vlog "PARTSTART=$PARTSTART DISK=$DISK"
else
if echo $IMGPARTITION | grep -q '^dm-[0-9][0-9]*'; then
echo "LVM/DM is not supported!"
fi
echo "/sys/class/block/$IMGPARTITION/start not exist!"
exit 1
fi
if [ -n "$OUT" ]; then
lowersuffix=$(echo ${IMG##*.} | tr 'A-Z' 'a-z')
OUT="${OUT}.vlnk.${lowersuffix}"
else
name=${IMGFILE%.*}
lowersuffix=$(echo ${IMGFILE##*.} | tr 'A-Z' 'a-z')
OUT="${name}.vlnk.${lowersuffix}"
fi
echo "Output VLNK file is $OUT"
[ -f "${OUT}" ] && rm -f "${OUT}"
touch "${OUT}"
if [ -f "${OUT}" ]; then
rm -f "${OUT}"
else
echo "Failed to create ${OUT}"
exit 1
fi
if $VLNKCMD -c "$IMGPATH" -d $DISK -p $PARTSTART -o "${OUT}"; then
echo "====== Vlnk file create success ========="
echo ""
else
echo "====== Vlnk file create failed ========="
echo ""
exit 1
fi
elif [ "$CMD" = "l" ]; then
vlog "Parse vlnk for $VLNK"
if [ ! -f "$VLNK" ]; then
echo "$VLNK does not exist!"
exit 1
fi
if vlnk_suffix "$VLNK"; then
:
else
echo "Invalid vlnk file suffix!"
exit 1
fi
if $VLNKCMD -t "$VLNK"; then
vlog "Vlnk data check OK"
else
echo "This is not a valid vlnk file!"
exit 1
fi
$VLNKCMD -l "$VLNK"
echo ""
else
echo "invalid cmd"
print_usage
exit 1
fi

32
Vlnk/build.sh Normal file
View File

@@ -0,0 +1,32 @@
#!/bin/sh
rm -f vlnk_64
rm -f vlnk_32
rm -f vlnk_aa64
rm -f vlnk_m64e
SRCS="src/crc32.c src/main_linux.c src/vlnk.c"
gcc -specs "/usr/local/musl/lib/musl-gcc.specs" -Os -static -D_FILE_OFFSET_BITS=64 $SRCS -Isrc -o vlnk_64
/opt/diet32/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 -m32 -static $SRCS -Isrc -o vlnk_32
aarch64-buildroot-linux-uclibc-gcc -static -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Isrc -o vlnk_aa64
mips64el-linux-musl-gcc -mips64r2 -mabi=64 -static -O2 -D_FILE_OFFSET_BITS=64 $SRCS -Isrc -o vlnk_m64e
if [ -e vlnk_64 ] && [ -e vlnk_32 ] && [ -e vlnk_aa64 ] && [ -e vlnk_m64e ]; then
echo -e "\n===== success =======\n"
strip --strip-all vlnk_32
strip --strip-all vlnk_64
aarch64-buildroot-linux-uclibc-strip --strip-all vlnk_aa64
mips64el-linux-musl-strip --strip-all vlnk_m64e
[ -d ../INSTALL/tool/i386/ ] && mv vlnk_32 ../INSTALL/tool/i386/vlnk
[ -d ../INSTALL/tool/x86_64/ ] && mv vlnk_64 ../INSTALL/tool/x86_64/vlnk
[ -d ../INSTALL/tool/aarch64/ ] && mv vlnk_aa64 ../INSTALL/tool/aarch64/vlnk
[ -d ../INSTALL/tool/mips64el/ ] && mv vlnk_m64e ../INSTALL/tool/mips64el/vlnk
else
echo -e "\n===== failed =======\n"
exit 1
fi

7
Vlnk/pack.sh Normal file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
rm -f ../INSTALL/VentoyVlnk.sh
cp -a ./VentoyVlnk.sh ../INSTALL/VentoyVlnk.sh
rm -f ../INSTALL/VentoyVlnk.exe
cp -a ./vs/VentoyVlnk/Release/VentoyVlnk.exe ../INSTALL/VentoyVlnk.exe

77
Vlnk/src/crc32.c Normal file
View File

@@ -0,0 +1,77 @@
/******************************************************************************
* crc32.c ----
*
* Copyright (c) 2022, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "vlnk.h"
static uint32_t crc32c_table [256];
/* Helper for init_crc32c_table. */
static uint32_t reflect (uint32_t ref, int len)
{
uint32_t result = 0;
int i;
for (i = 1; i <= len; i++)
{
if (ref & 1)
result |= 1 << (len - i);
ref >>= 1;
}
return result;
}
static void init_crc32c_table (void)
{
uint32_t polynomial = 0x1edc6f41;
int i, j;
for(i = 0; i < 256; i++)
{
crc32c_table[i] = reflect(i, 8) << 24;
for (j = 0; j < 8; j++)
crc32c_table[i] = (crc32c_table[i] << 1) ^
(crc32c_table[i] & (1 << 31) ? polynomial : 0);
crc32c_table[i] = reflect(crc32c_table[i], 32);
}
}
uint32_t ventoy_getcrc32c (uint32_t crc, const void *buf, int size)
{
int i;
const uint8_t *data = buf;
if (! crc32c_table[1])
init_crc32c_table ();
crc^= 0xffffffff;
for (i = 0; i < size; i++)
{
crc = (crc >> 8) ^ crc32c_table[(crc & 0xFF) ^ *data];
data++;
}
return crc ^ 0xffffffff;
}

457
Vlnk/src/main_linux.c Normal file
View File

@@ -0,0 +1,457 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/statfs.h>
#include <dirent.h>
#include <unistd.h>
#include "vlnk.h"
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
static int verbose = 0;
#define debug(fmt, args...) if(verbose) printf(fmt, ##args)
static uint8_t g_vlnk_buf[VLNK_FILE_LEN];
static int64_t get_file_size(char *file)
{
struct stat stStat;
if (stat(file, &stStat) < 0)
{
return -1;
}
return (int64_t)(stStat.st_size);
}
static int get_disk_sig(char *diskname, uint32_t *sig)
{
int fd;
uint8_t buf[512] = {0};
fd = open(diskname, O_RDONLY);
if (fd < 0)
{
printf("Failed to open %s\n", diskname);
return 1;
}
read(fd, buf, 512);
close(fd);
memcpy(sig, buf + 0x1b8, 4);
return 0;
}
static int vtoy_get_disk_guid(const char *diskname, uint8_t *vtguid, uint8_t *vtsig)
{
int i = 0;
int fd = 0;
char devdisk[128] = {0};
snprintf(devdisk, sizeof(devdisk) - 1, "/dev/%s", diskname);
fd = open(devdisk, O_RDONLY);
if (fd >= 0)
{
lseek(fd, 0x180, SEEK_SET);
read(fd, vtguid, 16);
lseek(fd, 0x1b8, SEEK_SET);
read(fd, vtsig, 4);
close(fd);
return 0;
}
else
{
debug("failed to open %s %d\n", devdisk, errno);
return errno;
}
}
static int vtoy_is_possible_blkdev(const char *name)
{
if (name[0] == '.')
{
return 0;
}
/* /dev/ramX */
if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
{
return 0;
}
/* /dev/loopX */
if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
{
return 0;
}
/* /dev/dm-X */
if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && IS_DIGIT(name[3]))
{
return 0;
}
/* /dev/srX */
if (name[0] == 's' && name[1] == 'r' && IS_DIGIT(name[2]))
{
return 0;
}
return 1;
}
static int find_disk_by_sig(uint8_t *sig, char *diskname)
{
int rc = 0;
int count = 0;
DIR* dir = NULL;
struct dirent* p = NULL;
uint8_t vtguid[16];
uint8_t vtsig[16];
dir = opendir("/sys/block");
if (!dir)
{
return 0;
}
while ((p = readdir(dir)) != NULL)
{
if (!vtoy_is_possible_blkdev(p->d_name))
{
continue;
}
rc = vtoy_get_disk_guid(p->d_name, vtguid, vtsig);
if (rc == 0 && memcmp(vtsig, sig, 4) == 0)
{
sprintf(diskname, "%s", p->d_name);
count++;
}
}
closedir(dir);
return count;
}
static uint64_t get_part_offset(char *partname)
{
int fd;
uint64_t offset;
char buf[32] = {0};
char path[PATH_MAX];
snprintf(path, PATH_MAX - 1, "/sys/class/block/%s/start", partname);
fd = open(path, O_RDONLY);
if (fd < 0)
{
return 0;
}
read(fd, buf, sizeof(buf));
close(fd);
offset = (uint64_t)strtoull(buf, NULL, 10);
offset *= 512;
return offset;
}
static int create_vlnk(char *infile, char *diskname, uint64_t partoff, char *outfile)
{
FILE *fp;
int len;
uint32_t sig = 0;
debug("create vlnk\n");
if (infile[0] == 0 || outfile[0] == 0 || diskname[0] == 0 || partoff == 0)
{
debug("Invalid parameters: %d %d %d %llu\n", infile[0], outfile[0], diskname[0], (unsigned long long)partoff);
return 1;
}
len = (int)strlen(infile);
if (len >= VLNK_NAME_MAX)
{
printf("File name length %d is too long for vlnk!\n", len);
return 1;
}
if (get_disk_sig(diskname, &sig))
{
printf("Failed to read disk sig\n");
return 1;
}
fp = fopen(outfile, "wb+");
if (!fp)
{
printf("Failed to create file %s\n", outfile);
return 1;
}
memset(g_vlnk_buf, 0, sizeof(g_vlnk_buf));
ventoy_create_vlnk(sig, partoff, infile, (ventoy_vlnk *)g_vlnk_buf);
fwrite(g_vlnk_buf, 1, VLNK_FILE_LEN, fp);
fclose(fp);
return 0;
}
static int get_mount_point(char *partname, char *mntpoint)
{
int i;
int len;
int rc = 1;
FILE *fp = NULL;
char line[PATH_MAX];
fp = fopen("/proc/mounts", "r");
if (!fp)
{
return 1;
}
len = (int)strlen(partname);
while (fgets(line, sizeof(line), fp))
{
if (strncmp(line, partname, len) == 0)
{
for (i = len; i < PATH_MAX && line[i]; i++)
{
if (line[i] == ' ')
{
line[i] = 0;
rc = 0;
strncpy(mntpoint, line + len, PATH_MAX - 1);
break;
}
}
break;
}
}
fclose(fp);
return rc;
}
static int parse_vlnk(char *infile)
{
int i;
int fd;
int cnt;
int pflag = 0;
char diskname[128] = {0};
char partname[128] = {0};
char partpath[256] = {0};
char mntpoint[PATH_MAX];
ventoy_vlnk vlnk;
debug("parse vlnk\n");
if (infile[0] == 0)
{
debug("input file null\n");
return 1;
}
fd = open(infile, O_RDONLY);
if (fd < 0)
{
printf("Failed to open file %s error %d\n", infile, errno);
return 1;
}
memset(&vlnk, 0, sizeof(vlnk));
read(fd, &vlnk, sizeof(vlnk));
close(fd);
debug("disk_signature:%08X\n", vlnk.disk_signature);
debug("file path:<%s>\n", vlnk.filepath);
debug("part offset: %llu\n", (unsigned long long)vlnk.part_offset);
cnt = find_disk_by_sig((uint8_t *)&(vlnk.disk_signature), diskname);
if (cnt != 1)
{
printf("Disk in vlnk not found!\n");
return 1;
}
debug("Disk is <%s>\n", diskname);
if (strstr(diskname, "nvme") || strstr(diskname, "mmc") || strstr(diskname, "nbd"))
{
pflag = 1;
}
for (i = 1; i <= 128; i++)
{
if (pflag)
{
snprintf(partname, sizeof(partname) - 1, "%sp%d", diskname, i);
}
else
{
snprintf(partname, sizeof(partname) - 1, "%s%d", diskname, i);
}
if (get_part_offset(partname) == vlnk.part_offset)
{
debug("Find correct partition </dev/%s>\n", partname);
break;
}
}
if (i > 128)
{
printf("Partition in vlnk not found!");
return 1;
}
snprintf(partpath, sizeof(partpath), "/dev/%s ", partname);
if (get_mount_point(partpath, mntpoint))
{
printf("Mountpoint of %s is not found!\n", partpath);
return 1;
}
debug("moutpoint of %s is <%s>\n", partpath, mntpoint);
strcat(mntpoint, vlnk.filepath);
printf("Vlnk Point: %s\n", mntpoint);
if (access(mntpoint, F_OK) >= 0)
{
printf("File Exist: YES\n");
}
else
{
printf("File Exist: NO\n");
}
return 0;
}
static int check_vlnk(char *infile)
{
int fd;
int64_t size;
ventoy_vlnk vlnk;
debug("check vlnk\n");
if (infile[0] == 0)
{
debug("input file null\n");
return 1;
}
size = get_file_size(infile);
if (size != VLNK_FILE_LEN)
{
debug("file size %lld is not a vlnk file size\n", (long long)size);
return 1;
}
fd = open(infile, O_RDONLY);
if (fd < 0)
{
debug("Failed to open file %s error %d\n", infile, errno);
return 1;
}
memset(&vlnk, 0, sizeof(vlnk));
read(fd, &vlnk, sizeof(vlnk));
close(fd);
if (CheckVlnkData(&vlnk))
{
return 0;
}
return 1;
}
int main(int argc, char **argv)
{
int ch = 0;
int cmd = 0;
uint64_t partoff = 0;
char infile[PATH_MAX] = {0};
char outfile[PATH_MAX] = {0};
char diskname[256] = {0};
while ((ch = getopt(argc, argv, "c:t:l:d:p:o:v::")) != -1)
{
if (ch == 'c')
{
cmd = 1;
strncpy(infile, optarg, sizeof(infile) - 1);
}
else if (ch == 'o')
{
strncpy(outfile, optarg, sizeof(outfile) - 1);
}
else if (ch == 'l')
{
cmd = 2;
strncpy(infile, optarg, sizeof(infile) - 1);
}
else if (ch == 't')
{
cmd = 3;
strncpy(infile, optarg, sizeof(infile) - 1);
}
else if (ch == 'd')
{
strncpy(diskname, optarg, sizeof(diskname) - 1);
}
else if (ch == 'p')
{
partoff = (uint64_t)strtoull(optarg, NULL, 10);
partoff *= 512;
}
else if (ch == 'v')
{
verbose = 1;
}
else
{
return 1;
}
}
if (cmd == 1)
{
return create_vlnk(infile, diskname, partoff, outfile);
}
else if (cmd == 2)
{
return parse_vlnk(infile);
}
else if (cmd == 3)
{
return check_vlnk(infile);
}
else
{
printf("Invalid command %d\n", cmd);
return 1;
}
}

711
Vlnk/src/main_windows.c Normal file
View File

@@ -0,0 +1,711 @@
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <resource.h>
#include <vlnk.h>
static WCHAR g_CurDirW[MAX_PATH];
static CHAR g_CurDirA[MAX_PATH];
static CHAR g_LogFile[MAX_PATH];
static HWND g_create_button;
static HWND g_parse_button;
typedef enum MSGID
{
MSGID_ERROR = 0,
MSGID_INFO,
MSGID_BTN_CREATE,
MSGID_BTN_PARSE,
MSGID_SRC_UNSUPPORTED,
MSGID_FS_UNSUPPORTED,
MSGID_SUFFIX_UNSUPPORTED,
MSGID_DISK_INFO_ERR,
MSGID_VLNK_SUCCESS,
MSGID_RUNNING_TIP,
MSGID_CREATE_FILE_ERR,
MSGID_ALREADY_VLNK,
MSGID_INVALID_VLNK,
MSGID_VLNK_POINT_TO,
MSGID_VLNK_NO_DST,
MSGID_FILE_NAME_TOO_LONG,
MSGID_BUTT
}MSGID;
const WCHAR *g_msg_cn[MSGID_BUTT] =
{
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD>֧<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>vlnk",
L"<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD><EFBFBD>ļ<EFBFBD>ϵͳ",
L"<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>׺<EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"Vlnk <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD>ȹر<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD> VentoyVlnk <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><EFBFBD>",
L"<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD>Ѿ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>vlnk<EFBFBD>ļ<EFBFBD><EFBFBD>ˣ<EFBFBD>",
L"<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD>vlnk<EFBFBD>ļ<EFBFBD>!",
L"<EFBFBD><EFBFBD> vlnk <20>ļ<EFBFBD>ָ<EFBFBD><D6B8> ",
L"<EFBFBD><EFBFBD> vlnk ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>",
L"<EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD>̫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
};
const WCHAR *g_msg_en[MSGID_BUTT] =
{
L"Error",
L"Info",
L"Create",
L"Parse",
L"This file is not supported for vlnk",
L"Unsupported file system!",
L"Unsupported file suffix!",
L"Error when getting disk info",
L"Vlnk file successfully created!",
L"Please close another running VentoyVlnk instance!",
L"Failed to create file!",
L"This file is already a vlnk file!",
L"Invalid vlnk file!",
L"The vlnk file point to ",
L"The file pointed by the vlnk does NOT exist!",
L"The file full path is too long!",
};
const WCHAR **g_msg_lang = NULL;
HINSTANCE g_hInst;
static void Log2File(const char *log)
{
time_t stamp;
struct tm ttm;
FILE *fp;
time(&stamp);
localtime_s(&ttm, &stamp);
fopen_s(&fp, g_LogFile, "a+");
if (fp)
{
fprintf_s(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_mday,
ttm.tm_hour, ttm.tm_min, ttm.tm_sec, log);
fclose(fp);
}
}
void LogW(const WCHAR *Fmt, ...)
{
WCHAR log[512];
CHAR alog[2048];
va_list arg;
if (g_LogFile[0] == 0)
{
return;
}
va_start(arg, Fmt);
vswprintf_s(log, 512, Fmt, arg);
va_end(arg);
WideCharToMultiByte(CP_UTF8, 0, log, -1, alog, 2048, 0, 0);
Log2File(alog);
}
void LogA(const CHAR *Fmt, ...)
{
CHAR log[512];
va_list arg;
if (g_LogFile[0] == 0)
{
return;
}
va_start(arg, Fmt);
vsprintf_s(log, 512, Fmt, arg);
va_end(arg);
Log2File(log);
}
static int Utf8ToUtf16(const char* src, WCHAR * dst)
{
int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);
return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);
}
static BOOL OnDestroyDialog()
{
return TRUE;
}
static BOOL InitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HICON hIcon;
g_create_button = GetDlgItem(hWnd, IDC_BUTTON1);
g_parse_button = GetDlgItem(hWnd, IDC_BUTTON2);
hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SetWindowTextW(g_create_button, g_msg_lang[MSGID_BTN_CREATE]);
SetWindowTextW(g_parse_button, g_msg_lang[MSGID_BTN_PARSE]);
return TRUE;
}
static int GetPhyDiskInfo(const char LogicalDrive, UINT32 *DiskSig, DISK_EXTENT *DiskExtent)
{
BOOL Ret;
DWORD dwSize;
HANDLE Handle;
VOLUME_DISK_EXTENTS DiskExtents;
CHAR PhyPath[128];
UINT8 SectorBuf[512];
LogA("GetPhyDiskInfo %C\n", LogicalDrive);
sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (Handle == INVALID_HANDLE_VALUE)
{
LogA("Could not open the disk %C: error:%u\n", LogicalDrive, GetLastError());
return 1;
}
Ret = DeviceIoControl(Handle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
&DiskExtents,
(DWORD)(sizeof(DiskExtents)),
(LPDWORD)&dwSize,
NULL);
if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
{
LogA("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u\n", GetLastError());
CloseHandle(Handle);
return 1;
}
CloseHandle(Handle);
memcpy(DiskExtent, DiskExtents.Extents, sizeof(DISK_EXTENT));
LogA("%C: is in PhysicalDrive%d Offset:%llu\n", LogicalDrive, DiskExtents.Extents[0].DiskNumber,
(ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart));
sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (Handle == INVALID_HANDLE_VALUE)
{
LogA("Could not open the disk<PhysicalDrive%d>, error:%u\n", DiskExtents.Extents[0].DiskNumber, GetLastError());
return 1;
}
if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
{
LogA("ReadFile failed, dwSize:%u error:%u\n", dwSize, GetLastError());
CloseHandle(Handle);
return 1;
}
memcpy(DiskSig, SectorBuf + 0x1B8, 4);
CloseHandle(Handle);
return 0;
}
static int SaveBuffer2File(const WCHAR *Fullpath, void *Buffer, DWORD Length)
{
int rc = 1;
DWORD dwSize;
HANDLE Handle;
LogW(L"SaveBuffer2File <%ls> len:%u\n", Fullpath, Length);
Handle = CreateFileW(Fullpath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
if (Handle == INVALID_HANDLE_VALUE)
{
LogA("Could not create new file, error:%u\n", GetLastError());
goto End;
}
WriteFile(Handle, Buffer, Length, &dwSize, NULL);
rc = 0;
End:
if (Handle != INVALID_HANDLE_VALUE)
{
CloseHandle(Handle);
}
return rc;
}
static int DefaultVlnkDstFullPath(WCHAR *Src, WCHAR *Dir, WCHAR *Dst)
{
int i, j;
int len;
int wrlen;
WCHAR C;
len = (int)lstrlen(Src);
for (i = len - 1; i >= 0; i--)
{
if (Src[i] == '.')
{
C = Src[i];
Src[i] = 0;
wrlen = swprintf_s(Dst, MAX_PATH, L"%ls\\%ls.vlnk.%ls", Dir, Src, Src + i + 1);
Src[i] = C;
for (j = wrlen - (len - i); j < wrlen; j++)
{
if (Dst[j] >= 'A' && Dst[j] <= 'Z')
{
Dst[j] = 'a' + (Dst[j] - 'A');
}
}
break;
}
}
return 0;
}
static BOOL IsVlnkFile(WCHAR *path, ventoy_vlnk *outvlnk)
{
BOOL bRet;
BOOL bVlnk = FALSE;
DWORD dwSize;
LARGE_INTEGER FileSize;
HANDLE Handle;
ventoy_vlnk vlnk;
Handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (Handle == INVALID_HANDLE_VALUE)
{
LogA("Could not open this file, error:%u\n", GetLastError());
return FALSE;
}
if (!GetFileSizeEx(Handle, &FileSize))
{
LogA("Failed to get vlnk file size\n");
goto End;
}
if (FileSize.QuadPart != VLNK_FILE_LEN)
{
LogA("Invalid vlnk file length %llu\n", (unsigned long long)FileSize.QuadPart);
goto End;
}
memset(&vlnk, 0, sizeof(vlnk));
bRet = ReadFile(Handle, &vlnk, sizeof(vlnk), &dwSize, NULL);
if (bRet && CheckVlnkData(&vlnk))
{
if (outvlnk)
{
memcpy(outvlnk, &vlnk, sizeof(vlnk));
}
bVlnk = TRUE;
}
End:
if (Handle != INVALID_HANDLE_VALUE)
{
CloseHandle(Handle);
}
return bVlnk;
}
static int CreateVlnk(HWND hWnd, WCHAR *Dir)
{
int i;
int end;
int len;
UINT32 DiskSig;
DISK_EXTENT DiskExtend;
OPENFILENAME ofn = { 0 };
CHAR UTF8Path[MAX_PATH];
WCHAR DstFullPath[MAX_PATH];
WCHAR szFile[MAX_PATH] = { 0 };
CHAR suffix[8] = { 0 };
CHAR Drive[8] = { 0 };
CHAR FsName[64] = { 0 };
CHAR *Buf = NULL;
WCHAR *Pos = NULL;
ventoy_vlnk *vlnk = NULL;
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"Vlnk Source File\0*.iso;*.img;*.wim;*.vhd;*.vhdx;*.vtoy;*.efi;*.dat\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) != TRUE)
{
return 1;
}
LogW(L"Create vlnk for <%ls>\n", szFile);
len = lstrlen(szFile);
if (len < 5 || szFile[0] == '.' || szFile[1] != ':')
{
MessageBox(hWnd, g_msg_lang[MSGID_SRC_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
Drive[0] = (CHAR)szFile[0];
Drive[1] = ':';
Drive[2] = '\\';
if (0 == GetVolumeInformationA(Drive, NULL, 0, NULL, NULL, NULL, FsName, sizeof(FsName) - 1))
{
LogA("GetVolumeInformationA failed %u\n", GetLastError());
return 1;
}
LogA("Partition filesystem of <%s> is <%s>\n", Drive, FsName);
if (_stricmp(FsName, "NTFS") == 0 ||
_stricmp(FsName, "exFAT") == 0 ||
_stricmp(FsName, "FAT") == 0 ||
_stricmp(FsName, "FAT32") == 0 ||
_stricmp(FsName, "FAT16") == 0 ||
_stricmp(FsName, "FAT12") == 0 ||
_stricmp(FsName, "UDF") == 0)
{
LogA("FS Check OK\n");
}
else
{
MessageBox(hWnd, g_msg_lang[MSGID_FS_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
end = (szFile[len - 5] == '.') ? 5 : 4;
for (i = 0; i < end; i++)
{
suffix[i] = (CHAR)szFile[len - (end - i)];
}
if (!IsSupportedImgSuffix(suffix))
{
MessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
if (IsVlnkFile(szFile, NULL))
{
MessageBox(hWnd, g_msg_lang[MSGID_ALREADY_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
for (i = 0; i < MAX_PATH && szFile[i]; i++)
{
if (szFile[i] == '\\' || szFile[i] == '/')
{
Pos = szFile + i;
}
}
if (!Pos)
{
LogA("name part not found\n");
return 1;
}
LogW(L"File Name is <%ls>\n", Pos + 1);
memset(UTF8Path, 0, sizeof(UTF8Path));
WideCharToMultiByte(CP_UTF8, 0, szFile + 2, -1, UTF8Path, MAX_PATH, NULL, 0);
for (i = 0; i < MAX_PATH && UTF8Path[i]; i++)
{
if (UTF8Path[i] == '\\')
{
UTF8Path[i] = '/';
}
}
len = (int)strlen(UTF8Path);
if (len >= VLNK_NAME_MAX)
{
LogA("File name length %d overflow\n", len);
MessageBox(hWnd, g_msg_lang[MSGID_FILE_NAME_TOO_LONG], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
DiskExtend.StartingOffset.QuadPart = 0;
if (GetPhyDiskInfo((char)szFile[0], &DiskSig, &DiskExtend))
{
MessageBox(hWnd, g_msg_lang[MSGID_DISK_INFO_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
Buf = malloc(VLNK_FILE_LEN);
if (Buf)
{
memset(Buf, 0, VLNK_FILE_LEN);
vlnk = (ventoy_vlnk *)Buf;
ventoy_create_vlnk(DiskSig, (uint64_t)DiskExtend.StartingOffset.QuadPart, UTF8Path, vlnk);
DefaultVlnkDstFullPath(Pos + 1, Dir, DstFullPath);
LogW(L"vlnk output file path is <%ls>\n", DstFullPath);
if (SaveBuffer2File(DstFullPath, Buf, VLNK_FILE_LEN) == 0)
{
WCHAR Msg[1024];
swprintf_s(Msg, 1024, L"%ls\r\n\r\n%ls", g_msg_lang[MSGID_VLNK_SUCCESS], DstFullPath + lstrlen(Dir) + 1);
LogW(L"Vlnk file create success <%ls>\n", DstFullPath);
MessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);
}
else
{
LogA("Vlnk file save failed\n");
MessageBox(hWnd, g_msg_lang[MSGID_CREATE_FILE_ERR], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
}
free(Buf);
}
return 0;
}
static CHAR GetDriveLetter(UINT32 disksig, UINT64 PartOffset)
{
CHAR Letter;
DWORD Drives;
UINT32 Sig;
DISK_EXTENT DiskExtent;
Letter = 'A';
Drives = GetLogicalDrives();
LogA("Logic Drives: 0x%x", Drives);
while (Drives)
{
if (Drives & 0x01)
{
Sig = 0;
DiskExtent.StartingOffset.QuadPart = 0;
if (GetPhyDiskInfo(Letter, &Sig, &DiskExtent) == 0)
{
if (Sig == disksig && DiskExtent.StartingOffset.QuadPart == PartOffset)
{
return Letter;
}
}
}
Drives >>= 1;
Letter++;
}
return 0;
}
static int ParseVlnk(HWND hWnd)
{
int i;
CHAR Letter;
ventoy_vlnk vlnk;
OPENFILENAME ofn = { 0 };
WCHAR szFile[MAX_PATH] = { 0 };
WCHAR szDst[MAX_PATH + 2] = { 0 };
WCHAR Msg[1024];
CHAR *suffix = NULL;
HANDLE hFile;
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"Vlnk File\0*.vlnk.iso;*.vlnk.img;*.vlnk.wim;*.vlnk.efi;*.vlnk.vhd;*.vlnk.vhdx;*.vlnk.vtoy;*.vlnk.dat\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) != TRUE)
{
return 1;
}
LogW(L"Parse vlnk for <%ls>\n", szFile);
if (!IsVlnkFile(szFile, &vlnk))
{
MessageBox(hWnd, g_msg_lang[MSGID_INVALID_VLNK], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
for (i = 0; i < sizeof(vlnk.filepath) && vlnk.filepath[i]; i++)
{
if (vlnk.filepath[i] == '.')
{
suffix = vlnk.filepath + i;
}
}
if (!IsSupportedImgSuffix(suffix))
{
MessageBox(hWnd, g_msg_lang[MSGID_SUFFIX_UNSUPPORTED], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
Utf8ToUtf16(vlnk.filepath, szDst + 2);
for (i = 2; i < MAX_PATH && szDst[i]; i++)
{
if (szDst[i] == '/')
{
szDst[i] = '\\';
}
}
Letter = GetDriveLetter(vlnk.disk_signature, vlnk.part_offset);
if (Letter == 0)
{
MessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
szDst[0] = toupper(Letter);
szDst[1] = ':';
LogW(L"vlnk dst is %ls\n", szDst);
hFile = CreateFileW(szDst, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hFile)
{
MessageBox(hWnd, g_msg_lang[MSGID_VLNK_NO_DST], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
CloseHandle(hFile);
swprintf_s(Msg, 1024, L"%ls %ls", g_msg_lang[MSGID_VLNK_POINT_TO], szDst);
MessageBox(hWnd, Msg, g_msg_lang[MSGID_INFO], MB_OK | MB_ICONINFORMATION);
return 0;
}
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
WORD NotifyCode;
WORD CtrlID;
switch (Message)
{
case WM_COMMAND:
{
NotifyCode = HIWORD(wParam);
CtrlID = LOWORD(wParam);
if (NotifyCode == BN_CLICKED)
{
if (CtrlID == IDC_BUTTON1)
{
EnableWindow(g_create_button, FALSE);
CreateVlnk(hWnd, g_CurDirW);
EnableWindow(g_create_button, TRUE);
}
else if (CtrlID == IDC_BUTTON2)
{
EnableWindow(g_parse_button, FALSE);
ParseVlnk(hWnd);
EnableWindow(g_parse_button, TRUE);
}
}
break;
}
case WM_INITDIALOG:
{
InitDialog(hWnd, wParam, lParam);
break;
}
case WM_CLOSE:
{
OnDestroyDialog();
EndDialog(hWnd, 0);
}
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
int i;
HANDLE hMutex;
UNREFERENCED_PARAMETER(hPrevInstance);
if (GetUserDefaultUILanguage() == 0x0804)
{
g_msg_lang = g_msg_cn;
}
else
{
g_msg_lang = g_msg_en;
}
hMutex = CreateMutexA(NULL, TRUE, "VtoyVlnkMUTEX");
if ((hMutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS))
{
MessageBoxW(NULL, g_msg_lang[MSGID_RUNNING_TIP], g_msg_lang[MSGID_ERROR], MB_OK | MB_ICONERROR);
return 1;
}
GetCurrentDirectoryA(MAX_PATH, g_CurDirA);
GetCurrentDirectoryW(MAX_PATH, g_CurDirW);
sprintf_s(g_LogFile, sizeof(g_LogFile), "%s\\VentoyVlnk.log", g_CurDirA);
for (i = 0; i < __argc; i++)
{
if (strncmp(__argv[i], "-Q", 2) == 0 ||
strncmp(__argv[i], "-q", 2) == 0)
{
g_LogFile[0] = 0;
break;
}
}
LogA("========= VentoyVlnk =========\n");
g_hInst = hInstance;
DialogBoxA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG1), NULL, DialogProc);
return 0;
}

80
Vlnk/src/vlnk.c Normal file
View File

@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "vlnk.h"
int ventoy_create_vlnk(uint32_t disksig, uint64_t partoffset, const char *path, ventoy_vlnk *vlnk)
{
uint32_t crc;
ventoy_guid guid = VENTOY_GUID;
memcpy(&(vlnk->guid), &guid, sizeof(ventoy_guid));
vlnk->disk_signature = disksig;
vlnk->part_offset = partoffset;
#ifdef WIN32
strcpy_s(vlnk->filepath, sizeof(vlnk->filepath) - 1, path);
#else
strncpy(vlnk->filepath, path, sizeof(vlnk->filepath) - 1);
#endif
crc = ventoy_getcrc32c(0, vlnk, sizeof(ventoy_vlnk));
vlnk->crc32 = crc;
return 0;
}
int CheckVlnkData(ventoy_vlnk *vlnk)
{
uint32_t readcrc, calccrc;
ventoy_guid guid = VENTOY_GUID;
if (memcmp(&vlnk->guid, &guid, sizeof(guid)))
{
return 0;
}
readcrc = vlnk->crc32;
vlnk->crc32 = 0;
calccrc = ventoy_getcrc32c(0, vlnk, sizeof(ventoy_vlnk));
if (readcrc != calccrc)
{
return 0;
}
return 1;
}
int IsSupportedImgSuffix(char *suffix)
{
int i = 0;
const char *suffixs[] =
{
".iso", ".img", ".wim", ".efi", ".vhd", ".vhdx", ".dat", ".vtoy", NULL
};
if (!suffix)
{
return 0;
}
while (suffixs[i])
{
#ifdef WIN32
if (_stricmp(suffixs[i], suffix) == 0)
#else
if (strcasecmp(suffixs[i], suffix) == 0)
#endif
{
return 1;
}
i++;
}
return 0;
}

38
Vlnk/src/vlnk.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef __VLNK_H__
#define __VLNK_H__
#define VLNK_FILE_LEN 32768
#define VLNK_NAME_MAX 384
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
#pragma pack(1)
typedef struct ventoy_guid
{
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
}ventoy_guid;
typedef struct ventoy_vlnk
{
ventoy_guid guid; // VENTOY_GUID
uint32_t crc32; // crc32
uint32_t disk_signature;
uint64_t part_offset; // in bytes
char filepath[VLNK_NAME_MAX];
uint8_t reserverd[96];
}ventoy_vlnk;
#pragma pack()
uint32_t ventoy_getcrc32c (uint32_t crc, const void *buf, int size);
int ventoy_create_vlnk(uint32_t disksig, uint64_t partoffset, const char *path, ventoy_vlnk *vlnk);
int CheckVlnkData(ventoy_vlnk *vlnk);
int IsSupportedImgSuffix(char *suffix);
#endif

Binary file not shown.

View File

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VentoyVlnk", "VentoyVlnk\VentoyVlnk.vcxproj", "{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}.Debug|Win32.ActiveCfg = Debug|Win32
{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}.Debug|Win32.Build.0 = Debug|Win32
{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}.Release|Win32.ActiveCfg = Release|Win32
{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="amd64"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="arm"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="arm64"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9987D9FE-1A40-4C5F-835C-D66B0FEADA26}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>VentoyVlnk</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir);$(SolutionDir)/../../src;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)/../../src;$(ProjectDir);$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Manifest>
<AdditionalManifestFiles>$(ProjectDir)\Res\Vlnk32.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
</Link>
<Manifest>
<AdditionalManifestFiles>$(ProjectDir)\Res\Vlnk32.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\vlnk.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="VentoyVlnk.rc" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\crc32.c" />
<ClCompile Include="..\..\..\src\main_windows.c" />
<ClCompile Include="..\..\..\src\vlnk.c" />
</ItemGroup>
<ItemGroup>
<Image Include="Res\vlnk.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\vlnk.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="VentoyVlnk.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\crc32.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\main_windows.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\vlnk.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Image Include="Res\vlnk.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerWorkingDirectory>K:\test\ventoy\ventoy-1.0.57</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

Binary file not shown.