OSDN Git Service

Add routines for IPv6.
[ffftp/ffftp.git] / socket.c
1 /*=============================================================================\r
2 *\r
3 *                                                                       ソケット\r
4 *\r
5 ===============================================================================\r
6 / Copyright (C) 1997-2007 Sota. All rights reserved.\r
7 /\r
8 / Redistribution and use in source and binary forms, with or without \r
9 / modification, are permitted provided that the following conditions \r
10 / are met:\r
11 /\r
12 /  1. Redistributions of source code must retain the above copyright \r
13 /     notice, this list of conditions and the following disclaimer.\r
14 /  2. Redistributions in binary form must reproduce the above copyright \r
15 /     notice, this list of conditions and the following disclaimer in the \r
16 /     documentation and/or other materials provided with the distribution.\r
17 /\r
18 / THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR \r
19 / IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES \r
20 / OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
21 / IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, \r
22 / INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
23 / BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
24 / USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
25 / ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
26 / (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF \r
27 / THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 /============================================================================*/\r
29 \r
30 #define STRICT\r
31 // IPv6対応\r
32 #include <ws2tcpip.h>\r
33 #include <windows.h>\r
34 #include <stdio.h>\r
35 #include <stdlib.h>\r
36 #include <string.h>\r
37 #include <time.h>\r
38 #include <windowsx.h>\r
39 #include <commctrl.h>\r
40 \r
41 #include "common.h"\r
42 #include "resource.h"\r
43 // UTF-8対応\r
44 #include "punycode.h"\r
45 \r
46 #define USE_THIS        1\r
47 #define DBG_MSG         0\r
48 \r
49 \r
50 \r
51 \r
52 // Winsock2で定義される定数と名前が重複し値が異なるため使用不可\r
53 //#define FD_CONNECT_BIT                0x0001\r
54 //#define FD_CLOSE_BIT          0x0002\r
55 //#define FD_ACCEPT_BIT         0x0004\r
56 //#define FD_READ_BIT                   0x0008\r
57 //#define FD_WRITE_BIT          0x0010\r
58 \r
59 \r
60 \r
61 \r
62 \r
63 typedef struct {\r
64         SOCKET Socket;\r
65         int FdConnect;\r
66         int FdClose;\r
67         int FdAccept;\r
68         int FdRead;\r
69         int FdWrite;\r
70         int Error;\r
71 } ASYNCSIGNAL;\r
72 \r
73 \r
74 typedef struct {\r
75         HANDLE Async;\r
76         int Done;\r
77         int ErrorDb;\r
78 } ASYNCSIGNALDATABASE;\r
79 \r
80 \r
81 // スレッド衝突のバグ修正\r
82 // 念のためテーブルを増量\r
83 //#define MAX_SIGNAL_ENTRY              10\r
84 //#define MAX_SIGNAL_ENTRY_DBASE        5\r
85 #define MAX_SIGNAL_ENTRY                16\r
86 #define MAX_SIGNAL_ENTRY_DBASE  16\r
87 \r
88 \r
89 \r
90 \r
91 /*===== プロトタイプ =====*/\r
92 \r
93 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
94 static int AskAsyncDone(SOCKET s, int *Error, int Mask);\r
95 static int AskAsyncDoneDbase(HANDLE Async, int *Error);\r
96 static int RegistAsyncTable(SOCKET s);\r
97 static int RegistAsyncTableDbase(HANDLE Async);\r
98 static int UnRegistAsyncTable(SOCKET s);\r
99 static int UnRegistAsyncTableDbase(HANDLE Async);\r
100 // UTF-8対応\r
101 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen);\r
102 // IPv6対応\r
103 static HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family);\r
104 \r
105 \r
106 /*===== 外部参照 =====*/\r
107 \r
108 extern int TimeOut;\r
109 \r
110 \r
111 /*===== ローカルなワーク =====*/\r
112 \r
113 static const char SocketWndClass[] = "FFFTPSocketWnd";\r
114 static HWND hWndSocket;\r
115 \r
116 static ASYNCSIGNAL Signal[MAX_SIGNAL_ENTRY];\r
117 static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];\r
118 \r
119 //static HANDLE hAsyncTblAccMutex;\r
120 // スレッド衝突のバグ修正\r
121 static HANDLE hAsyncTblAccMutex;\r
122 \r
123 \r
124 \r
125 \r
126 \r
127 /*----- \r
128 *\r
129 *       Parameter\r
130 *\r
131 *       Return Value\r
132 *               int ステータス\r
133 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
134 *----------------------------------------------------------------------------*/\r
135 \r
136 int MakeSocketWin(HWND hWnd, HINSTANCE hInst)\r
137 {\r
138         int i;\r
139         int Sts;\r
140         WNDCLASSEX wClass;\r
141 \r
142         wClass.cbSize        = sizeof(WNDCLASSEX);\r
143         wClass.style         = 0;\r
144         wClass.lpfnWndProc   = SocketWndProc;\r
145         wClass.cbClsExtra    = 0;\r
146         wClass.cbWndExtra    = 0;\r
147         wClass.hInstance     = hInst;\r
148         wClass.hIcon         = NULL;\r
149         wClass.hCursor       = NULL;\r
150         wClass.hbrBackground = (HBRUSH)CreateSolidBrush(GetSysColor(COLOR_INFOBK));\r
151         wClass.lpszMenuName  = NULL;\r
152         wClass.lpszClassName = SocketWndClass;\r
153         wClass.hIconSm       = NULL;\r
154         RegisterClassEx(&wClass);\r
155 \r
156         Sts = FFFTP_FAIL;\r
157         hWndSocket = CreateWindowEx(0, SocketWndClass, NULL,\r
158                         WS_BORDER | WS_POPUP,\r
159                         0, 0, 0, 0,\r
160                         hWnd, NULL, hInst, NULL);\r
161 \r
162         if(hWndSocket != NULL)\r
163         {\r
164 //              hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL);\r
165 \r
166                 // スレッド衝突のバグ修正\r
167 //              for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
168 //                      Signal[i].Socket = INVALID_SOCKET;\r
169 //              for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
170 //                      SignalDbase[i].Async = 0;\r
171                 if(hAsyncTblAccMutex = CreateMutex(NULL, FALSE, NULL))\r
172                 {\r
173                         for(i = 0; i < MAX_SIGNAL_ENTRY; i++)\r
174                                 Signal[i].Socket = INVALID_SOCKET;\r
175                         for(i = 0; i < MAX_SIGNAL_ENTRY_DBASE; i++)\r
176                                 SignalDbase[i].Async = 0;\r
177                 }\r
178                 Sts = FFFTP_SUCCESS;\r
179         }\r
180         return(Sts);\r
181 }\r
182 \r
183 \r
184 /*----- \r
185 *\r
186 *       Parameter\r
187 *               なし\r
188 *\r
189 *       Return Value\r
190 *               なし\r
191 *----------------------------------------------------------------------------*/\r
192 \r
193 void DeleteSocketWin(void)\r
194 {\r
195 //      CloseHandle(hAsyncTblAccMutex);\r
196         // スレッド衝突のバグ修正\r
197         CloseHandle(hAsyncTblAccMutex);\r
198         hAsyncTblAccMutex = NULL;\r
199 \r
200         if(hWndSocket != NULL)\r
201                 DestroyWindow(hWndSocket);\r
202         return;\r
203 }\r
204 \r
205 \r
206 /*----- \r
207 *\r
208 *       Parameter\r
209 *               HWND hWnd : ウインドウハンドル\r
210 *               UINT message : メッセージ番号\r
211 *               WPARAM wParam : メッセージの WPARAM 引数\r
212 *               LPARAM lParam : メッセージの LPARAM 引数\r
213 *\r
214 *       Return Value\r
215 *               BOOL TRUE/FALSE\r
216 *----------------------------------------------------------------------------*/\r
217 \r
218 static LRESULT CALLBACK SocketWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)\r
219 {\r
220         int Pos;\r
221 \r
222         switch(message)\r
223         {\r
224                 case WM_ASYNC_SOCKET :\r
225                         // スレッド衝突のバグ修正\r
226                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
227                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
228                         {\r
229                                 if(Signal[Pos].Socket == (SOCKET)wParam)\r
230                                 {\r
231                                         Signal[Pos].Error = WSAGETSELECTERROR(lParam);\r
232 #if DBG_MSG\r
233                                         if(WSAGETSELECTERROR(lParam) != 0)\r
234                                                 DoPrintf("####### Signal: error (%d)", WSAGETSELECTERROR(lParam));\r
235 #endif\r
236 \r
237                                         switch(WSAGETSELECTEVENT(lParam))\r
238                                         {\r
239                                                 case FD_CONNECT :\r
240                                                         Signal[Pos].FdConnect = 1;\r
241 #if DBG_MSG\r
242                                                         DoPrintf("####### Signal: connect (S=%x)", Signal[Pos].Socket);\r
243 #endif\r
244                                                         break;\r
245 \r
246                                                 case FD_CLOSE :\r
247                                                         Signal[Pos].FdClose = 1;\r
248 #if DBG_MSG\r
249                                                         DoPrintf("####### Signal: close (S=%x)", Signal[Pos].Socket);\r
250 #endif\r
251 //SetTaskMsg("####### Signal: close (%d) (S=%x)", Pos, Signal[Pos].Socket);\r
252                                                         break;\r
253 \r
254                                                 case FD_ACCEPT :\r
255                                                         Signal[Pos].FdAccept = 1;\r
256 #if DBG_MSG\r
257                                                         DoPrintf("####### Signal: accept (S=%x)", Signal[Pos].Socket);\r
258 #endif\r
259                                                         break;\r
260 \r
261                                                 case FD_READ :\r
262                                                         Signal[Pos].FdRead = 1;\r
263 #if DBG_MSG\r
264                                                         DoPrintf("####### Signal: read (S=%x)", Signal[Pos].Socket);\r
265 #endif\r
266                                                         break;\r
267 \r
268                                                 case FD_WRITE :\r
269                                                         Signal[Pos].FdWrite = 1;\r
270 #if DBG_MSG\r
271                                                         DoPrintf("####### Signal: write (S=%x)", Signal[Pos].Socket);\r
272 #endif\r
273                                                         break;\r
274                                         }\r
275                                         break;\r
276                                 }\r
277                         }\r
278                         // スレッド衝突のバグ修正\r
279                         ReleaseMutex(hAsyncTblAccMutex);\r
280                         break;\r
281 \r
282                 case WM_ASYNC_DBASE :\r
283                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
284                         RegistAsyncTableDbase((HANDLE)wParam);\r
285                         // スレッド衝突のバグ修正\r
286                         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
287                         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
288                         {\r
289                                 if(SignalDbase[Pos].Async == (HANDLE)wParam)\r
290                                 {\r
291                                         if(HIWORD(lParam) != 0)\r
292                                         {\r
293                                                 SignalDbase[Pos].ErrorDb = 1;\r
294 #if DBG_MSG\r
295                                                 DoPrintf("##### SignalDatabase: error");\r
296 #endif\r
297                                         }\r
298                                         SignalDbase[Pos].Done = 1;\r
299 #if DBG_MSG\r
300                                         DoPrintf("##### SignalDatabase: Done");\r
301 #endif\r
302                                         break;\r
303                                 }\r
304                         }\r
305                         // スレッド衝突のバグ修正\r
306                         ReleaseMutex(hAsyncTblAccMutex);\r
307                         break;\r
308 \r
309                 default :\r
310                         return(DefWindowProc(hWnd, message, wParam, lParam));\r
311         }\r
312     return(0);\r
313 }\r
314 \r
315 \r
316 \r
317 \r
318 /*----- \r
319 *\r
320 *       Parameter\r
321 *               \r
322 *\r
323 *       Return Value\r
324 *               \r
325 *----------------------------------------------------------------------------*/\r
326 \r
327 static int AskAsyncDone(SOCKET s, int *Error, int Mask)\r
328 {\r
329         int Sts;\r
330         int Pos;\r
331 \r
332         // スレッド衝突のバグ修正\r
333         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
334         Sts = NO;\r
335         *Error = 0;\r
336         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
337         {\r
338                 if(Signal[Pos].Socket == s)\r
339                 {\r
340                         *Error = Signal[Pos].Error;\r
341                         if(Signal[Pos].Error != 0)\r
342                                 Sts = YES;\r
343                         if((Mask & FD_CONNECT) && (Signal[Pos].FdConnect != 0))\r
344                         {\r
345                                 Sts = YES;\r
346 #if DBG_MSG\r
347                                 DoPrintf("### Ask: connect (Sts=%d, Error=%d)", Sts, *Error);\r
348 #endif\r
349                         }\r
350                         if((Mask & FD_CLOSE) && (Signal[Pos].FdClose != 0))\r
351 //                      if(Mask & FD_CLOSE)\r
352                         {\r
353                                 Sts = YES;\r
354 #if DBG_MSG\r
355                                 DoPrintf("### Ask: close (Sts=%d, Error=%d)", Sts, *Error);\r
356 #endif\r
357                         }\r
358                         if((Mask & FD_ACCEPT) && (Signal[Pos].FdAccept != 0))\r
359                         {\r
360                                 Signal[Pos].FdAccept = 0;\r
361                                 Sts = YES;\r
362 #if DBG_MSG\r
363                                 DoPrintf("### Ask: accept (Sts=%d, Error=%d)", Sts, *Error);\r
364 #endif\r
365                         }\r
366                         if((Mask & FD_READ) && (Signal[Pos].FdRead != 0))\r
367                         {\r
368                                 Signal[Pos].FdRead = 0;\r
369                                 Sts = YES;\r
370 #if DBG_MSG\r
371                                 DoPrintf("### Ask: read (Sts=%d, Error=%d)", Sts, *Error);\r
372 #endif\r
373                         }\r
374                         if((Mask & FD_WRITE) && (Signal[Pos].FdWrite != 0))\r
375                         {\r
376                                 Signal[Pos].FdWrite = 0;\r
377                                 Sts = YES;\r
378 #if DBG_MSG\r
379                                 DoPrintf("### Ask: write (Sts=%d, Error=%d)", Sts, *Error);\r
380 #endif\r
381                         }\r
382                         break;\r
383                 }\r
384         }\r
385         // スレッド衝突のバグ修正\r
386         ReleaseMutex(hAsyncTblAccMutex);\r
387 \r
388         if(Pos == MAX_SIGNAL_ENTRY)\r
389         {\r
390                 if(Mask & FD_CLOSE)\r
391                 {\r
392                                 Sts = YES;\r
393                 }\r
394                 else\r
395                 {\r
396                         MessageBox(GetMainHwnd(), "AskAsyncDone called with unregisterd socket.", "FFFTP inner error", MB_OK);\r
397                         exit(1);\r
398                 }\r
399         }\r
400         return(Sts);\r
401 }\r
402 \r
403 \r
404 /*----- \r
405 *\r
406 *       Parameter\r
407 *               \r
408 *\r
409 *       Return Value\r
410 *               \r
411 *----------------------------------------------------------------------------*/\r
412 \r
413 static int AskAsyncDoneDbase(HANDLE Async, int *Error)\r
414 {\r
415         int Sts;\r
416         int Pos;\r
417 \r
418         // スレッド衝突のバグ修正\r
419         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
420         Sts = NO;\r
421         *Error = 0;\r
422         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
423         {\r
424                 if(SignalDbase[Pos].Async == Async)\r
425                 {\r
426                         if(SignalDbase[Pos].Done != 0)\r
427                         {\r
428                                 *Error = SignalDbase[Pos].ErrorDb;\r
429                                 Sts = YES;\r
430 #if DBG_MSG\r
431                                 DoPrintf("### Ask: Dbase (Sts=%d, Error=%d)", Sts, *Error);\r
432 #endif\r
433                         }\r
434                         break;\r
435                 }\r
436         }\r
437         // スレッド衝突のバグ修正\r
438         ReleaseMutex(hAsyncTblAccMutex);\r
439 \r
440         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
441         {\r
442                 MessageBox(GetMainHwnd(), "AskAsyncDoneDbase called with unregisterd handle.", "FFFTP inner error", MB_OK);\r
443                 exit(1);\r
444         }\r
445         return(Sts);\r
446 }\r
447 \r
448 \r
449 \r
450 /*----- \r
451 *\r
452 *       Parameter\r
453 *               \r
454 *\r
455 *       Return Value\r
456 *               \r
457 *----------------------------------------------------------------------------*/\r
458 \r
459 static int RegistAsyncTable(SOCKET s)\r
460 {\r
461         int Sts;\r
462         int Pos;\r
463 \r
464         // スレッド衝突のバグ修正\r
465         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
466         Sts = NO;\r
467         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
468         {\r
469                 if(Signal[Pos].Socket == s)\r
470                 {\r
471                         // 強制的に閉じられたソケットがあると重複する可能性あり\r
472 //                      MessageBox(GetMainHwnd(), "Async socket already registerd.", "FFFTP inner error", MB_OK);\r
473 //                      break;\r
474                         Signal[Pos].Socket = INVALID_SOCKET;\r
475                 }\r
476         }\r
477         // スレッド衝突のバグ修正\r
478         ReleaseMutex(hAsyncTblAccMutex);\r
479 \r
480         if(Pos == MAX_SIGNAL_ENTRY)\r
481         {\r
482                 // スレッド衝突のバグ修正\r
483                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
484                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
485                 {\r
486                         if(Signal[Pos].Socket == INVALID_SOCKET)\r
487                         {\r
488 \r
489 //SetTaskMsg("############### Regist socket (%d)", Pos);\r
490 \r
491                                 Signal[Pos].Socket = s;\r
492                                 Signal[Pos].Error = 0;\r
493                                 Signal[Pos].FdConnect = 0;\r
494                                 Signal[Pos].FdClose = 0;\r
495                                 Signal[Pos].FdAccept = 0;\r
496                                 Signal[Pos].FdRead = 0;\r
497                                 Signal[Pos].FdWrite = 0;\r
498                                 Sts = YES;\r
499                                 break;\r
500                         }\r
501                 }\r
502                 // スレッド衝突のバグ修正\r
503                 ReleaseMutex(hAsyncTblAccMutex);\r
504 \r
505                 if(Pos == MAX_SIGNAL_ENTRY)\r
506                 {\r
507                         MessageBox(GetMainHwnd(), "No more async regist space.", "FFFTP inner error", MB_OK);\r
508                         exit(1);\r
509                 }\r
510         }\r
511 \r
512         return(Sts);\r
513 }\r
514 \r
515 \r
516 /*----- \r
517 *\r
518 *       Parameter\r
519 *               \r
520 *\r
521 *       Return Value\r
522 *               \r
523 *----------------------------------------------------------------------------*/\r
524 \r
525 static int RegistAsyncTableDbase(HANDLE Async)\r
526 {\r
527         int Sts;\r
528         int Pos;\r
529 \r
530         // スレッド衝突のバグ修正\r
531         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
532         Sts = NO;\r
533         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
534         {\r
535                 if(SignalDbase[Pos].Async == Async)\r
536                 {\r
537                         // 強制的に閉じられたハンドルがあると重複する可能性あり\r
538 //                      MessageBox(GetMainHwnd(), "Async handle already registerd.", "FFFTP inner error", MB_OK);\r
539                         // APIの仕様上ハンドルが登録される前にウィンドウメッセージが呼び出される可能性あり\r
540                         break;\r
541                 }\r
542         }\r
543         // スレッド衝突のバグ修正\r
544         ReleaseMutex(hAsyncTblAccMutex);\r
545 \r
546         if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
547         {\r
548                 // スレッド衝突のバグ修正\r
549                 WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
550                 for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
551                 {\r
552                         if(SignalDbase[Pos].Async == 0)\r
553                         {\r
554 \r
555 //SetTaskMsg("############### Regist dbase (%d)", Pos);\r
556 \r
557                                 SignalDbase[Pos].Async = Async;\r
558                                 SignalDbase[Pos].Done = 0;\r
559                                 SignalDbase[Pos].ErrorDb = 0;\r
560                                 Sts = YES;\r
561                                 break;\r
562                         }\r
563                 }\r
564                 // スレッド衝突のバグ修正\r
565                 ReleaseMutex(hAsyncTblAccMutex);\r
566 \r
567                 if(Pos == MAX_SIGNAL_ENTRY_DBASE)\r
568                 {\r
569                         MessageBox(GetMainHwnd(), "No more async dbase regist space.", "FFFTP inner error", MB_OK);\r
570                         exit(1);\r
571                 }\r
572         }\r
573 \r
574         return(Sts);\r
575 }\r
576 \r
577 \r
578 /*----- \r
579 *\r
580 *       Parameter\r
581 *               \r
582 *\r
583 *       Return Value\r
584 *               \r
585 *----------------------------------------------------------------------------*/\r
586 \r
587 static int UnRegistAsyncTable(SOCKET s)\r
588 {\r
589         int Sts;\r
590         int Pos;\r
591 \r
592         // スレッド衝突のバグ修正\r
593         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
594         Sts = NO;\r
595         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
596         {\r
597                 if(Signal[Pos].Socket == s)\r
598                 {\r
599 \r
600 //SetTaskMsg("############### UnRegist socket (%d)", Pos);\r
601 \r
602                         Signal[Pos].Socket = INVALID_SOCKET;\r
603                         Sts = YES;\r
604                         break;\r
605                 }\r
606         }\r
607         // スレッド衝突のバグ修正\r
608         ReleaseMutex(hAsyncTblAccMutex);\r
609         return(Sts);\r
610 }\r
611 \r
612 \r
613 /*----- \r
614 *\r
615 *       Parameter\r
616 *               \r
617 *\r
618 *       Return Value\r
619 *               \r
620 *----------------------------------------------------------------------------*/\r
621 \r
622 static int UnRegistAsyncTableDbase(HANDLE Async)\r
623 {\r
624         int Sts;\r
625         int Pos;\r
626 \r
627         // スレッド衝突のバグ修正\r
628         WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
629         Sts = NO;\r
630         for(Pos = 0; Pos < MAX_SIGNAL_ENTRY_DBASE; Pos++)\r
631         {\r
632                 if(SignalDbase[Pos].Async == Async)\r
633                 {\r
634 \r
635 //SetTaskMsg("############### UnRegist dbase (%d)", Pos);\r
636 \r
637                         SignalDbase[Pos].Async = 0;\r
638                         Sts = YES;\r
639                         break;\r
640                 }\r
641         }\r
642         // スレッド衝突のバグ修正\r
643         ReleaseMutex(hAsyncTblAccMutex);\r
644         return(Sts);\r
645 }\r
646 \r
647 \r
648 \r
649 \r
650 \r
651 \r
652 \r
653 \r
654 struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork)\r
655 {\r
656 #if USE_THIS\r
657         struct hostent *Ret;\r
658         HANDLE hAsync;\r
659         int Error;\r
660 \r
661 #if DBG_MSG\r
662         DoPrintf("# Start gethostbyname");\r
663 #endif\r
664         Ret = NULL;\r
665         // 同時接続対応\r
666 //      *CancelCheckWork = NO;\r
667 \r
668         // UTF-8対応\r
669 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
670         // IPv6対応\r
671 //      hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
672         hAsync = WSAAsyncGetHostByNameIPv6M(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len, AF_INET);\r
673         if(hAsync != NULL)\r
674         {\r
675                 RegistAsyncTableDbase(hAsync);\r
676                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
677                 {\r
678                         Sleep(1);\r
679                         if(BackgrndMessageProc() == YES)\r
680                                 *CancelCheckWork = YES;\r
681                 }\r
682 \r
683                 if(*CancelCheckWork == YES)\r
684                 {\r
685                         WSACancelAsyncRequest(hAsync);\r
686                 }\r
687                 else if(Error == 0)\r
688                 {\r
689                         Ret = (struct hostent *)Buf;\r
690                 }\r
691                 UnRegistAsyncTableDbase(hAsync);\r
692         }\r
693         return(Ret);\r
694 #else\r
695         return(gethostbyname(Name));\r
696 #endif\r
697 }\r
698 \r
699 \r
700 \r
701 \r
702 \r
703 SOCKET do_socket(int af, int type, int protocol)\r
704 {\r
705         SOCKET Ret;\r
706 \r
707         Ret = socket(af, type, protocol);\r
708         if(Ret != INVALID_SOCKET)\r
709         {\r
710                 RegistAsyncTable(Ret);\r
711         }\r
712 #if DBG_MSG\r
713         DoPrintf("# do_socket (S=%x)", Ret);\r
714 #endif\r
715         return(Ret);\r
716 }\r
717 \r
718 \r
719 \r
720 int do_closesocket(SOCKET s)\r
721 {\r
722 #if USE_THIS\r
723         int Ret;\r
724         int Error;\r
725         int CancelCheckWork;\r
726 \r
727 #if DBG_MSG\r
728         DoPrintf("# Start close (S=%x)", s);\r
729 #endif\r
730         CancelCheckWork = NO;\r
731 \r
732         // スレッド衝突のバグ修正\r
733         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
734         UnRegistAsyncTable(s);\r
735         // FTPS対応\r
736 //      Ret = closesocket(s);\r
737         Ret = closesocketS(s);\r
738         if(Ret == SOCKET_ERROR)\r
739         {\r
740                 Error = 0;\r
741                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE) != YES))\r
742                 {\r
743                         Sleep(1);\r
744                         if(BackgrndMessageProc() == YES)\r
745                                 CancelCheckWork = YES;\r
746                 }\r
747 \r
748                 if((CancelCheckWork == NO) && (Error == 0))\r
749                         Ret = 0;\r
750         }\r
751 \r
752         // スレッド衝突のバグ修正\r
753 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
754         if(BackgrndMessageProc() == YES)\r
755                 CancelCheckWork = YES;\r
756         // スレッド衝突のバグ修正\r
757 //      UnRegistAsyncTable(s);\r
758 \r
759 #if DBG_MSG\r
760         DoPrintf("# Exit close");\r
761 #endif\r
762         return(Ret);\r
763 #else\r
764         return(closesocket(s));\r
765 #endif\r
766 }\r
767 \r
768 \r
769 \r
770 \r
771 \r
772 \r
773 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
774 {\r
775 #if USE_THIS\r
776         int Ret;\r
777         int Error;\r
778 \r
779 #if DBG_MSG\r
780         DoPrintf("# Start connect (S=%x)", s);\r
781 #endif\r
782         // 同時接続対応\r
783 //      *CancelCheckWork = NO;\r
784 \r
785 #if DBG_MSG\r
786         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
787 #endif\r
788         // 高速化のためFD_READとFD_WRITEを使用しない\r
789 //      Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
790         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT);\r
791         if(Ret != SOCKET_ERROR)\r
792         {\r
793                 Ret = connect(s, name, namelen);\r
794                 if(Ret == SOCKET_ERROR)\r
795                 {\r
796                         do\r
797                         {\r
798                                 Error = 0;\r
799                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT) != YES))\r
800                                 {\r
801                                         Sleep(1);\r
802                                         if(BackgrndMessageProc() == YES)\r
803                                                 *CancelCheckWork = YES;\r
804                                 }\r
805 \r
806                                 if(*CancelCheckWork == YES)\r
807                                         break;\r
808                                 if(Error == 0)\r
809                                         Ret = 0;\r
810                                 else\r
811                                 {\r
812 //                                      Error = WSAGetLastError();\r
813                                         DoPrintf("#### Connect: Error=%d", Error);\r
814                                 }\r
815                         }\r
816                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
817                 }\r
818         }\r
819         else\r
820                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
821 \r
822 #if DBG_MSG\r
823         DoPrintf("# Exit connect (%d)", Ret);\r
824 #endif\r
825         return(Ret);\r
826 #else\r
827         return(connect(s, name, namelen));\r
828 #endif\r
829 }\r
830 \r
831 \r
832 \r
833 \r
834 \r
835 int do_listen(SOCKET s, int backlog)\r
836 {\r
837         int Ret;\r
838 \r
839         Ret = 1;\r
840 #if DBG_MSG\r
841         DoPrintf("# Start listen (S=%x)", s);\r
842         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
843 #endif\r
844 \r
845         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
846         if(Ret != SOCKET_ERROR)\r
847                 Ret = listen(s, backlog);\r
848 \r
849 #if DBG_MSG\r
850         DoPrintf("# Exit listen (%d)", Ret);\r
851 #endif\r
852         return(Ret);\r
853 }\r
854 \r
855 \r
856 \r
857 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
858 {\r
859 #if USE_THIS\r
860         SOCKET Ret2;\r
861         int CancelCheckWork;\r
862         int Error;\r
863 \r
864 #if DBG_MSG\r
865         DoPrintf("# Start accept (S=%x)", s);\r
866 #endif\r
867         CancelCheckWork = NO;\r
868         Ret2 = INVALID_SOCKET;\r
869         Error = 0;\r
870 \r
871         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT) != YES))\r
872         {\r
873                 if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
874                 {\r
875                         Error = 1;\r
876                         break;\r
877                 }\r
878                 Sleep(1);\r
879                 if(BackgrndMessageProc() == YES)\r
880                         CancelCheckWork = YES;\r
881         }\r
882 \r
883         if((CancelCheckWork == NO) && (Error == 0))\r
884         {\r
885                 do\r
886                 {\r
887                         Ret2 = accept(s, addr, addrlen);\r
888                         if(Ret2 != INVALID_SOCKET)\r
889                         {\r
890 #if DBG_MSG\r
891                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
892                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
893 #endif\r
894                                 RegistAsyncTable(Ret2);\r
895                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
896                                 {\r
897                                         do_closesocket(Ret2);\r
898                                         Ret2 = INVALID_SOCKET;\r
899                                 }\r
900                                 break;\r
901                         }\r
902                         Error = WSAGetLastError();\r
903                         Sleep(1);\r
904                         if(BackgrndMessageProc() == YES)\r
905                                 break;\r
906                 }\r
907                 while(Error == WSAEWOULDBLOCK);\r
908         }\r
909 \r
910 #if DBG_MSG\r
911         DoPrintf("# Exit accept");\r
912 #endif\r
913         return(Ret2);\r
914 #else\r
915         return(accept(s, addr, addrlen));\r
916 #endif\r
917 }\r
918 \r
919 \r
920 \r
921 \r
922 /*----- recv相当の関数 --------------------------------------------------------\r
923 *\r
924 *       Parameter\r
925 *               SOCKET s : ソケット\r
926 *               char *buf : データを読み込むバッファ\r
927 *               int len : 長さ\r
928 *               int flags : recvに与えるフラグ\r
929 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
930 *\r
931 *       Return Value\r
932 *               int : recvの戻り値と同じ\r
933 *\r
934 *       Note\r
935 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
936 *----------------------------------------------------------------------------*/\r
937 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
938 {\r
939 #if USE_THIS\r
940         int Ret;\r
941         time_t StartTime;\r
942         time_t ElapseTime;\r
943         int Error;\r
944 \r
945 #if DBG_MSG\r
946         DoPrintf("# Start recv (S=%x)", s);\r
947 #endif\r
948         *TimeOutErr = NO;\r
949         // 同時接続対応\r
950 //      *CancelCheckWork = NO;\r
951         Ret = SOCKET_ERROR;\r
952         Error = 0;\r
953 \r
954         if(TimeOut != 0)\r
955                 time(&StartTime);\r
956 \r
957         // FTPS対応\r
958         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
959 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
960         // 短時間にFD_READが2回以上通知される対策\r
961 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ) != YES))\r
962 //      {\r
963 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
964 //              {\r
965 //                      Ret = 0;\r
966 //                      break;\r
967 //              }\r
968 //              Sleep(1);\r
969 //              if(BackgrndMessageProc() == YES)\r
970 //                      *CancelCheckWork = YES;\r
971 //              else if(TimeOut != 0)\r
972 //              {\r
973 //                      time(&ElapseTime);\r
974 //                      ElapseTime -= StartTime;\r
975 //                      if(ElapseTime >= TimeOut)\r
976 //                      {\r
977 //                              DoPrintf("do_recv timed out");\r
978 //                              *TimeOutErr = YES;\r
979 //                              *CancelCheckWork = YES;\r
980 //                      }\r
981 //              }\r
982 //      }\r
983 \r
984         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
985         {\r
986                 do\r
987                 {\r
988 #if DBG_MSG\r
989                         DoPrintf("## recv()");\r
990 #endif\r
991 \r
992                         // FTPS対応\r
993 //                      Ret = recv(s, buf, len, flags);\r
994                         Ret = recvS(s, buf, len, flags);\r
995                         if(Ret != SOCKET_ERROR)\r
996                                 break;\r
997                         Error = WSAGetLastError();\r
998                         Sleep(1);\r
999                         if(BackgrndMessageProc() == YES)\r
1000                                 break;\r
1001                         // FTPS対応\r
1002                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
1003                         if(BackgrndMessageProc() == YES)\r
1004                                 *CancelCheckWork = YES;\r
1005                         else if(TimeOut != 0)\r
1006                         {\r
1007                                 time(&ElapseTime);\r
1008                                 ElapseTime -= StartTime;\r
1009                                 if(ElapseTime >= TimeOut)\r
1010                                 {\r
1011                                         DoPrintf("do_recv timed out");\r
1012                                         *TimeOutErr = YES;\r
1013                                         *CancelCheckWork = YES;\r
1014                                 }\r
1015                         }\r
1016                         if(*CancelCheckWork == YES)\r
1017                                 break;\r
1018                 }\r
1019                 while(Error == WSAEWOULDBLOCK);\r
1020         }\r
1021 \r
1022         if(BackgrndMessageProc() == YES)\r
1023                 Ret = SOCKET_ERROR;\r
1024 \r
1025 #if DBG_MSG\r
1026         DoPrintf("# Exit recv (%d)", Ret);\r
1027 #endif\r
1028         return(Ret);\r
1029 #else\r
1030         return(recv(s, buf, len, flags));\r
1031 #endif\r
1032 }\r
1033 \r
1034 \r
1035 \r
1036 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1037 {\r
1038 #if USE_THIS\r
1039         int Ret;\r
1040         time_t StartTime;\r
1041         time_t ElapseTime;\r
1042         int Error;\r
1043 \r
1044 #if DBG_MSG\r
1045         DoPrintf("# Start send (S=%x)", s);\r
1046 #endif\r
1047         *TimeOutErr = NO;\r
1048         // 同時接続対応\r
1049 //      *CancelCheckWork = NO;\r
1050         Ret = SOCKET_ERROR;\r
1051         Error = 0;\r
1052 \r
1053         if(TimeOut != 0)\r
1054                 time(&StartTime);\r
1055 \r
1056 #if DBG_MSG\r
1057         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1058 #endif\r
1059         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1060         // 毎回通知されたのはNT 4.0までのバグであり仕様ではない\r
1061         // XP以降は互換性のためか毎回通知される\r
1062 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1063         if(BackgrndMessageProc() == YES)\r
1064                 *CancelCheckWork = YES;\r
1065 \r
1066         // FTPS対応\r
1067         // 送信バッファの空き確認には影響しないが念のため\r
1068 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1069         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1070 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE) != YES))\r
1071 //      {\r
1072 //              if(AskAsyncDone(s, &Error, FD_CLOSE) == YES)\r
1073 //              {\r
1074 //                      Error = 1;\r
1075 //                      break;\r
1076 //              }\r
1077 //\r
1078 //              Sleep(1);\r
1079 //              if(BackgrndMessageProc() == YES)\r
1080 //                      *CancelCheckWork = YES;\r
1081 //              else if(TimeOut != 0)\r
1082 //              {\r
1083 //                      time(&ElapseTime);\r
1084 //                      ElapseTime -= StartTime;\r
1085 //                      if(ElapseTime >= TimeOut)\r
1086 //                      {\r
1087 //                              DoPrintf("do_write timed out");\r
1088 //                              *TimeOutErr = YES;\r
1089 //                              *CancelCheckWork = YES;\r
1090 //                      }\r
1091 //              }\r
1092 //      }\r
1093 \r
1094         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1095         {\r
1096                 do\r
1097                 {\r
1098 #if DBG_MSG\r
1099                         DoPrintf("## send()");\r
1100 #endif\r
1101 \r
1102                         // FTPS対応\r
1103 //                      Ret = send(s, buf, len, flags);\r
1104                         Ret = sendS(s, buf, len, flags);\r
1105                         if(Ret != SOCKET_ERROR)\r
1106                         {\r
1107 #if DBG_MSG\r
1108                                 DoPrintf("## send() OK");\r
1109 #endif\r
1110                                 break;\r
1111                         }\r
1112                         Error = WSAGetLastError();\r
1113                         Sleep(1);\r
1114                         if(BackgrndMessageProc() == YES)\r
1115                                 break;\r
1116                         // FTPS対応\r
1117                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1118                         if(BackgrndMessageProc() == YES)\r
1119                                 *CancelCheckWork = YES;\r
1120                         else if(TimeOut != 0)\r
1121                         {\r
1122                                 time(&ElapseTime);\r
1123                                 ElapseTime -= StartTime;\r
1124                                 if(ElapseTime >= TimeOut)\r
1125                                 {\r
1126                                         DoPrintf("do_recv timed out");\r
1127                                         *TimeOutErr = YES;\r
1128                                         *CancelCheckWork = YES;\r
1129                                 }\r
1130                         }\r
1131                         if(*CancelCheckWork == YES)\r
1132                                 break;\r
1133                 }\r
1134                 while(Error == WSAEWOULDBLOCK);\r
1135         }\r
1136 \r
1137         if(BackgrndMessageProc() == YES)\r
1138                 Ret = SOCKET_ERROR;\r
1139 \r
1140 #if DBG_MSG\r
1141         DoPrintf("# Exit send (%d)", Ret);\r
1142 #endif\r
1143         return(Ret);\r
1144 #else\r
1145         return(send(s, buf, len, flags));\r
1146 #endif\r
1147 }\r
1148 \r
1149 \r
1150 // 同時接続対応\r
1151 void RemoveReceivedData(SOCKET s)\r
1152 {\r
1153         char buf[1024];\r
1154         int len;\r
1155         int Error;\r
1156         while((len = recvS(s, buf, sizeof(buf), MSG_PEEK)) >= 0)\r
1157         {\r
1158                 AskAsyncDone(s, &Error, FD_READ);\r
1159                 recvS(s, buf, len, 0);\r
1160         }\r
1161 }\r
1162 \r
1163 \r
1164 /*----- \r
1165 *\r
1166 *       Parameter\r
1167 *\r
1168 *       Return Value\r
1169 *               int ステータス\r
1170 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1171 *----------------------------------------------------------------------------*/\r
1172 \r
1173 int CheckClosedAndReconnect(void)\r
1174 {\r
1175         int Error;\r
1176         int Sts;\r
1177 \r
1178 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1179 \r
1180         Sts = FFFTP_SUCCESS;\r
1181         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE) == YES)\r
1182         {\r
1183                 Sts = ReConnectCmdSkt();\r
1184         }\r
1185         return(Sts);\r
1186 }\r
1187 \r
1188 \r
1189 \r
1190 // IPv6対応\r
1191 \r
1192 typedef struct\r
1193 {\r
1194         HANDLE h;\r
1195         HWND hWnd;\r
1196         u_int wMsg;\r
1197         char * name;\r
1198         char * buf;\r
1199         int buflen;\r
1200         short Family;\r
1201 } GETHOSTBYNAMEDATA;\r
1202 \r
1203 static DWORD WINAPI WSAAsyncGetHostByNameIPv6ThreadProc(LPVOID lpParameter)\r
1204 {\r
1205         GETHOSTBYNAMEDATA* pData;\r
1206         struct hostent* pHost;\r
1207         struct addrinfo* pAddr;\r
1208         struct addrinfo* p;\r
1209         pHost = NULL;\r
1210         pData = (GETHOSTBYNAMEDATA*)lpParameter;\r
1211         if(getaddrinfo(pData->name, NULL, NULL, &pAddr) == 0)\r
1212         {\r
1213                 p = pAddr;\r
1214                 while(p)\r
1215                 {\r
1216                         if(p->ai_family == pData->Family)\r
1217                         {\r
1218                                 switch(p->ai_family)\r
1219                                 {\r
1220                                 case AF_INET:\r
1221                                         pHost = (struct hostent*)pData->buf;\r
1222                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)\r
1223                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in))\r
1224                                         {\r
1225                                                 pHost->h_name = NULL;\r
1226                                                 pHost->h_aliases = NULL;\r
1227                                                 pHost->h_addrtype = p->ai_family;\r
1228                                                 pHost->h_length = sizeof(struct in_addr);\r
1229                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
1230                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
1231                                                 pHost->h_addr_list[1] = NULL;\r
1232                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in*)p->ai_addr)->sin_addr, sizeof(struct in_addr));\r
1233                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
1234                                         }\r
1235                                         else\r
1236                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
1237                                         break;\r
1238                                 case AF_INET6:\r
1239                                         pHost = (struct hostent*)pData->buf;\r
1240                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)\r
1241                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in6))\r
1242                                         {\r
1243                                                 pHost->h_name = NULL;\r
1244                                                 pHost->h_aliases = NULL;\r
1245                                                 pHost->h_addrtype = p->ai_family;\r
1246                                                 pHost->h_length = sizeof(struct in6_addr);\r
1247                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
1248                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
1249                                                 pHost->h_addr_list[1] = NULL;\r
1250                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, sizeof(struct in6_addr));\r
1251                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
1252                                         }\r
1253                                         else\r
1254                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
1255                                         break;\r
1256                                 }\r
1257                         }\r
1258                         if(pHost)\r
1259                                 break;\r
1260                         p = p->ai_next;\r
1261                 }\r
1262                 if(!p)\r
1263                         PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
1264                 freeaddrinfo(pAddr);\r
1265         }\r
1266         else\r
1267                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
1268         free(pData->name);\r
1269         free(pData);\r
1270         // CreateThreadが返すハンドルが重複するのを回避\r
1271         Sleep(10000);\r
1272         return 0;\r
1273 }\r
1274 \r
1275 // IPv6対応のWSAAsyncGetHostByName相当の関数\r
1276 // FamilyにはAF_INETまたはAF_INET6を指定可能\r
1277 // ただしANSI用\r
1278 static HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1279 {\r
1280         HANDLE hResult;\r
1281         GETHOSTBYNAMEDATA* pData;\r
1282         hResult = NULL;\r
1283         if(pData = malloc(sizeof(GETHOSTBYNAMEDATA)))\r
1284         {\r
1285                 pData->hWnd = hWnd;\r
1286                 pData->wMsg = wMsg;\r
1287                 if(pData->name = malloc(sizeof(char) * (strlen(name) + 1)))\r
1288                 {\r
1289                         strcpy(pData->name, name);\r
1290                         pData->buf = buf;\r
1291                         pData->buflen = buflen;\r
1292                         pData->Family = Family;\r
1293                         if(pData->h = CreateThread(NULL, 0, WSAAsyncGetHostByNameIPv6ThreadProc, pData, CREATE_SUSPENDED, NULL))\r
1294                         {\r
1295                                 ResumeThread(pData->h);\r
1296                                 hResult = pData->h;\r
1297                         }\r
1298                 }\r
1299         }\r
1300         if(!hResult)\r
1301         {\r
1302                 if(pData)\r
1303                 {\r
1304                         if(pData->name)\r
1305                                 free(pData->name);\r
1306                         free(pData);\r
1307                 }\r
1308         }\r
1309         return hResult;\r
1310 }\r
1311 \r
1312 // WSAAsyncGetHostByNameIPv6用のWSACancelAsyncRequest相当の関数\r
1313 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)\r
1314 {\r
1315         int Result;\r
1316         Result = SOCKET_ERROR;\r
1317         if(TerminateThread(hAsyncTaskHandle, 0))\r
1318                 Result = 0;\r
1319         return Result;\r
1320 }\r
1321 \r
1322 // UTF-8対応\r
1323 \r
1324 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1325 {\r
1326         BOOL bResult;\r
1327         punycode_uint* pUnicode;\r
1328         punycode_uint* p;\r
1329         BOOL bNeeded;\r
1330         LPCSTR InputString;\r
1331         punycode_uint Length;\r
1332         punycode_uint OutputLength;\r
1333         bResult = FALSE;\r
1334         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1335         {\r
1336                 p = pUnicode;\r
1337                 bNeeded = FALSE;\r
1338                 InputString = Input;\r
1339                 Length = 0;\r
1340                 while(*InputString != '\0')\r
1341                 {\r
1342                         *p = (punycode_uint)GetNextCharM(InputString, &InputString);\r
1343                         if(*p >= 0x80)\r
1344                                 bNeeded = TRUE;\r
1345                         p++;\r
1346                         Length++;\r
1347                 }\r
1348                 if(bNeeded)\r
1349                 {\r
1350                         if(Count >= strlen("xn--") + 1)\r
1351                         {\r
1352                                 strcpy(Output, "xn--");\r
1353                                 OutputLength = Count - strlen("xn--");\r
1354                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1355                                 {\r
1356                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1357                                         bResult = TRUE;\r
1358                                 }\r
1359                         }\r
1360                 }\r
1361                 free(pUnicode);\r
1362         }\r
1363         if(!bResult)\r
1364         {\r
1365                 if(Count >= strlen(Input) + 1)\r
1366                 {\r
1367                         strcpy(Output, Input);\r
1368                         bResult = TRUE;\r
1369                 }\r
1370         }\r
1371         return bResult;\r
1372 }\r
1373 \r
1374 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1375 {\r
1376         BOOL bResult;\r
1377         DWORD Length;\r
1378         char* pm0;\r
1379         char* pm1;\r
1380         char* p;\r
1381         char* pNext;\r
1382         bResult = FALSE;\r
1383         Length = strlen(Input);\r
1384         if(pm0 = AllocateStringM(Length + 1))\r
1385         {\r
1386                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1387                 {\r
1388                         strcpy(pm0, Input);\r
1389                         p = pm0;\r
1390                         while(p)\r
1391                         {\r
1392                                 if(pNext = strchr(p, '.'))\r
1393                                 {\r
1394                                         *pNext = '\0';\r
1395                                         pNext++;\r
1396                                 }\r
1397                                 if(ConvertStringToPunycode(pm1, Length * 4, p))\r
1398                                         strcat(Output, pm1);\r
1399                                 if(pNext)\r
1400                                         strcat(Output, ".");\r
1401                                 p = pNext;\r
1402                         }\r
1403                         bResult = TRUE;\r
1404                         FreeDuplicatedString(pm1);\r
1405                 }\r
1406                 FreeDuplicatedString(pm0);\r
1407         }\r
1408         return bResult;\r
1409 }\r
1410 \r
1411 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1412 {\r
1413         HANDLE r = NULL;\r
1414         char* pa0 = NULL;\r
1415         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1416         {\r
1417                 if(ConvertNameToPunycode(pa0, name))\r
1418                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1419         }\r
1420         FreeDuplicatedString(pa0);\r
1421         return r;\r
1422 }\r
1423 \r
1424 static HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1425 {\r
1426         HANDLE r = NULL;\r
1427         char* pa0 = NULL;\r
1428         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1429         {\r
1430                 if(ConvertNameToPunycode(pa0, name))\r
1431                         r = WSAAsyncGetHostByNameIPv6(hWnd, wMsg, pa0, buf, buflen, Family);\r
1432         }\r
1433         FreeDuplicatedString(pa0);\r
1434         return r;\r
1435 }\r
1436 \r