OSDN Git Service

Fix bugs of deadlock around simultaneous connection.
[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 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
359 {
360         HANDLE r = INVALID_HANDLE_VALUE;
361         wchar_t* pw0 = NULL;
362 START_ROUTINE
363         pw0 = DuplicateMtoW(lpFileName, -1);
364         r = CreateFileW(pw0, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
365 END_ROUTINE
366         FreeDuplicatedString(pw0);
367         return r;
368 }
369
370 int MessageBoxM(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
371 {
372         int r = IDOK;
373         wchar_t* pw0 = NULL;
374         wchar_t* pw1 = NULL;
375 START_ROUTINE
376         pw0 = DuplicateMtoW(lpText, -1);
377         pw1 = DuplicateMtoW(lpCaption, -1);
378         r = MessageBoxW(hWnd, pw0, pw1, uType);
379 END_ROUTINE
380         FreeDuplicatedString(pw0);
381         FreeDuplicatedString(pw1);
382         return r;
383 }
384
385 HANDLE FindFirstFileM(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
386 {
387         HANDLE r = INVALID_HANDLE_VALUE;
388         wchar_t* pw0 = NULL;
389         WIN32_FIND_DATAW a0;
390 START_ROUTINE
391         pw0 = DuplicateMtoW(lpFileName, -1);
392         r = FindFirstFileW(pw0, &a0);
393         if(r != INVALID_HANDLE_VALUE)
394         {
395                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;
396                 lpFindFileData->ftCreationTime = a0.ftCreationTime;
397                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;
398                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;
399                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;
400                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;
401                 lpFindFileData->dwReserved0 = a0.dwReserved0;
402                 lpFindFileData->dwReserved1 = a0.dwReserved1;
403                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);
404                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);
405         }
406 END_ROUTINE
407         FreeDuplicatedString(pw0);
408         return r;
409 }
410
411 BOOL FindNextFileM(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)
412 {
413         BOOL r = FALSE;
414         WIN32_FIND_DATAW a0;
415 START_ROUTINE
416         r = FindNextFileW(hFindFile, &a0);
417         if(r)
418         {
419                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;
420                 lpFindFileData->ftCreationTime = a0.ftCreationTime;
421                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;
422                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;
423                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;
424                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;
425                 lpFindFileData->dwReserved0 = a0.dwReserved0;
426                 lpFindFileData->dwReserved1 = a0.dwReserved1;
427                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);
428                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);
429         }
430 END_ROUTINE
431         return r;
432 }
433
434 DWORD GetLogicalDriveStringsM(DWORD nBufferLength, LPSTR lpBuffer)
435 {
436         DWORD r = 0;
437         wchar_t* pw0 = NULL;
438 START_ROUTINE
439         pw0 = AllocateStringW(nBufferLength * 4);
440         GetLogicalDriveStringsW(nBufferLength * 4, pw0);
441         WtoMMultiString(lpBuffer, nBufferLength, pw0);
442         r = TerminateStringM(lpBuffer, nBufferLength);
443 END_ROUTINE
444         FreeDuplicatedString(pw0);
445         return r;
446 }
447
448 ATOM RegisterClassExM(CONST WNDCLASSEXA * v0)
449 {
450         ATOM r = 0;
451 START_ROUTINE
452         // WNDPROCがShift_JIS用であるため
453         r = RegisterClassExA(v0);
454 END_ROUTINE
455         return r;
456 }
457
458 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)
459 {
460         HWND r = NULL;
461         wchar_t* pw0 = NULL;
462         wchar_t* pw1 = NULL;
463 START_ROUTINE
464         pw0 = DuplicateMtoW(lpClassName, -1);
465         pw1 = DuplicateMtoW(lpWindowName, -1);
466         r = CreateWindowExW(dwExStyle, pw0, pw1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
467 END_ROUTINE
468         FreeDuplicatedString(pw0);
469         FreeDuplicatedString(pw1);
470         return r;
471 }
472
473 LONG GetWindowLongM(HWND hWnd, int nIndex)
474 {
475         LRESULT r = 0;
476 START_ROUTINE
477         // WNDPROCがShift_JIS用であるため
478         if(IsWindowUnicode(hWnd))
479                 r = GetWindowLongW(hWnd, nIndex);
480         else
481                 r = GetWindowLongA(hWnd, nIndex);
482 END_ROUTINE
483         return r;
484 }
485
486 LONG SetWindowLongM(HWND hWnd, int nIndex, LONG dwNewLong)
487 {
488         LRESULT r = 0;
489 START_ROUTINE
490         // WNDPROCがShift_JIS用であるため
491         if(IsWindowUnicode(hWnd))
492                 r = SetWindowLongW(hWnd, nIndex, dwNewLong);
493         else
494                 r = SetWindowLongA(hWnd, nIndex, dwNewLong);
495 END_ROUTINE
496         return r;
497 }
498
499 LRESULT DefWindowProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
500 {
501         LRESULT r = 0;
502 START_ROUTINE
503         // WNDPROCがShift_JIS用であるため
504         if(IsWindowUnicode(hWnd))
505                 r = DefWindowProcW(hWnd, Msg, wParam, lParam);
506         else
507                 r = DefWindowProcA(hWnd, Msg, wParam, lParam);
508 END_ROUTINE
509         return r;
510 }
511
512 LRESULT CallWindowProcM(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
513 {
514         LRESULT r = 0;
515 START_ROUTINE
516         // WNDPROCがShift_JIS用であるため
517         if(IsWindowUnicode(hWnd))
518                 r = CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
519         else
520                 r = CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
521 END_ROUTINE
522         return r;
523 }
524
525 LRESULT SendMessageM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
526 {
527         LRESULT r = 0;
528         wchar_t* pw0 = NULL;
529         wchar_t* pw1 = NULL;
530         int Size;
531         LVITEMA* pmLVItem;
532         LVITEMW wLVItem;
533         LVFINDINFOA* pmLVFindInfo;
534         LVFINDINFOW wLVFindInfo;
535         LVCOLUMNA* pmLVColumn;
536         LVCOLUMNW wLVColumn;
537         wchar_t ClassName[MAX_PATH];
538 START_ROUTINE
539         switch(Msg)
540         {
541         case WM_SETTEXT:
542                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
543                 r = SendMessageW(hWnd, WM_SETTEXT, wParam, (LPARAM)pw0);
544                 break;
545         case WM_GETTEXT:
546                 pw0 = AllocateStringW(wParam * 4);
547                 SendMessageW(hWnd, WM_GETTEXT, wParam * 4, (LPARAM)pw0);
548                 WtoM((LPSTR)lParam, wParam, pw0, -1);
549                 r = TerminateStringM((LPSTR)lParam, wParam);
550                 break;
551         case WM_GETTEXTLENGTH:
552                 Size = SendMessageW(hWnd, WM_GETTEXTLENGTH, wParam, lParam) + 1;
553                 pw0 = AllocateStringW(Size);
554                 SendMessageW(hWnd, WM_GETTEXT, (WPARAM)Size, (LPARAM)pw0);
555                 r = WtoM(NULL, 0, pw0, -1) - 1;
556                 break;
557         default:
558                 GetClassNameW(hWnd, ClassName, sizeof(ClassName) / sizeof(wchar_t));
559                 if(_wcsicmp(ClassName, WC_EDITW) == 0)
560                 {
561                         switch(Msg)
562                         {
563                         case EM_REPLACESEL:
564                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
565                                 r = SendMessageW(hWnd, EM_REPLACESEL, wParam, (LPARAM)pw0);
566                                 break;
567                         default:
568                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
569                                 break;
570                         }
571                 }
572                 else if(_wcsicmp(ClassName, WC_COMBOBOXW) == 0)
573                 {
574                         switch(Msg)
575                         {
576                         case CB_ADDSTRING:
577                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
578                                 r = SendMessageW(hWnd, CB_ADDSTRING, wParam, (LPARAM)pw0);
579                                 break;
580                         case CB_GETLBTEXT:
581                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
582                                 pw0 = AllocateStringW(Size);
583                                 SendMessageW(hWnd, CB_GETLBTEXT, wParam, (LPARAM)pw0);
584                                 // バッファ長不明のためオーバーランの可能性あり
585                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);
586                                 r = TerminateStringM((LPSTR)lParam, Size * 4);
587                                 break;
588                         case CB_GETLBTEXTLEN:
589                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
590                                 pw0 = AllocateStringW(Size);
591                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
592                                 r = WtoM(NULL, 0, pw0, -1) - 1;
593                                 break;
594                         case CB_INSERTSTRING:
595                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
596                                 r = SendMessageW(hWnd, CB_INSERTSTRING, wParam, (LPARAM)pw0);
597                                 break;
598                         case CB_FINDSTRINGEXACT:
599                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
600                                 r = SendMessageW(hWnd, CB_FINDSTRINGEXACT, wParam, (LPARAM)pw0);
601                                 break;
602                         default:
603                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
604                                 break;
605                         }
606                 }
607                 else if(_wcsicmp(ClassName, WC_LISTBOXW) == 0)
608                 {
609                         switch(Msg)
610                         {
611                         case LB_ADDSTRING:
612                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
613                                 r = SendMessageW(hWnd, LB_ADDSTRING, wParam, (LPARAM)pw0);
614                                 break;
615                         case LB_INSERTSTRING:
616                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
617                                 r = SendMessageW(hWnd, LB_INSERTSTRING, wParam, (LPARAM)pw0);
618                                 break;
619                         case LB_GETTEXT:
620                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
621                                 pw0 = AllocateStringW(Size);
622                                 SendMessageW(hWnd, LB_GETTEXT, wParam, (LPARAM)pw0);
623                                 // バッファ長不明のためオーバーランの可能性あり
624                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);
625                                 r = TerminateStringM((LPSTR)lParam, Size * 4);
626                                 break;
627                         case LB_GETTEXTLEN:
628                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
629                                 pw0 = AllocateStringW(Size);
630                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
631                                 r = WtoM(NULL, 0, pw0, -1) - 1;
632                                 break;
633                         default:
634                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
635                                 break;
636                         }
637                 }
638                 else if(_wcsicmp(ClassName, WC_LISTVIEWW) == 0)
639                 {
640                         switch(Msg)
641                         {
642                         case LVM_GETITEMA:
643                                 pmLVItem = (LVITEMA*)lParam;
644                                 wLVItem.mask = pmLVItem->mask;
645                                 wLVItem.iItem = pmLVItem->iItem;
646                                 wLVItem.iSubItem = pmLVItem->iSubItem;
647                                 wLVItem.state = pmLVItem->state;
648                                 wLVItem.stateMask = pmLVItem->stateMask;
649                                 if(pmLVItem->mask & LVIF_TEXT)
650                                 {
651                                         Size = pmLVItem->cchTextMax * 4;
652                                         pw0 = AllocateStringW(Size);
653                                         wLVItem.pszText = pw0;
654                                         wLVItem.cchTextMax = Size;
655                                 }
656                                 wLVItem.iImage = pmLVItem->iImage;
657                                 wLVItem.lParam = pmLVItem->lParam;
658                                 wLVItem.iIndent = pmLVItem->iIndent;
659                                 r = SendMessageW(hWnd, LVM_GETITEMW, wParam, (LPARAM)&wLVItem);
660                                 pmLVItem->mask = wLVItem.mask;
661                                 pmLVItem->iItem = wLVItem.iItem;
662                                 pmLVItem->iSubItem = wLVItem.iSubItem;
663                                 pmLVItem->state = wLVItem.state;
664                                 pmLVItem->stateMask = wLVItem.stateMask;
665                                 if(pmLVItem->mask & LVIF_TEXT)
666                                 {
667                                         WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
668                                         TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
669                                 }
670                                 pmLVItem->iImage = wLVItem.iImage;
671                                 pmLVItem->lParam = wLVItem.lParam;
672                                 pmLVItem->iIndent = wLVItem.iIndent;
673                                 break;
674                         case LVM_SETITEMA:
675                                 pmLVItem = (LVITEMA*)lParam;
676                                 wLVItem.mask = pmLVItem->mask;
677                                 wLVItem.iItem = pmLVItem->iItem;
678                                 wLVItem.iSubItem = pmLVItem->iSubItem;
679                                 wLVItem.state = pmLVItem->state;
680                                 wLVItem.stateMask = pmLVItem->stateMask;
681                                 if(pmLVItem->mask & LVIF_TEXT)
682                                 {
683                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
684                                         wLVItem.pszText = pw0;
685                                         // TODO: cchTextMaxの確認
686                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;
687                                 }
688                                 wLVItem.iImage = pmLVItem->iImage;
689                                 wLVItem.lParam = pmLVItem->lParam;
690                                 wLVItem.iIndent = pmLVItem->iIndent;
691                                 r = SendMessageW(hWnd, LVM_SETITEMW, wParam, (LPARAM)&wLVItem);
692                                 break;
693                         case LVM_INSERTITEMA:
694                                 pmLVItem = (LVITEMA*)lParam;
695                                 wLVItem.mask = pmLVItem->mask;
696                                 wLVItem.iItem = pmLVItem->iItem;
697                                 wLVItem.iSubItem = pmLVItem->iSubItem;
698                                 wLVItem.state = pmLVItem->state;
699                                 wLVItem.stateMask = pmLVItem->stateMask;
700                                 if(pmLVItem->mask & LVIF_TEXT)
701                                 {
702                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
703                                         wLVItem.pszText = pw0;
704                                         // TODO: cchTextMaxの確認
705                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;
706                                 }
707                                 wLVItem.iImage = pmLVItem->iImage;
708                                 wLVItem.lParam = pmLVItem->lParam;
709                                 wLVItem.iIndent = pmLVItem->iIndent;
710                                 r = SendMessageW(hWnd, LVM_INSERTITEMW, wParam, (LPARAM)&wLVItem);
711                                 break;
712                         case LVM_FINDITEMA:
713                                 pmLVFindInfo = (LVFINDINFOA*)lParam;
714                                 wLVFindInfo.flags = pmLVFindInfo->flags;
715                                 if(pmLVFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL))
716                                 {
717                                         pw0 = DuplicateMtoW(pmLVFindInfo->psz, -1);
718                                         wLVFindInfo.psz = pw0;
719                                 }
720                                 wLVFindInfo.lParam = pmLVFindInfo->lParam;
721                                 wLVFindInfo.pt = pmLVFindInfo->pt;
722                                 wLVFindInfo.vkDirection = pmLVFindInfo->vkDirection;
723                                 r = SendMessageW(hWnd, LVM_FINDITEMW, wParam, (LPARAM)&wLVItem);
724                                 break;
725                         case LVM_GETCOLUMNA:
726                                 pmLVColumn = (LVCOLUMNA*)lParam;
727                                 wLVColumn.mask = pmLVColumn->mask;
728                                 wLVColumn.fmt = pmLVColumn->fmt;
729                                 wLVColumn.cx = pmLVColumn->cx;
730                                 Size = pmLVColumn->cchTextMax * 4;
731                                 if(pmLVColumn->mask & LVCF_TEXT)
732                                 {
733                                         pw0 = AllocateStringW(Size);
734                                         wLVColumn.pszText = pw0;
735                                         wLVColumn.cchTextMax = Size;
736                                 }
737                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;
738                                 wLVColumn.iImage = pmLVColumn->iImage;
739                                 wLVColumn.iOrder = pmLVColumn->iOrder;
740                                 r = SendMessageW(hWnd, LVM_GETCOLUMNW, wParam, (LPARAM)&wLVColumn);
741                                 pmLVColumn->mask = wLVColumn.mask;
742                                 pmLVColumn->fmt = wLVColumn.fmt;
743                                 pmLVColumn->cx = wLVColumn.cx;
744                                 if(pmLVColumn->mask & LVCF_TEXT)
745                                 {
746                                         WtoM(pmLVColumn->pszText, pmLVColumn->cchTextMax, wLVColumn.pszText, -1);
747                                         TerminateStringM(pmLVColumn->pszText, pmLVColumn->cchTextMax);
748                                 }
749                                 pmLVColumn->iSubItem = wLVColumn.iSubItem;
750                                 pmLVColumn->iImage = wLVColumn.iImage;
751                                 pmLVColumn->iOrder = wLVColumn.iOrder;
752                                 break;
753                         case LVM_INSERTCOLUMNA:
754                                 pmLVColumn = (LVCOLUMNA*)lParam;
755                                 wLVColumn.mask = pmLVColumn->mask;
756                                 wLVColumn.fmt = pmLVColumn->fmt;
757                                 wLVColumn.cx = pmLVColumn->cx;
758                                 if(pmLVColumn->mask & LVCF_TEXT)
759                                 {
760                                         pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);
761                                         wLVColumn.pszText = pw0;
762                                         // TODO: cchTextMaxの確認
763                                         wLVColumn.cchTextMax = pmLVColumn->cchTextMax;
764                                 }
765                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;
766                                 wLVColumn.iImage = pmLVColumn->iImage;
767                                 wLVColumn.iOrder = pmLVColumn->iOrder;
768                                 r = SendMessageW(hWnd, LVM_INSERTCOLUMNW, wParam, (LPARAM)&wLVColumn);
769                                 break;
770                         case LVM_GETITEMTEXTA:
771                                 pmLVItem = (LVITEMA*)lParam;
772                                 wLVItem.mask = pmLVItem->mask;
773                                 wLVItem.iItem = pmLVItem->iItem;
774                                 wLVItem.iSubItem = pmLVItem->iSubItem;
775                                 wLVItem.state = pmLVItem->state;
776                                 wLVItem.stateMask = pmLVItem->stateMask;
777                                 Size = pmLVItem->cchTextMax * 4;
778                                 pw0 = AllocateStringW(Size);
779                                 wLVItem.pszText = pw0;
780                                 wLVItem.cchTextMax = Size;
781                                 wLVItem.iImage = pmLVItem->iImage;
782                                 wLVItem.lParam = pmLVItem->lParam;
783                                 wLVItem.iIndent = pmLVItem->iIndent;
784                                 r = SendMessageW(hWnd, LVM_GETITEMTEXTW, wParam, (LPARAM)&wLVItem);
785                                 pmLVItem->mask = wLVItem.mask;
786                                 pmLVItem->iItem = wLVItem.iItem;
787                                 pmLVItem->iSubItem = wLVItem.iSubItem;
788                                 pmLVItem->state = wLVItem.state;
789                                 pmLVItem->stateMask = wLVItem.stateMask;
790                                 WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
791                                 TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
792                                 pmLVItem->iImage = wLVItem.iImage;
793                                 pmLVItem->lParam = wLVItem.lParam;
794                                 pmLVItem->iIndent = wLVItem.iIndent;
795                                 break;
796                         default:
797                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
798                                 break;
799                         }
800                 }
801                 else if(_wcsicmp(ClassName, STATUSCLASSNAMEW) == 0)
802                 {
803                         switch(Msg)
804                         {
805                         case SB_SETTEXTA:
806                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
807                                 r = SendMessageW(hWnd, SB_SETTEXTW, wParam, (LPARAM)pw0);
808                                 break;
809                         default:
810                                 r = SendMessageW(hWnd, Msg, wParam, lParam);
811                                 break;
812                         }
813                 }
814                 else
815                         r = SendMessageW(hWnd, Msg, wParam, lParam);
816                 break;
817         }
818 END_ROUTINE
819         FreeDuplicatedString(pw0);
820         FreeDuplicatedString(pw1);
821         return r;
822 }
823
824 LRESULT DefDlgProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
825 {
826         LRESULT r = 0;
827 START_ROUTINE
828         // WNDPROCがShift_JIS用であるため
829         if(IsWindowUnicode(hWnd))
830                 r = DefDlgProcW(hWnd, Msg, wParam, lParam);
831         else
832                 r = DefDlgProcA(hWnd, Msg, wParam, lParam);
833 END_ROUTINE
834         return r;
835 }
836
837 LRESULT SendDlgItemMessageM(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam)
838 {
839         LRESULT r = 0;
840 START_ROUTINE
841         r = SendMessageM(GetDlgItem(hDlg, nIDDlgItem), Msg, wParam, lParam);
842 END_ROUTINE
843         return r;
844 }
845
846 BOOL SetWindowTextM(HWND hWnd, LPCSTR lpString)
847 {
848         BOOL r = FALSE;
849         wchar_t* pw0 = NULL;
850 START_ROUTINE
851         pw0 = DuplicateMtoW(lpString, -1);
852         r = SetWindowTextW(hWnd, pw0);
853 END_ROUTINE
854         FreeDuplicatedString(pw0);
855         return r;
856 }
857
858 UINT DragQueryFileM(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch)
859 {
860         UINT r = 0;
861         wchar_t* pw0 = NULL;
862 START_ROUTINE
863         if(iFile == (UINT)-1)
864                 r = DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);
865         else
866         {
867                 pw0 = AllocateStringW(cch * 4);
868                 DragQueryFileW(hDrop, iFile, pw0, cch * 4);
869                 WtoM(lpszFile, cch, pw0, -1);
870                 r = TerminateStringM(lpszFile, cch);
871         }
872 END_ROUTINE
873         FreeDuplicatedString(pw0);
874         return r;
875 }
876
877 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)
878 {
879         DWORD r = 0;
880         wchar_t* pw0 = NULL;
881 START_ROUTINE
882         pw0 = AllocateStringW(nBufferLength * 4);
883         GetCurrentDirectoryW(nBufferLength * 4, pw0);
884         WtoM(lpBuffer, nBufferLength, pw0, -1);
885         r = TerminateStringM(lpBuffer, nBufferLength);
886 END_ROUTINE
887         FreeDuplicatedString(pw0);
888         return r;
889 }
890
891 BOOL SetCurrentDirectoryM(LPCSTR lpPathName)
892 {
893         BOOL r = FALSE;
894         wchar_t* pw0 = NULL;
895 START_ROUTINE
896         pw0 = DuplicateMtoW(lpPathName, -1);
897         r = SetCurrentDirectoryW(pw0);
898 END_ROUTINE
899         FreeDuplicatedString(pw0);
900         return r;
901 }
902
903 BOOL SetDllDirectoryM(LPCSTR lpPathName)
904 {
905         BOOL r = FALSE;
906         wchar_t* pw0 = NULL;
907 START_ROUTINE
908         pw0 = DuplicateMtoW(lpPathName, -1);
909         r = SetDllDirectoryW(pw0);
910 END_ROUTINE
911         FreeDuplicatedString(pw0);
912         return r;
913 }
914
915 DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)
916 {
917         DWORD r = 0;
918         wchar_t* pw0 = NULL;
919 START_ROUTINE
920         pw0 = AllocateStringW(nBufferLength * 4);
921         GetTempPathW(nBufferLength * 4, pw0);
922         WtoM(lpBuffer, nBufferLength, pw0, -1);
923         r = TerminateStringM(lpBuffer, nBufferLength);
924 END_ROUTINE
925         FreeDuplicatedString(pw0);
926         return r;
927 }
928
929 DWORD GetFileAttributesM(LPCSTR lpFileName)
930 {
931         DWORD r = FALSE;
932         wchar_t* pw0 = NULL;
933 START_ROUTINE
934         pw0 = DuplicateMtoW(lpFileName, -1);
935         r = GetFileAttributesW(pw0);
936 END_ROUTINE
937         FreeDuplicatedString(pw0);
938         return r;
939 }
940
941 DWORD GetModuleFileNameM(HMODULE hModule, LPCH lpFilename, DWORD nSize)
942 {
943         DWORD r = 0;
944         wchar_t* pw0 = NULL;
945 START_ROUTINE
946         pw0 = AllocateStringW(nSize * 4);
947         GetModuleFileNameW(hModule, pw0, nSize * 4);
948         WtoM(lpFilename, nSize, pw0, -1);
949         r = TerminateStringM(lpFilename, nSize);
950 END_ROUTINE
951         FreeDuplicatedString(pw0);
952         return r;
953 }
954
955 LSTATUS RegOpenKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
956 {
957         LSTATUS r = 0;
958         wchar_t* pw0 = NULL;
959 START_ROUTINE
960         pw0 = DuplicateMtoW(lpSubKey, -1);
961         r = RegOpenKeyExW(hKey, pw0, ulOptions, samDesired, phkResult);
962 END_ROUTINE
963         FreeDuplicatedString(pw0);
964         return r;
965 }
966
967 LSTATUS RegCreateKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
968 {
969         LSTATUS r = 0;
970         wchar_t* pw0 = NULL;
971         wchar_t* pw1 = NULL;
972 START_ROUTINE
973         pw0 = DuplicateMtoW(lpSubKey, -1);
974         pw1 = DuplicateMtoW(lpClass, -1);
975         r = RegCreateKeyExW(hKey, pw0, Reserved, pw1, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
976 END_ROUTINE
977         FreeDuplicatedString(pw0);
978         FreeDuplicatedString(pw1);
979         return r;
980 }
981
982 LSTATUS RegDeleteValueM(HKEY hKey, LPCSTR lpValueName)
983 {
984         LSTATUS r = 0;
985         wchar_t* pw0 = NULL;
986 START_ROUTINE
987         pw0 = DuplicateMtoW(lpValueName, -1);
988         r = RegDeleteValueW(hKey, pw0);
989 END_ROUTINE
990         FreeDuplicatedString(pw0);
991         return r;
992 }
993
994 LSTATUS RegQueryValueExM(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
995 {
996         LSTATUS r = 0;
997         wchar_t* pw0 = NULL;
998         wchar_t* pw1 = NULL;
999         DWORD dwType;
1000         DWORD wcbData;
1001 START_ROUTINE
1002         pw0 = DuplicateMtoW(lpValueName, -1);
1003         if(RegQueryValueExW(hKey, pw0, NULL, &dwType, NULL, 0) == ERROR_SUCCESS)
1004         {
1005                 switch(dwType)
1006                 {
1007                 case REG_SZ:
1008                 case REG_EXPAND_SZ:
1009                 case REG_MULTI_SZ:
1010                         if(lpcbData)
1011                         {
1012                                 pw1 = AllocateStringW(*lpcbData / sizeof(char) * 4);
1013                                 wcbData = *lpcbData / sizeof(char) * 4;
1014                                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, (LPBYTE)pw1, &wcbData);
1015                                 if(lpData)
1016                                         *lpcbData = sizeof(char) * WtoM((char*)lpData, *lpcbData / sizeof(char), pw1, wcbData / sizeof(wchar_t));
1017                                 else
1018                                         *lpcbData = sizeof(char) * WtoM(NULL, 0, pw1, wcbData / sizeof(wchar_t));
1019                         }
1020                         break;
1021                 default:
1022                         r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
1023                         break;
1024                 }
1025         }
1026         else
1027                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
1028 END_ROUTINE
1029         FreeDuplicatedString(pw0);
1030         FreeDuplicatedString(pw1);
1031         return r;
1032 }
1033
1034 LSTATUS RegSetValueExM(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData)
1035 {
1036         LSTATUS r = 0;
1037         wchar_t* pw0 = NULL;
1038         wchar_t* pw1 = NULL;
1039         DWORD wcbData;
1040 START_ROUTINE
1041         pw0 = DuplicateMtoW(lpValueName, -1);
1042         switch(dwType)
1043         {
1044         case REG_SZ:
1045         case REG_EXPAND_SZ:
1046         case REG_MULTI_SZ:
1047                 wcbData = MtoW(NULL, 0, (char*)lpData, cbData / sizeof(char));
1048                 pw1 = AllocateStringW(wcbData);
1049                 MtoW(pw1, wcbData, (char*)lpData, cbData / sizeof(char));
1050                 wcbData = sizeof(wchar_t) * wcbData;
1051                 lpData = (BYTE*)pw1;
1052                 cbData = wcbData;
1053                 break;
1054         }
1055         r = RegSetValueExW(hKey, pw0, Reserved, dwType, lpData, cbData);
1056 END_ROUTINE
1057         FreeDuplicatedString(pw0);
1058         FreeDuplicatedString(pw1);
1059         return r;
1060 }
1061
1062 BOOL TextOutM(HDC hdc, int x, int y, LPCSTR lpString, int c)
1063 {
1064         BOOL r = FALSE;
1065         wchar_t* pw0 = NULL;
1066 START_ROUTINE
1067         pw0 = DuplicateMtoW(lpString, c);
1068         r = TextOutW(hdc, x, y, pw0, wcslen(pw0));
1069 END_ROUTINE
1070         FreeDuplicatedString(pw0);
1071         return r;
1072 }
1073
1074 BOOL GetTextExtentPoint32M(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl)
1075 {
1076         BOOL r = FALSE;
1077         wchar_t* pw0 = NULL;
1078 START_ROUTINE
1079         pw0 = DuplicateMtoW(lpString, c);
1080         r = GetTextExtentPoint32W(hdc, pw0, wcslen(pw0), psizl);
1081 END_ROUTINE
1082         FreeDuplicatedString(pw0);
1083         return r;
1084 }
1085
1086 INT_PTR PropertySheetM(LPCPROPSHEETHEADERA v0)
1087 {
1088         INT_PTR r = 0;
1089         PROPSHEETHEADERW a0;
1090         PROPSHEETPAGEW* pwPage;
1091         UINT i;
1092 START_ROUTINE
1093         a0.dwSize = sizeof(PROPSHEETHEADERW);
1094         a0.dwFlags = v0->dwFlags;
1095         a0.hwndParent = v0->hwndParent;
1096         a0.hInstance = v0->hInstance;
1097         if(v0->dwFlags & PSH_USEICONID)
1098                 a0.pszIcon = DuplicateMtoW(v0->pszIcon, -1);
1099         else
1100                 a0.hIcon = v0->hIcon;
1101         a0.pszCaption = DuplicateMtoW(v0->pszCaption, -1);
1102         a0.nPages = v0->nPages;
1103         a0.pStartPage = DuplicateMtoW(v0->pStartPage, -1);
1104         if(v0->ppsp && (pwPage = (PROPSHEETPAGEW*)malloc(sizeof(PROPSHEETPAGEW) * v0->nPages)))
1105         {
1106                 for(i = 0; i < v0->nPages; i++)
1107                 {
1108                         pwPage[i].dwSize = sizeof(PROPSHEETPAGEW);
1109                         pwPage[i].dwFlags = v0->ppsp[i].dwFlags;
1110                         pwPage[i].hInstance = v0->ppsp[i].hInstance;
1111                         pwPage[i].pszTemplate = DuplicateMtoW(v0->ppsp[i].pszTemplate, -1);
1112                         if(v0->ppsp[i].dwFlags & PSP_USEICONID)
1113                                 pwPage[i].pszIcon = DuplicateMtoW(v0->ppsp[i].pszIcon, -1);
1114                         else
1115                                 pwPage[i].hIcon = v0->ppsp[i].hIcon;
1116                         if(v0->ppsp[i].dwFlags & PSP_USETITLE)
1117                                 pwPage[i].pszTitle = DuplicateMtoW(v0->ppsp[i].pszTitle, -1);
1118                         pwPage[i].pfnDlgProc = v0->ppsp[i].pfnDlgProc;
1119                         pwPage[i].lParam = v0->ppsp[i].lParam;
1120                         // TODO: pfnCallback
1121                         pwPage[i].pfnCallback = v0->ppsp[i].pfnCallback;
1122                         pwPage[i].pcRefParent = v0->ppsp[i].pcRefParent;
1123 //                      pwPage[i].pszHeaderTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderTitle, -1);
1124 //                      pwPage[i].pszHeaderSubTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderSubTitle, -1);
1125                         pwPage[i].hActCtx = v0->ppsp[i].hActCtx;
1126 //                      pwPage[i].pszbmHeader = DuplicateMtoW(v0->ppsp[i].pszbmHeader, -1);
1127                 }
1128         }
1129         else
1130                 pwPage = NULL;
1131         a0.ppsp = pwPage;
1132         a0.pfnCallback = v0->pfnCallback;
1133         r = PropertySheetW(&a0);
1134         if(a0.dwFlags & PSH_USEICONID)
1135                 FreeDuplicatedString(a0.pszIcon);
1136         FreeDuplicatedString(a0.pszCaption);
1137         FreeDuplicatedString(a0.pStartPage);
1138         if(pwPage)
1139         {
1140                 for(i = 0; i < v0->nPages; i++)
1141                 {
1142                         FreeDuplicatedString(pwPage[i].pszTemplate);
1143                         if(pwPage[i].dwFlags & PSP_USEICONID)
1144                                 FreeDuplicatedString(pwPage[i].pszIcon);
1145                         if(pwPage[i].dwFlags & PSP_USETITLE)
1146                                 FreeDuplicatedString(pwPage[i].pszTitle);
1147 //                      FreeDuplicatedString(pwPage[i].pszHeaderTitle);
1148 //                      FreeDuplicatedString(pwPage[i].pszHeaderSubTitle);
1149 //                      FreeDuplicatedString(pwPage[i].pszbmHeader);
1150                 }
1151                 free(pwPage);
1152         }
1153 END_ROUTINE
1154         return r;
1155 }
1156
1157 BOOL GetOpenFileNameM(LPOPENFILENAMEA v0)
1158 {
1159         BOOL r = FALSE;
1160         wchar_t* pw0 = NULL;
1161         wchar_t* pw1 = NULL;
1162         wchar_t* pw2 = NULL;
1163         wchar_t* pw3 = NULL;
1164         wchar_t* pw4 = NULL;
1165         wchar_t* pw5 = NULL;
1166         wchar_t* pw6 = NULL;
1167         wchar_t* pw7 = NULL;
1168         wchar_t* pw8 = NULL;
1169         wchar_t* pw9 = NULL;
1170         OPENFILENAMEW wofn;
1171 START_ROUTINE
1172         wofn.lStructSize = sizeof(OPENFILENAMEW);
1173         wofn.hwndOwner = v0->hwndOwner;
1174         wofn.hInstance = v0->hInstance;
1175         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);
1176         wofn.lpstrFilter = pw0;
1177         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);
1178         wofn.lpstrCustomFilter = pw1;
1179         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;
1180         wofn.nFilterIndex = v0->nFilterIndex;
1181         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);
1182         wofn.lpstrFile = pw2;
1183         wofn.nMaxFile = v0->nMaxFile * 4;
1184         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);
1185         wofn.lpstrFileTitle = pw3;
1186         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;
1187         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);
1188         wofn.lpstrInitialDir = pw4;
1189         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);
1190         wofn.lpstrTitle = pw5;
1191         wofn.Flags = v0->Flags;
1192         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);
1193         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);
1194         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);
1195         wofn.lpstrDefExt = pw6;
1196         wofn.lCustData = v0->lCustData;
1197         wofn.lpfnHook = v0->lpfnHook;
1198         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1199         wofn.pvReserved = v0->pvReserved;
1200         wofn.FlagsEx = v0->FlagsEx;
1201         r = GetOpenFileNameW(&wofn);
1202         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);
1203         TerminateStringM(v0->lpstrFile, v0->nMaxFile);
1204         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);
1205         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);
1206 END_ROUTINE
1207         FreeDuplicatedString(pw0);
1208         FreeDuplicatedString(pw1);
1209         FreeDuplicatedString(pw2);
1210         FreeDuplicatedString(pw3);
1211         FreeDuplicatedString(pw4);
1212         FreeDuplicatedString(pw5);
1213         FreeDuplicatedString(pw6);
1214         return r;
1215 }
1216
1217 BOOL GetSaveFileNameM(LPOPENFILENAMEA v0)
1218 {
1219         BOOL r = FALSE;
1220         wchar_t* pw0 = NULL;
1221         wchar_t* pw1 = NULL;
1222         wchar_t* pw2 = NULL;
1223         wchar_t* pw3 = NULL;
1224         wchar_t* pw4 = NULL;
1225         wchar_t* pw5 = NULL;
1226         wchar_t* pw6 = NULL;
1227         wchar_t* pw7 = NULL;
1228         wchar_t* pw8 = NULL;
1229         wchar_t* pw9 = NULL;
1230         OPENFILENAMEW wofn;
1231 START_ROUTINE
1232         wofn.lStructSize = sizeof(OPENFILENAMEW);
1233         wofn.hwndOwner = v0->hwndOwner;
1234         wofn.hInstance = v0->hInstance;
1235         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);
1236         wofn.lpstrFilter = pw0;
1237         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);
1238         wofn.lpstrCustomFilter = pw1;
1239         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;
1240         wofn.nFilterIndex = v0->nFilterIndex;
1241         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);
1242         wofn.lpstrFile = pw2;
1243         wofn.nMaxFile = v0->nMaxFile * 4;
1244         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);
1245         wofn.lpstrFileTitle = pw3;
1246         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;
1247         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);
1248         wofn.lpstrInitialDir = pw4;
1249         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);
1250         wofn.lpstrTitle = pw5;
1251         wofn.Flags = v0->Flags;
1252         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);
1253         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);
1254         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);
1255         wofn.lpstrDefExt = pw6;
1256         wofn.lCustData = v0->lCustData;
1257         wofn.lpfnHook = v0->lpfnHook;
1258         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1259         wofn.pvReserved = v0->pvReserved;
1260         wofn.FlagsEx = v0->FlagsEx;
1261         r = GetSaveFileNameW(&wofn);
1262         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);
1263         TerminateStringM(v0->lpstrFile, v0->nMaxFile);
1264         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);
1265         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);
1266 END_ROUTINE
1267         FreeDuplicatedString(pw0);
1268         FreeDuplicatedString(pw1);
1269         FreeDuplicatedString(pw2);
1270         FreeDuplicatedString(pw3);
1271         FreeDuplicatedString(pw4);
1272         FreeDuplicatedString(pw5);
1273         FreeDuplicatedString(pw6);
1274         return r;
1275 }
1276
1277 HWND HtmlHelpM(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
1278 {
1279         HWND r = NULL;
1280         wchar_t* pw0 = NULL;
1281 START_ROUTINE
1282         pw0 = DuplicateMtoW(pszFile, -1);
1283         r = HtmlHelpW(hwndCaller, pw0, uCommand, dwData);
1284 END_ROUTINE
1285         FreeDuplicatedString(pw0);
1286         return r;
1287 }
1288
1289 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)
1290 {
1291         BOOL r = FALSE;
1292         wchar_t* pw0 = NULL;
1293         wchar_t* pw1 = NULL;
1294         wchar_t* pw2 = NULL;
1295         wchar_t* pw3 = NULL;
1296         wchar_t* pw4 = NULL;
1297         wchar_t* pw5 = NULL;
1298         STARTUPINFOW wStartupInfo;
1299 START_ROUTINE
1300         pw0 = DuplicateMtoW(lpApplicationName, -1);
1301         pw1 = DuplicateMtoWBuffer(lpCommandLine, -1, (strlen(lpCommandLine) + 1) * 4);
1302         pw2 = DuplicateMtoW(lpCurrentDirectory, -1);
1303         wStartupInfo.cb = sizeof(LPSTARTUPINFOW);
1304         pw3 = DuplicateMtoW(lpStartupInfo->lpReserved, -1);
1305         wStartupInfo.lpReserved = pw3;
1306         pw4 = DuplicateMtoW(lpStartupInfo->lpDesktop, -1);
1307         wStartupInfo.lpDesktop = pw4;
1308         pw5 = DuplicateMtoW(lpStartupInfo->lpTitle, -1);
1309         wStartupInfo.lpTitle = pw5;
1310         wStartupInfo.dwX = lpStartupInfo->dwX;
1311         wStartupInfo.dwY = lpStartupInfo->dwY;
1312         wStartupInfo.dwXSize = lpStartupInfo->dwXSize;
1313         wStartupInfo.dwYSize = lpStartupInfo->dwYSize;
1314         wStartupInfo.dwXCountChars = lpStartupInfo->dwXCountChars;
1315         wStartupInfo.dwYCountChars = lpStartupInfo->dwYCountChars;
1316         wStartupInfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
1317         wStartupInfo.dwFlags = lpStartupInfo->dwFlags;
1318         wStartupInfo.wShowWindow = lpStartupInfo->wShowWindow;
1319         wStartupInfo.cbReserved2 = lpStartupInfo->cbReserved2;
1320         wStartupInfo.lpReserved2 = lpStartupInfo->lpReserved2;
1321         wStartupInfo.hStdInput = lpStartupInfo->hStdInput;
1322         wStartupInfo.hStdOutput = lpStartupInfo->hStdOutput;
1323         wStartupInfo.hStdError = lpStartupInfo->hStdError;
1324         r = CreateProcessW(pw0, pw1, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, pw2, &wStartupInfo, lpProcessInformation);
1325         WtoM(lpCommandLine, strlen(lpCommandLine) + 1, pw1, -1);
1326 END_ROUTINE
1327         FreeDuplicatedString(pw0);
1328         FreeDuplicatedString(pw1);
1329         FreeDuplicatedString(pw2);
1330         FreeDuplicatedString(pw3);
1331         FreeDuplicatedString(pw4);
1332         FreeDuplicatedString(pw5);
1333         return r;
1334 }
1335
1336 HINSTANCE FindExecutableM(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
1337 {
1338         HINSTANCE r = NULL;
1339         wchar_t* pw0 = NULL;
1340         wchar_t* pw1 = NULL;
1341         wchar_t* pw2 = NULL;
1342         wchar_t* pw3 = NULL;
1343 START_ROUTINE
1344         pw0 = DuplicateMtoW(lpFile, -1);
1345         pw1 = DuplicateMtoW(lpDirectory, -1);
1346         pw2 = AllocateStringW(MAX_PATH * 4);
1347         r = FindExecutableW(pw0, pw1, pw2);
1348         // バッファ長不明のためオーバーランの可能性あり
1349         WtoM(lpResult, MAX_PATH, pw2, -1);
1350         TerminateStringM(lpResult, MAX_PATH);
1351 END_ROUTINE
1352         FreeDuplicatedString(pw0);
1353         FreeDuplicatedString(pw1);
1354         FreeDuplicatedString(pw2);
1355         FreeDuplicatedString(pw3);
1356         return r;
1357 }
1358
1359 HINSTANCE ShellExecuteM(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
1360 {
1361         HINSTANCE r = NULL;
1362         wchar_t* pw0 = NULL;
1363         wchar_t* pw1 = NULL;
1364         wchar_t* pw2 = NULL;
1365         wchar_t* pw3 = NULL;
1366 START_ROUTINE
1367         pw0 = DuplicateMtoW(lpOperation, -1);
1368         pw1 = DuplicateMtoW(lpFile, -1);
1369         pw2 = DuplicateMtoW(lpParameters, -1);
1370         pw3 = DuplicateMtoW(lpDirectory, -1);
1371         r = ShellExecuteW(hwnd, pw0, pw1, pw2, pw3, nShowCmd);
1372 END_ROUTINE
1373         FreeDuplicatedString(pw0);
1374         FreeDuplicatedString(pw1);
1375         FreeDuplicatedString(pw2);
1376         FreeDuplicatedString(pw3);
1377         return r;
1378 }
1379
1380 PIDLIST_ABSOLUTE SHBrowseForFolderM(LPBROWSEINFOA lpbi)
1381 {
1382         PIDLIST_ABSOLUTE r = NULL;
1383         wchar_t* pw0 = NULL;
1384         wchar_t* pw1 = NULL;
1385         BROWSEINFOW wbi;
1386 START_ROUTINE
1387         wbi.hwndOwner = lpbi->hwndOwner;
1388         wbi.pidlRoot = lpbi->pidlRoot;
1389         pw0 = DuplicateMtoWBuffer(lpbi->pszDisplayName, -1, MAX_PATH * 4);
1390         wbi.pszDisplayName = pw0;
1391         pw1 = DuplicateMtoW(lpbi->lpszTitle, -1);
1392         wbi.lpszTitle = pw1;
1393         wbi.ulFlags = lpbi->ulFlags;
1394         // TODO: lpfn
1395         wbi.lpfn = lpbi->lpfn;
1396         wbi.lParam = lpbi->lParam;
1397         wbi.iImage = lpbi->iImage;
1398         r = SHBrowseForFolderW(&wbi);
1399         // バッファ長不明のためオーバーランの可能性あり
1400         WtoM(lpbi->pszDisplayName, MAX_PATH, wbi.pszDisplayName, -1);
1401         lpbi->iImage = wbi.iImage;
1402 END_ROUTINE
1403         FreeDuplicatedString(pw0);
1404         FreeDuplicatedString(pw1);
1405         return r;
1406 }
1407
1408 BOOL SHGetPathFromIDListM(PCIDLIST_ABSOLUTE pidl, LPSTR pszPath)
1409 {
1410         BOOL r = FALSE;
1411         wchar_t* pw0 = NULL;
1412 START_ROUTINE
1413         pw0 = AllocateStringW(MAX_PATH * 4);
1414         r = SHGetPathFromIDListW(pidl, pw0);
1415         // バッファ長不明のためオーバーランの可能性あり
1416         WtoM(pszPath, MAX_PATH, pw0, -1);
1417         TerminateStringM(pszPath, MAX_PATH);
1418 END_ROUTINE
1419         FreeDuplicatedString(pw0);
1420         return r;
1421 }
1422
1423 int SHFileOperationM(LPSHFILEOPSTRUCTA lpFileOp)
1424 {
1425         int r = 0;
1426         wchar_t* pw0 = NULL;
1427         wchar_t* pw1 = NULL;
1428         wchar_t* pw2 = NULL;
1429         SHFILEOPSTRUCTW wFileOp;
1430 START_ROUTINE
1431         wFileOp.hwnd = lpFileOp->hwnd;
1432         wFileOp.wFunc = lpFileOp->wFunc;
1433         pw0 = DuplicateMtoWMultiString(lpFileOp->pFrom);
1434         wFileOp.pFrom = pw0;
1435         pw1 = DuplicateMtoWMultiString(lpFileOp->pTo);
1436         wFileOp.pTo = pw1;
1437         wFileOp.fFlags = lpFileOp->fFlags;
1438         wFileOp.fAnyOperationsAborted = lpFileOp->fAnyOperationsAborted;
1439         wFileOp.hNameMappings = lpFileOp->hNameMappings;
1440         pw2 = DuplicateMtoW(lpFileOp->lpszProgressTitle, -1);
1441         r = SHFileOperationW(&wFileOp);
1442         lpFileOp->fAnyOperationsAborted = wFileOp.fAnyOperationsAborted;
1443 END_ROUTINE
1444         FreeDuplicatedString(pw0);
1445         FreeDuplicatedString(pw1);
1446         FreeDuplicatedString(pw2);
1447         return r;
1448 }
1449
1450 BOOL AppendMenuM(HMENU hMenu, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem)
1451 {
1452         int r = 0;
1453         wchar_t* pw0 = NULL;
1454 START_ROUTINE
1455         if(uFlags & (MF_BITMAP | MF_OWNERDRAW))
1456                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, (LPCWSTR)lpNewItem);
1457         else
1458         {
1459                 pw0 = DuplicateMtoW(lpNewItem, -1);
1460                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, pw0);
1461         }
1462 END_ROUTINE
1463         FreeDuplicatedString(pw0);
1464         return r;
1465 }
1466
1467 BOOL GetMenuItemInfoM(HMENU hmenu, UINT item, BOOL fByPosition, LPMENUITEMINFOA lpmii)
1468 {
1469         BOOL r = FALSE;
1470         wchar_t* pw0 = NULL;
1471         MENUITEMINFOW wmii;
1472 START_ROUTINE
1473         wmii.cbSize = sizeof(MENUITEMINFOW);
1474         wmii.fMask = lpmii->fMask;
1475         wmii.fType = lpmii->fType;
1476         wmii.fState = lpmii->fState;
1477         wmii.wID = lpmii->wID;
1478         wmii.hSubMenu = lpmii->hSubMenu;
1479         wmii.hbmpChecked = lpmii->hbmpChecked;
1480         wmii.hbmpUnchecked = lpmii->hbmpUnchecked;
1481         wmii.dwItemData = lpmii->dwItemData;
1482         pw0 = DuplicateMtoWBuffer(lpmii->dwTypeData, -1, lpmii->cch * 4);
1483         wmii.dwTypeData = pw0;
1484         wmii.cch = lpmii->cch * 4;
1485         r = GetMenuItemInfoW(hmenu, item, fByPosition, &wmii);
1486         lpmii->fType = wmii.fType;
1487         lpmii->fState = wmii.fState;
1488         lpmii->wID = wmii.wID;
1489         lpmii->hSubMenu = wmii.hSubMenu;
1490         lpmii->hbmpChecked = wmii.hbmpChecked;
1491         lpmii->hbmpUnchecked = wmii.hbmpUnchecked;
1492         lpmii->dwItemData = wmii.dwItemData;
1493         WtoM(lpmii->dwTypeData, lpmii->cch, wmii.dwTypeData, -1);
1494         TerminateStringM(lpmii->dwTypeData, lpmii->cch);
1495 END_ROUTINE
1496         FreeDuplicatedString(pw0);
1497         return r;
1498 }
1499
1500 HFONT CreateFontIndirectM(CONST LOGFONTA *lplf)
1501 {
1502         HFONT r = NULL;
1503         LOGFONTW wlf;
1504 START_ROUTINE
1505         wlf.lfHeight = lplf->lfHeight;
1506         wlf.lfWidth = lplf->lfWidth;
1507         wlf.lfEscapement = lplf->lfEscapement;
1508         wlf.lfOrientation = lplf->lfOrientation;
1509         wlf.lfWeight = lplf->lfWeight;
1510         wlf.lfItalic = lplf->lfItalic;
1511         wlf.lfUnderline = lplf->lfUnderline;
1512         wlf.lfStrikeOut = lplf->lfStrikeOut;
1513         wlf.lfCharSet = lplf->lfCharSet;
1514         wlf.lfOutPrecision = lplf->lfOutPrecision;
1515         wlf.lfClipPrecision = lplf->lfClipPrecision;
1516         wlf.lfQuality = lplf->lfQuality;
1517         wlf.lfPitchAndFamily = lplf->lfPitchAndFamily;
1518         MtoW(wlf.lfFaceName, LF_FACESIZE, lplf->lfFaceName, -1);
1519         TerminateStringW(wlf.lfFaceName, LF_FACESIZE);
1520         r = CreateFontIndirect(&wlf);
1521 END_ROUTINE
1522         return r;
1523 }
1524
1525 BOOL ChooseFontM(LPCHOOSEFONTA v0)
1526 {
1527         BOOL r = FALSE;
1528         wchar_t* pw0 = NULL;
1529         CHOOSEFONTW a0;
1530         LOGFONTW* pwlf;
1531 START_ROUTINE
1532         a0.lStructSize = sizeof(CHOOSEFONTW);
1533         a0.hwndOwner = v0->hwndOwner;
1534         a0.hDC = v0->hDC;
1535         if(v0->lpLogFont && (pwlf = (LOGFONTW*)malloc(sizeof(LOGFONTW))))
1536         {
1537                 pwlf->lfHeight = v0->lpLogFont->lfHeight;
1538                 pwlf->lfWidth = v0->lpLogFont->lfWidth;
1539                 pwlf->lfEscapement = v0->lpLogFont->lfEscapement;
1540                 pwlf->lfOrientation = v0->lpLogFont->lfOrientation;
1541                 pwlf->lfWeight = v0->lpLogFont->lfWeight;
1542                 pwlf->lfItalic = v0->lpLogFont->lfItalic;
1543                 pwlf->lfUnderline = v0->lpLogFont->lfUnderline;
1544                 pwlf->lfStrikeOut = v0->lpLogFont->lfStrikeOut;
1545                 pwlf->lfCharSet = v0->lpLogFont->lfCharSet;
1546                 pwlf->lfOutPrecision = v0->lpLogFont->lfOutPrecision;
1547                 pwlf->lfClipPrecision = v0->lpLogFont->lfClipPrecision;
1548                 pwlf->lfQuality = v0->lpLogFont->lfQuality;
1549                 pwlf->lfPitchAndFamily = v0->lpLogFont->lfPitchAndFamily;
1550                 MtoW(pwlf->lfFaceName, LF_FACESIZE, v0->lpLogFont->lfFaceName, -1);
1551                 TerminateStringW(pwlf->lfFaceName, LF_FACESIZE);
1552         }
1553         else
1554                 pwlf = NULL;
1555         a0.lpLogFont = pwlf;
1556         a0.iPointSize = v0->iPointSize;
1557         a0.Flags = v0->Flags;
1558         a0.rgbColors = v0->rgbColors;
1559         a0.lCustData = v0->lCustData;
1560         a0.lpfnHook = v0->lpfnHook;
1561         a0.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);
1562         a0.hInstance = v0->hInstance;
1563         a0.lpszStyle = DuplicateMtoWBuffer(v0->lpszStyle, -1, LF_FACESIZE * 4);
1564         a0.nFontType = v0->nFontType;
1565         a0.nSizeMin = v0->nSizeMin;
1566         a0.nSizeMax = v0->nSizeMax;
1567         r = ChooseFontW(&a0);
1568         if(v0->lpLogFont)
1569         {
1570                 v0->lpLogFont->lfHeight = pwlf->lfHeight;
1571                 v0->lpLogFont->lfWidth = pwlf->lfWidth;
1572                 v0->lpLogFont->lfEscapement = pwlf->lfEscapement;
1573                 v0->lpLogFont->lfOrientation = pwlf->lfOrientation;
1574                 v0->lpLogFont->lfWeight = pwlf->lfWeight;
1575                 v0->lpLogFont->lfItalic = pwlf->lfItalic;
1576                 v0->lpLogFont->lfUnderline = pwlf->lfUnderline;
1577                 v0->lpLogFont->lfStrikeOut = pwlf->lfStrikeOut;
1578                 v0->lpLogFont->lfCharSet = pwlf->lfCharSet;
1579                 v0->lpLogFont->lfOutPrecision = pwlf->lfOutPrecision;
1580                 v0->lpLogFont->lfClipPrecision = pwlf->lfClipPrecision;
1581                 v0->lpLogFont->lfQuality = pwlf->lfQuality;
1582                 v0->lpLogFont->lfPitchAndFamily = pwlf->lfPitchAndFamily;
1583                 WtoM(v0->lpLogFont->lfFaceName, LF_FACESIZE, pwlf->lfFaceName, -1);
1584                 TerminateStringM(v0->lpLogFont->lfFaceName, LF_FACESIZE);
1585         }
1586         v0->rgbColors = a0.rgbColors;
1587         WtoM(v0->lpszStyle, LF_FACESIZE, a0.lpszStyle, -1);
1588         TerminateStringM(v0->lpszStyle, LF_FACESIZE);
1589         v0->nFontType = a0.nFontType;
1590         if(pwlf)
1591                 free(pwlf);
1592         FreeDuplicatedString(a0.lpTemplateName);
1593         FreeDuplicatedString(a0.lpszStyle);
1594 END_ROUTINE
1595         FreeDuplicatedString(pw0);
1596         return r;
1597 }
1598
1599 INT_PTR DialogBoxParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
1600 {
1601         INT_PTR r = 0;
1602         wchar_t* pw0 = NULL;
1603 START_ROUTINE
1604         pw0 = DuplicateMtoW(lpTemplateName, -1);
1605         r = DialogBoxParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
1606 END_ROUTINE
1607         FreeDuplicatedString(pw0);
1608         return r;
1609 }
1610
1611 HWND CreateDialogParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
1612 {
1613         HWND r = NULL;
1614         wchar_t* pw0 = NULL;
1615 START_ROUTINE
1616         pw0 = DuplicateMtoW(lpTemplateName, -1);
1617         r = CreateDialogParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
1618 END_ROUTINE
1619         FreeDuplicatedString(pw0);
1620         return r;
1621 }
1622
1623 int mkdirM(const char * _Path)
1624 {
1625         int r = 0;
1626         wchar_t* pw0 = NULL;
1627 START_ROUTINE
1628         pw0 = DuplicateMtoW(_Path, -1);
1629         r = _wmkdir(pw0);
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 rmdirM(const char * _Path)
1648 {
1649         int r = 0;
1650         wchar_t* pw0 = NULL;
1651 START_ROUTINE
1652         pw0 = DuplicateMtoW(_Path, -1);
1653         r = _wrmdir(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 size_t _mbslenM(const unsigned char * _Str)
1672 {
1673         size_t r = 0;
1674         wchar_t* pw0 = NULL;
1675 START_ROUTINE
1676         pw0 = DuplicateMtoW(_Str, -1);
1677         r = wcslen(pw0);
1678 END_ROUTINE
1679         FreeDuplicatedString(pw0);
1680         return r;
1681 }
1682
1683 unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)
1684 {
1685         unsigned char* r = NULL;
1686         wchar_t* pw0 = NULL;
1687         wchar_t* wr;
1688 START_ROUTINE
1689         pw0 = DuplicateMtoW(_Str, -1);
1690         // TODO: 非ASCII文字の対応
1691         wr = wcschr(pw0, _Ch);
1692         if(wr)
1693         {
1694                 *wr = L'\0';
1695                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1696         }
1697 END_ROUTINE
1698         FreeDuplicatedString(pw0);
1699         return r;
1700 }
1701
1702 unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)
1703 {
1704         unsigned char* r = NULL;
1705         wchar_t* pw0 = NULL;
1706         wchar_t* wr;
1707 START_ROUTINE
1708         pw0 = DuplicateMtoW(_Str, -1);
1709         // TODO: 非ASCII文字の対応
1710         wr = wcsrchr(pw0, _Ch);
1711         if(wr)
1712         {
1713                 *wr = L'\0';
1714                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1715         }
1716 END_ROUTINE
1717         FreeDuplicatedString(pw0);
1718         return r;
1719 }
1720
1721 unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)
1722 {
1723         unsigned char* r = NULL;
1724         wchar_t* pw0 = NULL;
1725         wchar_t* pw1 = NULL;
1726         wchar_t* wr;
1727 START_ROUTINE
1728         pw0 = DuplicateMtoW(_Str, -1);
1729         pw1 = DuplicateMtoW(_Substr, -1);
1730         wr = wcsstr(pw0, pw1);
1731         if(wr)
1732         {
1733                 *wr = L'\0';
1734                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1735         }
1736 END_ROUTINE
1737         FreeDuplicatedString(pw0);
1738         FreeDuplicatedString(pw1);
1739         return r;
1740 }
1741
1742 int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)
1743 {
1744         int r = 0;
1745         wchar_t* pw0 = NULL;
1746         wchar_t* pw1 = NULL;
1747 START_ROUTINE
1748         pw0 = DuplicateMtoW(_Str1, -1);
1749         pw1 = DuplicateMtoW(_Str2, -1);
1750         r = wcscmp(pw0, pw1);
1751 END_ROUTINE
1752         FreeDuplicatedString(pw0);
1753         FreeDuplicatedString(pw1);
1754         return r;
1755 }
1756
1757 int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)
1758 {
1759         int r = 0;
1760         wchar_t* pw0 = NULL;
1761         wchar_t* pw1 = NULL;
1762 START_ROUTINE
1763         pw0 = DuplicateMtoW(_Str1, -1);
1764         pw1 = DuplicateMtoW(_Str2, -1);
1765         r = _wcsicmp(pw0, pw1);
1766 END_ROUTINE
1767         FreeDuplicatedString(pw0);
1768         FreeDuplicatedString(pw1);
1769         return r;
1770 }
1771
1772 int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)
1773 {
1774         int r = 0;
1775         wchar_t* pw0 = NULL;
1776         wchar_t* pw1 = NULL;
1777 START_ROUTINE
1778         pw0 = DuplicateMtoW(_Str1, -1);
1779         pw1 = DuplicateMtoW(_Str2, -1);
1780         r = wcsncmp(pw0, pw1, _MaxCount);
1781 END_ROUTINE
1782         FreeDuplicatedString(pw0);
1783         FreeDuplicatedString(pw1);
1784         return r;
1785 }
1786
1787 unsigned char * _mbslwrM(unsigned char * _String)
1788 {
1789         unsigned char* r = NULL;
1790         wchar_t* pw0 = NULL;
1791 START_ROUTINE
1792         pw0 = DuplicateMtoW(_String, -1);
1793         _wcslwr(pw0);
1794         r = _String;
1795         WtoM(_String, strlen(_String) + 1, pw0, -1);
1796 END_ROUTINE
1797         FreeDuplicatedString(pw0);
1798         return r;
1799 }
1800
1801 unsigned char * _mbsuprM(unsigned char * _String)
1802 {
1803         unsigned char* r = NULL;
1804         wchar_t* pw0 = NULL;
1805 START_ROUTINE
1806         pw0 = DuplicateMtoW(_String, -1);
1807         _wcsupr(pw0);
1808         r = _String;
1809         WtoM(_String, strlen(_String) + 1, pw0, -1);
1810 END_ROUTINE
1811         FreeDuplicatedString(pw0);
1812         return r;
1813 }
1814
1815 unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)
1816 {
1817         unsigned char* r = NULL;
1818         wchar_t* pw0 = NULL;
1819         wchar_t* wr;
1820 START_ROUTINE
1821         pw0 = DuplicateMtoW(_Str, -1);
1822         wr = _wcsninc(pw0, _Count);
1823         if(wr)
1824         {
1825                 *wr = L'\0';
1826                 r = _Str + WtoM(NULL, 0, pw0, -1) - 1;
1827         }
1828 END_ROUTINE
1829         FreeDuplicatedString(pw0);
1830         return r;
1831 }
1832