Ticket #252: libbasic_fix_1_of_1_rev_6dfa3e4e2c32_Issue__252__Smalltak_X_is_writing_Windows_Registry_only_in_ASCII_but_registry_is_UTF16.patch

File libbasic_fix_1_of_1_rev_6dfa3e4e2c32_Issue__252__Smalltak_X_is_writing_Windows_Registry_only_in_ASCII_but_registry_is_UTF16.patch, 5.2 KB (added by patrik.svestka@…, 5 years ago)

the new method valueTypeAndSize: for better testing

  • Win32OperatingSystem.st

    # HG changeset patch
    # User Patrik Svestka <patrik.svestka@gmail.com>
    # Date 1544622027 -3600
    #      Wed Dec 12 14:40:27 2018 +0100
    # Branch jv
    # Node ID 6dfa3e4e2c32066a3101f26e62a977f621920516
    # Parent  af859227e285b51c0e688f4ee4ba1d3ec9d8e5de
    Issue #252: Smalltak/X is writing Windows Registry only in ASCII but registry is UTF16
     - Adding valueTypeAndSize: which returns a dictionary (#registryType -> dataSize)
      (note: dataSize can be either in characters (sizeInChars) or bytes (sizeInBytes))
    
    diff -r af859227e285 -r 6dfa3e4e2c32 Win32OperatingSystem.st
    a b  
    1591115911    "return the keys full key path name"
    1591215912
    1591315913    ^ path.
     15914!
     15915
     15916valueTypeAndSize:nameString
     15917    "Returns a Windows registry dictinary (#type -> size) based on value name
     15918    REG_NONE        -> nil
     15919    REG_BINARY      -> ByteArray
     15920    REG_SZ          -> String
     15921    REG_EXPAND_SZ   -> String (unexpadned windows variables)
     15922    REG_DWORD       -> Integer (can be LITTLE_ENDIAN or BIG_ENDIAN)
     15923    REG_DWORD       -> 64bit Integer
     15924    REG_MULTI_SZ    -> Array of strings (note: dataSize returns number of bytes)
     15925    "
     15926
     15927    |windowsRegistryTable nameUtf16Z errorNumber|
     15928
     15929    windowsRegistryTable := Dictionary new.
     15930
     15931    "/ adding terminating null into empty string
     15932    nameString notNil ifTrue:[
     15933        nameUtf16Z := nameString isEmpty ifTrue:[(nameString, (Character codePoint: 0)) asUnicode16String] "/ needed for defaultValue
     15934                                        ifFalse:[nameString asUnicode16StringZ]
     15935    ].
     15936
     15937%{
     15938    HKEY myKey;
     15939    DWORD valueType;
     15940
     15941    DWORD dataSize, sizeInChars, sizeInBytes = 0;
     15942
     15943    if (__isExternalAddressLike(__INST(handle))
     15944     && __isUnicode16String(nameUtf16Z)) {
     15945    int ret;
     15946
     15947    myKey = (HKEY)__externalAddressVal(__INST(handle));
     15948
     15949    // Getting valuetype and dataSize (actual data is not important)
     15950    ret = RegQueryValueExW(myKey, __unicode16StringVal(nameUtf16Z),
     15951             NULL,
     15952             &valueType,
     15953             NULL,
     15954             &dataSize);
     15955
     15956    if (ret == ERROR_SUCCESS) {
     15957        switch (valueType) {
     15958        case REG_NONE: // returns alwyas REG_NONE -> 0
     15959            __AT_PUT_(windowsRegistryTable , @symbol(REG_NONE), __MKUINT(0));
     15960            break;
     15961
     15962        case REG_BINARY:
     15963            sizeInBytes = dataSize;     
     15964            __AT_PUT_(windowsRegistryTable , @symbol(REG_BINARY), __MKUINT(sizeInBytes));
     15965            break;
     15966
     15967        case REG_SZ:
     15968            sizeInChars = (dataSize / sizeof(wchar_t)) - 1; // (datasize / character width) - terminating NULL
     15969            __AT_PUT_(windowsRegistryTable , @symbol(REG_SZ), __MKUINT(sizeInChars));
     15970            break;
     15971
     15972        case REG_EXPAND_SZ:
     15973            sizeInChars = (dataSize / sizeof(wchar_t)) - 1; // (datasize / character width) - terminating NULL
     15974            __AT_PUT_(windowsRegistryTable , @symbol(REG_EXPAND_SZ), __MKUINT(sizeInChars));
     15975            break;
     15976
     15977        case REG_DWORD_LITTLE_ENDIAN:
     15978            sizeInBytes = dataSize; // bytes of the registry type
     15979            __AT_PUT_(windowsRegistryTable , @symbol(REG_DWORD_LITTLE_ENDIAN), __MKUINT(sizeInBytes));
     15980            break;
     15981
     15982        case REG_DWORD_BIG_ENDIAN:
     15983            sizeInBytes = dataSize; // bytes of the registry type
     15984            __AT_PUT_(windowsRegistryTable , @symbol(REG_DWORD_BIG_ENDIAN), __MKUINT(sizeInBytes));
     15985            break;
     15986       
     15987        case REG_QWORD:
     15988            sizeInBytes = dataSize; // bytes of the registry type
     15989            __AT_PUT_(windowsRegistryTable , @symbol(REG_QWORD), __MKUINT(sizeInBytes));
     15990            break;
     15991           
     15992        case REG_MULTI_SZ:
     15993            {
     15994            /* dataSize note:
     15995             * Since we are not reading the actual data there is unknown number of terminaing NULL (every array item has one) and
     15996             * the end of the array has addtional one.  User has to count manually the number of terminaing NULL(s).
     15997             *
     15998             * A general formula for calculating size for REG_MULTI_SZ:
     15999             * ((array node size(1) + terminating NULL) + (array node size(2) + terminating NULL) + ... + (array node size(n) + terminating NULL)) * character width (sizeof(wchar_t)) - last terminating NULL (-1)
     16000             * A Smalltalk/C way:
     16001             * (((Array at: 1) size + 1) + ((Array at: 2) size + 1) + ... + ((Array at: n) size + 1))) * sizeof(wchar_t) - 1
     16002             */
     16003            sizeInBytes = dataSize;
     16004            __AT_PUT_(windowsRegistryTable , @symbol(REG_MULTI_SZ), __MKUINT(sizeInBytes));         
     16005            break;             
     16006            }       
     16007        default:
     16008            console_printf("[warning]: Unknown RegistryEntry valueType: %d\n", valueType);
     16009            break;
     16010        }
     16011    } else {
     16012        errorNumber = __MKSMALLINT(ret);
     16013    }
     16014    }
     16015
     16016%}.
     16017    errorNumber notNil ifTrue:[
     16018    (OperatingSystem errorHolderForNumber:errorNumber) reportError.
     16019    ].
     16020    ^ windowsRegistryTable
     16021
     16022    "
     16023     |key|
     16024
     16025     key := Dictionary new.
     16026     key := self key:'HKEY_LOCAL_MACHINE\SOFTWARE\eXept\Smalltalk/X'.
     16027     key valueTypeAndSize:'CurrentVersion'
     16028    "
    1591416029! !
    1591516030
    1591616031!Win32OperatingSystem::RegistryEntry methodsFor:'accessing subkeys'!