wait.c

来自「一个类似windows」· C语言 代码 · 共 310 行

C
310
字号
/* $Id: wait.c 21253 2006-03-08 21:33:04Z audit $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/kernel32/synch/wait.c
 * PURPOSE:         Wait functions
 * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
 * UPDATE HISTORY:
 *                  Created 01/11/98
 */

/* INCLUDES *****************************************************************/

#include <k32.h>

#define NDEBUG
#include "../include/debug.h"


/* FUNCTIONS ****************************************************************/

DWORD STDCALL
GetConsoleInputWaitHandle (VOID);

/*
 * @implemented
 */
DWORD STDCALL
WaitForSingleObject(HANDLE hHandle,
		    DWORD dwMilliseconds)
{
   return WaitForSingleObjectEx(hHandle,
				dwMilliseconds,
				FALSE);
}


/*
 * @implemented
 */
DWORD STDCALL
WaitForSingleObjectEx(HANDLE hHandle,
                      DWORD  dwMilliseconds,
                      BOOL   bAlertable)
{
  PLARGE_INTEGER TimePtr;
  LARGE_INTEGER Time;
  NTSTATUS Status;

  /* Get real handle */
  switch ((ULONG)hHandle)
    {
      case STD_INPUT_HANDLE:
	hHandle = NtCurrentPeb()->ProcessParameters->StandardInput;
	break;

      case STD_OUTPUT_HANDLE:
	hHandle = NtCurrentPeb()->ProcessParameters->StandardOutput;
	break;

      case STD_ERROR_HANDLE:
	hHandle = NtCurrentPeb()->ProcessParameters->StandardError;
	break;
    }

  /* Check for console handle */
  if (IsConsoleHandle(hHandle))
    {
      if (!VerifyConsoleIoHandle(hHandle))
	{
	  SetLastError (ERROR_INVALID_HANDLE);
	  return WAIT_FAILED;
        }

      hHandle = (HANDLE)GetConsoleInputWaitHandle();
      if (hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
        {
	  SetLastError (ERROR_INVALID_HANDLE);
	  return WAIT_FAILED;

	}
    }

  if (dwMilliseconds == INFINITE)
    {
      TimePtr = NULL;
    }
  else
    {
      Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
      TimePtr = &Time;
    }

  do
    {
      Status = NtWaitForSingleObject(hHandle,
				     (BOOLEAN) bAlertable,
				     TimePtr);

      if (HIWORD(Status))
        {
          SetLastErrorByStatus (Status);
          return WAIT_FAILED;
        }

    } while (Status == STATUS_ALERTED && bAlertable);

  return Status;
}


/*
 * @implemented
 */
DWORD STDCALL
WaitForMultipleObjects(DWORD nCount,
		       CONST HANDLE *lpHandles,
		       BOOL  bWaitAll,
		       DWORD dwMilliseconds)
{
  return WaitForMultipleObjectsEx(nCount,
				  lpHandles,
				  bWaitAll,
				  dwMilliseconds,
				  FALSE);
}


/*
 * @implemented
 */
DWORD STDCALL
WaitForMultipleObjectsEx(DWORD nCount,
                         CONST HANDLE *lpHandles,
                         BOOL  bWaitAll,
                         DWORD dwMilliseconds,
                         BOOL  bAlertable)
{
  PLARGE_INTEGER TimePtr;
  LARGE_INTEGER Time;
  PHANDLE HandleBuffer;
  HANDLE Handle[3];
  DWORD i;
  NTSTATUS Status;

  DPRINT("nCount %lu\n", nCount);

  if (nCount > 3)
    {
      HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HANDLE));
      if (HandleBuffer == NULL)
        {
          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
          return WAIT_FAILED;
        }
    }
  else
    {
      HandleBuffer = Handle;
    }
  for (i = 0; i < nCount; i++)
    {
      switch ((DWORD)lpHandles[i])
	{
	  case STD_INPUT_HANDLE:
	    HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->StandardInput;
	    break;

	  case STD_OUTPUT_HANDLE:
	    HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->StandardOutput;
	    break;

	  case STD_ERROR_HANDLE:
	    HandleBuffer[i] = NtCurrentPeb()->ProcessParameters->StandardError;
	    break;

	  default:
	    HandleBuffer[i] = lpHandles[i];
	    break;
	}

      /* Check for console handle */
      if (IsConsoleHandle(HandleBuffer[i]))
	{
	  if (!VerifyConsoleIoHandle(HandleBuffer[i]))
	    {
	      if (HandleBuffer != Handle)
	        {
	          RtlFreeHeap(GetProcessHeap(),0,HandleBuffer);
	        }
	      SetLastError (ERROR_INVALID_HANDLE);
	      return WAIT_FAILED;
	    }
	  HandleBuffer[i] = (HANDLE)GetConsoleInputWaitHandle();
	  if (HandleBuffer[i] == NULL || HandleBuffer[i] == INVALID_HANDLE_VALUE)
	    {
	      if (HandleBuffer != Handle)
	        {
	          RtlFreeHeap(GetProcessHeap(),0,HandleBuffer);
	        }
	      SetLastError (ERROR_INVALID_HANDLE);
	      return WAIT_FAILED;
	    }
	}
    }

  if (dwMilliseconds == INFINITE)
    {
      TimePtr = NULL;
    }
  else
    {
      Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
      TimePtr = &Time;
    }

  do
    {
      Status = NtWaitForMultipleObjects (nCount,
				         HandleBuffer,
				         bWaitAll  ? WaitAll : WaitAny,
				         (BOOLEAN)bAlertable,
				         TimePtr);
      if (HIWORD(Status))
        {
          SetLastErrorByStatus (Status);
          Status = WAIT_FAILED;
        }

    } while (Status == STATUS_ALERTED && bAlertable);

  if (HandleBuffer != Handle)
  {
      RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
  }

  return Status;
}


/*
 * @implemented
 */
DWORD STDCALL
SignalObjectAndWait(HANDLE hObjectToSignal,
		    HANDLE hObjectToWaitOn,
		    DWORD dwMilliseconds,
		    BOOL bAlertable)
{
  PLARGE_INTEGER TimePtr;
  LARGE_INTEGER Time;
  NTSTATUS Status;

  /* Get real handle */
  switch ((ULONG)hObjectToWaitOn)
    {
      case STD_INPUT_HANDLE:
	hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->StandardInput;
	break;

      case STD_OUTPUT_HANDLE:
	hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->StandardOutput;
	break;

      case STD_ERROR_HANDLE:
	hObjectToWaitOn = NtCurrentPeb()->ProcessParameters->StandardError;
	break;
    }

  /* Check for console handle */
  if (IsConsoleHandle(hObjectToWaitOn))
    {
      if (VerifyConsoleIoHandle(hObjectToWaitOn))
	{
	  DPRINT1("Console handles are not supported yet!\n");
	  SetLastError(ERROR_INVALID_HANDLE);
	  return WAIT_FAILED;
	}
    }

  if (dwMilliseconds == INFINITE)
    {
      TimePtr = NULL;
    }
  else
    {
      Time.QuadPart = -10000 * (LONGLONG)dwMilliseconds;
      TimePtr = &Time;
    }

  do
    {
      Status = NtSignalAndWaitForSingleObject (hObjectToSignal,
					       hObjectToWaitOn,
					       (BOOLEAN)bAlertable,
					       TimePtr);
      if (!NT_SUCCESS(Status))
        {
          SetLastErrorByStatus (Status);
          return WAIT_FAILED;
        }

    } while (Status == STATUS_ALERTED && bAlertable);

  /* STATUS_SUCCESS maps to WAIT_OBJECT_0 */
  return Status;
}

/* EOF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?