feat: First working Windows build

This commit is contained in:
Stéphane Lesimple
2020-08-23 16:36:56 +02:00
parent f9e8ce83bc
commit f8dbe54a8c
18 changed files with 3155 additions and 2511 deletions

View File

@@ -79,4 +79,4 @@ int ProbeCacheLineSize()
#endif
/* TODO MINGW: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-cache_descriptor */

View File

@@ -22,6 +22,19 @@
#include "dvdisaster.h"
/*
* Those are now declared as extern in dvdisaster.h,
* and as such are accessible from everywhere.
* MinGW didn't link these being declared directly
* in dvdisaster.h (ended up having one copy of each
* struct for every .c including dvdisaster.h)
*/
struct _RawBuffer *rawbuffer_forward;
struct _DefectiveSectorHeader *dsh_forward;
struct _DeviceHandle *dh_forward;
struct _Image *dh_image;
/*
* The all-famous main() loop
*/

View File

@@ -77,7 +77,11 @@
/* File permissions for images */
#ifdef SYS_MINGW
#define IMG_PERMS (S_IRUSR | S_IWUSR)
#else
#define IMG_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
#endif
/* Using round() is preferred over rint() on systems which have it */
@@ -452,13 +456,13 @@ typedef struct _CrcBlock
} CrcBlock;
/***
*** forward declarations
*** dvdisaster.c
***/
struct _RawBuffer *rawbuffer_forward;
struct _DefectiveSectorHeader *dsh_forward;
struct _DeviceHandle *dh_forward;
struct _Image *dh_image;
extern struct _RawBuffer *rawbuffer_forward;
extern struct _DefectiveSectorHeader *dsh_forward;
extern struct _DeviceHandle *dh_forward;
extern struct _Image *dh_image;
/***
*** bitmap.c

View File

@@ -109,6 +109,9 @@ LargeFile* LargeOpen(char *name, int flags, mode_t mode)
#ifdef HAVE_O_LARGEFILE
flags |= O_LARGEFILE;
#endif
#ifdef SYS_MINGW
flags |= O_BINARY;
#endif
cp_path = os_path(name);
if(!cp_path)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -61,7 +61,6 @@ static void action_cb(GtkWidget *widget, gpointer data)
if(action != ACTION_STOP)
{
/* Clear the log buffer, request new log file time stamp */
if(action != ACTION_CREATE_CONT)
{ g_mutex_lock(Closure->logLock);
g_string_truncate(Closure->logString, 0);
@@ -69,7 +68,6 @@ static void action_cb(GtkWidget *widget, gpointer data)
g_mutex_unlock(Closure->logLock);
Closure->logFileStamped = FALSE;
}
/* Make sure we're using the current file selections */
g_free(Closure->imageName);

View File

@@ -20,6 +20,8 @@
* along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SYS_MINGW /* completely untested under Windows, and we don't need it for releases anyway */
#define _GNU_SOURCE
#if !defined(SYS_FREEBSD) /* FreeBSD declares malloc() in stdlib.h */
@@ -85,7 +87,7 @@ void remember(void *ptr, int size, char *file, int line)
g_mutex_lock(&phMutex);
hash_idx = (((long)ptr)>>3)&63;
hash_idx = (((long long)ptr)>>3)&63;
if(phCnt[hash_idx] >= phMax[hash_idx])
{ if(!phMax[hash_idx]) phMax[hash_idx] = 16;
else phMax[hash_idx] *= 2;
@@ -348,3 +350,4 @@ void check_memleaks(void)
else g_printf("dvdisaster: No memory leaks found.\n");
}
#endif

View File

@@ -353,7 +353,7 @@ void RS01ScanImage(Method *method, Image* image, struct MD5Context *ecc_ctxt, in
}
if(crc != crcbuf[crcidx++] && !current_missing)
{ PrintCLI(_("* CRC error, sector: %lld\n"), s);
{ PrintCLI(_("* CRC error, sector: %lld, found %08x instead of %08x\n"), crc, crcbuf[crcidx], s);
image->crcErrors++;
}
}

View File

@@ -24,6 +24,10 @@
#include "rs03-includes.h"
#ifdef SYS_MINGW
#include <windows.h>
#endif
/* Needed version must be consistent between CRC blocks and ECC headers
since ECC headers may be reconstructed from CRC blocks. */
@@ -1220,7 +1224,15 @@ static void create_reed_solomon(ecc_closure *ec)
ec->chunkBytes = 2048*Closure->prefetchSectors;
ec->chunkSize = Closure->prefetchSectors;
#ifdef SYS_MINGW
{
SYSTEM_INFO si;
GetSystemInfo(&si);
ec->pageSize = si.dwPageSize;
}
#else
ec->pageSize = sysconf(_SC_PAGE_SIZE);
#endif
/*** Allocate stuff shared by all threads */

View File

@@ -18,7 +18,6 @@
# along with Bash based configure. If not, see <http://www.gnu.org/licenses/>.
#/
# Command overview:
#
# PACKAGE Define package name and version

View File

@@ -28,6 +28,11 @@
#include <linux/cdrom.h>
#endif
#ifdef SYS_MINGW
#include <windows.h>
#include <winioctl.h>
#endif
#if defined(SYS_FREEBSD) || defined(SYS_KFREEBSD)
#include <camlib.h>
#endif
@@ -106,6 +111,8 @@ typedef struct _DeviceHandle
#elif defined(SYS_FREEBSD) || defined(SYS_KFREEBSD)
struct cam_device *camdev; /* camlib device handle */
union ccb *ccb;
#elif defined(SYS_MINGW)
HANDLE fd; /* Windows SPTI file handle for the device */
#endif
/*
@@ -226,6 +233,10 @@ typedef struct _DeviceHandle
DeviceHandle* OpenDevice(char*);
#ifdef SYS_MINGW
DeviceHandle* open_spti_device(char*);
#endif
int SendPacket(DeviceHandle*, unsigned char*, int, unsigned char*, int, Sense*, int);
int SimulateSendPacket(DeviceHandle*, unsigned char*, int, unsigned char*, int, Sense*, int);

286
scsi-win32.c Normal file
View File

@@ -0,0 +1,286 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2010 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/
#include "dvdisaster.h"
#include "scsi-layer.h"
#include "udf.h"
/**
** Windows wrapper.
**
* As of dvdisaster 0.73.1, Windows 2000 SP4 is the minimum
* system requirement and thus only SPTI is supported.
*/
#ifdef SYS_MINGW
/*
* The drive letter ordering is remembered for
* historical reasons (it was once useful for ASPI mapping)
*/
static int drive_letters[26];
static int cd_dvd_drives = 0;
char* DefaultDevice()
{
char drive_letter;
char device_path[16],buf[80];
DeviceHandle *dh;
/* As a convenience, add the simulated drive first. */
InitSimulatedCD();
/* Now probe the physical drives. */
for(drive_letter='C'; drive_letter<='Z'; drive_letter++)
{ UINT drive_type;
g_sprintf(device_path, "%c:\\", drive_letter);
drive_type = GetDriveType(device_path);
if(drive_type == DRIVE_CDROM)
{ drive_letters[cd_dvd_drives] = drive_letter;
cd_dvd_drives++;
/* Collect drives accessible via SPTI */
sprintf(buf, "%c:", drive_letter);
if((dh = open_spti_device(buf)))
{ InquireDevice(dh, 1);
g_ptr_array_add(Closure->deviceNodes, g_strdup(buf));
sprintf(buf, "%c: %s", drive_letter, dh->devinfo);
g_ptr_array_add(Closure->deviceNames, g_strdup(buf));
CloseDevice(dh);
}
}
}
if(Closure->deviceNodes->len)
return g_strdup(g_ptr_array_index(Closure->deviceNodes, 0));
else
{ PrintLog(_("No optical drives found in /dev.\n"
"No drives will be pre-selected.\n"));
return g_strdup("No_Drive_found");
}
}
/*
* Close the SPTI device.
*/
void CloseDevice(DeviceHandle *dh)
{
if(dh->simImage)
LargeClose(dh->simImage);
if(dh->canReadDefective)
SetRawMode(dh, MODE_PAGE_UNSET);
if(dh->rawBuffer)
FreeRawBuffer(dh->rawBuffer);
if(dh->fd) /* SPTI cleanup */
CloseHandle(dh->fd);
if(dh->typeDescr)
g_free(dh->typeDescr);
if(dh->mediumDescr)
g_free(dh->mediumDescr);
if(dh->defects)
FreeBitmap(dh->defects);
g_free(dh->device);
g_free(dh);
}
/**
** The SPTI wrapper.
**/
/*
* The Mingw includes are missing the following structs
* for sending SCSI packets via SPTI.
*/
typedef struct
{ USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT;
typedef struct
{ SCSI_PASS_THROUGH_DIRECT spt;
ULONG Filler;
UCHAR SenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
#define IOCTL_SCSI_BASE 0x00000004
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
/*
* Open the device using SPTI.
*/
DeviceHandle* open_spti_device(char *device)
{ DeviceHandle *dh;
char device_path[16];
if( strlen(device) != 2
|| toupper(*device) < 'C'
|| toupper(*device) > 'Z'
|| device[1] != ':')
{
Stop(_("\nIllegal device name \"%s\" (use devices \"C:\" ... \"Z:\")"),device);
return NULL;
}
dh = g_malloc0(sizeof(DeviceHandle));
dh->device = g_strdup(device);
g_sprintf(device_path, "\\\\.\\%c:", toupper(*device));
dh->fd = CreateFile(device_path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if(dh->fd == INVALID_HANDLE_VALUE) /* Might be Win9x or missing priviledges */
{ g_free(dh->device);
g_free(dh);
return NULL;
}
return dh;
}
/*
* Send the SCSI command through SPTI.
* At least W2K seems to have problems with SCSI commands timing out;
* it even manages to do a spontaneous reboot because of that occasionally.
* So we set the time out value to a conservative 120 secs.
*/
static int send_spti_packet(HANDLE fd, unsigned char *cmd, int cdb_size, char *buf, int size, Sense *sense, int data_mode)
{ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER ss;
BOOL success;
ULONG returned;
memset(&ss, 0, sizeof(ss));
ss.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
ss.spt.CdbLength = cdb_size;
ss.spt.SenseInfoLength = 24;
ss.spt.TargetId = 1;
switch(data_mode)
{ case DATA_WRITE:
ss.spt.DataIn = 0; /* SCSI_IOCTL_DATA_OUT */
break;
case DATA_READ:
ss.spt.DataIn = 1; /* SCSI_IOCTL_DATA_IN */
break;
case DATA_NONE:
ss.spt.DataIn = 2; /* SCSI_IOCTL_DATA_UNSPECIFIED */
break;
default:
Stop("illegal data_mode: %d",data_mode);
return -1;
}
ss.spt.DataTransferLength = size;
ss.spt.TimeOutValue = 120; /* see comment above */
ss.spt.DataBuffer = buf;
ss.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseBuf);
memcpy(ss.spt.Cdb, cmd, cdb_size);
success = DeviceIoControl(fd, IOCTL_SCSI_PASS_THROUGH_DIRECT,
&ss, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&ss, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER),
&returned, FALSE);
memcpy(sense, ss.SenseBuf, 24); /* Hmm. What a kludge. */
if(!success || ss.spt.ScsiStatus) return -1;
return 0;
}
/*
* Open the device
*/
DeviceHandle* OpenDevice(char *device)
{ DeviceHandle *dh = NULL;
if(!strcmp(device, "sim-cd"))
{ if(!Closure->simulateCD) /* can happen via resource file / last-device */
return NULL;
dh = g_malloc0(sizeof(DeviceHandle));
dh->senseSize = sizeof(Sense);
dh->simImage = LargeOpen(Closure->simulateCD, O_RDONLY, IMG_PERMS);
if(!dh->simImage)
{ g_free(dh);
Stop(_("Could not open %s: %s"), Closure->simulateCD, strerror(errno));
return NULL;
}
}
else {
if( (*device >= 'c' && *device <= 'z')
|| (*device >= 'C' && *device <= 'Z'))
dh = open_spti_device(Closure->device);
if(!dh)
{ Stop(_("\nCould not open device %s."), device);
return NULL;
}
}
return dh;
}
/*
* Translate Scsi wrapper into SPTI call
*/
int SendPacket(DeviceHandle *dh, unsigned char *cmd, int cdb_size, unsigned char *buf, int size, Sense *sense, int data_mode)
{
if(dh->simImage)
return SimulateSendPacket(dh, cmd, cdb_size, buf, size, sense, data_mode);
return send_spti_packet(dh->fd, cmd, cdb_size, (char *)buf, size, sense, data_mode);
}
#endif /* SYS_MINGW */

View File

@@ -23,12 +23,23 @@
#include "dvdisaster.h"
#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_KFREEBSD) || \
defined(SYS_NETBSD) || defined(SYS_HURD)
#include <sys/wait.h>
#endif
#ifdef SYS_MINGW
#include "windows.h"
#include "shellapi.h"
#endif
/***
*** Ask user to specify his viewer
***/
#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_KFREEBSD) || \
defined(SYS_NETBSD) || defined(SYS_HURD)
#define SEARCH_BUTTON 1
typedef struct
@@ -141,6 +152,7 @@ static void viewer_dialog(char *path)
gtk_widget_show_all(dialog);
}
#endif /* SYS_ unix-like */
/***
*** Show the manual in an external viewer
@@ -165,6 +177,9 @@ static void msg_destroy_cb(GtkWidget *widget, gpointer data)
bi->msg = NULL;
}
#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_KFREEBSD) || \
defined(SYS_NETBSD) || defined(SYS_HURD)
/*
* The following list of viewers
* will be tried one at a time until one entry succeeds by:
@@ -234,11 +249,34 @@ static gboolean viewer_timeout_func(gpointer data)
return bi->seconds > 60 ? FALSE : TRUE;
}
#endif /* SYS_ unix-like */
#ifdef SYS_MINGW
static gboolean viewer_timeout_func(gpointer data)
{ viewer_info *bi = (viewer_info*)data;
bi->seconds++;
if(bi->seconds >= 10)
{ if(bi->msg)
{ gtk_widget_destroy(bi->msg);
bi->msg = NULL;
}
//if(bi->url) g_free(bi->url);
g_free(bi);
return FALSE;
}
return TRUE;
}
#endif /* SYS_MINGW */
/*
* Invoke the viewer
*/
#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_KFREEBSD) || \
defined(SYS_NETBSD) || defined(SYS_HURD)
static void try_viewer(viewer_info *bi)
{ pid_t pid;
@@ -274,6 +312,8 @@ static void try_viewer(viewer_info *bi)
_exit(110); /* couldn't execute */
}
}
#endif /* SYS_ unix-like */
void ShowPDF(char *target)
{ viewer_info *bi = g_malloc0(sizeof(viewer_info));
@@ -311,6 +351,15 @@ void ShowPDF(char *target)
/* Try the first viwer */
#ifdef SYS_MINGW
/* Okay, Billy wins big time here ;-) */
ShellExecute(NULL, "open", bi->path, NULL, NULL, SW_SHOWNORMAL);
g_timeout_add(1000, viewer_timeout_func, (gpointer)bi);
#endif
#if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_DARWIN) || defined(SYS_NETBSD)
viewer_index = 0;
try_viewer(bi);
#endif
}