--- a/Win32OperatingSystem.st Fri Jan 18 11:57:14 2019 +0000
+++ b/Win32OperatingSystem.st Wed Dec 05 14:21:11 2018 +0100
@@ -16533,7 +16533,7 @@
"
!
-defaultValue:datum
+defaultValue:data
"store a value; the value type depends upon the stored value:
ByteArray -> REG_BINARY
String -> REG_SZ
@@ -16542,7 +16542,7 @@
nil -> REG_NONE
"
- ^ self valueNamed:'' put:datum
+ ^ self valueNamed:'' put:data
"
(self key:'HKEY_CLASSES_ROOT\MicrosoftWorks.WordProcessor\CLSID') defaultValue
@@ -16923,16 +16923,62 @@
"
!
-valueNamed:aValueName put:datum
+valueNamed:name put:data
+ "store a value; the value type depends upon the stored value:
+ ByteArray -> REG_BINARY
+ String -> REG_SZ
+ Array of string -> REG_MULTI_SZ
+ Integer -> REG_DWORD
+ nil -> REG_NONE
+ "
+ "Transcript showCR: 'name:', name.
+ Transcript showCR: 'data:', data."
+
+ ^ self valueNamed:name put:data unexpandedReferences:false
+!
+
+valueNamed:name put:data unexpandedReferences:containsUnexpandedReferences
"store a value; the value type depends upon the stored value:
ByteArray -> REG_BINARY
- String -> REG_SZ
+ String -> REG_SZ OR REG_EXPAND_SZ based on containsUnexpandedReferences
Array of string -> REG_MULTI_SZ
Integer -> REG_DWORD
nil -> REG_NONE
- "
-
- |data stringArray errorNumber|
+
+ containsUnexpandedReferences:
+ true -> REG_EXPAND_SZ
+ false -> REG_SZ
+
+ REG_EXPAND_SZ:
+ Null-terminated string that contains unexpanded references to environment variables (for example, ""%PATH%""). It will be a Unicode or ANSI string,
+ depending on whether you use the Unicode or ANSI functions.
+ "
+
+ |nameUtf16Z dataUtf16Z stringArray errorNumber|
+
+ "/ name must be a string, if not return nil
+ name isString ifFalse: [
+ Transcript showCR: 'The registry value name must be a String!!'.
+ ^ nil
+ ].
+ "/ name asUnicodeString and null terminated
+ name notNil ifTrue:[
+ name isEmpty ifTrue:[nameUtf16Z := (name, (Character codePoint: 0)) asUnicode16String] "/ needed for defaultValue:
+ ifFalse:[nameUtf16Z := name asUnicode16StringZ]
+ ].
+ "/ data asUnicode16String and null terminated
+ data notNil ifTrue:[
+ data isString ifTrue:[
+ data isEmpty ifTrue:[dataUtf16Z := (data, (Character codePoint: 0)) asUnicode16String] "/ for empty data strings
+ ifFalse:[dataUtf16Z := data asUnicode16StringZ]
+ ].
+ data isArray ifTrue:[
+ dataUtf16Z := data collect:[:eachString | "/ for every Array member to be null terminated
+ eachString asUnicode16StringZ
+ ]
+ ]
+ ].
+
%{
/* Registry Element Size Limits
*
@@ -16952,48 +16998,90 @@
* another backslash as an escape character. For example, specify "C:\\mydir\\myfile" to store the string "C:\mydir\myfile".
* 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,
* which are not allowed in key names.
+ *
+ * RegSetValueExW (catches)
+ *
+ * LSTATUS RegSetValueExW(
+ * HKEY hKey,
+ * LPCSTR lpValueName,
+ * DWORD Reserved,
+ * DWORD dwType,
+ * const BYTE *lpData,
+ * DWORD cbData
+ * );
+ *
+ * lpValueName
+ * The name of the value to be set. If a value with this name is not already present in the key, the function adds it to the key.
+ * If lpValueName is NULL or an empty string, "", the function sets the type and data for the key's unnamed or default value.
+ * For more information, see Registry Element Size Limits (above).
+ * Registry keys do not have default values, but they can have one unnamed value, which can be of any type.
+ *
+ * lpData
+ * The data to be stored.
+ * For string-based types, such as REG_SZ, the string must be null-terminated. With the REG_MULTI_SZ data type, the string must be terminated
+ * with **two** null characters.
+ * Note lpData indicating a null value is valid, however, if this is the case, cbData must be set to '0'.
+ *
+ * cbData
+ * The size of the information pointed to by the lpData parameter, in bytes.
+ * If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.
+ *
+ * Remarks
+ * Value sizes are limited by available memory. However, storing large values in the registry can affect its performance.
+ * Long values (more than 2,048 bytes) should be stored as files, with the locations of the files stored in the registry.
+ *
+ * Application elements such as icons, bitmaps, and executable files should be stored as files and not be placed in the registry.
+ *
+ * If dwType is the REG_SZ, REG_MULTI_SZ, or REG_EXPAND_SZ type and the ANSI version of this function is used (either by explicitly
+ * calling RegSetValueExA or by not defining UNICODE before including the Windows.h file), the data pointed to by the lpData parameter
+ * must be an ANSI character string. The string is converted to Unicode before it is stored in the registry.
+ *
+ * Note that operations that access certain registry keys are redirected. For more information, see Registry Virtualization and 32-bit and
+ * 64-bit Application Data in the Registry.
+ *
*/
HKEY myKey;
DWORD valueType = -1;
int val;
+ ULONGLONG longVal;
DWORD dataSize = -1;
- unsigned char *dataPointer = NULL;
- int datumOk = 1, mustFreeData = 0;
+ void *dataPointer = NULL;
+ int dataOk = 1, mustFreeData = 0;
if (__isExternalAddressLike(__INST(handle))
- && __isStringLike(aValueName)) {
+ && __isUnicode16String(nameUtf16Z)) {
int ret;
OBJ cls;
myKey = (HKEY)__externalAddressVal(__INST(handle));
- if (datum == nil) {
+ if (data == nil) {
valueType = REG_NONE;
dataSize = 0;
- } else if (__isSmallInteger(datum)) {
+ } else if (__isSmallInteger(data)) {
valueType = REG_DWORD;
- val = __intVal(datum);
- dataPointer = (unsigned char *)(&val);
+ val = __intVal(data);
+ dataPointer = &val;
dataSize = sizeof(val);
- } else if (__isStringLike(datum)) {
- valueType = REG_SZ;
- dataPointer = __stringVal(datum);
- dataSize = __stringSize(datum) + 1;
- } else if (__Class(datum) == ByteArray) {
+ } else if (__isUnicode16String(dataUtf16Z)) {
+ valueType = containsUnexpandedReferences == true ? REG_EXPAND_SZ : REG_SZ;
+ dataPointer = __unicode16StringVal(dataUtf16Z);
+ dataSize = __unicode16StringSize(dataUtf16Z) * sizeof(wchar_t);
+ } else if (__Class(data) == ByteArray) {
valueType = REG_BINARY;
- dataPointer = __ByteArrayInstPtr(datum)->ba_element;
- dataSize = __byteArraySize(datum);
- } else if (__Class(datum) == LargeInteger) {
- valueType = REG_DWORD;
- val = __longIntVal(datum);
- if (val) {
- dataPointer = (unsigned char *)(&val);
- dataSize = sizeof(val);
+ dataPointer = __ByteArrayInstPtr(data)->ba_element;
+ dataSize = __byteArraySize(data);
+ } else if (__Class(data) == LargeInteger) {
+ valueType = REG_QWORD;
+ longVal = __longIntVal(data);
+ if (longVal) {
+ dataPointer = &longVal;
+ dataSize = sizeof(longVal);
} else {
- datumOk = 0;
- }
- } else if (__Class(datum) == Array) {
+ dataOk = 0;
+ }
+ } else if (__Class(data) == Array) {
int i = 0, ns = 0, totalSize = 0;
valueType = REG_MULTI_SZ;
@@ -17002,45 +17090,48 @@
* must allocate a local buffer
* find size ...
*/
- for (i=0; i<__arraySize(datum); i++) {
- OBJ s = __ArrayInstPtr(datum)->a_element[i];
-
- if (__isStringLike(s)) {
- totalSize += __stringSize(s) + 1;
+ for (i=0; i<__arraySize(dataUtf16Z); i++) {
+ OBJ s = __ArrayInstPtr(dataUtf16Z)->a_element[i];
+
+ if (__isUnicode16String(s)) {
+ totalSize += __unicode16StringSize(s);
} else {
- datumOk = 0;
+ dataOk = 0;
break;
}
ns++;
}
- if (datumOk) {
- char *cp;
+
+ if (dataOk) {
+ wchar_t *cp;
/*
* allocate and fill...
*/
- totalSize ++;
- dataPointer = (char *)(malloc(totalSize));
+ // (totalSize length * size of wide char) + terminating null character
+ totalSize = (totalSize * sizeof(wchar_t)) + 1;
+ dataPointer = malloc(totalSize);
mustFreeData = 1;
cp = dataPointer;
- for (i=0; i<__arraySize(datum); i++) {
- OBJ s = __ArrayInstPtr(datum)->a_element[i];
-
- strcpy(cp, __stringVal(s));
- cp += __stringSize(s);
- *cp++ = '\0';
+ for (i=0; i<__arraySize(dataUtf16Z); i++) {
+ OBJ s = __ArrayInstPtr(dataUtf16Z)->a_element[i];
+
+ memcpy(cp, __unicode16StringVal(s), __unicode16StringSize(s) * sizeof(wchar_t));
+ cp += __unicode16StringSize(s);
}
- *cp++ = '\0';
+ *cp++ = '\0'; // adding second terminating null character (for more information see MSDN comment above)
dataSize = totalSize;
+ //console_printf("DataSize: %d\n", dataSize);
}
} else {
- datumOk = 0;
- }
-
- if (datumOk) {
- ret = RegSetValueExA(myKey, __stringVal(aValueName),
+ dataOk = 0;
+ }
+
+ if (dataOk) {
+ ret = RegSetValueExW(myKey, __unicode16StringVal(nameUtf16Z),
0, valueType,
- dataPointer, dataSize);
+ (LPBYTE) dataPointer,
+ dataSize);
if (mustFreeData) {
free(dataPointer);
}