String with Embedded Nulls?
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
Does anyone know how I can use a string that has embedded nulls (zeros)? I have to create a string for a Windows API call that has some zeros in it, but PureBasic "stops" at the very first zero. It doesn't pass the entire string, just up to the first zero, and the API call fails. I have tested the API call in Visual Basic, which doesn't use null-terminated strings, and it works correctly. Is there some way to do this in PureBasic?
Thank you,
Eric Schuyler
Does anyone know how I can use a string that has embedded nulls (zeros)? I have to create a string for a Windows API call that has some zeros in it, but PureBasic "stops" at the very first zero. It doesn't pass the entire string, just up to the first zero, and the API call fails. I have tested the API call in Visual Basic, which doesn't use null-terminated strings, and it works correctly. Is there some way to do this in PureBasic?
Thank you,
Eric Schuyler
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by freak.
Instead of strings, you can also use an Array of bytes for the API calls.
Dim text.b(10)
Now fill up the bytes with the Ascii-values of your string. You can get them with the Asc() function. Fill in the zeros where needed.
Now call your API call with @text() instead of the string variable.
That's it, hope it helps...
Timo
--
A debugged program is one for which you have not yet found the conditions that make it fail.
Instead of strings, you can also use an Array of bytes for the API calls.
Dim text.b(10)
Now fill up the bytes with the Ascii-values of your string. You can get them with the Asc() function. Fill in the zeros where needed.
Now call your API call with @text() instead of the string variable.
That's it, hope it helps...
Timo
--
A debugged program is one for which you have not yet found the conditions that make it fail.
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
PB,
I'm trying to set up an ODBC data source with the API function SQLConfigDataSource() in odbccp32.dll. Here's the Visual Basic declaration:
Private Declare Function SQLConfigDataSource Lib "odbccp32.dll" (ByVal hwndParent As Long, ByVal fRequest As Integer, ByVal lpszDriver As String, ByVal lpszAttributes As String) As Long
The last parameter (lpszAttributes) is built like this in Visual Basic:
Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
& vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
(vbNullChar is a byte with a value of 0)
When I do something similar in PureBasic, the string it passes ends at the first null character (after the DSNName). Do you have any suggestions?
Thanks,
Eric
PB,
I'm trying to set up an ODBC data source with the API function SQLConfigDataSource() in odbccp32.dll. Here's the Visual Basic declaration:
Private Declare Function SQLConfigDataSource Lib "odbccp32.dll" (ByVal hwndParent As Long, ByVal fRequest As Integer, ByVal lpszDriver As String, ByVal lpszAttributes As String) As Long
The last parameter (lpszAttributes) is built like this in Visual Basic:
Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
& vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
(vbNullChar is a byte with a value of 0)
When I do something similar in PureBasic, the string it passes ends at the first null character (after the DSNName). Do you have any suggestions?
Thanks,
Eric
I don't know the answer to your specific null-related question, but if you tell
me what the API is that you're trying to use, I may be able to show you a way to
do it...
PB - Registered PureBasic Coder
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by PB.
> I'm trying to set up an ODBC data source with the API function SQLConfigDataSource() in odbccp32.dll
I'm not familiar with that DLL... but read on...
> Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
> & vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
I think you can replace vbNullChar with an empty string (""), so try replacing
vbNullString with "" in your Visual Basic source to check if the API call still
works, and if it does, then try this in your PureBasic source:
Attributes = "DSN=" + DSNName + "" + "Description=" + Description + "" + "DBQ=" + Databasename + "" + ""
If this doesn't work, then I'm not sure how to proceed just yet... sorry.
PB - Registered PureBasic Coder
> I'm trying to set up an ODBC data source with the API function SQLConfigDataSource() in odbccp32.dll
I'm not familiar with that DLL... but read on...
> Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
> & vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
I think you can replace vbNullChar with an empty string (""), so try replacing
vbNullString with "" in your Visual Basic source to check if the API call still
works, and if it does, then try this in your PureBasic source:
Attributes = "DSN=" + DSNName + "" + "Description=" + Description + "" + "DBQ=" + Databasename + "" + ""
If this doesn't work, then I'm not sure how to proceed just yet... sorry.
PB - Registered PureBasic Coder
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
PB,
Unfortunately, that doesn't work. The API call requires one byte of 0 separating each part of the string - that's what vbNullChar is. Thanks for the suggestion, though!
Freak,
I've tried using the byte array as you suggest, but that doesn't seem to work at all. Using the string method, I can see that the first part of the string was applied correctly - I get an ODBC datasource called "TestDSN". With a byte array, nothing happens, so I guess I must not be passing the address of the array correctly. I've tried using "@Bytes", "@Bytes()", and "@Bytes(0)" with similar results. Anything else you can suggest?
Thanks to both,
Eric
PB,
Unfortunately, that doesn't work. The API call requires one byte of 0 separating each part of the string - that's what vbNullChar is. Thanks for the suggestion, though!
Freak,
I've tried using the byte array as you suggest, but that doesn't seem to work at all. Using the string method, I can see that the first part of the string was applied correctly - I get an ODBC datasource called "TestDSN". With a byte array, nothing happens, so I guess I must not be passing the address of the array correctly. I've tried using "@Bytes", "@Bytes()", and "@Bytes(0)" with similar results. Anything else you can suggest?
Thanks to both,
Eric
> I'm trying to set up an ODBC data source with the API function SQLConfigDataSource() in odbccp32.dll
I'm not familiar with that DLL... but read on...
> Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
> & vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
I think you can replace vbNullChar with an empty string (""), so try replacing
vbNullString with "" in your Visual Basic source to check if the API call still
works, and if it does, then try this in your PureBasic source:
Attributes = "DSN=" + DSNName + "" + "Description=" + Description + "" + "DBQ=" + Databasename + "" + ""
If this doesn't work, then I'm not sure how to proceed just yet... sorry.
PB - Registered PureBasic Coder
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by PB.
> Unfortunately, that doesn't work. The API call requires one byte of 0
> separating each part of the string - that's what vbNullChar is.
Oops, I just realised you said vbNullChar, not vbNullString -- no wonder I got
it wrong! Hmm, that definitely makes it harder to solve then... perhaps you
could show us your code so we can try experimenting ourselves?
Or Fred, if you're reading, perhaps an option to allow API calls to go beyond
a 0-byte and to the end of the string instead?
PB - Registered PureBasic Coder
> Unfortunately, that doesn't work. The API call requires one byte of 0
> separating each part of the string - that's what vbNullChar is.
Oops, I just realised you said vbNullChar, not vbNullString -- no wonder I got
it wrong! Hmm, that definitely makes it harder to solve then... perhaps you
could show us your code so we can try experimenting ourselves?
Or Fred, if you're reading, perhaps an option to allow API calls to go beyond
a 0-byte and to the end of the string instead?
PB - Registered PureBasic Coder
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by freak.
It doesn't seem to work with Arrays directly. What I've been using with API successfully was Arrays inside Structures, so this could work (just an example):
Got the point?
Hope that helps...
Timo
--
A debugged program is one for which you have not yet found the conditions that make it fail.
It doesn't seem to work with Arrays directly. What I've been using with API successfully was Arrays inside Structures, so this could work (just an example):
Code: Select all
; ***********
Structure stringarray ; define Structure
bytes.b[10]
EndStructure
text.stringarray ; create Structure
text\bytes[0] = 65 ; fill in the Charakters
text\bytes[1] = 66
.
.
.
text\bytes[10] = 0
SomeApiCommand_( @text\bytes[0] ) ; call some API command
; *****************
Hope that helps...
Timo
--
A debugged program is one for which you have not yet found the conditions that make it fail.
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
Timo,
I tried your structure suggestion - still no joy!
Thanks for all your help so far.
BTW - I noticed an inconsistency with the array syntax:
When I use just a "plain" byte array, I used parentheses "(" and ")" around the array element, like this: Bytes(0) = 65. When I tried your structure suggestion like this: Text\Bytes(0) = 65, I get a syntax error. Changing the parentheses to brackets "[" and "]" makes it compile correctly.
Fred - is this by design, or is it a bug? Also, can you help me with my original problem, PLEASE????
Thanks again,
Eric
Timo,
I tried your structure suggestion - still no joy!
Thanks for all your help so far.
BTW - I noticed an inconsistency with the array syntax:
When I use just a "plain" byte array, I used parentheses "(" and ")" around the array element, like this: Bytes(0) = 65. When I tried your structure suggestion like this: Text\Bytes(0) = 65, I get a syntax error. Changing the parentheses to brackets "[" and "]" makes it compile correctly.
Fred - is this by design, or is it a bug? Also, can you help me with my original problem, PLEASE????
Thanks again,
Eric
It doesn't seem to work with Arrays directly. What I've been using with API successfully was Arrays inside Structures, so this could work (just an example):Got the point?Code: Select all
; *********** Structure stringarray ; define Structure bytes.b[10] EndStructure text.stringarray ; create Structure text\bytes[0] = 65 ; fill in the Charakters text\bytes[1] = 66 . . . text\bytes[10] = 0 SomeApiCommand_( @text\bytes[0] ) ; call some API command ; *****************
Hope that helps...
Timo
--
A debugged program is one for which you have not yet found the conditions that make it fail.
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by Danilo.
>Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
>& vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
You can do this with memory commands or with
a string with many spaces.
One way with memory:
Hope you get the idea...
The other way would be without allocating memory
and use A$ = space(1000) or so, and follow the
same things i´ve shown above.
Instead of variable "mem" you could use "@A$" with
this method.
Anyway... The AllocateMemory way is fine and shows
exactly whats goin on.
cya,
...Danilo
(registered PureBasic user)
Edited by - Danilo on 19 June 2002 06:27:19
>Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
>& vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
You can do this with memory commands or with
a string with many spaces.
One way with memory:
Code: Select all
mem = AllocateMemory(1,5000,0) ; 5000 bytes should be enough (well, 1000 should be Ok!)
PokeS(mem , "DSN=") ; 4 bytes
x = 4
PokeS(mem+x, DSNName$) ; variable length and vbNullChar is included at the end
x + Len(DSNName$)+1 ; +1 = the NullChar that is needed here
PokeS(mem+x, "Description=") ; 12 bytes
x + 12
PokeS(mem+x, Description$) ; variable length and vbNullChar is included at the end
x + Len(Description$)+1 ; +1 = the NullChar that is needed here
PokeS(mem+x, "DBQ=") ; 4 bytes
x + 4
PokeS(mem+x, Databasename$) ; 1 Nullchar is included at the end
PokeB(mem+x+Len(Databasename$)+1,0) ; the second NullChar at the end
; because this special "string" ends
; with double-NULL
return = SQLConfigDataSource_(hwndParent, fRequest, lpszDriver$, mem)
; call the API (call it with CallFunction() if you opened
the DLL yourself)
The other way would be without allocating memory
and use A$ = space(1000) or so, and follow the
same things i´ve shown above.
Instead of variable "mem" you could use "@A$" with
this method.
Anyway... The AllocateMemory way is fine and shows
exactly whats goin on.
cya,
...Danilo
(registered PureBasic user)
Edited by - Danilo on 19 June 2002 06:27:19
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm
Restored from previous forum. Originally posted by ebs.
Danilo,
Yes - THANK YOU! I put your "poke memory" code into procedures called PutString() and PutStringZero(), and it works!
That's a lot of work to get a string with embedded nulls. I hope Fred considers incorporating something into PureBasic.
Thanks again,
Eric
Danilo,
Yes - THANK YOU! I put your "poke memory" code into procedures called PutString() and PutStringZero(), and it works!
That's a lot of work to get a string with embedded nulls. I hope Fred considers incorporating something into PureBasic.
Thanks again,
Eric
>Attributes = "DSN=" & DSNName & vbNullChar & "Description=" & Description _
>& vbNullChar & "DBQ=" & Databasename & vbNullChar & vbNullChar
You can do this with memory commands or with
a string with many spaces.
One way with memory:Hope you get the idea...Code: Select all
mem = AllocateMemory(1,5000,0) ; 5000 bytes should be enough (well, 1000 should be Ok!) PokeS(mem , "DSN=") ; 4 bytes x = 4 PokeS(mem+x, DSNName$) ; variable length and vbNullChar is included at the end x + Len(DSNName$)+1 ; +1 = the NullChar that is needed here PokeS(mem+x, "Description=") ; 12 bytes x + 12 PokeS(mem+x, Description$) ; variable length and vbNullChar is included at the end x + Len(Description$)+1 ; +1 = the NullChar that is needed here PokeS(mem+x, "DBQ=") ; 4 bytes x + 4 PokeS(mem+x, Databasename$) ; 1 Nullchar is included at the end PokeB(mem+x+Len(Databasename$)+1,0) ; the second NullChar at the end ; because this special "string" ends ; with double-NULL return = SQLConfigDataSource_(hwndParent, fRequest, lpszDriver$, mem) ; call the API (call it with CallFunction() if you opened the DLL yourself)
The other way would be without allocating memory
and use A$ = space(1000) or so, and follow the
same things i´ve shown above.
Instead of variable "mem" you could use "@A$" with
this method.
Anyway... The AllocateMemory way is fine and shows
exactly whats goin on.
cya,
...Danilo
(registered PureBasic user)
Edited by - Danilo on 19 June 2002 06:27:19
-
BackupUser
- PureBasic Guru

- Posts: 16777133
- Joined: Tue Apr 22, 2003 7:42 pm