EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Unicode Build of MsgConnect?

Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.
#8128
Posted: 11/07/2008 16:40:04
by Tim Sullivan (Standard support level)
Joined: 06/25/2008
Posts: 26

Hi,
I'm working on incorporating MsgConnect into a Unicode COM object.
I've built out MC_VC_Full, setting char set to Unicode.
This compiled/linked into my project properly, and worked with SOCKET Transport communication.
However, when I tried to use MMF transport, it threw an access exception on line (522) of MCMMF.cpp:
RFreeMutex = CreateMutex((LPSECURITY_ATTRIBUTES) MUTEX_ALL_ACCESS, false, w);

All my Queue Name, Messenger names were tranferred from TCHAR to CHAR using wcstombs. If I compile MsgConnect with char set to Multi-Byte, MMF works fine.

The only reason Unicode is an issue, is that GetErrorMessage returns TCHAR, which in my Unicode app is defined as wchar, but the MsgConnect library is, by default, compiled so that GetErrorMessage returns char. I'd hoped to resolve this by compiling MsgConnect for full Unicode support.

Any ideas what could be causing this crash/exception in MMF Transport?

Thanks.
#8149
Posted: 11/10/2008 08:06:13
by Eugene Mayevski (EldoS Corp.)

I will check the issue today and will let you know then.


Sincerely yours
Eugene Mayevski
#8156
Posted: 11/11/2008 02:13:20
by Eugene Mayevski (EldoS Corp.)

It appears that the call to

CreateMutexW((LPSECURITY_ATTRIBUTES) MUTEX_ALL_ACCESS, ... )

causes AV. In CreateMutexA the first parameter works fine, also CreateMutexW(NULL, ...) works. I will need to investigate the issue deeper.


Sincerely yours
Eugene Mayevski
#8157
Posted: 11/11/2008 02:27:58
by Eugene Mayevski (EldoS Corp.)

That was a bug in our code, related to Unicode on Win32. The correct code of the function is

Code
void MCMMFSenderThread::SendMessage(void)
{
   MCMessageInfo* Info;
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
   MCEvent *RFreeMutex, *RReplyEvent, *RRequestEvent, *RReceiptEvent;
   int RMMF;
#else
//$ifndef LINUX
   MCHandle HandleArray[2];
   MCHandle RFreeMutex, RReplyEvent, RRequestEvent, RReceiptEvent;
   MCHandle RMMF;
//$endif
#endif
   MCMMFHeader* RMMFPtr;

   char* DMessenger;
   long i;
   //char* AQueue;
   __int64 StartTime, EndTime;
   unsigned long ToWait;
   char* p;
   __int64 GTC;
   MCStream* AStream = NULL;

   Info = NULL;
   FOwner->FCriticalSection->Enter();
   TRY_BLOCK
    {
        for(i = 0;i <= FOwner->FOutgoingQueue->Length() - 1;i++)
      {
         MCMessageState aState = ((MCMessageInfo*)((*FOwner->FOutgoingQueue)[i]))->State;
         if(aState == imsDispatching || aState == imsComplete || aState == imsFailed)
         {
            Info = (MCMessageInfo*)((*FOwner->FOutgoingQueue)[i]);
            FOwner->FOutgoingQueue->Del(i);
            break;
         }
      }
   } FINALLY (
      FOwner->FCriticalSection->Leave();
   )
  
   if(!Info)
      return;
  
   FSendingInfo = Info;
   
   //   AQueue = Pstr2c(Info->DQueue);
   //   AQueue = strdup(Info->DQueue);
      DMessenger = Info->DMessenger;
      // get destination messenger name
      if(!DMessenger)
      {
         Info->MCError = MCError_GenTransportFailure;
         FOwner->DeliveryFailed(Info);
         FSendingInfo = NULL;
         return;
      }
  
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
      char* ttmpdir = getenv("TEMP");
      char tmpdir[1024];
      if(ttmpdir)
      {
         strcpy(tmpdir, ttmpdir);
         strcat(tmpdir, "/");
      }
      else
         strcpy(tmpdir, "/tmp/");
      p = (char*)MCMemAlloc(strlen(tmpdir) + strlen(DMessenger) + strlen("_Mapping") + 1);
      strcpy(p, tmpdir);
      strcat(p, DMessenger);
      strcat(p, "_Mapping");
      RMMF = open(p, O_RDWR|O_SYNC, DEFFILEMODE);
      MCMemFree(p);
      if(RMMF < 0)
#else
//$ifndef LINUX
      p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_Mapping") + 1);
      strcpy(p, DMessenger);
      strcat(p, "_Mapping");
#if defined(_WIN32_WCE) || defined(UNICODE)
      wchar_t* w = s2w(p);
#ifndef _WIN32_WCE
      RMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, w);
      delete w;
#else
      SetLastError(0);
      RMMF = CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
         strlen(Info->SMessenger) + 4 + sizeof(Info) + Info->Message.DataSize, w);
      delete w;
      if(GetLastError() != ERROR_ALREADY_EXISTS)
      {
         CloseHandle(RMMF);
         RMMF = 0;
      }
#endif
#else
      RMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, p);
#endif
      MCMemFree(p);
      if(RMMF == 0)
//$endif
#endif
      {
         Info->MCError = MCError_GenTransportFailure;
         FOwner->DeliveryFailed(Info);
         FSendingInfo = NULL;
         return;
      }

#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
      RMMFPtr = (MCMMFHeader*)mmap(0, MMF_FRAME_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, RMMF, 0);
      if(-1 == (long) RMMFPtr)
#else
//$ifndef LINUX
      RMMFPtr = (MCMMFHeader*)MapViewOfFile(RMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0);
      if(!RMMFPtr)
//$endif
#endif
      {
         Info->MCError = MCError_GenTransportFailure;
         FOwner->DeliveryFailed(Info);
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
         close(RMMF);
#else
//$ifndef LINUX
         CloseHandle(RMMF);
//$endif
#endif
         FSendingInfo = NULL;
         return;
      }

      // create necessary events
      RFreeMutex = NULL;
      RReceiptEvent = NULL;
      RRequestEvent = NULL;
      RReplyEvent = NULL;

      TRY_BLOCK
      {
         TRY_BLOCK
         {
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_MMFFreeMutex") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_MMFFreeMutex");
            RFreeMutex      = new MCEvent(NULL, false, false, p, true);
               MCMemFree(p);

            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_ReceiptEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_ReceiptEvent");
            RReceiptEvent   = new MCEvent(NULL, false, false, p, true);
            MCMemFree(p);

            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_RequestEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_RequestEvent");
            RRequestEvent   = new MCEvent(NULL, false, false, p, true);
            MCMemFree(p);

            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_ReplyEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_ReplyEvent");
            RReplyEvent      = new MCEvent(NULL, false, false, p, true);
            MCMemFree(p);
#else
//$ifndef LINUX
            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_MMFFreeMutex") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_MMFFreeMutex");
#if defined(_WIN32_WCE) || defined(UNICODE)
            LPCTSTR w = s2w(p);
#if defined(_WIN32_WCE)
            RFreeMutex = CreateMutex(NULL, false, w);
#else
            RFreeMutex = OpenMutex(MUTEX_ALL_ACCESS, false, w);
#endif
            
            delete (void*)w;
#else
            RFreeMutex = OpenMutex(MUTEX_ALL_ACCESS, false, p);
#endif
            MCMemFree(p);
            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_ReceiptEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_ReceiptEvent");
#if defined(_WIN32_WCE) || defined(UNICODE)
            w = s2w(p);
            RReceiptEvent = OpenEvent(EVENT_ALL_ACCESS, false, w);
            delete (void*)w;
#else
            RReceiptEvent = OpenEvent(EVENT_ALL_ACCESS, false, p);
#endif
            MCMemFree(p);
            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_RequestEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_RequestEvent");
#if defined(_WIN32_WCE) || defined(UNICODE)
            w = s2w(p);
            RRequestEvent = OpenEvent(EVENT_ALL_ACCESS, false, w);
            delete (void*)w;
#else
            RRequestEvent = OpenEvent(EVENT_ALL_ACCESS, false, p);
#endif
            MCMemFree(p);
            p = (char*)MCMemAlloc(strlen(DMessenger) + strlen("_ReplyEvent") + 1);
            strcpy(p, DMessenger);
            strcat(p, "_ReplyEvent");
#if defined(_WIN32_WCE) || defined(UNICODE)
            w = s2w(p);
            RReplyEvent = OpenEvent(EVENT_ALL_ACCESS, false, w);
            delete (void*)w;
#else
            RReplyEvent = OpenEvent(EVENT_ALL_ACCESS, false, p);
#endif
            MCMemFree(p);
//$endif
#endif

            if((RFreeMutex == 0) ||
               (RReceiptEvent == 0) ||
               (RRequestEvent == 0) ||
               (RReplyEvent == 0))
               THROW_ERROR(MCError_GenTransportFailure);
  
            // write transferrable data to the buffer
            AStream = new MCMemStream();
            i = strlen(Info->SMessenger);
            if(i > 0)
               AStream->Write(&i, sizeof(i));
  
            AStream->Write(Info->SMessenger, i);
            Info->WriteToStream(AStream);
            if(Info->Message.DataSize > 0)
               AStream->Write((char*)(Info->Message.Data), Info->Message.DataSize);
            AStream->SetPos(0);
  
            // initialize time counters
            StartTime = GetTickCount();
            ToWait = FOwner->getMaxTimeout();
            EndTime = StartTime + ToWait;
   
            if (FCancelID != Info->Message.MsgID)
            {

#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
               long l_wait = ToWait*100;
               while(true)
               {
                  if(FStopEvent->WaitFor(0) == wrSignaled)
                     throw EMCError(MCError_TransportTimeout);
                  if(RFreeMutex->WaitFor(0) == wrSignaled)
                     break;
                  Sleep(10);
                  l_wait--;
                  if(l_wait == 0)
                  {
                     printf("timeout when waiting for signal\n");
                     throw EMCError(MCError_TransportTimeout);
                  }
               }
#else
//$ifndef LINUX
               HandleArray[0] = FStopEvent->getHandle();
               HandleArray[1] = RFreeMutex;
               i = WaitForMultipleObjects(2, HandleArray, false, ToWait);
               if((i == (long)WAIT_OBJECT_0) || (i == (long)WAIT_TIMEOUT))
                  THROW_ERROR(MCError_TransportTimeout);
//$endif
#endif
  
               // begin transfer operation
               RMMFPtr->dwDataSize = AStream->Len();
  
               while(AStream->Pos() < AStream->Len())
               {
                  RMMFPtr->bIsFirst = AStream->Pos() == 0;
                  RMMFPtr->dwErrorCode = 0;
                  RMMFPtr->dwBlockStart = AStream->Pos();
                  if((RMMFPtr->dwMMFSize - sizeof(MCMMFHeader)) < (unsigned long)(AStream->Len() - AStream->Pos()))
                     RMMFPtr->dwBlockSize = RMMFPtr->dwMMFSize - sizeof(MCMMFHeader);
                  else
                     RMMFPtr->dwBlockSize = AStream->Len() - AStream->Pos();
  
                  p = (char*)&RMMFPtr->dwBlockSize;
                  p += 4;
                  AStream->Read(p, RMMFPtr->dwBlockSize);
  
                  // flag the availability of the data
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
                  msync(RMMFPtr, MMF_FRAME_SIZE, MS_SYNC);
                  RRequestEvent->setEvent();
#else
//$ifndef LINUX
                  SetEvent(RRequestEvent);
//$endif
#endif
  
                  GTC = GetTickCount();
                  if(GTC < StartTime)
#if defined(__GNUC__)
                     GTC = GTC + 0x100000000ll;
#else
//$ifndef LINUX
                     GTC = GTC + 0x100000000l;
//$endif
#endif
                  if((GTC > EndTime) && (ToWait != INFINITE))
                     THROW_ERROR(MCError_TransportTimeout);
                  
                  if(ToWait != INFINITE)
#if !defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW64__)
//$ifndef LINUX
                     ToWait = (unsigned long)(EndTime - (__int64)GTC);
//$endif
#else
                     ToWait = EndTime - GTC;
#endif

#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
                  long l_wait = ToWait*100;
                  while(true)
                  {
                     if(FStopEvent->WaitFor(0) == wrSignaled)
                        throw EMCError(MCError_TransportTimeout);
                     if(RReplyEvent->WaitFor(0) == wrSignaled)
                        break;
                     Sleep(10);
                     l_wait--;
                     if(l_wait == 0)
                     {
                        printf("timeout when waiting for signal\n");
                        throw EMCError(MCError_TransportTimeout);
                     }
                  }
#else
//$ifndef LINUX
                  HandleArray[0] = FStopEvent->getHandle();
                  HandleArray[1] = RReplyEvent;
                  if(WaitForMultipleObjects(2, HandleArray, false, ToWait) != (WAIT_OBJECT_0 + 1))
                     THROW_ERROR(MCError_TransportTimeout);
                  //ResetEvent(RReplyEvent);
//$endif
#endif
                  if(AStream->Pos() < AStream->Len())
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
                     RReceiptEvent->setEvent();
#else
//$ifndef LINUX
                     SetEvent(RReceiptEvent);
//$endif
#endif
               }

               if((Info->State == imsDispatching) && Info->IsSendMsg && (Info->Message.MsgID != FCancelID))
               {
                  FOwner->FCriticalSection->Enter();
                  TRY_BLOCK
                  {
                     Info->State = imsWaiting;
                     FOwner->FOutgoingQueue->Add(Info);
                  } FINALLY (
                     FOwner->FCriticalSection->Leave();
                  )
               }
               else
               {
                  if (Info->Message.MsgID != FCancelID)
                  {
                     delete Info;
                     Info = NULL; //MCMessenger::DestroyMessageInfo(Info);
                  }
               }
            }
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
            RReceiptEvent->setEvent();
            RFreeMutex->setEvent();
#else
//$ifndef LINUX
            SetEvent(RReceiptEvent);
            ReleaseMutex(RFreeMutex);
//$endif
#endif
#ifdef USE_CPPEXCEPTIONS
         } catch(EMCError* E) {
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
            RFreeMutex->setEvent();
#else
//$ifndef LINUX
            ReleaseMutex(RFreeMutex);
//$endif
#endif
            Info->MCError = E->ErrorCode();
            FOwner->DeliveryFailed(Info);
   //         return;
         }
#else
         } __except(1) {
            ReleaseMutex(RFreeMutex);
            Info->MCError = _exception_code();
            FOwner->DeliveryFailed(Info);
   //         return;
         }
#endif
        
#if defined(__GNUC__) && !(defined(__MINGW32__) || defined(__MINGW64__))
      }
      FINALLY
      (
         delete AStream;
         munmap(RMMFPtr, MMF_FRAME_SIZE);
         close(RMMF);
         delete RFreeMutex;
         delete RReceiptEvent;
         delete RRequestEvent;
         delete RReplyEvent;
      )
#else
//$ifndef LINUX
      } FINALLY (
         delete AStream;
         UnmapViewOfFile(RMMFPtr);
         CloseHandle(RMMF);
         CloseHandle(RFreeMutex);
         CloseHandle(RReceiptEvent);
         CloseHandle(RRequestEvent);
         CloseHandle(RReplyEvent);
      )
//$endif
#endif
}


Sincerely yours
Eugene Mayevski

Reply

Statistics

Topic viewed 3295 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!