From: mayayana on
I've got another problem with C string arrays
that I'm hoping someome might shed some light on.
Attempting to create a CAB file with cabinet.dll,
the in parameter for the file list is:

char **var or char *var[]

It turns out that I can successfully send that array
as a null-delimited plain string, or as an array of
UDTs like so:

Type CArr
Ab() as byte
End Type

I start with a string thus:

C:\WINDOWS\Desktop\Up\wed1-31.txt|C:\WINDOWS\Desktop\Up\fri2-2.txt|C:\WINDOW
S\Desktop\Up\sat2-3.txt|C:\WINDOWS\Desktop\Up\sun2-4.txt

I then change the "|" to chr(0) and send it to
my C++ DLL. Using message boxes in my DLL, it
turns out that the first array member is fine. It's
the first file path, as expected. But the second array
member gets chopped just before the file name:

C:\WINDOWS\Desktop\Up\

Very weird. If there's only 1 file I'll successfully get a
CAB produced, but with a second file it fails because
the path is not valid for the 2nd file. The second file path
is chopped even if I check it first thing after receiving the
array in the DLL call!. I figure this must be an obvious thing
I'm overlooking, or maybe something about C++ that I don't
know. Grabbing at straws I tried doubling the "\" to "\\", but
that's not the problem.



From: Jim Mack on
Since there's no obvious reason why that would happen, it'd help if you showed us exactly how you're declaring the function that you send these strings to, and the code that formats the string and sends it along.

For one thing, an array of a UDT containing dynamic byte arrays is not even remotely similar to char *var[] and could never substitute for a single VB string, so I don't think we're getting a clear picture of what's going on.

I take it that your DLL is just a wrapper, and that it's passing the VB arguments along to the underlying CAB DLL? Have you debugged this at that level to see exactly what's getting to the CAB DLL?

--

Jim Mack
MicroDexterity Inc
www.microdexterity.com


mayayana wrote:
> I've got another problem with C string arrays
> that I'm hoping someome might shed some light on.
> Attempting to create a CAB file with cabinet.dll,
> the in parameter for the file list is:
>
> char **var or char *var[]
>
> It turns out that I can successfully send that array
> as a null-delimited plain string, or as an array of
> UDTs like so:
>
> Type CArr
> Ab() as byte
> End Type
>
> I start with a string thus:
>
> C:\WINDOWS\Desktop\Up\wed1-31.txt|C:\WINDOWS\Desktop\Up\fri2-2.txt|C:\WINDOW
> S\Desktop\Up\sat2-3.txt|C:\WINDOWS\Desktop\Up\sun2-4.txt
>
> I then change the "|" to chr(0) and send it to
> my C++ DLL. Using message boxes in my DLL, it
> turns out that the first array member is fine. It's
> the first file path, as expected. But the second array
> member gets chopped just before the file name:
>
> C:\WINDOWS\Desktop\Up\
>
> Very weird. If there's only 1 file I'll successfully get a
> CAB produced, but with a second file it fails because
> the path is not valid for the 2nd file. The second file path
> is chopped even if I check it first thing after receiving the
> array in the DLL call!. I figure this must be an obvious thing
> I'm overlooking, or maybe something about C++ that I don't
> know. Grabbing at straws I tried doubling the "\" to "\\", but
> that's not the problem.
From: mayayana on
Since there's no obvious reason why that would happen, it'd help if you
showed us exactly how you're declaring the function that you send these
strings to, and the code that formats the string and sends it along.

For one thing, an array of a UDT containing dynamic byte arrays is not even
remotely similar to char *var[] and could never substitute for a single VB
string, so I don't think we're getting a clear picture of what's going on.

I take it that your DLL is just a wrapper, and that it's passing the VB
arguments along to the underlying CAB DLL? Have you debugged this at that
level to see exactly what's getting to the CAB DLL?
-------------------------------------------

Yes, it's based on the MS sample from the CAB SDK,
"testfci". I've put in message boxes at various places in
my DLL. As for cabinet.dll, my call is returning 21, which
is my own personal code for a combination of two things:

The call failed with this error:
"Failure opening file to be stored in cabinet"

and it failed during the call to FCIAddFile.

Sorry about the volume of code here. It's awkward
because there's quite a bit interconnected.

Much of the code in this function is not relevant, but I'm
including it for thoroughness. This is what VB calls:

-----------------------------------------------------------
int WINAPI MakeCAB(LPSTR sCABFileName, LPSTR sDestFolder, int iNumFiles,
char **afiles)

{
int i;

i = strlen(sDestFolder);
if ((i > 255) || (i < 3))
{
return 1; // 1 - invalid cab destination path.
}
i = strlen(sCABFileName);
if (i < 5)
{
return 2; // 2 - invalid cab name. (Doesn't check for extension
validity.)
}

if (iNumFiles < 1)
{
return 3; // 3 - no files.
}

strcpy(sCABFol, sDestFolder);
strcpy(sCABName, sCABFileName);

MessageBox(NULL, afiles[1], "2nd file path", MB_OK | MB_ICONINFORMATION);

// Strange thing here: this message box never shows.

MessageBox(NULL, afiles[2], "3rd file path", MB_OK | MB_ICONINFORMATION);

if (test_fci(iNumFiles, &afiles[0]) == TRUE)
return 0;
else
return LRet; // LRet is a global.
}

-------------------------------------------------------

that function calls this:

BOOL test_fci(int num_files, char *file_list[])
{
HFCI hfci;
ERF erf;
CCAB cab_parameters;
int i;
client_state cs;

/*
* Initialise our internal state
*/
cs.total_compressed_size = 0;
cs.total_uncompressed_size = 0;

set_cab_parameters(&cab_parameters);

hfci = FCICreate(
&erf,
file_placed,
mem_alloc,
mem_free,
fci_open,
fci_read,
fci_write,
fci_close,
fci_seek,
fci_delete,
get_temp_file,
&cab_parameters,
&cs
);


if (hfci == NULL)
{
LRet = (erf.erfOper + 10);
return FALSE;
}


// for each file in array...
for (i = 0; i < num_files; i++)
{

char stripped_name[256];
char spath[256];

strcpy(spath, file_list[i]);
/*
* Don't store the path name in the cabinet file!
*/
strip_path(spath, stripped_name); // strip off path.

// this message box will return correctly for first index,
// but for second index it returns "" for stripped_name
// and only folder path for file_list[i]

MessageBox(NULL, file_list[i], stripped_name, MB_OK |
MB_ICONINFORMATION);

if (FALSE == FCIAddFile(
hfci,
file_list[i], /* file to add */
stripped_name, /* file name in cabinet file */
FALSE, /* file is not executable */
get_next_cabinet,
progress,
get_open_info,
tcompTYPE_MSZIP))
{

(void) FCIDestroy(hfci);
LRet = (erf.erfOper + 20);
return FALSE;
}
}
--------------------------------------------------
.....etc..... The spath variable is not necessary, but
I added it in just to make sure that the strip_path
sub was not somehow affecting the next iteration.
strip_path takes a path string and returns the file name
in the 2nd parameter.
------------------------------------------------


On the VB side, the following is my current
code, which seems to clip the file name on the
second array member. The sList string is exactly as
I posted it earlier - 4 file names.
(With the array of UDTs: I'm not sure what I was
thinking about that. I tried that method but it didn't
work.)

Private Declare Function MakeCAB Lib "jcabmake.dll" (ByVal sCABFileName As
String, ByVal sDestFolder As String, ByVal iNumFiles As Long, AFileList As
String) As Long


Private sList As String

Private Sub Command1_Click()
Dim LNum As Long

sList = Text4.Text
A1 = Split(sList, "|")
LNum = UBound(A1) + 1

sList = Replace(sList, "|", Chr(0))
sList = sList & Chr(0)

'-- sName and sDest here are file name and
'-- destination folder. That all works OK.

LRet = MakeCAB(sName, sDest, LNum, sList)
End Sub.


From: mayayana on
Footnote:

I had said before that I had an array of byte arrays
working. I had that mixed up. What worked was
this:

'-- using a string array instead of a null-delimited string.

A1 = Split(sList, "|")
LNum = UBound(A1) + 1

'-- sList = Replace(sList, "|", Chr(0))
'-- sList = sList & Chr(0)


ReDim AAsc(LNum) As String
For i2 = 0 To LNum - 1
AAsc(i2) = A1(i2)
Next
AAsc(LNum) = vbNullChar

'-- LRet = MakeCAB(sName, sDest, LNum, sList)

'-- AAsc is an array declared as String and the MakeCAB last
'-- parameter is declared as Any in that case. I thought that was
"-- interesting: The C++
'-- side is getting an array of c string pointers, which makes
'-- sense. But what surprises me is that it somehow receives
'-- a null-delimited string in the same way. Even though the former
'-- is an array of string pointers (pointer to pointer) while
'-- the latter is a pointer to a string, both have the exact same result,
'-- with array(0) getting through as a file path while array(1)
'-- gets through as the parent folder path.

LRet = MakeCAB(sName, sDest, LNum, AAsc(0))



From: Jim Mack on
mayayana wrote:

I didn't have time to look at your previous, but until I do, you may recall what I said earlier: you might think that just passing element 0 of a string array would work, but it doesn't -- you'll get the first string and that's all. Anything else is a coincidence.

The only thing that will reliably work is building your own null-terminated string of null-terminated strings.

--
Jim


> I had said before that I had an array of byte arrays
> working. I had that mixed up. What worked was
> this:
>
> '-- using a string array instead of a null-delimited string.
>
> A1 = Split(sList, "|")
> LNum = UBound(A1) + 1
>
> '-- sList = Replace(sList, "|", Chr(0))
> '-- sList = sList & Chr(0)
>
>
> ReDim AAsc(LNum) As String
> For i2 = 0 To LNum - 1
> AAsc(i2) = A1(i2)
> Next
> AAsc(LNum) = vbNullChar
>
> '-- LRet = MakeCAB(sName, sDest, LNum, sList)
>
> '-- AAsc is an array declared as String and the MakeCAB last
> '-- parameter is declared as Any in that case. I thought that was
> "-- interesting: The C++
> '-- side is getting an array of c string pointers, which makes
> '-- sense. But what surprises me is that it somehow receives
> '-- a null-delimited string in the same way. Even though the former
> '-- is an array of string pointers (pointer to pointer) while
> '-- the latter is a pointer to a string, both have the exact same
> result, '-- with array(0) getting through as a file path while
> array(1) '-- gets through as the parent folder path.
>
> LRet = MakeCAB(sName, sDest, LNum, AAsc(0))
 |  Next  |  Last
Pages: 1 2 3 4
Prev: VB6 vs DirectX
Next: VB6 - Vista - Mouse wheel