/* * @implemented */ BOOL WINAPI CloseHandle(HANDLE hObject) /* * FUNCTION: Closes an open object handle * PARAMETERS: * hObject = Identifies an open object handle * RETURNS: If the function succeeds, the return value is nonzero * If the function fails, the return value is zero */ { NTSTATUS Status; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { return(CloseConsoleHandle(hObject)); } Status = NtClose(hObject); if (!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; }
/* * @implemented */ DWORD WINAPI SignalObjectAndWait(IN HANDLE hObjectToSignal, IN HANDLE hObjectToWaitOn, IN DWORD dwMilliseconds, IN BOOL bAlertable) { PLARGE_INTEGER TimePtr; LARGE_INTEGER Time; NTSTATUS Status; RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; /* APCs must execute with the default activation context */ if (bAlertable) { /* Setup the frame */ RtlZeroMemory(&ActCtx, sizeof(ActCtx)); ActCtx.Size = sizeof(ActCtx); ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); } /* Get real handle */ hObjectToWaitOn = TranslateStdHandle(hObjectToWaitOn); /* Check for console handle */ if ((IsConsoleHandle(hObjectToWaitOn)) && (VerifyConsoleIoHandle(hObjectToWaitOn))) { /* Get the real wait handle */ hObjectToWaitOn = GetConsoleInputWaitHandle(); } /* Convert the timeout */ TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); /* Start wait loop */ do { /* Do the wait */ Status = NtSignalAndWaitForSingleObject(hObjectToSignal, hObjectToWaitOn, (BOOLEAN)bAlertable, TimePtr); if (!NT_SUCCESS(Status)) { /* The wait failed */ BaseSetLastNTError(Status); Status = WAIT_FAILED; } } while ((Status == STATUS_ALERTED) && (bAlertable)); /* Cleanup the activation context */ if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); /* Return wait status */ return Status; }
/* * @implemented */ BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions) { NTSTATUS Status; HANDLE hTargetHandle; hSourceHandle = TranslateStdHandle(hSourceHandle); if ((IsConsoleHandle(hSourceHandle)) && ((hSourceHandle != NtCurrentProcess()) && (hSourceHandle != NtCurrentThread()))) { if ((hSourceProcessHandle != NtCurrentProcess()) && (hTargetProcessHandle != NtCurrentProcess())) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } hTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); if (hTargetHandle != INVALID_HANDLE_VALUE) { if (lpTargetHandle) *lpTargetHandle = hTargetHandle; return TRUE; } return FALSE; } Status = NtDuplicateObject(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle ? OBJ_INHERIT : 0, dwOptions); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL WINAPI SetHandleInformation(IN HANDLE hObject, IN DWORD dwMask, IN DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { /* FIXME: SetConsoleHandleInformation required */ UNIMPLEMENTED; BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); return FALSE; } Status = NtQueryObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } if (dwMask & HANDLE_FLAG_INHERIT) { HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; } if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) { HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; } Status = NtSetInformationObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(HandleInfo)); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL WINAPI CloseHandle(IN HANDLE hObject) { NTSTATUS Status; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) return CloseConsoleHandle(hObject); Status = NtClose(hObject); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ BOOL WINAPI DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions) { DWORD SourceProcessId, TargetProcessId; NTSTATUS Status; hSourceHandle = TranslateStdHandle(hSourceHandle); if (IsConsoleHandle(hSourceHandle)) { SourceProcessId = GetProcessId(hSourceProcessHandle); TargetProcessId = GetProcessId(hTargetProcessHandle); if (!SourceProcessId || !TargetProcessId || SourceProcessId != TargetProcessId || SourceProcessId != GetCurrentProcessId()) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } *lpTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); return *lpTargetHandle != INVALID_HANDLE_VALUE; } Status = NtDuplicateObject(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle ? OBJ_INHERIT : 0, dwOptions); if (!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; }
/* * @implemented */ BOOL WINAPI SetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; hObject = TranslateStdHandle(hObject); Status = NtQueryObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (NT_SUCCESS(Status)) { if (dwMask & HANDLE_FLAG_INHERIT) HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) != 0; if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) != 0; Status = NtSetInformationObject (hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION)); if(!NT_SUCCESS(Status)) { SetLastErrorByStatus (Status); return FALSE; } return TRUE; } else { SetLastErrorByStatus (Status); return FALSE; } }
/* * @implemented */ HANDLE WINAPI RegisterWaitForSingleObjectEx(IN HANDLE hObject, IN WAITORTIMERCALLBACK Callback, IN PVOID Context, IN ULONG dwMilliseconds, IN ULONG dwFlags) { NTSTATUS Status; HANDLE hNewWaitObject; /* Get real handle */ hObject = TranslateStdHandle(hObject); /* Check for console handle */ if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject))) { /* Get the real wait handle */ hObject = GetConsoleInputWaitHandle(); } /* Register the wait */ Status = RtlRegisterWait(&hNewWaitObject, hObject, Callback, Context, dwMilliseconds, dwFlags); if (!NT_SUCCESS(Status)) { /* Return failure */ BaseSetLastNTError(Status); return NULL; } /* Return the object */ return hNewWaitObject; }
/* * @implemented */ BOOL WINAPI GetHandleInformation(IN HANDLE hObject, OUT LPDWORD lpdwFlags) { OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; ULONG BytesWritten; NTSTATUS Status; DWORD Flags; hObject = TranslateStdHandle(hObject); if (IsConsoleHandle(hObject)) { /* FIXME: GetConsoleHandleInformation required */ UNIMPLEMENTED; BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); return FALSE; } Status = NtQueryObject(hObject, ObjectHandleFlagInformation, &HandleInfo, sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION), &BytesWritten); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } Flags = 0; if (HandleInfo.Inherit) Flags |= HANDLE_FLAG_INHERIT; if (HandleInfo.ProtectFromClose) Flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE; *lpdwFlags = Flags; return TRUE; }
/* * @implemented */ BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL) { NTSTATUS Status; TRACE("WriteFile(hFile %p)\n", hFile); if (lpNumberOfBytesWritten != NULL) *lpNumberOfBytesWritten = 0; hFile = TranslateStdHandle(hFile); if (IsConsoleHandle(hFile)) { return WriteConsoleA(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); } if (lpOverlapped != NULL) { LARGE_INTEGER Offset; PVOID ApcContext; Offset.u.LowPart = lpOverlapped->Offset; Offset.u.HighPart = lpOverlapped->OffsetHigh; lpOverlapped->Internal = STATUS_PENDING; ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); Status = NtWriteFile(hFile, lpOverlapped->hEvent, NULL, ApcContext, (PIO_STATUS_BLOCK)lpOverlapped, (PVOID)lpBuffer, nNumberOfBytesToWrite, &Offset, NULL); /* return FALSE in case of failure and pending operations! */ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) { BaseSetLastNTError(Status); return FALSE; } if (lpNumberOfBytesWritten != NULL) *lpNumberOfBytesWritten = lpOverlapped->InternalHigh; } else { IO_STATUS_BLOCK Iosb; Status = NtWriteFile(hFile, NULL, NULL, NULL, &Iosb, (PVOID)lpBuffer, nNumberOfBytesToWrite, NULL, NULL); /* Wait in case operation is pending */ if (Status == STATUS_PENDING) { Status = NtWaitForSingleObject(hFile, FALSE, NULL); if (NT_SUCCESS(Status)) Status = Iosb.Status; } if (NT_SUCCESS(Status)) { /* * lpNumberOfBytesWritten must not be NULL here, in fact Win doesn't * check that case either and crashes (only after the operation * completed). */ *lpNumberOfBytesWritten = Iosb.Information; } else { BaseSetLastNTError(Status); return FALSE; } } TRACE("WriteFile() succeeded\n"); return TRUE; }
/* * @implemented */ BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL) { NTSTATUS Status; TRACE("ReadFile(hFile %p)\n", hFile); if (lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = 0; if (!nNumberOfBytesToRead) return TRUE; hFile = TranslateStdHandle(hFile); if (IsConsoleHandle(hFile)) { if (ReadConsoleA(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL)) { DWORD dwMode; GetConsoleMode(hFile, &dwMode); if ((dwMode & ENABLE_PROCESSED_INPUT) && *(PCHAR)lpBuffer == 0x1a) { /* EOF character entered; simulate end-of-file */ *lpNumberOfBytesRead = 0; } return TRUE; } return FALSE; } if (lpOverlapped != NULL) { LARGE_INTEGER Offset; PVOID ApcContext; Offset.u.LowPart = lpOverlapped->Offset; Offset.u.HighPart = lpOverlapped->OffsetHigh; lpOverlapped->Internal = STATUS_PENDING; ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped); Status = NtReadFile(hFile, lpOverlapped->hEvent, NULL, ApcContext, (PIO_STATUS_BLOCK)lpOverlapped, lpBuffer, nNumberOfBytesToRead, &Offset, NULL); /* return FALSE in case of failure and pending operations! */ if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) { if (Status == STATUS_END_OF_FILE && lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = 0; BaseSetLastNTError(Status); return FALSE; } if (lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = lpOverlapped->InternalHigh; } else { IO_STATUS_BLOCK Iosb; Status = NtReadFile(hFile, NULL, NULL, NULL, &Iosb, lpBuffer, nNumberOfBytesToRead, NULL, NULL); /* Wait in case operation is pending */ if (Status == STATUS_PENDING) { Status = NtWaitForSingleObject(hFile, FALSE, NULL); if (NT_SUCCESS(Status)) Status = Iosb.Status; } if (Status == STATUS_END_OF_FILE) { /* * lpNumberOfBytesRead must not be NULL here, in fact Win doesn't * check that case either and crashes (only after the operation * completed). */ *lpNumberOfBytesRead = 0; return TRUE; } if (NT_SUCCESS(Status)) { /* * lpNumberOfBytesRead must not be NULL here, in fact Win doesn't * check that case either and crashes (only after the operation * completed). */ *lpNumberOfBytesRead = Iosb.Information; } else { BaseSetLastNTError(Status); return FALSE; } } TRACE("ReadFile() succeeded\n"); return TRUE; }
/* * @implemented */ DWORD WINAPI WaitForMultipleObjectsEx(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds, IN BOOL bAlertable) { PLARGE_INTEGER TimePtr; LARGE_INTEGER Time; PHANDLE HandleBuffer; HANDLE Handle[8]; DWORD i; NTSTATUS Status; RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; /* APCs must execute with the default activation context */ if (bAlertable) { /* Setup the frame */ RtlZeroMemory(&ActCtx, sizeof(ActCtx)); ActCtx.Size = sizeof(ActCtx); ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); } /* Check if we have more handles then we locally optimize */ if (nCount > 8) { /* Allocate a buffer for them */ HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HANDLE)); if (!HandleBuffer) { /* No buffer, fail the wait */ SetLastError(ERROR_NOT_ENOUGH_MEMORY); if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); return WAIT_FAILED; } } else { /* Otherwise, use our local buffer */ HandleBuffer = Handle; } /* Copy the handles into our buffer and loop them all */ RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE)); for (i = 0; i < nCount; i++) { /* Check what kind of handle this is */ HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]); /* Check for console handle */ if ((IsConsoleHandle(HandleBuffer[i])) && (VerifyConsoleIoHandle(HandleBuffer[i]))) { /* Get the real wait handle */ HandleBuffer[i] = GetConsoleInputWaitHandle(); } } /* Convert the timeout */ TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); /* Start wait loop */ do { /* Do the wait */ Status = NtWaitForMultipleObjects(nCount, HandleBuffer, bWaitAll ? WaitAll : WaitAny, (BOOLEAN)bAlertable, TimePtr); if (!NT_SUCCESS(Status)) { /* Wait failed */ BaseSetLastNTError(Status); Status = WAIT_FAILED; } } while ((Status == STATUS_ALERTED) && (bAlertable)); /* Check if we didn't use our local buffer */ if (HandleBuffer != Handle) { /* Free the allocated one */ RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); } /* Cleanup the activation context */ if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); /* Return wait status */ return Status; }