right_popen 1.0.5-x86-mswin32-60 → 1.0.6-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
@@ -1144,7 +1144,7 @@ static VALUE right_popen_get_current_user_environment(VALUE vSelf)
1144
1144
  }
1145
1145
  }
1146
1146
 
1147
- // merge environment.
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
  }
@@ -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
- # user environment from registry supercedes process.
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 (which is stored in the registry on Windows as a combination of
351
- # system and user-specific environment variables). The resulting hash
352
- # represents any variables set for the persisted user context but any set
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
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.5'
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.5
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-02-23 00:00:00 -08:00
13
+ date: 2010-03-16 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency