OSDN Git Service

Fix bugs of UTF-8 to UTF-16 API bridge.
[ffftp/ffftp.git] / mbswrapper.c
1 // mbswrapper.cpp
2 // Copyright (C) 2011 Suguru Kawamoto
3 // マルチバイト文字ワイド文字APIラッパー
4 // マルチバイト文字はUTF-8、ワイド文字はUTF-16であるものとする
5 // 全ての制御用の文字はASCIIの範囲であるため、Shift_JISとUTF-8間の変換は不要
6
7 #define UNICODE
8 #define _UNICODE
9 #define _WIN32_WINNT 0x0600
10 #undef _WIN32_IE
11 #define _WIN32_IE 0x0400
12
13 #include <tchar.h>
14 #include <direct.h>
15 #include <windows.h>
16 #include <commctrl.h>
17 #include <shlobj.h>
18 #include <htmlhelp.h>
19
20 #define DO_NOT_REPLACE
21 #include "mbswrapper.h"
22
23 // マルチバイト文字列からワイド文字列へ変換
24 int MtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)
25 {
26         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
27                 return 0;
28         if(pDst)
29                 return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, pDst, size);
30         return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, NULL, 0);
31 }
32
33 // ワイド文字列からマルチバイト文字列へ変換
34 int WtoM(LPSTR pDst, int size, LPCWSTR pSrc, int count)
35 {
36         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
37                 return 0;
38         if(pDst)
39                 return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, pDst, size, NULL, NULL);
40         return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, NULL, 0, NULL, NULL);
41 }
42
43 // ワイド文字列からShift_JIS文字列へ変換
44 int WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)
45 {
46         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
47                 return 0;
48         if(pDst)
49                 return WideCharToMultiByte(CP_ACP, 0, pSrc, count, pDst, size, NULL, NULL);
50         return WideCharToMultiByte(CP_ACP, 0, pSrc, count, NULL, 0, NULL, NULL);
51 }
52
53 // マルチバイト文字列バッファ終端を強制的にNULLで置換
54 int TerminateStringM(LPSTR lpString, int size)
55 {
56         int i;
57         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)
58                 return 0;
59         for(i = 0; i < size; i++)
60         {
61                 if(lpString[i] == '\0')
62                         return i;
63         }
64         i--;
65         lpString[i] = '\0';
66         return i;
67 }
68
69 // ワイド文字列バッファ終端を強制的にNULLで置換
70 int TerminateStringW(LPWSTR lpString, int size)
71 {
72         int i;
73         if(lpString < (LPWSTR)0x00010000 || lpString == (LPWSTR)~0)
74                 return 0;
75         for(i = 0; i < size; i++)
76         {
77                 if(lpString[i] == L'\0')
78                         return i;
79         }
80         i--;
81         lpString[i] = L'\0';
82         return i;
83 }
84
85 // Shift_JIS文字列バッファ終端を強制的にNULLで置換
86 int TerminateStringA(LPSTR lpString, int size)
87 {
88         int i;
89         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)
90                 return 0;
91         for(i = 0; i < size; i++)
92         {
93                 if(lpString[i] == '\0')
94                         return i;
95         }
96         i--;
97         lpString[i] = '\0';
98         return i;
99 }
100
101 // NULL区切り複数マルチバイト文字列の長さを取得
102 size_t GetMultiStringLengthM(LPCSTR lpString)
103 {
104         size_t i;
105         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
106                 return 0;
107         i = 0;
108         while(lpString[i] != '\0' || lpString[i + 1] != '\0')
109         {
110                 i++;
111         }
112         i++;
113         return i;
114 }
115
116 // NULL区切り複数ワイド文字列の長さを取得
117 size_t GetMultiStringLengthW(LPCWSTR lpString)
118 {
119         size_t i;
120         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
121                 return 0;
122         i = 0;
123         while(lpString[i] != L'\0' || lpString[i + 1] != L'\0')
124         {
125                 i++;
126         }
127         i++;
128         return i;
129 }
130
131 // NULL区切り複数Shift_JIS文字列の長さを取得
132 size_t GetMultiStringLengthA(LPCSTR lpString)
133 {
134         size_t i;
135         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
136                 return 0;
137         i = 0;
138         while(lpString[i] != '\0' || lpString[i + 1] != '\0')
139         {
140                 i++;
141         }
142         i++;
143         return i;
144 }
145
146 // NULL区切りマルチバイト文字列からワイド文字列へ変換
147 int MtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)
148 {
149         int i;
150         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
151                 return 0;
152         if(!pDst)
153                 return GetMultiStringLengthM(pSrc);
154         i = 0;
155         while(*pSrc != '\0')
156         {
157                 i += MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1);
158                 pSrc += strlen(pSrc) + 1;
159         }
160         pDst[i] = L'\0';
161         return i;
162 }
163
164 // NULL区切りワイド文字列からマルチバイト文字列へ変換
165 int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
166 {
167         int i;
168         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
169                 return 0;
170         if(!pDst)
171                 return GetMultiStringLengthW(pSrc);
172         i = 0;
173         while(*pSrc != L'\0')
174         {
175                 i += WideCharToMultiByte(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);
176                 pSrc += wcslen(pSrc) + 1;
177         }
178         pDst[i] = '\0';
179         return i;
180 }
181
182 // NULL区切りワイド文字列からShift_JIS文字列へ変換
183 int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
184 {
185         int i;
186         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
187                 return 0;
188         if(!pDst)
189                 return GetMultiStringLengthW(pSrc);
190         i = 0;
191         while(*pSrc != L'\0')
192         {
193                 i += WideCharToMultiByte(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);
194                 pSrc += wcslen(pSrc) + 1;
195         }
196         pDst[i] = '\0';
197         return i;
198 }
199
200 // マルチバイト文字列用のメモリを確保
201 char* AllocateStringM(int size)
202 {
203         char* p;
204         // 0が指定される場合があるため1文字分追加
205         p = (char*)malloc(sizeof(char) * (size + 1));
206         // 念のため先頭にNULL文字を代入
207         if(p)
208                 *p = '\0';
209         return p;
210 }
211
212 // ワイド文字列用のメモリを確保
213 wchar_t* AllocateStringW(int size)
214 {
215         wchar_t* p;
216         // 0が指定される場合があるため1文字分追加
217         p = (wchar_t*)malloc(sizeof(wchar_t) * (size + 1));
218         // 念のため先頭にNULL文字を代入
219         if(p)
220                 *p = L'\0';
221         return p;
222 }
223
224 // Shift_JIS文字列用のメモリを確保
225 char* AllocateStringA(int size)
226 {
227         char* p;
228         // 0が指定される場合があるため1文字分追加
229         p = (char*)malloc(sizeof(char) * (size + 1));
230         // 念のため先頭にNULL文字を代入
231         if(p)
232                 *p = '\0';
233         return p;
234 }
235
236 // メモリを確保してマルチバイト文字列からワイド文字列へ変換
237 wchar_t* DuplicateMtoW(LPCSTR lpString, int c)
238 {
239         wchar_t* p;
240         int i;
241         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
242                 return (wchar_t*)lpString;
243         if(c < 0)
244                 c = strlen(lpString);
245         p = AllocateStringW(MtoW(NULL, 0, lpString, c) + 1);
246         if(p)
247         {
248                 i = MtoW(p, 65535, lpString, c);
249                 p[i] = L'\0';
250         }
251         return p;
252 }
253
254 // 指定したサイズのメモリを確保してマルチバイト文字列からワイド文字列へ変換
255 wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)
256 {
257         wchar_t* p;
258         int i;
259         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
260                 return (wchar_t*)lpString;
261         if(c < 0)
262                 c = strlen(lpString);
263         p = AllocateStringW(size);
264         if(p)
265         {
266                 i = MtoW(p, size, lpString, c);
267                 p[i] = L'\0';
268         }
269         return p;
270 }
271
272 // メモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換
273 wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)
274 {
275         int count;
276         wchar_t* p;
277         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
278                 return (wchar_t*)lpString;
279         count = GetMultiStringLengthM(lpString) + 1;
280         p = AllocateStringW(count);
281         if(p)
282                 MtoW(p, count, lpString, count);
283         return p;
284 }
285
286 // 指定したサイズのメモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換
287 wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)
288 {
289         int count;
290         wchar_t* p;
291         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
292                 return (wchar_t*)lpString;
293         count = GetMultiStringLengthM(lpString) + 1;
294         p = AllocateStringW(size);
295         if(p)
296         {
297                 MtoW(p, size, lpString, count);
298                 p[size - 2] = L'\0';
299                 p[size - 1] = L'\0';
300         }
301         return p;
302 }
303
304 // メモリを確保してワイド文字列からマルチバイト文字列へ変換
305 char* DuplicateWtoM(LPCWSTR lpString, int c)
306 {
307         char* p;
308         int i;
309         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
310                 return (char*)lpString;
311         if(c < 0)
312                 c = wcslen(lpString);
313         p = AllocateStringM(WtoM(NULL, 0, lpString, c) + 1);
314         if(p)
315         {
316                 i = WtoM(p, 65535, lpString, c);
317                 p[i] = L'\0';
318         }
319         return p;
320 }
321
322 // メモリを確保してワイド文字列からShift_JIS文字列へ変換
323 char* DuplicateWtoA(LPCWSTR lpString, int c)
324 {
325         char* p;
326         int i;
327         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
328                 return (char*)lpString;
329         if(c < 0)
330                 c = wcslen(lpString);
331         p = AllocateStringA(WtoA(NULL, 0, lpString, c) + 1);
332         if(p)
333         {
334                 i = WtoA(p, 65535, lpString, c);
335                 p[i] = L'\0';
336         }
337         return p;
338 }
339
340 // 文字列用に確保したメモリを開放
341 void FreeDuplicatedString(void* p)
342 {
343         if(p < (void*)0x00010000 || p == (void*)~0)
344                 return;
345         free(p);
346 }
347
348 // 以下ラッパー
349 // 戻り値バッファ r
350 // ワイド文字バッファ pw%d
351 // マルチバイト文字バッファ pm%d
352 // 引数バッファ a%d
353
354 #define START_ROUTINE                                   do{
355 #define END_ROUTINE                                             }while(0);end_of_routine:
356 #define QUIT_ROUTINE                                    goto end_of_routine;
357
358 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
359 {
360         int r = 0;
361         char* pm0 = NULL;
362 START_ROUTINE
363         pm0 = DuplicateWtoM(lpCmdLine, -1);
364         r = WinMainM(hInstance, hPrevInstance, pm0, nCmdShow);
365 END_ROUTINE
366         FreeDuplicatedString(pm0);
367         return r;
368 }
369
370 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
371 {
372         HANDLE r = INVALID_HANDLE_VALUE;
373         wchar_t* pw0 = NULL;
374 START_ROUTINE
375         pw0 = DuplicateMtoW(lpFileName, -1);
376         r = CreateFileW(pw0, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
377 END_ROUTINE
378         FreeDuplicatedString(pw0);
379         return r;
380 }
381
382 int MessageBoxM(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
383 {
384         int r = IDOK;
385         wchar_t* pw0 = NULL;
386         wchar_t* pw1 = NULL;
387 START_ROUTINE
388         pw0 = DuplicateMtoW(lpText, -1);
389         pw1 = DuplicateMtoW(lpCaption, -1);
390         r = MessageBoxW(hWnd, pw0, pw1, uType);
391 END_ROUTINE
392         FreeDuplicatedString(pw0);
393         FreeDuplicatedString(pw1);
394         return r;
395 }
396
397 HANDLE FindFirstFileM(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
398 {
399         HANDLE r = INVALID_HANDLE_VALUE;
400         wchar_t* pw0 = NULL;
401         WIN32_FIND_DATAW a0;
402 START_ROUTINE
403         pw0 = DuplicateMtoW(lpFileName, -1);
404         r = FindFirstFileW(pw0, &a0);
405         if(r != INVALID_HANDLE_VALUE)
406         {
407                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;
408                 lpFindFileData->ftCreationTime = a0.ftCreationTime;
409                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;
410                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;
411                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;
412                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;
413                 lpFindFileData->dwReserved0 = a0.dwReserved0;
414                 lpFindFileData->dwReserved1 = a0.dwReserved1;
415                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);
416                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);
417         }
418 END_ROUTINE
419         FreeDuplicatedString(pw0);
420         return r;
421 }
422
423 BOOL FindNextFileM(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
424 {
425         BOOL r = FALSE;
426         WIN32_FIND_DATAW a0;
427 START_ROUTINE
428         r = FindNextFileW(hFindFile, &a0);
429         if(r)
430         {
431                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;
432                 lpFindFileData->ftCreationTime = a0.ftCreationTime;
433                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;
434                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;
435                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;
436                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;
437                 lpFindFileData->dwReserved0 = a0.dwReserved0;
438                 lpFindFileData->dwReserved1 = a0.dwReserved1;
439                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);
440                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);
441         }
442 END_ROUTINE
443         return r;
444 }
445
446 DWORD GetLogicalDriveStringsM(DWORD nBufferLength, LPSTR lpBuffer)
447 {
448         DWORD r = 0;
449         wchar_t* pw0 = NULL;
450 START_ROUTINE
451         pw0 = AllocateStringW(nBufferLength * 4);
452         GetLogicalDriveStringsW(nBufferLength * 4, pw0);
453         WtoMMultiString(lpBuffer, nBufferLength, pw0);
454         r = TerminateStringM(lpBuffer, nBufferLength);
455 END_ROUTINE
456         FreeDuplicatedString(pw0);
457         return r;
458 }
459
460 ATOM RegisterClassExM(CONST WNDCLASSEXA * v0)
461 {
462         ATOM r = 0;
463 START_ROUTINE
464         // WNDPROCがShift_JIS用であるため
465         r = RegisterClassExA(v0);
466 END_ROUTINE
467         return r;
468 }
469
470 HWND CreateWindowExM(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
471 {
472         HWND r = NULL;
473         wchar_t* pw0 = NULL;
474         wchar_t* pw1 = NULL;
475 START_ROUTINE
476         pw0 = DuplicateMtoW(lpClassName, -1);
477         pw1 = DuplicateMtoW(lpWindowName, -1);
478         r = CreateWindowExW(dwExStyle, pw0, pw1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
479 END_ROUTINE
480         FreeDuplicatedString(pw0);
481         FreeDuplicatedString(pw1);
482         return r;
483 }
484
485 LONG GetWindowLongM(HWND hWnd, int nIndex)
486 {
487         LRESULT r = 0;
488 START_ROUTINE
489         // WNDPROCがShift_JIS用であるため
490         if(IsWindowUnicode(hWnd))
491                 r = GetWindowLongW(hWnd, nIndex);
492         else
493                 r = GetWindowLongA(hWnd, nIndex);
494 END_ROUTINE
495         return r;
496 }
497
498 LONG SetWindowLongM(HWND hWnd, int nIndex, LONG dwNewLong)
499 {
500         LRESULT r = 0;
501 START_ROUTINE
502         // WNDPROCがShift_JIS用であるため
503         if(IsWindowUnicode(hWnd))
504                 r = SetWindowLongW(hWnd, nIndex, dwNewLong);
505         else
506                 r = SetWindowLongA(hWnd, nIndex, dwNewLong);
507 END_ROUTINE
508         return r;
509 }
510
511 LRESULT DefWindowProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
512 {
513         LRESULT r = 0;
514 START_ROUTINE
515         // WNDPROCがShift_JIS用であるため
516         if(IsWindowUnicode(hWnd))
517                 r = DefWindowProcW(hWnd, Msg, wParam, lParam);
518         else
519                 r = DefWindowProcA(hWnd, Msg, wParam, lParam);
520 END_ROUTINE
521         return r;
522 }
523
524 LRESULT CallWindowProcM(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
525 {
526         LRESULT r = 0;
527 START_ROUTINE
528         // WNDPROCがShift_JIS用であるため
529         if(IsWindowUnicode(hWnd))
530                 r = CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
531         else
532                 r = CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
533 END_ROUTINE
534         return r;
535 }
536
537 LRESULT SendMessageM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
538 {
539         LRESULT r = 0;
540         wchar_t* pw0 = NULL;
541         wchar_t* pw1 = NULL;
542         int Size;
543         LVITEMA* pmLVItem;
544         LVITEMW wLVItem;
545         LVFINDINFOA* pmLVFindInfo;
546         LVFINDINFOW wLVFindInfo;
547         LVCOLUMNA* pmLVColumn;
548         LVCOLUMNW wLVColumn;
549         wchar_t ClassName[MAX_PATH];
550 START_ROUTINE
551         switch(Msg)
552         {
553         case WM_SETTEXT:
554                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
555                 r = SendMessageW(hWnd, WM_SETTEXT, wParam, (LPARAM)pw0);
556                 break;
557         case WM_GETTEXT:
558                 pw0 = AllocateStringW(wParam * 4);
559                 SendMessageW(hWnd, WM_GETTEXT, wParam * 4, (LPARAM)pw0);
560                 WtoM((LPSTR)lParam, wParam, pw0, -1);
561                 r = TerminateStringM((LPSTR)lParam, wParam);
562                 break;
563         case WM_GETTEXTLENGTH:
564                 Size = SendMessageW(hWnd, WM_GETTEXTLENGTH, wParam, lParam) + 1;
565                 pw0 = AllocateStringW(Size);
566                 SendMessageW(hWnd, WM_GETTEXT, (WPARAM)Size, (LPARAM)pw0);
567                 r = WtoM(NULL, 0, pw0, -1) - 1;
568                 break;
569         default:
570                 GetClassNameW(hWnd, ClassName, sizeof(ClassName) / sizeof(wchar_t));
571                 if(_wcsicmp(ClassName, WC_EDITW) == 0)
572                 {
573                         switch(Msg)
574                         {
575                         case EM_REPLACESEL:
576                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
577                                 r = SendMessageW(hWnd, EM_REPLACESEL, wParam, (LPARAM)pw0);
578                                 break;
579                         default:
580                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
581                                 break;
582                         }
583                 }
584                 else if(_wcsicmp(ClassName, WC_COMBOBOXW) == 0)
585                 {
586                         switch(Msg)
587                         {
588                         case CB_ADDSTRING:
589                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
590                                 r = SendMessageW(hWnd, CB_ADDSTRING, wParam, (LPARAM)pw0);
591                                 break;
592                         case CB_GETLBTEXT:
593                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
594                                 pw0 = AllocateStringW(Size);
595                                 SendMessageW(hWnd, CB_GETLBTEXT, wParam, (LPARAM)pw0);
596                                 // バッファ長不明のためオーバーランの可能性あり
597                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);
598                                 r = TerminateStringM((LPSTR)lParam, Size * 4);
599                                 break;
600                         case CB_GETLBTEXTLEN:
601                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
602                                 pw0 = AllocateStringW(Size);
603                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
604                                 r = WtoM(NULL, 0, pw0, -1) - 1;
605                                 break;
606                         case CB_INSERTSTRING:
607                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
608                                 r = SendMessageW(hWnd, CB_INSERTSTRING, wParam, (LPARAM)pw0);
609                                 break;
610                         case CB_FINDSTRINGEXACT:
611                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
612                                 r = SendMessageW(hWnd, CB_FINDSTRINGEXACT, wParam, (LPARAM)pw0);
613                                 break;
614                         default:
615                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
616                                 break;
617                         }
618                 }
619                 else if(_wcsicmp(ClassName, WC_LISTBOXW) == 0)
620                 {
621                         switch(Msg)
622                         {
623                         case LB_ADDSTRING:
624                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
625                                 r = SendMessageW(hWnd, LB_ADDSTRING, wParam, (LPARAM)pw0);
626                                 break;
627                         case LB_INSERTSTRING:
628                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
629                                 r = SendMessageW(hWnd, LB_INSERTSTRING, wParam, (LPARAM)pw0);
630                                 break;
631                         case LB_GETTEXT:
632                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
633                                 pw0 = AllocateStringW(Size);
634                                 SendMessageW(hWnd, LB_GETTEXT, wParam, (LPARAM)pw0);
635                                 // バッファ長不明のためオーバーランの可能性あり
636                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);
637                                 r = TerminateStringM((LPSTR)lParam, Size * 4);
638                                 break;
639                         case LB_GETTEXTLEN:
640                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
641                                 pw0 = AllocateStringW(Size);
642                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
643                                 r = WtoM(NULL, 0, pw0, -1) - 1;
644                                 break;
645                         default:
646                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
647                                 break;
648                         }
649                 }
650                 else if(_wcsicmp(ClassName, WC_LISTVIEWW) == 0)
651                 {
652                         switch(Msg)
653                         {
654                         case LVM_GETITEMA:
655                                 pmLVItem = (LVITEMA*)lParam;
656                                 wLVItem.mask = pmLVItem->mask;
657                                 wLVItem.iItem = pmLVItem->iItem;
658                                 wLVItem.iSubItem = pmLVItem->iSubItem;
659                                 wLVItem.state = pmLVItem->state;
660                                 wLVItem.stateMask = pmLVItem->stateMask;
661                                 if(pmLVItem->mask & LVIF_TEXT)
662                                 {
663                                         Size = pmLVItem->cchTextMax * 4;
664                                         pw0 = AllocateStringW(Size);
665                                         wLVItem.pszText = pw0;
666                                         wLVItem.cchTextMax = Size;
667                                 }
668                                 wLVItem.iImage = pmLVItem->iImage;
669                                 wLVItem.lParam = pmLVItem->lParam;
670                                 wLVItem.iIndent = pmLVItem->iIndent;
671                                 r = SendMessageW(hWnd, LVM_GETITEMW, wParam, (LPARAM)&wLVItem);
672                                 pmLVItem->mask = wLVItem.mask;
673                                 pmLVItem->iItem = wLVItem.iItem;
674                                 pmLVItem->iSubItem = wLVItem.iSubItem;
675                                 pmLVItem->state = wLVItem.state;
676                                 pmLVItem->stateMask = wLVItem.stateMask;
677                                 if(pmLVItem->mask & LVIF_TEXT)
678                                 {
679                                         WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
680                                         TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
681                                 }
682                                 pmLVItem->iImage = wLVItem.iImage;
683                                 pmLVItem->lParam = wLVItem.lParam;
684                                 pmLVItem->iIndent = wLVItem.iIndent;
685                                 break;
686                         case LVM_SETITEMA:
687                                 pmLVItem = (LVITEMA*)lParam;
688                                 wLVItem.mask = pmLVItem->mask;
689                                 wLVItem.iItem = pmLVItem->iItem;
690                                 wLVItem.iSubItem = pmLVItem->iSubItem;
691                                 wLVItem.state = pmLVItem->state;
692                                 wLVItem.stateMask = pmLVItem->stateMask;
693                                 if(pmLVItem->mask & LVIF_TEXT)
694                                 {
695                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
696                                         wLVItem.pszText = pw0;
697                                         // TODO: cchTextMaxの確認
698                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;
699                                 }
700                                 wLVItem.iImage = pmLVItem->iImage;
701                                 wLVItem.lParam = pmLVItem->lParam;
702                                 wLVItem.iIndent = pmLVItem->iIndent;
703                                 r = SendMessageW(hWnd, LVM_SETITEMW, wParam, (LPARAM)&wLVItem);
704                                 break;
705                         case LVM_INSERTITEMA:
706                                 pmLVItem = (LVITEMA*)lParam;
707                                 wLVItem.mask = pmLVItem->mask;
708                                 wLVItem.iItem = pmLVItem->iItem;
709                                 wLVItem.iSubItem = pmLVItem->iSubItem;
710                                 wLVItem.state = pmLVItem->state;
711                                 wLVItem.stateMask = pmLVItem->stateMask;
712                                 if(pmLVItem->mask & LVIF_TEXT)
713                                 {
714                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
715                                         wLVItem.pszText = pw0;
716                                         // TODO: cchTextMaxの確認
717                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;
718                                 }
719                                 wLVItem.iImage = pmLVItem->iImage;
720                                 wLVItem.lParam = pmLVItem->lParam;
721                                 wLVItem.iIndent = pmLVItem->iIndent;
722                                 r = SendMessageW(hWnd, LVM_INSERTITEMW, wParam, (LPARAM)&wLVItem);
723                                 break;
724                         case LVM_FINDITEMA:
725                                 pmLVFindInfo = (LVFINDINFOA*)lParam;
726                                 wLVFindInfo.flags = pmLVFindInfo->flags;
727                                 if(pmLVFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL))
728                                 {
729                                         pw0 = DuplicateMtoW(pmLVFindInfo->psz, -1);
730                                         wLVFindInfo.psz = pw0;
731                                 }
732                                 wLVFindInfo.lParam = pmLVFindInfo->lParam;
733                                 wLVFindInfo.pt = pmLVFindInfo->pt;
734                                 wLVFindInfo.vkDirection = pmLVFindInfo->vkDirection;
735                                 r = SendMessageW(hWnd, LVM_FINDITEMW, wParam, (LPARAM)&wLVItem);
736                                 break;
737                         case LVM_GETCOLUMNA:
738                                 pmLVColumn = (LVCOLUMNA*)lParam;
739                                 wLVColumn.mask = pmLVColumn->mask;
740                                 wLVColumn.fmt = pmLVColumn->fmt;
741                                 wLVColumn.cx = pmLVColumn->cx;
742                                 Size = pmLVColumn->cchTextMax * 4;
743                                 if(pmLVColumn->mask & LVCF_TEXT)
744                                 {
745                                         pw0 = AllocateStringW(Size);
746                                         wLVColumn.pszText = pw0;
747                                         wLVColumn.cchTextMax = Size;
748                                 }
749                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;
750                                 wLVColumn.iImage = pmLVColumn->iImage;
751                                 wLVColumn.iOrder = pmLVColumn->iOrder;
752                                 r = SendMessageW(hWnd, LVM_GETCOLUMNW, wParam, (LPARAM)&wLVColumn);
753                                 pmLVColumn->mask = wLVColumn.mask;
754                                 pmLVColumn->fmt = wLVColumn.fmt;
755                                 pmLVColumn->cx = wLVColumn.cx;
756                                 if(pmLVColumn->mask & LVCF_TEXT)
757                                 {
758                                         WtoM(pmLVColumn->pszText, pmLVColumn->cchTextMax, wLVColumn.pszText, -1);
759                                         TerminateStringM(pmLVColumn->pszText, pmLVColumn->cchTextMax);
760                                 }
761                                 pmLVColumn->iSubItem = wLVColumn.iSubItem;
762                                 pmLVColumn->iImage = wLVColumn.iImage;
763                                 pmLVColumn->iOrder = wLVColumn.iOrder;
764                                 break;
765                         case LVM_INSERTCOLUMNA:
766                                 pmLVColumn = (LVCOLUMNA*)lParam;
767                                 wLVColumn.mask = pmLVColumn->mask;
768                                 wLVColumn.fmt = pmLVColumn->fmt;
769                                 wLVColumn.cx = pmLVColumn->cx;
770                                 if(pmLVColumn->mask & LVCF_TEXT)
771                                 {
772                                         pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);
773                                         wLVColumn.pszText = pw0;
774                                         // TODO: cchTextMaxの確認
775                                         wLVColumn.cchTextMax = pmLVColumn->cchTextMax;
776                                 }
777                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;
778                                 wLVColumn.iImage = pmLVColumn->iImage;
779                                 wLVColumn.iOrder = pmLVColumn->iOrder;
780                                 r = SendMessageW(hWnd, LVM_INSERTCOLUMNW, wParam, (LPARAM)&wLVColumn);
781                                 break;
782                         case LVM_GETITEMTEXTA:
783                                 pmLVItem = (LVITEMA*)lParam;
784                                 wLVItem.mask = pmLVItem->mask;
785                                 wLVItem.iItem = pmLVItem->iItem;
786                                 wLVItem.iSubItem = pmLVItem->iSubItem;
787                                 wLVItem.state = pmLVItem->state;
788                                 wLVItem.stateMask = pmLVItem->stateMask;
789                                 Size = pmLVItem->cchTextMax * 4;
790                                 pw0 = AllocateStringW(Size);
791                                 wLVItem.pszText = pw0;
792                                 wLVItem.cchTextMax = Size;
793                                 wLVItem.iImage = pmLVItem->iImage;
794                                 wLVItem.lParam = pmLVItem->lParam;
795                                 wLVItem.iIndent = pmLVItem->iIndent;
796                                 r = SendMessageW(hWnd, LVM_GETITEMTEXTW, wParam, (LPARAM)&wLVItem);
797                                 pmLVItem->mask = wLVItem.mask;
798                                 pmLVItem->iItem = wLVItem.iItem;
799                                 pmLVItem->iSubItem = wLVItem.iSubItem;
800                                 pmLVItem->state = wLVItem.state;
801                                 pmLVItem->stateMask = wLVItem.stateMask;
802                                 WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
803                                 TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
804                                 pmLVItem->iImage = wLVItem.iImage;
805                                 pmLVItem->lParam = wLVItem.lParam;
806                                 pmLVItem->iIndent = wLVItem.iIndent;
807                                 break;
808                         default:
809                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
810                                 break;
811                         }
812                 }
813                 else if(_wcsicmp(ClassName, STATUSCLASSNAMEW) == 0)
814                 {
815                         switch(Msg)
816                         {
817                         case SB_SETTEXTA:
818                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
819                                 r = SendMessageW(hWnd, SB_SETTEXTW, wParam, (LPARAM)pw0);
820                                 break;
821                         default:
822                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
823                                 break;
824                         }
825                 }
826                 else
827                         r = SendMessageW(hWnd, Msg, wParam, lParam);
828                 break;
829         }
830 END_ROUTINE
831         FreeDuplicatedString(pw0);
832         FreeDuplicatedString(pw1);
833         return r;
834 }
835
836 LRESULT DefDlgProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
837 {
838         LRESULT r = 0;
839 START_ROUTINE
840         // WNDPROCがShift_JIS用であるため
841         if(IsWindowUnicode(hWnd))
842                 r = DefDlgProcW(hWnd, Msg, wParam, lParam);
843         else
844                 r = DefDlgProcA(hWnd, Msg, wParam, lParam);
845 END_ROUTINE
846         return r;
847 }
848
849 LRESULT SendDlgItemMessageM(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam)
850 {
851         LRESULT r = 0;
852 START_ROUTINE
853         r = SendMessageM(GetDlgItem(hDlg, nIDDlgItem), Msg, wParam, lParam);
854 END_ROUTINE
855         return r;
856 }
857
858 BOOL SetWindowTextM(HWND hWnd, LPCSTR lpString)
859 {
860         BOOL r = FALSE;
861         wchar_t* pw0 = NULL;
862 START_ROUTINE
863         pw0 = DuplicateMtoW(lpString, -1);
864         r = SetWindowTextW(hWnd, pw0);
865 END_ROUTINE
866         FreeDuplicatedString(pw0);
867         return r;
868 }
869
870 UINT DragQueryFileM(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch)
871 {
872         UINT r = 0;
873         wchar_t* pw0 = NULL;
874 START_ROUTINE
875         if(iFile == (UINT)-1)
876                 r = DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);
877         else
878         {
879                 pw0 = AllocateStringW(cch * 4);
880                 DragQueryFileW(hDrop, iFile, pw0, cch * 4);
881                 WtoM(lpszFile, cch, pw0, -1);
882                 r = TerminateStringM(lpszFile, cch);
883         }
884 END_ROUTINE
885         FreeDuplicatedString(pw0);
886         return r;
887 }
888
889 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)
890 {
891         DWORD r = 0;
892         wchar_t* pw0 = NULL;
893 START_ROUTINE
894         pw0 = AllocateStringW(nBufferLength * 4);
895         GetCurrentDirectoryW(nBufferLength * 4, pw0);
896         WtoM(lpBuffer, nBufferLength, pw0, -1);
897         r = TerminateStringM(lpBuffer, nBufferLength);
898 END_ROUTINE
899         FreeDuplicatedString(pw0);
900         return r;
901 }
902
903 BOOL SetCurrentDirectoryM(LPCSTR lpPathName)
904 {
905         BOOL r = FALSE;
906         wchar_t* pw0 = NULL;
907 START_ROUTINE
908         pw0 = DuplicateMtoW(lpPathName, -1);
909         r = SetCurrentDirectoryW(pw0);
910 END_ROUTINE
911         FreeDuplicatedString(pw0);
912         return r;
913 }
914
915 BOOL SetDllDirectoryM(LPCSTR lpPathName)
916 {
917         BOOL r = FALSE;
918         wchar_t* pw0 = NULL;
919 START_ROUTINE
920         pw0 = DuplicateMtoW(lpPathName, -1);
921         r = SetDllDirectoryW(pw0);
922 END_ROUTINE
923         FreeDuplicatedString(pw0);
924         return r;
925 }
926
927 DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)
928 {
929         DWORD r = 0;
930         wchar_t* pw0 = NULL;
931 START_ROUTINE
932         pw0 = AllocateStringW(nBufferLength * 4);
933         GetTempPathW(nBufferLength * 4, pw0);
934         WtoM(lpBuffer, nBufferLength, pw0, -1);
935         r = TerminateStringM(lpBuffer, nBufferLength);
936 END_ROUTINE
937         FreeDuplicatedString(pw0);
938         return r;
939 }
940
941 DWORD GetFileAttributesM(LPCSTR lpFileName)
942 {
943         DWORD r = FALSE;
944         wchar_t* pw0 = NULL;
945 START_ROUTINE
946         pw0 = DuplicateMtoW(lpFileName, -1);
947         r = GetFileAttributesW(pw0);
948 END_ROUTINE
949         FreeDuplicatedString(pw0);
950         return r;
951 }
952
953 DWORD GetModuleFileNameM(HMODULE hModule, LPCH lpFilename, DWORD nSize)
954 {
955         DWORD r = 0;
956         wchar_t* pw0 = NULL;
957 START_ROUTINE
958         pw0 = AllocateStringW(nSize * 4);
959         GetModuleFileNameW(hModule, pw0, nSize * 4);
960         WtoM(lpFilename, nSize, pw0, -1);
961         r = TerminateStringM(lpFilename, nSize);
962 END_ROUTINE
963         FreeDuplicatedString(pw0);
964         return r;
965 }
966
967 LSTATUS RegOpenKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
968 {
969         LSTATUS r = 0;
970         wchar_t* pw0 = NULL;
971 START_ROUTINE
972         pw0 = DuplicateMtoW(lpSubKey, -1);
973         r = RegOpenKeyExW(hKey, pw0, ulOptions, samDesired, phkResult);
974 END_ROUTINE
975         FreeDuplicatedString(pw0);
976         return r;
977 }
978
979 LSTATUS RegCreateKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
980 {
981         LSTATUS r = 0;
982         wchar_t* pw0 = NULL;
983         wchar_t* pw1 = NULL;
984 START_ROUTINE
985         pw0 = DuplicateMtoW(lpSubKey, -1);
986         pw1 = DuplicateMtoW(lpClass, -1);
987         r = RegCreateKeyExW(hKey, pw0, Reserved, pw1, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
988 END_ROUTINE
989         FreeDuplicatedString(pw0);
990         FreeDuplicatedString(pw1);
991         return r;
992 }
993
994 LSTATUS RegDeleteValueM(HKEY hKey, LPCSTR lpValueName)
995 {
996         LSTATUS r = 0;
997         wchar_t* pw0 = NULL;
998 START_ROUTINE
999         pw0 = DuplicateMtoW(lpValueName, -1);
1000         r = RegDeleteValueW(hKey, pw0);
1001 END_ROUTINE
1002         FreeDuplicatedString(pw0);
1003         return r;
1004 }
1005
1006 LSTATUS RegQueryValueExM(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
1007 {
1008         LSTATUS r = 0;
1009         wchar_t* pw0 = NULL;
1010         wchar_t* pw1 = NULL;
1011         DWORD dwType;
1012         DWORD wcbData;
1013 START_ROUTINE
1014         pw0 = DuplicateMtoW(lpValueName, -1);
1015         if(RegQueryValueExW(hKey, pw0, NULL, &dwType, NULL, 0) == ERROR_SUCCESS)
1016         {
1017                 switch(dwType)
1018                 {
1019                 case REG_SZ:
1020                 case REG_EXPAND_SZ:
1021                 case REG_MULTI_SZ:
1022                         if(lpcbData)
1023                         {
1024                                 pw1 = AllocateStringW(*lpcbData / sizeof(char) * 4);
1025                                 wcbData = *lpcbData / sizeof(char) * 4;
1026                                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, (LPBYTE)pw1, &wcbData);
1027                                 if(lpData)
1028                                         *lpcbData = sizeof(char) * WtoM((char*)lpData, *lpcbData / sizeof(char), pw1, wcbData / sizeof(wchar_t));
1029                                 else
1030                                         *lpcbData = sizeof(char) * WtoM(NULL, 0, pw1, wcbData / sizeof(wchar_t));
1031                         }
1032                         break;
1033                 default:
1034                         r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
1035                         break;
1036                 }
1037         }
1038         else
1039                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
1040 END_ROUTINE
1041         FreeDuplicatedString(pw0);
1042         FreeDuplicatedString(pw1);
1043         return r;
1044 }
1045
1046 LSTATUS RegSetValueExM(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData)
1047 {
1048         LSTATUS r = 0;
1049         wchar_t* pw0 = NULL;
1050         wchar_t* pw1 = NULL;
1051         DWORD wcbData;
1052 START_ROUTINE
1053         pw0 = DuplicateMtoW(lpValueName, -1);
1054         switch(dwType)
1055         {
1056         case REG_SZ:
1057         case REG_EXPAND_SZ:
1058         case REG_MULTI_SZ:
1059                 wcbData = MtoW(NULL, 0, (char*)lpData, cbData / sizeof(char));
1060                 pw1 = AllocateStringW(wcbData);
1061                 MtoW(pw1, wcbData, (char*)lpData, cbData / sizeof(char));
1062                 wcbData = sizeof(wchar_t) * wcbData;
1063                 lpData = (BYTE*)pw1;
1064                 cbData = wcbData;
1065                 break;
1066         }
1067         r = RegSetValueExW(hKey, pw0, Reserved, dwType, lpData, cbData);
1068 END_ROUTINE
1069         FreeDuplicatedString(pw0);
1070         FreeDuplicatedString(pw1);
1071         return r;
1072 }
1073
1074 BOOL TextOutM(HDC hdc, int x, int y, LPCSTR lpString, int c)
1075 {
1076         BOOL r = FALSE;
1077         wchar_t* pw0 = NULL;
1078 START_ROUTINE
1079         pw0 = DuplicateMtoW(lpString, c);
1080         r = TextOutW(hdc, x, y, pw0, wcslen(pw0));
1081 END_ROUTINE
1082         FreeDuplicatedString(pw0);
1083         return r;
1084 }
1085
1086 BOOL GetTextExtentPoint32M(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl)
1087 {
1088         BOOL r = FALSE;
1089         wchar_t* pw0 = NULL;
1090 START_ROUTINE
1091         pw0 = DuplicateMtoW(lpString, c);
1092         r = GetTextExtentPoint32W(hdc, pw0, wcslen(pw0), psizl);
1093 END_ROUTINE
1094         FreeDuplicatedString(pw0);
1095         return r;
1096 }
1097
1098 INT_PTR PropertySheetM(LPCPROPSHEETHEADERA v0)
1099 {
1100         INT_PTR r = 0;
1101         PROPSHEETHEADERW a0;
1102         PROPSHEETPAGEW* pwPage;
1103         UINT i;
1104 START_ROUTINE
1105         a0.dwSize = sizeof(PROPSHEETHEADERW);
1106         a0.dwFlags = v0->dwFlags;
1107         a0.hwndParent = v0->hwndParent;
1108         a0.hInstance = v0->hInstance;
1109         if(v0->dwFlags & PSH_USEICONID)
1110                 a0.pszIcon = DuplicateMtoW(v0->pszIcon, -1);
1111         else
1112                 a0.hIcon = v0->hIcon;
1113         a0.pszCaption = DuplicateMtoW(v0->pszCaption, -1);
1114         a0.nPages = v0->nPages;
1115         a0.pStartPage = DuplicateMtoW(v0->pStartPage, -1);
1116         if(v0->ppsp && (pwPage = (PROPSHEETPAGEW*)malloc(sizeof(PROPSHEETPAGEW) * v0->nPages)))
1117         {
1118                 for(i = 0; i < v0->nPages; i++)
1119                 {
1120                         pwPage[i].dwSize = sizeof(PROPSHEETPAGEW);
1121                         pwPage[i].dwFlags = v0->ppsp[i].dwFlags;
1122                         pwPage[i].hInstance = v0->ppsp[i].hInstance;
1123                         pwPage[i].pszTemplate = DuplicateMtoW(v0->ppsp[i].pszTemplate, -1);
1124                         if(v0->ppsp[i].dwFlags & PSP_USEICONID)
1125                                 pwPage[i].pszIcon = DuplicateMtoW(v0->ppsp[i].pszIcon, -1);
1126                         else
1127                                 pwPage[i].hIcon = v0->ppsp[i].hIcon;
1128                         if(v0->ppsp[i].dwFlags & PSP_USETITLE)
1129                                 pwPage[i].pszTitle = DuplicateMtoW(v0->ppsp[i].pszTitle, -1);
1130                         pwPage[i].pfnDlgProc = v0->ppsp[i].pfnDlgProc;
1131                         pwPage[i].lParam = v0->ppsp[i].lParam;
1132                         // TODO: pfnCallback
1133                         pwPage[i].pfnCallback = v0->ppsp[i].pfnCallback;
1134                         pwPage[i].pcRefParent = v0->ppsp[i].pcRefParent;
1135 //                      pwPage[i].pszHeaderTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderTitle, -1);
1136 //                      pwPage[i].pszHeaderSubTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderSubTitle, -1);
1137                         pwPage[i].hActCtx = v0->ppsp[i].hActCtx;
1138 //                      pwPage[i].pszbmHeader = DuplicateMtoW(v0->ppsp[i].pszbmHeader, -1);
1139                 }
1140         }
1141         else
1142                 pwPage = NULL;
1143         a0.ppsp = pwPage;
1144         a0.pfnCallback = v0->pfnCallback;
1145         r = PropertySheetW(&a0);
1146         if(a0.dwFlags & PSH_USEICONID)
1147                 FreeDuplicatedString(a0.pszIcon);
1148         FreeDuplicatedString(a0.pszCaption);
1149         FreeDuplicatedString(a0.pStartPage);
1150         if(pwPage)
1151         {
1152                 for(i = 0; i < v0->nPages; i++)
1153                 {
1154                         FreeDuplicatedString(pwPage[i].pszTemplate);
1155                         if(pwPage[i].dwFlags & PSP_USEICONID)
1156                                 FreeDuplicatedString(pwPage[i].pszIcon);
1157                         if(pwPage[i].dwFlags & PSP_USETITLE)
1158                                 FreeDuplicatedString(pwPage[i].pszTitle);
1159 //                      FreeDuplicatedString(pwPage[i].pszHeaderTitle);
1160 //                      FreeDuplicatedString(pwPage[i].pszHeaderSubTitle);
1161 //                      FreeDuplicatedString(pwPage[i].pszbmHeader);
1162                 }
1163                 free(pwPage);
1164         }
1165 END_ROUTINE
1166         return r;
1167 }
1168
1169 BOOL GetOpenFileNameM(LPOPENFILENAMEA v0)
1170 {
1171         BOOL r = FALSE;
1172         wchar_t* pw0 = NULL;
1173         wchar_t* pw1 = NULL;
1174         wchar_t* pw2 = NULL;
1175         wchar_t* pw3 = NULL;
1176         wchar_t* pw4 = NULL;
1177         wchar_t* pw5 = NULL;
1178         wchar_t* pw6 = NULL;
1179         wchar_t* pw7 = NULL;
1180         wchar_t* pw8 = NULL;
1181         wchar_t* pw9 = NULL;
1182         OPENFILENAMEW wofn;
1183 START_ROUTINE
1184         wofn.lStructSize = sizeof(OPENFILENAMEW);
1185         wofn.hwndOwner = v0->hwndOwner;
1186         wofn.hInstance = v0->hInstance;
1187         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);
1188         wofn.lpstrFilter = pw0;
1189         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);
1190         wofn.lpstrCustomFilter = pw1;
1191         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;
1192         wofn.nFilterIndex = v0->nFilterIndex;
1193         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);
1194         wofn.lpstrFile = pw2;
1195         wofn.nMaxFile = v0->nMaxFile * 4;
1196         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);
1197         wofn.lpstrFileTitle = pw3;
1198         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;
1199         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);
1200         wofn.lpstrInitialDir = pw4;
1201         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);
1202         wofn.lpstrTitle = pw5;
1203         wofn.Flags = v0->Flags;
1204         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);
1205         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);
1206         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);
1207         wofn.lpstrDefExt = pw6;
1208         wofn.lCustData = v0->lCustData;
1209         wofn.lpfnHook = v0->lpfnHook;
1210         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1211         wofn.pvReserved = v0->pvReserved;
1212         wofn.FlagsEx = v0->FlagsEx;
1213         r = GetOpenFileNameW(&wofn);
1214         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);
1215         TerminateStringM(v0->lpstrFile, v0->nMaxFile);
1216         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);
1217         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);
1218 END_ROUTINE
1219         FreeDuplicatedString(pw0);
1220         FreeDuplicatedString(pw1);
1221         FreeDuplicatedString(pw2);
1222         FreeDuplicatedString(pw3);
1223         FreeDuplicatedString(pw4);
1224         FreeDuplicatedString(pw5);
1225         FreeDuplicatedString(pw6);
1226         return r;
1227 }
1228
1229 BOOL GetSaveFileNameM(LPOPENFILENAMEA v0)
1230 {
1231         BOOL r = FALSE;
1232         wchar_t* pw0 = NULL;
1233         wchar_t* pw1 = NULL;
1234         wchar_t* pw2 = NULL;
1235         wchar_t* pw3 = NULL;
1236         wchar_t* pw4 = NULL;
1237         wchar_t* pw5 = NULL;
1238         wchar_t* pw6 = NULL;
1239         wchar_t* pw7 = NULL;
1240         wchar_t* pw8 = NULL;
1241         wchar_t* pw9 = NULL;
1242         OPENFILENAMEW wofn;
1243 START_ROUTINE
1244         wofn.lStructSize = sizeof(OPENFILENAMEW);
1245         wofn.hwndOwner = v0->hwndOwner;
1246         wofn.hInstance = v0->hInstance;
1247         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);
1248         wofn.lpstrFilter = pw0;
1249         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);
1250         wofn.lpstrCustomFilter = pw1;
1251         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;
1252         wofn.nFilterIndex = v0->nFilterIndex;
1253         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);
1254         wofn.lpstrFile = pw2;
1255         wofn.nMaxFile = v0->nMaxFile * 4;
1256         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);
1257         wofn.lpstrFileTitle = pw3;
1258         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;
1259         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);
1260         wofn.lpstrInitialDir = pw4;
1261         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);
1262         wofn.lpstrTitle = pw5;
1263         wofn.Flags = v0->Flags;
1264         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);
1265         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);
1266         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);
1267         wofn.lpstrDefExt = pw6;
1268         wofn.lCustData = v0->lCustData;
1269         wofn.lpfnHook = v0->lpfnHook;
1270         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1271         wofn.pvReserved = v0->pvReserved;
1272         wofn.FlagsEx = v0->FlagsEx;
1273         r = GetSaveFileNameW(&wofn);
1274         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);
1275         TerminateStringM(v0->lpstrFile, v0->nMaxFile);
1276         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);
1277         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);
1278 END_ROUTINE
1279         FreeDuplicatedString(pw0);
1280         FreeDuplicatedString(pw1);
1281         FreeDuplicatedString(pw2);
1282         FreeDuplicatedString(pw3);
1283         FreeDuplicatedString(pw4);
1284         FreeDuplicatedString(pw5);
1285         FreeDuplicatedString(pw6);
1286         return r;
1287 }
1288
1289 HWND HtmlHelpM(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
1290 {
1291         HWND r = NULL;
1292         wchar_t* pw0 = NULL;
1293 START_ROUTINE
1294         pw0 = DuplicateMtoW(pszFile, -1);
1295         r = HtmlHelpW(hwndCaller, pw0, uCommand, dwData);
1296 END_ROUTINE
1297         FreeDuplicatedString(pw0);
1298         return r;
1299 }
1300
1301 BOOL CreateProcessM(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
1302 {
1303         BOOL r = FALSE;
1304         wchar_t* pw0 = NULL;
1305         wchar_t* pw1 = NULL;
1306         wchar_t* pw2 = NULL;
1307         wchar_t* pw3 = NULL;
1308         wchar_t* pw4 = NULL;
1309         wchar_t* pw5 = NULL;
1310         STARTUPINFOW wStartupInfo;
1311 START_ROUTINE
1312         pw0 = DuplicateMtoW(lpApplicationName, -1);
1313         pw1 = DuplicateMtoWBuffer(lpCommandLine, -1, (strlen(lpCommandLine) + 1) * 4);
1314         pw2 = DuplicateMtoW(lpCurrentDirectory, -1);
1315         wStartupInfo.cb = sizeof(LPSTARTUPINFOW);
1316         pw3 = DuplicateMtoW(lpStartupInfo->lpReserved, -1);
1317         wStartupInfo.lpReserved = pw3;
1318         pw4 = DuplicateMtoW(lpStartupInfo->lpDesktop, -1);
1319         wStartupInfo.lpDesktop = pw4;
1320         pw5 = DuplicateMtoW(lpStartupInfo->lpTitle, -1);
1321         wStartupInfo.lpTitle = pw5;
1322         wStartupInfo.dwX = lpStartupInfo->dwX;
1323         wStartupInfo.dwY = lpStartupInfo->dwY;
1324         wStartupInfo.dwXSize = lpStartupInfo->dwXSize;
1325         wStartupInfo.dwYSize = lpStartupInfo->dwYSize;
1326         wStartupInfo.dwXCountChars = lpStartupInfo->dwXCountChars;
1327         wStartupInfo.dwYCountChars = lpStartupInfo->dwYCountChars;
1328         wStartupInfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
1329         wStartupInfo.dwFlags = lpStartupInfo->dwFlags;
1330         wStartupInfo.wShowWindow = lpStartupInfo->wShowWindow;
1331         wStartupInfo.cbReserved2 = lpStartupInfo->cbReserved2;
1332         wStartupInfo.lpReserved2 = lpStartupInfo->lpReserved2;
1333         wStartupInfo.hStdInput = lpStartupInfo->hStdInput;
1334         wStartupInfo.hStdOutput = lpStartupInfo->hStdOutput;
1335         wStartupInfo.hStdError = lpStartupInfo->hStdError;
1336         r = CreateProcessW(pw0, pw1, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, pw2, &wStartupInfo, lpProcessInformation);
1337         WtoM(lpCommandLine, strlen(lpCommandLine) + 1, pw1, -1);
1338 END_ROUTINE
1339         FreeDuplicatedString(pw0);
1340         FreeDuplicatedString(pw1);
1341         FreeDuplicatedString(pw2);
1342         FreeDuplicatedString(pw3);
1343         FreeDuplicatedString(pw4);
1344         FreeDuplicatedString(pw5);
1345         return r;
1346 }
1347
1348 HINSTANCE FindExecutableM(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
1349 {
1350         HINSTANCE r = NULL;
1351         wchar_t* pw0 = NULL;
1352         wchar_t* pw1 = NULL;
1353         wchar_t* pw2 = NULL;
1354         wchar_t* pw3 = NULL;
1355 START_ROUTINE
1356         pw0 = DuplicateMtoW(lpFile, -1);
1357         pw1 = DuplicateMtoW(lpDirectory, -1);
1358         pw2 = AllocateStringW(MAX_PATH * 4);
1359         r = FindExecutableW(pw0, pw1, pw2);
1360         // バッファ長不明のためオーバーランの可能性あり
1361         WtoM(lpResult, MAX_PATH, pw2, -1);
1362         TerminateStringM(lpResult, MAX_PATH);
1363 END_ROUTINE
1364         FreeDuplicatedString(pw0);
1365         FreeDuplicatedString(pw1);
1366         FreeDuplicatedString(pw2);
1367         FreeDuplicatedString(pw3);
1368         return r;
1369 }
1370
1371 HINSTANCE ShellExecuteM(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
1372 {
1373         HINSTANCE r = NULL;
1374         wchar_t* pw0 = NULL;
1375         wchar_t* pw1 = NULL;
1376         wchar_t* pw2 = NULL;
1377         wchar_t* pw3 = NULL;
1378 START_ROUTINE
1379         pw0 = DuplicateMtoW(lpOperation, -1);
1380         pw1 = DuplicateMtoW(lpFile, -1);
1381         pw2 = DuplicateMtoW(lpParameters, -1);
1382         pw3 = DuplicateMtoW(lpDirectory, -1);
1383         r = ShellExecuteW(hwnd, pw0, pw1, pw2, pw3, nShowCmd);
1384 END_ROUTINE
1385         FreeDuplicatedString(pw0);
1386         FreeDuplicatedString(pw1);
1387         FreeDuplicatedString(pw2);
1388         FreeDuplicatedString(pw3);
1389         return r;
1390 }
1391
1392 PIDLIST_ABSOLUTE SHBrowseForFolderM(LPBROWSEINFOA lpbi)
1393 {
1394         PIDLIST_ABSOLUTE r = NULL;
1395         wchar_t* pw0 = NULL;
1396         wchar_t* pw1 = NULL;
1397         BROWSEINFOW wbi;
1398 START_ROUTINE
1399         wbi.hwndOwner = lpbi->hwndOwner;
1400         wbi.pidlRoot = lpbi->pidlRoot;
1401         pw0 = DuplicateMtoWBuffer(lpbi->pszDisplayName, -1, MAX_PATH * 4);
1402         wbi.pszDisplayName = pw0;
1403         pw1 = DuplicateMtoW(lpbi->lpszTitle, -1);
1404         wbi.lpszTitle = pw1;
1405         wbi.ulFlags = lpbi->ulFlags;
1406         // TODO: lpfn
1407         wbi.lpfn = lpbi->lpfn;
1408         wbi.lParam = lpbi->lParam;
1409         wbi.iImage = lpbi->iImage;
1410         r = SHBrowseForFolderW(&wbi);
1411         // バッファ長不明のためオーバーランの可能性あり
1412         WtoM(lpbi->pszDisplayName, MAX_PATH, wbi.pszDisplayName, -1);
1413         lpbi->iImage = wbi.iImage;
1414 END_ROUTINE
1415         FreeDuplicatedString(pw0);
1416         FreeDuplicatedString(pw1);
1417         return r;
1418 }
1419
1420 BOOL SHGetPathFromIDListM(PCIDLIST_ABSOLUTE pidl, LPSTR pszPath)
1421 {
1422         BOOL r = FALSE;
1423         wchar_t* pw0 = NULL;
1424 START_ROUTINE
1425         pw0 = AllocateStringW(MAX_PATH * 4);
1426         r = SHGetPathFromIDListW(pidl, pw0);
1427         // バッファ長不明のためオーバーランの可能性あり
1428         WtoM(pszPath, MAX_PATH, pw0, -1);
1429         TerminateStringM(pszPath, MAX_PATH);
1430 END_ROUTINE
1431         FreeDuplicatedString(pw0);
1432         return r;
1433 }
1434
1435 int SHFileOperationM(LPSHFILEOPSTRUCTA lpFileOp)
1436 {
1437         int r = 0;
1438         wchar_t* pw0 = NULL;
1439         wchar_t* pw1 = NULL;
1440         wchar_t* pw2 = NULL;
1441         SHFILEOPSTRUCTW wFileOp;
1442 START_ROUTINE
1443         wFileOp.hwnd = lpFileOp->hwnd;
1444         wFileOp.wFunc = lpFileOp->wFunc;
1445         pw0 = DuplicateMtoWMultiString(lpFileOp->pFrom);
1446         wFileOp.pFrom = pw0;
1447         pw1 = DuplicateMtoWMultiString(lpFileOp->pTo);
1448         wFileOp.pTo = pw1;
1449         wFileOp.fFlags = lpFileOp->fFlags;
1450         wFileOp.fAnyOperationsAborted = lpFileOp->fAnyOperationsAborted;
1451         wFileOp.hNameMappings = lpFileOp->hNameMappings;
1452         pw2 = DuplicateMtoW(lpFileOp->lpszProgressTitle, -1);
1453         r = SHFileOperationW(&wFileOp);
1454         lpFileOp->fAnyOperationsAborted = wFileOp.fAnyOperationsAborted;
1455 END_ROUTINE
1456         FreeDuplicatedString(pw0);
1457         FreeDuplicatedString(pw1);
1458         FreeDuplicatedString(pw2);
1459         return r;
1460 }
1461
1462 BOOL AppendMenuM(HMENU hMenu, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem)
1463 {
1464         int r = 0;
1465         wchar_t* pw0 = NULL;
1466 START_ROUTINE
1467         if(uFlags & (MF_BITMAP | MF_OWNERDRAW))
1468                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, (LPCWSTR)lpNewItem);
1469         else
1470         {
1471                 pw0 = DuplicateMtoW(lpNewItem, -1);
1472                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, pw0);
1473         }
1474 END_ROUTINE
1475         FreeDuplicatedString(pw0);
1476         return r;
1477 }
1478
1479 BOOL GetMenuItemInfoM(HMENU hmenu, UINT item, BOOL fByPosition, LPMENUITEMINFOA lpmii)
1480 {
1481         BOOL r = FALSE;
1482         wchar_t* pw0 = NULL;
1483         MENUITEMINFOW wmii;
1484 START_ROUTINE
1485         wmii.cbSize = sizeof(MENUITEMINFOW);
1486         wmii.fMask = lpmii->fMask;
1487         wmii.fType = lpmii->fType;
1488         wmii.fState = lpmii->fState;
1489         wmii.wID = lpmii->wID;
1490         wmii.hSubMenu = lpmii->hSubMenu;
1491         wmii.hbmpChecked = lpmii->hbmpChecked;
1492         wmii.hbmpUnchecked = lpmii->hbmpUnchecked;
1493         wmii.dwItemData = lpmii->dwItemData;
1494         pw0 = DuplicateMtoWBuffer(lpmii->dwTypeData, -1, lpmii->cch * 4);
1495         wmii.dwTypeData = pw0;
1496         wmii.cch = lpmii->cch * 4;
1497         r = GetMenuItemInfoW(hmenu, item, fByPosition, &wmii);
1498         lpmii->fType = wmii.fType;
1499         lpmii->fState = wmii.fState;
1500         lpmii->wID = wmii.wID;
1501         lpmii->hSubMenu = wmii.hSubMenu;
1502         lpmii->hbmpChecked = wmii.hbmpChecked;
1503         lpmii->hbmpUnchecked = wmii.hbmpUnchecked;
1504         lpmii->dwItemData = wmii.dwItemData;
1505         WtoM(lpmii->dwTypeData, lpmii->cch, wmii.dwTypeData, -1);
1506         TerminateStringM(lpmii->dwTypeData, lpmii->cch);
1507 END_ROUTINE
1508         FreeDuplicatedString(pw0);
1509         return r;
1510 }
1511
1512 HFONT CreateFontIndirectM(CONST LOGFONTA *lplf)
1513 {
1514         HFONT r = NULL;
1515         LOGFONTW wlf;
1516 START_ROUTINE
1517         wlf.lfHeight = lplf->lfHeight;
1518         wlf.lfWidth = lplf->lfWidth;
1519         wlf.lfEscapement = lplf->lfEscapement;
1520         wlf.lfOrientation = lplf->lfOrientation;
1521         wlf.lfWeight = lplf->lfWeight;
1522         wlf.lfItalic = lplf->lfItalic;
1523         wlf.lfUnderline = lplf->lfUnderline;
1524         wlf.lfStrikeOut = lplf->lfStrikeOut;
1525         wlf.lfCharSet = lplf->lfCharSet;
1526         wlf.lfOutPrecision = lplf->lfOutPrecision;
1527         wlf.lfClipPrecision = lplf->lfClipPrecision;
1528         wlf.lfQuality = lplf->lfQuality;
1529         wlf.lfPitchAndFamily = lplf->lfPitchAndFamily;
1530         MtoW(wlf.lfFaceName, LF_FACESIZE, lplf->lfFaceName, -1);
1531         TerminateStringW(wlf.lfFaceName, LF_FACESIZE);
1532         r = CreateFontIndirect(&wlf);
1533 END_ROUTINE
1534         return r;
1535 }
1536
1537 BOOL ChooseFontM(LPCHOOSEFONTA v0)
1538 {
1539         BOOL r = FALSE;
1540         wchar_t* pw0 = NULL;
1541         CHOOSEFONTW a0;
1542         LOGFONTW* pwlf;
1543 START_ROUTINE
1544         a0.lStructSize = sizeof(CHOOSEFONTW);
1545         a0.hwndOwner = v0->hwndOwner;
1546         a0.hDC = v0->hDC;
1547         if(v0->lpLogFont && (pwlf = (LOGFONTW*)malloc(sizeof(LOGFONTW))))
1548         {
1549                 pwlf->lfHeight = v0->lpLogFont->lfHeight;
1550                 pwlf->lfWidth = v0->lpLogFont->lfWidth;
1551                 pwlf->lfEscapement = v0->lpLogFont->lfEscapement;
1552                 pwlf->lfOrientation = v0->lpLogFont->lfOrientation;
1553                 pwlf->lfWeight = v0->lpLogFont->lfWeight;
1554                 pwlf->lfItalic = v0->lpLogFont->lfItalic;
1555                 pwlf->lfUnderline = v0->lpLogFont->lfUnderline;
1556                 pwlf->lfStrikeOut = v0->lpLogFont->lfStrikeOut;
1557                 pwlf->lfCharSet = v0->lpLogFont->lfCharSet;
1558                 pwlf->lfOutPrecision = v0->lpLogFont->lfOutPrecision;
1559                 pwlf->lfClipPrecision = v0->lpLogFont->lfClipPrecision;
1560                 pwlf->lfQuality = v0->lpLogFont->lfQuality;
1561                 pwlf->lfPitchAndFamily = v0->lpLogFont->lfPitchAndFamily;
1562                 MtoW(pwlf->lfFaceName, LF_FACESIZE, v0->lpLogFont->lfFaceName, -1);
1563                 TerminateStringW(pwlf->lfFaceName, LF_FACESIZE);
1564         }
1565         else
1566                 pwlf = NULL;
1567         a0.lpLogFont = pwlf;
1568         a0.iPointSize = v0->iPointSize;
1569         a0.Flags = v0->Flags;
1570         a0.rgbColors = v0->rgbColors;
1571         a0.lCustData = v0->lCustData;
1572         a0.lpfnHook = v0->lpfnHook;
1573         a0.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1574         a0.hInstance = v0->hInstance;
1575         a0.lpszStyle = DuplicateMtoWBuffer(v0->lpszStyle, -1, LF_FACESIZE * 4);
1576         a0.nFontType = v0->nFontType;
1577         a0.nSizeMin = v0->nSizeMin;
1578         a0.nSizeMax = v0->nSizeMax;
1579         r = ChooseFontW(&a0);
1580         if(v0->lpLogFont)
1581         {
1582                 v0->lpLogFont->lfHeight = pwlf->lfHeight;
1583                 v0->lpLogFont->lfWidth = pwlf->lfWidth;
1584                 v0->lpLogFont->lfEscapement = pwlf->lfEscapement;
1585                 v0->lpLogFont->lfOrientation = pwlf->lfOrientation;
1586                 v0->lpLogFont->lfWeight = pwlf->lfWeight;
1587                 v0->lpLogFont->lfItalic = pwlf->lfItalic;
1588                 v0->lpLogFont->lfUnderline = pwlf->lfUnderline;
1589                 v0->lpLogFont->lfStrikeOut = pwlf->lfStrikeOut;
1590                 v0->lpLogFont->lfCharSet = pwlf->lfCharSet;
1591                 v0->lpLogFont->lfOutPrecision = pwlf->lfOutPrecision;
1592                 v0->lpLogFont->lfClipPrecision = pwlf->lfClipPrecision;
1593                 v0->lpLogFont->lfQuality = pwlf->lfQuality;
1594                 v0->lpLogFont->lfPitchAndFamily = pwlf->lfPitchAndFamily;
1595                 WtoM(v0->lpLogFont->lfFaceName, LF_FACESIZE, pwlf->lfFaceName, -1);
1596                 TerminateStringM(v0->lpLogFont->lfFaceName, LF_FACESIZE);
1597         }
1598         v0->rgbColors = a0.rgbColors;
1599         WtoM(v0->lpszStyle, LF_FACESIZE, a0.lpszStyle, -1);
1600         TerminateStringM(v0->lpszStyle, LF_FACESIZE);
1601         v0->nFontType = a0.nFontType;
1602         if(pwlf)
1603                 free(pwlf);
1604         FreeDuplicatedString(a0.lpTemplateName);
1605         FreeDuplicatedString(a0.lpszStyle);
1606 END_ROUTINE
1607         FreeDuplicatedString(pw0);
1608         return r;
1609 }
1610
1611 INT_PTR DialogBoxParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
1612 {
1613         INT_PTR r = 0;
1614         wchar_t* pw0 = NULL;
1615 START_ROUTINE
1616         pw0 = DuplicateMtoW(lpTemplateName, -1);
1617         r = DialogBoxParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
1618 END_ROUTINE
1619         FreeDuplicatedString(pw0);
1620         return r;
1621 }
1622
1623 HWND CreateDialogParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
1624 {
1625         HWND r = NULL;
1626         wchar_t* pw0 = NULL;
1627 START_ROUTINE
1628         pw0 = DuplicateMtoW(lpTemplateName, -1);
1629         r = CreateDialogParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
1630 END_ROUTINE
1631         FreeDuplicatedString(pw0);
1632         return r;
1633 }
1634
1635 int mkdirM(const char * _Path)
1636 {
1637         int r = 0;
1638         wchar_t* pw0 = NULL;
1639 START_ROUTINE
1640         pw0 = DuplicateMtoW(_Path, -1);
1641         r = _wmkdir(pw0);
1642 END_ROUTINE
1643         FreeDuplicatedString(pw0);
1644         return r;
1645 }
1646
1647 int _mkdirM(const char * _Path)
1648 {
1649         int r = 0;
1650         wchar_t* pw0 = NULL;
1651 START_ROUTINE
1652         pw0 = DuplicateMtoW(_Path, -1);
1653         r = _wmkdir(pw0);
1654 END_ROUTINE
1655         FreeDuplicatedString(pw0);
1656         return r;
1657 }
1658
1659 int rmdirM(const char * _Path)
1660 {
1661         int r = 0;
1662         wchar_t* pw0 = NULL;
1663 START_ROUTINE
1664         pw0 = DuplicateMtoW(_Path, -1);
1665         r = _wrmdir(pw0);
1666 END_ROUTINE
1667         FreeDuplicatedString(pw0);
1668         return r;
1669 }
1670
1671 int _rmdirM(const char * _Path)
1672 {
1673         int r = 0;
1674         wchar_t* pw0 = NULL;
1675 START_ROUTINE
1676         pw0 = DuplicateMtoW(_Path, -1);
1677         r = _wrmdir(pw0);
1678 END_ROUTINE
1679         FreeDuplicatedString(pw0);
1680         return r;
1681 }
1682
1683 size_t _mbslenM(const unsigned char * _Str)
1684 {
1685         size_t r = 0;
1686         wchar_t* pw0 = NULL;
1687 START_ROUTINE
1688         pw0 = DuplicateMtoW(_Str, -1);
1689         r = wcslen(pw0);
1690 END_ROUTINE
1691         FreeDuplicatedString(pw0);
1692         return r;
1693 }
1694
1695 unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)
1696 {
1697         unsigned char* r = NULL;
1698         wchar_t* pw0 = NULL;
1699         wchar_t* wr;
1700 START_ROUTINE
1701         pw0 = DuplicateMtoW(_Str, -1);
1702         // TODO: 非ASCII文字の対応
1703         wr = wcschr(pw0, _Ch);
1704         if(wr)
1705         {
1706                 *wr = L'\0';
1707                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1708         }
1709 END_ROUTINE
1710         FreeDuplicatedString(pw0);
1711         return r;
1712 }
1713
1714 unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)
1715 {
1716         unsigned char* r = NULL;
1717         wchar_t* pw0 = NULL;
1718         wchar_t* wr;
1719 START_ROUTINE
1720         pw0 = DuplicateMtoW(_Str, -1);
1721         // TODO: 非ASCII文字の対応
1722         wr = wcsrchr(pw0, _Ch);
1723         if(wr)
1724         {
1725                 *wr = L'\0';
1726                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1727         }
1728 END_ROUTINE
1729         FreeDuplicatedString(pw0);
1730         return r;
1731 }
1732
1733 unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)
1734 {
1735         unsigned char* r = NULL;
1736         wchar_t* pw0 = NULL;
1737         wchar_t* pw1 = NULL;
1738         wchar_t* wr;
1739 START_ROUTINE
1740         pw0 = DuplicateMtoW(_Str, -1);
1741         pw1 = DuplicateMtoW(_Substr, -1);
1742         wr = wcsstr(pw0, pw1);
1743         if(wr)
1744         {
1745                 *wr = L'\0';
1746                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1747         }
1748 END_ROUTINE
1749         FreeDuplicatedString(pw0);
1750         FreeDuplicatedString(pw1);
1751         return r;
1752 }
1753
1754 int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)
1755 {
1756         int r = 0;
1757         wchar_t* pw0 = NULL;
1758         wchar_t* pw1 = NULL;
1759 START_ROUTINE
1760         pw0 = DuplicateMtoW(_Str1, -1);
1761         pw1 = DuplicateMtoW(_Str2, -1);
1762         r = wcscmp(pw0, pw1);
1763 END_ROUTINE
1764         FreeDuplicatedString(pw0);
1765         FreeDuplicatedString(pw1);
1766         return r;
1767 }
1768
1769 int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)
1770 {
1771         int r = 0;
1772         wchar_t* pw0 = NULL;
1773         wchar_t* pw1 = NULL;
1774 START_ROUTINE
1775         pw0 = DuplicateMtoW(_Str1, -1);
1776         pw1 = DuplicateMtoW(_Str2, -1);
1777         r = _wcsicmp(pw0, pw1);
1778 END_ROUTINE
1779         FreeDuplicatedString(pw0);
1780         FreeDuplicatedString(pw1);
1781         return r;
1782 }
1783
1784 int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)
1785 {
1786         int r = 0;
1787         wchar_t* pw0 = NULL;
1788         wchar_t* pw1 = NULL;
1789 START_ROUTINE
1790         pw0 = DuplicateMtoW(_Str1, -1);
1791         pw1 = DuplicateMtoW(_Str2, -1);
1792         r = wcsncmp(pw0, pw1, _MaxCount);
1793 END_ROUTINE
1794         FreeDuplicatedString(pw0);
1795         FreeDuplicatedString(pw1);
1796         return r;
1797 }
1798
1799 unsigned char * _mbslwrM(unsigned char * _String)
1800 {
1801         unsigned char* r = NULL;
1802         wchar_t* pw0 = NULL;
1803 START_ROUTINE
1804         pw0 = DuplicateMtoW(_String, -1);
1805         _wcslwr(pw0);
1806         r = _String;
1807         WtoM(_String, strlen(_String) + 1, pw0, -1);
1808 END_ROUTINE
1809         FreeDuplicatedString(pw0);
1810         return r;
1811 }
1812
1813 unsigned char * _mbsuprM(unsigned char * _String)
1814 {
1815         unsigned char* r = NULL;
1816         wchar_t* pw0 = NULL;
1817 START_ROUTINE
1818         pw0 = DuplicateMtoW(_String, -1);
1819         _wcsupr(pw0);
1820         r = _String;
1821         WtoM(_String, strlen(_String) + 1, pw0, -1);
1822 END_ROUTINE
1823         FreeDuplicatedString(pw0);
1824         return r;
1825 }
1826
1827 unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)
1828 {
1829         unsigned char* r = NULL;
1830         wchar_t* pw0 = NULL;
1831         wchar_t* wr;
1832 START_ROUTINE
1833         pw0 = DuplicateMtoW(_Str, -1);
1834         wr = _wcsninc(pw0, _Count);
1835         if(wr)
1836         {
1837                 *wr = L'\0';
1838                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1839         }
1840 END_ROUTINE
1841         FreeDuplicatedString(pw0);
1842         return r;
1843 }
1844
1845 FILE * fopenM(const char * _Filename, const char * _Mode)
1846 {
1847         FILE* r = NULL;
1848         wchar_t* pw0 = NULL;
1849         wchar_t* pw1 = NULL;
1850 START_ROUTINE
1851         pw0 = DuplicateMtoW(_Filename, -1);
1852         pw1 = DuplicateMtoW(_Mode, -1);
1853         r = _wfopen(pw0, pw1);
1854 END_ROUTINE
1855         FreeDuplicatedString(pw0);
1856         FreeDuplicatedString(pw1);
1857         return r;
1858 }
1859