⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 npipe.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
WINAPI
GetNamedPipeHandleStateW(HANDLE hNamedPipe,
                         LPDWORD lpState,
                         LPDWORD lpCurInstances,
                         LPDWORD lpMaxCollectionCount,
                         LPDWORD lpCollectDataTimeout,
                         LPWSTR lpUserName,
                         DWORD nMaxUserNameSize)
{
    IO_STATUS_BLOCK StatusBlock;
    NTSTATUS Status;

    if (lpState != NULL)
    {
        FILE_PIPE_INFORMATION PipeInfo;

        Status = NtQueryInformationFile(hNamedPipe,
                                        &StatusBlock,
                                        &PipeInfo,
                                        sizeof(FILE_PIPE_INFORMATION),
                                        FilePipeInformation);
        if (!NT_SUCCESS(Status))
        {
            SetLastErrorByStatus(Status);
            return FALSE;
        }

        *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
        *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
    }

    if(lpCurInstances != NULL)
    {
        FILE_PIPE_LOCAL_INFORMATION LocalInfo;

        Status = NtQueryInformationFile(hNamedPipe,
                                        &StatusBlock,
                                        &LocalInfo,
                                        sizeof(FILE_PIPE_LOCAL_INFORMATION),
                                        FilePipeLocalInformation);
        if (!NT_SUCCESS(Status))
        {
            SetLastErrorByStatus(Status);
            return FALSE;
        }

        *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
    }

    if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
    {
        FILE_PIPE_REMOTE_INFORMATION RemoteInfo;

        Status = NtQueryInformationFile(hNamedPipe,
                                        &StatusBlock,
                                        &RemoteInfo,
                                        sizeof(FILE_PIPE_REMOTE_INFORMATION),
                                        FilePipeRemoteInformation);
        if (!NT_SUCCESS(Status))
        {
            SetLastErrorByStatus(Status);
            return FALSE;
        }

        if (lpMaxCollectionCount != NULL)
        {
            *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
        }

        if(lpCollectDataTimeout != NULL)
        {
            /* FIXME */
           *lpCollectDataTimeout = 0;
        }
    }

    if (lpUserName != NULL)
    {
      /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
                 retreive the user name with GetUserName(), revert the impersonation
                 and finally restore the thread token */
    }

    return TRUE;
}


/*
 * @implemented
 */
BOOL
WINAPI
GetNamedPipeHandleStateA(HANDLE hNamedPipe,
                         LPDWORD lpState,
                         LPDWORD lpCurInstances,
                         LPDWORD lpMaxCollectionCount,
                         LPDWORD lpCollectDataTimeout,
                         LPSTR lpUserName,
                         DWORD nMaxUserNameSize)
{
    UNICODE_STRING UserNameW = {0};
    ANSI_STRING UserNameA;
    BOOL Ret;

    if(lpUserName != NULL)
    {
        UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR);
        UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
        if (UserNameW.Buffer == NULL)
        {
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            return FALSE;
        }

        UserNameA.Buffer = lpUserName;
        UserNameA.Length = 0;
        UserNameA.MaximumLength = (USHORT)nMaxUserNameSize;
    }

    Ret = GetNamedPipeHandleStateW(hNamedPipe,
                                   lpState,
                                   lpCurInstances,
                                   lpMaxCollectionCount,
                                   lpCollectDataTimeout,
                                   UserNameW.Buffer,
                                   nMaxUserNameSize);
    if (Ret && lpUserName != NULL)
    {
        NTSTATUS Status;

        RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
        Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
        if (!NT_SUCCESS(Status))
        {
            SetLastErrorByStatus(Status);
            Ret = FALSE;
        }
    }

    if (UserNameW.Buffer != NULL)
    {
        RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
    }

    return Ret;
}


/*
 * @implemented
 */
BOOL
WINAPI
GetNamedPipeInfo(HANDLE hNamedPipe,
                 LPDWORD lpFlags,
                 LPDWORD lpOutBufferSize,
                 LPDWORD lpInBufferSize,
                 LPDWORD lpMaxInstances)
{
    FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
    IO_STATUS_BLOCK StatusBlock;
    NTSTATUS Status;

    Status = NtQueryInformationFile(hNamedPipe,
                                    &StatusBlock,
                                    &PipeLocalInformation,
                                    sizeof(FILE_PIPE_LOCAL_INFORMATION),
                                    FilePipeLocalInformation);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    if (lpFlags != NULL)
    {
        *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
        *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
    }

    if (lpOutBufferSize != NULL)
        *lpOutBufferSize = PipeLocalInformation.OutboundQuota;

    if (lpInBufferSize != NULL)
        *lpInBufferSize = PipeLocalInformation.InboundQuota;

    if (lpMaxInstances != NULL)
    {
        if (PipeLocalInformation.MaximumInstances >= 255)
            *lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
        else
            *lpMaxInstances = PipeLocalInformation.MaximumInstances;
    }

    return TRUE;
}


/*
 * @implemented
 */
BOOL
WINAPI
PeekNamedPipe(HANDLE hNamedPipe,
              LPVOID lpBuffer,
              DWORD nBufferSize,
              LPDWORD lpBytesRead,
              LPDWORD lpTotalBytesAvail,
              LPDWORD lpBytesLeftThisMessage)
{
    PFILE_PIPE_PEEK_BUFFER Buffer;
    IO_STATUS_BLOCK Iosb;
    ULONG BufferSize;
    ULONG BytesRead;
    NTSTATUS Status;

    /* Calculate the buffer space that we'll need and allocate it */
    BufferSize = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
    Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
    if (Buffer == NULL)
    {
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }

    /* Tell the driver to seek */
    Status = NtFsControlFile(hNamedPipe,
                             NULL,
                             NULL,
                             NULL,
                             &Iosb,
                             FSCTL_PIPE_PEEK,
                             NULL,
                             0,
                             Buffer,
                             BufferSize);
    if (Status == STATUS_PENDING)
    {
        /* Wait for npfs to be done, and update the status */
        Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
        if (NT_SUCCESS(Status))
            Status = Iosb.Status;
    }

    /* Overflow is success for us */
    if (Status == STATUS_BUFFER_OVERFLOW)
        Status = STATUS_SUCCESS;

    /* If we failed */
    if (!NT_SUCCESS(Status))
    {
        /* Free the buffer and return failure */
        RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    /* Check if caller requested bytes available */
    if (lpTotalBytesAvail)
        *lpTotalBytesAvail = Buffer->ReadDataAvailable;

    /* Calculate the bytes returned, minus our structure overhead */
    BytesRead = (ULONG)(Iosb.Information -
                        FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));

    /* Check if caller requested bytes read */
    if (lpBytesRead)
    {
        /* Return the bytes read */
        *lpBytesRead = BytesRead;
    }

    /* Check if caller requested bytes left */
    if (lpBytesLeftThisMessage)
    {
        /* Calculate total minus what we returned and our structure overhead */
        *lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead;
    }

    /* Check if the caller wanted to see the actual data */
    if (lpBuffer)
    {
        /* Give him what he wants */
        RtlCopyMemory(lpBuffer,
                      Buffer->Data,
                      BytesRead);
    }

    /* Free the buffer */
    RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);

    return TRUE;
}


/*
 * @implemented
 */
BOOL
WINAPI
TransactNamedPipe(IN HANDLE hNamedPipe,
                  IN LPVOID lpInBuffer,
                  IN DWORD nInBufferSize,
                  OUT LPVOID lpOutBuffer,
                  IN DWORD nOutBufferSize,
                  OUT LPDWORD lpBytesRead  OPTIONAL,
                  IN LPOVERLAPPED lpOverlapped  OPTIONAL)
{
    NTSTATUS Status;

    if (lpBytesRead != NULL)
    {
        *lpBytesRead = 0;
    }

    if (lpOverlapped != NULL)
    {
        PVOID ApcContext;

        ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
        lpOverlapped->Internal = STATUS_PENDING;

        Status = NtFsControlFile(hNamedPipe,
                                 lpOverlapped->hEvent,
                                 NULL,
                                 ApcContext,
                                 (PIO_STATUS_BLOCK)lpOverlapped,
                                 FSCTL_PIPE_TRANSCEIVE,
                                 lpInBuffer,
                                 nInBufferSize,
                                 lpOutBuffer,
                                 nOutBufferSize);
        if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
        {
            SetLastErrorByStatus(Status);
            return FALSE;
        }

        if (lpBytesRead != NULL)
        {
            *lpBytesRead = lpOverlapped->InternalHigh;
        }
    }
    else
    {
#if 0 /* We don't implement FSCTL_PIPE_TRANSCEIVE yet */
        IO_STATUS_BLOCK Iosb;

        Status = NtFsControlFile(hNamedPipe,
                                 NULL,
                                 NULL,
                                 NULL,
                                 &Iosb,
                                 FSCTL_PIPE_TRANSCEIVE,
                                 lpInBuffer,
                                 nInBufferSize,
                                 lpOutBuffer,
                                 nOutBufferSize);
        if (Status == STATUS_PENDING)
        {
            Status = NtWaitForSingleObject(hNamedPipe,
                                           FALSE,
                                           NULL);
            if (NT_SUCCESS(Status))
                Status = Iosb.Status;
        }

        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) */
            *lpBytesRead = Iosb.Information;
        }
        else
        {
            SetLastErrorByStatus(Status);
            return FALSE;
        }
#else /* Workaround while FSCTL_PIPE_TRANSCEIVE not available */
        DWORD nActualBytes;

        while (0 != nInBufferSize &&
               WriteFile(hNamedPipe, lpInBuffer, nInBufferSize, &nActualBytes,
                         NULL))
        {
             lpInBuffer = (LPVOID)((char *) lpInBuffer + nActualBytes);
             nInBufferSize -= nActualBytes;
        }

        if (0 != nInBufferSize)
        {
             /* Must have dropped out of the while 'cause WriteFile failed */
             return FALSE;
        }

        if (!ReadFile(hNamedPipe, lpOutBuffer, nOutBufferSize, &nActualBytes,
                      NULL))
        {
             return FALSE;
        }

        if (NULL != lpBytesRead)
        {
            *lpBytesRead = nActualBytes;
        }
#endif
    }

    return TRUE;
}

/* EOF */

⌨️ 快捷键说明

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