OSDN Git Service

最新のUnRAR.dllに対応。
[tpi/lychee.git] / src / plugin / rarArc / rarArc.cpp
index 11d199c..aa1f846 100644 (file)
@@ -38,58 +38,64 @@ wxDynamicLibrary g_hLib;
 TPI_PROC g_prProc;\r
 char g_szComment[64001];\r
 RAROpenArchiveDataEx g_oaInfo;\r
-RARHeaderDataEx * g_hdInfo;\r
 \r
 //******************************************************************************\r
 //    Callback Wrapper\r
 //******************************************************************************\r
 \r
-int __stdcall CallbackProc(unsigned int msg, long, long P1, long P2)\r
+int __stdcall CallbackProc(unsigned int msg, long p, long P1, long P2)\r
 {\r
        // 構造体を初期化。\r
-       static TPI_PROCESSINFO piInfo;\r
+       static TPI_PROCESSINFO pi;\r
+       TPI_PROCESSINFO * piInfo = p == 0 ? & pi : (TPI_PROCESSINFO *) p;\r
 \r
        switch (msg)\r
        {\r
        case UCM_CHANGEVOLUME:\r
+       case UCM_CHANGEVOLUMEW:\r
                switch (P2)\r
                {\r
                case RAR_VOL_ASK:\r
                        // 分割書庫の次の部分を要求。\r
-                       piInfo.eMessage = TPI_MESSAGE_ASK;\r
-                       piInfo.eStatus  = TPI_PARAM_NEXTVOLUME;\r
-                       piInfo.szParam.Empty();\r
+                       piInfo->eMessage = TPI_MESSAGE_ASK;\r
+                       piInfo->eStatus  = TPI_PARAM_NEXTVOLUME;\r
+                       piInfo->szParam.Empty();\r
                        break;\r
                case RAR_VOL_NOTIFY:\r
                        // 分割部分の読み込みを開始。\r
-                       piInfo.eMessage = TPI_MESSAGE_STATUS;\r
-                       piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
-                       piInfo.fiInfo.fnFileName = wxFileName(UTF82String((char *) P1));\r
+                       piInfo->eMessage = TPI_MESSAGE_STATUS;\r
+                       piInfo->eStatus  = TPI_STATUS_OPENARCHIVE;\r
+                       piInfo->fiInfo.fnFileName = wxFileName(msg == UCM_CHANGEVOLUMEW ? WC2String((wchar_t *) P1) : UTF82String((char *) P1));\r
                        break;\r
                default:\r
-                       return 1;\r
+                       return 0;\r
                }\r
                break;\r
        case UCM_PROCESSDATA:\r
-               piInfo.eMessage = TPI_MESSAGE_STATUS;\r
-               piInfo.eStatus  = TPI_STATUS_INPROCESS;\r
-               piInfo.nProcessedSize += P2;\r
+               piInfo->eMessage = TPI_MESSAGE_STATUS;\r
+               piInfo->eStatus  = TPI_STATUS_INPROCESS;\r
+               piInfo->nProcessedSize += P2;\r
                break;\r
        case UCM_NEEDPASSWORD:\r
-               piInfo.eMessage = TPI_MESSAGE_ASK;\r
-               piInfo.eStatus  = TPI_PARAM_PASSWORD;\r
-               piInfo.szParam.Empty();\r
+       case UCM_NEEDPASSWORDW:\r
+               piInfo->eMessage = TPI_MESSAGE_ASK;\r
+               piInfo->eStatus  = TPI_PARAM_PASSWORD;\r
+               piInfo->szParam.Empty();\r
                break;\r
        default:\r
-               return 1;\r
+               return 0;\r
        }\r
 \r
        // コールバック関数に送信。\r
-       if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, piInfo) == TPI_CALLBACK_CONTINUE)\r
+       if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, piInfo) == TPI_CALLBACK_CONTINUE)\r
        {\r
-               if (msg != UCM_PROCESSDATA && P2 != RAR_VOL_NOTIFY)\r
+               if (msg == UCM_NEEDPASSWORDW || (msg == UCM_CHANGEVOLUMEW && P2 == RAR_VOL_ASK))\r
+               {\r
+                       wcsncpy((wchar_t *) P1, piInfo->szParam.wchar_str(), (msg == UCM_CHANGEVOLUMEW ? 1024 : P2) - 1);\r
+               }\r
+               if (msg == UCM_NEEDPASSWORD  || (msg == UCM_CHANGEVOLUME  && P2 == RAR_VOL_ASK))\r
                {\r
-                       strncpy((char *) P1, piInfo.szParam.char_str(), (msg == UCM_CHANGEVOLUME ? 1024 : P2) - 1);\r
+                       strncpy((char *)    P1, piInfo->szParam.char_str(),  (msg == UCM_CHANGEVOLUME  ? 1024 : P2) - 1);\r
                }\r
                return 1;\r
        }\r
@@ -122,6 +128,8 @@ int ErrorCodeConvert(int nErrorCode)
        case ERAR_SMALL_BUF:        return TPI_ERROR_UNDEFINED;\r
        case ERAR_UNKNOWN:          return TPI_ERROR_UNDEFINED;\r
        case ERAR_MISSING_PASSWORD: return TPI_ERROR_ARC_ENCRYPTED;\r
+       case ERAR_EREFERENCE:       return TPI_ERROR_UNDEFINED;\r
+       case ERAR_BAD_PASSWORD:     return TPI_ERROR_ARC_ENCRYPTED;\r
        default:                    return TPI_ERROR_UNDEFINED;\r
        }\r
 }\r
@@ -155,6 +163,9 @@ int __stdcall GetPluginInformation
        case TPI_INFO_VERSION_API:\r
                * (int *) _pPtr = 2;\r
                break;\r
+       case TPI_INFO_HANDLE_ON_COMMAND:\r
+               * (int *) _pPtr = 0;\r
+               break;\r
        default:\r
                return TPI_ERROR_D_UNSUPPORTED;\r
        }\r
@@ -187,17 +198,23 @@ int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)
 int __stdcall LoadPlugin\r
 (\r
        const wxString &,\r
+       TPI_PROC _prProc,\r
        wxULongLong_t\r
 )\r
 {\r
        ::RemoveCwdFromSearchPath();\r
-       g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")));\r
+       g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")), wxDL_QUIET);\r
        if (! g_hLib.IsLoaded())\r
        {\r
                g_hLib.Unload();\r
                return TPI_ERROR_U_LOAD_LIBRARY;\r
        }\r
 \r
+       // コールバック関数を設定。\r
+       if (_prProc != NULL)\r
+       {\r
+               g_prProc = * _prProc;\r
+       }\r
        return TPI_ERROR_SUCCESS;\r
 }\r
 \r
@@ -229,36 +246,16 @@ int __stdcall OpenArchive
 \r
        memset(& g_oaInfo, 0, sizeof(g_oaInfo));\r
        g_oaInfo.ArcName    = NULL;\r
+//     g_oaInfo.ArcNameW   = _szArcName.wchar_str();\r
        g_oaInfo.ArcNameW   = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));\r
        wcscpy(g_oaInfo.ArcNameW, _szArcName.wchar_str());\r
-       g_oaInfo.OpenMode   = RAR_OM_EXTRACT;\r
+       g_oaInfo.OpenMode   = RAR_OM_LIST;\r
        g_oaInfo.CmtBuf     = g_szComment;\r
        g_oaInfo.CmtBufSize = sizeof(g_szComment) - 1;\r
+       g_oaInfo.Callback   = CallbackProc;\r
        * _hArchive = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& g_oaInfo);\r
        free(g_oaInfo.ArcNameW);\r
-       if (* _hArchive == NULL)\r
-       {\r
-               return TPI_ERROR_UNDEFINED;\r
-       }\r
-       int nErrorCode = ErrorCodeConvert(g_oaInfo.OpenResult);\r
-       if (nErrorCode != TPI_ERROR_SUCCESS)\r
-       {\r
-               return nErrorCode;\r
-       }\r
-\r
-       // コールバック関数を設定。\r
-       if (! g_hLib.HasSymbol(wxT("RARSetCallback")))\r
-       {\r
-               return TPI_ERROR_U_USE_LIBRARY;\r
-       }\r
-       p = g_hLib.GetSymbol(wxT("RARSetCallback"));\r
-       if (! p)\r
-       {\r
-               return TPI_ERROR_U_USE_LIBRARY;\r
-       }\r
-       ((void (__stdcall *)(void *, void *, long)) p)(* _hArchive, (void *) CallbackProc, (long) & g_hdInfo);\r
-\r
-       return TPI_ERROR_SUCCESS;\r
+       return * _hArchive == NULL ? TPI_ERROR_UNDEFINED : ErrorCodeConvert(g_oaInfo.OpenResult);\r
 }\r
 \r
 int __stdcall CloseArchive\r
@@ -289,7 +286,7 @@ int __stdcall GetFileInformation
        {\r
                s_nFileId = 0;\r
                pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL;\r
-               pP = g_hLib.HasSymbol(wxT("RARProcessFileW"))  ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
+               pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
                if (! pR || ! pP)\r
                {\r
                        return TPI_ERROR_U_USE_LIBRARY;\r
@@ -303,7 +300,14 @@ int __stdcall GetFileInformation
        nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(_hArchive, & hdInfo));\r
        if (nErrorCode == TPI_ERROR_SUCCESS)\r
        {\r
-               _fiInfo->dwAttribute    = hdInfo.FileAttr;\r
+               if (hdInfo.HostOS == 3)\r
+               {\r
+                       _fiInfo->wPermission = hdInfo.FileAttr;\r
+               }\r
+               else\r
+               {\r
+                       _fiInfo->dwAttribute = hdInfo.FileAttr;\r
+               }\r
                if (hdInfo.Flags & 0x04)\r
                {\r
                        _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
@@ -315,7 +319,7 @@ int __stdcall GetFileInformation
                _fiInfo->nUnpackedSize  = hdInfo.UnpSizeHigh;\r
                _fiInfo->nUnpackedSize  = _fiInfo->nUnpackedSize << 32;\r
                _fiInfo->nUnpackedSize += hdInfo.UnpSize;\r
-               _fiInfo->tmModified.SetFromDOS(hdInfo.FileTime);\r
+               _fiInfo->tmModify.SetFromDOS(hdInfo.FileTime);\r
                _fiInfo->eOSType        = hdInfo.HostOS;\r
                _fiInfo->szStoredName   = WC2String(hdInfo.FileNameW);\r
                _fiInfo->szMethod.Printf(wxT("%x"), hdInfo.Method);\r
@@ -347,7 +351,7 @@ int __stdcall Command
 (\r
        wxULongLong_t _eCommand,\r
        TPI_SWITCHES * _swInfo,\r
-       const wxString & _szArcName,\r
+       void *,// _hArchive,\r
        const wxArrayString & _szFiles\r
 )\r
 {\r
@@ -357,8 +361,41 @@ int __stdcall Command
        }\r
 \r
        // 開きなおす。\r
-       void * hArc;\r
-       int nErrorCode = OpenArchive(_szArcName, & hArc);\r
+       if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))\r
+       {\r
+               return TPI_ERROR_U_USE_LIBRARY;\r
+       }\r
+       void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));\r
+       if (! p)\r
+       {\r
+               return TPI_ERROR_U_USE_LIBRARY;\r
+       }\r
+\r
+       TPI_PROCESSINFO piInfo;\r
+       piInfo.eMessage = TPI_MESSAGE_STATUS;\r
+       piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
+       piInfo.fiInfo.fnFileName = wxFileName(_swInfo->szArcName);\r
+       if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
+       {\r
+               return TPI_ERROR_D_SKIPPED;\r
+       }\r
+       RAROpenArchiveDataEx oaInfo;\r
+       memset(& oaInfo, 0, sizeof(oaInfo));\r
+       oaInfo.ArcName    = NULL;\r
+//     oaInfo.ArcNameW   = _swInfo->szArcName.wchar_str();\r
+       oaInfo.ArcNameW   = (wchar_t *) malloc((_swInfo->szArcName.Len() + 1) * sizeof(wchar_t));\r
+       wcscpy(oaInfo.ArcNameW, _swInfo->szArcName.wchar_str());\r
+       oaInfo.OpenMode   = RAR_OM_EXTRACT;\r
+       oaInfo.CmtBufSize = 0;\r
+       oaInfo.Callback   = CallbackProc;\r
+       oaInfo.UserData   = (long) & piInfo;\r
+       void * hArc = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& oaInfo);\r
+       free(oaInfo.ArcNameW);\r
+       if (hArc == NULL)\r
+       {\r
+               return TPI_ERROR_UNDEFINED;\r
+       }\r
+       int nErrorCode = ErrorCodeConvert(oaInfo.OpenResult);\r
        if (nErrorCode != TPI_ERROR_SUCCESS)\r
        {\r
                return nErrorCode;\r
@@ -370,6 +407,7 @@ int __stdcall Command
                * pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
        if (! pR || ! pP)\r
        {\r
+               CloseArchive(hArc);\r
                return TPI_ERROR_U_USE_LIBRARY;\r
        }\r
        if (pS)\r
@@ -378,38 +416,58 @@ int __stdcall Command
        }\r
 \r
        RARHeaderDataEx hdInfo;\r
-       g_hdInfo = & hdInfo;\r
        while (nErrorCode == TPI_ERROR_SUCCESS && ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(hArc, & hdInfo)) == TPI_ERROR_SUCCESS)\r
        {\r
-               nErrorCode =\r
-                       ErrorCodeConvert(\r
-                               ((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(\r
-                                       hArc,\r
-                                       (_szFiles.GetCount() != 0 && _szFiles.Index(wxString(hdInfo.FileNameW)) == wxNOT_FOUND) ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST,\r
-                                       _swInfo->fStoreDirectoryPathes ? _swInfo->fnDestinationDirectory.GetFullPath().wchar_str() : NULL,\r
-                                       _swInfo->fStoreDirectoryPathes ? NULL : (_swInfo->fnDestinationDirectory.GetPathWithSep() + wxFileName(hdInfo.FileNameW).GetFullName()).wchar_str()\r
-                               )\r
-                       );\r
+               piInfo.fiInfo.fnFileName     = wxFileName(WC2String(hdInfo.FileNameW));\r
+               piInfo.fnDestination         = wxFileName(_swInfo->fnDestinationDirectory.GetPathWithSep() + (_swInfo->fStoreDirectoryPathes ? piInfo.fiInfo.fnFileName.GetFullPath() : piInfo.fiInfo.fnFileName.GetFullName()));\r
+               bool bSkip = _szFiles.GetCount() != 0 && _szFiles.Index(piInfo.fiInfo.fnFileName.GetFullPath()) == wxNOT_FOUND;\r
+               if (! bSkip && _eCommand == TPI_COMMAND_EXTRACT)\r
+               {\r
+                       // 処理するかどうか確認。\r
+                       piInfo.eMessage = TPI_MESSAGE_ASK;\r
+                       piInfo.eStatus  = TPI_PARAM_DEST;\r
+                       piInfo.fiInfo.nUnpackedSize  = hdInfo.UnpSizeHigh;\r
+                       piInfo.fiInfo.nUnpackedSize  = piInfo.fiInfo.nUnpackedSize << 32;\r
+                       piInfo.fiInfo.nUnpackedSize += hdInfo.UnpSize;\r
+                       piInfo.fiInfo.tmModify.SetFromDOS(hdInfo.FileTime);\r
+                       if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
+                       {\r
+                               nErrorCode = TPI_ERROR_D_SKIPPED;\r
+                               break;\r
+                       }\r
+                       bSkip = ! piInfo.fnDestination.IsOk();\r
+               }\r
+\r
+               if (! bSkip)\r
+               {\r
+                       // 処理の開始を通知。\r
+                       piInfo.eMessage = TPI_MESSAGE_STATUS;\r
+                       piInfo.eStatus  = TPI_STATUS_BEGINPROCESS;\r
+                       if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
+                       {\r
+                               nErrorCode = TPI_ERROR_D_SKIPPED;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(hArc, bSkip ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST, NULL, piInfo.fnDestination.GetFullPath().wchar_str()));\r
+\r
+               if (! bSkip)\r
+               {\r
+                       // 処理の終了を通知。\r
+                       piInfo.eMessage = TPI_MESSAGE_STATUS;\r
+                       piInfo.eStatus  = TPI_STATUS_ENDPROCESS;\r
+                       if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) != TPI_CALLBACK_CONTINUE)\r
+                       {\r
+                               nErrorCode = TPI_ERROR_D_SKIPPED;\r
+                               break;\r
+                       }\r
+               }\r
        }\r
        CloseArchive(hArc);\r
        return nErrorCode;\r
 }\r
 \r
-int __stdcall SetCallbackProc\r
-(\r
-       TPI_PROC _prArcProc\r
-)\r
-{\r
-       // ポインタを保存。\r
-       if (_prArcProc == NULL)\r
-       {\r
-               return TPI_ERROR_D_PARAMETER;\r
-       }\r
-       g_prProc = * _prArcProc;\r
-\r
-       return TPI_ERROR_SUCCESS;\r
-}\r
-\r
 #ifdef __cplusplus\r
 }\r
 #endif\r