[PSDK]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / mntpoint.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/file/mntpoint.c
5 * PURPOSE: File volume mount point functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * Erik Bos, Alexandre Julliard :
8 * GetLogicalDriveStringsA,
9 * GetLogicalDriveStringsW, GetLogicalDrives
10 * UPDATE HISTORY:
11 * Created 01/11/98
12 */
13 //WINE copyright notice:
14 /*
15 * DOS drives handling functions
16 *
17 * Copyright 1993 Erik Bos
18 * Copyright 1996 Alexandre Julliard
19 */
20
21 #include <k32.h>
22 #define NDEBUG
23 #include <debug.h>
24 DEBUG_CHANNEL(kernel32file);
25
26 /**
27 * @name GetVolumeNameForVolumeMountPointW
28 * @implemented
29 *
30 * Return an unique volume name for a drive root or mount point.
31 *
32 * @param VolumeMountPoint
33 * Pointer to string that contains either root drive name or
34 * mount point name.
35 * @param VolumeName
36 * Pointer to buffer that is filled with resulting unique
37 * volume name on success.
38 * @param VolumeNameLength
39 * Size of VolumeName buffer in TCHARs.
40 *
41 * @return
42 * TRUE when the function succeeds and the VolumeName buffer is filled,
43 * FALSE otherwise.
44 */
45 BOOL
46 WINAPI
47 GetVolumeNameForVolumeMountPointW(IN LPCWSTR VolumeMountPoint,
48 OUT LPWSTR VolumeName,
49 IN DWORD VolumeNameLength)
50 {
51 UNICODE_STRING NtFileName;
52 OBJECT_ATTRIBUTES ObjectAttributes;
53 HANDLE FileHandle;
54 IO_STATUS_BLOCK Iosb;
55 ULONG BufferLength;
56 PMOUNTDEV_NAME MountDevName;
57 PMOUNTMGR_MOUNT_POINT MountPoint;
58 ULONG MountPointSize;
59 PMOUNTMGR_MOUNT_POINTS MountPoints;
60 ULONG Index;
61 PUCHAR SymbolicLinkName;
62 BOOL Result;
63 NTSTATUS Status;
64
65 if (!VolumeMountPoint || !VolumeMountPoint[0])
66 {
67 SetLastError(ERROR_PATH_NOT_FOUND);
68 return FALSE;
69 }
70
71 /*
72 * First step is to convert the passed volume mount point name to
73 * an NT acceptable name.
74 */
75
76 if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint, &NtFileName, NULL, NULL))
77 {
78 SetLastError(ERROR_PATH_NOT_FOUND);
79 return FALSE;
80 }
81
82 if (NtFileName.Length > sizeof(WCHAR) &&
83 NtFileName.Buffer[(NtFileName.Length / sizeof(WCHAR)) - 1] == '\\')
84 {
85 NtFileName.Length -= sizeof(WCHAR);
86 }
87
88 /*
89 * Query mount point device name which we will later use for determining
90 * the volume name.
91 */
92
93 InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
94 Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE,
95 &ObjectAttributes, &Iosb,
96 FILE_SHARE_READ | FILE_SHARE_WRITE,
97 FILE_SYNCHRONOUS_IO_NONALERT);
98 RtlFreeUnicodeString(&NtFileName);
99 if (!NT_SUCCESS(Status))
100 {
101 BaseSetLastNTError(Status);
102 return FALSE;
103 }
104
105 BufferLength = sizeof(MOUNTDEV_NAME) + 50 * sizeof(WCHAR);
106 do
107 {
108 MountDevName = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
109 if (MountDevName == NULL)
110 {
111 NtClose(FileHandle);
112 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
113 return FALSE;
114 }
115
116 Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
117 IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
118 NULL, 0, MountDevName, BufferLength);
119 if (!NT_SUCCESS(Status))
120 {
121 RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
122 if (Status == STATUS_BUFFER_OVERFLOW)
123 {
124 BufferLength = sizeof(MOUNTDEV_NAME) + MountDevName->NameLength;
125 continue;
126 }
127 else
128 {
129 NtClose(FileHandle);
130 BaseSetLastNTError(Status);
131 return FALSE;
132 }
133 }
134 }
135 while (!NT_SUCCESS(Status));
136
137 NtClose(FileHandle);
138
139 /*
140 * Get the mount point information from mount manager.
141 */
142
143 MountPointSize = MountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
144 MountPoint = RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize);
145 if (MountPoint == NULL)
146 {
147 RtlFreeHeap(GetProcessHeap(), 0, MountDevName);
148 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
149 return FALSE;
150 }
151 RtlZeroMemory(MountPoint, sizeof(MOUNTMGR_MOUNT_POINT));
152 MountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
153 MountPoint->DeviceNameLength = MountDevName->NameLength;
154 RtlCopyMemory(MountPoint + 1, MountDevName->Name, MountDevName->NameLength);
155 RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName);
156
157 RtlInitUnicodeString(&NtFileName, L"\\??\\MountPointManager");
158 InitializeObjectAttributes(&ObjectAttributes, &NtFileName, 0, NULL, NULL);
159 Status = NtOpenFile(&FileHandle, FILE_GENERIC_READ, &ObjectAttributes,
160 &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE,
161 FILE_SYNCHRONOUS_IO_NONALERT);
162 if (!NT_SUCCESS(Status))
163 {
164 BaseSetLastNTError(Status);
165 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
166 return FALSE;
167 }
168
169 BufferLength = sizeof(MOUNTMGR_MOUNT_POINTS);
170 do
171 {
172 MountPoints = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
173 if (MountPoints == NULL)
174 {
175 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
176 NtClose(FileHandle);
177 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
178 return FALSE;
179 }
180
181 Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb,
182 IOCTL_MOUNTMGR_QUERY_POINTS,
183 MountPoint, MountPointSize,
184 MountPoints, BufferLength);
185 if (!NT_SUCCESS(Status))
186 {
187 if (Status == STATUS_BUFFER_OVERFLOW)
188 {
189 BufferLength = MountPoints->Size;
190 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
191 continue;
192 }
193 else if (!NT_SUCCESS(Status))
194 {
195 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
196 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
197 NtClose(FileHandle);
198 BaseSetLastNTError(Status);
199 return FALSE;
200 }
201 }
202 }
203 while (!NT_SUCCESS(Status));
204
205 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint);
206 NtClose(FileHandle);
207
208 /*
209 * Now we've gathered info about all mount points mapped to our device, so
210 * select the correct one and copy it into the output buffer.
211 */
212
213 for (Index = 0; Index < MountPoints->NumberOfMountPoints; Index++)
214 {
215 MountPoint = MountPoints->MountPoints + Index;
216 SymbolicLinkName = (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset;
217
218 /*
219 * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
220 * (with the last slash being optional) style symbolic links.
221 */
222
223 if (MountPoint->SymbolicLinkNameLength == 48 * sizeof(WCHAR) ||
224 (MountPoint->SymbolicLinkNameLength == 49 * sizeof(WCHAR) &&
225 SymbolicLinkName[48] == L'\\'))
226 {
227 if (RtlCompareMemory(SymbolicLinkName, L"\\??\\Volume{",
228 11 * sizeof(WCHAR)) == 11 * sizeof(WCHAR) &&
229 SymbolicLinkName[19] == L'-' && SymbolicLinkName[24] == L'-' &&
230 SymbolicLinkName[29] == L'-' && SymbolicLinkName[34] == L'-' &&
231 SymbolicLinkName[47] == L'}')
232 {
233 if (VolumeNameLength >= MountPoint->SymbolicLinkNameLength / sizeof(WCHAR))
234 {
235 RtlCopyMemory(VolumeName,
236 (PUCHAR)MountPoints + MountPoint->SymbolicLinkNameOffset,
237 MountPoint->SymbolicLinkNameLength);
238 VolumeName[1] = L'\\';
239 Result = TRUE;
240 }
241 else
242 {
243 SetLastError(ERROR_FILENAME_EXCED_RANGE);
244 Result = FALSE;
245 }
246
247 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
248
249 return Result;
250 }
251 }
252 }
253
254 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints);
255 SetLastError(ERROR_INVALID_PARAMETER);
256
257 return FALSE;
258 }
259
260 /*
261 * @implemented (Wine 13 sep 2008)
262 */
263 BOOL
264 WINAPI
265 GetVolumeNameForVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint,
266 IN LPSTR lpszVolumeName,
267 IN DWORD cchBufferLength)
268 {
269 BOOL ret;
270 WCHAR volumeW[50], *pathW = NULL;
271 DWORD len = min( sizeof(volumeW) / sizeof(WCHAR), cchBufferLength );
272
273 TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint), lpszVolumeName, cchBufferLength);
274
275 if (!lpszVolumeMountPoint || !(pathW = FilenameA2W( lpszVolumeMountPoint, TRUE )))
276 return FALSE;
277
278 if ((ret = GetVolumeNameForVolumeMountPointW( pathW, volumeW, len )))
279 FilenameW2A_N( lpszVolumeName, len, volumeW, -1 );
280
281 RtlFreeHeap( RtlGetProcessHeap(), 0, pathW );
282 return ret;
283 }
284
285 /*
286 * @unimplemented
287 */
288 BOOL
289 WINAPI
290 SetVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint,
291 IN LPCWSTR lpszVolumeName)
292 {
293 STUB;
294 return 0;
295 }
296
297 /*
298 * @unimplemented
299 */
300 BOOL
301 WINAPI
302 SetVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint,
303 IN LPCSTR lpszVolumeName)
304 {
305 STUB;
306 return 0;
307 }
308
309 /*
310 * @unimplemented
311 */
312 BOOL
313 WINAPI
314 DeleteVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint)
315 {
316 STUB;
317 return 0;
318 }
319
320 /*
321 * @unimplemented
322 */
323 BOOL
324 WINAPI
325 DeleteVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint)
326 {
327 STUB;
328 return 0;
329 }
330
331 /*
332 * @unimplemented
333 */
334 HANDLE
335 WINAPI
336 FindFirstVolumeMountPointW(IN LPCWSTR lpszRootPathName,
337 IN LPWSTR lpszVolumeMountPoint,
338 IN DWORD cchBufferLength)
339 {
340 STUB;
341 return 0;
342 }
343
344 /*
345 * @unimplemented
346 */
347 HANDLE
348 WINAPI
349 FindFirstVolumeMountPointA(IN LPCSTR lpszRootPathName,
350 IN LPSTR lpszVolumeMountPoint,
351 IN DWORD cchBufferLength)
352 {
353 STUB;
354 return 0;
355 }
356
357 /*
358 * @unimplemented
359 */
360 BOOL
361 WINAPI
362 FindNextVolumeMountPointA(IN HANDLE hFindVolumeMountPoint,
363 IN LPSTR lpszVolumeMountPoint,
364 DWORD cchBufferLength)
365 {
366 STUB;
367 return 0;
368 }
369
370 /*
371 * @unimplemented
372 */
373 BOOL
374 WINAPI
375 FindNextVolumeMountPointW(IN HANDLE hFindVolumeMountPoint,
376 IN LPWSTR lpszVolumeMountPoint,
377 DWORD cchBufferLength)
378 {
379 STUB;
380 return 0;
381 }
382
383 /*
384 * @unimplemented
385 */
386 BOOL
387 WINAPI
388 FindVolumeMountPointClose(IN HANDLE hFindVolumeMountPoint)
389 {
390 STUB;
391 return 0;
392 }
393
394 /* EOF */