0b2c738975b364a61e573387b56359586429777dvboxsync/* $Id$ */
0b2c738975b364a61e573387b56359586429777dvboxsync/** @file
0b2c738975b364a61e573387b56359586429777dvboxsync * IPRT - Directory Enumeration, Windows.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync/*
0b2c738975b364a61e573387b56359586429777dvboxsync * Copyright (C) 2006-2013 Oracle Corporation
0b2c738975b364a61e573387b56359586429777dvboxsync *
0b2c738975b364a61e573387b56359586429777dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b2c738975b364a61e573387b56359586429777dvboxsync * available from http://www.virtualbox.org. This file is free software;
0b2c738975b364a61e573387b56359586429777dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b2c738975b364a61e573387b56359586429777dvboxsync * General Public License (GPL) as published by the Free Software
0b2c738975b364a61e573387b56359586429777dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0b2c738975b364a61e573387b56359586429777dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0b2c738975b364a61e573387b56359586429777dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0b2c738975b364a61e573387b56359586429777dvboxsync *
0b2c738975b364a61e573387b56359586429777dvboxsync * The contents of this file may alternatively be used under the terms
0b2c738975b364a61e573387b56359586429777dvboxsync * of the Common Development and Distribution License Version 1.0
0b2c738975b364a61e573387b56359586429777dvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0b2c738975b364a61e573387b56359586429777dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
0b2c738975b364a61e573387b56359586429777dvboxsync * CDDL are applicable instead of those of the GPL.
0b2c738975b364a61e573387b56359586429777dvboxsync *
0b2c738975b364a61e573387b56359586429777dvboxsync * You may elect to license modified versions of this file under the
0b2c738975b364a61e573387b56359586429777dvboxsync * terms and conditions of either the GPL or the CDDL or both.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync/*******************************************************************************
0b2c738975b364a61e573387b56359586429777dvboxsync* Header Files *
0b2c738975b364a61e573387b56359586429777dvboxsync*******************************************************************************/
0b2c738975b364a61e573387b56359586429777dvboxsync#define LOG_GROUP RTLOGGROUP_DIR
0b2c738975b364a61e573387b56359586429777dvboxsync#include <Windows.h>
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/dir.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/path.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/mem.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/string.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/assert.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/err.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/file.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include <iprt/log.h>
0b2c738975b364a61e573387b56359586429777dvboxsync#include "internal/fs.h"
0b2c738975b364a61e573387b56359586429777dvboxsync#include "internal/dir.h"
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsyncsize_t rtDirNativeGetStructSize(const char *pszPath)
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync{
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync NOREF(pszPath);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync return sizeof(RTDIR);
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync}
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsyncint rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
0b2c738975b364a61e573387b56359586429777dvboxsync{
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Setup the search expression.
0b2c738975b364a61e573387b56359586429777dvboxsync *
0b2c738975b364a61e573387b56359586429777dvboxsync * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
0b2c738975b364a61e573387b56359586429777dvboxsync * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
0b2c738975b364a61e573387b56359586429777dvboxsync * it when adding the wildcard expression.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync size_t cbExpr;
0b2c738975b364a61e573387b56359586429777dvboxsync const char *pszExpr;
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->enmFilter == RTDIRFILTER_WINNT)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync pszExpr = pDir->pszFilter;
0b2c738975b364a61e573387b56359586429777dvboxsync cbExpr = pDir->cchFilter + 1;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync else
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync pszExpr = "*";
0b2c738975b364a61e573387b56359586429777dvboxsync cbExpr = sizeof("*");
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->cchPath + cbExpr > RTPATH_MAX)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_FILENAME_TOO_LONG;
0b2c738975b364a61e573387b56359586429777dvboxsync memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr);
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Attempt opening the search.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync int rc = VINF_SUCCESS;
0b2c738975b364a61e573387b56359586429777dvboxsync PRTUTF16 pwszName;
0b2c738975b364a61e573387b56359586429777dvboxsync rc = RTStrToUtf16(pszPathBuf, &pwszName);
0b2c738975b364a61e573387b56359586429777dvboxsync if (RT_SUCCESS(rc))
0b2c738975b364a61e573387b56359586429777dvboxsync {
6f82db701c69ae6925eb7e8bf1dfe25c9f951bddvboxsync pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->hDir != INVALID_HANDLE_VALUE)
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->fDataUnread = true;
0b2c738975b364a61e573387b56359586429777dvboxsync else
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync DWORD dwErr = GetLastError();
0b2c738975b364a61e573387b56359586429777dvboxsync /* Theoretical case of an empty directory or more normal case of no matches. */
0b2c738975b364a61e573387b56359586429777dvboxsync if ( dwErr == ERROR_FILE_NOT_FOUND
0b2c738975b364a61e573387b56359586429777dvboxsync || dwErr == ERROR_NO_MORE_FILES /* ???*/)
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->fDataUnread = false;
0b2c738975b364a61e573387b56359586429777dvboxsync else
0b2c738975b364a61e573387b56359586429777dvboxsync rc = RTErrConvertFromWin32(GetLastError());
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync RTUtf16Free(pwszName);
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync return rc;
0b2c738975b364a61e573387b56359586429777dvboxsync}
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsyncRTDECL(int) RTDirClose(PRTDIR pDir)
0b2c738975b364a61e573387b56359586429777dvboxsync{
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Validate input.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->u32Magic != RTDIR_MAGIC)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid pDir=%p\n", pDir));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Close the handle.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->u32Magic++;
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->hDir != INVALID_HANDLE_VALUE)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync BOOL fRc = FindClose(pDir->hDir);
0b2c738975b364a61e573387b56359586429777dvboxsync Assert(fRc);
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->hDir = INVALID_HANDLE_VALUE;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync RTStrFree(pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->pszName = NULL;
0b2c738975b364a61e573387b56359586429777dvboxsync RTMemFree(pDir);
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync return VINF_SUCCESS;
0b2c738975b364a61e573387b56359586429777dvboxsync}
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsyncRTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync{
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Validate input.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid pDir=%p\n", pDir));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync size_t cbDirEntry = sizeof(*pDirEntry);
0b2c738975b364a61e573387b56359586429777dvboxsync if (pcbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync cbDirEntry = *pcbDirEntry;
0b2c738975b364a61e573387b56359586429777dvboxsync if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Fetch data?
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir->fDataUnread)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync RTStrFree(pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->pszName = NULL;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
0b2c738975b364a61e573387b56359586429777dvboxsync if (!fRc)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync int iErr = GetLastError();
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_NO_MORE_FILES;
0b2c738975b364a61e573387b56359586429777dvboxsync return RTErrConvertFromWin32(iErr);
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Convert the filename to UTF-8.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir->pszName)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync if (RT_FAILURE(rc))
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->pszName = NULL;
0b2c738975b364a61e573387b56359586429777dvboxsync return rc;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->cchName = strlen(pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Check if we've got enough space to return the data.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync const char *pszName = pDir->pszName;
0b2c738975b364a61e573387b56359586429777dvboxsync const size_t cchName = pDir->cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync if (pcbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync *pcbDirEntry = cbRequired;
0b2c738975b364a61e573387b56359586429777dvboxsync if (cbRequired > cbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_BUFFER_OVERFLOW;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Setup the returned data.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->fDataUnread = false;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
0b2c738975b364a61e573387b56359586429777dvboxsync ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->cbName = (uint16_t)cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync Assert(pDirEntry->cbName == cchName);
0b2c738975b364a61e573387b56359586429777dvboxsync memcpy(pDirEntry->szName, pszName, cchName + 1);
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync return VINF_SUCCESS;
0b2c738975b364a61e573387b56359586429777dvboxsync}
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsyncRTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
0b2c738975b364a61e573387b56359586429777dvboxsync{
0b2c738975b364a61e573387b56359586429777dvboxsync /** @todo Symlinks: Find[First|Next]FileW will return info about
0b2c738975b364a61e573387b56359586429777dvboxsync the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Validate input.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid pDir=%p\n", pDir));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
0b2c738975b364a61e573387b56359586429777dvboxsync || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
0b2c738975b364a61e573387b56359586429777dvboxsync size_t cbDirEntry = sizeof(*pDirEntry);
0b2c738975b364a61e573387b56359586429777dvboxsync if (pcbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync cbDirEntry = *pcbDirEntry;
0b2c738975b364a61e573387b56359586429777dvboxsync if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INVALID_PARAMETER;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Fetch data?
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir->fDataUnread)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync RTStrFree(pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->pszName = NULL;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
0b2c738975b364a61e573387b56359586429777dvboxsync if (!fRc)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync int iErr = GetLastError();
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_NO_MORE_FILES;
0b2c738975b364a61e573387b56359586429777dvboxsync return RTErrConvertFromWin32(iErr);
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Convert the filename to UTF-8.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync if (!pDir->pszName)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync if (RT_FAILURE(rc))
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->pszName = NULL;
0b2c738975b364a61e573387b56359586429777dvboxsync return rc;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->cchName = strlen(pDir->pszName);
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Check if we've got enough space to return the data.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync const char *pszName = pDir->pszName;
0b2c738975b364a61e573387b56359586429777dvboxsync const size_t cchName = pDir->cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync if (pcbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync *pcbDirEntry = cbRequired;
0b2c738975b364a61e573387b56359586429777dvboxsync if (cbRequired > cbDirEntry)
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_BUFFER_OVERFLOW;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Setup the returned data.
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync pDir->fDataUnread = false;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->cbName = (uint16_t)cchName;
0b2c738975b364a61e573387b56359586429777dvboxsync Assert(pDirEntry->cbName == cchName);
0b2c738975b364a61e573387b56359586429777dvboxsync memcpy(pDirEntry->szName, pszName, cchName + 1);
0b2c738975b364a61e573387b56359586429777dvboxsync if (pDir->Data.cAlternateFileName[0])
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync /* copy and calc length */
0b2c738975b364a61e573387b56359586429777dvboxsync PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
0b2c738975b364a61e573387b56359586429777dvboxsync PRTUTF16 pwszDst = pDirEntry->wszShortName;
0b2c738975b364a61e573387b56359586429777dvboxsync uint32_t off = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync pwszDst[off] = pwszSrc[off];
0b2c738975b364a61e573387b56359586429777dvboxsync off++;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->cwcShortName = (uint16_t)off;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /* zero the rest */
0b2c738975b364a61e573387b56359586429777dvboxsync do
0b2c738975b364a61e573387b56359586429777dvboxsync pwszDst[off++] = '\0';
0b2c738975b364a61e573387b56359586429777dvboxsync while (off < RT_ELEMENTS(pDirEntry->wszShortName));
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync else
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->cwcShortName = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
0b2c738975b364a61e573387b56359586429777dvboxsync | (uint64_t)pDir->Data.nFileSizeLow;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
0b2c738975b364a61e573387b56359586429777dvboxsync RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime);
0b2c738975b364a61e573387b56359586429777dvboxsync RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime);
0b2c738975b364a61e573387b56359586429777dvboxsync RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime);
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
0b2c738975b364a61e573387b56359586429777dvboxsync pszName, cchName);
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync /*
0b2c738975b364a61e573387b56359586429777dvboxsync * Requested attributes (we cannot provide anything actually).
0b2c738975b364a61e573387b56359586429777dvboxsync */
0b2c738975b364a61e573387b56359586429777dvboxsync switch (enmAdditionalAttribs)
0b2c738975b364a61e573387b56359586429777dvboxsync {
0b2c738975b364a61e573387b56359586429777dvboxsync case RTFSOBJATTRADD_EASIZE:
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.EASize.cb = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync break;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync case RTFSOBJATTRADD_UNIX:
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.uid = ~0U;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.gid = ~0U;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.cHardlinks = 1;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.fFlags = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.GenerationId = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.Unix.Device = 0;
0b2c738975b364a61e573387b56359586429777dvboxsync break;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync case RTFSOBJATTRADD_NOTHING:
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
0b2c738975b364a61e573387b56359586429777dvboxsync break;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync case RTFSOBJATTRADD_UNIX_OWNER:
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */
0b2c738975b364a61e573387b56359586429777dvboxsync break;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync case RTFSOBJATTRADD_UNIX_GROUP:
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U;
0b2c738975b364a61e573387b56359586429777dvboxsync pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0';
0b2c738975b364a61e573387b56359586429777dvboxsync break;
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync default:
0b2c738975b364a61e573387b56359586429777dvboxsync AssertMsgFailed(("Impossible!\n"));
0b2c738975b364a61e573387b56359586429777dvboxsync return VERR_INTERNAL_ERROR;
0b2c738975b364a61e573387b56359586429777dvboxsync }
0b2c738975b364a61e573387b56359586429777dvboxsync
0b2c738975b364a61e573387b56359586429777dvboxsync return VINF_SUCCESS;
0b2c738975b364a61e573387b56359586429777dvboxsync}
0b2c738975b364a61e573387b56359586429777dvboxsync