aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier S. Pedro <javier@javispedro.com>2013-01-06 02:04:56 +0100
committerJavier S. Pedro <javier@javispedro.com>2013-01-06 02:04:56 +0100
commit2f7314162c2a63a1015cc969bbe55319b3c99077 (patch)
tree5410d957743c6a4d6eb15a57bc961d815d690062
parentdc5428be5c92f77a9bb8fb11d1a1b75cd44052d7 (diff)
downloadrodisc-client-win32-master.tar.gz
rodisc-client-win32-master.zip
initial importHEADmaster
-rw-r--r--httpdisk.h51
-rw-r--r--list.h21
-rw-r--r--main.c347
-rw-r--r--main.rcbin0 -> 4658 bytes
-rw-r--r--mounter.c350
-rw-r--r--mounter.h7
-rw-r--r--resource.hbin0 -> 1172 bytes
-rw-r--r--rodisc-client.sln26
-rw-r--r--rodisc-client.vcxproj222
9 files changed, 1024 insertions, 0 deletions
diff --git a/httpdisk.h b/httpdisk.h
new file mode 100644
index 0000000..a412544
--- /dev/null
+++ b/httpdisk.h
@@ -0,0 +1,51 @@
+/*
+ HTTP virtual disk driver for Windows.
+ Copyright (C) 1999-2009 Bo Brantén.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _HTTP_DISK_
+#define _HTTP_DISK_
+
+#ifndef __T
+#ifdef _NTDDK_
+#define __T(x) L ## x
+#else
+#define __T(x) x
+#endif
+#endif
+
+#ifndef _T
+#define _T(x) __T(x)
+#endif
+
+#define DEVICE_BASE_NAME _T("\\HttpDisk")
+#define DEVICE_DIR_NAME _T("\\Device") DEVICE_BASE_NAME
+#define DEVICE_NAME_PREFIX DEVICE_DIR_NAME _T("\\Http")
+
+#define FILE_DEVICE_HTTP_DISK 0x8000
+
+#define IOCTL_HTTP_DISK_CONNECT CTL_CODE(FILE_DEVICE_HTTP_DISK, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_HTTP_DISK_DISCONNECT CTL_CODE(FILE_DEVICE_HTTP_DISK, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+typedef struct _HTTP_DISK_INFORMATION {
+ ULONG Address;
+ USHORT Port;
+ UCHAR DriveLetter;
+ USHORT HostNameLength;
+ UCHAR HostName[256];
+ USHORT FileNameLength;
+ UCHAR FileName[1];
+} HTTP_DISK_INFORMATION, *PHTTP_DISK_INFORMATION;
+
+#endif
diff --git a/list.h b/list.h
new file mode 100644
index 0000000..571b6d7
--- /dev/null
+++ b/list.h
@@ -0,0 +1,21 @@
+#ifndef LIST_H
+#define LIST_H
+
+#define list_add(Type, Head, Item) do {\
+ Item->next = Head; \
+ Head = Item; \
+ } while (0);
+
+#define list_remove(Type, Head, Item) do {\
+ Type **p; \
+ for (p = &Head; *p; p = &((*p)->next)) { \
+ if (*p = Item) { \
+ *p = Item->next; \
+ } \
+ } \
+ } while (0);
+
+#define list_foreach(Type, Head, Item) \
+ for (Item = Head; Item; Item = Item->next)
+
+#endif \ No newline at end of file
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..5fa5f54
--- /dev/null
+++ b/main.c
@@ -0,0 +1,347 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <assert.h>
+#include <Windows.h>
+#include <CommCtrl.h>
+#include <WinSock2.h>
+#include <dns_sd.h>
+
+#include "resource.h"
+#include "list.h"
+#include "mounter.h"
+
+#define DIALOG_CAPTIONS "Remote optical disc"
+#define DRIVE_LETTER 'O'
+#define EVENT_SOCKET_ACTIVITY (WM_APP+0)
+
+typedef struct _DNSSocket {
+ struct _DNSSocket *next;
+ SOCKET sock;
+ DNSServiceRef ref;
+} DNSSocket;
+
+typedef struct _Disc {
+ struct _Disc *next;
+ struct _Host *host;
+
+ char *name;
+ int list_index;
+} Disc;
+
+typedef struct _Host {
+ struct _Host *next;
+
+ DNSServiceRef resolve_ref;
+ DNSServiceRef query_ref;
+
+ char *name;
+ USHORT port;
+
+ struct _Disc discs;
+} Host;
+
+static HWND dialog_hwnd = NULL;
+static DNSServiceRef search_ref = NULL;
+static DNSSocket *sock_list = NULL;
+static Host *host_list = NULL;
+
+static void __cdecl odprintf(const char *format, ...)
+{
+ char buf[4096], *p = buf;
+ va_list args;
+ int n;
+
+ va_start(args, format);
+ n = _vsnprintf(p, sizeof buf - 3, format, args); // buf-3 is room for CR/LF/NUL
+ va_end(args);
+
+ p += (n < 0) ? sizeof buf - 3 : n;
+
+ while ( p > buf && isspace(p[-1]) )
+ *--p = '\0';
+
+ *p++ = '\r';
+ *p++ = '\n';
+ *p = '\0';
+
+ OutputDebugString(buf);
+}
+
+static void dnssocket_monitor(DNSServiceRef ref)
+{
+ DNSSocket *d = (DNSSocket*) malloc(sizeof(DNSSocket));
+ int err;
+ d->ref = ref;
+ d->sock = (SOCKET) DNSServiceRefSockFD(ref);
+
+ assert(d->ref);
+
+ err = WSAAsyncSelect(d->sock, dialog_hwnd, EVENT_SOCKET_ACTIVITY, FD_READ | FD_CLOSE);
+ if (err) {
+ MessageBox(dialog_hwnd, "Failed to start WSAAsyncSelect", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ free(d);
+ return;
+ }
+
+ list_add(DNSSocket, sock_list, d);
+}
+
+static void dnssocket_close(DNSServiceRef ref)
+{
+ DNSSocket **p;
+ for (p = &sock_list; *p; p = &((*p)->next)) {
+ if ((*p)->ref == ref) {
+ DNSSocket *d = *p;
+ *p = d->next;
+ DNSServiceRefDeallocate(d->ref);
+ free(d);
+ return;
+ }
+ }
+}
+
+static void dnssocket_fire(SOCKET sock)
+{
+ DNSSocket *d;
+ list_foreach(DNSSocket, sock_list, d) {
+ if (d->sock == sock) {
+ DNSServiceProcessResult(d->ref);
+ return;
+ }
+ }
+}
+
+static Disc *disc_alloc()
+{
+ return (Disc*) calloc(1, sizeof(Disc));
+}
+
+static void disc_free(Disc *disc)
+{
+ if (disc->name) {
+ free((void*) disc->name);
+ }
+ free(disc);
+}
+
+static Host *host_alloc()
+{
+ return (Host*) calloc(1, sizeof(Host));
+}
+
+static void host_free(Host *host)
+{
+ if (host->resolve_ref) {
+ dnssocket_close(host->resolve_ref);
+ }
+ if (host->query_ref) {
+ dnssocket_close(host->query_ref);
+ }
+ if (host->name) {
+ free((void*) host->name);
+ }
+ free(host);
+}
+
+static void center_dialog(HWND hwndDlg)
+{
+ HWND desktop = GetDesktopWindow();
+ RECT rc, rcDlg, rcOwner;
+
+ GetWindowRect(desktop, &rcOwner);
+ GetWindowRect(hwndDlg, &rcDlg);
+ CopyRect(&rc, &rcOwner);
+
+ OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
+ OffsetRect(&rc, -rc.left, -rc.top);
+ OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
+
+ SetWindowPos(hwndDlg,
+ HWND_TOP,
+ rcOwner.left + (rc.right / 2),
+ rcOwner.top + (rc.bottom / 2),
+ 0, 0, // Ignores size arguments.
+ SWP_NOSIZE);
+}
+
+static int disc_connect(Disc *disc)
+{
+ static char url[1024];
+ _snprintf(url, sizeof(url), "http://%s:%d/%s.dmg", disc->host->name, disc->host->port, disc->name);
+ odprintf("Connecting to URL %s\n", url);
+ return HttpDiskMountUrl(0, url, DRIVE_LETTER, TRUE);
+}
+
+static void CALLBACK query_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
+{
+ Host *host = (Host*) context;
+ DNSServiceErrorType err;
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ if (flags & kDNSServiceFlagsAdd) {
+ int count = TXTRecordGetCount(rdlen, rdata);
+ int i;
+ for (i = 0; i < count; i++) {
+ char *key = (char*)malloc(256);
+ uint8_t value_len;
+ void *value;
+ err = TXTRecordGetItemAtIndex(rdlen, rdata, i, 256, key, &value_len, &value);
+ if (err != kDNSServiceErr_NoError) continue;
+ if (strcmp(key, "sys") == 0) {
+ // Sys record, ignore for now
+ free(key);
+ } else {
+ Disc *disc = disc_alloc();
+ disc->host = host;
+ disc->name = key;
+
+ disc->list_index = SendDlgItemMessage(dialog_hwnd, IDC_LIST, LB_ADDSTRING, 0, (LPARAM) key);
+ SendDlgItemMessage(dialog_hwnd, IDC_LIST, LB_SETITEMDATA, (WPARAM) disc->list_index, (LPARAM) disc);
+ }
+ }
+ }
+ } else {
+ MessageBox(NULL, "Bonjour query error occurred", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ }
+}
+
+static void CALLBACK resolve_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context)
+{
+ Host *host = (Host*)context;
+ DNSServiceErrorType err;
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ odprintf("Resolved %s\n", fullname);
+
+ dnssocket_close(host->resolve_ref);
+ host->resolve_ref = NULL;
+
+ host->name = _strdup(hosttarget);
+ host->port = ntohs(port);
+
+ err = DNSServiceQueryRecord(&host->query_ref, 0, 0, fullname, kDNSServiceType_TXT, kDNSServiceClass_IN, query_reply, host);
+ if (err != kDNSServiceErr_NoError) {
+ MessageBox(dialog_hwnd, "Failed to start DNSServiceQueryRecord", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ return;
+ }
+
+ dnssocket_monitor(host->query_ref);
+ } else {
+ MessageBox(NULL, "Bonjour resolver error occurred", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ }
+}
+
+static void start_resolve(const char *service, const char *regtype, const char *domain)
+{
+ Host *host = host_alloc();
+ DNSServiceErrorType err;
+
+ odprintf("Resolving %s\n", service);
+
+ err = DNSServiceResolve(&host->resolve_ref, 0, 0, service, regtype, domain, resolve_reply, host);
+ if (err != kDNSServiceErr_NoError) {
+ MessageBox(dialog_hwnd, "Failed to start DNSServiceResolve", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ host_free(host);
+ return;
+ }
+
+ dnssocket_monitor(host->resolve_ref);
+
+ list_add(Host, host_list, host);
+}
+
+static void CALLBACK search_reply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context)
+{
+ HWND hwndDlg = (HWND) context;
+
+ if (errorCode == kDNSServiceErr_NoError) {
+ if (flags & kDNSServiceFlagsAdd) {
+ start_resolve(serviceName, regtype, replyDomain);
+ }
+ } else {
+ MessageBox(hwndDlg, "Bonjour browser error occurred", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ }
+}
+
+static void start_search()
+{
+ DNSServiceErrorType err;
+
+ err = DNSServiceBrowse(&search_ref, 0, 0, "_odisk._tcp", NULL, search_reply, NULL);
+ if (err != kDNSServiceErr_NoError) {
+ MessageBox(dialog_hwnd, "Failed to start DNSServiceBrowse", DIALOG_CAPTIONS, MB_ICONWARNING | MB_OK);
+ return;
+ }
+
+ dnssocket_monitor(search_ref);
+}
+
+static void stop_search()
+{
+ dnssocket_close(search_ref);
+}
+
+static void handle_ok()
+{
+ Disc *disc;
+ int sel = SendDlgItemMessage(dialog_hwnd, IDC_LIST, LB_GETCURSEL, 0, 0);
+ if (sel == LB_ERR) {
+ MessageBox(dialog_hwnd, "Please select a disc", DIALOG_CAPTIONS, MB_ICONINFORMATION | MB_OK);
+ return;
+ }
+
+ disc = (Disc*) SendDlgItemMessage(dialog_hwnd, IDC_LIST, LB_GETITEMDATA, (WPARAM) sel, 0);
+ assert(disc);
+ if (disc_connect(disc) == 0) {
+ EndDialog(dialog_hwnd, IDOK);
+ }
+}
+
+static void handle_disconnect()
+{
+ HttpDiskUmount(DRIVE_LETTER);
+}
+
+BOOL CALLBACK ConnectDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ dialog_hwnd = hwnd;
+ center_dialog(hwnd);
+ start_search();
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ handle_ok();
+ return TRUE;
+ case IDCANCEL:
+ EndDialog(hwnd, IDCANCEL);
+ return TRUE;
+ case IDC_DISCONNECT:
+ handle_disconnect();
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ case EVENT_SOCKET_ACTIVITY:
+ dnssocket_fire((SOCKET) wParam);
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ INITCOMMONCONTROLSEX icex;
+ icex.dwSize = sizeof(icex);
+ icex.dwICC = ICC_STANDARD_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_CONNECT), NULL, ConnectDlgProc);
+
+ return EXIT_SUCCESS;
+}
diff --git a/main.rc b/main.rc
new file mode 100644
index 0000000..d296bae
--- /dev/null
+++ b/main.rc
Binary files differ
diff --git a/mounter.c b/mounter.c
new file mode 100644
index 0000000..256b7c4
--- /dev/null
+++ b/mounter.c
@@ -0,0 +1,350 @@
+/*
+ HTTP virtual disk driver for Windows.
+ Copyright (C) 1999-2009 Bo Brantén.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <windows.h>
+#include <winioctl.h>
+#include <winsock2.h>
+#include <shlobj.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "httpdisk.h"
+#include "mounter.h"
+
+static void PrintLastError(const char* Prefix)
+{
+ LPVOID lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ 0,
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+
+ MessageBox(NULL, lpMsgBuf, Prefix, MB_ICONEXCLAMATION | MB_OK);
+ //fprintf(stderr, "%s: %s", Prefix, (LPTSTR) lpMsgBuf);
+
+ LocalFree(lpMsgBuf);
+}
+
+int
+HttpDiskMount(
+ int DeviceNumber,
+ PHTTP_DISK_INFORMATION HttpDiskInformation,
+ BOOLEAN CdImage
+)
+{
+ char VolumeName[] = "\\\\.\\ :";
+ char DriveName[] = " :\\";
+ char DeviceName[255];
+ HANDLE Device;
+ DWORD BytesReturned;
+
+ VolumeName[4] = HttpDiskInformation->DriveLetter;
+ DriveName[0] = HttpDiskInformation->DriveLetter;
+
+ Device = CreateFile(
+ VolumeName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_NO_BUFFERING,
+ NULL
+ );
+
+ if (Device != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(Device);
+ SetLastError(ERROR_BUSY);
+ PrintLastError(&VolumeName[4]);
+ return -1;
+ }
+
+ if (CdImage)
+ {
+ sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
+ }
+ else
+ {
+ sprintf(DeviceName, DEVICE_NAME_PREFIX "Disk" "%u", DeviceNumber);
+ }
+
+ if (!DefineDosDevice(
+ DDD_RAW_TARGET_PATH,
+ &VolumeName[4],
+ DeviceName
+ ))
+ {
+ PrintLastError(&VolumeName[4]);
+ return -1;
+ }
+
+ Device = CreateFile(
+ VolumeName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_NO_BUFFERING,
+ NULL
+ );
+
+ if (Device == INVALID_HANDLE_VALUE)
+ {
+ PrintLastError(&VolumeName[4]);
+ DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
+ return -1;
+ }
+
+ if (!DeviceIoControl(
+ Device,
+ IOCTL_HTTP_DISK_CONNECT,
+ HttpDiskInformation,
+ sizeof(HTTP_DISK_INFORMATION) + HttpDiskInformation->FileNameLength - 1,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL
+ ))
+ {
+ PrintLastError("HttpDisk");
+ DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
+ CloseHandle(Device);
+ return -1;
+ }
+
+ CloseHandle(Device);
+
+ SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATH, DriveName, NULL);
+
+ return 0;
+}
+
+int
+HttpDiskMountUrl(
+ int DeviceNumber,
+ const char * Url,
+ char DriveLetter,
+ BOOLEAN CdImage
+)
+{
+ PHTTP_DISK_INFORMATION HttpDiskInformation;
+ char* FileName;
+ char* PortStr;
+ struct hostent* HostEnt;
+ WSADATA wsaData;
+
+ HttpDiskInformation = (PHTTP_DISK_INFORMATION) malloc(sizeof(HTTP_DISK_INFORMATION) + strlen(Url));
+
+ memset(
+ HttpDiskInformation,
+ 0,
+ sizeof(HTTP_DISK_INFORMATION) + strlen(Url)
+ );
+
+ if (strstr(Url, "//"))
+ {
+ if (strlen(Url) > 7 && !strncmp(Url, "http://", 7))
+ {
+ Url += 7;
+ }
+ else
+ {
+ fprintf(stderr, "Invalid protocol.\n");
+ return -1;
+ }
+ }
+
+ FileName = strstr(Url, "/");
+
+ if (!FileName)
+ {
+ fprintf(stderr, "%s: Invalid url.\n", Url);
+ return -1;
+ }
+
+ strcpy(HttpDiskInformation->FileName, FileName);
+
+ HttpDiskInformation->FileNameLength = (USHORT) strlen(HttpDiskInformation->FileName);
+
+ *FileName = '\0';
+
+ PortStr = strstr(Url, ":");
+
+ if (PortStr)
+ {
+ HttpDiskInformation->Port = htons((USHORT) atoi(PortStr + 1));
+
+ if (HttpDiskInformation->Port == 0)
+ {
+ fprintf(stderr, "%s: Invalid port.\n", PortStr + 1);
+ return -1;
+ }
+
+ *PortStr = '\0';
+ }
+ else
+ {
+ HttpDiskInformation->Port = htons(80);
+ }
+
+ HttpDiskInformation->HostNameLength = (USHORT) strlen(Url);
+
+ if (HttpDiskInformation->HostNameLength > 255)
+ {
+ fprintf(stderr, "%s: Host name to long.\n", Url);
+ return -1;
+ }
+
+ strcpy(HttpDiskInformation->HostName, Url);
+
+ HttpDiskInformation->Address = inet_addr(Url);
+
+ if (HttpDiskInformation->Address == INADDR_NONE)
+ {
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
+ {
+ PrintLastError("HttpDisk");
+ return -1;
+ }
+
+ HostEnt = gethostbyname(Url);
+
+ if (!HostEnt)
+ {
+ PrintLastError(Url);
+ return -1;
+ }
+
+ HttpDiskInformation->Address = ((struct in_addr*) HostEnt->h_addr)->s_addr;
+ }
+
+ HttpDiskInformation->DriveLetter = DriveLetter;
+ return HttpDiskMount(DeviceNumber, HttpDiskInformation, CdImage);
+}
+
+int HttpDiskUmount(char DriveLetter)
+{
+ char VolumeName[] = "\\\\.\\ :";
+ char DriveName[] = " :\\";
+ HANDLE Device;
+ DWORD BytesReturned;
+
+ VolumeName[4] = DriveLetter;
+ DriveName[0] = DriveLetter;
+
+ Device = CreateFile(
+ VolumeName,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_NO_BUFFERING,
+ NULL
+ );
+
+ if (Device == INVALID_HANDLE_VALUE)
+ {
+ PrintLastError(&VolumeName[4]);
+ return -1;
+ }
+
+ if (!DeviceIoControl(
+ Device,
+ FSCTL_LOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL
+ ))
+ {
+ PrintLastError(&VolumeName[4]);
+ CloseHandle(Device);
+ return -1;
+ }
+
+ if (!DeviceIoControl(
+ Device,
+ IOCTL_HTTP_DISK_DISCONNECT,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL
+ ))
+ {
+ PrintLastError("HttpDisk");
+ CloseHandle(Device);
+ return -1;
+ }
+
+ if (!DeviceIoControl(
+ Device,
+ FSCTL_DISMOUNT_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL
+ ))
+ {
+ PrintLastError(&VolumeName[4]);
+ CloseHandle(Device);
+ return -1;
+ }
+
+ if (!DeviceIoControl(
+ Device,
+ FSCTL_UNLOCK_VOLUME,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &BytesReturned,
+ NULL
+ ))
+ {
+ PrintLastError(&VolumeName[4]);
+ CloseHandle(Device);
+ return -1;
+ }
+
+ CloseHandle(Device);
+
+ if (!DefineDosDevice(
+ DDD_REMOVE_DEFINITION,
+ &VolumeName[4],
+ NULL
+ ))
+ {
+ PrintLastError(&VolumeName[4]);
+ return -1;
+ }
+
+ SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATH, DriveName, NULL);
+
+ return 0;
+} \ No newline at end of file
diff --git a/mounter.h b/mounter.h
new file mode 100644
index 0000000..074eec3
--- /dev/null
+++ b/mounter.h
@@ -0,0 +1,7 @@
+#ifndef MOUNTER_H
+#define MOUNTER_H
+
+int HttpDiskMountUrl(int DeviceNumber, const char * Url, char DriveLetter, BOOLEAN CdImage);
+int HttpDiskUmount(char DriveLetter);
+
+#endif \ No newline at end of file
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..f22fe03
--- /dev/null
+++ b/resource.h
Binary files differ
diff --git a/rodisc-client.sln b/rodisc-client.sln
new file mode 100644
index 0000000..65b9d34
--- /dev/null
+++ b/rodisc-client.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rodisc-client", "rodisc-client.vcxproj", "{AA230639-E115-4A44-AA5A-44A61235BA50}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|Win32.ActiveCfg = Debug|Win32
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|Win32.Build.0 = Debug|Win32
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|x64.ActiveCfg = Debug|x64
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Debug|x64.Build.0 = Debug|x64
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|Win32.ActiveCfg = Release|Win32
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|Win32.Build.0 = Release|Win32
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|x64.ActiveCfg = Release|x64
+ {AA230639-E115-4A44-AA5A-44A61235BA50}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/rodisc-client.vcxproj b/rodisc-client.vcxproj
new file mode 100644
index 0000000..ad89d11
--- /dev/null
+++ b/rodisc-client.vcxproj
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AA230639-E115-4A44-AA5A-44A61235BA50}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectName>rodisc-client</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>$(BONJOUR_SDK_HOME)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../mDNSWindows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/NXCOMPAT /DYNAMICBASE /SAFESEH %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>$(BONJOUR_SDK_HOME)/Lib/$(Platform)/dnssd.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)dns-sd.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalManifestDependencies>type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*';%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ </Link>
+ <Manifest />
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>$(BONJOUR_SDK_HOME)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;_DEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../mDNSWindows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/NXCOMPAT /DYNAMICBASE %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>$(BONJOUR_SDK_HOME)/Lib/$(Platform)/dnssd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)dns-sd.exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)dns-sd.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Manifest>
+ <AdditionalManifestFiles>DNS-SD64.manifest;%(AdditionalManifestFiles)</AdditionalManifestFiles>
+ </Manifest>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <OmitFramePointers>true</OmitFramePointers>
+ <AdditionalIncludeDirectories>$(BONJOUR_SDK_HOME)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../mDNSWindows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/NXCOMPAT /DYNAMICBASE /SAFESEH %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>$(BONJOUR_SDK_HOME)/Lib/$(Platform)/dnssd.lib;ws2_32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalManifestDependencies>type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*';%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
+ </Link>
+ <Manifest />
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <OmitFramePointers>true</OmitFramePointers>
+ <AdditionalIncludeDirectories>$(BONJOUR_SDK_HOME)/Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_WIN32;NDEBUG;_CONSOLE;NOT_HAVE_GETOPT;NOT_HAVE_SETLINEBUF;WIN32_LEAN_AND_MEAN;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../../mDNSWindows;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <AdditionalOptions>/NXCOMPAT /DYNAMICBASE %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>$(BONJOUR_SDK_HOME)/Lib/$(Platform)/dnssd.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)dns-sd.exe</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <Manifest>
+ <AdditionalManifestFiles>DNS-SD64.manifest;%(AdditionalManifestFiles)</AdditionalManifestFiles>
+ </Manifest>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="mounter.c" />
+ <ClCompile Include="main.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="httpdisk.h" />
+ <ClInclude Include="list.h" />
+ <ClInclude Include="mounter.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="main.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file