Skip to content

Commit 8c781fa

Browse files
author
Steven Edouard
committed
Merge pull request #2 from CatalystCode/feat_registry_apis
feat(lib/registry) - intitial registry api wrappers
2 parents 2adde61 + 3b3f855 commit 8c781fa

File tree

10 files changed

+295
-93
lines changed

10 files changed

+295
-93
lines changed

.beautifyrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"js": {
3+
"indentChar": " ",
4+
"indentLevel": 0,
5+
"indentSize": 4,
6+
"indentWithTabs": false,
7+
"space_after_anon_function": "true"
8+
}
9+
}

.vscode/settings.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Place your settings in this file to overwrite default and user settings.
2+
{
3+
"search.excludeFolders": [
4+
".git",
5+
"node_modules",
6+
"bower_components",
7+
"dist",
8+
"cache",
9+
"tmp"
10+
],
11+
"editor.tabSize": 4,
12+
"editor.insertSpaces": true
13+
}

Gruntfile.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ grunt.initConfig({
5555
}
5656
});
5757
grunt.registerTask('test', ['jshint', 'jscs', 'mochacli:all']);
58+
grunt.registerTask('unitTest', ['mochacli:all']);

index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
registry: require('./lib/registry'),
3+
error: require('./lib/error'),
4+
types: require('./lib/types'),
5+
windef: require('./lib/windef'),
6+
Key: require('./lib/key')
7+
}

lib/error.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
0x2: 'ERROR_FILE_NOT_FOUND',
3+
0x3: 'ERROR_PATH_NOT_FOUND',
4+
0x6: 'ERROR_INVALID_HANDLE'
5+
};

lib/key.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
class Key {
3+
constructor (pHKey, path) {
4+
this.handle = pHKey;
5+
this.path = path;
6+
}
7+
close () {
8+
}
9+
10+
toString () {
11+
return this.path;
12+
}
13+
}
14+
15+
module.exports = Key;

lib/registry.js

Lines changed: 150 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,157 @@
1+
/* global Buffer */
12
'use strict';
23
var ffi = require('ffi'),
3-
types = require('./types');
4+
types = require('./types'),
5+
Key = require('./key'),
6+
ref = require('ref'),
7+
error = require('./error'),
8+
windef = require('./windef');
49

510
var advApi = ffi.Library('Advapi32', {
6-
'RegOpenCurrentUser': [ 'uint64', [ types.REGSAM, types.PHKEY ] ],
7-
'RegQueryValueExA' : ['uint64', [types.HKEY, 'string', 'pointer', types.LPDWORD, types.LPBYTE, types.LPDWORD]],
8-
'RegOpenKeyExA' : ['uint64', ['uint64', 'string', types.DWORD, types.REGSAM, types.PHKEY]],
9-
'RegSetValueExA' : [ 'uint64', [types.HKEY, 'string', 'pointer', types.DWORD, types.LPBYTE, types.DWORD ] ]
11+
RegOpenCurrentUser: ['uint64', [types.REGSAM, types.PHKEY]],
12+
RegQueryValueExA: ['uint64', [types.HKEY, 'string', 'pointer', types.LPDWORD, types.LPBYTE, types.LPDWORD]],
13+
RegOpenKeyExA: ['uint64', ['uint64', 'string', types.DWORD, types.REGSAM, types.PHKEY]],
14+
RegSetValueExA: ['uint64', [types.HKEY, 'string', 'pointer', types.DWORD, types.LPBYTE, types.DWORD]],
15+
/**
16+
* LONG WINAPI RegCreateKeyEx(
17+
_In_ HKEY hKey,
18+
_In_ LPCTSTR lpSubKey,
19+
_Reserved_ DWORD Reserved,
20+
_In_opt_ LPTSTR lpClass,
21+
_In_ DWORD dwOptions,
22+
_In_ REGSAM samDesired,
23+
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
24+
_Out_ PHKEY phkResult,
25+
_Out_opt_ LPDWORD lpdwDisposition
26+
);
27+
*/
28+
RegCreateKeyExA: ['uint64', [types.HKEY, 'string', 'pointer', 'pointer', types.DWORD, types.REGSAM, 'pointer', types.PHKEY, 'pointer']],
29+
/*
30+
LONG WINAPI RegDeleteTree(
31+
_In_ HKEY hKey,
32+
_In_opt_ LPCTSTR lpSubKey
33+
);
34+
*/
35+
RegDeleteTreeA: ['uint64', [types.HKEY, 'string']]
1036
});
1137

12-
class Key {
13-
constructor(pHkey, path) {
14-
15-
}
16-
}
17-
1838
var api = {
19-
openKey: function (key, subKeyName) {
20-
21-
},
22-
queryValue: function (key, valueName) {
23-
24-
},
25-
setValue: function (key, valueName, valueType, value) {
26-
27-
}
28-
}
29-
30-
module.exports = api;
39+
openKeyFromPredefined: function (preDefinedKey, subKeyName, accessLevel) {
40+
if (preDefinedKey < 0x80000000 || preDefinedKey > 0x80000006) {
41+
throw 'The key ' + preDefinedKey + ' is not valid. Use the windef module for the list of predefined keys';
42+
}
43+
44+
var pHkey = ref.alloc(types.PHKEY);
45+
var result = advApi.RegOpenKeyExA(preDefinedKey, subKeyName, 0, accessLevel, pHkey);
46+
console.log('result:' + result);
47+
if (result !== 0) {
48+
throw 'Failed to open key error: ' + error[result];
49+
}
50+
51+
return new Key(pHkey, subKeyName);
52+
},
53+
openKeyFromKeyObject: function (keyObject, subKeyName, accessLevel) {
54+
var pHkey = ref.alloc(types.PHKEY);
55+
56+
// RegOpenKeyEx can also take an HKEY in addition to a predefined value
57+
var advApi2 = ffi.Library('Advapi32', {
58+
RegOpenKeyExA: ['uint64', [types.HKEY, 'string', types.DWORD, types.REGSAM, types.PHKEY]]
59+
});
60+
var result = advApi2.RegOpenKeyExA(keyObject.handle.deref(), subKeyName, 0, accessLevel, pHkey);
61+
62+
if (result !== 0) {
63+
throw 'Failed to open key error: ' + error[result];
64+
}
65+
66+
return new Key(pHkey, subKeyName);
67+
},
68+
queryValueForKeyObject: function (key, valueName) {
69+
var pKeyDataLength = ref.alloc(types.LPDWORD),
70+
pKeyType = ref.alloc(types.LPDWORD);
71+
// QUERY FOR VALUE SIZE & TYPE
72+
var result = advApi.RegQueryValueExA(key.handle.deref(), valueName, null, pKeyType, null, pKeyDataLength);
73+
74+
// READ VALUE
75+
var value = new Buffer(pKeyDataLength.readUInt32LE()),
76+
valueType = pKeyType.readUInt32LE();
77+
console.log(valueType === 1);
78+
switch (valueType) {
79+
case windef.REG_VALUE_TYPE.REG_SZ:
80+
case windef.REG_VALUE_TYPE.REG_EXPAND_SZ:
81+
case windef.REG_VALUE_TYPE.REG_LINK:
82+
value.type = types.LPCTSR;
83+
break;
84+
case windef.REG_VALUE_TYPE.REG_BINARY:
85+
value.type = types.PVOID;
86+
break;
87+
case windef.REG_VALUE_TYPE.REG_DWORD:
88+
case windef.REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
89+
case windef.REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
90+
value.type = types.DWORD;
91+
break;
92+
default:
93+
throw 'The Value Type: ' + valueType + ' is currently unsupported';
94+
}
95+
96+
// READ VALUE
97+
result = advApi.RegQueryValueExA(key.handle.deref(), valueName, null, pKeyType, value, pKeyDataLength);
98+
99+
if (result !== 0) {
100+
throw 'Failed to open key error: ' + error[result];
101+
}
102+
103+
return value.toString();
104+
},
105+
setValueForKeyObject: function (key, valueName, valueType, value) {
106+
if (valueType < 1 || valueType > 8) {
107+
throw 'Invalid valueType parameter: ' + valueType + ' use values from windef.REG_VALUE_TYPE';
108+
}
109+
var buffer,
110+
byte;
111+
112+
switch (windef.REG_VALUE_TYPE[valueType]) {
113+
case windef.REG_SZ:
114+
case windef.REG_EXPAND_SZ:
115+
case windef.REG_LINK:
116+
buffer = new Buffer(value, 'ascii');
117+
break;
118+
case windef.REG_BINARY:
119+
// we assume that the value is a buffer since it should be binary data
120+
buffer = value;
121+
break;
122+
case windef.REG_VALUE_TYPE.REG_DWORD:
123+
case windef.REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
124+
case windef.REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
125+
buffer = new Buffer(4, value);
126+
break;
127+
default:
128+
throw 'The type ' + valueType + ' is currently unsupported';
129+
}
130+
131+
byte = ref.alloc(types.LPBYTE, buffer);
132+
133+
var result = advApi.RegSetValueExA(key.handle.deref(), valueName, null, valueType, byte.deref(), buffer.length);
134+
135+
if (result !== 0) {
136+
throw 'Failed to open key error: ' + error[result];
137+
}
138+
},
139+
createKey: function (key, subKeyName, accessLevel) {
140+
var pHkey = ref.alloc(types.PHKEY);
141+
142+
var result = advApi.RegCreateKeyExA(key.handle.deref(), subKeyName, null, null, 0 /*REG_OPTION_NON_VOLATILE*/ , accessLevel, null, pHkey, null);
143+
144+
if (result !== 0) {
145+
throw 'Failed to open key error: ' + error[result];
146+
}
147+
},
148+
deleteKey: function (key, subKeyName) {
149+
var result = advApi.RegDeleteTreeA(key.handle.deref(), subKeyName);
150+
151+
if (result !== 0) {
152+
throw 'Failed to open key error ' + result + ': + error[result]';
153+
}
154+
}
155+
};
156+
157+
module.exports = api;

lib/types.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ var types = {
55
DWORD: ref.types.uint32,
66
BYTE: ref.types.uint8,
77
HKEY: ref.refType(ref.types.void),
8-
PHKEY: ref.refType(this.HKEY),
9-
LPBYTE: ref.refType(this.BYTE),
10-
LPDWORD: ref.refType(this.DWORD),
8+
PVOID: ref.refType(ref.types.void),
119
LPCTSTR: ref.refType(ref.types.CString)
1210
};
1311

12+
types.PHKEY = ref.refType(types.HKEY);
13+
types.LPBYTE = ref.refType(types.BYTE);
14+
types.LPDWORD = ref.refType(types.DWORD);
1415
module.exports = types;
15-

lib/windef.js

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
1-
var HKEY = {
2-
HKEY_CLASSES_ROOT: 0x80000000,
3-
HKEY_CURRENT_USER: 0x80000001,
4-
HKEY_LOCAL_MACHINE: 0x80000002,
5-
HKEY_USERS: 0x80000003,
6-
HKEY_PERFORMANCE_DATA: 0x80000004,
7-
HKEY_CURRENT_CONFIG: 0x80000005,
8-
HKEY_DYN_DATA: 0x80000006
9-
};
101
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724878(v=vs.85).aspx
11-
var KEY_ACCESS = {
12-
KEY_ALL_ACCESS: 0xF003F,
13-
KEY_CREATE_LINK: 0x0020,
14-
KEY_CREATE_SUB_KEY: 0x0004,
15-
KEY_ENUMERATE_SUB_KEYS: 0x0008,
16-
KEY_EXECUTE: 0x20019,
17-
KEY_NOTIFY: 0x0010,
18-
KEY_QUERY_VALUE: 0x0001,
19-
KEY_READ: 0x20019,
20-
KEY_SET_VALUE: 0x0002,
21-
KEY_WOW64_32KEY: 0x0200,
22-
KEY_WOW64_64KEY: 0x0100,
23-
KEY_WRITE: 0x20006
24-
}
25-
26-
module.exports = def;
2+
module.exports = {
3+
KEY_ACCESS: {
4+
KEY_ALL_ACCESS: 0xF003F,
5+
KEY_CREATE_LINK: 0x0020,
6+
KEY_CREATE_SUB_KEY: 0x0004,
7+
KEY_ENUMERATE_SUB_KEYS: 0x0008,
8+
KEY_EXECUTE: 0x20019,
9+
KEY_NOTIFY: 0x0010,
10+
KEY_QUERY_VALUE: 0x0001,
11+
KEY_READ: 0x20019,
12+
KEY_SET_VALUE: 0x0002,
13+
KEY_WOW64_32KEY: 0x0200,
14+
KEY_WOW64_64KEY: 0x0100,
15+
KEY_WRITE: 0x20006
16+
},
17+
HKEY: {
18+
HKEY_CLASSES_ROOT: 0x80000000,
19+
HKEY_CURRENT_USER: 0x80000001,
20+
HKEY_LOCAL_MACHINE: 0x80000002,
21+
HKEY_USERS: 0x80000003,
22+
HKEY_PERFORMANCE_DATA: 0x80000004,
23+
HKEY_CURRENT_CONFIG: 0x80000005,
24+
HKEY_DYN_DATA: 0X80000006
25+
},
26+
REG_VALUE_TYPE: {
27+
REG_SZ: 1,
28+
REG_EXPAND_SZ: 2,
29+
REG_BINARY: 3,
30+
REG_DWORD: 4,
31+
REG_DWORD_BIG_ENDIAN: 5,
32+
REG_DWORD_LITTLE_ENDIAN: 6,
33+
REG_LINK: 6,
34+
REG_MULTI_SZ: 7,
35+
REG_RESOURCE_LIST: 8
36+
}
37+
};

0 commit comments

Comments
 (0)