OSDN Git Service

fb04a0fa82ccc392ae9409df8499120af770a1a4
[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                 // FTPS対応\r
783 //              Ret = connect(s, name, namelen);\r
784                 if(AskCryptMode() == CRYPT_FTPIS)\r
785                         Ret = connectS(s, name, namelen);\r
786                 else\r
787                         Ret = connect(s, name, namelen);\r
788                 if(Ret == SOCKET_ERROR)\r
789                 {\r
790                         do\r
791                         {\r
792                                 Error = 0;\r
793                                 while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_CONNECT_BIT) != YES))\r
794                                 {\r
795                                         Sleep(1);\r
796                                         if(BackgrndMessageProc() == YES)\r
797                                                 *CancelCheckWork = YES;\r
798                                 }\r
799 \r
800                                 if(*CancelCheckWork == YES)\r
801                                         break;\r
802                                 if(Error == 0)\r
803                                         Ret = 0;\r
804                                 else\r
805                                 {\r
806 //                                      Error = WSAGetLastError();\r
807                                         DoPrintf("#### Connect: Error=%d", Error);\r
808                                 }\r
809                         }\r
810                         while((Ret != 0) && (Error == WSAEWOULDBLOCK));\r
811                 }\r
812         }\r
813         else\r
814                 DoPrintf("#### Connect: AsyncSelect error (%d)", WSAGetLastError());\r
815 \r
816 #if DBG_MSG\r
817         DoPrintf("# Exit connect (%d)", Ret);\r
818 #endif\r
819         return(Ret);\r
820 #else\r
821         return(connect(s, name, namelen));\r
822 #endif\r
823 }\r
824 \r
825 \r
826 \r
827 \r
828 \r
829 int do_listen(SOCKET s, int backlog)\r
830 {\r
831         int Ret;\r
832 \r
833         Ret = 1;\r
834 #if DBG_MSG\r
835         DoPrintf("# Start listen (S=%x)", s);\r
836         DoPrintf("## Async set: FD_CLOSE|FD_ACCEPT");\r
837 #endif\r
838 \r
839         Ret = WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CLOSE | FD_ACCEPT);\r
840         if(Ret != SOCKET_ERROR)\r
841                 Ret = listen(s, backlog);\r
842 \r
843 #if DBG_MSG\r
844         DoPrintf("# Exit listen (%d)", Ret);\r
845 #endif\r
846         return(Ret);\r
847 }\r
848 \r
849 \r
850 \r
851 SOCKET do_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
852 {\r
853 #if USE_THIS\r
854         SOCKET Ret2;\r
855         int CancelCheckWork;\r
856         int Error;\r
857 \r
858 #if DBG_MSG\r
859         DoPrintf("# Start accept (S=%x)", s);\r
860 #endif\r
861         CancelCheckWork = NO;\r
862         Ret2 = INVALID_SOCKET;\r
863         Error = 0;\r
864 \r
865         while((CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_ACCEPT_BIT) != YES))\r
866         {\r
867                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
868                 {\r
869                         Error = 1;\r
870                         break;\r
871                 }\r
872                 Sleep(1);\r
873                 if(BackgrndMessageProc() == YES)\r
874                         CancelCheckWork = YES;\r
875         }\r
876 \r
877         if((CancelCheckWork == NO) && (Error == 0))\r
878         {\r
879                 do\r
880                 {\r
881                         // FTPS対応\r
882 //                      Ret2 = accept(s, addr, addrlen);\r
883                         if(AskCryptMode() == CRYPT_FTPIS)\r
884                                 Ret2 = acceptS(s, addr, addrlen);\r
885                         else\r
886                                 Ret2 = accept(s, addr, addrlen);\r
887                         if(Ret2 != INVALID_SOCKET)\r
888                         {\r
889 #if DBG_MSG\r
890                                 DoPrintf("## do_sccept (S=%x)", Ret2);\r
891                                 DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
892 #endif\r
893                                 RegistAsyncTable(Ret2);\r
894                                 if(WSAAsyncSelect(Ret2, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE) == SOCKET_ERROR)\r
895                                 {\r
896                                         do_closesocket(Ret2);\r
897                                         Ret2 = INVALID_SOCKET;\r
898                                 }\r
899                                 break;\r
900                         }\r
901                         Error = WSAGetLastError();\r
902                         Sleep(1);\r
903                         if(BackgrndMessageProc() == YES)\r
904                                 break;\r
905                 }\r
906                 while(Error == WSAEWOULDBLOCK);\r
907         }\r
908 \r
909 #if DBG_MSG\r
910         DoPrintf("# Exit accept");\r
911 #endif\r
912         return(Ret2);\r
913 #else\r
914         return(accept(s, addr, addrlen));\r
915 #endif\r
916 }\r
917 \r
918 \r
919 \r
920 \r
921 /*----- recv相当の関数 --------------------------------------------------------\r
922 *\r
923 *       Parameter\r
924 *               SOCKET s : ソケット\r
925 *               char *buf : データを読み込むバッファ\r
926 *               int len : 長さ\r
927 *               int flags : recvに与えるフラグ\r
928 *               int *TimeOutErr : タイムアウトしたかどうかを返すワーク\r
929 *\r
930 *       Return Value\r
931 *               int : recvの戻り値と同じ\r
932 *\r
933 *       Note\r
934 *               タイムアウトの時は TimeOut=YES、Ret=SOCKET_ERROR になる\r
935 *----------------------------------------------------------------------------*/\r
936 int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
937 {\r
938 #if USE_THIS\r
939         int Ret;\r
940         time_t StartTime;\r
941         time_t ElapseTime;\r
942         int Error;\r
943 \r
944 #if DBG_MSG\r
945         DoPrintf("# Start recv (S=%x)", s);\r
946 #endif\r
947         *TimeOutErr = NO;\r
948         *CancelCheckWork = NO;\r
949         Ret = SOCKET_ERROR;\r
950         Error = 0;\r
951 \r
952         if(TimeOut != 0)\r
953                 time(&StartTime);\r
954 \r
955         // FTPS対応\r
956         // OpenSSLでは受信確認はFD_READが複数回受信される可能性がある\r
957 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
958         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_READ_BIT) != YES))\r
959         {\r
960                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
961                 {\r
962                         Ret = 0;\r
963                         break;\r
964                 }\r
965                 Sleep(1);\r
966                 if(BackgrndMessageProc() == YES)\r
967                         *CancelCheckWork = YES;\r
968                 else if(TimeOut != 0)\r
969                 {\r
970                         time(&ElapseTime);\r
971                         ElapseTime -= StartTime;\r
972                         if(ElapseTime >= TimeOut)\r
973                         {\r
974                                 DoPrintf("do_recv timed out");\r
975                                 *TimeOutErr = YES;\r
976                                 *CancelCheckWork = YES;\r
977                         }\r
978                 }\r
979         }\r
980 \r
981         if(/*(Ret != 0) && */(Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
982         {\r
983                 do\r
984                 {\r
985 #if DBG_MSG\r
986                         DoPrintf("## recv()");\r
987 #endif\r
988 \r
989                         // FTPS対応\r
990 //                      Ret = recv(s, buf, len, flags);\r
991                         Ret = recvS(s, buf, len, flags);\r
992                         if(Ret != SOCKET_ERROR)\r
993                                 break;\r
994                         // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応\r
995                         if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES && recvS(s, buf, len, MSG_PEEK) <= 0)\r
996                                 break;\r
997                         Error = WSAGetLastError();\r
998                         Sleep(1);\r
999                         if(BackgrndMessageProc() == YES)\r
1000                                 break;\r
1001                         // FTPS対応\r
1002                         // 受信確認をバイパスしたためここでタイムアウトの確認\r
1003                         if(BackgrndMessageProc() == YES)\r
1004                                 *CancelCheckWork = YES;\r
1005                         else if(TimeOut != 0)\r
1006                         {\r
1007                                 time(&ElapseTime);\r
1008                                 ElapseTime -= StartTime;\r
1009                                 if(ElapseTime >= TimeOut)\r
1010                                 {\r
1011                                         DoPrintf("do_recv timed out");\r
1012                                         *TimeOutErr = YES;\r
1013                                         *CancelCheckWork = YES;\r
1014                                 }\r
1015                         }\r
1016                         if(*CancelCheckWork == YES)\r
1017                                 break;\r
1018                 }\r
1019                 while(Error == WSAEWOULDBLOCK);\r
1020         }\r
1021 \r
1022         if(BackgrndMessageProc() == YES)\r
1023                 Ret = SOCKET_ERROR;\r
1024 \r
1025 #if DBG_MSG\r
1026         DoPrintf("# Exit recv (%d)", Ret);\r
1027 #endif\r
1028         return(Ret);\r
1029 #else\r
1030         return(recv(s, buf, len, flags));\r
1031 #endif\r
1032 }\r
1033 \r
1034 \r
1035 \r
1036 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork)\r
1037 {\r
1038 #if USE_THIS\r
1039         int Ret;\r
1040         time_t StartTime;\r
1041         time_t ElapseTime;\r
1042         int Error;\r
1043 \r
1044 #if DBG_MSG\r
1045         DoPrintf("# Start send (S=%x)", s);\r
1046 #endif\r
1047         *TimeOutErr = NO;\r
1048         *CancelCheckWork = NO;\r
1049         Ret = SOCKET_ERROR;\r
1050         Error = 0;\r
1051 \r
1052         if(TimeOut != 0)\r
1053                 time(&StartTime);\r
1054 \r
1055 #if DBG_MSG\r
1056         DoPrintf("## Async set: FD_CONNECT|FD_CLOSE|FD_ACCEPT|FD_READ|FD_WRITE");\r
1057 #endif\r
1058         WSAAsyncSelect(s, hWndSocket, WM_ASYNC_SOCKET, FD_CONNECT | FD_CLOSE | FD_ACCEPT | FD_READ | FD_WRITE);\r
1059         if(BackgrndMessageProc() == YES)\r
1060                 *CancelCheckWork = YES;\r
1061 \r
1062         // FTPS対応\r
1063         // 送信バッファの空き確認には影響しないが念のため\r
1064 //      while((*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1065         while(!IsSSLAttached(s) && (*CancelCheckWork == NO) && (AskAsyncDone(s, &Error, FD_WRITE_BIT) != YES))\r
1066         {\r
1067                 if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1068                 {\r
1069                         Error = 1;\r
1070                         break;\r
1071                 }\r
1072 \r
1073                 Sleep(1);\r
1074                 if(BackgrndMessageProc() == YES)\r
1075                         *CancelCheckWork = YES;\r
1076                 else if(TimeOut != 0)\r
1077                 {\r
1078                         time(&ElapseTime);\r
1079                         ElapseTime -= StartTime;\r
1080                         if(ElapseTime >= TimeOut)\r
1081                         {\r
1082                                 DoPrintf("do_write timed out");\r
1083                                 *TimeOutErr = YES;\r
1084                                 *CancelCheckWork = YES;\r
1085                         }\r
1086                 }\r
1087         }\r
1088 \r
1089         if((Error == 0) && (*CancelCheckWork == NO) && (*TimeOutErr == NO))\r
1090         {\r
1091                 do\r
1092                 {\r
1093 #if DBG_MSG\r
1094                         DoPrintf("## send()");\r
1095 #endif\r
1096 \r
1097                         // FTPS対応\r
1098 //                      Ret = send(s, buf, len, flags);\r
1099                         Ret = sendS(s, buf, len, flags);\r
1100                         if(Ret != SOCKET_ERROR)\r
1101                         {\r
1102 #if DBG_MSG\r
1103                                 DoPrintf("## send() OK");\r
1104 #endif\r
1105                                 break;\r
1106                         }\r
1107                         // 何故か一部のホストとWindows 2000の組み合わせで通信できないバグに暫定対応\r
1108                         if(AskAsyncDone(s, &Error, FD_CLOSE_BIT) == YES)\r
1109                                 break;\r
1110                         Error = WSAGetLastError();\r
1111                         Sleep(1);\r
1112                         if(BackgrndMessageProc() == YES)\r
1113                                 break;\r
1114                         // FTPS対応\r
1115                         // 送信バッファ確認をバイパスしたためここでタイムアウトの確認\r
1116                         if(BackgrndMessageProc() == YES)\r
1117                                 *CancelCheckWork = YES;\r
1118                         else if(TimeOut != 0)\r
1119                         {\r
1120                                 time(&ElapseTime);\r
1121                                 ElapseTime -= StartTime;\r
1122                                 if(ElapseTime >= TimeOut)\r
1123                                 {\r
1124                                         DoPrintf("do_recv timed out");\r
1125                                         *TimeOutErr = YES;\r
1126                                         *CancelCheckWork = YES;\r
1127                                 }\r
1128                         }\r
1129                         if(*CancelCheckWork == YES)\r
1130                                 break;\r
1131                 }\r
1132                 while(Error == WSAEWOULDBLOCK);\r
1133         }\r
1134 \r
1135         if(BackgrndMessageProc() == YES)\r
1136                 Ret = SOCKET_ERROR;\r
1137 \r
1138 #if DBG_MSG\r
1139         DoPrintf("# Exit send (%d)", Ret);\r
1140 #endif\r
1141         return(Ret);\r
1142 #else\r
1143         return(send(s, buf, len, flags));\r
1144 #endif\r
1145 }\r
1146 \r
1147 \r
1148 /*----- \r
1149 *\r
1150 *       Parameter\r
1151 *\r
1152 *       Return Value\r
1153 *               int ステータス\r
1154 *                       FFFTP_SUCCESS/FFFTP_FAIL\r
1155 *----------------------------------------------------------------------------*/\r
1156 \r
1157 int CheckClosedAndReconnect(void)\r
1158 {\r
1159         int Error;\r
1160         int Sts;\r
1161 \r
1162 //SetTaskMsg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");\r
1163 \r
1164         Sts = FFFTP_SUCCESS;\r
1165         if(AskAsyncDone(AskCmdCtrlSkt(), &Error, FD_CLOSE_BIT) == YES)\r
1166         {\r
1167                 Sts = ReConnectCmdSkt();\r
1168         }\r
1169         return(Sts);\r
1170 }\r
1171 \r
1172 \r
1173 \r
1174 // UTF-8対応\r
1175 \r
1176 static BOOL ConvertStringToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1177 {\r
1178         BOOL bResult;\r
1179         punycode_uint* pUnicode;\r
1180         punycode_uint* p;\r
1181         BOOL bNeeded;\r
1182         LPCSTR InputString;\r
1183         punycode_uint Length;\r
1184         punycode_uint OutputLength;\r
1185         bResult = FALSE;\r
1186         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1187         {\r
1188                 p = pUnicode;\r
1189                 bNeeded = FALSE;\r
1190                 InputString = Input;\r
1191                 Length = 0;\r
1192                 while(*InputString != '\0')\r
1193                 {\r
1194                         *p = 0;\r
1195                         if((*InputString & 0x80) == 0x00)\r
1196                                 *p |= (punycode_uint)*InputString & 0x7f;\r
1197                         else if((*InputString & 0xe0) == 0xc0)\r
1198                                 *p |= (punycode_uint)*InputString & 0x1f;\r
1199                         else if((*InputString & 0xf0) == 0xe0)\r
1200                                 *p |= (punycode_uint)*InputString & 0x0f;\r
1201                         else if((*InputString & 0xf8) == 0xf0)\r
1202                                 *p |= (punycode_uint)*InputString & 0x07;\r
1203                         else if((*InputString & 0xfc) == 0xf8)\r
1204                                 *p |= (punycode_uint)*InputString & 0x03;\r
1205                         else if((*InputString & 0xfe) == 0xfc)\r
1206                                 *p |= (punycode_uint)*InputString & 0x01;\r
1207                         InputString++;\r
1208                         while((*InputString & 0xc0) == 0x80)\r
1209                         {\r
1210                                 *p = *p << 6;\r
1211                                 *p |= (punycode_uint)*InputString & 0x3f;\r
1212                                 InputString++;\r
1213                         }\r
1214                         if(*p >= 0x80)\r
1215                                 bNeeded = TRUE;\r
1216                         p++;\r
1217                         Length++;\r
1218                 }\r
1219                 if(bNeeded)\r
1220                 {\r
1221                         if(Count >= strlen("xn--") + 1)\r
1222                         {\r
1223                                 strcpy(Output, "xn--");\r
1224                                 OutputLength = Count - strlen("xn--");\r
1225                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1226                                 {\r
1227                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1228                                         bResult = TRUE;\r
1229                                 }\r
1230                         }\r
1231                 }\r
1232                 free(pUnicode);\r
1233         }\r
1234         if(!bResult)\r
1235         {\r
1236                 if(Count >= strlen(Input) + 1)\r
1237                 {\r
1238                         strcpy(Output, Input);\r
1239                         bResult = TRUE;\r
1240                 }\r
1241         }\r
1242         return bResult;\r
1243 }\r
1244 \r
1245 static BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1246 {\r
1247         BOOL bResult;\r
1248         DWORD Length;\r
1249         char* pm0;\r
1250         char* pm1;\r
1251         char* p;\r
1252         char* pNext;\r
1253         bResult = FALSE;\r
1254         Length = strlen(Input);\r
1255         if(pm0 = AllocateStringM(Length + 1))\r
1256         {\r
1257                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1258                 {\r
1259                         strcpy(pm0, Input);\r
1260                         p = pm0;\r
1261                         while(p)\r
1262                         {\r
1263                                 if(pNext = strchr(p, '.'))\r
1264                                 {\r
1265                                         *pNext = '\0';\r
1266                                         pNext++;\r
1267                                 }\r
1268                                 if(ConvertStringToPunycode(pm1, Length * 4, p))\r
1269                                         strcat(Output, pm1);\r
1270                                 if(pNext)\r
1271                                         strcat(Output, ".");\r
1272                                 p = pNext;\r
1273                         }\r
1274                         bResult = TRUE;\r
1275                         FreeDuplicatedString(pm1);\r
1276                 }\r
1277                 FreeDuplicatedString(pm0);\r
1278         }\r
1279         return bResult;\r
1280 }\r
1281 \r
1282 static HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1283 {\r
1284         HANDLE r = NULL;\r
1285         char* pa0 = NULL;\r
1286         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1287         {\r
1288                 if(ConvertNameToPunycode(pa0, name))\r
1289                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1290         }\r
1291         FreeDuplicatedString(pa0);\r
1292         return r;\r
1293 }\r
1294 \r