tag:blogger.com,1999:blog-46123636295590283192024-03-11T21:51:55.504-07:00Win32Easy - Win32 API easy explained!Yanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.comBlogger18125tag:blogger.com,1999:blog-4612363629559028319.post-66194600430063510182012-11-03T05:07:00.004-07:002012-11-03T05:28:17.880-07:00Working with GDI+ - Part 2Welcome back!<br />
<br />
In the last part we have seen how to initialize GDI+ and draw some basic shapes. In this part we wanna draw some images to the window! I have chosen an image from a site where you can get free images:<br />
<a href="http://www.freedigitalphotos.net/images/Blues_and_Violets_g333-Blue_Wallpaper_p59652.html">http://www.freedigitalphotos.net/images/Blues_and_Violets_g333-Blue_Wallpaper_p59652.html</a><br />
<br />
Drawing images is a very simple task. You have to do the following steps:<br />
1. Create a Gdiplus::Image object<br />
2. Draw it<br />
<br />
You see, nothing complex here!<br />
<br />
As in the previous part I'm loading my image in the startup function and I dispose of it in the shutdown function. And then i draw it in the draw function. To load you can use one Image::FromFile or Image::FromStream. To emulate a Image::FromMemory you can either implement your own IStream based on a MemoryStream or you can copy it to a HGLOBAL allocated large enough and then use the CreateStreamOnHGlobal function.<br />
<br />
<pre class="Cpp" name="code">Gdiplus::Image* backgroundImage = nullptr;
void startupGDIPlus(ULONG_PTR* pToken) {
// code omitted to start Gdiplus
backgroundImage = Gdiplus::Image::FromFile(L"ID-10059652.jpg");
status = backgroundImage->GetLastStatus();
}
void shutdownGDIPlus(ULONG_PTR token) {
delete backgroundImage;
Gdiplus::GdiplusShutdown(token);
}
void drawGDI(HDC hDc) {
Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hDc);
g->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
g->DrawImage(backgroundImage, 10, 10);
g->Flush();
delete g;
}
</pre>
<br />
For DrawImage you have a lot of possible parameters. In general they can be grouped the following way:<br />
<br />
<ol>
<li>Parameters with "src" refer to the portion of the image you want to draw. They allow you to select only a part of the image</li>
<li>Parameters that are also position or size related but with no "src"-prefix refer to the part of the window that the portion selected with "src" should be drawn to. The "src"-portion is stretched to fit into this area.</li>
<li>The GraphicsUnit parameter lets you choose how the previous two parameter groups should be measured. Usually (and default) it uses Pixels.</li>
<li>The ImageAttributes can define more sophisticated operations on the image. We will have a look on them later.</li>
</ol>
<div>
Now lets modify our image a bit. In a first step Id like to add a transform to the image that rotates it 45° clock wise. Thus i create a Gdiplus::Matrix for identity (no transform) and one for rotation and before i draw the image I call SetTransform to apply the transform to the next drawing calls.</div>
<div>
<br /></div>
<pre class="Cpp" name="code">Gdiplus::Matrix* matrixIdentity = nullptr;
Gdiplus::Matrix* matrixRotation = nullptr;
void startupGDIPlus(ULONG_PTR* pToken) {
// previous code omitted
matrixIdentity = new Gdiplus::Matrix();
matrixRotation = new Gdiplus::Matrix();
matrixRotation->RotateAt(45.0f, Gdiplus::PointF(210, 210));
}
void drawGDI(HDC hDc) {
Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hDc);
g->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
g->SetTransform(matrixRotation);
g->DrawImage(backgroundImage, 10, 10);
g->SetTransform(matrixIdentity);
g->Flush();
delete g;
}
</pre>
<br />
The first question I already see: Why RotateAt with 210/210?! Now thats just math! The behavior of a rotation matrix is to rotate around the origin which is the top left corner of the window in my case. So that means our whole image gets rotate around the top left corner of the window. That is not what we want (or at least not what I want). The rotation should be at the center of the image. My image is 400x400 pixels so its center is at 200/200 and I have to add the offset 10/10 because I draw the image at 10/10. Now i created a matrix that rotates around the center of the image. You get a result like that:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3jnGlnusVvLr6kAwJQFUplox9SJ0mjUzoXOynXc-vvAk93rYeuYVMcmPE6JTnHeGKBLJHIWIGXw_iFmGzqOBYJ_HXuEON9l5DRi3xg54XUtvGkTKG89c-vsSO_maQSDeS1wlxmQPXSWbK/s1600/GDIP3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3jnGlnusVvLr6kAwJQFUplox9SJ0mjUzoXOynXc-vvAk93rYeuYVMcmPE6JTnHeGKBLJHIWIGXw_iFmGzqOBYJ_HXuEON9l5DRi3xg54XUtvGkTKG89c-vsSO_maQSDeS1wlxmQPXSWbK/s320/GDIP3.jpg" width="308" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
A common request is to draw images that have an alpha channel and contain transparency. GDI+ supports transparency without any further adjustments needed. So I created a PNG of my image and set the color of the border to be transparent. Its not optimal because the border changes color a bit but you see clearly that it works.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhef50gUALO_Tnj_UsA2rIYXYMSgl0qbYOhzsNkcW1ZWN_X9zrBQ6Ajg8KTmK4RZjtu3gduNKror8YP0F1wZ45KwqwvpbJcAlsLwDO4D3pxdcuUdV11Tn41GUfpZe85u3PsuZnTOZVGxBY3/s1600/GDIP4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhef50gUALO_Tnj_UsA2rIYXYMSgl0qbYOhzsNkcW1ZWN_X9zrBQ6Ajg8KTmK4RZjtu3gduNKror8YP0F1wZ45KwqwvpbJcAlsLwDO4D3pxdcuUdV11Tn41GUfpZe85u3PsuZnTOZVGxBY3/s320/GDIP4.jpg" width="317" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
There are transparent parts as well as semi transparent parts.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
You can obtain very cool effects with the ImageAttributes parameter. You crate an ImageAttribute like any other object in GDI+. Then you can add several effects to the object. The first one I like to explain is the SetOutputChannel-function. It allows you to specify one of the 4 channels in CMYK (cyan, magenta, yellow, black) that is used to calculate a grayscale picture where the shade of gray equals the intensity of that channel. An example:</div>
<pre class="Cpp" name="code">imageAttribs->SetOutputChannel(Gdiplus::ColorChannelFlagsM);
</pre>
<br />
and the result:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghNLhelruFP0MJcBOjqWnqnmY0oQmJYdx9YUWFITCicc8ROJYTBWa-9wlWosu6DRDjwzGlXRPjXUXP_gGamYgDWdQKgZEwXBaTUzdNf_H6Yk1mnH4bCHHpV6i0xiSiNS4YDoCWOSLNu_nf/s1600/GDIP5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghNLhelruFP0MJcBOjqWnqnmY0oQmJYdx9YUWFITCicc8ROJYTBWa-9wlWosu6DRDjwzGlXRPjXUXP_gGamYgDWdQKgZEwXBaTUzdNf_H6Yk1mnH4bCHHpV6i0xiSiNS4YDoCWOSLNu_nf/s320/GDIP5.jpg" width="309" /></a></div>
<br />
The second parameter id like to explain is the color matrix. The color matrix is a 5x5 matrix that gets applied to the color of the image. It is 5x5 because it uses homogeneous coordinates and a color vector has 4 components (r, g, b, a) in that order. So lets start with the identity matrix:<br />
<br />
<pre class="Cpp" name="code"> Gdiplus::ColorMatrix clrMatrix = {
{
{ 1, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 1 }
}
};
imageAttribs->SetColorMatrix(&clrMatrix);
</pre>
<br />
As expected there is no effect on the image, because its the identity matrix. To understand which component is creating which result you have to understand how matrix multiplication works. I try to visualize it a bit more:<br />
<br />
<pre>{ a, b, c, d, e }
{ f, g, h, i, j }
{ k, l, m, n, o } * { red, green, blue, alpha, 1 }
{ p, q, r, s, t }
{ u, v, w, x, y }
{ a * red + f * green + k * blue + p * alpha + u }
{ b * red + g * green + l * blue + q * alpha + v }
= { c * red + h * green + m * blue + r * alpha + w }
{ d * red + i * green + n * blue + s * alpha + x }
{ e * red + j * green + o * blue + t * alpha + y }
</pre>
<br />
From the fact that the last component must be 1 its clear that e j and o must always be 0 and y must be 1. It also gets clear that the center diagonal is used for scaling the color. So lets try the following matrix:<br />
<br />
<pre> { 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 1 }
</pre>
<br />
What do we expect? For the first component we only have 1 * red because all other are 0, for the second component we have 0 because all matrix elements on the second row are 0, same for the third. So the resulting color should be: (red, 0, 0, alpha). Thats the output:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbrbn6Aj9lrna3X3IS_grrjHZ9zY4396S4um2PuPKZU0kMPIa_k7schMpHe52T5qIOfWPKFNFmtdFmZ1MkDOOitQ1gFSfEvoiZMm1_yJ089RbJZ-vYB-12MWzx9mBLDIsnx1ltv7bdwZ1X/s1600/GDIP6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbrbn6Aj9lrna3X3IS_grrjHZ9zY4396S4um2PuPKZU0kMPIa_k7schMpHe52T5qIOfWPKFNFmtdFmZ1MkDOOitQ1gFSfEvoiZMm1_yJ089RbJZ-vYB-12MWzx9mBLDIsnx1ltv7bdwZ1X/s320/GDIP6.jpg" width="304" /></a></div>
<br />
As expected, only the red channel was shown. Success! If we take a look at the matrix equation we see that u, v and w can be used to add something to a color component. Colors are in range 0 to 1 so lets intensify our red channel a bit:<br />
<br />
<pre> { 1, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 0, 1, 0 },
{ 0.5f, 0, 0, 0, 1 }
</pre>
<pre></pre>
So this should add 0.5 to the red channel (dont worry, if its bigger than 1 it just stays white, GDI+ clamps the color). The result:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCHUgYHhmoDscvC-XRtB99equeEnvur5FwHZiaT4EGYlBhGgBIZwJe8NY8NUfrEIwsKxNFfaHzlO9M-HdP8DtSCTgRF1LESS_oEtN04PrB_EXgLoW9Loed-BCLklRnzad5f2n1Ke9KSUVZ/s1600/GDIP7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCHUgYHhmoDscvC-XRtB99equeEnvur5FwHZiaT4EGYlBhGgBIZwJe8NY8NUfrEIwsKxNFfaHzlO9M-HdP8DtSCTgRF1LESS_oEtN04PrB_EXgLoW9Loed-BCLklRnzad5f2n1Ke9KSUVZ/s320/GDIP7.jpg" width="302" /></a></div>
<br />
Now lets think of something else: Lets have a look at the red component of the resulting color. Its calculated the following way:<br />
<br />
<pre>finalRed = { a * inputRed + f * inputGreen + k * inputBlue + p * inputAlpha + u }
</pre>
<br />
Now what if we set a to 0 and k to 1 and f to 0. We get 0 * inputRed + 0 * inputGreen + 1 * inputBlue. So we map the blue channel also to the red channel. So lets have a look at the following matrix:<br />
<br />
<pre> { 1, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0 },
{ 0.5f, 0, 0.5f, 0, 0 },
{ 0, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 1 }</pre>
<br />
Interesting is the third line, it stands for the blue channel. What we do is taking the average of the red and blue channel together as the blue channel. We get a very interesting result:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKhoyYoVudqlXHfceFW2fCM8dcsD2nKk_C2Tol7j5ELBn5pdKxmocxItQQy8MJL143l8kgt7cvPml8TAavqAWs8NlBsWjCiFVKid-ag9T0jOEcLb9FFnfTJoVCyoRjE_sTy9TYjUtIWqYB/s1600/GDIP8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKhoyYoVudqlXHfceFW2fCM8dcsD2nKk_C2Tol7j5ELBn5pdKxmocxItQQy8MJL143l8kgt7cvPml8TAavqAWs8NlBsWjCiFVKid-ag9T0jOEcLb9FFnfTJoVCyoRjE_sTy9TYjUtIWqYB/s320/GDIP8.jpg" width="306" /></a></div>
<br />
Well thats it for the image part. You can explore the other functions of the ImageAttribute pretty easy.<br />
<br />
See you soon in the next part, text rendering!<br />
<br />
Greetings<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-81408617960853743322012-11-03T03:00:00.001-07:002012-11-03T05:27:20.726-07:00Working with GDI+ - Part 1Hello everyone<br />
<br />
If you are using nothing but the plain Win32-API you might have a lot of struggles when you want to perform more complicated drawing actions in your window or control. Loading compressed image formats like PNG or JPG requires a lot of work and your code pretty soon starts to get bloated.For that reason Microsoft added a new feature to Windows with XP which is called GDI+. If you need it on an older platform you can install it using Windows Update back till Windows 2000. Now whats GDI+? Pretty simple: Its a library containing a lot (and by that I mean A LOT) of features that help you working with everything related to windows graphics. As the name suggests it supersedes the traditional GDI.<br />
<br />
Well, enough talk now, lets get some code! In our first step we just want to draw a simple shape using GDI+. I have created a simple framework that creates a window and runs the message loop, ill omit these because there is nothing special there, its just the regular code for creating a window and running its message loop. This leads me to the following main function:<br />
<br />
<pre class="Cpp" name="code">#include <gdiplus.h>
#pragma comment(lib, "Gdiplus.lib")
BOOL WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT) {
HWND hWindow = createWindow(L"GDI+", WndProc);
ULONG_PTR gdiToken = 0;
startupGDIPlus(&gdiToken);
runWindowLoop(hWindow);
shutdownGDIPlus(gdiToken);
return TRUE;
}
</pre>
<br />
As you can see you have to start GDI+ before you are using it and you have to shut it down when you are finished using it. The token acts as an indicator which call to startup shutdown should process. These two functions perform the following tasks:<br />
<br />
<pre class="Cpp" name="code">Gdiplus::Pen* redPen = nullptr;
void startupGDIPlus(ULONG_PTR* pToken) {
Gdiplus::GdiplusStartupInput startInput;
Gdiplus::Status status = Gdiplus::GdiplusStartup(pToken, &startInput, nullptr);
if(status != Gdiplus::Ok) {
// do error handling
}
redPen = new Gdiplus::Pen(Gdiplus::Color::IndianRed, 3.0f);
}
void shutdownGDIPlus(ULONG_PTR token) {
delete redPen;
Gdiplus::GdiplusShutdown(token);
}
</pre>
<br />
The functions are pretty easy to understand, we call GdiplusStartup to start GDI+ and GdiplusShutdown to shut it down. GdiplusStartup has two additional parameters, a GdiplusStartupInput and a GdiplusStartupOutput. With the input you can control a few settings like which version should be loaded. Just passing the default object is fair enough for most cases. The GdiplusStartupOutput parameter gets populated by the function and then contains two function pointers that have to be called if you specified in the input that the background thread should be suspended. You see: Most likely you will never use that!<br />
<br />
You can also use the startup-function to load resources that persist over the entire lifetime of GDI+ and then delete them in shutdown. I did this for the pen I will be using later to draw my shape. It creates a pen with a stroke width of 3 and the color IndianRed.<br />
<br />
Drawing is now done at the same place it is for regular GDI drawings - in WM_PAINT. You use the HDC from BeginPaint to and then draw the actions to that context. I created a function drawGDI which takes the HDC and then performs the painting.<br />
<pre class="Cpp" name="code">void drawGDI(HDC hDc) {
Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hDc);
g->DrawArc(redPen, Gdiplus::Rect(10, 10, 100, 50), 0, 270);
g->Flush();
delete g;
}
</pre>
All drawing is done with a Graphics object. It encapsulates all the functionality for painting. There are several ways to obtain a Graphics object. You can use FromHDC to draw to a device context, you can use FromImage to draw to an image (we will use that later) or FromHwnd to draw to the window. We use the FromHDC as we want to paint to the device context returned by BeginPaint. The next step is to actually draw something. I used the DrawArc-function to draw... well... an arc! I use the Pen created by the startup function to draw the arc at the coordinates specified by my Rect and using the angles 0 and 270 as boundaries. At the end I Flush all the draw actions so that they get executed and then delete the object. The result you get should be something like that:
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Bf2gm34_wkzwb9N8-uk98SMfKQOR4Shjcsu_Q0J1_q-Eaq6CTjpgdt_lYfzaGCNv4ljJ84Qws933mMMAUVlguXi0JnBo5YKK8ss-kvpCjEryV5vDuyS7H6Jdc-f840VhxJA8N7pqihvA/s1600/GDIP1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Bf2gm34_wkzwb9N8-uk98SMfKQOR4Shjcsu_Q0J1_q-Eaq6CTjpgdt_lYfzaGCNv4ljJ84Qws933mMMAUVlguXi0JnBo5YKK8ss-kvpCjEryV5vDuyS7H6Jdc-f840VhxJA8N7pqihvA/s320/GDIP1.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
We see or first problem: That line is so blocky! Is there something to change that? Of course there is! Its called anti aliasing. The concept of anti aliasing is pretty simple: Instead of saying "Here we have red, here not" the renderer creates a fade out at the edge of the arc addind several pixels around the edge which are partially transparent and fade into completely transparent. For the eye it still looks like a single line but with way less blocky appearance. We are only one function call away from having a perfectly smooth arc. After we created the graphics object we tell GDI+ to smooth the lines using AntiAlias:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<pre class="Cpp" name="code">void drawGDI(HDC hDc) {
Gdiplus::Graphics* g = Gdiplus::Graphics::FromHDC(hDc);
g->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
g->DrawArc(redPen, Gdiplus::Rect(10, 10, 100, 50), 0, 270);
g->Flush();
delete g;
}
</pre>
<pre></pre>
And thats it, you should see a nice smoothed line like the one in the picture:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh0ZJyPwwfROxcLUp482H384xcAszMtgcPZzGR0S8Fxfo1Cxl-7KsFVimLcKz_m-zWpohhVY2LAbeZ8sPK63g17VreywR3xRDoI16XKnqyrMPqhfk3a2N3ZXZNrpT3qefGKjNftmV7Uapj/s1600/GDIP2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh0ZJyPwwfROxcLUp482H384xcAszMtgcPZzGR0S8Fxfo1Cxl-7KsFVimLcKz_m-zWpohhVY2LAbeZ8sPK63g17VreywR3xRDoI16XKnqyrMPqhfk3a2N3ZXZNrpT3qefGKjNftmV7Uapj/s320/GDIP2.jpg" width="320" /></a></div>
<br />
Now you can play with the different functions like DrawLine, DrawRectangle and so on and we will meet for the <a href="http://win32easy.blogspot.ch/2012/11/working-with-gdi-part-2.html">next part</a> when you are ready to draw some images!<br />
<br />
Thanks for reading and see you soon<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-70879719415481289242011-03-30T06:35:00.000-07:002011-03-30T06:36:58.533-07:00Compiler internals - What happens with try/catch/throw in MSVCHello everyone<br />
<br />
After i have seen that a lot of people are thinking that try - catch is a concept which is completely analyzed during compile time and therefore wont have big impact at runtime i thought i might shed some light on how the Microsoft compiler (cl.exe) is acting with try, catch and throw.<br />
<br />
First off we will have a look on how a throw statement is interpreted by the compiler. Lets have a look at the following code:<br />
<pre name="code" class="Cpp">int main()
{
try
{
throw 2;
}
catch(...)
{
}
}
</pre><br />
For now we are only interested in the throw 2. When the compiler hits the throw statement it actually has no clue if the exception its now converting is handled by an exception handler (and it doesnt care). The throw statement will be converted into a call to _CxxThrowException (exported by MSVCR100.dll (or any other version)). That function is a built in function in the compiler. You can call it yourself if you like ;). The first parameter of that function is a pointer to the object thrown. Therefore it gets clear, that the code above definitely expands to the following:<br />
<pre name="code" class="Cpp">int main()
{
try
{
int throwObj = 2;
throw throwObj;
}
catch(...)
{
}
}
</pre><br />
The second parameter of _CxxThrowException holds a pointer to a _ThrowInfo object. _ThrowInfo is also a built in type of the compiler. Its a struct holding various information about the type of exception that was thrown. It looks like that:<br />
<pre name="code" class="Cpp">typedef const struct _s__ThrowInfo
{
unsigned int attributes;
_PMFN pmfnUnwind;
int (__cdecl*pForwardCompat)(...);
_CatchableTypeArray *pCatachableTypeArray;
} _ThrowInfo;
</pre><br />
Here the important thing is the _CatchableTypeArray. It holds a set of runtime type informations of the types that are catchable within this throw. In our case thats pretty simple. The only catchable type is typeid(int). Lets say you have a class derived from std::exception called my_exception. If you now throw an object of type my_exception you will have two entries in pCatchableTypeArray. One of them is typeid(my_exception) and the other is typeid(std::exception).<br />
<br />
The compiler now fills the _ThrowInfo object as a global variable (and all the other objects needed). In the above case this is done the following way:<br />
<pre name="code" class="Cpp">_TypeDescriptor tDescInt = typeid(int);
_CatchableType tcatchInt =
{
0,
&tDescInt,
0,
0,
0,
0,
NULL,
};
_CatchableTypeArray tcatchArrInt =
{
1,
&tcatchInt,
};
_ThrowInfo tiMain1 =
{
0,
NULL,
NULL,
&tcatchArrInt
};
</pre><br />
You see that thats pretty a lot of information stored just for the throw 2. So finally Our above code expands to:<br />
<pre name="code" class="Cpp">_TypeDescriptor tDescInt = typeid(int);
_CatchableType tcatchInt =
{
0,
&tDescInt,
0,
0,
0,
0,
NULL,
};
_CatchableTypeArray tcatchArrInt =
{
1,
&tcatchInt,
};
_ThrowInfo tiMain1 =
{
0,
NULL,
NULL,
&tcatchArrInt
};
int main()
{
try
{
int throwObj = 2;
_CxxThrowException(&throwObj, &tiMain1);
}
catch(...)
{
}
}
</pre><br />
Inside _CxxThrowException now the following happens: RaiseException is called. But first the neccessary parameters are created. The exception code for an exception thrown by _CxxThrowException is 0xE06D7363. It also passes 3 parameters to RaiseException. A magic number, the pointer to the object thrown and the pointer to the _ThrowInfo. Resulting in the following pseudo code:<br />
<pre name="code" class="Cpp">__declspec(noreturn) void __stdcall __CxxThrowException(void* pObj, _ThrowInfo* pInfo)
{
struct { unsigned int magic; void* object, _ThrowInfo* info } Params;
Params throwParams =
{
0x19930520,
pObj,
pInfo
}
RaiseException(0xE06D7363, 1, 3, (const ULONG_PTR*)&throwParams);
}
</pre><br />
Now we basically know how throw is handled by the compiler and we also see that in the end what you will notice is something like if you have encountered an access violation as they are also invoked by RaiseException.<br />
<br />
Ok, if we now go further and inspect the try and catch there should be a bell ringing like crazy and it should be yelling "Wait!! You say that the throw gets transformed into a call to RaiseException like its for access violations, 0 divides and so on?! But they cannot be catched with try-catch!". And yes, you are right, they cant and thats way try - catch in fact gets transformed to a __try __except but in a special form. In code it would look somehow like that (its not real code, just theory):<br />
<pre name="code" class="Cpp">unsigned long __stdcall mainHandler1(LPEXCEPTION_POINTERS info)
{
if(info->ExceptionRecord->ExceptionCode != 0xE06D7363)
return EXCEPTION_CONTINUE_SEARCH;
if(WeHaveAHandlerForThisTypeSomeWhere(info->ExceptionRecord))
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTON_CONTINUE_SEARCH;
}
/* The stuff with _ThrowInfo comes here, omitted for readability */
int main()
{
__try
{
int throwObj = 2;
_CxxThrowException(&throwObj, &tiMain1);
}
__except(mainHandler1(GetExceptionInfo())
{
}
}
</pre><br />
But thats not all! Somewhere we need to store which types of exceptions we can catch using our catch-statement. In fact the catch(int) gets transformed into an own function (actually only a function chunk where the runtime jumps using jmp not a real function called with call) which looks like that (now its really pseudocode because i cannot really translate it to C as it misses some information which would blow up the whole thing)<br />
<pre name="code" class="Cpp">_s_FuncInfo* info = mainCatchBlockInfo1;
__asm { mov eax, info } // Its used for the following function as argument and passed through eax
goto CxxFrameHandler3;
</pre><br />
The _s_FuncInfo is now again a structure that is built in to the compiler. It would make the article to big to explain everything like i did for the _ThrowInfo. In short it holds information for every type that can be caught in the current block. This consists (beneath other stuff) of runtime type information for every type and for each of them also the address of the actual code that is inside the catch-block.<br />
<br />
Ok, now what is CxxFrameHandler3 doing? This is pretty simple:<br />
1. It rejects exceptions that dont have 0xE06D7363 as code (which stands for C++ exceptions).<br />
2. It searches through the _s_FuncInfo structure to find a type witch matches with one of the types it gets from the exception objects _CatchableTypeArray.<br />
3. If it gets a match it indicates that there is a handler read<br />
4. If there is not match it instructs the OS to search in the next frame<br />
<br />
To finish the catch-part all we now need is the actual handler code. This code also is transformed into a function chunk (not a complete function). It actually is transformed into the chunk that ends a function. In code it would look like that:<br />
<pre name="code" class="Cpp">// execute handler code
return addressWhereToContinueAfterCatch;
</pre><br />
The operating system gets the address where it should jump to when it has set up again the original context and performs that jump. An example:<br />
<pre name="code" class="Cpp">catch(...)
{
}
MessageBox(0, L"Ello!", L"", MB_OK);
</pre><br />
Gets translated into the following assembler code:<br />
<pre>.text:00401088 $LN16:
.text:00401088 mov eax, offset $LN9
.text:0040108D retn
.text:0040108E ; ---------------------------------------------------------------------------
.text:0040108E
.text:0040108E $LN9: ; DATA XREF: _main:$LN16 o
.text:0040108E push 0 ; uType
.text:00401090 push offset Caption ; lpCaption
.text:00401095 push offset Text ; "Ello!"
.text:0040109A push 0 ; hWnd
.text:0040109C call ds:__imp__MessageBoxW@16 ; MessageBoxW(x,x,x,x)
</pre><br />
You see that it returns $LN9 in eax which is the address of the call to MessageBox. And $LN16 is the address of the catch block which is referenced in the _s_FuncInfo somewhere.<br />
<br />
All that remains now is the try part. Here its no longer the compiler that can "decide" how to do things because now its the operating system that says how it works. <br />
<br />
Inside the Thread Information Block the first field (fs:[0]) holds a pointer to a linked list of exception handlers (in our case its the address of the part where it goes to CxxFrameHandler3). Now what try does is it adds the catch-block to the linked list. After the RaiseException call we arrive in the function KiUserExceptionDispatcher. This function does a lot of work but in the end the important thing is that it loads the current linked list from the TIB using FS:[0] and loops through it to find a handler that says that it could handle the exception and calls its handler. If you want to browse through the currently attached handlers you do the following:<br />
<pre name="code" class="Cpp">struct LinkedExceptionFrame
{
LinkedExceptionFrame* pPrevious;
void* pFunction;
};
LinkedExceptionFrame* pCur = NULL;
__asm
{
mov eax, fs:[0]
mov pCur, eax
}
while((DWORD)pCur != 0xFFFFFFFF)
{
std::cout << pCur->pFunction << std::endl;
pCur = pCur->pPrevious;
}
</pre><br />
Now we have all the basic concepts we need to understand that try/catch/throw is not as trivial as most people think and that most things are actually handled at runtime (though a huge amount of additional data and function overhead is made to catch the correct type of exception). There is way more we could talk about (for example: What if we have parts of our frame protected by try-catch and others not or if we even have more than one try-catch-block and so on. But i think so far the most important things are said!<br />
<br />
Some tips if you like to browse through it using a disassembler and a debugger:<br />
Use Release build but disable any kind of code optimization. So you dont have all the register checks at the beginning and the end of function calls but your code is not getting rearranged by the optimizer so you can better compare it to the source. And its a good thing to disable Dynamic Base (ASLR) in the linker options (under Advanced).<br />
<br />
So far<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com2tag:blogger.com,1999:blog-4612363629559028319.post-22004875811412893342011-03-27T14:13:00.000-07:002011-03-27T14:16:30.346-07:00Internet Explorer 9 - Avoid JavaScript in x64Ahoi<br />
<br />
Even though im not using the Internet Explorer since ages now and am pretty sticked to one type of browser i still like to browse announcements of new browser (versions). It was Microsoft to release version 9 some days ago so i decided to test it out and see if there are cool new things available.<br />
<br />
While actually the x86 version runs pretty fair ive seen a problem coming up with the x64 version. If you launch a site which makes heavy usage of javascript (and there are plenty) you should be aware that it might get pretty slow. Its parsed and executed in a way that really makes you fall asleep. Of course i first thought that this is an issue caused by my system. So i restarted everything checked windows update and dug through the settings of the IE. Sadly nothing helped to make it faster. After browsing a bit through the wide web ive seen that this is an issue that Microsoft obviously knows. They didnt implement the JIT compiler into the x64 version of the browser. This causes the javascript code made by the programmer being executed without any optimization.<br />
<br />
Why does Microsoft release a version of a product which lacks such an important feature? It reminds me a lot of visual studio 2010 which until yet does not have any support for intellisense in CLI/C++ which is one of the most important features of .NET as no one can memorize those zillions of objects... I really hate that manner of "We release half finished products and maybe there will be updates some when..."!<br />
<br />
What do you think?<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-82984866489900707092011-03-27T08:36:00.000-07:002011-03-27T08:36:34.299-07:00RtlCaptureStackBackTrace in managed world - Error, error, error!Hello everyone<br />
<br />
Lately ive created an API for a game which is no longer maintained by its developers which will be loaded using DLL-injection. It allows users to write plug-ins for that game. The DLL containing the Framework consists of pure managed code (C#) and is therefore loaded using the ICLRRuntimeHost::ExecuteInDefaultAppDomain method. <br />
<br />
As its hard to debug an executable without having the source code of it ive started to create my own symbol database for functions and global objects. I planed to use that table in my stack trace to see more detailed information if i did something wrong (those who now throw in debuggers may know that the game had anti debugging mechanics implemented (as it was an online game back then) and i was to lazy to bypass them (sadly...)).<br />
<br />
Since ages i use the function RtlCaptureStackBackTrace to easily create stack traces in unmanaged world. So i did the same in C# using DllImport. After setting framesToSkip to 0 i was pretty shocked that i only got 1 frame returned by the function which was actually RtlCaptureSBT itself. I tried several things and then used Marshal.GetLastWin32Error() to get more information on what im doing wrong. Interestingly it returned that no error happened (yes, SetLastError=true ;)). So the function said something is wrong and GetLastError said nothing is wrong, oh yeah!<br />
<br />
So i launched IDA and stepped through the function in another .NET executable which wasn't injected to the game. On my (in this time) x86 machine what it did was calling RtlWalkFrameChain which then called RtlWalk32BitStack. That function loops through the stack frames and calls for the address of each of them the function RtlpIsPointerInDllRange from ntdll.dll which determines if a given pointer is in the accessible memory of any of the loaded modules. If it returns false RtlWalk32BitStack returns false thus RtlWalkFrameChain returns false which also causes RtlCaptureStackBackTrace to return false. But as none of these functions calls SetLastError it stays 0 also on failure.<br />
<br />
Ok, so i started a debug run. First frame worked good and it was added to the list. Second frame was in a managed module which caused RtlpIsPointerInDllRange to return false. Now all aborted.<br />
<br />
Well then i dug trough ntdll.dll searching references of the global variable used to indicate accessible ranges and found the function RtlpStkMarkDllRange. This function is only referenced by LdrpLoadOrMapDll which is used by LdrLoadDll (called by LoadLibrary). RtlpStkMarkDllRange is also not exported so other DLLs can not actually call it. So i searched for references to RtlpIsPointerInDLLRange (also not exported) and found that its only used by functions that perform stack walks.<br />
<br />
So i got the feeling that somehow they forgot to include the call to RtlpStkMarkDllRange when a fully managed DLL is loaded because actually there is no reason why a .NET executable should be not valid for holding pointers to functions! Even more as StackWalk64 works as intended and returns all frames while RtlCaptureStackBackTrace isnt.<br />
<br />
What do you think?<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-12492564563787784292011-03-26T12:31:00.000-07:002011-03-26T13:57:45.747-07:00Exception Handling - Inform your users! Part 2Hello again<br />
<br />
In the previous article (Part 1) i explained how you provide some basic information about an unhandled exception to the user and announced that in the next part we will have a look on how to get more detailed information. Now thats exactly what we will do in this article. Ill show two methods to gather more information what happened and why it happened.<br />
<br />
<b>Method 1: Do it manually</b><br />
For this method we will create several helper functions that handle one or more types of exceptions. We start with the following code:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include <iostream>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
}
</pre><br />
The first function we make will return a name which describes the type of exception that happened. Writing that function is pretty easy if we use macro that helps us:<br />
<pre class="Cpp" name="code">#define EX_CASE(code) \
case code:\
return #code;
LPCSTR GetExceptionName(DWORD code)
{
switch(code)
{
EX_CASE(EXCEPTION_ACCESS_VIOLATION);
EX_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
EX_CASE(EXCEPTION_BREAKPOINT);
EX_CASE(EXCEPTION_SINGLE_STEP);
EX_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
EX_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
EX_CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO);
EX_CASE(EXCEPTION_FLT_INEXACT_RESULT);
EX_CASE(EXCEPTION_FLT_INVALID_OPERATION);
EX_CASE(EXCEPTION_FLT_OVERFLOW);
EX_CASE(EXCEPTION_FLT_STACK_CHECK);
EX_CASE(EXCEPTION_FLT_UNDERFLOW);
EX_CASE(EXCEPTION_INT_DIVIDE_BY_ZERO);
EX_CASE(EXCEPTION_INT_OVERFLOW);
EX_CASE(EXCEPTION_PRIV_INSTRUCTION);
EX_CASE(EXCEPTION_IN_PAGE_ERROR);
EX_CASE(EXCEPTION_ILLEGAL_INSTRUCTION);
EX_CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION);
EX_CASE(EXCEPTION_STACK_OVERFLOW);
EX_CASE(EXCEPTION_INVALID_DISPOSITION);
EX_CASE(EXCEPTION_GUARD_PAGE);
EX_CASE(EXCEPTION_INVALID_HANDLE);
case 0xE06D7363:
return "C++ Exception";
default:
return "Unknown exception";
}
}
#undef EX_CASE
</pre><br />
The next helper function will take an exception address an return in which module the exception occurred. This is done by looping through the loaded modules and comparing which one is the last with its base address before the exception location. Then we use GetModuleFileName to retrieve the name of the module.<br />
<pre name="code" class="Cpp">#include <windows.h>
#include <iostream>
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
// Definition of function GetExceptionName....
HMODULE GetExceptionModule(LPVOID address, LPSTR moduleName /* must support MAX_PATH characters */)
{
HMODULE moduleList[1024];
DWORD sizeNeeded = 0;
if(FALSE == EnumProcessModules(GetCurrentProcess(), moduleList, 1024, &sizeNeeded) || sizeNeeded < sizeof(HMODULE))
return NULL;
int curModule = -1;
for(int i = 0; i < (sizeNeeded / sizeof(HMODULE)); ++i)
{
if((DWORD)moduleList[i] < (DWORD)address)
{
if(curModule == -1)
curModule = i;
else
{
if((DWORD)moduleList[curModule] < (DWORD)moduleList[i])
curModule = i;
}
}
}
if(curModule == -1)
return NULL;
if(!GetModuleFileName(moduleList[curModule], moduleName, MAX_PATH))
return NULL;
return moduleList[curModule];
}
</pre>
We can test those two functions now and see what result we get using the following code:
<pre name="code" class="cpp">// previous code...
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
char message[MAX_PATH + 255];
char module[MAX_PATH];
char* moduleName = NULL;
if(GetExceptionModule(exceptionInfo->ExceptionRecord->ExceptionAddress, module))
moduleName = module;
else
moduleName = "Unknown module!";
sprintf_s<max_path + 255>(message,
"An exception has occured which was not handled!\nCode: %s\nModule: %s",
GetExceptionName(exceptionInfo->ExceptionRecord->ExceptionCode),
moduleName
);
MessageBox(0, message, "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
int b = 0;
int a = 2 / b;
}
</pre>The messagebox now should display the name of your executable. The EXCEPTION_RECORD structure inside exceptionInfo contains an array of additional data that can be used to provide more information. Sadly those values are not defined by a standard. Its up to every compiler to do whatever it likes to. There are only 2 codes for which additional information is defined in a standardized way. EXCEPTION_ACCESS_VIOLATION and EXCEPTION_IN_PAGE_ERROR. We will now write a function that handles EXCEPTION_ACCESS_VIOLATION separately and provide a function that handles all the other codes.
<pre name="code" class="Cpp">void HandleAccessViolation(LPEXCEPTION_POINTERS info)
{
char message[MAX_PATH + 512];
char module[MAX_PATH];
char* moduleName = NULL;
if(GetExceptionModule(info->ExceptionRecord->ExceptionAddress, module))
moduleName = module;
else
moduleName = "Unknown module!";
DWORD codeBase = (DWORD)GetModuleHandle(NULL);
DWORD offset = (DWORD)info->ExceptionRecord->ExceptionAddress - codeBase;
char* accessType = NULL;
switch(info->ExceptionRecord->ExceptionInformation[0])
{
case 0:
accessType = "Read";
break;
case 1:
accessType = "Write";
break;
case 2:
accessType = "Execute";
break;
default:
accessType = "Unknown";
break;
}
sprintf_s<max_path + 512>(message,
"An exception has occured which was not handled!\nCode: %s\nModule: %s\n"\
"The thread %u tried to %s memory at address 0x%08X which is inaccessible!\n"\
"Offset: 0x%08X\nCodebase: 0x%08X",
GetExceptionName(info->ExceptionRecord->ExceptionCode),
moduleName,
GetCurrentThreadId(),
accessType,
info->ExceptionRecord->ExceptionInformation[1],
offset,
codeBase
);
MessageBox(0, message, "Error!", MB_OK);
}
void HandleCommonException(LPEXCEPTION_POINTERS info)
{
char message[MAX_PATH + 512];
char module[MAX_PATH];
char* moduleName = NULL;
if(GetExceptionModule(info->ExceptionRecord->ExceptionAddress, module))
moduleName = module;
else
moduleName = "Unknown module!";
DWORD codeBase = (DWORD)GetModuleHandle(NULL);
DWORD offset = (DWORD)info->ExceptionRecord->ExceptionAddress - codeBase;
sprintf_s<max_path + 512>(message,
"An exception has occured which was not handled!\nCode: %s\nModule: %s\n"\
"Offset: 0x%08X\nCodebase: 0x%08X",
GetExceptionName(info->ExceptionRecord->ExceptionCode),
moduleName,
offset,
codeBase
);
MessageBox(0, message, "Error!", MB_OK);
}
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
switch(exceptionInfo->ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
HandleAccessViolation(exceptionInfo);
break;
default:
HandleCommonException(exceptionInfo);
break;
}
return EXCEPTION_EXECUTE_HANDLER;
}
</pre>Well, thats it! Now we have handled access violations and also a default handling for other exceptions.
<b>Method 2: Let windows do the thing!</b>
Windows provides a method to create a dump file from the current execution context. This will include a dump of the memory as well as other information visual studio can use to display all the information necessary.
The function is called inside the exception handler. Its very easy so i wont tell much about it. It will create a .dmp file which can be opened with Visual Studio. When you start debugging (using the green arrow) you will get all the information needed. Here is the corresponding code:
<pre name="code" class="cpp">#include <Windows.h>
#include <iostream>
#include <DbgHelp.h>
#include <ctime>
#pragma comment(lib, "dbghelp.lib")
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
char timeStr[255];
time_t t = time(NULL);
tm* tM = localtime(&t);
strftime(timeStr, 255, "CrashDump_%d_%m_%Y_%H_%M_%S.dmp", tM);
HANDLE hFile = CreateFile(
timeStr,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
0,
NULL
);
if(hFile != NULL)
{
MINIDUMP_EXCEPTION_INFORMATION info =
{
GetCurrentThreadId(),
exceptionInfo,
TRUE
};
MiniDumpWriteDump(
GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpWithIndirectlyReferencedMemory,
&info,
NULL,
NULL
);
CloseHandle(hFile);
}
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
int b = 0;
int a = 2 / b;
}
</pre><br />
<br />
Now you have 2 good methods to retreive vital information about errors that happened.<br />
<br />
Thanks for reading and bye<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-4788143529812742612011-03-26T10:13:00.000-07:002011-03-26T10:16:13.939-07:00Exception Handling - Inform your users!Hello everyone!<br />
<br />
This article will show you methods to inform the user that something has happened in the program which caused an exception that was not handled by the program. It will also teach you how to use the values you will get and display some more information the user can then submit to you. <br />
<br />
First we should know what happens if an exception is thrown. The operating system now aims to find a handler which tells what to do now. In order to find such a handler the system has a fixed order to search. It will start with the <b>vectored exception handlers</b> (added for example using AddVectoredExceptionHandler). If no handler was found there it will continue and in each frame of the stack it will examine all the <b>frame based exception handlers</b> (try - catch, __try - __except). If no handler suited the exception thrown it will then have a look if a <b>top level exception handler</b> is registered (using SetUnhandledExceptionFilter). If that fails too you will get a window "XY has stopped working" with the commonly known options. There is actually one exception from that behavior: When a debugger is attached. In this case the debugger is automatically installed as the top level exception handler and you cannot change it. Using various settings you can even intercept all of the above mentioned handlers and directly pass every exception to the debugger.<br />
<br />
Well, now how could we get informed that an exception happened that was not properly handled? Using AddVectoredExceptionHandler is not a good idea because every exception that happened will be interpreted as if it was not handled. Thats not what we try to achieve. Installing a frame on top of every thread that gets started and handling every type of exception there is possible but to much work. Also threads started by external components maybe dont act like that and exceptions caused by them wont be recognized.<br />
<br />
The response is using SetUnhandledExceptionFilter. This function lets us register a function that is called if all other handlers failed. As this is the last resort we can be sure that no one "cared" about that exception and that it will lead to an unwanted program termination if nothing is done now. The usage of that function is very easy. All it wants is a pointer to a function which has a special format. It then returns a pointer to the function that was installed before our call so we could reset it if we dont need to handle the exceptions anymore. So to test that we make a simple program:<br />
<pre class="cpp" name="code">#include <Windows.h>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
char* ptr = NULL;
*ptr = 'a';
}
</pre>The return value of our function indicates what the operating system should do next. Returning EXCEPTION_CONTINUE_HANDLER instructs it to execute the handler for that exception. On the top level this actually means that it will directly call ExitProcess. If you run the above code (please make sure you are not attaching any debugger) you will get the messagebox (unless you are in kernel mode) and the application will terminate.<br />
<br />
Now lets experiment with that. First we will look if the function also gets called if we surround the bad code with try - catch(...). First maybe think if you can figure out the response yourself.<br />
<pre class="cpp" name="code">#include <Windows.h>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
try
{
char* ptr = NULL;
*ptr = 'a';
}
catch(...)
{
}
}
</pre><br />
After running the code we know: It gets called! Maybe that is surprising you. If so have a look at the following code:<br />
<pre class="cpp" name="code">#include <Windows.h>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
MessageBox(0, "An exception occured which wasnt handled!", "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
__try
{
char* ptr = NULL;
*ptr = 'a';
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
</pre><br />
Wait, now it is not called?! But why? The answer is pretty simple: There are two main types of exceptions. The first type are exceptions that are thrown using the keyword 'throw'. They are called C++-exceptions. These exceptions get caught using the try-catch statement. The other type are exceptions that are thrown by the operating system in response of faults that happened. These are called SEH-exceptions (structed exception handling). To catch such an exception there must be a frame which catches exceptions using __try - __except. We see the EXCEPTION_EXECUTE_HANDLER here again. In this case the executed "handler" is the part in the scope after __except.<br />
<br />
As dereferencing the NULL-Pointer and assigning a value to it in user mode is not allowed the operating system indicates a fault and throws a SEH-exception. Those exceptions cannot be handled by try - catch statements. Therefore in the first code the exception is passed to our function. But in the second code the exception is caught and the program can continue so our function is not called.<br />
<br />
Well, now our messagebox does not really contain a lot of information. A user which sees that message wont have an idea what to do and if he submits it to you this wont help at all. So providing some more information would be helpful. So we'll use the parameter our exception handler receives to find additional information about the exception which we can show to the user. The most important things one should now are the following two:<br />
What happened?<br />
Where did it happen?<br />
<br />
The answer to both questions lies inside the exceptionInfo parameter. And here is how we can access it:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include <iostream>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
char message[255];
sprintf_s<255>(message,
"An exception occured which wasnt handled!\nCode: 0x%08X\nAddress: 0x%08X",
exceptionInfo->ExceptionRecord->ExceptionCode,
exceptionInfo->ExceptionRecord->ExceptionAddress
);
MessageBox(0, message, "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
char* ptr = NULL;
*ptr = 'a';
}
</pre><br />
I think this is pretty self-explaining. Though there is one major problem with the exception address. If our binary uses ASLR (Address Space Layout Randomization) its base address will start at a random address at every launch. Therefore the address is completely useless for us as we dont know where the binary starts. To solve that problem we could print the start and end address for every module loaded into the message box which would allow us to exactly determine in which module at which offset the exception happened or we just print the start of the main module and the offset from there. The second version is less informative because if the exception didnt happen in the main module we again have an offset which is not really useful. But anyway, we will use the second approach as we focus on our executable.<br />
<br />
<pre class="cpp" name="code">#include <Windows.h>
#include <iostream>
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
DWORD codeBase = (DWORD)GetModuleHandle(NULL);
char message[255];
sprintf_s<255>(message,
"An exception occured which wasnt handled!\nCode: 0x%08X\nOffset: 0x%08X\nCodebase: 0x%08X",
exceptionInfo->ExceptionRecord->ExceptionCode,
(DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
codeBase
);
MessageBox(0, message, "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
char* ptr = NULL;
*ptr = 'a';
}
</pre><br />
Now we have an offset which can be used to determine which instruction caused the exception. If you start google and search for "Exception code 0xC0000005" you will find that this stands for an access violation. Wouldnt it be nice to show EXCEPTION_ACCESS_VIOLATION instead of 0xC0000005? There is a simple way doing that using a little macro that converts the predefined codes into a friendlier form:<br />
<pre class="cpp" name="code">#include <Windows.h>
#include <iostream>
#define EXCEPTION_CASE(code) \
case code: \
exceptionString = #code; \
break
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
const char* exceptionString = NULL;
switch(exceptionInfo->ExceptionRecord->ExceptionCode)
{
EXCEPTION_CASE(EXCEPTION_ACCESS_VIOLATION);
EXCEPTION_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
EXCEPTION_CASE(EXCEPTION_BREAKPOINT);
EXCEPTION_CASE(EXCEPTION_SINGLE_STEP);
EXCEPTION_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
EXCEPTION_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
// add more cases...
default:
exceptionString = "Unknown exception";
break;
}
DWORD codeBase = (DWORD)GetModuleHandle(NULL);
char message[255];
sprintf_s<255>(message,
"An exception occured which wasnt handled!\nCode: %s (0x%08X)\nOffset: 0x%08X\nCodebase: 0x%08X",
exceptionString,
exceptionInfo->ExceptionRecord->ExceptionCode,
(DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
codeBase
);
MessageBox(0, message, "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
char* ptr = NULL;
*ptr = 'a';
}
</pre><br />
Now the user sees a better readable name for the exception code. Have a look at this article on MSDN to get a list with all defined exception codes that commonly occur: <a href="http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx">Article</a><br />
<br />
Now lets change the main function to the following:<br />
<pre name="code" class="Cpp">int main()
{
SetUnhandledExceptionFilter(UnhandledException);
throw "An error!";
}
</pre><br />
Even if you defined all cases from the MSDN-article here you will get "Unknown exception (weird hex-number)". What does that number stand for? Maybe its a pointer to the string we have thrown? And beside that, why do we get such a huge offset? Our executable isn't that big! To answer the second question first: throw will actually be replaced by the compiler to a internal function call to CxxThrowException which then again calls RaiseException. The offset you get is the offset to RaiseException as this is considered the source of the exception and RaiseException lies inside the ntdll.dll which is loaded in high memory regions. See the following extract from IDA Pro:<br />
<pre>.text:7DE80000 ; File Name : C:\Windows\System32\ntdll.dll
.text:7DE80000 ; Format : Portable executable for 80386 (PE)
.text:7DE80000 ; Imagebase : 7DE70000
</pre><br />
To answer the first question try throwing different things. Throw an integer, throw nothing (just throw;), throw another string, ... . You will notice that the hex-number will always be the same (<b>0xE06D7363</b>). So obviously it has nothing to do with the content thrown. No, it denotes that the thrown exception was a C++ exception (remember, these are exceptions thrown by the programmer using throw). So every time you use throw you will get the code mentioned above. So we can extend our switch with that static code:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include <iostream>
#define EXCEPTION_CASE(code) \
case code: \
exceptionString = #code; \
break
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
const char* exceptionString = NULL;
switch(exceptionInfo->ExceptionRecord->ExceptionCode)
{
EXCEPTION_CASE(EXCEPTION_ACCESS_VIOLATION);
EXCEPTION_CASE(EXCEPTION_DATATYPE_MISALIGNMENT);
EXCEPTION_CASE(EXCEPTION_BREAKPOINT);
EXCEPTION_CASE(EXCEPTION_SINGLE_STEP);
EXCEPTION_CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
EXCEPTION_CASE(EXCEPTION_FLT_DENORMAL_OPERAND);
// add more cases...
case 0xE06D7363:
exceptionString = "C++ exception (using throw)";
break;
default:
exceptionString = "Unknown exception";
break;
}
DWORD codeBase = (DWORD)GetModuleHandle(NULL);
char message[255];
sprintf_s<255>(message,
"An exception occured which wasnt handled!\nCode: %s (0x%08X)\nOffset: 0x%08X\nCodebase: 0x%08X",
exceptionString,
exceptionInfo->ExceptionRecord->ExceptionCode,
(DWORD)exceptionInfo->ExceptionRecord->ExceptionAddress - codeBase,
codeBase
);
MessageBox(0, message, "Error!", MB_OK);
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(UnhandledException);
throw "An error!";
}
</pre><br />
So far those are the most important things you should now about displaying generic information about every type of exception. In upcoming articles we will have a look on how we can give more information which will require us to perform individual actions for each type of exception.<br />
<br />
Thanks for reading and happy commenting<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com11tag:blogger.com,1999:blog-4612363629559028319.post-73949325607443411102011-03-26T08:30:00.000-07:002011-03-26T08:32:53.961-07:00Using WMI to call method on objectsHello everyone<br />
<br />
As the title states in this article we will have a look on how to call methods on objects we have got in WMI. In the example source code we will stick on printers and call the SetDefaultPrinter method on an instance of a printer.<br />
<br />
Functions can be called as static functions or they can be called on an object. For the function mentioned above it may be pretty clear that we need to call it as part of an object (which actually indicates the printer to be the default one).<br />
<br />
We will start with a part of the code presented in the last part of the WMI articles (See here). This actually just initializes WMI and connects to the CIMV2 namespace.<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
if((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
</pre>Now what we need to identify our printer is a value that identifies it. I used the Caption but you can also choose other keys. You can find the caption of your printers in the control panel under "Devices and Printers" (also linked when you press Start). This will look somehow like that but with your printers: <br />
<img src="https://sites.google.com/site/win32easy/viewPrinter.jpg" /> <br />
<br />
The tick in the green circle indicates that the printer is the default printer. In my case its the PDFCreator. Now i want to make the HP Deskjet my default printer. So i rember the name "HP Deskjet F4100 series" which will be the caption used to query it. To query a special object we can use the WHERE claue in the query. That gives this code <br />
<pre class="Cpp" name="code">IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_Printer WHERE Caption = 'HP Deskjet F4100 Series'", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
cout << "Unable to retrive the printer: " << std::hex << hRes << endl;
return 1;
}
</pre>Now we have an enumerator for the printers which are named "HP Deskjet F4100 Series" (case insensitive). Even if there is only one printer matching the criteria you will still get enumerator to enumerate all of them (which is only one...). The next step we could do is actually not necessary for that particular function. When we call GetMethod in a IWbemClassObject we can query information about a method. This includes parameters that are used by the function as input and parameters that are output by the function. The second one (output) is pretty useless if you will call the function because the call actually will also return an IWbemClassObject containing all the output parameters of the function. The input parameter object is actually also not really useful because if you call a function you actually already know what input parameters it expects. Thats why the GetMethod method is actually more for informative purpose if you dont plan to call the function afterwards. In our case its even worse, we dont have any Input or Output parameters so we dont need that at all. So we can start enumerating the objects right on. Every instance of a certain object (in our case Win32_Printer) becomes it unique path. Also objects themselves have paths. <br />
<br />
For example a path for the object would be: \\ADMIN-PC\root\CIMV2:Win32_Printer <br />
<br />
A path for an instance of that object could be: \\ADMIN-PC\root\CIMV2:Win32_Printer.DeviceID="HP Deskjet F4100 series" <br />
<br />
To obtain the path of our instance we can query the __PATH property of the object. So our loop starts like that: <br />
<pre class="Cpp" name="code">IWbemClassObject* clsObj = NULL;
int numElems;
while((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if(FAILED(hRes))
break;
VARIANT vtPath;
VariantInit(&vtPath);
if(FAILED(clsObj->Get(L"__Path", 0, &vtPath, NULL, NULL)))
{
cout << "Object has no __Path!" << endl;
clsObj->Release();
continue;
}
</pre>To call a method we use the IWbemServices interface which exposes a method called ExecMethod. This method first expects the path of the object or instance the function should be called on. If you are calling a static function line Win32_Process.Create you should provide the path to the object and if you are calling a non-static method like SetDefaultPrinter you should give the path to an instance. The second parameter is pretty simple just the name of the function to call. The flags and context parameters are not important now but interesting are the parameters pInParams and ppOutParams. The first expects a pointer to a IWbemClassObject which has properties that holds the input parameters for that function. For example the function Win32_Process.Create has an input parameter called CommandLine. Therefore your IWbemClassObject which will be put as pInParams must define a property with the name CommandLine and its value should be the command line. Our function has no parameters so we can pass NULL. ppOutParams will hold a pointer to a IWbemClassObject after the function has completed. This object has a property for each output parameter and one special property called "ReturnValue". So we can call the function like that: <br />
<br />
<pre class="Cpp" name="code">IWbemClassObject* pResult = NULL;
if(FAILED(hRes = pService->ExecMethod(vtPath.bstrVal, L"SetDefaultPrinter", 0, NULL, NULL, &pResult, NULL)))
cout << "Unable to set the default printer: " << std::hex << hRes << endl;
</pre><br />
Next we want to extract the returned value if the function has succeeded. As i mentioned above this value is stored in the property "ReturnValue". So we query that property from the returned result object.<br />
<pre class="Cpp" name="code">else
{
VARIANT vtRet;
VariantInit(&vtRet);
if(FAILED(hRes = pResult->Get(L"ReturnValue", 0, &vtRet, NULL, 0)))
cout << "Unable to get return value of call: " << std::hex << hRes << endl;
else
cout << "Method returned: " << vtRet.intVal << endl;
VariantClear(&vtRet);
pResult->Release();
}
</pre><br />
Thats it! We have called the function and got its return value. All left now is releasing everything we dont need anymore and exit the program.<br />
<pre class="Cpp" name="code">VariantClear(&vtPath);
clsObj->Release();
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
cin.get();
return 0;
}
</pre><br />
And here is the complete source code again:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
if((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_Printer WHERE Caption = 'HP Deskjet F4100 Series'", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
cout << "Unable to retrive the printer: " << std::hex << hRes << endl;
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if(FAILED(hRes))
break;
VARIANT vtPath;
VariantInit(&vtPath);
if(FAILED(clsObj->Get(L"__Path", 0, &vtPath, NULL, NULL)))
{
cout << "Object has no __Path!" << endl;
clsObj->Release();
continue;
}
IWbemClassObject* pResult = NULL;
if(FAILED(hRes = pService->ExecMethod(vtPath.bstrVal, L"SetDefaultPrinter", 0, NULL, NULL, &pResult, NULL)))
cout << "Unable to set the default printer: " << std::hex << hRes << endl;
else
{
VARIANT vtRet;
VariantInit(&vtRet);
if(FAILED(hRes = pResult->Get(L"ReturnValue", 0, &vtRet, NULL, 0)))
cout << "Unable to get return value of call: " << std::hex << hRes << endl;
else
cout << "Method returned: " << vtRet.intVal << endl;
VariantClear(&vtRet);
pResult->Release();
}
VariantClear(&vtPath);
clsObj->Release();
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
return 0;
}
</pre><br />
I hope you have learned how methods are called and when you run the above code you will see that your printer is now the default one!<br />
<img src="https://sites.google.com/site/win32easy/viewPrinter2.jpg" /><br />
<br />
Thanks for reading and bye<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com1tag:blogger.com,1999:blog-4612363629559028319.post-31608426819753342332011-03-25T17:00:00.000-07:002011-03-25T17:01:42.889-07:00WMI in C++ - Query everyting from your OS!Hi everyone<br />
<br />
In this article i will give you some information how you can dig into the deep waters of WMI which is a part of the Windows API that is designed to give feedback to queries about software and hardware specifications of the windows system the calling application is executing on or even on remote machines. This goes from simple things like the version of the installed windows over installed software and running processors up to very detailed stuff like the number of cycles the fan of your cooler (if you have a fan cooling the CPU) made so far.<br />
<br />
WMI is designed to act like a huge database system. Such a system contains databases, tables and rows. Thats also what WMI provides us. We can select objects from tables using a SQL like syntax. For example the following would be a legit query in WMI:<br />
<pre name="code" class="sql">SELECT * FROM Win32_Session;
</pre><br />
In WMI databases are not called databases but namespaces. On your system there may be various namespaces available. One with very interesting tables is the namespace "CIMV2". It contains tables for nearly everything that acts on your computer! As with any other database you first need to connect to it. This is done using the interface IWbemLocator. This interface (and all subsequent ones) are defined in the header file WbemCli.h. The CLSID for those interfaces are defined in wbemuuid.lib. So this results in our first code snippet:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
pLocator->Release();
return 0;
}
</pre><br />
Thats just some COM-stuff, nothing special. The IWbemLocator interface now exposes a method called ConnectServer. This function connects to a namespace. We will be using CIMV2 so thats where we will connect to. As a result of that function we get an interface called IWbemServices. Imagine that like an open connection to the database. As i stated above you can also connect to namespace on a different machine. So the ConnectServer accepts also a username, a password and an authority to connect. As we will just use the current user on the local machine we dont need to supply that and can pass NULL to all of them and we set root as the location where the namespace should be searched. Its important to specify WBEM_FLAG_CONNECT_USE_MAX_WAIT as flag to indicate that the function should abort after MAX_WAIT time has passed. So we can prevent that the function never returns if the remote host for example is not ready.<br />
<br />
Here is some more code:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
pService->Release();
pLocator->Release();
return 0;
}
</pre><br />
Now we are ready to query information from the CIMV2 namespace! This is done using the function ExecQuery from the IWbemService interface. This function will return an enumerator which enumerates all objects that match the query. This enumerator can be speed up if it must not be a bidirectional enumerator. Therefore if you dont need it its good to specify that in ExecQuery. The first parameter of ExecQuery theoretically would allow to specify the type of language that is used in the query but at the moment the only valid value is WQL. So we get the following code.<br />
<pre name="code" class="cpp">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
cout << "Unable to retrive desktop monitors: " << std::hex << hRes << endl;
return 1;
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
return 0;
}
</pre><br />
If you compile that code and run it you will most likely run into problems because it will print Unalbe to retrieve desktop monitors. Thats because all those objects are encapsulated into security levels. At the moment our application has not chosen any security level and is therefore assigned to the lowest. From this layer we cannot access that object! In order to do that we call the function CoInitializeSecurity right after CoInitialiize. Please refer to MSDN for a full description of security levels (until i wrote an article about that). Just believe that for the current operation (and most common ones) the following is fairly enough:<br />
<pre>CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);</pre><br />
Adding that after CoInitialize should remove the error encountered above! That means we are now ready to enumerate through the objects! The enumerator is pretty easy to handle. IEnumWbemClassObjects exposes a method called Next. This method request a chunk of objects from the collection and returns how many objects were extracted. Also here its important to know that these objects could be on another machine. So Next also expects a parameter indicating how long it should wait for the objects to respond. As we are on our own computer i specify INFINITE. That yields the following code:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
if((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
cout << "Unable to retrive desktop monitors: " << std::hex << hRes << endl;
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if(FAILED(hRes))
break;
clsObj->Release();
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
return 0;
}
</pre><br />
Now finally we have a IWbemClassObject that exposes the properties of the selected object. This is done using the Get function. The usage is pretty simple! We query the Description of the monitor in this example:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include <iostream>
#include <WbemCli.h>
#pragma comment(lib, "wbemuuid.lib")
int main()
{
using std::cout;
using std::cin;
using std::endl;
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
cout << "Unable to launch COM: 0x" << std::hex << hRes << endl;
return 1;
}
if((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
cout << "Unable to initialize security: 0x" << std::hex << hRes << endl;
return 1;
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
cout << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
return 1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_DesktopMonitor", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
cout << "Unable to retrive desktop monitors: " << std::hex << hRes << endl;
return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if(FAILED(hRes))
break;
VARIANT vRet;
VariantInit(&vRet);
if(SUCCEEDED(clsObj->Get(L"Description", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR)
{
std::wcout << L"Description: " << vRet.bstrVal << endl;
VariantClear(&vRet);
}
clsObj->Release();
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
return 0;
}
</pre><br />
Thats it, we now successfully accessed our first objects from WMI!<br />
<br />
For a full list of classes available please have a look at the following link:<br />
<a href="http://msdn.microsoft.com/en-us/library/aa394554(v=VS.85).aspx">MSDN</a><br />
<br />
In the next part we will have a look on how to call methods inside those objects!<br />
<br />
Thanks for reading and bye bye<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com4tag:blogger.com,1999:blog-4612363629559028319.post-85495183247724070002011-03-25T16:15:00.000-07:002011-03-25T16:15:35.259-07:00Dialog Controls explained - Part 1Hello<br />
<br />
In this series of articles i will describe you the usage of several common controls that are used together with windows. Here it actually doesn't matter if you are using a dialog resource and DialogBox to create the window or if you are doing it the manual way using CreateWindow for the main window and all its controls. All you need is just a HWND to that control you are interacting with. Tough in this article for now you can only see the source code that uses a dialog template to create the window. So if you are not using a dialog resource just stick to the part we are actually acting with the controls.<br />
<br />
The base part of this project is an empty dialog with no controls on it and the following code that displays it:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
Now lets start adding controls to it!<br />
<br />
<br />
<b><span style="color: blue;"><span style="font-size: 18;">The common button control</span></span></b><br />
<br />
Buttons are represented by the following window class: "Button" (pretty unexpected...)<br />
<br />
We can drag & drop button from the toolbox onto our dialog:<br />
<img src="https://sites.google.com/site/win32easy/dlgAddButton.jpg" /><br />
<br />
The property bar in Visual Studio already gives you a lot of customization options. As every of them is described pretty well inside the property view i think its not really necessary to talk about them. If you are unsure about one just leave a comment!<br />
<br />
Well, the most important thing buttons are for is handling clicks. Thus we should know what happens if we click on a button. This is rather simple. The button sends a WM_COMMAND message to its parent window setting wParam and lParam to appropriate values. Its like that:<br />
HIWORD(wParam) = notification code = BN_CLICKED<br />
LOWORD(wParam) = Control ID = IDC_BUTTON1 (for this button in my case)<br />
lParam = Control handle = some value we dont know yet<br />
<br />
So to handle a click from a button all you need to do is catching WM_COMMAND in the DialogProc (or WndProc if you are using a regular window) and interpret the values!<br />
<br />
Thats an example code that handles the click on our button:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
{
if(LOWORD(wParam) == IDC_BUTTON1)
{
if(HIWORD(wParam) == BN_CLICKED)
MessageBox(0, "Button clicked!", "", MB_OK);
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
All we do is catching WM_COMMAND and then we compare if the ID is our button and if the code is BN_CLICKED. Thats pretty easy!<br />
<br />
As a side note there are interesting styles for buttons defined in CommCtrl.h! For example the following code:<br />
<pre class="Cpp" name="code">#include <windows.h>
#include "resource.h"
#include <commctrl.h>
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
// do something if hButton == NULL
LONG oldStyle = GetWindowLongPtr(hButton, GWL_STYLE);
oldStyle |= BS_SPLITBUTTON;
SetWindowLongPtr(hButton, GWL_STYLE, oldStyle);
}
return TRUE;
case WM_COMMAND:
{
if(LOWORD(wParam) == IDC_BUTTON1)
{
if(HIWORD(wParam) == BN_CLICKED)
MessageBox(0, "Button clicked!", "", MB_OK);
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</commctrl.h></windows.h></pre><br />
Lets the button look like that:<br />
<img src="https://sites.google.com/site/win32easy/dlgButtonSplit.jpg" /><br />
<br />
but be aware: This is only available from Windows Vista on!<br />
<br />
Another neat feature of buttons is that they can display images! This is done pretty easy. In the property page you can set the "Bitmap" property to true which will instruct the button to display a bitmap (of course only after we send BM_SETIMAGE). With that in mind the following code can be used to add the image to the button:<br />
<pre class="Cpp" name="code">#include <windows.h>
#include "resource.h"
#include <commctrl.h>
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hButtonBackg = (HBITMAP)LoadImage(0, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
// do something if hButton == NULL
SendMessage(hButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hButtonBackg);
}
return TRUE;
case WM_COMMAND:
{
if(LOWORD(wParam) == IDC_BUTTON1)
{
if(HIWORD(wParam) == BN_CLICKED)
MessageBox(0, "Button clicked!", "", MB_OK);
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
And instead of text now there is an image being displayed (of course only if image.bmp exists in the current folder!). One might expect that setting the bitmap property inside the property page to false will hide the image on the button. But thats not true. That property more says "Only bitmap and no text". If you set Bitmap to false and send BM_SETIMAGE the text and the image will displayed organized on the button!<br />
<br />
And a last nice feature of buttons (starting at Windows Vista) is that they can be used to elevate the current user level (pushing the application into administrator mode).<br />
<br />
If you have windows vista the following code will put an UAC-Shield on the button (this wont handle putting the application into a higher state! It only displays the shield!)<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include "resource.h"
#include <commctrl.h>
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hButtonBackg = (HBITMAP)LoadImage(0, "image2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
HWND hButton = GetDlgItem(hWindow, IDC_BUTTON1);
// do something if hButton == NULL
SendMessage(hButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hButtonBackg);
Button_SetElevationRequiredState(hButton, TRUE);
}
return TRUE;
case WM_COMMAND:
{
if(LOWORD(wParam) == IDC_BUTTON1)
{
if(HIWORD(wParam) == BN_CLICKED)
MessageBox(0, "Button clicked!", "", MB_OK);
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
Note that the other image we sent isnt displayed anymore!<br />
<br />
More to come later...<br />
<br />
Thanks for reading and happy commenting!<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com1tag:blogger.com,1999:blog-4612363629559028319.post-35214211530043748442011-03-24T17:04:00.000-07:002011-03-25T02:10:37.643-07:00Getting static - Tips with static controlsAloha<br />
<br />
This article covers handling of static controls. Those controls are a bit nasty and need to be tweaked so they work correctly. Also it sometimes is not obvious that a control is a static control which we will see later!<br />
<br />
The following code is based on the project created in <a href="http://win32easy.blogspot.com/2011/03/opening-window-creating-dialog.html">this article</a>. If you dont remember how interacting with controls works check out <a href="http://win32easy.blogspot.com/2011/03/using-dialog-using-buttons-co.html">this article</a>.<br />
<br />
Our final application will load an image when a button is pressed and display it inside a picturebox. You maybe are wondering now where there is a static control involved because neither a button nor a picturebox is really static. But in fact a picturebox is considered a static control. To be clearer a picturebox is nothing more than a simple static control with a style that indicates that this control accepts bitmaps as background.<br />
<br />
To start we drag a picturebox control on the dialog and we add a button. I renamed the button to IDB_LOADIMG and left the picturebox as it is. If you save now and open the resource.h you may see that there is only the IDB_LOADIMG and the ID from the picturebox is not present! Why?<br />
<br />
Static controls by default are not listed and cannot be accessed. To change that you have to <b>change the ID of every static control you create. </b>This will immediatly add it to the resource.h. Ok, i renamed my picturebox control to IDC_PICBOX. To set the background of a static control you have to send a message to that control. This is done using the function SendMessage. The message to use is STM_SETIMAGE. So the code looks like that:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hButtonLoad = NULL;
static HWND hPicBox = NULL;
static HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
hButtonLoad = GetDlgItem(hWindow, IDB_LOADIMG);
hPicBox = GetDlgItem(hWindow, IDC_PICBOX);
if(hButtonLoad == NULL || hPicBox == NULL)
{
MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
}
break;
}
return TRUE;
case WM_COMMAND:
{
if(HIWORD(wParam) != BN_CLICKED) // we are only interested in clicks
break;
switch(LOWORD(wParam))
{
case IDB_LOADIMG:
{
SendMessage(hPicBox, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBmp);
break;
}
break;
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
If you run this you need to make sure that an image called image.bmp is in the folder of the executable. LoadImage is used to load that image as a bitmap. The WPARAM of STM_SETIMAGE indicates which type of background we are sending and the LPARAM is in this case a handle to the bitmap.<br />
<br />
When you compile this and run the application and press the button to load the image most likely you will see something like that:<br />
<img src="https://sites.google.com/site/win32easy/imgPrevNoImg.jpg" /><br />
<br />
Hey, where is our image?! The answer: Its not displayed at all! Why? Pretty simple: Have a look at the properties page of the picturebox control inside the dialog editor. You can find the column "type" which currently contains "Frame" (unless you have changed it). This tells the system that the control is just a frame. If you send an image to that control Windows will think "Wow, its nice he sends me an image, but actually im just a frame, i dont display images!". So we need to instruct the operating system that our control should accept bitmaps. We change the "Type" to "Bitmap". You may notice that the control now isnt scalable anymore. This is because it will automatically scale to fit the size of the image that gets loaded.<br />
<br />
If we compile now and rerun the application after pressing the button the image gets displayed, in my case it looks like that:<br />
<img src="https://sites.google.com/site/win32easy/imgPrevImg.jpg" /><br />
<br />
Cool, isnt it? :)<br />
<br />
Thanks for reading and cya<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com3tag:blogger.com,1999:blog-4612363629559028319.post-20615133764398593562011-03-24T16:08:00.000-07:002011-03-24T16:20:57.726-07:00Using a dialog - Using buttons & co.Hi everyone<br />
<br />
This article continues where the first article about dialogs ended. If you didn't read that so far you can do it <a href="http://win32easy.blogspot.com/2011/03/opening-window-creating-dialog.html">here</a>.<br />
<br />
<span style="color: red;"><b>Important notice for users which do not use the paid version of Visual Studio:<br />
Depending on the free editor you are using you maybe need to convert the source code a bit or move files. For example ResEdit creates a resource.h but you need to move it to your projects folder first</b></span>.<br />
<br />
In the article linked above we have seen how we can show and destroy a dialog using a resource inside the executable and the function DialogBox. Now we want to let the user interact with controls on the dialog. In this example we will make a dialog that has a two buttons and an edit box where the user can enter text.<br />
<br />
First we need to design our dialog. Please have a look at the properties tab in visual studio for the dialog and the children to customize them. Here is how i made mine look:<br />
<img src="https://sites.google.com/site/win32easy/dialogCtrls1.jpg" /><br />
<br />
Now in order to identify controls on a dialog every control becomes its own ID. You can view this ID if you select the control and go to the properties tab. There you'll find the column "ID". It contains the name of the control. For my Flash Window button it looks like that:<br />
<img src="https://sites.google.com/site/win32easy/dialogCtrlsID.png" /><br />
<br />
This name will be important later. The Request text button has the ID IDB_REQTEXT and the edit control is named IDC_EDIT1. Thats all for the design. Now we can switch back to the code!<br />
<br />
As all logic will be performed inside the DialogProc function so long all variables will be static ones inside that function. To retrieve handles (accessors) for the controls windows exposes the function GetDlgItem (which means "get item inside dialog") which searches all controls and looks if it matches the given ID. The usage of GetDlgItem is very simple. The first parameter is the dialog that should be searched and the second parameter is the ID (see above) of the control to search.<br />
<br />
This results in the following code:<br />
<pre class="Cpp" name="code">#include <windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hButtonFlash = NULL;
static HWND hButtonReq = NULL;
static HWND hEdit1 = NULL;
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
hButtonFlash = GetDlgItem(hWindow, IDB_FLASH);
hButtonReq = GetDlgItem(hWindow, IDB_REQTEXT);
hEdit1 = GetDlgItem(hWindow, IDC_EDIT1);
if(hButtonFlash == NULL || hButtonReq == NULL || hEdit1 == NULL)
{
MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
}
break;
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}</pre><br />
We are searching the codes as soon as the dialog is ready which is inside WM_INITDIALOG. We also check if we could get handles to all controls we need and if not we sadly need to terminate the application because they are essential!<br />
<br />
Well, now, what happens if the user clicks on the flash button? In fact a message to its owner (which is the dialog) is sent indicating what happened. The ID of that message is WM_COMMAND. For controls of a dialog it has a special layout. The high word of wParam holds the type of command that is sent. The low word of wParam holds the ID of the control that sent the message and lParam holds a handle to that control. Using that we can easily determine if one of our buttons was pressed and also which one as you can see in this code:<br />
<pre name="code" class="Cpp">#include <Windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hButtonFlash = NULL;
static HWND hButtonReq = NULL;
static HWND hEdit1 = NULL;
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
{
hButtonFlash = GetDlgItem(hWindow, IDB_FLASH);
hButtonReq = GetDlgItem(hWindow, IDB_REQTEXT);
hEdit1 = GetDlgItem(hWindow, IDC_EDIT1);
if(hButtonFlash == NULL || hButtonReq == NULL || hEdit1 == NULL)
{
MessageBox(hWindow, "Unable to retrieve controls! Closing....", "Error!", MB_OK);
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
}
break;
}
return TRUE;
case WM_COMMAND:
{
if(HIWORD(wParam) != BN_CLICKED) // we are only interested in clicks
break;
switch(LOWORD(wParam))
{
case IDB_FLASH:
{
FlashWindow(hWindow, TRUE);
break;
}
break;
case IDB_REQTEXT:
{
int textLen = GetWindowTextLength(hEdit1);
if(textLen == 0)
break;
// We need to include the terminating 0, GetWindowTextLength does not count it!
TCHAR* wndText = new TCHAR[textLen + 1];
GetWindowText(hEdit1, wndText, textLen + 1);
MessageBox(hWindow, wndText, "Info", MB_OK);
delete [] wndText;
}
break;
}
}
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
There is one other important thing to say about WM_COMMAND. The high word of wParam which specifies the notification code is not different for every single type of notification that exists. Its only unique for each type of control. For example BN_CLICKED is defined as 0. There are other types of controls which also have the notification code defined which not really means that they were clicked. So always take the type of control that sent the notification into account, thats very important!<br />
<br />
Thanks for reading and cheers<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-27539131251016506702011-03-24T14:08:00.000-07:002011-03-24T14:08:45.796-07:00Messages - The communicationHello there<br />
<br />
In this article I will show how the message system in windows works. The message system is actually used where communication between different thread is necessary. They are used to inform a thread that either something has happened or that the sender needs to know something only the receiving thread can tell. Windows already implements all necessary to work with messages.<br />
<br />
A commonly known place where messages are used are windows. If anything happens with the window the operating system sends a message to the application telling it what happened. For example if you click with the left mouse button on the window the system first sends a message WM_LBUTTONDOW and when you release the button a WM_LBUTTONUP message to the application. Thats how an application gets informed that something happened in its window. There are also dozens of other messages that may be sent from a window.<br />
<br />
Of course messages are not restricted to windows! You can also implement your own message system using the message API. There are several functions that can be used to work with messages. These are examples:<pre name="code" class="Cpp">PostThreadMessage // Sends a message to a thread without waiting what the thread returns!
GetMessage // Takes a message from the current threads message queue. It will not return until a message could be taken
PeekMessage // Takes a message from the current threads message queue. Returns immediatly and indicates if there was message in the queue.
</pre><br />
You can find a full list <a href="http://msdn.microsoft.com/en-us/library/ff468870(v=VS.85).aspx">here</a>Yanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-60286670792445211842011-03-24T13:38:00.000-07:002011-03-25T03:50:17.195-07:00Opening the Window - Creating a dialog!Hello everyone!<br />
<br />
In this article we will focus on how to easily create a basic layout for a window. It is using dialog templates stored as a resource inside an executable or DLL. It is often a lot of work to create a layout for a window just using the <br />
<pre>CreateWindow</pre>function is pretty a mess also because you cannot view directly how it will finally look. Having a WYSIWYG editor would be way easier! Interestingly there exists a simple way to code using such an editor. In order to achieve that you need to create the window from a resource which is embedded into the executable. This resource contains text that describes how the window should be led out. And the best thing is: There are free and paid editors for those files. Ill describe both, one with a free and one with a paid editor.<br />
<br />
<b>Users with a paid version of Visual Studio </b><br />
To add a dialog resource you do the following<br />
<br />
<img src="https://sites.google.com/site/win32easy/dlgAddResource.jpg" /><br />
<br />
This will show up a new dialog window that lets us select which type of resource to add. Obviously we will create a dialog resource!<br />
<br />
<img src="https://sites.google.com/site/win32easy/dlgAddDialog.jpg" /><br />
<br />
The simplest is to just use Dialog. It will create a nice window and show it up in a new UI. There you can freely add controls, change properties of the window or the controls added.<br />
<br />
When you are finished designing the window you can return to your project and you see that there are 2 new files. One is the resource.h which defines symbolic names for the resources and ProjectName.rc. This is the file which describes how resources are called inside the executable.<br />
<br />
<br />
<b>Users which have no paid version of Visual Studio </b><br />
There are free editors available to create a resource script (.rc) file and edit the contents. I think the best one is <a href="http://www.resedit.net/">ResEdit</a>. Its freely available and pretty easy to handle. When finished you will have a .rc file with a dialog resource included. You can drag that .rc file into your project and compile. It will be included into the executable. Thats it!<br />
<br />
<b><span style="color: red;">From now on everything is the same for the paid and the free version.</span> </b><br />
<br />
Simply displaying the dialog is a very easy task. Windows offers us a function called DialogBox. This function expects parameters that specify where to find the dialog resource. Then it shows the dialog and returns when the dialog is destroyed. As usual also dialogs send messages to the application telling it that something interesting may have happened. So the code to show our dialog is pretty simple:<br />
<pre class="Cpp" name="code">#include <Windows.h>
#include "resource.h" // users with ResEdit do not need that because they dont have it
// make sure visual styles are enabled
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
int main()
{
// Users with ResEdit specify "Name of the resource" for the second param
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
The most complex is the DialogProc function. In opposite to regular message handlers it only returns a boolean. This boolean tells the operation system if our application has handled the message or not. The two messages that are important are WM_CLOSE and WM_INITDIALOG. The first message is sent when the user presses the close icon, the latter is sent when the dialog is loaded. In WM_INITDIALOG the return value indicates if the keyboard focus should be set to the control the operating system has chosen or not. This actually the recommended way.<br />
<br />
In WM_CLOSE we first end the dialog using EndDialog and then destroy the window using DestroyWindow. The second parameter of EndDialog will be the value that DialogBox will return!<br />
<br />
Thats it, we have made a nice window without much code!<br />
<br />
<strong><span style="color: red;">Next step</span></strong>: <a href="http://win32easy.blogspot.com/2011/03/using-dialog-using-buttons-co.html">here</a><br />
<br />
Thanks for reading and greetings<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com1tag:blogger.com,1999:blog-4612363629559028319.post-40263226871665584102011-03-24T08:56:00.000-07:002011-03-24T08:57:36.781-07:00Enabling Visual Styles - Make it pretty!Hello there<br />
<br />
A lot of people ask me why in C++ the windows they create look that ugly while in C# or other .NET languages they look very nice. To illustrate what i mean look at the following images:<br />
C++:<br />
<img src="https://sites.google.com/site/win32easy/styleNormal.jpg" /><br />
<br />
C#<br />
<img src="https://sites.google.com/site/win32easy/styleEnhanced.jpg" /><br />
<br />
The reason why this happens lies inside the <a href="http://win32easy.blogspot.com/2011/03/manifests-lets-declare-some-principles.html">manifest</a> (or more exactly the application context). A .NET application automatically generates an application context that loads the Version 6 of the Microsoft.Windows.Common-Controls assembly instead of the default one which is Version 5. While Version 5 renders the common controls without any visual styles Version 6 uses the appropriate styles since Windows XP.<br />
<br />
To achieve that you need to add a dependency inside the <a href="http://win32easy.blogspot.com/2011/03/manifests-lets-declare-some-principles.html">manifest</a> and you need to <a href="http://win32easy.blogspot.com/2011/03/shipping-manifests.html">ship</a> it with your executable. Thats how the source code looks in my example application which is the way i prefer to ship the manifest with my application.<br />
<pre class="Cpp" name="code">#include <windows.h>
#include "resource.h"
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
BOOL WINAPI DialogProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CLOSE:
EndDialog(hWindow, 0);
DestroyWindow(hWindow);
return TRUE;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
int main()
{
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), GetDesktopWindow(), DialogProc);
}
</pre><br />
IDD_DIALOG1 is the numerical constant of a dialog resource embedded inside my executable.<br />
<br />
Thanks for reading and im looking forward reading your comments!<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com1tag:blogger.com,1999:blog-4612363629559028319.post-69024972558740784632011-03-24T07:32:00.000-07:002011-03-24T07:32:59.760-07:00Shipping ManifestsHello there<br />
<br />
In this article we will have a look how to ship a manifest with your application. If you need to know what a manifest is please reference to this <a href="http://win32easy.blogspot.com/2011/03/manifests-lets-declare-some-principles.html">article</a>.<br />
<br />
There are different ways to deploy a manifest with your application. I will refer on how to achieve it using the Microsoft IDE (either for C# or C++ respectively).<br />
<ol><li>In C++ you can directly modify the default manifest using a #pragma directive or the project settings</li>
<li>In C++ you can directly create a manifest as a resource of your application</li>
<li>In C# you have to possibility to add a manifest as a project object and select it as default one</li>
<li>For every component you can ship the manifest as separate file (not recommended!)</li>
</ol>Now lets explain this a bit more:<br />
<br />
<strong><span style="font-size: small;">Modify the default manifest </span></strong><br />
To modify the manifest directly inside your code you can use the #pragma comment(linker, "...") directive. This is an example how this would look like:<br />
<br />
<pre class="Cpp" name="code">#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
</pre><br />
This adds a dependent assembly to the manifest (reference article linked above if you need to know what a dependent assembly is). The same can also be achieved if you go to your project properties. There in the category linker you find the property page "Manifest file". This looks like the following:<br />
<br />
<img src="https://sites.google.com/site/win32easy/propManifestFile.jpg" /><br />
<br />
There you can modify the manifest as you like to.<br />
<br />
<strong>Add a manifest resource</strong><br />
Adding a manifest as a resource is very easy. You can simply create your manifest as you like and add it to the executable with resource type RT_MANIFEST or 24. Its recommended that you choose the name taken in the assemblyIdentity part inside the manifest followed by .manifest as name of the resource. Thats it!<br />
<br />
<br />
<strong>Add a manifest inside C#</strong>Adding manifests in C# is even simpler. Right click into your project and choose Add -> New Item. In the dialog scroll down until you find "Application manifest file" and give it a name. It creates the default entries and lists it in the solution explorer. You can now edit the manifest inside the editor. If you want to make your manifest the default one visit the project settings and go to the "Application" tab. There you find a region with "Resources" which contains a drop down list with possible manifest files to use. Thats it!<br />
<br />
So adding manifests is a very easy thing to do and its worth it ;)<br />
<br />
Thanks for reading and goodbye<br />
Yanick<strong> </strong>Yanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0tag:blogger.com,1999:blog-4612363629559028319.post-92125216778456263062011-03-24T06:32:00.000-07:002011-03-24T06:50:43.528-07:00Manifests - Lets declare some principles!Hello again!<br />
<br />
In this article I like to spend a few words on a concept introduced with Windows XP: Manifest files. These files are used beside an executable to tell various things about the context the program will run in. I think the most common usage of manifests is to enable visual styles in an application. But if we look closer on that we can see that it actually is not like manifests directly <b>enable</b> the visual styles, no, the manifest actually only tells the operating system that our application depends on a so called 'assembly'. Don't be scared, it has nothing to do with assembler, ill explain later what to understand under assemblies and what dependency means.<br />
<br />
So we have learned one important aspect of manifests:<br />
<ul><li>They can declare dependencies to assemblies.</li>
</ul>Ok, but ask yourself: Did you ever find a manifest in programming world yet? I bet no if you didn't intend to ;). So is no one using manifests or what is the reason for that? No, id say every executable you start is using a manifest, but where is it? To answer that question you need to know how the operating system actually searches for that manifest.<br />
<ol><li>It searches in the global cache.</li>
<li> It searches for the first resource inside the executable which has the type RT_MANIFEST (24 on my system) </li>
<li>If nothing is found inside the exe it searches inside the folder if it finds a file named EXENAME.exe.manifest.</li>
</ol>Because modifying a manifest without knowledge about it by an end user may result in severe problems running the application the third method isn't chosen often by deployed programs. As modifying resources at least requires the knowledge how to access and compile resources into a file you can be pretty sure that most users of your application wont be able to accidentally destroy the manifest (and if they do its not our problem :D). Thats the reason why you probably have never seen a manifest file - <b>they are inside the executable!</b><br />
<br />
Well, i think its time now to have a view on an example manifest. If you create a new project in Visual Studio a manifest is automatically generated when you build your application. It can be found inside the Debug (or Release) folder of your project (not solution) and is called 'ProjectName.exe.intermediate.manifest'. It has the intermediate inside it because thats the part that gets automatically added but you can modify that inside the project settings and thus its not the final version but only an intermediate one.<br />
<br />
I named my Project ManifestExample so the manifest is called ManifestExample.exe.intermediate.manifest and the contents are:<br />
<pre class="Xml" name="code"><assembly manifestversion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedprivileges>
<requestedexecutionlevel level="asInvoker" uiaccess="false">
</requestedexecutionlevel>
</security>
</trustinfo>
</assembly> </pre><br />
First thing we see is that manifests are written using the XML syntax. That makes it pretty straightforward to understand and we can focus on the actual elements. What this manifest does is that it defines some security related properties of the application. To be more clear: It declares which access rights the user has to have this application will run in. That is controlled using the 'level' attribute inside the requestedexecutionlevel tag. There are 3 values valid for the level attribute:<br />
<ol><li>asInvoker -> The application will run with the same privileges as the calling user</li>
<li>highestAvailable -> The application will run with the highest privileges the current user can reach</li>
<li>requireAdministrator -> The application must be run in administrator mode (on Vista and Win7 a window will pop up asking the user to allow the application to run as administrator if thats enabled)</li>
</ol>The default value of course is asInvoker as thats pretty neutral.<br />
<br />
The <b>uiaccess</b> attribute is a bit more complex. Imagine you are writing an application that simulates a keyboard on the monitor where the user can make input. Now it may be necessary to bypass regular input control mechanics to work properly. To be able to do that the uiaccess attribute must be set to true.<br />
<br />
In addition setting uiaccess to true requires some additional security options! The application first has to be signed by Authenticode and second it has to be in protected folder (for example system32 or program files).<br />
<br />
Second thing we learned about manifests:<br />
<ul><li>Manifests define security aspects of an application.</li>
</ul>Now lets have a look at a manifest that does what i ment above: Add a dependency to an executable. In this example we add a dependency to the assembly called "CommonControls". It has to be said that your application be default already has a dependency to CommonControls but it depends on version 5 of CommonControls which contains the old visual themes and we need version 6 which contains the new visual themes since XP!<br />
<ol><li><br />
</li>
</ol><pre class="Xml" name="code"><?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type='win32'
name='Microsoft.Windows.Common-Controls'
version='6.0.0.0'
processorArchitecture='*'
publicKeyToken='6595b64144ccf1df'
language='*'
/>
</dependentAssembly>
</dependency>
</assembly>
</pre><br />
<br />
The new tags we see are dependency, dependentAssembly, assemblyIndentity. The dependency tag lists a dependency for application the dependentAssembly tag hosts a dependency to an assembly and the assemblyIndentity tag finally specifies the assembly our application is depending from. There we find several possible attributes that identify the assembly. Actually only two of them are required the rest is optional and is used to distinguish it from other assemblies that may have the same attributes.<br />
<br />
Explanation:<br />
<ul><li>type - Optional - Only valid value is win32</li>
<li>name - Required - The name of the assembly</li>
<li>version - Required - The version of the assembly to load</li>
<li>processorArchitectur - Optional - May be clear. Valid values are (ia64, amd64, x86, msil)</li>
<li>publicKeyToken - Optional - The strong name of the assembly</li>
<li>language - Optional - The language ID of the assembly</li>
</ul>As you can see we request version 6 of the Common-Controls which means controls with new visual styles!<br />
<br />
Now its time to talk about how the system finds an assembly. This is actually pretty simple. The system does the same as it does when you launch an application. In the above code it will search a manifest which denotes an assembly witch defines an assemblyIdentity that matches the requested one. In our case it searches the following way:<br />
<ol><li>It searches the Microsoft.Windows.Common-Controls.dll inside global search paths and inside the current executables path. If it finds that dll it searches a manifest resource inside that dll that is called "Microsoft.Windows.Common-Controls.manifest" and compares it.</li>
<li>If that didnt succeed the system searches in the same paths for a file called Microsoft.Windows.Common-Controls.manifest and parses it</li>
<li>If that failed it searches for the folder "Microsoft.Windows.Common-Controls" inside all global search paths and the current executable path and does the same search as above again</li>
</ol>To be identified a component (for example a DLL) must have a manifest that defines a global assemblyIdentity. That actually makes it an recognizable assembly inside the system. Here is an example manifest that identifies everything its included into as an assembly of the given name (and does nothing more):<br />
<br />
<br />
<ol></ol><ul></ul><pre class="xml" name="code"><?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="Win32"
name="MyNiceAssembly"
version="1.0.0.0"
/>
</assembly>
</pre><br />
We learn:<br />
<ul><li>Manifests can be used to give any component (DLL, exe, ...) a name with which it can be identified</li>
</ul>Thats it for this article! Feel free to post comments or ask questions. I dont think that everything got clear enough for everyone so im really happy if you tell me your problems or questions!<br />
<br />
Thanks<br />
Yanick<br />
<ul></ul>Yanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com1tag:blogger.com,1999:blog-4612363629559028319.post-83350289650004575922011-03-24T05:13:00.000-07:002011-03-24T05:13:20.586-07:00Hello world!As the title says: Hello world!<br />
<br />
Well I guess that I should write some very cool lines here as those are the first published on that new blog out in the internet but if you ask people from my personal environment you most likely will always here the same response: "Oh dear, he's just terrible at writing stuff like that!". To be honest they're not really wrong with that ;). Regarding this fact ill just focus on giving you a little preview on what this blog will be about.<br />
<br />
Within this blog you will be able to find articles and tutorials about various aspects of the application programming interface (API) all Windows versions provide. It will cover commonly known aspects (like creating windows, interacting with the user, operating with files, ...) together with subjects that may be less known to the broad public (like manifests, mechanics of COM, visual themes, ...). <strong>It is always my main goal to bring these topics to you on a way that is understandable also for people that never used the Win32 API until yet.</strong><br />
<br />
In the preceding paragraphs I used the word "programming". This brings us to an important question: "What knowledge do I need to have to understand what you are writing about?". Actually this depends on each article. If you for example start understanding COM its recommended that you know the fundamental datatypes used in the API or how to act with the registry. Of course if I make an article about a subjects and it covers knowledge that was taught in previous (or upcoming) articles i will link to them so that you can read through them if something is not clear. Concerning that it actually will be possible to read every article and understand it even if you have never used the API before. It may just take longer because you need to read and understand all of the other articles that may be linked! Of course at the beginning that may not be true as I just haven wrote enough articles to make references to every topic. To be honest there is one very important fact you should know: <strong>This is not an introduction in the programming languages used!</strong> (mostly C++ and C#) You need to know the basic concepts of the programming languages as they will not be explained in the articles! But don't worry, it really just means the basics.<br />
<br />
Here are some books that may help you with that if you never used C++ or C# before:<br />
<a href="http://www.amazon.com/Primer-4th-Stanley-B-Lippman/dp/0201721481">C++ Primer by Stanley B. Lippman</a><br />
<a href="http://www.amazon.com/Primer-Plus-5th-Stephen-Prata/dp/0672326973">C++ Primer by Stephen Prata (i used that at university)</a><br />
<a href="http://www.amazon.com/Microsoft%C2%AE-Visual-2010-Step-ebook/dp/B004OR1XRO">Microsoft Visual C# 2010 Step by Step by John Sharp (Kindle edition)</a><br />
<a href="http://www.amazon.com/2010-NET-Platform-Andrew-Troelsen/dp/1430225491/ref=tmm_pap_title_0">Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen</a><br />
<br />
Ok, now we have talked enough about what will be here soon and i think its time to start writing articles. Make sure to recheck that blog regularly even if theres nothing interesting for you know. Maybe tomorrow there will be a new article that covers a new subject that attracts you ;).<br />
<br />
See you<br />
YanickYanickhttp://www.blogger.com/profile/17025235562972849437noreply@blogger.com0