示例#1
0
BOOL IsReparseDataSame(void *d1, void *d2)
{
	REPARSE_DATA_BUFFER *r1 = (REPARSE_DATA_BUFFER *)d1;
	REPARSE_DATA_BUFFER *r2 = (REPARSE_DATA_BUFFER *)d2;

	return	r1->ReparseTag        == r2->ReparseTag
		&&	r1->ReparseDataLength == r2->ReparseDataLength
		&&	!memcmp(&r1->GenericReparseBuffer, &r2->GenericReparseBuffer,
			r1->ReparseDataLength + (IsReparseTagMicrosoft(r1->ReparseTag) ? 0 : sizeof(GUID)));
}
示例#2
0
BOOL DeleteReparsePoint(HANDLE hFile, void *buf)
{
	REPARSE_DATA_BUFFER	rdbuf;
	DWORD	size = IsReparseTagMicrosoft(((REPARSE_DATA_BUFFER *)buf)->ReparseTag) ?
					REPARSE_DATA_BUFFER_HEADER_SIZE : REPARSE_GUID_DATA_BUFFER_HEADER_SIZE;

	memcpy(&rdbuf, buf, size);
	rdbuf.ReparseDataLength = 0;
	return	::DeviceIoControl(hFile, FSCTL_DELETE_REPARSE_POINT, &rdbuf, size, 0, 0, &size, NULL);
}
示例#3
0
arx_error arx_sys_follow(arx_utf8 const *path,
    arx_utf8 *buffer, arx_count count, arx_count *result)
{
    arx_error error = 0;
    arx_count length = 0;
#ifndef __WINDOWS__
    arx_mbcs *string = NULL;
    arx_mbcs *target = NULL;
    arx_mbcs stack[ARX_STRING_STACK];
#else
    BOOL ext = FALSE;
    DWORD total = 0;
    arx_wcs *string = NULL;
    arx_wcs *target = NULL;
    arx_wcs stack[ARX_STRING_STACK];
    DWORD const access = FILE_READ_EA;
    DWORD const disposition = OPEN_EXISTING;
    DWORD const share = (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE);
    DWORD const flags = (FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);
    HANDLE handle = INVALID_HANDLE_VALUE;
    LPREPARSE reparse = NULL;
#endif


    if ((path == NULL)
    ||  (*path == '\0')
    ||  ((buffer == NULL) && (count != 0))
    ||  ((buffer != NULL) && (count == 0)))
        return arx_argerror();


    if ((error = arx_path_export('?', path, stack, sizeof(stack), &length))) { goto cleanup; }
    if (length > sizeof(stack)) {
        if ((string = malloc(length * sizeof(stack[0]))) == NULL) {
            error = arx_memerror();
            goto cleanup;
        }
        if ((error = arx_path_export('?', path, string, length, &length))) { goto cleanup; }
    } else { string = stack; }


#ifndef __WINDOWS__
    if ((target = calloc((length = 1024), sizeof(arx_mbcs))) == NULL) {
        error = arx_memerror();
        goto cleanup;
    }
    while (1) {
        arx_count const xlength = length;
        arx_mbcs *const xtarget = target;

        length = (arx_count)readlink(string, target, length);
        if (length != (arx_count)-1) {
            if (length < xlength) { break; }
            length = (xlength * 2);
            target = realloc(target, (length * sizeof(arx_mbcs)));
            if (target == NULL) {
                error = arx_memerror();
                target = xtarget;
                goto cleanup;
            }
        } else {
            error = arx_unixerror(errno);
            goto cleanup;
        }
    }
    error = arx_path_mbimport('u', target, buffer, count, result);


#else
    handle = CreateFileW(string, access, share, NULL, disposition, flags, NULL);
    if (handle == INVALID_HANDLE_VALUE) {
        error = arx_winerror(GetLastError());
        goto cleanup;
    }
    if ((reparse = calloc(1, sizeof(REPARSE))) == NULL) {
        error = arx_winerror(GetLastError());
        goto cleanup;
    }
    if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT,
        NULL, 0, reparse, sizeof(REPARSE), &total, NULL)) {
        error = arx_winerror(GetLastError());
        goto cleanup;
    }
    if (!IsReparseTagMicrosoft(reparse->tag)) {
        error = arx_winerror(ERROR_INVALID_HANDLE);
        goto cleanup;
    }
    if ((reparse->tag != IO_REPARSE_TAG_SYMLINK)
    &&  (reparse->tag != IO_REPARSE_TAG_MOUNT_POINT)) {
        error = arx_winerror(ERROR_INVALID_HANDLE);
        goto cleanup;
    }
    if (reparse->tag == IO_REPARSE_TAG_SYMLINK) {
        arx_count const lengthgth = (reparse->symlink.target.lengthgth / sizeof(WCHAR));
        arx_count const offset = (reparse->symlink.target.offset / sizeof(WCHAR));
        arx_wcs const *const string = reparse->symlink.string;

        if ((target = calloc((lengthgth + 1), sizeof(arx_wcs))) == NULL) {
            error = arx_memerror();
            goto cleanup;
        }
        wcsncpy(target, (string + offset), lengthgth);
    } else if (reparse->tag == IO_REPARSE_TAG_MOUNT_POINT) {
        arx_count lengthgth = (reparse->junction.target.lengthgth / sizeof(WCHAR));
        arx_count offset = (reparse->junction.target.offset / sizeof(WCHAR));
        arx_wcs *string = reparse->junction.string;

        if ((target = calloc((lengthgth + 1), sizeof(arx_wcs))) == NULL) {
            error = arx_memerror();
            goto cleanup;
        }
        wcsncpy(target, (string + offset), lengthgth);
    } else {
        error = arx_winerror(ERROR_INVALID_HANDLE);
        goto cleanup;
    }
    ext = ((wcsncmp(target, L"\\??\\", 4) == 0) || (wcsncmp(target, L"\\\\?\\", 4) == 0));
    error = arx_path_wcimport('w', (target + (ext ? 4 : 0)), buffer, count, result);
#endif


cleanup:
#ifdef __WINDOWS__
    if (handle != INVALID_HANDLE_VALUE) { CloseHandle(handle); }
    free(reparse);
#endif
    free(target);
    if (string != stack) { free(string); }
    return error;
}
示例#4
0
文件: fsrtl.c 项目: GYGit/reactos
NTKERNELAPI
NTSTATUS
NTAPI
FsRtlValidateReparsePointBuffer(IN ULONG BufferLength,
                                IN PREPARSE_DATA_BUFFER ReparseBuffer)
{
    USHORT DataLength;
    ULONG ReparseTag;
    PREPARSE_GUID_DATA_BUFFER GuidBuffer;

    /* Validate data size range */
    if (BufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE || BufferLength > MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
    {
        return STATUS_IO_REPARSE_DATA_INVALID;
    }

    GuidBuffer = (PREPARSE_GUID_DATA_BUFFER)ReparseBuffer;
    DataLength = ReparseBuffer->ReparseDataLength;
    ReparseTag = ReparseBuffer->ReparseTag;

    /* Validate size consistency */
    if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE != BufferLength && DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE != BufferLength)
    {
        return STATUS_IO_REPARSE_DATA_INVALID;
    }

    /* REPARSE_DATA_BUFFER is reserved for MS tags */
    if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE == BufferLength && !IsReparseTagMicrosoft(ReparseTag))
    {
        return STATUS_IO_REPARSE_DATA_INVALID;
    }

    /* If that a GUID data buffer, its GUID cannot be null, and it cannot contain a MS tag */
    if (DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE == BufferLength && ((!IsReparseTagMicrosoft(ReparseTag)
        && IsNullGuid(&GuidBuffer->ReparseGuid)) || (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT || ReparseTag == IO_REPARSE_TAG_SYMLINK)))
    {
        return STATUS_IO_REPARSE_DATA_INVALID;
    }

    /* Check the data for MS non reserved tags */
    if (!(ReparseTag & 0xFFF0000) && ReparseTag != IO_REPARSE_TAG_RESERVED_ZERO && ReparseTag != IO_REPARSE_TAG_RESERVED_ONE)
    {
        /* If that's a mount point, validate the MountPointReparseBuffer branch */
        if (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
        {
            /* We need information */
            if (DataLength >= REPARSE_DATA_BUFFER_HEADER_SIZE)
            {
                /* Substitue must be the first in row */
                if (!ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset)
                {
                    /* Substitude must be null-terminated */
                    if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset == ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL))
                    {
                        /* There must just be the Offset/Length fields + buffer + 2 null chars */
                        if (DataLength == ReparseBuffer->MountPointReparseBuffer.PrintNameLength + ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + (FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.SubstituteNameOffset)) + 2 * sizeof(UNICODE_NULL))
                        {
                            return STATUS_SUCCESS;
                        }
                    }
                }
            }
        }
        else
        {
#define FIELDS_SIZE (FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset))

            /* If that's not a symlink, accept the MS tag as it */
            if (ReparseTag != IO_REPARSE_TAG_SYMLINK)
            {
                return STATUS_SUCCESS;
            }

            /* We need information */
            if (DataLength >= FIELDS_SIZE)
            {
                /* Validate lengths */
                if (ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength && ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength)
                {
                    /* Validate unicode strings */
                    if (IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength) &&
                        IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset) && IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset))
                    {
                        if ((DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE)
                            && (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >= ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength + ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + FIELDS_SIZE + REPARSE_DATA_BUFFER_HEADER_SIZE))
                        {
                            return STATUS_SUCCESS;
                        }
                    }
                }
            }
#undef FIELDS_SIZE
        }

        return STATUS_IO_REPARSE_DATA_INVALID;
    }

    return STATUS_IO_REPARSE_TAG_INVALID;
}
bool os_get_symlink_target(const std::string &lname, std::string &target)
{
	HANDLE hJunc=CreateFileW(ConvertToWchar(lname).c_str(), GENERIC_READ, FILE_SHARE_READ,
		NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_ATTRIBUTE_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);

	if(hJunc==INVALID_HANDLE_VALUE)
		return false;

	DWORD needed_buffer_size = 0;
	DWORD bytes_returned;
	std::string buffer;
	buffer.resize((std::max)((size_t)REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, (size_t)512));
	BOOL b = DeviceIoControl(hJunc, FSCTL_GET_REPARSE_POINT, NULL, 0, &buffer[0], static_cast<DWORD>(buffer.size()), &bytes_returned, NULL);
	if(!b)
	{
		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
			&& GetLastError() != ERROR_MORE_DATA)
		{
			CloseHandle(hJunc);
			return false;
		}
	}
	const REPARSE_DATA_BUFFER* reparse_buffer = reinterpret_cast<const REPARSE_DATA_BUFFER*>(buffer.data());

	if(!IsReparseTagMicrosoft(reparse_buffer->ReparseTag))
	{
		CloseHandle(hJunc);
		return false;
	}

	if(!b)
	{
		buffer.resize(reparse_buffer->ReparseDataLength+ REPARSE_GUID_DATA_BUFFER_HEADER_SIZE+10);
		reparse_buffer = reinterpret_cast<const REPARSE_DATA_BUFFER*>(buffer.data());
		b = DeviceIoControl(hJunc, FSCTL_GET_REPARSE_POINT, NULL, 0, &buffer[0], static_cast<DWORD>(buffer.size()), &bytes_returned, NULL);
		if(!b)
		{
			CloseHandle(hJunc);
			return false;
		}
	}

	CloseHandle(hJunc);

	bool ret=true;

	std::wstring wtarget;
	if(reparse_buffer->ReparseTag==IO_REPARSE_TAG_SYMLINK)
	{
		wtarget.resize(reparse_buffer->SymbolicLinkReparseBuffer.SubstituteNameLength/sizeof(wchar_t));
		memcpy(&wtarget[0],
			&reparse_buffer->SymbolicLinkReparseBuffer.PathBuffer[reparse_buffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(wchar_t)],
			reparse_buffer->SymbolicLinkReparseBuffer.SubstituteNameLength);
	}
	else if(reparse_buffer->ReparseTag==IO_REPARSE_TAG_MOUNT_POINT)
	{
		wtarget.resize(reparse_buffer->MountPointReparseBuffer.SubstituteNameLength/sizeof(wchar_t));
		memcpy(&wtarget[0],
			&reparse_buffer->MountPointReparseBuffer.PathBuffer[reparse_buffer->MountPointReparseBuffer.SubstituteNameOffset/sizeof(wchar_t)],
			reparse_buffer->MountPointReparseBuffer.SubstituteNameLength);
	}
	else
	{
		ret=false;
	}

	target = ConvertFromWchar(wtarget);

	if(next(target, 0, "\\??\\"))
		target.erase(0,4);

	return ret;
}