Instantiate a wcx64 dll

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: sheep, Hacker, Stefan2, white

Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Instantiate a wcx64 dll

Post by *Hurdet »

I am trying to instantiate a wcx64 dll from a c++ command line.

Code: Select all

static wchar_t packedFile[MAX_PATH] = L"";
static wchar_t srcPath[MAX_PATH] = L".\\";
static wchar_t subPath[MAX_PATH] = L".\\";
static wchar_t addList[MAX_PATH] = L".\\";
std::wcsncpy(packedFile, L"c:\\packed.7z", MAX_PATH);
//std::wcsncpy(subPath, L"c:", MAX_PATH);
std::wcsncpy(srcPath, L"c:", MAX_PATH);
std::wcsncpy(addList, L"list.txt", MAX_PATH);
int ret = PackFilesW(packedFile, NULL, srcPath, addList, flags);
I get only a 32 byte long "packed.7z.tmp" header.
i suspect addList is wrong.
how do i instantiate correctly?
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

EDIT: In the orignal version of my post, i wrote about zero-terminated strings with a zero byte being the zero/NUL terminator. Considering we are dealing with wchar_t here, this is entirely incorrect. Instead of "zero byte", i should have more accurately said "NUL character" (because one NUL character in wchar_t type is actually two zero bytes in itself, not just a single zero byte).



First, check the return value of the function. It should hopefully give you some clues about the problem.

Aside from that, i see at least two problems with your code (each of which might or might not contribute to the issue you are having).

1. Pay attention to the documentation in the wcx / packer plug-in guide, especially what it says about the AddList parameter. Note that AddList is a list of file names. It is not just a single zero/NUL-terminated string, but a sequence of zero/NUL-terminated strings, with the end of the list indicated by an additional NUL character. In other words, the AddList parameter needs to end with two NUL characters, not just with a single NUL character. Simply using string copy functions like you did will _only_ make sure that a single NUL character is terminating the AddList parameter. Unless you fully initialize the array used for addList with zero bytes / NUL characters, you will have to "manually" add the second, final NUL character to the addList parameter. (You might also have had pure luck during your tries and debugging session where the array was always filled with zero bytes no matter what, and there is still another cause for your problem somewhere. But hey, do you like to rely on chance in your programming endeavors?)

Fortunately, initializing this array fully with zero bytes / NUL characters is rather easy. I don't know why you are trying to initialize the arrays with ".\", but this does not enforce the rest of the array being fully zero-byte initialized (all array positions behind the ".\" with NUL character could remain uninitialized or initialized with a byte pattern different from NUL charactgers, depending on compiler and/or C++ runtime behavior, and other system/environmental factors). Unless you are using a compiler from the iron age, try to initialize it like this (empty-bracket aggregate initializer):

Code: Select all

static wchar_t addList[MAX_PATH] = { };

2. I assume the full path of the file you are trying to pack is "C:\list.txt", and i am not sure using "C:" instead of "C:\" for SrcPath will work reliably. "C:" normally does NOT specify the root directory of C:. It specifies the current working directory last active for this drive with respect to the current process (which may or may not happen to be the root directory). But how this parameter is actually processed and interpreted here probably depends to a great deal on the packer plug-in itself, so it might or it might not be a problem with the specific packer-plugin you are testing with. But all bets are off how other packer plug-ins (or a different version of the same packer plug-in) will treat a srcPath like "C:"...
Last edited by elgonzo on 2020-09-05, 14:40 UTC, edited 3 times in total.
Windows 7 Pro x64 SP1
User avatar
petermad
Power Member
Power Member
Posts: 9848
Joined: 2003-02-05, 20:24 UTC
Location: Valsted, Denmark
Contact:

Re: Instantiate a wcx64 dll

Post by *petermad »

This topic should be moved to Plugins and addons: devel.+support (English)

.
License #524 (1994)
Danish Total Commander Translator
TC 9.51 32+64bit on Win XP 32bit & Win 7, 8.1 & 10 (2004) 64bit, 'Everything' 1.4.1.992 (x64)
TC 3.10 on Android 6.0
Get:
Extended TC Menus | TC Languagebar | TC Dark Help | PHSM-Calendar
User avatar
Hacker
Moderator
Moderator
Posts: 11822
Joined: 2003-02-06, 14:56 UTC
Location: Bratislava, Slovakia

Re: Instantiate a wcx64 dll

Post by *Hacker »

Message from moderator Hacker

Moved to the Plugins forum.
Mal angenommen, du drückst Strg+F, wählst die FTP-Verbindung (mit gespeichertem Passwort), klickst aber nicht auf Verbinden, sondern fällst tot um.
Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Re: Instantiate a wcx64 dll

Post by *Hurdet »

I have tryed to update script.
It not catch error but in debug stop: "0xC0000005: Access violation executing location ".
If use PackFiles instead of PackFilesW, PackFiles return 0 but not pack nothing.

Code: Select all

int main()
{
	TCHAR dll[MAX_PATH];
	ExpandEnvironmentStrings(L"%WinDir%\\Test.wcx64", dll, MAX_PATH - 1);
	typedef WINBASEAPI int WINAPI _PackFilesW(wchar_t* packedFile, wchar_t* subPath, wchar_t* srcPath, wchar_t* addList, int flags);
	static _PackFilesW* PackFilesW;
	if (PackFilesW == NULL) {
		HMODULE hDLL = LoadLibrary(dll);//fn
		if (hDLL) {
			PackFilesW = (_PackFilesW*)GetProcAddress(hDLL, "PackFilesW");
		}
	}
    static wchar_t packedFile[MAX_PATH] = { };
    static wchar_t srcPath[MAX_PATH] = { };
    static wchar_t subPath[MAX_PATH] = { };
    static wchar_t addList[MAX_PATH] = { };
	int flags = 2;
	static wchar_t aaa[MAX_PATH] = L"list.txt\r\nlist2.txt\r\n";
	int n, p = 0;
	int l = std::wcslen(aaa);
	for (n = 0; n < l;n++) {
		if (aaa[n] == '\r' && aaa[n+1] == '\n') {
			addList[p] = 0;
			n++;
		}
		else if (aaa[n] == '\n') {
			addList[p] = 0;
		}
		else {
			addList[p] = aaa[n];
		}
		p++;
	}
	addList[p] = 0;
	//std::wcsncpy(addList, L"list.txt\0x0list2.txt\0x0\0x0", MAX_PATH);
	printf("%ls %d %d\n", addList, std::wcslen(addList), std::wcslen(aaa));
	std::wcsncpy(packedFile, L"K:\\packed.7z", MAX_PATH);
	std::wcsncpy(subPath, L"SubDir", MAX_PATH);
	std::wcsncpy(srcPath, L"k:\\", MAX_PATH);
	int ret=0;
	std::cout << "Packing...\n";
	try{
		ret = PackFilesW(packedFile, subPath, srcPath, addList, flags);
	}
	catch (int e) {
		printf("catch %d\n", e);
	}
	printf("Error %d\n", ret);
	std::cout << "Packed!\n";
}
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

Explicitly initialize the _PackFilesW variable.
You currently use it uninitialized. Unless some authorative documentation says it is automatically initialized to NULL, treat it as uninitialized with no guarantee that it is auto-initialized to NULL and initialize it explicitly. (As a side note, the test for _PackFiles being NULL makes no sense at least here in your given code, because obviously the function pointer can not be valid already right there at the beginning of the code before loading the actual DLL.)

But anyways, I have tested your code as-is with Total7zip.wcx64, and the code runs just fine and the 7z archive is created. This indicates to me that the access violation you get is a bug within that Test.wcx64 you are using. Well, it could also mean the DLL failed to load with the function pointer _PackFilesW remaining NULL, but being able to execute PackFiles without an access violation contradicts this theory unless you are changing your code functionally between the tests. (at which point it would become pointless for me to speculate about the problem, as i have no insight in how exactly the changed code looked like for every test you tried.)

Also, PackFiles returning 0 despite apparently not doing anything is a further indication that this mysterious Test.wcx64 is likely broken. Whether the cause of the problem is environmental or is just plain broken plug-in code, i have unfortunately no idea. (With "environmental" i mean things external to the plug-in but which the plug-in code might rely upon. A -random- example would be the plug-in code needing a certain current working directory for loading some resources, but the current working directory is not what the plug-in expects when your code calls into it. Again, that's just a random example. There is so far no indication whether the real problem/bug is actually related to this example or not...)


If Test.wcx64 is a known and publicly available packer plug-in, it could perhaps help if you tell the name and version of the plug-in you are experimenting with. (If on the other hand it is a plug-in you are writing yourself, nothing stops you from debugging the plug-in code and see where the access violation happens and why PackFiles doesn't do anything.)



By the way, i have to make a correction to my first post. I didn't really pay that much attention and did not notice you are using wcsncpy with MAX_PATH as "count" argument. This will actually ensure that the array/buffer area behind the string will be filled with NUL characters (up to the array position indicated by "count", which in your case here spans the whole array). My apologies for this oversight.

That said, note that wcsncpy (and other string functions with "n" in their name) is considered unsafe. If you are to happen to have a string that is longer than the "count" argument, the copied string will NOT possess a zero terminator, possibly causing trouble when other pieces of code want to work with the copied string. It is not an issue with your current code here as all strings involved are far shorter than MAX_PATH, but worth to keep in mind when you further develop your code.
Windows 7 Pro x64 SP1
Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Re: Instantiate a wcx64 dll

Post by *Hurdet »

To Explicitly initialize the _PackFilesW variable I have to do?
static pPackFiles PackFilesW = NULL;
in this way VS it no longer marks how uninitialized;

I would to use the static for function [not main()] that initialize only the first time.

I'm testing this.
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

Hurdet wrote:
2020-09-05, 17:40 UTC
I'm testing this.
Which version precisely?
Windows 7 Pro x64 SP1
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

I have just tested your example code with version 0.7.6.6 available on totalcmd.net, and PackFilesW works flawlessy with it.
If you are using a different version, give 0.7.6.6 a try.
Last edited by elgonzo on 2020-09-05, 17:54 UTC, edited 2 times in total.
Windows 7 Pro x64 SP1
Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Re: Instantiate a wcx64 dll

Post by *Hurdet »

The most recent: wcx_7zip_0.8.0.0alpha
x64 version.
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

Then give version 0.7.6.6 a try. It worked fine for me (at least with regard to PackFilesW).

If the problem still persists even with 0.7.6.6, perhaps try not to put the plug-in into a previleged Windows folder, but rather put it into an ordinary non-previleged directory of your choice. I don't really expect it to be the reason for your problems, but who knows... And it is easy to attempt this, so why not try it...
Windows 7 Pro x64 SP1
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

By the way, 0.8.0.0 also crashes for me.
Which kinda is not surprising because it is an alpha version

Solution: Don't use alpha versions. There is always a high chance of them containing serious bugs. That's why the developers mark them as alpha versions...
Windows 7 Pro x64 SP1
Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Re: Instantiate a wcx64 dll

Post by *Hurdet »

I tested 0.7.6.6.bin work but pack only first file of two.
Then i have compiled 0.7.6.6.src and not work the same way as before.
Also 0.8.0.0alpha.bin original not work the same way as before.
User avatar
elgonzo
Power Member
Power Member
Posts: 570
Joined: 2013-09-04, 14:07 UTC

Re: Instantiate a wcx64 dll

Post by *elgonzo »

Hurdet wrote:
2020-09-05, 18:04 UTC
I tested 0.7.6.6.bin work but pack only first file of two.
Using your full example code from above with 0.7.6.6, both list.txt and list2.txt are packed. I cannot reproduce your problem, unfortunately.
Whatever the problem, it is not with the example code you posted above, and it is not with plug-in version 0.7.6.6.
Windows 7 Pro x64 SP1
Hurdet
Power Member
Power Member
Posts: 542
Joined: 2003-05-10, 18:02 UTC

Re: Instantiate a wcx64 dll

Post by *Hurdet »

You're right, I had changed the code a bit, but restoring the posted one works with two files to me too.
it is strange that the recompiled code of the same version no longer works.
Thanks for everything!
Post Reply