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 if (Status
== STATUS_BUFFER_OVERFLOW
)
123 BufferLength
= sizeof(MOUNTDEV_NAME
) + MountDevName
->NameLength
;
124 RtlFreeHeap(GetProcessHeap(), 0, MountDevName
);
129 RtlFreeHeap(GetProcessHeap(), 0, MountDevName
);
131 BaseSetLastNTError(Status
);
136 while (!NT_SUCCESS(Status
));
141 * Get the mount point information from mount manager.
144 MountPointSize
= MountDevName
->NameLength
+ sizeof(MOUNTMGR_MOUNT_POINT
);
145 MountPoint
= RtlAllocateHeap(GetProcessHeap(), 0, MountPointSize
);
146 if (MountPoint
== NULL
)
148 RtlFreeHeap(GetProcessHeap(), 0, MountDevName
);
149 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
152 RtlZeroMemory(MountPoint
, sizeof(MOUNTMGR_MOUNT_POINT
));
153 MountPoint
->DeviceNameOffset
= sizeof(MOUNTMGR_MOUNT_POINT
);
154 MountPoint
->DeviceNameLength
= MountDevName
->NameLength
;
155 RtlCopyMemory(MountPoint
+ 1, MountDevName
->Name
, MountDevName
->NameLength
);
156 RtlFreeHeap(RtlGetProcessHeap(), 0, MountDevName
);
158 RtlInitUnicodeString(&NtFileName
, L
"\\??\\MountPointManager");
159 InitializeObjectAttributes(&ObjectAttributes
, &NtFileName
, 0, NULL
, NULL
);
160 Status
= NtOpenFile(&FileHandle
, FILE_GENERIC_READ
, &ObjectAttributes
,
161 &Iosb
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
162 FILE_SYNCHRONOUS_IO_NONALERT
);
163 if (!NT_SUCCESS(Status
))
165 BaseSetLastNTError(Status
);
166 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
170 BufferLength
= sizeof(MOUNTMGR_MOUNT_POINTS
);
173 MountPoints
= RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength
);
174 if (MountPoints
== NULL
)
176 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
178 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
182 Status
= NtDeviceIoControlFile(FileHandle
, NULL
, NULL
, NULL
, &Iosb
,
183 IOCTL_MOUNTMGR_QUERY_POINTS
,
184 MountPoint
, MountPointSize
,
185 MountPoints
, BufferLength
);
186 if (!NT_SUCCESS(Status
))
188 if (Status
== STATUS_BUFFER_OVERFLOW
)
190 BufferLength
= MountPoints
->Size
;
191 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
194 else if (!NT_SUCCESS(Status
))
196 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
197 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
199 BaseSetLastNTError(Status
);
204 while (!NT_SUCCESS(Status
));
206 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoint
);
210 * Now we've gathered info about all mount points mapped to our device, so
211 * select the correct one and copy it into the output buffer.
214 for (Index
= 0; Index
< MountPoints
->NumberOfMountPoints
; Index
++)
216 MountPoint
= MountPoints
->MountPoints
+ Index
;
217 SymbolicLinkName
= (PUCHAR
)MountPoints
+ MountPoint
->SymbolicLinkNameOffset
;
220 * Check for "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\"
221 * (with the last slash being optional) style symbolic links.
224 if (MountPoint
->SymbolicLinkNameLength
== 48 * sizeof(WCHAR
) ||
225 (MountPoint
->SymbolicLinkNameLength
== 49 * sizeof(WCHAR
) &&
226 SymbolicLinkName
[48] == L
'\\'))
228 if (RtlCompareMemory(SymbolicLinkName
, L
"\\??\\Volume{",
229 11 * sizeof(WCHAR
)) == 11 * sizeof(WCHAR
) &&
230 SymbolicLinkName
[19] == L
'-' && SymbolicLinkName
[24] == L
'-' &&
231 SymbolicLinkName
[29] == L
'-' && SymbolicLinkName
[34] == L
'-' &&
232 SymbolicLinkName
[47] == L
'}')
234 if (VolumeNameLength
>= MountPoint
->SymbolicLinkNameLength
/ sizeof(WCHAR
))
236 RtlCopyMemory(VolumeName
,
237 (PUCHAR
)MountPoints
+ MountPoint
->SymbolicLinkNameOffset
,
238 MountPoint
->SymbolicLinkNameLength
);
239 VolumeName
[1] = L
'\\';
244 SetLastError(ERROR_FILENAME_EXCED_RANGE
);
248 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
255 RtlFreeHeap(RtlGetProcessHeap(), 0, MountPoints
);
256 SetLastError(ERROR_INVALID_PARAMETER
);
262 * @implemented (Wine 13 sep 2008)
266 GetVolumeNameForVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
,
267 IN LPSTR lpszVolumeName
,
268 IN DWORD cchBufferLength
)
271 WCHAR volumeW
[50], *pathW
= NULL
;
272 DWORD len
= min( sizeof(volumeW
) / sizeof(WCHAR
), cchBufferLength
);
274 TRACE("(%s, %p, %x)\n", debugstr_a(lpszVolumeMountPoint
), lpszVolumeName
, cchBufferLength
);
276 if (!lpszVolumeMountPoint
|| !(pathW
= FilenameA2W( lpszVolumeMountPoint
, TRUE
)))
279 if ((ret
= GetVolumeNameForVolumeMountPointW( pathW
, volumeW
, len
)))
280 FilenameW2A_N( lpszVolumeName
, len
, volumeW
, -1 );
282 RtlFreeHeap( RtlGetProcessHeap(), 0, pathW
);
291 SetVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint
,
292 IN LPCWSTR lpszVolumeName
)
303 SetVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
,
304 IN LPCSTR lpszVolumeName
)
315 DeleteVolumeMountPointA(IN LPCSTR lpszVolumeMountPoint
)
326 DeleteVolumeMountPointW(IN LPCWSTR lpszVolumeMountPoint
)
337 FindFirstVolumeMountPointW(IN LPCWSTR lpszRootPathName
,
338 IN LPWSTR lpszVolumeMountPoint
,
339 IN DWORD cchBufferLength
)
350 FindFirstVolumeMountPointA(IN LPCSTR lpszRootPathName
,
351 IN LPSTR lpszVolumeMountPoint
,
352 IN DWORD cchBufferLength
)
363 FindNextVolumeMountPointA(IN HANDLE hFindVolumeMountPoint
,
364 IN LPSTR lpszVolumeMountPoint
,
365 DWORD cchBufferLength
)
376 FindNextVolumeMountPointW(IN HANDLE hFindVolumeMountPoint
,
377 IN LPWSTR lpszVolumeMountPoint
,
378 DWORD cchBufferLength
)
389 FindVolumeMountPointClose(IN HANDLE hFindVolumeMountPoint
)