In this post we will see how to play with the new dll; as support, I would like to add a new tutorial:
http://www.woodmann.net/fravia/kayaker_RegmonPlus.htm
Read it, it's full of interesting informations ;-)
Now that we know almost everything about the program, we have to show these damned bombs. I will try to explain you how to show them when the mouse pass over a cell; the bombs will remain showed until the end of the game.
We need to show the bombs when the mouse passes over a cell (that hide a bomb) so, we need to find where the program checks for WM_MOUSEMOVE message. Now, if you read the previous messages, you should not have problems to find the location; as you can see this type of message is not so useful for the original program, it makes a simple jump to the end of the routine. 
When we will patch the program in memory we will need to change this jump into a jump to our code. 
Which are the runtime modifications to apply at the program?
- a new compare instruction for the new itemmenu (remember the old message...)
- the jumps to the new code (one for the item menu and one for the wm_mousemove)
- the code necessary in order to call the dll functions
I will only speak about the last modification, the other two are very easy; if you have problem do not hesitate to ask.
How to call a dll? Practically you have to call 3 simple functions: LoadLibrary, GetProcAddress and FreeLibrary.
LoadLibrary: it's the first function to use and it maps the dll module into the address space of the calling process.
HINSTANCE LoadLibrary(
    LPCTSTR lpLibFileName   // address of the string that names the executable module 
   );
The function returns a handle that can be used in GetProcAddress to get the address of a dll function.
GetProcAddress: returns the address of the exported dll function.
FARPROC GetProcAddress(
    HMODULE hModule,	// handle to DLL module (the value returned by LoadLibrary)
    LPCSTR lpProcName 	// address of the string that names the function
   );
FreeLibrary: unmaps the dll module fro the address space of the calling process
BOOL FreeLibrary(
    HMODULE hLibModule 	// handle to DLL module (the value returned by LoadLibrary) 
   );
This is the code I used to call the dll and it's the code you have to inject into a cave of the original program:
Code:
010049A2:   ; Initial address
specialMode BYTE 1h dup(0) ; specialMode=08h if specialMode is enable
                           ; otherwise specialMode=00h
dllName db "zaiWinmine.dll",0 ; The name of the new DLL
; The name of the 2 exported functions:
changeItemStatus db "changeItemStatus",0 ; Changes the status of the itemmenu     
revealCell db "revealCell", 0 ; Reveal a bomb under a cell
; From 'specialMode' item clicked (10018C4)
 push 10019ADh     ; Address from where to return to
 pushad
 push offset changeItemStatus   ; Used by GetProcAddress     
 jmp @go
; From WM_MOUSEMOVE event (1001b50)
 push 1001DD5h                ; Address from where to return to
 .IF [specialMode] == 00h   ; Is the special mode enable?
  pop eax                     ; specialMode is disable, no need to show the bomb
  jmp eax
 .ENDIF
 pushad
 push offset revealCell        ; Used by GetProcAddress
 jmp @go
@go:
 push offset dllName   ; The name of the dll
 call LoadLibrary
 mov esi, eax
 push eax                 ; Handle to dll module
 call GetProcAddress
 call eax    ; call the exported function
 push esi   ; Handle to dll module
 call FreeLibrary
 popad
 pop eax
 jmp eax      ; Jump back to the original code
I think there is nothing to add. 
Now we can write the other function of the dll, the one I called revealCell. What this function is supposed to do? Remembering that the function will be called on every single movement of the mouse (and let's suppose specialMode is enable), we have this scheme:
1. Is the pointer inside the grid?
No: quit from the function
Yes: jump to 2
2. Is the cell hiding a bomb?
No: quit from the function
Yes: reveal the bomb
The point number 1 is necessary because the bombs can not be outside the grid while the point number 2 is the final check.
The first cell (upper left corner) starts from coordinates 0x0C,0x37 and each cell is 0x10,0x10. Now that we know this information, we are able to implement the point number 1: a simple 'if' based on the coordinates of the point where the mouse has been pressed. How did you know the x and the y coordinates where the mouse has been pressed? WM_MOUSEMOVE will tell you; infact:
WM_MOUSEMOVE  
   fwKeys = wParam;        // key flags 
   xPos = LOWORD(lParam);  // horizontal position of cursor 
   yPos = HIWORD(lParam);  // vertical position of cursor
Here is all that you need :-D
Point number 2: first of all, we have to check whether a cell hides a bomb; this is not a problem because we know where the program stores the grid in memory and, we will easily perform this check but... how can I reveal a bomb under a cell? The answer is inside Graphics Device Interface (GDI) library; in this specific case we will use GDI to display a bitmap. My new version of the game displays the image that has the bomb on the red background (open the program with a resource editor, you will find the image I am talking about under "Bitmap-410-1033"

. You can display the image you prefer taken from the proggie or created by you. To display this image I use these functions: GetDC, BitBlt, ReleaseDC.
GetDC: retrieves a handle of a display Device Context (DC) for the client area of the specified window.
HDC GetDC(
    HWND hWnd 	// handle of window  
   );
This is the first function we have to call and it takes a single parameter. How do we know the handle of the window? Simple, these 3 functions are used by MineSweeper and so, the best way to understand how to use them is to bpx them and to look how they are used. This time, put a bpx on GetDC and run again the program. Ollydbg will surely break and the only thing you have to do is to take note of the address that contains the handle...
BitBlt: it clips an image from a source DC to a destination DC.
BOOL BitBlt(
    HDC hdcDest,// handle to destination DC, the GetDC returned address 
    int nXDest,	// x-coordinate of destination rectangle's upper-left corner
    int nYDest,	// y-coordinate of destination rectangle's upper-left corner
    int nWidth,	// width of destination rectangle 
    int nHeight,// height of destination rectangle 
    HDC hdcSrc,	// handle to source device context 
    int nXSrc,	// x-coordinate of source rectangle's upper-left corner  
    int nYSrc,	// y-coordinate of source rectangle's upper-left corner
    DWORD dwRop // raster operation code 
   );
As before, the best way for to understand how to use the function is to bpx it on Ollydbg. If you want to display another image you have to change the 6° parameter: hdcSrc.
ReleaseDC: the ReleaseDC function releases a device context
int ReleaseDC(
    HWND hWnd,	// handle of window 
    HDC hDC 	// handle of device context  
   );
Ok, it's time to past the source of the revealCell procedure (add it to the code I gave you before):
Code:
.data 
oldRow	db	"01004998"
oldColumn	db	"0100499C"
; Display the image under a cell
revealCell proc
   pushad
   ; Is the mouse pointer inside the grid ?
   .IF word ptr [ebp+14h] < 0Ch || word ptr [ebp+16h] < 37h
      jmp @exitRevealCell
   .endif
	
   xor eax, eax
   mov ax, word ptr [ebp+14h]   ; The x-coord of the mouse
   sub eax, 0Ch	
   shr eax, 4
   add eax, 1   ; The number of the column -inside the grid-  where the mouse is pressed
   xor ebx, ebx
   mov bx, word ptr [ebp+16h]	; The y-coord of the mouse
   sub ebx, 37h
   shr ebx, 4
   add ebx, 1   ; The number of the row where the mouse is pressed
   mov edi, 1004998h
   .IF ax == word ptr [edi] && bx == word ptr [edi+4]	
      ; It's in the same cell than before, no need to display the same image again
      jmp @exitRevealCell   
   .ENDIF
   mov ecx, ebx
   mov edx, ecx
   shl edx, 5
   mov ebx, 1005700h
   add ebx, eax
   add ebx,edx
   ; Reveal the cell if and only if there is an hidden bomb
   .IF byte ptr [ebx]  == 8Fh
      mov edi, 1004998h
      mov dword ptr [edi], eax	; Save the column
      mov dword ptr [edi+4], ecx	; Save the row
      push eax
      push ecx
      mov esi, 10052A8h   ; Pointer to handle of window
      push [esi]   ; Handle of window
      call GetDC
      mov esi, eax
      pop ecx
      pop eax
      shl ecx, 4
      add ecx, 27h
      shl eax, 4
      sub eax, 4
      mov ebx, 1005AE0h
      push 0CC0020h   ; SRCCOPY flag
      push 0
      push 0
      push [ebx+48] ; Source DC, the image to display
      push 10h        ; Height of the rectangle
      push 10h        ; Width of the rectangle
      push ecx        ; y coord
      push eax        ; x coord
      push esi         ; Handle to destination DC
      call BitBlt
      mov ebx, 10052A8h
      push esi               ; Handle of DC
      push dword ptr [ebx]   ; Handle of window
      call ReleaseDC
   .ELSE
      mov dword ptr [edi], 0
      mov dword ptr [edi+4], 0
   .ENDIF	
	 
   @exitRevealCell:
   popad
ret
revealCell endp
I think that's all...
Ciao,
ZaiRoN