|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* WinPR: Windows Portable Runtime
|
|
Packit |
1fb8d4 |
* Asynchronous I/O Functions
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
Packit |
1fb8d4 |
* you may not use this file except in compliance with the License.
|
|
Packit |
1fb8d4 |
* You may obtain a copy of the License at
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
1fb8d4 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
1fb8d4 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
1fb8d4 |
* See the License for the specific language governing permissions and
|
|
Packit |
1fb8d4 |
* limitations under the License.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
1fb8d4 |
#include "config.h"
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <winpr/io.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifndef _WIN32
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include "io.h"
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <stdio.h>
|
|
Packit |
1fb8d4 |
#include <fcntl.h>
|
|
Packit |
1fb8d4 |
#include <stdlib.h>
|
|
Packit |
1fb8d4 |
#include <errno.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
1fb8d4 |
#include <unistd.h>
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <sys/types.h>
|
|
Packit |
1fb8d4 |
#include <sys/stat.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <winpr/crt.h>
|
|
Packit |
1fb8d4 |
#include <winpr/path.h>
|
|
Packit |
1fb8d4 |
#include <winpr/file.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* I/O Manager Routines
|
|
Packit |
1fb8d4 |
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff551797/
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* These routines are only accessible to kernel drivers, but we need
|
|
Packit |
1fb8d4 |
* similar functionality in WinPR in user space.
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* This is a best effort non-conflicting port of this API meant for
|
|
Packit |
1fb8d4 |
* non-Windows, WinPR usage only.
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* References:
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Device Objects and Device Stacks:
|
|
Packit |
1fb8d4 |
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff543153/
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Driver Development Part 1: Introduction to Drivers:
|
|
Packit |
1fb8d4 |
* http://www.codeproject.com/Articles/9504/Driver-Development-Part-1-Introduction-to-Drivers/
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
#define DEVICE_FILE_PREFIX_PATH "\\Device\\"
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static char* GetDeviceFileNameWithoutPrefixA(LPCSTR lpName)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
char* lpFileName;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!lpName)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (strncmp(lpName, DEVICE_FILE_PREFIX_PATH, sizeof(DEVICE_FILE_PREFIX_PATH) - 1) != 0)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
lpFileName =
|
|
Packit Service |
5a9772 |
_strdup(&lpName[strnlen(DEVICE_FILE_PREFIX_PATH, sizeof(DEVICE_FILE_PREFIX_PATH))]);
|
|
Packit |
1fb8d4 |
return lpFileName;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static char* GetDeviceFileUnixDomainSocketBaseFilePathA(void)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
char* lpTempPath;
|
|
Packit |
1fb8d4 |
char* lpPipePath;
|
|
Packit |
1fb8d4 |
lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!lpTempPath)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
lpPipePath = GetCombinedPath(lpTempPath, ".device");
|
|
Packit |
1fb8d4 |
free(lpTempPath);
|
|
Packit |
1fb8d4 |
return lpPipePath;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static char* GetDeviceFileUnixDomainSocketFilePathA(LPCSTR lpName)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
char* lpPipePath = NULL;
|
|
Packit |
1fb8d4 |
char* lpFileName = NULL;
|
|
Packit |
1fb8d4 |
char* lpFilePath = NULL;
|
|
Packit |
1fb8d4 |
lpPipePath = GetDeviceFileUnixDomainSocketBaseFilePathA();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!lpPipePath)
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
lpFileName = GetDeviceFileNameWithoutPrefixA(lpName);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!lpFileName)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(lpPipePath);
|
|
Packit |
1fb8d4 |
return NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
lpFilePath = GetCombinedPath(lpPipePath, (char*)lpFileName);
|
|
Packit |
1fb8d4 |
free(lpPipePath);
|
|
Packit |
1fb8d4 |
free(lpFileName);
|
|
Packit |
1fb8d4 |
return lpFilePath;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* IoCreateDevice:
|
|
Packit |
1fb8d4 |
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff548397/
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
NTSTATUS _IoCreateDeviceEx(PDRIVER_OBJECT_EX DriverObject, ULONG DeviceExtensionSize,
|
|
Packit Service |
5a9772 |
PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType,
|
|
Packit Service |
5a9772 |
ULONG DeviceCharacteristics, BOOLEAN Exclusive,
|
|
Packit |
1fb8d4 |
PDEVICE_OBJECT_EX* DeviceObject)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
int status;
|
|
Packit |
1fb8d4 |
char* DeviceBasePath;
|
|
Packit |
1fb8d4 |
DEVICE_OBJECT_EX* pDeviceObjectEx;
|
|
Packit |
1fb8d4 |
DeviceBasePath = GetDeviceFileUnixDomainSocketBaseFilePathA();
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!DeviceBasePath)
|
|
Packit |
1fb8d4 |
return STATUS_NO_MEMORY;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!PathFileExistsA(DeviceBasePath))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (mkdir(DeviceBasePath, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(DeviceBasePath);
|
|
Packit |
1fb8d4 |
return STATUS_ACCESS_DENIED;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(DeviceBasePath);
|
|
Packit Service |
5a9772 |
pDeviceObjectEx = (DEVICE_OBJECT_EX*)calloc(1, sizeof(DEVICE_OBJECT_EX));
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!pDeviceObjectEx)
|
|
Packit |
1fb8d4 |
return STATUS_NO_MEMORY;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
ConvertFromUnicode(CP_UTF8, 0, DeviceName->Buffer, DeviceName->Length / 2,
|
|
Packit |
1fb8d4 |
&(pDeviceObjectEx->DeviceName), 0, NULL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!pDeviceObjectEx->DeviceName)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx);
|
|
Packit |
1fb8d4 |
return STATUS_NO_MEMORY;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
pDeviceObjectEx->DeviceFileName =
|
|
Packit Service |
5a9772 |
GetDeviceFileUnixDomainSocketFilePathA(pDeviceObjectEx->DeviceName);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!pDeviceObjectEx->DeviceFileName)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx);
|
|
Packit |
1fb8d4 |
return STATUS_NO_MEMORY;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (PathFileExistsA(pDeviceObjectEx->DeviceFileName))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (unlink(pDeviceObjectEx->DeviceFileName) == -1)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceFileName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx);
|
|
Packit |
1fb8d4 |
return STATUS_ACCESS_DENIED;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
status = mkfifo(pDeviceObjectEx->DeviceFileName, 0666);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (status != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceFileName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
switch (errno)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
case EACCES:
|
|
Packit |
1fb8d4 |
return STATUS_ACCESS_DENIED;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case EEXIST:
|
|
Packit |
1fb8d4 |
return STATUS_OBJECT_NAME_EXISTS;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case ENAMETOOLONG:
|
|
Packit |
1fb8d4 |
return STATUS_NAME_TOO_LONG;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case ENOENT:
|
|
Packit |
1fb8d4 |
case ENOTDIR:
|
|
Packit |
1fb8d4 |
return STATUS_NOT_A_DIRECTORY;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
case ENOSPC:
|
|
Packit |
1fb8d4 |
return STATUS_DISK_FULL;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
default:
|
|
Packit |
1fb8d4 |
return STATUS_INTERNAL_ERROR;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
*((ULONG_PTR*)(DeviceObject)) = (ULONG_PTR)pDeviceObjectEx;
|
|
Packit |
1fb8d4 |
return STATUS_SUCCESS;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* IoDeleteDevice:
|
|
Packit |
1fb8d4 |
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff549083/
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
VOID _IoDeleteDeviceEx(PDEVICE_OBJECT_EX DeviceObject)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DEVICE_OBJECT_EX* pDeviceObjectEx;
|
|
Packit Service |
5a9772 |
pDeviceObjectEx = (DEVICE_OBJECT_EX*)DeviceObject;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!pDeviceObjectEx)
|
|
Packit |
1fb8d4 |
return;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
unlink(pDeviceObjectEx->DeviceFileName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx->DeviceFileName);
|
|
Packit |
1fb8d4 |
free(pDeviceObjectEx);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#endif
|