ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
April 2018
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
26 participants
247 discussions
Start a n
N
ew thread
05/08: [USERSRV] Hard-error improvements 4/7
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9ea2783e5640598bf7155…
commit 9ea2783e5640598bf7155372b84a7b0be0feebaa Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sat Mar 24 22:47:50 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Apr 7 18:48:10 2018 +0200 [USERSRV] Hard-error improvements 4/7 - Make UserpFormatMessages() always succeed by falling back on static string buffers if allocating large string buffers fail due to lack of memory. Then the hard error popups will have truncated strings, but at least something will be displayed instead of nothing, thus alerting the user that something went wrong anyway. - Simplify a bit the code by moving the NtOpenProcess(), UserpCaptureStringParameters() and UserpFreeStringParameters() calls inside UserpFormatMessages(). This also allows simplifying its prototype. --- win32ss/user/winsrv/usersrv/harderror.c | 454 ++++++++++++++++---------------- 1 file changed, 225 insertions(+), 229 deletions(-) diff --git a/win32ss/user/winsrv/usersrv/harderror.c b/win32ss/user/winsrv/usersrv/harderror.c index 463911ba73..ad3815a434 100644 --- a/win32ss/user/winsrv/usersrv/harderror.c +++ b/win32ss/user/winsrv/usersrv/harderror.c @@ -73,117 +73,6 @@ MessageBoxTimeoutW( DWORD dwTime); -static -NTSTATUS -UserpGetClientFileName( - OUT PUNICODE_STRING ClientFileNameU, - IN HANDLE hProcess) -{ - PLIST_ENTRY ModuleListHead; - PLIST_ENTRY Entry; - PLDR_DATA_TABLE_ENTRY Module; - PPEB_LDR_DATA Ldr; - PROCESS_BASIC_INFORMATION ClientBasicInfo; - LDR_DATA_TABLE_ENTRY ModuleData; - PVOID ClientDllBase; - NTSTATUS Status; - PPEB Peb; - - /* Initialize string */ - RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); - - /* Query process information */ - Status = NtQueryInformationProcess(hProcess, - ProcessBasicInformation, - &ClientBasicInfo, - sizeof(ClientBasicInfo), - NULL); - if (!NT_SUCCESS(Status)) return Status; - - /* Locate the process loader data table and retrieve its name from it */ - - Peb = ClientBasicInfo.PebBaseAddress; - if (!Peb) return STATUS_UNSUCCESSFUL; - - Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL); - if (!NT_SUCCESS(Status)) return Status; - - ModuleListHead = &Ldr->InLoadOrderModuleList; - Status = NtReadVirtualMemory(hProcess, - &ModuleListHead->Flink, - &Entry, - sizeof(Entry), - NULL); - if (!NT_SUCCESS(Status)) return Status; - - if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL; - - Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - Status = NtReadVirtualMemory(hProcess, - Module, - &ModuleData, - sizeof(ModuleData), - NULL); - if (!NT_SUCCESS(Status)) return Status; - - Status = NtReadVirtualMemory(hProcess, - &Peb->ImageBaseAddress, - &ClientDllBase, - sizeof(ClientDllBase), - NULL); - if (!NT_SUCCESS(Status)) return Status; - - if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL; - - ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength; - ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - ClientFileNameU->MaximumLength); - if (!ClientFileNameU->Buffer) - { - RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); - return STATUS_NO_MEMORY; - } - - Status = NtReadVirtualMemory(hProcess, - ModuleData.BaseDllName.Buffer, - ClientFileNameU->Buffer, - ClientFileNameU->MaximumLength, - NULL); - if (!NT_SUCCESS(Status)) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer); - RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); - return Status; - } - - ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR); - DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU); - - return STATUS_SUCCESS; -} - -static -VOID -UserpFreeStringParameters( - IN OUT PULONG_PTR Parameters, - IN PHARDERROR_MSG Message) -{ - ULONG nParam; - - /* Loop all parameters */ - for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam) - { - /* Check if the current parameter is a string */ - if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0)) - { - /* Free the string buffer */ - RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); - } - } -} - static VOID UserpCaptureStringParameters( @@ -293,35 +182,165 @@ UserpCaptureStringParameters( *SizeOfAllUnicodeStrings = Size; } +static +VOID +UserpFreeStringParameters( + IN OUT PULONG_PTR Parameters, + IN PHARDERROR_MSG Message) +{ + ULONG nParam; + + /* Loop all parameters */ + for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam) + { + /* Check if the current parameter is a string */ + if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0)) + { + /* Free the string buffer */ + RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); + } + } +} + static NTSTATUS +UserpGetClientFileName( + OUT PUNICODE_STRING ClientFileNameU, + IN HANDLE hProcess) +{ + PLIST_ENTRY ModuleListHead; + PLIST_ENTRY Entry; + PLDR_DATA_TABLE_ENTRY Module; + PPEB_LDR_DATA Ldr; + PROCESS_BASIC_INFORMATION ClientBasicInfo; + LDR_DATA_TABLE_ENTRY ModuleData; + PVOID ClientDllBase; + NTSTATUS Status; + PPEB Peb; + + /* Initialize string */ + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); + + /* Query process information */ + Status = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ClientBasicInfo, + sizeof(ClientBasicInfo), + NULL); + if (!NT_SUCCESS(Status)) return Status; + + /* Locate the process loader data table and retrieve its name from it */ + + Peb = ClientBasicInfo.PebBaseAddress; + if (!Peb) return STATUS_UNSUCCESSFUL; + + Status = NtReadVirtualMemory(hProcess, &Peb->Ldr, &Ldr, sizeof(Ldr), NULL); + if (!NT_SUCCESS(Status)) return Status; + + ModuleListHead = &Ldr->InLoadOrderModuleList; + Status = NtReadVirtualMemory(hProcess, + &ModuleListHead->Flink, + &Entry, + sizeof(Entry), + NULL); + if (!NT_SUCCESS(Status)) return Status; + + if (Entry == ModuleListHead) return STATUS_UNSUCCESSFUL; + + Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + + Status = NtReadVirtualMemory(hProcess, + Module, + &ModuleData, + sizeof(ModuleData), + NULL); + if (!NT_SUCCESS(Status)) return Status; + + Status = NtReadVirtualMemory(hProcess, + &Peb->ImageBaseAddress, + &ClientDllBase, + sizeof(ClientDllBase), + NULL); + if (!NT_SUCCESS(Status)) return Status; + + if (ClientDllBase != ModuleData.DllBase) return STATUS_UNSUCCESSFUL; + + ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength; + ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + ClientFileNameU->MaximumLength); + if (!ClientFileNameU->Buffer) + { + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); + return STATUS_NO_MEMORY; + } + + Status = NtReadVirtualMemory(hProcess, + ModuleData.BaseDllName.Buffer, + ClientFileNameU->Buffer, + ClientFileNameU->MaximumLength, + NULL); + if (!NT_SUCCESS(Status)) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer); + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); + return Status; + } + + ClientFileNameU->Length = (USHORT)(wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR)); + DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU); + + return STATUS_SUCCESS; +} + +static +VOID UserpFormatMessages( - OUT PUNICODE_STRING TextStringU, - OUT PUNICODE_STRING CaptionStringU, - IN PULONG_PTR Parameters, - IN ULONG SizeOfStrings, - IN PHARDERROR_MSG Message, - IN HANDLE hProcess OPTIONAL) + IN OUT PUNICODE_STRING TextStringU, + IN OUT PUNICODE_STRING CaptionStringU, + IN PHARDERROR_MSG Message) { NTSTATUS Status; - UNICODE_STRING FileNameU, TempStringU, WindowTitleU, FormatU, Format2U; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hProcess; + ULONG SizeOfStrings; + ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0}; + ULONG_PTR CopyParameters[MAXIMUM_HARDERROR_PARAMETERS]; + UNICODE_STRING WindowTitleU, FileNameU, TempStringU, FormatU, Format2U; ANSI_STRING FormatA, Format2A; HWND hwndOwner; PMESSAGE_RESOURCE_ENTRY MessageResource; - ULONG_PTR CapturedParameters[MAXIMUM_HARDERROR_PARAMETERS]; PWSTR FormatString, pszBuffer; - size_t cchBuffer; - ULONG ExceptionCode, Severity; + size_t cszBuffer; + ULONG Severity; ULONG Size; + /* Open client process */ + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + Status = NtOpenProcess(&hProcess, + PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, + &ObjectAttributes, + &Message->h.ClientId); + if (!NT_SUCCESS(Status)) + { + DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status); + hProcess = NULL; + } + + /* Capture all string parameters from the process memory */ + UserpCaptureStringParameters(Parameters, &SizeOfStrings, Message, hProcess); + /* Copy the Parameters array locally */ - RtlCopyMemory(&CapturedParameters, Parameters, sizeof(CapturedParameters)); + RtlCopyMemory(&CopyParameters, Parameters, sizeof(CopyParameters)); /* Get the file name of the client process */ Status = STATUS_SUCCESS; if (hProcess) Status = UserpGetClientFileName(&FileNameU, hProcess); + /* Close the process handle but keep its original value to know where stuff came from */ + if (hProcess) NtClose(hProcess); + /* * Fall back to SYSTEM process if the client process handle * was NULL or we failed retrieving a file name. @@ -389,7 +408,7 @@ UserpFormatMessages( else if (Severity == STATUS_SEVERITY_ERROR) TempStringU = g_ErrorU; else - RtlInitEmptyUnicodeString(&TempStringU, NULL, 0); + ASSERT(FALSE); // Unexpected, since Severity is only <= 3. } /* Retrieve the window title of the client, if it has one */ @@ -399,20 +418,20 @@ UserpFormatMessages( FindTopLevelWnd, (LPARAM)&hwndOwner); if (hwndOwner) { - cchBuffer = GetWindowTextLengthW(hwndOwner); - if (cchBuffer != 0) + cszBuffer = GetWindowTextLengthW(hwndOwner); + if (cszBuffer != 0) { - cchBuffer += 3; // 2 characters for ": " and a NULL terminator. - WindowTitleU.MaximumLength = (USHORT)(cchBuffer * sizeof(WCHAR)); + cszBuffer += 3; // 2 characters for ": " and a NULL terminator. + WindowTitleU.MaximumLength = (USHORT)(cszBuffer * sizeof(WCHAR)); WindowTitleU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, WindowTitleU.MaximumLength); if (WindowTitleU.Buffer) { - cchBuffer = GetWindowTextW(hwndOwner, + cszBuffer = GetWindowTextW(hwndOwner, WindowTitleU.Buffer, WindowTitleU.MaximumLength / sizeof(WCHAR)); - WindowTitleU.Length = (USHORT)(cchBuffer * sizeof(WCHAR)); + WindowTitleU.Length = (USHORT)(cszBuffer * sizeof(WCHAR)); RtlAppendUnicodeToString(&WindowTitleU, L": "); } else @@ -423,26 +442,32 @@ UserpFormatMessages( } /* Calculate buffer length for the caption */ - CaptionStringU->MaximumLength = WindowTitleU.Length + - FileNameU.Length + TempStringU.Length + - 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL); - - /* Allocate a buffer for the caption */ - CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - CaptionStringU->MaximumLength); - if (!CaptionStringU->Buffer) + cszBuffer = WindowTitleU.Length + FileNameU.Length + TempStringU.Length + + 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL); + if (cszBuffer > CaptionStringU->MaximumLength) { - DPRINT1("Cannot allocate memory for CaptionStringU\n"); - Status = STATUS_NO_MEMORY; + /* Allocate a larger buffer for the caption */ + pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + cszBuffer); + if (!pszBuffer) + { + /* We could not allocate a larger buffer; continue using the smaller static buffer */ + DPRINT1("Cannot allocate memory for CaptionStringU, use static buffer.\n"); + } + else + { + RtlInitEmptyUnicodeString(CaptionStringU, pszBuffer, (USHORT)cszBuffer); + } } + CaptionStringU->Length = 0; /* Append the file name, the separator and the caption text */ RtlStringCbPrintfW(CaptionStringU->Buffer, CaptionStringU->MaximumLength, L"%wZ%wZ - %wZ", &WindowTitleU, &FileNameU, &TempStringU); - CaptionStringU->Length = wcslen(CaptionStringU->Buffer) * sizeof(WCHAR); + CaptionStringU->Length = (USHORT)(wcslen(CaptionStringU->Buffer) * sizeof(WCHAR)); /* Free string buffers if needed */ if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU); @@ -454,7 +479,7 @@ UserpFormatMessages( /* Check if this is an exception message */ if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { - ExceptionCode = CapturedParameters[0]; + ULONG ExceptionCode = CopyParameters[0]; /* Get text string of the exception code */ Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), @@ -479,24 +504,24 @@ UserpFormatMessages( if (ExceptionCode == STATUS_ACCESS_VIOLATION) { FormatString = Format2U.Buffer; - CapturedParameters[0] = CapturedParameters[1]; - CapturedParameters[1] = CapturedParameters[3]; - if (CapturedParameters[2]) - CapturedParameters[2] = (ULONG_PTR)L"written"; + CopyParameters[0] = CopyParameters[1]; + CopyParameters[1] = CopyParameters[3]; + if (CopyParameters[2]) + CopyParameters[2] = (ULONG_PTR)L"written"; else - CapturedParameters[2] = (ULONG_PTR)L"read"; + CopyParameters[2] = (ULONG_PTR)L"read"; } else if (ExceptionCode == STATUS_IN_PAGE_ERROR) { FormatString = Format2U.Buffer; - CapturedParameters[0] = CapturedParameters[1]; - CapturedParameters[1] = CapturedParameters[3]; + CopyParameters[0] = CopyParameters[1]; + CopyParameters[1] = CopyParameters[3]; } else { /* Keep the existing FormatString */ - CapturedParameters[2] = CapturedParameters[1]; - CapturedParameters[1] = CapturedParameters[0]; + CopyParameters[2] = CopyParameters[1]; + CopyParameters[1] = CopyParameters[0]; pszBuffer = Format2U.Buffer; if (!_wcsnicmp(pszBuffer, L"{EXCEPTION}", 11)) @@ -510,21 +535,21 @@ UserpFormatMessages( /* Skip '\r', '\n' */ pszBuffer += 2; - CapturedParameters[0] = (ULONG_PTR)pszBuffer; + CopyParameters[0] = (ULONG_PTR)pszBuffer; } else { /* Fall back to hardcoded value */ - CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; + CopyParameters[0] = (ULONG_PTR)L"unknown software exception"; } } } else { /* Fall back to hardcoded value, and keep the existing FormatString */ - CapturedParameters[2] = CapturedParameters[1]; - CapturedParameters[1] = CapturedParameters[0]; - CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; + CopyParameters[2] = CopyParameters[1]; + CopyParameters[1] = CopyParameters[0]; + CopyParameters[0] = (ULONG_PTR)L"unknown software exception"; } if (Message->ValidResponseOptions == OptionOk || @@ -540,53 +565,55 @@ UserpFormatMessages( } } - /* Calculate length of text buffer */ - TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + - (USHORT)(Size * sizeof(WCHAR)) + - sizeof(UNICODE_NULL); - - /* Allocate a buffer for the text */ - TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - TextStringU->MaximumLength); - if (!TextStringU->Buffer) + /* Calculate buffer length for the text message */ + cszBuffer = FormatU.Length + SizeOfStrings + Size * sizeof(WCHAR) + + sizeof(UNICODE_NULL); + if (cszBuffer > TextStringU->MaximumLength) { - DPRINT1("Cannot allocate memory for TextStringU\n"); - Status = STATUS_NO_MEMORY; + /* Allocate a larger buffer for the text message */ + pszBuffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + cszBuffer); + if (!pszBuffer) + { + /* We could not allocate a larger buffer; continue using the smaller static buffer */ + DPRINT1("Cannot allocate memory for TextStringU, use static buffer.\n"); + } + else + { + RtlInitEmptyUnicodeString(TextStringU, pszBuffer, (USHORT)cszBuffer); + } } - - Status = STATUS_SUCCESS; + TextStringU->Length = 0; /* Wrap in SEH to protect from invalid string parameters */ _SEH2_TRY { /* Print the string into the buffer */ pszBuffer = TextStringU->Buffer; - cchBuffer = TextStringU->MaximumLength; - RtlStringCbPrintfExW(pszBuffer, cchBuffer, - &pszBuffer, &cchBuffer, + cszBuffer = TextStringU->MaximumLength; + RtlStringCbPrintfExW(pszBuffer, cszBuffer, + &pszBuffer, &cszBuffer, STRSAFE_IGNORE_NULLS, FormatString, - CapturedParameters[0], - CapturedParameters[1], - CapturedParameters[2], - CapturedParameters[3]); + CopyParameters[0], CopyParameters[1], + CopyParameters[2], CopyParameters[3]); if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { if (Message->ValidResponseOptions == OptionOk || Message->ValidResponseOptions == OptionOkCancel) { - RtlStringCbPrintfExW(pszBuffer, cchBuffer, - &pszBuffer, &cchBuffer, + RtlStringCbPrintfExW(pszBuffer, cszBuffer, + &pszBuffer, &cszBuffer, STRSAFE_IGNORE_NULLS, L"\n%wZ", &g_OKTerminateU); } if (Message->ValidResponseOptions == OptionOkCancel) { - RtlStringCbPrintfExW(pszBuffer, cchBuffer, - &pszBuffer, &cchBuffer, + RtlStringCbPrintfExW(pszBuffer, cszBuffer, + &pszBuffer, &cszBuffer, STRSAFE_IGNORE_NULLS, L"\n%wZ", &g_CancelDebugU); @@ -595,7 +622,7 @@ UserpFormatMessages( } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* An exception occurred, use a default string */ + /* An exception occurred, use a default string with the original parameters */ DPRINT1("Exception 0x%08lx occurred while building hard-error message, fall back to default message.\n", _SEH2_GetExceptionCode()); @@ -604,24 +631,19 @@ UserpFormatMessages( L"Exception processing message 0x%08lx\n" L"Parameters: 0x%p 0x%p 0x%p 0x%p", Message->Status, - CapturedParameters[0], CapturedParameters[1], - CapturedParameters[2], CapturedParameters[3]); - - /* Set error and free buffers */ - // Status = _SEH2_GetExceptionCode(); + Parameters[0], Parameters[1], + Parameters[2], Parameters[3]); } _SEH2_END; - if (NT_SUCCESS(Status)) - { - TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR); - } + TextStringU->Length = (USHORT)(wcslen(TextStringU->Buffer) * sizeof(WCHAR)); /* Free converted Unicode strings */ if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U); if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); - return Status; + /* Final cleanup */ + UserpFreeStringParameters(Parameters, Message); } static ULONG @@ -872,13 +894,10 @@ UserServerHardError( IN PCSR_THREAD ThreadData, IN PHARDERROR_MSG Message) { - ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0}; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING TextU, CaptionU; - NTSTATUS Status; - HANDLE hProcess; - ULONG Size; ULONG ErrorMode; + UNICODE_STRING TextU, CaptionU; + WCHAR LocalTextBuffer[256]; + WCHAR LocalCaptionBuffer[256]; ASSERT(ThreadData->Process != NULL); @@ -899,39 +918,13 @@ UserServerHardError( } // TODO: More message validation: check NumberOfParameters wrt. Message Status code. - /* Open client process */ - InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); - Status = NtOpenProcess(&hProcess, - PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, - &ObjectAttributes, - &Message->h.ClientId); - if (!NT_SUCCESS(Status)) - { - DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status); - hProcess = NULL; - } - /* Re-initialize the hard errors cache */ UserInitHardErrorsCache(); - /* Capture all string parameters from the process memory */ - UserpCaptureStringParameters(Parameters, &Size, Message, hProcess); - /* Format the message caption and text */ - Status = UserpFormatMessages(&TextU, - &CaptionU, - Parameters, - Size, - Message, - hProcess); - - /* Cleanup */ - UserpFreeStringParameters(Parameters, Message); - if (hProcess) NtClose(hProcess); - - /* If we failed, bail out */ - if (!NT_SUCCESS(Status)) - return; + RtlInitEmptyUnicodeString(&TextU, LocalTextBuffer, sizeof(LocalTextBuffer)); + RtlInitEmptyUnicodeString(&CaptionU, LocalCaptionBuffer, sizeof(LocalCaptionBuffer)); + UserpFormatMessages(&TextU, &CaptionU, Message); /* Log the hard error message */ UserpLogHardError(&TextU, &CaptionU); @@ -970,8 +963,11 @@ UserServerHardError( (ULONG)-1); Quit: - RtlFreeUnicodeString(&TextU); - RtlFreeUnicodeString(&CaptionU); + /* Free the strings if they have been reallocated */ + if (TextU.Buffer != LocalTextBuffer) + RtlFreeUnicodeString(&TextU); + if (CaptionU.Buffer != LocalCaptionBuffer) + RtlFreeUnicodeString(&CaptionU); return; }
6 years, 8 months
1
0
0
0
04/08: [USERSRV] Hard-error improvements 3/7
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5a1a35ca5a6fca02dcabc…
commit 5a1a35ca5a6fca02dcabced12a5d19b020dc184d Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sun Mar 4 17:38:06 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Apr 7 18:48:09 2018 +0200 [USERSRV] Hard-error improvements 3/7 - Cache localized hard error message components: the status severity, the system process name and the unhandled exception debug strings. - Try not to fail too much. In particular, don't fail if a string could not be correctly captured in UserpCaptureStringParameters() (we then use a default empty string). The next aim is to make UserpFormatMessages() not failing at all. - Use RtlStringCbPrintf(Ex)W where possible so that one can use counted (and not NULL-terminated) UNICODE_STRINGs where possible. This allows using counted resource strings without having to allocate memory. - If available, prepend the window title of the application that triggered the hard error to the hard error message box caption. --- win32ss/user/winsrv/usersrv/harderror.c | 285 +++++++++++++++++++----------- win32ss/user/winsrv/usersrv/init.c | 16 ++ win32ss/user/winsrv/usersrv/lang/bg-BG.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/cs-CZ.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/de-DE.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/el-GR.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/en-US.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/es-ES.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/fr-FR.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/he-IL.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/id-ID.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/it-IT.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/ja-JP.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/no-NO.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/pl-PL.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/pt-BR.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/ro-RO.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/ru-RU.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/sk-SK.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/sv-SE.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/tr-TR.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/uk-UA.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/zh-CN.rc | 17 ++ win32ss/user/winsrv/usersrv/lang/zh-TW.rc | 17 ++ win32ss/user/winsrv/usersrv/resource.h | 23 ++- win32ss/user/winsrv/usersrv/shutdown.c | 12 -- win32ss/user/winsrv/usersrv/usersrv.h | 8 + 27 files changed, 601 insertions(+), 117 deletions(-) diff --git a/win32ss/user/winsrv/usersrv/harderror.c b/win32ss/user/winsrv/usersrv/harderror.c index 19a8db644f..463911ba73 100644 --- a/win32ss/user/winsrv/usersrv/harderror.c +++ b/win32ss/user/winsrv/usersrv/harderror.c @@ -18,14 +18,49 @@ #include <undocelfapi.h> #include <ntstrsafe.h> +#include "resource.h" + #define NDEBUG #include <debug.h> -#define IDTRYAGAIN 10 -#define IDCONTINUE 11 /* FUNCTIONS ******************************************************************/ +/* Cache for the localized hard-error message box strings */ +LANGID g_CurrentUserLangId = 0; +UNICODE_STRING g_SuccessU = {0, 0, NULL}; +UNICODE_STRING g_InformationU = {0, 0, NULL}; +UNICODE_STRING g_WarningU = {0, 0, NULL}; +UNICODE_STRING g_ErrorU = {0, 0, NULL}; +UNICODE_STRING g_SystemProcessU = {0, 0, NULL}; +UNICODE_STRING g_OKTerminateU = {0, 0, NULL}; +UNICODE_STRING g_CancelDebugU = {0, 0, NULL}; + +VOID +RtlLoadUnicodeString( + IN HINSTANCE hInstance OPTIONAL, + IN UINT uID, + OUT PUNICODE_STRING pUnicodeString, + IN PCWSTR pDefaultString) +{ + UINT Length; + + /* Try to load the string from the resource */ + Length = LoadStringW(hInstance, uID, (LPWSTR)&pUnicodeString->Buffer, 0); + if (Length == 0) + { + /* If the resource string was not found, use the fallback default one */ + RtlInitUnicodeString(pUnicodeString, pDefaultString); + } + else + { + /* Set the string length (not NULL-terminated!) */ + pUnicodeString->MaximumLength = (USHORT)(Length * sizeof(WCHAR)); + pUnicodeString->Length = pUnicodeString->MaximumLength; + } +} + + /* FIXME */ int WINAPI @@ -133,15 +168,15 @@ static VOID UserpFreeStringParameters( IN OUT PULONG_PTR Parameters, - IN PHARDERROR_MSG HardErrorMessage) + IN PHARDERROR_MSG Message) { ULONG nParam; /* Loop all parameters */ - for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) + for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam) { /* Check if the current parameter is a string */ - if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0)) + if ((Message->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0)) { /* Free the string buffer */ RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); @@ -150,14 +185,14 @@ UserpFreeStringParameters( } static -NTSTATUS +VOID UserpCaptureStringParameters( OUT PULONG_PTR Parameters, OUT PULONG SizeOfAllUnicodeStrings, - IN PHARDERROR_MSG HardErrorMessage, + IN PHARDERROR_MSG Message, IN HANDLE hProcess OPTIONAL) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; ULONG nParam, Size = 0; UNICODE_STRING TempStringU, ParamStringU; ANSI_STRING TempStringA; @@ -166,12 +201,12 @@ UserpCaptureStringParameters( *SizeOfAllUnicodeStrings = 0; /* Read all strings from client space */ - for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) + for (nParam = 0; nParam < Message->NumberOfParameters; ++nParam) { Parameters[nParam] = 0; /* Check if the current parameter is a unicode string */ - if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) + if (Message->UnicodeStringParameterMask & (1 << nParam)) { /* Skip this string if we do not have a client process */ if (!hProcess) @@ -179,14 +214,14 @@ UserpCaptureStringParameters( /* Read the UNICODE_STRING from the process memory */ Status = NtReadVirtualMemory(hProcess, - (PVOID)HardErrorMessage->Parameters[nParam], + (PVOID)Message->Parameters[nParam], &ParamStringU, sizeof(ParamStringU), NULL); if (!NT_SUCCESS(Status)) { /* We failed, skip this string */ - DPRINT1("NtReadVirtualMemory(HardErrorMessage->Parameters) failed, Status 0x%lx\n", Status); + DPRINT1("NtReadVirtualMemory(Message->Parameters) failed, Status 0x%lx, skipping.\n", Status); continue; } @@ -199,8 +234,7 @@ UserpCaptureStringParameters( if (!TempStringU.Buffer) { /* We failed, skip this string */ - DPRINT1("Cannot allocate memory with size %u\n", TempStringU.MaximumLength); - Status = STATUS_NO_MEMORY; + DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringU.MaximumLength); continue; } @@ -213,7 +247,7 @@ UserpCaptureStringParameters( if (!NT_SUCCESS(Status)) { /* We failed, skip this string */ - DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx\n", Status); + DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx, skipping.\n", Status); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); continue; } @@ -228,9 +262,8 @@ UserpCaptureStringParameters( if (!TempStringA.Buffer) { /* We failed, skip this string */ - DPRINT1("Cannot allocate memory with size %u\n", TempStringA.MaximumLength); + DPRINT1("Cannot allocate memory with size %u, skipping.\n", TempStringA.MaximumLength); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); - Status = STATUS_NO_MEMORY; continue; } @@ -240,6 +273,7 @@ UserpCaptureStringParameters( if (!NT_SUCCESS(Status)) { /* We failed, skip this string */ + DPRINT1("RtlUnicodeStringToAnsiString() failed, Status 0x%lx, skipping.\n", Status); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer); continue; } @@ -251,22 +285,12 @@ UserpCaptureStringParameters( else { /* It's not a unicode string, just copy the parameter */ - Parameters[nParam] = HardErrorMessage->Parameters[nParam]; + Parameters[nParam] = Message->Parameters[nParam]; } } -#if 0 - if (!NT_SUCCESS(Status)) - { - UserpFreeStringParameters(Parameters, HardErrorMessage); - return Status; - } -#endif - if (SizeOfAllUnicodeStrings) *SizeOfAllUnicodeStrings = Size; - - return Status; } static @@ -280,11 +304,13 @@ UserpFormatMessages( IN HANDLE hProcess OPTIONAL) { NTSTATUS Status; - UNICODE_STRING FileNameU, TempStringU, FormatU, Format2U; + UNICODE_STRING FileNameU, TempStringU, WindowTitleU, FormatU, Format2U; ANSI_STRING FormatA, Format2A; + HWND hwndOwner; PMESSAGE_RESOURCE_ENTRY MessageResource; ULONG_PTR CapturedParameters[MAXIMUM_HARDERROR_PARAMETERS]; - PWSTR FormatString; + PWSTR FormatString, pszBuffer; + size_t cchBuffer; ULONG ExceptionCode, Severity; ULONG Size; @@ -302,8 +328,8 @@ UserpFormatMessages( */ if (!hProcess || !NT_SUCCESS(Status) || !FileNameU.Buffer) { - RtlInitUnicodeString(&FileNameU, L"System Process"); - hProcess = NULL; + hProcess = NULL; + FileNameU = g_SystemProcessU; } Severity = (ULONG)(Message->Status) >> 30; @@ -324,7 +350,7 @@ UserpFormatMessages( else { RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text); - RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE); + /* Status = */ RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE); } } else @@ -354,23 +380,52 @@ UserpFormatMessages( } else { - /* FIXME: Use localized strings! */ - if (Severity == STATUS_SEVERITY_SUCCESS) - RtlInitUnicodeString(&TempStringU, L"Success"); + TempStringU = g_SuccessU; else if (Severity == STATUS_SEVERITY_INFORMATIONAL) - RtlInitUnicodeString(&TempStringU, L"System Information"); + TempStringU = g_InformationU; else if (Severity == STATUS_SEVERITY_WARNING) - RtlInitUnicodeString(&TempStringU, L"System Warning"); + TempStringU = g_WarningU; else if (Severity == STATUS_SEVERITY_ERROR) - RtlInitUnicodeString(&TempStringU, L"System Error"); + TempStringU = g_ErrorU; else RtlInitEmptyUnicodeString(&TempStringU, NULL, 0); } + /* Retrieve the window title of the client, if it has one */ + RtlInitEmptyUnicodeString(&WindowTitleU, NULL, 0); + hwndOwner = NULL; + EnumThreadWindows(HandleToUlong(Message->h.ClientId.UniqueThread), + FindTopLevelWnd, (LPARAM)&hwndOwner); + if (hwndOwner) + { + cchBuffer = GetWindowTextLengthW(hwndOwner); + if (cchBuffer != 0) + { + cchBuffer += 3; // 2 characters for ": " and a NULL terminator. + WindowTitleU.MaximumLength = (USHORT)(cchBuffer * sizeof(WCHAR)); + WindowTitleU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), + HEAP_ZERO_MEMORY, + WindowTitleU.MaximumLength); + if (WindowTitleU.Buffer) + { + cchBuffer = GetWindowTextW(hwndOwner, + WindowTitleU.Buffer, + WindowTitleU.MaximumLength / sizeof(WCHAR)); + WindowTitleU.Length = (USHORT)(cchBuffer * sizeof(WCHAR)); + RtlAppendUnicodeToString(&WindowTitleU, L": "); + } + else + { + RtlInitEmptyUnicodeString(&WindowTitleU, NULL, 0); + } + } + } + /* Calculate buffer length for the caption */ - CaptionStringU->MaximumLength = FileNameU.Length + TempStringU.Length + - 4 * sizeof(WCHAR); + CaptionStringU->MaximumLength = WindowTitleU.Length + + FileNameU.Length + TempStringU.Length + + 3 * sizeof(WCHAR) + sizeof(UNICODE_NULL); /* Allocate a buffer for the caption */ CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), @@ -382,17 +437,16 @@ UserpFormatMessages( Status = STATUS_NO_MEMORY; } - /* Append the file name, seperator and the caption text */ - CaptionStringU->Length = 0; - RtlAppendUnicodeStringToString(CaptionStringU, &FileNameU); - RtlAppendUnicodeToString(CaptionStringU, L" - "); - RtlAppendUnicodeStringToString(CaptionStringU, &TempStringU); - - /* Zero terminate the buffer */ - CaptionStringU->Buffer[CaptionStringU->Length / sizeof(WCHAR)] = UNICODE_NULL; + /* Append the file name, the separator and the caption text */ + RtlStringCbPrintfW(CaptionStringU->Buffer, + CaptionStringU->MaximumLength, + L"%wZ%wZ - %wZ", + &WindowTitleU, &FileNameU, &TempStringU); + CaptionStringU->Length = wcslen(CaptionStringU->Buffer) * sizeof(WCHAR); - /* Free the file name buffer */ - RtlFreeUnicodeString(&FileNameU); + /* Free string buffers if needed */ + if (WindowTitleU.Buffer) RtlFreeUnicodeString(&WindowTitleU); + if (hProcess) RtlFreeUnicodeString(&FileNameU); // FIXME: What is 42 == ?? Size = 42; @@ -418,7 +472,7 @@ UserpFormatMessages( else { RtlInitAnsiString(&Format2A, (PCHAR)MessageResource->Text); - RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE); + /* Status = */ RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE); } /* Handle special cases */ @@ -440,25 +494,23 @@ UserpFormatMessages( } else { - PWSTR pTmp; - /* Keep the existing FormatString */ CapturedParameters[2] = CapturedParameters[1]; CapturedParameters[1] = CapturedParameters[0]; - pTmp = Format2U.Buffer; - if (!_wcsnicmp(pTmp, L"{EXCEPTION}", 11)) + pszBuffer = Format2U.Buffer; + if (!_wcsnicmp(pszBuffer, L"{EXCEPTION}", 11)) { /* * This is a named exception. Skip the mark and * retrieve the exception name that follows it. */ - pTmp += 11; + pszBuffer += 11; /* Skip '\r', '\n' */ - pTmp += 2; + pszBuffer += 2; - CapturedParameters[0] = (ULONG_PTR)pTmp; + CapturedParameters[0] = (ULONG_PTR)pszBuffer; } else { @@ -475,18 +527,16 @@ UserpFormatMessages( CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; } - /* FIXME: Use localized strings! */ if (Message->ValidResponseOptions == OptionOk || Message->ValidResponseOptions == OptionOkCancel) { - // Tmp = FormatString + wcslen(FormatString); - // *++Tmp = L'\n'; - // *++Tmp = L'\n'; - Size += 1 + wcslen(L"Click on OK to terminate the program."); + /* Reserve space for one newline and the OK-terminate-program string */ + Size += 1 + (g_OKTerminateU.Length / sizeof(WCHAR)); } if (Message->ValidResponseOptions == OptionOkCancel) { - Size += 1 + wcslen(L"Click on CANCEL to debug the program."); + /* Reserve space for one newline and the CANCEL-debug-program string */ + Size += 1 + (g_CancelDebugU.Length / sizeof(WCHAR)); } } @@ -505,50 +555,50 @@ UserpFormatMessages( Status = STATUS_NO_MEMORY; } + Status = STATUS_SUCCESS; + /* Wrap in SEH to protect from invalid string parameters */ _SEH2_TRY { /* Print the string into the buffer */ - RtlStringCbPrintfW(TextStringU->Buffer, - TextStringU->MaximumLength, - FormatString, - CapturedParameters[0], - CapturedParameters[1], - CapturedParameters[2], - CapturedParameters[3]); + pszBuffer = TextStringU->Buffer; + cchBuffer = TextStringU->MaximumLength; + RtlStringCbPrintfExW(pszBuffer, cchBuffer, + &pszBuffer, &cchBuffer, + STRSAFE_IGNORE_NULLS, + FormatString, + CapturedParameters[0], + CapturedParameters[1], + CapturedParameters[2], + CapturedParameters[3]); if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { - /* FIXME: Use localized strings! */ if (Message->ValidResponseOptions == OptionOk || Message->ValidResponseOptions == OptionOkCancel) { - // Tmp = FormatString + wcslen(FormatString); - // *++Tmp = L'\n'; - // *++Tmp = L'\n'; - RtlStringCbCatW(TextStringU->Buffer, - TextStringU->MaximumLength, - L"\n"); - RtlStringCbCatW(TextStringU->Buffer, - TextStringU->MaximumLength, - L"Click on OK to terminate the program."); + RtlStringCbPrintfExW(pszBuffer, cchBuffer, + &pszBuffer, &cchBuffer, + STRSAFE_IGNORE_NULLS, + L"\n%wZ", + &g_OKTerminateU); } if (Message->ValidResponseOptions == OptionOkCancel) { - RtlStringCbCatW(TextStringU->Buffer, - TextStringU->MaximumLength, - L"\n"); - RtlStringCbCatW(TextStringU->Buffer, - TextStringU->MaximumLength, - L"Click on CANCEL to debug the program."); + RtlStringCbPrintfExW(pszBuffer, cchBuffer, + &pszBuffer, &cchBuffer, + STRSAFE_IGNORE_NULLS, + L"\n%wZ", + &g_CancelDebugU); } } - - Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* An exception occurred, use a default string */ + DPRINT1("Exception 0x%08lx occurred while building hard-error message, fall back to default message.\n", + _SEH2_GetExceptionCode()); + RtlStringCbPrintfW(TextStringU->Buffer, TextStringU->MaximumLength, L"Exception processing message 0x%08lx\n" @@ -559,8 +609,6 @@ UserpFormatMessages( /* Set error and free buffers */ // Status = _SEH2_GetExceptionCode(); - // RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); - // RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); } _SEH2_END; @@ -569,7 +617,7 @@ UserpFormatMessages( TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR); } - /* Free converted Unicode strings if the original format strings were Ansi */ + /* Free converted Unicode strings */ if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U); if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); @@ -863,13 +911,11 @@ UserServerHardError( hProcess = NULL; } + /* Re-initialize the hard errors cache */ + UserInitHardErrorsCache(); + /* Capture all string parameters from the process memory */ - Status = UserpCaptureStringParameters(Parameters, &Size, Message, hProcess); - if (!NT_SUCCESS(Status)) - { - if (hProcess) NtClose(hProcess); - return; - } + UserpCaptureStringParameters(Parameters, &Size, Message, hProcess); /* Format the message caption and text */ Status = UserpFormatMessages(&TextU, @@ -930,4 +976,45 @@ Quit: return; } +VOID +UserInitHardErrorsCache(VOID) +{ + NTSTATUS Status; + LCID CurrentUserLCID = 0; + + Status = NtQueryDefaultLocale(TRUE, &CurrentUserLCID); + if (!NT_SUCCESS(Status) || CurrentUserLCID == 0) + { + /* Fall back to english locale */ + DPRINT1("NtQueryDefaultLocale failed with Status = 0x%08lx\n", Status); + // LOCALE_SYSTEM_DEFAULT; + CurrentUserLCID = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + } + if (g_CurrentUserLangId == LANGIDFROMLCID(CurrentUserLCID)) + { + /* The current lang ID and the hard error strings have already been cached */ + return; + } + + /* Load the strings using the current system locale */ + RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_SUCCESS, + &g_SuccessU, L"Success"); + RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_INFORMATIONAL, + &g_InformationU, L"System Information"); + RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_WARNING, + &g_WarningU, L"System Warning"); + RtlLoadUnicodeString(UserServerDllInstance, IDS_SEVERITY_ERROR, + &g_ErrorU, L"System Error"); + // "unknown software exception" + RtlLoadUnicodeString(UserServerDllInstance, IDS_SYSTEM_PROCESS, + &g_SystemProcessU, L"System Process"); + RtlLoadUnicodeString(UserServerDllInstance, IDS_OK_TERMINATE_PROGRAM, + &g_OKTerminateU, L"Click on OK to terminate the program."); + RtlLoadUnicodeString(UserServerDllInstance, IDS_CANCEL_DEBUG_PROGRAM, + &g_CancelDebugU, L"Click on CANCEL to debug the program."); + + /* Remember that we cached the hard error strings */ + g_CurrentUserLangId = LANGIDFROMLCID(CurrentUserLCID); +} + /* EOF */ diff --git a/win32ss/user/winsrv/usersrv/init.c b/win32ss/user/winsrv/usersrv/init.c index 2e9ac5a66f..8ee21e6417 100644 --- a/win32ss/user/winsrv/usersrv/init.c +++ b/win32ss/user/winsrv/usersrv/init.c @@ -90,6 +90,19 @@ PCHAR UserServerApiNameTable[UserpMaxApiNumber - USERSRV_FIRST_API_NUMBER] = /* FUNCTIONS ******************************************************************/ +BOOL CALLBACK +FindTopLevelWnd( + IN HWND hWnd, + IN LPARAM lParam) +{ + if (GetWindow(hWnd, GW_OWNER) == NULL) + { + *(HWND*)lParam = hWnd; + return FALSE; + } + return TRUE; +} + // PUSER_SOUND_SENTRY. Used in basesrv.dll BOOL NTAPI _UserSoundSentry(VOID) { @@ -256,6 +269,9 @@ CSR_SERVER_DLL_INIT(UserServerDllInitialization) /* Set the process creation notify routine for BASE */ BaseSetProcessCreateNotify(NtUserNotifyProcessCreate); + /* Initialize the hard errors cache */ + UserInitHardErrorsCache(); + /* Initialize the kernel mode subsystem */ Status = NtUserInitialize(USER_VERSION, ghPowerRequestEvent, diff --git a/win32ss/user/winsrv/usersrv/lang/bg-BG.rc b/win32ss/user/winsrv/usersrv/lang/bg-BG.rc index 56728454be..52e986ec16 100644 --- a/win32ss/user/winsrv/usersrv/lang/bg-BG.rc +++ b/win32ss/user/winsrv/usersrv/lang/bg-BG.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "За да се върнете в РеактОС и да проверите състоянието на приложението, натиснете „Отказ“.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Ако решите да затворите приложението веднага, ще изгубите всички незаписани данни. За да прекратите приложението веднага, натиснете „Прекратяване веднага“.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/cs-CZ.rc b/win32ss/user/winsrv/usersrv/lang/cs-CZ.rc index 747e0dcd16..46b44808ed 100644 --- a/win32ss/user/winsrv/usersrv/lang/cs-CZ.rc +++ b/win32ss/user/winsrv/usersrv/lang/cs-CZ.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "Kliknutím na Storno se lze vrátit do systému ReactOS a ověřit stav programu.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Pokud zvolíte okamžité ukončení programu, všechna neuložená data budou ztracena. Kliknutím na Ukončit okamžitě ukončíte program.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/de-DE.rc b/win32ss/user/winsrv/usersrv/lang/de-DE.rc index afb4741ecf..8d854f06c3 100644 --- a/win32ss/user/winsrv/usersrv/lang/de-DE.rc +++ b/win32ss/user/winsrv/usersrv/lang/de-DE.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "Um zu ReactOS zurückzukehren und den Status der Anwendung zu überprüfen, wählen Sie Abbrechen.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Wenn Sie das Programm sofort beenden, werden Sie eventuell ungespeicherte Daten verlieren. Um das Programm zu beenden, wählen Sie Jetzt beenden.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/el-GR.rc b/win32ss/user/winsrv/usersrv/lang/el-GR.rc index 7468f527f3..4adb7d79df 100644 --- a/win32ss/user/winsrv/usersrv/lang/el-GR.rc +++ b/win32ss/user/winsrv/usersrv/lang/el-GR.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "Για να επιστρέψετε στο ReactOS και να ελέγξετε την κατάσταση του προγράμματος, πατήστε 'ʼκυρο'.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Αν κλείσετε την εφαρμογή τώρα , θα χάσετε όλα τα μη αποθηκευμένα δεδομένα. Για να κλείσετε το πρόγραμμα τώρα, πατήστε 'Κλείσιμο Τώρα'.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/en-US.rc b/win32ss/user/winsrv/usersrv/lang/en-US.rc index c245f75236..b876aea3e2 100644 --- a/win32ss/user/winsrv/usersrv/lang/en-US.rc +++ b/win32ss/user/winsrv/usersrv/lang/en-US.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "To return to ReactOS and check the status of the program, click Cancel.", IDC_STATIC, 7, 26, 178, 16 LTEXT "If you choose to end the program immediately, you will lose any unsaved data. To end the program now, click End Now.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/es-ES.rc b/win32ss/user/winsrv/usersrv/lang/es-ES.rc index 781b485f5e..d502b8e19f 100644 --- a/win32ss/user/winsrv/usersrv/lang/es-ES.rc +++ b/win32ss/user/winsrv/usersrv/lang/es-ES.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "Para volver a ReactOS y ver el estado del programa, haga clic en Cancelar.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Si elige finalizar el programa ahora, perderá todos los datos no guardados. Para finalizar el programa ahora, haga clic en Finalizar ahora.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/fr-FR.rc b/win32ss/user/winsrv/usersrv/lang/fr-FR.rc index 9edf599095..94fcabb2b9 100644 --- a/win32ss/user/winsrv/usersrv/lang/fr-FR.rc +++ b/win32ss/user/winsrv/usersrv/lang/fr-FR.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "Pour retourner à ReactOS et vérifier l'état du programme, cliquez sur Annuler.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Si vous choisissez de terminer le programme immédiatement, vous perdrez toutes les données non sauvegardées. Pour terminer le programme maintenant, cliquez sur Terminer maintenant.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Succès" + IDS_SEVERITY_INFORMATIONAL "Information système" + IDS_SEVERITY_WARNING "Avertissement système" + IDS_SEVERITY_ERROR "Erreur système" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "Processus système" + IDS_UNKNOWN_SOFTWARE_EXCEPT "Exception logicielle inconnue" + IDS_OK_TERMINATE_PROGRAM "Cliquez sur OK pour terminer le programme." + IDS_CANCEL_DEBUG_PROGRAM "Cliquez sur Annuler pour déboguer le programme." +END diff --git a/win32ss/user/winsrv/usersrv/lang/he-IL.rc b/win32ss/user/winsrv/usersrv/lang/he-IL.rc index 096191dbbc..50ec399ea9 100644 --- a/win32ss/user/winsrv/usersrv/lang/he-IL.rc +++ b/win32ss/user/winsrv/usersrv/lang/he-IL.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "כדי לחזור לReactOS ולבדוק את מצב התכנית, לחץ ביטול.", IDC_STATIC, 7, 26, 178, 16 LTEXT "אם תבחר לסיים את התכנית באופן מיידי, אתה תאבד את כל המידע שלא נשמר. כדי לסיים את התכנית עכשיו, לחץ סיים כעת.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/id-ID.rc b/win32ss/user/winsrv/usersrv/lang/id-ID.rc index 5e39167d4b..6a67e699c4 100644 --- a/win32ss/user/winsrv/usersrv/lang/id-ID.rc +++ b/win32ss/user/winsrv/usersrv/lang/id-ID.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "Untuk kembali ke ReactOS dan memeriksa status program, klik Batal.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Jika anda memilih untuk segera mengakhiri program, anda akan kehilangan data yang belum disimpan. Untuk mengakhiri program sekarang, klik Akhiri Sekarang.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/it-IT.rc b/win32ss/user/winsrv/usersrv/lang/it-IT.rc index 031887167a..7a2354fcf6 100644 --- a/win32ss/user/winsrv/usersrv/lang/it-IT.rc +++ b/win32ss/user/winsrv/usersrv/lang/it-IT.rc @@ -30,3 +30,20 @@ BEGIN LTEXT "Per tornare a ReactOS e controllare lo stato del programma, selezionare Annulla.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Se si sceglie di terminare il programma immediatamente, si perderanno tutti i dati non salvati. Per terminare il programma ora, selezionare Termina ora.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/ja-JP.rc b/win32ss/user/winsrv/usersrv/lang/ja-JP.rc index 2ac22bdb20..8bb5252d13 100644 --- a/win32ss/user/winsrv/usersrv/lang/ja-JP.rc +++ b/win32ss/user/winsrv/usersrv/lang/ja-JP.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "ReactOS に戻ってプログラムの状態を確認するには[キャンセル]をクリックしてください", IDC_STATIC, 7, 26, 178, 16 LTEXT "プログラムをすぐに終了させるよう選択した場合、保存されていないデータはすべて失われます。プログラムを直ちに終了するには[すぐに終了]をクリックしてください", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/no-NO.rc b/win32ss/user/winsrv/usersrv/lang/no-NO.rc index f8d0c3a1d4..a942692ef3 100644 --- a/win32ss/user/winsrv/usersrv/lang/no-NO.rc +++ b/win32ss/user/winsrv/usersrv/lang/no-NO.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "For å returnere til ReactOS for å sjekke statusen på programmet, trykk på avbryt.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Hvis du velger å avslutte programmet øyeblikkelig, vil du miste alt data som ikke er lagret. For å avslutte programmet nå, Trykk på Avslutt nå.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/pl-PL.rc b/win32ss/user/winsrv/usersrv/lang/pl-PL.rc index 539e0a1b27..5f9dd73401 100644 --- a/win32ss/user/winsrv/usersrv/lang/pl-PL.rc +++ b/win32ss/user/winsrv/usersrv/lang/pl-PL.rc @@ -30,3 +30,20 @@ BEGIN LTEXT "Aby powrócić do ReactOS i sprawdzić status programu, kliknij Anuluj.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Jeśli zdecydujesz się zamknąć program natychmiastowo, utracisz wszelkie niezapisane dane. Aby zakończyć program, wciśnij Zakończ teraz.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/pt-BR.rc b/win32ss/user/winsrv/usersrv/lang/pt-BR.rc index 4b7b520f4c..320cc195d7 100644 --- a/win32ss/user/winsrv/usersrv/lang/pt-BR.rc +++ b/win32ss/user/winsrv/usersrv/lang/pt-BR.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "Parar retornar ao ReactOS e verificar o estado do programa, pressione Cancelar.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Se você finalizar o programa imediatamente, você irá perder qualquer alteração não salva. Para finalizar o programa agora, pressione Finalizar Agora.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/ro-RO.rc b/win32ss/user/winsrv/usersrv/lang/ro-RO.rc index 2b802fc8dc..9ad34941d2 100644 --- a/win32ss/user/winsrv/usersrv/lang/ro-RO.rc +++ b/win32ss/user/winsrv/usersrv/lang/ro-RO.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "Pentru a vă întoarce în ReactOS și a verifica starea programului, apăsați „Anulează”.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Dacă alegeți închiderea imediată a programului, riscați pierderi de date. Pentru a forța închiderea, apăsați „Termină forțat”.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/ru-RU.rc b/win32ss/user/winsrv/usersrv/lang/ru-RU.rc index 799da0aab7..0e54451831 100644 --- a/win32ss/user/winsrv/usersrv/lang/ru-RU.rc +++ b/win32ss/user/winsrv/usersrv/lang/ru-RU.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "Для возврата в ReactOS и проверки состояния приложения нажмите ""Отмена"".", IDC_STATIC, 7, 26, 178, 16 LTEXT "Если вы завершите программу сейчас, то вы можете потерять несохраненные данные. Чтобы завершить программу сейчас нажмите ""Завершить"".", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/sk-SK.rc b/win32ss/user/winsrv/usersrv/lang/sk-SK.rc index 6f3f14f8a4..672a571dc9 100644 --- a/win32ss/user/winsrv/usersrv/lang/sk-SK.rc +++ b/win32ss/user/winsrv/usersrv/lang/sk-SK.rc @@ -27,3 +27,20 @@ BEGIN LTEXT "Pre návrat do systému ReactOS a overenie stavu programu kliknite na tlačidlo Zrušiť.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Ak zvolíte okamžité ukončenie programu, stratíte všetky neuložené údaje. Ak chcete program ukončiť okamžite, kliknite na tlačidlo Ukončiť ihneď.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/sv-SE.rc b/win32ss/user/winsrv/usersrv/lang/sv-SE.rc index 418e45e7b2..925daf2f23 100644 --- a/win32ss/user/winsrv/usersrv/lang/sv-SE.rc +++ b/win32ss/user/winsrv/usersrv/lang/sv-SE.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "För att återgå till ReactOS och undersöka programmets status klicka Avbryt.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Om du väljer att avsluta programmet omedelbart kommer du att förlora all osparad data. För att avsluta programmet, klicka Avsluta nu.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/tr-TR.rc b/win32ss/user/winsrv/usersrv/lang/tr-TR.rc index 4645381471..72cd661da9 100644 --- a/win32ss/user/winsrv/usersrv/lang/tr-TR.rc +++ b/win32ss/user/winsrv/usersrv/lang/tr-TR.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "ReactOS'a dönmek ve programın durumunu denetlemek için İptal'e tıklayınız.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Programı hemen kapatmayı seçerseniz, tüm saklanmamış veriyi yitireceksiniz. Programdan şimdi çıkmak için Şimdi Sonlandır'a tıklayınız.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/uk-UA.rc b/win32ss/user/winsrv/usersrv/lang/uk-UA.rc index acd1a2e046..3104e91127 100644 --- a/win32ss/user/winsrv/usersrv/lang/uk-UA.rc +++ b/win32ss/user/winsrv/usersrv/lang/uk-UA.rc @@ -24,3 +24,20 @@ BEGIN LTEXT "Щоб повернутися у ReactOS і перевірити стан програми, натисніть 'Скасувати'.", IDC_STATIC, 7, 26, 178, 16 LTEXT "Якщо завершити програму негайно, то можна втратити всі незбережені дані. Щоб завершити програму зараз, натисніть 'Завершити зараз'.", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/zh-CN.rc b/win32ss/user/winsrv/usersrv/lang/zh-CN.rc index c22137e50a..69b39c6e65 100644 --- a/win32ss/user/winsrv/usersrv/lang/zh-CN.rc +++ b/win32ss/user/winsrv/usersrv/lang/zh-CN.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "若要返回至 ReactOS 并检查该程序的状态,请点击“取消”。", IDC_STATIC, 7, 26, 178, 16 LTEXT "如果您选择立即终止程序,您将失去所有未保存的数据。若要立即结束程序,单击“立即终止”。", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/lang/zh-TW.rc b/win32ss/user/winsrv/usersrv/lang/zh-TW.rc index 8cf9dfa513..3fdf105aff 100644 --- a/win32ss/user/winsrv/usersrv/lang/zh-TW.rc +++ b/win32ss/user/winsrv/usersrv/lang/zh-TW.rc @@ -22,3 +22,20 @@ BEGIN LTEXT "若要返回至 ReactOS 並檢視程式的狀態,請按下“取消”", IDC_STATIC, 7, 26, 178, 16 LTEXT "如果您選擇立即結束程式,您將失去所有未儲存的資料。若要立即結束程式,請按下“立即結束”。", IDC_STATIC, 7, 53, 178, 26 END + + +STRINGTABLE +BEGIN + IDS_SEVERITY_SUCCESS "Success" + IDS_SEVERITY_INFORMATIONAL "System Information" + IDS_SEVERITY_WARNING "System Warning" + IDS_SEVERITY_ERROR "System Error" +END + +STRINGTABLE +BEGIN + IDS_SYSTEM_PROCESS "System Process" + IDS_UNKNOWN_SOFTWARE_EXCEPT "unknown software exception" + IDS_OK_TERMINATE_PROGRAM "Click on OK to terminate the program." + IDS_CANCEL_DEBUG_PROGRAM "Click on CANCEL to debug the program." +END diff --git a/win32ss/user/winsrv/usersrv/resource.h b/win32ss/user/winsrv/usersrv/resource.h index 187dca1134..670b20116f 100644 --- a/win32ss/user/winsrv/usersrv/resource.h +++ b/win32ss/user/winsrv/usersrv/resource.h @@ -1,8 +1,8 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS User API Server DLL - * FILE: win32ss/user/winsrv/usersrv/resource.h - * PURPOSE: Resource #defines + * PROJECT: ReactOS User API Server DLL + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Resource #defines. + * COPYRIGHT: Copyright 2012-2018 Hermes Belusca-Maito */ #pragma once @@ -12,5 +12,16 @@ #define IDC_STATIC -1 -#define IDC_PROGRESS 101 -#define IDC_END_NOW 102 +#define IDC_PROGRESS 20 +#define IDC_END_NOW 21 + +/* Strings */ +#define IDS_SEVERITY_SUCCESS 100 +#define IDS_SEVERITY_INFORMATIONAL 101 +#define IDS_SEVERITY_WARNING 102 +#define IDS_SEVERITY_ERROR 103 + +#define IDS_SYSTEM_PROCESS 104 +#define IDS_UNKNOWN_SOFTWARE_EXCEPT 105 +#define IDS_OK_TERMINATE_PROGRAM 106 +#define IDS_CANCEL_DEBUG_PROGRAM 107 diff --git a/win32ss/user/winsrv/usersrv/shutdown.c b/win32ss/user/winsrv/usersrv/shutdown.c index f8d5329652..5c2f464f84 100644 --- a/win32ss/user/winsrv/usersrv/shutdown.c +++ b/win32ss/user/winsrv/usersrv/shutdown.c @@ -413,18 +413,6 @@ ConioConsoleCtrlEventTimeout(DWORD Event, PCSR_PROCESS ProcessData, DWORD Timeou /************************************************/ -static BOOL CALLBACK -FindTopLevelWnd(IN HWND hWnd, - IN LPARAM lParam) -{ - if (GetWindow(hWnd, GW_OWNER) == NULL) - { - *(HWND*)lParam = hWnd; - return FALSE; - } - return TRUE; -} - static VOID ThreadShutdownNotify(IN PCSR_THREAD CsrThread, IN ULONG Flags, diff --git a/win32ss/user/winsrv/usersrv/usersrv.h b/win32ss/user/winsrv/usersrv/usersrv.h index bb281e65de..76ed26925b 100644 --- a/win32ss/user/winsrv/usersrv/usersrv.h +++ b/win32ss/user/winsrv/usersrv/usersrv.h @@ -33,4 +33,12 @@ extern HANDLE UserServerHeap; extern ULONG_PTR ServicesProcessId; extern ULONG_PTR LogonProcessId; +BOOL CALLBACK +FindTopLevelWnd( + IN HWND hWnd, + IN LPARAM lParam); + +VOID +UserInitHardErrorsCache(VOID); + #endif /* __USERSRV_H__ */
6 years, 8 months
1
0
0
0
03/08: [USERSRV] Hard-error improvements 2/7 - More failure path handling.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2b299f5fec3067b6bc1c5…
commit 2b299f5fec3067b6bc1c5795f9efe3a35b158fd6 Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sun Mar 4 17:39:44 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Apr 7 18:48:08 2018 +0200 [USERSRV] Hard-error improvements 2/7 - More failure path handling. In particular do not always fail as soon as there is an error, because they may be the sign of an OS problem and this is precisely in this case that we want to display a hard-error. --- win32ss/user/winsrv/usersrv/harderror.c | 284 +++++++++++++++++++------------- 1 file changed, 167 insertions(+), 117 deletions(-) diff --git a/win32ss/user/winsrv/usersrv/harderror.c b/win32ss/user/winsrv/usersrv/harderror.c index 9889a54d85..19a8db644f 100644 --- a/win32ss/user/winsrv/usersrv/harderror.c +++ b/win32ss/user/winsrv/usersrv/harderror.c @@ -26,6 +26,18 @@ /* FUNCTIONS ******************************************************************/ +/* FIXME */ +int +WINAPI +MessageBoxTimeoutW( + HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType, + WORD wLanguageId, + DWORD dwTime); + + static NTSTATUS UserpGetClientFileName( @@ -43,9 +55,7 @@ UserpGetClientFileName( PPEB Peb; /* Initialize string */ - ClientFileNameU->MaximumLength = 0; - ClientFileNameU->Length = 0; - ClientFileNameU->Buffer = NULL; + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); /* Query process information */ Status = NtQueryInformationProcess(hProcess, @@ -55,6 +65,8 @@ UserpGetClientFileName( NULL); if (!NT_SUCCESS(Status)) return Status; + /* Locate the process loader data table and retrieve its name from it */ + Peb = ClientBasicInfo.PebBaseAddress; if (!Peb) return STATUS_UNSUCCESSFUL; @@ -91,8 +103,13 @@ UserpGetClientFileName( ClientFileNameU->MaximumLength = ModuleData.BaseDllName.MaximumLength; ClientFileNameU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - ClientFileNameU->MaximumLength); + HEAP_ZERO_MEMORY, + ClientFileNameU->MaximumLength); + if (!ClientFileNameU->Buffer) + { + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); + return STATUS_NO_MEMORY; + } Status = NtReadVirtualMemory(hProcess, ModuleData.BaseDllName.Buffer, @@ -102,13 +119,12 @@ UserpGetClientFileName( if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, ClientFileNameU->Buffer); - ClientFileNameU->Buffer = NULL; - ClientFileNameU->MaximumLength = 0; + RtlInitEmptyUnicodeString(ClientFileNameU, NULL, 0); return Status; } ClientFileNameU->Length = wcslen(ClientFileNameU->Buffer) * sizeof(WCHAR); - DPRINT("ClientFileNameU=\'%wZ\'\n", &ClientFileNameU); + DPRINT("ClientFileNameU = \'%wZ\'\n", &ClientFileNameU); return STATUS_SUCCESS; } @@ -125,7 +141,7 @@ UserpFreeStringParameters( for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) { /* Check if the current parameter is a string */ - if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && Parameters[nParam]) + if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && (Parameters[nParam] != 0)) { /* Free the string buffer */ RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); @@ -139,10 +155,10 @@ UserpCaptureStringParameters( OUT PULONG_PTR Parameters, OUT PULONG SizeOfAllUnicodeStrings, IN PHARDERROR_MSG HardErrorMessage, - IN HANDLE hProcess) + IN HANDLE hProcess OPTIONAL) { - ULONG nParam, Size = 0; NTSTATUS Status = STATUS_SUCCESS; + ULONG nParam, Size = 0; UNICODE_STRING TempStringU, ParamStringU; ANSI_STRING TempStringA; @@ -157,6 +173,10 @@ UserpCaptureStringParameters( /* Check if the current parameter is a unicode string */ if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) { + /* Skip this string if we do not have a client process */ + if (!hProcess) + continue; + /* Read the UNICODE_STRING from the process memory */ Status = NtReadVirtualMemory(hProcess, (PVOID)HardErrorMessage->Parameters[nParam], @@ -164,7 +184,11 @@ UserpCaptureStringParameters( sizeof(ParamStringU), NULL); if (!NT_SUCCESS(Status)) - break; + { + /* We failed, skip this string */ + DPRINT1("NtReadVirtualMemory(HardErrorMessage->Parameters) failed, Status 0x%lx\n", Status); + continue; + } /* Allocate a buffer for the string */ TempStringU.MaximumLength = ParamStringU.Length; @@ -174,8 +198,10 @@ UserpCaptureStringParameters( TempStringU.MaximumLength); if (!TempStringU.Buffer) { - DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength); + /* We failed, skip this string */ + DPRINT1("Cannot allocate memory with size %u\n", TempStringU.MaximumLength); Status = STATUS_NO_MEMORY; + continue; } /* Read the string buffer from the process memory */ @@ -186,12 +212,13 @@ UserpCaptureStringParameters( NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("NtReadVirtualMemory failed with code: %lx\n", Status); + /* We failed, skip this string */ + DPRINT1("NtReadVirtualMemory(ParamStringU) failed, Status 0x%lx\n", Status); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); - break; + continue; } - DPRINT("ParamString=\'%wZ\'\n", &TempStringU); + DPRINT("ParamString = \'%wZ\'\n", &TempStringU); /* Allocate a buffer for converted to ANSI string */ TempStringA.MaximumLength = RtlUnicodeStringToAnsiSize(&TempStringU); @@ -200,10 +227,11 @@ UserpCaptureStringParameters( TempStringA.MaximumLength); if (!TempStringA.Buffer) { - DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength); + /* We failed, skip this string */ + DPRINT1("Cannot allocate memory with size %u\n", TempStringA.MaximumLength); RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); Status = STATUS_NO_MEMORY; - break; + continue; } /* Convert string to ANSI and free temporary buffer */ @@ -211,8 +239,9 @@ UserpCaptureStringParameters( RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringU.Buffer); if (!NT_SUCCESS(Status)) { + /* We failed, skip this string */ RtlFreeHeap(RtlGetProcessHeap(), 0, TempStringA.Buffer); - break; + continue; } /* Note: RtlUnicodeStringToAnsiString returns NULL terminated string */ @@ -221,16 +250,18 @@ UserpCaptureStringParameters( } else { - /* It's not a unicode string */ + /* It's not a unicode string, just copy the parameter */ Parameters[nParam] = HardErrorMessage->Parameters[nParam]; } } +#if 0 if (!NT_SUCCESS(Status)) { UserpFreeStringParameters(Parameters, HardErrorMessage); return Status; } +#endif if (SizeOfAllUnicodeStrings) *SizeOfAllUnicodeStrings = Size; @@ -246,24 +277,33 @@ UserpFormatMessages( IN PULONG_PTR Parameters, IN ULONG SizeOfStrings, IN PHARDERROR_MSG Message, - IN HANDLE hProcess) + IN HANDLE hProcess OPTIONAL) { NTSTATUS Status; UNICODE_STRING FileNameU, TempStringU, FormatU, Format2U; ANSI_STRING FormatA, Format2A; PMESSAGE_RESOURCE_ENTRY MessageResource; + ULONG_PTR CapturedParameters[MAXIMUM_HARDERROR_PARAMETERS]; PWSTR FormatString; ULONG ExceptionCode, Severity; ULONG Size; - /* Get the file name of the client process */ - UserpGetClientFileName(&FileNameU, hProcess); + /* Copy the Parameters array locally */ + RtlCopyMemory(&CapturedParameters, Parameters, sizeof(CapturedParameters)); - /* Check if we have a file name */ - if (!FileNameU.Buffer) + /* Get the file name of the client process */ + Status = STATUS_SUCCESS; + if (hProcess) + Status = UserpGetClientFileName(&FileNameU, hProcess); + + /* + * Fall back to SYSTEM process if the client process handle + * was NULL or we failed retrieving a file name. + */ + if (!hProcess || !NT_SUCCESS(Status) || !FileNameU.Buffer) { - /* No, this is system process */ RtlInitUnicodeString(&FileNameU, L"System Process"); + hProcess = NULL; } Severity = (ULONG)(Message->Status) >> 30; @@ -334,8 +374,13 @@ UserpFormatMessages( /* Allocate a buffer for the caption */ CaptionStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), - HEAP_ZERO_MEMORY, - CaptionStringU->MaximumLength); + HEAP_ZERO_MEMORY, + CaptionStringU->MaximumLength); + if (!CaptionStringU->Buffer) + { + DPRINT1("Cannot allocate memory for CaptionStringU\n"); + Status = STATUS_NO_MEMORY; + } /* Append the file name, seperator and the caption text */ CaptionStringU->Length = 0; @@ -355,7 +400,7 @@ UserpFormatMessages( /* Check if this is an exception message */ if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { - ExceptionCode = Parameters[0]; + ExceptionCode = CapturedParameters[0]; /* Get text string of the exception code */ Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), @@ -376,30 +421,30 @@ UserpFormatMessages( RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE); } - /* Handle the special cases */ + /* Handle special cases */ if (ExceptionCode == STATUS_ACCESS_VIOLATION) { - FormatString = Format2U.Buffer; - Parameters[0] = Parameters[1]; - Parameters[1] = Parameters[3]; - if (Parameters[2]) - Parameters[2] = (ULONG_PTR)L"written"; + FormatString = Format2U.Buffer; + CapturedParameters[0] = CapturedParameters[1]; + CapturedParameters[1] = CapturedParameters[3]; + if (CapturedParameters[2]) + CapturedParameters[2] = (ULONG_PTR)L"written"; else - Parameters[2] = (ULONG_PTR)L"read"; + CapturedParameters[2] = (ULONG_PTR)L"read"; } else if (ExceptionCode == STATUS_IN_PAGE_ERROR) { - FormatString = Format2U.Buffer; - Parameters[0] = Parameters[1]; - Parameters[1] = Parameters[3]; + FormatString = Format2U.Buffer; + CapturedParameters[0] = CapturedParameters[1]; + CapturedParameters[1] = CapturedParameters[3]; } else { PWSTR pTmp; /* Keep the existing FormatString */ - Parameters[2] = Parameters[1]; - Parameters[1] = Parameters[0]; + CapturedParameters[2] = CapturedParameters[1]; + CapturedParameters[1] = CapturedParameters[0]; pTmp = Format2U.Buffer; if (!_wcsnicmp(pTmp, L"{EXCEPTION}", 11)) @@ -413,21 +458,21 @@ UserpFormatMessages( /* Skip '\r', '\n' */ pTmp += 2; - Parameters[0] = (ULONG_PTR)pTmp; + CapturedParameters[0] = (ULONG_PTR)pTmp; } else { /* Fall back to hardcoded value */ - Parameters[0] = (ULONG_PTR)L"unknown software exception"; + CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; } } } else { /* Fall back to hardcoded value, and keep the existing FormatString */ - Parameters[2] = Parameters[1]; - Parameters[1] = Parameters[0]; - Parameters[0] = (ULONG_PTR)L"unknown software exception"; + CapturedParameters[2] = CapturedParameters[1]; + CapturedParameters[1] = CapturedParameters[0]; + CapturedParameters[0] = (ULONG_PTR)L"unknown software exception"; } /* FIXME: Use localized strings! */ @@ -437,7 +482,7 @@ UserpFormatMessages( // Tmp = FormatString + wcslen(FormatString); // *++Tmp = L'\n'; // *++Tmp = L'\n'; - Size += 2 + wcslen(L"Click on OK to terminate the program."); + Size += 1 + wcslen(L"Click on OK to terminate the program."); } if (Message->ValidResponseOptions == OptionOkCancel) { @@ -454,6 +499,11 @@ UserpFormatMessages( TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TextStringU->MaximumLength); + if (!TextStringU->Buffer) + { + DPRINT1("Cannot allocate memory for TextStringU\n"); + Status = STATUS_NO_MEMORY; + } /* Wrap in SEH to protect from invalid string parameters */ _SEH2_TRY @@ -462,10 +512,10 @@ UserpFormatMessages( RtlStringCbPrintfW(TextStringU->Buffer, TextStringU->MaximumLength, FormatString, - Parameters[0], - Parameters[1], - Parameters[2], - Parameters[3]); + CapturedParameters[0], + CapturedParameters[1], + CapturedParameters[2], + CapturedParameters[3]); if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { @@ -478,13 +528,16 @@ UserpFormatMessages( // *++Tmp = L'\n'; RtlStringCbCatW(TextStringU->Buffer, TextStringU->MaximumLength, - L"\n\n"); + L"\n"); RtlStringCbCatW(TextStringU->Buffer, TextStringU->MaximumLength, L"Click on OK to terminate the program."); } if (Message->ValidResponseOptions == OptionOkCancel) { + RtlStringCbCatW(TextStringU->Buffer, + TextStringU->MaximumLength, + L"\n"); RtlStringCbCatW(TextStringU->Buffer, TextStringU->MaximumLength, L"Click on CANCEL to debug the program."); @@ -498,16 +551,16 @@ UserpFormatMessages( /* An exception occurred, use a default string */ RtlStringCbPrintfW(TextStringU->Buffer, TextStringU->MaximumLength, - L"Exception processing message 0x%lx\n" - L"Parameters 0x%lx 0x%lx 0x%lx 0x%lx", + L"Exception processing message 0x%08lx\n" + L"Parameters: 0x%p 0x%p 0x%p 0x%p", Message->Status, - Parameters[0], Parameters[1], - Parameters[2], Parameters[3]); + CapturedParameters[0], CapturedParameters[1], + CapturedParameters[2], CapturedParameters[3]); /* Set error and free buffers */ - Status = _SEH2_GetExceptionCode(); - RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); - RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); + // Status = _SEH2_GetExceptionCode(); + // RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); + // RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); } _SEH2_END; @@ -523,6 +576,54 @@ UserpFormatMessages( return Status; } +static ULONG +GetRegInt( + IN PCWSTR KeyName, + IN PCWSTR ValueName, + IN ULONG DefaultValue) +{ + NTSTATUS Status; + ULONG Value = DefaultValue; + UNICODE_STRING String; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + ULONG ResultLength; + UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; + + RtlInitUnicodeString(&String, KeyName); + InitializeObjectAttributes(&ObjectAttributes, + &String, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the registry key */ + Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* Query the value */ + RtlInitUnicodeString(&String, ValueName); + Status = NtQueryValueKey(KeyHandle, + &String, + KeyValuePartialInformation, + ValueInfo, + sizeof(ValueBuffer), + &ResultLength); + + /* Close the registry key */ + NtClose(KeyHandle); + + if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD)) + { + /* Directly retrieve the data */ + Value = *(PULONG)ValueInfo->Data; + } + } + + return Value; +} + static BOOL UserpShowInformationBalloon(PWSTR Text, PWSTR Caption, @@ -596,55 +697,6 @@ UserpShowInformationBalloon(PWSTR Text, return (ret && dwResult) ? TRUE : FALSE; } - -static ULONG -GetRegInt( - IN PCWSTR KeyName, - IN PCWSTR ValueName, - IN ULONG DefaultValue) -{ - NTSTATUS Status; - ULONG Value = DefaultValue; - UNICODE_STRING String; - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE KeyHandle; - ULONG ResultLength; - UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; - PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; - - RtlInitUnicodeString(&String, KeyName); - InitializeObjectAttributes(&ObjectAttributes, - &String, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Open the registry key */ - Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); - if (NT_SUCCESS(Status)) - { - /* Query the value */ - RtlInitUnicodeString(&String, ValueName); - Status = NtQueryValueKey(KeyHandle, - &String, - KeyValuePartialInformation, - ValueInfo, - sizeof(ValueBuffer), - &ResultLength); - - /* Close the registry key */ - NtClose(KeyHandle); - - if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD)) - { - /* Directly retrieve the data */ - Value = *(PULONG)ValueInfo->Data; - } - } - - return Value; -} - static ULONG UserpMessageBox( @@ -799,29 +851,27 @@ UserServerHardError( } // TODO: More message validation: check NumberOfParameters wrt. Message Status code. - /* Initialize object attributes */ - InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); - /* Open client process */ + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); Status = NtOpenProcess(&hProcess, PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, &ObjectAttributes, &Message->h.ClientId); if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenProcess failed with status 0x%08lx\n", Status); - return; + DPRINT1("NtOpenProcess failed with status 0x%08lx, possibly SYSTEM process.\n", Status); + hProcess = NULL; } /* Capture all string parameters from the process memory */ Status = UserpCaptureStringParameters(Parameters, &Size, Message, hProcess); if (!NT_SUCCESS(Status)) { - NtClose(hProcess); + if (hProcess) NtClose(hProcess); return; } - /* Format the caption and message box text */ + /* Format the message caption and text */ Status = UserpFormatMessages(&TextU, &CaptionU, Parameters, @@ -831,7 +881,7 @@ UserServerHardError( /* Cleanup */ UserpFreeStringParameters(Parameters, Message); - NtClose(hProcess); + if (hProcess) NtClose(hProcess); /* If we failed, bail out */ if (!NT_SUCCESS(Status)) @@ -846,7 +896,7 @@ UserServerHardError( ErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows", L"ErrorMode", 0); - if (ErrorMode != 0) + if (Message->Status != STATUS_SERVICE_NOTIFICATION && ErrorMode != 0) { /* Returns OK for the hard error */ Message->Response = ResponseOk;
6 years, 8 months
1
0
0
0
02/08: [USERSRV] Hard-error improvements 1/7
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6718a1aa83217585a9241…
commit 6718a1aa83217585a9241a75e56e0d24a4a769dc Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sat Mar 24 21:26:20 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Apr 7 18:48:06 2018 +0200 [USERSRV] Hard-error improvements 1/7 - Use hard-error captions depending on the status code severity. - Improve handling of the STATUS_UNHANDLED_EXCEPTION error. Start implementing the display of the dialog button descriptions ("OK" to terminate the application; "Cancel" to debug the application). - Add support for the "ErrorMode" and "ShellErrorMode" registry values under HKLM\System\CurrentControlSet\Control\Windows. - Use MessageBoxTimeoutW() in UserpMessageBox() to support different message box timeouts. - Log hard errors into the System event log. --- win32ss/user/winsrv/usersrv/harderror.c | 416 ++++++++++++++++++++++++-------- 1 file changed, 313 insertions(+), 103 deletions(-) diff --git a/win32ss/user/winsrv/usersrv/harderror.c b/win32ss/user/winsrv/usersrv/harderror.c index 54d4b52764..9889a54d85 100644 --- a/win32ss/user/winsrv/usersrv/harderror.c +++ b/win32ss/user/winsrv/usersrv/harderror.c @@ -1,19 +1,22 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS User API Server DLL - * FILE: win32ss/user/winsrv/usersrv/harderror.c - * PURPOSE: Hard errors - * PROGRAMMERS: Dmitry Philippov (shedon(a)mail.ru) - * Timo Kreuzer (timo.kreuzer(a)reactos.org) + * PROJECT: ReactOS User API Server DLL + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Hard errors support. + * COPYRIGHT: Copyright 2007-2018 Dmitry Philippov (shedon(a)mail.ru) + * Copyright 2010-2018 Timo Kreuzer (timo.kreuzer(a)reactos.org) + * Copyright 2012-2018 Hermes Belusca-Maito + * Copyright 2018 Giannis Adamopoulos */ /* INCLUDES *******************************************************************/ #include "usersrv.h" +#define NTOS_MODE_USER #include <ndk/mmfuncs.h> -#include <pseh/pseh2.h> -#include <strsafe.h> + +#include <undocelfapi.h> +#include <ntstrsafe.h> #define NDEBUG #include <debug.h> @@ -27,7 +30,7 @@ static NTSTATUS UserpGetClientFileName( OUT PUNICODE_STRING ClientFileNameU, - HANDLE hProcess) + IN HANDLE hProcess) { PLIST_ENTRY ModuleListHead; PLIST_ENTRY Entry; @@ -122,7 +125,7 @@ UserpFreeStringParameters( for (nParam = 0; nParam < HardErrorMessage->NumberOfParameters; nParam++) { /* Check if the current parameter is a string */ - if (HardErrorMessage->UnicodeStringParameterMask & (1 << nParam) && Parameters[nParam]) + if ((HardErrorMessage->UnicodeStringParameterMask & (1 << nParam)) && Parameters[nParam]) { /* Free the string buffer */ RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)Parameters[nParam]); @@ -136,7 +139,7 @@ UserpCaptureStringParameters( OUT PULONG_PTR Parameters, OUT PULONG SizeOfAllUnicodeStrings, IN PHARDERROR_MSG HardErrorMessage, - HANDLE hProcess) + IN HANDLE hProcess) { ULONG nParam, Size = 0; NTSTATUS Status = STATUS_SUCCESS; @@ -169,7 +172,6 @@ UserpCaptureStringParameters( TempStringU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TempStringU.MaximumLength); - if (!TempStringU.Buffer) { DPRINT1("Cannot allocate memory %u\n", TempStringU.MaximumLength); @@ -196,7 +198,6 @@ UserpCaptureStringParameters( TempStringA.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TempStringA.MaximumLength); - if (!TempStringA.Buffer) { DPRINT1("Cannot allocate memory %u\n", TempStringA.MaximumLength); @@ -248,11 +249,12 @@ UserpFormatMessages( IN HANDLE hProcess) { NTSTATUS Status; - UNICODE_STRING FileNameU, TempStringU, FormatU; - ANSI_STRING FormatA; + UNICODE_STRING FileNameU, TempStringU, FormatU, Format2U; + ANSI_STRING FormatA, Format2A; PMESSAGE_RESOURCE_ENTRY MessageResource; PWSTR FormatString; - ULONG Size, ExceptionCode; + ULONG ExceptionCode, Severity; + ULONG Size; /* Get the file name of the client process */ UserpGetClientFileName(&FileNameU, hProcess); @@ -260,10 +262,12 @@ UserpFormatMessages( /* Check if we have a file name */ if (!FileNameU.Buffer) { - /* No, use system */ - RtlInitUnicodeString(&FileNameU, L"System"); + /* No, this is system process */ + RtlInitUnicodeString(&FileNameU, L"System Process"); } + Severity = (ULONG)(Message->Status) >> 30; + /* Get text string of the error code */ Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), (ULONG_PTR)RT_MESSAGETABLE, @@ -299,19 +303,29 @@ UserpFormatMessages( TempStringU.Buffer = ++FormatString; /* Get size of the caption */ - for (Size = 0; *FormatString != 0 && *FormatString != L'}'; Size++) + for (Size = 0; *FormatString != UNICODE_NULL && *FormatString != L'}'; Size++) FormatString++; /* Skip '}', '\r', '\n' */ FormatString += 3; - TempStringU.Length = Size * sizeof(WCHAR); + TempStringU.Length = (USHORT)(Size * sizeof(WCHAR)); TempStringU.MaximumLength = TempStringU.Length; } else { - /* FIXME: Set string based on severity */ - RtlInitUnicodeString(&TempStringU, L"Application Error"); + /* FIXME: Use localized strings! */ + + if (Severity == STATUS_SEVERITY_SUCCESS) + RtlInitUnicodeString(&TempStringU, L"Success"); + else if (Severity == STATUS_SEVERITY_INFORMATIONAL) + RtlInitUnicodeString(&TempStringU, L"System Information"); + else if (Severity == STATUS_SEVERITY_WARNING) + RtlInitUnicodeString(&TempStringU, L"System Warning"); + else if (Severity == STATUS_SEVERITY_ERROR) + RtlInitUnicodeString(&TempStringU, L"System Error"); + else + RtlInitEmptyUnicodeString(&TempStringU, NULL, 0); } /* Calculate buffer length for the caption */ @@ -330,77 +344,111 @@ UserpFormatMessages( RtlAppendUnicodeStringToString(CaptionStringU, &TempStringU); /* Zero terminate the buffer */ - CaptionStringU->Buffer[CaptionStringU->Length / sizeof(WCHAR)] = 0; + CaptionStringU->Buffer[CaptionStringU->Length / sizeof(WCHAR)] = UNICODE_NULL; /* Free the file name buffer */ RtlFreeUnicodeString(&FileNameU); + // FIXME: What is 42 == ?? + Size = 42; + /* Check if this is an exception message */ if (Message->Status == STATUS_UNHANDLED_EXCEPTION) { ExceptionCode = Parameters[0]; - /* Handle special cases */ - if (ExceptionCode == STATUS_ACCESS_VIOLATION) + /* Get text string of the exception code */ + Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), + (ULONG_PTR)RT_MESSAGETABLE, + LANG_NEUTRAL, + ExceptionCode, + &MessageResource); + if (NT_SUCCESS(Status)) { - Parameters[0] = Parameters[1]; - Parameters[1] = Parameters[3]; - if (Parameters[2]) - Parameters[2] = (ULONG_PTR)L"written"; + if (MessageResource->Flags) + { + RtlInitUnicodeString(&Format2U, (PWSTR)MessageResource->Text); + Format2A.Buffer = NULL; + } else - Parameters[2] = (ULONG_PTR)L"read"; - MessageResource = NULL; - } - else if (ExceptionCode == STATUS_IN_PAGE_ERROR) - { - Parameters[0] = Parameters[1]; - Parameters[1] = Parameters[3]; - MessageResource = NULL; - } - else - { - /* Fall back to hardcoded value */ - Parameters[2] = Parameters[1]; - Parameters[1] = Parameters[0]; - Parameters[0] = (ULONG_PTR)L"unknown software exception"; - } - - if (!MessageResource) - { - /* Get text string of the exception code */ - Status = RtlFindMessage(GetModuleHandleW(L"ntdll"), - (ULONG_PTR)RT_MESSAGETABLE, - LANG_NEUTRAL, - ExceptionCode, - &MessageResource); - if (NT_SUCCESS(Status)) { - if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); + RtlInitAnsiString(&Format2A, (PCHAR)MessageResource->Text); + RtlAnsiStringToUnicodeString(&Format2U, &Format2A, TRUE); + } - if (MessageResource->Flags) - { - RtlInitUnicodeString(&FormatU, (PWSTR)MessageResource->Text); - FormatA.Buffer = NULL; - } + /* Handle the special cases */ + if (ExceptionCode == STATUS_ACCESS_VIOLATION) + { + FormatString = Format2U.Buffer; + Parameters[0] = Parameters[1]; + Parameters[1] = Parameters[3]; + if (Parameters[2]) + Parameters[2] = (ULONG_PTR)L"written"; else - { - RtlInitAnsiString(&FormatA, (PCHAR)MessageResource->Text); - RtlAnsiStringToUnicodeString(&FormatU, &FormatA, TRUE); - } - FormatString = FormatU.Buffer; + Parameters[2] = (ULONG_PTR)L"read"; + } + else if (ExceptionCode == STATUS_IN_PAGE_ERROR) + { + FormatString = Format2U.Buffer; + Parameters[0] = Parameters[1]; + Parameters[1] = Parameters[3]; } else { - /* Fall back to hardcoded value */ + PWSTR pTmp; + + /* Keep the existing FormatString */ Parameters[2] = Parameters[1]; Parameters[1] = Parameters[0]; - Parameters[0] = (ULONG_PTR)L"unknown software exception"; + + pTmp = Format2U.Buffer; + if (!_wcsnicmp(pTmp, L"{EXCEPTION}", 11)) + { + /* + * This is a named exception. Skip the mark and + * retrieve the exception name that follows it. + */ + pTmp += 11; + + /* Skip '\r', '\n' */ + pTmp += 2; + + Parameters[0] = (ULONG_PTR)pTmp; + } + else + { + /* Fall back to hardcoded value */ + Parameters[0] = (ULONG_PTR)L"unknown software exception"; + } } } + else + { + /* Fall back to hardcoded value, and keep the existing FormatString */ + Parameters[2] = Parameters[1]; + Parameters[1] = Parameters[0]; + Parameters[0] = (ULONG_PTR)L"unknown software exception"; + } + + /* FIXME: Use localized strings! */ + if (Message->ValidResponseOptions == OptionOk || + Message->ValidResponseOptions == OptionOkCancel) + { + // Tmp = FormatString + wcslen(FormatString); + // *++Tmp = L'\n'; + // *++Tmp = L'\n'; + Size += 2 + wcslen(L"Click on OK to terminate the program."); + } + if (Message->ValidResponseOptions == OptionOkCancel) + { + Size += 1 + wcslen(L"Click on CANCEL to debug the program."); + } } /* Calculate length of text buffer */ - TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + 42 * sizeof(WCHAR); + TextStringU->MaximumLength = FormatU.Length + SizeOfStrings + + (USHORT)(Size * sizeof(WCHAR)) + + sizeof(UNICODE_NULL); /* Allocate a buffer for the text */ TextStringU->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), @@ -411,78 +459,124 @@ UserpFormatMessages( _SEH2_TRY { /* Print the string into the buffer */ - StringCbPrintfW(TextStringU->Buffer, - TextStringU->MaximumLength, - FormatString, - Parameters[0], - Parameters[1], - Parameters[2], - Parameters[3]); + RtlStringCbPrintfW(TextStringU->Buffer, + TextStringU->MaximumLength, + FormatString, + Parameters[0], + Parameters[1], + Parameters[2], + Parameters[3]); + + if (Message->Status == STATUS_UNHANDLED_EXCEPTION) + { + /* FIXME: Use localized strings! */ + if (Message->ValidResponseOptions == OptionOk || + Message->ValidResponseOptions == OptionOkCancel) + { + // Tmp = FormatString + wcslen(FormatString); + // *++Tmp = L'\n'; + // *++Tmp = L'\n'; + RtlStringCbCatW(TextStringU->Buffer, + TextStringU->MaximumLength, + L"\n\n"); + RtlStringCbCatW(TextStringU->Buffer, + TextStringU->MaximumLength, + L"Click on OK to terminate the program."); + } + if (Message->ValidResponseOptions == OptionOkCancel) + { + RtlStringCbCatW(TextStringU->Buffer, + TextStringU->MaximumLength, + L"Click on CANCEL to debug the program."); + } + } + Status = STATUS_SUCCESS; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + /* An exception occurred, use a default string */ + RtlStringCbPrintfW(TextStringU->Buffer, + TextStringU->MaximumLength, + L"Exception processing message 0x%lx\n" + L"Parameters 0x%lx 0x%lx 0x%lx 0x%lx", + Message->Status, + Parameters[0], Parameters[1], + Parameters[2], Parameters[3]); + /* Set error and free buffers */ Status = _SEH2_GetExceptionCode(); RtlFreeHeap(RtlGetProcessHeap(), 0, TextStringU->Buffer); RtlFreeHeap(RtlGetProcessHeap(), 0, CaptionStringU->Buffer); } - _SEH2_END + _SEH2_END; if (NT_SUCCESS(Status)) { TextStringU->Length = wcslen(TextStringU->Buffer) * sizeof(WCHAR); } + /* Free converted Unicode strings if the original format strings were Ansi */ + if (Format2A.Buffer) RtlFreeUnicodeString(&Format2U); if (FormatA.Buffer) RtlFreeUnicodeString(&FormatU); return Status; } static BOOL -UserpShowInformationBalloon(PWSTR Text, +UserpShowInformationBalloon(PWSTR Text, PWSTR Caption, PHARDERROR_MSG Message) { + ULONG ShellErrorMode; HWND hwnd; COPYDATASTRUCT CopyData; PBALLOON_HARD_ERROR_DATA pdata; - DWORD dwSize, cchText, cchCaption; + DWORD dwSize, cbTextLen, cbTitleLen; PWCHAR pText, pCaption; DWORD ret, dwResult; + /* Query the shell error mode value */ + ShellErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows", + L"ShellErrorMode", 0); + + /* Make the shell display the hard error message in balloon only if necessary */ + if (ShellErrorMode != 1) + return FALSE; + hwnd = GetTaskmanWindow(); if (!hwnd) { - DPRINT1("Failed to find Shell_TrayWnd\n"); + DPRINT1("Failed to find shell task window (last error %lu)\n", GetLastError()); return FALSE; } - cchText = wcslen(Text); - cchCaption = wcslen(Caption); + cbTextLen = ((Text ? wcslen(Text) : 0) + 1) * sizeof(WCHAR); + cbTitleLen = ((Caption ? wcslen(Caption) : 0) + 1) * sizeof(WCHAR); dwSize = sizeof(BALLOON_HARD_ERROR_DATA); - dwSize += (cchText + 1) * sizeof(WCHAR); - dwSize += (cchCaption + 1) * sizeof(WCHAR); + dwSize += cbTextLen + cbTitleLen; pdata = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); if (!pdata) { - DPRINT1("Failed to allocate balloon package\n"); + DPRINT1("Failed to allocate balloon data\n"); return FALSE; } pdata->cbHeaderSize = sizeof(BALLOON_HARD_ERROR_DATA); pdata->Status = Message->Status; + if (NT_SUCCESS(Message->Status)) pdata->dwType = MB_OK; else if (Message->Status == STATUS_SERVICE_NOTIFICATION) pdata->dwType = Message->Parameters[2]; else pdata->dwType = MB_ICONINFORMATION; + pdata->TitleOffset = pdata->cbHeaderSize; pdata->MessageOffset = pdata->TitleOffset; - pdata->MessageOffset += (cchCaption + 1) * sizeof(WCHAR); + pdata->MessageOffset += cbTitleLen; pCaption = (PWCHAR)((ULONG_PTR)pdata + pdata->TitleOffset); pText = (PWCHAR)((ULONG_PTR)pdata + pdata->MessageOffset); wcscpy(pCaption, Caption); @@ -502,13 +596,63 @@ UserpShowInformationBalloon(PWSTR Text, return (ret && dwResult) ? TRUE : FALSE; } + +static ULONG +GetRegInt( + IN PCWSTR KeyName, + IN PCWSTR ValueName, + IN ULONG DefaultValue) +{ + NTSTATUS Status; + ULONG Value = DefaultValue; + UNICODE_STRING String; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE KeyHandle; + ULONG ResultLength; + UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; + + RtlInitUnicodeString(&String, KeyName); + InitializeObjectAttributes(&ObjectAttributes, + &String, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the registry key */ + Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* Query the value */ + RtlInitUnicodeString(&String, ValueName); + Status = NtQueryValueKey(KeyHandle, + &String, + KeyValuePartialInformation, + ValueInfo, + sizeof(ValueBuffer), + &ResultLength); + + /* Close the registry key */ + NtClose(KeyHandle); + + if (NT_SUCCESS(Status) && (ValueInfo->Type == REG_DWORD)) + { + /* Directly retrieve the data */ + Value = *(PULONG)ValueInfo->Data; + } + } + + return Value; +} + static ULONG UserpMessageBox( - PWSTR Text, - PWSTR Caption, - ULONG ValidResponseOptions, - ULONG Severity) + IN PCWSTR Text, + IN PCWSTR Caption, + IN ULONG ValidResponseOptions, + IN ULONG Severity, + IN ULONG Timeout) { ULONG Type, MessageBoxResponse; @@ -555,9 +699,10 @@ UserpMessageBox( } /* Set severity */ - if (Severity == STATUS_SEVERITY_INFORMATIONAL) Type |= MB_ICONINFORMATION; - else if (Severity == STATUS_SEVERITY_WARNING) Type |= MB_ICONWARNING; - else if (Severity == STATUS_SEVERITY_ERROR) Type |= MB_ICONERROR; + // STATUS_SEVERITY_SUCCESS + if (Severity == STATUS_SEVERITY_INFORMATIONAL) Type |= MB_ICONINFORMATION; + else if (Severity == STATUS_SEVERITY_WARNING) Type |= MB_ICONWARNING; + else if (Severity == STATUS_SEVERITY_ERROR) Type |= MB_ICONERROR; Type |= MB_SYSTEMMODAL | MB_SETFOREGROUND; @@ -565,7 +710,7 @@ UserpMessageBox( Text, Caption, Severity, Type); /* Display a message box */ - MessageBoxResponse = MessageBoxW(NULL, Text, Caption, Type); + MessageBoxResponse = MessageBoxTimeoutW(NULL, Text, Caption, Type, 0, Timeout); /* Return response value */ switch (MessageBoxResponse) @@ -584,18 +729,56 @@ UserpMessageBox( return ResponseNotHandled; } +static +VOID +UserpLogHardError( + IN PUNICODE_STRING TextStringU, + IN PUNICODE_STRING CaptionStringU) +{ + NTSTATUS Status; + HANDLE hEventLog; + UNICODE_STRING UNCServerNameU = {0, 0, NULL}; + UNICODE_STRING SourceNameU = RTL_CONSTANT_STRING(L"Application Popup"); + PUNICODE_STRING Strings[] = {CaptionStringU, TextStringU}; + + Status = ElfRegisterEventSourceW(&UNCServerNameU, &SourceNameU, &hEventLog); + if (!NT_SUCCESS(Status) || !hEventLog) + { + DPRINT1("ElfRegisterEventSourceW failed with Status 0x%08lx\n", Status); + return; + } + + Status = ElfReportEventW(hEventLog, + EVENTLOG_INFORMATION_TYPE, + 0, + STATUS_LOG_HARD_ERROR, + NULL, // lpUserSid + ARRAYSIZE(Strings), + 0, // dwDataSize + Strings, + NULL, // lpRawData + 0, + NULL, + NULL); + if (!NT_SUCCESS(Status)) + DPRINT1("ElfReportEventW failed with Status 0x%08lx\n", Status); + + ElfDeregisterEventSource(hEventLog); +} + VOID NTAPI UserServerHardError( IN PCSR_THREAD ThreadData, IN PHARDERROR_MSG Message) { - ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS]; + ULONG_PTR Parameters[MAXIMUM_HARDERROR_PARAMETERS] = {0}; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING TextU, CaptionU; NTSTATUS Status; HANDLE hProcess; ULONG Size; + ULONG ErrorMode; ASSERT(ThreadData->Process != NULL); @@ -604,7 +787,17 @@ UserServerHardError( /* Make sure we don't have too many parameters */ if (Message->NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS) + { + // FIXME: Windows just fails (STATUS_INVALID_PARAMETER) & returns ResponseNotHandled. Message->NumberOfParameters = MAXIMUM_HARDERROR_PARAMETERS; + } + if (Message->ValidResponseOptions > OptionCancelTryContinue) + { + // STATUS_INVALID_PARAMETER; + Message->Response = ResponseNotHandled; + return; + } + // TODO: More message validation: check NumberOfParameters wrt. Message Status code. /* Initialize object attributes */ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); @@ -616,7 +809,7 @@ UserServerHardError( &Message->h.ClientId); if (!NT_SUCCESS(Status)) { - DPRINT1("NtOpenProcess failed with code: %lx\n", Status); + DPRINT1("NtOpenProcess failed with status 0x%08lx\n", Status); return; } @@ -640,22 +833,36 @@ UserServerHardError( UserpFreeStringParameters(Parameters, Message); NtClose(hProcess); + /* If we failed, bail out */ if (!NT_SUCCESS(Status)) - { return; + + /* Log the hard error message */ + UserpLogHardError(&TextU, &CaptionU); + + /* Display a hard error popup depending on the current ErrorMode */ + + /* Query the error mode value */ + ErrorMode = GetRegInt(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows", + L"ErrorMode", 0); + + if (ErrorMode != 0) + { + /* Returns OK for the hard error */ + Message->Response = ResponseOk; + goto Quit; } if (Message->ValidResponseOptions == OptionOkNoWait) { /* Display the balloon */ - if (UserpShowInformationBalloon(TextU.Buffer, - CaptionU.Buffer, + Message->Response = ResponseOk; + if (UserpShowInformationBalloon(TextU.Buffer, + CaptionU.Buffer, Message)) { Message->Response = ResponseOk; - RtlFreeUnicodeString(&TextU); - RtlFreeUnicodeString(&CaptionU); - return; + goto Quit; } } @@ -663,10 +870,13 @@ UserServerHardError( Message->Response = UserpMessageBox(TextU.Buffer, CaptionU.Buffer, Message->ValidResponseOptions, - (ULONG)Message->Status >> 30); + (ULONG)(Message->Status) >> 30, + (ULONG)-1); +Quit: RtlFreeUnicodeString(&TextU); RtlFreeUnicodeString(&CaptionU); + return; }
6 years, 8 months
1
0
0
0
01/08: [NDK] Increase MAXIMUM_HARDERROR_PARAMETERS for Win2k3 compatibility.
by Hermès Bélusca-Maïto
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e6d7ed7080db38dad9e5d…
commit e6d7ed7080db38dad9e5d968e90a005fa2b774af Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> AuthorDate: Sat Feb 17 16:25:44 2018 +0100 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Sat Apr 7 18:48:00 2018 +0200 [NDK] Increase MAXIMUM_HARDERROR_PARAMETERS for Win2k3 compatibility. --- sdk/include/ndk/extypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/include/ndk/extypes.h b/sdk/include/ndk/extypes.h index feaf7b95df..adf1371500 100644 --- a/sdk/include/ndk/extypes.h +++ b/sdk/include/ndk/extypes.h @@ -142,7 +142,7 @@ extern ULONG NTSYSAPI NtBuildNumber; // // NtRaiseHardError-related parameters // -#define MAXIMUM_HARDERROR_PARAMETERS 4 +#define MAXIMUM_HARDERROR_PARAMETERS 5 #define HARDERROR_OVERRIDE_ERRORMODE 0x10000000 //
6 years, 8 months
1
0
0
0
01/01: [RAPPS] Introduce 'SizeBytes' DB entry and use it for display
by Alexander Shaposhnikov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=627739aed9b355e7e51e7…
commit 627739aed9b355e7e51e7adca93867071c70ce17 Author: Alexander Shaposhnikov <sanchaez(a)reactos.org> AuthorDate: Sat Apr 7 19:17:22 2018 +0300 Commit: Alexander Shaposhnikov <sanchaez(a)reactos.org> CommitDate: Sat Apr 7 19:25:12 2018 +0300 [RAPPS] Introduce 'SizeBytes' DB entry and use it for display This will allow us to reduce the DB size a little by avoiding duplication for each and every entry. Original patch by JIRA user "swyter" CORE-10310 --- base/applications/rapps/available.cpp | 24 +++++++++++++++++++++--- base/applications/rapps/include/available.h | 1 + base/applications/rapps/include/misc.h | 4 ++-- base/applications/rapps/include/resource.h | 3 +++ base/applications/rapps/installed.cpp | 2 +- base/applications/rapps/misc.cpp | 11 +++++++---- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/base/applications/rapps/available.cpp b/base/applications/rapps/available.cpp index 5ed7119853..61c5a16e5e 100644 --- a/base/applications/rapps/available.cpp +++ b/base/applications/rapps/available.cpp @@ -38,7 +38,7 @@ VOID CAvailableApplicationInfo::RetrieveGeneralInfo() { m_Parser = new CConfigParser(m_sFileName); - m_Category = m_Parser->GetInt(L"Category"); + m_Parser->GetInt(L"Category", m_Category); if (!GetString(L"Name", m_szName) || !GetString(L"URLDownload", m_szUrlDownload)) @@ -51,15 +51,16 @@ VOID CAvailableApplicationInfo::RetrieveGeneralInfo() GetString(L"Version", m_szVersion); GetString(L"License", m_szLicense); GetString(L"Description", m_szDesc); - GetString(L"Size", m_szSize); GetString(L"URLSite", m_szUrlSite); GetString(L"CDPath", m_szCDPath); GetString(L"Language", m_szRegName); GetString(L"SHA1", m_szSHA1); + RetrieveSize(); RetrieveLicenseType(); RetrieveLanguages(); RetrieveInstalledStatus(); + if (m_IsInstalled) { RetrieveInstalledVersion(); @@ -128,7 +129,9 @@ VOID CAvailableApplicationInfo::RetrieveLanguages() VOID CAvailableApplicationInfo::RetrieveLicenseType() { - INT IntBuffer = m_Parser->GetInt(L"LicenseType"); + INT IntBuffer; + + m_Parser->GetInt(L"LicenseType", IntBuffer); if (IsLicenseType(IntBuffer)) { @@ -140,6 +143,21 @@ VOID CAvailableApplicationInfo::RetrieveLicenseType() } } +VOID CAvailableApplicationInfo::RetrieveSize() +{ + INT iSizeBytes; + + if (!m_Parser->GetInt(L"SizeBytes", iSizeBytes)) + { + // fall back to "Size" string + GetString(L"Size", m_szSize); + return; + } + + StrFormatByteSizeW(iSizeBytes, m_szSize.GetBuffer(MAX_PATH), MAX_PATH); + m_szSize.ReleaseBuffer(); +} + BOOL CAvailableApplicationInfo::FindInLanguages(LCID what) const { if (!m_HasLanguageInfo) diff --git a/base/applications/rapps/include/available.h b/base/applications/rapps/include/available.h index 876465fd09..c0b0f2017f 100644 --- a/base/applications/rapps/include/available.h +++ b/base/applications/rapps/include/available.h @@ -75,6 +75,7 @@ private: VOID RetrieveInstalledVersion(); VOID RetrieveLanguages(); VOID RetrieveLicenseType(); + VOID RetrieveSize(); inline BOOL FindInLanguages(LCID what) const; }; diff --git a/base/applications/rapps/include/misc.h b/base/applications/rapps/include/misc.h index 738f6746cb..143d9769b7 100644 --- a/base/applications/rapps/include/misc.h +++ b/base/applications/rapps/include/misc.h @@ -41,6 +41,6 @@ class CConfigParser public: CConfigParser(const ATL::CStringW& FileName = ""); - UINT GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString); - UINT GetInt(const ATL::CStringW& KeyName); + BOOL GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString); + BOOL GetInt(const ATL::CStringW& KeyName, INT& iResult); }; diff --git a/base/applications/rapps/include/resource.h b/base/applications/rapps/include/resource.h index 9f4c4b15de..7d5a9b9ebf 100644 --- a/base/applications/rapps/include/resource.h +++ b/base/applications/rapps/include/resource.h @@ -154,6 +154,9 @@ #define IDS_AINFO_URLDOWNLOAD 355 #define IDS_AINFO_AVAILABLEVERSION 356 #define IDS_AINFO_LANGUAGES 357 +#define IDS_AINFO_KILOBYTE_EXT 358 +#define IDS_AINFO_MEGABYTE_EXT 359 +#define IDS_AINFO_GIGABYTE_EXT 360 /* Names of categories */ diff --git a/base/applications/rapps/installed.cpp b/base/applications/rapps/installed.cpp index e1325770da..c8418dca93 100644 --- a/base/applications/rapps/installed.cpp +++ b/base/applications/rapps/installed.cpp @@ -129,7 +129,7 @@ BOOL ShowInstalledAppInfo(INT Index) GET_INFO(L"UninstallString", IDS_INFO_UNINSTALLSTR, CFE_BOLD, 0); GET_INFO(L"InstallSource", IDS_INFO_INSTALLSRC, CFE_BOLD, 0); GET_INFO(L"ModifyPath", IDS_INFO_MODIFYPATH, CFE_BOLD, 0); - + return TRUE; } diff --git a/base/applications/rapps/misc.cpp b/base/applications/rapps/misc.cpp index db0ae0bf1b..cc1dc6541f 100644 --- a/base/applications/rapps/misc.cpp +++ b/base/applications/rapps/misc.cpp @@ -354,7 +354,7 @@ VOID CConfigParser::CacheINILocale() m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale + m_szLocaleID.Right(2); } -UINT CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString) +BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString) { DWORD dwResult; @@ -392,10 +392,12 @@ UINT CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& Resul return (dwResult != 0 ? TRUE : FALSE); } -UINT CConfigParser::GetInt(const ATL::CStringW& KeyName) +BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult) { ATL::CStringW Buffer; + iResult = 0; + // grab the text version of our entry if (!GetString(KeyName, Buffer)) return FALSE; @@ -404,8 +406,9 @@ UINT CConfigParser::GetInt(const ATL::CStringW& KeyName) return FALSE; // convert it to an actual integer - INT result = StrToIntW(Buffer.GetString()); + iResult = StrToIntW(Buffer.GetString()); - return (UINT) (result <= 0) ? 0 : result; + // we only care about values > 0 + return (iResult > 0); } // CConfigParser
6 years, 8 months
1
0
0
0
06/06: [ZIPFLDR] Register the shell extension. CORE-7684
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=da6a46c6ac52cda4191fb…
commit da6a46c6ac52cda4191fb09955fa791f13039fb7 Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Fri Dec 29 23:45:47 2017 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Apr 7 15:29:59 2018 +0200 [ZIPFLDR] Register the shell extension. CORE-7684 --- media/inf/syssetup.inf | 1 + 1 file changed, 1 insertion(+) diff --git a/media/inf/syssetup.inf b/media/inf/syssetup.inf index e1545dadf2..3d12be6bfd 100644 --- a/media/inf/syssetup.inf +++ b/media/inf/syssetup.inf @@ -118,6 +118,7 @@ AddReg=Classes 11,wbem,wbemdisp.dll,1 11,wbem,wbemprox.dll,1 11,,shellbtrfs.dll,1 +11,,zipfldr.dll,1 [TypeLibraries] stdole2.tlb
6 years, 8 months
1
0
0
0
05/06: [ZIPFLDR] Initial implementation. Icon by Jared Smudde CORE-7684
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c7e6a9d04b08131fd1bc6…
commit c7e6a9d04b08131fd1bc6b5ed70d1b9e4bf8140a Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Fri Dec 29 23:45:02 2017 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Apr 7 15:29:59 2018 +0200 [ZIPFLDR] Initial implementation. Icon by Jared Smudde CORE-7684 --- dll/shellext/CMakeLists.txt | 1 + dll/shellext/zipfldr/CEnumZipContents.cpp | 95 +++++ dll/shellext/zipfldr/CExplorerCommand.cpp | 189 +++++++++ dll/shellext/zipfldr/CFolderViewCB.cpp | 54 +++ dll/shellext/zipfldr/CMakeLists.txt | 50 +++ dll/shellext/zipfldr/CZipEnumerator.hpp | 94 +++++ dll/shellext/zipfldr/CZipExtract.cpp | 481 +++++++++++++++++++++++ dll/shellext/zipfldr/CZipFolder.hpp | 625 ++++++++++++++++++++++++++++++ dll/shellext/zipfldr/Debug.cpp | 44 +++ dll/shellext/zipfldr/IZip.hpp | 12 + dll/shellext/zipfldr/precomp.h | 62 +++ dll/shellext/zipfldr/res/zipfldr.ico | Bin 0 -> 26070 bytes dll/shellext/zipfldr/res/zipfldr.rgs | 54 +++ dll/shellext/zipfldr/resource.h | 58 +++ dll/shellext/zipfldr/zipfldr.cpp | 117 ++++++ dll/shellext/zipfldr/zipfldr.rc | 88 +++++ dll/shellext/zipfldr/zipfldr.spec | 5 + dll/shellext/zipfldr/zippidl.cpp | 42 ++ dll/shellext/zipfldr/zippidl.hpp | 34 ++ 19 files changed, 2105 insertions(+) diff --git a/dll/shellext/CMakeLists.txt b/dll/shellext/CMakeLists.txt index 56fabe1299..e11df36001 100644 --- a/dll/shellext/CMakeLists.txt +++ b/dll/shellext/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(netshell) add_subdirectory(ntobjshex) add_subdirectory(shellbtrfs) add_subdirectory(stobject) +add_subdirectory(zipfldr) diff --git a/dll/shellext/zipfldr/CEnumZipContents.cpp b/dll/shellext/zipfldr/CEnumZipContents.cpp new file mode 100644 index 0000000000..f135fe756f --- /dev/null +++ b/dll/shellext/zipfldr/CEnumZipContents.cpp @@ -0,0 +1,95 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: CEnumZipContents + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +class CEnumZipContents : + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IEnumIDList +{ +private: + CZipEnumerator mEnumerator; + DWORD dwFlags; + CStringA m_Prefix; +public: + CEnumZipContents() + :dwFlags(0) + { + } + + STDMETHODIMP Initialize(IZip* zip, DWORD flags, const char* prefix) + { + dwFlags = flags; + m_Prefix = prefix; + if (mEnumerator.initialize(zip)) + return S_OK; + return E_FAIL; + } + + // *** IEnumIDList methods *** + STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) + { + if (!pceltFetched || !rgelt) + return E_POINTER; + + *pceltFetched = 0; + + if (celt != 1) + return E_FAIL; + + CStringA name; + bool dir; + unz_file_info64 info; + if (mEnumerator.next_unique(m_Prefix, name, dir, info)) + { + *pceltFetched = 1; + *rgelt = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, info); + return S_OK; + } + + return S_FALSE; + } + STDMETHODIMP Skip(ULONG celt) + { + CStringA name; + bool dir; + unz_file_info64 info; + while (celt--) + { + if (!mEnumerator.next_unique(m_Prefix, name, dir, info)) + return E_FAIL; + ; + } + return S_OK; + } + STDMETHODIMP Reset() + { + if (mEnumerator.reset()) + return S_OK; + return E_FAIL; + } + STDMETHODIMP Clone(IEnumIDList **ppenum) + { + return E_NOTIMPL; + } + + +public: + DECLARE_NOT_AGGREGATABLE(CEnumZipContents) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CEnumZipContents) + COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) + END_COM_MAP() +}; + + +HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, const char* prefix, REFIID riid, LPVOID * ppvOut) +{ + return ShellObjectCreatorInit<CEnumZipContents>(zip, flags, prefix, riid, ppvOut); +} + diff --git a/dll/shellext/zipfldr/CExplorerCommand.cpp b/dll/shellext/zipfldr/CExplorerCommand.cpp new file mode 100644 index 0000000000..1e634f81c8 --- /dev/null +++ b/dll/shellext/zipfldr/CExplorerCommand.cpp @@ -0,0 +1,189 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: IExplorerCommand implementation + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +class CExplorerCommand : + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IExplorerCommand +{ +private: + CComPtr<IContextMenu> m_pZipObject; + +public: + + STDMETHODIMP Initialize(IContextMenu* zipObject) + { + m_pZipObject = zipObject; + return S_OK; + } + + // *** IExplorerCommand methods *** + STDMETHODIMP GetTitle(IShellItemArray *psiItemArray, LPWSTR *ppszName) + { + CStringW Title(MAKEINTRESOURCEW(IDS_MENUITEM)); + return SHStrDup(Title, ppszName); + } + STDMETHODIMP GetIcon(IShellItemArray *psiItemArray, LPWSTR *ppszIcon) + { + CStringW IconName = L"zipfldr.dll,-1"; + return SHStrDup(IconName, ppszIcon); + } + STDMETHODIMP GetToolTip(IShellItemArray *psiItemArray, LPWSTR *ppszInfotip) + { + CStringW HelpText(MAKEINTRESOURCEW(IDS_HELPTEXT)); + return SHStrDup(HelpText, ppszInfotip); + } + STDMETHODIMP GetCanonicalName(GUID *pguidCommandName) + { + *pguidCommandName = CLSID_ZipFolderExtractAllCommand; + return S_OK; + } + STDMETHODIMP GetState(IShellItemArray *psiItemArray, BOOL fOkToBeSlow, EXPCMDSTATE *pCmdState) + { + *pCmdState = ECS_ENABLED; + return S_OK; + } + STDMETHODIMP Invoke(IShellItemArray *psiItemArray, IBindCtx *pbc) + { + CMINVOKECOMMANDINFO cm = { sizeof(cm), 0 }; + cm.lpVerb = EXTRACT_VERBA; + cm.nShow = SW_SHOW; + return m_pZipObject->InvokeCommand(&cm); + } + STDMETHODIMP GetFlags(EXPCMDFLAGS *pFlags) + { + *pFlags = ECF_DEFAULT; + return S_OK; + } + STDMETHODIMP EnumSubCommands(IEnumExplorerCommand **ppEnum) + { + DbgPrint("%s\n", __FUNCTION__); + return E_NOTIMPL; + } + +public: + DECLARE_NOT_AGGREGATABLE(CExplorerCommand) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CExplorerCommand) + COM_INTERFACE_ENTRY_IID(IID_IExplorerCommand, IExplorerCommand) + END_COM_MAP() +}; + + +class CEnumExplorerCommand : + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IEnumExplorerCommand +{ +private: + bool m_bFirst; + CComPtr<IContextMenu> m_pZipObject; + +public: + + CEnumExplorerCommand() + :m_bFirst(true) + { + } + + STDMETHODIMP Initialize(IContextMenu* zipObject) + { + m_pZipObject = zipObject; + return S_OK; + } + + // *** IEnumExplorerCommand methods *** + STDMETHODIMP Next(ULONG celt, IExplorerCommand **pUICommand, ULONG *pceltFetched) + { + if (!pUICommand) + return E_POINTER; + + if (pceltFetched) + *pceltFetched = 0; + if (m_bFirst && celt) + { + m_bFirst = false; + celt--; + HRESULT hr = ShellObjectCreatorInit<CExplorerCommand>(m_pZipObject, IID_PPV_ARG(IExplorerCommand, pUICommand)); + if (SUCCEEDED(hr)) + { + if (pceltFetched) + *pceltFetched = 1; + } + return hr; + } + return S_FALSE; + } + STDMETHODIMP Skip(ULONG celt) + { + if (m_bFirst) + { + m_bFirst = false; + return S_OK; + } + return S_FALSE; + } + STDMETHODIMP Reset() + { + m_bFirst = true; + return S_OK; + } + STDMETHODIMP Clone(IEnumExplorerCommand **ppenum) + { + return E_NOTIMPL; + } + +public: + DECLARE_NOT_AGGREGATABLE(CEnumExplorerCommand) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CEnumExplorerCommand) + COM_INTERFACE_ENTRY_IID(IID_IEnumExplorerCommand, IEnumExplorerCommand) + END_COM_MAP() +}; + +class CExplorerCommandProvider : + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IExplorerCommandProvider +{ +private: + CComPtr<IContextMenu> m_pZipObject; + +public: + STDMETHODIMP Initialize(IContextMenu* zipObject) + { + m_pZipObject = zipObject; + return S_OK; + } + + // *** IExplorerCommandProvider methods *** + STDMETHODIMP GetCommands(IUnknown *punkSite, REFIID riid, void **ppv) + { + return ShellObjectCreatorInit<CEnumExplorerCommand>(m_pZipObject, riid, ppv); + } + STDMETHODIMP GetCommand(REFGUID rguidCommandId, REFIID riid, void **ppv) + { + UNIMPLEMENTED; + *ppv = NULL; + return E_NOTIMPL; + } + +public: + DECLARE_NOT_AGGREGATABLE(CExplorerCommandProvider) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CExplorerCommandProvider) + COM_INTERFACE_ENTRY_IID(IID_IExplorerCommandProvider, IExplorerCommandProvider) + END_COM_MAP() +}; + + +HRESULT _CExplorerCommandProvider_CreateInstance(IContextMenu* zipObject, REFIID riid, LPVOID * ppvOut) +{ + return ShellObjectCreatorInit<CExplorerCommandProvider>(zipObject, riid, ppvOut); +} diff --git a/dll/shellext/zipfldr/CFolderViewCB.cpp b/dll/shellext/zipfldr/CFolderViewCB.cpp new file mode 100644 index 0000000000..2a46f6576a --- /dev/null +++ b/dll/shellext/zipfldr/CFolderViewCB.cpp @@ -0,0 +1,54 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: IShellFolderViewCB implementation + * COPYRIGHT: Copyright 2017 David Quintana (gigaherz(a)gmail.com) + * Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +class CFolderViewCB : + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IShellFolderViewCB +{ +public: + + virtual ~CFolderViewCB() + { + } + + // *** IShellFolderViewCB methods *** + STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + /* TODO: Handle SFVM_GET_WEBVIEW_CONTENT to add tasks */ + switch (uMsg) + { + case SFVM_DEFVIEWMODE: + { + FOLDERVIEWMODE* pViewMode = (FOLDERVIEWMODE*)lParam; + *pViewMode = FVM_DETAILS; + return S_OK; + } + case SFVM_COLUMNCLICK: + return S_FALSE; + case SFVM_BACKGROUNDENUM: + return S_OK; + } + + return E_NOTIMPL; + } + +public: + DECLARE_NOT_AGGREGATABLE(CFolderViewCB) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CFolderViewCB) + COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB) + END_COM_MAP() +}; + +HRESULT _CFolderViewCB_CreateInstance(REFIID riid, LPVOID * ppvOut) +{ + return ShellObjectCreator<CFolderViewCB>(riid, ppvOut); +} diff --git a/dll/shellext/zipfldr/CMakeLists.txt b/dll/shellext/zipfldr/CMakeLists.txt new file mode 100644 index 0000000000..d491f1d7c2 --- /dev/null +++ b/dll/shellext/zipfldr/CMakeLists.txt @@ -0,0 +1,50 @@ + +set_cpp(WITH_RUNTIME WITH_EXCEPTIONS) +if(NOT MSVC) + # HACK: this should be enabled globally! + add_compile_flags_language("-std=c++11" "CXX") +endif() + +remove_definitions(-D_WIN32_WINNT=0x502) +add_definitions(-D_WIN32_WINNT=0x600) + +add_definitions( + -D_ATL_NO_EXCEPTIONS) + +include_directories( + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib + ${REACTOS_SOURCE_DIR}/sdk/lib/atl + ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/zlib/contrib) + +spec2def(zipfldr.dll zipfldr.spec ADD_IMPORTLIB) + + +list(APPEND SOURCE + zipfldr.cpp + zippidl.cpp + zippidl.hpp + IZip.hpp + CExplorerCommand.cpp + CEnumZipContents.cpp + CFolderViewCB.cpp + CZipEnumerator.hpp + CZipExtract.cpp + CZipFolder.hpp + Debug.cpp + zipfldr.spec + precomp.h + resource.h) + +add_library(zipfldr SHARED + ${SOURCE} + ${ZLIB_SOURCE} + zipfldr.rc + ${CMAKE_CURRENT_BINARY_DIR}/zipfldr.def) + + +set_module_type(zipfldr win32dll UNICODE) +target_link_libraries(zipfldr minizip zlib atlnew uuid) +add_importlibs(zipfldr oleaut32 ole32 shlwapi comctl32 shell32 user32 advapi32 msvcrt kernel32 ntdll) +add_pch(zipfldr precomp.h SOURCE) +add_cd_file(TARGET zipfldr DESTINATION reactos/system32 FOR all) + diff --git a/dll/shellext/zipfldr/CZipEnumerator.hpp b/dll/shellext/zipfldr/CZipEnumerator.hpp new file mode 100644 index 0000000000..2c36aac2ea --- /dev/null +++ b/dll/shellext/zipfldr/CZipEnumerator.hpp @@ -0,0 +1,94 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: CZipEnumerator + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +struct CZipEnumerator +{ +private: + CComPtr<IZip> m_Zip; + bool m_First; + CAtlList<CStringA> m_Returned; +public: + CZipEnumerator() + :m_First(true) + { + } + + bool initialize(IZip* zip) + { + m_Zip = zip; + return reset(); + } + + bool reset() + { + unzFile uf = m_Zip->getZip(); + m_First = true; + if (unzGoToFirstFile(uf) != UNZ_OK) + return false; + m_Returned.RemoveAll(); + return true; + } + + bool next_unique(const char* prefix, CStringA& name, bool& folder, unz_file_info64& info) + { + size_t len = strlen(prefix); + CStringA tmp; + while (next(tmp, info)) + { + if (!_strnicmp(tmp, prefix, len)) + { + int pos = tmp.Find('/', len); + if (pos < 0) + { + name = tmp.Mid(len); + folder = false; + } + else + { + name = tmp.Mid(len, pos - len); + folder = true; + } + tmp = name.MakeLower(); + + POSITION it = m_Returned.Find(tmp); + if (!name.IsEmpty() && !it) + { + m_Returned.AddTail(tmp); + return true; + } + } + } + return false; + } + + bool next(CStringA& name, unz_file_info64& info) + { + int err; + + unzFile uf = m_Zip->getZip(); + if (!m_First) + { + err = unzGoToNextFile(uf); + if (err == UNZ_END_OF_LIST_OF_FILE) + { + return false; + } + } + m_First = false; + + err = unzGetCurrentFileInfo64(uf, &info, NULL, 0, NULL, 0, NULL, 0); + if (err == UNZ_OK) + { + PSTR buf = name.GetBuffer(info.size_filename); + err = unzGetCurrentFileInfo64(uf, NULL, buf, name.GetAllocLength(), NULL, 0, NULL, 0); + name.ReleaseBuffer(info.size_filename); + name.Replace('\\', '/'); + } + return err == UNZ_OK; + } +}; + diff --git a/dll/shellext/zipfldr/CZipExtract.cpp b/dll/shellext/zipfldr/CZipExtract.cpp new file mode 100644 index 0000000000..5fbebefbb7 --- /dev/null +++ b/dll/shellext/zipfldr/CZipExtract.cpp @@ -0,0 +1,481 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Zip extraction + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +class CZipExtract : + public IZip +{ + CStringW m_Filename; + CStringW m_Directory; + unzFile uf; +public: + CZipExtract(PCWSTR Filename) + :uf(NULL) + { + m_Filename = Filename; + m_Directory = m_Filename; + PWSTR Dir = m_Directory.GetBuffer(); + PathRemoveExtensionW(Dir); + m_Directory.ReleaseBuffer(); + } + + ~CZipExtract() + { + if (uf) + { + DPRINT1("WARNING: uf not closed!\n"); + Close(); + } + } + + void Close() + { + if (uf) + unzClose(uf); + uf = NULL; + } + + // *** IZip methods *** + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) + { + if (riid == IID_IUnknown) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; + } + STDMETHODIMP_(ULONG) AddRef(void) + { + return 2; + } + STDMETHODIMP_(ULONG) Release(void) + { + return 1; + } + STDMETHODIMP_(unzFile) getZip() + { + return uf; + } + + class CConfirmReplace : public CDialogImpl<CConfirmReplace> + { + private: + CStringA m_Filename; + public: + enum DialogResult + { + Yes, + YesToAll, + No, + Cancel + }; + + static DialogResult ShowDlg(HWND hDlg, PCSTR FullPath) + { + PCSTR Filename = PathFindFileNameA(FullPath); + CConfirmReplace confirm(Filename); + INT_PTR Result = confirm.DoModal(hDlg); + switch (Result) + { + case IDYES: return Yes; + case IDYESALL: return YesToAll; + default: + case IDNO: return No; + case IDCANCEL: return Cancel; + } + } + + CConfirmReplace(const char* filename) + { + m_Filename = filename; + } + + LRESULT OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + CenterWindow(GetParent()); + + HICON hIcon = LoadIcon(NULL, IDI_EXCLAMATION); + SendDlgItemMessage(IDC_EXCLAMATION_ICON, STM_SETICON, (WPARAM)hIcon); + + /* Our CString does not support FormatMessage yet */ + CStringA message(MAKEINTRESOURCE(IDS_OVERWRITEFILE_TEXT)); + CHeapPtr<CHAR, CLocalAllocator> formatted; + + DWORD_PTR args[2] = + { + (DWORD_PTR)m_Filename.GetString(), + NULL + }; + + ::FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY, + message, 0, 0, (LPSTR)&formatted, 0, (va_list*)args); + + ::SetDlgItemTextA(m_hWnd, IDC_MESSAGE, formatted); + return 0; + } + + LRESULT OnButton(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) + { + EndDialog(wID); + return 0; + } + + public: + enum { IDD = IDD_CONFIRM_FILE_REPLACE }; + + BEGIN_MSG_MAP(CConfirmReplace) + MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) + COMMAND_ID_HANDLER(IDYES, OnButton) + COMMAND_ID_HANDLER(IDYESALL, OnButton) + COMMAND_ID_HANDLER(IDNO, OnButton) + COMMAND_ID_HANDLER(IDCANCEL, OnButton) + END_MSG_MAP() + }; + + + class CExtractSettingsPage : public CPropertyPageImpl<CExtractSettingsPage> + { + private: + CZipExtract* m_pExtract; + + public: + CExtractSettingsPage(CZipExtract* extract) + :CPropertyPageImpl<CExtractSettingsPage>(MAKEINTRESOURCE(IDS_WIZ_TITLE)) + ,m_pExtract(extract) + { + m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_WIZ_DEST_TITLE); + m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_WIZ_DEST_SUBTITLE); + m_psp.dwFlags |= PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; + } + + int OnSetActive() + { + SetDlgItemTextW(IDC_DIRECTORY, m_pExtract->m_Directory); + ::EnableWindow(GetDlgItem(IDC_PASSWORD), FALSE); /* Not supported for now */ + GetParent().CenterWindow(::GetDesktopWindow()); + return 0; + } + + int OnWizardNext() + { + ::EnableWindow(GetDlgItem(IDC_BROWSE), FALSE); + ::EnableWindow(GetDlgItem(IDC_DIRECTORY), FALSE); + ::EnableWindow(GetDlgItem(IDC_PASSWORD), FALSE); + + if (!m_pExtract->Extract(m_hWnd, GetDlgItem(IDC_PROGRESS))) + { + /* Extraction failed, do not go to the next page */ + SetWindowLongPtr(DWLP_MSGRESULT, -1); + + ::EnableWindow(GetDlgItem(IDC_BROWSE), TRUE); + ::EnableWindow(GetDlgItem(IDC_DIRECTORY), TRUE); + ::EnableWindow(GetDlgItem(IDC_PASSWORD), FALSE); /* Not supported for now */ + + return TRUE; + } + return 0; + } + + struct browse_info + { + HWND hWnd; + LPCWSTR Directory; + }; + + static INT CALLBACK s_BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lp, LPARAM pData) + { + if (uMsg == BFFM_INITIALIZED) + { + browse_info* info = (browse_info*)pData; + CWindow dlg(hWnd); + dlg.SendMessage(BFFM_SETSELECTION, TRUE, (LPARAM)info->Directory); + dlg.CenterWindow(info->hWnd); + } + return 0; + } + + LRESULT OnBrowse(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) + { + BROWSEINFOW bi = { m_hWnd }; + WCHAR path[MAX_PATH]; + bi.pszDisplayName = path; + bi.lpfn = s_BrowseCallbackProc; + bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS; + CStringW title(MAKEINTRESOURCEW(IDS_WIZ_BROWSE_TITLE)); + bi.lpszTitle = title; + + browse_info info = { m_hWnd, m_pExtract->m_Directory.GetString() }; + bi.lParam = (LPARAM)&info; + + CComHeapPtr<ITEMIDLIST> pidl; + pidl.Attach(SHBrowseForFolderW(&bi)); + + WCHAR tmpPath[MAX_PATH]; + if (pidl && SHGetPathFromIDListW(pidl, tmpPath)) + { + m_pExtract->m_Directory = tmpPath; + SetDlgItemTextW(IDC_DIRECTORY, m_pExtract->m_Directory); + } + return 0; + } + + LRESULT OnPassword(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) + { + return 0; + } + + public: + enum { IDD = IDD_PROPPAGEDESTIONATION }; + + BEGIN_MSG_MAP(CCompleteSettingsPage) + COMMAND_ID_HANDLER(IDC_BROWSE, OnBrowse) + COMMAND_ID_HANDLER(IDC_PASSWORD, OnPassword) + CHAIN_MSG_MAP(CPropertyPageImpl<CExtractSettingsPage>) + END_MSG_MAP() + }; + + + class CCompleteSettingsPage : public CPropertyPageImpl<CCompleteSettingsPage> + { + private: + CZipExtract* m_pExtract; + + public: + CCompleteSettingsPage(CZipExtract* extract) + :CPropertyPageImpl<CCompleteSettingsPage>(MAKEINTRESOURCE(IDS_WIZ_TITLE)) + , m_pExtract(extract) + { + m_psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_WIZ_COMPL_TITLE); + m_psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_WIZ_COMPL_SUBTITLE); + m_psp.dwFlags |= PSP_USETITLE | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE; + } + + + int OnSetActive() + { + SetWizardButtons(PSWIZB_FINISH); + CStringW Path = m_pExtract->m_Directory; + PWSTR Ptr = Path.GetBuffer(); + RECT rc; + ::GetWindowRect(GetDlgItem(IDC_DESTDIR), &rc); + HDC dc = GetDC(); + PathCompactPathW(dc, Ptr, rc.right - rc.left); + ReleaseDC(dc); + Path.ReleaseBuffer(); + SetDlgItemTextW(IDC_DESTDIR, Path); + CheckDlgButton(IDC_SHOW_EXTRACTED, BST_CHECKED); + return 0; + } + BOOL OnWizardFinish() + { + if (IsDlgButtonChecked(IDC_SHOW_EXTRACTED) == BST_CHECKED) + { + ShellExecuteW(NULL, L"explore", m_pExtract->m_Directory, NULL, NULL, SW_SHOW); + } + return FALSE; + } + + public: + enum { IDD = IDD_PROPPAGECOMPLETE }; + + BEGIN_MSG_MAP(CCompleteSettingsPage) + CHAIN_MSG_MAP(CPropertyPageImpl<CCompleteSettingsPage>) + END_MSG_MAP() + }; + + + void runWizard() + { + PROPSHEETHEADERW psh = { sizeof(psh), 0 }; + psh.dwFlags = PSH_WIZARD97 | PSH_HEADER; + psh.hInstance = _AtlBaseModule.GetResourceInstance(); + + CExtractSettingsPage extractPage(this); + CCompleteSettingsPage completePage(this); + HPROPSHEETPAGE hpsp[] = + { + extractPage.Create(), + completePage.Create() + }; + + psh.phpage = hpsp; + psh.nPages = _countof(hpsp); + + PropertySheetW(&psh); + } + + bool Extract(HWND hDlg, HWND hProgress) + { + unz_global_info64 gi; + uf = unzOpen2_64(m_Filename.GetString(), &g_FFunc); + int err = unzGetGlobalInfo64(uf, &gi); + if (err != UNZ_OK) + { + DPRINT1("ERROR, unzGetGlobalInfo64: 0x%x\n", err); + return false; + } + + CZipEnumerator zipEnum; + if (!zipEnum.initialize(this)) + { + DPRINT1("ERROR, zipEnum.initialize\n"); + return false; + } + + CWindow Progress(hProgress); + Progress.SendMessage(PBM_SETRANGE32, 0, gi.number_entry); + Progress.SendMessage(PBM_SETPOS, 0, 0); + + BYTE Buffer[2048]; + CStringA BaseDirectory = m_Directory; + CStringA Name; + unz_file_info64 Info; + int CurrentFile = 0; + bool bOverwriteAll = false; + while (zipEnum.next(Name, Info)) + { + bool is_dir = Name.GetLength() > 0 && Name[Name.GetLength()-1] == '/'; + + char CombinedPath[MAX_PATH * 2] = { 0 }; + PathCombineA(CombinedPath, BaseDirectory, Name); + CStringA FullPath = CombinedPath; + FullPath.Replace('/', '\\'); /* SHPathPrepareForWriteA does not handle '/' */ + DWORD dwFlags = SHPPFW_DIRCREATE | (is_dir ? SHPPFW_NONE : SHPPFW_IGNOREFILENAME); + HRESULT hr = SHPathPrepareForWriteA(hDlg, NULL, FullPath, dwFlags); + if (FAILED_UNEXPECTEDLY(hr)) + { + return false; + } + CurrentFile++; + if (is_dir) + continue; + + const char* password = NULL; + /* FIXME: Process password, if required and not specified, prompt the user */ + err = unzOpenCurrentFilePassword(uf, password); + if (err != UNZ_OK) + { + DPRINT1("ERROR, unzOpenCurrentFilePassword: 0x%x\n", err); + return false; + } + + HANDLE hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_FILE_EXISTS) + { + bool bOverwrite = bOverwriteAll; + if (!bOverwriteAll) + { + CConfirmReplace::DialogResult Result = CConfirmReplace::ShowDlg(hDlg, FullPath); + switch (Result) + { + case CConfirmReplace::YesToAll: + bOverwriteAll = true; + case CConfirmReplace::Yes: + bOverwrite = true; + break; + case CConfirmReplace::No: + break; + case CConfirmReplace::Cancel: + return false; + } + } + + if (bOverwrite) + { + hFile = CreateFileA(FullPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + dwErr = GetLastError(); + } + } + else + { + unzCloseCurrentFile(uf); + continue; + } + } + if (hFile == INVALID_HANDLE_VALUE) + { + unzCloseCurrentFile(uf); + DPRINT1("ERROR, CreateFileA: 0x%x (%s)\n", dwErr, bOverwriteAll ? "Y" : "N"); + return false; + } + } + + do + { + err = unzReadCurrentFile(uf, Buffer, sizeof(Buffer)); + + if (err < 0) + { + DPRINT1("ERROR, unzReadCurrentFile: 0x%x\n", err); + break; + } + else if (err > 0) + { + DWORD dwWritten; + if (!WriteFile(hFile, Buffer, err, &dwWritten, NULL)) + { + DPRINT1("ERROR, WriteFile: 0x%x\n", GetLastError()); + break; + } + if (dwWritten != (DWORD)err) + { + DPRINT1("ERROR, WriteFile: dwWritten:%d err:%d\n", dwWritten, err); + break; + } + } + + } while (err > 0); + + /* Update Filetime */ + FILETIME LastAccessTime; + GetFileTime(hFile, NULL, &LastAccessTime, NULL); + FILETIME LocalFileTime; + DosDateTimeToFileTime((WORD)(Info.dosDate >> 16), (WORD)Info.dosDate, &LocalFileTime); + FILETIME FileTime; + LocalFileTimeToFileTime(&LocalFileTime, &FileTime); + SetFileTime(hFile, &FileTime, &LastAccessTime, &FileTime); + + /* Done.. */ + CloseHandle(hFile); + + if (err) + { + unzCloseCurrentFile(uf); + DPRINT1("ERROR, unzReadCurrentFile2: 0x%x\n", err); + return false; + } + else + { + err = unzCloseCurrentFile(uf); + if (err != UNZ_OK) + { + DPRINT1("ERROR(non-fatal), unzCloseCurrentFile: 0x%x\n", err); + } + } + Progress.SendMessage(PBM_SETPOS, CurrentFile, 0); + } + + Close(); + return true; + } +}; + + +void _CZipExtract_runWizard(PCWSTR Filename) +{ + CZipExtract extractor(Filename); + extractor.runWizard(); +} + diff --git a/dll/shellext/zipfldr/CZipFolder.hpp b/dll/shellext/zipfldr/CZipFolder.hpp new file mode 100644 index 0000000000..fa98673ff2 --- /dev/null +++ b/dll/shellext/zipfldr/CZipFolder.hpp @@ -0,0 +1,625 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Main class + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + + +EXTERN_C HRESULT WINAPI SHCreateFileExtractIconW(LPCWSTR pszPath, DWORD dwFileAttributes, REFIID riid, void **ppv); + + +struct FolderViewColumns +{ + int iResource; + DWORD dwDefaultState; + int cxChar; + int fmt; +}; + +static FolderViewColumns g_ColumnDefs[] = +{ + { IDS_COL_NAME, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 25, LVCFMT_LEFT }, + { IDS_COL_TYPE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 20, LVCFMT_LEFT }, + { IDS_COL_COMPRSIZE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 10, LVCFMT_RIGHT }, + { IDS_COL_PASSWORD, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 10, LVCFMT_LEFT }, + { IDS_COL_SIZE, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 10, LVCFMT_RIGHT }, + { IDS_COL_RATIO, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, 10, LVCFMT_LEFT }, + { IDS_COL_DATE_MOD, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, 15, LVCFMT_LEFT }, +}; + + +class CZipFolder : + public CComCoClass<CZipFolder, &CLSID_ZipFolderStorageHandler>, + public CComObjectRootEx<CComMultiThreadModelNoCS>, + public IShellFolder2, + //public IStorage, + public IContextMenu, + public IShellExtInit, + //public IPersistFile, + public IPersistFolder2, + public IZip +{ + CStringW m_ZipFile; + CStringA m_ZipDir; + CComHeapPtr<ITEMIDLIST> m_CurDir; + unzFile m_UnzipFile; + +public: + CZipFolder() + :m_UnzipFile(NULL) + { + } + + ~CZipFolder() + { + Close(); + } + + void Close() + { + if (m_UnzipFile) + unzClose(m_UnzipFile); + m_UnzipFile = NULL; + } + + // *** IZip methods *** + STDMETHODIMP_(unzFile) getZip() + { + if (!m_UnzipFile) + { + m_UnzipFile = unzOpen2_64(m_ZipFile, &g_FFunc); + } + + return m_UnzipFile; + } + + // *** IShellFolder2 methods *** + STDMETHODIMP GetDefaultSearchGUID(GUID *pguid) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP EnumSearches(IEnumExtraSearch **ppenum) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags) + { + if (!pcsFlags || iColumn >= _countof(g_ColumnDefs)) + return E_INVALIDARG; + *pcsFlags = g_ColumnDefs[iColumn].dwDefaultState; + return S_OK; + } + STDMETHODIMP GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + // Adapted from CFileDefExt::GetFileTimeString + BOOL _GetFileTimeString(LPFILETIME lpFileTime, LPWSTR pwszResult, UINT cchResult) + { + SYSTEMTIME st; + + if (!FileTimeToSystemTime(lpFileTime, &st)) + return FALSE; + + size_t cchRemaining = cchResult; + LPWSTR pwszEnd = pwszResult; + int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pwszEnd, cchRemaining); + if (cchWritten) + --cchWritten; // GetDateFormatW returns count with terminating zero + else + return FALSE; + cchRemaining -= cchWritten; + pwszEnd += cchWritten; + + StringCchCopyExW(pwszEnd, cchRemaining, L" ", &pwszEnd, &cchRemaining, 0); + + cchWritten = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, pwszEnd, cchRemaining); + if (cchWritten) + --cchWritten; // GetTimeFormatW returns count with terminating zero + else + return FALSE; + + return TRUE; + } + STDMETHODIMP GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd) + { + if (iColumn >= _countof(g_ColumnDefs)) + return E_FAIL; + + psd->cxChar = g_ColumnDefs[iColumn].cxChar; + psd->fmt = g_ColumnDefs[iColumn].fmt; + + if (pidl == NULL) + { + return SHSetStrRet(&psd->str, _AtlBaseModule.GetResourceInstance(), g_ColumnDefs[iColumn].iResource); + } + + PCUIDLIST_RELATIVE curpidl = ILGetNext(pidl); + if (curpidl->mkid.cb != 0) + { + DPRINT1("ERROR, unhandled PIDL!\n"); + return E_FAIL; + } + + const ZipPidlEntry* zipEntry = _ZipFromIL(pidl); + if (!zipEntry) + return E_INVALIDARG; + + WCHAR Buffer[100]; + bool isDir = zipEntry->ZipType == ZIP_PIDL_DIRECTORY; + switch (iColumn) + { + case 0: /* Name, ReactOS specific? */ + return GetDisplayNameOf(pidl, 0, &psd->str); + case 1: /* Type */ + { + SHFILEINFOA shfi; + DWORD dwAttributes = isDir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + ULONG_PTR firet = SHGetFileInfoA(zipEntry->Name, dwAttributes, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME); + if (!firet) + return E_FAIL; + return SHSetStrRet(&psd->str, shfi.szTypeName); + } + case 2: /* Compressed size */ + case 4: /* Size */ + { + ULONG64 Size = iColumn == 2 ? zipEntry->CompressedSize : zipEntry->UncompressedSize; + if (!StrFormatByteSizeW(Size, Buffer, _countof(Buffer))) + return E_FAIL; + return SHSetStrRet(&psd->str, Buffer); + } + case 3: /* Password */ + if (isDir) + return SHSetStrRet(&psd->str, L""); + return SHSetStrRet(&psd->str, _AtlBaseModule.GetResourceInstance(), zipEntry->Password ? IDS_YES : IDS_NO); + case 5: /* Ratio */ + { + int ratio = 0; + if (zipEntry->UncompressedSize && !isDir) + ratio = 100 - (int)((zipEntry->CompressedSize*100)/zipEntry->UncompressedSize); + StringCchPrintfW(Buffer, _countof(Buffer), L"%d%%", ratio); + return SHSetStrRet(&psd->str, Buffer); + } + case 6: /* Date */ + { + if (isDir) + return SHSetStrRet(&psd->str, L""); + FILETIME ftLocal; + DosDateTimeToFileTime((WORD)(zipEntry->DosDate>>16), (WORD)zipEntry->DosDate, &ftLocal); + if (!_GetFileTimeString(&ftLocal, Buffer, _countof(Buffer))) + return E_FAIL; + return SHSetStrRet(&psd->str, Buffer); + } + } + + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP MapColumnToSCID(UINT column, SHCOLUMNID *pscid) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + + // *** IShellFolder methods *** + STDMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) + { + return _CEnumZipContents_CreateInstance(this, dwFlags, m_ZipDir, IID_PPV_ARG(IEnumIDList, ppEnumIDList)); + } + STDMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) + { + if (riid == IID_IShellFolder) + { + CStringA newZipDir = m_ZipDir; + PCUIDLIST_RELATIVE curpidl = pidl; + while (curpidl->mkid.cb) + { + const ZipPidlEntry* zipEntry = _ZipFromIL(curpidl); + if (!zipEntry) + { + return E_FAIL; + } + newZipDir += zipEntry->Name; + newZipDir += '/'; + + curpidl = ILGetNext(curpidl); + } + return ShellObjectCreatorInit<CZipFolder>(m_ZipFile, newZipDir, m_CurDir, pidl, riid, ppvOut); + } + DbgPrint("%s(%S) UNHANDLED\n", __FUNCTION__, guid2string(riid)); + return E_NOTIMPL; + } + STDMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + STDMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) + { + const ZipPidlEntry* zipEntry1 = _ZipFromIL(pidl1); + const ZipPidlEntry* zipEntry2 = _ZipFromIL(pidl2); + + if (!zipEntry1 || !zipEntry2) + return E_INVALIDARG; + + int result = 0; + if (zipEntry1->ZipType != zipEntry2->ZipType) + result = zipEntry1->ZipType - zipEntry2->ZipType; + else + result = stricmp(zipEntry1->Name, zipEntry2->Name); + + if (!result && zipEntry1->ZipType == ZIP_PIDL_DIRECTORY) + { + PCUIDLIST_RELATIVE child1 = ILGetNext(pidl1); + PCUIDLIST_RELATIVE child2 = ILGetNext(pidl2); + + if (child1->mkid.cb && child2->mkid.cb) + return CompareIDs(lParam, child1, child2); + else if (child1->mkid.cb) + result = 1; + else if (child2->mkid.cb) + result = -1; + } + + return MAKE_COMPARE_HRESULT(result); + } + STDMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) + { + static const GUID UnknownIID = // {93F81976-6A0D-42C3-94DD-AA258A155470} + {0x93F81976, 0x6A0D, 0x42C3, {0x94, 0xDD, 0xAA, 0x25, 0x8A, 0x15, 0x54, 0x70}}; + if (riid == IID_IShellView) + { + SFV_CREATE sfvparams = {sizeof(SFV_CREATE), this}; + CComPtr<IShellFolderViewCB> pcb; + + HRESULT hr = _CFolderViewCB_CreateInstance(IID_PPV_ARG(IShellFolderViewCB, &pcb)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + sfvparams.psfvcb = pcb; + hr = SHCreateShellFolderView(&sfvparams, (IShellView**)ppvOut); + + return hr; + } + if (riid == IID_IExplorerCommandProvider) + { + return _CExplorerCommandProvider_CreateInstance(this, riid, ppvOut); + } + if (UnknownIID != riid) + DbgPrint("%s(%S) UNHANDLED\n", __FUNCTION__, guid2string(riid)); + return E_NOTIMPL; + } + STDMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) + { + if (!rgfInOut || !cidl || !apidl) + return E_INVALIDARG; + + *rgfInOut = 0; + + //static DWORD dwFileAttrs = SFGAO_STREAM | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_CANCOPY | SFGAO_CANMOVE; + //static DWORD dwFolderAttrs = SFGAO_FOLDER | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_STORAGE | SFGAO_CANCOPY | SFGAO_CANMOVE; + static DWORD dwFileAttrs = SFGAO_STREAM; + static DWORD dwFolderAttrs = SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE; + + + while (cidl > 0 && *apidl) + { + const ZipPidlEntry* zipEntry = _ZipFromIL(*apidl); + + if (zipEntry) + { + if (zipEntry->ZipType == ZIP_PIDL_FILE) + *rgfInOut |= dwFileAttrs; + else + *rgfInOut |= dwFolderAttrs; + } + else + { + *rgfInOut = 0; + } + + apidl++; + cidl--; + } + + *rgfInOut &= ~SFGAO_VALIDATE; + return S_OK; + } + static HRESULT CALLBACK ZipFolderMenuCallback(IShellFolder *psf, HWND hwnd, IDataObject *pdtobj, + UINT uMsg, WPARAM wParam, LPARAM lParam) + { + switch (uMsg) + { + case DFM_MERGECONTEXTMENU: + DPRINT1("FIXME: Add menu items for DFM_MERGECONTEXTMENU\n"); + return S_OK; + case DFM_INVOKECOMMAND: + case DFM_INVOKECOMMANDEX: + case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default + return S_FALSE; + } + return E_NOTIMPL; + } + STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) + { + if ((riid == IID_IExtractIconA || riid == IID_IExtractIconW) && cidl == 1) + { + const ZipPidlEntry* zipEntry = _ZipFromIL(*apidl); + if (zipEntry) + { + CComHeapPtr<WCHAR> pathW; + + int len = MultiByteToWideChar(CP_ACP, 0, zipEntry->Name, -1, NULL, 0); + pathW.Allocate(len); + MultiByteToWideChar(CP_ACP, 0, zipEntry->Name, -1, pathW, len); + + DWORD dwAttributes = (zipEntry->ZipType == ZIP_PIDL_DIRECTORY) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; + return SHCreateFileExtractIconW(pathW, dwAttributes, riid, ppvOut); + } + } + else if (riid == IID_IContextMenu && cidl >= 0) + { + const ZipPidlEntry* zipEntry = _ZipFromIL(*apidl); + if (zipEntry) + { + HKEY keys[1] = {0}; + int nkeys = 0; + if (zipEntry->ZipType == ZIP_PIDL_DIRECTORY) + { + LSTATUS res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ | KEY_QUERY_VALUE, keys); + if (res != ERROR_SUCCESS) + return E_FAIL; + nkeys++; + } + return CDefFolderMenu_Create2(NULL, hwndOwner, cidl, apidl, this, ZipFolderMenuCallback, nkeys, keys, (IContextMenu**)ppvOut); + } + } + else if (riid == IID_IDataObject && cidl >= 1) + { + return CIDLData_CreateFromIDArray(m_CurDir, cidl, apidl, (IDataObject**)ppvOut); + } + + DbgPrint("%s(%S) UNHANDLED\n", __FUNCTION__ , guid2string(riid)); + return E_NOINTERFACE; + } + STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet) + { + if (!pidl) + return S_FALSE; + + PCUIDLIST_RELATIVE curpidl = ILGetNext(pidl); + if (curpidl->mkid.cb != 0) + { + DPRINT1("ERROR, unhandled PIDL!\n"); + return E_FAIL; + } + + const ZipPidlEntry* zipEntry = _ZipFromIL(pidl); + if (!zipEntry) + return E_FAIL; + + return SHSetStrRet(strRet, (LPCSTR)zipEntry->Name); + } + STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) + { + UNIMPLEMENTED; + return E_NOTIMPL; + } + //// IStorage + //STDMETHODIMP CreateStream(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved1, DWORD reserved2, IStream **ppstm); + //STDMETHODIMP OpenStream(LPCOLESTR pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream **ppstm); + //STDMETHODIMP CreateStorage(LPCOLESTR pwcsName, DWORD grfMode, DWORD dwStgFmt, DWORD reserved2, IStorage **ppstg); + //STDMETHODIMP OpenStorage(LPCOLESTR pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstg); + //STDMETHODIMP CopyTo(DWORD ciidExclude, const IID *rgiidExclude, SNB snbExclude, IStorage *pstgDest); + //STDMETHODIMP MoveElementTo(LPCOLESTR pwcsName, IStorage *pstgDest, LPCOLESTR pwcsNewName, DWORD grfFlags); + //STDMETHODIMP Commit(DWORD grfCommitFlags); + //STDMETHODIMP Revert(); + //STDMETHODIMP EnumElements(DWORD reserved1, void *reserved2, DWORD reserved3, IEnumSTATSTG **ppenum); + //STDMETHODIMP DestroyElement(LPCOLESTR pwcsName); + //STDMETHODIMP RenameElement(LPCOLESTR pwcsOldName, LPCOLESTR pwcsNewName); + //STDMETHODIMP SetElementTimes(LPCOLESTR pwcsName, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime); + //STDMETHODIMP SetClass(REFCLSID clsid); + //STDMETHODIMP SetStateBits(DWORD grfStateBits, DWORD grfMask); + //STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag); + + // *** IContextMenu methods *** + STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) + { + if (idCmd != 0) + return E_INVALIDARG; + + switch (uFlags) + { + case GCS_VERBA: + return StringCchCopyA(pszName, cchMax, EXTRACT_VERBA); + case GCS_VERBW: + return StringCchCopyW((LPWSTR)pszName, cchMax, EXTRACT_VERBW); + case GCS_HELPTEXTA: + { + CStringA helpText(MAKEINTRESOURCEA(IDS_HELPTEXT)); + return StringCchCopyA(pszName, cchMax, helpText); + } + case GCS_HELPTEXTW: + { + CStringW helpText(MAKEINTRESOURCEA(IDS_HELPTEXT)); + return StringCchCopyW((LPWSTR)pszName, cchMax, helpText); + } + case GCS_VALIDATEA: + case GCS_VALIDATEW: + return S_OK; + } + + return E_INVALIDARG; + } + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici) + { + if (!pici || pici->cbSize != sizeof(*pici)) + return E_INVALIDARG; + + if (pici->lpVerb == MAKEINTRESOURCEA(0) || (HIWORD(pici->lpVerb) && !strcmp(pici->lpVerb, EXTRACT_VERBA))) + { + BSTR ZipFile = m_ZipFile.AllocSysString(); + InterlockedIncrement(&g_ModuleRefCnt); + + DWORD tid; + HANDLE hThread = CreateThread(NULL, 0, s_ExtractProc, ZipFile, NULL, &tid); + if (hThread) + { + CloseHandle(hThread); + return S_OK; + } + } + return E_INVALIDARG; + } + STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) + { + int Entries = 0; + + CStringW menuText(MAKEINTRESOURCEW(IDS_MENUITEM)); + + InsertMenuW(hmenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + Entries++; + InsertMenuW(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst++, menuText); + Entries++; + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Entries); + } + + // *** IShellExtInit methods *** + STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hkeyProgID) + { + FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM stg; + + HRESULT hr = pDataObj->GetData(&etc, &stg); + if (FAILED_UNEXPECTEDLY(hr)) + { + return hr; + } + hr = E_FAIL; + HDROP hdrop = (HDROP)GlobalLock(stg.hGlobal); + if (hdrop) + { + UINT uNumFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, NULL, 0); + if (uNumFiles == 1) + { + WCHAR szFile[MAX_PATH * 2]; + if (DragQueryFileW(hdrop, 0, szFile, _countof(szFile))) + { + CComHeapPtr<ITEMIDLIST> pidl; + hr = SHParseDisplayName(szFile, NULL, &pidl, 0, NULL); + if (!FAILED_UNEXPECTEDLY(hr)) + { + hr = Initialize(pidl); + } + } + else + { + DbgPrint("Failed to query the file.\r\n"); + } + } + else + { + DbgPrint("Invalid number of files: %d\r\n", uNumFiles); + } + GlobalUnlock(stg.hGlobal); + } + else + { + DbgPrint("Could not lock stg.hGlobal\r\n"); + } + ReleaseStgMedium(&stg); + return hr; + + } + + //// IPersistFile + ////STDMETHODIMP GetClassID(CLSID *pclsid); + //STDMETHODIMP IsDirty(); + //STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode); + //STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember); + //STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName); + //STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName); + + //// *** IPersistFolder2 methods *** + STDMETHODIMP GetCurFolder(LPITEMIDLIST * pidl) + { + *pidl = ILClone(m_CurDir); + return S_OK; + } + + // *** IPersistFolder methods *** + STDMETHODIMP Initialize(LPCITEMIDLIST pidl) + { + WCHAR tmpPath[MAX_PATH]; + + if (SHGetPathFromIDListW(pidl, tmpPath)) + { + m_ZipFile = tmpPath; + m_CurDir.Attach(ILClone(pidl)); + return S_OK; + } + DbgPrint("%s() => Unable to parse pidl\n", __FUNCTION__); + return E_INVALIDARG; + } + + // *** IPersist methods *** + STDMETHODIMP GetClassID(CLSID *lpClassId) + { + DbgPrint("%s\n", __FUNCTION__); + return E_NOTIMPL; + } + + + STDMETHODIMP Initialize(PCWSTR zipFile, PCSTR zipDir, PCUIDLIST_ABSOLUTE curDir, PCUIDLIST_RELATIVE pidl) + { + m_ZipFile = zipFile; + m_ZipDir = zipDir; + + m_CurDir.Attach(ILCombine(curDir, pidl)); + return S_OK; + } + static DWORD WINAPI s_ExtractProc(LPVOID arg) + { + CComBSTR ZipFile; + ZipFile.Attach((BSTR)arg); + + _CZipExtract_runWizard(ZipFile); + + InterlockedDecrement(&g_ModuleRefCnt); + return 0; + } + +public: + DECLARE_NO_REGISTRY() // Handled manually because this object is exposed via multiple clsid's + DECLARE_NOT_AGGREGATABLE(CZipFolder) + + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CZipFolder) + COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2) + COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder) +// COM_INTERFACE_ENTRY_IID(IID_IStorage, IStorage) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) + //COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile) + COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) + COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + END_COM_MAP() +}; + diff --git a/dll/shellext/zipfldr/Debug.cpp b/dll/shellext/zipfldr/Debug.cpp new file mode 100644 index 0000000000..35580771db --- /dev/null +++ b/dll/shellext/zipfldr/Debug.cpp @@ -0,0 +1,44 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: Zip extraction + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +static bool GetInterfaceName(const WCHAR* InterfaceString, WCHAR* buf, size_t size) +{ + WCHAR LocalBuf[100]; + DWORD dwType = 0, dwDataSize = size * sizeof(WCHAR); + + if (!SUCCEEDED(StringCchPrintfW(LocalBuf, _countof(LocalBuf), L"Interface\\%s", InterfaceString))) + return false; + + return SHRegGetValueW(HKEY_CLASSES_ROOT, LocalBuf, NULL, RRF_RT_REG_SZ, &dwType, buf, &dwDataSize) == ERROR_SUCCESS; +} + +WCHAR* guid2string(REFCLSID iid) +{ + static WCHAR buf[2][300]; + static int idx = 0; + + idx ^= 1; + + LPOLESTR tmp; + HRESULT hr = ProgIDFromCLSID(iid, &tmp); + if (SUCCEEDED(hr)) + { + wcscpy(buf[idx], tmp); + CoTaskMemFree(tmp); + return buf[idx]; + } + StringFromGUID2(iid, buf[idx], _countof(buf[idx])); + if (GetInterfaceName(buf[idx], buf[idx], _countof(buf[idx]))) + { + return buf[idx]; + } + StringFromGUID2(iid, buf[idx], _countof(buf[idx])); + + return buf[idx]; +} diff --git a/dll/shellext/zipfldr/IZip.hpp b/dll/shellext/zipfldr/IZip.hpp new file mode 100644 index 0000000000..bb16e50fb4 --- /dev/null +++ b/dll/shellext/zipfldr/IZip.hpp @@ -0,0 +1,12 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: IZip + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +struct IZip : public IUnknown +{ + virtual STDMETHODIMP_(unzFile) getZip() PURE; +}; + diff --git a/dll/shellext/zipfldr/precomp.h b/dll/shellext/zipfldr/precomp.h new file mode 100644 index 0000000000..01b92991d5 --- /dev/null +++ b/dll/shellext/zipfldr/precomp.h @@ -0,0 +1,62 @@ +#ifndef ZIPFLDR_PRECOMP_H +#define ZIPFLDR_PRECOMP_H + +#define COBJMACROS +#define COM_NO_WINDOWS_H +#define NTOS_MODE_USER + +#include <windef.h> +#include <winbase.h> +#include <shlobj.h> +#include <atlbase.h> +#include <atlcom.h> +#include <atlcoll.h> +#include <atlstr.h> +#include <rosdlgs.h> +#include <shlwapi.h> +#include <shellapi.h> +#include <strsafe.h> +// debug.h needs this: +#define NTSTATUS LONG +#include <reactos/debug.h> +#include <shellutils.h> + + + +#define EXTRACT_VERBA "extract" +#define EXTRACT_VERBW L"extract" + +EXTERN_C const GUID CLSID_ZipFolderStorageHandler; +EXTERN_C const GUID CLSID_ZipFolderSendTo; +EXTERN_C const GUID CLSID_ZipFolderContextMenu; +EXTERN_C const GUID CLSID_ZipFolderRightDragHandler; +EXTERN_C const GUID CLSID_ZipFolderDropHandler; + +EXTERN_C const GUID CLSID_ZipFolderExtractAllCommand; + +extern LONG g_ModuleRefCnt; + + +#define Win32DbgPrint(file, line, warn, func) DbgPrint("(%s:%d) " warn, file, line, func) +WCHAR* guid2string(REFCLSID iid); + + +#include "minizip/unzip.h" +#include "minizip/ioapi.h" + +extern zlib_filefunc64_def g_FFunc; + +#include "resource.h" + +#include "zippidl.hpp" +#include "IZip.hpp" + +HRESULT _CEnumZipContents_CreateInstance(IZip* zip, DWORD flags, const char* prefix, REFIID riid, LPVOID * ppvOut); +HRESULT _CExplorerCommandProvider_CreateInstance(IContextMenu* zipObject, REFIID riid, LPVOID * ppvOut); +HRESULT _CFolderViewCB_CreateInstance(REFIID riid, LPVOID * ppvOut); +void _CZipExtract_runWizard(PCWSTR Filename); + +#include "CZipEnumerator.hpp" +#include "CZipFolder.hpp" + +#endif /* ZIPFLDR_PRECOMP_H */ diff --git a/dll/shellext/zipfldr/res/zipfldr.ico b/dll/shellext/zipfldr/res/zipfldr.ico new file mode 100644 index 0000000000..04f98dcb2f Binary files /dev/null and b/dll/shellext/zipfldr/res/zipfldr.ico differ diff --git a/dll/shellext/zipfldr/res/zipfldr.rgs b/dll/shellext/zipfldr/res/zipfldr.rgs new file mode 100644 index 0000000000..82cfc8dfae --- /dev/null +++ b/dll/shellext/zipfldr/res/zipfldr.rgs @@ -0,0 +1,54 @@ +HKCR +{ + NoRemove CLSID + { + '{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}' = s 'CompressedFolder' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' } + ProgId = s 'CompressedFolder' + ShellFolder + { + val Attributes = d '0x200001a0' + val UseDropHandler = s '' + } + } + '{b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af}' = s 'Compressed (zipped) Folder Menu' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Apartment' } + } + } + NoRemove Applications + { + 'zipfldr.dll' { val NoOpenWith = s '' } + } + NoRemove CompressedFolder + { + FriendlyTypeName = s '%MODULE%,-10195' + CLSID = s '{E88DCCE0-B7B3-11d1-A9F0-00AA0060FA31}' + DefaultIcon = s '%MODULE%' + + NoRemove Shell + { + NoRemove Open + { + command = s 'rundll32.exe zipfldr.dll,RouteTheCall %%L' + val BrowserFlags = d '0x10' + val ExplorerFlags = d '0x10' + } + } + + NoRemove shellex + { + NoRemove ContextMenuHandlers + { + ForceRemove '{b8cdcb65-b1bf-4b42-9428-1dfdb7ee92af}' = s 'Compressed (zipped) Folder Menu' + { + } + } + } + } + NoRemove '.zip' = s 'CompressedFolder' + { + val 'Content Type' = s 'application/x-zip-compressed' + } +} diff --git a/dll/shellext/zipfldr/resource.h b/dll/shellext/zipfldr/resource.h new file mode 100644 index 0000000000..10cadc742a --- /dev/null +++ b/dll/shellext/zipfldr/resource.h @@ -0,0 +1,58 @@ +#pragma once + +/* registry stuff */ +#define IDR_ZIPFLDR 8000 + + +/* Dialogs */ + +#define IDD_PROPPAGEDESTIONATION 1000 +#define IDC_DIRECTORY 1001 +#define IDC_BROWSE 1002 +#define IDC_PASSWORD 1003 +#define IDC_PROGRESS 1004 + +#define IDD_PROPPAGECOMPLETE 1100 +#define IDC_DESTDIR 1101 +#define IDC_SHOW_EXTRACTED 1102 + +#define IDD_CONFIRM_FILE_REPLACE 1200 +#define IDYESALL 1202 +#define IDC_EXCLAMATION_ICON 1205 +#define IDC_MESSAGE 1206 + + +/* Strings */ +#define IDS_COL_NAME 100 +#define IDS_COL_TYPE 101 +#define IDS_COL_COMPRSIZE 102 +#define IDS_COL_PASSWORD 103 +#define IDS_COL_SIZE 104 +#define IDS_COL_RATIO 105 +#define IDS_COL_DATE_MOD 106 +#define IDS_YES 107 +#define IDS_NO 108 + + +/* Wizard titles */ +#define IDS_WIZ_TITLE 8000 +#define IDS_WIZ_DEST_TITLE 8001 +#define IDS_WIZ_DEST_SUBTITLE 8002 +#define IDS_WIZ_COMPL_TITLE 8003 +#define IDS_WIZ_COMPL_SUBTITLE 8004 + +#define IDS_WIZ_BROWSE_TITLE 8010 + +/* Questions */ +#define IDS_OVERWRITEFILE_TEXT 9000 + + +/* Context menu / ExplorerCommand strings */ +#define IDS_MENUITEM 10039 +#define IDS_HELPTEXT 10041 +#define IDS_FRIENDLYNAME 10195 + + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif diff --git a/dll/shellext/zipfldr/zipfldr.cpp b/dll/shellext/zipfldr/zipfldr.cpp new file mode 100644 index 0000000000..27a354e0a1 --- /dev/null +++ b/dll/shellext/zipfldr/zipfldr.cpp @@ -0,0 +1,117 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: zipfldr entrypoint + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +HMODULE g_hModule = NULL; +LONG g_ModuleRefCnt = 0; + +#include <initguid.h> + +DEFINE_GUID(CLSID_ZipFolderStorageHandler, 0xe88dcce0, 0xb7b3, 0x11d1, 0xa9, 0xf0, 0x00, 0xaa, 0x00, 0x60, 0xfa, 0x31); +DEFINE_GUID(CLSID_ZipFolderSendTo, 0x888dca60, 0xfc0a, 0x11cf, 0x8f, 0x0f, 0x00, 0xc0, 0x4f, 0xd7, 0xd0, 0x62); +DEFINE_GUID(CLSID_ZipFolderContextMenu, 0xb8cdcb65, 0xb1bf, 0x4b42, 0x94, 0x28, 0x1d, 0xfd, 0xb7, 0xee, 0x92, 0xaf); +DEFINE_GUID(CLSID_ZipFolderRightDragHandler,0xbd472f60, 0x27fa, 0x11cf, 0xb8, 0xb4, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); +DEFINE_GUID(CLSID_ZipFolderDropHandler, 0xed9d80b9, 0xd157, 0x457b, 0x91, 0x92, 0x0e, 0x72, 0x80, 0x31, 0x3b, 0xf0); + +/* IExplorerCommand: Extract All */ +DEFINE_GUID(CLSID_ZipFolderExtractAllCommand, 0xc3d9647b, 0x8fd9, 0x4ee6, 0x8b, 0xc7, 0x82, 0x7, 0x80, 0x9, 0x10, 0x5a); + + +class CZipFldrModule : public CComModule +{ +public: +}; + + +BEGIN_OBJECT_MAP(ObjectMap) + OBJECT_ENTRY(CLSID_ZipFolderStorageHandler, CZipFolder) + OBJECT_ENTRY(CLSID_ZipFolderContextMenu, CZipFolder) +END_OBJECT_MAP() + +CZipFldrModule gModule; + + +#include "minizip/ioapi.h" +#include "minizip/iowin32.h" + +zlib_filefunc64_def g_FFunc; + +static void init_zlib() +{ + fill_win32_filefunc64W(&g_FFunc); +} + +EXTERN_C +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + switch (dwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hInstance); + g_hModule = hInstance; + gModule.Init(ObjectMap, hInstance, NULL); + init_zlib(); + break; + } + + return TRUE; +} + +STDAPI DllCanUnloadNow() +{ + if (g_ModuleRefCnt) + return S_FALSE; + return gModule.DllCanUnloadNow(); +} + +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + return gModule.DllGetClassObject(rclsid, riid, ppv); +} + +STDAPI DllRegisterServer() +{ + HRESULT hr; + + hr = gModule.DllRegisterServer(FALSE); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = gModule.UpdateRegistryFromResource(IDR_ZIPFLDR, TRUE, NULL); + if (FAILED(hr)) + return hr; + + return S_OK; +} + +STDAPI DllUnregisterServer() +{ + HRESULT hr; + + hr = gModule.DllUnregisterServer(FALSE); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = gModule.UpdateRegistryFromResource(IDR_ZIPFLDR, FALSE, NULL); + if (FAILED(hr)) + return hr; + + return S_OK; +} + +EXTERN_C +BOOL WINAPI +RouteTheCall( + IN HWND hWndOwner, + IN HINSTANCE hInstance, + IN LPWSTR lpNamedPipeName, + IN INT Show) +{ + UNIMPLEMENTED; + return FALSE; +} diff --git a/dll/shellext/zipfldr/zipfldr.rc b/dll/shellext/zipfldr/zipfldr.rc new file mode 100644 index 0000000000..0b577b5f3e --- /dev/null +++ b/dll/shellext/zipfldr/zipfldr.rc @@ -0,0 +1,88 @@ +#include <windef.h> +#include <winuser.h> + +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +1 ICON "res/zipfldr.ico" + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Zip Shell Extension" +#define REACTOS_STR_INTERNAL_NAME "zipfldr" +#define REACTOS_STR_ORIGINAL_FILENAME "zipfldr.dll" +#include <reactos/version.rc> + +#include <reactos/manifest_dll.rc> + +IDR_ZIPFLDR REGISTRY "res/zipfldr.rgs" + + + +IDD_PROPPAGEDESTIONATION DIALOGEX 0, 0, 235, 156 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Select a Destination" +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + LTEXT "Select the destionation directory",IDC_STATIC,6,12,174,8 + EDITTEXT IDC_DIRECTORY,6,24,222,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse...",IDC_BROWSE,174,42,54,14 + PUSHBUTTON "Password",IDC_PASSWORD,174,66,54,14 + LTEXT "Extracting...",IDC_STATIC,6,114,42,8 + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,6,126,222,6 +END + + +IDD_PROPPAGECOMPLETE DIALOGEX 0, 0, 235, 156 +STYLE DS_SHELLFONT | WS_CHILD | WS_DISABLED | WS_CAPTION +CAPTION "Extraction Complete" +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + LTEXT "The files have been extracted to the following directory:",IDC_STATIC,6,12,222,18 + LTEXT "Target dir",IDC_DESTDIR,6,36,222,8 + CONTROL "Show extracted files",IDC_SHOW_EXTRACTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,66,81,10 + LTEXT "Press finish to continue.",IDC_STATIC,6,84,174,8 +END + + +IDD_CONFIRM_FILE_REPLACE DIALOGEX 0, 0, 273, 56 +STYLE DS_MODALFRAME | DS_SHELLFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm File Replace" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&Yes",IDYES,6,36,62,14 + PUSHBUTTON "Cancel",IDCANCEL,204,36,62,14 + PUSHBUTTON "Yes &To All",IDYESALL,72,36,62,14 + PUSHBUTTON "&No",IDNO,138,36,62,14 + ICON "",IDC_EXCLAMATION_ICON,6,6,24,22 + LTEXT "",IDC_MESSAGE,36,6,228,24 +END + + + +STRINGTABLE +BEGIN + IDS_COL_NAME "Name" + IDS_COL_TYPE "Type" + IDS_COL_COMPRSIZE "Compressed size" + IDS_COL_PASSWORD "Password" + IDS_COL_SIZE "Size" + IDS_COL_RATIO "Ratio" + IDS_COL_DATE_MOD "Date modified" + IDS_YES "Yes" + IDS_NO "No" + + IDS_WIZ_TITLE "Extraction Wizard" + IDS_WIZ_DEST_TITLE "Select a Destination" + IDS_WIZ_DEST_SUBTITLE "The files from the zip archive will be extracted to the location specified." + IDS_WIZ_COMPL_TITLE "Extraction Complete" + IDS_WIZ_COMPL_SUBTITLE "The files from the zip archive have been extracted." + IDS_WIZ_BROWSE_TITLE "Select the place where you want to extract the selected items." + + IDS_OVERWRITEFILE_TEXT "This folder already contains a file called '%1'.\nDo you want to replace it?" + + IDS_MENUITEM "Extract &All..." + IDS_HELPTEXT "Extracts folder contents" + IDS_FRIENDLYNAME "Compressed (zipped) Folder" + +END diff --git a/dll/shellext/zipfldr/zipfldr.spec b/dll/shellext/zipfldr/zipfldr.spec new file mode 100644 index 0000000000..8b689b5e12 --- /dev/null +++ b/dll/shellext/zipfldr/zipfldr.spec @@ -0,0 +1,5 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() +@ stdcall RouteTheCall(ptr ptr wstr long) \ No newline at end of file diff --git a/dll/shellext/zipfldr/zippidl.cpp b/dll/shellext/zipfldr/zippidl.cpp new file mode 100644 index 0000000000..1e1eb9f57f --- /dev/null +++ b/dll/shellext/zipfldr/zippidl.cpp @@ -0,0 +1,42 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: zip pidl handling + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + +#include "precomp.h" + +LPITEMIDLIST _ILCreate(ZipPidlType Type, LPCSTR lpString, unz_file_info64& info) +{ + int cbData = sizeof(ZipPidlEntry) + strlen(lpString); + ZipPidlEntry* pidl = (ZipPidlEntry*)SHAlloc(cbData + sizeof(WORD)); + if (!pidl) + return NULL; + + pidl->cb = cbData; + pidl->MagicType = 'z'; + pidl->ZipType = Type; + + if (Type != ZIP_PIDL_DIRECTORY) + { + pidl->CompressedSize = info.compressed_size; + pidl->UncompressedSize = info.uncompressed_size; + pidl->DosDate = info.dosDate; + pidl->Password = info.flag & 1; + } + + strcpy(pidl->Name, lpString); + *(WORD*)((char*)pidl + cbData) = 0; + + return (LPITEMIDLIST)pidl; +} + + +const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl) +{ + const ZipPidlEntry* zipPidl = (const ZipPidlEntry*)pidl; + if (zipPidl->MagicType == 'z') + return zipPidl; + return NULL; +} diff --git a/dll/shellext/zipfldr/zippidl.hpp b/dll/shellext/zipfldr/zippidl.hpp new file mode 100644 index 0000000000..8c81158525 --- /dev/null +++ b/dll/shellext/zipfldr/zippidl.hpp @@ -0,0 +1,34 @@ +/* + * PROJECT: ReactOS Zip Shell Extension + * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) + * PURPOSE: zip pidl handling + * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + */ + + +enum ZipPidlType +{ + ZIP_PIDL_DIRECTORY, + ZIP_PIDL_FILE +}; + +#include <pshpack1.h> +struct ZipPidlEntry +{ + WORD cb; + BYTE MagicType; + ZipPidlType ZipType; + + ULONG64 CompressedSize; + ULONG64 UncompressedSize; + ULONG DosDate; + BYTE Password; + + char Name[1]; +}; +#include <poppack.h> + + +LPITEMIDLIST _ILCreate(ZipPidlType Type, LPCSTR lpString, unz_file_info64& info); +const ZipPidlEntry* _ZipFromIL(LPCITEMIDLIST pidl); +
6 years, 8 months
1
0
0
0
04/06: [ZLIB] Add minizip as library. CORE-7684
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5100859e06f46c6860ee7…
commit 5100859e06f46c6860ee7ac8c27772a8433633a9 Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Tue Apr 3 22:15:20 2018 +0200 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Apr 7 15:29:59 2018 +0200 [ZLIB] Add minizip as library. CORE-7684 --- sdk/lib/3rdparty/zlib/CMakeLists.txt | 14 + .../zlib/contrib/minizip/MiniZip64_info.txt | 74 + sdk/lib/3rdparty/zlib/contrib/minizip/crypt.h | 131 ++ sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.c | 250 +++ sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.h | 208 ++ sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.c | 462 +++++ sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.h | 28 + sdk/lib/3rdparty/zlib/contrib/minizip/unzip.c | 2128 ++++++++++++++++++++ sdk/lib/3rdparty/zlib/contrib/minizip/unzip.h | 437 ++++ sdk/lib/3rdparty/zlib/contrib/minizip/zip.c | 2012 ++++++++++++++++++ sdk/lib/3rdparty/zlib/contrib/minizip/zip.h | 362 ++++ 11 files changed, 6106 insertions(+) diff --git a/sdk/lib/3rdparty/zlib/CMakeLists.txt b/sdk/lib/3rdparty/zlib/CMakeLists.txt index b8b2061264..12b02fb3d9 100644 --- a/sdk/lib/3rdparty/zlib/CMakeLists.txt +++ b/sdk/lib/3rdparty/zlib/CMakeLists.txt @@ -21,10 +21,24 @@ list(APPEND SOURCE infback.c uncompr.c) +list(APPEND MINIZIP_SOURCE + contrib/minizip/crypt.h + contrib/minizip/ioapi.c + contrib/minizip/ioapi.h + contrib/minizip/iowin32.c + contrib/minizip/iowin32.h + contrib/minizip/unzip.c + contrib/minizip/unzip.h + contrib/minizip/zip.c + contrib/minizip/zip.h) + + if(CMAKE_CROSSCOMPILING) add_library(zlib ${SOURCE} ${SOLO_SOURCE}) add_library(zlib_solo ${SOLO_SOURCE}) add_target_compile_definitions(zlib_solo Z_SOLO) + add_library(minizip ${MINIZIP_SOURCE}) + add_dependencies(minizip xdk) else() add_library(zlibhost ${SOLO_SOURCE}) add_target_compile_definitions(zlibhost Z_SOLO) diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/MiniZip64_info.txt b/sdk/lib/3rdparty/zlib/contrib/minizip/MiniZip64_info.txt new file mode 100644 index 0000000000..57d7152420 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/MiniZip64_info.txt @@ -0,0 +1,74 @@ +MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson + +Introduction +--------------------- +MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant (
http://www.winimage.com/zLibDll/minizip.html
) + +When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. +All possible work was done for compatibility. + + +Background +--------------------- +When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 +support for unzip.c into minizip for a open source project called gdal (
http://www.gdal.org/
) + +That was used as a starting point. And after that ZIP64 support was added to zip.c +some refactoring and code cleanup was also done. + + +Changed from MiniZip 1.0 to MiniZip 1.1 +--------------------------------------- +* Added ZIP64 support for unzip ( by Even Rouault ) +* Added ZIP64 support for zip ( by Mathias Svensson ) +* Reverted some changed that Even Rouault did. +* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. +* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) +* Added BZIP Compress method for zip +* Did some refactoring and code cleanup + + +Credits + + Gilles Vollant - Original MiniZip author + Even Rouault - ZIP64 unzip Support + Daniel Borca - BZip Compression method support in unzip + Mathias Svensson - ZIP64 zip support + Mathias Svensson - BZip Compression method support in zip + + Resources + + ZipLayout
http://result42.com/projects/ZipFileLayout
+ Command line tool for Windows that shows the layout and information of the headers in a zip archive. + Used when debugging and validating the creation of zip files using MiniZip64 + + + ZIP App Note
http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+ Zip File specification + + +Notes. + * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. + +License +---------------------------------------------------------- + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------------- + diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/crypt.h b/sdk/lib/3rdparty/zlib/contrib/minizip/crypt.h new file mode 100644 index 0000000000..1e9e8200b2 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/crypt.h @@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page +
http://www.winzip.com/aes_info.htm
) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const z_crc_t* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize<RAND_HEAD_LEN) + return 0; + + /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the + * output of rand() to get less predictability, since rand() is + * often poorly implemented. + */ + if (++calls == 1) + { + srand((unsigned)(time(NULL) ^ ZCR_SEED2)); + } + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + c = (rand() >> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.c b/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.c new file mode 100644 index 0000000000..754a98eff1 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.c @@ -0,0 +1,250 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + +*/ + +#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(__APPLE__) || defined(IOAPI_NO_64) +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == MAXU32) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +#ifndef __REACTOS__ +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = FTELLO_FUNC((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +#endif diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.h b/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.h new file mode 100644 index 0000000000..8dcbdb06e3 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/ioapi.h @@ -0,0 +1,208 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif + +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "zlib.h" + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef __FreeBSD__ +#define fopen64 fopen +#define ftello64 ftello +#define fseeko64 fseeko +#endif +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include <stdint.h> + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#define MAXU32 0xffffffff + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.c b/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.c new file mode 100644 index 0000000000..cec9b4a046 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.c @@ -0,0 +1,462 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + +*/ + +#include <stdlib.h> + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + +// see Include/shared/winapifamily.h in the Windows Kit +#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) +#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) +#define IOWIN32_USING_WINRT_API 1 +#endif +#endif + +voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); +uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); +long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); +int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + + +static void win32_translate_open_mode(int mode, + DWORD* lpdwDesiredAccess, + DWORD* lpdwCreationDisposition, + DWORD* lpdwShareMode, + DWORD* lpdwFlagsAndAttributes) +{ + *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + *lpdwDesiredAccess = GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + *lpdwShareMode = FILE_SHARE_READ; + } + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + } + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = CREATE_ALWAYS; + } +} + +static voidpf win32_build_iowin(HANDLE hFile) +{ + voidpf ret=NULL; + + if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + + if (ret==NULL) + CloseHandle(hFile); + else + *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + +voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) +{ + //const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) +{ + //const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) +{ + //const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) +{ + //const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) +{ +#ifdef IOWIN32_USING_WINRT_API + return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); +#else + LONG lHigh = pos.HighPart; + DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); + BOOL fOk = TRUE; + if (dwNewPos == 0xFFFFFFFF) + if (GetLastError() != NO_ERROR) + fOk = FALSE; + if ((newPos != NULL) && (fOk)) + { + newPos->LowPart = dwNewPos; + newPos->HighPart = lHigh; + } + return fOk; +#endif +} + +long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)pos.LowPart; + } + return ret; +} + +ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret= (ZPOS64_T)-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = (ZPOS64_T)-1; + } + else + ret=pos.QuadPart; + } + return ret; +} + + +long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + long ret=-1; + + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.h b/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.h new file mode 100644 index 0000000000..0ca0969a7d --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/iowin32.h @@ -0,0 +1,28 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + +*/ + +#include <windows.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.c b/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.c new file mode 100644 index 0000000000..c88b4b7de1 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.c @@ -0,0 +1,2128 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at:
ftp://ftp.info-zip.org/pub/infozip/license.html
+ + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifndef NOUNCRYPT + #define NOUNCRYPT +#endif + +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant -
http://www.winimage.com/zLibDll
"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been successfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1<c2) + return -1; + if (c1>c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos ; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + 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; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; +#ifndef __REACTOS__ + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else +#endif + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&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 (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + 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 (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pos<us.offset_central_dir+us.size_central_dir) && + (err==UNZ_OK)) + err=UNZ_BADZIPFILE; + + if (err!=UNZ_OK) + { + ZCLOSE64(us.z_filefunc, us.filestream); + return NULL; + } + + us.byte_before_the_zipfile = central_pos - + (us.offset_central_dir+us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + us.encrypted = 0; + + + s=(unz64_s*)ALLOC(sizeof(unz64_s)); + if( s != NULL) + { + *s=us; + unzGoToFirstFile((unzFile)s); + } + return (unzFile)s; +} + +#ifndef __REACTOS__ +extern unzFile ZEXPORT unzOpen2 (const char *path, + zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0); + } + else + return unzOpenInternal(path, NULL, 0); +} +#endif + +extern unzFile ZEXPORT unzOpen2_64 (const void *path, + zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1); + } + else + return unzOpenInternal(path, NULL, 1); +} + +extern unzFile ZEXPORT unzOpen (const char *path) +{ + return unzOpenInternal(path, NULL, 0); +} + +extern unzFile ZEXPORT unzOpen64 (const void *path) +{ + return unzOpenInternal(path, NULL, 1); +} + +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzClose (unzFile file) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + if (s->pfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + 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. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(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)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename<fileNameBufferSize) + { + *(szFileName+file_info.size_filename)='\0'; + uSizeRead = file_info.size_filename; + } + else + uSizeRead = fileNameBufferSize; + + if ((file_info.size_filename>0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extra<extraFieldBufferSize) + uSizeRead = file_info.size_file_extra; + else + uSizeRead = extraFieldBufferSize; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == MAXU32) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_comment<commentBufferSize) + { + *(szComment+file_info.size_file_comment)='\0'; + uSizeRead = file_info.size_file_comment; + } + else + uSizeRead = commentBufferSize; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + + 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; + + return err; +} + + + +/* + 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. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if ((err==UNZ_OK) && (pfile_info != NULL)) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_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. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + 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 = unz64local_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; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + 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 +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + 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; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&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) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&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 (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&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; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&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; + + return err; +} + +/* + 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. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(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->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + 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; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + 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; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* 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->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_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->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)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->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + 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) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;i<uReadThis;i++) + pfile_in_zip_read_info->read_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + 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 = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + 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->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(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; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(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) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_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->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +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) + + 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 +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + 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); + + 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 (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_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->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + 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 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_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; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.h b/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.h new file mode 100644 index 0000000000..2104e39150 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/unzip.h @@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong 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_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_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. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + 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 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + 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. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + 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 +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((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) + + if buf==NULL, it return the size of the local extra field + + 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 +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/sdk/lib/3rdparty/zlib/contrib/minizip/zip.c b/sdk/lib/3rdparty/zlib/contrib/minizip/zip.c new file mode 100644 index 0000000000..d5ab730933 --- /dev/null +++ b/sdk/lib/3rdparty/zlib/contrib/minizip/zip.c @@ -0,0 +1,2012 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - (
http://www.winimage.com/zLibDll/minizip.html
) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) (
http://www.winimage.com/zLibDll/minizip.html
) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson (
http://result42.com
) + + For more info read MiniZip_info.txt + + Changes + Oct-2009 - Mathias Svensson - Remove old C style function prototypes + Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives + Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. + Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data + It is used when recreting zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. + Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include <stddef.h> +# include <string.h> +# include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include <errno.h> +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant -
http://www.winimage.com/zLibDll
"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignment */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralExtra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; + int zip64; /* Add ZIP64 extened information in the extra field */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T totalCompressedData; + ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile64_info ci; /* info on the file curretly writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writing_offset; + ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;i<copy_this;i++) + *(to_copy+i)=*(from_copy+i); + + ldi->filled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ + uLong year = (uLong)ptm->tm_year; + if (year>=1980) + year-=1980; + else if (year>=80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<24; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<32; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<40; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<48; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<56; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos ; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + 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; + } + TRYFREE(buf); + return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackRead<uMaxBack) + { + uLong uReadSize; + ZPOS64_T uReadPos; + int i; + if (uBackRead+BUFREADCOMMENT>uMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + { + // Signature "0x07064b50" Zip64 end of central directory locater + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + } + + if (uPosFound!=0) + break; + } + + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) + return 0; + + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto Zip64 end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + return 0; + + return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ + int err=ZIP_OK; + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory */ + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry; + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong VersionMadeBy; + uLong VersionNeeded; + uLong size_comment; + + int hasZIP64Record = 0; + + // check first if we find a ZIP64 record + central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); + if(central_pos > 0) + { + hasZIP64Record = 1; + } + else if(central_pos == 0) + { + central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); + } + +/* disable to allow appending to empty ZIP archive + if (central_pos==0) + err=ZIP_ERRNO; +*/ + + if(hasZIP64Record) + { + ZPOS64_T sizeEndOfCentralDirectory; + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version made by */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version needed to extract */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + // TODO.. + // read the comment from the standard central header. + size_comment = 0; + } + else + { + // Read End of central Directory info + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry = uL; + + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry_CD = uL; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + size_central_dir = uL; + + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + offset_central_dir = uL; + + + /* zipfile global comment length */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + } + + if ((central_pos<offset_central_dir+size_central_dir) && + (err==ZIP_OK)) + err=ZIP_BADZIPFILE; + + if (err!=ZIP_OK) + { + ZCLOSE64(pziinit->z_filefunc, pziinit->filestream); + return ZIP_ERRNO; + } + + if (size_comment>0) + { + pziinit->globalcomment = (char*)ALLOC(size_comment+1); + if (pziinit->globalcomment) + { + size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); + pziinit->globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; + + { + ZPOS64_T size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + pziinit->begin_pos = byte_before_the_zipfile; + pziinit->number_entry = number_entry_CD; + + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal* zi; + int err=ZIP_OK; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; +#ifndef __REACTOS__ + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else +#endif + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writing_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + + zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); + if (zi==NULL) + { + ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + // Read and Cache Central Directory Records + err = LoadCentralDirectoryRecord(&ziinit); + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +#ifndef __REACTOS__ +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} +#endif + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ + return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ + return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ + /* write the local header */ + int err; + uInt size_filename = (uInt)strlen(filename); + uInt size_extrafield = size_extrafield_local; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + } + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if(zi->ci.zip64) + { + size_extrafield += 20; + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + + if ((err==ZIP_OK) && (size_filename > 0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + } + + if ((err==ZIP_OK) && (size_extrafield_local > 0)) + { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + + if ((err==ZIP_OK) && (zi->ci.zip64)) + { + // write the Zip64 extended info + short HeaderID = 1; + short DataSize = 16; + ZPOS64_T CompressedSize = 0; + ZPOS64_T UncompressedSize = 0; + + // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); + } + + return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + (crcForCrypting); + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 + if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) + return ZIP_PARAMERROR; +#else + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; +#endif + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.flag = flagBase; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; + zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + + zi->ci.size_centralExtra = size_extrafield_global; + zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + if(zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); + + for (i=0;i<size_filename;i++) + *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;i<size_extrafield_global;i++) ... 1203 lines suppressed ...
6 years, 8 months
1
0
0
0
03/06: [SHELL32_APITEST] Show that our current SHCreateFileExtractIconW is incorrect. CORE-14082
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7fe78f2779bf47a9e2d14…
commit 7fe78f2779bf47a9e2d1495f96b56fce8fb8060e Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Tue Mar 27 19:58:43 2018 +0200 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Apr 7 15:29:59 2018 +0200 [SHELL32_APITEST] Show that our current SHCreateFileExtractIconW is incorrect. CORE-14082 --- .../apitests/shell32/SHCreateFileExtractIconW.cpp | 172 ++++++++++++++------- 1 file changed, 113 insertions(+), 59 deletions(-) diff --git a/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp b/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp index b48054ee86..144ce8128e 100644 --- a/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp +++ b/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp @@ -2,7 +2,7 @@ * PROJECT: ReactOS API tests * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+
) * PURPOSE: Test for SHCreateFileExtractIconW - * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org) + * COPYRIGHT: Copyright 2017,2018 Mark Jansen (mark.jansen(a)reactos.org) */ #include "shelltest.h" @@ -35,6 +35,22 @@ static TestData IconTests[] = { NULL, FILE_ATTRIBUTE_DIRECTORY }, }; +struct TestIID +{ + const GUID* IID; + HRESULT ExpectedCreate; + HRESULT ExpectedQueryInterface; +}; + +static TestIID InterfaceTests[] = +{ + { &IID_IDefaultExtractIconInit, E_NOINTERFACE, E_NOINTERFACE }, + { &IID_IExtractIconW, S_OK, S_OK }, + { &IID_IExtractIconA, S_OK, S_OK }, + { &IID_IPersist, E_NOINTERFACE, E_NOINTERFACE }, + { &IID_IPersistFile, E_NOINTERFACE, E_NOINTERFACE }, +}; + static void ExtractOneBitmap(HBITMAP hbm, CComHeapPtr<BYTE>& data, DWORD& size) { @@ -81,6 +97,9 @@ START_TEST(SHCreateFileExtractIconW) HICON myIcon; pSHCreateFileExtractIconW = (HRESULT (__stdcall *)(LPCWSTR, DWORD, REFIID, void **))GetProcAddress(shell32, "SHCreateFileExtractIconW"); + /* Show that icons returned are always the same */ + UINT tryFlags[4] = { 0, GIL_FORSHORTCUT, GIL_OPENICON }; + CoInitialize(NULL); GetModuleFileNameW(NULL, CurrentModule, _countof(CurrentModule)); @@ -101,6 +120,24 @@ START_TEST(SHCreateFileExtractIconW) return; } + for (size_t n = 0; n < _countof(InterfaceTests); ++n) + { + { + CComPtr<IUnknown> spUnknown; + HRESULT hr = pSHCreateFileExtractIconW(L"test.txt", FILE_ATTRIBUTE_NORMAL, *InterfaceTests[n].IID, (void**)&spUnknown); + ok(hr == InterfaceTests[n].ExpectedCreate, "Expected hr to be 0x%lx, was 0x%lx for %u\n", InterfaceTests[n].ExpectedCreate, hr, n); + } + + { + CComPtr<IUnknown> spUnknown, spUnknown2; + HRESULT hr = pSHCreateFileExtractIconW(L"test.txt", FILE_ATTRIBUTE_NORMAL, IID_PPV_ARG(IUnknown, &spUnknown)); + ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %u\n", hr, n); + + hr = spUnknown->QueryInterface(*InterfaceTests[n].IID, (void**)&spUnknown2); + ok(hr == InterfaceTests[n].ExpectedQueryInterface, "Expected hr to be 0x%lx, was 0x%lx for %u\n", InterfaceTests[n].ExpectedQueryInterface, hr, n); + } + } + for (size_t n = 0; n < _countof(IconTests); ++n) { TestData& cur = IconTests[n]; @@ -119,85 +156,102 @@ START_TEST(SHCreateFileExtractIconW) if (!SUCCEEDED(hr)) continue; - int ilIndex = -1; - UINT wFlags = 0xdeaddead; - WCHAR Buffer[MAX_PATH]; + /* Show that GIL_DEFAULTICON does not work. */ + { + int ilIndex = -1; + UINT wFlags = 0xdeaddead; + WCHAR Buffer[MAX_PATH]; + + hr = spExtract->GetIconLocation(GIL_DEFAULTICON, Buffer, _countof(Buffer), &ilIndex, &wFlags); + ok(hr == S_FALSE, "Expected hr to be S_FALSE, was 0x%lx for %S(0x%lx)\n", hr, cur.Name, cur.dwFlags); + } - hr = spExtract->GetIconLocation(0, Buffer, _countof(Buffer), &ilIndex, &wFlags); - ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr, cur.Name, cur.dwFlags); - if (!SUCCEEDED(hr)) - continue; - ok(wFlags & (GIL_NOTFILENAME|GIL_PERCLASS), "Expected GIL_NOTFILENAME|GIL_PERCLASS to be set for %S(%lx)\n", cur.Name, cur.dwFlags); - ok(!wcscmp(Buffer, L"*"), "Expected '*', was '%S' for %S(%lx)\n", Buffer, cur.Name, cur.dwFlags); + for (UINT idFlags = 0; idFlags < _countof(tryFlags); ++idFlags) + { + int ilIndex = -1; + UINT wFlags = 0xdeaddead; + WCHAR Buffer[MAX_PATH]; - HICON ico; - hr = spExtract->Extract(Buffer, ilIndex, &ico, NULL, 0); + hr = spExtract->GetIconLocation(tryFlags[idFlags], Buffer, _countof(Buffer), &ilIndex, &wFlags); + ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(0x%lx,0x%x)\n", hr, cur.Name, cur.dwFlags, tryFlags[idFlags]); + if (!SUCCEEDED(hr)) + continue; - /* Visualize the icon extracted for whoever is stepping through this code. */ - HWND console = GetConsoleWindow(); - SendMessage(console, WM_SETICON, ICON_BIG, (LPARAM)ico); - SendMessage(console, WM_SETICON, ICON_SMALL, (LPARAM)ico); + ok(wFlags & (GIL_NOTFILENAME|GIL_PERCLASS), "Expected GIL_NOTFILENAME|GIL_PERCLASS to be set for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]); + ok(!wcscmp(Buffer, L"*"), "Expected '*', was '%S' for %S(0x%lx,0x%x)\n", Buffer, cur.Name, cur.dwFlags, tryFlags[idFlags]); - CComHeapPtr<BYTE> colorData, maskData; - DWORD colorSize = 0, maskSize = 0; + HICON ico; + hr = spExtract->Extract(Buffer, ilIndex, &ico, NULL, 0); - GetIconData(ico, colorData, colorSize, maskData, maskSize); + /* Visualize the icon extracted for whoever is stepping through this code. */ + HWND console = GetConsoleWindow(); + SendMessage(console, WM_SETICON, ICON_BIG, (LPARAM)ico); + SendMessage(console, WM_SETICON, ICON_SMALL, (LPARAM)ico); - if (!colorSize || !maskSize) - continue; + CComHeapPtr<BYTE> colorData, maskData; + DWORD colorSize = 0, maskSize = 0; - SHFILEINFOW shfi; - ULONG_PTR firet = SHGetFileInfoW(cur.Name, cur.dwFlags, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON); + GetIconData(ico, colorData, colorSize, maskData, maskSize); - if (!firet) - continue; + if (!colorSize || !maskSize) + continue; - CComHeapPtr<BYTE> colorDataRef, maskDataRef; - DWORD colorSizeRef = 0, maskSizeRef = 0; - GetIconData(shfi.hIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef); + SHFILEINFOW shfi; + ULONG_PTR firet = SHGetFileInfoW(cur.Name, cur.dwFlags, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SYSICONINDEX); - ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(%lx)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags); - ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags); + if (!firet) + continue; - if (colorSizeRef == colorSize) - { - ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(%lx)\n", cur.Name, cur.dwFlags); - } + ok(shfi.iIcon == ilIndex, "Expected ilIndex to be 0%x, was 0x%x for %S(0x%lx,0x%x)\n", shfi.iIcon, ilIndex, cur.Name, cur.dwFlags, tryFlags[idFlags]); - if (maskSizeRef == maskSize) - { - ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(%lx)\n", cur.Name, cur.dwFlags); - } - if (useMyIcon) - { - colorDataRef.Free(); - maskDataRef.Free(); - colorSizeRef = maskSizeRef = 0; - GetIconData(myIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef); + CComHeapPtr<BYTE> colorDataRef, maskDataRef; + DWORD colorSizeRef = 0, maskSizeRef = 0; + GetIconData(shfi.hIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef); - ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(%lx)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags); - ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags); + ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags, tryFlags[idFlags]); + ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags, tryFlags[idFlags]); if (colorSizeRef == colorSize) { - /* Incase requested filetype does not match, the exe icon is not used! */ - if (cur.dwFlags == FILE_ATTRIBUTE_DIRECTORY) - { - ok(memcmp(colorData, colorDataRef, colorSize), "Expected colorData to be changed for %S(%lx)\n", cur.Name, cur.dwFlags); - } - else + ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]); + } + + if (maskSizeRef == maskSize) + { + ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]); + } + + if (useMyIcon) + { + colorDataRef.Free(); + maskDataRef.Free(); + colorSizeRef = maskSizeRef = 0; + GetIconData(myIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef); + + ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags, tryFlags[idFlags]); + ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(0x%lx,0x%x)\n", maskSizeRef, maskSize, cur.Name, cur.dwFlags, tryFlags[idFlags]); + + if (colorSizeRef == colorSize) { - ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(%lx)\n", cur.Name, cur.dwFlags); + /* In case requested filetype does not match, the exe icon is not used! */ + if (cur.dwFlags == FILE_ATTRIBUTE_DIRECTORY) + { + ok(memcmp(colorData, colorDataRef, colorSize), "Expected colorData to be changed for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]); + } + else + { + ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal colorData for %S(0x%lx,0x%x)\n", cur.Name, cur.dwFlags, tryFlags[idFlags]); + } } - } - // Mask is not reliable for some reason - //if (maskSizeRef == maskSize) - //{ - // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(%lx)\n", cur.Name, cur.dwFlags); - //} + // Mask is not reliable for some reason + //if (maskSizeRef == maskSize) + //{ + // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData for %S(0x%lx,0x%lx)\n", cur.Name, cur.dwFlags); + //} + } } } }
6 years, 8 months
1
0
0
0
← Newer
1
...
13
14
15
16
17
18
19
...
25
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Results per page:
10
25
50
100
200