15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/service_resolver.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "sandbox/win/src/sandbox_nt_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/win_utils.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma pack(push, 1)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG kMmovR10EcxMovEax = 0xB8D18B4C;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const USHORT kSyscall = 0x050F;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BYTE kRetNp = 0xC3;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG64 kMov1 = 0x54894808244C8948;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG64 kMov2 = 0x4C182444894C1024;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ULONG kMov3 = 0x20244C89;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for 64 bit systems.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceEntry {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This struct contains roughly the following code:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 00 mov     r10,rcx
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 03 mov     eax,52h
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 08 syscall
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0a ret
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0b xchg    ax,ax
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0e xchg    ax,ax
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG mov_r10_rcx_mov_eax;  // = 4C 8B D1 B8
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG service_id;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT syscall;             // = 0F 05
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BYTE ret;                   // = C3
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BYTE pad;                   // = 66
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT xchg_ax_ax1;         // = 66 90
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT xchg_ax_ax2;         // = 66 90
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Service code for 64 bit Windows 8.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceEntryW8 {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This struct contains the following code:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 00 48894c2408      mov     [rsp+8], rcx
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 05 4889542410      mov     [rsp+10], rdx
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0a 4c89442418      mov     [rsp+18], r8
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0f 4c894c2420      mov     [rsp+20], r9
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 14 4c8bd1          mov     r10,rcx
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 17 b825000000      mov     eax,25h
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1c 0f05            syscall
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1e c3              ret
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1f 90              nop
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG64 mov_1;              // = 48 89 4C 24 08 48 89 54
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG64 mov_2;              // = 24 10 4C 89 44 24 18 4C
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG mov_3;                // = 89 4C 24 20
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG mov_r10_rcx_mov_eax;  // = 4C 8B D1 B8
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ULONG service_id;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT syscall;             // = 0F 05
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BYTE ret;                   // = C3
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BYTE nop;                   // = 90
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't have an internal thunk for x64.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ServiceFullThunk {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServiceEntry original;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServiceEntryW8 original_w8;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma pack(pop)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsService(const void* source) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ServiceEntry* service =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const ServiceEntry*>(source);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (kMmovR10EcxMovEax == service->mov_r10_rcx_mov_eax &&
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kSyscall == service->syscall && kRetNp == service->ret);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};  // namespace
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS ServiceResolverThunk::Setup(const void* target_module,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const void* interceptor_module,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const char* target_name,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const char* interceptor_name,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const void* interceptor_entry_point,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     void* thunk_storage,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     size_t storage_bytes,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     size_t* storage_used) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS ret = Init(target_module, interceptor_module, target_name,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      interceptor_name, interceptor_entry_point,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      thunk_storage, storage_bytes);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NT_SUCCESS(ret))
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t thunk_bytes = GetThunkSize();
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> thunk_buffer(new char[thunk_bytes]);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                thunk_buffer.get());
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsFunctionAService(&thunk->original))
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return STATUS_UNSUCCESSFUL;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret = PerformPatch(thunk, thunk_storage);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL != storage_used)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *storage_used = thunk_bytes;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ServiceResolverThunk::GetThunkSize() const {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sizeof(ServiceFullThunk);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module,
12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         const char* target_name,
12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         BYTE* thunk_storage,
12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         size_t storage_bytes,
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         size_t* storage_used) {
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  NTSTATUS ret = ResolveTarget(target_module, target_name, &target_);
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!NT_SUCCESS(ret))
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return ret;
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  size_t thunk_bytes = GetThunkSize();
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (storage_bytes < thunk_bytes)
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return STATUS_UNSUCCESSFUL;
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ServiceFullThunk* thunk = reinterpret_cast<ServiceFullThunk*>(thunk_storage);
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!IsFunctionAService(&thunk->original))
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return STATUS_UNSUCCESSFUL;
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (NULL != storage_used)
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    *storage_used = thunk_bytes;
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return ret;
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceFullThunk function_code;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIZE_T read;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::ReadProcessMemory(process_, target_, &function_code,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sizeof(function_code), &read))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sizeof(function_code) != read)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsService(&function_code)) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See if it's the Win8 signature.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ServiceEntryW8* w8_service = &function_code.original_w8;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsService(&w8_service->mov_r10_rcx_mov_eax) ||
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w8_service->mov_1 != kMov1 || w8_service->mov_1 != kMov1 ||
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        w8_service->mov_1 != kMov1) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the verified code.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(local_thunk, &function_code, sizeof(function_code));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            void* remote_thunk) {
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ServiceFullThunk* full_local_thunk =
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reinterpret_cast<ServiceFullThunk*>(local_thunk);
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ServiceFullThunk* full_remote_thunk =
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      reinterpret_cast<ServiceFullThunk*>(remote_thunk);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Patch the original code.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ServiceEntry local_service;
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_NT(GetInternalThunkSize() >= sizeof(local_service));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SetInternalThunk(&local_service, sizeof(local_service), NULL,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        interceptor_))
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return STATUS_UNSUCCESSFUL;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy the local thunk buffer to the child.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIZE_T actual;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::WriteProcessMemory(process_, remote_thunk, local_thunk,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            sizeof(ServiceFullThunk), &actual))
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return STATUS_UNSUCCESSFUL;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sizeof(ServiceFullThunk) != actual)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return STATUS_UNSUCCESSFUL;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And now change the function to intercept, on the child.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL != ntdll_base_) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Running a unit test.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::WriteProcessMemory(process_, target_, &local_service,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              sizeof(local_service), &actual))
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return STATUS_UNSUCCESSFUL;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!WriteProtectedChildMemory(process_, target_, &local_service,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   sizeof(local_service)))
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return STATUS_UNSUCCESSFUL;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return STATUS_SUCCESS;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const {
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  NOTREACHED_NT();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
213