Friday, 4 November 2011

How to get notified when network adapters' IP addresses change? (Windows OS)

TCP/IP networking software requires at least one network adapter bounded to TCP/IP protocol stack. Each physical network card has unique MAC address and static or dynamic IP address. Static address (one or possibly more) is configured manually and dynamic address is assigned by Dynamic Host Configuration Protocol (DHCP) server (if DHCP is enabled; Obtain IP address automatically is ticked in TCP/IPv4 Properties window). Operating system maintains table which maps IP addresses to network interfaces. Use ipconfig command in command prompt window to display that table. If your adapter has DHCP enabled and you unplug/plug network cable (if using LAN adapter), disable/enable network adapter through adapter settings, issue ipconfig /release or /renew command, get out of/into WiFi range (if using WiFi adapter)...your adapter will loose existing or get a new IP address. NIC to IP address table will change.

Networking applications often need to be aware when changes in this table occur. Windows API function NotifyAddrChange notifies caller on this event. Here is an example of how to call it synchronously (when it's blocking):

#if !defined(_MT)
#error _beginthreadex requires a multithreaded C run-time library.
#endif

#include <winsock2.h>
#include <iphlpapi.h>
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <process.h>
#include <iomanip>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

#define APP_RETURN_CODE_SUCCESS 0
#define APP_RETURN_CODE_ERROR 1

#define THREAD_RETURN_CODE_SUCCESS 0
#define THREAD_RETURN_CODE_ERROR 1

// 127.0.0.1 in network byte order
#define IP_LOCALHOST 0x0100007F

void PrintIPTable()
    PMIB_IPADDRTABLE pIPAddrTable;

 pIPAddrTable = (MIB_IPADDRTABLE*)malloc(sizeof(MIB_IPADDRTABLE));

 if(!pIPAddrTable) 
 {
  std::cout << "malloc() failed" << std::endl;
  return;
 }
  
 // Before calling AddIPAddress we use GetIpAddrTable to get
 // an adapter to which we can add the IP
 // Make an initial call to GetIpAddrTable to get the
 // necessary size into the dwSize variable
 
 DWORD dwSize = 0;

 if(GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) 
 {
  free(pIPAddrTable);
  pIPAddrTable = (MIB_IPADDRTABLE*)malloc(dwSize);

  if(!pIPAddrTable) 
  {
   std::cout << "malloc() failed" << std::endl;
   return;
  }
 }
 
 DWORD dwRetVal = 0;
 LPVOID lpMsgBuf;

 // Make a second call to GetIpAddrTable to get the actual data we want
 if((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR ) 
 { 
  std::cout << "GetIpAddrTable() failed. Error code: " << dwRetVal << std::endl;
  
  if(FormatMessage(
   FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 
   NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),       
   (LPTSTR) & lpMsgBuf, 0, NULL)) 
  {
   std::cout << "\tError: " << lpMsgBuf << std::endl;
   LocalFree(lpMsgBuf);
  }

  free(pIPAddrTable);
  return;  
 }

 std::cout << "\tNum Entries: " << pIPAddrTable->dwNumEntries << std::endl;
  
 for(int i = 0; i < (int)pIPAddrTable->dwNumEntries; i++) 
 {   
  std::cout << "\n\tInterface Index[" << i << "]:\t" << pIPAddrTable->table[i].dwIndex << std::endl;

  IN_ADDR IPAddr;

  IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
  std::cout << "\tIP Address[" << i << "]:     \t" << inet_ntoa(IPAddr) << std::endl;

  IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
  std::cout << "\tSubnet Mask[" << i << "]:    \t" << inet_ntoa(IPAddr) << std::endl;

  IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
  std::cout << "\tBroadCast[" << i << "]:      \t" << inet_ntoa(IPAddr) << "(" << pIPAddrTable->table[i].dwBCastAddr << ")" << std::endl;
  std::cout << "\tReassembly size[" << i << "]:\t" << pIPAddrTable->table[i].dwReasmSize << std::endl;

  std::cout << "\tType and State[" << i << "]:";

  if(pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY)
   std::cout << "\tPrimary IP Address";

  if(pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC)
   std::cout << "\tDynamic IP Address";

  if(pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED)
   std::cout << "\tAddress is on disconnected interface";

  if(pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED)
   std::cout << "\tAddress is being deleted";

  if(pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT)
   std::cout << "\tTransient address";

  std::cout << std::endl;

  if(IP_LOCALHOST == pIPAddrTable->table[i].dwAddr)
  {
   std::cout << "\tLOCALHOST interface" << std::endl;
   // continue;
  }
    
  MIB_IFROW iInfo;
  memset(&iInfo, 0, sizeof(MIB_IFROW));
  iInfo.dwIndex = pIPAddrTable->table[i].dwIndex;
  GetIfEntry(&iInfo);

  std::cout << "\tNetwork interface name: " << iInfo.bDescr << std::endl;

  std::cout << "\tNetwork interface type: ";

  switch(iInfo.dwType)
  {
  case MIB_IF_TYPE_OTHER:
   std::cout << "OTHER" << std::endl;
   break;
  case MIB_IF_TYPE_ETHERNET:
   std::cout << "ETHERNET" << std::endl;
   break;
  case MIB_IF_TYPE_TOKENRING:
   std::cout << "TOKENRING" << std::endl;
   break;
  case MIB_IF_TYPE_FDDI:
   std::cout << "FDDI" << std::endl;
   break;
  case MIB_IF_TYPE_PPP:
   std::cout << "PPP" << std::endl;
   break;
  case MIB_IF_TYPE_LOOPBACK:
   std::cout << "LOOPBACK" << std::endl;
   break;
  case MIB_IF_TYPE_SLIP:
   std::cout << "SLIP" << std::endl;
   break;
  }

  const int unMACSegmentsCount = 6;

  if(unMACSegmentsCount == iInfo.dwPhysAddrLen)
  {      
   std::ostringstream ossMAC;
   ossMAC.fill('0');
   
   ossMAC << std::setw(2) << std::hex << static_cast<unsigned int>(iInfo.bPhysAddr[0]);

   for(int i = 1; i < unMACSegmentsCount; i++)
   {
    ossMAC << '-' << std::setw(2) << std::hex << static_cast<unsigned int>(iInfo.bPhysAddr[i]);
   }
    
   std::cout << "\tMAC Address:            " << ossMAC.str() << std::endl;   
  }  

  std::cout << std::endl;
 } 

 if (pIPAddrTable) 
 {
  free(pIPAddrTable);
  pIPAddrTable = 0;
 }
}

unsigned __stdcall thfn(void* args)
{
 HANDLE hTerminateEvent = *(HANDLE*)args;
 BOOL bTerminate = FALSE;
 
 OVERLAPPED overlap;
 overlap.hEvent = WSACreateEvent();

 if(overlap.hEvent == WSA_INVALID_EVENT)
 {
  std::cout << "WSACreateEvent() failed. Error code: " << WSAGetLastError() << std::endl;
  return THREAD_RETURN_CODE_ERROR;
 }

 while(!bTerminate)
 { 
  
  HANDLE h = 0;

  // call NotifyAddrChange in synchronous mode
  DWORD dwRetVal = NotifyAddrChange(&h, &overlap);

  if(dwRetVal != ERROR_IO_PENDING)
  {
   std::cout << "NotifyAddrChange() failed. Error code: " << WSAGetLastError() << std::endl;
   break;
  }

  HANDLE waitObjects[2] = {hTerminateEvent, overlap.hEvent};

  std::cout << "\nWaiting for IP Table change or termination request..." << std::endl;

  dwRetVal = WaitForMultipleObjects(2, waitObjects, FALSE, INFINITE);

  switch(dwRetVal)
  {
  case WAIT_OBJECT_0:
   std::cout << "WaitForSingleObject(waitObjects) returned WAIT_OBJECT_0 (hTerminateEvent is signaled)" << std::endl;
   bTerminate = TRUE;
   break;
  case WAIT_OBJECT_0 + 1:
   std::cout << "WaitForSingleObject(waitObjects) returned WAIT_OBJECT_0 + 1 (overlap.hEvent is signaled)" << std::endl;   
   
   if(!WSAResetEvent(overlap.hEvent))
   {
    std::cout << "WSAResetEvent() failed. Error code: " << WSAGetLastError() << std::endl;
    bTerminate = TRUE;
    break;
   }

   PrintIPTable();
   break;
  case WAIT_FAILED:
   std::cout << "WaitForSingleObject(waitObjects) returned WAIT_FAILED (function failed)" << std::endl;
   bTerminate = TRUE;
   break;
  }  
 }
 
 if(!WSACloseEvent(overlap.hEvent))
 {
  std::cout << "WSACloseEvent() failed. Error code: " << WSAGetLastError() << std::endl;
  return THREAD_RETURN_CODE_ERROR;
 }

 return THREAD_RETURN_CODE_SUCCESS;
}

void WaitUserInput()
{
 std::cin.clear(); 
 std::cin.ignore(1, '\n');
}

// NOTE: std::cout is shared between two threads and is not thread safe!
int main(int argc, char* argv[])
{
// std::cout << "main()" << std::endl;

 HANDLE hTerminateEvent = CreateEvent(0, TRUE, FALSE, 0);

 if(!hTerminateEvent)
 {
  std::cout << "CreateEvent() failed. Error code: " << GetLastError() << std::endl;
  return APP_RETURN_CODE_ERROR;
 }

 unsigned unThreadID = 0;
 HANDLE hThread = 0;

// std::cout << "Creating thread..." << std::endl;
 hThread = (HANDLE) _beginthreadex(0, 0, thfn, &hTerminateEvent, 0, &unThreadID);

 if(!hThread)
 {
  std::cout << "_beginthreadex() failed. Error code: " << errno << std::endl;
  return APP_RETURN_CODE_ERROR;
 }

 // (not reliable way to) make sure child thread has started before main thread continues
 Sleep(1000);

// std::cout << "Created thread with ID: " << unThreadID << std::endl;

 std::cout << "Press ENTER to terminate listening for changes in IP address table..." << std::endl;
 WaitUserInput();

 SetEvent(hTerminateEvent);

 // wait for thread to terminate
 DWORD dwRetVal = WaitForSingleObject(hThread, INFINITE);

 switch(dwRetVal)
 {
 case WAIT_OBJECT_0:
  std::cout << "WaitForSingleObject(hThread) returned WAIT_OBJECT_0 (event is signaled)" << std::endl;
  break;
 case WAIT_TIMEOUT:
  std::cout << "WaitForSingleObject(hThread) returned WAIT_TIMEOUT (timeout elapsed; event is nonsignaled)" << std::endl;
  break;
 case WAIT_FAILED:
  std::cout << "WaitForSingleObject(hThread) returned WAIT_FAILED (function failed)" << std::endl;
  break;
 }

 if(!CloseHandle(hThread))
 {
  std::cout << "CloseHandle() failed. Error code: " << GetLastError() << std::endl;
  return APP_RETURN_CODE_ERROR;
 }

 std::cout << "Press ENTER to exit..." << std::endl;
 WaitUserInput();

// std::cout << "~main()" << std::endl;
 return APP_RETURN_CODE_SUCCESS;
}

This is the output if we unplug network cable and then plug it back again:


Waiting for IP Table change or termination request...
Press ENTER to terminate listening for changes in IP address table...
WaitForSingleObject(waitObjects) returned WAIT_OBJECT_0 + 1 (overlap.hEvent is s
ignaled)
Num Entries: 2

Interface Index[0]: 17
IP Address[0]: 192.168.56.1
Subnet Mask[0]: 255.255.255.0
BroadCast[0]: 1.0.0.0(1)
Reassembly size[0]: 65535
Type and State[0]: Primary IP Address
Network interface name: VirtualBox Host-Only Ethernet Adapter
Network interface type: ETHERNET
MAC Address: 08-00-27-00-68-56


Interface Index[1]: 1
IP Address[1]: 127.0.0.1
Subnet Mask[1]: 255.0.0.0
BroadCast[1]: 1.0.0.0(1)
Reassembly size[1]: 65535
Type and State[1]: Primary IP Address
LOCALHOST interface
Network interface name: Software Loopback Interface 1
Network interface type: LOOPBACK


Waiting for IP Table change or termination request...
WaitForSingleObject(waitObjects) returned WAIT_OBJECT_0 + 1 (overlap.hEvent is s
ignaled)
Num Entries: 3

Interface Index[0]: 10
IP Address[0]: 192.168.253.122
Subnet Mask[0]: 255.255.255.0
BroadCast[0]: 1.0.0.0(1)
Reassembly size[0]: 65535
Type and State[0]: Primary IP Address Dynamic IP Address
Network interface name: Intel(R) 82566DC Gigabit Network Connection
Network interface type: ETHERNET
MAC Address: 00-19-d1-1b-e0-88


Interface Index[1]: 17
IP Address[1]: 192.168.56.1
Subnet Mask[1]: 255.255.255.0
BroadCast[1]: 1.0.0.0(1)
Reassembly size[1]: 65535
Type and State[1]: Primary IP Address
Network interface name: VirtualBox Host-Only Ethernet Adapter
Network interface type: ETHERNET
MAC Address: 08-00-27-00-68-56


Interface Index[2]: 1
IP Address[2]: 127.0.0.1
Subnet Mask[2]: 255.0.0.0
BroadCast[2]: 1.0.0.0(1)
Reassembly size[2]: 65535
Type and State[2]: Primary IP Address
LOCALHOST interface
Network interface name: Software Loopback Interface 1
Network interface type: LOOPBACK


Waiting for IP Table change or termination request...

WaitForSingleObject(waitObjects) returned WAIT_OBJECT_0 (hTerminateEvent is sign
aled)
WaitForSingleObject(hThread) returned WAIT_OBJECT_0 (event is signaled)
Press ENTER to exit...

Thursday, 27 October 2011

How to include stdafx.h conditionally?

Don't try it as that's not possible!

If you try to put #include "stdafx.h" between #ifdef and #endif, you'll end up with error C1020: unexpected #endif. You need to include stdafx.h at the beginning of any source file in your project, apart from those files for which using precompiled headers is turned off.

There is one situation where this feature - setting using precompiled headers at the file level - comes very handy. Let's say we have some code file which does not include stdafx.h and we need to share it between project which uses precompiled headers - P1, and project which doesn't - P2. If we add that file to P1, this project won't compile  - compiler will complain with fatal error C1010: unexpected end of file while looking for precompiled header. We cannot include stdafx.h at the beginning of that file either as then P2 won't compile - it does not have stdafx.h. The only solution is to turn off using precompiled headers for that particular file.

Tuesday, 25 October 2011

Finite State Machine in C

Finite State Machine is a way of modelling behaviour of some entity that can have a (finite) set of states. Depending on the received event, entity performs some action and changes its state (or remains in the current one).

Let's say we want to model a behaviour of some simple car. I call it "simple" as it has only ignition switch, accelerator and brake. Driver can turn it on, then accelerate, brake and, at the end of the journey, turn it off. If not careful, driver can break the car - if tries to turn it on (again) while driving. Driver's actions are events - inputs of our model. Car can be turned off, idling, moving or broken - and this is a set of our car's states. So, car is in some state, it reacts on driver's command (event), performs some action and goes into the next state.

We have a finite set of states and events and can draw a diagram which precisely define state transitions (state transition diagram):


FSM_CarExample_1

Now, how to implement this model and show how this state machine changes states after receiving events?

Each state can be represented as unique number - its code, or ID. The similar thing is with events. As we have finite number of both states and events, we can use enum type to represent them: one variable will be of enum STATE type and contain the ID of the current state and another variable will be of type enum EVENT and will contain the most recent event this system received. Initially, our car is turned off so the state variable will be set to STATE_TURNED_OFF. After this simple initialization we just need to wait for events and handle them in accordance to the given transition diagram. Events can be obtained from a keyboard or some other source and they are usually kept in a queue as sometimes a new event can be received before processing of the previous one is finished. In this example, in order to keep things simple, I'm gonna assume that processing is fast enough and will just create a predefined set of events and put them in an array.

As we have repetitive action - receiving and handling events - we'll put it in a loop. If our events source is keyboard and we don't know how many events will user issue, we can use while-loop and CTRL-C as a loop termination command. In this example, we have an array of events which is of predefined (known in advance) size so we can use for-loop. Inside this loop, we need to place event processing code for each event, received in each state. This means we will have switch-statement inside another switch-statement. So, here's the code:

main.c:



Output:

Whoooa! I'm turned on!
Yipee! I'm accelerating!
Whoops! Was I too fast?
That was probably enough...

Having a switch inside a switch looks a bit complex and difficult to maintain. If we add a new state, we need to add a new case-branch for each event. In the code above it would mean we need to make changes at 4 different places in the code! Not good!

A solution for this is a state transition table. It is basically a table in which each state has its column and each event has its row. Table elements are pairs action/next-state - let's put them in some structure called TRANSITION. If transition table is called trans_tbl its element, trans_tbl[evt][state] is of type TRANSITION and action is a function called during transition and next-state is the state our model goes into for the current event. Code tells this better:

main.c:


Output is the same:

Whoooa! I'm turned on!
Yipee! I'm accelerating!
Whoops! Was I too fast?
That was probably enough...

The code has shrunk and become easier to understand and maintain: if we want to add a new event or a state, we just need to change transition table (trans_tbl) - we don't need to touch the code in a loop!

My article "Finite State Machine in C++" shows how to use OOP and State design pattern in order to implement FSM described here.

Links and references:
Finite-state machine (Wikipedia)
UML Tutorial: Finite State Machines

Friday, 14 October 2011

Reading XML with Guththila

Guththila is Apache XML parser for Axis2/C.

I've been playing with Guththila recently and just want to share code which demonstrates how to use Guththila in a standalone application, GuththilaTest. It will read data from the following XML file:

books.xml:

<?xml version="1.0" ?>
<books>
<Genre Name="Biography">
<Author Name="Michael Moore">
<Book Name="Here Comes Trouble" ISBN="9780713997019" PublishingDate="13-Sep-2011"/>
</Author>
<Author Name="Alan Sugar">
<Book Name="Way I See it" ISBN="9780230760899" PublishingDate="29-Sep-2011"/>
</Author>
</Genre>
<Genre Name="Fiction">
<Author Name="Ivo Andric">
<Book Name="Bridge Over the Drina" ISBN="9781860460586" PublishingDate="05-Apr-1994"/>                      
</Author>
<Author Name="Fyodor Dostoyevsky">
<Book Name="Crime and Punishment" ISBN="9780955816949" PublishingDate="30-Oct-2008"/>
   <Book Name="Brothers Karamazov" ISBN="9780140449242" PublishingDate="27-Feb-2003"/>
</Author>
</Genre>
</books>


We need to download Axis2/C binary package (or its source and build binaries ourselves) as Guththila requires axutil.dll and guththila.dll in a runtime and application that uses Guththila must be linked against its static libraries axutil.lib and guththila.lib.

Axis2/C manual suggest placing Axis2/C package at some location your disk (e.g. c:\axis2c) and setting environment variable AXIS2C_HOME to that path, plus adding %AXIS2C_HOME%/lib to Path environment variable so any application can find Axis2C libraries.

In this example, I will use minimalistic approach, putting all necessary libraries (axutil.dll, guththila.dll) in application's directory.

If path to necessary Axis2C DLLs is not in Path environment variable and if necessary DLLs are not in the application's directory, following message appears if you try to run the app:

---------------------------
GuththilaTest.exe - System Error
---------------------------
The program can't start because axutil.dll is missing from your computer. Try reinstalling the program to fix this problem.
---------------------------
OK
---------------------------

We need to create environment variable, and we want to have log file as well so we need to call axutil_env_create_all() function.

This algorithm explains the logic of the Axis2/C log file creation:

pass log file string to axutil_env_create_all() as an argument

axutil_env_create_all() forwards that string to axutil_log_create()

if (string is full path to log file, including its name)
   axutil_log_create() creates log file at the proved path
else (string is just log file name)
   axutil_log_create() tries to read path from AXIS2C_HOME environment variable
   if AXIS2C_HOME path obtained
      axutil_log_create() creates log file at AXIS2C_HOME/logs path
   else
     axutil_log_create() creates log file in the current directory

I don't want to change environment variables so just place axutil.dll and guththila.dll (together with books.xml) in the same directory with GuththilaTest.exe. As I don't set AXIS2C_HOME environment variable, Axis creates log file in the same directory.

So here is the code. ReadXML(...) outputs formatted content of the XML file to the standard output. GetBookInfo(...) performs search for a particular node. Each parsing session (going through XML) requires (re)initialized parser. guth_init(...) is therefore called before and guth_clean() after each of these two functions. GetStrLen(), CopyStrRealloc() and PrintSpaces() are some helper functions.

main.c:



This is the output:


..\GuththilaTest\Debug>GuththilaTest.exe
AXIS2C_HOME is not set - log is written to . dir
 <books>
  <Genre Name="Biography">
   <Author Name="Michael Moore">
    <Book PublishingDate="13-Sep-2011" ISBN="9780713997019" Name="Here Comes Tro
uble"/>
   </Author>
   <Author Name="Alan Sugar">
    <Book PublishingDate="29-Sep-2011" ISBN="9780230760899" Name="Way I See it"/
>
   </Author>
  </Genre>
  <Genre Name="Fiction">
   <Author Name="Ivo Andric">
    <Book PublishingDate="05-Apr-1994" ISBN="9781860460586" Name="Bridge Over th
e Drina"/>
   </Author>
   <Author Name="Fyodor Dostoyevsky">
    <Book PublishingDate="30-Oct-2008" ISBN="9780955816949" Name="Crime and Puni
shment"/>
    <Book PublishingDate="27-Feb-2003" ISBN="9780140449242" Name="Brothers Karam
azov"/>
   </Author>
  </Genre>
 </books>

Details for book "Brothers Karamazov" found: ISBN="9780140449242", PublishingDat
e="27-Feb-2003"
..\GuththilaTest\Debug>

And this is the content of the log file:

[Fri Oct 14 19:49:18 2011] [debug] c:\development\research\c\guththilatest\guththilatest\main.c(595)
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(534) reader created
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(517) DebugReader()
buff_size=-1163005939
type=1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(553) parser created
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(502) DebugParser()
guththila_event=-1
last_start=-1
name=0
next=0
status=1

[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(517) DebugReader()
buff_size=-1163005939
type=1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(103) GUTHTHILA_START_DOCUMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "books"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Biography"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Michael Moore"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(120) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "13-Sep-2011"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "9780713997019"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Here Comes Trouble"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Alan Sugar"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(120) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "29-Sep-2011"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "9780230760899"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Way I See it"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Fiction"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Ivo Andric"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(120) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "05-Apr-1994"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "9781860460586"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Bridge Over the Drina"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(115) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Fyodor Dostoyevsky"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(120) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "30-Oct-2008"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "9780955816949"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Crime and Punishment"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(120) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(142) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(149) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "27-Feb-2003"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "9780140449242"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(177) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(189) AttribVal: "Brothers Karamazov"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(239) GUTHTHILA_SPACE
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(97) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(212) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(217) Name: "books"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(566) guththila_reader_free() ok
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(573) guththila_un_init() ok
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(534) reader created
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(517) DebugReader()
buff_size=-1163005939
type=1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(553) parser created
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(502) DebugParser()
guththila_event=-1
last_start=-1
name=0
next=0
status=1

[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(517) DebugReader()
buff_size=-1163005939
type=1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(267) GetBookInfo()
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(268) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(278) GUTHTHILA_START_DOCUMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 0
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "books"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(322) Current node is Genre node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Biography"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Biography"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(295) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(468) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(473) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(295) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(468) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(473) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(468) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(473) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Genre"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(318) Is current node Genre node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(322) Current node is Genre node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Fiction"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Fiction"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(400) Found Genre node with Name "Fiction"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(328) Is current node Author node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(332) Current node is Author node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Ivo Andric"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Ivo Andric"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(295) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(328) Is current node Author node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(468) GUTHTHILA_END_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(473) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 2
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(290) GUTHTHILA_START_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Author"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(328) Is current node Author node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(332) Current node is Author node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 1
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Fyodor Dostoyevsky"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Fyodor Dostoyevsky"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(411) Found Author node with Name "Fyodor Dostoyevsky"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(295) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(338) Is current node Book node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(343) Current node is Book node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "30-Oct-2008"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(441) PublishingDate: "30-Oct-2008"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(451) pBookInfo->pszPublishingDate = "30-Oct-2008"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "9780955816949"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(427) ISBN: "9780955816949"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(437) pBookInfo->pszISBN = "9780955816949"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Crime and Punishment"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Crime and Punishment"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(272) Number of elements in guththila stack: 4
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(295) GUTHTHILA_EMPTY_ELEMENT
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(313) Name: "Book"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(338) Is current node Book node?
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(343) Current node is Book node
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(353) Number of attributes: 3
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "PublishingDate"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "27-Feb-2003"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(441) PublishingDate: "27-Feb-2003"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(451) pBookInfo->pszPublishingDate = "27-Feb-2003"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "ISBN"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "9780140449242"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(427) ISBN: "9780140449242"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(437) pBookInfo->pszISBN = "9780140449242"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(370) AttribName: "Name"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(385) AttribVal: "Brothers Karamazov"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(393) Name="Brothers Karamazov"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(421) Found Book node with Name "Brothers Karamazov"
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(495) ~GetBookInfo()
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(566) guththila_reader_free() ok
[Fri Oct 14 19:49:18 2011] [debug] \guththilatest\main.c(573) guththila_un_init() ok

Please be aware that Guththila is not intended for direct use but through its wrapper, axis2_parser [link]. That is probably the reason why there is no documentation about it available on the Internet.

axis2_parser is XML parser abstraction layer which can be either guththila or libxml2 wrapper. In the first case (in Axis2/C binary package), axis2_parser.dll depends on guththila.dll. In the second case (in custom Axis2/C builds), axis2_parser.dll depends on libxm2.dll, zlib1.dll and iconv.dll.

Thursday, 13 October 2011

What to do when sending message to some window fails or crashes the application

You want to send a message from one window to another by calling CWnd::SendMessage(...) or CWnd::PostMessage(...) and application crashes during these calls. How to find the cause of the crash?

We first need to determine the nature of the crash. Open crash dump, read message in Windows Debugger Dialog Box, read log file (if any). Functions above are called on the window through its pointer so check whether pointer is valid (not NULL - in which case you'll have access violation exception). Get window's handle and check whether it's valid (IsWindow(...)). If message is supposed to be sent to window's parent/owner, make sure that sending and receiving window are of proper type and in desired relation (parent/child or owner/owned).

It is very important to understand types of windows and relationships between them. They are all set at the time of window creation.

When creating some window with Create(...)/CreateEx(...) we need to pass two important arguments to these functions:
1) window styles
2) parent/owner window

Window styles define the nature (type) of the window and its appearance. There are three types of windows: overlapped, pop-up and child. For example, main application window is an overlapped window, which has some embedded controls (e.g. buttons) and these controls are child windows. When we press some of those buttons, a dialog box can appear and dialog box is a pop-up window. Each of these three types has its own flag within Window styles and they are defined in WinUser.hWS_OVERLAPPED (0x00000000L), WS_POPUP (0x80000000L), WS_CHILD (0x40000000L). Window style can have only one of these flags set (e.g. window cannot be pop-up and child at the same time). If you omit setting style, your window will be overlapped by default and no matter the fact you passed the pointer/handler of some window as its e.g. parent, you might not get expected behaviour as this window will not actually be of a child type!

When passing pointer or handler to parent/owner window, make sure that pointer is not NULL, and that handler is a valid handler of parent/owner at the time of the creation of child/owned window (use IsWindow()).

Do the same for window you're calling SendMessage/PostMessage on.

You can use this helper function which analyses some arbitrary window:

WndHelper.h:

#ifndef _WNDHELPER_H
#define _WNDHELPER_H

#include <afxwin.h>

// Usage:
// CWnd* pWnd = ...
// AnalyzeWnd(pWnd);
void AnalyzeWnd(const CWnd* pWnd);

#endif // _WNDHELPER_H

WndHelper.cpp:


#include "Include\WndHelper.h"

void AnalyzeWnd(const CWnd* pWnd)
{
TRACE(_T("AnalyzeWnd()"));

if(!pWnd)
{
TRACE(_T("pWnd is NULL!"));
return;
}

//
// Get Desktop
//

CWnd* pWndDesktop = pWnd->GetDesktopWindow();

if(pWndDesktop)
{
TRACE(_T("GetDesktopWindow() returned valid window pointer. pWndDesktop = %p"), pWndDesktop);

HWND hWndDesktop = pWndDesktop->GetSafeHwnd();
TRACE(_T("hWndDesktop = %p"), hWndDesktop);
}
else
{
TRACE(_T("GetDesktopWindow() returned NULL!"));
}

//
// Analyze Window
//

TRACE(_T("pWnd = %p"), pWnd);

HWND hWnd = pWnd->GetSafeHwnd();

if(::IsWindow(hWnd))
{
TRACE(_T("GetSafeHwnd() returned valid window handle. hWnd = %p"), hWnd);
}
else
{
TRACE(_T("GetSafeHwnd() returned INVALID window handle!"));
}

if(::IsWindow(pWnd->m_hWnd))
{
TRACE(_T("m_hWnd is a valid window handle. pWnd->m_hWnd = %p"), pWnd->m_hWnd);

TRACE(_T("Window styles: "));
LONG lStyle = ::GetWindowLong(pWnd->m_hWnd, GWL_STYLE);

if(lStyle == WS_OVERLAPPED) // 0
{
TRACE(_T("\t\tWS_OVERLAPPED (0)"));
}
else
{
if((lStyle & WS_POPUP) == WS_POPUP)
TRACE(_T("\t\tWS_POPUP"));

if((lStyle & WS_CHILD) == WS_CHILD)
TRACE(_T("\t\tWS_CHILD"));

if((lStyle & WS_VISIBLE) == WS_VISIBLE)
TRACE(_T("\t\tWS_VISIBLE"));

if((lStyle & WS_DISABLED) == WS_DISABLED)
TRACE(_T("\t\tWS_DISABLED"));

if((lStyle & WS_CAPTION) == WS_CAPTION)
TRACE(_T("\t\tWS_CAPTION"));

if((lStyle & WS_BORDER) == WS_BORDER)
TRACE(_T("\t\tWS_BORDER"));

if((lStyle & WS_DLGFRAME) == WS_DLGFRAME)
LOGGER_PRINTF(Debug, _T("\t\tWS_DLGFRAME"));

if((lStyle & WS_SYSMENU) == WS_SYSMENU)
TRACE(_T("\t\tWS_SYSMENU"));

// todo: add checks for other styles...
}

// todo: check extended styles
// LONG lStyleEx = GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
}
else
{
TRACE(_T("pWnd->m_hWnd is an INVALID window handle!"));
}

hWnd = pWnd->m_hWndOwner;

if(::IsWindow(hWnd))
{
TRACE(_T("m_hWndOwner is a valid window handle. m_hWndOwner = %p"), hWnd);
}
else
{
TRACE(_T("m_hWndOwner is an INVALID window handle!"));
}

//
// Analyze Parent
//

CWnd* pWndParent = pWnd->GetParent();

if(pWndParent)
{
TRACE(_T("GetParent() returned valid pointer. pWndParent = %p"), pWndParent);

HWND hWnd = pWndParent->GetSafeHwnd();

if(::IsWindow(hWnd))
{
TRACE(_T("GetSafeHwnd() returned valid window handle. hWnd = %p"), hWnd);
}
else
{
TRACE(_T("GetSafeHwnd() returned INVALID window handle!"));
}
}
else
{
TRACE(_T("GetParent() returned NULL!"));
}

CWnd* pWndParentOwner = pWnd->GetParentOwner();

if(pWndParentOwner)
{
TRACE(_T("GetParentOwner() returned valid pointer. pWndParentOwner = %p"), pWndParentOwner);

HWND hWnd = pWndParentOwner->GetSafeHwnd();

if(::IsWindow(hWnd))
{
TRACE(_T("GetSafeHwnd() returned valid window handle. hWnd = %p"), hWnd);
}
else
{
TRACE(_T("GetSafeHwnd() returned INVALID window handle!"));
}
}
else
{
TRACE(_T("GetParentOwner() returned NULL!"));
}

//
// Analyze Owner
//

CWnd* pWndOwner = pWnd->GetOwner();

if(pWndOwner)
{
TRACE(_T("GetOwner() returned valid pointer. pWndOwner = %p"), pWndOwner);

HWND hWnd = pWndOwner->GetSafeHwnd();

if(::IsWindow(hWnd))
{
TRACE(_T("GetSafeHwnd() returned valid window handle. hWnd = %p"), hWnd);
}
else
{
TRACE(_T("GetSafeHwnd() returned INVALID window handle!"));
}
}
else
{
TRACE(_T("GetOwner() returned NULL!"));
}

CWnd* pWndSafeOwner = pWnd->GetSafeOwner();

if(pWndSafeOwner)
{
TRACE(_T("GetSafeOwner() returned valid pointer. pWndSafeOwner = %p"), pWndSafeOwner);

HWND hWnd = pWndSafeOwner->GetSafeHwnd();

if(::IsWindow(hWnd))
{
TRACE(_T("GetSafeHwnd() returned valid window handle. hWnd = %p"), hWnd);
}
else
{
TRACE(_T("GetSafeHwnd() returned INVALID window handle!"));
}
}
else
{
TRACE(_T("GetSafeOwner() returned NULL!"));
}
}

Links and references:
CWnd::SendMessage (MSDN)
CWnd::PostMessage (MSDN)