   DDraw DDERR_INVALIDPARAMS errors
  Hi,I have been programming a 2D tower defence game using directdraw and c++. I have ran into a few issues that i am unable to solve.I want to be able to rotate surfaces. I have found some source code which manually records the source surface's pixels and then pastes them onto the destination surface at the desired rotation. To do this I need to lock the source and destination surfaces and acquire the DDSURFACEDESC2.lpSurface.When ever i try to lock the surface and obtain the DDSURFACEDESC2 I recieve a DDERR_INVALIDPARAMS error.below is the effected function (untested due to the error)typedef union{struct{BYTE b;BYTE g;BYTE r;} rgb;struct{BYTE r;BYTE g;BYTE b;} bgr;} TRIPLE, *LPTRIPLE;void dx::rotateandrender(int index, int rotation, vector2D screenpos){DDSURFACEDESC2 ddsdOriginal;DDSURFACEDESC2 ddsdDestination;double dblRMax, lWidth, lHeight, sngA;int lngXO, lngYO, iXDest, iYDest, iX, iY;DWORD dwColor, dwRed, dwGreen, dwBlue;LPTRIPLE pTriple;double SinA, CosA;sngA = rotation * (PI / 180);SinA = sin(sngA);CosA = cos(sngA);memset( &ddsdOriginal, 0, sizeof(ddsdOriginal) );HRESULT hr = surfaces[index].surface->Lock(NULL, &ddsdOriginal, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);lWidth = ddsdOriginal.dwWidth;lHeight = ddsdOriginal.dwHeight;dblRMax = sqrt((lWidth*lWidth) + (lHeight*lHeight));lpDDSBack->GetSurfaceDesc(&ddsdDestination);lpDDSBack->Lock(NULL, &ddsdDestination, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);screenpos.x += (lWidth / 2);screenpos.y += (lHeight / 2);for(iX = -dblRMax; iX <= dblRMax; iX++){for(iY = -dblRMax; iY <= dblRMax; iY++){lngXO = lWidth / 2 - (iX * CosA + iY * SinA);lngYO = lHeight / 2 - (iX * SinA - iY * CosA);if(lngXO >= 0){if(lngYO >= 0){if(lngXO < lWidth){if(lngYO < lHeight){pTriple = (LPTRIPLE)ddsdOriginal.lpSurface + ((ddsdOriginal.lPitch / 3) * lngYO) + lngXO;dwRed = (DWORD)pTriple->rgb.r;dwGreen = (DWORD)pTriple->rgb.g;dwBlue = (DWORD)pTriple->rgb.b;dwColor = (dwRed << 16) | (dwGreen << 8) | (dwBlue);DWORD lpscreen = (DWORD)ddsdOriginal.lpSurface + ((ddsdOriginal.lPitch / 3) * (iYDest + iY)) + (iXDest + iX);lpscreen = dwColor;}}}}}}surfaces[index].surface->Unlock(NULL);lpDDSBack->Unlock(NULL);}Below is the header file of the effected class#ifndef DX_H#define DX_H// include the basic windows header files and the Direct3D header file#include <ddraw.h>#include "variables.h"#include "windows.h"#include <iostream>#include <math.h>#define PI 3.141592//make life easier on the fingers#define DX dx::Instance()struct _surfaces{LPDIRECTDRAWSURFACE7 surface;int sizex, sizey;};class dx{private://constructor is privatedx();//copy ctor and assignment should be privatedx(const dx &);dx& operator=(const dx &);int SCREEN_WIDTH;int SCREEN_HEIGHT;bool FULLSCREEN;HWND hwnd;_surfaces * surfaces;// Bitmap surfacesLPDIRECTDRAW7 lpDD;// DirectDraw object defined in DDRAW.HLPDIRECTDRAWSURFACE7 lpDDSPrimary;// DirectDraw primary surfaceLPDIRECTDRAWSURFACE7 lpDDSBack;// DirectDraw back surfaceDDCOLORKEY ddck;// Color keyHFONT font;// default fontvector2D gridorigin;vector2D cellsize;vector2D gridsize;int end;public:~dx();static dx* Instance();//initbool DirectDrawInit(HWND hwnd, int screenw, int screenh, bool fullscreen);bool DirectDrawInitFullscreen(HWND hwnd, int screenw, int screenh);bool DirectDrawInitWindowed(HWND hwnd, int screenw, int screenh);void cleanup(void);//rendervoid renderback(int index);void rendergrid(int index, int gridx, int gridy);void renderpos(int index, int posx, int posy, int destwidth = -1, int destheight = -1);void rendercenterpos(int index, int posx, int posy, int destwidth = -1, int destheight = -1);void rotateandrender(int index, int rotation, vector2D screenpos);void rendertext(int x, int y, int width, int height, LPCTSTR textbuffer2, int R = 0, int G = 0, int B = 0);void drawcircle(vector2D gridpos, int radius);void drawline(vector2D gridstart, vector2D gridend);//flipvoid flipscreen( void );//propetiesvoid setmapdetails(vector2D gridorigin1, vector2D cellsize1, vector2D gridsize1);int retwidth()const{return SCREEN_WIDTH;}int retheight()const{return SCREEN_HEIGHT;}HWND rethwnd()const{return hwnd;}//load bitmapsbool preparebitmapstorage(int size);bool loadbitmap(int index, LPCSTR bitmap);bool loadbackgroundbitmap(int index, LPCWSTR bitmap, vector2D gridorigin, vector2D cellsize, vector2D gridsize);_surfaces DDLoadBitmap(IDirectDraw7 *pdd, LPCSTR szBitmap);HRESULT DDCopyBitmap(IDirectDrawSurface7 *pdds, HBITMAP hbm, int dx, int dy);IDirectDrawSurface7 * CreateOffScreenSurface(IDirectDraw7 *pdd, int dx, int dy);//retrieve dataint getgridsizex(int mapID);int getgridsizey(int mapID);HWND gethwnd(){return hwnd;}vector2D getcellsize(){return cellsize;}vector2D screentogrid(vector2D screenpos);vector2D gridtoscreen(vector2D gridpos);vector2D centergridtoscreen(vector2D gridpos);vector2D screentonearestgrid(vector2D screenpos);};#endifand this is all the functions of the class#include "DX.h"dx* dx::Instance(){  static dx instance;  return &instance;}dx::dx(){for(int ct = 0; ct < end; ct++){surfaces[ct].surface = NULL;}ddck.dwColorSpaceLowValue = RGB(255,255,255);ddck.dwColorSpaceHighValue = RGB(255,255,255);font = CreateFont(46, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,  OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_ROMAN, L"Times New Roman");}dx::~dx(){}/* * Function to initialize DirectDraw * Demonstrates: *   1) Creating the Direct Draw Object *   2) Setting the Cooperative level *   3) Setting the Display mode * */bool dx::DirectDrawInit(HWND hwnd, int screenw, int screenh, bool fullscreen){dx::FULLSCREEN = fullscreen;dx::hwnd = hwnd;SCREEN_WIDTH = screenw;SCREEN_HEIGHT = screenh;bool ret;if(fullscreen){ret = DirectDrawInitFullscreen(hwnd, screenw, screenh);}else{ret =  DirectDrawInitWindowed(hwnd, screenw, screenh);}if(ret == true){lpDDSBack->SetColorKey(DDCKEY_COLORSPACE|DDCKEY_SRCBLT,&ddck); lpDDSPrimary->SetColorKey(DDCKEY_COLORSPACE|DDCKEY_SRCBLT,&ddck); }return ret;}bool dx::DirectDrawInitFullscreen(HWND hwnd, int screenw, int screenh){    HRESULT ddrval;   /*    * Create the main DirectDraw object.    *    * This function takes care of initializing COM and Constructing    * the DirectDraw object.    */    ddrval = DirectDrawCreateEx( NULL, (LPVOID*)&lpDD, IID_IDirectDraw7, NULL );    if( ddrval != DD_OK )    {   return(false);    }   /*    * The cooperative level determines how much control we have over the    * screen. This must at least be either DDSCL_EXCLUSIVE or DDSCL_NORMAL    *    * DDSCL_EXCLUSIVE allows us to change video modes, and requires    * the DDSCL_FULLSCREEN flag, which will cause the window to take over    * the fullscreen. This is the preferred DirectDraw mode because it allows    * us to have control of the whole screen without regard for GDI.    *    * DDSCL_NORMAL is used to allow the DirectDraw app to run windowed.    */    ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);    if( ddrval != DD_OK )    {   lpDD->Release();   return(false);    }   /*    * Set the video mode to 640x480x8    * This is allowed because we have set exclusive mode above    */    ddrval = lpDD->SetDisplayMode( screenw, screenh, 32, 0, 0);    if( ddrval != DD_OK )    {   lpDD->Release();   return(false);    }    //Create Surface    DDSURFACEDESC2 ddsd;    DDSCAPS2 ddscaps;    // Create the primary surface with 1 back buffer    memset( &ddsd, 0, sizeof(ddsd) );    ddsd.dwSize = sizeof( ddsd );    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;    ddsd.dwBackBufferCount = 1;    ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );    if( ddrval != DD_OK )    {   lpDD->Release();   return false;    }    // Get the pointer to the back buffer    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;    ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);    if( ddrval != DD_OK )    {   lpDDSPrimary->Release();   lpDD->Release();   return false;    }    return true;}// function to initialize DirectDraw in windowed modebool dx::DirectDrawInitWindowed(HWND hwnd, int screenw, int screenh){    DDSURFACEDESC2 ddsd;    DDSCAPS ddscaps;    HRESULT ddrval;LPDIRECTDRAWCLIPPER lpClipper;   /*    * create the main DirectDraw object    */    ddrval = DirectDrawCreateEx( NULL, (LPVOID*)&lpDD, IID_IDirectDraw7, NULL );    if( ddrval != DD_OK )    {   return(false);    }    // using DDSCL_NORMAL means we will coexist with GDI    ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );    if( ddrval != DD_OK )    {   lpDD->Release();   return(false);    }    memset( &ddsd, 0, sizeof(ddsd) );    ddsd.dwSize = sizeof( ddsd );    ddsd.dwFlags = DDSD_CAPS;    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;    // The primary surface is not a page flipping surface this time    ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );    if( ddrval != DD_OK )    {   lpDD->Release();if(ddrval == DDERR_INCOMPATIBLEPRIMARY){int test = 0;}if(ddrval == DDERR_INVALIDPARAMS){int test = 0;}   return(false);    }    // Create a clipper to ensure that our drawing stays inside our window    ddrval = lpDD->CreateClipper( 0, &lpClipper, NULL );    if( ddrval != DD_OK )    {   lpDDSPrimary->Release();   lpDD->Release();   return(false);    }    // setting it to our hwnd gives the clipper the coordinates from our window    ddrval = lpClipper->SetHWnd( 0, hwnd );    if( ddrval != DD_OK )    {   lpClipper-> Release();   lpDDSPrimary->Release();   lpDD->Release();   return(false);    }    // attach the clipper to the primary surface    ddrval = lpDDSPrimary->SetClipper( lpClipper );    if( ddrval != DD_OK )    {   lpClipper-> Release();   lpDDSPrimary->Release();   lpDD->Release();   return(false);    }    memset( &ddsd, 0, sizeof(ddsd) );    ddsd.dwSize = sizeof( ddsd );    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;ddsd.dwWidth = SCREEN_WIDTH;    ddsd.dwHeight = SCREEN_HEIGHT;    // create the backbuffer separately    ddrval = lpDD->CreateSurface( &ddsd, &lpDDSBack, NULL );    if( ddrval != DD_OK )    {   lpClipper-> Release();   lpDDSPrimary->Release();   lpDD->Release();   return(false);    }    return(true);}bool dx::preparebitmapstorage(int size){//create enough storage for all bitmapsend = size;surfaces = new _surfaces [end];return true;}//load bitmap for a specific object type (ID)bool dx::loadbitmap(int index, LPCSTR bitmap){surfaces[index] = DDLoadBitmap(lpDD, bitmap);surfaces[index].surface->SetColorKey(DDCKEY_COLORSPACE|DDCKEY_SRCBLT,&ddck); return true;}/* * Function to create an offscreen surface and load a bitmap from * disk into it. The szBitmap field is the filename of the Bitmap. */_surfaces dx::DDLoadBitmap(IDirectDraw7 *pdd, LPCSTR szBitmap){    HBITMAP hbm;    BITMAP bm;    _surfaces bmpsurface;    // LoadImage has some added functionality in Windows 95 that allows    // you to load a bitmap from a file on disk.hbm = (HBITMAP)LoadImageA(NULL, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);    if (hbm == NULL)std::cout << "Error 002 - Bitmap " << szBitmap << " could not be loaded!";    GetObject(hbm, sizeof(bm), &bm); // get size of bitmap   /*    * create a DirectDrawSurface for this bitmap    * source to function CreateOffScreenSurface() follows immediately    */bmpsurface.sizex = bm.bmWidth;bmpsurface.sizey = bm.bmHeight;    bmpsurface.surface = CreateOffScreenSurface(pdd, bm.bmWidth, bm.bmHeight);    if (bmpsurface.surface) {   DDCopyBitmap(bmpsurface.surface, hbm, bm.bmWidth, bm.bmHeight);    }    DeleteObject(hbm);    return bmpsurface;}/* * Creates a DirectDraw Surface of a specified size * This surface will be in video memory if enough is * available, otherwise it will be created in system memory */IDirectDrawSurface7 * dx::CreateOffScreenSurface(LPDIRECTDRAW7 pdd, int dx, int dy){    DDSURFACEDESC2 ddsd;    LPDIRECTDRAWSURFACE7 pdds;    //    // create a DirectDrawSurface for this bitmap    //    ZeroMemory(&ddsd, sizeof(ddsd));    ddsd.dwSize = sizeof(ddsd);    ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;    ddsd.dwWidth = dx;    ddsd.dwHeight = dy;    if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)    {   return NULL;    } else {   return pdds;    }}/* * This function copies a previously loaded bitmap into a DirectDraw surface. * Notice that we can obtain a GDI style device context for a * DirectDraw surface, with which to BitBlt the bitmap into the * surface. */HRESULT dx::DDCopyBitmap(IDirectDrawSurface7 *pdds, HBITMAP hbm, int dx, int dy){    HDC hdcImage;    HDC hdc;    HRESULT hr;    HBITMAP hbmOld;    //    // select bitmap into a memoryDC so we can use it.    //    hdcImage = CreateCompatibleDC(NULL);    hbmOld = (HBITMAP)SelectObject(hdcImage, hbm);    if ((hr = pdds->GetDC(&hdc)) == DD_OK)    {   BitBlt(hdc, 0, 0, dx, dy, hdcImage, 0, 0, SRCCOPY);   pdds->ReleaseDC(hdc);    }    SelectObject(hdcImage, hbmOld);    DeleteDC(hdcImage);    return hr;}// This function should be called repeatedly during the idle time of your// PeekMessage()loop.void dx::flipscreen( void ){    HRESULT ddrval;    RECT rcRectSrc;    RECT rcRectDest;    POINT p;    // if we're windowed do the blit, else just Flip    if (!FULLSCREEN)    {   // first we need to figure out where on the primary surface our window lives   p.x = 0; p.y = 0;   ClientToScreen(hwnd, &p);   GetClientRect(hwnd, &rcRectDest);   OffsetRect(&rcRectDest, p.x, p.y);   SetRect(&rcRectSrc, 0, 0, 640, 480);   ddrval = lpDDSPrimary->Blt( &rcRectDest, lpDDSBack, &rcRectSrc, DDBLT_WAIT, NULL);    } else {   ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT);    }}/* * Call Release on all objects we created to clean up */void dx::cleanup( void ){    if( lpDD != NULL )    {for(int ct = 0; ct < end; ct++){ if( surfaces[ct].surface != NULL ){surfaces[ct].surface->Release();surfaces[ct].surface = NULL;}}   if( lpDDSPrimary != NULL )   {  lpDDSPrimary->Release();  lpDDSPrimary = NULL;   }    }    lpDD->Release();    lpDD = NULL;}typedef union{struct{BYTE b;BYTE g;BYTE r;} rgb;struct{BYTE r;BYTE g;BYTE b;} bgr;} TRIPLE, *LPTRIPLE;void dx::rotateandrender(int index, int rotation, vector2D screenpos){DDSURFACEDESC2 ddsdOriginal;DDSURFACEDESC2 ddsdDestination;double dblRMax, lWidth, lHeight, sngA;int lngXO, lngYO, iXDest, iYDest, iX, iY;DWORD dwColor, dwRed, dwGreen, dwBlue;LPTRIPLE pTriple;double SinA, CosA;sngA = rotation * (PI / 180);SinA = sin(sngA);CosA = cos(sngA);memset( &ddsdOriginal, 0, sizeof(ddsdOriginal) );HRESULT hr = surfaces[index].surface->Lock(NULL, &ddsdOriginal, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);lWidth = ddsdOriginal.dwWidth;lHeight = ddsdOriginal.dwHeight;dblRMax = sqrt((lWidth*lWidth) + (lHeight*lHeight));lpDDSBack->GetSurfaceDesc(&ddsdDestination);lpDDSBack->Lock(NULL, &ddsdDestination, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);screenpos.x += (lWidth / 2);screenpos.y += (lHeight / 2);for(iX = -dblRMax; iX <= dblRMax; iX++){for(iY = -dblRMax; iY <= dblRMax; iY++){lngXO = lWidth / 2 - (iX * CosA + iY * SinA);lngYO = lHeight / 2 - (iX * SinA - iY * CosA);if(lngXO >= 0){if(lngYO >= 0){if(lngXO < lWidth){if(lngYO < lHeight){pTriple = (LPTRIPLE)ddsdOriginal.lpSurface + ((ddsdOriginal.lPitch / 3) * lngYO) + lngXO;dwRed = (DWORD)pTriple->rgb.r;dwGreen = (DWORD)pTriple->rgb.g;dwBlue = (DWORD)pTriple->rgb.b;dwColor = (dwRed << 16) | (dwGreen << 8) | (dwBlue);DWORD lpscreen = (DWORD)ddsdOriginal.lpSurface + ((ddsdOriginal.lPitch / 3) * (iYDest + iY)) + (iXDest + iX);lpscreen = dwColor;}}}}}}surfaces[index].surface->Unlock(NULL);lpDDSBack->Unlock(NULL);}I also have a problem when initialising direct draw in full screen mode. The program crashes when trying to call createsurface from the CreateOffScreenSurface function. The error says I have an access violation. Any help would be greatDan   