02-10-2006 04:35 PM
I am having a problem calling a 3rd party DLL that creates a IP thread for windows messaging. I think the problem is in passing the encryption key although I am no certain. The doumentation gives the following export function description:
Function: OmniConnect
typedef int (_stdcall *pOmniConnect) (char * IpAddress, unsigned int Port, unsigned int Timeout, unsigned char EncryptionKey[16], HWND NotifyWindow);
This function creates the initial communications thread in the DLL and passes all the information it needs to communicate with the Omni controller.
The parameters are:
• IpAddress - The IP Address of the Omni controller as an ASCII string. It will also accept a DNS host name, but is limited to 31 characters (+ the \x0 terminator for a total of 32 bytes).
• Port - The UDP port number as an integer. This must match the port number configured in the Omni. The default port is 4369.
• Timeout – This represents the timeout value, in seconds, for all communications attempts. This includes the initial connection, or reconnect and all message send/receive tasks. The valid range is 0-60 seconds. Internally 0 is converted to ½ second and anything over 60 is converted to 60 seconds.
• EncryptionKey - This is the 16 byte binary representation of the encryption key configured in the Omni. From the control panel or PC Access this is entered as 2, 8-byte hex inputs but is stored as a single 16 byte binary value.
• NotifyWindow - This should be the handle of the main window of your application. This is the window handle that will receive the WM_CopyData messages.
Returns:
• 0 – Was unable to pass the task to the thread.
• 1 – Successfully passed the task to the thread.
A graphic of the labview code (v6.1) I am using is attached. I'm fairly certain the other parameters are being called correctly since I have isolated the crash to the encryption key. I build the 16 byte array from the string and pass it as an array to the DLL. The DLL crashes regardless of parameter setup (pointer to value, handles, adapt to type). If I feed the DLL a dummy unsigned char it gets me into the DLL but I get an exception error. Curiously, If I run the DLL as a C calling convention it runs and gives me a success return, but I don't think it is establishing the thread since I don't get any message return in the queue farther down. The function prototype shows the DLL being called as stdcall. Any suggestions would be greatly appreciated.
02-13-2006 04:21 PM
Hello,
What stands out the most to me is that apparent contradition in the following two elements of your function definition and program:
1. The encryption key is defined as: "EncryptionKey - This is the 16 byte binary representation of the encryption key configured in the Omni. From the control panel or PC Access this is entered as 2, 8-byte hex inputs but is stored as a single 16 byte binary value."
2. You pass a key which is initially defined as a string consisting of 8 blocks of 4 characters, with a space after each block. In memory, that comes to 8 (blocks)*4(chars/block)*1 (byte/char) + 8 (space chars)*1 (byte/char) = 32 + 8 = 40 bytes.
Thus, it seems like you are defining 40 bytes where the function is expecting only 16 bytes. The definition notes that your encryption key is meant to be taken as hex at least from PC Access or the control panel. With that said, I would interpret your encryption code as hexadecimal digits, where each pair of digits represents a single byte. That would make sense since hex digits can be represented by 4 bits, and two those builds a single byte (8 bits). As further evidence that this is the way to interpret your key, if you look at the values in your key (without spaces), you'll see that there are 32 characters there, and taking them in chunks of 2 (interpreted as hex values as described in the previous sentence), you end up with exactly 16 bytes! Thus, I would do the following:
a). Take your key, 21DB 3AAF B429 1182 1F03 BFED 77AA 181A, and group it into 2 character pieces (excluding spaces) as:
21 DB 3A AF B4 29 11 82 1F 03 BF ED 77 AA 18 1A
b). Convert each of these two character pieces from ascii to the true integer representation. Remember that the representation we are viewing is hex - fortunately LabVIEW has a function which will do that for us called "Hexadecimal String to Number" which can be found under the String -> String/Number Conversion palette (also see the attached screenshot). ALSO, we want each set of 2 digits to be converted into a SINGLE BYTE, so be sure to wire the lower left-hand input with something that has a BYTE representation, such as a U8 constant, also shown in the screenshot, where the type of the constant was changed by right clicking and selecting under Representation.
c). Build the resulting 16 bytes into an array, and try passing that to the function.
The second of the attached screenshots shows a sample implementation which you should be able to recreate in version 6.1 fairly quickly (although the find and replace string function used might look different).
I think that's the fundamental problem you're having!
Best Regards,
JLS
02-13-2006 08:51 PM - edited 02-13-2006 08:51 PM
Message Edited by Geovo on 02-13-2006 09:10 PM
02-14-2006 05:43 PM
Hello,
I see... I am now considering another aspect of this as a potential culprit... do you know which calling convention the dll was built with? The basic distinction as I understand it is that the standard calling convention is used by dll functions which are responsible for cleaning up their own stack, where as with the C calling convention, the caller of the dll is responsible for cleaning up the stack. Not that this information really matters here, but assigning the right convention in the call library function node will matter. Is it possible that the dll does use the C calling convention, and perhaps is executing properly in that case. Perhaps you can verify this with the 3rd party. Also, is there any other mechanism you can use to, perhaps empirically, determine that the thread is being established?
Sorry I don't have any more concrete ideas, but let's keep gathering information and playing with it!
Best Regards,
JLS
02-14-2006 05:46 PM
Just popping in with one way to monitor the threads... although it's not the best way (since the number can change for other reasons as well), perhaps this will show up in the Performance tab of Task Manager for the thread totals?
JLS
02-14-2006 06:28 PM
02-15-2006 10:54 AM
02-15-2006 03:11 PM
Your problem is indeed the EncryptionKey parameter. Your function expects a pointer to a 16byte memory area, you however pass in a pointer to a LabVIEW array. What you want to do is configure this as Array Format : Array Data Pointer.
@Geovo wrote:
I am having a problem calling a 3rd party DLL that creates a IP thread for windows messaging. I think the problem is in passing the encryption key although I am no certain. The doumentation gives the following export function description:
Function: OmniConnect
typedef int (_stdcall *pOmniConnect) (char * IpAddress, unsigned int Port, unsigned int Timeout, unsigned char EncryptionKey[16], HWND NotifyWindow);
This function creates the initial communications thread in the DLL and passes all the information it needs to communicate with the Omni controller.
The parameters are:
• IpAddress - The IP Address of the Omni controller as an ASCII string. It will also accept a DNS host name, but is limited to 31 characters (+ the \x0 terminator for a total of 32 bytes).
• Port - The UDP port number as an integer. This must match the port number configured in the Omni. The default port is 4369.
• Timeout – This represents the timeout value, in seconds, for all communications attempts. This includes the initial connection, or reconnect and all message send/receive tasks. The valid range is 0-60 seconds. Internally 0 is converted to ½ second and anything over 60 is converted to 60 seconds.
• EncryptionKey - This is the 16 byte binary representation of the encryption key configured in the Omni. From the control panel or PC Access this is entered as 2, 8-byte hex inputs but is stored as a single 16 byte binary value.
• NotifyWindow - This should be the handle of the main window of your application. This is the window handle that will receive the WM_CopyData messages.
Returns:
• 0 – Was unable to pass the task to the thread.
• 1 – Successfully passed the task to the thread.
A graphic of the labview code (v6.1) I am using is attached. I'm fairly certain the other parameters are being called correctly since I have isolated the crash to the encryption key. I build the 16 byte array from the string and pass it as an array to the DLL. The DLL crashes regardless of parameter setup (pointer to value, handles, adapt to type). If I feed the DLL a dummy unsigned char it gets me into the DLL but I get an exception error. Curiously, If I run the DLL as a C calling convention it runs and gives me a success return, but I don't think it is establishing the thread since I don't get any message return in the queue farther down. The function prototype shows the DLL being called as stdcall. Any suggestions would be greatly appreciated.
02-18-2006 09:02 PM
02-19-2006 01:51 AM
I think you do not want to typecast the message queue refnum. That is just a pointer to some data created by the message queue DLL (actually it is an occurrence but that doesn't matter here). Instead you want to typecast the
@Geovo wrote:
I believe I have the DLL establishing a thread, although I am still having a problem retreiving the message from the queue. It appears the main problems was in the call convention. The C call works, and I'm getting a one for the return on both the connect, and disconnect DLL functions. Not sure why that is, if I ever hear back from the vendor maybe they can explain it. Furthur evidence was provided by the performance monitor tool in XP (Control Box, Administrator Tools). I hadn't known about it before, it's pretty impressive. I set the monitor to: Objects->Thread count, and could see the thread count increase and decrease by one when I toggled my connect/disconnect switch (cool!).The problem I'm encountering now is a "Not a valid windows message queue" from one of the sub vi's in the Windows Message Queue for LabVIEW" VI library that I downloaded off the NI site. The message is originating in the "Windows Message Queue Size" vi, which is the farthest down a chain call of vi's which is supposed to return my controller's messages. The controller sends messages in the form of WM_COPYDATA responses. I have the the "Create message Queue" wired to hex 4A, which is supposed to be the message number for WM_COPYDATA. I assume that this is valid for the XP windows platform although I have not downloaded the SDK from MS to look at the Winuser.h header file for myself. I typecast the message queue to a U32 integer for my DLL which for some reason may also be part of the problem for all I know. Thanks for all the help so far, and I would appreciate any help on this next hurdle. For my part I'm going to bone up on windows messaging and check some other LabView resources for clues. I've downloaded the Open G mesaging vi's, but I assume their similar to the one's provided by NI.