diff options
| author | Eli Zaretskii | 2018-05-29 20:52:17 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2018-05-29 20:52:17 +0300 |
| commit | 5be83e343f9f0f3487793b54ff95bc89ee6b824a (patch) | |
| tree | de6c30ce8ef10deb795a9d391a9769acda6c92f0 | |
| parent | fd6f08840eb095465dfe555785eee228306ab876 (diff) | |
| download | emacs-5be83e343f9f0f3487793b54ff95bc89ee6b824a.tar.gz emacs-5be83e343f9f0f3487793b54ff95bc89ee6b824a.zip | |
Allow access to MS-Windows Registry from Lisp programs
* src/w32.c (g_b_init_reg_open_key_ex_w)
(g_b_init_reg_query_value_ex_w)
(g_b_init_expand_environment_strings_w): New init flags.
(globals_of_w32): Initialize them at startup.
(RegOpenKeyExW_Proc, RegQueryValueExW_Proc)
(ExpandEnvironmentStringsW_Proc): New function typedefs.
(reg_open_key_ex_w, reg_query_value_ex_w)
(expand_environment_strings_w): New wrapper function.
(w32_read_registry): New function.
* src/w32fns.c (Fw32_read_registry) [WINDOWSNT]: New primitive.
(syms_of_w32fns) [WINDOWSNT]: Defsubr it. DEFSYM "HKLM", "HKCU",
etc. root keys.
* etc/NEWS: Mention the new primitive.
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | src/w32.c | 291 | ||||
| -rw-r--r-- | src/w32.h | 2 | ||||
| -rw-r--r-- | src/w32fns.c | 81 |
4 files changed, 381 insertions, 0 deletions
| @@ -682,6 +682,13 @@ to 't' would enable the macOS proxy icon has been replaced with a | |||
| 682 | separate variable, 'ns-use-proxy-icon'. 'frame-title-format' will now | 682 | separate variable, 'ns-use-proxy-icon'. 'frame-title-format' will now |
| 683 | work as on other platforms. | 683 | work as on other platforms. |
| 684 | 684 | ||
| 685 | --- | ||
| 686 | ** New primitive 'w32-read-registry'. | ||
| 687 | This primitive lets Lisp programs access the MS-Windows Registry by | ||
| 688 | retrieving values stored under a given key. It is intended to be used | ||
| 689 | for supporting features such as XDG-like location of important files | ||
| 690 | and directories. | ||
| 691 | |||
| 685 | 692 | ||
| 686 | ---------------------------------------------------------------------- | 693 | ---------------------------------------------------------------------- |
| 687 | This file is part of GNU Emacs. | 694 | This file is part of GNU Emacs. |
| @@ -326,6 +326,9 @@ static BOOL g_b_init_set_file_security_a; | |||
| 326 | static BOOL g_b_init_set_named_security_info_w; | 326 | static BOOL g_b_init_set_named_security_info_w; |
| 327 | static BOOL g_b_init_set_named_security_info_a; | 327 | static BOOL g_b_init_set_named_security_info_a; |
| 328 | static BOOL g_b_init_get_adapters_info; | 328 | static BOOL g_b_init_get_adapters_info; |
| 329 | static BOOL g_b_init_reg_open_key_ex_w; | ||
| 330 | static BOOL g_b_init_reg_query_value_ex_w; | ||
| 331 | static BOOL g_b_init_expand_environment_strings_w; | ||
| 329 | 332 | ||
| 330 | BOOL g_b_init_compare_string_w; | 333 | BOOL g_b_init_compare_string_w; |
| 331 | BOOL g_b_init_debug_break_process; | 334 | BOOL g_b_init_debug_break_process; |
| @@ -504,6 +507,9 @@ typedef DWORD (WINAPI *GetAdaptersInfo_Proc) ( | |||
| 504 | int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); | 507 | int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int); |
| 505 | int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); | 508 | int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL); |
| 506 | DWORD multiByteToWideCharFlags; | 509 | DWORD multiByteToWideCharFlags; |
| 510 | typedef LONG (WINAPI *RegOpenKeyExW_Proc) (HKEY,LPCWSTR,DWORD,REGSAM,PHKEY); | ||
| 511 | typedef LONG (WINAPI *RegQueryValueExW_Proc) (HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD); | ||
| 512 | typedef DWORD (WINAPI *ExpandEnvironmentStringsW_Proc) (LPCWSTR,LPWSTR,DWORD); | ||
| 507 | 513 | ||
| 508 | /* ** A utility function ** */ | 514 | /* ** A utility function ** */ |
| 509 | static BOOL | 515 | static BOOL |
| @@ -1376,6 +1382,79 @@ get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) | |||
| 1376 | return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen); | 1382 | return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen); |
| 1377 | } | 1383 | } |
| 1378 | 1384 | ||
| 1385 | static LONG WINAPI | ||
| 1386 | reg_open_key_ex_w (HKEY hkey, LPCWSTR lpSubKey, DWORD ulOptions, | ||
| 1387 | REGSAM samDesired, PHKEY phkResult) | ||
| 1388 | { | ||
| 1389 | static RegOpenKeyExW_Proc s_pfn_Reg_Open_Key_Ex_w = NULL; | ||
| 1390 | HMODULE hm_advapi32 = NULL; | ||
| 1391 | |||
| 1392 | if (is_windows_9x () == TRUE) | ||
| 1393 | return ERROR_NOT_SUPPORTED; | ||
| 1394 | |||
| 1395 | if (g_b_init_reg_open_key_ex_w == 0) | ||
| 1396 | { | ||
| 1397 | g_b_init_reg_open_key_ex_w = 1; | ||
| 1398 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 1399 | if (hm_advapi32) | ||
| 1400 | s_pfn_Reg_Open_Key_Ex_w = (RegOpenKeyExW_Proc) | ||
| 1401 | GetProcAddress (hm_advapi32, "RegOpenKeyExW"); | ||
| 1402 | } | ||
| 1403 | if (s_pfn_Reg_Open_Key_Ex_w == NULL) | ||
| 1404 | return ERROR_NOT_SUPPORTED; | ||
| 1405 | return s_pfn_Reg_Open_Key_Ex_w (hkey, lpSubKey, ulOptions, | ||
| 1406 | samDesired, phkResult); | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | static LONG WINAPI | ||
| 1410 | reg_query_value_ex_w (HKEY hkey, LPCWSTR lpValueName, LPDWORD lpReserved, | ||
| 1411 | LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) | ||
| 1412 | { | ||
| 1413 | static RegQueryValueExW_Proc s_pfn_Reg_Query_Value_Ex_w = NULL; | ||
| 1414 | HMODULE hm_advapi32 = NULL; | ||
| 1415 | |||
| 1416 | if (is_windows_9x () == TRUE) | ||
| 1417 | return ERROR_NOT_SUPPORTED; | ||
| 1418 | |||
| 1419 | if (g_b_init_reg_query_value_ex_w == 0) | ||
| 1420 | { | ||
| 1421 | g_b_init_reg_query_value_ex_w = 1; | ||
| 1422 | hm_advapi32 = LoadLibrary ("Advapi32.dll"); | ||
| 1423 | if (hm_advapi32) | ||
| 1424 | s_pfn_Reg_Query_Value_Ex_w = (RegQueryValueExW_Proc) | ||
| 1425 | GetProcAddress (hm_advapi32, "RegQueryValueExW"); | ||
| 1426 | } | ||
| 1427 | if (s_pfn_Reg_Query_Value_Ex_w == NULL) | ||
| 1428 | return ERROR_NOT_SUPPORTED; | ||
| 1429 | return s_pfn_Reg_Query_Value_Ex_w (hkey, lpValueName, lpReserved, | ||
| 1430 | lpType, lpData, lpcbData); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | static DWORD WINAPI | ||
| 1434 | expand_environment_strings_w (LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize) | ||
| 1435 | { | ||
| 1436 | static ExpandEnvironmentStringsW_Proc s_pfn_Expand_Environment_Strings_w = NULL; | ||
| 1437 | HMODULE hm_kernel32 = NULL; | ||
| 1438 | |||
| 1439 | if (is_windows_9x () == TRUE) | ||
| 1440 | return ERROR_NOT_SUPPORTED; | ||
| 1441 | |||
| 1442 | if (g_b_init_expand_environment_strings_w == 0) | ||
| 1443 | { | ||
| 1444 | g_b_init_expand_environment_strings_w = 1; | ||
| 1445 | hm_kernel32 = LoadLibrary ("Kernel32.dll"); | ||
| 1446 | if (hm_kernel32) | ||
| 1447 | s_pfn_Expand_Environment_Strings_w = (ExpandEnvironmentStringsW_Proc) | ||
| 1448 | GetProcAddress (hm_kernel32, "ExpandEnvironmentStringsW"); | ||
| 1449 | } | ||
| 1450 | if (s_pfn_Expand_Environment_Strings_w == NULL) | ||
| 1451 | { | ||
| 1452 | errno = ENOSYS; | ||
| 1453 | return FALSE; | ||
| 1454 | } | ||
| 1455 | return s_pfn_Expand_Environment_Strings_w (lpSrc, lpDst, nSize); | ||
| 1456 | } | ||
| 1457 | |||
| 1379 | 1458 | ||
| 1380 | 1459 | ||
| 1381 | /* Return 1 if P is a valid pointer to an object of size SIZE. Return | 1460 | /* Return 1 if P is a valid pointer to an object of size SIZE. Return |
| @@ -9269,6 +9348,215 @@ network_interface_info (Lisp_Object ifname) | |||
| 9269 | } | 9348 | } |
| 9270 | 9349 | ||
| 9271 | 9350 | ||
| 9351 | /* Workhorse for w32-read-registry, which see. */ | ||
| 9352 | Lisp_Object | ||
| 9353 | w32_read_registry (HKEY rootkey, Lisp_Object lkey, Lisp_Object lname) | ||
| 9354 | { | ||
| 9355 | HKEY hkey = NULL; | ||
| 9356 | LONG status; | ||
| 9357 | DWORD vsize, vtype; | ||
| 9358 | LPBYTE pvalue; | ||
| 9359 | Lisp_Object val, retval; | ||
| 9360 | const char *key, *value_name; | ||
| 9361 | /* The following sizes are according to size limitations | ||
| 9362 | documented in MSDN. */ | ||
| 9363 | wchar_t key_w[255+1]; | ||
| 9364 | wchar_t value_w[16*1024+1]; | ||
| 9365 | bool use_unicode = is_windows_9x () == 0; | ||
| 9366 | |||
| 9367 | if (use_unicode) | ||
| 9368 | { | ||
| 9369 | Lisp_Object encoded_key, encoded_vname; | ||
| 9370 | |||
| 9371 | /* Convert input strings to UTF-16. */ | ||
| 9372 | encoded_key = code_convert_string_norecord (lkey, Qutf_16le, 1); | ||
| 9373 | memcpy (key_w, SSDATA (encoded_key), SBYTES (encoded_key)); | ||
| 9374 | /* wchar_t strings need to be terminated by 2 null bytes. */ | ||
| 9375 | key_w [SBYTES (encoded_key)/2] = L'\0'; | ||
| 9376 | encoded_vname = code_convert_string_norecord (lname, Qutf_16le, 1); | ||
| 9377 | memcpy (value_w, SSDATA (encoded_vname), SBYTES (encoded_vname)); | ||
| 9378 | value_w[SBYTES (encoded_vname)/2] = L'\0'; | ||
| 9379 | |||
| 9380 | /* Mirror the slashes, if required. */ | ||
| 9381 | for (int i = 0; i < SBYTES (encoded_key)/2; i++) | ||
| 9382 | { | ||
| 9383 | if (key_w[i] == L'/') | ||
| 9384 | key_w[i] = L'\\'; | ||
| 9385 | } | ||
| 9386 | if ((status = reg_open_key_ex_w (rootkey, key_w, 0, | ||
| 9387 | KEY_READ, &hkey)) == ERROR_NOT_SUPPORTED | ||
| 9388 | || (status = reg_query_value_ex_w (hkey, value_w, NULL, NULL, NULL, | ||
| 9389 | &vsize)) == ERROR_NOT_SUPPORTED | ||
| 9390 | || status != ERROR_SUCCESS) | ||
| 9391 | { | ||
| 9392 | if (hkey) | ||
| 9393 | RegCloseKey (hkey); | ||
| 9394 | if (status != ERROR_NOT_SUPPORTED) | ||
| 9395 | return Qnil; | ||
| 9396 | use_unicode = 0; /* fall back to non-Unicode calls */ | ||
| 9397 | } | ||
| 9398 | } | ||
| 9399 | if (!use_unicode) | ||
| 9400 | { | ||
| 9401 | /* Need to copy LKEY because we are going to modify it. */ | ||
| 9402 | Lisp_Object local_lkey = Fcopy_sequence (lkey); | ||
| 9403 | |||
| 9404 | /* Mirror the slashes. Note: this has to be done before | ||
| 9405 | encoding, because after encoding we cannot guarantee that a | ||
| 9406 | slash '/' always stands for itself, it could be part of some | ||
| 9407 | multibyte sequence. */ | ||
| 9408 | for (int i = 0; i < SBYTES (local_lkey); i++) | ||
| 9409 | { | ||
| 9410 | if (SSDATA (local_lkey)[i] == '/') | ||
| 9411 | SSDATA (local_lkey)[i] = '\\'; | ||
| 9412 | } | ||
| 9413 | |||
| 9414 | key = SSDATA (ENCODE_SYSTEM (local_lkey)); | ||
| 9415 | value_name = SSDATA (ENCODE_SYSTEM (lname)); | ||
| 9416 | |||
| 9417 | if ((status = RegOpenKeyEx (rootkey, key, 0, | ||
| 9418 | KEY_READ, &hkey)) != ERROR_SUCCESS | ||
| 9419 | || (status = RegQueryValueEx (hkey, value_name, NULL, | ||
| 9420 | NULL, NULL, &vsize)) != ERROR_SUCCESS) | ||
| 9421 | { | ||
| 9422 | if (hkey) | ||
| 9423 | RegCloseKey (hkey); | ||
| 9424 | return Qnil; | ||
| 9425 | } | ||
| 9426 | } | ||
| 9427 | |||
| 9428 | pvalue = xzalloc (vsize); | ||
| 9429 | if (use_unicode) | ||
| 9430 | status = reg_query_value_ex_w (hkey, value_w, NULL, &vtype, pvalue, &vsize); | ||
| 9431 | else | ||
| 9432 | status = RegQueryValueEx (hkey, value_name, NULL, &vtype, pvalue, &vsize); | ||
| 9433 | if (status != ERROR_SUCCESS) | ||
| 9434 | { | ||
| 9435 | xfree (pvalue); | ||
| 9436 | RegCloseKey (hkey); | ||
| 9437 | return Qnil; | ||
| 9438 | } | ||
| 9439 | |||
| 9440 | switch (vtype) | ||
| 9441 | { | ||
| 9442 | case REG_NONE: | ||
| 9443 | retval = Qt; | ||
| 9444 | break; | ||
| 9445 | case REG_DWORD: | ||
| 9446 | retval = INTEGER_TO_CONS (*((DWORD *)pvalue)); | ||
| 9447 | break; | ||
| 9448 | case REG_QWORD: | ||
| 9449 | retval = INTEGER_TO_CONS (*((long long *)pvalue)); | ||
| 9450 | break; | ||
| 9451 | case REG_BINARY: | ||
| 9452 | { | ||
| 9453 | int i; | ||
| 9454 | unsigned char *dbuf = (unsigned char *)pvalue; | ||
| 9455 | |||
| 9456 | val = make_uninit_vector (vsize); | ||
| 9457 | for (i = 0; i < vsize; i++) | ||
| 9458 | ASET (val, i, make_number (dbuf[i])); | ||
| 9459 | |||
| 9460 | retval = val; | ||
| 9461 | break; | ||
| 9462 | } | ||
| 9463 | case REG_SZ: | ||
| 9464 | if (use_unicode) | ||
| 9465 | { | ||
| 9466 | /* pvalue ends with 2 null bytes, but we need only one, | ||
| 9467 | and AUTO_STRING_WITH_LEN will add it. */ | ||
| 9468 | if (pvalue[vsize - 1] == '\0') | ||
| 9469 | vsize -= 2; | ||
| 9470 | AUTO_STRING_WITH_LEN (sval, (char *)pvalue, vsize); | ||
| 9471 | retval = from_unicode (sval); | ||
| 9472 | } | ||
| 9473 | else | ||
| 9474 | { | ||
| 9475 | /* Don't waste a byte on the terminating null character, | ||
| 9476 | since make_unibyte_string will add one anyway. */ | ||
| 9477 | if (pvalue[vsize - 1] == '\0') | ||
| 9478 | vsize--; | ||
| 9479 | retval = DECODE_SYSTEM (make_unibyte_string (pvalue, vsize)); | ||
| 9480 | } | ||
| 9481 | break; | ||
| 9482 | case REG_EXPAND_SZ: | ||
| 9483 | if (use_unicode) | ||
| 9484 | { | ||
| 9485 | wchar_t expanded_w[32*1024]; | ||
| 9486 | DWORD dsize = sizeof (expanded_w) / 2; | ||
| 9487 | DWORD produced = expand_environment_strings_w ((wchar_t *)pvalue, | ||
| 9488 | expanded_w, | ||
| 9489 | dsize); | ||
| 9490 | if (produced > 0 && produced < dsize) | ||
| 9491 | { | ||
| 9492 | AUTO_STRING_WITH_LEN (sval, (char *)expanded_w, | ||
| 9493 | produced * 2 - 2); | ||
| 9494 | retval = from_unicode (sval); | ||
| 9495 | } | ||
| 9496 | else | ||
| 9497 | { | ||
| 9498 | if (pvalue[vsize - 1] == '\0') | ||
| 9499 | vsize -= 2; | ||
| 9500 | AUTO_STRING_WITH_LEN (sval, (char *)pvalue, vsize); | ||
| 9501 | retval = from_unicode (sval); | ||
| 9502 | } | ||
| 9503 | } | ||
| 9504 | else | ||
| 9505 | { | ||
| 9506 | char expanded[32*1024]; /* size limitation according to MSDN */ | ||
| 9507 | DWORD produced = ExpandEnvironmentStrings ((char *)pvalue, | ||
| 9508 | expanded, | ||
| 9509 | sizeof (expanded)); | ||
| 9510 | if (produced > 0 && produced < sizeof (expanded)) | ||
| 9511 | retval = make_unibyte_string (expanded, produced - 1); | ||
| 9512 | else | ||
| 9513 | { | ||
| 9514 | if (pvalue[vsize - 1] == '\0') | ||
| 9515 | vsize--; | ||
| 9516 | retval = make_unibyte_string (pvalue, vsize); | ||
| 9517 | } | ||
| 9518 | |||
| 9519 | retval = DECODE_SYSTEM (retval); | ||
| 9520 | } | ||
| 9521 | break; | ||
| 9522 | case REG_MULTI_SZ: | ||
| 9523 | if (use_unicode) | ||
| 9524 | { | ||
| 9525 | wchar_t *wp = (wchar_t *)pvalue; | ||
| 9526 | |||
| 9527 | val = Qnil; | ||
| 9528 | do { | ||
| 9529 | size_t wslen = wcslen (wp); | ||
| 9530 | AUTO_STRING_WITH_LEN (sval, (char *)wp, wslen * 2); | ||
| 9531 | val = Fcons (from_unicode (sval), val); | ||
| 9532 | wp += wslen + 1; | ||
| 9533 | } while (*wp); | ||
| 9534 | } | ||
| 9535 | else | ||
| 9536 | { | ||
| 9537 | char *p = (char *)pvalue; | ||
| 9538 | |||
| 9539 | val = Qnil; | ||
| 9540 | do { | ||
| 9541 | size_t slen = strlen (p); | ||
| 9542 | |||
| 9543 | val = Fcons (DECODE_SYSTEM (make_unibyte_string (p, slen)), val); | ||
| 9544 | p += slen + 1; | ||
| 9545 | } while (*p); | ||
| 9546 | } | ||
| 9547 | |||
| 9548 | retval = Fnreverse (val); | ||
| 9549 | break; | ||
| 9550 | default: | ||
| 9551 | error ("unsupported registry data type: %d", (int)vtype); | ||
| 9552 | } | ||
| 9553 | |||
| 9554 | xfree (pvalue); | ||
| 9555 | RegCloseKey (hkey); | ||
| 9556 | return retval; | ||
| 9557 | } | ||
| 9558 | |||
| 9559 | |||
| 9272 | /* The Windows CRT functions are "optimized for speed", so they don't | 9560 | /* The Windows CRT functions are "optimized for speed", so they don't |
| 9273 | check for timezone and DST changes if they were last called less | 9561 | check for timezone and DST changes if they were last called less |
| 9274 | than 1 minute ago (see http://support.microsoft.com/kb/821231). So | 9562 | than 1 minute ago (see http://support.microsoft.com/kb/821231). So |
| @@ -9699,6 +9987,9 @@ globals_of_w32 (void) | |||
| 9699 | g_b_init_set_named_security_info_w = 0; | 9987 | g_b_init_set_named_security_info_w = 0; |
| 9700 | g_b_init_set_named_security_info_a = 0; | 9988 | g_b_init_set_named_security_info_a = 0; |
| 9701 | g_b_init_get_adapters_info = 0; | 9989 | g_b_init_get_adapters_info = 0; |
| 9990 | g_b_init_reg_open_key_ex_w = 0; | ||
| 9991 | g_b_init_reg_query_value_ex_w = 0; | ||
| 9992 | g_b_init_expand_environment_strings_w = 0; | ||
| 9702 | g_b_init_compare_string_w = 0; | 9993 | g_b_init_compare_string_w = 0; |
| 9703 | g_b_init_debug_break_process = 0; | 9994 | g_b_init_debug_break_process = 0; |
| 9704 | num_of_processors = 0; | 9995 | num_of_processors = 0; |
| @@ -227,6 +227,8 @@ extern int w32_compare_strings (const char *, const char *, char *, int); | |||
| 227 | /* Return a cryptographically secure seed for PRNG. */ | 227 | /* Return a cryptographically secure seed for PRNG. */ |
| 228 | extern int w32_init_random (void *, ptrdiff_t); | 228 | extern int w32_init_random (void *, ptrdiff_t); |
| 229 | 229 | ||
| 230 | extern Lisp_Object w32_read_registry (HKEY, Lisp_Object, Lisp_Object); | ||
| 231 | |||
| 230 | #ifdef HAVE_GNUTLS | 232 | #ifdef HAVE_GNUTLS |
| 231 | #include <gnutls/gnutls.h> | 233 | #include <gnutls/gnutls.h> |
| 232 | 234 | ||
diff --git a/src/w32fns.c b/src/w32fns.c index 2b920f29c65..5d1c3c84c67 100644 --- a/src/w32fns.c +++ b/src/w32fns.c | |||
| @@ -10059,6 +10059,78 @@ DEFUN ("w32-notification-close", | |||
| 10059 | #endif /* WINDOWSNT && !HAVE_DBUS */ | 10059 | #endif /* WINDOWSNT && !HAVE_DBUS */ |
| 10060 | 10060 | ||
| 10061 | 10061 | ||
| 10062 | #ifdef WINDOWSNT | ||
| 10063 | /*********************************************************************** | ||
| 10064 | Reading Registry | ||
| 10065 | ***********************************************************************/ | ||
| 10066 | DEFUN ("w32-read-registry", | ||
| 10067 | Fw32_read_registry, Sw32_read_registry, | ||
| 10068 | 3, 3, 0, | ||
| 10069 | doc: /* Return the value stored in MS-Windows Registry under ROOT/KEY/NAME. | ||
| 10070 | |||
| 10071 | ROOT is a symbol, one of `HKCR', `HKCU', `HKLM', `HKU', or `HKCC'. | ||
| 10072 | It can also be nil, which means try `HKCU', and if that fails, try `HKLM'. | ||
| 10073 | |||
| 10074 | KEY and NAME must be strings, and NAME must not include slashes. | ||
| 10075 | KEY can use either forward- or back-slashes. | ||
| 10076 | |||
| 10077 | If the the named KEY or its subkey called NAME don't exist, or cannot | ||
| 10078 | be accessed by the current user, the function returns nil. Otherwise, | ||
| 10079 | the return value depends on the type of the data stored in Registry: | ||
| 10080 | |||
| 10081 | If the data type is REG_NONE, the function returns t. | ||
| 10082 | If the data type is REG_DWORD or REG_QWORD, the function returns | ||
| 10083 | its integer value. If the value is too large for a Lisp integer, | ||
| 10084 | the function returns a cons (HIGH . LOW) of 2 integers, with LOW | ||
| 10085 | the low 16 bits and HIGH the high bits. If HIGH is too large for | ||
| 10086 | a Lisp integer, the function returns (HIGH MIDDLE . LOW), first | ||
| 10087 | the high bits, then the middle 24 bits, and finally the low 16 bits. | ||
| 10088 | If the data type is REG_BINARY, the function returns a vector whose | ||
| 10089 | elements are individual bytes of the value. | ||
| 10090 | If the data type is REG_SZ, the function returns a string. | ||
| 10091 | If the data type REG_EXPAND_SZ, the function returns a string with | ||
| 10092 | all the %..% references to environment variables replaced by the | ||
| 10093 | values of those variables. If the expansion fails, or some | ||
| 10094 | variables are not defined in the environment, some or all of | ||
| 10095 | the environment variables will remain unexpanded. | ||
| 10096 | If the data type is REG_MULTI_SZ, the function returns a list whose | ||
| 10097 | elements are the individual strings. | ||
| 10098 | |||
| 10099 | Note that this function doesn't know whether a string value is a file | ||
| 10100 | name, so file names will be returned with backslashes, which may need | ||
| 10101 | to be converted to forward slashes by the caller. */) | ||
| 10102 | (Lisp_Object root, Lisp_Object key, Lisp_Object name) | ||
| 10103 | { | ||
| 10104 | CHECK_SYMBOL (root); | ||
| 10105 | CHECK_STRING (key); | ||
| 10106 | CHECK_STRING (name); | ||
| 10107 | |||
| 10108 | HKEY rootkey; | ||
| 10109 | if (EQ (root, QHKCR)) | ||
| 10110 | rootkey = HKEY_CLASSES_ROOT; | ||
| 10111 | else if (EQ (root, QHKCU)) | ||
| 10112 | rootkey = HKEY_CURRENT_USER; | ||
| 10113 | else if (EQ (root, QHKLM)) | ||
| 10114 | rootkey = HKEY_LOCAL_MACHINE; | ||
| 10115 | else if (EQ (root, QHKU)) | ||
| 10116 | rootkey = HKEY_USERS; | ||
| 10117 | else if (EQ (root, QHKCC)) | ||
| 10118 | rootkey = HKEY_CURRENT_CONFIG; | ||
| 10119 | else if (!NILP (root)) | ||
| 10120 | error ("unknown root key: %s", SDATA (SYMBOL_NAME (root))); | ||
| 10121 | |||
| 10122 | Lisp_Object val = w32_read_registry (NILP (root) | ||
| 10123 | ? HKEY_CURRENT_USER | ||
| 10124 | : rootkey, | ||
| 10125 | key, name); | ||
| 10126 | if (NILP (val) && NILP (root)) | ||
| 10127 | val = w32_read_registry (HKEY_LOCAL_MACHINE, key, name); | ||
| 10128 | |||
| 10129 | return val; | ||
| 10130 | } | ||
| 10131 | |||
| 10132 | #endif /* WINDOWSNT */ | ||
| 10133 | |||
| 10062 | /*********************************************************************** | 10134 | /*********************************************************************** |
| 10063 | Initialization | 10135 | Initialization |
| 10064 | ***********************************************************************/ | 10136 | ***********************************************************************/ |
| @@ -10151,6 +10223,14 @@ syms_of_w32fns (void) | |||
| 10151 | DEFSYM (QCbody, ":body"); | 10223 | DEFSYM (QCbody, ":body"); |
| 10152 | #endif | 10224 | #endif |
| 10153 | 10225 | ||
| 10226 | #ifdef WINDOWSNT | ||
| 10227 | DEFSYM (QHKCR, "HKCR"); | ||
| 10228 | DEFSYM (QHKCU, "HKCU"); | ||
| 10229 | DEFSYM (QHKLM, "HKLM"); | ||
| 10230 | DEFSYM (QHKU, "HKU"); | ||
| 10231 | DEFSYM (QHKCC, "HKCC"); | ||
| 10232 | #endif | ||
| 10233 | |||
| 10154 | /* Symbols used elsewhere, but only in MS-Windows-specific code. */ | 10234 | /* Symbols used elsewhere, but only in MS-Windows-specific code. */ |
| 10155 | DEFSYM (Qgnutls, "gnutls"); | 10235 | DEFSYM (Qgnutls, "gnutls"); |
| 10156 | DEFSYM (Qlibxml2, "libxml2"); | 10236 | DEFSYM (Qlibxml2, "libxml2"); |
| @@ -10508,6 +10588,7 @@ tip frame. */); | |||
| 10508 | #endif | 10588 | #endif |
| 10509 | 10589 | ||
| 10510 | #ifdef WINDOWSNT | 10590 | #ifdef WINDOWSNT |
| 10591 | defsubr (&Sw32_read_registry); | ||
| 10511 | defsubr (&Sfile_system_info); | 10592 | defsubr (&Sfile_system_info); |
| 10512 | defsubr (&Sdefault_printer_name); | 10593 | defsubr (&Sdefault_printer_name); |
| 10513 | #endif | 10594 | #endif |