IdWship6.pas 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545
  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. Result := 0; // avoid warning
  426. IndyRaiseLastError;
  427. end;
  428. else
  429. Result := gaiError;
  430. end;
  431. end;
  432. procedure CloseLibrary;
  433. var
  434. h : TIdLibHandle;
  435. begin
  436. h := InterlockedExchangeTLibHandle(hWship6Dll, IdNilHandle);
  437. if h <> IdNilHandle then begin
  438. FreeLibrary(h);
  439. end;
  440. {$IFNDEF WINCE}
  441. h := InterlockedExchangeTLibHandle(hfwpuclntDll, IdNilHandle);
  442. if h <> IdNilHandle then begin
  443. FreeLibrary(h);
  444. end;
  445. {$ENDIF}
  446. {$I IdSymbolDeprecatedOff.inc}
  447. GIdIPv6FuncsAvailable := False;
  448. {$I IdSymbolDeprecatedOn.inc}
  449. {$IFDEF WINCE_UNICODE}
  450. getaddrinfoCE := nil;
  451. getnameinfoCE := nil;
  452. freeaddrinfoCE := nil;
  453. {$ENDIF}
  454. getaddrinfo := nil;
  455. getnameinfo := nil;
  456. freeaddrinfo := nil;
  457. {$IFNDEF WINCE}
  458. inet_pton := nil;
  459. inet_ntop := nil;
  460. GetAddrInfoEx := nil;
  461. SetAddrInfoEx := nil;
  462. FreeAddrInfoEx := nil;
  463. WSASetSocketPeerTargetName := nil;
  464. WSADeleteSocketPeerTargetName := nil;
  465. WSAImpersonateSocketPeer := nil;
  466. WSAQuerySocketSecurity := nil;
  467. WSARevertImpersonation := nil;
  468. {$ENDIF}
  469. end;
  470. {$IFDEF FPC} //{$IFDEF STRING_IS_ANSI}
  471. {$IFDEF UNICODE}
  472. // FreePascal does not have PWideChar overloads of these functions
  473. function StrComp(const Str1, Str2: PWideChar): Integer; overload;
  474. var
  475. P1, P2: PWideChar;
  476. begin
  477. P1 := Str1;
  478. P2 := Str2;
  479. while True do
  480. begin
  481. if (P1^ <> P2^) or (P1^ = #0) then
  482. begin
  483. Result := Ord(P1^) - Ord(P2^);
  484. Exit;
  485. end;
  486. Inc(P1);
  487. Inc(P2);
  488. end;
  489. Result := 0;
  490. end;
  491. function StrScan(const Str: PWideChar; Chr: WideChar): PWideChar; overload;
  492. begin
  493. Result := Str;
  494. while Result^ <> #0 do
  495. begin
  496. if Result^ = Chr then begin
  497. Exit;
  498. end;
  499. Inc(Result);
  500. end;
  501. if Chr <> #0 then begin
  502. Result := nil;
  503. end;
  504. end;
  505. {$ENDIF}
  506. {$ENDIF}
  507. // The IPv6 functions were added to the Ws2_32.dll on Windows XP and later.
  508. // To execute an application that uses these functions on earlier versions of
  509. // Windows, the functions are defined as inline functions in the Wspiapi.h file.
  510. // At runtime, the functions are implemented in such a way that if the Ws2_32.dll
  511. // or the Wship6.dll (the file containing the functions in the IPv6 Technology
  512. // Preview for Windows 2000) does not include them, then versions are implemented
  513. // inline based on code in the Wspiapi.h header file. This inline code will be
  514. // used on older Windows platforms that do not natively support the functions.
  515. // RLebeau: Wspiapi.h only defines Ansi versions of the legacy functions, but we
  516. // need to handle Unicode as well...
  517. function WspiapiMalloc(tSize: size_t): Pointer;
  518. begin
  519. try
  520. GetMem(Result, tSize);
  521. ZeroMemory(Result, tSize);
  522. except
  523. Result := nil;
  524. end;
  525. end;
  526. procedure WspiapiFree(p: Pointer);
  527. begin
  528. FreeMem(p);
  529. end;
  530. procedure WspiapiSwap(var a, b, c: PIdPlatformChar);
  531. {$IFDEF USE_INLINE}inline;{$ENDIF}
  532. begin
  533. c := a;
  534. a := b;
  535. b := c;
  536. end;
  537. function WspiapiStrdup(const pszString: PIdPlatformChar): PIdPlatformChar; stdcall;
  538. var
  539. pszMemory: PIdPlatformChar;
  540. cchMemory: size_t;
  541. begin
  542. if pszString = nil then begin
  543. Result := nil;
  544. Exit;
  545. end;
  546. cchMemory := StrLen(pszString) + 1;
  547. pszMemory := PIdPlatformChar(WspiapiMalloc(cchMemory * SizeOf(TIdPlatformChar)));
  548. if pszMemory = nil then begin
  549. Result := nil;
  550. Exit;
  551. end;
  552. StrLCopy(pszMemory, pszString, cchMemory);
  553. Result := pszMemory;
  554. end;
  555. function WspiapiParseV4Address(const pszAddress: PIdPlatformChar; var pdwAddress: DWORD): BOOL; stdcall;
  556. var
  557. dwAddress: DWORD;
  558. pcNext: PIdPlatformChar;
  559. iCount: Integer;
  560. {$IFDEF USE_MARSHALLED_PTRS}
  561. M: TMarshaller;
  562. {$ENDIF}
  563. begin
  564. iCount := 0;
  565. // ensure there are 3 '.' (periods)
  566. pcNext := pszAddress;
  567. while pcNext^ <> TIdPlatformChar(0) do begin
  568. if pcNext^ = '.' then begin
  569. Inc(iCount);
  570. end;
  571. Inc(pcNext);
  572. end;
  573. if iCount <> 3 then begin
  574. Result := FALSE;
  575. Exit;
  576. end;
  577. // return an error if dwAddress is INADDR_NONE (255.255.255.255)
  578. // since this is never a valid argument to getaddrinfo.
  579. dwAddress := inet_addr(
  580. {$IFDEF USE_MARSHALLED_PTRS}
  581. M.AsAnsi(pszAddress).ToPointer
  582. {$ELSE}
  583. {$IFDEF UNICODE}
  584. PIdAnsiChar(AnsiString(pszAddress)) // explicit convert to Ansi
  585. {$ELSE}
  586. pszAddress
  587. {$ENDIF}
  588. {$ENDIF}
  589. );
  590. if dwAddress = INADDR_NONE then begin
  591. Result := FALSE;
  592. Exit;
  593. end;
  594. pdwAddress := dwAddress;
  595. Result := TRUE;
  596. end;
  597. function WspiapiNewAddrInfo(iSocketType, iProtocol: Integer; wPort: WORD; dwAddress: DWORD): {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}; stdcall;
  598. var
  599. ptNew: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  600. ptAddress: PSockAddrIn;
  601. begin
  602. // allocate a new addrinfo structure.
  603. {$IFDEF UNICODE}
  604. ptNew := PaddrinfoW(WspiapiMalloc(SizeOf(addrinfoW)));
  605. {$ELSE}
  606. ptNew := Paddrinfo(WspiapiMalloc(SizeOf(addrinfo)));
  607. {$ENDIF}
  608. if ptNew = nil then begin
  609. Result := nil;
  610. Exit;
  611. end;
  612. ptAddress := PSockAddrIn(WspiapiMalloc(SizeOf(sockaddr_in)));
  613. if ptAddress = nil then begin
  614. WspiapiFree(ptNew);
  615. Result := nil;
  616. Exit;
  617. end;
  618. ptAddress^.sin_family := AF_INET;
  619. ptAddress^.sin_port := wPort;
  620. ptAddress^.sin_addr.s_addr := dwAddress;
  621. // fill in the fields...
  622. ptNew^.ai_family := PF_INET;
  623. ptNew^.ai_socktype := iSocketType;
  624. ptNew^.ai_protocol := iProtocol;
  625. ptNew^.ai_addrlen := SizeOf(sockaddr_in);
  626. ptNew^.ai_addr := Psockaddr(ptAddress);
  627. Result := ptNew;
  628. end;
  629. function WspiapiQueryDNS(const pszNodeName: PIdPlatformChar; iSocketType, iProtocol: Integer;
  630. wPort: WORD; pszAlias: PIdPlatformChar; var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  631. var
  632. pptNext: {$IFDEF UNICODE}PPaddrinfoW{$ELSE}PPaddrinfo{$ENDIF};
  633. ptHost: Phostent;
  634. ppAddresses: ^PInAddr;
  635. {$IFDEF USE_MARSHALLED_PTRS}
  636. M: TMarshaller;
  637. {$ENDIF}
  638. begin
  639. pptNext := @pptResult;
  640. pptNext^ := nil;
  641. pszAlias^ := TIdPlatformChar(0);
  642. ptHost := gethostbyname(
  643. {$IFDEF USE_MARSHALLED_PTRS}
  644. M.AsAnsi(pszNodeName).ToPointer
  645. {$ELSE}
  646. {$IFDEF UNICODE}
  647. PIdAnsiChar(AnsiString(pszNodeName)) // explicit convert to Ansi
  648. {$ELSE}
  649. pszNodeName
  650. {$ENDIF}
  651. {$ENDIF}
  652. );
  653. if ptHost <> nil then begin
  654. if (ptHost^.h_addrtype = AF_INET) and (ptHost^.h_length = SizeOf(in_addr)) then begin
  655. ppAddresses := Pointer(ptHost^.h_address_list);
  656. while ppAddresses^ <> nil do begin
  657. // create an addrinfo structure...
  658. pptNext^ := WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, ppAddresses^^.s_addr);
  659. if pptNext^ = nil then begin
  660. Result := EAI_MEMORY;
  661. Exit;
  662. end;
  663. pptNext := @((pptNext^)^.ai_next);
  664. Inc(ppAddresses);
  665. end;
  666. end;
  667. // pick up the canonical name.
  668. StrLCopy(pszAlias,
  669. {$IFNDEF UNICODE}
  670. ptHost^.h_name
  671. {$ELSE}
  672. PIdPlatformChar(TIdPlatformString(ptHost^.h_name))
  673. {$ENDIF}
  674. , NI_MAXHOST);
  675. Result := 0;
  676. Exit;
  677. end;
  678. case WSAGetLastError() of
  679. WSAHOST_NOT_FOUND: Result := EAI_NONAME;
  680. WSATRY_AGAIN: Result := EAI_AGAIN;
  681. WSANO_RECOVERY: Result := EAI_FAIL;
  682. WSANO_DATA: Result := EAI_NODATA;
  683. else
  684. Result := EAI_NONAME;
  685. end;
  686. end;
  687. function WspiapiLookupNode(const pszNodeName: PIdPlatformChar; iSocketType: Integer;
  688. iProtocol: Integer; wPort: WORD; bAI_CANONNAME: BOOL; var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  689. var
  690. iError: Integer;
  691. iAliasCount: Integer;
  692. szFQDN1: array[0..NI_MAXHOST-1] of TIdPlatformChar;
  693. szFQDN2: array[0..NI_MAXHOST-1] of TIdPlatformChar;
  694. pszName: PIdPlatformChar;
  695. pszAlias: PIdPlatformChar;
  696. pszScratch: PIdPlatformChar;
  697. begin
  698. iAliasCount := 0;
  699. ZeroMemory(@szFQDN1, SizeOf(szFQDN1));
  700. ZeroMemory(@szFQDN2, SizeOf(szFQDN2));
  701. pszName := @szFQDN1[0];
  702. pszAlias := @szFQDN2[0];
  703. pszScratch := nil;
  704. StrLCopy(pszName, pszNodeName, NI_MAXHOST);
  705. repeat
  706. iError := WspiapiQueryDNS(pszNodeName, iSocketType, iProtocol, wPort, pszAlias, pptResult);
  707. if iError <> 0 then begin
  708. Break;
  709. end;
  710. // if we found addresses, then we are done.
  711. if pptResult <> nil then begin
  712. Break;
  713. end;
  714. // stop infinite loops due to DNS misconfiguration. there appears
  715. // to be no particular recommended limit in RFCs 1034 and 1035.
  716. if (StrLen(pszAlias) = 0) or (StrComp(pszName, pszAlias) = 0) then begin
  717. iError := EAI_FAIL;
  718. Break;
  719. end;
  720. Inc(iAliasCount);
  721. if iAliasCount = 16 then begin
  722. iError := EAI_FAIL;
  723. Break;
  724. end;
  725. // there was a new CNAME, look again.
  726. WspiapiSwap(pszName, pszAlias, pszScratch);
  727. until False;
  728. if (iError = 0) and bAI_CANONNAME then begin
  729. pptResult^.ai_canonname := WspiapiStrdup(pszAlias);
  730. if pptResult^.ai_canonname = nil then begin
  731. iError := EAI_MEMORY;
  732. end;
  733. end;
  734. Result := iError;
  735. end;
  736. function WspiapiClone(wPort: WORD; ptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  737. var
  738. ptNext, ptNew: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  739. begin
  740. ptNext := ptResult;
  741. while ptNext <> nil do begin
  742. // create an addrinfo structure...
  743. ptNew := WspiapiNewAddrInfo(SOCK_DGRAM, ptNext^.ai_protocol, wPort, PSockAddrIn(ptNext^.ai_addr)^.sin_addr.s_addr);
  744. if ptNew = nil then begin
  745. Break;
  746. end;
  747. // link the cloned addrinfo
  748. ptNew^.ai_next := ptNext^.ai_next;
  749. ptNext^.ai_next := ptNew;
  750. ptNext := ptNew^.ai_next;
  751. end;
  752. if ptNext <> nil then begin
  753. Result := EAI_MEMORY;
  754. Exit;
  755. end;
  756. Result := 0;
  757. end;
  758. procedure WspiapiLegacyFreeAddrInfo(ptHead: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}); stdcall;
  759. var
  760. ptNext: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  761. begin
  762. ptNext := ptHead;
  763. while ptNext <> nil do
  764. begin
  765. if ptNext^.ai_canonname <> nil then begin
  766. WspiapiFree(ptNext^.ai_canonname);
  767. end;
  768. if ptNext^.ai_addr <> nil then begin
  769. WspiapiFree(ptNext^.ai_addr);
  770. end;
  771. ptHead := ptNext^.ai_next;
  772. WspiapiFree(ptNext);
  773. ptNext := ptHead;
  774. end;
  775. end;
  776. {$IFNDEF HAS_TryStrToInt}
  777. // TODO: use the implementation already in IdGlobalProtocols...
  778. function TryStrToInt(const S: string; out Value: Integer): Boolean;
  779. {$IFDEF USE_INLINE}inline;{$ENDIF}
  780. var
  781. E: Integer;
  782. begin
  783. Val(S, Value, E);
  784. Result := E = 0;
  785. end;
  786. {$ENDIF}
  787. function WspiapiLegacyGetAddrInfo(const pszNodeName: PIdPlatformChar; const pszServiceName: PIdPlatformChar;
  788. const ptHints: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF};
  789. var pptResult: {$IFDEF UNICODE}PaddrinfoW{$ELSE}Paddrinfo{$ENDIF}): Integer; stdcall;
  790. var
  791. iError: Integer;
  792. iFlags: Integer;
  793. iSocketType: Integer;
  794. iProtocol: Integer;
  795. wPort: WORD;
  796. iTmp: Integer;
  797. dwAddress: DWORD;
  798. ptService: Pservent;
  799. bClone: BOOL;
  800. wTcpPort: WORD;
  801. wUdpPort: WORD;
  802. {$IFDEF USE_MARSHALLED_PTRS}
  803. M: TMarshaller;
  804. {$ENDIF}
  805. begin
  806. iError := 0;
  807. iFlags := 0;
  808. iSocketType := 0;
  809. iProtocol := 0;
  810. wPort := 0;
  811. dwAddress := 0;
  812. bClone := FALSE;
  813. wTcpPort := 0;
  814. wUdpPort := 0;
  815. // initialize pptResult with default return value.
  816. pptResult := nil;
  817. ////////////////////////////////////////
  818. // validate arguments...
  819. //
  820. // both the node name and the service name can't be NULL.
  821. if (pszNodeName = nil) and (pszServiceName = nil) then begin
  822. Result := EAI_NONAME;
  823. Exit;
  824. end;
  825. // validate hints.
  826. if ptHints <> nil then
  827. begin
  828. // all members other than ai_flags, ai_family, ai_socktype
  829. // and ai_protocol must be zero or a null pointer.
  830. if (ptHints^.ai_addrlen <> 0) or
  831. (ptHints^.ai_canonname <> nil) or
  832. (ptHints^.ai_addr <> nil) or
  833. (ptHints^.ai_next <> nil) then
  834. begin
  835. Result := EAI_FAIL;
  836. Exit;
  837. end;
  838. // the spec has the "bad flags" error code, so presumably we
  839. // should check something here. insisting that there aren't
  840. // any unspecified flags set would break forward compatibility,
  841. // however. so we just check for non-sensical combinations.
  842. //
  843. // we cannot come up with a canonical name given a null node name.
  844. iFlags := ptHints^.ai_flags;
  845. if ((iFlags and AI_CANONNAME) <> 0) and (pszNodeName = nil) then begin
  846. Result := EAI_BADFLAGS;
  847. Exit;
  848. end;
  849. // we only support a limited number of protocol families.
  850. if (ptHints^.ai_family <> PF_UNSPEC) and (ptHints^.ai_family <> PF_INET) then begin
  851. Result := EAI_FAMILY;
  852. Exit;
  853. end;
  854. // we only support only these socket types.
  855. iSocketType := ptHints^.ai_socktype;
  856. if (iSocketType <> 0) and
  857. (iSocketType <> SOCK_STREAM) and
  858. (iSocketType <> SOCK_DGRAM) and
  859. (iSocketType <> SOCK_RAW) then
  860. begin
  861. Result := EAI_SOCKTYPE;
  862. Exit;
  863. end;
  864. // REVIEW: What if ai_socktype and ai_protocol are at odds?
  865. iProtocol := ptHints^.ai_protocol;
  866. end;
  867. ////////////////////////////////////////
  868. // do service lookup...
  869. if pszServiceName <> nil then begin
  870. if TryStrToInt(pszServiceName, iTmp) and (iTmp >= 0) then begin
  871. wPort := htons(WORD(iTmp));
  872. //wTcpPort := wPort; // never used
  873. wUdpPort := wPort;
  874. if iSocketType = 0 then begin
  875. bClone := TRUE;
  876. iSocketType := SOCK_STREAM;
  877. end;
  878. end else
  879. begin
  880. if (iSocketType = 0) or (iSocketType = SOCK_DGRAM) then begin
  881. ptService := getservbyname(
  882. {$IFDEF USE_MARSHALLED_PTRS}
  883. M.AsAnsi(pszServiceName).ToPointer
  884. {$ELSE}
  885. {$IFDEF UNICODE}
  886. PIdAnsiChar(AnsiString(pszServiceName)) // explicit convert to Ansi
  887. {$ELSE}
  888. pszServiceName
  889. {$ENDIF}
  890. {$ENDIF}
  891. , 'udp'); {do not localize}
  892. if ptService <> nil then begin
  893. wPort := ptService^.s_port;
  894. wUdpPort := wPort;
  895. end;
  896. end;
  897. if (iSocketType = 0) or (iSocketType = SOCK_STREAM) then begin
  898. ptService := getservbyname(
  899. {$IFDEF USE_MARSHALLED_PTRS}
  900. M.AsAnsi(pszServiceName).ToPointer
  901. {$ELSE}
  902. {$IFDEF UNICODE}
  903. PIdAnsiChar(AnsiString(pszServiceName)) // explicit convert to Ansi
  904. {$ELSE}
  905. pszServiceName
  906. {$ENDIF}
  907. {$ENDIF}
  908. , 'tcp'); {do not localize}
  909. if ptService <> nil then begin
  910. wPort := ptService^.s_port;
  911. wTcpPort := wPort;
  912. end;
  913. end;
  914. // assumes 0 is an invalid service port...
  915. if wPort = 0 then begin
  916. Result := iif(iSocketType <> 0, EAI_SERVICE, EAI_NONAME);
  917. Exit;
  918. end;
  919. if iSocketType = 0 then begin
  920. // if both tcp and udp, process tcp now & clone udp later.
  921. iSocketType := iif(wTcpPort <> 0, SOCK_STREAM, SOCK_DGRAM);
  922. bClone := (wTcpPort <> 0) and (wUdpPort <> 0);
  923. end;
  924. end;
  925. end;
  926. ////////////////////////////////////////
  927. // do node name lookup...
  928. // if we weren't given a node name,
  929. // return the wildcard or loopback address (depending on AI_PASSIVE).
  930. //
  931. // if we have a numeric host address string,
  932. // return the binary address.
  933. //
  934. if ((pszNodeName = nil) or WspiapiParseV4Address(pszNodeName, dwAddress)) then begin
  935. if pszNodeName = nil then begin
  936. dwAddress := htonl(iif((iFlags and AI_PASSIVE) <> 0, INADDR_ANY, INADDR_LOOPBACK));
  937. end;
  938. // create an addrinfo structure...
  939. pptResult := WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
  940. if pptResult = nil then begin
  941. iError := EAI_MEMORY;
  942. end;
  943. if (iError = 0) and (pszNodeName <> nil) then begin
  944. // implementation specific behavior: set AI_NUMERICHOST
  945. // to indicate that we got a numeric host address string.
  946. pptResult^.ai_flags := pptResult^.ai_flags or AI_NUMERICHOST;
  947. // return the numeric address string as the canonical name
  948. if (iFlags and AI_CANONNAME) <> 0 then begin
  949. pptResult^.ai_canonname := WspiapiStrdup(
  950. {$IFNDEF UNICODE}
  951. inet_ntoa(PInAddr(@dwAddress)^)
  952. {$ELSE}
  953. PWideChar(TIdUnicodeString(inet_ntoa(PInAddr(@dwAddress)^)))
  954. {$ENDIF}
  955. );
  956. if pptResult^.ai_canonname = nil then begin
  957. iError := EAI_MEMORY;
  958. end;
  959. end;
  960. end;
  961. end
  962. // if we do not have a numeric host address string and
  963. // AI_NUMERICHOST flag is set, return an error!
  964. else if ((iFlags and AI_NUMERICHOST) <> 0) then begin
  965. iError := EAI_NONAME;
  966. end
  967. // since we have a non-numeric node name,
  968. // we have to do a regular node name lookup.
  969. else begin
  970. iError := WspiapiLookupNode(pszNodeName, iSocketType, iProtocol, wPort, (iFlags and AI_CANONNAME) <> 0, pptResult);
  971. end;
  972. if (iError = 0) and bClone then begin
  973. iError := WspiapiClone(wUdpPort, pptResult);
  974. end;
  975. if iError <> 0 then begin
  976. WspiapiLegacyFreeAddrInfo(pptResult);
  977. pptResult := nil;
  978. end;
  979. Result := iError;
  980. end;
  981. function iif(ATest: Boolean; const ATrue, AFalse: PIdAnsiChar): PIdAnsiChar;
  982. {$IFDEF USE_INLINE}inline;{$ENDIF}
  983. begin
  984. if ATest then begin
  985. Result := ATrue;
  986. end else begin
  987. Result := AFalse;
  988. end;
  989. end;
  990. function WspiapiLegacyGetNameInfo(ptSocketAddress: Psockaddr;
  991. tSocketLength: u_int; pszNodeName: PIdPlatformChar; tNodeLength: size_t;
  992. pszServiceName: PIdPlatformChar; tServiceLength: size_t; iFlags: Integer): Integer; stdcall;
  993. var
  994. ptService: Pservent;
  995. wPort: WORD;
  996. szBuffer: array[0..5] of TIdPlatformChar;
  997. pszService: PIdPlatformChar;
  998. ptHost: Phostent;
  999. tAddress: in_addr;
  1000. pszNode: PIdPlatformChar;
  1001. pc: PIdPlatformChar;
  1002. {$IFDEF UNICODE}
  1003. tmpService: TIdUnicodeString;
  1004. tmpNode: TIdUnicodeString;
  1005. {$ENDIF}
  1006. begin
  1007. StrCopy(szBuffer, '65535');
  1008. pszService := szBuffer;
  1009. // sanity check ptSocketAddress and tSocketLength.
  1010. if (ptSocketAddress = nil) or (tSocketLength < SizeOf(sockaddr)) then begin
  1011. Result := EAI_FAIL;
  1012. Exit;
  1013. end;
  1014. if ptSocketAddress^.sa_family <> AF_INET then begin
  1015. Result := EAI_FAMILY;
  1016. Exit;
  1017. end;
  1018. if tSocketLength < SizeOf(sockaddr_in) then begin
  1019. Result := EAI_FAIL;
  1020. Exit;
  1021. end;
  1022. if (not ((pszNodeName <> nil) and (tNodeLength > 0))) and (not ((pszServiceName <> nil) and (tServiceLength > 0))) then begin
  1023. Result := EAI_NONAME;
  1024. Exit;
  1025. end;
  1026. // the draft has the "bad flags" error code, so presumably we
  1027. // should check something here. insisting that there aren't
  1028. // any unspecified flags set would break forward compatibility,
  1029. // however. so we just check for non-sensical combinations.
  1030. if ((iFlags and NI_NUMERICHOST) <> 0) and ((iFlags and NI_NAMEREQD) <> 0) then begin
  1031. Result := EAI_BADFLAGS;
  1032. Exit;
  1033. end;
  1034. // translate the port to a service name (if requested).
  1035. if (pszServiceName <> nil) and (tServiceLength > 0) then begin
  1036. wPort := PSockAddrIn(ptSocketAddress)^.sin_port;
  1037. if (iFlags and NI_NUMERICSERV) <> 0 then begin
  1038. // return numeric form of the address.
  1039. StrPLCopy(szBuffer, IntToStr(ntohs(wPort)), Length(szBuffer));
  1040. end else
  1041. begin
  1042. // return service name corresponding to port.
  1043. ptService := getservbyport(wPort, iif((iFlags and NI_DGRAM) <> 0, 'udp', nil));
  1044. if (ptService <> nil) and (ptService^.s_name <> nil) then begin
  1045. // lookup successful.
  1046. {$IFNDEF UNICODE}
  1047. pszService := ptService^.s_name;
  1048. {$ELSE}
  1049. tmpService := TIdUnicodeString(ptService^.s_name);
  1050. pszService := PWideChar(tmpService);
  1051. {$ENDIF}
  1052. end else begin
  1053. // DRAFT: return numeric form of the port!
  1054. StrPLCopy(szBuffer, IntToStr(ntohs(wPort)), Length(szBuffer));
  1055. end;
  1056. end;
  1057. if tServiceLength > size_t(StrLen(pszService)) then begin
  1058. StrLCopy(pszServiceName, pszService, tServiceLength);
  1059. end else begin
  1060. Result := EAI_FAIL;
  1061. Exit;
  1062. end;
  1063. end;
  1064. // translate the address to a node name (if requested).
  1065. if (pszNodeName <> nil) and (tNodeLength > 0) then begin
  1066. // this is the IPv4-only version, so we have an IPv4 address.
  1067. tAddress := PSockAddrIn(ptSocketAddress)^.sin_addr;
  1068. if (iFlags and NI_NUMERICHOST) <> 0 then begin
  1069. // return numeric form of the address.
  1070. {$IFNDEF UNICODE}
  1071. pszNode := inet_ntoa(tAddress);
  1072. {$ELSE}
  1073. tmpNode := TIdUnicodeString(inet_ntoa(tAddress));
  1074. pszNode := PWideChar(tmpNode);
  1075. {$ENDIF}
  1076. end else
  1077. begin
  1078. // return node name corresponding to address.
  1079. ptHost := gethostbyaddr(PIdAnsiChar(@tAddress), SizeOf(in_addr), AF_INET);
  1080. if (ptHost <> nil) and (ptHost^.h_name <> nil) then begin
  1081. // DNS lookup successful.
  1082. // stop copying at a "." if NI_NOFQDN is specified.
  1083. {$IFNDEF UNICODE}
  1084. pszNode := ptHost^.h_name;
  1085. {$ELSE}
  1086. tmpNode := TIdUnicodeString(ptHost^.h_name);
  1087. pszNode := PWideChar(tmpNode);
  1088. {$ENDIF}
  1089. if (iFlags and NI_NOFQDN) <> 0 then begin
  1090. pc := StrScan(pszNode, '.');
  1091. if pc <> nil then begin
  1092. pc^ := TIdPlatformChar(0);
  1093. end;
  1094. end;
  1095. end else
  1096. begin
  1097. // DNS lookup failed. return numeric form of the address.
  1098. if (iFlags and NI_NAMEREQD) <> 0 then begin
  1099. case WSAGetLastError() of
  1100. WSAHOST_NOT_FOUND: Result := EAI_NONAME;
  1101. WSATRY_AGAIN: Result := EAI_AGAIN;
  1102. WSANO_RECOVERY: Result := EAI_FAIL;
  1103. else
  1104. Result := EAI_NONAME;
  1105. end;
  1106. Exit;
  1107. end else begin
  1108. {$IFNDEF UNICODE}
  1109. pszNode := inet_ntoa(tAddress);
  1110. {$ELSE}
  1111. tmpNode := TIdUnicodeString(inet_ntoa(tAddress));
  1112. pszNode := PWideChar(tmpNode);
  1113. {$ENDIF}
  1114. end;
  1115. end;
  1116. end;
  1117. if tNodeLength > size_t(StrLen(pszNode)) then begin
  1118. StrLCopy(pszNodeName, pszNode, tNodeLength);
  1119. end else begin
  1120. Result := EAI_FAIL;
  1121. Exit;
  1122. end;
  1123. end;
  1124. Result := 0;
  1125. end;
  1126. {$IFDEF WINCE_UNICODE}
  1127. function IndyStrdupAToW(const pszString: PIdAnsiChar): PWideChar;
  1128. var
  1129. szStr: TIdUnicodeString;
  1130. pszMemory: PWideChar;
  1131. cchMemory: size_t;
  1132. begin
  1133. if pszString = nil then begin
  1134. Result := nil;
  1135. Exit;
  1136. end;
  1137. szStr := TIdUnicodeString(pszString);
  1138. cchMemory := Length(szStr) + 1;
  1139. pszMemory := PWideChar(WspiapiMalloc(cchMemory * SizeOf(WideChar)));
  1140. if pszMemory = nil then begin
  1141. Result := nil;
  1142. Exit;
  1143. end;
  1144. StrLCopy(pszMemory, PWideChar(szStr), cchMemory);
  1145. Result := pszMemory;
  1146. end;
  1147. procedure IndyFreeAddrInfoW(ptHead: PaddrinfoW); stdcall;
  1148. var
  1149. ptNext: PaddrinfoW;
  1150. begin
  1151. ptNext := ptHead;
  1152. while ptNext <> nil do
  1153. begin
  1154. if ptNext^.ai_canonname <> nil then begin
  1155. WspiapiFree(ptNext^.ai_canonname);
  1156. end;
  1157. if ptNext^.ai_addr <> nil then begin
  1158. WspiapiFree(ptNext^.ai_addr);
  1159. end;
  1160. ptHead := ptNext^.ai_next;
  1161. WspiapiFree(ptNext);
  1162. ptNext := ptHead;
  1163. end;
  1164. end;
  1165. function IndyAddrInfoConvert(AddrInfo: Paddrinfo): PaddrinfoW;
  1166. var
  1167. ptNew: PaddrinfoW;
  1168. ptAddress: Pointer;
  1169. begin
  1170. Result := nil;
  1171. if AddrInfo = nil then begin
  1172. Exit;
  1173. end;
  1174. // allocate a new addrinfo structure.
  1175. ptNew := PaddrinfoW(WspiapiMalloc(SizeOf(addrinfoW)));
  1176. if ptNew = nil then begin
  1177. WspiapiFree(ptNew);
  1178. Exit;
  1179. end;
  1180. ptAddress := WspiapiMalloc(AddrInfo^.ai_addrlen);
  1181. if ptAddress = nil then begin
  1182. WspiapiFree(ptNew);
  1183. Exit;
  1184. end;
  1185. Move(AddrInfo^.ai_addr^, ptAddress^, AddrInfo^.ai_addrlen);
  1186. // fill in the fields...
  1187. ptNew^.ai_flags := AddrInfo^.ai_flags;
  1188. ptNew^.ai_family := AddrInfo^.ai_family;
  1189. ptNew^.ai_socktype := AddrInfo^.ai_socktype;
  1190. ptNew^.ai_protocol := AddrInfo^.ai_protocol;
  1191. ptNew^.ai_addrlen := AddrInfo^.ai_addrlen;
  1192. ptNew^.ai_canonname := nil;
  1193. ptNew^.ai_addr := Psockaddr(ptAddress);
  1194. ptNew^.ai_next := nil;
  1195. if AddrInfo^.ai_canonname <> nil then begin
  1196. ptNew^.ai_canonname := IndyStrdupAToW(AddrInfo^.ai_canonname);
  1197. if ptNew^.ai_canonname = nil then begin
  1198. IndyFreeAddrInfoW(ptNew);
  1199. Exit;
  1200. end;
  1201. end;
  1202. if AddrInfo^.ai_next <> nil then begin
  1203. ptNew^.ai_next := IndyAddrInfoConvert(AddrInfo^.ai_next);
  1204. if ptNew^.ai_next = nil then begin
  1205. IndyFreeAddrInfoW(ptNew);
  1206. Exit;
  1207. end;
  1208. end;
  1209. Result := ptNew;
  1210. end;
  1211. function IndyGetAddrInfoW(const pszNodeName: PWideChar; const pszServiceName: PWideChar;
  1212. const ptHints: PaddrinfoW; var pptResult: PaddrinfoW): Integer; stdcall;
  1213. var
  1214. LNodeName: AnsiString;
  1215. LPNodeName: PIdAnsiChar;
  1216. LServiceName: AnsiString;
  1217. LPServiceName: PIdAnsiChar;
  1218. LHints: addrinfo;
  1219. LPHints: Paddrinfo;
  1220. LResult: Paddrinfo;
  1221. begin
  1222. // initialize pptResult with default return value.
  1223. pptResult := nil;
  1224. if pszNodeName <> nil then begin
  1225. LNodeName := AnsiString(pszNodeName);
  1226. LPNodeName := PIdAnsiChar(LNodeName);
  1227. end else begin
  1228. LPNodeName := nil;
  1229. end;
  1230. if pszServiceName <> nil then begin
  1231. LServiceName := AnsiString(pszServiceName);
  1232. LPServiceName := PIdAnsiChar(LServiceName);
  1233. end else begin
  1234. LPServiceName := nil;
  1235. end;
  1236. if ptHints <> nil then begin
  1237. ZeroMemory(@LHints, SizeOf(LHints));
  1238. LHints.ai_flags := ptHints^.ai_flags;
  1239. LHints.ai_family := ptHints^.ai_family;
  1240. LHints.ai_socktype := ptHints^.ai_socktype;
  1241. LHints.ai_protocol := ptHints^.ai_protocol;
  1242. LPHints := @LHints;
  1243. end else begin
  1244. LPHints := nil;
  1245. end;
  1246. Result := getaddrinfoCE(LPNodeName, LPServiceName, LPHints, @LResult);
  1247. if Result = 0 then begin
  1248. try
  1249. pptResult := IndyAddrInfoConvert(LResult);
  1250. finally
  1251. freeaddrinfoCE(LResult);
  1252. end;
  1253. if pptResult = nil then begin
  1254. Result := EAI_MEMORY;
  1255. end;
  1256. end;
  1257. end;
  1258. function IndyGetNameInfoW(ptSocketAddress: Psockaddr; tSocketLength: u_int;
  1259. pszNodeName: PWideChar; tNodeLength: size_t; pszServiceName: PWideChar;
  1260. tServiceLength: size_t; iFlags: Integer): Integer; stdcall;
  1261. var
  1262. LHost: array[0..NI_MAXHOST-1] of TIdAnsiChar;
  1263. LPHost: PIdAnsiChar;
  1264. LHostLen: u_int;
  1265. LServ: array[0..NI_MAXSERV-1] of TIdAnsiChar;
  1266. LPServ: PIdAnsiChar;
  1267. LServLen: u_int;
  1268. begin
  1269. if pszNodeName <> nil then
  1270. begin
  1271. LPHost := @LHost[0];
  1272. LHostLen := Length(LHost);
  1273. end else begin
  1274. LPHost := nil;
  1275. LHostLen := 0;
  1276. end;
  1277. if pszServiceName <> nil then
  1278. begin
  1279. LPServ := @LServ[0];
  1280. LServLen := Length(LServ);
  1281. end else begin
  1282. LPServ := nil;
  1283. LServLen := 0;
  1284. end;
  1285. Result := getnameinfoCE(ptSocketAddress, tSocketLength, LPHost, LHostLen, LPServ, LServLen, iFlags);
  1286. if Result = 0 then begin
  1287. if pszNodeName <> nil then begin
  1288. StrPLCopy(pszNodeName, TIdUnicodeString(LPHost), tNodeLength);
  1289. end;
  1290. if pszServiceName <> nil then begin
  1291. StrPLCopy(pszServiceName, TIdUnicodeString(LPServ), tServiceLength);
  1292. end;
  1293. end;
  1294. end;
  1295. {$ENDIF}
  1296. procedure InitLibrary;
  1297. var
  1298. {$IFDEF WINCE_UNICODE}
  1299. gai: LPFN_GETADDRINFO;
  1300. gni: LPFN_GETNAMEINFO;
  1301. fai: LPFN_FREEADDRINFO;
  1302. {$ELSE}
  1303. gai: {$IFDEF UNICODE}LPFN_GETADDRINFOW{$ELSE}LPFN_GETADDRINFO{$ENDIF};
  1304. gni: {$IFDEF UNICODE}LPFN_GETNAMEINFOW{$ELSE}LPFN_GETNAMEINFO{$ENDIF};
  1305. fai: {$IFDEF UNICODE}LPFN_FREEADDRINFOW{$ELSE}LPFN_FREEADDRINFO{$ENDIF};
  1306. {$ENDIF}
  1307. begin
  1308. {
  1309. IMPORTANT!!!
  1310. I am doing things this way because the functions we want are probably in
  1311. the Winsock2 dll. If they are not there, only then do you actually want
  1312. to try the Wship6.dll. I know it's a mess but I found that the functions
  1313. may not load if they aren't in Wship6.dll (and they aren't there in some
  1314. versions of Windows).
  1315. hProcHandle provides a transparant way of managing the two possible library
  1316. locations. hWship6Dll is kept so we can unload the Wship6.dll if necessary.
  1317. }
  1318. //Winsock2 has to be loaded by IdWinsock first.
  1319. if not IdWinsock2.Winsock2Loaded then
  1320. begin
  1321. IdWinsock2.InitializeWinSock;
  1322. end;
  1323. hProcHandle := IdWinsock2.WinsockHandle;
  1324. gai := LoadLibFunction(hProcHandle, fn_getaddrinfo);
  1325. if not Assigned(gai) then
  1326. begin
  1327. hWship6Dll := SafeLoadLibrary(Wship6_dll);
  1328. hProcHandle := hWship6Dll;
  1329. gai := LoadLibFunction(hProcHandle, fn_getaddrinfo);
  1330. end;
  1331. if Assigned(gai) then
  1332. begin
  1333. gni := LoadLibFunction(hProcHandle, fn_getnameinfo);
  1334. if Assigned(gni) then
  1335. begin
  1336. fai := LoadLibFunction(hProcHandle, fn_freeaddrinfo);
  1337. if Assigned(fai) then
  1338. begin
  1339. {$IFDEF WINCE_UNICODE}
  1340. getaddrinfoCE := gai;
  1341. getnameinfoCE := gni;
  1342. freeaddrinfoCE := fai;
  1343. getaddrinfo := @IndyGetAddrInfoW;
  1344. getnameinfo := @IndyGetNameInfoW;
  1345. freeaddrinfo := @IndyFreeAddrInfoW;
  1346. {$ELSE}
  1347. getaddrinfo := gai;
  1348. getnameinfo := gni;
  1349. freeaddrinfo := fai;
  1350. {$ENDIF}
  1351. //Additional functions should be initialized here.
  1352. {$IFNDEF WINCE}
  1353. inet_pton := LoadLibFunction(hProcHandle, fn_inet_pton);
  1354. inet_ntop := LoadLibFunction(hProcHandle, fn_inet_ntop);
  1355. GetAddrInfoEx := LoadLibFunction(hProcHandle, fn_GetAddrInfoEx);
  1356. SetAddrInfoEx := LoadLibFunction(hProcHandle, fn_SetAddrInfoEx);
  1357. FreeAddrInfoEx := LoadLibFunction(hProcHandle, fn_FreeAddrInfoEx);
  1358. hfwpuclntDll := SafeLoadLibrary(fwpuclnt_dll);
  1359. if hfwpuclntDll <> IdNilHandle then
  1360. begin
  1361. WSASetSocketSecurity := LoadLibFunction(hfwpuclntDll, 'WSASetSocketSecurity'); {Do not localize}
  1362. WSAQuerySocketSecurity := LoadLibFunction(hfwpuclntDll, 'WSAQuerySocketSecurity'); {Do not localize}
  1363. WSASetSocketPeerTargetName := LoadLibFunction(hfwpuclntDll, 'WSASetSocketPeerTargetName'); {Do not localize}
  1364. WSADeleteSocketPeerTargetName := LoadLibFunction(hfwpuclntDll, 'WSADeleteSocketPeerTargetName'); {Do not localize}
  1365. WSAImpersonateSocketPeer := LoadLibFunction(hfwpuclntDll, 'WSAImpersonateSocketPeer'); {Do not localize}
  1366. WSARevertImpersonation := LoadLibFunction(hfwpuclntDll, 'WSARevertImpersonation'); {Do not localize}
  1367. end;
  1368. {$ENDIF}
  1369. Exit;
  1370. end;
  1371. end;
  1372. end;
  1373. CloseLibrary;
  1374. getaddrinfo := Addr(WspiapiLegacyGetAddrInfo);
  1375. getnameinfo := Addr(WspiapiLegacyGetNameInfo);
  1376. freeaddrinfo := Addr(WspiapiLegacyFreeAddrInfo);
  1377. {$I IdSymbolDeprecatedOff.inc}
  1378. GIdIPv6FuncsAvailable := True;
  1379. {$I IdSymbolDeprecatedOn.inc}
  1380. end;
  1381. initialization
  1382. finalization
  1383. CloseLibrary;
  1384. end.