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_UTIL_WIN_REGISTRATION_PROTOCOL_WIN_H_
16 #define CRASHPAD_UTIL_WIN_REGISTRATION_PROTOCOL_WIN_H_
17 
18 #include <windows.h>
19 #include <stdint.h>
20 
21 #include <string>
22 
23 #include "util/win/address_types.h"
24 
25 namespace crashpad {
26 
27 #pragma pack(push, 1)
28 
29 //! \brief Structure read out of the client process by the crash handler when an
30 //!     exception occurs.
31 struct ExceptionInformation {
32   //! \brief The address of an EXCEPTION_POINTERS structure in the client
33   //!     process that describes the exception.
34   WinVMAddress exception_pointers;
35 
36   //! \brief The thread on which the exception happened.
37   DWORD thread_id;
38 };
39 
40 //! \brief A client registration request.
41 struct RegistrationRequest {
42   //! \brief The expected value of `version`. This should be changed whenever
43   //!     the messages or ExceptionInformation are modified incompatibly.
44   enum { kMessageVersion = 1 };
45 
46   //! \brief Version field to detect skew between client and server. Should be
47   //!     set to kMessageVersion.
48   int version;
49 
50   //! \brief The PID of the client process.
51   DWORD client_process_id;
52 
53   //! \brief The address, in the client process's address space, of an
54   //!     ExceptionInformation structure, used when handling a crash dump
55   //!     request.
56   WinVMAddress crash_exception_information;
57 
58   //! \brief The address, in the client process's address space, of an
59   //!     ExceptionInformation structure, used when handling a non-crashing dump
60   //!     request.
61   WinVMAddress non_crash_exception_information;
62 
63   //! \brief The address, in the client process's address space, of a
64   //!     `CRITICAL_SECTION` allocated with a valid .DebugInfo field. This can
65   //!     be accomplished by using
66   //!     InitializeCriticalSectionWithDebugInfoIfPossible() or equivalent. This
67   //!     value can be `0`, however then limited lock data will be available in
68   //!     minidumps.
69   WinVMAddress critical_section_address;
70 };
71 
72 //! \brief A message only sent to the server by itself to trigger shutdown.
73 struct ShutdownRequest {
74   //! \brief A randomly generated token used to validate the the shutdown
75   //!     request was not sent from another process.
76   uint64_t token;
77 };
78 
79 //! \brief The message passed from client to server by
80 //!     SendToCrashHandlerServer().
81 struct ClientToServerMessage {
82   //! \brief Indicates which field of the union is in use.
83   enum Type : uint32_t {
84     //! \brief For RegistrationRequest.
85     kRegister,
86 
87     //! \brief For ShutdownRequest.
88     kShutdown,
89 
90     //! \brief An empty message sent by the initial client in asynchronous mode.
91     //!     No data is required, this just confirms that the server is ready to
92     //!     accept client registrations.
93     kPing,
94   } type;
95 
96   union {
97     RegistrationRequest registration;
98     ShutdownRequest shutdown;
99   };
100 };
101 
102 //! \brief A client registration response.
103 struct RegistrationResponse {
104   //! \brief An event `HANDLE`, valid in the client process, that should be
105   //!     signaled to request a crash report. Clients should convert the value
106   //!     to a `HANDLE` by calling IntToHandle().
107   int request_crash_dump_event;
108 
109   //! \brief An event `HANDLE`, valid in the client process, that should be
110   //!     signaled to request a non-crashing dump be taken. Clients should
111   //!     convert the value to a `HANDLE` by calling IntToHandle().
112   int request_non_crash_dump_event;
113 
114   //! \brief An event `HANDLE`, valid in the client process, that will be
115   //!     signaled by the server when the non-crashing dump is complete. Clients
116   //!     should convert the value to a `HANDLE` by calling IntToHandle().
117   int non_crash_dump_completed_event;
118 };
119 
120 //! \brief The response sent back to the client via SendToCrashHandlerServer().
121 union ServerToClientMessage {
122   RegistrationResponse registration;
123 };
124 
125 #pragma pack(pop)
126 
127 //! \brief Connect over the given \a pipe_name, passing \a message to the
128 //!     server, storing the server's reply into \a response.
129 //!
130 //! Typically clients will not use this directly, instead using
131 //! CrashpadClient::SetHandler().
132 //!
133 //! \sa CrashpadClient::SetHandler()
134 bool SendToCrashHandlerServer(const std::wstring& pipe_name,
135                               const ClientToServerMessage& message,
136                               ServerToClientMessage* response);
137 
138 //! \brief Wraps CreateNamedPipe() to create a single named pipe instance.
139 //!
140 //! \param[in] pipe_name The name to use for the pipe.
141 //! \param[in] first_instance If `true`, the named pipe instance will be
142 //!     created with `FILE_FLAG_FIRST_PIPE_INSTANCE`. This ensures that the the
143 //!     pipe name is not already in use when created. The first instance will be
144 //!     created with an untrusted integrity SACL so instances of this pipe can
145 //!     be connected to by processes of any integrity level.
146 HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name,
147                                bool first_instance);
148 
149 //! \brief Returns the `SECURITY_DESCRIPTOR` blob that will be used for creating
150 //!     the connection pipe in CreateNamedPipeInstance().
151 //!
152 //! This function is only exposed for testing.
153 //!
154 //! \param[out] size The size of the returned blob. May be `nullptr` if not
155 //!     required.
156 //!
157 //! \return A pointer to a self-relative `SECURITY_DESCRIPTOR`. Ownership is not
158 //!     transferred to the caller.
159 const void* GetSecurityDescriptorForNamedPipeInstance(size_t* size);
160 
161 //! \brief Returns the `SECURITY_DESCRIPTOR` blob that will be used for creating
162 //!     the connection pipe in CreateNamedPipeInstance() if the full descriptor
163 //!     can't be created.
164 //!
165 //! This function is only exposed for testing.
166 //!
167 //! \param[out] size The size of the returned blob. May be `nullptr` if not
168 //!     required.
169 //!
170 //! \return A pointer to a self-relative `SECURITY_DESCRIPTOR`. Ownership is not
171 //!     transferred to the caller.
172 const void* GetFallbackSecurityDescriptorForNamedPipeInstance(size_t* size);
173 
174 }  // namespace crashpad
175 
176 #endif  // CRASHPAD_UTIL_WIN_REGISTRATION_PROTOCOL_WIN_H_
177