OSDN Git Service

Fix bugs of receiving data on Windows 2000.
[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         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1050         // 毎回通知されたのはNT 4.0までのバグであり仕様ではない\r
1051         // XP以降は互換性のためか毎回通知される\r
1052 //      WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1053         if(BackgrndMessageProc() == YES)\r
1054                 *CancelCheckWork = YES;\r
1055 \r
1056         // FTPS対応\r
1057         // 送信バッファの空き確認には影響しないが念のため\r
1058 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1059         // Windows 2000でFD_WRITEが通知されないことがあるバグ修正\r
1060 //      while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1061 //      {\r
1062 //              if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1063 //              {\r
1064 //                      Error = 1;\r
1065 //                      break;\r
1066 //              }\r
1067 //\r
1068 //              Sleep(1);\r
1069 //              if(BackgrndMessageProc() == YES)\r
1070 //                      *CancelCheckWork = YES;\r
1071 //              else if(TimeOut != 0)\r
1072 //              {\r
1073 //                      time(&ElapseTime);\r
1074 //                      ElapseTime -= StartTime;\r
1075 //                      if(ElapseTime >= TimeOut)\r
1076 //                      {\r
1077 //                              DoPrintf("do_write timed out");\r
1078 //                              *TimeOutErr = YES;\r
1079 //                              *CancelCheckWork = YES;\r
1080 //                      }\r
1081 //              }\r
1082 //      }\r
1083 \r
1084         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1085         {\r
1086                 do\r
1087                 {\r
1088 #if DBG_MSG\r
1089                         DoPrintf("## send()");\r
1090 #endif\r
1091 \r
1092                         // FTPS対応\r
1093 //                      Ret = send(s, buf, len, flags);\r
1094                         Ret = sendS(s, buf, len, flags);\r
1095                         if(Ret != SOCKET_ERROR)\r
1096                         {\r
1097 #if DBG_MSG\r
1098                                 DoPrintf("## send() OK");\r
1099 #endif\r
1100                                 break;\r
1101                         }\r
1102                         Error = WSAGetLastError();\r
1103                         Sleep(1);\r
1104                         if(BackgrndMessageProc() == YES)\r
1105                                 break;\r
1106                         // FTPS対応\r
1107                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1108                         if(BackgrndMessageProc() == YES)\r
1109                                 *CancelCheckWork = YES;\r
1110                         else if(TimeOut != 0)\r
1111                         {\r
1112                                 time(&ElapseTime);\r
1113                                 ElapseTime -= StartTime;\r
1114                                 if(ElapseTime >= TimeOut)\r
1115                                 {\r
1116                                         DoPrintf("do_recv timed out");\r
1117                                         *TimeOutErr = YES;\r
1118                                         *CancelCheckWork = YES;\r
1119                                 }\r
1120                         }\r
1121                         if(*CancelCheckWork == YES)\r
1122                                 break;\r
1123                 }\r
1124                 while(Error == WSAEWOULDBLOCK);\r
1125         }\r
1126 \r
1127         if(BackgrndMessageProc() == YES)\r
1128                 Ret = SOCKET_ERROR;\r
1129 \r
1130 #if DBG_MSG\r
1131         DoPrintf("# Exit send (%d)", Ret);\r
1132 #endif\r
1133         return(Ret);\r
1134 #else\r
1135         return(send(s, buf, len, flags));\r
1136 #endif\r
1137 }\r
1138 \r
1139 \r
1140 // 同時接続対応\r
1141 void RemoveReceivedData(SOCKET s)\r
1142 {\r
1143         char buf[1024];\r
1144         int len;\r
1145         int Error;\r
1146         while((len = recvS(s, buf, sizeof(buf), MSG_PEEK)) >= 0)\r
1147         {\r
1148                 AskAsyncDone(s, &Error, FD_READ_BIT);\r
1149                 recvS(s, buf, len, 0);\r
1150         }\r
1151 }\r
1152 \r
1153 \r
1154 /*----- \r
1155 *\r
1156 *       Parameter\r
1157 *\r
1158 *       Return Value\r
1159 *               int ステータス\r
1160 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1161 *----------------------------------------------------------------------------*/\r
1162 \r
1163 int CheckClosedAndReconnect(void)\r
1164 {\r
1165         int Error;\r
1166         int Sts;\r
1167 \r
1168 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1169 \r
1170         Sts = FFFTP_SUCCESS;\r
1171         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)\r
1172         {\r
1173                 Sts = ReConnectCmdSkt();\r
1174         }\r
1175         return(Sts);\r
1176 }\r
1177 \r
1178 \r
1179 \r
1180 // UTF-8対応\r
1181 \r
1182 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1183 {\r
1184         BOOL bResult;\r
1185         punycode_uint* pUnicode;\r
1186         punycode_uint* p;\r
1187         BOOL bNeeded;\r
1188         LPCSTR InputString;\r
1189         punycode_uint Length;\r
1190         punycode_uint OutputLength;\r
1191         bResult = FALSE;\r
1192         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1193         {\r
1194                 p = pUnicode;\r
1195                 bNeeded = FALSE;\r
1196                 InputString = Input;\r
1197                 Length = 0;\r
1198                 while(*InputString != '\0')\r
1199                 {\r
1200                         *p = 0;\r
1201                         if((*InputString & 0x80) == 0x00)\r
1202                                 *p |= (punycode_uint)*InputString & 0x7f;\r
1203                         else if((*InputString & 0xe0) == 0xc0)\r
1204                                 *p |= (punycode_uint)*InputString & 0x1f;\r
1205                         else if((*InputString & 0xf0) == 0xe0)\r
1206                                 *p |= (punycode_uint)*InputString & 0x0f;\r
1207                         else if((*InputString & 0xf8) == 0xf0)\r
1208                                 *p |= (punycode_uint)*InputString & 0x07;\r
1209                         else if((*InputString & 0xfc) == 0xf8)\r
1210                                 *p |= (punycode_uint)*InputString & 0x03;\r
1211                         else if((*InputString & 0xfe) == 0xfc)\r
1212                                 *p |= (punycode_uint)*InputString & 0x01;\r
1213                         InputString++;\r
1214                         while((*InputString & 0xc0) == 0x80)\r
1215                         {\r
1216                                 *p = *p << 6;\r
1217                                 *p |= (punycode_uint)*InputString & 0x3f;\r
1218                                 InputString++;\r
1219                         }\r
1220                         if(*p >= 0x80)\r
1221                                 bNeeded = TRUE;\r
1222                         p++;\r
1223                         Length++;\r
1224                 }\r
1225                 if(bNeeded)\r
1226                 {\r
1227                         if(Count >= strlen("xn--") + 1)\r
1228                         {\r
1229                                 strcpy(Output, "xn--");\r
1230                                 OutputLength = Count - strlen("xn--");\r
1231                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1232                                 {\r
1233                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1234                                         bResult = TRUE;\r
1235                                 }\r
1236                         }\r
1237                 }\r
1238                 free(pUnicode);\r
1239         }\r
1240         if(!bResult)\r
1241         {\r
1242                 if(Count >= strlen(Input) + 1)\r
1243                 {\r
1244                         strcpy(Output, Input);\r
1245                         bResult = TRUE;\r
1246                 }\r
1247         }\r
1248         return bResult;\r
1249 }\r
1250 \r
1251 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1252 {\r
1253         BOOL bResult;\r
1254         DWORD Length;\r
1255         char* pm0;\r
1256         char* pm1;\r
1257         char* p;\r
1258         char* pNext;\r
1259         bResult = FALSE;\r
1260         Length = strlen(Input);\r
1261         if(pm0 = AllocateStringM(Length + 1))\r
1262         {\r
1263                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1264                 {\r
1265                         strcpy(pm0, Input);\r
1266                         p = pm0;\r
1267                         while(p)\r
1268                         {\r
1269                                 if(pNext = strchr(p, '.'))\r
1270                                 {\r
1271                                         *pNext = '\0';\r
1272                                         pNext++;\r
1273                                 }\r
1274                                 if(ConvertStringToPunycode(pm1, Length * 4, p))\r
1275                                         strcat(Output, pm1);\r
1276                                 if(pNext)\r
1277                                         strcat(Output, ".");\r
1278                                 p = pNext;\r
1279                         }\r
1280                         bResult = TRUE;\r
1281                         FreeDuplicatedString(pm1);\r
1282                 }\r
1283                 FreeDuplicatedString(pm0);\r
1284         }\r
1285         return bResult;\r
1286 }\r
1287 \r
1288 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1289 {\r
1290         HANDLE r = NULL;\r
1291         char* pa0 = NULL;\r
1292         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1293         {\r
1294                 if(ConvertNameToPunycode(pa0, name))\r
1295                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1296         }\r
1297         FreeDuplicatedString(pa0);\r
1298         return r;\r
1299 }\r
1300 \r