[httpdisk] Initial population into WinVBlock repository
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Tue, 11 May 2010 02:54:49 +0000 (22:54 -0400)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Tue, 11 May 2010 03:01:42 +0000 (23:01 -0400)
The extremely nice work of Bo Brantén found at:

http://www.acc.umu.se/~bosse/

includes HTTPDisk, a read-only HTTP SAN driver, of sorts.

He has very kindly provided permission for its incorporation
into WinVBlock.  It will be developed to be a "feature
driver", just as AoE is a "feature driver".

Please note that HTTPDisk is GPLv2 or any later version.

17 files changed:
src/httpdisk/COPYING.TXT [new file with mode: 0644]
src/httpdisk/MAKEFILE [new file with mode: 0644]
src/httpdisk/Sources [new file with mode: 0644]
src/httpdisk/httpdisk.c [new file with mode: 0644]
src/httpdisk/httpdisk.rc [new file with mode: 0644]
src/httpdisk/ksocket.c [new file with mode: 0644]
src/httpdisk/ksocket.h [new file with mode: 0644]
src/httpdisk/ktdi.c [new file with mode: 0644]
src/httpdisk/ktdi.h [new file with mode: 0644]
src/httpdisk/readme.txt [new file with mode: 0644]
src/httpdisk_util/COPYING.TXT [new file with mode: 0644]
src/httpdisk_util/MAKEFILE [new file with mode: 0644]
src/httpdisk_util/httpdisk.c [new file with mode: 0644]
src/httpdisk_util/httpdisk.rc [new file with mode: 0644]
src/httpdisk_util/readme.txt [new file with mode: 0644]
src/httpdisk_util/sources [new file with mode: 0644]
src/include/httpdisk.h [new file with mode: 0644]

diff --git a/src/httpdisk/COPYING.TXT b/src/httpdisk/COPYING.TXT
new file mode 100644 (file)
index 0000000..fbdd65f
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE\r
+                      Version 2, June 1991\r
+\r
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\r
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+License is intended to guarantee your freedom to share and change free\r
+software--to make sure the software is free for all its users.  This\r
+General Public License applies to most of the Free Software\r
+Foundation's software and to any other program whose authors commit to\r
+using it.  (Some other Free Software Foundation software is covered by\r
+the GNU Library General Public License instead.)  You can apply it to\r
+your programs, too.\r
+\r
+  When we speak of free software, we are referring to freedom, not\r
+price.  Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+this service if you wish), that you receive source code or can get it\r
+if you want it, that you can change the software or use pieces of it\r
+in new free programs; and that you know you can do these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+anyone to deny you these rights or to ask you to surrender the rights.\r
+These restrictions translate to certain responsibilities for you if you\r
+distribute copies of the software, or if you modify it.\r
+\r
+  For example, if you distribute copies of such a program, whether\r
+gratis or for a fee, you must give the recipients all the rights that\r
+you have.  You must make sure that they, too, receive or can get the\r
+source code.  And you must show them these terms so they know their\r
+rights.\r
+\r
+  We protect your rights with two steps: (1) copyright the software, and\r
+(2) offer you this license which gives you legal permission to copy,\r
+distribute and/or modify the software.\r
+\r
+  Also, for each author's protection and ours, we want to make certain\r
+that everyone understands that there is no warranty for this free\r
+software.  If the software is modified by someone else and passed on, we\r
+want its recipients to know that what they have is not the original, so\r
+that any problems introduced by others will not reflect on the original\r
+authors' reputations.\r
+\r
+  Finally, any free program is threatened constantly by software\r
+patents.  We wish to avoid the danger that redistributors of a free\r
+program will individually obtain patent licenses, in effect making the\r
+program proprietary.  To prevent this, we have made it clear that any\r
+patent must be licensed for everyone's free use or not licensed at all.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.\r
+\f\r
+                   GNU GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License applies to any program or other work which contains\r
+a notice placed by the copyright holder saying it may be distributed\r
+under the terms of this General Public License.  The "Program", below,\r
+refers to any such program or work, and a "work based on the Program"\r
+means either the Program or any derivative work under copyright law:\r
+that is to say, a work containing the Program or a portion of it,\r
+either verbatim or with modifications and/or translated into another\r
+language.  (Hereinafter, translation is included without limitation in\r
+the term "modification".)  Each licensee is addressed as "you".\r
+\r
+Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running the Program is not restricted, and the output from the Program\r
+is covered only if its contents constitute a work based on the\r
+Program (independent of having been made by running the Program).\r
+Whether that is true depends on what the Program does.\r
+\r
+  1. You may copy and distribute verbatim copies of the Program's\r
+source code as you receive it, in any medium, provided that you\r
+conspicuously and appropriately publish on each copy an appropriate\r
+copyright notice and disclaimer of warranty; keep intact all the\r
+notices that refer to this License and to the absence of any warranty;\r
+and give any other recipients of the Program a copy of this License\r
+along with the Program.\r
+\r
+You may charge a fee for the physical act of transferring a copy, and\r
+you may at your option offer warranty protection in exchange for a fee.\r
+\r
+  2. You may modify your copy or copies of the Program or any portion\r
+of it, thus forming a work based on the Program, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) You must cause the modified files to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    b) You must cause any work that you distribute or publish, that in\r
+    whole or in part contains or is derived from the Program or any\r
+    part thereof, to be licensed as a whole at no charge to all third\r
+    parties under the terms of this License.\r
+\r
+    c) If the modified program normally reads commands interactively\r
+    when run, you must cause it, when started running for such\r
+    interactive use in the most ordinary way, to print or display an\r
+    announcement including an appropriate copyright notice and a\r
+    notice that there is no warranty (or else, saying that you provide\r
+    a warranty) and that users may redistribute the program under\r
+    these conditions, and telling the user how to view a copy of this\r
+    License.  (Exception: if the Program itself is interactive but\r
+    does not normally print such an announcement, your work based on\r
+    the Program is not required to print an announcement.)\r
+\f\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Program,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Program, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Program.\r
+\r
+In addition, mere aggregation of another work not based on the Program\r
+with the Program (or with a work based on the Program) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may copy and distribute the Program (or a work based on it,\r
+under Section 2) in object code or executable form under the terms of\r
+Sections 1 and 2 above provided that you also do one of the following:\r
+\r
+    a) Accompany it with the complete corresponding machine-readable\r
+    source code, which must be distributed under the terms of Sections\r
+    1 and 2 above on a medium customarily used for software interchange; or,\r
+\r
+    b) Accompany it with a written offer, valid for at least three\r
+    years, to give any third party, for a charge no more than your\r
+    cost of physically performing source distribution, a complete\r
+    machine-readable copy of the corresponding source code, to be\r
+    distributed under the terms of Sections 1 and 2 above on a medium\r
+    customarily used for software interchange; or,\r
+\r
+    c) Accompany it with the information you received as to the offer\r
+    to distribute corresponding source code.  (This alternative is\r
+    allowed only for noncommercial distribution and only if you\r
+    received the program in object code or executable form with such\r
+    an offer, in accord with Subsection b above.)\r
+\r
+The source code for a work means the preferred form of the work for\r
+making modifications to it.  For an executable work, complete source\r
+code means all the source code for all modules it contains, plus any\r
+associated interface definition files, plus the scripts used to\r
+control compilation and installation of the executable.  However, as a\r
+special exception, the source code distributed need not include\r
+anything that is normally distributed (in either source or binary\r
+form) with the major components (compiler, kernel, and so on) of the\r
+operating system on which the executable runs, unless that component\r
+itself accompanies the executable.\r
+\r
+If distribution of executable or object code is made by offering\r
+access to copy from a designated place, then offering equivalent\r
+access to copy the source code from the same place counts as\r
+distribution of the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\f\r
+  4. You may not copy, modify, sublicense, or distribute the Program\r
+except as expressly provided under this License.  Any attempt\r
+otherwise to copy, modify, sublicense or distribute the Program is\r
+void, and will automatically terminate your rights under this License.\r
+However, parties who have received copies, or rights, from you under\r
+this License will not have their licenses terminated so long as such\r
+parties remain in full compliance.\r
+\r
+  5. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Program or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Program (or any work based on the\r
+Program), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Program or works based on it.\r
+\r
+  6. Each time you redistribute the Program (or any work based on the\r
+Program), the recipient automatically receives a license from the\r
+original licensor to copy, distribute or modify the Program subject to\r
+these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties to\r
+this License.\r
+\r
+  7. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Program at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Program by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Program.\r
+\r
+If any portion of this section is held invalid or unenforceable under\r
+any particular circumstance, the balance of the section is intended to\r
+apply and the section as a whole is intended to apply in other\r
+circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system, which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\f\r
+  8. If the distribution and/or use of the Program is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Program under this License\r
+may add an explicit geographical distribution limitation excluding\r
+those countries, so that distribution is permitted only in or among\r
+countries not thus excluded.  In such case, this License incorporates\r
+the limitation as if written in the body of this License.\r
+\r
+  9. The Free Software Foundation may publish revised and/or new versions\r
+of the General Public License from time to time.  Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Program\r
+specifies a version number of this License which applies to it and "any\r
+later version", you have the option of following the terms and conditions\r
+either of that version or of any later version published by the Free\r
+Software Foundation.  If the Program does not specify a version number of\r
+this License, you may choose any version ever published by the Free Software\r
+Foundation.\r
+\r
+  10. If you wish to incorporate parts of the Program into other free\r
+programs whose distribution conditions are different, write to the author\r
+to ask for permission.  For software which is copyrighted by the Free\r
+Software Foundation, write to the Free Software Foundation; we sometimes\r
+make exceptions for this.  Our decision will be guided by the two goals\r
+of preserving the free status of all derivatives of our free software and\r
+of promoting the sharing and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\r
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\r
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\r
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\r
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r
+REPAIR OR CORRECTION.\r
+\r
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
+\f\r
+           How to Apply These Terms to Your New Programs\r
+\r
+  If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+\r
+  To do so, attach the following notices to the program.  It is safest\r
+to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the program's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+If the program is interactive, make it output a short notice like this\r
+when it starts in an interactive mode:\r
+\r
+    Gnomovision version 69, Copyright (C) year  name of author\r
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+    This is free software, and you are welcome to redistribute it\r
+    under certain conditions; type `show c' for details.\r
+\r
+The hypothetical commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License.  Of course, the commands you use may\r
+be called something other than `show w' and `show c'; they could even be\r
+mouse-clicks or menu items--whatever suits your program.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the program, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1989\r
+  Ty Coon, President of Vice\r
+\r
+This General Public License does not permit incorporating your program into\r
+proprietary programs.  If your program is a subroutine library, you may\r
+consider it more useful to permit linking proprietary applications with the\r
+library.  If this is what you want to do, use the GNU Library General\r
+Public License instead of this License.\r
diff --git a/src/httpdisk/MAKEFILE b/src/httpdisk/MAKEFILE
new file mode 100644 (file)
index 0000000..9c985f5
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
diff --git a/src/httpdisk/Sources b/src/httpdisk/Sources
new file mode 100644 (file)
index 0000000..b6e736c
--- /dev/null
@@ -0,0 +1,6 @@
+TARGETNAME=httpdisk\r
+TARGETPATH=..\obj\r
+TARGETTYPE=DRIVER\r
+TARGETLIBS=$(SDK_LIB_PATH)\libcntpr.lib\r
+INCLUDES=..\inc;$(DDK_INC_PATH);$(BASEDIR)\src\network\inc\r
+SOURCES=ksocket.c ktdi.c httpdisk.c httpdisk.rc\r
diff --git a/src/httpdisk/httpdisk.c b/src/httpdisk/httpdisk.c
new file mode 100644 (file)
index 0000000..e9d4e7b
--- /dev/null
@@ -0,0 +1,1560 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#include <ntddk.h>\r
+#include <ntdddisk.h>\r
+#include <ntddcdrm.h>\r
+#include <ntverp.h>\r
+#include "ksocket.h"\r
+\r
+//\r
+// We include some stuff from newer DDK:s here so that one\r
+// version of the driver for all versions of Windows can\r
+// be compiled with the Windows NT 4.0 DDK.\r
+//\r
+#if (VER_PRODUCTBUILD < 2195)\r
+\r
+#define FILE_DEVICE_MASS_STORAGE            0x0000002d\r
+#define IOCTL_STORAGE_CHECK_VERIFY2         CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS)\r
+\r
+#endif // (VER_PRODUCTBUILD < 2195)\r
+\r
+#if (VER_PRODUCTBUILD < 2600)\r
+\r
+#define IOCTL_DISK_GET_PARTITION_INFO_EX    CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS)\r
+#define IOCTL_DISK_GET_LENGTH_INFO          CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)\r
+\r
+typedef enum _PARTITION_STYLE {\r
+    PARTITION_STYLE_MBR,\r
+    PARTITION_STYLE_GPT\r
+} PARTITION_STYLE;\r
+\r
+typedef unsigned __int64 ULONG64, *PULONG64;\r
+\r
+typedef struct _PARTITION_INFORMATION_MBR {\r
+    UCHAR   PartitionType;\r
+    BOOLEAN BootIndicator;\r
+    BOOLEAN RecognizedPartition;\r
+    ULONG   HiddenSectors;\r
+} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR;\r
+\r
+typedef struct _PARTITION_INFORMATION_GPT {\r
+    GUID    PartitionType;\r
+    GUID    PartitionId;\r
+    ULONG64 Attributes;\r
+    WCHAR   Name[36];\r
+} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT;\r
+\r
+typedef struct _PARTITION_INFORMATION_EX {\r
+    PARTITION_STYLE PartitionStyle;\r
+    LARGE_INTEGER   StartingOffset;\r
+    LARGE_INTEGER   PartitionLength;\r
+    ULONG           PartitionNumber;\r
+    BOOLEAN         RewritePartition;\r
+    union {\r
+        PARTITION_INFORMATION_MBR Mbr;\r
+        PARTITION_INFORMATION_GPT Gpt;\r
+    };\r
+} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX;\r
+\r
+typedef struct _GET_LENGTH_INFORMATION {\r
+    LARGE_INTEGER Length;\r
+} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION;\r
+\r
+#endif // (VER_PRODUCTBUILD < 2600)\r
+\r
+//\r
+// For backward compatibility with Windows NT 4.0 by Bruce Engle.\r
+//\r
+#ifndef MmGetSystemAddressForMdlSafe\r
+#define MmGetSystemAddressForMdlSafe(MDL, PRIORITY) MmGetSystemAddressForMdlPrettySafe(MDL)\r
+\r
+PVOID\r
+MmGetSystemAddressForMdlPrettySafe (\r
+    PMDL Mdl\r
+    )\r
+{\r
+    CSHORT  MdlMappingCanFail;\r
+    PVOID   MappedSystemVa;\r
+\r
+    MdlMappingCanFail = Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL;\r
+\r
+    Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;\r
+\r
+    MappedSystemVa = MmGetSystemAddressForMdl(Mdl);\r
+\r
+    if (MdlMappingCanFail == 0)\r
+    {\r
+        Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;\r
+    }\r
+\r
+    return MappedSystemVa;\r
+}\r
+#endif\r
+\r
+#include "httpdisk.h"\r
+\r
+#define PARAMETER_KEY           L"\\Parameters"\r
+\r
+#define NUMBEROFDEVICES_VALUE   L"NumberOfDevices"\r
+\r
+#define DEFAULT_NUMBEROFDEVICES 4\r
+\r
+#define SECTOR_SIZE             512\r
+\r
+#define TOC_DATA_TRACK          0x04\r
+\r
+#define BUFFER_SIZE             (4096 * 4)\r
+\r
+HANDLE dir_handle;\r
+\r
+typedef struct _HTTP_HEADER {\r
+    LARGE_INTEGER ContentLength;\r
+} HTTP_HEADER, *PHTTP_HEADER;\r
+\r
+typedef struct _DEVICE_EXTENSION {\r
+    BOOLEAN         media_in_device;\r
+    ULONG           address;\r
+    USHORT          port;\r
+    PUCHAR          host_name;\r
+    PUCHAR          file_name;\r
+    LARGE_INTEGER   file_size;\r
+    int             socket;\r
+    LIST_ENTRY      list_head;\r
+    KSPIN_LOCK      list_lock;\r
+    KEVENT          request_event;\r
+    PVOID           thread_pointer;\r
+    BOOLEAN         terminate_thread;\r
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;\r
+\r
+NTSTATUS\r
+DriverEntry (\r
+    IN PDRIVER_OBJECT   DriverObject,\r
+    IN PUNICODE_STRING  RegistryPath\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskCreateDevice (\r
+    IN PDRIVER_OBJECT   DriverObject,\r
+    IN ULONG            Number,\r
+    IN DEVICE_TYPE      DeviceType\r
+);\r
+\r
+VOID\r
+HttpDiskUnload (\r
+    IN PDRIVER_OBJECT   DriverObject\r
+);\r
+\r
+PDEVICE_OBJECT\r
+HttpDiskDeleteDevice (\r
+    IN PDEVICE_OBJECT   DeviceObject\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskCreateClose (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskReadWrite (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskDeviceControl (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+);\r
+\r
+VOID\r
+HttpDiskThread (\r
+    IN PVOID            Context\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskConnect (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskDisconnect (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskGetHeader (\r
+    IN ULONG                Address,\r
+    IN USHORT               Port,\r
+    IN PUCHAR               HostName,\r
+    IN PUCHAR               FileName,\r
+    OUT PIO_STATUS_BLOCK    IoStatus,\r
+    OUT PHTTP_HEADER        HttpHeader\r
+);\r
+\r
+NTSTATUS\r
+HttpDiskGetBlock (\r
+    IN int                  *Socket,\r
+    IN ULONG                Address,\r
+    IN USHORT               Port,\r
+    IN PUCHAR               HostName,\r
+    IN PUCHAR               FileName,\r
+    IN PLARGE_INTEGER       Offset,\r
+    IN ULONG                Length,\r
+    OUT PIO_STATUS_BLOCK    IoStatus,\r
+    OUT PVOID               SystemBuffer\r
+);\r
+\r
+__int64 __cdecl _atoi64(const char *);\r
+int __cdecl _snprintf(char *, size_t, const char *, ...);\r
+int __cdecl swprintf(wchar_t *, const wchar_t *, ...);\r
+\r
+#pragma code_seg("INIT")\r
+\r
+NTSTATUS\r
+DriverEntry (\r
+    IN PDRIVER_OBJECT   DriverObject,\r
+    IN PUNICODE_STRING  RegistryPath\r
+    )\r
+{\r
+    UNICODE_STRING              parameter_path;\r
+    RTL_QUERY_REGISTRY_TABLE    query_table[2];\r
+    ULONG                       n_devices;\r
+    NTSTATUS                    status;\r
+    UNICODE_STRING              device_dir_name;\r
+    OBJECT_ATTRIBUTES           object_attributes;\r
+    ULONG                       n;\r
+    USHORT                      n_created_devices;\r
+\r
+    parameter_path.Length = 0;\r
+\r
+    parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY);\r
+\r
+    parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength);\r
+\r
+    if (parameter_path.Buffer == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlCopyUnicodeString(&parameter_path, RegistryPath);\r
+\r
+    RtlAppendUnicodeToString(&parameter_path, PARAMETER_KEY);\r
+\r
+    RtlZeroMemory(&query_table[0], sizeof(query_table));\r
+\r
+    query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
+    query_table[0].Name = NUMBEROFDEVICES_VALUE;\r
+    query_table[0].EntryContext = &n_devices;\r
+\r
+    status = RtlQueryRegistryValues(\r
+        RTL_REGISTRY_ABSOLUTE,\r
+        parameter_path.Buffer,\r
+        &query_table[0],\r
+        NULL,\r
+        NULL\r
+        );\r
+\r
+    ExFreePool(parameter_path.Buffer);\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        DbgPrint("HttpDisk: Query registry failed, using default values.\n");\r
+        n_devices = DEFAULT_NUMBEROFDEVICES;\r
+    }\r
+\r
+    RtlInitUnicodeString(&device_dir_name, DEVICE_DIR_NAME);\r
+\r
+    InitializeObjectAttributes(\r
+        &object_attributes,\r
+        &device_dir_name,\r
+        OBJ_PERMANENT,\r
+        NULL,\r
+        NULL\r
+        );\r
+\r
+    status = ZwCreateDirectoryObject(\r
+        &dir_handle,\r
+        DIRECTORY_ALL_ACCESS,\r
+        &object_attributes\r
+        );\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        return status;\r
+    }\r
+\r
+    ZwMakeTemporaryObject(dir_handle);\r
+\r
+    for (n = 0, n_created_devices = 0; n < n_devices; n++)\r
+    {\r
+        status = HttpDiskCreateDevice(DriverObject, n, FILE_DEVICE_DISK);\r
+\r
+        if (NT_SUCCESS(status))\r
+        {\r
+            n_created_devices++;\r
+        }\r
+    }\r
+\r
+    for (n = 0; n < n_devices; n++)\r
+    {\r
+        status = HttpDiskCreateDevice(DriverObject, n, FILE_DEVICE_CD_ROM);\r
+\r
+        if (NT_SUCCESS(status))\r
+        {\r
+            n_created_devices++;\r
+        }\r
+    }\r
+\r
+    if (n_created_devices == 0)\r
+    {\r
+        ZwClose(dir_handle);\r
+        return status;\r
+    }\r
+\r
+    DriverObject->MajorFunction[IRP_MJ_CREATE]         = HttpDiskCreateClose;\r
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = HttpDiskCreateClose;\r
+    DriverObject->MajorFunction[IRP_MJ_READ]           = HttpDiskReadWrite;\r
+    DriverObject->MajorFunction[IRP_MJ_WRITE]          = HttpDiskReadWrite;\r
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HttpDiskDeviceControl;\r
+\r
+    DriverObject->DriverUnload = HttpDiskUnload;\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskCreateDevice (\r
+    IN PDRIVER_OBJECT   DriverObject,\r
+    IN ULONG            Number,\r
+    IN DEVICE_TYPE      DeviceType\r
+    )\r
+{\r
+    WCHAR               device_name_buffer[MAXIMUM_FILENAME_LENGTH];\r
+    UNICODE_STRING      device_name;\r
+    NTSTATUS            status;\r
+    PDEVICE_OBJECT      device_object;\r
+    PDEVICE_EXTENSION   device_extension;\r
+    HANDLE              thread_handle;\r
+\r
+    ASSERT(DriverObject != NULL);\r
+\r
+    if (DeviceType == FILE_DEVICE_CD_ROM)\r
+    {\r
+        swprintf(\r
+            device_name_buffer,\r
+            DEVICE_NAME_PREFIX L"Cd" L"%u",\r
+            Number\r
+            );\r
+    }\r
+    else\r
+    {\r
+        swprintf(\r
+            device_name_buffer,\r
+            DEVICE_NAME_PREFIX L"Disk" L"%u",\r
+            Number\r
+            );\r
+    }\r
+\r
+    RtlInitUnicodeString(&device_name, device_name_buffer);\r
+\r
+    status = IoCreateDevice(\r
+        DriverObject,\r
+        sizeof(DEVICE_EXTENSION),\r
+        &device_name,\r
+        DeviceType,\r
+        0,\r
+        FALSE,\r
+        &device_object\r
+        );\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        return status;\r
+    }\r
+\r
+    device_object->Flags |= DO_DIRECT_IO;\r
+\r
+    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;\r
+\r
+    device_extension->media_in_device = FALSE;\r
+\r
+    device_extension->host_name = NULL;\r
+\r
+    device_extension->file_name = NULL;\r
+\r
+    device_extension->socket = -1;\r
+\r
+    device_object->Characteristics |= FILE_READ_ONLY_DEVICE;\r
+\r
+    InitializeListHead(&device_extension->list_head);\r
+\r
+    KeInitializeSpinLock(&device_extension->list_lock);\r
+\r
+    KeInitializeEvent(\r
+        &device_extension->request_event,\r
+        SynchronizationEvent,\r
+        FALSE\r
+        );\r
+\r
+    device_extension->terminate_thread = FALSE;\r
+\r
+    status = PsCreateSystemThread(\r
+        &thread_handle,\r
+        (ACCESS_MASK) 0L,\r
+        NULL,\r
+        NULL,\r
+        NULL,\r
+        HttpDiskThread,\r
+        device_object\r
+        );\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        IoDeleteDevice(device_object);\r
+        return status;\r
+    }\r
+\r
+    status = ObReferenceObjectByHandle(\r
+        thread_handle,\r
+        THREAD_ALL_ACCESS,\r
+        NULL,\r
+        KernelMode,\r
+        &device_extension->thread_pointer,\r
+        NULL\r
+        );\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        ZwClose(thread_handle);\r
+\r
+        device_extension->terminate_thread = TRUE;\r
+\r
+        KeSetEvent(\r
+            &device_extension->request_event,\r
+            (KPRIORITY) 0,\r
+            FALSE\r
+            );\r
+\r
+        IoDeleteDevice(device_object);\r
+\r
+        return status;\r
+    }\r
+\r
+    ZwClose(thread_handle);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+#pragma code_seg("PAGE")\r
+\r
+VOID\r
+HttpDiskUnload (\r
+    IN PDRIVER_OBJECT DriverObject\r
+    )\r
+{\r
+    PDEVICE_OBJECT device_object;\r
+\r
+    device_object = DriverObject->DeviceObject;\r
+\r
+    while (device_object)\r
+    {\r
+        device_object = HttpDiskDeleteDevice(device_object);\r
+    }\r
+\r
+    ZwClose(dir_handle);\r
+}\r
+\r
+PDEVICE_OBJECT\r
+HttpDiskDeleteDevice (\r
+    IN PDEVICE_OBJECT DeviceObject\r
+    )\r
+{\r
+    PDEVICE_EXTENSION   device_extension;\r
+    PDEVICE_OBJECT      next_device_object;\r
+\r
+    ASSERT(DeviceObject != NULL);\r
+\r
+    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;\r
+\r
+    device_extension->terminate_thread = TRUE;\r
+\r
+    KeSetEvent(\r
+        &device_extension->request_event,\r
+        (KPRIORITY) 0,\r
+        FALSE\r
+        );\r
+\r
+    KeWaitForSingleObject(\r
+        device_extension->thread_pointer,\r
+        Executive,\r
+        KernelMode,\r
+        FALSE,\r
+        NULL\r
+        );\r
+\r
+    ObDereferenceObject(device_extension->thread_pointer);\r
+\r
+    next_device_object = DeviceObject->NextDevice;\r
+\r
+    IoDeleteDevice(DeviceObject);\r
+\r
+    return next_device_object;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskCreateClose (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+    )\r
+{\r
+    Irp->IoStatus.Status = STATUS_SUCCESS;\r
+    Irp->IoStatus.Information = FILE_OPENED;\r
+\r
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+#pragma code_seg()\r
+\r
+NTSTATUS\r
+HttpDiskReadWrite (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+    )\r
+{\r
+    PDEVICE_EXTENSION   device_extension;\r
+    PIO_STACK_LOCATION  io_stack;\r
+\r
+    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;\r
+\r
+    if (!device_extension->media_in_device)\r
+    {\r
+        Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;\r
+        Irp->IoStatus.Information = 0;\r
+\r
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
+\r
+        return STATUS_NO_MEDIA_IN_DEVICE;\r
+    }\r
+\r
+    io_stack = IoGetCurrentIrpStackLocation(Irp);\r
+\r
+    if (io_stack->Parameters.Read.Length == 0)\r
+    {\r
+        Irp->IoStatus.Status = STATUS_SUCCESS;\r
+        Irp->IoStatus.Information = 0;\r
+\r
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
+\r
+        return STATUS_SUCCESS;\r
+    }\r
+\r
+    IoMarkIrpPending(Irp);\r
+\r
+    ExInterlockedInsertTailList(\r
+        &device_extension->list_head,\r
+        &Irp->Tail.Overlay.ListEntry,\r
+        &device_extension->list_lock\r
+        );\r
+\r
+    KeSetEvent(\r
+        &device_extension->request_event,\r
+        (KPRIORITY) 0,\r
+        FALSE\r
+        );\r
+\r
+    return STATUS_PENDING;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskDeviceControl (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+    )\r
+{\r
+    PDEVICE_EXTENSION   device_extension;\r
+    PIO_STACK_LOCATION  io_stack;\r
+    NTSTATUS            status;\r
+\r
+    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;\r
+\r
+    io_stack = IoGetCurrentIrpStackLocation(Irp);\r
+\r
+    if (!device_extension->media_in_device &&\r
+        io_stack->Parameters.DeviceIoControl.IoControlCode !=\r
+        IOCTL_HTTP_DISK_CONNECT)\r
+    {\r
+        Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;\r
+        Irp->IoStatus.Information = 0;\r
+\r
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
+\r
+        return STATUS_NO_MEDIA_IN_DEVICE;\r
+    }\r
+\r
+    switch (io_stack->Parameters.DeviceIoControl.IoControlCode)\r
+    {\r
+    case IOCTL_HTTP_DISK_CONNECT:\r
+        {\r
+            if (device_extension->media_in_device)\r
+            {\r
+                DbgPrint("HttpDisk: IOCTL_HTTP_DISK_CONNECT: Media already opened.\n");\r
+\r
+                status = STATUS_INVALID_DEVICE_REQUEST;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.InputBufferLength <\r
+                sizeof(HTTP_DISK_INFORMATION))\r
+            {\r
+                status = STATUS_INVALID_PARAMETER;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.InputBufferLength <\r
+                sizeof(HTTP_DISK_INFORMATION) +\r
+                ((PHTTP_DISK_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->FileNameLength -\r
+                sizeof(UCHAR))\r
+            {\r
+                status = STATUS_INVALID_PARAMETER;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            IoMarkIrpPending(Irp);\r
+\r
+            ExInterlockedInsertTailList(\r
+                &device_extension->list_head,\r
+                &Irp->Tail.Overlay.ListEntry,\r
+                &device_extension->list_lock\r
+                );\r
+\r
+            KeSetEvent(\r
+                &device_extension->request_event,\r
+                (KPRIORITY) 0,\r
+                FALSE\r
+                );\r
+\r
+            status = STATUS_PENDING;\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_HTTP_DISK_DISCONNECT:\r
+        {\r
+            IoMarkIrpPending(Irp);\r
+\r
+            ExInterlockedInsertTailList(\r
+                &device_extension->list_head,\r
+                &Irp->Tail.Overlay.ListEntry,\r
+                &device_extension->list_lock\r
+                );\r
+\r
+            KeSetEvent(\r
+                &device_extension->request_event,\r
+                (KPRIORITY) 0,\r
+                FALSE\r
+                );\r
+\r
+            status = STATUS_PENDING;\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_CHECK_VERIFY:\r
+    case IOCTL_CDROM_CHECK_VERIFY:\r
+    case IOCTL_STORAGE_CHECK_VERIFY:\r
+    case IOCTL_STORAGE_CHECK_VERIFY2:\r
+        {\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = 0;\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_GET_DRIVE_GEOMETRY:\r
+    case IOCTL_CDROM_GET_DRIVE_GEOMETRY:\r
+        {\r
+            PDISK_GEOMETRY  disk_geometry;\r
+            ULONGLONG       length;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <\r
+                sizeof(DISK_GEOMETRY))\r
+            {\r
+                status = STATUS_BUFFER_TOO_SMALL;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            length = device_extension->file_size.QuadPart;\r
+\r
+            disk_geometry->Cylinders.QuadPart = length / SECTOR_SIZE / 32 / 2;\r
+            disk_geometry->MediaType = FixedMedia;\r
+            disk_geometry->TracksPerCylinder = 2;\r
+            disk_geometry->SectorsPerTrack = 32;\r
+            disk_geometry->BytesPerSector = SECTOR_SIZE;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_GET_LENGTH_INFO:\r
+        {\r
+            PGET_LENGTH_INFORMATION get_length_information;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <\r
+                sizeof(GET_LENGTH_INFORMATION))\r
+            {\r
+                status = STATUS_BUFFER_TOO_SMALL;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            get_length_information = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            get_length_information->Length.QuadPart = device_extension->file_size.QuadPart;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);\r
+\r
+        break;\r
+        }\r
+\r
+    case IOCTL_DISK_GET_PARTITION_INFO:\r
+        {\r
+            PPARTITION_INFORMATION  partition_information;\r
+            ULONGLONG               length;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <\r
+                sizeof(PARTITION_INFORMATION))\r
+            {\r
+                status = STATUS_BUFFER_TOO_SMALL;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            length = device_extension->file_size.QuadPart;\r
+\r
+            partition_information->StartingOffset.QuadPart = 0;\r
+            partition_information->PartitionLength.QuadPart = length;\r
+            partition_information->HiddenSectors = 1;\r
+            partition_information->PartitionNumber = 0;\r
+            partition_information->PartitionType = 0;\r
+            partition_information->BootIndicator = FALSE;\r
+            partition_information->RecognizedPartition = FALSE;\r
+            partition_information->RewritePartition = FALSE;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_GET_PARTITION_INFO_EX:\r
+        {\r
+            PPARTITION_INFORMATION_EX   partition_information_ex;\r
+            ULONGLONG                   length;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <\r
+                sizeof(PARTITION_INFORMATION_EX))\r
+            {\r
+                status = STATUS_BUFFER_TOO_SMALL;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            partition_information_ex = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            length = device_extension->file_size.QuadPart;\r
+\r
+            partition_information_ex->PartitionStyle = PARTITION_STYLE_MBR;\r
+            partition_information_ex->StartingOffset.QuadPart = 0;\r
+            partition_information_ex->PartitionLength.QuadPart = length;\r
+            partition_information_ex->PartitionNumber = 0;\r
+            partition_information_ex->RewritePartition = FALSE;\r
+            partition_information_ex->Mbr.PartitionType = 0;\r
+            partition_information_ex->Mbr.BootIndicator = FALSE;\r
+            partition_information_ex->Mbr.RecognizedPartition = FALSE;\r
+            partition_information_ex->Mbr.HiddenSectors = 1;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_IS_WRITABLE:\r
+        {\r
+            status = STATUS_MEDIA_WRITE_PROTECTED;\r
+            Irp->IoStatus.Information = 0;\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_MEDIA_REMOVAL:\r
+    case IOCTL_STORAGE_MEDIA_REMOVAL:\r
+        {\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = 0;\r
+            break;\r
+        }\r
+\r
+    case IOCTL_CDROM_READ_TOC:\r
+        {\r
+            PCDROM_TOC cdrom_toc;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.OutputBufferLength <\r
+                sizeof(CDROM_TOC))\r
+            {\r
+                status = STATUS_BUFFER_TOO_SMALL;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            cdrom_toc = (PCDROM_TOC) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            RtlZeroMemory(cdrom_toc, sizeof(CDROM_TOC));\r
+\r
+            cdrom_toc->FirstTrack = 1;\r
+            cdrom_toc->LastTrack = 1;\r
+            cdrom_toc->TrackData[0].Control = TOC_DATA_TRACK;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = sizeof(CDROM_TOC);\r
+\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_SET_PARTITION_INFO:\r
+        {\r
+            status = STATUS_MEDIA_WRITE_PROTECTED;\r
+            Irp->IoStatus.Information = 0;\r
+            break;\r
+        }\r
+\r
+    case IOCTL_DISK_VERIFY:\r
+        {\r
+            PVERIFY_INFORMATION verify_information;\r
+\r
+            if (io_stack->Parameters.DeviceIoControl.InputBufferLength <\r
+                sizeof(VERIFY_INFORMATION))\r
+            {\r
+                status = STATUS_INVALID_PARAMETER;\r
+                Irp->IoStatus.Information = 0;\r
+                break;\r
+            }\r
+\r
+            verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+            status = STATUS_SUCCESS;\r
+            Irp->IoStatus.Information = verify_information->Length;\r
+\r
+            break;\r
+        }\r
+\r
+    default:\r
+        {\r
+            KdPrint((\r
+                "HttpDisk: Unknown IoControlCode: %#x\n",\r
+                io_stack->Parameters.DeviceIoControl.IoControlCode\r
+                ));\r
+\r
+            status = STATUS_INVALID_DEVICE_REQUEST;\r
+            Irp->IoStatus.Information = 0;\r
+        }\r
+    }\r
+\r
+    if (status != STATUS_PENDING)\r
+    {\r
+        Irp->IoStatus.Status = status;\r
+\r
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+#pragma code_seg("PAGE")\r
+\r
+VOID\r
+HttpDiskThread (\r
+    IN PVOID Context\r
+    )\r
+{\r
+    PDEVICE_OBJECT      device_object;\r
+    PDEVICE_EXTENSION   device_extension;\r
+    PLIST_ENTRY         request;\r
+    PIRP                irp;\r
+    PIO_STACK_LOCATION  io_stack;\r
+\r
+    ASSERT(Context != NULL);\r
+\r
+    device_object = (PDEVICE_OBJECT) Context;\r
+\r
+    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;\r
+\r
+    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);\r
+\r
+    for (;;)\r
+    {\r
+        KeWaitForSingleObject(\r
+            &device_extension->request_event,\r
+            Executive,\r
+            KernelMode,\r
+            FALSE,\r
+            NULL\r
+            );\r
+\r
+        if (device_extension->terminate_thread)\r
+        {\r
+            PsTerminateSystemThread(STATUS_SUCCESS);\r
+        }\r
+\r
+        while (request = ExInterlockedRemoveHeadList(\r
+            &device_extension->list_head,\r
+            &device_extension->list_lock\r
+            ))\r
+        {\r
+            irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);\r
+\r
+            io_stack = IoGetCurrentIrpStackLocation(irp);\r
+\r
+            switch (io_stack->MajorFunction)\r
+            {\r
+            case IRP_MJ_READ:\r
+                HttpDiskGetBlock(\r
+                    &device_extension->socket,\r
+                    device_extension->address,\r
+                    device_extension->port,\r
+                    device_extension->host_name,\r
+                    device_extension->file_name,\r
+                    &io_stack->Parameters.Read.ByteOffset,\r
+                    io_stack->Parameters.Read.Length,\r
+                    &irp->IoStatus,\r
+                    MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority)\r
+                    );\r
+                if (!NT_SUCCESS(irp->IoStatus.Status))\r
+                {\r
+                    HttpDiskGetBlock(\r
+                        &device_extension->socket,\r
+                        device_extension->address,\r
+                        device_extension->port,\r
+                        device_extension->host_name,\r
+                        device_extension->file_name,\r
+                        &io_stack->Parameters.Read.ByteOffset,\r
+                        io_stack->Parameters.Read.Length,\r
+                        &irp->IoStatus,\r
+                        MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority)\r
+                        );\r
+                }\r
+                break;\r
+\r
+            case IRP_MJ_WRITE:\r
+                irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;\r
+                irp->IoStatus.Information = 0;\r
+                break;\r
+\r
+            case IRP_MJ_DEVICE_CONTROL:\r
+                switch (io_stack->Parameters.DeviceIoControl.IoControlCode)\r
+                {\r
+                case IOCTL_HTTP_DISK_CONNECT:\r
+                    irp->IoStatus.Status = HttpDiskConnect(device_object, irp);\r
+                    break;\r
+\r
+                case IOCTL_HTTP_DISK_DISCONNECT:\r
+                    irp->IoStatus.Status = HttpDiskDisconnect(device_object, irp);\r
+                    break;\r
+\r
+                default:\r
+                    irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;\r
+                }\r
+                break;\r
+\r
+            default:\r
+                irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;\r
+            }\r
+\r
+            IoCompleteRequest(\r
+                irp,\r
+                (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?\r
+                IO_DISK_INCREMENT : IO_NO_INCREMENT)\r
+                );\r
+        }\r
+    }\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskConnect (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+    )\r
+{\r
+    PDEVICE_EXTENSION       device_extension;\r
+    PHTTP_DISK_INFORMATION  http_disk_information;\r
+    HTTP_HEADER             http_header;\r
+\r
+    ASSERT(DeviceObject != NULL);\r
+    ASSERT(Irp != NULL);\r
+\r
+    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;\r
+\r
+    http_disk_information = (PHTTP_DISK_INFORMATION) Irp->AssociatedIrp.SystemBuffer;\r
+\r
+    device_extension->address = http_disk_information->Address;\r
+\r
+    device_extension->port = http_disk_information->Port;\r
+\r
+    device_extension->host_name = ExAllocatePool(NonPagedPool, http_disk_information->HostNameLength + 1);\r
+\r
+    if (device_extension->host_name == NULL)\r
+    {\r
+        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;\r
+        return Irp->IoStatus.Status;\r
+    }\r
+\r
+    RtlCopyMemory(\r
+        device_extension->host_name,\r
+        http_disk_information->HostName,\r
+        http_disk_information->HostNameLength\r
+        );\r
+\r
+    device_extension->host_name[http_disk_information->HostNameLength] = '\0';\r
+\r
+    device_extension->file_name = ExAllocatePool(NonPagedPool, http_disk_information->FileNameLength + 1);\r
+\r
+    if (device_extension->file_name == NULL)\r
+    {\r
+        if (device_extension->host_name != NULL)\r
+        {\r
+            ExFreePool(device_extension->host_name);\r
+            device_extension->host_name = NULL;\r
+        }\r
+\r
+        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;\r
+        return Irp->IoStatus.Status;\r
+    }\r
+\r
+    RtlCopyMemory(\r
+        device_extension->file_name,\r
+        http_disk_information->FileName,\r
+        http_disk_information->FileNameLength\r
+        );\r
+\r
+    device_extension->file_name[http_disk_information->FileNameLength] = '\0';\r
+\r
+    HttpDiskGetHeader(\r
+        device_extension->address,\r
+        device_extension->port,\r
+        device_extension->host_name,\r
+        device_extension->file_name,\r
+        &Irp->IoStatus,\r
+        &http_header\r
+        );\r
+\r
+    if (!NT_SUCCESS(Irp->IoStatus.Status))\r
+    {\r
+        HttpDiskGetHeader(\r
+            device_extension->address,\r
+            device_extension->port,\r
+            device_extension->host_name,\r
+            device_extension->file_name,\r
+            &Irp->IoStatus,\r
+            &http_header\r
+            );\r
+    }\r
+\r
+    if (!NT_SUCCESS(Irp->IoStatus.Status))\r
+    {\r
+        if (device_extension->host_name != NULL)\r
+        {\r
+            ExFreePool(device_extension->host_name);\r
+            device_extension->host_name = NULL;\r
+        }\r
+\r
+        if (device_extension->file_name != NULL)\r
+        {\r
+            ExFreePool(device_extension->file_name);\r
+            device_extension->file_name = NULL;\r
+        }\r
+\r
+        return Irp->IoStatus.Status;\r
+    }\r
+\r
+    device_extension->file_size.QuadPart = http_header.ContentLength.QuadPart;\r
+\r
+    device_extension->media_in_device = TRUE;\r
+\r
+    return Irp->IoStatus.Status;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskDisconnect (\r
+    IN PDEVICE_OBJECT   DeviceObject,\r
+    IN PIRP             Irp\r
+    )\r
+{\r
+    PDEVICE_EXTENSION device_extension;\r
+\r
+    ASSERT(DeviceObject != NULL);\r
+    ASSERT(Irp != NULL);\r
+\r
+    device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;\r
+\r
+    device_extension->media_in_device = FALSE;\r
+\r
+    if (device_extension->host_name != NULL)\r
+    {\r
+        ExFreePool(device_extension->host_name);\r
+        device_extension->host_name = NULL;\r
+    }\r
+\r
+    if (device_extension->file_name != NULL)\r
+    {\r
+        ExFreePool(device_extension->file_name);\r
+        device_extension->file_name = NULL;\r
+    }\r
+\r
+    if (device_extension->socket > 0)\r
+    {\r
+        close(device_extension->socket);\r
+        device_extension->socket = -1;\r
+    }\r
+\r
+    Irp->IoStatus.Status = STATUS_SUCCESS;\r
+    Irp->IoStatus.Information = 0;\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskGetHeader (\r
+    IN ULONG                Address,\r
+    IN USHORT               Port,\r
+    IN PUCHAR               HostName,\r
+    IN PUCHAR               FileName,\r
+    OUT PIO_STATUS_BLOCK    IoStatus,\r
+    OUT PHTTP_HEADER        HttpHeader\r
+    )\r
+{\r
+    int                 kSocket;\r
+    struct sockaddr_in  toAddr;\r
+    int                 status, nSent, nRecv;\r
+    char                *buffer, *pStr;\r
+\r
+    ASSERT(HostName != NULL);\r
+    ASSERT(FileName != NULL);\r
+    ASSERT(IoStatus != NULL);\r
+    ASSERT(HttpHeader != NULL);\r
+\r
+    buffer = ExAllocatePool(PagedPool, BUFFER_SIZE);\r
+\r
+    if (buffer == NULL)\r
+    {\r
+        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    kSocket = socket(AF_INET, SOCK_STREAM, 0);\r
+\r
+    if (kSocket < 0)\r
+    {\r
+        DbgPrint("HttpDisk: socket() error: %#x\n", kSocket);\r
+        ExFreePool(buffer);\r
+        IoStatus->Status = kSocket;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    toAddr.sin_family = AF_INET;\r
+    toAddr.sin_port = Port;\r
+    toAddr.sin_addr.s_addr = Address;\r
+\r
+    status = connect(kSocket, (struct sockaddr*) &toAddr, sizeof(toAddr));\r
+\r
+    if (status < 0)\r
+    {\r
+        DbgPrint("HttpDisk: connect() error: %#x\n", status);\r
+        ExFreePool(buffer);\r
+        close(kSocket);\r
+        IoStatus->Status = status;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    // Example request:\r
+    //  HEAD 'FileName' HTTP/1.1\r
+    //  Host: 'HostName'\r
+    //  Accept: */*\r
+    //  User-Agent: HttpDisk/1.2\r
+    //  Connection: close\r
+    //\r
+    // Interesting lines in answer:\r
+    //  HTTP/1.1 200 OK\r
+    //  Accept-Ranges: bytes\r
+    //  Content-Length: 'total file size'\r
+\r
+    _snprintf(\r
+        buffer,\r
+        BUFFER_SIZE,\r
+        "HEAD %s HTTP/1.1\r\nHost: %s\r\nAccept: */*\r\nUser-Agent: HttpDisk/1.2\r\nConnection: close\r\n\r\n",\r
+        FileName,\r
+        HostName\r
+        );\r
+\r
+    nSent = send(kSocket, buffer, strlen(buffer), 0);\r
+\r
+    if (nSent < 0)\r
+    {\r
+        DbgPrint("HttpDisk: send() error: %#x\n", nSent);\r
+        ExFreePool(buffer);\r
+        close(kSocket);\r
+        IoStatus->Status = nSent;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    nRecv = recv(kSocket, buffer, BUFFER_SIZE, 0);\r
+\r
+    if (nRecv < 0)\r
+    {\r
+        DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);\r
+        ExFreePool(buffer);\r
+        close(kSocket);\r
+        IoStatus->Status = nRecv;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    close(kSocket);\r
+\r
+    buffer[BUFFER_SIZE - 1] = '\0';\r
+\r
+    if (_strnicmp(buffer, "HTTP/1.1 200 OK", 15))\r
+    {\r
+        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);\r
+        ExFreePool(buffer);\r
+        IoStatus->Status = STATUS_NO_SUCH_FILE;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    pStr = strstr(buffer, "Content-Length:");\r
+\r
+    if (pStr == NULL || pStr + 16 >= buffer + BUFFER_SIZE)\r
+    {\r
+        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);\r
+        ExFreePool(buffer);\r
+        IoStatus->Status = STATUS_NO_SUCH_FILE;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    HttpHeader->ContentLength.QuadPart = _atoi64(pStr + 16);\r
+\r
+    if (HttpHeader->ContentLength.QuadPart == 0)\r
+    {\r
+        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);\r
+        ExFreePool(buffer);\r
+        IoStatus->Status = STATUS_NO_SUCH_FILE;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    ExFreePool(buffer);\r
+\r
+    IoStatus->Status = STATUS_SUCCESS;\r
+    IoStatus->Information = 0;\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS\r
+HttpDiskGetBlock (\r
+    IN int                  *Socket,\r
+    IN ULONG                Address,\r
+    IN USHORT               Port,\r
+    IN PUCHAR               HostName,\r
+    IN PUCHAR               FileName,\r
+    IN PLARGE_INTEGER       Offset,\r
+    IN ULONG                Length,\r
+    OUT PIO_STATUS_BLOCK    IoStatus,\r
+    OUT PVOID               SystemBuffer\r
+    )\r
+{\r
+    struct sockaddr_in  toAddr;\r
+    int                 status, nSent, nRecv;\r
+    unsigned int        dataLen;\r
+    char                *buffer, *pData;\r
+\r
+    ASSERT(Socket != NULL);\r
+    ASSERT(HostName != NULL);\r
+    ASSERT(FileName != NULL);\r
+    ASSERT(Offset != NULL);\r
+    ASSERT(IoStatus != NULL);\r
+    ASSERT(SystemBuffer != NULL);\r
+\r
+    IoStatus->Information = 0;\r
+\r
+    buffer = ExAllocatePool(PagedPool, BUFFER_SIZE + 1);\r
+\r
+    if (buffer == NULL)\r
+    {\r
+        IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    // Example request:\r
+    //  GET 'FileName' HTTP/1.1\r
+    //  Host: 'HostName'\r
+    //  Range: bytes='Offset'-'Offset + Length - 1'\r
+    //  Accept: */*\r
+    //  User-Agent: HttpDisk/1.2\r
+    //\r
+    // Interesting lines in answer:\r
+    //  HTTP/1.1 206 Partial content\r
+    //  Content-Length: 'requested size'\r
+    //  Content-Range: bytes 'start'-'end'/'total file size'\r
+    //  Data follows after '\r\n\r\n'\r
+\r
+    _snprintf(\r
+        buffer,\r
+        BUFFER_SIZE,\r
+        "GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%I64u-%I64u\r\nAccept: */*\r\nUser-Agent: HttpDisk/1.2\r\n\r\n",\r
+        FileName,\r
+        HostName,\r
+        Offset->QuadPart,\r
+        Offset->QuadPart + Length - 1\r
+        );\r
+\r
+    if (*Socket < 0)\r
+    {\r
+        *Socket = socket(AF_INET, SOCK_STREAM, 0);\r
+\r
+        if (*Socket < 0)\r
+        {\r
+            ExFreePool(buffer);\r
+            *Socket = -1;\r
+            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        toAddr.sin_family = AF_INET;\r
+        toAddr.sin_port = Port;\r
+        toAddr.sin_addr.s_addr = Address;\r
+\r
+        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));\r
+\r
+        if (status < 0)\r
+        {\r
+            DbgPrint("HttpDisk: connect() error: %#x\n", status);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = status;\r
+            return IoStatus->Status;\r
+        }\r
+    }\r
+\r
+    nSent = send(*Socket, buffer, strlen(buffer), 0);\r
+\r
+    if (nSent < 0)\r
+    {\r
+        KdPrint(("HttpDisk: send() error: %#x\n", nSent));\r
+\r
+        close(*Socket);\r
+\r
+        *Socket = socket(AF_INET, SOCK_STREAM, 0);\r
+\r
+        if (*Socket < 0)\r
+        {\r
+            ExFreePool(buffer);\r
+            *Socket = -1;\r
+            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        toAddr.sin_family = AF_INET;\r
+        toAddr.sin_port = Port;\r
+        toAddr.sin_addr.s_addr = Address;\r
+\r
+        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));\r
+\r
+        if (status < 0)\r
+        {\r
+            DbgPrint("HttpDisk: connect() error: %#x\n", status);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = status;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        nSent = send(*Socket, buffer, strlen(buffer), 0);\r
+\r
+        if (nSent < 0)\r
+        {\r
+            DbgPrint("HttpDisk: send() error: %#x\n", nSent);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = nSent;\r
+            return IoStatus->Status;\r
+        }\r
+    }\r
+\r
+    nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);\r
+\r
+    if (nRecv < 0)\r
+    {\r
+        KdPrint(("HttpDisk: recv() error: %#x\n", nRecv));\r
+\r
+        close(*Socket);\r
+\r
+        *Socket = socket(AF_INET, SOCK_STREAM, 0);\r
+\r
+        if (*Socket < 0)\r
+        {\r
+            ExFreePool(buffer);\r
+            *Socket = -1;\r
+            IoStatus->Status = STATUS_INSUFFICIENT_RESOURCES;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        toAddr.sin_family = AF_INET;\r
+        toAddr.sin_port = Port;\r
+        toAddr.sin_addr.s_addr = Address;\r
+\r
+        status = connect(*Socket, (struct sockaddr*) &toAddr, sizeof(toAddr));\r
+\r
+        if (status < 0)\r
+        {\r
+            DbgPrint("HttpDisk: connect() error: %#x\n", status);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = status;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        nSent = send(*Socket, buffer, strlen(buffer), 0);\r
+\r
+        if (nSent < 0)\r
+        {\r
+            DbgPrint("HttpDisk: send() error: %#x\n", nSent);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = nSent;\r
+            return IoStatus->Status;\r
+        }\r
+\r
+        nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);\r
+\r
+        if (nRecv < 0)\r
+        {\r
+            DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);\r
+            ExFreePool(buffer);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            IoStatus->Status = nRecv;\r
+            return IoStatus->Status;\r
+        }\r
+    }\r
+\r
+    buffer[BUFFER_SIZE] = '\0';\r
+\r
+    if (_strnicmp(buffer, "HTTP/1.1 206 Partial Content", 28))\r
+    {\r
+        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);\r
+        ExFreePool(buffer);\r
+        close(*Socket);\r
+        *Socket = -1;\r
+        IoStatus->Status = STATUS_UNSUCCESSFUL;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    pData = strstr(buffer, "\r\n\r\n") + 4;\r
+\r
+    if (pData == NULL || pData < buffer || pData >= buffer + BUFFER_SIZE)\r
+    {\r
+        DbgPrint("HttpDisk: Invalid HTTP response:\n%s", buffer);\r
+        ExFreePool(buffer);\r
+        close(*Socket);\r
+        *Socket = -1;\r
+        IoStatus->Status = STATUS_UNSUCCESSFUL;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    dataLen = nRecv - (pData - buffer);\r
+\r
+    if (dataLen > Length || pData + dataLen > buffer + BUFFER_SIZE)\r
+    {\r
+        DbgPrint("HttpDisk: Invalid data length %u in HTTP response:\n%s", dataLen, buffer);\r
+        ExFreePool(buffer);\r
+        close(*Socket);\r
+        *Socket = -1;\r
+        IoStatus->Status = STATUS_UNSUCCESSFUL;\r
+        return IoStatus->Status;\r
+    }\r
+\r
+    if (dataLen > 0)\r
+    {\r
+        RtlCopyMemory(\r
+            SystemBuffer,\r
+            pData,\r
+            dataLen\r
+            );\r
+    }\r
+\r
+    while (dataLen < Length)\r
+    {\r
+        nRecv = recv(*Socket, buffer, BUFFER_SIZE, 0);\r
+        if (nRecv < 0)\r
+        {\r
+            DbgPrint("HttpDisk: recv() error: %#x\n", nRecv);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            break;\r
+        }\r
+        if (nRecv < 1 || dataLen + nRecv > Length || nRecv > BUFFER_SIZE)\r
+        {\r
+            DbgPrint("HttpDisk: Invalid data length %u+%u\n", dataLen, nRecv);\r
+            close(*Socket);\r
+            *Socket = -1;\r
+            break;\r
+        }\r
+        RtlCopyMemory(\r
+            (PVOID)((PUCHAR) SystemBuffer + dataLen),\r
+            buffer,\r
+            nRecv\r
+        );\r
+        dataLen += nRecv;\r
+    }\r
+\r
+    if (dataLen != Length)\r
+    {\r
+        DbgPrint("HttpDisk: received data length: %u, expected data length: %u\n", dataLen, Length);\r
+    }\r
+\r
+    ExFreePool(buffer);\r
+    IoStatus->Status = STATUS_SUCCESS;\r
+    IoStatus->Information = dataLen;\r
+    return IoStatus->Status;\r
+}\r
diff --git a/src/httpdisk/httpdisk.rc b/src/httpdisk/httpdisk.rc
new file mode 100644 (file)
index 0000000..0495bb1
--- /dev/null
@@ -0,0 +1,104 @@
+//Microsoft Developer Studio generated resource script.\r
+//\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifndef _MAC\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION 3,0,0,0\r
+ PRODUCTVERSION 3,0,0,0\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x40004L\r
+ FILETYPE 0x3L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+    BLOCK "StringFileInfo"\r
+    BEGIN\r
+        BLOCK "040904b0"\r
+        BEGIN\r
+            VALUE "CompanyName", "Bo Brantén\0"\r
+            VALUE "FileDescription", "HTTP Virtual Disk\0"\r
+            VALUE "FileVersion", "3.0.0.0\0"\r
+            VALUE "InternalName", "httpdisk\0"\r
+            VALUE "LegalCopyright", "Copyright © 2006 Bo Brantén\0"\r
+            VALUE "OriginalFilename", "httpdisk.sys\0"\r
+            VALUE "ProductName", "httpdisk\0"\r
+            VALUE "ProductVersion", "3.0.0.0\0"\r
+        END\r
+    END\r
+    BLOCK "VarFileInfo"\r
+    BEGIN\r
+        VALUE "Translation", 0x409, 1200\r
+    END\r
+END\r
+\r
+#endif    // !_MAC\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "#include ""afxres.h""\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/src/httpdisk/ksocket.c b/src/httpdisk/ksocket.c
new file mode 100644 (file)
index 0000000..df971e2
--- /dev/null
@@ -0,0 +1,529 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#include <ntddk.h>\r
+#include <tdikrnl.h>\r
+#include "ktdi.h"\r
+#include "ksocket.h"\r
+\r
+typedef struct _STREAM_SOCKET {\r
+    HANDLE              connectionHandle;\r
+    PFILE_OBJECT        connectionFileObject;\r
+    KEVENT              disconnectEvent;\r
+} STREAM_SOCKET, *PSTREAM_SOCKET;\r
+\r
+typedef struct _SOCKET {\r
+    int                 type;\r
+    BOOLEAN             isBound;\r
+    BOOLEAN             isConnected;\r
+    BOOLEAN             isListening;\r
+    BOOLEAN             isShuttingdown;\r
+    BOOLEAN             isShared;\r
+    HANDLE              addressHandle;\r
+    PFILE_OBJECT        addressFileObject;\r
+    PSTREAM_SOCKET      streamSocket;\r
+    struct sockaddr     peer;\r
+} SOCKET, *PSOCKET;\r
+\r
+NTSTATUS event_disconnect(PVOID TdiEventContext, CONNECTION_CONTEXT ConnectionContext, LONG DisconnectDataLength,\r
+                          PVOID DisconnectData, LONG DisconnectInformationLength, PVOID DisconnectInformation,\r
+                          ULONG DisconnectFlags)\r
+{\r
+    PSOCKET s = (PSOCKET) TdiEventContext;\r
+    PSTREAM_SOCKET streamSocket = (PSTREAM_SOCKET) ConnectionContext;\r
+    KeSetEvent(&streamSocket->disconnectEvent, 0, FALSE);\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+int __cdecl accept(int socket, struct sockaddr *addr, int *addrlen)\r
+{\r
+    return -1;\r
+}\r
+\r
+int __cdecl bind(int socket, const struct sockaddr *addr, int addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+    const struct sockaddr_in* localAddr = (const struct sockaddr_in*) addr;\r
+    UNICODE_STRING devName;\r
+    NTSTATUS status;\r
+\r
+    if (s->isBound || addr == NULL || addrlen < sizeof(struct sockaddr_in))\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    if (s->type == SOCK_DGRAM)\r
+    {\r
+        RtlInitUnicodeString(&devName, L"\\Device\\Udp");\r
+    }\r
+    else if (s->type == SOCK_STREAM)\r
+    {\r
+        RtlInitUnicodeString(&devName, L"\\Device\\Tcp");\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    status = tdi_open_transport_address(\r
+        &devName,\r
+        localAddr->sin_addr.s_addr,\r
+        localAddr->sin_port,\r
+        s->isShared,\r
+        &s->addressHandle,\r
+        &s->addressFileObject\r
+        );\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        s->addressFileObject = NULL;\r
+        s->addressHandle = (HANDLE) -1;\r
+        return status;\r
+    }\r
+\r
+    if (s->type == SOCK_STREAM)\r
+    {\r
+        tdi_set_event_handler(s->addressFileObject, TDI_EVENT_DISCONNECT, event_disconnect, s);\r
+    }\r
+\r
+    s->isBound = TRUE;\r
+\r
+    return 0;\r
+}\r
+\r
+int __cdecl close(int socket)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+\r
+    if (s->isBound)\r
+    {\r
+        if (s->type == SOCK_STREAM && s->streamSocket)\r
+        {\r
+            if (s->isConnected)\r
+            {\r
+                if (!s->isShuttingdown)\r
+                {\r
+                    tdi_disconnect(s->streamSocket->connectionFileObject, TDI_DISCONNECT_RELEASE);\r
+                }\r
+                //KeWaitForSingleObject(&s->streamSocket->disconnectEvent, Executive, KernelMode, FALSE, NULL);\r
+            }\r
+            if (s->streamSocket->connectionFileObject)\r
+            {\r
+                tdi_disassociate_address(s->streamSocket->connectionFileObject);\r
+                ObDereferenceObject(s->streamSocket->connectionFileObject);\r
+            }\r
+            if (s->streamSocket->connectionHandle != (HANDLE) -1)\r
+            {\r
+                ZwClose(s->streamSocket->connectionHandle);\r
+            }\r
+            ExFreePool(s->streamSocket);\r
+        }\r
+\r
+        if (s->type == SOCK_DGRAM || s->type == SOCK_STREAM)\r
+        {\r
+            ObDereferenceObject(s->addressFileObject);\r
+            if (s->addressHandle != (HANDLE) -1)\r
+            {\r
+                ZwClose(s->addressHandle);\r
+            }\r
+        }\r
+    }\r
+\r
+    ExFreePool(s);\r
+\r
+    return 0;\r
+}\r
+\r
+int __cdecl connect(int socket, const struct sockaddr *addr, int addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+    const struct sockaddr_in* remoteAddr = (const struct sockaddr_in*) addr;\r
+    UNICODE_STRING devName;\r
+    NTSTATUS status;\r
+\r
+    if (addr == NULL || addrlen < sizeof(struct sockaddr_in))\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    if (!s->isBound)\r
+    {\r
+        struct sockaddr_in localAddr;\r
+\r
+        localAddr.sin_family = AF_INET;\r
+        localAddr.sin_port = 0;\r
+        localAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+        status = bind(socket, (struct sockaddr*) &localAddr, sizeof(localAddr));\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    if (s->type == SOCK_STREAM)\r
+    {\r
+        if (s->isConnected || s->isListening)\r
+        {\r
+            return -1;\r
+        }\r
+\r
+        if (!s->streamSocket)\r
+        {\r
+            s->streamSocket = (PSTREAM_SOCKET) ExAllocatePool(NonPagedPool, sizeof(STREAM_SOCKET));\r
+\r
+            if (!s->streamSocket)\r
+            {\r
+                return STATUS_INSUFFICIENT_RESOURCES;\r
+            }\r
+\r
+            RtlZeroMemory(s->streamSocket, sizeof(STREAM_SOCKET));\r
+            s->streamSocket->connectionHandle = (HANDLE) -1;\r
+            KeInitializeEvent(&s->streamSocket->disconnectEvent, NotificationEvent, FALSE);\r
+        }\r
+\r
+        RtlInitUnicodeString(&devName, L"\\Device\\Tcp");\r
+\r
+        status = tdi_open_connection_endpoint(\r
+            &devName,\r
+            s->streamSocket,\r
+            s->isShared,\r
+            &s->streamSocket->connectionHandle,\r
+            &s->streamSocket->connectionFileObject\r
+            );\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            s->streamSocket->connectionFileObject = NULL;\r
+            s->streamSocket->connectionHandle = (HANDLE) -1;\r
+            return status;\r
+        }\r
+\r
+        status = tdi_associate_address(s->streamSocket->connectionFileObject, s->addressHandle);\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            ObDereferenceObject(s->streamSocket->connectionFileObject);\r
+            s->streamSocket->connectionFileObject = NULL;\r
+            ZwClose(s->streamSocket->connectionHandle);\r
+            s->streamSocket->connectionHandle = (HANDLE) -1;\r
+            return status;\r
+        }\r
+\r
+        status = tdi_connect(\r
+            s->streamSocket->connectionFileObject,\r
+            remoteAddr->sin_addr.s_addr,\r
+            remoteAddr->sin_port\r
+            );\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            tdi_disassociate_address(s->streamSocket->connectionFileObject);\r
+            ObDereferenceObject(s->streamSocket->connectionFileObject);\r
+            s->streamSocket->connectionFileObject = NULL;\r
+            ZwClose(s->streamSocket->connectionHandle);\r
+            s->streamSocket->connectionHandle = (HANDLE) -1;\r
+            return status;\r
+        }\r
+        else\r
+        {\r
+            s->peer = *addr;\r
+            s->isConnected = TRUE;\r
+            return 0;\r
+        }\r
+    }\r
+    else if (s->type == SOCK_DGRAM)\r
+    {\r
+        s->peer = *addr;\r
+        if (remoteAddr->sin_addr.s_addr == 0 && remoteAddr->sin_port == 0)\r
+        {\r
+            s->isConnected = FALSE;\r
+        }\r
+        else\r
+        {\r
+            s->isConnected = TRUE;\r
+        }\r
+        return 0;\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl getpeername(int socket, struct sockaddr *addr, int *addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+\r
+    if (!s->isConnected || addr == NULL || addrlen == NULL || *addrlen < sizeof(struct sockaddr_in))\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    *addr = s->peer;\r
+    *addrlen = sizeof(s->peer);\r
+\r
+    return 0;\r
+}\r
+\r
+int __cdecl getsockname(int socket, struct sockaddr *addr, int *addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+    struct sockaddr_in* localAddr = (struct sockaddr_in*) addr;\r
+\r
+    if (!s->isBound || addr == NULL || addrlen == NULL || *addrlen < sizeof(struct sockaddr_in))\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    if (s->type == SOCK_DGRAM)\r
+    {\r
+        *addrlen = sizeof(struct sockaddr_in);\r
+\r
+        return tdi_query_address(\r
+            s->addressFileObject,\r
+            &localAddr->sin_addr.s_addr,\r
+            &localAddr->sin_port\r
+            );\r
+    }\r
+    else if (s->type == SOCK_STREAM)\r
+    {\r
+        *addrlen = sizeof(struct sockaddr_in);\r
+\r
+        return tdi_query_address(\r
+            s->streamSocket && s->streamSocket->connectionFileObject ? s->streamSocket->connectionFileObject : s->addressFileObject,\r
+            &localAddr->sin_addr.s_addr,\r
+            &localAddr->sin_port\r
+            );\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl getsockopt(int socket, int level, int optname, char *optval, int *optlen)\r
+{\r
+    return -1;\r
+}\r
+\r
+int __cdecl listen(int socket, int backlog)\r
+{\r
+    return -1;\r
+}\r
+\r
+int __cdecl recv(int socket, char *buf, int len, int flags)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+\r
+    if (s->type == SOCK_DGRAM)\r
+    {\r
+        return recvfrom(socket, buf, len, flags, 0, 0);\r
+    }\r
+    else if (s->type == SOCK_STREAM)\r
+    {\r
+        if (!s->isConnected)\r
+        {\r
+            return -1;\r
+        }\r
+\r
+        return tdi_recv_stream(\r
+            s->streamSocket->connectionFileObject,\r
+            buf,\r
+            len,\r
+            flags == MSG_OOB ? TDI_RECEIVE_EXPEDITED : TDI_RECEIVE_NORMAL\r
+            );\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl recvfrom(int socket, char *buf, int len, int flags, struct sockaddr *addr, int *addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+    struct sockaddr_in* returnAddr = (struct sockaddr_in*) addr;\r
+\r
+    if (s->type == SOCK_STREAM)\r
+    {\r
+        return recv(socket, buf, len, flags);\r
+    }\r
+    else if (s->type == SOCK_DGRAM)\r
+    {\r
+        u_long* sin_addr = 0;\r
+        u_short* sin_port = 0;\r
+\r
+        if (!s->isBound)\r
+        {\r
+            return -1;\r
+        }\r
+\r
+        if (addr != NULL && addrlen != NULL && *addrlen >= sizeof(struct sockaddr_in))\r
+        {\r
+            sin_addr = &returnAddr->sin_addr.s_addr;\r
+            sin_port = &returnAddr->sin_port;\r
+            *addrlen = sizeof(struct sockaddr_in);\r
+        }\r
+\r
+        return tdi_recv_dgram(\r
+            s->addressFileObject,\r
+            sin_addr,\r
+            sin_port,\r
+            buf,\r
+            len,\r
+            TDI_RECEIVE_NORMAL\r
+            );\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)\r
+{\r
+    return -1;\r
+}\r
+\r
+int __cdecl send(int socket, const char *buf, int len, int flags)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+\r
+    if (!s->isConnected)\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    if (s->type == SOCK_DGRAM)\r
+    {\r
+        return sendto(socket, buf, len, flags, &s->peer, sizeof(s->peer));\r
+    }\r
+    else if (s->type == SOCK_STREAM)\r
+    {\r
+        return tdi_send_stream(\r
+            s->streamSocket->connectionFileObject,\r
+            buf,\r
+            len,\r
+            flags == MSG_OOB ? TDI_SEND_EXPEDITED : 0\r
+            );\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl sendto(int socket, const char *buf, int len, int flags, const struct sockaddr *addr, int addrlen)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+    const struct sockaddr_in* remoteAddr = (const struct sockaddr_in*) addr;\r
+\r
+    if (s->type == SOCK_STREAM)\r
+    {\r
+        return send(socket, buf, len, flags);\r
+    }\r
+    else if (s->type == SOCK_DGRAM)\r
+    {\r
+        if (addr == NULL || addrlen < sizeof(struct sockaddr_in))\r
+        {\r
+            return -1;\r
+        }\r
+\r
+        if (!s->isBound)\r
+        {\r
+            struct sockaddr_in localAddr;\r
+            NTSTATUS status;\r
+\r
+            localAddr.sin_family = AF_INET;\r
+            localAddr.sin_port = 0;\r
+            localAddr.sin_addr.s_addr = INADDR_ANY;\r
+\r
+            status = bind(socket, (struct sockaddr*) &localAddr, sizeof(localAddr));\r
+\r
+            if (!NT_SUCCESS(status))\r
+            {\r
+                return status;\r
+            }\r
+        }\r
+\r
+        return tdi_send_dgram(\r
+            s->addressFileObject,\r
+            remoteAddr->sin_addr.s_addr,\r
+            remoteAddr->sin_port,\r
+            buf,\r
+            len\r
+            );\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl setsockopt(int socket, int level, int optname, const char *optval, int optlen)\r
+{\r
+    return -1;\r
+}\r
+\r
+int __cdecl shutdown(int socket, int how)\r
+{\r
+    PSOCKET s = (PSOCKET) -socket;\r
+\r
+    if (!s->isConnected)\r
+    {\r
+        return -1;\r
+    }\r
+\r
+    if (s->type == SOCK_STREAM)\r
+    {\r
+        s->isShuttingdown = TRUE;\r
+        return tdi_disconnect(s->streamSocket->connectionFileObject, TDI_DISCONNECT_RELEASE);\r
+    }\r
+    else\r
+    {\r
+        return -1;\r
+    }\r
+}\r
+\r
+int __cdecl socket(int af, int type, int protocol)\r
+{\r
+    PSOCKET s;\r
+\r
+    if (af != AF_INET ||\r
+       (type != SOCK_DGRAM && type != SOCK_STREAM) ||\r
+       (type == SOCK_DGRAM && protocol != IPPROTO_UDP && protocol != 0) ||\r
+       (type == SOCK_STREAM && protocol != IPPROTO_TCP && protocol != 0)\r
+       )\r
+    {\r
+        return STATUS_INVALID_PARAMETER;\r
+    }\r
+\r
+    s = (PSOCKET) ExAllocatePool(NonPagedPool, sizeof(SOCKET));\r
+\r
+    if (!s)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlZeroMemory(s, sizeof(SOCKET));\r
+\r
+    s->type = type;\r
+    s->addressHandle = (HANDLE) -1;\r
+\r
+    return -(int)s;\r
+}\r
diff --git a/src/httpdisk/ksocket.h b/src/httpdisk/ksocket.h
new file mode 100644 (file)
index 0000000..206c8f0
--- /dev/null
@@ -0,0 +1,146 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#if !defined(KSOCKET_H)\r
+#define KSOCKET_H\r
+\r
+#if defined(__cplusplus)\r
+extern "C" {\r
+#endif\r
+\r
+typedef unsigned char   u_char;\r
+typedef unsigned short  u_short;\r
+typedef unsigned int    u_int;\r
+typedef unsigned long   u_long;\r
+\r
+#define AF_INET             2\r
+\r
+#define SOCK_STREAM         1\r
+#define SOCK_DGRAM          2\r
+#define SOCK_RAW            3\r
+\r
+#define IPPROTO_ICMP        1\r
+#define IPPROTO_TCP         6\r
+#define IPPROTO_UDP         17\r
+\r
+#define INADDR_ANY          0x00000000\r
+#define INADDR_LOOPBACK     0x7f000001\r
+#define INADDR_BROADCAST    0xffffffff\r
+#define INADDR_NONE         0xffffffff\r
+\r
+#define MSG_OOB             0x1\r
+\r
+#define SOMAXCONN           5\r
+\r
+#define SD_RECEIVE          0x00\r
+#define SD_SEND             0x01\r
+#define SD_BOTH             0x02\r
+\r
+#ifndef FD_SETSIZE\r
+#define FD_SETSIZE          64\r
+#endif\r
+\r
+typedef struct fd_set {\r
+    u_int   fd_count;\r
+    int     fd_array[FD_SETSIZE];\r
+} fd_set;\r
+\r
+struct hostent {\r
+    char    *h_name;\r
+    char    **h_aliases;\r
+    short   h_addrtype;\r
+    short   h_length;\r
+    char    **h_addr_list;\r
+};\r
+\r
+#define h_addr h_addr_list[0]\r
+\r
+struct in_addr {\r
+    union {\r
+        struct { u_char s_b1, s_b2, s_b3, s_b4; }   S_un_b;\r
+        struct { u_short s_w1, s_w2; }              S_un_w;\r
+        u_long                                      S_addr;\r
+    } S_un;\r
+};\r
+\r
+#define s_addr S_un.S_addr\r
+\r
+struct protoent {\r
+    char    *p_name;\r
+    char    **p_aliases;\r
+    short   p_proto;\r
+};\r
+\r
+struct servent {\r
+    char    *s_name;\r
+    char    **s_aliases;\r
+    short   s_port;\r
+    char    *s_proto;\r
+};\r
+\r
+struct sockaddr {\r
+    u_short sa_family;\r
+    char    sa_data[14];\r
+};\r
+\r
+struct sockaddr_in {\r
+    short           sin_family;\r
+    u_short         sin_port;\r
+    struct in_addr  sin_addr;\r
+    char            sin_zero[8];\r
+};\r
+\r
+struct timeval {\r
+    long tv_sec;\r
+    long tv_usec;\r
+};\r
+\r
+int __cdecl accept(int socket, struct sockaddr *addr, int *addrlen);\r
+int __cdecl bind(int socket, const struct sockaddr *addr, int addrlen);\r
+int __cdecl close(int socket);\r
+int __cdecl connect(int socket, const struct sockaddr *addr, int addrlen);\r
+struct hostent * __cdecl gethostbyaddr(const char *addr, int addrlen, int type);\r
+struct hostent * __cdecl gethostbyname(const char *name);\r
+int __cdecl gethostname(char *name, int namelen);\r
+int __cdecl getpeername(int socket, struct sockaddr *addr, int *addrlen);\r
+struct protoent * __cdecl getprotobyname(const char *name);\r
+struct protoent * __cdecl getprotobynumber(int number);\r
+struct servent * __cdecl getservbyname(const char *name, const char *proto);\r
+struct servent * __cdecl getservbyport(int port, const char *proto);\r
+int __cdecl getsockname(int socket, struct sockaddr *addr, int *addrlen);\r
+int __cdecl getsockopt(int socket, int level, int optname, char *optval, int *optlen);\r
+u_long __cdecl htonl(u_long hostlong);\r
+u_short __cdecl htons(u_short hostshort);\r
+u_long __cdecl inet_addr(const char *name);\r
+int __cdecl inet_aton(const char *name, struct in_addr *addr);\r
+char * __cdecl inet_ntoa(struct in_addr addr);\r
+int __cdecl listen(int socket, int backlog);\r
+u_long __cdecl ntohl(u_long netlong);\r
+u_short __cdecl ntohs(u_short netshort);\r
+int __cdecl recv(int socket, char *buf, int len, int flags);\r
+int __cdecl recvfrom(int socket, char *buf, int len, int flags, struct sockaddr *addr, int *addrlen);\r
+int __cdecl select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout);\r
+int __cdecl send(int socket, const char *buf, int len, int flags);\r
+int __cdecl sendto(int socket, const char *buf, int len, int flags, const struct sockaddr *addr, int addrlen);\r
+int __cdecl setsockopt(int socket, int level, int optname, const char *optval, int optlen);\r
+int __cdecl shutdown(int socket, int how);\r
+int __cdecl socket(int af, int type, int protocol);\r
+\r
+#if defined(__cplusplus)\r
+}\r
+#endif\r
+\r
+#endif // !defined(KSOCKET_H)\r
diff --git a/src/httpdisk/ktdi.c b/src/httpdisk/ktdi.c
new file mode 100644 (file)
index 0000000..4c5ee20
--- /dev/null
@@ -0,0 +1,768 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#include <ntddk.h>\r
+#include <tdikrnl.h>\r
+#include "ktdi.h"\r
+\r
+NTSTATUS tdi_open_transport_address(PUNICODE_STRING devName, ULONG addr, USHORT port, BOOLEAN shared, PHANDLE addressHandle, PFILE_OBJECT *addressFileObject)\r
+{\r
+    OBJECT_ATTRIBUTES           attr;\r
+    PFILE_FULL_EA_INFORMATION   eaBuffer;\r
+    ULONG                       eaSize;\r
+    PTA_IP_ADDRESS              localAddr;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+#if (VER_PRODUCTBUILD >= 2195)\r
+    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);\r
+#else\r
+    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE, NULL, NULL);\r
+#endif\r
+\r
+    eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +\r
+             TDI_TRANSPORT_ADDRESS_LENGTH                      +\r
+             1                                                 +\r
+             sizeof(TA_IP_ADDRESS);\r
+\r
+    eaBuffer = (PFILE_FULL_EA_INFORMATION) ExAllocatePool(PagedPool, eaSize);\r
+\r
+    if (eaBuffer == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    eaBuffer->NextEntryOffset = 0;\r
+    eaBuffer->Flags = 0;\r
+    eaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;\r
+    eaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS);\r
+\r
+    RtlCopyMemory(eaBuffer->EaName, TdiTransportAddress, eaBuffer->EaNameLength + 1);\r
+\r
+    localAddr = (PTA_IP_ADDRESS)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);\r
+\r
+    localAddr->TAAddressCount = 1;\r
+    localAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;\r
+    localAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;\r
+    localAddr->Address[0].Address[0].sin_port = port;\r
+    localAddr->Address[0].Address[0].in_addr = addr;\r
+\r
+    RtlZeroMemory(localAddr->Address[0].Address[0].sin_zero, sizeof(localAddr->Address[0].Address[0].sin_zero));\r
+\r
+    status = ZwCreateFile(\r
+        addressHandle,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        &attr,\r
+        &iosb,\r
+        NULL,\r
+        FILE_ATTRIBUTE_NORMAL,\r
+        shared ? FILE_SHARE_READ | FILE_SHARE_WRITE : 0,\r
+        FILE_OPEN,\r
+        0,\r
+        eaBuffer,\r
+        eaSize\r
+        );\r
+\r
+    ExFreePool(eaBuffer);\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        return status;\r
+    }\r
+\r
+    status = ObReferenceObjectByHandle(*addressHandle, FILE_ALL_ACCESS, NULL, KernelMode, addressFileObject, NULL);\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        ZwClose(*addressHandle);\r
+        return status;\r
+    }\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS tdi_open_connection_endpoint(PUNICODE_STRING devName, PVOID connectionContext, BOOLEAN shared, PHANDLE connectionHandle, PFILE_OBJECT *connectionFileObject)\r
+{\r
+    OBJECT_ATTRIBUTES           attr;\r
+    PFILE_FULL_EA_INFORMATION   eaBuffer;\r
+    ULONG                       eaSize;\r
+    PVOID                       *context;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+#if (VER_PRODUCTBUILD >= 2195)\r
+    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);\r
+#else\r
+    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE, NULL, NULL);\r
+#endif\r
+\r
+    eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +\r
+             TDI_CONNECTION_CONTEXT_LENGTH                     +\r
+             1                                                 +\r
+             sizeof(int);\r
+\r
+    eaBuffer = (PFILE_FULL_EA_INFORMATION) ExAllocatePool(PagedPool, eaSize);\r
+\r
+    if (eaBuffer == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    eaBuffer->NextEntryOffset = 0;\r
+    eaBuffer->Flags = 0;\r
+    eaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;\r
+    eaBuffer->EaValueLength = sizeof(int);\r
+\r
+    RtlCopyMemory(eaBuffer->EaName, TdiConnectionContext, eaBuffer->EaNameLength + 1);\r
+\r
+    context = (PVOID*) &(eaBuffer->EaName[eaBuffer->EaNameLength + 1]);\r
+\r
+    *context = connectionContext;\r
+\r
+    status = ZwCreateFile(\r
+        connectionHandle,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        &attr,\r
+        &iosb,\r
+        NULL,\r
+        FILE_ATTRIBUTE_NORMAL,\r
+        shared ? FILE_SHARE_READ | FILE_SHARE_WRITE : 0,\r
+        FILE_OPEN,\r
+        0,\r
+        eaBuffer,\r
+        eaSize\r
+        );\r
+\r
+    ExFreePool(eaBuffer);\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        return status;\r
+    }\r
+\r
+    status = ObReferenceObjectByHandle(*connectionHandle, FILE_ALL_ACCESS, NULL, KernelMode, connectionFileObject, NULL);\r
+\r
+    if (!NT_SUCCESS(status))\r
+    {\r
+        ZwClose(*connectionHandle);\r
+        return status;\r
+    }\r
+\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+NTSTATUS tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler, PVOID eventContext)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(addressFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devObj, addressFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    TdiBuildSetEventHandler(irp, devObj, addressFileObject, NULL, NULL, eventType, eventHandler, eventContext);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+NTSTATUS tdi_unset_event_handler(PFILE_OBJECT addressFileObject, LONG eventType)\r
+{\r
+    return tdi_set_event_handler(addressFileObject, eventType, NULL, NULL);\r
+}\r
+\r
+NTSTATUS tdi_associate_address(PFILE_OBJECT connectionFileObject, HANDLE addressHandle)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    TdiBuildAssociateAddress(irp, devObj, connectionFileObject, NULL, NULL, addressHandle);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+NTSTATUS tdi_disassociate_address(PFILE_OBJECT connectionFileObject)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    TdiBuildDisassociateAddress(irp, devObj, connectionFileObject, NULL, NULL);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+NTSTATUS tdi_connect(PFILE_OBJECT connectionFileObject, ULONG addr, USHORT port)\r
+{\r
+    PDEVICE_OBJECT              devObj;\r
+    KEVENT                      event;\r
+    PTDI_CONNECTION_INFORMATION remoteInfo;\r
+    PTA_IP_ADDRESS              remoteAddr;\r
+    PTDI_CONNECTION_INFORMATION returnInfo;\r
+    PTA_IP_ADDRESS              returnAddr;\r
+    PIRP                        irp;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    remoteInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, 2 * sizeof(TDI_CONNECTION_INFORMATION) + 2 * sizeof(TA_IP_ADDRESS));\r
+\r
+    if (remoteInfo == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlZeroMemory(remoteInfo, 2 * sizeof(TDI_CONNECTION_INFORMATION) + 2 * sizeof(TA_IP_ADDRESS));\r
+\r
+    remoteInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);\r
+    remoteInfo->RemoteAddress = (PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION);\r
+\r
+    remoteAddr = (PTA_IP_ADDRESS) remoteInfo->RemoteAddress;\r
+\r
+    remoteAddr->TAAddressCount = 1;\r
+    remoteAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;\r
+    remoteAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;\r
+    remoteAddr->Address[0].Address[0].sin_port = port;\r
+    remoteAddr->Address[0].Address[0].in_addr = addr;\r
+\r
+    returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));\r
+\r
+    returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);\r
+    returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION);\r
+\r
+    returnAddr = (PTA_IP_ADDRESS) returnInfo->RemoteAddress;\r
+\r
+    returnAddr->TAAddressCount = 1;\r
+    returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;\r
+    returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        ExFreePool(remoteInfo);\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    TdiBuildConnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, remoteInfo, returnInfo);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    ExFreePool(remoteInfo);\r
+\r
+    return status;\r
+}\r
+\r
+NTSTATUS tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    TdiBuildDisconnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, flags, NULL, NULL);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return status;\r
+}\r
+\r
+NTSTATUS tdi_send_dgram(PFILE_OBJECT addressFileObject, ULONG addr, USHORT port, const char *buf, int len)\r
+{\r
+    PDEVICE_OBJECT              devObj;\r
+    KEVENT                      event;\r
+    PTDI_CONNECTION_INFORMATION remoteInfo;\r
+    PTA_IP_ADDRESS              remoteAddr;\r
+    PIRP                        irp;\r
+    PMDL                        mdl;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(addressFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    remoteInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));\r
+\r
+    if (remoteInfo == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlZeroMemory(remoteInfo, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));\r
+\r
+    remoteInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);\r
+    remoteInfo->RemoteAddress = (PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION);\r
+\r
+    remoteAddr = (PTA_IP_ADDRESS) remoteInfo->RemoteAddress;\r
+\r
+    remoteAddr->TAAddressCount = 1;\r
+    remoteAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;\r
+    remoteAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;\r
+    remoteAddr->Address[0].Address[0].sin_port = port;\r
+    remoteAddr->Address[0].Address[0].in_addr = addr;\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, devObj, addressFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        ExFreePool(remoteInfo);\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    if (len)\r
+    {\r
+        mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL);\r
+\r
+        if (mdl == NULL)\r
+        {\r
+            IoFreeIrp(irp);\r
+            ExFreePool(remoteInfo);\r
+            return STATUS_INSUFFICIENT_RESOURCES;\r
+        }\r
+\r
+        __try\r
+        {\r
+            MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);\r
+            status = STATUS_SUCCESS;\r
+        }\r
+        __except (EXCEPTION_EXECUTE_HANDLER)\r
+        {\r
+            IoFreeMdl(mdl);\r
+            IoFreeIrp(irp);\r
+            ExFreePool(remoteInfo);\r
+            status = STATUS_INVALID_USER_BUFFER;\r
+        }\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    TdiBuildSendDatagram(irp, devObj, addressFileObject, NULL, NULL, len ? mdl : 0, len, remoteInfo);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    ExFreePool(remoteInfo);\r
+\r
+    return NT_SUCCESS(status) ? iosb.Information : status;\r
+}\r
+\r
+NTSTATUS tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char *buf, int len, ULONG flags)\r
+{\r
+    PDEVICE_OBJECT              devObj;\r
+    KEVENT                      event;\r
+    PTDI_CONNECTION_INFORMATION remoteInfo;\r
+    PTDI_CONNECTION_INFORMATION returnInfo;\r
+    PTA_IP_ADDRESS              returnAddr;\r
+    PIRP                        irp;\r
+    PMDL                        mdl;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(addressFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    remoteInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));\r
+\r
+    if (remoteInfo == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlZeroMemory(remoteInfo, 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));\r
+\r
+    remoteInfo->RemoteAddressLength = 0;\r
+    remoteInfo->RemoteAddress = NULL;\r
+\r
+    returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION));\r
+\r
+    returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);\r
+    returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION);\r
+\r
+    returnAddr = (PTA_IP_ADDRESS) returnInfo->RemoteAddress;\r
+\r
+    returnAddr->TAAddressCount = 1;\r
+    returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;\r
+    returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, devObj, addressFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        ExFreePool(remoteInfo);\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    if (len)\r
+    {\r
+        mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL);\r
+\r
+        if (mdl == NULL)\r
+        {\r
+            IoFreeIrp(irp);\r
+            ExFreePool(remoteInfo);\r
+            return STATUS_INSUFFICIENT_RESOURCES;\r
+        }\r
+\r
+        __try\r
+        {\r
+            MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);\r
+            status = STATUS_SUCCESS;\r
+        }\r
+        __except (EXCEPTION_EXECUTE_HANDLER)\r
+        {\r
+            IoFreeMdl(mdl);\r
+            IoFreeIrp(irp);\r
+            ExFreePool(remoteInfo);\r
+            status = STATUS_INVALID_USER_BUFFER;\r
+        }\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    TdiBuildReceiveDatagram(irp, devObj, addressFileObject, NULL, NULL, len ? mdl : 0, len, remoteInfo, returnInfo, flags);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    if (addr)\r
+    {\r
+        *addr = returnAddr->Address[0].Address[0].in_addr;\r
+    }\r
+\r
+    if (port)\r
+    {\r
+        *port = returnAddr->Address[0].Address[0].sin_port;\r
+    }\r
+\r
+    ExFreePool(remoteInfo);\r
+\r
+    return NT_SUCCESS(status) ? iosb.Information : status;\r
+}\r
+\r
+NTSTATUS tdi_send_stream(PFILE_OBJECT connectionFileObject, const char *buf, int len, ULONG flags)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    PMDL            mdl;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_SEND, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    if (len)\r
+    {\r
+        mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL);\r
+\r
+        if (mdl == NULL)\r
+        {\r
+            IoFreeIrp(irp);\r
+            return STATUS_INSUFFICIENT_RESOURCES;\r
+        }\r
+\r
+        __try\r
+        {\r
+            MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);\r
+            status = STATUS_SUCCESS;\r
+        }\r
+        __except (EXCEPTION_EXECUTE_HANDLER)\r
+        {\r
+            IoFreeMdl(mdl);\r
+            IoFreeIrp(irp);\r
+            status = STATUS_INVALID_USER_BUFFER;\r
+        }\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    TdiBuildSend(irp, devObj, connectionFileObject, NULL, NULL, len ? mdl : 0, flags, len);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return NT_SUCCESS(status) ? iosb.Information : status;\r
+}\r
+\r
+NTSTATUS tdi_recv_stream(PFILE_OBJECT connectionFileObject, char *buf, int len, ULONG flags)\r
+{\r
+    PDEVICE_OBJECT  devObj;\r
+    KEVENT          event;\r
+    PIRP            irp;\r
+    PMDL            mdl;\r
+    IO_STATUS_BLOCK iosb;\r
+    NTSTATUS        status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(connectionFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE, devObj, connectionFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    if (len)\r
+    {\r
+        mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL);\r
+\r
+        if (mdl == NULL)\r
+        {\r
+            IoFreeIrp(irp);\r
+            return STATUS_INSUFFICIENT_RESOURCES;\r
+        }\r
+\r
+        __try\r
+        {\r
+            MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);\r
+            status = STATUS_SUCCESS;\r
+        }\r
+        __except (EXCEPTION_EXECUTE_HANDLER)\r
+        {\r
+            IoFreeMdl(mdl);\r
+            IoFreeIrp(irp);\r
+            status = STATUS_INVALID_USER_BUFFER;\r
+        }\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    TdiBuildReceive(irp, devObj, connectionFileObject, NULL, NULL, len ? mdl : 0, flags, len);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    return NT_SUCCESS(status) ? iosb.Information : status;\r
+}\r
+\r
+NTSTATUS tdi_query_address(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port)\r
+{\r
+    PDEVICE_OBJECT              devObj;\r
+    KEVENT                      event;\r
+    PTRANSPORT_ADDRESS          localInfo;\r
+    PTA_IP_ADDRESS              localAddr;\r
+    PIRP                        irp;\r
+    PMDL                        mdl;\r
+    IO_STATUS_BLOCK             iosb;\r
+    NTSTATUS                    status;\r
+\r
+    devObj = IoGetRelatedDeviceObject(addressFileObject);\r
+\r
+    KeInitializeEvent(&event, NotificationEvent, FALSE);\r
+\r
+    localInfo = (PTRANSPORT_ADDRESS) ExAllocatePool(NonPagedPool, sizeof(TDI_ADDRESS_INFO)*10);\r
+\r
+    if (localInfo == NULL)\r
+    {\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    RtlZeroMemory(localInfo, sizeof(TDI_ADDRESS_INFO)*10);\r
+\r
+    irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, devObj, addressFileObject, &event, &iosb);\r
+\r
+    if (irp == NULL)\r
+    {\r
+        ExFreePool(localInfo);\r
+        return STATUS_INSUFFICIENT_RESOURCES;\r
+    }\r
+\r
+    {\r
+        mdl = IoAllocateMdl((void*) localInfo, sizeof(TDI_ADDRESS_INFO)*10, FALSE, FALSE, NULL);\r
+\r
+        if (mdl == NULL)\r
+        {\r
+            IoFreeIrp(irp);\r
+            ExFreePool(localInfo);\r
+            return STATUS_INSUFFICIENT_RESOURCES;\r
+        }\r
+\r
+        __try\r
+        {\r
+            MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);\r
+            status = STATUS_SUCCESS;\r
+        }\r
+        __except (EXCEPTION_EXECUTE_HANDLER)\r
+        {\r
+            IoFreeMdl(mdl);\r
+            IoFreeIrp(irp);\r
+            ExFreePool(localInfo);\r
+            status = STATUS_INVALID_USER_BUFFER;\r
+        }\r
+\r
+        if (!NT_SUCCESS(status))\r
+        {\r
+            return status;\r
+        }\r
+    }\r
+\r
+    TdiBuildQueryInformation(irp, devObj, addressFileObject, NULL, NULL, TDI_QUERY_ADDRESS_INFO, mdl);\r
+\r
+    status = IoCallDriver(devObj, irp);\r
+\r
+    if (status == STATUS_PENDING)\r
+    {\r
+        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
+        status = iosb.Status;\r
+    }\r
+\r
+    localAddr = (PTA_IP_ADDRESS)&localInfo->Address[0];\r
+\r
+    if (addr)\r
+    {\r
+        *addr = localAddr->Address[0].Address[0].in_addr;\r
+    }\r
+\r
+    if (port)\r
+    {\r
+        *port = localAddr->Address[0].Address[0].sin_port;\r
+    }\r
+\r
+    ExFreePool(localInfo);\r
+\r
+    return status;\r
+}\r
diff --git a/src/httpdisk/ktdi.h b/src/httpdisk/ktdi.h
new file mode 100644 (file)
index 0000000..7cd018b
--- /dev/null
@@ -0,0 +1,29 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+NTSTATUS tdi_open_transport_address(PUNICODE_STRING devName, ULONG addr, USHORT port, BOOLEAN shared, PHANDLE addressHandle, PFILE_OBJECT *addressFileObject);\r
+NTSTATUS tdi_open_connection_endpoint(PUNICODE_STRING devName, PVOID connectionContext, BOOLEAN shared, PHANDLE connectionHandle, PFILE_OBJECT *connectionFileObject);\r
+NTSTATUS tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler, PVOID eventContext);\r
+NTSTATUS tdi_unset_event_handler(PFILE_OBJECT addressFileObject, LONG eventType);\r
+NTSTATUS tdi_associate_address(PFILE_OBJECT connectionFileObject, HANDLE addressHandle);\r
+NTSTATUS tdi_disassociate_address(PFILE_OBJECT connectionFileObject);\r
+NTSTATUS tdi_connect(PFILE_OBJECT connectionFileObject, ULONG addr, USHORT port);\r
+NTSTATUS tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags);\r
+NTSTATUS tdi_send_dgram(PFILE_OBJECT addressFileObject, ULONG addr, USHORT port, const char *buf, int len);\r
+NTSTATUS tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char *buf, int len, ULONG flags);\r
+NTSTATUS tdi_send_stream(PFILE_OBJECT connectionFileObject, const char *buf, int len, ULONG flags);\r
+NTSTATUS tdi_recv_stream(PFILE_OBJECT connectionFileObject, char *buf, int len, ULONG flags);\r
+NTSTATUS tdi_query_address(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port);\r
diff --git a/src/httpdisk/readme.txt b/src/httpdisk/readme.txt
new file mode 100644 (file)
index 0000000..a76e1e8
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+    The GNU General Public License is also available from:\r
+    http://www.gnu.org/copyleft/gpl.html\r
+\r
+    Windows and Windows NT are either registered trademarks or trademarks of\r
+    Microsoft Corporation in the United States and/or other countries.\r
+\r
+    Please send comments, corrections and contributions to bosse@acc.umu.se\r
+\r
+    The most recent version of this program is available from:\r
+    http://www.acc.umu.se/~bosse/\r
+\r
+    Revision history:\r
+\r
+    3. 2006-03-08\r
+       Small bug fix in handling of receive data length.\r
+\r
+    2. 2006-03-05\r
+       Added support for persistent connections.\r
+\r
+    1. 2006-02-11\r
+       Initial release.\r
diff --git a/src/httpdisk_util/COPYING.TXT b/src/httpdisk_util/COPYING.TXT
new file mode 100644 (file)
index 0000000..fbdd65f
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE\r
+                      Version 2, June 1991\r
+\r
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.\r
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ Everyone is permitted to copy and distribute verbatim copies\r
+ of this license document, but changing it is not allowed.\r
+\r
+                           Preamble\r
+\r
+  The licenses for most software are designed to take away your\r
+freedom to share and change it.  By contrast, the GNU General Public\r
+License is intended to guarantee your freedom to share and change free\r
+software--to make sure the software is free for all its users.  This\r
+General Public License applies to most of the Free Software\r
+Foundation's software and to any other program whose authors commit to\r
+using it.  (Some other Free Software Foundation software is covered by\r
+the GNU Library General Public License instead.)  You can apply it to\r
+your programs, too.\r
+\r
+  When we speak of free software, we are referring to freedom, not\r
+price.  Our General Public Licenses are designed to make sure that you\r
+have the freedom to distribute copies of free software (and charge for\r
+this service if you wish), that you receive source code or can get it\r
+if you want it, that you can change the software or use pieces of it\r
+in new free programs; and that you know you can do these things.\r
+\r
+  To protect your rights, we need to make restrictions that forbid\r
+anyone to deny you these rights or to ask you to surrender the rights.\r
+These restrictions translate to certain responsibilities for you if you\r
+distribute copies of the software, or if you modify it.\r
+\r
+  For example, if you distribute copies of such a program, whether\r
+gratis or for a fee, you must give the recipients all the rights that\r
+you have.  You must make sure that they, too, receive or can get the\r
+source code.  And you must show them these terms so they know their\r
+rights.\r
+\r
+  We protect your rights with two steps: (1) copyright the software, and\r
+(2) offer you this license which gives you legal permission to copy,\r
+distribute and/or modify the software.\r
+\r
+  Also, for each author's protection and ours, we want to make certain\r
+that everyone understands that there is no warranty for this free\r
+software.  If the software is modified by someone else and passed on, we\r
+want its recipients to know that what they have is not the original, so\r
+that any problems introduced by others will not reflect on the original\r
+authors' reputations.\r
+\r
+  Finally, any free program is threatened constantly by software\r
+patents.  We wish to avoid the danger that redistributors of a free\r
+program will individually obtain patent licenses, in effect making the\r
+program proprietary.  To prevent this, we have made it clear that any\r
+patent must be licensed for everyone's free use or not licensed at all.\r
+\r
+  The precise terms and conditions for copying, distribution and\r
+modification follow.\r
+\f\r
+                   GNU GENERAL PUBLIC LICENSE\r
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\r
+\r
+  0. This License applies to any program or other work which contains\r
+a notice placed by the copyright holder saying it may be distributed\r
+under the terms of this General Public License.  The "Program", below,\r
+refers to any such program or work, and a "work based on the Program"\r
+means either the Program or any derivative work under copyright law:\r
+that is to say, a work containing the Program or a portion of it,\r
+either verbatim or with modifications and/or translated into another\r
+language.  (Hereinafter, translation is included without limitation in\r
+the term "modification".)  Each licensee is addressed as "you".\r
+\r
+Activities other than copying, distribution and modification are not\r
+covered by this License; they are outside its scope.  The act of\r
+running the Program is not restricted, and the output from the Program\r
+is covered only if its contents constitute a work based on the\r
+Program (independent of having been made by running the Program).\r
+Whether that is true depends on what the Program does.\r
+\r
+  1. You may copy and distribute verbatim copies of the Program's\r
+source code as you receive it, in any medium, provided that you\r
+conspicuously and appropriately publish on each copy an appropriate\r
+copyright notice and disclaimer of warranty; keep intact all the\r
+notices that refer to this License and to the absence of any warranty;\r
+and give any other recipients of the Program a copy of this License\r
+along with the Program.\r
+\r
+You may charge a fee for the physical act of transferring a copy, and\r
+you may at your option offer warranty protection in exchange for a fee.\r
+\r
+  2. You may modify your copy or copies of the Program or any portion\r
+of it, thus forming a work based on the Program, and copy and\r
+distribute such modifications or work under the terms of Section 1\r
+above, provided that you also meet all of these conditions:\r
+\r
+    a) You must cause the modified files to carry prominent notices\r
+    stating that you changed the files and the date of any change.\r
+\r
+    b) You must cause any work that you distribute or publish, that in\r
+    whole or in part contains or is derived from the Program or any\r
+    part thereof, to be licensed as a whole at no charge to all third\r
+    parties under the terms of this License.\r
+\r
+    c) If the modified program normally reads commands interactively\r
+    when run, you must cause it, when started running for such\r
+    interactive use in the most ordinary way, to print or display an\r
+    announcement including an appropriate copyright notice and a\r
+    notice that there is no warranty (or else, saying that you provide\r
+    a warranty) and that users may redistribute the program under\r
+    these conditions, and telling the user how to view a copy of this\r
+    License.  (Exception: if the Program itself is interactive but\r
+    does not normally print such an announcement, your work based on\r
+    the Program is not required to print an announcement.)\r
+\f\r
+These requirements apply to the modified work as a whole.  If\r
+identifiable sections of that work are not derived from the Program,\r
+and can be reasonably considered independent and separate works in\r
+themselves, then this License, and its terms, do not apply to those\r
+sections when you distribute them as separate works.  But when you\r
+distribute the same sections as part of a whole which is a work based\r
+on the Program, the distribution of the whole must be on the terms of\r
+this License, whose permissions for other licensees extend to the\r
+entire whole, and thus to each and every part regardless of who wrote it.\r
+\r
+Thus, it is not the intent of this section to claim rights or contest\r
+your rights to work written entirely by you; rather, the intent is to\r
+exercise the right to control the distribution of derivative or\r
+collective works based on the Program.\r
+\r
+In addition, mere aggregation of another work not based on the Program\r
+with the Program (or with a work based on the Program) on a volume of\r
+a storage or distribution medium does not bring the other work under\r
+the scope of this License.\r
+\r
+  3. You may copy and distribute the Program (or a work based on it,\r
+under Section 2) in object code or executable form under the terms of\r
+Sections 1 and 2 above provided that you also do one of the following:\r
+\r
+    a) Accompany it with the complete corresponding machine-readable\r
+    source code, which must be distributed under the terms of Sections\r
+    1 and 2 above on a medium customarily used for software interchange; or,\r
+\r
+    b) Accompany it with a written offer, valid for at least three\r
+    years, to give any third party, for a charge no more than your\r
+    cost of physically performing source distribution, a complete\r
+    machine-readable copy of the corresponding source code, to be\r
+    distributed under the terms of Sections 1 and 2 above on a medium\r
+    customarily used for software interchange; or,\r
+\r
+    c) Accompany it with the information you received as to the offer\r
+    to distribute corresponding source code.  (This alternative is\r
+    allowed only for noncommercial distribution and only if you\r
+    received the program in object code or executable form with such\r
+    an offer, in accord with Subsection b above.)\r
+\r
+The source code for a work means the preferred form of the work for\r
+making modifications to it.  For an executable work, complete source\r
+code means all the source code for all modules it contains, plus any\r
+associated interface definition files, plus the scripts used to\r
+control compilation and installation of the executable.  However, as a\r
+special exception, the source code distributed need not include\r
+anything that is normally distributed (in either source or binary\r
+form) with the major components (compiler, kernel, and so on) of the\r
+operating system on which the executable runs, unless that component\r
+itself accompanies the executable.\r
+\r
+If distribution of executable or object code is made by offering\r
+access to copy from a designated place, then offering equivalent\r
+access to copy the source code from the same place counts as\r
+distribution of the source code, even though third parties are not\r
+compelled to copy the source along with the object code.\r
+\f\r
+  4. You may not copy, modify, sublicense, or distribute the Program\r
+except as expressly provided under this License.  Any attempt\r
+otherwise to copy, modify, sublicense or distribute the Program is\r
+void, and will automatically terminate your rights under this License.\r
+However, parties who have received copies, or rights, from you under\r
+this License will not have their licenses terminated so long as such\r
+parties remain in full compliance.\r
+\r
+  5. You are not required to accept this License, since you have not\r
+signed it.  However, nothing else grants you permission to modify or\r
+distribute the Program or its derivative works.  These actions are\r
+prohibited by law if you do not accept this License.  Therefore, by\r
+modifying or distributing the Program (or any work based on the\r
+Program), you indicate your acceptance of this License to do so, and\r
+all its terms and conditions for copying, distributing or modifying\r
+the Program or works based on it.\r
+\r
+  6. Each time you redistribute the Program (or any work based on the\r
+Program), the recipient automatically receives a license from the\r
+original licensor to copy, distribute or modify the Program subject to\r
+these terms and conditions.  You may not impose any further\r
+restrictions on the recipients' exercise of the rights granted herein.\r
+You are not responsible for enforcing compliance by third parties to\r
+this License.\r
+\r
+  7. If, as a consequence of a court judgment or allegation of patent\r
+infringement or for any other reason (not limited to patent issues),\r
+conditions are imposed on you (whether by court order, agreement or\r
+otherwise) that contradict the conditions of this License, they do not\r
+excuse you from the conditions of this License.  If you cannot\r
+distribute so as to satisfy simultaneously your obligations under this\r
+License and any other pertinent obligations, then as a consequence you\r
+may not distribute the Program at all.  For example, if a patent\r
+license would not permit royalty-free redistribution of the Program by\r
+all those who receive copies directly or indirectly through you, then\r
+the only way you could satisfy both it and this License would be to\r
+refrain entirely from distribution of the Program.\r
+\r
+If any portion of this section is held invalid or unenforceable under\r
+any particular circumstance, the balance of the section is intended to\r
+apply and the section as a whole is intended to apply in other\r
+circumstances.\r
+\r
+It is not the purpose of this section to induce you to infringe any\r
+patents or other property right claims or to contest validity of any\r
+such claims; this section has the sole purpose of protecting the\r
+integrity of the free software distribution system, which is\r
+implemented by public license practices.  Many people have made\r
+generous contributions to the wide range of software distributed\r
+through that system in reliance on consistent application of that\r
+system; it is up to the author/donor to decide if he or she is willing\r
+to distribute software through any other system and a licensee cannot\r
+impose that choice.\r
+\r
+This section is intended to make thoroughly clear what is believed to\r
+be a consequence of the rest of this License.\r
+\f\r
+  8. If the distribution and/or use of the Program is restricted in\r
+certain countries either by patents or by copyrighted interfaces, the\r
+original copyright holder who places the Program under this License\r
+may add an explicit geographical distribution limitation excluding\r
+those countries, so that distribution is permitted only in or among\r
+countries not thus excluded.  In such case, this License incorporates\r
+the limitation as if written in the body of this License.\r
+\r
+  9. The Free Software Foundation may publish revised and/or new versions\r
+of the General Public License from time to time.  Such new versions will\r
+be similar in spirit to the present version, but may differ in detail to\r
+address new problems or concerns.\r
+\r
+Each version is given a distinguishing version number.  If the Program\r
+specifies a version number of this License which applies to it and "any\r
+later version", you have the option of following the terms and conditions\r
+either of that version or of any later version published by the Free\r
+Software Foundation.  If the Program does not specify a version number of\r
+this License, you may choose any version ever published by the Free Software\r
+Foundation.\r
+\r
+  10. If you wish to incorporate parts of the Program into other free\r
+programs whose distribution conditions are different, write to the author\r
+to ask for permission.  For software which is copyrighted by the Free\r
+Software Foundation, write to the Free Software Foundation; we sometimes\r
+make exceptions for this.  Our decision will be guided by the two goals\r
+of preserving the free status of all derivatives of our free software and\r
+of promoting the sharing and reuse of software generally.\r
+\r
+                           NO WARRANTY\r
+\r
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\r
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\r
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\r
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\r
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\r
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\r
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\r
+REPAIR OR CORRECTION.\r
+\r
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\r
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\r
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\r
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\r
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\r
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\r
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGES.\r
+\r
+                    END OF TERMS AND CONDITIONS\r
+\f\r
+           How to Apply These Terms to Your New Programs\r
+\r
+  If you develop a new program, and you want it to be of the greatest\r
+possible use to the public, the best way to achieve this is to make it\r
+free software which everyone can redistribute and change under these terms.\r
+\r
+  To do so, attach the following notices to the program.  It is safest\r
+to attach them to the start of each source file to most effectively\r
+convey the exclusion of warranty; and each file should have at least\r
+the "copyright" line and a pointer to where the full notice is found.\r
+\r
+    <one line to give the program's name and a brief idea of what it does.>\r
+    Copyright (C) <year>  <name of author>\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+\r
+Also add information on how to contact you by electronic and paper mail.\r
+\r
+If the program is interactive, make it output a short notice like this\r
+when it starts in an interactive mode:\r
+\r
+    Gnomovision version 69, Copyright (C) year  name of author\r
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r
+    This is free software, and you are welcome to redistribute it\r
+    under certain conditions; type `show c' for details.\r
+\r
+The hypothetical commands `show w' and `show c' should show the appropriate\r
+parts of the General Public License.  Of course, the commands you use may\r
+be called something other than `show w' and `show c'; they could even be\r
+mouse-clicks or menu items--whatever suits your program.\r
+\r
+You should also get your employer (if you work as a programmer) or your\r
+school, if any, to sign a "copyright disclaimer" for the program, if\r
+necessary.  Here is a sample; alter the names:\r
+\r
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\r
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.\r
+\r
+  <signature of Ty Coon>, 1 April 1989\r
+  Ty Coon, President of Vice\r
+\r
+This General Public License does not permit incorporating your program into\r
+proprietary programs.  If your program is a subroutine library, you may\r
+consider it more useful to permit linking proprietary applications with the\r
+library.  If this is what you want to do, use the GNU Library General\r
+Public License instead of this License.\r
diff --git a/src/httpdisk_util/MAKEFILE b/src/httpdisk_util/MAKEFILE
new file mode 100644 (file)
index 0000000..9c985f5
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
diff --git a/src/httpdisk_util/httpdisk.c b/src/httpdisk_util/httpdisk.c
new file mode 100644 (file)
index 0000000..dd6b606
--- /dev/null
@@ -0,0 +1,385 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#include <windows.h>\r
+#include <winioctl.h>\r
+#include <winsock2.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "httpdisk.h"\r
+\r
+int HttpDiskSyntax(void)\r
+{\r
+    fprintf(stderr, "syntax:\n");\r
+    fprintf(stderr, "httpdisk /mount  <devicenumber> <url> [/cd] <drive:>\n");\r
+    fprintf(stderr, "httpdisk /umount <drive:>\n");\r
+    fprintf(stderr, "\n");\r
+    fprintf(stderr, "example:\n");\r
+    fprintf(stderr, "httpdisk /mount  0 http://server.domain.com/path/diskimage.img d:\n");\r
+    fprintf(stderr, "httpdisk /mount  1 http://server.domain.com/path/cdimage.iso /cd e:\n");\r
+    fprintf(stderr, "...\n");\r
+    fprintf(stderr, "httpdisk /umount d:\n");\r
+    fprintf(stderr, "httpdisk /umount e:\n");\r
+\r
+    return -1;\r
+}\r
+\r
+void PrintLastError(char* Prefix)\r
+{\r
+    LPVOID lpMsgBuf;\r
+\r
+    FormatMessage( \r
+        FORMAT_MESSAGE_ALLOCATE_BUFFER |\r
+        FORMAT_MESSAGE_FROM_SYSTEM |\r
+        FORMAT_MESSAGE_IGNORE_INSERTS,\r
+        NULL,\r
+        GetLastError(),\r
+        0,\r
+        (LPTSTR) &lpMsgBuf,\r
+        0,\r
+        NULL\r
+        );\r
+\r
+    fprintf(stderr, "%s: %s", Prefix, (LPTSTR) lpMsgBuf);\r
+\r
+    LocalFree(lpMsgBuf);\r
+}\r
+\r
+int\r
+HttpDiskMount(\r
+    int                     DeviceNumber,\r
+    PHTTP_DISK_INFORMATION  HttpDiskInformation,\r
+    char                    DriveLetter,\r
+    BOOLEAN                 CdImage\r
+)\r
+{\r
+    char    VolumeName[] = "\\\\.\\ :";\r
+    char    DeviceName[255];\r
+    HANDLE  Device;\r
+    DWORD   BytesReturned;\r
+\r
+    VolumeName[4] = DriveLetter;\r
+\r
+    Device = CreateFile(\r
+        VolumeName,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        OPEN_EXISTING,\r
+        FILE_FLAG_NO_BUFFERING,\r
+        NULL\r
+        );\r
+\r
+    if (Device != INVALID_HANDLE_VALUE)\r
+    {\r
+        SetLastError(ERROR_BUSY);\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    if (CdImage)\r
+    {\r
+        sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);\r
+    }\r
+    else\r
+    {\r
+        sprintf(DeviceName, DEVICE_NAME_PREFIX "Disk" "%u", DeviceNumber);\r
+    }\r
+\r
+    if (!DefineDosDevice(\r
+        DDD_RAW_TARGET_PATH,\r
+        &VolumeName[4],\r
+        DeviceName\r
+        ))\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    Device = CreateFile(\r
+        VolumeName,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        OPEN_EXISTING,\r
+        FILE_FLAG_NO_BUFFERING,\r
+        NULL\r
+        );\r
+\r
+    if (Device == INVALID_HANDLE_VALUE)\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);\r
+        return -1;\r
+    }\r
+\r
+    if (!DeviceIoControl(\r
+        Device,\r
+        IOCTL_HTTP_DISK_CONNECT,\r
+        HttpDiskInformation,\r
+        sizeof(HTTP_DISK_INFORMATION) + HttpDiskInformation->FileNameLength - 1,\r
+        NULL,\r
+        0,\r
+        &BytesReturned,\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError("HttpDisk");\r
+        DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);\r
+        return -1;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+int HttpDiskUmount(char DriveLetter)\r
+{\r
+    char    VolumeName[] = "\\\\.\\ :";\r
+    HANDLE  Device;\r
+    DWORD   BytesReturned;\r
+\r
+    VolumeName[4] = DriveLetter;\r
+\r
+    Device = CreateFile(\r
+        VolumeName,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        OPEN_EXISTING,\r
+        FILE_FLAG_NO_BUFFERING,\r
+        NULL\r
+        );\r
+\r
+    if (Device == INVALID_HANDLE_VALUE)\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    if (!DeviceIoControl(\r
+        Device,\r
+        FSCTL_LOCK_VOLUME,\r
+        NULL,\r
+        0,\r
+        NULL,\r
+        0,\r
+        &BytesReturned,\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    if (!DeviceIoControl(\r
+        Device,\r
+        IOCTL_HTTP_DISK_DISCONNECT,\r
+        NULL,\r
+        0,\r
+        NULL,\r
+        0,\r
+        &BytesReturned,\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError("HttpDisk");\r
+        return -1;\r
+    }\r
+\r
+    if (!DeviceIoControl(\r
+        Device,\r
+        FSCTL_DISMOUNT_VOLUME,\r
+        NULL,\r
+        0,\r
+        NULL,\r
+        0,\r
+        &BytesReturned,\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    if (!DeviceIoControl(\r
+        Device,\r
+        FSCTL_UNLOCK_VOLUME,\r
+        NULL,\r
+        0,\r
+        NULL,\r
+        0,\r
+        &BytesReturned,\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    CloseHandle(Device);\r
+\r
+    if (!DefineDosDevice(\r
+        DDD_REMOVE_DEFINITION,\r
+        &VolumeName[4],\r
+        NULL\r
+        ))\r
+    {\r
+        PrintLastError(&VolumeName[4]);\r
+        return -1;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+int __cdecl main(int argc, char* argv[])\r
+{\r
+    char*                   Command;\r
+    int                     DeviceNumber;\r
+    char*                   Url;\r
+    char*                   Option;\r
+    char                    DriveLetter;\r
+    BOOLEAN                 CdImage;\r
+    PHTTP_DISK_INFORMATION  HttpDiskInformation;\r
+    char*                   FileName;\r
+    char*                   PortStr;\r
+    struct hostent*         HostEnt;\r
+    WSADATA                 wsaData;\r
+\r
+    Command = argv[1];\r
+\r
+    if ((argc == 5 || argc == 6) && !strcmp(Command, "/mount"))\r
+    {\r
+        DeviceNumber = atoi(argv[2]);\r
+        Url = argv[3];\r
+\r
+        if (argc > 5)\r
+        {\r
+            Option = argv[4];\r
+            DriveLetter = argv[5][0];\r
+\r
+            if (!strcmp(Option, "/cd"))\r
+            {\r
+                CdImage = TRUE;\r
+            }\r
+            else\r
+            {\r
+                return HttpDiskSyntax();\r
+            }\r
+        }\r
+        else\r
+        {\r
+            Option = NULL;\r
+            DriveLetter = argv[4][0];\r
+            CdImage = FALSE;\r
+        }\r
+\r
+        HttpDiskInformation = malloc(sizeof(HTTP_DISK_INFORMATION) + strlen(Url));\r
+\r
+        memset(\r
+            HttpDiskInformation,\r
+            0,\r
+            sizeof(HTTP_DISK_INFORMATION) + strlen(Url)\r
+            );\r
+\r
+        if (strstr(Url, "//"))\r
+        {\r
+            if (strlen(Url) > 7 && !strncmp(Url, "http://", 7))\r
+            {\r
+                Url += 7;\r
+            }\r
+            else\r
+            {\r
+                fprintf(stderr, "Invalid protocol.\n");\r
+                return -1;\r
+            }\r
+        }\r
+\r
+        FileName = strstr(Url, "/");\r
+\r
+        if (!FileName)\r
+        {\r
+            fprintf(stderr, "%s: Invalid url.\n", Url);\r
+            return -1;\r
+        }\r
+\r
+        strcpy(HttpDiskInformation->FileName, FileName);\r
+\r
+        HttpDiskInformation->FileNameLength = (USHORT) strlen(HttpDiskInformation->FileName);\r
+\r
+        *FileName = '\0';\r
+\r
+        PortStr = strstr(Url, ":");\r
+\r
+        if (PortStr)\r
+        {\r
+            HttpDiskInformation->Port = htons((USHORT) atoi(PortStr + 1));\r
+\r
+            if (HttpDiskInformation->Port == 0)\r
+            {\r
+                fprintf(stderr, "%s: Invalid port.\n", PortStr + 1);\r
+                return -1;\r
+            }\r
+\r
+            *PortStr = '\0';\r
+        }\r
+        else\r
+        {\r
+            HttpDiskInformation->Port = htons(80);\r
+        }\r
+\r
+        HttpDiskInformation->HostNameLength = (USHORT) strlen(Url);\r
+\r
+        if (HttpDiskInformation->HostNameLength > 255)\r
+        {\r
+            fprintf(stderr, "%s: Host name to long.\n", Url);\r
+            return -1;\r
+        }\r
+\r
+        strcpy(HttpDiskInformation->HostName, Url);\r
+\r
+        HttpDiskInformation->Address = inet_addr(Url);\r
+\r
+        if (HttpDiskInformation->Address == INADDR_NONE)\r
+        {\r
+            if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)\r
+            {\r
+                PrintLastError("HttpDisk");\r
+                return -1;\r
+            }\r
+\r
+            HostEnt = gethostbyname(Url);\r
+\r
+            if (!HostEnt)\r
+            {\r
+                PrintLastError(Url);\r
+                return -1;\r
+            }\r
+\r
+            HttpDiskInformation->Address = ((struct in_addr*) HostEnt->h_addr)->s_addr;\r
+        }\r
+\r
+        return HttpDiskMount(DeviceNumber, HttpDiskInformation, DriveLetter, CdImage);\r
+    }\r
+    else if (argc == 3 && !strcmp(Command, "/umount"))\r
+    {\r
+        DriveLetter = argv[2][0];\r
+        return HttpDiskUmount(DriveLetter);\r
+    }\r
+    else\r
+    {\r
+        return HttpDiskSyntax();\r
+    }\r
+}\r
diff --git a/src/httpdisk_util/httpdisk.rc b/src/httpdisk_util/httpdisk.rc
new file mode 100644 (file)
index 0000000..ec74925
--- /dev/null
@@ -0,0 +1,104 @@
+//Microsoft Developer Studio generated resource script.\r
+//\r
+\r
+#define APSTUDIO_READONLY_SYMBOLS\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 2 resource.\r
+//\r
+#include "afxres.h"\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#undef APSTUDIO_READONLY_SYMBOLS\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+// English (U.S.) resources\r
+\r
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r
+#ifdef _WIN32\r
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\r
+#pragma code_page(1252)\r
+#endif //_WIN32\r
+\r
+#ifndef _MAC\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Version\r
+//\r
+\r
+VS_VERSION_INFO VERSIONINFO\r
+ FILEVERSION 1,0,0,0\r
+ PRODUCTVERSION 1,0,0,0\r
+ FILEFLAGSMASK 0x3fL\r
+#ifdef _DEBUG\r
+ FILEFLAGS 0x1L\r
+#else\r
+ FILEFLAGS 0x0L\r
+#endif\r
+ FILEOS 0x40004L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+    BLOCK "StringFileInfo"\r
+    BEGIN\r
+        BLOCK "040904b0"\r
+        BEGIN\r
+            VALUE "CompanyName", "Bo Brantén\0"\r
+            VALUE "FileDescription", "HTTP Virtual Disk\0"\r
+            VALUE "FileVersion", "1.0.0.0\0"\r
+            VALUE "InternalName", "httpdisk\0"\r
+            VALUE "LegalCopyright", "Copyright © 2006 Bo Brantén\0"\r
+            VALUE "OriginalFilename", "httpdisk.exe\0"\r
+            VALUE "ProductName", "httpdisk\0"\r
+            VALUE "ProductVersion", "1.0.0.0\0"\r
+        END\r
+    END\r
+    BLOCK "VarFileInfo"\r
+    BEGIN\r
+        VALUE "Translation", 0x409, 1200\r
+    END\r
+END\r
+\r
+#endif    // !_MAC\r
+\r
+\r
+#ifdef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// TEXTINCLUDE\r
+//\r
+\r
+1 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "resource.h\0"\r
+END\r
+\r
+2 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "#include ""afxres.h""\r\n"\r
+    "\0"\r
+END\r
+\r
+3 TEXTINCLUDE DISCARDABLE \r
+BEGIN\r
+    "\r\n"\r
+    "\0"\r
+END\r
+\r
+#endif    // APSTUDIO_INVOKED\r
+\r
+#endif    // English (U.S.) resources\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+\r
+\r
+#ifndef APSTUDIO_INVOKED\r
+/////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Generated from the TEXTINCLUDE 3 resource.\r
+//\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+#endif    // not APSTUDIO_INVOKED\r
+\r
diff --git a/src/httpdisk_util/readme.txt b/src/httpdisk_util/readme.txt
new file mode 100644 (file)
index 0000000..a76e1e8
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+\r
+    The GNU General Public License is also available from:\r
+    http://www.gnu.org/copyleft/gpl.html\r
+\r
+    Windows and Windows NT are either registered trademarks or trademarks of\r
+    Microsoft Corporation in the United States and/or other countries.\r
+\r
+    Please send comments, corrections and contributions to bosse@acc.umu.se\r
+\r
+    The most recent version of this program is available from:\r
+    http://www.acc.umu.se/~bosse/\r
+\r
+    Revision history:\r
+\r
+    3. 2006-03-08\r
+       Small bug fix in handling of receive data length.\r
+\r
+    2. 2006-03-05\r
+       Added support for persistent connections.\r
+\r
+    1. 2006-02-11\r
+       Initial release.\r
diff --git a/src/httpdisk_util/sources b/src/httpdisk_util/sources
new file mode 100644 (file)
index 0000000..97c09d9
--- /dev/null
@@ -0,0 +1,7 @@
+TARGETNAME=httpdisk\r
+TARGETPATH=obj\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+INCLUDES=..\sys\inc\r
+TARGETLIBS=$(SDK_LIB_PATH)\ws2_32.lib\r
+SOURCES=httpdisk.c httpdisk.rc\r
diff --git a/src/include/httpdisk.h b/src/include/httpdisk.h
new file mode 100644 (file)
index 0000000..2d2a5f6
--- /dev/null
@@ -0,0 +1,50 @@
+/*\r
+    HTTP Virtual Disk.\r
+    Copyright (C) 2006 Bo Brantén.\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+#ifndef _HTTP_DISK_\r
+#define _HTTP_DISK_\r
+\r
+#ifndef __T\r
+#ifdef _NTDDK_\r
+#define __T(x)  L ## x\r
+#else\r
+#define __T(x)  x\r
+#endif\r
+#endif\r
+\r
+#ifndef _T\r
+#define _T(x)   __T(x)\r
+#endif\r
+\r
+#define DEVICE_BASE_NAME    _T("\\HttpDisk")\r
+#define DEVICE_DIR_NAME     _T("\\Device")      DEVICE_BASE_NAME\r
+#define DEVICE_NAME_PREFIX  DEVICE_DIR_NAME     _T("\\Http")\r
+\r
+#define FILE_DEVICE_HTTP_DISK       0x8000\r
+\r
+#define IOCTL_HTTP_DISK_CONNECT     CTL_CODE(FILE_DEVICE_HTTP_DISK, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\r
+#define IOCTL_HTTP_DISK_DISCONNECT  CTL_CODE(FILE_DEVICE_HTTP_DISK, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\r
+\r
+typedef struct _HTTP_DISK_INFORMATION {\r
+    ULONG   Address;\r
+    USHORT  Port;\r
+    USHORT  HostNameLength;\r
+    UCHAR   HostName[256];\r
+    USHORT  FileNameLength;\r
+    UCHAR   FileName[1];\r
+} HTTP_DISK_INFORMATION, *PHTTP_DISK_INFORMATION;\r
+\r
+#endif\r