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
