OSDN Git Service

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