Faculty of Information Technology
Software Engineering Group

Ticket #109: libbasic_fix_1_of_1_rev_12176ee7234c_Issue__109__Call__RegDeleteKeyExW____indirectly_via_function_pointer.patch

File libbasic_fix_1_of_1_rev_12176ee7234c_Issue__109__Call__RegDeleteKeyExW____indirectly_via_function_pointer.patch, 4.5 KB (added by Jan Vrany, 3 years ago)

Fix proposal (attempt 1)

  • Win32OperatingSystem.st

    # 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  
    1585615856!
    1585715857
    1585815858deleteSubKeyNamed: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:
    1586215862        #KEY_WOW64_64KEY to force access to the 64Bit Windows key,
    1586315863        #KEY_WOW64_32KEY to force access to the 32Bit Windows key,
    1586415864        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    "
    1586815866
    1586915867    |subKeyStringZ errorNumber|
    1587015868
    1587115869    subKeyStringZ := subKeyString asUnicode16StringZ.
    1587215870
    1587315871%{
    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   
    1588015897    HKEY myKey, subKey = 0;
    1588115898    int _retVal;
    1588215899    int _flags = 0;
     
    1589515912    if (__isExternalAddressLike(__INST(handle))
    1589615913     && __isUnicode16String(subKeyStringZ)) {
    1589715914        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        }
    1590615936        if (_retVal == ERROR_SUCCESS) {
    1590715937            RETURN (true);
    1590815938        }
     
    1591515945%}.
    1591615946
    1591715947    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        ]
    1591915953    ].
    1592015954    ^ false
    1592115955