2 * ScsiDeviceList.cpp - Class which provides information on installed devices.
4 * Author: Robert Nelson, August, 2006 <robertn@the-nelsons.org>
8 * This file was contributed to the Bacula project by Robert Nelson.
10 * Robert Nelson has been granted a perpetual, worldwide,
11 * non-exclusive, no-charge, royalty-free, irrevocable copyright
12 * license to reproduce, prepare derivative works of, publicly
13 * display, publicly perform, sublicense, and distribute the original
14 * work contributed by Robert Nelson to the Bacula project in source
17 * If you wish to license contributions from Robert Nelson
18 * under an alternate open source license please contact
19 * Robert Nelson <robertn@the-nelsons.org>.
22 Bacula® - The Network Backup Solution
24 Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
26 The main author of Bacula is Kern Sibbald, with contributions from
27 many others, a complete list can be found in the file AUTHORS.
28 This program is Free Software; you can redistribute it and/or
29 modify it under the terms of version two of the GNU General Public
30 License as published by the Free Software Foundation and included
33 This program is distributed in the hope that it will be useful, but
34 WITHOUT ANY WARRANTY; without even the implied warranty of
35 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36 General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
43 Bacula® is a registered trademark of Kern Sibbald.
44 The licensor of Bacula is the Free Software Foundation Europe
45 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
46 Switzerland, email:ftf@fsfeurope.org.
49 #if defined(_MSC_VER) && defined(_DEBUG)
58 #include "ScsiDeviceList.h"
60 #if defined(_MSC_VER) && defined(_DEBUG)
64 TCHAR CScsiDeviceList::c_ScsiPath[] = _T("HARDWARE\\DEVICEMAP\\Scsi");
66 LPCTSTR CScsiDeviceList::c_lpszFormatList[] =
68 _T("Logical Unit Id %d"),
74 LPCTSTR CScsiDeviceListEntry::c_DeviceTypes[] =
83 CScsiDeviceListEntry::CScsiDeviceListEntry(const CScsiDeviceListEntry &other)
85 m_eDeviceType = other.m_eDeviceType;
87 m_lpszIdentifier = other.m_lpszIdentifier != NULL ? _tcsdup(other.m_lpszIdentifier) : NULL;
89 m_lpszDeviceName = other.m_lpszDeviceName != NULL ? _tcsdup(other.m_lpszDeviceName) : NULL;
91 m_dwDeviceId = other.m_dwDeviceId;
92 _tcscpy(m_szDevicePath, other.m_szDevicePath);
95 CScsiDeviceListEntry::CScsiDeviceListEntry(void)
97 m_eDeviceType = Unknown;
98 m_lpszIdentifier = NULL;
99 m_lpszDeviceName = NULL;
101 m_szDevicePath[0] = _T('\0');
104 CScsiDeviceListEntry::~CScsiDeviceListEntry(void)
106 if (m_lpszIdentifier != NULL)
108 free(m_lpszIdentifier);
111 if (m_lpszDeviceName != NULL)
113 free(m_lpszDeviceName);
118 CScsiDeviceList::Populate()
124 _tcscpy(m_szLastKey, _T("\\Scsi"));
125 m_dwLastKeyLength = 5;
127 m_lLastError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
133 if (m_lLastError != ERROR_SUCCESS) {
134 _tcscpy(m_szLastOperation, _T("Opening key "));
135 _tcscpy(m_szLastKey, c_ScsiPath);
139 if (!ProcessKey(hScsiKey, c_MaxKeyDepth - 1, 0)) {
144 _fputtc(_T('\n'), stderr);
151 CScsiDeviceList::ProcessKey(HKEY hKey, int iLevel, DWORD dwDeviceId)
173 (dwDeviceId >> 8) & 0xFF,
179 _T("%-64s%d:%d:%d\n"),
181 (dwDeviceId >> 16) & 0xFF,
182 (dwDeviceId >> 8) & 0xFF,
188 for (int idxSubkey = 0; ; idxSubkey++) {
190 TCHAR szSubkeyName[c_MaxSubkeyLength + 1];
193 dwLength = sizeof(szSubkeyName);
195 m_lLastError = RegEnumKeyEx( hKey,
204 if (m_lLastError == ERROR_NO_MORE_ITEMS) {
206 } else if (m_lLastError == ERROR_MORE_DATA) {
208 _tcscpy(m_szLastOperation, _T("Enumerating subkeys of "));
211 // Subkey name is too long
213 } else if (m_lLastError != ERROR_SUCCESS) {
215 _tcscpy(m_szLastOperation, _T("Enumerating subkeys of "));
221 if (_stscanf(szSubkeyName, c_lpszFormatList[iLevel], &iValue) != 1) {
222 // Ignore this subkey, it is probably Initiator Id n
226 m_szLastKey[m_dwLastKeyLength++] = _T('\\');
228 DWORD dwSubkeyLength = (DWORD)_tcslen(szSubkeyName);
229 memcpy(&m_szLastKey[m_dwLastKeyLength], szSubkeyName, (dwSubkeyLength + 1) * sizeof(TCHAR));
230 m_dwLastKeyLength += dwSubkeyLength;
234 m_lLastError = RegOpenKeyEx(hKey, szSubkeyName, 0, KEY_READ, &hSubkey);
236 if (m_lLastError != ERROR_SUCCESS) {
237 _tcscpy(m_szLastOperation, _T("Opening key "));
244 _T("%-64s%d:%d:%d:%d\n"),
246 (dwDeviceId >> 16) & 0xFF,
247 (dwDeviceId >> 8) & 0xFF,
252 ProcessValues(hSubkey, (dwDeviceId << 8) | iValue);
254 if (!ProcessKey(hSubkey, iLevel - 1, (dwDeviceId << 8) | iValue)) {
259 m_dwLastKeyLength -= dwSubkeyLength;
261 m_szLastKey[m_dwLastKeyLength] = _T('\0');
268 CScsiDeviceList::ProcessValues(HKEY hKey, DWORD dwDeviceId)
270 CScsiDeviceListEntry EntryTemplate;
273 TCHAR szValue[c_MaxValueLength + 1];
275 this->push_back(EntryTemplate);
276 CScsiDeviceListEntry & entry = this->back();
278 dwSize = sizeof(szValue);
280 m_lLastError = RegQueryValueEx( hKey,
287 if (m_lLastError == ERROR_SUCCESS) {
288 entry.m_lpszIdentifier = _tcsdup(szValue);
291 _tcscpy(m_szLastOperation, _T("Reading value "));
292 PrintLastError(_T("Identifier"));
296 dwSize = sizeof(szValue);
298 m_lLastError = RegQueryValueEx( hKey,
305 if (m_lLastError == ERROR_SUCCESS) {
306 entry.m_lpszDeviceName = _tcsdup(szValue);
309 _tcscpy(m_szLastOperation, _T("Reading value "));
310 PrintLastError(_T("DeviceName"));
314 dwSize = sizeof(szValue);
316 m_lLastError = RegQueryValueEx( hKey,
323 if (m_lLastError == ERROR_SUCCESS) {
324 if (_tcscmp(_T("CdRomPeripheral"), szValue) == 0) {
325 entry.m_eDeviceType = CScsiDeviceListEntry::CDRom;
326 } else if (_tcscmp(_T("DiskPeripheral"), szValue) == 0) {
327 entry.m_eDeviceType = CScsiDeviceListEntry::Disk;
328 } else if (_tcscmp(_T("MediumChangerPeripheral"), szValue) == 0) {
329 entry.m_eDeviceType = CScsiDeviceListEntry::Changer;
330 } else if (_tcscmp(_T("TapePeripheral"), szValue) == 0) {
331 entry.m_eDeviceType = CScsiDeviceListEntry::Tape;
335 _tcscpy(m_szLastOperation, _T("Reading value "));
336 PrintLastError(_T("Type"));
340 entry.m_dwDeviceId = dwDeviceId;
346 CScsiDeviceList::PrintLastError(LPTSTR lpszName)
348 LPTSTR lpszMessage = NULL;
350 _fputts(_T("Error: "), stderr);
351 _fputts(m_szLastOperation, stderr);
352 _fputtc(_T('"'), stderr);
353 _fputts(lpszName != NULL ? lpszName : m_szLastKey, stderr);
354 _fputts(_T("\" - "), stderr);
356 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
357 NULL, m_lLastError, 0, (LPTSTR)&lpszMessage, 0, NULL);
359 if (lpszMessage != NULL) {
360 _fputts(lpszMessage, stderr);
361 LocalFree(lpszMessage);