diff --git a/.editorconfig b/.editorconfig index 3fc88b42..a05d0910 100644 --- a/.editorconfig +++ b/.editorconfig @@ -123,3 +123,72 @@ insert_final_newline=false [*.vb] # Modifier preferences visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion + +[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] + +# Visual C++ Code Style settings + +cpp_generate_documentation_comments = xml + +# Visual C++ Formatting settings +indent_style = space +indent_size = 4 + +cpp_indent_braces = false +cpp_indent_multi_line_relative_to = innermost_parenthesis +cpp_indent_within_parentheses = indent +cpp_indent_preserve_within_parentheses = true +cpp_indent_case_contents = true +cpp_indent_case_labels = false +cpp_indent_case_contents_when_block = false +cpp_indent_lambda_braces_when_parameter = true +cpp_indent_goto_labels = one_left +cpp_indent_preprocessor = leftmost_column +cpp_indent_access_specifiers = false +cpp_indent_namespace_contents = true +cpp_indent_preserve_comments = false +cpp_new_line_before_open_brace_namespace = new_line +cpp_new_line_before_open_brace_type = new_line +cpp_new_line_before_open_brace_function = new_line +cpp_new_line_before_open_brace_block = same_line +cpp_new_line_before_open_brace_lambda = ignore +cpp_new_line_scope_braces_on_separate_lines = false +cpp_new_line_close_brace_same_line_empty_type = false +cpp_new_line_close_brace_same_line_empty_function = false +cpp_new_line_before_catch = true +cpp_new_line_before_else = true +cpp_new_line_before_while_in_do_while = false +cpp_space_before_function_open_parenthesis = remove +cpp_space_within_parameter_list_parentheses = false +cpp_space_between_empty_parameter_list_parentheses = false +cpp_space_after_keywords_in_control_flow_statements = true +cpp_space_within_control_flow_statement_parentheses = false +cpp_space_before_lambda_open_parenthesis = false +cpp_space_within_cast_parentheses = false +cpp_space_after_cast_close_parenthesis = false +cpp_space_within_expression_parentheses = false +cpp_space_before_block_open_brace = true +cpp_space_between_empty_braces = false +cpp_space_before_initializer_list_open_brace = false +cpp_space_within_initializer_list_braces = true +cpp_space_preserve_in_initializer_list = true +cpp_space_before_open_square_bracket = false +cpp_space_within_square_brackets = false +cpp_space_before_empty_square_brackets = false +cpp_space_between_empty_square_brackets = false +cpp_space_group_square_brackets = true +cpp_space_within_lambda_brackets = false +cpp_space_between_empty_lambda_brackets = false +cpp_space_before_comma = false +cpp_space_after_comma = true +cpp_space_remove_around_member_operators = true +cpp_space_before_inheritance_colon = true +cpp_space_before_constructor_colon = true +cpp_space_remove_before_semicolon = true +cpp_space_after_semicolon = false +cpp_space_remove_around_unary_operator = true +cpp_space_around_binary_operator = insert +cpp_space_around_assignment_operator = insert +cpp_space_pointer_reference_alignment = left +cpp_space_around_ternary_operator = insert +cpp_wrap_preserve_blocks = one_liners diff --git a/src/Setup/FxHelper.cpp b/src/Setup/FxHelper.cpp index caa746bc..d7d4bac7 100644 --- a/src/Setup/FxHelper.cpp +++ b/src/Setup/FxHelper.cpp @@ -5,246 +5,244 @@ using std::wstring; class ATL_NO_VTABLE CDownloadProgressCallback : - public CComObjectRoot, - public IBindStatusCallback + public CComObjectRoot, + public IBindStatusCallback { public: - CDownloadProgressCallback() - { - } + CDownloadProgressCallback() + {} - DECLARE_NOT_AGGREGATABLE(CDownloadProgressCallback) + DECLARE_NOT_AGGREGATABLE(CDownloadProgressCallback) + BEGIN_COM_MAP(CDownloadProgressCallback) + COM_INTERFACE_ENTRY(IBindStatusCallback) + END_COM_MAP() + DECLARE_PROTECT_FINAL_CONSTRUCT() - BEGIN_COM_MAP(CDownloadProgressCallback) - COM_INTERFACE_ENTRY(IBindStatusCallback) - END_COM_MAP() + HRESULT FinalConstruct() { return S_OK; } - DECLARE_PROTECT_FINAL_CONSTRUCT() + void FinalRelease() + {} - HRESULT FinalConstruct() { return S_OK; } + void SetProgressDialog(IProgressDialog* pd) + { + m_spProgressDialog = pd; + } - void FinalRelease() - { - } + STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG /*ulStatusCode*/, LPCWSTR /*szStatusText*/) + { + if (m_spProgressDialog != nullptr) { + if (m_spProgressDialog->HasUserCancelled()) { + return E_ABORT; + } - void SetProgressDialog(IProgressDialog* pd) - { - m_spProgressDialog = pd; - } + m_spProgressDialog->SetProgress(ulProgress, ulProgressMax); + } - STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG /*ulStatusCode*/, LPCWSTR /*szStatusText*/) - { - if (m_spProgressDialog != nullptr) { - if (m_spProgressDialog->HasUserCancelled()) { - return E_ABORT; - } + return S_OK; + } - m_spProgressDialog->SetProgress(ulProgress, ulProgressMax); - } - - return S_OK; - } - - STDMETHOD(OnStartBinding)(DWORD /*dwReserved*/, IBinding *pBinding) { return E_NOTIMPL; } - STDMETHOD(GetPriority)(LONG *pnPriority) { return E_NOTIMPL; } - STDMETHOD(OnLowResource)(DWORD /*reserved*/) { return E_NOTIMPL; } - STDMETHOD(OnStopBinding)(HRESULT /*hresult*/, LPCWSTR /*szError*/) { return E_NOTIMPL; } - STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo) { return E_NOTIMPL; } - STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC * /*pformatetc*/, STGMEDIUM *pstgmed) { return E_NOTIMPL; } - STDMETHOD(OnObjectAvailable)(REFIID /*riid*/, IUnknown * /*punk*/) { return E_NOTIMPL; } + STDMETHOD(OnStartBinding)(DWORD /*dwReserved*/, IBinding* pBinding) { return E_NOTIMPL; } + STDMETHOD(GetPriority)(LONG* pnPriority) { return E_NOTIMPL; } + STDMETHOD(OnLowResource)(DWORD /*reserved*/) { return E_NOTIMPL; } + STDMETHOD(OnStopBinding)(HRESULT /*hresult*/, LPCWSTR /*szError*/) { return E_NOTIMPL; } + STDMETHOD(GetBindInfo)(DWORD* pgrfBINDF, BINDINFO* pbindInfo) { return E_NOTIMPL; } + STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC* /*pformatetc*/, STGMEDIUM* pstgmed) { return E_NOTIMPL; } + STDMETHOD(OnObjectAvailable)(REFIID /*riid*/, IUnknown* /*punk*/) { return E_NOTIMPL; } private: - CComPtr m_spProgressDialog; + CComPtr m_spProgressDialog; }; HRESULT CFxHelper::InstallDotnet(const RUNTIMEINFO* runtime, bool isQuiet) { - auto runtimeName = wstring(runtime->friendlyName); - auto runtimeUrl = wstring(runtime->installerUrl); + auto runtimeName = wstring(runtime->friendlyName); + auto runtimeUrl = wstring(runtime->installerUrl); - if (!isQuiet) { - CTaskDialog dlg; - TASKDIALOG_BUTTON buttons[] = { - { 1, L"Install", }, - { 2, L"Cancel", }, - }; + if (!isQuiet) { + CTaskDialog dlg; + TASKDIALOG_BUTTON buttons[] = { + { 1, L"Install", }, + { 2, L"Cancel", }, + }; - wstring txtInstruction = L"Install " + runtimeName; - wstring txtMain = L"This application requires " + runtimeName + L". Click the Install button to get started."; - wstring txtExpanded = L"Clicking install will download the latest version of this operating system component from Microsoft and install it on your PC. Setup can not continue until this is complete."; + wstring txtInstruction = L"Install " + runtimeName; + wstring txtMain = L"This application requires " + runtimeName + L". Click the Install button to get started."; + wstring txtExpanded = L"Clicking install will download the latest version of this operating system component from Microsoft and install it on your PC. Setup can not continue until this is complete."; - dlg.SetButtons(buttons, 2); - dlg.SetMainInstructionText(txtInstruction.c_str()); - dlg.SetContentText(txtMain.c_str()); - dlg.SetMainIcon(TD_INFORMATION_ICON); + dlg.SetButtons(buttons, 2); + dlg.SetMainInstructionText(txtInstruction.c_str()); + dlg.SetContentText(txtMain.c_str()); + dlg.SetMainIcon(TD_INFORMATION_ICON); - dlg.SetExpandedInformationText(txtExpanded.c_str()); + dlg.SetExpandedInformationText(txtExpanded.c_str()); - int nButton; - if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) { - return S_FALSE; - } - } + int nButton; + if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) { + return S_FALSE; + } + } - HRESULT hr = E_FAIL; - WCHAR szFinalTempFileName[_MAX_PATH] = L""; - CComPtr bscb; - CComPtr pd; - SHELLEXECUTEINFO execInfo = { sizeof(execInfo), }; + HRESULT hr = E_FAIL; + WCHAR szFinalTempFileName[_MAX_PATH] = L""; + CComPtr bscb; + CComPtr pd; + SHELLEXECUTEINFO execInfo = { sizeof(execInfo), }; - WCHAR szTempPath[_MAX_PATH]; - DWORD dwTempPathResult = GetTempPath(_MAX_PATH, szTempPath); + WCHAR szTempPath[_MAX_PATH]; + DWORD dwTempPathResult = GetTempPath(_MAX_PATH, szTempPath); - if (dwTempPathResult == 0) { - hr = AtlHresultFromLastError(); - goto out; - } else if (dwTempPathResult > _MAX_PATH) { - hr = DISP_E_BUFFERTOOSMALL; - goto out; - } + if (dwTempPathResult == 0) { + hr = AtlHresultFromLastError(); + goto out; + } + else if (dwTempPathResult > _MAX_PATH) { + hr = DISP_E_BUFFERTOOSMALL; + goto out; + } - WCHAR szTempFileName[_MAX_PATH]; - if (!GetTempFileName(szTempPath, L"NDP", 0, szTempFileName)) { - hr = AtlHresultFromLastError(); - goto out; - } + WCHAR szTempFileName[_MAX_PATH]; + if (!GetTempFileName(szTempPath, L"NDP", 0, szTempFileName)) { + hr = AtlHresultFromLastError(); + goto out; + } - szTempFileName[_countof(szTempFileName) - 1] = L'\0'; - if (wcscpy_s(szFinalTempFileName, _countof(szFinalTempFileName), szTempFileName) != 0) { - hr = E_FAIL; - goto out; - } + szTempFileName[_countof(szTempFileName) - 1] = L'\0'; + if (wcscpy_s(szFinalTempFileName, _countof(szFinalTempFileName), szTempFileName) != 0) { + hr = E_FAIL; + goto out; + } - WCHAR* pLastDot = wcsrchr(szFinalTempFileName, L'.'); - if (pLastDot == nullptr) { - if (wcscat_s(szFinalTempFileName, _countof(szFinalTempFileName), L".exe") != 0) { - hr = E_FAIL; - goto out; - } - } else { - if (wcscpy_s(pLastDot, _countof(szFinalTempFileName) - (pLastDot - szFinalTempFileName), L".exe") != 0) { - hr = E_FAIL; - goto out; - } - } + WCHAR* pLastDot = wcsrchr(szFinalTempFileName, L'.'); + if (pLastDot == nullptr) { + if (wcscat_s(szFinalTempFileName, _countof(szFinalTempFileName), L".exe") != 0) { + hr = E_FAIL; + goto out; + } + } + else { + if (wcscpy_s(pLastDot, _countof(szFinalTempFileName) - (pLastDot - szFinalTempFileName), L".exe") != 0) { + hr = E_FAIL; + goto out; + } + } - if (!MoveFile(szTempFileName, szFinalTempFileName)) { - hr = AtlHresultFromLastError(); - goto out; - } + if (!MoveFile(szTempFileName, szFinalTempFileName)) { + hr = AtlHresultFromLastError(); + goto out; + } - if (!isQuiet) { - pd.CoCreateInstance(CLSID_ProgressDialog); + if (!isQuiet) { + pd.CoCreateInstance(CLSID_ProgressDialog); - if (pd != nullptr) { - pd->SetTitle(L"Downloading"); - pd->SetLine(1, L"Downloading the .NET installer", FALSE, nullptr); - pd->StartProgressDialog(nullptr, nullptr, 0, nullptr); + if (pd != nullptr) { + pd->SetTitle(L"Downloading"); + pd->SetLine(1, L"Downloading the .NET installer", FALSE, nullptr); + pd->StartProgressDialog(nullptr, nullptr, 0, nullptr); - CComObject* bscbObj = nullptr; - if (SUCCEEDED(CComObject::CreateInstance(&bscbObj))) { - bscbObj->SetProgressDialog(pd); - bscb = bscbObj; - } - } - } + CComObject* bscbObj = nullptr; + if (SUCCEEDED(CComObject::CreateInstance(&bscbObj))) { + bscbObj->SetProgressDialog(pd); + bscb = bscbObj; + } + } + } - hr = URLDownloadToFile(nullptr, runtimeUrl.c_str(), szFinalTempFileName, 0, bscb); - if (pd != nullptr) { - pd->StopProgressDialog(); - } - if (hr != S_OK) { - goto out; - } + hr = URLDownloadToFile(nullptr, runtimeUrl.c_str(), szFinalTempFileName, 0, bscb); + if (pd != nullptr) { + pd->StopProgressDialog(); + } + if (hr != S_OK) { + goto out; + } - execInfo.fMask = SEE_MASK_NOCLOSEPROCESS; - execInfo.lpVerb = L"open"; - execInfo.lpFile = szFinalTempFileName; + execInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + execInfo.lpVerb = L"open"; + execInfo.lpFile = szFinalTempFileName; - if (isQuiet) { - execInfo.lpParameters = L"/q /norestart"; - } - else { - execInfo.lpParameters = L"/passive /norestart /showrmui"; - } + if (isQuiet) { + execInfo.lpParameters = L"/q /norestart"; + } + else { + execInfo.lpParameters = L"/passive /norestart /showrmui"; + } - execInfo.nShow = SW_SHOW; - if (!ShellExecuteEx(&execInfo)) { - hr = AtlHresultFromLastError(); - goto out; - } + execInfo.nShow = SW_SHOW; + if (!ShellExecuteEx(&execInfo)) { + hr = AtlHresultFromLastError(); + goto out; + } - WaitForSingleObject(execInfo.hProcess, INFINITE); + WaitForSingleObject(execInfo.hProcess, INFINITE); - DWORD exitCode; - if (!GetExitCodeProcess(execInfo.hProcess, &exitCode)) { - hr = AtlHresultFromLastError(); - goto out; - } + DWORD exitCode; + if (!GetExitCodeProcess(execInfo.hProcess, &exitCode)) { + hr = AtlHresultFromLastError(); + goto out; + } - if (exitCode == 1641 || exitCode == 3010) { - // The framework installer wants a reboot before we can continue - // See https://msdn.microsoft.com/en-us/library/ee942965%28v=vs.110%29.aspx - // hr = HandleRebootRequirement(isQuiet); - // Exit as a failure, so that setup doesn't carry on now - hr = ERROR_SUCCESS_REBOOT_REQUIRED; - } - else { - hr = exitCode != 0 ? E_FAIL : S_OK; - } + if (exitCode == 1641 || exitCode == 3010) { + // The framework installer wants a reboot before we can continue + // See https://msdn.microsoft.com/en-us/library/ee942965%28v=vs.110%29.aspx + // hr = HandleRebootRequirement(isQuiet); + // Exit as a failure, so that setup doesn't carry on now + hr = ERROR_SUCCESS_REBOOT_REQUIRED; + } + else { + hr = exitCode != 0 ? E_FAIL : S_OK; + } out: - if (execInfo.hProcess != NULL && execInfo.hProcess != INVALID_HANDLE_VALUE) { - CloseHandle(execInfo.hProcess); - } + if (execInfo.hProcess != NULL && execInfo.hProcess != INVALID_HANDLE_VALUE) { + CloseHandle(execInfo.hProcess); + } - if (*szFinalTempFileName != L'\0') { - DeleteFile(szFinalTempFileName); - } + if (*szFinalTempFileName != L'\0') { + DeleteFile(szFinalTempFileName); + } - return hr; + return hr; } // Deal with the aftermath of the framework installer telling us that we need to reboot HRESULT CFxHelper::HandleRebootRequirement(bool isQuiet) { - if (isQuiet) { - // Don't silently reboot - just error-out - fprintf_s(stderr, "A reboot is required following .NET installation - reboot then run installer again.\n"); - return E_FAIL; - } + if (isQuiet) { + // Don't silently reboot - just error-out + fprintf_s(stderr, "A reboot is required following .NET installation - reboot then run installer again.\n"); + return E_FAIL; + } - CTaskDialog dlg; - TASKDIALOG_BUTTON buttons[] = { - { 1, L"Restart Now", }, - { 2, L"Cancel", }, - }; + CTaskDialog dlg; + TASKDIALOG_BUTTON buttons[] = { + { 1, L"Restart Now", }, + { 2, L"Cancel", }, + }; - dlg.SetButtons(buttons, 2); - dlg.SetMainInstructionText(L"Restart System"); - dlg.SetContentText(L"To finish installing the .NET Framework, the system now needs to restart. The installation will finish after you restart and log-in again."); - dlg.SetMainIcon(TD_INFORMATION_ICON); + dlg.SetButtons(buttons, 2); + dlg.SetMainInstructionText(L"Restart System"); + dlg.SetContentText(L"To finish installing the .NET Framework, the system now needs to restart. The installation will finish after you restart and log-in again."); + dlg.SetMainIcon(TD_INFORMATION_ICON); - dlg.SetExpandedInformationText(L"If you click 'Cancel', you'll need to re-run this setup program yourself, after restarting your system."); + dlg.SetExpandedInformationText(L"If you click 'Cancel', you'll need to re-run this setup program yourself, after restarting your system."); - int nButton; - if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) { - return S_FALSE; - } + int nButton; + if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton)) || nButton != 1) { + return S_FALSE; + } - // We need to set up a runonce entry to restart this installer once the reboot has happened - if (!WriteRunOnceEntry()) { - return E_FAIL; - } + // We need to set up a runonce entry to restart this installer once the reboot has happened + if (!WriteRunOnceEntry()) { + return E_FAIL; + } - // And now, reboot - if (!RebootSystem()) { - return E_FAIL; - } + // And now, reboot + if (!RebootSystem()) { + return E_FAIL; + } - // About to reboot, but just in case... - return S_FALSE; + // About to reboot, but just in case... + return S_FALSE; } // @@ -253,44 +251,44 @@ HRESULT CFxHelper::HandleRebootRequirement(bool isQuiet) // bool CFxHelper::WriteRunOnceEntry() { - ATL::CRegKey key; + ATL::CRegKey key; - if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", KEY_WRITE) != ERROR_SUCCESS) { - return false; - } + if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", KEY_WRITE) != ERROR_SUCCESS) { + return false; + } - TCHAR exePath[MAX_PATH]; - GetModuleFileName(NULL, exePath, MAX_PATH); + TCHAR exePath[MAX_PATH]; + GetModuleFileName(NULL, exePath, MAX_PATH); - if (key.SetStringValue(L"SquirrelInstall", exePath) != ERROR_SUCCESS) { - return false; - } + if (key.SetStringValue(L"SquirrelInstall", exePath) != ERROR_SUCCESS) { + return false; + } - return true; + return true; } bool CFxHelper::RebootSystem() { - // First we need to enable the SE_SHUTDOWN_NAME privilege - LUID luid; - if (!LookupPrivilegeValue(L"", SE_SHUTDOWN_NAME, &luid)) { - return false; - } + // First we need to enable the SE_SHUTDOWN_NAME privilege + LUID luid; + if (!LookupPrivilegeValue(L"", SE_SHUTDOWN_NAME, &luid)) { + return false; + } - HANDLE hToken = NULL; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { - return false; - } + HANDLE hToken = NULL; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { + return false; + } - TOKEN_PRIVILEGES tp; - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, 0)) { - CloseHandle(hToken); - return false; - } + TOKEN_PRIVILEGES tp; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, 0)) { + CloseHandle(hToken); + return false; + } - // Now we have that privilege, we can ask Windows to restart - return ExitWindowsEx(EWX_REBOOT, 0) != 0; + // Now we have that privilege, we can ask Windows to restart + return ExitWindowsEx(EWX_REBOOT, 0) != 0; } diff --git a/src/Setup/FxHelper.h b/src/Setup/FxHelper.h index 480654e8..3ad27d34 100644 --- a/src/Setup/FxHelper.h +++ b/src/Setup/FxHelper.h @@ -3,10 +3,12 @@ class CFxHelper { + public: - static HRESULT InstallDotnet(const RUNTIMEINFO* runtime, bool isQuiet); - static HRESULT HandleRebootRequirement(bool isQuiet); + static HRESULT InstallDotnet(const RUNTIMEINFO* runtime, bool isQuiet); + static HRESULT HandleRebootRequirement(bool isQuiet); private: - static bool WriteRunOnceEntry(); - static bool RebootSystem(); + static bool WriteRunOnceEntry(); + static bool RebootSystem(); + }; \ No newline at end of file diff --git a/src/Setup/ImageEx.cpp b/src/Setup/ImageEx.cpp index 372684b8..3e7ec840 100644 --- a/src/Setup/ImageEx.cpp +++ b/src/Setup/ImageEx.cpp @@ -12,245 +12,226 @@ void ASSERT(void* obj) {} // https://stackoverflow.com/a/66238748/184746 IStream* LoadImageFromResource(const wchar_t* resid, const wchar_t* restype) { - IStream* pStream = nullptr; - HGLOBAL hGlobal = nullptr; + IStream* pStream = nullptr; + HGLOBAL hGlobal = nullptr; - HINSTANCE hInst = GetModuleHandle(NULL); - HRSRC hrsrc = FindResourceW(hInst, resid, restype); // get the handle to the resource - if (hrsrc) - { - DWORD dwResourceSize = SizeofResource(hInst, hrsrc); - if (dwResourceSize > 0) - { - HGLOBAL hGlobalResource = LoadResource(hInst, hrsrc); // load it - if (hGlobalResource) - { - void* imagebytes = LockResource(hGlobalResource); // get a pointer to the file bytes + HINSTANCE hInst = GetModuleHandle(NULL); + HRSRC hrsrc = FindResourceW(hInst, resid, restype); // get the handle to the resource + if (hrsrc) { + DWORD dwResourceSize = SizeofResource(hInst, hrsrc); + if (dwResourceSize > 0) { + HGLOBAL hGlobalResource = LoadResource(hInst, hrsrc); // load it + if (hGlobalResource) { + void* imagebytes = LockResource(hGlobalResource); // get a pointer to the file bytes - // copy image bytes into a real hglobal memory handle - hGlobal = ::GlobalAlloc(GHND, dwResourceSize); - if (hGlobal) - { - void* pBuffer = ::GlobalLock(hGlobal); - if (pBuffer) - { - memcpy(pBuffer, imagebytes, dwResourceSize); - HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream); - if (SUCCEEDED(hr)) - { - // pStream now owns the global handle and will invoke GlobalFree on release - hGlobal = nullptr; - } - } - } - } - } - } + // copy image bytes into a real hglobal memory handle + hGlobal = ::GlobalAlloc(GHND, dwResourceSize); + if (hGlobal) { + void* pBuffer = ::GlobalLock(hGlobal); + if (pBuffer) { + memcpy(pBuffer, imagebytes, dwResourceSize); + HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream); + if (SUCCEEDED(hr)) { + // pStream now owns the global handle and will invoke GlobalFree on release + hGlobal = nullptr; + } + } + } + } + } + } - if (hGlobal) - { - GlobalFree(hGlobal); - hGlobal = nullptr; - } + if (hGlobal) { + GlobalFree(hGlobal); + hGlobal = nullptr; + } - return pStream; + return pStream; } ImageEx::ImageEx(const wchar_t* resid, const wchar_t* restype) { - Initialize(); + Initialize(); - auto stream = LoadImageFromResource(resid, restype); - if (stream) - { - nativeImage = NULL; - lastResult = DllExports::GdipLoadImageFromStreamICM(stream, &nativeImage); - m_bIsInitialized = true; - TestForAnimatedGIF(); - stream->Release(); - } + auto stream = LoadImageFromResource(resid, restype); + if (stream) { + nativeImage = NULL; + lastResult = DllExports::GdipLoadImageFromStreamICM(stream, &nativeImage); + m_bIsInitialized = true; + TestForAnimatedGIF(); + stream->Release(); + } } ImageEx::~ImageEx() { - Destroy(); + Destroy(); } bool ImageEx::InitAnimation(HWND hWnd, CPoint pt) { + m_hWnd = hWnd; + m_pt = pt; - m_hWnd = hWnd; - m_pt = pt; + if (!m_bIsInitialized) { + TRACE(_T("GIF not initialized\n")); + return false; + }; - if (!m_bIsInitialized) - { - TRACE(_T("GIF not initialized\n")); - return false; - }; + if (IsAnimatedGIF()) { + if (m_hThread == NULL) { - if (IsAnimatedGIF()) - { - if (m_hThread == NULL) - { + unsigned int nTID = 0; - unsigned int nTID = 0; + m_hThread = (HANDLE)_beginthreadex(NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED, &nTID); - m_hThread = (HANDLE)_beginthreadex(NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED, &nTID); + if (!m_hThread) { + TRACE(_T("Couldn't start a GIF animation thread\n")); + return true; + } + else + ResumeThread(m_hThread); + } + } - if (!m_hThread) - { - TRACE(_T("Couldn't start a GIF animation thread\n")); - return true; - } - else - ResumeThread(m_hThread); - } - } - - return false; + return false; } CSize ImageEx::GetSize() { - return CSize(GetWidth(), GetHeight()); + return CSize(GetWidth(), GetHeight()); } bool ImageEx::TestForAnimatedGIF() { - UINT count = 0; - count = GetFrameDimensionsCount(); - GUID* pDimensionIDs = new GUID[count]; + UINT count = 0; + count = GetFrameDimensionsCount(); + GUID* pDimensionIDs = new GUID[count]; - // Get the list of frame dimensions from the Image object. - GetFrameDimensionsList(pDimensionIDs, count); + // Get the list of frame dimensions from the Image object. + GetFrameDimensionsList(pDimensionIDs, count); - // Get the number of frames in the first dimension. - m_nFrameCount = GetFrameCount(&pDimensionIDs[0]); + // Get the number of frames in the first dimension. + m_nFrameCount = GetFrameCount(&pDimensionIDs[0]); - // Assume that the image has a property item of type PropertyItemEquipMake. - // Get the size of that property item. - int nSize = GetPropertyItemSize(PropertyTagFrameDelay); + // Assume that the image has a property item of type PropertyItemEquipMake. + // Get the size of that property item. + int nSize = GetPropertyItemSize(PropertyTagFrameDelay); - // Allocate a buffer to receive the property item. - m_pPropertyItem = (PropertyItem*)malloc(nSize); + // Allocate a buffer to receive the property item. + m_pPropertyItem = (PropertyItem*)malloc(nSize); - GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem); + GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem); - delete pDimensionIDs; + delete pDimensionIDs; - return m_nFrameCount > 1; + return m_nFrameCount > 1; } void ImageEx::Initialize() { - m_nFramePosition = 0; - m_nFrameCount = 0; - lastResult = InvalidParameter; - m_hThread = NULL; - m_bIsInitialized = false; - m_pPropertyItem = NULL; + m_nFramePosition = 0; + m_nFrameCount = 0; + lastResult = InvalidParameter; + m_hThread = NULL; + m_bIsInitialized = false; + m_pPropertyItem = NULL; #ifdef INDIGO_CTRL_PROJECT - m_hInst = _Module.GetResourceInstance(); + m_hInst = _Module.GetResourceInstance(); #else - m_hInst = GetModuleHandle(NULL);// AfxGetResourceHandle(); + m_hInst = GetModuleHandle(NULL);// AfxGetResourceHandle(); #endif - m_bPause = false; - m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - m_hPause = CreateEvent(NULL, TRUE, TRUE, NULL); + m_bPause = false; + m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + m_hPause = CreateEvent(NULL, TRUE, TRUE, NULL); } UINT WINAPI ImageEx::_ThreadAnimationProc(LPVOID pParam) { - ASSERT(pParam); - ImageEx* pImage = reinterpret_cast (pParam); - pImage->ThreadAnimation(); + ASSERT(pParam); + ImageEx* pImage = reinterpret_cast (pParam); + pImage->ThreadAnimation(); - return 0; + return 0; } void ImageEx::ThreadAnimation() { - m_nFramePosition = 0; + m_nFramePosition = 0; - bool bExit = false; - while (bExit == false) - { - bExit = DrawFrameGIF(); - } + bool bExit = false; + while (bExit == false) { + bExit = DrawFrameGIF(); + } } bool ImageEx::DrawFrameGIF() { - ::WaitForSingleObject(m_hPause, INFINITE); + ::WaitForSingleObject(m_hPause, INFINITE); - GUID pageGuid = FrameDimensionTime; + GUID pageGuid = FrameDimensionTime; - long hmWidth = GetWidth(); - long hmHeight = GetHeight(); + long hmWidth = GetWidth(); + long hmHeight = GetHeight(); - HDC hDC = GetDC(m_hWnd); - if (hDC) - { - Graphics graphics(hDC); - graphics.DrawImage(this, m_pt.x, m_pt.y, hmWidth, hmHeight); - ReleaseDC(m_hWnd, hDC); - } + HDC hDC = GetDC(m_hWnd); + if (hDC) { + Graphics graphics(hDC); + graphics.DrawImage(this, m_pt.x, m_pt.y, hmWidth, hmHeight); + ReleaseDC(m_hWnd, hDC); + } - SelectActiveFrame(&pageGuid, m_nFramePosition++); + SelectActiveFrame(&pageGuid, m_nFramePosition++); - if (m_nFramePosition == m_nFrameCount) - m_nFramePosition = 0; + if (m_nFramePosition == m_nFrameCount) + m_nFramePosition = 0; - long lPause = ((long*)m_pPropertyItem->value)[m_nFramePosition] * 10; - DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause); - return dwErr == WAIT_OBJECT_0; + long lPause = ((long*)m_pPropertyItem->value)[m_nFramePosition] * 10; + DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause); + return dwErr == WAIT_OBJECT_0; } void ImageEx::SetPause(bool bPause) { - if (!IsAnimatedGIF()) - return; + if (!IsAnimatedGIF()) + return; - if (bPause && !m_bPause) - { - ::ResetEvent(m_hPause); - } - else - { + if (bPause && !m_bPause) { + ::ResetEvent(m_hPause); + } + else { - if (m_bPause && !bPause) - { - ::SetEvent(m_hPause); - } - } + if (m_bPause && !bPause) { + ::SetEvent(m_hPause); + } + } - m_bPause = bPause; + m_bPause = bPause; } void ImageEx::Destroy() { - if (m_hThread) - { - // If pause un pause - SetPause(false); + if (m_hThread) { + // If pause un pause + SetPause(false); - SetEvent(m_hExitEvent); - WaitForSingleObject(m_hThread, INFINITE); - } + SetEvent(m_hExitEvent); + WaitForSingleObject(m_hThread, INFINITE); + } - CloseHandle(m_hThread); - CloseHandle(m_hExitEvent); - CloseHandle(m_hPause); + CloseHandle(m_hThread); + CloseHandle(m_hExitEvent); + CloseHandle(m_hPause); - free(m_pPropertyItem); + free(m_pPropertyItem); - m_pPropertyItem = NULL; - m_hThread = NULL; - m_hExitEvent = NULL; - m_hPause = NULL; + m_pPropertyItem = NULL; + m_hThread = NULL; + m_hExitEvent = NULL; + m_hPause = NULL; } \ No newline at end of file diff --git a/src/Setup/ImageEx.h b/src/Setup/ImageEx.h index d3d312f7..383957e9 100644 --- a/src/Setup/ImageEx.h +++ b/src/Setup/ImageEx.h @@ -17,36 +17,36 @@ class ImageEx : public Image { public: - ImageEx(const wchar_t* resid, const wchar_t* restype); - ~ImageEx(); + ImageEx(const wchar_t* resid, const wchar_t* restype); + ~ImageEx(); public: - CSize GetSize(); - bool IsAnimatedGIF() { return m_nFrameCount > 1; } - void SetPause(bool bPause); - bool IsPaused() { return m_bPause; } - bool InitAnimation(HWND hWnd, CPoint pt); - void Destroy(); + CSize GetSize(); + bool IsAnimatedGIF() { return m_nFrameCount > 1; } + void SetPause(bool bPause); + bool IsPaused() { return m_bPause; } + bool InitAnimation(HWND hWnd, CPoint pt); + void Destroy(); protected: - bool TestForAnimatedGIF(); - void Initialize(); - bool DrawFrameGIF(); + bool TestForAnimatedGIF(); + void Initialize(); + bool DrawFrameGIF(); - void ThreadAnimation(); - static UINT WINAPI _ThreadAnimationProc(LPVOID pParam); + void ThreadAnimation(); + static UINT WINAPI _ThreadAnimationProc(LPVOID pParam); - HANDLE m_hThread; - HANDLE m_hPause; - HANDLE m_hExitEvent; - HINSTANCE m_hInst; - HWND m_hWnd; - UINT m_nFrameCount; - UINT m_nFramePosition; - bool m_bIsInitialized; - bool m_bPause; - PropertyItem* m_pPropertyItem; - CPoint m_pt; + HANDLE m_hThread; + HANDLE m_hPause; + HANDLE m_hExitEvent; + HINSTANCE m_hInst; + HWND m_hWnd; + UINT m_nFrameCount; + UINT m_nFramePosition; + bool m_bIsInitialized; + bool m_bPause; + PropertyItem* m_pPropertyItem; + CPoint m_pt; }; diff --git a/src/Setup/MachineInstaller.cpp b/src/Setup/MachineInstaller.cpp index 7e3d1dd1..eb5bdeb7 100644 --- a/src/Setup/MachineInstaller.cpp +++ b/src/Setup/MachineInstaller.cpp @@ -4,64 +4,65 @@ #include "resource.h" #include -bool directoryExists(wchar_t* path) { - DWORD dwResult = GetFileAttributes(path); +bool directoryExists(wchar_t* path) +{ + DWORD dwResult = GetFileAttributes(path); - if (dwResult != INVALID_FILE_ATTRIBUTES) { - return true; - } + if (dwResult != INVALID_FILE_ATTRIBUTES) { + return true; + } - // NB: The directory could exist but we can't access it, let's check - DWORD dwLastError = GetLastError(); - if (dwLastError == ERROR_FILE_NOT_FOUND) return false; - if (dwLastError == ERROR_PATH_NOT_FOUND) return false; + // NB: The directory could exist but we can't access it, let's check + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_FILE_NOT_FOUND) return false; + if (dwLastError == ERROR_PATH_NOT_FOUND) return false; - return true; + return true; } bool MachineInstaller::ShouldSilentInstall() { - // Figure out the package name from our own EXE name - // The name consist of [$pkgName]DeploymentTool.exe - wchar_t ourFile[MAX_PATH]; - HMODULE hMod = GetModuleHandle(NULL); - GetModuleFileName(hMod, ourFile, _countof(ourFile)); + // Figure out the package name from our own EXE name + // The name consist of [$pkgName]DeploymentTool.exe + wchar_t ourFile[MAX_PATH]; + HMODULE hMod = GetModuleHandle(NULL); + GetModuleFileName(hMod, ourFile, _countof(ourFile)); - CString fullPath = CString(ourFile); - CString pkgName = CString(ourFile + fullPath.ReverseFind(L'\\')); - pkgName.Replace(L"DeploymentTool.exe", L""); - - wchar_t installFolder[MAX_PATH]; + CString fullPath = CString(ourFile); + CString pkgName = CString(ourFile + fullPath.ReverseFind(L'\\')); + pkgName.Replace(L"DeploymentTool.exe", L""); - // NB: Users often get into the sitch where they install the MSI, then try to - // install the standalone package on top of that. In previous versions we tried - // to detect if the app was properly installed, but now we're taking the much - // more conservative approach, that if the package dir exists in any way, we're - // bailing out + wchar_t installFolder[MAX_PATH]; - // C:\Users\Username\AppData\Local\$pkgName - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); - wcscat(installFolder, L"\\"); - wcscat(installFolder, pkgName); + // NB: Users often get into the sitch where they install the MSI, then try to + // install the standalone package on top of that. In previous versions we tried + // to detect if the app was properly installed, but now we're taking the much + // more conservative approach, that if the package dir exists in any way, we're + // bailing out - if (directoryExists(installFolder)) { - return false; - } + // C:\Users\Username\AppData\Local\$pkgName + SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); + wcscat(installFolder, L"\\"); + wcscat(installFolder, pkgName); - // C:\ProgramData\$pkgName\$username - wchar_t username[512]; - DWORD unamesize = _countof(username); - SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); - GetUserName(username, &unamesize); - wcscat(installFolder, L"\\"); - wcscat(installFolder, pkgName); - wcscat(installFolder, L"\\"); - wcscat(installFolder, username); + if (directoryExists(installFolder)) { + return false; + } - if (directoryExists(installFolder)) { - return false; - } + // C:\ProgramData\$pkgName\$username + wchar_t username[512]; + DWORD unamesize = _countof(username); + SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, installFolder); + GetUserName(username, &unamesize); + wcscat(installFolder, L"\\"); + wcscat(installFolder, pkgName); + wcscat(installFolder, L"\\"); + wcscat(installFolder, username); - // None of these exist, we should install - return true; + if (directoryExists(installFolder)) { + return false; + } + + // None of these exist, we should install + return true; } diff --git a/src/Setup/MachineInstaller.h b/src/Setup/MachineInstaller.h index c73a4cd7..23ae40e6 100644 --- a/src/Setup/MachineInstaller.h +++ b/src/Setup/MachineInstaller.h @@ -1,6 +1,8 @@ #pragma once class MachineInstaller { + public: - static bool ShouldSilentInstall(); + static bool ShouldSilentInstall(); + }; diff --git a/src/Setup/RuntimeInfo.cpp b/src/Setup/RuntimeInfo.cpp index 7315a869..6d26c536 100644 --- a/src/Setup/RuntimeInfo.cpp +++ b/src/Setup/RuntimeInfo.cpp @@ -9,104 +9,104 @@ using std::vector; RUNTIMEINFO supported_runtimes[] = { - // net45 through net46 is supported on Vista SP2 and newer + // net45 through net46 is supported on Vista SP2 and newer - { - _WIN32_WINNT_VISTA, 2, - L"net45", L".NET Framework 4.5", - L"http://go.microsoft.com/fwlink/?LinkId=397707", - 378389 - }, + { + _WIN32_WINNT_VISTA, 2, + L"net45", L".NET Framework 4.5", + L"http://go.microsoft.com/fwlink/?LinkId=397707", + 378389 + }, - { - _WIN32_WINNT_VISTA, 2, - L"net451", L".NET Framework 4.5.1", - L"http://go.microsoft.com/fwlink/?LinkId=397707", - 378675 - }, + { + _WIN32_WINNT_VISTA, 2, + L"net451", L".NET Framework 4.5.1", + L"http://go.microsoft.com/fwlink/?LinkId=397707", + 378675 + }, - { - _WIN32_WINNT_VISTA, 2, - L"net452", L".NET Framework 4.5.2", - L"http://go.microsoft.com/fwlink/?LinkId=397707", - 379893 - }, + { + _WIN32_WINNT_VISTA, 2, + L"net452", L".NET Framework 4.5.2", + L"http://go.microsoft.com/fwlink/?LinkId=397707", + 379893 + }, - // net461 through net48 supports Windows 7 and newer + // net461 through net48 supports Windows 7 and newer - { - _WIN32_WINNT_WIN7, 0, - L"net46", L".NET Framework 4.6", - L"http://go.microsoft.com/fwlink/?LinkId=780596", - 393295 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net46", L".NET Framework 4.6", + L"http://go.microsoft.com/fwlink/?LinkId=780596", + 393295 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net461", L".NET Framework 4.6.1", - L"http://go.microsoft.com/fwlink/?LinkId=780596", - 394254 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net461", L".NET Framework 4.6.1", + L"http://go.microsoft.com/fwlink/?LinkId=780596", + 394254 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net462", L".NET Framework 4.6.2", - L"http://go.microsoft.com/fwlink/?LinkId=780596", - 394802 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net462", L".NET Framework 4.6.2", + L"http://go.microsoft.com/fwlink/?LinkId=780596", + 394802 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net47", L".NET Framework 4.7", - L"http://go.microsoft.com/fwlink/?LinkId=863262", - 460798 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net47", L".NET Framework 4.7", + L"http://go.microsoft.com/fwlink/?LinkId=863262", + 460798 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net471", L".NET Framework 4.7.1", - L"http://go.microsoft.com/fwlink/?LinkId=863262", - 461308 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net471", L".NET Framework 4.7.1", + L"http://go.microsoft.com/fwlink/?LinkId=863262", + 461308 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net472", L".NET Framework 4.7.2", - L"http://go.microsoft.com/fwlink/?LinkId=863262", - 461808 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net472", L".NET Framework 4.7.2", + L"http://go.microsoft.com/fwlink/?LinkId=863262", + 461808 + }, - { - _WIN32_WINNT_WIN7, 0, - L"net48", L".NET Framework 4.8", - L"https://go.microsoft.com/fwlink/?LinkId=2085155", - 528040 - }, + { + _WIN32_WINNT_WIN7, 0, + L"net48", L".NET Framework 4.8", + L"https://go.microsoft.com/fwlink/?LinkId=2085155", + 528040 + }, - // dotnet core is supported on Windows 7 SP1 and newer. - // update this list periodically from https://dotnet.microsoft.com/download/dotnet - // we could add support for 2.0/2.1/2.2 but since those runtimes didn't ship with desktop support it is probably not needed. + // dotnet core is supported on Windows 7 SP1 and newer. + // update this list periodically from https://dotnet.microsoft.com/download/dotnet + // we could add support for 2.0/2.1/2.2 but since those runtimes didn't ship with desktop support it is probably not needed. - { - _WIN32_WINNT_WIN7, 1, - L"netcoreapp3", L".NET Core 3.0.3", - L"https://download.visualstudio.microsoft.com/download/pr/c525a2bb-6e98-4e6e-849e-45241d0db71c/d21612f02b9cae52fa50eb54de905986/windowsdesktop-runtime-3.0.3-win-x64.exe", - 0, L"WindowsDesktop.App 3.0" - }, + { + _WIN32_WINNT_WIN7, 1, + L"netcoreapp3", L".NET Core 3.0.3", + L"https://download.visualstudio.microsoft.com/download/pr/c525a2bb-6e98-4e6e-849e-45241d0db71c/d21612f02b9cae52fa50eb54de905986/windowsdesktop-runtime-3.0.3-win-x64.exe", + 0, L"WindowsDesktop.App 3.0" + }, - { - _WIN32_WINNT_WIN7, 1, - L"netcoreapp31", L".NET Core 3.1.18", - L"https://download.visualstudio.microsoft.com/download/pr/aa240732-82d7-4bd1-9701-e4014d7dc735/41a460f5e9c343f7b9207f64ab0e4c90/windowsdesktop-runtime-3.1.18-win-x64.exe", - 0, L"WindowsDesktop.App 3.1" - }, + { + _WIN32_WINNT_WIN7, 1, + L"netcoreapp31", L".NET Core 3.1.18", + L"https://download.visualstudio.microsoft.com/download/pr/aa240732-82d7-4bd1-9701-e4014d7dc735/41a460f5e9c343f7b9207f64ab0e4c90/windowsdesktop-runtime-3.1.18-win-x64.exe", + 0, L"WindowsDesktop.App 3.1" + }, - { - _WIN32_WINNT_WIN7, 1, - L"net5", L".NET 5.0.9", - L"https://download.visualstudio.microsoft.com/download/pr/8bc41df1-cbb4-4da6-944f-6652378e9196/1014aacedc80bbcc030dabb168d2532f/windowsdesktop-runtime-5.0.9-win-x64.exe", - 0, L"WindowsDesktop.App 5.0" - }, + { + _WIN32_WINNT_WIN7, 1, + L"net5", L".NET 5.0.9", + L"https://download.visualstudio.microsoft.com/download/pr/8bc41df1-cbb4-4da6-944f-6652378e9196/1014aacedc80bbcc030dabb168d2532f/windowsdesktop-runtime-5.0.9-win-x64.exe", + 0, L"WindowsDesktop.App 5.0" + }, }; @@ -114,126 +114,123 @@ RUNTIMEINFO supported_runtimes[] = const RUNTIMEINFO* GetRuntimeByName(wstring name) { - for (int i = 0; i < NUM_RUNTIMES; i++) - { - const RUNTIMEINFO* item = &supported_runtimes[i]; - auto itemName = wstring(item->name); + for (int i = 0; i < NUM_RUNTIMES; i++) { + const RUNTIMEINFO* item = &supported_runtimes[i]; + auto itemName = wstring(item->name); - if (name == itemName) - return item; - } + if (name == itemName) + return item; + } - return nullptr; + return nullptr; } bool IsRuntimeSupported(const RUNTIMEINFO* runtime) { - return IsWindowsVersionOrGreater(HIBYTE(runtime->minOS), LOBYTE(runtime->minOS), runtime->minSP); + return IsWindowsVersionOrGreater(HIBYTE(runtime->minOS), LOBYTE(runtime->minOS), runtime->minSP); } static const wchar_t* ndpPath = L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full"; bool IsFullNetFrameworkInstalled(DWORD requiredVersion) { - ATL::CRegKey key; + ATL::CRegKey key; - if (key.Open(HKEY_LOCAL_MACHINE, ndpPath, KEY_READ) != ERROR_SUCCESS) { - return false; - } + if (key.Open(HKEY_LOCAL_MACHINE, ndpPath, KEY_READ) != ERROR_SUCCESS) { + return false; + } - DWORD dwReleaseInfo = 0; - if (key.QueryDWORDValue(L"Release", dwReleaseInfo) != ERROR_SUCCESS || - dwReleaseInfo < requiredVersion) { - return false; - } + DWORD dwReleaseInfo = 0; + if (key.QueryDWORDValue(L"Release", dwReleaseInfo) != ERROR_SUCCESS || + dwReleaseInfo < requiredVersion) { + return false; + } - return true; + return true; } // TODO this is extremely messy, it should certainly be re-written. -wstring exec(const char* cmd) { - char buffer[128]; - string result = ""; - FILE* pipe = _popen(cmd, "r"); - if (!pipe) - return L""; - try { - while (fgets(buffer, sizeof buffer, pipe) != NULL) { - result += buffer; - } - } - catch (...) { - _pclose(pipe); - return L""; - } - _pclose(pipe); +wstring exec(const char* cmd) +{ + char buffer[128]; + string result = ""; + FILE* pipe = _popen(cmd, "r"); + if (!pipe) + return L""; + try { + while (fgets(buffer, sizeof buffer, pipe) != NULL) { + result += buffer; + } + } + catch (...) { + _pclose(pipe); + return L""; + } + _pclose(pipe); - // https://stackoverflow.com/a/8969776/184746 - std::wstring wsTmp(result.begin(), result.end()); - return wsTmp; + // https://stackoverflow.com/a/8969776/184746 + std::wstring wsTmp(result.begin(), result.end()); + return wsTmp; } bool IsDotNetCoreInstalled(wstring searchString) { - // it is possible to parse this registry entry, but it only returns the newest version - // and it might be necessary to install an older version of the runtime if it's not installed, - // so we need a full list of installed runtimes. - // static const wchar_t* dncPath = L"SOFTWARE\\dotnet\\Setup\\InstalledVersions"; + // it is possible to parse this registry entry, but it only returns the newest version + // and it might be necessary to install an older version of the runtime if it's not installed, + // so we need a full list of installed runtimes. + // static const wchar_t* dncPath = L"SOFTWARE\\dotnet\\Setup\\InstalledVersions"; - // note, dotnet cli will only return x64 results. - //auto runtimes = exec("dotnet --list-runtimes"); - auto runtimes = exec("dotnet --info"); - return runtimes.find(searchString) != std::string::npos; + // note, dotnet cli will only return x64 results. + //auto runtimes = exec("dotnet --list-runtimes"); + auto runtimes = exec("dotnet --info"); + return runtimes.find(searchString) != std::string::npos; } bool IsRuntimeInstalled(const RUNTIMEINFO* runtime) { - if (runtime->fxReleaseVersion > 0) - { - return IsFullNetFrameworkInstalled(runtime->fxReleaseVersion); - } - else - { - return IsDotNetCoreInstalled(wstring(runtime->dncRuntimeVersionName)); - } + if (runtime->fxReleaseVersion > 0) { + return IsFullNetFrameworkInstalled(runtime->fxReleaseVersion); + } + else { + return IsDotNetCoreInstalled(wstring(runtime->dncRuntimeVersionName)); + } } int ParseRuntimeString(std::wstring version, vector& runtimes) { - // split version string by comma - int ret = S_OK; - wstring temp; - std::wstringstream wss(version); - while (std::getline(wss, temp, L',')) - { - const RUNTIMEINFO* rt = GetRuntimeByName(temp); - if (rt != nullptr) - runtimes.push_back(rt); - else - ret = S_FALSE; - } - return ret; + // split version string by comma + int ret = S_OK; + wstring temp; + std::wstringstream wss(version); + while (std::getline(wss, temp, L',')) { + const RUNTIMEINFO* rt = GetRuntimeByName(temp); + if (rt != nullptr) + runtimes.push_back(rt); + else + ret = S_FALSE; + } + return ret; } vector GetRequiredRuntimes() { - vector runtimes; + vector runtimes; - // get comma-delimited version string from exe resources - wchar_t* versionFlag = (wchar_t*)LoadResource(NULL, FindResource(NULL, (LPCWSTR)IDR_FX_VERSION_FLAG, L"FLAGS")); - if (versionFlag == nullptr) - return runtimes; + // get comma-delimited version string from exe resources + wchar_t* versionFlag = (wchar_t*)LoadResource(NULL, FindResource(NULL, (LPCWSTR)IDR_FX_VERSION_FLAG, L"FLAGS")); + if (versionFlag == nullptr) + return runtimes; - wstring version(versionFlag); - if (version.length() == 0) - return runtimes; + wstring version(versionFlag); + if (version.length() == 0) + return runtimes; - ParseRuntimeString(version, runtimes); - return runtimes; + ParseRuntimeString(version, runtimes); + return runtimes; } int VerifyRuntimeString(std::wstring version) { - vector runtimes; - return ParseRuntimeString(version, runtimes); + vector runtimes; + return ParseRuntimeString(version, runtimes); } diff --git a/src/Setup/RuntimeInfo.h b/src/Setup/RuntimeInfo.h index 2f257a54..41a44f77 100644 --- a/src/Setup/RuntimeInfo.h +++ b/src/Setup/RuntimeInfo.h @@ -5,13 +5,13 @@ typedef struct { - WORD minOS; - WORD minSP; - wchar_t name[32]; - wchar_t friendlyName[32]; - wchar_t installerUrl[256]; - DWORD fxReleaseVersion; - wchar_t dncRuntimeVersionName[32]; + WORD minOS; + WORD minSP; + wchar_t name[32]; + wchar_t friendlyName[32]; + wchar_t installerUrl[256]; + DWORD fxReleaseVersion; + wchar_t dncRuntimeVersionName[32]; } RUNTIMEINFO; const RUNTIMEINFO* GetRuntimeByName(std::wstring name); diff --git a/src/Setup/SplashWnd.cpp b/src/Setup/SplashWnd.cpp index 2845aee8..5bcfed22 100644 --- a/src/Setup/SplashWnd.cpp +++ b/src/Setup/SplashWnd.cpp @@ -45,28 +45,23 @@ void CSplashWnd::SetImage(const wchar_t* resid, const wchar_t* restype) void CSplashWnd::Show() { - if (m_hThread == NULL) - { + if (m_hThread == NULL) { m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); m_hThread = (HANDLE)_beginthreadex(NULL, 0, SplashThreadProc, static_cast(this), 0, &m_ThreadId); - if (WaitForSingleObject(m_hEvent, 5000) == WAIT_TIMEOUT) - { + if (WaitForSingleObject(m_hEvent, 5000) == WAIT_TIMEOUT) { OutputDebugString(L"Error starting SplashThread\n"); } } - else - { + else { PostThreadMessage(m_ThreadId, WM_ACTIVATE, WA_CLICKACTIVE, 0); } } void CSplashWnd::Hide() { - if (m_hThread) - { + if (m_hThread) { PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0); - if (WaitForSingleObject(m_hThread, 9000) == WAIT_TIMEOUT) - { + if (WaitForSingleObject(m_hThread, 9000) == WAIT_TIMEOUT) { ::TerminateThread(m_hThread, 2222); } CloseHandle(m_hThread); @@ -101,8 +96,7 @@ unsigned int __stdcall CSplashWnd::SplashThreadProc(void* lpParameter) wndcls.lpszClassName = L"SplashWnd"; wndcls.hIcon = LoadIcon(wndcls.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); - if (!RegisterClass(&wndcls)) - { + if (!RegisterClass(&wndcls)) { if (GetLastError() != 0x00000582) // already registered) { OutputDebugString(L"Unable to register class SplashWnd\n"); @@ -118,13 +112,11 @@ unsigned int __stdcall CSplashWnd::SplashThreadProc(void* lpParameter) ::GetCursorPos(&point); hMonitor = ::MonitorFromPoint(point, MONITOR_DEFAULTTONEAREST); - if (::GetMonitorInfo(hMonitor, &mi)) - { + if (::GetMonitorInfo(hMonitor, &mi)) { rcArea.left = (mi.rcMonitor.right + mi.rcMonitor.left - static_cast(pThis->m_pImage->GetWidth())) / 2; rcArea.top = (mi.rcMonitor.top + mi.rcMonitor.bottom - static_cast(pThis->m_pImage->GetHeight())) / 2; } - else - { + else { SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); rcArea.left = (rcArea.right + rcArea.left - pThis->m_pImage->GetWidth()) / 2; rcArea.top = (rcArea.top + rcArea.bottom - pThis->m_pImage->GetHeight()) / 2; @@ -141,8 +133,7 @@ unsigned int __stdcall CSplashWnd::SplashThreadProc(void* lpParameter) wndcls.hInstance, NULL); - if (!pThis->m_hSplashWnd) - { + if (!pThis->m_hSplashWnd) { OutputDebugString(L"Unable to create SplashWnd\n"); return 0; } @@ -159,16 +150,13 @@ unsigned int __stdcall CSplashWnd::SplashThreadProc(void* lpParameter) PeekMessage(&msg, NULL, 0, 0, 0); // invoke creating message queue SetEvent(pThis->m_hEvent); - while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) - { + while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (msg.message == WM_QUIT) break; - if (bRet == -1) - { + if (bRet == -1) { // handle the error and possibly exit } - else - { + else { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -181,24 +169,19 @@ unsigned int __stdcall CSplashWnd::SplashThreadProc(void* lpParameter) LRESULT CALLBACK CSplashWnd::SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CSplashWnd* pInstance = reinterpret_cast(GetWindowLongPtr(hwnd, GWL_USERDATA)); - if (pInstance == NULL) - { + if (pInstance == NULL) { return DefWindowProc(hwnd, uMsg, wParam, lParam); } - switch (uMsg) - { + switch (uMsg) { case WM_PAINT: { - if (pInstance->m_pImage) - { - if (pInstance->m_pImage->IsAnimatedGIF()) - { + if (pInstance->m_pImage) { + if (pInstance->m_pImage->IsAnimatedGIF()) { // do nothing, the gif will be drawn by it's own thread. } - else - { + else { Gdiplus::Graphics gdip(hwnd); gdip.DrawImage(pInstance->m_pImage, 0, 0, pInstance->m_pImage->GetWidth(), pInstance->m_pImage->GetHeight()); } @@ -216,8 +199,7 @@ LRESULT CALLBACK CSplashWnd::SplashWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, case WM_MOUSEMOVE: { - if (GetCapture() == hwnd) - { + if (GetCapture() == hwnd) { RECT rcWnd; GetWindowRect(hwnd, &rcWnd); diff --git a/src/Setup/SplashWnd.h b/src/Setup/SplashWnd.h index a7521997..bc0a0e88 100644 --- a/src/Setup/SplashWnd.h +++ b/src/Setup/SplashWnd.h @@ -24,19 +24,18 @@ private: CSplashWnd& operator=(const CSplashWnd&) {}; protected: - HANDLE m_hThread; - unsigned int m_ThreadId; - HANDLE m_hEvent; - ImageEx* m_pImage; - HWND m_hSplashWnd; - HWND m_hParentWnd; - POINT m_ptMouseDown; + HANDLE m_hThread; + unsigned int m_ThreadId; + HANDLE m_hEvent; + ImageEx* m_pImage; + HWND m_hSplashWnd; + HWND m_hParentWnd; + POINT m_ptMouseDown; public: CSplashWnd(HWND hParent = NULL); ~CSplashWnd(); void SetImage(const wchar_t* resid, const wchar_t* restype); - void SetWindowName(const wchar_t* windowName); void Show(); void Hide(); diff --git a/src/Setup/UpdateRunner.cpp b/src/Setup/UpdateRunner.cpp index 49e6ceb8..0dec0460 100644 --- a/src/Setup/UpdateRunner.cpp +++ b/src/Setup/UpdateRunner.cpp @@ -6,296 +6,297 @@ void CUpdateRunner::DisplayErrorMessage(CString& errorMessage, wchar_t* logFile) { - CTaskDialog dlg; - TASKDIALOG_BUTTON buttons[] = { - { 1, L"Open Setup Log", }, - { 2, L"Close", }, - }; + CTaskDialog dlg; + TASKDIALOG_BUTTON buttons[] = { + { 1, L"Open Setup Log", }, + { 2, L"Close", }, + }; - // TODO: Something about contacting support? - if (logFile == NULL) { - dlg.SetButtons(&buttons[1], 1, 1); - } else { - dlg.SetButtons(buttons, 2, 1); - } + // TODO: Something about contacting support? + if (logFile == NULL) { + dlg.SetButtons(&buttons[1], 1, 1); + } + else { + dlg.SetButtons(buttons, 2, 1); + } - dlg.SetMainInstructionText(L"Installation has failed"); - dlg.SetContentText(errorMessage); - dlg.SetMainIcon(TD_ERROR_ICON); + dlg.SetMainInstructionText(L"Installation has failed"); + dlg.SetContentText(errorMessage); + dlg.SetMainIcon(TD_ERROR_ICON); - int nButton; + int nButton; - if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton))) { - return; - } + if (FAILED(dlg.DoModal(::GetActiveWindow(), &nButton))) { + return; + } - if (nButton == 1 && logFile != NULL) { - ShellExecute(NULL, NULL, logFile, NULL, NULL, SW_SHOW); - } + if (nButton == 1 && logFile != NULL) { + ShellExecute(NULL, NULL, logFile, NULL, NULL, SW_SHOW); + } } HRESULT CUpdateRunner::AreWeUACElevated() { - HANDLE hProcess = GetCurrentProcess(); - HANDLE hToken = 0; - HRESULT hr; + HANDLE hProcess = GetCurrentProcess(); + HANDLE hToken = 0; + HRESULT hr; - if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { - hr = HRESULT_FROM_WIN32(GetLastError()); - goto out; - } + if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto out; + } - TOKEN_ELEVATION_TYPE elevType; - DWORD dontcare; - if (!GetTokenInformation(hToken, TokenElevationType, &elevType, sizeof(TOKEN_ELEVATION_TYPE), &dontcare)) { - hr = HRESULT_FROM_WIN32(GetLastError()); - goto out; - } + TOKEN_ELEVATION_TYPE elevType; + DWORD dontcare; + if (!GetTokenInformation(hToken, TokenElevationType, &elevType, sizeof(TOKEN_ELEVATION_TYPE), &dontcare)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + goto out; + } - hr = (elevType == TokenElevationTypeFull ? S_OK : S_FALSE); + hr = (elevType == TokenElevationTypeFull ? S_OK : S_FALSE); out: - if (hToken) { - CloseHandle(hToken); - } + if (hToken) { + CloseHandle(hToken); + } - return hr; + return hr; } -HRESULT FindDesktopFolderView(REFIID riid, void **ppv) +HRESULT FindDesktopFolderView(REFIID riid, void** ppv) { - HRESULT hr; + HRESULT hr; - CComPtr spShellWindows; - spShellWindows.CoCreateInstance(CLSID_ShellWindows); + CComPtr spShellWindows; + spShellWindows.CoCreateInstance(CLSID_ShellWindows); - CComVariant vtLoc(CSIDL_DESKTOP); - CComVariant vtEmpty; - long lhwnd; - CComPtr spdisp; + CComVariant vtLoc(CSIDL_DESKTOP); + CComVariant vtEmpty; + long lhwnd; + CComPtr spdisp; - hr = spShellWindows->FindWindowSW( - &vtLoc, &vtEmpty, - SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp); - if (FAILED(hr)) return hr; + hr = spShellWindows->FindWindowSW( + &vtLoc, &vtEmpty, + SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp); + if (FAILED(hr)) return hr; - CComPtr spBrowser; - hr = CComQIPtr(spdisp)->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser)); - if (FAILED(hr)) return hr; + CComPtr spBrowser; + hr = CComQIPtr(spdisp)->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser)); + if (FAILED(hr)) return hr; - CComPtr spView; - hr = spBrowser->QueryActiveShellView(&spView); - if (FAILED(hr)) return hr; + CComPtr spView; + hr = spBrowser->QueryActiveShellView(&spView); + if (FAILED(hr)) return hr; - hr = spView->QueryInterface(riid, ppv); - if (FAILED(hr)) return hr; + hr = spView->QueryInterface(riid, ppv); + if (FAILED(hr)) return hr; - return S_OK; + return S_OK; } -HRESULT GetDesktopAutomationObject(REFIID riid, void **ppv) +HRESULT GetDesktopAutomationObject(REFIID riid, void** ppv) { - HRESULT hr; + HRESULT hr; - CComPtr spsv; - hr = FindDesktopFolderView(IID_PPV_ARGS(&spsv)); - if (FAILED(hr)) return hr; + CComPtr spsv; + hr = FindDesktopFolderView(IID_PPV_ARGS(&spsv)); + if (FAILED(hr)) return hr; - CComPtr spdispView; - hr = spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView)); - if (FAILED(hr)) return hr; + CComPtr spdispView; + hr = spsv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&spdispView)); + if (FAILED(hr)) return hr; - return spdispView->QueryInterface(riid, ppv); + return spdispView->QueryInterface(riid, ppv); } HRESULT CUpdateRunner::ShellExecuteFromExplorer(LPWSTR pszFile, LPWSTR pszParameters) { - HRESULT hr; + HRESULT hr; - CComPtr spFolderView; - hr = GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView)); - if (FAILED(hr)) return hr; + CComPtr spFolderView; + hr = GetDesktopAutomationObject(IID_PPV_ARGS(&spFolderView)); + if (FAILED(hr)) return hr; - CComPtr spdispShell; - hr = spFolderView->get_Application(&spdispShell); - if (FAILED(hr)) return hr; + CComPtr spdispShell; + hr = spFolderView->get_Application(&spdispShell); + if (FAILED(hr)) return hr; - return CComQIPtr(spdispShell)->ShellExecute( - CComBSTR(pszFile), - CComVariant(pszParameters ? pszParameters : L""), - CComVariant(L""), - CComVariant(L""), - CComVariant(SW_SHOWDEFAULT)); + return CComQIPtr(spdispShell)->ShellExecute( + CComBSTR(pszFile), + CComVariant(pszParameters ? pszParameters : L""), + CComVariant(L""), + CComVariant(L""), + CComVariant(SW_SHOWDEFAULT)); } bool CUpdateRunner::DirectoryExists(wchar_t* szPath) { - DWORD dwAttrib = GetFileAttributes(szPath); + DWORD dwAttrib = GetFileAttributes(szPath); - return (dwAttrib != INVALID_FILE_ATTRIBUTES && - (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && + (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } -bool CUpdateRunner::DirectoryIsWritable(wchar_t * szPath) +bool CUpdateRunner::DirectoryIsWritable(wchar_t* szPath) { - wchar_t szTempFileName[MAX_PATH]; - UINT uRetVal = GetTempFileNameW(szPath, L"Squirrel", 0, szTempFileName); - if (uRetVal == 0) { - return false; - } - DeleteFile(szTempFileName); - return true; + wchar_t szTempFileName[MAX_PATH]; + UINT uRetVal = GetTempFileNameW(szPath, L"Squirrel", 0, szTempFileName); + if (uRetVal == 0) { + return false; + } + DeleteFile(szTempFileName); + return true; } int CUpdateRunner::ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir, std::function& callback) { - PROCESS_INFORMATION pi = { 0 }; - STARTUPINFO si = { 0 }; - CResource zipResource; - wchar_t targetDir[MAX_PATH] = { 0 }; - wchar_t logFile[MAX_PATH]; + PROCESS_INFORMATION pi = { 0 }; + STARTUPINFO si = { 0 }; + CResource zipResource; + wchar_t targetDir[MAX_PATH] = { 0 }; + wchar_t logFile[MAX_PATH]; DWORD dwExitCode = 0; - std::vector to_delete; + std::vector to_delete; - wchar_t* envSquirrelTemp = _wgetenv(L"SQUIRREL_TEMP"); - if (envSquirrelTemp && - DirectoryExists(envSquirrelTemp) && - DirectoryIsWritable(envSquirrelTemp) && - !PathIsUNCW(envSquirrelTemp)) { - _swprintf_c(targetDir, _countof(targetDir), L"%s", envSquirrelTemp); - goto gotADir; - } + wchar_t* envSquirrelTemp = _wgetenv(L"SQUIRREL_TEMP"); + if (envSquirrelTemp && + DirectoryExists(envSquirrelTemp) && + DirectoryIsWritable(envSquirrelTemp) && + !PathIsUNCW(envSquirrelTemp)) { + _swprintf_c(targetDir, _countof(targetDir), L"%s", envSquirrelTemp); + goto gotADir; + } - if (!useFallbackDir) { - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, targetDir); - goto gotADir; - } + if (!useFallbackDir) { + SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, targetDir); + goto gotADir; + } - wchar_t username[512]; - wchar_t appDataDir[MAX_PATH]; - ULONG unameSize = _countof(username); + wchar_t username[512]; + wchar_t appDataDir[MAX_PATH]; + ULONG unameSize = _countof(username); - SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataDir); - GetUserName(username, &unameSize); + SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataDir); + GetUserName(username, &unameSize); - _swprintf_c(targetDir, _countof(targetDir), L"%s\\%s", appDataDir, username); + _swprintf_c(targetDir, _countof(targetDir), L"%s\\%s", appDataDir, username); - if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { - wchar_t err[4096]; - _swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir); + if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { + wchar_t err[4096]; + _swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir); callback(); - DisplayErrorMessage(CString(err), NULL); - return -1; - } + DisplayErrorMessage(CString(err), NULL); + return -1; + } gotADir: - wcscat_s(targetDir, _countof(targetDir), L"\\SquirrelTemp"); + wcscat_s(targetDir, _countof(targetDir), L"\\SquirrelTemp"); - if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { - wchar_t err[4096]; - _swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir); + if (!CreateDirectory(targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { + wchar_t err[4096]; + _swprintf_c(err, _countof(err), L"Unable to write to %s - IT policies may be restricting access to this folder", targetDir); - if (useFallbackDir) { + if (useFallbackDir) { callback(); DisplayErrorMessage(CString(err), NULL); - } + } - goto failedExtract; - } + goto failedExtract; + } - swprintf_s(logFile, L"%s\\SquirrelSetup.log", targetDir); + swprintf_s(logFile, L"%s\\SquirrelSetup.log", targetDir); - if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) { - goto failedExtract; - } + if (!zipResource.Load(L"DATA", IDR_UPDATE_ZIP)) { + goto failedExtract; + } - DWORD dwSize = zipResource.GetSize(); - if (dwSize < 0x100) { - goto failedExtract; - } + DWORD dwSize = zipResource.GetSize(); + if (dwSize < 0x100) { + goto failedExtract; + } - BYTE* pData = (BYTE*)zipResource.Lock(); - HZIP zipFile = OpenZip(pData, dwSize, NULL); - SetUnzipBaseDir(zipFile, targetDir); + BYTE* pData = (BYTE*)zipResource.Lock(); + HZIP zipFile = OpenZip(pData, dwSize, NULL); + SetUnzipBaseDir(zipFile, targetDir); - // NB: This library is kind of a disaster - ZRESULT zr; - int index = 0; - do { - ZIPENTRY zentry; - wchar_t targetFile[MAX_PATH]; + // NB: This library is kind of a disaster + ZRESULT zr; + int index = 0; + do { + ZIPENTRY zentry; + wchar_t targetFile[MAX_PATH]; - zr = GetZipItem(zipFile, index, &zentry); - if (zr != ZR_OK && zr != ZR_MORE) { - break; - } + zr = GetZipItem(zipFile, index, &zentry); + if (zr != ZR_OK && zr != ZR_MORE) { + break; + } - // NB: UnzipItem won't overwrite data, we need to do it ourselves - swprintf_s(targetFile, L"%s\\%s", targetDir, zentry.name); - DeleteFile(targetFile); + // NB: UnzipItem won't overwrite data, we need to do it ourselves + swprintf_s(targetFile, L"%s\\%s", targetDir, zentry.name); + DeleteFile(targetFile); - if (UnzipItem(zipFile, index, zentry.name) != ZR_OK) break; - to_delete.push_back(CString(targetFile)); - index++; - } while (zr == ZR_MORE || zr == ZR_OK); + if (UnzipItem(zipFile, index, zentry.name) != ZR_OK) break; + to_delete.push_back(CString(targetFile)); + index++; + } while (zr == ZR_MORE || zr == ZR_OK); - CloseZip(zipFile); - zipResource.Release(); + CloseZip(zipFile); + zipResource.Release(); - // nfi if the zip extract actually worked, check for Update.exe - wchar_t updateExePath[MAX_PATH]; - swprintf_s(updateExePath, L"%s\\%s", targetDir, L"Update.exe"); + // nfi if the zip extract actually worked, check for Update.exe + wchar_t updateExePath[MAX_PATH]; + swprintf_s(updateExePath, L"%s\\%s", targetDir, L"Update.exe"); - if (GetFileAttributes(updateExePath) == INVALID_FILE_ATTRIBUTES) { - goto failedExtract; - } + if (GetFileAttributes(updateExePath) == INVALID_FILE_ATTRIBUTES) { + goto failedExtract; + } - // Run Update.exe - si.cb = sizeof(STARTUPINFO); - si.wShowWindow = SW_SHOW; - si.dwFlags = STARTF_USESHOWWINDOW; + // Run Update.exe + si.cb = sizeof(STARTUPINFO); + si.wShowWindow = SW_SHOW; + si.dwFlags = STARTF_USESHOWWINDOW; - if (!lpCommandLine || wcsnlen_s(lpCommandLine, MAX_PATH) < 1) { - lpCommandLine = L""; - } + if (!lpCommandLine || wcsnlen_s(lpCommandLine, MAX_PATH) < 1) { + lpCommandLine = L""; + } - wchar_t cmd[MAX_PATH]; - swprintf_s(cmd, L"\"%s\" --install . %s", updateExePath, lpCommandLine); + wchar_t cmd[MAX_PATH]; + swprintf_s(cmd, L"\"%s\" --install . %s", updateExePath, lpCommandLine); - if (!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, targetDir, &si, &pi)) { - goto failedExtract; - } + if (!CreateProcess(NULL, cmd, NULL, NULL, false, 0, NULL, targetDir, &si, &pi)) { + goto failedExtract; + } - WaitForSingleObject(pi.hProcess, INFINITE); + WaitForSingleObject(pi.hProcess, INFINITE); - if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) { - dwExitCode = (DWORD)-1; - } + if (!GetExitCodeProcess(pi.hProcess, &dwExitCode)) { + dwExitCode = (DWORD)-1; + } - if (dwExitCode != 0) { + if (dwExitCode != 0) { callback(); - DisplayErrorMessage(CString( - L"There was an error while installing the application. " - L"Check the setup log for more information and contact the author."), logFile); - } + DisplayErrorMessage(CString( + L"There was an error while installing the application. " + L"Check the setup log for more information and contact the author."), logFile); + } - for (unsigned int i = 0; i < to_delete.size(); i++) { - DeleteFile(to_delete[i]); - } + for (unsigned int i = 0; i < to_delete.size(); i++) { + DeleteFile(to_delete[i]); + } - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return (int) dwExitCode; + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return (int)dwExitCode; failedExtract: - if (!useFallbackDir) { - // Take another pass at it, using C:\ProgramData instead - return ExtractUpdaterAndRun(lpCommandLine, true, callback); - } + if (!useFallbackDir) { + // Take another pass at it, using C:\ProgramData instead + return ExtractUpdaterAndRun(lpCommandLine, true, callback); + } callback(); DisplayErrorMessage(CString(L"Failed to extract installer"), NULL); - return (int) dwExitCode; + return (int)dwExitCode; } diff --git a/src/Setup/UpdateRunner.h b/src/Setup/UpdateRunner.h index 102db1de..86a44178 100644 --- a/src/Setup/UpdateRunner.h +++ b/src/Setup/UpdateRunner.h @@ -5,10 +5,11 @@ class CUpdateRunner { public: - static void DisplayErrorMessage(CString& errorMessage, wchar_t* logFile); - static HRESULT AreWeUACElevated(); - static HRESULT ShellExecuteFromExplorer(LPWSTR pszFile, LPWSTR pszParameters); - static bool DirectoryExists(wchar_t* szPath); - static bool DirectoryIsWritable(wchar_t* szPath); - static int ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir, std::function& callback); + static void DisplayErrorMessage(CString& errorMessage, wchar_t* logFile); + static HRESULT AreWeUACElevated(); + static HRESULT ShellExecuteFromExplorer(LPWSTR pszFile, LPWSTR pszParameters); + static bool DirectoryExists(wchar_t* szPath); + static bool DirectoryIsWritable(wchar_t* szPath); + static int ExtractUpdaterAndRun(wchar_t* lpCommandLine, bool useFallbackDir, std::function& callback); + }; diff --git a/src/Setup/unzip.cpp b/src/Setup/unzip.cpp index c2b062c3..6d2c3705 100644 --- a/src/Setup/unzip.cpp +++ b/src/Setup/unzip.cpp @@ -106,38 +106,41 @@ void zfree(void *buf) typedef struct tm_unz_s -{ unsigned int tm_sec; // seconds after the minute - [0,59] - unsigned int tm_min; // minutes after the hour - [0,59] - unsigned int tm_hour; // hours since midnight - [0,23] - unsigned int tm_mday; // day of the month - [1,31] - unsigned int tm_mon; // months since January - [0,11] - unsigned int tm_year; // years - [1980..2044] +{ + unsigned int tm_sec; // seconds after the minute - [0,59] + unsigned int tm_min; // minutes after the hour - [0,59] + unsigned int tm_hour; // hours since midnight - [0,23] + unsigned int tm_mday; // day of the month - [1,31] + unsigned int tm_mon; // months since January - [0,11] + unsigned int tm_year; // years - [1980..2044] } tm_unz; // unz_global_info structure contain global data about the ZIPfile typedef struct unz_global_info_s -{ unsigned long number_entry; // total number of entries in the central dir on this disk - unsigned long size_comment; // size of the global comment of the zipfile +{ + unsigned long number_entry; // total number of entries in the central dir on this disk + unsigned long size_comment; // size of the global comment of the zipfile } unz_global_info; // unz_file_info contain information about a file in the zipfile typedef struct unz_file_info_s -{ unsigned long version; // version made by 2 bytes - unsigned long version_needed; // version needed to extract 2 bytes - unsigned long flag; // general purpose bit flag 2 bytes - unsigned long compression_method; // compression method 2 bytes - unsigned long dosDate; // last mod file date in Dos fmt 4 bytes - unsigned long crc; // crc-32 4 bytes - unsigned long compressed_size; // compressed size 4 bytes - unsigned long uncompressed_size; // uncompressed size 4 bytes - unsigned long size_filename; // filename length 2 bytes - unsigned long size_file_extra; // extra field length 2 bytes - unsigned long size_file_comment; // file comment length 2 bytes - unsigned long disk_num_start; // disk number start 2 bytes - unsigned long internal_fa; // internal file attributes 2 bytes - unsigned long external_fa; // external file attributes 4 bytes - tm_unz tmu_date; +{ + unsigned long version; // version made by 2 bytes + unsigned long version_needed; // version needed to extract 2 bytes + unsigned long flag; // general purpose bit flag 2 bytes + unsigned long compression_method; // compression method 2 bytes + unsigned long dosDate; // last mod file date in Dos fmt 4 bytes + unsigned long crc; // crc-32 4 bytes + unsigned long compressed_size; // compressed size 4 bytes + unsigned long uncompressed_size; // uncompressed size 4 bytes + unsigned long size_filename; // filename length 2 bytes + unsigned long size_file_extra; // extra field length 2 bytes + unsigned long size_file_comment; // file comment length 2 bytes + unsigned long disk_num_start; // disk number start 2 bytes + unsigned long internal_fa; // internal file attributes 2 bytes + unsigned long external_fa; // external file attributes 4 bytes + tm_unz tmu_date; } unz_file_info; @@ -212,8 +215,8 @@ typedef struct unz_file_info_s typedef unsigned char Byte; // 8 bits typedef unsigned int uInt; // 16 bits or more typedef unsigned long uLong; // 32 bits or more -typedef void *voidpf; -typedef void *voidp; +typedef void* voidpf; +typedef void* voidp; typedef long z_off_t; @@ -227,22 +230,23 @@ typedef long z_off_t; -typedef voidpf (*alloc_func) (voidpf opaque, uInt items, uInt size); +typedef voidpf(*alloc_func) (voidpf opaque, uInt items, uInt size); typedef void (*free_func) (voidpf opaque, voidpf address); struct internal_state; -typedef struct z_stream_s { - Byte *next_in; // next input byte +typedef struct z_stream_s +{ + Byte* next_in; // next input byte uInt avail_in; // number of bytes available at next_in uLong total_in; // total nb of input bytes read so far - Byte *next_out; // next output byte should be put there + Byte* next_out; // next output byte should be put there uInt avail_out; // remaining free space at next_out uLong total_out; // total nb of bytes output so far - char *msg; // last error message, NULL if no error - struct internal_state *state; // not visible by applications + char* msg; // last error message, NULL if no error + struct internal_state* state; // not visible by applications alloc_func zalloc; // used to allocate the internal state free_func zfree; // used to free the internal state @@ -253,7 +257,7 @@ typedef struct z_stream_s { uLong reserved; // reserved for future use } z_stream; -typedef z_stream *z_streamp; +typedef z_stream* z_streamp; // The application must update next_in and avail_in when avail_in has @@ -281,7 +285,7 @@ typedef z_stream *z_streamp; // basic functions -const char *zlibVersion (); +const char* zlibVersion(); // The application can compare zlibVersion and ZLIB_VERSION for consistency. // If the first character differs, the library code actually used is // not compatible with the zlib.h header file used by the application. @@ -292,7 +296,7 @@ const char *zlibVersion (); -int inflate (z_streamp strm, int flush); +int inflate(z_streamp strm, int flush); // // inflate decompresses as much data as possible, and stops when the input // buffer becomes empty or the output buffer becomes full. It may some @@ -361,7 +365,7 @@ int inflate (z_streamp strm, int flush); // -int inflateEnd (z_streamp strm); +int inflateEnd(z_streamp strm); // // All dynamically allocated data structures for this stream are freed. // This function discards any unprocessed input and does not flush any @@ -379,8 +383,8 @@ int inflateEnd (z_streamp strm); -int inflateSetDictionary (z_streamp strm, - const Byte *dictionary, +int inflateSetDictionary(z_streamp strm, + const Byte* dictionary, uInt dictLength); // // Initializes the decompression dictionary from the given uncompressed byte @@ -398,7 +402,7 @@ int inflateSetDictionary (z_streamp strm, // inflate(). -int inflateSync (z_streamp strm); +int inflateSync(z_streamp strm); // // Skips invalid compressed data until a full flush point can be found, or until all // available input is skipped. No output is provided. @@ -412,7 +416,7 @@ int inflateSync (z_streamp strm); // until success or end of the input data. -int inflateReset (z_streamp strm); +int inflateReset(z_streamp strm); // This function is equivalent to inflateEnd followed by inflateInit, // but does not free and reallocate all the internal decompression state. // The stream will keep attributes that may have been set by inflateInit2. @@ -428,7 +432,7 @@ int inflateReset (z_streamp strm); // anyway because they might be useful in applications using the // compression library. -uLong adler32 (uLong adler, const Byte *buf, uInt len); +uLong adler32(uLong adler, const Byte* buf, uInt len); // Update a running Adler-32 checksum with the bytes buf[0..len-1] and // return the updated checksum. If buf is NULL, this function returns // the required initial value for the checksum. @@ -442,7 +446,7 @@ uLong adler32 (uLong adler, const Byte *buf, uInt len); // } // if (adler != original_adler) error(); -uLong ucrc32 (uLong crc, const Byte *buf, uInt len); +uLong ucrc32(uLong crc, const Byte* buf, uInt len); // Update a running crc with the bytes buf[0..len-1] and return the updated // crc. If buf is NULL, this function returns the required initial value // for the crc. Pre- and post-conditioning (one's complement) is performed @@ -459,9 +463,9 @@ uLong ucrc32 (uLong crc, const Byte *buf, uInt len); -const char *zError (int err); -int inflateSyncPoint (z_streamp z); -const uLong *get_crc_table (void); +const char* zError(int err); +int inflateSyncPoint(z_streamp z); +const uLong* get_crc_table(void); @@ -473,7 +477,7 @@ typedef unsigned long ulg; -const char * const z_errmsg[10] = { // indexed by 2-zlib_error +const char* const z_errmsg[10] = { // indexed by 2-zlib_error "need dictionary", // Z_NEED_DICT 2 "stream end", // Z_STREAM_END 1 "", // Z_OK 0 @@ -483,7 +487,7 @@ const char * const z_errmsg[10] = { // indexed by 2-zlib_error "insufficient memory", // Z_MEM_ERROR (-4) "buffer error", // Z_BUF_ERROR (-5) "incompatible version",// Z_VERSION_ERROR (-6) -""}; +"" }; #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] @@ -525,9 +529,9 @@ const char * const z_errmsg[10] = { // indexed by 2-zlib_error #define LuTracecv(c,x) -typedef uLong (*check_func) (uLong check, const Byte *buf, uInt len); -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size); -void zcfree (voidpf opaque, voidpf ptr); +typedef uLong(*check_func) (uLong check, const Byte* buf, uInt len); +voidpf zcalloc(voidpf opaque, unsigned items, unsigned size); +void zcfree(voidpf opaque, voidpf ptr); #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) @@ -548,15 +552,18 @@ void zcfree (voidpf opaque, voidpf ptr); typedef struct inflate_huft_s inflate_huft; -struct inflate_huft_s { - union { - struct { - Byte Exop; // number of extra bits or operation - Byte Bits; // number of bits in this code or subcode - } what; - uInt pad; // pad structure to a power of 2 (4 bytes for - } word; // 16-bit, 8 bytes for 32-bit int's) - uInt base; // literal, length base, distance base, or table offset +struct inflate_huft_s +{ + union + { + struct + { + Byte Exop; // number of extra bits or operation + Byte Bits; // number of bits in this code or subcode + } what; + uInt pad; // pad structure to a power of 2 (4 bytes for + } word; // 16-bit, 8 bytes for 32-bit int's) + uInt base; // literal, length base, distance base, or table offset }; // Maximum size of dynamic tree. The maximum found in a long but non- @@ -566,29 +573,29 @@ struct inflate_huft_s { // value below is more than safe. #define MANY 1440 -int inflate_trees_bits ( - uInt *, // 19 code lengths - uInt *, // bits tree desired/actual depth - inflate_huft * *, // bits tree result - inflate_huft *, // space for trees +int inflate_trees_bits( + uInt*, // 19 code lengths + uInt*, // bits tree desired/actual depth + inflate_huft**, // bits tree result + inflate_huft*, // space for trees z_streamp); // for messages -int inflate_trees_dynamic ( +int inflate_trees_dynamic( uInt, // number of literal/length codes uInt, // number of distance codes - uInt *, // that many (total) code lengths - uInt *, // literal desired/actual bit depth - uInt *, // distance desired/actual bit depth - inflate_huft * *, // literal/length tree result - inflate_huft * *, // distance tree result - inflate_huft *, // space for trees + uInt*, // that many (total) code lengths + uInt*, // literal desired/actual bit depth + uInt*, // distance desired/actual bit depth + inflate_huft**, // literal/length tree result + inflate_huft**, // distance tree result + inflate_huft*, // space for trees z_streamp); // for messages -int inflate_trees_fixed ( - uInt *, // literal desired/actual bit depth - uInt *, // distance desired/actual bit depth - const inflate_huft * *, // literal/length tree result - const inflate_huft * *, // distance tree result +int inflate_trees_fixed( + uInt*, // literal desired/actual bit depth + uInt*, // distance desired/actual bit depth + const inflate_huft**, // literal/length tree result + const inflate_huft**, // distance tree result z_streamp); // for memory allocation @@ -598,32 +605,32 @@ int inflate_trees_fixed ( struct inflate_blocks_state; typedef struct inflate_blocks_state inflate_blocks_statef; -inflate_blocks_statef * inflate_blocks_new ( +inflate_blocks_statef* inflate_blocks_new( z_streamp z, check_func c, // check function uInt w); // window size -int inflate_blocks ( - inflate_blocks_statef *, - z_streamp , +int inflate_blocks( + inflate_blocks_statef*, + z_streamp, int); // initial return code -void inflate_blocks_reset ( - inflate_blocks_statef *, - z_streamp , - uLong *); // check value on output +void inflate_blocks_reset( + inflate_blocks_statef*, + z_streamp, + uLong*); // check value on output -int inflate_blocks_free ( - inflate_blocks_statef *, +int inflate_blocks_free( + inflate_blocks_statef*, z_streamp); -void inflate_set_dictionary ( - inflate_blocks_statef *s, - const Byte *d, // dictionary +void inflate_set_dictionary( + inflate_blocks_statef* s, + const Byte* d, // dictionary uInt n); // dictionary length -int inflate_blocks_sync_point ( - inflate_blocks_statef *s); +int inflate_blocks_sync_point( + inflate_blocks_statef* s); @@ -631,69 +638,75 @@ int inflate_blocks_sync_point ( struct inflate_codes_state; typedef struct inflate_codes_state inflate_codes_statef; -inflate_codes_statef *inflate_codes_new ( +inflate_codes_statef* inflate_codes_new( uInt, uInt, - const inflate_huft *, const inflate_huft *, - z_streamp ); + const inflate_huft*, const inflate_huft*, + z_streamp); -int inflate_codes ( - inflate_blocks_statef *, - z_streamp , +int inflate_codes( + inflate_blocks_statef*, + z_streamp, int); -void inflate_codes_free ( - inflate_codes_statef *, - z_streamp ); +void inflate_codes_free( + inflate_codes_statef*, + z_streamp); -typedef enum { - IBM_TYPE, // get type bits (3, including end bit) - IBM_LENS, // get lengths for stored - IBM_STORED, // processing stored block - IBM_TABLE, // get table lengths - IBM_BTREE, // get bit lengths tree for a dynamic block - IBM_DTREE, // get length, distance trees for a dynamic block - IBM_CODES, // processing fixed or dynamic block - IBM_DRY, // output remaining window bytes - IBM_DONE, // finished last block, done - IBM_BAD} // got a data error--stuck here +typedef enum +{ + IBM_TYPE, // get type bits (3, including end bit) + IBM_LENS, // get lengths for stored + IBM_STORED, // processing stored block + IBM_TABLE, // get table lengths + IBM_BTREE, // get bit lengths tree for a dynamic block + IBM_DTREE, // get length, distance trees for a dynamic block + IBM_CODES, // processing fixed or dynamic block + IBM_DRY, // output remaining window bytes + IBM_DONE, // finished last block, done + IBM_BAD +} // got a data error--stuck here inflate_block_mode; // inflate blocks semi-private state -struct inflate_blocks_state { +struct inflate_blocks_state +{ - // mode - inflate_block_mode mode; // current inflate_block mode + // mode + inflate_block_mode mode; // current inflate_block mode - // mode dependent information - union { - uInt left; // if STORED, bytes left to copy - struct { - uInt table; // table lengths (14 bits) - uInt index; // index into blens (or border) - uInt *blens; // bit lengths of codes - uInt bb; // bit length tree depth - inflate_huft *tb; // bit length decoding tree - } trees; // if DTREE, decoding info for trees - struct { - inflate_codes_statef - *codes; - } decode; // if CODES, current state - } sub; // submode - uInt last; // true if this block is the last block + // mode dependent information + union + { + uInt left; // if STORED, bytes left to copy + struct + { + uInt table; // table lengths (14 bits) + uInt index; // index into blens (or border) + uInt* blens; // bit lengths of codes + uInt bb; // bit length tree depth + inflate_huft* tb; // bit length decoding tree + } trees; // if DTREE, decoding info for trees + struct + { + inflate_codes_statef + * codes; + } decode; // if CODES, current state + } sub; // submode + uInt last; // true if this block is the last block - // mode independent information - uInt bitk; // bits in bit buffer - uLong bitb; // bit buffer - inflate_huft *hufts; // single malloc for tree space - Byte *window; // sliding window - Byte *end; // one byte after sliding window - Byte *read; // window read pointer - Byte *write; // window write pointer - check_func checkfn; // check function - uLong check; // check on output + // mode independent information + uInt bitk; // bits in bit buffer + uLong bitb; // bit buffer + inflate_huft* hufts; // single malloc for tree space + Byte* window; // sliding window + Byte* end; // one byte after sliding window + Byte* read; // window read pointer + Byte* write; // window write pointer + check_func checkfn; // check function + uLong check; // check on output }; @@ -730,9 +743,9 @@ const uInt inflate_mask[17] = { }; // copy as much as possible from the sliding window to the output area -int inflate_flush (inflate_blocks_statef *, z_streamp, int); +int inflate_flush(inflate_blocks_statef*, z_streamp, int); -int inflate_fast (uInt, uInt, const inflate_huft *, const inflate_huft *, inflate_blocks_statef *, z_streamp ); +int inflate_fast(uInt, uInt, const inflate_huft*, const inflate_huft*, inflate_blocks_statef*, z_streamp); @@ -867,7 +880,7 @@ const inflate_huft fixed_tl[] = { {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; +}; const inflate_huft fixed_td[] = { {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, @@ -877,7 +890,7 @@ const inflate_huft fixed_td[] = { {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; +}; @@ -886,46 +899,18 @@ const inflate_huft fixed_td[] = { // copy as much as possible from the sliding window to the output area -int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r) +int inflate_flush(inflate_blocks_statef* s, z_streamp z, int r) { - uInt n; - Byte *p; - Byte *q; + uInt n; + Byte* p; + Byte* q; - // local copies of source and destination pointers - p = z->next_out; - q = s->read; + // local copies of source and destination pointers + p = z->next_out; + q = s->read; - // compute number of bytes to copy as far as end of window - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - // update counters - z->avail_out -= n; - z->total_out += n; - - // update check information - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - // copy as far as end of window - if (n!=0) // check for n!=0 to avoid waking up CodeGuard - { memcpy(p, q, n); - p += n; - q += n; - } - - // see if more to copy at beginning of window - if (q == s->end) - { - // wrap pointers - q = s->window; - if (s->write == s->end) - s->write = s->window; - - // compute bytes to copy - n = (uInt)(s->write - q); + // compute number of bytes to copy as far as end of window + n = (uInt)((q <= s->write ? s->write : s->end) - q); if (n > z->avail_out) n = z->avail_out; if (n && r == Z_BUF_ERROR) r = Z_OK; @@ -935,18 +920,46 @@ int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r) // update check information if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); + z->adler = s->check = (*s->checkfn)(s->check, q, n); - // copy - if (n!=0) {memcpy(p,q,n); p+=n; q+=n;} - } + // copy as far as end of window + if (n != 0) // check for n!=0 to avoid waking up CodeGuard + { + memcpy(p, q, n); + p += n; + q += n; + } - // update pointers - z->next_out = p; - s->read = q; + // see if more to copy at beginning of window + if (q == s->end) { + // wrap pointers + q = s->window; + if (s->write == s->end) + s->write = s->window; - // done - return r; + // compute bytes to copy + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z->avail_out -= n; + z->total_out += n; + + // update check information + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + // copy + if (n != 0) { memcpy(p, q, n); p += n; q += n; } + } + + // update pointers + z->next_out = p; + s->read = q; + + // done + return r; } @@ -958,231 +971,233 @@ int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r) #define exop word.what.Exop #define bits word.what.Bits -typedef enum { // waiting for "i:"=input, "o:"=output, "x:"=nothing - START, // x: set up for LEN - LEN, // i: get length/literal/eob next - LENEXT, // i: getting length extra (have base) - DIST, // i: get distance next - DISTEXT, // i: getting distance extra - COPY, // o: copying bytes in window, waiting for space - LIT, // o: got literal, waiting for output space - WASH, // o: got eob, possibly still output waiting - END, // x: got eob and all data flushed - BADCODE} // x: got error +typedef enum +{ // waiting for "i:"=input, "o:"=output, "x:"=nothing + START, // x: set up for LEN + LEN, // i: get length/literal/eob next + LENEXT, // i: getting length extra (have base) + DIST, // i: get distance next + DISTEXT, // i: getting distance extra + COPY, // o: copying bytes in window, waiting for space + LIT, // o: got literal, waiting for output space + WASH, // o: got eob, possibly still output waiting + END, // x: got eob and all data flushed + BADCODE +} // x: got error inflate_codes_mode; // inflate codes private state -struct inflate_codes_state { +struct inflate_codes_state +{ - // mode - inflate_codes_mode mode; // current inflate_codes mode + // mode + inflate_codes_mode mode; // current inflate_codes mode - // mode dependent information - uInt len; - union { - struct { - const inflate_huft *tree; // pointer into tree - uInt need; // bits needed - } code; // if LEN or DIST, where in tree - uInt lit; // if LIT, literal - struct { - uInt get; // bits to get for extra - uInt dist; // distance back to copy from - } copy; // if EXT or COPY, where and how much - } sub; // submode + // mode dependent information + uInt len; + union + { + struct + { + const inflate_huft* tree; // pointer into tree + uInt need; // bits needed + } code; // if LEN or DIST, where in tree + uInt lit; // if LIT, literal + struct + { + uInt get; // bits to get for extra + uInt dist; // distance back to copy from + } copy; // if EXT or COPY, where and how much + } sub; // submode - // mode independent information - Byte lbits; // ltree bits decoded per branch - Byte dbits; // dtree bits decoder per branch - const inflate_huft *ltree; // literal/length/eob tree - const inflate_huft *dtree; // distance tree + // mode independent information + Byte lbits; // ltree bits decoded per branch + Byte dbits; // dtree bits decoder per branch + const inflate_huft* ltree; // literal/length/eob tree + const inflate_huft* dtree; // distance tree }; -inflate_codes_statef *inflate_codes_new( +inflate_codes_statef* inflate_codes_new( uInt bl, uInt bd, -const inflate_huft *tl, -const inflate_huft *td, // need separate declaration for Borland C++ +const inflate_huft* tl, +const inflate_huft* td, // need separate declaration for Borland C++ z_streamp z) { - inflate_codes_statef *c; + inflate_codes_statef* c; - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - LuTracev((stderr, "inflate: codes new\n")); - } - return c; + if ((c = (inflate_codes_statef*) + ZALLOC(z, 1, sizeof(struct inflate_codes_state))) != Z_NULL) { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + LuTracev((stderr, "inflate: codes new\n")); + } + return c; } -int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r) +int inflate_codes(inflate_blocks_statef* s, z_streamp z, int r) { - uInt j; // temporary storage - const inflate_huft *t; // temporary pointer - uInt e; // extra bits or operation - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer - Byte *f; // pointer to copy strings from - inflate_codes_statef *c = s->sub.decode.codes; // codes state + uInt j; // temporary storage + const inflate_huft* t; // temporary pointer + uInt e; // extra bits or operation + uLong b; // bit buffer + uInt k; // bits in bit buffer + Byte* p; // input data pointer + uInt n; // bytes available there + Byte* q; // output window write pointer + uInt m; // bytes to end of window or read pointer + Byte* f; // pointer to copy strings from + inflate_codes_statef* c = s->sub.decode.codes; // codes state - // copy input/output information to locals (UPDATE macro restores) - LOAD + // copy input/output information to locals (UPDATE macro restores) + LOAD - // process input and output based on current state - for(;;) switch (c->mode) - { // waiting for "i:"=input, "o:"=output, "x:"=nothing - case START: // x: set up for LEN + // process input and output based on current state + for (;;) switch (c->mode) { // waiting for "i:"=input, "o:"=output, "x:"=nothing + case START: // x: set up for LEN #ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } + if (m >= 258 && n >= 10) { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } #endif // !SLOW - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: // i: get length/literal/eob next - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) // literal - { - c->sub.lit = t->base; - LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) // length - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) // next table - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) // end of block - { - LuTracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; // invalid code - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: // i: getting length extra (have base) - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - LuTracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: // i: get distance next - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) // distance - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) // next table - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; // invalid code - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: // i: getting distance extra - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - LuTracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: // o: copying bytes in window, waiting for space - f = q - c->sub.copy.dist; - while (f < s->window) // modulo window size-"while" instead - f += s->end - s->window; // of "if" handles invalid distances - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: // o: got literal, waiting for output space - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: // o: got eob, possibly more output - if (k > 7) // return unused byte, if any - { - //Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; // can always return one - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: // x: got error - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: // i: get length/literal/eob next + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) // literal + { + c->sub.lit = t->base; + LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) // length + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) // next table + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) // end of block + { + LuTracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; // invalid code + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: // i: getting length extra (have base) + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + LuTracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: // i: get distance next + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) // distance + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) // next table + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; // invalid code + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: // i: getting distance extra + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + LuTracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: // o: copying bytes in window, waiting for space + f = q - c->sub.copy.dist; + while (f < s->window) // modulo window size-"while" instead + f += s->end - s->window; // of "if" handles invalid distances + while (c->len) { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: // o: got literal, waiting for output space + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: // o: got eob, possibly more output + if (k > 7) // return unused byte, if any + { + //Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; // can always return one + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: // x: got error + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } } -void inflate_codes_free(inflate_codes_statef *c,z_streamp z) -{ ZFREE(z, c); - LuTracev((stderr, "inflate: codes free\n")); +void inflate_codes_free(inflate_codes_statef* c, z_streamp z) +{ + ZFREE(z, c); + LuTracev((stderr, "inflate: codes free\n")); } @@ -1197,7 +1212,7 @@ void inflate_codes_free(inflate_codes_statef *c,z_streamp z) // Table for deflate from PKZIP's appnote.txt. const uInt border[] = { // Order of the bit length code lengths - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; // // Notes beyond the 1.93a appnote.txt: @@ -1243,309 +1258,291 @@ const uInt border[] = { // Order of the bit length code lengths // the two sets of lengths. -void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c) +void inflate_blocks_reset(inflate_blocks_statef* s, z_streamp z, uLong* c) { - if (c != Z_NULL) - *c = s->check; - if (s->mode == IBM_BTREE || s->mode == IBM_DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == IBM_CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = IBM_TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0); - LuTracev((stderr, "inflate: blocks reset\n")); + if (c != Z_NULL) + *c = s->check; + if (s->mode == IBM_BTREE || s->mode == IBM_DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == IBM_CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = IBM_TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Byte*)Z_NULL, 0); + LuTracev((stderr, "inflate: blocks reset\n")); } -inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w) +inflate_blocks_statef* inflate_blocks_new(z_streamp z, check_func c, uInt w) { - inflate_blocks_statef *s; + inflate_blocks_statef* s; - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + if ((s = (inflate_blocks_statef*)ZALLOC + (z, 1, sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft*)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Byte*)ZALLOC(z, 1, w)) == Z_NULL) { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = IBM_TYPE; + LuTracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = IBM_TYPE; - LuTracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; } -int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r) +int inflate_blocks(inflate_blocks_statef* s, z_streamp z, int r) { - uInt t; // temporary storage - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer + uInt t; // temporary storage + uLong b; // bit buffer + uInt k; // bits in bit buffer + Byte* p; // input data pointer + uInt n; // bytes available there + Byte* q; // output window write pointer + uInt m; // bytes to end of window or read pointer - // copy input/output information to locals (UPDATE macro restores) - LOAD + // copy input/output information to locals (UPDATE macro restores) + LOAD - // process input based on current state - for(;;) switch (s->mode) - { - case IBM_TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: // stored - LuTracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; // go to byte boundary - DUMPBITS(t) - s->mode = IBM_LENS; // get length of stored block - break; - case 1: // fixed - LuTracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - const inflate_huft *tl, *td; + // process input based on current state + for (;;) switch (s->mode) { + case IBM_TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) { + case 0: // stored + LuTracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; // go to byte boundary + DUMPBITS(t) + s->mode = IBM_LENS; // get length of stored block + break; + case 1: // fixed + LuTracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + const inflate_huft* tl, * td; - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = IBM_CODES; + break; + case 2: // dynamic + LuTracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = IBM_TABLE; + break; + case 3: // illegal + DUMPBITS(3) + s->mode = IBM_BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE } - } - DUMPBITS(3) - s->mode = IBM_CODES; - break; - case 2: // dynamic - LuTracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = IBM_TABLE; - break; - case 3: // illegal - DUMPBITS(3) - s->mode = IBM_BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case IBM_LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = IBM_BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; // dump bits - LuTracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? IBM_STORED : (s->last ? IBM_DRY : IBM_TYPE); - break; - case IBM_STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - memcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - LuTracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? IBM_DRY : IBM_TYPE; - break; - case IBM_TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; - // remove this section to workaround bug in pkzip - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = IBM_BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } - // end remove - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - LuTracev((stderr, "inflate: table sizes ok\n")); - s->mode = IBM_BTREE; - case IBM_BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - r = t; - if (r == Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = IBM_BAD; - } - LEAVE - } - s->sub.trees.index = 0; - LuTracev((stderr, "inflate: bits tree ok\n")); - s->mode = IBM_DTREE; - case IBM_DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; + break; + case IBM_LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) { + s->mode = IBM_BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; // dump bits + LuTracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? IBM_STORED : (s->last ? IBM_DRY : IBM_TYPE); + break; + case IBM_STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + memcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + LuTracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? IBM_DRY : IBM_TYPE; + break; + case IBM_TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; + // remove this section to workaround bug in pkzip + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { + s->mode = IBM_BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } + // end remove + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + LuTracev((stderr, "inflate: table sizes ok\n")); + s->mode = IBM_BTREE; + case IBM_BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) { + r = t; + if (r == Z_DATA_ERROR) { + ZFREE(z, s->sub.trees.blens); + s->mode = IBM_BAD; + } + LEAVE + } + s->sub.trees.index = 0; + LuTracev((stderr, "inflate: bits tree ok\n")); + s->mode = IBM_DTREE; + case IBM_DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) { + inflate_huft* h; + uInt i, j, c; - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else // c == 16..18 - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else // c == 16..18 + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) { + ZFREE(z, s->sub.trees.blens); + s->mode = IBM_BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft* tl, * td; + inflate_codes_statef* c; + + bl = 9; // must be <= 9 for lookahead assumptions + bd = 6; // must be <= 9 for lookahead assumptions + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) { + if (t == (uInt)Z_DATA_ERROR) { + ZFREE(z, s->sub.trees.blens); + s->mode = IBM_BAD; + } + r = t; + LEAVE + } + LuTracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } ZFREE(z, s->sub.trees.blens); - s->mode = IBM_BAD; - z->msg = (char*)"invalid bit length repeat"; + s->mode = IBM_CODES; + case IBM_CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + LuTracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) { + s->mode = IBM_TYPE; + break; + } + s->mode = IBM_DRY; + case IBM_DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = IBM_DONE; + case IBM_DONE: + r = Z_STREAM_END; + LEAVE + case IBM_BAD: r = Z_DATA_ERROR; LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; + default: + r = Z_STREAM_ERROR; + LEAVE } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; // must be <= 9 for lookahead assumptions - bd = 6; // must be <= 9 for lookahead assumptions - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - { - ZFREE(z, s->sub.trees.blens); - s->mode = IBM_BAD; - } - r = t; - LEAVE - } - LuTracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - ZFREE(z, s->sub.trees.blens); - s->mode = IBM_CODES; - case IBM_CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - LuTracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = IBM_TYPE; - break; - } - s->mode = IBM_DRY; - case IBM_DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = IBM_DONE; - case IBM_DONE: - r = Z_STREAM_END; - LEAVE - case IBM_BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } } -int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z) +int inflate_blocks_free(inflate_blocks_statef* s, z_streamp z) { - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - LuTracev((stderr, "inflate: blocks freed\n")); - return Z_OK; + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + LuTracev((stderr, "inflate: blocks freed\n")); + return Z_OK; } @@ -1558,7 +1555,7 @@ int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z) extern const char inflate_copyright[] = - " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; +" inflate 1.1.3 Copyright 1995-1998 Mark Adler "; // If you use the zlib library in a product, an acknowledgment is welcome // in the documentation of your product. If for some reason you cannot // include such an acknowledgment, I would appreciate that you keep this @@ -1566,34 +1563,34 @@ extern const char inflate_copyright[] = -int huft_build ( - uInt *, // code lengths in bits +int huft_build( + uInt*, // code lengths in bits uInt, // number of codes uInt, // number of "simple" codes - const uInt *, // list of base values for non-simple codes - const uInt *, // list of extra bits for non-simple codes - inflate_huft **,// result: starting table - uInt *, // maximum lookup bits (returns actual) - inflate_huft *, // space for trees - uInt *, // hufts used in space - uInt * ); // space for values + const uInt*, // list of base values for non-simple codes + const uInt*, // list of extra bits for non-simple codes + inflate_huft**,// result: starting table + uInt*, // maximum lookup bits (returns actual) + inflate_huft*, // space for trees + uInt*, // hufts used in space + uInt*); // space for values // Tables for deflate from PKZIP's appnote.txt. const uInt cplens[31] = { // Copy lengths for literal codes 257..285 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - // see note #13 above about 258 + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }; +// see note #13 above about 258 const uInt cplext[31] = { // Extra bits for literal codes 257..285 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; // 112==invalid + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 }; // 112==invalid const uInt cpdist[30] = { // Copy offsets for distance codes 0..29 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; + 8193, 12289, 16385, 24577 }; const uInt cpdext[30] = { // Extra bits for distance codes 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; + 12, 12, 13, 13 }; // // Huffman code decoding is performed using a multi-level table lookup. @@ -1632,288 +1629,276 @@ const uInt cpdext[30] = { // Extra bits for distance codes #define BMAX 15 // maximum bit length of any code int huft_build( -uInt *b, // code lengths in bits (all assumed <= BMAX) +uInt* b, // code lengths in bits (all assumed <= BMAX) uInt n, // number of codes (assumed <= 288) uInt s, // number of simple-valued codes (0..s-1) -const uInt *d, // list of base values for non-simple codes -const uInt *e, // list of extra bits for non-simple codes -inflate_huft * *t, // result: starting table -uInt *m, // maximum lookup bits, returns actual -inflate_huft *hp, // space for trees -uInt *hn, // hufts used in space -uInt *v) // working area: values in order of bit length +const uInt* d, // list of base values for non-simple codes +const uInt* e, // list of extra bits for non-simple codes +inflate_huft** t, // result: starting table +uInt* m, // maximum lookup bits, returns actual +inflate_huft* hp, // space for trees +uInt* hn, // hufts used in space +uInt* v) // working area: values in order of bit length // Given a list of code lengths and a maximum table size, make a set of // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR // if the given code set is incomplete (the tables are still built in this // case), or Z_DATA_ERROR if the input is invalid. { - uInt a; // counter for codes of length k - uInt c[BMAX+1]; // bit length count table - uInt f; // i repeats in table every f entries - int g; // maximum code length - int h; // table level - register uInt i; // counter, current code - register uInt j; // counter - register int k; // number of bits in current code - int l; // bits per table (returned in m) - uInt mask; // (1 << w) - 1, to avoid cc -O bug on HP - register uInt *p; // pointer into c[], b[], or v[] - inflate_huft *q; // points to current table - struct inflate_huft_s r; // table entry for structure assignment - inflate_huft *u[BMAX]; // table stack - register int w; // bits before this table == (l * h) - uInt x[BMAX+1]; // bit offsets, then code stack - uInt *xp; // pointer into x - int y; // number of dummy codes added - uInt z; // number of entries in current table + uInt a; // counter for codes of length k + uInt c[BMAX + 1]; // bit length count table + uInt f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + register uInt i; // counter, current code + register uInt j; // counter + register int k; // number of bits in current code + int l; // bits per table (returned in m) + uInt mask; // (1 << w) - 1, to avoid cc -O bug on HP + register uInt* p; // pointer into c[], b[], or v[] + inflate_huft* q; // points to current table + struct inflate_huft_s r; // table entry for structure assignment + inflate_huft* u[BMAX]; // table stack + register int w; // bits before this table == (l * h) + uInt x[BMAX + 1]; // bit offsets, then code stack + uInt* xp; // pointer into x + int y; // number of dummy codes added + uInt z; // number of entries in current table - // Generate counts for each bit length - p = c; + // Generate counts for each bit length + p = c; #define C0 *p++ = 0; #define C2 C0 C0 C0 C0 #define C4 C2 C2 C2 C2 - C4; p; // clear c[]--assume BMAX+1 is 16 - p = b; i = n; - do { - c[*p++]++; // assume all entries <= BMAX - } while (--i); - if (c[0] == n) // null input--all zero length codes - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - // Find minimum and maximum length, bound *m by those - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; // minimum code length - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; // maximum code length - if ((uInt)l > i) - l = i; - *m = l; - - - // Adjust last length count to fill out codes, if needed - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - // Generate starting offsets into the value table for each length - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { // note that i == g from above - *xp++ = (j += *p++); - } - - - // Make a table of values in order of bit lengths - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; // set n to length of v - - - // Generate the Huffman codes and for each, make the table entries - x[0] = i = 0; // first Huffman code is zero - p = v; // grab values in bit order - h = -1; // no tables yet--level -1 - w = -l; // bits decoded == (l * h) - u[0] = (inflate_huft *)Z_NULL; // just to keep compilers happy - q = (inflate_huft *)Z_NULL; // ditto - z = 0; // ditto - - // go through the bit lengths (k already is bits in shortest code) - for (; k <= g; k++) - { - a = c[k]; - while (a--) + C4; p; // clear c[]--assume BMAX+1 is 16 + p = b; i = n; + do { + c[*p++]++; // assume all entries <= BMAX + } while (--i); + if (c[0] == n) // null input--all zero length codes { - // here i is the Huffman code of length k bits for value *p - // make tables up to required level - while (k > w + l) - { - h++; - w += l; // previous table always l bits + *t = (inflate_huft*)Z_NULL; + *m = 0; + return Z_OK; + } - // compute minimum size table less than or equal to l bits - z = g - w; - z = z > (uInt)l ? l : z; // table size upper limit - if ((f = 1 << (j = k - w)) > a + 1) // try a k-w bit table - { // too few codes for k-w bit table - f -= a + 1; // deduct codes from patterns left - xp = c + k; - if (j < z) - while (++j < z) // try smaller tables up to z bits - { - if ((f <<= 1) <= *++xp) - break; // enough codes to use up j bits - f -= *xp; // else deduct codes from patterns + + // Find minimum and maximum length, bound *m by those + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; // minimum code length + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; // maximum code length + if ((uInt)l > i) + l = i; + *m = l; + + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { // note that i == g from above + *xp++ = (j += *p++); + } + + + // Make a table of values in order of bit lengths + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; // set n to length of v + + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = v; // grab values in bit order + h = -1; // no tables yet--level -1 + w = -l; // bits decoded == (l * h) + u[0] = (inflate_huft*)Z_NULL; // just to keep compilers happy + q = (inflate_huft*)Z_NULL; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++) { + a = c[k]; + while (a--) { + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l) { + h++; + w += l; // previous table always l bits + + // compute minimum size table less than or equal to l bits + z = g - w; + z = z > (uInt)l ? l : z; // table size upper limit + if ((f = 1 << (j = k - w)) > a + 1) // try a k-w bit table + { // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = c + k; + if (j < z) + while (++j < z) // try smaller tables up to z bits + { + if ((f <<= 1) <= *++xp) + break; // enough codes to use up j bits + f -= *xp; // else deduct codes from patterns + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (*hn + z > MANY) // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + u[h] = q = hp + *hn; + *hn += z; + + // connect to last table, if there is one + if (h) { + x[h] = i; // save pattern for backing up + r.bits = (Byte)l; // bits to dump before this table + r.exop = (Byte)j; // bits in this table + j = i >> (w - l); + r.base = (uInt)(q - u[h - 1] - j); // offset to this table + u[h - 1][j] = r; // connect to last table + } + else + *t = q; // first table is returned result + } + + // set up table entry in r + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; // out of values--invalid code + else if (*p < s) { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); // 256 is end-of-block + r.base = *p++; // simple code is just the value + } + else { + r.exop = (Byte)(e[*p - s] + 16 + 64);// non-simple--look up in lists + r.base = d[*p++ - s]; + } + + // fill code-like entries with r + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + // backwards increment the k-bit code i + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]) { + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; } } - z = 1 << j; // table entries for j-bit table - - // allocate new table - if (*hn + z > MANY) // (note: doesn't matter for fixed) - return Z_DATA_ERROR; // overflow of MANY - u[h] = q = hp + *hn; - *hn += z; - - // connect to last table, if there is one - if (h) - { - x[h] = i; // save pattern for backing up - r.bits = (Byte)l; // bits to dump before this table - r.exop = (Byte)j; // bits in this table - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); // offset to this table - u[h-1][j] = r; // connect to last table - } - else - *t = q; // first table is returned result - } - - // set up table entry in r - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; // out of values--invalid code - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); // 256 is end-of-block - r.base = *p++; // simple code is just the value - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);// non-simple--look up in lists - r.base = d[*p++ - s]; - } - - // fill code-like entries with r - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - // backwards increment the k-bit code i - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - // backup over finished tables - mask = (1 << w) - 1; // needed on HP, cc -O bug - while ((i & mask) != x[h]) - { - h--; // don't need to update q - w -= l; - mask = (1 << w) - 1; - } } - } - // Return Z_BUF_ERROR if we were given an incomplete table - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; } int inflate_trees_bits( -uInt *c, // 19 code lengths -uInt *bb, // bits tree desired/actual depth -inflate_huft * *tb, // bits tree result -inflate_huft *hp, // space for trees +uInt* c, // 19 code lengths +uInt* bb, // bits tree desired/actual depth +inflate_huft** tb, // bits tree result +inflate_huft* hp, // space for trees z_streamp z) // for messages { - int r; - uInt hn = 0; // hufts used in space - uInt *v; // work area for huft_build + int r; + uInt hn = 0; // hufts used in space + uInt* v; // work area for huft_build - if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; + if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; } int inflate_trees_dynamic( uInt nl, // number of literal/length codes uInt nd, // number of distance codes -uInt *c, // that many (total) code lengths -uInt *bl, // literal desired/actual bit depth -uInt *bd, // distance desired/actual bit depth -inflate_huft * *tl, // literal/length tree result -inflate_huft * *td, // distance tree result -inflate_huft *hp, // space for trees +uInt* c, // that many (total) code lengths +uInt* bl, // literal desired/actual bit depth +uInt* bd, // distance desired/actual bit depth +inflate_huft** tl, // literal/length tree result +inflate_huft** td, // distance tree result +inflate_huft* hp, // space for trees z_streamp z) // for messages { - int r; - uInt hn = 0; // hufts used in space - uInt *v; // work area for huft_build + int r; + uInt hn = 0; // hufts used in space + uInt* v; // work area for huft_build - // allocate work area - if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; + // allocate work area + if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; - // build literal/length tree - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; + // build literal/length tree + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; } + + // build distance tree + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + // done ZFREE(z, v); - return r; - } - - // build distance tree - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - // done - ZFREE(z, v); - return Z_OK; + return Z_OK; } @@ -1921,17 +1906,17 @@ z_streamp z) // for messages int inflate_trees_fixed( -uInt *bl, // literal desired/actual bit depth -uInt *bd, // distance desired/actual bit depth -const inflate_huft * * tl, // literal/length tree result -const inflate_huft * *td, // distance tree result -z_streamp ) // for memory allocation +uInt* bl, // literal desired/actual bit depth +uInt* bd, // distance desired/actual bit depth +const inflate_huft** tl, // literal/length tree result +const inflate_huft** td, // distance tree result +z_streamp) // for memory allocation { - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; } @@ -1955,159 +1940,149 @@ z_streamp ) // for memory allocation int inflate_fast( uInt bl, uInt bd, -const inflate_huft *tl, -const inflate_huft *td, // need separate declaration for Borland C++ -inflate_blocks_statef *s, +const inflate_huft* tl, +const inflate_huft* td, // need separate declaration for Borland C++ +inflate_blocks_statef* s, z_streamp z) { - const inflate_huft *t; // temporary pointer - uInt e; // extra bits or operation - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer - uInt ml; // mask for literal/length tree - uInt md; // mask for distance tree - uInt c; // bytes to copy - uInt d; // distance back to copy from - Byte *r; // copy source pointer + const inflate_huft* t; // temporary pointer + uInt e; // extra bits or operation + uLong b; // bit buffer + uInt k; // bits in bit buffer + Byte* p; // input data pointer + uInt n; // bytes available there + Byte* q; // output window write pointer + uInt m; // bytes to end of window or read pointer + uInt ml; // mask for literal/length tree + uInt md; // mask for distance tree + uInt c; // bytes to copy + uInt d; // distance back to copy from + Byte* r; // copy source pointer - // load input, output, bit values - LOAD + // load input, output, bit values + LOAD - // initialize masks - ml = inflate_mask[bl]; - md = inflate_mask[bd]; + // initialize masks + ml = inflate_mask[bl]; + md = inflate_mask[bd]; - // do until not enough input or output space for fast loop - do { // assume called with m >= 258 && n >= 10 - // get literal/length code - GRABBITS(20) // max bits for literal/length code - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - for (;;) { - DUMPBITS(t->bits) - if (e & 16) - { - // get extra bits for length - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - LuTracevv((stderr, "inflate: * length %u\n", c)); - - // decode distance base of block to copy - GRABBITS(15); // max bits for distance code - e = (t = td + ((uInt)b & md))->exop; + // do until not enough input or output space for fast loop + do { // assume called with m >= 258 && n >= 10 + // get literal/length code + GRABBITS(20) // max bits for literal/length code + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) { + DUMPBITS(t->bits) + LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } for (;;) { - DUMPBITS(t->bits) - if (e & 16) - { - // get extra bits to add to distance base - e &= 15; - GRABBITS(e) // get extra bits (up to 13) - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - LuTracevv((stderr, "inflate: * distance %u\n", d)); + DUMPBITS(t->bits) + if (e & 16) { + // get extra bits for length + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + LuTracevv((stderr, "inflate: * length %u\n", c)); - // do the copy - m -= c; - r = q - d; - if (r < s->window) // wrap if needed - { - do { - r += s->end - s->window; // force pointer in window - } while (r < s->window); // covers invalid distances - e = (uInt) (s->end - r); - if (c > e) - { - c -= e; // wrapped copy - do { - *q++ = *r++; - } while (--e); - r = s->window; - do { - *q++ = *r++; - } while (--c); - } - else // normal copy - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); - } + // decode distance base of block to copy + GRABBITS(15); // max bits for distance code + e = (t = td + ((uInt)b & md))->exop; + for (;;) { + DUMPBITS(t->bits) + if (e & 16) { + // get extra bits to add to distance base + e &= 15; + GRABBITS(e) // get extra bits (up to 13) + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + LuTracevv((stderr, "inflate: * distance %u\n", d)); + + // do the copy + m -= c; + r = q - d; + if (r < s->window) // wrap if needed + { + do { + r += s->end - s->window; // force pointer in window + } while (r < s->window); // covers invalid distances + e = (uInt)(s->end - r); + if (c > e) { + c -= e; // wrapped copy + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else // normal copy + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + }; + break; + } + if ((e & 64) == 0) { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) { + DUMPBITS(t->bits) + LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } } - else /* normal copy */ - { - *q++ = *r++; c--; - *q++ = *r++; c--; - do { - *q++ = *r++; - } while (--c); + else if (e & 32) { + LuTracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; } - break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } }; - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - LuTracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - LuTracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - }; - } while (m >= 258 && n >= 10); + } while (m >= 258 && n >= 10); - // not enough input or output--restore pointers and return - UNGRAB - UPDATE - return Z_OK; + // not enough input or output--restore pointers and return + UNGRAB + UPDATE + return Z_OK; } @@ -2182,8 +2157,9 @@ const uLong crc_table[256] = { 0x2d02ef8dL }; -const uLong * get_crc_table() -{ return (const uLong *)crc_table; +const uLong* get_crc_table() +{ + return (const uLong*)crc_table; } #define CRC_DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); @@ -2191,12 +2167,13 @@ const uLong * get_crc_table() #define CRC_DO4(buf) CRC_DO2(buf); CRC_DO2(buf); #define CRC_DO8(buf) CRC_DO4(buf); CRC_DO4(buf); -uLong ucrc32(uLong crc, const Byte *buf, uInt len) -{ if (buf == Z_NULL) return 0L; - crc = crc ^ 0xffffffffL; - while (len >= 8) {CRC_DO8(buf); len -= 8;} - if (len) do {CRC_DO1(buf);} while (--len); - return crc ^ 0xffffffffL; +uLong ucrc32(uLong crc, const Byte* buf, uInt len) +{ + if (buf == Z_NULL) return 0L; + crc = crc ^ 0xffffffffL; + while (len >= 8) { CRC_DO8(buf); len -= 8; } + if (len) do { CRC_DO1(buf); } while (--len); + return crc ^ 0xffffffffL; } @@ -2204,20 +2181,23 @@ uLong ucrc32(uLong crc, const Byte *buf, uInt len) // ============================================================= // some decryption routines #define CRC32(c, b) (crc_table[((int)(c)^(b))&0xff]^((c)>>8)) -void Uupdate_keys(unsigned long *keys, char c) -{ keys[0] = CRC32(keys[0],c); - keys[1] += keys[0] & 0xFF; - keys[1] = keys[1]*134775813L +1; - keys[2] = CRC32(keys[2], keys[1] >> 24); +void Uupdate_keys(unsigned long* keys, char c) +{ + keys[0] = CRC32(keys[0], c); + keys[1] += keys[0] & 0xFF; + keys[1] = keys[1] * 134775813L + 1; + keys[2] = CRC32(keys[2], keys[1] >> 24); } -char Udecrypt_byte(unsigned long *keys) -{ unsigned temp = ((unsigned)keys[2] & 0xffff) | 2; - return (char)(((temp * (temp ^ 1)) >> 8) & 0xff); +char Udecrypt_byte(unsigned long* keys) +{ + unsigned temp = ((unsigned)keys[2] & 0xffff) | 2; + return (char)(((temp * (temp ^ 1)) >> 8) & 0xff); } -char zdecode(unsigned long *keys, char c) -{ c^=Udecrypt_byte(keys); - Uupdate_keys(keys,c); - return c; +char zdecode(unsigned long* keys, char c) +{ + c ^= Udecrypt_byte(keys); + Uupdate_keys(keys, c); + return c; } @@ -2240,7 +2220,7 @@ char zdecode(unsigned long *keys, char c) #define AD_DO16(buf) AD_DO8(buf,0); AD_DO8(buf,8); // ========================================================================= -uLong adler32(uLong adler, const Byte *buf, uInt len) +uLong adler32(uLong adler, const Byte* buf, uInt len) { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; @@ -2253,12 +2233,12 @@ uLong adler32(uLong adler, const Byte *buf, uInt len) len -= k; while (k >= 16) { AD_DO16(buf); - buf += 16; + buf += 16; k -= 16; } if (k != 0) do { s1 += *buf++; - s2 += s1; + s2 += s1; } while (--k); s1 %= BASE; s2 %= BASE; @@ -2278,27 +2258,28 @@ uLong adler32(uLong adler, const Byte *buf, uInt len) -const char * zlibVersion() +const char* zlibVersion() { return ZLIB_VERSION; } // exported to allow conversion of error code to string for compress() and // uncompress() -const char * zError(int err) -{ return ERR_MSG(err); +const char* zError(int err) +{ + return ERR_MSG(err); } -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +voidpf zcalloc(voidpf opaque, unsigned items, unsigned size) { if (opaque) items += size - size; // make compiler happy return (voidpf)calloc(items, size); } -void zcfree (voidpf opaque, voidpf ptr) +void zcfree(voidpf opaque, voidpf ptr) { zfree(ptr); if (opaque) return; // make compiler happy @@ -2312,133 +2293,135 @@ void zcfree (voidpf opaque, voidpf ptr) //struct inflate_blocks_state {int dummy;}; // for buggy compilers -typedef enum { - IM_METHOD, // waiting for method byte - IM_FLAG, // waiting for flag byte - IM_DICT4, // four dictionary check bytes to go - IM_DICT3, // three dictionary check bytes to go - IM_DICT2, // two dictionary check bytes to go - IM_DICT1, // one dictionary check byte to go - IM_DICT0, // waiting for inflateSetDictionary - IM_BLOCKS, // decompressing blocks - IM_CHECK4, // four check bytes to go - IM_CHECK3, // three check bytes to go - IM_CHECK2, // two check bytes to go - IM_CHECK1, // one check byte to go - IM_DONE, // finished check, done - IM_BAD} // got an error--stay here +typedef enum +{ + IM_METHOD, // waiting for method byte + IM_FLAG, // waiting for flag byte + IM_DICT4, // four dictionary check bytes to go + IM_DICT3, // three dictionary check bytes to go + IM_DICT2, // two dictionary check bytes to go + IM_DICT1, // one dictionary check byte to go + IM_DICT0, // waiting for inflateSetDictionary + IM_BLOCKS, // decompressing blocks + IM_CHECK4, // four check bytes to go + IM_CHECK3, // three check bytes to go + IM_CHECK2, // two check bytes to go + IM_CHECK1, // one check byte to go + IM_DONE, // finished check, done + IM_BAD +} // got an error--stay here inflate_mode; // inflate private state -struct internal_state { +struct internal_state +{ - // mode - inflate_mode mode; // current inflate mode + // mode + inflate_mode mode; // current inflate mode - // mode dependent information - union { - uInt method; // if IM_FLAGS, method byte - struct { - uLong was; // computed check value - uLong need; // stream check value - } check; // if CHECK, check values to compare - uInt marker; // if IM_BAD, inflateSync's marker bytes count - } sub; // submode + // mode dependent information + union + { + uInt method; // if IM_FLAGS, method byte + struct + { + uLong was; // computed check value + uLong need; // stream check value + } check; // if CHECK, check values to compare + uInt marker; // if IM_BAD, inflateSync's marker bytes count + } sub; // submode - // mode independent information - int nowrap; // flag for no wrapper - uInt wbits; // log2(window size) (8..15, defaults to 15) - inflate_blocks_statef - *blocks; // current inflate_blocks state + // mode independent information + int nowrap; // flag for no wrapper + uInt wbits; // log2(window size) (8..15, defaults to 15) + inflate_blocks_statef + * blocks; // current inflate_blocks state }; int inflateReset(z_streamp z) { - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? IM_BLOCKS : IM_METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - LuTracev((stderr, "inflate: reset\n")); - return Z_OK; + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? IM_BLOCKS : IM_METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + LuTracev((stderr, "inflate: reset\n")); + return Z_OK; } int inflateEnd(z_streamp z) { - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - LuTracev((stderr, "inflate: end\n")); - return Z_OK; + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + LuTracev((stderr, "inflate: end\n")); + return Z_OK; } int inflateInit2(z_streamp z) -{ const char *version = ZLIB_VERSION; int stream_size = sizeof(z_stream); - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR; +{ + const char* version = ZLIB_VERSION; int stream_size = sizeof(z_stream); + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR; - int w = -15; // MAX_WBITS: 32K LZ77 window. - // Warning: reducing MAX_WBITS makes minigzip unable to extract .gz files created by gzip. - // The memory requirements for deflate are (in bytes): - // (1 << (windowBits+2)) + (1 << (memLevel+9)) - // that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - // plus a few kilobytes for small objects. For example, if you want to reduce - // the default memory requirements from 256K to 128K, compile with - // make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - // Of course this will generally degrade compression (there's no free lunch). - // - // The memory requirements for inflate are (in bytes) 1 << windowBits - // that is, 32K for windowBits=15 (default value) plus a few kilobytes - // for small objects. + int w = -15; // MAX_WBITS: 32K LZ77 window. + // Warning: reducing MAX_WBITS makes minigzip unable to extract .gz files created by gzip. + // The memory requirements for deflate are (in bytes): + // (1 << (windowBits+2)) + (1 << (memLevel+9)) + // that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + // plus a few kilobytes for small objects. For example, if you want to reduce + // the default memory requirements from 256K to 128K, compile with + // make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + // Of course this will generally degrade compression (there's no free lunch). + // + // The memory requirements for inflate are (in bytes) 1 << windowBits + // that is, 32K for windowBits=15 (default value) plus a few kilobytes + // for small objects. - // initialize state - if (z == Z_NULL) return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; + // initialize state + if (z == Z_NULL) return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state*) + ZALLOC(z, 1, sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; - // handle undocumented nowrap option (no zlib header or check) - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } + // handle undocumented nowrap option (no zlib header or check) + z->state->nowrap = 0; + if (w < 0) { + w = -w; + z->state->nowrap = 1; + } - // set window size - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; + // set window size + if (w < 8 || w > 15) { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; - // create inflate_blocks state - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - LuTracev((stderr, "inflate: allocated\n")); + // create inflate_blocks state + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) { + inflateEnd(z); + return Z_MEM_ERROR; + } + LuTracev((stderr, "inflate: allocated\n")); - // reset state - inflateReset(z); - return Z_OK; + // reset state + inflateReset(z); + return Z_OK; } @@ -2448,124 +2431,116 @@ int inflateInit2(z_streamp z) int inflate(z_streamp z, int f) { - int r; - uInt b; + int r; + uInt b; - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - for (;;) switch (z->state->mode) - { + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + for (;;) switch (z->state->mode) { case IM_METHOD: - IM_NEEDBYTE - if (((z->state->sub.method = IM_NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = IM_BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = IM_BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - z->state->mode = IM_FLAG; + IM_NEEDBYTE + if (((z->state->sub.method = IM_NEXTBYTE) & 0xf) != Z_DEFLATED) { + z->state->mode = IM_BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; // can't try inflateSync + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) { + z->state->mode = IM_BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; // can't try inflateSync + break; + } + z->state->mode = IM_FLAG; case IM_FLAG: - IM_NEEDBYTE - b = IM_NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = IM_BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - LuTracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = IM_BLOCKS; - break; - } - z->state->mode = IM_DICT4; + IM_NEEDBYTE + b = IM_NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) { + z->state->mode = IM_BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; // can't try inflateSync + break; + } + LuTracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) { + z->state->mode = IM_BLOCKS; + break; + } + z->state->mode = IM_DICT4; case IM_DICT4: - IM_NEEDBYTE - z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; - z->state->mode = IM_DICT3; + IM_NEEDBYTE + z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; + z->state->mode = IM_DICT3; case IM_DICT3: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; - z->state->mode = IM_DICT2; + IM_NEEDBYTE + z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; + z->state->mode = IM_DICT2; case IM_DICT2: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; - z->state->mode = IM_DICT1; + IM_NEEDBYTE + z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; + z->state->mode = IM_DICT1; case IM_DICT1: - IM_NEEDBYTE; r; - z->state->sub.check.need += (uLong)IM_NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = IM_DICT0; - return Z_NEED_DICT; + IM_NEEDBYTE; r; + z->state->sub.check.need += (uLong)IM_NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = IM_DICT0; + return Z_NEED_DICT; case IM_DICT0: - z->state->mode = IM_BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; // can try inflateSync - return Z_STREAM_ERROR; - case IM_BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { z->state->mode = IM_BAD; + z->msg = (char*)"need dictionary"; z->state->sub.marker = 0; // can try inflateSync - break; - } - if (r == Z_OK) + return Z_STREAM_ERROR; + case IM_BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) { + z->state->mode = IM_BAD; + z->state->sub.marker = 0; // can try inflateSync + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = IM_DONE; - break; - } - z->state->mode = IM_CHECK4; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) { + z->state->mode = IM_DONE; + break; + } + z->state->mode = IM_CHECK4; case IM_CHECK4: - IM_NEEDBYTE - z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; - z->state->mode = IM_CHECK3; + IM_NEEDBYTE + z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; + z->state->mode = IM_CHECK3; case IM_CHECK3: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; - z->state->mode = IM_CHECK2; + IM_NEEDBYTE + z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; + z->state->mode = IM_CHECK2; case IM_CHECK2: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; - z->state->mode = IM_CHECK1; + IM_NEEDBYTE + z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; + z->state->mode = IM_CHECK1; case IM_CHECK1: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE; + IM_NEEDBYTE + z->state->sub.check.need += (uLong)IM_NEXTBYTE; - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = IM_BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - LuTracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = IM_DONE; + if (z->state->sub.check.was != z->state->sub.check.need) { + z->state->mode = IM_BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; // can't try inflateSync + break; + } + LuTracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = IM_DONE; case IM_DONE: - return Z_STREAM_END; + return Z_STREAM_END; case IM_BAD: - return Z_DATA_ERROR; + return Z_DATA_ERROR; default: - return Z_STREAM_ERROR; - } + return Z_STREAM_ERROR; + } } @@ -2597,104 +2572,111 @@ typedef struct unz_file_info_internal_s typedef struct -{ bool is_handle; // either a handle or memory - bool canseek; - // for handles: - HANDLE h; bool herr; unsigned long initial_offset; bool mustclosehandle; - // for memory: - void *buf; unsigned int len,pos; // if it's a memory block +{ + bool is_handle; // either a handle or memory + bool canseek; + // for handles: + HANDLE h; bool herr; unsigned long initial_offset; bool mustclosehandle; + // for memory: + void* buf; unsigned int len, pos; // if it's a memory block } LUFILE; -LUFILE *lufopen(void *z,unsigned int len,DWORD flags,ZRESULT *err) -{ if (flags!=ZIP_HANDLE && flags!=ZIP_FILENAME && flags!=ZIP_MEMORY) {*err=ZR_ARGS; return NULL;} - // - HANDLE h=0; bool canseek=false; *err=ZR_OK; - bool mustclosehandle=false; - if (flags==ZIP_HANDLE||flags==ZIP_FILENAME) - { if (flags==ZIP_HANDLE) - { HANDLE hf = z; - h=hf; mustclosehandle=false; +LUFILE* lufopen(void* z, unsigned int len, DWORD flags, ZRESULT* err) +{ + if (flags != ZIP_HANDLE && flags != ZIP_FILENAME && flags != ZIP_MEMORY) { *err = ZR_ARGS; return NULL; } + // + HANDLE h = 0; bool canseek = false; *err = ZR_OK; + bool mustclosehandle = false; + if (flags == ZIP_HANDLE || flags == ZIP_FILENAME) { + if (flags == ZIP_HANDLE) { + HANDLE hf = z; + h = hf; mustclosehandle = false; #ifdef DuplicateHandle - BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&h,0,FALSE,DUPLICATE_SAME_ACCESS); - if (!res) mustclosehandle=true; + BOOL res = DuplicateHandle(GetCurrentProcess(), hf, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS); + if (!res) mustclosehandle = true; #endif + } + else { + h = CreateFile((const TCHAR*)z, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { *err = ZR_NOFILE; return NULL; } + mustclosehandle = true; + } + // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE. + DWORD res = SetFilePointer(h, 0, 0, FILE_CURRENT); + canseek = (res != 0xFFFFFFFF); } - else - { h=CreateFile((const TCHAR*)z,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); - if (h==INVALID_HANDLE_VALUE) {*err=ZR_NOFILE; return NULL;} - mustclosehandle=true; + LUFILE* lf = new LUFILE; + if (flags == ZIP_HANDLE || flags == ZIP_FILENAME) { + lf->is_handle = true; lf->mustclosehandle = mustclosehandle; + lf->canseek = canseek; + lf->h = h; lf->herr = false; + lf->initial_offset = 0; + if (canseek) lf->initial_offset = SetFilePointer(h, 0, NULL, FILE_CURRENT); } - // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE. - DWORD res = SetFilePointer(h,0,0,FILE_CURRENT); - canseek = (res!=0xFFFFFFFF); - } - LUFILE *lf = new LUFILE; - if (flags==ZIP_HANDLE||flags==ZIP_FILENAME) - { lf->is_handle=true; lf->mustclosehandle=mustclosehandle; - lf->canseek=canseek; - lf->h=h; lf->herr=false; - lf->initial_offset=0; - if (canseek) lf->initial_offset = SetFilePointer(h,0,NULL,FILE_CURRENT); - } - else - { lf->is_handle=false; - lf->canseek=true; - lf->mustclosehandle=false; - lf->buf=z; lf->len=len; lf->pos=0; lf->initial_offset=0; - } - *err=ZR_OK; - return lf; + else { + lf->is_handle = false; + lf->canseek = true; + lf->mustclosehandle = false; + lf->buf = z; lf->len = len; lf->pos = 0; lf->initial_offset = 0; + } + *err = ZR_OK; + return lf; } -int lufclose(LUFILE *stream) -{ if (stream==NULL) return EOF; - if (stream->mustclosehandle) CloseHandle(stream->h); - delete stream; - return 0; -} - -int luferror(LUFILE *stream) -{ if (stream->is_handle && stream->herr) return 1; - else return 0; -} - -long int luftell(LUFILE *stream) -{ if (stream->is_handle && stream->canseek) return SetFilePointer(stream->h,0,NULL,FILE_CURRENT)-stream->initial_offset; - else if (stream->is_handle) return 0; - else return stream->pos; -} - -int lufseek(LUFILE *stream, long offset, int whence) -{ if (stream->is_handle && stream->canseek) - { if (whence==SEEK_SET) SetFilePointer(stream->h,stream->initial_offset+offset,0,FILE_BEGIN); - else if (whence==SEEK_CUR) SetFilePointer(stream->h,offset,NULL,FILE_CURRENT); - else if (whence==SEEK_END) SetFilePointer(stream->h,offset,NULL,FILE_END); - else return 19; // EINVAL +int lufclose(LUFILE* stream) +{ + if (stream == NULL) return EOF; + if (stream->mustclosehandle) CloseHandle(stream->h); + delete stream; return 0; - } - else if (stream->is_handle) return 29; // ESPIPE - else - { if (whence==SEEK_SET) stream->pos=offset; - else if (whence==SEEK_CUR) stream->pos+=offset; - else if (whence==SEEK_END) stream->pos=stream->len+offset; - return 0; - } +} + +int luferror(LUFILE* stream) +{ + if (stream->is_handle && stream->herr) return 1; + else return 0; +} + +long int luftell(LUFILE* stream) +{ + if (stream->is_handle && stream->canseek) return SetFilePointer(stream->h, 0, NULL, FILE_CURRENT) - stream->initial_offset; + else if (stream->is_handle) return 0; + else return stream->pos; +} + +int lufseek(LUFILE* stream, long offset, int whence) +{ + if (stream->is_handle && stream->canseek) { + if (whence == SEEK_SET) SetFilePointer(stream->h, stream->initial_offset + offset, 0, FILE_BEGIN); + else if (whence == SEEK_CUR) SetFilePointer(stream->h, offset, NULL, FILE_CURRENT); + else if (whence == SEEK_END) SetFilePointer(stream->h, offset, NULL, FILE_END); + else return 19; // EINVAL + return 0; + } + else if (stream->is_handle) return 29; // ESPIPE + else { + if (whence == SEEK_SET) stream->pos = offset; + else if (whence == SEEK_CUR) stream->pos += offset; + else if (whence == SEEK_END) stream->pos = stream->len + offset; + return 0; + } } -size_t lufread(void *ptr,size_t size,size_t n,LUFILE *stream) -{ unsigned int toread = (unsigned int)(size*n); - if (stream->is_handle) - { DWORD red; BOOL res = ReadFile(stream->h,ptr,toread,&red,NULL); - if (!res) stream->herr=true; - return red/size; - } - if (stream->pos+toread > stream->len) toread = stream->len-stream->pos; - memcpy(ptr, (char*)stream->buf + stream->pos, toread); DWORD red = toread; - stream->pos += red; - return red/size; +size_t lufread(void* ptr, size_t size, size_t n, LUFILE* stream) +{ + unsigned int toread = (unsigned int)(size * n); + if (stream->is_handle) { + DWORD red; BOOL res = ReadFile(stream->h, ptr, toread, &red, NULL); + if (!res) stream->herr = true; + return red / size; + } + if (stream->pos + toread > stream->len) toread = stream->len - stream->pos; + memcpy(ptr, (char*)stream->buf + stream->pos, toread); DWORD red = toread; + stream->pos += red; + return red / size; } @@ -2704,60 +2686,60 @@ size_t lufread(void *ptr,size_t size,size_t n,LUFILE *stream) // when reading and decompress it typedef struct { - char *read_buffer; // internal buffer for compressed data - z_stream stream; // zLib stream structure for inflate + char* read_buffer; // internal buffer for compressed data + z_stream stream; // zLib stream structure for inflate - uLong pos_in_zipfile; // position in byte on the zipfile, for fseek - uLong stream_initialised; // flag set if stream structure is initialised + uLong pos_in_zipfile; // position in byte on the zipfile, for fseek + uLong stream_initialised; // flag set if stream structure is initialised - uLong offset_local_extrafield;// offset of the local extra field - uInt size_local_extrafield;// size of the local extra field - uLong pos_local_extrafield; // position in the local extra field in read + uLong offset_local_extrafield;// offset of the local extra field + uInt size_local_extrafield;// size of the local extra field + uLong pos_local_extrafield; // position in the local extra field in read - uLong crc32; // crc32 of all data uncompressed - uLong crc32_wait; // crc32 we must obtain after decompress all - uLong rest_read_compressed; // number of byte to be decompressed - uLong rest_read_uncompressed;//number of byte to be obtained after decomp - LUFILE* file; // io structore of the zipfile - uLong compression_method; // compression method (0==store) - uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) - bool encrypted; // is it encrypted? - unsigned long keys[3]; // decryption keys, initialized by unzOpenCurrentFile - int encheadleft; // the first call(s) to unzReadCurrentFile will read this many encryption-header bytes first - char crcenctest; // if encrypted, we'll check the encryption buffer against this + uLong crc32; // crc32 of all data uncompressed + uLong crc32_wait; // crc32 we must obtain after decompress all + uLong rest_read_compressed; // number of byte to be decompressed + uLong rest_read_uncompressed;//number of byte to be obtained after decomp + LUFILE* file; // io structore of the zipfile + uLong compression_method; // compression method (0==store) + uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) + bool encrypted; // is it encrypted? + unsigned long keys[3]; // decryption keys, initialized by unzOpenCurrentFile + int encheadleft; // the first call(s) to unzReadCurrentFile will read this many encryption-header bytes first + char crcenctest; // if encrypted, we'll check the encryption buffer against this } file_in_zip_read_info_s; // unz_s contain internal information about the zipfile typedef struct { - LUFILE* file; // io structore of the zipfile - unz_global_info gi; // public global information - uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) - uLong num_file; // number of the current file in the zipfile - uLong pos_in_central_dir; // pos of the current file in the central dir - uLong current_file_ok; // flag about the usability of the current file - uLong central_pos; // position of the beginning of the central dir + LUFILE* file; // io structore of the zipfile + unz_global_info gi; // public global information + uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) + uLong num_file; // number of the current file in the zipfile + uLong pos_in_central_dir; // pos of the current file in the central dir + uLong current_file_ok; // flag about the usability of the current file + uLong central_pos; // position of the beginning of the central dir - uLong size_central_dir; // size of the central directory - uLong offset_central_dir; // offset of start of central directory with respect to the starting disk number + uLong size_central_dir; // size of the central directory + uLong offset_central_dir; // offset of start of central directory with respect to the starting disk number - unz_file_info cur_file_info; // public info about the current file in zip - unz_file_info_internal cur_file_info_internal; // private info about it + unz_file_info cur_file_info; // public info about the current file in zip + unz_file_info_internal cur_file_info_internal; // private info about it file_in_zip_read_info_s* pfile_in_zip_read; // structure about the current file if we are decompressing it -} unz_s, *unzFile; +} unz_s, * unzFile; -int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity); +int unzStringFileNameCompare(const char* fileName1, const char* fileName2, int iCaseSensitivity); // Compare two filename (fileName1,fileName2). -z_off_t unztell (unzFile file); +z_off_t unztell(unzFile file); // Give the current position in uncompressed data -int unzeof (unzFile file); +int unzeof(unzFile file); // return 1 if the end of file was reached, 0 elsewhere -int unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len); +int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len); // Read extra field from the current file (opened by unzOpenCurrentFile) // This is the local-header version of the extra field (sometimes, there is // more info in the local-header version than in the central-header) @@ -2776,64 +2758,65 @@ int unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len); // for end of file. // IN assertion: the stream s has been sucessfully opened for reading. -int unzlocal_getByte(LUFILE *fin,int *pi) -{ unsigned char c; - int err = (int)lufread(&c, 1, 1, fin); - if (err==1) - { *pi = (int)c; - return UNZ_OK; - } - else - { if (luferror(fin)) return UNZ_ERRNO; - else return UNZ_EOF; - } +int unzlocal_getByte(LUFILE* fin, int* pi) +{ + unsigned char c; + int err = (int)lufread(&c, 1, 1, fin); + if (err == 1) { + *pi = (int)c; + return UNZ_OK; + } + else { + if (luferror(fin)) return UNZ_ERRNO; + else return UNZ_EOF; + } } // =========================================================================== // Reads a long in LSB order from the given gz_stream. Sets -int unzlocal_getShort (LUFILE *fin,uLong *pX) +int unzlocal_getShort(LUFILE* fin, uLong* pX) { - uLong x ; + uLong x; int i; int err; - err = unzlocal_getByte(fin,&i); + err = unzlocal_getByte(fin, &i); x = (uLong)i; - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; + if (err == UNZ_OK) + err = unzlocal_getByte(fin, &i); + x += ((uLong)i) << 8; - if (err==UNZ_OK) + if (err == UNZ_OK) *pX = x; else *pX = 0; return err; } -int unzlocal_getLong (LUFILE *fin,uLong *pX) +int unzlocal_getLong(LUFILE* fin, uLong* pX) { - uLong x ; + uLong x; int i; int err; - err = unzlocal_getByte(fin,&i); + err = unzlocal_getByte(fin, &i); x = (uLong)i; - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; + if (err == UNZ_OK) + err = unzlocal_getByte(fin, &i); + x += ((uLong)i) << 8; - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<16; + if (err == UNZ_OK) + err = unzlocal_getByte(fin, &i); + x += ((uLong)i) << 16; - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<24; + if (err == UNZ_OK) + err = unzlocal_getByte(fin, &i); + x += ((uLong)i) << 24; - if (err==UNZ_OK) + if (err == UNZ_OK) *pX = x; else *pX = 0; @@ -2842,25 +2825,24 @@ int unzlocal_getLong (LUFILE *fin,uLong *pX) // My own strcmpi / strcasecmp -int strcmpcasenosensitive_internal (const char* fileName1,const char *fileName2) +int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) { - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= (char)0x20; - if ((c2>='a') && (c2<='z')) - c2 -= (char)0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } + for (;;) { + char c1 = *(fileName1++); + char c2 = *(fileName2++); + if ((c1 >= 'a') && (c1 <= 'z')) + c1 -= (char)0x20; + if ((c2 >= 'a') && (c2 <= 'z')) + c2 -= (char)0x20; + if (c1 == '\0') + return ((c2 == '\0') ? 0 : -1); + if (c2 == '\0') + return 1; + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + } } @@ -2871,9 +2853,10 @@ int strcmpcasenosensitive_internal (const char* fileName1,const char *fileName2) // If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) // If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) // -int unzStringFileNameCompare (const char*fileName1,const char*fileName2,int iCaseSensitivity) -{ if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); - else return strcmpcasenosensitive_internal(fileName1,fileName2); +int unzStringFileNameCompare(const char* fileName1, const char* fileName2, int iCaseSensitivity) +{ + if (iCaseSensitivity == 1) return strcmp(fileName1, fileName2); + else return strcmpcasenosensitive_internal(fileName1, fileName2); } #define BUFREADCOMMENT (0x400) @@ -2882,88 +2865,90 @@ int unzStringFileNameCompare (const char*fileName1,const char*fileName2,int iCas // Locate the Central directory of a zipfile (at the end, just before // the global comment). Lu bugfix 2005.07.26 - returns 0xFFFFFFFF if not found, // rather than 0, since 0 is a valid central-dir-location for an empty zipfile. -uLong unzlocal_SearchCentralDir(LUFILE *fin) -{ if (lufseek(fin,0,SEEK_END) != 0) return 0xFFFFFFFF; - uLong uSizeFile = luftell(fin); +uLong unzlocal_SearchCentralDir(LUFILE* fin) +{ + if (lufseek(fin, 0, SEEK_END) != 0) return 0xFFFFFFFF; + uLong uSizeFile = luftell(fin); - uLong uMaxBack=0xffff; // maximum size of global comment - if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; + uLong uMaxBack = 0xffff; // maximum size of global comment + if (uMaxBack > uSizeFile) uMaxBack = uSizeFile; - unsigned char *buf = (unsigned char*)zmalloc(BUFREADCOMMENT+4); - if (buf==NULL) return 0xFFFFFFFF; - uLong uPosFound=0xFFFFFFFF; + unsigned char* buf = (unsigned char*)zmalloc(BUFREADCOMMENT + 4); + if (buf == NULL) return 0xFFFFFFFF; + uLong uPosFound = 0xFFFFFFFF; - uLong uBackRead = 4; - while (uBackReaduMaxBack) uBackRead = uMaxBack; - else uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (lufseek(fin,uReadPos,SEEK_SET)!=0) break; - if (lufread(buf,(uInt)uReadSize,1,fin)!=1) break; - for (i=(int)uReadSize-3; (i--)>=0;) - { if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { uPosFound = uReadPos+i; break; - } + uLong uBackRead = 4; + while (uBackRead < uMaxBack) { + uLong uReadSize, uReadPos; + int i; + if (uBackRead + BUFREADCOMMENT > uMaxBack) uBackRead = uMaxBack; + else uBackRead += BUFREADCOMMENT; + uReadPos = uSizeFile - uBackRead; + uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uSizeFile - uReadPos); + if (lufseek(fin, uReadPos, SEEK_SET) != 0) break; + if (lufread(buf, (uInt)uReadSize, 1, fin) != 1) break; + for (i = (int)uReadSize - 3; (i--) >= 0;) { + if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06)) { + uPosFound = uReadPos + i; break; + } + } + if (uPosFound != 0) break; } - if (uPosFound!=0) break; - } - if (buf) zfree(buf); - return uPosFound; + if (buf) zfree(buf); + return uPosFound; } -int unzGoToFirstFile (unzFile file); -int unzCloseCurrentFile (unzFile file); +int unzGoToFirstFile(unzFile file); +int unzCloseCurrentFile(unzFile file); // Open a Zip file. // If the zipfile cannot be opened (file don't exist or in not valid), return NULL. // Otherwise, the return value is a unzFile Handle, usable with other unzip functions -unzFile unzOpenInternal(LUFILE *fin) -{ if (fin==NULL) return NULL; - if (unz_copyright[0]!=' ') {lufclose(fin); return NULL;} +unzFile unzOpenInternal(LUFILE* fin) +{ + if (fin == NULL) return NULL; + if (unz_copyright[0] != ' ') { lufclose(fin); return NULL; } - int err=UNZ_OK; - unz_s us; - uLong central_pos,uL; - central_pos = unzlocal_SearchCentralDir(fin); - if (central_pos==0xFFFFFFFF) err=UNZ_ERRNO; - if (lufseek(fin,central_pos,SEEK_SET)!=0) err=UNZ_ERRNO; - // the signature, already checked - if (unzlocal_getLong(fin,&uL)!=UNZ_OK) err=UNZ_ERRNO; - // number of this disk - uLong number_disk; // number of the current dist, used for spanning ZIP, unsupported, always 0 - if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; - // number of the disk with the start of the central directory - uLong number_disk_with_CD; // number the the disk with central dir, used for spaning ZIP, unsupported, always 0 - if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; - // total number of entries in the central dir on this disk - if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; - // total number of entries in the central dir - uLong number_entry_CD; // total number of entries in the central dir (same than number_entry on nospan) - if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; - if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; - // size of the central directory - if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; - // offset of start of central directory with respect to the starting disk number - if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; - // zipfile comment length - if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; - if ((central_pos+fin->initial_offsetinitial_offset < us.offset_central_dir + us.size_central_dir) && (err == UNZ_OK)) err = UNZ_BADZIPFILE; + if (err != UNZ_OK) { lufclose(fin);return NULL; } - us.file=fin; - us.byte_before_the_zipfile = central_pos+fin->initial_offset - (us.offset_central_dir+us.size_central_dir); - us.central_pos = central_pos; - us.pfile_in_zip_read = NULL; - fin->initial_offset = 0; // since the zipfile itself is expected to handle this + us.file = fin; + us.byte_before_the_zipfile = central_pos + fin->initial_offset - (us.offset_central_dir + us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + fin->initial_offset = 0; // since the zipfile itself is expected to handle this - unz_s *s = (unz_s*)zmalloc(sizeof(unz_s)); - *s=us; - unzGoToFirstFile((unzFile)s); - return (unzFile)s; + unz_s* s = (unz_s*)zmalloc(sizeof(unz_s)); + *s = us; + unzGoToFirstFile((unzFile)s); + return (unzFile)s; } @@ -2972,206 +2957,201 @@ unzFile unzOpenInternal(LUFILE *fin) // If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), // these files MUST be closed with unzipCloseCurrentFile before call unzipClose. // return UNZ_OK if there is no problem. -int unzClose (unzFile file) +int unzClose(unzFile file) { - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; + unz_s* s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; - if (s->pfile_in_zip_read!=NULL) + if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); - lufclose(s->file); - if (s) zfree(s); // unused s=0; - return UNZ_OK; + lufclose(s->file); + if (s) zfree(s); // unused s=0; + return UNZ_OK; } // Write info about the ZipFile in the *pglobal_info structure. // No preparation of the structure is needed // return UNZ_OK if there is no problem. -int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info) +int unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info) { - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; + unz_s* s; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + *pglobal_info = s->gi; + return UNZ_OK; } // Translate date/time from Dos format to tm_unz (readable more easilty) -void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) +void unzlocal_DosDateToTmuDate(uLong ulDosDate, tm_unz* ptm) { uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + uDate = (uLong)(ulDosDate >> 16); + ptm->tm_mday = (uInt)(uDate & 0x1f); + ptm->tm_mon = (uInt)((((uDate) & 0x1E0) / 0x20) - 1); + ptm->tm_year = (uInt)(((uDate & 0x0FE00) / 0x0200) + 1980); - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; + ptm->tm_hour = (uInt)((ulDosDate & 0xF800) / 0x800); + ptm->tm_min = (uInt)((ulDosDate & 0x7E0) / 0x20); + ptm->tm_sec = (uInt)(2 * (ulDosDate & 0x1f)); } // Get Info about the current file in the zipfile, with internal only info -int unzlocal_GetCurrentFileInfoInternal (unzFile file, - unz_file_info *pfile_info, +int unzlocal_GetCurrentFileInfoInternal(unzFile file, + unz_file_info* pfile_info, unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); + * pfile_info_internal, + char* szFileName, + uLong fileNameBufferSize, + void* extraField, + uLong extraFieldBufferSize, + char* szComment, + uLong commentBufferSize); -int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info, - unz_file_info_internal *pfile_info_internal, char *szFileName, - uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, - char *szComment, uLong commentBufferSize) +int unzlocal_GetCurrentFileInfoInternal(unzFile file, unz_file_info* pfile_info, + unz_file_info_internal* pfile_info_internal, char* szFileName, + uLong fileNameBufferSize, void* extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) { - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err = UNZ_OK; + uLong uMagic; + long lSeek = 0; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (lufseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) - err=UNZ_ERRNO; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + if (lufseek(s->file, s->pos_in_central_dir + s->byte_before_the_zipfile, SEEK_SET) != 0) + err = UNZ_ERRNO; - // we check the magic - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; + // we check the magic + if (err == UNZ_OK) + if (unzlocal_getLong(s->file, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != 0x02014b50) + err = UNZ_BADZIPFILE; - if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.version) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.version_needed) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.flag) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.compression_method) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info.dosDate) != UNZ_OK) + err = UNZ_ERRNO; - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date); - if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info.crc) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info.compressed_size) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info.uncompressed_size) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.size_filename) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.size_file_extra) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.size_file_comment) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.disk_num_start) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &file_info.internal_fa) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info.external_fa) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &file_info_internal.offset_curfile) != UNZ_OK) + err = UNZ_ERRNO; - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (lufread(szFileName,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } + if ((file_info.size_filename > 0) && (fileNameBufferSize > 0)) + if (lufread(szFileName, (uInt)uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + lSeek -= uSizeRead; + } - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (lufread(extraField,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; + if (lSeek != 0) + if (lufseek(s->file, lSeek, SEEK_CUR) == 0) + lSeek = 0; + else + err = UNZ_ERRNO; + if ((file_info.size_file_extra > 0) && (extraFieldBufferSize > 0)) + if (lufread(extraField, (uInt)uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek += file_info.size_file_extra; - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) - {} // unused lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (lufread(szComment,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - //unused lSeek+=file_info.size_file_comment - uSizeRead; - } - else {} //unused lSeek+=file_info.size_file_comment; + if (lSeek != 0) + if (lufseek(s->file, lSeek, SEEK_CUR) == 0) { + } // unused lSeek=0; + else + err = UNZ_ERRNO; + if ((file_info.size_file_comment > 0) && (commentBufferSize > 0)) + if (lufread(szComment, (uInt)uSizeRead, 1, s->file) != 1) + err = UNZ_ERRNO; + //unused lSeek+=file_info.size_file_comment - uSizeRead; + } + else {} //unused lSeek+=file_info.size_file_comment; - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; + if ((err == UNZ_OK) && (pfile_info != NULL)) + *pfile_info = file_info; - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; + if ((err == UNZ_OK) && (pfile_info_internal != NULL)) + *pfile_info_internal = file_info_internal; - return err; + return err; } @@ -3179,56 +3159,57 @@ int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info // Write info about the ZipFile in the *pglobal_info structure. // No preparation of the structure is needed // return UNZ_OK if there is no problem. -int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, - char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, - char *szComment, uLong commentBufferSize) -{ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, szComment,commentBufferSize); +int unzGetCurrentFileInfo(unzFile file, unz_file_info* pfile_info, + char* szFileName, uLong fileNameBufferSize, void* extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unzlocal_GetCurrentFileInfoInternal(file, pfile_info, NULL, szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, szComment, commentBufferSize); } // Set the current file of the zipfile to the first file. // return UNZ_OK if there is no problem -int unzGoToFirstFile (unzFile file) +int unzGoToFirstFile(unzFile file) { - int err; - unz_s* s; - if (file==NULL) return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; + int err; + unz_s* s; + if (file == NULL) return UNZ_PARAMERROR; + s = (unz_s*)file; + s->pos_in_central_dir = s->offset_central_dir; + s->num_file = 0; + err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info, + &s->cur_file_info_internal, + NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; } // Set the current file of the zipfile to the next file. // return UNZ_OK if there is no problem // return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -int unzGoToNextFile (unzFile file) +int unzGoToNextFile(unzFile file) { - unz_s* s; - int err; + unz_s* s; + int err; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->num_file + 1 == s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info, + &s->cur_file_info_internal, + NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; } @@ -3237,45 +3218,44 @@ int unzGoToNextFile (unzFile file) // return value : // UNZ_OK if the file is found. It becomes the current file. // UNZ_END_OF_LIST_OF_FILE if the file is not found -int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +int unzLocateFile(unzFile file, const char* szFileName, int iCaseSensitivity) { - unz_s* s; - int err; + unz_s* s; + int err; - uLong num_fileSaved; - uLong pos_in_central_dirSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + if (file == NULL) return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; + if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; + s = (unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; - err = unzGoToFirstFile(file); + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName,szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } + err = unzGoToFirstFile(file); - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; + while (err == UNZ_OK) { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1]; + unzGetCurrentFileInfo(file, NULL, + szCurrentFileName, sizeof(szCurrentFileName) - 1, + NULL, 0, NULL, 0); + if (unzStringFileNameCompare(szCurrentFileName, szFileName, iCaseSensitivity) == 0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + + s->num_file = num_fileSaved; + s->pos_in_central_dir = pos_in_central_dirSaved; + return err; } @@ -3284,82 +3264,82 @@ int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) // directory about this file // store in *piSizeVar the size of extra info in local header // (filename and size of extra field data) -int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,uInt *piSizeVar, - uLong *poffset_local_extrafield, uInt *psize_local_extrafield) +int unzlocal_CheckCurrentFileCoherencyHeader(unz_s* s, uInt* piSizeVar, + uLong* poffset_local_extrafield, uInt* psize_local_extrafield) { - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; + uLong uMagic, uData, uFlags; + uLong size_filename; + uLong size_extra_field; + int err = UNZ_OK; - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; - if (lufseek(s->file,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; + if (lufseek(s->file, s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile, SEEK_SET) != 0) + return UNZ_ERRNO; - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; + if (err == UNZ_OK) + if (unzlocal_getLong(s->file, &uMagic) != UNZ_OK) + err = UNZ_ERRNO; + else if (uMagic != 0x04034b50) + err = UNZ_BADZIPFILE; - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; -// else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) -// err=UNZ_BADZIPFILE; - if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; + if (unzlocal_getShort(s->file, &uData) != UNZ_OK) + err = UNZ_ERRNO; + // else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + // err=UNZ_BADZIPFILE; + if (unzlocal_getShort(s->file, &uFlags) != UNZ_OK) + err = UNZ_ERRNO; - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; + if (unzlocal_getShort(s->file, &uData) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method)) + err = UNZ_BADZIPFILE; - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; + if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) && + (s->cur_file_info.compression_method != Z_DEFLATED)) + err = UNZ_BADZIPFILE; - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // date/time - err=UNZ_ERRNO; + if (unzlocal_getLong(s->file, &uData) != UNZ_OK) // date/time + err = UNZ_ERRNO; - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // crc - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; + if (unzlocal_getLong(s->file, &uData) != UNZ_OK) // crc + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size compr - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; + if (unzlocal_getLong(s->file, &uData) != UNZ_OK) // size compr + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compressed_size) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size uncompr - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; + if (unzlocal_getLong(s->file, &uData) != UNZ_OK) // size uncompr + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (uData != s->cur_file_info.uncompressed_size) && + ((uFlags & 8) == 0)) + err = UNZ_BADZIPFILE; - if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; + if (unzlocal_getShort(s->file, &size_filename) != UNZ_OK) + err = UNZ_ERRNO; + else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename)) + err = UNZ_BADZIPFILE; - *piSizeVar += (uInt)size_filename; + *piSizeVar += (uInt)size_filename; - if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; + if (unzlocal_getShort(s->file, &size_extra_field) != UNZ_OK) + err = UNZ_ERRNO; + *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; - *piSizeVar += (uInt)size_extra_field; + *piSizeVar += (uInt)size_extra_field; - return err; + return err; } @@ -3368,96 +3348,93 @@ int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,uInt *piSizeVar, // Open for reading data the current file in the zipfile. // If there is no error and the file is opened, the return value is UNZ_OK. -int unzOpenCurrentFile (unzFile file, const char *password) +int unzOpenCurrentFile(unzFile file, const char* password) { - int err; - int Store; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; // offset of the local extra field - uInt size_local_extrafield; // size of the local extra field + int err; + int Store; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; // offset of the local extra field + uInt size_local_extrafield; // size of the local extra field - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; + if (unzlocal_CheckCurrentFileCoherencyHeader(s, &iSizeVar, + &offset_local_extrafield, &size_local_extrafield) != UNZ_OK) + return UNZ_BADZIPFILE; - pfile_in_zip_read_info = (file_in_zip_read_info_s*)zmalloc(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; + pfile_in_zip_read_info = (file_in_zip_read_info_s*)zmalloc(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info == NULL) + return UNZ_INTERNALERROR; - pfile_in_zip_read_info->read_buffer=(char*)zmalloc(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->read_buffer = (char*)zmalloc(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield = 0; - if (pfile_in_zip_read_info->read_buffer==NULL) - { - if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); //unused pfile_in_zip_read_info=0; - return UNZ_INTERNALERROR; - } + if (pfile_in_zip_read_info->read_buffer == NULL) { + if (pfile_in_zip_read_info != 0) zfree(pfile_in_zip_read_info); //unused pfile_in_zip_read_info=0; + return UNZ_INTERNALERROR; + } - pfile_in_zip_read_info->stream_initialised=0; + pfile_in_zip_read_info->stream_initialised = 0; - if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) - { // unused err=UNZ_BADZIPFILE; - } - Store = s->cur_file_info.compression_method==0; + if ((s->cur_file_info.compression_method != 0) && (s->cur_file_info.compression_method != Z_DEFLATED)) { // unused err=UNZ_BADZIPFILE; + } + Store = s->cur_file_info.compression_method == 0; - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; - pfile_in_zip_read_info->file=s->file; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc; + pfile_in_zip_read_info->crc32 = 0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->file = s->file; + pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile; pfile_in_zip_read_info->stream.total_out = 0; - if (!Store) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; + if (!Store) { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; - err=inflateInit2(&pfile_in_zip_read_info->stream); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; + err = inflateInit2(&pfile_in_zip_read_info->stream); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised = 1; // windowBits is passed < 0 to tell that there is no zlib header. // Note that in this case inflate *requires* an extra "dummy" byte // after the compressed stream in order to complete decompression and // return Z_STREAM_END. // In unzip, i don't wait absolutely Z_STREAM_END because I known the // size of both compressed and uncompressed data - } - pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ; - pfile_in_zip_read_info->encrypted = (s->cur_file_info.flag&1)!=0; - bool extlochead = (s->cur_file_info.flag&8)!=0; - if (extlochead) pfile_in_zip_read_info->crcenctest = (char)((s->cur_file_info.dosDate>>8)&0xff); - else pfile_in_zip_read_info->crcenctest = (char)(s->cur_file_info.crc >> 24); - pfile_in_zip_read_info->encheadleft = (pfile_in_zip_read_info->encrypted?12:0); - pfile_in_zip_read_info->keys[0] = 305419896L; - pfile_in_zip_read_info->keys[1] = 591751049L; - pfile_in_zip_read_info->keys[2] = 878082192L; - for (const char *cp=password; cp!=0 && *cp!=0; cp++) Uupdate_keys(pfile_in_zip_read_info->keys,*cp); + } + pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size; + pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size; + pfile_in_zip_read_info->encrypted = (s->cur_file_info.flag & 1) != 0; + bool extlochead = (s->cur_file_info.flag & 8) != 0; + if (extlochead) pfile_in_zip_read_info->crcenctest = (char)((s->cur_file_info.dosDate >> 8) & 0xff); + else pfile_in_zip_read_info->crcenctest = (char)(s->cur_file_info.crc >> 24); + pfile_in_zip_read_info->encheadleft = (pfile_in_zip_read_info->encrypted ? 12 : 0); + pfile_in_zip_read_info->keys[0] = 305419896L; + pfile_in_zip_read_info->keys[1] = 591751049L; + pfile_in_zip_read_info->keys[2] = 878082192L; + for (const char* cp = password; cp != 0 && *cp != 0; cp++) Uupdate_keys(pfile_in_zip_read_info->keys, *cp); - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; - pfile_in_zip_read_info->stream.avail_in = (uInt)0; + pfile_in_zip_read_info->stream.avail_in = (uInt)0; - s->pfile_in_zip_read = pfile_in_zip_read_info; + s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; + return UNZ_OK; } @@ -3468,138 +3445,139 @@ int unzOpenCurrentFile (unzFile file, const char *password) // return 0 if the end of file was reached. (and also sets *reached_eof). // return <0 with error code if there is an error. (in which case *reached_eof is meaningless) // (UNZ_ERRNO for IO error, or zLib error for uncompress error) -int unzReadCurrentFile (unzFile file, voidp buf, unsigned len, bool *reached_eof) -{ int err=UNZ_OK; - uInt iRead = 0; - if (reached_eof!=0) *reached_eof=false; +int unzReadCurrentFile(unzFile file, voidp buf, unsigned len, bool* reached_eof) +{ + int err = UNZ_OK; + uInt iRead = 0; + if (reached_eof != 0) *reached_eof = false; - unz_s *s = (unz_s*)file; - if (s==NULL) return UNZ_PARAMERROR; + unz_s* s = (unz_s*)file; + if (s == NULL) return UNZ_PARAMERROR; - file_in_zip_read_info_s* pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; - if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE; - if (len==0) return 0; + file_in_zip_read_info_s* pfile_in_zip_read_info = s->pfile_in_zip_read; + if (pfile_in_zip_read_info == NULL) return UNZ_PARAMERROR; + if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE; + if (len == 0) return 0; - pfile_in_zip_read_info->stream.next_out = (Byte*)buf; - pfile_in_zip_read_info->stream.avail_out = (uInt)len; + pfile_in_zip_read_info->stream.next_out = (Byte*)buf; + pfile_in_zip_read_info->stream.avail_out = (uInt)len; - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - { pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - } - - while (pfile_in_zip_read_info->stream.avail_out>0) - { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) - { uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) {if (reached_eof!=0) *reached_eof=true; return UNZ_EOF;} - if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO; - if (lufread(pfile_in_zip_read_info->read_buffer,uReadThis,1,pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - pfile_in_zip_read_info->stream.next_in = (Byte*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - // - if (pfile_in_zip_read_info->encrypted) - { char *buf = (char*)pfile_in_zip_read_info->stream.next_in; - for (unsigned int i=0; ikeys,buf[i]); - } + if (len > pfile_in_zip_read_info->rest_read_uncompressed) { + pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; } - unsigned int uDoEncHead = pfile_in_zip_read_info->encheadleft; - if (uDoEncHead>pfile_in_zip_read_info->stream.avail_in) uDoEncHead=pfile_in_zip_read_info->stream.avail_in; - if (uDoEncHead>0) - { char bufcrc=pfile_in_zip_read_info->stream.next_in[uDoEncHead-1]; - pfile_in_zip_read_info->rest_read_uncompressed-=uDoEncHead; - pfile_in_zip_read_info->stream.avail_in -= uDoEncHead; - pfile_in_zip_read_info->stream.next_in += uDoEncHead; - pfile_in_zip_read_info->encheadleft -= uDoEncHead; - if (pfile_in_zip_read_info->encheadleft==0) - { if (bufcrc!=pfile_in_zip_read_info->crcenctest) return UNZ_PASSWORD; - } + while (pfile_in_zip_read_info->stream.avail_out > 0) { + if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed > 0)) { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressed < uReadThis) uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed; + if (uReadThis == 0) { if (reached_eof != 0) *reached_eof = true; return UNZ_EOF; } + if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0) return UNZ_ERRNO; + if (lufread(pfile_in_zip_read_info->read_buffer, uReadThis, 1, pfile_in_zip_read_info->file) != 1) return UNZ_ERRNO; + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + pfile_in_zip_read_info->rest_read_compressed -= uReadThis; + pfile_in_zip_read_info->stream.next_in = (Byte*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + // + if (pfile_in_zip_read_info->encrypted) { + char* buf = (char*)pfile_in_zip_read_info->stream.next_in; + for (unsigned int i = 0; i < uReadThis; i++) buf[i] = zdecode(pfile_in_zip_read_info->keys, buf[i]); + } + } + + unsigned int uDoEncHead = pfile_in_zip_read_info->encheadleft; + if (uDoEncHead > pfile_in_zip_read_info->stream.avail_in) uDoEncHead = pfile_in_zip_read_info->stream.avail_in; + if (uDoEncHead > 0) { + char bufcrc = pfile_in_zip_read_info->stream.next_in[uDoEncHead - 1]; + pfile_in_zip_read_info->rest_read_uncompressed -= uDoEncHead; + pfile_in_zip_read_info->stream.avail_in -= uDoEncHead; + pfile_in_zip_read_info->stream.next_in += uDoEncHead; + pfile_in_zip_read_info->encheadleft -= uDoEncHead; + if (pfile_in_zip_read_info->encheadleft == 0) { + if (bufcrc != pfile_in_zip_read_info->crcenctest) return UNZ_PASSWORD; + } + } + + if (pfile_in_zip_read_info->compression_method == 0) { + uInt uDoCopy, i; + if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) { + uDoCopy = pfile_in_zip_read_info->stream.avail_out; + } + else { + uDoCopy = pfile_in_zip_read_info->stream.avail_in; + } + for (i = 0;i < uDoCopy;i++) *(pfile_in_zip_read_info->stream.next_out + i) = *(pfile_in_zip_read_info->stream.next_in + i); + pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) { if (reached_eof != 0) *reached_eof = true; } + } + else { + uLong uTotalOutBefore, uTotalOutAfter; + const Byte* bufBefore; + uLong uOutThis; + int flush = Z_SYNC_FLUSH; + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + // + err = inflate(&pfile_in_zip_read_info->stream, flush); + // + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter - uTotalOutBefore; + pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32, bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + if (err == Z_STREAM_END || pfile_in_zip_read_info->rest_read_uncompressed == 0) { + if (reached_eof != 0) *reached_eof = true; + return iRead; + } + if (err != Z_OK) break; + } } - if (pfile_in_zip_read_info->compression_method==0) - { uInt uDoCopy,i ; - if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) - { uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - } - else - { uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - } - for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); - pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,pfile_in_zip_read_info->stream.next_out,uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - if (pfile_in_zip_read_info->rest_read_uncompressed==0) {if (reached_eof!=0) *reached_eof=true;} - } - else - { uLong uTotalOutBefore,uTotalOutAfter; - const Byte *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - // - err=inflate(&pfile_in_zip_read_info->stream,flush); - // - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,bufBefore,(uInt)(uOutThis)); - pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - if (err==Z_STREAM_END || pfile_in_zip_read_info->rest_read_uncompressed==0) - { if (reached_eof!=0) *reached_eof=true; - return iRead; - } - if (err!=Z_OK) break; - } - } - - if (err==Z_OK) return iRead; - return err; + if (err == Z_OK) return iRead; + return err; } // Give the current position in uncompressed data -z_off_t unztell (unzFile file) +z_off_t unztell(unzFile file) { - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; - return (z_off_t)pfile_in_zip_read_info->stream.total_out; + return (z_off_t)pfile_in_zip_read_info->stream.total_out; } // return 1 if the end of file was reached, 0 elsewhere -int unzeof (unzFile file) +int unzeof(unzFile file) { - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; } @@ -3610,549 +3588,564 @@ int unzeof (unzFile file) // if buf==NULL, it return the size of the local extra field that can be read // if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. // the return value is the number of bytes copied in buf, or (if <0) the error code -int unzGetLocalExtrafield (unzFile file,voidp buf,unsigned len) +int unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) { - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); - if (buf==NULL) - return (int)size_to_read; + if (buf == NULL) + return (int)size_to_read; - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; + if (len > size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len; - if (read_now==0) - return 0; + if (read_now == 0) + return 0; - if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) - return UNZ_ERRNO; + if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, SEEK_SET) != 0) + return UNZ_ERRNO; - if (lufread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; + if (lufread(buf, (uInt)size_to_read, 1, pfile_in_zip_read_info->file) != 1) + return UNZ_ERRNO; - return (int)read_now; + return (int)read_now; } // Close the file in zip opened with unzipOpenCurrentFile // Return UNZ_CRCERROR if all the file was read but the CRC is not good -int unzCloseCurrentFile (unzFile file) +int unzCloseCurrentFile(unzFile file) { - int err=UNZ_OK; + int err = UNZ_OK; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file == NULL) + return UNZ_PARAMERROR; + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; + if (pfile_in_zip_read_info == NULL) + return UNZ_PARAMERROR; - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err = UNZ_CRCERROR; + } - if (pfile_in_zip_read_info->read_buffer!=0) - { void *buf = pfile_in_zip_read_info->read_buffer; - zfree(buf); - pfile_in_zip_read_info->read_buffer=0; - } - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); + if (pfile_in_zip_read_info->read_buffer != 0) { + void* buf = pfile_in_zip_read_info->read_buffer; + zfree(buf); + pfile_in_zip_read_info->read_buffer = 0; + } + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); - pfile_in_zip_read_info->stream_initialised = 0; - if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); // unused pfile_in_zip_read_info=0; + pfile_in_zip_read_info->stream_initialised = 0; + if (pfile_in_zip_read_info != 0) zfree(pfile_in_zip_read_info); // unused pfile_in_zip_read_info=0; - s->pfile_in_zip_read=NULL; + s->pfile_in_zip_read = NULL; - return err; + return err; } // Get the global comment string of the ZipFile, in the szComment buffer. // uSizeBuf is the size of the szComment buffer. // return the number of byte copied or an error code <0 -int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf) +int unzGetGlobalComment(unzFile file, char* szComment, uLong uSizeBuf) { //int err=UNZ_OK; - unz_s* s; - uLong uReadThis ; - if (file==NULL) return UNZ_PARAMERROR; - s=(unz_s*)file; - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; - if (lufseek(s->file,s->central_pos+22,SEEK_SET)!=0) return UNZ_ERRNO; - if (uReadThis>0) - { *szComment='\0'; - if (lufread(szComment,(uInt)uReadThis,1,s->file)!=1) return UNZ_ERRNO; - } - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; + unz_s* s; + uLong uReadThis; + if (file == NULL) return UNZ_PARAMERROR; + s = (unz_s*)file; + uReadThis = uSizeBuf; + if (uReadThis > s->gi.size_comment) uReadThis = s->gi.size_comment; + if (lufseek(s->file, s->central_pos + 22, SEEK_SET) != 0) return UNZ_ERRNO; + if (uReadThis > 0) { + *szComment = '\0'; + if (lufread(szComment, (uInt)uReadThis, 1, s->file) != 1) return UNZ_ERRNO; + } + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment + s->gi.size_comment) = '\0'; + return (int)uReadThis; } -int unzOpenCurrentFile (unzFile file, const char *password); -int unzReadCurrentFile (unzFile file, void *buf, unsigned len); -int unzCloseCurrentFile (unzFile file); +int unzOpenCurrentFile(unzFile file, const char* password); +int unzReadCurrentFile(unzFile file, void* buf, unsigned len); +int unzCloseCurrentFile(unzFile file); typedef unsigned __int32 lutime_t; // define it ourselves since we don't include time.h FILETIME timet2filetime(const lutime_t t) -{ LONGLONG i = Int32x32To64(t,10000000) + 116444736000000000; - FILETIME ft; - ft.dwLowDateTime = (DWORD) i; - ft.dwHighDateTime = (DWORD)(i >>32); - return ft; +{ + LONGLONG i = Int32x32To64(t, 10000000) + 116444736000000000; + FILETIME ft; + ft.dwLowDateTime = (DWORD)i; + ft.dwHighDateTime = (DWORD)(i >> 32); + return ft; } -FILETIME dosdatetime2filetime(WORD dosdate,WORD dostime) +FILETIME dosdatetime2filetime(WORD dosdate, WORD dostime) { // date: bits 0-4 are day of month 1-31. Bits 5-8 are month 1..12. Bits 9-15 are year-1980 // time: bits 0-4 are seconds/2, bits 5-10 are minute 0..59. Bits 11-15 are hour 0..23 - SYSTEMTIME st; - st.wYear = (WORD)(((dosdate>>9)&0x7f) + 1980); - st.wMonth = (WORD)((dosdate>>5)&0xf); - st.wDay = (WORD)(dosdate&0x1f); - st.wHour = (WORD)((dostime>>11)&0x1f); - st.wMinute = (WORD)((dostime>>5)&0x3f); - st.wSecond = (WORD)((dostime&0x1f)*2); - st.wMilliseconds = 0; - FILETIME ft; SystemTimeToFileTime(&st,&ft); - return ft; + SYSTEMTIME st; + st.wYear = (WORD)(((dosdate >> 9) & 0x7f) + 1980); + st.wMonth = (WORD)((dosdate >> 5) & 0xf); + st.wDay = (WORD)(dosdate & 0x1f); + st.wHour = (WORD)((dostime >> 11) & 0x1f); + st.wMinute = (WORD)((dostime >> 5) & 0x3f); + st.wSecond = (WORD)((dostime & 0x1f) * 2); + st.wMilliseconds = 0; + FILETIME ft; SystemTimeToFileTime(&st, &ft); + return ft; } class TUnzip -{ public: - TUnzip(const char *pwd) : uf(0), unzbuf(0), currentfile(-1), czei(-1), password(0) {if (pwd!=0) {password=new char[strlen(pwd)+1]; strcpy_s(password,MAX_PATH,pwd);}} - ~TUnzip() {if (password!=0) delete[] password; password=0; if (unzbuf!=0) delete[] unzbuf; unzbuf=0;} +{ +public: + TUnzip(const char* pwd) : uf(0), unzbuf(0), currentfile(-1), czei(-1), password(0) { if (pwd != 0) { password = new char[strlen(pwd) + 1]; strcpy_s(password, MAX_PATH, pwd); } } + ~TUnzip() { if (password != 0) delete[] password; password = 0; if (unzbuf != 0) delete[] unzbuf; unzbuf = 0; } - unzFile uf; int currentfile; ZIPENTRY cze; int czei; - char *password; - char *unzbuf; // lazily created and destroyed, used by Unzip - TCHAR rootdir[MAX_PATH]; // includes a trailing slash + unzFile uf; int currentfile; ZIPENTRY cze; int czei; + char* password; + char* unzbuf; // lazily created and destroyed, used by Unzip + TCHAR rootdir[MAX_PATH]; // includes a trailing slash - ZRESULT Open(void *z,unsigned int len,DWORD flags); - ZRESULT Get(int index,ZIPENTRY *ze); - ZRESULT Find(const TCHAR *name,bool ic,int *index,ZIPENTRY *ze); - ZRESULT Unzip(int index,void *dst,unsigned int len,DWORD flags); - ZRESULT SetUnzipBaseDir(const TCHAR *dir); - ZRESULT Close(); + ZRESULT Open(void* z, unsigned int len, DWORD flags); + ZRESULT Get(int index, ZIPENTRY* ze); + ZRESULT Find(const TCHAR* name, bool ic, int* index, ZIPENTRY* ze); + ZRESULT Unzip(int index, void* dst, unsigned int len, DWORD flags); + ZRESULT SetUnzipBaseDir(const TCHAR* dir); + ZRESULT Close(); }; -ZRESULT TUnzip::Open(void *z,unsigned int len,DWORD flags) -{ if (uf!=0 || currentfile!=-1) return ZR_NOTINITED; - // -#ifdef GetCurrentDirectory - GetCurrentDirectory(MAX_PATH,rootdir); -#else - _tcscpy(rootdir,_T("\\")); -#endif - TCHAR lastchar = rootdir[_tcslen(rootdir)-1]; - if (lastchar!='\\' && lastchar!='/') _tcscat_s(rootdir,_T("\\")); - // - if (flags==ZIP_HANDLE) - { // test if we can seek on it. We can't use GetFileType(h)==FILE_TYPE_DISK since it's not on CE. - DWORD res = SetFilePointer(z,0,0,FILE_CURRENT); - bool canseek = (res!=0xFFFFFFFF); - if (!canseek) return ZR_SEEK; - } - ZRESULT e; LUFILE *f = lufopen(z,len,flags,&e); - if (f==NULL) return e; - uf = unzOpenInternal(f); - if (uf==0) return ZR_NOFILE; - return ZR_OK; -} - -ZRESULT TUnzip::SetUnzipBaseDir(const TCHAR *dir) +ZRESULT TUnzip::Open(void* z, unsigned int len, DWORD flags) { - _tcscpy_s(rootdir, MAX_PATH, dir); - TCHAR lastchar = rootdir[_tcslen(rootdir)-1]; - if (lastchar!='\\' && lastchar!='/') _tcscat_s(rootdir,_T("\\")); - return ZR_OK; -} - -ZRESULT TUnzip::Get(int index,ZIPENTRY *ze) -{ if (index<-1 || index>=(int)uf->gi.number_entry) return ZR_ARGS; - if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; - if (index==czei && index!=-1) {memcpy(ze,&cze,sizeof(ZIPENTRY)); return ZR_OK;} - if (index==-1) - { ze->index = uf->gi.number_entry; - ze->name[0]=0; - ze->attr=0; - ze->atime.dwLowDateTime=0; ze->atime.dwHighDateTime=0; - ze->ctime.dwLowDateTime=0; ze->ctime.dwHighDateTime=0; - ze->mtime.dwLowDateTime=0; ze->mtime.dwHighDateTime=0; - ze->comp_size=0; - ze->unc_size=0; - return ZR_OK; - } - if (index<(int)uf->num_file) unzGoToFirstFile(uf); - while ((int)uf->num_filefile,offset,SEEK_SET)!=0) return ZR_READ; - unsigned char *extra = new unsigned char[extralen]; - if (lufread(extra,1,(uInt)extralen,uf->file)!=extralen) {delete[] extra; return ZR_READ;} - // - ze->index=uf->num_file; - TCHAR tfn[MAX_PATH]; -#ifdef UNICODE - MultiByteToWideChar(CP_UTF8,0,fn,-1,tfn,MAX_PATH); -#else - strcpy(tfn,fn); -#endif - // As a safety feature: if the zip filename had sneaky stuff - // like "c:\windows\file.txt" or "\windows\file.txt" or "fred\..\..\..\windows\file.txt" - // then we get rid of them all. That way, when the programmer does UnzipItem(hz,i,ze.name), - // it won't be a problem. (If the programmer really did want to get the full evil information, - // then they can edit out this security feature from here). - // In particular, we chop off any prefixes that are "c:\" or "\" or "/" or "[stuff]\.." or "[stuff]/.." - const TCHAR *sfn=tfn; - for (;;) - { if (sfn[0]!=0 && sfn[1]==':') {sfn+=2; continue;} - if (sfn[0]=='\\') {sfn++; continue;} - if (sfn[0]=='/') {sfn++; continue;} - const TCHAR *c; - c=_tcsstr(sfn,_T("\\..\\")); if (c!=0) {sfn=c+4; continue;} - c=_tcsstr(sfn,_T("\\../")); if (c!=0) {sfn=c+4; continue;} - c=_tcsstr(sfn,_T("/../")); if (c!=0) {sfn=c+4; continue;} - c=_tcsstr(sfn,_T("/..\\")); if (c!=0) {sfn=c+4; continue;} - break; - } - _tcscpy_s(ze->name, MAX_PATH, sfn); - - - // zip has an 'attribute' 32bit value. Its lower half is windows stuff - // its upper half is standard unix stat.st_mode. We'll start trying - // to read it in unix mode - unsigned long a = ufi.external_fa; - bool isdir = (a&0x40000000)!=0; - bool readonly= (a&0x00800000)==0; - //bool readable= (a&0x01000000)!=0; // unused - //bool executable=(a&0x00400000)!=0; // unused - bool hidden=false, system=false, archive=true; - // but in normal hostmodes these are overridden by the lower half... - int host = ufi.version>>8; - if (host==0 || host==7 || host==11 || host==14) - { readonly= (a&0x00000001)!=0; - hidden= (a&0x00000002)!=0; - system= (a&0x00000004)!=0; - isdir= (a&0x00000010)!=0; - archive= (a&0x00000020)!=0; - } - ze->attr=0; - if (isdir) ze->attr |= FILE_ATTRIBUTE_DIRECTORY; - if (archive) ze->attr|=FILE_ATTRIBUTE_ARCHIVE; - if (hidden) ze->attr|=FILE_ATTRIBUTE_HIDDEN; - if (readonly) ze->attr|=FILE_ATTRIBUTE_READONLY; - if (system) ze->attr|=FILE_ATTRIBUTE_SYSTEM; - ze->comp_size = ufi.compressed_size; - ze->unc_size = ufi.uncompressed_size; - // - WORD dostime = (WORD)(ufi.dosDate&0xFFFF); - WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF); - FILETIME ftd = dosdatetime2filetime(dosdate,dostime); - FILETIME ft; LocalFileTimeToFileTime(&ftd,&ft); - ze->atime=ft; ze->ctime=ft; ze->mtime=ft; - // the zip will always have at least that dostime. But if it also has - // an extra header, then we'll instead get the info from that. - unsigned int epos=0; - while (epos+4mtime = timet2filetime(mtime); - } - if (hasatime) - { lutime_t atime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24); - epos+=4; - ze->atime = timet2filetime(atime); - } - if (hasctime) - { lutime_t ctime = ((extra[epos+0])<<0) | ((extra[epos+1])<<8) |((extra[epos+2])<<16) | ((extra[epos+3])<<24); - epos+=4; - ze->ctime = timet2filetime(ctime); - } - break; - } - // - if (extra!=0) delete[] extra; - memcpy(&cze,ze,sizeof(ZIPENTRY)); czei=index; - return ZR_OK; -} - -ZRESULT TUnzip::Find(const TCHAR *tname,bool ic,int *index,ZIPENTRY *ze) -{ char name[MAX_PATH]; -#ifdef UNICODE - WideCharToMultiByte(CP_UTF8,0,tname,-1,name,MAX_PATH,0,0); -#else - strcpy(name,tname); -#endif - int res = unzLocateFile(uf,name,ic?CASE_INSENSITIVE:CASE_SENSITIVE); - if (res!=UNZ_OK) - { if (index!=0) *index=-1; - if (ze!=NULL) {ZeroMemory(ze,sizeof(ZIPENTRY)); ze->index=-1;} - return ZR_NOTFOUND; - } - if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; - int i = (int)uf->num_file; - if (index!=NULL) *index=i; - if (ze!=NULL) - { ZRESULT zres = Get(i,ze); - if (zres!=ZR_OK) return zres; - } - return ZR_OK; -} - -void EnsureDirectory(const TCHAR *rootdir, const TCHAR *dir) -{ if (rootdir!=0 && GetFileAttributes(rootdir)==0xFFFFFFFF) CreateDirectory(rootdir,0); - if (*dir==0) return; - const TCHAR *lastslash=dir, *c=lastslash; - while (*c!=0) {if (*c=='/' || *c=='\\') lastslash=c; c++;} - const TCHAR *name=lastslash; - if (lastslash!=dir) - { TCHAR tmp[MAX_PATH]; memcpy(tmp,dir,sizeof(TCHAR)*(lastslash-dir)); - tmp[lastslash-dir]=0; - EnsureDirectory(rootdir,tmp); - name++; - } - TCHAR cd[MAX_PATH]; *cd=0; if (rootdir!=0) _tcscpy_s(cd, MAX_PATH, rootdir); _tcscat_s(cd,dir); - if (GetFileAttributes(cd)==0xFFFFFFFF) CreateDirectory(cd,NULL); -} - - - -ZRESULT TUnzip::Unzip(int index,void *dst,unsigned int len,DWORD flags) -{ if (flags!=ZIP_MEMORY && flags!=ZIP_FILENAME && flags!=ZIP_HANDLE) return ZR_ARGS; - if (flags==ZIP_MEMORY) - { if (index!=currentfile) - { if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; - if (index>=(int)uf->gi.number_entry) return ZR_ARGS; - if (index<(int)uf->num_file) unzGoToFirstFile(uf); - while ((int)uf->num_file0) return ZR_MORE; - if (res==UNZ_PASSWORD) return ZR_PASSWORD; - return ZR_FLATE; - } - // otherwise we're writing to a handle or a file - if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; - if (index>=(int)uf->gi.number_entry) return ZR_ARGS; - if (index<(int)uf->num_file) unzGoToFirstFile(uf); - while ((int)uf->num_file0) {DWORD writ; BOOL bres=WriteFile(h,unzbuf,res,&writ,NULL); if (!bres) {haderr=ZR_WRITE; break;}} - if (reached_eof) break; - if (res==0) {haderr=ZR_FLATE; break;} - } - if (!haderr) SetFileTime(h,&ze.ctime,&ze.atime,&ze.mtime); // may fail if it was a pipe - if (flags!=ZIP_HANDLE) CloseHandle(h); - unzCloseCurrentFile(uf); - if (haderr!=0) return haderr; - return ZR_OK; +ZRESULT TUnzip::SetUnzipBaseDir(const TCHAR* dir) +{ + _tcscpy_s(rootdir, MAX_PATH, dir); + TCHAR lastchar = rootdir[_tcslen(rootdir) - 1]; + if (lastchar != '\\' && lastchar != '/') _tcscat_s(rootdir, _T("\\")); + return ZR_OK; +} + +ZRESULT TUnzip::Get(int index, ZIPENTRY* ze) +{ + if (index < -1 || index >= (int)uf->gi.number_entry) return ZR_ARGS; + if (currentfile != -1) unzCloseCurrentFile(uf); currentfile = -1; + if (index == czei && index != -1) { memcpy(ze, &cze, sizeof(ZIPENTRY)); return ZR_OK; } + if (index == -1) { + ze->index = uf->gi.number_entry; + ze->name[0] = 0; + ze->attr = 0; + ze->atime.dwLowDateTime = 0; ze->atime.dwHighDateTime = 0; + ze->ctime.dwLowDateTime = 0; ze->ctime.dwHighDateTime = 0; + ze->mtime.dwLowDateTime = 0; ze->mtime.dwHighDateTime = 0; + ze->comp_size = 0; + ze->unc_size = 0; + return ZR_OK; + } + if (index < (int)uf->num_file) unzGoToFirstFile(uf); + while ((int)uf->num_file < index) unzGoToNextFile(uf); + unz_file_info ufi; char fn[MAX_PATH]; + unzGetCurrentFileInfo(uf, &ufi, fn, MAX_PATH, NULL, 0, NULL, 0); + // now get the extra header. We do this ourselves, instead of + // calling unzOpenCurrentFile &c., to avoid allocating more than necessary. + unsigned int extralen, iSizeVar; unsigned long offset; + int res = unzlocal_CheckCurrentFileCoherencyHeader(uf, &iSizeVar, &offset, &extralen); + if (res != UNZ_OK) return ZR_CORRUPT; + if (lufseek(uf->file, offset, SEEK_SET) != 0) return ZR_READ; + unsigned char* extra = new unsigned char[extralen]; + if (lufread(extra, 1, (uInt)extralen, uf->file) != extralen) { delete[] extra; return ZR_READ; } + // + ze->index = uf->num_file; + TCHAR tfn[MAX_PATH]; +#ifdef UNICODE + MultiByteToWideChar(CP_UTF8, 0, fn, -1, tfn, MAX_PATH); +#else + strcpy(tfn, fn); +#endif + // As a safety feature: if the zip filename had sneaky stuff + // like "c:\windows\file.txt" or "\windows\file.txt" or "fred\..\..\..\windows\file.txt" + // then we get rid of them all. That way, when the programmer does UnzipItem(hz,i,ze.name), + // it won't be a problem. (If the programmer really did want to get the full evil information, + // then they can edit out this security feature from here). + // In particular, we chop off any prefixes that are "c:\" or "\" or "/" or "[stuff]\.." or "[stuff]/.." + const TCHAR* sfn = tfn; + for (;;) { + if (sfn[0] != 0 && sfn[1] == ':') { sfn += 2; continue; } + if (sfn[0] == '\\') { sfn++; continue; } + if (sfn[0] == '/') { sfn++; continue; } + const TCHAR* c; + c = _tcsstr(sfn, _T("\\..\\")); if (c != 0) { sfn = c + 4; continue; } + c = _tcsstr(sfn, _T("\\../")); if (c != 0) { sfn = c + 4; continue; } + c = _tcsstr(sfn, _T("/../")); if (c != 0) { sfn = c + 4; continue; } + c = _tcsstr(sfn, _T("/..\\")); if (c != 0) { sfn = c + 4; continue; } + break; + } + _tcscpy_s(ze->name, MAX_PATH, sfn); + + + // zip has an 'attribute' 32bit value. Its lower half is windows stuff + // its upper half is standard unix stat.st_mode. We'll start trying + // to read it in unix mode + unsigned long a = ufi.external_fa; + bool isdir = (a & 0x40000000) != 0; + bool readonly = (a & 0x00800000) == 0; + //bool readable= (a&0x01000000)!=0; // unused + //bool executable=(a&0x00400000)!=0; // unused + bool hidden = false, system = false, archive = true; + // but in normal hostmodes these are overridden by the lower half... + int host = ufi.version >> 8; + if (host == 0 || host == 7 || host == 11 || host == 14) { + readonly = (a & 0x00000001) != 0; + hidden = (a & 0x00000002) != 0; + system = (a & 0x00000004) != 0; + isdir = (a & 0x00000010) != 0; + archive = (a & 0x00000020) != 0; + } + ze->attr = 0; + if (isdir) ze->attr |= FILE_ATTRIBUTE_DIRECTORY; + if (archive) ze->attr |= FILE_ATTRIBUTE_ARCHIVE; + if (hidden) ze->attr |= FILE_ATTRIBUTE_HIDDEN; + if (readonly) ze->attr |= FILE_ATTRIBUTE_READONLY; + if (system) ze->attr |= FILE_ATTRIBUTE_SYSTEM; + ze->comp_size = ufi.compressed_size; + ze->unc_size = ufi.uncompressed_size; + // + WORD dostime = (WORD)(ufi.dosDate & 0xFFFF); + WORD dosdate = (WORD)((ufi.dosDate >> 16) & 0xFFFF); + FILETIME ftd = dosdatetime2filetime(dosdate, dostime); + FILETIME ft; LocalFileTimeToFileTime(&ftd, &ft); + ze->atime = ft; ze->ctime = ft; ze->mtime = ft; + // the zip will always have at least that dostime. But if it also has + // an extra header, then we'll instead get the info from that. + unsigned int epos = 0; + while (epos + 4 < extralen) { + char etype[3]; etype[0] = extra[epos + 0]; etype[1] = extra[epos + 1]; etype[2] = 0; + int size = extra[epos + 2]; + if (strcmp(etype, "UT") != 0) { epos += 4 + size; continue; } + int flags = extra[epos + 4]; + bool hasmtime = (flags & 1) != 0; + bool hasatime = (flags & 2) != 0; + bool hasctime = (flags & 4) != 0; + epos += 5; + if (hasmtime) { + lutime_t mtime = ((extra[epos + 0]) << 0) | ((extra[epos + 1]) << 8) | ((extra[epos + 2]) << 16) | ((extra[epos + 3]) << 24); + epos += 4; + ze->mtime = timet2filetime(mtime); + } + if (hasatime) { + lutime_t atime = ((extra[epos + 0]) << 0) | ((extra[epos + 1]) << 8) | ((extra[epos + 2]) << 16) | ((extra[epos + 3]) << 24); + epos += 4; + ze->atime = timet2filetime(atime); + } + if (hasctime) { + lutime_t ctime = ((extra[epos + 0]) << 0) | ((extra[epos + 1]) << 8) | ((extra[epos + 2]) << 16) | ((extra[epos + 3]) << 24); + epos += 4; + ze->ctime = timet2filetime(ctime); + } + break; + } + // + if (extra != 0) delete[] extra; + memcpy(&cze, ze, sizeof(ZIPENTRY)); czei = index; + return ZR_OK; +} + +ZRESULT TUnzip::Find(const TCHAR* tname, bool ic, int* index, ZIPENTRY* ze) +{ + char name[MAX_PATH]; +#ifdef UNICODE + WideCharToMultiByte(CP_UTF8, 0, tname, -1, name, MAX_PATH, 0, 0); +#else + strcpy(name, tname); +#endif + int res = unzLocateFile(uf, name, ic ? CASE_INSENSITIVE : CASE_SENSITIVE); + if (res != UNZ_OK) { + if (index != 0) *index = -1; + if (ze != NULL) { ZeroMemory(ze, sizeof(ZIPENTRY)); ze->index = -1; } + return ZR_NOTFOUND; + } + if (currentfile != -1) unzCloseCurrentFile(uf); currentfile = -1; + int i = (int)uf->num_file; + if (index != NULL) *index = i; + if (ze != NULL) { + ZRESULT zres = Get(i, ze); + if (zres != ZR_OK) return zres; + } + return ZR_OK; +} + +void EnsureDirectory(const TCHAR* rootdir, const TCHAR* dir) +{ + if (rootdir != 0 && GetFileAttributes(rootdir) == 0xFFFFFFFF) CreateDirectory(rootdir, 0); + if (*dir == 0) return; + const TCHAR* lastslash = dir, * c = lastslash; + while (*c != 0) { if (*c == '/' || *c == '\\') lastslash = c; c++; } + const TCHAR* name = lastslash; + if (lastslash != dir) { + TCHAR tmp[MAX_PATH]; memcpy(tmp, dir, sizeof(TCHAR) * (lastslash - dir)); + tmp[lastslash - dir] = 0; + EnsureDirectory(rootdir, tmp); + name++; + } + TCHAR cd[MAX_PATH]; *cd = 0; if (rootdir != 0) _tcscpy_s(cd, MAX_PATH, rootdir); _tcscat_s(cd, dir); + if (GetFileAttributes(cd) == 0xFFFFFFFF) CreateDirectory(cd, NULL); +} + + + +ZRESULT TUnzip::Unzip(int index, void* dst, unsigned int len, DWORD flags) +{ + if (flags != ZIP_MEMORY && flags != ZIP_FILENAME && flags != ZIP_HANDLE) return ZR_ARGS; + if (flags == ZIP_MEMORY) { + if (index != currentfile) { + if (currentfile != -1) unzCloseCurrentFile(uf); currentfile = -1; + if (index >= (int)uf->gi.number_entry) return ZR_ARGS; + if (index < (int)uf->num_file) unzGoToFirstFile(uf); + while ((int)uf->num_file < index) unzGoToNextFile(uf); + unzOpenCurrentFile(uf, password); currentfile = index; + } + bool reached_eof; + int res = unzReadCurrentFile(uf, dst, len, &reached_eof); + if (res <= 0) { unzCloseCurrentFile(uf); currentfile = -1; } + if (reached_eof) return ZR_OK; + if (res > 0) return ZR_MORE; + if (res == UNZ_PASSWORD) return ZR_PASSWORD; + return ZR_FLATE; + } + // otherwise we're writing to a handle or a file + if (currentfile != -1) unzCloseCurrentFile(uf); currentfile = -1; + if (index >= (int)uf->gi.number_entry) return ZR_ARGS; + if (index < (int)uf->num_file) unzGoToFirstFile(uf); + while ((int)uf->num_file < index) unzGoToNextFile(uf); + ZIPENTRY ze; Get(index, &ze); + // zipentry=directory is handled specially + if ((ze.attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + if (flags == ZIP_HANDLE) return ZR_OK; // don't do anything + const TCHAR* dir = (const TCHAR*)dst; + bool isabsolute = (dir[0] == '/' || dir[0] == '\\' || (dir[0] != 0 && dir[1] == ':')); + if (isabsolute) EnsureDirectory(0, dir); else EnsureDirectory(rootdir, dir); + return ZR_OK; + } + // otherwise, we write the zipentry to a file/handle + HANDLE h; + if (flags == ZIP_HANDLE) h = dst; + else { + const TCHAR* ufn = (const TCHAR*)dst; + // We'll qualify all relative names to our root dir, and leave absolute names as they are + // ufn="zipfile.txt" dir="" name="zipfile.txt" fn="c:\\currentdir\\zipfile.txt" + // ufn="dir1/dir2/subfile.txt" dir="dir1/dir2/" name="subfile.txt" fn="c:\\currentdir\\dir1/dir2/subfiles.txt" + // ufn="\z\file.txt" dir="\z\" name="file.txt" fn="\z\file.txt" + // This might be a security risk, in the case where we just use the zipentry's name as "ufn", where + // a malicious zip could unzip itself into c:\windows. Our solution is that GetZipItem (which + // is how the user retrieve's the file's name within the zip) never returns absolute paths. + const TCHAR* name = ufn; const TCHAR* c = name; while (*c != 0) { if (*c == '/' || *c == '\\') name = c + 1; c++; } + TCHAR dir[MAX_PATH]; _tcscpy_s(dir, MAX_PATH, ufn); if (name == ufn) *dir = 0; else dir[name - ufn] = 0; + TCHAR fn[MAX_PATH]; + bool isabsolute = (dir[0] == '/' || dir[0] == '\\' || (dir[0] != 0 && dir[1] == ':')); + if (isabsolute) { wsprintf(fn, _T("%s%s"), dir, name); EnsureDirectory(0, dir); } + else { wsprintf(fn, _T("%s%s%s"), rootdir, dir, name); EnsureDirectory(rootdir, dir); } + // + h = CreateFile(fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, ze.attr, NULL); + } + if (h == INVALID_HANDLE_VALUE) return ZR_NOFILE; + unzOpenCurrentFile(uf, password); + if (unzbuf == 0) unzbuf = new char[16384]; DWORD haderr = 0; + // + + for (; haderr == 0;) { + bool reached_eof; + int res = unzReadCurrentFile(uf, unzbuf, 16384, &reached_eof); + if (res == UNZ_PASSWORD) { haderr = ZR_PASSWORD; break; } + if (res < 0) { haderr = ZR_FLATE; break; } + if (res > 0) { DWORD writ; BOOL bres = WriteFile(h, unzbuf, res, &writ, NULL); if (!bres) { haderr = ZR_WRITE; break; } } + if (reached_eof) break; + if (res == 0) { haderr = ZR_FLATE; break; } + } + if (!haderr) SetFileTime(h, &ze.ctime, &ze.atime, &ze.mtime); // may fail if it was a pipe + if (flags != ZIP_HANDLE) CloseHandle(h); + unzCloseCurrentFile(uf); + if (haderr != 0) return haderr; + return ZR_OK; } ZRESULT TUnzip::Close() -{ if (currentfile!=-1) unzCloseCurrentFile(uf); currentfile=-1; - if (uf!=0) unzClose(uf); uf=0; - return ZR_OK; +{ + if (currentfile != -1) unzCloseCurrentFile(uf); currentfile = -1; + if (uf != 0) unzClose(uf); uf = 0; + return ZR_OK; } -ZRESULT lasterrorU=ZR_OK; +ZRESULT lasterrorU = ZR_OK; -unsigned int FormatZipMessageU(ZRESULT code, TCHAR *buf,unsigned int len) -{ if (code==ZR_RECENT) code=lasterrorU; - const TCHAR *msg=_T("unknown zip result code"); - switch (code) - { case ZR_OK: msg=_T("Success"); break; - case ZR_NODUPH: msg=_T("Culdn't duplicate handle"); break; - case ZR_NOFILE: msg=_T("Couldn't create/open file"); break; - case ZR_NOALLOC: msg=_T("Failed to allocate memory"); break; - case ZR_WRITE: msg=_T("Error writing to file"); break; - case ZR_NOTFOUND: msg=_T("File not found in the zipfile"); break; - case ZR_MORE: msg=_T("Still more data to unzip"); break; - case ZR_CORRUPT: msg=_T("Zipfile is corrupt or not a zipfile"); break; - case ZR_READ: msg=_T("Error reading file"); break; - case ZR_PASSWORD: msg=_T("Correct password required"); break; - case ZR_ARGS: msg=_T("Caller: faulty arguments"); break; - case ZR_PARTIALUNZ: msg=_T("Caller: the file had already been partially unzipped"); break; - case ZR_NOTMMAP: msg=_T("Caller: can only get memory of a memory zipfile"); break; - case ZR_MEMSIZE: msg=_T("Caller: not enough space allocated for memory zipfile"); break; - case ZR_FAILED: msg=_T("Caller: there was a previous error"); break; - case ZR_ENDED: msg=_T("Caller: additions to the zip have already been ended"); break; - case ZR_ZMODE: msg=_T("Caller: mixing creation and opening of zip"); break; - case ZR_NOTINITED: msg=_T("Zip-bug: internal initialisation not completed"); break; - case ZR_SEEK: msg=_T("Zip-bug: trying to seek the unseekable"); break; - case ZR_MISSIZE: msg=_T("Zip-bug: the anticipated size turned out wrong"); break; - case ZR_NOCHANGE: msg=_T("Zip-bug: tried to change mind, but not allowed"); break; - case ZR_FLATE: msg=_T("Zip-bug: an internal error during flation"); break; - } - unsigned int mlen=(unsigned int)_tcslen(msg); - if (buf==0 || len==0) return mlen; - unsigned int n=mlen; if (n+1>len) n=len-1; - _tcsncpy_s(buf,MAX_PATH,msg,n); buf[n]=0; - return mlen; +unsigned int FormatZipMessageU(ZRESULT code, TCHAR* buf, unsigned int len) +{ + if (code == ZR_RECENT) code = lasterrorU; + const TCHAR* msg = _T("unknown zip result code"); + switch (code) { + case ZR_OK: msg = _T("Success"); break; + case ZR_NODUPH: msg = _T("Culdn't duplicate handle"); break; + case ZR_NOFILE: msg = _T("Couldn't create/open file"); break; + case ZR_NOALLOC: msg = _T("Failed to allocate memory"); break; + case ZR_WRITE: msg = _T("Error writing to file"); break; + case ZR_NOTFOUND: msg = _T("File not found in the zipfile"); break; + case ZR_MORE: msg = _T("Still more data to unzip"); break; + case ZR_CORRUPT: msg = _T("Zipfile is corrupt or not a zipfile"); break; + case ZR_READ: msg = _T("Error reading file"); break; + case ZR_PASSWORD: msg = _T("Correct password required"); break; + case ZR_ARGS: msg = _T("Caller: faulty arguments"); break; + case ZR_PARTIALUNZ: msg = _T("Caller: the file had already been partially unzipped"); break; + case ZR_NOTMMAP: msg = _T("Caller: can only get memory of a memory zipfile"); break; + case ZR_MEMSIZE: msg = _T("Caller: not enough space allocated for memory zipfile"); break; + case ZR_FAILED: msg = _T("Caller: there was a previous error"); break; + case ZR_ENDED: msg = _T("Caller: additions to the zip have already been ended"); break; + case ZR_ZMODE: msg = _T("Caller: mixing creation and opening of zip"); break; + case ZR_NOTINITED: msg = _T("Zip-bug: internal initialisation not completed"); break; + case ZR_SEEK: msg = _T("Zip-bug: trying to seek the unseekable"); break; + case ZR_MISSIZE: msg = _T("Zip-bug: the anticipated size turned out wrong"); break; + case ZR_NOCHANGE: msg = _T("Zip-bug: tried to change mind, but not allowed"); break; + case ZR_FLATE: msg = _T("Zip-bug: an internal error during flation"); break; + } + unsigned int mlen = (unsigned int)_tcslen(msg); + if (buf == 0 || len == 0) return mlen; + unsigned int n = mlen; if (n + 1 > len) n = len - 1; + _tcsncpy_s(buf, MAX_PATH, msg, n); buf[n] = 0; + return mlen; } typedef struct -{ DWORD flag; - TUnzip *unz; +{ + DWORD flag; + TUnzip* unz; } TUnzipHandleData; -HZIP OpenZipInternal(void *z,unsigned int len,DWORD flags, const char *password) -{ TUnzip *unz = new TUnzip(password); - lasterrorU = unz->Open(z,len,flags); - if (lasterrorU!=ZR_OK) {delete unz; return 0;} - TUnzipHandleData *han = new TUnzipHandleData; - han->flag=1; han->unz=unz; return (HZIP)han; +HZIP OpenZipInternal(void* z, unsigned int len, DWORD flags, const char* password) +{ + TUnzip* unz = new TUnzip(password); + lasterrorU = unz->Open(z, len, flags); + if (lasterrorU != ZR_OK) { delete unz; return 0; } + TUnzipHandleData* han = new TUnzipHandleData; + han->flag = 1; han->unz = unz; return (HZIP)han; } -HZIP OpenZipHandle(HANDLE h, const char *password) {return OpenZipInternal((void*)h,0,ZIP_HANDLE,password);} -HZIP OpenZip(const TCHAR *fn, const char *password) {return OpenZipInternal((void*)fn,0,ZIP_FILENAME,password);} -HZIP OpenZip(void *z,unsigned int len, const char *password) {return OpenZipInternal(z,len,ZIP_MEMORY,password);} +HZIP OpenZipHandle(HANDLE h, const char* password) { return OpenZipInternal((void*)h, 0, ZIP_HANDLE, password); } +HZIP OpenZip(const TCHAR* fn, const char* password) { return OpenZipInternal((void*)fn, 0, ZIP_FILENAME, password); } +HZIP OpenZip(void* z, unsigned int len, const char* password) { return OpenZipInternal(z, len, ZIP_MEMORY, password); } -ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze) -{ ze->index=0; *ze->name=0; ze->unc_size=0; - if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->Get(index,ze); - return lasterrorU; +ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY* ze) +{ + ze->index = 0; *ze->name = 0; ze->unc_size = 0; + if (hz == 0) { lasterrorU = ZR_ARGS;return ZR_ARGS; } + TUnzipHandleData* han = (TUnzipHandleData*)hz; + if (han->flag != 1) { lasterrorU = ZR_ZMODE;return ZR_ZMODE; } + TUnzip* unz = han->unz; + lasterrorU = unz->Get(index, ze); + return lasterrorU; } -ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze) -{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->Find(name,ic,index,ze); - return lasterrorU; +ZRESULT FindZipItem(HZIP hz, const TCHAR* name, bool ic, int* index, ZIPENTRY* ze) +{ + if (hz == 0) { lasterrorU = ZR_ARGS;return ZR_ARGS; } + TUnzipHandleData* han = (TUnzipHandleData*)hz; + if (han->flag != 1) { lasterrorU = ZR_ZMODE;return ZR_ZMODE; } + TUnzip* unz = han->unz; + lasterrorU = unz->Find(name, ic, index, ze); + return lasterrorU; } -ZRESULT UnzipItemInternal(HZIP hz, int index, void *dst, unsigned int len, DWORD flags) -{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->Unzip(index,dst,len,flags); - return lasterrorU; +ZRESULT UnzipItemInternal(HZIP hz, int index, void* dst, unsigned int len, DWORD flags) +{ + if (hz == 0) { lasterrorU = ZR_ARGS;return ZR_ARGS; } + TUnzipHandleData* han = (TUnzipHandleData*)hz; + if (han->flag != 1) { lasterrorU = ZR_ZMODE;return ZR_ZMODE; } + TUnzip* unz = han->unz; + lasterrorU = unz->Unzip(index, dst, len, flags); + return lasterrorU; } -ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h) {return UnzipItemInternal(hz,index,(void*)h,0,ZIP_HANDLE);} -ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn) {return UnzipItemInternal(hz,index,(void*)fn,0,ZIP_FILENAME);} -ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len) {return UnzipItemInternal(hz,index,z,len,ZIP_MEMORY);} +ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h) { return UnzipItemInternal(hz, index, (void*)h, 0, ZIP_HANDLE); } +ZRESULT UnzipItem(HZIP hz, int index, const TCHAR* fn) { return UnzipItemInternal(hz, index, (void*)fn, 0, ZIP_FILENAME); } +ZRESULT UnzipItem(HZIP hz, int index, void* z, unsigned int len) { return UnzipItemInternal(hz, index, z, len, ZIP_MEMORY); } -ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir) -{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->SetUnzipBaseDir(dir); - return lasterrorU; +ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR* dir) +{ + if (hz == 0) { lasterrorU = ZR_ARGS;return ZR_ARGS; } + TUnzipHandleData* han = (TUnzipHandleData*)hz; + if (han->flag != 1) { lasterrorU = ZR_ZMODE;return ZR_ZMODE; } + TUnzip* unz = han->unz; + lasterrorU = unz->SetUnzipBaseDir(dir); + return lasterrorU; } ZRESULT CloseZipU(HZIP hz) -{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->Close(); - delete unz; - delete han; - return lasterrorU; +{ + if (hz == 0) { lasterrorU = ZR_ARGS;return ZR_ARGS; } + TUnzipHandleData* han = (TUnzipHandleData*)hz; + if (han->flag != 1) { lasterrorU = ZR_ZMODE;return ZR_ZMODE; } + TUnzip* unz = han->unz; + lasterrorU = unz->Close(); + delete unz; + delete han; + return lasterrorU; } bool IsZipHandleU(HZIP hz) -{ if (hz==0) return false; - TUnzipHandleData *han = (TUnzipHandleData*)hz; - return (han->flag==1); +{ + if (hz == 0) return false; + TUnzipHandleData* han = (TUnzipHandleData*)hz; + return (han->flag == 1); } \ No newline at end of file diff --git a/src/Setup/unzip.h b/src/Setup/unzip.h index 7e50e548..25fdf999 100644 --- a/src/Setup/unzip.h +++ b/src/Setup/unzip.h @@ -18,18 +18,19 @@ typedef DWORD ZRESULT; // return codes from any of the zip functions. Listed later. typedef struct -{ int index; // index of this file within the zip - TCHAR name[MAX_PATH]; // filename within the zip - DWORD attr; // attributes, as in GetFileAttributes. - FILETIME atime,ctime,mtime;// access, create, modify filetimes - long comp_size; // sizes of item, compressed and uncompressed. These - long unc_size; // may be -1 if not yet known (e.g. being streamed in) +{ + int index; // index of this file within the zip + TCHAR name[MAX_PATH]; // filename within the zip + DWORD attr; // attributes, as in GetFileAttributes. + FILETIME atime, ctime, mtime;// access, create, modify filetimes + long comp_size; // sizes of item, compressed and uncompressed. These + long unc_size; // may be -1 if not yet known (e.g. being streamed in) } ZIPENTRY; -HZIP OpenZip(const TCHAR *fn, const char *password); -HZIP OpenZip(void *z,unsigned int len, const char *password); -HZIP OpenZipHandle(HANDLE h, const char *password); +HZIP OpenZip(const TCHAR* fn, const char* password); +HZIP OpenZip(void* z, unsigned int len, const char* password); +HZIP OpenZipHandle(HANDLE h, const char* password); // OpenZip - opens a zip file and returns a handle with which you can // subsequently examine its contents. You can open a zip file from: // from a pipe: OpenZipHandle(hpipe_read,0); @@ -46,7 +47,7 @@ HZIP OpenZipHandle(HANDLE h, const char *password); // but for real windows, the zip makes its own copy of your handle, so you // can close yours anytime. -ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze); +ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY* ze); // GetZipItem - call this to get information about an item in the zip. // If index is -1 and the file wasn't opened through a pipe, // then it returns information about the whole zipfile @@ -61,14 +62,14 @@ ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze); // then then comp_size and sometimes unc_size as well may not be known until // after the item has been unzipped. -ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze); +ZRESULT FindZipItem(HZIP hz, const TCHAR* name, bool ic, int* index, ZIPENTRY* ze); // FindZipItem - finds an item by name. ic means 'insensitive to case'. // It returns the index of the item, and returns information about it. // If nothing was found, then index is set to -1 and the function returns // an error code. -ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn); -ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len); +ZRESULT UnzipItem(HZIP hz, int index, const TCHAR* fn); +ZRESULT UnzipItem(HZIP hz, int index, void* z, unsigned int len); ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h); // UnzipItem - given an index to an item, unzips it. You can unzip to: // to a pipe: UnzipItemHandle(hz,i, hpipe_write); @@ -85,7 +86,7 @@ ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h); // If you unzip a directory with ZIP_FILENAME, then the directory gets created. // If you unzip it to a handle or a memory block, then nothing gets created // and it emits 0 bytes. -ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir); +ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR* dir); // if unzipping to a filename, and it's a relative filename, then it will be relative to here. // (defaults to current-directory). @@ -93,7 +94,7 @@ ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir); ZRESULT CloseZip(HZIP hz); // CloseZip - the zip handle must be closed with this function. -unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); +unsigned int FormatZipMessage(ZRESULT code, TCHAR* buf, unsigned int len); // FormatZipMessage - given an error code, formats it as a string. // It returns the length of the error message. If buf/len points // to a real buffer, then it also writes as much as possible into there. @@ -199,7 +200,7 @@ unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); // one or the other of them based on a dynamic choice. If the header file // for only one is present, then we will bind to that particular one. ZRESULT CloseZipU(HZIP hz); -unsigned int FormatZipMessageU(ZRESULT code, TCHAR *buf,unsigned int len); +unsigned int FormatZipMessageU(ZRESULT code, TCHAR* buf, unsigned int len); bool IsZipHandleU(HZIP hz); #ifdef _zip_H #undef CloseZip diff --git a/src/Setup/winmain.cpp b/src/Setup/winmain.cpp index b8135ad3..aae84fea 100644 --- a/src/Setup/winmain.cpp +++ b/src/Setup/winmain.cpp @@ -22,156 +22,146 @@ typedef BOOL(WINAPI* SetDefaultDllDirectoriesFunction)(DWORD DirectoryFlags); // If we pre-load them with an absolute path then we are good. void PreloadLibs() { - wchar_t sys32Folder[MAX_PATH]; - GetSystemDirectory(sys32Folder, MAX_PATH); + wchar_t sys32Folder[MAX_PATH]; + GetSystemDirectory(sys32Folder, MAX_PATH); - std::wstring version = (std::wstring(sys32Folder) + L"\\version.dll"); - std::wstring logoncli = (std::wstring(sys32Folder) + L"\\logoncli.dll"); - std::wstring sspicli = (std::wstring(sys32Folder) + L"\\sspicli.dll"); + std::wstring version = (std::wstring(sys32Folder) + L"\\version.dll"); + std::wstring logoncli = (std::wstring(sys32Folder) + L"\\logoncli.dll"); + std::wstring sspicli = (std::wstring(sys32Folder) + L"\\sspicli.dll"); - LoadLibrary(version.c_str()); - LoadLibrary(logoncli.c_str()); - LoadLibrary(sspicli.c_str()); + LoadLibrary(version.c_str()); + LoadLibrary(logoncli.c_str()); + LoadLibrary(sspicli.c_str()); } void MitigateDllHijacking() { - // Set the default DLL lookup directory to System32 for ourselves and kernel32.dll - SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); + // Set the default DLL lookup directory to System32 for ourselves and kernel32.dll + SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32); - HMODULE hKernel32 = LoadLibrary(L"kernel32.dll"); - ATLASSERT(hKernel32 != NULL); + HMODULE hKernel32 = LoadLibrary(L"kernel32.dll"); + ATLASSERT(hKernel32 != NULL); - SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction)GetProcAddress(hKernel32, "SetDefaultDllDirectories"); - if (pfn) { (*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32); } + SetDefaultDllDirectoriesFunction pfn = (SetDefaultDllDirectoriesFunction)GetProcAddress(hKernel32, "SetDefaultDllDirectories"); + if (pfn) { (*pfn)(LOAD_LIBRARY_SEARCH_SYSTEM32); } - PreloadLibs(); + PreloadLibs(); } int APIENTRY wWinMain( - _In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPWSTR lpCmdLine, - _In_ int nCmdShow) + _In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) { - MitigateDllHijacking(); + MitigateDllHijacking(); - int exitCode = -1; - CString cmdLine(lpCmdLine); + int exitCode = -1; + CString cmdLine(lpCmdLine); - // see if the requested framework(s) are supported and exit. - int chkFrameworkIdx = cmdLine.Find(L"--checkFramework"); - if (chkFrameworkIdx >= 0) { - return VerifyRuntimeString(std::wstring(cmdLine).substr(chkFrameworkIdx + 17)); - } + // see if the requested framework(s) are supported and exit. + int chkFrameworkIdx = cmdLine.Find(L"--checkFramework"); + if (chkFrameworkIdx >= 0) + return VerifyRuntimeString(std::wstring(cmdLine).substr(chkFrameworkIdx + 17)); - if (cmdLine.Find(L"--checkInstall") >= 0) { - // If we're already installed, exit as fast as possible - if (!MachineInstaller::ShouldSilentInstall()) { - return 0; - } + if (cmdLine.Find(L"--checkInstall") >= 0) { + // If we're already installed, exit as fast as possible + if (!MachineInstaller::ShouldSilentInstall()) + return 0; - // Make sure update.exe gets silent - wcscat(lpCmdLine, L" --silent"); - } + // Make sure update.exe gets silent + wcscat(lpCmdLine, L" --silent"); + } - // Initialize COM - HRESULT hr = ::CoInitialize(NULL); - ATLASSERT(SUCCEEDED(hr)); - AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); + // Initialize COM + HRESULT hr = ::CoInitialize(NULL); + ATLASSERT(SUCCEEDED(hr)); + AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); - // Initialize ATL - _Module = new CAppModule(); - hr = _Module->Init(NULL, hInstance); + // Initialize ATL + _Module = new CAppModule(); + hr = _Module->Init(NULL, hInstance); - // Initialize GDI - ULONG_PTR gdiplusToken; - Gdiplus::GdiplusStartupInput gdiplusStartupInput; - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); - CSplashWnd splash; + // Initialize GDI + ULONG_PTR gdiplusToken; + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + CSplashWnd splash; std::function closeSplashFn([&]() { splash.Hide(); }); - bool isQuiet = (cmdLine.Find(L"-s") >= 0); - bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK; - bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0); + bool isQuiet = (cmdLine.Find(L"-s") >= 0); + bool weAreUACElevated = CUpdateRunner::AreWeUACElevated() == S_OK; + bool attemptingToRerun = (cmdLine.Find(L"--rerunningWithoutUAC") >= 0); - // todo: make min windows version configurable (eg, > windows 10 18362) - auto runtimes = GetRequiredRuntimes(); + // todo: make min windows version configurable (eg, > windows 10 18362) + auto runtimes = GetRequiredRuntimes(); - if (weAreUACElevated && attemptingToRerun) { - CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL); - exitCode = E_FAIL; - goto out; - } + if (weAreUACElevated && attemptingToRerun) { + CUpdateRunner::DisplayErrorMessage(CString(L"Please re-run this installer as a normal user instead of \"Run as Administrator\"."), NULL); + exitCode = E_FAIL; + goto out; + } - bool rebootRequired = false; + bool rebootRequired = false; - // check all required runtimes against the current operating system version - for (auto rt : runtimes) - { - if (!IsRuntimeSupported(rt)) - { - // Explain this as nicely as possible and give up. - MessageBox(0L, L"This program cannot run on this computer; it requires a later version of Windows.", L"Incompatible Operating System", 0); - exitCode = E_FAIL; - goto out; - } - } + // check all required runtimes against the current operating system version + for (auto rt : runtimes) { + if (!IsRuntimeSupported(rt)) { + // Explain this as nicely as possible and give up. + MessageBox(0L, L"This program cannot run on this computer; it requires a later version of Windows.", L"Incompatible Operating System", 0); + exitCode = E_FAIL; + goto out; + } + } - // install any missing runtimes - for (auto rt : runtimes) - { - if (!IsRuntimeInstalled(rt)) - { - HRESULT hr = CFxHelper::InstallDotnet(rt, isQuiet); - if (hr == ERROR_SUCCESS_REBOOT_REQUIRED) - { - // we will reboot after installing all required runtimes. - rebootRequired = true; - } - else if (FAILED(hr)) - { - exitCode = hr; // #yolo - CUpdateRunner::DisplayErrorMessage(CString(L"Failed to install .NET, you can try installing it manually."), NULL); - goto out; - } - // S_FALSE isn't failure, but we still shouldn't try to install - else if (hr != S_OK) - { - exitCode = 0; - goto out; - } - } - } + // install any missing runtimes + for (auto rt : runtimes) { + if (!IsRuntimeInstalled(rt)) { + HRESULT hr = CFxHelper::InstallDotnet(rt, isQuiet); + if (hr == ERROR_SUCCESS_REBOOT_REQUIRED) { + // we will reboot after installing all required runtimes. + rebootRequired = true; + } + else if (FAILED(hr)) { + exitCode = hr; // #yolo + CUpdateRunner::DisplayErrorMessage(CString(L"Failed to install .NET, you can try installing it manually."), NULL); + goto out; + } + // S_FALSE isn't failure, but we still shouldn't try to install + else if (hr != S_OK) { + exitCode = 0; + goto out; + } + } + } - // if any runtimes indicated a reboot is required, let's do that now - if (rebootRequired) - { - exitCode = CFxHelper::HandleRebootRequirement(isQuiet); - goto out; - } + // if any runtimes indicated a reboot is required, let's do that now + if (rebootRequired) { + exitCode = CFxHelper::HandleRebootRequirement(isQuiet); + goto out; + } - // If we're UAC-elevated, we shouldn't be because it will give us permissions - // problems later. Just silently rerun ourselves. - if (weAreUACElevated) { - wchar_t buf[4096]; - HMODULE hMod = GetModuleHandle(NULL); - GetModuleFileNameW(hMod, buf, 4096); - wcscat(lpCmdLine, L" --rerunningWithoutUAC"); + // If we're UAC-elevated, we shouldn't be because it will give us permissions + // problems later. Just silently rerun ourselves. + if (weAreUACElevated) { + wchar_t buf[4096]; + HMODULE hMod = GetModuleHandle(NULL); + GetModuleFileNameW(hMod, buf, 4096); + wcscat(lpCmdLine, L" --rerunningWithoutUAC"); - CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine); - exitCode = 0; - goto out; - } + CUpdateRunner::ShellExecuteFromExplorer(buf, lpCmdLine); + exitCode = 0; + goto out; + } - splash.SetImage(MAKEINTRESOURCE(IDR_SPLASH_IMG), L"DATA"); - splash.Show(); + splash.SetImage(MAKEINTRESOURCE(IDR_SPLASH_IMG), L"DATA"); + splash.Show(); - // run updater - exitCode = CUpdateRunner::ExtractUpdaterAndRun(lpCmdLine, false, closeSplashFn); + // run updater + exitCode = CUpdateRunner::ExtractUpdaterAndRun(lpCmdLine, false, closeSplashFn); out: - splash.Hide(); - _Module->Term(); - return exitCode; + splash.Hide(); + _Module->Term(); + return exitCode; } diff --git a/src/StubExecutable/Semver200_comparator.cpp b/src/StubExecutable/Semver200_comparator.cpp index bd5e5700..769f4f04 100644 --- a/src/StubExecutable/Semver200_comparator.cpp +++ b/src/StubExecutable/Semver200_comparator.cpp @@ -31,82 +31,91 @@ SOFTWARE. using namespace std; -namespace version { +namespace version +{ - namespace { + namespace + { - // Compare normal version identifiers. - int compare_normal(const Version_data& l, const Version_data& r) { - if (l.major > r.major) return 1; - if (l.major < r.major) return -1; - if (l.minor > r.minor) return 1; - if (l.minor < r.minor) return -1; - if (l.patch > r.patch) return 1; - if (l.patch < r.patch) return -1; - return 0; - } + // Compare normal version identifiers. + int compare_normal(const Version_data& l, const Version_data& r) + { + if (l.major > r.major) return 1; + if (l.major < r.major) return -1; + if (l.minor > r.minor) return 1; + if (l.minor < r.minor) return -1; + if (l.patch > r.patch) return 1; + if (l.patch < r.patch) return -1; + return 0; + } - // Compare alphanumeric prerelease identifiers. - inline int cmp_alnum_prerel_ids(const string& l, const string& r) { - auto cmp = l.compare(r); - if (cmp == 0) { - return cmp; - } else { - return cmp > 0 ? 1 : -1; - } - } + // Compare alphanumeric prerelease identifiers. + inline int cmp_alnum_prerel_ids(const string& l, const string& r) + { + auto cmp = l.compare(r); + if (cmp == 0) { + return cmp; + } + else { + return cmp > 0 ? 1 : -1; + } + } - // Compare numeric prerelease identifiers. - inline int cmp_num_prerel_ids(const string& l, const string& r) { - long long li = stoll(l); - long long ri = stoll(r); - if (li == ri) return 0; - return li > ri ? 1 : -1; - } + // Compare numeric prerelease identifiers. + inline int cmp_num_prerel_ids(const string& l, const string& r) + { + long long li = stoll(l); + long long ri = stoll(r); + if (li == ri) return 0; + return li > ri ? 1 : -1; + } - using Prerel_type_pair = pair; - using Prerel_id_comparator = function; - const map comparators = { - { { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids }, - { { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} }, - { { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} }, - { { Id_type::num, Id_type::num }, cmp_num_prerel_ids } - }; + using Prerel_type_pair = pair; + using Prerel_id_comparator = function; + const map comparators = { + { { Id_type::alnum, Id_type::alnum }, cmp_alnum_prerel_ids }, + { { Id_type::alnum, Id_type::num }, [](const string&, const string&) {return 1;} }, + { { Id_type::num, Id_type::alnum }, [](const string&, const string&) {return -1;} }, + { { Id_type::num, Id_type::num }, cmp_num_prerel_ids } + }; - // Compare prerelease identifiers based on their types. - inline int compare_prerel_identifiers(const Prerelease_identifier& l, const Prerelease_identifier& r) { - auto cmp = comparators.at({ l.second, r.second }); - return cmp(l.first, r.first); - } + // Compare prerelease identifiers based on their types. + inline int compare_prerel_identifiers(const Prerelease_identifier& l, const Prerelease_identifier& r) + { + auto cmp = comparators.at({ l.second, r.second }); + return cmp(l.first, r.first); + } - inline int cmp_rel_prerel(const Prerelease_identifiers& l, const Prerelease_identifiers& r) { - if (l.empty() && !r.empty()) return 1; - if (r.empty() && !l.empty()) return -1; - return 0; - } - } + inline int cmp_rel_prerel(const Prerelease_identifiers& l, const Prerelease_identifiers& r) + { + if (l.empty() && !r.empty()) return 1; + if (r.empty() && !l.empty()) return -1; + return 0; + } + } - int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const { - // Compare normal version components. - int cmp = compare_normal(l, r); - if (cmp != 0) return cmp; + int Semver200_comparator::compare(const Version_data& l, const Version_data& r) const + { + // Compare normal version components. + int cmp = compare_normal(l, r); + if (cmp != 0) return cmp; - // Compare if one version is release and the other prerelease - release is always higher. - cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids); - if (cmp != 0) return cmp; + // Compare if one version is release and the other prerelease - release is always higher. + cmp = cmp_rel_prerel(l.prerelease_ids, r.prerelease_ids); + if (cmp != 0) return cmp; - // Compare prerelease by looking at each identifier: numeric ones are compared as numbers, - // alphanum as ASCII strings. - auto shorter = min(l.prerelease_ids.size(), r.prerelease_ids.size()); - for (size_t i = 0; i < shorter; i++) { - cmp = compare_prerel_identifiers(l.prerelease_ids[i], r.prerelease_ids[i]); - if (cmp != 0) return cmp; - } + // Compare prerelease by looking at each identifier: numeric ones are compared as numbers, + // alphanum as ASCII strings. + auto shorter = min(l.prerelease_ids.size(), r.prerelease_ids.size()); + for (size_t i = 0; i < shorter; i++) { + cmp = compare_prerel_identifiers(l.prerelease_ids[i], r.prerelease_ids[i]); + if (cmp != 0) return cmp; + } - // Prerelease identifiers are the same, to the length of the shorter version string; - // if they are the same length, then versions are equal, otherwise, longer one wins. - if (l.prerelease_ids.size() == r.prerelease_ids.size()) return 0; - return l.prerelease_ids.size() > r.prerelease_ids.size() ? 1 : -1; - } + // Prerelease identifiers are the same, to the length of the shorter version string; + // if they are the same length, then versions are equal, otherwise, longer one wins. + if (l.prerelease_ids.size() == r.prerelease_ids.size()) return 0; + return l.prerelease_ids.size() > r.prerelease_ids.size() ? 1 : -1; + } } diff --git a/src/StubExecutable/Semver200_parser.cpp b/src/StubExecutable/Semver200_parser.cpp index abacc9a0..9cfa75ca 100644 --- a/src/StubExecutable/Semver200_parser.cpp +++ b/src/StubExecutable/Semver200_parser.cpp @@ -35,176 +35,190 @@ SOFTWARE. using namespace std; -namespace version { +namespace version +{ - namespace { - enum class Parser_state { - major, minor, patch, prerelease, build - }; + namespace + { + enum class Parser_state + { + major, minor, patch, prerelease, build + }; - using Validator = function; - using State_transition_hook = function; - /// State transition is described by a character that triggers it, a state to transition to and - /// optional hook to be invoked on transition. - using Transition = tuple; - using Transitions = vector; - using State = tuple; - using State_machine = map; + using Validator = function; + using State_transition_hook = function; + /// State transition is described by a character that triggers it, a state to transition to and + /// optional hook to be invoked on transition. + using Transition = tuple; + using Transitions = vector; + using State = tuple; + using State_machine = map; - // Ranges of characters allowed in prerelease and build identifiers. - const vector> allowed_prerel_id_chars = { - { '0', '9' },{ 'A','Z' },{ 'a','z' },{ '-','-' } - }; + // Ranges of characters allowed in prerelease and build identifiers. + const vector> allowed_prerel_id_chars = { + { '0', '9' },{ 'A','Z' },{ 'a','z' },{ '-','-' } + }; - inline Transition mkx(const char c, Parser_state p, State_transition_hook pth) { - return make_tuple(c, p, pth); - } + inline Transition mkx(const char c, Parser_state p, State_transition_hook pth) + { + return make_tuple(c, p, pth); + } - /// Advance parser state machine by a single step. - /** - Perform single step of parser state machine: if character matches one from transition tables - - trigger transition to next state; otherwise, validate if current token is in legal state - (throw Parse_error if not) and then add character to current token; State transition includes - preparing various vars for next state and invoking state transition hook (if specified) which is - where whole tokens are validated. - */ - inline void process_char(const char c, Parser_state& cstate, Parser_state& pstate, - const Transitions& transitions, string& target, Validator validate) { - for (const auto& transition : transitions) { - if (c == get<0>(transition)) { - if (get<2>(transition)) get<2>(transition)(target); - pstate = cstate; - cstate = get<1>(transition); - return; - } - } - validate(target, c); - target.push_back(c); - } + /// Advance parser state machine by a single step. + /** + Perform single step of parser state machine: if character matches one from transition tables - + trigger transition to next state; otherwise, validate if current token is in legal state + (throw Parse_error if not) and then add character to current token; State transition includes + preparing various vars for next state and invoking state transition hook (if specified) which is + where whole tokens are validated. + */ + inline void process_char(const char c, Parser_state& cstate, Parser_state& pstate, + const Transitions& transitions, string& target, Validator validate) + { + for (const auto& transition : transitions) { + if (c == get<0>(transition)) { + if (get<2>(transition)) get<2>(transition)(target); + pstate = cstate; + cstate = get<1>(transition); + return; + } + } + validate(target, c); + target.push_back(c); + } - /// Validate normal (major, minor, patch) version components. - inline void normal_version_validator(const string& tgt, const char c) { - if (c < '0' || c > '9') throw Parse_error("invalid character encountered: " + string(1, c)); - if (tgt.compare(0, 1, "0") == 0) throw Parse_error("leading 0 not allowed"); - } + /// Validate normal (major, minor, patch) version components. + inline void normal_version_validator(const string& tgt, const char c) + { + if (c < '0' || c > '9') throw Parse_error("invalid character encountered: " + string(1, c)); + if (tgt.compare(0, 1, "0") == 0) throw Parse_error("leading 0 not allowed"); + } - /// Validate that prerelease and build version identifiers are comprised of allowed chars only. - inline void prerelease_version_validator(const string&, const char c) { - bool res = false; - for (const auto& r : allowed_prerel_id_chars) { - res |= (c >= r.first && c <= r.second); - } - if (!res) - throw Parse_error("invalid character encountered: " + string(1, c)); - } + /// Validate that prerelease and build version identifiers are comprised of allowed chars only. + inline void prerelease_version_validator(const string&, const char c) + { + bool res = false; + for (const auto& r : allowed_prerel_id_chars) { + res |= (c >= r.first && c <= r.second); + } + if (!res) + throw Parse_error("invalid character encountered: " + string(1, c)); + } - inline bool is_identifier_numeric(const string& id) { - return id.find_first_not_of("0123456789") == string::npos; - } + inline bool is_identifier_numeric(const string& id) + { + return id.find_first_not_of("0123456789") == string::npos; + } - inline bool check_for_leading_0(const string& str) { - return str.length() > 1 && str[0] == '0'; - } + inline bool check_for_leading_0(const string& str) + { + return str.length() > 1 && str[0] == '0'; + } - /// Validate every individual prerelease identifier, determine it's type and add it to collection. - void prerelease_hook_impl(string& id, Prerelease_identifiers& prerelease) { - if (id.empty()) throw Parse_error("version identifier cannot be empty"); - Id_type t = Id_type::alnum; - if (is_identifier_numeric(id)) { - t = Id_type::num; - if (check_for_leading_0(id)) { - throw Parse_error("numeric identifiers cannot have leading 0"); - } - } - prerelease.push_back(Prerelease_identifier(id, t)); - id.clear(); - } + /// Validate every individual prerelease identifier, determine it's type and add it to collection. + void prerelease_hook_impl(string& id, Prerelease_identifiers& prerelease) + { + if (id.empty()) throw Parse_error("version identifier cannot be empty"); + Id_type t = Id_type::alnum; + if (is_identifier_numeric(id)) { + t = Id_type::num; + if (check_for_leading_0(id)) { + throw Parse_error("numeric identifiers cannot have leading 0"); + } + } + prerelease.push_back(Prerelease_identifier(id, t)); + id.clear(); + } - /// Validate every individual build identifier and add it to collection. - void build_hook_impl(string& id, Parser_state& pstate, Build_identifiers& build, - std::string& prerelease_id, Prerelease_identifiers& prerelease) { - // process last token left from parsing prerelease data - if (pstate == Parser_state::prerelease) prerelease_hook_impl(prerelease_id, prerelease); - if (id.empty()) throw Parse_error("version identifier cannot be empty"); - build.push_back(id); - id.clear(); - } + /// Validate every individual build identifier and add it to collection. + void build_hook_impl(string& id, Parser_state& pstate, Build_identifiers& build, + std::string& prerelease_id, Prerelease_identifiers& prerelease) + { + // process last token left from parsing prerelease data + if (pstate == Parser_state::prerelease) prerelease_hook_impl(prerelease_id, prerelease); + if (id.empty()) throw Parse_error("version identifier cannot be empty"); + build.push_back(id); + id.clear(); + } - } + } - /// Parse semver 2.0.0-compatible string to Version_data structure. - /** - Version text parser is implemented as a state machine. In each step one successive character from version - string is consumed and is either added to current token or triggers state transition. Hooks can be - injected into state transitions for validation/customization purposes. - */ - Version_data Semver200_parser::parse(const string& s) const { - string major; - string minor; - string patch; - string prerelease_id; - string build_id; - Prerelease_identifiers prerelease; - Build_identifiers build; - Parser_state cstate{ Parser_state::major }; - Parser_state pstate; + /// Parse semver 2.0.0-compatible string to Version_data structure. + /** + Version text parser is implemented as a state machine. In each step one successive character from version + string is consumed and is either added to current token or triggers state transition. Hooks can be + injected into state transitions for validation/customization purposes. + */ + Version_data Semver200_parser::parse(const string& s) const + { + string major; + string minor; + string patch; + string prerelease_id; + string build_id; + Prerelease_identifiers prerelease; + Build_identifiers build; + Parser_state cstate{ Parser_state::major }; + Parser_state pstate; - auto prerelease_hook = [&](string& id) { - prerelease_hook_impl(id, prerelease); - }; + auto prerelease_hook = [&](string& id) { + prerelease_hook_impl(id, prerelease); + }; - auto build_hook = [&](string& id) { - build_hook_impl(id, pstate, build, prerelease_id, prerelease); - }; + auto build_hook = [&](string& id) { + build_hook_impl(id, pstate, build, prerelease_id, prerelease); + }; - // State transition tables - auto major_trans = { - mkx('.', Parser_state::minor, {}) - }; - auto minor_trans = { - mkx('.', Parser_state::patch, {}) - }; - auto patch_trans = { - mkx('-', Parser_state::prerelease, {}), - mkx('+', Parser_state::build, {}) - }; - auto prerelease_trans = { - // When identifier separator (.) is found, stay in the same state but invoke hook - // in order to process each individual identifier separately. - mkx('.', Parser_state::prerelease, prerelease_hook), - mkx('+', Parser_state::build, {}) - }; - auto build_trans = { - // Same stay-in-the-same-state-but-invoke-hook trick from above. - mkx('.', Parser_state::build, build_hook) - }; + // State transition tables + auto major_trans = { + mkx('.', Parser_state::minor, {}) + }; + auto minor_trans = { + mkx('.', Parser_state::patch, {}) + }; + auto patch_trans = { + mkx('-', Parser_state::prerelease, {}), + mkx('+', Parser_state::build, {}) + }; + auto prerelease_trans = { + // When identifier separator (.) is found, stay in the same state but invoke hook + // in order to process each individual identifier separately. + mkx('.', Parser_state::prerelease, prerelease_hook), + mkx('+', Parser_state::build, {}) + }; + auto build_trans = { + // Same stay-in-the-same-state-but-invoke-hook trick from above. + mkx('.', Parser_state::build, build_hook) + }; - State_machine state_machine = { - {Parser_state::major, State{major_trans, major, normal_version_validator}}, - {Parser_state::minor, State{minor_trans, minor, normal_version_validator}}, - {Parser_state::patch, State{patch_trans, patch, normal_version_validator}}, - {Parser_state::prerelease, State{prerelease_trans, prerelease_id, prerelease_version_validator}}, - {Parser_state::build, State{build_trans, build_id, prerelease_version_validator}} - }; + State_machine state_machine = { + {Parser_state::major, State{major_trans, major, normal_version_validator}}, + {Parser_state::minor, State{minor_trans, minor, normal_version_validator}}, + {Parser_state::patch, State{patch_trans, patch, normal_version_validator}}, + {Parser_state::prerelease, State{prerelease_trans, prerelease_id, prerelease_version_validator}}, + {Parser_state::build, State{build_trans, build_id, prerelease_version_validator}} + }; - // Main loop. - for (const auto& c : s) { - auto state = state_machine.at(cstate); - process_char(c, cstate, pstate, get<0>(state), get<1>(state), get<2>(state)); - } + // Main loop. + for (const auto& c : s) { + auto state = state_machine.at(cstate); + process_char(c, cstate, pstate, get<0>(state), get<1>(state), get<2>(state)); + } - // Trigger appropriate hooks in order to process last token, because no state transition was - // triggered for it. - if (cstate == Parser_state::prerelease) { - prerelease_hook(prerelease_id); - } else if (cstate == Parser_state::build) { - build_hook(build_id); - } + // Trigger appropriate hooks in order to process last token, because no state transition was + // triggered for it. + if (cstate == Parser_state::prerelease) { + prerelease_hook(prerelease_id); + } + else if (cstate == Parser_state::build) { + build_hook(build_id); + } - try { - return Version_data{ stoi(major), stoi(minor), stoi(patch), prerelease, build }; - } catch (invalid_argument& ex) { - throw Parse_error(ex.what()); - } - } + try { + return Version_data{ stoi(major), stoi(minor), stoi(patch), prerelease, build }; + } + catch (invalid_argument& ex) { + throw Parse_error(ex.what()); + } + } } diff --git a/src/StubExecutable/StubExecutable.cpp b/src/StubExecutable/StubExecutable.cpp index 6299dec5..e5393b93 100644 --- a/src/StubExecutable/StubExecutable.cpp +++ b/src/StubExecutable/StubExecutable.cpp @@ -8,81 +8,81 @@ using namespace std; -wchar_t* FindRootAppDir() +wchar_t* FindRootAppDir() { - wchar_t* ourDirectory = new wchar_t[MAX_PATH]; + wchar_t* ourDirectory = new wchar_t[MAX_PATH]; - GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH); - wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\'); - if (!lastSlash) { - delete[] ourDirectory; - return NULL; - } + GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH); + wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\'); + if (!lastSlash) { + delete[] ourDirectory; + return NULL; + } - // Null-terminate the string at the slash so now it's a directory - *lastSlash = 0x0; - return ourDirectory; + // Null-terminate the string at the slash so now it's a directory + *lastSlash = 0x0; + return ourDirectory; } -wchar_t* FindOwnExecutableName() +wchar_t* FindOwnExecutableName() { - wchar_t* ourDirectory = new wchar_t[MAX_PATH]; + wchar_t* ourDirectory = new wchar_t[MAX_PATH]; - GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH); - wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\'); - if (!lastSlash) { - delete[] ourDirectory; - return NULL; - } + GetModuleFileName(GetModuleHandle(NULL), ourDirectory, MAX_PATH); + wchar_t* lastSlash = wcsrchr(ourDirectory, L'\\'); + if (!lastSlash) { + delete[] ourDirectory; + return NULL; + } - wchar_t* ret = _wcsdup(lastSlash + 1); - delete[] ourDirectory; - return ret; + wchar_t* ret = _wcsdup(lastSlash + 1); + delete[] ourDirectory; + return ret; } -std::wstring FindLatestAppDir() +std::wstring FindLatestAppDir() { - std::wstring ourDir; - ourDir.assign(FindRootAppDir()); + std::wstring ourDir; + ourDir.assign(FindRootAppDir()); - ourDir += L"\\app-*"; + ourDir += L"\\app-*"; - WIN32_FIND_DATA fileInfo = { 0 }; - HANDLE hFile = FindFirstFile(ourDir.c_str(), &fileInfo); - if (hFile == INVALID_HANDLE_VALUE) { - return NULL; - } + WIN32_FIND_DATA fileInfo = { 0 }; + HANDLE hFile = FindFirstFile(ourDir.c_str(), &fileInfo); + if (hFile == INVALID_HANDLE_VALUE) { + return NULL; + } - version::Semver200_version acc("0.0.0"); - std::wstring acc_s; + version::Semver200_version acc("0.0.0"); + std::wstring acc_s; - do { - std::wstring appVer = fileInfo.cFileName; - appVer = appVer.substr(4); // Skip 'app-' - if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - continue; - } + do { + std::wstring appVer = fileInfo.cFileName; + appVer = appVer.substr(4); // Skip 'app-' + if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + continue; + } - std::string s(appVer.begin(), appVer.end()); + std::string s(appVer.begin(), appVer.end()); - version::Semver200_version thisVer(s); + version::Semver200_version thisVer(s); - if (thisVer > acc) { - acc = thisVer; - acc_s = appVer; - } - } while (FindNextFile(hFile, &fileInfo)); + if (thisVer > acc) { + acc = thisVer; + acc_s = appVer; + } + } while (FindNextFile(hFile, &fileInfo)); - if (acc == version::Semver200_version("0.0.0")) { - return NULL; - } + if (acc == version::Semver200_version("0.0.0")) { + return NULL; + } - ourDir.assign(FindRootAppDir()); - std::wstringstream ret; - ret << ourDir << L"\\app-" << acc_s; + ourDir.assign(FindRootAppDir()); + std::wstringstream ret; + ret << ourDir << L"\\app-" << acc_s; - FindClose(hFile); - return ret.str(); + FindClose(hFile); + return ret.str(); } int APIENTRY wWinMain(_In_ HINSTANCE hInstance, @@ -90,31 +90,31 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { - std::wstring appName; - appName.assign(FindOwnExecutableName()); + std::wstring appName; + appName.assign(FindOwnExecutableName()); - std::wstring workingDir(FindLatestAppDir()); - std::wstring fullPath(workingDir + L"\\" + appName); + std::wstring workingDir(FindLatestAppDir()); + std::wstring fullPath(workingDir + L"\\" + appName); - STARTUPINFO si = { 0 }; - PROCESS_INFORMATION pi = { 0 }; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; - si.cb = sizeof(si); - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = nCmdShow; + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = nCmdShow; - std::wstring cmdLine(L"\""); - cmdLine += fullPath; - cmdLine += L"\" "; - cmdLine += lpCmdLine; + std::wstring cmdLine(L"\""); + cmdLine += fullPath; + cmdLine += L"\" "; + cmdLine += lpCmdLine; - wchar_t* lpCommandLine = _wcsdup(cmdLine.c_str()); - wchar_t* lpCurrentDirectory = _wcsdup(workingDir.c_str()); - if (!CreateProcess(NULL, lpCommandLine, NULL, NULL, true, 0, NULL, lpCurrentDirectory, &si, &pi)) { - return -1; - } + wchar_t* lpCommandLine = _wcsdup(cmdLine.c_str()); + wchar_t* lpCurrentDirectory = _wcsdup(workingDir.c_str()); + if (!CreateProcess(NULL, lpCommandLine, NULL, NULL, true, 0, NULL, lpCurrentDirectory, &si, &pi)) { + return -1; + } - AllowSetForegroundWindow(pi.dwProcessId); - WaitForInputIdle(pi.hProcess, 5 * 1000); - return 0; + AllowSetForegroundWindow(pi.dwProcessId); + WaitForInputIdle(pi.hProcess, 5 * 1000); + return 0; } diff --git a/src/StubExecutable/semver200.h b/src/StubExecutable/semver200.h index 7f5bbc4b..d217c1ff 100644 --- a/src/StubExecutable/semver200.h +++ b/src/StubExecutable/semver200.h @@ -26,26 +26,32 @@ SOFTWARE. #include "version.h" -namespace version { +namespace version +{ - /// Parse string into Version_data structure according to semantic versioning 2.0.0 rules. - struct Semver200_parser { - Version_data parse(const std::string&) const; - }; + /// Parse string into Version_data structure according to semantic versioning 2.0.0 rules. + struct Semver200_parser + { + Version_data parse(const std::string&) const; + }; - /// Compare Version_data to another using semantic versioning 2.0.0 rules. - struct Semver200_comparator { - int compare(const Version_data&, const Version_data&) const; - }; + /// Compare Version_data to another using semantic versioning 2.0.0 rules. + struct Semver200_comparator + { + int compare(const Version_data&, const Version_data&) const; + }; - /// Concrete version class that binds all semver 2.0.0 functionality together. - class Semver200_version : public Basic_version { - public: - Semver200_version() - : Basic_version{ Semver200_parser(), Semver200_comparator() } {} + /// Concrete version class that binds all semver 2.0.0 functionality together. + class Semver200_version : public Basic_version + { + public: + Semver200_version() + : Basic_version{ Semver200_parser(), Semver200_comparator() } + {} - Semver200_version(const std::string& v) - : Basic_version{ v, Semver200_parser(), Semver200_comparator() } {} - }; + Semver200_version(const std::string& v) + : Basic_version{ v, Semver200_parser(), Semver200_comparator() } + {} + }; } \ No newline at end of file diff --git a/src/StubExecutable/version.h b/src/StubExecutable/version.h index 58e26134..a06875a2 100644 --- a/src/StubExecutable/version.h +++ b/src/StubExecutable/version.h @@ -28,129 +28,134 @@ SOFTWARE. #include #include -namespace version { +namespace version +{ - /// Any error in parsing or validation of version string will result in Parse_error exception being thrown. - class Parse_error : public std::runtime_error { - using std::runtime_error::runtime_error; - }; + /// Any error in parsing or validation of version string will result in Parse_error exception being thrown. + class Parse_error : public std::runtime_error + { + using std::runtime_error::runtime_error; + }; - /// Type of prerelease identifier: alphanumeric or numeric. - /** - Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while - numeric identifiers are compared as numbers. - */ - enum class Id_type { - alnum, ///< Identifier is alphanumerical - num ///< Identifier is numeric - }; + /// Type of prerelease identifier: alphanumeric or numeric. + /** + Type of identifier affects comparison: alphanumeric identifiers are compared as ASCII strings, while + numeric identifiers are compared as numbers. + */ + enum class Id_type + { + alnum, ///< Identifier is alphanumerical + num ///< Identifier is numeric + }; - /// Container for prerelease identifier value and it's type. - /** - Prerelease version string consist of an optional series of dot-separated identifiers. - These identifiers can be either numerical or alphanumerical. - This structure describes one such identifier. - */ - using Prerelease_identifier = std::pair; + /// Container for prerelease identifier value and it's type. + /** + Prerelease version string consist of an optional series of dot-separated identifiers. + These identifiers can be either numerical or alphanumerical. + This structure describes one such identifier. + */ + using Prerelease_identifier = std::pair; - /// Container for all prerelease identifiers for a given version string. - using Prerelease_identifiers = std::vector; + /// Container for all prerelease identifiers for a given version string. + using Prerelease_identifiers = std::vector; - /// Build identifier is arbitrary string with no special meaning with regards to version precedence. - using Build_identifier = std::string; + /// Build identifier is arbitrary string with no special meaning with regards to version precedence. + using Build_identifier = std::string; - /// Container for all build identifiers of a given version string. - using Build_identifiers = std::vector; + /// Container for all build identifiers of a given version string. + using Build_identifiers = std::vector; - /// Description of version broken into parts, as per semantic versioning specification. - struct Version_data { - int major; ///< Major version, change only on incompatible API modifications. - int minor; ///< Minor version, change on backwards-compatible API modifications. - int patch; ///< Patch version, change only on bugfixes. + /// Description of version broken into parts, as per semantic versioning specification. + struct Version_data + { + int major; ///< Major version, change only on incompatible API modifications. + int minor; ///< Minor version, change on backwards-compatible API modifications. + int patch; ///< Patch version, change only on bugfixes. - /// Optional series of prerelease identifiers. - Prerelease_identifiers prerelease_ids; + /// Optional series of prerelease identifiers. + Prerelease_identifiers prerelease_ids; - /// Optional series of build identifiers. - Build_identifiers build_ids; - }; + /// Optional series of build identifiers. + Build_identifiers build_ids; + }; - // Forward declaration required for operators' template declarations. - template - class Basic_version; + // Forward declaration required for operators' template declarations. + template + class Basic_version; - /// Test if left-hand version operand is of lower precedence than the right-hand version. - template - bool operator<(const Basic_version&, - const Basic_version&); + /// Test if left-hand version operand is of lower precedence than the right-hand version. + template + bool operator<(const Basic_version&, + const Basic_version&); - /// Test if left-hand version operand if of equal precedence as the right-hand version. - template - bool operator==(const Basic_version&, - const Basic_version&); + /// Test if left-hand version operand if of equal precedence as the right-hand version. + template + bool operator==(const Basic_version&, + const Basic_version&); - /// Output version object to stream using standard semver format (X.Y.Z-PR+B). - template - std::ostream& operator<<(std::ostream&, - const Basic_version&); + /// Output version object to stream using standard semver format (X.Y.Z-PR+B). + template + std::ostream& operator<<(std::ostream&, + const Basic_version&); - /// Test if left-hand version and right-hand version are of different precedence. - template - bool operator!=(const Basic_version&, - const Basic_version&); + /// Test if left-hand version and right-hand version are of different precedence. + template + bool operator!=(const Basic_version&, + const Basic_version&); - /// Test if left-hand version operand is of higher precedence than the right-hand version. - template - bool operator>(const Basic_version&, - const Basic_version&); + /// Test if left-hand version operand is of higher precedence than the right-hand version. + template + bool operator>(const Basic_version&, + const Basic_version&); - /// Test if left-hand version operand is of higher or equal precedence as the right-hand version. - template - bool operator>=(const Basic_version&, - const Basic_version&); + /// Test if left-hand version operand is of higher or equal precedence as the right-hand version. + template + bool operator>=(const Basic_version&, + const Basic_version&); - /// Test if left-hand version operand is of lower or equal precedence as the right-hand version. - template - bool operator<=(const Basic_version&, - const Basic_version&); + /// Test if left-hand version operand is of lower or equal precedence as the right-hand version. + template + bool operator<=(const Basic_version&, + const Basic_version&); - /// Base class for various version parsing and precedence ordering schemes. - /** - Basic_version class describes general version object without prescribing parsing, - validation and comparison rules. These rules are implemented by supplied Parser and - Comparator objects. - */ - template - class Basic_version { - public: - /// Construct Basic_version object using Parser object to parse default ("0.0.0") version string and Comparator for comparison. - Basic_version(Parser, Comparator); + /// Base class for various version parsing and precedence ordering schemes. + /** + Basic_version class describes general version object without prescribing parsing, + validation and comparison rules. These rules are implemented by supplied Parser and + Comparator objects. + */ + template + class Basic_version + { + public: + /// Construct Basic_version object using Parser object to parse default ("0.0.0") version string and Comparator for comparison. + Basic_version(Parser, Comparator); - /// Construct Basic_version object using Parser to parse supplied version string and Comparator for comparison. - Basic_version(const std::string&, Parser, Comparator); + /// Construct Basic_version object using Parser to parse supplied version string and Comparator for comparison. + Basic_version(const std::string&, Parser, Comparator); - /// Construct Basic_version by copying data from another one. - Basic_version(const Basic_version&); + /// Construct Basic_version by copying data from another one. + Basic_version(const Basic_version&); - /// Copy version data from another Basic_version to this one. - Basic_version& operator=(const Basic_version&); + /// Copy version data from another Basic_version to this one. + Basic_version& operator=(const Basic_version&); - int major() const; ///< Get major version. - int minor() const; ///< Get minor version. - int patch() const; ///< Get patch version. - const std::string prerelease() const; ///< Get prerelease version string. - const std::string build() const; ///< Get build version string. + int major() const; ///< Get major version. + int minor() const; ///< Get minor version. + int patch() const; ///< Get patch version. + const std::string prerelease() const; ///< Get prerelease version string. + const std::string build() const; ///< Get build version string. - friend bool operator< <>(const Basic_version&, const Basic_version&); - friend bool operator== <>(const Basic_version&, const Basic_version&); - friend std::ostream& operator<< <>(std::ostream&s, const Basic_version&); + friend bool operator< <>(const Basic_version&, const Basic_version&); + friend bool operator== <>(const Basic_version&, const Basic_version&); + friend std::ostream& operator<< <>(std::ostream& s, const Basic_version&); - private: - Parser parser_; - Comparator comparator_; - Version_data ver_; - }; + private: + Parser parser_; + Comparator comparator_; + Version_data ver_; + }; } #include "version.inl" diff --git a/src/WriteZipToSetup/WriteZipToSetup.cpp b/src/WriteZipToSetup/WriteZipToSetup.cpp index fd00ecc4..48523779 100644 --- a/src/WriteZipToSetup/WriteZipToSetup.cpp +++ b/src/WriteZipToSetup/WriteZipToSetup.cpp @@ -13,171 +13,171 @@ using namespace std; BOOL CALLBACK EnumResLangProc(HMODULE hModule, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, LONG_PTR lParam) { - HANDLE hUpdate = (HANDLE)lParam; - HRSRC hFindItAgain = FindResourceEx(hModule, lpszType, lpszName, wIDLanguage); + HANDLE hUpdate = (HANDLE)lParam; + HRSRC hFindItAgain = FindResourceEx(hModule, lpszType, lpszName, wIDLanguage); - HGLOBAL hGlobal = LoadResource(hModule, hFindItAgain); - if (!hGlobal) return true; + HGLOBAL hGlobal = LoadResource(hModule, hFindItAgain); + if (!hGlobal) return true; - UpdateResource(hUpdate, lpszType, lpszName, wIDLanguage, LockResource(hGlobal), SizeofResource(hModule, hFindItAgain)); - return true; + UpdateResource(hUpdate, lpszType, lpszName, wIDLanguage, LockResource(hGlobal), SizeofResource(hModule, hFindItAgain)); + return true; } BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) { - HANDLE hUpdate = (HANDLE)lParam; + HANDLE hUpdate = (HANDLE)lParam; - EnumResourceLanguages(hModule, lpszType, lpszName, EnumResLangProc, (LONG_PTR)hUpdate); - return true; + EnumResourceLanguages(hModule, lpszType, lpszName, EnumResLangProc, (LONG_PTR)hUpdate); + return true; } BOOL CALLBACK EnumResTypeProc(HMODULE hMod, LPTSTR lpszType, LONG_PTR lParam) { - std::vector* typeList = (std::vector*)lParam; - if (IS_INTRESOURCE(lpszType)) { - typeList->push_back(lpszType); - } - else { - typeList->push_back(_wcsdup(lpszType)); - } + std::vector* typeList = (std::vector*)lParam; + if (IS_INTRESOURCE(lpszType)) { + typeList->push_back(lpszType); + } + else { + typeList->push_back(_wcsdup(lpszType)); + } - return true; + return true; } int CopyResourcesToStubExecutable(wchar_t* src, wchar_t* dest) { - HMODULE hSrc = LoadLibraryEx(src, NULL, LOAD_LIBRARY_AS_DATAFILE); - if (!hSrc) return GetLastError(); + HMODULE hSrc = LoadLibraryEx(src, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (!hSrc) return GetLastError(); - HANDLE hUpdate = BeginUpdateResource(dest, true); - if (!hUpdate) return GetLastError(); + HANDLE hUpdate = BeginUpdateResource(dest, true); + if (!hUpdate) return GetLastError(); - std::vector typeList; - EnumResourceTypes(hSrc, EnumResTypeProc, (LONG_PTR)&typeList); + std::vector typeList; + EnumResourceTypes(hSrc, EnumResTypeProc, (LONG_PTR)&typeList); - for (auto& type : typeList) { - EnumResourceNames(hSrc, type, EnumResNameProc, (LONG_PTR)hUpdate); - } + for (auto& type : typeList) { + EnumResourceNames(hSrc, type, EnumResNameProc, (LONG_PTR)hUpdate); + } - EndUpdateResource(hUpdate, false); - return 0; + EndUpdateResource(hUpdate, false); + return 0; } int LoadFileIntoMemory(wstring fpath, BYTE** pBuf, int* cBuf) { - HANDLE hFile = CreateFile(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - printf("Can't open file\n"); - return E_FAIL; - } + HANDLE hFile = CreateFile(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + printf("Can't open file\n"); + return E_FAIL; + } - BY_HANDLE_FILE_INFORMATION fileInfo; - if (!GetFileInformationByHandle(hFile, &fileInfo)) { - printf("Can't read file handle\n"); - return E_FAIL; - } + BY_HANDLE_FILE_INFORMATION fileInfo; + if (!GetFileInformationByHandle(hFile, &fileInfo)) { + printf("Can't read file handle\n"); + return E_FAIL; + } - *cBuf = fileInfo.nFileSizeLow; - *pBuf = new BYTE[fileInfo.nFileSizeLow + 0x1000]; + *cBuf = fileInfo.nFileSizeLow; + *pBuf = new BYTE[fileInfo.nFileSizeLow + 0x1000]; - BYTE* pCurrent = *pBuf; - DWORD dwBytesRead; + BYTE* pCurrent = *pBuf; + DWORD dwBytesRead; - printf("Starting to read file!\n"); - do { - if (!ReadFile(hFile, pCurrent, 0x1000, &dwBytesRead, NULL)) { - printf("Failed to read file! 0x%u\n", GetLastError()); - return E_FAIL; - } + printf("Starting to read file!\n"); + do { + if (!ReadFile(hFile, pCurrent, 0x1000, &dwBytesRead, NULL)) { + printf("Failed to read file! 0x%u\n", GetLastError()); + return E_FAIL; + } - pCurrent += dwBytesRead; - } while (dwBytesRead > 0); + pCurrent += dwBytesRead; + } while (dwBytesRead > 0); - return S_OK; + return S_OK; } int fail() { - printf("Usage: WriteZipToSetup [Setup.exe template] [Zip File]\n"); - return -1; + printf("Usage: WriteZipToSetup [Setup.exe template] [Zip File]\n"); + return -1; } int wmain(int argc, wchar_t* argv[]) { - // short circuit exit for stub executable - if (argc > 1 && wcscmp(argv[1], L"--copy-stub-resources") == 0) { - if (argc != 4) return fail(); - return CopyResourcesToStubExecutable(argv[2], argv[3]); - } + // short circuit exit for stub executable + if (argc > 1 && wcscmp(argv[1], L"--copy-stub-resources") == 0) { + if (argc != 4) return fail(); + return CopyResourcesToStubExecutable(argv[2], argv[3]); + } - // parse command line arguments - const flags::args args(argc, argv); - const auto& parg = args.positional(); - if (parg.size() != 2) { - return fail(); - } - const auto setupFile = wstring(parg[0]); - const auto zipFile = wstring(parg[1]); - const auto requiredFramework = args.get(L"set-required-framework"); - const auto splashImage = args.get(L"set-splash"); + // parse command line arguments + const flags::args args(argc, argv); + const auto& parg = args.positional(); + if (parg.size() != 2) { + return fail(); + } + const auto setupFile = wstring(parg[0]); + const auto zipFile = wstring(parg[1]); + const auto requiredFramework = args.get(L"set-required-framework"); + const auto splashImage = args.get(L"set-splash"); - wprintf(L"Setup: %s, Zip: %s\n", setupFile.c_str(), zipFile.c_str()); + wprintf(L"Setup: %s, Zip: %s\n", setupFile.c_str(), zipFile.c_str()); - // Read the entire zip file into memory, yolo - BYTE *pZipBuf, *pSplashBuf; - int cZipBuf, cSplashBuf; + // Read the entire zip file into memory, yolo + BYTE* pZipBuf, * pSplashBuf; + int cZipBuf, cSplashBuf; - if (FAILED(LoadFileIntoMemory(zipFile, &pZipBuf, &cZipBuf))) { - printf("Couldn't read zip file.\n"); - return fail(); - } + if (FAILED(LoadFileIntoMemory(zipFile, &pZipBuf, &cZipBuf))) { + printf("Couldn't read zip file.\n"); + return fail(); + } - printf("Updating Resource!\n"); - HANDLE hRes = BeginUpdateResource(setupFile.c_str(), false); - if (!hRes) { - printf("Couldn't open setup.exe for writing\n"); - return fail(); - } + printf("Updating Resource!\n"); + HANDLE hRes = BeginUpdateResource(setupFile.c_str(), false); + if (!hRes) { + printf("Couldn't open setup.exe for writing\n"); + return fail(); + } - if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_UPDATE_ZIP), RESOURCE_LANG, pZipBuf, cZipBuf)) { - printf("Failed to update zip resource\n"); - return fail(); - } + if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_UPDATE_ZIP), RESOURCE_LANG, pZipBuf, cZipBuf)) { + printf("Failed to update zip resource\n"); + return fail(); + } - if (requiredFramework.has_value()) { - wstring sReq = requiredFramework.value(); - LPVOID pReq = &sReq[0]; - if (!UpdateResource(hRes, L"FLAGS", MAKEINTRESOURCE(IDR_FX_VERSION_FLAG), RESOURCE_LANG, pReq, (sReq.length() + 1) * sizeof(wchar_t))) { - printf("Failed to update required version resource\n"); - return fail(); - } - } + if (requiredFramework.has_value()) { + wstring sReq = requiredFramework.value(); + LPVOID pReq = &sReq[0]; + if (!UpdateResource(hRes, L"FLAGS", MAKEINTRESOURCE(IDR_FX_VERSION_FLAG), RESOURCE_LANG, pReq, (sReq.length() + 1) * sizeof(wchar_t))) { + printf("Failed to update required version resource\n"); + return fail(); + } + } - if (splashImage.has_value()) { - if (FAILED(LoadFileIntoMemory(splashImage.value(), &pSplashBuf, &cSplashBuf))) { - printf("Couldn't read splash image.\n"); - return fail(); - } + if (splashImage.has_value()) { + if (FAILED(LoadFileIntoMemory(splashImage.value(), &pSplashBuf, &cSplashBuf))) { + printf("Couldn't read splash image.\n"); + return fail(); + } - if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_SPLASH_IMG), RESOURCE_LANG, pSplashBuf, cSplashBuf)) { - printf("Failed to update splash resource\n"); - return fail(); - } - } - else { + if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_SPLASH_IMG), RESOURCE_LANG, pSplashBuf, cSplashBuf)) { + printf("Failed to update splash resource\n"); + return fail(); + } + } + else { // if the user hasn't given us a splash screen, let's remove the default (there will be no splash at all) - if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_SPLASH_IMG), RESOURCE_LANG, 0, 0)) { - printf("Failed to update splash resource\n"); - return fail(); - } - } + if (!UpdateResource(hRes, L"DATA", MAKEINTRESOURCE(IDR_SPLASH_IMG), RESOURCE_LANG, 0, 0)) { + printf("Failed to update splash resource\n"); + return fail(); + } + } - printf("Finished!\n"); - if (!EndUpdateResource(hRes, false)) { - printf("Failed to update resource\n"); - return fail(); - } + printf("Finished!\n"); + if (!EndUpdateResource(hRes, false)) { + printf("Failed to update resource\n"); + return fail(); + } - printf("It worked!\n"); - return 0; + printf("It worked!\n"); + return 0; } diff --git a/src/WriteZipToSetup/flags.h b/src/WriteZipToSetup/flags.h index 18b25bdb..9e24dc53 100644 --- a/src/WriteZipToSetup/flags.h +++ b/src/WriteZipToSetup/flags.h @@ -11,8 +11,10 @@ #include #include -namespace flags { - namespace detail { +namespace flags +{ + namespace detail + { using argument_map = std::unordered_map>; @@ -21,8 +23,10 @@ namespace flags { // * If the token does not begin with a -, it will be considered a value for the // previous option. If there was no previous option, it will be considered a // positional argument. - struct parser { - parser(const int argc, wchar_t** argv) { + struct parser + { + parser(const int argc, wchar_t** argv) + { for (int i = 1; i < argc; ++i) { churn(argv[i]); } @@ -32,22 +36,26 @@ namespace flags { parser& operator=(const parser&) = delete; const argument_map& options() const { return options_; } - const std::vector& positional_arguments() const { + const std::vector& positional_arguments() const + { return positional_arguments_; } private: // Advance the state machine for the current token. - void churn(const std::wstring_view& item) { + void churn(const std::wstring_view& item) + { item.at(0) == '-' ? on_option(item) : on_value(item); } // Consumes the current option if there is one. - void flush() { + void flush() + { if (current_option_) on_value(); } - void on_option(const std::wstring_view& option) { + void on_option(const std::wstring_view& option) + { // Consume the current_option and reassign it to the new option while // removing all leading dashes. flush(); @@ -64,7 +72,8 @@ namespace flags { } } - void on_value(const std::optional& value = std::nullopt) { + void on_value(const std::optional& value = std::nullopt) + { // If there's not an option preceding the value, it's a positional argument. if (!current_option_) { if (value) positional_arguments_.emplace_back(*value); @@ -82,7 +91,8 @@ namespace flags { // If a key exists, return an optional populated with its value. inline std::optional get_value( - const argument_map& options, const std::wstring_view& option) { + const argument_map& options, const std::wstring_view& option) + { if (const auto it = options.find(option); it != options.end()) { return it->second; } @@ -94,7 +104,8 @@ namespace flags { // nullopt. template std::optional get(const argument_map& options, - const std::wstring_view& option) { + const std::wstring_view& option) + { if (const auto view = get_value(options, option)) { if (T value; std::istringstream(std::wstring(*view)) >> value) return value; } @@ -104,13 +115,15 @@ namespace flags { // Since the values are already stored as strings, there's no need to use `>>`. template <> inline std::optional get(const argument_map& options, - const std::wstring_view& option) { + const std::wstring_view& option) + { return get_value(options, option); } template <> inline std::optional get(const argument_map& options, - const std::wstring_view& option) { + const std::wstring_view& option) + { if (const auto view = get(options, option)) { return std::wstring(*view); } @@ -123,7 +136,8 @@ namespace flags { constexpr std::array falsities{ {L"0", L"n", L"no", L"f", L"false"} }; template <> inline std::optional get(const argument_map& options, - const std::wstring_view& option) { + const std::wstring_view& option) + { if (const auto value = get_value(options, option)) { return std::none_of(falsities.begin(), falsities.end(), [&value](auto falsity) { return *value == falsity; }); @@ -137,7 +151,8 @@ namespace flags { // nullopt. template std::optional get(const std::vector& positional_arguments, - size_t positional_index) { + size_t positional_index) + { if (positional_index < positional_arguments.size()) { if (T value; std::istringstream( std::wstring(positional_arguments[positional_index])) >> @@ -151,7 +166,8 @@ namespace flags { template <> inline std::optional get( const std::vector& positional_arguments, - size_t positional_index) { + size_t positional_index) + { if (positional_index < positional_arguments.size()) { return positional_arguments[positional_index]; } @@ -161,7 +177,8 @@ namespace flags { template <> inline std::optional get( const std::vector& positional_arguments, - size_t positional_index) { + size_t positional_index) + { if (positional_index < positional_arguments.size()) { return std::wstring(positional_arguments[positional_index]); } @@ -169,30 +186,36 @@ namespace flags { } } // namespace detail - struct args { + struct args + { args(const int argc, wchar_t** argv) : parser_(argc, argv) {} template - std::optional get(const std::wstring_view& option) const { + std::optional get(const std::wstring_view& option) const + { return detail::get(parser_.options(), option); } template - T get(const std::wstring_view& option, T&& default_value) const { + T get(const std::wstring_view& option, T&& default_value) const + { return get(option).value_or(default_value); } template - std::optional get(size_t positional_index) const { + std::optional get(size_t positional_index) const + { return detail::get(parser_.positional_arguments(), positional_index); } template - T get(size_t positional_index, T&& default_value) const { + T get(size_t positional_index, T&& default_value) const + { return get(positional_index).value_or(default_value); } - const std::vector& positional() const { + const std::vector& positional() const + { return parser_.positional_arguments(); }