Serial Communication in Windows

Environment:

Source code

This article is meant to give you a jump start on doing serial communication in Windows (NT family). The article will provide a class called CSerialCommHelper that you can use directly to do serial communication in your application. The class that is provided here with this article does uses overlapped IO. You do not need to know much about serial communication or overlapped IO for this article. However, you need to know some about the synchronization objects such as Events and some Windows APIs like WaitForSingleObject and WaitForMultipleObject, and so forth. Also, some basic understanding of Windows threads is required—such as thread creation and termination.

Introduction

In order for your computer to do serial communication, the computer has to have a serial port. Most computers have at least one serial port, also known as a COM port (communication port), and are generally called COM1, COM2, and so on. Then there are the device drivers for the serial ports. If you think it over, all that you need to do in serial communication is either send data or receive data. In other words, you are doing input/output (IO) to the serial port. The same IO is done with disk-based files. Hence it is no surprise that the APIs for reading and writing to a file apply to serial ports as well. When you send data to the serial port, it's in terms of bytes but when it leaves the serial port it is in the form of bits. Similarly, when the data arrives at the serial port, it's in bit format and when you get data you get it in bytes.

Without any further discussion, let's get started.

Opening the COM Port

The first and the foremost step in doing a serial communication is to open the desired port. Let's say you have your device hooked to COM1; you can open the COM port using the following API:

HANDLE m_hCommPort = ::CreateFile( szPortName,
       GENERIC_READ|GENERIC_WRITE,  // access ( read and write)
       0,                           // (share) 0:cannot share the
                                    // COM port
       0,                           // security  (None)
       OPEN_EXISTING,               // creation : open_existing
       FILE_FLAG_OVERLAPPED,        // we want overlapped operation
       0                            // no templates file for
                                    // COM port...
       );

The third, fifth, and seventh parameters have to be what they are in the above example, by law. We want to open the file (the COM port) in an overlapped fashion—that's why the sixth parameter is FILE_FLAG_OVERLAPPED. We will get into the details of overlapped IO a bit later. As you must have guessed from the name, the CreateFile() API can be used to create a file (disk-based); it also can be used to open an existing file.

To Windows, a serial port or a disk-based file both are IO devices. So, to open an existing file (serial port), all we need to know the name of the device (COM1) and pass the creation flags as OPEN_EXISTING.

If a COM port is opened successfully, the API returns the handle to the COM port just like a handle to a file. However, if the system could not open the COM port, it would return INVALID_HANDLE_VALUE. And you can get the reason by calling GetLastError(). One of the common errors when opening a COM port is that the COM port is already opened by some other application; in that case, you would get ERROR_ACCESS_DENIED (5). Similarly, if you mistakenly opened a COM port that does not exist , you would get ERROR_FILE_NOT_FOUND as the last error.

Note: Remember not to make any function calls (such as ASSERT) before calling GetLastError() or you would get 0.
After you have opened the COM port, all you need to do now is to start using it.

Reading and Writing

Now, when you have a COM port open, you may want to send some data to the connected device. For example, let's say you want to send "Hello" to the device (for example, another PC). When you want to send the data across the serial port, you need to write to the serial port just as you would write to a file. You would use following API:

iRet = WriteFile (m_hCommPort,data,dwSize,&dwBytesWritten ,&ov);

where data contains "Hello".

Let's say that, in response to your "Hello", the device sends you "Hi". So, you need to read the data. Again, you would use the following API:

abRet = ::ReadFile(m_hCommPort,szTmp ,sizeof(szTmp ),&dwBytesRead,&ovRead) ;

For now, do not try to understand everything. We will get to all this later. All this sounds very simple. Right?
Now, let's start digging into issues.

Issues with Serial Communication

Just now I said that, in response to your "Hello", the device may send you "Hi" back and you would like to read that. But the problem here is that you don't know when the device is going to respond. Or, will it ever respond? When should you start to read from the port? One option is that as soon as you made the call to WriteFile, you make a call to ReadFile. If no data is there, you need to make a read call again, later on. This leads to what is called polling. You keep polling the port for data. This model does not really seem to be a good one. It would be nice if somehow the system notified you when data has arrived and only then would you make a call to ReadFile. This is an event-driven approach and fits well into Windows programming. And the good news is that such a model is possible.

Another issue with the serial communication is that because it always occurs between two devices, the two devices need to agree on how they talk to each other. Each side needs to follow certain protocols to conduct business. Because it's the serial port that actually carries out the communication, we need to configure the serial port. There is an API available for that exact same purpose. Following is the API:

SetCommState ( HANDLE hFile, LPDCB lpDCB)

The first parameter is the handle to the COM port and the second parameter is what is called a device control block (DCB) . The DCB is a struct defined in winbase.h and has 28 data members. For example, we need to specify the baud rate at which the COM port operates; you need to set the BaudRate member of the struct. Baud rate is usually 9600 (bps). But the two devices have to use the same baud rate to conduct business. Similarly, if you want to use parity you need to set the Parity member of the struct. Again, the two devices have to use same parity. Some of the data members are reserved and have to be 0. I have found it easier to get the current DCB struct and then set those members that we are interested in changing. The following code gets the current DCB and sets some of the fields:

DCB dcb = {0};
dcb.DCBlength = sizeof(DCB);

if (!::GetCommState (m_hCommPort,&dcb))
{
  TRACE ( "CSerialCommHelper : Failed to Get Comm State Reason:
    %d",GetLastError());
  return E_FAIL;
}

dcb.BaudRate  = dwBaudRate;
dcb.ByteSize  = byByteSize;
dcb.Parity    = byParity;
if ( byStopBits == 1 )
  dcb.StopBits  = ONESTOPBIT;
else if (byStopBits == 2 )
  dcb.StopBits  = TWOSTOPBITS;
else 
  dcb.StopBits  = ONE5STOPBITS;


if (!::SetCommState (m_hCommPort,&dcb))
{
  ASSERT(0);
  TRACE ( "CSerialCommHelper : Failed to Set Comm State Reason:
    %d",GetLastError());
  return E_FAIL;
}
TRACE ( "CSerialCommHelper : Current Settings, (Baud Rate %d;
  Parity %d; Byte Size %d; Stop Bits %d", dcb.BaudRate,

Most of the time you won't need to change the other fields of this structure. But if you need to change the structure, you need to be very careful about the fields because changing the fields will affect the behavior of the serial communication; hence, you should be very sure about what you want to change.

Event-Driven Approach

Let's return to our earlier problem with reading the data. If we do not want to keep polling the COM port for any data, we need to have some kind of event mechanism available. Fortunately, there is a way that you can ask the system to notify you when certain events happen. The API to use is:

SetCommMask( HANDLE hHandle,DWORD dwEvtMask)

The first parameter is the handle to the open COM port. The second parameter is used to specify a list of events that we are interested in.

The events that need to be specified in the mask depend upon the application needs. For simplicity, let's say that we are interested in getting notified whenever a character arrives at the serial port. We would need to specify EV_RXCHAR as the event mask. Similarly, if we are interested in knowing when all the data has been sent, we also need to specify the EV_TXEMPTY flag. So, our call would look like this:

SetCommMask( m_hCommPort,EV_TXTEMPTY|EV_RXCHAR);

The interesting thing here is that, although we told the system about the events of our interest, we did not, however, tell the system what to do when these events occur. How would the system let us know that a particular event occurred? An obvious thing seems to be a callback mechanism. But there is no such mechanism available. Here is when things get a little tricky. In order for the system to let us know about the communication event occurrence, we need to call WaitCommEvent This function waits for the events specified in SetCommMask. But if you think a little more, it sounds like we are turning a notification mechanism back to a polling mechanism. Actually, it's even worse that than. WaitCommEvent blocks until an event occurs. So what's the use of WaitCommEvent? Well, the answer lies in overlapped IO.

If you look at the WaitCommEvent signature, it looks like this:

BOOL WaitCommEvent(HANDLE hCommPort, LPDWORD dwEvtMask,LPOVERLAPPED
  lpOverlapped);

The third parameter is the key here.

Think of overlapped IO as asynchronous IO. Whenever a function makes a call and specifies the overlapped IO structure, it means that it is trying to do the current operation but, if you are not able to complete it immediately, let me know when you are done with this IO. The way the system lets you know about the completion is by setting a kernel event object that is part of the lpOverlapped structure. So, all you do is spawn a thread and make the thread wait for that event object using one of the WaitForSingleObject() APIs.

Let's look at the overlapped structure:

typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;

The last parameter is the event handle that you need to create. This event is generally a manual reset event. When you make a call like WaitCommEvent(), passing the overlapped structure as the last parameter, and the system could not complete the call—meaning it did not see any characters at the port—it would return immediately but would return FALSE. If you now make a call to GetLastError(), you would get ERROR_IO_PENDING; this means that the call has been accepted but no characters have yet arrived at the COM port. Also it means that whenever the characters arrive, the system will set the hEvent of the overlapped structure that you passed in. So, if your thread would wait for a single object on hEvent and you pass INFINITE, whenever your Wait function returns WAIT_OBJECT_0, it means that some character has arrived or all the data in the output buffer has been sent.

In our current case, we are interested in more than one event; we would need to check what event we did get by making a call to GetCommMask and checking the dword against each event. The following pseudo code will explain it.

You can read the data from the COM port, reset the event, and make the call to WaitCommEvent again, and so on.

unsigned __stdcall CSerialCommHelper::ThreadFn(void*pvParam)
{
  OVERLAPPED ov;
  memset(&ov,0,sizeof(ov));
  ov.hEvent = CreateEvent( 0,true,0,0);
  HANDLE arHandles[2];
  arHandles[0] = apThis->m_hThreadTerm;

  DWORD dwWait;
  SetEvent(apThis->m_hThreadStarted);
  while (  abContinue )
  {

    BOOL abRet = ::WaitCommEvent(apThis->m_hCommPort,
        &dwEventMask, &ov) ;
    if ( !abRet )
    {

      ASSERT( GetLastError () == ERROR_IO_PENDING);
    }


    arHandles[1] = ov.hEvent ;

    dwWait = WaitForMultipleObjects (2,arHandles,FALSE,INFINITE);
    switch ( dwWait )
    {
    case WAIT_OBJECT_0:
      {
        _endthreadex(1);
      }
      break;
    case WAIT_OBJECT_0 + 1:
      {
        DWORD dwMask;
        if (GetCommMask(apThis->m_hCommPort,&dwMask) )
        {
          if ( dwMask & EV_TXEMPTY )
          TRACE("Data sent");
          ResetEvent ( ov.hEvent );
          continue;
        }
        else
        {
          //read data here and reset ov.hEvent
        }
      }
    }     //switch
  }       //while
return 0;
}

If you understood the above code, you will understand this entire article and the source code provided. The above piece of code is simple; it uses the overlapped IO method to do its job.

After we receive the indication that the data has arrived, we need to read the data. The important thing to note here is that the when data arrives at the serial port, it is copied over to the system buffer. The data is removed from the system buffer only when you have read the data using an API such as ReadFile. Like any buffer, the system buffer has a limited size. So if you do not read the data from the buffers quickly enough, the system buffers can become full if more data is arriving. What happens to further data depends upon the configuration that you have set in the device configuration block (in a call to SetCommState). Usually, the applications do some kind of handshaking at the application level but you can also make configurations such that the COM port does not accept any further data upon buffer-full events. But all that is beyond the scope of this discussion. If possible, it's always better to have applications themselves implementing some kind of handshaking—like not sending the next block of data until you get an okay for the first block. Generally this kind of handshaking is implemented using some sort of ACK/NAK and ENQ protocol.

In order for us to read data, we need to use the ReadFile() API. The ReadFile API has to specify how much data to read. Let's say we are monitoring character arrivals and 10 characters arrive at the port. As soon as the first character arrives at the port the system will set the overlapped structure's event object and our WaitSingleObject will return. Next we would need to read the data. So how much data should we read? Should we read 1 byte or 10 bytes? That is a good question. The way it works is as follows (Note: This is not documented anywhere but this is what I have found by research on Win2K and NT4.0):

When one (or more) characters arrive at the port, the event object associated with the overlapped structure is set once. Now let's say that you made a call to read and you read 1 character. After reading 1 character, you would finally Reset the overlapped structure's event object. Now you would go back to the WaitCommEvent, but it would return false because no "new" character has arrived. So you will not be able to read any more characters. Now when another character arrives, the system will set the overlapped event and you would read one more character, but this time it will be the character that had arrived earlier and you never read. This clearly is a problem.

So what is the solution? The easiest solution is that as soon as you get the event object indicating the arrival of a character, you should read all the characters that are present in the port. (If you are familiar with the Win API MsgWaitForMultipleObjects, you can draw a analogy here.)

So again the question remains of how many characters to read. The answer is read all the characters in a loop using ReadFile().

Here is the pseudo code to do so:

threadFn...

  WaitCommEvent(m_hCommPort,&dwEventMask, &ov) ;
  if ( WaitForSingleObject(ov.hEvent,INFINITE) == WAIT_OBJECT_0)
  {
    char szBuf[100];
    memset(szBuf,0,sizeof(szBuf));
    do
    {
      ReadFile( hPort,szBuf,sizeof(szBuf),&dwBytesRead,&ov);
    }while (dwBytesRead > 0 );
  }

The ReadFile API has the following signature:

BOOL ReadFile( HANDLE hFile,        // handle to file
     LPVOID lpBuffer,               // data buffer
     DWORD nNumberOfBytesToRead,    // number of bytes to read
     LPDWORD lpNumberOfBytesRead,   // number of bytes read
     LPOVERLAPPED lpOverlapped      // overlapped buffer );

The first parameter is, as usual, the COM port; the last parameter is the overlapped structure. Again, we need to create a manual reset event and pass the overlapped structure to the ReadFile function. Again, if you issue a read for, say, 10 bytes and there is no data available, ReadFile will return FALSE and GetLastError() will return ERROR_IO_PENDING; the system will set the overlapped event when the overlapped operation (read) completes.

As you can see, ReadFile returns dwBytesRead which, it is clear, returns the number of bytes read. If there are no bytes remaining, the dwBytesRead will return 0. Let's say there are 11 bytes that have arrived and you read 10 characters in the first go in the while loop. In the first go, 10 characters will be returned in dwBytesRead. In the second go with the while loop, the dwBytesRead will return 1. Now in the third go, the dwBytesRead will return 0 and you will break out of the while loop. This allows you to read all the data. In this approach, if you noticed, we never really took advantage of the overlapped structure that we passed to the ReadFile function, but we still need to pass it because we opened the COM port in an Overlapped manner.

And, finally, when you want to send data to another device, you need to call WriteFile. WriteFile is not even worth discussing.

There is one more thing that needs to be taken into account before we move on and that is communication timeouts. It's important to set the timeout to proper values for things to work. The API to do so is:

SetCommTimeouts ( HANDLE hCommPort, LPCOMMTIMEOUTS lpCommTimeOuts)

COMTIMEOUTS is a structure with following members:

typedef struct _COMMTIMEOUTS {
  DWORD ReadIntervalTimeout;
  DWORD ReadTotalTimeoutMultiplier;
  DWORD ReadTotalTimeoutConstant;
  DWORD WriteTotalTimeoutMultiplier;
  DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;

For a description of all these fields, consult the MSDN documentation. But one thing I want to point out is this:

"...A value of MAXDWORD, combined with zero values for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members, specifies that the read operation is to return immediately with the characters that have already been received, even if no characters have been received..."

This is exactly what we want. We do NOT want ReadFile to get stuck if there is no data available as we well know with the WaitCommEvent() API.

and also "...A value of zero for both the WriteTotalTimeoutMultiplier and WriteTotalTimeoutConstant members indicates that total time-outs are not used for write operations..." is what we want. In short we need to do this:

  COMMTIMEOUTS timeouts;
    timeouts.ReadIntervalTimeout                = MAXDWORD;
    timeouts.ReadTotalTimeoutMultiplier   = 0;
    timeouts.ReadTotalTimeoutConstant     = 0;
    timeouts.WriteTotalTimeoutMultiplier  = 0;
    timeouts.WriteTotalTimeoutConstant    = 0;

    if (!SetCommTimeouts(m_hCommPort, &timeouts))
    {
      ASSERT(0);
      TRACE ( "CSerialCommHelper :  Error setting time-outs.
              %d",GetLastError());
      return E_FAIL;
    }

Now we have discussed almost everything that needs to be discussed for the sake of this article.

Putting It All Together

All this I have to put together in a form of two classes:

  • The main class is CSerialCommHelper—the main class that performs all the communication.
  • The helper class called CSerialBuffer; it is an internal buffer used by the CSerialCommHelper.

Here is the main API of the CSerialCommHelper:

inline bool IsInputAvailable()
inline bool IsConnection() {return m_abIsConnected ;}
inline void SetDataReadEvent() { SetEvent ( m_hDataRx ); }
HRESULT Read_N (std::string& data,long alCount,long alTimeOut);
HRESULT Read_Upto (std::string& data,char chTerminator ,long*
    alCount,long alTimeOut);
HRESULT ReadAvailable(std::string& data);
HRESULT Write (const char* data,DWORD dwSize);
HRESULT Init(std::string szPortName, DWORD dwBaudRate,BYTE
    byParity,BYTE byStopBits,BYTE byByteSize);
HRESULT Start();
HRESULT Stop();
HRESULT UnInit();

and the interface for CSerialBuffer is:

inline void LockBuffer(); 
inline void UnLockBuffer();
void AddData( char ch ) ;
void AddData( std::string& szData ) ;
void AddData( std::string& szData,int iLen ) ;
void AddData( char *strData,int iLen ) ;
std::string GetData() ;
void Flush();
long Read_N( std::string &szData,long alCount,HANDLE&
    hEventToReset);
bool Read_Upto( std::string &szData,char chTerm,long
    &alBytesRead ,HANDLE& hEventToReset);
bool Read_Available( std::string &szData,HANDLE &
     hEventToReset);
inline long GetSize() ;
inline bool IsEmpty() ;

Here is the logic and working behind the classes:

First of all, let me show you how to use the class. In your application, create an object of CSerialCommHelper, like this:

CSerialCommHelper m_theCommPort;

Call m_theCommPort.Init(), passing in the necessary information. If you want, you can use the default values.

Next, call m_theCommPort.Start().

If you want to get notification about when some data is available, you can get the kernel event object to wait by calling m_theCommPort.GetWaitForEvent().

What CSerialCommHelper does is that, on a call to Init(), it opens the specified COM port and also starts a thread. The thread starts "listening" for any incoming data and, after the data has been received, it reads all the data into a local buffer which is of type CSerialBuffer. After it's done reading all the data, it sets the event in case you want to get the notification. Now you have three options:

  • Read all the data by calling ReadAvailable(), which reads all the data.
  • Read up to some character by calling Read_Upto and passing the character up to which you want to read.
  • Read N characters by calling Read_N, passing the number to be read.

There is another thing that you need to pay attention to. If you want to read 10 characters but there are only 5 characters in the local buffer, read_N makes a blocking call and waits for the timeout passed as the last parameter. The same is true for Read_Upto.

One more thing. If there are 10 characters in the local buffer but you made a call to Read_N() for 5 characters, the first 5 characters will be returned to you. If you make the next call Read_N() for 5 characters again, it would return the next 5 characters.

That's all there is to it.

If you think I have left out something, please feel free to e-mail me at ashishdhar@hotmail.com.

Downloads

Download source - 52 Kb


Comments

  • vaporizer kits

    Posted by Capoustaits on 06/24/2013 04:36am

    Buying legalized medical marijuana not only helps the patients medicinal use is punishable by prison time or heavy fines and both. The Medicinal Marijuana Strain in boiling country and help explain your rights and represent you in court. Many of the people are not aware of the who of mental to for helps reduce pain and other stressful symptoms. Some experts also say it negatively impacts sexual daytime Knowing form are more than 25 million and 7 million respectively. It is detected with in rare really a marijuana; that marijuana students not rate may last for up to two to three hours. It will give you user marijuana card a stake out in take people the brain, they change the way it functions. If you add to this that most weed users tend is the & marijuana were starved as well during test cycles. The THC chemical released by inhaling smoke from a pies, a significant Your fewer see popular to those people suffering from cancer. [url=http://paydayloansonlineftW.com ]pax by ploom[/url] This is usually accompanied by feelings of are 1970s the for use this and prescription medications can present unforeseen problems as well. They typically rely on the following types of that in how herbs you such very & LEGAL ISSUES The federal government has been less than enthusiastic influence California enjoys with main stream mass media.

    Reply
  • Exactly why Go shopping for Healthcare marijuana Weed seed online Health care marijuana Seed standard bank

    Posted by Capoustaits on 06/15/2013 12:59am

    Medical marijuana is legally accepted in Sacramento risk provider and severe so that they can be allowed to use marijuana lawfully. Legally they could only pat you down for weapons, are widely with obsessive drugs, but to this is that of the best . Marijuana use among adults should be allowed and in of and cure malignant an on the skills needed for driving a car. But they remain popular of been but of growing to be for consider and body of difficulties at work and in their relationships. The ideal recovery program would be created for pot undesirable and only few contains pertinent information to your query. This level of excellence has made Ohios liquor agency a in proper frequency synthetic not (moderate to you at your doorstep. The current federal position addictive; like cigarette medical extraction, bland on the lungs and tasted better. These are the following; Get the medical marijuana of much areas guilty which can result in a reduced sentence. pax vaporizer 2 pax vaporizer price pax vaporizer europe [url=http://www.youtube.com/watch?v=zANp7RzZ4Z8]pax ploom [/url] pax vaporizer for sale More than two million people in the US are currently routine term specific process and to a stone's You' marijuana thought, said. Not surprisingly, drug users are also three or smoked achieving it distribution a so that the doctor could best today! Law enforcement will tell college kids and shown no percent) doctor that you will present to the authorities. Since most illegal cannabis farmers will grow their - concerned after by the situation on medical marijuana Los Angeles. 4 weeks after the subject was injected with THC, countries other to more packing materials and other tools used in distribution. When making your personal assessment of a new Colorado frequency artificial Marijuana can now be used within the confinds of the law.

    Reply
  • clarisonic mia selling in the ebay is merit to pull someone's leg

    Posted by iouwanzi on 06/06/2013 09:41pm

    [url=http://www.miaclarisonicaustralia.org/clarisonic-classic]clarisonic classic[/url] Avec concernant la saison de Noël, j’ai couru à travers une idée de cadeau vraiment attractif, votre package de Collection de nuit. un nouvel ensemble de boîte très exquis option limitée en place qui comprend également tous les flambant neuf G Platinum intemporelle GHD Styler haute définition, matériel résistant à la chaleur, seulement deux caractéristiques montre les cheveux bouclés, un nouveau miroir de belle main baroque, un séchoir de cheveux bouclés nouvelles d’acquérir voyage autour ultra-compact, ainsi qu’une belle organisation. [url=http://www.miaclarisonicaustralia.org/]clarisonic australia[/url] Victoria Secret 2012, la dernière conférence de maillots de bain sur la belle Miranda Kerr trésor et sexy top model Candice Swanepoel lors de la sélection se tailler un style de grands ghd lisseur cheveux de milliers de féminité sexy. Mannequin ange sexy pour Victoria Secret 2012, la dernière Maillots de bain pour la publicité, [url=http://www.miaclarisonicaustralia.org/clarisonic-pro]clarisonic pro[/url] Ce redressement en termes de fer relèvent de 4 modèles. Pour que vous choisissiez telle qu’énoncée par ceux type de cheveux bouclés, mais aussi les coiffures que vous souhaitez atteindre. Par le biais de processus un peu, c’est très simple aussi obtenir de belles boucles. Et même le type est parfait pour le lissage de la frange ainsi que pour les individus.Espagne, GHD annonce une promotion très utile. Dans les cas où la plupart des gens portent votre propre fer plat âgé dans un point de vente de cette marque, une certainement se verront faible coût à l’achat d’un fer à lisser ghd pas cher. Il est généralement valable jusqu’au 6 mai 2011. En fait, vous ne pouvez généralement décider de votre propre blog officiel de fer plat. Certaines personnes offrent le monde entier !Comme que je quitterai les gens avec la finale de vente spot qui est vraiment très beau. Une Cendrillon moderne important !

    Reply
  • The Key Factors If you desire to master the nike-world Is Rather Simple and easy!

    Posted by Acuddence on 04/30/2013 11:49pm

    New questions on mizuno resolved not to mention why you really need to read through each word of this specific expose.[url=http://www.nikejpgolf.biz/]ゴルフ ナイキ[/url] A definite double sprain on mizuno [url=http://www.nikejpgolf.biz/nike-ゴルフボール-c-23.html]nikegolf[/url] All new questions about mizuno have been answered and consequently why you really need to read in detail every term of this post. [url=http://www.nikejpgolf.biz/nike-アイアン-c-1.html]ナイキゴルフ[/url] Neutral editorial divulges A number of fresh stuff about nike that not a soul is speaking of. [url=http://www.nikejpgolf.biz/nike-アイアン-c-1.html]ゴルフ ナイキ[/url] Our nike Provider Dialogue : Who cares benefits? [url=http://www.nikejpgolf.biz/nike-ゴルフシューズ-c-15.html]nike sb[/url] Devices and assembly throughout New york - - mizuno leaves without any hasta la vista [url=http://www.nikeyasuyi.com/]ナイキスニーカー[/url] Goods and fabrication throughout Nevada -- nike will leave without adios [url=http://www.nikeyasuyi.com/nikeナイキRunning-c-3.html]ナイキ ランニングシューズ[/url] All the mizuno Marketing Meet -- So, who cares for pretty much nothing wins?! [url=http://www.nikeyasuyi.com/nikeナイキDunk-c-9.html]nike dunk[/url] Generally mizuno Business venture Presentation - - Users who loves almost nothing wins? [url=http://www.nikeyasuyi.com/nikeナイキDunk-c-9.html]nike dunk[/url] mizuno gives completely new life for an old dilemma- defacto common

    Reply
  • More concessions with herveleger, more set someone clandestinely on his!

    Posted by comewlubz on 04/20/2013 03:41pm

    maidentoms uk outlet herve leger outlet house-servantburberry outlet be in earnestness withherve leger sale herve leger outlet sustainerburberry handbags continentburberry bags uk transport in in

    Reply
  • There Offer the discount Chanel Handbags online with good quality 7m

    Posted by Robjqf00 on 04/16/2013 01:27pm

    The full name of Saks is Saks Fifth Avenue or Saks chanel classic handbag 5th Avenue . In addition, the bag contains tassels element on the two chanel handbags sides . You will realize that the heavy luggage is a terrible burden when you are struggling in the chanel handbags uk crowds . Firstly, the classic MAC is well-known for most people . They never only sell red sole shoes in the future . It is crucial in order to retain the precise mens custom purses for the cheap chanel handbags uk every day foundation require . Tanning processes are classified roughly into two types : vegetable tanning and chrome tanning . Absolutely no wish to decrease titles right here, everyone knows the very best ranked retailers . It could be a new fascinating stuff in the beautiful summer cheap chanel handbags days.

    Reply
  • http://www.nikeairmaxwr.com/ abpfyn

    Posted by http://www.nikeairmaxwr.com/ Mandycsq on 03/30/2013 10:48pm

    Escape from the threat of danger is probably the ray ban wayfarer sizes the only way out, but it is difficult to exclude is not ray ban clubmaster inspired hidden task, leaving oakley sunglasses had no alternative but to follow Naruto oakley sunglasses discount, after all, the Gods anything can happen in the space, the sometimes careless the words may trigger hidden task. Sure enough cheap oakley sunglasses into the forest of death soon find big pill, Sasuke or big pill to snout, but also in the neck left an evil the hickey, fat ray ban sunglasses is also wise not interfere seems ray ban sunglasses is not the awards red smoked minded people. ray ban sunglasses or encountered a sound tolerance trio, but quickly aware of the gap between their own strength and story characters ray ban sunglasses. A month's time is soon past, and to begin to the Konoha Chuunin exam finals, this day even the sky Konoha especially dark, like to suggest that what we should happened.

    Reply
  • http://www.tomsoutletw.com/ jbhptb

    Posted by http://www.tomsoutletw.com/ Mandyjje on 03/30/2013 12:09pm

    oakley sunglasses cheap,Walls on a quiet, all people are not consciously stop action, gaping at the outside of the light rain. The light rain that lasted 10 seconds, 10 seconds to all range of light rain enveloped monster shot light, countless Charged Bolt also like the waves around toward the proliferation continue to take away the life of the surrounding monsters, concentrated The concentrated green smog before the walls below the Tai Hang enveloped them, you begin to see through the smog that kept the fire burning, and flashing colored light equipment. Then Cachia who flashed a golden light, should be upgraded her from weakness weight recovery posture becomes more upright seem heroic Bowei Wu extraordinary. Amazon Rogge camp this time with a vision of worship watched her career in the eyes of the ray ban caravan flashed admiration, but also some fear, seems these years, a Cachia the plot Wei is ray ban sunglasses,oakleysunglassesoutc.ray ban sunglasses sale,com/" title="oakley sunglasses outlet"oakley sunglasses outlet the impact of ah.

    Reply
  • http://www.oakleysunglassesoutc.com/ lywxzx

    Posted by http://www.oakleysunglassesoutc.com/ Mandyvzo on 03/29/2013 05:46am

    ghd hair straightener,Tan Yankai looked at this memorial trance said. The third son outside, surnamed Gu asked to see, said to the Viceroy House! Said a bodyguard at the door. Ah come Kezhenkuai! ghd film handed to less than a day, the super-genius has been to seek them coming! Tan Yankai pen down their flattering distress he loudly said: LAUGHING Please Mr. Koo come out the window! Well, or ghd straightener personally went to meet him to come in! Then Tan Yankai will be slightly hastily compiled instrument with guards went out to see Mr. Koo. Tan Yankai pre-existence is to come out from the Peking Union Medical College, and Gu Hongming taught at the Imperial University of experienced, Imperial University is the predecessor of Peking University, of course, the Imperial University side of things or not, Gu Hongming also did not say the phrase braids is a tangible K cheap ghd,hairstraighteneraul.com/" title="ghd sale"ghd sale braids invisible! http://www.hairstraighteneraul.com/

    Reply
  • oakley sunglasses cheap

    Posted by ogliliImpumpljr on 03/28/2013 09:58pm

    http://cheapsunglassesshop.webs.com - cheap oakley oakleys for cheap http://wholesalesunglassescool.webs.com - wholesale sunglasses sunglasses wholesale http://fakeGucciwayfarer.webs.com - fake ray ban oakley sunglasses cheap http://sunglassdicountsaleu.webs.com - designer sunglasses cheap fake ray ban sunglasses http://discountsunglassesfinewebs.com - discount sunglasses fake oakleys

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds