OSDN Git Service

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