- add sources.
[platform/framework/web/crosswalk.git] / src / sandbox / win / src / interception_unittest.cc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This file contains unit tests for InterceptionManager.
6 // The tests require private information so the whole interception.cc file is
7 // included from this file.
8
9 #include <windows.h>
10
11 #include "base/memory/scoped_ptr.h"
12 #include "sandbox/win/src/interception.h"
13 #include "sandbox/win/src/interceptors.h"
14 #include "sandbox/win/src/interception_internal.h"
15 #include "sandbox/win/src/target_process.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace sandbox {
19
20 // Walks the settings buffer, verifying that the values make sense and counting
21 // objects.
22 // Arguments:
23 // buffer (in): the buffer to walk.
24 // size (in): buffer size
25 // num_dlls (out): count of the dlls on the buffer.
26 // num_function (out): count of intercepted functions.
27 // num_names (out): count of named interceptor functions.
28 void WalkBuffer(void* buffer, size_t size, int* num_dlls, int* num_functions,
29                 int* num_names) {
30   ASSERT_TRUE(NULL != buffer);
31   ASSERT_TRUE(NULL != num_functions);
32   ASSERT_TRUE(NULL != num_names);
33   *num_dlls = *num_functions = *num_names = 0;
34   SharedMemory *memory = reinterpret_cast<SharedMemory*>(buffer);
35
36   ASSERT_GT(size, sizeof(SharedMemory));
37   DllPatchInfo *dll = &memory->dll_list[0];
38
39   for (int i = 0; i < memory->num_intercepted_dlls; i++) {
40     ASSERT_NE(0u, wcslen(dll->dll_name));
41     ASSERT_EQ(0u, dll->record_bytes % sizeof(size_t));
42     ASSERT_EQ(0u, dll->offset_to_functions % sizeof(size_t));
43     ASSERT_NE(0, dll->num_functions);
44
45     FunctionInfo *function = reinterpret_cast<FunctionInfo*>(
46       reinterpret_cast<char*>(dll) + dll->offset_to_functions);
47
48     for (int j = 0; j < dll->num_functions; j++) {
49       ASSERT_EQ(0u, function->record_bytes % sizeof(size_t));
50
51       char* name = function->function;
52       size_t length = strlen(name);
53       ASSERT_NE(0u, length);
54       name += length + 1;
55
56       // look for overflows
57       ASSERT_GT(reinterpret_cast<char*>(buffer) + size, name + strlen(name));
58
59       // look for a named interceptor
60       if (strlen(name)) {
61         (*num_names)++;
62         EXPECT_TRUE(NULL == function->interceptor_address);
63       } else {
64         EXPECT_TRUE(NULL != function->interceptor_address);
65       }
66
67       (*num_functions)++;
68       function = reinterpret_cast<FunctionInfo*>(
69         reinterpret_cast<char*>(function) + function->record_bytes);
70     }
71
72     (*num_dlls)++;
73     dll = reinterpret_cast<DllPatchInfo*>(reinterpret_cast<char*>(dll) +
74                                           dll->record_bytes);
75   }
76 }
77
78 TEST(InterceptionManagerTest, BufferLayout1) {
79   wchar_t exe_name[MAX_PATH];
80   ASSERT_NE(0u, GetModuleFileName(NULL, exe_name, MAX_PATH - 1));
81
82   TargetProcess *target = MakeTestTargetProcess(::GetCurrentProcess(),
83                                                 ::GetModuleHandle(exe_name));
84
85   InterceptionManager interceptions(target, true);
86
87   // Any pointer will do for a function pointer.
88   void* function = &interceptions;
89
90   // We don't care about the interceptor id.
91   interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtCreateFile",
92                                       INTERCEPTION_SERVICE_CALL, function,
93                                       OPEN_KEY_ID);
94   interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx",
95                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
96   interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx",
97                                       INTERCEPTION_SMART_SIDESTEP, function,
98                                       OPEN_KEY_ID);
99   interceptions.AddToPatchedFunctions(L"user32.dll", "FindWindow",
100                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
101   interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateMutex",
102                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
103   interceptions.AddToPatchedFunctions(L"user32.dll", "PostMsg",
104                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
105   interceptions.AddToPatchedFunctions(L"user32.dll", "PostMsg",
106                                       INTERCEPTION_EAT, "replacement",
107                                       OPEN_KEY_ID);
108   interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
109                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
110   interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtClose",
111                                       INTERCEPTION_SERVICE_CALL, function,
112                                       OPEN_KEY_ID);
113   interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtOpenFile",
114                                       INTERCEPTION_SIDESTEP, function,
115                                       OPEN_KEY_ID);
116   interceptions.AddToPatchedFunctions(L"some.dll", "Superfn",
117                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
118   interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
119                                       INTERCEPTION_EAT, "a", OPEN_KEY_ID);
120   interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
121                                       INTERCEPTION_SIDESTEP, "ab", OPEN_KEY_ID);
122   interceptions.AddToPatchedFunctions(L"comctl.dll", "SaveAsDlg",
123                                       INTERCEPTION_EAT, "abc", OPEN_KEY_ID);
124   interceptions.AddToPatchedFunctions(L"a.dll", "p",
125                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
126   interceptions.AddToPatchedFunctions(L"b.dll",
127                                       "TheIncredibleCallToSaveTheWorld",
128                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
129   interceptions.AddToPatchedFunctions(L"a.dll", "BIsLame",
130                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
131   interceptions.AddToPatchedFunctions(L"a.dll", "ARules",
132                                       INTERCEPTION_EAT, function, OPEN_KEY_ID);
133
134   // Verify that all interceptions were added
135   ASSERT_EQ(18, interceptions.interceptions_.size());
136
137   size_t buffer_size = interceptions.GetBufferSize();
138   scoped_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]);
139
140   ASSERT_TRUE(interceptions.SetupConfigBuffer(local_buffer.get(),
141                                               buffer_size));
142
143   // At this point, the interceptions should have been separated into two
144   // groups: one group with the local ("cold") interceptions, consisting of
145   // everything from ntdll and stuff set as INTRECEPTION_SERVICE_CALL, and
146   // another group with the interceptions belonging to dlls that will be "hot"
147   // patched on the client. The second group lives on local_buffer, and the
148   // first group remains on the list of interceptions (inside the object
149   // "interceptions"). There are 3 local interceptions (of ntdll); the
150   // other 15 have to be sent to the child to be performed "hot".
151   EXPECT_EQ(3, interceptions.interceptions_.size());
152
153   int num_dlls, num_functions, num_names;
154   WalkBuffer(local_buffer.get(), buffer_size, &num_dlls, &num_functions,
155              &num_names);
156
157   // The 15 interceptions on the buffer (to the child) should be grouped on 6
158   // dlls. Only four interceptions are using an explicit name for the
159   // interceptor function.
160   EXPECT_EQ(6, num_dlls);
161   EXPECT_EQ(15, num_functions);
162   EXPECT_EQ(4, num_names);
163 }
164
165 TEST(InterceptionManagerTest, BufferLayout2) {
166   wchar_t exe_name[MAX_PATH];
167   ASSERT_NE(0u, GetModuleFileName(NULL, exe_name, MAX_PATH - 1));
168
169   TargetProcess *target = MakeTestTargetProcess(::GetCurrentProcess(),
170                                                 ::GetModuleHandle(exe_name));
171
172   InterceptionManager interceptions(target, true);
173
174   // Any pointer will do for a function pointer.
175   void* function = &interceptions;
176   interceptions.AddToUnloadModules(L"some01.dll");
177   // We don't care about the interceptor id.
178   interceptions.AddToPatchedFunctions(L"ntdll.dll", "NtCreateFile",
179                                       INTERCEPTION_SERVICE_CALL, function,
180                                       OPEN_FILE_ID);
181   interceptions.AddToPatchedFunctions(L"kernel32.dll", "CreateFileEx",
182                                       INTERCEPTION_EAT, function, OPEN_FILE_ID);
183   interceptions.AddToUnloadModules(L"some02.dll");
184   interceptions.AddToPatchedFunctions(L"kernel32.dll", "SomeFileEx",
185                                       INTERCEPTION_SMART_SIDESTEP, function,
186                                       OPEN_FILE_ID);
187   // Verify that all interceptions were added
188   ASSERT_EQ(5, interceptions.interceptions_.size());
189
190   size_t buffer_size = interceptions.GetBufferSize();
191   scoped_ptr<BYTE[]> local_buffer(new BYTE[buffer_size]);
192
193   ASSERT_TRUE(interceptions.SetupConfigBuffer(local_buffer.get(),
194                                               buffer_size));
195
196   // At this point, the interceptions should have been separated into two
197   // groups: one group with the local ("cold") interceptions, and another
198   // group with the interceptions belonging to dlls that will be "hot"
199   // patched on the client. The second group lives on local_buffer, and the
200   // first group remains on the list of interceptions, in this case just one.
201   EXPECT_EQ(1, interceptions.interceptions_.size());
202
203   int num_dlls, num_functions, num_names;
204   WalkBuffer(local_buffer.get(), buffer_size, &num_dlls, &num_functions,
205              &num_names);
206
207   EXPECT_EQ(3, num_dlls);
208   EXPECT_EQ(4, num_functions);
209   EXPECT_EQ(0, num_names);
210 }
211
212 }  // namespace sandbox