FreeRDP
device.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/io.h>
23 
24 #ifndef _WIN32
25 
26 #include "io.h"
27 
28 #include <stdio.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 
33 #ifdef WINPR_HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 
40 #include <winpr/crt.h>
41 #include <winpr/path.h>
42 #include <winpr/file.h>
43 
63 #define DEVICE_FILE_PREFIX_PATH "\\Device\\"
64 
65 static char* GetDeviceFileNameWithoutPrefixA(LPCSTR lpName)
66 {
67  char* lpFileName = NULL;
68 
69  if (!lpName)
70  return NULL;
71 
72  if (strncmp(lpName, DEVICE_FILE_PREFIX_PATH, sizeof(DEVICE_FILE_PREFIX_PATH) - 1) != 0)
73  return NULL;
74 
75  lpFileName =
76  _strdup(&lpName[strnlen(DEVICE_FILE_PREFIX_PATH, sizeof(DEVICE_FILE_PREFIX_PATH))]);
77  return lpFileName;
78 }
79 
80 static char* GetDeviceFileUnixDomainSocketBaseFilePathA(void)
81 {
82  char* lpTempPath = NULL;
83  char* lpPipePath = NULL;
84  lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
85 
86  if (!lpTempPath)
87  return NULL;
88 
89  lpPipePath = GetCombinedPath(lpTempPath, ".device");
90  free(lpTempPath);
91  return lpPipePath;
92 }
93 
94 static char* GetDeviceFileUnixDomainSocketFilePathA(LPCSTR lpName)
95 {
96  char* lpPipePath = NULL;
97  char* lpFileName = NULL;
98  char* lpFilePath = NULL;
99  lpPipePath = GetDeviceFileUnixDomainSocketBaseFilePathA();
100 
101  if (!lpPipePath)
102  return NULL;
103 
104  lpFileName = GetDeviceFileNameWithoutPrefixA(lpName);
105 
106  if (!lpFileName)
107  {
108  free(lpPipePath);
109  return NULL;
110  }
111 
112  lpFilePath = GetCombinedPath(lpPipePath, lpFileName);
113  free(lpPipePath);
114  free(lpFileName);
115  return lpFilePath;
116 }
117 
123 NTSTATUS _IoCreateDeviceEx(PDRIVER_OBJECT_EX DriverObject, ULONG DeviceExtensionSize,
124  PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType,
125  ULONG DeviceCharacteristics, BOOLEAN Exclusive,
126  PDEVICE_OBJECT_EX* DeviceObject)
127 {
128  int status = 0;
129  char* DeviceBasePath = NULL;
130  DEVICE_OBJECT_EX* pDeviceObjectEx = NULL;
131  DeviceBasePath = GetDeviceFileUnixDomainSocketBaseFilePathA();
132 
133  if (!DeviceBasePath)
134  return STATUS_NO_MEMORY;
135 
136  if (!winpr_PathFileExists(DeviceBasePath))
137  {
138  if (mkdir(DeviceBasePath, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
139  {
140  free(DeviceBasePath);
141  return STATUS_ACCESS_DENIED;
142  }
143  }
144 
145  free(DeviceBasePath);
146  pDeviceObjectEx = (DEVICE_OBJECT_EX*)calloc(1, sizeof(DEVICE_OBJECT_EX));
147 
148  if (!pDeviceObjectEx)
149  return STATUS_NO_MEMORY;
150 
151  pDeviceObjectEx->DeviceName =
152  ConvertWCharNToUtf8Alloc(DeviceName->Buffer, DeviceName->Length / sizeof(WCHAR), NULL);
153  if (!pDeviceObjectEx->DeviceName)
154  {
155  free(pDeviceObjectEx);
156  return STATUS_NO_MEMORY;
157  }
158 
159  pDeviceObjectEx->DeviceFileName =
160  GetDeviceFileUnixDomainSocketFilePathA(pDeviceObjectEx->DeviceName);
161 
162  if (!pDeviceObjectEx->DeviceFileName)
163  {
164  free(pDeviceObjectEx->DeviceName);
165  free(pDeviceObjectEx);
166  return STATUS_NO_MEMORY;
167  }
168 
169  if (winpr_PathFileExists(pDeviceObjectEx->DeviceFileName))
170  {
171  if (unlink(pDeviceObjectEx->DeviceFileName) == -1)
172  {
173  free(pDeviceObjectEx->DeviceName);
174  free(pDeviceObjectEx->DeviceFileName);
175  free(pDeviceObjectEx);
176  return STATUS_ACCESS_DENIED;
177  }
178  }
179 
180  status = mkfifo(pDeviceObjectEx->DeviceFileName, 0666);
181 
182  if (status != 0)
183  {
184  free(pDeviceObjectEx->DeviceName);
185  free(pDeviceObjectEx->DeviceFileName);
186  free(pDeviceObjectEx);
187 
188  switch (errno)
189  {
190  case EACCES:
191  return STATUS_ACCESS_DENIED;
192 
193  case EEXIST:
194  return STATUS_OBJECT_NAME_EXISTS;
195 
196  case ENAMETOOLONG:
197  return STATUS_NAME_TOO_LONG;
198 
199  case ENOENT:
200  case ENOTDIR:
201  return STATUS_NOT_A_DIRECTORY;
202 
203  case ENOSPC:
204  return STATUS_DISK_FULL;
205 
206  default:
207  return STATUS_INTERNAL_ERROR;
208  }
209  }
210 
211  *((ULONG_PTR*)(DeviceObject)) = (ULONG_PTR)pDeviceObjectEx;
212  return STATUS_SUCCESS;
213 }
214 
220 VOID _IoDeleteDeviceEx(PDEVICE_OBJECT_EX DeviceObject)
221 {
222  DEVICE_OBJECT_EX* pDeviceObjectEx = NULL;
223  pDeviceObjectEx = (DEVICE_OBJECT_EX*)DeviceObject;
224 
225  if (!pDeviceObjectEx)
226  return;
227 
228  unlink(pDeviceObjectEx->DeviceFileName);
229  free(pDeviceObjectEx->DeviceName);
230  free(pDeviceObjectEx->DeviceFileName);
231  free(pDeviceObjectEx);
232 }
233 
234 #endif