OSDN Git Service

Fix bugs of UTF-8 to UTF-16 API bridge.
[ffftp/ffftp.git] / mbswrapper.c
index 337d9ff..585a26b 100644 (file)
@@ -1,8 +1,8 @@
-// mbswrapper.cpp
+// mbswrapper.cpp
 // 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 _UNICODE
@@ -20,7 +20,7 @@
 #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 || pSrc == (LPCSTR)~0)
@@ -30,7 +30,7 @@ int MtoW(LPWSTR pDst, int size, LPCSTR pSrc, int count)
        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 || pSrc == (LPCWSTR)~0)
@@ -40,7 +40,7 @@ int WtoM(LPSTR pDst, int size, LPCWSTR pSrc, int count)
        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 WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)
 {
        if(pSrc < (LPCWSTR)0x00010000 || pSrc == (LPCWSTR)~0)
@@ -50,7 +50,7 @@ int WtoA(LPSTR pDst, int size, LPCWSTR pSrc, int count)
        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;
@@ -66,7 +66,7 @@ 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;
@@ -82,7 +82,23 @@ 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;
@@ -97,7 +113,7 @@ 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;
@@ -112,7 +128,22 @@ size_t GetMultiStringLengthW(LPCWSTR lpString)
        return i;
 }
 
-// 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区切り複数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;
@@ -130,7 +161,7 @@ int MtoWMultiString(LPWSTR pDst, int size, LPCSTR pSrc)
        return i;
 }
 
-// NULL\8bæ\90Ø\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·
+// NULL区切りワイド文字列からマルチバイト文字列へ変換
 int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
 {
        int i;
@@ -148,7 +179,7 @@ int WtoMMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
        return i;
 }
 
-// NULL\8bæ\90Ø\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·
+// NULL区切りワイド文字列からShift_JIS文字列へ変換
 int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
 {
        int i;
@@ -166,43 +197,43 @@ int WtoAMultiString(LPSTR pDst, int size, LPCWSTR pSrc)
        return i;
 }
 
-// \83}\83\8b\83`\83o\83C\83g\95\8e\9a\97ñ\97p\82Ì\83\81\83\82\83\8a\82ð\8am\95Û
+// マルチバイト文字列用のメモリを確保
 char* AllocateStringM(int size)
 {
        char* p;
-       // 0\82ª\8ew\92è\82³\82ê\82é\8fê\8d\87\82ª\82 \82é\82½\82ß1\95\8e\9a\95ª\92Ç\89Á
+       // 0が指定される場合があるため1文字分追加
        p = (char*)malloc(sizeof(char) * (size + 1));
-       // \94O\82Ì\82½\82ß\90æ\93ª\82ÉNULL\95\8e\9a\82ð\91ã\93ü
+       // 念のため先頭に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;
-       // 0\82ª\8ew\92è\82³\82ê\82é\8fê\8d\87\82ª\82 \82é\82½\82ß1\95\8e\9a\95ª\92Ç\89Á
+       // 0が指定される場合があるため1文字分追加
        p = (wchar_t*)malloc(sizeof(wchar_t) * (size + 1));
-       // \94O\82Ì\82½\82ß\90æ\93ª\82ÉNULL\95\8e\9a\82ð\91ã\93ü
+       // 念のため先頭に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;
-       // 0\82ª\8ew\92è\82³\82ê\82é\8fê\8d\87\82ª\82 \82é\82½\82ß1\95\8e\9a\95ª\92Ç\89Á
+       // 0が指定される場合があるため1文字分追加
        p = (char*)malloc(sizeof(char) * (size + 1));
-       // \94O\82Ì\82½\82ß\90æ\93ª\82ÉNULL\95\8e\9a\82ð\91ã\93ü
+       // 念のため先頭に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·
+// メモリを確保してマルチバイト文字列からワイド文字列へ変換
 wchar_t* DuplicateMtoW(LPCSTR lpString, int c)
 {
        wchar_t* p;
@@ -220,7 +251,7 @@ 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·
+// 指定したサイズのメモリを確保してマルチバイト文字列からワイド文字列へ変換
 wchar_t* DuplicateMtoWBuffer(LPCSTR lpString, int c, int size)
 {
        wchar_t* p;
@@ -238,7 +269,7 @@ 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区切りマルチバイト文字列からワイド文字列へ変換
 wchar_t* DuplicateMtoWMultiString(LPCSTR lpString)
 {
        int count;
@@ -252,7 +283,7 @@ 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区切りマルチバイト文字列からワイド文字列へ変換
 wchar_t* DuplicateMtoWMultiStringBuffer(LPCSTR lpString, int size)
 {
        int count;
@@ -270,7 +301,7 @@ 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·
+// メモリを確保してワイド文字列からマルチバイト文字列へ変換
 char* DuplicateWtoM(LPCWSTR lpString, int c)
 {
        char* p;
@@ -288,7 +319,7 @@ 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文字列へ変換
 char* DuplicateWtoA(LPCWSTR lpString, int c)
 {
        char* p;
@@ -306,7 +337,7 @@ 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ú
+// 文字列用に確保したメモリを開放
 void FreeDuplicatedString(void* p)
 {
        if(p < (void*)0x00010000 || p == (void*)~0)
@@ -314,16 +345,28 @@ void FreeDuplicatedString(void* p)
        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
 
 #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;
+}
+
 HANDLE CreateFileM(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
 {
        HANDLE r = INVALID_HANDLE_VALUE;
@@ -418,7 +461,7 @@ ATOM RegisterClassExM(CONST WNDCLASSEXA * v0)
 {
        ATOM r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        r = RegisterClassExA(v0);
 END_ROUTINE
        return r;
@@ -443,7 +486,7 @@ LONG GetWindowLongM(HWND hWnd, int nIndex)
 {
        LRESULT r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        if(IsWindowUnicode(hWnd))
                r = GetWindowLongW(hWnd, nIndex);
        else
@@ -456,7 +499,7 @@ LONG SetWindowLongM(HWND hWnd, int nIndex, LONG dwNewLong)
 {
        LRESULT r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        if(IsWindowUnicode(hWnd))
                r = SetWindowLongW(hWnd, nIndex, dwNewLong);
        else
@@ -469,7 +512,7 @@ LRESULT DefWindowProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
        LRESULT r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        if(IsWindowUnicode(hWnd))
                r = DefWindowProcW(hWnd, Msg, wParam, lParam);
        else
@@ -482,7 +525,7 @@ LRESULT CallWindowProcM(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wPara
 {
        LRESULT r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        if(IsWindowUnicode(hWnd))
                r = CallWindowProcW(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
        else
@@ -518,7 +561,7 @@ 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;
@@ -550,7 +593,7 @@ START_ROUTINE
                                Size = SendMessageW(hWnd, CB_GETLBTEXTLEN, wParam, 0) + 1;
                                pw0 = AllocateStringW(Size);
                                SendMessageW(hWnd, CB_GETLBTEXT, 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;
@@ -589,7 +632,7 @@ START_ROUTINE
                                Size = SendMessageW(hWnd, LB_GETTEXTLEN, wParam, 0) + 1;
                                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;
@@ -651,7 +694,7 @@ START_ROUTINE
                                {
                                        pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
                                        wLVItem.pszText = pw0;
-                                       // TODO: cchTextMax\82Ì\8am\94F
+                                       // TODO: cchTextMaxの確認
                                        wLVItem.cchTextMax = pmLVItem->cchTextMax;
                                }
                                wLVItem.iImage = pmLVItem->iImage;
@@ -670,7 +713,7 @@ START_ROUTINE
                                {
                                        pw0 = DuplicateMtoW(pmLVItem->pszText, -1);
                                        wLVItem.pszText = pw0;
-                                       // TODO: cchTextMax\82Ì\8am\94F
+                                       // TODO: cchTextMaxの確認
                                        wLVItem.cchTextMax = pmLVItem->cchTextMax;
                                }
                                wLVItem.iImage = pmLVItem->iImage;
@@ -728,7 +771,7 @@ START_ROUTINE
                                {
                                        pw0 = DuplicateMtoW(pmLVColumn->pszText, -1);
                                        wLVColumn.pszText = pw0;
-                                       // TODO: cchTextMax\82Ì\8am\94F
+                                       // TODO: cchTextMaxの確認
                                        wLVColumn.cchTextMax = pmLVColumn->cchTextMax;
                                }
                                wLVColumn.iSubItem = pmLVColumn->iSubItem;
@@ -794,7 +837,7 @@ LRESULT DefDlgProcM(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
        LRESULT r = 0;
 START_ROUTINE
-       // WNDPROC\82ªShift_JIS\97p\82Å\82 \82é\82½\82ß
+       // WNDPROCがShift_JIS用であるため
        if(IsWindowUnicode(hWnd))
                r = DefDlgProcW(hWnd, Msg, wParam, lParam);
        else
@@ -976,12 +1019,15 @@ START_ROUTINE
                case REG_SZ:
                case REG_EXPAND_SZ:
                case REG_MULTI_SZ:
-                       if(lpData && lpcbData)
+                       if(lpcbData)
                        {
                                pw1 = AllocateStringW(*lpcbData / sizeof(char) * 4);
                                wcbData = *lpcbData / sizeof(char) * 4;
                                r = RegQueryValueExW(hKey, pw0, lpReserved, lpType, (LPBYTE)pw1, &wcbData);
-                               *lpcbData = sizeof(char) * WtoM((char*)lpData, *lpcbData / sizeof(char), pw1, wcbData / sizeof(wchar_t));
+                               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:
@@ -1311,7 +1357,7 @@ START_ROUTINE
        pw1 = DuplicateMtoW(lpDirectory, -1);
        pw2 = AllocateStringW(MAX_PATH * 4);
        r = FindExecutableW(pw0, pw1, pw2);
-       // \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(lpResult, MAX_PATH, pw2, -1);
        TerminateStringM(lpResult, MAX_PATH);
 END_ROUTINE
@@ -1362,7 +1408,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
@@ -1378,7 +1424,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
@@ -1653,7 +1699,7 @@ unsigned char * _mbschrM(const unsigned char * _Str, unsigned int _Ch)
        wchar_t* wr;
 START_ROUTINE
        pw0 = DuplicateMtoW(_Str, -1);
-       // TODO: \94ñASCII\95\8e\9a\82Ì\91Î\89\9e
+       // TODO: 非ASCII文字の対応
        wr = wcschr(pw0, _Ch);
        if(wr)
        {
@@ -1672,7 +1718,7 @@ unsigned char * _mbsrchrM(const unsigned char * _Str, unsigned int _Ch)
        wchar_t* wr;
 START_ROUTINE
        pw0 = DuplicateMtoW(_Str, -1);
-       // TODO: \94ñASCII\95\8e\9a\82Ì\91Î\89\9e
+       // TODO: 非ASCII文字の対応
        wr = wcsrchr(pw0, _Ch);
        if(wr)
        {
@@ -1796,3 +1842,18 @@ END_ROUTINE
        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;
+}
+