Skip to content

Commit 27d5848

Browse files
author
Steven Edouard
committed
Merge pull request CatalystCode#10 from CatalystCode/fix_7_8
fix(lib) - Object-like Key api + Fix Key Value Test
2 parents 4858b70 + 840b6ca commit 27d5848

13 files changed

+437
-194
lines changed

.vscode/launch.json

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"version": "0.1.0",
3+
// List of configurations. Add new configurations or edit existing ones.
4+
// ONLY "node" and "mono" are supported, change "type" to switch.
5+
"configurations": [
6+
{
7+
// Name of configuration; appears in the launch configuration drop down menu.
8+
"name": "Launch index.js",
9+
// Type of configuration. Possible values: "node", "mono".
10+
"type": "node",
11+
// Workspace relative or absolute path to the program.
12+
"program": "node_modules\\grunt-cli\\bin\\grunt",
13+
// Automatically stop program after launch.
14+
"stopOnEntry": true,
15+
// Command line arguments passed to the program.
16+
"args": ["unitTest"],
17+
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
18+
"cwd": ".",
19+
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
20+
"runtimeExecutable": null,
21+
// Optional arguments passed to the runtime executable.
22+
"runtimeArgs": ["--nolazy"],
23+
// Environment variables passed to the program.
24+
"env": {
25+
"NODE_ENV": "development"
26+
},
27+
// Use JavaScript source maps (if they exist).
28+
"sourceMaps": false,
29+
// If JavaScript source maps are enabled, the generated code is expected in this directory.
30+
"outDir": null
31+
},
32+
{
33+
"name": "Attach",
34+
"type": "node",
35+
// TCP/IP address. Default is "localhost".
36+
"address": "localhost",
37+
// Port to attach to.
38+
"port": 5858,
39+
"sourceMaps": false
40+
}
41+
]
42+
}

lib/key.js

+63-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,73 @@
11
'use strict';
2-
2+
/**
3+
* An object wrapper for easier use of registry api
4+
*/
35
class Key {
4-
constructor (pHKey, path) {
5-
this.handle = pHKey;
6+
constructor (pHKeyOrPredefined, path, accessLevel) {
7+
var isPredefined = false;
8+
this._registry = require('./registry');
9+
this._windef = require('./windef');
10+
for (var k in this._windef.HKEY) {
11+
if (this._windef.HKEY[k] === pHKeyOrPredefined) {
12+
isPredefined = true;
13+
break;
14+
}
15+
}
16+
17+
// this is a predefined key
18+
if (isPredefined) {
19+
return this._registry.openKeyFromPredefined(pHKeyOrPredefined, path, accessLevel);
20+
}
21+
22+
this.handle = pHKeyOrPredefined;
623
this.path = path;
724
}
25+
26+
/**
27+
* Closes this Key, releasing the native OS handle
28+
* all the containers matching the query. Automatically closes current key
29+
*/
830
close () {
9-
var registry = require('./registry');
10-
registry.closeKey(this);
31+
this._registry.closeKey(this);
32+
}
33+
34+
deleteKey () {
35+
this._registry.deleteKey(this);
36+
}
37+
38+
/**
39+
* Sets a value for a value name on this key
40+
* all the containers matching the query.
41+
* @param {DS.Record Container} selectedContainer - The container to be selected
42+
*/
43+
setValue (valueName, valueType, value) {
44+
this._registry.setValueForKeyObject(this, valueName, valueType, value);
45+
}
46+
47+
getValue (valueName) {
48+
return this._registry.queryValueForKeyObject(this, valueName);
49+
}
50+
51+
/**
52+
* Returns a new Key object given a subkeyName
53+
* @param {string} subKeyName - The container to be selected
54+
* @param {string} accessLevel - The container to be selected
55+
* @return {Key}
56+
*/
57+
openSubKey (subKeyName, accessLevel) {
58+
var key = this._registry.openKeyFromKeyObject(this, subKeyName, accessLevel);
59+
return key;
60+
}
61+
62+
createSubKey (subKeyName, accessLevel) {
63+
this._registry.createKey(this, subKeyName, accessLevel);
64+
65+
return new Key(this.handle, subKeyName, accessLevel);
1166
}
1267

68+
/**
69+
* Returns the string representing this Key
70+
*/
1371
toString () {
1472
return this.path;
1573
}

lib/native/adv_api.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Minimal wrappers for Advapi32.dll to support basic registry manipulations
2+
3+
'use strict';
4+
var ffi = require('ffi'),
5+
types = require('../types');
6+
7+
// Javascript bindings for native Win32 registry APIs
8+
var advApi = ffi.Library('Advapi32', {
9+
/*
10+
LONG WINAPI RegOpenCurrentUser(
11+
_In_ REGSAM samDesired,
12+
_Out_ PHKEY phkResult
13+
);
14+
*/
15+
RegOpenCurrentUser: ['uint64', [types.REGSAM, types.PHKEY]],
16+
/*
17+
LONG WINAPI RegQueryValueEx(
18+
_In_ HKEY hKey,
19+
_In_opt_ LPCTSTR lpValueName,
20+
_Reserved_ LPDWORD lpReserved,
21+
_Out_opt_ LPDWORD lpType,
22+
_Out_opt_ LPBYTE lpData,
23+
_Inout_opt_ LPDWORD lpcbData
24+
);
25+
*/
26+
RegQueryValueExA: ['uint64', [types.HKEY, 'string', 'pointer', types.LPDWORD, types.LPBYTE, types.LPDWORD]],
27+
/*
28+
LONG WINAPI RegOpenKeyEx(
29+
_In_ HKEY hKey,
30+
_In_opt_ LPCTSTR lpSubKey,
31+
_In_ DWORD ulOptions,
32+
_In_ REGSAM samDesired,
33+
_Out_ PHKEY phkResult
34+
);
35+
*/
36+
RegOpenKeyExA: ['uint64', ['uint64', 'string', types.DWORD, types.REGSAM, types.PHKEY]],
37+
/*
38+
LONG WINAPI RegSetValueEx(
39+
_In_ HKEY hKey,
40+
_In_opt_ LPCTSTR lpValueName,
41+
_Reserved_ DWORD Reserved,
42+
_In_ DWORD dwType,
43+
_In_ const BYTE *lpData,
44+
_In_ DWORD cbData
45+
);
46+
*/
47+
RegSetValueExA: ['uint64', [types.HKEY, 'string', 'pointer', types.DWORD, types.LPBYTE, types.DWORD]],
48+
/**
49+
* LONG WINAPI RegCreateKeyEx(
50+
_In_ HKEY hKey,
51+
_In_ LPCTSTR lpSubKey,
52+
_Reserved_ DWORD Reserved,
53+
_In_opt_ LPTSTR lpClass,
54+
_In_ DWORD dwOptions,
55+
_In_ REGSAM samDesired,
56+
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
57+
_Out_ PHKEY phkResult,
58+
_Out_opt_ LPDWORD lpdwDisposition
59+
);
60+
*/
61+
RegCreateKeyExA: ['uint64', [types.HKEY, 'string', 'pointer', 'pointer', types.DWORD, types.REGSAM, 'pointer', types.PHKEY, 'pointer']],
62+
/*
63+
LONG WINAPI RegDeleteTree(
64+
_In_ HKEY hKey,
65+
_In_opt_ LPCTSTR lpSubKey
66+
);
67+
*/
68+
RegDeleteTreeA: ['uint64', [types.HKEY, 'string']],
69+
/*
70+
LONG WINAPI RegCloseKey(
71+
_In_ HKEY hKey
72+
);
73+
*/
74+
RegCloseKey: ['uint64', [types.HKEY]]
75+
});
76+
77+
module.exports = advApi;

lib/native/shell32.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Minimnal wrappers for shell32.js
2+
var windef = require('../windef'),
3+
ffi = require('ffi'),
4+
ref = require('ref');
5+
6+
var SHELLEXECUTEINFOPtr = ref.refType(windef.SHELLEXECUTEINFO);
7+
var shell32 = new ffi.Library('Shell32', {
8+
/*
9+
BOOL ShellExecuteEx(
10+
_Inout_ SHELLEXECUTEINFO *pExecInfo
11+
);
12+
*/
13+
ShellExecuteExA: ['bool', [SHELLEXECUTEINFOPtr]]
14+
});
15+
16+
module.exports = shell32;

lib/registry.js

+30-52
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,12 @@
22
'use strict';
33
var ffi = require('ffi'),
44
types = require('./types'),
5+
advApi = require('./native/adv_api'),
56
Key = require('./key'),
67
ref = require('ref'),
78
error = require('./error'),
8-
windef = require('./windef');
9-
10-
var advApi = ffi.Library('Advapi32', {
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']],
36-
/*
37-
LONG WINAPI RegCloseKey(
38-
_In_ HKEY hKey
39-
);
40-
*/
41-
RegCloseKey: ['uint64', [types.HKEY]]
42-
});
9+
windef = require('./windef'),
10+
debug = require('debug')('windows-registry');
4311

4412
var api = {
4513
openKeyFromPredefined: function (preDefinedKey, subKeyName, accessLevel) {
@@ -49,7 +17,7 @@ var api = {
4917

5018
var pHkey = ref.alloc(types.PHKEY);
5119
var result = advApi.RegOpenKeyExA(preDefinedKey, subKeyName, 0, accessLevel, pHkey);
52-
console.log('result:' + result);
20+
debug('result:' + result);
5321
if (result !== 0) {
5422
throw 'Failed to open key error: ' + error[result];
5523
}
@@ -80,7 +48,6 @@ var api = {
8048
// READ VALUE
8149
var value = new Buffer(pKeyDataLength.readUInt32LE()),
8250
valueType = pKeyType.readUInt32LE();
83-
console.log(valueType === 1);
8451
switch (valueType) {
8552
case windef.REG_VALUE_TYPE.REG_SZ:
8653
case windef.REG_VALUE_TYPE.REG_EXPAND_SZ:
@@ -106,38 +73,49 @@ var api = {
10673
throw 'Failed to open key error: ' + error[result];
10774
}
10875

109-
return value.toString();
76+
if (value.type === types.LPTSR) {
77+
// TODO not sure why buffer's utf8 parsing leaves in the unicode null
78+
// escape sequence. This is a work-around (at least on node 4.1)
79+
value = value.toString().replace('\u0000', '');
80+
}
81+
82+
return value;
11083
},
11184
setValueForKeyObject: function (key, valueName, valueType, value) {
11285
if (valueType < 1 || valueType > 8) {
11386
throw 'Invalid valueType parameter: ' + valueType + ' use values from windef.REG_VALUE_TYPE';
11487
}
11588
var buffer,
116-
byte;
89+
byte,
90+
result;
11791

118-
switch (windef.REG_VALUE_TYPE[valueType]) {
119-
case windef.REG_SZ:
120-
case windef.REG_EXPAND_SZ:
121-
case windef.REG_LINK:
122-
buffer = new Buffer(value, 'ascii');
92+
switch (valueType) {
93+
case windef.REG_VALUE_TYPE.REG_SZ:
94+
case windef.REG_VALUE_TYPE.REG_EXPAND_SZ:
95+
case windef.REG_VALUE_TYPE.REG_LINK:
96+
buffer = new Buffer(value, 'utf8');
97+
byte = ref.alloc(types.LPBYTE, buffer);
98+
debug('content length:' + Buffer.byteLength(value, 'utf8'));
99+
debug(value);
100+
debug(buffer.length);
101+
result = advApi.RegSetValueExA(key.handle.deref(), valueName, null, valueType, byte.deref(), Buffer.byteLength(value, 'utf8'));
123102
break;
124-
case windef.REG_BINARY:
103+
case windef.REG_VALUE_TYPE.REG_BINARY:
125104
// we assume that the value is a buffer since it should be binary data
126105
buffer = value;
106+
byte = ref.alloc(types.LPBYTE, buffer);
107+
result = advApi.RegSetValueExA(key.handle.deref(), valueName, null, valueType, byte.deref(), buffer.length);
127108
break;
128109
case windef.REG_VALUE_TYPE.REG_DWORD:
129110
case windef.REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
130111
case windef.REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
131112
buffer = new Buffer(4, value);
113+
result = advApi.RegSetValueExA(key.handle.deref(), valueName, null, valueType, byte.deref(), buffer.length);
132114
break;
133115
default:
134116
throw 'The type ' + valueType + ' is currently unsupported';
135117
}
136118

137-
byte = ref.alloc(types.LPBYTE, buffer);
138-
139-
var result = advApi.RegSetValueExA(key.handle.deref(), valueName, null, valueType, byte.deref(), buffer.length);
140-
141119
if (result !== 0) {
142120
throw 'Failed to open key error: ' + error[result];
143121
}
@@ -155,15 +133,15 @@ var api = {
155133
var result = advApi.RegDeleteTreeA(key.handle.deref(), subKeyName);
156134

157135
if (result !== 0) {
158-
throw 'Failed to open key error ' + result + ': + error[result]';
136+
throw 'Failed to open key error ' + result + ':' + error[result];
159137
}
160138
},
161139
closeKey: function (key) {
162-
console.log('KEY:' + key);
140+
debug('KEY:' + key);
163141
var result = advApi.RegCloseKey(key.handle.deref());
164142

165143
if (result !== 0) {
166-
throw 'Failed to open key error ' + result + ': + error[result]';
144+
throw 'Failed to open key error ' + result + ':' + error[result];
167145
}
168146
}
169147
};

0 commit comments

Comments
 (0)