]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/win32/patches/mtx.patch
Restore win32 dir from Branch-5.2 and update it
[bacula/bacula] / bacula / src / win32 / patches / mtx.patch
diff --git a/bacula/src/win32/patches/mtx.patch b/bacula/src/win32/patches/mtx.patch
new file mode 100644 (file)
index 0000000..d22e261
--- /dev/null
@@ -0,0 +1,1576 @@
+Index: README.win32
+===================================================================
+--- /dev/null  Sat Jul 29 14:54:52 2006
++++ README.win32       Sat Jul 29 14:46:45 2006
+@@ -0,0 +1,22 @@
++CHANGES FROM UNIX
++=================
++
++The only difference is in the naming of devices.  On Linux the changer is 
++accessed using /dev/sg<N>, on Windows you use Changer<N>.
++
++On Linux the tape drive is referenced using /dev/nst<N>, on Windows you use
++Tape<N>.
++
++There is one exception in the case where there isn't a driver loaded for the
++device.  This is usually only the case on Windows 2000 or if the Windows XP or
++Windows Server 2003 system supplied driver has been disabled.
++
++In the case where there is no driver loaded you can access the device directly 
++through the SCSI driver using the following notation:
++
++      <port>:<bus>:<target>:<lun>
++      
++              Port is the adapter number
++              Bus is the SCSI bus number relative to the adapter
++              Target is the SCSI device's target ID
++              LUN is the SCSI device's logical unit number
+Index: scsi_win32.c
+===================================================================
+--- /dev/null  Sat Jul 29 14:55:00 2006
++++ scsi_win32.c       Sat Jul 29 14:54:08 2006
+@@ -0,0 +1,353 @@
++/* Copyright 2006 Robert Nelson <robertn@the-nelsons.org>
++
++$Date: 2006-07-30 06:32:36 -0700 (Sun, 30 Jul 2006) $
++$Revision: 3200 $
++
++  This program is free software; you may redistribute and/or modify it under
++  the terms of the GNU General Public License Version 2 as published by the
++  Free Software Foundation.
++
++  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 complete details.
++
++*/
++
++/* These are the SCSI commands for Microsoft Windows.  This is derived from
++ * the file scsi_linux.c substituting Windows specific emulation of the Linux
++ * behaviour.
++ */
++
++#include <stdio.h>
++#include <windows.h>
++
++#ifdef _MSC_VER
++#include <ntddscsi.h>
++#else
++#include <ddk/ntddscsi.h>
++#endif
++
++#ifndef HZ
++#define HZ 1000
++#endif
++
++/* These are copied out of BRU 16.1, with all the boolean masks changed
++ * to our bitmasks.
++*/
++#define S_NO_SENSE(s) ((s)->SenseKey == 0x0)
++#define S_RECOVERED_ERROR(s) ((s)->SenseKey == 0x1)
++
++#define S_NOT_READY(s) ((s)->SenseKey == 0x2)
++#define S_MEDIUM_ERROR(s) ((s)->SenseKey == 0x3)
++#define S_HARDWARE_ERROR(s) ((s)->SenseKey == 0x4)
++#define S_UNIT_ATTENTION(s) ((s)->SenseKey == 0x6)
++#define S_BLANK_CHECK(s) ((s)->SenseKey == 0x8)
++#define S_VOLUME_OVERFLOW(s) ((s)->SenseKey == 0xd)
++
++#define DEFAULT_TIMEOUT 3 * 60  /* 3 minutes here */
++
++/* Sigh, the T-10 SSC spec says all of the following is needed to
++ * detect a short read while in variable block mode, and that even
++ * though we got a BLANK_CHECK or MEDIUM_ERROR, it's still a valid read.
++ */
++
++#define HIT_FILEMARK(s) (S_NO_SENSE((s)) && (s)->Filemark && (s)->Valid)
++#define SHORT_READ(s) (S_NO_SENSE((s)) && (s)->ILI && (s)->Valid &&  (s)->AdditionalSenseCode==0  && (s)->AdditionalSenseCodeQualifier==0)
++#define HIT_EOD(s) (S_BLANK_CHECK((s)) && (s)->Valid)
++#define HIT_EOP(s) (S_MEDIUM_ERROR((s)) && (s)->EOM && (s)->Valid)
++#define HIT_EOM(s) ((s)->EOM && (s)->Valid)
++
++#define STILL_A_VALID_READ(s) (HIT_FILEMARK(s) || SHORT_READ(s) || HIT_EOD(s) || HIT_EOP(s) || HIT_EOM(s))
++
++#define SCSI_DEFAULT_TIMEOUT  60    /* 1 minute */
++#define SCSI_MAX_TIMEOUT      108   /* 1 minute 48 seconds */
++
++typedef       struct  _HANDLE_ENTRY {
++  HANDLE  hDevice;
++  UCHAR   PortId;
++  UCHAR   PathId;
++  UCHAR   TargetId;
++  UCHAR   Lun;
++} HANDLE_ENTRY, *PHANDLE_ENTRY;
++
++PHANDLE_ENTRY HandleTable = NULL;
++int           nEntries = 0;
++
++DEVICE_TYPE SCSI_OpenDevice(char *DeviceName)
++{
++  int   DeviceIndex;
++  TCHAR szDevicePath[256];
++
++  int   nColons = 0;
++  int   index;
++
++  int   port, path, target, lun;
++
++  for (DeviceIndex = 0; DeviceIndex < nEntries; DeviceIndex++)
++  {
++    if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
++      break;
++  }
++
++  if (DeviceIndex >= nEntries)
++  {
++    PHANDLE_ENTRY pNewTable;
++
++    nEntries += 4;
++
++    if (HandleTable == NULL)
++    {
++      pNewTable = (PHANDLE_ENTRY)malloc(nEntries * sizeof(HANDLE_ENTRY));
++    }
++    else
++    {
++      pNewTable = (PHANDLE_ENTRY)realloc(HandleTable, nEntries * sizeof(HANDLE_ENTRY));
++    }
++
++    if (pNewTable == NULL)
++    {
++      FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
++    }
++
++    HandleTable = pNewTable;
++  }
++
++  for (index = 0; DeviceName[index] != '\0'; index++)
++  {
++    if (DeviceName[index] == ':')
++      nColons++;
++    else if (DeviceName[index] < '0' || DeviceName[index] > '9')
++      break;
++  }
++
++  if (DeviceName[index] == '\0' && nColons == 3 && 
++      sscanf(DeviceName, "%d:%d:%d:%d", &port, &path, &target, &lun) == 4) {
++
++    HandleTable[DeviceIndex].PortId = (UCHAR)port;
++    HandleTable[DeviceIndex].PathId = (UCHAR)path;
++    HandleTable[DeviceIndex].TargetId = (UCHAR)target;
++    HandleTable[DeviceIndex].Lun = (UCHAR)lun;
++
++    sprintf(szDevicePath, "\\\\.\\scsi%d:", port);
++  }
++  else 
++  {
++    int nPrefixLength = 0;
++
++    if (DeviceName[0] != '\\') {
++      memcpy(szDevicePath, "\\\\.\\", 4 * sizeof(TCHAR));
++      nPrefixLength = 4;
++    }
++
++    HandleTable[DeviceIndex].PortId = 0;
++    HandleTable[DeviceIndex].PathId = 0;
++    HandleTable[DeviceIndex].TargetId = 0;
++    HandleTable[DeviceIndex].Lun = 0;
++
++    strncpy( &szDevicePath[nPrefixLength], 
++              DeviceName, 
++              sizeof(szDevicePath) / sizeof(TCHAR) - nPrefixLength - 1);
++    
++    szDevicePath[sizeof(szDevicePath) / sizeof(TCHAR) - 1] = '\0';
++  }
++
++  HandleTable[DeviceIndex].hDevice = CreateFile(szDevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
++
++  if (HandleTable[DeviceIndex].hDevice == INVALID_HANDLE_VALUE)
++  {
++    DWORD dwError = GetLastError();
++
++#if DEBUG
++    LPSTR lpszMessage;
++
++    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
++    fputs(lpszMessage, stderr);
++#endif
++
++    switch (dwError) {
++    case ERROR_FILE_NOT_FOUND:
++    case ERROR_PATH_NOT_FOUND:
++      errno = ENOENT;
++      break;
++
++    case ERROR_TOO_MANY_OPEN_FILES:
++      errno =  EMFILE;
++      break;
++
++    default:
++    case ERROR_ACCESS_DENIED:
++    case ERROR_SHARING_VIOLATION:
++    case ERROR_LOCK_VIOLATION:
++    case ERROR_INVALID_NAME:
++      errno = EACCES;
++      break;
++
++    case ERROR_FILE_EXISTS:
++      errno = EEXIST;
++      break;
++
++    case ERROR_INVALID_PARAMETER:
++      errno = EINVAL;
++      break;
++    }
++
++    FatalError("cannot open SCSI device '%s' - %m\n", DeviceName);
++  }
++
++  return DeviceIndex;
++}
++
++static int scsi_timeout = SCSI_DEFAULT_TIMEOUT;
++
++void SCSI_Set_Timeout(int secs)
++{
++  if (secs > SCSI_MAX_TIMEOUT) {
++    secs = SCSI_MAX_TIMEOUT;
++  }
++  scsi_timeout = secs * HZ;
++}
++ 
++void SCSI_Default_Timeout(void)
++{
++  scsi_timeout = SCSI_DEFAULT_TIMEOUT * HZ;
++}
++
++void SCSI_CloseDevice(char *DeviceName, DEVICE_TYPE DeviceFD)
++{
++  if (DeviceFD < nEntries)
++  {
++    CloseHandle(HandleTable[DeviceFD].hDevice);
++    HandleTable[DeviceFD].hDevice = INVALID_HANDLE_VALUE;
++  }
++  else
++  {
++    errno = EBADF;
++    FatalError("cannot close SCSI device '%s' - %m\n", DeviceName);
++  }
++}
++
++
++/* Added by Eric Green <eric@estinc.com> to deal with burping
++ * Seagate autoloader (hopefully!). 
++ */
++/* Get the SCSI ID and LUN... */
++scsi_id_t *SCSI_GetIDLun(DEVICE_TYPE fd) {
++  scsi_id_t *          retval;
++
++  SCSI_ADDRESS         ScsiAddress;
++  BOOL                 bResult;
++  DWORD                dwBytesReturned;
++
++  if (fd < nEntries) {
++    retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
++    retval->id = HandleTable[fd].TargetId;
++    retval->lun = HandleTable[fd].Lun;
++
++#ifdef DEBUG
++    fprintf(stderr,"SCSI:ID=%d LUN=%d\n", retval->id, retval->lun);
++#endif
++    return retval;
++  } else {
++    errno = EBADF;
++    FatalError("cannot close SCSI device - %m\n");
++  }
++
++  memset(&ScsiAddress, 0, sizeof(ScsiAddress));
++
++  ScsiAddress.Length = sizeof(ScsiAddress);
++
++  bResult = DeviceIoControl(HandleTable[fd].hDevice, 
++                            IOCTL_SCSI_GET_ADDRESS, 
++                            &ScsiAddress, sizeof(ScsiAddress), 
++                            &ScsiAddress, sizeof(ScsiAddress), 
++                            &dwBytesReturned, 
++                            NULL);
++   
++  if (!bResult) {
++    return NULL;
++  }
++
++  retval = (scsi_id_t *)xmalloc(sizeof(scsi_id_t));
++  retval->id = ScsiAddress.TargetId;
++  retval->lun = ScsiAddress.Lun;
++
++#ifdef DEBUG
++  fprintf(stderr,"SCSI:ID=%d LUN=%d\n",retval->id,retval->lun);
++#endif
++  return retval;
++}
++  
++int SCSI_ExecuteCommand(DEVICE_TYPE DeviceFD,
++                        Direction_T Direction,
++                        CDB_T *CDB,
++                        int CDB_Length,
++                        void *DataBuffer,
++                        int DataBufferLength,
++                        RequestSense_T *RequestSense)
++{
++  PSCSI_PASS_THROUGH_DIRECT ScsiPassThrough;
++
++  const DWORD dwBufferSize = sizeof(SCSI_PASS_THROUGH_DIRECT) + sizeof(RequestSense_T);
++  BOOL        bResult;
++  DWORD       dwBytesReturned;
++
++  if (DeviceFD >= nEntries || HandleTable[DeviceFD].hDevice == INVALID_HANDLE_VALUE)
++  {
++    errno = EBADF;
++    return -1;
++  }
++
++  ScsiPassThrough = (PSCSI_PASS_THROUGH_DIRECT)malloc(dwBufferSize);
++
++  memset(ScsiPassThrough, 0, dwBufferSize);
++
++  ScsiPassThrough->Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
++
++  ScsiPassThrough->PathId = HandleTable[DeviceFD].PathId;
++  ScsiPassThrough->TargetId = HandleTable[DeviceFD].TargetId;
++  ScsiPassThrough->Lun = HandleTable[DeviceFD].Lun;
++  ScsiPassThrough->CdbLength = (UCHAR)CDB_Length;
++  ScsiPassThrough->SenseInfoLength = sizeof(RequestSense_T);
++  ScsiPassThrough->DataIn = Direction == Input;
++  ScsiPassThrough->DataTransferLength = DataBufferLength;
++  ScsiPassThrough->TimeOutValue = scsi_timeout;
++  ScsiPassThrough->DataBuffer = DataBuffer;
++  ScsiPassThrough->SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
++
++  memcpy(ScsiPassThrough->Cdb, CDB, CDB_Length);
++  dwBytesReturned = 0;
++
++  bResult = DeviceIoControl(HandleTable[DeviceFD].hDevice, 
++                            IOCTL_SCSI_PASS_THROUGH_DIRECT, 
++                            ScsiPassThrough, sizeof(SCSI_PASS_THROUGH_DIRECT), 
++                            ScsiPassThrough, dwBufferSize, 
++                            &dwBytesReturned, 
++                            NULL);
++  if (bResult) {
++    if (ScsiPassThrough->ScsiStatus != 0) {
++      memcpy(RequestSense, &ScsiPassThrough[1], sizeof(RequestSense_T));
++#if DEBUG
++      fprintf(stderr, "Command failed - ScsiStatus = %d\n", ScsiPassThrough->ScsiStatus);
++      PrintRequestSense(RequestSense);
++#endif
++      bResult = false;
++    }
++  }
++  else
++  {
++#if DEBUG
++    DWORD   dwError = GetLastError();
++    LPSTR   lpszMessage;
++
++    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPSTR)&lpszMessage, 0, NULL);
++    fputs(lpszMessage, stderr);
++#endif
++
++    memset(RequestSense, 0, sizeof(RequestSense_T));
++  }
++
++  free(ScsiPassThrough);
++
++  return bResult ? 0 : -1;
++}
+Index: tapeinfo.c
+===================================================================
+--- tapeinfo.c (revision 139)
++++ tapeinfo.c (revision 147)
+@@ -211,25 +211,18 @@
+   unsigned int partition1_size;
+ } TapeCapacity;
++#if defined(DEBUG)
+ /* DEBUG */
+ static void dump_data(unsigned char *data, int len) {
+-  int i;
+   if (!len) {
+     fprintf(stderr,"**NO DATA**\n");
+     return;
+   }
+-  for (i=0;i<len;i++) {
+-    if ((i % 10) == 0) {
+-      if (i) {
+-      fprintf(stderr,"\n");
+-      }
+-      fprintf(stderr,"DATA:");
+-    }
+-    fprintf(stderr,"%02x ",(unsigned int)*data++);
+-  }
+-  fprintf(stderr,"\n");
++  fprintf(stderr,"DATA:");
++  PrintHex(1, data, len);
+ }
++#endif
+@@ -243,7 +236,7 @@
+   
+   unsigned char buffer[TAPEALERT_SIZE]; /* Overkill, but ... */
+-  slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
++  slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
+   /* now to create the CDB block: */
+   CDB[0]=0x4d;   /* Log Sense */
+@@ -325,7 +318,7 @@
+   unsigned char buffer[TAPEALERT_SIZE];
+   unsigned char *walkptr;
+-  slow_bzero(buffer,TAPEALERT_SIZE); /*zero it... */
++  slow_bzero((char *)buffer,TAPEALERT_SIZE); /*zero it... */
+   /* now to create the CDB block: */
+   CDB[0]=0x4d;   /* Log Sense */
+@@ -676,7 +669,7 @@
+      the sernum field, and bytes 4 onward are the serial #. */
+   
+   lim=(int)buffer[3];
+-  bufptr= &(buffer[4]);
++  bufptr=(char *)&(buffer[4]);
+   
+   printf("SerialNumber: '");
+   for (i=0;i<lim;i++) {
+@@ -702,7 +695,7 @@
+   CDB[4]=0;
+   CDB[5]=0; 
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,6,&sense)!=0){
+     return;
+   }
+@@ -735,7 +728,7 @@
+   CDB[8]=0;
+   CDB[9]=0;
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   /* set the timeout: */
+   SCSI_Set_Timeout(2); /* set timeout to 2 seconds! */
+@@ -789,7 +782,7 @@
+   CDB[4]=0;
+   CDB[5]=0; 
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
+     printf("Ready: no\n");
+     return 0;
+@@ -817,7 +810,7 @@
+   CDB[5]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(fd,Input,&CDB,6,buffer,0,&sense)!=0){
+     return 1;
+   }
+Index: mtx.c
+===================================================================
+--- mtx.c      (revision 139)
++++ mtx.c      (revision 147)
+@@ -623,7 +623,7 @@
+              "illegal <drive-number> argument '%d' to 'unload' command\n",
+              arg2);
+   }
+-  if (ElementStatus->DataTransferElementFull[arg2] < 0 ) {
++  if (!ElementStatus->DataTransferElementFull[arg2]) {
+     FatalError("Data Transfer Element %d is Empty\n", arg2);
+   }    
+   /* Now see if something already lives where  we wanna go... */
+@@ -715,7 +715,7 @@
+     }
+     ElementStatus = ReadElementStatus(MediumChangerFD,&RequestSense,inquiry_info,&SCSI_Flags);
+     if (!ElementStatus) {
+-      PrintRequestSense(&RequestSense);                   
++      PrintRequestSense(&RequestSense);
+       FatalError("READ ELEMENT STATUS Command Failed\n"); 
+     }
+   }
+@@ -813,9 +813,6 @@
+   argv0=argv[0];
+-   
+-
+-
+   parse_args();  /* also executes them as it sees them, sigh. */
+ #ifndef VMS
+Index: scsitape.c
+===================================================================
+--- scsitape.c (revision 139)
++++ scsitape.c (revision 147)
+@@ -41,11 +41,26 @@
+ #include "mtx.h"
+ #include "mtxl.h"
++#if HAVE_UNISTD_H
+ #include <unistd.h>
++#endif
++
++#if HAVE_SYS_TYPES_H
+ #include <sys/types.h>
++#endif
++
++#if HAVE_SYS_IOCTL_H
+ #include <sys/ioctl.h>
++#endif
++
++#if HAVE_SYS_MTIO_H
+ #include <sys/mtio.h> /* will try issuing some ioctls for Solaris, sigh. */
++#endif
++#ifdef _MSC_VER
++#include <io.h>
++#endif
++
+ void Usage(void) {
+   FatalError("Usage: scsitape -f <generic-device> <command> where <command> is:\n setblk <n> | fsf <n> | bsf <n> | eod | rewind | eject | mark <n> |\n  seek <n> | read [<blksize> [<numblocks]] | write [<blocksize>] \n");
+ }
+@@ -54,7 +69,7 @@
+ static int arg[4];  /* the argument for the command, sigh. */
+ /* the device handle we're operating upon, sigh. */
+-static unsigned char *device;  /* the text of the device thingy. */
++static char *device;  /* the text of the device thingy. */
+ static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) 0;
+@@ -96,43 +111,7 @@
+ char *argv0;
+-/* A table for printing out the peripheral device type as ASCII. */ 
+-static char *PeripheralDeviceType[32] = {
+-  "Disk Drive",
+-  "Tape Drive",
+-  "Printer",
+-  "Processor",
+-  "Write-once",
+-  "CD-ROM",
+-  "Scanner",
+-  "Optical",
+-  "Medium Changer",
+-  "Communications",
+-  "ASC IT8",
+-  "ASC IT8",
+-  "RAID Array",
+-  "Enclosure Services",
+-  "OCR/W",
+-  "Bridging Expander", /* 0x10 */
+-  "Reserved",  /* 0x11 */
+-  "Reserved", /* 0x12 */
+-  "Reserved",  /* 0x13 */
+-  "Reserved",  /* 0x14 */
+-  "Reserved",  /* 0x15 */
+-  "Reserved",  /* 0x16 */
+-  "Reserved",  /* 0x17 */
+-  "Reserved",  /* 0x18 */
+-  "Reserved",  /* 0x19 */
+-  "Reserved",  /* 0x1a */
+-  "Reserved",  /* 0x1b */
+-  "Reserved",  /* 0x1c */
+-  "Reserved",  /* 0x1d */
+-  "Reserved",  /* 0x1e */
+-  "Unknown"    /* 0x1f */
+-};
+-
+-
+ /* open_device() -- set the 'fh' variable.... */
+ void open_device(void) {
+@@ -301,7 +280,7 @@
+   CDB[5]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&RequestSense,sizeof(RequestSense_T));
++  slow_bzero((char *)&RequestSense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&RequestSense)!=0){
+     PrintRequestSense(&RequestSense);
+     return 1;
+@@ -324,7 +303,7 @@
+   CDB[5]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
+     PrintRequestSense(&sense);
+     return 1;
+@@ -349,7 +328,7 @@
+   CDB[5]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
+     PrintRequestSense(&sense);
+     return 1;
+@@ -392,7 +371,7 @@
+   CDB[5]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,buffer,0,&sense)!=0){
+     PrintRequestSense(&sense);
+     return 1;
+@@ -422,7 +401,7 @@
+   CDB[9]=0; 
+   /* we really don't care if this command works or not, sigh.  */
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,10,buffer,0,&sense)!=0){
+     PrintRequestSense(&sense);
+     return 1;
+@@ -462,7 +441,7 @@
+ static int S_setblk(void) {
+   RequestSense_T sense;
+   CDB_T CDB;
+-  unsigned char buffer[12];
++  char buffer[12];
+   unsigned int count = (unsigned int) arg1;
+   
+@@ -473,7 +452,7 @@
+   CDB[4]=12; /* length of data */
+   CDB[5]=0;
+-  slow_bzero((unsigned char *)&sense,sizeof(RequestSense_T));
++  slow_bzero((char *)&sense,sizeof(RequestSense_T));
+   slow_bzero(buffer,12);
+   /* Now to set the mode page header: */
+@@ -679,9 +658,9 @@
+ /* S_write is not implemented yet! */
+ static int S_write(void) {
+-  unsigned char *buffer; /* the buffer we're gonna read/write out of. */
++  char *buffer; /* the buffer we're gonna read/write out of. */
+   int buffersize;
+-  int len; /* the length of the data in the buffer */
++  unsigned int len; /* the length of the data in the buffer */
+   int blocksize=arg[0];
+   int numblocks=arg[1];
+   int varsize=0; /* variable size block flag */
+@@ -755,9 +734,9 @@
+ static int S_read(void) {
+-  unsigned char *buffer; /* the buffer we're going to be reading out of */
++  char *buffer; /* the buffer we're going to be reading out of */
+   int buffersize;
+-  int len; /* the length of the data in the buffer */
++  unsigned int len; /* the length of the data in the buffer */
+   int blocksize=arg[0];
+   int numblocks=arg[1];
+   int varsize=0; /* variable size block flag. */
+Index: mtx.h
+===================================================================
+--- mtx.h      (revision 139)
++++ mtx.h      (working copy)
+@@ -18,7 +18,11 @@
+ #include "[.vms]defs.h"
+ #else /* all the Unix stuff:  */
++#ifdef _MSC_VER
++#include "msvc/config.h"  /* all the autoconf stuff. */
++#else
+ #include "config.h"  /* all the autoconf stuff. */
++#endif
+ /* all the general Unix includes: */
+@@ -59,7 +63,7 @@
+ #  include <sys/ioctl.h>
+ #endif
+-/* Now greately modified to use GNU Autoconf stuff: */
++/* Now greatly modified to use GNU Autoconf stuff: */
+ /* If we use the 'sg' interface, like Linux, do this: */
+ #if HAVE_SCSI_SG_H
+ #  include <scsi/scsi.h>
+@@ -69,6 +73,27 @@
+ #  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
+ #endif
++/* Windows Native programs built using MinGW */
++#if HAVE_DDK_NTDDSCSI_H
++#  include <windows.h>
++#  include <ddk/ntddscsi.h>
++#  undef DEVICE_TYPE
++
++typedef int DEVICE_TYPE;
++#  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
++#endif
++
++/* Windows Native programs built using Microsoft Visual C */
++#ifdef _MSC_VER
++#  include <windows.h>
++#  include <winioctl.h>
++#  include <ntddscsi.h>
++#  undef DEVICE_TYPE
++
++typedef int DEVICE_TYPE;
++#  define HAVE_GET_ID_LUN 1  /* signal that we have it... */
++#endif
++
+ /* The 'cam' interface, like FreeBSD: */
+ #if HAVE_CAMLIB_H
+ #  include <camlib.h> /* easy (?) access to the CAM user library. */
+@@ -176,10 +201,23 @@
+   unsigned char invert2; /* used for EXCHANGE command, sigh. */
+ } SCSI_Flags_T;
++#ifdef _MSC_VER
++typedef unsigned char boolean;
++
++#define false   0
++#define true    1
++
++
++typedef unsigned char Direction_T;
++
++#define Input   0
++#define Output  1
++#else
+ typedef enum { false, true } boolean;
+ typedef enum { Input, Output } Direction_T;
++#endif
+ typedef unsigned char CDB_T[12];
+@@ -354,6 +392,15 @@
+ } ElementModeSense_T;
++#ifdef _MSC_VER
++typedef char ElementTypeCode_T;
++
++#define AllElementTypes               0
++#define MediumTransportElement  1
++#define StorageElement                2
++#define ImportExportElement     3
++#define DataTransferElement     4
++#else
+ typedef enum ElementTypeCode
+ {
+   AllElementTypes =           0,
+@@ -363,6 +410,7 @@
+   DataTransferElement =               4
+ }
+ ElementTypeCode_T;
++#endif
+ typedef struct ElementStatusDataHeader
+Index: nsmhack.c
+===================================================================
+--- nsmhack.c  (revision 139)
++++ nsmhack.c  (revision 147)
+@@ -33,13 +33,13 @@
+ #include "mtxl.h"  /* get the SCSI routines out of the main file */
+-/*****************************************************************
++/****************************************************************/
+ /* Variables:  */
+ /****************************************************************/   
+ /* the device handle we're operating upon, sigh. */
+-static unsigned char *device;  /* the text of the device thingy. */
+-static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) 0;
++static char *device;  /* the text of the device thingy. */
++static DEVICE_TYPE MediumChangerFD = (DEVICE_TYPE) -1;
+ char *argv0;
+ int arg[4]; /* arguments for the command. */
+ #define arg1 (arg[0])  /* for backward compatibility, sigh */
+@@ -74,7 +74,7 @@
+ /* open_device() -- set the 'fh' variable.... */
+ void open_device(void) {
+-  if (MediumChangerFD) {
++  if (MediumChangerFD != -1) {
+     SCSI_CloseDevice("Unknown",MediumChangerFD);  /* close it, sigh...  new device now! */
+   }
+@@ -101,7 +101,7 @@
+   /* if the device is not already open, then open it from the 
+    * environment.
+    */
+-  if (!MediumChangerFD) {
++  if (MediumChangerFD == -1) {
+     /* try to get it from STAPE or TAPE environment variable... */
+     device=getenv("STAPE");
+     if (device==NULL) {
+@@ -302,7 +302,7 @@
+ }
+ static int S_tongue_in(void) {
+-
++  return 0;
+ }
+ /* okay, stick our tongue out. We need a slot ID to grab a caddy from. */
+@@ -326,6 +326,7 @@
+   }
+   
+   /* Okay, we have element status, so now let's assume that */
++  return 0;
+ }
+ /* See parse_args for the scoop. parse_args does all. */
+Index: mtxl.h
+===================================================================
+--- mtxl.h     (revision 139)
++++ mtxl.h     (revision 147)
+@@ -27,6 +27,9 @@
+ #include "mtx.h"
++#undef min
++#undef max
++
+ void FatalError(char *ErrorMessage, ...);
+ void *xmalloc(size_t Size);
+ void *xzmalloc(size_t Size);
+Index: config.h
+===================================================================
+--- ../release/mtx-1.3.9/config.h.in   2003-09-29 19:43:20.000000000 -0700
++++ config.h   2006-07-30 00:42:37.000000000 -0700
+@@ -1,3 +1,4 @@
++/* config.h.  Generated by configure.  */
+ /* Copyright 2001 Enhanced Software Technologies Inc.
+  * Released under GNU General Public License V2 or Above
+  * See http://www.gnu.org for more information about the terms of
+@@ -10,10 +11,10 @@
+ #define CONFIG_H 1
+ /* autoconf changes these. */
+-#define HAVE_STRING_H 0
+-#define HAVE_UNISTD_H 0
+-#define HAVE_STDLIB_H 0
+-#define HAVE_STDARG_H 0
++#define HAVE_STRING_H 1
++#define HAVE_UNISTD_H 1
++#define HAVE_STDLIB_H 1
++#define HAVE_STDARG_H 1
+ #define HAVE_SCSI_SCSI_H 0
+ #define HAVE_SCSI_SCSI_IOCTL_H 0
+ #define HAVE_SCSI_SG_H 0
+@@ -23,10 +24,12 @@
+ #define HAVE_SYS_SCSI_CTL_H 0
+ #define HAVE_DSLIB_H 0
+ #define HAVE_DU_DEFS_H 0
+-#define HAVE_SYS_STAT_H 0
+-#define HAVE_SYS_TYPES_H 0
+-#define HAVE_FCNTL_H 0
++#define HAVE_SYS_STAT_H 1
++#define HAVE_SYS_TYPES_H 1
++#define HAVE_FCNTL_H 1
+ #define HAVE_SYS_IOCTL_H 0
++#define HAVE_SYS_MTIO_H 0
++#define HAVE_DDK_NTDDSCSI_H 1
+ #define WORDS_BIGENDIAN 0
+Index: mtxl.c
+===================================================================
+--- ../release/mtx-1.3.9/mtxl.c        2003-10-02 23:03:20.000000000 -0700
++++ mtxl.c     2006-07-30 00:49:31.000000000 -0700
+@@ -53,6 +53,11 @@
+ #  include "scsi_linux.c"
+ #endif
++/* the IOCTL_SCSI_PASSTHROUGH interface is used on Windows. */
++#if HAVE_DDK_NTDDSCSI_H || defined(_MSC_VER)
++#  include "scsi_win32.c"
++#endif
++
+ /* The 'uscsi' interface is used on Solaris. */
+ #if HAVE_SYS_SCSI_IMPL_USCSI_H
+ #  include "scsi_sun.c"
+@@ -78,6 +83,7 @@
+ #include "[.vms]scsi.c"
+ #endif
++void PrintHex(int Indent, unsigned char *Buffer, int Length);
+ extern char *argv0; /* something to let us do good error messages. */
+ /* create a global RequestSenseT value. */
+@@ -104,6 +110,9 @@
+   if (SCSI_ExecuteCommand(fd, Input, &CDB, 6,
+                         Inquiry, sizeof(Inquiry_T), RequestSense) != 0)
+     {
++#ifdef DEBUG
++      fprintf(stderr, "SCSI Inquiry Command failed\n");
++#endif
+       free(Inquiry);
+       return NULL;  /* sorry! */
+     }
+@@ -111,36 +120,27 @@
+ }
++#if defined(DEBUG_NSM) || defined(DEBUG_EXCHANGE)
+ /* DEBUG */
+ static void dump_cdb(unsigned char *CDB, int len) {
+-  int i;
+   fprintf(stderr,"CDB:");
+-  for (i=0;i<len;i++) {
+-    fprintf(stderr,"%02x ",CDB[i]);
+-  }
+-  fprintf(stderr,"\n");
++  PrintHex(1, CDB, len);
+ }
++#endif
++#if defined(DEBUG_NSM) || defined(DEBUG_ADIC)
+ /* DEBUG */
+ static void dump_data(unsigned char *data, int len) {
+-  int i;
+   if (!len) {
+     fprintf(stderr,"**NO DATA**\n");
+     return;
+   }
+-  for (i=0;i<len;i++) {
+-    if ((i % 10) == 0) {
+-      if (i) {
+-      fprintf(stderr,"\n");
+-      }
+-      fprintf(stderr,"DATA:");
+-    }
+-    fprintf(stderr,"%02x ",(unsigned int)*data++);
+-  }
+-  fprintf(stderr,"\n");
++  fprintf(stderr,"DATA:");
++  PrintHex(1, data, len);
+ }
++#endif
+ int BigEndian16(unsigned char *BigEndianData)
+@@ -255,7 +255,7 @@
+ /* Okay, this is a hack for the NSM modular jukebox series, which
+- * uses the "SEND DIAGNOSTIC" command do to shit. 
++ * uses the "SEND DIAGNOSTIC" command to do shit. 
+  */
+ int SendNSMHack(DEVICE_TYPE MediumChangerFD, NSM_Param_T *nsm_command, 
+@@ -346,6 +346,10 @@
+   SCSI_Set_Timeout(30*60); /* 30 minutes, sigh! */
+   
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0) {
++#ifdef DEBUG
++    PrintRequestSense(&scsi_error_sense);
++    fprintf(stderr, "Initialize Element Status (0x07) failed\n");
++#endif
+     return -1;  /* could not do! */
+   }
+   return 0; /* did do! */
+@@ -364,6 +368,10 @@
+   CDB[1]=CDB[2]=CDB[3]=CDB[4]=CDB[5]=0;
+   
+   if (SCSI_ExecuteCommand(fd,Input,&CDB,6,NULL,0,&scsi_error_sense) != 0) {
++#ifdef DEBUG_MODE_SENSE
++    PrintRequestSense(&scsi_error_sense);
++    fprintf(stderr, "Eject (0x1B) failed\n");
++#endif
+     return -1;  /* could not do! */
+   }
+   return 0; /* did do! */
+@@ -396,7 +404,8 @@
+   if (SCSI_ExecuteCommand(MediumChangerFD,Input,&CDB,6,
+                         &input_buffer,sizeof(input_buffer),&scsi_error_sense) != 0) {
+ #ifdef DEBUG_MODE_SENSE
+-    fprintf(stderr,"Could not execute mode sense...\n");
++    PrintRequestSense(&scsi_error_sense);
++    fprintf(stderr,"Mode sense (0x1A) for Page 0x1D failed\n");
+     fflush(stderr);
+ #endif
+     return NULL; /* sorry, couldn't do it. */
+@@ -405,18 +414,7 @@
+   /* Could do it, now build return value: */
+ #ifdef DEBUG_MODE_SENSE
+-  {
+-    int i;
+-    for (i=0;i<30;i+=3) {
+-      fprintf(stderr,"ib[%d]=%d ib[%d]=%d ib[%d]=%d\n",
+-            i,input_buffer[i],i+1,input_buffer[i+1],
+-            i+2,input_buffer[i+2]);
+-      /*  fprintf(stderr,"input_buffer[0]=%d input_buffer[3]=%d\n",
+-       *        input_buffer[0], input_buffer[3]);
+-       */
+-    }
+-    fflush(stderr);
+-  }
++  PrintHex(0, input_buffer, 30);
+ #endif
+   /* first, skip past: mode data header, and block descriptor header if any */
+   sense_page=(ElementModeSensePage_T *)(input_buffer+4+input_buffer[3]);
+@@ -444,11 +442,11 @@
+ #ifdef DEBUG_MODE_SENSE
+   fprintf(stderr,"rawNumStorage= %d %d    rawNumImportExport= %d %d\n",
+-        sense_page->NumStorageHi,sense_page->NumStorageLo,
+-        sense_page->NumImportExportHi, sense_page->NumImportExportLo);
++          sense_page->NumStorageHi,sense_page->NumStorageLo,
++          sense_page->NumImportExportHi, sense_page->NumImportExportLo);
+   fprintf(stderr,"rawNumTransport=%d %d  rawNumDataTransfer=%d %d\n",
+-        sense_page->NumMediumTransportHi,sense_page->NumMediumTransportLo,
+-        sense_page->NumDataTransferHi,sense_page->NumDataTransferLo);
++          sense_page->NumMediumTransportHi,sense_page->NumMediumTransportLo,
++          sense_page->NumDataTransferHi,sense_page->NumDataTransferLo);
+   fflush(stderr);
+ #endif
+@@ -620,19 +618,16 @@
+   CDB[11] = 0;                        /* Control */
+ #ifdef DEBUG_BARCODE
+-  {
+-    int i;
+-    fprintf(stderr,"CDB= ");
+-    for (i=0;i<12;i++) {
+-      fprintf(stderr,"%x ",CDB[i]);
+-    }
+-    fprintf(stderr,"\n");
+-    fflush(stderr);
+-  }
++  fprintf(stderr,"CDB:\n");
++  PrintHex(2, CDB, 12);
+ #endif
+   if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
+                         DataBuffer,NumBytes, RequestSense) != 0){
++
++#ifdef DEBUG
++    fprintf(stderr, "Read Element Status (0x%02X) failed\n", CDB[0]);
++#endif
+     /* okay, first see if we have sense key of 'illegal request',
+        additional sense code of '24', additional sense qualfier of 
+        '0', and field in error of '4'. This means that we issued a request
+@@ -654,15 +649,8 @@
+       CDB[1] &= ~0x10; /* clear bar code flag! */
+ #ifdef DEBUG_BARCODE
+-      {
+-      int i;
+-      fprintf(stderr,"CDB= ");
+-      for (i=0;i<12;i++) {
+-        fprintf(stderr,"%x ",CDB[i]);
+-      }
+-      fprintf(stderr,"\n");
+-      fflush(stderr);
+-      }
++      fprintf(stderr,"CDB:\n");
++      PrintHex(2, CDB, 12);
+ #endif
+       
+       if (SCSI_ExecuteCommand(MediumChangerFD, Input, &CDB, 12,
+@@ -679,14 +667,8 @@
+ #ifdef DEBUG_BARCODE
+   /* print a bunch of extra debug data :-(.  */
+   PrintRequestSense(RequestSense); /* see what it sez :-(. */
+-  {
+-    int i;
+-    fprintf(stderr,"Data:");
+-    for (i=0;i<40;i++) {
+-      fprintf(stderr,"%02x ",DataBuffer[i]);
+-    }
+-    fprintf(stderr,"\n");
+-  }
++  fprintf(stderr,"Data:\n");
++  PrintHex(2, DataBuffer, 40);
+ #endif  
+   return DataBuffer; /* we succeeded! */
+ }
+@@ -703,7 +685,7 @@
+                                       ) {
+   unsigned char *DataBuffer; /* size of data... */
+-  unsigned int real_numbytes;
++  int real_numbytes;
+   
+   DataBuffer=SendElementStatusRequestActual(MediumChangerFD,
+@@ -950,34 +932,42 @@
+               BigEndian16(TransportElementDescriptor
+                           ->SourceStorageElementAddress);
+-            if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
+-              FatalError("Too many Data Transfer Elements Reported\n");
+-            }
+-            if (ElementStatusPage->VolBits & E2_PVOLTAG) {
+-              copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
+-                           ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
+-            } else {
+-              ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
+-            }
+-            if (ElementStatusPage->VolBits & E2_AVOLTAG) {
+-              copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
+-                           ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
+-            } else {
+-              ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
+-            }
+-            ElementStatus->DataTransferElementCount++;
+-            /* 0 actually is a usable element address */
+-            /* if (DataTransferElementAddress == 0) */
+-            /*        FatalError( */
+-            /*  "illegal Data Transfer Element Address %d reported\n", */
+-            /* DataTransferElementAddress); */
+-            break;
+-          default:
+-            FatalError("illegal Element Type Code %d reported\n",
+-                       ElementStatusPage->ElementTypeCode);
+-          }
+-      }
++#if DEBUG
++        fprintf(stderr, "%d: ElementAddress = %d, Full = %d, SourceElement = %d\n", 
++                ElementStatus->DataTransferElementCount,
++                ElementStatus->DataTransferElementAddress[ElementStatus->DataTransferElementCount],
++                ElementStatus->DataTransferElementFull[ElementStatus->DataTransferElementCount],
++                ElementStatus->DataTransferElementSourceStorageElementNumber[ElementStatus->DataTransferElementCount]);
++#endif
++        if (ElementStatus->DataTransferElementCount >= mode_sense->NumDataTransfer) {
++          FatalError("Too many Data Transfer Elements Reported\n");
++        }
++        if (ElementStatusPage->VolBits & E2_PVOLTAG) {
++          copy_barcode(TransportElementDescriptor->PrimaryVolumeTag,
++                       ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount]);
++        } else {
++          ElementStatus->DataTransferPrimaryVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
++        }
++        if (ElementStatusPage->VolBits & E2_AVOLTAG) {
++          copy_barcode(TransportElementDescriptor->AlternateVolumeTag,
++                       ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount]);
++        } else {
++          ElementStatus->DataTransferAlternateVolumeTag[ElementStatus->DataTransferElementCount][0]=0; /* null string */
++        }
++        ElementStatus->DataTransferElementCount++;
++
++        /* 0 actually is a usable element address */
++        /* if (DataTransferElementAddress == 0) */
++        /*    FatalError( */
++        /*  "illegal Data Transfer Element Address %d reported\n", */
++        /* DataTransferElementAddress); */
++        break;
++      default:
++        FatalError("illegal Element Type Code %d reported\n",
++          ElementStatusPage->ElementTypeCode);
++      }
+     }
++  }
+ }
+ /********************* Real ReadElementStatus ********************* */
+@@ -1008,7 +998,6 @@
+   int *EmptyStorageElementAddress; /* [MAX_STORAGE_ELEMENTS]; */
+   
+   int empty_idx=0;
+-  int invalid_sources=0;
+   boolean is_attached = false;
+   int i,j;
+   
+@@ -1049,7 +1038,7 @@
+   
+   EmptyStorageElementAddress=(int *)xzmalloc((mode_sense->NumStorage+1)*sizeof(int));
+   for (i=0;i<mode_sense->NumStorage;i++) {
+-    EmptyStorageElementAddress[i]=-1;
++    EmptyStorageElementAddress[i] = -1;
+   }
+   
+   /* Okay, now to send some requests for the various types of stuff: */
+@@ -1076,6 +1065,9 @@
+ #endif
+     /* darn. Free up stuff and return. */
+     /****FIXME**** do a free on element data! */
++#ifdef DEBUG_MODE_SENSE
++      PrintRequestSense(RequestSense);
++#endif
+     FreeElementData(ElementStatus);
+     return NULL; 
+   } 
+@@ -1107,6 +1099,9 @@
+ #endif
+       /* darn. Free up stuff and return. */
+       /****FIXME**** do a free on element data! */
++#ifdef DEBUG_MODE_SENSE
++      PrintRequestSense(RequestSense);
++#endif
+       FreeElementData(ElementStatus);
+       return NULL; 
+     } 
+@@ -1138,6 +1133,9 @@
+ #endif
+     /* darn. Free up stuff and return. */
+     /****FIXME**** do a free on element data! */
++#ifdef DEBUG_MODE_SENSE
++    PrintRequestSense(RequestSense);
++#endif
+     FreeElementData(ElementStatus);
+     return NULL; 
+   } 
+@@ -1172,6 +1170,9 @@
+ #endif
+        /* darn. Free up stuff and return. */
+        /****FIXME**** do a free on element data! */
++#ifdef DEBUG_MODE_SENSE
++      PrintRequestSense(RequestSense);
++#endif
+        FreeElementData(ElementStatus);
+        return NULL; 
+      } 
+@@ -1223,34 +1224,24 @@
+    * is obviously defective: 
+    */
+   /* pass one: */
+-  invalid_sources=0; /* no invalid sources yet! */
+   for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
+     int elnum;
+-    int translated_elnum = -1;
+     /* if we have an element, then ... */
+     if (ElementStatus->DataTransferElementFull[i]) {
+       elnum=ElementStatus->DataTransferElementSourceStorageElementNumber[i];
+       /* if we have an element number, then ... */
+       if (elnum >= 0) {
+-         /* Now to translate the elnum: */
+-       for (j=0; j<ElementStatus->StorageElementCount; j++) {
+-           if (elnum == ElementStatus->StorageElementAddress[j]) {
+-               translated_elnum=j; 
+-           }
+-       }
+-      /* now see if the element # is already occupied: */
+-      if (ElementStatus->StorageElementFull[translated_elnum]) {
+-        invalid_sources=1;
+-        break; /* break out of the loop! */
+-      } else {
+-         /* properly set the source... */
+-      ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
+-              translated_elnum;
+-      }
+-               
+-      } else {
+-      /* if element # was not >=0, then we had an invalid source anyhow! */
+-      invalid_sources=1;
++        /* Now to translate the elnum: */
++        ElementStatus->DataTransferElementSourceStorageElementNumber[i] = -1;
++        for (j=0; j<ElementStatus->StorageElementCount; j++) {
++          if (elnum == ElementStatus->StorageElementAddress[j]) {
++            /* now see if the element # is already occupied:*/
++            if (!ElementStatus->StorageElementFull[j]) {
++              /* properly set the source... */
++              ElementStatus->DataTransferElementSourceStorageElementNumber[i]= j;
++            }
++          }
++        }
+       }
+     }
+   }
+@@ -1267,21 +1258,19 @@
+    * by the user interface. This is an invalid value, but more useful for us
+    * to have than just crapping out here :-(. 
+    */ 
+-  if (invalid_sources) {
+-    empty_idx=0;
+-    for (i=0;i<ElementStatus->DataTransferElementCount;i++) {
+-      if (ElementStatus->DataTransferElementFull[i]) {
++  empty_idx=0;
++  for (i = 0; i < ElementStatus->DataTransferElementCount; i++) {
++    if (ElementStatus->DataTransferElementFull[i] && 
++      ElementStatus->DataTransferElementSourceStorageElementNumber[i] < 0) {
+ #ifdef DEBUG_TAPELIST
+-        fprintf(stderr,"for drive %d, changing source %d to %d (empty slot #%d)\n",
+-           i,
+-           ElementStatus->DataTransferElementSourceStorageElementNumber[i],
+-             EmptyStorageElementAddress[empty_idx],
+-             empty_idx);
++      fprintf(stderr,"for drive %d, changing to %d (empty slot #%d)\n",
++              i,
++              EmptyStorageElementAddress[empty_idx],
++              empty_idx);
+ #endif
+               
+       ElementStatus->DataTransferElementSourceStorageElementNumber[i]=
+         EmptyStorageElementAddress[empty_idx++];
+-      }
+     }
+   }
+@@ -1337,9 +1326,9 @@
+   CDB[2] = (ElementStatus->TransportElementAddress >> 8) & 0xFF;  /* Transport Element Address MSB */
+   CDB[3] = (ElementStatus->TransportElementAddress) & 0xff;   /* Transport Element Address LSB */
+   CDB[4] = (SourceAddress >> 8) & 0xFF;       /* Source Address MSB */
+-  CDB[5] = SourceAddress & 0xFF; /* Source Address MSB */
++  CDB[5] = SourceAddress & 0xFF; /* Source Address LSB */
+   CDB[6] = (DestinationAddress >> 8) & 0xFF; /* Destination Address MSB */
+-  CDB[7] = DestinationAddress & 0xFF; /* Destination Address MSB */
++  CDB[7] = DestinationAddress & 0xFF; /* Destination Address LSB */
+   CDB[8] = 0;                 /* Reserved */
+   CDB[9] = 0;                 /* Reserved */
+   if (flags->invert) {
+@@ -1351,7 +1340,11 @@
+   CDB[11] = 0 | (flags->eepos <<6);                   /* Control */
+   
+   if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 12,
+-                        NULL, 0, RequestSense) != 0) {
++                          NULL, 0, RequestSense) != 0) {
++
++#ifdef DEBUG
++    fprintf(stderr, "Move Medium (0x%02X) failed\n", CDB[0]);
++#endif
+     return RequestSense;
+   }
+   free(RequestSense);
+@@ -1372,9 +1365,9 @@
+   CDB[2] = (ElementStatus->TransportElementAddress >> 8) & 0xFF;  /* Transport Element Address MSB */
+   CDB[3] = (ElementStatus->TransportElementAddress) & 0xff;   /* Transport Element Address LSB */
+   CDB[4] = (SourceAddress >> 8) & 0xFF;       /* Source Address MSB */
+-  CDB[5] = SourceAddress & 0xFF; /* Source Address MSB */
++  CDB[5] = SourceAddress & 0xFF; /* Source Address LSB */
+   CDB[6] = (DestinationAddress >> 8) & 0xFF; /* Destination Address MSB */
+-  CDB[7] = DestinationAddress & 0xFF; /* Destination Address MSB */
++  CDB[7] = DestinationAddress & 0xFF; /* Destination Address LSB */
+   CDB[8] = (Dest2Address>>8) & 0xFF; /* move destination back to source? */
+   CDB[9] = Dest2Address & 0xFF; /* move destination back to source? */
+   CDB[10]=0;
+@@ -1418,12 +1411,53 @@
+   if (SCSI_ExecuteCommand(MediumChangerFD, Output, &CDB, 6,
+                         NULL, 0, RequestSense) != 0) {
++#ifdef DEBUG
++    fprintf(stderr, "Erase (0x19) failed\n");
++#endif
+     return RequestSense;
+   }
+   free(RequestSense);
+   return NULL;  /* Success! */
+ }  
++static char Spaces[] = "                                                            ";
++
++void PrintHex(int Indent, unsigned char *Buffer, int Length)
++{
++  int idxBuffer;
++  int idxAscii;
++  int PadLength;
++  char        cAscii;
++
++  for (idxBuffer = 0; idxBuffer < Length; idxBuffer++) {
++    if ((idxBuffer % 16) == 0) {
++      if (idxBuffer > 0) {
++        fputc('\'', stderr);
++
++        for (idxAscii = idxBuffer - 16; idxAscii < idxBuffer; idxAscii++) {
++          cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x7F ? Buffer[idxAscii] : '.';
++          fputc(cAscii, stderr);
++        }
++        fputs("'\n", stderr);
++      }
++      fprintf(stderr, "%.*s%04X: ", Indent, Spaces, idxBuffer);
++    }
++    fprintf(stderr, "%02X ", (unsigned char)Buffer[idxBuffer]);
++  }
++
++  PadLength = 16 - (Length % 16);
++
++  if (PadLength > 0) {
++    fprintf(stderr, "%.*s'", 3 * PadLength, Spaces);
++
++    for (idxAscii = idxBuffer - (16 - PadLength); idxAscii < idxBuffer; idxAscii++) {
++      cAscii = Buffer[idxAscii] >= 0x20 && Buffer[idxAscii] < 0x80 ? Buffer[idxAscii] : '.';
++      fputc(cAscii, stderr);
++    }
++    fputs("'\n", stderr);
++  }
++  fflush(stderr);
++}
+ #ifdef LONG_PRINT_REQUEST_SENSE
+@@ -1488,12 +1522,9 @@
+ #else
+ void PrintRequestSense(RequestSense_T *RequestSense)
+ {
+-  int i;
+-  fprintf(stderr, "mtx: Request Sense: %02X",
+-        ((unsigned char *) RequestSense)[0]);
+-  for (i = 1; i < sizeof(RequestSense_T); i++)
+-    fprintf(stderr, " %02X", ((unsigned char *) RequestSense)[i]);
+-  fprintf(stderr, "\n");
++  fprintf(stderr, "mtx: Request Sense: %02X\n",
++          ((unsigned char *) RequestSense)[0]);
++  PrintHex(2, (char *)RequestSense, sizeof(RequestSense_T));
+ }
+ #endif
+Index: Makefile
+===================================================================
+--- ../release/mtx-1.3.9/Makefile.in   2006-02-20 13:42:10.000000000 -0800
++++ Makefile   2006-07-30 01:22:00.000000000 -0700
+@@ -11,26 +11,28 @@
+ # Version # for 'make dist'...
+ VERSION=1.3.9
+-BINS = mtx tapeinfo loaderinfo scsitape nsmhack
++BINS = mtx.exe tapeinfo.exe loaderinfo.exe scsitape.exe nsmhack.exe
++DBGS := $(BINS:%.exe=%.dbg)
+-TARGET        = @TARGET@
+-CPU   = @CPU@
+-CC    = @CC@
+-INSTALL       = @INSTALL@
+-
+-CFLAGS                = @CFLAGS@
+-CPPFLAGS      = @CPPFLAGS@ -DVERSION="\"$(VERSION)\""
+-LDFLAGS               = @LDFLAGS@
+-LIBS          = @LIBS@
++TARGET        = mingw
++CPU   = 386
++CC    = mingw32-gcc
++INSTALL       = install -c
++
++CFLAGS                = -g -O2
++CPPFLAGS      =  -DVERSION="\"$(VERSION)\""
++LDFLAGS               = 
++LIBS          = 
++USE_OBJCOPY   = yes
+ INSTALL_DOC = $(INSTALL) -m 644
+ INSTALL_BIN = $(INSTALL) -m 755
+ INSTALL_DIR = $(INSTALL) -m 755 -d
+-prefix                = @prefix@
+-exec_prefix   = @exec_prefix@
+-sbindir               = @sbindir@
+-mandir                = @mandir@
++prefix                = dummy
++exec_prefix   = ${prefix}
++sbindir       = ${exec_prefix}/bin
++mandir                = ${prefix}/man
+ #
+ # Linux on x86...
+@@ -40,6 +42,11 @@
+ CPPFLAGS      += -I/usr/src/linux/include -DLONG_PRINT_REQUEST_SENSE=1
+ endif
++ifeq ($(TARGET),mingw)
++CFLAGS += -Wall
++CPPFLAGS      += -DLONG_PRINT_REQUEST_SENSE=1
++endif
++
+ #
+ # FreeBSD on x86...
+ #
+@@ -82,12 +89,22 @@
+ See vms/000readme for information.
+ endif
++%.dbg : %.exe
++ifeq ($(USE_OBJCOPY),yes)
++      mingw32-objcopy --only-keep-debug $< $@
++      mingw32-objcopy --strip-debug $<
++      mingw32-objcopy --add-gnu-debuglink=$@ $<
++else
++      strip $< -o $@
++endif
++
+ all:  $(BINS)
+-install: $(BINS)
++dbgs: $(DBGS)
++
++install: $(BINS) $(DBGS)
+       $(INSTALL_DIR) $(sbindir)
+       for file in $(BINS); do \
+-      strip "$$file" ;        \
+       $(INSTALL_BIN) "$$file" $(sbindir) ; \
+       done    
+       $(INSTALL_DIR) $(mandir) $(mandir)/man1
+@@ -98,7 +115,9 @@
+ clean:
+       rm -f *.o *~
+       rm -f $(BINS)
+-      rm -f mam2debug mam2debug2
++      rm -f $(DBGS)
++      rm -f mam2debug.exe mam2debug2.exe
++      rm -rf autom4te.cache
+ distclean: clean
+       rm -f Makefile config.log config.cache config.status
+@@ -106,27 +125,26 @@
+ dist: distclean
+       ./makedist $(VERSION)   
+-loaderinfo: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
+-      $(CC) $(LDFLAGS) -o loaderinfo loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
+-
++loaderinfo.exe: loaderinfo.o mtxl.o mtxl.h mtx.h $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ loaderinfo.o mtxl.o $(EXTRA) $(LIBS)
+-nsmhack: nsmhack.o mtxl.o $(EXTRA)
+-      $(CC) $(LDFLAGS) -o nsmhack nsmhack.o mtxl.o $(EXTRA) $(LIBS)
++nsmhack.exe: nsmhack.o mtxl.o $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ nsmhack.o mtxl.o $(EXTRA) $(LIBS)
+-mtx: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
+-      $(CC) $(LDFLAGS) -o mtx mtx.o mtxl.o $(EXTRA) $(LIBS)
++mtx.exe: mtx.o mtxl.o mtxl.h mtx.h $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ mtx.o mtxl.o $(EXTRA) $(LIBS)
+-mam2debug: mtxl.o mam2debug.o mtx.h $(EXTRA)  
+-      $(CC) $(LDFLAGS) -o mam2debug mtxl.o mam2debug.o $(EXTRA) $(LIBS)
++mam2debug.exe: mtxl.o mam2debug.o mtx.h $(EXTRA)      
++      $(CC) $(LDFLAGS) -o $@ mtxl.o mam2debug.o $(EXTRA) $(LIBS)
+-tapeinfo: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
+-      $(CC) $(LDFLAGS) -o tapeinfo tapeinfo.o mtxl.o $(EXTRA) $(LIBS)
++tapeinfo.exe: tapeinfo.o mtxl.o mtx.h mtxl.h $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ tapeinfo.o mtxl.o $(EXTRA) $(LIBS)
+-mam2debug2: mtxl.o mam2debug2.o mtx.h $(EXTRA)
+-      $(CC) $(LDFLAGS) -o mam2debug2 mtxl.o mam2debug2.o $(EXTRA) $(LIBS)
++mam2debug2.exe: mtxl.o mam2debug2.o mtx.h $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ mtxl.o mam2debug2.o $(EXTRA) $(LIBS)
+-scsitape: scsitape.o mtxl.o mtxl.h mtx.h $(EXTRA)
+-      $(CC) $(LDFLAGS) -o scsitape scsitape.o mtxl.o $(EXTRA) $(LIBS)
++scsitape.exe: scsitape.o mtxl.o mtxl.h mtx.h $(EXTRA)
++      $(CC) $(LDFLAGS) -o $@ scsitape.o mtxl.o $(EXTRA) $(LIBS)
+ scsitape.o: scsitape.c mtx.h mtxl.h
+@@ -140,6 +158,6 @@
+ mtx.o: mtx.c mtx.h mtxl.h
+-mtxl.o: mtxl.c mtx.h mtxl.h scsi_linux.c 
++mtxl.o: mtxl.c mtx.h mtxl.h scsi_linux.c scsi_win32.c
+ nsmhack.o: nsmhack.c mtxl.h mtx.h