OSDN Git Service

Change OpenSSL context mode flags.
[ffftp/ffftp.git] / putty / mbswrapper.c
1 // mbswrapper.c\r
2 // Copyright (C) 2011 Suguru Kawamoto\r
3 // マルチバイト文字ワイド文字APIラッパー\r
4 // マルチバイト文字はUTF-8、ワイド文字はUTF-16であるものとする\r
5 // 全ての制御用の文字はASCIIの範囲であるため、Shift_JISとUTF-8間の変換は不要\r
6 \r
7 #define UNICODE\r
8 #define _UNICODE\r
9 \r
10 #include <stdio.h>\r
11 #include <tchar.h>\r
12 #include <direct.h>\r
13 #include <windows.h>\r
14 #include <commctrl.h>\r
15 #include <shlobj.h>\r
16 #include <htmlhelp.h>\r
17 \r
18 #define DO_NOT_REPLACE\r
19 #include "mbswrapper.h"\r
20 \r
21 // マルチバイト文字列からワイド文字列へ変換\r
22 int MtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)\r
23 {\r
24         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
25                 return 0;\r
26         if(pDst)\r
27                 return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, pDst, size);\r
28         return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, NULL, 0);\r
29 }\r
30 \r
31 // ワイド文字列からマルチバイト文字列へ変換\r
32 int WtoM(LPSTR pDst, int size, LPCWSTR pSrc, int count)\r
33 {\r
34         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
35                 return 0;\r
36         if(pDst)\r
37                 return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, pDst, size, NULL, NULL);\r
38         return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, NULL, 0, NULL, NULL);\r
39 }\r
40 \r
41 // Shift_JIS文字列からワイド文字列へ変換\r
42 int AtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)\r
43 {\r
44         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
45                 return 0;\r
46         if(pDst)\r
47                 return MultiByteToWideChar(CP_ACP, 0, pSrc, count, pDst, size);\r
48         return MultiByteToWideChar(CP_ACP, 0, pSrc, count, NULL, 0);\r
49 }\r
50 \r
51 // ワイド文字列からShift_JIS文字列へ変換\r
52 int WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)\r
53 {\r
54         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
55                 return 0;\r
56         if(pDst)\r
57                 return WideCharToMultiByte(CP_ACP, 0, pSrc, count, pDst, size, NULL, NULL);\r
58         return WideCharToMultiByte(CP_ACP, 0, pSrc, count, NULL, 0, NULL, NULL);\r
59 }\r
60 \r
61 // マルチバイト文字列バッファ終端を強制的にNULLで置換\r
62 int TerminateStringM(LPSTR lpString, int size)\r
63 {\r
64         int i;\r
65         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)\r
66                 return 0;\r
67         for(i = 0; i < size; i++)\r
68         {\r
69                 if(lpString[i] == '\0')\r
70                         return i;\r
71         }\r
72         i--;\r
73         lpString[i] = '\0';\r
74         return i;\r
75 }\r
76 \r
77 // ワイド文字列バッファ終端を強制的にNULLで置換\r
78 int TerminateStringW(LPWSTR lpString, int size)\r
79 {\r
80         int i;\r
81         if(lpString < (LPWSTR)0x00010000 || lpString == (LPWSTR)~0)\r
82                 return 0;\r
83         for(i = 0; i < size; i++)\r
84         {\r
85                 if(lpString[i] == L'\0')\r
86                         return i;\r
87         }\r
88         i--;\r
89         lpString[i] = L'\0';\r
90         return i;\r
91 }\r
92 \r
93 // Shift_JIS文字列バッファ終端を強制的にNULLで置換\r
94 int TerminateStringA(LPSTR lpString, int size)\r
95 {\r
96         int i;\r
97         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)\r
98                 return 0;\r
99         for(i = 0; i < size; i++)\r
100         {\r
101                 if(lpString[i] == '\0')\r
102                         return i;\r
103         }\r
104         i--;\r
105         lpString[i] = '\0';\r
106         return i;\r
107 }\r
108 \r
109 // NULL区切り複数マルチバイト文字列の長さを取得\r
110 size_t GetMultiStringLengthM(LPCSTR lpString)\r
111 {\r
112         size_t i;\r
113         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
114                 return 0;\r
115         i = 0;\r
116         while(lpString[i] != '\0' || lpString[i + 1] != '\0')\r
117         {\r
118                 i++;\r
119         }\r
120         i++;\r
121         return i;\r
122 }\r
123 \r
124 // NULL区切り複数ワイド文字列の長さを取得\r
125 size_t GetMultiStringLengthW(LPCWSTR lpString)\r
126 {\r
127         size_t i;\r
128         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
129                 return 0;\r
130         i = 0;\r
131         while(lpString[i] != L'\0' || lpString[i + 1] != L'\0')\r
132         {\r
133                 i++;\r
134         }\r
135         i++;\r
136         return i;\r
137 }\r
138 \r
139 // NULL区切り複数Shift_JIS文字列の長さを取得\r
140 size_t GetMultiStringLengthA(LPCSTR lpString)\r
141 {\r
142         size_t i;\r
143         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
144                 return 0;\r
145         i = 0;\r
146         while(lpString[i] != '\0' || lpString[i + 1] != '\0')\r
147         {\r
148                 i++;\r
149         }\r
150         i++;\r
151         return i;\r
152 }\r
153 \r
154 // NULL区切りマルチバイト文字列からワイド文字列へ変換\r
155 int MtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)\r
156 {\r
157         int i;\r
158         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
159                 return 0;\r
160         if(!pDst)\r
161                 return GetMultiStringLengthM(pSrc);\r
162         i = 0;\r
163         while(*pSrc != '\0')\r
164         {\r
165                 i += MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1);\r
166                 pSrc += strlen(pSrc) + 1;\r
167         }\r
168         pDst[i] = L'\0';\r
169         return i;\r
170 }\r
171 \r
172 // NULL区切りワイド文字列からマルチバイト文字列へ変換\r
173 int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)\r
174 {\r
175         int i;\r
176         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
177                 return 0;\r
178         if(!pDst)\r
179                 return GetMultiStringLengthW(pSrc);\r
180         i = 0;\r
181         while(*pSrc != L'\0')\r
182         {\r
183                 i += WideCharToMultiByte(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);\r
184                 pSrc += wcslen(pSrc) + 1;\r
185         }\r
186         pDst[i] = '\0';\r
187         return i;\r
188 }\r
189 \r
190 // NULL区切りShift_JIS文字列からワイド文字列へ変換\r
191 int AtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)\r
192 {\r
193         int i;\r
194         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
195                 return 0;\r
196         if(!pDst)\r
197                 return GetMultiStringLengthA(pSrc);\r
198         i = 0;\r
199         while(*pSrc != '\0')\r
200         {\r
201                 i += MultiByteToWideChar(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1);\r
202                 pSrc += strlen(pSrc) + 1;\r
203         }\r
204         pDst[i] = L'\0';\r
205         return i;\r
206 }\r
207 \r
208 // NULL区切りワイド文字列からShift_JIS文字列へ変換\r
209 int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)\r
210 {\r
211         int i;\r
212         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
213                 return 0;\r
214         if(!pDst)\r
215                 return GetMultiStringLengthW(pSrc);\r
216         i = 0;\r
217         while(*pSrc != L'\0')\r
218         {\r
219                 i += WideCharToMultiByte(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);\r
220                 pSrc += wcslen(pSrc) + 1;\r
221         }\r
222         pDst[i] = '\0';\r
223         return i;\r
224 }\r
225 \r
226 // マルチバイト文字列用のメモリを確保\r
227 char* AllocateStringM(int size)\r
228 {\r
229         char* p;\r
230         // 0が指定される場合があるため1文字分追加\r
231         p = (char*)malloc(sizeof(char) * (size + 1));\r
232         // 念のため先頭にNULL文字を代入\r
233         if(p)\r
234                 *p = '\0';\r
235         return p;\r
236 }\r
237 \r
238 // ワイド文字列用のメモリを確保\r
239 wchar_t* AllocateStringW(int size)\r
240 {\r
241         wchar_t* p;\r
242         // 0が指定される場合があるため1文字分追加\r
243         p = (wchar_t*)malloc(sizeof(wchar_t) * (size + 1));\r
244         // 念のため先頭にNULL文字を代入\r
245         if(p)\r
246                 *p = L'\0';\r
247         return p;\r
248 }\r
249 \r
250 // Shift_JIS文字列用のメモリを確保\r
251 char* AllocateStringA(int size)\r
252 {\r
253         char* p;\r
254         // 0が指定される場合があるため1文字分追加\r
255         p = (char*)malloc(sizeof(char) * (size + 1));\r
256         // 念のため先頭にNULL文字を代入\r
257         if(p)\r
258                 *p = '\0';\r
259         return p;\r
260 }\r
261 \r
262 // メモリを確保してマルチバイト文字列からワイド文字列へ変換\r
263 // リソースIDならば元の値を返す\r
264 wchar_t* DuplicateMtoW(LPCSTR lpString, int c)\r
265 {\r
266         wchar_t* p;\r
267         int i;\r
268         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
269                 return (wchar_t*)lpString;\r
270         if(c < 0)\r
271                 c = strlen(lpString);\r
272         p = AllocateStringW(MtoW(NULL, 0, lpString, c) + 1);\r
273         if(p)\r
274         {\r
275                 i = MtoW(p, 65535, lpString, c);\r
276                 p[i] = L'\0';\r
277         }\r
278         return p;\r
279 }\r
280 \r
281 // 指定したサイズのメモリを確保してマルチバイト文字列からワイド文字列へ変換\r
282 // リソースIDならば元の値を返す\r
283 wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)\r
284 {\r
285         wchar_t* p;\r
286         int i;\r
287         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
288                 return (wchar_t*)lpString;\r
289         if(c < 0)\r
290                 c = strlen(lpString);\r
291         p = AllocateStringW(size);\r
292         if(p)\r
293         {\r
294                 i = MtoW(p, size, lpString, c);\r
295                 p[i] = L'\0';\r
296         }\r
297         return p;\r
298 }\r
299 \r
300 // メモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換\r
301 // リソースIDならば元の値を返す\r
302 wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)\r
303 {\r
304         int count;\r
305         wchar_t* p;\r
306         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
307                 return (wchar_t*)lpString;\r
308         count = GetMultiStringLengthM(lpString) + 1;\r
309         p = AllocateStringW(count);\r
310         if(p)\r
311                 MtoW(p, count, lpString, count);\r
312         return p;\r
313 }\r
314 \r
315 // 指定したサイズのメモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換\r
316 // リソースIDならば元の値を返す\r
317 wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)\r
318 {\r
319         int count;\r
320         wchar_t* p;\r
321         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
322                 return (wchar_t*)lpString;\r
323         count = GetMultiStringLengthM(lpString) + 1;\r
324         p = AllocateStringW(size);\r
325         if(p)\r
326         {\r
327                 MtoW(p, size, lpString, count);\r
328                 p[size - 2] = L'\0';\r
329                 p[size - 1] = L'\0';\r
330         }\r
331         return p;\r
332 }\r
333 \r
334 // メモリを確保してワイド文字列からマルチバイト文字列へ変換\r
335 // リソースIDならば元の値を返す\r
336 char* DuplicateWtoM(LPCWSTR lpString, int c)\r
337 {\r
338         char* p;\r
339         int i;\r
340         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
341                 return (char*)lpString;\r
342         if(c < 0)\r
343                 c = wcslen(lpString);\r
344         p = AllocateStringM(WtoM(NULL, 0, lpString, c) + 1);\r
345         if(p)\r
346         {\r
347                 i = WtoM(p, 65535, lpString, c);\r
348                 p[i] = L'\0';\r
349         }\r
350         return p;\r
351 }\r
352 \r
353 // メモリを確保してShift_JIS文字列からワイド文字列へ変換\r
354 // リソースIDならば元の値を返す\r
355 wchar_t* DuplicateAtoW(LPCSTR lpString, int c)\r
356 {\r
357         wchar_t* p;\r
358         int i;\r
359         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
360                 return (wchar_t*)lpString;\r
361         if(c < 0)\r
362                 c = strlen(lpString);\r
363         p = AllocateStringW(AtoW(NULL, 0, lpString, c) + 1);\r
364         if(p)\r
365         {\r
366                 i = AtoW(p, 65535, lpString, c);\r
367                 p[i] = L'\0';\r
368         }\r
369         return p;\r
370 }\r
371 \r
372 // メモリを確保してワイド文字列からShift_JIS文字列へ変換\r
373 // リソースIDならば元の値を返す\r
374 char* DuplicateWtoA(LPCWSTR lpString, int c)\r
375 {\r
376         char* p;\r
377         int i;\r
378         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
379                 return (char*)lpString;\r
380         if(c < 0)\r
381                 c = wcslen(lpString);\r
382         p = AllocateStringA(WtoA(NULL, 0, lpString, c) + 1);\r
383         if(p)\r
384         {\r
385                 i = WtoA(p, 65535, lpString, c);\r
386                 p[i] = L'\0';\r
387         }\r
388         return p;\r
389 }\r
390 \r
391 // マルチバイト文字列からコードポイントと次のポインタを取得\r
392 // エンコードが不正な場合は0x80000000を返す\r
393 DWORD GetNextCharM(LPCSTR lpString, LPCSTR pLimit, LPCSTR* ppNext)\r
394 {\r
395         DWORD Code;\r
396         int i;\r
397         Code = 0;\r
398         i = -1;\r
399         if(!pLimit)\r
400                 pLimit = (LPCSTR)(~0);\r
401         if(lpString < pLimit)\r
402         {\r
403                 if((*lpString & 0xfe) == 0xfc)\r
404                 {\r
405                         i = 5;\r
406                         Code |= (DWORD)*lpString & 0x01;\r
407                 }\r
408                 else if((*lpString & 0xfc) == 0xf8)\r
409                 {\r
410                         i = 4;\r
411                         Code |= (DWORD)*lpString & 0x03;\r
412                 }\r
413                 else if((*lpString & 0xf8) == 0xf0)\r
414                 {\r
415                         i = 3;\r
416                         Code |= (DWORD)*lpString & 0x07;\r
417                 }\r
418                 else if((*lpString & 0xf0) == 0xe0)\r
419                 {\r
420                         i = 2;\r
421                         Code |= (DWORD)*lpString & 0x0f;\r
422                 }\r
423                 else if((*lpString & 0xe0) == 0xc0)\r
424                 {\r
425                         i = 1;\r
426                         Code |= (DWORD)*lpString & 0x1f;\r
427                 }\r
428                 else if((*lpString & 0x80) == 0x00)\r
429                 {\r
430                         i = 0;\r
431                         Code |= (DWORD)*lpString & 0x7f;\r
432                 }\r
433                 lpString++;\r
434                 while(lpString < pLimit && i > 0 && (*lpString & 0xc0) == 0x80)\r
435                 {\r
436                         i--;\r
437                         Code = Code << 6;\r
438                         Code |= (DWORD)*lpString & 0x3f;\r
439                         lpString++;\r
440                 }\r
441         }\r
442         if(i != 0)\r
443                 Code = 0x80000000;\r
444         if(ppNext)\r
445                 *ppNext = lpString;\r
446         return Code;\r
447 }\r
448 \r
449 // マルチバイト文字列へコードポイントの文字を追加して次のポインタを取得\r
450 // 文字の長さを返す\r
451 int PutNextCharM(LPSTR lpString, LPSTR pLimit, LPSTR* ppNext, DWORD Code)\r
452 {\r
453         int Count;\r
454         int i;\r
455         Count = 0;\r
456         i = -1;\r
457         if(!pLimit)\r
458                 pLimit = (LPSTR)(~0);\r
459         if(lpString < pLimit)\r
460         {\r
461                 if(Code & 0x7c000000)\r
462                 {\r
463                         i = 5;\r
464                         *lpString = 0xfc | ((CHAR)(Code >> 30) & 0x01);\r
465                 }\r
466                 else if(Code & 0x03e00000)\r
467                 {\r
468                         i = 4;\r
469                         *lpString = 0xf8 | ((CHAR)(Code >> 24) & 0x03);\r
470                 }\r
471                 else if(Code & 0x001f0000)\r
472                 {\r
473                         i = 3;\r
474                         *lpString = 0xf0 | ((CHAR)(Code >> 18) & 0x07);\r
475                 }\r
476                 else if(Code & 0x0000f800)\r
477                 {\r
478                         i = 2;\r
479                         *lpString = 0xe0 | ((CHAR)(Code >> 12) & 0x0f);\r
480                 }\r
481                 else if(Code & 0x00000780)\r
482                 {\r
483                         i = 1;\r
484                         *lpString = 0xc0 | ((CHAR)(Code >> 6) & 0x1f);\r
485                 }\r
486                 else\r
487                 {\r
488                         i = 0;\r
489                         *lpString = (CHAR)Code & 0x7f;\r
490                 }\r
491                 Count = i + 1;\r
492                 lpString++;\r
493                 while(lpString < pLimit && i > 0)\r
494                 {\r
495                         i--;\r
496                         *lpString = 0x80 | ((CHAR)(Code >> (i * 6)) & 0x3f);\r
497                         lpString++;\r
498                 }\r
499         }\r
500         if(i != 0)\r
501                 Count = 0;\r
502         if(ppNext)\r
503                 *ppNext = lpString;\r
504         return Count;\r
505 }\r
506 \r
507 // ワイド文字列からコードポイントと次のポインタを取得\r
508 // エンコードが不正な場合は0x80000000を返す\r
509 DWORD GetNextCharW(LPCWSTR lpString, LPCWSTR pLimit, LPCWSTR* ppNext)\r
510 {\r
511         DWORD Code;\r
512         Code = 0x80000000;\r
513         if(!pLimit)\r
514                 pLimit = (LPCWSTR)(~0);\r
515         if(lpString < pLimit)\r
516         {\r
517                 if((*lpString & 0xf800) == 0xd800)\r
518                 {\r
519                         if((*lpString & 0x0400) == 0x0400)\r
520                         {\r
521                                 Code = (DWORD)*lpString & 0x03ff;\r
522                                 lpString++;\r
523                                 if(lpString < pLimit)\r
524                                 {\r
525                                         if((*lpString & 0x0400) == 0x0000)\r
526                                         {\r
527                                                 Code |= ((DWORD)*lpString & 0x03ff) << 10;\r
528                                                 lpString++;\r
529                                         }\r
530                                         else\r
531                                                 Code = 0x80000000;\r
532                                 }\r
533                                 else\r
534                                         Code = 0x80000000;\r
535                         }\r
536                 }\r
537                 else\r
538                 {\r
539                         Code = (DWORD)*lpString;\r
540                         lpString++;\r
541                 }\r
542         }\r
543         if(ppNext)\r
544                 *ppNext = lpString;\r
545         return Code;\r
546 }\r
547 \r
548 // ワイド文字列へコードポイントの文字を追加して次のポインタを取得\r
549 // 文字の長さを返す\r
550 int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code)\r
551 {\r
552         int Count;\r
553         Count = 0;\r
554         if(!pLimit)\r
555                 pLimit = (LPWSTR)(~0);\r
556         if(lpString < pLimit)\r
557         {\r
558                 if((Code & 0x7fff0000) || (Code & 0x0000f800) == 0x0000d800)\r
559                 {\r
560                         *lpString = 0xdc00 | ((WCHAR)Code & 0x03ff);\r
561                         lpString++;\r
562                         if(lpString < pLimit)\r
563                         {\r
564                                 *lpString = 0xd800 | ((WCHAR)(Code >> 10) & 0x03ff);\r
565                                 lpString++;\r
566                                 Count = 2;\r
567                         }\r
568                 }\r
569                 else\r
570                 {\r
571                         *lpString = (WCHAR)Code;\r
572                         lpString++;\r
573                         Count = 1;\r
574                 }\r
575         }\r
576         if(ppNext)\r
577                 *ppNext = lpString;\r
578         return Count;\r
579 }\r
580 \r
581 // マルチバイト文字列の冗長表現を修正\r
582 // 修正があればTRUEを返す\r
583 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
584 BOOL FixStringM(LPSTR pDst, LPCSTR pSrc)\r
585 {\r
586         BOOL bResult;\r
587         char* p;\r
588         DWORD Code;\r
589         int i;\r
590         char c;\r
591         bResult = FALSE;\r
592         p = (char*)pSrc;\r
593         while(*pSrc != '\0')\r
594         {\r
595                 Code = GetNextCharM(pSrc, NULL, &pSrc);\r
596                 if(Code & 0x80000000)\r
597                         continue;\r
598                 else if(Code & 0x7c000000)\r
599                 {\r
600                         i = 5;\r
601                         c = (char)(0xfc | (Code >> (6 * i)));\r
602                 }\r
603                 else if(Code & 0x03e00000)\r
604                 {\r
605                         i = 4;\r
606                         c = (char)(0xf8 | (Code >> (6 * i)));\r
607                 }\r
608                 else if(Code & 0x001f0000)\r
609                 {\r
610                         i = 3;\r
611                         c = (char)(0xf0 | (Code >> (6 * i)));\r
612                 }\r
613                 else if(Code & 0x0000f800)\r
614                 {\r
615                         i = 2;\r
616                         c = (char)(0xe0 | (Code >> (6 * i)));\r
617                 }\r
618                 else if(Code & 0x00000780)\r
619                 {\r
620                         i = 1;\r
621                         c = (char)(0xc0 | (Code >> (6 * i)));\r
622                 }\r
623                 else\r
624                 {\r
625                         i = 0;\r
626                         c = (char)Code;\r
627                 }\r
628                 if(c != *p)\r
629                         bResult = TRUE;\r
630                 p++;\r
631                 *pDst = c;\r
632                 pDst++;\r
633                 while(i > 0)\r
634                 {\r
635                         i--;\r
636                         c = (char)(0x80 | ((Code >> (6 * i)) & 0x3f));\r
637                         if(c != *p)\r
638                                 bResult = TRUE;\r
639                         p++;\r
640                         *pDst = c;\r
641                         pDst++;\r
642                 }\r
643         }\r
644         if(*p != '\0')\r
645                 bResult = TRUE;\r
646         *pDst = '\0';\r
647         return bResult;\r
648 }\r
649 \r
650 // NULL区切りマルチバイト文字列の冗長表現を修正\r
651 // 修正があればTRUEを返す\r
652 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
653 BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc)\r
654 {\r
655         BOOL bResult;\r
656         int Length;\r
657         bResult = FALSE;\r
658         while(*pSrc != '\0')\r
659         {\r
660                 Length = strlen(pSrc) + 1;\r
661                 bResult = bResult | FixStringM(pDst, pSrc);\r
662                 pSrc += Length;\r
663                 pDst += strlen(pDst) + 1;\r
664         }\r
665         *pDst = '\0';\r
666         return bResult;\r
667 }\r
668 \r
669 // マルチバイト文字列の冗長表現を確認\r
670 // 冗長表現があればTRUEを返す\r
671 BOOL CheckStringM(LPCSTR lpString)\r
672 {\r
673         BOOL bResult;\r
674         char* p;\r
675         bResult = FALSE;\r
676         p = AllocateStringM(strlen(lpString) + 1);\r
677         if(p)\r
678         {\r
679                 bResult = FixStringM(p, lpString);\r
680                 FreeDuplicatedString(p);\r
681         }\r
682         return bResult;\r
683 }\r
684 \r
685 // NULL区切りマルチバイト文字列の冗長表現を確認\r
686 // 冗長表現があればTRUEを返す\r
687 BOOL CheckMultiStringM(LPCSTR lpString)\r
688 {\r
689         BOOL bResult;\r
690         char* p;\r
691         bResult = FALSE;\r
692         p = AllocateStringM(GetMultiStringLengthM(lpString) + 1);\r
693         if(p)\r
694         {\r
695                 bResult = FixMultiStringM(p, lpString);\r
696                 FreeDuplicatedString(p);\r
697         }\r
698         return bResult;\r
699 }\r
700 \r
701 // 文字列用に確保したメモリを開放\r
702 // リソースIDならば何もしない\r
703 void FreeDuplicatedString(void* p)\r
704 {\r
705         if(p < (void*)0x00010000 || p == (void*)~0)\r
706                 return;\r
707         free(p);\r
708 }\r
709 \r
710 // マルチバイト文字列からワイド文字列へ変換\r
711 // UTF-8からUTF-16 LEへの変換専用\r
712 int MultiByteToWideCharAlternative(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)\r
713 {\r
714         int WideCount;\r
715         LPCSTR pMultiLimit;\r
716         LPWSTR pWideLimit;\r
717         DWORD Code;\r
718         WCHAR Temp[8];\r
719         if(CodePage != CP_UTF8 || dwFlags != 0)\r
720                 return MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar);\r
721         WideCount = 0;\r
722         if(cbMultiByte == -1)\r
723                 pMultiLimit = lpMultiByteStr + strlen(lpMultiByteStr) + 1;\r
724         else\r
725                 pMultiLimit = lpMultiByteStr + cbMultiByte;\r
726         pWideLimit = lpWideCharStr + cchWideChar;\r
727         while(lpMultiByteStr < pMultiLimit)\r
728         {\r
729                 Code = GetNextCharM(lpMultiByteStr, pMultiLimit, &lpMultiByteStr);\r
730                 if(Code == 0x80000000)\r
731                         continue;\r
732                 if(lpWideCharStr)\r
733                 {\r
734                         WideCount += PutNextCharW(lpWideCharStr, pWideLimit, &lpWideCharStr, Code);\r
735                         if(lpWideCharStr >= pWideLimit)\r
736                         {\r
737                                 WideCount = 0;\r
738                                 break;\r
739                         }\r
740                 }\r
741                 else\r
742                         WideCount += PutNextCharW(Temp, NULL, NULL, Code);\r
743         }\r
744         return WideCount;\r
745 }\r
746 \r
747 // ワイド文字列からマルチバイト文字列へ変換\r
748 // UTF-16 LEからUTF-8への変換専用\r
749 int WideCharToMultiByteAlternative(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)\r
750 {\r
751         int MultiCount;\r
752         LPCWSTR pWideLimit;\r
753         LPSTR pMultiLimit;\r
754         DWORD Code;\r
755         CHAR Temp[8];\r
756         if(CodePage != CP_UTF8 || dwFlags != 0)\r
757                 return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);\r
758         MultiCount = 0;\r
759         if(cchWideChar == -1)\r
760                 pWideLimit = lpWideCharStr + wcslen(lpWideCharStr) + 1;\r
761         else\r
762                 pWideLimit = lpWideCharStr + cchWideChar;\r
763         pMultiLimit = lpMultiByteStr + cbMultiByte;\r
764         while(lpWideCharStr < pWideLimit)\r
765         {\r
766                 Code = GetNextCharW(lpWideCharStr, pWideLimit, &lpWideCharStr);\r
767                 if(Code == 0x80000000)\r
768                         continue;\r
769                 if(lpMultiByteStr)\r
770                 {\r
771                         MultiCount += PutNextCharM(lpMultiByteStr, pMultiLimit, &lpMultiByteStr, Code);\r
772                         if(lpMultiByteStr >= pMultiLimit)\r
773                         {\r
774                                 MultiCount = 0;\r
775                                 break;\r
776                         }\r
777                 }\r
778                 else\r
779                         MultiCount += PutNextCharM(Temp, NULL, NULL, Code);\r
780         }\r
781         if(lpUsedDefaultChar)\r
782                 *lpUsedDefaultChar = FALSE;\r
783         return MultiCount;\r
784 }\r
785 \r
786 // 以下ラッパー\r
787 // 戻り値バッファ r\r
788 // ワイド文字バッファ pw%d\r
789 // マルチバイト文字バッファ pm%d\r
790 // 引数バッファ a%d\r
791 \r
792 #pragma warning(disable:4102)\r
793 #define START_ROUTINE                                   do{\r
794 #define END_ROUTINE                                             }while(0);end_of_routine:\r
795 #define QUIT_ROUTINE                                    goto end_of_routine;\r
796 \r
797 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)\r
798 {\r
799         HANDLE r = INVALID_HANDLE_VALUE;\r
800         wchar_t* pw0 = NULL;\r
801 START_ROUTINE\r
802         pw0 = DuplicateMtoW(lpFileName, -1);\r
803         r = CreateFileW(pw0, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);\r
804 END_ROUTINE\r
805         FreeDuplicatedString(pw0);\r
806         return r;\r
807 }\r
808 \r
809 HANDLE FindFirstFileM(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)\r
810 {\r
811         HANDLE r = INVALID_HANDLE_VALUE;\r
812         wchar_t* pw0 = NULL;\r
813         WIN32_FIND_DATAW a0;\r
814 START_ROUTINE\r
815         pw0 = DuplicateMtoW(lpFileName, -1);\r
816         r = FindFirstFileW(pw0, &a0);\r
817         if(r != INVALID_HANDLE_VALUE)\r
818         {\r
819                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
820                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
821                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
822                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
823                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
824                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
825                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
826                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
827                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
828                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
829         }\r
830 END_ROUTINE\r
831         FreeDuplicatedString(pw0);\r
832         return r;\r
833 }\r
834 \r
835 BOOL FindNextFileM(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)\r
836 {\r
837         BOOL r = FALSE;\r
838         WIN32_FIND_DATAW a0;\r
839 START_ROUTINE\r
840         r = FindNextFileW(hFindFile, &a0);\r
841         if(r)\r
842         {\r
843                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
844                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
845                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
846                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
847                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
848                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
849                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
850                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
851                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
852                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
853         }\r
854 END_ROUTINE\r
855         return r;\r
856 }\r
857 \r
858 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)\r
859 {\r
860         DWORD r = 0;\r
861         wchar_t* pw0 = NULL;\r
862 START_ROUTINE\r
863         // TODO: バッファが不十分な場合に必要なサイズを返す\r
864         pw0 = AllocateStringW(nBufferLength * 4);\r
865         GetCurrentDirectoryW(nBufferLength * 4, pw0);\r
866         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
867         r = TerminateStringM(lpBuffer, nBufferLength);\r
868 END_ROUTINE\r
869         FreeDuplicatedString(pw0);\r
870         return r;\r
871 }\r
872 \r
873 BOOL SetCurrentDirectoryM(LPCSTR lpPathName)\r
874 {\r
875         BOOL r = FALSE;\r
876         wchar_t* pw0 = NULL;\r
877 START_ROUTINE\r
878         pw0 = DuplicateMtoW(lpPathName, -1);\r
879         r = SetCurrentDirectoryW(pw0);\r
880 END_ROUTINE\r
881         FreeDuplicatedString(pw0);\r
882         return r;\r
883 }\r
884 \r
885 DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)\r
886 {\r
887         DWORD r = 0;\r
888         wchar_t* pw0 = NULL;\r
889 START_ROUTINE\r
890         pw0 = AllocateStringW(nBufferLength * 4);\r
891         GetTempPathW(nBufferLength * 4, pw0);\r
892         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
893         r = TerminateStringM(lpBuffer, nBufferLength);\r
894 END_ROUTINE\r
895         FreeDuplicatedString(pw0);\r
896         return r;\r
897 }\r
898 \r
899 DWORD GetFileAttributesM(LPCSTR lpFileName)\r
900 {\r
901         DWORD r = FALSE;\r
902         wchar_t* pw0 = NULL;\r
903 START_ROUTINE\r
904         pw0 = DuplicateMtoW(lpFileName, -1);\r
905         r = GetFileAttributesW(pw0);\r
906 END_ROUTINE\r
907         FreeDuplicatedString(pw0);\r
908         return r;\r
909 }\r
910 \r
911 DWORD GetModuleFileNameM(HMODULE hModule, LPCH lpFilename, DWORD nSize)\r
912 {\r
913         DWORD r = 0;\r
914         wchar_t* pw0 = NULL;\r
915 START_ROUTINE\r
916         pw0 = AllocateStringW(nSize * 4);\r
917         GetModuleFileNameW(hModule, pw0, nSize * 4);\r
918         WtoM(lpFilename, nSize, pw0, -1);\r
919         r = TerminateStringM(lpFilename, nSize);\r
920 END_ROUTINE\r
921         FreeDuplicatedString(pw0);\r
922         return r;\r
923 }\r
924 \r
925 BOOL CopyFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists)\r
926 {\r
927         BOOL r = FALSE;\r
928         wchar_t* pw0 = NULL;\r
929         wchar_t* pw1 = NULL;\r
930 START_ROUTINE\r
931         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
932         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
933         r = CopyFileW(pw0, pw1, bFailIfExists);\r
934 END_ROUTINE\r
935         FreeDuplicatedString(pw0);\r
936         FreeDuplicatedString(pw1);\r
937         return r;\r
938 }\r
939 \r
940 BOOL MoveFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)\r
941 {\r
942         BOOL r = FALSE;\r
943         wchar_t* pw0 = NULL;\r
944         wchar_t* pw1 = NULL;\r
945 START_ROUTINE\r
946         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
947         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
948         r = MoveFileW(pw0, pw1);\r
949 END_ROUTINE\r
950         FreeDuplicatedString(pw0);\r
951         FreeDuplicatedString(pw1);\r
952         return r;\r
953 }\r
954 \r
955 int mkdirM(const char * _Path)\r
956 {\r
957         int r = -1;\r
958         wchar_t* pw0 = NULL;\r
959 START_ROUTINE\r
960         pw0 = DuplicateMtoW(_Path, -1);\r
961         r = _wmkdir(pw0);\r
962 END_ROUTINE\r
963         FreeDuplicatedString(pw0);\r
964         return r;\r
965 }\r
966 \r
967 int _mkdirM(const char * _Path)\r
968 {\r
969         int r = -1;\r
970         wchar_t* pw0 = NULL;\r
971 START_ROUTINE\r
972         pw0 = DuplicateMtoW(_Path, -1);\r
973         r = _wmkdir(pw0);\r
974 END_ROUTINE\r
975         FreeDuplicatedString(pw0);\r
976         return r;\r
977 }\r
978 \r
979 int rmdirM(const char * _Path)\r
980 {\r
981         int r = -1;\r
982         wchar_t* pw0 = NULL;\r
983 START_ROUTINE\r
984         pw0 = DuplicateMtoW(_Path, -1);\r
985         r = _wrmdir(pw0);\r
986 END_ROUTINE\r
987         FreeDuplicatedString(pw0);\r
988         return r;\r
989 }\r
990 \r
991 int _rmdirM(const char * _Path)\r
992 {\r
993         int r = -1;\r
994         wchar_t* pw0 = NULL;\r
995 START_ROUTINE\r
996         pw0 = DuplicateMtoW(_Path, -1);\r
997         r = _wrmdir(pw0);\r
998 END_ROUTINE\r
999         FreeDuplicatedString(pw0);\r
1000         return r;\r
1001 }\r
1002 \r
1003 int removeM(const char * _Filename)\r
1004 {\r
1005         int r = -1;\r
1006         wchar_t* pw0 = NULL;\r
1007 START_ROUTINE\r
1008         pw0 = DuplicateMtoW(_Filename, -1);\r
1009         r = _wremove(pw0);\r
1010 END_ROUTINE\r
1011         FreeDuplicatedString(pw0);\r
1012         return r;\r
1013 }\r
1014 \r
1015 int _removeM(const char * _Filename)\r
1016 {\r
1017         int r = -1;\r
1018         wchar_t* pw0 = NULL;\r
1019 START_ROUTINE\r
1020         pw0 = DuplicateMtoW(_Filename, -1);\r
1021         r = _wremove(pw0);\r
1022 END_ROUTINE\r
1023         FreeDuplicatedString(pw0);\r
1024         return r;\r
1025 }\r
1026 \r
1027 int _unlinkM(const char * _Filename)\r
1028 {\r
1029         int r = -1;\r
1030         wchar_t* pw0 = NULL;\r
1031 START_ROUTINE\r
1032         pw0 = DuplicateMtoW(_Filename, -1);\r
1033         r = _wunlink(pw0);\r
1034 END_ROUTINE\r
1035         FreeDuplicatedString(pw0);\r
1036         return r;\r
1037 }\r
1038 \r
1039 size_t _mbslenM(const unsigned char * _Str)\r
1040 {\r
1041         size_t r = 0;\r
1042 START_ROUTINE\r
1043         while(GetNextCharM(_Str, NULL, &_Str) > 0)\r
1044         {\r
1045                 r++;\r
1046         }\r
1047 END_ROUTINE\r
1048         return r;\r
1049 }\r
1050 \r
1051 unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)\r
1052 {\r
1053         unsigned char* r = NULL;\r
1054         unsigned int c;\r
1055         unsigned char* p;\r
1056 START_ROUTINE\r
1057         while((c = GetNextCharM(_Str, NULL, &p)) > 0)\r
1058         {\r
1059                 if(c == _Ch)\r
1060                         break;\r
1061                 _Str = p;\r
1062         }\r
1063         if(c == _Ch)\r
1064                 r = (unsigned char*)_Str;\r
1065 END_ROUTINE\r
1066         return r;\r
1067 }\r
1068 \r
1069 unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)\r
1070 {\r
1071         unsigned char* r = NULL;\r
1072         unsigned int c;\r
1073         unsigned char* p;\r
1074 START_ROUTINE\r
1075         while((c = GetNextCharM(_Str, NULL, &p)) > 0)\r
1076         {\r
1077                 if(c == _Ch)\r
1078                         r = (unsigned char*)_Str;\r
1079                 _Str = p;\r
1080         }\r
1081         if(c == _Ch)\r
1082                 r = (unsigned char*)_Str;\r
1083 END_ROUTINE\r
1084         return r;\r
1085 }\r
1086 \r
1087 unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)\r
1088 {\r
1089         unsigned char* r = NULL;\r
1090 START_ROUTINE\r
1091         r = strstr(_Str, _Substr);\r
1092 END_ROUTINE\r
1093         return r;\r
1094 }\r
1095 \r
1096 int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
1097 {\r
1098         int r = 0;\r
1099 START_ROUTINE\r
1100         r = strcmp(_Str1, _Str2);\r
1101 END_ROUTINE\r
1102         return r;\r
1103 }\r
1104 \r
1105 int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
1106 {\r
1107         int r = 0;\r
1108 START_ROUTINE\r
1109         r = _stricmp(_Str1, _Str2);\r
1110 END_ROUTINE\r
1111         return r;\r
1112 }\r
1113 \r
1114 int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)\r
1115 {\r
1116         int r = 0;\r
1117         DWORD c1;\r
1118         DWORD c2;\r
1119 START_ROUTINE\r
1120         c1 = 0;\r
1121         c2 = 0;\r
1122         while(_MaxCount > 0)\r
1123         {\r
1124                 c1 = GetNextCharM(_Str1, NULL, &_Str1);\r
1125                 c2 = GetNextCharM(_Str2, NULL, &_Str2);\r
1126                 if(c1 != c2)\r
1127                         break;\r
1128                 _MaxCount--;\r
1129                 if(c1 == 0 || c2 == 0)\r
1130                         break;\r
1131         }\r
1132         r = c1 - c2;\r
1133 END_ROUTINE\r
1134         return r;\r
1135 }\r
1136 \r
1137 unsigned char * _mbslwrM(unsigned char * _String)\r
1138 {\r
1139         unsigned char* r = NULL;\r
1140 START_ROUTINE\r
1141         r = _strlwr(_String);\r
1142 END_ROUTINE\r
1143         return r;\r
1144 }\r
1145 \r
1146 unsigned char * _mbsuprM(unsigned char * _String)\r
1147 {\r
1148         unsigned char* r = NULL;\r
1149 START_ROUTINE\r
1150         r = _strupr(_String);\r
1151 END_ROUTINE\r
1152         return r;\r
1153 }\r
1154 \r
1155 unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)\r
1156 {\r
1157         unsigned char* r = NULL;\r
1158 START_ROUTINE\r
1159         while(_Count > 0 && GetNextCharM(_Str, NULL, &_Str) > 0)\r
1160         {\r
1161                 _Count--;\r
1162         }\r
1163         r = (unsigned char*)_Str;\r
1164 END_ROUTINE\r
1165         return r;\r
1166 }\r
1167 \r
1168 FILE * fopenM(const char * _Filename, const char * _Mode)\r
1169 {\r
1170         FILE* r = NULL;\r
1171         wchar_t* pw0 = NULL;\r
1172         wchar_t* pw1 = NULL;\r
1173 START_ROUTINE\r
1174         pw0 = DuplicateMtoW(_Filename, -1);\r
1175         pw1 = DuplicateMtoW(_Mode, -1);\r
1176         r = _wfopen(pw0, pw1);\r
1177 END_ROUTINE\r
1178         FreeDuplicatedString(pw0);\r
1179         FreeDuplicatedString(pw1);\r
1180         return r;\r
1181 }\r
1182 \r