/* - ARcToy 1.40f 2002/03/23 - Written by S.Noda プログラムのコマンドライン引数を統合アーカイバ DLL に渡し、各種の書庫操作を行う。 C マガジン(1999年10月号)を参考にしました。 */ /* special thanks : shoda T. */ /* このファイルの利用条件: このソースファイルの利用制限は一切ありません。 ソースの一部、全部を商用、非商用など目的に かかわりなく他のプログラムで自由に使用できます。 パブリック・ドメイン・ソフトウェアと同様に扱えます。 プログラマ向けの要望(制限ではありません): ソース中に改善すべき点があればお知らせください。 ソースコード中にバグを見つけた場合は報告してください。 直した部分などありましたら教えてください。 断片的な情報でも結構です。 このファイルを利用した場合はなるべく教えてください。 */ /* LICENSE of this file: There is no restriction for using this file. You can use this file in your software for any purpose. In other words, you can use this file as Public Domain Software. RECOMMENDATION for Programmer(not restriction): If you find points to improve code, please report me. If you find bug in source code, please report me. If you fixed bug, please teach me. I want any trivial information. If you use this file, please report me. */ #include #include #include #include "unlha32.h" #define SPACECHAR ' ' #define DQUOTECHAR '\"' #define WILDNAME "*" #define BUFFSIZE (16 * 1024) // 16kB #define Number(arr) (sizeof(arr) / sizeof(arr[0])) #define OPENMODE M_REGARDLESS_INIT_FILE | M_RECOVERY_ON | M_ERROR_MESSAGE_ON #define CHECKMODE CHECKARCHIVE_RAPID | CHECKARCHIVE_RECOVERY | CHECKARCHIVE_ENDDATA #define DLLNAME lpszDLLName() #define MAINPROC lpszMainProc() #define GETVERSION lpszProc("GetVersion") #define GETRUNNING lpszProc("GetRunning") #define CHECKARCHIVE lpszProc("CheckArchive") #define QUERYFUNCTIONLIST lpszProc("QueryFunctionList") #define CONFIGDIALOG lpszProc("ConfigDialog") #define OPENARCHIVE lpszProc("OpenArchive") #define CLOSEARCHIVE lpszProc("CloseArchive") #define FINDFIRST lpszProc("FindFirst") #define FINDNEXT lpszProc("FindNext") #define GETARCFILENAME lpszProc("GetArcFileName") #define GETARCORIGINALSIZE lpszProc("GetArcOriginalSize") #define GETARCORIGINALSIZEEX lpszProc("GetArcOriginalSizeEx") #define GETARCRATIO lpszProc("GetArcRatio") #define GETARCDATE lpszProc("GetArcDate") #define GETARCTIME lpszProc("GetArcTime") #define GETARCWRITETIMEEX lpszProc("GetArcWriteTimeEx") #define GETARCOSTYPE lpszProc("GetArcOSType") #define ISSFXFILE lpszProc("IsSFXFile") #define GETFILENAME lpszProc("GetFileName") #define GETMETHOD lpszProc("GetMethod") #define GETORIGINALSIZE lpszProc("GetOriginalSize") #define GETORIGINALSIZEEX lpszProc("GetOriginalSizeEx") #define GETRATIO lpszProc("GetRatio") #define GETDATE lpszProc("GetDate") #define GETTIME lpszProc("GetTime") #define GETWRITETIME lpszProc("GetWriteTime") #define GETWRITETIMEEX lpszProc("GetWriteTimeEx") #define GETATTRIBUTE lpszProc("GetAttribute") #define GETOSTYPE lpszProc("GetOSType") typedef int (WINAPI * ARC_MAINPROC)(const HWND,LPCSTR,LPSTR,const DWORD); typedef WORD (WINAPI * ARC_GETVERSION)(VOID); typedef BOOL (WINAPI * ARC_GETRUNNING)(VOID); typedef BOOL (WINAPI * ARC_CHECKARCHIVE)(LPCSTR,const int); typedef BOOL (WINAPI * ARC_QUERYFUNCTIONLIST)(const int); typedef BOOL (WINAPI * ARC_CONFIGDIALOG)(const HWND,LPSTR,const int); typedef HARC (WINAPI * ARC_OPENARCHIVE)(const HWND,LPCSTR,const DWORD); typedef int (WINAPI * ARC_CLOSEARCHIVE)(HARC); typedef int (WINAPI * ARC_FINDFIRST)(HARC,LPCSTR,INDIVIDUALINFO *); typedef int (WINAPI * ARC_FINDNEXT)(HARC,INDIVIDUALINFO *); typedef int (WINAPI * ARC_GETARCFILENAME)(HARC,LPSTR,const int); typedef DWORD (WINAPI * ARC_GETARCORIGINALSIZE)(HARC); typedef BOOL (WINAPI * ARC_GETARCORIGINALSIZEEX)(HARC,ULHA_INT64); typedef WORD (WINAPI * ARC_GETARCRATIO)(HARC); typedef WORD (WINAPI * ARC_GETARCDATE)(HARC); typedef WORD (WINAPI * ARC_GETARCTIME)(HARC); typedef BOOL (WINAPI * ARC_GETARCWRITETIMEEX)(HARC,FILETIME *); typedef UINT (WINAPI * ARC_GETARCOSTYPE)(HARC); typedef int (WINAPI * ARC_ISSFXFILE)(HARC); typedef int (WINAPI * ARC_GETFILENAME)(HARC,LPSTR,const int); typedef int (WINAPI * ARC_GETMETHOD)(HARC,LPSTR,const int); typedef DWORD (WINAPI * ARC_GETORIGINALSIZE)(HARC); typedef BOOL (WINAPI * ARC_GETORIGINALSIZEEX)(HARC,ULHA_INT64 *); typedef WORD (WINAPI * ARC_GETRATIO)(HARC); typedef WORD (WINAPI * ARC_GETDATE)(HARC); typedef WORD (WINAPI * ARC_GETTIME)(HARC); typedef DWORD (WINAPI * ARC_GETWRITETIME)(HARC); typedef BOOL (WINAPI * ARC_GETWRITETIMEEX)(HARC,FILETIME *); typedef int (WINAPI * ARC_GETATTRIBUTE)(HARC); typedef UINT (WINAPI * ARC_GETOSTYPE)(HARC); typedef struct { LPTSTR lpszMainProc; LPTSTR lpszDLLName; } ARCTYPE; typedef struct { LPTSTR lpszSufix; LPTSTR lpszMainProc; } SUFIX; ARCTYPE ArcTypeInfo[] = { // "MainProc", "DLLName" {"Unlha", "unlha32.dll"}, {"UnZip", "unzip32.dll"}, {"Zip", "zip32j.dll"}, {"Cab", "cab32.dll"}, {"Unarj", "unarj32j.dll"}, {"Tar", "tar32.dll"}, {"Unrar", "unrar32.dll"}, {"Ish", "dmish32.dll"}, {"Bga", "bga32.dll"}, {"Yz1", "yz1.dll"}, {"UnGCA", "ungca32.dll"}, {"Unbel", "unbel32.dll"}, {"Jack", "jack32.dll"} }; SUFIX SufixInfo[] = { // "Sufix", "MainProc" {".lzh", "Unlha"}, {".lha", "Unlha"}, {".lzs", "Unlha"}, {".zip", "UnZip"}, {".jar", "UnZip"}, {".cab", "Cab"}, {".arj", "Unarj"}, {".tar", "Tar"}, {".tgz", "Tar"}, // (tar.gz) {".taz", "Tar"}, // (tar.gz) {".gz", "Tar"}, {".z", "Tar"}, {".bz2", "Tar"}, {".cpio", "Tar"}, {".rpm", "Tar"}, {".deb", "Tar"}, {".rar", "Unrar"}, {".ish", "Ish"}, {".gza", "Bga"}, {".bza", "Bga"}, {".yz1", "Yz1"}, {".gca", "UnGCA"}, {".bel", "Unbel"}, {".jak", "Jack"}, // (分割ファイル) {".exe", "Unlha"}, {".exe", "UnZip"}, {".exe", "Cab"}, {".exe", "Unarj"}, {".exe", "Tar"}, {".exe", "Unrar"}, {".exe", "Bga"}, {".exe", "Yz1"}, {".exe", "UnGCA"}, {".exe", "Jack"} // (分割ファイル) }; int nArcTypeInfo = 0; // デフォルトは unlha32.dll LPTSTR lpszDLLName(void) { static char szDLLName[20]; lstrcpy(szDLLName, ArcTypeInfo[nArcTypeInfo].lpszDLLName); return szDLLName; } LPTSTR lpszMainProc(void) { static char szMainProc[20]; lstrcpy(szMainProc, ArcTypeInfo[nArcTypeInfo].lpszMainProc); return szMainProc; } LPTSTR lpszProc(char *lpszBody) { static char szProc[20]; lstrcpy(szProc, ArcTypeInfo[nArcTypeInfo].lpszMainProc); lstrcat(szProc, lpszBody); return szProc; } #if 0 LPTSTR lpszDateTimes(WORD wDate, WORD wTime) { static char szDateTime[20]; union { WORD wDate; struct { unsigned ft_day : 5; unsigned ft_month : 4; unsigned ft_year : 7; // 1980年からの経過年数 } Date; } DosDate; union { WORD wTime; struct { unsigned ft_tsec : 5; // 秒を2で割ったもの unsigned ft_min : 6; unsigned ft_hour : 5; } Time; } DosTime; DosDate.wDate = wDate; DosTime.wTime = wTime; wsprintf(szDateTime, "%04u/%02u/%02u %02u:%02u:%02u", DosDate.Date.ft_year + 1980, DosDate.Date.ft_month, DosDate.Date.ft_day, DosTime.Time.ft_hour, DosTime.Time.ft_min, DosTime.Time.ft_tsec * 2); return szDateTime; } #else LPTSTR lpszDateTimes(WORD wDate, WORD wTime) { static char szDateTime[20]; wsprintf(szDateTime, "%04u/%02u/%02u %02u:%02u:%02u", (wDate >> 9) + 1980, (wDate >> 5) & 0x0F, (wDate & 0x1F), (wTime >> 11), (wTime >> 5) & 0x3F, (wTime & 0x1F) * 2); return szDateTime; } LPTSTR lpszDateTimes(time_t DateTime) // 注意!!使用厳禁!! // ARJ 書庫にはタイムゾーンの概念がない。 // 常にローカル時間で格納が行われている。 // したがって、localtime() は使えない。(T_T) { static char szDateTime[20]; struct tm *LocalTime = localtime(&DateTime); wsprintf(szDateTime, "%04u/%02u/%02u %02u:%02u:%02u", LocalTime->tm_year + 1900, LocalTime->tm_mon + 1, LocalTime->tm_mday, LocalTime->tm_hour, LocalTime->tm_min, LocalTime->tm_sec); return szDateTime; } #endif LPTSTR lpszCmdLine(int nSkip) // 全角文字や空白が含まれるファイル名、ロングファイル名を指定する場合は、 // ファイル名全体を " (ダブルクォテーション) で括る必要がある。 { LPTSTR lpszCommandLine = GetCommandLine(); for (int nCounts = 0; nCounts < nSkip; nCounts++) { // Skip past program name (first token in command line). // Check for and handle quoted program name. if (*lpszCommandLine == DQUOTECHAR) { // Scan, and skip over, subsequent characters until // another double-quote or a null is encountered. do { lpszCommandLine = CharNext(lpszCommandLine); } while ((*lpszCommandLine != DQUOTECHAR) && (*lpszCommandLine != '\0')); // If we stopped on a double-quote (usual case), skip over it. if (*lpszCommandLine == DQUOTECHAR) lpszCommandLine = CharNext(lpszCommandLine); } else { while (*lpszCommandLine > SPACECHAR) lpszCommandLine = CharNext(lpszCommandLine); } // Skip past any white space preceeding the second token. while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR)) lpszCommandLine = CharNext(lpszCommandLine); } return lpszCommandLine; } int Archive(LPCSTR lpszCmdLine) { int nRetcode = -1; // DLL をダイナミックにロードする。 HINSTANCE hDll = LoadLibrary(DLLNAME); if (hDll == NULL) return nRetcode; // 各 API のエントリーアドレスを得る。 ARC_MAINPROC fpMainProc = (ARC_MAINPROC) GetProcAddress(hDll, MAINPROC); ARC_GETVERSION fpGetVersion = (ARC_GETVERSION) GetProcAddress(hDll, GETVERSION); ARC_GETRUNNING fpGetRunning = (ARC_GETRUNNING) GetProcAddress(hDll, GETRUNNING); // 実用的なプログラムでは、ここで DLL のバージョンチェックや // fpGetRunning 等が NULL でないかの判定が必要。 if (fpMainProc && fpGetVersion && fpGetRunning) { // 下記の判定は Win32 でシングルスレッドなら不要だが、マルチスレッドの場合は // アプリ側でスレッドセーフを保証しなければならないため必要。 if ((*fpGetRunning)() == FALSE) { try { char szOutput[BUFFSIZE]; WORD wVer = (*fpGetVersion)(); nRetcode = (*fpMainProc)(NULL, lpszCmdLine, szOutput, sizeof(szOutput)); szOutput[sizeof(szOutput) - 1] = '\0'; printf("[CommandLine to %s (Ver %u.%02u) : %s]\n%s\n", DLLNAME, wVer / 100, wVer % 100, lpszCmdLine, szOutput); } catch (...) { printf("書庫操作中に例外が発生しました。 (%s)\n", DLLNAME); nRetcode = -1; } } else printf("現在 %s が動作中のため、書庫操作が行えません。\n", DLLNAME); }// else printf("書庫操作に必要な API が実装されていません。 (%s)\n", DLLNAME); // DLL を解放する。 // もちろん、ロードと解放はアプリの起動時と終了時に行うだけでも良い。 FreeLibrary(hDll); return nRetcode; } int OpenArchive(LPCSTR lpszFileName, const DWORD dwMode, LPCSTR lpszWildName) { int nCounts = 0; // DLL をダイナミックにロードする。 HINSTANCE hDll = LoadLibrary(DLLNAME); if (hDll == NULL) return nCounts; // 各 API のエントリーアドレスを得る。 ARC_GETRUNNING fpGetRunning = (ARC_GETRUNNING) GetProcAddress(hDll, GETRUNNING); ARC_OPENARCHIVE fpOpenArchive = (ARC_OPENARCHIVE) GetProcAddress(hDll, OPENARCHIVE); ARC_CLOSEARCHIVE fpCloseArchive = (ARC_CLOSEARCHIVE) GetProcAddress(hDll, CLOSEARCHIVE); ARC_FINDFIRST fpFindFirst = (ARC_FINDFIRST) GetProcAddress(hDll, FINDFIRST); ARC_FINDNEXT fpFindNext = (ARC_FINDNEXT) GetProcAddress(hDll, FINDNEXT); ARC_GETARCDATE fpGetArcDate = (ARC_GETARCDATE) GetProcAddress(hDll, GETARCDATE); ARC_GETARCTIME fpGetArcTime = (ARC_GETARCTIME) GetProcAddress(hDll, GETARCTIME); ARC_GETWRITETIME fpGetWriteTime = (ARC_GETWRITETIME) GetProcAddress(hDll, GETWRITETIME); // 実用的なプログラムでは、ここで DLL のバージョンチェックや // fpGetRunning 等が NULL でないかの判定が必要。 if (fpGetRunning && fpOpenArchive && fpCloseArchive && fpFindFirst && fpFindNext) { // 下記の判定は Win32 でシングルスレッドなら不要だが、マルチスレッドの場合は // アプリ側でスレッドセーフを保証しなければならないため必要。 if ((*fpGetRunning)() == FALSE) { try { // まずファイルをオープンする。 HARC hArc = (*fpOpenArchive)(NULL, lpszFileName, dwMode); if (hArc != NULL) { INDIVIDUALINFO Info; DWORD dwOriginalSize = 0; // 一個以上のファイルが見つかれば if ((*fpFindFirst)(hArc, (lstrlen(lpszWildName)) ? lpszWildName : WILDNAME, &Info) == 0) { printf("[Listing of archive : %s %s]\n", lpszFileName, (lstrlen(lpszWildName)) ? lpszWildName : WILDNAME, &Info); printf(" File name File size Date Time Attrs Type\n"); printf("----------------------------- ---------- ---------- -------- ----- -----\n"); do { // この例では ファイル名、圧縮前のサイズ、タイムスタンプ、属性と圧縮方式 // だけを表示している。DLLによっては圧縮方式等は無意味な場合もある。 printf("%s\n", Info.szFileName); printf(" %8lu %s %-5s %s\n", Info.dwOriginalSize, lpszDateTimes(Info.wDate, Info.wTime), Info.szAttribute, Info.szMode); dwOriginalSize += Info.dwOriginalSize; nCounts++; // ファイルが見つかる間、繰り返す。 } while ((*fpFindNext)(hArc, &Info) == 0); printf("----------------------------- ---------- ---------- --------\n"); printf(" %4u files %8lu %s\n", nCounts, dwOriginalSize, (fpGetArcDate && fpGetArcTime) ? lpszDateTimes((*fpGetArcDate)(hArc), (*fpGetArcTime)(hArc)) : ""); } else printf("検索条件 (%s) にマッチする格納ファイルが見つかりません。 (%s)\n", (lstrlen(lpszWildName)) ? lpszWildName : WILDNAME, DLLNAME); // 最後にクローズする。 (*fpCloseArchive)(hArc); } else printf("書庫 (%s) のオープンに失敗しました。(%s)\n", lpszFileName, DLLNAME); } catch (...) { printf("書庫情報取得中に例外が発生しました。 (%s)\n", DLLNAME); nCounts = 0; } } else printf("現在 %s が動作中のため、書庫情報取得が行えません。\n", DLLNAME); }// else printf("書庫情報取得に必要な API が実装されていません。 (%s)\n", DLLNAME); // DLL を解放する。 // もちろん、ロードと解放はアプリの起動時と終了時に行うだけでも良い。 FreeLibrary(hDll); return nCounts; } BOOL CheckArchive(LPCSTR lpszFileName, const int iMode) { BOOL bRetcode = FALSE; // DLL をダイナミックにロードする。 HINSTANCE hDll = LoadLibrary(DLLNAME); if (hDll == NULL) return bRetcode; // 各 API のエントリーアドレスを得る。 ARC_GETRUNNING fpGetRunning = (ARC_GETRUNNING) GetProcAddress(hDll, GETRUNNING); ARC_CHECKARCHIVE fpCheckArchive = (ARC_CHECKARCHIVE) GetProcAddress(hDll, CHECKARCHIVE); // 実用的なプログラムでは、ここで DLL のバージョンチェックや // fpGetRunning 等が NULL でないかの判定が必要。 if (fpGetRunning && fpCheckArchive) { // 下記の判定は Win32 でシングルスレッドなら不要だが、マルチスレッドの場合は // アプリ側でスレッドセーフを保証しなければならないため必要。 if ((*fpGetRunning)() == FALSE) { try { bRetcode = (*fpCheckArchive)(lpszFileName, iMode); } catch (...) { printf("書庫のチェック中に例外が発生しました。 (%s)\n", DLLNAME); bRetcode = FALSE; } } else printf("現在 %s が動作中のため書庫のチェックが行えません。\n", DLLNAME); }// else printf("書庫のチェックに必要な API が実装されていません。 (%s)\n", DLLNAME); // DLL を解放する。 // もちろん、ロードと解放はアプリの起動時と終了時に行うだけでも良い。 FreeLibrary(hDll); return bRetcode; } BOOL SetMainProcInfo(char *lpszMainProc) { for (nArcTypeInfo = 0; nArcTypeInfo < Number(ArcTypeInfo); nArcTypeInfo++) { if (lstrcmpi(lpszMainProc, ArcTypeInfo[nArcTypeInfo].lpszMainProc) == 0) return TRUE; } return FALSE; } BOOL SetSufixInfo(char *lpszFileName, const int iMode, BOOL bFull) // bFull == TRUE 拡張子決め打ちしない { int nSufixInfo; char szFname[_MAX_FNAME]; char szExt[_MAX_EXT]; // パスを分解。 _splitpath(lpszFileName, NULL, NULL, szFname, szExt); for (nSufixInfo = 0; nSufixInfo < Number(SufixInfo); nSufixInfo++) { if (lstrcmpi(szExt, SufixInfo[nSufixInfo].lpszSufix) == 0) { SetMainProcInfo(SufixInfo[nSufixInfo].lpszMainProc); if (CheckArchive(lpszFileName, iMode)) return TRUE; } } if (bFull) { for (nArcTypeInfo = 0; nArcTypeInfo < Number(ArcTypeInfo); nArcTypeInfo++) { if (CheckArchive(lpszFileName, iMode)) return TRUE; } } return FALSE; } int OpenFolders(LPCSTR lpszPath, BOOL bRecurse, const int iMode, BOOL bFull, // SetSufixInfo const DWORD dwMode, LPCSTR lpszWildName) // OpenArchive // bRecurse == TRUE サブフォルダも検索 { int nCounts = 0; char szSearchPath[MAX_PATH]; char szTempPath[MAX_PATH]; WIN32_FIND_DATA FindData; HANDLE hFindFile; lstrcpy(szSearchPath, lpszPath); lstrcat(szSearchPath, "\\*"); if ((hFindFile = FindFirstFile(szSearchPath, &FindData)) != INVALID_HANDLE_VALUE) { do { lstrcpy(szTempPath, lpszPath); lstrcat(szTempPath, "\\"); lstrcat(szTempPath, FindData.cFileName); if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (bRecurse && lstrcmpi(FindData.cFileName, ".") && lstrcmpi(FindData.cFileName, "..")) nCounts += OpenFolders(szTempPath, bRecurse, iMode, bFull, dwMode, lpszWildName); } else { if (SetSufixInfo(szTempPath, iMode, bFull)) nCounts += OpenArchive(szTempPath, dwMode, lpszWildName); } } while (FindNextFile (hFindFile, &FindData)); } FindClose(hFindFile); return nCounts; } void main(int argc, char *argv[]) { printf("- ARcToy 1.40f 2002/03/23 - Written by S.Noda \n"); if (argc > 1) { DWORD dwFileAttributes = GetFileAttributes(argv[1]); if (dwFileAttributes == -1) { if (SetMainProcInfo(argv[1])) Archive(lpszCmdLine(2)); } else if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { OpenFolders(argv[1], TRUE, CHECKMODE, FALSE, OPENMODE, lpszCmdLine(2)); } else { if (SetSufixInfo(argv[1], CHECKMODE, TRUE)) OpenArchive(argv[1], OPENMODE, lpszCmdLine(2)); } } else { printf( "[Help of ARcToy]\n" " Usage : \n" " or \n" " or \n" " IsArc - アーカイバ DLL が提供する API のリーダー\n" " CmdLine - アーカイバ DLL に渡すコマンドライン\n" " Archive - 書庫ファイル名(拡張子を含む)\n" " Folder - 検索するフォルダ名\n" " WildName - 検索するファイル名(複数指定が可能)\n"); } exit(EXIT_SUCCESS); }