1 // Copyright 2015 The Crashpad Authors. 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 #ifndef CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_ 16 #define CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_ 17 18 #include <windows.h> 19 #include <stdint.h> 20 21 #include <vector> 22 23 #include "base/macros.h" 24 #include "snapshot/win/process_subrange_reader.h" 25 #include "util/misc/initialization_state_dcheck.h" 26 #include "util/win/address_types.h" 27 28 namespace crashpad { 29 30 //! \brief A reader for resources stored in PE images mapped into another 31 //! process. 32 //! 33 //! \sa PEImageReader 34 class PEImageResourceReader { 35 public: 36 PEImageResourceReader(); 37 ~PEImageResourceReader(); 38 39 //! \brief Initializes the resource reader. 40 //! 41 //! \param[in] module_subrange_reader The reader for the module. 42 //! \param[in] resources_directory_entry The module’s `IMAGE_DATA_DIRECTORY` 43 //! for its resources area. This is taken from the module’s 44 //! `IMAGE_OPTIONAL_HEADER::DataDirectory` at index 45 //! `IMAGE_DIRECTORY_ENTRY_RESOURCE`. 46 //! 47 //! \return `true` on success, `false` on failure with a message logged. 48 bool Initialize(const ProcessSubrangeReader& module_subrange_reader, 49 const IMAGE_DATA_DIRECTORY& resources_directory_entry); 50 51 //! \brief Locates a resource in a module by its ID. 52 //! 53 //! This method is similar to `FindResourceEx()`, but it operates on modules 54 //! loaded in a remote process’ address space. It is not necessary to 55 //! `LoadLibrary()` a module into a process in order to use this method. 56 //! 57 //! No support is provided at present for locating resources by \a type or \a 58 //! name using strings as opposed to integer identifiers. 59 //! 60 //! Languages are scanned in the order determined by 61 //! GetEntryFromResourceDirectoryByLanguage(). 62 //! 63 //! \param[in] type The integer identifier of the resource type, as in the 64 //! `lpType` parameter of `FindResourceEx()`. 65 //! \param[in] name The integer identifier of the resource, as in the `lpName` 66 //! parameter of `FindResourceEx()`. 67 //! \param[in] language The language of the resource, as in the `wLanguage` 68 //! parameter of `FindResourceEx()`. 69 //! \param[out] address The address, in the remote process’ address space, of 70 //! the resource data. 71 //! \param[out] size The size of the resource data. 72 //! \param[out] code_page The code page used to encode textual resource data. 73 //! This parameter is optional. 74 //! 75 //! \return `true` on success, with the out parameters set appropriately. 76 //! `false` if the resource was not found, without logging any messages. 77 //! `false` on failure, with a message logged. 78 bool FindResourceByID(uint16_t type, 79 uint16_t name, 80 uint16_t language, 81 WinVMAddress* address, 82 WinVMSize* size, 83 uint32_t* code_page) const; 84 85 private: 86 //! \brief Locates a resource directory entry within a resource directory by 87 //! integer ID. 88 //! 89 //! \param[in] resource_directory_offset The offset, in the module’s resources 90 //! area, of the resource directory to search. 91 //! \param[in] id The integer identifier of the resource to search for. 92 //! \param[in] want_subdirectory `true` if the resource directory entry is 93 //! expected to be a resource directory itself, `false` otherwise. 94 //! 95 //! \return The offset, in the module’s resources area, of the entry that was 96 //! found. On failure, `0`. `0` is technically a valid offset, but it 97 //! corresponds to the root resource directory, which should never be the 98 //! offset of another resource directory entry. If \a id was not found, 99 //! `0` will be returned without logging anything. For other failures, a 100 //! message will be logged. 101 uint32_t GetEntryFromResourceDirectoryByID(uint32_t resource_directory_offset, 102 uint16_t id, 103 bool want_subdirectory) const; 104 105 //! \brief Locates a resource directory entry within a resource directory by 106 //! language. 107 //! 108 //! This method is similar to GetEntryFromResourceDirectoryByID() with \a 109 //! want_subdirectory set to `false`. Attempts are made to locate the resource 110 //! by using these languages: 111 //! <ul> 112 //! <li>If \a language is `LANG_NEUTRAL`:</li> 113 //! <ul> 114 //! <li>Unless `SUBLANG_SYS_DEFAULT` is specified, the language of the 115 //! thread’s locale, with its normal sublanguage and with 116 //! `SUBLANG_NEUTRAL`.</li> 117 //! <li>Unless `SUBLANG_SYS_DEFAULT` is specified, the language of the 118 //! user’s default locale, with its normal sublanguage and with 119 //! `SUBLANG_NEUTRAL`.</li> 120 //! <li>Unless `SUBLANG_DEFAULT` is specified, the language of the 121 //! system’s default locale, with its normal sublanguage and with 122 //! `SUBLANG_NEUTRAL`.</li> 123 //! </ul> 124 //! <li>If \a language is not `LANG_NEUTRAL`:</li> 125 //! <ul> 126 //! <li>\a language</li> 127 //! <li>\a language, with `SUBLANG_NEUTRAL`</li> 128 //! </ul> 129 //! <li>`LANG_NEUTRAL` with `SUBLANG_NEUTRAL`</li> 130 //! <li>`LANG_ENGLISH` with `SUBLANG_DEFAULT`</li> 131 //! <li>If none of the above match, the first language found</li> 132 //! </ul> 133 //! 134 //! If only a specific language is desired without any fallbacks, call 135 //! GetEntryFromResourceDirectoryByID() with the language directory’s offset 136 //! instead, passing the desired language in the \a id parameter, and `false` 137 //! for \a want_subdirectory. 138 //! 139 //! \param[in] language_directory_offset The offset, in the module’s resources 140 //! area, of the resource directory to search. 141 //! \param[in] language The language of the resource to search for. 142 //! 143 //! \return The return value is as in GetEntryFromResourceDirectoryByID(). 144 uint32_t GetEntryFromResourceDirectoryByLanguage( 145 uint32_t language_directory_offset, 146 uint16_t language) const; 147 148 //! \brief Reads a resource directory. 149 //! 150 //! \param[in] resource_directory_offset The offset, in the module’s resources 151 //! area, of the resource directory to read. 152 //! \param[out] resource_directory The `IMAGE_RESOURCE_DIRECTORY` structure. 153 //! This parameter is optional. 154 //! \param[out] named_entries A vector of \a 155 //! resource_directory->NumberOfNamedEntries 156 //! `IMAGE_RESOURCE_DIRECTORY_ENTRY` items that follow the resource 157 //! directory. This parameter is optional. 158 //! \param[out] id_entries A vector of \a 159 //! resource_directory->NumberOfIdEntries `IMAGE_RESOURCE_DIRECTORY_ENTRY` 160 //! items that follow the named entries. This parameter is optional. 161 //! 162 //! \return `true` on success, with the out parameters set appropriately. 163 //! `false` on failure with a message logged. 164 bool ReadResourceDirectory( 165 uint32_t resource_directory_offset, 166 IMAGE_RESOURCE_DIRECTORY* resource_directory, 167 std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* named_entries, 168 std::vector<IMAGE_RESOURCE_DIRECTORY_ENTRY>* id_entries) const; 169 170 ProcessSubrangeReader resources_subrange_reader_; 171 WinVMAddress module_base_; 172 InitializationStateDcheck initialized_; 173 174 DISALLOW_COPY_AND_ASSIGN(PEImageResourceReader); 175 }; 176 177 } // namespace crashpad 178 179 #endif // CRASHPAD_SNAPSHOT_WIN_PE_IMAGE_RESOURCE_READER_H_ 180