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)

Friday 7 October 2011

Minimal Axis2C Web Service package needed for deployment with IIS

If Axis2/C engine does not support OpenSSL and does not use libxml2 as XML parser, this is the minimal set of Axis2C files needed to be deployed on the machine with IIS in order to support hosting MyWebService Axis2/C Web Service:

C:\axis2c\lib\axiom.dll
C:\axis2c\lib\axis2_engine.dll
C:\axis2c\lib\axis2_http_receiver.dll
C:\axis2c\lib\axis2_http_sender.dll
C:\axis2c\lib\axis2_parser.dll
C:\axis2c\lib\axis2_xpath.dll
C:\axis2c\lib\axutil.dll
C:\axis2c\lib\guththila.dll
C:\axis2c\lib\mod_axis2_IIS.dll
C:\axis2c\lib\neethi.dll

C:\axis2c\modules\addressing
C:\axis2c\modules\addressing\axis2_mod_addr.dll
C:\axis2c\modules\addressing\module.xml

C:\axis2c\services\MyWebService\MyWebService.dll
C:\axis2c\services\MyWebService\services.xml

C:\axis2c\axis2.xml
C:\axis2c\LICENCE
C:\axis2c\NOTICE

Conditional compilation of resource file in Visual Studio

How to use different resources in different build configurations, having a single resource file in project? 
Answer: define different resource file preprocessor symbols for different configurations.


1. Open your project in Visual Studio 2008

2. Right click on resource script file (e.g. app.rc) and select "Properties"


3. At the top of the property page, select one platform like "Win32" or "x64".

4. In the left menu bar, select [Configuration Properties] / [Resources] / [General].

5. In the "Preprocessor Definitions" field, add "WIN32" for "Win32" platform and "WIN64" for "x64" platform. The field value will become "WINXX;_UNICODE;UNICODE". (XX will be 32 or 64)


6. Click OK to close the window.


7. Right click on resource script file (e.g. app.rc) and select "View Code".


8. In the code editor, add #ifdef and #elif to conditionally include resources when compiling. Use "WIN32" and "WIN64" preprocessor definitions that we defined just now. 



Here is a sample code:
--------------------------------
#ifdef WIN32
   IDB_BITMAP1             BITMAP                  "bitmap1.bmp"
   IDB_BITMAP2             BITMAP                  "bitmap2.bmp"
#elif WIN64
   IDR_TOOLBAR1         BITMAP                   "toolbar1.bmp"
   IDI_ICON1                  ICON                       "icon1.ico"
#endif
--------------------------------

9. Save the resource script file and compile the project in different platforms.


[source]

NSIS installer for 64-bit Windows

Here are some tips for creating (32-bit) NSIS installer which installs 64-bit application on 64-bit Windows.

There is no 64-bit NSIS Installer (yet) so only 32-bit version will be running on 64-bit host which means that 32-bit redirection will take place: by default its Installation Directory is "C:\Program Files (x86)" and it reads/writes only from HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node portion of the registry. This is not what we want so we need to enable access to native Win64 directories/registry for our Installer.

Our installer, as 32-bit application, will probably be used both for 32-bit and 64-bit installations. It therefore needs to be able to determine architecture of the CPU it runs on. x64 plug-in offers macro RunningX64 which returns true if installer is running on 64-bit Windows (under WoW64 emulation):

setup.nsi:
!include x64.nsh
...
${If} ${RunningX64}
   DetailPrint "Installer running on 64-bit host"
${EndIf}

Once we've detected 64-bit host, we need to:
  • set "C:\Program Files" as Installation Directory - use $PROGRAMFILES64 instead of $PROGRAMFILES
  • enable access to 64-bit registry - use SetRegView NSIS command

setup.nsi:
!include x64.nsh

;set initial value for $INSTDIR
InstallDir "$PROGRAMFILES\${MY_COMPANY}\${MY_APP}"
...
${If} ${RunningX64}
   DetailPrint "Installer running on 64-bit host"
   ; disable registry redirection (enable access to 64-bit portion of registry)
   SetRegView 64
   ; change install dir
   StrCpy $INSTDIR "$PROGRAMFILES64\${MY_COMPANY}\${MY_APP}"
${EndIf}

If installer needs to detect whether some 64-bit process is running, use FindProcDLL plug-in (there are couple of versions available but I found only this one - FindProcDLL_mod_by_hnedka.7z - working for me; please have a look at this forum thread). Download this archived file, unpack it and copy FindProcDLL.dll to your ..\NSIS\Plugins directory.

setup.nsi:
${If} ${RunningX64}
   FindProcDLL::FindProc "Some64BitProcess.exe"
   ${If} $R0 == 1
      DetailPrint "FindProcDLL::FindProc() returned 1 (process is running)"
   ${ElseIf} $R0 == 0
      DetailPrint "FindProcDLL::FindProc() returned 0 (process is not running)"
   ${Else}
      DetailPrint "FindProcDLL::FindProc() returned unexpected value"
   ${Endif}
${Else}
...

How to build Axis2C for 64-bit Windows

This article shows how to build Axis2/C package for 64-bit Windows (AMD64 processor architecture) from command line, by using NMAKE that comes with Visual Studio 2010. Building this package for 32-bit Windows is described here.

Step 1:    Download source distribution for Windows from Apache Axis2/C Releases page. It comes as axis2c-src-1.6.0.zip file. Unzip it to some folder, e.g. "..\axis2c-src-1.6.0"

Step 2:    Set NMAKE environment
..\axis2c-src-1.6.0\build\win32\makefile is Microsoft's NMAKE makefile and ..\axis2c-src-1.6.0\build\win32\configure.in is its configuration file. As I explained in the article "NMAKE and its environment", in order to compile code targeting 64-bit OS on 32-bit host NMAKE needs to use cross-compiler and linker, it needs to be able to access headers for 64-bit code, and 64-bit libraries. To achieve this we need to set environment variables in the current command prompt session which can be done in couple of ways:
  • run my batch file setenv.bat from the ..\axis2c-src-1.6.0\build\win32 directory providing "x64" as its argument
  • go to "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\x86_amd64" and run vcvarsx86_amd64.bat
  • go to "C:\Program Files\Microsoft Visual Studio 10.0\VC" and run vcvarsall.bat providing "x86_amd64" as argument
After this, check whether nmake will use proper compiler and linker (x86_amd64 versions of cl.exe link.exe):

C:\DEVELOPMENT\Toolkits\Axis2C\axis2c-src-1.6.0\build\win32>cd "C:\Program
Files\Microsoft Visual Studio 10.0\VC"

C:\Program Files\Microsoft Visual Studio 10.0\VC>vcvarsall.bat x86_amd64
Setting environment for using Microsoft Visual Studio 2010 x64 cross tools.

C:\Program Files\Microsoft Visual Studio 10.0\VC>goto :eof

C:\Program Files\Microsoft Visual Studio 10.0\VC>cd "C:\DEVELOPMENT\Toolkits\Axi
s2C\axis2c-src-1.6.0\build\win32"

C:\DEVELOPMENT\Toolkits\Axis2C\axis2c-src-1.6.0\build\win32>where nmake
c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\nmake.exe

C:\DEVELOPMENT\Toolkits\Axis2C\axis2c-src-1.6.0\build\win32>where cl
c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\cl.exe
c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\cl.exe

C:\DEVELOPMENT\Toolkits\Axis2C\axis2c-src-1.6.0\build\win32>where link
c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\x86_amd64\link.exe
c:\Program Files\Microsoft Visual Studio 10.0\VC\bin\link.exe

C:\DEVELOPMENT\Toolkits\Axis2C\axis2c-src-1.6.0\build\win32>

Step 3:    Modify configure.in

This file contains variables and flags for conditional compiling defined in makefile. If you don't need OpenSSL support, TCP server, using libxml2 (and so zlib1 and iconv), building Apache Axis2C engine module, libcurl, then modify configure.in to be like this:

#############################################################################
### Build Details ###
#############################################################################
#
# enables https support
ENABLE_SSL = 0
#
# build libcurl transport
ENABLE_LIBCURL = 0
#
# build axis2 with Libxml2 Parser. Axis2/C will be built with embeded guththila # parser by Default.
ENABLE_LIBXML2=0
#
# build tcp server in addition to http server
WITH_TCP = 0
#
# build with archive based deployment
WITH_ARCHIVE = 0
#
#
#############################################################################
### Dependant Binary Locations (Required) ###
#############################################################################
#
# libxml2 binary location ( axis2c is built with libxml2 )
LIBXML2_BIN_DIR =
#
# iconv binary location
ICONV_BIN_DIR =
#
# zlib binary location
ZLIB_BIN_DIR=
#
#
#############################################################################
### Dependant Binary Locations (Optional) ###
#############################################################################
#
# openssl binary location
# required if ENABLE_SSL = 1
OPENSSL_BIN_DIR =
#
# libcurl binary location, only required if libcurl transport is enabled
LIBCURL_BIN_DIR =
#
#
#############################################################################
### Apache Server module (required when building Axis2/C Apache Module) ###
#############################################################################
#
# apache binary location
APACHE_BIN_DIR =
#
# apache 2 server family
# To use apache 2.2 family, use APACHE_VERSION_IS_2_0_X = 0
APACHE_VERSION_2_0_X = 0
#
#
#############################################################################
### Compiler Options ###
#############################################################################
#
# C runtime LIBRARY OPTION ( Use /MD or /MT )
CRUNTIME = /MT
#
# Embed Manifest Files
EMBED_MANIFEST = 1
#
# debug symbols
# To build with debug symbols use DEBUG = 1
DEBUG = 0

Step 4:    Run NMAKE.

..\axis2c-src-1.6.0\build\win32>nmake install

Build output is in directory ..\axis2c-src-1.6.0\build\deploy:

..\axis2c-src-1.6.0\build\deploy\
                                 bin
                                 docs
                                 include
                                 lib
                                 logs
                                 modules
                                 samples
                                 services 
                                 axis2.xml
                                 ...

...and that's it! There is NO need to change any compiler/linker options in makefile. Just make sure you've set NMAKE environment properly - so x86_amd64 versions of cl.exe and link.exe are used!

You can check that all these binaries are 64-bit by using Dependency Walker.

NOTE 1: If you need to have different compiler/linker options in makefile, just add custom BUILD_X86 flag to configure.in:

# BUILD_X86 = 1 if nmake should create x86 binaries.
# BUILD_X86 = 0 if nmake should create x64 (amd) binaries.
BUILD_X86 = 0

makefile can use this file to separate compiler/linker settings for 32 and 64-bit builds (I have defined some symbols here and set /MACHINE to X64 but THAT IS NOT NECESSARY - build succeeds even without these options!):

...
...
!if "$(BUILD_X86)" == "1"
CFLAGS = /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "AXIS2_DECLARE_EXPORT" \
/D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_SECURE_NO_WARNINGS" \
/D "AXIS2_SVR_MULTI_THREADED" /W3 /wd4100 /MP10 /nologo $(AXIS2_INCLUDE_PATH) \
$(APACHE_INCLUDE_PATH)
!else
CFLAGS = /D "WIN32" /D "WIN64" /D "AMD64" /D "_WINDOWS" /D "_MBCS" /D "AXIS2_DECLARE_EXPORT" \
/D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_SECURE_NO_WARNINGS" \
/D "AXIS2_SVR_MULTI_THREADED" /W3 /wd4100 /MP10 /nologo $(AXIS2_INCLUDE_PATH) \
$(APACHE_INCLUDE_PATH)
!endif
...
...
!if "$(BUILD_X86)" == "1"
LDFLAGS = /NOLOGO /LIBPATH:$(AXIS2_LIBS) /LIBPATH:$(LIBXML2_BIN_DIR)\lib \
/LIBPATH:$(APACHE_BIN_DIR)\lib /LIBPATH:$(ZLIB_BIN_DIR)\lib
!else
LDFLAGS = /NOLOGO /LIBPATH:$(AXIS2_LIBS) /LIBPATH:$(LIBXML2_BIN_DIR)\lib \
/LIBPATH:$(APACHE_BIN_DIR)\lib /LIBPATH:$(ZLIB_BIN_DIR)\lib /MACHINE:X64
!endif

NOTE 2: If you need to build 64-bit Axis2C for deploying it as IIS module add this target to makefile:

iis_deploy: deploy axis2_core_without_server axis2_IIS_module copy_axis2_xml

and call nmake with it:

..\axis2c-src-1.6.0\build\win32>nmake iis_deploy

Your web service dll must be built for 64-bit Windows as well and must be built against 64-bit Axis2/C libraries.

Links and references:
Apache Axis2/C Installation Guide
How to: Enable a 64-Bit Visual C++ Toolset at the Command Line