IdWship6.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.0 2004.02.03 3:14:52 PM czhower
  18. Move and updates
  19. Rev 1.2 10/15/2003 9:43:20 PM DSiders
  20. Added localization comments.
  21. Rev 1.1 1-10-2003 19:44:28 BGooijen
  22. fixed leak in CloseLibrary()
  23. Rev 1.0 11/13/2002 09:03:24 AM JPMugaas
  24. }
  25. unit IdWship6;
  26. interface
  27. {$I IdCompilerDefines.inc}
  28. {$IFDEF FPC}
  29. {$IFDEF WIN32}
  30. {$ALIGN OFF}
  31. {$ELSE}
  32. //It turns out that Win64 and WinCE require record alignment
  33. {$PACKRECORDS C}
  34. {$ENDIF}
  35. {$ELSE}
  36. {$IFDEF WIN64}
  37. {$ALIGN ON}
  38. {$MINENUMSIZE 4}
  39. {$ELSE}
  40. {$MINENUMSIZE 4}
  41. {$IFDEF REQUIRES_PROPER_ALIGNMENT}
  42. {$ALIGN ON}
  43. {$ELSE}
  44. {$ALIGN OFF}
  45. {$WRITEABLECONST OFF}
  46. {$ENDIF}
  47. {$ENDIF}
  48. {$ENDIF}
  49. uses
  50. {$IFDEF HAS_TInterlocked}
  51. syncobjs, //here to facilitate inlining with Delphi
  52. {$ENDIF}
  53. IdGlobal,
  54. Windows,
  55. IdWinsock2;
  56. const
  57. Wship6_dll = 'Wship6.dll'; {do not localize}
  58. iphlpapi_dll = 'iphlpapi.dll'; {do not localize}
  59. fwpuclnt_dll = 'Fwpuclnt.dll'; {Do not localize}
  60. // Error codes from getaddrinfo().
  61. //JPM
  62. //Note that I am adding a GIA_ prefix on my own because
  63. //some names here share some names defined in IdWinsock2 causing
  64. //an unpredictible problem. The values are not defined the same in IdWinsock2
  65. {$EXTERNALSYM GIA_EAI_ADDRFAMILY}
  66. GIA_EAI_ADDRFAMILY = 1 ; // Address family for nodename not supported.
  67. {$EXTERNALSYM GIA_EAI_AGAIN}
  68. GIA_EAI_AGAIN = 2 ; // Temporary failure in name resolution.
  69. {$EXTERNALSYM GIA_EAI_BADFLAGS}
  70. GIA_EAI_BADFLAGS = 3 ; // Invalid value for ai_flags.
  71. {$EXTERNALSYM GIA_EAI_FAIL}
  72. GIA_EAI_FAIL = 4 ; // Non-recoverable failure in name resolution.
  73. {$EXTERNALSYM GIA_EAI_FAMILY}
  74. GIA_EAI_FAMILY = 5 ; // Address family ai_family not supported.
  75. {$EXTERNALSYM GIA_EAI_MEMORY}
  76. GIA_EAI_MEMORY = 6 ; // Memory allocation failure.
  77. {$EXTERNALSYM GIA_EAI_NODATA}
  78. GIA_EAI_NODATA = 7 ; // No address associated with nodename.
  79. {$EXTERNALSYM GIA_EAI_NONAME}
  80. GIA_EAI_NONAME = 8 ; // Nodename nor servname provided, or not known.
  81. {$EXTERNALSYM GIA_EAI_SERVICE}
  82. GIA_EAI_SERVICE = 9 ; // Servname not supported for ai_socktype.
  83. {$EXTERNALSYM GIA_EAI_SOCKTYPE}
  84. GIA_EAI_SOCKTYPE = 10 ; // Socket type ai_socktype not supported.
  85. {$EXTERNALSYM GIA_EAI_SYSTEM}
  86. GIA_EAI_SYSTEM = 11 ; // System error returned in errno.
  87. {$EXTERNALSYM NI_MAXHOST}
  88. NI_MAXHOST = 1025; // Max size of a fully-qualified domain name.
  89. {$EXTERNALSYM NI_MAXSERV}
  90. NI_MAXSERV = 32; // Max size of a service name.
  91. // Flags for getnameinfo().
  92. {$EXTERNALSYM NI_NOFQDN}
  93. NI_NOFQDN = $1 ; // Only return nodename portion for local hosts.
  94. {$EXTERNALSYM NI_NUMERICHOST}
  95. NI_NUMERICHOST = $2 ; // Return numeric form of the host's address.
  96. {$EXTERNALSYM NI_NAMEREQD}
  97. NI_NAMEREQD = $4 ; // Error if the host's name not in DNS.
  98. {$EXTERNALSYM NI_NUMERICSERV}
  99. NI_NUMERICSERV = $8 ; // Return numeric form of the service (port #).
  100. {$EXTERNALSYM NI_DGRAM}
  101. NI_DGRAM = $10 ; // Service is a datagram service.
  102. //JPM - These may not be supported in WinCE 4.2
  103. {$EXTERNALSYM PROTECTION_LEVEL_RESTRICTED}
  104. PROTECTION_LEVEL_RESTRICTED = 30; //* for Intranet apps /*
  105. {$EXTERNALSYM PROTECTION_LEVEL_DEFAULT}
  106. PROTECTION_LEVEL_DEFAULT = 20; //* default level /*
  107. {$EXTERNALSYM PROTECTION_LEVEL_UNRESTRICTED}
  108. PROTECTION_LEVEL_UNRESTRICTED = 10; //* for peer-to-peer apps /*
  109. {$EXTERNALSYM SOCKET_SETTINGS_GUARANTEE_ENCRYPTION}
  110. SOCKET_SETTINGS_GUARANTEE_ENCRYPTION = $00000001;
  111. {$EXTERNALSYM SOCKET_SETTINGS_ALLOW_INSECURE}
  112. SOCKET_SETTINGS_ALLOW_INSECURE = $00000002;
  113. {$EXTERNALSYM SOCKET_INFO_CONNECTION_SECURED}
  114. SOCKET_INFO_CONNECTION_SECURED = $00000001;
  115. {$EXTERNALSYM SOCKET_INFO_CONNECTION_ENCRYPTED}
  116. SOCKET_INFO_CONNECTION_ENCRYPTED = $00000002;
  117. type
  118. // RLebeau: find a better place for this
  119. {$IFNDEF HAS_UInt64}
  120. {$EXTERNALSYM UINT64}
  121. UINT64 = {$IFDEF HAS_QWord}QWord{$ELSE}Int64{$ENDIF};
  122. {$ENDIF}
  123. {$NODEFINE PPaddrinfo}
  124. PPaddrinfo = ^PAddrInfo;
  125. {$NODEFINE PPaddrinfoW}
  126. PPaddrinfoW = ^PAddrInfoW;
  127. {$IFNDEF WINCE}
  128. {$EXTERNALSYM SOCKET_SECURITY_PROTOCOL}
  129. {$EXTERNALSYM SOCKET_SECURITY_PROTOCOL_DEFAULT}
  130. {$EXTERNALSYM SOCKET_SECURITY_PROTOCOL_IPSEC}
  131. {$EXTERNALSYM SOCKET_SECURITY_PROTOCOL_INVALID}
  132. SOCKET_SECURITY_PROTOCOL = (
  133. SOCKET_SECURITY_PROTOCOL_DEFAULT, SOCKET_SECURITY_PROTOCOL_IPSEC, SOCKET_SECURITY_PROTOCOL_INVALID
  134. );
  135. {$EXTERNALSYM SOCKET_SECURITY_SETTINGS_IPSEC}
  136. SOCKET_SECURITY_SETTINGS_IPSEC = record
  137. SecurityProtocol : SOCKET_SECURITY_PROTOCOL;
  138. SecurityFlags : ULONG;
  139. IpsecFlags : ULONG;
  140. AuthipMMPolicyKey : TGUID;
  141. AuthipQMPolicyKey : TGUID;
  142. Reserved : TGUID;
  143. Reserved2 : UINT64;
  144. UserNameStringLen : ULONG;
  145. DomainNameStringLen : ULONG;
  146. PasswordStringLen : ULONG;
  147. // wchar_t AllStrings[0];
  148. end;
  149. {$EXTERNALSYM PSOCKET_SECURITY_SETTINGS_IPSEC}
  150. PSOCKET_SECURITY_SETTINGS_IPSEC = ^SOCKET_SECURITY_SETTINGS_IPSEC;
  151. {$EXTERNALSYM SOCKET_SECURITY_SETTINGS}
  152. SOCKET_SECURITY_SETTINGS = record
  153. SecurityProtocol : SOCKET_SECURITY_PROTOCOL;
  154. SecurityFlags : ULONG;
  155. end;
  156. {$EXTERNALSYM PSOCKET_SECURITY_SETTINGS}
  157. PSOCKET_SECURITY_SETTINGS = ^SOCKET_SECURITY_SETTINGS;
  158. {$EXTERNALSYM SOCKET_PEER_TARGET_NAME}
  159. SOCKET_PEER_TARGET_NAME = record
  160. SecurityProtocol : SOCKET_SECURITY_PROTOCOL;
  161. PeerAddress : SOCKADDR_STORAGE;
  162. PeerTargetNameStringLen : ULONG;
  163. //wchar_t AllStrings[0];
  164. end;
  165. {$EXTERNALSYM PSOCKET_PEER_TARGET_NAME}
  166. PSOCKET_PEER_TARGET_NAME = ^SOCKET_PEER_TARGET_NAME;
  167. {$EXTERNALSYM SOCKET_SECURITY_QUERY_INFO}
  168. SOCKET_SECURITY_QUERY_INFO = record
  169. SecurityProtocol : SOCKET_SECURITY_PROTOCOL;
  170. Flags : ULONG;
  171. PeerApplicationAccessTokenHandle : UINT64;
  172. PeerMachineAccessTokenHandle : UINT64;
  173. end;
  174. {$EXTERNALSYM PSOCKET_SECURITY_QUERY_INFO}
  175. PSOCKET_SECURITY_QUERY_INFO = ^SOCKET_SECURITY_QUERY_INFO;
  176. {$EXTERNALSYM SOCKET_SECURITY_QUERY_TEMPLATE}
  177. SOCKET_SECURITY_QUERY_TEMPLATE = record
  178. SecurityProtocol : SOCKET_SECURITY_PROTOCOL;
  179. PeerAddress : SOCKADDR_STORAGE;
  180. PeerTokenAccessMask : ULONG;
  181. end;
  182. {$EXTERNALSYM PSOCKET_SECURITY_QUERY_TEMPLATE}
  183. PSOCKET_SECURITY_QUERY_TEMPLATE = ^SOCKET_SECURITY_QUERY_TEMPLATE;
  184. //callback defs
  185. type
  186. {$EXTERNALSYM LPLOOKUPSERVICE_COMPLETION_ROUTINE}
  187. LPLOOKUPSERVICE_COMPLETION_ROUTINE = procedure (const dwError, dwBytes : DWORD; lpOverlapped : LPWSAOVERLAPPED); stdcall;
  188. {$ENDIF}
  189. type
  190. {$EXTERNALSYM LPFN_GETADDRINFO}
  191. LPFN_GETADDRINFO = function(NodeName: PIdAnsiChar; ServiceName: PIdAnsiChar; Hints: Paddrinfo; ppResult: PPaddrinfo): Integer; stdcall;
  192. {$EXTERNALSYM LPFN_GETADDRINFOW}
  193. LPFN_GETADDRINFOW = function(NodeName: PWideChar; ServiceName: PWideChar; Hints: PaddrinfoW; ppResult: PPaddrinfoW): Integer; stdcall;
  194. {$EXTERNALSYM LPFN_GETNAMEINFO}
  195. //The IPv6 preview for Win2K defines hostlen and servelen as size_t but do not use them
  196. //for these definitions as the newer SDK's define those as DWORD.
  197. LPFN_GETNAMEINFO = function(sa: psockaddr; salen: u_int; host: PIdAnsiChar; hostlen: u_int; serv: PIdAnsiChar; servlen: u_int; flags: Integer): Integer; stdcall;
  198. {$EXTERNALSYM LPFN_GETNAMEINFOW}
  199. LPFN_GETNAMEINFOW = function(sa: psockaddr; salen: u_int; host: PWideChar; hostlen: u_int; serv: PWideChar; servlen: u_int; flags: Integer): Integer; stdcall;
  200. {$EXTERNALSYM LPFN_FREEADDRINFO}
  201. LPFN_FREEADDRINFO = procedure(ai: Paddrinfo); stdcall;
  202. {$EXTERNALSYM LPFN_FREEADDRINFOW}
  203. LPFN_FREEADDRINFOW = procedure(ai: PaddrinfoW); stdcall;
  204. //function GetAdaptersAddresses( Family:ULONG; Flags:ULONG; Reserved:Pointer; pAdapterAddresses: PIP_ADAPTER_ADDRESSES; pOutBufLen:PULONG):ULONG;stdcall; external iphlpapi_dll;
  205. { the following are not used, nor tested}
  206. {function getipnodebyaddr(const src:pointer; len:integer; af:integer;var error_num:integer) :phostent;stdcall; external Wship6_dll;
  207. procedure freehostent(ptr:phostent);stdcall; external Wship6_dll;
  208. function inet_pton(af:integer; const src:pchar; dst:pointer):integer;stdcall; external Wship6_dll;
  209. function inet_ntop(af:integer; const src:pointer; dst:pchar;size:integer):pchar;stdcall; external Wship6_dll;
  210. }
  211. {$IFNDEF WINCE}
  212. {$EXTERNALSYM LPFN_INET_PTON}
  213. LPFN_INET_PTON = function (af: Integer; const src: PIdAnsiChar; dst: Pointer): Integer; stdcall;
  214. {$EXTERNALSYM LPFN_INET_PTONW}
  215. LPFN_INET_PTONW = function (af: Integer; const src: PWideChar; dst: Pointer): Integer; stdcall;
  216. {$EXTERNALSYM LPFN_INET_NTOP}
  217. LPFN_INET_NTOP = function (af: Integer; const src: Pointer; dst: PIdAnsiChar; size: size_t): PIdAnsiChar; stdcall;
  218. {$EXTERNALSYM LPFN_INET_NTOPW}
  219. LPFN_INET_NTOPW = function (af: Integer; const src: Pointer; dst: PWideChar; size: size_t): PIdAnsiChar; stdcall;
  220. { end the following are not used, nor tested}
  221. //These are provided in case we need them later
  222. //Windows Vista
  223. {$EXTERNALSYM LPFN_GETADDRINFOEXA}
  224. LPFN_GETADDRINFOEXA = function(pName : PIdAnsiChar; pServiceName : PIdAnsiChar;
  225. const dwNameSpace: DWord; lpNspId : LPGUID; hints : PADDRINFOEXA;
  226. var ppResult : PADDRINFOEXA; timeout : Ptimeval; lpOverlapped : LPWSAOVERLAPPED;
  227. lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE;
  228. lpNameHandle : PHandle) : Integer; stdcall;
  229. {$EXTERNALSYM LPFN_GETADDRINFOEXW}
  230. LPFN_GETADDRINFOEXW = function(pName : PWideChar; pServiceName : PWideChar;
  231. const dwNameSpace: DWord; lpNspId : LPGUID;hints : PADDRINFOEXW;
  232. var ppResult : PADDRINFOEXW; timeout : Ptimeval; lpOverlapped : LPWSAOVERLAPPED;
  233. lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE;
  234. lpNameHandle : PHandle) : Integer; stdcall;
  235. {$EXTERNALSYM LPFN_SETADDRINFOEXA}
  236. LPFN_SETADDRINFOEXA= function(pName : PIdAnsiChar; pServiceName : PIdAnsiChar;
  237. pAddresses : PSOCKET_ADDRESS; const dwAddressCount : DWord; lpBlob : LPBLOB;
  238. const dwFlags : DWord; const dwNameSpace : DWord; lpNspId : LPGUID;
  239. timeout : Ptimeval;
  240. lpOverlapped : LPWSAOVERLAPPED;
  241. lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE; lpNameHandle : PHandle) : Integer; stdcall;
  242. {$EXTERNALSYM LPFN_SETADDRINFOEXW}
  243. LPFN_SETADDRINFOEXW= function(pName : PWideChar; pServiceName : PWideChar;
  244. pAddresses : PSOCKET_ADDRESS; const dwAddressCount : DWord; lpBlob : LPBLOB;
  245. const dwFlags : DWord; const dwNameSpace : DWord; lpNspId : LPGUID;
  246. timeout : Ptimeval;
  247. lpOverlapped : LPWSAOVERLAPPED;
  248. lpCompletionRoutine : LPLOOKUPSERVICE_COMPLETION_ROUTINE; lpNameHandle : PHandle) : Integer; stdcall;
  249. {$EXTERNALSYM LPFN_FREEADDRINFOEX}
  250. LPFN_FREEADDRINFOEX = procedure(pAddrInfoEx : PADDRINFOEXA) ; stdcall;
  251. {$EXTERNALSYM LPFN_FREEADDRINFOEXW}
  252. LPFN_FREEADDRINFOEXW = procedure(pAddrInfoEx : PADDRINFOEXW) ; stdcall;
  253. {$EXTERNALSYM LPFN_GETADDRINFOEX}
  254. {$EXTERNALSYM LPFN_SETADDRINFOEX}
  255. {$IFDEF UNICODE}
  256. LPFN_GETADDRINFOEX = LPFN_GETADDRINFOEXW;
  257. LPFN_SETADDRINFOEX = LPFN_SETADDRINFOEXW;
  258. {$ELSE}
  259. LPFN_GETADDRINFOEX = LPFN_GETADDRINFOEXA;
  260. LPFN_SETADDRINFOEX = LPFN_SETADDRINFOEXA;
  261. {$ENDIF}
  262. // Fwpuclnt.dll - API
  263. {$EXTERNALSYM LPFN_WSASetSocketSecurity}
  264. LPFN_WSASetSocketSecurity = function (socket : TSocket;
  265. SecuritySettings : PSOCKET_SECURITY_SETTINGS; const SecuritySettingsLen : ULONG;
  266. OVERLAPPED : LPWSAOVERLAPPED; CompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) : Integer; stdcall;
  267. {$EXTERNALSYM LPFN_WSADELETESOCKETPEERTARGETNAME}
  268. LPFN_WSADELETESOCKETPEERTARGETNAME = function (Socket : TSocket;
  269. PeerAddr : Psockaddr; PeerAddrLen : ULONG;
  270. Overlapped : LPWSAOVERLAPPED; CompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer; stdcall;
  271. {$EXTERNALSYM LPFN_WSASETSOCKETPEERTARGETNAME}
  272. LPFN_WSASETSOCKETPEERTARGETNAME = function (Socket : TSocket;
  273. PeerTargetName : PSOCKET_PEER_TARGET_NAME; PeerTargetNameLen : ULONG;
  274. Overlapped : LPWSAOVERLAPPED; CompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) : Integer; stdcall;
  275. {$EXTERNALSYM LPFN_WSAIMPERSONATESOCKETPEER}
  276. LPFN_WSAIMPERSONATESOCKETPEER = function (Socket : TSocket;
  277. PeerAddress : Psockaddr; peerAddressLen : ULONG) : Integer; stdcall;
  278. {$EXTERNALSYM LPFN_WSAQUERYSOCKETSECURITY}
  279. LPFN_WSAQUERYSOCKETSECURITY = function (Socket : TSocket;
  280. SecurityQueryTemplate : PSOCKET_SECURITY_QUERY_TEMPLATE; const SecurityQueryTemplateLen : ULONG;
  281. SecurityQueryInfo : PSOCKET_SECURITY_QUERY_INFO; var SecurityQueryInfoLen : ULONG;
  282. Overlapped : LPWSAOVERLAPPED; CompletionRoutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) : Integer; stdcall;
  283. {$EXTERNALSYM LPFN_WSAREVERTIMPERSONATION}
  284. LPFN_WSAREVERTIMPERSONATION = function : Integer; stdcall;
  285. {$ENDIF}
  286. const
  287. {$NODEFINE fn_GetAddrInfo}
  288. {$NODEFINE fn_getnameinfo}
  289. {$NODEFINE fn_freeaddrinfo}
  290. {$IFNDEF WINCE}
  291. {$NODEFINE fn_GetAddrInfoEx}
  292. {$NODEFINE fn_SetAddrInfoEx}
  293. {$NODEFINE fn_FreeAddrInfoEx}
  294. {$NODEFINE fn_inet_pton}
  295. {$NODEFINE fn_inet_ntop}
  296. {$ENDIF}
  297. {$IFDEF UNICODE}
  298. // WinCE does not support GetAddrInfoW(), GetNameInfoW(), or FreeAddrInfoW().
  299. // To support IPv6 on WinCE when UNICODE is defined, we will use our own
  300. // wrappers that internally call WinCE's functions...
  301. fn_GetAddrInfo = {$IFDEF WINCE}'getaddrinfo'{$ELSE}'GetAddrInfoW'{$ENDIF};
  302. fn_getnameinfo = {$IFDEF WINCE}'getnameinfo'{$ELSE}'GetNameInfoW'{$ENDIF};
  303. fn_freeaddrinfo = {$IFDEF WINCE}'freeaddrinfo'{$ELSE}'FreeAddrInfoW'{$ENDIF};
  304. {$IFNDEF WINCE}
  305. fn_GetAddrInfoEx = 'GetAddrInfoExW';
  306. fn_SetAddrInfoEx = 'SetAddrInfoExW';
  307. fn_FreeAddrInfoEx = 'FreeAddrInfoExW';
  308. fn_inet_pton = 'InetPtonW';
  309. fn_inet_ntop = 'InetNtopW';
  310. {$ENDIF}
  311. {$ELSE}
  312. fn_GetAddrInfo = 'getaddrinfo';
  313. fn_getnameinfo = 'getnameinfo';
  314. fn_freeaddrinfo = 'freeaddrinfo';
  315. {$IFNDEF WINCE}
  316. fn_GetAddrInfoEx = 'GetAddrInfoExA';
  317. fn_SetAddrInfoEx = 'SetAddrInfoExA';
  318. fn_FreeAddrInfoEx = 'FreeAddrInfoEx';
  319. fn_inet_pton = 'inet_pton';
  320. fn_inet_ntop = 'inet_ntop';
  321. {$ENDIF}
  322. {$ENDIF}
  323. {$UNDEF WINCE_UNICODE}
  324. {$IFDEF WINCE}
  325. {$IFDEF UNICODE}
  326. {$DEFINE WINCE_UNICODE}
  327. {$ENDIF}
  328. {$ENDIF}
  329. var
  330. {$EXTERNALSYM getaddrinfo}
  331. {$EXTERNALSYM getnameinfo}
  332. {$EXTERNALSYM freeaddrinfo}
  333. {$IFNDEF WINCE}
  334. {$EXTERNALSYM inet_pton}
  335. {$EXTERNALSYM inet_ntop}
  336. {$ENDIF}
  337. {$IFDEF UNICODE}
  338. {$IFDEF WINCE}
  339. getaddrinfoCE: LPFN_GETADDRINFO = nil;
  340. getnameinfoCE: LPFN_GETNAMEINFO = nil;
  341. freeaddrinfoCE: LPFN_FREEADDRINFO = nil;
  342. {$ENDIF}
  343. getaddrinfo: LPFN_GETADDRINFOW = nil;
  344. getnameinfo: LPFN_GETNAMEINFOW = nil;
  345. freeaddrinfo: LPFN_FREEADDRINFOW = nil;
  346. {$IFNDEF WINCE}
  347. //These are here for completeness
  348. inet_pton : LPFN_inet_ptonW = nil;
  349. inet_ntop : LPFN_inet_ntopW = nil;
  350. {$ENDIF}
  351. {$ELSE}
  352. getaddrinfo: LPFN_GETADDRINFO = nil;
  353. getnameinfo: LPFN_GETNAMEINFO = nil;
  354. freeaddrinfo: LPFN_FREEADDRINFO = nil;
  355. {$IFNDEF WINCE}
  356. //These are here for completeness
  357. inet_pton : LPFN_inet_pton = nil;
  358. inet_ntop : LPFN_inet_ntop = nil;
  359. {$ENDIF}
  360. {$ENDIF}
  361. {$IFNDEF WINCE}
  362. {
  363. IMPORTANT!!!
  364. These are Windows Vista functions and there's no guarantee that you will have
  365. them so ALWAYS check the function pointer before calling them.
  366. }
  367. {$EXTERNALSYM GetAddrInfoEx}
  368. GetAddrInfoEx : LPFN_GETADDRINFOEX = nil;
  369. {$EXTERNALSYM SetAddrInfoEx}
  370. SetAddrInfoEx : LPFN_SETADDRINFOEX = nil;
  371. {$EXTERNALSYM FreeAddrInfoEx}
  372. //You can't alias the LPFN for this because the ASCII version of this
  373. //does not end with an "a"
  374. {$IFDEF UNICODE}
  375. FreeAddrInfoEx : LPFN_FREEADDRINFOEXW = nil;
  376. {$ELSE}
  377. FreeAddrInfoEx : LPFN_FREEADDRINFOEX = nil;
  378. {$ENDIF}
  379. //Fwpuclnt.dll available for Windows Vista and later
  380. {$EXTERNALSYM WSASetSocketSecurity}
  381. WSASetSocketSecurity : LPFN_WSASetSocketSecurity = nil;
  382. {$EXTERNALSYM WSASETSOCKETPEERTARGETNAME}
  383. WSASetSocketPeerTargetName : LPFN_WSASETSOCKETPEERTARGETNAME = nil;
  384. {$EXTERNALSYM WSADELETESOCKETPEERTARGETNAME}
  385. WSADeleteSocketPeerTargetName : LPFN_WSADELETESOCKETPEERTARGETNAME = nil;
  386. {$EXTERNALSYM WSAImpersonateSocketPeer}
  387. WSAImpersonateSocketPeer : LPFN_WSAIMPERSONATESOCKETPEER = nil;
  388. {$EXTERNALSYM WSAQUERYSOCKETSECURITY}
  389. WSAQUERYSOCKETSECURITY : LPFN_WSAQUERYSOCKETSECURITY = nil;
  390. {$EXTERNALSYM WSAREVERTIMPERSONATION}
  391. WSARevertImpersonation : LPFN_WSAREVERTIMPERSONATION = nil;
  392. {$ENDIF}
  393. var
  394. GIdIPv6FuncsAvailable: Boolean = False{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF};
  395. function gaiErrorToWsaError(const gaiError: Integer): Integer;
  396. //We want to load this library only after loading Winsock and unload immediately
  397. //before unloading Winsock.
  398. procedure InitLibrary;
  399. procedure CloseLibrary;
  400. implementation
  401. uses
  402. SysUtils;
  403. var
  404. hWship6Dll : TIdLibHandle = IdNilHandle; // Wship6.dll handle
  405. //Use this instead of hWship6Dll because this will point to the correct lib.
  406. hProcHandle : TIdLibHandle = IdNilHandle;
  407. {$IFNDEF WINCE}
  408. hfwpuclntDll : TIdLibHandle = IdNilHandle;
  409. {$ENDIF}
  410. function gaiErrorToWsaError(const gaiError: Integer): Integer;
  411. begin
  412. case gaiError of
  413. GIA_EAI_ADDRFAMILY: Result := 0; // TODO: find a decent error for here
  414. GIA_EAI_AGAIN: Result := WSATRY_AGAIN;
  415. GIA_EAI_BADFLAGS: Result := WSAEINVAL;
  416. GIA_EAI_FAIL: Result := WSANO_RECOVERY;
  417. GIA_EAI_FAMILY: Result := WSAEAFNOSUPPORT;
  418. GIA_EAI_MEMORY: Result := WSA_NOT_ENOUGH_MEMORY;
  419. GIA_EAI_NODATA: Result := WSANO_DATA;
  420. GIA_EAI_NONAME: Result := WSAHOST_NOT_FOUND;
  421. GIA_EAI_SERVICE: Result := WSATYPE_NOT_FOUND;
  422. GIA_EAI_SOCKTYPE: Result := WSAESOCKTNOSUPPORT;
  423. GIA_EAI_SYSTEM:
  424. begin
  425. {$IFNDEF USE_NORETURN}
  426. Result := 0; // avoid warning
  427. {$ENDIF}
  428. IndyRaiseLastError;
  429. end;
  430. else
  431. Result := gaiError;
  432. end;
  433. end;
  434. procedure CloseLibrary;
  435. var
  436. h : TIdLibHandle;
  437. begin
  438. h := InterlockedExchangeTLibHandle(hWship6Dll, IdNilHandle);
  439. if h <> IdNilHandle then begin
  440. FreeLibrary(h);
  441. end;
  442. {$IFNDEF WINCE}
  443. h := InterlockedExchangeTLibHandle(hfwpuclntDll, IdNilHandle);
  444. if h <> IdNilHandle then begin
  445. FreeLibrary(h);
  446. end;
  447. {$ENDIF}
  448. {$I IdSymbolDeprecatedOff.inc}
  449. GIdIPv6FuncsAvailable := False;
  450. {$I IdSymbolDeprecatedOn.inc}
  451. {$IFDEF WINCE_UNICODE}
  452. getaddrinfoCE := nil;
  453. getnameinfoCE := nil;
  454. freeaddrinfoCE := nil;
  455. {$ENDIF}
  456. getaddrinfo := nil;
  457. getnameinfo := nil;
  458. freeaddrinfo := nil;
  459. {$IFNDEF WINCE}
  460. inet_pton := nil;
  461. inet_ntop := nil;
  462. GetAddrInfoEx := nil;
  463. SetAddrInfoEx := nil;
  464. FreeAddrInfoEx := nil;
  465. WSASetSocketPeerTargetName := nil;
  466. WSADeleteSocketPeerTargetName := nil;
  467. WSAImpersonateSocketPeer := nil;
  468. WSAQuerySocketSecurity := nil;
  469. WSARevertImpersonation := nil;
  470. {$ENDIF}
  471. end;
  472. {$IFDEF FPC} //{$IFDEF STRING_IS_ANSI}
  473. {$IFDEF UNICODE}
  474. // FreePascal does not have PWideChar overloads of these functions
  475. function StrComp(const Str1, Str2: PWideChar): Integer; overload;
  476. var
  477. P1, P2: PWideChar;
  478. begin
  479. P1 := Str1;
  480. P2 := Str2;
  481. while True do
  482. begin
  483. if (P1^ <> P2^) or (P1^ = #0) then
  484. begin
  485. Result := Ord(P1^) - Ord(P2^);
  486. Exit;
  487. end;
  488. Inc(P1);
  489. Inc(P2);
  490. end;
  491. Result := 0;
  492. end;
  493. function StrScan(const Str: PWideChar; Chr: WideChar): PWideChar; overload;
  494. begin
  495. Result := Str;
  496. while Result^ <> #0 do
  497. begin
  498. if Result^ = Chr then begin
  499. Exit;
  500. end;
  501. Inc(Result);
  502. end;
  503. if Chr <> #0 then begin
  504. Result := nil;
  505. end;
  506. end;
  507. {$ENDIF}
  508. {$ENDIF}
  509. // The IPv6 functions were added to the Ws2_32.dll on Windows XP and later.
  510. // To execute an application that uses these functions on earlier versions of
  511. // Windows, the functions are defined as inline functions in the Wspiapi.h file.
  512. // At runtime, the functions are implemented in such a way that if the Ws2_32.dll
  513. // or the Wship6.dll (the file containing the functions in the IPv6 Technology
  514. // Preview for Windows 2000) does not include them, then versions are implemented
  515. // inline based on code in the Wspiapi.h header file. This inline code will be
  516. // used on older Windows platforms that do not natively support the functions.
  517. // RLebeau: Wspiapi.h only defines Ansi versions of the legacy functions, but we
  518. // need to handle Unicode as well...
  519. function WspiapiMalloc(tSize: size_t): Pointer;
  520. begin
  521. try
  522. GetMem(Result, tSize);
  523. ZeroMemory(Result, tSize);
  524. except
  525. Result := nil;
  526. end;
  527. end;
  528. procedure WspiapiFree(p: Pointer);
  529. begin
  530. FreeMem(p);
  531. end;
  532. procedure WspiapiSwap(var a, b, c: PIdPlatformChar);
  533. {$IFDEF USE_INLINE}inline;{$ENDIF}
  534. begin
  535. c := a;
  536. a := b;
  537. b := c;
  538. end;
  539. function WspiapiStrdup(const pszString: PIdPlatformChar): PIdPlatformChar; stdcall;
  540. var
  541. pszMemory: PIdPlatformChar;
  542. cchMemory: size_t;
  543. begin
  544. if pszString = nil then begin
  545. Result := nil;
  546. Exit;
  547. end;
  548. cchMemory := StrLen(pszString) + 1;
  549. pszMemory := PIdPlatformChar(WspiapiMalloc(cchMemory * SizeOf(TIdPlatformChar)));
  550. if pszMemory = nil then begin
  551. Result := nil;
  552. Exit;
  553. end;
  554. StrLCopy(pszMemory, pszString, cchMemory);
  555. Result := pszMemory;
  556. end;
  557. function WspiapiParseV4Address(const pszAddress: PIdPlatformChar; var pdwAddress: DWORD): BOOL; stdcall;
  558. var
  559. dwAddress: DWORD;
  560. pcNext: PIdPlatformChar;
  561. iCount: Integer;
  562. {$IFDEF USE_MARSHALLED_PTRS}
  563. M: TMarshaller;
  564. {$ENDIF}
  565. begin
  566. iCount := 0;
  567. // ensure there are 3 '.' (periods)
  568. pcNext := pszAddress;
  569. while pcNext^ <> TIdPlatformChar(0) do begin
  570. if pcNext^ = '.' then begin
  571. Inc(iCount);
  572. end;
  573. Inc(pcNext);
  574. end;
  575. if iCount <> 3 then begin
  576. Result := FALSE;
  577. Exit;
  578. end;
  579. // return an error if dwAddress is INADDR_NONE (255.255.255.255)
  580. // since this is never a valid argument to getaddrinfo.
  581. dwAddress := inet_addr(
  582. {$IFDEF USE_MARSHALLED_PTRS}
  583. M.AsAnsi(pszAddress).ToPointer
  584. {$ELSE}
  585. {$IFDEF UNICODE}
  586. PIdAnsiChar(AnsiString(pszAddress)) // explicit convert to Ansi
  587. {$ELSE}
  588. pszAddress
  589. {$ENDIF}
  590. {$ENDIF}
  591. );
  592. if dwAddress = INADDR_NONE then begin
  593. Result := FALSE;
  594. Exit;
  595. end;
  596. pdwAddress := dwAddress;
  597. Result := TRUE;
  598. end;
  599. function WspiapiNewAddrInfo(iSocketType, iProtocol: Integer; wPort: WORD; dwAddress: DWORD): {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}; stdcall;
  600. var
  601. ptNew: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  602. ptAddress: PSockAddrIn;
  603. begin
  604. // allocate a new addrinfo structure.
  605. {$IFDEF UNICODE}
  606. ptNew := PaddrinfoW(WspiapiMalloc(SizeOf(addrinfoW)));
  607. {$ELSE}
  608. ptNew := Paddrinfo(WspiapiMalloc(SizeOf(addrinfo)));
  609. {$ENDIF}
  610. if ptNew = nil then begin
  611. Result := nil;
  612. Exit;
  613. end;
  614. ptAddress := PSockAddrIn(WspiapiMalloc(SizeOf(sockaddr_in)));
  615. if ptAddress = nil then begin
  616. WspiapiFree(ptNew);
  617. Result := nil;
  618. Exit;
  619. end;
  620. ptAddress^.sin_family := AF_INET;
  621. ptAddress^.sin_port := wPort;
  622. ptAddress^.sin_addr.s_addr := dwAddress;
  623. // fill in the fields...
  624. ptNew^.ai_family := PF_INET;
  625. ptNew^.ai_socktype := iSocketType;
  626. ptNew^.ai_protocol := iProtocol;
  627. ptNew^.ai_addrlen := SizeOf(sockaddr_in);
  628. ptNew^.ai_addr := Psockaddr(ptAddress);
  629. Result := ptNew;
  630. end;
  631. function WspiapiQueryDNS(const pszNodeName: PIdPlatformChar; iSocketType, iProtocol: Integer;
  632. wPort: WORD; pszAlias: PIdPlatformChar; var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  633. var
  634. pptNext: {$IFDEF UNICODE}PPaddrinfoW{$ELSE}PPaddrinfo{$ENDIF};
  635. ptHost: Phostent;
  636. ppAddresses: ^PInAddr;
  637. {$IFDEF USE_MARSHALLED_PTRS}
  638. M: TMarshaller;
  639. {$ENDIF}
  640. begin
  641. pptNext := @pptResult;
  642. pptNext^ := nil;
  643. pszAlias^ := TIdPlatformChar(0);
  644. ptHost := gethostbyname(
  645. {$IFDEF USE_MARSHALLED_PTRS}
  646. M.AsAnsi(pszNodeName).ToPointer
  647. {$ELSE}
  648. {$IFDEF UNICODE}
  649. PIdAnsiChar(AnsiString(pszNodeName)) // explicit convert to Ansi
  650. {$ELSE}
  651. pszNodeName
  652. {$ENDIF}
  653. {$ENDIF}
  654. );
  655. if ptHost <> nil then begin
  656. if (ptHost^.h_addrtype = AF_INET) and (ptHost^.h_length = SizeOf(in_addr)) then begin
  657. ppAddresses := Pointer(ptHost^.h_address_list);
  658. while ppAddresses^ <> nil do begin
  659. // create an addrinfo structure...
  660. pptNext^ := WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, ppAddresses^^.s_addr);
  661. if pptNext^ = nil then begin
  662. Result := EAI_MEMORY;
  663. Exit;
  664. end;
  665. pptNext := @((pptNext^)^.ai_next);
  666. Inc(ppAddresses);
  667. end;
  668. end;
  669. // pick up the canonical name.
  670. StrLCopy(pszAlias,
  671. {$IFNDEF UNICODE}
  672. ptHost^.h_name
  673. {$ELSE}
  674. PIdPlatformChar(TIdPlatformString(ptHost^.h_name))
  675. {$ENDIF}
  676. , NI_MAXHOST);
  677. Result := 0;
  678. Exit;
  679. end;
  680. case WSAGetLastError() of
  681. WSAHOST_NOT_FOUND: Result := EAI_NONAME;
  682. WSATRY_AGAIN: Result := EAI_AGAIN;
  683. WSANO_RECOVERY: Result := EAI_FAIL;
  684. WSANO_DATA: Result := EAI_NODATA;
  685. else
  686. Result := EAI_NONAME;
  687. end;
  688. end;
  689. function WspiapiLookupNode(const pszNodeName: PIdPlatformChar; iSocketType: Integer;
  690. iProtocol: Integer; wPort: WORD; bAI_CANONNAME: BOOL; var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  691. var
  692. iError: Integer;
  693. iAliasCount: Integer;
  694. szFQDN1: array[0..NI_MAXHOST-1] of TIdPlatformChar;
  695. szFQDN2: array[0..NI_MAXHOST-1] of TIdPlatformChar;
  696. pszName: PIdPlatformChar;
  697. pszAlias: PIdPlatformChar;
  698. pszScratch: PIdPlatformChar;
  699. begin
  700. iAliasCount := 0;
  701. ZeroMemory(@szFQDN1, SizeOf(szFQDN1));
  702. ZeroMemory(@szFQDN2, SizeOf(szFQDN2));
  703. pszName := @szFQDN1[0];
  704. pszAlias := @szFQDN2[0];
  705. pszScratch := nil;
  706. StrLCopy(pszName, pszNodeName, NI_MAXHOST);
  707. repeat
  708. iError := WspiapiQueryDNS(pszNodeName, iSocketType, iProtocol, wPort, pszAlias, pptResult);
  709. if iError <> 0 then begin
  710. Break;
  711. end;
  712. // if we found addresses, then we are done.
  713. if pptResult <> nil then begin
  714. Break;
  715. end;
  716. // stop infinite loops due to DNS misconfiguration. there appears
  717. // to be no particular recommended limit in RFCs 1034 and 1035.
  718. if (StrLen(pszAlias) = 0) or (StrComp(pszName, pszAlias) = 0) then begin
  719. iError := EAI_FAIL;
  720. Break;
  721. end;
  722. Inc(iAliasCount);
  723. if iAliasCount = 16 then begin
  724. iError := EAI_FAIL;
  725. Break;
  726. end;
  727. // there was a new CNAME, look again.
  728. WspiapiSwap(pszName, pszAlias, pszScratch);
  729. until False;
  730. if (iError = 0) and bAI_CANONNAME then begin
  731. pptResult^.ai_canonname := WspiapiStrdup(pszAlias);
  732. if pptResult^.ai_canonname = nil then begin
  733. iError := EAI_MEMORY;
  734. end;
  735. end;
  736. Result := iError;
  737. end;
  738. function WspiapiClone(wPort: WORD; ptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  739. var
  740. ptNext, ptNew: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  741. begin
  742. ptNext := ptResult;
  743. while ptNext <> nil do begin
  744. // create an addrinfo structure...
  745. ptNew := WspiapiNewAddrInfo(SOCK_DGRAM, ptNext^.ai_protocol, wPort, PSockAddrIn(ptNext^.ai_addr)^.sin_addr.s_addr);
  746. if ptNew = nil then begin
  747. Break;
  748. end;
  749. // link the cloned addrinfo
  750. ptNew^.ai_next := ptNext^.ai_next;
  751. ptNext^.ai_next := ptNew;
  752. ptNext := ptNew^.ai_next;
  753. end;
  754. if ptNext <> nil then begin
  755. Result := EAI_MEMORY;
  756. Exit;
  757. end;
  758. Result := 0;
  759. end;
  760. procedure WspiapiLegacyFreeAddrInfo(ptHead: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}); stdcall;
  761. var
  762. ptNext: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  763. begin
  764. ptNext := ptHead;
  765. while ptNext <> nil do
  766. begin
  767. if ptNext^.ai_canonname <> nil then begin
  768. WspiapiFree(ptNext^.ai_canonname);
  769. end;
  770. if ptNext^.ai_addr <> nil then begin
  771. WspiapiFree(ptNext^.ai_addr);
  772. end;
  773. ptHead := ptNext^.ai_next;
  774. WspiapiFree(ptNext);
  775. ptNext := ptHead;
  776. end;
  777. end;
  778. {$IFNDEF HAS_TryStrToInt}
  779. // TODO: use the implementation already in IdGlobalProtocols...
  780. function TryStrToInt(const S: string; out Value: Integer): Boolean;
  781. {$IFDEF USE_INLINE}inline;{$ENDIF}
  782. var
  783. E: Integer;
  784. begin
  785. Val(S, Value, E);
  786. Result := E = 0;
  787. end;
  788. {$ENDIF}
  789. function WspiapiLegacyGetAddrInfo(const pszNodeName: PIdPlatformChar; const pszServiceName: PIdPlatformChar;
  790. const ptHints: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  791. var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  792. var
  793. iError: Integer;
  794. iFlags: Integer;
  795. iSocketType: Integer;
  796. iProtocol: Integer;
  797. wPort: WORD;
  798. iTmp: Integer;
  799. dwAddress: DWORD;
  800. ptService: Pservent;
  801. bClone: BOOL;
  802. wTcpPort: WORD;
  803. wUdpPort: WORD;
  804. {$IFDEF USE_MARSHALLED_PTRS}
  805. M: TMarshaller;
  806. {$ENDIF}
  807. begin
  808. iError := 0;
  809. iFlags := 0;
  810. iSocketType := 0;
  811. iProtocol := 0;
  812. wPort := 0;
  813. dwAddress := 0;
  814. bClone := FALSE;
  815. wTcpPort := 0;
  816. wUdpPort := 0;
  817. // initialize pptResult with default return value.
  818. pptResult := nil;
  819. ////////////////////////////////////////
  820. // validate arguments...
  821. //
  822. // both the node name and the service name can't be NULL.
  823. if (pszNodeName = nil) and (pszServiceName = nil) then begin
  824. Result := EAI_NONAME;
  825. Exit;
  826. end;
  827. // validate hints.
  828. if ptHints <> nil then
  829. begin
  830. // all members other than ai_flags, ai_family, ai_socktype
  831. // and ai_protocol must be zero or a null pointer.
  832. if (ptHints^.ai_addrlen <> 0) or
  833. (ptHints^.ai_canonname <> nil) or
  834. (ptHints^.ai_addr <> nil) or
  835. (ptHints^.ai_next <> nil) then
  836. begin
  837. Result := EAI_FAIL;
  838. Exit;
  839. end;
  840. // the spec has the "bad flags" error code, so presumably we
  841. // should check something here. insisting that there aren't
  842. // any unspecified flags set would break forward compatibility,
  843. // however. so we just check for non-sensical combinations.
  844. //
  845. // we cannot come up with a canonical name given a null node name.
  846. iFlags := ptHints^.ai_flags;
  847. if ((iFlags and AI_CANONNAME) <> 0) and (pszNodeName = nil) then begin
  848. Result := EAI_BADFLAGS;
  849. Exit;
  850. end;
  851. // we only support a limited number of protocol families.
  852. if (ptHints^.ai_family <> PF_UNSPEC) and (ptHints^.ai_family <> PF_INET) then begin
  853. Result := EAI_FAMILY;
  854. Exit;
  855. end;
  856. // we only support only these socket types.
  857. iSocketType := ptHints^.ai_socktype;
  858. if (iSocketType <> 0) and
  859. (iSocketType <> SOCK_STREAM) and
  860. (iSocketType <> SOCK_DGRAM) and
  861. (iSocketType <> SOCK_RAW) then
  862. begin
  863. Result := EAI_SOCKTYPE;
  864. Exit;
  865. end;
  866. // REVIEW: What if ai_socktype and ai_protocol are at odds?
  867. iProtocol := ptHints^.ai_protocol;
  868. end;
  869. ////////////////////////////////////////
  870. // do service lookup...
  871. if pszServiceName <> nil then begin
  872. if TryStrToInt(pszServiceName, iTmp) and (iTmp >= 0) then begin
  873. wPort := htons(WORD(iTmp));
  874. //wTcpPort := wPort; // never used
  875. wUdpPort := wPort;
  876. if iSocketType = 0 then begin
  877. bClone := TRUE;
  878. iSocketType := SOCK_STREAM;
  879. end;
  880. end else
  881. begin
  882. if (iSocketType = 0) or (iSocketType = SOCK_DGRAM) then begin
  883. ptService := getservbyname(
  884. {$IFDEF USE_MARSHALLED_PTRS}
  885. M.AsAnsi(pszServiceName).ToPointer
  886. {$ELSE}
  887. {$IFDEF UNICODE}
  888. PIdAnsiChar(AnsiString(pszServiceName)) // explicit convert to Ansi
  889. {$ELSE}
  890. pszServiceName
  891. {$ENDIF}
  892. {$ENDIF}
  893. , 'udp'); {do not localize}
  894. if ptService <> nil then begin
  895. wPort := ptService^.s_port;
  896. wUdpPort := wPort;
  897. end;
  898. end;
  899. if (iSocketType = 0) or (iSocketType = SOCK_STREAM) then begin
  900. ptService := getservbyname(
  901. {$IFDEF USE_MARSHALLED_PTRS}
  902. M.AsAnsi(pszServiceName).ToPointer
  903. {$ELSE}
  904. {$IFDEF UNICODE}
  905. PIdAnsiChar(AnsiString(pszServiceName)) // explicit convert to Ansi
  906. {$ELSE}
  907. pszServiceName
  908. {$ENDIF}
  909. {$ENDIF}
  910. , 'tcp'); {do not localize}
  911. if ptService <> nil then begin
  912. wPort := ptService^.s_port;
  913. wTcpPort := wPort;
  914. end;
  915. end;
  916. // assumes 0 is an invalid service port...
  917. if wPort = 0 then begin
  918. Result := iif(iSocketType <> 0, EAI_SERVICE, EAI_NONAME);
  919. Exit;
  920. end;
  921. if iSocketType = 0 then begin
  922. // if both tcp and udp, process tcp now & clone udp later.
  923. iSocketType := iif(wTcpPort <> 0, SOCK_STREAM, SOCK_DGRAM);
  924. bClone := (wTcpPort <> 0) and (wUdpPort <> 0);
  925. end;
  926. end;
  927. end;
  928. ////////////////////////////////////////
  929. // do node name lookup...
  930. // if we weren't given a node name,
  931. // return the wildcard or loopback address (depending on AI_PASSIVE).
  932. //
  933. // if we have a numeric host address string,
  934. // return the binary address.
  935. //
  936. if ((pszNodeName = nil) or WspiapiParseV4Address(pszNodeName, dwAddress)) then begin
  937. if pszNodeName = nil then begin
  938. dwAddress := htonl(iif((iFlags and AI_PASSIVE) <> 0, INADDR_ANY, INADDR_LOOPBACK));
  939. end;
  940. // create an addrinfo structure...
  941. pptResult := WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
  942. if pptResult = nil then begin
  943. iError := EAI_MEMORY;
  944. end;
  945. if (iError = 0) and (pszNodeName <> nil) then begin
  946. // implementation specific behavior: set AI_NUMERICHOST
  947. // to indicate that we got a numeric host address string.
  948. pptResult^.ai_flags := pptResult^.ai_flags or AI_NUMERICHOST;
  949. // return the numeric address string as the canonical name
  950. if (iFlags and AI_CANONNAME) <> 0 then begin
  951. pptResult^.ai_canonname := WspiapiStrdup(
  952. {$IFNDEF UNICODE}
  953. inet_ntoa(PInAddr(@dwAddress)^)
  954. {$ELSE}
  955. PWideChar(TIdUnicodeString(inet_ntoa(PInAddr(@dwAddress)^)))
  956. {$ENDIF}
  957. );
  958. if pptResult^.ai_canonname = nil then begin
  959. iError := EAI_MEMORY;
  960. end;
  961. end;
  962. end;
  963. end
  964. // if we do not have a numeric host address string and
  965. // AI_NUMERICHOST flag is set, return an error!
  966. else if ((iFlags and AI_NUMERICHOST) <> 0) then begin
  967. iError := EAI_NONAME;
  968. end
  969. // since we have a non-numeric node name,
  970. // we have to do a regular node name lookup.
  971. else begin
  972. iError := WspiapiLookupNode(pszNodeName, iSocketType, iProtocol, wPort, (iFlags and AI_CANONNAME) <> 0, pptResult);
  973. end;
  974. if (iError = 0) and bClone then begin
  975. iError := WspiapiClone(wUdpPort, pptResult);
  976. end;
  977. if iError <> 0 then begin
  978. WspiapiLegacyFreeAddrInfo(pptResult);
  979. pptResult := nil;
  980. end;
  981. Result := iError;
  982. end;
  983. function iif(ATest: Boolean; const ATrue, AFalse: PIdAnsiChar): PIdAnsiChar;
  984. {$IFDEF USE_INLINE}inline;{$ENDIF}
  985. begin
  986. if ATest then begin
  987. Result := ATrue;
  988. end else begin
  989. Result := AFalse;
  990. end;
  991. end;
  992. function WspiapiLegacyGetNameInfo(ptSocketAddress: Psockaddr;
  993. tSocketLength: u_int; pszNodeName: PIdPlatformChar; tNodeLength: size_t;
  994. pszServiceName: PIdPlatformChar; tServiceLength: size_t; iFlags: Integer): Integer; stdcall;
  995. var
  996. ptService: Pservent;
  997. wPort: WORD;
  998. szBuffer: array[0..5] of TIdPlatformChar;
  999. pszService: PIdPlatformChar;
  1000. ptHost: Phostent;
  1001. tAddress: in_addr;
  1002. pszNode: PIdPlatformChar;
  1003. pc: PIdPlatformChar;
  1004. {$IFDEF UNICODE}
  1005. tmpService: TIdUnicodeString;
  1006. tmpNode: TIdUnicodeString;
  1007. {$ENDIF}
  1008. begin
  1009. StrCopy(szBuffer, '65535');
  1010. pszService := szBuffer;
  1011. // sanity check ptSocketAddress and tSocketLength.
  1012. if (ptSocketAddress = nil) or (tSocketLength < SizeOf(sockaddr)) then begin
  1013. Result := EAI_FAIL;
  1014. Exit;
  1015. end;
  1016. if ptSocketAddress^.sa_family <> AF_INET then begin
  1017. Result := EAI_FAMILY;
  1018. Exit;
  1019. end;
  1020. if tSocketLength < SizeOf(sockaddr_in) then begin
  1021. Result := EAI_FAIL;
  1022. Exit;
  1023. end;
  1024. if (not ((pszNodeName <> nil) and (tNodeLength > 0))) and (not ((pszServiceName <> nil) and (tServiceLength > 0))) then begin
  1025. Result := EAI_NONAME;
  1026. Exit;
  1027. end;
  1028. // the draft has the "bad flags" error code, so presumably we
  1029. // should check something here. insisting that there aren't
  1030. // any unspecified flags set would break forward compatibility,
  1031. // however. so we just check for non-sensical combinations.
  1032. if ((iFlags and NI_NUMERICHOST) <> 0) and ((iFlags and NI_NAMEREQD) <> 0) then begin
  1033. Result := EAI_BADFLAGS;
  1034. Exit;
  1035. end;
  1036. // translate the port to a service name (if requested).
  1037. if (pszServiceName <> nil) and (tServiceLength > 0) then begin
  1038. wPort := PSockAddrIn(ptSocketAddress)^.sin_port;
  1039. if (iFlags and NI_NUMERICSERV) <> 0 then begin
  1040. // return numeric form of the address.
  1041. StrPLCopy(szBuffer, IntToStr(ntohs(wPort)), Length(szBuffer));
  1042. end else
  1043. begin
  1044. // return service name corresponding to port.
  1045. ptService := getservbyport(wPort, iif((iFlags and NI_DGRAM) <> 0, 'udp', nil));
  1046. if (ptService <> nil) and (ptService^.s_name <> nil) then begin
  1047. // lookup successful.
  1048. {$IFNDEF UNICODE}
  1049. pszService := ptService^.s_name;
  1050. {$ELSE}
  1051. tmpService := TIdUnicodeString(ptService^.s_name);
  1052. pszService := PWideChar(tmpService);
  1053. {$ENDIF}
  1054. end else begin
  1055. // DRAFT: return numeric form of the port!
  1056. StrPLCopy(szBuffer, IntToStr(ntohs(wPort)), Length(szBuffer));
  1057. end;
  1058. end;
  1059. if tServiceLength > size_t(StrLen(pszService)) then begin
  1060. StrLCopy(pszServiceName, pszService, tServiceLength);
  1061. end else begin
  1062. Result := EAI_FAIL;
  1063. Exit;
  1064. end;
  1065. end;
  1066. // translate the address to a node name (if requested).
  1067. if (pszNodeName <> nil) and (tNodeLength > 0) then begin
  1068. // this is the IPv4-only version, so we have an IPv4 address.
  1069. tAddress := PSockAddrIn(ptSocketAddress)^.sin_addr;
  1070. if (iFlags and NI_NUMERICHOST) <> 0 then begin
  1071. // return numeric form of the address.
  1072. {$IFNDEF UNICODE}
  1073. pszNode := inet_ntoa(tAddress);
  1074. {$ELSE}
  1075. tmpNode := TIdUnicodeString(inet_ntoa(tAddress));
  1076. pszNode := PWideChar(tmpNode);
  1077. {$ENDIF}
  1078. end else
  1079. begin
  1080. // return node name corresponding to address.
  1081. ptHost := gethostbyaddr(PIdAnsiChar(@tAddress), SizeOf(in_addr), AF_INET);
  1082. if (ptHost <> nil) and (ptHost^.h_name <> nil) then begin
  1083. // DNS lookup successful.
  1084. // stop copying at a "." if NI_NOFQDN is specified.
  1085. {$IFNDEF UNICODE}
  1086. pszNode := ptHost^.h_name;
  1087. {$ELSE}
  1088. tmpNode := TIdUnicodeString(ptHost^.h_name);
  1089. pszNode := PWideChar(tmpNode);
  1090. {$ENDIF}
  1091. if (iFlags and NI_NOFQDN) <> 0 then begin
  1092. pc := StrScan(pszNode, '.');
  1093. if pc <> nil then begin
  1094. pc^ := TIdPlatformChar(0);
  1095. end;
  1096. end;
  1097. end else
  1098. begin
  1099. // DNS lookup failed. return numeric form of the address.
  1100. if (iFlags and NI_NAMEREQD) <> 0 then begin
  1101. case WSAGetLastError() of
  1102. WSAHOST_NOT_FOUND: Result := EAI_NONAME;
  1103. WSATRY_AGAIN: Result := EAI_AGAIN;
  1104. WSANO_RECOVERY: Result := EAI_FAIL;
  1105. else
  1106. Result := EAI_NONAME;
  1107. end;
  1108. Exit;
  1109. end else begin
  1110. {$IFNDEF UNICODE}
  1111. pszNode := inet_ntoa(tAddress);
  1112. {$ELSE}
  1113. tmpNode := TIdUnicodeString(inet_ntoa(tAddress));
  1114. pszNode := PWideChar(tmpNode);
  1115. {$ENDIF}
  1116. end;
  1117. end;
  1118. end;
  1119. if tNodeLength > size_t(StrLen(pszNode)) then begin
  1120. StrLCopy(pszNodeName, pszNode, tNodeLength);
  1121. end else begin
  1122. Result := EAI_FAIL;
  1123. Exit;
  1124. end;
  1125. end;
  1126. Result := 0;
  1127. end;
  1128. {$IFDEF WINCE_UNICODE}
  1129. function IndyStrdupAToW(const pszString: PIdAnsiChar): PWideChar;
  1130. var
  1131. szStr: TIdUnicodeString;
  1132. pszMemory: PWideChar;
  1133. cchMemory: size_t;
  1134. begin
  1135. if pszString = nil then begin
  1136. Result := nil;
  1137. Exit;
  1138. end;
  1139. szStr := TIdUnicodeString(pszString);
  1140. cchMemory := Length(szStr) + 1;
  1141. pszMemory := PWideChar(WspiapiMalloc(cchMemory * SizeOf(WideChar)));
  1142. if pszMemory = nil then begin
  1143. Result := nil;
  1144. Exit;
  1145. end;
  1146. StrLCopy(pszMemory, PWideChar(szStr), cchMemory);
  1147. Result := pszMemory;
  1148. end;
  1149. procedure IndyFreeAddrInfoW(ptHead: PaddrinfoW); stdcall;
  1150. var
  1151. ptNext: PaddrinfoW;
  1152. begin
  1153. ptNext := ptHead;
  1154. while ptNext <> nil do
  1155. begin
  1156. if ptNext^.ai_canonname <> nil then begin
  1157. WspiapiFree(ptNext^.ai_canonname);
  1158. end;
  1159. if ptNext^.ai_addr <> nil then begin
  1160. WspiapiFree(ptNext^.ai_addr);
  1161. end;
  1162. ptHead := ptNext^.ai_next;
  1163. WspiapiFree(ptNext);
  1164. ptNext := ptHead;
  1165. end;
  1166. end;
  1167. function IndyAddrInfoConvert(AddrInfo: Paddrinfo): PaddrinfoW;
  1168. var
  1169. ptNew: PaddrinfoW;
  1170. ptAddress: Pointer;
  1171. begin
  1172. Result := nil;
  1173. if AddrInfo = nil then begin
  1174. Exit;
  1175. end;
  1176. // allocate a new addrinfo structure.
  1177. ptNew := PaddrinfoW(WspiapiMalloc(SizeOf(addrinfoW)));
  1178. if ptNew = nil then begin
  1179. WspiapiFree(ptNew);
  1180. Exit;
  1181. end;
  1182. ptAddress := WspiapiMalloc(AddrInfo^.ai_addrlen);
  1183. if ptAddress = nil then begin
  1184. WspiapiFree(ptNew);
  1185. Exit;
  1186. end;
  1187. Move(AddrInfo^.ai_addr^, ptAddress^, AddrInfo^.ai_addrlen);
  1188. // fill in the fields...
  1189. ptNew^.ai_flags := AddrInfo^.ai_flags;
  1190. ptNew^.ai_family := AddrInfo^.ai_family;
  1191. ptNew^.ai_socktype := AddrInfo^.ai_socktype;
  1192. ptNew^.ai_protocol := AddrInfo^.ai_protocol;
  1193. ptNew^.ai_addrlen := AddrInfo^.ai_addrlen;
  1194. ptNew^.ai_canonname := nil;
  1195. ptNew^.ai_addr := Psockaddr(ptAddress);
  1196. ptNew^.ai_next := nil;
  1197. if AddrInfo^.ai_canonname <> nil then begin
  1198. ptNew^.ai_canonname := IndyStrdupAToW(AddrInfo^.ai_canonname);
  1199. if ptNew^.ai_canonname = nil then begin
  1200. IndyFreeAddrInfoW(ptNew);
  1201. Exit;
  1202. end;
  1203. end;
  1204. if AddrInfo^.ai_next <> nil then begin
  1205. ptNew^.ai_next := IndyAddrInfoConvert(AddrInfo^.ai_next);
  1206. if ptNew^.ai_next = nil then begin
  1207. IndyFreeAddrInfoW(ptNew);
  1208. Exit;
  1209. end;
  1210. end;
  1211. Result := ptNew;
  1212. end;
  1213. function IndyGetAddrInfoW(const pszNodeName: PWideChar; const pszServiceName: PWideChar;
  1214. const ptHints: PaddrinfoW; var pptResult: PaddrinfoW): Integer; stdcall;
  1215. var
  1216. LNodeName: AnsiString;
  1217. LPNodeName: PIdAnsiChar;
  1218. LServiceName: AnsiString;
  1219. LPServiceName: PIdAnsiChar;
  1220. LHints: addrinfo;
  1221. LPHints: Paddrinfo;
  1222. LResult: Paddrinfo;
  1223. begin
  1224. // initialize pptResult with default return value.
  1225. pptResult := nil;
  1226. if pszNodeName <> nil then begin
  1227. LNodeName := AnsiString(pszNodeName);
  1228. LPNodeName := PIdAnsiChar(LNodeName);
  1229. end else begin
  1230. LPNodeName := nil;
  1231. end;
  1232. if pszServiceName <> nil then begin
  1233. LServiceName := AnsiString(pszServiceName);
  1234. LPServiceName := PIdAnsiChar(LServiceName);
  1235. end else begin
  1236. LPServiceName := nil;
  1237. end;
  1238. if ptHints <> nil then begin
  1239. ZeroMemory(@LHints, SizeOf(LHints));
  1240. LHints.ai_flags := ptHints^.ai_flags;
  1241. LHints.ai_family := ptHints^.ai_family;
  1242. LHints.ai_socktype := ptHints^.ai_socktype;
  1243. LHints.ai_protocol := ptHints^.ai_protocol;
  1244. LPHints := @LHints;
  1245. end else begin
  1246. LPHints := nil;
  1247. end;
  1248. Result := getaddrinfoCE(LPNodeName, LPServiceName, LPHints, @LResult);
  1249. if Result = 0 then begin
  1250. try
  1251. pptResult := IndyAddrInfoConvert(LResult);
  1252. finally
  1253. freeaddrinfoCE(LResult);
  1254. end;
  1255. if pptResult = nil then begin
  1256. Result := EAI_MEMORY;
  1257. end;
  1258. end;
  1259. end;
  1260. function IndyGetNameInfoW(ptSocketAddress: Psockaddr; tSocketLength: u_int;
  1261. pszNodeName: PWideChar; tNodeLength: size_t; pszServiceName: PWideChar;
  1262. tServiceLength: size_t; iFlags: Integer): Integer; stdcall;
  1263. var
  1264. LHost: array[0..NI_MAXHOST-1] of TIdAnsiChar;
  1265. LPHost: PIdAnsiChar;
  1266. LHostLen: u_int;
  1267. LServ: array[0..NI_MAXSERV-1] of TIdAnsiChar;
  1268. LPServ: PIdAnsiChar;
  1269. LServLen: u_int;
  1270. begin
  1271. if pszNodeName <> nil then
  1272. begin
  1273. LPHost := @LHost[0];
  1274. LHostLen := Length(LHost);
  1275. end else begin
  1276. LPHost := nil;
  1277. LHostLen := 0;
  1278. end;
  1279. if pszServiceName <> nil then
  1280. begin
  1281. LPServ := @LServ[0];
  1282. LServLen := Length(LServ);
  1283. end else begin
  1284. LPServ := nil;
  1285. LServLen := 0;
  1286. end;
  1287. Result := getnameinfoCE(ptSocketAddress, tSocketLength, LPHost, LHostLen, LPServ, LServLen, iFlags);
  1288. if Result = 0 then begin
  1289. if pszNodeName <> nil then begin
  1290. StrPLCopy(pszNodeName, TIdUnicodeString(LPHost), tNodeLength);
  1291. end;
  1292. if pszServiceName <> nil then begin
  1293. StrPLCopy(pszServiceName, TIdUnicodeString(LPServ), tServiceLength);
  1294. end;
  1295. end;
  1296. end;
  1297. {$ENDIF}
  1298. procedure InitLibrary;
  1299. var
  1300. {$IFDEF WINCE_UNICODE}
  1301. gai: LPFN_GETADDRINFO;
  1302. gni: LPFN_GETNAMEINFO;
  1303. fai: LPFN_FREEADDRINFO;
  1304. {$ELSE}
  1305. gai: {$IFDEF UNICODE}LPFN_GETADDRINFOW{$ELSE}LPFN_GETADDRINFO{$ENDIF};
  1306. gni: {$IFDEF UNICODE}LPFN_GETNAMEINFOW{$ELSE}LPFN_GETNAMEINFO{$ENDIF};
  1307. fai: {$IFDEF UNICODE}LPFN_FREEADDRINFOW{$ELSE}LPFN_FREEADDRINFO{$ENDIF};
  1308. {$ENDIF}
  1309. begin
  1310. {
  1311. IMPORTANT!!!
  1312. I am doing things this way because the functions we want are probably in
  1313. the Winsock2 dll. If they are not there, only then do you actually want
  1314. to try the Wship6.dll. I know it's a mess but I found that the functions
  1315. may not load if they aren't in Wship6.dll (and they aren't there in some
  1316. versions of Windows).
  1317. hProcHandle provides a transparant way of managing the two possible library
  1318. locations. hWship6Dll is kept so we can unload the Wship6.dll if necessary.
  1319. }
  1320. //Winsock2 has to be loaded by IdWinsock first.
  1321. if not IdWinsock2.Winsock2Loaded then
  1322. begin
  1323. IdWinsock2.InitializeWinSock;
  1324. end;
  1325. hProcHandle := IdWinsock2.WinsockHandle;
  1326. gai := LoadLibFunction(hProcHandle, fn_getaddrinfo);
  1327. if not Assigned(gai) then
  1328. begin
  1329. hWship6Dll := SafeLoadLibrary(Wship6_dll);
  1330. hProcHandle := hWship6Dll;
  1331. gai := LoadLibFunction(hProcHandle, fn_getaddrinfo);
  1332. end;
  1333. if Assigned(gai) then
  1334. begin
  1335. gni := LoadLibFunction(hProcHandle, fn_getnameinfo);
  1336. if Assigned(gni) then
  1337. begin
  1338. fai := LoadLibFunction(hProcHandle, fn_freeaddrinfo);
  1339. if Assigned(fai) then
  1340. begin
  1341. {$IFDEF WINCE_UNICODE}
  1342. getaddrinfoCE := gai;
  1343. getnameinfoCE := gni;
  1344. freeaddrinfoCE := fai;
  1345. getaddrinfo := @IndyGetAddrInfoW;
  1346. getnameinfo := @IndyGetNameInfoW;
  1347. freeaddrinfo := @IndyFreeAddrInfoW;
  1348. {$ELSE}
  1349. getaddrinfo := gai;
  1350. getnameinfo := gni;
  1351. freeaddrinfo := fai;
  1352. {$ENDIF}
  1353. //Additional functions should be initialized here.
  1354. {$IFNDEF WINCE}
  1355. inet_pton := LoadLibFunction(hProcHandle, fn_inet_pton);
  1356. inet_ntop := LoadLibFunction(hProcHandle, fn_inet_ntop);
  1357. GetAddrInfoEx := LoadLibFunction(hProcHandle, fn_GetAddrInfoEx);
  1358. SetAddrInfoEx := LoadLibFunction(hProcHandle, fn_SetAddrInfoEx);
  1359. FreeAddrInfoEx := LoadLibFunction(hProcHandle, fn_FreeAddrInfoEx);
  1360. hfwpuclntDll := SafeLoadLibrary(fwpuclnt_dll);
  1361. if hfwpuclntDll <> IdNilHandle then
  1362. begin
  1363. WSASetSocketSecurity := LoadLibFunction(hfwpuclntDll, 'WSASetSocketSecurity'); {Do not localize}
  1364. WSAQuerySocketSecurity := LoadLibFunction(hfwpuclntDll, 'WSAQuerySocketSecurity'); {Do not localize}
  1365. WSASetSocketPeerTargetName := LoadLibFunction(hfwpuclntDll, 'WSASetSocketPeerTargetName'); {Do not localize}
  1366. WSADeleteSocketPeerTargetName := LoadLibFunction(hfwpuclntDll, 'WSADeleteSocketPeerTargetName'); {Do not localize}
  1367. WSAImpersonateSocketPeer := LoadLibFunction(hfwpuclntDll, 'WSAImpersonateSocketPeer'); {Do not localize}
  1368. WSARevertImpersonation := LoadLibFunction(hfwpuclntDll, 'WSARevertImpersonation'); {Do not localize}
  1369. end;
  1370. {$ENDIF}
  1371. Exit;
  1372. end;
  1373. end;
  1374. end;
  1375. CloseLibrary;
  1376. getaddrinfo := Addr(WspiapiLegacyGetAddrInfo);
  1377. getnameinfo := Addr(WspiapiLegacyGetNameInfo);
  1378. freeaddrinfo := Addr(WspiapiLegacyFreeAddrInfo);
  1379. {$I IdSymbolDeprecatedOff.inc}
  1380. GIdIPv6FuncsAvailable := True;
  1381. {$I IdSymbolDeprecatedOn.inc}
  1382. end;
  1383. initialization
  1384. finalization
  1385. CloseLibrary;
  1386. end.