right_popen 1.0.5-x86-mswin32-60 → 1.0.6-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/win32/right_popen.c +264 -1
- data/lib/win32/right_popen.rb +18 -5
- data/lib/win32/right_popen.so +0 -0
- data/right_popen.gemspec +1 -1
- metadata +2 -2
data/ext/win32/right_popen.c
CHANGED
@@ -1144,7 +1144,7 @@ static VALUE right_popen_get_current_user_environment(VALUE vSelf)
|
|
1144
1144
|
}
|
1145
1145
|
}
|
1146
1146
|
|
1147
|
-
//
|
1147
|
+
// convert environment block to a Ruby string.
|
1148
1148
|
//
|
1149
1149
|
// note that there is only a unicode form of this API call (instead of
|
1150
1150
|
// the usual _A and _W pair) and that the environment strings appear to
|
@@ -1166,6 +1166,268 @@ static VALUE right_popen_get_current_user_environment(VALUE vSelf)
|
|
1166
1166
|
}
|
1167
1167
|
}
|
1168
1168
|
|
1169
|
+
// Summary:
|
1170
|
+
// grows the environment block as needed.
|
1171
|
+
//
|
1172
|
+
// Parameters:
|
1173
|
+
// ppEnvironmentBlock:
|
1174
|
+
// address of environment block buffer or NULL, receives reallocated buffer if necessary.
|
1175
|
+
//
|
1176
|
+
// pdwBlockLength:
|
1177
|
+
// address of current block length or zero, receives updated block length.
|
1178
|
+
//
|
1179
|
+
// dwBlockOffset:
|
1180
|
+
// current block offset.
|
1181
|
+
//
|
1182
|
+
// dwNeededLength:
|
1183
|
+
// needed allocation length not including nul terminator(s)
|
1184
|
+
static void win32_grow_environment_block(LPWSTR* ppEnvironmentBlock, DWORD* pdwBlockLength, DWORD dwBlockOffset, DWORD dwNeededLength)
|
1185
|
+
{
|
1186
|
+
DWORD dwOldLength = *pdwBlockLength;
|
1187
|
+
DWORD dwTerminatedLength = dwBlockOffset + dwNeededLength + 2; // need two nuls after last string
|
1188
|
+
|
1189
|
+
if (dwOldLength < dwTerminatedLength)
|
1190
|
+
{
|
1191
|
+
// generally double length to degrade grow frequency.
|
1192
|
+
DWORD dwNewLength = max(dwOldLength * 2, dwTerminatedLength);
|
1193
|
+
|
1194
|
+
dwNewLength = max(dwNewLength, 512);
|
1195
|
+
|
1196
|
+
// reallocate.
|
1197
|
+
{
|
1198
|
+
WCHAR* pOldBlock = *ppEnvironmentBlock;
|
1199
|
+
WCHAR* pNewBlock = (WCHAR*)malloc(dwNewLength * sizeof(WCHAR));
|
1200
|
+
|
1201
|
+
if (NULL != pOldBlock)
|
1202
|
+
{
|
1203
|
+
memcpy(pNewBlock, pOldBlock, dwOldLength * sizeof(WCHAR));
|
1204
|
+
}
|
1205
|
+
ZeroMemory(pNewBlock + dwOldLength, (dwNewLength - dwOldLength) * sizeof(WCHAR));
|
1206
|
+
if (NULL != pOldBlock)
|
1207
|
+
{
|
1208
|
+
free(pOldBlock);
|
1209
|
+
pOldBlock = NULL;
|
1210
|
+
}
|
1211
|
+
*ppEnvironmentBlock = pNewBlock;
|
1212
|
+
*pdwBlockLength = dwNewLength;
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
// Summary:
|
1218
|
+
// reallocates the buffer needed to contain the given name/value pair and
|
1219
|
+
// copies the name/value pair in expected format to the end of the
|
1220
|
+
// environment block.
|
1221
|
+
//
|
1222
|
+
// Parameters:
|
1223
|
+
// pValueName:
|
1224
|
+
// nul-terminated value name
|
1225
|
+
//
|
1226
|
+
// dwValueNameLength:
|
1227
|
+
// length of value name not including nul terminator
|
1228
|
+
//
|
1229
|
+
// pValueData:
|
1230
|
+
// nul-terminated string or expand-string style value data
|
1231
|
+
//
|
1232
|
+
// dwValueDataLength:
|
1233
|
+
// length of value data not including nul terminator
|
1234
|
+
//
|
1235
|
+
// ppEnvironmentBlock:
|
1236
|
+
// result buffer to receive all name/value pairs or NULL to measure
|
1237
|
+
//
|
1238
|
+
// pdwBlockLength:
|
1239
|
+
// address of current buffer length or zero, receives updated length
|
1240
|
+
//
|
1241
|
+
// pdwBlockOffset:
|
1242
|
+
// address of current buffer offset or zero, receives updated offset
|
1243
|
+
static void win32_append_to_environment_block(LPCWSTR pValueName,
|
1244
|
+
DWORD dwValueNameLength,
|
1245
|
+
LPCWSTR pValueData,
|
1246
|
+
DWORD dwValueDataLength,
|
1247
|
+
LPWSTR* ppEnvironmentBlock,
|
1248
|
+
DWORD* pdwBlockLength,
|
1249
|
+
DWORD* pdwBlockOffset)
|
1250
|
+
{
|
1251
|
+
// grow, if necessary.
|
1252
|
+
DWORD dwNeededLength = dwValueNameLength + 1 + dwValueDataLength;
|
1253
|
+
|
1254
|
+
win32_grow_environment_block(ppEnvironmentBlock, pdwBlockLength, *pdwBlockOffset, dwNeededLength);
|
1255
|
+
|
1256
|
+
// copy name/value pair using "<value name>=<value data>\0" format.
|
1257
|
+
{
|
1258
|
+
DWORD dwBlockOffset = *pdwBlockOffset;
|
1259
|
+
LPWSTR pszBuffer = *ppEnvironmentBlock + dwBlockOffset;
|
1260
|
+
|
1261
|
+
memcpy(pszBuffer, pValueName, dwValueNameLength * sizeof(WCHAR));
|
1262
|
+
pszBuffer += dwValueNameLength;
|
1263
|
+
*pszBuffer++ = '=';
|
1264
|
+
memcpy(pszBuffer, pValueData, dwValueDataLength * sizeof(WCHAR));
|
1265
|
+
pszBuffer += dwValueDataLength;
|
1266
|
+
*pszBuffer = 0;
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
// update offset.
|
1270
|
+
*pdwBlockOffset += dwNeededLength + 1;
|
1271
|
+
}
|
1272
|
+
|
1273
|
+
// Summary:
|
1274
|
+
// gets the environment strings from the registry for the machine.
|
1275
|
+
//
|
1276
|
+
// Returns:
|
1277
|
+
// nul-terminated block of nul-terminated environment strings as a Ruby string value.
|
1278
|
+
static VALUE right_popen_get_machine_environment(VALUE vSelf)
|
1279
|
+
{
|
1280
|
+
// open key.
|
1281
|
+
HKEY hKey = NULL;
|
1282
|
+
LPWSTR pEnvironmentBlock = NULL;
|
1283
|
+
DWORD dwValueCount = 0;
|
1284
|
+
DWORD dwMaxValueNameLength = 0;
|
1285
|
+
DWORD dwMaxValueDataSizeBytes = 0;
|
1286
|
+
DWORD dwResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
1287
|
+
L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
|
1288
|
+
0,
|
1289
|
+
KEY_READ,
|
1290
|
+
&hKey);
|
1291
|
+
if (ERROR_SUCCESS != dwResult)
|
1292
|
+
{
|
1293
|
+
rb_raise(rb_eRuntimeError, "RegOpenKeyExW() failed: %s", win32_error_description(dwResult));
|
1294
|
+
}
|
1295
|
+
|
1296
|
+
// query key info.
|
1297
|
+
dwResult = RegQueryInfoKeyW(hKey, // key handle
|
1298
|
+
NULL, // buffer for class name
|
1299
|
+
NULL, // size of class string
|
1300
|
+
NULL, // reserved
|
1301
|
+
NULL, // number of subkeys
|
1302
|
+
NULL, // longest subkey size
|
1303
|
+
NULL, // longest class string
|
1304
|
+
&dwValueCount, // number of values for this key
|
1305
|
+
&dwMaxValueNameLength, // longest value name
|
1306
|
+
&dwMaxValueDataSizeBytes, // longest value data
|
1307
|
+
NULL, // security descriptor
|
1308
|
+
NULL); // last write time
|
1309
|
+
if (ERROR_SUCCESS != dwResult)
|
1310
|
+
{
|
1311
|
+
RegCloseKey(hKey);
|
1312
|
+
rb_raise(rb_eRuntimeError, "RegQueryInfoKeyW() failed: %s", win32_error_description(dwResult));
|
1313
|
+
}
|
1314
|
+
|
1315
|
+
// enumerate values and create result block.
|
1316
|
+
{
|
1317
|
+
LPWSTR pszValueName = (WCHAR*)malloc((dwMaxValueNameLength + 1) * sizeof(WCHAR));
|
1318
|
+
BYTE* pValueData = (BYTE*)malloc(dwMaxValueDataSizeBytes);
|
1319
|
+
|
1320
|
+
ZeroMemory(pszValueName, (dwMaxValueNameLength + 1) * sizeof(WCHAR));
|
1321
|
+
ZeroMemory(pValueData, dwMaxValueDataSizeBytes);
|
1322
|
+
{
|
1323
|
+
// enumerate values.
|
1324
|
+
//
|
1325
|
+
// note that there is nothing to prevent the data changing while
|
1326
|
+
// the key is open for reading; we need to be cautious and not
|
1327
|
+
// overrun the queried data buffer size in the rare case that the
|
1328
|
+
// max data increases in size.
|
1329
|
+
DWORD dwBlockLength = 0;
|
1330
|
+
DWORD dwBlockOffset = 0;
|
1331
|
+
DWORD dwValueIndex = 0;
|
1332
|
+
|
1333
|
+
for (; dwValueIndex < dwValueCount; ++dwValueIndex)
|
1334
|
+
{
|
1335
|
+
DWORD dwValueNameLength = dwMaxValueNameLength + 1;
|
1336
|
+
DWORD dwValueDataSizeBytes = dwMaxValueDataSizeBytes;
|
1337
|
+
DWORD dwValueType = REG_NONE;
|
1338
|
+
|
1339
|
+
dwResult = RegEnumValueW(hKey,
|
1340
|
+
dwValueIndex,
|
1341
|
+
pszValueName,
|
1342
|
+
&dwValueNameLength,
|
1343
|
+
NULL,
|
1344
|
+
&dwValueType,
|
1345
|
+
pValueData,
|
1346
|
+
&dwValueDataSizeBytes);
|
1347
|
+
|
1348
|
+
// ignore any failures but continue on to next value.
|
1349
|
+
if (ERROR_SUCCESS == dwResult)
|
1350
|
+
{
|
1351
|
+
// only expecting string and expand string values; ignore anything else.
|
1352
|
+
switch (dwValueType)
|
1353
|
+
{
|
1354
|
+
case REG_EXPAND_SZ:
|
1355
|
+
case REG_SZ:
|
1356
|
+
{
|
1357
|
+
// byte size of Unicode string value must be even and include nul terminator.
|
1358
|
+
if (0 == (dwValueDataSizeBytes % sizeof(WCHAR)) && dwValueDataSizeBytes >= sizeof(WCHAR))
|
1359
|
+
{
|
1360
|
+
LPWSTR pszValueData = (LPWSTR)pValueData;
|
1361
|
+
DWORD dwValueDataLength = (dwValueDataSizeBytes / sizeof(WCHAR)) - 1;
|
1362
|
+
|
1363
|
+
if (0 == pszValueData[dwValueDataLength])
|
1364
|
+
{
|
1365
|
+
// need to expand (pseudo) environment variables for expand string values.
|
1366
|
+
if (REG_EXPAND_SZ == dwValueType)
|
1367
|
+
{
|
1368
|
+
DWORD dwExpandedDataLength = ExpandEnvironmentStringsW(pszValueData, NULL, 0);
|
1369
|
+
LPWSTR pszExpandedData = (WCHAR*)malloc(dwExpandedDataLength * sizeof(WCHAR));
|
1370
|
+
|
1371
|
+
ZeroMemory(pszExpandedData, dwExpandedDataLength * sizeof(WCHAR));
|
1372
|
+
if (dwExpandedDataLength == ExpandEnvironmentStringsW(pszValueData, pszExpandedData, dwExpandedDataLength))
|
1373
|
+
{
|
1374
|
+
win32_append_to_environment_block(pszValueName,
|
1375
|
+
dwValueNameLength,
|
1376
|
+
pszExpandedData,
|
1377
|
+
dwExpandedDataLength - 1,
|
1378
|
+
&pEnvironmentBlock,
|
1379
|
+
&dwBlockLength,
|
1380
|
+
&dwBlockOffset);
|
1381
|
+
}
|
1382
|
+
free(pszExpandedData);
|
1383
|
+
pszExpandedData = NULL;
|
1384
|
+
}
|
1385
|
+
else
|
1386
|
+
{
|
1387
|
+
win32_append_to_environment_block(pszValueName,
|
1388
|
+
dwValueNameLength,
|
1389
|
+
pszValueData,
|
1390
|
+
dwValueDataLength,
|
1391
|
+
&pEnvironmentBlock,
|
1392
|
+
&dwBlockLength,
|
1393
|
+
&dwBlockOffset);
|
1394
|
+
}
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
}
|
1398
|
+
}
|
1399
|
+
}
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
// handle corner case of no (valid) machine environment values.
|
1403
|
+
if (NULL == pEnvironmentBlock)
|
1404
|
+
{
|
1405
|
+
win32_grow_environment_block(&pEnvironmentBlock, &dwBlockLength, dwBlockOffset, 0);
|
1406
|
+
}
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
// free temporary buffers.
|
1410
|
+
free(pszValueName);
|
1411
|
+
pszValueName = NULL;
|
1412
|
+
free(pValueData);
|
1413
|
+
pValueData = NULL;
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
// close.
|
1417
|
+
RegCloseKey(hKey);
|
1418
|
+
hKey = NULL;
|
1419
|
+
|
1420
|
+
// convert environment block to a Ruby string.
|
1421
|
+
{
|
1422
|
+
VALUE value = win32_unicode_environment_block_to_ruby(pEnvironmentBlock);
|
1423
|
+
|
1424
|
+
free(pEnvironmentBlock);
|
1425
|
+
pEnvironmentBlock = NULL;
|
1426
|
+
|
1427
|
+
return value;
|
1428
|
+
}
|
1429
|
+
}
|
1430
|
+
|
1169
1431
|
// Summary:
|
1170
1432
|
// gets the environment strings for the current process.
|
1171
1433
|
//
|
@@ -1200,5 +1462,6 @@ void Init_right_popen()
|
|
1200
1462
|
rb_define_module_function(vModule, "popen4", (VALUE(*)(ANYARGS))right_popen_popen4, -1);
|
1201
1463
|
rb_define_module_function(vModule, "async_read", (VALUE(*)(ANYARGS))right_popen_async_read, 1);
|
1202
1464
|
rb_define_module_function(vModule, "get_current_user_environment", (VALUE(*)(ANYARGS))right_popen_get_current_user_environment, 0);
|
1465
|
+
rb_define_module_function(vModule, "get_machine_environment", (VALUE(*)(ANYARGS))right_popen_get_machine_environment, 0);
|
1203
1466
|
rb_define_module_function(vModule, "get_process_environment", (VALUE(*)(ANYARGS))right_popen_get_process_environment, 0);
|
1204
1467
|
}
|
data/lib/win32/right_popen.rb
CHANGED
@@ -265,9 +265,13 @@ module RightScale
|
|
265
265
|
# merged string block
|
266
266
|
def self.merge_environment(environment_hash)
|
267
267
|
current_user_environment_hash = get_current_user_environment
|
268
|
+
machine_environment_hash = get_machine_environment
|
268
269
|
result_environment_hash = get_process_environment
|
269
270
|
|
270
|
-
#
|
271
|
+
# machine from registry supercedes process.
|
272
|
+
merge_environment2(machine_environment_hash, result_environment_hash)
|
273
|
+
|
274
|
+
# user environment from registry supercedes machine and process.
|
271
275
|
merge_environment2(current_user_environment_hash, result_environment_hash)
|
272
276
|
|
273
277
|
# caller's environment supercedes all.
|
@@ -347,10 +351,9 @@ module RightScale
|
|
347
351
|
end
|
348
352
|
|
349
353
|
# Queries the environment strings from the current thread/process user's
|
350
|
-
# environment
|
351
|
-
#
|
352
|
-
#
|
353
|
-
# dynamically in the current process context.
|
354
|
+
# environment. The resulting hash represents any variables set for the
|
355
|
+
# persisted user context but any set dynamically in the current process
|
356
|
+
# context.
|
354
357
|
#
|
355
358
|
# === Returns
|
356
359
|
# environment_hash(Hash):: hash of environment key (String) to value (String).
|
@@ -360,6 +363,16 @@ module RightScale
|
|
360
363
|
return string_block_to_environment_hash(environment_strings)
|
361
364
|
end
|
362
365
|
|
366
|
+
# Queries the environment strings from the machine's environment.
|
367
|
+
#
|
368
|
+
# === Returns
|
369
|
+
# environment_hash(Hash):: hash of environment key (String) to value (String).
|
370
|
+
def self.get_machine_environment
|
371
|
+
environment_strings = RightPopen.get_machine_environment
|
372
|
+
|
373
|
+
return string_block_to_environment_hash(environment_strings)
|
374
|
+
end
|
375
|
+
|
363
376
|
# Queries the environment strings from the process environment (which is kept
|
364
377
|
# in memory for each process and generally begins life as a copy of the
|
365
378
|
# process user's environment context plus any changes made by ancestral
|
data/lib/win32/right_popen.so
CHANGED
Binary file
|
data/right_popen.gemspec
CHANGED
@@ -6,7 +6,7 @@ end
|
|
6
6
|
|
7
7
|
spec = Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'right_popen'
|
9
|
-
spec.version = '1.0.
|
9
|
+
spec.version = '1.0.6'
|
10
10
|
spec.authors = ['Scott Messier', 'Raphael Simon']
|
11
11
|
spec.email = 'scott@rightscale.com'
|
12
12
|
spec.homepage = 'https://github.com/rightscale/right_popen'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_popen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: x86-mswin32-60
|
6
6
|
authors:
|
7
7
|
- Scott Messier
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-
|
13
|
+
date: 2010-03-16 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|