Sunday, February 28, 2010

History, Saved

For far too long I’ve worked on personal projects without using any source control management tools.  As George Santayana said, “Those who cannot remember the past are condemned to repeat it,” or in my case rewrite it as I can’t find some code I’ve written before.  I know that’s not a good practice so I have fixed it.

This morning I setup IIS and Mercurial on my local server.  While there are still a few kinks to work out with the setup, such as Chrome and IE warnings about self signed certificates, I’m able to push, pull and clone repositories.  For now I’m just hosting these on my local network.  I do plan on releasing some of my projects with an open source license but I’ll post those on bitbucket.org.  Long gone are the days when I spend time trying to host public facing websites from my network.

Next I’m going to create a symbol server.  I’ve found them to be invaluable when debugging crash reports.  As I’ve mentioned before.

Thursday, January 14, 2010

It Runs! It Crashes! It's Fixed!


To the left is a screen shot of the Sudoku application that is developed in the book Hello, Android.  You can click on the screen shot to see more that I captured.  Unlike other screen shots I've posted before these are from my T-Mobile myTouch and not the Android emulator.  Aren't they pretty?

At the end of chapter 4 I should have had a playable sudoku game.  What I had was a "nifty" error screen as my app crashed.  It turns out that I missed a few characters when typing in the long string that defines the starting position for a game.  It was an easy mistake and should have been easy to find.  I guess my inexperience using Eclipse slowed down finding the problem as I wasn't able to walk the stack backward from the crash to find the bug.  On the whole though getting the Android SDK and development environment setup and running was straightforward.

While I've made a few minor changes, such as the app name, I have followed along with the book.  Though I have a list of things I want to implement for my own version.  Some of them are, in no particular order:
  • Enter puzzles to be solved.
  • Load and save puzzles to local database.
  • Protect the original numbers from modification.
  • Highlight the original numbers when drawing the game board.
  • Allow the user to change colors and fonts used to display the game.
  • Check the board and alert the user when they've solved the game.
That will all have to wait until I finish the book though.  Some of these features might be covered in later chapters.

Tuesday, January 12, 2010

New Year, New Direction

It's been a while since I've updated this blog. Priorities at work changed and I haven't been focused on crash dump analysis. Also I spread myself a bit thin with all my activities and hobbies. Work and life has slowed down so now I have some time to dedicate to my coding activities. So here we go again...

I have a shiny new T-Mobile myTouch. So I'm going to spend some time learning how to write apps for the Android platform. To start I'm working through Hello, Android by Ed Burnette. Expect some updates about my progress soon.

Friday, July 31, 2009

DllRegisterServer w/o regsvr32

I have a need to register some COM DLLs from a C# program. Every example I found on the web used regsvr32 to perform the registration. This didn't make much sense to me as all regsvr32 does is call DllRegisterServer() exported in the DLL. So I worked out how to do the same from C# using P/Inovke and System.Runtime.InteropServices.

And here it is for you to use. This is a small sample but it compiles and registers the DLLs that are listed on the command line. Be sure to compile with the /unsafe switch. Also, I have more error checking and reporting in my application which I removed from this sample. Enjoy!

   1:  using System;
   2:  using System.Runtime.InteropServices;
   3:   
   4:  public class RegisterDll
   5:  {
   6:      unsafe internal delegate UInt32 DllRegisterServer();
   7:      
   8:      public static void Main(string[] args)
   9:      {
  10:          foreach (string file in args)
  11:          {
  12:              Console.WriteLine("Registering {0}", file);
  13:              RegisterCOMDll(file);
  14:          }
  15:   
  16:          Console.WriteLine("Done!");
  17:      }
  18:   
  19:      private static void RegisterCOMDll(string file)
  20:      {
  21:          IntPtr library = LoadLibraryEx(file, IntPtr.Zero, 0);
  22:          if (library == IntPtr.Zero)
  23:          {
  24:              string msg = "Unable to load '" + file + "' error is " + Marshal.GetLastWin32Error().ToString();
  25:              throw new ApplicationException(msg);
  26:          }
  27:   
  28:          IntPtr proc = GetProcAddress(library, "DllRegisterServer");
  29:          if (proc == IntPtr.Zero)
  30:          {
  31:              int err = Marshal.GetLastWin32Error();
  32:              string msg = "Unable to load 'DllRegisterServer' from '" + file + "' error is " + err.ToString();
  33:              throw new ApplicationException(msg);
  34:          }
  35:   
  36:          DllRegisterServer drs = (DllRegisterServer)Marshal.GetDelegateForFunctionPointer(proc, typeof(DllRegisterServer));
  37:          UInt32 result = drs();
  38:          if (result != 0)
  39:          {
  40:              string msg = "Error " + result.ToString() + " returned from DllRegisterServer in " + file;
  41:              throw new ApplicationException(msg);
  42:          }
  43:   
  44:          FreeLibrary(library);
  45:      }
  46:   
  47:      [Flags]
  48:      public enum LoadLibraryFlags : uint
  49:      {
  50:          DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
  51:          LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
  52:          LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
  53:          LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008,
  54:      }
  55:   
  56:      [DllImport("kernel32.dll", EntryPoint = "FreeLibrary", SetLastError = true)]
  57:      public static extern bool FreeLibrary(IntPtr hModule);
  58:   
  59:      [DllImport("kernel32.dll", EntryPoint = "LoadLibraryExW", CharSet = CharSet.Unicode, SetLastError = true)]
  60:      public static extern IntPtr LoadLibraryEx(
  61:          [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
  62:          IntPtr hFile,
  63:          [MarshalAs(UnmanagedType.U4)] LoadLibraryFlags dwFlags);
  64:   
  65:      [DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "GetProcAddress", ExactSpelling = true, SetLastError = true)]
  66:      public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
  67:  }

Thursday, March 26, 2009

KioskCrash: It goes *BOOM*!

Today I'm going to cover what happens when the KioskCrash application crashes. We'll cover what information the operating system provides to help diagnose the crash and what we can use to help diagnose the crash before we add any debugging support to our application. So without further ado...

When KioskCrash crashes Windows XP will display a window similar to this. There really isn't much information here, just a button to automatically send an error report to Microsoft and another button to skip sending the report. If you click the "Send Error Report" button the operating system will bundle up a bit of information about the crash and send it off to Microsoft for diagnosis. This window also includes a link to see what data the error report contains.

This is an example of what you would see with if you clicked the link to see what data is contained in the error report. The first section is the only interesting thing displayed in this window. It contains the application name & version, the module name & version and the location where the crash occurred in our image. This is why you should always add a version information resource in executables you create. Since KioskCrash is a simple application I only filled in basic information. In a large application this information would be invaluable for locating the crash. The location of the crash, called "Offset" in this window, can be used to get an idea where to find the problem in your code. I will go into more detail about how to do that in a later post. (Probably the next one.) The only other interesting thing displayed in this window is a link at the bottom to see more technical information about the error report.

Now we get to the details of the exception. The important things to note in this window is the type of exception (0xC0000005 Access Violation) and the address of the exception (0x401016). Using the image base address we can calculate that the offending instruction was located at offset 0x1016 in our module. This is about all the information we can extract from the error report windows that are displayed by the operating system.

To recap the information we've been able to determine from the Windows XP error report is that version 1.0.0.1 of the KioskCrash application crashed because of an access violation at offset 0x1016. This doesn't help us much because we don't have a way to match the source code to offset 0x1016. If we had a "map" file we might be able to determine which function caused the crash. With the symbols for this version of KioskCrash we could determine which function and perhaps even which line in that function crashed.

Next time I'll cover map files, how to create them as part of the build and how to use them with this information to locate the source of a crash. Until then...

Monday, February 9, 2009

Testing Google Code Prettyfier

I'm testing using Google's code syntax highlighter. So here's a simple C++ function to see the results.

int fact(int n)
{
    // quickly return the simple terminal case
    if (n <= 1)
        return 1.0;

    return n * fact(n - 1);
}

Microsoft Visual C++ 2008 Redistributable

The KioskCrash executable in my last post was created using Microsoft Visual C++ 2008. I forgot to include links to the redistributable which needs to be installed on systems without VC++ 2008.

Sorry about that folks.