void StdOut_Convert_UString_to_AString(const UString &s, AString &temp) { int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, temp); else UnicodeStringToMultiByte2(temp, s, (UINT)codePage); }
CStdOutStream & CStdOutStream::operator<<(const wchar_t *s) { int codePage = g_CodePage; if (codePage == -1) codePage = CP_OEMCP; AString dest; if (codePage == CP_UTF8) ConvertUnicodeToUTF8(s, dest); else UnicodeStringToMultiByte2(dest, s, (UINT)codePage); return operator<<((const char *)dest); }
int WINAPI SevenZipSfxConfigDialog(HWND _hwnd, LPSTR _szBuffer, DWORD _dwSize) { CSfxDialog dlgSfx(_hwnd); if (dlgSfx.DoModal() == IDCANCEL) { g_StdOut.SetLastError(ERROR_USER_CANCEL); return -1; } AString utf8String; ConvertUnicodeToUTF8(dlgSfx.GetConfigText(), utf8String); ::lstrcpynA(_szBuffer, utf8String, _dwSize); return g_StdOut.SetLastError((DWORD)utf8String.Len() < _dwSize ? 0 : ERROR_INVALID_VALUE); }
AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) { if ((global_use_utf16_conversion) && (!srcString.IsEmpty())) { AString resultString; ConvertUnicodeToUTF8(srcString,resultString); return resultString; } AString resultString; for (int i = 0; i < srcString.Len(); i++) { if (srcString[i] >= 256) resultString += '?'; else resultString += char(srcString[i]); } return resultString; }
HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database) { if (ReadUInt32() != 1) // version return S_FALSE; if (ReadUInt32() != 0x28) // Location of header section table return S_FALSE; UInt32 numHeaderSections = ReadUInt32(); const unsigned kNumHeaderSectionsMax = 5; if (numHeaderSections != kNumHeaderSectionsMax) return S_FALSE; IsArc = true; ReadUInt32(); // Len of post-header table Byte g[16]; ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754} // header section table UInt64 sectionOffsets[kNumHeaderSectionsMax]; UInt64 sectionSizes[kNumHeaderSectionsMax]; UInt32 i; for (i = 0; i < numHeaderSections; i++) { sectionOffsets[i] = ReadUInt64(); sectionSizes[i] = ReadUInt64(); UInt64 end = sectionOffsets[i] + sectionSizes[i]; database.UpdatePhySize(end); } // Post-Header ReadUInt32(); // 2 ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header) // ----- Directory information ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1 ReadUInt64(); // Chunk number of first AOLL chunk in directory ReadUInt64(); // Chunk number of last AOLL chunk in directory ReadUInt64(); // 0 (unknown) ReadUInt32(); // $2000 (Directory chunk size of directory) ReadUInt32(); // Quickref density for main directory, usually 2 ReadUInt32(); // 0 (unknown) ReadUInt32(); // Depth of main directory index tree // 1 there is no index, 2 if there is one level of AOLI chunks. ReadUInt64(); // 0 (unknown) UInt64 numDirEntries = ReadUInt64(); // Number of directory entries // ----- Directory Index Information ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index) ReadUInt64(); // Chunk number of first AOLL chunk in directory index ReadUInt64(); // Chunk number of last AOLL chunk in directory index ReadUInt64(); // 0 (unknown) ReadUInt32(); // $200 (Directory chunk size of directory index) ReadUInt32(); // Quickref density for directory index, usually 2 ReadUInt32(); // 0 (unknown) ReadUInt32(); // Depth of directory index index tree. ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0. ReadUInt64(); // Number of directory index entries (same as number of AOLL // chunks in main directory) // (The obvious guess for the following two fields, which recur in a number // of places, is they are maximum sizes for the directory and directory index. // However, I have seen no direct evidence that this is the case.) ReadUInt32(); // $100000 (Same as field following chunk size in directory) ReadUInt32(); // $20000 (Same as field following chunk size in directory index) ReadUInt64(); // 0 (unknown) if (ReadUInt32() != kSignature_CAOL) return S_FALSE; if (ReadUInt32() != 2) // (Most likely a version number) return S_FALSE; UInt32 caolLength = ReadUInt32(); // $50 (Len of the CAOL section, which includes the ITSF section) if (caolLength >= 0x2C) { /* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built. // Does not appear to be a checksum. Many files have // 'HH' (HTML Help?) here, indicating this may be a compiler ID // field. But at least one ITOL/ITLS compiler does not set this // field to a constant value. ReadUInt16(); // 0 (Unknown. Possibly part of 00A4 field) ReadUInt32(); // Unknown. Two values have been seen -- $43ED, and 0. ReadUInt32(); // $2000 (Directory chunk size of directory) ReadUInt32(); // $200 (Directory chunk size of directory index) ReadUInt32(); // $100000 (Same as field following chunk size in directory) ReadUInt32(); // $20000 (Same as field following chunk size in directory index) ReadUInt32(); // 0 (unknown) ReadUInt32(); // 0 (Unknown) if (caolLength == 0x2C) { // fprintf(stdout, "\n !!!NewFormat\n"); // fflush(stdout); database.ContentOffset = 0; // maybe we must add database.StartPosition here? database.NewFormat = true; } else if (caolLength == 0x50) { ReadUInt32(); // 0 (Unknown) if (ReadUInt32() != kSignature_ITSF) return S_FALSE; if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3) return S_FALSE; if (ReadUInt32() != 0x20) // $20 (length of ITSF) return S_FALSE; UInt32 unknown = ReadUInt32(); if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases; return S_FALSE; database.ContentOffset = database.StartPosition + ReadUInt64(); /* UInt32 timeStamp = */ ReadUInt32(); // A timestamp of some sort. // Considered as a big-endian DWORD, it appears to contain // seconds (MSB) and fractional seconds (second byte). // The third and fourth bytes may contain even more fractional // bits. The 4 least significant bits in the last byte are constant. /* UInt32 lang = */ ReadUInt32(); // BE? } else return S_FALSE; } // Section 0 ReadChunk(inStream, database.StartPosition + sectionOffsets[0], sectionSizes[0]); if (sectionSizes[0] < 0x18) return S_FALSE; if (ReadUInt32() != 0x01FE) return S_FALSE; ReadUInt32(); // unknown: 0 UInt64 fileSize = ReadUInt64(); database.UpdatePhySize(fileSize); ReadUInt32(); // unknown: 0 ReadUInt32(); // unknown: 0 // Section 1: The Directory Listing ReadChunk(inStream, database.StartPosition + sectionOffsets[1], sectionSizes[1]); if (ReadUInt32() != kSignature_IFCM) return S_FALSE; if (ReadUInt32() != 1) // (probably a version number) return S_FALSE; UInt32 dirChunkSize = ReadUInt32(); // $2000 if (dirChunkSize < 64) return S_FALSE; ReadUInt32(); // $100000 (unknown) ReadUInt32(); // -1 (unknown) ReadUInt32(); // -1 (unknown) UInt32 numDirChunks = ReadUInt32(); ReadUInt32(); // 0 (unknown, probably high word of above) for (UInt32 ci = 0; ci < numDirChunks; ci++) { UInt64 chunkPos = _inBuffer.GetProcessedSize(); if (ReadUInt32() == kSignature_AOLL) { UInt32 quickrefLength = ReadUInt32(); // Len of quickref area at end of directory chunk if (quickrefLength > dirChunkSize || quickrefLength < 2) return S_FALSE; ReadUInt64(); // Directory chunk number // This must match physical position in file, that is // the chunk size times the chunk number must be the // offset from the end of the directory header. ReadUInt64(); // Chunk number of previous listing chunk when reading // directory in sequence (-1 if first listing chunk) ReadUInt64(); // Chunk number of next listing chunk when reading // directory in sequence (-1 if last listing chunk) ReadUInt64(); // Number of first listing entry in this chunk ReadUInt32(); // 1 (unknown -- other values have also been seen here) ReadUInt32(); // 0 (unknown) unsigned numItems = 0; for (;;) { UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos; UInt32 offsetLimit = dirChunkSize - quickrefLength; if (offset > offsetLimit) return S_FALSE; if (offset == offsetLimit) break; if (database.NewFormat) { UInt16 nameLen = ReadUInt16(); if (nameLen == 0) return S_FALSE; UString name; ReadUString((unsigned)nameLen, name); AString s; ConvertUnicodeToUTF8(name, s); Byte b = ReadByte(); s.Add_Space(); PrintByte(b, s); s.Add_Space(); UInt64 len = ReadEncInt(); // then number of items ? // then length ? // then some data (binary encoding?) while (len-- != 0) { b = ReadByte(); PrintByte(b, s); } database.NewFormatString += s; database.NewFormatString += "\r\n"; } else { RINOK(ReadDirEntry(database)); } numItems++; } Skip(quickrefLength - 2); if (ReadUInt16() != numItems) return S_FALSE; if (numItems > numDirEntries) return S_FALSE; numDirEntries -= numItems; } else Skip(dirChunkSize - 4); } return numDirEntries == 0 ? S_OK : S_FALSE; }
int WINAPI SevenZip(const HWND _hwnd, LPCSTR _szCmdLine, LPSTR _szOutput, const DWORD _dwSize) { if (g_StdOut.GetThread()) return g_StdOut.SetLastError(ERROR_ALREADY_RUNNING); CSplitCmdLine scl; if (!scl.Split(_szCmdLine)) return g_StdOut.SetLastError(ERROR_COMMAND_NAME); NWindows::NFile::NDir::CTempFile sfxFile; if (scl.m_bSfx && scl.IsUpdateCommands()) { CSfxDialog dlgSfx(_hwnd); if (dlgSfx.DoModal() == IDCANCEL) return g_StdOut.SetLastError(ERROR_USER_CANCEL); UInt32 sfxSize, processedSize; NWindows::NFile::NIO::COutFile file; sfxFile.CreateRandomInTempFolder(FTEXT("sfx"), &file); g_StdOut.SetSfxPath(sfxFile.GetPath()); LPVOID lpResource = CSfxDialog::LoadSfxResource(sfxSize); file.Write(lpResource, sfxSize, processedSize); AString utf8String; ConvertUnicodeToUTF8(dlgSfx.GetConfigText(), utf8String); file.Write((const char*)utf8String, utf8String.Len(), processedSize); file.Close(); } g_StdOut.SetCommandLine(scl); UString strCurrentDirectory; if (scl.m_lpBaseDirectory) { ::NWindows::NFile::NDir::GetCurrentDir(strCurrentDirectory); if (::NWindows::NFile::NDir::SetCurrentDir(::MultiByteToUnicodeString(scl.m_lpBaseDirectory, scl.m_codePage)) == false) { g_StdOut << "Base directory isn't found."; g_StdOut.CopyBuf(_szOutput, _dwSize); g_StdOut.ReSet(); return g_StdOut.SetLastError(ERROR_COMMAND_NAME); } } g_StdOut.CreateMainThread(); CProgressDialog dlgProgress(_hwnd); g_StdOut.SetProgressDialog(&dlgProgress); dlgProgress.SetShowDialog(!scl.m_bHide); dlgProgress.SetProgressMode(scl.m_argv[0][0]); dlgProgress.CreateModal(); DWORD dwThreadId; ::WaitForSingleObject(g_StdOut.GetThread(), INFINITE); ::GetExitCodeThread(g_StdOut.GetThread(), &dwThreadId); ::CloseHandle(g_StdOut.GetThread()); g_StdOut.CopyBuf(_szOutput, _dwSize); g_StdOut.ReSet(); g_CodePage = -1; if (scl.m_lpBaseDirectory) ::NWindows::NFile::NDir::SetCurrentDir(strCurrentDirectory); return dwThreadId; }