You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
11 KiB
385 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
handle.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the Win32 handle management services.
|
|
|
|
Author:
|
|
|
|
Mark Lucovsky (markl) 21-Sep-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "basedll.h"
|
|
|
|
BOOL
|
|
CloseHandle(
|
|
HANDLE hObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
An open handle to any object can be closed using CloseHandle.
|
|
|
|
This is a generic function and operates on the following object
|
|
types:
|
|
|
|
- Process Object
|
|
|
|
- Thread Object
|
|
|
|
- Mutex Object
|
|
|
|
- Event Object
|
|
|
|
- Semaphore Object
|
|
|
|
- File Object
|
|
|
|
Please note that Module Objects are not in this list.
|
|
|
|
Closing an open handle to an object causes the handle to become
|
|
invalid and the HandleCount of the associated object to be
|
|
decremented and object retention checks to be performed. Once the
|
|
last open handle to an object is closed, the object is removed from
|
|
the system.
|
|
|
|
Arguments:
|
|
|
|
hObject - An open handle to an object.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The operation was successful.
|
|
|
|
FALSE/NULL - The operation failed. Extended error status is available
|
|
using GetLastError.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PPEB Peb;
|
|
|
|
Peb = NtCurrentPeb();
|
|
|
|
//
|
|
// Perhaps we ought to use a full-fledged lock here, however, it
|
|
// doesn't seem absolutely necessary, and it's reasonable to
|
|
// assume that callers are aware of the various race conditions
|
|
// which may be involved with using and closing the standard
|
|
// handles.
|
|
//
|
|
// In any event, a proper fix would use a lock in kernel mode, and
|
|
// do the mapping there, as the lock would really need to be held
|
|
// across the translation from handle to kernel object.
|
|
//
|
|
// Replacing handles with NULL will cause StuffStdHandle() to
|
|
// ignore them when duplicating handles to child processes.
|
|
//
|
|
|
|
switch( HandleToUlong(hObject) ) {
|
|
case STD_INPUT_HANDLE:
|
|
hObject = InterlockedExchangePointer(
|
|
&Peb->ProcessParameters->StandardInput,
|
|
NULL);
|
|
break;
|
|
case STD_OUTPUT_HANDLE:
|
|
hObject = InterlockedExchangePointer(
|
|
&Peb->ProcessParameters->StandardOutput,
|
|
NULL);
|
|
break;
|
|
case STD_ERROR_HANDLE:
|
|
hObject = InterlockedExchangePointer(
|
|
&Peb->ProcessParameters->StandardError,
|
|
NULL);
|
|
break;
|
|
}
|
|
if (CONSOLE_HANDLE(hObject)) {
|
|
return CloseConsoleHandle(hObject);
|
|
}
|
|
|
|
Status = NtClose(hObject);
|
|
if ( NT_SUCCESS(Status) ) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
BaseSetLastNTError(Status);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
DuplicateHandle(
|
|
HANDLE hSourceProcessHandle,
|
|
HANDLE hSourceHandle,
|
|
HANDLE hTargetProcessHandle,
|
|
LPHANDLE lpTargetHandle,
|
|
DWORD dwDesiredAccess,
|
|
BOOL bInheritHandle,
|
|
DWORD dwOptions
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
A duplicate handle can be created with the DuplicateHandle function.
|
|
|
|
This is a generic function and operates on the following object
|
|
types:
|
|
|
|
- Process Object
|
|
|
|
- Thread Object
|
|
|
|
- Mutex Object
|
|
|
|
- Event Object
|
|
|
|
- Semaphore Object
|
|
|
|
- File Object
|
|
|
|
Please note that Module Objects are not in this list.
|
|
|
|
This function requires PROCESS_DUP_ACCESS to both the
|
|
SourceProcessHandle and the TargetProcessHandle. This function is
|
|
used to pass an object handle from one process to another. Once
|
|
this call is complete, the target process needs to be informed of
|
|
the value of the target handle. The target process can then operate
|
|
on the object using this handle value.
|
|
|
|
Arguments:
|
|
|
|
hSourceProcessHandle - An open handle to the process that contains the
|
|
handle to be duplicated. The handle must have been created with
|
|
PROCESS_DUP_HANDLE access to the process.
|
|
|
|
hSourceHandle - An open handle to any object that is valid in the
|
|
context of the source process.
|
|
|
|
hTargetProcessHandle - An open handle to the process that is to
|
|
receive the duplicated handle. The handle must have been
|
|
created with PROCESS_DUP_HANDLE access to the process.
|
|
|
|
lpTargetHandle - A pointer to a variable which receives the new handle
|
|
that points to the same object as SourceHandle does. This
|
|
handle value is valid in the context of the target process.
|
|
|
|
dwDesiredAccess - The access requested to for the new handle. This
|
|
parameter is ignored if the DUPLICATE_SAME_ACCESS option is
|
|
specified.
|
|
|
|
bInheritHandle - Supplies a flag that if TRUE, marks the target
|
|
handle as inheritable. If this is the case, then the target
|
|
handle will be inherited to new processes each time the target
|
|
process creates a new process using CreateProcess.
|
|
|
|
dwOptions - Specifies optional behaviors for the caller.
|
|
|
|
Options Flags:
|
|
|
|
DUPLICATE_CLOSE_SOURCE - The SourceHandle will be closed by
|
|
this service prior to returning to the caller. This occurs
|
|
regardless of any error status returned.
|
|
|
|
DUPLICATE_SAME_ACCESS - The DesiredAccess parameter is ignored
|
|
and instead the GrantedAccess associated with SourceHandle
|
|
is used as the DesiredAccess when creating the TargetHandle.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The operation was successful.
|
|
|
|
FALSE/NULL - The operation failed. Extended error status is available
|
|
using GetLastError.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PPEB Peb;
|
|
|
|
Peb = NtCurrentPeb();
|
|
switch( HandleToUlong(hSourceHandle) ) {
|
|
case STD_INPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardInput;
|
|
break;
|
|
case STD_OUTPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardOutput;
|
|
break;
|
|
case STD_ERROR_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardError;
|
|
break;
|
|
}
|
|
|
|
if (CONSOLE_HANDLE(hSourceHandle) &&
|
|
(hSourceHandle != NtCurrentProcess() &&
|
|
hSourceHandle != NtCurrentThread()) ) {
|
|
HANDLE Target;
|
|
|
|
if (hSourceProcessHandle != NtCurrentProcess() ||
|
|
hTargetProcessHandle != NtCurrentProcess()) {
|
|
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
Target = DuplicateConsoleHandle(hSourceHandle,
|
|
dwDesiredAccess,
|
|
bInheritHandle,
|
|
dwOptions
|
|
);
|
|
if (Target == INVALID_HANDLE_VALUE) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
try {
|
|
if ( ARGUMENT_PRESENT(lpTargetHandle) ) {
|
|
*lpTargetHandle = Target;
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
return TRUE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
Status = NtDuplicateObject(
|
|
hSourceProcessHandle,
|
|
hSourceHandle,
|
|
hTargetProcessHandle,
|
|
lpTargetHandle,
|
|
(ACCESS_MASK)dwDesiredAccess,
|
|
bInheritHandle ? OBJ_INHERIT : 0,
|
|
dwOptions
|
|
);
|
|
if ( NT_SUCCESS(Status) ) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
BaseSetLastNTError(Status);
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetHandleInformation(
|
|
HANDLE hObject,
|
|
LPDWORD lpdwFlags
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
|
|
DWORD Result;
|
|
PPEB Peb;
|
|
|
|
Peb = NtCurrentPeb();
|
|
switch( HandleToUlong(hObject) ) {
|
|
case STD_INPUT_HANDLE: hObject = Peb->ProcessParameters->StandardInput;
|
|
break;
|
|
case STD_OUTPUT_HANDLE: hObject = Peb->ProcessParameters->StandardOutput;
|
|
break;
|
|
case STD_ERROR_HANDLE: hObject = Peb->ProcessParameters->StandardError;
|
|
break;
|
|
}
|
|
|
|
if (CONSOLE_HANDLE(hObject)) {
|
|
return GetConsoleHandleInformation(hObject,
|
|
lpdwFlags
|
|
);
|
|
}
|
|
|
|
Status = NtQueryObject( hObject,
|
|
ObjectHandleFlagInformation,
|
|
&HandleInfo,
|
|
sizeof( HandleInfo ),
|
|
NULL
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
Result = 0;
|
|
if (HandleInfo.Inherit) {
|
|
Result |= HANDLE_FLAG_INHERIT;
|
|
}
|
|
|
|
if (HandleInfo.ProtectFromClose) {
|
|
Result |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
|
|
}
|
|
|
|
*lpdwFlags = Result;
|
|
return TRUE;
|
|
}
|
|
else {
|
|
BaseSetLastNTError( Status );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
SetHandleInformation(
|
|
HANDLE hObject,
|
|
DWORD dwMask,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
|
|
PPEB Peb;
|
|
|
|
Peb = NtCurrentPeb();
|
|
switch( HandleToUlong(hObject) ) {
|
|
case STD_INPUT_HANDLE: hObject = Peb->ProcessParameters->StandardInput;
|
|
break;
|
|
case STD_OUTPUT_HANDLE: hObject = Peb->ProcessParameters->StandardOutput;
|
|
break;
|
|
case STD_ERROR_HANDLE: hObject = Peb->ProcessParameters->StandardError;
|
|
break;
|
|
}
|
|
|
|
if (CONSOLE_HANDLE(hObject)) {
|
|
return SetConsoleHandleInformation(hObject,
|
|
dwMask,
|
|
dwFlags
|
|
);
|
|
}
|
|
|
|
Status = NtQueryObject( hObject,
|
|
ObjectHandleFlagInformation,
|
|
&HandleInfo,
|
|
sizeof( HandleInfo ),
|
|
NULL
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
if (dwMask & HANDLE_FLAG_INHERIT) {
|
|
HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
|
|
}
|
|
|
|
if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) {
|
|
HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
|
|
}
|
|
|
|
Status = NtSetInformationObject( hObject,
|
|
ObjectHandleFlagInformation,
|
|
&HandleInfo,
|
|
sizeof( HandleInfo )
|
|
);
|
|
if (NT_SUCCESS( Status )) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BaseSetLastNTError( Status );
|
|
return FALSE;
|
|
}
|