示例#1
0
文件: win32_init.c 项目: hanxi/glfw
int _glfwPlatformInit(void)
{
    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                          &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                          SPIF_SENDCHANGE);

    if (!loadLibraries())
        return GLFW_FALSE;

    createKeyTables();
    _glfwUpdateKeyNamesWin32();

    if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
        SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
    else if (IsWindows8Point1OrGreater())
        SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
    else if (IsWindowsVistaOrGreater())
        SetProcessDPIAware();

    if (!_glfwRegisterWindowClassWin32())
        return GLFW_FALSE;

    if (!createHelperWindow())
        return GLFW_FALSE;

    _glfwInitTimerWin32();
    _glfwInitJoysticksWin32();

    _glfwPollMonitorsWin32();
    return GLFW_TRUE;
}
示例#2
0
int _glfwPlatformInit(void)
{
    if (!_glfwInitThreadLocalStorageWin32())
        return GLFW_FALSE;

    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                          &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                          SPIF_SENDCHANGE);

    if (!loadLibraries())
        return GLFW_FALSE;

    createKeyTables();

    if (_glfw_SetProcessDpiAwareness)
        _glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
    else if (_glfw_SetProcessDPIAware)
        _glfw_SetProcessDPIAware();

    if (!_glfwRegisterWindowClassWin32())
        return GLFW_FALSE;

    _glfw.win32.helperWindowHandle = createHelperWindow();
    if (!_glfw.win32.helperWindowHandle)
        return GLFW_FALSE;

    _glfwInitTimerWin32();
    _glfwInitJoysticksWin32();

    return GLFW_TRUE;
}
示例#3
0
文件: win32_init.c 项目: Draghi/glfw
void _glfwPlatformTerminate(void)
{
    if (_glfw.win32.deviceNotificationHandle)
        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);

    if (_glfw.win32.helperWindowHandle)
        DestroyWindow(_glfw.win32.helperWindowHandle);

    _glfwUnregisterWindowClassWin32();

    // Restore previous foreground lock timeout system setting
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
                          SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);
    free(_glfw.win32.rawInput);

    _glfwTerminateWGL();
    _glfwTerminateEGL();

    _glfwTerminateJoysticksWin32();

    freeLibraries();
}
示例#4
0
int _glfwPlatformInit(void)
{
    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                         &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                         SPIF_SENDCHANGE);

    if (!initLibraries())
        return GL_FALSE;

#ifdef __BORLANDC__
    // With the Borland C++ compiler, we want to disable FPU exceptions
    // (this is recommended for OpenGL applications under Windows)
    _control87(MCW_EM, MCW_EM);
#endif

    _glfw.win32.instance = GetModuleHandle(NULL);

    // Save the original gamma ramp
    _glfw.originalRampSize = 256;
    _glfwPlatformGetGammaRamp(&_glfw.originalRamp);
    _glfw.currentRamp = _glfw.originalRamp;

    if (!_glfwInitOpenGL())
        return GL_FALSE;

    _glfwInitTimer();

    _glfwInitJoysticks();

    return GL_TRUE;
}
示例#5
0
int _glfwPlatformInit(void)
{
    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                          &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                          SPIF_SENDCHANGE);

    if (!initLibraries())
        return GL_FALSE;

    createKeyTables();

    if (_glfw_SetProcessDPIAware)
        _glfw_SetProcessDPIAware();

    if (!_glfwRegisterWindowClass())
        return GL_FALSE;

    if (!_glfwInitContextAPI())
        return GL_FALSE;

    _glfwInitTimer();
    _glfwInitJoysticks();

    return GL_TRUE;
}
示例#6
0
int _glfwPlatformInit(void)
{
    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                         &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                         SPIF_SENDCHANGE);

    if (!initLibraries())
        return GL_FALSE;

    if (_glfw_SetProcessDPIAware)
        _glfw_SetProcessDPIAware();

#ifdef __BORLANDC__
    // With the Borland C++ compiler, we want to disable FPU exceptions
    // (this is recommended for OpenGL applications under Windows)
    _control87(MCW_EM, MCW_EM);
#endif

    if (!_glfwInitContextAPI())
        return GL_FALSE;

    _glfwInitTimer();
    _glfwInitJoysticks();

    return GL_TRUE;
}
示例#7
0
void _glfwPlatformTerminate(void)
{
    _glfwUnregisterWindowClassWin32();

    // Restore previous foreground lock timeout system setting
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
                          SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);

#if defined(_GLFW_WGL)
    _glfwTerminateWGL();
#elif defined(_GLFW_EGL)
    _glfwTerminateEGL();
#endif

    _glfwTerminateJoysticksWin32();
    _glfwTerminateThreadLocalStorageWin32();

    if (_glfw.win32.helperWindow)
        DestroyWindow(_glfw.win32.helperWindow);

    freeLibraries();
}
示例#8
0
文件: util.c 项目: kcrazy/winekit
VOID
SplOutSem(
   VOID
    )
{
    if ( pjlMonSection.OwningThread == (HANDLE) UIntToPtr(GetCurrentThreadId()) ) {
        DBG_MSG(DBG_ERROR, ("Pjlmon: Inside spooler semaphore !!\n"));
    }
}
示例#9
0
文件: util.c 项目: Realhram/wdk81
VOID
LcmSplOutSem(
   VOID
)
{

    if (LcmSpoolerSection.OwningThread == (HANDLE) UIntToPtr(GetCurrentThreadId())) {
    }
}
示例#10
0
文件: thread.c 项目: Dimillian/wine
/***********************************************************************
 *           terminate_thread
 */
void terminate_thread( int status )
{
    pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status );

    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
    pthread_exit( UIntToPtr(status) );
}
示例#11
0
文件: thread.c 项目: vindo-app/wine
/***********************************************************************
 *           exit_thread
 */
void exit_thread( int status )
{
    static void *prev_teb;
    shmlocal_t *shmlocal;
    sigset_t sigset;
    TEB *teb;

    if (status)  /* send the exit code to the server (0 is already the default) */
    {
        SERVER_START_REQ( terminate_thread )
        {
            req->handle    = wine_server_obj_handle( GetCurrentThread() );
            req->exit_code = status;
            wine_server_call( req );
        }
        SERVER_END_REQ;
    }

    if (interlocked_xchg_add( &nb_threads, 0 ) <= 1)
    {
        LdrShutdownProcess();
        exit( status );
    }

    LdrShutdownThread();
    RtlFreeThreadActivationContextStack();

    shmlocal = interlocked_xchg_ptr( &NtCurrentTeb()->Reserved5[2], NULL );
    if (shmlocal) NtUnmapViewOfSection( NtCurrentProcess(), shmlocal );

    pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );

    if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
    {
        struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;

        if (thread_data->pthread_id)
        {
            pthread_join( thread_data->pthread_id, NULL );
            signal_free_thread( teb );
        }
    }

    sigemptyset( &sigset );
    sigaddset( &sigset, SIGQUIT );
    pthread_sigmask( SIG_BLOCK, &sigset, NULL );
    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status );

    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
    pthread_exit( UIntToPtr(status) );
}
示例#12
0
HWND MakeWindow (LPCTSTR pszClass, LPCTSTR pszTitle, DWORD dwStyle, RECT *prSource, 
                 HWND hParent, UINT idc, DWORD dwStyleEx = 0)
{
   RECT rr = { 0, 0, 16, 16 };
   if (prSource)
      rr = *prSource;
   HWND hWnd = CreateWindowEx (dwStyleEx, pszClass, pszTitle, dwStyle, 
                               rr.left, rr.top, rr.right - rr.left, rr.bottom - rr.top, 
                               hParent, (HMENU)UIntToPtr(idc), GetModuleHandle(0), 0);
   if (IsWindow (hWnd))
      SendMessage (hWnd, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 1);
   return hWnd;
}
示例#13
0
/***********************************************************************
 *           exit_thread
 */
void exit_thread( int status )
{
    static void *prev_teb;
    TEB *teb;

    if (status)  /* send the exit code to the server (0 is already the default) */
    {
        SERVER_START_REQ( terminate_thread )
        {
            req->handle    = wine_server_obj_handle( GetCurrentThread() );
            req->exit_code = status;
            wine_server_call( req );
        }
        SERVER_END_REQ;
    }

    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1)
    {
        LdrShutdownProcess();
#ifdef CONFIG_UNIFIED_KERNEL
        server_kill_thread( status );
#endif
        exit( status );
    }

    LdrShutdownThread();

    pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );

    if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
    {
        struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;

        if (thread_data->pthread_id)
        {
            pthread_join( thread_data->pthread_id, NULL );
            signal_free_thread( teb );
        }
    }

    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
#ifdef CONFIG_UNIFIED_KERNEL
    server_kill_thread( status );
#endif
    pthread_exit( UIntToPtr(status) );
}
示例#14
0
void _glfwPlatformTerminate(void)
{
    _glfwUnregisterWindowClass();

    // Restore previous foreground lock timeout system setting
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
                          SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);

    _glfwTerminateJoysticks();
    _glfwTerminateContextAPI();
    terminateLibraries();
}
示例#15
0
文件: thread.c 项目: evelikov/wine
/***********************************************************************
 *           exit_thread
 */
void exit_thread( int status )
{
    static void *prev_teb;
    TEB *teb;

    if (status)  /* send the exit code to the server (0 is already the default) */
    {
        SERVER_START_REQ( terminate_thread )
        {
            req->handle    = wine_server_obj_handle( GetCurrentThread() );
            req->exit_code = status;
            wine_server_call( req );
        }
        SERVER_END_REQ;
    }

    if (interlocked_xchg_add( &nb_threads, -1 ) <= 1)
    {
        LdrShutdownProcess();
        exit( status );
    }

    LdrShutdownThread();
    RtlAcquirePebLock();
    RemoveEntryList( &NtCurrentTeb()->TlsLinks );
    RtlReleasePebLock();
    RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots );
    RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );

    pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );

    if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
    {
        struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;

        if (thread_data->pthread_id)
        {
            pthread_join( thread_data->pthread_id, NULL );
            signal_free_thread( teb );
        }
    }

    close( ntdll_get_thread_data()->wait_fd[0] );
    close( ntdll_get_thread_data()->wait_fd[1] );
    close( ntdll_get_thread_data()->reply_fd );
    close( ntdll_get_thread_data()->request_fd );
    pthread_exit( UIntToPtr(status) );
}
示例#16
0
void _glfwPlatformTerminate(void)
{
    if (_glfw.win32.classAtom)
    {
        UnregisterClass(_GLFW_WNDCLASSNAME, GetModuleHandle(NULL));
        _glfw.win32.classAtom = 0;
    }

    // Restore previous foreground lock timeout system setting
    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                         UIntToPtr(_glfw.win32.foregroundLockTimeout),
                         SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);

    _glfwTerminateJoysticks();
    _glfwTerminateContextAPI();
    terminateLibraries();
}
示例#17
0
void _glfwPlatformTerminate(void)
{
    // Restore the original gamma ramp
    if (_glfw.rampChanged)
        _glfwPlatformSetGammaRamp(&_glfw.originalRamp);

    if (_glfw.win32.classAtom)
    {
        UnregisterClass(_GLFW_WNDCLASSNAME, _glfw.win32.instance);
        _glfw.win32.classAtom = 0;
    }

    _glfwTerminateOpenGL();

    _glfwTerminateJoysticks();

    freeLibraries();

    // Restore previous FOREGROUNDLOCKTIMEOUT system setting
    SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                         UIntToPtr(_glfw.win32.foregroundLockTimeout),
                         SPIF_SENDCHANGE);
}
示例#18
0
文件: signal.c 项目: Lance0312/tcsh
unsigned int alarm(unsigned int seconds) {

	unsigned int temp;
	static unsigned int prev_val=0;
	HANDLE ht;
	DWORD tid;
	SECURITY_ATTRIBUTES secd;

	secd.nLength=sizeof(secd);
	secd.lpSecurityDescriptor=NULL;
	secd.bInheritHandle=TRUE;


	if (!__halarm) {
		__halarm=CreateEvent(&secd,FALSE,FALSE,NULL);
	}
	if(__alarm_set )
		SetEvent(__halarm);

	if (!seconds){
		__alarm_set=0;
		return 0;
	}
	__alarm_set = 1;

	ht = CreateThread(NULL,gdwStackSize,
				(LPTHREAD_START_ROUTINE)alarm_callback, 
				(void*)UIntToPtr(seconds),
				0,&tid);
	if (ht)
		CloseHandle(ht);
	
	temp = prev_val;
	prev_val = seconds*1000;

	return temp;
}
示例#19
0
LRESULT
CALLBACK 
MainWndProc
(
    HWND      hWnd,
    UINT      Msg,
    WPARAM    wParam,
    LPARAM    lParam
)
/*++

Routine Description:

    This is the main window procedure to the testing program


Arguments:

    See SDK


Return Value:

    See SDK

--*/
{
    DWORD   Result;
    LONG    Ret;

    switch (Msg)
    {
    case WM_INITMENUPOPUP:

        if (!HIWORD(lParam))
        {
            CheckMenuItem( (HMENU)UIntToPtr((UINT)wParam),
                           IDM_PERMISSION,
                           MF_BYCOMMAND | ((UpdatePermission) ? MF_CHECKED : MF_UNCHECKED)
                         );

            CheckMenuItem( (HMENU)UIntToPtr((UINT)wParam),
                           IDM_USESTDABOUT,
                           MF_BYCOMMAND | ((UseStdAbout) ? MF_CHECKED : MF_UNCHECKED)
                         );
        }
        break;

    case WM_COMMAND:

        switch (wParam)
        {
        case IDM_USESTDABOUT:

            UseStdAbout = !UseStdAbout;
            break;

        case IDM_PERMISSION:

            UpdatePermission = !UpdatePermission;
            break;

        case IDM_DOCPROP:
        case IDM_TVTEST:
        case IDM_DOCPROP_TVTEST:

            Ret = CommonPropertySheetUI( hWnd,
                                         (PFNPROPSHEETUI)CPSUIFunc,
                                         (LPARAM)LOWORD(wParam),
                                         &Result
                                       );

            CPSUIDBG( DBG_WINMAINPROC,
                      ("CommonPropertySheetUI()=%ld, Result=%ld", Ret, Result)
                    );

            break;

        default:

            break;
        }
        break;

    case WM_DESTROY:

        PostQuitMessage(0);
        break;

    default:

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

    return 0L;
}
示例#20
0
文件: pensetup.c 项目: kcrazy/winekit
UINT
CreatePenSetupOI(
    PPRINTERINFO    pPI,
    POPTITEM        pOptItem,
    POIDATA         pOIData
    )

/*++

Routine Description:




Arguments:




Return Value:




Author:

    06-Nov-1995 Mon 16:23:36 created  


Revision History:


--*/

{
    PPENDATA    pPenData;
    POPTITEM    pOI;
    POPTITEM    pOIPen;
    POPTTYPE    pOTPen;
    EXTRAINFO   EI;
    UINT        i;
    UINT        j;
    UINT        MaxPens;
    UINT        cPenClr;
    WCHAR       Buf[128];
    DWORD       dwchSize;
    HRESULT     hr;

    MaxPens  = (UINT)pPI->pPlotGPC->MaxPens;
    cPenClr  = PC_IDX_TOTAL;

    if (!pOptItem) {

        return(((MaxPens + 1) * PRK_MAX_PENDATA_SET) + 1);
    }

    EI.Size  = (UINT)((LoadString(hPlotUIModule,
                                  IDS_PEN_NUM,
                                  Buf,
                                  (sizeof(Buf) / sizeof(WCHAR)) - 1)
                       + 5) * sizeof(WCHAR));
    dwchSize = EI.Size;
    pPenData = PI_PPENDATA(pPI);
    pOTPen   = NULL;
    pOIPen   = NULL;
    pOI      = pOptItem;

    //
    // First: Create PenSetup: HEADER
    //

    if (CreateOPTTYPE(pPI, pOI, pOIData, 0, NULL)) {

        pOI++;
    }

    //
    // Now Create Each pen set
    //

    for (i = (UINT)IDS_PENSET_FIRST; i <= (UINT)IDS_PENSET_LAST; i++) {

        if (CreateOPTTYPE(pPI, pOI, &OIPenSet, 0, NULL)) {

            pOI->pName     = (LPTSTR)UIntToPtr(i);
            pOI->Flags    |= OPTIF_EXT_IS_EXTPUSH;
            pOI->pExtPush  = &PenSetExtPush;
        }

        pOI++;

        for (j = 1; j <= MaxPens; j++, pOI++, pPenData++) {

            if (CreateOPTTYPE(pPI, pOI, &OIPenNum, cPenClr, &EI)) {

                if (pOTPen) {

                    pOI->pOptType = pOTPen;

                } else {

                    pOTPen  = pOI->pOptType;
                    cPenClr = 0;
                }

                if (pOIPen) {

                    pOI->pName = pOIPen->pName;
                    pOIPen++;

                } else {

                    pOI->pName = (LPTSTR)EI.pData;
                    hr = StringCchPrintfW(pOI->pName, dwchSize, L"%ws%u", Buf, j);
                    if ( FAILED(hr) )
                    {
                        PLOTASSERT(0,
                                   "Couldn't format string into pName",
                                   SUCCEEDED(hr), 0);

                    }
                }
            }

            pOI->Sel = pPenData->ColorIdx;
        }

        if (!pOIPen) {

            EI.Size = 0;
            pOIPen  = pOI;
        }

        pOIPen -= MaxPens;
    }

    return (UINT)(pOI - pOptItem);
}
示例#21
0
VOID
FASTCALL
ObpFreeObject (
    IN PVOID Object
    )

/*++

Routine Description:

    This routine undoes ObpAllocateObject.  It returns the object back to free pool.

Arguments:

    Object - Supplies a pointer to the body of the object being freed.

Return Value:

    None.

--*/

{
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    POBJECT_HEADER_QUOTA_INFO QuotaInfo;
    POBJECT_HEADER_HANDLE_INFO HandleInfo;
    POBJECT_HEADER_NAME_INFO NameInfo;
    POBJECT_HEADER_CREATOR_INFO CreatorInfo;
    PVOID FreeBuffer;
    ULONG NonPagedPoolCharge;
    ULONG PagedPoolCharge;

    PAGED_CODE();

    //
    //  Get the address of the object header.
    //

    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    ObjectType = ObjectHeader->Type;

    //
    //  Now from the header determine the start of the allocation.  We need
    //  to backup based on what precedes the header.  The order is very
    //  important and must be the inverse of that used by ObpAllocateObject
    //

    FreeBuffer = ObjectHeader;

    CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );

    if (CreatorInfo != NULL) {

        FreeBuffer = CreatorInfo;
    }

    NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );

    if (NameInfo != NULL) {

        FreeBuffer = NameInfo;
    }

    HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader );

    if (HandleInfo != NULL) {

        FreeBuffer = HandleInfo;
    }

    QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader );

    if (QuotaInfo != NULL) {

        FreeBuffer = QuotaInfo;
    }

#if DBG

    //
    //  On a checked build echo out frees
    //

    if (ObpShowAllocAndFree) {

        DbgPrint( "OB: Free  %lx (%lx) - Type: %wZ\n", ObjectHeader, ObjectHeader, &ObjectType->Name );
    }
#endif

    //
    //  Decrement the number of objects of this type
    //

    InterlockedDecrement((PLONG)&ObjectType->TotalNumberOfObjects);

    //
    //  Check where we were in the object initialization phase.  This
    //  flag really only tests if we have charged quota for this object.
    //  This is because the object create info and the quota block charged
    //  are unioned together.
    //

    if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {

        if (ObjectHeader->ObjectCreateInfo != NULL) {

            ObpFreeObjectCreateInformation( ObjectHeader->ObjectCreateInfo );

            ObjectHeader->ObjectCreateInfo = NULL;
        }

    } else {

        if (ObjectHeader->QuotaBlockCharged != NULL) {

            if (QuotaInfo != NULL) {

                PagedPoolCharge = QuotaInfo->PagedPoolCharge +
                                  QuotaInfo->SecurityDescriptorCharge;

                NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;

            } else {

                PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;

                if (ObjectHeader->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA ) {

                    PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA;
                }

                NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
            }

            PsReturnSharedPoolQuota( ObjectHeader->QuotaBlockCharged,
                                     PagedPoolCharge,
                                     NonPagedPoolCharge );

            ObjectHeader->QuotaBlockCharged = NULL;
        }
    }

    if ((HandleInfo != NULL) &&
        ((ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) == 0)) {

        //
        //  If a handle database has been allocated, then free the memory.
        //

        ExFreePool( HandleInfo->HandleCountDataBase );

        HandleInfo->HandleCountDataBase = NULL;
    }

    //
    //  If a name string buffer has been allocated, then free the memory.
    //

    if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) {

        ExFreePool( NameInfo->Name.Buffer );

        NameInfo->Name.Buffer = NULL;
    }

    PERFINFO_REMOVE_OBJECT_FROM_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectHeader);

    //
    //  Trash type field so we don't get far if we attempt to
    //  use a stale object pointer to this object.
    //
    //  Win64 Note: trash it by zero-extended it. 
    //                sign-extension will create a valid kernel address.


    ObjectHeader->Type = UIntToPtr(0xBAD0B0B0); 
    ExFreePoolWithTag( FreeBuffer,
                       (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |
                            PROTECTED_POOL );

    return;
}
示例#22
0
文件: injdll32.c 项目: adoxa/errout
void InjectDLL32( LPPROCESS_INFORMATION ppi )
{
  CONTEXT context;
  DWORD   ep;
  DWORD   len;
  LPVOID  mem;
  DWORD   mem32;
  DWORD   pr;
  BYTE	  code[CODE32SIZE+GLOBAL32SIZE+TSIZE(MAX_PATH)];
  union
  {
    PBYTE  pB;
    PWORD  pW;
    PDWORD pL;
  } ip;
#ifdef _WIN64
  BOOL entry = FALSE;
#endif

#ifdef IMPORT_WOW64
  if (Wow64GetThreadContext == 0)
  {
    #define GETPROC( proc ) proc = (T##proc)GetProcAddress( hKernel, #proc )
    HMODULE hKernel = GetModuleHandle( L"kernel32.dll" );
    GETPROC( Wow64GetThreadContext );
    GETPROC( Wow64SetThreadContext );
    // Assume if one is defined, so is the other.
    if (Wow64GetThreadContext == 0)
      return;
  }
#endif

  len = TSIZE(lstrlen( hDllName ) + 1);
  if (len > TSIZE(MAX_PATH))
    return;

  CopyMemory( code + CODE32SIZE + GLOBAL32SIZE, hDllName, len );
  len += CODE32SIZE + GLOBAL32SIZE;

  context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
  GetThreadContext( ppi->hThread, &context );
  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
			PAGE_READWRITE );
  mem32 = (DWORD)(DWORD_PTR)mem;

  ip.pB = code;

  ep = context.Eip;
  if (LLW32 == 0)
  {
#ifndef _WIN64
    LLW32 = (DWORD)GetProcAddress( GetModuleHandle( L"kernel32.dll" ),
						     "LoadLibraryW" );
#else
    struct unicode_string
    {
      USHORT Length;
      USHORT MaximumLength;
      DWORD  Buffer;
    };
    struct ldr_module		// incomplete definition
    {
      DWORD next, prev;
      DWORD baseAddress;
      DWORD entryPoint;
      DWORD sizeOfImage;
      struct unicode_string fullDllName;
      struct unicode_string baseDllName;
    } ldr;
    WCHAR basename[MAX_PATH];

    if (!get_LLW32())
      return;
    // Determine the base address of the 32-bit kernel32.dll.
    // Use the PEB to walk the loaded modules.
    // When a process is created suspended, EAX has the entry point and EBX
    // points to the PEB.
    if (!ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),
			    ip.pL, 4, NULL ))
    {
      return;
    }
    // In case we're a bit slow (which seems to be unlikely), set up an
    // infinite loop as the entry point.
    WriteProcessMemory( ppi->hProcess, mem, "\xEB\xFE", 2, NULL );
    FlushInstructionCache( ppi->hProcess, mem, 2 );
    ep = context.Eax;
    context.Eax = mem32;
    SetThreadContext( ppi->hThread, &context );
    VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );
    // Now resume the thread, as the PEB hasn't even been created yet.
    ResumeThread( ppi->hThread );
    while (*ip.pL == 0)
    {
      Sleep( 0 );
      ReadProcessMemory( ppi->hProcess, UIntToPtr( context.Ebx + 0x0C ),
			 ip.pL, 4, NULL );
    }
    // Read PEB_LDR_DATA.InInitializationOrderModuleList.Flink.
    ReadProcessMemory( ppi->hProcess, UIntToPtr( *ip.pL + 0x1c ),
		       &ip.pL[1], 4, NULL );
    // Sometimes we're so quick ntdll.dll is the only one present, so keep
    // looping until kernel32.dll shows up.
    for (;;)
    {
      ldr.next = ip.pL[1];
      do
      {
	ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.next ),
			   &ldr, sizeof(ldr), NULL );
	ReadProcessMemory( ppi->hProcess, UIntToPtr( ldr.baseDllName.Buffer ),
			   basename, ldr.baseDllName.MaximumLength, NULL );
	if (_wcsicmp( basename, L"kernel32.dll" ) == 0)
	{
	  LLW32 += ldr.baseAddress;
	  goto gotit;
	}
      } while (ldr.next != *ip.pL + 0x1c);
    }
  gotit:
    SuspendThread( ppi->hThread );
    VirtualProtectEx( ppi->hProcess, mem, len, pr, &pr );
    entry = TRUE;
#endif
  }

  *ip.pB++ = 0x68;			// push  ep
  *ip.pL++ = ep;
  *ip.pB++ = 0x9c;			// pushf
  *ip.pB++ = 0x60;			// pusha
  *ip.pB++ = 0x68;			// push  L"path\to\errout32.dll"
  *ip.pL++ = mem32 + CODE32SIZE + GLOBAL32SIZE;
  *ip.pB++ = 0xe8;			// call  LoadLibraryW
  *ip.pL++ = LLW32 - (mem32 + (DWORD)(ip.pB+4 - code));
  *ip.pB++ = 0x61;			// popa
  *ip.pB++ = 0x9d;			// popf
  *ip.pB++ = 0xc3;			// ret

  // Should probably now use shared memory rather than a shared section.
  *ip.pL++ = PtrToUint( global.hStdOut );
  *ip.pL++ = PtrToUint( global.hStdCon );
  *ip.pL++ = PtrToUint( global.hFilOut );
  *ip.pL++ = PtrToUint( global.hFilErr );
  *ip.pL++ = PtrToUint( global.hFilCon );
  *ip.pW++ = global.console;
  *ip.pW++ = global.errcol;

  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
  FlushInstructionCache( ppi->hProcess, mem, len );
  VirtualProtectEx( ppi->hProcess, mem, len, PAGE_EXECUTE, &pr );
#ifdef _WIN64
  if (entry)
    return;
#endif
  context.Eip = mem32;
  SetThreadContext( ppi->hThread, &context );
}
示例#23
0
BOOLEAN
SpRemoveLogicalUnit(
    IN PDEVICE_OBJECT LogicalUnit,
    IN UCHAR RemoveType
    )

{
    PLOGICAL_UNIT_EXTENSION logicalUnitExtension = LogicalUnit->DeviceExtension;
    PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
    PADAPTER_EXTENSION adapterExtension = logicalUnitExtension->AdapterExtension;

    ULONG isRemoved;
    ULONG oldDebugLevel;

    PAGED_CODE();

    if(commonExtension->IsRemoved != REMOVE_COMPLETE) {

        if(RemoveType == IRP_MN_REMOVE_DEVICE) {

            SpWaitForRemoveLock(LogicalUnit, UIntToPtr( 0xabcdabcd) );

            //
            // If the device was claimed we should release it now.
            //

            if(logicalUnitExtension->IsClaimed) {
                logicalUnitExtension->IsClaimed = FALSE;
                logicalUnitExtension->IsLegacyClaim = FALSE;
            }

        }

        DebugPrint((1, "SpRemoveLogicalUnit - %sremoving device %#p\n",
                    (RemoveType == IRP_MN_SURPRISE_REMOVAL) ? "surprise " : "",
                    LogicalUnit));

        //
        // If the lun isn't marked as missing yet or is marked as missing but 
        // PNP hasn't been informed yet then we cannot delete it.  Set it back 
        // to the NO_REMOVE state so that we'll be able to attempt a rescan.
        //
        // Likewise if the lun is invisible then just swallow the remove 
        // operation now that we've cleared any existing claims.
        //

        if(RemoveType == IRP_MN_REMOVE_DEVICE) {

            //
            // If the device is not missing or is missing but is still 
            // enumerated then don't finish destroying it.
            //

            if((logicalUnitExtension->IsMissing == TRUE) &&
               (logicalUnitExtension->IsEnumerated == FALSE)) {

                // do nothing here - fall through and destroy the device.

            } else {

                DebugPrint((1, "SpRemoveLogicalUnit - device is not missing "
                               "and will not be destroyed\n"));

                SpAcquireRemoveLock(LogicalUnit, UIntToPtr( 0xabcdabcd ));

                logicalUnitExtension->CommonExtension.IsRemoved = NO_REMOVE;

                return FALSE;
            }

        } else if((logicalUnitExtension->IsVisible == FALSE) && 
                  (logicalUnitExtension->IsMissing == FALSE)) {

            //
            // The surprise remove came because the device is no longer 
            // visible.  We don't want to destroy it.
            //

            return FALSE;
        }

        //
        // Mark the device as uninitialized so that we'll go back and
        // recreate all the necessary stuff if it gets restarted.
        //

        commonExtension->IsInitialized = FALSE;

        //
        // Delete the device map entry for this one (if any).
        //

        SpDeleteDeviceMapEntry(LogicalUnit);

        if(RemoveType == IRP_MN_REMOVE_DEVICE) {

            ASSERT(logicalUnitExtension->RequestTimeoutCounter == -1);
            ASSERT(logicalUnitExtension->ReadyLogicalUnit == NULL);
            ASSERT(logicalUnitExtension->PendingRequest == NULL);
            ASSERT(logicalUnitExtension->BusyRequest == NULL);
            ASSERT(logicalUnitExtension->QueueCount == 0);
    
            commonExtension->IsRemoved = REMOVE_COMPLETE;
            SpDeleteLogicalUnit(LogicalUnit);
        }
    }

    return TRUE;
}
示例#24
0
文件: text.cpp 项目: kcrazy/winekit
/*++
*******************************************************************
    P r i n t T e x t J o b

    Routine Description:
        Prints a text data job.

    Arguments:
        pData           => Data structure for this job
        pDocumentName   => Name of this document

    Return Value:
        TRUE  if successful
        FALSE if failed - GetLastError() will return reason.
*******************************************************************
--*/
BOOL
PrintTextJob(
         IN PPRINTPROCESSORDATA pData,
    __in IN LPWSTR pDocumentName)
{
    DOCINFO     DocInfo;
    LOGFONT     LogFont;
    CHARSETINFO CharSetInfo;
    HFONT       hOldFont, hFont = NULL;
    DWORD       Copies;
    BOOL        rc;
    DWORD       NoRead;
    DWORD       CurrentLine;
    DWORD       CurrentCol;
    HANDLE      hPrinter = NULL;
    BYTE        *ReadBufferStart = NULL;
    PBYTE       pLineBuffer = NULL;
    PBYTE       pReadBuffer = NULL;
    PBYTE       pReadBufferEnd = NULL;
    ULONG       CharHeight, CharWidth, CharsPerLine, LinesPerPage;
    ULONG       PageWidth, PageHeight;
    ULONG       Length, TabBase;
    BOOL        ReadAll;
    TEXTMETRIC  tm;
    DWORD       fdwFlags;
    DWORD       Encoding;
    DWORD       SplitSize;
    BOOL        ReturnValue = FALSE;
    BOOL        bAbortDoc   = FALSE;

    DWORD       dwNeeded;
    DWORD       dwNoTranslate = 0;
    DWORD       dwNoTranslateCR = 0;
    DWORD       dwTransparent = 0;
    INT         iBkMode = OPAQUE;

    DocInfo.lpszDocName = pData->pDocument;  /* Document name */
    DocInfo.lpszOutput  = NULL;              /* Output file */
    DocInfo.lpszDatatype = NULL;             /* Datatype */
    DocInfo.cbSize = sizeof(DOCINFO);        /* Size of the structure */



    //
    // Go figure out the size of the form on the printer.  We do this
    // by calling GetTextMetrics, which gives us the font size of the
    // printer font, then getting the form size and calculating the
    // number of characters that will fit. In other cases we treat it as ANSI text.
    // Currently the codepage context is fixed to the system default codepage.
    //

    Encoding = GetACP();

    //
    // Create FIXED PITCH font and select
    //

    hOldFont = 0;
    ZeroMemory(&CharSetInfo, sizeof(CHARSETINFO));
    if (TranslateCharsetInfo((PDWORD)UIntToPtr(Encoding), &CharSetInfo, TCI_SRCCODEPAGE))
    {
        ZeroMemory(&LogFont, sizeof(LOGFONT));

        LogFont.lfWeight = 400;
        LogFont.lfCharSet = (BYTE)CharSetInfo.ciCharset;
        LogFont.lfPitchAndFamily = FIXED_PITCH;

        hFont = CreateFontIndirect(&LogFont);
        hOldFont = (HFONT) SelectObject(pData->hDC, hFont);
    }

    if (!GetTextMetrics(pData->hDC, &tm)) {
        // Essential text processing computation failed
        goto Done;
    }

    CharHeight = tm.tmHeight + tm.tmExternalLeading;
    CharWidth  = tm.tmAveCharWidth;

    if (!CharWidth || !CharHeight) {
        // Essential text processing computation failed
        goto Done;
    }

    //
    // Calculate most fittable characters' number to one line.
    //

    PageWidth = GetDeviceCaps(pData->hDC, DESKTOPHORZRES);
    PageHeight = GetDeviceCaps(pData->hDC, DESKTOPVERTRES);

    CharsPerLine = PageWidth / CharWidth;
    LinesPerPage = PageHeight / CharHeight;

    if (!CharsPerLine || !LinesPerPage) {
        // Essential text processing computation failed
        goto Done;
    }

    /** Allocate a buffer for one line of text **/

    pLineBuffer = (PBYTE)AllocSplMem(CharsPerLine + 5);

    if (!pLineBuffer) {
        goto Done;
    }

    /** Let the printer know we are starting a new document **/

    if (!StartDoc(pData->hDC, (LPDOCINFO)&DocInfo)) {

        goto Done;
    }

    ReadBufferStart = (BYTE *)AllocSplMem(READ_BUFFER_SIZE);

    if (!ReadBufferStart) {

        goto Done;
    }

    /** Print the data pData->Copies times **/

    Copies = pData->Copies;

    while (Copies--) {

        /**
            Loop, getting data and sending it to the printer.  This also
            takes care of pausing and cancelling print jobs by checking
            the processor's status flags while printing.  The way we do
            this is to read in some data from the printer.  We will then
            pull data, one tabbed line at a time from there and print
            it.  If the last bit of data in the buffer does not make up
            a whole line, we call GetTabbedLineFromBuffer() with a non-
            zero Length, which indicates that there are chars left
            from the previous read.
        **/

        TabBase = 0;
        Length = 0;
        fdwFlags = FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF;

        CurrentLine = 0;
        CurrentCol = 0;

        /**
            Open the printer.  If it fails, return.  This also sets up the
            pointer for the ReadPrinter calls.
        **/

        if (!OpenPrinter(pDocumentName, &hPrinter, NULL)) {

            hPrinter = NULL;
            bAbortDoc = TRUE;
            goto Done;
        }

        //
        // Call GetPrinterData to see if the queue wants no LF/CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCRLF,
                            NULL,
                            (PBYTE)&dwNoTranslate,
                            sizeof( dwNoTranslate ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslate ){
                fdwFlags &= ~( FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF );
            }
        }

        //
        // Call GetPrinterData to see if the queue wants no CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCR,
                            NULL,
                            (PBYTE)&dwNoTranslateCR,
                            sizeof( dwNoTranslateCR ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslateCR ){

                fdwFlags &= ~FLAG_TRANSLATE_CR;

                if( GetPrinterData( hPrinter,
                                (LPWSTR)gszTransparency,
                                NULL,
                                (PBYTE)&dwTransparent,
                                sizeof( dwTransparent ),
                                &dwNeeded ) == ERROR_SUCCESS ){

                    if( dwTransparent ){
                        iBkMode = SetBkMode( pData->hDC, TRANSPARENT );
                    }
                }
            }
        }

        if (StartPage(pData->hDC) == SP_ERROR) {

            bAbortDoc = TRUE;
            goto Done;
        }

        /** ReadAll indicates if we are on the last line of the file **/

        ReadAll = FALSE;

        /**
            This next do loop continues until we have read all of the
            data for the print job.
        **/

        do {

            if (fdwFlags & FLAG_DBCS_SPLIT) {
                SplitSize = (DWORD)(pReadBufferEnd - pReadBuffer);
                memcpy(ReadBufferStart, pReadBuffer, SplitSize);
                fdwFlags &= ~FLAG_DBCS_SPLIT;
            }
            else {
                SplitSize = 0;
            }

            rc = ReadPrinter(hPrinter,
                             (ReadBufferStart + SplitSize),
                             (READ_BUFFER_SIZE - SplitSize),
                             &NoRead);

            if (!rc || !NoRead) {

                ReadAll = TRUE;

            } else {

                /** Pick up a pointer to the end of the data **/

                pReadBuffer    = ReadBufferStart;
                pReadBufferEnd = ReadBufferStart + SplitSize + NoRead;
            }

            /**
                This loop will process all the data that we have
                just read from the printer.
            **/

            do {

                if (!ReadAll) {

                    /**
                        Length on entry holds the length of any
                        residual chars from the last line that we couldn't
                        print out because we ran out of characters on
                        the ReadPrinter buffer.
                    **/

                    pReadBuffer = GetTabbedLineFromBuffer(
                                      pReadBuffer,
                                      pReadBufferEnd,
                                      pLineBuffer,
                                      CharsPerLine - CurrentCol,
                                      pData->TabSize,
                                      Encoding,
                                      &Length,
                                      &TabBase,
                                      &fdwFlags );

                    /**

                        If pReadBuffer == NULL, then we have
                        exhausted the read buffer and we need to ReadPrinter
                        again and save the last line chars.  Length holds
                        the number of characters on this partial line,
                        so the next time we call ReadPrinter we will
                        pickup where we left off.

                        The only time we'll get residual chars is if:

                        1. The last line ends w/o ff/lf/cr ("Hello\EOF")
                           In this case we should TextOutA the last line
                           and then quit.

                           (In this case, don't break here; go ahead and
                           print, then we'll break out below in the do..while.)


                        2. The ReadPrinter last byte is in the middle of a line.
                           Here we should read the next chunk and add the
                           new characters at the end of the chars we just read.

                           (In this case, we should break and leave Length
                           as it is so we will read again and append to the
                           buffer, beginning at Length.)
                    **/

                    if (!pReadBuffer || (fdwFlags & FLAG_DBCS_SPLIT))
                        break;
                }


                /** If the print processor is paused, wait for it to be resumed **/

                if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
                    WaitForSingleObject(pData->semPaused, INFINITE);
                }

                /** If the job has been aborted, clean up and leave **/

                if (pData->fsStatus & PRINTPROCESSOR_ABORTED) {

                    ReturnValue = TRUE;

                    bAbortDoc = TRUE;
                    goto Done;
                }

                /** Write the data to the printer **/

                /** Make sure Length is not zero  **/
                /** TextOut will fail if Length == 0 **/

                if (Length) {

                    /**
                        We may have a number of newlines pending, that
                        may push us to the next page (or even next-next
                        page).
                    **/

                    while (CurrentLine >= LinesPerPage) {

                        /**
                            We need a new page; always defer this to the
                            last second to prevent extra pages from coming out.
                        **/

                        if (EndPage(pData->hDC) == SP_ERROR ||
                            StartPage(pData->hDC) == SP_ERROR) {

                            bAbortDoc = TRUE;
                            goto Done;
                        }

                        CurrentLine -= LinesPerPage;
                    }

#pragma prefast(suppress:__WARNING_ANSI_APICALL, "By design. This function is inherently handling only ANSI text print jobs.")
                    if (TextOutA(pData->hDC,
                                 CurrentCol * CharWidth,
                                 CurrentLine * CharHeight,
                                 (LPCSTR)pLineBuffer,
                                 Length) == FALSE) {

                        ODS(("TextOut() failed\n"));

                        bAbortDoc = TRUE;
                        goto Done;
                    }

                    CurrentCol += Length;
                }

                /**
                    Even if the length is zero, increment the line.
                    Should happen when the character is only 0x0D or 0x0A.
                **/

                if (fdwFlags & FLAG_CR) {
                    CurrentCol=0;
                    fdwFlags &= ~FLAG_CR;
                }

                if (fdwFlags & FLAG_LF) {
                    CurrentLine++;
                    fdwFlags &= ~FLAG_LF;
                }

                /**
                    We need a new page.  Set the current line to the
                    end of the page.  We could do a End/StartPage
                    sequence, but this may cause a blank page to get
                    ejected.

                    Note: this code will avoid printing out pages that
                    consist of formfeeds only (if you have a page with a
                    space in it, that counts as text).
                **/

                if (fdwFlags & FLAG_FF) {

                    CurrentLine = LinesPerPage;
                    CurrentCol = 0;
                    fdwFlags &= ~FLAG_FF;
                }

                /**
                    We have done the text out, so these characters have
                    been successfully printed.  Zero out Length
                    so these characters won't be printed again
                **/

                Length = 0;

                /**
                    We only terminate this loop if we run out of chars
                    or we run out of read buffer.
                **/

            } while (pReadBuffer && pReadBuffer != pReadBufferEnd);

            /** Keep going until we get the last line **/

        } while (!ReadAll);

        if (EndPage(pData->hDC) == SP_ERROR) {

            bAbortDoc = TRUE;
            goto Done;
        }

        /**
            Close the printer - we open/close the printer for each
            copy so the data pointer will rewind.
        **/

        ClosePrinter(hPrinter);
        hPrinter = NULL;

    } /* While copies to print */

    /** Let the printer know that we are done printing **/

    EndDoc(pData->hDC);

    ReturnValue = TRUE;

Done:

    if (dwTransparent)
        SetBkMode( pData->hDC, iBkMode  );

    if (hPrinter)
        ClosePrinter(hPrinter);

    if (bAbortDoc)
        AbortDoc(pData->hDC);

    if (pLineBuffer)
        FreeSplMem(pLineBuffer);

    if (hOldFont)
    {
        SelectObject(pData->hDC, hOldFont);
        DeleteObject(hFont);
    }

    if (ReadBufferStart) 
    {
        FreeSplMem(ReadBufferStart);
    }

    return ReturnValue;
}