CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 28 of 28
  1. #16
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    How did you create the crypto.dll? cryptopp version 5.6.1.0 is available from Wei Dai's home page as a set of source files to be compiled to produce a .dll. Using their standard build produces cryptopp.dll and cryptopp.lib files. If you have (or can make) the .lib file why are you bothering using LoadLibrary etc when you could just link with the .lib file and include the .h file with your program? This would be my preferred way of doing it when these files are available.

    However, as the source of the dll is available then if you build a debug version then you can use the debugger to debug into the dll when dllmain(..) is called to find the problem.

    Code:

    int code = (decryptAddress)((char *) pswd, (char *) out, (char*)key);

    This is not the usual way that a C++ (or C) programmer calls a function. Why are there parentheses around the name of the function?
    Because decryptAddress is variable containing a pointer to a function and not a function name. It could have been written

    Code:
    int code = (*decryptAddress)((char *) pswd, (char *) out, (char*)key);
    but the '*' is now optional.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  2. #17
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    I tried your suggestion with the dwFlags DONT_RESOLVE_DLL_REFERENCES and even that didn’t work. It didn’t give me error 183 this time while loading the crypto.dll. As per my log file, it even got the address for the decrypt function as well,
    This means that the problem is probably within dllmain() as DONT_RESOLVE_DLL_REFERENCES means that dllmain() isn't called for process and thread initialisation. However, it also means that the system does not load additional executable modules that are referenced by crypto.dll - so the problem could be with loading a module used by cryto.dll and not with crypto.dll itself. What modules does crypto.dll use? According to the dll.h file, it needs msvcrt.dll loaded BEFORE crypto.dll is loaded as dllmain() uses malloc and free. As an expt, try doing LoadLibrary("msvcrt") before LoadLibrary("crypto") and see what happens. This may explain why it works under eclipse and not under jar if eclipse already has mscvrt.dll loaded and jar hasn't????
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #18
    Join Date
    Apr 1999
    Posts
    27,449

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Quote Originally Posted by 2kaud View Post
    Because decryptAddress is variable containing a pointer to a function and not a function name. It could have been written

    Code:
    int code = (*decryptAddress)((char *) pswd, (char *) out, (char*)key);
    I know this, and your method is the second way of doing this, but none of that is necessary, even if the variable is a function pointer. You can call the function as if it is a regular function.
    Code:
    decryptAddress((char *) pswd, (char *) out, (char*)key);
    But it is the casting that is suspicious. Whenever I see that, it raises red flags as it was placed there either due to inexperience of the programmer (not really serious), or more seriously, the programmer is (unwittingly) trying to outsmart the compiler by masking a serious compiler error or warning concerning differing types.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 17th, 2013 at 08:08 PM.

  4. #19
    Join Date
    Apr 2013
    Posts
    10

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    I tried out the sample program as per your suggestion in post #12. Below is the code:

    Code:
    void main(int argc, TCHAR * argv[])
    {	
    	
    	HINSTANCE myCrypto = (HINSTANCE)NULL;
    		myCrypto = LoadLibrary("crypto");		
    		if(myCrypto == NULL )
    		{
    			printf("bad ret: %i\n", GetLastError());			
    		} 
    		else 
    		{
    			puts("ok");
    		};
    
    }
    On executing it, I got result as
    bad ret: 183

    I then added one more printf statement in the if block to get the value of HINSTANCE
    Code:
    if(myCrypto == NULL )
    {
    	printf("myCrypto: %d\n",(int)myCrypto);
                 printf("bad ret: %i\n", GetLastError());			
    }
    On executing it, I got the results
    myCrypto: 0
    bad ret: 183

    ================
    I then tried out loading the msvcrt dll before loading crypto

    Code:
    void main(int argc, TCHAR * argv[])
    {	
    	HINSTANCE hi = (HINSTANCE)NULL;
    	HINSTANCE myCrypto = (HINSTANCE)NULL;
    
    	hi = LoadLibrary("msvcrt"); 
    	if(hi == NULL )
    	{
    		printf("hi: %d\n",(int)hi);
    		printf("bad ret: %i\n", GetLastError());			
    	} 
    	else
    	{
    		puts("ok");
    		printf("hi: %d\n",(int)hi);
    	}
    
    		myCrypto = LoadLibrary("crypto");		
    		if(myCrypto == NULL )
    		{
    			printf("myCrypto: %d\n",(int)myCrypto);
    			printf("bad ret: %i\n", GetLastError());			
    		} 
    		else 
    		{
    			puts("ok");
    			printf("myCrypto: %d\n",(int)myCrypto);
    		}
    }
    and got the result as
    ok
    hi: 2009137152
    myCrypto: 0
    bad ret: 183


    So the msvcrt.dll is loaded successfully, where as it still failed to load crypto.dll.
    ================

    This Cryptowrapper is a CPP program compiled with Visual Studio 2010 to generate the cryptowrapper.dll.

    ================

    Yes you are right, after compiling the set of files from Wei dai the cryptopp.dll and cryptopp.lib files were created. Which are then referred into the crypto program. I am not really sure why this was done in this particular manner, but its how it has been over a period of time.

    Cryptowrapper calling crypto which in turn uses cryptopp. This used to work fine till now with Java1 program. Now we have introduced Java2 program and with this we are getting the issue with Cryptowrapper failing to Load crypto dll. Pls not ethat Java1 program is still able to function successfully on the same machines where Java2 is failing.

    ================

    In decryptAddress((char *) pswd, (char *) out, (char*)key);

    The parameters pswd and key are passed from Java program, so the value initially comes as jstring and are then converted to char cons * type and then passed to the decryptAddress function. Similary the out var defined as char * is later converted to jstring and returned back to Java program.

    ================

    For debugging – After the Java program is kicked off, I attach it to the CryptoWrapper program using ‘Attach to the Process’ and I am able to debug the program.

    Thanks..
    Last edited by RituP; April 18th, 2013 at 12:06 AM.

  5. #20
    Join Date
    Apr 2013
    Posts
    3

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Share Your very useful and intelligent individuals.
    Ming Thank you much.
    I'll read carefully easier to understand.
    Chia se cua ban rat hay va huu ich voi ca nhan minh.
    Minh cam on ban nhieu.
    Minh se doc ky de hieu hon.
    Tran trong

  6. #21
    Join Date
    Apr 1999
    Posts
    27,449

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Quote Originally Posted by RituP View Post
    I tried out the sample program as per your suggestion in post #12. Below is the code:

    Code:
    void main(int argc, TCHAR * argv[])
    {	
    	
    	HINSTANCE myCrypto = (HINSTANCE)NULL;
    		myCrypto = LoadLibrary("crypto");		
    		if(myCrypto == NULL )
    		{
    			printf("bad ret: %i\n", GetLastError());			
    		} 
    		else 
    		{
    			puts("ok");
    		};
    
    }
    On executing it, I got result as
    bad ret: 183

    I then added one more printf statement in the if block to get the value of HINSTANCE
    Code:
    if(myCrypto == NULL )
    {
    	printf("myCrypto: %d\n",(int)myCrypto);
                 printf("bad ret: %i\n", GetLastError());			
    }
    On executing it, I got the results
    myCrypto: 0
    bad ret: 183
    Then you should concentrate on getting this to return a valid instance handle.

    First, you didn't place the full path of the module to load. By not putting the full path, you are now at the mercy of the Windows OS search logic when finding modules. See here:

    http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

    That's why I mentioned earlier about possibly other modules that are named the same but just happen to be loaded (or attempted to be loaded) by the Windows OS. If you have more than one crypto.dll or other dependent module floating around on your computer with the same name, by using a relative name in the LoadLibrary() call, the library that is loaded is no longer under your control.
    In decryptAddress((char *) pswd, (char *) out, (char*)key);

    The parameters pswd and key are passed from Java program, so the value initially comes as jstring and are then converted to char cons * type and then passed to the decryptAddress function.
    You didn't really answer the question as to what happens if you leave out those casts.

    The compiler is not being stupid or annoying when it gives you the errors that you're now masking. If the function wants a char*, then it is possible that the function can attempt to change what that char* points to. Passing a const char* to a function that takes a char* is inviting disaster. There is a big difference between a function that wants a const char* and one that wants a char*. The former is guaranteeing that what the argument is pointing to can't be changed, while the latter makes no such guarantee.
    Similary the out var defined as char *
    No, I asked where does it get initialized. A char* by itself means nothing. Where does it point to? Where does the buffer it must point to come from? You can't just declare a char* and pass it to the C++ function that expects it to point to a buffer.

    Regards,

    Paul McKenzie

  7. #22
    Join Date
    Apr 2013
    Posts
    10

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    In my sample code, if I try to hardcode the full path (along with the dll name) for crypto. I have removed all the instances of the crypto, cryptowrapper and cryptopp dlls from this machine. Just one copy is maintained in C:\ drive and I am referring to that in my code.

    Code:
    void main(int argc, TCHAR * argv[])
    {	
    	HINSTANCE myCrypto = (HINSTANCE)NULL;
                 myCrypto = LoadLibrary("C:\\crypto.dll");	
    
    	if(myCrypto == NULL )
    		{
    		  	printf("myCrypto: %d\n",(int)myCrypto);
    			printf("bad ret: %i\n", GetLastError());			
    		} 
    		else 
    		{
    			puts("ok");
    			printf("myCrypto: %d\n",(int)myCrypto);			 
    		}
    }
    On executing this code, it prompted an error message box titled ‘Unable to Locate Component’ with text as – ‘This application has failed to start because cryptopp.dll was not found. Re-installing the application may fix this problem.’

    On clicking OK button on that message box I got the result as
    myCrypto: 0
    bad ret: 183


    But I do have the cryptopp.dll along with crypto dll in the C:\ drive, so why is it not able to find it. I tried to register the crytoppp.dll placed in C:\ drive using regsvr32 and got this message:

    'C:\cryptopp.dll was loaded, but the DllUnregisterServer entry point was not found. The file can not be registered.'


    I tried moving both the dlls (crypto and cryptopp) to its original location and then in the code provided the same path to Loadlibrary, but then also I got the same error message ‘Unable to Locate Component’ .

    ============
    Here’s the original code that does the casting for pswd and key. The variables thePassword and theKey are jstrings. I am relatively new to this code, so it’s taking me some time to understand, sorry for the delay..

    Code:
    char const *pswd = env->GetStringUTFChars(thePassword, 0);		
    char  const *key = env->GetStringUTFChars(theKey, 0);
    int length =strlen(key);
    length=int((7+length)/8)*8;
    char* out = (char*) malloc(sizeof(char)*length+1);
    memset(out, ' ', length);
    out[length] = 0;
    int code = (decryptAddress)((char *) pswd, (char *) out, (char*)key);
    jstring result = env->NewStringUTF(out);
    The return type for GetStringUTFChars()defined in jni.h is const char* and as the pswd and key values are not to be changed I thought it was ok if its defined as const char*.

    ==========
    Further the decrypt function in crypto is defined as

    Code:
    int __declspec( dllexport )  __stdcall decrypt(char *in, char *out, char *systemKey)
    So its expecting arguments of char * type.


    Thanks…

  8. #23
    Join Date
    Apr 1999
    Posts
    27,449

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Quote Originally Posted by RituP View Post
    I tried to register the crytoppp.dll placed in C:\ drive using regsvr32 and got this message:

    'C:\cryptopp.dll was loaded, but the DllUnregisterServer entry point was not found. The file can not be registered.'
    That is because the DLL is not a COM DLL. It is a garden variety, non-COM, Windows DLL -- you don't use regsrvr32.exe on such DLL's.
    Here’s the original code that does the casting for pswd and key. The variables thePassword and theKey are jstrings.
    The term "jstring" doesn't really mean anything in a C++ forum, unless you tell us exactly, in C++ terms, what a "jstring" is an alias for.
    Further the decrypt function in crypto is defined as
    Code:
    int __declspec( dllexport )  __stdcall decrypt(char *in, char *out, char *systemKey)
    So its expecting arguments of char * type.
    So why are you passing const char* types to this function? If I wrote a function that expects a pointer to an Animal, you can cast a pointer to a Toaster to a pointer to Animal. Does it make it right? No.

    Again, what were the compiler errors if you didn't cast? Those errors/warnings really do mean something, and should not be masked by applying inappropriate casts as you're doing now.

    If a function wants a char*, it is by convention that the function has full rights in changing the information being pointed to by that char*. So if you really give it a const char* instead, you are risking undefined behaviour and possible crashes when you give this function an unchangeable (that's why it's const char *) string.

    Casting a const char* to a char* changes nothing. All it does, again, is shut the compiler up about the compilation error you're code is producing.

    You should actually give the function a writeable char buffer for the password. That is the only way to guarantee that nothing goes wrong. In other words, there is no need to cast anything if you send the function the correct types.

    Regards,

    Paul McKenzie

  9. #24
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Try first to LoadLibrary "msvcrt", then LoadLibrary "cryptocpp.dll" (using full path) and then LoadLibrary "crypto.dll" (using full path). I tried to load cryptocpp.dll on my computer and I got an error until I loaded msvcrt first.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #25
    Join Date
    Apr 2013
    Posts
    10

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    @ 2kaud - wow!...this worked!
    Tried out your suggestion -try first to LoadLibrary "msvcrt", then LoadLibrary "cryptocpp.dll" (using full path) and then LoadLibrary "crypto.dll" (using full path). And it worked. I have to revert back to my original code and then add this piece of code and test it again. But I am sure now it will work. I just wanted to let you guys know that something did work out. Will keep you updated how it goes with my actual code and running it with Java2 program.

    @Paul McKenzie

    In jni.h you have jstring defined as

    Code:
    class _jstring : public _jobject {};
    typedef _jstring *jstring;
    The following link helped me to figure out few things about JNI and C++
    http://journals.ecs.soton.ac.uk/java...nting/cpp.html


    The jni.h is included in this Cryptowrapper program.
    ============
    If I dont cast the parameters in decryptAddress function

    Code:
    decryptAddress(pswd,  out, key);
    it gives me this error - error C2664: 'int (char *,char *,char *)' : cannot convert parameter 3 from 'const char *' to 'char *'


    I am not sure how we can achieve this in our scenario– ‘there is no need to cast anything if you send the function the correct types.’

    The GetStringUTFChars returns const char *, this value is to be passed to decryptAddress which requires char *, somewhere we will have to do the casting to achieve that, right? Please suggest if there is some correct way to do this. Even if things work out with 2kaud's suggestion I would still like to learn how to do it in a right way.

    Thanks..

  11. #26
    Join Date
    Apr 1999
    Posts
    27,449

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Quote Originally Posted by RituP View Post
    If I dont cast the parameters in decryptAddress function
    Code:
    decryptAddress(pswd,  out, key);
    it gives me this error - error C2664: 'int (char *,char *,char *)' : cannot convert parameter 3 from 'const char *' to 'char *'

    I am not sure how we can achieve this in our scenario– ‘there is no need to cast anything if you send the function the correct types.’

    The GetStringUTFChars returns const char *, this value is to be passed to decryptAddress which requires char *, somewhere we will have to do the casting to achieve that, right? Please suggest if there is some correct way to do this. Even if things work out with 2kaud's suggestion I would still like to learn how to do it in a right way.

    Thanks..
    Ok. Here is the issue in a nutshell.

    A C++ or C function that is prototyped to take a "const char *" guarantees to the caller that the data being sent will not be changed. This is by convention. Therefore, you can pass anything that can be converted to a const char* without intervention. This means a "char *" will also work.

    Now, a function that has an argument that is prototyped as a "char *" is different. By convention, this means there is no guarantee that the function will not change the internal contents of the string. This means that passing a "const char *" to such a function not only is wrong, it is dangerous, as changing the contents of something declared as const is undefined behaviour. That's why the compiler is basically yelling at you not to do what you are doing, and that is to pass a const char* to a char*. The types are not the same.

    When you applied the cast, you told the compiler to "shut up" -- you did not "convert" or change the types. To get around this, actually create a real, bona-fide, writeable, char buffer and pass that instead.

    First of all, the language you're using is C++. Why such low-level 'C' usage? (I know it's C++, since you can't declare variables in the middle of a functional block in C, and that is exactly what you're doing in your code snippets).
    Code:
    #include <vector>
    #include <string>
    //...
    //.. Create some std::string's here
    std::string pswd(env->GetStringUTFChars(thePassword, 0));		
    std::string key(env->GetStringUTFChars(theKey, 0));
    //..
    //...Convert them to vectors for writing purposes
    std::vector<char> vpswd(pswd.begin(), pswd.end());
    std::vector<char> vkey(key.begin(), key.end());
    vpswd.push_back(0);
    vkey.push_back(0);
    //..
    //.. now declare the out variable
    int length = int((7+length)/8)*8;
    std::vector<char> out(length + 1, 0);
    
    //...now call the function
    int code = decryptAddress(&vpswd[0], &out[0], &vkey[0]);
    jstring result = env->NewStringUTF(&out[0]);
    Now, if the parameters were const char*, then there would be no need for the vectors at all, since std::string has a c_str() member function that returns a const char*.

    The vector is basically a dynamic array that is writeable. Note how the address of the first element is passed to the function. For vector<T> a pointer to the first element is a T*, thus a vector<char> first element is a char*, and voila.

    Also note that there is no need for cleanup -- no calls to free(), delete[], or anything. To be honest with you, you should write your JNI code this way, and that is to use RAII classes that on exit of a functional block, destroy themselves properly (classes like std::string and std::vector). If for some reason a JNI function throws an exception back to Java, you had better make sure you clean up that allocated memory, and you can't do that (or you can't do that easily) calling low-level 'C' functions such as malloc(), or even with operator new.

    In addition, you also need to make your JNI functions that create and destroy resources safer. You should make use of (again) RAII -- look up that term, and you will see what it means and why frankly, it is a must if you're writing a JNI layer.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 18th, 2013 at 03:27 PM.

  12. #27
    Join Date
    Apr 1999
    Posts
    27,449

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    An RAII example:

    Let's say that there is a JNI function that creates a string, and you know you must call this function's converse to release the string.

    So pretend the mythical functions are: JNICreateString and JNIReleaseString:
    Code:
    const char *p = JNICreateString( whatever );
    // now do stuff with p
    JNIReleaseString( p );
    So that looks OK right? However, what happens if "do stuff with p" throws an exception? You never get to the line of code that calls JNIReleaseString, thus you now have a memory leak.

    The way to get around this is to use RAII:
    Code:
    struct JNIStringHandler
    {
        const char *theString;
       JNIStringHandler( const char *s) : theString(s) {}
       ~JNIStringHanlder() { JNIReleaseString( theString ); }
    };
    //...
    const char *p = JNICreateString( whatever );
    JNIStringHandler handler(p);
    // now do stuff with p
    What was accomplished? First, there is no need to call JNIReleaseString. Second, if an exception is thrown in "do stuff with p", JNIReleaseString is automatically called. Can you figure out why you don't need to call JNIReleaseString any more, and the JNIReleaseString gets called automatically, regardless of how we leave that block of code (exception, a normal return, whatever)?

    That's RAII in a nutshell.

    Regards,

    Paul McKenzie

  13. #28
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: LoadLibrary giving system err 183 while loading Crypto dll

    Cryptowrapper calling crypto which in turn uses cryptopp.

    int __declspec( dllexport ) __stdcall decrypt(char *in, char *out, char *systemKey)
    Now, if the parameters were const char*, then there would be no need for the vectors at all, since std::string has a c_str() member function that returns a const char*.
    Do you have the source for crypto? If yes, I suggest that you change the interface so that both in and systemKey are const char *. This would simplify things.

    As general good practice, function parameters which are not changed by the function should be passed as const.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured