diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/00am.sln ./00am.sln
--- /var/tmp/ax7z_src-orig/00am.sln	2004-10-07 19:57:12.000000000 +0900
+++ ./00am.sln	2013-08-17 22:00:04.872222400 +0900
@@ -1,34 +1,19 @@
-Microsoft Visual Studio Solution File, Format Version 8.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "00am", "00am.vcproj", "{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}"
-	ProjectSection(ProjectDependencies) = postProject
-	EndProjectSection
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "00am", "00am.vcxproj", "{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}"
 EndProject
 Global
-	GlobalSection(SourceCodeControl) = preSolution
-		SccNumberOfProjects = 2
-		SccProjectName0 = \u0022$/Hamana/00am\u0022,\u0020FHBAAAAA
-		SccLocalPath0 = ..
-		SccProvider0 = MSSCCI:Microsoft\u0020Visual\u0020SourceSafe
-		CanCheckoutShared = false
-		SccProjectFilePathRelativizedFromConnection0 = if7z\\
-		SolutionUniqueID = {F41EEF12-39F9-46A7-ABEF-136E24B830E0}
-		SccProjectUniqueName1 = 00am.vcproj
-		SccLocalPath1 = ..
-		CanCheckoutShared = false
-		SccProjectFilePathRelativizedFromConnection1 = if7z\\
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
 	EndGlobalSection
-	GlobalSection(SolutionConfiguration) = preSolution
-		Debug = Debug
-		Release = Release
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Debug|Win32.ActiveCfg = Debug|Win32
+		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Debug|Win32.Build.0 = Debug|Win32
+		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Release|Win32.ActiveCfg = Release|Win32
+		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
-	GlobalSection(ProjectConfiguration) = postSolution
-		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Debug.ActiveCfg = Debug|Win32
-		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Debug.Build.0 = Debug|Win32
-		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Release.ActiveCfg = Release|Win32
-		{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}.Release.Build.0 = Release|Win32
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-	EndGlobalSection
-	GlobalSection(ExtensibilityAddIns) = postSolution
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
 	EndGlobalSection
 EndGlobal
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/00am.vcproj ./00am.vcproj
--- /var/tmp/ax7z_src-orig/00am.vcproj	2005-09-26 03:31:18.000000000 +0900
+++ ./00am.vcproj	2015-01-09 00:41:22.338847500 +0900
@@ -3,6 +3,7 @@
 	ProjectType="Visual C++"
 	Version="7.10"
 	Name="00am"
+	RootNamespace="00am"
 	SccProjectName="&quot;$/Hamana/00am&quot;, FHBAAAAA"
 	SccAuxPath=""
 	SccLocalPath=".."
@@ -24,12 +25,13 @@
 				Name="VCCLCompilerTool"
 				Optimization="2"
 				InlineFunctionExpansion="1"
-				AdditionalIncludeDirectories=".,7z"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS"
+				AdditionalIncludeDirectories=".;7z;&quot;C:\Program Files (x86)\Library\boost\boost_1_50&quot;"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS"
 				StringPooling="TRUE"
 				RuntimeLibrary="0"
 				EnableFunctionLevelLinking="TRUE"
-				RuntimeTypeInfo="FALSE"
+				TreatWChar_tAsBuiltInType="TRUE"
+				RuntimeTypeInfo="TRUE"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderFile=".\Release/00am.pch"
 				AssemblerListingLocation=".\Release/"
@@ -42,9 +44,11 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				OutputFile="Release/ax7z.spi"
+				AdditionalDependencies="comctl32.lib version.lib"
+				OutputFile="Release/ax7z_s.spi"
 				LinkIncremental="1"
 				SuppressStartupBanner="TRUE"
+				AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Library\boost\boost_1_50\lib&quot;"
 				ModuleDefinitionFile=".\ax7z.def"
 				ProgramDatabaseFile=".\Release/ax7z.pdb"
 				ImportLibrary=".\Release/ax7z.lib"
@@ -89,10 +93,12 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories=".,7z"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS"
+				AdditionalIncludeDirectories=".;7z;&quot;C:\Program Files (x86)\Library\boost\boost_1_50&quot;"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
+				TreatWChar_tAsBuiltInType="TRUE"
+				RuntimeTypeInfo="TRUE"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderFile=".\Debug/00am.pch"
 				AssemblerListingLocation=".\Debug/"
@@ -107,9 +113,11 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				OutputFile="F:\projects\hamana\Hamana\target\DefaultSPIs\ax7z.spi"
+				AdditionalDependencies="comctl32.lib version.lib"
+				OutputFile="$(OutDir)/ax7z_s.spi"
 				LinkIncremental="1"
 				SuppressStartupBanner="TRUE"
+				AdditionalLibraryDirectories="&quot;C:\Program Files (x86)\Library\boost\boost_1_50\lib&quot;"
 				ModuleDefinitionFile=".\ax7z.def"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile=".\Debug/ax7z.pdb"
@@ -250,6 +258,18 @@
 					RelativePath=".\7z\Common\MyCom.h">
 				</File>
 				<File
+					RelativePath=".\7z\common\MyString.cpp">
+				</File>
+				<File
+					RelativePath=".\7z\common\MyString.h">
+				</File>
+				<File
+					RelativePath=".\7z\common\MyVector.cpp">
+				</File>
+				<File
+					RelativePath=".\7z\common\MyVector.h">
+				</File>
+				<File
 					RelativePath=".\7z\Common\StdInStream.cpp">
 					<FileConfiguration
 						Name="Release|Win32">
@@ -308,26 +328,6 @@
 					RelativePath=".\7z\7zip\Common\StreamUtils.h">
 				</File>
 				<File
-					RelativePath=".\7z\Common\String.cpp">
-					<FileConfiguration
-						Name="Release|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath=".\7z\Common\String.h">
-				</File>
-				<File
 					RelativePath="7z\Common\StringConvert.cpp">
 					<FileConfiguration
 						Name="Release|Win32">
@@ -373,26 +373,6 @@
 					RelativePath=".\7z\Common\StringToInt.h">
 				</File>
 				<File
-					RelativePath=".\7z\Common\Vector.cpp">
-					<FileConfiguration
-						Name="Release|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
-				</File>
-				<File
-					RelativePath=".\7z\Common\Vector.h">
-				</File>
-				<File
 					RelativePath=".\7z\Common\Wildcard.cpp">
 					<FileConfiguration
 						Name="Release|Win32">
@@ -432,7 +412,7 @@
 							Name="VCCLCompilerTool"
 							Optimization="0"
 							AdditionalIncludeDirectories=""
-							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit)"
+							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit);EXTERNAL_CODECS"
 							BasicRuntimeChecks="3"
 							UsePrecompiledHeader="0"
 							BrowseInformation="1"/>
@@ -454,7 +434,7 @@
 							Name="VCCLCompilerTool"
 							Optimization="0"
 							AdditionalIncludeDirectories=""
-							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit)"
+							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit);EXTERNAL_CODECS"
 							BasicRuntimeChecks="3"
 							UsePrecompiledHeader="0"
 							BrowseInformation="1"/>
@@ -479,7 +459,7 @@
 							Name="VCCLCompilerTool"
 							Optimization="0"
 							AdditionalIncludeDirectories=""
-							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit)"
+							PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;$(NoInherit);EXTERNAL_CODECS"
 							BasicRuntimeChecks="3"
 							UsePrecompiledHeader="0"
 							BrowseInformation="1"/>
@@ -489,6 +469,12 @@
 					RelativePath="7z\7zip\Bundles\ax7z\OpenCallback.h">
 				</File>
 				<File
+					RelativePath=".\7z\7zip\Bundles\ax7z\PasswordManager.cpp">
+				</File>
+				<File
+					RelativePath=".\7z\7zip\Bundles\ax7z\PasswordManager.h">
+				</File>
+				<File
 					RelativePath=".\7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.cpp">
 					<FileConfiguration
 						Name="Release|Win32">
@@ -500,12 +486,22 @@
 						Name="Debug|Win32">
 						<Tool
 							Name="VCCLCompilerTool"
+							PreprocessorDefinitions="EXTERNAL_CODECS"
 							UsePrecompiledHeader="0"/>
 					</FileConfiguration>
 				</File>
 				<File
 					RelativePath=".\7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.h">
 				</File>
+				<File
+					RelativePath=".\7z\7zip\Bundles\ax7z\SolidCache.cpp">
+				</File>
+				<File
+					RelativePath=".\7z\7zip\Bundles\ax7z\SolidCache.h">
+				</File>
+				<File
+					RelativePath=".\7z\7zip\Bundles\ax7z\SolidCacheDisk.cpp">
+				</File>
 			</Filter>
 			<Filter
 				Name="7-zip Common"
@@ -713,7 +709,7 @@
 					RelativePath=".\7z\7zip\Ui\Common\ArchiveOpenCallback.h">
 				</File>
 				<File
-					RelativePath=".\7z\7zip\Ui\Common\ArchiverInfo.cpp">
+					RelativePath=".\7z\7zip\Ui\Common\DefaultName.cpp">
 					<FileConfiguration
 						Name="Release|Win32">
 						<Tool
@@ -730,27 +726,13 @@
 					</FileConfiguration>
 				</File>
 				<File
-					RelativePath=".\7z\7zip\Ui\Common\ArchiverInfo.h">
+					RelativePath=".\7z\7zip\Ui\Common\DefaultName.h">
 				</File>
 				<File
-					RelativePath=".\7z\7zip\Ui\Common\DefaultName.cpp">
-					<FileConfiguration
-						Name="Release|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
-					<FileConfiguration
-						Name="Debug|Win32">
-						<Tool
-							Name="VCCLCompilerTool"
-							UsePrecompiledHeader="0"
-							ObjectFile="$(IntDir)/$(InputName)1.obj"/>
-					</FileConfiguration>
+					RelativePath=".\7z\7zip\ui\common\LoadCodecs.cpp">
 				</File>
 				<File
-					RelativePath=".\7z\7zip\Ui\Common\DefaultName.h">
+					RelativePath=".\7z\7zip\ui\common\LoadCodecs.h">
 				</File>
 				<File
 					RelativePath=".\7z\7zip\Ui\Common\OpenArchive.cpp">
@@ -778,6 +760,31 @@
 			Name="Resource Files"
 			Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
 		</Filter>
+		<Filter
+			Name="sqlite3"
+			Filter="">
+			<File
+				RelativePath=".\sqlite3\sqlite3.c">
+				<FileConfiguration
+					Name="Release|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions="SQLITE_THREADSAFE;_WIN32_WINNT=0x500"/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32">
+					<Tool
+						Name="VCCLCompilerTool"
+						PreprocessorDefinitions="SQLITE_THREADSAFE;_WIN32_WINNT=0x500"/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\sqlite3\sqlite3.h">
+			</File>
+			<File
+				RelativePath=".\sqlite3\sqlite3helper.h">
+			</File>
+		</Filter>
 		<File
 			RelativePath=".\ax7z.txt">
 		</File>
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/00am.vcxproj ./00am.vcxproj
--- /var/tmp/ax7z_src-orig/00am.vcxproj	1970-01-01 09:00:00.000000000 +0900
+++ ./00am.vcxproj	2015-01-09 00:41:43.992012600 +0900
@@ -0,0 +1,417 @@
+ï»¿<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <RootNamespace>00am</RootNamespace>
+    <SccProjectName>"$/Hamana/00am", FHBAAAAA</SccProjectName>
+    <SccAuxPath />
+    <SccLocalPath>..</SccLocalPath>
+    <SccProvider>MSSCCI:Microsoft Visual SourceSafe</SccProvider>
+    <ProjectGuid>{BB1F21AB-35C8-4474-AD0E-5138023DCD7C}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <PlatformToolset>v110</PlatformToolset>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <OutDir>.\Release\</OutDir>
+    <IntDir>.\Release\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <OutDir>.\Debug\</OutDir>
+    <IntDir>.\Debug\</IntDir>
+    <LinkIncremental>false</LinkIncremental>
+    <TargetName>ax7z_s</TargetName>
+    <TargetExt>.spi</TargetExt>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <AdditionalIncludeDirectories>.;7z;C:\Program Files (x86)\Library\boost\boost_1_57_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0501;NDEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <StringPooling>true</StringPooling>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>
+      <PrecompiledHeader />
+      <PrecompiledHeaderOutputFile>.\Release/00am.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+      <ObjectFileName>.\Release/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>comctl32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>Release/ax7z_s.spi</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <AdditionalLibraryDirectories>C:\Program Files (x86)\Library\boost\boost_1_57_0\lib32-msvc-11.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ModuleDefinitionFile>.\ax7z.def</ModuleDefinitionFile>
+      <ProgramDatabaseFile>.\Release/ax7z.pdb</ProgramDatabaseFile>
+      <ImportLibrary>.\Release/ax7z.lib</ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Release/00am.tlb</TypeLibraryName>
+      <HeaderFileName />
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0411</Culture>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;7z;C:\Program Files (x86)\Library\boost\boost_1_57_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+      <RuntimeTypeInfo>true</RuntimeTypeInfo>
+      <PrecompiledHeader />
+      <PrecompiledHeaderOutputFile>.\Debug/00am.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+      <ObjectFileName>.\Debug/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <BrowseInformation>true</BrowseInformation>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <CompileAs>Default</CompileAs>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>comctl32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>$(OutDir)ax7z_s.spi</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <AdditionalLibraryDirectories>C:\Program Files (x86)\Library\boost\boost_1_57_0\lib32-msvc-11.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ModuleDefinitionFile>.\ax7z.def</ModuleDefinitionFile>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>.\Debug/ax7z.pdb</ProgramDatabaseFile>
+      <ImportLibrary>.\Debug/ax7z.lib</ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Debug/00am.tlb</TypeLibraryName>
+      <HeaderFileName />
+    </Midl>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0411</Culture>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <None Include="ax7z.def" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="ax7z.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="entryFuncs.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;_WIN32_WINNT=0x0501;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS</PreprocessorDefinitions>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="infcache.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;_WIN32_WINNT=0x0501;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS</PreprocessorDefinitions>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\Common\IntToString.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\common\MyString.cpp" />
+    <ClCompile Include="7z\common\MyVector.cpp" />
+    <ClCompile Include="7z\Common\StdInStream.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StdOutStream.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Common\StreamUtils.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StringConvert.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StringToInt.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Common\Wildcard.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\bridge.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\ExtractCallback.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\OpenCallback.cpp">
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_WIN32_WINNT=0x0501;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MY00AM_EXPORTS;EXTERNAL_CODECS</PreprocessorDefinitions>
+      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
+      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\PasswordManager.cpp" />
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.cpp">
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EXTERNAL_CODECS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidCache.cpp" />
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidCacheDisk.cpp" />
+    <ClCompile Include="7z\7zip\Common\FileStreams.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\DLL.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileDir.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileFind.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileIO.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileName.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\PropVariant.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\PropVariantConversions.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\Registry.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Ui\Common\ArchiveOpenCallback.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Ui\Common\DefaultName.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\ui\common\LoadCodecs.cpp" />
+    <ClCompile Include="7z\7zip\Ui\Common\OpenArchive.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+      </PrecompiledHeader>
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.obj</ObjectFileName>
+    </ClCompile>
+    <ClCompile Include="sqlite3\sqlite3.c">
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">SQLITE_THREADSAFE;_WIN32_WINNT=0x500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">SQLITE_THREADSAFE;_WIN32_WINNT=0x500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="critsect.h" />
+    <ClInclude Include="entryFuncs.h" />
+    <ClInclude Include="infcache.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="7z\Common\IntToString.h" />
+    <ClInclude Include="7z\Common\MyCom.h" />
+    <ClInclude Include="7z\common\MyString.h" />
+    <ClInclude Include="7z\common\MyVector.h" />
+    <ClInclude Include="7z\Common\StdInStream.h" />
+    <ClInclude Include="7z\Common\StdOutStream.h" />
+    <ClInclude Include="7z\7zip\Common\StreamUtils.h" />
+    <ClInclude Include="7z\Common\StringConvert.h" />
+    <ClInclude Include="7z\Common\StringToInt.h" />
+    <ClInclude Include="7z\Common\Wildcard.h" />
+    <ClInclude Include="7z\7zip\Bundles\ax7z\ExtractCallback.h" />
+    <ClInclude Include="7z\7zip\Bundles\ax7z\OpenCallback.h" />
+    <ClInclude Include="7z\7zip\Bundles\ax7z\PasswordManager.h" />
+    <ClInclude Include="7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.h" />
+    <ClInclude Include="7z\7zip\Bundles\ax7z\SolidCache.h" />
+    <ClInclude Include="7z\7zip\Common\FileStreams.h" />
+    <ClInclude Include="7z\Windows\DLL.h" />
+    <ClInclude Include="7z\Windows\FileDir.h" />
+    <ClInclude Include="7z\Windows\FileFind.h" />
+    <ClInclude Include="7z\Windows\FileIO.h" />
+    <ClInclude Include="7z\Windows\FileName.h" />
+    <ClInclude Include="7z\Windows\PropVariant.h" />
+    <ClInclude Include="7z\Windows\PropVariantConversions.h" />
+    <ClInclude Include="7z\Windows\Registry.h" />
+    <ClInclude Include="7z\7zip\Ui\Common\ArchiveOpenCallback.h" />
+    <ClInclude Include="7z\7zip\Ui\Common\DefaultName.h" />
+    <ClInclude Include="7z\7zip\ui\common\LoadCodecs.h" />
+    <ClInclude Include="7z\7zip\Ui\Common\OpenArchive.h" />
+    <ClInclude Include="sqlite3\sqlite3.h" />
+    <ClInclude Include="sqlite3\sqlite3helper.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ax7z.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/00am.vcxproj.filters ./00am.vcxproj.filters
--- /var/tmp/ax7z_src-orig/00am.vcxproj.filters	1970-01-01 09:00:00.000000000 +0900
+++ ./00am.vcxproj.filters	2015-01-09 00:41:22.351848800 +0900
@@ -0,0 +1,253 @@
+ï»¿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{1a96980a-a03d-4668-8860-37aa154d89dc}</UniqueIdentifier>
+      <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{a24b5a2c-f87e-4506-b293-cbd4225e91c8}</UniqueIdentifier>
+      <Extensions>h;hpp;hxx;hm;inl</Extensions>
+    </Filter>
+    <Filter Include="7-zip">
+      <UniqueIdentifier>{c22458e7-7223-4e81-bafc-eeebda33ce82}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="7-zip\Common">
+      <UniqueIdentifier>{261cec54-8ae9-4e70-b362-6f6156c839c8}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="7-zip\bridge">
+      <UniqueIdentifier>{a176f517-0023-4015-9202-2e24e81305ff}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="7-zip\7-zip Common">
+      <UniqueIdentifier>{b6f8533a-d893-47eb-b9fb-a8a86609c854}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="7-zip\Windows">
+      <UniqueIdentifier>{eb818b1b-32cb-4ab5-ac05-e92ed3c33631}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="7-zip\UI Common">
+      <UniqueIdentifier>{08784d0c-10b8-4903-84aa-ccc39ea26c47}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{09374d5a-8ff3-45a5-858d-f651e6e22f79}</UniqueIdentifier>
+      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+    </Filter>
+    <Filter Include="sqlite3">
+      <UniqueIdentifier>{1c076c8e-2708-48ae-aa5b-3c508db1d41e}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="ax7z.def">
+      <Filter>Source Files</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="ax7z.rc">
+      <Filter>Source Files</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="entryFuncs.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="infcache.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\IntToString.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\common\MyString.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\common\MyVector.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StdInStream.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StdOutStream.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Common\StreamUtils.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StringConvert.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\StringToInt.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Common\Wildcard.cpp">
+      <Filter>7-zip\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\bridge.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\ExtractCallback.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\OpenCallback.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\PasswordManager.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidCache.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Bundles\ax7z\SolidCacheDisk.cpp">
+      <Filter>7-zip\bridge</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Common\FileStreams.cpp">
+      <Filter>7-zip\7-zip Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\DLL.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileDir.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileFind.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileIO.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\FileName.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\PropVariant.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\PropVariantConversions.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\Windows\Registry.cpp">
+      <Filter>7-zip\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Ui\Common\ArchiveOpenCallback.cpp">
+      <Filter>7-zip\UI Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Ui\Common\DefaultName.cpp">
+      <Filter>7-zip\UI Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\ui\common\LoadCodecs.cpp">
+      <Filter>7-zip\UI Common</Filter>
+    </ClCompile>
+    <ClCompile Include="7z\7zip\Ui\Common\OpenArchive.cpp">
+      <Filter>7-zip\UI Common</Filter>
+    </ClCompile>
+    <ClCompile Include="sqlite3\sqlite3.c">
+      <Filter>sqlite3</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="critsect.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="entryFuncs.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="infcache.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="resource.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\IntToString.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\MyCom.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\common\MyString.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\common\MyVector.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\StdInStream.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\StdOutStream.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Common\StreamUtils.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\StringConvert.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\StringToInt.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Common\Wildcard.h">
+      <Filter>7-zip\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Bundles\ax7z\ExtractCallback.h">
+      <Filter>7-zip\bridge</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Bundles\ax7z\OpenCallback.h">
+      <Filter>7-zip\bridge</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Bundles\ax7z\PasswordManager.h">
+      <Filter>7-zip\bridge</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Bundles\ax7z\SolidArchiveExtractCallback.h">
+      <Filter>7-zip\bridge</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Bundles\ax7z\SolidCache.h">
+      <Filter>7-zip\bridge</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Common\FileStreams.h">
+      <Filter>7-zip\7-zip Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\DLL.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\FileDir.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\FileFind.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\FileIO.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\FileName.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\PropVariant.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\PropVariantConversions.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\Windows\Registry.h">
+      <Filter>7-zip\Windows</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Ui\Common\ArchiveOpenCallback.h">
+      <Filter>7-zip\UI Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Ui\Common\DefaultName.h">
+      <Filter>7-zip\UI Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\ui\common\LoadCodecs.h">
+      <Filter>7-zip\UI Common</Filter>
+    </ClInclude>
+    <ClInclude Include="7z\7zip\Ui\Common\OpenArchive.h">
+      <Filter>7-zip\UI Common</Filter>
+    </ClInclude>
+    <ClInclude Include="sqlite3\sqlite3.h">
+      <Filter>sqlite3</Filter>
+    </ClInclude>
+    <ClInclude Include="sqlite3\sqlite3helper.h">
+      <Filter>sqlite3</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <Text Include="ax7z.txt" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/ExtractCallback.cpp ./7z/7zip/Bundles/ax7z/ExtractCallback.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/ExtractCallback.cpp	2005-09-26 00:48:18.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/ExtractCallback.cpp	2015-01-09 00:41:22.355849200 +0900
@@ -1,6 +1,9 @@
 // ExtractCallback.h
+#define NOMINMAX
 #include <windows.h>
+#undef NOMINMAX
 #include "ExtractCallback.h"
+#include "PasswordManager.h"
 #include "Common/StringConvert.h"
 #include "Windows/FileDir.h"
 #include "Windows/PropVariant.h"
@@ -9,7 +12,7 @@
 
 using namespace NWindows;
 
-void CExtractCallbackImp::Init(IInArchive *archive, char* pBuf, UINT32 nBufSize, FILE* fp, UINT32 index)
+void CExtractCallbackImp::Init(IInArchive *archive, char** pBuf, UINT32 nBufSize, FILE* fp, UINT32 index, SolidFileCache *cache, SPI_PROGRESS lpPrgressCallback, long lData)
 {
   assert(!pBuf || !fp);
   m_NumErrors = 0;
@@ -18,6 +21,10 @@
   m_fp = fp;
   m_nBufSize = nBufSize;
   m_nIndex = index;
+  m_nCurIndex = 0xFFFFFFFF;
+  m_cache = cache;
+  m_lpPrgressCallback = lpPrgressCallback;
+  m_lData = lData;
 }
 
 bool CExtractCallbackImp::IsEncrypted(UINT32 index)
@@ -46,38 +53,63 @@
 {
 public:
     CMemOutStream() : m_iPos(0), m_pBuf(NULL), m_nBufSize(0) {}
-    void Init(char* pBuf, UINT32 nBufSize, FILE* fp, bool bValid) { m_pBuf = pBuf; m_fp = fp; m_nBufSize = nBufSize; m_bValid = bValid; }
+    void Init(char** pBuf, UINT32 nBufSize, FILE* fp, bool bValid, SolidFileCache *cache, UINT32 nIndex)
+	{
+		m_pBuf = pBuf;
+		m_fp = fp;
+		m_nBufSize = nBufSize;
+		m_bValid = bValid;
+		m_cache = cache;
+		m_index = nIndex;
+		m_bIsSizeUnspecified = (nBufSize == 0);
+	}
   MY_UNKNOWN_IMP
 
   STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
   STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
 protected:
     UINT32 m_iPos;
-    char* m_pBuf;
+    char** m_pBuf;
     FILE* m_fp;
     UINT32 m_nBufSize;
     bool m_bValid;
+	SolidFileCache *m_cache;
+	UINT32 m_index;
+    bool m_bIsSizeUnspecified;
 };
 
 STDMETHODIMP CMemOutStream::Write(const void *data, UINT32 size, UINT32 *processedSize)
 {
-    if (!m_bValid) {
-        *processedSize = size;
-        return S_OK;
-    }
-
     UINT32 dummy;
     if (processedSize == NULL) {
         processedSize = &dummy;
     }
     
+    if(m_cache && !m_cache->IsCached(m_index)) m_cache->Append(m_index, data, size);
+
+    if (!m_bValid) {
+        *processedSize = size;
+        return S_OK;
+    }
+
     if (m_nBufSize < m_iPos + size) {
-        // ”O‚Ì‚½‚ßƒ`ƒFƒbƒN
-        return S_FALSE;
+		if(m_bIsSizeUnspecified) {
+			// Extend buffer
+			if(m_pBuf) {
+				char *pBuf = (char*)LocalAlloc(LMEM_FIXED, static_cast<size_t>(m_iPos + size));
+				if(!pBuf) return S_FALSE;
+				CopyMemory(pBuf, *m_pBuf, m_iPos);
+				LocalFree(*m_pBuf);
+				*m_pBuf = pBuf;
+			}
+		} else {
+			// ”O‚Ì‚½‚ßƒ`ƒFƒbƒN
+			return S_FALSE;
+		}
     }
 
     if (m_pBuf) {
-        memcpy(m_pBuf + m_iPos, data, size);
+        memcpy(*m_pBuf + m_iPos, data, size);
     } else {
         fwrite(data, size, 1, m_fp);
     }
@@ -94,10 +126,15 @@
 STDMETHODIMP CExtractCallbackImp::GetStream(UINT32 index,
     ISequentialOutStream **outStream, INT32 askExtractMode)
 {
+    m_nCurIndex = index;
     CMemOutStream* pRealStream = new CMemOutStream;
     pRealStream->AddRef();
-    pRealStream->Init(m_pBuf, m_nBufSize, m_fp, index == m_nIndex);
+    pRealStream->Init(m_pBuf, m_nBufSize, m_fp, index == m_nIndex, m_cache, index);
     *outStream = pRealStream;
+// TODO: support abort?
+	if(m_lpPrgressCallback && m_cache)
+		if(m_lpPrgressCallback(m_cache->GetProgress(index), m_cache->GetProgressDenom(index), m_lData))
+			return E_ABORT;
     return S_OK;
 }
 
@@ -112,7 +149,16 @@
   {
     case NArchive::NExtract::NOperationResult::kOK:
     {
-      break;
+	  if(m_cache) {
+		m_cache->Cached(m_nCurIndex);
+		boost::this_thread::yield();
+	  }
+	  break;
+    }
+    case NArchive::NExtract::NOperationResult::kDataError:
+    case NArchive::NExtract::NOperationResult::kCRCError:
+    {
+      PasswordManager::Get().NotifyError();
     }
     default:
     {
@@ -124,17 +170,10 @@
 
 STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
 {
-  /*
-  if (!m_PasswordIsDefined)
-  {
-    g_StdOut << "\nEnter password:";
-    AString oemPassword = g_StdIn.ScanStringUntilNewLine();
-    m_Password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); 
-    m_PasswordIsDefined = true;
-  }
-  CMyComBSTR tempName(m_Password);
+  UString usPassword = PasswordManager::Get().GetPassword(false);
+  CMyComBSTR tempName(usPassword);
   *password = tempName.Detach();
-  */
+
   return S_OK;
 }
   
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/ExtractCallback.h ./7z/7zip/Bundles/ax7z/ExtractCallback.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/ExtractCallback.h	2005-06-28 22:01:40.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/ExtractCallback.h	2015-01-09 00:41:22.357849400 +0900
@@ -5,13 +5,16 @@
 #ifndef __EXTRACTCALLBACK_H
 #define __EXTRACTCALLBACK_H
 
-#include "Common/String.h"
+//#include "Common/String.h"
 #include "../../Common/FileStreams.h"
 #include "../../IPassword.h"
 #include "../../Archive/IArchive.h"
 #include "../../UI/Common/ZipRegistry.h"
 #include <stdio.h>
 
+#include "entryFuncs.h"
+#include "SolidCache.h"
+
 class CExtractCallbackImp: 
   public IArchiveExtractCallback,
   public ICryptoGetTextPassword,
@@ -39,13 +42,18 @@
 
   bool IsEncrypted(UINT32 index);
 public:
-  void Init(IInArchive *archive, char* pBuf, UINT32 nBufSize, FILE* fp, UINT32 index);
+  void Init(IInArchive *archive, char** pBuf, UINT32 nBufSize, FILE* fp, UINT32 index, SolidFileCache *cache, SPI_PROGRESS lpPrgressCallback, long lData);
 
   UINT64 m_NumErrors;
-  char* m_pBuf;
+private:
+  char** m_pBuf;
   FILE* m_fp;
   UINT32 m_nBufSize;
   UINT32 m_nIndex;
+  UINT32 m_nCurIndex;
+  SolidFileCache *m_cache;
+  SPI_PROGRESS m_lpPrgressCallback;
+  long m_lData;
 };
 
 #endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/Lock.h ./7z/7zip/Bundles/ax7z/Lock.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/Lock.h	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/Lock.h	2015-01-09 00:41:22.360849700 +0900
@@ -0,0 +1,45 @@
+#define N BOOST_PP_ITERATION()
+
+#define VAR_TN BOOST_PP_ENUM_PARAMS(N, t)
+#if   BOOST_PP_ITERATION_FLAGS() == 1
+#define ARG_(z, n, data) typename boost::call_traits<typename boost::mpl::at<boost::function_types::parameter_types<Method>, boost::mpl::int_<n+1> >::type>::param_type BOOST_PP_CAT(t, n)
+#elif BOOST_PP_ITERATION_FLAGS() == 2
+#define ARG_(z, n, data) typename boost::call_traits<typename boost::mpl::at<boost::function_types::parameter_types<Method>, boost::mpl::long_<n+1> >::type>::param_type BOOST_PP_CAT(t, n)
+#elif BOOST_PP_ITERATION_FLAGS() == 3
+#define ARG_(z, n, data) typename boost::call_traits<typename boost::mpl::at_c<boost::function_types::parameter_types<Method>, n+1>::type>::param_type BOOST_PP_CAT(t, n)
+#endif
+#define ARG_N BOOST_PP_ENUM_TRAILING(N, ARG_, _)
+
+	template<typename Method>
+	typename boost::enable_if_c<boost::function_types::function_arity<Method>::value == N + 1, typename boost::function_types::result_type<Method>::type>::type
+	CallWithLockGuard(Method m /*,*/ ARG_N)
+	{
+		boost::lock_guard<SolidCache::Mutex> guard(SolidCache::GetMutex());
+		return (this->*m)(VAR_TN);
+	}
+	template<typename Method>
+	typename boost::enable_if_c<boost::function_types::function_arity<Method>::value == N + 1, typename boost::function_types::result_type<Method>::type>::type
+	CallWithLockGuard(Method m /*,*/ ARG_N) const
+	{
+		boost::lock_guard<SolidCache::Mutex> guard(SolidCache::GetMutex());
+		return (this->*m)(VAR_TN);
+	}
+	template<typename Method>
+	typename boost::enable_if_c<boost::function_types::function_arity<Method>::value == N + 1, typename boost::function_types::result_type<Method>::type>::type
+	CallWithSharedLock(Method m /*,*/ ARG_N)
+	{
+		boost::shared_lock<SolidCache::Mutex> guard(SolidCache::GetMutex());
+		return (this->*m)(VAR_TN);
+	}
+	template<typename Method>
+	typename boost::enable_if_c<boost::function_types::function_arity<Method>::value == N + 1, typename boost::function_types::result_type<Method>::type>::type
+	CallWithSharedLock(Method m /*,*/ ARG_N) const
+	{
+		boost::shared_lock<SolidCache::Mutex> guard(SolidCache::GetMutex());
+		return (this->*m)(VAR_TN);
+	}
+
+#undef ARG_N
+#undef ARG_
+#undef VAR_TN
+#undef N
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/OpenCallback.cpp ./7z/7zip/Bundles/ax7z/OpenCallback.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/OpenCallback.cpp	2005-06-21 21:50:12.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/OpenCallback.cpp	2013-04-12 00:17:01.659373300 +0900
@@ -1,6 +1,7 @@
 // OpenCallback.cpp
 #include <windows.h>
 #include "OpenCallback.h"
+#include "PasswordManager.h"
 
 #include "Common/StdOutStream.h"
 #include "Common/StdInStream.h"
@@ -70,17 +71,10 @@
 
 STDMETHODIMP COpenCallbackImp2::CryptoGetTextPassword(BSTR *password)
 {
-    /*
-    if (!PasswordIsDefined)
-    {
-    g_StdOut << "\nEnter password:";
-    AString oemPassword = g_StdIn.ScanStringUntilNewLine();
-    Password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); 
-    PasswordIsDefined = true;
-    }
-    CMyComBSTR temp(Password);
+	UString usPassword = PasswordManager::Get().GetPassword(true);
+	CMyComBSTR temp(usPassword);
     *password = temp.Detach();
-    */
+
     return S_OK;
 }
 
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/OpenCallback.h ./7z/7zip/Bundles/ax7z/OpenCallback.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/OpenCallback.h	2005-06-21 21:50:12.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/OpenCallback.h	2013-04-12 00:17:01.661373500 +0900
@@ -5,7 +5,7 @@
 #ifndef __OPENCALLBACK_H
 #define __OPENCALLBACK_H
 
-#include "Common/String.h"
+//#include "Common/String.h"
 #include "Common/MyCom.h"
 #include "Windows/FileFind.h"
 
@@ -38,9 +38,7 @@
   UString _folderPrefix;
   NWindows::NFile::NFind::CFileInfoW _fileInfo;
 public:
-  bool PasswordIsDefined;
-  UString Password;
-  COpenCallbackImp2(): PasswordIsDefined(false) {}
+  COpenCallbackImp2() {}
   void LoadFileInfo(const UString &folderPrefix,  const UString &fileName)
   {
     _folderPrefix = folderPrefix;
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/PasswordManager.cpp ./7z/7zip/Bundles/ax7z/PasswordManager.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/PasswordManager.cpp	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/PasswordManager.cpp	2013-04-12 00:17:01.663373700 +0900
@@ -0,0 +1,152 @@
+//PasswordManager.cpp
+#include "PasswordManager.h"
+#include "../../../Common/StringConvert.h"
+#include "resource.h"
+
+PasswordManager& PasswordManager::Get()
+{
+	static PasswordManager pm;
+	return pm;
+}
+
+const UString& PasswordManager::GetPassword(bool bFilename)
+{
+	extern HINSTANCE g_hInstance;
+	m_bFilename = bFilename;
+	if(IsRetry()) {
+		m_bPassword = false;
+	}
+	if(!m_bPassword && !m_bSkip && !m_bSkipArc) {
+		DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_PASSWORD), NULL, (DLGPROC)PasswordDlgProc, reinterpret_cast<LPARAM>(static_cast<void*>(this)));
+		m_bError = false;
+	}
+	if(!m_bPassword) {
+		m_usPassword = L"";
+	}
+	m_bPasswordUsed = true;
+	return m_usPassword;
+}
+
+bool PasswordManager::IsRetry() const
+{
+	return m_bPasswordUsed && m_bError && !m_bSkip && !m_bSkipArc;
+}
+
+bool PasswordManager::IsValid() const
+{
+	return !m_bArchiveChanged && !m_bError && !m_bSkip && !m_bSkipArc;
+}
+
+void PasswordManager::NotifyArchive(const UString& usArchive)
+{
+	if(m_usArchive != usArchive) {
+		m_bPasswordUsed = false;
+		m_bArchiveChanged = true;
+		m_bError = false;
+		m_bSkip = false;
+		m_bSkipArc = false;
+		m_usArchive = usArchive;
+	}
+}
+
+void PasswordManager::NotfiyEndFile()
+{
+	m_bPasswordUsed = false;
+	m_bError = false;
+	m_bSkip = false;
+}
+
+void PasswordManager::NotifyError()
+{
+	m_bError = true;
+}
+
+void PasswordManager::ClearError()
+{
+	m_bError = false;
+}
+
+void PasswordManager::Reset()
+{
+	m_bPassword = false;
+}
+
+INT_PTR CALLBACK PasswordManager::PasswordDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+	switch(uMsg)
+	{
+	case WM_INITDIALOG:
+	{
+		SetWindowLongPtr(hwnd, DWLP_USER, lParam);
+		PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+		if(p->m_bFilename) EnableWindow(GetDlgItem(hwnd, IDC_SKIP_BUTTON), FALSE);
+		if(p->IsRetry()) SetWindowText(GetDlgItem(hwnd, IDC_GUIDE_STATIC), "Extract error, maybe caused by wrong password,\nretype password:");
+		HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
+		InsertMenu(hSysMenu, SC_CLOSE, MF_STRING | (p->m_bTopMost ? MF_CHECKED : 0), IDM_TOPMOST, TEXT("TopMost"));
+		InsertMenu(hSysMenu, SC_CLOSE, MF_SEPARATOR, 0, 0);
+		if(p->m_bTopMost) {
+			SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+		} else {
+			SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+		}
+		return TRUE;
+	}
+	case WM_INITMENUPOPUP:
+	{
+		HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
+		if(hSysMenu == static_cast<HANDLE>(reinterpret_cast<void*>(wParam))) {
+			PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+			ModifyMenu(hSysMenu, IDM_TOPMOST, MF_BYCOMMAND | MF_STRING | (p->m_bTopMost ? MF_CHECKED : 0), IDM_TOPMOST, TEXT("TopMost"));
+		}
+		return TRUE;
+	}
+	case WM_SYSCOMMAND:
+		if((wParam & 0xFFF0) == IDM_TOPMOST) {
+			PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+			p->m_bTopMost = !p->m_bTopMost;
+			if(p->m_bTopMost) {
+				SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+			} else {
+				SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+			}
+			return TRUE;
+		}
+		return FALSE;
+	case WM_COMMAND:
+		switch(LOWORD(wParam)) {
+		case IDOK:
+		{
+			PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+			char buf[4096+1];
+			GetDlgItemText(hwnd, IDC_PASSWORD_EDIT, buf, sizeof(buf));
+			AString oemPassword = buf;
+			p->m_usPassword = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
+			p->m_bPassword = true;
+			p->m_bArchiveChanged = false;
+			EndDialog(hwnd, TRUE);
+			break;
+		}
+		case IDC_SKIP_BUTTON:
+		{
+			PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+			p->m_bSkip = true;
+			p->m_bPassword = false;
+			EndDialog(hwnd, FALSE);
+			break;
+		}
+		case IDC_SKIPARC_BUTTON:
+		{
+			PasswordManager* p = static_cast<PasswordManager*>(reinterpret_cast<void*>(GetWindowLongPtr(hwnd, DWLP_USER)));
+			p->m_bSkipArc = true;
+			p->m_bPassword = false;
+			EndDialog(hwnd, FALSE);
+			break;
+		}
+		default:
+			return FALSE;
+		}
+	default:
+		return FALSE;
+	}
+	return FALSE; // not reached
+}
\ No newline at end of file
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/PasswordManager.h ./7z/7zip/Bundles/ax7z/PasswordManager.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/PasswordManager.h	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/PasswordManager.h	2013-04-12 00:17:01.665373900 +0900
@@ -0,0 +1,45 @@
+//PasswordManager.h
+
+#pragma once
+
+#ifndef PASSWORDMANAGER_H
+#define PASSWORDMANAGER_H
+
+#include "../../../Common/MyString.h"
+
+class PasswordManager
+{
+public:
+	static PasswordManager& Get();
+	bool IsRetry() const;
+	bool IsDefined() const { return m_bPassword; }
+	bool IsValid() const;
+	const UString& GetPassword(bool bFilename);
+	void NotifyArchive(const UString& usArchive);
+	void NotfiyEndFile();
+	void NotifyError();
+	void ClearError();
+	void Reset();
+	bool SetTopMost(bool flag)
+	{
+		bool bPrev = m_bTopMost;
+		m_bTopMost = flag;
+		return bPrev;
+	}
+	bool GetTopMost() const { return m_bTopMost; }
+private:
+	static INT_PTR CALLBACK PasswordDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+	PasswordManager() : m_bPassword(false), m_bPasswordUsed(false), m_bArchiveChanged(false), m_bError(false), m_bSkip(false), m_bSkipArc(false) {}
+	bool m_bPassword;
+	bool m_bPasswordUsed;
+	bool m_bArchiveChanged;
+	bool m_bError;
+	bool m_bFilename;
+	bool m_bSkip;
+	bool m_bSkipArc;
+	bool m_bTopMost;
+	UString m_usPassword;
+	UString m_usArchive;
+};
+
+#endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.cpp ./7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.cpp	2005-09-26 02:36:18.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.cpp	2015-01-09 00:41:22.363850000 +0900
@@ -1,6 +1,7 @@
 // SolidArchiveExtractCallback.h
 #include <windows.h>
 #include "SolidArchiveExtractCallback.h"
+#include "PasswordManager.h"
 #include "Common/StringConvert.h"
 #include "Windows/FileDir.h"
 #include "Windows/PropVariant.h"
@@ -110,27 +111,25 @@
     {
       break;
     }
+    case NArchive::NExtract::NOperationResult::kDataError:
+    case NArchive::NExtract::NOperationResult::kCRCError:
+    {
+      PasswordManager::Get().NotifyError();
+    }
     default:
     {
       m_NumErrors++;
     }
   }
+  PasswordManager::Get().NotfiyEndFile();
   return S_OK;
 }
 
 STDMETHODIMP CSolidArchiveExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
 {
-  /*
-  if (!m_PasswordIsDefined)
-  {
-    g_StdOut << "\nEnter password:";
-    AString oemPassword = g_StdIn.ScanStringUntilNewLine();
-    m_Password = MultiByteToUnicodeString(oemPassword, CP_OEMCP); 
-    m_PasswordIsDefined = true;
-  }
-  CMyComBSTR tempName(m_Password);
+  UString usPassword = PasswordManager::Get().GetPassword(false);
+  CMyComBSTR tempName(usPassword);
   *password = tempName.Detach();
-  */
   return S_OK;
 }
   
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.h ./7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.h	2005-09-26 02:36:38.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/SolidArchiveExtractCallback.h	2013-04-12 00:17:01.667374100 +0900
@@ -5,7 +5,7 @@
 #ifndef __SOLIDARCHIVEEXTRACTCALLBACK_H
 #define __SOLIDARCHIVEEXTRACTCALLBACK_H
 
-#include "Common/String.h"
+//#include "Common/String.h"
 #include "../../Common/FileStreams.h"
 #include "../../IPassword.h"
 #include "../../Archive/IArchive.h"
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCache.cpp ./7z/7zip/Bundles/ax7z/SolidCache.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCache.cpp	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/SolidCache.cpp	2015-01-09 00:41:22.368850500 +0900
@@ -0,0 +1,125 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sstream>
+#include "SolidCache.h"
+
+SolidCache& SolidCache::GetInstance()
+{
+	static SolidCache sc;
+	return sc;
+}
+
+SolidFileCache SolidCache::GetFileCache(const std::string& filename)
+{
+	return SolidFileCache(GetInstance(), filename);
+}
+
+void SolidCache::Append(const std::string& sArchive, unsigned int index, const void* data, unsigned int size)
+{
+	OutputDebugPrintf("SolidCache::Append %s %u %u bytes\n", sArchive.c_str(), index, size);
+	if(m_scd.Exists(sArchive.c_str(), index) || GetMaxMemory() <= 0) {
+		m_scd.Append(sArchive.c_str(), index, data, size);
+		OutputDebugPrintf("SolidCache::Append:disk %s %u %u bytes\n", sArchive.c_str(), index, size);
+	} else {
+		m_scm.GetFileCache(sArchive).Append(index, data, size);
+		OutputDebugPrintf("SolidCache::Append:memory %s %u %u bytes\n", sArchive.c_str(), index, size);
+		if(m_scm.GetMaxMemory() > 0 && m_scm.GetSize() > m_scm.GetMaxMemoryInBytes()) {
+			OutputDebugPrintf("SolidCache::Append:purge_memory2disk %s %u %u maxmem: %" UINT64_S "u curmem: %" UINT64_S "u\n", sArchive.c_str(), index, m_scm.GetFileCache(sArchive).GetCurSize(index), m_scm.GetMaxMemoryInBytes(), m_scm.GetSize());
+			m_scm.ReduceSize(std::min(m_scm.GetSize(), std::max(m_scm.GetPurgeMemoryInBytes(), m_scm.GetSize() - m_scm.GetMaxMemoryInBytes())), SolidCacheDisk::ReduceSizeCallback, &m_scd, sArchive);
+		}
+	}
+}
+
+void SolidFileCacheMemory::AccessArchive_() const
+{
+	std::time(&m_atime);
+}
+
+struct Argument2
+{
+	std::string sArchive;
+	void *pArg;
+};
+
+boost::uint64_t SolidFileCacheMemory::ReduceSize_(boost::uint64_t uiSize, void(*fCallback)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg)
+{
+	Argument2 *pArg2 = static_cast<Argument2*>(pArg);
+	while(uiSize > 0 && m_cache.size() > 0) {
+		OutputDebugPrintf("SolidFileCacheMemory::ReduceSize %" UINT64_S "u\n", uiSize);
+		unsigned int index = m_cache.begin()->first;
+		fCallback(pArg2->pArg, pArg2->sArchive, index, &m_cache[index].vBuffer[0], m_cache[index].vBuffer.size(), m_cache[index].fCached);
+		if(uiSize < m_cache[index].vBuffer.size()) uiSize = 0;
+		else uiSize -= m_cache[index].vBuffer.size();
+		m_cache.erase(index);
+	}
+	return uiSize;
+}
+
+SolidCacheMemory::Key SolidCacheMemory::MakeKey(const std::string &sArchive)
+{
+	struct __stat64 st;
+// TODO: error check
+	_stat64(sArchive.c_str(), &st);
+	return boost::make_tuple(sArchive, st.st_mtime, st.st_size);
+}
+
+void SolidCacheMemory::AccessArchive_(const char* archive)
+{
+	std::time_t atime;
+	std::time(&atime);
+	m_mAccess[MakeKey(archive)] = atime;
+}
+
+SolidCacheMemory::Key SolidCacheMemory::GetLRUArchive_(const Key& sExcludeArchive) const
+{
+	Key sArchive = m_mAccess.begin()->first;
+	std::time_t atime = m_mAccess.begin()->second;
+	for(ArchiveTable::const_iterator it = m_mAccess.begin(); it != m_mAccess.end(); ++it) {
+		if(sArchive == sExcludeArchive || (it->first != sExcludeArchive && atime > it->second)) {
+			sArchive = it->first;
+			atime = it->second;
+		}
+	}
+	return sArchive;
+}
+
+boost::uint64_t SolidCacheMemory::GetSize_() const
+{
+	boost::uint64_t nResult = 0;
+	for(Table::const_iterator it1 = m_mTable.begin(); it1 != m_mTable.end(); ++it1) {
+		for(SolidFileCacheMemory::FileCache::const_iterator it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
+			nResult += it2->second.vBuffer.size();
+		}
+	}
+	return nResult;
+}
+
+boost::uint64_t SolidCacheMemory::ReduceSize_(boost::uint64_t uiSize, void(*fCallback)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg, const Key& sExcludeArchive)
+{
+	OutputDebugPrintf("SolidCacheMemory::ReduceSize %" UINT64_S "u %s:%" UINT64_S "u:%" UINT64_S "u", uiSize, sExcludeArchive.get<0>().c_str(),sExcludeArchive.get<1>(),sExcludeArchive.get<2>());
+	while(uiSize > 0) {
+		OutputDebugPrintf("SolidCacheMemory::ReduceSize trace %" UINT64_S "u %s:%" UINT64_S "u:%" UINT64_S "u", uiSize, sExcludeArchive.get<0>().c_str(),sExcludeArchive.get<1>(),sExcludeArchive.get<2>());
+		if(m_mTable.size() > 0) {
+			Key sArchive = GetLRUArchive_(sExcludeArchive);
+			SolidFileCacheMemory scm = GetFileCache_(sArchive);
+			if(scm.GetCount_() > 0) {
+				Argument2 arg2 = { RestoreKey(sArchive), pArg };
+				OutputDebugPrintf("SolidCacheMemory::ReduceSize calling scm.ReduceSize_()\n");
+				uiSize = scm.ReduceSize_(uiSize, fCallback, &arg2);
+			} else {
+				m_mTable.erase(sArchive);
+				m_mAccess.erase(sArchive);
+			}
+		}
+	}
+	return uiSize;
+}
+
+Queue::Key Queue::MakeKey(const std::string &sArchive) const
+{
+	struct __stat64 st;
+// TODO: error check
+	_stat64(sArchive.c_str(), &st);
+	return boost::make_tuple(sArchive, st.st_mtime, st.st_size);
+}
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCache.h ./7z/7zip/Bundles/ax7z/SolidCache.h
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCache.h	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/SolidCache.h	2015-01-09 00:41:22.373851000 +0900
@@ -0,0 +1,757 @@
+// SolidCache.h
+
+#pragma once
+
+#ifndef SOLIDCACHE_H
+#define SOLIDCACHE_H
+
+#define NOMINMAX
+#include <windows.h>
+#undef NOMINMAX
+#include <vector>
+#include <map>
+#include <string>
+#include <algorithm>
+#include <ctime>
+#include <cassert>
+
+#define __STDC_CONSTANT_MACROS
+#include <boost/cstdint.hpp>
+#define UINT64_S "I64"
+
+#include <boost/function_types/result_type.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/function_types/function_arity.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/call_traits.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/preprocessor/iteration/iterate.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing.hpp>
+
+#define BOOST_THREAD_VERSION 4
+#include <boost/thread.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+#include "sqlite3/sqlite3helper_decl.h"
+
+#ifdef NDEBUG
+#define OutputDebugPrintf (void)
+#else
+static void OutputDebugPrintf(const char* format, ...)
+{
+	va_list ap;
+	va_start(ap, format);
+	char buf[2048];
+	std::vsprintf(buf, format, ap);
+	OutputDebugString(buf);
+	va_end(ap);
+}
+#endif
+
+class SolidFileCacheDisk;
+
+class SolidCacheDisk
+{
+// TODO: Bad design
+	friend class SolidCache;
+private:
+	int m_nMaxDisk;
+	int m_nPurgeDisk;
+	std::string m_sCacheFolder;
+	yak::sqlite::Database m_db;
+
+#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, 4, "Lock.h", 1))
+#include BOOST_PP_ITERATE()
+
+// private:
+	bool OpenDB_();
+	void InitDB_();
+	void CheckDB_();
+	bool ExistsArchive_(const char* archive) const;
+	void AddArchive_(const char* archive);
+	unsigned int GetArchiveIdx_(const char* archive) const;
+	bool ExistsEntry_(unsigned int aidx, unsigned int idx) const;
+	void AppendEntry_(unsigned int aidx, unsigned int idx, const void* data, unsigned int size);
+	void AddEntry_(unsigned int aidx, unsigned int idx, const void *data, unsigned int size);
+	void PurgeUnreferenced_();
+	void PurgeUnreferencedOther_(unsigned int aidx);
+	void PurgeUnreferencedWithAIdx_(unsigned int aidx);
+	void PurgeUnmarkedAll_();
+	void PurgeUnmarkedOther_(unsigned int aidx);
+	boost::uint64_t GetSize_() const;
+	void ReduceSizeWithAIdx_(unsigned int aidx, boost::uint64_t size);
+	void ReduceSize_(boost::uint64_t size, unsigned int exclude_aidx);
+	bool IsProcessing_(const char* archive, unsigned int index) const;
+// public:
+	bool IsCached_(const char* archive, unsigned int index) const;
+	bool Exists_(const char* archive, unsigned int index) const;
+	void Append_(const char* archive, unsigned int index, const void* data, unsigned int size);
+	void Cached_(const char* archive, unsigned int index);
+	void CachedVector_(const char* archive, std::vector<unsigned int>& vIndex);
+	void PurgeUnmarked_(const char *archive);
+	void GetContent_(const char* archive, unsigned int index, void* dest, unsigned int size) const;
+	void OutputContent_(const char* archive, unsigned int index, unsigned int size, FILE* fp) const;
+	void AccessArchive_(const char* archive);
+	void Clear_();
+
+//
+	std::string GetFileName(__int64 id) const;
+public:
+	SolidCacheDisk():m_nMaxDisk(-1),m_nPurgeDisk(10),m_sCacheFolder(""),m_db(0) {}
+	~SolidCacheDisk();
+	bool IsCached(const char* archive, unsigned int index) const
+	{
+		return CallWithSharedLock(&SolidCacheDisk::IsCached_, archive, index);
+	}
+	bool Exists(const char* archive, unsigned int index) const
+	{
+		return CallWithSharedLock(&SolidCacheDisk::Exists_, archive, index);
+	}
+	void Append(const char* archive, unsigned int index, const void* data, unsigned int size)
+	{
+		return CallWithLockGuard(&SolidCacheDisk::Append_, archive, index, data, size);
+	}
+	void Cached(const char* archive, unsigned int index)
+	{
+		return CallWithLockGuard(&SolidCacheDisk::Cached_, archive, index);
+	}
+	void CachedVector(const char* archive, std::vector<unsigned int>& vIndex)
+	{
+		return CallWithLockGuard(&SolidCacheDisk::CachedVector_, archive, vIndex);
+	}
+	void PurgeUnmarked(const char *archive)
+	{
+		return CallWithLockGuard(&SolidCacheDisk::PurgeUnmarked_, archive);
+	}
+	void GetContent(const char* archive, unsigned int index, void* dest, unsigned int size) const
+	{
+		return CallWithSharedLock(&SolidCacheDisk::GetContent_, archive, index, dest, size);
+	}
+	void OutputContent(const char* archive, unsigned int index, unsigned int size, FILE* fp) const
+	{
+		return CallWithSharedLock(&SolidCacheDisk::OutputContent_, archive, index, size, fp);
+	}
+	void AccessArchive(const char* archive)
+	{
+		return CallWithLockGuard(&SolidCacheDisk::AccessArchive_, archive);
+	}
+	void Clear()
+	{
+		return CallWithLockGuard(&SolidCacheDisk::Clear_);
+	}
+
+	static SolidCacheDisk& GetInstance();
+	static SolidFileCacheDisk GetFileCache(const std::string& filename);
+
+	int GetMaxDisk() const { return m_nMaxDisk; }
+	boost::uint64_t GetMaxDiskInBytes() const { return m_nMaxDisk * UINT64_C(1024)*UINT64_C(1024); }
+	int SetMaxDisk(int nNew)
+	{
+		int nOld = m_nMaxDisk;
+		m_nMaxDisk = nNew;
+		return nOld;
+	}
+	int GetPurgeDisk() const { return m_nPurgeDisk; }
+	boost::uint64_t GetPurgeDiskInBytes() const { return m_nPurgeDisk * UINT64_C(1024)*UINT64_C(1024); }
+	int SetPurgeDisk(int nNew)
+	{
+		int nOld = m_nPurgeDisk;
+		m_nPurgeDisk = nNew;
+		return nOld;
+	}
+	const std::string& GetCacheFolder() const { return m_sCacheFolder; }
+	std::string SetCacheFolder(std::string sNew);
+	static void ReduceSizeCallback(void *pArg, const std::string& sArchive, unsigned int index, void* data, unsigned int size, bool flag);
+};
+
+class SolidFileCacheDisk
+{
+	friend class SolidCacheDisk;
+private:
+	SolidCacheDisk &m_scd;
+	std::string m_sArchive;
+	UINT32 m_nMaxNum;
+	SolidFileCacheDisk(SolidCacheDisk &scd, const std::string &sArchive)
+	    : m_scd(scd), m_sArchive(sArchive)
+	{
+	}
+public:
+	bool IsCached(unsigned int index) const
+	{
+		return m_scd.IsCached(m_sArchive.c_str(), index);
+	}
+	bool Exists(unsigned int index) const
+	{
+		return m_scd.Exists(m_sArchive.c_str(), index);
+	}
+	void Append(unsigned int index, const void* data, unsigned int size)
+	{
+		m_scd.Append(m_sArchive.c_str(), index, data, size);
+	}
+	void Cached(unsigned int index)
+	{
+		m_scd.Cached(m_sArchive.c_str(), index);
+	}
+	void CachedVector(std::vector<unsigned int>& vIndex)
+	{
+		m_scd.CachedVector(m_sArchive.c_str(), vIndex);
+	}
+	void PurgeUnmarked()
+	{
+		m_scd.PurgeUnmarked(m_sArchive.c_str());
+	}
+	void GetContent(unsigned int index, void* dest, unsigned int size) const
+	{
+		m_scd.AccessArchive(m_sArchive.c_str());
+		m_scd.GetContent(m_sArchive.c_str(), index, dest, size);
+	}
+	void OutputContent(unsigned int index, unsigned int size, FILE* fp) const
+	{
+		m_scd.AccessArchive(m_sArchive.c_str());
+		m_scd.OutputContent(m_sArchive.c_str(), index, size, fp);
+	}
+};
+
+class SolidFileCacheMemory
+{
+	friend class SolidCacheMemory;
+
+#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, 3, "Lock.h", 2))
+#include BOOST_PP_ITERATE()
+
+// private:
+	void AccessArchive_() const;
+// public:
+	boost::uint64_t ReduceSize_(boost::uint64_t uiSize, void(*fCallback)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg);
+	void Append_(unsigned int index, const void* data, unsigned int size)
+	{
+		m_cache[index].vBuffer.insert(m_cache[index].vBuffer.end(), 
+			static_cast<const unsigned char*>(data), 
+			static_cast<const unsigned char*>(data)+size);
+		OutputDebugPrintf("SolidCacheMemory::Append: %d %p %d %d, %02X %02X %02X %02X\n", index, data, size, m_cache[index].vBuffer.size(), m_cache[index].vBuffer[0], m_cache[index].vBuffer[1], m_cache[index].vBuffer[2], m_cache[index].vBuffer[3]);
+	}
+	void Cached_(unsigned int index)
+	{
+		m_cache[index].fCached = true;
+//		OutputDebugPrintf("SolidCache::Cached: %d", index);
+	}
+	void CachedVector_(std::vector<unsigned int>& vIndex)
+	{
+		std::vector<unsigned int>::iterator it = vIndex.begin(), itEnd = vIndex.end();
+		for(; it != itEnd; ++it) {
+			if(m_cache.count(*it)) {
+				OutputDebugPrintf("SolidCacheMemory::CachedVector %d\n", *it);
+				m_cache[*it].fCached = true;
+			}
+		}
+	}
+	void Remove_(unsigned int index)
+	{
+		m_cache.erase(index);
+	}
+	void PurgeUnmarked_()
+	{
+		FileCache::iterator it = m_cache.begin(), itEnd = m_cache.end();
+		while(it != itEnd) {
+			if(!it->second.fCached) {
+				it = m_cache.erase(it);
+			} else 
+				++it;
+		}
+	}
+	unsigned int GetCount_() const
+	{
+		return m_cache.size();
+	}
+	unsigned int GetCurSize_(unsigned int index) const
+	{
+		return m_cache[index].vBuffer.size();
+	}
+	const void* GetContent_(unsigned int index) const
+	{
+		return &m_cache[index].vBuffer[0];
+	}
+	void GetContent_(unsigned int index, void* dest, unsigned int size) const
+	{
+		OutputDebugPrintf("SolidCacheMemory::GetContent: %d %p %d %d %02X %02X %02X %02X\n", index, dest, size, m_cache[index].vBuffer.size(), m_cache[index].vBuffer[0], m_cache[index].vBuffer[1], m_cache[index].vBuffer[2], m_cache[index].vBuffer[3]);
+		// TODO: error check
+		CopyMemory(dest, &m_cache[index].vBuffer[0], std::min(size, m_cache[index].vBuffer.size()));
+		AccessArchive_();
+	}
+	void OutputContent_(unsigned int index, unsigned int size, FILE* fp) const
+	{
+		OutputDebugPrintf("SolidCacheMemory::OutputContent: %d %p %d %d %02X %02X %02X %02X\n", index, fp, size, m_cache[index].vBuffer.size(), m_cache[index].vBuffer[0], m_cache[index].vBuffer[1], m_cache[index].vBuffer[2], m_cache[index].vBuffer[3]);
+		fwrite(&m_cache[index].vBuffer[0], std::min(size, m_cache[index].vBuffer.size()), 1, fp);
+		AccessArchive_();
+	}
+
+private:
+	struct Entry
+	{
+		bool fCached;
+		std::vector<unsigned char> vBuffer;
+		Entry():fCached(false) {}
+	};
+	typedef std::map<unsigned int, Entry> FileCache;
+	SolidFileCacheMemory(FileCache& cache, std::time_t &atime) : m_cache(cache), m_atime(atime)
+	{
+	}
+	void AccessArchive() const
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::AccessArchive_);
+	}
+	FileCache& m_cache;
+	mutable std::time_t& m_atime;
+public:
+	bool IsCached_(unsigned int index) const
+	{
+		return m_cache.count(index) > 0 && m_cache[index].fCached;
+	}
+	bool Exists_(unsigned int index) const
+	{
+		return m_cache.count(index) > 0;
+	}
+	void Append(unsigned int index, const void* data, unsigned int size)
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::Append_, index, data, size);
+	}
+	void Cached(unsigned int index)
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::Cached_, index);
+	}
+	void CachedVector(std::vector<unsigned int>& vIndex)
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::CachedVector_, vIndex);
+	}
+	void Remove(unsigned int index)
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::Remove_, index);
+	}
+	void PurgeUnmarked()
+	{
+		return CallWithLockGuard(&SolidFileCacheMemory::PurgeUnmarked_);
+	}
+//	unsigned int ReduceSize(unsigned int uiSize, void(*fCallback)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg);
+	unsigned int GetCount() const
+	{
+		return CallWithSharedLock(&SolidFileCacheMemory::GetCount_);
+	}
+	unsigned int GetCurSize(unsigned int index) const
+	{
+		return CallWithSharedLock(&SolidFileCacheMemory::GetCurSize_, index);
+	}
+	const void* GetContent(unsigned int index) const
+	{
+		return CallWithSharedLock(static_cast<const void* (SolidFileCacheMemory::*)(unsigned int) const>(&SolidFileCacheMemory::GetContent_), index);
+	}
+	void GetContent(unsigned int index, void* dest, unsigned int size) const
+	{
+		return CallWithSharedLock(static_cast<void (SolidFileCacheMemory::*)(unsigned int, void*, unsigned int) const>(&SolidFileCacheMemory::GetContent_), index, dest, size);
+	}
+	void OutputContent(unsigned int index, unsigned int size, FILE* fp) const
+	{
+		return CallWithSharedLock(&SolidFileCacheMemory::OutputContent_, index, size, fp);
+	}
+};
+
+class SolidCacheMemory
+{
+private:
+	friend class SolidCache;
+	typedef boost::tuple<std::string, __int64, __int64> Key;
+	typedef std::map<Key, SolidFileCacheMemory::FileCache> Table;
+	typedef std::map<Key, std::time_t> ArchiveTable;
+	Table m_mTable;
+	ArchiveTable m_mAccess;
+	int m_nMaxMemory;
+	int m_nPurgeMemory;
+
+	static Key MakeKey(const std::string &sArchive);
+	static std::string RestoreKey(const Key &sArchive)
+	{
+		return sArchive.get<0>();
+	}
+
+#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, 4, "Lock.h", 3))
+#include BOOST_PP_ITERATE()
+
+// private:
+	void AccessArchive_(const char* archive);
+	Key GetLRUArchive_(const Key& sExcludeArchive) const;
+
+// public:
+	boost::uint64_t GetSize_() const;
+	boost::uint64_t ReduceSize_(boost::uint64_t uiSize, void(*)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg, const Key &sExcludeArchive);
+	void Clear_()
+	{
+		m_mTable.clear();
+		m_mAccess.clear();
+	}
+	void PurgeUnreferenced_()
+	{
+		Table::iterator it = m_mTable.begin(), itEnd = m_mTable.end();
+		while(it != itEnd) {
+			if(it->second.size() == 0) {
+				it = m_mTable.erase(it);
+			} else ++it;
+		}
+	}
+	bool Exists_(const Key &sArchive) const
+	{
+		return m_mTable.count(sArchive) > 0;
+	}
+	bool Peek_(bool (SolidFileCacheMemory::*method)(unsigned int) const, const Key& sArchive, unsigned int index) const
+	{
+		Table::const_iterator it = m_mTable.find(sArchive);
+		ArchiveTable::const_iterator it2 = m_mAccess.find(sArchive);
+		if(it != m_mTable.end()) {
+			return (SolidFileCacheMemory(const_cast<Table::mapped_type&>(it->second), const_cast<ArchiveTable::mapped_type&>(it2->second)).*method)(index);
+		}
+		return false;
+	}
+	SolidFileCacheMemory GetFileCache_(const Key& sArchive)
+	{
+		return SolidFileCacheMemory(m_mTable[sArchive], m_mAccess[sArchive]);
+	}
+	SolidFileCacheMemory GetFileCache_(const Key& sArchive) const
+	{
+		Table::const_iterator it = m_mTable.find(sArchive);
+		ArchiveTable::const_iterator it2 = m_mAccess.find(sArchive);
+		if(it == m_mTable.end() || it2 == m_mAccess.end()) throw std::domain_error("SolidCacheMemory::GetFileCache() const: not initialized");
+		return SolidFileCacheMemory(const_cast<Table::mapped_type&>(it->second), const_cast<ArchiveTable::mapped_type&>(it2->second));
+	}
+
+//
+//	void AccessArchive(const char* archive);
+//	std::string GetLRUArchive(const std::string& sExcludeArchive) const;
+
+public:
+	SolidCacheMemory():m_nMaxMemory(-1),m_nPurgeMemory(10) {}
+	SolidFileCacheMemory GetFileCache(const std::string& sArchive)
+	{
+		return SolidFileCacheMemory(m_mTable[MakeKey(sArchive)], m_mAccess[MakeKey(sArchive)]);
+	}
+	SolidFileCacheMemory GetFileCache(const std::string& sArchive) const
+	{
+		Table::const_iterator it = m_mTable.find(MakeKey(sArchive));
+		ArchiveTable::const_iterator it2 = m_mAccess.find(MakeKey(sArchive));
+		if(it == m_mTable.end() || it2 == m_mAccess.end()) throw std::domain_error("SolidCacheMemory::GetFileCache() const: not initialized");
+		return SolidFileCacheMemory(const_cast<Table::mapped_type&>(it->second), const_cast<ArchiveTable::mapped_type&>(it2->second));
+	}
+	bool Peek(bool (SolidFileCacheMemory::*method)(unsigned int) const, const std::string& sArchive, unsigned int index) const
+	{
+		return CallWithSharedLock(&SolidCacheMemory::Peek_, method, MakeKey(sArchive), index);
+	}
+	void PurgeUnreferenced()
+	{
+		return CallWithLockGuard(&SolidCacheMemory::PurgeUnreferenced_);
+	}
+	bool Exists(const std::string &sArchive) const
+	{
+		return CallWithSharedLock(&SolidCacheMemory::Exists_, MakeKey(sArchive));
+	}
+	boost::uint64_t GetSize() const
+	{
+		return CallWithSharedLock(&SolidCacheMemory::GetSize_);
+	}
+	boost::uint64_t ReduceSize(boost::uint64_t uiSize, void(*f)(void*, const std::string&, unsigned int, void*, unsigned int, bool), void* pArg, const std::string& sExcludeArchive)
+	{
+		return CallWithLockGuard(&SolidCacheMemory::ReduceSize_, uiSize, f, pArg, MakeKey(sExcludeArchive));
+	}
+	void Clear()
+	{
+		return CallWithLockGuard(&SolidCacheMemory::Clear_);
+	}
+
+	int GetMaxMemory() const { return m_nMaxMemory; }
+	boost::uint64_t GetMaxMemoryInBytes() const { return m_nMaxMemory * UINT64_C(1024)*UINT64_C(1024); }
+	int SetMaxMemory(int nNew)
+	{
+		int nOld = m_nMaxMemory;
+		m_nMaxMemory = nNew;
+		return nOld;
+	}
+	int GetPurgeMemory() const { return m_nPurgeMemory; }
+	boost::uint64_t GetPurgeMemoryInBytes() const { return m_nPurgeMemory * UINT64_C(1024)*UINT64_C(1024); }
+	int SetPurgeMemory(int nNew)
+	{
+		int nOld = m_nPurgeMemory;
+		m_nPurgeMemory = nNew;
+		return nOld;
+	}
+};
+
+class SolidFileCache;
+
+class Queue
+{
+	typedef boost::tuple<std::string, __int64, __int64> Key;
+	Key MakeKey(const std::string &sArchive) const;
+	typedef std::map<Key, boost::shared_ptr<boost::thread> > ThreadMap;
+	ThreadMap threads;
+	typedef std::map<std::pair<Key, unsigned int>, boost::shared_ptr<boost::condition_variable_any> > CondVarMap;
+	CondVarMap cvs;
+	void CleanupAll()
+	{
+OutputDebugPrintf("Queue::CleanupAll(): Cleanup %d", threads.size());
+		for(ThreadMap::iterator mi = threads.begin(), mie = threads.end(); mi != mie;) {
+			if(mi->second->get_id() != boost::this_thread::get_id() && (!mi->second->joinable() || mi->second->try_join_until(boost::chrono::system_clock::now() + boost::chrono::milliseconds(1)))) {
+OutputDebugPrintf("Queue::CleanupAll(): Cleanup thread for %s", mi->first.get<0>().c_str());
+				Cleanup(mi->first);
+				mi = threads.erase(mi);
+			} else ++mi;
+		}
+	}
+	void Cleanup(const Key& key)
+	{
+		for(CondVarMap::iterator mi = cvs.begin(), mie = cvs.end(); mi != mie;) {
+			if(mi->first.first == key) {
+				mi->second->notify_all();
+				mi = cvs.erase(mi);
+			} else ++mi;
+		}
+	}
+public:
+	bool IsQueued(const std::string &s)
+	{
+		CleanupAll();
+OutputDebugPrintf("Queue::IsQueued(): %s [%d]", s.c_str(), int(threads.count(MakeKey(s)) != 0));
+		return threads.count(MakeKey(s)) != 0;
+	}
+	template<typename Callable>
+	void Invoke(const std::string &s, Callable c)
+	{
+OutputDebugPrintf("Queue::Invoke(): s: %s", s.c_str());
+		CleanupAll();
+		if(threads.count(MakeKey(s))) {
+			OutputDebugPrintf("Queue::Invoke(): thread for %s already invoked", s.c_str());
+		} else {
+			boost::shared_ptr<boost::thread> ptr(new boost::thread(c));
+			OutputDebugPrintf("Queue::Invoke(): thread for %s %d", s.c_str(), ptr->get_id());
+			threads[MakeKey(s)].swap(ptr);
+		}
+	}
+	bool ExistsCondVar(const std::string &s, unsigned int index)
+	{
+OutputDebugPrintf("Queue::ExistsCondVar(): %s %d [%d]", s.c_str(), index, int(cvs.count(make_pair(MakeKey(s), index)) != 0));
+		CleanupAll();
+OutputDebugPrintf("Queue::ExistsCondVar(): after %s %d [%d]", s.c_str(), index, int(cvs.count(make_pair(MakeKey(s), index)) != 0));
+		return cvs.count(make_pair(MakeKey(s), index)) != 0;
+	}
+	boost::shared_ptr<boost::condition_variable_any> GetCondVar(const std::string &s, unsigned int index)
+	{
+		CleanupAll();
+		if(cvs.count(make_pair(MakeKey(s), index)) == 0) {
+			boost::shared_ptr<boost::condition_variable_any> ptr(new boost::condition_variable_any);
+			cvs[make_pair(MakeKey(s), index)] = ptr;
+		}
+		return cvs[make_pair(MakeKey(s), index)];
+	}
+	void NotifyCondVar(const std::string &s, unsigned int index)
+	{
+OutputDebugPrintf("Queue::NotifyCondVar(): %s %d [%d]", s.c_str(), index, int(cvs.count(make_pair(MakeKey(s), index)) != 0));
+		if(ExistsCondVar(s, index)) {
+			cvs[make_pair(MakeKey(s), index)]->notify_all();
+			cvs.erase(make_pair(MakeKey(s), index));
+		}
+	}
+	void Cleanup(const std::string &sArchive)
+	{
+OutputDebugPrintf("Queue::Cleanup(): %s", sArchive.c_str());
+		Cleanup(MakeKey(sArchive));
+//		threads.erase(MakeKey(sArchive));  // Not sure but seems to cause application error
+	}
+	~Queue() {
+OutputDebugPrintf("Queue::~Queue(): thread %d", threads.size());
+		for(ThreadMap::iterator mi = threads.begin(), mie = threads.end(); mi != mie; ++mi) {
+			if(mi->second->joinable()) {
+OutputDebugPrintf("Queue::~Queue(): joinable thread %d is the current %s", mi->second->get_id(), mi->second->get_id() == boost::this_thread::get_id() ? "true" : "false");
+				mi->second->join();
+			}
+		}
+OutputDebugPrintf("Queue::~Queue(): end");
+	}
+};
+
+class SolidCache
+{
+private:
+	int m_nMaxLookAhead;
+	SolidCacheDisk m_scd;
+	SolidCacheMemory m_scm;
+	boost::shared_mutex m_sm;
+	Queue m_queue;
+	SolidCache() : m_nMaxLookAhead(-1) {}
+public:
+	static SolidCache& GetInstance();
+	static SolidFileCache GetFileCache(const std::string& filename);
+	typedef boost::shared_mutex Mutex;
+	static Mutex& GetMutex(void)
+	{
+		return GetInstance().m_sm;
+	}
+	Queue& GetQueue() {	return m_queue; }
+
+	bool IsCached(const std::string& sArchive, unsigned int index) const
+	{
+		return m_scm.Peek(&SolidFileCacheMemory::IsCached_, sArchive, index) || m_scd.IsCached(sArchive.c_str(), index);
+	}
+	bool IsCached_(const std::string& sArchive, unsigned int index) const
+	{
+		return m_scm.Peek_(&SolidFileCacheMemory::IsCached_, SolidCacheMemory::MakeKey(sArchive), index) || m_scd.IsCached_(sArchive.c_str(), index);
+	}
+	void Append(const std::string& sArchvie, unsigned int index, const void* data, unsigned int size);
+	void Cached(const std::string& sArchive, unsigned int index)
+	{
+		OutputDebugPrintf("SolidCache::Cached %s %d\n", sArchive.c_str(), index);
+		if(m_scm.Peek(&SolidFileCacheMemory::Exists_, sArchive, index)) {
+			OutputDebugPrintf("SolidCache::Cached:memory %s %d\n", sArchive.c_str(), index);
+			m_scm.GetFileCache(sArchive).Cached(index);
+		} else if(m_scd.Exists(sArchive.c_str(), index)) {
+			OutputDebugPrintf("SolidCache::Cached:disk %s %d\n", sArchive.c_str(), index);
+			m_scd.Cached(sArchive.c_str(), index);
+		} else {
+			assert("SolidCache::Cached: Not reached\n");
+		}
+		if(m_queue.ExistsCondVar(sArchive, index)) {
+			OutputDebugPrintf("SolidCache::Cached calling notify_all() for %s [%d]\n", sArchive.c_str(), index);
+			m_queue.NotifyCondVar(sArchive, index);
+		}
+	}
+	void PurgeUnmarked(const std::string& sArchive)
+	{
+		m_scm.GetFileCache(sArchive).PurgeUnmarked();
+		m_scm.PurgeUnreferenced();
+		m_scd.PurgeUnmarked(sArchive.c_str());
+	}
+	void GetContent(const std::string& sArchive, unsigned int index, void* dest, unsigned int size) const
+	{
+		OutputDebugPrintf("SolidCache::GetContent %s %d %d bytes\n", sArchive.c_str(), index, size);
+		if(m_scm.Peek(&SolidFileCacheMemory::IsCached_, sArchive, index)) {
+			m_scm.GetFileCache(sArchive).GetContent(index, dest, size);
+		} else if(m_scd.IsCached(sArchive.c_str(), index)) {
+			m_scd.GetContent(sArchive.c_str(), index, dest, size);
+		} else {
+			assert("SolidCache::GetContent: Not reached\n");
+		}
+	}
+	void OutputContent(const std::string& sArchive, unsigned int index, unsigned int size, FILE* fp) const
+	{
+		OutputDebugPrintf("SolidCache::OutputContent %s %d %d bytes\n", sArchive.c_str(), index, size);
+		if(m_scm.Peek(&SolidFileCacheMemory::IsCached_, sArchive, index)) {
+			m_scm.GetFileCache(sArchive).OutputContent(index, size, fp);
+		} else if(m_scd.IsCached(sArchive.c_str(), index)) {
+			m_scd.OutputContent(sArchive.c_str(), index, size, fp);
+		} else {
+			assert("SolidCache::OutputContent: Not reached\n");
+		}
+	}
+
+	void Clear()
+	{
+		m_scm.Clear();
+		m_scd.Clear();
+	}
+
+	int GetMaxLookAhead() const { return m_nMaxLookAhead; }
+	int SetMaxLookAhead(int nNew)
+	{
+		int nOld = m_nMaxLookAhead;
+		m_nMaxLookAhead = nNew;
+		return nOld;
+	}
+	int GetMaxMemory() const { return m_scm.GetMaxMemory(); }
+	boost::uint64_t GetMaxMemoryInBytes() const { return m_scm.GetMaxMemoryInBytes(); }
+	int SetMaxMemory(int nNew) { return m_scm.SetMaxMemory(nNew); }
+	int GetPurgeMemory() const { return m_scm.GetPurgeMemory(); }
+	boost::uint64_t GetPurgeMemoryInBytes() const { return m_scm.GetPurgeMemoryInBytes(); }
+	int SetPurgeMemory(int nNew) { return m_scm.SetPurgeMemory(nNew); }
+	int GetMaxDisk() const { return m_scd.GetMaxDisk(); }
+	boost::uint64_t GetMaxDiskInBytes() const { return m_scd.GetMaxDiskInBytes(); }
+	int SetMaxDisk(int nNew) { return m_scd.SetMaxDisk(nNew); }
+	int GetPurgeDisk() const { return m_scd.GetPurgeDisk(); }
+	boost::uint64_t GetPurgeDiskInBytes() const { return m_scd.GetPurgeDiskInBytes(); }
+	int SetPurgeDisk(int nNew) { return m_scd.SetPurgeDisk(nNew); }
+	const std::string& GetCacheFolder() const { return m_scd.GetCacheFolder(); }
+	std::string SetCacheFolder(std::string sNew) { return m_scd.SetCacheFolder(sNew); }
+};
+
+class SolidFileCache
+{
+	friend class SolidCache;
+private:
+	SolidCache &m_sc;
+	std::string m_sArchive;
+	UINT32 m_nMaxNum;
+	SolidFileCache(SolidCache &sc, const std::string &sArchive) : m_sc(sc), m_sArchive(sArchive) {}
+	bool IsCached_(unsigned int index) const { return m_sc.IsCached_(m_sArchive, index); }
+public:
+	bool IsCached(unsigned int index) const { return m_sc.IsCached(m_sArchive, index); }
+	void Append(unsigned int index, const void* data, unsigned int size)
+	{
+		m_sc.Append(m_sArchive, index, data, size);
+	}
+	void Cached(unsigned int index) { m_sc.Cached(m_sArchive, index); }
+	void PurgeUnmarked() { m_sc.PurgeUnmarked(m_sArchive); }
+	void GetContent(unsigned int index, void* dest, unsigned int size) const
+	{
+		m_sc.GetContent(m_sArchive, index, dest, size);
+	}
+	void OutputContent(unsigned int index, unsigned int size, FILE* fp) const
+	{
+		m_sc.OutputContent(m_sArchive, index, size, fp);
+	}
+
+	void GetExtractVector(std::vector<UINT32> &v, UINT32 max_num)
+	{
+		m_nMaxNum = max_num;
+		v.resize(m_nMaxNum);
+		for(UINT32 i = 0; i < m_nMaxNum; ++i) v[i] = i;
+	}
+	template<typename Callable>
+	void Extract(Callable c, unsigned int index)
+	{
+		OutputDebugPrintf("SolidFileCache::Extract(): called for %s %d\n", m_sArchive.c_str(), index);
+		boost::unique_lock<SolidCache::Mutex> lock(SolidCache::GetMutex());
+		if(!IsCached_(index)) {
+			OutputDebugPrintf("SolidFileCache::Extract(): Not cached for %s %d\n", m_sArchive.c_str(), index);
+			boost::shared_ptr<boost::condition_variable_any> cv = m_sc.GetQueue().GetCondVar(m_sArchive,index);
+			if(!m_sc.GetQueue().IsQueued(m_sArchive)) {
+				OutputDebugPrintf("SolidFileCache::Extract(): Not queued for %s\n", m_sArchive.c_str());
+				m_sc.GetQueue().Invoke(m_sArchive, c);
+				boost::this_thread::yield();
+			}
+			bool signaled = false;
+			while(!signaled && !IsCached_(index) && /* Defensive to avoid deadlock */ m_sc.GetQueue().IsQueued(m_sArchive)) {
+				signaled = cv->wait_for(lock, boost::chrono::milliseconds(500)) != boost::cv_status::timeout;
+				lock.unlock();
+				boost::this_thread::yield();
+				MSG msg;
+				while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+					TranslateMessage(&msg); 
+					DispatchMessage(&msg); 
+					boost::this_thread::yield();
+				}
+				lock.lock();
+			}
+		}
+		OutputDebugPrintf("SolidFileCache::Extract(): cached for %s %d\n", m_sArchive.c_str(), index);
+	}
+	int GetProgress(UINT32 index)
+	{
+		return index;
+	}
+	int GetProgressDenom(UINT32 index)
+	{
+		return m_nMaxNum;
+	}
+};
+
+#endif
\ No newline at end of file
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCacheDisk.cpp ./7z/7zip/Bundles/ax7z/SolidCacheDisk.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/SolidCacheDisk.cpp	1970-01-01 09:00:00.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/SolidCacheDisk.cpp	2015-01-09 00:41:22.378851500 +0900
@@ -0,0 +1,551 @@
+#include <iostream>
+#define NOMINMAX
+#include <windows.h>
+#undef NOMINMAX
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sqlite3/sqlite3.h"
+#include "sqlite3/sqlite3helper.h"
+#include "SolidCache.h"
+
+#include "7z/Common/MyString.h"
+#include "7z/Common/StringConvert.h"
+
+using yak::sqlite::Statement;
+
+void dump_table(sqlite3 *db, char *name)
+{
+	std::cout << '[' << name << ']' << std::endl;
+	char buf[2048];
+	sqlite3_snprintf(sizeof(buf), buf, "select * from %s", name);
+	Statement stmt(db, buf);
+	while(stmt()) {
+		int nColumn = stmt.get_count();
+		for(int i=0;i<nColumn;++i) {
+			std::cout << stmt.get_name(i) << ':';
+			switch(stmt.get_type(i)) {
+			case SQLITE_INTEGER:
+				std::cout << stmt.get_int(i);
+				break;
+			case SQLITE_FLOAT:
+				std::cout << stmt.get_double(i);
+				break;
+			case SQLITE_TEXT:
+				std::cout << stmt.get_text(i);
+				break;
+			case SQLITE_BLOB:
+				std::cout << '(' << stmt.get_bytes(i) << ')';
+				break;
+			case SQLITE_NULL:
+				std::cout << "NULL";
+				break;
+			}
+			std::cout << '\t';
+		}
+		std::cout << std::endl;
+	}
+}
+
+SolidCacheDisk::~SolidCacheDisk()
+{
+	m_db.close();
+}
+
+bool SolidCacheDisk::OpenDB_()
+{
+	try {
+		std::string sDB = GetCacheFolder() + "ax7z_s.db";
+		UString us(GetUnicodeString(sDB.c_str()));
+		int nLen = WideCharToMultiByte(CP_UTF8, 0, us.GetBuffer(0), -1, 0, 0, 0, 0);
+		std::vector<char> vBuf(nLen);
+		WideCharToMultiByte(CP_UTF8, 0, us.GetBuffer(0), -1, &vBuf[0], vBuf.size(), 0, 0);
+		m_db.reopen(&vBuf[0]);
+	} catch(yak::sqlite::sqlite_error &e) {
+		return false;
+	}
+	return true;
+}
+
+void SolidCacheDisk::InitDB_()
+{
+	Statement stmt_enc(m_db, "pragma encoding");
+	if(stmt_enc()) {
+		std::string sEnc(stmt_enc.get_text(0));
+		if(sEnc != "UTF-8") {
+			OutputDebugPrintf("SolidCacheDisk::InitDB: encoding is not UTF-8, recreating DB\n");
+			stmt_enc.finalize();
+			std::string sDB = GetCacheFolder() + "ax7z_s.db";
+			try {
+				m_db.close();
+			} catch (yak::sqlite::sqlite_error &e) {
+				OutputDebugPrintf("SolidCache::InitDB: sqlite3_close for %s failed by %s\n", sDB.c_str(), sqlite3_errmsg(m_db));
+			}
+			if(!DeleteFile(sDB.c_str())) {
+				OutputDebugPrintf("SolidCache::InitDB: deleting %s failed %d\n", sDB.c_str(), GetLastError());
+			}
+			if(!OpenDB_()) {
+				OutputDebugPrintf("SolidCache::InitDB: sqlite3_open for %s failed by %s\n", sDB.c_str(), sqlite3_errmsg(m_db));
+			}
+			sqlite3_exec(m_db, "PRAGMA encoding = \"UTF-8\"", NULL, NULL, NULL);
+		}
+	}
+	m_db.exec("PRAGMA journal_mode = OFF");
+	m_db.exec("PRAGMA synchronous = OFF"); // very effective
+	m_db.exec("PRAGMA temp_store = MEMORY");
+	Statement stmt(m_db, "pragma user_version");
+	if(stmt() && stmt.get_int(0) > 0) {
+		switch(stmt.get_int(0)) {
+		case 1:
+			OutputDebugPrintf("SolidCacheDisk::InitDB: version 1 exists, need to update\n");
+			m_db.exec("ALTER TABLE archive ADD COLUMN mtime INTEGER");
+			m_db.exec("ALTER TABLE archive ADD COLUMN size INTEGER");
+			{
+				Statement stmt2(m_db, "SELECT rowid FROM entry WHERE completed <> 1");
+				while(stmt2()) {
+					OutputDebugPrintf("SolidCacheDisk::InitDB(): DeleteFile %s\n", GetFileName(stmt2.get_int64(0)).c_str());
+					DeleteFile(GetFileName(stmt2.get_int64(0)).c_str());
+				}
+			}
+			m_db.exec("DELETE FROM entry WHERE completed <> 1");
+			m_db.exec("UPDATE entry SET completed = 0");
+			m_db.exec("PRAGMA user_version = 2");
+			break;
+		case 2:
+			OutputDebugPrintf("SolidCacheDisk::InitDB: version 2 exists, skip\n");
+			break;
+		default:
+			OutputDebugPrintf("SolidCacheDisk::InitDB: Unknown version %d\n", stmt.get_int(0));
+			break;
+		}
+	} else {
+		OutputDebugPrintf("SolidCacheDisk::InitDB: Create version 2\n");
+		m_db.exec("PRAGMA user_version = 2");
+		m_db.exec("CREATE TABLE archive (idx INTEGER PRIMARY KEY AUTOINCREMENT, path TEXT, atime INTEGER, mtime INTEGER, size INTEGER)");
+		m_db.exec("CREATE TABLE entry (aidx INTERGER, idx INTEGER, size INTEGER, completed INTEGER, CONSTRAINT pkey PRIMARY KEY (aidx, idx) )");
+	}
+}
+
+void SolidCacheDisk::CheckDB_()
+{
+	Statement stmt(m_db, "SELECT idx, path, mtime, size FROM archive");
+	while(stmt()) {
+		if(stmt.get_int64(2) == 0 && stmt.get_int64(3) == 0) continue;
+		struct __stat64 st;
+		if(!_stat64(stmt.get_text(1), &st) && st.st_mtime == stmt.get_int64(2) && st.st_size == stmt.get_int64(3))
+			continue;
+		Statement stmt2(m_db, "SELECT rowid FROM entry WHERE aidx = ?");
+		stmt2.bind(1, stmt.get_int(0));
+		while(stmt2()) {
+			OutputDebugPrintf("SolidCacheDisk::CheckDB(): DeleteFile %s\n", GetFileName(stmt2.get_int64(0)).c_str());
+			DeleteFile(GetFileName(stmt2.get_int64(0)).c_str());
+		}
+		Statement(m_db, "DELETE FROM entry WHERE aidx = ?").bind(1, stmt.get_int(0))();
+		OutputDebugPrintf("SolidCacheDisk::CheckDB invalid %s %u actualtime %" UINT64_S "u dbmtime %" UINT64_S "u actualsize %" UINT64_S "u dbsize %" UINT64_S "u\n", stmt.get_text(1), stmt.get_int(0), st.st_mtime, stmt.get_int64(2), st.st_size, stmt.get_int64(3));
+	}
+	PurgeUnreferenced_();
+}
+
+std::string SolidCacheDisk::GetFileName(__int64 id) const
+{
+	char buf[32768];
+	wsprintf(buf, "%sax7z_s%08X%08X.tmp", m_sCacheFolder.c_str(), static_cast<unsigned int>(id >> 32), static_cast<unsigned int>(id & 0xFFFFFFFF));
+	return std::string(buf);
+}
+
+bool SolidCacheDisk::ExistsArchive_(const char* archive) const
+{
+	struct __stat64 st;
+	if(!_stat64(archive, &st)) {
+		Statement stmt(m_db, "SELECT COUNT(*) FROM archive WHERE path = ? AND mtime = ? AND size = ?");
+		stmt.bind(1, archive).bind(2, st.st_mtime).bind(3, st.st_size);
+		bool success = stmt();
+		OutputDebugPrintf("SolidCacheDisk::ExistsArchive_(): archive %s : %d [%d]\n", archive, int(success), stmt.get_int(0));
+		return success && stmt.get_int(0) > 0;
+	}
+// TODO: proper error handling
+	OutputDebugPrintf("ERROR on SolidCacheDisk::ExistArchive_ archive %s\n", archive);
+	return false;
+}
+
+void SolidCacheDisk::AddArchive_(const char* archive)
+{
+	struct __stat64 st;
+	if(!_stat64(archive, &st)) {
+		Statement(m_db, "INSERT INTO archive (path, atime, mtime, size) VALUES (?, 0, ?, ?)")
+			.bind(1, archive).bind(2, st.st_mtime).bind(3, st.st_size)();
+		OutputDebugPrintf("SolidCacheDisk::AddArchive archive %s mtime %" UINT64_S "u size %" UINT64_S "u\n", archive, st.st_mtime, st.st_size);
+	} else {
+// TODO: proper error handling
+		OutputDebugPrintf("ERROR on SolidCacheDisk::AddArchive_ archive %s\n", archive);
+	}
+}
+
+unsigned int SolidCacheDisk::GetArchiveIdx_(const char* archive) const
+{
+	struct __stat64 st;
+	if(!_stat64(archive, &st)) {
+		Statement stmt(m_db, "SELECT idx FROM archive WHERE path = ? AND mtime = ? AND size = ?");
+		bool success = stmt.bind(1, archive).bind(2, st.st_mtime).bind(3, st.st_size)();
+		OutputDebugPrintf("SolidCacheDisk::GetArchiveIdx_(): archive %s : %d [%d]\n", archive, int(success), stmt.get_int(0));
+		return stmt.get_int(0);
+	}
+// TODO: proper error handling
+	OutputDebugPrintf("ERROR on SolidCacheDisk::GetArchiveIdx_ archive %s\n", archive);
+	return 0;
+}
+
+bool SolidCacheDisk::ExistsEntry_(unsigned int aidx, unsigned int idx) const
+{
+	Statement stmt(m_db, "SELECT COUNT(*) FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, idx);
+	return stmt() && stmt.get_int(0) > 0;
+}
+
+void SolidCacheDisk::AppendEntry_(unsigned int aidx, unsigned int idx, const void* data, unsigned int size)
+{
+	Statement stmt(m_db, "SELECT size, completed, rowid FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, idx)();
+	if(stmt.get_int(1) == GetCurrentThreadId()) {
+		int old_size = stmt.get_int(0);
+		FILE *fp = fopen(GetFileName(stmt.get_int64(2)).c_str(), "a+b");
+		fwrite(data, size, 1, fp);
+		fclose(fp);
+
+		stmt.reprepare(m_db, "UPDATE entry SET size = ? WHERE aidx = ? AND idx = ?")
+		    .bind(1, old_size + size).bind(2, aidx).bind(3, idx)();
+	}
+}
+
+void SolidCacheDisk::AddEntry_(unsigned int aidx, unsigned int idx, const void *data, unsigned int size)
+{
+	Statement(m_db, "INSERT INTO entry (aidx, idx, size, completed) VALUES (?, ?, ?, ?)")
+	    .bind(1, aidx).bind(2, idx).bind(3, size).bind(4, static_cast<int>(GetCurrentThreadId()))();
+	Statement stmt(m_db, "SELECT size, completed, rowid FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, idx)();
+	FILE *fp = fopen(GetFileName(stmt.get_int64(2)).c_str(), "wb");
+	fwrite(data, size, 1, fp);
+	fclose(fp);
+}
+
+void SolidCacheDisk::Append_(const char* archive, unsigned int idx, const void* data, unsigned int size)
+{
+	OutputDebugPrintf("SolidCacheDisk::Append: archive %s idx %u size %u\n", archive, idx, size);
+	if(!ExistsArchive_(archive)) {
+		AddArchive_(archive);
+	}
+
+	unsigned int aidx = GetArchiveIdx_(archive);
+	if(GetMaxDisk() >= 0 && GetSize_() + size >= GetMaxDiskInBytes()) {
+//		PurgeUnmarkedOther_(aidx);
+		if(GetSize_() + size >= GetMaxDiskInBytes()) {
+			ReduceSize_(std::max(GetPurgeDiskInBytes(), GetSize_() + size - GetMaxDiskInBytes()), aidx);
+		}
+	}
+	if(!ExistsArchive_(archive)) {
+		AddArchive_(archive);
+		aidx = GetArchiveIdx_(archive);
+		OutputDebugPrintf("SolidCacheDisk::Append: Should not reach: new aidx %d\n", aidx);
+	}
+	if(ExistsEntry_(aidx, idx)) {
+		AppendEntry_(aidx, idx, data, size);
+	} else {
+		AddEntry_(aidx, idx, data, size);
+	}
+}
+
+void SolidCacheDisk::Cached_(const char* archive, unsigned int idx)
+{
+	if(IsProcessing_(archive, idx)) {
+		unsigned int aidx = GetArchiveIdx_(archive); 
+		Statement(m_db, "UPDATE entry SET completed = 0 WHERE idx = ? AND aidx = ?")
+		    .bind(1, idx).bind(2, aidx)();
+	}
+}
+
+void SolidCacheDisk::CachedVector_(const char* archive, std::vector<unsigned int>& vIndex)
+{
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "UPDATE entry SET completed = 0 WHERE idx = ? AND aidx = ?");
+	stmt.bind(2, aidx);
+	std::vector<unsigned int>::iterator it = vIndex.begin(), itEnd = vIndex.end();
+	for(; it != itEnd; ++it) {
+		if(IsProcessing_(archive, *it)) {
+			OutputDebugPrintf("SolidCacheDisk::CachedVector %s %u\n", archive, *it);
+			stmt.bind(1, *it)();
+			stmt.reset();
+		}
+	}
+}
+
+void SolidCacheDisk::PurgeUnreferenced_()
+{
+	OutputDebugPrintf("SolidCacheDisk::PurgeUnreferenced()\n");
+	m_db.exec("DELETE FROM archive WHERE idx NOT IN (SELECT aidx FROM entry)");
+}
+
+void SolidCacheDisk::PurgeUnreferencedOther_(unsigned int aidx)
+{
+	OutputDebugPrintf("SolidCacheDisk::PurgeUnreferencedOther(): aidx %u\n", aidx);
+	Statement(m_db, "DELETE FROM archive WHERE idx NOT IN (SELECT aidx FROM entry) AND idx <> ?").bind(1, aidx)();
+}
+
+void SolidCacheDisk::PurgeUnreferencedWithAIdx_(unsigned int aidx)
+{
+	OutputDebugPrintf("SolidCacheDisk::PurgeUnreferencedWithAIdx(): aidx %u\n", aidx);
+	Statement(m_db, "DELETE FROM archive WHERE idx NOT IN (SELECT aidx FROM entry) AND idx = ?").bind(1, aidx)();
+}
+
+void SolidCacheDisk::PurgeUnmarked_(const char *archive)
+{
+	OutputDebugPrintf("SolidCacheDisk::PurgeUnmarked(): archive %s\n", archive);
+	unsigned int aidx = SolidCacheDisk::GetArchiveIdx_(archive);
+// TODO: transaction
+// TODO: may need to restrict rows affected by current thread
+	Statement stmt(m_db, "SELECT rowid FROM entry WHERE completed <> 0 AND aidx = ?");
+	stmt.bind(1, aidx);
+	while(stmt()) {
+		OutputDebugPrintf("SolidCacheDisk::PurgeUnmarked(): DeleteFile %s\n", GetFileName(stmt.get_int64(0)).c_str());
+		DeleteFile(GetFileName(stmt.get_int64(0)).c_str());
+	}
+	Statement(m_db, "DELETE FROM entry WHERE completed <> 0 AND aidx = ?")
+	    .bind(1, aidx)();
+	PurgeUnreferencedWithAIdx_(aidx);
+}
+
+void SolidCacheDisk::PurgeUnmarkedAll_()
+{
+// TODO: transaction
+	Statement stmt(m_db, "SELECT rowid FROM entry WHERE completed <> 0");
+	while(stmt()) {
+		OutputDebugPrintf("SolidCacheDisk::PurgeUnmarkedAll(): DeleteFile %s\n", GetFileName(stmt.get_int64(0)).c_str());
+		DeleteFile(GetFileName(stmt.get_int64(0)).c_str());
+	}
+	m_db.exec("DELETE FROM entry WHERE completed <> 0");
+	PurgeUnreferenced_();
+}
+
+void SolidCacheDisk::PurgeUnmarkedOther_(unsigned int aidx)
+{
+// TODO: transaction
+	Statement stmt(m_db, "SELECT rowid FROM entry WHERE aidx <> ? AND completed <> 0");
+	stmt.bind(1,aidx);
+	while(stmt()) {
+		OutputDebugPrintf("SolidCacheDisk::PurgeUnmarkedOther(): DeleteFile %s\n", GetFileName(stmt.get_int64(0)).c_str());
+		DeleteFile(GetFileName(stmt.get_int64(0)).c_str());
+	}
+	Statement(m_db, "DELETE FROM entry WHERE aidx <> ? AND completed <> 0").bind(1,aidx)();
+	PurgeUnreferencedOther_(aidx);
+}
+
+boost::uint64_t SolidCacheDisk::GetSize_() const
+{
+	Statement stmt(m_db, "select sum(size) from entry");
+	stmt();
+	return stmt.get_int64(0);
+}
+
+void SolidCacheDisk::ReduceSizeWithAIdx_(unsigned int aidx, boost::uint64_t size)
+{
+// TODO: transaction
+	OutputDebugPrintf("SolidCacheDisk::ReduceSizeWithAidx: aidx %u size %" UINT64_S "u\n", aidx, size);
+	boost::uint64_t total = 0;
+	int idx = -1;
+	Statement stmt(m_db, "SELECT idx, size, rowid FROM entry WHERE aidx = ? AND completed = 0 ORDER BY idx");
+	stmt.bind(1, aidx);
+	while(stmt()) {
+		idx = stmt.get_int(0);
+		total += stmt.get_int64(1);
+		OutputDebugPrintf("SolidCacheDisk::ReduceSizeWithAIdx(): DeleteFile %s\n", GetFileName(stmt.get_int64(2)).c_str());
+		DeleteFile(GetFileName(stmt.get_int64(2)).c_str());
+		if(total >= size) break;
+	}
+
+	stmt.reprepare(m_db, "DELETE FROM entry WHERE completed = 0 AND aidx = ? AND idx <= ?");
+	stmt.bind(1, aidx).bind(2, idx)();
+	PurgeUnreferencedWithAIdx_(aidx);
+}
+
+void SolidCacheDisk::ReduceSize_(boost::uint64_t size, unsigned int exclude_aidx)
+{
+	OutputDebugPrintf("SolidCacheDisk::ReduceSize: size %" UINT64_S "u exclude_aidx %u\n", size, exclude_aidx);
+	boost::uint64_t cur_size = GetSize_();
+	while(size > 0 && cur_size != 0) {
+		Statement stmt(m_db, "SELECT archive.idx FROM archive, entry WHERE archive.idx <> ? AND archive.idx = entry.aidx AND entry.completed = 0 GROUP BY archive.idx HAVING count(entry.idx) > 0 ORDER BY atime LIMIT 1");
+		stmt.bind(1, exclude_aidx);
+		if(stmt()) {
+			unsigned int aidx = stmt.get_int(0);
+			ReduceSizeWithAIdx_(aidx, size);
+			boost::uint64_t new_size = GetSize_();
+			OutputDebugPrintf("SolidCacheDisk::ReduceSize: size %" UINT64_S "u cur_size %" UINT64_S "u new_size %" UINT64_S "u\n", size, cur_size, new_size);
+			if(cur_size - new_size < size) size -= (cur_size - new_size);
+			else size = 0;
+			cur_size = new_size;
+		} else break;
+	}
+}
+
+void SolidCacheDisk::AccessArchive_(const char* archive)
+{
+	OutputDebugPrintf("SolidCacheDisk::AccessArchive(): archive: %s\n", archive);
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	std::time_t atime;
+	std::time(&atime);
+	Statement(m_db, "UPDATE archive SET atime = ? WHERE idx = ?")
+	    .bind(1, (int)atime).bind(2, aidx)();
+}
+
+bool SolidCacheDisk::IsCached_(const char* archive, unsigned int idx) const
+{
+	OutputDebugPrintf("SolidCacheDisk::IsCached(): archive: %s idx %d\n", archive, idx);
+	if(!ExistsArchive_(archive)) return false;
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "SELECT COUNT(*) FROM entry WHERE aidx = ? AND idx = ? AND completed = 0");
+	stmt.bind(1, aidx).bind(2, idx);
+	return stmt() && stmt.get_int(0) > 0;
+}
+
+bool SolidCacheDisk::Exists_(const char* archive, unsigned int idx) const
+{
+	OutputDebugPrintf("SolidCacheDisk::Exists(): archive: %s idx %d\n", archive, idx);
+	if(!ExistsArchive_(archive)) return false;
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "SELECT COUNT(*) FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, idx);
+	return stmt() && stmt.get_int(0) > 0;
+}
+
+bool SolidCacheDisk::IsProcessing_(const char *archive, unsigned int idx) const
+{
+	OutputDebugPrintf("SolidCacheDisk::IsProcessing(): archive: %s idx %d\n", archive, idx);
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "SELECT COUNT(*) FROM entry WHERE aidx = ? AND idx = ? AND completed <> 0");
+	stmt.bind(1, aidx).bind(2, idx);
+	return stmt() && stmt.get_int(0) > 0;
+}
+
+class MMap
+{
+private:
+	HANDLE hFile;
+	HANDLE hView;
+	LPVOID pMap;
+public:
+	MMap(const std::string& name, unsigned int size)
+	{
+		hFile = CreateFile(name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+		hView = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+		pMap = MapViewOfFile(hView, FILE_MAP_READ, 0, 0, size);
+//		OutputDebugPrintf("hFile %08X hView %08X pMap %08X", hFile, hView, pMap);
+	}
+	operator LPVOID() { return pMap; }
+	~MMap()
+	{
+		UnmapViewOfFile(pMap);
+		CloseHandle(hView);
+		CloseHandle(hFile);
+	}
+};
+
+void SolidCacheDisk::GetContent_(const char *archive, unsigned int index, void* dest, unsigned int size) const
+{
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "SELECT rowid, size FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, index)();
+	unsigned int uiSize = std::min<unsigned int>(size, stmt.get_int(1));
+	MMap mm(GetFileName(stmt.get_int64(0)), uiSize);
+	CopyMemory(dest, mm, uiSize);
+	OutputDebugPrintf("SolidCacheDisk::GetContent: %s %u %p reqsize: %u dbsize: %u\n", archive, index, dest, size, stmt.get_int(1));
+}
+
+void SolidCacheDisk::OutputContent_(const char *archive, unsigned int index, unsigned int size, FILE* fp) const
+{
+	unsigned int aidx = GetArchiveIdx_(archive); 
+	Statement stmt(m_db, "SELECT rowid, size FROM entry WHERE aidx = ? AND idx = ?");
+	stmt.bind(1, aidx).bind(2, index)();
+	unsigned int uiSize = std::min<unsigned int>(size, stmt.get_int(1));
+	MMap mm(GetFileName(stmt.get_int64(0)), uiSize);
+	fwrite(mm, uiSize, 1, fp);
+	OutputDebugPrintf("SolidCacheDisk::OutputContent: %s %u %p reqsize: %u dbsize: %u\n", archive, index, fp, size, stmt.get_int(1));
+}
+
+SolidCacheDisk& SolidCacheDisk::GetInstance()
+{
+	static SolidCacheDisk scSingleton;
+	return scSingleton;
+}
+
+SolidFileCacheDisk SolidCacheDisk::GetFileCache(const std::string& filename)
+{
+	return SolidFileCacheDisk(GetInstance(), filename);
+}
+
+void SolidCacheDisk::Clear_()
+{
+	std::string sDB = GetCacheFolder() + "ax7z_s.db";
+	std::string s;
+
+	m_db.close();
+	DeleteFile(sDB.c_str());
+	s = GetCacheFolder() + "ax7z_s????????????????.tmp";
+	WIN32_FIND_DATA find;
+	HANDLE hFind;
+	hFind = FindFirstFile(s.c_str(), &find);
+	if(hFind != INVALID_HANDLE_VALUE) {
+		do {
+			s = GetCacheFolder() + find.cFileName;
+			DeleteFile(s.c_str());
+		} while(FindNextFile(hFind, &find));
+		CloseHandle(hFind);
+	}
+	if(!OpenDB_()) {
+		OutputDebugPrintf("SolidCache::Clear: sqlite3_open for %s failed by %s\n", sDB.c_str(), sqlite3_errmsg(m_db));
+	}
+	InitDB_();
+}
+
+std::string SolidCacheDisk::SetCacheFolder(std::string sNew)
+{
+	boost::shared_lock<SolidCache::Mutex> guard(SolidCache::GetMutex());
+
+	{
+		const char* temp = sNew.c_str();
+		const char* temp2 = temp + sNew.size();
+		if(*CharPrev(temp, temp2) != '\\') sNew += '\\';
+	}
+	if(sNew != m_sCacheFolder) {
+	    m_db.close();
+		std::string sNewDB = sNew + "ax7z_s.db";
+		if(m_sCacheFolder != "") {
+			std::string sOldDB = m_sCacheFolder + "ax7z_s.db";
+			MoveFileEx(sOldDB.c_str(), sNewDB.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
+			std::string s = m_sCacheFolder + "ax7z_s????????????????.tmp";
+			WIN32_FIND_DATA find;
+			HANDLE hFind;
+			hFind = FindFirstFile(s.c_str(), &find);
+			if(hFind != INVALID_HANDLE_VALUE) {
+				do {
+					s = m_sCacheFolder + find.cFileName;
+					std::string sNewData = sNew + find.cFileName;
+					MoveFileEx(s.c_str(), sNewData.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
+				} while(FindNextFile(hFind, &find));
+				CloseHandle(hFind);
+			}
+		}
+		std::swap(sNew, m_sCacheFolder);
+		if(!OpenDB_()) {
+			OutputDebugPrintf("SetCacheFolder: sqlite3_open for %s failed by %s\n", sNewDB.c_str(), sqlite3_errmsg(m_db));
+		}
+		InitDB_();
+		CheckDB_();
+	}
+	return sNew;
+}
+
+void SolidCacheDisk::ReduceSizeCallback(void *pArg, const std::string& sArchive, unsigned int index, void* data, unsigned int size, bool flag)
+{
+	SolidCacheDisk *pscd = static_cast<SolidCacheDisk*>(pArg);
+	assert(!pscd->Exists_(sArchive.c_str(), index));
+	pscd->Append_(sArchive.c_str(), index, data, size);
+	if(flag) pscd->Cached_(sArchive.c_str(), index);
+}
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/bridge.cpp ./7z/7zip/Bundles/ax7z/bridge.cpp
--- /var/tmp/ax7z_src-orig/7z/7zip/Bundles/ax7z/bridge.cpp	2005-09-26 01:35:36.000000000 +0900
+++ ./7z/7zip/Bundles/ax7z/bridge.cpp	2015-01-09 00:41:22.382851900 +0900
@@ -2,10 +2,12 @@
 7-zip decode engine - susie bridge
 */
 
+#define NOMINMAX
 #include <windows.h>
+#undef NOMINMAX
+#include <commctrl.h>
 #include <initguid.h>
 #include <time.h>
-#include <vector>
 
 #include "entryFuncs.h"
 
@@ -25,17 +27,19 @@
 #include "ExtractCallback.h"
 #include "SolidArchiveExtractCallback.h"
 #include "OpenCallback.h"
-
-HINSTANCE g_hInstance = 0;
+#include "SolidCache.h"
+#include "PasswordManager.h"
+#include "resource.h"
+
+extern HINSTANCE g_hInstance;
+extern int g_nSolidEnable7z;
+extern int g_nSolidEnableRar;
 
 using namespace NWindows;
 using namespace NFile;
 
-static bool MyOpenArchive(const UString &archiveName, 
+static bool MyOpenArchive(CCodecs *cc, const UString &archiveName, 
                          const NFind::CFileInfoW &archiveFileInfo,
-#ifndef EXCLUDE_COM
-                         HMODULE *module,
-#endif
                          IInArchive **archiveHandler,
                          UString &defaultItemName,
                          bool &passwordEnabled, 
@@ -43,11 +47,8 @@
 {
     COpenCallbackImp2 *openCallbackSpec = new COpenCallbackImp2;
     CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
-    if (passwordEnabled)
-    {
-        openCallbackSpec->PasswordIsDefined = passwordEnabled;
-        openCallbackSpec->Password = password;
-    }
+
+    PasswordManager::Get().NotifyArchive(archiveName);
 
     UString fullName;
     int fileNamePartStartIndex;
@@ -56,26 +57,22 @@
         fullName.Left(fileNamePartStartIndex), 
         fullName.Mid(fileNamePartStartIndex));
 
-    CArchiverInfo archiverInfo;
-    HRESULT result = OpenArchive(archiveName, 
-#ifndef EXCLUDE_COM
-        module,
-#endif
-        archiveHandler, 
-        archiverInfo, 
-        defaultItemName,
-        openCallback);
-    if (result == S_FALSE) {
-        return false;
-    }
-    if (result != S_OK) {
-        return false;
-    }
-//    defaultItemName = GetDefaultName(archiveName, 
-//        archiverInfo.Extensions[subExtIndex].Extension, 
-//        archiverInfo.Extensions[subExtIndex].AddExtension);
-    passwordEnabled = openCallbackSpec->PasswordIsDefined;
-    password = openCallbackSpec->Password;
+    int dummy;
+    HRESULT result;
+	do {
+		result = OpenArchive(cc, archiveName, 
+			archiveHandler, 
+			dummy,
+			defaultItemName,
+			openCallback);
+		if (result != S_OK) {
+			PasswordManager::Get().NotifyError();
+			if(!PasswordManager::Get().IsRetry())
+				return false;
+		} else {
+			PasswordManager::Get().ClearError();
+		}
+	} while(result != S_OK && PasswordManager::Get().IsRetry());
 
     return true;
 }
@@ -93,13 +90,35 @@
     return true;
 }
 
-static bool IsSolid(IInArchive* archive, const NFind::CFileInfoW& archiverInfo, UINT32 numItems)
+enum SOLID_TYPE
+{
+    SOLID_NONE,
+    SOLID_RAR,
+    SOLID_7Z
+};
+
+static SOLID_TYPE IsSolid(IInArchive* archive, const NFind::CFileInfoW& archiverInfo, UINT32 numItems)
 {
     // rar ‚Ì�ê�‡‚Í kpidSolid‚ª�Ý’è‚³‚ê‚Ä‚¢‚é‚æ‚¤‚È‚Ì‚Å‚»‚¿‚ç‚ðŽg—p
+    // 7z ‚Ì�ê�‡‚Å‚à�Ý’è‚³‚ê‚Ä‚¢‚é�ê�‡‚ ‚è
     NCOM::CPropVariant propVariant;
     if (S_OK == archive->GetArchiveProperty(kpidSolid, &propVariant)) {
         if (propVariant.vt == VT_BOOL) {
-            return propVariant.bVal ? true : false;
+            if(propVariant.bVal) {
+                UString extension;
+                {
+                    int dotPos = archiverInfo.Name.ReverseFind(L'.');
+                    if (dotPos >= 0)
+                        extension = archiverInfo.Name.Mid(dotPos + 1);
+                }
+                if (extension.CompareNoCase(L"7z") == 0) {
+                    return SOLID_7Z;
+                } else {
+                    return SOLID_RAR;
+                }
+            } else {
+                return SOLID_NONE;
+            }
         }
     }
 
@@ -111,23 +130,23 @@
             extension = archiverInfo.Name.Mid(dotPos + 1);
     }
     if (extension.CompareNoCase(L"7z") == 0) {
-		NWindows::NCOM::CPropVariant aPropVariant;
-		BOOL bFlag = 0;
+        NWindows::NCOM::CPropVariant aPropVariant;
+        BOOL bFlag = 0;
         for (size_t i = 0; i < numItems; ++i) {
-			archive->GetProperty(i, kpidBlock, &aPropVariant);
+            archive->GetProperty(i, kpidBlock, &aPropVariant);
             if (aPropVariant.vt == 0) {
-				continue;
+                continue;
             }
             if (aPropVariant.ulVal > 0) {
-				break;
+                break;
             }
             if (bFlag) {
-                return true;
-			}
-			bFlag = TRUE;
-		}
+                return SOLID_7Z;
+            }
+            bFlag = TRUE;
+        }
     }
-    return false;
+    return SOLID_NONE;
 }
 
 int GetArchiveInfoEx(LPSTR filename, long len, HLOCAL *lphInf)
@@ -143,9 +162,15 @@
         return SPI_FILE_READ_ERROR;
     }
 
-#ifndef EXCLUDE_COM
-    NDLL::CLibrary library;
-#endif
+  CCodecs *codecs = new CCodecs;
+  CMyComPtr<
+    #ifdef EXTERNAL_CODECS
+    ICompressCodecsInfo
+    #else
+    IUnknown
+    #endif
+    > compressCodecsInfo = codecs;
+  HRESULT result0 = codecs->Load();
 
     bool passwordEnabled = false;
     UString password;
@@ -153,10 +178,7 @@
 
     // �‘ŒÉ‚ðŠJ‚­
     CMyComPtr<IInArchive> archiveHandler;
-    if (!MyOpenArchive(archiveName, archiveFileInfo, 
-#ifndef EXCLUDE_COM
-        &library,
-#endif
+    if (!MyOpenArchive(codecs, archiveName, archiveFileInfo, 
         &archiveHandler, 
         defaultItemName, passwordEnabled, password)) {
         return SPI_FILE_READ_ERROR;
@@ -168,7 +190,7 @@
     }
 
     // solid?
-    bool bSolid = IsSolid(archiveHandler, archiveFileInfo, numItems);
+    SOLID_TYPE stSolid = IsSolid(archiveHandler, archiveFileInfo, numItems);
 
     std::vector<fileInfo> vFileInfos;
     for (UINT32 i = 0; i < numItems; i++) {
@@ -178,7 +200,7 @@
         }
         UString filePath;
         if (propVariant.vt == VT_EMPTY) {
-            continue;
+            filePath = defaultItemName;
         } else if(propVariant.vt != VT_BSTR) {
             continue;
         } else {
@@ -187,9 +209,9 @@
 
         UINT64 unpackSize = 0;
         if (!GetUINT64Value(archiveHandler, i, kpidSize, unpackSize)) {
-            continue;
-        }
-        if (unpackSize == 0) {
+            // Archive handlers for, at least, bzip2 can return no unpackSize.
+            //continue;
+        } else  if (unpackSize == 0) {
             continue;
         }
 
@@ -203,7 +225,10 @@
             continue;
         }
         if (property.vt != VT_FILETIME) {
-            continue;
+            // Archive handlers for, at least, bzip2 and gzip can return no modified time.
+			property.filetime.dwHighDateTime = 0;
+			property.filetime.dwLowDateTime = 0;
+            //continue;
         }
         FILETIME fileTime = property.filetime;
         // first convert file time (UTC time) to local time
@@ -225,18 +250,26 @@
         atm.tm_year = sysTime.wYear - 1900;     // tm_year is 1900 based
         atm.tm_isdst = -1;
         time_t time = mktime(&atm);
-	
+    
         vFileInfos.push_back(fileInfo());
         fileInfo* pinfo = &vFileInfos.back();
-        if (bSolid) {
-    		lstrcpy((char*)pinfo->method, "7zip_s");
-        } else {
-    		lstrcpy((char*)pinfo->method, "7zip");
-        }
-		pinfo->position = i;
-		pinfo->compsize = static_cast<unsigned long>(packSize);
-		pinfo->filesize = static_cast<unsigned long>(unpackSize);
-		pinfo->timestamp = time;
+        switch(stSolid) {
+        case SOLID_NONE:
+            lstrcpy((char*)pinfo->method, "7zip");
+            break;
+        case SOLID_RAR:
+            lstrcpy((char*)pinfo->method, "7zip_s");
+            pinfo->method[7] = 'R';
+            break;
+        case SOLID_7Z:
+            lstrcpy((char*)pinfo->method, "7zip_s");
+            pinfo->method[7] = '7';
+            break;
+        }
+        pinfo->position = i;
+        pinfo->compsize = static_cast<unsigned long>(packSize);
+        pinfo->filesize = static_cast<unsigned long>(unpackSize);
+        pinfo->timestamp = time;
         // path
         UStringVector vPaths;
         SplitPathToParts(filePath, vPaths);
@@ -266,14 +299,20 @@
             s = s.Left(199);
         }
         strcpy(pinfo->filename, (LPCSTR)s);
-		pinfo->crc = 0;
+
+        pinfo->crc = 0;
+        if (S_OK == archiveHandler->GetProperty(i, kpidCRC, &property)) {
+            if (property.vt == VT_UI4) {
+                pinfo->crc = property.ulVal;
+            }
+        }
     }
 
-	/* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä(ƒtƒ@ƒCƒ‹�”+1‚¾‚¯‚Ì—Ìˆæ‚ª•K—v)�A0‚Å�‰Šú‰»‚µ‚Ä‚¨‚­ */
-	*lphInf = LocalAlloc(LPTR, sizeof(fileInfo) * (vFileInfos.size() + 1));
-	if (*lphInf == NULL) {
-		return SPI_NO_MEMORY;
-	}
+    /* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä(ƒtƒ@ƒCƒ‹�”+1‚¾‚¯‚Ì—Ìˆæ‚ª•K—v)�A0‚Å�‰Šú‰»‚µ‚Ä‚¨‚­ */
+    *lphInf = LocalAlloc(LPTR, sizeof(fileInfo) * (vFileInfos.size() + 1));
+    if (*lphInf == NULL) {
+        return SPI_NO_MEMORY;
+    }
 
     // Œ‹‰Ê‚Ì�ì�¬
     memcpy(*lphInf, &vFileInfos[0], sizeof(fileInfo) * vFileInfos.size());
@@ -281,7 +320,7 @@
     fileInfo* pLast = pFirst + vFileInfos.size();
     pLast->method[0] = '\0';
 
-	return SPI_ALL_RIGHT;
+    return SPI_ALL_RIGHT;
 }
 
 static int GetArchiveInfoWEx_impl(LPCWSTR filename, std::vector<fileInfoW>& vFileInfos)
@@ -297,9 +336,15 @@
         return SPI_FILE_READ_ERROR;
     }
 
-#ifndef EXCLUDE_COM
-    NDLL::CLibrary library;
-#endif
+    CCodecs *codecs = new CCodecs;
+    CMyComPtr<
+        #ifdef EXTERNAL_CODECS
+        ICompressCodecsInfo
+        #else
+        IUnknown
+        #endif
+    > compressCodecsInfo = codecs;
+    HRESULT result = codecs->Load();
 
     bool passwordEnabled = false;
     UString password;
@@ -307,10 +352,7 @@
 
     // �‘ŒÉ‚ðŠJ‚­
     CMyComPtr<IInArchive> archiveHandler;
-    if (!MyOpenArchive(archiveName, archiveFileInfo, 
-#ifndef EXCLUDE_COM
-        &library,
-#endif
+    if (!MyOpenArchive(codecs, archiveName, archiveFileInfo, 
         &archiveHandler, 
         defaultItemName, passwordEnabled, password)) {
         return SPI_FILE_READ_ERROR;
@@ -322,7 +364,7 @@
     }
 
     // solid?
-    bool bSolid = IsSolid(archiveHandler, archiveFileInfo, numItems);
+    SOLID_TYPE stSolid = IsSolid(archiveHandler, archiveFileInfo, numItems);
 
     for (UINT32 i = 0; i < numItems; i++) {
         NCOM::CPropVariant propVariant;
@@ -331,7 +373,7 @@
         }
         UString filePath;
         if (propVariant.vt == VT_EMPTY) {
-            continue;
+            filePath = defaultItemName;
         } else if(propVariant.vt != VT_BSTR) {
             continue;
         } else {
@@ -340,9 +382,9 @@
 
         UINT64 unpackSize = 0;
         if (!GetUINT64Value(archiveHandler, i, kpidSize, unpackSize)) {
-            continue;
-        }
-        if (unpackSize == 0) {
+            // Archive handlers for, at least, bzip2 can return no unpackSize.
+            //continue;
+        } else if (unpackSize == 0) {
             continue;
         }
 
@@ -356,7 +398,10 @@
             continue;
         }
         if (property.vt != VT_FILETIME) {
-            continue;
+            // Archive handlers for, at least, bzip2 and gzip can return no modified time.
+            property.filetime.dwHighDateTime = 0;
+            property.filetime.dwLowDateTime = 0;
+            //continue;
         }
         FILETIME fileTime = property.filetime;
         // first convert file time (UTC time) to local time
@@ -378,18 +423,26 @@
         atm.tm_year = sysTime.wYear - 1900;     // tm_year is 1900 based
         atm.tm_isdst = -1;
         time_t time = mktime(&atm);
-	
+    
         vFileInfos.push_back(fileInfoW());
         fileInfoW* pinfo = &vFileInfos.back();
-        if (bSolid) {
-    		lstrcpy((char*)pinfo->method, "7zip_s");
-        } else {
-    		lstrcpy((char*)pinfo->method, "7zip");
-        }
-		pinfo->position = i;
-		pinfo->compsize = static_cast<unsigned long>(packSize);
-		pinfo->filesize = static_cast<unsigned long>(unpackSize);
-		pinfo->timestamp = time;
+        switch(stSolid) {
+        case SOLID_NONE:
+            lstrcpy((char*)pinfo->method, "7zip");
+            break;
+        case SOLID_RAR:
+            lstrcpy((char*)pinfo->method, "7zip_s");
+            pinfo->method[7] = 'R';
+            break;
+        case SOLID_7Z:
+            lstrcpy((char*)pinfo->method, "7zip_s");
+            pinfo->method[7] = '7';
+            break;
+        }
+        pinfo->position = i;
+        pinfo->compsize = static_cast<unsigned long>(packSize);
+        pinfo->filesize = static_cast<unsigned long>(unpackSize);
+        pinfo->timestamp = time;
         // path
         UStringVector vPaths;
         SplitPathToParts(filePath, vPaths);
@@ -419,7 +472,12 @@
             s = s.Left(199);
         }
         wcscpy(pinfo->filename, (LPCWSTR)s);
-		pinfo->crc = 0;
+        pinfo->crc = 0;
+        if (S_OK == archiveHandler->GetProperty(i, kpidCRC, &property)) {
+            if (property.vt == VT_UI4) {
+                pinfo->crc = property.ulVal;
+            }
+        }
     }
     return SPI_ALL_RIGHT;
 }
@@ -432,11 +490,11 @@
         return nRet;
     }
 
-	/* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä(ƒtƒ@ƒCƒ‹�”+1‚¾‚¯‚Ì—Ìˆæ‚ª•K—v)�A0‚Å�‰Šú‰»‚µ‚Ä‚¨‚­ */
-	*lphInf = LocalAlloc(LPTR, sizeof(fileInfoW) * (vFileInfos.size() + 1));
-	if (*lphInf == NULL) {
-		return SPI_NO_MEMORY;
-	}
+    /* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä(ƒtƒ@ƒCƒ‹�”+1‚¾‚¯‚Ì—Ìˆæ‚ª•K—v)�A0‚Å�‰Šú‰»‚µ‚Ä‚¨‚­ */
+    *lphInf = LocalAlloc(LPTR, sizeof(fileInfoW) * (vFileInfos.size() + 1));
+    if (*lphInf == NULL) {
+        return SPI_NO_MEMORY;
+    }
 
     // Œ‹‰Ê‚Ì�ì�¬
     memcpy(*lphInf, &vFileInfos[0], sizeof(fileInfoW) * vFileInfos.size());
@@ -444,83 +502,330 @@
     fileInfoW* pLast = pFirst + vFileInfos.size();
     pLast->method[0] = '\0';
 
-	return SPI_ALL_RIGHT;
+    return SPI_ALL_RIGHT;
 }
 
-int GetFileEx(char *filename, HLOCAL *dest, const char* pOutFile, fileInfo *pinfo,
-			SPI_PROGRESS lpPrgressCallback, long lData)
+int GetFileExImp_Cached(HLOCAL *dest, const char* pOutFile, UINT32 iExtractFileIndex, UINT64 unpackSize, const SolidFileCache &scCache)
 {
-    UString archiveName = MultiByteToUnicodeString(filename);
+    FILE* fp = NULL;
+    if (dest) {
+        *dest = LocalAlloc(LMEM_FIXED, static_cast<size_t>(unpackSize));
+        if (*dest == NULL) {
+            return SPI_NO_MEMORY;
+        }
 
-    NFind::CFileInfoW archiveFileInfo;
-    if (!NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) {
-        return SPI_FILE_READ_ERROR;
+		// Due to Susie plugin specification, size should be in 32 bits.
+        scCache.GetContent(iExtractFileIndex, *dest, static_cast<unsigned int>(unpackSize));
+    } else {
+        fp = fopen(pOutFile, "wb");
+        if (fp == NULL) {
+            return SPI_FILE_WRITE_ERROR;
+        }
+		// Due to Susie plugin specification, size should be in 32 bits.
+        scCache.OutputContent(iExtractFileIndex, static_cast<unsigned int>(unpackSize), fp);
     }
 
-    if (archiveFileInfo.IsDirectory()) {
-        return SPI_FILE_READ_ERROR;
+    if (fp) {
+        fclose(fp);
     }
 
-#ifndef EXCLUDE_COM
-    NDLL::CLibrary library;
-#endif
-
-    bool passwordEnabled = false;
-    UString password;
-    UString defaultItemName;
+    return SPI_ALL_RIGHT;
+}
 
-    CMyComPtr<IInArchive> archiveHandler;
+INT_PTR CALLBACK ProgressDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+    switch (msg) {
+        case WM_INITDIALOG:
+			SetWindowLongPtr(hDlgWnd, DWLP_USER, 0);
+            return FALSE;
+		case WM_COMMAND:
+			if(HIWORD(wp) == BN_CLICKED && LOWORD(wp) == IDCANCEL)
+				SetWindowLongPtr(hDlgWnd, DWLP_USER, 1);
+			break;
 
-    if (!MyOpenArchive(archiveName, archiveFileInfo, 
-#ifndef EXCLUDE_COM
-        &library,
-#endif
-        &archiveHandler, 
-        defaultItemName, passwordEnabled, password)) {
-            return SPI_FILE_READ_ERROR;
     }
+    return FALSE;
+}
 
-    // ‰ð“€‚·‚×‚«ƒtƒ@ƒCƒ‹‚ÌƒCƒ“ƒfƒbƒNƒX‚ð‹�‚ß‚é
-    UINT32 iExtractFileIndex = pinfo->position;
-    UINT64 unpackSize = 0;
-    if (!GetUINT64Value(archiveHandler, iExtractFileIndex, kpidSize, unpackSize)) {
-        return SPI_FILE_READ_ERROR;
+struct ProgressArgument
+{
+    SPI_PROGRESS procTrueProgress;
+    long lTrueData;
+    HWND hwnd;
+};
+
+int PASCAL ProgressFunc(int nNum, int nDenom, long lData)
+{
+    ProgressArgument *pArg = reinterpret_cast<ProgressArgument*>(lData);
+    SendDlgItemMessage(pArg->hwnd, IDC_PROGRESSBAR, PBM_SETRANGE32, 0, nDenom);
+    SendDlgItemMessage(pArg->hwnd, IDC_PROGRESSBAR, PBM_SETPOS, nNum, 0);
+    char buf[1024];
+    wsprintf(buf, "%d / %d", nNum, nDenom);
+    SendDlgItemMessage(pArg->hwnd, IDC_PROGRESSTEXT, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(buf));
+	RedrawWindow(pArg->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+    MSG msg;
+    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+        TranslateMessage(&msg); 
+        DispatchMessage(&msg); 
     }
+	return ((pArg->procTrueProgress) ? (pArg->procTrueProgress)(nNum, nDenom, pArg->lTrueData) : 0) || GetWindowLongPtr(pArg->hwnd, DWLP_USER);
+}
 
-    // ‰ð“€
+int GetFileExImp_Normal(CMyComPtr<IInArchive> archiveHandler, HLOCAL *dest, const char* pOutFile, fileInfo *pinfo, SPI_PROGRESS lpPrgressCallback, long lData, UINT32 iExtractFileIndex, UINT64 unpackSize)
+{
     CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp;
     CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
 
+    ProgressArgument pa = {
+        lpPrgressCallback,
+        lData,
+        0
+    };
+
     FILE* fp = NULL;
     if (dest) {
         *dest = LocalAlloc(LMEM_FIXED, static_cast<size_t>(unpackSize));
         if (*dest == NULL) {
             return SPI_NO_MEMORY;
-        }
-        extractCallbackSpec->Init(archiveHandler, (char*)*dest, static_cast<UINT32>(unpackSize), NULL, iExtractFileIndex);
+		}
+        extractCallbackSpec->Init(archiveHandler, (char**)dest, static_cast<UINT32>(unpackSize), NULL, iExtractFileIndex, NULL, ProgressFunc, reinterpret_cast<long>(&pa));
     } else {
         fp = fopen(pOutFile, "wb");
         if (fp == NULL) {
             return SPI_FILE_WRITE_ERROR;
-        }
-        extractCallbackSpec->Init(archiveHandler, NULL, static_cast<UINT32>(unpackSize), fp, iExtractFileIndex);
+		}
+        extractCallbackSpec->Init(archiveHandler, NULL, static_cast<UINT32>(unpackSize), fp, iExtractFileIndex, NULL, ProgressFunc, reinterpret_cast<long>(&pa));
     }
 
-    HRESULT result = archiveHandler->Extract(&iExtractFileIndex, 1, false, extractCallback);
+	HRESULT result;
+
+    // It seems that password retry can not work for solid RAR
+    if(!lstrcmp((LPSTR)pinfo->method, "7zip_s") && pinfo->method[7] == 'R' && !PasswordManager::Get().IsValid())
+         PasswordManager::Get().Reset();
+
+    do {
+        extractCallbackSpec->m_NumErrors = 0;
+        result = archiveHandler->Extract(&iExtractFileIndex, 1, false, extractCallback);
+		if(PasswordManager::Get().IsRetry()) {
+			if (fp) rewind(fp);
+		}
+    } while(extractCallbackSpec->m_NumErrors != 0 && PasswordManager::Get().IsRetry());
 
     if (fp) {
         fclose(fp);
     }
 
     if (extractCallbackSpec->m_NumErrors != 0) {
-        ::DeleteFile(pOutFile);
+        if (dest) {
+            LocalFree(*dest);
+            *dest = NULL;
+        } else {
+            ::DeleteFile(pOutFile);
+        }
+        PasswordManager::Get().NotfiyEndFile();
+        return SPI_FILE_READ_ERROR;
+    }
+
+    PasswordManager::Get().NotfiyEndFile();
+    return SPI_ALL_RIGHT;
+}
+
+class Extractor
+{
+	CMyComPtr<IInArchive> archiveHandler;
+	SolidFileCache scCache;
+	SPI_PROGRESS lpPrgressCallback;
+	long lData;
+	std::string sFilename;
+	class Cleanup
+	{
+		std::string sArchive;
+		HANDLE hMutex;
+	public:
+		Cleanup(const std::string &s, HANDLE h) : sArchive(s), hMutex(h) {}
+		void operator()()
+		{
+			OutputDebugPrintf("Extractor::Cleanup::operator(): filename: %s", sArchive.c_str());
+			SolidCache::GetInstance().GetQueue().Cleanup(sArchive);
+			ReleaseMutex(hMutex);
+			CloseHandle(hMutex);
+			FreeLibraryAndExitThread(g_hInstance, 0);
+		}
+	};
+public:
+	Extractor(CMyComPtr<IInArchive> archiveHandler, const SolidFileCache &scCache, SPI_PROGRESS lpPrgressCallback, long lData, const char* filename) :
+		archiveHandler(archiveHandler), scCache(scCache), lpPrgressCallback(lpPrgressCallback), lData(lData), sFilename(filename)
+	{
+	}
+	void operator()()
+	{
+		OutputDebugPrintf("Extractor::operator(): filename: %s", sFilename.c_str());
+		HANDLE hMutex;
+		hMutex = CreateMutex(NULL, FALSE, "cx.myhome.yak.ax_7z_s.extractor");
+		WaitForSingleObject(hMutex, INFINITE);
+OutputDebugPrintf("Extractor::operator(): Lock acquired: filename: %s", sFilename.c_str());
+        boost::this_thread::at_thread_exit(Cleanup(sFilename, hMutex));
+
+	    CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp;
+	    CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
+
+	    ProgressArgument pa = {
+	        0 /*lpPrgressCallback */,
+	        lData,
+	        0
+	    };
+
+        // Just calling Append()
+	    extractCallbackSpec->Init(archiveHandler, NULL, 0, NULL, 0xFFFFFFFF, &scCache, ProgressFunc, reinterpret_cast<long>(&pa));
+
+	    UINT32 numItems;
+	    if (S_OK != archiveHandler->GetNumberOfItems(&numItems)) {
+	        return; // SPI_FILE_READ_ERROR;
+	    }
+	    // Currently, password retry do not work for solid archive.
+	    // Therefore, password is force flushed.
+	    if(!PasswordManager::Get().IsValid()) PasswordManager::Get().Reset();
+
+	    std::vector<UINT32> v;
+	// TODO: may need to call PurgeUnmarkedAll() somewhere
+	    scCache.PurgeUnmarked();
+	    scCache.GetExtractVector(v, numItems);
+	    pa.hwnd = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_PROGRESS), NULL, ProgressDlgProc);
+	    ProgressFunc(0, scCache.GetProgressDenom(0), reinterpret_cast<long>(&pa));
+	    HRESULT result = archiveHandler->Extract(&v[0], v.size(), false, extractCallback);
+	// TODO: may need to distribute cached mark
+		scCache.PurgeUnmarked();
+	    DestroyWindow(pa.hwnd);
+
+	    PasswordManager::Get().NotfiyEndFile();
+	}
+};
+
+void IncrementDLLRefCount()
+{
+	std::vector<char> buf(1024);
+	DWORD dwLen;
+	do {
+		dwLen = GetModuleFileName(g_hInstance, &buf[0], buf.size());
+	} while(dwLen == buf.size());
+	buf.resize(dwLen);
+	std::string s(buf.begin(), buf.end());
+	LoadLibrary(s.c_str()); // LoadLibraryEx with DONT_RESOLVE_DLL_REFERENCES is deprecated
+}
+
+int GetFileExImp_Caching(CMyComPtr<IInArchive> archiveHandler, HLOCAL *dest, const char* pOutFile, fileInfo *pinfo, SPI_PROGRESS lpPrgressCallback, long lData, UINT32 iExtractFileIndex, UINT64 unpackSize, SolidFileCache &scCache, const char* filename)
+{
+	FILE* fp = NULL;
+    if (dest) {
+        *dest = LocalAlloc(LMEM_FIXED, static_cast<size_t>(unpackSize));
+        if (*dest == NULL) {
+            return SPI_NO_MEMORY;
+		}
+    } else {
+        fp = fopen(pOutFile, "wb");
+        if (fp == NULL) {
+            return SPI_FILE_WRITE_ERROR;
+		}
+    }
+
+	IncrementDLLRefCount();
+    scCache.Extract(Extractor(archiveHandler, scCache, lpPrgressCallback, lData, filename), iExtractFileIndex);
+
+OutputDebugPrintf("IsCached(): calling 1 %p %d\n", &scCache, iExtractFileIndex);
+	if(scCache.IsCached(iExtractFileIndex)) {
+		if (dest) {
+			scCache.GetContent(iExtractFileIndex, *dest, static_cast<UINT32>(unpackSize));
+		} else {
+			scCache.OutputContent(iExtractFileIndex, static_cast<UINT32>(unpackSize), fp);
+		}
+	}
+
+    if (fp) {
+        fclose(fp);
+    }
+
+OutputDebugPrintf("IsCached(): calling 2 %p %d\n", &scCache, iExtractFileIndex);
+	if (!scCache.IsCached(iExtractFileIndex)) {
+        if (dest) {
+            LocalFree(*dest);
+            *dest = NULL;
+        } else {
+            ::DeleteFile(pOutFile);
+        }
+        PasswordManager::Get().NotfiyEndFile();
         return SPI_FILE_READ_ERROR;
     }
 
 	return SPI_ALL_RIGHT;
 }
+
+int GetFileEx(char *filename, HLOCAL *dest, const char* pOutFile, fileInfo *pinfo,
+            SPI_PROGRESS lpPrgressCallback, long lData)
+{
+	OutputDebugPrintf("GetFileEx(): called %s %d\n", filename, pinfo->position);
+    UString archiveName = MultiByteToUnicodeString(filename);
+
+    NFind::CFileInfoW archiveFileInfo;
+    if (!NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) {
+        return SPI_FILE_READ_ERROR;
+    }
+
+    if (archiveFileInfo.IsDirectory()) {
+        return SPI_FILE_READ_ERROR;
+    }
+
+    CCodecs *codecs = new CCodecs;
+    CMyComPtr<
+        #ifdef EXTERNAL_CODECS
+        ICompressCodecsInfo
+        #else
+        IUnknown
+        #endif
+    > compressCodecsInfo = codecs;
+    HRESULT result0 = codecs->Load();
+
+    bool passwordEnabled = false;
+    UString password;
+    UString defaultItemName;
+
+    CMyComPtr<IInArchive> archiveHandler;
+
+    if (!MyOpenArchive(codecs, archiveName, archiveFileInfo, 
+        &archiveHandler, 
+        defaultItemName, passwordEnabled, password)) {
+            return SPI_FILE_READ_ERROR;
+    }
+
+    // ‰ð“€‚·‚×‚«ƒtƒ@ƒCƒ‹‚ÌƒCƒ“ƒfƒbƒNƒX‚ð‹�‚ß‚é
+    UINT32 iExtractFileIndex = pinfo->position;
+    UINT64 unpackSize = 0;
+    if (!GetUINT64Value(archiveHandler, iExtractFileIndex, kpidSize, unpackSize)) {
+        // Archive handlers for, at least, bzip2 can return no unpackSize.
+        //return SPI_FILE_READ_ERROR;
+    }
+
+    // ‰ð“€
+    if(!lstrcmp((char*)pinfo->method, "7zip_s")
+        && ((pinfo->method[7] == 'R' && g_nSolidEnableRar)
+            || (pinfo->method[7] == '7' && g_nSolidEnable7z))) {
+        SolidFileCache scCache = SolidCache::GetFileCache(filename);
+        // TODO: There's race condition between IsCached and GetFileExImp_Normal
+OutputDebugPrintf("IsCached(): calling 3 %p %d\n", &scCache, iExtractFileIndex);
+        if(scCache.IsCached(iExtractFileIndex)) { // Cached
+			OutputDebugPrintf("GetFileEx(): %s %d, calling GetFileExImp_Cached\n", filename, pinfo->position);
+            return GetFileExImp_Cached(dest, pOutFile, iExtractFileIndex, unpackSize, scCache);
+        } else { // with Cache
+			OutputDebugPrintf("GetFileEx(): %s %d, calling GetFileExImp_Caching\n", filename, pinfo->position);
+            return GetFileExImp_Caching(archiveHandler, dest, pOutFile, pinfo, lpPrgressCallback, lData, iExtractFileIndex, unpackSize, scCache, filename);
+        }
+    } else { // Normal
+		OutputDebugPrintf("GetFileEx(): %s %d, calling GetFileExImp_Normal\n", filename, pinfo->position);
+        return GetFileExImp_Normal(archiveHandler, dest, pOutFile, pinfo, lpPrgressCallback, lData, iExtractFileIndex, unpackSize);
+    }
+}
+
 int GetFileWEx(wchar_t *filename, HLOCAL *dest, const wchar_t* pOutFile, fileInfoW *pinfo,
-			SPI_PROGRESS lpPrgressCallback, long lData)
+            SPI_PROGRESS lpPrgressCallback, long lData)
 {
     UString archiveName = filename;
 
@@ -533,9 +838,15 @@
         return SPI_FILE_READ_ERROR;
     }
 
-#ifndef EXCLUDE_COM
-    NDLL::CLibrary library;
-#endif
+    CCodecs *codecs = new CCodecs;
+    CMyComPtr<
+        #ifdef EXTERNAL_CODECS
+        ICompressCodecsInfo
+        #else
+        IUnknown
+        #endif
+    > compressCodecsInfo = codecs;
+    HRESULT result0 = codecs->Load();
 
     bool passwordEnabled = false;
     UString password;
@@ -543,10 +854,7 @@
 
     CMyComPtr<IInArchive> archiveHandler;
 
-    if (!MyOpenArchive(archiveName, archiveFileInfo, 
-#ifndef EXCLUDE_COM
-        &library,
-#endif
+    if (!MyOpenArchive(codecs, archiveName, archiveFileInfo, 
         &archiveHandler, 
         defaultItemName, passwordEnabled, password)) {
             return SPI_FILE_READ_ERROR;
@@ -556,7 +864,8 @@
     UINT32 iExtractFileIndex = pinfo->position;
     UINT64 unpackSize = 0;
     if (!GetUINT64Value(archiveHandler, iExtractFileIndex, kpidSize, unpackSize)) {
-        return SPI_FILE_READ_ERROR;
+        // Archive handlers for, at least, bzip2 can return no unpackSize.  
+        //return SPI_FILE_READ_ERROR;
     }
 
     // ‰ð“€
@@ -569,31 +878,54 @@
         if (*dest == NULL) {
             return SPI_NO_MEMORY;
         }
-        extractCallbackSpec->Init(archiveHandler, (char*)*dest, static_cast<UINT32>(unpackSize), NULL, iExtractFileIndex);
+        extractCallbackSpec->Init(archiveHandler, (char**)*dest, static_cast<UINT32>(unpackSize), NULL, iExtractFileIndex, &SolidCache::GetFileCache(std::string()), lpPrgressCallback, lData);
     } else {
         fp = _wfopen(pOutFile, L"wb");
         if (fp == NULL) {
             return SPI_FILE_WRITE_ERROR;
         }
-        extractCallbackSpec->Init(archiveHandler, NULL, static_cast<UINT32>(unpackSize), fp, iExtractFileIndex);
+        extractCallbackSpec->Init(archiveHandler, NULL, static_cast<UINT32>(unpackSize), fp, iExtractFileIndex, &SolidCache::GetFileCache(std::string()), lpPrgressCallback, lData);
     }
 
-    HRESULT result = archiveHandler->Extract(&iExtractFileIndex, 1, false, extractCallback);
+    HRESULT result;
+
+    // It seems that password retry can not work for solid RAR
+    if(!lstrcmp((LPSTR)pinfo->method, "7zip_s") && pinfo->method[7] == 'R' && !PasswordManager::Get().IsValid())
+        PasswordManager::Get().Reset();
+
+	do {
+        extractCallbackSpec->m_NumErrors = 0;
+		result = archiveHandler->Extract(&iExtractFileIndex, 1, false, extractCallback);
+		if(PasswordManager::Get().IsRetry()) {
+			if (fp) rewind(fp);
+		}
+	} while(extractCallbackSpec->m_NumErrors != 0 && PasswordManager::Get().IsRetry());
 
     if (fp) {
         fclose(fp);
     }
 
     if (extractCallbackSpec->m_NumErrors != 0) {
-        ::DeleteFileW(pOutFile);
+        if (dest) {
+            LocalFree(*dest);
+            *dest = NULL;
+        } else {
+            ::DeleteFileW(pOutFile);
+        }
+        PasswordManager::Get().NotfiyEndFile();
         return SPI_FILE_READ_ERROR;
     }
 
-	return SPI_ALL_RIGHT;
+   PasswordManager::Get().NotfiyEndFile();
+    return SPI_ALL_RIGHT;
 }
 
 int ExtractSolidArchiveEx(LPCWSTR filename, SPI_OnWriteCallback pCallback)
 {
+	// Currently, password retry do not work for solid archive.
+	// Therefore, password is force flushed.
+	if(!PasswordManager::Get().IsValid()) PasswordManager::Get().Reset();
+
     // ‰ð“€‚·‚×‚«ƒtƒ@ƒCƒ‹‚ÌƒCƒ“ƒfƒbƒNƒX‚ð‹�‚ß‚é
     std::vector<fileInfoW> vFileInfos;
     int nRet = GetArchiveInfoWEx_impl(filename, vFileInfos);
@@ -621,9 +953,15 @@
         return SPI_FILE_READ_ERROR;
     }
 
-#ifndef EXCLUDE_COM
-    NDLL::CLibrary library;
-#endif
+    CCodecs *codecs = new CCodecs;
+    CMyComPtr<
+        #ifdef EXTERNAL_CODECS
+        ICompressCodecsInfo
+        #else
+        IUnknown
+        #endif
+    > compressCodecsInfo = codecs;
+    HRESULT result0 = codecs->Load();
 
     bool passwordEnabled = false;
     UString password;
@@ -631,10 +969,7 @@
 
     CMyComPtr<IInArchive> archiveHandler;
 
-    if (!MyOpenArchive(archiveName, archiveFileInfo, 
-#ifndef EXCLUDE_COM
-        &library,
-#endif
+    if (!MyOpenArchive(codecs, archiveName, archiveFileInfo, 
         &archiveHandler, 
         defaultItemName, passwordEnabled, password)) {
             return SPI_FILE_READ_ERROR;
@@ -652,5 +987,32 @@
         return SPI_FILE_READ_ERROR;
     }
 
-	return SPI_ALL_RIGHT;
+    return SPI_ALL_RIGHT;
+}
+
+void GetFormats(std::vector<std::pair<std::string, std::string> > &res)
+{
+	std::map<std::string, std::string> mTable;
+	CCodecs *codecs = new CCodecs;
+    CMyComPtr<
+        #ifdef EXTERNAL_CODECS
+        ICompressCodecsInfo
+        #else
+        IUnknown
+        #endif
+    > compressCodecsInfo = codecs;
+	HRESULT result = codecs->Load();
+    int num = codecs->Formats.Size();
+	res.clear();
+	for(int i = 0; i < num; ++i) {
+        const CArcInfoEx &arc = codecs->Formats[i];
+        std::string arcname = UnicodeStringToMultiByte(arc.Name, CP_OEMCP);
+		int num_ext = arc.Exts.Size();
+		for(int j = 0; j < num_ext; ++j) {
+			if(!arc.Exts[j].Ext.IsEmpty()) {
+				std::string extname = UnicodeStringToMultiByte(arc.Exts[j].Ext, CP_OEMCP);
+				res.push_back(std::make_pair(extname, arcname));
+			}
+		}
+	}
 }
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/ax7z.def ./ax7z.def
--- /var/tmp/ax7z_src-orig/ax7z.def	2005-09-26 00:29:40.000000000 +0900
+++ ./ax7z.def	2013-08-24 11:36:30.042761100 +0900
@@ -9,4 +9,4 @@
 	GetFileInfoW
 	GetFileW
 	ConfigurationDlg
-    ExtractSolidArchive
\ No newline at end of file
+	ExtractSolidArchive
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/ax7z.rc ./ax7z.rc
--- /var/tmp/ax7z_src-orig/ax7z.rc	2005-08-25 23:08:40.000000000 +0900
+++ ./ax7z.rc	2015-01-09 00:41:22.397853400 +0900
@@ -1,6 +1,7 @@
 // Microsoft Visual C++ generated resource script.
 //
 #include "resource.h"
+#include "release.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
 /////////////////////////////////////////////////////////////////////////////
@@ -13,13 +14,11 @@
 #undef APSTUDIO_READONLY_SYMBOLS
 
 /////////////////////////////////////////////////////////////////////////////
-// “ú–{Œê resources
+// “ú–{Œê (“ú–{) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
-#ifdef _WIN32
 LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
 #pragma code_page(932)
-#endif //_WIN32
 
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
@@ -46,7 +45,7 @@
 
 #endif    // APSTUDIO_INVOKED
 
-#endif    // “ú–{Œê resources
+#endif    // “ú–{Œê (“ú–{) resources
 /////////////////////////////////////////////////////////////////////////////
 
 
@@ -54,50 +53,143 @@
 // ‰pŒê (•Ä�‘) resources
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 #pragma code_page(1252)
-#endif //_WIN32
 
 /////////////////////////////////////////////////////////////////////////////
 //
 // Dialog
 //
 
-IDD_CONFIG_DIALOG DIALOGEX 0, 0, 162, 55
-STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
-    WS_SYSMENU
-CAPTION "ax7z.spi config"
+IDD_PROGRESS DIALOGEX 0, 0, 143, 67
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | 
+    WS_VISIBLE | WS_CAPTION
+CAPTION "ax7z_s.spi"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    CONTROL         "",IDC_PROGRESSBAR,"msctls_progress32",WS_BORDER | 0x1,
+                    21,15,100,14
+    CTEXT           "0 / 0",IDC_PROGRESSTEXT,41,33,60,8
+    PUSHBUTTON      "Cancel",IDCANCEL,46,46,50,14
+END
+
+IDD_CONFIG_DIALOG DIALOGEX 0, 0, 211, 167
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "ax7z_s.spi config"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    LTEXT           "&DLL defined:",IDC_STATIC,7,7,41,8
+    LISTBOX         IDC_EXTENSION_LIST,7,17,131,63,LBS_SORT | LBS_MULTIPLESEL | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+    PUSHBUTTON      "S&elect all",IDC_SELECT_ALL_BUTTON,152,17,52,14
+    PUSHBUTTON      "&Unselect all",IDC_UNSELECT_ALL_BUTTON,152,38,52,14
+    PUSHBUTTON      "&Load Default",IDC_DEFAULT_BUTTON,152,59,52,14
+    LTEXT           "Use&r defined: (semi-colon separated list like bin;img;mdf)",IDC_STATIC,7,88,197,8
+    EDITTEXT        IDC_EXTENSION_EDIT,7,100,197,14,ES_AUTOHSCROLL
+    CONTROL         "S&tay password dialog on top",IDC_TOPMOST_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,120,107,10
+    CONTROL         "&Per-user configuration (ini in AppData)",IDC_PERUSERCONF_CHECK,
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,134,140,10
+    DEFPUSHBUTTON   "&OK",IDOK,18,147,43,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,81,147,40,14
+    PUSHBUTTON      "&Solid...",IDC_SOLID_BUTTON,141,147,50,14
+END
+
+IDD_ABOUT_DIALOG DIALOGEX 0, 0, 167, 72
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About ax7z_s.spi"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    CONTROL         "7z",IDC_7Z_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
-                    7,7,23,10
-    CONTROL         "rar",IDC_RAR_CHECK,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,46,7,25,10
-    CONTROL         "cbr",IDC_CBR_CHECK,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,85,7,26,10
-    CONTROL         "cab",IDC_CAB_CHECK,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,122,7,27,10
-    CONTROL         "arj",IDC_ARJ_CHECK,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,7,20,25,10
-    CONTROL         "lzh",IDC_LZH_CHECK,"Button",BS_AUTOCHECKBOX | 
-                    WS_TABSTOP,46,20,25,10
-    DEFPUSHBUTTON   "OK",IDOK,7,34,43,14
-    PUSHBUTTON      "Cancel",IDCANCEL,58,34,40,14
-    PUSHBUTTON      "Load Default",IDC_DEFAULT_BUTTON,103,34,52,14
+    DEFPUSHBUTTON   "OK",IDOK,55,51,50,14
+    LTEXT           "ax7z_s.spi  v0.7",IDC_STATIC,7,7,62,10
+    LTEXT           "7Z/RAR/CBR/CAB/ARJ etc. plug-in using 7z",IDC_STATIC,7,28,151,12
+    LTEXT           "(c) Makito Miyano",IDC_STATIC,98,7,62,12
+    LTEXT           RELEASE_LONG_STR,IDC_STATIC,14,17,86,10
+    LTEXT           "Enhanced by Yak!",IDC_STATIC,98,17,62,12
+    LTEXT           "Using 7z.dll version",IDC_STATIC,27,40,62,8
+    LTEXT           "",IDC_7ZVERSION,92,40,70,8
 END
 
-IDD_ABOUT_DIALOG DIALOGEX 0, 0, 167, 61
+IDD_SOLID_CONFIG_DIALOG DIALOGEX 0, 0, 294, 105
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
     WS_SYSMENU
-CAPTION "About ax7z.spi"
+CAPTION "ax7z_s.spi config cache for solid archive"
 FONT 8, "MS Shell Dlg", 400, 0, 0x1
 BEGIN
-    DEFPUSHBUTTON   "OK",IDOK,55,40,50,14
-    LTEXT           "ax7z.spi  v0.4",IDC_STATIC,7,7,62,12
-    LTEXT           "7Z/RAR/CBR/CAB/ARJ plug-in using 7z",IDC_STATIC,7,18,
-                    151,21
-    LTEXT           "(c) Makito Miyano",IDC_STATIC,98,7,62,12
+    GROUPBOX        "Solid cache",IDC_STATIC,7,7,49,49
+    CONTROL         "&7z",IDC_SOLID_7Z_CHECK,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,20,20,23,10
+    CONTROL         "&rar",IDC_SOLID_RAR_CHECK,"Button",BS_AUTOCHECKBOX | 
+                    WS_TABSTOP,20,36,25,10
+    LTEXT           "Look-ahead:",IDC_STATIC,66,21,41,8
+    LTEXT           "Memory:",IDC_STATIC,66,37,29,8
+    LTEXT           "Disk:",IDC_STATIC,66,53,16,8
+    LTEXT           "&Max",IDC_STATIC,120,7,14,8
+    EDITTEXT        IDC_MAX_LOOKAHEAD_EDIT,109,19,40,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_MAX_MEMORY_EDIT,109,35,40,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_MAX_DISK_EDIT,109,51,40,14,ES_AUTOHSCROLL
+    LTEXT           "MB",IDC_STATIC,156,37,10,8
+    LTEXT           "MB",IDC_STATIC,156,54,10,8
+    LTEXT           "&Purge",IDC_STATIC,184,7,20,8
+    EDITTEXT        IDC_PURGE_MEMORY_EDIT,171,35,40,14,ES_AUTOHSCROLL
+    EDITTEXT        IDC_PURGE_DISK_EDIT,171,51,40,14,ES_AUTOHSCROLL
+    LTEXT           "MB",IDC_STATIC,217,37,10,8
+    LTEXT           "MB",IDC_STATIC,217,54,10,8
+    LTEXT           "Cache &folder:",IDC_STATIC,7,78,44,8
+    EDITTEXT        IDC_CACHE_FOLDER_EDIT,58,75,119,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "&Browse...",IDC_BROWSE_BUTTON,185,75,42,14
+    PUSHBUTTON      "Cache c&lear...",IDC_CLEAR_BUTTON,237,75,50,14
+    DEFPUSHBUTTON   "&OK",IDOK,237,14,50,14
+    PUSHBUTTON      "&Cancel",IDCANCEL,237,35,50,14
+END
+
+IDD_PASSWORD DIALOGEX 0, 0, 186, 71
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "ax7z_s.spi password"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    EDITTEXT        IDC_PASSWORD_EDIT,7,28,172,14,ES_PASSWORD | ES_AUTOHSCROLL
+    DEFPUSHBUTTON   "OK",IDOK,7,50,50,14
+    PUSHBUTTON      "&Skip",IDC_SKIP_BUTTON,68,50,50,14
+    PUSHBUTTON      "Skip &Archive",IDC_SKIPARC_BUTTON,129,50,50,14
+    LTEXT           "Input password:",IDC_GUIDE_STATIC,9,8,170,17
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+IDV_VERSIONINFO VERSIONINFO
+ FILEVERSION 0,7,PATCH_MAJOR,PATCH_MINOR
+ PRODUCTVERSION 0,7,PATCH_MAJOR,PATCH_MINOR
+ FILEFLAGSMASK 0x0L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904E4"
+        BEGIN
+            VALUE "CompanyName", "Yak!"
+            VALUE "FileDescription", "ax7z_s.spi - 7Z/RAR/CBR/CAB/ARJ etc. plug-in using 7z with solid cache"
+            VALUE "FileVersion", "v0.7 " RELEASE_STR
+            VALUE "InternalName", "ax7z_s.spi"
+            VALUE "LegalCopyright", "(c) Makito Miyano, enhanced by Yak!"
+            VALUE "OriginalFilename", "ax7z_s.spi"
+            VALUE "ProductName", "ax7z_s.spi"
+            VALUE "ProductVersion", "v0.7 " RELEASE_STR
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252
+    END
 END
 
 
@@ -107,14 +199,22 @@
 //
 
 #ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO 
+GUIDELINES DESIGNINFO
 BEGIN
+    IDD_PROGRESS, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 136
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 60
+    END
+
     IDD_CONFIG_DIALOG, DIALOG
     BEGIN
         LEFTMARGIN, 7
-        RIGHTMARGIN, 155
+        RIGHTMARGIN, 204
         TOPMARGIN, 7
-        BOTTOMMARGIN, 48
+        BOTTOMMARGIN, 143
     END
 
     IDD_ABOUT_DIALOG, DIALOG
@@ -122,7 +222,23 @@
         LEFTMARGIN, 7
         RIGHTMARGIN, 160
         TOPMARGIN, 7
-        BOTTOMMARGIN, 54
+        BOTTOMMARGIN, 65
+    END
+
+    IDD_SOLID_CONFIG_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 287
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 98
+    END
+
+    IDD_PASSWORD, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 179
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 64
     END
 END
 #endif    // APSTUDIO_INVOKED
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/critsect.h ./critsect.h
--- /var/tmp/ax7z_src-orig/critsect.h	2000-11-11 11:30:02.000000000 +0900
+++ ./critsect.h	2013-08-25 21:56:26.830986500 +0900
@@ -14,24 +14,24 @@
 class CriticalSection
 {
 public:
-    CriticalSection()
-    {
-        InitializeCriticalSection(&crit_sect);
-    };
-    ~CriticalSection()
-    {
-        DeleteCriticalSection(&crit_sect);
-    };
-    void Enter()
-    {
-        EnterCriticalSection(&crit_sect);
-    };
-    void Leave()
-    {
-        LeaveCriticalSection(&crit_sect);
-    };
+	CriticalSection()
+	{
+		InitializeCriticalSection(&crit_sect);
+	};
+	~CriticalSection()
+	{
+		DeleteCriticalSection(&crit_sect);
+	};
+	void Enter()
+	{
+		EnterCriticalSection(&crit_sect);
+	};
+	void Leave()
+	{
+		LeaveCriticalSection(&crit_sect);
+	};
 private:
-    CRITICAL_SECTION crit_sect;
+	CRITICAL_SECTION crit_sect;
 };
 
 #endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/entryFuncs.cpp ./entryFuncs.cpp
--- /var/tmp/ax7z_src-orig/entryFuncs.cpp	2006-06-18 23:04:06.000000000 +0900
+++ ./entryFuncs.cpp	2015-01-09 00:41:22.418855500 +0900
@@ -2,103 +2,464 @@
 ax7z entry funcs
 */
 
+#define NOMINMAX
 #include <windows.h>
+#undef NOMINMAX
+#include <commctrl.h>
+#include <shlobj.h>
 #include <vector>
 #include <algorithm>
+#include <numeric>
+#include <map>
+#include <set>
 #include "entryFuncs.h"
 #include "infcache.h"
 #include <sstream>
 #include "resource.h"
+#include "7z/7zip/Bundles/ax7z/PasswordManager.h"
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include "7z/7zip/Bundles/ax7z/SolidCache.h"
+#include "version.hpp"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "release.h"
+#include "7z/Windows/FileDir.h"
+
+struct NoCaseLess
+{
+	bool operator()(const std::string &s1, const std::string &s2) const
+	{
+		return _stricmp(s1.c_str(), s2.c_str()) < 0;
+	}
+};
+
+//Šg’£ŽqŠÇ—�ƒNƒ‰ƒX
+class ExtManager
+{
+private:
+	typedef std::string Ext;
+	struct Info
+	{
+		std::vector<std::string> methods;
+		bool enable;
+	};
+	std::map<Ext, Info, NoCaseLess> m_mTable;
+	std::set<Ext, NoCaseLess> m_sTableUser;
+public:
+	static const char* const SECTION_NAME;
+	static const char* const DEFAULT_EXTENSIONS;
+	ExtManager() {}
+	typedef std::vector<std::pair<std::string, std::string> > Conf;
+	void Init(const Conf& conf);
+	bool IsEnable(LPSTR filename) const;
+	void SetEnable(const std::string &sExt, bool fEnable)
+	{
+		m_mTable[sExt].enable = fEnable;
+	}
+	typedef std::map<Ext, Info, NoCaseLess>::value_type EachValueType;
+	template<typename Functor>
+	void Each(Functor f) const
+	{
+		std::for_each(m_mTable.begin(), m_mTable.end(), f);
+	}
+	void SetDefault();
+	void Save(const std::string &sIniFileName) const;
+	void Load(const std::string &sIniFileName);
+	void SetPluginInfo(std::vector<std::string> &info) const;
+	void AddUserExt(const std::string& sExt);
+	void RemoveUserExt(const std::string& sExt);
+	void SetUserExtensions(const std::string& sExts);
+	std::string GetUserExtensions() const;
+};
+
+const char* const ExtManager::SECTION_NAME = "ax7z_s";
+const char* const ExtManager::DEFAULT_EXTENSIONS = "bin;img;mdf";
+
+void ExtManager::Init(const Conf& conf)
+{
+	Conf::const_iterator ciEnd = conf.end();
+	for(Conf::const_iterator ci = conf.begin(); ci != ciEnd; ++ci) {
+		m_mTable[ci->first].enable = true;
+		m_mTable[ci->first].methods.push_back(ci->second);
+	}
+}
+
+bool ExtManager::IsEnable(LPSTR filename) const
+{
+	char buf[_MAX_EXT];
+	_splitpath(filename, NULL, NULL, NULL, buf);
+	if(buf[0] == 0) buf[1] = 0; // guard
+	std::string sBuf(buf+1); // skip period
+	std::map<Ext, Info, NoCaseLess>::const_iterator ci = m_mTable.find(sBuf);
+	if(ci != m_mTable.end()) {
+		return ci->second.enable;
+	}
+	std::set<Ext, NoCaseLess>::const_iterator ciUser = m_sTableUser.find(sBuf);
+	if(ciUser != m_sTableUser.end()) {
+		return true;
+	}
+	return false;
+}
+
+void ExtManager::SetDefault()
+{
+	std::map<Ext, Info, NoCaseLess>::iterator it, itEnd = m_mTable.end();
+	for(it = m_mTable.begin(); it != itEnd; ++it) {
+		it->second.enable = true;
+	}
+}
+
+void ExtManager::Save(const std::string &sIniFileName) const
+{
+	if(m_sTableUser.size()) {
+		const std::string &sResult = GetUserExtensions();
+		WritePrivateProfileString(SECTION_NAME, "user_extensions", sResult.c_str(), sIniFileName.c_str());
+	} else {
+		WritePrivateProfileString(SECTION_NAME, "user_extensions", NULL, sIniFileName.c_str());
+	}
+
+	std::map<Ext, Info, NoCaseLess>::const_iterator ci, ciEnd = m_mTable.end();
+	for(ci = m_mTable.begin(); ci != ciEnd; ++ci) {
+		WritePrivateProfileString(SECTION_NAME, ci->first.c_str(), ci->second.enable ? "1" : "0", sIniFileName.c_str());
+	}
+}
+
+void ExtManager::Load(const std::string &sIniFileName)
+{
+	std::vector<char> vBuf(1024);
+
+	DWORD dwSize;
+	do {
+		vBuf.resize(vBuf.size() * 2);
+		dwSize = GetPrivateProfileString(SECTION_NAME, "user_extensions", DEFAULT_EXTENSIONS, &vBuf[0], vBuf.size(), sIniFileName.c_str());
+	} while(dwSize == vBuf.size() - 1);
+	std::string sResult(&vBuf[0]);
+	SetUserExtensions(sResult);
+
+	std::map<Ext, Info, NoCaseLess>::iterator mi, miEnd = m_mTable.end();
+	for(mi = m_mTable.begin(); mi != miEnd; ++mi) {
+		mi->second.enable = GetPrivateProfileInt(SECTION_NAME, mi->first.c_str(), 1, sIniFileName.c_str()) != 0;
+	}
+}
+
+struct MyConcat2
+{
+	std::string operator()(const std::string &s1, const std::string &s2) const
+	{
+		if(s1 == "")
+			return "*." + s2;
+		return s1 + ";" + "*." + s2;
+	}
+};
+
+void ExtManager::SetPluginInfo(std::vector<std::string> &vsPluginInfo) const
+{
+	std::map<std::string, std::string> mResmap;
+	std::map<Ext, Info, NoCaseLess>::const_iterator ci, ciEnd = m_mTable.end();	
+	for(ci = m_mTable.begin(); ci != ciEnd; ++ci) {
+		if(!ci->second.enable) continue;
+		std::vector<std::string>::const_iterator ci2, ciEnd2 = ci->second.methods.end();
+		for(ci2 = ci->second.methods.begin(); ci2 != ciEnd2; ++ci2) {
+			if(!mResmap[*ci2].empty()) {
+				mResmap[*ci2] += ";";
+			}
+			mResmap[*ci2] += "*.";
+			mResmap[*ci2] += ci->first;
+		}
+	}
+
+	vsPluginInfo.clear();
+	vsPluginInfo.push_back("00AM");
+	vsPluginInfo.push_back("7z extract library v0.7 for 7-zip 4.57+ " RELEASE_STR " (C) Makito Miyano / enhanced by Yak!"); 
+
+	std::map<std::string, std::string>::const_iterator ci2, ciEnd2 = mResmap.end();
+	for(ci2 = mResmap.begin(); ci2 != ciEnd2; ++ci2) {
+		vsPluginInfo.push_back(ci2->second);
+		vsPluginInfo.push_back(ci2->first + " files");
+	}
+	if(m_sTableUser.size()) {
+		vsPluginInfo.push_back(std::accumulate(m_sTableUser.begin(), m_sTableUser.end(), std::string(), MyConcat2()));
+		vsPluginInfo.push_back("User-defined");
+	}
+}
+
+void ExtManager::AddUserExt(const std::string& sExt)
+{
+	m_sTableUser.insert(sExt);
+}
+
+void ExtManager::RemoveUserExt(const std::string& sExt)
+{
+	m_sTableUser.erase(sExt);
+}
+
+struct MyConcat
+{
+	std::string operator()(const std::string &s1, const std::string &s2) const
+	{
+		if(s1 == "") return s2;
+		return s1 + ";" + s2;
+	}
+};
+
+std::string ExtManager::GetUserExtensions() const
+{
+	return std::accumulate(m_sTableUser.begin(), m_sTableUser.end(), std::string(), MyConcat());
+}
+
+void ExtManager::SetUserExtensions(const std::string& sExts)
+{
+	boost::algorithm::split(m_sTableUser, sExts, boost::algorithm::is_any_of(";"), boost::algorithm::token_compress_on);
+	m_sTableUser.erase("");
+}
 
 //ƒOƒ��[ƒoƒ‹•Ï�”
 static InfoCache infocache; //ƒA�[ƒJƒCƒu�î•ñƒLƒƒƒbƒVƒ…ƒNƒ‰ƒX
 static InfoCacheW infocacheW; //ƒA�[ƒJƒCƒu�î•ñƒLƒƒƒbƒVƒ…ƒNƒ‰ƒX
 static std::string g_sIniFileName; // ini ƒtƒ@ƒCƒ‹–¼
-static int s_nEnable7z = 1;
-static int s_nEnableRar = 1;
-static int s_nEnableCbr = 1;
-static int s_nEnableCab = 1;
-static int s_nEnableArj = 1;
-static int s_nEnableLzh = 1;
-static HANDLE s_hInstance;
+static ExtManager g_extManager;
+static bool g_fSharedConf;
+HINSTANCE g_hInstance;
+int g_nSolidEnable7z = 1;
+int g_nSolidEnableRar = 1;
+
+#ifndef _UNICODE
+bool g_IsNT = false;
+static inline bool IsItWindowsNT()
+{
+	OSVERSIONINFO versionInfo;
+	versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
+	if (!::GetVersionEx(&versionInfo)) 
+		return false;
+	return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+}
+#endif
 
 void SetParamDefault()
 {
-    s_nEnable7z = 1;
-    s_nEnableRar = 1;
-    s_nEnableCbr = 1;
-    s_nEnableCab = 1;
-    s_nEnableArj = 1;
-    s_nEnableLzh = 1;
+	g_extManager.SetDefault();
+	g_extManager.SetUserExtensions(ExtManager::DEFAULT_EXTENSIONS);
+	g_nSolidEnable7z = 1;
+	g_nSolidEnableRar = 1;
+
+	SolidCache& sc = SolidCache::GetInstance();
+
+	sc.SetMaxLookAhead(-1);
+	sc.SetMaxMemory(100);
+	sc.SetMaxDisk(1024);
+	sc.SetPurgeMemory(10);
+	sc.SetPurgeDisk(10);
+//	char buf[2048];
+//	GetTempPath(sizeof(buf), buf);
+//	sc.SetCacheFolder(buf);
+
+	g_fSharedConf = false;
 }
 
 std::string GetIniFileName()
 {
-    return g_sIniFileName;
+	return g_sIniFileName;
 }
 
 void LoadFromIni()
 {
-    SetParamDefault();
+	SetParamDefault();
 
-    std::string sIniFileName = GetIniFileName();
+	std::string sIniFileName = GetIniFileName();
 
-    s_nEnable7z = GetPrivateProfileInt("ax7z", "7z", s_nEnable7z, sIniFileName.c_str());
-    s_nEnableRar = GetPrivateProfileInt("ax7z", "rar", s_nEnableRar, sIniFileName.c_str());
-    s_nEnableCbr = GetPrivateProfileInt("ax7z", "cbr", s_nEnableCbr, sIniFileName.c_str());
-    s_nEnableCab = GetPrivateProfileInt("ax7z", "cab", s_nEnableCab, sIniFileName.c_str());
-    s_nEnableArj = GetPrivateProfileInt("ax7z", "arj", s_nEnableArj, sIniFileName.c_str());
-    s_nEnableLzh = GetPrivateProfileInt("ax7z", "lzh", s_nEnableLzh, sIniFileName.c_str());
-}
+	g_extManager.Load(sIniFileName);
 
-void SaveToIni()
-{
-    std::string sIniFileName = GetIniFileName();
+	SolidCache& sc = SolidCache::GetInstance();
 
-    WritePrivateProfileString("ax7z", "7z", s_nEnable7z ? "1" : "0", sIniFileName.c_str());
-    WritePrivateProfileString("ax7z", "rar", s_nEnableRar ? "1" : "0", sIniFileName.c_str());
-    WritePrivateProfileString("ax7z", "cbr", s_nEnableCbr ? "1" : "0", sIniFileName.c_str());
-    WritePrivateProfileString("ax7z", "cab", s_nEnableCab ? "1" : "0", sIniFileName.c_str());
-    WritePrivateProfileString("ax7z", "arj", s_nEnableArj ? "1" : "0", sIniFileName.c_str());
-    WritePrivateProfileString("ax7z", "lzh", s_nEnableLzh ? "1" : "0", sIniFileName.c_str());
+	g_nSolidEnable7z = GetPrivateProfileInt(ExtManager::SECTION_NAME, "solid7z", g_nSolidEnable7z, sIniFileName.c_str());
+	g_nSolidEnableRar = GetPrivateProfileInt(ExtManager::SECTION_NAME, "solidrar", g_nSolidEnableRar, sIniFileName.c_str());
+	sc.SetMaxLookAhead(GetPrivateProfileInt(ExtManager::SECTION_NAME, "lookahead", sc.GetMaxLookAhead(), sIniFileName.c_str()));
+	sc.SetMaxMemory(GetPrivateProfileInt(ExtManager::SECTION_NAME, "memory", sc.GetMaxMemory(), sIniFileName.c_str()));
+	sc.SetMaxDisk(GetPrivateProfileInt(ExtManager::SECTION_NAME, "disk", sc.GetMaxDisk(), sIniFileName.c_str()));
+	sc.SetPurgeMemory(GetPrivateProfileInt(ExtManager::SECTION_NAME, "purge_memory", sc.GetPurgeMemory(), sIniFileName.c_str()));
+	sc.SetPurgeDisk(GetPrivateProfileInt(ExtManager::SECTION_NAME, "purge_disk", sc.GetPurgeDisk(), sIniFileName.c_str()));
+	char buf[2048], buf2[2048];
+	GetTempPath(sizeof(buf2), buf2);
+	GetPrivateProfileString(ExtManager::SECTION_NAME, "folder", buf2, buf, sizeof(buf), sIniFileName.c_str());
+	sc.SetCacheFolder(buf);
+
+	std::vector<char> vBuf(1024);
+
+	DWORD dwSize;
+	do {
+		vBuf.resize(vBuf.size() * 2);
+		dwSize = GetPrivateProfileString(ExtManager::SECTION_NAME, "topmost", "false", &vBuf[0], vBuf.size(), sIniFileName.c_str());
+	} while(dwSize == vBuf.size() - 1);
+	std::string sResult(&vBuf[0]);
+	PasswordManager::Get().SetTopMost(sResult == "true");
+	int nShared = GetPrivateProfileInt(ExtManager::SECTION_NAME, "shared", -1, sIniFileName.c_str());
+	if(nShared != -1) g_fSharedConf = nShared;
+}
+
+bool SaveToIni()
+{
+	std::string sIniFileName = GetIniFileName();
+
+	g_extManager.Save(sIniFileName);
+
+	char buf[2048];
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "solid7z", g_nSolidEnable7z ? "1" : "0", sIniFileName.c_str());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "solidrar", g_nSolidEnableRar ? "1" : "0", sIniFileName.c_str());
+
+	SolidCache& sc = SolidCache::GetInstance();
+	wsprintf(buf, "%d", sc.GetMaxLookAhead());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "lookahead", buf, sIniFileName.c_str());
+	wsprintf(buf, "%d", sc.GetMaxMemory());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "memory", buf, sIniFileName.c_str());
+	wsprintf(buf, "%d", sc.GetMaxDisk());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "disk", buf, sIniFileName.c_str());
+	wsprintf(buf, "%d", sc.GetPurgeMemory());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "purge_memory", buf, sIniFileName.c_str());
+	wsprintf(buf, "%d", sc.GetPurgeDisk());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "purge_disk", buf, sIniFileName.c_str());
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "folder", sc.GetCacheFolder().c_str(), sIniFileName.c_str());
+
+	WritePrivateProfileString(ExtManager::SECTION_NAME, "topmost", PasswordManager::Get().GetTopMost() ? "true" : "false", sIniFileName.c_str());
+
+	int nResult = 1;
+	nResult &= WritePrivateProfileString(ExtManager::SECTION_NAME, "topmost", PasswordManager::Get().GetTopMost() ? "true" : "false", sIniFileName.c_str());
+	if(g_fSharedConf)
+		nResult &= WritePrivateProfileString(ExtManager::SECTION_NAME, "shared", "1", sIniFileName.c_str());
+
+	return nResult;
+}
+
+std::string GetSharedIniFileName(HANDLE hModule)
+{
+	std::vector<char> vModulePath(1024);
+	size_t nLen = GetModuleFileName((HMODULE)hModule, &vModulePath[0], (DWORD)vModulePath.size());
+	vModulePath.resize(nLen + 1);
+
+	std::string sResult(&vModulePath[0]);
+	sResult += ".ini";
+	return sResult;
+}
+
+void MakePersonalIniFolder()
+{
+	char p[MAX_PATH];
+	SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, p);
+	std::string s(p);
+	s += "\\ax7z";
+	CreateDirectory(s.c_str(), 0);
+}
+
+std::string GetPersonalIniFileName(HANDLE hModule)
+{
+	char p[MAX_PATH];
+	SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, p);
+	std::string s(p);
+	s += "\\ax7z";
+	std::vector<char> vModulePath(1024);
+	size_t nLen = GetModuleFileName((HMODULE)hModule, &vModulePath[0], (DWORD)vModulePath.size());
+	vModulePath.resize(nLen + 1);
+	std::vector<char>::reverse_iterator it = find(vModulePath.rbegin(), vModulePath.rend(), '\\');
+	s += "\\";
+	s += std::string(&*it.base());
+	s += ".ini";
+	return s;
 }
 
 void SetIniFileName(HANDLE hModule)
 {
-    std::vector<char> vModulePath(1024);
-    size_t nLen = GetModuleFileName((HMODULE)hModule, &vModulePath[0], (DWORD)vModulePath.size());
-    vModulePath.resize(nLen + 1);
-    // –{—ˆ‚Í2ƒoƒCƒg•¶Žš‘Î�ô‚ª•K—v‚¾‚ª�Aƒvƒ‰ƒOƒCƒ“–¼‚É“ú–{Œê‚Í‚È‚¢‚Æ”»’f‚µ‚ÄŽè”²‚«
-    while (!vModulePath.empty() && vModulePath.back() != '\\') {
-        vModulePath.pop_back();
-    }
+	std::string sPersonal(GetPersonalIniFileName(hModule));
+	struct __stat64 st;
+	if(!_stat64(sPersonal.c_str(), &st)) { // If personal ini file found, always used
+		g_sIniFileName = sPersonal;
+		g_fSharedConf = false;
+		return;
+	}
+	std::string sShared(GetSharedIniFileName(hModule));
+	if(!_stat64(sShared.c_str(), &st)) { // Found
+		int nShared = GetPrivateProfileInt(ExtManager::SECTION_NAME, "shared", -1, sShared.c_str());
+		if(nShared == 1) {
+			g_sIniFileName = sShared;
+			g_fSharedConf = true;
+			return;
+		}
+		char buf[1024];
+		wsprintf(buf,
+			"The %s.spi.ini file is found where the %s.spi file exists.\n"
+			"To support multiple users, the default place of the %s.spi.ini file is changed to your AppData folder.\n"
+			"\n"
+			"Do you want to move the %s.spi.ini file to your AppData folder?\n"
+			"If you can not understand what it is, please select NO.",
+			ExtManager::SECTION_NAME, ExtManager::SECTION_NAME, ExtManager::SECTION_NAME, ExtManager::SECTION_NAME);
+		int nRet = MessageBox(NULL, buf,
+			ExtManager::SECTION_NAME, MB_TASKMODAL | MB_ICONWARNING | MB_YESNO);
+		if(nRet == IDNO) {
+			WritePrivateProfileString(ExtManager::SECTION_NAME, "shared", "1", sShared.c_str());
+			g_sIniFileName = sShared;
+			g_fSharedConf = true;
+			return;
+		} else {
+			MakePersonalIniFolder();
+			if(!CopyFile(sShared.c_str(), sPersonal.c_str(), TRUE)) {
+				MessageBox(NULL, "Copy of the ini file is failed. Use the old ini file.", ExtManager::SECTION_NAME, MB_TASKMODAL | MB_ICONWARNING | MB_OK);
+				g_sIniFileName = sShared;
+				g_fSharedConf = true;
+				return;
+			}
+			if(!DeleteFile(sShared.c_str())) {
+				MessageBox(NULL, "Delete of the old ini file is failed. Leave as it is.", ExtManager::SECTION_NAME, MB_TASKMODAL | MB_ICONWARNING | MB_OK);
+			}
+		}
+	}
+	g_sIniFileName = sPersonal;
+	g_fSharedConf = false;
+}
 
-    g_sIniFileName = &vModulePath[0];
-    g_sIniFileName +=".ini";
+void handle_exception(const std::string &s)
+{
+	try {
+		throw;
+	} catch (std::exception &e) {
+		OutputDebugPrintf("%s: exception %s thrown", s.c_str(), e.what());
+	} catch (...) {
+		OutputDebugPrintf("%s: unknown exception thrown", s.c_str());
+	}
 }
 
 /* ƒGƒ“ƒgƒŠƒ|ƒCƒ“ƒg */
 BOOL APIENTRY SpiEntryPoint(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
-    bool bInitPath = false;
-	switch (ul_reason_for_call) {
+	try {
+		bool bInitPath = false;
+		INITCOMMONCONTROLSEX ice = { sizeof(INITCOMMONCONTROLSEX), ICC_PROGRESS_CLASS };
+		switch (ul_reason_for_call) {
 		case DLL_PROCESS_ATTACH:
-            CoInitialize(NULL);
-            SetIniFileName(hModule);
-            LoadFromIni();
-            bInitPath = true;
+#ifndef _UNICODE
+			g_IsNT = IsItWindowsNT();
+#endif
+			InitCommonControlsEx(&ice);
+			{
+				extern void GetFormats(ExtManager::Conf &res);
+				ExtManager::Conf v;
+				GetFormats(v);
+				g_extManager.Init(v);
+			}
+			SetIniFileName(hModule);
+			LoadFromIni();
+			bInitPath = true;
 			break;
 		case DLL_THREAD_ATTACH:
-            CoInitialize(NULL);
-            SetIniFileName(hModule);
-            LoadFromIni();
-            break;
+			SetIniFileName(hModule);
+			LoadFromIni();
+			break;
 		case DLL_THREAD_DETACH:
-            CoUninitialize();
 			break;
 		case DLL_PROCESS_DETACH:
-            CoUninitialize();
 			break;
+		}
+	} catch (...) {
+		handle_exception(__FUNCTION__);
+		return FALSE;
 	}
 
 	return TRUE;
@@ -108,15 +469,15 @@
 /* ƒGƒ“ƒgƒŠƒ|ƒCƒ“ƒg */
 BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
-    int a = sizeof(fileInfoW);
+	int a = sizeof(fileInfoW);
 	switch (ul_reason_for_call) {
 		case DLL_PROCESS_DETACH:
 			infocache.Clear();
-            infocacheW.Clear();
+			infocacheW.Clear();
 			break;
 	}
-    s_hInstance = hModule;
-    return SpiEntryPoint(hModule, ul_reason_for_call, lpReserved);
+	g_hInstance = (HINSTANCE)hModule;
+	return SpiEntryPoint(hModule, ul_reason_for_call, lpReserved);
 }
 
 /***************************************************************************
@@ -125,111 +486,65 @@
 //---------------------------------------------------------------------------
 int __stdcall GetPluginInfo(int infono, LPSTR buf, int buflen)
 {
-    std::vector<std::string> vsPluginInfo;
-    vsPluginInfo.push_back("00AM");
-    vsPluginInfo.push_back("7z extract library v0.7 (C) Makito Miyano");
-    if (s_nEnable7z) {
-        vsPluginInfo.push_back("*.7z");
-        vsPluginInfo.push_back("7-zip files");
-    }
-    if (s_nEnableRar) {
-        vsPluginInfo.push_back("*.rar");
-        vsPluginInfo.push_back("Rar files");
-    }
-    if (s_nEnableCbr) {
-        vsPluginInfo.push_back("*.cbr");
-        vsPluginInfo.push_back("Cbr(rar) files");
-    }
-    if (s_nEnableCab) {
-        vsPluginInfo.push_back("*.cab");
-        vsPluginInfo.push_back("Cab files");
-    }
-    if (s_nEnableArj) {
-        vsPluginInfo.push_back("*.arj");
-        vsPluginInfo.push_back("Arj files");
-    }
-    if (s_nEnableLzh) {
-        vsPluginInfo.push_back("*.lzh");
-        vsPluginInfo.push_back("LZH files");
-    }
+	try {
+		std::vector<std::string> vsPluginInfo;
 
-    if (infono < 0 || infono >= (int)vsPluginInfo.size()) {
-		return 0;
-    }
+		g_extManager.SetPluginInfo(vsPluginInfo);
+
+		if (infono < 0 || infono >= (int)vsPluginInfo.size()) {
+			return 0;
+		}
 
-    lstrcpyn(buf, vsPluginInfo[infono].c_str(), buflen);
+		lstrcpyn(buf, vsPluginInfo[infono].c_str(), buflen);
 
-	return lstrlen(buf);
+		return lstrlen(buf);
+	} catch (...) {
+		handle_exception(__FUNCTION__);
+		return 0;
+	}
 }
 
 static bool CheckFileExtension(const char* pFileName, const char* pExtension)
 {
-    int nExtensionLen = strlen(pExtension);
-    int nFileNameLen = strlen(pFileName);
+	int nExtensionLen = strlen(pExtension);
+	int nFileNameLen = strlen(pFileName);
 
-    // ƒsƒŠƒIƒh‚ð“ü‚ê‚Äƒtƒ@ƒCƒ‹–¼–{‘Ì‚ª‘¶�Ý‚·‚é‚©?
-    if (nFileNameLen <= nExtensionLen + 1) {
-        return false;
-    }
+	// ƒsƒŠƒIƒh‚ð“ü‚ê‚Äƒtƒ@ƒCƒ‹–¼–{‘Ì‚ª‘¶�Ý‚·‚é‚©?
+	if (nFileNameLen <= nExtensionLen + 1) {
+		return false;
+	}
 
-    return (strnicmp(pFileName + nFileNameLen - nExtensionLen, pExtension, nExtensionLen) == 0);
+	return (strnicmp(pFileName + nFileNameLen - nExtensionLen, pExtension, nExtensionLen) == 0);
 }
 static bool CheckFileExtensionW(const wchar_t* pFileName, const wchar_t* pExtension)
 {
-    int nExtensionLen = wcslen(pExtension);
-    int nFileNameLen = wcslen(pFileName);
+	int nExtensionLen = wcslen(pExtension);
+	int nFileNameLen = wcslen(pFileName);
 
-    // ƒsƒŠƒIƒh‚ð“ü‚ê‚Äƒtƒ@ƒCƒ‹–¼–{‘Ì‚ª‘¶�Ý‚·‚é‚©?
-    if (nFileNameLen <= nExtensionLen + 1) {
-        return false;
-    }
+	// ƒsƒŠƒIƒh‚ð“ü‚ê‚Äƒtƒ@ƒCƒ‹–¼–{‘Ì‚ª‘¶�Ý‚·‚é‚©?
+	if (nFileNameLen <= nExtensionLen + 1) {
+		return false;
+	}
 
-    return (wcsnicmp(pFileName + nFileNameLen - nExtensionLen, pExtension, nExtensionLen) == 0);
+	return (wcsnicmp(pFileName + nFileNameLen - nExtensionLen, pExtension, nExtensionLen) == 0);
 }
 
 //---------------------------------------------------------------------------
 int __stdcall IsSupported(LPSTR filename, DWORD dw)
 {
-    // Œ»Žž“_‚Å‚Í–¼‘O‚Ì‚Ý‚Å”»’f
-    int nLen = strlen(filename);
-    if (nLen < 4) {
-        // �Å’á‚Å‚à4•¶Žš‚Í•K—v‚È‚Í‚¸ (a.7z‚ª�Å’Z)
-        return 0;
-    }
-
-    if ((s_nEnable7z && CheckFileExtension(filename, "7z"))
-        || (s_nEnableRar && CheckFileExtension(filename, "rar"))
-        || (s_nEnableCbr && CheckFileExtension(filename, "cbr"))
-        || (s_nEnableCab && CheckFileExtension(filename, "cab"))
-        || (s_nEnableLzh && CheckFileExtension(filename, "lzh"))
-        || (s_nEnableArj && CheckFileExtension(filename, "arj"))) {
-        // ƒTƒ|�[ƒg‚µ‚Ä‚¢‚é‚Æ”»’f
-        return 1;
-    }
-
-    return 0;
+	try {
+		// Œ»Žž“_‚Å‚Í–¼‘O‚Ì‚Ý‚Å”»’f
+		return g_extManager.IsEnable(filename);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return 0;
+	}
 }
 
 int __stdcall IsSupportedW(LPWSTR filename, DWORD dw)
 {
-    // Œ»Žž“_‚Å‚Í–¼‘O‚Ì‚Ý‚Å”»’f
-    int nLen = wcslen(filename);
-    if (nLen < 4) {
-        // �Å’á‚Å‚à4•¶Žš‚Í•K—v‚È‚Í‚¸ (a.7z‚ª�Å’Z)
-        return 0;
-    }
-
-    if ((s_nEnable7z && CheckFileExtensionW(filename, L"7z"))
-        || (s_nEnableRar && CheckFileExtensionW(filename, L"rar"))
-        || (s_nEnableCbr && CheckFileExtensionW(filename, L"cbr"))
-        || (s_nEnableCab && CheckFileExtensionW(filename, L"cab"))
-        || (s_nEnableLzh && CheckFileExtensionW(filename, L"lzh"))
-        || (s_nEnableArj && CheckFileExtensionW(filename, L"arj"))) {
-        // ƒTƒ|�[ƒg‚µ‚Ä‚¢‚é‚Æ”»’f
-        return 1;
-    }
-
-    return 0;
+	// Unicode –¢ƒTƒ|�[ƒg
+	return 0;
 }
 
 //---------------------------------------------------------------------------
@@ -247,32 +562,39 @@
 	//ƒLƒƒƒbƒVƒ…
 	infocache.Add(filename, &hinfo);
 
-    if (phinfo != NULL) {
-        UINT size = LocalSize(hinfo);
-        /* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
-        *phinfo = LocalAlloc(LMEM_FIXED, size);
-        if (*phinfo == NULL) {
-            return SPI_NO_MEMORY;
-        }
-
-        memcpy(*phinfo, (void*)hinfo, size);
-    } else {
-        fileInfo *ptmp = (fileInfo *)hinfo;
-        if (pinfo->filename[0] != '\0') {
-            for (;;) {
-                if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
-                if (lstrcmpi(ptmp->filename, pinfo->filename) == 0) break;
-                ptmp++;
-            }
-        } else {
-            for (;;) {
-                if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
-                if (ptmp->position == pinfo->position) break;
-                ptmp++;
-            }
-        }
-        *pinfo = *ptmp;
-    }
+	if (phinfo != NULL) {
+		UINT size = LocalSize(hinfo);
+		/* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
+		*phinfo = LocalAlloc(LMEM_FIXED, size);
+		if (*phinfo == NULL) {
+			return SPI_NO_MEMORY;
+		}
+
+		memcpy(*phinfo, (void*)hinfo, size);
+	} else {
+		fileInfo *ptmp = (fileInfo *)hinfo;
+		if (pinfo->filename[0] != '\0') {
+			for (;;) {
+				if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
+				// complete path relative to archive root
+				char path[sizeof(ptmp->path)+sizeof(ptmp->filename)];
+				strcpy(path, ptmp->path);
+				size_t len = strlen(path);
+				if(len && path[len-1] != '/' && path[len-1] != '\\') // need delimiter
+					strcat(path, "\\");
+				strcat(path, ptmp->filename);
+				if (lstrcmpi(path, pinfo->filename) == 0) break;
+				ptmp++;
+			}
+		} else {
+			for (;;) {
+				if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
+				if (ptmp->position == pinfo->position) break;
+				ptmp++;
+			}
+		}
+		*pinfo = *ptmp;
+	}
 	return SPI_ALL_RIGHT;
 }
 int GetArchiveInfoCacheW(wchar_t *filename, long len, HLOCAL *phinfo, fileInfoW *pinfo)
@@ -288,229 +610,529 @@
 	//ƒLƒƒƒbƒVƒ…
 	infocacheW.Add(filename, &hinfo);
 
-    if (phinfo != NULL) {
-        UINT size = LocalSize(hinfo);
-        /* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
-        *phinfo = LocalAlloc(LMEM_FIXED, size);
-        if (*phinfo == NULL) {
-            return SPI_NO_MEMORY;
-        }
-
-        memcpy(*phinfo, (void*)hinfo, size);
-    } else {
-        fileInfoW *ptmp = (fileInfoW *)hinfo;
-        if (pinfo->filename[0] != L'\0') {
-            for (;;) {
-                if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
-                if (wcsicmp(ptmp->filename, pinfo->filename) == 0) break;
-                ptmp++;
-            }
-        } else {
-            for (;;) {
-                if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
-                if (ptmp->position == pinfo->position) break;
-                ptmp++;
-            }
-        }
-        *pinfo = *ptmp;
-    }
+	if (phinfo != NULL) {
+		UINT size = LocalSize(hinfo);
+		/* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
+		*phinfo = LocalAlloc(LMEM_FIXED, size);
+		if (*phinfo == NULL) {
+			return SPI_NO_MEMORY;
+		}
+
+		memcpy(*phinfo, (void*)hinfo, size);
+	} else {
+		fileInfoW *ptmp = (fileInfoW *)hinfo;
+		if (pinfo->filename[0] != L'\0') {
+			for (;;) {
+				if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
+				// complete path relative to archive root
+				wchar_t path[sizeof(ptmp->path)+sizeof(ptmp->filename)];
+				wcscpy(path, ptmp->path);
+				size_t len = wcslen(path);
+				if(len && path[len-1] != L'/' && path[len-1] != L'\\') // need delimiter
+					wcscat(path, L"\\");
+				wcscat(path, ptmp->filename);
+				if (wcsicmp(path, pinfo->filename) == 0) break;
+				ptmp++;
+			}
+		} else {
+			for (;;) {
+				if (ptmp->method[0] == '\0') return SPI_NO_FUNCTION;
+				if (ptmp->position == pinfo->position) break;
+				ptmp++;
+			}
+		}
+		*pinfo = *ptmp;
+	}
 	return SPI_ALL_RIGHT;
 }
 //---------------------------------------------------------------------------
 int __stdcall GetArchiveInfo(LPSTR buf, long len, unsigned int flag, HLOCAL *lphInf)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
-
-	*lphInf = NULL;
-	return GetArchiveInfoCache(buf, len, lphInf, NULL);
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		*lphInf = NULL;
+		return GetArchiveInfoCache(buf, len, lphInf, NULL);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
 int __stdcall GetArchiveInfoW(LPWSTR buf, long len, unsigned int flag, HLOCAL *lphInf)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
-
-	*lphInf = NULL;
-	return GetArchiveInfoCacheW(buf, len, lphInf, NULL);
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		*lphInf = NULL;
+		return GetArchiveInfoCacheW(buf, len, lphInf, NULL);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
 
 //---------------------------------------------------------------------------
 int __stdcall GetFileInfo
 (LPSTR buf, long len, LPSTR filename, unsigned int flag, struct fileInfo *lpInfo)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
-
-	lstrcpy(lpInfo->filename, filename);
-
-	return GetArchiveInfoCache(buf, len, NULL, lpInfo);
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		lstrcpy(lpInfo->filename, filename);
+
+		return GetArchiveInfoCache(buf, len, NULL, lpInfo);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
+
 int __stdcall GetFileInfoW
 (LPWSTR buf, long len, LPWSTR filename, unsigned int flag, struct fileInfoW *lpInfo)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
-
-	wcscpy(lpInfo->filename, filename);
-
-	return GetArchiveInfoCacheW(buf, len, NULL, lpInfo);
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		wcscpy(lpInfo->filename, filename);
+
+		return GetArchiveInfoCacheW(buf, len, NULL, lpInfo);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
 //---------------------------------------------------------------------------
 int __stdcall GetFile(LPSTR src, long len,
 			   LPSTR dest, unsigned int flag,
 			   SPI_PROGRESS lpPrgressCallback, long lData)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
-
-	fileInfo info;
-	info.filename[0] = '\0';
-	info.position = len;
-	int ret = GetArchiveInfoCache(src, 0, NULL, &info);
-    if (ret != SPI_ALL_RIGHT) {
-        CoUninitialize();
-        return ret;
-    }
-
-    int nRet;
-    if ((flag & 0x700) == 0) {
-    	//ƒtƒ@ƒCƒ‹‚Ö‚Ì�o—Í‚Ì�ê�‡
-        std::string s = dest;
-        s += "\\";
-        s += info.filename;
-        nRet = GetFileEx(src, NULL, s.c_str(), &info, lpPrgressCallback, lData);
-    } else {
-        // ƒ�ƒ‚ƒŠ‚Ö‚Ì�o—Í‚Ì�ê�‡
-    	nRet = GetFileEx(src, (HLOCAL *)dest, NULL, &info, lpPrgressCallback, lData);
-    }
-    return nRet;
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		fileInfo info;
+		info.filename[0] = '\0';
+		info.position = len;
+		int ret = GetArchiveInfoCache(src, 0, NULL, &info);
+		if (ret != SPI_ALL_RIGHT) {
+			return ret;
+		}
+
+		int nRet;
+		if ((flag & 0x700) == 0) {
+			//ƒtƒ@ƒCƒ‹‚Ö‚Ì�o—Í‚Ì�ê�‡
+			std::string s = dest;
+			s += "\\";
+			s += info.filename;
+			nRet = GetFileEx(src, NULL, s.c_str(), &info, lpPrgressCallback, lData);
+		} else {
+			// ƒ�ƒ‚ƒŠ‚Ö‚Ì�o—Í‚Ì�ê�‡
+			nRet = GetFileEx(src, (HLOCAL *)dest, NULL, &info, lpPrgressCallback, lData);
+		}
+		return nRet;
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
 int __stdcall GetFileW(LPWSTR src, long len,
 			   LPWSTR dest, unsigned int flag,
 			   SPI_PROGRESS lpPrgressCallback, long lData)
 {
-	//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
-	if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+	try {
+		//ƒ�ƒ‚ƒŠ“ü—Í‚É‚Í‘Î‰ž‚µ‚È‚¢
+		if ((flag & 7) != 0) return SPI_NO_FUNCTION;
+
+		fileInfoW info;
+		info.filename[0] = L'\0';
+		info.position = len;
+		int ret = GetArchiveInfoCacheW(src, 0, NULL, &info);
+		if (ret != SPI_ALL_RIGHT) {
+			return ret;
+		}
+
+		int nRet;
+		if ((flag & 0x700) == 0) {
+			//ƒtƒ@ƒCƒ‹‚Ö‚Ì�o—Í‚Ì�ê�‡
+			std::wstring s = dest;
+			s += L"\\";
+			s += info.filename;
+			nRet = GetFileWEx(src, NULL, s.c_str(), &info, lpPrgressCallback, lData);
+		} else {
+			// ƒ�ƒ‚ƒŠ‚Ö‚Ì�o—Í‚Ì�ê�‡
+			nRet = GetFileWEx(src, (HLOCAL *)dest, NULL, &info, lpPrgressCallback, lData);
+		}
+		return nRet;
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
+}
 
-	fileInfoW info;
-	info.filename[0] = L'\0';
-	info.position = len;
-	int ret = GetArchiveInfoCacheW(src, 0, NULL, &info);
-    if (ret != SPI_ALL_RIGHT) {
-        CoUninitialize();
-        return ret;
-    }
-
-    int nRet;
-    if ((flag & 0x700) == 0) {
-    	//ƒtƒ@ƒCƒ‹‚Ö‚Ì�o—Í‚Ì�ê�‡
-        std::wstring s = dest;
-        s += L"\\";
-        s += info.filename;
-        nRet = GetFileWEx(src, NULL, s.c_str(), &info, lpPrgressCallback, lData);
-    } else {
-        // ƒ�ƒ‚ƒŠ‚Ö‚Ì�o—Í‚Ì�ê�‡
-    	nRet = GetFileWEx(src, (HLOCAL *)dest, NULL, &info, lpPrgressCallback, lData);
-    }
-    return nRet;
+static std::string Get7zPath(HKEY hkParent)
+{
+	HKEY hkey;
+	if(RegOpenKey(hkParent, "Software\\7-zip", &hkey) == ERROR_SUCCESS) {
+		std::vector<BYTE> buf(4096);
+		DWORD dwSize = buf.size();
+		if(RegQueryValueEx(hkey, "Path", 0, 0, &buf[0], &dwSize) == ERROR_SUCCESS) {
+			buf.resize(dwSize ? dwSize - 1 : 0);
+			return std::string(buf.begin(), buf.end());
+		}
+	}
+	return std::string();
+}
+
+static HINSTANCE LoadLibrary7z()
+{
+	HINSTANCE h = LoadLibrary("7z.dll");
+	if(h) return h;
+	std::string s = Get7zPath(HKEY_CURRENT_USER) + "7z.dll";
+	h = LoadLibrary(s.c_str());
+	if(h) return h;
+	s = Get7zPath(HKEY_LOCAL_MACHINE) + "7z.dll";
+	h = LoadLibrary(s.c_str());
+	return h;
+}
+
+static std::string Find7zPath()
+{
+	HINSTANCE h = LoadLibrary7z();
+	if(!h) return std::string();
+	std::string s(4096, '\0');
+	DWORD dwLen = GetModuleFileName(h, &s[0], s.size());
+	s.resize(dwLen);
+	FreeLibrary(h);
+	return s;
 }
 //---------------------------------------------------------------------------
 LRESULT CALLBACK AboutDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
 {
-    switch (msg) {
-        case WM_INITDIALOG:
-            return FALSE;
-        case WM_COMMAND:
-            switch (LOWORD(wp)) {
-                case IDOK:
-                    EndDialog(hDlgWnd, IDOK);
-                    break;
-                case IDCANCEL:
-                    EndDialog(hDlgWnd, IDCANCEL);
-                    break;
-                default:
-                    return FALSE;
-            }
-        default:
-            return FALSE;
-    }
-    return TRUE;
+	try {
+		switch (msg) {
+			case WM_INITDIALOG:
+			{
+OutputDebugPrintf("AboutDlgProc: 7z DLL path %s", Find7zPath().c_str());
+				yak::util::windows::VersionResource vr(Find7zPath().c_str());
+				std::string s = vr.GetValue(yak::util::windows::VersionResource::FILE_VERSION);
+OutputDebugPrintf("AboutDlgProc: 7z DLL version %s", s.c_str());
+				SendDlgItemMessage(hDlgWnd, IDC_7ZVERSION, WM_SETTEXT, 0, (LPARAM)s.c_str());
+				return FALSE;
+			}
+			case WM_COMMAND:
+				switch (LOWORD(wp)) {
+					case IDOK:
+						EndDialog(hDlgWnd, IDOK);
+						break;
+					case IDCANCEL:
+						EndDialog(hDlgWnd, IDCANCEL);
+						break;
+					default:
+						return FALSE;
+				}
+			default:
+				return FALSE;
+		}
+		return TRUE;
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
+}
+
+//---------------------------------------------------------------------------
+static void UpdateSolidDialogItem(HWND hDlgWnd)
+{
+	SendDlgItemMessage(hDlgWnd, IDC_SOLID_7Z_CHECK, BM_SETCHECK, (WPARAM)g_nSolidEnable7z, 0L);
+	SendDlgItemMessage(hDlgWnd, IDC_SOLID_RAR_CHECK, BM_SETCHECK, (WPARAM)g_nSolidEnableRar, 0L);
+
+	SolidCache& sc = SolidCache::GetInstance();
+	char buf[2048];
+	wsprintf(buf, "%d", sc.GetMaxLookAhead());
+	SendDlgItemMessage(hDlgWnd, IDC_MAX_LOOKAHEAD_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+	wsprintf(buf, "%d", sc.GetMaxMemory());
+	SendDlgItemMessage(hDlgWnd, IDC_MAX_MEMORY_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+	wsprintf(buf, "%d", sc.GetMaxDisk());
+	SendDlgItemMessage(hDlgWnd, IDC_MAX_DISK_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+	wsprintf(buf, "%d", sc.GetPurgeMemory());
+	SendDlgItemMessage(hDlgWnd, IDC_PURGE_MEMORY_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+	wsprintf(buf, "%d", sc.GetPurgeDisk());
+	SendDlgItemMessage(hDlgWnd, IDC_PURGE_DISK_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+	SendDlgItemMessage(hDlgWnd, IDC_CACHE_FOLDER_EDIT, WM_SETTEXT, 0, (LPARAM)sc.GetCacheFolder().c_str());
+}
+
+static bool IsChecked2(HWND hDlgWnd, int nID, int &nVar)
+{
+	int nOldVar = nVar;
+	if (IsDlgButtonChecked(hDlgWnd, nID) == BST_CHECKED) {
+		nVar = 1;
+	} else {
+		nVar = 0;
+	}
+	return (nVar != nOldVar);
+}
+
+static bool GetIntValue(HWND hDlgWnd, int nID, int (SolidCache::*mfGetter)() const, int (SolidCache::*mfSetter)(int))
+{
+	char buf[2048];
+	SendDlgItemMessage(hDlgWnd, nID, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
+	int nTempVar = atoi(buf);
+	if(nTempVar != (SolidCache::GetInstance().*mfGetter)()) {
+		(SolidCache::GetInstance().*mfSetter)(nTempVar);
+		return true;
+	}
+	return false;
+}
+
+static bool UpdateSolidValue(HWND hDlgWnd)
+{
+	bool fChanged = false;
+	fChanged |= IsChecked2(hDlgWnd, IDC_SOLID_7Z_CHECK, g_nSolidEnable7z);
+	fChanged |= IsChecked2(hDlgWnd, IDC_SOLID_RAR_CHECK, g_nSolidEnableRar);
+	fChanged |= GetIntValue(hDlgWnd, IDC_MAX_LOOKAHEAD_EDIT, &SolidCache::GetMaxLookAhead, &SolidCache::SetMaxLookAhead);
+	fChanged |= GetIntValue(hDlgWnd, IDC_MAX_MEMORY_EDIT, &SolidCache::GetMaxMemory, &SolidCache::SetMaxMemory);
+	fChanged |= GetIntValue(hDlgWnd, IDC_MAX_DISK_EDIT, &SolidCache::GetMaxDisk, &SolidCache::SetMaxDisk);
+	fChanged |= GetIntValue(hDlgWnd, IDC_PURGE_MEMORY_EDIT, &SolidCache::GetPurgeMemory, &SolidCache::SetPurgeMemory);
+	fChanged |= GetIntValue(hDlgWnd, IDC_PURGE_DISK_EDIT, &SolidCache::GetPurgeDisk, &SolidCache::SetPurgeDisk);
+	char buf[2048];
+	SendDlgItemMessage(hDlgWnd, IDC_CACHE_FOLDER_EDIT, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
+	if(lstrcmp(buf, SolidCache::GetInstance().GetCacheFolder().c_str())) {
+		fChanged = true;
+		SolidCache::GetInstance().SetCacheFolder(buf);
+	}
+
+	return fChanged;
+}
+
+static bool IsExistentFolder(HWND hwnd, const std::string &sPath)
+{
+	DWORD dwAttr = GetFileAttributes(sPath.c_str());
+	if(dwAttr == -1) {
+		std::string sText = "Directory: " + sPath + " is not found, create?";
+		if(MessageBox(hwnd, sText.c_str(), ExtManager::SECTION_NAME, MB_YESNO) == IDYES) {
+			if(NWindows::NFile::NDirectory::CreateComplexDirectory(sPath.c_str())) {
+				return true;
+			} else {
+				std::string sText = "Directory: " + sPath + " can't be created.";
+				MessageBox(hwnd, sText.c_str(), ExtManager::SECTION_NAME, MB_ICONERROR | MB_OK);
+			}
+		}
+	} else {
+		if(dwAttr & FILE_ATTRIBUTE_DIRECTORY) {
+			return true;
+		} else {
+			std::string sText = "Path: " + sPath + " already exists and is not a directory.";
+			MessageBox(hwnd, sText.c_str(), ExtManager::SECTION_NAME, MB_ICONERROR | MB_OK);
+		}
+	}
+	return false;
+}
+
+LRESULT CALLBACK SolidConfigDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+	switch (msg) {
+		case WM_INITDIALOG:
+			UpdateSolidDialogItem(hDlgWnd);
+			EnableWindow(GetDlgItem(hDlgWnd, IDC_MAX_LOOKAHEAD_EDIT), FALSE);
+			return FALSE;
+		case WM_COMMAND:
+			switch (LOWORD(wp)) {
+				case IDOK:
+				{
+					char buf[2048];
+					SendDlgItemMessage(hDlgWnd, IDC_CACHE_FOLDER_EDIT, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
+					if (IsExistentFolder(hDlgWnd, buf)) {
+						if (UpdateSolidValue(hDlgWnd)) {
+								SaveToIni();
+						}
+						EndDialog(hDlgWnd, IDOK);
+					}
+					break;
+				}
+				case IDCANCEL:
+					EndDialog(hDlgWnd, IDCANCEL);
+					break;
+				case IDC_BROWSE_BUTTON:
+				{
+					char buf[MAX_PATH];
+					HRESULT hr = CoInitialize(NULL);
+					BROWSEINFO bwi = { hDlgWnd, NULL, buf, "Specify cache folder", BIF_RETURNONLYFSDIRS };
+					LPITEMIDLIST piid = SHBrowseForFolder(&bwi);
+					if(piid) {
+						SHGetPathFromIDList(piid, buf);
+						SendDlgItemMessage(hDlgWnd, IDC_CACHE_FOLDER_EDIT, WM_SETTEXT, 0, (LPARAM)buf);
+						CoTaskMemFree(piid);
+					}
+					if(SUCCEEDED(hr)) CoUninitialize();
+				}
+					break;
+				case IDC_CLEAR_BUTTON:
+					if(MessageBox(hDlgWnd, "Do you want to clear cache contents?", "ax7z_s.spi confirmation", MB_YESNO) == IDYES)
+						SolidCache::GetInstance().Clear();
+					break;
+				default:
+					return FALSE;
+			}
+	}
+	return FALSE;
 }
 
+//---------------------------------------------------------------------------
+struct MyConcat3
+{
+	std::string operator()(const std::string &s1, const std::string &s2) const
+	{
+		if(s1 == "") return s2;
+		return s1 + ", " + s2;
+	}
+};
+
+struct ListUpdater
+{
+	ListUpdater(HWND hwnd, std::vector<std::string> &v) : hwnd(hwnd), v(v) {}
+	HWND hwnd;
+	std::vector<std::string> &v;
+	void operator()(const ExtManager::EachValueType& value)
+	{
+		std::string sLine("*.");
+		sLine += value.first;
+		if(value.first.size() < 8)
+			sLine += std::string(8 - value.first.size(), ' ');
+		sLine += std::accumulate(value.second.methods.begin(), value.second.methods.end(), std::string(), MyConcat3());
+		LRESULT lResult = SendMessage(hwnd, LB_ADDSTRING, 0, reinterpret_cast<LPARAM>(static_cast<const void*>(sLine.c_str())));
+		v.push_back(value.first);
+		SendMessage(hwnd, LB_SETSEL, value.second.enable, lResult);
+	}
+};
+
 void UpdateDialogItem(HWND hDlgWnd)
 {
-    std::ostringstream ost;
-    SendMessage(GetDlgItem(hDlgWnd, IDC_7Z_CHECK), BM_SETCHECK, (WPARAM)s_nEnable7z, 0L);
-    SendMessage(GetDlgItem(hDlgWnd, IDC_RAR_CHECK), BM_SETCHECK, (WPARAM)s_nEnableRar, 0L);
-    SendMessage(GetDlgItem(hDlgWnd, IDC_CBR_CHECK), BM_SETCHECK, (WPARAM)s_nEnableCbr, 0L);
-    SendMessage(GetDlgItem(hDlgWnd, IDC_CAB_CHECK), BM_SETCHECK, (WPARAM)s_nEnableCab, 0L);
-    SendMessage(GetDlgItem(hDlgWnd, IDC_ARJ_CHECK), BM_SETCHECK, (WPARAM)s_nEnableArj, 0L);
-    SendMessage(GetDlgItem(hDlgWnd, IDC_LZH_CHECK), BM_SETCHECK, (WPARAM)s_nEnableLzh, 0L);
-}
-
-int IsChecked(HWND hDlgWnd, int nID)
-{
-    if (IsDlgButtonChecked(hDlgWnd, nID) == BST_CHECKED) {
-        return 1;
-    } else {
-        return 0;
-    }
+	std::vector<std::string> *pvMap = static_cast<std::vector<std::string>*>(reinterpret_cast<void*>(GetWindowLongPtr(hDlgWnd, DWLP_USER)));
+
+	pvMap->clear();
+	SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_LIST, LB_RESETCONTENT, 0L, 0L);
+
+	g_extManager.Each(ListUpdater(GetDlgItem(hDlgWnd, IDC_EXTENSION_LIST), *pvMap));
+	SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_LIST, LB_SETCARETINDEX, 0, 0);
+
+	SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_EDIT, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(static_cast<const void*>(g_extManager.GetUserExtensions().c_str())));
+
+	SendDlgItemMessage(hDlgWnd, IDC_TOPMOST_CHECK, BM_SETCHECK, PasswordManager::Get().GetTopMost() ? BST_CHECKED : BST_UNCHECKED, 0);
+
+	SendDlgItemMessage(hDlgWnd, IDC_PERUSERCONF_CHECK, BM_SETCHECK, !g_fSharedConf ? BST_CHECKED : BST_UNCHECKED, 0);
 }
 
 bool UpdateValue(HWND hDlgWnd)
 {
-    s_nEnable7z = IsChecked(hDlgWnd, IDC_7Z_CHECK);
-    s_nEnableRar = IsChecked(hDlgWnd, IDC_RAR_CHECK);
-    s_nEnableCbr = IsChecked(hDlgWnd, IDC_CBR_CHECK);
-    s_nEnableCab = IsChecked(hDlgWnd, IDC_CAB_CHECK);
-    s_nEnableArj = IsChecked(hDlgWnd, IDC_ARJ_CHECK);
-    s_nEnableLzh = IsChecked(hDlgWnd, IDC_LZH_CHECK);
+	std::vector<std::string> *pvMap = static_cast<std::vector<std::string>*>(reinterpret_cast<void*>(GetWindowLongPtr(hDlgWnd, DWLP_USER)));
+
+	int nNum = pvMap->size();
+	for(int i = 0; i < nNum; ++i) {
+		g_extManager.SetEnable((*pvMap)[i], SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_LIST, LB_GETSEL, i, 0) > 0);
+	}
 
-    return true;
+	LRESULT lLen = SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_EDIT, WM_GETTEXTLENGTH, 0, 0);
+	std::vector<char> vBuf(lLen+1);
+	SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_EDIT, WM_GETTEXT, lLen+1, reinterpret_cast<LPARAM>(&vBuf[0]));
+	g_extManager.SetUserExtensions(&vBuf[0]);
+
+	PasswordManager::Get().SetTopMost(SendDlgItemMessage(hDlgWnd, IDC_TOPMOST_CHECK, BM_GETCHECK, 0, 0) == BST_CHECKED);
+
+	bool fSharedConf = g_fSharedConf;
+	std::string sIniFileName = g_sIniFileName;
+	if(SendDlgItemMessage(hDlgWnd, IDC_PERUSERCONF_CHECK, BM_GETCHECK, 0, 0) == BST_CHECKED) {
+		g_fSharedConf = false;
+		g_sIniFileName = GetPersonalIniFileName(g_hInstance);
+		MakePersonalIniFolder();
+	} else {
+		g_fSharedConf = true;
+		g_sIniFileName = GetSharedIniFileName(g_hInstance);
+	}
+	if(fSharedConf != g_fSharedConf) {
+		if(SaveToIni()) {
+			DeleteFile(sIniFileName.c_str());
+		} else {
+			MessageBox(NULL, "Writing ini file is failed. Keep the old ini file location.", ExtManager::SECTION_NAME, MB_TASKMODAL | MB_ICONWARNING | MB_OK);
+			g_fSharedConf = fSharedConf;
+			g_sIniFileName = sIniFileName;
+		}
+	}
+
+	return true;
 }
 
 LRESULT CALLBACK ConfigDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
 {
-    switch (msg) {
-        case WM_INITDIALOG:
-            UpdateDialogItem(hDlgWnd);
-            return TRUE;
-        case WM_COMMAND:
-            switch (LOWORD(wp)) {
-                case IDOK:
-                    if (UpdateValue(hDlgWnd)) {
-                        SaveToIni();
-                        EndDialog(hDlgWnd, IDOK);
-                    }
-                    break;
-                case IDCANCEL:
-                    EndDialog(hDlgWnd, IDCANCEL);
-                    break;
-                case IDC_DEFAULT_BUTTON:
-                    SetParamDefault();
-                    UpdateDialogItem(hDlgWnd);
-                    break;
-                default:
-                    return FALSE;
-            }
-        default:
-            return FALSE;
-    }
-    return TRUE;
+	try {
+		switch (msg) {
+			case WM_INITDIALOG:
+				SetWindowLongPtr(hDlgWnd, DWLP_USER, lp);
+				UpdateDialogItem(hDlgWnd);
+				return TRUE;
+			case WM_COMMAND:
+				switch (LOWORD(wp)) {
+					case IDOK:
+						if (UpdateValue(hDlgWnd)) {
+							SaveToIni();
+							EndDialog(hDlgWnd, IDOK);
+						}
+						break;
+					case IDCANCEL:
+						EndDialog(hDlgWnd, IDCANCEL);
+						break;
+					case IDC_DEFAULT_BUTTON:
+						SetParamDefault();
+						UpdateDialogItem(hDlgWnd);
+						break;
+					case IDC_SOLID_BUTTON:
+						DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_SOLID_CONFIG_DIALOG), hDlgWnd, (DLGPROC)SolidConfigDlgProc);
+						break;
+					case IDC_SELECT_ALL_BUTTON:
+						SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_LIST, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0xFFFFU));
+						break;
+					case IDC_UNSELECT_ALL_BUTTON:
+						SendDlgItemMessage(hDlgWnd, IDC_EXTENSION_LIST, LB_SELITEMRANGE, FALSE, MAKELPARAM(0, 0xFFFFU));
+						break;
+					default:
+						return FALSE;
+				}
+			default:
+				return FALSE;
+		}
+		return TRUE;
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
 
 int __stdcall ConfigurationDlg(HWND parent, int fnc)
 {
-    if (fnc == 0) {
-        //about
-        DialogBox((HINSTANCE)s_hInstance, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), parent, (DLGPROC)AboutDlgProc);
-    } else {
-        DialogBox((HINSTANCE)s_hInstance, MAKEINTRESOURCE(IDD_CONFIG_DIALOG), parent, (DLGPROC)ConfigDlgProc);
-    }
-    return 0;
+	try {
+		if (fnc == 0) {
+			//about
+			DialogBox((HINSTANCE)g_hInstance, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), parent, (DLGPROC)AboutDlgProc);
+		} else {
+			std::vector<std::string> vMap;
+			DialogBoxParam((HINSTANCE)g_hInstance, MAKEINTRESOURCE(IDD_CONFIG_DIALOG), parent, (DLGPROC)ConfigDlgProc, reinterpret_cast<LPARAM>(static_cast<void*>(&vMap)));
+		}
+		return 0;
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return 0;
+	}
 }
 
 int __stdcall ExtractSolidArchive(LPCWSTR filename, SPI_OnWriteCallback pCallback)
 {
-    return ExtractSolidArchiveEx(filename, pCallback);
+	try {
+		return ExtractSolidArchiveEx(filename, pCallback);
+	} catch(...) {
+		handle_exception(__FUNCTION__);
+		return SPI_OTHER_ERROR;
+	}
 }
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/entryFuncs.h ./entryFuncs.h
--- /var/tmp/ax7z_src-orig/entryFuncs.h	2005-09-26 00:32:06.000000000 +0900
+++ ./entryFuncs.h	2013-08-24 11:36:30.042761100 +0900
@@ -1,7 +1,9 @@
 #ifndef spi00am_h
 #define spi00am_h
 
+#define NOMINMAX
 #include <windows.h>
+#undef NOMINMAX
 
 /*-------------------------------------------------------------------------*/
 // ƒtƒ@ƒCƒ‹�î•ñ�\‘¢‘Ì
@@ -51,7 +53,9 @@
 /*-------------------------------------------------------------------------*/
 // '00AM'ŠÖ�”‚Ìƒvƒ�ƒgƒ^ƒCƒv�éŒ¾
 /*-------------------------------------------------------------------------*/
-typedef int (CALLBACK *SPI_PROGRESS)(int, int, long);
+// Wrong calling convention
+typedef int (PASCAL *SPI_PROGRESS)(int nNum,int nDenom,long lData);
+//typedef int (CALLBACK *SPI_PROGRESS)(int, int, long);
 typedef void (CALLBACK *SPI_OnWriteCallback)(const void *data, UINT32 size, UINT32 processed, const fileInfoW* pFileInfo, UCHAR* pbStop);
 extern "C" {
 	int __declspec(dllexport) __stdcall GetPluginInfo
@@ -72,8 +76,8 @@
 	int __declspec(dllexport) __stdcall GetFileW(LPWSTR src,long len,
 			   LPWSTR dest, unsigned int flag,
 			   SPI_PROGRESS prgressCallback, long lData);
-    int __declspec(dllexport) __stdcall ConfigurationDlg(HWND parent, int fnc);
-    int __declspec(dllexport) __stdcall ExtractSolidArchive(LPCWSTR filename, SPI_OnWriteCallback pCallback);
+	int __declspec(dllexport) __stdcall ConfigurationDlg(HWND parent, int fnc);
+	int __declspec(dllexport) __stdcall ExtractSolidArchive(LPCWSTR filename, SPI_OnWriteCallback pCallback);
 }
 
 int GetArchiveInfoEx(LPSTR filename, long len, HLOCAL *lphInf);
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/infcache.cpp ./infcache.cpp
--- /var/tmp/ax7z_src-orig/infcache.cpp	2005-06-28 18:36:54.000000000 +0900
+++ ./infcache.cpp	2013-08-24 11:36:30.042761100 +0900
@@ -64,8 +64,8 @@
 //ƒLƒƒƒbƒVƒ…‚É‚ ‚ê‚ÎƒRƒs�[
 //ph:ƒA�[ƒJƒCƒu�î•ñ‚ðŽó‚¯Žæ‚éƒnƒ“ƒhƒ‹‚Ö‚Ìƒ|ƒCƒ“ƒ^
 //pinfo:ƒA�[ƒJƒCƒu‚Ìƒtƒ@ƒCƒ‹�î•ñ‚ðŽó‚¯Žæ‚éƒ|ƒCƒ“ƒ^
-//      ‚ ‚ç‚©‚¶‚ß pinfo ‚É filename ‚© position ‚ðƒZƒbƒg‚µ‚Ä‚¨‚­�B
-//      ƒLƒƒƒbƒVƒ…‚ª‚ ‚ê‚Î filename(position) ‚Ìˆê’v‚·‚é�î•ñ‚ð•Ô‚·�B
+//		‚ ‚ç‚©‚¶‚ß pinfo ‚É filename ‚© position ‚ðƒZƒbƒg‚µ‚Ä‚¨‚­�B
+//		ƒLƒƒƒbƒVƒ…‚ª‚ ‚ê‚Î filename(position) ‚Ìˆê’v‚·‚é�î•ñ‚ð•Ô‚·�B
 //ƒLƒƒƒbƒVƒ…‚É‚È‚¯‚ê‚Î�ASPI_NO_FUNCTION ‚ª•Ô‚é�B
 //ƒLƒƒƒbƒVƒ…‚É‚ ‚ê‚Î SPI_ALL_RIGHT ‚ª•Ô‚é�B
 //ƒA�[ƒJƒCƒu�î•ñ‚ÍƒLƒƒƒbƒVƒ…‚É‚ ‚é‚ª�Afilename(position) ‚ªˆê’v‚µ‚È‚¢�ê�‡‚Í
@@ -95,7 +95,14 @@
 					ret = SPI_NOT_SUPPORT;
 					break;
 				}
-				if (lstrcmpi(ptmp->filename, pinfo->filename) == 0) break;
+				// complete path relative to archive root
+				char path[sizeof(ptmp->path)+sizeof(ptmp->filename)];
+				strcpy(path, ptmp->path);
+				size_t len = strlen(path);
+				if(len && path[len-1] != '/' && path[len-1] != '\\') // need delimiter
+					strcat(path, "\\");
+				strcat(path, ptmp->filename);
+				if (lstrcmpi(path, pinfo->filename) == 0) break;
 				ptmp++;
 			}
 		} else {
@@ -185,8 +192,8 @@
 //ƒLƒƒƒbƒVƒ…‚É‚ ‚ê‚ÎƒRƒs�[
 //ph:ƒA�[ƒJƒCƒu�î•ñ‚ðŽó‚¯Žæ‚éƒnƒ“ƒhƒ‹‚Ö‚Ìƒ|ƒCƒ“ƒ^
 //pinfo:ƒA�[ƒJƒCƒu‚Ìƒtƒ@ƒCƒ‹�î•ñ‚ðŽó‚¯Žæ‚éƒ|ƒCƒ“ƒ^
-//      ‚ ‚ç‚©‚¶‚ß pinfo ‚É filename ‚© position ‚ðƒZƒbƒg‚µ‚Ä‚¨‚­�B
-//      ƒLƒƒƒbƒVƒ…‚ª‚ ‚ê‚Î filename(position) ‚Ìˆê’v‚·‚é�î•ñ‚ð•Ô‚·�B
+//		‚ ‚ç‚©‚¶‚ß pinfo ‚É filename ‚© position ‚ðƒZƒbƒg‚µ‚Ä‚¨‚­�B
+//		ƒLƒƒƒbƒVƒ…‚ª‚ ‚ê‚Î filename(position) ‚Ìˆê’v‚·‚é�î•ñ‚ð•Ô‚·�B
 //ƒLƒƒƒbƒVƒ…‚É‚È‚¯‚ê‚Î�ASPI_NO_FUNCTION ‚ª•Ô‚é�B
 //ƒLƒƒƒbƒVƒ…‚É‚ ‚ê‚Î SPI_ALL_RIGHT ‚ª•Ô‚é�B
 //ƒA�[ƒJƒCƒu�î•ñ‚ÍƒLƒƒƒbƒVƒ…‚É‚ ‚é‚ª�Afilename(position) ‚ªˆê’v‚µ‚È‚¢�ê�‡‚Í
@@ -197,43 +204,50 @@
 	HLOCAL hinfo;
 	int ret = GetCache(filepath, &hinfo);
 
-    if (ret) {
-        ret = SPI_ALL_RIGHT;
-        if (ph != NULL) {
-            UINT size = LocalSize(hinfo);
-            /* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
-            *ph = LocalAlloc(LMEM_FIXED, size);
-            if (*ph == NULL) {
-                ret = SPI_NO_MEMORY;
-            } else {
-                memcpy(*ph, (void*)hinfo, size);
-            }
-        } else {
-            fileInfoW *ptmp = (fileInfoW *)hinfo;
-            if (pinfo->filename[0] != L'\0') {
-                for (;;) {
-                    if (ptmp->method[0] == '\0') {
-                        ret = SPI_NOT_SUPPORT;
-                        break;
-                    }
-                    if (wcsicmp(ptmp->filename, pinfo->filename) == 0) break;
-                    ptmp++;
-                }
-            } else {
-                for (;;) {
-                    if (ptmp->method[0] == '\0') {
-                        ret = SPI_NOT_SUPPORT;
-                        break;
-                    }
-                    if (ptmp->position == pinfo->position) break;
-                    ptmp++;
-                }
-            }
-            if (ret == SPI_ALL_RIGHT) *pinfo = *ptmp;
-        }
-    } else {
-        ret = SPI_NO_FUNCTION;
-    }
+	if (ret) {
+		ret = SPI_ALL_RIGHT;
+		if (ph != NULL) {
+			UINT size = LocalSize(hinfo);
+			/* �o—Í—p‚Ìƒ�ƒ‚ƒŠ‚ÌŠ„‚è“–‚Ä */
+			*ph = LocalAlloc(LMEM_FIXED, size);
+			if (*ph == NULL) {
+				ret = SPI_NO_MEMORY;
+			} else {
+				memcpy(*ph, (void*)hinfo, size);
+			}
+		} else {
+			fileInfoW *ptmp = (fileInfoW *)hinfo;
+			if (pinfo->filename[0] != L'\0') {
+				for (;;) {
+					if (ptmp->method[0] == '\0') {
+						ret = SPI_NOT_SUPPORT;
+						break;
+					}
+					// complete path relative to archive root
+					wchar_t path[sizeof(ptmp->path)+sizeof(ptmp->filename)];
+					wcscpy(path, ptmp->path);
+					size_t len = wcslen(path);
+					if(len && path[len-1] != L'/' && path[len-1] != L'\\') // need delimiter
+						wcscat(path, L"\\");
+					wcscat(path, ptmp->filename);
+					if (wcsicmp(path, pinfo->filename) == 0) break;
+					ptmp++;
+				}
+			} else {
+				for (;;) {
+					if (ptmp->method[0] == '\0') {
+						ret = SPI_NOT_SUPPORT;
+						break;
+					}
+					if (ptmp->position == pinfo->position) break;
+					ptmp++;
+				}
+			}
+			if (ret == SPI_ALL_RIGHT) *pinfo = *ptmp;
+		}
+	} else {
+		ret = SPI_NO_FUNCTION;
+	}
 
 	cs.Leave();
 	return ret;
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/release.h ./release.h
--- /var/tmp/ax7z_src-orig/release.h	1970-01-01 09:00:00.000000000 +0900
+++ ./release.h	2015-01-09 01:07:13.452962200 +0900
@@ -0,0 +1,9 @@
+#ifndef RELEASE_H
+#define RELEASE_H
+
+#define RELEASE_STR "s_y4b5"
+#define RELEASE_LONG_STR "for 7-zip 4.57+ s_y4b5"
+#define PATCH_MAJOR 4
+#define PATCH_MINOR 5
+
+#endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/resource.h ./resource.h
--- /var/tmp/ax7z_src-orig/resource.h	2005-08-25 23:08:40.000000000 +0900
+++ ./resource.h	2013-08-17 15:47:40.469925700 +0900
@@ -2,25 +2,53 @@
 // Microsoft Visual C++ generated include file.
 // Used by ax7z.rc
 //
+#define IDV_VERSIONINFO                 1
+#define IDC_BROWSE_BUTTON               3
 #define IDD_CONFIG_DIALOG               101
 #define IDD_ABOUT_DIALOG                102
+#define IDD_PROGRESS                    103
+#define IDD_SOLID_CONFIG_DIALOG         104
+#define IDD_PASSWORD                    105
 #define IDC_7Z_CHECK                    1001
 #define IDC_RAR_CHECK                   1002
 #define IDC_CBR_CHECK                   1003
 #define IDC_CAB_CHECK                   1004
 #define IDC_ARJ_CHECK                   1005
-#define IDC_ARJ_CHECK2                  1006
 #define IDC_LZH_CHECK                   1006
-#define IDC_BUTTON1                     1010
-#define IDC_DEFAULT_BUTTON              1010
+#define IDC_DEFAULT_BUTTON              1007
+#define IDC_PROGRESSBAR                 1008
+#define IDC_ISO_CHECK                   1008
+#define IDC_PROGRESSTEXT                1009
+#define IDC_SOLID_BUTTON                1010
+#define IDC_SOLID_7Z_CHECK              1011
+#define IDC_SOLID_RAR_CHECK             1012
+#define IDC_MAX_LOOKAHEAD_EDIT          1013
+#define IDC_MAX_MEMORY_EDIT             1014
+#define IDC_MAX_DISK_EDIT               1015
+#define IDC_CACHE_FOLDER_EDIT           1016
+#define IDC_CLEAR_BUTTON                1017
+#define IDC_PURGE_MEMORY_EDIT           1018
+#define IDC_PURGE_DISK_EDIT             1019
+#define IDC_PASSWORD_EDIT               1020
+#define IDC_EXTENSION_LIST              1021
+#define IDC_SELECT_ALL_BUTTON           1022
+#define IDC_UNSELECT_ALL_BUTTON         1023
+#define IDC_EXTENSION_EDIT              1024
+#define IDC_SKIPARC_BUTTON              1028
+#define IDC_SKIP_BUTTON                 1029
+#define IDC_GUIDE_STATIC                1030
+#define IDC_TOPMOST_CHECK               1031
+#define IDC_7ZVERSION                   1032
+#define IDC_PERUSERCONF_CHECK           1033
+#define IDM_TOPMOST                     40000
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        103
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1011
+#define _APS_NEXT_RESOURCE_VALUE        106
+#define _APS_NEXT_COMMAND_VALUE         40002
+#define _APS_NEXT_CONTROL_VALUE         1034
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/sqlite3/sqlite3helper.h ./sqlite3/sqlite3helper.h
--- /var/tmp/ax7z_src-orig/sqlite3/sqlite3helper.h	1970-01-01 09:00:00.000000000 +0900
+++ ./sqlite3/sqlite3helper.h	2015-01-09 00:41:22.509864600 +0900
@@ -0,0 +1,151 @@
+#ifndef SQLITE3HELPER_H
+#define SQLITE3HELPER_H
+
+#include "sqlite3helper_decl.h"
+#include "sqlite3.h"
+
+namespace yak {
+namespace sqlite {
+
+// TODO: Move support
+
+// Tiny wrapper to sqlite3
+#define CHECK(exp) do { if((exp) != SQLITE_OK) { throw sqlite_error(this->errmsg()); } } while(0)
+inline Database::Database() : m_db(0) {}
+inline Database::Database(const char* dbfile)
+{
+	CHECK(sqlite3_open(dbfile, &m_db));
+}
+inline Database& Database::reopen(const char* dbfile)
+{
+	// TODO: check return value
+	CHECK(sqlite3_close(m_db));
+	CHECK(sqlite3_open(dbfile, &m_db));
+	return *this;
+}
+inline Database::~Database()
+{
+	sqlite3_close(m_db); // no throw
+}
+inline void Database::close()
+{
+	CHECK(sqlite3_close(m_db));
+	m_db = 0;
+}
+inline const Database& Database::exec(const char* sql) const
+{
+	CHECK(sqlite3_exec(m_db, sql, 0, 0, 0));
+	return *this;
+}
+inline const char* Database::errmsg() const
+{
+	return sqlite3_errmsg(m_db);
+}
+inline Database::operator sqlite3*() const { return m_db; }
+#undef CHECK
+
+// Tiny wrapper to sqlite3_stmt
+inline Statement::Statement() : m_stmt(0) {}
+inline Statement::Statement(sqlite3 *db, const char* sql)
+{
+	sqlite3_prepare_v2(db, sql, -1, &m_stmt, NULL);
+}
+inline Statement& Statement::reprepare(sqlite3 *db, const char* sql)
+{
+	sqlite3_finalize(m_stmt);
+	sqlite3_prepare_v2(db, sql, -1, &m_stmt, NULL);
+	return *this;
+}
+inline const Statement& Statement::reset() const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_reset(m_stmt);
+	return *this;
+}
+inline Statement& Statement::finalize()
+{
+	sqlite3_finalize(m_stmt);
+	m_stmt = 0;
+	return *this;
+}
+inline Statement::~Statement()
+{
+	sqlite3_finalize(m_stmt);
+}
+inline const Statement& Statement::bind(int idx, int value) const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_bind_int(m_stmt, idx, value);
+	return *this;
+}
+inline const Statement& Statement::bind(int idx, unsigned int value) const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_bind_int64(m_stmt, idx, value);
+	return *this;
+}
+inline const Statement& Statement::bind(int idx, int64_t value) const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_bind_int64(m_stmt, idx, value);
+	return *this;
+}
+inline const Statement& Statement::bind(int idx, const char* value) const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_bind_text(m_stmt, idx, value, -1, SQLITE_TRANSIENT);
+	return *this;
+}
+inline const Statement& Statement::bind(int idx, const void* value, int size, void (*func)(void*)) const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+	sqlite3_bind_blob(m_stmt, idx, value, size, func);
+	return *this;
+}
+inline bool Statement::operator()() const
+{
+	if(!m_stmt) throw std::logic_error("not prepared");
+// TODO: catch error on prepare()
+	return sqlite3_step(m_stmt) == SQLITE_ROW;
+}
+inline int Statement::get_int(int idx) const
+{
+	return sqlite3_column_int(m_stmt, idx);
+}
+inline int64_t Statement::get_int64(int idx) const
+{
+	return sqlite3_column_int64(m_stmt, idx);
+}
+inline double Statement::get_double(int idx) const
+{
+	return sqlite3_column_double(m_stmt, idx);
+}
+inline const char* Statement::get_text(int idx) const
+{
+	return static_cast<const char*>(static_cast<const void*>(sqlite3_column_text(m_stmt, idx)));
+}
+inline const void* Statement::get_blob(int idx) const
+{
+	return sqlite3_column_blob(m_stmt, idx);
+}
+inline int Statement::get_bytes(int idx) const
+{
+	return sqlite3_column_bytes(m_stmt, idx);
+}
+inline const char* Statement::get_name(int idx) const
+{
+	return sqlite3_column_name(m_stmt, idx);
+}
+inline int Statement::get_type(int idx) const
+{
+	return sqlite3_column_type(m_stmt, idx);
+}
+inline int Statement::get_count() const
+{
+	return sqlite3_column_count(m_stmt);
+}
+
+} // namespace sqlite
+} // namespace yak
+
+#endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/sqlite3/sqlite3helper_decl.h ./sqlite3/sqlite3helper_decl.h
--- /var/tmp/ax7z_src-orig/sqlite3/sqlite3helper_decl.h	1970-01-01 09:00:00.000000000 +0900
+++ ./sqlite3/sqlite3helper_decl.h	2015-01-09 00:41:22.513865000 +0900
@@ -0,0 +1,70 @@
+#ifndef SQLITE3HELPER_DECL_H
+#define SQLITE3HELPER_DECL_H
+
+#include <stdexcept>
+#include <stdint.h>
+
+struct sqlite3;
+struct sqlite3_stmt;
+
+namespace yak {
+namespace sqlite {
+
+struct sqlite_error : std::runtime_error
+{
+	sqlite_error(const char* msg) : std::runtime_error(msg) {}
+};
+
+// Tiny wrapper to sqlite3
+class Database
+{
+private:
+	sqlite3* m_db;
+	Database& operator=(const Database&);
+	Database(const Database&);
+public:
+	Database();
+	Database(const char* dbfile);
+	Database& reopen(const char* dbfile);
+	~Database();
+	void close();
+	const Database& exec(const char* sql) const;
+	const char* errmsg() const;
+	operator sqlite3*() const;
+};
+
+// Tiny wrapper to sqlite3_stmt
+class Statement
+{
+private:
+	sqlite3_stmt *m_stmt;
+	Statement& operator=(const Statement&);
+	Statement(const Statement&);
+public:
+	Statement();
+	Statement(sqlite3 *db, const char* sql);
+	Statement& reprepare(sqlite3 *db, const char* sql);
+	const Statement& reset() const;
+	Statement& finalize();
+	~Statement();
+	const Statement& bind(int idx, int value) const;
+	const Statement& bind(int idx, unsigned int value) const;
+	const Statement& bind(int idx, int64_t value) const;
+	const Statement& bind(int idx, const char* value) const;
+	const Statement& bind(int idx, const void* value, int size, void (*func)(void*) = reinterpret_cast<void(*)(void*)>(-1) /* SQLITE_TRANSIENT */) const;
+	bool operator()() const;
+	int get_int(int idx) const;
+	int64_t get_int64(int idx) const;
+	double get_double(int idx) const;
+	const char* get_text(int idx) const;
+	const void* get_blob(int idx) const;
+	int get_bytes(int idx) const;
+	const char* get_name(int idx) const;
+	int get_type(int idx) const;
+	int get_count() const;
+};
+
+} // namespace sqlite
+} // namespace yak
+
+#endif
diff -urN -X diff-exclude.txt /var/tmp/ax7z_src-orig/version.hpp ./version.hpp
--- /var/tmp/ax7z_src-orig/version.hpp	1970-01-01 09:00:00.000000000 +0900
+++ ./version.hpp	2013-08-14 15:06:26.070136300 +0900
@@ -0,0 +1,102 @@
+#ifndef YAK_UTIL_WINDOWS_HPP
+#define YAK_UTIL_WINDOWS_HPP
+
+#include <windows.h>
+
+#include <vector>
+#include <string>
+#include <stdexcept>
+
+namespace yak {
+namespace util {
+namespace windows {
+
+class VersionResource
+{
+public:
+	VersionResource(const std::string &sPath) : pTrans(0)
+	{
+		const char* sz = sPath.c_str();
+		DWORD dwDummy;
+		DWORD dwSize = GetFileVersionInfoSize(sz, &dwDummy);
+		if(!dwSize) throw std::runtime_error("File not found");
+		buf.resize(dwSize);
+		GetFileVersionInfo(sz, 0, dwSize, &buf[0]);
+	}
+	struct LANGANDCODEPAGE
+	{
+		WORD wLanguage;
+		WORD wCodePage;
+	};
+	UINT GetLangAndCodePageCount() const
+	{
+		if(!pTrans) SetTranslation();
+		return uiTrans / sizeof(LANGANDCODEPAGE);
+	}
+	const LANGANDCODEPAGE& GetLangAndCodePage(UINT idx) const
+	{
+		if(!pTrans) SetTranslation();
+		return pTrans[idx];
+	}
+	enum VT_TYPE {
+		COMMENTS, COMPANY_NAME, FILE_DESCRIPTION, FILE_VERSION,
+		INTERNAL_NAME, LEGAL_COPYRIGHT, LEGAL_TRADEMARKS, ORIGINAL_FILENAME,
+		PRODUCT_NAME, PRODUCT_VERSION, PRIVATE_BUILD, SPECIAL_BUID,
+		EOT,
+	};
+	bool IsExisted(VT_TYPE type, UINT idx = 0) const
+	{
+		std::string key = Key(type, idx);
+		LPVOID p; UINT ui;
+		// Probably win32api declaration error
+		return VerQueryValue(const_cast<BYTE*>(&buf[0]), const_cast<LPSTR>(key.c_str()), &p, &ui) ? true : false;
+	}
+	std::string GetValue(VT_TYPE type, UINT idx = 0) const
+	{
+		std::string key = Key(type, idx);
+		LPVOID p; UINT ui;
+		// Probably win32api declaration error
+		if(VerQueryValue(const_cast<BYTE*>(&buf[0]), const_cast<LPSTR>(key.c_str()), &p, &ui)) {
+			return std::string(static_cast<char*>(p));
+		} else return std::string();
+	}
+	static const char* GetKeyName(VT_TYPE idx)
+	{
+		static const char* const szBlockName[] = {
+			"Comments", "CompanyName", "FileDescription", "FileVersion",
+			"InternalName", "LegalCopyright", "LegalTrademarks", "OriginalFilename",
+			"ProductName", "ProductVersion", "PrivateBuild", "SpecialBuild",
+		};
+		const UINT num = sizeof(szBlockName) / sizeof(szBlockName[0]);
+		if(idx < num) return szBlockName[idx];
+		else return 0;
+	}
+private:
+	void SetTranslation() const
+	{
+		LPVOID p;
+		// Probably win32api declaration error
+		VerQueryValue(const_cast<BYTE*>(&buf[0]), "\\VarFileInfo\\Translation", &p, &uiTrans);
+		pTrans = static_cast<LANGANDCODEPAGE*>(p);
+	}
+	std::string Key(VT_TYPE type, UINT idx) const
+	{
+		if(!pTrans) SetTranslation();
+		std::string buf2(4096, '\0');
+		const char* key = GetKeyName(type);
+		if(key) {
+			std::size_t size = wsprintf(&buf2[0], "\\StringFileInfo\\%04x%04x\\%s", pTrans[idx].wLanguage, pTrans[idx].wCodePage, key);
+			buf2.resize(size);
+		} else buf2.resize(0);
+		return buf2;
+	}
+	std::vector<BYTE> buf;
+	mutable LANGANDCODEPAGE *pTrans;
+	mutable UINT uiTrans;
+};
+
+} // namespace windows
+} // namespace util
+} // namespace yak
+
+#endif
--- /var/tmp/ax7z_src-orig/7z/7zip/UI/Common/OpenArchive.cpp	2007-08-28 17:57:45.000000000 +0900
+++ 7z/7zip/UI/Common/OpenArchive.cpp	2013-04-12 00:17:02.204427800 +0900
@@ -155,6 +155,26 @@
     }
     orderIndices2 += orderIndices;
     orderIndices = orderIndices2;
+
+/* begin: extracted from 4.65 */
+    if (orderIndices.Size() >= 2)
+    {
+      int isoIndex = codecs->FindFormatForArchiveType(L"iso");
+      int udfIndex = codecs->FindFormatForArchiveType(L"udf");
+      int iIso = -1;
+      int iUdf = -1;
+      for (int i = 0; i < orderIndices.Size(); i++)
+      {
+        if (orderIndices[i] == isoIndex) iIso = i;
+        if (orderIndices[i] == udfIndex) iUdf = i;
+      }
+      if (iUdf == iIso + 1)
+      {
+        orderIndices[iUdf] = isoIndex;
+        orderIndices[iIso] = udfIndex;
+      }
+    }
+/* end: extracted from 4.65 */
   }
   else if (extension == L"000" || extension == L"001")
   {
--- /var/tmp/ax7z_src-orig/7z/7zip/UI/Common/LoadCodecs.cpp	2007-10-24 18:44:50.000000000 +0900
+++ 7z/7zip/UI/Common/LoadCodecs.cpp	2013-04-12 00:17:02.201427500 +0900
@@ -468,9 +468,11 @@
   for (int i = 0; i < Formats.Size(); i++)
   {
     const CArcInfoEx &arc = Formats[i];
-    if (!arc.UpdateEnabled)
-      continue;
-    if (arc.Name.CompareNoCase(arcType) == 0)
+// begin: adjusted to 4.65
+//    if (!arc.UpdateEnabled)
+//      continue;
+// end: adjusted to 4.65
+	if (arc.Name.CompareNoCase(arcType) == 0)
       return i;
   }
   return -1;
