static ::LRESULT CALLBACK WindowProc(::HWND hWnd, ::UINT Msg, ::WPARAM wParam, ::LPARAM lParam)
{
    Application *lpApplication = Application::GetInstance();
    switch (Msg)
    {
    case WM_CREATE:
        {
            Renderer *renderer = new Renderer(hWnd);
            renderer->Initialize();
            lpApplication->SetRenderer(renderer);

            int li32SocketVersion = MAKEWORD(1, 1);
            Networking::Socket::Initialize(li32SocketVersion);
        }
        break;

    case WM_DESTROY:
        {
            Networking::Socket::Release();

            Renderer *lpRenderer = lpApplication->GetRenderer();
            if (lpRenderer != 0)
            {
                lpRenderer->Release();
                delete lpRenderer;
                lpApplication->SetRenderer(0);
            }
        }
        break;

    case WM_CLOSE:
        {
            Renderer *lpRenderer = lpApplication->GetRenderer();
            if (0 != lpRenderer)
            {
                lpRenderer->Exit();
            }

            REPORTERROR("Sending quit message");
            ::PostQuitMessage(0);
        }
        return 0;

    case WM_DROPFILES:
        {
            ::HDROP hDrop = reinterpret_cast< ::HDROP>(wParam);
            ::UINT luFilesDropped = ::DragQueryFile(hDrop, 0xFFFFFFFF, 0, 0);
            REPORTERROR1("There were %d files dropped", luFilesDropped);

            if (1 == luFilesDropped)
            {
                ::UINT luBufferSize = ::DragQueryFile(hDrop, 0, 0, 0);
                luBufferSize += 1;
                char *lpBuffer = new char[luBufferSize];

                ::UINT luResult = ::DragQueryFile(hDrop, 0, lpBuffer, luBufferSize);
                if (0 == luResult)
                {
                    ::DWORD luErrorCode = ::GetLastError();
                    REPORTWIN32ERROR("DragQueryFile failed", luErrorCode);
                }

                struct addrinfo hints;
                ::ZeroMemory(&hints, sizeof(hints));

                hints.ai_family = AF_UNSPEC;
                hints.ai_socktype = SOCK_STREAM;
                hints.ai_protocol = IPPROTO_TCP;

#if 1
                Networking::Socket mySocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

                struct hostent *host = ::gethostbyname("localhost");

                ::SOCKADDR_IN SockAddr;
                SockAddr.sin_port = ::htons(8888);
                SockAddr.sin_family = AF_INET;
                SockAddr.sin_addr.s_addr = *((unsigned long *)host->h_addr);

                bool lbResult = mySocket.Connect(&SockAddr, sizeof(SockAddr));
#else
                // Resolve the server address and port
                struct addrinfo *result;
                int iResult = ::getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
                if ( iResult != 0 )
                {
                    REPORTWIN32MODULEERROR(::GetModuleHandle("WS2_32.dll"), "Failed to getaddrinfo, error %d, '%s'", iResult);
                }

                //::hostent *lpLocalHost = ::gethostbyname("localhost");

                Networking::Socket mySocket(result->ai_family, result->ai_socktype, result->ai_protocol);
                bool lbResult = mySocket.Connect(result->ai_addr, result->ai_addrlen);

                ::freeaddrinfo(result);
#endif

                if (lbResult)
                {
                    lbResult = mySocket.Send(lpBuffer, luBufferSize);
                }
                if (lbResult)
                {
                    TextureHeader textureHeader;
                    int liSize;
                    lbResult = mySocket.Receive(&textureHeader, liSize);
                    if (lbResult)
                    {
                        REPORTERROR3("Texture %dx%d of size %d", textureHeader.mu32Width, textureHeader.mu32Height, textureHeader.mu32TotalTextureDataSize);

                        unsigned char *lpTextureData = new unsigned char[textureHeader.mu32TotalTextureDataSize];
                        lbResult = mySocket.Receive(lpTextureData, liSize);

                        textureHeader.mpData = lpTextureData;

                        Renderer *lpRenderer = lpApplication->GetRenderer();
                        if (0 != lpRenderer)
                        {
                            lpRenderer->UploadTexture(textureHeader);
                        }

                        delete [] lpTextureData;
                    }
                }

                delete [] lpBuffer;
            }
        }
        break;
    }

    return ::DefWindowProc(hWnd, Msg, wParam, lParam);
}