diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-12-31 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:58 +0300 |
commit | 9608215ad8deb58355bae27692669fda067c4f43 (patch) | |
tree | 1227131a3f19bc36e5da4ba11791154d05cc08af | |
parent | 5de23c1deb52b8be4c43ad9f694c64bbddd0c38a (diff) |
15.1315.13
73 files changed, 1849 insertions, 778 deletions
diff --git a/C/7zVersion.h b/C/7zVersion.h index 2975c81f..3e5c9bd5 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,9 +1,9 @@ #define MY_VER_MAJOR 15 -#define MY_VER_MINOR 12 +#define MY_VER_MINOR 13 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "15.12" -#define MY_VERSION "15.12" -#define MY_DATE "2015-11-19" +#define MY_VERSION_NUMBERS "15.13" +#define MY_VERSION "15.13" +#define MY_DATE "2015-12-31" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" diff --git a/C/CpuArch.h b/C/CpuArch.h index fa44160a..f6a28ba7 100644 --- a/C/CpuArch.h +++ b/C/CpuArch.h @@ -1,5 +1,5 @@ /* CpuArch.h -- CPU specific code -2015-10-31: Igor Pavlov : Public domain */ +2015-12-01: Igor Pavlov : Public domain */ #ifndef __CPU_ARCH_H #define __CPU_ARCH_H @@ -78,7 +78,9 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem || defined(__MIPSEB) \ || defined(_MIPSEB) \ || defined(__m68k__) \ + || defined(__s390__) \ || defined(__s390x__) \ + || defined(__zarch__) \ || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) #define MY_CPU_BE #endif diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c index f3263988..41aab71e 100644 --- a/C/Util/7zipInstall/7zipInstall.c +++ b/C/Util/7zipInstall/7zipInstall.c @@ -1,5 +1,5 @@ /* 7zipInstall.c - 7-Zip Installer -2015-11-08 : Igor Pavlov : Public domain */ +2015-12-09 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -571,6 +571,8 @@ static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM #endif break; } + + default: return FALSE; } break; @@ -1011,7 +1013,8 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, BOOL bRet; MSG msg; - while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0) + // we need messages for all thread windows (including EDITTEXT window in dialog) + while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) return retCode; diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c index d0bfd4cc..cd66002a 100644 --- a/C/Util/7zipUninstall/7zipUninstall.c +++ b/C/Util/7zipUninstall/7zipUninstall.c @@ -1,5 +1,5 @@ /* 7zipUninstall.c - 7-Zip Uninstaller -2015-11-08 : Igor Pavlov : Public domain */ +2015-12-26 : Igor Pavlov : Public domain */ #include "Precomp.h" @@ -542,7 +542,7 @@ static BOOL RemoveDir() #define k_Lang L"Lang" // NUM_LANG_TXT_FILES files are placed before en.ttt -#define NUM_LANG_TXT_FILES 86 +#define NUM_LANG_TXT_FILES 87 #ifdef _64BIT_INSTALLER #define NUM_EXTRA_FILES_64BIT 1 @@ -556,7 +556,7 @@ static const char *k_Names = "af an ar ast az ba be bg bn br ca co cs cy da de el eo es et eu ext" " fa fi fr fur fy ga gl gu he hi hr hu hy id io is it ja ka kaa kk ko ku ku-ckb ky" " lij lt lv mk mn mng mng2 mr ms nb ne nl nn pa-in pl ps pt pt-br ro ru" - " sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi zh-cn zh-tw" + " sa si sk sl sq sr-spc sr-spl sv ta th tr tt ug uk uz va vi yo zh-cn zh-tw" " en.ttt" " descript.ion" " History.txt" @@ -771,6 +771,8 @@ static INT_PTR CALLBACK MyDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM OnClose(); break; } + + default: return FALSE; } break; @@ -1033,7 +1035,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, BOOL bRet; MSG msg; - while ((bRet = GetMessage(&msg, g_HWND, 0, 0)) != 0) + while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) return retCode; diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index c2478a29..7e9478fc 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -567,14 +567,17 @@ static const char *g_Exts = " iso bin nrg mdf img pdi tar cpio xpi" " vfd vhd vud vmc vsv" " vmdk dsk nvram vmem vmsd vmsn vmss vmtm" - " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def" + " inl inc idl acf asa" + " h hpp hxx c cpp cxx m mm go swift" + " rc java cs rs pas bas vb cls ctl frm dlg def" " f77 f f90 f95" - " asm sql manifest dep" + " asm s" + " sql manifest dep" " mak clw csproj vcproj sln dsp dsw" " class" - " bat cmd" + " bat cmd bash sh" " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml" - " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs" + " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs" " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf" " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf" " abw afp cwk lwp wpd wps wpt wrf wri" diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp index 711bfdf7..e31de4fe 100644 --- a/CPP/7zip/Archive/Cab/CabHandler.cpp +++ b/CPP/7zip/Archive/Cab/CabHandler.cpp @@ -781,6 +781,7 @@ HRESULT CFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processe realProcessed += size; if (processedSize) *processedSize = realProcessed; + m_PosInFolder += size; return S_OK; // return E_FAIL; } @@ -843,7 +844,7 @@ HRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex) return S_OK; } - const unsigned kBufSize = (1 << 10); + const unsigned kBufSize = (1 << 12); Byte buf[kBufSize]; for (unsigned i = 0; i < kBufSize; i++) buf[i] = 0; @@ -937,8 +938,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CRecordVector<bool> extractStatuses; - for (i = 0; i < numItems;) + for (i = 0;;) { + lps->OutSize = totalUnPacked; + lps->InSize = totalPacked; + RINOK(lps->SetCur()); + + if (i >= numItems) + break; + unsigned index = allFilesMode ? i : indices[i]; const CMvItem &mvItem = m_Database.Items[index]; @@ -1003,10 +1011,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, curUnpack = item.GetEndOffset(); } - lps->OutSize = totalUnPacked; - lps->InSize = totalPacked; - RINOK(lps->SetCur()); - CFolderOutStream *cabFolderOutStream = new CFolderOutStream; CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream); diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp index a72e05f7..ca0052bf 100644 --- a/CPP/7zip/Archive/Cab/CabIn.cpp +++ b/CPP/7zip/Archive/Cab/CabIn.cpp @@ -67,6 +67,7 @@ void CInArchive::ReadOtherArc(COtherArc &oa) ReadName(oa.DiskName); } + struct CSignatureFinder { Byte *Buf; @@ -100,6 +101,7 @@ struct CSignatureFinder HRESULT Find(); }; + HRESULT CSignatureFinder::Find() { for (;;) @@ -156,6 +158,7 @@ HRESULT CSignatureFinder::Find() } } + bool CInArcInfo::Parse(const Byte *p) { if (Get32(p + 0x0C) != 0 || @@ -177,6 +180,7 @@ bool CInArcInfo::Parse(const Byte *p) return true; } + HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) { IsArc = false; @@ -286,7 +290,9 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) if (ai.IsThereNext()) ReadOtherArc(ai.NextArc); UInt32 i; + db.Folders.ClearAndReserve(ai.NumFolders); + for (i = 0; i < ai.NumFolders; i++) { Read(p, 8); @@ -311,6 +317,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) } db.Items.ClearAndReserve(ai.NumFiles); + for (i = 0; i < ai.NumFiles; i++) { Read(p, 16); @@ -324,6 +331,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) item.Attributes = Get16(p + 14); ReadName(item.Name); + if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size()) { HeaderError = true; @@ -336,6 +344,7 @@ HRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) return S_OK; } + HRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit) { try @@ -370,6 +379,7 @@ static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param) return MyCompare(p1->ItemIndex, p2->ItemIndex); } + bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) { const CMvItem *p1 = &Items[i1]; @@ -384,12 +394,15 @@ bool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2) && item1.Name == item2.Name; } + void CMvDatabaseEx::FillSortAndShrink() { Items.Clear(); StartFolderOfVol.Clear(); FolderStartFileIndex.Clear(); + int offset = 0; + FOR_VECTOR (v, Volumes) { const CDatabaseEx &db = Volumes[v]; @@ -422,11 +435,12 @@ void CMvDatabaseEx::FillSortAndShrink() FOR_VECTOR (i, Items) { int folderIndex = GetFolderIndex(&Items[i]); - if (folderIndex >= (int)FolderStartFileIndex.Size()) + while (folderIndex >= (int)FolderStartFileIndex.Size()) FolderStartFileIndex.Add(i); } } + bool CMvDatabaseEx::Check() { for (unsigned v = 1; v < Volumes.Size(); v++) @@ -444,9 +458,11 @@ bool CMvDatabaseEx::Check() return false; } } + UInt32 beginPos = 0; UInt64 endPos = 0; int prevFolder = -2; + FOR_VECTOR (i, Items) { const CMvItem &mvItem = Items[i]; @@ -456,15 +472,19 @@ bool CMvDatabaseEx::Check() const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex]; if (item.IsDir()) continue; + int folderIndex = GetFolderIndex(&mvItem); + if (folderIndex != prevFolder) prevFolder = folderIndex; else if (item.Offset < endPos && (item.Offset != beginPos || item.GetEndOffset() != endPos)) return false; + beginPos = item.Offset; endPos = item.GetEndOffset(); } + return true; } diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h index baeeb7b2..a1fc6bdc 100644 --- a/CPP/7zip/Archive/Cab/CabIn.h +++ b/CPP/7zip/Archive/Cab/CabIn.h @@ -25,6 +25,7 @@ struct COtherArc } }; + struct CArchInfo { Byte VersionMinor; // cabinet file format version, minor @@ -65,6 +66,7 @@ struct CArchInfo } }; + struct CInArcInfo: public CArchInfo { UInt32 Size; // size of this cabinet file in bytes @@ -105,17 +107,20 @@ struct CDatabase } }; + struct CDatabaseEx: public CDatabase { CMyComPtr<IInStream> Stream; }; + struct CMvItem { unsigned VolumeIndex; unsigned ItemIndex; }; + class CMvDatabaseEx { bool AreItemsEqual(unsigned i1, unsigned i2); diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index 3a4834cd..e39dbab5 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp @@ -571,6 +571,7 @@ HRESULT CDatabase::Open(IInStream *inStream) RINOK(AddNode(-1, root.SonDid)); unsigned numCabs = 0; + FOR_VECTOR (i, Refs) { const CItem &item = Items[Refs[i].Did]; @@ -578,16 +579,20 @@ HRESULT CDatabase::Open(IInStream *inStream) continue; bool isMsiName; UString msiName = ConvertName(item.Name, isMsiName); - if (isMsiName) + if (isMsiName && !msiName.IsEmpty()) { + bool isThereExt = (msiName.Find(L'.') >= 0); + bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); if (msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab") - || msiName.Len() >= 3 && msiName[0] != k_Msi_SpecChar && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) + || !isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe") + || !isMsiSpec && !isThereExt) { numCabs++; MainSubfile = i; } } } + if (numCabs > 1) MainSubfile = -1; diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index a9d0facb..606aeed1 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp @@ -1118,7 +1118,7 @@ HRESULT CHandler::SeekAndRead(IInStream *inStream, UInt64 block, Byte *data, siz { if (block == 0 || block >= _h.NumBlocks) return S_FALSE; - if (((size + (1 << _h.BlockBits) + 1) >> _h.BlockBits) > _h.NumBlocks - block) + if (((size + ((size_t)1 << _h.BlockBits) - 1) >> _h.BlockBits) > _h.NumBlocks - block) return S_FALSE; RINOK(inStream->Seek((UInt64)block << _h.BlockBits, STREAM_SEEK_SET, NULL)); _totalRead += size; @@ -1167,6 +1167,9 @@ HRESULT CHandler::Open2(IInStream *inStream) RINOK(_openCallback->SetTotal(NULL, &_phySize)); } + UInt64 fileSize = 0; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &fileSize)); + CRecordVector<CGroupDescriptor> groups; { @@ -1213,6 +1216,21 @@ HRESULT CHandler::Open2(IInStream *inStream) if (_h.NumInodes < _h.NumFreeInodes) return S_FALSE; + + UInt32 numNodes = _h.InodesPerGroup; + if (numNodes > _h.NumInodes) + numNodes = _h.NumInodes; + size_t nodesDataSize = (size_t)numNodes * _h.InodeSize; + + if (nodesDataSize / _h.InodeSize != numNodes) + return S_FALSE; + + // that code to reduce false detecting cases + if (nodesDataSize > fileSize) + { + if (numNodes > (1 << 24)) + return S_FALSE; + } UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; // numReserveInodes = _h.NumInodes + 1; @@ -1222,13 +1240,6 @@ HRESULT CHandler::Open2(IInStream *inStream) _refs.Reserve(numReserveInodes); } - UInt32 numNodes = _h.InodesPerGroup; - if (numNodes > _h.NumInodes) - numNodes = _h.NumInodes; - size_t nodesDataSize = numNodes * _h.InodeSize; - if (nodesDataSize / _h.InodeSize != numNodes) - return S_FALSE; - CByteBuffer nodesData; nodesData.Alloc(nodesDataSize); diff --git a/CPP/7zip/Archive/FatHandler.cpp b/CPP/7zip/Archive/FatHandler.cpp index e8340f1d..9c37c062 100644 --- a/CPP/7zip/Archive/FatHandler.cpp +++ b/CPP/7zip/Archive/FatHandler.cpp @@ -160,10 +160,13 @@ bool CHeader::Parse(const Byte *p) if (NumFats < 1 || NumFats > 4) return false; + // we also support images that contain 0 in offset field. + bool isOkOffset = (codeOffset == 0 || (p[0] == 0xEB && p[1] == 0)); + UInt16 numRootDirEntries = Get16(p + 17); if (numRootDirEntries == 0) { - if (codeOffset < 90) + if (codeOffset < 90 && !isOkOffset) return false; NumFatBits = 32; NumRootDirSectors = 0; @@ -171,7 +174,7 @@ bool CHeader::Parse(const Byte *p) else { // Some FAT12s don't contain VolFields - if (codeOffset < 62 - 24) + if (codeOffset < 62 - 24 && !isOkOffset) return false; NumFatBits = 0; UInt32 mask = (1 << (SectorSizeLog - 5)) - 1; diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h index 5c1a4bcf..4000fc92 100644 --- a/CPP/7zip/Archive/Iso/IsoIn.h +++ b/CPP/7zip/Archive/Iso/IsoIn.h @@ -170,7 +170,7 @@ struct CBootInitialEntry // Partition Table found in the boot image. UInt16 SectorCount; // This is the number of virtual/emulated sectors the system // will store at Load Segment during the initial boot procedure. - UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use + UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use // Relative/Logical block addressing. Byte VendorSpec[20]; diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 9cbc7c3c..28562007 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -347,18 +347,24 @@ struct CSection CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} + // const UInt32 GetSize() const { return PSize; } + const UInt32 GetSize() const { return MyMin(PSize, VSize); } + void UpdateTotalSize(UInt32 &totalSize) const { UInt32 t = Pa + PSize; if (totalSize < t) totalSize = t; } + void Parse(const Byte *p); int Compare(const CSection &s) const { RINOZ(MyCompare(Pa, s.Pa)); - return MyCompare(PSize, s.PSize); + UInt32 size1 = GetSize(); + UInt32 size2 = s.GetSize(); + return MyCompare(size1, size2); } }; @@ -1039,7 +1045,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val switch (propID) { case kpidPath: prop = MultiByteToUnicodeString(item.Name); break; - case kpidSize: prop = (UInt64)MyMin(item.PSize, item.VSize); break; + case kpidSize: prop = (UInt64)item.GetSize(); break; case kpidPackSize: prop = (UInt64)item.PSize; break; case kpidVirtualSize: prop = (UInt64)item.VSize; break; case kpidOffset: prop = item.Pa; break; @@ -1883,14 +1889,17 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector } f.CloseBlock(2); } + f.CloseBlock(0); return true; } + HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchiveOpenCallback *callback) { const CSection § = _sections[sectionIndex]; - size_t fileSize = sect.PSize; // Maybe we need sect.VSize here !!! + const size_t fileSize = sect.GetSize(); + if (fileSize > kFileSizeMax) return S_FALSE; { @@ -2031,8 +2040,8 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi { UInt32 mask = (1 << numBits) - 1; size_t end = ((maxOffset + mask) & ~mask); - // 9.29: we use only PSize. PSize can be larger than VSize - if (/* end < sect.VSize && */ end <= sect.PSize) + + if (/* end < sect.VSize && */ end <= sect.GetSize()) { CSection sect2; sect2.Flags = 0; @@ -2050,7 +2059,8 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX // the code for .rsrc_2 is commented. - sect2.PSize = sect.PSize - (UInt32)maxOffset; + sect2.PSize = sect.GetSize() - (UInt32)maxOffset; + if (sect2.PSize != 0) { sect2.VSize = sect2.PSize; @@ -2463,7 +2473,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, else if (mixItem.ResourceIndex >= 0) size = _items[mixItem.ResourceIndex].GetSize(); else - size = _sections[mixItem.SectionIndex].PSize; + size = _sections[mixItem.SectionIndex].GetSize(); totalSize += size; } extractCallback->SetTotal(totalSize); @@ -2539,7 +2549,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, } else { - currentItemSize = sect.PSize; + currentItemSize = sect.GetSize(); if (!testMode && !outStream) continue; diff --git a/CPP/7zip/Archive/PpmdHandler.cpp b/CPP/7zip/Archive/PpmdHandler.cpp index 86927f8f..528c5ceb 100644 --- a/CPP/7zip/Archive/PpmdHandler.cpp +++ b/CPP/7zip/Archive/PpmdHandler.cpp @@ -1,5 +1,5 @@ -/* PpmdHandler.c -- PPMd format handler -2010-03-10 : Igor Pavlov : Public domain +/* PpmdHandler.cpp -- PPMd format handler +2015-11-30 : Igor Pavlov : Public domain This code is based on: PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ @@ -349,6 +349,7 @@ struct CPpmdCpp } }; + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { @@ -386,13 +387,17 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CPpmdCpp ppmd(_item.Ver); if (!ppmd.Alloc(_item.MemInMB)) return E_OUTOFMEMORY; + Int32 opRes = NExtract::NOperationResult::kUnsupportedMethod; + if (_item.IsSupported()) { opRes = NExtract::NOperationResult::kDataError; + ppmd.Init(_item.Order, _item.Restor); inBuf.Init(); UInt64 outSize = 0; + if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK) for (;;) { @@ -431,6 +436,13 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, { RINOK(WriteStream(realOutStream, outBuf.Buf, i)); } + + if (inBuf.Extra) + { + opRes = NExtract::NOperationResult::kUnexpectedEnd; + break; + } + if (sym < 0) { if (sym == -1 && ppmd.IsFinishedOK()) @@ -438,12 +450,15 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, break; } } + RINOK(inBuf.Res); } + realOutStream.Release(); return extractCallback->SetOperationResult(opRes); } + static const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 }; REGISTER_ARC_I( diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp index a65c9e32..092dcbc9 100644 --- a/CPP/7zip/Archive/Zip/ZipHandler.cpp +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -4,6 +4,7 @@ #include "../../../Common/ComTry.h" #include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" #include "../../../Windows/PropVariant.h" #include "../../../Windows/TimeUtils.h" @@ -241,12 +242,14 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val COM_TRY_BEGIN NWindows::NCOM::CPropVariant prop; const CItemEx &item = m_Items[index]; + const CExtraBlock &extra = item.GetMainExtra(); + switch (propID) { case kpidPath: { UString res; - item.GetUnicodeString(item.Name, res, _forceCodePage, _specifiedCodePage); + item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage); NItemName::ConvertToOSName2(res); prop = res; break; @@ -261,9 +264,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val FILETIME ft; UInt32 unixTime; UInt32 type; - if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) + if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft)) type = NFileTimeType::kWindows; - else if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) + else if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) type = NFileTimeType::kUnix; else type = NFileTimeType::kDOS; @@ -274,7 +277,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidCTime: { FILETIME ft; - if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft)) + if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kCTime, ft)) prop = ft; break; } @@ -282,7 +285,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val case kpidATime: { FILETIME ft; - if (item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft)) + if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kATime, ft)) prop = ft; break; } @@ -291,10 +294,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { FILETIME utc; bool defined = true; - if (!item.CentralExtra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) + if (!extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, utc)) { UInt32 unixTime = 0; - if (item.CentralExtra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) + if (extra.GetUnixTime(true, NFileHeader::NUnixTime::kMTime, unixTime)) NTime::UnixTimeToFileTime(unixTime, utc); else { @@ -328,7 +331,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val if (item.Comment.Size() != 0) { UString res; - item.GetUnicodeString(BytesToString(item.Comment), res, _forceCodePage, _specifiedCodePage); + item.GetUnicodeString(res, BytesToString(item.Comment), true, _forceCodePage, _specifiedCodePage); prop = res; } break; @@ -347,7 +350,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { m += kMethod_AES; CWzAesExtra aesField; - if (item.CentralExtra.GetWzAes(aesField)) + if (extra.GetWzAes(aesField)) { char s[16]; s[0] = '-'; @@ -360,7 +363,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val { CStrongCryptoExtra f; f.AlgId = 0; - if (item.CentralExtra.GetStrongCrypto(f)) + if (extra.GetStrongCrypto(f)) { const char *s = FindNameForId(k_StrongCryptoPairs, ARRAY_SIZE(k_StrongCryptoPairs), f.AlgId); if (s) @@ -427,6 +430,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val prop = (UInt32)item.ExtractVersion.Version; break; } + prop.Detach(value); return S_OK; COM_TRY_END @@ -617,7 +621,7 @@ HRESULT CZipDecoder::Decode( if (!pkAesMode && id == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtra aesField; - if (item.CentralExtra.GetWzAes(aesField)) + if (item.GetMainExtra().GetWzAes(aesField)) { wzAesMode = true; needCRC = aesField.NeedCrc(); @@ -653,7 +657,7 @@ HRESULT CZipDecoder::Decode( if (wzAesMode) { CWzAesExtra aesField; - if (!item.CentralExtra.GetWzAes(aesField)) + if (!item.GetMainExtra().GetWzAes(aesField)) return S_OK; id = aesField.Method; if (!_wzAesDecoder) diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h index 18ba064a..82e46eb6 100644 --- a/CPP/7zip/Archive/Zip/ZipHeader.h +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -84,6 +84,8 @@ namespace NFileHeader kNTFS = 0x0A, kStrongEncrypt = 0x17, kUnixTime = 0x5455, + kIzUnicodeComment = 0x6375, + kIzUnicodeName = 0x7075, kWzAES = 0x9901 }; } diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 77ca89ea..2ba7e3fa 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -203,7 +203,8 @@ API_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size) const Byte *p2 = p + kLocalHeaderSize; for (size_t i = 0; i < rem; i++) if (p2[i] == 0) - return k_IsArc_Res_NO; + if (i != nameSize - 1) + return k_IsArc_Res_NO; } if (size < extraOffset) diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp index 9e1f5e00..e732df7c 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.cpp +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -3,8 +3,10 @@ #include "StdAfx.h" #include "../../../../C/CpuArch.h" +#include "../../../../C/7zCrc.h" #include "../../../Common/MyLinux.h" +#include "../../../Common/StringConvert.h" #include "../Common/ItemNameUtils.h" @@ -80,6 +82,30 @@ bool CExtraSubBlock::ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res return false; } + +bool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const +{ + FOR_VECTOR (i, SubBlocks) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kNTFS) + return sb.ExtractNtfsTime(index, ft); + } + return false; +} + +bool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const +{ + FOR_VECTOR (i, SubBlocks) + { + const CExtraSubBlock &sb = SubBlocks[i]; + if (sb.ID == NFileHeader::NExtraID::kUnixTime) + return sb.ExtractUnixTime(isCentral, index, res); + } + return false; +} + + bool CLocalItem::IsDir() const { return NItemName::HasTailSlash(Name, GetCodePage()); @@ -89,12 +115,29 @@ bool CItem::IsDir() const { if (NItemName::HasTailSlash(Name, GetCodePage())) return true; + + Byte hostOS = GetHostOS(); + + if (Size == 0 && PackSize == 0 && !Name.IsEmpty() && Name.Back() == '\\') + { + // do we need to use CharPrevExA? + // .NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers? + // so we support that case + switch (hostOS) + { + case NHostOS::kFAT: + case NHostOS::kNTFS: + case NHostOS::kHPFS: + case NHostOS::kVFAT: + return true; + } + } + if (!FromCentral) return false; UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF); - Byte hostOS = GetHostOS(); switch (hostOS) { case NHostOS::kAMIGA: @@ -158,4 +201,53 @@ bool CItem::GetPosixAttrib(UInt32 &attrib) const return false; } +void CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const +{ + bool isUtf8 = IsUtf8(); + bool ignore_Utf8_Errors = true; + + if (!isUtf8) + { + { + const unsigned id = isComment ? + NFileHeader::NExtraID::kIzUnicodeComment: + NFileHeader::NExtraID::kIzUnicodeName; + const CObjectVector<CExtraSubBlock> &subBlocks = GetMainExtra().SubBlocks; + + FOR_VECTOR (i, subBlocks) + { + const CExtraSubBlock &sb = subBlocks[i]; + if (sb.ID == id) + { + AString utf; + if (sb.ExtractIzUnicode(CrcCalc(s, s.Len()), utf)) + if (ConvertUTF8ToUnicode(utf, res)) + return; + break; + } + } + } + + if (useSpecifiedCodePage) + isUtf8 = (codePage == CP_UTF8); + #ifdef _WIN32 + else if (GetHostOS() == NFileHeader::NHostOS::kUnix) + { + /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header. + We try to get name as UTF-8. + Do we need to do it in POSIX version also? */ + isUtf8 = true; + ignore_Utf8_Errors = false; + } + #endif + } + + + if (isUtf8) + if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors) + return; + + MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); +} + }} diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h index c01ede8d..5f078b60 100644 --- a/CPP/7zip/Archive/Zip/ZipItem.h +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -7,7 +7,6 @@ #include "../../../Common/MyBuffer.h" #include "../../../Common/MyString.h" -#include "../../../Common/StringConvert.h" #include "../../../Common/UTFConvert.h" #include "ZipHeader.h" @@ -28,6 +27,23 @@ struct CExtraSubBlock bool ExtractNtfsTime(unsigned index, FILETIME &ft) const; bool ExtractUnixTime(bool isCentral, unsigned index, UInt32 &res) const; + + bool ExtractIzUnicode(UInt32 crc, AString &name) const + { + unsigned size = (unsigned)Data.Size(); + if (size < 1 + 4) + return false; + const Byte *p = (const Byte *)Data; + if (p[0] > 1) + return false; + if (crc != GetUi32(p + 1)) + return false; + size -= 5; + name.SetFrom_CalcLen((const char *)p + 5, size); + if (size != name.Len()) + return false; + return CheckUTF8(name, false); + } }; const unsigned k_WzAesExtra_Size = 7; @@ -157,27 +173,8 @@ struct CExtraBlock } */ - bool GetNtfsTime(unsigned index, FILETIME &ft) const - { - FOR_VECTOR (i, SubBlocks) - { - const CExtraSubBlock &sb = SubBlocks[i]; - if (sb.ID == NFileHeader::NExtraID::kNTFS) - return sb.ExtractNtfsTime(index, ft); - } - return false; - } - - bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const - { - FOR_VECTOR (i, SubBlocks) - { - const CExtraSubBlock &sb = SubBlocks[i]; - if (sb.ID == NFileHeader::NExtraID::kUnixTime) - return sb.ExtractUnixTime(isCentral, index, res); - } - return false; - } + bool GetNtfsTime(unsigned index, FILETIME &ft) const; + bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const; void RemoveUnknownSubBlocks() { @@ -274,45 +271,22 @@ public: MadeByVersion.HostOS = 0; } + const CExtraBlock &GetMainExtra() const { return *(FromCentral ? &CentralExtra : &LocalExtra); } + bool IsDir() const; UInt32 GetWinAttrib() const; bool GetPosixAttrib(UInt32 &attrib) const; Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : ExtractVersion.HostOS; } - void GetUnicodeString(const AString &s, UString &res, bool useSpecifiedCodePage, UINT codePage) const - { - bool isUtf8 = IsUtf8(); - bool ignore_Utf8_Errors = true; - - #ifdef _WIN32 - if (!isUtf8) - { - if (useSpecifiedCodePage) - isUtf8 = (codePage == CP_UTF8); - else if (GetHostOS() == NFileHeader::NHostOS::kUnix) - { - /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header. - We try to get name as UTF-8. - Do we need to do it in POSIX version also? */ - isUtf8 = true; - ignore_Utf8_Errors = false; - } - } - #endif - - if (isUtf8) - if (ConvertUTF8ToUnicode(s, res) || ignore_Utf8_Errors) - return; - MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage()); - } + void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const; bool IsThereCrc() const { if (Method == NFileHeader::NCompressionMethod::kWzAES) { CWzAesExtra aesField; - if (CentralExtra.GetWzAes(aesField)) + if (GetMainExtra().GetWzAes(aesField)) return aesField.NeedCrc(); } return (Crc != 0 || !IsDir()); @@ -322,8 +296,10 @@ public: { Byte hostOS = GetHostOS(); return (UINT)(( - hostOS == NFileHeader::NHostOS::kFAT || - hostOS == NFileHeader::NHostOS::kNTFS) ? CP_OEMCP : CP_ACP); + hostOS == NFileHeader::NHostOS::kFAT + || hostOS == NFileHeader::NHostOS::kNTFS + || hostOS == NFileHeader::NHostOS::kUnix // do we need it? + ) ? CP_OEMCP : CP_ACP); } }; diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index 944feb4d..1f3d88d1 100644 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -325,14 +325,6 @@ SOURCE=..\..\UI\FileManager\ComboDialog.h # End Source File # Begin Source File -SOURCE=..\..\UI\FileManager\MessagesDialog.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\UI\FileManager\MessagesDialog.h -# End Source File -# Begin Source File - SOURCE=..\..\UI\FileManager\OverwriteDialog.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index f39cf162..1bd202ed 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp @@ -917,7 +917,7 @@ void CArcCmdLineParser::Parse1(const UStringVector &commandStrings, if (parser[NKey::kAffinity].ThereIs) { - const UString &s = us2fs(parser[NKey::kAffinity].PostStrings[0]); + const UString &s = parser[NKey::kAffinity].PostStrings[0]; if (!s.IsEmpty()) { UInt32 v = 0; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index fe9c3366..62da5e9f 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -1265,7 +1265,7 @@ if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode) CReparseAttr attr; if (!attr.Parse(data, data.Size())) { - RINOK(SendMessageError("Internal error for symbolic link file", _item.Path)); + RINOK(SendMessageError("Internal error for symbolic link file", us2fs(_item.Path))); // return E_FAIL; } else diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index f861f503..fb69b544 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp @@ -2487,7 +2487,7 @@ HRESULT Bench( #ifdef USE_WIN_FILE NFile::NIO::CInFile file; - if (!file.Open(property.Value)) + if (!file.Open(us2fs(property.Value))) return E_INVALIDARG; UInt64 len; if (!file.GetLength(len)) diff --git a/CPP/7zip/UI/Common/OpenArchive.cpp b/CPP/7zip/UI/Common/OpenArchive.cpp index a6afaf1c..e323abd2 100644 --- a/CPP/7zip/UI/Common/OpenArchive.cpp +++ b/CPP/7zip/UI/Common/OpenArchive.cpp @@ -39,7 +39,7 @@ #endif // increase it, if you need to support larger SFX stubs -static const UInt64 kMaxCheckStartPosition = 1 << 22; +static const UInt64 kMaxCheckStartPosition = 1 << 23; /* Open: diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 4c48bd70..74660186 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -42,6 +42,12 @@ static void Key_Get_BoolPair(CKey &key, LPCTSTR name, CBoolPair &b) b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); } +static void Key_Get_BoolPair_true(CKey &key, LPCTSTR name, CBoolPair &b) +{ + b.Val = true; + b.Def = (key.GetValue_IfOk(name, b.Val) == ERROR_SUCCESS); +} + namespace NExtract { @@ -112,9 +118,8 @@ void CInfo::Load() OverwriteMode_Force = true; } - Key_Get_BoolPair(key, kSplitDest, SplitDest); - if (!SplitDest.Def) - SplitDest.Val = true; + Key_Get_BoolPair_true(key, kSplitDest, SplitDest); + Key_Get_BoolPair(key, kElimDup, ElimDup); // Key_Get_BoolPair(key, kAltStreams, AltStreams); Key_Get_BoolPair(key, kNtSecur, NtSecurity); @@ -348,27 +353,45 @@ void CInfo::Load() static const TCHAR *kCascadedMenu = TEXT("CascadedMenu"); static const TCHAR *kContextMenu = TEXT("ContextMenu"); static const TCHAR *kMenuIcons = TEXT("MenuIcons"); +static const TCHAR *kElimDup = TEXT("ElimDupExtract"); void CContextMenuInfo::Save() const { CS_LOCK CKey key; CreateMainKey(key, kOptionsInfoKeyName); - key.SetValue(kCascadedMenu, Cascaded); - key.SetValue(kMenuIcons, MenuIcons); - key.SetValue(kContextMenu, Flags); + + Key_Set_BoolPair(key, kCascadedMenu, Cascaded); + Key_Set_BoolPair(key, kMenuIcons, MenuIcons); + Key_Set_BoolPair(key, kElimDup, ElimDup); + + if (Flags_Def) + key.SetValue(kContextMenu, Flags); } void CContextMenuInfo::Load() { - MenuIcons = false; - Cascaded = true; + Cascaded.Val = true; + Cascaded.Def = false; + + MenuIcons.Val = false; + MenuIcons.Def = false; + + ElimDup.Val = true; + ElimDup.Def = false; + Flags = (UInt32)(Int32)-1; + Flags_Def = false; + CS_LOCK + CKey key; if (OpenMainKey(key, kOptionsInfoKeyName) != ERROR_SUCCESS) return; - key.GetValue_IfOk(kCascadedMenu, Cascaded); - key.GetValue_IfOk(kMenuIcons, MenuIcons); - key.GetValue_IfOk(kContextMenu, Flags); + + Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded); + Key_Get_BoolPair_true(key, kElimDup, ElimDup); + Key_Get_BoolPair(key, kMenuIcons, MenuIcons); + + Flags_Def = (key.GetValue_IfOk(kContextMenu, Flags) == ERROR_SUCCESS); } diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index cd2ea67d..935f97bb 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -111,8 +111,11 @@ namespace NWorkDir struct CContextMenuInfo { - bool Cascaded; - bool MenuIcons; + CBoolPair Cascaded; + CBoolPair MenuIcons; + CBoolPair ElimDup; + + bool Flags_Def; UInt32 Flags; void Save() const; diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 68af4a1e..d94e28e6 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -241,7 +241,7 @@ static const CHashCommand g_HashCommands[] = static int FindCommand(CZipContextMenu::ECommandInternalID &id) { - for (int i = 0; i < ARRAY_SIZE(g_Commands); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_Commands); i++) if (g_Commands[i].CommandInternalID == id) return i; return -1; @@ -287,12 +287,10 @@ static const char * const kArcExts[] = , "zip" }; -static bool IsItArcExt(const UString &ext2) +static bool IsItArcExt(const UString &ext) { - UString ext = ext2; - ext.MakeLower_Ascii(); for (unsigned i = 0; i < ARRAY_SIZE(kArcExts); i++) - if (ext.IsEqualTo(kArcExts[i])) + if (ext.IsEqualTo_Ascii_NoCase(kArcExts[i])) return true; return false; } @@ -429,6 +427,7 @@ void CZipContextMenu::AddMapItem_ForSubMenu(const wchar_t *verb) _commandMap.Add(commandMapItem); } + STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT commandIDFirst, UINT commandIDLast, UINT flags) { @@ -451,12 +450,15 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, CContextMenuInfo ci; ci.Load(); + _elimDup = ci.ElimDup; + HBITMAP bitmap = NULL; - if (ci.MenuIcons) + if (ci.MenuIcons.Val) bitmap = _bitmap; UINT subIndex = indexMenu; - if (ci.Cascaded) + + if (ci.Cascaded.Val) { if (!popupMenu.CreatePopup()) return E_FAIL; @@ -473,15 +475,21 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, else { popupMenu.Attach(hMenu); + CMenuItem mi; + mi.fType = MFT_SEPARATOR; + mi.fMask = MIIM_TYPE; + popupMenu.InsertItem(subIndex++, true, mi); } UInt32 contextMenuFlags = ci.Flags; NFind::CFileInfo fi0; FString folderPrefix; + if (_fileNames.Size() > 0) { const UString &fileName = _fileNames.Front(); + #if defined(_WIN32) && !defined(UNDER_CE) if (NName::IsDevicePath(us2fs(fileName))) { @@ -505,6 +513,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, } UString mainString; + if (_fileNames.Size() == 1 && currentCommandID + 14 <= commandIDLast) { if (!fi0.IsDir() && DoNeedExtract(fi0.Name)) @@ -565,6 +574,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) { bool needExtract = (!fi0.IsDir() && DoNeedExtract(fi0.Name)); + if (!needExtract) { FOR_VECTOR (i, _fileNames) @@ -579,7 +589,9 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, } } } + const UString &fileName = _fileNames.Front(); + if (needExtract) { // Extract @@ -629,6 +641,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s, bitmap); _commandMap.Add(commandMapItem); } + // Test if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) { @@ -644,6 +657,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, arcName = CreateArchiveName(fi0, false); else arcName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); + UString arcName7z = arcName + L".7z"; UString arcNameZip = arcName + L".zip"; @@ -745,7 +759,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension // ID: Q214477 - if (ci.Cascaded) + if (ci.Cascaded.Val) { CMenuItem mi; mi.fType = MFT_STRING; @@ -756,12 +770,20 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.hSubMenu = popupMenu.Detach(); mi.StringValue.SetFromAscii("7-Zip"); // LangString(IDS_CONTEXT_POPUP_CAPTION); mi.hbmpUnchecked = bitmap; + CMenu menu; menu.Attach(hMenu); menuDestroyer.Disable(); menu.InsertItem(indexMenu++, true, mi); + AddMapItem_ForSubMenu(kMainVerb); } + else + { + popupMenu.Detach(); + indexMenu = subIndex; + } + if (!_isMenuForFM && ((contextMenuFlags & NContextMenuFlags::kCRC) != 0 @@ -771,6 +793,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, // CMenuDestroyer menuDestroyer_CRC; UINT subIndex_CRC = 0; + if (subMenu.CreatePopup()) { // menuDestroyer_CRC.Attach(subMenu); @@ -783,13 +806,15 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, mi.hSubMenu = subMenu; mi.StringValue.SetFromAscii("CRC SHA"); mi.hbmpUnchecked = bitmap; + CMenu menu; menu.Attach(hMenu); // menuDestroyer_CRC.Disable(); menu.InsertItem(indexMenu++, true, mi); + AddMapItem_ForSubMenu(kCheckSumCascadedVerb); - for (int i = 0; i < ARRAY_SIZE(g_HashCommands); i++) + for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++) { const CHashCommand &hc = g_HashCommands[i]; CCommandMapItem commandMapItem; @@ -799,6 +824,7 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, MyInsertMenu(subMenu, subIndex_CRC++, currentCommandID++, hc.UserName, bitmap); _commandMap.Add(commandMapItem); } + subMenu.Detach(); } } @@ -872,7 +898,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) { ExtractArchives(_fileNames, commandMapItem.Folder, (cmdID == kExtract), // showDialog - (cmdID == kExtractTo) // elimDup + (cmdID == kExtractTo) && _elimDup.Val // elimDup ); break; } @@ -902,12 +928,14 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) _fileNames, email, showDialog, false); break; } + case kHash_CRC32: case kHash_CRC64: case kHash_SHA1: case kHash_SHA256: case kHash_All: - for (int i = 0; i < ARRAY_SIZE(g_HashCommands); i++) + { + for (unsigned i = 0; i < ARRAY_SIZE(g_HashCommands); i++) { const CHashCommand &hc = g_HashCommands[i]; if (hc.CommandInternalID == cmdID) @@ -917,6 +945,7 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo) } } break; + } } } catch(...) diff --git a/CPP/7zip/UI/Explorer/ContextMenu.h b/CPP/7zip/UI/Explorer/ContextMenu.h index 90ca0e64..53bf18de 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.h +++ b/CPP/7zip/UI/Explorer/ContextMenu.h @@ -74,6 +74,8 @@ private: HBITMAP _bitmap; + CBoolPair _elimDup; + HRESULT GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames); int FindVerb(const UString &verb); bool FillCommand(ECommandInternalID id, UString &mainString, CCommandMapItem &commandMapItem); diff --git a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp index 3b04e7be..d02af9ef 100644 --- a/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp +++ b/CPP/7zip/UI/Explorer/DllExportsExplorer.cpp @@ -10,13 +10,11 @@ #include "../../../Common/MyWindows.h" -#include <ShlGuid.h> #include <OleCtl.h> #include "../../../Common/MyInitGuid.h" #include "../../../Common/ComTry.h" -#include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" #include "../../../Windows/ErrorMsg.h" @@ -24,11 +22,15 @@ #include "../../../Windows/Registry.h" #include "../FileManager/IFolder.h" -#include "../FileManager/LangUtils.h" #include "ContextMenu.h" +static LPCTSTR k_ShellExtName = TEXT("7-Zip Shell Extension"); +static LPCTSTR k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); + // {23170F69-40C1-278A-1000-000100020000} +static LPCTSTR k_Clsid = TEXT("{23170F69-40C1-278A-1000-000100020000}"); + DEFINE_GUID(CLSID_CZipContextMenu, k_7zip_GUID_Data1, k_7zip_GUID_Data2, @@ -42,10 +44,6 @@ HWND g_HWND = 0; LONG g_DllRefCount = 0; // Reference count of this DLL. -static LPCWSTR kShellExtName = L"7-Zip Shell Extension"; -static LPCTSTR kClsidMask = TEXT("CLSID\\%s"); -static LPCTSTR kClsidInprocMask = TEXT("CLSID\\%s\\InprocServer32"); -static LPCTSTR kApprovedKeyPath = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); // #define ODS(sz) OutputDebugString(L#sz) @@ -77,7 +75,7 @@ STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, shellExt = new CZipContextMenu(); } catch(...) { return E_OUTOFMEMORY; } - if (shellExt == NULL) + if (!shellExt) return E_OUTOFMEMORY; HRESULT res = shellExt->QueryInterface(riid, ppvObj); @@ -117,7 +115,7 @@ BOOL WINAPI DllMain( return TRUE; } -///////////////////////////////////////////////////////////////////////////// + // Used to determine whether the DLL can be unloaded by OLE STDAPI DllCanUnloadNow(void) @@ -138,7 +136,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) cf = new CShellExtClassFactory; } catch(...) { return E_OUTOFMEMORY; } - if (cf == 0) + if (!cf) return E_OUTOFMEMORY; HRESULT res = cf->QueryInterface(riid, ppv); if (res != S_OK) @@ -149,66 +147,28 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) // return _Module.GetClassObject(rclsid, riid, ppv); } -static BOOL GetStringFromIID(CLSID clsid, LPTSTR s, int size) -{ - LPWSTR pwsz; - if (StringFromIID(clsid, &pwsz) != S_OK) - return FALSE; - if (!pwsz) - return FALSE; - #ifdef UNICODE - for (int i = 0; i < size; i++) - { - s[i] = pwsz[i]; - if (pwsz[i] == 0) - break; - } - s[size - 1] = 0; - #else - WideCharToMultiByte(CP_ACP, 0, pwsz, -1, s, size, NULL, NULL); - #endif - CoTaskMemFree(pwsz); - s[size - 1] = 0; - return TRUE; -} - -typedef struct -{ - HKEY hRootKey; - LPCTSTR SubKey; - LPCWSTR ValueName; - LPCWSTR Data; -} CRegItem; -static BOOL RegisterServer(CLSID clsid, LPCWSTR title) +static BOOL RegisterServer() { - TCHAR clsidString[MAX_PATH]; - if (!GetStringFromIID(clsid, clsidString, MAX_PATH)) - return FALSE; - FString modulePath; if (!NDLL::MyGetModuleFileName(modulePath)) return FALSE; - UString modulePathU = fs2us(modulePath); + const UString modulePathU = fs2us(modulePath); - CRegItem clsidEntries[] = - { - HKEY_CLASSES_ROOT, kClsidMask, NULL, title, - HKEY_CLASSES_ROOT, kClsidInprocMask, NULL, modulePathU, - HKEY_CLASSES_ROOT, kClsidInprocMask, L"ThreadingModel", L"Apartment", - NULL, NULL, NULL, NULL - }; + CSysString clsidString = k_Clsid; + CSysString s = TEXT("CLSID\\"); + s += clsidString; - //register the CLSID entries - for (int i = 0; clsidEntries[i].hRootKey; i++) { - TCHAR subKey[MAX_PATH]; - const CRegItem &r = clsidEntries[i]; - wsprintf(subKey, r.SubKey, clsidString); NRegistry::CKey key; - if (key.Create(r.hRootKey, subKey, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR) + if (key.Create(HKEY_CLASSES_ROOT, s, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR) return FALSE; - key.SetValue(clsidEntries[i].ValueName, clsidEntries[i].Data); + key.SetValue(NULL, k_ShellExtName); + NRegistry::CKey keyInproc; + if (keyInproc.Create(key, TEXT("InprocServer32"), NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) != NOERROR) + return FALSE; + keyInproc.SetValue(NULL, modulePathU); + keyInproc.SetValue(TEXT("ThreadingModel"), TEXT("Apartment")); } #if !defined(_WIN64) && !defined(UNDER_CE) @@ -216,46 +176,45 @@ static BOOL RegisterServer(CLSID clsid, LPCWSTR title) #endif { NRegistry::CKey key; - if (key.Create(HKEY_LOCAL_MACHINE, kApprovedKeyPath, NULL, - REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR) - key.SetValue(GetUnicodeString(clsidString), title); + if (key.Create(HKEY_LOCAL_MACHINE, k_Approved, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE) == NOERROR) + key.SetValue(clsidString, k_ShellExtName); } + return TRUE; } STDAPI DllRegisterServer(void) { - return RegisterServer(CLSID_CZipContextMenu, kShellExtName) ? S_OK: SELFREG_E_CLASS; + return RegisterServer() ? S_OK: SELFREG_E_CLASS; } -static BOOL UnregisterServer(CLSID clsid) +static BOOL UnregisterServer() { - TCHAR clsidString[MAX_PATH]; - if (!GetStringFromIID(clsid, clsidString, MAX_PATH)) - return FALSE; + const CSysString clsidString = k_Clsid; + CSysString s = TEXT("CLSID\\"); + s += clsidString; + CSysString s2 = s; + s2.AddAscii("\\InprocServer32"); - TCHAR subKey[MAX_PATH]; - wsprintf(subKey, kClsidInprocMask, clsidString); - RegDeleteKey(HKEY_CLASSES_ROOT, subKey); - - wsprintf (subKey, kClsidMask, clsidString); - RegDeleteKey(HKEY_CLASSES_ROOT, subKey); + RegDeleteKey(HKEY_CLASSES_ROOT, s2); + RegDeleteKey(HKEY_CLASSES_ROOT, s); #if !defined(_WIN64) && !defined(UNDER_CE) if (IsItWindowsNT()) #endif { HKEY hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, kApprovedKeyPath, 0, KEY_SET_VALUE, &hKey) == NOERROR) + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, k_Approved, 0, KEY_SET_VALUE, &hKey) == NOERROR) { RegDeleteValue(hKey, clsidString); RegCloseKey(hKey); } } + return TRUE; } STDAPI DllUnregisterServer(void) { - return UnregisterServer(CLSID_CZipContextMenu) ? S_OK: SELFREG_E_CLASS; + return UnregisterServer() ? S_OK: SELFREG_E_CLASS; } diff --git a/CPP/7zip/UI/Explorer/Explorer.dsp b/CPP/7zip/UI/Explorer/Explorer.dsp index 84e2a6a4..2a6166ee 100644 --- a/CPP/7zip/UI/Explorer/Explorer.dsp +++ b/CPP/7zip/UI/Explorer/Explorer.dsp @@ -538,13 +538,5 @@ SOURCE=".\7-zip.dll.manifest" SOURCE=.\ContextMenuFlags.h # End Source File -# Begin Source File - -SOURCE=.\RegistryContextMenu.cpp -# End Source File -# Begin Source File - -SOURCE=.\RegistryContextMenu.h -# End Source File # End Target # End Project diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp index da6ecf38..d0c9189d 100644 --- a/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.cpp @@ -2,114 +2,218 @@ #include "StdAfx.h" +#include "../../../Common/StringConvert.h" + #include "../../../Windows/Registry.h" -#include "../../../Windows/Synchronization.h" #include "RegistryContextMenu.h" using namespace NWindows; using namespace NRegistry; -namespace NZipRootRegistry { - #ifndef UNDER_CE -static NSynchronization::CCriticalSection g_CS; - -static const TCHAR *kContextMenuKeyName = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); -static const TCHAR *kDragDropMenuKeyName = TEXT("\\shellex\\DragDropHandlers\\7-Zip"); +// does extension can work, if Approved is removed ? +// CLISID (and Approved ?) items are separated for 32-bit and 64-bit code. +// shellex items shared by 32-bit and 64-bit code? -static const TCHAR *kExtensionCLSID = TEXT("{23170F69-40C1-278A-1000-000100020000}"); +static LPCTSTR k_Clsid = TEXT("{23170F69-40C1-278A-1000-000100020000}"); +static LPCTSTR k_ShellExtName = TEXT("7-Zip Shell Extension"); -static const TCHAR *kRootKeyNameForFile = TEXT("*"); -static const TCHAR *kRootKeyNameForFolder = TEXT("Folder"); -static const TCHAR *kRootKeyNameForDirectory = TEXT("Directory"); -static const TCHAR *kRootKeyNameForDrive = TEXT("Drive"); +static LPCTSTR k_Approved = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"); +static LPCTSTR k_Inproc = TEXT("InprocServer32"); -static CSysString GetFullContextMenuKeyName(const CSysString &keyName) - { return (keyName + kContextMenuKeyName); } +static LPCTSTR k_KeyPostfix_ContextMenu = TEXT("\\shellex\\ContextMenuHandlers\\7-Zip"); +static LPCTSTR k_KeyPostfix_DragDrop = TEXT("\\shellex\\DragDropHandlers\\7-Zip"); -static CSysString GetFullDragDropMenuKeyName(const CSysString &keyName) - { return (keyName + kDragDropMenuKeyName); } +static LPCTSTR k_KeyName_File = TEXT("*"); +static LPCTSTR k_KeyName_Folder = TEXT("Folder"); +static LPCTSTR k_KeyName_Directory = TEXT("Directory"); +static LPCTSTR k_KeyName_Drive = TEXT("Drive"); -static bool CheckHandlerCommon(const CSysString &keyName) +static LPCTSTR const k_shellex_Prefixes[] = { - NSynchronization::CCriticalSectionLock lock(g_CS); - CKey key; - if (key.Open(HKEY_CLASSES_ROOT, keyName, KEY_READ) != ERROR_SUCCESS) - return false; - CSysString value; - if (key.QueryValue(NULL, value) != ERROR_SUCCESS) - return false; - return StringsAreEqualNoCase_Ascii(value, kExtensionCLSID); -} + k_KeyName_File, + k_KeyName_Folder, + k_KeyName_Directory, + k_KeyName_Drive +}; -bool CheckContextMenuHandler() +static const bool k_shellex_Statuses[2][4] = { - return - // CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFolder)) && - CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForDirectory)) && - CheckHandlerCommon(GetFullContextMenuKeyName(kRootKeyNameForFile)) && - CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDirectory)) && - CheckHandlerCommon(GetFullDragDropMenuKeyName(kRootKeyNameForDrive)); -} + { true, true, true, false }, + { false, false, true, true } +}; + + +// can we use static RegDeleteKeyExW in _WIN64 mode? +// is it supported by Windows 2003 x64? + +/* +#ifdef _WIN64 + +#define INIT_REG_WOW -static void DeleteContextMenuHandlerCommon(const CSysString &keyName) +#else +*/ + +typedef WINADVAPI LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); +static Func_RegDeleteKeyExW func_RegDeleteKeyExW; + +static void Init_RegDeleteKeyExW() { - CKey rootKey; - rootKey.Attach(HKEY_CLASSES_ROOT); - rootKey.RecurseDeleteKey(GetFullContextMenuKeyName(keyName)); - rootKey.Detach(); + if (!func_RegDeleteKeyExW) + func_RegDeleteKeyExW = (Func_RegDeleteKeyExW) + GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW"); } -static void DeleteDragDropMenuHandlerCommon(const CSysString &keyName) +#define INIT_REG_WOW if (wow != 0) Init_RegDeleteKeyExW(); + +// #endif + +static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCTSTR name, UInt32 wow) { - CKey rootKey; - rootKey.Attach(HKEY_CLASSES_ROOT); - rootKey.RecurseDeleteKey(GetFullDragDropMenuKeyName(keyName)); - rootKey.Detach(); + if (wow == 0) + return RegDeleteKey(parentKey, name); + + /* + #ifdef _WIN64 + return RegDeleteKeyExW + #else + */ + if (!func_RegDeleteKeyExW) + return E_NOTIMPL; + return func_RegDeleteKeyExW + // #endif + (parentKey, GetUnicodeString(name), wow, 0); } -void DeleteContextMenuHandler() +static LONG MyRegistry_DeleteKey_HKCR(LPCTSTR name, UInt32 wow) { - DeleteContextMenuHandlerCommon(kRootKeyNameForFile); - DeleteContextMenuHandlerCommon(kRootKeyNameForFolder); - DeleteContextMenuHandlerCommon(kRootKeyNameForDirectory); - DeleteContextMenuHandlerCommon(kRootKeyNameForDrive); - DeleteDragDropMenuHandlerCommon(kRootKeyNameForFile); - DeleteDragDropMenuHandlerCommon(kRootKeyNameForFolder); - DeleteDragDropMenuHandlerCommon(kRootKeyNameForDirectory); - DeleteDragDropMenuHandlerCommon(kRootKeyNameForDrive); + return MyRegistry_DeleteKey(HKEY_CLASSES_ROOT, name, wow); } -static void AddContextMenuHandlerCommon(const CSysString &keyName) +// static NSynchronization::CCriticalSection g_CS; + +static CSysString Get_ContextMenuHandler_KeyName(const CSysString &keyName) + { return (keyName + k_KeyPostfix_ContextMenu); } + +/* +static CSysString Get_DragDropHandler_KeyName(const CSysString &keyName) + { return (keyName + k_KeyPostfix_DragDrop); } +*/ + +static bool CheckHandlerCommon(const CSysString &keyName, UInt32 wow) { - DeleteContextMenuHandlerCommon(keyName); - NSynchronization::CCriticalSectionLock lock(g_CS); CKey key; - key.Create(HKEY_CLASSES_ROOT, GetFullContextMenuKeyName(keyName)); - key.SetValue(NULL, kExtensionCLSID); + if (key.Open(HKEY_CLASSES_ROOT, keyName, KEY_READ | wow) != ERROR_SUCCESS) + return false; + CSysString value; + if (key.QueryValue(NULL, value) != ERROR_SUCCESS) + return false; + return StringsAreEqualNoCase_Ascii(value, k_Clsid); } -static void AddDragDropMenuHandlerCommon(const CSysString &keyName) +bool CheckContextMenuHandler(const UString &path, UInt32 wow) { - DeleteDragDropMenuHandlerCommon(keyName); - NSynchronization::CCriticalSectionLock lock(g_CS); - CKey key; - key.Create(HKEY_CLASSES_ROOT, GetFullDragDropMenuKeyName(keyName)); - key.SetValue(NULL, kExtensionCLSID); + // NSynchronization::CCriticalSectionLock lock(g_CS); + + CSysString s = TEXT("CLSID\\"); + s += k_Clsid; + s.AddAscii("\\InprocServer32"); + + { + NRegistry::CKey key; + if (key.Open(HKEY_CLASSES_ROOT, s, KEY_READ | wow) != ERROR_SUCCESS) + return false; + UString regPath; + if (key.QueryValue(NULL, regPath) != ERROR_SUCCESS) + return false; + if (!path.IsEqualTo_NoCase(regPath)) + return false; + } + + return + CheckHandlerCommon(Get_ContextMenuHandler_KeyName(k_KeyName_File), wow); + /* + && CheckHandlerCommon(Get_ContextMenuHandler_KeyName(k_KeyName_Directory), wow) + // && CheckHandlerCommon(Get_ContextMenuHandler_KeyName(k_KeyName_Folder)) + + && CheckHandlerCommon(Get_DragDropHandler_KeyName(k_KeyName_Directory), wow) + && CheckHandlerCommon(Get_DragDropHandler_KeyName(k_KeyName_Drive), wow); + */ } -void AddContextMenuHandler() + +static LONG MyCreateKey(CKey &key, HKEY parentKey, LPCTSTR keyName, UInt32 wow) { - AddContextMenuHandlerCommon(kRootKeyNameForFile); - // AddContextMenuHandlerCommon(kRootKeyNameForFolder); - AddContextMenuHandlerCommon(kRootKeyNameForDirectory); + return key.Create(parentKey, keyName, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | wow); +} - AddDragDropMenuHandlerCommon(kRootKeyNameForDirectory); - AddDragDropMenuHandlerCommon(kRootKeyNameForDrive); +LONG SetContextMenuHandler(bool setMode, const UString &path, UInt32 wow) +{ + // NSynchronization::CCriticalSectionLock lock(g_CS); + + INIT_REG_WOW + + CSysString s = TEXT("CLSID\\"); + s += k_Clsid; + + LONG res; + if (setMode) + { + { + CKey key; + res = MyCreateKey(key, HKEY_CLASSES_ROOT, s, wow); + if (res == ERROR_SUCCESS) + { + key.SetValue(NULL, k_ShellExtName); + CKey keyInproc; + res = MyCreateKey(keyInproc, key, k_Inproc, wow); + if (res == ERROR_SUCCESS) + { + res = keyInproc.SetValue(NULL, path); + keyInproc.SetValue(TEXT("ThreadingModel"), TEXT("Apartment")); + } + } + } + + { + CKey key; + if (MyCreateKey(key, HKEY_LOCAL_MACHINE, k_Approved, wow) == ERROR_SUCCESS) + key.SetValue(k_Clsid, k_ShellExtName); + } + } + else + { + CSysString s2 = s; + s2.AddAscii("\\InprocServer32"); + + MyRegistry_DeleteKey_HKCR(s2, wow); + res = MyRegistry_DeleteKey_HKCR(s, wow); + } + + // shellex items probably are shared beween 32-bit and 64-bit apps. So we don't delete items for delete operation. + if (setMode) + for (unsigned i = 0; i < 2; i++) + { + for (unsigned k = 0; k < ARRAY_SIZE(k_shellex_Prefixes); k++) + { + CSysString s = k_shellex_Prefixes[k]; + s += (i == 0 ? k_KeyPostfix_ContextMenu : k_KeyPostfix_DragDrop); + if (k_shellex_Statuses[i][k]) + { + CKey key; + MyCreateKey(key, HKEY_CLASSES_ROOT, s, wow); + key.SetValue(NULL, k_Clsid); + } + else + MyRegistry_DeleteKey_HKCR(s, wow); + } + } + + return res; } #endif - -} diff --git a/CPP/7zip/UI/Explorer/RegistryContextMenu.h b/CPP/7zip/UI/Explorer/RegistryContextMenu.h index 139526a8..8c2acc42 100644 --- a/CPP/7zip/UI/Explorer/RegistryContextMenu.h +++ b/CPP/7zip/UI/Explorer/RegistryContextMenu.h @@ -3,14 +3,11 @@ #ifndef __REGISTRY_CONTEXT_MENU_H #define __REGISTRY_CONTEXT_MENU_H -namespace NZipRootRegistry { - #ifndef UNDER_CE - bool CheckContextMenuHandler(); - void AddContextMenuHandler(); - void DeleteContextMenuHandler(); -#endif -} +bool CheckContextMenuHandler(const UString &path, UInt32 wow = 0); +LONG SetContextMenuHandler(bool setMode, const UString &path, UInt32 wow = 0); + +#endif #endif diff --git a/CPP/7zip/UI/Explorer/makefile b/CPP/7zip/UI/Explorer/makefile index 02a4cd6f..1c8639be 100644 --- a/CPP/7zip/UI/Explorer/makefile +++ b/CPP/7zip/UI/Explorer/makefile @@ -14,7 +14,6 @@ EXPLORER_OBJS = \ $O\DllExportsExplorer.obj \ $O\ContextMenu.obj \ $O\MyMessages.obj \ - $O\RegistryContextMenu.obj \ COMMON_OBJS = \ $O\IntToString.obj \ diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index 1875a189..cc058ef9 100644 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -448,7 +448,7 @@ int PrintErrorMessage(const char *message, const char *text) } -static void ReduceString(UString &s, unsigned size) +void ReduceString(UString &s, unsigned size) { if (s.Len() > size) { diff --git a/CPP/7zip/UI/Far/FarUtils.h b/CPP/7zip/UI/Far/FarUtils.h index edec4cf9..5617c6c8 100644 --- a/CPP/7zip/UI/Far/FarUtils.h +++ b/CPP/7zip/UI/Far/FarUtils.h @@ -190,6 +190,8 @@ int ShowLastErrorMessage(); bool WasEscPressed(); +void ReduceString(UString &s, unsigned size); + } #endif diff --git a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp index a7fb495e..e950f695 100644 --- a/CPP/7zip/UI/Far/OverwriteDialogFar.cpp +++ b/CPP/7zip/UI/Far/OverwriteDialogFar.cpp @@ -68,8 +68,17 @@ NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInf SetFileInfoStrings(oldFileInfo, oldFileInfoStrings); SetFileInfoStrings(newFileInfo, newFileInfoStrings); - AString oldName = UnicodeStringToMultiByte(oldFileInfo.Name, CP_OEMCP); - AString newName = UnicodeStringToMultiByte(newFileInfo.Name, CP_OEMCP); + UString oldName2 = oldFileInfo.Name; + UString newName2 = newFileInfo.Name; + + { + const unsigned maxNameLen = kXSize - 9 - 2; + ReduceString(oldName2, maxNameLen); + ReduceString(newName2, maxNameLen); + } + + AString oldName = UnicodeStringToMultiByte(oldName2); + AString newName = UnicodeStringToMultiByte(newName2); struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL }, diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index b6a66975..a262029f 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -72,17 +72,18 @@ void CApp::ReloadLang() void CApp::SetListSettings() { - bool showDots = ReadShowDots(); - bool showRealFileIcons = ReadShowRealFileIcons(); + CFmSettings st; + st.Load(); + + ShowSystemMenu = st.ShowSystemMenu; DWORD extendedStyle = LVS_EX_HEADERDRAGDROP; - if (ReadFullRow()) + if (st.FullRow) extendedStyle |= LVS_EX_FULLROWSELECT; - if (ReadShowGrid()) + if (st.ShowGrid) extendedStyle |= LVS_EX_GRIDLINES; - bool mySelectionMode = ReadAlternativeSelection(); - if (ReadSingleClick()) + if (st.SingleClick) { extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT; /* @@ -91,16 +92,16 @@ void CApp::SetListSettings() */ } - for (int i = 0; i < kNumPanelsMax; i++) + for (unsigned i = 0; i < kNumPanelsMax; i++) { CPanel &panel = Panels[i]; - panel._mySelectMode = mySelectionMode; - panel._showDots = showDots; - panel._showRealFileIcons = showRealFileIcons; + panel._mySelectMode = st.AlternativeSelection; + panel._showDots = st.ShowDots; + panel._showRealFileIcons = st.ShowRealFileIcons; panel._exStyle = extendedStyle; DWORD style = (DWORD)panel._listView.GetStyle(); - if (mySelectionMode) + if (st.AlternativeSelection) style |= LVS_SINGLESEL; else style &= ~LVS_SINGLESEL; @@ -109,11 +110,6 @@ void CApp::SetListSettings() } } -void CApp::SetShowSystemMenu() -{ - ShowSystemMenu = Read_ShowSystemMenu(); -} - #ifndef ILC_COLOR32 #define ILC_COLOR32 0x0020 #endif @@ -179,7 +175,7 @@ struct CButtonInfo UString GetText() const { return LangString(StringResID); } }; -static CButtonInfo g_StandardButtons[] = +static const CButtonInfo g_StandardButtons[] = { { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY }, { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE }, @@ -187,16 +183,16 @@ static CButtonInfo g_StandardButtons[] = { IDM_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO } }; -static CButtonInfo g_ArchiveButtons[] = +static const CButtonInfo g_ArchiveButtons[] = { { kMenuCmdID_Toolbar_Add, IDB_ADD, IDB_ADD2, IDS_ADD }, { kMenuCmdID_Toolbar_Extract, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT }, { kMenuCmdID_Toolbar_Test, IDB_TEST, IDB_TEST2, IDS_TEST } }; -static bool SetButtonText(int commandID, CButtonInfo *buttons, int numButtons, UString &s) +static bool SetButtonText(int commandID, const CButtonInfo *buttons, unsigned numButtons, UString &s) { - for (int i = 0; i < numButtons; i++) + for (unsigned i = 0; i < numButtons; i++) { const CButtonInfo &b = buttons[i]; if (b.CommandID == commandID) @@ -218,7 +214,7 @@ static void SetButtonText(int commandID, UString &s) static void AddButton( NControl::CImageList &imageList, NControl::CToolBar &toolBar, - CButtonInfo &butInfo, bool showText, bool large) + const CButtonInfo &butInfo, bool showText, bool large) { TBBUTTON but; but.iBitmap = 0; @@ -258,7 +254,7 @@ void CApp::ReloadToolbars() if (ShowArchiveToolbar || ShowStandardToolbar) { CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons); - int i; + unsigned i; if (ShowArchiveToolbar) for (i = 0; i < ARRAY_SIZE(g_ArchiveButtons); i++) AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons); @@ -282,10 +278,13 @@ void MyLoadMenu(); HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool &archiveIsOpened, bool &encrypted) { _window.Attach(hwnd); + #ifdef UNDER_CE _commandBar.Create(g_hInstance, hwnd, 1); #endif + MyLoadMenu(); + #ifdef UNDER_CE _commandBar.AutoSize(); #endif @@ -298,14 +297,16 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma PanelsCreated[i] = false; AppState.Read(); + SetListSettings(); - SetShowSystemMenu(); + if (LastFocusedPanel >= kNumPanelsMax) LastFocusedPanel = 0; // ShowDeletedFiles = Read_ShowDeleted(); CListMode listMode; listMode.Read(); + for (i = 0; i < kNumPanelsMax; i++) { CPanel &panel = Panels[i]; @@ -313,6 +314,7 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma panel._xSize = xSizes[i]; panel._flatModeForArc = ReadFlatView(i); } + for (i = 0; i < kNumPanelsMax; i++) if (NumPanels > 1 || i == LastFocusedPanel) { @@ -328,6 +330,7 @@ HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcForma encrypted = encrypted2; } } + SetFocusedPanel(LastFocusedPanel); Panels[LastFocusedPanel].SetFocusToList(); return S_OK; @@ -357,7 +360,8 @@ void CApp::Save() { AppState.Save(); CListMode listMode; - for (int i = 0; i < kNumPanelsMax; i++) + + for (unsigned i = 0; i < kNumPanelsMax; i++) { const CPanel &panel = Panels[i]; UString path; @@ -370,6 +374,7 @@ void CApp::Save() listMode.Panels[i] = panel.GetListViewMode(); SaveFlatView(i, panel._flatModeForArc); } + listMode.Save(); // Save_ShowDeleted(ShowDeletedFiles); } @@ -377,7 +382,7 @@ void CApp::Save() void CApp::Release() { // It's for unloading COM dll's: don't change it. - for (int i = 0; i < kNumPanelsMax; i++) + for (unsigned i = 0; i < kNumPanelsMax; i++) Panels[i].Release(); } @@ -467,6 +472,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices) UString info; UInt64 numDirs, numFiles, filesSize, foldersSize; numDirs = numFiles = filesSize = foldersSize = 0; + unsigned i; for (i = 0; i < indices.Size(); i++) { diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index 190864cb..dedbd821 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -258,7 +258,6 @@ public: */ void SetListSettings(); - void SetShowSystemMenu(); HRESULT SwitchOnOffOnePanel(); bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); } diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index 1c2f6374..066ac219 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -197,9 +197,11 @@ bool CBrowseDialog::OnInit() #endif #ifndef _SFX - if (ReadSingleClick()) + CFmSettings st; + st.Load(); + if (st.SingleClick) _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); - _showDots = ReadShowDots(); + _showDots = st.ShowDots; #endif { @@ -999,11 +1001,13 @@ bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result } #else + bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result) { result = path; return true; } + #endif bool Dlg_CreateFolder(HWND wnd, UString &destName) diff --git a/CPP/7zip/UI/FileManager/EditPage.cpp b/CPP/7zip/UI/FileManager/EditPage.cpp index 627088b9..b88c0f68 100644 --- a/CPP/7zip/UI/FileManager/EditPage.cpp +++ b/CPP/7zip/UI/FileManager/EditPage.cpp @@ -27,48 +27,50 @@ static LPCWSTR kEditTopic = L"FM/options.htm#editor"; bool CEditPage::OnInit() { + _initMode = true; + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon)); - _viewer.Attach(GetItem(IDE_EDIT_VIEWER)); - _editor.Attach(GetItem(IDE_EDIT_EDITOR)); - _diff.Attach(GetItem(IDE_EDIT_DIFF)); - - { - UString path; - ReadRegEditor(false, path); - _viewer.SetText(path); - } - { - UString path; - ReadRegEditor(true, path); - _editor.SetText(path); - } + _ctrls[0].Ctrl = IDE_EDIT_VIEWER; _ctrls[0].Button = IDB_EDIT_VIEWER; + _ctrls[1].Ctrl = IDE_EDIT_EDITOR; _ctrls[1].Button = IDB_EDIT_EDITOR; + _ctrls[2].Ctrl = IDE_EDIT_DIFF; _ctrls[2].Button = IDB_EDIT_DIFF; + + for (unsigned i = 0; i < 3; i++) { + CEditPageCtrl &c = _ctrls[i]; + c.WasChanged = false; + c.Edit.Attach(GetItem(c.Ctrl)); UString path; - ReadRegDiff(path); - _diff.SetText(path); + if (i < 2) + ReadRegEditor(i > 0, path); + else + ReadRegDiff(path); + c.Edit.SetText(path); } + + _initMode = false; + return CPropertyPage::OnInit(); } LONG CEditPage::OnApply() { + for (unsigned i = 0; i < 3; i++) { - UString path; - _viewer.GetText(path); - SaveRegEditor(false, path); - } - { - UString path; - _editor.GetText(path); - SaveRegEditor(true, path); - } - { - UString path; - _diff.GetText(path); - SaveRegDiff(path); + CEditPageCtrl &c = _ctrls[i]; + if (c.WasChanged) + { + UString path; + c.Edit.GetText(path); + if (i < 2) + SaveRegEditor(i > 0, path); + else + SaveRegDiff(path); + c.WasChanged = false; + } } + return PSNRET_NOERROR; } @@ -91,24 +93,34 @@ static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd) bool CEditPage::OnButtonClicked(int buttonID, HWND buttonHWND) { - switch (buttonID) + for (unsigned i = 0; i < 3; i++) { - case IDB_EDIT_VIEWER: Edit_BrowseForFile(_viewer, *this); return true; - case IDB_EDIT_EDITOR: Edit_BrowseForFile(_editor, *this); return true; - case IDB_EDIT_DIFF: Edit_BrowseForFile(_diff, *this); return true; + CEditPageCtrl &c = _ctrls[i]; + if (buttonID == c.Button) + { + Edit_BrowseForFile(c.Edit, *this); + return true; + } } + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } bool CEditPage::OnCommand(int code, int itemID, LPARAM param) { - if (code == EN_CHANGE && ( - itemID == IDE_EDIT_VIEWER || - itemID == IDE_EDIT_EDITOR || - itemID == IDE_EDIT_DIFF)) + if (!_initMode && code == EN_CHANGE) { - Changed(); - return true; + for (unsigned i = 0; i < 3; i++) + { + CEditPageCtrl &c = _ctrls[i]; + if (itemID == c.Ctrl) + { + c.WasChanged = true; + Changed(); + return true; + } + } } + return CPropertyPage::OnCommand(code, itemID, param); } diff --git a/CPP/7zip/UI/FileManager/EditPage.h b/CPP/7zip/UI/FileManager/EditPage.h index c11e613b..208edd8d 100644 --- a/CPP/7zip/UI/FileManager/EditPage.h +++ b/CPP/7zip/UI/FileManager/EditPage.h @@ -6,11 +6,19 @@ #include "../../../Windows/Control/PropertyPage.h" #include "../../../Windows/Control/Edit.h" +struct CEditPageCtrl +{ + NWindows::NControl::CEdit Edit; + bool WasChanged; + int Ctrl; + int Button; +}; + class CEditPage: public NWindows::NControl::CPropertyPage { - NWindows::NControl::CEdit _viewer; - NWindows::NControl::CEdit _editor; - NWindows::NControl::CEdit _diff; + CEditPageCtrl _ctrls[3]; + + bool _initMode; public: virtual bool OnInit(); virtual void OnNotifyHelp(); diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp index a320c016..f91dda09 100644 --- a/CPP/7zip/UI/FileManager/FM.cpp +++ b/CPP/7zip/UI/FileManager/FM.cpp @@ -324,42 +324,44 @@ static void GetCommands(const UString &aCommandLine, UString &aCommands) } */ -/* -#ifndef _WIN64 -typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +#if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE) + +bool g_Is_Wow64; -static bool IsWow64() +typedef BOOL (WINAPI *Func_IsWow64Process)(HANDLE, PBOOL); + +static void Set_Wow64() { - LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( - GetModuleHandle("kernel32"), "IsWow64Process"); - if (fnIsWow64Process == NULL) - return false; - BOOL isWow; - if (!fnIsWow64Process(GetCurrentProcess(),&isWow)) - return false; - return isWow != FALSE; + g_Is_Wow64 = false; + Func_IsWow64Process fnIsWow64Process = (Func_IsWow64Process)GetProcAddress( + GetModuleHandleA("kernel32.dll"), "IsWow64Process"); + if (fnIsWow64Process) + { + BOOL isWow; + if (fnIsWow64Process(GetCurrentProcess(), &isWow)) + g_Is_Wow64 = (isWow != FALSE); + } } + #endif -*/ + bool IsLargePageSupported() { #ifdef _WIN64 return true; #else - OSVERSIONINFO versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); - if (!::GetVersionEx(&versionInfo)) + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!::GetVersionEx(&vi)) return false; - if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 5) + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) return false; - if (versionInfo.dwMajorVersion > 5) - return true; - if (versionInfo.dwMinorVersion < 1) - return false; - if (versionInfo.dwMinorVersion > 1) - return true; - // return IsWow64(); + if (vi.dwMajorVersion < 5) return false; + if (vi.dwMajorVersion > 5) return true; + if (vi.dwMinorVersion < 1) return false; + if (vi.dwMinorVersion > 1) return true; + // return g_Is_Wow64; return false; #endif } @@ -382,11 +384,11 @@ bool g_SymLink_Supported = false; static void Set_SymLink_Supported() { g_SymLink_Supported = false; - OSVERSIONINFO versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); - if (!::GetVersionEx(&versionInfo)) + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!::GetVersionEx(&vi)) return; - if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 6) + if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT || vi.dwMajorVersion < 6) return; g_SymLink_Supported = true; // if (g_SymLink_Supported) @@ -468,6 +470,11 @@ static int WINAPI WinMain2(int nCmdShow) g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); #endif + #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE) + Set_Wow64(); + #endif + + g_IsSmallScreen = !NWindows::NControl::IsDialogSizeOK(200, 200); // OleInitialize is required for drag and drop. @@ -635,7 +642,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, try { - return WinMain2(nCmdShow); + try + { + return WinMain2(nCmdShow); + } + catch (...) + { + g_ExitEventLauncher.Exit(true); + throw; + } } catch(const CNewException &) { @@ -855,15 +870,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) g_App.Save(); g_App.Release(); SaveWindowInfo(hWnd); + + g_ExitEventLauncher.Exit(true); PostQuitMessage(0); break; } - /* - case WM_MOVE: - { - break; - } - */ + + // case WM_MOVE: break; + case WM_LBUTTONDOWN: g_StartCaptureMousePos = LOWORD(lParam); g_StartCaptureSplitterPos = g_Splitter.GetPos(); @@ -993,6 +1007,7 @@ void CApp::MoveSubWindows() if (xSize == 0) return; int headerSize = 0; + #ifdef UNDER_CE _commandBar.AutoSize(); { @@ -1000,6 +1015,7 @@ void CApp::MoveSubWindows() headerSize += _commandBar.Height(); } #endif + if (_toolBar) { _toolBar.AutoSize(); @@ -1009,6 +1025,7 @@ void CApp::MoveSubWindows() #endif headerSize += Window_GetRealHeight(_toolBar); } + int ySize = MyMax((int)(rect.bottom - headerSize), 0); if (NumPanels > 1) diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp index af0cd8cc..c91deb07 100644 --- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp +++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp @@ -208,7 +208,6 @@ struct CCopyState { CProgressInfo ProgressInfo; IFolderOperationsExtractCallback *Callback; - UInt64 TotalSize; bool MoveMode; bool UseReadWriteMode; @@ -423,7 +422,7 @@ static HRESULT CopyFile_Ask( NFsFolder::CCopyStateIO state2; state2.Progress = state.Callback; state2.DeleteSrcFile = state.MoveMode; - state2.TotalSize = state.TotalSize; + state2.TotalSize = state.ProgressInfo.TotalSize; state2.StartPos = state.ProgressInfo.StartPos; RINOK(state2.MyCopyFile(srcPath, destPathNew)); if (state2.ErrorFileIndex >= 0) @@ -460,10 +459,10 @@ static HRESULT CopyFile_Ask( } else { - if (state.TotalSize >= srcFileInfo.Size) + if (state.ProgressInfo.TotalSize >= srcFileInfo.Size) { - state.TotalSize -= srcFileInfo.Size; - RINOK(state.ProgressInfo.Progress->SetTotal(state.TotalSize)); + state.ProgressInfo.TotalSize -= srcFileInfo.Size; + RINOK(state.ProgressInfo.Progress->SetTotal(state.ProgressInfo.TotalSize)); } } return state.CallProgress(); diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp index 8719dd2c..42662153 100644 --- a/CPP/7zip/UI/FileManager/FoldersPage.cpp +++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp @@ -27,10 +27,13 @@ static const int kWorkModeButtons[] = IDR_FOLDERS_WORK_SPECIFIED }; -static const int kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons); +static const unsigned kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons); bool CFoldersPage::OnInit() { + _initMode = true; + _needSave = false; + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); m_WorkDirInfo.Load(); @@ -40,18 +43,18 @@ bool CFoldersPage::OnInit() kWorkModeButtons[m_WorkDirInfo.Mode]); m_WorkPath.Init(*this, IDE_FOLDERS_WORK_PATH); - m_ButtonSetWorkPath.Init(*this, IDB_FOLDERS_WORK_PATH); m_WorkPath.SetText(fs2us(m_WorkDirInfo.Path)); MyEnableControls(); + _initMode = false; return CPropertyPage::OnInit(); } int CFoldersPage::GetWorkMode() const { - for (int i = 0; i < kNumWorkModeButtons; i++) + for (unsigned i = 0; i < kNumWorkModeButtons; i++) if (IsButtonCheckedBool(kWorkModeButtons[i])) return i; throw 0; @@ -61,7 +64,7 @@ void CFoldersPage::MyEnableControls() { bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified); m_WorkPath.Enable(enablePath); - m_ButtonSetWorkPath.Enable(enablePath); + EnableItem(IDB_FOLDERS_WORK_PATH, enablePath); } void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo) @@ -86,7 +89,11 @@ bool CFoldersPage::WasChanged() void CFoldersPage::ModifiedEvent() { - Changed(); + if (!_initMode) + { + _needSave = true; + Changed(); + } /* if (WasChanged()) Changed(); @@ -97,23 +104,25 @@ void CFoldersPage::ModifiedEvent() bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND) { - for (int i = 0; i < kNumWorkModeButtons; i++) + for (unsigned i = 0; i < kNumWorkModeButtons; i++) if (buttonID == kWorkModeButtons[i]) { MyEnableControls(); ModifiedEvent(); return true; } + switch (buttonID) { case IDB_FOLDERS_WORK_PATH: OnFoldersWorkButtonPath(); - break; + return true; case IDX_FOLDERS_WORK_FOR_REMOVABLE: break; default: return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } + ModifiedEvent(); return true; } @@ -140,8 +149,12 @@ void CFoldersPage::OnFoldersWorkButtonPath() LONG CFoldersPage::OnApply() { - GetWorkDir(m_WorkDirInfo); - m_WorkDirInfo.Save(); + if (_needSave) + { + GetWorkDir(m_WorkDirInfo); + m_WorkDirInfo.Save(); + _needSave = false; + } return PSNRET_NOERROR; } diff --git a/CPP/7zip/UI/FileManager/FoldersPage.h b/CPP/7zip/UI/FileManager/FoldersPage.h index 7aaa80f7..71c7bfce 100644 --- a/CPP/7zip/UI/FileManager/FoldersPage.h +++ b/CPP/7zip/UI/FileManager/FoldersPage.h @@ -10,11 +10,14 @@ class CFoldersPage : public NWindows::NControl::CPropertyPage { NWorkDir::CInfo m_WorkDirInfo; + NWindows::NControl::CDialogChildControl m_WorkPath; + + bool _needSave; + bool _initMode; void MyEnableControls(); void ModifiedEvent(); - NWindows::NControl::CDialogChildControl m_WorkPath; - NWindows::NControl::CDialogChildControl m_ButtonSetWorkPath; + void OnFoldersWorkButtonPath(); int GetWorkMode() const; void GetWorkDir(NWorkDir::CInfo &workDirInfo); diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index d9dc6c52..cb1bbaab 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp @@ -84,14 +84,16 @@ bool CLangPage::OnInit() } if (!error.IsEmpty()) - MessageBoxW(0, error, L"Error in Lang file", MB_OK | MB_ICONSTOP); + MessageBoxW(0, error, L"Error in Lang file", MB_ICONERROR); return CPropertyPage::OnInit(); } LONG CLangPage::OnApply() { int pathIndex = (int)_langCombo.GetItemData_of_CurSel(); - SaveRegLang(_paths[pathIndex]); + if (_needSave) + SaveRegLang(_paths[pathIndex]); + _needSave = false; ReloadLang(); LangWasChanged = true; return PSNRET_NOERROR; @@ -106,6 +108,7 @@ bool CLangPage::OnCommand(int code, int itemID, LPARAM param) { if (code == CBN_SELCHANGE && itemID == IDC_LANG_LANG) { + _needSave = true; Changed(); return true; } diff --git a/CPP/7zip/UI/FileManager/LangPage.h b/CPP/7zip/UI/FileManager/LangPage.h index 589941b2..b8062573 100644 --- a/CPP/7zip/UI/FileManager/LangPage.h +++ b/CPP/7zip/UI/FileManager/LangPage.h @@ -10,10 +10,12 @@ class CLangPage: public NWindows::NControl::CPropertyPage { NWindows::NControl::CComboBox _langCombo; UStringVector _paths; + + bool _needSave; public: bool LangWasChanged; - CLangPage() { LangWasChanged = false; } + CLangPage(): _needSave(false), LangWasChanged(false) {} virtual bool OnInit(); virtual void OnNotifyHelp(); virtual bool OnCommand(int code, int itemID, LPARAM param); diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp index 9723704a..761319b5 100644 --- a/CPP/7zip/UI/FileManager/LangUtils.cpp +++ b/CPP/7zip/UI/FileManager/LangUtils.cpp @@ -140,13 +140,18 @@ void LangString_OnlyFromLangFile(UInt32 langID, UString &dest) } static const char *kLangs = -"ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is.it.ja.ko.nl.no.=nb.=nn." -"pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr.ur.id.uk.be.sl.et.lv.lt.tg." -"fa.vi.hy.az.eu.hsb.mk...tn..xh.zu.af.ka.fo.hi.mt.se.ga." -".ms.kk.ky.sw.tk.uz.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa.mn.=mn.=mng" -"bo.cy.kh.lo..gl.kok..sd.syr.si..iu.am.tzm.ks.ne.fy.ps.fil." -"dv...ha..yo.quz.nso.ba.lb.kl.ig...ti.....ii." -".arn..moh..br..ug.mi.oc.co.gsw.sah.qut.rw.wo....prs."; + "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is." + "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr." + "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk." + "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk." + "ky.sw.tk.uz.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa." + "mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm." + "ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl." + "ig.kr.om.ti.gn..la.so.ii..arn..moh..br.." + "ug.mi.oc.co." + // "gsw.sah.qut.rw.wo....prs...." + // ".gd." + ; static void FindShortNames(UInt32 primeLang, UStringVector &names) { @@ -158,10 +163,10 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names) bool isSub = (p[0] == '-' || p[0] == '='); if (!isSub) index++; - if (index > primeLang) - break; - if (index == primeLang) + if (index >= primeLang) { + if (index > primeLang) + break; UString s; if (isSub) { @@ -178,6 +183,33 @@ static void FindShortNames(UInt32 primeLang, UStringVector &names) } } +/* +#include "../../../Common/IntToString.h" + +static struct CC1Lang +{ + CC1Lang() + { + for (int i = 1; i < 150; i++) + { + UString s; + char ttt[32]; + ConvertUInt32ToHex(i, ttt); + s.AddAscii(ttt); + UStringVector names; + FindShortNames(i, names); + + FOR_VECTOR (k, names) + { + s.Add_Space(); + s += names[k]; + } + OutputDebugStringW(s); + } + } +} g_cc1; +*/ + // typedef LANGID (WINAPI *GetUserDefaultUILanguageP)(); static void OpenDefaultLang() diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp index 58468816..80cdd7f6 100644 --- a/CPP/7zip/UI/FileManager/ListViewDialog.cpp +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -18,7 +18,9 @@ bool CListViewDialog::OnInit() #endif _listView.Attach(GetItem(IDL_LISTVIEW)); - if (ReadSingleClick()) + CFmSettings st; + st.Load(); + if (st.SingleClick) _listView.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); SetText(Title); diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index 0784f92c..8852ce35 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp @@ -4,25 +4,34 @@ #include "../Common/ZipRegistry.h" +#include "../../../Windows/DLL.h" +#include "../../../Windows/ErrorMsg.h" +#include "../../../Windows/FileFind.h" + #include "../Explorer/ContextMenuFlags.h" #include "../Explorer/RegistryContextMenu.h" #include "../Explorer/resource.h" +#include "../FileManager/PropertyNameRes.h" + +#include "../GUI/ExtractDialogRes.h" + +#include "FormatUtils.h" #include "HelpUtils.h" #include "LangUtils.h" #include "MenuPage.h" #include "MenuPageRes.h" -#include "FormatUtils.h" -#include "../FileManager/PropertyNameRes.h" +using namespace NWindows; using namespace NContextMenuFlags; static const UInt32 kLangIDs[] = { - IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, + IDX_SYSTEM_INTEGRATE_TO_MENU, IDX_SYSTEM_CASCADED_MENU, IDX_SYSTEM_ICON_IN_MENU, + IDX_EXTRACT_ELIM_DUP, IDT_SYSTEM_CONTEXT_MENU_ITEMS }; @@ -34,64 +43,147 @@ struct CContextMenuItem UInt32 Flag; }; -static CContextMenuItem kMenuItems[] = +static const CContextMenuItem kMenuItems[] = { - { IDS_CONTEXT_OPEN, kOpen}, - { IDS_CONTEXT_OPEN, kOpenAs}, - { IDS_CONTEXT_EXTRACT, kExtract}, + { IDS_CONTEXT_OPEN, kOpen }, + { IDS_CONTEXT_OPEN, kOpenAs }, + { IDS_CONTEXT_EXTRACT, kExtract }, { IDS_CONTEXT_EXTRACT_HERE, kExtractHere }, { IDS_CONTEXT_EXTRACT_TO, kExtractTo }, - { IDS_CONTEXT_TEST, kTest}, + { IDS_CONTEXT_TEST, kTest }, { IDS_CONTEXT_COMPRESS, kCompress }, { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z }, - { IDS_CONTEXT_COMPRESS_TO, kCompressToZip } + { IDS_CONTEXT_COMPRESS_TO, kCompressToZip }, #ifndef UNDER_CE - , { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail }, { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail }, - { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail } + { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail }, #endif - , { IDS_PROP_CHECKSUM, kCRC } + { IDS_PROP_CHECKSUM, kCRC } }; + +#if !defined(_WIN64) +extern bool g_Is_Wow64; +#endif + + bool CMenuPage::OnInit() { _initMode = true; + + Clear_MenuChanged(); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #ifdef UNDER_CE - EnableItem(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, false); + + HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU); + HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2); + #else - CheckButton(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, NZipRootRegistry::CheckContextMenuHandler()); + + { + UString s; + { + CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU)); + window.GetText(s); + } + UString bit64 = LangString(IDS_PROP_BIT64); + if (bit64.IsEmpty()) + bit64.SetFromAscii("64-bit"); + #ifdef _WIN64 + bit64.Replace(L"64", L"32"); + #endif + s.Add_Space(); + s += L'('; + s += bit64; + s += L')'; + SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s); + } + + const FString prefix = NDLL::GetModuleDirPrefix(); + + _dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU; + _dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2; + + _dlls[0].wow = 0; + _dlls[1].wow = + #ifdef _WIN64 + KEY_WOW64_32KEY + #else + KEY_WOW64_64KEY + #endif + ; + + for (unsigned d = 0; d < 2; d++) + { + CShellDll &dll = _dlls[d]; + + dll.wasChanged = false; + + #ifndef _WIN64 + if (d != 0 && !g_Is_Wow64) + { + HideItem(dll.ctrl); + continue; + } + #endif + + FString &path = dll.Path; + path = prefix; + path.AddAscii(d == 0 ? "7-zip.dll" : + #ifdef _WIN64 + "7-zip32.dll" + #else + "7-zip64.dll" + #endif + ); + + + if (!NFile::NFind::DoesFileExist(path)) + { + path.Empty(); + EnableItem(dll.ctrl, false); + } + else + { + dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow); + CheckButton(dll.ctrl, dll.prevValue); + } + } + #endif + CContextMenuInfo ci; ci.Load(); - CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded); - CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons); + CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val); + CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val); + CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val); _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS)); - UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; + const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT; _listView.SetExtendedListViewStyle(newFlags, newFlags); - _listView.InsertColumn(0, L"", 100); + _listView.InsertColumn(0, L"", 200); - for (int i = 0; i < ARRAY_SIZE(kMenuItems); i++) + for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++) { - CContextMenuItem &menuItem = kMenuItems[i]; + const CContextMenuItem &menuItem = kMenuItems[i]; UString s = LangString(menuItem.ControlID); if (menuItem.Flag == kCRC) - s = L"CRC SHA"; + s.SetFromAscii("CRC SHA"); if (menuItem.Flag == kOpenAs || menuItem.Flag == kCRC) - s += L" >"; + s.AddAscii(" >"); switch (menuItem.ControlID) { @@ -108,11 +200,11 @@ bool CMenuPage::OnInit() { case kCompressTo7z: case kCompressTo7zEmail: - s2 += L".7z"; + s2.AddAscii(".7z"); break; case kCompressToZip: case kCompressToZipEmail: - s2 += L".zip"; + s2.AddAscii(".zip"); break; } s = MyFormatNew(s, s2); @@ -126,39 +218,68 @@ bool CMenuPage::OnInit() _listView.SetColumnWidthAuto(0); _initMode = false; + return CPropertyPage::OnInit(); } + #ifndef UNDER_CE -STDAPI DllRegisterServer(void); -STDAPI DllUnregisterServer(void); -HWND g_MenuPageHWND = 0; + +static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd) +{ + MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR); +} + #endif + LONG CMenuPage::OnApply() { #ifndef UNDER_CE - g_MenuPageHWND = *this; - if (IsButtonCheckedBool(IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU)) + + for (unsigned d = 2; d != 0;) { - DllRegisterServer(); - NZipRootRegistry::AddContextMenuHandler(); + d--; + CShellDll &dll = _dlls[d]; + if (dll.wasChanged && !dll.Path.IsEmpty()) + { + bool newVal = IsButtonCheckedBool(dll.ctrl); + LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow); + if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal)) + ShowMenuErrorMessage(NError::MyFormatMessage(res), *this); + dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow); + CheckButton(dll.ctrl, dll.prevValue); + dll.wasChanged = false; + } } - else + + #endif + + if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed) { - DllUnregisterServer(); - NZipRootRegistry::DeleteContextMenuHandler(); + CContextMenuInfo ci; + ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU); + ci.Cascaded.Def = _cascaded_Changed; + + ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU); + ci.MenuIcons.Def = _menuIcons_Changed; + + ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP); + ci.ElimDup.Def = _elimDup_Changed; + + ci.Flags = 0; + + for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++) + if (_listView.GetCheckState(i)) + ci.Flags |= kMenuItems[i].Flag; + + ci.Flags_Def = _flags_Changed; + ci.Save(); + + Clear_MenuChanged(); } - #endif - CContextMenuInfo ci; - ci.Cascaded = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU); - ci.MenuIcons = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU); - ci.Flags = 0; - for (int i = 0; i < ARRAY_SIZE(kMenuItems); i++) - if (_listView.GetCheckState(i)) - ci.Flags |= kMenuItems[i].Flag; - ci.Save(); + // UnChanged(); return PSNRET_NOERROR; } @@ -172,14 +293,30 @@ bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch (buttonID) { - case IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU: - case IDX_SYSTEM_CASCADED_MENU: - case IDX_SYSTEM_ICON_IN_MENU: - Changed(); - return true; + #ifndef UNDER_CE + case IDX_SYSTEM_INTEGRATE_TO_MENU: + case IDX_SYSTEM_INTEGRATE_TO_MENU_2: + { + for (unsigned d = 0; d < 2; d++) + { + CShellDll &dll = _dlls[d]; + if (buttonID == dll.ctrl && !dll.Path.IsEmpty()) + dll.wasChanged = true; + } + break; + } + #endif + + case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break; + case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break; + case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break; + + default: + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } - return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); - + + Changed(); + return true; } bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam) @@ -205,7 +342,10 @@ bool CMenuPage::OnItemChanged(const NMLISTVIEW *info) UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK; UINT newState = info->uNewState & LVIS_STATEIMAGEMASK; if (oldState != newState) + { + _flags_Changed = true; Changed(); + } } return true; } diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h index 1363687f..3807d9dd 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.h +++ b/CPP/7zip/UI/FileManager/MenuPage.h @@ -6,11 +6,38 @@ #include "../../../Windows/Control/PropertyPage.h" #include "../../../Windows/Control/ListView.h" -#include "../Common/LoadCodecs.h" +struct CShellDll +{ + FString Path; + bool wasChanged; + bool prevValue; + int ctrl; + UInt32 wow; + + CShellDll(): wasChanged (false), prevValue(false), ctrl(0), wow(0) {} +}; class CMenuPage: public NWindows::NControl::CPropertyPage { bool _initMode; + + bool _cascaded_Changed; + bool _menuIcons_Changed; + bool _elimDup_Changed; + bool _flags_Changed; + + void Clear_MenuChanged() + { + _cascaded_Changed = false; + _menuIcons_Changed = false; + _elimDup_Changed = false; + _flags_Changed = false; + } + + #ifndef UNDER_CE + CShellDll _dlls[2]; + #endif + NWindows::NControl::CListView _listView; virtual bool OnInit(); diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc index f20c574e..dd32898f 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.rc +++ b/CPP/7zip/UI/FileManager/MenuPage.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 240 -#define yc 196 +#define yc 224 IDD_MENU MY_PAGE #include "MenuPage2.rc" diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc index 442d1bdd..af86226d 100644 --- a/CPP/7zip/UI/FileManager/MenuPage2.rc +++ b/CPP/7zip/UI/FileManager/MenuPage2.rc @@ -1,12 +1,16 @@ -#define y 54 +#include "../GUI/ExtractDialogRes.h" + +#define y 82 CAPTION "7-Zip" BEGIN - CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU, MY_CHECKBOX, m, m, xc, 10 - CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 14, xc, 10 - CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 28, xc, 10 + CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_MENU, MY_CHECKBOX, m, m, xc, 10 + CONTROL "(32-bit)", IDX_SYSTEM_INTEGRATE_TO_MENU_2, MY_CHECKBOX, m, m + 14, xc, 10 + CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 28, xc, 10 + CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10 + CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10 - LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 42, xc, 8 + LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 70, xc, 8 CONTROL "List", IDL_SYSTEM_OPTIONS, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP, m, m + y, xc, yc - y diff --git a/CPP/7zip/UI/FileManager/MenuPageRes.h b/CPP/7zip/UI/FileManager/MenuPageRes.h index 91f75710..ae0bf66d 100644 --- a/CPP/7zip/UI/FileManager/MenuPageRes.h +++ b/CPP/7zip/UI/FileManager/MenuPageRes.h @@ -1,9 +1,11 @@ #define IDD_MENU 2300 #define IDD_MENU_2 12300 -#define IDX_SYSTEM_INTEGRATE_TO_CONTEXT_MENU 2301 -#define IDX_SYSTEM_CASCADED_MENU 2302 -#define IDT_SYSTEM_CONTEXT_MENU_ITEMS 2303 -#define IDX_SYSTEM_ICON_IN_MENU 2304 +#define IDX_SYSTEM_INTEGRATE_TO_MENU 2301 +#define IDX_SYSTEM_CASCADED_MENU 2302 +#define IDT_SYSTEM_CONTEXT_MENU_ITEMS 2303 +#define IDX_SYSTEM_ICON_IN_MENU 2304 + +#define IDX_SYSTEM_INTEGRATE_TO_MENU_2 2310 #define IDL_SYSTEM_OPTIONS 100 diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp index b9dbf232..d3031f5a 100644 --- a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp +++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp @@ -512,7 +512,8 @@ bool OnMenuCommand(HWND hWnd, int id) // File case IDCLOSE: SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd); - SendMessage (hWnd, WM_CLOSE, 0, 0); + g_ExitEventLauncher.Exit(false); + SendMessage(hWnd, WM_CLOSE, 0, 0); break; // Edit diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp index fa2ab922..66e6f3c4 100644 --- a/CPP/7zip/UI/FileManager/OptionsDialog.cpp +++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp @@ -6,6 +6,7 @@ #include "../../../Windows/Control/PropertyPage.h" #include "DialogSize.h" + #include "EditPage.h" #include "EditPageRes.h" #include "FoldersPage.h" @@ -14,8 +15,6 @@ #include "LangPageRes.h" #include "MenuPage.h" #include "MenuPageRes.h" -// #include "PluginsPage.h" -// #include "PluginsPageRes.h" #include "SettingsPage.h" #include "SettingsPageRes.h" #include "SystemPage.h" @@ -29,90 +28,38 @@ using namespace NWindows; -#ifndef UNDER_CE -typedef UINT32 (WINAPI * DllRegisterServerPtr)(); - -extern HWND g_MenuPageHWND; - -static void ShowMenuErrorMessage(const wchar_t *m) -{ - MessageBoxW(g_MenuPageHWND, m, L"7-Zip", MB_ICONERROR); -} - -static int DllRegisterServer2(const char *name) -{ - NDLL::CLibrary lib; - - FString prefix = NDLL::GetModuleDirPrefix(); - if (!lib.Load(prefix + FTEXT("7-zip.dll"))) - { - ShowMenuErrorMessage(L"7-Zip cannot load 7-zip.dll"); - return E_FAIL; - } - DllRegisterServerPtr f = (DllRegisterServerPtr)lib.GetProc(name); - if (f == NULL) - { - ShowMenuErrorMessage(L"Incorrect plugin"); - return E_FAIL; - } - HRESULT res = f(); - if (res != S_OK) - ShowMenuErrorMessage(HResultToMessage(res)); - return (int)res; -} - -STDAPI DllRegisterServer(void) -{ - #ifdef UNDER_CE - return S_OK; - #else - return DllRegisterServer2("DllRegisterServer"); - #endif -} - -STDAPI DllUnregisterServer(void) -{ - #ifdef UNDER_CE - return S_OK; - #else - return DllRegisterServer2("DllUnregisterServer"); - #endif -} - -#endif - void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) { CSystemPage systemPage; - // CPluginsPage pluginsPage; + CMenuPage menuPage; + CFoldersPage foldersPage; CEditPage editPage; CSettingsPage settingsPage; CLangPage langPage; - CMenuPage menuPage; - CFoldersPage foldersPage; CObjectVector<NControl::CPageInfo> pages; BIG_DIALOG_SIZE(200, 200); - UINT pageIDs[] = { + const UINT pageIDs[] = { SIZED_DIALOG(IDD_SYSTEM), SIZED_DIALOG(IDD_MENU), SIZED_DIALOG(IDD_FOLDERS), SIZED_DIALOG(IDD_EDIT), SIZED_DIALOG(IDD_SETTINGS), SIZED_DIALOG(IDD_LANG) }; - NControl::CPropertyPage *pagePinters[] = { &systemPage, &menuPage, &foldersPage, &editPage, &settingsPage, &langPage }; - const int kNumPages = ARRAY_SIZE(pageIDs); - for (int i = 0; i < kNumPages; i++) + + NControl::CPropertyPage *pagePointers[] = { &systemPage, &menuPage, &foldersPage, &editPage, &settingsPage, &langPage }; + + for (unsigned i = 0; i < ARRAY_SIZE(pageIDs); i++) { - NControl::CPageInfo page; + NControl::CPageInfo &page = pages.AddNew(); page.ID = pageIDs[i]; LangString_OnlyFromLangFile(page.ID, page.Title); - page.Page = pagePinters[i]; - pages.Add(page); + page.Page = pagePointers[i]; } INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS)); + if (res != -1 && res != 0) { if (langPage.LangWasChanged) @@ -120,9 +67,10 @@ void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) // g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000)); MyLoadMenu(); g_App.ReloadToolbars(); - g_App.MoveSubWindows(); + g_App.MoveSubWindows(); // we need it to change list window aafter _toolBar.AutoSize(); g_App.ReloadLang(); } + /* if (systemPage.WasChanged) { @@ -130,8 +78,8 @@ void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */) g_App.SysIconsWereChanged(); } */ + g_App.SetListSettings(); - g_App.SetShowSystemMenu(); g_App.RefreshAllPanels(); // ::PostMessage(hwndOwner, kLangWasChangedMessage, 0 , 0); } diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index 709ef0f5..fc74d556 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -841,4 +841,28 @@ public: ~CMyBuffer() { ::MidFree(_data); } }; +class CExitEventLauncher +{ +public: + NWindows::NSynchronization::CManualResetEvent _exitEvent; + bool _needExit; + CRecordVector< ::CThread > _threads; + unsigned _numActiveThreads; + + CExitEventLauncher() + { + _needExit = false; + if (_exitEvent.Create(false) != S_OK) + throw 9387173; + _needExit = true; + _numActiveThreads = 0; + }; + + ~CExitEventLauncher() { Exit(true); } + + void Exit(bool hardExit); +}; + +extern CExitEventLauncher g_ExitEventLauncher; + #endif diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp index e20ddd63..0cd08d4c 100644 --- a/CPP/7zip/UI/FileManager/PanelDrag.cpp +++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp @@ -209,7 +209,23 @@ STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState) { CCopyToOptions options; options.folder = Folder; + + // 15.13: fixed problem with mouse cursor for password window. + // DoDragDrop() probably calls SetCapture() to some hidden window. + // But it's problem, if we show some modal window, like MessageBox. + // So we return capture to our window. + // If you know better way to solve the problem, please notify 7-Zip developer. + + // MessageBoxW(*Panel, L"test", L"test", 0); + + /* HWND oldHwnd = */ SetCapture(*Panel); + Result = Panel->CopyTo(options, Indices, &Messages); + + // do we need to restore capture? + // ReleaseCapture(); + // oldHwnd = SetCapture(oldHwnd); + if (Result != S_OK || !Messages.IsEmpty()) return DRAGDROP_S_CANCEL; } @@ -357,10 +373,14 @@ void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */) effectsOK |= DROPEFFECT_MOVE; DWORD effect; _panelCallback->DragBegin(); + HRESULT res = DoDragDrop(dataObject, dropSource, effectsOK, &effect); + _panelCallback->DragEnd(); bool canceled = (res == DRAGDROP_S_CANCEL); + CDisableNotify disableNotify(*this); + if (res == DRAGDROP_S_DROP) { res = dropSourceSpec->Result; diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index c37ac64f..cfbc5770 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp @@ -6,6 +6,8 @@ #include <tlhelp32.h> +#include "../../../Common/IntToString.h" + #include "../../../Common/AutoPtr.h" #include "../../../Common/StringConvert.h" @@ -24,6 +26,7 @@ #include "FileFolderPluginOpen.h" #include "FormatUtils.h" #include "LangUtils.h" +#include "PropertyNameRes.h" #include "RegistryUtils.h" #include "UpdateCallback100.h" @@ -45,6 +48,20 @@ extern bool g_IsNT; static CFSTR kTempDirPrefix = FTEXT("7zO"); +// #define SHOW_DEBUG_INFO + +#ifdef SHOW_DEBUG_INFO + #define DEBUG_PRINT(s) OutputDebugStringA(s); + #define DEBUG_PRINT_W(s) OutputDebugStringW(s); + #define DEBUG_PRINT_NUM(s, num) { char ttt[32]; ConvertUInt32ToString(num, ttt); OutputDebugStringA(s); OutputDebugStringA(ttt); } +#else + #define DEBUG_PRINT(s) + #define DEBUG_PRINT_W(s) + #define DEBUG_PRINT_NUM(s, num) +#endif + + + #ifndef UNDER_CE class CProcessSnapshot @@ -76,90 +93,329 @@ public: #endif -typedef DWORD (WINAPI *GetProcessIdFunc)(HANDLE process); + +/* +struct COpenExtProg +{ + const char *Ext; + const char *Prog; +}; + +static const COpenExtProg g_Progs[] = +{ + { "jpeg jpg png bmp gif", "Microsoft.Photos.exe" }, + { "html htm pdf", "MicrosoftEdge.exe" }, + // , { "rrr", "notepad.exe" } +}; + +static bool FindExtProg(const char *exts, const char *ext) +{ + unsigned len = (unsigned)strlen(ext); + for (;;) + { + const char *p = exts; + for (;; p++) + { + const char c = *p; + if (c == 0 || c == ' ') + break; + } + if (len == (unsigned)(p - exts) && IsString1PrefixedByString2(exts, ext)) + return true; + if (*p == 0) + return false; + exts = p + 1; + } +} + +class CPossibleProgs +{ +public: + AStringVector ProgNames; + + void SetFromExtension(const char *ext) // ext must be low case + { + ProgNames.Clear(); + for (unsigned i = 0; i < ARRAY_SIZE(g_Progs); i++) + if (FindExtProg(g_Progs[i].Ext, ext)) + { + ProgNames.Add(g_Progs[i].Prog); + } + } + + bool IsFromList(const UString &progName) const + { + FOR_VECTOR (i, ProgNames) + if (progName.IsEqualTo_Ascii_NoCase(ProgNames[i])) + return true; + return false; + } +}; +*/ + + +#ifndef UNDER_CE + +EXTERN_C_BEGIN + +/* +GetProcessImageFileName + returns the path in device form, rather than drive letters: + \Device\HarddiskVolume1\WINDOWS\SysWOW64\notepad.exe + +GetModuleFileNameEx works only after Sleep(something). Why? + returns the path + C:\WINDOWS\system32\NOTEPAD.EXE +*/ + +/* Kernel32.dll: Win7, Win2008R2; + Psapi.dll: (if PSAPI_VERSION=1) on Win7 and Win2008R2; + Psapi.dll: XP, Win2003, Vista, 2008; +*/ + +typedef DWORD (WINAPI *Func_GetProcessImageFileNameW)( + HANDLE hProcess, LPWSTR lpFilename, DWORD nSize); + +typedef DWORD (WINAPI *Func_GetModuleFileNameExW)( + HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize); + +typedef DWORD (WINAPI *Func_GetProcessId)(HANDLE process); + +EXTERN_C_END + + +static HMODULE g_Psapi_dll_module; + +/* +static void My_GetProcessFileName_2(HANDLE hProcess, UString &path) +{ + path.Empty(); + const unsigned maxPath = 1024; + WCHAR temp[maxPath + 1]; + + const char *func_name = "GetModuleFileNameExW"; + Func_GetModuleFileNameExW my_func = (Func_GetModuleFileNameExW) + ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name); + if (!my_func) + { + if (!g_Psapi_dll_module) + g_Psapi_dll_module = LoadLibraryW(L"Psapi.dll"); + if (g_Psapi_dll_module) + my_func = (Func_GetModuleFileNameExW)::GetProcAddress(g_Psapi_dll_module, func_name); + } + if (my_func) + { + // DWORD num = GetModuleFileNameEx(hProcess, NULL, temp, maxPath); + DWORD num = my_func(hProcess, NULL, temp, maxPath); + if (num != 0) + path = temp; + } + // FreeLibrary(lib); +} +*/ + +static void My_GetProcessFileName(HANDLE hProcess, UString &path) +{ + path.Empty(); + const unsigned maxPath = 1024; + WCHAR temp[maxPath + 1]; + + const char *func_name = "GetProcessImageFileNameW"; + Func_GetProcessImageFileNameW my_func = (Func_GetProcessImageFileNameW) + ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name); + + if (!my_func) + { + if (!g_Psapi_dll_module) + g_Psapi_dll_module = LoadLibraryW(L"Psapi.dll"); + if (g_Psapi_dll_module) + my_func = (Func_GetProcessImageFileNameW)::GetProcAddress(g_Psapi_dll_module, func_name); + } + + if (my_func) + { + // DWORD num = GetProcessImageFileNameW(hProcess, temp, maxPath); + DWORD num = my_func(hProcess, temp, maxPath); + if (num != 0) + path = temp; + } + // FreeLibrary(lib); +} + +struct CSnapshotProcess +{ + DWORD Id; + DWORD ParentId; + UString Name; +}; + +static void GetSnapshot(CObjectVector<CSnapshotProcess> &items) +{ + items.Clear(); + + CProcessSnapshot snapshot; + if (!snapshot.Create()) + return; + + DEBUG_PRINT("snapshot.Create() OK"); + PROCESSENTRY32 pe; + CSnapshotProcess item; + memset(&pe, 0, sizeof(pe)); + pe.dwSize = sizeof(pe); + BOOL res = snapshot.GetFirstProcess(&pe); + while (res) + { + item.Id = pe.th32ProcessID; + item.ParentId = pe.th32ParentProcessID; + item.Name = GetUnicodeString(pe.szExeFile); + items.Add(item); + res = snapshot.GetNextProcess(&pe); + } +} + +#endif + class CChildProcesses { #ifndef UNDER_CE CRecordVector<DWORD> _ids; #endif + public: + // bool ProgsWereUsed; CRecordVector<HANDLE> Handles; CRecordVector<bool> NeedWait; + // UStringVector Names; + + #ifndef UNDER_CE + UString Path; + #endif + // CChildProcesses(): ProgsWereUsed(false) {} ~CChildProcesses() { CloseAll(); } void DisableWait(unsigned index) { NeedWait[index] = false; } void CloseAll() { - FOR_VECTOR (i, Handles) + FOR_VECTOR (i, Handles) { HANDLE h = Handles[i]; if (h != NULL) CloseHandle(h); } + Handles.Clear(); NeedWait.Clear(); + // Names.Clear(); + + #ifndef UNDER_CE + // Path.Empty(); + _ids.Clear(); + #endif } - void AddProcess(HANDLE h) + void SetMainProcess(HANDLE h) { #ifndef UNDER_CE - GetProcessIdFunc func = (GetProcessIdFunc)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId"); + + Func_GetProcessId func = (Func_GetProcessId)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId"); if (func) - _ids.AddToUniqueSorted(func(h)); + { + DWORD id = func(h); + if (id != 0) + _ids.AddToUniqueSorted(id); + } + + My_GetProcessFileName(h, Path); + DEBUG_PRINT_W(Path); + #endif + Handles.Add(h); NeedWait.Add(true); } - void Update() + #ifndef UNDER_CE + + void Update(bool needFindProcessByPath /* , const CPossibleProgs &progs */) { - #ifndef UNDER_CE - CRecordVector<DWORD> ids, parents; + /* + if (_ids.IsEmpty()) + return; + */ + + CObjectVector<CSnapshotProcess> sps; + GetSnapshot(sps); + + const int separ = Path.ReverseFind_PathSepar(); + const UString mainName = Path.Ptr(separ + 1); + if (mainName.IsEmpty()) + needFindProcessByPath = false; + + const DWORD currentProcessId = GetCurrentProcessId(); + + for (;;) { - CProcessSnapshot snapshot; - if (snapshot.Create()) + bool wasAdded = false; + + FOR_VECTOR (i, sps) { - PROCESSENTRY32 pe; - memset(&pe, 0, sizeof(pe)); - pe.dwSize = sizeof(pe); - BOOL res = snapshot.GetFirstProcess(&pe); - while (res) + const CSnapshotProcess &sp = sps[i]; + const DWORD id = sp.Id; + + if (id == currentProcessId) + continue; + if (_ids.FindInSorted(id) >= 0) + continue; + + bool isSameName = false; + const UString &name = sp.Name; + + if (needFindProcessByPath) + isSameName = mainName.IsEqualTo_NoCase(name); + + bool needAdd = false; + // bool isFromProgs = false; + + if (isSameName || _ids.FindInSorted(sp.ParentId) >= 0) + needAdd = true; + /* + else if (progs.IsFromList(name)) { - ids.Add(pe.th32ProcessID); - parents.Add(pe.th32ParentProcessID); - res = snapshot.GetNextProcess(&pe); + needAdd = true; + isFromProgs = true; } - } - } + */ - for (;;) - { - unsigned i; - for (i = 0; i < ids.Size(); i++) - { - DWORD id = ids[i]; - if (_ids.FindInSorted(parents[i]) >= 0 && - _ids.FindInSorted(id) < 0) + if (needAdd) { + DEBUG_PRINT("----- OpenProcess -----"); + DEBUG_PRINT_W(name); HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, id); if (hProcess) { - _ids.AddToUniqueSorted(id); + DEBUG_PRINT("----- OpenProcess OK -----"); + // if (!isFromProgs) + _ids.AddToUniqueSorted(id); Handles.Add(hProcess); NeedWait.Add(true); - break; + // Names.Add(name); + wasAdded = true; + // ProgsWereUsed = isFromProgs; } } } - if (i == ids.Size()) + + if (!wasAdded) break; } - #endif } + + #endif }; + struct CTmpProcessInfo: public CTempFileInfo { CChildProcesses Processes; @@ -168,9 +424,12 @@ struct CTmpProcessInfo: public CTempFileInfo bool UsePassword; UString Password; - CTmpProcessInfo(): UsePassword(false) {} + bool ReadOnly; + + CTmpProcessInfo(): UsePassword(false), ReadOnly(false) {} }; + class CTmpProcessInfoRelease { CTmpProcessInfo *_tmpProcessInfo; @@ -600,6 +859,9 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi process.Attach(execInfo.hProcess); } + + DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result) + if (result <= 32) { switch (result) @@ -610,6 +872,8 @@ static HRESULT StartApplication(const UString &dir, const UString &path, HWND wi // L"There is no application associated with the given file name extension", L"7-Zip", MB_OK | MB_ICONSTOP); } + + return E_FAIL; // fixed in 15.13. Can we use it for any Windows version? } return S_OK; @@ -800,6 +1064,8 @@ HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, LRESULT CPanel::OnOpenItemChanged(LPARAM lParam) { + // DEBUG_PRINT_NUM("OnOpenItemChanged", GetCurrentThreadId()); + CTmpProcessInfo &tpi = *(CTmpProcessInfo *)lParam; if (tpi.FullPathFolderPrefix != _currentFolderPrefix) return 0; @@ -834,24 +1100,75 @@ LRESULT CPanel::OnOpenItemChanged(LPARAM lParam) return 1; } -class CExitEventLauncher + +CExitEventLauncher g_ExitEventLauncher; + +void CExitEventLauncher::Exit(bool hardExit) { -public: - NWindows::NSynchronization::CManualResetEvent _exitEvent; - CExitEventLauncher() + if (_needExit) { - if (_exitEvent.Create(false) != S_OK) - throw 9387173; - }; - ~CExitEventLauncher() { _exitEvent.Set(); } -} g_ExitEventLauncher; + _exitEvent.Set(); + _needExit = false; + } + + if (_numActiveThreads == 0) + return; + + FOR_VECTOR (i, _threads) + { + ::CThread &th = _threads[i]; + DWORD wait = (hardExit ? 100 : INFINITE); + if (Thread_WasCreated(&th)) + { + DWORD waitResult = WaitForSingleObject(th, wait); + // Thread_Wait(&th); + if (waitResult == WAIT_TIMEOUT) + wait = 1; + if (!hardExit && waitResult != WAIT_OBJECT_0) + continue; + Thread_Close(&th); + _numActiveThreads--; + } + } +} + + static THREAD_FUNC_DECL MyThreadFunction(void *param) { + DEBUG_PRINT("==== MyThreadFunction ===="); + CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param); CTmpProcessInfo *tpi = tmpProcessInfoPtr.get(); CChildProcesses &processes = tpi->Processes; + bool mainProcessWasSet = !processes.Handles.IsEmpty(); + + bool isComplexMode = true; + + if (!processes.Handles.IsEmpty()) + { + + const DWORD startTime = GetTickCount(); + + /* + CPossibleProgs progs; + { + const UString &name = tpi->RelPath; + int slashPos = name.ReverseFind_PathSepar(); + int dotPos = name.ReverseFind_Dot(); + if (dotPos > slashPos) + { + const UString ext = name.Ptr(dotPos + 1); + AString extA = UnicodeStringToMultiByte(ext); + extA.MakeLower_Ascii(); + progs.SetFromExtension(extA); + } + } + */ + + bool firstPass = true; + for (;;) { CRecordVector<HANDLE> handles; @@ -859,6 +1176,8 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) FOR_VECTOR (i, processes.Handles) { + if (handles.Size() > 60) + break; if (processes.NeedWait[i]) { handles.Add(processes.Handles[i]); @@ -866,43 +1185,150 @@ static THREAD_FUNC_DECL MyThreadFunction(void *param) } } + bool needFindProcessByPath = false; + if (handles.IsEmpty()) - break; + { + if (!firstPass) + break; + } + else + { + handles.Add(g_ExitEventLauncher._exitEvent); + + DWORD waitResult = ::WaitForMultipleObjects(handles.Size(), &handles.Front(), FALSE, INFINITE); + + waitResult -= WAIT_OBJECT_0; + + if (waitResult >= handles.Size() - 1) + { + processes.CloseAll(); + /* + if (waitResult == handles.Size() - 1) + { + // exit event + // we want to delete temp files, if progs were used + if (processes.ProgsWereUsed) + break; + } + */ + return waitResult >= (DWORD)handles.Size() ? 1 : 0; + } - handles.Add(g_ExitEventLauncher._exitEvent); + if (firstPass && indices.Size() == 1) + { + DWORD curTime = GetTickCount() - startTime; - DWORD waitResult = ::WaitForMultipleObjects(handles.Size(), &handles.Front(), FALSE, INFINITE); + /* + if (curTime > 5 * 1000) + progs.ProgNames.Clear(); + */ - if (waitResult >= (DWORD)handles.Size() - 1) - { - processes.CloseAll(); - return waitResult >= (DWORD)handles.Size() ? 1 : 0; + needFindProcessByPath = (curTime < 2 * 1000); + + if (needFindProcessByPath) + { + NFind::CFileInfo newFileInfo; + if (newFileInfo.Find(tpi->FilePath)) + if (tpi->WasChanged(newFileInfo)) + needFindProcessByPath = false; + } + + DEBUG_PRINT_NUM(" -- firstPass -- time = ", curTime) + } + + processes.DisableWait(indices[waitResult]); } - processes.Update(); - processes.DisableWait(indices[waitResult]); + + firstPass = false; + + // Sleep(300); + #ifndef UNDER_CE + processes.Update(needFindProcessByPath /* , progs */); + #endif } - NFind::CFileInfo newFileInfo; - if (newFileInfo.Find(tpi->FilePath)) + + DWORD curTime = GetTickCount() - startTime; + + DEBUG_PRINT_NUM("after time = ", curTime) + + processes.CloseAll(); + + isComplexMode = (curTime < 2 * 1000); + + } + + bool needCheckTimestamp = true; + + for (;;) { - if (tpi->WasChanged(newFileInfo)) + NFind::CFileInfo newFileInfo; + + if (!newFileInfo.Find(tpi->FilePath)) + break; + + if (mainProcessWasSet) { - UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, tpi->RelPath); - if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) + if (tpi->WasChanged(newFileInfo)) { - if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1) + UString m = MyFormatNew(IDS_CANNOT_UPDATE_FILE, fs2us(tpi->FilePath)); + if (tpi->ReadOnly) { - ::MessageBoxW(g_HWND, MyFormatNew(IDS_CANNOT_UPDATE_FILE, - fs2us(tpi->FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP); + m.Add_LF(); + AddLangString(m, IDS_PROP_READ_ONLY); + m.Add_LF(); + m += tpi->FullPathFolderPrefix; + ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP); return 0; } + { + const UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, tpi->RelPath); + if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK) + { + // DEBUG_PRINT_NUM("SendMessage", GetCurrentThreadId()); + if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1) + { + ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP); + return 0; + } + } + needCheckTimestamp = false; + break; + } } + + if (!isComplexMode) + break; } + + // DEBUG_PRINT("WaitForSingleObject"); + DWORD waitResult = ::WaitForSingleObject(g_ExitEventLauncher._exitEvent, INFINITE); + // DEBUG_PRINT("---"); + + if (waitResult == WAIT_OBJECT_0) + break; + + return 1; } - tpi->DeleteDirAndFile(); + + { + NFind::CFileInfo newFileInfo; + + bool finded = newFileInfo.Find(tpi->FilePath); + + if (!needCheckTimestamp || !finded || !tpi->WasChanged(newFileInfo)) + { + DEBUG_PRINT("Delete Temp file"); + tpi->DeleteDirAndFile(); + } + } + return 0; } + + #if defined(_WIN32) && !defined(UNDER_CE) static const FChar *k_ZoneId_StreamName = FTEXT(":Zone.Identifier"); #endif @@ -1284,6 +1710,7 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo tpi->NeedDelete = true; tpi->UsePassword = usePassword; tpi->Password = password; + tpi->ReadOnly = IsThereReadOnlyFolder(); if (!tpi->FileInfo.Find(tempFilePath)) return; @@ -1291,29 +1718,41 @@ void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bo CTmpProcessInfoRelease tmpProcessInfoRelease(*tpi); CProcess process; - // HRESULT res; + HRESULT res; if (editMode) - /* res = */ StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); + res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); else - /* res = */ StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); + res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); - if ((HANDLE)process == 0) - return; + if ((HANDLE)process == NULL) + { + // win7 / win10 work so for some extensions (pdf, html ..); + DEBUG_PRINT("#### (HANDLE)process == 0"); + // return; + if (res != SZ_OK) + return; + } tpi->Window = (HWND)(*this); tpi->FullPathFolderPrefix = _currentFolderPrefix; tpi->FileIndex = index; tpi->RelPath = relPath; - tpi->Processes.AddProcess(process.Detach()); + + if ((HANDLE)process != 0) + tpi->Processes.SetMainProcess(process.Detach()); - NWindows::CThread thread; - if (thread.Create(MyThreadFunction, tpi) != S_OK) + ::CThread th; + if (Thread_Create(&th, MyThreadFunction, tpi) != 0) throw 271824; + g_ExitEventLauncher._threads.Add(th); + g_ExitEventLauncher._numActiveThreads++; + tempDirectory.DisableDeleting(); tmpProcessInfoPtr.release(); tmpProcessInfoRelease._needDelete = false; } + /* static const UINT64 kTimeLimit = UINT64(10000000) * 3600 * 24; diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp index c87d04e1..26aa0b2f 100644 --- a/CPP/7zip/UI/FileManager/PanelKey.cpp +++ b/CPP/7zip/UI/FileManager/PanelKey.cpp @@ -18,7 +18,7 @@ struct CVKeyPropIDPair PROPID PropID; }; -static CVKeyPropIDPair g_VKeyPropIDPairs[] = +static const CVKeyPropIDPair g_VKeyPropIDPairs[] = { { VK_F3, kpidName }, { VK_F4, kpidExtension }, diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp index 84dada2b..9cc76c36 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.cpp +++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp @@ -18,21 +18,24 @@ static const TCHAR *kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("F // static const TCHAR *kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM"); static const WCHAR *kLangValueName = L"Lang"; + static const WCHAR *kViewer = L"Viewer"; static const WCHAR *kEditor = L"Editor"; static const WCHAR *kDiff = L"Diff"; + static const TCHAR *kShowDots = TEXT("ShowDots"); static const TCHAR *kShowRealFileIcons = TEXT("ShowRealFileIcons"); -static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu"); - static const TCHAR *kFullRow = TEXT("FullRow"); static const TCHAR *kShowGrid = TEXT("ShowGrid"); -static const TCHAR *kAlternativeSelection = TEXT("AlternativeSelection"); -// static const TCHAR *kLockMemoryAdd = TEXT("LockMemoryAdd"); -static const TCHAR *kLargePagesEnable = TEXT("LargePages"); static const TCHAR *kSingleClick = TEXT("SingleClick"); +static const TCHAR *kAlternativeSelection = TEXT("AlternativeSelection"); // static const TCHAR *kUnderline = TEXT("Underline"); +static const TCHAR *kShowSystemMenu = TEXT("ShowSystemMenu"); + +// static const TCHAR *kLockMemoryAdd = TEXT("LockMemoryAdd"); +static const TCHAR *kLargePages = TEXT("LargePages"); + static const TCHAR *kFlatViewName = TEXT("FlatViewArc"); // static const TCHAR *kShowDeletedFiles = TEXT("ShowDeleted"); @@ -86,16 +89,11 @@ static bool Read7ZipOption(const TCHAR *value, bool defaultValue) return defaultValue; } -static bool ReadOption(const TCHAR *value, bool defaultValue) +static void ReadOption(CKey &key, const TCHAR *value, bool &dest) { - CKey key; - if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS) - { - bool enabled; - if (key.QueryValue(value, enabled) == ERROR_SUCCESS) - return enabled; - } - return defaultValue; + bool enabled = false; + if (key.QueryValue(value, enabled) == ERROR_SUCCESS) + dest = enabled; } /* @@ -119,37 +117,52 @@ static bool ReadLmOption(const TCHAR *value, bool defaultValue) } */ -void SaveShowDots(bool showDots) { SaveOption(kShowDots, showDots); } -bool ReadShowDots() { return ReadOption(kShowDots, false); } - -void SaveShowRealFileIcons(bool show) { SaveOption(kShowRealFileIcons, show); } -bool ReadShowRealFileIcons() { return ReadOption(kShowRealFileIcons, false); } - -void Save_ShowSystemMenu(bool show) { SaveOption(kShowSystemMenu, show); } -bool Read_ShowSystemMenu(){ return ReadOption(kShowSystemMenu, false); } - -void SaveFullRow(bool enable) { SaveOption(kFullRow, enable); } -bool ReadFullRow() { return ReadOption(kFullRow, false); } +void CFmSettings::Save() const +{ + SaveOption(kShowDots, ShowDots); + SaveOption(kShowRealFileIcons, ShowRealFileIcons); + SaveOption(kFullRow, FullRow); + SaveOption(kShowGrid, ShowGrid); + SaveOption(kSingleClick, SingleClick); + SaveOption(kAlternativeSelection, AlternativeSelection); + // SaveOption(kUnderline, Underline); + + SaveOption(kShowSystemMenu, ShowSystemMenu); +} -void SaveShowGrid(bool enable) { SaveOption(kShowGrid, enable); } -bool ReadShowGrid(){ return ReadOption(kShowGrid, false); } +void CFmSettings::Load() +{ + ShowDots = false; + ShowRealFileIcons = false; + FullRow = false; + ShowGrid = false; + SingleClick = false; + AlternativeSelection = false; + // Underline = false; -void SaveAlternativeSelection(bool enable) { SaveOption(kAlternativeSelection, enable); } -bool ReadAlternativeSelection(){ return ReadOption(kAlternativeSelection, false); } + ShowSystemMenu = false; -void SaveSingleClick(bool enable) { SaveOption(kSingleClick, enable); } -bool ReadSingleClick(){ return ReadOption(kSingleClick, false); } + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS) + { + ReadOption(key, kShowDots, ShowDots); + ReadOption(key, kShowRealFileIcons, ShowRealFileIcons); + ReadOption(key, kFullRow, FullRow); + ReadOption(key, kShowGrid, ShowGrid); + ReadOption(key, kSingleClick, SingleClick); + ReadOption(key, kAlternativeSelection, AlternativeSelection); + // ReadOption(key, kUnderline, Underline); + + ReadOption(key, kShowSystemMenu, ShowSystemMenu ); + } +} -/* -void SaveUnderline(bool enable) { SaveOption(kUnderline, enable); } -bool ReadUnderline(){ return ReadOption(kUnderline, false); } -*/ // void SaveLockMemoryAdd(bool enable) { SaveLmOption(kLockMemoryAdd, enable); } // bool ReadLockMemoryAdd() { return ReadLmOption(kLockMemoryAdd, true); } -void SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePagesEnable, enable); } -bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePagesEnable, false); } +void SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePages, enable); } +bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePages, false); } static CSysString GetFlatViewName(UInt32 panelIndex) { @@ -159,7 +172,15 @@ static CSysString GetFlatViewName(UInt32 panelIndex) } void SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); } -bool ReadFlatView(UInt32 panelIndex) { return ReadOption(GetFlatViewName(panelIndex), false); } + +bool ReadFlatView(UInt32 panelIndex) +{ + bool enabled = false; + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS) + ReadOption(key, GetFlatViewName(panelIndex), enabled); + return enabled; +} /* void Save_ShowDeleted(bool enable) { SaveOption(kShowDeletedFiles, enable); } diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h index 678a3375..b731778b 100644 --- a/CPP/7zip/UI/FileManager/RegistryUtils.h +++ b/CPP/7zip/UI/FileManager/RegistryUtils.h @@ -15,23 +15,21 @@ void ReadRegEditor(bool useEditor, UString &path); void SaveRegDiff(const UString &path); void ReadRegDiff(UString &path); -void SaveShowDots(bool showDots); -bool ReadShowDots(); - -void SaveShowRealFileIcons(bool show); -bool ReadShowRealFileIcons(); - -void Save_ShowSystemMenu(bool showSystemMenu); -bool Read_ShowSystemMenu(); - -void SaveFullRow(bool enable); -bool ReadFullRow(); - -void SaveShowGrid(bool enable); -bool ReadShowGrid(); - -void SaveAlternativeSelection(bool enable); -bool ReadAlternativeSelection(); +struct CFmSettings +{ + bool ShowDots; + bool ShowRealFileIcons; + bool FullRow; + bool ShowGrid; + bool SingleClick; + bool AlternativeSelection; + // bool Underline; + + bool ShowSystemMenu; + + void Save() const; + void Load(); +}; // void SaveLockMemoryAdd(bool enable); // bool ReadLockMemoryAdd(); @@ -39,14 +37,6 @@ bool ReadAlternativeSelection(); bool ReadLockMemoryEnable(); void SaveLockMemoryEnable(bool enable); -void SaveSingleClick(bool enable); -bool ReadSingleClick(); - -/* -void SaveUnderline(bool enable); -bool ReadUnderline(); -*/ - void SaveFlatView(UInt32 panelIndex, bool enable); bool ReadFlatView(UInt32 panelIndex); diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index cecaf808..07121b28 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -35,21 +35,29 @@ extern bool IsLargePageSupported(); bool CSettingsPage::OnInit() { + _wasChanged = false; + _largePages_wasChanged = false; + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - CheckButton(IDX_SETTINGS_SHOW_DOTS, ReadShowDots()); - CheckButton(IDX_SETTINGS_SHOW_SYSTEM_MENU, Read_ShowSystemMenu()); - CheckButton(IDX_SETTINGS_SHOW_REAL_FILE_ICONS, ReadShowRealFileIcons()); - CheckButton(IDX_SETTINGS_FULL_ROW, ReadFullRow()); - CheckButton(IDX_SETTINGS_SHOW_GRID, ReadShowGrid()); - CheckButton(IDX_SETTINGS_ALTERNATIVE_SELECTION, ReadAlternativeSelection()); + CFmSettings st; + st.Load(); + + CheckButton(IDX_SETTINGS_SHOW_DOTS, st.ShowDots); + CheckButton(IDX_SETTINGS_SHOW_REAL_FILE_ICONS, st.ShowRealFileIcons); + CheckButton(IDX_SETTINGS_FULL_ROW, st.FullRow); + CheckButton(IDX_SETTINGS_SHOW_GRID, st.ShowGrid); + CheckButton(IDX_SETTINGS_SINGLE_CLICK, st.SingleClick); + CheckButton(IDX_SETTINGS_ALTERNATIVE_SELECTION, st.AlternativeSelection); + // CheckButton(IDX_SETTINGS_UNDERLINE, st.Underline); + + CheckButton(IDX_SETTINGS_SHOW_SYSTEM_MENU, st.ShowSystemMenu); + if (IsLargePageSupported()) CheckButton(IDX_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); else EnableItem(IDX_SETTINGS_LARGE_PAGES, false); - CheckButton(IDX_SETTINGS_SINGLE_CLICK, ReadSingleClick()); - // CheckButton(IDX_SETTINGS_UNDERLINE, ReadUnderline()); - + // EnableSubItems(); return CPropertyPage::OnInit(); @@ -64,25 +72,37 @@ void CSettingsPage::EnableSubItems() LONG CSettingsPage::OnApply() { - SaveShowDots(IsButtonCheckedBool(IDX_SETTINGS_SHOW_DOTS)); - Save_ShowSystemMenu(IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU)); - SaveShowRealFileIcons(IsButtonCheckedBool(IDX_SETTINGS_SHOW_REAL_FILE_ICONS)); - - SaveFullRow(IsButtonCheckedBool(IDX_SETTINGS_FULL_ROW)); - SaveShowGrid(IsButtonCheckedBool(IDX_SETTINGS_SHOW_GRID)); - SaveAlternativeSelection(IsButtonCheckedBool(IDX_SETTINGS_ALTERNATIVE_SELECTION)); + if (_wasChanged) + { + CFmSettings st; + st.ShowDots = IsButtonCheckedBool(IDX_SETTINGS_SHOW_DOTS); + st.ShowRealFileIcons = IsButtonCheckedBool(IDX_SETTINGS_SHOW_REAL_FILE_ICONS); + st.FullRow = IsButtonCheckedBool(IDX_SETTINGS_FULL_ROW); + st.ShowGrid = IsButtonCheckedBool(IDX_SETTINGS_SHOW_GRID); + st.SingleClick = IsButtonCheckedBool(IDX_SETTINGS_SINGLE_CLICK); + st.AlternativeSelection = IsButtonCheckedBool(IDX_SETTINGS_ALTERNATIVE_SELECTION); + // st.Underline = IsButtonCheckedBool(IDX_SETTINGS_UNDERLINE); + + st.ShowSystemMenu = IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU); + + st.Save(); + + _wasChanged = false; + } + #ifndef UNDER_CE - if (IsLargePageSupported()) + if (_largePages_wasChanged) { - bool enable = IsButtonCheckedBool(IDX_SETTINGS_LARGE_PAGES); - NSecurity::EnablePrivilege_LockMemory(enable); - SaveLockMemoryEnable(enable); + if (IsLargePageSupported()) + { + bool enable = IsButtonCheckedBool(IDX_SETTINGS_LARGE_PAGES); + NSecurity::EnablePrivilege_LockMemory(enable); + SaveLockMemoryEnable(enable); + } + _largePages_wasChanged = false; } #endif - SaveSingleClick(IsButtonCheckedBool(IDX_SETTINGS_SINGLE_CLICK)); - // SaveUnderline(IsButtonCheckedBool(IDX_SETTINGS_UNDERLINE)); - return PSNRET_NOERROR; } @@ -106,9 +126,17 @@ bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) case IDX_SETTINGS_FULL_ROW: case IDX_SETTINGS_SHOW_GRID: case IDX_SETTINGS_ALTERNATIVE_SELECTION: + _wasChanged = true; + break; + case IDX_SETTINGS_LARGE_PAGES: - Changed(); - return true; + _largePages_wasChanged = true; + break; + + default: + return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } - return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); + + Changed(); + return true; } diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h index e7e5d73e..77cc67b9 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.h +++ b/CPP/7zip/UI/FileManager/SettingsPage.h @@ -8,6 +8,10 @@ class CSettingsPage: public NWindows::NControl::CPropertyPage { + bool _wasChanged; + + bool _largePages_wasChanged; + // void EnableSubItems(); bool OnButtonClicked(int buttonID, HWND buttonHWND); public: diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc index 66629612..277f45d5 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage2.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc @@ -2,10 +2,12 @@ CAPTION "Settings" BEGIN CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10 CONTROL "Show real file &icons", IDX_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX, m, 22, xc, 10 - CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 36, xc, 10 - CONTROL "&Full row select", IDX_SETTINGS_FULL_ROW, MY_CHECKBOX, m, 50, xc, 10 - CONTROL "Show &grid lines", IDX_SETTINGS_SHOW_GRID, MY_CHECKBOX, m, 64, xc, 10 - CONTROL "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, m, 78, xc, 10 - CONTROL "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, m, 92, xc, 10 - CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 106, xc, 10 + CONTROL "&Full row select", IDX_SETTINGS_FULL_ROW, MY_CHECKBOX, m, 36, xc, 10 + CONTROL "Show &grid lines", IDX_SETTINGS_SHOW_GRID, MY_CHECKBOX, m, 50, xc, 10 + CONTROL "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, m, 64, xc, 10 + CONTROL "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, m, 78, xc, 10 + + CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 100, xc, 10 + + CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 122, xc, 10 END diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp index d60d7b4f..5214a55c 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.cpp +++ b/CPP/7zip/UI/FileManager/SystemPage.cpp @@ -6,8 +6,8 @@ #include <ShlObj.h> -#include "../../../Common/StringConvert.h" #include "../../../Common/Defs.h" +#include "../../../Common/StringConvert.h" #include "../../../Windows/DLL.h" #include "../../../Windows/ErrorMsg.h" @@ -43,13 +43,16 @@ CSysString CModifiedExtInfo::GetString() const return ProgramKey; }; + int CSystemPage::AddIcon(const UString &iconPath, int iconIndex) { if (iconPath.IsEmpty()) return -1; if (iconIndex == -1) iconIndex = 0; + HICON hicon; + #ifdef UNDER_CE ExtractIconExW(iconPath, iconIndex, NULL, &hicon, 1); if (!hicon) @@ -65,12 +68,14 @@ int CSystemPage::AddIcon(const UString &iconPath, int iconIndex) if (num != 1 || !hicon) #endif return -1; + _imageList.AddIcon(hicon); DestroyIcon(hicon); return _numIcons++; } -void CSystemPage::RefreshListItem(int group, int listIndex) + +void CSystemPage::RefreshListItem(unsigned group, unsigned listIndex) { const CAssoc &assoc = _items[GetRealIndex(listIndex)]; _listView.SetSubItem(listIndex, group + 1, assoc.Pair[group].GetString()); @@ -82,13 +87,14 @@ void CSystemPage::RefreshListItem(int group, int listIndex) _listView.SetItem(&newItem); } -void CSystemPage::ChangeState(int group, const CIntVector &indices) + +void CSystemPage::ChangeState(unsigned group, const CUIntVector &indices) { if (indices.IsEmpty()) return; bool thereAreClearItems = false; - int counters[3] = { 0, 0, 0 }; + unsigned counters[3] = { 0, 0, 0 }; unsigned i; for (i = 0; i < indices.Size(); i++) @@ -114,27 +120,34 @@ void CSystemPage::ChangeState(int group, const CIntVector &indices) for (i = 0; i < indices.Size(); i++) { - int listIndex = indices[i]; + unsigned listIndex = indices[i]; CAssoc &assoc = _items[GetRealIndex(listIndex)]; CModifiedExtInfo &mi = assoc.Pair[group]; bool change = false; + switch (state) { case kExtState_Clear: change = true; break; case kExtState_Other: change = mi.Other; break; default: change = !(mi.Other && thereAreClearItems); break; } + if (change) { mi.State = state; RefreshListItem(group, listIndex); } } + + _needSave = true; Changed(); } + bool CSystemPage::OnInit() { + _needSave = false; + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); _listView.Attach(GetItem(IDL_SYSTEM_ASSOCIATE)); @@ -159,6 +172,7 @@ bool CSystemPage::OnInit() BOOL res; DWORD size = kSize; + #ifndef _UNICODE if (!g_IsNT) { @@ -218,7 +232,7 @@ bool CSystemPage::OnInit() assoc.SevenZipImageIndex = AddIcon(plug.IconPath, plug.IconIndex); CSysString texts[NUM_EXT_GROUPS]; - int g; + unsigned g; for (g = 0; g < NUM_EXT_GROUPS; g++) { CModifiedExtInfo &mi = assoc.Pair[g]; @@ -240,62 +254,83 @@ bool CSystemPage::OnInit() return CPropertyPage::OnInit(); } + static UString GetProgramCommand() { - return L"\"" + fs2us(NDLL::GetModuleDirPrefix()) + L"7zFM.exe\" \"%1\""; + UString s = L"\""; + s += fs2us(NDLL::GetModuleDirPrefix()); + s.AddAscii("7zFM.exe\" \"%1\""); + return s; } + LONG CSystemPage::OnApply() { + if (!_needSave) + return PSNRET_NOERROR; + const UString command = GetProgramCommand(); LONG res = 0; FOR_VECTOR (listIndex, _extDB.Exts) { - int realIndex = GetRealIndex(listIndex); + unsigned realIndex = GetRealIndex(listIndex); const CExtPlugins &extInfo = _extDB.Exts[realIndex]; CAssoc &assoc = _items[realIndex]; - for (int g = 0; g < NUM_EXT_GROUPS; g++) + for (unsigned g = 0; g < NUM_EXT_GROUPS; g++) { CModifiedExtInfo &mi = assoc.Pair[g]; HKEY key = GetHKey(g); + if (mi.OldState != mi.State) { LONG res2 = 0; + if (mi.State == kExtState_7Zip) { - UString title = extInfo.Ext + UString(L" Archive"); + UString title = extInfo.Ext; + title.AddAscii(" Archive"); const CPluginToIcon &plug = extInfo.Plugins[0]; res2 = NRegistryAssoc::AddShellExtensionInfo(key, GetSystemString(extInfo.Ext), title, command, plug.IconPath, plug.IconIndex); } else if (mi.State == kExtState_Clear) res2 = NRegistryAssoc::DeleteShellExtensionInfo(key, GetSystemString(extInfo.Ext)); + if (res == 0) res = res2; if (res2 == 0) mi.OldState = mi.State; + mi.State = mi.OldState; RefreshListItem(g, listIndex); } } } + #ifndef UNDER_CE SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); - WasChanged = true; #endif + + WasChanged = true; + + _needSave = false; + if (res != 0) MessageBoxW(*this, NError::MyFormatMessage(res), L"7-Zip", MB_ICONERROR); + return PSNRET_NOERROR; } + void CSystemPage::OnNotifyHelp() { ShowHelpWindow(NULL, kSystemTopic); } + bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch (buttonID) @@ -313,6 +348,7 @@ bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND) return CPropertyPage::OnButtonClicked(buttonID, buttonHWND); } + bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) { if (lParam->hwndFrom == HWND(_listView)) @@ -324,7 +360,7 @@ bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) ChangeState(0); return true; } - break; + case NM_CLICK: { #ifdef UNDER_CE @@ -334,12 +370,12 @@ bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) if (item->uKeyFlags == 0) #endif { - int realIndex = GetRealIndex(item->iItem); - if (realIndex >= 0) + if (item->iItem >= 0) { + // unsigned realIndex = GetRealIndex(item->iItem); if (item->iSubItem >= 1 && item->iSubItem <= 2) { - CIntVector indices; + CUIntVector indices; indices.Add(item->iItem); ChangeState(item->iSubItem < 2 ? 0 : 1, indices); } @@ -347,12 +383,14 @@ bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) } break; } + case LVN_KEYDOWN: { if (OnListKeyDown(LPNMLVKEYDOWN(lParam))) return true; break; } + /* case NM_RCLICK: case NM_DBLCLK: @@ -366,18 +404,23 @@ bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam) return CPropertyPage::OnNotify(controlID, lParam); } -void CSystemPage::ChangeState(int group) + +void CSystemPage::ChangeState(unsigned group) { - CIntVector indices; + CUIntVector indices; + int itemIndex = -1; while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1) indices.Add(itemIndex); + if (indices.IsEmpty()) FOR_VECTOR (i, _items) indices.Add(i); + ChangeState(group, indices); } + bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) { bool ctrl = IsKeyDown(VK_CONTROL); @@ -386,8 +429,8 @@ bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) if (alt) return false; - if ((ctrl && keyDownInfo->wVKey == 'A') || - (!ctrl && keyDownInfo->wVKey == VK_MULTIPLY)) + if ((ctrl && keyDownInfo->wVKey == 'A') + || (!ctrl && keyDownInfo->wVKey == VK_MULTIPLY)) { _listView.SelectAll(); return true; @@ -400,15 +443,19 @@ bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo) case VK_SUBTRACT: case VK_SEPARATOR: case VK_DIVIDE: + #ifndef UNDER_CE case VK_OEM_PLUS: case VK_OEM_MINUS: #endif + if (!ctrl) { ChangeState(keyDownInfo->wVKey == VK_SPACE ? 0 : 1); return true; } + break; } + return false; } diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h index d38bd1b0..761a49ac 100644 --- a/CPP/7zip/UI/FileManager/SystemPage.h +++ b/CPP/7zip/UI/FileManager/SystemPage.h @@ -59,7 +59,7 @@ struct CAssoc int GetIconIndex() const { - for (int i = 0; i < 2; i++) + for (unsigned i = 0; i < 2; i++) { const CModifiedExtInfo &pair = Pair[i]; if (pair.State == kExtState_Clear) @@ -84,11 +84,13 @@ class CSystemPage: public NWindows::NControl::CPropertyPage CExtDatabase _extDB; CObjectVector<CAssoc> _items; - int _numIcons; + unsigned _numIcons; NWindows::NControl::CImageList _imageList; NWindows::NControl::CListView _listView; - const HKEY GetHKey(int + bool _needSave; + + const HKEY GetHKey(unsigned #if NUM_EXT_GROUPS != 1 group #endif @@ -102,15 +104,16 @@ class CSystemPage: public NWindows::NControl::CPropertyPage } int AddIcon(const UString &path, int iconIndex); - int GetRealIndex(int listIndex) const { return listIndex; } - void RefreshListItem(int group, int listIndex); - void ChangeState(int group, const CIntVector &indices); - void ChangeState(int group); + unsigned GetRealIndex(unsigned listIndex) const { return listIndex; } + void RefreshListItem(unsigned group, unsigned listIndex); + void ChangeState(unsigned group, const CUIntVector &indices); + void ChangeState(unsigned group); bool OnListKeyDown(LPNMLVKEYDOWN keyDownInfo); public: bool WasChanged; + CSystemPage(): WasChanged(false) {} virtual bool OnInit(); diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h index 2430230b..02308555 100644 --- a/CPP/Common/MyString.h +++ b/CPP/Common/MyString.h @@ -303,7 +303,7 @@ public: void SetFrom_CalcLen(const char *s, unsigned len); // void SetFromAscii(const char *s) { operator+=(s); } - // AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } + AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); } AString Left(unsigned count) const { return AString(count, *this); } // void MakeUpper() { MyStringUpper(_chars); } diff --git a/CPP/Windows/Control/Trackbar.h b/CPP/Windows/Control/Trackbar.h index c6d31112..313e0c85 100644 --- a/CPP/Windows/Control/Trackbar.h +++ b/CPP/Windows/Control/Trackbar.h @@ -4,23 +4,22 @@ #define __WINDOWS_CONTROL_TRACKBAR_H #include "../Window.h" -#include "../Defs.h" namespace NWindows { namespace NControl { -class CTrackbar1: public CWindow +class CTrackbar: public CWindow { public: void SetRange(int minimum, int maximum, bool redraw = true) - { SendMessage(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } + { SendMsg(TBM_SETRANGE, BoolToBOOL(redraw), MAKELONG(minimum, maximum)); } void SetPos(int pos, bool redraw = true) - { SendMessage(TBM_SETPOS, BoolToBOOL(redraw), pos); } + { SendMsg(TBM_SETPOS, BoolToBOOL(redraw), pos); } void SetTicFreq(int freq) - { SendMessage(TBM_SETTICFREQ, freq); } + { SendMsg(TBM_SETTICFREQ, freq); } int GetPos() - { return (int)SendMessage(TBM_GETPOS); } + { return (int)SendMsg(TBM_GETPOS); } }; }} diff --git a/DOC/7zip.inf b/DOC/7zip.inf index 2e6f722a..aabe2246 100644 --- a/DOC/7zip.inf +++ b/DOC/7zip.inf @@ -10,8 +10,8 @@ AppName = "7-Zip" InstallDir = %CE1%\%AppName% [Strings] -AppVer = "15.12" -AppDate = "2015-11-19" +AppVer = "15.13" +AppDate = "2015-12-31" [CEDevice] ; ProcessorType = 2577 ; ARM diff --git a/DOC/7zip.nsi b/DOC/7zip.nsi index 55d7af41..b166b429 100644 --- a/DOC/7zip.nsi +++ b/DOC/7zip.nsi @@ -2,7 +2,7 @@ ;Defines !define VERSION_MAJOR 15 -!define VERSION_MINOR 12 +!define VERSION_MINOR 13 !define VERSION_POSTFIX_FULL "" !ifdef WIN64 !ifdef IA64 @@ -262,6 +262,7 @@ Section File uz.txt File va.txt File vi.txt + File yo.txt File zh-cn.txt File zh-tw.txt @@ -464,6 +465,7 @@ Section Uninstall Delete $INSTDIR\Lang\va.txt Delete $INSTDIR\Lang\vi.txt Delete $INSTDIR\Lang\vr.txt + Delete $INSTDIR\Lang\yo.txt Delete $INSTDIR\Lang\zh-cn.txt Delete $INSTDIR\Lang\zh-tw.txt diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index 8f430923..2f9e01fc 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ <?xml version="1.0"?> <?define VerMajor = "15" ?> -<?define VerMinor = "12" ?> +<?define VerMinor = "13" ?> <?define VerBuild = "00" ?> <?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?> <?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?> @@ -335,6 +335,7 @@ <File Id="uz.txt" Name="uz.txt" /> <File Id="va.txt" Name="va.txt" /> <File Id="vi.txt" Name="vi.txt" /> + <File Id="yo.txt" Name="yo.txt" /> <File Id="zh_cn.txt" Name="zh-cn.txt" /> <File Id="zh_tw.txt" Name="zh-tw.txt" /> </Component> diff --git a/DOC/readme.txt b/DOC/readme.txt index db7b229d..b1f8d93f 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 15.12 Sources +7-Zip 15.13 Sources ------------------- 7-Zip is a file archiver for Windows. |