Results 1 to 29 of 29

Thread: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED but still in Brainstorming)

  1. #1

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Resolved CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED but still in Brainstorming)

    Hi everybody. I previously had some issues with WM_SETTEXT that are now fixed, thanks to some great help around here : ). I still have one more problem related to this though.... The problem is the CopyMemory function.

    I don't know how exactly can I retrieve from memory the text that I receive with the WM_SETTEXT message. I send this message from a VC++ Application. If I send a short message (under 10 characters or so) it works. If I send a really long message (more than 50 characters), the below code crashes.

    I think that "Len(lParam)" is not correct. Logically, that's a LONG so Len will always return 4 I guess. So how can I know how much memory to copy? It's a kind of recursive problem: I can't know how much memory to copy unless if I copy it and I can't copy it because I don't know how much to copy : |.

    Anybody got an idea about this?

    VB Code:
    1. Public Function TheSubclassedWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    2.  
    3. Dim sString As String
    4.  
    5.     If uMsg = WM_SETTEXT Then
    6.         CopyMemory sString, lParam, Len(lParam)
    7.         MsgBox sString, vbInformation + vbSystemModal, "Trying to get the value"
    8.         Exit Function
    9.     End If
    10.    
    11.    TheSubclassedWndProc= CallWindowProc(loOriginalWindowProcedureAddress, hWnd, uMsg, wParam, lParam)
    12. End Function

    Thank you for reading anyway! : D.
    Last edited by Axonn; May 29th, 2005 at 04:18 AM. Reason: Problem solved
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  2. #2
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: CopyMemory issue (WM_SETTEXT problem RELOADED)

    You can turn the pointer into a string by copying to the address of the string.
    VB Code:
    1. Public Function PointerToString(ByVal lpString As Long) As String
    2.     Dim sTemp As String
    3.     'copy the pointer into the temporary string
    4.     CopyMemory ByVal VarPtr(sTemp), lpString, 4&
    5.     'since sTemp points to the original string it is an easy task to copy it
    6.     PointerToString = sTemp
    7.     'But we need to manually destroy the sTemp string to avoid a nasty GPF
    8.     CopyMemory ByVal VarPtr(sTemp), 0&, 4&
    9. End Function
    Simply pass lParam to this function to get the string.

  3. #3

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Re: CopyMemory issue (WM_SETTEXT problem RELOADED)

    All I get now is a row of question marks. I get a message box with "????????????????????????????????????". Maybe it's not formatted correctly with that function? As you can see, I just used the function you gave me there in the message box : ).

    VB Code:
    1. Public Function TheSubclassedWndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    2. Dim sString As String
    3.  
    4.     If uMsg = WM_SETTEXT Then
    5.         MsgBox PointerToString(lParam), vbInformation + vbSystemModal, "Test"
    6.         Exit Function
    7.     End If
    8.    
    9.    TheSubclassedWndProc= CallWindowProc(loOriginalWindowProcedureAddress, hWnd, uMsg, wParam, lParam)
    10. End Function

    This is the Visual C++ sender:

    Code:
    SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(LPCTSTR) "Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. ");
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  4. #4
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: CopyMemory issue (WM_SETTEXT problem RELOADED)

    Oh yeah. That's because in an NT based system (NT/200x/XP) the LPCTSTR is a wide unicode string so if you use it on a non Win9x/ME system you need to modify the function a little.
    VB Code:
    1. Public Function PointerToString(ByVal lpString As Long) As String
    2.     Dim sTemp As String
    3.     'copy the pointer into the temporary string
    4.     CopyMemory ByVal VarPtr(sTemp), lpString, 4&
    5.     'since sTemp points to the original string it is an easy task to copy it
    6.     PointerToString = StrConv(sTemp, vbFromUnicode)
    7.     'But we need to manually destroy the sTemp string to avoid a nasty GPF
    8.     CopyMemory ByVal VarPtr(sTemp), 0&, 4&
    9. End Function
    This might be a bit confusing since VB uses BSTR which is in Unicode format already.

  5. #5

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Re: CopyMemory issue (WM_SETTEXT problem RELOADED)

    Ain't workin'. Same "???" problem. Here are some things I tried:

    Code:
    SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(BSTR) "Just a long string.");
    
    SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(LPCTSTR) "Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. ");
    As you can see I also tried casting to BSTR. I knew that VB works with BSTRs but that casting didn't help. However, when I pass short values (like the first line of the above code) to VB, I also get one or two funny symbols in that message box. You know, weird symbols. Probably unicodes.

    VB Code:
    1. If uMsg = WM_SETTEXT Then
    2.         CopyMemory sString, lParam, Len(lParam)
    3.         MsgBox sString, vbInformation + vbSystemModal, "Working?"
    4.         MsgBox PointerToString2(lParam), vbInformation + vbSystemModal, "Working?"
    5.         Exit Function
    6.     End If

    PointerToString2 = the new function you gave me.

    When I comment the line with the message box with the new function, it works for short strings. For the first line of the first code I included here, it works. When I use longer strings, it crashes. If I comment my old copymemory and use only your function, I get question marks everywhere. No matter if I use short or long strings, BSTRs or LPCSTRs. I tried everything possible. Hm. Strange.

    Here's the complete set of calls that I tried. Maybe it helps.

    Code:
    	SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(LPCSTR) "Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. ");
    	SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(LPCSTR) "Just a long string.");
    	SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(BSTR) "Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. ");
    	SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(BSTR) "Just a long string.");
    Last edited by Axonn; May 27th, 2005 at 03:23 AM.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  6. #6
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem RELOADED)

    Maybe you could do this:
    Code:
    Private Declare Function lstrlenW Lib "kernel32" _
        (ByVal lpString As Long) _
        As Long
    
    Public Function TheSubclassedWndProc(ByVal hWnd As Long, _
                       ByVal uMsg As Long, _
                       ByVal wParam As Long, _
                       ByVal lParam As Long) _
                      As Long
    
    Dim sString     As String
    Dim lStringLen  As Long
    
        If (uMsg = WM_SETTEXT) Then
            lStringLen = lstrlenW(lParam)
            sString = Space$(lStringLen)
            CopyMemory sString, lParam, lStringLen
            
            MsgBox sString, vbInformation + vbSystemModal, "Trying to get the value"
            
            Exit Function
        End If
        
        TheSubclassedWndProc= CallWindowProc(loOriginalWindowProcedureAddress, hWnd, uMsg, wParam, lParam)  
    End Function
    I know lstrlenW works with pointers because I only really pass pointers. I used to try to pass strings but I find pointers are much easier (especially when working with C++).
    Last edited by penagate; May 27th, 2005 at 05:45 AM. Reason: Added sString = Space$(lstrlenW)

  7. #7

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Exclamation GRRRRRRRRRRRRRRRRRRRRR Visual Basic

    Nope. Something still stinks here. I used your idea penagate but now when the CopyMemory tries to execute, my IDE crashes. I tried sending the message from Visual C++ like this:

    Code:
    SendMessage(hwndASDClockWindow, WM_SETTEXT, 0, (LPARAM)(LPCSTR) "Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string. Just a long string.\0");
    And I also tried sending using casting to BSTR but I get the same result. What I can tell you is that lStringLen after I do lStringLen = lstrlenW(lParam) is equal to 98. Don't ask me why lStringLen is 98, since I measured the VC++ string that I'm sending and that is 181 characters long (179 if you don't consider the \0 at the end as two characters). I don't see the connection between 98 and 181 : ). It's not even double. So I don't know if this is a Unicode issue. It might be that the pointer isn't working properly? I don't know : |.

    I also tried without the "\0". The MSDN documentation says that:
    "Security Alert Using this function incorrectly can compromise the security of your application. lstrlen assumes that lpString is a NULL-terminated string. If it is not, this could lead to a buffer overrun or a denial of service attack against your application."
    I also tried hardcoding "181" instead of lStringLen. Ain't working.

    Will I ever get rid of these WM_SETTEXT issues? Pf. Now that VB catches it, it's unable to get the data. How annoying : (.

    Thanks for helping anyway : ). It's a lot nicer to crack a problem together with somebody else, no matter how far he/she is.
    Last edited by Axonn; May 27th, 2005 at 04:48 PM.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  8. #8

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Angry lstrlen

    I discovered another function. lstrlen. So not lstrlenW, but lstrlen. Surprise surprise. This function returns the correct lenght of the string I got in Visual C++, that is, 179. However, my IDE still crashes when trying to copy the memory! Grrrrrrrrrrrrrrrrr !

    So, anybody has any more ideas??
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  9. #9
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Welcome to the weird and (sometimes) wonderful world of VB and APIs

    Sorry, I forgot you were sending the string from C++, so I used lstrlenW. The 'W' signifes a 'wide' string (Unicode, so dividing the ASCII length by 2) whereas the non-wide equivalent is the ASCII version which is as you found out the right one to use when the string is a C++ ASCII string.

    Also, I stuffed up the string copying code. This version should work (a bit better at least ):

    Code:
    Public Function TheSubclassedWndProc(ByVal hWnd As Long, _
                       ByVal uMsg As Long, _
                       ByVal wParam As Long, _
                       ByVal lParam As Long) _
                      As Long
    
        Dim strString       As String
        Dim lngStringLen    As Long
    
        If (uMsg = WM_SETTEXT) Then
            If (lParam) Then
                lngStringLen = lstrlen(lParam)
                If (lngStringLen) Then
                    sString = Space$(lngStringLen)
                    CopyMemory ByVal strString, ByVal lParam, lngStringLen
                End If
            End If
            
            MsgBox sString, vbInformation + vbSystemModal, "Trying to get the value"
            
            Exit Function
        End If
        
        TheSubclassedWndProc = CallWindowProc(loOriginalWindowProcedureAddress, hWnd, uMsg, wParam, lParam)
    End Function
    I forgot the ByVal's before. HTH.
    Last edited by penagate; May 28th, 2005 at 02:06 AM.

  10. #10

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Hm. I don't think that byVal is important. Doesn't VB add that by its own? Anyway, I also used lstrlen and as I said, I got the same crash, except that it did return the proper amount of characters (179). I will try your new idea though... I'll tell you if it worked it a few minutes : ).
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  11. #11
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Quote Originally Posted by Axonn
    Hm. I don't think that byVal is important. Doesn't VB add that by its own?
    Nope, by default VB uses ByRef. As opposed to C++ which by default uses ByVal, unless you use a * character.

  12. #12

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Thumbs up Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Hahahahaha. It worked!!!

    WHY DID IT WORK??????? Only because of the ByVal! WEIRD DUDE! I've been using API in VB for some years, but this is way out there. Strange. I only added the ByVals and it worked straight out of the box. I didn't do any other modification. But I knew that VB passes using ByVal anyway. If it would have been byRef maybe I would have understood... but like this, I'm totally puzzled.

    And why does it work with Space(lngStringLen)? Last night I was trying all sorts of things and I modified your Space$ with Space. What's the difference between Space$ and Space? I looked it up in MSDN but it doesn't say. I find only help related to Space, not to Space$.

    Anyway Penagate dude, thanks a lot : D.

    EDIT: Hm. Interesting about ByRef. I knew the opposite : ).
    Last edited by Axonn; May 28th, 2005 at 02:49 AM.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  13. #13
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Quote Originally Posted by Axonn
    Hahahahaha. It worked!!!

    WHY DID IT WORK??????? Only because of the ByVal! WEIRD DUDE! I've been using API in VB for some years, but this is way out there.
    ByVal is the most common way to pass parameters to API functions, you only use ByRef say with CopyMemory when you pass a pointer to an object. At all other times using CopyMemory you would use ByVal.

    Although, myself, I'm not entirely sure why ByVal is used with the string destination parameter, surely it would be ByRef or ByVal StrPtr? but eh...

    But I knew that VB passes using ByVal anyway.
    See my last post.

    And why does it work with Space(lngStringLen)? Last night I was trying all sorts of things and I modified your Space$ with Space. What's the difference between Space$ and Space? I looked it up in MSDN but it doesn't say. I find only help related to Space, not to Space$.
    The $ character just tells VB to use the string-typed Space function, instead of the variant (default) function. It's more efficient and works with a lot of those string functions.

    e.g. Left$ returns string, Left returns variant.

  14. #14

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Wm_copydata

    We made our replies in the same time : ). That's why I didn't notice the ByVal stuff.

    Thanks again for the help penagate : D. You brought light in the dark, hopeless world of WM_SETTEXT : >.

    Just in case you are wondering, I want to use WM_SETTEXT to pass data from VC++ to VB. Variables, call functions in VB, stuff like that. I also saw something about WM_COPYDATA. There's an example around here. I could also use that but I really wanted to understand this issue and solve it. Anyway, even with WM_COPYDATA, I'd probably have to use some string to pass the data and then parse it. Or was it working with custom made structures.... hm : ).
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  15. #15
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED)

    Quote Originally Posted by Me
    ByVal is the most common way to pass parameters to API functions, you only use ByRef say with CopyMemory when you pass a pointer to an object. At all other times using CopyMemory you would use ByVal.
    Maybe I should clarify this.

    Use ByVal when you pass a memory address.
    Use ByRef when you want to entice VB to pass a pointer.

    For example, these two code snippets achieve the same result, but one using ByRef and the other using ByVal:
    Code:
    Dim lngDest     As Long
    Dim lngSource   As Long
    
    '---------------------------------
    
    CopyMemory lngDest, lngSource, 4
    
    '---------------------------------
    
    Dim lngDestPtr  As Long
    Dim lngSrcPtr   As Long
    
    lngDestPtr = VarPtr(lngDest)
    lngSrcPtr = VarPtr(lngSource)
    
    CopyMemory ByVal lngDestPtr, ByVal lngSrcPtr, 4
    Hope this clears it up a bit better

    Quote Originally Posted by Axonn
    Anyway, even with WM_COPYDATA, I'd probably have to use some string to pass the data and then parse it. Or was it working with custom made structures.... hm : ).
    With WM_COPYDATA you pass data using a COPYDATASTRUCT type.

    Quote Originally Posted by Axonn
    Just in case you are wondering, I want to use WM_SETTEXT to pass data from VC++ to VB
    I pass data between C++ and VB regularly. I use a C++ DLL (cos that's the only thing I know how to make in C++ ) and store functions that can't be done in VB, in there. I find callbacks a fairly good way of passing data, even if they are a bit obscure they do work.

    Example:
    - VB app calls function in C++ DLL, passing address of callback function.
    - C++ function calls callback function (maybe several times), passing data in the stack each time.

    Or an even more spaghetti-like example:
    - VB app calls function in VB DLL, passing address of callback function.
    - VB DLL function calls callback function using function in C++ DLL, cos it can't be done in VB
    - C++ DLL passes data back to VB app.
    - Since callback function has to be in a module, an interface class is used to pass the data back to a form (if that's where it is needed).

    Simple if you know what's going on, but not exactly straightforward

  16. #16

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Pointers, Callbacks and sending data

    About ByVal and ByRef: I'm not a beginner, I knew about those things (value and reference, pointer, etc). But I thought that VB passes ByVal by default, not ByRef.

    And about the C++ DLL, we're very much alike here : ). This is just about all I know to do in VC++ too. I use a DLL to hook processes, which I can't do in VB. I did try the callbacks stuff, but I don't like it! You know why? It doesn't work right. THIS IS EXACTLY WHY I want to use WM_SETTEXT and stuff like that. I've been there: I made a VB application that calls a C++ DLL passing it the address of the callback. But the annoying thing is that I can't call the VB from C++ whenever I want to! I don't know why. I can call the VB function only when VB has just called a VC++ DLL function. Practically, I can't call the VB from a WM_TIMER callback procedure from within VC++. So I can call VB only when the two are somehow linked together. This problem was annoying. WM_SETTEXT allows me to send stuff whenever I want to.

    Oh yeah, now I remember that I read last night about COPYDATASTRUCT. Hm. For me, it's worse than WM_SETTEXT. It does the same thing except it's more complicated. It is however safer I guess. And WM_SETTEXT is normally used for other stuff : ). For me it's not, 'cause I subclassed my VB application so I don't care what it does originally : ).
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  17. #17
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Pointers, Callbacks and sending data

    Quote Originally Posted by Axonn
    About ByVal and ByRef: I'm not a beginner, I knew about those things (value and reference, pointer, etc).
    OK, well hopefully my post might clear some things up for beginners then... if they read it

    I've been there: I made a VB application that calls a C++ DLL passing it the address of the callback. But the annoying thing is that I can't call the VB from C++ whenever I want to! I don't know why. I can call the VB function only when VB has just called a VC++ DLL function.
    That's strange. Can you post the C++ code you were using to do that? I can take a look at it... I was trying to do something like that just now, but I kinda suck with C++ and for some strange reason the function doesn't want to export.

  18. #18

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED)

    *laugh* I'm really "smart" today. I spent 2 minutes wondering why a message box ain't appearing. Hehe. I forgot to build the VB exe and copy it in the Debug folder of my VC++ DLL project : >.

    And then again, I really am smart today. It's wierd. 'cause this time it worked *laugh*. Hm. Perhaps because I'm using a byte variable? Some while ago I was using a string and that didn't work, I'm sure of it. I'm gonna remake my code and try to pass a string. Who knows, maybe today I'm more in shape.

    Here's the code, but unfortunately, it works : D. It's not the first time in my life I'm pissed off that something WORKS. Sorry for the delay, I had to change my code in order not to post useless stuff. I made a few new functions to remove my usual tasks in it and show you only the relevant code. Hm. I'm gonna try makin' it with string after this.

    1. Visual Basic Declarations & Click event of the "Test" button.
    VB Code:
    1. Private Declare Function ASDSetExternalAddress Lib ".\Debug\ASDClock.dll" (ByVal NewVal As Long) As Long
    2.  
    3. Private Sub cmdTest_Click()
    4.     ASDSetExternalAddress AddressOf Testing
    5. End Sub

    2. Visual Basic Module
    VB Code:
    1. Public Sub Testing(ByVal byTest As Byte)
    2. MsgBox byTest, , "Testing callbacks"
    3. End Sub

    3. Visual C++ Code
    Code:
    long extProc;
    
    VOID CALLBACK TestTmrProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
    	typedef void (__stdcall *OutsideFunction)(BYTE byAByteVariable);
    	OutsideFunction TestFunctionCall;
    	TestFunctionCall = (OutsideFunction)extProc;
    	TestFunctionCall(22);
    }
    
    void WINAPI ASDSetExternalAddress(long ExtAddress)
    {
    	extProc = ExtAddress;
    	ctRefreshTimerID = SetTimer(NULL, NULL, 2000, (TIMERPROC) TestTmrProc);
    }
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  19. #19
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED)

    Hmm... I don't specify "CALLBACK".

    here's one of my functions. I call it from a VB DLL to call the callback proc in the VB app.
    Code:
    long __stdcall CallProgressCallback( void* lpfnProcAddress,
                                         long  lpszStatus,
                                         long  dwProgress )
    {
      typedef long (__stdcall* ProcAddress)(long arg1, long arg2);
      ProcAddress _lpfnProcAddress = (ProcAddress) lpfnProcAddress;
        
      return _lpfnProcAddress(lpszStatus, dwProgress);
    }
    Also, I don't think you can pass strings very well, I just use pointers instead.

  20. #20

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Passing strings

    I'm gonna try to pass a string now. Using pointers of course. But it's still weird. 'cause I remember that the other time when this didn't work, I called the GetLastError() to find out why, and it gave me a strange "access denied" error code. Why? Don't ask me, I don't have the slightest idea. Probably my hook DLL was trying to access a process's space that it wasn't allowed to. I don't know. Hm. Let me see with this string.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  21. #21
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: Passing strings

    Quote Originally Posted by Axonn
    ... I called the GetLastError() to find out why, and it gave me a strange "access denied" error code. Why?
    Probably because of the fact that VB (IDE and/or runtime) does many API calls itself and you are seeing an error code from one of them. You should use Err.LastDLLError instead, to get the error code of the last API call that you made.

  22. #22

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    String Callbacks

    Guess what. It worked. It may very well be because I learned quite a lot since the last time I tried to pass a string pointer from VC++ to VB. Here's the modified code : ). As you can see, I used what you showed me earlier.

    1. The form button click code remained the same.

    2. Visual Basic Module.

    VB Code:
    1. Private Declare Function lstrlen Lib "kernel32" (ByVal lpString As Long) As Long
    2. Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
    3.  
    4. Public Sub Testing(ByVal byTest As Long)
    5. Dim sString As String
    6. Dim sLen As Long
    7.  
    8.         sLen = lstrlen(byTest)
    9.         sString = Space$(sLen)
    10.         CopyMemory ByVal sString, ByVal byTest, sLen
    11.         MsgBox sString, vbInformation + vbSystemModal, "Trying to get the value"
    12. End Sub

    3. Visual C++ Code

    Code:
    VOID CALLBACK TestTmrProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
    	typedef void (__stdcall *OutsideFunction)(BSTR sTest);
    	OutsideFunction TestFunctionCall;
    	TestFunctionCall = (OutsideFunction)extProc;
    	BSTR sTest2 = (BSTR)"Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. Just a very long string. ";
    	TestFunctionCall(sTest2);
    }
    
    void WINAPI ASDSetExternalAddress(long ExtAddress)
    {
    	extProc = ExtAddress;
    	ctRefreshTimerID = SetTimer(NULL, NULL, 2000, (TIMERPROC) TestTmrProc);
    }
    Last edited by Axonn; May 28th, 2005 at 05:48 AM. Reason: Modification, duh : )
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  23. #23
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED)

    Nice, glad it works Sorry about the delay in replying.

    I figured out my exportation issues, turned out I was building it to the wrong DLL... oops

    Anyway I tried your timer function thing and it worked for me too. I did make some slight modifications though... not sure if they are any better than the code you had. I'm still learning C++

    Code:
    typedef long (__stdcall* ProcAddress)(BYTE byAByteVariable);
    ProcAddress extProc;
    long ctRefreshTimerID;
    
    VOID CALLBACK TestTmrProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
      extProc(22);
    }
    
    void WINAPI ASDSetExternalAddress(long ExtAddress)
    {
      extProc = (ProcAddress) ExtAddress;
      ctRefreshTimerID = SetTimer(NULL, NULL, 2000, (TIMERPROC) TestTmrProc);
    }
    Any good?

  24. #24

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Better

    Hehe, earlier today I was forgetting to build the EXE : D.

    Hm. Don't ask me, I'm pretty much of a beginner in VC++ too : ). But it does look better since you're doing less in that timer callback function, so it should work better. But the difference is probably 1 milisecond of performance gain per day of running : D.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  25. #25
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED)

    Sorry to jump into the discussion so late. I know it's resolved, but I have a few comments that might shed some light in the future.

    1. The reason you have to use ByVal when passing a string pointer from VB to a C++ dll is that VB strings are not stored the same way as C++ strings. ByVal actually forces VB to pass the pointer to the sting and in addition adds a chr(0) to the end of the string so that it looks exactly like a C style string.

    2. One way to copy the string sent to VB from a C-dll or API is to copy each character one at a time until the terminating chr(0) is reached. The lstrlen API function calculates the length of a string by looking for this termination character.

    3. Callbacks from C to VB can be tricky especially from a seperate thread. This is because when VB creates threads, each thread acts as if it were an application of its own. Each thread gets its own copy of global variables, the Err object and the App object. The information for the location of these objects is stored in each thread's thread local storage (TLS). See this link for more info
    http://www.vbforums.com/showthread.php?t=327589

  26. #26
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED)

    Quote Originally Posted by moeur
    1. The reason you have to use ByVal when passing a string pointer from VB to a C++ dll is that VB strings are not stored the same way as C++ strings. ByVal actually forces VB to pass the pointer to the sting and in addition adds a chr(0) to the end of the string so that it looks exactly like a C style string.
    That sounds right, I did actually know that once.

    3. Callbacks from C to VB can be tricky especially from a seperate thread. This is because when VB creates threads, each thread acts as if it were an application of its own. Each thread gets its own copy of global variables, the Err object and the App object. The information for the location of these objects is stored in each thread's thread local storage (TLS). See this link for more info
    http://www.vbforums.com/showthread.php?t=327589
    But that I didn't know. Interesting stuff.

  27. #27

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Using WM_SETTEXT

    Hi moeur, thanks for the comments. As penagate, I didn't know about that threading stuff. But so far, I have had success with those callbacks, so it seems that there are no problems.

    However, if any of you guys think that the callbacks are unsure, I welcome you to apply my idea : D. Use WM_SETTEXT to send a message and then you can parse that message in Visual Basic and interpret it. You could pass variables, function calls, anything you would want : D. I think it's a fair bet and it's very effective. It might be a bit weird, but hey, we're programmers right? : ). As long as it does the job and it's safe, USE IT : D. This is exactly why I had all this fuss with WM_SETTEXT in the first place.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

  28. #28
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: CopyMemory issue (WM_SETTEXT problem - ADVANCED) (SOLVED but still in Brainstormi

    Quote Originally Posted by Axonn
    As long as it does the job and it's safe, USE IT : D.
    Take a peek at the "Sending strings between VB apps" link in my sig. That's an example of a nice hacky method of achieving results It's also easier to receive them that way instead of using subclassing, but if you're subclassing anyway there's not all that much point.

  29. #29

    Thread Starter
    Lively Member Axonn's Avatar
    Join Date
    May 2005
    Posts
    64

    Subclassing preffered

    I looked at that article a long time ago : D. At least three days ago. That requires a textbox and I didn't like the idea. I prefer subclassing. I'm using it only for capturing that message, but I still prefer it over the textbox method. Who knows when I'm gonna need to pass something different than WM_SETTEXT. Maybe in the future program development I will need to expand that subclassing.
    . - = E C H Y S T T A S = - .
    The Greater Mind Balance

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