# HG changeset patch
# User Jan Vrany <jan.vrany@fit.cvut.cz>
# Date 1482965927 0
# Wed Dec 28 22:58:47 2016 +0000
# Branch jv
# Node ID 12176ee7234c57f06115e5ec74cbc4d52950a5f9
# Parent 9ee1206fc24752642c5427ee8d7eda7c4812152b
Issue #109: Call `RegDeleteKeyExW()` indirectly via function pointer
...to allow running Smalltalk/X on (old) Windows XP. To be able to
delete 32bit / 64bit key we need to use RegDeleteKeyExW() which not
however available on (old) 32bit Windows XP. Yet we'd like
Smalltalk/X to run on those.
To do so, call RegDeleteKeyExW() indirectly via a function pointer
obtained by GetProcAddress(). If GetProcAddress() fails - meaning
we're running on such old Windows - we call old RegDeleteKeyW().
https://swing.fit.cvut.cz/projects/stx-jv/ticket/109
diff -r 9ee1206fc247 -r 12176ee7234c Win32OperatingSystem.st
a
|
b
|
|
15856 | 15856 | ! |
15857 | 15857 | |
15858 | 15858 | deleteSubKeyNamed:subKeyString flags:flags |
15859 | | "delete a key below mySelf. |
15860 | | Return true on success. |
15861 | | flags may be one of: |
| 15859 | "Delete a key below myself. return true on success. |
| 15860 | |
| 15861 | `flags` may be one of: |
15862 | 15862 | #KEY_WOW64_64KEY to force access to the 64Bit Windows key, |
15863 | 15863 | #KEY_WOW64_32KEY to force access to the 32Bit Windows key, |
15864 | 15864 | or nil, to access the key (32/64) for the current application. |
15865 | | |
15866 | | CAVEAT: due to a missing library entry in the BCC system, |
15867 | | the flags are currently ignored" |
| 15865 | " |
15868 | 15866 | |
15869 | 15867 | |subKeyStringZ errorNumber| |
15870 | 15868 | |
15871 | 15869 | subKeyStringZ := subKeyString asUnicode16StringZ. |
15872 | 15870 | |
15873 | 15871 | %{ |
15874 | | #ifndef KEY_WOW64_64KEY |
15875 | | // this is missing in BCC header files |
15876 | | # define KEY_WOW64_64KEY 0x0100 |
15877 | | # define KEY_WOW64_32KEY 0x0200 |
15878 | | #endif |
15879 | | |
| 15872 | /* |
| 15873 | * Following is a little tricky. To be able to access 32bit / 64bit keys |
| 15874 | * we need to use RegDeleteKeyExW() which not however available on (old)\ |
| 15875 | * 32bit Windows XP. Yet we'd like Smalltalk/X to run on those. |
| 15876 | * |
| 15877 | * To do so, call RegDeleteKeyExW() indirectly via a function pointer |
| 15878 | * obtained by GetProcAddress(). If GetProcAddress() fails - meaning |
| 15879 | * we're running on such old Windows - we call old RegDeleteKeyW(). |
| 15880 | */ |
| 15881 | static int initialized = 0; |
| 15882 | static LONG (WINAPI *RegDeleteKeyExWPtr)(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD Reserved) = NULL; |
| 15883 | if (1/*!initialized*/) { |
| 15884 | initialized = 1; |
| 15885 | HMODULE advapi32 = LoadLibrary("advapi32.dll"); |
| 15886 | if (!advapi32) { |
| 15887 | /* |
| 15888 | * Hmm, failed to load Advapi32.dll, can this happen? |
| 15889 | */ |
| 15890 | console_printf("Cannot load advapi32.dll\n"); |
| 15891 | errorNumber = __MKSMALLINT(GetLastError()); |
| 15892 | goto out; |
| 15893 | } |
| 15894 | RegDeleteKeyExWPtr = GetProcAddress(advapi32, "RegDeleteKeyExW"); |
| 15895 | } |
| 15896 | |
15880 | 15897 | HKEY myKey, subKey = 0; |
15881 | 15898 | int _retVal; |
15882 | 15899 | int _flags = 0; |
… |
… |
|
15895 | 15912 | if (__isExternalAddressLike(__INST(handle)) |
15896 | 15913 | && __isUnicode16String(subKeyStringZ)) { |
15897 | 15914 | myKey = (HKEY)__externalAddressVal(__INST(handle)); |
15898 | | #ifdef __BORLANDC__ |
15899 | | _retVal = RegDeleteKeyW(myKey, __unicode16StringVal(subKeyStringZ)); |
15900 | | #else |
15901 | | _retVal = RegDeleteKeyExW(myKey, |
15902 | | __unicode16StringVal(subKeyStringZ), |
15903 | | _flags, |
15904 | | 0); // reserved |
15905 | | #endif |
| 15915 | if (RegDeleteKeyExWPtr) { |
| 15916 | _retVal = RegDeleteKeyExWPtr(myKey, |
| 15917 | __unicode16StringVal(subKeyStringZ), |
| 15918 | _flags, |
| 15919 | 0); // reserved |
| 15920 | } else { |
| 15921 | /* |
| 15922 | * Some old Windows without RegDeleteKeyExW() such as |
| 15923 | * 32bit Windows XP. |
| 15924 | * In that case, try hard and call RegDeleteKeyW() - but only |
| 15925 | * if no flags are passed, i.e., `flags` parameter is nil. |
| 15926 | * This is to avoid silent failures when one explicitly asks |
| 15927 | * for 32bit or 64bit view on Windows that does not support |
| 15928 | * RegDeleteKeyExW(). |
| 15929 | */ |
| 15930 | if (flags != nil) { |
| 15931 | errorNumber = __MKSMALLINT(-1); // really stupid, should do better |
| 15932 | goto out; |
| 15933 | } |
| 15934 | _retVal = RegDeleteKeyW(myKey, __unicode16StringVal(subKeyStringZ)); |
| 15935 | } |
15906 | 15936 | if (_retVal == ERROR_SUCCESS) { |
15907 | 15937 | RETURN (true); |
15908 | 15938 | } |
… |
… |
|
15915 | 15945 | %}. |
15916 | 15946 | |
15917 | 15947 | errorNumber notNil ifTrue:[ |
15918 | | (OperatingSystem errorHolderForNumber:errorNumber) reportError. |
| 15948 | errorNumber == -1 ifTrue:[ |
| 15949 | self primitiveFailed: '32/64bit registry view requested but no RegDeleteKeyExW(). Windows too old?' |
| 15950 | ] ifFalse:[ |
| 15951 | (OperatingSystem errorHolderForNumber:errorNumber) reportError. |
| 15952 | ] |
15919 | 15953 | ]. |
15920 | 15954 | ^ false |
15921 | 15955 | |