Solved

application crash outside Visual Studio

Posted on 2003-11-19
8
424 Views
Last Modified: 2013-11-20
hi,

i've developped an mfc application, which uses 2 external dlls (Xerces and curl) and an activeX control to access the local machine's WMI and produce a XML file with the information.
The application does it's stuff in a timer triggered loop, ie every 30 seconds or so it accesses some info via WMI.

Everything works fine when I run the app inside VS.NET (in both debug and release configs), but when i run the app outside the IDE, it crashes after the first loop (sometimes it goes for a few loops, sometimes just one).

All this in windows xp sp1.

All the memory leak detectors i've tried report no leaks.

When I JIT debug, I see that the crash happens on code that has worked on previous iterations, sometimes on the Xerces stuff, other times on my registry accessing functions (RegQueryValueEx, namely). I get a "Memory could not be read[/written] sometimes" error. I have looked in to some dynamic condition that would cause the error, but i can't get past the fact that all the iterations are exactly alike (same information retrieved over and over again) and the code works inside VS.NET (both configs).

All this happens only from the second iteration of the program onward. To my best knowledge, the registry related system calls are made as seen on the msdn sample code. xerces stuff is also very much like the samples (including cleanup stuff).

help much appreciated. thanks!

sopppas
0
Comment
Question by:sopppas
8 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 9781957
>>Everything works fine when I run the app inside VS.NET

As you haven't posted any code: Check for uninitialized variables, especially pointers. The behaviour you described is typical for such small mistakes.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9785224
The difference in running application from VS and out of it is current directory. Maybe this can be a reason?
0
 

Author Comment

by:sopppas
ID: 9786114
hi,

AlexFM I've tried running the program inside the Debug|Release directory and in the project dir. No luck!

I'm gonna provide you with some code, then:

- the whole program is a systray application which, from time to time, iterates do find system info. This is done with the following loop:

void CEasyAppDlg::OnTimer (UINT TimerVal)
{
      KillTimer(timerId);

#ifdef _DEBUG
      CMemoryState oldMemState, newMemState, diffMemState;
      oldMemState.Checkpoint();
#endif
      
      CEasyApp::XMLCreate();
      

#ifdef _DEBUG
      newMemState.Checkpoint();
      if( diffMemState.Difference( oldMemState, newMemState ) )
    {
        TRACE( "Memory leaked!\n" );
            oldMemState.DumpStatistics();
    }
#endif

      timerId = SetTimer(IDT_TIMER_0, 1000, NULL); // 30 segundos
}

this function is also called when the program is first started, ie inside the OnInitDialog. As previously stated, no memory leaks are reported by CMemoryState.

- anyways, CEasyApp::XMLCreate is the core function of the program: it makes A LOT of wmi queries, a few registry ones, and uses xerces to create a XML file with the collected system info. These queries are made from within an ocx active X controller. The following are examples of how I'm doing this
 
      
      // inside XMLCREATE
      CString str;
      str = CagenteActXApp::getDomainAndName(); // the getDomainAndName function is in the ocx

      machineElem->setAttribute(X("id"), X(str)); // these are Xerces lib functions.
      ////////////////////////////


      // this function is defined in the ocx
      CString CagenteActXApp::getDomainAndName() {

      HRESULT hr;

      // Get list of objects
      CComPtr<IEnumWbemClassObject> spEnumInst;
      CComBSTR bstrQuery("SELECT * FROM Win32_ComputerSystem");

      hr = spServices->ExecQuery(CComBSTR(_T("WQL")), bstrQuery,
                  WBEM_FLAG_BIDIRECTIONAL, NULL, &spEnumInst); // some crashes occur in this line on the 2nd or 3rd iteration

      CComVariant varName, domain;
      bool bFinished = false;
      while (!bFinished)
      {
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
                  &uNumOfInstances);
            
            if (hrNext == WBEM_S_FALSE || uNumOfInstances == 0)
                  bFinished = true;
            else
            {
                  // Get properties from the object
                  hr = spInstance->Get(CComBSTR(_T("Name")), 0, &varName, 0, 0);
                  hr = spInstance->Get(CComBSTR(_T("Domain")), 0, &domain, 0, 0);
      
            }
      }

      BSTR bstr = V_BSTR(&domain);
      BSTR bstr2 = V_BSTR(&varName);
      
      CString cs(bstr);
      cs += "\\";
      CString cs2(bstr2);
      cs += cs2;
      
      VariantClear(&varName);
      VariantClear(&domain);

      return cs;  // returns something like WORKGROUP\MYCOMPUTER
      }
      /////////////////

      // again in XMLCreate;
      list<CString> propVal2;
      CagenteActXApp::getSoftwareSet(&propVal2); // this retrieves all the installed programs
      //////////////////////

      void CagenteActXApp::getSoftwareSet(std::list<CString> *res) {


      CHAR    swName[sizeof( DWORD ) * 1024] = ""; // Buffer for class name.


      HKEY hKey;
      HKEY hKeyRoot;

      hKeyRoot = HKEY_LOCAL_MACHINE;

      HRESULT retCode;

      retCode = RegOpenKeyEx (hKeyRoot,
                            "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
                            0,
                            KEY_ALL_ACCESS,
                            &hKey);

      list<char *> keys;
      HRESULT hr = 0;
      int j = 0;
      while(hr != ERROR_NO_MORE_ITEMS) {
            DWORD dwSize = sizeof( DWORD ) * 1024;
            swName[0] = '\0';
            rucucu = RegEnumKeyEx(
                                    hKey,         // handle of key to enumerate
                                    j,            // index of subkey to enumerate
                                    swName,         // address of buffer for subkey name
                                    &dwSize,         // address for size of subkey buffer
                                    NULL,         // reserved
                                    NULL,         // address of buffer for class string
                                    0,            // address for size of class buffer
                                    NULL          // address for time key last written to
                                    );
            keys.push_back(strdup(swName));
            j++;
      }

      while(!keys.empty()) {
            TCHAR skey[sizeof(DWORD)*1024];
            DWORD dwSize = sizeof( DWORD ) * 1024;
            strcpy(skey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\0");
            strcat(skey, "\\");
            strcat(skey, keys.front());
            strcat(skey, "\0");
            delete keys.front();
            keys.pop_front();
            HKEY hKey2;

            retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                            skey,
                            0,
                            KEY_ALL_ACCESS,
                            &hKey2);

            skey[0] = '\0';

            retCode = RegQueryValueEx(hKey2, "DisplayName", 0, NULL, NULL, &dwSize ); // it's been known to crash here
            retCode = RegQueryValueEx(hKey2, "DisplayName", 0, NULL, (BYTE *)&skey, &dwSize );
            if(skey[0] == '\0') {
                  dwSize = sizeof( DWORD ) * 1024;
                  retCode = RegQueryValueEx(hKey2, "Display Name", 0, NULL, NULL, &dwSize );
                  retCode = RegQueryValueEx(hKey2, "Display Name", 0, NULL, (BYTE *)&skey, &dwSize );
            }
            if(skey[0] == '\0') {
                  dwSize = sizeof( DWORD ) * 1024;
                  retCode = RegQueryValueEx(hKey2, "QuietDisplayName", 0, NULL, NULL, &dwSize );
                  retCode = RegQueryValueEx(hKey2, "QuietDisplayName", 0, NULL, (BYTE *)&skey, &dwSize );
            }

            strcat(skey, "\0");
            if(skey[0] != '\0'){
                  res->push_back(skey);
            }
            
            RegCloseKey (hKey2);

      }

      RegCloseKey (hKey);
      }
      
I think this illustrates how must of it is being done...
Thanks for the suggestions so far.
s
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 1

Expert Comment

by:bearcrsw
ID: 9805836
A couple of bits which look dubious are

     HRESULT hr = 0;
     int j = 0;
     while(hr != ERROR_NO_MORE_ITEMS) {
          DWORD dwSize = sizeof( DWORD ) * 1024;
          swName[0] = '\0';
          rucucu = RegEnumKeyEx(
                              hKey,         // handle of key to enumerate
                              j,            // index of subkey to enumerate
                              swName,         // address of buffer for subkey name
                              &dwSize,         // address for size of subkey buffer
                              NULL,         // reserved
                              NULL,         // address of buffer for class string
                              0,            // address for size of class buffer
                              NULL          // address for time key last written to
                              );
          keys.push_back(strdup(swName));
          j++;
     }

the swName is pushed onto list even if RegEnumKeyEx failed.
also hr does not ppear to be changed, as rucucu is the return value, also what about errors other than NO_MORE _ITEMS .

also on the

retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                            skey,
                            0,
                            KEY_ALL_ACCESS,
                            &hKey2);

the retVal is  not checked. Which could lead to problems with the RegQueryValueEx
0
 

Author Comment

by:sopppas
ID: 9809462
Hi everyone,

I've got it! Don't really know what was wrong, but it seems to be working now.

this code doen't work:

        CComVariant varName;
      bool bFinished = false;
      while (!bFinished)
      {
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance = 0;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
                  &uNumOfInstances);
      
            if (hrNext == WBEM_S_FALSE || uNumOfInstances == 0) // jit debug often indicated a crash right here
                  bFinished = true;
            else
            {
 (...)

and this does:

bool bFinished = false;
      while (!bFinished)
      {
            // Get the instance
            ULONG uNumOfInstances = 0;
            CComPtr<IWbemClassObject> spInstance;
            HRESULT hrNext = spEnumInst->Next(10000, 1, &spInstance,
            &uNumOfInstances);
 
            if (hrNext == WBEM_S_FALSE)
                  bFinished = true;
            else if (hrNext == WBEM_S_NO_ERROR)
            {

I can't really tell where exactly the error is, but maybe the result is sometimes an error code other than WBEM_S_FALSE, causing the problem.
Anyway, thanks  bearcrsw for the tips (I'm gonna use them anyway), and thanks to everyone else who took the time to respond to this cry for help!

s
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
ID: 11984792
PAQed, with points refunded (500)

Computer101
E-E Admin
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
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.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

758 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now