From be75f39fb105a6a685d2a682cd16cb12fb29efcd Mon Sep 17 00:00:00 2001
From: Ann Priestman <apriestman@basistech.com>
Date: Mon, 6 Feb 2017 09:41:38 -0500
Subject: [PATCH] Add image writer path to makeAddImageProcess Cleanup

---
 bindings/java/jni/dataModel_SleuthkitJNI.cpp  |  34 -
 bindings/java/jni/dataModel_SleuthkitJNI.h    |   8 -
 .../sleuthkit/datamodel/Examples/Sample.java  |   2 +-
 .../sleuthkit/datamodel/SleuthkitCase.java    |   6 +-
 .../org/sleuthkit/datamodel/SleuthkitJNI.java |  21 +-
 .../org/sleuthkit/datamodel/BottomUpTest.java |   2 +-
 .../datamodel/DataModelTestSuite.java         |   2 +-
 tsk/auto/auto.cpp                             |   3 -
 tsk/img/img_writer.cpp                        | 817 +++++++++---------
 tsk/img/img_writer.h                          |   5 +-
 tsk/img/raw.c                                 |   7 +-
 tsk/img/vhd.c                                 |   3 +
 12 files changed, 421 insertions(+), 489 deletions(-)

diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
index 806ec806a..c8c556b80 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
@@ -1184,9 +1184,6 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_runAddImgNat(JNIEnv * env,
 	}
 	else {
 		tskAuto->disableImageWriter();
-		setThrowTskCoreError(env,
-			"runAddImgNat: Disabling image writer.");
-		return;
 	}
 
 	// Add the data source.
@@ -2162,34 +2159,3 @@ JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_isImageSupp
 
     return (jboolean) result;
 }
-
-/*
- * Enable image writing during ingest
- * @param env pointer to java environment this was called from
- * @param obj the java object this was called from
- * @param directoryJ directory to store the image in
- * @param baseNameJ base name for the new image
- * @return 0 if successful, -1 otherwise
- */
-JNIEXPORT jint JNICALL
-Java_org_sleuthkit_datamodel_SleuthkitJNI_enableImageWriterNat (JNIEnv * env, jclass obj,
-	jlong a_img_info, jstring directoryJ, jstring baseNameJ) {
-
-	TSK_IMG_INFO *img_info = castImgInfo(env, a_img_info);
-	if (img_info == 0) {
-		//exception already set
-		return -1;
-	}
-
-	TSK_TCHAR directoryT[1024];
-	toTCHAR(env, directoryT, 1024, directoryJ);
-
-	TSK_TCHAR baseNameT[1024];
-	toTCHAR(env, baseNameT, 1024, baseNameJ);
-
-	if (TSK_ERR == tsk_img_writer_create_from_dir(img_info, directoryT, baseNameT)) {
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h
index 0f1a0094f..74b4c7808 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.h
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.h
@@ -407,14 +407,6 @@ JNIEXPORT jstring JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_getCurDirNat
 JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_isImageSupportedNat
   (JNIEnv *, jclass, jstring);
 
-/*
- * Class:     org_sleuthkit_datamodel_SleuthkitJNI
- * Method:    enableImageWriterNat
- * Signature: (JLjava/lang/String;Ljava/lang/String;)I
- */
-JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_enableImageWriterNat
-  (JNIEnv *, jclass, jlong, jstring, jstring);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Examples/Sample.java b/bindings/java/src/org/sleuthkit/datamodel/Examples/Sample.java
index 6fc7b8224..3f6620ae5 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/Examples/Sample.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/Examples/Sample.java
@@ -43,7 +43,7 @@ public static void run(String imagePath) {
 
 			// initialize the case with an image
 			String timezone = "";
-			AddImageProcess process = sk.makeAddImageProcess(timezone, true, false);
+			AddImageProcess process = sk.makeAddImageProcess(timezone, true, false, "");
 			ArrayList<String> paths = new ArrayList<String>();
 			paths.add(imagePath);
 			try {
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 40c2536d4..ffb0642a9 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -1223,12 +1223,14 @@ public static SleuthkitCase newCase(String databaseName, CaseDbConnectionInfo in
 	 *                        unallocated space in the image.
 	 * @param noFatFsOrphans  Set to true to skip processing orphan files of FAT
 	 *                        file systems.
+     * @param imageWriterPath  Path that a copy of the image should be written to.
+     *                         Use empty string to disable image writing
 	 *
 	 * @return Object that encapsulates control of adding an image via the
 	 *         SleuthKit native code layer.
 	 */
-	public AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) {
-		return this.caseHandle.initAddImageProcess(timezone, addUnallocSpace, noFatFsOrphans);
+	public AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageWriterPath) {
+		return this.caseHandle.initAddImageProcess(timezone, addUnallocSpace, noFatFsOrphans, imageWriterPath);
 	}
 
 	/**
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
index 5961cdbdb..a546ca927 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java
@@ -168,12 +168,15 @@ long addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone
 		 *                         unallocated space.
 		 * @param skipFatFsOrphans Pass true to skip processing of orphan files
 		 *                         for FAT file systems.
+		 * @param imageWriterPath  Path that a copy of the image should be written to.
+		 *                         Use empty string to disable image writing
 		 *
 		 * @return An object that can be used to exercise fine-grained control
 		 *         of the process of adding the image to the case database.
 		 */
-		AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans) {
-			return new AddImageProcess(timeZone, addUnallocSpace, skipFatFsOrphans);
+		//AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans) {
+		AddImageProcess initAddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageWriterPath) {
+			return new AddImageProcess(timeZone, addUnallocSpace, skipFatFsOrphans, imageWriterPath);
 		}
 
 		/**
@@ -185,6 +188,7 @@ public class AddImageProcess {
 			private final String timeZone;
 			private final boolean addUnallocSpace;
 			private final boolean skipFatFsOrphans;
+			private final String imageWriterPath;
 			private volatile long tskAutoDbPointer;
 
 			/**
@@ -196,11 +200,14 @@ public class AddImageProcess {
 			 *                         unallocated space.
 			 * @param skipFatFsOrphans Pass true to skip processing of orphan
 			 *                         files for FAT file systems.
+			 * @param imageWriterPath  Path that a copy of the image should be written to.
+			 *                         Use empty string to disable image writing
 			 */
-			private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans) {
+			private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFatFsOrphans, String imageWriterPath) {
 				this.timeZone = timeZone;
 				this.addUnallocSpace = addUnallocSpace;
 				this.skipFatFsOrphans = skipFatFsOrphans;
+				this.imageWriterPath = imageWriterPath;
 				tskAutoDbPointer = 0;
 			}
 
@@ -236,7 +243,7 @@ public void run(String deviceId, String[] imageFilePaths) throws TskCoreExceptio
 				}
 
 				//runAddImgNat(tskAutoDbPointer, deviceId, imageFilePaths, imageFilePaths.length, timeZone);
-				runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, "C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\autopsyVHD3.vhd");
+				runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath);
 			}
 
 			/**
@@ -988,10 +995,6 @@ public static long findDeviceSize(String devPath) throws TskCoreException {
 	public static boolean isImageSupported(String imagePath){
 		return isImageSupportedNat(imagePath);
 	}
-	
-	public static int enableImageWriter(long imgHandle, String directory, String baseName){
-		return enableImageWriterNat(imgHandle, directory, baseName);
-	}
 
 	private static native String getVersionNat();
 
@@ -1092,7 +1095,5 @@ public static int enableImageWriter(long imgHandle, String directory, String bas
 	private static native String getCurDirNat(long process);
 	
 	private static native boolean isImageSupportedNat(String imagePath);
-	
-	private static native int enableImageWriterNat(long imgHandle, String directory, String baseName);
 
 }
diff --git a/bindings/java/test/org/sleuthkit/datamodel/BottomUpTest.java b/bindings/java/test/org/sleuthkit/datamodel/BottomUpTest.java
index 349e22236..96684cb85 100644
--- a/bindings/java/test/org/sleuthkit/datamodel/BottomUpTest.java
+++ b/bindings/java/test/org/sleuthkit/datamodel/BottomUpTest.java
@@ -80,7 +80,7 @@ public void testBottomUpDiff() {
 			SleuthkitCase sk = SleuthkitCase.newCase(dbPath);
 			String timezone = "";
 			title = title + DataModelTestSuite.BTTMUP + ".txt";
-			SleuthkitJNI.CaseDbHandle.AddImageProcess process = sk.makeAddImageProcess(timezone, true, false);
+			SleuthkitJNI.CaseDbHandle.AddImageProcess process = sk.makeAddImageProcess(timezone, true, false, "");
 			try {
 				process.run(imagePaths.toArray(new String[imagePaths.size()]));
 			} catch (TskDataException ex) {
diff --git a/bindings/java/test/org/sleuthkit/datamodel/DataModelTestSuite.java b/bindings/java/test/org/sleuthkit/datamodel/DataModelTestSuite.java
index 7bb4a3981..66d00e391 100644
--- a/bindings/java/test/org/sleuthkit/datamodel/DataModelTestSuite.java
+++ b/bindings/java/test/org/sleuthkit/datamodel/DataModelTestSuite.java
@@ -115,7 +115,7 @@ public static void createOutput(String outputPath, String tempDirPath, List<Stri
 			SleuthkitCase sk = SleuthkitCase.newCase(dbPath);
 
 			String timezone = "";
-			SleuthkitJNI.CaseDbHandle.AddImageProcess process = sk.makeAddImageProcess(timezone, true, false);
+			SleuthkitJNI.CaseDbHandle.AddImageProcess process = sk.makeAddImageProcess(timezone, true, false, "");
 			try {
 				process.run(imagePaths.toArray(new String[imagePaths.size()]));
 			} catch (TskDataException ex) {
diff --git a/tsk/auto/auto.cpp b/tsk/auto/auto.cpp
index 95e298fd2..0a57a040e 100644
--- a/tsk/auto/auto.cpp
+++ b/tsk/auto/auto.cpp
@@ -81,10 +81,7 @@ uint8_t
         closeImage();
 
     m_internalOpen = true;
-	enableImageWriter("C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\newTest.vhd");
     m_img_info = tsk_img_open(a_numImg, a_images, a_imgType, a_sSize);
-	tsk_img_writer_create(m_img_info, m_imageWriterPath);
-	//tsk_img_writer_create_from_dir(m_img_info, L"C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput", a_images[0]);
     if (m_img_info)
         return 0;
     else
diff --git a/tsk/img/img_writer.cpp b/tsk/img/img_writer.cpp
index 85b268258..decc00a53 100644
--- a/tsk/img/img_writer.cpp
+++ b/tsk/img/img_writer.cpp
@@ -24,378 +24,371 @@
 #include <winioctl.h>
 #endif
 
-/* This is a little lower than the actual maximum size for the VHD */
-#define VHD_MAX_IMAGE_SIZE 2000000000000
-#define VHD_DEFAULT_BLOCK_SIZE 0x200000
+#define VHD_MAX_IMAGE_SIZE 2000000000000 /* VHD_MAX_IMAGE_SIZE is a little lower than the actual maximum size for the VHD */
+#define VHD_DEFAULT_BLOCK_SIZE 0x200000  /* This needs to be 0x200000 to load the VHD in Windows */
 #define VHD_SECTOR_SIZE 0x200
 #define VHD_FOOTER_LENGTH 0x200
 #define VHD_DISK_HEADER_LENGTH 0x400
 
 TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer);
 
-// TEMP LOGGING
+// TEMP LOGGING TEMP
 char messageBuffer[0x2000];
 char logBuffer[0x2000];
 void openLogFile(TSK_IMG_WRITER * writer);
 void writeLogFile(TSK_IMG_WRITER * writer, const char * message) {
-	if (writer->logFileHandle == 0) {
-		// Open it back up
-		openLogFile(writer);
-	}
-	time_t ltime; /* calendar time */
-	ltime = time(NULL); /* get current cal time */
-	sprintf(logBuffer, "%s : ", asctime(localtime(&ltime)));
-	strcat(logBuffer, message);
-
-	DWORD bytesWritten;
-	if (FALSE == WriteFile(writer->logFileHandle, logBuffer,
-		strlen(logBuffer), &bytesWritten, NULL)) {
-		int lastError = GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-		tsk_error_set_errstr("writeLogFile: error writing log",
-			lastError);
-	}
+    if (writer->logFileHandle == 0) {
+        // Open it back up
+        openLogFile(writer);
+    }
+    time_t ltime; /* calendar time */
+    ltime = time(NULL); /* get current cal time */
+    sprintf(logBuffer, "%s : ", asctime(localtime(&ltime)));
+    strcat(logBuffer, message);
+
+    DWORD bytesWritten;
+    if (FALSE == WriteFile(writer->logFileHandle, logBuffer,
+        strlen(logBuffer), &bytesWritten, NULL)) {
+        int lastError = GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+        tsk_error_set_errstr("writeLogFile: error writing log",
+            lastError);
+    }
 }
 
 void openLogFile(TSK_IMG_WRITER * writer) {
-	writer->logFileHandle = CreateFile(L"C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\tskLog.txt", FILE_APPEND_DATA,
-		FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0,
-		NULL);
-	if (writer->logFileHandle == INVALID_HANDLE_VALUE) {
-		tsk_fprintf(stderr, "Error opening VHD!!!"); // temp
-		fflush(stderr);
-		int lastError = (int)GetLastError();
-		writer->outputFileHandle = 0; /* so we don't close it next time */
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_OPEN);
-		tsk_error_set_errstr("openLogFile: file  %d", lastError);
-	}
-	writeLogFile(writer, "Opened log file\n");
+    writer->logFileHandle = CreateFile(L"C:\\cygwin\\home\\apriestman\\Work\\autopsy\\vhdTesting\\tskOutput\\tskLog.txt", FILE_APPEND_DATA,
+        FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0,
+        NULL);
+    if (writer->logFileHandle == INVALID_HANDLE_VALUE) {
+        tsk_fprintf(stderr, "Error opening VHD!!!"); // temp
+        fflush(stderr);
+        int lastError = (int)GetLastError();
+        writer->outputFileHandle = 0; /* so we don't close it next time */
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_OPEN);
+        tsk_error_set_errstr("openLogFile: file  %d", lastError);
+    }
+    writeLogFile(writer, "Opened log file\n");
 
 }
+// END TEMP LOGGING
 
 
+/*
+ * Considering the buffer to be an array of bits, get the entry at
+ * the given index.
+ */
+static bool getBit(unsigned char * buffer, TSK_OFF_T index) {
+    unsigned char b = buffer[index / 8];
+    return (b >> (7 - (index % 8)) & 0x01) == 1;
+}
 
-
-bool getBit(unsigned char * buffer, TSK_OFF_T index) {
-	unsigned char b = buffer[index / 8];
-	return (b >> (7 - (index % 8)) & 0x01) == 1;
+/*
+ * Considering the buffer to be an array of bits, set the entry at
+ * the given index.
+ */
+static void setBit(unsigned char * buffer, TSK_OFF_T index, bool val) {
+    unsigned char b = buffer[index / 8];
+    unsigned char mask = 0xff ^ (1 << (7 - (index % 8)));
+    b = (b & mask) | (val << (7 - (index % 8)));
+    buffer[index / 8] = b;
 }
 
-void setBit(unsigned char * buffer, TSK_OFF_T index, bool val) {
-	if (tsk_verbose) {
-		//tsk_fprintf(stderr, "setBit: Setting bit 0x%x to %d\n", index, val);
-		//fflush(stderr);
-	}
-	unsigned char b = buffer[index / 8];
-	unsigned char mask = 0xff ^ (1 << (7 - (index % 8)));
-	b = (b & mask) | (val << (7 - (index % 8)));
-	buffer[index / 8] = b;
+/*
+ * Move the file pointer to the given offset (relative the beginning of the file)
+ */
+static TSK_RETVAL_ENUM seekToOffset(TSK_IMG_WRITER * writer, TSK_OFF_T offset) {
+    LARGE_INTEGER li;
+    li.QuadPart = offset;
+
+    li.LowPart = SetFilePointer(writer->outputFileHandle, li.LowPart,
+        &li.HighPart, FILE_BEGIN);
+
+    if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
+        (GetLastError() != NO_ERROR)) {
+        int lastError = (int)GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_SEEK);
+        tsk_error_set_errstr("img_writer::seekToOffset: offset %" PRIuOFF " seek - %d",
+            offset,
+            lastError);
+        return TSK_ERR;
+    }
+    return TSK_OK;
 }
 
-TSK_RETVAL_ENUM seekToOffset(TSK_IMG_WRITER * writer, TSK_OFF_T offset) {
-	LARGE_INTEGER li;
-	li.QuadPart = offset;
-
-	li.LowPart = SetFilePointer(writer->outputFileHandle, li.LowPart,
-		&li.HighPart, FILE_BEGIN);
-
-	if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
-		(GetLastError() != NO_ERROR)) {
-		int lastError = (int)GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_SEEK);
-		tsk_error_set_errstr("img_writer::seekToOffset: offset %" PRIuOFF " seek - %d",
-			offset,
-			lastError);
-		return TSK_ERR;
-	}
-	return TSK_OK;
+/*
+ * Move the file pointer from the current location
+ */
+static TSK_RETVAL_ENUM seekAhead(TSK_IMG_WRITER * writer, TSK_OFF_T dist) {
+    LARGE_INTEGER li;
+    li.QuadPart = dist;
+
+    li.LowPart = SetFilePointer(writer->outputFileHandle, li.LowPart,
+        &li.HighPart, FILE_CURRENT);
+
+    if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
+        (GetLastError() != NO_ERROR)) {
+        int lastError = (int)GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_SEEK);
+        tsk_error_set_errstr("img_writer::seekAhead: offset %" PRIuOFF " seek - %d",
+            dist,
+            lastError);
+        return TSK_ERR;
+    }
+    return TSK_OK;
 }
 
-TSK_RETVAL_ENUM seekAhead(TSK_IMG_WRITER * writer, TSK_OFF_T dist) {
-	LARGE_INTEGER li;
-	li.QuadPart = dist;
-
-	li.LowPart = SetFilePointer(writer->outputFileHandle, li.LowPart,
-		&li.HighPart, FILE_CURRENT);
-
-	if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
-		(GetLastError() != NO_ERROR)) {
-		int lastError = (int)GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_SEEK);
-		tsk_error_set_errstr("img_writer::seekAhead: offset %" PRIuOFF " seek - %d",
-			dist,
-			lastError);
-		return TSK_ERR;
-	}
-	return TSK_OK;
+/*
+ * Use the sector bitmap to determine whether we're done writing data to a given block 
+ */
+static void checkIfBlockIsFinished(TSK_IMG_WRITER* writer, TSK_OFF_T blockNum) {
+
+    /* The final block may not contain the full number of sectors */
+    unsigned int nSectors;
+    if ((blockNum == writer->totalBlocks - 1) && (writer->imageSize % writer->blockSize != 0)) {
+        nSectors = (writer->imageSize % writer->blockSize) / VHD_SECTOR_SIZE;
+    }
+    else {
+        nSectors = writer->sectorsPerBlock;
+    }
+
+    unsigned char * sectBitmap = writer->blockToSectorBitmap[blockNum];
+    for (unsigned int i = 0; i < nSectors; i++) {
+        if (false == getBit(sectBitmap, i)) {
+            /* At least one sector has not been written */
+            return;
+        }
+    }
+
+    /* Mark the block as finished and free the memory for its sector bitmap */
+    writer->blockStatus[blockNum] = IMG_WRITER_BLOCK_STATUS_FINISHED;
+    if (writer->blockToSectorBitmap[blockNum] != NULL) {
+        free(writer->blockToSectorBitmap[blockNum]);
+        writer->blockToSectorBitmap[blockNum] = NULL;
+    }
 }
 
-void checkIfBlockIsFinished(TSK_IMG_WRITER* writer, TSK_OFF_T blockNum) {
+/*
+ * Add a buffer of data to a previously started block in the VHD 
+ */
+static TSK_RETVAL_ENUM addToExistingBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer,
+    size_t len, TSK_OFF_T blockNum) {
+
+    if (tsk_verbose) {
+        tsk_fprintf(stderr, "addToExistingBlock: Adding data to existing block 0x%x\n", blockNum);
+        fflush(stderr);
+    }
 
-	/* This may not ever mark the last block as finished - need to work on that */
+    /* Seek to where this buffer should start in the image */
+    if (TSK_OK != seekToOffset(writer, VHD_SECTOR_SIZE * TSK_OFF_T(writer->blockToSectorNumber[blockNum]) + writer->sectorBitmapLength +
+            (addr % writer->blockSize))) {
+        return TSK_ERR;
+    }
 
-	unsigned char * sectBitmap = writer->blockToSectorBitmap[blockNum];
-	for (int i = 0; i < writer->sectorsPerBlock; i++) {
-		if (false == getBit(sectBitmap, i)) {
-			/* At least one sector has not been written */
-			return;
-		}
-	}
+    /* Copy each sector that isn't already there */
+    for (size_t inputOffset = 0; inputOffset < len; inputOffset += VHD_SECTOR_SIZE) {
+        uint32_t currentSector = uint32_t((addr % writer->blockSize + inputOffset) / VHD_SECTOR_SIZE);
 
-	/* Mark the block as finished and free the memory for its sector bitmap */
-	writer->blockStatus[blockNum] = IMG_WRITER_BLOCK_STATUS_FINISHED;
-	if (writer->blockToSectorBitmap[blockNum] != NULL) {
-		free(writer->blockToSectorBitmap[blockNum]);
-	}
+        if (getBit(writer->blockToSectorBitmap[blockNum], currentSector)) {
+            if (TSK_OK != seekAhead(writer, VHD_SECTOR_SIZE)) {
+                return TSK_ERR;
+            }
+        }
+        else {
+            
+            DWORD bytesWritten;
+            if (FALSE == WriteFile(writer->outputFileHandle, &(buffer[inputOffset]), VHD_SECTOR_SIZE, 
+                    &bytesWritten, NULL)) {
+                int lastError = GetLastError();
+                tsk_error_reset();
+                tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+                tsk_error_set_errstr("addToExistingBlock: error writing sector",
+                    lastError);
+                return TSK_ERR;
+            }
+            setBit(writer->blockToSectorBitmap[blockNum], currentSector, true);
+        }
+    }
 
-}
+    /* Update the sector bitmap */
+    if (TSK_OK != seekToOffset(writer, VHD_SECTOR_SIZE * TSK_OFF_T(writer->blockToSectorNumber[blockNum]))) {
+        return TSK_ERR;
+    }
+    
+    DWORD bytesWritten;
+    if (FALSE == WriteFile(writer->outputFileHandle, writer->blockToSectorBitmap[blockNum], 
+            writer->sectorBitmapArrayLength, &bytesWritten, NULL)) {
+        int lastError = GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+        tsk_error_set_errstr("addToExistingBlock: error writing sector",
+            lastError);
+        return TSK_ERR;
+    }
 
-TSK_RETVAL_ENUM addToExistingBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer,
-	size_t len, TSK_OFF_T blockNum) {
-
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "addToExistingBlock: Adding data to existing block 0x%x\n", blockNum);
-		fflush(stderr);
-	}
-
-	/* Seek to where this buffer should start in the image */
-	if (TSK_OK != seekToOffset(writer, writer->blockToOffset[blockNum] + writer->sectorBitmapLength +
-			(addr % writer->blockSize))) {
-		return TSK_ERR;
-	}
-
-	/* Copy each sector that isn't already there */
-	for (TSK_OFF_T inputOffset = 0; inputOffset < len; inputOffset += VHD_SECTOR_SIZE) {
-		uint32_t currentSector = (addr % writer->blockSize + inputOffset) / VHD_SECTOR_SIZE;
-
-		if (getBit(writer->blockToSectorBitmap[blockNum], currentSector)) {
-			if (TSK_OK != seekAhead(writer, VHD_SECTOR_SIZE)) {
-				return TSK_ERR;
-			}
-		}
-		else {
-			
-			DWORD bytesWritten;
-			if (FALSE == WriteFile(writer->outputFileHandle, &(buffer[inputOffset]), VHD_SECTOR_SIZE, 
-					&bytesWritten, NULL)) {
-				int lastError = GetLastError();
-				tsk_error_reset();
-				tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-				tsk_error_set_errstr("addToExistingBlock: error writing sector",
-					lastError);
-				return TSK_ERR;
-			}
-			setBit(writer->blockToSectorBitmap[blockNum], currentSector, true);
-		}
-	}
-
-	/* Update the sector bitmap */
-	if (TSK_OK != seekToOffset(writer, writer->blockToOffset[blockNum])) {
-		return TSK_ERR;
-	}
-	
-	DWORD bytesWritten;
-	if (FALSE == WriteFile(writer->outputFileHandle, writer->blockToSectorBitmap[blockNum], 
-			writer->sectorBitmapArrayLength, &bytesWritten, NULL)) {
-		int lastError = GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-		tsk_error_set_errstr("addToExistingBlock: error writing sector",
-			lastError);
-		return TSK_ERR;
-	}
-
-	return TSK_OK;
+    return TSK_OK;
 }
 
-TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len, TSK_OFF_T blockNum) {
-
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "addNewBlock: Adding new block 0x%x\n", blockNum);
-		fflush(stderr);
-	}
-
-	writer->blockStatus[blockNum] = IMG_WRITER_BLOCK_STATUS_ALLOC;
-	writer->blockToOffset[blockNum] = writer->nextDataOffset;
-
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "addNewBlock: Allocating memory\n fullBuffer length: 0x%x\n sectorBitmap length: 0x%x\n completedSectors length: 0x%x\n",
-			writer->blockSize, writer->sectorBitmapLength, writer->sectorBitmapArrayLength);
-		fflush(stderr);
-	}
-	char * fullBuffer = (char *)tsk_malloc(writer->blockSize * sizeof(char));
-	char * sectorBitmap = (char *)tsk_malloc(writer->sectorBitmapLength * sizeof(char));
-	unsigned char * completedSectors = (unsigned char *)tsk_malloc(((writer->sectorBitmapArrayLength) * sizeof(char)));
-
-	/* Create the full new block and record the sectors written */
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "addNewBlock: Writing sector bitmap and full buffer. len = 0x%x\n", len);
-		fflush(stderr);
-	}
-	TSK_OFF_T startingOffset = addr % writer->blockSize;
-	for (size_t i = 0; i < len; i++) {
-
-		if (((startingOffset + i) % VHD_SECTOR_SIZE) == 0) {
-			TSK_OFF_T currentSector = (startingOffset + i) / VHD_SECTOR_SIZE;
-			setBit(completedSectors, currentSector, true);
-			if (tsk_verbose) {
-				tsk_fprintf(stderr, "addNewBlock: Setting sectorBitmap[%d] to completedSectors[%d]\n",
-					currentSector / 8, currentSector / 8);
-				fflush(stderr);
-			}
-			sectorBitmap[currentSector / 8] = completedSectors[currentSector / 8];
-		}
-
-		if (tsk_verbose) {
-			//tsk_fprintf(stderr, "addNewBlock: Setting fullBuffer[0x%x] to buffer[0x%x]\n",
-			//	startingOffset + i, i);
-			//fflush(stderr);
-		}
-		fullBuffer[startingOffset + i] = buffer[i];
-	}
-	writer->blockToSectorBitmap[blockNum] = completedSectors;
-
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "addNewBlock: Sector bitmap");
-		for (int i = 0; i < writer->sectorBitmapArrayLength; i++) {
-			if (i % 16 == 0) {
-				tsk_fprintf(stderr, "\n");
-			}
-			tsk_fprintf(stderr, "%02x ", completedSectors[i]);
-		}
-		fflush(stderr);
-	}
-
-	/* Prepare the new block offset */
-	TSK_OFF_T nextDataOffsetSector = writer->nextDataOffset / VHD_SECTOR_SIZE;
-	unsigned char newBlockOffset[4];
-	newBlockOffset[0] = (nextDataOffsetSector >> 24) & 0xff;
-	newBlockOffset[1] = (nextDataOffsetSector >> 16) & 0xff;
-	newBlockOffset[2] = (nextDataOffsetSector >> 8) & 0xff;
-	newBlockOffset[3] = nextDataOffsetSector & 0xff;
-
-	/* Write the new offset to the BAT */
-	if (TSK_OK != seekToOffset(writer, writer->batOffset + 4 * blockNum)) {
-		return TSK_ERR;
-	}
-	DWORD bytesWritten;
-	if (FALSE == WriteFile(writer->outputFileHandle, newBlockOffset, 4, &bytesWritten, NULL)) {
-		int lastError = GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-		tsk_error_set_errstr("addNewBlock: error writing BAT entry",
-			lastError);
-		return TSK_ERR;
-	}
-
-	/* Write the sector bitmap and the data */
-	if (TSK_OK != seekToOffset(writer, writer->nextDataOffset)) {
-		return TSK_ERR;
-	}
-	if (FALSE == WriteFile(writer->outputFileHandle, sectorBitmap, writer->sectorBitmapLength, &bytesWritten, NULL)) {
-		int lastError = GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-		tsk_error_set_errstr("addNewBlock: error writing sector bitmap",
-			lastError);
-		return TSK_ERR;
-	}
-	if (FALSE == WriteFile(writer->outputFileHandle, fullBuffer, writer->blockSize, &bytesWritten, NULL)) {
-		int lastError = GetLastError();
-		tsk_error_reset();
-		tsk_error_set_errno(TSK_ERR_IMG_WRITE);
-		tsk_error_set_errstr("addNewBlock: error writing block data",
-			lastError);
-		return TSK_ERR;
-	}
-
-	writer->nextDataOffset += writer->sectorBitmapLength + writer->blockSize;
-
-	/* Always add the footer on to make it a valid VHD */
-	writeFooter(writer);
-
-	free(fullBuffer);
-	free(sectorBitmap);
-
-	return TSK_OK;
+/* 
+ * Add a new block to the VHD and copy in the buffer
+ */
+static TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len, TSK_OFF_T blockNum) {
+
+    if (tsk_verbose) {
+        tsk_fprintf(stderr, "addNewBlock: Adding new block 0x%x\n", blockNum);
+        fflush(stderr);
+    }
+
+    writer->blockStatus[blockNum] = IMG_WRITER_BLOCK_STATUS_ALLOC;
+
+    /* Given the max size of the VHD, the sector number will always fit in four bytes */
+    writer->blockToSectorNumber[blockNum] = uint32_t(writer->nextDataOffset / VHD_SECTOR_SIZE);
+
+    char * fullBuffer = (char *)tsk_malloc(writer->blockSize * sizeof(char));
+    char * sectorBitmap = (char *)tsk_malloc(writer->sectorBitmapLength * sizeof(char));
+    unsigned char * completedSectors = (unsigned char *)tsk_malloc(((writer->sectorBitmapArrayLength) * sizeof(char)));
+
+    /* Create the full new block and record the sectors written */
+    TSK_OFF_T startingOffset = addr % writer->blockSize;
+    for (size_t i = 0; i < len; i++) {
+
+        /* Update the sector bitmap */
+        if (((startingOffset + i) % VHD_SECTOR_SIZE) == 0) {
+            TSK_OFF_T currentSector = (startingOffset + i) / VHD_SECTOR_SIZE;
+            setBit(completedSectors, currentSector, true);
+            sectorBitmap[currentSector / 8] = completedSectors[currentSector / 8];
+        }
+
+        fullBuffer[startingOffset + i] = buffer[i];
+    }
+    writer->blockToSectorBitmap[blockNum] = completedSectors;
+
+    /* Prepare the new block offset - this is stored in big-endian order */
+    TSK_OFF_T nextDataOffsetSector = writer->nextDataOffset / VHD_SECTOR_SIZE;
+    unsigned char newBlockOffset[4];
+    newBlockOffset[0] = (nextDataOffsetSector >> 24) & 0xff;
+    newBlockOffset[1] = (nextDataOffsetSector >> 16) & 0xff;
+    newBlockOffset[2] = (nextDataOffsetSector >> 8) & 0xff;
+    newBlockOffset[3] = nextDataOffsetSector & 0xff;
+
+    /* Write the new offset to the BAT */
+    if (TSK_OK != seekToOffset(writer, writer->batOffset + 4 * blockNum)) {
+        return TSK_ERR;
+    }
+    DWORD bytesWritten;
+    if (FALSE == WriteFile(writer->outputFileHandle, newBlockOffset, 4, &bytesWritten, NULL)) {
+        int lastError = GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+        tsk_error_set_errstr("addNewBlock: error writing BAT entry",
+            lastError);
+        return TSK_ERR;
+    }
+
+    /* Write the sector bitmap and the data */
+    if (TSK_OK != seekToOffset(writer, writer->nextDataOffset)) {
+        return TSK_ERR;
+    }
+    if (FALSE == WriteFile(writer->outputFileHandle, sectorBitmap, writer->sectorBitmapLength, &bytesWritten, NULL)) {
+        int lastError = GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+        tsk_error_set_errstr("addNewBlock: error writing sector bitmap",
+            lastError);
+        return TSK_ERR;
+    }
+    if (FALSE == WriteFile(writer->outputFileHandle, fullBuffer, writer->blockSize, &bytesWritten, NULL)) {
+        int lastError = GetLastError();
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_IMG_WRITE);
+        tsk_error_set_errstr("addNewBlock: error writing block data",
+            lastError);
+        return TSK_ERR;
+    }
+
+    /* Update the offset where the next block will start */
+    writer->nextDataOffset += writer->sectorBitmapLength + writer->blockSize;
+
+    /* Always add the footer on to make it a valid VHD */
+    writeFooter(writer);
+
+    free(fullBuffer);
+    free(sectorBitmap);
+
+    return TSK_OK;
 }
 
-TSK_RETVAL_ENUM addBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len) {
-	TSK_OFF_T blockNum = addr / writer->blockSize;
+/*
+ * Add a buffer that fits in a single block of the VHD 
+ */
+static TSK_RETVAL_ENUM addBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len) {
+    TSK_OFF_T blockNum = addr / writer->blockSize;
 
-	if (writer->blockStatus[blockNum] == IMG_WRITER_BLOCK_STATUS_FINISHED){
-		return TSK_OK;
-	}
+    if (writer->blockStatus[blockNum] == IMG_WRITER_BLOCK_STATUS_FINISHED){
+        return TSK_OK;
+    }
 
-	if (writer->blockStatus[blockNum] == IMG_WRITER_BLOCK_STATUS_ALLOC) {
-		addToExistingBlock(writer, addr, buffer, len, blockNum);
-	}
-	else {
-		addNewBlock(writer, addr, buffer, len, blockNum);
-	}
+    if (writer->blockStatus[blockNum] == IMG_WRITER_BLOCK_STATUS_ALLOC) {
+        addToExistingBlock(writer, addr, buffer, len, blockNum);
+    }
+    else {
+        addNewBlock(writer, addr, buffer, len, blockNum);
+    }
 
-	/* Check whether the block is now done */
-	checkIfBlockIsFinished(writer, blockNum);
+    /* Check whether the block is now done */
+    checkIfBlockIsFinished(writer, blockNum);
 
-	return TSK_OK;
+    return TSK_OK;
 }
 
+/*
+ * Add a buffer to the VHD. The buffer can span multiple blocks.
+ * @param writer Image writer object
+ * @param addr   Offset in the original image where the data starts
+ * @param buffer The data to copy
+ * @param len    Length of the data (this must be a multiple of the sector size)
+ */
 static TSK_RETVAL_ENUM tsk_img_writer_add(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len) {
 #ifndef TSK_WIN32
-	return TSK_ERR;
+    return TSK_ERR;
 #else
-	if (tsk_verbose) {
-		tsk_fprintf(stderr,
-			"tsk_img_writer_add: Adding data at offset: %"
-			PRIuOFF " len: %" PRIuOFF "\n", addr,
-			(TSK_OFF_T)len);
-	}
-
-	sprintf(messageBuffer, "tsk_img_writer_add: addr: 0x%llx  len: 0x%llx\n", addr, len);
-	writeLogFile(writer, messageBuffer);
-
-	if (writer->outputFileHandle == 0) {
-		writeLogFile(writer, "tsk_img_writer_add: outputFileHandle is closed");
-	}
-
-	/* This should never happen, but best to check */
-	if (addr % VHD_SECTOR_SIZE != 0) {
-		return TSK_ERR;
-	}
-
-	if ((addr / writer->blockSize) == ((addr + len) / writer->blockSize)) {
-		/* The buffer is contained in a single block */
-		if (tsk_verbose) {
-			tsk_fprintf(stderr, "tsk_img_writer_add: Data fits in one block (0x%x)", (addr / writer->blockSize));
-		}
-		return addBlock(writer, addr, buffer, len);
-	}
-	else {
-		/* The buffer spans two blocks */
-
-
-		TSK_OFF_T firstPartLength = writer->blockSize - (addr % writer->blockSize);
-
-		if (tsk_verbose) {
-			tsk_fprintf(stderr, "tsk_img_writer_add: Data spans two blocks (0x%x and 0x%x)\n",
-				(addr / writer->blockSize), ((addr + len) / writer->blockSize));
-			tsk_fprintf(stderr, "tsk_img_writer_add: first part len: 0x%llx\n", firstPartLength);
-			tsk_fprintf(stderr, "tsk_img_writer_add: second part len: 0x%llx\n", addr % writer->blockSize);
-		}
-		addBlock(writer, addr, buffer, firstPartLength);
-		if (addr + firstPartLength < writer->imageSize) {
-			addBlock(writer, addr + firstPartLength, buffer + firstPartLength, (addr + len) % writer->blockSize);
-		}
-	}
-
-	return TSK_OK;
+    if (tsk_verbose) {
+        tsk_fprintf(stderr,
+            "tsk_img_writer_add: Adding data at offset: %"
+            PRIuOFF " len: %" PRIuOFF "\n", addr,
+            (TSK_OFF_T)len);
+    }
+
+    /* This should never happen, but best to check */
+    if (addr % VHD_SECTOR_SIZE != 0) {
+        return TSK_ERR;
+    }
+
+    if ((addr / writer->blockSize) == ((addr + len) / writer->blockSize)) {
+        /* The buffer is contained in a single block */
+        return addBlock(writer, addr, buffer, len);
+    }
+    else {
+        /* The buffer spans two blocks */
+        TSK_OFF_T firstPartLength = writer->blockSize - (addr % writer->blockSize);
+        addBlock(writer, addr, buffer, firstPartLength);
+        if (addr + firstPartLength < writer->imageSize) {
+            addBlock(writer, addr + firstPartLength, buffer + firstPartLength, (addr + len) % writer->blockSize);
+        }
+    }
+
+    return TSK_OK;
 #endif
 }
 
+/*
+ * Close the image writer and free its memory
+ * @param writer Image writer object
+ */
 static TSK_RETVAL_ENUM tsk_img_writer_close(TSK_IMG_WRITER* img_writer) {
 #ifndef TSK_WIN32
     return TSK_ERR;
@@ -404,22 +397,58 @@ static TSK_RETVAL_ENUM tsk_img_writer_close(TSK_IMG_WRITER* img_writer) {
         tsk_fprintf(stderr,
             "tsk_img_writer_close: Closing image writer");
     }
-	writeLogFile(img_writer, "Closing image writer");
-	
+    
     if (img_writer->outputFileHandle != 0) {
         CloseHandle(img_writer->outputFileHandle);
         img_writer->outputFileHandle = 0;
-
-		/* TODO: Free the data */
     }	
-	if (img_writer->logFileHandle != 0) {
-		CloseHandle(img_writer->logFileHandle);
-		img_writer->logFileHandle = 0;
-	}
+
+    /* Free the memory */
+    if (img_writer->blockToSectorNumber != NULL) {
+        free(img_writer->blockToSectorNumber);
+        img_writer->blockToSectorNumber = NULL;
+    }
+
+    if (img_writer->blockStatus != NULL) {
+        free(img_writer->blockStatus);
+        img_writer->blockStatus = NULL;
+    }
+
+    if (img_writer->blockToSectorBitmap != NULL) {
+        for (uint32_t i = 0; i < img_writer->totalBlocks; i++) {
+            if (img_writer->blockToSectorBitmap[i] != NULL) {
+                free(img_writer->blockToSectorBitmap[i]);
+            }
+        }
+        free(img_writer->blockToSectorBitmap);
+        img_writer->blockToSectorBitmap = NULL;
+    }
+
+    if (img_writer->footer != NULL) {
+        free(img_writer->footer);
+        img_writer->footer = NULL;
+    }
+
+    if (img_writer->fileName != NULL) {
+        free(img_writer->fileName);
+        img_writer->fileName = NULL;
+    }
+
+
+    // TEMP TEMP TEMP
+    if (img_writer->logFileHandle != 0) {
+        CloseHandle(img_writer->logFileHandle);
+        img_writer->logFileHandle = 0;
+    }
 
     return TSK_OK;
 #endif
 }
+
+/*
+ * NOT IMPLENTED YET - Will go through the image and manually read and copy any missing sectors
+ * @param writer Image writer object
+ */
 static TSK_RETVAL_ENUM tsk_img_writer_finish_image(TSK_IMG_WRITER* img_writer) {
 #ifndef TSK_WIN32
     return TSK_ERR;
@@ -439,7 +468,7 @@ static TSK_RETVAL_ENUM tsk_img_writer_finish_image(TSK_IMG_WRITER* img_writer) {
  * Will write val as an nBytes-long value to the buffer at the given offset.
  * Byte ordering is big endian
  */
-void addIntToBuffer(unsigned char * buffer, int offset, TSK_OFF_T val, int nBytes) {
+static void addIntToBuffer(unsigned char * buffer, int offset, TSK_OFF_T val, int nBytes) {
     for (int i = 0; i < nBytes; i++) {
         buffer[offset + i] = (val >> (8 * (nBytes - 1 - i))) & 0xff;
     }
@@ -448,7 +477,7 @@ void addIntToBuffer(unsigned char * buffer, int offset, TSK_OFF_T val, int nByte
 /* 
  * Utility function to write strings to the VHD headers.
  */
-void addStringToBuffer(unsigned char * buffer, int offset, char const * str, int nBytes) {
+static void addStringToBuffer(unsigned char * buffer, int offset, char const * str, int nBytes) {
     for (int i = 0; i < nBytes; i++) {
         buffer[offset + i] = str[i];
     }
@@ -458,7 +487,7 @@ void addStringToBuffer(unsigned char * buffer, int offset, char const * str, int
  * Calculate the checksum for the header. It's the one's complement of the sum of
  * all the bytes (apart from the checksum)
  */
-uint32_t generateChecksum(unsigned char * buffer, int len) {
+static uint32_t generateChecksum(unsigned char * buffer, int len) {
 
     uint32_t sum = 0;
     for (int i = 0; i < len; i++) {
@@ -473,7 +502,7 @@ uint32_t generateChecksum(unsigned char * buffer, int len) {
  * Will write to the current file position.
  * Save it so we only have to generate it once.
  */
-TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer) {
+static TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer) {
     if (writer->footer == NULL) {
         writer->footer = (unsigned char *)tsk_malloc(VHD_FOOTER_LENGTH * sizeof(unsigned char));
 
@@ -520,8 +549,7 @@ TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer) {
         addIntToBuffer(writer->footer, 8, 2, 4);         // Features
         addIntToBuffer(writer->footer, 0xc, 0x10000, 4); // File format version
         addIntToBuffer(writer->footer, 0x10, 0x200, 8);  // Data offset
-        // 0x18 is a four byte timestamp - leave blank (or maybe not...)
-		addIntToBuffer(writer->footer, 0x18, 0x200a44cf, 4);
+        // 0x18 is a four byte timestamp - ok to leave blank
         addStringToBuffer(writer->footer, 0x1c, "win ", 4);  // Creator app
         addIntToBuffer(writer->footer, 0x20, 0x60001, 4);    // Creator version
         addStringToBuffer(writer->footer, 0x24, "Wi2k", 4);  // Creator host OS
@@ -531,12 +559,7 @@ TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer) {
         addIntToBuffer(writer->footer, 0x3a, heads, 1);            // Geometry
         addIntToBuffer(writer->footer, 0x3b, sectorsPerTrack, 1);  // Geometry
         addIntToBuffer(writer->footer, 0x3c, 3, 4);                // Disk type
-
-		// Maybe we need the UUID to be set to something?
-		addIntToBuffer(writer->footer, 0x44, 0xde08e6bb, 4);// UUID1
-		addIntToBuffer(writer->footer, 0x48, 0xf7684142, 4);
-		addIntToBuffer(writer->footer, 0x4c, 0x938758ea, 4);
-		addIntToBuffer(writer->footer, 0x50, 0x77385e49, 4);
+        // Bytes 0x44 to 0x54 are a UUID, which is ok to leave blank
 
         addIntToBuffer(writer->footer, 0x40, generateChecksum(writer->footer, VHD_FOOTER_LENGTH), 4); // Checksum
     }
@@ -556,7 +579,7 @@ TSK_RETVAL_ENUM writeFooter(TSK_IMG_WRITER* writer) {
 /*
  * Write the dynamic disk header to the file
  */
-TSK_RETVAL_ENUM writeDynamicDiskHeader(TSK_IMG_WRITER * writer) {
+static TSK_RETVAL_ENUM writeDynamicDiskHeader(TSK_IMG_WRITER * writer) {
     unsigned char * diskHeader = (unsigned char *)malloc(VHD_DISK_HEADER_LENGTH * sizeof(unsigned char));
     for (int i = 0; i < VHD_DISK_HEADER_LENGTH; i++) {
         diskHeader[i] = 0;
@@ -587,50 +610,23 @@ TSK_RETVAL_ENUM writeDynamicDiskHeader(TSK_IMG_WRITER * writer) {
 /*
  * Create and initailize the TSK_IMG_WRITER struct and save reference in img_info,
  * then write the headers to the output file
+ * @param img_info        the TSK_IMG_INFO object
+ * @param outputFileName  path to the VHD
  */
-TSK_RETVAL_ENUM tsk_img_writer_create_from_dir(TSK_IMG_INFO * img_info, const TSK_TCHAR * directory,
-	const TSK_TCHAR * basename) {
-
-#ifndef TSK_WIN32
-	return TSK_ERR;
-#else
-	if (tsk_verbose) {
-		tsk_fprintf(stderr,
-			"tsk_img_writer_create: Creating image writer in directory %" PRIttocTSK" with basename %" PRIttocTSK"\n",
-			directory, basename);
-		fflush(stderr);
-	}
-
-	/* Set up the output file */
-	size_t len = TSTRLEN(directory) + TSTRLEN(basename) + 10;
-	TSK_TCHAR * outputFileName = (TSK_TCHAR *)malloc(len * sizeof(TSK_TCHAR));
-	TSTRNCPY(outputFileName, directory, TSTRLEN(directory) + 1);
-	TSTRNCAT(outputFileName, _TSK_T("\\"), 2);
-	TSTRNCAT(outputFileName, basename, TSTRLEN(basename) + 1);
-	TSTRNCAT(outputFileName, _TSK_T(".vhd"), 5);
-	if (tsk_verbose) {
-		tsk_fprintf(stderr,
-			"tsk_img_writer_create: Output file: %" PRIttocTSK"\n", outputFileName);
-		fflush(stderr);
-	}
-
-	return tsk_img_writer_create(img_info, outputFileName);
-#endif
-}
-
-/*
-* Create and initailize the TSK_IMG_WRITER struct and save reference in img_info,
-* then write the headers to the output file
-*/
 TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR * outputFileName) {
 #ifndef TSK_WIN32
-	return TSK_ERR;
+    return TSK_ERR;
 #else
     if (tsk_verbose) {
         tsk_fprintf(stderr,
             "tsk_img_writer_create: Creating image writer in %" PRIttocTSK"\n",
             outputFileName);
-		fflush(stderr);
+    }
+
+    /* Everything will break if the buffers coming in are larger than the block 
+       size (i.e., they could span three blocks instead of just two)*/
+    if (TSK_IMG_INFO_CACHE_LEN > VHD_DEFAULT_BLOCK_SIZE) {
+        return TSK_ERR;
     }
 
     IMG_RAW_INFO* raw_info = (IMG_RAW_INFO *)img_info;
@@ -650,8 +646,8 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR *
     writer->close = tsk_img_writer_close;
     writer->finish_image = tsk_img_writer_finish_image;
 
-	writer->fileName = (TSK_TCHAR*)tsk_malloc((TSTRLEN(outputFileName) + 1) * sizeof(TCHAR));
-	TSTRNCPY(writer->fileName, outputFileName, TSTRLEN(outputFileName) + 1);
+    writer->fileName = (TSK_TCHAR*)tsk_malloc((TSTRLEN(outputFileName) + 1) * sizeof(TCHAR));
+    TSTRNCPY(writer->fileName, outputFileName, TSTRLEN(outputFileName) + 1);
 
     /* Calculation time */
     writer->imageSize = raw_info->img_info.size;
@@ -664,22 +660,20 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR *
         writer->totalBlocks++;
     }
     writer->sectorsPerBlock = writer->blockSize / VHD_SECTOR_SIZE;
-	writer->sectorBitmapArrayLength = writer->sectorsPerBlock / 8;
-	if (writer->sectorBitmapArrayLength % 8 != 0) {
-		writer->sectorBitmapArrayLength++;
-	}
-	writer->sectorBitmapLength = writer->sectorBitmapArrayLength;
-	if (0 != writer->sectorBitmapLength % VHD_SECTOR_SIZE) {
-		writer->sectorBitmapLength += VHD_SECTOR_SIZE - (writer->sectorBitmapLength % VHD_SECTOR_SIZE);
-	}
+    writer->sectorBitmapArrayLength = writer->sectorsPerBlock / 8;
+    if (writer->sectorBitmapArrayLength % 8 != 0) {
+        writer->sectorBitmapArrayLength++;
+    }
+    writer->sectorBitmapLength = writer->sectorBitmapArrayLength;
+    if (0 != writer->sectorBitmapLength % VHD_SECTOR_SIZE) {
+        writer->sectorBitmapLength += VHD_SECTOR_SIZE - (writer->sectorBitmapLength % VHD_SECTOR_SIZE);
+    }
 
     /* TODO: Decide what to do if the file already exisits. For now, always overwrite */
     writer->outputFileHandle = CreateFile(writer->fileName, FILE_WRITE_DATA,
         FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0,
         NULL);
     if (writer->outputFileHandle == INVALID_HANDLE_VALUE) {
-		tsk_fprintf(stderr, "Error opening VHD!!!"); // temp
-		fflush(stderr);
         int lastError = (int)GetLastError();
         writer->outputFileHandle = 0; /* so we don't close it next time */
         tsk_error_reset();
@@ -689,31 +683,24 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR *
         return TSK_ERR;
     }
 
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "tsk_img_writer_create: Writing VHD headers");
-		fflush(stderr);
-	}
-
     /* Write the backup copy of the footer */
     TSK_RETVAL_ENUM retval = writeFooter(writer);
     if (retval != TSK_OK) {
         return retval;
     }
+
+    /* Write the dynamic disk header */
     retval = writeDynamicDiskHeader(writer);
     if (retval != TSK_OK) {
         return retval;
     }
 
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "tsk_img_writer_create: Writing block allocation table");
-		fflush(stderr);
-	}
-    /* Write the (empty) Block Allocation Table */
+    /* Write the (empty) Block Allocation Table. Each entry is 4 bytes*/
     writer->batOffset = VHD_FOOTER_LENGTH + VHD_DISK_HEADER_LENGTH;
     uint32_t batLengthOnDisk = 4 * writer->totalBlocks;
-    if ((batLengthOnDisk % 0x200) != 0) {
+    if ((batLengthOnDisk % VHD_SECTOR_SIZE) != 0) {
         /* Pad out to the next sector boundary */
-        batLengthOnDisk += (0x200 - ((4 * writer->totalBlocks) % 0x200));
+        batLengthOnDisk += (VHD_SECTOR_SIZE - ((4 * writer->totalBlocks) % VHD_SECTOR_SIZE));
     }
 
     DWORD bytesWritten;
@@ -733,20 +720,10 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO * img_info, const TSK_TCHAR *
     /* Offset for the first data block - 0x600 bytes for the two headers plus the BAT length*/
     writer->nextDataOffset = 0x600 + batLengthOnDisk;
 
-	if (tsk_verbose) {
-		tsk_fprintf(stderr, "VHD data:\n imageSize: %x\n blockSize: %x\n totalBlocks: %x\n sectorBitmapLength: %x\n ", 
-			writer->imageSize, writer->blockSize, writer->totalBlocks, writer->sectorBitmapLength);
-		tsk_fprintf(stderr, " sectorBitmapInMemory: %x\n sectorsPerBlock: %x\n", 
-			writer->sectorBitmapArrayLength, writer->sectorsPerBlock);
-		fflush(stderr);
-
-	}
-
-	/* Initialze all the bookkeeping arrays */
-	writer->blockStatus = (IMG_WRITER_BLOCK_STATUS_ENUM*)tsk_malloc(writer->totalBlocks * sizeof(IMG_WRITER_BLOCK_STATUS_ENUM));
-
-	writer->blockToOffset = (TSK_OFF_T*)tsk_malloc(writer->totalBlocks * sizeof(TSK_OFF_T));
-	writer->blockToSectorBitmap = (unsigned char **)tsk_malloc(writer->totalBlocks * sizeof(unsigned char *));
+    /* Initialze all the bookkeeping arrays */
+    writer->blockStatus = (IMG_WRITER_BLOCK_STATUS_ENUM*)tsk_malloc(writer->totalBlocks * sizeof(IMG_WRITER_BLOCK_STATUS_ENUM));
+    writer->blockToSectorNumber = (uint32_t*)tsk_malloc(writer->totalBlocks * sizeof(uint32_t));
+    writer->blockToSectorBitmap = (unsigned char **)tsk_malloc(writer->totalBlocks * sizeof(unsigned char *));
 
     return TSK_OK;
 #endif
diff --git a/tsk/img/img_writer.h b/tsk/img/img_writer.h
index e421e020c..dac6a69e5 100644
--- a/tsk/img/img_writer.h
+++ b/tsk/img/img_writer.h
@@ -19,9 +19,6 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
-
-    TSK_RETVAL_ENUM tsk_img_writer_create_from_dir(TSK_IMG_INFO* img_info, const TSK_TCHAR * directory,
-        const TSK_TCHAR * basename);
 	TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO* img_info, const TSK_TCHAR * outputPath);
 
 	enum IMG_WRITER_BLOCK_STATUS_ENUM {
@@ -54,7 +51,7 @@ extern "C" {
 		HANDLE logFileHandle;
 
 		IMG_WRITER_BLOCK_STATUS_ENUM* blockStatus;
-		TSK_OFF_T* blockToOffset;
+        uint32_t* blockToSectorNumber;
 		unsigned char ** blockToSectorBitmap;
 
         TSK_RETVAL_ENUM(*add)(TSK_IMG_WRITER* img_writer, TSK_OFF_T addr, char *buffer, size_t len);
diff --git a/tsk/img/raw.c b/tsk/img/raw.c
index 1ddcded72..a3d85123a 100644
--- a/tsk/img/raw.c
+++ b/tsk/img/raw.c
@@ -359,6 +359,8 @@ raw_close(TSK_IMG_INFO * img_info)
 #ifdef TSK_WIN32
     if (raw_info->img_writer != NULL) {
         raw_info->img_writer->close(raw_info->img_writer);
+        free(raw_info->img_writer);
+        raw_info->img_writer = NULL;
     }
 #endif
 
@@ -759,11 +761,6 @@ tsk_img_malloc(size_t a_len)
 void
 tsk_img_free(void *a_ptr)
 {
-    IMG_RAW_INFO *rawInfo = (IMG_RAW_INFO *)a_ptr;
-    if (rawInfo->img_writer != NULL) {
-        free(rawInfo->img_writer);
-        rawInfo->img_writer = NULL;
-    }
     TSK_IMG_INFO *imgInfo = (TSK_IMG_INFO *) a_ptr;
     imgInfo->tag = 0;
     free(imgInfo);
diff --git a/tsk/img/vhd.c b/tsk/img/vhd.c
index ba45fedc1..864aa0167 100644
--- a/tsk/img/vhd.c
+++ b/tsk/img/vhd.c
@@ -202,6 +202,7 @@ vhdi_open(int a_num_img,
     }
     // Check the file signature before we call the library open
 #if defined( TSK_WIN32 )
+    tsk_fprintf(stderr, "Trying to open file: %s\n", vhdi_info->img_info.images[0]);
     if( libvhdi_check_file_signature_wide((const wchar_t *) vhdi_info->img_info.images[0], &vhdi_error ) != 1 )
 #else
     if( libvhdi_check_file_signature((const char *) vhdi_info->images[0], &vhdi_error) != 1)
@@ -214,6 +215,8 @@ vhdi_open(int a_num_img,
         tsk_error_set_errstr("vhdi_open file: %" PRIttocTSK
             ": Error checking file signature for image (%s)", a_images[0],
             error_string);
+
+        tsk_fprintf(stderr, "VHD error string: %s\n", error_string); // temp temp
         libvhdi_error_free(&vhdi_error);
 
         tsk_img_free(vhdi_info);
-- 
GitLab