OSDN Git Service

Add support for FTP over Implicit SSL/TLS (untested and please set the port number...
[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         *CancelCheckWork = NO;\r
661 \r
662         // UTF-8対応\r
663 //      hAsync = WSAAsyncGetHostByName(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
664         hAsync = WSAAsyncGetHostByNameM(hWndSocket, WM_ASYNC_DBASE, Name, Buf, Len);\r
665         if(hAsync != NULL)\r
666         {\r
667                 RegistAsyncTableDbase(hAsync);\r
668                 while((*CancelCheckWork == NO) && (AskAsyncDoneDbase(hAsync, &Error) != YES))\r
669                 {\r
670                         Sleep(1);\r
671                         if(BackgrndMessageProc() == YES)\r
672                                 *CancelCheckWork = YES;\r
673                 }\r
674 \r
675                 if(*CancelCheckWork == YES)\r
676                 {\r
677                         WSACancelAsyncRequest(hAsync);\r
678                 }\r
679                 else if(Error == 0)\r
680                 {\r
681                         Ret = (struct hostent *)Buf;\r
682                 }\r
683                 UnRegistAsyncTableDbase(hAsync);\r
684         }\r
685         return(Ret);\r
686 #else\r
687         return(gethostbyname(Name));\r
688 #endif\r
689 }\r
690 \r
691 \r
692 \r
693 \r
694 \r
695 SOCKET do_socket(int af, int type, int protocol)\r
696 {\r
697         SOCKET Ret;\r
698 \r
699         Ret = socket(af, type, protocol);\r
700         if(Ret != INVALID_SOCKET)\r
701         {\r
702                 RegistAsyncTable(Ret);\r
703         }\r
704 #if DBG_MSG\r
705         DoPrintf("# do_socket (S=%x)", Ret);\r
706 #endif\r
707         return(Ret);\r
708 }\r
709 \r
710 \r
711 \r
712 int do_closesocket(SOCKET s)\r
713 {\r
714 #if USE_THIS\r
715         int Ret;\r
716         int Error;\r
717         int CancelCheckWork;\r
718 \r
719 #if DBG_MSG\r
720         DoPrintf("# Start close (S=%x)", s);\r
721 #endif\r
722         CancelCheckWork = NO;\r
723 \r
724         // スレッド衝突のバグ修正\r
725         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
726         UnRegistAsyncTable(s);\r
727         // FTPS対応\r
728 //      Ret = closesocket(s);\r
729         Ret = closesocketS(s);\r
730         if(Ret == SOCKET_ERROR)\r
731         {\r
732                 Error = 0;\r
733                 while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CLOSE_BIT) != YES))\r
734                 {\r
735                         Sleep(1);\r
736                         if(BackgrndMessageProc() == YES)\r
737                                 CancelCheckWork = YES;\r
738                 }\r
739 \r
740                 if((CancelCheckWork == NO) && (Error == 0))\r
741                         Ret = 0;\r
742         }\r
743 \r
744         // スレッド衝突のバグ修正\r
745 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, 0);\r
746         if(BackgrndMessageProc() == YES)\r
747                 CancelCheckWork = YES;\r
748         // スレッド衝突のバグ修正\r
749 //      UnRegistAsyncTable(s);\r
750 \r
751 #if DBG_MSG\r
752         DoPrintf("# Exit close");\r
753 #endif\r
754         return(Ret);\r
755 #else\r
756         return(closesocket(s));\r
757 #endif\r
758 }\r
759 \r
760 \r
761 \r
762 \r
763 \r
764 \r
765 int do_connect(SOCKET s, const struct sockaddr *name, int namelen, int *CancelCheckWork)\r
766 {\r
767 #if USE_THIS\r
768         int Ret;\r
769         int Error;\r
770 \r
771 #if DBG_MSG\r
772         DoPrintf("# Start connect (S=%x)", s);\r
773 #endif\r
774         *CancelCheckWork = NO;\r
775 \r
776 #if DBG_MSG\r
777         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
778 #endif\r
779         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
780         if(Ret != SOCKET_ERROR)\r
781         {\r
782                 Ret = connect(s, name, namelen);\r
783                 if(Ret == SOCKET_ERROR)\r
784                 {\r
785                         do\r
786                         {\r
787                                 Error = 0;\r
788                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES))\r
789                                 {\r
790                                         Sleep(1);\r
791                                         if(BackgrndMessageProc() == YES)\r
792                                                 *CancelCheckWork = YES;\r
793                                 }\r
794 \r
795                                 if(*CancelCheckWork == YES)\r
796                                         break;\r
797                                 if(Error == 0)\r
798                                         Ret = 0;\r
799                                 else\r
800                                 {\r
801 //                                      Error = WSAGetLastError();\r
802                                         DoPrintf("#### Connect: Error=%d", Error);\r
803                                 }\r
804                         }\r
805                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
806                 }\r
807         }\r
808         else\r
809                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
810 \r
811 #if DBG_MSG\r
812         DoPrintf("# Exit connect (%d)", Ret);\r
813 #endif\r
814         return(Ret);\r
815 #else\r
816         return(connect(s, name, namelen));\r
817 #endif\r
818 }\r
819 \r
820 \r
821 \r
822 \r
823 \r
824 int do_listen(SOCKET s, int backlog)\r
825 {\r
826         int Ret;\r
827 \r
828         Ret = 1;\r
829 #if DBG_MSG\r
830         DoPrintf("# Start listen (S=%x)", s);\r
831         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
832 #endif\r
833 \r
834         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
835         if(Ret != SOCKET_ERROR)\r
836                 Ret = listen(s, backlog);\r
837 \r
838 #if DBG_MSG\r
839         DoPrintf("# Exit listen (%d)", Ret);\r
840 #endif\r
841         return(Ret);\r
842 }\r
843 \r
844 \r
845 \r
846 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
847 {\r
848 #if USE_THIS\r
849         SOCKET Ret2;\r
850         int CancelCheckWork;\r
851         int Error;\r
852 \r
853 #if DBG_MSG\r
854         DoPrintf("# Start accept (S=%x)", s);\r
855 #endif\r
856         CancelCheckWork = NO;\r
857         Ret2 = INVALID_SOCKET;\r
858         Error = 0;\r
859 \r
860         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES))\r
861         {\r
862                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
863                 {\r
864                         Error = 1;\r
865                         break;\r
866                 }\r
867                 Sleep(1);\r
868                 if(BackgrndMessageProc() == YES)\r
869                         CancelCheckWork = YES;\r
870         }\r
871 \r
872         if((CancelCheckWork == NO) && (Error == 0))\r
873         {\r
874                 do\r
875                 {\r
876                         Ret2 = accept(s, addr, addrlen);\r
877                         if(Ret2 != INVALID_SOCKET)\r
878                         {\r
879 #if DBG_MSG\r
880                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
881                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
882 #endif\r
883                                 RegistAsyncTable(Ret2);\r
884                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
885                                 {\r
886                                         do_closesocket(Ret2);\r
887                                         Ret2 = INVALID_SOCKET;\r
888                                 }\r
889                                 break;\r
890                         }\r
891                         Error = WSAGetLastError();\r
892                         Sleep(1);\r
893                         if(BackgrndMessageProc() == YES)\r
894                                 break;\r
895                 }\r
896                 while(Error == WSAEWOULDBLOCK);\r
897         }\r
898 \r
899 #if DBG_MSG\r
900         DoPrintf("# Exit accept");\r
901 #endif\r
902         return(Ret2);\r
903 #else\r
904         return(accept(s, addr, addrlen));\r
905 #endif\r
906 }\r
907 \r
908 \r
909 \r
910 \r
911 /*----- recv相当の関数 --------------------------------------------------------\r
912 *\r
913 *       Parameter\r
914 *               SOCKET s : ソケット\r
915 *               char *buf : データを読み込むバッファ\r
916 *               int len : 長さ\r
917 *               int flags : recvに与えるフラグ\r
918 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
919 *\r
920 *       Return Value\r
921 *               int : recvの戻り値と同じ\r
922 *\r
923 *       Note\r
924 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
925 *----------------------------------------------------------------------------*/\r
926 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
927 {\r
928 #if USE_THIS\r
929         int Ret;\r
930         time_t StartTime;\r
931         time_t ElapseTime;\r
932         int Error;\r
933 \r
934 #if DBG_MSG\r
935         DoPrintf("# Start recv (S=%x)", s);\r
936 #endif\r
937         *TimeOutErr = NO;\r
938         *CancelCheckWork = NO;\r
939         Ret = SOCKET_ERROR;\r
940         Error = 0;\r
941 \r
942         if(TimeOut != 0)\r
943                 time(&StartTime);\r
944 \r
945         // FTPS対応\r
946         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
947 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
948         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
949         {\r
950                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
951                 {\r
952                         Ret = 0;\r
953                         break;\r
954                 }\r
955                 Sleep(1);\r
956                 if(BackgrndMessageProc() == YES)\r
957                         *CancelCheckWork = YES;\r
958                 else if(TimeOut != 0)\r
959                 {\r
960                         time(&ElapseTime);\r
961                         ElapseTime -= StartTime;\r
962                         if(ElapseTime >= TimeOut)\r
963                         {\r
964                                 DoPrintf("do_recv timed out");\r
965                                 *TimeOutErr = YES;\r
966                                 *CancelCheckWork = YES;\r
967                         }\r
968                 }\r
969         }\r
970 \r
971         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
972         {\r
973                 do\r
974                 {\r
975 #if DBG_MSG\r
976                         DoPrintf("## recv()");\r
977 #endif\r
978 \r
979                         // FTPS対応\r
980 //                      Ret = recv(s, buf, len, flags);\r
981                         Ret = recvS(s, buf, len, flags);\r
982                         if(Ret != SOCKET_ERROR)\r
983                                 break;\r
984                         // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応\r
985                         if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES && recvS(s, buf, len, MSG_PEEK) <= 0)\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         *CancelCheckWork = NO;\r
1039         Ret = SOCKET_ERROR;\r
1040         Error = 0;\r
1041 \r
1042         if(TimeOut != 0)\r
1043                 time(&StartTime);\r
1044 \r
1045 #if DBG_MSG\r
1046         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1047 #endif\r
1048         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1049         if(BackgrndMessageProc() == YES)\r
1050                 *CancelCheckWork = YES;\r
1051 \r
1052         // FTPS対応\r
1053         // 送信バッファの空き確認には影響しないが念のため\r
1054 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1055         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1056         {\r
1057                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1058                 {\r
1059                         Error = 1;\r
1060                         break;\r
1061                 }\r
1062 \r
1063                 Sleep(1);\r
1064                 if(BackgrndMessageProc() == YES)\r
1065                         *CancelCheckWork = YES;\r
1066                 else if(TimeOut != 0)\r
1067                 {\r
1068                         time(&ElapseTime);\r
1069                         ElapseTime -= StartTime;\r
1070                         if(ElapseTime >= TimeOut)\r
1071                         {\r
1072                                 DoPrintf("do_write timed out");\r
1073                                 *TimeOutErr = YES;\r
1074                                 *CancelCheckWork = YES;\r
1075                         }\r
1076                 }\r
1077         }\r
1078 \r
1079         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1080         {\r
1081                 do\r
1082                 {\r
1083 #if DBG_MSG\r
1084                         DoPrintf("## send()");\r
1085 #endif\r
1086 \r
1087                         // FTPS対応\r
1088 //                      Ret = send(s, buf, len, flags);\r
1089                         Ret = sendS(s, buf, len, flags);\r
1090                         if(Ret != SOCKET_ERROR)\r
1091                         {\r
1092 #if DBG_MSG\r
1093                                 DoPrintf("## send() OK");\r
1094 #endif\r
1095                                 break;\r
1096                         }\r
1097                         // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応\r
1098                         if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1099                                 break;\r
1100                         Error = WSAGetLastError();\r
1101                         Sleep(1);\r
1102                         if(BackgrndMessageProc() == YES)\r
1103                                 break;\r
1104                         // FTPS対応\r
1105                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1106                         if(BackgrndMessageProc() == YES)\r
1107                                 *CancelCheckWork = YES;\r
1108                         else if(TimeOut != 0)\r
1109                         {\r
1110                                 time(&ElapseTime);\r
1111                                 ElapseTime -= StartTime;\r
1112                                 if(ElapseTime >= TimeOut)\r
1113                                 {\r
1114                                         DoPrintf("do_recv timed out");\r
1115                                         *TimeOutErr = YES;\r
1116                                         *CancelCheckWork = YES;\r
1117                                 }\r
1118                         }\r
1119                         if(*CancelCheckWork == YES)\r
1120                                 break;\r
1121                 }\r
1122                 while(Error == WSAEWOULDBLOCK);\r
1123         }\r
1124 \r
1125         if(BackgrndMessageProc() == YES)\r
1126                 Ret = SOCKET_ERROR;\r
1127 \r
1128 #if DBG_MSG\r
1129         DoPrintf("# Exit send (%d)", Ret);\r
1130 #endif\r
1131         return(Ret);\r
1132 #else\r
1133         return(send(s, buf, len, flags));\r
1134 #endif\r
1135 }\r
1136 \r
1137 \r
1138 /*----- \r
1139 *\r
1140 *       Parameter\r
1141 *\r
1142 *       Return Value\r
1143 *               int ステータス\r
1144 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1145 *----------------------------------------------------------------------------*/\r
1146 \r
1147 int CheckClosedAndReconnect(void)\r
1148 {\r
1149         int Error;\r
1150         int Sts;\r
1151 \r
1152 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1153 \r
1154         Sts = FFFTP_SUCCESS;\r
1155         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)\r
1156         {\r
1157                 Sts = ReConnectCmdSkt();\r
1158         }\r
1159         return(Sts);\r
1160 }\r
1161 \r
1162 \r
1163 \r
1164 // UTF-8対応\r
1165 \r
1166 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1167 {\r
1168         BOOL bResult;\r
1169         punycode_uint* pUnicode;\r
1170         punycode_uint* p;\r
1171         BOOL bNeeded;\r
1172         LPCSTR InputString;\r
1173         punycode_uint Length;\r
1174         punycode_uint OutputLength;\r
1175         bResult = FALSE;\r
1176         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1177         {\r
1178                 p = pUnicode;\r
1179                 bNeeded = FALSE;\r
1180                 InputString = Input;\r
1181                 Length = 0;\r
1182                 while(*InputString != '\0')\r
1183                 {\r
1184                         *p = 0;\r
1185                         if((*InputString & 0x80) == 0x00)\r
1186                                 *p |= (punycode_uint)*InputString & 0x7f;\r
1187                         else if((*InputString & 0xe0) == 0xc0)\r
1188                                 *p |= (punycode_uint)*InputString & 0x1f;\r
1189                         else if((*InputString & 0xf0) == 0xe0)\r
1190                                 *p |= (punycode_uint)*InputString & 0x0f;\r
1191                         else if((*InputString & 0xf8) == 0xf0)\r
1192                                 *p |= (punycode_uint)*InputString & 0x07;\r
1193                         else if((*InputString & 0xfc) == 0xf8)\r
1194                                 *p |= (punycode_uint)*InputString & 0x03;\r
1195                         else if((*InputString & 0xfe) == 0xfc)\r
1196                                 *p |= (punycode_uint)*InputString & 0x01;\r
1197                         InputString++;\r
1198                         while((*InputString & 0xc0) == 0x80)\r
1199                         {\r
1200                                 *p = *p << 6;\r
1201                                 *p |= (punycode_uint)*InputString & 0x3f;\r
1202                                 InputString++;\r
1203                         }\r
1204                         if(*p >= 0x80)\r
1205                                 bNeeded = TRUE;\r
1206                         p++;\r
1207                         Length++;\r
1208                 }\r
1209                 if(bNeeded)\r
1210                 {\r
1211                         if(Count >= strlen("xn--") + 1)\r
1212                         {\r
1213                                 strcpy(Output, "xn--");\r
1214                                 OutputLength = Count - strlen("xn--");\r
1215                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1216                                 {\r
1217                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1218                                         bResult = TRUE;\r
1219                                 }\r
1220                         }\r
1221                 }\r
1222                 free(pUnicode);\r
1223         }\r
1224         if(!bResult)\r
1225         {\r
1226                 if(Count >= strlen(Input) + 1)\r
1227                 {\r
1228                         strcpy(Output, Input);\r
1229                         bResult = TRUE;\r
1230                 }\r
1231         }\r
1232         return bResult;\r
1233 }\r
1234 \r
1235 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1236 {\r
1237         BOOL bResult;\r
1238         DWORD Length;\r
1239         char* pm0;\r
1240         char* pm1;\r
1241         char* p;\r
1242         char* pNext;\r
1243         bResult = FALSE;\r
1244         Length = strlen(Input);\r
1245         if(pm0 = AllocateStringM(Length + 1))\r
1246         {\r
1247                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1248                 {\r
1249                         strcpy(pm0, Input);\r
1250                         p = pm0;\r
1251                         while(p)\r
1252                         {\r
1253                                 if(pNext = strchr(p, '.'))\r
1254                                 {\r
1255                                         *pNext = '\0';\r
1256                                         pNext++;\r
1257                                 }\r
1258                                 if(ConvertStringToPunycode(pm1, Length * 4, p))\r
1259                                         strcat(Output, pm1);\r
1260                                 if(pNext)\r
1261                                         strcat(Output, ".");\r
1262                                 p = pNext;\r
1263                         }\r
1264                         bResult = TRUE;\r
1265                         FreeDuplicatedString(pm1);\r
1266                 }\r
1267                 FreeDuplicatedString(pm0);\r
1268         }\r
1269         return bResult;\r
1270 }\r
1271 \r
1272 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1273 {\r
1274         HANDLE r = NULL;\r
1275         char* pa0 = NULL;\r
1276         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1277         {\r
1278                 if(ConvertNameToPunycode(pa0, name))\r
1279                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1280         }\r
1281         FreeDuplicatedString(pa0);\r
1282         return r;\r
1283 }\r
1284 \r