From: Itamar Tal <ita...@guardicore.com>

this patch add support for some more functionality in the qemu-guest-agent,
both for windows and linux. Main added features are:
- interface listing in Windows
- Process list in Windows
- network connections enumeration in Windows
- file delete for both Windows and Posix
- file stat() for both Windows and Posix
- system uptime for both Windows and Posix

Itamar,
Guardicore
ita...@guardicore.com

---
 qga/commands-posix.c    |  49 +++++
 qga/commands-win32.c    | 552 +++++++++++++++++++++++++++++++++++++++++++++++-
 qga/commands.c          |  25 +++
 qga/guest-agent-core.h  |   2 +
 qga/main.c              |   9 +
 qga/qapi-schema.json    | 172 +++++++++++++++
 qga/win32-definitions.h | 115 ++++++++++
 qga/win32-iptypes.h     | 411 +++++++++++++++++++++++++++++++++++
 8 files changed, 1332 insertions(+), 3 deletions(-)
 create mode 100644 qga/win32-definitions.h
 create mode 100644 qga/win32-iptypes.h

diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index ba8de62..15e39fc 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <inttypes.h>
+#include <sys/sysinfo.h>
 #include "qga/guest-agent-core.h"
 #include "qga-qmp-commands.h"
 #include "qapi/qmp/qerror.h"
@@ -2456,3 +2457,51 @@ void ga_command_state_init(GAState *s, GACommandState 
*cs)
 #endif
     ga_command_state_add(cs, guest_file_init, NULL);
 }
+
+uint64_t qmp_guest_uptime(Error **errp)
+{
+       struct sysinfo sys_info;
+       if (sysinfo(&sys_info))
+       {
+               error_setg(errp, "Failed reading system info");
+       }
+
+       return sys_info.uptime;
+}
+
+GuestFileStat *qmp_guest_file_stat(const char *path, Error **errp)
+{
+       GuestFileStat * file_stat = g_malloc0(sizeof(GuestFileStat));
+       struct stat file_os_stat;
+
+       if (stat(path, &file_os_stat))
+       {
+               error_setg(errp, "Failed to get file stat() for file '%s'", 
path);
+               return NULL;
+       }
+
+       file_stat->mode = file_os_stat.st_mode;
+       file_stat->inode = file_os_stat.st_ino;
+       file_stat->dev = file_os_stat.st_dev;
+       file_stat->nlink = file_os_stat.st_nlink;
+       file_stat->uid = file_os_stat.st_uid;
+       file_stat->gid = file_os_stat.st_gid;
+       file_stat->size = file_os_stat.st_size;
+       file_stat->atime = file_os_stat.st_atime;
+       file_stat->mtime = file_os_stat.st_mtime;
+       file_stat->ctime = file_os_stat.st_ctime;
+
+       return file_stat;
+}
+
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+       error_set(errp, QERR_UNSUPPORTED);
+       return NULL;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+       error_set(errp, QERR_UNSUPPORTED);
+       return NULL;
+}
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 3ef0549..55d8f2e 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -19,6 +19,7 @@
 #include "qga/guest-agent-core.h"
 #include "qga/vss-win32.h"
 #include "qga-qmp-commands.h"
+#include "qga/win32-definitions.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/queue.h"
 
@@ -26,6 +27,41 @@
 #define SHTDN_REASON_FLAG_PLANNED 0x80000000
 #endif
 
+ULONG (__stdcall * GetAdaptersAddresses)(      uint32_t Family,
+                                                                               
        uint32_t Flags,
+                                                                               
        void * Reserved,
+                                                                               
        IP_ADAPTER_ADDRESSES * AdapterAddresses,
+                                                                               
        uint32_t * SizePointer) = NULL;
+
+DWORD (__stdcall * GetExtendedTcpTable)(void * pTcpTable,
+                                                                               
DWORD * pdwSize,
+                                                                               
BOOL bOrder,
+                                                                               
ULONG ulAf,
+                                                                               
TCP_TABLE_CLASS TableClass,
+                                                                               
ULONG Reserved) = NULL;
+
+DWORD (__stdcall * GetExtendedUdpTable)(       void * pUdpTable,
+                                                                               
DWORD * pdwSize,
+                                                                               
BOOL bOrder,
+                                                                               
ULONG ulAf,
+                                                                               
UDP_TABLE_CLASS TableClass,
+                                                                               
ULONG Reserved) = NULL;
+
+NTSTATUS (__stdcall * RtlUnicodeStringToAnsiString)(ANSI_STRING * 
DestinationString,
+                                                                               
                        UNICODE_STRING * SourceString,
+                                                                               
                        BOOLEAN AllocateDestinationString) = NULL;
+
+NTSTATUS (__stdcall * NtQueryInformationProcess)(      HANDLE ProcessHandle,
+                                                                               
                        PROCESSINFOCLASS ProcessInformationClass,
+                                                                               
                        void * ProcessInformation,
+                                                                               
                        uint32_t ProcessInformationLength,
+                                                                               
                        uint32_t * ReturnLength) = NULL;
+
+NTSTATUS (__stdcall * NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS 
SystemInformationClass,
+                                                                               
                void * SystemInformation,
+                                                                               
                uint32_t SystemInformationLength,
+                                                                               
                uint32_t * ReturnLength) = NULL;
+
 /* multiple of 100 nanoseconds elapsed between windows baseline
  *    (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */
 #define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \
@@ -591,8 +627,132 @@ void qmp_guest_suspend_hybrid(Error **errp)
 
 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
 {
-    error_set(errp, QERR_UNSUPPORTED);
-    return NULL;
+       GuestNetworkInterfaceList * iface_list = NULL;
+       IP_ADAPTER_ADDRESSES * ip_adapter_addresses = NULL;
+       IP_ADAPTER_ADDRESSES * current_adapter = NULL;
+       uint32_t adapter_buff_size = 15 * 1024;
+       ULONG ret = 0;
+
+       for (;;)
+       {
+               ip_adapter_addresses = g_malloc0(adapter_buff_size);
+               if (NULL == ip_adapter_addresses)
+               {
+                       error_setg(errp, "Failed allocating adapters info 
buffer");
+                       return NULL;
+               }
+
+               ret = GetAdaptersAddresses(     AF_UNSPEC,
+                                                                       
GAA_FLAG_SKIP_ANYCAST |
+                                                                       
GAA_FLAG_SKIP_MULTICAST |
+                                                                       
GAA_FLAG_SKIP_DNS_SERVER |
+                                                                       
GAA_FLAG_INCLUDE_PREFIX,
+                                                                       NULL,
+                                                                       
ip_adapter_addresses,
+                                                                       
&adapter_buff_size);
+               if (NO_ERROR != ret)
+               {
+                       (void)g_free(ip_adapter_addresses);
+                       ip_adapter_addresses = NULL;
+
+                       if (ERROR_BUFFER_OVERFLOW == ret)
+                       {
+                               adapter_buff_size <<= 1;
+                               continue;
+                       }
+
+                       error_setg(errp, "Error quering network adapters info");
+                       return NULL;
+               }
+
+               break;
+       }
+
+       /* add all adapters to the list */
+       for (   current_adapter = ip_adapter_addresses;
+                       NULL != current_adapter;
+                       current_adapter = current_adapter->Next)
+       {
+               IP_ADAPTER_UNICAST_ADDRESS * ip_address = NULL;
+               UNICODE_STRING adapter_name_us;
+               ANSI_STRING adapter_name;
+               GuestNetworkInterfaceList * new_item = 
g_malloc0(sizeof(GuestNetworkInterfaceList));
+               new_item->value = g_malloc0(sizeof(GuestNetworkInterface));
+               new_item->next = iface_list;
+               iface_list = new_item;
+
+               adapter_name_us.Buffer = current_adapter->FriendlyName;
+               adapter_name_us.Length = wcslen(current_adapter->FriendlyName) 
* sizeof(wchar_t);
+               adapter_name_us.MaximumLength = adapter_name_us.Length + 
sizeof(wchar_t);
+               adapter_name.MaximumLength = adapter_name_us.MaximumLength;
+               adapter_name.Length = 0;
+               adapter_name.Buffer = g_malloc0(adapter_name_us.MaximumLength);
+
+               /* convert the adapter name to ansi string */
+               (void)RtlUnicodeStringToAnsiString(     &adapter_name,
+                                                                               
        &adapter_name_us,
+                                                                               
        FALSE);
+               new_item->value->name = adapter_name.Buffer;
+
+               /* copy physical address */
+               if (current_adapter->PhysicalAddressLength != 0)
+               {
+                       int i = 0;
+
+                       new_item->value->hardware_address = 
g_malloc0(current_adapter->PhysicalAddressLength * 3 + 1);
+
+                       for (i = 0; i < current_adapter->PhysicalAddressLength; 
++i)
+                       {
+                               sprintf(&new_item->value->hardware_address[i * 
3],
+                                               "%02x:", 
current_adapter->PhysicalAddress[i]);
+                       }
+
+                       new_item->value->hardware_address[i * 3 - 1] = '\0';
+                       new_item->value->has_hardware_address = true;
+               }
+
+               /* build IP list */
+               for (   ip_address = current_adapter->FirstUnicastAddress;
+                               NULL != ip_address;
+                               ip_address = ip_address->Next)
+               {
+                       GuestIpAddressList * new_ip = NULL;
+
+                       /* skip unknown addresses */
+                       if ((AF_INET != 
ip_address->Address.lpSockaddr->sa_family) &&
+                               (AF_INET6 != 
ip_address->Address.lpSockaddr->sa_family))
+                       {
+                               continue;
+                       }
+
+                       /* allocate new item in the list */
+                       new_ip = g_malloc0(sizeof(GuestIpAddressList));
+                       new_ip->value = g_malloc0(sizeof(GuestIpAddress));
+                       new_item->value->has_ip_addresses = true;
+
+                       /* push the new IP at the head of the list */
+                       new_ip->next = new_item->value->ip_addresses;
+                       new_item->value->ip_addresses = new_ip;
+
+
+                       /* convert IP info by family */
+                       if (AF_INET == 
ip_address->Address.lpSockaddr->sa_family)
+                       {
+                               SOCKADDR_IN * in_addr = (SOCKADDR_IN 
*)ip_address->Address.lpSockaddr;
+                               new_ip->value->ip_address_type = 
GUEST_IP_ADDRESS_TYPE_IPV4;
+                               new_ip->value->ip_address = 
g_strdup(inet_ntoa(in_addr->sin_addr));
+                       }
+                       else if (AF_INET6 == 
ip_address->Address.lpSockaddr->sa_family)
+                       {
+                               new_ip->value->ip_address_type = 
GUEST_IP_ADDRESS_TYPE_IPV6;
+                               new_ip->value->ip_address = g_strdup("IPv6 not 
supported");
+                       }
+               }
+       }
+
+       (void)g_free(ip_adapter_addresses);
+
+    return iface_list;
 }
 
 int64_t qmp_guest_get_time(Error **errp)
@@ -703,11 +863,73 @@ GuestMemoryBlockInfo 
*qmp_guest_get_memory_block_info(Error **errp)
     return NULL;
 }
 
+int ga_win_commands_init(void)
+{
+       HMODULE ntdll_module = GetModuleHandle("ntdll.dll");
+       HMODULE iphlpapi_module = LoadLibrary("iphlpapi.dll");
+       WSADATA wsa_data = {0};
+
+       if (WSAStartup(MAKEWORD(2,2), &wsa_data))
+       {
+               g_critical("failed to initialize WSA engine");
+               goto error;
+       }
+
+       if ((NULL == ntdll_module) ||
+               (NULL == iphlpapi_module))
+       {
+               goto error;
+       }
+
+       NtQuerySystemInformation = (void *)GetProcAddress(ntdll_module, 
"NtQuerySystemInformation");
+       if (NULL == NtQuerySystemInformation)
+       {
+               goto error;
+       }
+
+       RtlUnicodeStringToAnsiString = (void *)GetProcAddress(ntdll_module, 
"RtlUnicodeStringToAnsiString");
+       if (NULL == RtlUnicodeStringToAnsiString)
+       {
+               goto error;
+       }
+
+       NtQueryInformationProcess = (void *)GetProcAddress(ntdll_module, 
"NtQueryInformationProcess");
+       if (NULL == NtQueryInformationProcess)
+       {
+               goto error;
+       }
+
+       GetAdaptersAddresses = (void *)GetProcAddress(iphlpapi_module, 
"GetAdaptersAddresses");
+       if (NULL == GetAdaptersAddresses)
+       {
+               goto error;
+       }
+
+       GetExtendedTcpTable = (void *)GetProcAddress(iphlpapi_module, 
"GetExtendedTcpTable");
+       if (NULL == GetExtendedTcpTable)
+       {
+               goto error;
+       }
+
+       GetExtendedUdpTable = (void *)GetProcAddress(iphlpapi_module, 
"GetExtendedUdpTable");
+       if (NULL == GetExtendedUdpTable)
+       {
+               goto error;
+       }
+
+       return 1;
+
+error:
+       (void)FreeLibrary(iphlpapi_module);
+
+       return 0;
+}
+
 /* add unsupported commands to the blacklist */
 GList *ga_command_blacklist_init(GList *blacklist)
 {
     const char *list_unsupported[] = {
-        "guest-suspend-hybrid", "guest-network-get-interfaces",
+        "guest-suspend-hybrid",
         "guest-get-vcpus", "guest-set-vcpus",
         "guest-set-user-password",
         "guest-get-memory-blocks", "guest-set-memory-blocks",
@@ -742,3 +964,327 @@ void ga_command_state_init(GAState *s, GACommandState *cs)
     }
     ga_command_state_add(cs, guest_file_init, NULL);
 }
+
+uint64_t qmp_guest_uptime(Error **errp)
+{
+       uint64_t uptime_milli = GetTickCount();
+       return uptime_milli / 1000;
+}
+
+GuestFileStat *qmp_guest_file_stat(const char *path, Error **errp)
+{
+       GuestFileStat * file_stat = g_malloc0(sizeof(GuestFileStat));
+       struct _stat file_os_stat = {0};
+
+       if (_stat(path, &file_os_stat))
+       {
+               error_setg(errp, "Failed to get file stat() for file '%s': %d", 
path, (int)GetLastError());
+               return NULL;
+       }
+
+       file_stat->mode = file_os_stat.st_mode;
+       file_stat->inode = file_os_stat.st_ino;
+       file_stat->dev = file_os_stat.st_dev;
+       file_stat->nlink = file_os_stat.st_nlink;
+       file_stat->uid = file_os_stat.st_uid;
+       file_stat->gid = file_os_stat.st_gid;
+       file_stat->size = file_os_stat.st_size;
+       file_stat->atime = file_os_stat.st_atime;
+       file_stat->mtime = file_os_stat.st_mtime;
+       file_stat->ctime = file_os_stat.st_ctime;
+
+       return file_stat;
+}
+
+GuestProcessInfoList *qmp_guest_get_process_list(Error **errp)
+{
+       uint32_t bytes_needed = sizeof(SYSTEM_PROCESS_INFORMATION) * 20;
+       SYSTEM_PROCESS_INFORMATION * process_list = NULL;
+       SYSTEM_PROCESS_INFORMATION * process_list_iter = NULL;
+       GuestProcessInfoList * process_list_head = NULL;
+       GuestProcessInfoList * process_list_last = NULL;
+       NTSTATUS status = STATUS_SUCCESS;
+
+       /* find the minimal buffer for the process list */
+       for (;;)
+       {
+               process_list = g_malloc0(bytes_needed);
+               if (NULL == process_list)
+               {
+                       error_setg(errp, "Failed allocating space for process 
list (%d bytes)", bytes_needed);
+                       return NULL;
+               }
+
+               /* query the process list (if enough bytes are given) */
+               status = NtQuerySystemInformation(      
SystemProcessInformation,
+                                                                               
        process_list,
+                                                                               
        bytes_needed,
+                                                                               
        &bytes_needed);
+               if (STATUS_SUCCESS != status)
+               {
+                       (void)g_free(process_list);
+
+                       if (STATUS_INFO_LENGTH_MISMATCH == status)
+                       {
+                               bytes_needed <<= 1;
+                               continue;
+                       }
+
+                       error_setg(errp, "Failed quering process list (status 
%08X)", (int)status);
+                       return NULL;
+               }
+
+               break;
+       }
+
+       /* iterate the process list and build the JSON reply */
+       for (process_list_iter = process_list;;)
+       {
+               GuestProcessInfoList * list_item = 
g_malloc0(sizeof(GuestProcessInfoList));
+               ANSI_STRING process_name;
+               HANDLE process_handle = NULL;
+               UNICODE_STRING * process_image_path = NULL;
+               PROCESS_BASIC_INFORMATION process_basic_info = {0};
+
+               if (NULL == process_list_head)
+               {
+                       process_list_head = list_item;
+               }
+               if (NULL != process_list_last)
+               {
+                       process_list_last->next = list_item;
+               }
+               process_list_last = list_item;
+
+               list_item->next = NULL;
+               list_item->value = g_malloc0(sizeof(GuestProcessInfo));
+               list_item->value->process_id = 
(int)process_list_iter->UniqueProcessId;
+               list_item->value->session_id = 
(int)process_list_iter->SessionId;
+
+               process_name.MaximumLength = 
process_list_iter->ImageName.MaximumLength;
+               process_name.Length = 0;
+               process_name.Buffer = g_malloc0(process_name.MaximumLength);
+
+               /* convert the image name to ansi string */
+               (void)RtlUnicodeStringToAnsiString(     &process_name,
+                                                                               
        &process_list_iter->ImageName,
+                                                                               
        FALSE);
+               list_item->value->process_name = process_name.Buffer;
+
+               if (!process_list_iter->NextEntryOffset)
+               {
+                       break;
+               }
+
+               process_handle = OpenProcess(   PROCESS_QUERY_INFORMATION,
+                                                                               
FALSE,
+                                                                               
list_item->value->process_id);
+               if (NULL != process_handle)
+               {
+                       status = NtQueryInformationProcess(     process_handle,
+                                                                               
                ProcessBasicInformation,
+                                                                               
                &process_basic_info,
+                                                                               
                sizeof(PROCESS_BASIC_INFORMATION),
+                                                                               
                NULL);
+                       if (STATUS_SUCCESS == status)
+                       {
+                               list_item->value->parent_id = 
(int)process_basic_info.InheritedFromUniqueProcessId;
+                       }
+
+                       process_image_path = g_malloc0(sizeof(UNICODE_STRING) + 
256 * sizeof(wchar_t));
+
+                       status = NtQueryInformationProcess(     process_handle,
+                                                                               
                ProcessImageFileName,
+                                                                               
                process_image_path,
+                                                                               
                sizeof(UNICODE_STRING) + 256 * sizeof(wchar_t),
+                                                                               
                NULL);
+                       if (STATUS_SUCCESS == status)
+                       {
+                               process_name.MaximumLength = 
process_image_path->MaximumLength;
+                               process_name.Length = 0;
+                               process_name.Buffer = 
g_malloc0(process_name.MaximumLength);
+
+                               /* convert the image name to ansi string */
+                               (void)RtlUnicodeStringToAnsiString(     
&process_name,
+                                                                               
                        process_image_path,
+                                                                               
                        FALSE);
+                               list_item->value->image_path = 
process_name.Buffer;
+                       }
+
+                       (void)g_free(process_image_path);
+
+                       (void)CloseHandle(process_handle);
+               }
+
+               process_list_iter = (void *)((uint32_t)process_list_iter + 
process_list_iter->NextEntryOffset);
+       }
+
+       (void)g_free(process_list);
+
+       return process_list_head;
+}
+
+GuestActiveConnectionList *qmp_guest_get_active_connections(Error **errp)
+{
+       MIB_UDPTABLE_OWNER_MODULE * udp_table = NULL;
+       MIB_TCPTABLE_OWNER_MODULE * tcp_table = NULL;
+       DWORD bytes_needed = sizeof(MIB_UDPTABLE_OWNER_MODULE) * 30;
+       GuestActiveConnectionList * connections = NULL;
+       int entry_index = 0;
+       DWORD ret;
+
+       /* get the UDP table */
+       for (;;)
+       {
+               udp_table = g_malloc0(bytes_needed);
+               if (NULL == udp_table)
+               {
+                       error_setg(errp, "Failed allocating active UDP 
connections table");
+                       return NULL;
+               }
+
+               ret = GetExtendedUdpTable(      udp_table,
+                                                                       
&bytes_needed,
+                                                                       TRUE,
+                                                                       AF_INET,
+                                                                       
UDP_TABLE_OWNER_MODULE,
+                                                                       0);
+               if (NO_ERROR != ret)
+               {
+                       (void)g_free(tcp_table);
+                       udp_table = NULL;
+
+                       if (ERROR_INSUFFICIENT_BUFFER == ret)
+                       {
+                               bytes_needed <<= 1;
+                               continue;
+                       }
+               }
+
+               break;
+       }
+
+       /* add the UDP connections to the list backward */
+       for (   entry_index = udp_table->dwNumEntries - 1;
+                       entry_index >= 0;
+                       --entry_index)
+       {
+               /* allocate new active connection item */
+               GuestActiveConnectionList * new_item = 
g_malloc0(sizeof(GuestActiveConnectionList));
+               new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+               /* push the connection to the head of the list */
+               new_item->next = connections;
+               connections = new_item;
+
+               new_item->value->source_addr = g_strdup(inet_ntoa(*(struct 
in_addr *)&udp_table->table[entry_index].dwLocalAddr));
+               new_item->value->source_port = 
htons(udp_table->table[entry_index].dwLocalPort);
+               new_item->value->owner_process_id = 
udp_table->table[entry_index].dwOwningPid;
+               new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+               new_item->value->protocol = GUEST_IP_PROTOCOL_UDP;
+               new_item->value->start_time = 
udp_table->table[entry_index].liCreateTimestamp.QuadPart;
+       }
+
+       (void)g_free(udp_table);
+       udp_table = NULL;
+
+       bytes_needed = sizeof(MIB_TCPROW_OWNER_PID) * 30;
+
+       /* get the TCP table */
+       for (;;)
+       {
+               tcp_table = g_malloc0(bytes_needed);
+               if (NULL == tcp_table)
+               {
+                       error_setg(errp, "Failed allocating active connections 
table");
+                       return NULL;
+               }
+
+               ret = GetExtendedTcpTable(      tcp_table,
+                                                                       
&bytes_needed,
+                                                                       TRUE,
+                                                                       AF_INET,
+                                                                       
TCP_TABLE_OWNER_MODULE_ALL,
+                                                                       0);
+               if (NO_ERROR != ret)
+               {
+                       (void)g_free(tcp_table);
+                       tcp_table = NULL;
+
+                       if (ERROR_INSUFFICIENT_BUFFER == ret)
+                       {
+                               bytes_needed <<= 1;
+                               continue;
+                       }
+               }
+
+               break;
+       }
+
+       /* add the TCP connections to the list backward */
+       for (   entry_index = tcp_table->dwNumEntries - 1;
+                       entry_index >= 0;
+                       --entry_index)
+       {
+               /* allocate new active connection item */
+               GuestActiveConnectionList * new_item = 
g_malloc0(sizeof(GuestActiveConnectionList));
+               new_item->value = g_malloc0(sizeof(GuestActiveConnection));
+
+               /* push the connection to the head of the list */
+               new_item->next = connections;
+               connections = new_item;
+
+               new_item->value->source_addr = g_strdup(inet_ntoa(*(struct 
in_addr *)&tcp_table->table[entry_index].dwLocalAddr));
+               new_item->value->source_port = 
htons(tcp_table->table[entry_index].dwLocalPort);
+               new_item->value->dest_addr = g_strdup(inet_ntoa(*(struct 
in_addr *)&tcp_table->table[entry_index].dwRemoteAddr));
+               new_item->value->dest_port = 
htons(tcp_table->table[entry_index].dwRemotePort);
+               new_item->value->owner_process_id = 
tcp_table->table[entry_index].dwOwningPid;
+               new_item->value->if_family = GUEST_IP_ADDRESS_TYPE_IPV4;
+               new_item->value->protocol = GUEST_IP_PROTOCOL_TCP;
+               new_item->value->start_time = 
tcp_table->table[entry_index].liCreateTimestamp.QuadPart;
+
+               switch (tcp_table->table[entry_index].dwState)
+               {
+               case MIB_TCP_STATE_CLOSED:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_CLOSED;
+                       break;
+               case MIB_TCP_STATE_LISTEN:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_LISTEN;
+                       break;
+               case MIB_TCP_STATE_SYN_SENT:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_SYN_SENT;
+                       break;
+               case MIB_TCP_STATE_SYN_RCVD:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_SYN_RCVD;
+                       break;
+               case MIB_TCP_STATE_ESTAB:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_ESTABLISHED;
+                       break;
+               case MIB_TCP_STATE_FIN_WAIT1:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_FIN_WAIT1;
+                       break;
+               case MIB_TCP_STATE_FIN_WAIT2:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_FIN_WAIT2;
+                       break;
+               case MIB_TCP_STATE_CLOSE_WAIT:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_CLOSE_WAIT;
+                       break;
+               case MIB_TCP_STATE_CLOSING:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_CLOSING;
+                       break;
+               case MIB_TCP_STATE_LAST_ACK:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_LAST_ACK;
+                       break;
+               case MIB_TCP_STATE_TIME_WAIT:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_TIME_WAIT;
+                       break;
+               case MIB_TCP_STATE_DELETE_TCB:
+                       new_item->value->state = 
GUEST_TCP_PROTOCOL_STATE_DELETE_TCB;
+                       break;
+               }
+       }
+
+       (void)g_free(tcp_table);
+
+       return connections;
+}
diff --git a/qga/commands.c b/qga/commands.c
index 7834967..2fb364c 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -70,3 +70,28 @@ struct GuestAgentInfo *qmp_guest_info(Error **errp)
     qmp_for_each_command(qmp_command_info, info);
     return info;
 }
+
+void qmp_guest_file_delete(const char *path, Error **errp)
+{
+       if (unlink(path))
+       {
+               error_setg(errp, "Error deleting file '%s'", path);
+       }
+}
+
+char *qmp_guest_get_hostname(Error **errp)
+{
+       char hostname[64];
+
+       if (gethostname(hostname, 64))
+       {
+#ifdef _WIN32
+               error_setg(errp, "Error getting hostname (%d)", 
WSAGetLastError());
+#else
+               error_setg(errp, "Error getting hostname");
+#endif
+               return NULL;
+       }
+
+       return g_strdup(hostname);
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index e92c6ab..89d4165 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -40,4 +40,6 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp);
 
 #ifndef _WIN32
 void reopen_fd_to_null(int fd);
+#else
+int ga_win_commands_init(void);
 #endif
diff --git a/qga/main.c b/qga/main.c
index 9939a2b..3992aac 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -1163,6 +1163,15 @@ int main(int argc, char **argv)
         g_critical("failed to register signal handlers");
         goto out_bad;
     }
+#else
+    {
+
+       if (!ga_win_commands_init())
+       {
+               g_critical("failed initializing commands module");
+               goto out_bad;
+       }
+    }
 #endif
 
     s->main_loop = g_main_loop_new(NULL, false);
diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
index 95f49e3..1e38f98 100644
--- a/qga/qapi-schema.json
+++ b/qga/qapi-schema.json
@@ -891,3 +891,175 @@
 ##
 { 'command': 'guest-get-memory-block-info',
   'returns': 'GuestMemoryBlockInfo' }
+
+##
+# @GuestFileStat
+#
+# @st_mode: file access permissions mode
+# @st_ino: file inode id
+# @st_dev: file device node
+# @st_nlink: number of links pointing to the file
+# @st_uid: file user id
+# @st_gid: file group id
+# @st_atime: file access time
+# @st_mtime: file modification time
+# @st_ctime: file creation time
+# @st_size: file size in bytes
+#
+# Since: 2.3
+##
+{ 'type': 'GuestFileStat',
+  'data': {'mode': 'int', 'inode': 'int', 'dev': 'int',
+                       'nlink': 'int', 'uid': 'int', 'gid': 'int',
+                       'size': 'uint64', 'atime': 'int', 'mtime': 'int',
+                       'ctime': 'int'
+           }}
+
+##
+# @guest-file-stat:
+#
+# Get the stat() for a file in the guest's operating system
+#
+# Returns: hostname string.
+#
+# Since 2.3
+##
+{ 'command': 'guest-file-stat',
+  'data': { 'path': 'str' },
+  'returns': 'GuestFileStat' }
+  
+##
+# @guest-file-delete:
+#
+# Delete a file in the guest's operating system
+#
+# Returns: 
+#
+# Since 2.3
+##
+{ 'command': 'guest-file-delete',
+  'data': { 'path': 'str' }}
+
+##
+# @guest-get-hostname:
+#
+# Get the hostname of the guest's operating system
+#
+# Returns: hostname string.
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-hostname',
+  'returns': 'str' }
+ 
+##
+# @guest-uptime:
+#
+# Get the time in seconds since the guest machine operating system was started
+#
+# Returns: uptime in seconds
+#
+# Since 2.3
+##
+{ 'command': 'guest-uptime',
+  'returns': 'uint64' }
+
+##
+# @GuestProcessInfo
+#
+# @process-id: the process unique id
+# @parent-id: the process parent unique id
+# @process-name: the name of the process
+# @image-path: full path of the process image
+# @session-id: the session id of the process
+#
+# Since: 2.3
+##
+{ 'type': 'GuestProcessInfo',
+  'data': {'process-id': 'int', 'parent-id': 'int', 'process-name': 'str',
+                       'image-path': 'str', 'session-id': 'int'}}
+  
+##
+# @guest-get-process-list:
+#
+# Get the list of active processes on the guest operating system
+#
+# Returns: array of active processes
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-process-list',
+  'returns': ['GuestProcessInfo'] }
+
+##
+# @GuestIpProtocol:
+#
+# An enumeration of supported IP protocols
+#
+# @tcp: TCP
+#
+# @udp: UDP
+#
+# Since: 2.3
+##
+{ 'enum': 'GuestIpProtocol',
+  'data': [ 'tcp', 'udp' ] }
+  
+##
+# @GuestTcpProtocolState:
+#
+# An enumeration of TCP connection state
+#
+# @closed: CLOSED
+# @listen: LISTEN
+# @syn-sent: SYN_SENT
+# @syn-rcvd: SYN_RCVD
+# @established: ESTABLISHED
+# @fin-wait1: FIN_WAIT1
+# @fin-wait2: FIN_WAIT2
+# @close-wait: CLOSE_WAIT
+# @closing: CLOSING
+# @last-ack: LAST_ACK
+# @time-wait: TIME_WAIT
+# @delete-tcb: DELETE_TCB
+#
+# Since: 2.3
+##
+{ 'enum': 'GuestTcpProtocolState',
+  'data': [ 'closed', 'listen', 'syn-sent', 'syn-rcvd', 'established',
+                       'fin-wait1', 'fin-wait2', 'close-wait', 'closing',
+                       'last-ack', 'time-wait', 'delete-tcb' ] }
+
+##
+# @GuestActiveConnection
+#
+# @if-family: 4 / 6
+# @protocol: TCP / UDP
+# @source-addr: the source IP address of the connection
+# @source-port: the source port of the connection
+# @dest-addr: the destination IP address of the connection
+# @dest-port: the destination port of the connection
+# @owner-process_id: the process unique id for the connection owner
+# @state: connection protocol state
+# @start-time: time where bind() was called for the connection
+#
+# Since: 2.3
+##
+{ 'type': 'GuestActiveConnection',
+  'data': {    'source-addr': 'str', 'source-port': 'int', 'dest-addr': 'str',
+                       'dest-port': 'int', 'owner-process_id': 'int', 'state': 
'GuestTcpProtocolState',
+                       'if-family': 'GuestIpAddressType', 'protocol': 
'GuestIpProtocol',
+                       'start-time': 'uint64'}}
+ 
+ ##
+# @guest-get-active-connections:
+#
+# Get the list of active connections on the guest operating system
+#
+# Returns: array of active connections
+#
+# Since 2.3
+##
+{ 'command': 'guest-get-active-connections',
+  'returns': ['GuestActiveConnection'] }
+ 
diff --git a/qga/win32-definitions.h b/qga/win32-definitions.h
new file mode 100644
index 0000000..6bb610e
--- /dev/null
+++ b/qga/win32-definitions.h
@@ -0,0 +1,115 @@
+
+#ifndef WIN32_DEFINITIONS_H_
+#define WIN32_DEFINITIONS_H_   1
+
+#include "win32-iptypes.h"
+
+#define STATUS_INFO_LENGTH_MISMATCH            (0xC0000004)
+
+typedef
+enum _PROCESSINFOCLASS
+{
+       ProcessBasicInformation=0x0000,
+       ProcessDebugPort=0x0007,
+       ProcessWow64Information=0x001a,
+       ProcessImageFileName=0x001b,
+       ProcessBreakOnTermination=0x001d,
+} PROCESSINFOCLASS;
+
+typedef struct
+{
+    ULONG          AllocationSize;
+    ULONG          ActualSize;
+    ULONG          Flags;
+    ULONG          Unknown1;
+    UNICODE_STRING Unknown2;
+    HANDLE         InputHandle;
+    HANDLE         OutputHandle;
+    HANDLE         ErrorHandle;
+    UNICODE_STRING CurrentDirectory;
+    HANDLE         CurrentDirectoryHandle;
+    UNICODE_STRING SearchPaths;
+    UNICODE_STRING ApplicationName;
+    UNICODE_STRING CommandLine;
+    PVOID          EnvironmentBlock;
+    ULONG          Unknown[9];
+    UNICODE_STRING Unknown3;
+    UNICODE_STRING Unknown4;
+    UNICODE_STRING Unknown5;
+    UNICODE_STRING Unknown6;
+} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;
+
+typedef struct
+{
+    ULONG               AllocationSize;
+    ULONG               Unknown1;
+    HINSTANCE           ProcessHinstance;
+    PVOID               ListDlls;
+    PPROCESS_PARAMETERS ProcessParameters;
+    ULONG               Unknown2;
+    HANDLE              Heap;
+} PEB, *PPEB;
+
+typedef struct
+{
+    DWORD ExitStatus;
+    PPEB  PebBaseAddress;
+    DWORD AffinityMask;
+    DWORD BasePriority;
+    ULONG UniqueProcessId;
+    ULONG InheritedFromUniqueProcessId;
+}   PROCESS_BASIC_INFORMATION;
+
+typedef
+enum _SYSTEM_INFORMATION_CLASS
+{
+    SystemBasicInformation=0x0000,
+    SystemProcessorInformation=0x0001,
+    SystemPerformanceInformation=0x0002,
+    SystemTimeOfDayInformation=0x0003,
+    SystemPathInformation=0x0004,
+    SystemProcessInformation=0x0005,
+    SystemDeviceInformation=0x0007,
+    SystemModuleInformation=0x000B,
+} SYSTEM_INFORMATION_CLASS;
+
+typedef
+struct _SYSTEM_PROCESS_INFORMATION // Size=184
+{
+    ULONG NextEntryOffset; // Size=4 Offset=0
+    ULONG NumberOfThreads; // Size=4 Offset=4
+    LARGE_INTEGER WorkingSetPrivateSize; // Size=8 Offset=8
+    ULONG HardFaultCount; // Size=4 Offset=16
+    ULONG NumberOfThreadsHighWatermark; // Size=4 Offset=20
+    ULONGLONG CycleTime; // Size=8 Offset=24
+    LARGE_INTEGER CreateTime; // Size=8 Offset=32
+    LARGE_INTEGER UserTime; // Size=8 Offset=40
+    LARGE_INTEGER KernelTime; // Size=8 Offset=48
+    UNICODE_STRING ImageName; // Size=8 Offset=56
+    LONG BasePriority; // Size=4 Offset=64
+    PVOID UniqueProcessId; // Size=4 Offset=68
+    PVOID InheritedFromUniqueProcessId; // Size=4 Offset=72
+    ULONG HandleCount; // Size=4 Offset=76
+    ULONG SessionId; // Size=4 Offset=80
+    ULONG UniqueProcessKey; // Size=4 Offset=84
+    ULONG PeakVirtualSize; // Size=4 Offset=88
+    ULONG VirtualSize; // Size=4 Offset=92
+    ULONG PageFaultCount; // Size=4 Offset=96
+    ULONG PeakWorkingSetSize; // Size=4 Offset=100
+    ULONG WorkingSetSize; // Size=4 Offset=104
+    ULONG QuotaPeakPagedPoolUsage; // Size=4 Offset=108
+    ULONG QuotaPagedPoolUsage; // Size=4 Offset=112
+    ULONG QuotaPeakNonPagedPoolUsage; // Size=4 Offset=116
+    ULONG QuotaNonPagedPoolUsage; // Size=4 Offset=120
+    ULONG PagefileUsage; // Size=4 Offset=124
+    ULONG PeakPagefileUsage; // Size=4 Offset=128
+    ULONG PrivatePageCount; // Size=4 Offset=132
+    LARGE_INTEGER ReadOperationCount; // Size=8 Offset=136
+    LARGE_INTEGER WriteOperationCount; // Size=8 Offset=144
+    LARGE_INTEGER OtherOperationCount; // Size=8 Offset=152
+    LARGE_INTEGER ReadTransferCount; // Size=8 Offset=160
+    LARGE_INTEGER WriteTransferCount; // Size=8 Offset=168
+    LARGE_INTEGER OtherTransferCount; // Size=8 Offset=176
+} SYSTEM_PROCESS_INFORMATION;
+
+#endif /* WIN32_DEFINITIONS_H_ */
diff --git a/qga/win32-iptypes.h b/qga/win32-iptypes.h
new file mode 100644
index 0000000..baae4ea
--- /dev/null
+++ b/qga/win32-iptypes.h
@@ -0,0 +1,411 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+    iptypes.h
+
+--*/
+
+#ifndef IP_TYPES_INCLUDED
+#define IP_TYPES_INCLUDED
+
+#include <time.h>
+
+#define INET_ADDRSTRLEN         (16)
+#define INET6_ADDRSTRLEN        (48)
+
+// Definitions and structures used by getnetworkparams and getadaptersinfo apis
+
+#define MAX_ADAPTER_DESCRIPTION_LENGTH  128 // arb.
+#define MAX_ADAPTER_NAME_LENGTH         256 // arb.
+#define MAX_ADAPTER_ADDRESS_LENGTH      8   // arb.
+#define DEFAULT_MINIMUM_ENTITIES        32  // arb.
+#define MAX_HOSTNAME_LEN                128 // arb.
+#define MAX_DOMAIN_NAME_LEN             128 // arb.
+#define MAX_SCOPE_ID_LEN                256 // arb.
+
+//
+// types
+//
+
+// Node Type
+
+#define BROADCAST_NODETYPE              1
+#define PEER_TO_PEER_NODETYPE           2
+#define MIXED_NODETYPE                  4
+#define HYBRID_NODETYPE                 8
+
+//
+// IP_ADDRESS_STRING - store an IP address as a dotted decimal string
+//
+
+typedef struct {
+    char String[4 * 4];
+} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
+
+//
+// IP_ADDR_STRING - store an IP address with its corresponding subnet mask,
+// both as dotted decimal strings
+//
+
+typedef struct _IP_ADDR_STRING {
+    struct _IP_ADDR_STRING* Next;
+    IP_ADDRESS_STRING IpAddress;
+    IP_MASK_STRING IpMask;
+    DWORD Context;
+} IP_ADDR_STRING, *PIP_ADDR_STRING;
+
+//
+// ADAPTER_INFO - per-adapter information. All IP addresses are stored as
+// strings
+//
+
+typedef struct _IP_ADAPTER_INFO {
+    struct _IP_ADAPTER_INFO* Next;
+    DWORD ComboIndex;
+    char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
+    char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
+    UINT AddressLength;
+    BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
+    DWORD Index;
+    UINT Type;
+    UINT DhcpEnabled;
+    PIP_ADDR_STRING CurrentIpAddress;
+    IP_ADDR_STRING IpAddressList;
+    IP_ADDR_STRING GatewayList;
+    IP_ADDR_STRING DhcpServer;
+    BOOL HaveWins;
+    IP_ADDR_STRING PrimaryWinsServer;
+    IP_ADDR_STRING SecondaryWinsServer;
+    time_t LeaseObtained;
+    time_t LeaseExpires;
+} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
+
+//
+// The following types require Winsock2.
+//
+
+typedef enum {
+    IpPrefixOriginOther = 0,
+    IpPrefixOriginManual,
+    IpPrefixOriginWellKnown,
+    IpPrefixOriginDhcp,
+    IpPrefixOriginRouterAdvertisement,
+} IP_PREFIX_ORIGIN;
+
+typedef enum {
+    IpSuffixOriginOther = 0,
+    IpSuffixOriginManual,
+    IpSuffixOriginWellKnown,
+    IpSuffixOriginDhcp,
+    IpSuffixOriginLinkLayerAddress,
+    IpSuffixOriginRandom,
+} IP_SUFFIX_ORIGIN;
+
+typedef enum {
+    IpDadStateInvalid    = 0,
+    IpDadStateTentative,
+    IpDadStateDuplicate,
+    IpDadStateDeprecated,
+    IpDadStatePreferred,
+} IP_DAD_STATE;
+
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct { 
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_UNICAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+
+    IP_PREFIX_ORIGIN PrefixOrigin;
+    IP_SUFFIX_ORIGIN SuffixOrigin;
+    IP_DAD_STATE DadState;
+
+    ULONG ValidLifetime;
+    ULONG PreferredLifetime;
+    ULONG LeaseLifetime;
+} IP_ADAPTER_UNICAST_ADDRESS, *PIP_ADAPTER_UNICAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_ANYCAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct { 
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_ANYCAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_ANYCAST_ADDRESS, *PIP_ADAPTER_ANYCAST_ADDRESS;
+
+typedef struct _IP_ADAPTER_MULTICAST_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_MULTICAST_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_MULTICAST_ADDRESS, *PIP_ADAPTER_MULTICAST_ADDRESS;
+
+//
+// Per-address Flags
+//
+#define IP_ADAPTER_ADDRESS_DNS_ELIGIBLE 0x01
+#define IP_ADAPTER_ADDRESS_TRANSIENT    0x02
+
+typedef struct _IP_ADAPTER_DNS_SERVER_ADDRESS {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Reserved;
+        };
+    };
+    struct _IP_ADAPTER_DNS_SERVER_ADDRESS *Next;
+    SOCKET_ADDRESS Address;
+} IP_ADAPTER_DNS_SERVER_ADDRESS, *PIP_ADAPTER_DNS_SERVER_ADDRESS;
+
+typedef struct _IP_ADAPTER_PREFIX {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD Flags;
+        };
+    };
+    struct _IP_ADAPTER_PREFIX *Next;
+    SOCKET_ADDRESS Address;
+    ULONG PrefixLength;
+} IP_ADAPTER_PREFIX, *PIP_ADAPTER_PREFIX;
+
+//
+// Per-adapter Flags
+//
+#define IP_ADAPTER_DDNS_ENABLED               0x01
+#define IP_ADAPTER_REGISTER_ADAPTER_SUFFIX    0x02
+#define IP_ADAPTER_DHCP_ENABLED               0x04
+#define IP_ADAPTER_RECEIVE_ONLY               0x08
+#define IP_ADAPTER_NO_MULTICAST               0x10
+#define IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG 0x20
+
+//
+// OperStatus values from RFC 2863
+//
+typedef enum {
+    IfOperStatusUp = 1,
+    IfOperStatusDown,
+    IfOperStatusTesting,
+    IfOperStatusUnknown,
+    IfOperStatusDormant,
+    IfOperStatusNotPresent,
+    IfOperStatusLowerLayerDown
+} IF_OPER_STATUS;
+
+//
+// Scope levels from RFC 2373 used with ZoneIndices array.
+//
+typedef enum {
+    ScopeLevelInterface    = 1,
+    ScopeLevelLink         = 2,
+    ScopeLevelSubnet       = 3,
+    ScopeLevelAdmin        = 4,
+    ScopeLevelSite         = 5,
+    ScopeLevelOrganization = 8,
+    ScopeLevelGlobal       = 14
+} SCOPE_LEVEL;
+
+typedef struct _IP_ADAPTER_ADDRESSES {
+    union {
+        ULONGLONG Alignment;
+        struct {
+            ULONG Length;
+            DWORD IfIndex;
+        };
+    };
+    struct _IP_ADAPTER_ADDRESSES *Next;
+    PCHAR AdapterName;
+    PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
+    PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
+    PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
+    PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
+    PWCHAR DnsSuffix;
+    PWCHAR Description;
+    PWCHAR FriendlyName;
+    BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
+    DWORD PhysicalAddressLength;
+    DWORD Flags;
+    DWORD Mtu;
+    DWORD IfType;
+    IF_OPER_STATUS OperStatus;
+    DWORD Ipv6IfIndex;
+    DWORD ZoneIndices[16];
+    PIP_ADAPTER_PREFIX FirstPrefix;
+} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
+
+//
+// Flags used as argument to GetAdaptersAddresses().
+// "SKIP" flags are added when the default is to include the information.
+// "INCLUDE" flags are added when the default is to skip the information.
+//
+#define GAA_FLAG_SKIP_UNICAST       0x0001
+#define GAA_FLAG_SKIP_ANYCAST       0x0002
+#define GAA_FLAG_SKIP_MULTICAST     0x0004
+#define GAA_FLAG_SKIP_DNS_SERVER    0x0008
+#define GAA_FLAG_INCLUDE_PREFIX     0x0010
+#define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
+
+//
+// IP_PER_ADAPTER_INFO - per-adapter IP information such as DNS server list.
+//
+
+typedef struct _IP_PER_ADAPTER_INFO {
+    UINT AutoconfigEnabled;
+    UINT AutoconfigActive;
+    PIP_ADDR_STRING CurrentDnsServer;
+    IP_ADDR_STRING DnsServerList;
+} IP_PER_ADAPTER_INFO, *PIP_PER_ADAPTER_INFO;
+
+//
+// FIXED_INFO - the set of IP-related information which does not depend on DHCP
+//
+
+typedef struct {
+    char HostName[MAX_HOSTNAME_LEN + 4] ;
+    char DomainName[MAX_DOMAIN_NAME_LEN + 4];
+    PIP_ADDR_STRING CurrentDnsServer;
+    IP_ADDR_STRING DnsServerList;
+    UINT NodeType;
+    char ScopeId[MAX_SCOPE_ID_LEN + 4];
+    UINT EnableRouting;
+    UINT EnableProxy;
+    UINT EnableDns;
+} FIXED_INFO, *PFIXED_INFO;
+
+typedef struct ip_interface_name_info {
+    ULONG           Index;      // Interface Index
+    ULONG           MediaType;  // Interface Types - see ipifcons.h
+    UCHAR           ConnectionType;
+    UCHAR           AccessType;
+    GUID            DeviceGuid; // Device GUID is the guid of the device
+                                // that IP exposes
+    GUID            InterfaceGuid; // Interface GUID, if not GUID_NULL is the
+                                // GUID for the interface mapped to the device.
+} IP_INTERFACE_NAME_INFO, *PIP_INTERFACE_NAME_INFO;
+
+typedef enum  {
+  TCP_TABLE_BASIC_LISTENER,
+  TCP_TABLE_BASIC_CONNECTIONS,
+  TCP_TABLE_BASIC_ALL,
+  TCP_TABLE_OWNER_PID_LISTENER,
+  TCP_TABLE_OWNER_PID_CONNECTIONS,
+  TCP_TABLE_OWNER_PID_ALL,
+  TCP_TABLE_OWNER_MODULE_LISTENER,
+  TCP_TABLE_OWNER_MODULE_CONNECTIONS,
+  TCP_TABLE_OWNER_MODULE_ALL
+} TCP_TABLE_CLASS, *PTCP_TABLE_CLASS;
+
+typedef enum  {
+  UDP_TABLE_BASIC,
+  UDP_TABLE_OWNER_PID,
+  UDP_TABLE_OWNER_MODULE
+} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;
+
+#define TCPIP_OWNING_MODULE_SIZE       (16)
+#define ANY_SIZE                                       (1)
+
+typedef enum
+{
+  MIB_TCP_STATE_CLOSED = 1,
+  MIB_TCP_STATE_LISTEN = 2,
+  MIB_TCP_STATE_SYN_SENT = 3,
+  MIB_TCP_STATE_SYN_RCVD = 4,
+  MIB_TCP_STATE_ESTAB = 5,
+  MIB_TCP_STATE_FIN_WAIT1 = 6,
+  MIB_TCP_STATE_FIN_WAIT2 = 7,
+  MIB_TCP_STATE_CLOSE_WAIT = 8,
+  MIB_TCP_STATE_CLOSING = 9,
+  MIB_TCP_STATE_LAST_ACK = 10,
+  MIB_TCP_STATE_TIME_WAIT = 11,
+  MIB_TCP_STATE_DELETE_TCB = 12
+} MIB_TCP_STATE;
+
+typedef struct _MIB_UDPROW {
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+} MIB_UDPROW, *PMIB_UDPROW;
+
+typedef struct _MIB_UDPTABLE {
+  DWORD      dwNumEntries;
+  MIB_UDPROW table[ANY_SIZE];
+} MIB_UDPTABLE, *PMIB_UDPTABLE;
+
+typedef struct _MIB_UDPROW_OWNER_PID {
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+  DWORD dwOwningPid;
+} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
+
+typedef struct _MIB_UDPTABLE_OWNER_PID {
+  DWORD                dwNumEntries;
+  MIB_UDPROW_OWNER_PID table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
+
+typedef struct _MIB_UDPROW_OWNER_MODULE {
+  DWORD         dwLocalAddr;
+  DWORD         dwLocalPort;
+  DWORD         dwOwningPid;
+  LARGE_INTEGER liCreateTimestamp;
+  union {
+    struct {
+      int SpecificPortBind  :1;
+    };
+    int    dwFlags;
+  };
+  ULONGLONG     OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_UDPROW_OWNER_MODULE, *PMIB_UDPROW_OWNER_MODULE;
+
+typedef struct _MIB_UDPTABLE_OWNER_MODULE {
+  DWORD                   dwNumEntries;
+  MIB_UDPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_MODULE, *PMIB_UDPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_MODULE {
+  DWORD                dwState;
+  DWORD         dwLocalAddr;
+  DWORD         dwLocalPort;
+  DWORD         dwRemoteAddr;
+  DWORD         dwRemotePort;
+  DWORD         dwOwningPid;
+  LARGE_INTEGER liCreateTimestamp;
+  ULONGLONG     OwningModuleInfo[TCPIP_OWNING_MODULE_SIZE];
+} MIB_TCPROW_OWNER_MODULE, *PMIB_TCPROW_OWNER_MODULE;
+
+typedef struct {
+  DWORD                   dwNumEntries;
+  MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE;
+
+typedef struct _MIB_TCPROW_OWNER_PID {
+  DWORD dwState;
+  DWORD dwLocalAddr;
+  DWORD dwLocalPort;
+  DWORD dwRemoteAddr;
+  DWORD dwRemotePort;
+  DWORD dwOwningPid;
+} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;
+
+typedef struct {
+  DWORD                dwNumEntries;
+  MIB_TCPROW_OWNER_PID table[ANY_SIZE];
+} MIB_TCPTABLE_OWNER_PID, *PMIB_TCPTABLE_OWNER_PID;
+
+#endif /* IP_TYPES_INCLUDED */ 
-- 
2.3.4


Reply via email to