Load PNG/JPEG from resource using GDI+ (MASM)

Following my previous post on how to load JPG/PNG file from resource using GDI+:
http://devpinoy.org/blogs/cvega/archive/2008/07/28/loading-png-and-jpg-image-from-resource-using-gdi.aspx

I’ve written an equivalent function for MASM32 users:
http://www.masm32.com/board/index.php?topic=10191.0

Just follow these simple steps and you’re set to use resource image in your program in no time.

    gdiplusLoadBitmapFromResource,
              hInstance,
              resourceName,
              resourceType,
              outImage

    where:
       hInstance      - the module handle where to load the resource
       resourceName   - the name or the ID of the resource
       resourceType   - string pointer that will indicate the type
                        of the resource., e.g., "PNG",0
       outImage       - address of variable where to put the handle
                        of loaded image


Here's how to use it:

1. Add the function gdiplusLoadBitmapFromResource to your program, or include gdiplusLoadBitmapFromResource.inc.

2. Add the proto (so you can use INVOKE to call gdiplusLoadBitmapFromResource):

gdiplusLoadBitmapFromResource proto :HMODULE, :LPSTR, :LPSTR, :DWORD


3. Initialize GDI+ on your program's start

GdiplusStartupInput struc
    GdiplusVersion dd ?
    DebugEventCallback dd ?
    SuppressBackgroundThread BOOL ?
    SuppressExternalCodecs BOOL ?
GdiplusStartupInput ends

.data
      gdiplusToken dd ?
      gdiplusSInput GdiplusStartupInput <1, NULL, FALSE, FALSE>

.code
      invoke GetModuleHandle, 0
      mov hInstance, eax
     
      ; Initialize GDI+
      invoke GdiplusStartup, addr gdiplusToken, addr gdiplusSInput, NULL


4. In your resource script, add your image with specified type, something like:

9000 PNG "myImage.png"


where
9000 is the ID of the resource, and PNG is the type

5. Add a null-terminated string entry to your data section for the type of resource, e.g., "PNG"

.data
    pngImage dd NULL
    pngType db "PNG", 0


6. Load the image using gdiplusLoadBitmapFromResource:

invoke gdiplusLoadBitmapFromResource, hInstance, 9000, addr pngType, addr pngImage


7. When you're done using the image, dispose it using GdipDisposeImage function:

invoke GdipDisposeImage, addr pngImage


8. Finally, shutdown GDI+ before you exit your program:

invoke GdiplusShutdown, gdiplusToken


Hope you find this little code useful.



Cheers,

-chris



 

 

Posted by cvega with no comments
Filed under:

[REDUX] Message Cracker for MASM

About 3 years ago, I’ve released a MASM version of message cracker for handling windows messages here:  http://devpinoy.org/forums/p/516/1524.aspx#1524

I really find this include file useful whenever I am working on a GUI based win32 program using MASM. Unfortunately, only few people know about it, so I hope this blog post will provide a late introduction about what this include file is all about.


About message cracker:


To make it simple, message cracker is a set of macros that you can line-up to your message-handling routine to enable window-message handling to a separate (or inline) procedure. This line-up of macro calls may improve the readability of your program compared to a long list of
.IF/.ELSEIF/.ENDIF.

To see the advantage of using a message-cracker, let’s see how a typical message-handling routine would look like:

WinProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
    LOCAL ps:PAINTSTRUCT

        .if uMsg == WM_INITDIALOG
            invoke LoadIcon, hInstance, ICON_APP
            invoke SendMessage, hWnd, WM_SETICON, ICON_BIG or ICON_SMALL, eax
        .elseif uMsg == WM_COMMAND
            mov eax,  wParam
            .if eax == ID_BUTTON1
            ; ID_BUTTON1 was accessed, handle the event here
            .elseif eax == ID_BUTTON2
            ; ID_BUTTON2 was accessed, handle the event here
            .endif
        .elseif uMsg == WM_PAINT
            invoke BeginPaint, hWnd, addr ps
            ; Peform paint routine here
            nvoke EndPaint, hWnd, addr ps
        .elseif uMsg == WM_CLOSE
              invoke EndDialog, hWnd, 0
        .endif

        xor eax,eax
        ret
WinProc endp

And that’s kind of clean and readable, because the procedure handles only 4 window-messages. However, you can imagine how this procedure will look like if it handles 20 or more window-messages. It will become a long procedure that is hard to trace and not too readable.

And as you have already known it, there’s a neat solution for that kind of situation. This is, to break the handler for each window-message to their own respective handler-procedure. If I break-up a the example above, it will be done similar to:

WinProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
      .if uMsg == WM_INITDIALOG
            push hWnd
            call WmInitDialog
        .elseif uMsg == WM_COMMAND
            push hWnd
            push wParam
            call WmCommand
        .elseif uMsg == WM_PAINT
            push hWnd
            call WmPaint
        .elseif uMsg == WM_CLOSE
              invoke EndDialog, hWnd, 0
        .endif

        xor eax,eax
        ret                
WinProc endp

WmInitDialog proc hWnd:HWND
      invoke      LoadIcon, hInstance, ICON_APP
      invoke      SendMessage, hWnd, WM_SETICON, ICON_BIG or ICON_SMALL, eax
      ret
WmInitDialog endp

WmCommand proc hWnd:HWND, wParam:WPARAM
      mov eax, wParam
      .if eax == ID_BUTTON
      ; ID_BUTTON was accessed, handle the event here
      .elseif eax == ID_BUTTON2
      ; ID_BUTTON2 was accessed, handle the event here
      .endif
      ret
WmCommand endp

WmPaint proc hWnd:HWND
      LOCAL ps:PAINTSTRUCT
      invoke BeginPaint, hWnd, addr ps
      ; Peform paint routine here
      invoke EndPaint, hWnd, addr ps
      ret
WmPaint endp

Then, the more window-messages you add, the more handler-procedure you will need to add as well. Or you may leave it inline if the handler contains only 1 line, similar to what I’ve done to
WM_CLOSE above.

The idea of a message-cracker is just that -> Break the handler for each window-message to their own respective handler-procedure. In addition, the message-cracker helps you get the needed information for quickly handing a particular message.

For example, the
WM_MOUSEMOVE message passes the x and y coordinates of mouse-pointer into LPARAM. You need to extract the high-word (y) and low-word (x) from LPARAM to actually use the x and y coordinate.

When assigning a handler-procedure to handle a window-message, message-cracker will actually do much of the work for these small details. Your handler-procedure will receive only the needed information (argument) to work with the window-message itself.

Here’s how the handler of WM_MOUSEMOVE looks like:

WmMouseMove proc hWnd:HWND, x:DWORD, y:DWORD
      ; add code to handle mouse move
      ret
WmMouseMove endp

There’s no more
LPARAM to worry about. Your handler-procedure will receive x and y coordinates, as it should.


Using it:


First you need to get the message-cracker include file. Download the attachment, and extract the file MsgCrack.inc.

In your program, include the MsgCrack.inc

include MsgCrack.inc

Then you’re ready message cracking.


How to add handler

Inside your window procedure, start cracking messages with this block:

.handle_msg_begin
.handle_msg_end

The .handle_msg_begin accepts 4 optional arguments:

.handle_msg_begin [HWND], [MSG], [WPARAM], [LPARAM], [REG]

The default is:
  HWND = hWnd
  MSG = uMsg
  WPARAM = lParam
  LPARAM = wParam
  REG = EAX


If your window procedure is defined this way:

WndProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
   xor eax, eax
   ret
WndProc endp


Where all the arguments matches the default arguments, then you don’t need to specify anything, just add the block as is:

WndProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
  .handle_msg_begin
  .handle_msg_end

   xor eax, eax
   ret
WndProc endp

However, if your window procedure is defined differently, something like this one:

WndProc proc hWin:DWORD, uMsg:DWORD, aParam:DWORD, bParam:DWORD
   xor eax, eax
   ret
WndProc endp

Then you have to tell the message-cracker which identifier should be used:

WndProc proc hWin:DWORD, uMsg:DWORD, aParam:DWORD, bParam:DWORD
  .handle_msg_begin hWin, uMsg, aParam, bParam, eax
  .handle_msg_end

   xor eax, eax
   ret
WndProc endp


That’s the quick part of it. Check the comment I’ve written inside MsgCrack.inc for detail about these default identifier.

Now, let’s move to the next part. Let’s register a handler-procedure with window-message.  This is done using the macro
.handle_msg with the following arguments:

.handle_msg <window message constant>, <handler function>

Where
<window message constant> is the constant defined in windows.inc include file (MASM32), WM_PAINT, WM_MOUSEMOVE and WM_CLOSE, are some of the window-message constant. The macro won’t work if you used integer value, so you should always use the defined constant. Then the <handler function> is the name of your handler-procedure.

Here’s the similar code above, redefined to use the message cracker:

WinProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
      .handle_msg_begin
            .handle_msg WM_INITDIALOG, WmInitDialog
            .handle_msg WM_COMMAND, WmCommand
            .handle_msg WM_PAINT, WmPaint
            .handle_msg_inline WM_CLOSE
                  invoke EndDialog, hWnd, 0
      .handle_msg_end

        xor eax,eax
        ret                
WinProc endp

WmInitDialog proc hWnd:HWND, defCtrl:HWND, initData:dword
      invoke      LoadIcon, hInstance, ICON_APP
      invoke      SendMessage, hWnd, WM_SETICON, ICON_BIG or ICON_SMALL, eax
      ret
WmInitDialog endp

WmCommand proc hWnd:HWND, id:dword, hWndCtl:HWND, codeNotify:dword
      .if id == ID_BUTTON
      ; ID_BUTTON was accessed, handle the event here
      .elseif id == ID_BUTTON2
      ; ID_BUTTON2 was accessed, handle the event here
      .endif
      ret
WmCommand endp

WmPaint proc hWnd:HWND
      LOCAL ps:PAINTSTRUCT
      invoke BeginPaint, hWnd, addr ps
      ; Peform paint routine here
      invoke EndPaint, hWnd, addr ps
      ret
WmPaint endp

The noticeable difference is the replacement of .if/.elseif/.endif statements into .handle_msg_begin/.handle_msg/.handle_msg_inline/.handle_msg_end. And in the handler-procedures, the arguments have changed to reflect the information passed by the window-message (see the argument list of WmCommand handler).

Now, if you notice
WM_CLOSE message handling is different, because we don’t want to branch the handler to a separate handler-procedure, so we use .handle_msg_inline to indicate that WM_CLOSE handling follows on the next line (inline):

            .handle_msg_inline WM_CLOSE

Another good thing about message-cracker is, you can register similar window-messages to a single handler-procedure, if they share similar argument listing. For example, assigning 3 button-up messages,
WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP to WmButtonUp should be as easy as this:

      .handle_msg WM_LBUTTONUP, WmButtonUp
      .handle_msg WM_MBUTTONUP, WmButtonUp
      .handle_msg WM_RBUTTONUP, WmButtonUp


From this point, I’ve probably covered the how-to-use part of the include file., now let me tell you how you can create your handler-procedure.

Creating Handler Procedure:

Open MsgCrack.inc file, then search the window-message you want to handle e.g., WM_SETCURSOR.  You can see the defined macro for handling that window-message as:

; WM_handler(hWnd:HWND, hWndCursor:HWND, codeHitTest:dword, msg:dword)
.handle_WM_SETCURSOR macro in_hWnd, in_lParam, in_wParam, addr_handler

The part we are interested is the comment line above it, as:
WM_handler(argument-listing)

That’s your cue about the argument listing, inside the parentheses. Copy-it, then paste it in a new procedure, similar to this one:

WmSetCursor proc hWnd:HWND, hWndCursor:HWND, codeHitTest:dword, msg:dword
      ret
WmSetCursor endp

That’s it. For any questions, suggestions, bug-report, or any feedback, please post it below.

See the attachment for the sample program and the include file.

Happy coding.

-chris

 

Posted by cvega with 1 comment(s)
Filed under:

How To: OOP in assembly language

This post is a response to forum question posted by modchip:

"Recently, I've seen a lot of stuff about doing OOP in assembly language. Most of the stuff I've seen almost fried my brain. So... does anybody have some simple (by simple, I mean very simple) examples to get n00bs like me started? What are the basic requirements? What are its advantages? I would definitely want to learn more about this."


Definition:


Objects in assembly is implemented only by using structure (which serves as the class definition), defined to have its first member as a pointer to the class's virtual table (vtable), something like this:

    Animal struc
        vtable dd 0
        m_kind db 32 dup (0)
    Animal ends


Instance methods on the other hand are written as normal procedure having the “instance of the class“ as the first argument, known as the `this’ pointer, see these two methods for the Animal class I’ve written:

    GetKind@Animal proc $this:dword

       mov eax, $this                 ; setup the $this argument to EAX
       add eax, offset Animal.m_kind  ; Add the offset of member variable m_kind
       ret                            ; Return it

    GetKind@Animal endp

    SetKind@Animal proc uses esi edi $this:dword, lpValue:dword

       invoke GetKind@Animal, $this   ; Get the address of the member variable 
       invoke szCopy, lpValue, eax    ; Set it  with different value

       xor eax, eax
       ret

    SetKind@Animal endp


As you can see, there’s nothing fancy about writing methods, all you need is a naming convention that will help you work with unique namings. I use $this as the name of the `this’ pointer, and for method name, I use method name + ‘@’ character + name of the class who owns the method, thus GetKind@Animal and SetKind@Animal. For overloaded methods, I just append '@' + size of arguments. Something like, if I overloaded GetKind@Animal with argument for catching the output, I'll be writing it as: GetKind@Animal@4 where @4 means 1 DWORD argument pass the $this pointer.

Inside each methods, all you need is knowledge of working with assembly structures to get around with the $this pointer. In my example, I simply added the offset of the member I’m interested in, with the $this pointer:

    mov eax, $this                    ; setup the $this argument to EAX
    add eax, offset Animal.m_kind     ; Add the offset of member variable m_kind
my_class struc
        vtable dd 0
    my_class ends


Note: you only need vtable if there are virtual members defined (members that can be overridden by derived classes). I'll get to that on my next post.

This structure also holds all instance variables for that class.
Let’s assume we have a class called Animal with instance variable m_kind as 32 bytes, then our structure will be written like this:

That’s how I set register to point to the correct member variable. The code above, EAX now holds the effective address of Instance.m_kind. Then we can return it, or perform whatever logic we desire to that member variable.


Instanciation:

Creating an instance of the class is simply declaring a variable of type structure we’ve defined earlier:

     .data
       AnimalInstance Animal <>

Then call the constructor as "the first thing" before using the instance (if you want). C++ calls the constructor automagically for you (even creating default constructor for you), but in assembly, it’s up to you whether you want to call the constructor or not (you can actually implement constructorless objects).

Ok, assuming we've declared a default constructor ctor@Animal, calling it is similar to calling assembly procedure, passing the instance as the first argument:

    push offset AnimalInstance
    call ctor@Animal

Similar to calling the constructor above, calling the method is no different. Let’s assume we want to set the animal’s kind to “Bird” by calling the methof SetKind@Animal, you can do it this way: 

    .data
        AnimalInstance Animal <>
        animalInstanceKind db "Bird", 0

    .code
        push offset animalInstanceKind
        push offset AnimalInstance
        call SetKind@Animal

 I suggest to define a prototype for the methods, so we can use the MASM’s invoke:

     SetKind@Animal proto :dword, :dword

   
.code
        invoke SetKind@Animal, addr AnimalInstance, addr animalInstanceKind


Benefits:

I can't think of any good benefits, really. Implementing OOP in a non-OOP compiler is simply a kind of workaround which introduces much work and maintenance than working with procedural which is what's available in assembly language.

Benefits probably will count if OOP is available built-in in an assembler. HLA is one of the 'compiler' that provides this "built-in" functionality; and also, there's ObjAsm32 too, implementing OOP using set of MASM macros (emulating OOP keywords).



Closing:

That’s basically pretty much of it, practice and enjoy OOP in assembly language.
Thanks for reading. I’ll cover Overloading, Inheritance, Static and Virtual members on my next post.

Until the next time, happy coding.  

 

 

Posted by cvega with 2 comment(s)
Filed under: ,

C# seems to preserve left-hand value of an assignment statement

Consider this weird piece of code:

  int[] a = new int[] { 0, 1, 2 };

  int i = 2; // Point it to the last item of array

  // Set the value of array indexed by i while
  // changing the value of i
  a[ i ] = ++i + ++i;


The code above will not cause an array's bounds overflow.

The value of i was incremented (++i) then added to its another incremented value (+ ++i),
but for some reason the left hand part seems to remember the original value of i.

I didn't know that Big Smile

Posted by cvega with 6 comment(s)

Loading PNG (and JPG) image from resource using GDI+

Last night while I was translating some of my old animation program from GDI32 to GDI+, I’ve hit a roadblock where GDI+ cannot load PNG (and JPEG) file stored as resource: 

// This code doesn't work
Gdiplus::Bitmap* m_image = Gdiplus::Bitmap::FromResource(hInst, L"IDB_IMAGE1");

I’m thinking of an alternative using Bitmap::FromStream / FindResource / LoadResource combo, but I have one problem, I’m not familiar with Bitmap::FromStream. So I’ve checked CodeProject for some sample code on how to use Bitmap::FromStream, this I think will be a good start at what I want to do.

While I was searching for sample code, I’ve bumped on an article posted by Joe Woodbury entitled Loading JPG & PNG resources using GDI+ (glad I’ve searched CodeProject before going to MSDN). This article and the demo source code is exactly what I need, so I figure I will write a sample program using his CGdiPlusBitmapResource to test it.

Just to make things quicker and smaller, I’ve used David Nash's Win++ for this sample program:

The class CGdiPlusBitmapResource doesn’t need any documentation., all you have to do is create an instance of this class., and call it’s Load function and you’re technically done:

CGdiPlusBitmapResource* m_image = new CGdiPlusBitmapResource();
m_image->Load(IDB_IMAGE, _T("PNG"), hInst);

 

And draw it using Graphics object:

// Create graphics object from HDC
Gdiplus::Graphics g(hDC);

// Draw the PNG image using graohics object
g.DrawImage(*m_image, 0, 0);

 


That’s about it. Then you can delete the m_image when you’re done using it.
Check attached sample program for a working demo. It contains Win++ for writing C++ Win32 application, and CGdiPlusBitmap.h header file for loading images from resources.

If you want to know more about GDI+, here' a good article: Starting with GDI+

Posted by cvega with 2 comment(s)
Filed under: ,

WTL links

Definition taken from Wikipedia Big Smile

The Windows Template Library (WTL) is a free software, object-oriented C++ template library for Win32 development. WTL was created by Microsoft employee Nenad Stefanovic for internal use and later released as an unsupported add-on to Visual Studio and the Win32 Framework SDK. It was developed primarily as a light-weight alternative to the Microsoft Foundation Classes and builds upon Microsoft's ATL, another lightweight API widely used to create COM and ActiveX libraries.

As the subject says, this post only contains useful links about this wonderful library:

Home of WTL in Sorceforge
WTL download from Microsoft download center
WTL on CodeProject - If you're an MFC programmer, check the series WTL for MFC programmers.
GameDev.NET - Using the Windows Template Library part 1
GameDev.NET - Using the Windows Template Library part 2
WTL Wiki
Chris Sells's WTL Makes UI Programming a Joy, Part 1: The Basics
Chris Sells's WTL Makes UI Programming a Joy Part 2: The Bells and Whistles
vicsoe.dk WTL samples

I've also attached the Clipcode's WTL developer's guide ebook (the original link seems to be down at the moment)

Finally, don't forget to join the WTL User Group

Posted by cvega with no comments
Filed under: ,

I'm back :)

Hi guys,

I can't believe my eyes that It's already been 2 years since my last post here. Wow, time flies really fast! 
My hands up, I'm not going to make any excuses for my long absence, the important thing is that I found my way back to DevPinoy Cool

Been busy working with different technologies for the past 2 years, also experienced some bad turns in career shifts etch..
I thought it might be a good refresher to write something about what I learned in my blog.., but I’m kind-of thinking what exactly to write.

Any suggestions?

Posted by cvega with 7 comment(s)

Arrows available in Wingdings 3

Let me show you another good use of applying the trick I've posted earlier, when I wrote the "how-to" for making .NET password field to look more like an XP password field – the trick is done by playing with Fonts.

Now, let's play with fonts even more to have our UI some "arrows" displayed on form without the need to use any arrow-image and/or arrow icons. See the screen-shot below for possible use:



The form above has button displaying up and down arrows, and using the same trick, the arrow buttons doesn't used any images. It is setup using the characters small letter H ('h') and small letter I ('i') with it's font set to Wingdings 3.

Here's the steps in making up arrow button:

1. Add a button
2. Set the button's font to Wingdings 3.
3. Set the Text property to small letter H ('h').

And here's the steps in making the down arrow button:

1. Add a button
2. Set the button's font to Wingdings 3.
3. Set the Text property to small letter I ('i').

In case you might need different arrows, other than up and down arrows, or you want different styles of arrows, here's a small list I've come up which are available arrows inside Wingdings 3:

Play around with the font even more, and you'll see that there are more arrows you can choose from.

Have fun coding your UI!

Cheers,

-chris

Posted by cvega with 2 comment(s)
Filed under:

.NET Password field that looks like Windows XP password field

Here's a trick to make your regular .NET TextBox to have a look similar to Windows XP password field, where it displays large black circles instead of asterisks (****) to "mask" the password (see the Password field shown in the screenshot below):



This trick is fairly easy, and it doesn't require you to perform any complicated owner drawings.

Here's how:

1. Add a TextBox to your Form
2. Set the Font of that TextBox to Wingdings (not Webdings)
3. Set the PasswordChar property to small letter L ('l').

And you're all set, quick and easy.

If you want your password field to have customized look and feel other than the one I described, you may want to experiment using different characters other than small letter L, or use Symbols Font, for more symbols.

Happy coding

-chris

Posted by cvega with 1 comment(s)
Filed under:

Clone a class by using MemberwiseClone method

I am currently working on a project that I accepted to "continue" because the original freelance programmer left the project without completing it. The project was started using VB.NET, and as the company requested, I am now converting it to C# before I go ahead to completing it.

While I'm doing the conversion, I've seen many parts in the codes that are in need of attention. One that I spotted quickly is how the project implemented the Clone method for all cloneable classes (making a copy of the instance rather, as opposed to referencing an instance using the equal (=) assignment operator).

Below is a shorter version how the implementation of a Profile class would look like, converted to C#:

public class Profile : ICloneable
{

 private string m_firstname;
 public string FirstName
 {
  get { return m_firstname; }
  set { m_firstname = value; }
 }

 private string m_lastname;
 public string LastName
 {
  get { return m_lastname; }
  set { m_lastname = value; }
 }

 private int m_age;
 public int Age
 {
  get { return m_age; }
  set { m_age = value; }
 }

 object ICloneable.Clone()
 {
  return this.Clone();
 }

 public Profile Clone()
 {
  Profile temp = new Profile();
  temp.FirstName = this.FirstName;
  temp.LastName = this.LastName;
  temp.Age = this.Age;

  return temp;
 }
}


The above class was purposely shortened, but as you may have imagined, the class has more properties than just FirstName, LastName, and Age, hence the more properties the Profile class have, the larger the implementation of the Clone method. Not very manageable.

The simpliest way to shorten the Clone method is to call the object's MemberwiseClone method, which is provided by .NET to make a shallow copy of an object's instance -- rather than one-by-one copying all the properties, as shown above.

Here's how the updated version would look like:

public class Profile : ICloneable
{
 private string m_firstname;
 public string FirstName
 {
  get { return m_firstname; }
  set { m_firstname = value; }
 }

 private string m_lastname;
 public string LastName
 {
  get { return m_lastname; }
  set { m_lastname = value; }
 }

 private int m_age;
 public int Age
 {
  get { return m_age; }
  set { m_age = value; }
 }

 object ICloneable.Clone()
 {
  return this.MemberwiseClone();
 }

 public Profile Clone()
 {
  return (Profile)this.MemberwiseClone();
 }
}

I am aware that MemberwiseClone uses reflection to make a shallow copy, therefore it won't copy publicly exposed variables.

Anyway, this will be another busy month for me -- work, work, work.

Posted by cvega with no comments

xtoi (Hex to Integer) C function

C language has many functions for converting numerical values to and from string. Here are some from the standard C library:

atof   converts a string to a double
atol   converts a string to a long
atoi   converts a string to an integer

Then you can get the reverse by using sprintf function to get the string representation of numerical values using various formating. That's great for ready made stuffs, though the C library is lacking some functions to convert to and from a hexadecimal string function, we can simply write our own. Here's something I wrote to convert hexadecimal string to integer, I called it xtoi to follow the same function naming used by C library:

// Converts a hexadecimal string to integer
int xtoi(const char* xs, unsigned int* result)
{
 size_t szlen = strlen(xs);
 int i, xv, fact;

 if (szlen > 0)
 {
  // Converting more than 32bit hexadecimal value?
  if (szlen>8) return 2; // exit

  // Begin conversion here
  *result = 0;
  fact = 1;

  // Run until no more character to convert
  for(i=szlen-1; i>=0 ;i--)
  {
   if (isxdigit(*(xs+i)))
   {
    if (*(xs+i)>=97)
    {
     xv = ( *(xs+i) - 97) + 10;
    }
    else if ( *(xs+i) >= 65)
    {
     xv = (*(xs+i) - 65) + 10;
    }
    else
    {
     xv = *(xs+i) - 48;
    }
    *result += (xv * fact);
    fact *= 16;
   }
   else
   {
    // Conversion was abnormally terminated
    // by non hexadecimal digit, hence
    // returning only the converted with
    // an error value 4 (illegal hex character)

    return 4;
   }
  }
 }

 // Nothing to convert
 return 1;
}


The function above is a little different, as it return the result back to the parameter, hence you need to provide storage to where to put the result, while capturing what the function may return as the conversion status.

xtoi conversion status:

  0    - Conversion is successful
  1    - String is empty
  2    - String has more than 8 bytes
  4    - Conversion is in process but abnormally terminated by
         illegal hexadecimal character



Sample usage:

  unsigned int result;

  if (xtoi("ABCD", &result) == 0)
  {
     printf("ABCD = %d", result);
  }


Output:

  ABCD = 43981

That's for this time, and next time I will see what I can come up for a function that will convert a 64bit hexadecimal string to its 64bit numerical value.

For now, enjoy and hopefully you may find the function useful.


Edit:
From the comment below the page, you can see the C way of decoding hex from string using sscanf function:

unsigned int hex = 0;
const char* hexstr = "ABCD";

sscanf(hexstr, "%X", &hex);
printf("%s = %d\n", hexstr, hex);

Posted by cvega with 4 comment(s)

HexDump utility (converted to MASM)

For the benefit of assembly language programmers working with file mapping (and also for the purpose of honing my personal skills), I converted my file mapping functions posted previously to assembly language, particularly in MASM.

I also converted (and managed to made few optimizations) the source code of Hex Dump utility to assembly language, this is by the way the example utility program I posted as an example for the file mapping functions.

The difference between what's compiled in C and what's assembled in MASM in term of executable size is quite big, DUMP.EXE in C is around the average of 26KB, while the DUMP.EXE assembled in MASM is just 3KB!

Anyway, most of the discussion regarding the file mapping functions and the HexDump utility has been covered in my previous post - so there's no much point in keeping you with lengthy explanation.

Here's the converted source code in MASM, and enjoy:

; --------------------- filemap.inc ---------------------

ifndef  __FILEMAPPING__
        __FILEMAPPING__ equ 1

; Prototypes
OpenAndMapFile    proto :LPCSTR, :PHANDLE, :PHANDLE, :PHANDLE
CloseAndUnmapFile proto :PHANDLE, :PHANDLE, :PHANDLE

; Maximum length of filename
MAX_FNAME_LEN           equ 256

; Constants
SUCCESS                 equ 0
ERROR_OPENFILE_FAILED   equ 1
ERROR_CREATEMAP_FAILED  equ 2
ERROR_MAPVIEW_FAILED    equ 3

; OpenAndMapFile function settings
fm_desired_access       equ GENERIC_READ
fm_share_mode           equ FILE_SHARE_READ
fm_file_attributes      equ FILE_ATTRIBUTE_NORMAL or \
                            FILE_ATTRIBUTE_ARCHIVE
fm_page_access          equ PAGE_READONLY
fm_map_desired_access   equ FILE_MAP_READ

;
; This function will try to open and memory map a specified file,
; and return all the handles for the opened file, created mapping
; object and the base of the memory mapped file. This function returns
; any of the status defined above for errors or success; Also, this 
; function handles the closing of the handles for any errors that may
; happen during the process of memory mapping of the file.
;

.code

OpenAndMapFile proc lpszFilename:LPCSTR, \
                    _hFile:PHANDLE, \
                    _hFileMap:PHANDLE, \
                    _hFileBase:PHANDLE

 local dwFileSize:DWORD
 
 ; Open the specified file
 invoke CreateFile, \
           lpszFilename, \
           fm_desired_access, \
           fm_share_mode, \
           NULL, \
           OPEN_EXISTING, \
           fm_file_attributes, \
           NULL
 mov    edx, _hFile
 mov    [edx], eax
 
 .if eax != INVALID_HANDLE_VALUE

  ; Create FileMapping object for the file
  push   edx
  invoke GetFileSize, [edx], NULL
  mov    dwFileSize, eax
  pop    edx

  invoke CreateFileMapping, \
              [edx], \
              NULL, \
              fm_page_access, \
              0, \
              dwFileSize, \
              NULL

  mov    edx, _hFileMap
  mov    [edx], eax

  .if eax != INVALID_HANDLE_VALUE
  
   ; Map the file to the process memory
   invoke  MapViewOfFile, \
              [edx], \
              fm_map_desired_access, \
              0, \
              0, \
              0

   mov     edx, _hFileBase
   mov     [edx], eax

   .if eax != INVALID_HANDLE_VALUE
    mov    eax, SUCCESS
    ret
   .else
    mov   
edx, _hFileMap
    invoke CloseHandle, [edx]
    mov    edx, _hFile
    invoke CloseHandle, [edx]
    mov    eax, ERROR_MAPVIEW_FAILED
    ret
   .endif
  .else
   mov    
edx, _hFile
   invoke  CloseHandle, [edx]
   mov     eax, ERROR_CREATEMAP_FAILED
   ret
  .endif
 .endif

 mov    eax, ERROR_OPENFILE_FAILED
 ret
OpenAndMapFile endp

;
; This function will cloase all the handles opened and created by
; OpenAndMapFile function
;

CloseAndUnmapFile proc _hFile:PHANDLE, \
                       _hFileMap:PHANDLE, \
                       _hFileBase:PHANDLE
 mov    edx, _hFileBase
 invoke UnmapViewOfFile, [edx]
 mov    edx, _hFileMap
 invoke CloseHandle, [edx]
 mov    edx, _hFile
 invoke CloseHandle, [edx]
 ret
CloseAndUnmapFile endp
 
endif


; --------------------- dump.asm ---------------------

;
; HexDump utility written by Chris Vega.
;

;
; Copy both dump.asm and filemap.inc to bin directory of your
; MASM32 package, and execute these commands:
;
; ml /c /coff /Cp /nologo /I"..\include" dump.asm
; link /SUBSYSTEM:CONSOLE /OPT:NOREF dump.obj "..\lib\kernel32.lib"
; "..\lib\user32.lib" "..\lib\masm32.lib"
;

.386
.model flat, stdcall

include windows.inc

include kernel32.inc
includelib kernel32.lib

include user32.inc
includelib user32.lib

include masm32.inc
includelib masm32.lib

include filemap.inc

.data
 filename  db MAX_FNAME_LEN dup(0)
 fname_cnt dd 0
 linebytes db 17 dup(0)
 
 ; Strings
 dump000   db "usage: DUMP [filename]", 0ah, 0dh, 0
 dump001   db "DUMP has failed to open the specified file."
           db 0ah, 0dh, 0
 dump0x0   db "%08X: ", 0
 dump0x1   db "%02X ", 0
 dump0x2   db ": ", 0
 dump0x3   db ": %s", 0ah, 0dh, 0
 dump0x4   db ".. ", 0
 
.data?
 result    dd ?
 hFile     dd ?
 hFileMap  dd ?
 hFileBase dd ?
 
 buffer    db 128 dup(?)

.code
start:
 call   ProcessCommandLine
 cmp    fname_cnt, 0
 jnz    @_proceed
 
 ; Print usage
 invoke StdOut, addr dump000
 jz     @_exit
 
 @_proceed:
 
 ; Open and map the specified file
 invoke OpenAndMapFile, addr filename, \
        addr hFile, addr hFileMap, addr hFileBase
 mov    result, eax
 cmp    eax, SUCCESS
 jz     @_00
 
 ; Failed to open the file? Print 'open error' and exit
 invoke StdOut, offset dump001
 ret
 
 @_00:
 
 ; Get the file size and dump the file
 invoke GetFileSize, hFile, NULL
 push   eax
 push   hFileBase
 push   hFileBase
 call   HexDump

 invoke CloseAndUnmapFile, addr hFile, \
        addr hFileMap, addr hFileBase
 
 ; Exit the program
 @_exit:
 invoke ExitProcess, 0

; Procedure to extract the filename from the command line.
; This procedure is done for that purpose only, and not designed
; to be reusable.

ProcessCommandLine proc uses esi edi ecx
 mov    edi, offset filename
 mov    byte ptr [edi], 0
 xor    ecx, ecx
 invoke GetCommandLine
 
 ; Find the pointer to the first argument
 mov    esi, eax
 @_@:
 cmp    byte ptr [esi], 32
 je     @_0
 cmp    byte ptr [esi], 0
 je     @_cx
 inc    esi
 jmp    @_@
 @_0:
 inc    esi
 cmp    byte ptr [esi], 32
 jne    @__
 cmp    byte ptr [esi], 0
 je     @_cx
 jmp    @_0
 @__:
 
 ; Copy the first argument to the filename buffer
 cmp    byte ptr [esi], '"'
 je     @_cq
 
 ; Filename is not quoted
 @_c0:
 lodsb
 cmp    al, 32
 je     @_c2
 cmp    al, 0
 je     @_c2
 inc    ecx
 stosb
 jmp    @_c0
 
 ; Filename is quoted
 @_cq:
 inc    esi
 @_c1:
 cmp    byte ptr [esi], '"'
 je     @_c2
 cmp    byte ptr [esi], 0
 je     @_c2
 lodsb
 inc    ecx
 stosb
 jmp    @_c1
 
 ; Close the string
 @_c2:
 xor    eax, eax
 stosb
 
 ; Return to caller
 mov    fname_cnt, ecx
 @_cx:
 ret
ProcessCommandLine endp

; This is the main reusable hex dump procedure. Just specify the
; Base memory address, the memory address to dump and the
; count of bytes to dump, and everything will be done the the
; procedure, except that it doesn't check for read permission, so
; you have to manually capture that kind of error.

HexDump proc uses ebx edi esi base:DWORD, mem_ptr:DWORD, count:DWORD

 mov    byte ptr [linebytes + 16], 0
 mov    ebx, mem_ptr
 mov    edi, 0
 
 @_loop_ebx_lt_count:
 mov    ecx, mem_ptr
 add    ecx, count
 cmp    ebx, ecx
 jnb    @_exit_hexdump
 push   ebx
 
 cmp    edi, 0
 jnz    @_get_a_byte

 ; Print the address
 mov    eax, ebx
 sub    eax, base
 invoke wsprintf, addr buffer, addr dump0x0, eax
 invoke StdOut, addr buffer
 
 @_get_a_byte:
 ; Get a byte from pointer
 xor    eax, eax
 mov    al, byte ptr [ebx]
 
 ; Save it for later text printing, but remove all
 ; non printable characters by replacing them with
 ; a dot (.) character

 cmp    al, 255
 jz     @_non_printable
 cmp    al, 13
 jbe    @_non_printable
 
 mov    byte ptr [linebytes + edi], al
 jmp    @_print_the_byte
 
 @_non_printable:
 mov    byte ptr [linebytes + edi], '.'
 
 ; Print the byte
 @_print_the_byte:
 invoke wsprintf, addr buffer, addr dump0x1, eax
 invoke StdOut, addr buffer
 inc    edi
 
 ; Print 8th byte separator
 cmp    edi, 8
 jne    @_no_8th_byte_separator
 invoke StdOut, addr dump0x2
 @_no_8th_byte_separator:
 
 ; print end of line
 cmp    edi, 15
 jne    @_not_end_of_line
 invoke wsprintf, addr buffer, addr dump0x3, addr linebytes
 invoke StdOut, addr buffer
 mov    edi, 0
 @_not_end_of_line:
 
 ; This is similar to the entire procedure, except this
 ; part is especially crafted as the last line scenario
 ; where the loop is expected to be terminated after
 ; this last line printing

 cmp    edi, 0
 jbe    @_not_last_line
 mov    ecx, base
 add    ecx, count
 dec    ecx
 cmp    ebx, ecx
 jne    @_not_last_line
 
 ; Is this the last line?
 mov    ebx, edi
 inc    ebx
 @_loop_last_line:
 cmp    ebx, 16
 jnb    @_eloop_last_line
 
 invoke StdOut, addr dump0x4
 cmp    ebx, 8
 jne    @_il_no8th
 invoke StdOut, addr dump0x2
 @_il_no8th:
 
 inc    ebx
 jmp    @_loop_last_line
 @_eloop_last_line:
 
 mov    byte ptr [linebytes + edi], 0
 invoke wsprintf, addr buffer, addr dump0x3, addr linebytes
 invoke StdOut, addr buffer
 
 jmp    @_exit_hexdump
 @_not_last_line:
 
 pop    ebx
 inc    ebx
 jmp    @_loop_ebx_lt_count 
  
 @_exit_hexdump:
 ret
HexDump endp

end start

Posted by cvega with no comments
Filed under:

Visit NETFX3 community sites

If you've read my old post listing the community sites of WinFX, it seems that the sites are already being consolidated to the new official site, and it's called the NETFX3 community site.

You can find it here:
http://wcs.netfx3.com/

Or if you want, you can visit these subsites:

Windows Presentation Foundation: http://wpf.netfx3.com/
Windows Communication Foundation: http://wcf.netfx3.com/
Windows Workflow Foundation: http://wf.netfx3.com/
Windows CardSpace: http://wcs.netfx3.com/


\
-chris

Posted by cvega with no comments

Filemapping and a hex dump utility

Last time, I blogged about "how to reference function parameters to and from a function". This time I would like to demonstrate how to put something of that approach in action. I wrote two functions that will allow you to use file mapping in less C/C++ codes. In order for you to understand how the function uses the parameters as its referenced variables, I suggest read my other post about it.

File mapping functions:
Here are the two functions I created, see below for instructions on using them in your application, and download the demo application dump.exe which is a hex dump utility, attached in this post.

The functions:

HRESULT OpenAndMapFile(
                LPCSTR lpszFilename, 
                PHANDLE _hFile, 
                PHANDLE _hFileMap, 
                PHANDLE _hFileBase)
{
    int dwFileSize;

    // Open the specified file
    if ((*_hFile = CreateFile(
        (char*)lpszFilename, 
        OPEN_EXISTING, 
        FILE_SHARE_READ, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL,
        NULL )) != INVALID_HANDLE_VALUE)
    {
        // Create FileMapping object for the file
        dwFileS