From f7d692ca5448140fb21ffa42ca8b1535aae0b490 Mon Sep 17 00:00:00 2001 From: shrikant Date: Fri, 24 Apr 2015 17:35:51 -0700 Subject: [PATCH] Try NtDuplicateObject instead of DuplicateHandle on Windows 8/8.1 for debugging AppContainer related failures. This patch should be reverted as soon as we get some confirmation that NtDuplicateObject is working better compared to DuplicateHandle. Theory behind this patch is that it might be possible that on machines which reporting this find of failure have some software like AV which might be intercepting calls to DuplciateHandle and may be failing somewhere in intercepted code path due to AppContainer. Looking in IDA error code that we are receiving 0xC0000023 (Which translates INSUFFICIENT_BUFFER (0x7a) in win32 language) doesn't seem to be in NtDuplicateObject code path (At least not found easily.). BUG=468922 R=jschuh@chromium.org,cpu@chromium.org Review URL: https://codereview.chromium.org/1101913002 Cr-Commit-Position: refs/heads/master@{#326943} --- base/win/scoped_process_information.cc | 49 +++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc index bb2463774a8a32..634a538eece513 100644 --- a/base/win/scoped_process_information.cc +++ b/base/win/scoped_process_information.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" namespace base { namespace win { @@ -20,11 +21,49 @@ bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) { return true; HANDLE temp = NULL; - if (!::DuplicateHandle(::GetCurrentProcess(), source, - ::GetCurrentProcess(), &temp, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - DPLOG(ERROR) << "Failed to duplicate a handle."; - return false; + + // TODO(shrikant): Remove following code as soon as we gather some + // information regarding AppContainer related DuplicateHandle failures that + // only seem to happen on certain machine and only random launches (normally + // renderer launches seem to succeed even on those machines.) + if (base::win::GetVersion() == base::win::VERSION_WIN8 || + base::win::GetVersion() == base::win::VERSION_WIN8_1) { + typedef LONG (WINAPI *NtDuplicateObject)( + IN HANDLE SourceProcess, + IN HANDLE SourceHandle, + IN HANDLE TargetProcess, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes, + IN ULONG Options); + + typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status); + + NtDuplicateObject nt_duplicate_object = + reinterpret_cast(::GetProcAddress( + GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject")); + if (nt_duplicate_object != NULL) { + LONG status = nt_duplicate_object(::GetCurrentProcess(), source, + ::GetCurrentProcess(), &temp, + 0, FALSE, DUPLICATE_SAME_ACCESS); + if (status < 0) { + DPLOG(ERROR) << "Failed to duplicate a handle."; + RtlNtStatusToDosError ntstatus_to_doserror = + reinterpret_cast(::GetProcAddress( + GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError")); + if (ntstatus_to_doserror != NULL) { + ::SetLastError(ntstatus_to_doserror(status)); + } + return false; + } + } + } else { + if (!::DuplicateHandle(::GetCurrentProcess(), source, + ::GetCurrentProcess(), &temp, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + DPLOG(ERROR) << "Failed to duplicate a handle."; + return false; + } } target->Set(temp); return true;