OSDN Git Service

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