Ticket #250: libbasic_fix_1_of_1_rev_6bd6624bd026_Issue__250__Smalltak_X_is_reading_Windows_Registry_only_in_ASCII_but_registry_is_UTF16.patch
File libbasic_fix_1_of_1_rev_6bd6624bd026_Issue__250__Smalltak_X_is_reading_Windows_Registry_only_in_ASCII_but_registry_is_UTF16.patch, 21.5 KB (added by , 5 years ago) |
---|
-
Win32OperatingSystem.st
# HG changeset patch # User Patrik Svestka <patrik.svestka@gmail.com> # Date 1542973588 -3600 # Fri Nov 23 12:46:28 2018 +0100 # Branch jv # Node ID 6bd6624bd026ff1637706eeeb1c84c2cba7b0e97 # Parent 20f35741c92ddc9da0dda0e43d8b34c2072a1285 Issue #250: Smalltak/X is reading Windows Registry only in ASCII but registry is UTF16 Fixed reading of unicode name and values from registry via valueNamed: - Added a REG_QWORD registry type (64bit number) - Added regression tests for the changes at RegressionTests::Win32OperatingSystemTest - At initialization (Win32OperatingSystem::RegistryEntry class) -> added #define USE_UNICODE - Added a comment on registry size limitations at #valueNamed:put: The #valueNameAtIndex: now supports unicode. The method is used at (all these now support unicode): - #valueNames (had to change nextPut: to nextPutUnicode:) - #valueNamesAndValuesDo: - #valueNamesDo: The #subKeyAtIndex:: now supports unicode. The method is used at (all these now support unicode): - #subKeysDo: - #allSubKeysDo: #valueNamed: dded a check if aValueName isEmptyOrNil (otherwise the Unicode conversion will bring out a debugger) Now supporting unicode (the ASCII option is there till write into registry fully supports Unicode too, then it will be removed) - #subKeyNameAndClassAtIndex: - #remoteKeyOnHost: For #ifdef USE_UNICODE added a #undef for each function so warning will not be displayed diff -r 20f35741c92d -r 6bd6624bd026 Win32OperatingSystem.st
a b 15503 15503 /* sigh - not defined with borland-cc */ 15504 15504 # define HKEY_PERFORMANCE_NLSTEXT (( HKEY ) (ULONG_PTR)((LONG)0x80000060) ) 15505 15505 #endif 15506 /* using unicode */ 15507 #define USE_UNICODE 15506 15508 %}. 15507 15509 HKEY_PERFORMANCE_TEXT := %{ __MKEXTERNALADDRESS(HKEY_PERFORMANCE_TEXT) %}. 15508 15510 HKEY_PERFORMANCE_NLSTEXT := %{ __MKEXTERNALADDRESS(HKEY_PERFORMANCE_NLSTEXT) %}. … … 16073 16075 16074 16076 remoteKeyOnHost:hostName 16075 16077 "return the corresponding registry entry from 16076 a remote computers registry." 16077 16078 |newEntry remoteHandle errorNumber| 16079 16078 a remote computers registry. 16079 Note: The registry key must be form a predefined list defined by Microsoft." 16080 16081 |aHostName newEntry remoteHandle errorNumber| 16082 16083 aHostName := hostName notEmptyOrNil ifTrue:[hostName asUnicode16StringZ]. 16084 16080 16085 %{ 16081 16086 HKEY myKey, remoteKey = 0; 16082 16087 int _retVal; 16083 16088 16084 if (__isExternalAddressLike(__INST(handle)) && __isStringLike(hostName)) { 16089 #ifdef USE_UNICODE 16090 #undef RegConnectRegistry 16091 #endif 16092 #ifdef USE_UNICODE 16093 #define RegConnectRegistry RegConnectRegistryW 16094 #else 16095 #define RegConnectRegistry RegConnectRegistryA 16096 #endif 16097 16098 /* Notes from MSDN: 16099 * link: https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regconnectregistryw 16100 * 16101 * 1) RegConnectRegistry requires the Remote Registry service to be running on the remote computer. 16102 * By default, this service is configured to be started manually. To configure the Remote Registry 16103 * service to start automatically, run Services.msc and change the Startup Type of the service to Automatic. 16104 * 16105 * 2) If the computer is joined to a workgroup and the "Force network logons using local accounts to authenticate as 16106 * Guest" policy is enabled, the function fails. Note that this policy is enabled by default if the computer is joined 16107 * to a workgroup. 16108 * 16109 * 3) If the current user does not have proper access to the remote computer, the call to RegConnectRegistry fails. To connect 16110 * to a remote registry, call LogonUser with LOGON32_LOGON_NEW_CREDENTIALS and ImpersonateLoggedOnUser before calling 16111 * RegConnectRegistry. 16112 * 16113 * 4) myKey must be a predefined registry handle. 16114 * more at: https://docs.microsoft.com/en-us/windows/desktop/SysInfo/predefined-keys 16115 * 16116 * 5) When a handle returned by RegConnectRegistry is no longer needed, it should be closed by calling RegCloseKey. (done by registerForFinaliation) 16117 * 16118 */ 16119 16120 if (__isExternalAddressLike(__INST(handle)) && __isUnicode16String(aHostName)) { 16085 16121 myKey = (HKEY)__externalAddressVal(__INST(handle)); 16086 if ((_retVal = RegConnectRegistry A(__stringVal(hostName), myKey, &remoteKey)) == ERROR_SUCCESS) {16122 if ((_retVal = RegConnectRegistry(__unicode16StringVal(aHostName), myKey, &remoteKey)) == ERROR_SUCCESS) { 16087 16123 remoteHandle = __MKEXTERNALADDRESS(remoteKey); 16088 16124 } else { 16089 16125 if ((_retVal != ERROR_PATH_NOT_FOUND) … … 16100 16136 ]. 16101 16137 errorNumber notNil ifTrue:[ 16102 16138 (OperatingSystem errorHolderForNumber:errorNumber) reportError. 16103 ]. 16139 ]. 16140 16104 16141 ^ nil 16105 16142 16106 16143 " … … 16131 16168 16132 16169 subKeyAtIndex:subKeyIndex 16133 16170 "return a new registry entry below mySelf for the given subKey index. 16134 Return nil if no such key exists" 16171 Return nil if no such key exists 16172 WARNING: subKeyIndex is 0-based!!" 16173 16135 16174 16136 16175 |subKeyName subKeyClassName errorNumber| 16137 16176 16138 16177 %{ 16139 16178 HKEY myKey, subKey = 0; 16179 16180 #ifdef USE_UNICODE 16181 #undef RegEnumKeyEx 16182 #endif 16183 #ifdef USE_UNICODE 16184 #define RegEnumKeyEx RegEnumKeyExW 16185 #else 16186 #define RegEnumKeyEx RegEnumKeyExA 16187 #endif 16188 16189 /* lpName (nameBuffer): 16190 * A pointer to a buffer that receives the name of the subkey, including the 16191 * terminating null character. The function copies only the name of the subkey, 16192 * not the full key hierarchy, to the buffer. If the function fails, no information is copied to this buffer. 16193 * 16194 * note: This actually means that the if the path fits within 255 chacaters you could get another 255 characters for the key itself. 16195 * This could help if you are having issues with the registry path lenght. 16196 */ 16197 16198 #ifdef USE_UNICODE 16199 wchar_t nameBuffer[256]; // 256 is due to Key name limit (including path) 16200 #else 16140 16201 char nameBuffer[256]; 16141 DWORD nameSize = sizeof(nameBuffer) - 1; 16142 char classNameBuffer[256]; 16143 DWORD classNameSize = sizeof(classNameBuffer) - 1; 16202 #endif 16203 DWORD nameSize = sizeof(nameBuffer); 16204 16205 /* lpClass (classNameBuffer): 16206 * A pointer to a buffer that receives the user-defined class of the enumerated subkey. 16207 */ 16208 16209 #ifdef USE_UNICODE 16210 wchar_t classNameBuffer[256]; 16211 #else 16212 char classNameBuffer[256]; 16213 #endif 16214 DWORD classNameSize = sizeof(classNameBuffer); 16144 16215 FILETIME modificationTime; 16145 16216 int _retVal; 16146 16217 16147 16218 if (__isExternalAddressLike(__INST(handle)) 16148 16219 && __isSmallInteger(subKeyIndex)) { 16149 16220 myKey = (HKEY)__externalAddressVal(__INST(handle)); 16150 if ((_retVal = RegEnumKeyEx A(myKey, __intVal(subKeyIndex),16221 if ((_retVal = RegEnumKeyEx(myKey, __intVal(subKeyIndex), 16151 16222 nameBuffer, &nameSize, 16152 16223 NULL, 16153 16224 classNameBuffer, &classNameSize, 16154 16225 &modificationTime)) == ERROR_SUCCESS) { 16155 16226 nameBuffer[nameSize] = '\0'; 16156 16227 classNameBuffer[classNameSize] = '\0'; 16157 subKeyName = __MKSTRING(nameBuffer); 16158 subKeyClassName = __MKSTRING(classNameBuffer); 16228 #ifdef USE_UNICODE 16229 subKeyName = __MKU16STRING(nameBuffer); 16230 subKeyClassName = __MKU16STRING(classNameBuffer); 16231 #else 16232 subKeyName = __MKSTRING(nameBuffer); 16233 subKeyClassName = __MKSTRING(classNameBuffer); 16234 #endif 16235 16159 16236 } else { 16160 16237 if ((_retVal != ERROR_PATH_NOT_FOUND) 16161 16238 && (_retVal != ERROR_FILE_NOT_FOUND) … … 16183 16260 16184 16261 subKeyNameAndClassAtIndex:subKeyIndex 16185 16262 "return the name and className of the given subKey at index as a pair. 16186 Return nil if no such key exists" 16263 Return nil if no such key exists 16264 WARNING: subKeyIndex is 0-based!!" 16187 16265 16188 16266 |subKeyName subKeyClassName errorNumber| 16189 16267 16190 16268 %{ 16191 16269 HKEY myKey, subKey = 0; 16270 16271 #ifdef USE_UNICODE 16272 #undef RegEnumKeyEx 16273 #endif 16274 #ifdef USE_UNICODE 16275 #define RegEnumKeyEx RegEnumKeyExW 16276 #else 16277 #define RegEnumKeyEx RegEnumKeyExA 16278 #endif 16279 16280 /* lpName (nameBuffer): 16281 * A pointer to a buffer that receives the name of the subkey, including the 16282 * terminating null character. The function copies only the name of the subkey, 16283 * not the full key hierarchy, to the buffer. If the function fails, no information is copied to this buffer. 16284 * 16285 * note: This actually means that the if the path fits within 255 chacaters you could get another 255 characters for the key itself. 16286 * This could help if you are having issues with the registry path lenght. 16287 */ 16288 16289 #ifdef USE_UNICODE 16290 wchar_t nameBuffer[256]; // limiting the nameBuffer to 255 characters + null terminator 16291 #else 16192 16292 char nameBuffer[256]; 16193 DWORD nameSize = sizeof(nameBuffer) - 1; 16194 char classNameBuffer[256]; 16195 DWORD classNameSize = sizeof(classNameBuffer) - 1; 16293 #endif 16294 DWORD nameSize = sizeof(nameBuffer); // - 1; 16295 16296 /* lpClass (classNameBuffer): 16297 * A pointer to a buffer that receives the user-defined class of the enumerated subkey. 16298 */ 16299 #ifdef USE_UNICODE 16300 wchar_t classNameBuffer[256]; // limiting the classNameBuffer to 255 characters + nul terminator 16301 #else 16302 char classNameBuffer[256]; 16303 #endif 16304 DWORD classNameSize = sizeof(classNameBuffer); // - 1; 16305 16196 16306 FILETIME modificationTime; 16197 16307 int _retVal; 16198 16308 16199 16309 if (__isExternalAddressLike(__INST(handle)) 16200 16310 && __isSmallInteger(subKeyIndex)) { 16201 16311 myKey = (HKEY)__externalAddressVal(__INST(handle)); 16202 if ((_retVal = RegEnumKeyEx A(myKey, __intVal(subKeyIndex),16312 if ((_retVal = RegEnumKeyEx(myKey, __intVal(subKeyIndex), 16203 16313 nameBuffer, &nameSize, 16204 16314 NULL, 16205 16315 classNameBuffer, &classNameSize, 16206 16316 &modificationTime)) == ERROR_SUCCESS) { 16207 16317 nameBuffer[nameSize] = '\0'; 16208 classNameBuffer[classNameSize] = '\0'; 16209 subKeyName = __MKSTRING(nameBuffer); 16210 subKeyClassName = __MKSTRING(classNameBuffer); 16318 classNameBuffer[classNameSize] = '\0'; 16319 #ifdef USE_UNICODE 16320 subKeyName = __MKU16STRING(nameBuffer); 16321 subKeyClassName = __MKU16STRING(classNameBuffer); 16322 #else 16323 subKeyName = __MKSTRING(nameBuffer); 16324 subKeyClassName = __MKSTRING(classNameBuffer); 16325 #endif 16211 16326 } else { 16212 16327 if ((_retVal != ERROR_PATH_NOT_FOUND) 16213 16328 && (_retVal != ERROR_FILE_NOT_FOUND) … … 16432 16547 16433 16548 valueNameAtIndex:valueIndex 16434 16549 "return a values name for the given value index. 16435 Return nil if no such value exists" 16550 Return nil if no such value exists 16551 WARNING: valueIndex is 0-based!!" 16436 16552 16437 16553 |valueName errorNumber| 16438 16554 16439 16555 %{ 16440 16556 HKEY myKey; 16441 char nameBuffer[256]; 16442 DWORD nameSize = sizeof(nameBuffer) - 1; 16557 16558 /* nameBuffer (lpValueName in RegEnumValue function): 16559 * A pointer to a buffer that receives the name of the value as a null-terminated string. 16560 * This buffer must be large enough to include the terminating null character. 16561 * For more information, see Registry Element Size Limits. 16562 */ 16563 #ifdef USE_UNICODE 16564 #undef RegEnumValue 16565 #endif 16566 #ifdef USE_UNICODE 16567 #define RegEnumValue RegEnumValueW 16568 wchar_t nameBuffer[256]; // 256 is due to Key name limit (including path) + the null character 16569 #else 16570 #define RegEnumValue RegEnumValueA 16571 char nameBuffer[256]; 16572 #endif 16573 16574 /* nameSize (lpcchValueName in RegEnumValue function): 16575 * 16576 * A pointer to a variable that specifies the size of the buffer pointed to by the lpValueName parameter, in characters. 16577 * When the function returns, the variable receives the number of characters stored in the buffer, not including the terminating null character. 16578 * 16579 * Registry value names are limited to 32,767 bytes. The ANSI version of this function treats this parameter as a SHORT value. 16580 * Therefore, if you specify a value greater than 32,767 bytes, there is an overflow and the function may return ERROR_MORE_DATA. 16581 */ 16582 DWORD nameSize = sizeof(nameBuffer); 16443 16583 DWORD valueType; 16444 16584 int _retVal; 16445 16585 16446 16586 if (__isExternalAddressLike(__INST(handle)) 16447 16587 && __isSmallInteger(valueIndex)) { 16448 16588 myKey = (HKEY)__externalAddressVal(__INST(handle)); 16449 if ((_retVal = RegEnumValue A(myKey, __intVal(valueIndex),16589 if ((_retVal = RegEnumValue(myKey, __intVal(valueIndex), 16450 16590 nameBuffer, &nameSize, 16451 16591 NULL, 16452 16592 &valueType, 16453 16593 NULL, NULL)) == ERROR_SUCCESS) { 16454 16594 nameBuffer[nameSize] = '\0'; 16595 #ifdef USE_UNICODE 16596 valueName = __MKU16STRING(nameBuffer); 16597 #else 16455 16598 valueName = __MKSTRING(nameBuffer); 16599 #endif 16456 16600 } else { 16457 16601 if ((_retVal != ERROR_PATH_NOT_FOUND) 16458 16602 && (_retVal != ERROR_FILE_NOT_FOUND) … … 16484 16628 REG_NONE -> nil 16485 16629 " 16486 16630 16487 |stringArray retVal errorNumber| 16631 |aValueNameZ stringArray retVal errorNumber| 16632 16633 aValueNameZ := aValueName notEmptyOrNil ifTrue:[aValueName asUnicode16StringZ]. 16488 16634 16489 16635 %{ /* STACK: 20000 */ 16490 HKEY myKey;16491 DWORD valueType;16492 union {16493 DWORD dWord;16494 unsigned char dWordBytes[4];16495 unsigned char smallDataBuffer[1024*16];16496 } quickData;16497 int val;16498 DWORD dataSize = sizeof(quickData);16499 unsigned char *dataBuffer = NULL;16500 #define xxUSE_UNICODE16501 16636 #ifdef USE_UNICODE 16502 # define xRegQueryValueEx RegQueryValueExW 16637 #undef RegQueryValueEx 16638 #endif 16639 #ifdef USE_UNICODE 16640 # define RegQueryValueEx RegQueryValueExW 16503 16641 # define CHAR short 16504 16642 #else 16505 16643 # define RegQueryValueEx RegQueryValueExA 16506 16644 # define CHAR char 16507 16645 #endif 16508 16646 16647 HKEY myKey; 16648 DWORD valueType; 16649 int val; 16650 union { 16651 DWORD dWord; 16652 unsigned char dWordBytes[4]; // needed for the shifts at REG_DWORD_LITTLE_ENDIAN and REG_DWORD_BIG_ENDIAN 16653 ULONGLONG qWord; // needed for the 64-bit int (QWORD) 16654 wchar_t wstringBuffer[1024*8]; // buffer for wide characters (unsigned char is not enough for Unicode) 16655 char stringBuffer[1024*16]; 16656 } quickData; 16657 16658 #ifdef USE_UNICODE 16659 wchar_t *dataBuffer = NULL; 16660 #else 16661 char *dataBuffer = NULL; 16662 #endif 16663 16664 DWORD dataSize = sizeof(quickData); 16665 16666 16509 16667 if (__isExternalAddressLike(__INST(handle)) 16510 && __is StringLike(aValueName)) {16668 && __isUnicode16String(aValueNameZ)) { 16511 16669 int ret; 16512 16670 16513 16671 myKey = (HKEY)__externalAddressVal(__INST(handle)); 16514 16672 16515 /* 16516 * try to get it with one call ... 16517 */ 16518 ret = RegQueryValueExA(myKey, __stringVal(aValueName), 16673 /* Reading values from registry 16674 * 16675 * LSTATUS RegQueryValueEx( // ends with either A(ascii) or W (unicode) 16676 * HKEY hKey, // a handle of a registry key 16677 * LPCWSTR lpValueName, // The name of the registry value 16678 * LPDWORD lpReserved, // reserved and must be NULL 16679 * LPDWORD lpType, // A pointer to a variable that recieves a code indicating the type of data stored in the specified value 16680 * LPBYTE lpData, // A pointer to a buffer that receives the value's data. This parameter can be NULL if datat is not required 16681 * LPDWORD lpcbData // A pointer to a variable that specifies the size of the buffer pointed to by the IpData parameter, in bytes. 16682 * // When the furnction returns, this variable contains the size of the data copied to IpData 16683 * ); 16684 */ 16685 16686 #if 0 16687 console_printf("================================================\n"); 16688 console_printf("Before - myKey: %p\n", &myKey); 16689 console_printf("Before - aValueName: %S\n", __unicode16StringVal(aValueNameZ)); 16690 console_printf("Before - valueType: %p, valueTypeData: %lu\n", &valueType, valueType); 16691 console_printf("Before - QuickData dWord: %lu\n", quickData.dWord); 16692 console_printf("Before - QuickData dWordBytes: %S\n", quickData.dWordBytes); 16693 console_printf("Before - QuickData qWord: %lu\n", quickData.qWord); 16694 console_printf("Before - QuickData smallDataBuffer: %S\n", quickData.smallDataBuffer); 16695 console_printf("Before - Databuffer: %p, dataBufferData: %s\n", &dataBuffer, dataBuffer); 16696 console_printf("Before - dataSize: %p, dataSizeData: %lu\n", &dataSize, dataSize); 16697 console_printf("================================================\n"); 16698 #endif 16699 16700 /* 16701 * try to get it with one call ... 16702 */ 16703 ret = RegQueryValueEx(myKey, __unicode16StringVal(aValueNameZ), 16519 16704 NULL, 16520 16705 &valueType, 16521 (char *)&quickData, 16706 #ifdef USE_UNICODE 16707 (LPBYTE) &quickData.wstringBuffer, // LPBYTE aka (unsigned char *) 16708 #else 16709 (LPBYTE) &quickData.stringBuffer, 16710 #endif 16711 16522 16712 &dataSize); 16713 #if 0 16714 console_printf("------------------------------------------------\n"); 16715 console_printf("After - myKey: %p\n", &myKey); 16716 console_printf("After - aValueName: %S\n", __unicode16StringVal(aValueNameZ)); 16717 console_printf("After - valueType: %p, valueTypeData: %lu\n", &valueType, valueType); 16718 console_printf("After - QuickData dWord: %lu\n", quickData.dWord); 16719 console_printf("After - QuickData dWordBytes: %S\n", quickData.dWordBytes); 16720 console_printf("After - QuickData qWord: %lu\n", quickData.qWord); 16721 console_printf("After - QuickData smallDataBuffer: %S\n", quickData.smallDataBuffer); 16722 console_printf("After - Databuffer: %p, dataBufferData: %s\n", &dataBuffer, dataBuffer); 16723 console_printf("After - dataSize: %p, dataSizeData: %lu\n", &dataSize, dataSize); 16724 console_printf("------------------------------------------------\n"); 16725 #endif 16726 16523 16727 #if 0 16524 console_printf("get \"%s\": dataSize=%d ret=%d\n", __stringVal(aValueName), dataSize, ret); 16728 console_printf("Registry key: %p\n", (void *) myKey); 16729 console_printf("get \"%S\": dataSize=%d ret=%d\n", __unicode16StringVal(aValueNameZ), dataSize, ret); 16525 16730 #endif 16526 16731 while (ret == ERROR_MORE_DATA) { 16527 16732 #if 0 16528 16733 console_printf("ERROR_MORE_DATA dataSize=%d valueType=%d\n", dataSize, valueType); 16529 16734 #endif 16530 16735 /* 16531 16736 * nope - need another one ... … … 16536 16741 switch (valueType) { 16537 16742 case REG_BINARY: 16538 16743 case REG_MULTI_SZ: 16539 dataBuffer = malloc(dataSize); ;16744 dataBuffer = malloc(dataSize); 16540 16745 break; 16541 16746 case REG_SZ: 16542 16747 dataBuffer = malloc(dataSize); … … 16546 16751 break; 16547 16752 } 16548 16753 if (dataBuffer) { 16549 ret = RegQueryValueEx(myKey, __stringVal(aValueName), 16754 console_printf("NOT EMPTY dataBuffer: %s", dataBuffer); 16755 ret = RegQueryValueEx(myKey, __unicode16StringVal(aValueNameZ), 16550 16756 NULL, 16551 16757 &valueType, 16552 dataBuffer,16758 (LPBYTE) dataBuffer, 16553 16759 &dataSize); 16554 16760 } else { 16555 16761 break; … … 16570 16776 break; 16571 16777 16572 16778 case REG_BINARY: 16573 retVal = __MKBYTEARRAY(dataBuffer ? dataBuffer : quickData.smallDataBuffer, dataSize); 16779 #ifdef USE_UNICODE 16780 retVal = __MKBYTEARRAY(dataBuffer ? dataBuffer : quickData.wstringBuffer, dataSize); 16781 #else 16782 retVal = __MKBYTEARRAY(dataBuffer ? dataBuffer : quickData.stringBuffer, dataSize); 16783 #endif 16574 16784 break; 16575 16785 16576 16786 case REG_SZ: 16577 16787 case REG_EXPAND_SZ: 16578 16788 #ifdef USE_UNICODE 16579 retVal = __MKU16STRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer); 16580 #else 16581 retVal = __MKSTRING(dataBuffer ? dataBuffer : quickData.smallDataBuffer); 16789 #if 0 16790 console_printf("dataBuffer before __MKU16STTRING: %S\n", dataBuffer); 16791 console_printf("QuickData smallDataBuffer before __MKU16STTRING: %S\n", quickData.smallDataBuffer); 16792 #endif 16793 retVal = __MKU16STRING(dataBuffer ? dataBuffer : quickData.wstringBuffer); 16794 #if 0 16795 console_printf("QuickData smallDataBuffer: %S\n", quickData.smallDataBuffer); 16796 console_printf("dataBuffer: %S\n", dataBuffer); 16797 #endif 16798 #else 16799 retVal = __MKSTRING(dataBuffer ? dataBuffer : quickData.stringBuffer); 16582 16800 #endif 16583 16801 break; 16584 16802 … … 16603 16821 val = (val << 8) | quickData.dWordBytes[3]; 16604 16822 retVal = __MKUINT(val); 16605 16823 break; 16824 16825 case REG_QWORD: // only REG_QWORD_LITTLE_ENDIAN present (no need for shifts) 16826 retVal = __MKULARGEINT(quickData.qWord); 16827 break; 16606 16828 16607 16829 case REG_MULTI_SZ: 16608 16830 { 16609 16831 CHAR *cp, *cp0; 16610 16832 int ns, i; 16611 16612 cp0 = dataBuffer ? dataBuffer : quickData.smallDataBuffer; 16833 #ifdef USE_UNICODE 16834 cp0 = dataBuffer ? dataBuffer : quickData.wstringBuffer; 16835 #else 16836 cp0 = dataBuffer ? dataBuffer : quickData.stringBuffer; 16837 #endif 16838 16613 16839 #if 0 16614 16840 console_printf("**************\n"); 16615 16841 for (i=0;i<50;i++) { … … 16689 16915 16690 16916 |data stringArray errorNumber| 16691 16917 %{ 16918 /* Registry Element Size Limits 16919 * 16920 * Found at MSDN: https://docs.microsoft.com/en-us/windows/desktop/SysInfo/registry-element-size-limits 16921 * 16922 * Registry Element | Size Limit 16923 * Key name 255 characters. The key name includes the absolute path of the key in the registry, always starting at a base key, for example, HKEY_LOCAL_MACHINE. 16924 * Value name 16,383 characters; Windows 2000: 260 ANSI characters or 16,383 Unicode characters. 16925 * Value Available memory (latest format)1 MB (standard format) 16926 * Tree A registry tree can be 512 levels deep. You can create up to 32 levels at a time through a single registry API call. 16927 * 16928 * Notes: 16929 * - Long values (more than 2,048 bytes) should be stored in a file, and the location of the file should be stored in the registry. 16930 * This helps the registry perform efficiently. 16931 * 16932 * - The file location can be the name of a value or the data of a value. Each backslash in the location string must be preceded by 16933 * another backslash as an escape character. For example, specify "C:\\mydir\\myfile" to store the string "C:\mydir\myfile". 16934 * A file location can also be the name of a key if it is within the 255-character limit for key names and does not contain backslashes, 16935 * which are not allowed in key names. 16936 */ 16937 16692 16938 HKEY myKey; 16693 16939 DWORD valueType = -1; 16694 16940 int val; … … 16918 17164 "evaluate aBlock for all value names" 16919 17165 16920 17166 ^ Array streamContents:[:s | 16921 self valueNamesDo:[:nm | s nextPut :nm]17167 self valueNamesDo:[:nm | s nextPutUnicode:nm] 16922 17168 ]. 16923 17169 16924 17170 "Created: / 18-01-2011 / 20:24:52 / cg"