RegSetValueEx - что-то не работает

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

RegSetValueEx - что-то не работает

Сообщение Eugenio » 02.01.2005 (Вс) 11:28

результат выполнения функции - '1450'
вот определение в Winerror.h:
Код: Выделить всё
#define ERROR_NO_SYSTEM_RESOURCES        1450L

а вот код:
Код: Выделить всё
ValueName = "FileName" & CStr(I)
StrBuffer = StrFileName
lngBufferSize = Len(StrBuffer)
lngResult = RegSetValueEx(hKeyRecentFileList, ValueName, 0&,REG_SZ, ByVal StrBuffer, lngBufferSize)

Доступ, с которым открыт ключ hKeyRecentFileList - KEY_ALL_ACCESS,
в проге эта константа определена, как в windows.h.
Спасите-помогите. :(
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 02.01.2005 (Вс) 11:32

Посмотреть бы ещё как декларирована функция.

Если хочешь загрузиться, глянь сюда ;) http://bbs.vbstreets.ru/viewtopic.php?p=58911
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 02.01.2005 (Вс) 11:43

Я как раз загружаюсь, а пока вот:
Код: Выделить всё
Public Declare Function RegSetValueEx _
Lib "advapi32.dll" Alias "RegSetValueExA" _
(ByVal hKey As Long, ByVal lpValueName As String, _
ByVal dwReserved As Long, lpType As Long, lpData As Any, lpBufferSize As Long) As Long
Есть ли у меня вопрос? У меня всегда есть вопрос

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 02.01.2005 (Вс) 11:54

Черт! Теперь (без всяких изменений) код завершения - 87.
Winerror.h:
Код: Выделить всё
#define ERROR_INVALID_PARAMETER          87L    // dderror

Вообще не понял!! :x
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 02.01.2005 (Вс) 12:00

byval lptype as long
byval lpbuffersize as long :)

Код: Выделить всё
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 02.01.2005 (Вс) 12:41

GSerg писал(а):byval lptype as long
byval lpbuffersize as long :)

Черт, там ведь не указатель ожидается. Thanks.

Исчо вопрос, GSerg!
Что такое происходит при чтение из реестра с помощью RegQueryValueEx:
если значение параметра не установлено, эта собака все же возвращает строку, заполненную чем-то непонятным (два символа, ASCII-код=0). Это что такое?
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 02.01.2005 (Вс) 12:48

Дык если параметра нет, она же вернёт ноль в качестве его длины - а буфер само собой она изменять не будет :)

Имхо, тебе следует почитать, что такое отведение памяти, как оно используется при работе с API, как на самом деле происходит передача строк и что за ней стоит... :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 02.01.2005 (Вс) 13:05

GSerg писал(а):Дык если параметра нет, она же вернёт ноль в качестве его длины - а буфер само собой она изменять не будет :)

А вот и нет! При неустановленном значении (REG_SZ) она вернула мне в качестве длины буфера 1 (единицу)! А в строке - какое-то дерьмо, вообще непонятно что. Фукнция ASC(Mid(StrBuffer,N,1)) возвращает 0!
Вот и не помогает ни проверка длины буфера, ни Trim!
придется, то есть, еще и парсить эту строку, чтоб узнать, не фигня ли там?

GSerg писал(а):Имхо, тебе следует почитать, что такое отведение памяти, как оно используется при работе с API, как на самом деле происходит передача строк и что за ней стоит... :)

Надо мне, для начала, внимательнее на объявления API-функций смотреть. И про то, что такое строки в C, не забывать тоже, согласен.
Есть ли у меня вопрос? У меня всегда есть вопрос

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 02.01.2005 (Вс) 13:08

Там не может быть фигни. Что она возвращает, то там и есть.

If the data has the REG_SZ, REG_MULTI_SZ or REG_EXPAND_SZ type, then lpcbData will also include the size of the terminating null character or characters.

The lpcbData parameter can be NULL only if lpData is NULL.

If the buffer specified by lpData parameter is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of the lpData buffer are undefined.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 02.01.2005 (Вс) 19:14

Понял. Это было не "непонятно что" :)

Совет дадите? Где именно почитать про строки и передачу строк в том же MSDNе? Не про использование API, а подробности именно про то, как строки хранятся и передаются в VB и в C. Кое-что, естественно, знаю, но, наверное, совет почитать был все-таки правильный :) ..
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 02.01.2005 (Вс) 22:16

Хм, хранятся в виде последовательности байт, передаётся указатель на первый байт, он же начало строки. В конце строки стоит нулевой байт - признак конца. Вот и всё...
(на самом деле всё чуть хитрее, но знать только это вполне достаточно)
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 03.01.2005 (Пн) 18:11

tyomitch писал(а):Хм, хранятся в виде последовательности байт, передаётся указатель на первый байт, он же начало строки. В конце строки стоит нулевой байт - признак конца. Вот и всё...

2 Tyomitch. Да, а переменная, содержащая массив, в C на деле указатель на первый элемент. С этим "непонятно чем в строке" я просто дико сглупил, и не прочел описание функции.
Я сейчас имею в виду больше VB. Вот именно это (то что в цитате) я знаю, писал на C, но я не знаю точно, как в VB отводится память под строки. Там вроде только длина строки где-то указывается, то-ли в начале, то-ли в конце... И вот, например, вопрос: часть параметров мы передаем в API-шные функции As String, и я никогда не заботился о том, чтобы добавить там в конце vbNullChar или еще чего. И они воспринимаются нормально: ByVal SomeStringParameter As String и всё! Почему? По идее, поведение при этом непредсказуемо - если строка не оканчивается на "\0", то СИшная прога считывает и содержимое следующих ячеек памяти (шаг в соотв. с размерностью типа char), как "продолжение" массива, а у меня все работает...
Есть ли у меня вопрос? У меня всегда есть вопрос

hCORe
VB - Экстремал
VB - Экстремал
Аватара пользователя
 
Сообщения: 2332
Зарегистрирован: 22.02.2003 (Сб) 15:21
Откуда: parent directory

Сообщение hCORe » 03.01.2005 (Пн) 19:08

Ну так VB же не дурень :) Он её в правильный формат преобразует, результат обратно получает, преобразует опять и отдаёт тебе :)

А отводится память под строки, насколько я помню, по-разному. Обычно, в куче, но для фиксированных строк - в стеке :P Только зачем это-то знать? 8)
Моду создают модоки, а распространяют модозвоны.

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 03.01.2005 (Пн) 21:03

hCORe писал(а):Ну так VB же не дурень :)

1. Да я, типа, не сомневаюсь, что VB не дурень. Но интересно..
То есть, он подгоняет то, что передается, под тип формального параметра? (и наверное, при условии передачи ByVal?)
2. Где именно память выделяется - черт с ним (хотя интересно тоже), а вот как это выглядит?
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.01.2005 (Пн) 22:02

1. Строки в самом VB хранятся в весьма любопытном формате: перед строкой записана длина, а после неё - нуль. Т.ч. все API видят её как завершённую нулём без проблем.
При передаче в функцию, объявленную по Declare, создаётся временная ANSI-копия строки - вне зависимости, идёт передача ByVal или ByRef. После завершения вызова данные из временной ANSI-копии копируется обратно в исходную строку, и временая копия удаляется.
2. SysAllocString и иже с ними.
Изображение

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 03.01.2005 (Пн) 22:25

Вот теперь исчерпывающе.
Уточнить только хотца: временная ANSI-копия, видимо, БЕЗ длины, указанной в начале, т.е. стандартный такой вариант символьного массива, да?
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 03.01.2005 (Пн) 23:16

Временная ANSI-копия, скорее всего - с длиной в начале, но я никогда не проверял.
Передаваемый указатель всё равно указывает не на длину, а на первый символ. Т.е. строка начинается чуть раньше, чем куда указывает указатель.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 4:55

Временная ANSI-копия идёт без длины. Таков уж её формат, поскольку создатели C посчитали, что заканчивать строку нулём достаточно. Таким образом, строка начинается именно там, куда указывается указатель.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Eugenio
Постоялец
Постоялец
 
Сообщения: 393
Зарегистрирован: 08.05.2004 (Сб) 13:27
Откуда: Ekaterinburg

Сообщение Eugenio » 04.01.2005 (Вт) 10:59

Угу. ясно
Thanks a lot, мегачелы.
И за modRegistry
Есть ли у меня вопрос? У меня всегда есть вопрос

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 14:26

GSerg писал(а):Временная ANSI-копия идёт без длины. Таков уж её формат, поскольку создатели C посчитали, что заканчивать строку нулём достаточно. Таким образом, строка начинается именно там, куда указывается указатель.

Временная ANSI-копия идёт с длиной. Проверить очень легко:
Код: Выделить всё
Option Explicit

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function VarPtrStr Lib "msvbvm60" Alias "VarPtr" (ByVal Str As String) As Long

Sub Main()
Test VarPtrStr("Hello!")
End Sub

Private Sub Test(ByVal lpstr As Long)
Dim l As Long
CopyMemory l, ByVal lpstr - 4, 4
Debug.Print l
End Sub

Таким образом, строка начинается раньше, чем куда указывает указатель.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 14:33

:? :)

Если это и так, то всё равно, ни одна апишка никогда этим не воспользуется. С её точки зрения, размера впереди нет :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 14:38

Ну, "ни одна" - это слишком громко сказано, VarBstrCmp, например, - воспользуется ;-)
Большинство, действительно, - не воспользуется.
Кроме того, речь шла именно о форме представления строк в VB, а не о том, что делают апишки с ними потом.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 14:40

Неееее, не надо путать BSTR с ASCIIZ :)

А речь шла и о том, и о другом :razz:
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 14:51

BSTR может хранить ANSI-строку :shock:
Я нарочно выбрал именно VarBstrCmp, потому что в её описании есть строка "lcid: Locale identifier of the program to determine if either UNICODE or ANSI strings are being used."
Я бы сказал, что BSTR является частным случаем null-terminated строки. Т.е. это не есть два взаимно исключающих формата.

Ну, и анекдот в тему:
These two strings walk into a bar and sit down.
The bartender says, "So what'll it be?"
The first string says, "I think I'll have a beer quag fulk boorg jdk^CjfdLkjk3s d#f67howe%^U r89nvy~~owmc63^Dz x.xvcu"
"Please excuse my friend." the second string says, "He isn't null-terminated."
:-)
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 14:54

Ещё раз, для дальнейшего прояснения: при передаче строки в апишку создаётся временная ANSI-BSTR-копия. Что с ней делает апишка - её личное дело: она может использовать или игнорировать длину, записанную перед началом строки.
ANSI-BSTR-строка отличается от обычной null-terminated строки исключительно тем, что перед символами строки записана её длина.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 14:58

A BSTR, known as basic string or binary string, is a pointer to a wide character string used by Automation data manipulation functions.

typedef OLECHAR FAR* BSTR;

BSTRs are wide, double-byte (Unicode) strings on 32-bit Windows platforms and narrow, single-byte strings on the Apple® PowerMac™.


Из чего следует, что то, что временно создаёт VB, не является BSTR :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 17:23

VarBstrCmp, по-твоему, тоже не с BSTR работает? И все другие функции oleaut32, принмающие lcid - например, VarCmp - тоже не с BSTR?

Ещё, посмотри "Eric's Complete Guide To BSTR Semantics": http://blogs.gotdotnet.com/ericli/perma ... 0695e61168 . Вот как эту статью комментирует Рэймонд Чен: "This is a document that is widely valued within Microsoft, since BSTR semantics are rather tricky, and I'm glad he's willing to share it with the world." Там говорится, что BSTR может содержать Unicode-строку, или любые двоичные данные (к таким, видимо, и относятся ANSI-строки в VB).
Далее, ANSI-BSTR-строки, согласно гуглу, нигде кроме VB не используются. Применительно к VB же, термин "ANSI BSTR", ака "ABSTR", вполне установившийся: http://www.oreilly.com/catalog/win32api ... /ch06.html Тем забавнее, что в MSDN слово "ABSTR" не встречается ни разу :-)
Последний раз редактировалось tyomitch 04.01.2005 (Вт) 17:35, всего редактировалось 1 раз.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 17:25

Я к тому, что BSTR - она unicode...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.01.2005 (Вт) 17:38

Если, по-твоему, BSTR всегда Unicode, то как ты прокоментируешь уже приведённую мной цитату из MSDN: "lcid: Locale identifier of the program to determine if either UNICODE or ANSI strings are being used."
Или VarBstrCmp работает не с BSTR?

Ещё, прочитай мой предыдущий пост, я его дополнил :-)
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.01.2005 (Вт) 17:50

А ты как прокомментируешь мою цитату из MSDN, что это массив юникодовых чаров? :)

Можно, кстати, потестить эту функцию просто, и позырить, чё она там возвращает и как...


Или, наверное, BSTR - это в иерархии типа как HANDLE, а ABSTR - это, к примеру, HBRUSH :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

След.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot, Mail.ru [бот] и гости: 24

    TopList