Revert "[httpdisk] Apply WinVBlock-as-usual indentation"
[people/sha0/winvblock.git] / src / httpdisk_util / httpdisk.c
1 /*
2     HTTP Virtual Disk.
3     Copyright (C) 2006 Bo Brantén.
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12     You should have received a copy of the GNU General Public License
13     along with this program; if not, write to the Free Software
14     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15 */
16
17 #include <windows.h>
18 #include <winioctl.h>
19 #include <winsock2.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "httpdisk.h"
23
24 int HttpDiskSyntax(void)
25 {
26     fprintf(stderr, "syntax:\n");
27     fprintf(stderr, "httpdisk /mount  <devicenumber> <url> [/cd] <drive:>\n");
28     fprintf(stderr, "httpdisk /umount <drive:>\n");
29     fprintf(stderr, "\n");
30     fprintf(stderr, "example:\n");
31     fprintf(stderr, "httpdisk /mount  0 http://server.domain.com/path/diskimage.img d:\n");
32     fprintf(stderr, "httpdisk /mount  1 http://server.domain.com/path/cdimage.iso /cd e:\n");
33     fprintf(stderr, "...\n");
34     fprintf(stderr, "httpdisk /umount d:\n");
35     fprintf(stderr, "httpdisk /umount e:\n");
36
37     return -1;
38 }
39
40 void PrintLastError(char* Prefix)
41 {
42     LPVOID lpMsgBuf;
43
44     FormatMessage( 
45         FORMAT_MESSAGE_ALLOCATE_BUFFER |
46         FORMAT_MESSAGE_FROM_SYSTEM |
47         FORMAT_MESSAGE_IGNORE_INSERTS,
48         NULL,
49         GetLastError(),
50         0,
51         (LPTSTR) &lpMsgBuf,
52         0,
53         NULL
54         );
55
56     fprintf(stderr, "%s: %s", Prefix, (LPTSTR) lpMsgBuf);
57
58     LocalFree(lpMsgBuf);
59 }
60
61 int
62 HttpDiskMount(
63     int                     DeviceNumber,
64     PHTTP_DISK_INFORMATION  HttpDiskInformation,
65     char                    DriveLetter,
66     BOOLEAN                 CdImage
67 )
68 {
69     char    VolumeName[] = "\\\\.\\ :";
70     char    DeviceName[255];
71     HANDLE  Device;
72     DWORD   BytesReturned;
73
74     VolumeName[4] = DriveLetter;
75
76     Device = CreateFile(
77         VolumeName,
78         GENERIC_READ | GENERIC_WRITE,
79         FILE_SHARE_READ | FILE_SHARE_WRITE,
80         NULL,
81         OPEN_EXISTING,
82         FILE_FLAG_NO_BUFFERING,
83         NULL
84         );
85
86     if (Device != INVALID_HANDLE_VALUE)
87     {
88         SetLastError(ERROR_BUSY);
89         PrintLastError(&VolumeName[4]);
90         return -1;
91     }
92
93     if (CdImage)
94     {
95         sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
96     }
97     else
98     {
99         sprintf(DeviceName, DEVICE_NAME_PREFIX "Disk" "%u", DeviceNumber);
100     }
101
102     if (!DefineDosDevice(
103         DDD_RAW_TARGET_PATH,
104         &VolumeName[4],
105         DeviceName
106         ))
107     {
108         PrintLastError(&VolumeName[4]);
109         return -1;
110     }
111
112     Device = CreateFile(
113         VolumeName,
114         GENERIC_READ | GENERIC_WRITE,
115         FILE_SHARE_READ | FILE_SHARE_WRITE,
116         NULL,
117         OPEN_EXISTING,
118         FILE_FLAG_NO_BUFFERING,
119         NULL
120         );
121
122     if (Device == INVALID_HANDLE_VALUE)
123     {
124         PrintLastError(&VolumeName[4]);
125         DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
126         return -1;
127     }
128
129     if (!DeviceIoControl(
130         Device,
131         IOCTL_HTTP_DISK_CONNECT,
132         HttpDiskInformation,
133         sizeof(HTTP_DISK_INFORMATION) + HttpDiskInformation->FileNameLength - 1,
134         NULL,
135         0,
136         &BytesReturned,
137         NULL
138         ))
139     {
140         PrintLastError("HttpDisk");
141         DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
142         return -1;
143     }
144
145     return 0;
146 }
147
148 int HttpDiskUmount(char DriveLetter)
149 {
150     char    VolumeName[] = "\\\\.\\ :";
151     HANDLE  Device;
152     DWORD   BytesReturned;
153
154     VolumeName[4] = DriveLetter;
155
156     Device = CreateFile(
157         VolumeName,
158         GENERIC_READ | GENERIC_WRITE,
159         FILE_SHARE_READ | FILE_SHARE_WRITE,
160         NULL,
161         OPEN_EXISTING,
162         FILE_FLAG_NO_BUFFERING,
163         NULL
164         );
165
166     if (Device == INVALID_HANDLE_VALUE)
167     {
168         PrintLastError(&VolumeName[4]);
169         return -1;
170     }
171
172     if (!DeviceIoControl(
173         Device,
174         FSCTL_LOCK_VOLUME,
175         NULL,
176         0,
177         NULL,
178         0,
179         &BytesReturned,
180         NULL
181         ))
182     {
183         PrintLastError(&VolumeName[4]);
184         return -1;
185     }
186
187     if (!DeviceIoControl(
188         Device,
189         IOCTL_HTTP_DISK_DISCONNECT,
190         NULL,
191         0,
192         NULL,
193         0,
194         &BytesReturned,
195         NULL
196         ))
197     {
198         PrintLastError("HttpDisk");
199         return -1;
200     }
201
202     if (!DeviceIoControl(
203         Device,
204         FSCTL_DISMOUNT_VOLUME,
205         NULL,
206         0,
207         NULL,
208         0,
209         &BytesReturned,
210         NULL
211         ))
212     {
213         PrintLastError(&VolumeName[4]);
214         return -1;
215     }
216
217     if (!DeviceIoControl(
218         Device,
219         FSCTL_UNLOCK_VOLUME,
220         NULL,
221         0,
222         NULL,
223         0,
224         &BytesReturned,
225         NULL
226         ))
227     {
228         PrintLastError(&VolumeName[4]);
229         return -1;
230     }
231
232     CloseHandle(Device);
233
234     if (!DefineDosDevice(
235         DDD_REMOVE_DEFINITION,
236         &VolumeName[4],
237         NULL
238         ))
239     {
240         PrintLastError(&VolumeName[4]);
241         return -1;
242     }
243
244     return 0;
245 }
246
247 int __cdecl main(int argc, char* argv[])
248 {
249     char*                   Command;
250     int                     DeviceNumber;
251     char*                   Url;
252     char*                   Option;
253     char                    DriveLetter;
254     BOOLEAN                 CdImage;
255     PHTTP_DISK_INFORMATION  HttpDiskInformation;
256     char*                   FileName;
257     char*                   PortStr;
258     struct hostent*         HostEnt;
259     WSADATA                 wsaData;
260
261     Command = argv[1];
262
263     if ((argc == 5 || argc == 6) && !strcmp(Command, "/mount"))
264     {
265         DeviceNumber = atoi(argv[2]);
266         Url = argv[3];
267
268         if (argc > 5)
269         {
270             Option = argv[4];
271             DriveLetter = argv[5][0];
272
273             if (!strcmp(Option, "/cd"))
274             {
275                 CdImage = TRUE;
276             }
277             else
278             {
279                 return HttpDiskSyntax();
280             }
281         }
282         else
283         {
284             Option = NULL;
285             DriveLetter = argv[4][0];
286             CdImage = FALSE;
287         }
288
289         HttpDiskInformation = malloc(sizeof(HTTP_DISK_INFORMATION) + strlen(Url));
290
291         memset(
292             HttpDiskInformation,
293             0,
294             sizeof(HTTP_DISK_INFORMATION) + strlen(Url)
295             );
296
297         if (strstr(Url, "//"))
298         {
299             if (strlen(Url) > 7 && !strncmp(Url, "http://", 7))
300             {
301                 Url += 7;
302             }
303             else
304             {
305                 fprintf(stderr, "Invalid protocol.\n");
306                 return -1;
307             }
308         }
309
310         FileName = strstr(Url, "/");
311
312         if (!FileName)
313         {
314             fprintf(stderr, "%s: Invalid url.\n", Url);
315             return -1;
316         }
317
318         strcpy(HttpDiskInformation->FileName, FileName);
319
320         HttpDiskInformation->FileNameLength = (USHORT) strlen(HttpDiskInformation->FileName);
321
322         *FileName = '\0';
323
324         PortStr = strstr(Url, ":");
325
326         if (PortStr)
327         {
328             HttpDiskInformation->Port = htons((USHORT) atoi(PortStr + 1));
329
330             if (HttpDiskInformation->Port == 0)
331             {
332                 fprintf(stderr, "%s: Invalid port.\n", PortStr + 1);
333                 return -1;
334             }
335
336             *PortStr = '\0';
337         }
338         else
339         {
340             HttpDiskInformation->Port = htons(80);
341         }
342
343         HttpDiskInformation->HostNameLength = (USHORT) strlen(Url);
344
345         if (HttpDiskInformation->HostNameLength > 255)
346         {
347             fprintf(stderr, "%s: Host name to long.\n", Url);
348             return -1;
349         }
350
351         strcpy(HttpDiskInformation->HostName, Url);
352
353         HttpDiskInformation->Address = inet_addr(Url);
354
355         if (HttpDiskInformation->Address == INADDR_NONE)
356         {
357             if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
358             {
359                 PrintLastError("HttpDisk");
360                 return -1;
361             }
362
363             HostEnt = gethostbyname(Url);
364
365             if (!HostEnt)
366             {
367                 PrintLastError(Url);
368                 return -1;
369             }
370
371             HttpDiskInformation->Address = ((struct in_addr*) HostEnt->h_addr)->s_addr;
372         }
373
374         return HttpDiskMount(DeviceNumber, HttpDiskInformation, DriveLetter, CdImage);
375     }
376     else if (argc == 3 && !strcmp(Command, "/umount"))
377     {
378         DriveLetter = argv[2][0];
379         return HttpDiskUmount(DriveLetter);
380     }
381     else
382     {
383         return HttpDiskSyntax();
384     }
385 }