Коммит 92bc7bda создал по автору Pierre Schweitzer's avatar Pierre Schweitzer
Просмотр файлов

[KERNEL32]

- Move InternalOpenDirW() to disk.c; that's the last place where it's used
- Implement GetVolumePathNamesForVolumeNameA(); its -W implementation is still to be implemented
- W2K3ify SetVolumeLabelW() and SetVolumeLabelA() 

svn path=/trunk/; revision=75978
владелец 4bce7ced
...@@ -26,7 +26,53 @@ ...@@ -26,7 +26,53 @@
DEBUG_CHANNEL(kernel32file); DEBUG_CHANNEL(kernel32file);
#define MAX_DOS_DRIVES 26 #define MAX_DOS_DRIVES 26
HANDLE WINAPI InternalOpenDirW(IN LPCWSTR DirName, IN BOOLEAN Write);
HANDLE
WINAPI
InternalOpenDirW(IN LPCWSTR DirName,
IN BOOLEAN Write)
{
UNICODE_STRING NtPathU;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hFile;
if (!RtlDosPathNameToNtPathName_U(DirName, &NtPathU, NULL, NULL))
{
WARN("Invalid path\n");
SetLastError(ERROR_BAD_PATHNAME);
return INVALID_HANDLE_VALUE;
}
InitializeObjectAttributes(&ObjectAttributes,
&NtPathU,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
errCode = NtCreateFile(&hFile,
Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0);
RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
if (!NT_SUCCESS(errCode))
{
BaseSetLastNTError(errCode);
return INVALID_HANDLE_VALUE;
}
return hFile;
}
/* /*
* @implemented * @implemented
......
...@@ -22,54 +22,7 @@ ...@@ -22,54 +22,7 @@
#include <k32.h> #include <k32.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
DEBUG_CHANNEL(kernel32file);
HANDLE
WINAPI
InternalOpenDirW(IN LPCWSTR DirName,
IN BOOLEAN Write)
{
UNICODE_STRING NtPathU;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE hFile;
if (!RtlDosPathNameToNtPathName_U(DirName, &NtPathU, NULL, NULL))
{
WARN("Invalid path\n");
SetLastError(ERROR_BAD_PATHNAME);
return INVALID_HANDLE_VALUE;
}
InitializeObjectAttributes(&ObjectAttributes,
&NtPathU,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
errCode = NtCreateFile(&hFile,
Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
&ObjectAttributes,
&IoStatusBlock,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
0,
NULL,
0);
RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
if (!NT_SUCCESS(errCode))
{
BaseSetLastNTError(errCode);
return INVALID_HANDLE_VALUE;
}
return hFile;
}
/* /*
* @implemented * @implemented
...@@ -506,30 +459,36 @@ WINAPI ...@@ -506,30 +459,36 @@ WINAPI
SetVolumeLabelA(IN LPCSTR lpRootPathName, SetVolumeLabelA(IN LPCSTR lpRootPathName,
IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */ IN LPCSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
{ {
PWCHAR RootPathNameW; BOOL Ret;
PWCHAR VolumeNameW = NULL; UNICODE_STRING VolumeNameU;
BOOL Result; PUNICODE_STRING RootPathNameU;
if (!(RootPathNameW = FilenameA2W(lpRootPathName, FALSE))) if (lpRootPathName == NULL)
return FALSE; {
lpRootPathName = "\\";
if (lpVolumeName) }
{
if (!(VolumeNameW = FilenameA2W(lpVolumeName, TRUE))) RootPathNameU = Basep8BitStringToStaticUnicodeString(lpRootPathName);
return FALSE; if (RootPathNameU == NULL)
} {
return FALSE;
Result = SetVolumeLabelW (RootPathNameW, }
VolumeNameW);
if (lpVolumeName != NULL)
if (VolumeNameW) {
{ if (!Basep8BitStringToDynamicUnicodeString(&VolumeNameU, lpVolumeName))
RtlFreeHeap (RtlGetProcessHeap (), {
0, return FALSE;
VolumeNameW ); }
} }
else
return Result; {
VolumeNameU.Buffer = NULL;
}
Ret = SetVolumeLabelW(RootPathNameU->Buffer, VolumeNameU.Buffer);
RtlFreeUnicodeString(&VolumeNameU);
return Ret;
} }
/* /*
...@@ -540,57 +499,153 @@ WINAPI ...@@ -540,57 +499,153 @@ WINAPI
SetVolumeLabelW(IN LPCWSTR lpRootPathName, SetVolumeLabelW(IN LPCWSTR lpRootPathName,
IN LPCWSTR lpVolumeName OPTIONAL) /* NULL if deleting label */ IN LPCWSTR lpVolumeName OPTIONAL) /* NULL if deleting label */
{ {
PFILE_FS_LABEL_INFORMATION LabelInfo; BOOL Ret;
IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status;
ULONG LabelLength; PWSTR VolumeRoot;
HANDLE hFile; HANDLE VolumeHandle;
NTSTATUS Status; WCHAR VolumeGuid[MAX_PATH];
IO_STATUS_BLOCK IoStatusBlock;
LabelLength = wcslen(lpVolumeName) * sizeof(WCHAR); OBJECT_ATTRIBUTES ObjectAttributes;
LabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), PFILE_FS_LABEL_INFORMATION FsLabelInfo;
0, UNICODE_STRING VolumeName, NtVolumeName;
sizeof(FILE_FS_LABEL_INFORMATION) +
LabelLength); /* If no root path provided, default to \ */
if (LabelInfo == NULL) VolumeRoot = L"\\";
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* If user wants to set a label, make it a string */
return FALSE; if (lpVolumeName != NULL)
} {
LabelInfo->VolumeLabelLength = LabelLength; RtlInitUnicodeString(&VolumeName, lpVolumeName);
memcpy(LabelInfo->VolumeLabel, }
lpVolumeName, else
LabelLength); {
VolumeName.Length = 0;
hFile = InternalOpenDirW(lpRootPathName, TRUE); VolumeName.MaximumLength = 0;
if (INVALID_HANDLE_VALUE == hFile) VolumeName.Buffer = NULL;
{ }
RtlFreeHeap(RtlGetProcessHeap(),
0, /* If we received a volume, try to get its GUID name */
LabelInfo); if (lpRootPathName != NULL)
{
Ret = GetVolumeNameForVolumeMountPointW(lpRootPathName, VolumeGuid, MAX_PATH);
}
else
{
Ret = FALSE;
}
/* If we got the GUID name, use it */
if (Ret)
{
VolumeRoot = VolumeGuid;
}
else
{
/* Otherwise, use the name provided by the caller */
if (lpRootPathName != NULL)
{
VolumeRoot = (PWSTR)lpRootPathName;
}
}
/* Convert to a NT path */
if (!RtlDosPathNameToNtPathName_U(VolumeRoot, &NtVolumeName, NULL, NULL))
{
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
/* Check we really end with a backslash */
if (NtVolumeName.Buffer[(NtVolumeName.Length / sizeof(WCHAR)) - 1] != L'\\')
{
RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
BaseSetLastNTError(STATUS_OBJECT_NAME_INVALID);
return FALSE;
}
/* Try to open the root directory */
InitializeObjectAttributes(&ObjectAttributes, &NtVolumeName,
OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | FILE_WRITE_DATA,
&ObjectAttributes, &IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
BaseSetLastNTError(Status);
return FALSE;
}
/* Validate it's really a root path */
if (!IsThisARootDirectory(VolumeHandle, NULL))
{
RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
NtClose(VolumeHandle);
SetLastError(ERROR_DIR_NOT_ROOT);
return FALSE; return FALSE;
} }
Status = NtSetVolumeInformationFile(hFile, /* Done */
&IoStatusBlock, NtClose(VolumeHandle);
LabelInfo,
sizeof(FILE_FS_LABEL_INFORMATION) + /* Now, open the volume to perform the label change */
LabelLength, NtVolumeName.Length -= sizeof(WCHAR);
FileFsLabelInformation); InitializeObjectAttributes(&ObjectAttributes, &NtVolumeName,
OBJ_CASE_INSENSITIVE, NULL, NULL);
RtlFreeHeap(RtlGetProcessHeap(),
0, Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | FILE_WRITE_DATA,
LabelInfo); &ObjectAttributes, &IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
if (!NT_SUCCESS(Status)) FILE_SYNCHRONOUS_IO_NONALERT);
{
WARN("Status: %x\n", Status); RtlFreeHeap(RtlGetProcessHeap(), 0, NtVolumeName.Buffer);
CloseHandle(hFile);
BaseSetLastNTError(Status); if (!NT_SUCCESS(Status))
return FALSE; {
} BaseSetLastNTError(Status);
return FALSE;
CloseHandle(hFile); }
return TRUE;
/* Assume success */
Ret = TRUE;
/* Allocate a buffer that can hold new label and its size */
FsLabelInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(FILE_FS_LABEL_INFORMATION) + VolumeName.Length);
if (FsLabelInfo != NULL)
{
/* Copy name and set its size */
RtlCopyMemory(FsLabelInfo->VolumeLabel, VolumeName.Buffer, VolumeName.Length);
FsLabelInfo->VolumeLabelLength = VolumeName.Length;
/* And finally, set new label */
Status = NtSetVolumeInformationFile(VolumeHandle, &IoStatusBlock, FsLabelInfo, sizeof(FILE_FS_LABEL_INFORMATION) + VolumeName.Length, FileFsLabelInformation);
}
else
{
/* Allocation failed */
Status = STATUS_NO_MEMORY;
}
/* In case of failure, set status and mark failure */
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
Ret = FALSE;
}
/* We're done */
NtClose(VolumeHandle);
/* Free buffer if required */
if (FsLabelInfo != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, FsLabelInfo);
}
return Ret;
} }
/* /*
...@@ -891,7 +946,7 @@ FindNextVolumeW(IN HANDLE handle, ...@@ -891,7 +946,7 @@ FindNextVolumeW(IN HANDLE handle,
} }
/* /*
* @unimplemented * @implemented
*/ */
BOOL BOOL
WINAPI WINAPI
...@@ -900,8 +955,103 @@ GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName, ...@@ -900,8 +955,103 @@ GetVolumePathNamesForVolumeNameA(IN LPCSTR lpszVolumeName,
IN DWORD cchBufferLength, IN DWORD cchBufferLength,
OUT PDWORD lpcchReturnLength) OUT PDWORD lpcchReturnLength)
{ {
STUB; BOOL Ret;
return 0; NTSTATUS Status;
DWORD cchReturnLength;
ANSI_STRING VolumePathName;
PUNICODE_STRING VolumeNameU;
UNICODE_STRING VolumePathNamesU;
/* Convert volume name to unicode */
VolumeNameU = Basep8BitStringToStaticUnicodeString(lpszVolumeName);
if (VolumeNameU == NULL)
{
return FALSE;
}
/* Initialize the strings we'll use later on */
VolumePathName.Length = 0;
VolumePathName.MaximumLength = cchBufferLength;
VolumePathName.Buffer = lpszVolumePathNames;
VolumePathNamesU.Length = 0;
VolumePathNamesU.MaximumLength = sizeof(WCHAR) * cchBufferLength;
/* If caller provided a non 0 sized string, allocate a buffer for our unicode string */
if (VolumePathNamesU.MaximumLength != 0)
{
VolumePathNamesU.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.MaximumLength);
if (VolumePathNamesU.Buffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
else
{
VolumePathNamesU.Buffer = NULL;
}
/* Call the -W implementation */
Ret = GetVolumePathNamesForVolumeNameW(VolumeNameU->Buffer, VolumePathNamesU.Buffer,
cchBufferLength, &cchReturnLength);
/* Call succeed, we'll return the total length */
if (Ret)
{
VolumePathNamesU.Length = sizeof(WCHAR) * cchReturnLength;
}
else
{
/* Else, if we fail for anything else than too small buffer, quit */
if (GetLastError() != ERROR_MORE_DATA)
{
if (VolumePathNamesU.Buffer != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
}
return FALSE;
}
/* Otherwise, we'll just copy as much as we can */
VolumePathNamesU.Length = sizeof(WCHAR) * cchBufferLength;
}
/* Convert our output string back to ANSI */
Status = RtlUnicodeStringToAnsiString(&VolumePathName, &VolumePathNamesU, FALSE);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
if (VolumePathNamesU.Buffer != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
}
return FALSE;
}
/* If caller wants return length, two cases... */
if (lpcchReturnLength != NULL)
{
/* We succeed: return the copied length */
if (Ret)
{
*lpcchReturnLength = VolumePathName.Length;
}
/* We failed, return the size we would have loved having! */
else
{
*lpcchReturnLength = sizeof(WCHAR) * cchReturnLength;
}
}
/* Release our buffer if allocated */
if (VolumePathNamesU.Buffer != NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, VolumePathNamesU.Buffer);
}
return Ret;
} }
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать