I am using the following code but it always crashes at the end the line "SafeRelease(lpDDSBmp);" right in the last funciton. What's going wrong with it?

PHP Code:
#include <windows.h>
#define INITGUID
#define SafeRelease(X) if (X) {X->Release(); X=NULL;}
#include <ddraw.h>

LPDIRECTDRAW lpDD=NULL;
LPDIRECTDRAWSURFACE lpDDSPrimary=NULL;
LPDIRECTDRAWSURFACE lpDDSBmp=NULL;
LPDIRECTDRAWCLIPPER lpClip=NULL;
//Initialized?
BOOL bInit FALSE;
//Window's handle
HWND hWnd;
//Window's class name
static char szClass[] = "myclass";
//Window's caption
static char szCaption [] = "Directx - Example 1(Image Loading)";

/************************************************
Error Handling
************************************************/
//Holds the main return value from any Directx function class
HRESULT retval;
//Variable that holds the error message
const char *Err_Str NULL;

//Variables to hold descriptions of different errors
const char Err_Reg_Class[] = "Error Registering Window Class";
const 
char Err_Create_Win[] = "Error Creating WIndow";
const 
char Err_DirectDrawCreate[] = "DirectDrawCreate FAILED";
const 
char Err_Query[] = "Query Interface FAILED";
const 
char Err_Coop[] = "SetCooperativeLevel FALIED";
const 
char Err_CreateSurf[] = "CreateSurface FALIED";
const 
char Err_Clip[] = "CreateClip FALIED";
const 
char Err_LoadBMP[] = "Error Loading Image";
/*************************************************/


void CleanUp();
void DrawImage();
LPDIRECTDRAWSURFACE surface_bitmap(LPCSTR filename);
BOOL Init(HINSTANCE hInstanceint nShowCmd);

LRESULT CALLBACK WndProc(HWND hWndUINT MsgWPARAM wParamLPARAM lParam)
{
    
        
//To get window's HDC
PAINTSTRUCT ps;

    switch(
Msg)
    {
    case 
WM_PAINT:
        
BeginPaint(hWnd,&ps);
        
DrawImage();
        
EndPaint(hWnd,&ps);
        break;
    case 
WM_DESTROY:
        
CleanUp();
        
PostQuitMessage(0);
        break;
    default:
        return 
DefWindowProc(hWnd,Msg,wParam,lParam);
    }
    return 
0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
    
MSG msg;
    
    if (!
Init(hInstancenShowCmd))
    {
        
CleanUp();
        return 
0;
    }

    while(
GetMessage(&msg,NULL,NULL,NULL))
    {
        
TranslateMessage(&msg);
        
DispatchMessage(&msg);
    }

    return 
msg.wParam;
}

BOOL Init(HINSTANCE hInstanceint nShowCmd)
{
//Holds description for the primary surface
DDSURFACEDESC ddsdP;
//Declare a type of WNDCLASS to fill in the class parameters
WNDCLASS wc;
wc.cbClsExtra 0
wc.cbWndExtra 0;
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hCursor LoadCursor(NULLIDC_ARROW);
wc.hIcon LoadIcon(NULL,IDI_APPLICATION);
wc.hInstance hInstance;
wc.lpfnWndProc WndProc;
wc.lpszClassName szClass;
wc.lpszMenuName NULL;
wc.style CS_HREDRAW CS_VREDRAW;

//Exit if can't register the class
if(!RegisterClass(&wc))
{
    
Err_Str Err_Reg_Class;
    return 
0;
}

int ScreenWidth GetSystemMetrics(SM_CXSCREEN);
int ScreenHeight GetSystemMetrics(SM_CYSCREEN);

hWnd CreateWindow(szClass,
                    
szCaption,
                    
WS_POPUP WS_VISIBLE,
                    
0,
                    
0,
                    
ScreenWidth,
                    
ScreenHeight,
                    
NULL,
                    
NULL,
                    
hInstance,
                    
NULL);

if (
hWnd NULL)
{
    
Err_Str Err_Create_Win;
    return 
0;
}

ShowWindow(hWnd,nShowCmd);
UpdateWindow(hWnd);
//Create a main DirectDraw object
retval DirectDrawCreate(NULL,&lpDD,NULL);

if (
retval != DD_OK)
{
    
Err_Str Err_DirectDrawCreate;
    return 
0;
}

//Set the cooperative level of our DirectDraw object
retval lpDD->SetCooperativeLevel(hWndDDSCL_NORMAL);

if (
retval != DD_OK)
{
    
Err_Str Err_Coop;
    return 
0;
}

//Create the clipper
retval lpDD->CreateClipper(NULL, &lpClip,NULL);

if (
retval != DD_OK)
{
    
Err_Str Err_Clip;
    return 
0;
}

//set the window handle for the clipper
lpClip->SetHWnd(NULL,hWnd);

//Create a primary Surface

//Reset all the member values to 0
ZeroMemory(&ddsdPsizeof(ddsdP));
ddsdP.dwSize sizeof(DDSURFACEDESC);
ddsdP.dwFlags DDSD_CAPS//all the properties to be changed
ddsdP.ddsCaps.dwCaps DDSCAPS_PRIMARYSURFACE//tells that it's a primary surface

//Create the actual surface
retval lpDD->CreateSurface(&ddsdP, &lpDDSPrimary,NULL);
if (
retval != DD_OK)
{
    
Err_Str Err_CreateSurf;
    return 
0;
}

//Set the clipper for the primary surface
lpDDSPrimary->SetClipper(lpClip);

//everything is initialized successfully
bInit TRUE;

//Load the bitmap into our bitmap surface
lpDDSBmp surface_bitmap("back.bmp");

//Copy the bitmap into our primary surface
DrawImage();

return 
TRUE;
}


LPDIRECTDRAWSURFACE surface_bitmap(LPCTSTR filename)
{
    
HDC hdc//holds hdc of the surface we'll create
    
HDC memhdc//temporary hdc in the memory
    
HRESULT retval//holds any error
    
HBITMAP bit//the image loaded from the file
    
BITMAP bitmap//holds properties of the image
    
LPDIRECTDRAWSURFACE surf//holds the surface
    
DDSURFACEDESC ddsd//holds the properties of the surface

    //load the image into "bit"
    
bit = (HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE LR_LOADFROMFILE);
    
    
//Return NULL if couldn't load
    
if (!bit)
    {
        
Err_Str Err_LoadBMP;
        return 
NULL;
    }

    
//Get the properties of the bitmap into "bitmap"
    
GetObject(bit,sizeof(BITMAP), &bitmap);

    
//Get the width of the bitmap
    
int Surface_Width bitmap.bmWidth;
    
//Get the height of the bitmap
    
int Surface_Height bitmap.bmHeight;

//Reset all the member values to 0
    
ZeroMemory(&ddsdsizeof(ddsd));
    
ddsd.dwSize sizeof(DDSURFACEDESC);
ddsd.dwFlags DDSD_HEIGHT DDSD_WIDTH DDSD_CAPS//all the properties to be changed
ddsd.dwHeight Surface_Height;  //height of the surface
ddsd.dwWidth Surface_Width//width of the surface
ddsd.ddsCaps.dwCaps DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY;

retval lpDD->CreateSurface(&ddsd,&surf,NULL);

//if error creating the surface
if (retval != DD_OK)
{
    
//Delete the bitmap and return failure to the caller
    
DeleteObject(bit);
return 
NULL;
}
else
{
//get the HDC of the surface
surf->GetDC(&hdc);
//Create a memory HDC
memhdc CreateCompatibleDC(hdc);
//Copy the bitmap into the memory HDC
SelectObject(memhdc,bit);
//Bitblt the bitmap from the memory on the surface
BitBlt(hdc,0,0,Surface_Width,Surface_Height,memhdc,0,0,SRCCOPY);

//Release the surface HDC
surf->ReleaseDC(hdc);
//Free up the memory DC
DeleteDC(memhdc);
//Delete the bitmap
DeleteObject(bit);

//return our surface
return surf;
}
}

void DrawImage()
{
    
//if the bitmap wasn't loaded or the window wasn't initialized
    
if (!lpDDSBmp || !bInit)
    {
        
//cancel
        
return;
    }
    
//bitblt the secondary surface onto the primary surface
    
lpDDSPrimary->Blt(NULL,lpDDSBmp,NULL,DDBLT_WAIT,NULL);
}
void CleanUp()
{
    
//Release the interfaces (all Directx objects) 
SafeRelease(lpDD);
SafeRelease(lpDDSPrimary);
SafeRelease(lpDDSBmp);
SafeRelease(lpClip);

    if (
Err_Str)
    {
        
MessageBox(NULL,Err_Str,"Error"MB_OK);
    }