|
| 1 | +/* globals Buffer */ |
| 2 | +/** |
| 3 | + * A very dumb minimal implementation of the Windows Registry. |
| 4 | + * Enough to run our tests |
| 5 | + */ |
| 6 | +'use strict'; |
| 7 | +var assert = require('assert'), |
| 8 | + windef = require('../../lib/windef'), |
| 9 | + types = require('../../lib/types'), |
| 10 | + debug = require('debug')('windows-registry'), |
| 11 | + ref = require('ref'); |
| 12 | + |
| 13 | +/* |
| 14 | +* Dumb O(n) search for value inside object |
| 15 | +*/ |
| 16 | +function findValueInHash(value, hash) { |
| 17 | + var found = false; |
| 18 | + for (let k in hash) { |
| 19 | + if (hash[k] === value) { |
| 20 | + found = true; |
| 21 | + break; |
| 22 | + } |
| 23 | + } |
| 24 | + return found; |
| 25 | +} |
| 26 | + |
| 27 | +var keys = { |
| 28 | +}; |
| 29 | +keys[windef.HKEY.HKEY_CLASSES_ROOT] = { |
| 30 | + predefValue: true, |
| 31 | + open: false, |
| 32 | + values: { |
| 33 | + } |
| 34 | +}; |
| 35 | +var mockIndex = 0x00000001; |
| 36 | + |
| 37 | +var advApi = { |
| 38 | + /* |
| 39 | + LONG WINAPI RegQueryValueEx( |
| 40 | + _In_ HKEY hKey, |
| 41 | + _In_opt_ LPCTSTR lpValueName, |
| 42 | + _Reserved_ LPDWORD lpReserved, |
| 43 | + _Out_opt_ LPDWORD lpType, |
| 44 | + _Out_opt_ LPBYTE lpData, |
| 45 | + _Inout_opt_ LPDWORD lpcbData |
| 46 | + ); |
| 47 | + */ |
| 48 | + RegQueryValueExA: function (hKey, valueName, shouldBeNull, lpType, lpData, lpcbData) { |
| 49 | + debug('RegQueryValueExA'); |
| 50 | + if (lpData === null) { |
| 51 | + debug(keys[hKey.address()].values.test_value_name); |
| 52 | + lpType.writeUInt32LE(windef.REG_VALUE_TYPE.REG_SZ, 0); |
| 53 | + lpcbData.writeUInt32LE(keys[hKey.address()].values[valueName].length, 0); |
| 54 | + return 0; |
| 55 | + } |
| 56 | + |
| 57 | + lpData.write(keys[hKey.address()].values[valueName].value, 'utf8'); |
| 58 | + lpType.writeUInt16LE(windef.REG_VALUE_TYPE.REG_SZ); |
| 59 | + return 0; |
| 60 | + }, |
| 61 | + /* |
| 62 | + LONG WINAPI RegOpenKeyEx( |
| 63 | + _In_ HKEY hKey, |
| 64 | + _In_opt_ LPCTSTR lpSubKey, |
| 65 | + _In_ DWORD ulOptions, |
| 66 | + _In_ REGSAM samDesired, |
| 67 | + _Out_ PHKEY phkResult |
| 68 | + ); |
| 69 | + */ |
| 70 | + RegOpenKeyExA: function (hKey, subKeyName, shouldBeZero, accessLevel, pHkey) { |
| 71 | + var accessLevelFound = findValueInHash(accessLevel, windef.KEY_ACCESS); |
| 72 | + debug('Mock: RegOpenKeyExA subkey: ' + subKeyName); |
| 73 | + if (hKey.address) { |
| 74 | + debug('Mock: hKey address:' + hKey.address()); |
| 75 | + } |
| 76 | + debug('keys:'); |
| 77 | + debug(keys); |
| 78 | + // predefined key |
| 79 | + ref.writeUInt64LE(pHkey.deref(), 0, mockIndex); |
| 80 | + mockIndex += 1; |
| 81 | + if (typeof hKey === 'number') { |
| 82 | + assert(findValueInHash(hKey, windef.HKEY), 'Mock: Invalid predefined key specified'); |
| 83 | + |
| 84 | + if (!keys[hKey]) { |
| 85 | + debug('failed to find key for ' + hKey + ' current keys:'); |
| 86 | + debug(keys); |
| 87 | + // FILE NOT FOUND |
| 88 | + return 2; |
| 89 | + } |
| 90 | + keys[pHkey.deref().address()] = { |
| 91 | + opened: true, |
| 92 | + values: { |
| 93 | + |
| 94 | + } |
| 95 | + }; |
| 96 | + } else { |
| 97 | + assert(hKey.constructor === Buffer); |
| 98 | + |
| 99 | + if (!keys[hKey.address()]) { |
| 100 | + debug('failed to find key for ' + hKey.address() + ' current keys:'); |
| 101 | + debug(keys); |
| 102 | + // FILE NOT FOUND |
| 103 | + return 2; |
| 104 | + } |
| 105 | + keys[hKey.address()].open = true; |
| 106 | + keys[pHkey.deref().address()] = keys[hKey.address()]; |
| 107 | + } |
| 108 | + |
| 109 | + assert(typeof subKeyName === 'string'); |
| 110 | + assert(shouldBeZero === 0); |
| 111 | + assert(accessLevelFound, 'Mock: Invalid access level specified'); |
| 112 | + assert(pHkey.deref().constructor === Buffer); |
| 113 | + |
| 114 | + return 0; |
| 115 | + }, |
| 116 | + /* |
| 117 | + LONG WINAPI RegSetValueEx( |
| 118 | + _In_ HKEY hKey, |
| 119 | + _In_opt_ LPCTSTR lpValueName, |
| 120 | + _Reserved_ DWORD Reserved, |
| 121 | + _In_ DWORD dwType, |
| 122 | + _In_ const BYTE *lpData, |
| 123 | + _In_ DWORD cbData |
| 124 | + ); |
| 125 | + */ |
| 126 | + RegSetValueExA: function (hKey, valueName, shouldBeNull, valueType, valueBuffer, bufferLength) { |
| 127 | + debug('Mock: RegSetValueExA'); |
| 128 | + // predefined key |
| 129 | + if (typeof hKey === 'number') { |
| 130 | + assert(findValueInHash(hKey, windef.HKEY), 'Mock: Invalid predefined key specified'); |
| 131 | + } else { |
| 132 | + assert(hKey.constructor === Buffer); |
| 133 | + } |
| 134 | + assert(typeof valueName === 'string'); |
| 135 | + assert(typeof valueType === 'number'); |
| 136 | + assert(valueBuffer.constructor === Buffer); |
| 137 | + assert(typeof bufferLength === 'number'); |
| 138 | + |
| 139 | + keys[hKey.address()].values[valueName] = { |
| 140 | + valueType: valueType, |
| 141 | + value: ref.readCString(valueBuffer), |
| 142 | + length: bufferLength |
| 143 | + }; |
| 144 | + return 0; |
| 145 | + }, |
| 146 | + /** |
| 147 | + * LONG WINAPI RegCreateKeyEx( |
| 148 | + _In_ HKEY hKey, |
| 149 | + _In_ LPCTSTR lpSubKey, |
| 150 | + _Reserved_ DWORD Reserved, |
| 151 | + _In_opt_ LPTSTR lpClass, |
| 152 | + _In_ DWORD dwOptions, |
| 153 | + _In_ REGSAM samDesired, |
| 154 | + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, |
| 155 | + _Out_ PHKEY phkResult, |
| 156 | + _Out_opt_ LPDWORD lpdwDisposition |
| 157 | + ); |
| 158 | + */ |
| 159 | + RegCreateKeyExA: function (hKey, subKeyName, shouldBeNull, shouldBeNull2, securityAttributes, accessLevel, shouldBeNull3, pHkey, shouldBeNull4) { |
| 160 | + debug('Mock: RegCreateKeyExA'); |
| 161 | + assert(hKey.constructor === Buffer); |
| 162 | + assert(typeof subKeyName === 'string'); |
| 163 | + assert(shouldBeNull === null); |
| 164 | + assert(shouldBeNull2 === null); |
| 165 | + assert(shouldBeNull3 === null); |
| 166 | + assert(shouldBeNull4 === null); |
| 167 | + assert.equal(securityAttributes, 0, 'Mock: Security Attributes are not supported yet'); |
| 168 | + assert(findValueInHash(accessLevel, windef.KEY_ACCESS), 'Mock: Invalid access level specified'); |
| 169 | + assert(pHkey.deref().constructor === Buffer); |
| 170 | + debug('Mock: Writing: ' + mockIndex + ' 64 bit dummy pointer to buffer with length: ' + pHkey.deref().length); |
| 171 | + |
| 172 | + ref.writeUInt64LE(pHkey.deref(), 0, mockIndex); |
| 173 | + debug('Mock: Wrote 64 bit dummy pointer'); |
| 174 | + mockIndex += 1; |
| 175 | + debug('Mock: Creating fake key for: ' + hKey.address()); |
| 176 | + debug('Subkey: ' + subKeyName); |
| 177 | + keys[hKey.address()] = { |
| 178 | + opened: true, |
| 179 | + subkeys: { |
| 180 | + subKeyName: '' |
| 181 | + }, |
| 182 | + values: { |
| 183 | + |
| 184 | + } |
| 185 | + }; |
| 186 | + |
| 187 | + return 0; |
| 188 | + }, |
| 189 | + /* |
| 190 | + LONG WINAPI RegDeleteTree( |
| 191 | + _In_ HKEY hKey, |
| 192 | + _In_opt_ LPCTSTR lpSubKey |
| 193 | + ); |
| 194 | + */ |
| 195 | + RegDeleteTreeA: function (hKey, subKeyName) { |
| 196 | + if (typeof hKey === 'number') { |
| 197 | + assert(findValueInHash(hKey, windef.HKEY), 'Mock: Invalid predefined key specified'); |
| 198 | + } else { |
| 199 | + assert(hKey.constructor === Buffer, 'Mock: hKey should be of type buffer if not a number'); |
| 200 | + } |
| 201 | + |
| 202 | + assert(typeof subKeyName === 'string' || subKeyName === undefined); |
| 203 | + delete keys[hKey.address()]; |
| 204 | + return 0; |
| 205 | + }, |
| 206 | + /* |
| 207 | + LONG WINAPI RegCloseKey( |
| 208 | + _In_ HKEY hKey |
| 209 | + ); |
| 210 | + */ |
| 211 | + RegCloseKey: function (hKey) { |
| 212 | + debug('Mock: RegCloseKey'); |
| 213 | + assert.equal(hKey.indirections, types.HKEY.indirections); |
| 214 | + |
| 215 | + delete keys[hKey.address()]; |
| 216 | + return 0; |
| 217 | + } |
| 218 | +}; |
| 219 | + |
| 220 | +module.exports = advApi; |
0 commit comments