1 /*
2 Copyright 2012 Michael Cohen <scudette@gmail.com>
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 /********************************************************************
18 This is a single binary memory imager for Windows.
19
20 Supported systems:
21 - Windows XPSP2 to Windows 8 inclusive, both 32 bit and 64 bit.
22
23 *********************************************************************/
24
25 /*
26 Copyright (c) 2009-2013, Intel Corporation
27 All rights reserved.
28
29 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
30
31 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
32 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
33 * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
34
35 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "winpmem.h"
39
40 #ifdef PCM_EXPORTS
41 #define PCM_API __declspec(dllexport)
42 #else
43 #define PCM_API
44 #endif
45
46 namespace pcm {
47
48 extern PCM_API void restrictDriverAccess(LPCWSTR path);
49
set_acquisition_mode(__int32 mode)50 int WinPmem::set_acquisition_mode(__int32 mode) {
51 DWORD size;
52 // Set the acquisition mode.
53 if(!DeviceIoControl(fd_, PMEM_CTRL_IOCTRL, &mode, 4, NULL, 0,
54 &size, NULL)) {
55 LogError(TEXT("Failed to set acquisition mode.\n"));
56 return -1;
57 };
58
59 return 1;
60 };
61
toggle_write_mode()62 int WinPmem::toggle_write_mode() {
63 DWORD size;
64 // Set the acquisition mode.
65 if (!DeviceIoControl(fd_, PMEM_WRITE_ENABLE, NULL, 0, NULL, 0,
66 &size, NULL)) {
67 LogError(TEXT("INFO: winpmem driver does not support write mode.\n"));
68 return -1;
69 };
70
71 return 1;
72 };
73
WinPmem()74 WinPmem::WinPmem():
75 suppress_output(FALSE),
76 fd_(INVALID_HANDLE_VALUE),
77 out_fd_(INVALID_HANDLE_VALUE),
78 service_name(PMEM_SERVICE_NAME) {
79 _tcscpy_s(last_error, TEXT(""));
80 max_physical_memory_ = 0;
81 }
82
~WinPmem()83 WinPmem::~WinPmem() {
84 if (fd_ != INVALID_HANDLE_VALUE) {
85 CloseHandle(fd_);
86 }
87 }
88
LogError(const TCHAR * message)89 void WinPmem::LogError(const TCHAR *message) {
90 _tcsncpy_s(last_error, message, sizeof(last_error));
91 if (suppress_output) return;
92
93 wprintf(L"%s", message);
94 };
95
Log(const TCHAR * message,...)96 void WinPmem::Log(const TCHAR *message, ...) {
97 if (suppress_output) return;
98
99 va_list ap;
100 va_start(ap, message);
101 vwprintf(message, ap);
102 va_end(ap);
103 };
104
105 // Roman Dementiev (Intel): added delete_driver option (default is true)
install_driver(bool delete_driver)106 int WinPmem::install_driver(bool delete_driver) {
107 SC_HANDLE scm, service;
108 int status = -1;
109
110 // Try to load the driver from the resource section.
111 if (load_driver_() < 0)
112 goto error;
113
114 uninstall_driver();
115
116 scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
117 if (!scm) {
118 LogError(TEXT("Can not open SCM. Are you administrator?"));
119 goto error;
120 }
121
122 service = CreateService(scm,
123 service_name,
124 service_name,
125 SERVICE_ALL_ACCESS,
126 SERVICE_KERNEL_DRIVER,
127 SERVICE_DEMAND_START,
128 SERVICE_ERROR_NORMAL,
129 driver_filename,
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 NULL);
135
136 if (GetLastError() == ERROR_SERVICE_EXISTS) {
137 service = OpenService(scm, service_name, SERVICE_ALL_ACCESS);
138 }
139
140 if (!service) {
141 goto error;
142 };
143 if (!StartService(service, 0, NULL)) {
144 if (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING) {
145 LogError(TEXT("Error: StartService(), Cannot start the driver.\n"));
146 goto service_error;
147 }
148 }
149
150 Log(L"Loaded Driver %s.\n", driver_filename);
151
152 fd_ = CreateFile(TEXT("\\\\.\\") TEXT(PMEM_DEVICE_NAME),
153 // Write is needed for IOCTL.
154 GENERIC_READ | GENERIC_WRITE,
155 FILE_SHARE_READ | FILE_SHARE_WRITE,
156 NULL,
157 OPEN_EXISTING,
158 FILE_ATTRIBUTE_NORMAL,
159 NULL);
160
161 if(fd_ == INVALID_HANDLE_VALUE) {
162 LogError(TEXT("Can not open raw device."));
163 status = -1;
164 }
165 else
166 status = 1;
167
168 service_error:
169 CloseServiceHandle(service);
170 CloseServiceHandle(scm);
171
172 if(status == 1) restrictDriverAccess(TEXT("\\\\.\\") TEXT(PMEM_DEVICE_NAME));
173 if(delete_driver) DeleteFile(driver_filename);
174
175 error:
176 return status;
177 }
178
uninstall_driver()179 int WinPmem::uninstall_driver() {
180 SC_HANDLE scm, service;
181 SERVICE_STATUS ServiceStatus;
182
183 scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
184
185 if (!scm) return 0;
186
187 service = OpenService(scm, service_name, SERVICE_ALL_ACCESS);
188
189 if (service) {
190 ControlService(service, SERVICE_CONTROL_STOP, &ServiceStatus);
191 };
192
193 DeleteService(service);
194 CloseServiceHandle(service);
195 Log(TEXT("Driver Unloaded.\n"));
196
197 return 1;
198 }
199
200 } // namespace pcm