diff --git a/c/meterpreter/source/extensions/networkpug/networkpug.c b/c/meterpreter/source/extensions/networkpug/networkpug.c
index 2bdf6b16..cbea7e45 100644
--- a/c/meterpreter/source/extensions/networkpug/networkpug.c
+++ b/c/meterpreter/source/extensions/networkpug/networkpug.c
@@ -76,7 +76,7 @@ void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *byt
 	}
 	np->packet_stream = tmp;
 
-	size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);  
+	size = (unsigned short int *)(np->packet_stream + np->packet_stream_length);
 	*size = htons(h->caplen);
 	data = (unsigned char *)(np->packet_stream + np->packet_stream_length + 2);
 
@@ -438,7 +438,11 @@ Command customCommands[] =
 /*
  * Initialize the server extension
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
+#else
+DWORD InitServerExtension(Remote *remote)
+#endif
 {
 	int peername_len;
 	struct sockaddr peername;
@@ -497,7 +501,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
 /*
  * Deinitialize the server extension
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
+#else
+DWORD DeinitServerExtension(Remote *remote)
+#endif
 {
 	command_deregister_all(customCommands);
 
@@ -507,3 +515,23 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
 
 	return ERROR_SUCCESS;
 }
+
+/*!
+ * @brief Get the name of the extension.
+ * @param buffer Pointer to the buffer to write the name to.
+ * @param bufferSize Size of the \c buffer parameter.
+ * @return Indication of success or failure.
+ */
+#ifdef _WIN32
+DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
+#else
+DWORD GetExtensionName(char* buffer, int bufferSize)
+#endif
+{
+#ifdef _WIN32
+	strncpy_s(buffer, bufferSize, "networkpug", bufferSize - 1);
+#else
+	strncpy(buffer, "networkpug", bufferSize - 1);
+#endif
+	return ERROR_SUCCESS;
+}
diff --git a/c/meterpreter/source/extensions/sniffer/sniffer.c b/c/meterpreter/source/extensions/sniffer/sniffer.c
index a4430a3d..efa06096 100644
--- a/c/meterpreter/source/extensions/sniffer/sniffer.c
+++ b/c/meterpreter/source/extensions/sniffer/sniffer.c
@@ -1197,7 +1197,11 @@ DWORD request_sniffer_capture_dump(Remote *remote, Packet *packet)
  * @param remote Pointer to the remote instance.
  * @return Indication of success or failure.
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
+#else
+DWORD InitServerExtension(Remote *remote)
+#endif
 {
 #ifdef _WIN32
 	// This handle has to be set before calls to command_register
@@ -1271,7 +1275,11 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
  * @param remote Pointer to the remote instance.
  * @return Indication of success or failure.
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
+#else
+DWORD DeinitServerExtension(Remote *remote)
+#endif
 {
 	command_register_all( customCommands );
 
@@ -1294,8 +1302,16 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
  * @param bufferSize Size of the \c buffer parameter.
  * @return Indication of success or failure.
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
+#else
+DWORD GetExtensionName(char* buffer, int bufferSize)
+#endif
 {
+#ifdef _WIN32
 	strncpy_s(buffer, bufferSize, "sniffer", bufferSize - 1);
+#else
+	strncpy(buffer, "sniffer", bufferSize - 1);
+#endif
 	return ERROR_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/dir.c b/c/meterpreter/source/extensions/stdapi/server/fs/dir.c
index a94e3b3f..cf3b1662 100644
--- a/c/meterpreter/source/extensions/stdapi/server/fs/dir.c
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/dir.c
@@ -1,370 +1,132 @@
-#include "precomp.h"
-#include <sys/stat.h>
-
-#ifndef _WIN32
- #include <dirent.h>
-#endif
-
-/*
- * Gets the contents of a given directory path and returns the list of file
- * names to the requestor.
- *
- * TLVs:
- *
- * req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
- */
-DWORD request_fs_ls(Remote *remote, Packet *packet)
-{
-	Packet *response = packet_create_response(packet);
-	LPCSTR directory;
-	DWORD result = ERROR_SUCCESS;
-	LPSTR expanded = NULL, tempFile = NULL;
-	size_t tempFileSize = 0;
-	LPSTR baseDirectory = NULL;
-	struct meterp_stat buf;
-
-	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
-
-	// Enumerate the directory if one was provided
-	if (!directory)
-		result = ERROR_INVALID_PARAMETER;
-	else
-	{
-#ifdef _WIN32
-		WIN32_FIND_DATA data;
-		HANDLE ctx = NULL;
-#else
-		DIR *ctx;
-		struct dirent *data;
-#endif
-		BOOLEAN freeDirectory = FALSE;
-		LPSTR tempDirectory = (LPSTR)directory;
-
-#ifdef _WIN32
-		// If there is not wildcard mask on the directory, create a version of the
-		// directory with a mask appended
-		if (!strrchr(directory, '*'))
-		{
-			if (!(tempDirectory = (LPSTR)malloc(strlen(directory) + 3)))
-			{
-				result = ERROR_NOT_ENOUGH_MEMORY;
-				goto out;
-			}
-
-			sprintf(tempDirectory, "%s\\*", directory);	
-
-			// Dupe!
-			if (!(baseDirectory = _strdup(directory)))
-			{
-				result = ERROR_NOT_ENOUGH_MEMORY;
-				goto out;
-			}
-		}
-		// Otherwise, if it does have an asterisk, we need to scan back and find
-		// the base directory.  If there is no slash, it means we're listing the
-		// cwd.
-		else
-		{
-			PCHAR slash = strrchr(directory, '\\');
-
-			if (slash)
-			{
-				*slash = 0;
-
-				if (!(baseDirectory = _strdup(directory)))
-				{
-					result = ERROR_NOT_ENOUGH_MEMORY;
-					goto out;
-				}
-
-				*slash = '\\';
-			}
-		}
-
-		// Expand the path
-		if (!(expanded = fs_expand_path(tempDirectory)))
-		{
-			result = ERROR_NOT_ENOUGH_MEMORY;
-			goto out;
-		}
-
-		// Start the find operation
-		ctx = FindFirstFile(expanded, &data);
-
- #define DF_NAME data.cFileName
-#else
-		expanded = 0;
-		ctx = opendir(tempDirectory);
-		if(ctx == NULL)
-		{
-		  result = errno;
-		  goto out;
-		}
-		data = readdir(ctx);
-		if (!(baseDirectory = _strdup(directory)))
-		{
-			result = ERROR_NOT_ENOUGH_MEMORY;
-			goto out;
-		}
-	      
- #define DF_NAME data->d_name
-#endif
-
-		do
-		{
-			size_t fullSize = (baseDirectory ? strlen(baseDirectory) : 0) + strlen(DF_NAME) + 2;
-
-			// No context?  Sucktastic
-			if (ctx == INVALID_HANDLE_VALUE)
-			{
-				result = GetLastError();
-				break;
-			}
-
-			// Allocate temporary storage to stat the file
-			if ((!tempFile) || (tempFileSize < fullSize))
-			{
-				if (tempFile)
-				{
-					free(tempFile);
-				}
-
-				// No memory means we suck a lot like spoon's mom
-				if (!(tempFile = (LPSTR)malloc(fullSize)))
-				{
-					result = ERROR_NOT_ENOUGH_MEMORY;
-					break;
-				}
-
-				// Update the tempFileSize so that we don't allocate if we don't
-				// need to like a true efficient ninja
-				tempFileSize = fullSize;
-			}
-
-			// Build the full path
-			if (baseDirectory)
-			{
-#ifdef _WIN32
-				sprintf(tempFile, "%s\\%s", baseDirectory, DF_NAME);
-#else
-				sprintf(tempFile, "%s/%s", baseDirectory, DF_NAME);
-#endif
-			}
-			else
-			{
-				sprintf(tempFile, "%s", DF_NAME);
-			}
-
-			// Add the file name to the response
-			packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, DF_NAME);
-			// Add the full path
-			packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, tempFile);
-
-			// Stat the file to get more information about it.
-			if (fs_stat(tempFile, &buf) >= 0)
-			{
-				packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
-			}
-
-#ifdef _WIN32
-		} while (FindNextFile(ctx, &data));
-#else
-	        } while (data = readdir(ctx));
-#endif
-#undef DF_NAME
-
-		// Clean up resources
-		if (freeDirectory)
-		{
-			free(tempDirectory);
-		}
-
-		if (ctx)
-		{
-#ifdef _WIN32
-			FindClose(ctx);
-#else
-			closedir(ctx);
-#endif
-		}
-	}
-
-	if (expanded)
-	{
-		free(expanded);
-	}
-
-out:
-	if (baseDirectory)
-	{
-		free(baseDirectory);
-	}
-
-	// Set the result and transmit the response
-	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
-}
-
-/*
- * Gets the current working directory
- */
-DWORD request_fs_getwd(Remote *remote, Packet *packet)
-{
-	Packet *response = packet_create_response(packet);
-	DWORD directorySize = 4096, realSize;
-	LPSTR directory = NULL;
-	DWORD result = ERROR_SUCCESS;
-
-	do
-	{
-again:
-		// Allocate storage for the directory path
-		if (!(directory = (LPSTR)malloc(directorySize)))
-		{
-			result = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
-
-		memset(directory, 0, directorySize);
-
-#ifdef _WIN32
-		if (!(realSize = GetCurrentDirectory(directorySize, directory)))
-		{
-			result = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
-		else if (realSize > directorySize)
-		{
-			free(directory);
-			directorySize = realSize;
-			goto again;
-		}
-#else
-		if (!getcwd(directory, directorySize))
-		{
-			if (errno == ERANGE && directorySize > 0)
-			{
-				// Then we didn't allocate enough to hold the whole path,
-				// increase the size and try again.
-				free(directory);
-				directorySize = directorySize * 2;
-				goto again;
-			} else {
-				dprintf("getcwd failed with errno %d", errno);
-				break;
-			}
-		}
-#endif
-
-		packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH,
-				directory);
-
-	} while (0);
-
-	// Set the result and transmit the response
-	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	if (directory)
-		free(directory);
-
-	return ERROR_SUCCESS;
-}
-
-/*
- * Changes the working directory of the process
- *
- * TLVs:
- *
- * req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
- *                                directory to.
- */
-DWORD request_fs_chdir(Remote *remote, Packet *packet)
-{
-	Packet *response = packet_create_response(packet);
-	LPCSTR directory;
-	DWORD result = ERROR_SUCCESS;
-
-	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
-
-	if (!directory)
-		result = ERROR_INVALID_PARAMETER;
-#ifdef _WIN32
-	else if (!SetCurrentDirectory(directory))
-#else
-	else if (chdir(directory))
-#endif
-		result = GetLastError();
-
-	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
-}
-
-/*
- * Creates a new directory
- *
- * TLVs:
- *
- * req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
- */
-DWORD request_fs_mkdir(Remote *remote, Packet *packet)
-{
-	Packet *response = packet_create_response(packet);
-	LPCSTR directory;
-	DWORD result = ERROR_SUCCESS;
-
-	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
-
-	if (!directory)
-		result = ERROR_INVALID_PARAMETER;
-#ifdef _WIN32
-	else if (!CreateDirectory(directory, NULL))
-#else
-	else if (mkdir(directory, 0777))
-#endif
-		result = GetLastError();
-
-	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
-}
-
-/*
- * Removes the supplied directory from disk if it's empty
- *
- * TLVs:
- *
- * req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
- */
-DWORD request_fs_delete_dir(Remote *remote, Packet *packet)
-{
-	Packet *response = packet_create_response(packet);
-	LPCSTR directory;
-	DWORD result = ERROR_SUCCESS;
-
-	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
-
-	if (!directory)
-		result = ERROR_INVALID_PARAMETER;
-#ifdef _WIN32
-	else if (!RemoveDirectory(directory))
-#else
-	else if (rmdir(directory))
-#endif
-		result = GetLastError();
-
-	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
-}
+#include "precomp.h"
+
+#include "fs_local.h"
+
+void request_fs_ls_cb(void *arg, char *name, char *short_name, char *path)
+{
+	Packet *response = arg;
+	struct meterp_stat s;
+
+	/*
+	 * Add the file name, full path and stat information
+	 */
+	packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, name);
+	packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, path);
+	if (short_name) {
+		packet_add_tlv_string(response, TLV_TYPE_FILE_SHORT_NAME, short_name);
+	}
+	if (fs_stat(path, &s) >= 0) {
+		packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &s, sizeof(s));
+	}
+}
+
+/*
+ * Gets the contents of a given directory path and returns the list of file
+ * names to the requestor.
+ *
+ * req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
+ */
+DWORD request_fs_ls(Remote * remote, Packet * packet)
+{
+	Packet *response = packet_create_response(packet);
+	LPCSTR directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
+	DWORD result;
+
+	if (!directory) {
+		result = ERROR_INVALID_PARAMETER;
+	} else {
+		result = fs_ls(directory, request_fs_ls_cb, response);
+	}
+
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
+}
+
+/*
+ * Gets the current working directory
+ *
+ * req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
+ *                                directory to.
+ */
+DWORD request_fs_getwd(Remote * remote, Packet * packet)
+{
+	Packet *response = packet_create_response(packet);
+	char *directory = NULL;
+	DWORD result;
+
+	result = fs_getwd(&directory);
+	if (directory != NULL) {
+		packet_add_tlv_string(response, TLV_TYPE_DIRECTORY_PATH, directory);
+		free(directory);
+	}
+
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
+}
+
+/*
+ * Changes the working directory of the process
+ *
+ * req: TLV_TYPE_DIRECTORY_PATH - The directory path to change the working
+ *                                directory to.
+ */
+DWORD request_fs_chdir(Remote * remote, Packet * packet)
+{
+	Packet *response = packet_create_response(packet);
+	char *directory;
+	DWORD result;
+	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
+
+	if (directory == NULL) {
+		result = ERROR_INVALID_PARAMETER;
+	} else {
+		result = fs_chdir(directory);
+	}
+
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
+}
+
+/*
+ * Creates a new directory
+ *
+ * req: TLV_TYPE_DIRECTORY_PATH - The directory path to create.
+ */
+DWORD request_fs_mkdir(Remote * remote, Packet * packet)
+{
+	Packet *response = packet_create_response(packet);
+	char *directory;
+	DWORD result;
+	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
+
+	if (directory == NULL) {
+		result = ERROR_INVALID_PARAMETER;
+	} else {
+		result = fs_mkdir(directory);
+	}
+
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
+}
+
+/*
+ * Removes the supplied directory from disk if it's empty
+ *
+ * req: TLV_TYPE_DIRECTORY_PATH - The directory that is to be removed.
+ */
+DWORD request_fs_delete_dir(Remote * remote, Packet * packet)
+{
+	Packet *response = packet_create_response(packet);
+	char *directory;
+	DWORD result;
+	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);
+
+	if (directory == NULL) {
+		result = ERROR_INVALID_PARAMETER;
+	} else {
+		result = fs_delete_dir(directory);
+	}
+
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
+}
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/file.c b/c/meterpreter/source/extensions/stdapi/server/fs/file.c
index 5b45959b..a3b7e256 100644
--- a/c/meterpreter/source/extensions/stdapi/server/fs/file.c
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/file.c
@@ -1,4 +1,6 @@
 #include "precomp.h"
+#include "fs_local.h"
+
 #include <sys/stat.h>
 
 #include <openssl/md5.h>
@@ -23,19 +25,18 @@ static DWORD file_channel_write(Channel *channel, Packet *request,
 {
 	FileContext *ctx = (FileContext *)context;
 	DWORD result= ERROR_SUCCESS;
-	DWORD written = 0;
+	size_t written = 0;
 
 	// Write a chunk
-	if (bufferSize && (written = (DWORD)fwrite(buffer, 1, bufferSize, ctx->fd)) <= 0)
-	{
-		written = 0;
-		result  = GetLastError();
+	if (bufferSize) {
+		written = fwrite(buffer, 1, bufferSize, ctx->fd);
+		if (written < bufferSize) {
+			result  = GetLastError();
+		}
 	}
 
-	// Set bytesWritten
-	if (bytesWritten)
-	{
-		*bytesWritten = written;
+	if (bytesWritten) {
+		*bytesWritten = (DWORD)written;
 	}
 
 	return result;
@@ -64,18 +65,19 @@ static DWORD file_channel_read(Channel *channel, Packet *request,
 {
 	FileContext *ctx = (FileContext *)context;
 	DWORD result = ERROR_SUCCESS;
-	DWORD bytes = 0;
+	size_t bytes = 0;
 
 	// Read a chunk
-	if (bufferSize && (bytes= (DWORD)fread(buffer, 1, bufferSize, ctx->fd)) <= 0)
-	{
-		bytes = 0;
-		result = GetLastError();
+	if (bufferSize) {
+	       	bytes = fread(buffer, 1, bufferSize, ctx->fd);
+		if (bytes < bufferSize) {
+			result = GetLastError();
+		}
 	}
 
-	// Set bytesRead
-	if (bytesRead)
-		*bytesRead = bytes;
+	if (bytesRead) {
+		*bytesRead = (DWORD)bytes;
+	}
 
 	return ERROR_SUCCESS;
 }
@@ -112,8 +114,9 @@ static DWORD file_channel_tell(Channel *channel, Packet *request,
 	DWORD result = ERROR_SUCCESS;
 	LONG pos = 0;
 
-	if ((pos = ftell(ctx->fd)) < 0)
+	if ((pos = ftell(ctx->fd)) < 0) {
 		result = GetLastError();
+	}
 
 	if (offset)
 		*offset = pos;
@@ -136,90 +139,64 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
 	FileContext *ctx;
 	LPSTR expandedFilePath = NULL;
 
-	do
-	{
-		// Allocate a response
-		response = packet_create_response(packet);
+	// Allocate a response
+	response = packet_create_response(packet);
 
-		// Get the channel flags
-		flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
+	// Get the channel flags
+	flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);
 
-		// Allocate storage for the file context
-		if (!(ctx = (FileContext *)malloc(sizeof(FileContext))))
-		{
-			res = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
+	// Allocate storage for the file context
+	if (!(ctx = calloc(1, sizeof(FileContext)))) {
+		res = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
 
-		// Get the file path and the mode
-		filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
-		mode     = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
+	// Get the file path and the mode
+	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
+	mode     = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);
 
-		// No file path? bogus.
-		if (!filePath)
-		{
-			res = ERROR_INVALID_PARAMETER;
-			break;
-		}
+	if (mode == NULL) {
+		mode = "rb";
+	}
 
-		// Expand the file path
-		if (!(expandedFilePath = fs_expand_path(filePath)))
-		{
-			res = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
+	res = fs_fopen(filePath, mode, &ctx->fd);
+	if (res != ERROR_SUCCESS) {
+		goto out;
+	}
 
-		if (!mode)
-			mode = "rb";
+	memset(&chops, 0, sizeof(chops));
 
-		// Invalid file?
-		if (!(ctx->fd = fopen(expandedFilePath, mode)))
-		{
-			res = GetLastError();
-			break;
-		}
+	// Initialize the pool operation handlers
+	chops.native.context = ctx;
+	chops.native.write   = file_channel_write;
+	chops.native.close   = file_channel_close;
+	chops.read           = file_channel_read;
+	chops.eof            = file_channel_eof;
+	chops.seek           = file_channel_seek;
+	chops.tell           = file_channel_tell;
 
-		memset(&chops, 0, sizeof(chops));
+	// Check the response allocation & allocate a un-connected
+	// channel
+	if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops)))) {
+		res = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
 
-		// Initialize the pool operation handlers
-		chops.native.context = ctx;
-		chops.native.write   = file_channel_write;
-		chops.native.close   = file_channel_close;
-		chops.read           = file_channel_read;
-		chops.eof            = file_channel_eof;
-		chops.seek           = file_channel_seek;
-		chops.tell           = file_channel_tell;
-
-		// Check the response allocation & allocate a un-connected
-		// channel
-		if ((!response) || (!(newChannel = channel_create_pool(0, flags, &chops))))
-		{
-			res = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
-
-		// Add the channel identifier to the response
-		packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,
-				channel_get_id(newChannel));
-
-	} while (0);
+	// Add the channel identifier to the response
+	packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));
 
+out:
 	// Transmit the packet if it's valid
 	packet_transmit_response(res, remote, response);
 
 	// Clean up on failure
-	if (res != ERROR_SUCCESS)
-	{
-		if (newChannel)
+	if (res != ERROR_SUCCESS) {
+		if (newChannel) {
 			channel_destroy(newChannel, NULL);
-		if (ctx)
-			free(ctx);
+		}
+		free(ctx);
 	}
 
-	// Free the expanded file path if it was allocated
-	if (expandedFilePath)
-		free(expandedFilePath);
-
 	return res;
 }
 
@@ -229,20 +206,12 @@ DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
 DWORD request_fs_separator(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
-#ifdef _WIN32
-	LPCSTR separator = "\\";
-#else
-	LPCSTR separator = "/";
-#endif
 
-	packet_add_tlv_string(response, TLV_TYPE_STRING, separator);
+	packet_add_tlv_string(response, TLV_TYPE_STRING, FS_SEPARATOR);
 
-	// Set the result and transmit the response
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, ERROR_SUCCESS);
 
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
+	return packet_transmit(remote, response, NULL);
 }
 
 
@@ -250,73 +219,62 @@ DWORD request_fs_separator(Remote *remote, Packet *packet)
  * Gets information about the file path that is supplied and returns it to the
  * requestor
  *
- * TLVs:
- *
  * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
  */
 DWORD request_fs_stat(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
 	struct meterp_stat buf;
-	LPCSTR filePath;
-	LPSTR expanded = NULL;
+	char *filePath;
+	char *expanded = NULL;
 	DWORD result = ERROR_SUCCESS;
 
 	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
 
-	// Validate parameters
-	if (!filePath)
+	if (!filePath) {
 		result = ERROR_INVALID_PARAMETER;
-	else if (!(expanded = fs_expand_path(filePath)))
-		result = ERROR_NOT_ENOUGH_MEMORY;
-	else
-	{
-		result = fs_stat(expanded, &buf);
-		if (0 == result)
-			packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
-					sizeof(buf));
+		goto out;
 	}
 
-	// Set the result and transmit the response
+	expanded = fs_expand_path(filePath);
+	if (expanded == NULL) {
+		result = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
+
+	result = fs_stat(expanded, &buf);
+	if (0 == result) {
+		packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
+	}
+
+	free(expanded);
+
+out:
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	if (expanded)
-		free(expanded);
-
-	return result;
+	return packet_transmit(remote, response, NULL);
 }
 
 /*
  * Removes the supplied file from disk
  *
- * TLVs:
- *
  * req: TLV_TYPE_FILE_PATH - The file that is to be removed.
  */
 DWORD request_fs_delete_file(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
-	LPCSTR path;
+	char *path;
 	DWORD result = ERROR_SUCCESS;
 
 	path = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
 
-	if (!path)
+	if (!path) {
 		result = ERROR_INVALID_PARAMETER;
-#ifdef _WIN32
-	else if (!DeleteFile(path))
-#else
-	else if (unlink(path))
-#endif
-		result = GetLastError();
+	} else {
+		result = fs_delete_file(path);
+	}
 
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
+	return packet_transmit(remote, response, NULL);
 }
 
 /*
@@ -328,164 +286,107 @@ DWORD request_fs_file_expand_path(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
 	DWORD result = ERROR_SUCCESS;
-	LPSTR expanded = NULL;
-	LPSTR regular;
+	char *expanded = NULL;
+	char *regular;
 
 	regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
+	if (regular == NULL) {
+		result = ERROR_INVALID_PARAMETER;
+		goto out;
+	}
 
-	do
-	{
-		// No regular path?
-		if (!regular)
-		{
-			result = ERROR_INVALID_PARAMETER;
-			break;
-		}
+	// Allocate storage for the expanded path
+	expanded = fs_expand_path(regular);
+	if (expanded == NULL) {
+		result = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
 
-		// Allocate storage for the expanded path
-		if (!(expanded = fs_expand_path(regular)))
-		{
-			result = ERROR_NOT_ENOUGH_MEMORY;
-			break;
-		}
-
-		packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
-
-	} while (0);
-
-	// Transmit the response to the mofo
-	packet_transmit_response(result, remote, response);
-
-	if (expanded)
-		free(expanded);
-
-	return ERROR_SUCCESS;
+	packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);
+	free(expanded);
+out:
+	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
+	return packet_transmit(remote, response, NULL);
 }
 
 
 /*
  * Returns the MD5 hash for a specified file path
  *
- * TLVs:
- *
  * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
  */
 DWORD request_fs_md5(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
-	LPCSTR filePath;
-	LPSTR expanded = NULL;
+	char *filePath;
 	DWORD result = ERROR_SUCCESS;
 	MD5_CTX context;
+
 	FILE *fd;
 	size_t ret;
 	unsigned char buff[16384];
-	unsigned char hash[128];
+	unsigned char hash[MD5_DIGEST_LENGTH + 1] = {0};
 
 	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
 
-	// Validate parameters
-	if (!filePath)
-		result = ERROR_INVALID_PARAMETER;
-	else if (!(expanded = fs_expand_path(filePath)))
-		result = ERROR_NOT_ENOUGH_MEMORY;
-	else
-	{
-		do {
-			MD5_Init(&context);
-			fd = fopen(expanded, "rb");
-			if (! fd) {
-				result = GetLastError();
-				break;
-			}
+	result = fs_fopen(filePath, "rb", &fd);
+	if (result == ERROR_SUCCESS) {
 
-			while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
-				MD5_Update(&context, buff, ret);
-			}
+		MD5_Init(&context);
 
-			fclose(fd);
-			MD5_Final(hash, &context);
+		while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
+			MD5_Update(&context, buff, ret);
+		}
 
-			// One byte extra for the NULL
-			packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 17);
-		} while(0);
+		MD5_Final(hash, &context);
+
+		packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
+
+		fclose(fd);
 	}
 
-	// Set the result and transmit the response
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	if (expanded)
-		free(expanded);
-
-	return ERROR_SUCCESS;
+	return packet_transmit(remote, response, NULL);
 }
 
 
-
 /*
  * Returns the SHA1 hash for a specified file path
  *
- * TLVs:
- *
  * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
  */
 DWORD request_fs_sha1(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
-	LPCSTR filePath;
-	LPSTR expanded = NULL;
+	char *filePath;
 	DWORD result = ERROR_SUCCESS;
 	SHA_CTX context;
 
 	FILE *fd;
 	size_t ret;
 	unsigned char buff[16384];
-	unsigned char hash[128];
+	unsigned char hash[SHA_DIGEST_LENGTH + 1] = {0};
 
 	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
 
-	// Validate parameters
-	if (!filePath)
-		result = ERROR_INVALID_PARAMETER;
-	else if (!(expanded = fs_expand_path(filePath)))
-		result = ERROR_NOT_ENOUGH_MEMORY;
-	else
-	{
-		do {
-			SHA1_Init(&context);
-			fd = fopen(expanded, "rb");
-			if (! fd) {
-				result = GetLastError();
-				break;
-			}
+	result = fs_fopen(filePath, "rb", &fd);
+	if (result == ERROR_SUCCESS) {
+		SHA1_Init(&context);
 
-			while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
-				SHA1_Update(&context, buff, ret);
-			}
+		while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
+			SHA1_Update(&context, buff, ret);
+		}
 
-			fclose(fd);
-			SHA1_Final(hash, &context);
+		fclose(fd);
+		SHA1_Final(hash, &context);
 
-			// One byte extra for the NULL
-			packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 21);
-		} while(0);
+		packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));
 	}
 
-	// Set the result and transmit the response
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	if (expanded)
-		free(expanded);
-
-	return ERROR_SUCCESS;
+	return packet_transmit(remote, response, NULL);
 }
 
-
-
 /*
  * Copies source file path to destination
  *
@@ -495,25 +396,19 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet)
 {
 	Packet *response = packet_create_response(packet);
 	DWORD result = ERROR_SUCCESS;
-	LPCSTR oldpath;
-	LPCSTR newpath;
+	char *oldpath;
+	char *newpath;
 
 	oldpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_NAME);
 	newpath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
 
-	if (!oldpath)
+	if (!oldpath) {
 		result = ERROR_INVALID_PARAMETER;
-#ifdef _WIN32
-	else if (!MoveFile(oldpath,newpath))
-#else
-	else if (rename(oldpath,newpath))
-#endif
-		result = GetLastError();
+	} else {
+		result = fs_move(oldpath, newpath);
+	}
 
 	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
-
-	packet_transmit(remote, response, NULL);
-
-	return ERROR_SUCCESS;
+	return packet_transmit(remote, response, NULL);
 }
 
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs.h b/c/meterpreter/source/extensions/stdapi/server/fs/fs.h
index 517fc961..3d1ccf4a 100644
--- a/c/meterpreter/source/extensions/stdapi/server/fs/fs.h
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs.h
@@ -1,6 +1,8 @@
 #ifndef _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
 #define _METERPRETER_SOURCE_EXTENSION_STDAPI_STDAPI_SERVER_FS_FS_H
 
+#include <stdint.h>
+
 LPSTR fs_expand_path(LPCSTR regular);
 
 /*
@@ -25,33 +27,4 @@ DWORD request_fs_file_move(Remote *remote, Packet *packet);
  */
 DWORD request_fs_file_channel_open(Remote *remote, Packet *packet);
 
-
-
-/*
- * Stat structures on Windows and various Unixes are all slightly different.
- * Use this as a means of standardization so the client has some hope of
- * understanding what the stat'd file really is.
- */
-struct meterp_stat {
-    unsigned int   st_dev;
-    unsigned short st_ino;
-    unsigned short st_mode;
-    unsigned short st_nlink;
-    unsigned short st_uid;
-    unsigned short st_gid;
-    unsigned short pad;
-    unsigned int   st_rdev;
-    unsigned int   st_size;
-    /*
-     * These are always 64-bits on Windows and usually 32-bits on Linux.  Force
-     * them to be the same size everywhere.
-     */
-    unsigned long long st_atime;
-    unsigned long long st_mtime;
-    unsigned long long st_ctime;
-};
-
-int fs_stat(LPCSTR filename, struct meterp_stat *buf);
-
-
 #endif
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h b/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h
new file mode 100644
index 00000000..4a6b615b
--- /dev/null
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_local.h
@@ -0,0 +1,68 @@
+#ifndef _FS_LOCAL_H
+#define _FS_LOCAL_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#define FS_SEPARATOR "\\"
+#define FS_MAX_PATH  32768
+#else
+#define FS_SEPARATOR "/"
+#define FS_MAX_PATH  PATH_MAX
+#endif
+
+/*
+ * Stat structures on Windows and various Unixes are all slightly different.
+ * Use this as a means of standardization so the client has some hope of
+ * understanding what the stat'd file really is.
+ */
+struct meterp_stat {
+    uint32_t st_dev;
+    uint16_t st_ino;
+    uint16_t st_mode;
+    uint16_t st_nlink;
+    uint16_t st_uid;
+    uint16_t st_gid;
+    uint16_t pad;
+    uint32_t st_rdev;
+    uint32_t st_size;
+    /*
+     * These are always 64-bits on Windows and usually 32-bits on Linux.  Force
+     * them to be the same size everywhere.
+     */
+    uint64_t st_atime;
+    uint64_t st_mtime;
+    uint64_t st_ctime;
+};
+
+typedef void (*fs_ls_cb_t)(void *arg, char *name, char *short_name, char *path);
+
+int fs_chdir(const char *directory);
+
+int fs_delete_dir(const char *directory);
+
+int fs_delete_file(const char *path);
+
+/*
+ * Returns an expanded file path that must be freed
+ */
+char * fs_expand_path(const char *regular);
+
+int fs_fopen(const char *path, const char *mode, FILE **f);
+
+int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg);
+
+int fs_getwd(char **directory);
+
+int fs_mkdir(const char *directory);
+
+int fs_move(const char *oldpath, const char *newpath);
+
+/*
+ * Fills the platform-independent meterp_stat buf with data from the
+ * platform-dependent stat()
+ */
+int fs_stat(char *filename, struct meterp_stat *buf);
+
+#endif
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c
new file mode 100644
index 00000000..3fc9054a
--- /dev/null
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_posix.c
@@ -0,0 +1,126 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "precomp.h"
+#include "fs_local.h"
+
+int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
+{
+	struct meterp_stat s;
+	struct dirent *data;
+	char path[FS_MAX_PATH];
+
+	DIR *ctx = opendir(directory);
+	if (ctx == NULL) {
+		return errno;
+	}
+
+	while ((data = readdir(ctx))) {
+
+		snprintf(path, sizeof(path), "%s/%s", directory, data->d_name);
+
+		cb(arg, data->d_name, NULL, path);
+	}
+
+	closedir(ctx);
+	return ERROR_SUCCESS;
+}
+
+int fs_chdir(const char *directory)
+{
+	if (chdir(directory) == -1) {
+		return errno;
+	}
+	return ERROR_SUCCESS;
+}
+
+int fs_delete_file(const char *path)
+{
+	if (unlink(path) == -1) {
+		return errno;
+	}
+	return ERROR_SUCCESS;
+}
+
+int fs_delete_dir(const char *directory)
+{
+	if (rmdir(directory) == -1) {
+		return errno;
+	}
+	return ERROR_SUCCESS;
+}
+
+char * fs_expand_path(const char *regular)
+{
+	return strdup(regular);
+}
+
+int fs_getwd(char **directory)
+{
+	char dir[FS_MAX_PATH];
+	if (getcwd(dir, sizeof(dir)) == NULL) {
+		return errno;
+	}
+	*directory = strdup(dir);
+	return *directory == NULL ? ERROR_NOT_ENOUGH_MEMORY : ERROR_SUCCESS;
+}
+
+int fs_mkdir(const char *directory)
+{
+	if (mkdir(directory, 0777) == -1) {
+		return errno;
+	}
+	return ERROR_SUCCESS;
+}
+
+int fs_fopen(const char *path, const char *mode, FILE **f)
+{
+	int rc = 0;
+
+	if (path == NULL || f == NULL) {
+		return ERROR_INVALID_PARAMETER;
+	}
+
+	*f = fopen(path, mode);
+	if (*f == NULL) {
+		rc = errno;
+	}
+
+	return rc;
+}
+
+int fs_move(const char *oldpath, const char *newpath)
+{
+	if (rename(oldpath, newpath) == -1) {
+		return errno;
+	}
+	return ERROR_SUCCESS;
+}
+
+int fs_stat(char *filename, struct meterp_stat *buf)
+{
+	struct stat sbuf;
+
+	if (stat(filename, &sbuf) == -1) {
+		return errno;
+	}
+
+	buf->st_dev   = sbuf.st_dev;
+	buf->st_ino   = sbuf.st_ino;
+	buf->st_mode  = sbuf.st_mode;
+	buf->st_nlink = sbuf.st_nlink;
+	buf->st_uid   = sbuf.st_uid;
+	buf->st_gid   = sbuf.st_gid;
+	buf->st_rdev  = sbuf.st_rdev;
+	buf->st_size  = sbuf.st_size;
+	buf->st_atime = sbuf.st_atime;
+	buf->st_mtime = sbuf.st_mtime;
+	buf->st_ctime = sbuf.st_ctime;
+
+	return ERROR_SUCCESS;
+}
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c
deleted file mode 100644
index 588298b5..00000000
--- a/c/meterpreter/source/extensions/stdapi/server/fs/fs_util.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "precomp.h"
-#include "fs.h"
-#include <sys/stat.h>
-
-/*
- * Returns an expanded file path that must be freed
- */
-LPSTR fs_expand_path(LPCSTR regular)
-{
-#ifdef _WIN32
-	DWORD expandedFilePathSize = 32768;
-	LPSTR expandedFilePath = NULL;
-
-	do
-	{
-		// Expand the file path
-		if (!(expandedFilePath = (LPSTR)malloc(expandedFilePathSize)))
-			break;
-
-		// Expand the file path being accessed
-		if (!ExpandEnvironmentStrings(regular, expandedFilePath,
-				expandedFilePathSize - 1))
-		{
-			free(expandedFilePath);
-
-			expandedFilePath = 0;
-
-			break;
-		}
-
-		expandedFilePath[expandedFilePathSize - 1] = 0;
-
-	} while (0);	
-
-	return expandedFilePath;
-#else /* Hack to make it work with existing code under *nix */
-	char *expandedFilePath;
-	DWORD expandedFilePathSize = strlen(regular)+1;
-	expandedFilePath = malloc(expandedFilePathSize);
-	strncpy(expandedFilePath, regular, expandedFilePathSize);
-	expandedFilePath[expandedFilePathSize - 1] = '\0';
-	return expandedFilePath;
-#endif
-}
-
-/*
- * Fills the platform-independent meterp_stat buf with data from the platform-dependent stat()
- */
-int fs_stat(LPCSTR filename, struct meterp_stat *buf) {
-	struct stat sbuf;
-	int ret;
-
-	ret = stat(filename, &sbuf);
-
-	if (ret == 0) {
-		buf->st_dev   = sbuf.st_dev;
-		buf->st_ino   = sbuf.st_ino;
-		buf->st_mode  = sbuf.st_mode;
-		buf->st_nlink = sbuf.st_nlink;
-		buf->st_uid   = sbuf.st_uid;
-		buf->st_gid   = sbuf.st_gid;
-		buf->st_rdev  = sbuf.st_rdev;
-		buf->st_size  = sbuf.st_size;
-		buf->st_atime = (unsigned long long)sbuf.st_atime;
-		buf->st_mtime = (unsigned long long)sbuf.st_mtime;
-		buf->st_ctime = (unsigned long long)sbuf.st_ctime;
-		return 0;
-	} else {
-#ifdef _WIN32
-		return GetLastError();
-#else
-		return errno;
-#endif
-	}
-}
diff --git a/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c
new file mode 100644
index 00000000..ada29181
--- /dev/null
+++ b/c/meterpreter/source/extensions/stdapi/server/fs/fs_win.c
@@ -0,0 +1,339 @@
+#include <sys/stat.h>
+
+#include "fs_local.h"
+#include "precomp.h"
+
+static wchar_t *utf8_to_wchar(const char *in)
+{
+	wchar_t *out;
+	int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, in, -1, NULL, 0);
+	if (len <= 0) {
+		return NULL;
+	}
+
+	out = calloc(len, sizeof(wchar_t));
+	if (out == NULL) {
+		return NULL;
+	}
+
+	if (MultiByteToWideChar(CP_UTF8, 0, in, -1, out, len) == 0) {
+		free(out);
+		out = NULL;
+	}
+
+	return out;
+}
+
+static char *wchar_to_utf8(const wchar_t *in)
+{
+	char *out;
+	int len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL);
+	if (len <= 0) {
+		return NULL;
+	}
+
+	out = calloc(len, sizeof(char));
+	if (out == NULL) {
+		return NULL;
+	}
+
+	if (WideCharToMultiByte(CP_UTF8, 0, in, -1, out, len, NULL, FALSE) == 0) {
+		free(out);
+		out = NULL;
+	}
+
+	return out;
+}
+
+char * fs_expand_path(const char *regular)
+{
+	wchar_t expanded_path[FS_MAX_PATH];
+	wchar_t *regular_w;
+
+	regular_w = utf8_to_wchar(regular);
+	if (regular_w == NULL) {
+		return NULL;
+	}
+
+	if (ExpandEnvironmentStringsW(regular_w, expanded_path, FS_MAX_PATH) == 0) {
+		free(regular_w);
+		return NULL;
+	}
+
+	free(regular_w);
+
+	return wchar_to_utf8(expanded_path);
+}
+
+int fs_ls(const char *directory, fs_ls_cb_t cb, void *arg)
+{
+	DWORD result = 0;
+	LPSTR expanded = NULL;
+	LPSTR baseDirectory = NULL;
+	char tempDirectory[FS_MAX_PATH];
+
+	_snprintf(tempDirectory, sizeof(tempDirectory), "%s", directory);
+
+	/*
+	 * If there is not wildcard mask on the directory, create a version of the
+	 * directory with a mask appended
+	 */
+	if (strrchr(directory, '*') == NULL) {
+		_snprintf(tempDirectory, sizeof(tempDirectory), "%s\\*",
+				directory);
+
+		baseDirectory = _strdup(directory);
+		if (baseDirectory == NULL) {
+			result = ERROR_NOT_ENOUGH_MEMORY;
+			goto out;
+		}
+
+	} else {
+		/*
+		 * Otherwise, if it does have an asterisk, we need to scan back
+		 * and find the base directory.  If there is no slash, it means
+		 * we're listing the cwd.
+		 */
+		PCHAR slash = strrchr(directory, '\\');
+		if (slash) {
+			*slash = 0;
+			baseDirectory = _strdup(directory);
+			if (baseDirectory == NULL) {
+				result = ERROR_NOT_ENOUGH_MEMORY;
+				goto out;
+			}
+			*slash = '\\';
+		}
+	}
+
+	expanded = fs_expand_path(tempDirectory);
+	if (expanded == NULL) {
+		result = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
+
+	WIN32_FIND_DATAW data;
+	wchar_t *path_w = utf8_to_wchar(expanded);
+	if (path_w == NULL) {
+		result = GetLastError();
+		goto out;
+	}
+
+	HANDLE ctx = FindFirstFileW(path_w, &data);
+	if (ctx == NULL) {
+		result = GetLastError();
+		goto out;
+	}
+
+	do {
+		if (ctx == INVALID_HANDLE_VALUE) {
+			result = GetLastError();
+			break;
+		}
+
+		char *filename = wchar_to_utf8(data.cFileName);
+		char *short_filename = wchar_to_utf8(data.cAlternateFileName);
+		char path[FS_MAX_PATH];
+
+		if (baseDirectory) {
+			_snprintf(path, sizeof(path), "%s\\%s", baseDirectory, filename);
+		} else {
+			_snprintf(path, sizeof(path), "%s", filename);
+		}
+
+		cb(arg, filename, short_filename, path);
+
+		free(filename);
+		free(short_filename);
+
+	} while (FindNextFileW(ctx, &data));
+
+	/*
+	 * Clean up resources
+	 */
+	FindClose(ctx);
+	free(expanded);
+out:
+	free(baseDirectory);
+	free(path_w);
+	return result;
+}
+
+int fs_chdir(const char *directory)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t *dir_w = utf8_to_wchar(directory);
+
+	if (dir_w == NULL) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	if (SetCurrentDirectoryW(dir_w) == 0) {
+		rc = GetLastError();
+	}
+
+out:
+	free(dir_w);
+	return rc;
+}
+
+int fs_delete_dir(const char *directory)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t *dir_w = utf8_to_wchar(directory);
+
+	if (dir_w == NULL) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	if (RemoveDirectoryW(dir_w) == 0) {
+		rc = GetLastError();
+	}
+
+out:
+	free(dir_w);
+	return rc;
+}
+
+int fs_delete_file(const char *path)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t *path_w = utf8_to_wchar(path);
+
+	if (path_w == NULL) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	if (DeleteFileW(path_w) == 0) {
+		rc = GetLastError();
+	}
+
+out:
+	free(path_w);
+	return rc;
+}
+
+int fs_getwd(char **dir)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t dir_w[FS_MAX_PATH];
+
+	if (GetCurrentDirectoryW(FS_MAX_PATH, dir_w) == 0) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	*dir = wchar_to_utf8(dir_w);
+	if (*dir == NULL) {
+		rc = GetLastError();
+	}
+
+out:
+	return rc;
+}
+
+int fs_move(const char *oldpath, const char *newpath)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t *old_w = utf8_to_wchar(oldpath);
+	wchar_t *new_w = utf8_to_wchar(newpath);
+
+	if ((old_w == NULL) || (new_w == NULL)) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	if (MoveFileW(old_w, new_w) == 0) {
+		rc = GetLastError();
+	}
+
+out:
+	free(old_w);
+	free(new_w);
+	return rc;
+}
+
+int fs_mkdir(const char *directory)
+{
+	int rc = ERROR_SUCCESS;
+	wchar_t *dir_w = utf8_to_wchar(directory);
+
+	if (dir_w == NULL) {
+		rc = GetLastError();
+		goto out;
+	}
+
+	if (CreateDirectoryW(dir_w, NULL) == 0) {
+		rc = GetLastError();
+	}
+
+out:
+	free(dir_w);
+	return rc;
+}
+
+int fs_fopen(const char *path, const char *mode, FILE **f)
+{
+	char *expanded = NULL;
+	int rc = ERROR_SUCCESS;
+
+	if (path == NULL || f == NULL) {
+		return ERROR_INVALID_PARAMETER;
+	}
+
+	if ((expanded = fs_expand_path(path)) == NULL) {
+		return ERROR_NOT_ENOUGH_MEMORY;
+	}
+
+	wchar_t *path_w = utf8_to_wchar(expanded);
+	wchar_t *mode_w = utf8_to_wchar(mode);
+
+	if ((path_w == NULL) || (mode_w == NULL)) {
+		rc = ERROR_NOT_ENOUGH_MEMORY;
+		goto out;
+	}
+
+	*f = _wfopen(path_w, mode_w);
+	if (*f == NULL) {
+		rc = GetLastError();
+	}
+
+out:
+	free(expanded);
+	free(path_w);
+	free(mode_w);
+	return rc;
+}
+
+int fs_stat(char *filename, struct meterp_stat *buf)
+{
+	struct _stat64i32 sbuf;
+
+	wchar_t *filename_w = utf8_to_wchar(filename);
+	if (filename_w == NULL) {
+		return -1;
+	}
+
+	if (_wstat(filename_w, &sbuf) == -1) {
+		return GetLastError();
+	}
+
+	free(filename_w);
+
+	buf->st_dev   = sbuf.st_dev;
+	buf->st_ino   = sbuf.st_ino;
+	buf->st_mode  = sbuf.st_mode;
+	buf->st_nlink = sbuf.st_nlink;
+	buf->st_uid   = sbuf.st_uid;
+	buf->st_gid   = sbuf.st_gid;
+	buf->st_rdev  = sbuf.st_rdev;
+	buf->st_size  = sbuf.st_size;
+	buf->st_atime = sbuf.st_atime;
+	buf->st_mtime = sbuf.st_mtime;
+	buf->st_ctime = sbuf.st_ctime;
+
+	return ERROR_SUCCESS;
+}
diff --git a/c/meterpreter/source/extensions/stdapi/server/stdapi.c b/c/meterpreter/source/extensions/stdapi/server/stdapi.c
index 0e1dde40..6ffcd3fc 100644
--- a/c/meterpreter/source/extensions/stdapi/server/stdapi.c
+++ b/c/meterpreter/source/extensions/stdapi/server/stdapi.c
@@ -216,8 +216,16 @@ DWORD DeinitServerExtension(Remote *remote)
  * @param bufferSize Size of the \c buffer parameter.
  * @return Indication of success or failure.
  */
+#ifdef _WIN32
 DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
+#else
+DWORD GetExtensionName(char* buffer, int bufferSize)
+#endif
 {
+#ifdef _WIN32
 	strncpy_s(buffer, bufferSize, "stdapi", bufferSize - 1);
+#else
+	strncpy(buffer, "stdapi", bufferSize - 1);
+#endif
 	return ERROR_SUCCESS;
 }
diff --git a/c/meterpreter/source/extensions/stdapi/stdapi.h b/c/meterpreter/source/extensions/stdapi/stdapi.h
index 52e7e36a..45b4f0ae 100644
--- a/c/meterpreter/source/extensions/stdapi/stdapi.h
+++ b/c/meterpreter/source/extensions/stdapi/stdapi.h
@@ -23,6 +23,7 @@
 #define TLV_TYPE_FILE_PATH                            MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING,  TLV_TYPE_EXTENSION_STDAPI, 1202 )
 #define TLV_TYPE_FILE_MODE                            MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING,  TLV_TYPE_EXTENSION_STDAPI, 1203 )
 #define TLV_TYPE_FILE_SIZE                            MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT,    TLV_TYPE_EXTENSION_STDAPI, 1204 )
+#define TLV_TYPE_FILE_SHORT_NAME                      MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING,  TLV_TYPE_EXTENSION_STDAPI, 1205 )
 
 #define TLV_TYPE_STAT_BUF                             MAKE_CUSTOM_TLV( TLV_META_TYPE_COMPLEX, TLV_TYPE_EXTENSION_STDAPI, 1220 )
 
diff --git a/c/meterpreter/source/server/posix/remote_dispatch.c b/c/meterpreter/source/server/posix/remote_dispatch.c
index 6873c635..c004cf7a 100644
--- a/c/meterpreter/source/server/posix/remote_dispatch.c
+++ b/c/meterpreter/source/server/posix/remote_dispatch.c
@@ -2,6 +2,7 @@
 #include "metsrv.h"
 
 extern Command *extensionCommands;
+extern PLIST gExtensionList;
 
 DWORD request_core_loadlib(Remote *remote, Packet *packet)
 {
@@ -61,15 +62,37 @@ DWORD request_core_loadlib(Remote *remote, Packet *packet)
 		// call its Init routine
 		if (flags & LOAD_LIBRARY_FLAG_EXTENSION)
 		{
-			DWORD(*init)(Remote *remote);
+			PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
+			if (!pExtension)
+			{
+				res = ERROR_NOT_ENOUGH_MEMORY;
+				break;
+			}
+			//DWORD(*init)(Remote *remote);
+
+			pExtension->init = dlsym(library, "InitServerExtension");
 
-			init = dlsym(library, "InitServerExtension");
 			// Call the init routine in the library
-			if (init)
+			if (pExtension->init)
 			{
 				dprintf("calling InitServerExtension");
-				res = init(remote);
+				res = pExtension->init(remote);
+				pExtension->getname = dlsym(library, "GetExtensionName");
+
+
+				pExtension->deinit = dlsym(library, "DeinitServerExtension");
+
+				if (pExtension->getname)
+				{
+					pExtension->getname(pExtension->name, sizeof(pExtension->name));
+				}
+				list_push(gExtensionList, pExtension);
 			}
+			else
+			{
+				free(pExtension);
+			}
+
 			if (response)
 			{
 				for (command = extensionCommands; command != first; command = command->next)
diff --git a/c/meterpreter/source/server/remote_dispatch_common.c b/c/meterpreter/source/server/remote_dispatch_common.c
index a044e886..f8e9c1fa 100644
--- a/c/meterpreter/source/server/remote_dispatch_common.c
+++ b/c/meterpreter/source/server/remote_dispatch_common.c
@@ -7,6 +7,8 @@ extern HINSTANCE hAppInstance;
 
 PLIST gExtensionList = NULL;
 
+DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket);
+
 // Dispatch table
 Command customCommands[] = 
 {
@@ -15,6 +17,56 @@ Command customCommands[] =
 	COMMAND_TERMINATOR
 };
 
+typedef struct _EnumExtensions
+{
+	Packet* pResponse;
+	char* lpExtensionName;
+} EnumExtensions, * PEnumExtensions;
+
+BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
+{
+	PEnumExtensions pEnum = (PEnumExtensions)pState;
+	Command* command = NULL;
+
+	if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
+	{
+		PEXTENSION pExt = (PEXTENSION)pData;
+		if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
+		{
+			dprintf("[LISTEXT] Found extension: %s", pExt->name);
+			for (command = pExt->start; command != pExt->end; command = command->next)
+			{
+				packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
+			}
+
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
+{
+	BOOL bResult = FALSE;
+	Packet* pResponse = packet_create_response(pPacket);
+
+	if (pResponse != NULL)
+	{
+		EnumExtensions enumExt;
+		enumExt.pResponse = pResponse;
+		enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
+
+		dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
+		// Start by enumerating the names of the extensions
+		bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
+
+		packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
+		packet_transmit(pRemote, pResponse, NULL);
+	}
+
+	return ERROR_SUCCESS;
+}
+
 /*
  * Registers custom command handlers
  */
@@ -38,7 +90,10 @@ VOID deregister_dispatch_routines(Remote * remote)
 			break;
 		}
 
-		extension->deinit(remote);
+		if (extension->deinit)
+		{
+			extension->deinit(remote);
+		}
 
 		free(extension);
 	}
diff --git a/c/meterpreter/source/server/win/remote_dispatch.c b/c/meterpreter/source/server/win/remote_dispatch.c
index 68148bfe..2f3588bc 100644
--- a/c/meterpreter/source/server/win/remote_dispatch.c
+++ b/c/meterpreter/source/server/win/remote_dispatch.c
@@ -8,54 +8,6 @@ extern PLIST gExtensionList;
 // see common/base.c
 extern Command *extensionCommands;
 
-typedef struct _EnumExtensions
-{
-	Packet* pResponse;
-	char* lpExtensionName;
-} EnumExtensions, * PEnumExtensions;
-
-BOOL ext_cmd_callback(LPVOID pState, LPVOID pData)
-{
-	PEnumExtensions pEnum = (PEnumExtensions)pState;
-
-	if (pEnum != NULL && pEnum->pResponse != NULL && pData != NULL)
-	{
-		PEXTENSION pExt = (PEXTENSION)pData;
-		if (pExt->name[0] != '\0' && pEnum->lpExtensionName != NULL && strcmp(pExt->name, pEnum->lpExtensionName) == 0)
-		{
-			dprintf("[LISTEXT] Found extension: %s", pExt->name);
-			for (Command* command = pExt->start; command != pExt->end; command = command->next)
-			{
-				packet_add_tlv_string(pEnum->pResponse, TLV_TYPE_STRING, command->method);
-			}
-
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-DWORD request_core_enumextcmd(Remote* pRemote, Packet* pPacket)
-{
-	Packet* pResponse = packet_create_response(pPacket);
-
-	if (pResponse != NULL)
-	{
-		EnumExtensions enumExt;
-		enumExt.pResponse = pResponse;
-		enumExt.lpExtensionName = packet_get_tlv_value_string(pPacket, TLV_TYPE_STRING);
-
-		dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
-		// Start by enumerating the names of the extensions
-		BOOL bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);
-
-		packet_add_tlv_uint(pResponse, TLV_TYPE_RESULT, ERROR_SUCCESS);
-		packet_transmit(pRemote, pResponse, NULL);
-	}
-
-	return ERROR_SUCCESS;
-}
-
 DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote* pRemote, Packet* pResponse, Command* pFirstCommand)
 {
 	DWORD dwResult = ERROR_OUTOFMEMORY;
@@ -129,6 +81,8 @@ DWORD initialise_extension(HMODULE hLibrary, BOOL bLibLoadedReflectivly, Remote*
 	return dwResult;
 }
 
+
+
 /*
  * core_loadlib
  * ------------
diff --git a/c/meterpreter/workspace/ext_server_stdapi/Makefile b/c/meterpreter/workspace/ext_server_stdapi/Makefile
index 8c59c9de..9e18aa12 100644
--- a/c/meterpreter/workspace/ext_server_stdapi/Makefile
+++ b/c/meterpreter/workspace/ext_server_stdapi/Makefile
@@ -9,7 +9,7 @@ CFLAGS+= -I../../source/extensions/stdapi/server
 objects = \
 	server/fs/dir.o \
 	server/fs/file.o \
-	server/fs/fs_util.o \
+	server/fs/fs_posix.o \
 	server/general.o \
 	server/net/config/interface.o \
 	server/net/config/route.o \
diff --git a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj
index f41ef2c1..859a89cb 100644
--- a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj
+++ b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj
@@ -633,7 +633,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
     </ClCompile>
     <ClCompile Include="..\..\source\extensions\stdapi\server\fs\dir.c" />
     <ClCompile Include="..\..\source\extensions\stdapi\server\fs\file.c" />
-    <ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_util.c" />
+    <ClCompile Include="..\..\source\extensions\stdapi\server\fs\fs_win.c" />
     <ClCompile Include="..\..\source\extensions\stdapi\server\fs\search.c" />
     <ClCompile Include="..\..\source\extensions\stdapi\server\net\net.c" />
     <ClCompile Include="..\..\source\extensions\stdapi\server\net\config\interface.c" />
@@ -687,6 +687,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
     <ClInclude Include="..\..\source\extensions\stdapi\server\webcam\bmp2jpeg.h" />
     <ClInclude Include="..\..\source\extensions\stdapi\server\webcam\webcam.h" />
     <ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs.h" />
+    <ClInclude Include="..\..\source\extensions\stdapi\server\fs\fs_local.h" />
     <ClInclude Include="..\..\source\extensions\stdapi\server\fs\search.h" />
   </ItemGroup>
   <ItemGroup>
@@ -714,4 +715,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho
   <ImportGroup Label="ExtensionTargets">
     <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>