From: J French on
On Thu, 08 Feb 2007 20:08:45 GMT, "mayayana"
<mayayana1a(a)mindspring.com> 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\

This is ringing bells, I wonder whether the author of the DLL is
expecting the first entry to contain the full path and file name and
subsequent entries to consist of just the pathless file name

The lpstrFile of the OPENFILENAME structure returns

<quote>
Pointer to a buffer that contains a filename used to initialize the
File Name edit control. The first character of this buffer must be
NULL if initialization is not necessary. When the GetOpenFileName or
GetSaveFileName function returns successfully, this buffer contains
the drive designator, path, filename, and extension of the selected
file.
If the OFN_ALLOWMULTISELECT flag is set and the user selects multiple
files, the buffer contains the current directory followed by the
filenames of the selected files.
</quote>

It is possible that the DLL is designed to receive input directly from
a buffer filled in by GetOpenFileName.

Just a thought ...
From: Jim Mack on
mayayana wrote:

> including it for thoroughness. This is what VB calls:
>
> -----------------------------------------------------------
> int WINAPI MakeCAB(LPSTR sCABFileName, LPSTR sDestFolder, int
> iNumFiles, char **afiles)


Here's where my knowledge of C falls over, so this may be wrong information: It seems to me that you're treating **char and *char[] as exactly equivalent, and that probably isn't true.

It's a bad idea to use MessageBox to debug, since the message box will only display up to the first NULL in any case -- even if you passed it the entire input string array, it would only show you the first string. Better to run this under a debugger and trace execution through the name-stripping code, etc.

In any case, what you're doing in VB is correct, so I think this now has to move to a C group.

--
Jim



> {
> 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

> This is ringing bells, I wonder whether the author of the DLL is
> expecting the first entry to contain the full path and file name and
> subsequent entries to consist of just the pathless file name
>

I guess that's possible. The cabinet.dll
operation expects a full path, but the code
is adapted from an MS command line sample.
In that case, the command line comes through
as:
testprogram.exe
file1.txt
file2.txt
.....etc...

And the MS sample code starts reading at array(1).

It may be that the sample program is just
setting current directory and sending file
names. That's odd, though, because the
cabinet.dll docs specifically say that the
FCIAddFile parameter should be a full path.
That would also mean that all of the CAB files
have to be in the same folder.
And that still doesn't explain why my path
is actually coming through chopped, before
it even gets to the cabinet.dll ops.

Anyway, thanks. Maybe I'll experiment with
building the path on the DLL side.



From: mayayana on

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


Here's where my knowledge of C falls over, so this may be wrong information:
It seems to me that you're treating **char and *char[] as exactly
equivalent, and that probably isn't true.

-----------

Thanks for the effort, anyway. On the declare, I actually
read in one place that char **var and char *[] are the same
thing - a matter of taste. And they do seem to work the
same way.

I'm still not entirely clear about the char type variations,
but there's obviously something I'm not getting. I get
the exact same partial result with a null-delimited string
as I do with a string array, and the way I figure it, a null-
delimited string is a char multi-dimensional array that's
lacking an accurate declaration. (like: var [4] [256] )

The array of strings seems like it *should* be right,
because I declare the array as string, so I'm passing
a pointer to char array pointers (once VB gets through
converting the string). But the C++ side is happy to
half-digest anything, it seems.

> In any case, what you're doing in VB is correct, so I think
> this now has to move to a C group.

I suspect they'd only sniff at me haughtily there.
I might just as well ask for kind help in a Linux group. :)


From: Ralph on

"mayayana" <mayayana1a(a)mindspring.com> wrote in message
news:d10zh.74$Jl.28(a)newsread3.news.pas.earthlink.net...
>
> > -----------------------------------------------------------
> > int WINAPI MakeCAB(LPSTR sCABFileName, LPSTR sDestFolder, int
> > iNumFiles, char **afiles)
>
>
> Here's where my knowledge of C falls over, so this may be wrong
information:
> It seems to me that you're treating **char and *char[] as exactly
> equivalent, and that probably isn't true.
>
> -----------
>
> Thanks for the effort, anyway. On the declare, I actually
> read in one place that char **var and char *[] are the same
> thing - a matter of taste. And they do seem to work the
> same way.
>
> I'm still not entirely clear about the char type variations,
> but there's obviously something I'm not getting. I get
> the exact same partial result with a null-delimited string
> as I do with a string array, and the way I figure it, a null-
> delimited string is a char multi-dimensional array that's
> lacking an accurate declaration. (like: var [4] [256] )
>
> The array of strings seems like it *should* be right,
> because I declare the array as string, so I'm passing
> a pointer to char array pointers (once VB gets through
> converting the string). But the C++ side is happy to
> half-digest anything, it seems.
>
> > In any case, what you're doing in VB is correct, so I think
> > this now has to move to a C group.
>
> I suspect they'd only sniff at me haughtily there.
> I might just as well ask for kind help in a Linux group. :)
>

**var and *var[], ( and var[][] for completness )are functionally equivalent
in a declaration, as ...

*var == &var[0], thus *var == var

Or to muddy the waters even further ...
char var[i] == *(var + (sizeof (char) * i))
thus
var[i][j] == *(var[i] + (sizeof(char) + j)), or
*( *(var + (sizeof(char) * i)) + (sizeof(char) * j))

It is just instructions to the compiler on how to stomp around on the
buffer.

Whenever strings appear to be mysteriously 'chopped' in C it is most often
caused by embedded nuls.

-ralph







First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: VB6 vs DirectX
Next: VB6 - Vista - Mouse wheel