Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

DLL shared variables problem

Posted on 2003-03-03
11
Medium Priority
?
268 Views
Last Modified: 2013-11-20
I have writen a DLL which is used by several different apps

There are 2 global variables (called started and currentLoggedLevel) that I want to be shared so that if one app makes started=TRUE, every other app sees started as true.
The way I have tried to go about this is to declared the variables as follows:



#pragma data_seg (".shared")
   
     bool started = false;
     int currentLoggedLevel = -1;

#pragma data_seg()


and then to include the following in my .DEF file

SECTIONS
.shared READ WRITE SHARED;



This does not seem to work, and if one application makes started=TRUE, the others still see it as false.

My question is should this technique work i.e. have I got the right idea but have probably done something wrong somewhere else (if not, what technique could I use to achieve this "shared" behaviour ?).


0
Comment
Question by:tpemckiernan
8 Comments
 
LVL 1

Expert Comment

by:vadik
ID: 8063680
This is my dll without a *.def file. This is working correct.

#include "stdafx.h"
#include "shr.h"

#include <stdlib.h>
#include <tchar.h>



#pragma data_seg (".shared")
 
    bool started = false;
    int currentLoggedLevel = -1;

#pragma data_seg()

#pragma comment(linker, "/SECTION:.shared,RWS")



BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                          )
{
    switch (ul_reason_for_call)
     {
          case DLL_PROCESS_ATTACH:
               if (started)
               {
                    TCHAR buf[10];

                    _itot(currentLoggedLevel++, &buf[0], 10);

                    MessageBox(0, TEXT("started"), &buf[0], MB_OK);
                   
               }
               else
               {
                    MessageBox(0, TEXT("not started"), TEXT("not started"), MB_OK);
                    started = true;
                    currentLoggedLevel++;
               }

          case DLL_THREAD_ATTACH:
          case DLL_THREAD_DETACH:
          case DLL_PROCESS_DETACH:
               break;
    }
    return TRUE;
}
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8095031
tpemckiernan,
Did that work for you?  If that did not work, try:

    static bool started = false;
    static int currentLoggedLevel = -1;

Please reply to all comments.  Thanks for maintaining your open questions!
-- Dan
0
 

Author Comment

by:tpemckiernan
ID: 8099119
Thanks for your suggestions.

declaring the variables as static didn't seem to help

However, the linker comment did seem to help - when apps call the DLL they can read the correct values. However, other DLLS don't read the correct values - any idea why this might be ?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 1

Expert Comment

by:vadik
ID: 8099175
What do you means "However, other DLLS don't read the correct values - any idea why this might be "??
DLL's in other processes? Sorry for my English...
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 8099539
>>what technique could I use to achieve this "shared" behaviour

A very simple technique is to create a global MUTEX.

#define strMutexName "MyAppsDllIsWorking"

HANDLE hMutex;
DWORD  dwLastError;

hMutex= CreateMutex(NULL, FALSE, strMutexName);
dwLastError= GetLastError();
if (hMutex==0) {
    // some screball erro, probaly strMutexName has slashes or something
}

if ( dwLastError == ERROR_ALREADY_EXISTS ) {
    // the DLL is already running or whatever
}

.... later....
CloseHandle( hMutex );

=-=-=-=-=-=-=-=-=-=-=-=-
I'm not sure exactly what you are going for, but here is how this works... see if it will do the trick for you:

Whenever any program or DLL or anything executes that CreateMutex API call with the sanem name, the first time it is called, you will get a handle return and no error.  But the next time it is called, you will get

  dwLastError == ERROR_ALREADY_EXISTS

so, you know that some other process called it first.  So the combination of CreateMutex and GetLastError makes for a one-shot 'gateway'.

Mutexes are more often used in synchronzing threads and processes via fns like WaitForSingleObject (and other complicated stuff), but they can also be used in a simpler fashion as shown.

If you are writing in C++, I can give you a tight little class call CLimitSingleInstance that uses this techique to prevent a user from running a second copy of my program and instead I can display the first one (it's probably forgotton on the taskbar).

-- Dan
0
 
LVL 1

Expert Comment

by:keitha1
ID: 8134832
As far as I know, the simplest way to share memory between processes is by using memory-mapped files.
0
 
LVL 1

Expert Comment

by:vadik
ID: 8135120
I don't think so because it's very expensive solution for  two variables only...
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 400 total points
ID: 8142075
This was hard to track down -- I know the technique works since I've used it in hook DLLs, but when I tried, it kept failing!

A clue: Dunpbin did not even display the .shared section!

Here it is:
      HOWTO: Share Data Between Different Mappings of a DLL
      http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B125677
and
      http://msdn.microsoft.com/library/en-us/vccore/html/_core_How_do_I_share_data_in_my_DLL_with_an_application_or_with_other_DLLs.3f.asp


In the "fine print" it says that you need to use INITIALIZED data!  For instance, this will fail...

      #pragma data_seg(".shared")
          int nShared;  
      #pragma data_seg()

but this will work exactly as advertized:

      #pragma data_seg(".shared")
         int nShared= 77;  
      #pragma data_seg()


I used the following code for testing (and my thanks go out to  vadik  for the #pragma(linker,... ) tip -- it's better than the often-documented .DEF file variation.

#include "stdafx.h"
#include "DllSharedMem.h"

#pragma data_seg(".shared")   // Make a new section that we'll make shared
   int nShared=77;  
#pragma data_seg() // Back to regular, nonshared data
#pragma comment(linker, "/SECTION:.shared,RWS")

int nUnshared;  

BOOL APIENTRY DllMain( HANDLE hModule, DWORD reason, LPVOID lpReserved ) {
      return TRUE;
}
DLLSHAREDMEM_API int  GetUnsharedInt(void) { return nUnshared; }
DLLSHAREDMEM_API void SetUnsharedInt(int nNewVal) { nUnshared= nNewVal; }
DLLSHAREDMEM_API int  GetSharedInt(void) { return nShared; }
DLLSHAREDMEM_API void SetSharedInt(int nNewVal) { nShared= nNewVal; }


Use that DLL in several processes and the nShared value will be the same everywhere.  There is one thing to watch out for.... If you have more than one copy of the DLL, or if you gave just one copy, but it can be called using different path names, then the modules are considered different and nothing is shard, including code or SHARED data.   See:
      PRB: Problem with Shared Data Sections in DLLs.
      http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B147136

-- Dan
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses
Course of the Month15 days, 12 hours left to enroll

580 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