Solved

why does data in my GetMsgProc in my DLL get set to 0xfffffffff outside it's own thread?

Posted on 2000-02-18
6
607 Views
Last Modified: 2012-05-07
Hi,

I've made a DLL which contains has an init func that sets a windows hook to receive messages (WH_MESSAGE).

The GetMsgProc only cares about WM_CHAR messages (the purpose of the dll is to monitor input for a particular string) but receives messages from all threads.

i've got a struct in the dll:

typedef struct
{

   // the string we looking for
    char hunted[MAXSTRING];      

} SEARCHSTRING;

and an array of these suckers (MAXSTRING is 20 btw):

SEARCHSTRING searchStrings[MAXSTRING];

I use a basic window derived from CWnd to call the dll func that sets the hook and when i type characters inside that window the data such as

searchString[i].hunted

exists and i can send it to a file using

myfile << searchString[i].hunted << endl;

however when i change focus to another window like netscape the characters are still read from the keyboard and my GetMsgProc is called but the data inside the SEARCHSTRING struct is 0xffffffffffffff when i print it out.

what goes on? how can i set up my dll so that other threads can access the dll's global variable?

muchas gracias,
dj
0
Comment
Question by:dreadedjew
  • 4
  • 2
6 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 400 total points
ID: 2537233
When you use a global hook, your DLL is mapped into every process in the system.  When the hook procedure is called it is called in the context of the process that it is hooking.  i.e when it hooks a messages for process A it is called in process's context (memory space) not the context of the process that set up the hook.

Fortunatley, you can share data between different mapping of the DLL.  The easiest way is with the "data_seg" #pragma.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 2537242
The following article from the VC help explains how to use the #pragma to share data between different instances of the DLL.
***************************
HOWTO: Share Data Between Different Mappings of a DLL
Last reviewed: March 17, 1998
Article ID: Q125677
The information in this article applies to:
* Microsoft Win32 Application Programming Interface (API) included with:
- Microsoft Windows NT versions 3.51, 4.0
- Microsoft Windows 95
SUMMARY
Under certain circumstances, 32-bit DLLs might have to share data with other 32-bit DLLs loaded by a different application or with different mappings of the same DLL. Because 32-bit DLLs are mapped into the calling process's address space, which is private, sharing data with other DLLs mapped into the address spaces of different applications involves creating shared data section(s) or using memory mapped files. This article discusses the former -- creating shared data sections by using the #pragma statement. Typically, system-wide hooks installed in a DLL need to share some common data among different mappings.
MORE INFORMATION
Each Win32-based application runs in its own private address space. If a 32- bit application installs a system-wide hook with the hook callback function in a DLL, this DLL is mapped into the address space of every application for which the hook event occurred.
Every application that the DLL gets mapped into, gets its own set of variables (data). Often there will be a scenario where hook callback functions mapped into different application or process address spaces need to share some data variables -- such as HHOOK or a Window Handle -- among all mappings of the DLL.
Because each application's address space is private, DLLs with hook callback functions mapped into one application's address spaces cannot share data (variables) with other hook callback functions mapped into a different application's address space unless a shared data SECTION exists in the DLL.
Every 32-bit DLL (or EXE) is composed of a collection of sections. By convention, each section name begins with a period. (The period is not required.) These sections can have the following attributes: READ, WRITE, SHARED, and EXECUTE.
DLLs that need to share data among different mappings can use the #pragma pre-processor command in the DLL source file to create a shared data section that contains the data to be shared.
The following sample code shows by example how to define a named-data section (.shared) in a DLL.
Sample Code
   #pragma data_seg(".shared")
   int iSharedVar = 0;
   #pragma data_seg()

The first line directs the compiler to place all the data declared in this section into the .shared data segment. Therefore, the iSharedVar variable is stored in the .shared segment. By default, data is not shared. Note that you must initialize all data in the named section. The data_seg pragma applies only to initialized data. The third line, #pragma data_seg(), resets allocation to the default data section.
If one application makes any changes to variables in the shared data section, all mappings of this DLL will reflect the same changes, so you need to be careful when dealing with shared data in applications or DLLs.
You must also tell the linker that the variables in the section you defined are to be shared by modifying your .DEF file to include a SECTIONS section or by specifying /SECTION:.shared,RWS in your link line. Here's an example SECTIONS section:
   SECTIONS
   .shared   READ WRITE SHARED

Alternatively, some compilers allow you to set the linker switch in your code so that if your file is ever copied to another project, the linker switch goes with it. To do this, include the following line in your code preferably near the #pragma data_seg(".shared") line:
   #pragma comment(linker, "/SECTION:.shared,RWS")

Be careful not to include any extraneous spaces inside the quotation marks because this may cause the linker to misinterpret the directive. In the case of a typical hook DLL, the HHOOK, HINSTDLL, and other variables can go into the shared data section.

**************
Let me know if you have any questions.
0
 

Author Comment

by:dreadedjew
ID: 2537363
Thanks,

this is almost a complete answer!

Do I want to put the typedef of the struct in the shared segmant also? Either way, what's the best way to initialize the array of array's in the shared segmant?
0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 22

Expert Comment

by:nietod
ID: 2538030
A type isn't data.  it isn't "located in memory"  So the type doesn't go in a data segment, only insances (objects, variables) of the type go in a data segment.  so you can declare the typedef anywhere, all that matters is where you declare the instances of the type.

>> Either way, what's the best way to
>> initialize the array of array's in the
>> shared segmant?
Provide an initialize procedure in the DLL and have the EXE that installs the hook call the initialize procedure (probably before installing the hook).  You cannot initialize from the Dll's entrypoint procedure because it will be called each time the DLL is mapped into a process.  (So it would initialize again and again...)
0
 

Author Comment

by:dreadedjew
ID: 2538657
I was initilizing again and again. Your answer was very good however the problem remains unsolved.

I've put the array into shared memory and initialize it from an app before I set the hook.

If i send the contents of the array to a file during the GetMsgProc the contents only show up if app that set the hook received the WM_CHAR message. Other apps still receive the WM_CHAR message but the arrays are still empty.

Do you know of a bug in MSVC 6.0 or WIn98 that might be causing this effect?

Thanks,
dj
0
 
LVL 22

Expert Comment

by:nietod
ID: 2538752
I think I just answered that on another of your questions.  (That or someone else is do the same thing.)  Did you make sure that the data segment is shared (using an entry in the module definition file (.def) or a "#pragma comment(linker..." statement.  Also you have to make sure that the data in the shared segment is statically initialized.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question