-/*\r
- This file is part of GNUnet.\r
- (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)\r
-\r
- GNUnet is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published\r
- by the Free Software Foundation; either version 2, or (at your\r
- option) any later version.\r
-\r
- GNUnet is distributed in the hope that it will be useful, but\r
- WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with GNUnet; see the file COPYING. If not, write to the\r
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
- Boston, MA 02111-1307, USA.\r
-*/\r
-\r
-/**\r
- * @file util/win.c\r
- * @brief Helper functions for MS Windows in C++\r
- * @author Nils Durner\r
- */\r
-\r
-#ifndef _WIN_C\r
-#define _WIN_C\r
-\r
-#include "winproc.h"\r
-#include "platform.h"\r
-#include "gnunet_common.h"\r
-#include "gnunet_connection_lib.h"\r
-\r
-#include <ntdef.h>\r
-\r
-#ifndef INHERITED_ACE\r
-#define INHERITED_ACE 0x10\r
-#endif\r
-\r
-int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);\r
-\r
-#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
- union { \\r
- struct { \\r
- ULONG Length; \\r
- DWORD Flags; \\r
- }; \\r
- }; \\r
-\r
-#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
- SOCKET_ADDRESS Address; \\r
- IP_PREFIX_ORIGIN PrefixOrigin; \\r
- IP_SUFFIX_ORIGIN SuffixOrigin; \\r
- IP_DAD_STATE DadState; \\r
- ULONG ValidLifetime; \\r
- ULONG PreferredLifetime; \\r
- ULONG LeaseLifetime;\r
-\r
-#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \\r
- UINT8 OnLinkPrefixLength;\r
-\r
-\r
-#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \\r
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \\r
- _IP_ADAPTER_UNICAST_ADDRESS_HEAD \\r
- struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \\r
- _IP_ADAPTER_UNICAST_ADDRESS_BASE \\r
- addition \\r
-} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;\r
-\r
-/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */\r
-_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)\r
-\r
-\r
-typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {\r
- union {\r
- ULONGLONG Alignment;\r
- struct {\r
- ULONG Length;\r
- DWORD Reserved;\r
- };\r
- };\r
- struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;\r
- SOCKET_ADDRESS Address;\r
-} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;\r
-\r
-typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {\r
- union {\r
- ULONGLONG Alignment;\r
- struct {\r
- ULONG Length;\r
- DWORD Reserved;\r
- };\r
- };\r
- struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;\r
- SOCKET_ADDRESS Address;\r
-} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;\r
-\r
-typedef UINT32 NET_IF_COMPARTMENT_ID;\r
-typedef GUID NET_IF_NETWORK_GUID;\r
-\r
-typedef enum _NET_IF_CONNECTION_TYPE {\r
- NET_IF_CONNECTION_DEDICATED = 1,\r
- NET_IF_CONNECTION_PASSIVE,\r
- NET_IF_CONNECTION_DEMAND,\r
- NET_IF_CONNECTION_MAXIMUM \r
-} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;\r
-\r
-typedef enum {\r
- TUNNEL_TYPE_NONE = 0,\r
- TUNNEL_TYPE_OTHER,\r
- TUNNEL_TYPE_DIRECT,\r
- TUNNEL_TYPE_6TO4,\r
- TUNNEL_TYPE_ISATAP,\r
- TUNNEL_TYPE_TEREDO,\r
- TUNNEL_TYPE_IPHTTPS \r
-} TUNNEL_TYPE, *PTUNNEL_TYPE;\r
-\r
-/*\r
-A DUID consists of a two-octet type code represented in network byte\r
- order, followed by a variable number of octets that make up the\r
- actual identifier. A DUID can be no more than 128 octets long (not\r
- including the type code).\r
-*/\r
-#define MAX_DHCPV6_DUID_LENGTH 130\r
-\r
-typedef union _NET_LUID {\r
- ULONG64 Value;\r
- struct {\r
- ULONG64 Reserved :24;\r
- ULONG64 NetLuidIndex :24;\r
- ULONG64 IfType :16;\r
- } Info;\r
-} NET_LUID, *PNET_LUID, IF_LUID;\r
-\r
-#define MAX_DNS_SUFFIX_STRING_LENGTH 246\r
-\r
-typedef struct _IP_ADAPTER_DNS_SUFFIX {\r
- struct _IP_ADAPTER_DNS_SUFFIX *Next;\r
- WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];\r
-} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;\r
-\r
-\r
-\r
-#define _IP_ADAPTER_ADDRESSES_HEAD \\r
- union { \\r
- ULONGLONG Alignment; \\r
- struct { \\r
- ULONG Length; \\r
- DWORD IfIndex; \\r
- }; \\r
- };\r
-\r
-#define _IP_ADAPTER_ADDRESSES_BASE \\r
- PCHAR AdapterName; \\r
- PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \\r
- PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \\r
- PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \\r
- PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \\r
- PWCHAR DnsSuffix; \\r
- PWCHAR Description; \\r
- PWCHAR FriendlyName; \\r
- BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \\r
- DWORD PhysicalAddressLength; \\r
- DWORD Flags; \\r
- DWORD Mtu; \\r
- DWORD IfType; \\r
- IF_OPER_STATUS OperStatus;\r
-\r
-#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
- DWORD Ipv6IfIndex; \\r
- DWORD ZoneIndices[16]; \\r
- PIP_ADAPTER_PREFIX FirstPrefix; \\r
-\r
-\r
-#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
- _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \\r
- ULONG64 TransmitLinkSpeed; \\r
- ULONG64 ReceiveLinkSpeed; \\r
- PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \\r
- PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \\r
- ULONG Ipv4Metric; \\r
- ULONG Ipv6Metric; \\r
- IF_LUID Luid; \\r
- SOCKET_ADDRESS Dhcpv4Server; \\r
- NET_IF_COMPARTMENT_ID CompartmentId; \\r
- NET_IF_NETWORK_GUID NetworkGuid; \\r
- NET_IF_CONNECTION_TYPE ConnectionType; \\r
- TUNNEL_TYPE TunnelType; \\r
- SOCKET_ADDRESS Dhcpv6Server; \\r
- BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \\r
- ULONG Dhcpv6ClientDuidLength; \\r
- ULONG Dhcpv6Iaid;\r
-\r
-#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \\r
- _IP_ADAPTER_ADDRESSES_ADD_VISTA \\r
- PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;\r
-\r
-#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \\r
-typedef struct _IP_ADAPTER_ADDRESSES##suffix { \\r
- _IP_ADAPTER_ADDRESSES_HEAD \\r
- struct _IP_ADAPTER_ADDRESSES##suffix *Next; \\r
- _IP_ADAPTER_ADDRESSES_BASE \\r
- addition \\r
-} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;\r
- \r
-\r
-/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */\r
-_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)\r
-_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)\r
-_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)\r
-\r
-static int\r
-EnumNICs_IPv6_get_ifs_count (SOCKET s)\r
-{\r
- DWORD dwret = 0, err;\r
- int iret;\r
- iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,\r
- &dwret, NULL, NULL);\r
- err = GetLastError ();\r
- if (iret == SOCKET_ERROR && err == WSAEFAULT)\r
- return dwret;\r
- else if (iret == 0)\r
- return 0;\r
- return GNUNET_SYSERR;\r
-}\r
-\r
-static int\r
-EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)\r
-{\r
- int iret;\r
- DWORD dwret = 0;\r
- iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,\r
- &dwret, NULL, NULL);\r
-\r
- if (iret != 0 || dwret != size)\r
- {\r
- /* It's supposed to succeed! And size should be the same */\r
- return GNUNET_SYSERR;\r
- }\r
- return GNUNET_OK;\r
-}\r
-\r
-#undef GNUNET_malloc\r
-#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \\r
- HEAP_GENERATE_EXCEPTIONS, a)\r
-\r
-#undef GNUNET_free\r
-#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)\r
-\r
-#undef GNUNET_free_non_null\r
-#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)\r
-\r
-static int\r
-EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)\r
-{\r
- int iret;\r
- DWORD dwret = 0;\r
- DWORD error;\r
- INTERFACE_INFO *ii = NULL;\r
- DWORD ii_size = sizeof (INTERFACE_INFO) * 15;\r
- while (TRUE)\r
- {\r
- if (ii_size >= sizeof (INTERFACE_INFO) * 1000)\r
- return GNUNET_SYSERR;\r
- ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);\r
- dwret = 0;\r
- iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,\r
- &dwret, NULL, NULL);\r
- error = GetLastError ();\r
- if (iret == SOCKET_ERROR)\r
- {\r
- if (error == WSAEFAULT)\r
- {\r
- GNUNET_free (ii);\r
- ii_size *= 2;\r
- continue;\r
- }\r
- GNUNET_free (ii);\r
- return GNUNET_SYSERR;\r
- }\r
- else\r
- {\r
- *inf = ii;\r
- *size = dwret;\r
- return GNUNET_OK;\r
- }\r
- }\r
- return GNUNET_SYSERR;\r
-}\r
-\r
-int\r
-EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)\r
-{\r
- int result = 0;\r
- SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;\r
- DWORD dwret1 = 0, dwret2;\r
- DWORD err1, err2;\r
- int ifs4len = 0, ifs6len = 0;\r
- INTERFACE_INFO *interfaces4 = NULL;\r
- SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
- SetLastError (0);\r
- s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
- err1 = GetLastError ();\r
- SetLastError (0);\r
- s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);\r
- err2 = GetLastError ();\r
- if (s6 != INVALID_SOCKET)\r
- {\r
- ifs6len = EnumNICs_IPv6_get_ifs_count (s6);\r
- if (ifs6len > 0)\r
- {\r
- interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);\r
- result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;\r
- }\r
- closesocket (s6);\r
- s6 = INVALID_SOCKET;\r
- }\r
-\r
- if (s4 != INVALID_SOCKET)\r
- {\r
- result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;\r
- closesocket (s4);\r
- s4 = INVALID_SOCKET;\r
- }\r
- if (ifs6len + ifs4len == 0)\r
- goto error;\r
-\r
- if (!result)\r
- {\r
- *ifs4 = interfaces4;\r
- *ifs4_len = ifs4len;\r
- *ifs6 = interfaces6;\r
- return GNUNET_OK;\r
- }\r
-error:\r
- if (interfaces4 != NULL)\r
- GNUNET_free (interfaces4);\r
- if (interfaces6 != NULL)\r
- GNUNET_free (interfaces6);\r
- if (s4 != INVALID_SOCKET)\r
- closesocket (s4);\r
- if (s6 != INVALID_SOCKET)\r
- closesocket (s6);\r
- return GNUNET_SYSERR;\r
-}\r
-\r
-/**\r
- * Returns GNUNET_OK on OK, GNUNET_SYSERR on error\r
- */\r
-int\r
-EnumNICs3 (struct EnumNICs3_results **results, int *results_count)\r
-{\r
- DWORD dwRetVal = 0;\r
- int count = 0;\r
- ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |\r
- GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;\r
- struct sockaddr_in6 examplecom6;\r
- IPAddr examplecom;\r
- DWORD best_interface = 0;\r
- DWORD best_interface6 = 0;\r
-\r
- int use_enum2 = 0;\r
- INTERFACE_INFO *interfaces4 = NULL;\r
- int interfaces4_len = 0;\r
- SOCKET_ADDRESS_LIST *interfaces6 = NULL;\r
-\r
- unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);\r
- IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;\r
- IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
-\r
- if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)\r
- == ERROR_BUFFER_OVERFLOW)\r
- {\r
- GNUNET_free (pAddresses);\r
- pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);\r
- }\r
-\r
- dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);\r
-\r
- if (dwRetVal != NO_ERROR)\r
- {\r
- GNUNET_free (pAddresses);\r
- return GNUNET_SYSERR;\r
- }\r
-\r
- if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))\r
- {\r
- use_enum2 = 1;\r
-\r
- /* Enumerate NICs using WSAIoctl() */\r
- if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))\r
- {\r
- GNUNET_free (pAddresses);\r
- return GNUNET_SYSERR;\r
- }\r
- }\r
-\r
- examplecom = inet_addr("192.0.34.166"); /* www.example.com */\r
- if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)\r
- best_interface = 0;\r
-\r
- if (GNGetBestInterfaceEx != NULL)\r
- {\r
- examplecom6.sin6_family = AF_INET6;\r
- examplecom6.sin6_port = 0;\r
- examplecom6.sin6_flowinfo = 0;\r
- examplecom6.sin6_scope_id = 0;\r
- inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",\r
- (struct sockaddr *) &examplecom6.sin6_addr);\r
- dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,\r
- &best_interface6);\r
- if (dwRetVal != NO_ERROR)\r
- best_interface6 = 0;\r
- }\r
-\r
- /* Give IPv6 a priority */\r
- if (best_interface6 != 0)\r
- best_interface = best_interface6;\r
-\r
- count = 0;\r
- for (pCurrentAddress = pAddresses;\r
- pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
- {\r
- if (pCurrentAddress->OperStatus == IfOperStatusUp)\r
- {\r
- IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
- for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
- unicast = unicast->Next)\r
- {\r
- if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||\r
- unicast->Address.lpSockaddr->sa_family == AF_INET6) &&\r
- (unicast->DadState == IpDadStateDeprecated ||\r
- unicast->DadState == IpDadStatePreferred))\r
- count += 1;\r
- }\r
- }\r
- }\r
-\r
- if (count == 0)\r
- {\r
- *results = NULL;\r
- *results_count = 0;\r
- GNUNET_free (pAddresses);\r
- GNUNET_free_non_null (interfaces4);\r
- GNUNET_free_non_null (interfaces6);\r
- return GNUNET_OK;\r
- }\r
-\r
- *results = (struct EnumNICs3_results *) GNUNET_malloc (\r
- sizeof (struct EnumNICs3_results) * count);\r
- *results_count = count;\r
-\r
- count = 0;\r
- for (pCurrentAddress = pAddresses;\r
- pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)\r
- {\r
- struct EnumNICs3_results *r;\r
- IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;\r
- if (pCurrentAddress->OperStatus != IfOperStatusUp)\r
- continue;\r
- for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;\r
- unicast = unicast->Next)\r
- {\r
- int i, j;\r
- int mask_length = -1;\r
- char dst[INET6_ADDRSTRLEN + 1];\r
-\r
- if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&\r
- unicast->Address.lpSockaddr->sa_family != AF_INET6) ||\r
- (unicast->DadState != IpDadStateDeprecated &&\r
- unicast->DadState != IpDadStatePreferred))\r
- continue;\r
-\r
- r = &(*results)[count];\r
- r->flags = 0;\r
- if (pCurrentAddress->IfIndex > 0 &&\r
- pCurrentAddress->IfIndex == best_interface &&\r
- unicast->Address.lpSockaddr->sa_family == AF_INET)\r
- r->is_default = 1;\r
- else if (pCurrentAddress->Ipv6IfIndex > 0 &&\r
- pCurrentAddress->Ipv6IfIndex == best_interface6 &&\r
- unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
- r->is_default = 1;\r
- else\r
- r->is_default = 0;\r
-\r
- /* Don't choose default interface twice */\r
- if (r->is_default)\r
- best_interface = best_interface6 = 0;\r
-\r
- if (!use_enum2)\r
- {\r
- memcpy (&r->address, unicast->Address.lpSockaddr,\r
- unicast->Address.iSockaddrLength);\r
- memset (&r->mask, 0, sizeof (struct sockaddr));\r
- mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->\r
- OnLinkPrefixLength;\r
- /* OnLinkPrefixLength is the number of leading 1s in the mask.\r
- * OnLinkPrefixLength is available on Vista and later (hence use_enum2).\r
- */\r
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
- {\r
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
- for (i = 0; i < mask_length; i++)\r
- ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
- }\r
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
- {\r
- struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;\r
- struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;\r
- for (i = 0; i < mask_length; i++)\r
- ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
- memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
- for (i = mask_length; i < 128; i++)\r
- ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);\r
- }\r
- r->flags |= ENUMNICS3_MASK_OK;\r
- }\r
- else\r
- {\r
- int found = 0;\r
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
- {\r
- for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)\r
- {\r
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
- if (memcpy (&interfaces4[i].iiAddress.Address,\r
- unicast->Address.lpSockaddr,\r
- unicast->Address.iSockaddrLength) != 0)\r
- continue;\r
- found = 1;\r
- memcpy (&r->address, &interfaces4[i].iiAddress.Address,\r
- sizeof (struct sockaddr_in));\r
- memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,\r
- sizeof (struct sockaddr_in));\r
- for (mask_length = 0;\r
- ((unsigned char *) &m->sin_addr)[mask_length / 8] &\r
- 0x80 >> (mask_length % 8); mask_length++)\r
- {\r
- }\r
- r->flags |= ENUMNICS3_MASK_OK;\r
- }\r
- }\r
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
- {\r
- for (i = 0;\r
- interfaces6 != NULL && !found && i < interfaces6->iAddressCount;\r
- i++)\r
- {\r
- if (memcpy (interfaces6->Address[i].lpSockaddr,\r
- unicast->Address.lpSockaddr,\r
- unicast->Address.iSockaddrLength) != 0)\r
- continue;\r
- found = 1;\r
- memcpy (&r->address, interfaces6->Address[i].lpSockaddr,\r
- sizeof (struct sockaddr_in6));\r
- /* TODO: Find a way to reliably get network mask for IPv6 on XP */\r
- memset (&r->mask, 0, sizeof (struct sockaddr));\r
- r->flags &= ~ENUMNICS3_MASK_OK;\r
- }\r
- }\r
- if (!found)\r
- {\r
- DebugBreak ();\r
- }\r
- }\r
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)\r
- {\r
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;\r
- struct sockaddr_in *a = (struct sockaddr_in *) &r->address;\r
- /* copy address to broadcast, then flip all the trailing bits not\r
- * falling under netmask to 1,\r
- * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.\r
- */\r
- memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);\r
- for (i = mask_length; i < 32; i++)\r
- ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);\r
- r->flags |= ENUMNICS3_BCAST_OK;\r
- r->addr_size = sizeof (struct sockaddr_in);\r
- inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);\r
- }\r
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)\r
- {\r
- struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;\r
- /* for IPv6 broadcast is not defined, zero it down */\r
- memset (&r->broadcast, 0, sizeof (struct sockaddr));\r
- r->flags &= ~ENUMNICS3_BCAST_OK;\r
- r->addr_size = sizeof (struct sockaddr_in6);\r
- inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);\r
- }\r
-\r
- i = 0;\r
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
- "%S (%s", pCurrentAddress->FriendlyName, dst);\r
- for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)\r
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,\r
- "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);\r
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");\r
- r->pretty_name[1000] = '\0';\r
- count += 1;\r
- }\r
- }\r
-\r
- if (use_enum2)\r
- {\r
- GNUNET_free_non_null (interfaces4);\r
- GNUNET_free_non_null (interfaces6);\r
- }\r
-\r
- GNUNET_free (pAddresses);\r
- return GNUNET_OK;\r
-}\r
-\r
-void\r
-EnumNICs3_free (struct EnumNICs3_results *r)\r
-{\r
- GNUNET_free_non_null (r);\r
-}\r
-\r
-\r
-/**\r
- * Lists all network interfaces in a combo box\r
- * Used by the basic GTK configurator\r
- *\r
- * @param callback function to call for each NIC\r
- * @param callback_cls closure for callback\r
- */\r
-int\r
-ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)\r
-{\r
- int r;\r
- int i;\r
- struct EnumNICs3_results *results = NULL;\r
- int results_count;\r
-\r
- r = EnumNICs3 (&results, &results_count);\r
- if (r != GNUNET_OK)\r
- return GNUNET_NO;\r
-\r
- for (i = 0; i < results_count; i++)\r
- callback (callback_cls, results[i].pretty_name, results[i].is_default);\r
- GNUNET_free_non_null (results);\r
- return GNUNET_YES;\r
-}\r
-\r
-/**\r
- * @brief Installs the Windows service\r
- * @param servicename name of the service as diplayed by the SCM\r
- * @param application path to the application binary\r
- * @param username the name of the service's user account\r
- * @returns 0 on success\r
- * 1 if the Windows version doesn't support services\r
- * 2 if the SCM could not be opened\r
- * 3 if the service could not be created\r
- */\r
-int InstallAsService(char *servicename, char *application, char *username)\r
-{\r
- SC_HANDLE hManager, hService;\r
- char szEXE[_MAX_PATH + 17] = "\"";\r
- char *user = NULL;\r
-\r
- if (! GNOpenSCManager)\r
- return 1;\r
-\r
- plibc_conv_to_win_path(application, szEXE + 1);\r
- strcat(szEXE, "\" --win-service");\r
- hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);\r
- if (! hManager)\r
- return 2;\r
-\r
- if (username)\r
- {\r
- user = (char *) malloc(strlen(username) + 3);\r
- sprintf(user, ".\\%s", username);\r
- }\r
-\r
- hService = GNCreateService(hManager, (LPCTSTR) servicename, (LPCTSTR) servicename, 0,\r
- SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR) szEXE,\r
- NULL, NULL, NULL, (LPCTSTR) user, (LPCTSTR) username);\r
-\r
- if (user)\r
- free(user);\r
-\r
- if (! hService)\r
- return 3;\r
-\r
- GNCloseServiceHandle(hService);\r
-\r
- return 0;\r
-}\r
-\r
-/**\r
- * @brief Uninstall Windows service\r
- * @param servicename name of the service to delete\r
- * @returns 0 on success\r
- * 1 if the Windows version doesn't support services\r
- * 2 if the SCM could not be openend\r
- * 3 if the service cannot be accessed\r
- * 4 if the service cannot be deleted\r
- */\r
-int UninstallService(char *servicename)\r
-{\r
- SC_HANDLE hManager, hService;\r
-\r
- if (! GNOpenSCManager)\r
- return 1;\r
-\r
- hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);\r
- if (! hManager)\r
- return 2;\r
-\r
- if (! (hService = GNOpenService(hManager, (LPCTSTR) servicename, DELETE)))\r
- if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)\r
- return 3;\r
- else\r
- goto closeSCM;\r
-\r
- if (! GNDeleteService(hService))\r
- if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)\r
- return 4;\r
-\r
-closeSCM:\r
- GNCloseServiceHandle(hService);\r
-\r
- return 0;\r
-}\r
-\r
-/**\r
- * @author Scott Field, Microsoft\r
- * @see http://support.microsoft.com/?scid=kb;en-us;132958\r
- * @date 12-Jul-95\r
- */\r
-void _InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)\r
-{\r
- DWORD StringLength;\r
-\r
- if(String == NULL)\r
- {\r
- LsaString->Buffer = NULL;\r
- LsaString->Length = 0;\r
- LsaString->MaximumLength = 0;\r
- return;\r
- }\r
-\r
- StringLength = wcslen(String);\r
- LsaString->Buffer = String;\r
- LsaString->Length = (USHORT) StringLength *sizeof(WCHAR);\r
- LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);\r
-}\r
-\r
-\r
-/**\r
- * @author Scott Field, Microsoft\r
- * @see http://support.microsoft.com/?scid=kb;en-us;132958\r
- * @date 12-Jul-95\r
- */\r
-NTSTATUS _OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)\r
-{\r
- LSA_OBJECT_ATTRIBUTES ObjectAttributes;\r
- LSA_UNICODE_STRING ServerString;\r
- PLSA_UNICODE_STRING Server = NULL;\r
-\r
- /* Always initialize the object attributes to all zeroes. */\r
- ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));\r
-\r
- if(ServerName != NULL)\r
- {\r
- /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */\r
- _InitLsaString(&ServerString, ServerName);\r
- Server = &ServerString;\r
- }\r
-\r
- /* Attempt to open the policy. */\r
- return GNLsaOpenPolicy(Server,\r
- &ObjectAttributes, DesiredAccess, PolicyHandle);\r
-}\r
-\r
-/**\r
- * @brief Obtain a SID representing the supplied account on the supplied system\r
- * @return TRUE on success, FALSE on failure\r
- * @author Scott Field, Microsoft\r
- * @date 12-Jul-95\r
- * @remarks A buffer is allocated which contains the SID representing the\r
- * supplied account. This buffer should be freed when it is no longer\r
- * needed by calling\n\r
- * HeapFree(GetProcessHeap(), 0, buffer)\r
- * @remarks Call GetLastError() to obtain extended error information.\r
- * @see http://support.microsoft.com/?scid=kb;en-us;132958\r
- */\r
-BOOL _GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)\r
-{\r
- LPTSTR ReferencedDomain = NULL;\r
- DWORD cbSid = 128; /* initial allocation attempt */\r
- DWORD cchReferencedDomain = 16; /* initial allocation size */\r
- SID_NAME_USE peUse;\r
- BOOL bSuccess = FALSE; /* assume this function will fail */\r
-\r
- /* initial memory allocations */\r
- if ((*Sid = HeapAlloc (GetProcessHeap (), 0, cbSid)) == NULL)\r
- return FALSE;\r
-\r
- if ((ReferencedDomain = (LPTSTR) HeapAlloc (GetProcessHeap (),\r
- 0,\r
- cchReferencedDomain *\r
- sizeof (TCHAR))) == NULL)\r
- return FALSE;\r
-\r
- /* Obtain the SID of the specified account on the specified system. */\r
- while (!GNLookupAccountName(SystemName, /* machine to lookup account on */\r
- AccountName, /* account to lookup */\r
- *Sid, /* SID of interest */\r
- &cbSid, /* size of SID */\r
- ReferencedDomain, /* domain account was found on */\r
- &cchReferencedDomain, &peUse))\r
- {\r
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)\r
- {\r
- /* reallocate memory */\r
- if ((*Sid = HeapReAlloc (GetProcessHeap (), 0, *Sid, cbSid)) == NULL)\r
- return FALSE;\r
-\r
- if ((ReferencedDomain = (LPTSTR) HeapReAlloc (GetProcessHeap (),\r
- 0,\r
- ReferencedDomain,\r
- cchReferencedDomain\r
- * sizeof (TCHAR))) == NULL)\r
- return FALSE;\r
- }\r
- else\r
- goto end;\r
- }\r
-\r
- /* Indicate success. */\r
- bSuccess = TRUE;\r
-\r
-end:\r
- /* Cleanup and indicate failure, if appropriate. */\r
- HeapFree (GetProcessHeap (), 0, ReferencedDomain);\r
-\r
- if (!bSuccess)\r
- {\r
- if (*Sid != NULL)\r
- {\r
- HeapFree (GetProcessHeap (), 0, *Sid);\r
- *Sid = NULL;\r
- }\r
- }\r
-\r
- return bSuccess;\r
-}\r
-\r
-/**\r
- * @author Scott Field, Microsoft\r
- * @see http://support.microsoft.com/?scid=kb;en-us;132958\r
- * @date 12-Jul-95\r
- */\r
-NTSTATUS _SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */\r
- PSID AccountSid, /* SID to grant privilege to */\r
- LPWSTR PrivilegeName, /* privilege to grant (Unicode) */\r
- BOOL bEnable /* enable or disable */\r
- )\r
-{\r
- LSA_UNICODE_STRING PrivilegeString;\r
-\r
- /* Create a LSA_UNICODE_STRING for the privilege name. */\r
- _InitLsaString(&PrivilegeString, PrivilegeName);\r
-\r
- /* grant or revoke the privilege, accordingly */\r
- if(bEnable)\r
- {\r
- NTSTATUS i;\r
-\r
- i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */\r
- AccountSid, /* target SID */\r
- &PrivilegeString, /* privileges */\r
- 1 /* privilege count */\r
- );\r
- }\r
- else\r
- {\r
- return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */\r
- AccountSid, /* target SID */\r
- FALSE, /* do not disable all rights */\r
- &PrivilegeString, /* privileges */\r
- 1 /* privilege count */\r
- );\r
- }\r
-}\r
-\r
-/**\r
- * @brief Create a Windows service account\r
- * @return 0 on success, > 0 otherwise\r
- * @param pszName the name of the account\r
- * @param pszDesc description of the account\r
- */\r
-int CreateServiceAccount(const char *pszName, const char *pszDesc)\r
-{\r
- USER_INFO_1 ui;\r
- USER_INFO_1008 ui2;\r
- NET_API_STATUS nStatus;\r
- wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH];\r
- DWORD dwErr;\r
- LSA_HANDLE hPolicy;\r
- PSID pSID;\r
-\r
- if (! GNNetUserAdd)\r
- return 1;\r
- mbstowcs(wszName, pszName, strlen(pszName) + 1);\r
- mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1);\r
-\r
- memset(&ui, 0, sizeof(ui));\r
- ui.usri1_name = wszName;\r
- ui.usri1_password = wszName; /* account is locked anyway */\r
- ui.usri1_priv = USER_PRIV_USER;\r
- ui.usri1_comment = wszDesc;\r
- ui.usri1_flags = UF_SCRIPT;\r
-\r
- nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);\r
-\r
- if (nStatus != NERR_Success && nStatus != NERR_UserExists)\r
- return 2;\r
-\r
- ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;\r
- GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL);\r
-\r
- if (_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy) !=\r
- STATUS_SUCCESS)\r
- return 3;\r
-\r
- _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID);\r
-\r
- if (_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE) != STATUS_SUCCESS)\r
- return 4;\r
-\r
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE);\r
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE);\r
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE);\r
-\r
- GNLsaClose(hPolicy);\r
-\r
- return 0;\r
-}\r
-\r
-/**\r
- * @brief Grant permission to a file\r
- * @param lpszFileName the name of the file or directory\r
- * @param lpszAccountName the user account\r
- * @param dwAccessMask the desired access (e.g. GENERIC_ALL)\r
- * @return TRUE on success\r
- * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&\r
- */\r
-BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,\r
- DWORD dwAccessMask)\r
-{\r
- /* SID variables. */\r
- SID_NAME_USE snuType;\r
- TCHAR * szDomain = NULL;\r
- DWORD cbDomain = 0;\r
- LPVOID pUserSID = NULL;\r
- DWORD cbUserSID = 0;\r
-\r
- /* File SD variables. */\r
- PSECURITY_DESCRIPTOR pFileSD = NULL;\r
- DWORD cbFileSD = 0;\r
-\r
- /* New SD variables. */\r
- SECURITY_DESCRIPTOR newSD;\r
-\r
- /* ACL variables. */\r
- PACL pACL = NULL;\r
- BOOL fDaclPresent;\r
- BOOL fDaclDefaulted;\r
- ACL_SIZE_INFORMATION AclInfo;\r
-\r
- /* New ACL variables. */\r
- PACL pNewACL = NULL;\r
- DWORD cbNewACL = 0;\r
-\r
- /* Temporary ACE. */\r
- LPVOID pTempAce = NULL;\r
- UINT CurrentAceIndex = 0;\r
-\r
- UINT newAceIndex = 0;\r
-\r
- /* Assume function will fail. */\r
- BOOL fResult = FALSE;\r
- BOOL fAPISuccess;\r
-\r
- SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;\r
-\r
- /**\r
- * STEP 1: Get SID of the account name specified.\r
- */\r
- fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,\r
- pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);\r
-\r
- /* API should have failed with insufficient buffer. */\r
- if (fAPISuccess)\r
- goto end;\r
- else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {\r
- goto end;\r
- }\r
-\r
- pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID);\r
- if (!pUserSID) {\r
- goto end;\r
- }\r
-\r
- szDomain = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR));\r
- if (!szDomain) {\r
- goto end;\r
- }\r
-\r
- fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,\r
- pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);\r
- if (!fAPISuccess) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 2: Get security descriptor (SD) of the file specified.\r
- */\r
- fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,\r
- secInfo, pFileSD, 0, &cbFileSD);\r
-\r
- /* API should have failed with insufficient buffer. */\r
- if (fAPISuccess)\r
- goto end;\r
- else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {\r
- goto end;\r
- }\r
-\r
- pFileSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- cbFileSD);\r
- if (!pFileSD) {\r
- goto end;\r
- }\r
-\r
- fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,\r
- secInfo, pFileSD, cbFileSD, &cbFileSD);\r
- if (!fAPISuccess) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 3: Initialize new SD.\r
- */\r
- if (!GNInitializeSecurityDescriptor(&newSD,\r
- SECURITY_DESCRIPTOR_REVISION)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 4: Get DACL from the old SD.\r
- */\r
- if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,\r
- &fDaclDefaulted)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 5: Get size information for DACL.\r
- */\r
- AclInfo.AceCount = 0; // Assume NULL DACL.\r
- AclInfo.AclBytesFree = 0;\r
- AclInfo.AclBytesInUse = sizeof(ACL);\r
-\r
- if (pACL == NULL)\r
- fDaclPresent = FALSE;\r
-\r
- /* If not NULL DACL, gather size information from DACL. */\r
- if (fDaclPresent) {\r
-\r
- if (!GNGetAclInformation(pACL, &AclInfo,\r
- sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {\r
- goto end;\r
- }\r
- }\r
-\r
- /**\r
- * STEP 6: Compute size needed for the new ACL.\r
- */\r
- cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)\r
- + GetLengthSid(pUserSID) - sizeof(DWORD);\r
-\r
- /**\r
- * STEP 7: Allocate memory for new ACL.\r
- */\r
- pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);\r
- if (!pNewACL) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 8: Initialize the new ACL.\r
- */\r
- if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 9 If DACL is present, copy all the ACEs from the old DACL\r
- * to the new DACL.\r
- *\r
- * The following code assumes that the old DACL is\r
- * already in Windows 2000 preferred order. To conform\r
- * to the new Windows 2000 preferred order, first we will\r
- * copy all non-inherited ACEs from the old DACL to the\r
- * new DACL, irrespective of the ACE type.\r
- */\r
-\r
- newAceIndex = 0;\r
-\r
- if (fDaclPresent && AclInfo.AceCount) {\r
-\r
- for (CurrentAceIndex = 0;\r
- CurrentAceIndex < AclInfo.AceCount;\r
- CurrentAceIndex++) {\r
-\r
- /**\r
- * TEP 10: Get an ACE.\r
- */\r
- if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 11: Check if it is a non-inherited ACE.\r
- * If it is an inherited ACE, break from the loop so\r
- * that the new access allowed non-inherited ACE can\r
- * be added in the correct position, immediately after\r
- * all non-inherited ACEs.\r
- */\r
- if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags\r
- & INHERITED_ACE)\r
- break;\r
-\r
- /**\r
- * STEP 12: Skip adding the ACE, if the SID matches\r
- * with the account specified, as we are going to\r
- * add an access allowed ACE with a different access\r
- * mask.\r
- */\r
- if (GNEqualSid(pUserSID,\r
- &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))\r
- continue;\r
-\r
- /**\r
- * STEP 13: Add the ACE to the new ACL.\r
- */\r
- if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,\r
- ((PACE_HEADER) pTempAce)->AceSize)) {\r
- goto end;\r
- }\r
-\r
- newAceIndex++;\r
- }\r
- }\r
-\r
- /**\r
- * STEP 14: Add the access-allowed ACE to the new DACL.\r
- * The new ACE added here will be in the correct position,\r
- * immediately after all existing non-inherited ACEs.\r
- */\r
- if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,\r
- pUserSID)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 14.5: Make new ACE inheritable\r
- */\r
- if (!GetAce(pNewACL, newAceIndex, &pTempAce))\r
- goto end;\r
- ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |=\r
- (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);\r
-\r
- /**\r
- * STEP 15: To conform to the new Windows 2000 preferred order,\r
- * we will now copy the rest of inherited ACEs from the\r
- * old DACL to the new DACL.\r
- */\r
- if (fDaclPresent && AclInfo.AceCount) {\r
-\r
- for (;\r
- CurrentAceIndex < AclInfo.AceCount;\r
- CurrentAceIndex++) {\r
-\r
- /**\r
- * STEP 16: Get an ACE.\r
- */\r
- if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {\r
- goto end;\r
- }\r
-\r
- /**\r
- * STEP 17: Add the ACE to the new ACL.\r
- */\r
- if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,\r
- ((PACE_HEADER) pTempAce)->AceSize)) {\r
- goto end;\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * STEP 18: Set permissions\r
- */\r
- if (GNSetNamedSecurityInfo((LPTSTR) lpszFileName, SE_FILE_OBJECT,\r
- DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) {\r
- goto end;\r
- }\r
-\r
- fResult = TRUE;\r
-\r
-end:\r
-\r
- /**\r
- * STEP 19: Free allocated memory\r
- */\r
- if (pUserSID)\r
- HeapFree(GetProcessHeap(), 0, pUserSID);\r
-\r
- if (szDomain)\r
- HeapFree(GetProcessHeap(), 0, szDomain);\r
-\r
- if (pFileSD)\r
- HeapFree(GetProcessHeap(), 0, pFileSD);\r
-\r
- if (pNewACL)\r
- HeapFree(GetProcessHeap(), 0, pNewACL);\r
-\r
- return fResult;\r
-}\r
-\r
-char *winErrorStr(const char *prefix, int dwErr)\r
-{\r
- char *err, *ret;\r
- int mem;\r
-\r
- if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err,\r
- 0, NULL ))\r
- {\r
- err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1);\r
- }\r
-\r
- mem = strlen(err) + strlen(prefix) + 20;\r
- ret = (char *) malloc(mem);\r
-\r
- snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);\r
-\r
- LocalFree(err);\r
-\r
- return ret;\r
-}\r
-\r
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * @file util/win.c
+ * @brief Helper functions for MS Windows in C++
+ * @author Nils Durner
+ */
+
+#ifndef _WIN_C
+#define _WIN_C
+
+#include "winproc.h"
+#include "platform.h"
+#include "gnunet_crypto_lib.h"
+#include "gnunet_common.h"
+#include "gnunet_connection_lib.h"
+
+#include <ntdef.h>
+#ifndef INHERITED_ACE
+#define INHERITED_ACE 0x10
+#endif
+
+int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
+ union { \
+ struct { \
+ ULONG Length; \
+ DWORD Flags; \
+ }; \
+ };
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
+ SOCKET_ADDRESS Address; \
+ IP_PREFIX_ORIGIN PrefixOrigin; \
+ IP_SUFFIX_ORIGIN SuffixOrigin; \
+ IP_DAD_STATE DadState; \
+ ULONG ValidLifetime; \
+ ULONG PreferredLifetime; \
+ ULONG LeaseLifetime;
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
+ UINT8 OnLinkPrefixLength;
+
+
+#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \
+ _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
+ struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \
+ _IP_ADAPTER_UNICAST_ADDRESS_BASE \
+ addition \
+} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;
+
+/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
+_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
+
+
+#ifndef __MINGW64_VERSION_MAJOR
+typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Reserved;
+ };
+ };
+ struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
+
+typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
+ union {
+ ULONGLONG Alignment;
+ struct {
+ ULONG Length;
+ DWORD Reserved;
+ };
+ };
+ struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;
+ SOCKET_ADDRESS Address;
+} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;
+#endif
+
+typedef UINT32 NET_IF_COMPARTMENT_ID;
+typedef GUID NET_IF_NETWORK_GUID;
+
+#ifndef __MINGW64_VERSION_MAJOR
+typedef enum _NET_IF_CONNECTION_TYPE {
+ NET_IF_CONNECTION_DEDICATED = 1,
+ NET_IF_CONNECTION_PASSIVE,
+ NET_IF_CONNECTION_DEMAND,
+ NET_IF_CONNECTION_MAXIMUM
+} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
+
+typedef enum {
+ TUNNEL_TYPE_NONE = 0,
+ TUNNEL_TYPE_OTHER,
+ TUNNEL_TYPE_DIRECT,
+ TUNNEL_TYPE_6TO4,
+ TUNNEL_TYPE_ISATAP,
+ TUNNEL_TYPE_TEREDO,
+ TUNNEL_TYPE_IPHTTPS
+} TUNNEL_TYPE, *PTUNNEL_TYPE;
+#endif
+
+/*
+A DUID consists of a two-octet type code represented in network byte
+ order, followed by a variable number of octets that make up the
+ actual identifier. A DUID can be no more than 128 octets long (not
+ including the type code).
+*/
+#define MAX_DHCPV6_DUID_LENGTH 130
+
+#ifndef __MINGW64_VERSION_MAJOR
+typedef union _NET_LUID {
+ ULONG64 Value;
+ struct {
+ ULONG64 Reserved :24;
+ ULONG64 NetLuidIndex :24;
+ ULONG64 IfType :16;
+ } Info;
+} NET_LUID, *PNET_LUID, IF_LUID;
+
+#define MAX_DNS_SUFFIX_STRING_LENGTH 246
+
+typedef struct _IP_ADAPTER_DNS_SUFFIX {
+ struct _IP_ADAPTER_DNS_SUFFIX *Next;
+ WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];
+} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
+#endif
+
+
+
+#define _IP_ADAPTER_ADDRESSES_HEAD \
+ union { \
+ ULONGLONG Alignment; \
+ struct { \
+ ULONG Length; \
+ DWORD IfIndex; \
+ }; \
+ };
+
+#define _IP_ADAPTER_ADDRESSES_BASE \
+ 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;
+
+#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
+ DWORD Ipv6IfIndex; \
+ DWORD ZoneIndices[16]; \
+ PIP_ADAPTER_PREFIX FirstPrefix; \
+
+
+#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
+ _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
+ ULONG64 TransmitLinkSpeed; \
+ ULONG64 ReceiveLinkSpeed; \
+ PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
+ PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \
+ ULONG Ipv4Metric; \
+ ULONG Ipv6Metric; \
+ IF_LUID Luid; \
+ SOCKET_ADDRESS Dhcpv4Server; \
+ NET_IF_COMPARTMENT_ID CompartmentId; \
+ NET_IF_NETWORK_GUID NetworkGuid; \
+ NET_IF_CONNECTION_TYPE ConnectionType; \
+ TUNNEL_TYPE TunnelType; \
+ SOCKET_ADDRESS Dhcpv6Server; \
+ BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \
+ ULONG Dhcpv6ClientDuidLength; \
+ ULONG Dhcpv6Iaid;
+
+#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
+ _IP_ADAPTER_ADDRESSES_ADD_VISTA \
+ PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
+
+#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \
+typedef struct _IP_ADAPTER_ADDRESSES##suffix { \
+ _IP_ADAPTER_ADDRESSES_HEAD \
+ struct _IP_ADAPTER_ADDRESSES##suffix *Next; \
+ _IP_ADAPTER_ADDRESSES_BASE \
+ addition \
+} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;
+
+
+/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
+_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)
+_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)
+_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
+
+static int
+EnumNICs_IPv6_get_ifs_count (SOCKET s)
+{
+ DWORD dwret = 0, err;
+ int iret;
+ iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
+ &dwret, NULL, NULL);
+ err = GetLastError ();
+ if (iret == SOCKET_ERROR && err == WSAEFAULT)
+ return dwret;
+ else if (iret == 0)
+ return 0;
+ return GNUNET_SYSERR;
+}
+
+static int
+EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)
+{
+ int iret;
+ DWORD dwret = 0;
+ iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
+ &dwret, NULL, NULL);
+
+ if (iret != 0 || dwret != size)
+ {
+ /* It's supposed to succeed! And size should be the same */
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+#undef GNUNET_malloc
+#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \
+ HEAP_GENERATE_EXCEPTIONS, a)
+
+#undef GNUNET_free
+#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)
+
+#undef GNUNET_free_non_null
+#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)
+
+static int
+EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)
+{
+ int iret;
+ DWORD dwret = 0;
+ DWORD error;
+ INTERFACE_INFO *ii = NULL;
+ DWORD ii_size = sizeof (INTERFACE_INFO) * 15;
+ while (TRUE)
+ {
+ if (ii_size >= sizeof (INTERFACE_INFO) * 1000)
+ return GNUNET_SYSERR;
+ ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);
+ dwret = 0;
+ iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
+ &dwret, NULL, NULL);
+ error = GetLastError ();
+ if (iret == SOCKET_ERROR)
+ {
+ if (error == WSAEFAULT)
+ {
+ GNUNET_free (ii);
+ ii_size *= 2;
+ continue;
+ }
+ GNUNET_free (ii);
+ return GNUNET_SYSERR;
+ }
+ else
+ {
+ *inf = ii;
+ *size = dwret;
+ return GNUNET_OK;
+ }
+ }
+ return GNUNET_SYSERR;
+}
+
+int
+EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
+{
+ int result = 0;
+ SOCKET s4;
+ SOCKET s6;
+ int ifs4len = 0;
+ int ifs6len = 0;
+ INTERFACE_INFO *interfaces4 = NULL;
+ SOCKET_ADDRESS_LIST *interfaces6 = NULL;
+
+ SetLastError (0);
+ s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ (void) GetLastError ();
+ SetLastError (0);
+ s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ (void) GetLastError ();
+ if (s6 != INVALID_SOCKET)
+ {
+ ifs6len = EnumNICs_IPv6_get_ifs_count (s6);
+ if (ifs6len > 0)
+ {
+ interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);
+ result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;
+ }
+ closesocket (s6);
+ s6 = INVALID_SOCKET;
+ }
+
+ if (s4 != INVALID_SOCKET)
+ {
+ result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;
+ closesocket (s4);
+ s4 = INVALID_SOCKET;
+ }
+ if (ifs6len + ifs4len == 0)
+ goto error;
+
+ if (!result)
+ {
+ *ifs4 = interfaces4;
+ *ifs4_len = ifs4len;
+ *ifs6 = interfaces6;
+ return GNUNET_OK;
+ }
+error:
+ if (interfaces4 != NULL)
+ GNUNET_free (interfaces4);
+ if (interfaces6 != NULL)
+ GNUNET_free (interfaces6);
+ if (s4 != INVALID_SOCKET)
+ closesocket (s4);
+ if (s6 != INVALID_SOCKET)
+ closesocket (s6);
+ return GNUNET_SYSERR;
+}
+
+
+/**
+ * @returns #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+EnumNICs3 (struct EnumNICs3_results **results, int *results_count)
+{
+ DWORD dwRetVal = 0;
+ int count = 0;
+ ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
+ GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
+ struct sockaddr_in6 examplecom6;
+ IPAddr examplecom;
+ DWORD best_interface = 0;
+ DWORD best_interface6 = 0;
+
+ int use_enum2 = 0;
+ INTERFACE_INFO *interfaces4 = NULL;
+ int interfaces4_len = 0;
+ SOCKET_ADDRESS_LIST *interfaces6 = NULL;
+
+ unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
+ IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
+ IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
+
+ if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
+ == ERROR_BUFFER_OVERFLOW)
+ {
+ GNUNET_free (pAddresses);
+ pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
+ }
+
+ dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
+
+ if (dwRetVal != NO_ERROR)
+ {
+ GNUNET_free (pAddresses);
+ return GNUNET_SYSERR;
+ }
+
+ if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))
+ {
+ use_enum2 = 1;
+
+ /* Enumerate NICs using WSAIoctl() */
+ if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))
+ {
+ GNUNET_free (pAddresses);
+ return GNUNET_SYSERR;
+ }
+ }
+
+ examplecom = inet_addr("192.0.34.166"); /* www.example.com */
+ if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)
+ best_interface = 0;
+
+ if (GNGetBestInterfaceEx != NULL)
+ {
+ examplecom6.sin6_family = AF_INET6;
+ examplecom6.sin6_port = 0;
+ examplecom6.sin6_flowinfo = 0;
+ examplecom6.sin6_scope_id = 0;
+ inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",
+ (struct sockaddr *) &examplecom6.sin6_addr);
+ dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,
+ &best_interface6);
+ if (dwRetVal != NO_ERROR)
+ best_interface6 = 0;
+ }
+
+ /* Give IPv6 a priority */
+ if (best_interface6 != 0)
+ best_interface = best_interface6;
+
+ count = 0;
+ for (pCurrentAddress = pAddresses;
+ pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
+ {
+ if (pCurrentAddress->OperStatus == IfOperStatusUp)
+ {
+ IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
+ for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
+ unicast = unicast->Next)
+ {
+ if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
+ unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
+ (unicast->DadState == IpDadStateDeprecated ||
+ unicast->DadState == IpDadStatePreferred))
+ count += 1;
+ }
+ }
+ }
+
+ if (count == 0)
+ {
+ *results = NULL;
+ *results_count = 0;
+ GNUNET_free (pAddresses);
+ GNUNET_free_non_null (interfaces4);
+ GNUNET_free_non_null (interfaces6);
+ return GNUNET_OK;
+ }
+
+ *results = (struct EnumNICs3_results *) GNUNET_malloc (
+ sizeof (struct EnumNICs3_results) * count);
+ *results_count = count;
+
+ count = 0;
+ for (pCurrentAddress = pAddresses;
+ pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
+ {
+ struct EnumNICs3_results *r;
+ IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
+ if (pCurrentAddress->OperStatus != IfOperStatusUp)
+ continue;
+ for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
+ unicast = unicast->Next)
+ {
+ int i, j;
+ int mask_length = -1;
+ char dst[INET6_ADDRSTRLEN + 1];
+
+ if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
+ unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
+ (unicast->DadState != IpDadStateDeprecated &&
+ unicast->DadState != IpDadStatePreferred))
+ continue;
+
+ r = &(*results)[count];
+ r->flags = 0;
+ if (pCurrentAddress->IfIndex > 0 &&
+ pCurrentAddress->IfIndex == best_interface &&
+ unicast->Address.lpSockaddr->sa_family == AF_INET)
+ r->is_default = 1;
+ else if (pCurrentAddress->Ipv6IfIndex > 0 &&
+ pCurrentAddress->Ipv6IfIndex == best_interface6 &&
+ unicast->Address.lpSockaddr->sa_family == AF_INET6)
+ r->is_default = 1;
+ else
+ r->is_default = 0;
+
+ /* Don't choose default interface twice */
+ if (r->is_default)
+ best_interface = best_interface6 = 0;
+
+ if (!use_enum2)
+ {
+ GNUNET_memcpy (&r->address, unicast->Address.lpSockaddr,
+ unicast->Address.iSockaddrLength);
+ memset (&r->mask, 0, sizeof (struct sockaddr));
+ mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->
+ OnLinkPrefixLength;
+ /* OnLinkPrefixLength is the number of leading 1s in the mask.
+ * OnLinkPrefixLength is available on Vista and later (hence use_enum2).
+ */
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+ for (i = 0; i < mask_length; i++)
+ ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
+ }
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;
+ struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;
+ for (i = 0; i < mask_length; i++)
+ ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
+ GNUNET_memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
+ for (i = mask_length; i < 128; i++)
+ ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
+ }
+ r->flags |= ENUMNICS3_MASK_OK;
+ }
+ else
+ {
+ int found = 0;
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)
+ {
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+ if (GNUNET_memcpy (&interfaces4[i].iiAddress.Address,
+ unicast->Address.lpSockaddr,
+ unicast->Address.iSockaddrLength) != 0)
+ continue;
+ found = 1;
+ GNUNET_memcpy (&r->address, &interfaces4[i].iiAddress.Address,
+ sizeof (struct sockaddr_in));
+ GNUNET_memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,
+ sizeof (struct sockaddr_in));
+ for (mask_length = 0;
+ ((unsigned char *) &m->sin_addr)[mask_length / 8] &
+ 0x80 >> (mask_length % 8); mask_length++)
+ {
+ }
+ r->flags |= ENUMNICS3_MASK_OK;
+ }
+ }
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+ {
+ for (i = 0;
+ interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
+ i++)
+ {
+ if (GNUNET_memcpy (interfaces6->Address[i].lpSockaddr,
+ unicast->Address.lpSockaddr,
+ unicast->Address.iSockaddrLength) != 0)
+ continue;
+ found = 1;
+ GNUNET_memcpy (&r->address, interfaces6->Address[i].lpSockaddr,
+ sizeof (struct sockaddr_in6));
+ /* TODO: Find a way to reliably get network mask for IPv6 on XP */
+ memset (&r->mask, 0, sizeof (struct sockaddr));
+ r->flags &= ~ENUMNICS3_MASK_OK;
+ }
+ }
+ if (!found)
+ {
+ DebugBreak ();
+ }
+ }
+ if (unicast->Address.lpSockaddr->sa_family == AF_INET)
+ {
+ struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
+ struct sockaddr_in *a = (struct sockaddr_in *) &r->address;
+ /* copy address to broadcast, then flip all the trailing bits not
+ * falling under netmask to 1,
+ * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
+ */
+ GNUNET_memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
+ for (i = mask_length; i < 32; i++)
+ ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
+ r->flags |= ENUMNICS3_BCAST_OK;
+ r->addr_size = sizeof (struct sockaddr_in);
+ inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
+ }
+ else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;
+ /* for IPv6 broadcast is not defined, zero it down */
+ memset (&r->broadcast, 0, sizeof (struct sockaddr));
+ r->flags &= ~ENUMNICS3_BCAST_OK;
+ r->addr_size = sizeof (struct sockaddr_in6);
+ inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
+ }
+
+ i = 0;
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
+ "%S (%s", pCurrentAddress->FriendlyName, dst);
+ for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
+ "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
+ i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
+ r->pretty_name[1000] = '\0';
+ count += 1;
+ }
+ }
+
+ if (use_enum2)
+ {
+ GNUNET_free_non_null (interfaces4);
+ GNUNET_free_non_null (interfaces6);
+ }
+
+ GNUNET_free (pAddresses);
+ return GNUNET_OK;
+}
+
+void
+EnumNICs3_free (struct EnumNICs3_results *r)
+{
+ GNUNET_free_non_null (r);
+}
+
+
+/**
+ * Lists all network interfaces in a combo box
+ * Used by the basic GTK configurator
+ *
+ * @param callback function to call for each NIC
+ * @param callback_cls closure for callback
+ */
+int
+ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)
+{
+ int r;
+ int i;
+ struct EnumNICs3_results *results = NULL;
+ int results_count;
+
+ r = EnumNICs3 (&results, &results_count);
+ if (r != GNUNET_OK)
+ return GNUNET_NO;
+
+ for (i = 0; i < results_count; i++)
+ callback (callback_cls, results[i].pretty_name, results[i].is_default);
+ GNUNET_free_non_null (results);
+ return GNUNET_YES;
+}
+
+/**
+ * @brief Installs the Windows service
+ * @param servicename name of the service as diplayed by the SCM
+ * @param application path to the application binary
+ * @param username the name of the service's user account
+ * @returns 0 on success
+ * 1 if the Windows version doesn't support services
+ * 2 if the SCM could not be opened
+ * 3 if the service could not be created
+ */
+int InstallAsService(char *servicename, char *application, char *username)
+{
+ SC_HANDLE hManager, hService;
+ char szEXE[_MAX_PATH + 17] = "\"";
+ char *user = NULL;
+
+ if (! GNOpenSCManager)
+ return 1;
+
+ plibc_conv_to_win_path(application, szEXE + 1);
+ strcat(szEXE, "\" --win-service");
+ hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
+ if (! hManager)
+ return 2;
+
+ if (username)
+ {
+ user = (char *) malloc(strlen(username) + 3);
+ sprintf(user, ".\\%s", username);
+ }
+
+ hService = GNCreateService(hManager, (LPCTSTR) servicename, (LPCTSTR) servicename, 0,
+ SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR) szEXE,
+ NULL, NULL, NULL, (LPCTSTR) user, (LPCTSTR) username);
+
+ if (user)
+ free(user);
+
+ if (! hService)
+ return 3;
+
+ GNCloseServiceHandle(hService);
+
+ return 0;
+}
+
+
+/**
+ * @brief Uninstall Windows service
+ * @param servicename name of the service to delete
+ * @returns 0 on success
+ * 1 if the Windows version doesn't support services
+ * 2 if the SCM could not be openend
+ * 3 if the service cannot be accessed
+ * 4 if the service cannot be deleted
+ */
+int
+UninstallService(char *servicename)
+{
+ SC_HANDLE hManager, hService;
+
+ if (! GNOpenSCManager)
+ return 1;
+
+ hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
+ if (! hManager)
+ return 2;
+
+ if (! (hService = GNOpenService(hManager, (LPCTSTR) servicename, DELETE)))
+ {
+ if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
+ return 3;
+ else
+ goto closeSCM;
+ }
+
+ if (! GNDeleteService(hService))
+ if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
+ return 4;
+
+closeSCM:
+ GNCloseServiceHandle(hService);
+
+ return 0;
+}
+
+/**
+ * @author Scott Field, Microsoft
+ * @see http://support.microsoft.com/?scid=kb;en-us;132958
+ * @date 12-Jul-95
+ */
+void
+_InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
+{
+ DWORD StringLength;
+
+ if(String == NULL)
+ {
+ LsaString->Buffer = NULL;
+ LsaString->Length = 0;
+ LsaString->MaximumLength = 0;
+ return;
+ }
+
+ StringLength = wcslen(String);
+ LsaString->Buffer = String;
+ LsaString->Length = (USHORT) StringLength *sizeof(WCHAR);
+ LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
+}
+
+
+/**
+ * @author Scott Field, Microsoft
+ * @see http://support.microsoft.com/?scid=kb;en-us;132958
+ * @date 12-Jul-95
+ */
+NTSTATUS
+_OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
+{
+ LSA_OBJECT_ATTRIBUTES ObjectAttributes;
+ LSA_UNICODE_STRING ServerString;
+ PLSA_UNICODE_STRING Server = NULL;
+
+ /* Always initialize the object attributes to all zeroes. */
+ ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
+
+ if(ServerName != NULL)
+ {
+ /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */
+ _InitLsaString(&ServerString, ServerName);
+ Server = &ServerString;
+ }
+
+ /* Attempt to open the policy. */
+ return GNLsaOpenPolicy(Server,
+ &ObjectAttributes, DesiredAccess, PolicyHandle);
+}
+
+/**
+ * @brief Obtain a SID representing the supplied account on the supplied system
+ * @return TRUE on success, FALSE on failure
+ * @author Scott Field, Microsoft
+ * @date 12-Jul-95
+ * @remarks A buffer is allocated which contains the SID representing the
+ * supplied account. This buffer should be freed when it is no longer
+ * needed by calling\n
+ * HeapFree(GetProcessHeap(), 0, buffer)
+ * @remarks Call GetLastError() to obtain extended error information.
+ * @see http://support.microsoft.com/?scid=kb;en-us;132958
+ */
+BOOL
+_GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)
+{
+ LPTSTR ReferencedDomain = NULL;
+ DWORD cbSid = 128; /* initial allocation attempt */
+ DWORD cchReferencedDomain = 16; /* initial allocation size */
+ SID_NAME_USE peUse;
+ BOOL bSuccess = FALSE; /* assume this function will fail */
+
+ /* initial memory allocations */
+ if ((*Sid = HeapAlloc (GetProcessHeap (), 0, cbSid)) == NULL)
+ return FALSE;
+
+ if ((ReferencedDomain = (LPTSTR) HeapAlloc (GetProcessHeap (),
+ 0,
+ cchReferencedDomain *
+ sizeof (TCHAR))) == NULL)
+ return FALSE;
+
+ /* Obtain the SID of the specified account on the specified system. */
+ while (!GNLookupAccountName(SystemName, /* machine to lookup account on */
+ AccountName, /* account to lookup */
+ *Sid, /* SID of interest */
+ &cbSid, /* size of SID */
+ ReferencedDomain, /* domain account was found on */
+ &cchReferencedDomain, &peUse))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ /* reallocate memory */
+ if ((*Sid = HeapReAlloc (GetProcessHeap (), 0, *Sid, cbSid)) == NULL)
+ return FALSE;
+
+ if ((ReferencedDomain = (LPTSTR) HeapReAlloc (GetProcessHeap (),
+ 0,
+ ReferencedDomain,
+ cchReferencedDomain
+ * sizeof (TCHAR))) == NULL)
+ return FALSE;
+ }
+ else
+ goto end;
+ }
+
+ /* Indicate success. */
+ bSuccess = TRUE;
+
+end:
+ /* Cleanup and indicate failure, if appropriate. */
+ HeapFree (GetProcessHeap (), 0, ReferencedDomain);
+
+ if (!bSuccess)
+ {
+ if (*Sid != NULL)
+ {
+ HeapFree (GetProcessHeap (), 0, *Sid);
+ *Sid = NULL;
+ }
+ }
+
+ return bSuccess;
+}
+
+/**
+ * @author Scott Field, Microsoft
+ * @see http://support.microsoft.com/?scid=kb;en-us;132958
+ * @date 12-Jul-95
+ */
+NTSTATUS
+_SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */
+ PSID AccountSid, /* SID to grant privilege to */
+ LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
+ BOOL bEnable /* enable or disable */
+ )
+{
+ LSA_UNICODE_STRING PrivilegeString;
+
+ /* Create a LSA_UNICODE_STRING for the privilege name. */
+ _InitLsaString(&PrivilegeString, PrivilegeName);
+
+ /* grant or revoke the privilege, accordingly */
+ if(bEnable)
+ {
+ NTSTATUS i;
+
+ i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */
+ AccountSid, /* target SID */
+ &PrivilegeString, /* privileges */
+ 1 /* privilege count */
+ );
+ return i;
+ }
+ else
+ {
+ return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */
+ AccountSid, /* target SID */
+ FALSE, /* do not disable all rights */
+ &PrivilegeString, /* privileges */
+ 1 /* privilege count */
+ );
+ }
+}
+
+/**
+ * @brief Create a Windows service account
+ * @return 0 on success, > 0 otherwise
+ * @param pszName the name of the account
+ * @param pszDesc description of the account
+ */
+int
+CreateServiceAccount(const char *pszName,
+ const char *pszDesc)
+{
+ USER_INFO_1 ui;
+ USER_INFO_1008 ui2;
+ NET_API_STATUS nStatus;
+ wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH];
+ LSA_HANDLE hPolicy;
+ PSID pSID;
+
+ if (! GNNetUserAdd)
+ return 1;
+ mbstowcs(wszName, pszName, strlen(pszName) + 1);
+ mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1);
+
+ memset(&ui, 0, sizeof(ui));
+ ui.usri1_name = wszName;
+ ui.usri1_password = wszName; /* account is locked anyway */
+ ui.usri1_priv = USER_PRIV_USER;
+ ui.usri1_comment = wszDesc;
+ ui.usri1_flags = UF_SCRIPT;
+
+ nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);
+
+ if (nStatus != NERR_Success && nStatus != NERR_UserExists)
+ return 2;
+
+ ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
+ GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL);
+
+ if (!NT_SUCCESS(_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy)))
+ return 3;
+
+ _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID);
+
+ if (!NT_SUCCESS(_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE)))
+ return 4;
+
+ _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE);
+ _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE);
+ _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE);
+
+ GNLsaClose(hPolicy);
+
+ return 0;
+}
+
+/**
+ * @brief Grant permission to a file
+ * @param lpszFileName the name of the file or directory
+ * @param lpszAccountName the user account
+ * @param dwAccessMask the desired access (e.g. GENERIC_ALL)
+ * @return TRUE on success
+ * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&
+ */
+BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,
+ DWORD dwAccessMask)
+{
+ /* SID variables. */
+ SID_NAME_USE snuType;
+ TCHAR * szDomain = NULL;
+ DWORD cbDomain = 0;
+ LPVOID pUserSID = NULL;
+ DWORD cbUserSID = 0;
+
+ /* File SD variables. */
+ PSECURITY_DESCRIPTOR pFileSD = NULL;
+ DWORD cbFileSD = 0;
+
+ /* New SD variables. */
+ SECURITY_DESCRIPTOR newSD;
+
+ /* ACL variables. */
+ PACL pACL = NULL;
+ BOOL fDaclPresent;
+ BOOL fDaclDefaulted;
+ ACL_SIZE_INFORMATION AclInfo;
+
+ /* New ACL variables. */
+ PACL pNewACL = NULL;
+ DWORD cbNewACL = 0;
+
+ /* Temporary ACE. */
+ LPVOID pTempAce = NULL;
+ UINT CurrentAceIndex = 0;
+
+ UINT newAceIndex = 0;
+
+ /* Assume function will fail. */
+ BOOL fResult = FALSE;
+ BOOL fAPISuccess;
+
+ SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
+
+ /**
+ * STEP 1: Get SID of the account name specified.
+ */
+ fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,
+ pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);
+
+ /* API should have failed with insufficient buffer. */
+ if (fAPISuccess)
+ goto end;
+ else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ goto end;
+ }
+
+ pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID);
+ if (!pUserSID) {
+ goto end;
+ }
+
+ szDomain = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR));
+ if (!szDomain) {
+ goto end;
+ }
+
+ fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,
+ pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);
+ if (!fAPISuccess) {
+ goto end;
+ }
+
+ /**
+ * STEP 2: Get security descriptor (SD) of the file specified.
+ */
+ fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,
+ secInfo, pFileSD, 0, &cbFileSD);
+
+ /* API should have failed with insufficient buffer. */
+ if (fAPISuccess)
+ goto end;
+ else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ goto end;
+ }
+
+ pFileSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ cbFileSD);
+ if (!pFileSD) {
+ goto end;
+ }
+
+ fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,
+ secInfo, pFileSD, cbFileSD, &cbFileSD);
+ if (!fAPISuccess) {
+ goto end;
+ }
+
+ /**
+ * STEP 3: Initialize new SD.
+ */
+ if (!GNInitializeSecurityDescriptor(&newSD,
+ SECURITY_DESCRIPTOR_REVISION)) {
+ goto end;
+ }
+
+ /**
+ * STEP 4: Get DACL from the old SD.
+ */
+ if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
+ &fDaclDefaulted)) {
+ goto end;
+ }
+
+ /**
+ * STEP 5: Get size information for DACL.
+ */
+ AclInfo.AceCount = 0; // Assume NULL DACL.
+ AclInfo.AclBytesFree = 0;
+ AclInfo.AclBytesInUse = sizeof(ACL);
+
+ if (pACL == NULL)
+ fDaclPresent = FALSE;
+
+ /* If not NULL DACL, gather size information from DACL. */
+ if (fDaclPresent) {
+
+ if (!GNGetAclInformation(pACL, &AclInfo,
+ sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
+ goto end;
+ }
+ }
+
+ /**
+ * STEP 6: Compute size needed for the new ACL.
+ */
+ cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
+ + GetLengthSid(pUserSID) - sizeof(DWORD);
+
+ /**
+ * STEP 7: Allocate memory for new ACL.
+ */
+ pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);
+ if (!pNewACL) {
+ goto end;
+ }
+
+ /**
+ * STEP 8: Initialize the new ACL.
+ */
+ if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) {
+ goto end;
+ }
+
+ /**
+ * STEP 9 If DACL is present, copy all the ACEs from the old DACL
+ * to the new DACL.
+ *
+ * The following code assumes that the old DACL is
+ * already in Windows 2000 preferred order. To conform
+ * to the new Windows 2000 preferred order, first we will
+ * copy all non-inherited ACEs from the old DACL to the
+ * new DACL, irrespective of the ACE type.
+ */
+
+ newAceIndex = 0;
+
+ if (fDaclPresent && AclInfo.AceCount) {
+
+ for (CurrentAceIndex = 0;
+ CurrentAceIndex < AclInfo.AceCount;
+ CurrentAceIndex++) {
+
+ /**
+ * TEP 10: Get an ACE.
+ */
+ if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {
+ goto end;
+ }
+
+ /**
+ * STEP 11: Check if it is a non-inherited ACE.
+ * If it is an inherited ACE, break from the loop so
+ * that the new access allowed non-inherited ACE can
+ * be added in the correct position, immediately after
+ * all non-inherited ACEs.
+ */
+ if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
+ & INHERITED_ACE)
+ break;
+
+ /**
+ * STEP 12: Skip adding the ACE, if the SID matches
+ * with the account specified, as we are going to
+ * add an access allowed ACE with a different access
+ * mask.
+ */
+ if (GNEqualSid(pUserSID,
+ &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
+ continue;
+
+ /**
+ * STEP 13: Add the ACE to the new ACL.
+ */
+ if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
+ ((PACE_HEADER) pTempAce)->AceSize)) {
+ goto end;
+ }
+
+ newAceIndex++;
+ }
+ }
+
+ /**
+ * STEP 14: Add the access-allowed ACE to the new DACL.
+ * The new ACE added here will be in the correct position,
+ * immediately after all existing non-inherited ACEs.
+ */
+ if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
+ pUserSID)) {
+ goto end;
+ }
+
+ /**
+ * STEP 14.5: Make new ACE inheritable
+ */
+ if (!GetAce(pNewACL, newAceIndex, &pTempAce))
+ goto end;
+ ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |=
+ (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
+
+ /**
+ * STEP 15: To conform to the new Windows 2000 preferred order,
+ * we will now copy the rest of inherited ACEs from the
+ * old DACL to the new DACL.
+ */
+ if (fDaclPresent && AclInfo.AceCount) {
+
+ for (;
+ CurrentAceIndex < AclInfo.AceCount;
+ CurrentAceIndex++) {
+
+ /**
+ * STEP 16: Get an ACE.
+ */
+ if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {
+ goto end;
+ }
+
+ /**
+ * STEP 17: Add the ACE to the new ACL.
+ */
+ if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
+ ((PACE_HEADER) pTempAce)->AceSize)) {
+ goto end;
+ }
+ }
+ }
+
+ /**
+ * STEP 18: Set permissions
+ */
+ if (GNSetNamedSecurityInfo((LPTSTR) lpszFileName, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) {
+ goto end;
+ }
+
+ fResult = TRUE;
+
+end:
+
+ /**
+ * STEP 19: Free allocated memory
+ */
+ if (pUserSID)
+ HeapFree(GetProcessHeap(), 0, pUserSID);
+
+ if (szDomain)
+ HeapFree(GetProcessHeap(), 0, szDomain);
+
+ if (pFileSD)
+ HeapFree(GetProcessHeap(), 0, pFileSD);
+
+ if (pNewACL)
+ HeapFree(GetProcessHeap(), 0, pNewACL);
+
+ return fResult;
+}
+
+char *winErrorStr(const char *prefix, int dwErr)
+{
+ char *err, *ret;
+ int mem;
+
+ if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err,
+ 0, NULL ))
+ {
+ err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1);
+ }
+
+ mem = strlen(err) + strlen(prefix) + 20;
+ ret = (char *) malloc(mem);
+
+ snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
+
+ LocalFree(err);
+
+ return ret;
+}
+
/**
* Terminate a process by creating a remote thread within it,
* which proceeds to call ExitProcess() inside that process.
* @param dwTimeout number of ms to wait for the process to terminate
* @return TRUE on success, FALSE on failure (check last error for the code)
*/
-BOOL\r
-SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)\r
-{\r
- DWORD dwTID, dwCode, dwErr = 0;\r
- HANDLE hProcessDup = INVALID_HANDLE_VALUE;\r
- HANDLE hRT = NULL;\r
- HINSTANCE hKernel = GetModuleHandle ("Kernel32");\r
- BOOL bSuccess = FALSE;\r
-\r
- BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,\r
- GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,\r
- FALSE, 0);\r
-\r
- /* Detect the special case where the process is\r
- * already dead...\r
- */\r
- if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&\r
- (STILL_ACTIVE == dwCode))\r
- {\r
- FARPROC pfnExitProc;\r
-\r
- pfnExitProc = GetProcAddress (hKernel, "ExitProcess");\r
-\r
- hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,\r
- (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);\r
-\r
- dwErr = GetLastError ();\r
- }\r
- else\r
- {\r
- dwErr = ERROR_PROCESS_ABORTED;\r
- }\r
-\r
- if (hRT)\r
- {\r
- /* Must wait process to terminate to\r
- * guarantee that it has exited...\r
- */\r
- DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,\r
- dwTimeout);\r
- if (dwWaitResult == WAIT_TIMEOUT)\r
- dwErr = WAIT_TIMEOUT;\r
- else\r
- dwErr = GetLastError ();\r
-\r
- CloseHandle (hRT);\r
- bSuccess = dwErr == NO_ERROR;\r
- }\r
-\r
- if (bDup)\r
- CloseHandle (hProcessDup);\r
-\r
- SetLastError (dwErr);\r
-\r
- return bSuccess;\r
+BOOL
+SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
+{
+ DWORD dwTID, dwCode, dwErr = 0;
+ HANDLE hProcessDup = INVALID_HANDLE_VALUE;
+ HANDLE hRT = NULL;
+ HINSTANCE hKernel = GetModuleHandle ("Kernel32");
+ BOOL bSuccess = FALSE;
+
+ BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess,
+ GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS,
+ FALSE, 0);
+
+ /* Detect the special case where the process is
+ * already dead...
+ */
+ if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) &&
+ (STILL_ACTIVE == dwCode))
+ {
+ FARPROC pfnExitProc;
+
+ pfnExitProc = GetProcAddress (hKernel, "ExitProcess");
+
+ hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0,
+ (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID);
+
+ dwErr = GetLastError ();
+ }
+ else
+ {
+ dwErr = ERROR_PROCESS_ABORTED;
+ }
+
+ if (hRT)
+ {
+ /* Must wait process to terminate to
+ * guarantee that it has exited...
+ */
+ DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess,
+ dwTimeout);
+ if (dwWaitResult == WAIT_TIMEOUT)
+ dwErr = WAIT_TIMEOUT;
+ else
+ dwErr = GetLastError ();
+
+ CloseHandle (hRT);
+ bSuccess = dwErr == NO_ERROR;
+ }
+
+ if (bDup)
+ CloseHandle (hProcessDup);
+
+ SetLastError (dwErr);
+
+ return bSuccess;
}
-\r
-#endif\r
+
+#endif