symbian-qemu-0.9.1-12/qemu-symbian-svp/tap-win32.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  *  TAP-Win32 -- A kernel driver to provide virtual tap device functionality
       
     3  *               on Windows.  Originally derived from the CIPE-Win32
       
     4  *               project by Damion K. Wilson, with extensive modifications by
       
     5  *               James Yonan.
       
     6  *
       
     7  *  All source code which derives from the CIPE-Win32 project is
       
     8  *  Copyright (C) Damion K. Wilson, 2003, and is released under the
       
     9  *  GPL version 2 (see below).
       
    10  *
       
    11  *  All other source code is Copyright (C) James Yonan, 2003-2004,
       
    12  *  and is released under the GPL version 2 (see below).
       
    13  *
       
    14  *  This program is free software; you can redistribute it and/or modify
       
    15  *  it under the terms of the GNU General Public License as published by
       
    16  *  the Free Software Foundation; either version 2 of the License, or
       
    17  *  (at your option) any later version.
       
    18  *
       
    19  *  This program is distributed in the hope that it will be useful,
       
    20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    22  *  GNU General Public License for more details.
       
    23  *
       
    24  *  You should have received a copy of the GNU General Public License
       
    25  *  along with this program (see the file COPYING included with this
       
    26  *  distribution); if not, write to the Free Software Foundation, Inc.,
       
    27  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    28  */
       
    29 #include "qemu-common.h"
       
    30 #include "net.h"
       
    31 #include "sysemu.h"
       
    32 #include <stdio.h>
       
    33 #define WIN32_LEAN_AND_MEAN
       
    34 #include <windows.h>
       
    35 
       
    36 /* NOTE: PCIBus is redefined in winddk.h */
       
    37 #define PCIBus _PCIBus
       
    38 #include <ddk/ntapi.h>
       
    39 #include <ddk/winddk.h>
       
    40 #include <ddk/ntddk.h>
       
    41 #undef PCIBus
       
    42 
       
    43 //=============
       
    44 // TAP IOCTLs
       
    45 //=============
       
    46 
       
    47 #define TAP_CONTROL_CODE(request,method) \
       
    48   CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
       
    49 
       
    50 #define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
       
    51 #define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
       
    52 #define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
       
    53 #define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
       
    54 #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
       
    55 #define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
       
    56 #define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
       
    57 #define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
       
    58 #define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
       
    59 
       
    60 //=================
       
    61 // Registry keys
       
    62 //=================
       
    63 
       
    64 #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
       
    65 
       
    66 #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
       
    67 
       
    68 //======================
       
    69 // Filesystem prefixes
       
    70 //======================
       
    71 
       
    72 #define USERMODEDEVICEDIR "\\\\.\\Global\\"
       
    73 #define TAPSUFFIX         ".tap"
       
    74 
       
    75 
       
    76 //======================
       
    77 // Compile time configuration
       
    78 //======================
       
    79 
       
    80 //#define DEBUG_TAP_WIN32
       
    81 
       
    82 #define TUN_ASYNCHRONOUS_WRITES 1
       
    83 
       
    84 #define TUN_BUFFER_SIZE 1560
       
    85 #define TUN_MAX_BUFFER_COUNT 32
       
    86 
       
    87 /*
       
    88  * The data member "buffer" must be the first element in the tun_buffer
       
    89  * structure. See the function, tap_win32_free_buffer.
       
    90  */
       
    91 typedef struct tun_buffer_s {
       
    92     unsigned char buffer [TUN_BUFFER_SIZE];
       
    93     unsigned long read_size;
       
    94     struct tun_buffer_s* next;
       
    95 } tun_buffer_t;
       
    96 
       
    97 typedef struct tap_win32_overlapped {
       
    98     HANDLE handle;
       
    99     HANDLE read_event;
       
   100     HANDLE write_event;
       
   101     HANDLE output_queue_semaphore;
       
   102     HANDLE free_list_semaphore;
       
   103     HANDLE tap_semaphore;
       
   104     CRITICAL_SECTION output_queue_cs;
       
   105     CRITICAL_SECTION free_list_cs;
       
   106     OVERLAPPED read_overlapped;
       
   107     OVERLAPPED write_overlapped;
       
   108     tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
       
   109     tun_buffer_t* free_list;
       
   110     tun_buffer_t* output_queue_front;
       
   111     tun_buffer_t* output_queue_back;
       
   112 } tap_win32_overlapped_t;
       
   113 
       
   114 static tap_win32_overlapped_t tap_overlapped;
       
   115 
       
   116 static tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
       
   117 {
       
   118     tun_buffer_t* buffer = NULL;
       
   119     WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
       
   120     EnterCriticalSection(&overlapped->free_list_cs);
       
   121     buffer = overlapped->free_list;
       
   122 //    assert(buffer != NULL);
       
   123     overlapped->free_list = buffer->next;
       
   124     LeaveCriticalSection(&overlapped->free_list_cs);
       
   125     buffer->next = NULL;
       
   126     return buffer;
       
   127 }
       
   128 
       
   129 static void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
       
   130 {
       
   131     EnterCriticalSection(&overlapped->free_list_cs);
       
   132     buffer->next = overlapped->free_list;
       
   133     overlapped->free_list = buffer;
       
   134     LeaveCriticalSection(&overlapped->free_list_cs);
       
   135     ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
       
   136 }
       
   137 
       
   138 static tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
       
   139 {
       
   140     tun_buffer_t* buffer = NULL;
       
   141     DWORD result, timeout = block ? INFINITE : 0L;
       
   142 
       
   143     // Non-blocking call
       
   144     result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
       
   145 
       
   146     switch (result)
       
   147     {
       
   148         // The semaphore object was signaled.
       
   149         case WAIT_OBJECT_0:
       
   150             EnterCriticalSection(&overlapped->output_queue_cs);
       
   151 
       
   152             buffer = overlapped->output_queue_front;
       
   153             overlapped->output_queue_front = buffer->next;
       
   154 
       
   155             if(overlapped->output_queue_front == NULL) {
       
   156                 overlapped->output_queue_back = NULL;
       
   157             }
       
   158 
       
   159             LeaveCriticalSection(&overlapped->output_queue_cs);
       
   160             break;
       
   161 
       
   162         // Semaphore was nonsignaled, so a time-out occurred.
       
   163         case WAIT_TIMEOUT:
       
   164             // Cannot open another window.
       
   165             break;
       
   166     }
       
   167 
       
   168     return buffer;
       
   169 }
       
   170 
       
   171 static tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
       
   172 {
       
   173     return get_buffer_from_output_queue(overlapped, 0);
       
   174 }
       
   175 
       
   176 static void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
       
   177 {
       
   178     EnterCriticalSection(&overlapped->output_queue_cs);
       
   179 
       
   180     if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
       
   181         overlapped->output_queue_front = overlapped->output_queue_back = buffer;
       
   182     } else {
       
   183         buffer->next = NULL;
       
   184         overlapped->output_queue_back->next = buffer;
       
   185         overlapped->output_queue_back = buffer;
       
   186     }
       
   187 
       
   188     LeaveCriticalSection(&overlapped->output_queue_cs);
       
   189 
       
   190     ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
       
   191 }
       
   192 
       
   193 
       
   194 static int is_tap_win32_dev(const char *guid)
       
   195 {
       
   196     HKEY netcard_key;
       
   197     LONG status;
       
   198     DWORD len;
       
   199     int i = 0;
       
   200 
       
   201     status = RegOpenKeyEx(
       
   202         HKEY_LOCAL_MACHINE,
       
   203         ADAPTER_KEY,
       
   204         0,
       
   205         KEY_READ,
       
   206         &netcard_key);
       
   207 
       
   208     if (status != ERROR_SUCCESS) {
       
   209         return FALSE;
       
   210     }
       
   211 
       
   212     for (;;) {
       
   213         char enum_name[256];
       
   214         char unit_string[256];
       
   215         HKEY unit_key;
       
   216         char component_id_string[] = "ComponentId";
       
   217         char component_id[256];
       
   218         char net_cfg_instance_id_string[] = "NetCfgInstanceId";
       
   219         char net_cfg_instance_id[256];
       
   220         DWORD data_type;
       
   221 
       
   222         len = sizeof (enum_name);
       
   223         status = RegEnumKeyEx(
       
   224             netcard_key,
       
   225             i,
       
   226             enum_name,
       
   227             &len,
       
   228             NULL,
       
   229             NULL,
       
   230             NULL,
       
   231             NULL);
       
   232 
       
   233         if (status == ERROR_NO_MORE_ITEMS)
       
   234             break;
       
   235         else if (status != ERROR_SUCCESS) {
       
   236             return FALSE;
       
   237         }
       
   238 
       
   239         snprintf (unit_string, sizeof(unit_string), "%s\\%s",
       
   240                   ADAPTER_KEY, enum_name);
       
   241 
       
   242         status = RegOpenKeyEx(
       
   243             HKEY_LOCAL_MACHINE,
       
   244             unit_string,
       
   245             0,
       
   246             KEY_READ,
       
   247             &unit_key);
       
   248 
       
   249         if (status != ERROR_SUCCESS) {
       
   250             return FALSE;
       
   251         } else {
       
   252             len = sizeof (component_id);
       
   253             status = RegQueryValueEx(
       
   254                 unit_key,
       
   255                 component_id_string,
       
   256                 NULL,
       
   257                 &data_type,
       
   258                 component_id,
       
   259                 &len);
       
   260 
       
   261             if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
       
   262                 len = sizeof (net_cfg_instance_id);
       
   263                 status = RegQueryValueEx(
       
   264                     unit_key,
       
   265                     net_cfg_instance_id_string,
       
   266                     NULL,
       
   267                     &data_type,
       
   268                     net_cfg_instance_id,
       
   269                     &len);
       
   270 
       
   271                 if (status == ERROR_SUCCESS && data_type == REG_SZ) {
       
   272                     if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
       
   273                         !strcmp (net_cfg_instance_id, guid)) {
       
   274                         RegCloseKey (unit_key);
       
   275                         RegCloseKey (netcard_key);
       
   276                         return TRUE;
       
   277                     }
       
   278                 }
       
   279             }
       
   280             RegCloseKey (unit_key);
       
   281         }
       
   282         ++i;
       
   283     }
       
   284 
       
   285     RegCloseKey (netcard_key);
       
   286     return FALSE;
       
   287 }
       
   288 
       
   289 static int get_device_guid(
       
   290     char *name,
       
   291     int name_size,
       
   292     char *actual_name,
       
   293     int actual_name_size)
       
   294 {
       
   295     LONG status;
       
   296     HKEY control_net_key;
       
   297     DWORD len;
       
   298     int i = 0;
       
   299     int stop = 0;
       
   300 
       
   301     status = RegOpenKeyEx(
       
   302         HKEY_LOCAL_MACHINE,
       
   303         NETWORK_CONNECTIONS_KEY,
       
   304         0,
       
   305         KEY_READ,
       
   306         &control_net_key);
       
   307 
       
   308     if (status != ERROR_SUCCESS) {
       
   309         return -1;
       
   310     }
       
   311 
       
   312     while (!stop)
       
   313     {
       
   314         char enum_name[256];
       
   315         char connection_string[256];
       
   316         HKEY connection_key;
       
   317         char name_data[256];
       
   318         DWORD name_type;
       
   319         const char name_string[] = "Name";
       
   320 
       
   321         len = sizeof (enum_name);
       
   322         status = RegEnumKeyEx(
       
   323             control_net_key,
       
   324             i,
       
   325             enum_name,
       
   326             &len,
       
   327             NULL,
       
   328             NULL,
       
   329             NULL,
       
   330             NULL);
       
   331 
       
   332         if (status == ERROR_NO_MORE_ITEMS)
       
   333             break;
       
   334         else if (status != ERROR_SUCCESS) {
       
   335             return -1;
       
   336         }
       
   337 
       
   338         snprintf(connection_string,
       
   339              sizeof(connection_string),
       
   340              "%s\\%s\\Connection",
       
   341              NETWORK_CONNECTIONS_KEY, enum_name);
       
   342 
       
   343         status = RegOpenKeyEx(
       
   344             HKEY_LOCAL_MACHINE,
       
   345             connection_string,
       
   346             0,
       
   347             KEY_READ,
       
   348             &connection_key);
       
   349 
       
   350         if (status == ERROR_SUCCESS) {
       
   351             len = sizeof (name_data);
       
   352             status = RegQueryValueEx(
       
   353                 connection_key,
       
   354                 name_string,
       
   355                 NULL,
       
   356                 &name_type,
       
   357                 name_data,
       
   358                 &len);
       
   359 
       
   360             if (status != ERROR_SUCCESS || name_type != REG_SZ) {
       
   361                     return -1;
       
   362             }
       
   363             else {
       
   364                 if (is_tap_win32_dev(enum_name)) {
       
   365                     snprintf(name, name_size, "%s", enum_name);
       
   366                     if (actual_name) {
       
   367                         if (strcmp(actual_name, "") != 0) {
       
   368                             if (strcmp(name_data, actual_name) != 0) {
       
   369                                 RegCloseKey (connection_key);
       
   370                                 ++i;
       
   371                                 continue;
       
   372                             }
       
   373                         }
       
   374                         else {
       
   375                             snprintf(actual_name, actual_name_size, "%s", name_data);
       
   376                         }
       
   377                     }
       
   378                     stop = 1;
       
   379                 }
       
   380             }
       
   381 
       
   382             RegCloseKey (connection_key);
       
   383         }
       
   384         ++i;
       
   385     }
       
   386 
       
   387     RegCloseKey (control_net_key);
       
   388 
       
   389     if (stop == 0)
       
   390         return -1;
       
   391 
       
   392     return 0;
       
   393 }
       
   394 
       
   395 static int tap_win32_set_status(HANDLE handle, int status)
       
   396 {
       
   397     unsigned long len = 0;
       
   398 
       
   399     return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
       
   400                 &status, sizeof (status),
       
   401                 &status, sizeof (status), &len, NULL);
       
   402 }
       
   403 
       
   404 static void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
       
   405 {
       
   406     overlapped->handle = handle;
       
   407 
       
   408     overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
       
   409     overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
       
   410 
       
   411     overlapped->read_overlapped.Offset = 0;
       
   412     overlapped->read_overlapped.OffsetHigh = 0;
       
   413     overlapped->read_overlapped.hEvent = overlapped->read_event;
       
   414 
       
   415     overlapped->write_overlapped.Offset = 0;
       
   416     overlapped->write_overlapped.OffsetHigh = 0;
       
   417     overlapped->write_overlapped.hEvent = overlapped->write_event;
       
   418 
       
   419     InitializeCriticalSection(&overlapped->output_queue_cs);
       
   420     InitializeCriticalSection(&overlapped->free_list_cs);
       
   421 
       
   422     overlapped->output_queue_semaphore = CreateSemaphore(
       
   423         NULL,   // default security attributes
       
   424         0,   // initial count
       
   425         TUN_MAX_BUFFER_COUNT,   // maximum count
       
   426         NULL);  // unnamed semaphore
       
   427 
       
   428     if(!overlapped->output_queue_semaphore)  {
       
   429         fprintf(stderr, "error creating output queue semaphore!\n");
       
   430     }
       
   431 
       
   432     overlapped->free_list_semaphore = CreateSemaphore(
       
   433         NULL,   // default security attributes
       
   434         TUN_MAX_BUFFER_COUNT,   // initial count
       
   435         TUN_MAX_BUFFER_COUNT,   // maximum count
       
   436         NULL);  // unnamed semaphore
       
   437 
       
   438     if(!overlapped->free_list_semaphore)  {
       
   439         fprintf(stderr, "error creating free list semaphore!\n");
       
   440     }
       
   441 
       
   442     overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
       
   443 
       
   444     {
       
   445         unsigned index;
       
   446         for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
       
   447             tun_buffer_t* element = &overlapped->buffers[index];
       
   448             element->next = overlapped->free_list;
       
   449             overlapped->free_list = element;
       
   450         }
       
   451     }
       
   452     /* To count buffers, initially no-signal. */
       
   453     overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
       
   454     if(!overlapped->tap_semaphore)
       
   455         fprintf(stderr, "error creating tap_semaphore.\n");
       
   456 }
       
   457 
       
   458 static int tap_win32_write(tap_win32_overlapped_t *overlapped,
       
   459                            const void *buffer, unsigned long size)
       
   460 {
       
   461     unsigned long write_size;
       
   462     BOOL result;
       
   463     DWORD error;
       
   464 
       
   465     result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
       
   466                                   &write_size, FALSE);
       
   467 
       
   468     if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
       
   469         WaitForSingleObject(overlapped->write_event, INFINITE);
       
   470 
       
   471     result = WriteFile(overlapped->handle, buffer, size,
       
   472                        &write_size, &overlapped->write_overlapped);
       
   473 
       
   474     if (!result) {
       
   475         switch (error = GetLastError())
       
   476         {
       
   477         case ERROR_IO_PENDING:
       
   478 #ifndef TUN_ASYNCHRONOUS_WRITES
       
   479             WaitForSingleObject(overlapped->write_event, INFINITE);
       
   480 #endif
       
   481             break;
       
   482         default:
       
   483             return -1;
       
   484         }
       
   485     }
       
   486 
       
   487     return 0;
       
   488 }
       
   489 
       
   490 static DWORD WINAPI tap_win32_thread_entry(LPVOID param)
       
   491 {
       
   492     tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
       
   493     unsigned long read_size;
       
   494     BOOL result;
       
   495     DWORD dwError;
       
   496     tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
       
   497 
       
   498 
       
   499     for (;;) {
       
   500         result = ReadFile(overlapped->handle,
       
   501                           buffer->buffer,
       
   502                           sizeof(buffer->buffer),
       
   503                           &read_size,
       
   504                           &overlapped->read_overlapped);
       
   505         if (!result) {
       
   506             dwError = GetLastError();
       
   507             if (dwError == ERROR_IO_PENDING) {
       
   508                 WaitForSingleObject(overlapped->read_event, INFINITE);
       
   509                 result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
       
   510                                               &read_size, FALSE);
       
   511                 if (!result) {
       
   512 #ifdef DEBUG_TAP_WIN32
       
   513                     LPVOID lpBuffer;
       
   514                     dwError = GetLastError();
       
   515                     FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       
   516                                    NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       
   517                                    (LPTSTR) & lpBuffer, 0, NULL );
       
   518                     fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
       
   519                     LocalFree( lpBuffer );
       
   520 #endif
       
   521                 }
       
   522             } else {
       
   523 #ifdef DEBUG_TAP_WIN32
       
   524                 LPVOID lpBuffer;
       
   525                 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       
   526                                NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       
   527                                (LPTSTR) & lpBuffer, 0, NULL );
       
   528                 fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
       
   529                 LocalFree( lpBuffer );
       
   530 #endif
       
   531             }
       
   532         }
       
   533 
       
   534         if(read_size > 0) {
       
   535             buffer->read_size = read_size;
       
   536             put_buffer_on_output_queue(overlapped, buffer);
       
   537             ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
       
   538             buffer = get_buffer_from_free_list(overlapped);
       
   539         }
       
   540     }
       
   541 
       
   542     return 0;
       
   543 }
       
   544 
       
   545 static int tap_win32_read(tap_win32_overlapped_t *overlapped,
       
   546                           uint8_t **pbuf, int max_size)
       
   547 {
       
   548     int size = 0;
       
   549 
       
   550     tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
       
   551 
       
   552     if(buffer != NULL) {
       
   553         *pbuf = buffer->buffer;
       
   554         size = (int)buffer->read_size;
       
   555         if(size > max_size) {
       
   556             size = max_size;
       
   557         }
       
   558     }
       
   559 
       
   560     return size;
       
   561 }
       
   562 
       
   563 static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
       
   564                                   char* pbuf)
       
   565 {
       
   566     tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
       
   567     put_buffer_on_free_list(overlapped, buffer);
       
   568 }
       
   569 
       
   570 static int tap_win32_open(tap_win32_overlapped_t **phandle,
       
   571                           const char *prefered_name)
       
   572 {
       
   573     char device_path[256];
       
   574     char device_guid[0x100];
       
   575     int rc;
       
   576     HANDLE handle;
       
   577     BOOL bret;
       
   578     char name_buffer[0x100] = {0, };
       
   579     struct {
       
   580         unsigned long major;
       
   581         unsigned long minor;
       
   582         unsigned long debug;
       
   583     } version;
       
   584     LONG version_len;
       
   585     DWORD idThread;
       
   586     HANDLE hThread;
       
   587 
       
   588     if (prefered_name != NULL)
       
   589         snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);
       
   590 
       
   591     rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
       
   592     if (rc)
       
   593         return -1;
       
   594 
       
   595     snprintf (device_path, sizeof(device_path), "%s%s%s",
       
   596               USERMODEDEVICEDIR,
       
   597               device_guid,
       
   598               TAPSUFFIX);
       
   599 
       
   600     handle = CreateFile (
       
   601         device_path,
       
   602         GENERIC_READ | GENERIC_WRITE,
       
   603         0,
       
   604         0,
       
   605         OPEN_EXISTING,
       
   606         FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
       
   607         0 );
       
   608 
       
   609     if (handle == INVALID_HANDLE_VALUE) {
       
   610         return -1;
       
   611     }
       
   612 
       
   613     bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
       
   614                            &version, sizeof (version),
       
   615                            &version, sizeof (version), &version_len, NULL);
       
   616 
       
   617     if (bret == FALSE) {
       
   618         CloseHandle(handle);
       
   619         return -1;
       
   620     }
       
   621 
       
   622     if (!tap_win32_set_status(handle, TRUE)) {
       
   623         return -1;
       
   624     }
       
   625 
       
   626     tap_win32_overlapped_init(&tap_overlapped, handle);
       
   627 
       
   628     *phandle = &tap_overlapped;
       
   629 
       
   630     hThread = CreateThread(NULL, 0, tap_win32_thread_entry,
       
   631                            (LPVOID)&tap_overlapped, 0, &idThread);
       
   632     return 0;
       
   633 }
       
   634 
       
   635 /********************************************/
       
   636 
       
   637  typedef struct TAPState {
       
   638      VLANClientState *vc;
       
   639      tap_win32_overlapped_t *handle;
       
   640  } TAPState;
       
   641 
       
   642 static void tap_receive(void *opaque, const uint8_t *buf, int size)
       
   643 {
       
   644     TAPState *s = opaque;
       
   645 
       
   646     tap_win32_write(s->handle, buf, size);
       
   647 }
       
   648 
       
   649 static void tap_win32_send(void *opaque)
       
   650 {
       
   651     TAPState *s = opaque;
       
   652     uint8_t *buf;
       
   653     int max_size = 4096;
       
   654     int size;
       
   655 
       
   656     size = tap_win32_read(s->handle, &buf, max_size);
       
   657     if (size > 0) {
       
   658         qemu_send_packet(s->vc, buf, size);
       
   659         tap_win32_free_buffer(s->handle, buf);
       
   660     }
       
   661 }
       
   662 
       
   663 int tap_win32_init(VLANState *vlan, const char *ifname)
       
   664 {
       
   665     TAPState *s;
       
   666 
       
   667     s = qemu_mallocz(sizeof(TAPState));
       
   668     if (!s)
       
   669         return -1;
       
   670     if (tap_win32_open(&s->handle, ifname) < 0) {
       
   671         printf("tap: Could not open '%s'\n", ifname);
       
   672         return -1;
       
   673     }
       
   674 
       
   675     s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
       
   676 
       
   677     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
       
   678              "tap: ifname=%s", ifname);
       
   679 
       
   680     qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
       
   681     return 0;
       
   682 }