1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/common/process_utils.h"
16 :
17 : #include <psapi.h>
18 :
19 : #include "base/logging.h"
20 : #include "base/win/pe_image.h"
21 : #include "syzygy/common/com_utils.h"
22 : #include "syzygy/common/path_util.h"
23 :
24 : namespace common {
25 :
26 E : bool GetCurrentProcessModules(ModuleVector* modules) {
27 E : return GetProcessModules(::GetCurrentProcess(), modules);
28 E : }
29 :
30 E : bool GetProcessModules(HANDLE process, ModuleVector* modules) {
31 E : DCHECK(modules != NULL);
32 :
33 E : modules->resize(128);
34 E : while (true) {
35 E : DWORD bytes_required = 0;
36 : // EnumProcessModules expects a DWORD as size, so it should fit.
37 E : DCHECK_LE(modules->size() * sizeof(modules->at(0)),
38 E : std::numeric_limits<DWORD>::max());
39 : // EnumProcessModules returns 'success' even if the buffer size is too
40 : // small.
41 E : if (!::EnumProcessModules(
42 : process,
43 : modules->data(),
44 : static_cast<DWORD>(modules->size() * sizeof(modules->at(0))),
45 : &bytes_required)) {
46 i : DPLOG(ERROR) << "::EnumProcessModules";
47 i : modules->clear();
48 i : return false;
49 : }
50 E : DCHECK_EQ(0u, bytes_required % sizeof(modules->at(0)));
51 E : size_t num_modules = bytes_required / sizeof(modules->at(0));
52 E : if (num_modules <= modules->size()) {
53 : // Buffer size was too big, presumably because a module was unloaded.
54 E : modules->resize(num_modules);
55 E : return true;
56 i : } else if (num_modules == 0) {
57 i : DLOG(ERROR) << "Can't determine the module list size.";
58 i : modules->clear();
59 i : return false;
60 i : } else {
61 : // Buffer size was too small. Try again with a larger buffer.
62 i : modules->resize(num_modules + 4, NULL);
63 : }
64 i : }
65 E : }
66 :
67 : } // namespace common
|