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
13 //WINE copyright notice:
15 * DOS drives handling functions
17 * Copyright 1993 Erik Bos
18 * Copyright 1996 Alexandre Julliard
24 DEBUG_CHANNEL(kernel32file
);
27 * @name GetVolumeNameForVolumeMountPointW
30 * Return an unique volume name for a drive root or mount point.
32 * @param VolumeMountPoint
33 * Pointer to string that contains either root drive name or
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.
42 * TRUE when the function succeeds and the VolumeName buffer is filled,
47 GetVolumeNameForVolumeMountPointW(IN LPCWSTR VolumeMountPoint
,
48 OUT LPWSTR VolumeName
,
49 IN DWORD VolumeNameLength
)
51 UNICODE_STRING NtFileName
;
52 OBJECT_ATTRIBUTES ObjectAttributes
;
56 PMOUNTDEV_NAME MountDevName
;
57 PMOUNTMGR_MOUNT_POINT MountPoint
;
59 PMOUNTMGR_MOUNT_POINTS MountPoints
;
61 PUCHAR SymbolicLinkName
;
65 if (!VolumeMountPoint
|| !VolumeMountPoint
[0])
67 SetLastError(ERROR_PATH_NOT_FOUND
);
72 * First step is to convert the passed volume mount point name to
73 * an NT acceptable name.
76 if (!RtlDosPathNameToNtPathName_U(VolumeMountPoint
, &NtFileName
, NULL
, NULL
))
78 SetLastError(ERROR_PATH_NOT_FOUND
);
82 if (NtFileName
.Length
> sizeof(WCHAR
) &&
83 NtFileName
.Buffer
[(NtFileName
.Length
/ sizeof(WCHAR
)) - 1] == '\\')
85 NtFileName
.Length
-= sizeof(WCHAR
);
89 * Query mount point device name which we will later use for determining
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
))
101 BaseSetLastNTError(Status
);
105 BufferLength
= sizeof(MOUNTDEV_NAME
) + 50 * sizeof(WCHAR
);
108 MountDevName
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
109 if (MountDevName
== NULL
)
112 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
116 Status
= NtDeviceIoControlFile(FileHandle
, NULL
, NULL
, NULL
, &Iosb
,
117 IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
,
118 NULL
, 0, MountDevName
, BufferLength
);
119 if (!NT_SUCCESS(Status
))
121 RtlFreeHeap(GetProcessHeap(), 0, MountDevName
);
122 if (Status
== STATUS_BUFFER_OVERFLOW
)
124 BufferLength
= sizeof(MOUNTDEV_NAME
) + MountDevName
->NameLength
;
130 BaseSetLastNTError(Status
);
135 while (!NT_SUCCESS(Status
));
140 * Get the mount point information from mount manager.
143 MountPointSize
= MountDevName
->NameLength
+ sizeof(MOUNTMGR_MOUNT_POINT
);
144 MountPoint
= RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize
);
145 if (MountPoint
== NULL
)
147 RtlFreeHeap(GetProcessHeap(), 0, MountDevName
);
148 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
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
);
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
))
164 BaseSetLastNTError(Status
);
165 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
169 BufferLength
= sizeof(MOUNTMGR_MOUNT_POINTS
);
172 MountPoints
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
173 if (MountPoints
== NULL
)
175 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
177 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
181 Status
= NtDeviceIoControlFile(FileHandle
, NULL
, NULL
, NULL
, &Iosb
,
182 IOCTL_MOUNTMGR_QUERY_POINTS
,
183 MountPoint
, MountPointSize
,
184 MountPoints
, BufferLength
);
185 if (!NT_SUCCESS(Status
))
187 if (Status
== STATUS_BUFFER_OVERFLOW
)
189 BufferLength
= MountPoints
->Size
;
190 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
193 else if (!NT_SUCCESS(Status
))
195 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
196 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
198 BaseSetLastNTError(Status
);
203 while (!NT_SUCCESS(Status
));
205 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
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.
213 for (Index
= 0; Index
< MountPoints
->NumberOfMountPoints
; Index
++)
215 MountPoint
= MountPoints
->MountPoints
+ Index
;
216 SymbolicLinkName
= (PUCHAR
)MountPoints
+ MountPoint
->SymbolicLinkNameOffset
;
219 * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
220 * (with the last slash being optional) style symbolic links.
223 if (MountPoint
->SymbolicLinkNameLength
== 48 * sizeof(WCHAR
) ||
224 (MountPoint
->SymbolicLinkNameLength
== 49 * sizeof(WCHAR
) &&
225 SymbolicLinkName
[48] == L
'\\'))
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
'}')
233 if (VolumeNameLength
>= MountPoint
->SymbolicLinkNameLength
/ sizeof(WCHAR
))
235 RtlCopyMemory(VolumeName
,
236 (PUCHAR
)MountPoints
+ MountPoint
->SymbolicLinkNameOffset
,
237 MountPoint
->SymbolicLinkNameLength
);
238 VolumeName
[1] = L
'\\';
243 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
247 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
254 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
255 SetLastError(ERROR_INVALID_PARAMETER
);
261 * @implemented (Wine 13 sep 2008)
265 GetVolumeNameForVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
,
266 IN LPSTR lpszVolumeName
,
267 IN DWORD cchBufferLength
)
270 WCHAR volumeW
[50], *pathW
= NULL
;
271 DWORD len
= min( sizeof(volumeW
) / sizeof(WCHAR
), cchBufferLength
);
273 TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint
), lpszVolumeName
, cchBufferLength
);
275 if (!lpszVolumeMountPoint
|| !(pathW
= FilenameA2W( lpszVolumeMountPoint
, TRUE
)))
278 if ((ret
= GetVolumeNameForVolumeMountPointW( pathW
, volumeW
, len
)))
279 FilenameW2A_N( lpszVolumeName
, len
, volumeW
, -1 );
281 RtlFreeHeap( RtlGetProcessHeap(), 0, pathW
);
290 SetVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint
,
291 IN LPCWSTR lpszVolumeName
)
302 SetVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
,
303 IN LPCSTR lpszVolumeName
)
314 DeleteVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
)
325 DeleteVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint
)
336 FindFirstVolumeMountPointW(IN LPCWSTR lpszRootPathName
,
337 IN LPWSTR lpszVolumeMountPoint
,
338 IN DWORD cchBufferLength
)
349 FindFirstVolumeMountPointA(IN LPCSTR lpszRootPathName
,
350 IN LPSTR lpszVolumeMountPoint
,
351 IN DWORD cchBufferLength
)
362 FindNextVolumeMountPointA(IN HANDLE hFindVolumeMountPoint
,
363 IN LPSTR lpszVolumeMountPoint
,
364 DWORD cchBufferLength
)
375 FindNextVolumeMountPointW(IN HANDLE hFindVolumeMountPoint
,
376 IN LPWSTR lpszVolumeMountPoint
,
377 DWORD cchBufferLength
)
388 FindVolumeMountPointClose(IN HANDLE hFindVolumeMountPoint
)