OSDN Git Service

Fix bugs of process protection on Windows 7.
[ffftp/ffftp.git] / mbswrapper.c
index 2b7e2cf..d65022e 100644 (file)
@@ -1,15 +1,14 @@
-// mbswrapper.cpp
+// mbswrapper.c
 // Copyright (C) 2011 Suguru Kawamoto
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\83\8f\83C\83h\95\8e\9aAPI\83\89\83b\83p\81[
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\82ÍUTF-8\81A\83\8f\83C\83h\95\8e\9a\82ÍUTF-16\82Å\82 \82é\82à\82Ì\82Æ\82·\82é
-// \91S\82Ä\82Ì\90§\8cä\97p\82Ì\95\8e\9a\82ÍASCII\82Ì\94Í\88Í\82Å\82 \82é\82½\82ß\81AShift_JIS\82ÆUTF-8\8aÔ\82Ì\95Ï\8a·\82Í\95s\97v
+// マルチバイト文字ワイド文字APIラッパー
+// マルチバイト文字はUTF-8、ワイド文字はUTF-16であるものとする
+// 全ての制御用の文字はASCIIの範囲であるため、Shift_JISとUTF-8間の変換は不要
 
 #define UNICODE
-#define _WIN32_WINNT 0x0600
-#undef _WIN32_IE
-#define _WIN32_IE 0x0400
+#define _UNICODE
 
 #include <tchar.h>
+#include <direct.h>
 #include <windows.h>
 #include <commctrl.h>
 #include <shlobj.h>
 #define DO_NOT_REPLACE
 #include "mbswrapper.h"
 
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82©\82ç\83\8f\83C\83h\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// マルチバイト文字列からワイド文字列へ変換
 int MtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)
 {
-       if(pSrc < (LPCSTR)0x00010000 || !((char*)pSrc + 1))
+       if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
                return 0;
        if(pDst)
                return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, pDst, size);
        return MultiByteToWideChar(CP_UTF8, 0, pSrc, count, NULL, 0);
 }
 
-// \83\8f\83C\83h\95\8e\9a\97ñ\82©\82ç\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// ワイド文字列からマルチバイト文字列へ変換
 int WtoM(LPSTR pDst, int size, LPCWSTR pSrc, int count)
 {
-       if(pSrc < (LPCWSTR)0x00010000 || !((char*)pSrc + 1))
+       if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
                return 0;
        if(pDst)
                return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, pDst, size, NULL, NULL);
        return WideCharToMultiByte(CP_UTF8, 0, pSrc, count, NULL, 0, NULL, NULL);
 }
 
-// \83\8f\83C\83h\95\8e\9a\97ñ\82©\82çShift_JIS\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// Shift_JIS文字列からワイド文字列へ変換
+int AtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)
+{
+       if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
+               return 0;
+       if(pDst)
+               return MultiByteToWideChar(CP_ACP, 0, pSrc, count, pDst, size);
+       return MultiByteToWideChar(CP_ACP, 0, pSrc, count, NULL, 0);
+}
+
+// ワイド文字列からShift_JIS文字列へ変換
 int WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)
 {
-       if(pSrc < (LPCWSTR)0x00010000 || !((char*)pSrc + 1))
+       if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
                return 0;
        if(pDst)
                return WideCharToMultiByte(CP_ACP, 0, pSrc, count, pDst, size, NULL, NULL);
        return WideCharToMultiByte(CP_ACP, 0, pSrc, count, NULL, 0, NULL, NULL);
 }
 
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\83o\83b\83t\83@\8fI\92[\82ð\8b­\90§\93I\82ÉNULL\82Å\92u\8a·
+// マルチバイト文字列バッファ終端を強制的にNULLで置換
 int TerminateStringM(LPSTR lpString, int size)
 {
        int i;
-       if(lpString < (LPSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)
                return 0;
        for(i = 0; i < size; i++)
        {
@@ -64,11 +73,11 @@ int TerminateStringM(LPSTR lpString, int size)
        return i;
 }
 
-// \83\8f\83C\83h\95\8e\9a\97ñ\83o\83b\83t\83@\8fI\92[\82ð\8b­\90§\93I\82ÉNULL\82Å\92u\8a·
+// ワイド文字列バッファ終端を強制的にNULLで置換
 int TerminateStringW(LPWSTR lpString, int size)
 {
        int i;
-       if(lpString < (LPWSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPWSTR)0x00010000 || lpString == (LPWSTR)~0)
                return 0;
        for(i = 0; i < size; i++)
        {
@@ -80,11 +89,27 @@ int TerminateStringW(LPWSTR lpString, int size)
        return i;
 }
 
-// NULL\8bæ\90Ø\82è\95¡\90\94\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82Ì\92·\82³\82ð\8eæ\93¾
+// Shift_JIS文字列バッファ終端を強制的にNULLで置換
+int TerminateStringA(LPSTR lpString, int size)
+{
+       int i;
+       if(lpString < (LPSTR)0x00010000 || lpString == (LPSTR)~0)
+               return 0;
+       for(i = 0; i < size; i++)
+       {
+               if(lpString[i] == '\0')
+                       return i;
+       }
+       i--;
+       lpString[i] = '\0';
+       return i;
+}
+
+// NULL区切り複数マルチバイト文字列の長さを取得
 size_t GetMultiStringLengthM(LPCSTR lpString)
 {
        size_t i;
-       if(lpString < (LPCSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
                return 0;
        i = 0;
        while(lpString[i] != '\0' || lpString[i + 1] != '\0')
@@ -95,11 +120,11 @@ size_t GetMultiStringLengthM(LPCSTR lpString)
        return i;
 }
 
-// NULL\8bæ\90Ø\82è\95¡\90\94\83\8f\83C\83h\95\8e\9a\97ñ\82Ì\92·\82³\82ð\8eæ\93¾
+// NULL区切り複数ワイド文字列の長さを取得
 size_t GetMultiStringLengthW(LPCWSTR lpString)
 {
        size_t i;
-       if(lpString < (LPCWSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
                return 0;
        i = 0;
        while(lpString[i] != L'\0' || lpString[i + 1] != L'\0')
@@ -110,42 +135,136 @@ size_t GetMultiStringLengthW(LPCWSTR lpString)
        return i;
 }
 
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\97p\82Ì\83\81\83\82\83\8a\82ð\8am\95Û
+// NULL区切り複数Shift_JIS文字列の長さを取得
+size_t GetMultiStringLengthA(LPCSTR lpString)
+{
+       size_t i;
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
+               return 0;
+       i = 0;
+       while(lpString[i] != '\0' || lpString[i + 1] != '\0')
+       {
+               i++;
+       }
+       i++;
+       return i;
+}
+
+// NULL区切りマルチバイト文字列からワイド文字列へ変換
+int MtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)
+{
+       int i;
+       if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
+               return 0;
+       if(!pDst)
+               return GetMultiStringLengthM(pSrc);
+       i = 0;
+       while(*pSrc != '\0')
+       {
+               i += MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1);
+               pSrc += strlen(pSrc) + 1;
+       }
+       pDst[i] = L'\0';
+       return i;
+}
+
+// NULL区切りワイド文字列からマルチバイト文字列へ変換
+int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
+{
+       int i;
+       if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
+               return 0;
+       if(!pDst)
+               return GetMultiStringLengthW(pSrc);
+       i = 0;
+       while(*pSrc != L'\0')
+       {
+               i += WideCharToMultiByte(CP_UTF8, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);
+               pSrc += wcslen(pSrc) + 1;
+       }
+       pDst[i] = '\0';
+       return i;
+}
+
+// NULL区切りShift_JIS文字列からワイド文字列へ変換
+int AtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)
+{
+       int i;
+       if(pSrc < (LPCSTR)0x00010000 || pSrc == (LPCSTR)~0)
+               return 0;
+       if(!pDst)
+               return GetMultiStringLengthA(pSrc);
+       i = 0;
+       while(*pSrc != '\0')
+       {
+               i += MultiByteToWideChar(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1);
+               pSrc += strlen(pSrc) + 1;
+       }
+       pDst[i] = L'\0';
+       return i;
+}
+
+// NULL区切りワイド文字列からShift_JIS文字列へ変換
+int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
+{
+       int i;
+       if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
+               return 0;
+       if(!pDst)
+               return GetMultiStringLengthW(pSrc);
+       i = 0;
+       while(*pSrc != L'\0')
+       {
+               i += WideCharToMultiByte(CP_ACP, 0, pSrc, -1, pDst + i, size - i - 1, NULL, NULL);
+               pSrc += wcslen(pSrc) + 1;
+       }
+       pDst[i] = '\0';
+       return i;
+}
+
+// マルチバイト文字列用のメモリを確保
 char* AllocateStringM(int size)
 {
        char* p;
-       p = (char*)malloc(sizeof(char) * size);
+       // 0が指定される場合があるため1文字分追加
+       p = (char*)malloc(sizeof(char) * (size + 1));
+       // 念のため先頭にNULL文字を代入
        if(p)
                *p = '\0';
        return p;
 }
 
-// \83\8f\83C\83h\95\8e\9a\97ñ\97p\82Ì\83\81\83\82\83\8a\82ð\8am\95Û
+// ワイド文字列用のメモリを確保
 wchar_t* AllocateStringW(int size)
 {
        wchar_t* p;
-       p = (wchar_t*)malloc(sizeof(wchar_t) * size);
+       // 0が指定される場合があるため1文字分追加
+       p = (wchar_t*)malloc(sizeof(wchar_t) * (size + 1));
+       // 念のため先頭にNULL文字を代入
        if(p)
                *p = L'\0';
        return p;
 }
 
-// Shift_JIS\95\8e\9a\97ñ\97p\82Ì\83\81\83\82\83\8a\82ð\8am\95Û
+// Shift_JIS文字列用のメモリを確保
 char* AllocateStringA(int size)
 {
        char* p;
-       p = (char*)malloc(sizeof(char) * size);
+       // 0が指定される場合があるため1文字分追加
+       p = (char*)malloc(sizeof(char) * (size + 1));
+       // 念のため先頭にNULL文字を代入
        if(p)
                *p = '\0';
        return p;
 }
 
-// \83\81\83\82\83\8a\82ð\8am\95Û\82µ\82Ä\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82©\82ç\83\8f\83C\83h\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// メモリを確保してマルチバイト文字列からワイド文字列へ変換
+// リソースIDならば元の値を返す
 wchar_t* DuplicateMtoW(LPCSTR lpString, int c)
 {
        wchar_t* p;
        int i;
-       if(lpString < (LPCSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
                return (wchar_t*)lpString;
        if(c < 0)
                c = strlen(lpString);
@@ -158,12 +277,13 @@ wchar_t* DuplicateMtoW(LPCSTR lpString, int c)
        return p;
 }
 
-// \8ew\92è\82µ\82½\83T\83C\83Y\82Ì\83\81\83\82\83\8a\82ð\8am\95Û\82µ\82Ä\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82©\82ç\83\8f\83C\83h\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// 指定したサイズのメモリを確保してマルチバイト文字列からワイド文字列へ変換
+// リソースIDならば元の値を返す
 wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)
 {
        wchar_t* p;
        int i;
-       if(lpString < (LPCSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
                return (wchar_t*)lpString;
        if(c < 0)
                c = strlen(lpString);
@@ -176,12 +296,13 @@ wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)
        return p;
 }
 
-// \83\81\83\82\83\8a\82ð\8am\95Û\82µ\82ÄNULL\8bæ\90Ø\82è\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82©\82ç\83\8f\83C\83h\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// メモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換
+// リソースIDならば元の値を返す
 wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)
 {
        int count;
        wchar_t* p;
-       if(lpString < (LPCSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
                return (wchar_t*)lpString;
        count = GetMultiStringLengthM(lpString) + 1;
        p = AllocateStringW(count);
@@ -190,12 +311,13 @@ wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)
        return p;
 }
 
-// \8ew\92è\82µ\82½\83T\83C\83Y\82Ì\83\81\83\82\83\8a\82ð\8am\95Û\82µ\82ÄNULL\8bæ\90Ø\82è\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82©\82ç\83\8f\83C\83h\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// 指定したサイズのメモリを確保してNULL区切りマルチバイト文字列からワイド文字列へ変換
+// リソースIDならば元の値を返す
 wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)
 {
        int count;
        wchar_t* p;
-       if(lpString < (LPCSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
                return (wchar_t*)lpString;
        count = GetMultiStringLengthM(lpString) + 1;
        p = AllocateStringW(size);
@@ -208,12 +330,13 @@ wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)
        return p;
 }
 
-// \83\81\83\82\83\8a\82ð\8am\95Û\82µ\82Ä\83\8f\83C\83h\95\8e\9a\97ñ\82©\82ç\83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// メモリを確保してワイド文字列からマルチバイト文字列へ変換
+// リソースIDならば元の値を返す
 char* DuplicateWtoM(LPCWSTR lpString, int c)
 {
        char* p;
        int i;
-       if(lpString < (LPCWSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
                return (char*)lpString;
        if(c < 0)
                c = wcslen(lpString);
@@ -226,12 +349,32 @@ char* DuplicateWtoM(LPCWSTR lpString, int c)
        return p;
 }
 
-// \83\81\83\82\83\8a\82ð\8am\95Û\82µ\82Ä\83\8f\83C\83h\95\8e\9a\97ñ\82©\82çShift_JIS\95\8e\9a\97ñ\82Ö\95Ï\8a·
+// メモリを確保してShift_JIS文字列からワイド文字列へ変換
+// リソースIDならば元の値を返す
+wchar_t* DuplicateAtoW(LPCSTR lpString, int c)
+{
+       wchar_t* p;
+       int i;
+       if(lpString < (LPCSTR)0x00010000 || lpString == (LPCSTR)~0)
+               return (wchar_t*)lpString;
+       if(c < 0)
+               c = strlen(lpString);
+       p = AllocateStringW(AtoW(NULL, 0, lpString, c) + 1);
+       if(p)
+       {
+               i = AtoW(p, 65535, lpString, c);
+               p[i] = L'\0';
+       }
+       return p;
+}
+
+// メモリを確保してワイド文字列からShift_JIS文字列へ変換
+// リソースIDならば元の値を返す
 char* DuplicateWtoA(LPCWSTR lpString, int c)
 {
        char* p;
        int i;
-       if(lpString < (LPCWSTR)0x00010000 || !((char*)lpString + 1))
+       if(lpString < (LPCWSTR)0x00010000 || lpString == (LPCWSTR)~0)
                return (char*)lpString;
        if(c < 0)
                c = wcslen(lpString);
@@ -244,24 +387,50 @@ char* DuplicateWtoA(LPCWSTR lpString, int c)
        return p;
 }
 
-// \95\8e\9a\97ñ\97p\82É\8am\95Û\82µ\82½\83\81\83\82\83\8a\82ð\8aJ\95ú
+// 文字列用に確保したメモリを開放
+// リソースIDならば何もしない
 void FreeDuplicatedString(void* p)
 {
-       if(p < (void*)0x00010000 || !((char*)p + 1))
+       if(p < (void*)0x00010000 || p == (void*)~0)
                return;
        free(p);
 }
 
-// \88È\89º\83\89\83b\83p\81[
-// \96ß\82è\92l\83o\83b\83t\83@ r
-// \83\8f\83C\83h\95\8e\9a\83o\83b\83t\83@ pw%d
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\83o\83b\83t\83@ pm%d
-// \88ø\90\94\83o\83b\83t\83@ a%d
+// 以下ラッパー
+// 戻り値バッファ r
+// ワイド文字バッファ pw%d
+// マルチバイト文字バッファ pm%d
+// 引数バッファ a%d
 
+#pragma warning(disable:4102)
 #define START_ROUTINE                                  do{
 #define END_ROUTINE                                            }while(0);end_of_routine:
 #define QUIT_ROUTINE                                   goto end_of_routine;
 
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
+{
+       int r = 0;
+       char* pm0 = NULL;
+START_ROUTINE
+       pm0 = DuplicateWtoM(lpCmdLine, -1);
+       r = WinMainM(hInstance, hPrevInstance, pm0, nCmdShow);
+END_ROUTINE
+       FreeDuplicatedString(pm0);
+       return r;
+}
+
+HMODULE LoadLibraryM(LPCSTR lpLibFileName)
+{
+       HMODULE r = NULL;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(lpLibFileName, -1);
+       r = LoadLibraryW(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
 {
        HANDLE r = INVALID_HANDLE_VALUE;
@@ -340,8 +509,26 @@ END_ROUTINE
 
 DWORD GetLogicalDriveStringsM(DWORD nBufferLength, LPSTR lpBuffer)
 {
-       // TODO: \96{\97\88\82Í\95Ï\8a·\82ª\95K\97v\82¾\82ª\94¼\8ap\89p\90\94\82Ì\82Ý\82Æ\8ev\82í\82ê\82é\82Ì\82Å\8fÈ\97ª
-       return GetLogicalDriveStringsA(nBufferLength, lpBuffer);
+       DWORD r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = AllocateStringW(nBufferLength * 4);
+       GetLogicalDriveStringsW(nBufferLength * 4, pw0);
+       WtoMMultiString(lpBuffer, nBufferLength, pw0);
+       r = TerminateStringM(lpBuffer, nBufferLength);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+ATOM RegisterClassExM(CONST WNDCLASSEXA * v0)
+{
+       ATOM r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       r = RegisterClassExA(v0);
+END_ROUTINE
+       return r;
 }
 
 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)
@@ -359,6 +546,58 @@ END_ROUTINE
        return r;
 }
 
+LONG GetWindowLongM(HWND hWnd, int nIndex)
+{
+       LRESULT r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       if(IsWindowUnicode(hWnd))
+               r = GetWindowLongW(hWnd, nIndex);
+       else
+               r = GetWindowLongA(hWnd, nIndex);
+END_ROUTINE
+       return r;
+}
+
+LONG SetWindowLongM(HWND hWnd, int nIndex, LONG dwNewLong)
+{
+       LRESULT r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       if(IsWindowUnicode(hWnd))
+               r = SetWindowLongW(hWnd, nIndex, dwNewLong);
+       else
+               r = SetWindowLongA(hWnd, nIndex, dwNewLong);
+END_ROUTINE
+       return r;
+}
+
+LRESULT DefWindowProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+       LRESULT r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       if(IsWindowUnicode(hWnd))
+               r = DefWindowProcW(hWnd, Msg, wParam, lParam);
+       else
+               r = DefWindowProcA(hWnd, Msg, wParam, lParam);
+END_ROUTINE
+       return r;
+}
+
+LRESULT CallWindowProcM(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+       LRESULT r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       if(IsWindowUnicode(hWnd))
+               r = CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
+       else
+               r = CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
+END_ROUTINE
+       return r;
+}
+
 LRESULT SendMessageM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
        LRESULT r = 0;
@@ -386,14 +625,14 @@ START_ROUTINE
                r = TerminateStringM((LPSTR)lParam, wParam);
                break;
        case WM_GETTEXTLENGTH:
-               Size = SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0) + 1;
+               Size = SendMessageW(hWnd, WM_GETTEXTLENGTH, wParam, lParam) + 1;
                pw0 = AllocateStringW(Size);
                SendMessageW(hWnd, WM_GETTEXT, (WPARAM)Size, (LPARAM)pw0);
                r = WtoM(NULL, 0, pw0, -1) - 1;
                break;
        default:
                GetClassNameW(hWnd, ClassName, sizeof(ClassName) / sizeof(wchar_t));
-               if(wcsicmp(ClassName, WC_EDITW) == 0)
+               if(_wcsicmp(ClassName, WC_EDITW) == 0)
                {
                        switch(Msg)
                        {
@@ -406,7 +645,7 @@ START_ROUTINE
                                break;
                        }
                }
-               else if(wcsicmp(ClassName, WC_COMBOBOXW) == 0)
+               else if(_wcsicmp(ClassName, WC_COMBOBOXW) == 0)
                {
                        switch(Msg)
                        {
@@ -414,6 +653,20 @@ START_ROUTINE
                                pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
                                r = SendMessageW(hWnd, CB_ADDSTRING, wParam, (LPARAM)pw0);
                                break;
+                       case CB_GETLBTEXT:
+                               Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
+                               pw0 = AllocateStringW(Size);
+                               SendMessageW(hWnd, CB_GETLBTEXT, wParam, (LPARAM)pw0);
+                               // バッファ長不明のためオーバーランの可能性あり
+                               WtoM((LPSTR)lParam, Size * 4, pw0, -1);
+                               r = TerminateStringM((LPSTR)lParam, Size * 4);
+                               break;
+                       case CB_GETLBTEXTLEN:
+                               Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
+                               pw0 = AllocateStringW(Size);
+                               SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
+                               r = WtoM(NULL, 0, pw0, -1) - 1;
+                               break;
                        case CB_INSERTSTRING:
                                pw0 = DuplicateMtoW((LPCSTR)lParam, -1);
                                r = SendMessageW(hWnd, CB_INSERTSTRING, wParam, (LPARAM)pw0);
@@ -427,7 +680,7 @@ START_ROUTINE
                                break;
                        }
                }
-               else if(wcsicmp(ClassName, WC_LISTBOXW) == 0)
+               else if(_wcsicmp(ClassName, WC_LISTBOXW) == 0)
                {
                        switch(Msg)
                        {
@@ -441,18 +694,24 @@ START_ROUTINE
                                break;
                        case LB_GETTEXT:
                                Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
-                               pw0 = AllocateStringW(Size * 4);
+                               pw0 = AllocateStringW(Size);
                                SendMessageW(hWnd, LB_GETTEXT, wParam, (LPARAM)pw0);
-                               // \83o\83b\83t\83@\92·\95s\96¾\82Ì\82½\82ß\83I\81[\83o\81[\83\89\83\93\82Ì\89Â\94\\90«\82 \82è
+                               // バッファ長不明のためオーバーランの可能性あり
                                WtoM((LPSTR)lParam, Size * 4, pw0, -1);
                                r = TerminateStringM((LPSTR)lParam, Size * 4);
                                break;
+                       case LB_GETTEXTLEN:
+                               Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
+                               pw0 = AllocateStringW(Size);
+                               SendMessageW(hWnd, WM_GETTEXT, wParam, (LPARAM)pw0);
+                               r = WtoM(NULL, 0, pw0, -1) - 1;
+                               break;
                        default:
                                r = SendMessageW(hWnd, Msg, wParam, lParam);
                                break;
                        }
                }
-               else if(wcsicmp(ClassName, WC_LISTVIEWW) == 0)
+               else if(_wcsicmp(ClassName, WC_LISTVIEWW) == 0)
                {
                        switch(Msg)
                        {
@@ -463,10 +722,13 @@ START_ROUTINE
                                wLVItem.iSubItem = pmLVItem->iSubItem;
                                wLVItem.state = pmLVItem->state;
                                wLVItem.stateMask = pmLVItem->stateMask;
-                               Size = pmLVItem->cchTextMax * 4;
-                               pw0 = AllocateStringW(Size);
-                               wLVItem.pszText = pw0;
-                               wLVItem.cchTextMax = Size;
+                               if(pmLVItem->mask & LVIF_TEXT)
+                               {
+                                       Size = pmLVItem->cchTextMax * 4;
+                                       pw0 = AllocateStringW(Size);
+                                       wLVItem.pszText = pw0;
+                                       wLVItem.cchTextMax = Size;
+                               }
                                wLVItem.iImage = pmLVItem->iImage;
                                wLVItem.lParam = pmLVItem->lParam;
                                wLVItem.iIndent = pmLVItem->iIndent;
@@ -476,8 +738,11 @@ START_ROUTINE
                                pmLVItem->iSubItem = wLVItem.iSubItem;
                                pmLVItem->state = wLVItem.state;
                                pmLVItem->stateMask = wLVItem.stateMask;
-                               WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
-                               TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
+                               if(pmLVItem->mask & LVIF_TEXT)
+                               {
+                                       WtoM(pmLVItem->pszText, pmLVItem->cchTextMax, wLVItem.pszText, -1);
+                                       TerminateStringM(pmLVItem->pszText, pmLVItem->cchTextMax);
+                               }
                                pmLVItem->iImage = wLVItem.iImage;
                                pmLVItem->lParam = wLVItem.lParam;
                                pmLVItem->iIndent = wLVItem.iIndent;
@@ -489,10 +754,13 @@ START_ROUTINE
                                wLVItem.iSubItem = pmLVItem->iSubItem;
                                wLVItem.state = pmLVItem->state;
                                wLVItem.stateMask = pmLVItem->stateMask;
-                               pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
-                               wLVItem.pszText = pw0;
-                               // TODO: cchTextMax\82Ì\8am\94F
-                               wLVItem.cchTextMax = pmLVItem->cchTextMax;
+                               if(pmLVItem->mask & LVIF_TEXT)
+                               {
+                                       pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
+                                       wLVItem.pszText = pw0;
+                                       // TODO: cchTextMaxの確認
+                                       wLVItem.cchTextMax = pmLVItem->cchTextMax;
+                               }
                                wLVItem.iImage = pmLVItem->iImage;
                                wLVItem.lParam = pmLVItem->lParam;
                                wLVItem.iIndent = pmLVItem->iIndent;
@@ -505,10 +773,13 @@ START_ROUTINE
                                wLVItem.iSubItem = pmLVItem->iSubItem;
                                wLVItem.state = pmLVItem->state;
                                wLVItem.stateMask = pmLVItem->stateMask;
-                               pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
-                               wLVItem.pszText = pw0;
-                               // TODO: cchTextMax\82Ì\8am\94F
-                               wLVItem.cchTextMax = pmLVItem->cchTextMax;
+                               if(pmLVItem->mask & LVIF_TEXT)
+                               {
+                                       pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
+                                       wLVItem.pszText = pw0;
+                                       // TODO: cchTextMaxの確認
+                                       wLVItem.cchTextMax = pmLVItem->cchTextMax;
+                               }
                                wLVItem.iImage = pmLVItem->iImage;
                                wLVItem.lParam = pmLVItem->lParam;
                                wLVItem.iIndent = pmLVItem->iIndent;
@@ -517,21 +788,56 @@ START_ROUTINE
                        case LVM_FINDITEMA:
                                pmLVFindInfo = (LVFINDINFOA*)lParam;
                                wLVFindInfo.flags = pmLVFindInfo->flags;
-                               pw0 = DuplicateMtoW(pmLVFindInfo->psz, -1);
-                               wLVFindInfo.psz = pw0;
+                               if(pmLVFindInfo->flags & (LVFI_STRING | LVFI_PARTIAL))
+                               {
+                                       pw0 = DuplicateMtoW(pmLVFindInfo->psz, -1);
+                                       wLVFindInfo.psz = pw0;
+                               }
                                wLVFindInfo.lParam = pmLVFindInfo->lParam;
                                wLVFindInfo.pt = pmLVFindInfo->pt;
                                wLVFindInfo.vkDirection = pmLVFindInfo->vkDirection;
                                r = SendMessageW(hWnd, LVM_FINDITEMW, wParam, (LPARAM)&wLVItem);
                                break;
+                       case LVM_GETCOLUMNA:
+                               pmLVColumn = (LVCOLUMNA*)lParam;
+                               wLVColumn.mask = pmLVColumn->mask;
+                               wLVColumn.fmt = pmLVColumn->fmt;
+                               wLVColumn.cx = pmLVColumn->cx;
+                               Size = pmLVColumn->cchTextMax * 4;
+                               if(pmLVColumn->mask & LVCF_TEXT)
+                               {
+                                       pw0 = AllocateStringW(Size);
+                                       wLVColumn.pszText = pw0;
+                                       wLVColumn.cchTextMax = Size;
+                               }
+                               wLVColumn.iSubItem = pmLVColumn->iSubItem;
+                               wLVColumn.iImage = pmLVColumn->iImage;
+                               wLVColumn.iOrder = pmLVColumn->iOrder;
+                               r = SendMessageW(hWnd, LVM_GETCOLUMNW, wParam, (LPARAM)&wLVColumn);
+                               pmLVColumn->mask = wLVColumn.mask;
+                               pmLVColumn->fmt = wLVColumn.fmt;
+                               pmLVColumn->cx = wLVColumn.cx;
+                               if(pmLVColumn->mask & LVCF_TEXT)
+                               {
+                                       WtoM(pmLVColumn->pszText, pmLVColumn->cchTextMax, wLVColumn.pszText, -1);
+                                       TerminateStringM(pmLVColumn->pszText, pmLVColumn->cchTextMax);
+                               }
+                               pmLVColumn->iSubItem = wLVColumn.iSubItem;
+                               pmLVColumn->iImage = wLVColumn.iImage;
+                               pmLVColumn->iOrder = wLVColumn.iOrder;
+                               break;
                        case LVM_INSERTCOLUMNA:
                                pmLVColumn = (LVCOLUMNA*)lParam;
                                wLVColumn.mask = pmLVColumn->mask;
                                wLVColumn.fmt = pmLVColumn->fmt;
                                wLVColumn.cx = pmLVColumn->cx;
-                               pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);
-                               wLVColumn.pszText = pw0;
-                               wLVColumn.cchTextMax = pmLVColumn->cchTextMax;
+                               if(pmLVColumn->mask & LVCF_TEXT)
+                               {
+                                       pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);
+                                       wLVColumn.pszText = pw0;
+                                       // TODO: cchTextMaxの確認
+                                       wLVColumn.cchTextMax = pmLVColumn->cchTextMax;
+                               }
                                wLVColumn.iSubItem = pmLVColumn->iSubItem;
                                wLVColumn.iImage = pmLVColumn->iImage;
                                wLVColumn.iOrder = pmLVColumn->iOrder;
@@ -568,7 +874,7 @@ START_ROUTINE
                                break;
                        }
                }
-               else if(wcsicmp(ClassName, STATUSCLASSNAMEW) == 0)
+               else if(_wcsicmp(ClassName, STATUSCLASSNAMEW) == 0)
                {
                        switch(Msg)
                        {
@@ -591,6 +897,19 @@ END_ROUTINE
        return r;
 }
 
+LRESULT DefDlgProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+       LRESULT r = 0;
+START_ROUTINE
+       // WNDPROCがShift_JIS用であるため
+       if(IsWindowUnicode(hWnd))
+               r = DefDlgProcW(hWnd, Msg, wParam, lParam);
+       else
+               r = DefDlgProcA(hWnd, Msg, wParam, lParam);
+END_ROUTINE
+       return r;
+}
+
 LRESULT SendDlgItemMessageM(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
        LRESULT r = 0;
@@ -617,20 +936,38 @@ UINT DragQueryFileM(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch)
        UINT r = 0;
        wchar_t* pw0 = NULL;
 START_ROUTINE
-       pw0 = AllocateStringW(cch * 4);
-       DragQueryFileW(hDrop, iFile, pw0, cch * 4);
-       WtoM(lpszFile, cch, pw0, -1);
-       r = TerminateStringM(lpszFile, cch);
+       if(iFile == (UINT)-1)
+               r = DragQueryFileW(hDrop, iFile, (LPWSTR)lpszFile, cch);
+       else
+       {
+               pw0 = AllocateStringW(cch * 4);
+               DragQueryFileW(hDrop, iFile, pw0, cch * 4);
+               WtoM(lpszFile, cch, pw0, -1);
+               r = TerminateStringM(lpszFile, cch);
+       }
 END_ROUTINE
        FreeDuplicatedString(pw0);
        return r;
 }
 
+LPSTR GetCommandLineM()
+{
+       LPSTR r = 0;
+       static char* pm0 = NULL;
+START_ROUTINE
+       if(!pm0)
+               pm0 = DuplicateWtoM(GetCommandLineW(), -1);
+       r = pm0;
+END_ROUTINE
+       return r;
+}
+
 DWORD GetCurrentDirectoryM(DWORD nBufferLength, LPSTR lpBuffer)
 {
        DWORD r = 0;
        wchar_t* pw0 = NULL;
 START_ROUTINE
+       // TODO: バッファが不十分な場合に必要なサイズを返す
        pw0 = AllocateStringW(nBufferLength * 4);
        GetCurrentDirectoryW(nBufferLength * 4, pw0);
        WtoM(lpBuffer, nBufferLength, pw0, -1);
@@ -652,13 +989,15 @@ END_ROUTINE
        return r;
 }
 
-BOOL SetDllDirectoryM(LPCSTR lpPathName)
+DWORD GetTempPathM(DWORD nBufferLength, LPSTR lpBuffer)
 {
-       BOOL r = FALSE;
+       DWORD r = 0;
        wchar_t* pw0 = NULL;
 START_ROUTINE
-       pw0 = DuplicateMtoW(lpPathName, -1);
-       r = SetDllDirectoryW(pw0);
+       pw0 = AllocateStringW(nBufferLength * 4);
+       GetTempPathW(nBufferLength * 4, pw0);
+       WtoM(lpBuffer, nBufferLength, pw0, -1);
+       r = TerminateStringM(lpBuffer, nBufferLength);
 END_ROUTINE
        FreeDuplicatedString(pw0);
        return r;
@@ -733,13 +1072,39 @@ LSTATUS RegQueryValueExM(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDW
 {
        LSTATUS r = 0;
        wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+       DWORD dwType;
+       DWORD wcbData;
 START_ROUTINE
        pw0 = DuplicateMtoW(lpValueName, -1);
-       // TODO: \83\8c\83W\83X\83g\83\8a\82ÍUTF-8\82Å\95Û\91\82³\82ê\82Ä\82µ\82Ü\82¤\81i\88È\91O\82Ì\83o\81[\83W\83\87\83\93\82Æ\8cÝ\8a·\90«\82È\82µ\81j
-       // UTF-16\82Å\95Û\91\82·\82é\82×\82«
-       r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
+       if(RegQueryValueExW(hKey, pw0, NULL, &dwType, NULL, 0) == ERROR_SUCCESS)
+       {
+               switch(dwType)
+               {
+               case REG_SZ:
+               case REG_EXPAND_SZ:
+               case REG_MULTI_SZ:
+                       if(lpcbData)
+                       {
+                               pw1 = AllocateStringW(*lpcbData / sizeof(char) * 4);
+                               wcbData = *lpcbData / sizeof(char) * 4;
+                               r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, (LPBYTE)pw1, &wcbData);
+                               if(lpData)
+                                       *lpcbData = sizeof(char) * WtoM((char*)lpData, *lpcbData / sizeof(char), pw1, wcbData / sizeof(wchar_t));
+                               else
+                                       *lpcbData = sizeof(char) * WtoM(NULL, 0, pw1, wcbData / sizeof(wchar_t));
+                       }
+                       break;
+               default:
+                       r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
+                       break;
+               }
+       }
+       else
+               r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, lpData, lpcbData);
 END_ROUTINE
        FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
        return r;
 }
 
@@ -747,13 +1112,27 @@ LSTATUS RegSetValueExM(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwTy
 {
        LSTATUS r = 0;
        wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+       DWORD wcbData;
 START_ROUTINE
        pw0 = DuplicateMtoW(lpValueName, -1);
-       // TODO: \83\8c\83W\83X\83g\83\8a\82ÍUTF-8\82Å\95Û\91\82³\82ê\82Ä\82µ\82Ü\82¤\81i\88È\91O\82Ì\83o\81[\83W\83\87\83\93\82Æ\8cÝ\8a·\90«\82È\82µ\81j
-       // UTF-16\82Å\95Û\91\82·\82é\82×\82«
+       switch(dwType)
+       {
+       case REG_SZ:
+       case REG_EXPAND_SZ:
+       case REG_MULTI_SZ:
+               wcbData = MtoW(NULL, 0, (char*)lpData, cbData / sizeof(char));
+               pw1 = AllocateStringW(wcbData);
+               MtoW(pw1, wcbData, (char*)lpData, cbData / sizeof(char));
+               wcbData = sizeof(wchar_t) * wcbData;
+               lpData = (BYTE*)pw1;
+               cbData = wcbData;
+               break;
+       }
        r = RegSetValueExW(hKey, pw0, Reserved, dwType, lpData, cbData);
 END_ROUTINE
        FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
        return r;
 }
 
@@ -798,56 +1177,79 @@ START_ROUTINE
                a0.hIcon = v0->hIcon;
        a0.pszCaption = DuplicateMtoW(v0->pszCaption, -1);
        a0.nPages = v0->nPages;
-       a0.pStartPage = DuplicateMtoW(v0->pStartPage, -1);
-       if(v0->ppsp && (pwPage = (PROPSHEETPAGEW*)malloc(sizeof(PROPSHEETPAGEW) * v0->nPages)))
+       if(v0->dwFlags & PSH_USEPSTARTPAGE)
+               a0.pStartPage = DuplicateMtoW(v0->pStartPage, -1);
+       else
+               a0.nStartPage = v0->nStartPage;
+       if(v0->dwFlags & PSH_PROPSHEETPAGE)
        {
-               for(i = 0; i < v0->nPages; i++)
+               if(v0->ppsp && (pwPage = (PROPSHEETPAGEW*)malloc(sizeof(PROPSHEETPAGEW) * v0->nPages)))
                {
-                       pwPage[i].dwSize = sizeof(PROPSHEETPAGEW);
-                       pwPage[i].dwFlags = v0->ppsp[i].dwFlags;
-                       pwPage[i].hInstance = v0->ppsp[i].hInstance;
-                       pwPage[i].pszTemplate = DuplicateMtoW(v0->ppsp[i].pszTemplate, -1);
-                       if(v0->ppsp[i].dwFlags & PSP_USEICONID)
-                               pwPage[i].pszIcon = DuplicateMtoW(v0->ppsp[i].pszIcon, -1);
-                       else
-                               pwPage[i].hIcon = v0->ppsp[i].hIcon;
-                       if(v0->ppsp[i].dwFlags & PSP_USETITLE)
-                               pwPage[i].pszTitle = DuplicateMtoW(v0->ppsp[i].pszTitle, -1);
-                       pwPage[i].pfnDlgProc = v0->ppsp[i].pfnDlgProc;
-                       pwPage[i].lParam = v0->ppsp[i].lParam;
-                       // TODO: pfnCallback
-                       pwPage[i].pfnCallback = v0->ppsp[i].pfnCallback;
-                       pwPage[i].pcRefParent = v0->ppsp[i].pcRefParent;
-//                     pwPage[i].pszHeaderTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderTitle, -1);
-//                     pwPage[i].pszHeaderSubTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderSubTitle, -1);
-                       pwPage[i].hActCtx = v0->ppsp[i].hActCtx;
-//                     pwPage[i].pszbmHeader = DuplicateMtoW(v0->ppsp[i].pszbmHeader, -1);
+                       for(i = 0; i < v0->nPages; i++)
+                       {
+                               pwPage[i].dwSize = sizeof(PROPSHEETPAGEW);
+                               pwPage[i].dwFlags = v0->ppsp[i].dwFlags;
+                               pwPage[i].hInstance = v0->ppsp[i].hInstance;
+                               if(v0->ppsp[i].dwFlags & PSP_DLGINDIRECT)
+                                       pwPage[i].pResource = v0->ppsp[i].pResource;
+                               else
+                                       pwPage[i].pszTemplate = DuplicateMtoW(v0->ppsp[i].pszTemplate, -1);
+                               if(v0->ppsp[i].dwFlags & PSP_USEICONID)
+                                       pwPage[i].pszIcon = DuplicateMtoW(v0->ppsp[i].pszIcon, -1);
+                               else
+                                       pwPage[i].hIcon = v0->ppsp[i].hIcon;
+                               if(v0->ppsp[i].dwFlags & PSP_USETITLE)
+                                       pwPage[i].pszTitle = DuplicateMtoW(v0->ppsp[i].pszTitle, -1);
+                               pwPage[i].pfnDlgProc = v0->ppsp[i].pfnDlgProc;
+                               pwPage[i].lParam = v0->ppsp[i].lParam;
+                               // TODO: pfnCallback
+                               pwPage[i].pfnCallback = (LPFNPSPCALLBACKW)v0->ppsp[i].pfnCallback;
+                               pwPage[i].pcRefParent = v0->ppsp[i].pcRefParent;
+                               if(v0->ppsp[i].dwFlags & PSP_USEHEADERTITLE)
+                                       pwPage[i].pszHeaderTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderTitle, -1);
+                               if(v0->ppsp[i].dwFlags & PSP_USEHEADERSUBTITLE)
+                                       pwPage[i].pszHeaderSubTitle = DuplicateMtoW(v0->ppsp[i].pszHeaderSubTitle, -1);
+                       }
                }
+               else
+                       pwPage = NULL;
+               a0.ppsp = pwPage;
        }
        else
-               pwPage = NULL;
-       a0.ppsp = pwPage;
+               a0.phpage = v0->phpage;
        a0.pfnCallback = v0->pfnCallback;
+       if(v0->dwFlags & PSH_USEHBMWATERMARK)
+               a0.hbmWatermark = v0->hbmWatermark;
+       else
+               a0.pszbmWatermark = DuplicateMtoW(v0->pszbmWatermark, -1);
        r = PropertySheetW(&a0);
        if(a0.dwFlags & PSH_USEICONID)
-               FreeDuplicatedString(a0.pszIcon);
-       FreeDuplicatedString(a0.pszCaption);
-       FreeDuplicatedString(a0.pStartPage);
-       if(pwPage)
+               FreeDuplicatedString((void*)a0.pszIcon);
+       FreeDuplicatedString((void*)a0.pszCaption);
+       if(v0->dwFlags & PSH_USEPSTARTPAGE)
+               FreeDuplicatedString((void*)a0.pStartPage);
+       if(v0->dwFlags & PSH_PROPSHEETPAGE)
        {
-               for(i = 0; i < v0->nPages; i++)
+               if(pwPage)
                {
-                       FreeDuplicatedString(pwPage[i].pszTemplate);
-                       if(pwPage[i].dwFlags & PSP_USEICONID)
-                               FreeDuplicatedString(pwPage[i].pszIcon);
-                       if(pwPage[i].dwFlags & PSP_USETITLE)
-                               FreeDuplicatedString(pwPage[i].pszTitle);
-//                     FreeDuplicatedString(pwPage[i].pszHeaderTitle);
-//                     FreeDuplicatedString(pwPage[i].pszHeaderSubTitle);
-//                     FreeDuplicatedString(pwPage[i].pszbmHeader);
+                       for(i = 0; i < v0->nPages; i++)
+                       {
+                               if(!(v0->ppsp[i].dwFlags & PSP_DLGINDIRECT))
+                                       FreeDuplicatedString((void*)pwPage[i].pszTemplate);
+                               if(v0->ppsp[i].dwFlags & PSP_USEICONID)
+                                       FreeDuplicatedString((void*)pwPage[i].pszIcon);
+                               if(v0->ppsp[i].dwFlags & PSP_USETITLE)
+                                       FreeDuplicatedString((void*)pwPage[i].pszTitle);
+                               if(v0->ppsp[i].dwFlags & PSP_USEHEADERTITLE)
+                                       FreeDuplicatedString((void*)pwPage[i].pszHeaderTitle);
+                               if(v0->ppsp[i].dwFlags & PSP_USEHEADERSUBTITLE)
+                                       FreeDuplicatedString((void*)pwPage[i].pszHeaderSubTitle);
+                       }
+                       free(pwPage);
                }
-               free(pwPage);
        }
+       if(!(v0->dwFlags & PSH_USEHBMWATERMARK))
+               FreeDuplicatedString((void*)a0.pszbmWatermark);
 END_ROUTINE
        return r;
 }
@@ -974,7 +1376,7 @@ END_ROUTINE
 
 HWND HtmlHelpM(HWND hwndCaller, LPCSTR pszFile, UINT uCommand, DWORD_PTR dwData)
 {
-       HINSTANCE r = NULL;
+       HWND r = NULL;
        wchar_t* pw0 = NULL;
 START_ROUTINE
        pw0 = DuplicateMtoW(pszFile, -1);
@@ -984,6 +1386,76 @@ END_ROUTINE
        return r;
 }
 
+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)
+{
+       BOOL r = FALSE;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+       wchar_t* pw2 = NULL;
+       wchar_t* pw3 = NULL;
+       wchar_t* pw4 = NULL;
+       wchar_t* pw5 = NULL;
+       STARTUPINFOW wStartupInfo;
+START_ROUTINE
+       pw0 = DuplicateMtoW(lpApplicationName, -1);
+       pw1 = DuplicateMtoWBuffer(lpCommandLine, -1, (strlen(lpCommandLine) + 1) * 4);
+       pw2 = DuplicateMtoW(lpCurrentDirectory, -1);
+       wStartupInfo.cb = sizeof(LPSTARTUPINFOW);
+       pw3 = DuplicateMtoW(lpStartupInfo->lpReserved, -1);
+       wStartupInfo.lpReserved = pw3;
+       pw4 = DuplicateMtoW(lpStartupInfo->lpDesktop, -1);
+       wStartupInfo.lpDesktop = pw4;
+       pw5 = DuplicateMtoW(lpStartupInfo->lpTitle, -1);
+       wStartupInfo.lpTitle = pw5;
+       wStartupInfo.dwX = lpStartupInfo->dwX;
+       wStartupInfo.dwY = lpStartupInfo->dwY;
+       wStartupInfo.dwXSize = lpStartupInfo->dwXSize;
+       wStartupInfo.dwYSize = lpStartupInfo->dwYSize;
+       wStartupInfo.dwXCountChars = lpStartupInfo->dwXCountChars;
+       wStartupInfo.dwYCountChars = lpStartupInfo->dwYCountChars;
+       wStartupInfo.dwFillAttribute = lpStartupInfo->dwFillAttribute;
+       wStartupInfo.dwFlags = lpStartupInfo->dwFlags;
+       wStartupInfo.wShowWindow = lpStartupInfo->wShowWindow;
+       wStartupInfo.cbReserved2 = lpStartupInfo->cbReserved2;
+       wStartupInfo.lpReserved2 = lpStartupInfo->lpReserved2;
+       wStartupInfo.hStdInput = lpStartupInfo->hStdInput;
+       wStartupInfo.hStdOutput = lpStartupInfo->hStdOutput;
+       wStartupInfo.hStdError = lpStartupInfo->hStdError;
+       r = CreateProcessW(pw0, pw1, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, pw2, &wStartupInfo, lpProcessInformation);
+       WtoM(lpCommandLine, strlen(lpCommandLine) + 1, pw1, -1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       FreeDuplicatedString(pw2);
+       FreeDuplicatedString(pw3);
+       FreeDuplicatedString(pw4);
+       FreeDuplicatedString(pw5);
+       return r;
+}
+
+HINSTANCE FindExecutableM(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
+{
+       HINSTANCE r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+       wchar_t* pw2 = NULL;
+       wchar_t* pw3 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(lpFile, -1);
+       pw1 = DuplicateMtoW(lpDirectory, -1);
+       pw2 = AllocateStringW(MAX_PATH * 4);
+       r = FindExecutableW(pw0, pw1, pw2);
+       // バッファ長不明のためオーバーランの可能性あり
+       WtoM(lpResult, MAX_PATH, pw2, -1);
+       TerminateStringM(lpResult, MAX_PATH);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       FreeDuplicatedString(pw2);
+       FreeDuplicatedString(pw3);
+       return r;
+}
+
 HINSTANCE ShellExecuteM(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
 {
        HINSTANCE r = NULL;
@@ -1024,7 +1496,7 @@ START_ROUTINE
        wbi.lParam = lpbi->lParam;
        wbi.iImage = lpbi->iImage;
        r = SHBrowseForFolderW(&wbi);
-       // \83o\83b\83t\83@\92·\95s\96¾\82Ì\82½\82ß\83I\81[\83o\81[\83\89\83\93\82Ì\89Â\94\\90«\82 \82è
+       // バッファ長不明のためオーバーランの可能性あり
        WtoM(lpbi->pszDisplayName, MAX_PATH, wbi.pszDisplayName, -1);
        lpbi->iImage = wbi.iImage;
 END_ROUTINE
@@ -1040,7 +1512,7 @@ BOOL SHGetPathFromIDListM(PCIDLIST_ABSOLUTE pidl, LPSTR pszPath)
 START_ROUTINE
        pw0 = AllocateStringW(MAX_PATH * 4);
        r = SHGetPathFromIDListW(pidl, pw0);
-       // \83o\83b\83t\83@\92·\95s\96¾\82Ì\82½\82ß\83I\81[\83o\81[\83\89\83\93\82Ì\89Â\94\\90«\82 \82è
+       // バッファ長不明のためオーバーランの可能性あり
        WtoM(pszPath, MAX_PATH, pw0, -1);
        TerminateStringM(pszPath, MAX_PATH);
 END_ROUTINE
@@ -1065,7 +1537,8 @@ START_ROUTINE
        wFileOp.fFlags = lpFileOp->fFlags;
        wFileOp.fAnyOperationsAborted = lpFileOp->fAnyOperationsAborted;
        wFileOp.hNameMappings = lpFileOp->hNameMappings;
-       pw2 = DuplicateMtoW(lpFileOp->lpszProgressTitle, -1);
+       if(lpFileOp->fFlags & FOF_SIMPLEPROGRESS)
+               pw2 = DuplicateMtoW(lpFileOp->lpszProgressTitle, -1);
        r = SHFileOperationW(&wFileOp);
        lpFileOp->fAnyOperationsAborted = wFileOp.fAnyOperationsAborted;
 END_ROUTINE
@@ -1107,9 +1580,13 @@ START_ROUTINE
        wmii.hbmpChecked = lpmii->hbmpChecked;
        wmii.hbmpUnchecked = lpmii->hbmpUnchecked;
        wmii.dwItemData = lpmii->dwItemData;
-       pw0 = DuplicateMtoWBuffer(lpmii->dwTypeData, -1, lpmii->cch * 4);
-       wmii.dwTypeData = pw0;
-       wmii.cch = lpmii->cch * 4;
+       if(lpmii->fMask & MIIM_TYPE)
+       {
+               pw0 = DuplicateMtoWBuffer(lpmii->dwTypeData, -1, lpmii->cch * 4);
+               wmii.dwTypeData = pw0;
+               wmii.cch = lpmii->cch * 4;
+       }
+       wmii.hbmpItem = lpmii->hbmpItem;
        r = GetMenuItemInfoW(hmenu, item, fByPosition, &wmii);
        lpmii->fType = wmii.fType;
        lpmii->fState = wmii.fState;
@@ -1217,17 +1694,259 @@ START_ROUTINE
        v0->nFontType = a0.nFontType;
        if(pwlf)
                free(pwlf);
-       FreeDuplicatedString(a0.lpTemplateName);
+       FreeDuplicatedString((void*)a0.lpTemplateName);
        FreeDuplicatedString(a0.lpszStyle);
 END_ROUTINE
        FreeDuplicatedString(pw0);
        return r;
 }
 
+INT_PTR DialogBoxParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+       INT_PTR r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(lpTemplateName, -1);
+       r = DialogBoxParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+HWND CreateDialogParamM(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+       HWND r = NULL;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(lpTemplateName, -1);
+       r = CreateDialogParamW(hInstance, pw0, hWndParent, lpDialogFunc, dwInitParam);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+int mkdirM(const char * _Path)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Path, -1);
+       r = _wmkdir(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+int _mkdirM(const char * _Path)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Path, -1);
+       r = _wmkdir(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+int rmdirM(const char * _Path)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Path, -1);
+       r = _wrmdir(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+int _rmdirM(const char * _Path)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Path, -1);
+       r = _wrmdir(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+size_t _mbslenM(const unsigned char * _Str)
+{
+       size_t r = 0;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str, -1);
+       r = wcslen(pw0);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* wr;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str, -1);
+       // TODO: 非ASCII文字の対応
+       wr = wcschr(pw0, _Ch);
+       if(wr)
+       {
+               *wr = L'\0';
+               r = (unsigned char*)_Str + WtoM(NULL, 0, pw0, -1) - 1;
+       }
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
 
+unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* wr;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str, -1);
+       // TODO: 非ASCII文字の対応
+       wr = wcsrchr(pw0, _Ch);
+       if(wr)
+       {
+               *wr = L'\0';
+               r = (unsigned char*)_Str + WtoM(NULL, 0, pw0, -1) - 1;
+       }
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
 
+unsigned char * _mbsstrM(const unsigned char * _Str, const unsigned char * _Substr)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+       wchar_t* wr;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str, -1);
+       pw1 = DuplicateMtoW(_Substr, -1);
+       wr = wcsstr(pw0, pw1);
+       if(wr)
+       {
+               *wr = L'\0';
+               r = (unsigned char*)_Str + WtoM(NULL, 0, pw0, -1) - 1;
+       }
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       return r;
+}
 
+int _mbscmpM(const unsigned char * _Str1, const unsigned char * _Str2)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str1, -1);
+       pw1 = DuplicateMtoW(_Str2, -1);
+       r = wcscmp(pw0, pw1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       return r;
+}
 
+int _mbsicmpM(const unsigned char * _Str1, const unsigned char * _Str2)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str1, -1);
+       pw1 = DuplicateMtoW(_Str2, -1);
+       r = _wcsicmp(pw0, pw1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       return r;
+}
+
+int _mbsncmpM(const unsigned char * _Str1, const unsigned char * _Str2, size_t _MaxCount)
+{
+       int r = 0;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str1, -1);
+       pw1 = DuplicateMtoW(_Str2, -1);
+       r = wcsncmp(pw0, pw1, _MaxCount);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       return r;
+}
+
+unsigned char * _mbslwrM(unsigned char * _String)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_String, -1);
+       _wcslwr(pw0);
+       r = _String;
+       WtoM(_String, strlen(_String) + 1, pw0, -1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
+
+unsigned char * _mbsuprM(unsigned char * _String)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_String, -1);
+       _wcsupr(pw0);
+       r = _String;
+       WtoM(_String, strlen(_String) + 1, pw0, -1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
 
+unsigned char * _mbsnincM(const unsigned char * _Str, size_t _Count)
+{
+       unsigned char* r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* wr;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Str, -1);
+       wr = _wcsninc(pw0, _Count);
+       if(wr)
+       {
+               *wr = L'\0';
+               r = (unsigned char*)_Str + WtoM(NULL, 0, pw0, -1) - 1;
+       }
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       return r;
+}
 
+FILE * fopenM(const char * _Filename, const char * _Mode)
+{
+       FILE* r = NULL;
+       wchar_t* pw0 = NULL;
+       wchar_t* pw1 = NULL;
+START_ROUTINE
+       pw0 = DuplicateMtoW(_Filename, -1);
+       pw1 = DuplicateMtoW(_Mode, -1);
+       r = _wfopen(pw0, pw1);
+END_ROUTINE
+       FreeDuplicatedString(pw0);
+       FreeDuplicatedString(pw1);
+       return r;
+}