OSDN Git Service

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