Posts Tagged ‘Win32’

Unexpected behavior of Win32 when checking serial ports.

I recently noticed very interesting behavior in ClearCommError() function of Win32.
This code returns how many bytes there are in incoming buffer for a serial port.

DWORD CSerialPort::BytesWaiting()
{
  //Validate our parameters
  ASSERT(IsOpen());

  //Check to see how many characters are unread
  COMSTAT stat;
  GetStatus(stat);
  return stat.cbInQue;
}

void CSerialPort::GetStatus(COMSTAT& stat)
{
  //Validate our parameters
  ASSERT(IsOpen());

  DWORD dwErrors;
  if (!ClearCommError(m_hComm, &dwErrors, &stat))
  {
    DWORD dwLastError = GetLastError();
    TRACE(_T("CSerialPort::GetStatus, Failed in call to ClearCommError, Error:%d\n"), dwLastError);
    ThrowSerialException(dwLastError);
  }
}

However, after actually debugging it I found out that there are cases where

  • The number of bytes in its incoming buffer doesn’t increase while it is calling BytesWaiting() to see if it received enough bytes to read. Then, it should read its incoming buffer for the given COM port to have BytesWaiting() starts to return accumulated number of bytes after reading.
  • When BytesWaiting() returns 0, you still need to read the buffer not to fail in detecting any further data arrived from the other side of communication. reading 0 bytes in this case, will cause the BytesWaiting() keeps returning the number of bytes read after that point.

Normally, whether you read or not, callying BytesWaiting() correctly reports the number of bytes in an incoming buffer.
However, if any of those listed above happens, it stops reporting correct number of bytes.

So, this code fails.

int CLensControllerDlg::ReadIncomingPacket(BYTE incomingBuffer[], int numOfBytesToRead, bool *pShouldGiveUp)
{
     DWORD bytesInReceptionQueue;
     int readNumOfBytes, extraReadNumOfBytes;

     readNumOfBytes = extraReadNumOfBytes = 0;

     // First read
     readNumOfBytes = m_pSerialPort->Read( incomingBuffer, numOfBytesToRead );
     int lengthToReadFurther;
     int secondTryReadLength = 0;

     static int trialCount = 0;

     // Check if it needs to read once more
     if( (incomingBuffer[ 0] == (BYTE) 0x50) &&
           (incomingBuffer[ 1] == (BYTE) 0xAF ))
     {
           lengthToReadFurther = static_cast<int >(incomingBuffer[4]) + 1; // payload length + check sum
            // Read length + 1 more ( 1 is for checksum )

            //!!!!! [1] !!!!!
            // There are cases where bytesInReceptionQueue doesn't have accumulated number of
            // bytes in a reception bufffer.
            while( (bytesInReceptionQueue = m_pSerialPort->BytesWaiting()) < lengthToReadFurther )
           {
                Sleep( 3 ); // 10 msec
                trialCount++;

                //!!!!! [2] !!!!!
                // So, if the bytesInReceptionQueue doesn't contain the accumulated number of bytes
                // through the iteration, try to read some.
                // Then it will start to work again.
                 if( trialCount > 10 )
                {
                      if( bytesInReceptionQueue > 0 )
                     {
                            // Give another chance
                           secondTryReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                           readNumOfBytes += secondTryReadLength;

                           lengthToReadFurther -= secondTryReadLength;

                           trialCount = 0;

                     }
                      else
                     {
                            // let's see what it happens if try reading for 0 bytes and read further
                           BYTE temp[ 16];
                            int tempReadLength;

                            // bytesInReceptionQueue == 0
                           tempReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                           readNumOfBytes += tempReadLength;
                           lengthToReadFurther -= tempReadLength;

                            //// Once read, somehow, bytesInReceptionQueue starts to be accumulated again.
                            //bytesInReceptionQueue = m_pSerialPort->BytesWaiting();

                            //tempReadLength = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], bytesInReceptionQueue );
                            //readNumOfBytes += tempReadLength;
                            //lengthToReadFurther -= tempReadLength;

                           CString msgString;
                           msgString.Format( _T( ">> Will give up this incoming data : %x %x %x %x %x\r\n"),
                                                  incomingBuffer[0], incomingBuffer[1 ],
                                                  incomingBuffer[2], incomingBuffer[3 ],
                                                  incomingBuffer[4] );

                           WriteLogMessage( msgString );
                           TRACE( msgString );

                            if( pShouldGiveUp != NULL )
                           {
                                *pShouldGiveUp = true;
                           }

                           trialCount = 0;
                            return 0;
                     }
                }
           }

            // In the queue, now there are lengthToReadFurther or more to read.
           extraReadNumOfBytes = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], lengthToReadFurther );
     }

     return (readNumOfBytes + extraReadNumOfBytes);
}

The code above was written while I was debugging. So, it’s not clean nor compact.
So, here is better version if you want to see.

int CLensControllerDlg::ReadIncomingPacket(BYTE incomingBuffer[], int numOfBytesToRead, bool *pShouldGiveUp)
{
     DWORD bytesInReceptionQueue;
     int readNumOfBytes, extraReadNumOfBytes;

     readNumOfBytes = extraReadNumOfBytes = 0;

     // First read
     readNumOfBytes = m_pSerialPort->Read( incomingBuffer, numOfBytesToRead );
     int lengthToReadFurther;
     int secondTryReadNumOfBytes = 0;

     // Check if it needs to read once more
     if( (incomingBuffer[0] == (BYTE)0x50) &&
          (incomingBuffer[1] == (BYTE)0xAF ))
     {
          lengthToReadFurther = static_cast<int>(incomingBuffer[4]) + 1; // payload length + check sum
          // Read length + 1 more ( 1 is for checksum )
          while( lengthToReadFurther > 0 )
          {
               Sleep( 1 ); // 10 msec

               bytesInReceptionQueue = m_pSerialPort->BytesWaiting();

               // If it's normal, just waiting until bytesInReceptionQueue >= lengthToReadFurther,
               // and read the whole "lengthToReadFurther" amount of data all at once.
               //
               // However, sometimes the inbound buffer should be read to have further data accumulated.
               // If not,
               secondTryReadNumOfBytes = m_pSerialPort->Read( &incomingBuffer[readNumOfBytes], lengthToReadFurther );
               readNumOfBytes += secondTryReadNumOfBytes;

               lengthToReadFurther -= secondTryReadNumOfBytes;
          }
     }

     return readNumOfBytes;
}

LCD screen brightness control for MacBook with Intel GMA X3100 chipset

In my previous post, The Strange DeviceIoControl result with IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, I said that query LCD screen as described in MSDN document didn’t work. Today I found out the reason. To tell the truth, I use a MacBook 13″ White with Intel GMA 950 chipset for the graphics component. So, the Windos 7 x64 couldn’t find a proper device driver for the built-in LCD screen and just installed Generic PnP display driver.

When a proper device driver is installed, it registers its device name. However, in the “Generic PnP display” driver case, it doesn’t register itself as “LCD”. So, the CreateFile() can’t create a handle to an LCD screen with that device name.

Then, what is a proper name for the unregistered device? It is not documented in any MSDN document. However, with help of querydosdevice program, I could find out the device name.

This is the device name.

So, in a source code, you will access the unregistered device like this.

// 1. Query the Backlight supported device
// IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS s
HANDLE hLCDScreen;
hLCDScreen = CreateFile( _T("\\\\.\\DISPLAY#APP9C5F#4&30ca27f4&0&UID67568640#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"), GENERIC_READ,			// No access to the drive 
						FILE_SHARE_READ | FILE_SHARE_WRITE,	// share mode
						NULL,								// default security attributes
						OPEN_EXISTING,						// Disposition
						0,
						NULL );
if( hLCDScreen == INVALID_HANDLE_VALUE )
{
	dwError = GetLastError();
	TRACE1( "CreateFile() error(%d)\n", dwError );

	return;
}

However, the Generic PnP Display driver doesn’t support brightness level. So, I couldn’t write any more codes to control the brightness.

Can anyone tell me what chipset MacBook with Intel GMA 940 uses for LCD screen? or tell me where I can find a proper device driver?

CreateEx() and Create() for CDockablePane

Historically CreateEx() has been thought as Create() with additional functionality like more styles.
So, if you take a look at many MFC classes which provide CreateEx() and Create(), you can see that CreateEx() calls Create() and do more chores to provide added functionality.

However, I found out that CDockablePane’s doesn’t.
Although MSDN document shows that there is CreateEx() for CDockablePane, it actually doesn’t exist.
So, you shouldn’t be fooled by the MSDN document and create CDockablePane with CreateEx() and wonder why it doesn’t work.

Storing a pointer value in a non-pointer variable vs. Storing general value in a pointer variable : INT_PTR, LONG_PTR etc vs. MAKEINTRESOURCE

If you are a programmer who studied C/C++ after Windows 95, you may not know the existence of windows data types like INT_PTR, LONG_PTR, because you don’t really need to use it.

So, when you have a chance to port legacy codes to x64 platform, you may  fail in considering proper porting of variables declared with those or variables which don’t use them but semantically means the same.

At StackOverFlow, there is good explanation on this subject.

DWORD_PTR, INT_PTR, LONG_PTR, UINT_PTR, ULONG_PTR When, How and Why?

However, I would like to add more comment.

During MS DOS era, many programmers wrote codes in a way that the longest data type available on his/her machine to store addresses or pointer values. There were a little reason for that. For example, you want to do somewhat mathematical calculation with addresses without bordering with the width of the data type.
To me, it has been always better to calculate on addresses with the width of data type in mind, but there are some other cases you should have disregard the width of data type and just calculate something. It was kind of high technique for doing something weird. ( Some can be, while others are not. )

Some Windows API functions and member functions still require to use such convention. They ask you to pass address value to a variable which is not pointer variables. For that purpose, they use *_PTR.

So, I noticed that not a few programmers, who don’t know history, tended to fail in porting legacy code to x64.

Also, there is opposite example.
This time, it is to store non-pointer value to a pointer variable. Such an example is MAKEINTRESOURCE() macro.

#define MAKEINTRESOURCE(i)(LPTSTR)((DWORD)((WORD)(i)))

So, it takes an integer number for a resource like resource ID for a bitmap or an icon, and converts it to pointer to string (LPTSTR).

So, if you are one of new guys who don’t know its history, just get familiar with this and don’t be puzzled!

LoadLibrary() can’t load a DLL, and have no clue why?

How do you link or load a DLL file?
My approach is to link a stub *.lib file to a host project. This approach supports best of dynamic load and static load. In other words, each DLL files can be maintained independently, while it is very easy to figure out what functions are not found properly and what functions are in conflict, etc.

However, if you really want to write a host program which can support plug-ins such that each plug-ins can be dropped in a given folder and the host program recognize the plug-in on the fly and starts to provide functionality defined in the plug-ins, you will want more dynamic approach.

Yes. MFC/Win32 provides such approach. With LoadLibrary(), anywhere in your source codes, DLL files can be loaded. Then you can define some common interface/parent class for pluggable architecture.
Neat, isn’t it?
However, there is one problem with LoadLibrary(). It can be difficult to troubleshoot. For example, if your DLL file can’t be loaded, you will check if the search path is correct, if the DLL file is really there, and so on. However, what if all those which affect visibility of the DLL are satisfied but the LoadLibrary() still fails?

Let’s take a look at such codes here.

// JongAm
// Let's try loading "Mediabase.dll". Why the hell WBMediabase started failing in finding the dll?

// Enable the line below to see what is wrong with LoadLibrary()
//SetErrorMode( 0 );

HMODULE dynamicLibrary_Handle = LoadLibrary( _T("MediaBase.dll") );

if( dynamicLibrary_Handle )
{
	AfxMessageBox( _T("Successful in finding Mediabase.dll") );
	TRACE( "Successful\n" );
}
else
{
	int lastError = GetLastError();

	CString message;
	message.Format( _T("Failed in finding Mediabase.dll (%d)"), lastError );
	AfxMessageBox( message );

	TRACE( "Can't find the mediabase.dll\n" );
}

Nothing special, right? However, it failed on me. Why? Later I found out that MediaBase.dll also required other DLL files, and those DLL files also require other DLLs. They are all loaded using LoadLibrary() functions. So, they were not detected with Dependency Walker. Hmmmm….
So, whenever you write LoadLibrary(), it is better to provide some feedback message when it fails loading DLL files like “Failed in loading Blah Blah.dll”.

However, what if you already have a few 3rd parth DLL files which you can’t control?
In such case, there is a really handy diagnosis function. It is the SetErrorMode(). If 0 is passed as its parameter, it will display a message box which tells what is wrong, like “X.dll is missing”.
So, for example, when you load a A.dll using LoadLibrary() but the A.dll also load A-1.dll and the A-1.dll loads A-2.dll and the A-2.dll is missing, the SetErrorMode(0) will make a message box which says “A-2.dll is missing” displayed.

Here are a few screenshots.

When a DLL file required by the designated Mediabase.dll is missing

When the designated DLL file, Mediabase.dll, itself can't be found.

When all DLL file dependency are resolved

Wow.. quite helpful, isn’t it?

Visual C++ 2008 resource editing and control variable annoyance

Hmmm.. It was strange that VC++ 2008 add variables wizard didn’t let a “value” variable of a radio button. With VC++ 6, it was possible as far as I remember.

So, I searched to find out what changed since VC++ 6.

What I found are :

However, the most official document is :
Grouping Radio Buttons on a Dialog Box

People are confused by the different way of setting variable for a radio button to they way you do with its previous version, and MS didn’t seem to present “What is changed and How is changed” document.

So, the way it manipulate resources was changed. No, problem. However again MS’s approach shows problems.

  1. In the resource editor, there is no way to group radio boxes visually
  2. Because only one radio buttons is to be turned on exclusively in its group, there should be a visual way to make a series of radio buttons grouped. However, a group is defined by setting the order of radio buttons in series and only the first radio button is flagged as “Group”.

  3. Setting only the first radio button as “Grouped” is not reasonable.
  4. Basically there are multiple radio buttons in a group. Then all should be “grouped”. But MS want you to set only the 1st radio button as “grouped”. Then all the following radio buttons are grouped. It doesn’t feel natural.

  5. Setting the variable to the first radio button
  6. So, a variable for a group should be declared for the group. But a variable for the 1st button is declared and treated like that it is the representative button for the group.

All of them don’t look natural and reasonable.

I think this is why people get confused and couldn’t get a clue on how to make set a variable for radio buttons.

Debugging a release build with the Visual C++ 2005

Sometimes debug build doesn’t crash but release build crashes. This usually happens when memory area which is not valid is accessed. Debug build usually has some fence around allocated memory area.

However, recently I suffered somewhat different case. In this case, you need to debug a release build.
Yeah.. It is quite easy. Just enable debug information for a release build. However, in my recent case, doing so didn’t reveal symbols or display correct values for variables.
At first, I thought a stack is corrupted. However, I found out that optimization option did affect the symptom.

So, disabling optimization was the solution to check content of variables.
coptimization

The cause of the crash was due to #pragma pack.
In one of its header file, #pragma pack (push, 1) is used, and at the end of the file #pragma pack(pop, 1).
It should have been #pragma pack(pop) to reverting.

So, in a influenced class implementation file, it used correct alignment, while in other source file which included a troubled header file, the alignment of this class is not interpreted as it should have been.
So, it caused a vtable evasion in a source file which includes the troubled header file. Therefore, it crashed when it called one of the method of the influenced class.

It is strange that this didn’t cause problem with a debug build. There is not explanation on the MSDN site whether this is disabled in debug build or not.

%d bloggers like this: