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