OSDN Git Service

Fix bugs of displaying icons in the local file list.
[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* ppNext)\r
394 {\r
395         DWORD Code;\r
396         int i;\r
397         Code = 0;\r
398         if((*lpString & 0xfe) == 0xfc)\r
399         {\r
400                 i = 5;\r
401                 Code |= (DWORD)*lpString & 0x01;\r
402         }\r
403         else if((*lpString & 0xfc) == 0xf8)\r
404         {\r
405                 i = 4;\r
406                 Code |= (DWORD)*lpString & 0x03;\r
407         }\r
408         else if((*lpString & 0xf8) == 0xf0)\r
409         {\r
410                 i = 3;\r
411                 Code |= (DWORD)*lpString & 0x07;\r
412         }\r
413         else if((*lpString & 0xf0) == 0xe0)\r
414         {\r
415                 i = 2;\r
416                 Code |= (DWORD)*lpString & 0x0f;\r
417         }\r
418         else if((*lpString & 0xe0) == 0xc0)\r
419         {\r
420                 i = 1;\r
421                 Code |= (DWORD)*lpString & 0x1f;\r
422         }\r
423         else if((*lpString & 0x80) == 0x00)\r
424         {\r
425                 i = 0;\r
426                 Code |= (DWORD)*lpString & 0x7f;\r
427         }\r
428         else\r
429                 i = -1;\r
430         lpString++;\r
431         while((*lpString & 0xc0) == 0x80)\r
432         {\r
433                 i--;\r
434                 Code = Code << 6;\r
435                 Code |= (DWORD)*lpString & 0x3f;\r
436                 lpString++;\r
437         }\r
438         if(i != 0)\r
439                 Code = 0x80000000;\r
440         if(ppNext)\r
441                 *ppNext = lpString;\r
442         return Code;\r
443 }\r
444 \r
445 // マルチバイト文字列の冗長表現を修正\r
446 // 修正があればTRUEを返す\r
447 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
448 BOOL FixStringM(LPSTR pDst, LPCSTR pSrc)\r
449 {\r
450         BOOL bResult;\r
451         char* p;\r
452         DWORD Code;\r
453         int i;\r
454         char c;\r
455         bResult = FALSE;\r
456         p = (char*)pSrc;\r
457         while(*pSrc != '\0')\r
458         {\r
459                 Code = GetNextCharM(pSrc, &pSrc);\r
460                 if(Code & 0x80000000)\r
461                         continue;\r
462                 else if(Code & 0x7c000000)\r
463                 {\r
464                         i = 5;\r
465                         c = (char)(0xfc | (Code >> (6 * i)));\r
466                 }\r
467                 else if(Code & 0x03e00000)\r
468                 {\r
469                         i = 4;\r
470                         c = (char)(0xf8 | (Code >> (6 * i)));\r
471                 }\r
472                 else if(Code & 0x001f0000)\r
473                 {\r
474                         i = 3;\r
475                         c = (char)(0xf0 | (Code >> (6 * i)));\r
476                 }\r
477                 else if(Code & 0x0000f800)\r
478                 {\r
479                         i = 2;\r
480                         c = (char)(0xe0 | (Code >> (6 * i)));\r
481                 }\r
482                 else if(Code & 0x00000780)\r
483                 {\r
484                         i = 1;\r
485                         c = (char)(0xc0 | (Code >> (6 * i)));\r
486                 }\r
487                 else\r
488                 {\r
489                         i = 0;\r
490                         c = (char)Code;\r
491                 }\r
492                 if(c != *p)\r
493                         bResult = TRUE;\r
494                 p++;\r
495                 *pDst = c;\r
496                 pDst++;\r
497                 while(i > 0)\r
498                 {\r
499                         i--;\r
500                         c = (char)(0x80 | ((Code >> (6 * i)) & 0x3f));\r
501                         if(c != *p)\r
502                                 bResult = TRUE;\r
503                         p++;\r
504                         *pDst = c;\r
505                         pDst++;\r
506                 }\r
507         }\r
508         if(*p != '\0')\r
509                 bResult = TRUE;\r
510         *pDst = '\0';\r
511         return bResult;\r
512 }\r
513 \r
514 // NULL区切りマルチバイト文字列の冗長表現を修正\r
515 // 修正があればTRUEを返す\r
516 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
517 BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc)\r
518 {\r
519         BOOL bResult;\r
520         int Length;\r
521         bResult = FALSE;\r
522         while(*pSrc != '\0')\r
523         {\r
524                 Length = strlen(pSrc) + 1;\r
525                 bResult = bResult | FixStringM(pDst, pSrc);\r
526                 pSrc += Length;\r
527                 pDst += strlen(pDst) + 1;\r
528         }\r
529         *pDst = '\0';\r
530         return bResult;\r
531 }\r
532 \r
533 // マルチバイト文字列の冗長表現を確認\r
534 // 冗長表現があればTRUEを返す\r
535 BOOL CheckStringM(LPCSTR lpString)\r
536 {\r
537         BOOL bResult;\r
538         char* p;\r
539         bResult = FALSE;\r
540         p = AllocateStringM(strlen(lpString) + 1);\r
541         if(p)\r
542         {\r
543                 bResult = FixStringM(p, lpString);\r
544                 FreeDuplicatedString(p);\r
545         }\r
546         return bResult;\r
547 }\r
548 \r
549 // NULL区切りマルチバイト文字列の冗長表現を確認\r
550 // 冗長表現があればTRUEを返す\r
551 BOOL CheckMultiStringM(LPCSTR lpString)\r
552 {\r
553         BOOL bResult;\r
554         char* p;\r
555         bResult = FALSE;\r
556         p = AllocateStringM(GetMultiStringLengthM(lpString) + 1);\r
557         if(p)\r
558         {\r
559                 bResult = FixMultiStringM(p, lpString);\r
560                 FreeDuplicatedString(p);\r
561         }\r
562         return bResult;\r
563 }\r
564 \r
565 // 文字列用に確保したメモリを開放\r
566 // リソースIDならば何もしない\r
567 void FreeDuplicatedString(void* p)\r
568 {\r
569         if(p < (void*)0x00010000 || p == (void*)~0)\r
570                 return;\r
571         free(p);\r
572 }\r
573 \r
574 // 以下ラッパー\r
575 // 戻り値バッファ r\r
576 // ワイド文字バッファ pw%d\r
577 // マルチバイト文字バッファ pm%d\r
578 // 引数バッファ a%d\r
579 \r
580 #pragma warning(disable:4102)\r
581 #define START_ROUTINE                                   do{\r
582 #define END_ROUTINE                                             }while(0);end_of_routine:\r
583 #define QUIT_ROUTINE                                    goto end_of_routine;\r
584 \r
585 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)\r
586 {\r
587         HANDLE r = INVALID_HANDLE_VALUE;\r
588         wchar_t* pw0 = NULL;\r
589 START_ROUTINE\r
590         pw0 = DuplicateMtoW(lpFileName, -1);\r
591         r = CreateFileW(pw0, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);\r
592 END_ROUTINE\r
593         FreeDuplicatedString(pw0);\r
594         return r;\r
595 }\r
596 \r
597 HANDLE FindFirstFileM(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)\r
598 {\r
599         HANDLE r = INVALID_HANDLE_VALUE;\r
600         wchar_t* pw0 = NULL;\r
601         WIN32_FIND_DATAW a0;\r
602 START_ROUTINE\r
603         pw0 = DuplicateMtoW(lpFileName, -1);\r
604         r = FindFirstFileW(pw0, &a0);\r
605         if(r != INVALID_HANDLE_VALUE)\r
606         {\r
607                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
608                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
609                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
610                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
611                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
612                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
613                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
614                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
615                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
616                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
617         }\r
618 END_ROUTINE\r
619         FreeDuplicatedString(pw0);\r
620         return r;\r
621 }\r
622 \r
623 BOOL FindNextFileM(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)\r
624 {\r
625         BOOL r = FALSE;\r
626         WIN32_FIND_DATAW a0;\r
627 START_ROUTINE\r
628         r = FindNextFileW(hFindFile, &a0);\r
629         if(r)\r
630         {\r
631                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
632                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
633                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
634                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
635                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
636                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
637                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
638                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
639                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
640                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
641         }\r
642 END_ROUTINE\r
643         return r;\r
644 }\r
645 \r
646 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)\r
647 {\r
648         DWORD r = 0;\r
649         wchar_t* pw0 = NULL;\r
650 START_ROUTINE\r
651         // TODO: バッファが不十分な場合に必要なサイズを返す\r
652         pw0 = AllocateStringW(nBufferLength * 4);\r
653         GetCurrentDirectoryW(nBufferLength * 4, pw0);\r
654         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
655         r = TerminateStringM(lpBuffer, nBufferLength);\r
656 END_ROUTINE\r
657         FreeDuplicatedString(pw0);\r
658         return r;\r
659 }\r
660 \r
661 BOOL SetCurrentDirectoryM(LPCSTR lpPathName)\r
662 {\r
663         BOOL r = FALSE;\r
664         wchar_t* pw0 = NULL;\r
665 START_ROUTINE\r
666         pw0 = DuplicateMtoW(lpPathName, -1);\r
667         r = SetCurrentDirectoryW(pw0);\r
668 END_ROUTINE\r
669         FreeDuplicatedString(pw0);\r
670         return r;\r
671 }\r
672 \r
673 DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)\r
674 {\r
675         DWORD r = 0;\r
676         wchar_t* pw0 = NULL;\r
677 START_ROUTINE\r
678         pw0 = AllocateStringW(nBufferLength * 4);\r
679         GetTempPathW(nBufferLength * 4, pw0);\r
680         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
681         r = TerminateStringM(lpBuffer, nBufferLength);\r
682 END_ROUTINE\r
683         FreeDuplicatedString(pw0);\r
684         return r;\r
685 }\r
686 \r
687 DWORD GetFileAttributesM(LPCSTR lpFileName)\r
688 {\r
689         DWORD r = FALSE;\r
690         wchar_t* pw0 = NULL;\r
691 START_ROUTINE\r
692         pw0 = DuplicateMtoW(lpFileName, -1);\r
693         r = GetFileAttributesW(pw0);\r
694 END_ROUTINE\r
695         FreeDuplicatedString(pw0);\r
696         return r;\r
697 }\r
698 \r
699 DWORD GetModuleFileNameM(HMODULE hModule, LPCH lpFilename, DWORD nSize)\r
700 {\r
701         DWORD r = 0;\r
702         wchar_t* pw0 = NULL;\r
703 START_ROUTINE\r
704         pw0 = AllocateStringW(nSize * 4);\r
705         GetModuleFileNameW(hModule, pw0, nSize * 4);\r
706         WtoM(lpFilename, nSize, pw0, -1);\r
707         r = TerminateStringM(lpFilename, nSize);\r
708 END_ROUTINE\r
709         FreeDuplicatedString(pw0);\r
710         return r;\r
711 }\r
712 \r
713 BOOL CopyFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists)\r
714 {\r
715         BOOL r = FALSE;\r
716         wchar_t* pw0 = NULL;\r
717         wchar_t* pw1 = NULL;\r
718 START_ROUTINE\r
719         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
720         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
721         r = CopyFileW(pw0, pw1, bFailIfExists);\r
722 END_ROUTINE\r
723         FreeDuplicatedString(pw0);\r
724         FreeDuplicatedString(pw1);\r
725         return r;\r
726 }\r
727 \r
728 BOOL MoveFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)\r
729 {\r
730         BOOL r = FALSE;\r
731         wchar_t* pw0 = NULL;\r
732         wchar_t* pw1 = NULL;\r
733 START_ROUTINE\r
734         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
735         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
736         r = MoveFileW(pw0, pw1);\r
737 END_ROUTINE\r
738         FreeDuplicatedString(pw0);\r
739         FreeDuplicatedString(pw1);\r
740         return r;\r
741 }\r
742 \r
743 int mkdirM(const char * _Path)\r
744 {\r
745         int r = -1;\r
746         wchar_t* pw0 = NULL;\r
747 START_ROUTINE\r
748         pw0 = DuplicateMtoW(_Path, -1);\r
749         r = _wmkdir(pw0);\r
750 END_ROUTINE\r
751         FreeDuplicatedString(pw0);\r
752         return r;\r
753 }\r
754 \r
755 int _mkdirM(const char * _Path)\r
756 {\r
757         int r = -1;\r
758         wchar_t* pw0 = NULL;\r
759 START_ROUTINE\r
760         pw0 = DuplicateMtoW(_Path, -1);\r
761         r = _wmkdir(pw0);\r
762 END_ROUTINE\r
763         FreeDuplicatedString(pw0);\r
764         return r;\r
765 }\r
766 \r
767 int rmdirM(const char * _Path)\r
768 {\r
769         int r = -1;\r
770         wchar_t* pw0 = NULL;\r
771 START_ROUTINE\r
772         pw0 = DuplicateMtoW(_Path, -1);\r
773         r = _wrmdir(pw0);\r
774 END_ROUTINE\r
775         FreeDuplicatedString(pw0);\r
776         return r;\r
777 }\r
778 \r
779 int _rmdirM(const char * _Path)\r
780 {\r
781         int r = -1;\r
782         wchar_t* pw0 = NULL;\r
783 START_ROUTINE\r
784         pw0 = DuplicateMtoW(_Path, -1);\r
785         r = _wrmdir(pw0);\r
786 END_ROUTINE\r
787         FreeDuplicatedString(pw0);\r
788         return r;\r
789 }\r
790 \r
791 int removeM(const char * _Filename)\r
792 {\r
793         int r = -1;\r
794         wchar_t* pw0 = NULL;\r
795 START_ROUTINE\r
796         pw0 = DuplicateMtoW(_Filename, -1);\r
797         r = _wremove(pw0);\r
798 END_ROUTINE\r
799         FreeDuplicatedString(pw0);\r
800         return r;\r
801 }\r
802 \r
803 int _removeM(const char * _Filename)\r
804 {\r
805         int r = -1;\r
806         wchar_t* pw0 = NULL;\r
807 START_ROUTINE\r
808         pw0 = DuplicateMtoW(_Filename, -1);\r
809         r = _wremove(pw0);\r
810 END_ROUTINE\r
811         FreeDuplicatedString(pw0);\r
812         return r;\r
813 }\r
814 \r
815 int _unlinkM(const char * _Filename)\r
816 {\r
817         int r = -1;\r
818         wchar_t* pw0 = NULL;\r
819 START_ROUTINE\r
820         pw0 = DuplicateMtoW(_Filename, -1);\r
821         r = _wunlink(pw0);\r
822 END_ROUTINE\r
823         FreeDuplicatedString(pw0);\r
824         return r;\r
825 }\r
826 \r
827 size_t _mbslenM(const unsigned char * _Str)\r
828 {\r
829         size_t r = 0;\r
830 START_ROUTINE\r
831         while(GetNextCharM(_Str, &_Str) > 0)\r
832         {\r
833                 r++;\r
834         }\r
835 END_ROUTINE\r
836         return r;\r
837 }\r
838 \r
839 unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)\r
840 {\r
841         unsigned char* r = NULL;\r
842         unsigned int c;\r
843         unsigned char* p;\r
844 START_ROUTINE\r
845         while((c = GetNextCharM(_Str, &p)) > 0)\r
846         {\r
847                 if(c == _Ch)\r
848                         break;\r
849                 _Str = p;\r
850         }\r
851         if(c == _Ch)\r
852                 r = (unsigned char*)_Str;\r
853 END_ROUTINE\r
854         return r;\r
855 }\r
856 \r
857 unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)\r
858 {\r
859         unsigned char* r = NULL;\r
860         unsigned int c;\r
861         unsigned char* p;\r
862 START_ROUTINE\r
863         while((c = GetNextCharM(_Str, &p)) > 0)\r
864         {\r
865                 if(c == _Ch)\r
866                         r = (unsigned char*)_Str;\r
867                 _Str = p;\r
868         }\r
869         if(c == _Ch)\r
870                 r = (unsigned char*)_Str;\r
871 END_ROUTINE\r
872         return r;\r
873 }\r
874 \r
875 unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)\r
876 {\r
877         unsigned char* r = NULL;\r
878 START_ROUTINE\r
879         r = strstr(_Str, _Substr);\r
880 END_ROUTINE\r
881         return r;\r
882 }\r
883 \r
884 int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
885 {\r
886         int r = 0;\r
887 START_ROUTINE\r
888         r = strcmp(_Str1, _Str2);\r
889 END_ROUTINE\r
890         return r;\r
891 }\r
892 \r
893 int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
894 {\r
895         int r = 0;\r
896 START_ROUTINE\r
897         r = _stricmp(_Str1, _Str2);\r
898 END_ROUTINE\r
899         return r;\r
900 }\r
901 \r
902 int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)\r
903 {\r
904         int r = 0;\r
905         DWORD c1;\r
906         DWORD c2;\r
907 START_ROUTINE\r
908         c1 = 0;\r
909         c2 = 0;\r
910         while(_MaxCount > 0)\r
911         {\r
912                 c1 = GetNextCharM(_Str1, &_Str1);\r
913                 c2 = GetNextCharM(_Str2, &_Str2);\r
914                 if(c1 != c2)\r
915                         break;\r
916                 _MaxCount--;\r
917                 if(c1 == 0 || c2 == 0)\r
918                         break;\r
919         }\r
920         r = c1 - c2;\r
921 END_ROUTINE\r
922         return r;\r
923 }\r
924 \r
925 unsigned char * _mbslwrM(unsigned char * _String)\r
926 {\r
927         unsigned char* r = NULL;\r
928 START_ROUTINE\r
929         r = _strlwr(_String);\r
930 END_ROUTINE\r
931         return r;\r
932 }\r
933 \r
934 unsigned char * _mbsuprM(unsigned char * _String)\r
935 {\r
936         unsigned char* r = NULL;\r
937 START_ROUTINE\r
938         r = _strupr(_String);\r
939 END_ROUTINE\r
940         return r;\r
941 }\r
942 \r
943 unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)\r
944 {\r
945         unsigned char* r = NULL;\r
946 START_ROUTINE\r
947         while(_Count > 0 && GetNextCharM(_Str, &_Str) > 0)\r
948         {\r
949                 _Count--;\r
950         }\r
951         r = (unsigned char*)_Str;\r
952 END_ROUTINE\r
953         return r;\r
954 }\r
955 \r
956 FILE * fopenM(const char * _Filename, const char * _Mode)\r
957 {\r
958         FILE* r = NULL;\r
959         wchar_t* pw0 = NULL;\r
960         wchar_t* pw1 = NULL;\r
961 START_ROUTINE\r
962         pw0 = DuplicateMtoW(_Filename, -1);\r
963         pw1 = DuplicateMtoW(_Mode, -1);\r
964         r = _wfopen(pw0, pw1);\r
965 END_ROUTINE\r
966         FreeDuplicatedString(pw0);\r
967         FreeDuplicatedString(pw1);\r
968         return r;\r
969 }\r
970 \r