OSDN Git Service

Fix bugs of UPnP port mapping control.
[ffftp/ffftp.git] / mbswrapper.c
1 // mbswrapper.c\r
2 // Copyright (C) 2011 Suguru Kawamoto\r
3 // マルチバイト文字ワイド文字APIラッパー\r
4 // マルチバイト文字はUTF-8、ワイド文字はUTF-16であるものとする\r
5 // 全ての制御用の文字はASCIIの範囲であるため、Shift_JISとUTF-8間の変換は不要\r
6 \r
7 #define UNICODE\r
8 #define _UNICODE\r
9 \r
10 #include <stdio.h>\r
11 #include <tchar.h>\r
12 #include <direct.h>\r
13 #include <windows.h>\r
14 #include <commctrl.h>\r
15 #include <shlobj.h>\r
16 #include <htmlhelp.h>\r
17 \r
18 #define DO_NOT_REPLACE\r
19 #include "mbswrapper.h"\r
20 \r
21 // マルチバイト文字列からワイド文字列へ変換\r
22 int MtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)\r
23 {\r
24         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
25                 return 0;\r
26         if(pDst)\r
27                 return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, pDst, size);\r
28         return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, NULL, 0);\r
29 }\r
30 \r
31 // ワイド文字列からマルチバイト文字列へ変換\r
32 int WtoM(LPSTR pDst, int size, LPCWSTR pSrc, int count)\r
33 {\r
34         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
35                 return 0;\r
36         if(pDst)\r
37                 return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, pDst, size, NULL, NULL);\r
38         return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, NULL, 0, NULL, NULL);\r
39 }\r
40 \r
41 // Shift_JIS文字列からワイド文字列へ変換\r
42 int AtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)\r
43 {\r
44         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
45                 return 0;\r
46         if(pDst)\r
47                 return MultiByteToWideChar(CP_ACP, 0, pSrc, count, pDst, size);\r
48         return MultiByteToWideChar(CP_ACP, 0, pSrc, count, NULL, 0);\r
49 }\r
50 \r
51 // ワイド文字列からShift_JIS文字列へ変換\r
52 int WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)\r
53 {\r
54         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
55                 return 0;\r
56         if(pDst)\r
57                 return WideCharToMultiByte(CP_ACP, 0, pSrc, count, pDst, size, NULL, NULL);\r
58         return WideCharToMultiByte(CP_ACP, 0, pSrc, count, NULL, 0, NULL, NULL);\r
59 }\r
60 \r
61 // マルチバイト文字列バッファ終端を強制的にNULLで置換\r
62 int TerminateStringM(LPSTR lpString, int size)\r
63 {\r
64         int i;\r
65         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)\r
66                 return 0;\r
67         for(i = 0; i < size; i++)\r
68         {\r
69                 if(lpString[i] == '\0')\r
70                         return i;\r
71         }\r
72         i--;\r
73         lpString[i] = '\0';\r
74         return i;\r
75 }\r
76 \r
77 // ワイド文字列バッファ終端を強制的にNULLで置換\r
78 int TerminateStringW(LPWSTR lpString, int size)\r
79 {\r
80         int i;\r
81         if(lpString < (LPWSTR)0x00010000 || lpString == (LPWSTR)~0)\r
82                 return 0;\r
83         for(i = 0; i < size; i++)\r
84         {\r
85                 if(lpString[i] == L'\0')\r
86                         return i;\r
87         }\r
88         i--;\r
89         lpString[i] = L'\0';\r
90         return i;\r
91 }\r
92 \r
93 // Shift_JIS文字列バッファ終端を強制的にNULLで置換\r
94 int TerminateStringA(LPSTR lpString, int size)\r
95 {\r
96         int i;\r
97         if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)\r
98                 return 0;\r
99         for(i = 0; i < size; i++)\r
100         {\r
101                 if(lpString[i] == '\0')\r
102                         return i;\r
103         }\r
104         i--;\r
105         lpString[i] = '\0';\r
106         return i;\r
107 }\r
108 \r
109 // NULL区切り複数マルチバイト文字列の長さを取得\r
110 size_t GetMultiStringLengthM(LPCSTR lpString)\r
111 {\r
112         size_t i;\r
113         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
114                 return 0;\r
115         i = 0;\r
116         while(lpString[i] != '\0' || lpString[i + 1] != '\0')\r
117         {\r
118                 i++;\r
119         }\r
120         i++;\r
121         return i;\r
122 }\r
123 \r
124 // NULL区切り複数ワイド文字列の長さを取得\r
125 size_t GetMultiStringLengthW(LPCWSTR lpString)\r
126 {\r
127         size_t i;\r
128         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
129                 return 0;\r
130         i = 0;\r
131         while(lpString[i] != L'\0' || lpString[i + 1] != L'\0')\r
132         {\r
133                 i++;\r
134         }\r
135         i++;\r
136         return i;\r
137 }\r
138 \r
139 // NULL区切り複数Shift_JIS文字列の長さを取得\r
140 size_t GetMultiStringLengthA(LPCSTR lpString)\r
141 {\r
142         size_t i;\r
143         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
144                 return 0;\r
145         i = 0;\r
146         while(lpString[i] != '\0' || lpString[i + 1] != '\0')\r
147         {\r
148                 i++;\r
149         }\r
150         i++;\r
151         return i;\r
152 }\r
153 \r
154 // NULL区切りマルチバイト文字列からワイド文字列へ変換\r
155 int MtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)\r
156 {\r
157         int i;\r
158         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
159                 return 0;\r
160         if(!pDst)\r
161                 return GetMultiStringLengthM(pSrc);\r
162         i = 0;\r
163         while(*pSrc != '\0')\r
164         {\r
165                 i += MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1);\r
166                 pSrc += strlen(pSrc) + 1;\r
167         }\r
168         pDst[i] = L'\0';\r
169         return i;\r
170 }\r
171 \r
172 // NULL区切りワイド文字列からマルチバイト文字列へ変換\r
173 int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)\r
174 {\r
175         int i;\r
176         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
177                 return 0;\r
178         if(!pDst)\r
179                 return GetMultiStringLengthW(pSrc);\r
180         i = 0;\r
181         while(*pSrc != L'\0')\r
182         {\r
183                 i += WideCharToMultiByte(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);\r
184                 pSrc += wcslen(pSrc) + 1;\r
185         }\r
186         pDst[i] = '\0';\r
187         return i;\r
188 }\r
189 \r
190 // NULL区切りShift_JIS文字列からワイド文字列へ変換\r
191 int AtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)\r
192 {\r
193         int i;\r
194         if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)\r
195                 return 0;\r
196         if(!pDst)\r
197                 return GetMultiStringLengthA(pSrc);\r
198         i = 0;\r
199         while(*pSrc != '\0')\r
200         {\r
201                 i += MultiByteToWideChar(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1);\r
202                 pSrc += strlen(pSrc) + 1;\r
203         }\r
204         pDst[i] = L'\0';\r
205         return i;\r
206 }\r
207 \r
208 // NULL区切りワイド文字列からShift_JIS文字列へ変換\r
209 int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)\r
210 {\r
211         int i;\r
212         if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)\r
213                 return 0;\r
214         if(!pDst)\r
215                 return GetMultiStringLengthW(pSrc);\r
216         i = 0;\r
217         while(*pSrc != L'\0')\r
218         {\r
219                 i += WideCharToMultiByte(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);\r
220                 pSrc += wcslen(pSrc) + 1;\r
221         }\r
222         pDst[i] = '\0';\r
223         return i;\r
224 }\r
225 \r
226 // マルチバイト文字列用のメモリを確保\r
227 char* AllocateStringM(int size)\r
228 {\r
229         char* p;\r
230         // 0が指定される場合があるため1文字分追加\r
231         p = (char*)malloc(sizeof(char) * (size + 1));\r
232         // 念のため先頭にNULL文字を代入\r
233         if(p)\r
234                 *p = '\0';\r
235         return p;\r
236 }\r
237 \r
238 // ワイド文字列用のメモリを確保\r
239 wchar_t* AllocateStringW(int size)\r
240 {\r
241         wchar_t* p;\r
242         // 0が指定される場合があるため1文字分追加\r
243         p = (wchar_t*)malloc(sizeof(wchar_t) * (size + 1));\r
244         // 念のため先頭にNULL文字を代入\r
245         if(p)\r
246                 *p = L'\0';\r
247         return p;\r
248 }\r
249 \r
250 // Shift_JIS文字列用のメモリを確保\r
251 char* AllocateStringA(int size)\r
252 {\r
253         char* p;\r
254         // 0が指定される場合があるため1文字分追加\r
255         p = (char*)malloc(sizeof(char) * (size + 1));\r
256         // 念のため先頭にNULL文字を代入\r
257         if(p)\r
258                 *p = '\0';\r
259         return p;\r
260 }\r
261 \r
262 // メモリを確保してマルチバイト文字列からワイド文字列へ変換\r
263 // リソースIDならば元の値を返す\r
264 wchar_t* DuplicateMtoW(LPCSTR lpString, int c)\r
265 {\r
266         wchar_t* p;\r
267         int i;\r
268         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
269                 return (wchar_t*)lpString;\r
270         if(c < 0)\r
271                 c = strlen(lpString);\r
272         p = AllocateStringW(MtoW(NULL, 0, lpString, c) + 1);\r
273         if(p)\r
274         {\r
275                 i = MtoW(p, 65535, lpString, c);\r
276                 p[i] = L'\0';\r
277         }\r
278         return p;\r
279 }\r
280 \r
281 // 指定したサイズのメモリを確保してマルチバイト文字列からワイド文字列へ変換\r
282 // リソースIDならば元の値を返す\r
283 wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)\r
284 {\r
285         wchar_t* p;\r
286         int i;\r
287         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
288                 return (wchar_t*)lpString;\r
289         if(c < 0)\r
290                 c = strlen(lpString);\r
291         p = AllocateStringW(size);\r
292         if(p)\r
293         {\r
294                 i = MtoW(p, size, lpString, c);\r
295                 p[i] = L'\0';\r
296         }\r
297         return p;\r
298 }\r
299 \r
300 // メモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換\r
301 // リソースIDならば元の値を返す\r
302 wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)\r
303 {\r
304         int count;\r
305         wchar_t* p;\r
306         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
307                 return (wchar_t*)lpString;\r
308         count = GetMultiStringLengthM(lpString) + 1;\r
309         p = AllocateStringW(count);\r
310         if(p)\r
311                 MtoW(p, count, lpString, count);\r
312         return p;\r
313 }\r
314 \r
315 // 指定したサイズのメモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換\r
316 // リソースIDならば元の値を返す\r
317 wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)\r
318 {\r
319         int count;\r
320         wchar_t* p;\r
321         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
322                 return (wchar_t*)lpString;\r
323         count = GetMultiStringLengthM(lpString) + 1;\r
324         p = AllocateStringW(size);\r
325         if(p)\r
326         {\r
327                 MtoW(p, size, lpString, count);\r
328                 p[size - 2] = L'\0';\r
329                 p[size - 1] = L'\0';\r
330         }\r
331         return p;\r
332 }\r
333 \r
334 // メモリを確保してワイド文字列からマルチバイト文字列へ変換\r
335 // リソースIDならば元の値を返す\r
336 char* DuplicateWtoM(LPCWSTR lpString, int c)\r
337 {\r
338         char* p;\r
339         int i;\r
340         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
341                 return (char*)lpString;\r
342         if(c < 0)\r
343                 c = wcslen(lpString);\r
344         p = AllocateStringM(WtoM(NULL, 0, lpString, c) + 1);\r
345         if(p)\r
346         {\r
347                 i = WtoM(p, 65535, lpString, c);\r
348                 p[i] = L'\0';\r
349         }\r
350         return p;\r
351 }\r
352 \r
353 // メモリを確保してShift_JIS文字列からワイド文字列へ変換\r
354 // リソースIDならば元の値を返す\r
355 wchar_t* DuplicateAtoW(LPCSTR lpString, int c)\r
356 {\r
357         wchar_t* p;\r
358         int i;\r
359         if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)\r
360                 return (wchar_t*)lpString;\r
361         if(c < 0)\r
362                 c = strlen(lpString);\r
363         p = AllocateStringW(AtoW(NULL, 0, lpString, c) + 1);\r
364         if(p)\r
365         {\r
366                 i = AtoW(p, 65535, lpString, c);\r
367                 p[i] = L'\0';\r
368         }\r
369         return p;\r
370 }\r
371 \r
372 // メモリを確保してワイド文字列からShift_JIS文字列へ変換\r
373 // リソースIDならば元の値を返す\r
374 char* DuplicateWtoA(LPCWSTR lpString, int c)\r
375 {\r
376         char* p;\r
377         int i;\r
378         if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)\r
379                 return (char*)lpString;\r
380         if(c < 0)\r
381                 c = wcslen(lpString);\r
382         p = AllocateStringA(WtoA(NULL, 0, lpString, c) + 1);\r
383         if(p)\r
384         {\r
385                 i = WtoA(p, 65535, lpString, c);\r
386                 p[i] = L'\0';\r
387         }\r
388         return p;\r
389 }\r
390 \r
391 // マルチバイト文字列からコードポイントと次のポインタを取得\r
392 // エンコードが不正な場合は0x80000000を返す\r
393 DWORD GetNextCharM(LPCSTR lpString, LPCSTR pLimit, LPCSTR* ppNext)\r
394 {\r
395         DWORD Code;\r
396         int i;\r
397         Code = 0;\r
398         i = -1;\r
399         if(!pLimit)\r
400                 pLimit = (LPCSTR)(~0);\r
401         if(lpString < pLimit)\r
402         {\r
403                 if((*lpString & 0xfe) == 0xfc)\r
404                 {\r
405                         i = 5;\r
406                         Code |= (DWORD)*lpString & 0x01;\r
407                 }\r
408                 else if((*lpString & 0xfc) == 0xf8)\r
409                 {\r
410                         i = 4;\r
411                         Code |= (DWORD)*lpString & 0x03;\r
412                 }\r
413                 else if((*lpString & 0xf8) == 0xf0)\r
414                 {\r
415                         i = 3;\r
416                         Code |= (DWORD)*lpString & 0x07;\r
417                 }\r
418                 else if((*lpString & 0xf0) == 0xe0)\r
419                 {\r
420                         i = 2;\r
421                         Code |= (DWORD)*lpString & 0x0f;\r
422                 }\r
423                 else if((*lpString & 0xe0) == 0xc0)\r
424                 {\r
425                         i = 1;\r
426                         Code |= (DWORD)*lpString & 0x1f;\r
427                 }\r
428                 else if((*lpString & 0x80) == 0x00)\r
429                 {\r
430                         i = 0;\r
431                         Code |= (DWORD)*lpString & 0x7f;\r
432                 }\r
433                 lpString++;\r
434                 while(lpString < pLimit && i > 0 && (*lpString & 0xc0) == 0x80)\r
435                 {\r
436                         i--;\r
437                         Code = Code << 6;\r
438                         Code |= (DWORD)*lpString & 0x3f;\r
439                         lpString++;\r
440                 }\r
441         }\r
442         if(i != 0)\r
443                 Code = 0x80000000;\r
444         if(ppNext)\r
445                 *ppNext = lpString;\r
446         return Code;\r
447 }\r
448 \r
449 // マルチバイト文字列へコードポイントの文字を追加して次のポインタを取得\r
450 // 文字の長さを返す\r
451 int PutNextCharM(LPSTR lpString, LPSTR pLimit, LPSTR* ppNext, DWORD Code)\r
452 {\r
453         int Count;\r
454         int i;\r
455         Count = 0;\r
456         i = -1;\r
457         if(!pLimit)\r
458                 pLimit = (LPSTR)(~0);\r
459         if(lpString < pLimit)\r
460         {\r
461                 if(Code & 0x7c000000)\r
462                 {\r
463                         i = 5;\r
464                         *lpString = 0xfc | ((CHAR)(Code >> 30) & 0x01);\r
465                 }\r
466                 else if(Code & 0x03e00000)\r
467                 {\r
468                         i = 4;\r
469                         *lpString = 0xf8 | ((CHAR)(Code >> 24) & 0x03);\r
470                 }\r
471                 else if(Code & 0x001f0000)\r
472                 {\r
473                         i = 3;\r
474                         *lpString = 0xf0 | ((CHAR)(Code >> 18) & 0x07);\r
475                 }\r
476                 else if(Code & 0x0000f800)\r
477                 {\r
478                         i = 2;\r
479                         *lpString = 0xe0 | ((CHAR)(Code >> 12) & 0x0f);\r
480                 }\r
481                 else if(Code & 0x00000780)\r
482                 {\r
483                         i = 1;\r
484                         *lpString = 0xc0 | ((CHAR)(Code >> 6) & 0x1f);\r
485                 }\r
486                 else\r
487                 {\r
488                         i = 0;\r
489                         *lpString = (CHAR)Code & 0x7f;\r
490                 }\r
491                 Count = i + 1;\r
492                 lpString++;\r
493                 while(lpString < pLimit && i > 0)\r
494                 {\r
495                         i--;\r
496                         *lpString = 0x80 | ((CHAR)(Code >> (i * 6)) & 0x3f);\r
497                         lpString++;\r
498                 }\r
499         }\r
500         if(i != 0)\r
501                 Count = 0;\r
502         if(ppNext)\r
503                 *ppNext = lpString;\r
504         return Count;\r
505 }\r
506 \r
507 // ワイド文字列からコードポイントと次のポインタを取得\r
508 // エンコードが不正な場合は0x80000000を返す\r
509 DWORD GetNextCharW(LPCWSTR lpString, LPCWSTR pLimit, LPCWSTR* ppNext)\r
510 {\r
511         DWORD Code;\r
512         Code = 0x80000000;\r
513         if(!pLimit)\r
514                 pLimit = (LPCWSTR)(~0);\r
515         if(lpString < pLimit)\r
516         {\r
517                 if((*lpString & 0xf800) == 0xd800)\r
518                 {\r
519                         if((*lpString & 0x0400) == 0x0400)\r
520                         {\r
521                                 Code = (DWORD)*lpString & 0x03ff;\r
522                                 lpString++;\r
523                                 if(lpString < pLimit)\r
524                                 {\r
525                                         if((*lpString & 0x0400) == 0x0000)\r
526                                         {\r
527                                                 Code |= ((DWORD)*lpString & 0x03ff) << 10;\r
528                                                 lpString++;\r
529                                         }\r
530                                         else\r
531                                                 Code = 0x80000000;\r
532                                 }\r
533                                 else\r
534                                         Code = 0x80000000;\r
535                         }\r
536                 }\r
537                 else\r
538                 {\r
539                         Code = (DWORD)*lpString;\r
540                         lpString++;\r
541                 }\r
542         }\r
543         if(ppNext)\r
544                 *ppNext = lpString;\r
545         return Code;\r
546 }\r
547 \r
548 // ワイド文字列へコードポイントの文字を追加して次のポインタを取得\r
549 // 文字の長さを返す\r
550 int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code)\r
551 {\r
552         int Count;\r
553         Count = 0;\r
554         if(!pLimit)\r
555                 pLimit = (LPWSTR)(~0);\r
556         if(lpString < pLimit)\r
557         {\r
558                 if((Code & 0x7fff0000) || (Code & 0x0000f800) == 0x0000d800)\r
559                 {\r
560                         *lpString = 0xdc00 | ((WCHAR)Code & 0x03ff);\r
561                         lpString++;\r
562                         if(lpString < pLimit)\r
563                         {\r
564                                 *lpString = 0xd800 | ((WCHAR)(Code >> 10) & 0x03ff);\r
565                                 lpString++;\r
566                                 Count = 2;\r
567                         }\r
568                 }\r
569                 else\r
570                 {\r
571                         *lpString = (WCHAR)Code;\r
572                         lpString++;\r
573                         Count = 1;\r
574                 }\r
575         }\r
576         if(ppNext)\r
577                 *ppNext = lpString;\r
578         return Count;\r
579 }\r
580 \r
581 // マルチバイト文字列のコードポイントの個数を取得\r
582 int GetCodeCountM(LPCSTR lpString, int CharCount)\r
583 {\r
584         int Count;\r
585         LPCSTR pLimit;\r
586         DWORD Code;\r
587         Count = 0;\r
588         if(CharCount == -1)\r
589                 pLimit = lpString + strlen(lpString);\r
590         else\r
591                 pLimit = lpString + CharCount;\r
592         while(lpString < pLimit)\r
593         {\r
594                 Code = GetNextCharM(lpString, pLimit, &lpString);\r
595                 if(Code == 0x80000000)\r
596                         continue;\r
597                 Count++;\r
598         }\r
599         return Count;\r
600 }\r
601 \r
602 // ワイド文字列のコードポイントの個数を取得\r
603 int GetCodeCountW(LPCWSTR lpString, int CharCount)\r
604 {\r
605         int Count;\r
606         LPCWSTR pLimit;\r
607         DWORD Code;\r
608         Count = 0;\r
609         if(CharCount == -1)\r
610                 pLimit = lpString + wcslen(lpString);\r
611         else\r
612                 pLimit = lpString + CharCount;\r
613         while(lpString < pLimit)\r
614         {\r
615                 Code = GetNextCharW(lpString, pLimit, &lpString);\r
616                 if(Code == 0x80000000)\r
617                         continue;\r
618                 Count++;\r
619         }\r
620         return Count;\r
621 }\r
622 \r
623 // マルチバイト文字列の冗長表現を修正\r
624 // 修正があればTRUEを返す\r
625 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
626 BOOL FixStringM(LPSTR pDst, LPCSTR pSrc)\r
627 {\r
628         BOOL bResult;\r
629         char* p;\r
630         DWORD Code;\r
631         int i;\r
632         char c;\r
633         bResult = FALSE;\r
634         p = (char*)pSrc;\r
635         while(*pSrc != '\0')\r
636         {\r
637                 Code = GetNextCharM(pSrc, NULL, &pSrc);\r
638                 if(Code & 0x80000000)\r
639                         continue;\r
640                 else if(Code & 0x7c000000)\r
641                 {\r
642                         i = 5;\r
643                         c = (char)(0xfc | (Code >> (6 * i)));\r
644                 }\r
645                 else if(Code & 0x03e00000)\r
646                 {\r
647                         i = 4;\r
648                         c = (char)(0xf8 | (Code >> (6 * i)));\r
649                 }\r
650                 else if(Code & 0x001f0000)\r
651                 {\r
652                         i = 3;\r
653                         c = (char)(0xf0 | (Code >> (6 * i)));\r
654                 }\r
655                 else if(Code & 0x0000f800)\r
656                 {\r
657                         i = 2;\r
658                         c = (char)(0xe0 | (Code >> (6 * i)));\r
659                 }\r
660                 else if(Code & 0x00000780)\r
661                 {\r
662                         i = 1;\r
663                         c = (char)(0xc0 | (Code >> (6 * i)));\r
664                 }\r
665                 else\r
666                 {\r
667                         i = 0;\r
668                         c = (char)Code;\r
669                 }\r
670                 if(c != *p)\r
671                         bResult = TRUE;\r
672                 p++;\r
673                 *pDst = c;\r
674                 pDst++;\r
675                 while(i > 0)\r
676                 {\r
677                         i--;\r
678                         c = (char)(0x80 | ((Code >> (6 * i)) & 0x3f));\r
679                         if(c != *p)\r
680                                 bResult = TRUE;\r
681                         p++;\r
682                         *pDst = c;\r
683                         pDst++;\r
684                 }\r
685         }\r
686         if(*p != '\0')\r
687                 bResult = TRUE;\r
688         *pDst = '\0';\r
689         return bResult;\r
690 }\r
691 \r
692 // NULL区切りマルチバイト文字列の冗長表現を修正\r
693 // 修正があればTRUEを返す\r
694 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
695 BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc)\r
696 {\r
697         BOOL bResult;\r
698         int Length;\r
699         bResult = FALSE;\r
700         while(*pSrc != '\0')\r
701         {\r
702                 Length = strlen(pSrc) + 1;\r
703                 bResult = bResult | FixStringM(pDst, pSrc);\r
704                 pSrc += Length;\r
705                 pDst += strlen(pDst) + 1;\r
706         }\r
707         *pDst = '\0';\r
708         return bResult;\r
709 }\r
710 \r
711 // マルチバイト文字列の冗長表現を確認\r
712 // 冗長表現があればTRUEを返す\r
713 BOOL CheckStringM(LPCSTR lpString)\r
714 {\r
715         BOOL bResult;\r
716         char* p;\r
717         bResult = FALSE;\r
718         p = AllocateStringM(strlen(lpString) + 1);\r
719         if(p)\r
720         {\r
721                 bResult = FixStringM(p, lpString);\r
722                 FreeDuplicatedString(p);\r
723         }\r
724         return bResult;\r
725 }\r
726 \r
727 // NULL区切りマルチバイト文字列の冗長表現を確認\r
728 // 冗長表現があればTRUEを返す\r
729 BOOL CheckMultiStringM(LPCSTR lpString)\r
730 {\r
731         BOOL bResult;\r
732         char* p;\r
733         bResult = FALSE;\r
734         p = AllocateStringM(GetMultiStringLengthM(lpString) + 1);\r
735         if(p)\r
736         {\r
737                 bResult = FixMultiStringM(p, lpString);\r
738                 FreeDuplicatedString(p);\r
739         }\r
740         return bResult;\r
741 }\r
742 \r
743 // 文字列用に確保したメモリを開放\r
744 // リソースIDならば何もしない\r
745 void FreeDuplicatedString(void* p)\r
746 {\r
747         if(p < (void*)0x00010000 || p == (void*)~0)\r
748                 return;\r
749         free(p);\r
750 }\r
751 \r
752 // マルチバイト文字列からワイド文字列へ変換\r
753 // UTF-8からUTF-16 LEへの変換専用\r
754 int MultiByteToWideCharAlternative(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR lpWideCharStr, int cchWideChar)\r
755 {\r
756         int WideCount;\r
757         LPCSTR pMultiLimit;\r
758         LPWSTR pWideLimit;\r
759         DWORD Code;\r
760         int TempCount;\r
761         WCHAR Temp[8];\r
762         if(CodePage != CP_UTF8 || dwFlags != 0)\r
763                 return MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar);\r
764         WideCount = 0;\r
765         if(cbMultiByte == -1)\r
766                 pMultiLimit = lpMultiByteStr + strlen(lpMultiByteStr) + 1;\r
767         else\r
768                 pMultiLimit = lpMultiByteStr + cbMultiByte;\r
769         pWideLimit = lpWideCharStr + cchWideChar;\r
770         while(lpMultiByteStr < pMultiLimit)\r
771         {\r
772                 Code = GetNextCharM(lpMultiByteStr, pMultiLimit, &lpMultiByteStr);\r
773                 if(Code == 0x80000000)\r
774                         continue;\r
775                 if(lpWideCharStr)\r
776                 {\r
777                         TempCount = PutNextCharW(lpWideCharStr, pWideLimit, &lpWideCharStr, Code);\r
778                         WideCount += TempCount;\r
779                         if(TempCount == 0 && lpWideCharStr >= pWideLimit)\r
780                         {\r
781                                 WideCount = 0;\r
782                                 break;\r
783                         }\r
784                 }\r
785                 else\r
786                         WideCount += PutNextCharW(Temp, NULL, NULL, Code);\r
787         }\r
788         return WideCount;\r
789 }\r
790 \r
791 // ワイド文字列からマルチバイト文字列へ変換\r
792 // UTF-16 LEからUTF-8への変換専用\r
793 int WideCharToMultiByteAlternative(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar)\r
794 {\r
795         int MultiCount;\r
796         LPCWSTR pWideLimit;\r
797         LPSTR pMultiLimit;\r
798         DWORD Code;\r
799         int TempCount;\r
800         CHAR Temp[8];\r
801         if(CodePage != CP_UTF8 || dwFlags != 0)\r
802                 return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar);\r
803         MultiCount = 0;\r
804         if(cchWideChar == -1)\r
805                 pWideLimit = lpWideCharStr + wcslen(lpWideCharStr) + 1;\r
806         else\r
807                 pWideLimit = lpWideCharStr + cchWideChar;\r
808         pMultiLimit = lpMultiByteStr + cbMultiByte;\r
809         while(lpWideCharStr < pWideLimit)\r
810         {\r
811                 Code = GetNextCharW(lpWideCharStr, pWideLimit, &lpWideCharStr);\r
812                 if(Code == 0x80000000)\r
813                         continue;\r
814                 if(lpMultiByteStr)\r
815                 {\r
816                         TempCount = PutNextCharM(lpMultiByteStr, pMultiLimit, &lpMultiByteStr, Code);\r
817                         MultiCount += TempCount;\r
818                         if(TempCount == 0 && lpMultiByteStr >= pMultiLimit)\r
819                         {\r
820                                 MultiCount = 0;\r
821                                 break;\r
822                         }\r
823                 }\r
824                 else\r
825                         MultiCount += PutNextCharM(Temp, NULL, NULL, Code);\r
826         }\r
827         if(lpUsedDefaultChar)\r
828                 *lpUsedDefaultChar = FALSE;\r
829         return MultiCount;\r
830 }\r
831 \r
832 // 以下ラッパー\r
833 // 戻り値バッファ r\r
834 // ワイド文字バッファ pw%d\r
835 // マルチバイト文字バッファ pm%d\r
836 // 引数バッファ a%d\r
837 \r
838 #pragma warning(disable:4102)\r
839 #define START_ROUTINE                                   do{\r
840 #define END_ROUTINE                                             }while(0);end_of_routine:\r
841 #define QUIT_ROUTINE                                    goto end_of_routine;\r
842 \r
843 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)\r
844 {\r
845         int r = 0;\r
846         char* pm0 = NULL;\r
847 START_ROUTINE\r
848         pm0 = DuplicateWtoM(lpCmdLine, -1);\r
849         r = WinMainM(hInstance, hPrevInstance, pm0, nCmdShow);\r
850 END_ROUTINE\r
851         FreeDuplicatedString(pm0);\r
852         return r;\r
853 }\r
854 \r
855 HMODULE LoadLibraryM(LPCSTR lpLibFileName)\r
856 {\r
857         HMODULE r = NULL;\r
858         wchar_t* pw0 = NULL;\r
859 START_ROUTINE\r
860         pw0 = DuplicateMtoW(lpLibFileName, -1);\r
861         r = LoadLibraryW(pw0);\r
862 END_ROUTINE\r
863         FreeDuplicatedString(pw0);\r
864         return r;\r
865 }\r
866 \r
867 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)\r
868 {\r
869         HANDLE r = INVALID_HANDLE_VALUE;\r
870         wchar_t* pw0 = NULL;\r
871 START_ROUTINE\r
872         pw0 = DuplicateMtoW(lpFileName, -1);\r
873         r = CreateFileW(pw0, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);\r
874 END_ROUTINE\r
875         FreeDuplicatedString(pw0);\r
876         return r;\r
877 }\r
878 \r
879 int MessageBoxM(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)\r
880 {\r
881         int r = IDOK;\r
882         wchar_t* pw0 = NULL;\r
883         wchar_t* pw1 = NULL;\r
884 START_ROUTINE\r
885         pw0 = DuplicateMtoW(lpText, -1);\r
886         pw1 = DuplicateMtoW(lpCaption, -1);\r
887         r = MessageBoxW(hWnd, pw0, pw1, uType);\r
888 END_ROUTINE\r
889         FreeDuplicatedString(pw0);\r
890         FreeDuplicatedString(pw1);\r
891         return r;\r
892 }\r
893 \r
894 HANDLE FindFirstFileM(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)\r
895 {\r
896         HANDLE r = INVALID_HANDLE_VALUE;\r
897         wchar_t* pw0 = NULL;\r
898         WIN32_FIND_DATAW a0;\r
899 START_ROUTINE\r
900         pw0 = DuplicateMtoW(lpFileName, -1);\r
901         r = FindFirstFileW(pw0, &a0);\r
902         if(r != INVALID_HANDLE_VALUE)\r
903         {\r
904                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
905                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
906                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
907                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
908                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
909                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
910                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
911                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
912                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
913                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
914         }\r
915 END_ROUTINE\r
916         FreeDuplicatedString(pw0);\r
917         return r;\r
918 }\r
919 \r
920 BOOL FindNextFileM(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData)\r
921 {\r
922         BOOL r = FALSE;\r
923         WIN32_FIND_DATAW a0;\r
924 START_ROUTINE\r
925         r = FindNextFileW(hFindFile, &a0);\r
926         if(r)\r
927         {\r
928                 lpFindFileData->dwFileAttributes = a0.dwFileAttributes;\r
929                 lpFindFileData->ftCreationTime = a0.ftCreationTime;\r
930                 lpFindFileData->ftLastAccessTime = a0.ftLastAccessTime;\r
931                 lpFindFileData->ftLastWriteTime = a0.ftLastWriteTime;\r
932                 lpFindFileData->nFileSizeHigh = a0.nFileSizeHigh;\r
933                 lpFindFileData->nFileSizeLow = a0.nFileSizeLow;\r
934                 lpFindFileData->dwReserved0 = a0.dwReserved0;\r
935                 lpFindFileData->dwReserved1 = a0.dwReserved1;\r
936                 WtoM(lpFindFileData->cFileName, sizeof(lpFindFileData->cFileName), a0.cFileName, -1);\r
937                 WtoM(lpFindFileData->cAlternateFileName, sizeof(lpFindFileData->cAlternateFileName), a0.cAlternateFileName, -1);\r
938         }\r
939 END_ROUTINE\r
940         return r;\r
941 }\r
942 \r
943 HANDLE FindFirstChangeNotificationM(LPCSTR lpPathName, BOOL bWatchSubtree, DWORD dwNotifyFilter)\r
944 {\r
945         HANDLE r = INVALID_HANDLE_VALUE;\r
946         wchar_t* pw0 = NULL;\r
947 START_ROUTINE\r
948         pw0 = DuplicateMtoW(lpPathName, -1);\r
949         r = FindFirstChangeNotificationW(pw0, bWatchSubtree, dwNotifyFilter);\r
950 END_ROUTINE\r
951         FreeDuplicatedString(pw0);\r
952         return r;\r
953 }\r
954 \r
955 DWORD GetLogicalDriveStringsM(DWORD nBufferLength, LPSTR lpBuffer)\r
956 {\r
957         DWORD r = 0;\r
958         wchar_t* pw0 = NULL;\r
959 START_ROUTINE\r
960         pw0 = AllocateStringW(nBufferLength * 4);\r
961         GetLogicalDriveStringsW(nBufferLength * 4, pw0);\r
962         WtoMMultiString(lpBuffer, nBufferLength, pw0);\r
963         r = TerminateStringM(lpBuffer, nBufferLength);\r
964 END_ROUTINE\r
965         FreeDuplicatedString(pw0);\r
966         return r;\r
967 }\r
968 \r
969 ATOM RegisterClassExM(CONST WNDCLASSEXA * v0)\r
970 {\r
971         ATOM r = 0;\r
972         wchar_t* pw0 = NULL;\r
973         wchar_t* pw1 = NULL;\r
974         WNDCLASSEXW a0;\r
975 START_ROUTINE\r
976         a0.cbSize = sizeof(WNDCLASSEXW);\r
977         a0.style = v0->style;\r
978         a0.lpfnWndProc = v0->lpfnWndProc;\r
979         a0.cbClsExtra = v0->cbClsExtra;\r
980         a0.cbWndExtra = v0->cbWndExtra;\r
981         a0.hInstance = v0->hInstance;\r
982         a0.hIcon = v0->hIcon;\r
983         a0.hCursor = v0->hCursor;\r
984         a0.hbrBackground = v0->hbrBackground;\r
985         pw0 = DuplicateMtoW(v0->lpszMenuName, -1);\r
986         a0.lpszMenuName = pw0;\r
987         pw1 = DuplicateMtoW(v0->lpszClassName, -1);\r
988         a0.lpszClassName = pw1;\r
989         a0.hIconSm = v0->hIconSm;\r
990         r = RegisterClassExW(&a0);\r
991 END_ROUTINE\r
992         FreeDuplicatedString(pw0);\r
993         FreeDuplicatedString(pw1);\r
994         return r;\r
995 }\r
996 \r
997 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)\r
998 {\r
999         HWND r = NULL;\r
1000         wchar_t* pw0 = NULL;\r
1001         wchar_t* pw1 = NULL;\r
1002 START_ROUTINE\r
1003         pw0 = DuplicateMtoW(lpClassName, -1);\r
1004         pw1 = DuplicateMtoW(lpWindowName, -1);\r
1005         r = CreateWindowExW(dwExStyle, pw0, pw1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);\r
1006 END_ROUTINE\r
1007         FreeDuplicatedString(pw0);\r
1008         FreeDuplicatedString(pw1);\r
1009         return r;\r
1010 }\r
1011 \r
1012 LONG GetWindowLongM(HWND hWnd, int nIndex)\r
1013 {\r
1014         LONG r = 0;\r
1015 START_ROUTINE\r
1016         if(IsWindowUnicode(hWnd))\r
1017                 r = GetWindowLongW(hWnd, nIndex);\r
1018         else\r
1019                 r = GetWindowLongA(hWnd, nIndex);\r
1020 END_ROUTINE\r
1021         return r;\r
1022 }\r
1023 \r
1024 LONG SetWindowLongM(HWND hWnd, int nIndex, LONG dwNewLong)\r
1025 {\r
1026         LONG r = 0;\r
1027 START_ROUTINE\r
1028         if(IsWindowUnicode(hWnd))\r
1029                 r = SetWindowLongW(hWnd, nIndex, dwNewLong);\r
1030         else\r
1031                 r = SetWindowLongA(hWnd, nIndex, dwNewLong);\r
1032 END_ROUTINE\r
1033         return r;\r
1034 }\r
1035 \r
1036 LONG_PTR GetWindowLongPtrM(HWND hWnd, int nIndex)\r
1037 {\r
1038         LONG_PTR r = 0;\r
1039 START_ROUTINE\r
1040         if(IsWindowUnicode(hWnd))\r
1041                 r = GetWindowLongPtrW(hWnd, nIndex);\r
1042         else\r
1043                 r = GetWindowLongPtrA(hWnd, nIndex);\r
1044 END_ROUTINE\r
1045         return r;\r
1046 }\r
1047 \r
1048 LONG_PTR SetWindowLongPtrM(HWND hWnd, int nIndex, LONG_PTR dwNewLong)\r
1049 {\r
1050         LONG_PTR r = 0;\r
1051 START_ROUTINE\r
1052         if(IsWindowUnicode(hWnd))\r
1053                 r = SetWindowLongPtrW(hWnd, nIndex, dwNewLong);\r
1054         else\r
1055                 r = SetWindowLongPtrA(hWnd, nIndex, dwNewLong);\r
1056 END_ROUTINE\r
1057         return r;\r
1058 }\r
1059 \r
1060 LRESULT DefWindowProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)\r
1061 {\r
1062         LRESULT r = 0;\r
1063 START_ROUTINE\r
1064         if(IsWindowUnicode(hWnd))\r
1065                 r = DefWindowProcW(hWnd, Msg, wParam, lParam);\r
1066         else\r
1067                 r = DefWindowProcA(hWnd, Msg, wParam, lParam);\r
1068 END_ROUTINE\r
1069         return r;\r
1070 }\r
1071 \r
1072 LRESULT CallWindowProcM(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)\r
1073 {\r
1074         LRESULT r = 0;\r
1075 START_ROUTINE\r
1076         if(IsWindowUnicode(hWnd))\r
1077                 r = CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);\r
1078         else\r
1079                 r = CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);\r
1080 END_ROUTINE\r
1081         return r;\r
1082 }\r
1083 \r
1084 LRESULT SendMessageM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)\r
1085 {\r
1086         LRESULT r = 0;\r
1087         wchar_t* pw0 = NULL;\r
1088         wchar_t* pw1 = NULL;\r
1089         int Size;\r
1090         LVITEMA* pmLVItem;\r
1091         LVITEMW wLVItem;\r
1092         LVFINDINFOA* pmLVFindInfo;\r
1093         LVFINDINFOW wLVFindInfo;\r
1094         LVCOLUMNA* pmLVColumn;\r
1095         LVCOLUMNW wLVColumn;\r
1096         TVITEMEXA* pmTVItem;\r
1097         TVITEMEXW wTVItem;\r
1098         TVINSERTSTRUCTA* pmTVInsert;\r
1099         TVINSERTSTRUCTW wTVInsert;\r
1100         wchar_t ClassName[MAX_PATH];\r
1101 START_ROUTINE\r
1102         switch(Msg)\r
1103         {\r
1104         case WM_SETTEXT:\r
1105                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1106                 r = SendMessageW(hWnd, WM_SETTEXT, wParam, (LPARAM)pw0);\r
1107                 break;\r
1108         case WM_GETTEXT:\r
1109                 pw0 = AllocateStringW(wParam * 4);\r
1110                 SendMessageW(hWnd, WM_GETTEXT, wParam * 4, (LPARAM)pw0);\r
1111                 WtoM((LPSTR)lParam, wParam, pw0, -1);\r
1112                 r = TerminateStringM((LPSTR)lParam, wParam);\r
1113                 break;\r
1114         case WM_GETTEXTLENGTH:\r
1115                 Size = SendMessageW(hWnd, WM_GETTEXTLENGTH, wParam, lParam) + 1;\r
1116                 pw0 = AllocateStringW(Size);\r
1117                 SendMessageW(hWnd, WM_GETTEXT, (WPARAM)Size, (LPARAM)pw0);\r
1118                 r = WtoM(NULL, 0, pw0, -1) - 1;\r
1119                 break;\r
1120         default:\r
1121                 GetClassNameW(hWnd, ClassName, sizeof(ClassName) / sizeof(wchar_t));\r
1122                 if(_wcsicmp(ClassName, WC_EDITW) == 0)\r
1123                 {\r
1124                         switch(Msg)\r
1125                         {\r
1126                         case EM_REPLACESEL:\r
1127                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1128                                 r = SendMessageW(hWnd, EM_REPLACESEL, wParam, (LPARAM)pw0);\r
1129                                 break;\r
1130                         default:\r
1131                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1132                                 break;\r
1133                         }\r
1134                 }\r
1135                 else if(_wcsicmp(ClassName, WC_COMBOBOXW) == 0)\r
1136                 {\r
1137                         switch(Msg)\r
1138                         {\r
1139                         case CB_ADDSTRING:\r
1140                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1141                                 r = SendMessageW(hWnd, CB_ADDSTRING, wParam, (LPARAM)pw0);\r
1142                                 break;\r
1143                         case CB_GETLBTEXT:\r
1144                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;\r
1145                                 pw0 = AllocateStringW(Size);\r
1146                                 SendMessageW(hWnd, CB_GETLBTEXT, wParam, (LPARAM)pw0);\r
1147                                 // バッファ長不明のためオーバーランの可能性あり\r
1148                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);\r
1149                                 r = TerminateStringM((LPSTR)lParam, Size * 4);\r
1150                                 break;\r
1151                         case CB_GETLBTEXTLEN:\r
1152                                 Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;\r
1153                                 pw0 = AllocateStringW(Size);\r
1154                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);\r
1155                                 r = WtoM(NULL, 0, pw0, -1) - 1;\r
1156                                 break;\r
1157                         case CB_INSERTSTRING:\r
1158                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1159                                 r = SendMessageW(hWnd, CB_INSERTSTRING, wParam, (LPARAM)pw0);\r
1160                                 break;\r
1161                         case CB_FINDSTRINGEXACT:\r
1162                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1163                                 r = SendMessageW(hWnd, CB_FINDSTRINGEXACT, wParam, (LPARAM)pw0);\r
1164                                 break;\r
1165                         default:\r
1166                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1167                                 break;\r
1168                         }\r
1169                 }\r
1170                 else if(_wcsicmp(ClassName, WC_LISTBOXW) == 0)\r
1171                 {\r
1172                         switch(Msg)\r
1173                         {\r
1174                         case LB_ADDSTRING:\r
1175                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1176                                 r = SendMessageW(hWnd, LB_ADDSTRING, wParam, (LPARAM)pw0);\r
1177                                 break;\r
1178                         case LB_INSERTSTRING:\r
1179                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1180                                 r = SendMessageW(hWnd, LB_INSERTSTRING, wParam, (LPARAM)pw0);\r
1181                                 break;\r
1182                         case LB_GETTEXT:\r
1183                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;\r
1184                                 pw0 = AllocateStringW(Size);\r
1185                                 SendMessageW(hWnd, LB_GETTEXT, wParam, (LPARAM)pw0);\r
1186                                 // バッファ長不明のためオーバーランの可能性あり\r
1187                                 WtoM((LPSTR)lParam, Size * 4, pw0, -1);\r
1188                                 r = TerminateStringM((LPSTR)lParam, Size * 4);\r
1189                                 break;\r
1190                         case LB_GETTEXTLEN:\r
1191                                 Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;\r
1192                                 pw0 = AllocateStringW(Size);\r
1193                                 SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);\r
1194                                 r = WtoM(NULL, 0, pw0, -1) - 1;\r
1195                                 break;\r
1196                         default:\r
1197                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1198                                 break;\r
1199                         }\r
1200                 }\r
1201                 else if(_wcsicmp(ClassName, WC_LISTVIEWW) == 0)\r
1202                 {\r
1203                         switch(Msg)\r
1204                         {\r
1205                         case LVM_GETITEMA:\r
1206                                 pmLVItem = (LVITEMA*)lParam;\r
1207                                 wLVItem.mask = pmLVItem->mask;\r
1208                                 wLVItem.iItem = pmLVItem->iItem;\r
1209                                 wLVItem.iSubItem = pmLVItem->iSubItem;\r
1210                                 wLVItem.state = pmLVItem->state;\r
1211                                 wLVItem.stateMask = pmLVItem->stateMask;\r
1212                                 if(pmLVItem->mask & LVIF_TEXT)\r
1213                                 {\r
1214                                         Size = pmLVItem->cchTextMax * 4;\r
1215                                         pw0 = AllocateStringW(Size);\r
1216                                         wLVItem.pszText = pw0;\r
1217                                         wLVItem.cchTextMax = Size;\r
1218                                 }\r
1219                                 wLVItem.iImage = pmLVItem->iImage;\r
1220                                 wLVItem.lParam = pmLVItem->lParam;\r
1221                                 wLVItem.iIndent = pmLVItem->iIndent;\r
1222                                 r = SendMessageW(hWnd, LVM_GETITEMW, wParam, (LPARAM)&wLVItem);\r
1223                                 pmLVItem->mask = wLVItem.mask;\r
1224                                 pmLVItem->iItem = wLVItem.iItem;\r
1225                                 pmLVItem->iSubItem = wLVItem.iSubItem;\r
1226                                 pmLVItem->state = wLVItem.state;\r
1227                                 pmLVItem->stateMask = wLVItem.stateMask;\r
1228                                 if(pmLVItem->mask & LVIF_TEXT)\r
1229                                 {\r
1230                                         WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);\r
1231                                         TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);\r
1232                                 }\r
1233                                 pmLVItem->iImage = wLVItem.iImage;\r
1234                                 pmLVItem->lParam = wLVItem.lParam;\r
1235                                 pmLVItem->iIndent = wLVItem.iIndent;\r
1236                                 break;\r
1237                         case LVM_SETITEMA:\r
1238                                 pmLVItem = (LVITEMA*)lParam;\r
1239                                 wLVItem.mask = pmLVItem->mask;\r
1240                                 wLVItem.iItem = pmLVItem->iItem;\r
1241                                 wLVItem.iSubItem = pmLVItem->iSubItem;\r
1242                                 wLVItem.state = pmLVItem->state;\r
1243                                 wLVItem.stateMask = pmLVItem->stateMask;\r
1244                                 if(pmLVItem->mask & LVIF_TEXT)\r
1245                                 {\r
1246                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);\r
1247                                         wLVItem.pszText = pw0;\r
1248                                         // TODO: cchTextMaxの確認\r
1249                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;\r
1250                                 }\r
1251                                 wLVItem.iImage = pmLVItem->iImage;\r
1252                                 wLVItem.lParam = pmLVItem->lParam;\r
1253                                 wLVItem.iIndent = pmLVItem->iIndent;\r
1254                                 r = SendMessageW(hWnd, LVM_SETITEMW, wParam, (LPARAM)&wLVItem);\r
1255                                 break;\r
1256                         case LVM_INSERTITEMA:\r
1257                                 pmLVItem = (LVITEMA*)lParam;\r
1258                                 wLVItem.mask = pmLVItem->mask;\r
1259                                 wLVItem.iItem = pmLVItem->iItem;\r
1260                                 wLVItem.iSubItem = pmLVItem->iSubItem;\r
1261                                 wLVItem.state = pmLVItem->state;\r
1262                                 wLVItem.stateMask = pmLVItem->stateMask;\r
1263                                 if(pmLVItem->mask & LVIF_TEXT)\r
1264                                 {\r
1265                                         pw0 = DuplicateMtoW(pmLVItem->pszText, -1);\r
1266                                         wLVItem.pszText = pw0;\r
1267                                         // TODO: cchTextMaxの確認\r
1268                                         wLVItem.cchTextMax = pmLVItem->cchTextMax;\r
1269                                 }\r
1270                                 wLVItem.iImage = pmLVItem->iImage;\r
1271                                 wLVItem.lParam = pmLVItem->lParam;\r
1272                                 wLVItem.iIndent = pmLVItem->iIndent;\r
1273                                 r = SendMessageW(hWnd, LVM_INSERTITEMW, wParam, (LPARAM)&wLVItem);\r
1274                                 break;\r
1275                         case LVM_FINDITEMA:\r
1276                                 pmLVFindInfo = (LVFINDINFOA*)lParam;\r
1277                                 wLVFindInfo.flags = pmLVFindInfo->flags;\r
1278                                 if(pmLVFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL))\r
1279                                 {\r
1280                                         pw0 = DuplicateMtoW(pmLVFindInfo->psz, -1);\r
1281                                         wLVFindInfo.psz = pw0;\r
1282                                 }\r
1283                                 wLVFindInfo.lParam = pmLVFindInfo->lParam;\r
1284                                 wLVFindInfo.pt = pmLVFindInfo->pt;\r
1285                                 wLVFindInfo.vkDirection = pmLVFindInfo->vkDirection;\r
1286                                 r = SendMessageW(hWnd, LVM_FINDITEMW, wParam, (LPARAM)&wLVFindInfo);\r
1287                                 break;\r
1288                         case LVM_GETCOLUMNA:\r
1289                                 pmLVColumn = (LVCOLUMNA*)lParam;\r
1290                                 wLVColumn.mask = pmLVColumn->mask;\r
1291                                 wLVColumn.fmt = pmLVColumn->fmt;\r
1292                                 wLVColumn.cx = pmLVColumn->cx;\r
1293                                 Size = pmLVColumn->cchTextMax * 4;\r
1294                                 if(pmLVColumn->mask & LVCF_TEXT)\r
1295                                 {\r
1296                                         pw0 = AllocateStringW(Size);\r
1297                                         wLVColumn.pszText = pw0;\r
1298                                         wLVColumn.cchTextMax = Size;\r
1299                                 }\r
1300                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;\r
1301                                 wLVColumn.iImage = pmLVColumn->iImage;\r
1302                                 wLVColumn.iOrder = pmLVColumn->iOrder;\r
1303                                 r = SendMessageW(hWnd, LVM_GETCOLUMNW, wParam, (LPARAM)&wLVColumn);\r
1304                                 pmLVColumn->mask = wLVColumn.mask;\r
1305                                 pmLVColumn->fmt = wLVColumn.fmt;\r
1306                                 pmLVColumn->cx = wLVColumn.cx;\r
1307                                 if(pmLVColumn->mask & LVCF_TEXT)\r
1308                                 {\r
1309                                         WtoM(pmLVColumn->pszText, pmLVColumn->cchTextMax, wLVColumn.pszText, -1);\r
1310                                         TerminateStringM(pmLVColumn->pszText, pmLVColumn->cchTextMax);\r
1311                                 }\r
1312                                 pmLVColumn->iSubItem = wLVColumn.iSubItem;\r
1313                                 pmLVColumn->iImage = wLVColumn.iImage;\r
1314                                 pmLVColumn->iOrder = wLVColumn.iOrder;\r
1315                                 break;\r
1316                         case LVM_INSERTCOLUMNA:\r
1317                                 pmLVColumn = (LVCOLUMNA*)lParam;\r
1318                                 wLVColumn.mask = pmLVColumn->mask;\r
1319                                 wLVColumn.fmt = pmLVColumn->fmt;\r
1320                                 wLVColumn.cx = pmLVColumn->cx;\r
1321                                 if(pmLVColumn->mask & LVCF_TEXT)\r
1322                                 {\r
1323                                         pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);\r
1324                                         wLVColumn.pszText = pw0;\r
1325                                         // TODO: cchTextMaxの確認\r
1326                                         wLVColumn.cchTextMax = pmLVColumn->cchTextMax;\r
1327                                 }\r
1328                                 wLVColumn.iSubItem = pmLVColumn->iSubItem;\r
1329                                 wLVColumn.iImage = pmLVColumn->iImage;\r
1330                                 wLVColumn.iOrder = pmLVColumn->iOrder;\r
1331                                 r = SendMessageW(hWnd, LVM_INSERTCOLUMNW, wParam, (LPARAM)&wLVColumn);\r
1332                                 break;\r
1333                         case LVM_GETITEMTEXTA:\r
1334                                 pmLVItem = (LVITEMA*)lParam;\r
1335                                 wLVItem.mask = pmLVItem->mask;\r
1336                                 wLVItem.iItem = pmLVItem->iItem;\r
1337                                 wLVItem.iSubItem = pmLVItem->iSubItem;\r
1338                                 wLVItem.state = pmLVItem->state;\r
1339                                 wLVItem.stateMask = pmLVItem->stateMask;\r
1340                                 Size = pmLVItem->cchTextMax * 4;\r
1341                                 pw0 = AllocateStringW(Size);\r
1342                                 wLVItem.pszText = pw0;\r
1343                                 wLVItem.cchTextMax = Size;\r
1344                                 wLVItem.iImage = pmLVItem->iImage;\r
1345                                 wLVItem.lParam = pmLVItem->lParam;\r
1346                                 wLVItem.iIndent = pmLVItem->iIndent;\r
1347                                 r = SendMessageW(hWnd, LVM_GETITEMTEXTW, wParam, (LPARAM)&wLVItem);\r
1348                                 pmLVItem->mask = wLVItem.mask;\r
1349                                 pmLVItem->iItem = wLVItem.iItem;\r
1350                                 pmLVItem->iSubItem = wLVItem.iSubItem;\r
1351                                 pmLVItem->state = wLVItem.state;\r
1352                                 pmLVItem->stateMask = wLVItem.stateMask;\r
1353                                 WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);\r
1354                                 TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);\r
1355                                 pmLVItem->iImage = wLVItem.iImage;\r
1356                                 pmLVItem->lParam = wLVItem.lParam;\r
1357                                 pmLVItem->iIndent = wLVItem.iIndent;\r
1358                                 break;\r
1359                         default:\r
1360                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1361                                 break;\r
1362                         }\r
1363                 }\r
1364                 else if(_wcsicmp(ClassName, STATUSCLASSNAMEW) == 0)\r
1365                 {\r
1366                         switch(Msg)\r
1367                         {\r
1368                         case SB_SETTEXTA:\r
1369                                 pw0 = DuplicateMtoW((LPCSTR)lParam, -1);\r
1370                                 r = SendMessageW(hWnd, SB_SETTEXTW, wParam, (LPARAM)pw0);\r
1371                                 break;\r
1372                         default:\r
1373                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1374                                 break;\r
1375                         }\r
1376                 }\r
1377                 else if(_wcsicmp(ClassName, WC_TREEVIEWW) == 0)\r
1378                 {\r
1379                         switch(Msg)\r
1380                         {\r
1381                         case TVM_GETITEMA:\r
1382                                 pmTVItem = (TVITEMEXA*)lParam;\r
1383                                 wTVItem.mask = pmTVItem->mask;\r
1384                                 wTVItem.hItem = pmTVItem->hItem;\r
1385                                 wTVItem.state = pmTVItem->state;\r
1386                                 wTVItem.stateMask = pmTVItem->stateMask;\r
1387                                 if(pmTVItem->mask & TVIF_TEXT)\r
1388                                 {\r
1389                                         Size = pmTVItem->cchTextMax * 4;\r
1390                                         pw0 = AllocateStringW(Size);\r
1391                                         wTVItem.pszText = pw0;\r
1392                                         wTVItem.cchTextMax = Size;\r
1393                                 }\r
1394                                 wTVItem.iImage = pmTVItem->iImage;\r
1395                                 wTVItem.iSelectedImage = pmTVItem->iSelectedImage;\r
1396                                 wTVItem.cChildren = pmTVItem->cChildren;\r
1397                                 wTVItem.lParam = pmTVItem->lParam;\r
1398                                 wTVItem.iIntegral = pmTVItem->iIntegral;\r
1399 //                              wTVItem.uStateEx = pmTVItem->uStateEx;\r
1400 //                              wTVItem.hwnd = pmTVItem->hwnd;\r
1401 //                              wTVItem.iExpandedImage = pmTVItem->iExpandedImage;\r
1402 //                              wTVItem.iReserved = pmTVItem->iReserved;\r
1403                                 r = SendMessageW(hWnd, TVM_GETITEMW, wParam, (LPARAM)&wTVItem);\r
1404                                 pmTVItem->mask = wTVItem.mask;\r
1405                                 pmTVItem->hItem = wTVItem.hItem;\r
1406                                 pmTVItem->state = wTVItem.state;\r
1407                                 pmTVItem->stateMask = wTVItem.stateMask;\r
1408                                 if(pmTVItem->mask & TVIF_TEXT)\r
1409                                 {\r
1410                                         WtoM(pmTVItem->pszText, pmTVItem->cchTextMax, wTVItem.pszText, -1);\r
1411                                         TerminateStringM(pmTVItem->pszText, pmTVItem->cchTextMax);\r
1412                                 }\r
1413                                 pmTVItem->iImage = wTVItem.iImage;\r
1414                                 pmTVItem->iSelectedImage = wTVItem.iSelectedImage;\r
1415                                 pmTVItem->cChildren = wTVItem.cChildren;\r
1416                                 pmTVItem->lParam = wTVItem.lParam;\r
1417                                 pmTVItem->iIntegral = wTVItem.iIntegral;\r
1418 //                              pmTVItem->uStateEx = wTVItem.uStateEx;\r
1419 //                              pmTVItem->hwnd = wTVItem.hwnd;\r
1420 //                              pmTVItem->iExpandedImage = wTVItem.iExpandedImage;\r
1421 //                              pmTVItem->iReserved = wTVItem.iReserved;\r
1422                                 break;\r
1423                         case TVM_INSERTITEMA:\r
1424                                 pmTVInsert = (TVINSERTSTRUCTA*)lParam;\r
1425                                 wTVInsert.hParent = pmTVInsert->hParent;\r
1426                                 wTVInsert.hInsertAfter = pmTVInsert->hInsertAfter;\r
1427                                 wTVInsert.itemex.mask = pmTVInsert->itemex.mask;\r
1428                                 wTVInsert.itemex.hItem = pmTVInsert->itemex.hItem;\r
1429                                 wTVInsert.itemex.state = pmTVInsert->itemex.state;\r
1430                                 wTVInsert.itemex.stateMask = pmTVInsert->itemex.stateMask;\r
1431                                 if(pmTVInsert->itemex.mask & TVIF_TEXT)\r
1432                                 {\r
1433                                         pw0 = DuplicateMtoW(pmTVInsert->itemex.pszText, -1);\r
1434                                         wTVInsert.itemex.pszText = pw0;\r
1435                                         // TODO: cchTextMaxの確認\r
1436                                         wTVInsert.itemex.cchTextMax = pmTVInsert->itemex.cchTextMax;\r
1437                                 }\r
1438                                 wTVInsert.itemex.iImage = pmTVInsert->itemex.iImage;\r
1439                                 wTVInsert.itemex.iSelectedImage = pmTVInsert->itemex.iSelectedImage;\r
1440                                 wTVInsert.itemex.cChildren = pmTVInsert->itemex.cChildren;\r
1441                                 wTVInsert.itemex.lParam = pmTVInsert->itemex.lParam;\r
1442                                 wTVInsert.itemex.iIntegral = pmTVInsert->itemex.iIntegral;\r
1443 //                              wTVInsert.itemex.uStateEx = pmTVInsert->itemex.uStateEx;\r
1444 //                              wTVInsert.itemex.hwnd = pmTVInsert->itemex.hwnd;\r
1445 //                              wTVInsert.itemex.iExpandedImage = pmTVInsert->itemex.iExpandedImage;\r
1446 //                              wTVInsert.itemex.iReserved = pmTVInsert->itemex.iReserved;\r
1447                                 r = SendMessageW(hWnd, TVM_INSERTITEMW, wParam, (LPARAM)&wTVInsert);\r
1448                                 break;\r
1449                         default:\r
1450                                 r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1451                                 break;\r
1452                         }\r
1453                 }\r
1454                 else\r
1455                         r = SendMessageW(hWnd, Msg, wParam, lParam);\r
1456                 break;\r
1457         }\r
1458 END_ROUTINE\r
1459         FreeDuplicatedString(pw0);\r
1460         FreeDuplicatedString(pw1);\r
1461         return r;\r
1462 }\r
1463 \r
1464 LRESULT DefDlgProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)\r
1465 {\r
1466         LRESULT r = 0;\r
1467 START_ROUTINE\r
1468         // WNDPROCがShift_JIS用であるため\r
1469         if(IsWindowUnicode(hWnd))\r
1470                 r = DefDlgProcW(hWnd, Msg, wParam, lParam);\r
1471         else\r
1472                 r = DefDlgProcA(hWnd, Msg, wParam, lParam);\r
1473 END_ROUTINE\r
1474         return r;\r
1475 }\r
1476 \r
1477 LRESULT SendDlgItemMessageM(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam)\r
1478 {\r
1479         LRESULT r = 0;\r
1480 START_ROUTINE\r
1481         r = SendMessageM(GetDlgItem(hDlg, nIDDlgItem), Msg, wParam, lParam);\r
1482 END_ROUTINE\r
1483         return r;\r
1484 }\r
1485 \r
1486 BOOL SetWindowTextM(HWND hWnd, LPCSTR lpString)\r
1487 {\r
1488         BOOL r = FALSE;\r
1489         wchar_t* pw0 = NULL;\r
1490 START_ROUTINE\r
1491         pw0 = DuplicateMtoW(lpString, -1);\r
1492         r = SetWindowTextW(hWnd, pw0);\r
1493 END_ROUTINE\r
1494         FreeDuplicatedString(pw0);\r
1495         return r;\r
1496 }\r
1497 \r
1498 UINT DragQueryFileM(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch)\r
1499 {\r
1500         UINT r = 0;\r
1501         wchar_t* pw0 = NULL;\r
1502 START_ROUTINE\r
1503         if(iFile == (UINT)-1)\r
1504                 r = DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);\r
1505         else\r
1506         {\r
1507                 pw0 = AllocateStringW(cch * 4);\r
1508                 DragQueryFileW(hDrop, iFile, pw0, cch * 4);\r
1509                 WtoM(lpszFile, cch, pw0, -1);\r
1510                 r = TerminateStringM(lpszFile, cch);\r
1511         }\r
1512 END_ROUTINE\r
1513         FreeDuplicatedString(pw0);\r
1514         return r;\r
1515 }\r
1516 \r
1517 LPSTR GetCommandLineM()\r
1518 {\r
1519         LPSTR r = 0;\r
1520         static char* pm0 = NULL;\r
1521 START_ROUTINE\r
1522         if(!pm0)\r
1523                 pm0 = DuplicateWtoM(GetCommandLineW(), -1);\r
1524         r = pm0;\r
1525 END_ROUTINE\r
1526         return r;\r
1527 }\r
1528 \r
1529 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)\r
1530 {\r
1531         DWORD r = 0;\r
1532         wchar_t* pw0 = NULL;\r
1533 START_ROUTINE\r
1534         // TODO: バッファが不十分な場合に必要なサイズを返す\r
1535         pw0 = AllocateStringW(nBufferLength * 4);\r
1536         GetCurrentDirectoryW(nBufferLength * 4, pw0);\r
1537         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
1538         r = TerminateStringM(lpBuffer, nBufferLength);\r
1539 END_ROUTINE\r
1540         FreeDuplicatedString(pw0);\r
1541         return r;\r
1542 }\r
1543 \r
1544 BOOL SetCurrentDirectoryM(LPCSTR lpPathName)\r
1545 {\r
1546         BOOL r = FALSE;\r
1547         wchar_t* pw0 = NULL;\r
1548 START_ROUTINE\r
1549         pw0 = DuplicateMtoW(lpPathName, -1);\r
1550         r = SetCurrentDirectoryW(pw0);\r
1551 END_ROUTINE\r
1552         FreeDuplicatedString(pw0);\r
1553         return r;\r
1554 }\r
1555 \r
1556 DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)\r
1557 {\r
1558         DWORD r = 0;\r
1559         wchar_t* pw0 = NULL;\r
1560 START_ROUTINE\r
1561         pw0 = AllocateStringW(nBufferLength * 4);\r
1562         GetTempPathW(nBufferLength * 4, pw0);\r
1563         WtoM(lpBuffer, nBufferLength, pw0, -1);\r
1564         r = TerminateStringM(lpBuffer, nBufferLength);\r
1565 END_ROUTINE\r
1566         FreeDuplicatedString(pw0);\r
1567         return r;\r
1568 }\r
1569 \r
1570 DWORD GetFileAttributesM(LPCSTR lpFileName)\r
1571 {\r
1572         DWORD r = FALSE;\r
1573         wchar_t* pw0 = NULL;\r
1574 START_ROUTINE\r
1575         pw0 = DuplicateMtoW(lpFileName, -1);\r
1576         r = GetFileAttributesW(pw0);\r
1577 END_ROUTINE\r
1578         FreeDuplicatedString(pw0);\r
1579         return r;\r
1580 }\r
1581 \r
1582 DWORD GetModuleFileNameM(HMODULE hModule, LPCH lpFilename, DWORD nSize)\r
1583 {\r
1584         DWORD r = 0;\r
1585         wchar_t* pw0 = NULL;\r
1586 START_ROUTINE\r
1587         pw0 = AllocateStringW(nSize * 4);\r
1588         GetModuleFileNameW(hModule, pw0, nSize * 4);\r
1589         WtoM(lpFilename, nSize, pw0, -1);\r
1590         r = TerminateStringM(lpFilename, nSize);\r
1591 END_ROUTINE\r
1592         FreeDuplicatedString(pw0);\r
1593         return r;\r
1594 }\r
1595 \r
1596 LSTATUS RegOpenKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)\r
1597 {\r
1598         LSTATUS r = 0;\r
1599         wchar_t* pw0 = NULL;\r
1600 START_ROUTINE\r
1601         pw0 = DuplicateMtoW(lpSubKey, -1);\r
1602         r = RegOpenKeyExW(hKey, pw0, ulOptions, samDesired, phkResult);\r
1603 END_ROUTINE\r
1604         FreeDuplicatedString(pw0);\r
1605         return r;\r
1606 }\r
1607 \r
1608 LSTATUS RegCreateKeyExM(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)\r
1609 {\r
1610         LSTATUS r = 0;\r
1611         wchar_t* pw0 = NULL;\r
1612         wchar_t* pw1 = NULL;\r
1613 START_ROUTINE\r
1614         pw0 = DuplicateMtoW(lpSubKey, -1);\r
1615         pw1 = DuplicateMtoW(lpClass, -1);\r
1616         r = RegCreateKeyExW(hKey, pw0, Reserved, pw1, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);\r
1617 END_ROUTINE\r
1618         FreeDuplicatedString(pw0);\r
1619         FreeDuplicatedString(pw1);\r
1620         return r;\r
1621 }\r
1622 \r
1623 LSTATUS RegDeleteValueM(HKEY hKey, LPCSTR lpValueName)\r
1624 {\r
1625         LSTATUS r = 0;\r
1626         wchar_t* pw0 = NULL;\r
1627 START_ROUTINE\r
1628         pw0 = DuplicateMtoW(lpValueName, -1);\r
1629         r = RegDeleteValueW(hKey, pw0);\r
1630 END_ROUTINE\r
1631         FreeDuplicatedString(pw0);\r
1632         return r;\r
1633 }\r
1634 \r
1635 LSTATUS RegQueryValueExM(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)\r
1636 {\r
1637         LSTATUS r = 0;\r
1638         wchar_t* pw0 = NULL;\r
1639         wchar_t* pw1 = NULL;\r
1640         DWORD dwType;\r
1641         DWORD wcbData;\r
1642 START_ROUTINE\r
1643         pw0 = DuplicateMtoW(lpValueName, -1);\r
1644         if(RegQueryValueExW(hKey, pw0, NULL, &dwType, NULL, 0) == ERROR_SUCCESS)\r
1645         {\r
1646                 switch(dwType)\r
1647                 {\r
1648                 case REG_SZ:\r
1649                 case REG_EXPAND_SZ:\r
1650                 case REG_MULTI_SZ:\r
1651                         if(lpcbData)\r
1652                         {\r
1653                                 pw1 = AllocateStringW(*lpcbData / sizeof(char) * 4);\r
1654                                 wcbData = *lpcbData / sizeof(char) * 4;\r
1655                                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, (LPBYTE)pw1, &wcbData);\r
1656                                 if(lpData)\r
1657                                         *lpcbData = sizeof(char) * WtoM((char*)lpData, *lpcbData / sizeof(char), pw1, wcbData / sizeof(wchar_t));\r
1658                                 else\r
1659                                         *lpcbData = sizeof(char) * WtoM(NULL, 0, pw1, wcbData / sizeof(wchar_t));\r
1660                         }\r
1661                         break;\r
1662                 default:\r
1663                         r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);\r
1664                         break;\r
1665                 }\r
1666         }\r
1667         else\r
1668                 r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);\r
1669 END_ROUTINE\r
1670         FreeDuplicatedString(pw0);\r
1671         FreeDuplicatedString(pw1);\r
1672         return r;\r
1673 }\r
1674 \r
1675 LSTATUS RegSetValueExM(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData)\r
1676 {\r
1677         LSTATUS r = 0;\r
1678         wchar_t* pw0 = NULL;\r
1679         wchar_t* pw1 = NULL;\r
1680         DWORD wcbData;\r
1681 START_ROUTINE\r
1682         pw0 = DuplicateMtoW(lpValueName, -1);\r
1683         switch(dwType)\r
1684         {\r
1685         case REG_SZ:\r
1686         case REG_EXPAND_SZ:\r
1687         case REG_MULTI_SZ:\r
1688                 wcbData = MtoW(NULL, 0, (char*)lpData, cbData / sizeof(char));\r
1689                 pw1 = AllocateStringW(wcbData);\r
1690                 MtoW(pw1, wcbData, (char*)lpData, cbData / sizeof(char));\r
1691                 wcbData = sizeof(wchar_t) * wcbData;\r
1692                 lpData = (BYTE*)pw1;\r
1693                 cbData = wcbData;\r
1694                 break;\r
1695         }\r
1696         r = RegSetValueExW(hKey, pw0, Reserved, dwType, lpData, cbData);\r
1697 END_ROUTINE\r
1698         FreeDuplicatedString(pw0);\r
1699         FreeDuplicatedString(pw1);\r
1700         return r;\r
1701 }\r
1702 \r
1703 BOOL TextOutM(HDC hdc, int x, int y, LPCSTR lpString, int c)\r
1704 {\r
1705         BOOL r = FALSE;\r
1706         wchar_t* pw0 = NULL;\r
1707 START_ROUTINE\r
1708         pw0 = DuplicateMtoW(lpString, c);\r
1709         r = TextOutW(hdc, x, y, pw0, wcslen(pw0));\r
1710 END_ROUTINE\r
1711         FreeDuplicatedString(pw0);\r
1712         return r;\r
1713 }\r
1714 \r
1715 BOOL GetTextExtentPoint32M(HDC hdc, LPCSTR lpString, int c, LPSIZE psizl)\r
1716 {\r
1717         BOOL r = FALSE;\r
1718         wchar_t* pw0 = NULL;\r
1719 START_ROUTINE\r
1720         pw0 = DuplicateMtoW(lpString, c);\r
1721         r = GetTextExtentPoint32W(hdc, pw0, wcslen(pw0), psizl);\r
1722 END_ROUTINE\r
1723         FreeDuplicatedString(pw0);\r
1724         return r;\r
1725 }\r
1726 \r
1727 INT_PTR PropertySheetM(LPCPROPSHEETHEADERA v0)\r
1728 {\r
1729         INT_PTR r = 0;\r
1730         PROPSHEETHEADERW a0;\r
1731         PROPSHEETPAGEW* pwPage;\r
1732         UINT i;\r
1733 START_ROUTINE\r
1734         a0.dwSize = sizeof(PROPSHEETHEADERW);\r
1735         a0.dwFlags = v0->dwFlags;\r
1736         a0.hwndParent = v0->hwndParent;\r
1737         a0.hInstance = v0->hInstance;\r
1738         if(v0->dwFlags & PSH_USEICONID)\r
1739                 a0.pszIcon = DuplicateMtoW(v0->pszIcon, -1);\r
1740         else\r
1741                 a0.hIcon = v0->hIcon;\r
1742         a0.pszCaption = DuplicateMtoW(v0->pszCaption, -1);\r
1743         a0.nPages = v0->nPages;\r
1744         if(v0->dwFlags & PSH_USEPSTARTPAGE)\r
1745                 a0.pStartPage = DuplicateMtoW(v0->pStartPage, -1);\r
1746         else\r
1747                 a0.nStartPage = v0->nStartPage;\r
1748         if(v0->dwFlags & PSH_PROPSHEETPAGE)\r
1749         {\r
1750                 if(v0->ppsp && (pwPage = (PROPSHEETPAGEW*)malloc(sizeof(PROPSHEETPAGEW) * v0->nPages)))\r
1751                 {\r
1752                         for(i = 0; i < v0->nPages; i++)\r
1753                         {\r
1754                                 pwPage[i].dwSize = sizeof(PROPSHEETPAGEW);\r
1755                                 pwPage[i].dwFlags = v0->ppsp[i].dwFlags;\r
1756                                 pwPage[i].hInstance = v0->ppsp[i].hInstance;\r
1757                                 if(v0->ppsp[i].dwFlags & PSP_DLGINDIRECT)\r
1758                                         pwPage[i].pResource = v0->ppsp[i].pResource;\r
1759                                 else\r
1760                                         pwPage[i].pszTemplate = DuplicateMtoW(v0->ppsp[i].pszTemplate, -1);\r
1761                                 if(v0->ppsp[i].dwFlags & PSP_USEICONID)\r
1762                                         pwPage[i].pszIcon = DuplicateMtoW(v0->ppsp[i].pszIcon, -1);\r
1763                                 else\r
1764                                         pwPage[i].hIcon = v0->ppsp[i].hIcon;\r
1765                                 if(v0->ppsp[i].dwFlags & PSP_USETITLE)\r
1766                                         pwPage[i].pszTitle = DuplicateMtoW(v0->ppsp[i].pszTitle, -1);\r
1767                                 pwPage[i].pfnDlgProc = v0->ppsp[i].pfnDlgProc;\r
1768                                 pwPage[i].lParam = v0->ppsp[i].lParam;\r
1769                                 // TODO: pfnCallback\r
1770                                 pwPage[i].pfnCallback = (LPFNPSPCALLBACKW)v0->ppsp[i].pfnCallback;\r
1771                                 pwPage[i].pcRefParent = v0->ppsp[i].pcRefParent;\r
1772                                 if(v0->ppsp[i].dwFlags & PSP_USEHEADERTITLE)\r
1773                                         pwPage[i].pszHeaderTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderTitle, -1);\r
1774                                 if(v0->ppsp[i].dwFlags & PSP_USEHEADERSUBTITLE)\r
1775                                         pwPage[i].pszHeaderSubTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderSubTitle, -1);\r
1776                         }\r
1777                 }\r
1778                 else\r
1779                         pwPage = NULL;\r
1780                 a0.ppsp = pwPage;\r
1781         }\r
1782         else\r
1783                 a0.phpage = v0->phpage;\r
1784         a0.pfnCallback = v0->pfnCallback;\r
1785         if(v0->dwFlags & PSH_USEHBMWATERMARK)\r
1786                 a0.hbmWatermark = v0->hbmWatermark;\r
1787         else\r
1788                 a0.pszbmWatermark = DuplicateMtoW(v0->pszbmWatermark, -1);\r
1789         r = PropertySheetW(&a0);\r
1790         if(a0.dwFlags & PSH_USEICONID)\r
1791                 FreeDuplicatedString((void*)a0.pszIcon);\r
1792         FreeDuplicatedString((void*)a0.pszCaption);\r
1793         if(v0->dwFlags & PSH_USEPSTARTPAGE)\r
1794                 FreeDuplicatedString((void*)a0.pStartPage);\r
1795         if(v0->dwFlags & PSH_PROPSHEETPAGE)\r
1796         {\r
1797                 if(pwPage)\r
1798                 {\r
1799                         for(i = 0; i < v0->nPages; i++)\r
1800                         {\r
1801                                 if(!(v0->ppsp[i].dwFlags & PSP_DLGINDIRECT))\r
1802                                         FreeDuplicatedString((void*)pwPage[i].pszTemplate);\r
1803                                 if(v0->ppsp[i].dwFlags & PSP_USEICONID)\r
1804                                         FreeDuplicatedString((void*)pwPage[i].pszIcon);\r
1805                                 if(v0->ppsp[i].dwFlags & PSP_USETITLE)\r
1806                                         FreeDuplicatedString((void*)pwPage[i].pszTitle);\r
1807                                 if(v0->ppsp[i].dwFlags & PSP_USEHEADERTITLE)\r
1808                                         FreeDuplicatedString((void*)pwPage[i].pszHeaderTitle);\r
1809                                 if(v0->ppsp[i].dwFlags & PSP_USEHEADERSUBTITLE)\r
1810                                         FreeDuplicatedString((void*)pwPage[i].pszHeaderSubTitle);\r
1811                         }\r
1812                         free(pwPage);\r
1813                 }\r
1814         }\r
1815         if(!(v0->dwFlags & PSH_USEHBMWATERMARK))\r
1816                 FreeDuplicatedString((void*)a0.pszbmWatermark);\r
1817 END_ROUTINE\r
1818         return r;\r
1819 }\r
1820 \r
1821 BOOL GetOpenFileNameM(LPOPENFILENAMEA v0)\r
1822 {\r
1823         BOOL r = FALSE;\r
1824         wchar_t* pw0 = NULL;\r
1825         wchar_t* pw1 = NULL;\r
1826         wchar_t* pw2 = NULL;\r
1827         wchar_t* pw3 = NULL;\r
1828         wchar_t* pw4 = NULL;\r
1829         wchar_t* pw5 = NULL;\r
1830         wchar_t* pw6 = NULL;\r
1831         wchar_t* pw7 = NULL;\r
1832         wchar_t* pw8 = NULL;\r
1833         wchar_t* pw9 = NULL;\r
1834         OPENFILENAMEW wofn;\r
1835 START_ROUTINE\r
1836         wofn.lStructSize = sizeof(OPENFILENAMEW);\r
1837         wofn.hwndOwner = v0->hwndOwner;\r
1838         wofn.hInstance = v0->hInstance;\r
1839         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);\r
1840         wofn.lpstrFilter = pw0;\r
1841         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);\r
1842         wofn.lpstrCustomFilter = pw1;\r
1843         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;\r
1844         wofn.nFilterIndex = v0->nFilterIndex;\r
1845         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);\r
1846         wofn.lpstrFile = pw2;\r
1847         wofn.nMaxFile = v0->nMaxFile * 4;\r
1848         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);\r
1849         wofn.lpstrFileTitle = pw3;\r
1850         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;\r
1851         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);\r
1852         wofn.lpstrInitialDir = pw4;\r
1853         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);\r
1854         wofn.lpstrTitle = pw5;\r
1855         wofn.Flags = v0->Flags;\r
1856         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);\r
1857         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);\r
1858         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);\r
1859         wofn.lpstrDefExt = pw6;\r
1860         wofn.lCustData = v0->lCustData;\r
1861         wofn.lpfnHook = v0->lpfnHook;\r
1862         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);\r
1863         wofn.pvReserved = v0->pvReserved;\r
1864         wofn.FlagsEx = v0->FlagsEx;\r
1865         r = GetOpenFileNameW(&wofn);\r
1866         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);\r
1867         TerminateStringM(v0->lpstrFile, v0->nMaxFile);\r
1868         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);\r
1869         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);\r
1870 END_ROUTINE\r
1871         FreeDuplicatedString(pw0);\r
1872         FreeDuplicatedString(pw1);\r
1873         FreeDuplicatedString(pw2);\r
1874         FreeDuplicatedString(pw3);\r
1875         FreeDuplicatedString(pw4);\r
1876         FreeDuplicatedString(pw5);\r
1877         FreeDuplicatedString(pw6);\r
1878         return r;\r
1879 }\r
1880 \r
1881 BOOL GetSaveFileNameM(LPOPENFILENAMEA v0)\r
1882 {\r
1883         BOOL r = FALSE;\r
1884         wchar_t* pw0 = NULL;\r
1885         wchar_t* pw1 = NULL;\r
1886         wchar_t* pw2 = NULL;\r
1887         wchar_t* pw3 = NULL;\r
1888         wchar_t* pw4 = NULL;\r
1889         wchar_t* pw5 = NULL;\r
1890         wchar_t* pw6 = NULL;\r
1891         wchar_t* pw7 = NULL;\r
1892         wchar_t* pw8 = NULL;\r
1893         wchar_t* pw9 = NULL;\r
1894         OPENFILENAMEW wofn;\r
1895 START_ROUTINE\r
1896         wofn.lStructSize = sizeof(OPENFILENAMEW);\r
1897         wofn.hwndOwner = v0->hwndOwner;\r
1898         wofn.hInstance = v0->hInstance;\r
1899         pw0 = DuplicateMtoWMultiString(v0->lpstrFilter);\r
1900         wofn.lpstrFilter = pw0;\r
1901         pw1 = DuplicateMtoWBuffer(v0->lpstrCustomFilter, -1, v0->nMaxCustFilter * 4);\r
1902         wofn.lpstrCustomFilter = pw1;\r
1903         wofn.nMaxCustFilter = v0->nMaxCustFilter * 4;\r
1904         wofn.nFilterIndex = v0->nFilterIndex;\r
1905         pw2 = DuplicateMtoWMultiStringBuffer(v0->lpstrFile, v0->nMaxFile * 4);\r
1906         wofn.lpstrFile = pw2;\r
1907         wofn.nMaxFile = v0->nMaxFile * 4;\r
1908         pw3 = DuplicateMtoWBuffer(v0->lpstrFileTitle, -1, v0->nMaxFileTitle * 4);\r
1909         wofn.lpstrFileTitle = pw3;\r
1910         wofn.nMaxFileTitle = v0->nMaxFileTitle * 4;\r
1911         pw4 = DuplicateMtoW(v0->lpstrInitialDir, -1);\r
1912         wofn.lpstrInitialDir = pw4;\r
1913         pw5 = DuplicateMtoW(v0->lpstrTitle, -1);\r
1914         wofn.lpstrTitle = pw5;\r
1915         wofn.Flags = v0->Flags;\r
1916         wofn.nFileOffset = MtoW(NULL, 0, v0->lpstrFile, v0->nFileOffset);\r
1917         wofn.nFileExtension = MtoW(NULL, 0, v0->lpstrFile, v0->nFileExtension);\r
1918         pw6 = DuplicateMtoW(v0->lpstrDefExt, -1);\r
1919         wofn.lpstrDefExt = pw6;\r
1920         wofn.lCustData = v0->lCustData;\r
1921         wofn.lpfnHook = v0->lpfnHook;\r
1922         wofn.lpTemplateName = DuplicateMtoW(v0->lpTemplateName, -1);\r
1923         wofn.pvReserved = v0->pvReserved;\r
1924         wofn.FlagsEx = v0->FlagsEx;\r
1925         r = GetSaveFileNameW(&wofn);\r
1926         WtoM(v0->lpstrFile, v0->nMaxFile, wofn.lpstrFile, -1);\r
1927         TerminateStringM(v0->lpstrFile, v0->nMaxFile);\r
1928         v0->nFileOffset = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileOffset);\r
1929         v0->nFileExtension = WtoM(NULL, 0, wofn.lpstrFile, wofn.nFileExtension);\r
1930 END_ROUTINE\r
1931         FreeDuplicatedString(pw0);\r
1932         FreeDuplicatedString(pw1);\r
1933         FreeDuplicatedString(pw2);\r
1934         FreeDuplicatedString(pw3);\r
1935         FreeDuplicatedString(pw4);\r
1936         FreeDuplicatedString(pw5);\r
1937         FreeDuplicatedString(pw6);\r
1938         return r;\r
1939 }\r
1940 \r
1941 HWND HtmlHelpM(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)\r
1942 {\r
1943         HWND r = NULL;\r
1944         wchar_t* pw0 = NULL;\r
1945 START_ROUTINE\r
1946         pw0 = DuplicateMtoW(pszFile, -1);\r
1947         r = HtmlHelpW(hwndCaller, pw0, uCommand, dwData);\r
1948 END_ROUTINE\r
1949         FreeDuplicatedString(pw0);\r
1950         return r;\r
1951 }\r
1952 \r
1953 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)\r
1954 {\r
1955         BOOL r = FALSE;\r
1956         wchar_t* pw0 = NULL;\r
1957         wchar_t* pw1 = NULL;\r
1958         wchar_t* pw2 = NULL;\r
1959         wchar_t* pw3 = NULL;\r
1960         wchar_t* pw4 = NULL;\r
1961         wchar_t* pw5 = NULL;\r
1962         STARTUPINFOW wStartupInfo;\r
1963 START_ROUTINE\r
1964         pw0 = DuplicateMtoW(lpApplicationName, -1);\r
1965         pw1 = DuplicateMtoWBuffer(lpCommandLine, -1, (strlen(lpCommandLine) + 1) * 4);\r
1966         pw2 = DuplicateMtoW(lpCurrentDirectory, -1);\r
1967         wStartupInfo.cb = sizeof(LPSTARTUPINFOW);\r
1968         pw3 = DuplicateMtoW(lpStartupInfo->lpReserved, -1);\r
1969         wStartupInfo.lpReserved = pw3;\r
1970         pw4 = DuplicateMtoW(lpStartupInfo->lpDesktop, -1);\r
1971         wStartupInfo.lpDesktop = pw4;\r
1972         pw5 = DuplicateMtoW(lpStartupInfo->lpTitle, -1);\r
1973         wStartupInfo.lpTitle = pw5;\r
1974         wStartupInfo.dwX = lpStartupInfo->dwX;\r
1975         wStartupInfo.dwY = lpStartupInfo->dwY;\r
1976         wStartupInfo.dwXSize = lpStartupInfo->dwXSize;\r
1977         wStartupInfo.dwYSize = lpStartupInfo->dwYSize;\r
1978         wStartupInfo.dwXCountChars = lpStartupInfo->dwXCountChars;\r
1979         wStartupInfo.dwYCountChars = lpStartupInfo->dwYCountChars;\r
1980         wStartupInfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;\r
1981         wStartupInfo.dwFlags = lpStartupInfo->dwFlags;\r
1982         wStartupInfo.wShowWindow = lpStartupInfo->wShowWindow;\r
1983         wStartupInfo.cbReserved2 = lpStartupInfo->cbReserved2;\r
1984         wStartupInfo.lpReserved2 = lpStartupInfo->lpReserved2;\r
1985         wStartupInfo.hStdInput = lpStartupInfo->hStdInput;\r
1986         wStartupInfo.hStdOutput = lpStartupInfo->hStdOutput;\r
1987         wStartupInfo.hStdError = lpStartupInfo->hStdError;\r
1988         r = CreateProcessW(pw0, pw1, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, pw2, &wStartupInfo, lpProcessInformation);\r
1989         WtoM(lpCommandLine, strlen(lpCommandLine) + 1, pw1, -1);\r
1990 END_ROUTINE\r
1991         FreeDuplicatedString(pw0);\r
1992         FreeDuplicatedString(pw1);\r
1993         FreeDuplicatedString(pw2);\r
1994         FreeDuplicatedString(pw3);\r
1995         FreeDuplicatedString(pw4);\r
1996         FreeDuplicatedString(pw5);\r
1997         return r;\r
1998 }\r
1999 \r
2000 HINSTANCE FindExecutableM(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)\r
2001 {\r
2002         HINSTANCE r = NULL;\r
2003         wchar_t* pw0 = NULL;\r
2004         wchar_t* pw1 = NULL;\r
2005         wchar_t* pw2 = NULL;\r
2006         wchar_t* pw3 = NULL;\r
2007 START_ROUTINE\r
2008         pw0 = DuplicateMtoW(lpFile, -1);\r
2009         pw1 = DuplicateMtoW(lpDirectory, -1);\r
2010         pw2 = AllocateStringW(MAX_PATH * 4);\r
2011         r = FindExecutableW(pw0, pw1, pw2);\r
2012         // バッファ長不明のためオーバーランの可能性あり\r
2013         WtoM(lpResult, MAX_PATH, pw2, -1);\r
2014         TerminateStringM(lpResult, MAX_PATH);\r
2015 END_ROUTINE\r
2016         FreeDuplicatedString(pw0);\r
2017         FreeDuplicatedString(pw1);\r
2018         FreeDuplicatedString(pw2);\r
2019         FreeDuplicatedString(pw3);\r
2020         return r;\r
2021 }\r
2022 \r
2023 HINSTANCE ShellExecuteM(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)\r
2024 {\r
2025         HINSTANCE r = NULL;\r
2026         wchar_t* pw0 = NULL;\r
2027         wchar_t* pw1 = NULL;\r
2028         wchar_t* pw2 = NULL;\r
2029         wchar_t* pw3 = NULL;\r
2030 START_ROUTINE\r
2031         pw0 = DuplicateMtoW(lpOperation, -1);\r
2032         pw1 = DuplicateMtoW(lpFile, -1);\r
2033         pw2 = DuplicateMtoW(lpParameters, -1);\r
2034         pw3 = DuplicateMtoW(lpDirectory, -1);\r
2035         r = ShellExecuteW(hwnd, pw0, pw1, pw2, pw3, nShowCmd);\r
2036 END_ROUTINE\r
2037         FreeDuplicatedString(pw0);\r
2038         FreeDuplicatedString(pw1);\r
2039         FreeDuplicatedString(pw2);\r
2040         FreeDuplicatedString(pw3);\r
2041         return r;\r
2042 }\r
2043 \r
2044 BOOL ShellExecuteExM(LPSHELLEXECUTEINFOA lpExecInfo)\r
2045 {\r
2046         BOOL r = FALSE;\r
2047         wchar_t* pw0 = NULL;\r
2048         wchar_t* pw1 = NULL;\r
2049         wchar_t* pw2 = NULL;\r
2050         wchar_t* pw3 = NULL;\r
2051         wchar_t* pw4 = NULL;\r
2052         SHELLEXECUTEINFOW wExecInfo;\r
2053 START_ROUTINE\r
2054         wExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);\r
2055         wExecInfo.fMask = lpExecInfo->fMask;\r
2056         wExecInfo.hwnd = lpExecInfo->hwnd;\r
2057         pw0 = DuplicateMtoW(lpExecInfo->lpVerb, -1);\r
2058         wExecInfo.lpVerb = pw0;\r
2059         pw1 = DuplicateMtoW(lpExecInfo->lpFile, -1);\r
2060         wExecInfo.lpFile = pw1;\r
2061         pw2 = DuplicateMtoW(lpExecInfo->lpParameters, -1);\r
2062         wExecInfo.lpParameters = pw2;\r
2063         pw3 = DuplicateMtoW(lpExecInfo->lpDirectory, -1);\r
2064         wExecInfo.lpDirectory = pw3;\r
2065         wExecInfo.nShow = lpExecInfo->nShow;\r
2066         wExecInfo.hInstApp = lpExecInfo->hInstApp;\r
2067         wExecInfo.lpIDList = lpExecInfo->lpIDList;\r
2068         if(lpExecInfo->fMask & SEE_MASK_CLASSNAME)\r
2069         {\r
2070                 pw4 = DuplicateMtoW(lpExecInfo->lpClass, -1);\r
2071                 wExecInfo.lpClass = pw4;\r
2072         }\r
2073         wExecInfo.hkeyClass = lpExecInfo->hkeyClass;\r
2074         wExecInfo.dwHotKey = lpExecInfo->dwHotKey;\r
2075         wExecInfo.hIcon = lpExecInfo->hIcon;\r
2076         wExecInfo.hProcess = lpExecInfo->hProcess;\r
2077         r = ShellExecuteExW(&wExecInfo);\r
2078         lpExecInfo->hInstApp = wExecInfo.hInstApp;\r
2079         lpExecInfo->hProcess = wExecInfo.hProcess;\r
2080 END_ROUTINE\r
2081         FreeDuplicatedString(pw0);\r
2082         FreeDuplicatedString(pw1);\r
2083         FreeDuplicatedString(pw2);\r
2084         FreeDuplicatedString(pw3);\r
2085         FreeDuplicatedString(pw4);\r
2086         return r;\r
2087 }\r
2088 \r
2089 PIDLIST_ABSOLUTE SHBrowseForFolderM(LPBROWSEINFOA lpbi)\r
2090 {\r
2091         PIDLIST_ABSOLUTE r = NULL;\r
2092         wchar_t* pw0 = NULL;\r
2093         wchar_t* pw1 = NULL;\r
2094         BROWSEINFOW wbi;\r
2095 START_ROUTINE\r
2096         wbi.hwndOwner = lpbi->hwndOwner;\r
2097         wbi.pidlRoot = lpbi->pidlRoot;\r
2098         pw0 = DuplicateMtoWBuffer(lpbi->pszDisplayName, -1, MAX_PATH * 4);\r
2099         wbi.pszDisplayName = pw0;\r
2100         pw1 = DuplicateMtoW(lpbi->lpszTitle, -1);\r
2101         wbi.lpszTitle = pw1;\r
2102         wbi.ulFlags = lpbi->ulFlags;\r
2103         // TODO: lpfn\r
2104         wbi.lpfn = lpbi->lpfn;\r
2105         wbi.lParam = lpbi->lParam;\r
2106         wbi.iImage = lpbi->iImage;\r
2107         r = SHBrowseForFolderW(&wbi);\r
2108         // バッファ長不明のためオーバーランの可能性あり\r
2109         WtoM(lpbi->pszDisplayName, MAX_PATH, wbi.pszDisplayName, -1);\r
2110         lpbi->iImage = wbi.iImage;\r
2111 END_ROUTINE\r
2112         FreeDuplicatedString(pw0);\r
2113         FreeDuplicatedString(pw1);\r
2114         return r;\r
2115 }\r
2116 \r
2117 BOOL SHGetPathFromIDListM(PCIDLIST_ABSOLUTE pidl, LPSTR pszPath)\r
2118 {\r
2119         BOOL r = FALSE;\r
2120         wchar_t* pw0 = NULL;\r
2121 START_ROUTINE\r
2122         pw0 = AllocateStringW(MAX_PATH * 4);\r
2123         r = SHGetPathFromIDListW(pidl, pw0);\r
2124         // バッファ長不明のためオーバーランの可能性あり\r
2125         WtoM(pszPath, MAX_PATH, pw0, -1);\r
2126         TerminateStringM(pszPath, MAX_PATH);\r
2127 END_ROUTINE\r
2128         FreeDuplicatedString(pw0);\r
2129         return r;\r
2130 }\r
2131 \r
2132 int SHFileOperationM(LPSHFILEOPSTRUCTA lpFileOp)\r
2133 {\r
2134         int r = 0;\r
2135         wchar_t* pw0 = NULL;\r
2136         wchar_t* pw1 = NULL;\r
2137         wchar_t* pw2 = NULL;\r
2138         SHFILEOPSTRUCTW wFileOp;\r
2139 START_ROUTINE\r
2140         wFileOp.hwnd = lpFileOp->hwnd;\r
2141         wFileOp.wFunc = lpFileOp->wFunc;\r
2142         pw0 = DuplicateMtoWMultiString(lpFileOp->pFrom);\r
2143         wFileOp.pFrom = pw0;\r
2144         pw1 = DuplicateMtoWMultiString(lpFileOp->pTo);\r
2145         wFileOp.pTo = pw1;\r
2146         wFileOp.fFlags = lpFileOp->fFlags;\r
2147         wFileOp.fAnyOperationsAborted = lpFileOp->fAnyOperationsAborted;\r
2148         wFileOp.hNameMappings = lpFileOp->hNameMappings;\r
2149         if(lpFileOp->fFlags & FOF_SIMPLEPROGRESS)\r
2150                 pw2 = DuplicateMtoW(lpFileOp->lpszProgressTitle, -1);\r
2151         r = SHFileOperationW(&wFileOp);\r
2152         lpFileOp->fAnyOperationsAborted = wFileOp.fAnyOperationsAborted;\r
2153 END_ROUTINE\r
2154         FreeDuplicatedString(pw0);\r
2155         FreeDuplicatedString(pw1);\r
2156         FreeDuplicatedString(pw2);\r
2157         return r;\r
2158 }\r
2159 \r
2160 DWORD_PTR SHGetFileInfoM(LPCSTR pszPath, DWORD dwFileAttributes, SHFILEINFOA *psfi, UINT cbFileInfo, UINT uFlags)\r
2161 {\r
2162         DWORD_PTR r = 0;\r
2163         wchar_t* pw0 = NULL;\r
2164         SHFILEINFOW wsfi;\r
2165 START_ROUTINE\r
2166         pw0 = DuplicateMtoWMultiString(pszPath);\r
2167         if((r = SHGetFileInfoW(pw0, dwFileAttributes, &wsfi, cbFileInfo, uFlags)) != 0)\r
2168         {\r
2169                 psfi->hIcon = wsfi.hIcon;\r
2170                 psfi->iIcon = wsfi.iIcon;\r
2171                 psfi->dwAttributes = wsfi.dwAttributes;\r
2172                 WtoM(psfi->szDisplayName, MAX_PATH, wsfi.szDisplayName, -1);\r
2173                 WtoM(psfi->szTypeName, 80, wsfi.szTypeName, -1);\r
2174         }\r
2175 END_ROUTINE\r
2176         FreeDuplicatedString(pw0);\r
2177         return r;\r
2178 }\r
2179 \r
2180 BOOL AppendMenuM(HMENU hMenu, UINT uFlags, UINT_PTR uIDNewItem, LPCSTR lpNewItem)\r
2181 {\r
2182         int r = 0;\r
2183         wchar_t* pw0 = NULL;\r
2184 START_ROUTINE\r
2185         if(uFlags & (MF_BITMAP | MF_OWNERDRAW))\r
2186                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, (LPCWSTR)lpNewItem);\r
2187         else\r
2188         {\r
2189                 pw0 = DuplicateMtoW(lpNewItem, -1);\r
2190                 r = AppendMenuW(hMenu, uFlags, uIDNewItem, pw0);\r
2191         }\r
2192 END_ROUTINE\r
2193         FreeDuplicatedString(pw0);\r
2194         return r;\r
2195 }\r
2196 \r
2197 BOOL GetMenuItemInfoM(HMENU hmenu, UINT item, BOOL fByPosition, LPMENUITEMINFOA lpmii)\r
2198 {\r
2199         BOOL r = FALSE;\r
2200         wchar_t* pw0 = NULL;\r
2201         MENUITEMINFOW wmii;\r
2202 START_ROUTINE\r
2203         wmii.cbSize = sizeof(MENUITEMINFOW);\r
2204         wmii.fMask = lpmii->fMask;\r
2205         wmii.fType = lpmii->fType;\r
2206         wmii.fState = lpmii->fState;\r
2207         wmii.wID = lpmii->wID;\r
2208         wmii.hSubMenu = lpmii->hSubMenu;\r
2209         wmii.hbmpChecked = lpmii->hbmpChecked;\r
2210         wmii.hbmpUnchecked = lpmii->hbmpUnchecked;\r
2211         wmii.dwItemData = lpmii->dwItemData;\r
2212         if(lpmii->fMask & MIIM_TYPE)\r
2213         {\r
2214                 pw0 = DuplicateMtoWBuffer(lpmii->dwTypeData, -1, lpmii->cch * 4);\r
2215                 wmii.dwTypeData = pw0;\r
2216                 wmii.cch = lpmii->cch * 4;\r
2217         }\r
2218         wmii.hbmpItem = lpmii->hbmpItem;\r
2219         r = GetMenuItemInfoW(hmenu, item, fByPosition, &wmii);\r
2220         lpmii->fType = wmii.fType;\r
2221         lpmii->fState = wmii.fState;\r
2222         lpmii->wID = wmii.wID;\r
2223         lpmii->hSubMenu = wmii.hSubMenu;\r
2224         lpmii->hbmpChecked = wmii.hbmpChecked;\r
2225         lpmii->hbmpUnchecked = wmii.hbmpUnchecked;\r
2226         lpmii->dwItemData = wmii.dwItemData;\r
2227         WtoM(lpmii->dwTypeData, lpmii->cch, wmii.dwTypeData, -1);\r
2228         TerminateStringM(lpmii->dwTypeData, lpmii->cch);\r
2229 END_ROUTINE\r
2230         FreeDuplicatedString(pw0);\r
2231         return r;\r
2232 }\r
2233 \r
2234 HFONT CreateFontIndirectM(CONST LOGFONTA *lplf)\r
2235 {\r
2236         HFONT r = NULL;\r
2237         LOGFONTW wlf;\r
2238 START_ROUTINE\r
2239         wlf.lfHeight = lplf->lfHeight;\r
2240         wlf.lfWidth = lplf->lfWidth;\r
2241         wlf.lfEscapement = lplf->lfEscapement;\r
2242         wlf.lfOrientation = lplf->lfOrientation;\r
2243         wlf.lfWeight = lplf->lfWeight;\r
2244         wlf.lfItalic = lplf->lfItalic;\r
2245         wlf.lfUnderline = lplf->lfUnderline;\r
2246         wlf.lfStrikeOut = lplf->lfStrikeOut;\r
2247         wlf.lfCharSet = lplf->lfCharSet;\r
2248         wlf.lfOutPrecision = lplf->lfOutPrecision;\r
2249         wlf.lfClipPrecision = lplf->lfClipPrecision;\r
2250         wlf.lfQuality = lplf->lfQuality;\r
2251         wlf.lfPitchAndFamily = lplf->lfPitchAndFamily;\r
2252         MtoW(wlf.lfFaceName, LF_FACESIZE, lplf->lfFaceName, -1);\r
2253         TerminateStringW(wlf.lfFaceName, LF_FACESIZE);\r
2254         r = CreateFontIndirect(&wlf);\r
2255 END_ROUTINE\r
2256         return r;\r
2257 }\r
2258 \r
2259 BOOL ChooseFontM(LPCHOOSEFONTA v0)\r
2260 {\r
2261         BOOL r = FALSE;\r
2262         wchar_t* pw0 = NULL;\r
2263         wchar_t* pw1 = NULL;\r
2264         CHOOSEFONTW a0;\r
2265         LOGFONTW* pwlf;\r
2266 START_ROUTINE\r
2267         a0.lStructSize = sizeof(CHOOSEFONTW);\r
2268         a0.hwndOwner = v0->hwndOwner;\r
2269         a0.hDC = v0->hDC;\r
2270         if(v0->lpLogFont && (pwlf = (LOGFONTW*)malloc(sizeof(LOGFONTW))))\r
2271         {\r
2272                 pwlf->lfHeight = v0->lpLogFont->lfHeight;\r
2273                 pwlf->lfWidth = v0->lpLogFont->lfWidth;\r
2274                 pwlf->lfEscapement = v0->lpLogFont->lfEscapement;\r
2275                 pwlf->lfOrientation = v0->lpLogFont->lfOrientation;\r
2276                 pwlf->lfWeight = v0->lpLogFont->lfWeight;\r
2277                 pwlf->lfItalic = v0->lpLogFont->lfItalic;\r
2278                 pwlf->lfUnderline = v0->lpLogFont->lfUnderline;\r
2279                 pwlf->lfStrikeOut = v0->lpLogFont->lfStrikeOut;\r
2280                 pwlf->lfCharSet = v0->lpLogFont->lfCharSet;\r
2281                 pwlf->lfOutPrecision = v0->lpLogFont->lfOutPrecision;\r
2282                 pwlf->lfClipPrecision = v0->lpLogFont->lfClipPrecision;\r
2283                 pwlf->lfQuality = v0->lpLogFont->lfQuality;\r
2284                 pwlf->lfPitchAndFamily = v0->lpLogFont->lfPitchAndFamily;\r
2285                 MtoW(pwlf->lfFaceName, LF_FACESIZE, v0->lpLogFont->lfFaceName, -1);\r
2286                 TerminateStringW(pwlf->lfFaceName, LF_FACESIZE);\r
2287         }\r
2288         else\r
2289                 pwlf = NULL;\r
2290         a0.lpLogFont = pwlf;\r
2291         a0.iPointSize = v0->iPointSize;\r
2292         a0.Flags = v0->Flags;\r
2293         a0.rgbColors = v0->rgbColors;\r
2294         a0.lCustData = v0->lCustData;\r
2295         a0.lpfnHook = v0->lpfnHook;\r
2296         pw0 = DuplicateMtoW(v0->lpTemplateName, -1);\r
2297         a0.lpTemplateName = pw0;\r
2298         a0.hInstance = v0->hInstance;\r
2299         pw1 = DuplicateMtoWBuffer(v0->lpszStyle, -1, LF_FACESIZE * 4);\r
2300         a0.lpszStyle = pw1;\r
2301         a0.nFontType = v0->nFontType;\r
2302         a0.nSizeMin = v0->nSizeMin;\r
2303         a0.nSizeMax = v0->nSizeMax;\r
2304         r = ChooseFontW(&a0);\r
2305         if(v0->lpLogFont)\r
2306         {\r
2307                 v0->lpLogFont->lfHeight = pwlf->lfHeight;\r
2308                 v0->lpLogFont->lfWidth = pwlf->lfWidth;\r
2309                 v0->lpLogFont->lfEscapement = pwlf->lfEscapement;\r
2310                 v0->lpLogFont->lfOrientation = pwlf->lfOrientation;\r
2311                 v0->lpLogFont->lfWeight = pwlf->lfWeight;\r
2312                 v0->lpLogFont->lfItalic = pwlf->lfItalic;\r
2313                 v0->lpLogFont->lfUnderline = pwlf->lfUnderline;\r
2314                 v0->lpLogFont->lfStrikeOut = pwlf->lfStrikeOut;\r
2315                 v0->lpLogFont->lfCharSet = pwlf->lfCharSet;\r
2316                 v0->lpLogFont->lfOutPrecision = pwlf->lfOutPrecision;\r
2317                 v0->lpLogFont->lfClipPrecision = pwlf->lfClipPrecision;\r
2318                 v0->lpLogFont->lfQuality = pwlf->lfQuality;\r
2319                 v0->lpLogFont->lfPitchAndFamily = pwlf->lfPitchAndFamily;\r
2320                 WtoM(v0->lpLogFont->lfFaceName, LF_FACESIZE, pwlf->lfFaceName, -1);\r
2321                 TerminateStringM(v0->lpLogFont->lfFaceName, LF_FACESIZE);\r
2322         }\r
2323         v0->rgbColors = a0.rgbColors;\r
2324         WtoM(v0->lpszStyle, LF_FACESIZE, pw1, -1);\r
2325         TerminateStringM(v0->lpszStyle, LF_FACESIZE);\r
2326         v0->nFontType = a0.nFontType;\r
2327         if(pwlf)\r
2328                 free(pwlf);\r
2329 END_ROUTINE\r
2330         FreeDuplicatedString(pw0);\r
2331         FreeDuplicatedString(pw1);\r
2332         return r;\r
2333 }\r
2334 \r
2335 INT_PTR DialogBoxParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)\r
2336 {\r
2337         INT_PTR r = 0;\r
2338         wchar_t* pw0 = NULL;\r
2339 START_ROUTINE\r
2340         pw0 = DuplicateMtoW(lpTemplateName, -1);\r
2341         r = DialogBoxParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);\r
2342 END_ROUTINE\r
2343         FreeDuplicatedString(pw0);\r
2344         return r;\r
2345 }\r
2346 \r
2347 HWND CreateDialogParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)\r
2348 {\r
2349         HWND r = NULL;\r
2350         wchar_t* pw0 = NULL;\r
2351 START_ROUTINE\r
2352         pw0 = DuplicateMtoW(lpTemplateName, -1);\r
2353         r = CreateDialogParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);\r
2354 END_ROUTINE\r
2355         FreeDuplicatedString(pw0);\r
2356         return r;\r
2357 }\r
2358 \r
2359 BOOL sndPlaySoundM(LPCSTR pszSound, UINT fuSound)\r
2360 {\r
2361         BOOL r = FALSE;\r
2362         wchar_t* pw0 = NULL;\r
2363 START_ROUTINE\r
2364         pw0 = DuplicateMtoW(pszSound, -1);\r
2365         r = sndPlaySoundW(pw0, fuSound);\r
2366 END_ROUTINE\r
2367         FreeDuplicatedString(pw0);\r
2368         return r;\r
2369 }\r
2370 \r
2371 HANDLE SetClipboardDataM(UINT uFormat, HANDLE hMem)\r
2372 {\r
2373         HANDLE r = NULL;\r
2374         char* p;\r
2375         int Length;\r
2376         int BufferLength;\r
2377         HGLOBAL hBufferMem;\r
2378 START_ROUTINE\r
2379         if(uFormat == CF_TEXT)\r
2380         {\r
2381                 p = (char*)GlobalLock(hMem);\r
2382                 Length = (int)GlobalSize(hMem);\r
2383                 BufferLength = MtoW(NULL, 0, p, Length);\r
2384                 if(hBufferMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(wchar_t) * BufferLength))\r
2385                 {\r
2386                         MtoW((LPWSTR)GlobalLock(hBufferMem), BufferLength, p, Length);\r
2387                         GlobalUnlock(hBufferMem);\r
2388                         r = SetClipboardData(CF_UNICODETEXT, hBufferMem);\r
2389                 }\r
2390                 GlobalUnlock(hMem);\r
2391                 GlobalFree(hMem);\r
2392         }\r
2393         else\r
2394                 r = SetClipboardData(uFormat, hMem);\r
2395 END_ROUTINE\r
2396         return r;\r
2397 }\r
2398 \r
2399 BOOL CopyFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists)\r
2400 {\r
2401         BOOL r = FALSE;\r
2402         wchar_t* pw0 = NULL;\r
2403         wchar_t* pw1 = NULL;\r
2404 START_ROUTINE\r
2405         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
2406         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
2407         r = CopyFileW(pw0, pw1, bFailIfExists);\r
2408 END_ROUTINE\r
2409         FreeDuplicatedString(pw0);\r
2410         FreeDuplicatedString(pw1);\r
2411         return r;\r
2412 }\r
2413 \r
2414 BOOL MoveFileM(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)\r
2415 {\r
2416         BOOL r = FALSE;\r
2417         wchar_t* pw0 = NULL;\r
2418         wchar_t* pw1 = NULL;\r
2419 START_ROUTINE\r
2420         pw0 = DuplicateMtoW(lpExistingFileName, -1);\r
2421         pw1 = DuplicateMtoW(lpNewFileName, -1);\r
2422         r = MoveFileW(pw0, pw1);\r
2423 END_ROUTINE\r
2424         FreeDuplicatedString(pw0);\r
2425         FreeDuplicatedString(pw1);\r
2426         return r;\r
2427 }\r
2428 \r
2429 BOOL DeleteFileM(LPCSTR lpFileName)\r
2430 {\r
2431         BOOL r = FALSE;\r
2432         wchar_t* pw0 = NULL;\r
2433 START_ROUTINE\r
2434         pw0 = DuplicateMtoW(lpFileName, -1);\r
2435         r = DeleteFileW(pw0);\r
2436 END_ROUTINE\r
2437         FreeDuplicatedString(pw0);\r
2438         return r;\r
2439 }\r
2440 \r
2441 BOOL CreateDirectoryM(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)\r
2442 {\r
2443         BOOL r = FALSE;\r
2444         wchar_t* pw0 = NULL;\r
2445 START_ROUTINE\r
2446         pw0 = DuplicateMtoW(lpPathName, -1);\r
2447         r = CreateDirectoryW(pw0, lpSecurityAttributes);\r
2448 END_ROUTINE\r
2449         FreeDuplicatedString(pw0);\r
2450         return r;\r
2451 }\r
2452 \r
2453 BOOL RemoveDirectoryM(LPCSTR lpPathName)\r
2454 {\r
2455         BOOL r = FALSE;\r
2456         wchar_t* pw0 = NULL;\r
2457 START_ROUTINE\r
2458         pw0 = DuplicateMtoW(lpPathName, -1);\r
2459         r = RemoveDirectoryW(pw0);\r
2460 END_ROUTINE\r
2461         FreeDuplicatedString(pw0);\r
2462         return r;\r
2463 }\r
2464 \r
2465 int mkdirM(const char * _Path)\r
2466 {\r
2467         int r = -1;\r
2468         wchar_t* pw0 = NULL;\r
2469 START_ROUTINE\r
2470         pw0 = DuplicateMtoW(_Path, -1);\r
2471         r = _wmkdir(pw0);\r
2472 END_ROUTINE\r
2473         FreeDuplicatedString(pw0);\r
2474         return r;\r
2475 }\r
2476 \r
2477 int _mkdirM(const char * _Path)\r
2478 {\r
2479         int r = -1;\r
2480         wchar_t* pw0 = NULL;\r
2481 START_ROUTINE\r
2482         pw0 = DuplicateMtoW(_Path, -1);\r
2483         r = _wmkdir(pw0);\r
2484 END_ROUTINE\r
2485         FreeDuplicatedString(pw0);\r
2486         return r;\r
2487 }\r
2488 \r
2489 int rmdirM(const char * _Path)\r
2490 {\r
2491         int r = -1;\r
2492         wchar_t* pw0 = NULL;\r
2493 START_ROUTINE\r
2494         pw0 = DuplicateMtoW(_Path, -1);\r
2495         r = _wrmdir(pw0);\r
2496 END_ROUTINE\r
2497         FreeDuplicatedString(pw0);\r
2498         return r;\r
2499 }\r
2500 \r
2501 int _rmdirM(const char * _Path)\r
2502 {\r
2503         int r = -1;\r
2504         wchar_t* pw0 = NULL;\r
2505 START_ROUTINE\r
2506         pw0 = DuplicateMtoW(_Path, -1);\r
2507         r = _wrmdir(pw0);\r
2508 END_ROUTINE\r
2509         FreeDuplicatedString(pw0);\r
2510         return r;\r
2511 }\r
2512 \r
2513 int removeM(const char * _Filename)\r
2514 {\r
2515         int r = -1;\r
2516         wchar_t* pw0 = NULL;\r
2517 START_ROUTINE\r
2518         pw0 = DuplicateMtoW(_Filename, -1);\r
2519         r = _wremove(pw0);\r
2520 END_ROUTINE\r
2521         FreeDuplicatedString(pw0);\r
2522         return r;\r
2523 }\r
2524 \r
2525 int _removeM(const char * _Filename)\r
2526 {\r
2527         int r = -1;\r
2528         wchar_t* pw0 = NULL;\r
2529 START_ROUTINE\r
2530         pw0 = DuplicateMtoW(_Filename, -1);\r
2531         r = _wremove(pw0);\r
2532 END_ROUTINE\r
2533         FreeDuplicatedString(pw0);\r
2534         return r;\r
2535 }\r
2536 \r
2537 int _unlinkM(const char * _Filename)\r
2538 {\r
2539         int r = -1;\r
2540         wchar_t* pw0 = NULL;\r
2541 START_ROUTINE\r
2542         pw0 = DuplicateMtoW(_Filename, -1);\r
2543         r = _wunlink(pw0);\r
2544 END_ROUTINE\r
2545         FreeDuplicatedString(pw0);\r
2546         return r;\r
2547 }\r
2548 \r
2549 size_t _mbslenM(const unsigned char * _Str)\r
2550 {\r
2551         size_t r = 0;\r
2552 START_ROUTINE\r
2553         while(GetNextCharM(_Str, NULL, &_Str) > 0)\r
2554         {\r
2555                 r++;\r
2556         }\r
2557 END_ROUTINE\r
2558         return r;\r
2559 }\r
2560 \r
2561 unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)\r
2562 {\r
2563         unsigned char* r = NULL;\r
2564         unsigned int c;\r
2565         unsigned char* p;\r
2566 START_ROUTINE\r
2567         while((c = GetNextCharM(_Str, NULL, &p)) > 0)\r
2568         {\r
2569                 if(c == _Ch)\r
2570                         break;\r
2571                 _Str = p;\r
2572         }\r
2573         if(c == _Ch)\r
2574                 r = (unsigned char*)_Str;\r
2575 END_ROUTINE\r
2576         return r;\r
2577 }\r
2578 \r
2579 unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)\r
2580 {\r
2581         unsigned char* r = NULL;\r
2582         unsigned int c;\r
2583         unsigned char* p;\r
2584 START_ROUTINE\r
2585         while((c = GetNextCharM(_Str, NULL, &p)) > 0)\r
2586         {\r
2587                 if(c == _Ch)\r
2588                         r = (unsigned char*)_Str;\r
2589                 _Str = p;\r
2590         }\r
2591         if(c == _Ch)\r
2592                 r = (unsigned char*)_Str;\r
2593 END_ROUTINE\r
2594         return r;\r
2595 }\r
2596 \r
2597 unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)\r
2598 {\r
2599         unsigned char* r = NULL;\r
2600 START_ROUTINE\r
2601         r = strstr(_Str, _Substr);\r
2602 END_ROUTINE\r
2603         return r;\r
2604 }\r
2605 \r
2606 int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
2607 {\r
2608         int r = 0;\r
2609 START_ROUTINE\r
2610         r = strcmp(_Str1, _Str2);\r
2611 END_ROUTINE\r
2612         return r;\r
2613 }\r
2614 \r
2615 int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)\r
2616 {\r
2617         int r = 0;\r
2618 START_ROUTINE\r
2619         r = _stricmp(_Str1, _Str2);\r
2620 END_ROUTINE\r
2621         return r;\r
2622 }\r
2623 \r
2624 int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)\r
2625 {\r
2626         int r = 0;\r
2627         DWORD c1;\r
2628         DWORD c2;\r
2629 START_ROUTINE\r
2630         c1 = 0;\r
2631         c2 = 0;\r
2632         while(_MaxCount > 0)\r
2633         {\r
2634                 c1 = GetNextCharM(_Str1, NULL, &_Str1);\r
2635                 c2 = GetNextCharM(_Str2, NULL, &_Str2);\r
2636                 if(c1 != c2)\r
2637                         break;\r
2638                 _MaxCount--;\r
2639                 if(c1 == 0 || c2 == 0)\r
2640                         break;\r
2641         }\r
2642         r = c1 - c2;\r
2643 END_ROUTINE\r
2644         return r;\r
2645 }\r
2646 \r
2647 unsigned char * _mbslwrM(unsigned char * _String)\r
2648 {\r
2649         unsigned char* r = NULL;\r
2650 START_ROUTINE\r
2651         r = _strlwr(_String);\r
2652 END_ROUTINE\r
2653         return r;\r
2654 }\r
2655 \r
2656 unsigned char * _mbsuprM(unsigned char * _String)\r
2657 {\r
2658         unsigned char* r = NULL;\r
2659 START_ROUTINE\r
2660         r = _strupr(_String);\r
2661 END_ROUTINE\r
2662         return r;\r
2663 }\r
2664 \r
2665 unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)\r
2666 {\r
2667         unsigned char* r = NULL;\r
2668 START_ROUTINE\r
2669         while(_Count > 0 && GetNextCharM(_Str, NULL, &_Str) > 0)\r
2670         {\r
2671                 _Count--;\r
2672         }\r
2673         r = (unsigned char*)_Str;\r
2674 END_ROUTINE\r
2675         return r;\r
2676 }\r
2677 \r
2678 FILE * fopenM(const char * _Filename, const char * _Mode)\r
2679 {\r
2680         FILE* r = NULL;\r
2681         wchar_t* pw0 = NULL;\r
2682         wchar_t* pw1 = NULL;\r
2683 START_ROUTINE\r
2684         pw0 = DuplicateMtoW(_Filename, -1);\r
2685         pw1 = DuplicateMtoW(_Mode, -1);\r
2686         r = _wfopen(pw0, pw1);\r
2687 END_ROUTINE\r
2688         FreeDuplicatedString(pw0);\r
2689         FreeDuplicatedString(pw1);\r
2690         return r;\r
2691 }\r
2692 \r