VirtualBox

Ignore:
Timestamp:
Nov 9, 2018 1:39:01 AM (6 years ago)
Author:
vboxsync
Message:

Add/os2/VBoxSF: Early shared folders for OS/2. Not perfect yet, but was able to build all the disassembler libraries on a shared folder mount.

Location:
trunk/src/VBox/Additions/os2/VBoxSF
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/os2/VBoxSF/Makefile.kmk

    r69339 r75337  
    2929#
    3030
     31ifneq ($(KBUILD_HOST),os2)
     32 VBOX_USE_WATCOM_FOR_OS2  = 1
     33 KBUILD_TARGET      = os2
     34  BUILD_TARGET      = os2
     35 KBUILD_TARGET_ARCH = x86
     36  BUILD_TARGET_ARCH = x86
     37endif
     38
    3139SUB_DEPTH = ../../../../..
    3240include $(KBUILD_PATH)/subheader.kmk
    3341
    34 VBOXSF_USE_WATCOM=1
    35 TEMPLATE_VBoxGuestR0Watcom = xxx
    36 TEMPLATE_VBoxGuestR0Watcom_EXTENDS = VBOXGUESTR0
    37 TEMPLATE_VBoxGuestR0Watcom_TOOL    = OPENWATCOM
    38 TEMPLATE_VBoxGuestR0Watcom_CTOOL   = OPENWATCOM
    39 TEMPLATE_VBoxGuestR0Watcom_CXXTOOL = OPENWATCOM
    40 TEMPLATE_VBoxGuestR0Watcom_LDTOOL  = OPENWATCOM-WL
    41 TEMPLATE_VBoxGuestR0Watcom_CINCS   = \
    42         $(PATH_TOOL_OPENWATCOM)/h \
    43         $(PATH_TOOL_OPENWATCOM)/h/os2 \
    44        $(PATH_ROOT)/include \
    45         /libc/svn/trunk/libc/include # for os2ddk
    46 TEMPLATE_VBoxGuestR0Watcom_CXXINCS = $(TEMPLATE_VBoxGuestR0Watcom_CINCS)
    47 TEMPLATE_VBoxGuestR0Watcom_CFLAGS  = -s  -ze -w4 -d2 -hc -nt=TEXT32 -nc=CODE -4
    48 TEMPLATE_VBoxGuestR0Watcom_CXXFLAGS = $(TEMPLATE_VBoxGuestR0Watcom_CFLAGS)
    49 
    50 TEMPLATE_VBoxGuestR0Watcom_LDFLAGS = \
    51         form os2 lx physdevice \
    52         option NODefaultlibs \
    53         debug codeview all \
    54         option symfile
    55 TEMPLATE_VBoxGuestR0Watcom_LIBS = $(NO_SUCH_VARIABLE)
    56 
    57 
    58 #?DLLS += VBoxSF
     42#
     43# Debug segment name hack for NASM and dependency workaround (see valkit/bootsector).
     44#
     45include $(KBUILD_PATH)/tools/NASM.kmk
     46TOOL_VBoxNasmDot = Our version of the NASM tool
     47ifndef TOOL_VBoxNasmDot_PATH
     48 ifdef TOOL_VBoxNasm_PATH
     49  TOOL_VBoxNasmDot_PATH = $(TOOL_VBoxNasm_PATH)
     50 else
     51  TOOL_VBoxNasmDot_PATH   := $(firstword $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST)/nasm/v*.*)))
     52  if "$(TOOL_VBoxNasmDot_PATH)" == "" && "$(KBUILD_DEVTOOLS_HST_ALT)" != ""
     53   TOOL_VBoxNasmDot_PATH  := $(firstword $(rsort $(wildcard $(KBUILD_DEVTOOLS_HST_ALT)/nasm/v*.*)))
     54  endif
     55 endif
     56endif
     57ifneq ($(TOOL_VBoxNasmDot_PATH),)
     58 TOOL_VBoxNasmDot_AS     ?= $(TOOL_VBoxNasmDot_PATH)/nasm$(HOSTSUFF_EXE)
     59else
     60 TOOL_VBoxNasmDot_AS     ?= nasm$(HOSTSUFF_EXE)
     61endif
     62TOOL_VBoxNasmDot_ASFLAGS ?= $(TOOL_NASM_ASFLAGS)
     63TOOL_VBoxNasmDot_COMPILE_AS_OUTPUT = $(outbase).lst
     64TOOL_VBoxNasmDot_COMPILE_AS_DEPEND = $(dotseg_1_TARGET)
     65TOOL_VBoxNasmDot_COMPILE_AS_DEPORD =
     66define TOOL_VBoxNasmDot_COMPILE_AS_CMDS
     67ifdef TOOL_VBoxNasmDot_USE_KSUBMIT
     68        $(QUIET)kmk_builtin_kSubmit -C $(PATH_OUT_BASE) -- $(TOOL_VBoxNasmDot_AS)\
     69                $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
     70                -l $(outbase).lst\
     71                -o $(obj)\
     72               -MD "$(dep)" -MP\
     73                $(abspath $(source))
     74else
     75        $(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) -- $(TOOL_VBoxNasmDot_AS)\
     76                $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
     77                -l $(outbase).lst\
     78                -o $(obj)\
     79               -MD "$(dep)" -MP\
     80                $(abspath $(source))
     81endif
     82        $(QUIET)"$(dotseg_1_TARGET)" "$(obj)"
     83endef
     84
     85#
     86# Tool for renaming segments and groups from '$debug_*' to '.debug_*'.
     87#
     88BLDPROGS += dotseg
     89dotseg_TEMPLATE = VBoxBldProg
     90dotseg_SOURCES = dotseg.cpp
     91
     92
     93#
     94# IFS kBuild template tweak.
     95#
     96TEMPLATE_VBoxR0DrvIFS = Hack to make sure we link a library. IFS must not be physical devices, but DLLs!
     97TEMPLATE_VBoxR0DrvIFS_EXTENDS = VBOXGUESTR0
     98ifdef VBOX_USE_WATCOM_FOR_OS2
     99TEMPLATE_VBoxR0DrvIFS_LDFLAGS = $(subst physdevice,dll, $(TEMPLATE_VBOXGUESTR0_LDFLAGS))
     100endif
     101TEMPLATE_VBoxR0DrvIFS_SYSSUFF = .ifs
     102TEMPLATE_VBoxR0DrvIFS_DLLSUFF = .ifs
     103TEMPLATE_VBoxR0DrvIFS_ASTOOL = VBoxNasmDot
     104
     105
     106#
     107# The OS/2 shared folder installable file system driver (IFS).
     108#
    59109SYSMODS += VBoxSF
    60 ifdef VBOXSF_USE_WATCOM
    61 VBoxSF_TEMPLATE      = VBoxGuestR0Watcom
    62 else
    63 VBoxSF_TEMPLATE      = VBOXGUESTR0
    64 endif
    65 VBoxSF_SYSSUFF       = .ifs
    66 VBoxSF_DLLSUFF       = .ifs
     110VBoxSF_TEMPLATE      = VBoxR0DrvIFS
    67111VBoxSF_DEFS          = VBOX_WITH_HGCM
    68112VBoxSF_INCS         := \
    69113        . \
    70114        $(PATH_ROOT)/src/VBox/Runtime/include
    71 ifdef VBOXSF_USE_WATCOM
     115ifdef VBOX_USE_WATCOM_FOR_OS2
    72116VBoxSF_LDFLAGS      := \
    73117        OPTION MODNAME='VBoxSF' \
     
    126170        EXPORT 'FS_SETSWAP' \
    127171        EXPORT 'FS_SHUTDOWN' \
     172        EXPORT 'FS_VERIFYUNCNAME' \
    128173        EXPORT 'FS_WRITE'
    129174# 32-bit entry points.
    130175VBoxSF_LDFLAGS += \
    131         EXPORT 'FS32_CHGFILEPTR' \
    132176        EXPORT 'FS32_CHGFILEPTRL' \
    133177        EXPORT 'FS32_READ' \
     
    148192        VBoxSFFind.cpp \
    149193        VBoxSFInit.cpp
    150 ifndef VBOXSF_USE_WATCOM
     194ifndef VBOX_USE_WATCOM_FOR_OS2
    151195 VBoxSF_SOURCES     += \
    152196        VBoxSF.def
     
    155199        $(VBOX_LIB_VBGL_R0) \
    156200        $(VBOX_LIB_IPRT_GUEST_R0)
    157 ifdef VBOXSF_USE_WATCOM
     201ifdef VBOX_USE_WATCOM_FOR_OS2
    158202 VBoxSF_LIBS        += $(PATH_IGCC)/lib/libend.lib
    159203else
     
    161205endif
    162206
     207
     208#
     209# Simple utility for attaching a shared folder to a drive letter.
     210#
     211PROGRAMS += VBoxSFUtil
     212VBoxSFUtil_TEMPLATE = DUMMY
     213VBoxSFUtil_TOOL     = OPENWATCOM
     214VBoxSFUtil_ASTOOL   = NASM
     215VBoxSFUtil_ASFLAGS  = -f obj -DASM_FORMAT_OMF
     216VBoxSFUtil_INCS     = $(PATH_TOOL_OPENWATCOM)/h/os2
     217VBoxSFUtil_LDFLAGS  = -bcl=os2v2
     218VBoxSFUtil_SOURCES  = \
     219        VBoxSFUtil.cpp \
     220        VBoxSFUtilA.asm
     221
     222#PROGRAMS += VBoxSFUtil16
     223#VBoxSFUtil16_TEMPLATE = DUMMY
     224#VBoxSFUtil16_TOOL     = OPENWATCOM-16
     225#VBoxSFUtil16_ASTOOL   = NASM
     226#VBoxSFUtil16_INCS     = $(PATH_TOOL_OPENWATCOM)/h/os2
     227#VBoxSFUtil16_LDFLAGS  = -bcl=os2
     228#VBoxSFUtil16_SOURCES  = VBoxSFUtil.cpp
     229
     230
    163231include $(FILE_KBUILD_SUB_FOOTER)
    164232
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp

    r68612 r75337  
    3838#include <VBox/log.h>
    3939#include <iprt/assert.h>
    40 
     40#include <iprt/ctype.h>
     41#include <iprt/mem.h>
     42
     43#include <iprt/asm.h>
     44#include <iprt/asm-amd64-x86.h>
     45
     46
     47/*********************************************************************************************************************************
     48*   Defined Constants And Macros                                                                                                 *
     49*********************************************************************************************************************************/
     50/** Max folder name length, including terminator.
     51 * Easier to deal with stack buffers if we put a reasonable limit on the. */
     52#define VBOXSFOS2_MAX_FOLDER_NAME   64
     53
     54
     55/*********************************************************************************************************************************
     56*   Global Variables                                                                                                             *
     57*********************************************************************************************************************************/
     58/** The shared mutex protecting folders list, drives and the connection. */
     59MutexLock_t         g_MtxFolders;
     60/** The shared folder service client structure. */
     61VBGLSFCLIENT        g_SfClient;
     62/** Set if g_SfClient is valid, clear if not. */
     63bool                g_fIsConnectedToService = false;
     64/** List of active folder (PVBOXSFFOLDER). */
     65RTLISTANCHOR        g_FolderHead;
     66/** This is incremented everytime g_FolderHead is modified. */
     67uint32_t volatile   g_uFolderRevision;
     68/** Folders mapped on drive letters.  Pointers include a reference. */
     69PVBOXSFFOLDER       g_apDriveFolders[26];
     70
     71
     72
     73/**
     74 * Generic IPRT -> OS/2 status code converter.
     75 *
     76 * @returns OS/2 status code.
     77 * @param   vrc             IPRT/VBox status code.
     78 * @param   rcDefault       The OS/2 status code to return when there
     79 *                          is no translation.
     80 */
     81APIRET vboxSfOs2ConvertStatusToOs2(int vrc, APIRET rcDefault)
     82{
     83    switch (vrc)
     84    {
     85        default:                        return rcDefault;
     86
     87        case VERR_FILE_NOT_FOUND:       return ERROR_FILE_NOT_FOUND;
     88        case VERR_PATH_NOT_FOUND:       return ERROR_PATH_NOT_FOUND;
     89        case VERR_SHARING_VIOLATION:    return ERROR_SHARING_VIOLATION;
     90        case VERR_ACCESS_DENIED:        return ERROR_ACCESS_DENIED;
     91        case VERR_ALREADY_EXISTS:       return ERROR_ACCESS_DENIED;
     92        case VERR_WRITE_PROTECT:        return ERROR_WRITE_PROTECT;
     93        case VERR_IS_A_DIRECTORY:       return ERROR_DIRECTORY;
     94        case VINF_SUCCESS:              return NO_ERROR;
     95    }
     96}
     97
     98
     99/**
     100 * Gets the delta for the local timezone, in minutes.
     101 *
     102 * We need to do this once for each API call rather than over and over again for
     103 * each date/time conversion, so as not to create an update race.
     104 *
     105 * @returns Delta in minutes.  Current thinking is that positive means timezone
     106 *          is west of UTC, while negative is east of it.
     107 */
     108int16_t vboxSfOs2GetLocalTimeDelta(void)
     109{
     110    GINFOSEG volatile *pGis = (GINFOSEG volatile *)&KernSISData;
     111    if (pGis)
     112    {
     113        uint16_t cDelta = pGis->timezone;
     114        if (cDelta != 0 && cDelta != 0xffff)
     115            return (int16_t)cDelta;
     116    }
     117    return 0;
     118}
     119
     120
     121/**
     122 * Helper for converting from IPRT timespec format to OS/2 DATE/TIME.
     123 *
     124 * @param   pDosDate            The output DOS date.
     125 * @param   pDosTime            The output DOS time.
     126 * @param   SrcTimeSpec         The IPRT input timestamp.
     127 * @param   cMinLocalTimeDelta  The timezone delta in minutes.
     128 */
     129void vboxSfOs2DateTimeFromTimeSpec(FDATE *pDosDate, FTIME *pDosTime, RTTIMESPEC SrcTimeSpec, int16_t cMinLocalTimeDelta)
     130{
     131    if (cMinLocalTimeDelta != 0)
     132        RTTimeSpecAddSeconds(&SrcTimeSpec, cMinLocalTimeDelta * 60);
     133
     134    RTTIME Time;
     135    if (   RTTimeSpecGetNano(&SrcTimeSpec) >= RTTIME_OFFSET_DOS_TIME
     136        && RTTimeExplode(&Time, &SrcTimeSpec))
     137    {
     138        pDosDate->year    = Time.i32Year - 1980;
     139        pDosDate->month   = Time.u8Month;
     140        pDosDate->day     = Time.u8MonthDay;
     141        pDosTime->hours   = Time.u8Hour;
     142        pDosTime->minutes = Time.u8Minute;
     143        pDosTime->twosecs = Time.u8Second / 2;
     144    }
     145    else
     146    {
     147        pDosDate->year    = 0;
     148        pDosDate->month   = 1;
     149        pDosDate->day     = 1;
     150        pDosTime->hours   = 0;
     151        pDosTime->minutes = 0;
     152        pDosTime->twosecs = 0;
     153    }
     154}
     155
     156
     157/**
     158 * Helper for converting from OS/2 DATE/TIME to IPRT timespec format.
     159 *
     160 * @returns pDstTimeSpec on success, NULL if invalid input.
     161 * @param   DosDate             The input DOS date.
     162 * @param   DosTime             The input DOS time.
     163 * @param   cMinLocalTimeDelta  The timezone delta in minutes.
     164 * @param   pDstTimeSpec        The IPRT output timestamp.
     165 */
     166PRTTIMESPEC vboxSfOs2DateTimeToTimeSpec(FDATE DosDate, FTIME DosTime, int16_t cMinLocalTimeDelta, PRTTIMESPEC pDstTimeSpec)
     167{
     168    RTTIME Time;
     169    Time.i32Year        = DosDate.year + 1980;
     170    Time.u8Month        = DosDate.month;
     171    Time.u8WeekDay      = UINT8_MAX;
     172    Time.u16YearDay     = 0;
     173    Time.u8MonthDay     = DosDate.day;
     174    Time.u8Hour         = DosTime.hours;
     175    Time.u8Minute       = DosTime.minutes;
     176    Time.u8Second       = DosTime.twosecs * 2;
     177    Time.u32Nanosecond  = 0;
     178    Time.fFlags         = RTTIME_FLAGS_TYPE_LOCAL;
     179    Time.offUTC         = cMinLocalTimeDelta;
     180    if (RTTimeLocalNormalize(&Time))
     181        return RTTimeImplode(pDstTimeSpec, &Time);
     182    return NULL;
     183}
     184
     185
     186/*********************************************************************************************************************************
     187*   Shared Folder String Buffer Management                                                                                       *
     188*********************************************************************************************************************************/
     189
     190/**
     191 * Allocates a SHFLSTRING buffer.
     192 *
     193 * @returns Pointer to a SHFLSTRING buffer, NULL if out of memory.
     194 * @param   cchLength   The desired string buffer length (excluding terminator).
     195 */
     196PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength)
     197{
     198    AssertReturn(cchLength <= 0x1000, NULL);
     199
     200    PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchLength + 1);
     201    if (pStr)
     202    {
     203        pStr->u16Size       = (uint16_t)(cchLength + 1);
     204        pStr->u16Length     = 0;
     205        pStr->String.ach[0] = '\0';
     206        return pStr;
     207    }
     208    return NULL;
     209}
     210
     211
     212/**
     213 * Duplicates a UTF-8 string into a SHFLSTRING buffer.
     214 *
     215 * @returns Pointer to a SHFLSTRING buffer containing the copy.
     216 *          NULL if out of memory or the string is too long.
     217 * @param   pachSrc     The string to clone.
     218 * @param   cchSrc      The length of the substring, RTMAX_STR for the whole.
     219 */
     220PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc)
     221{
     222    if (cchSrc == RTSTR_MAX)
     223        cchSrc = strlen(pachSrc);
     224    if (cchSrc < 0x1000)
     225    {
     226        PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchSrc + 1);
     227        if (pStr)
     228        {
     229            pStr->u16Size  = (uint16_t)(cchSrc + 1);
     230            pStr->u16Length = (uint16_t)cchSrc;
     231            memcpy(pStr->String.ach, pachSrc, cchSrc);
     232            pStr->String.ach[cchSrc] = '\0';
     233            return pStr;
     234        }
     235    }
     236    return NULL;
     237}
     238
     239
     240/**
     241 * Frees a SHLFSTRING buffer.
     242 *
     243 * @param   pStr        The buffer to free.
     244 */
     245void vboxSfOs2StrFree(PSHFLSTRING pStr)
     246{
     247    if (pStr)
     248        VbglR0PhysHeapFree(pStr);
     249}
     250
     251
     252
     253/*********************************************************************************************************************************
     254*   Folders, Paths and Service Connection.                                                                                       *
     255*********************************************************************************************************************************/
     256
     257/**
     258 * Ensures that we're connected to the host service.
     259 *
     260 * @returns VBox status code.
     261 * @remarks Caller owns g_MtxFolder exclusively!
     262 */
     263static int vboxSfOs2EnsureConnected(void)
     264{
     265    if (g_fIsConnectedToService)
     266        return VINF_SUCCESS;
     267
     268    int rc = VbglR0SfConnect(&g_SfClient);
     269    if (RT_SUCCESS(rc))
     270    {
     271        rc = VbglR0SfSetUtf8(&g_SfClient);
     272        if (RT_SUCCESS(rc))
     273            g_fIsConnectedToService = true;
     274        else
     275        {
     276            LogRel(("VbglR0SfSetUtf8 failed: %Rrc\n", rc));
     277            VbglR0SfDisconnect(&g_SfClient);
     278        }
     279    }
     280    else
     281        LogRel(("VbglR0SfConnect failed: %Rrc\n", rc));
     282    return rc;
     283}
     284
     285
     286/**
     287 * Destroys a folder when the reference count has reached zero.
     288 *
     289 * @param   pFolder         The folder to destroy.
     290 */
     291static void vboxSfOs2DestroyFolder(PVBOXSFFOLDER pFolder)
     292{
     293    /* Note! We won't get there while the folder is on the list. */
     294    LogRel(("vboxSfOs2ReleaseFolder: Destroying %p [%s]\n", pFolder, pFolder->szName));
     295    VbglR0SfUnmapFolder(&g_SfClient, &pFolder->hHostFolder);
     296    RT_ZERO(pFolder);
     297    RTMemFree(pFolder);
     298}
     299
     300
     301/**
     302 * Releases a reference to a folder.
     303 *
     304 * @param   pFolder         The folder to release.
     305 */
     306void vboxSfOs2ReleaseFolder(PVBOXSFFOLDER pFolder)
     307{
     308    if (pFolder)
     309    {
     310        uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
     311        AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
     312        if (!cRefs)
     313            vboxSfOs2DestroyFolder(pFolder);
     314    }
     315}
     316
     317
     318/**
     319 * Retain a reference to a folder.
     320 *
     321 * @param   pFolder         The folder to release.
     322 */
     323void vboxSfOs2RetainFolder(PVBOXSFFOLDER pFolder)
     324{
     325    uint32_t cRefs = ASMAtomicIncU32(&pFolder->cRefs);
     326    AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
     327}
     328
     329
     330/**
     331 * Locates and retains a folder structure.
     332 *
     333 * @returns Folder matching the name, NULL of not found.
     334 * @remarks Caller owns g_MtxFolder.
     335 */
     336static PVBOXSFFOLDER vboxSfOs2FindAndRetainFolder(const char *pachName, size_t cchName)
     337{
     338    PVBOXSFFOLDER pCur;
     339    RTListForEach(&g_FolderHead, pCur, VBOXSFFOLDER, ListEntry)
     340    {
     341        if (   pCur->cchName == cchName
     342            && RTStrNICmpAscii(pCur->szName, pachName, cchName) == 0)
     343        {
     344            uint32_t cRefs = ASMAtomicIncU32(&pCur->cRefs);
     345            AssertMsg(cRefs < _64K, ("%#x\n", cRefs));
     346            return pCur;
     347        }
     348    }
     349    return NULL;
     350}
     351
     352
     353/**
     354 * Maps a folder, linking it into the list of folders.
     355 *
     356 * One reference is retained for the caller, which must pass it on or release
     357 * it.  The list also have a reference to it.
     358 *
     359 * @returns VBox status code.
     360 * @param   pName       The name of the folder to map.
     361 * @param   ppFolder    Where to return the folder structure on success.
     362 *
     363 * @remarks Caller owns g_MtxFolder exclusively!
     364 */
     365static int vboxSfOs2MapFolder(PSHFLSTRING pName, PVBOXSFFOLDER *ppFolder)
     366{
     367    int rc;
     368    PVBOXSFFOLDER pNew = (PVBOXSFFOLDER)RTMemAlloc(RT_UOFFSETOF_DYN(VBOXSFFOLDER, szName[pName->u16Length + 1]));
     369    if (pNew != NULL)
     370    {
     371        pNew->u32Magic      = VBOXSFFOLDER_MAGIC;
     372        pNew->cRefs         = 2; /* (List reference + the returned reference.) */
     373        pNew->cOpenFiles    = 0;
     374        pNew->cDrives       = 0;
     375        RT_ZERO(pNew->hHostFolder);
     376        pNew->hVpb          = 0;
     377        pNew->cchName       = (uint8_t)pName->u16Length;
     378        memcpy(pNew->szName, pName->String.utf8, pName->u16Length);
     379        pNew->szName[pName->u16Length] = '\0';
     380
     381        rc = VbglR0SfMapFolder(&g_SfClient, pName, &pNew->hHostFolder);
     382        if (RT_SUCCESS(rc))
     383        {
     384            RTListAppend(&g_FolderHead, &pNew->ListEntry);
     385            ASMAtomicIncU32(&g_uFolderRevision);
     386            LogRel(("vboxSfOs2MapFolder: %p - %s\n", pNew, pNew->szName));
     387
     388            *ppFolder = pNew;
     389        }
     390        else
     391        {
     392            LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%.*s,) -> %Rrc\n", pName->u16Length, pName->String.utf8, rc));
     393            RTMemFree(pNew);
     394        }
     395    }
     396    else
     397    {
     398        LogRel(("vboxSfOs2MapFolder: Out of memory :-(\n"));
     399        rc = VERR_NO_MEMORY;
     400    }
     401    return rc;
     402}
     403
     404
     405/**
     406 * Worker for vboxSfOs2UncPrefixLength.
     407 */
     408DECLINLINE(size_t) vboxSfOs2CountLeadingSlashes(const char *pszPath)
     409{
     410    size_t cchSlashes = 0;
     411    char ch;
     412    while ((ch = *pszPath) == '\\' || ch == '/')
     413        cchSlashes++, pszPath++;
     414    return cchSlashes;
     415}
     416
     417
     418/**
     419 * Checks for a VBox UNC prefix (server + slashes) and determins its length when
     420 * found.
     421 *
     422 * @returns Length of VBoxSF UNC prefix, 0 if not VBoxSF UNC prefix.
     423 * @param   pszPath             The possible UNC path.
     424 */
     425DECLINLINE(size_t) vboxSfOs2UncPrefixLength(const char *pszPath)
     426{
     427    char ch;
     428    if (   ((ch = pszPath[0]) == '\\' || ch == '/')
     429        && ((ch = pszPath[1]) == '\\' || ch == '/')
     430        && ((ch = pszPath[2]) == 'V'  || ch == 'v')
     431        && ((ch = pszPath[3]) == 'B'  || ch == 'b')
     432        && ((ch = pszPath[4]) == 'O'  || ch == 'o')
     433        && ((ch = pszPath[5]) == 'X'  || ch == 'x')
     434        && ((ch = pszPath[6]) == 'S'  || ch == 's')
     435       )
     436    {
     437        /* \\VBoxSf\ */
     438        if (   ((ch = pszPath[7]) == 'F'  || ch == 'f')
     439            && ((ch = pszPath[8]) == '\\' || ch == '/') )
     440            return vboxSfOs2CountLeadingSlashes(&pszPath[9]) + 9;
     441
     442        /* \\VBoxSvr\ */
     443        if (   ((ch = pszPath[7]) == 'V'  || ch == 'v')
     444            && ((ch = pszPath[8]) == 'R'  || ch == 'r')
     445            && ((ch = pszPath[9]) == '\\' || ch == '/') )
     446            return vboxSfOs2CountLeadingSlashes(&pszPath[10]) + 10;
     447
     448        /* \\VBoxSrv\ */
     449        if (   ((ch = pszPath[7]) == 'R'  || ch == 'r')
     450            && ((ch = pszPath[8]) == 'V'  || ch == 'v')
     451            && ((ch = pszPath[9]) == '\\' || ch == '/') )
     452            return vboxSfOs2CountLeadingSlashes(&pszPath[10]) + 10;
     453    }
     454
     455    return 0;
     456}
     457
     458
     459/**
     460 * Converts a path to UTF-8 and puts it in a VBGL friendly buffer.
     461 *
     462 * @returns OS/2 status code
     463 * @param   pszFolderPath   The path to convert.
     464 * @param   ppStr           Where to return the pointer to the buffer.  Free
     465 *                          using vboxSfOs2FreePath.
     466 */
     467APIRET vboxSfOs2ConvertPath(const char *pszFolderPath, PSHFLSTRING *ppStr)
     468{
     469    /* Skip unnecessary leading slashes. */
     470    char ch = *pszFolderPath;
     471    if (ch == '\\' || ch == '/')
     472        while ((ch = pszFolderPath[1]) == '\\' || ch == '/')
     473            pszFolderPath++;
     474
     475    /** @todo do proper codepage -> utf8 conversion and straighten out
     476     *        everything... */
     477    size_t cchSrc = strlen(pszFolderPath);
     478    PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc);
     479    if (pDst)
     480    {
     481        pDst->u16Length = (uint16_t)cchSrc;
     482        memcpy(pDst->String.utf8, pszFolderPath, cchSrc);
     483        pDst->String.utf8[cchSrc] = '\0';
     484        *ppStr = pDst;
     485        return NO_ERROR;
     486    }
     487    *ppStr = NULL;
     488    return ERROR_NOT_ENOUGH_MEMORY;
     489}
     490
     491
     492/**
     493 * Counterpart to vboxSfOs2ResolvePath.
     494 *
     495 * @param   pStrPath        The path to free.
     496 * @param   pFolder         The folder to release.
     497 */
     498void vboxSfOs2ReleasePathAndFolder(PSHFLSTRING pStrPath, PVBOXSFFOLDER pFolder)
     499{
     500    if (pStrPath)
     501        VbglR0PhysHeapFree(pStrPath);
     502    if (pFolder)
     503    {
     504        uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
     505        Assert(cRefs < _64K);
     506        if (!cRefs)
     507            vboxSfOs2DestroyFolder(pFolder);
     508    }
     509}
     510
     511
     512/**
     513 * Worker for vboxSfOs2ResolvePath() for dynamically mapping folders for UNC
     514 * paths.
     515 *
     516 * @returns OS/2 status code.
     517 * @param   pachFolderName  The folder to map.  Not necessarily zero terminated
     518 *                          at the end of the folder name!
     519 * @param   cchFolderName   The length of the folder name.
     520 * @param   uRevBefore      The previous folder list revision.
     521 * @param   ppFolder        Where to return the pointer to the retained folder.
     522 */
     523DECL_NO_INLINE(static, int) vboxSfOs2AttachUncAndRetain(const char *pachFolderName, size_t cchFolderName,
     524                                                        uint32_t uRevBefore, PVBOXSFFOLDER *ppFolder)
     525{
     526    KernRequestExclusiveMutex(&g_MtxFolders);
     527
     528    /*
     529     * Check if someone raced us to it.
     530     */
     531    if (uRevBefore != g_uFolderRevision)
     532    {
     533        PVBOXSFFOLDER pFolder = vboxSfOs2FindAndRetainFolder(pachFolderName, cchFolderName);
     534        if (pFolder)
     535        {
     536            KernReleaseExclusiveMutex(&g_MtxFolders);
     537            *ppFolder = pFolder;
     538            return NO_ERROR;
     539        }
     540    }
     541
     542    int rc = vboxSfOs2EnsureConnected();
     543    if (RT_SUCCESS(rc))
     544    {
     545        /*
     546         * Copy the name into the buffer format that Vbgl desires.
     547         */
     548        PSHFLSTRING pStrName = vboxSfOs2StrDup(pachFolderName, cchFolderName);
     549        if (pStrName)
     550        {
     551            /*
     552             * Do the attaching.
     553             */
     554            rc = vboxSfOs2MapFolder(pStrName, ppFolder);
     555            vboxSfOs2StrFree(pStrName);
     556            if (RT_SUCCESS(rc))
     557            {
     558                KernReleaseExclusiveMutex(&g_MtxFolders);
     559                LogRel(("vboxSfOs2AttachUncAndRetain: Successfully attached '%s' (as UNC).\n", (*ppFolder)->szName));
     560                return NO_ERROR;
     561            }
     562
     563            if (rc == VERR_NO_MEMORY)
     564                rc = ERROR_NOT_ENOUGH_MEMORY;
     565            else
     566                rc = ERROR_PATH_NOT_FOUND;
     567        }
     568        else
     569            rc = ERROR_NOT_ENOUGH_MEMORY;
     570    }
     571    else
     572        rc = ERROR_PATH_NOT_FOUND;
     573
     574    KernReleaseExclusiveMutex(&g_MtxFolders);
     575    return rc;
     576}
     577
     578
     579/**
     580 * Resolves the given path to a folder structure and folder relative string.
     581 *
     582 * @returns OS/2 status code.
     583 * @param   pszPath         The path to resolve.
     584 * @param   pCdFsd          The IFS dependent CWD structure if present.
     585 * @param   offCurDirEnd    The offset into @a pszPath of the CWD.  -1 if not
     586 *                          CWD relative path.
     587 * @param   ppFolder        Where to return the referenced pointer to the folder
     588 *                          structure.  Call vboxSfOs2ReleaseFolder() when done.
     589 * @param   ppStrFolderPath Where to return a buffer holding the folder relative
     590 *                          path component.  Free using vboxSfOs2FreePath().
     591 */
     592APIRET vboxSfOs2ResolvePath(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd,
     593                            PVBOXSFFOLDER *ppFolder, PSHFLSTRING *ppStrFolderPath)
     594{
     595    APIRET rc;
     596
     597    /*
     598     * UNC path?  Reject the prefix to be on the safe side.
     599     */
     600    char ch = pszPath[0];
     601    if (ch == '\\' || ch == '/')
     602    {
     603        size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath);
     604        if (cchPrefix > 0)
     605        {
     606            /* Find the length of the folder name (share). */
     607            const char *pszFolderName = &pszPath[cchPrefix];
     608            size_t      cchFolderName = 0;
     609            while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/')
     610            {
     611                if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':')
     612                    cchFolderName++;
     613                else
     614                {
     615                    LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n",
     616                            cchPrefix + cchFolderName, strlen(pszPath), pszPath));
     617                    return ERROR_INVALID_NAME;
     618                }
     619            }
     620            if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME)
     621            {
     622                LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n",
     623                        cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath));
     624                return ERROR_FILENAME_EXCED_RANGE;
     625            }
     626
     627            /*
     628             * Look for the share.
     629             */
     630            KernRequestSharedMutex(&g_MtxFolders);
     631            PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName);
     632            if (pFolder)
     633            {
     634                vboxSfOs2RetainFolder(pFolder);
     635                KernReleaseSharedMutex(&g_MtxFolders);
     636            }
     637            else
     638            {
     639                uint32_t const uRevBefore = g_uFolderRevision;
     640                KernReleaseSharedMutex(&g_MtxFolders);
     641                rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder);
     642                if (rc == NO_ERROR)
     643                    pFolder = *ppFolder;
     644                else
     645                    return rc;
     646            }
     647
     648            /*
     649             * Convert the path and put it in a Vbgl compatible buffer..
     650             */
     651            rc = vboxSfOs2ConvertPath(&pszFolderName[cchFolderName], ppStrFolderPath);
     652            if (rc == NO_ERROR)
     653                return rc;
     654
     655            vboxSfOs2ReleaseFolder(pFolder);
     656            *ppFolder = NULL;
     657            return rc;
     658        }
     659
     660        LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
     661        return ERROR_PATH_NOT_FOUND;
     662    }
     663
     664    /*
     665     * Drive letter?
     666     */
     667    ch &= ~0x20; /* upper case */
     668    if (   ch >= 'A'
     669        && ch <= 'Z'
     670        && pszPath[1] == ':')
     671    {
     672        unsigned iDrive = ch - 'A';
     673        ch  = pszPath[2];
     674        if (ch == '\\' || ch == '/')
     675        {
     676            KernRequestSharedMutex(&g_MtxFolders);
     677            PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive];
     678            if (pFolder)
     679            {
     680                vboxSfOs2RetainFolder(pFolder);
     681                KernReleaseSharedMutex(&g_MtxFolders);
     682
     683                /*
     684                 * Convert the path and put it in a Vbgl compatible buffer..
     685                 */
     686                rc = vboxSfOs2ConvertPath(&pszPath[3], ppStrFolderPath);
     687                if (rc == NO_ERROR)
     688                    return rc;
     689
     690                vboxSfOs2ReleaseFolder(pFolder);
     691                *ppFolder = NULL;
     692                return rc;
     693            }
     694            KernReleaseSharedMutex(&g_MtxFolders);
     695            LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath));
     696            return ERROR_PATH_NOT_FOUND;
     697        }
     698        LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath));
     699        return ERROR_PATH_NOT_FOUND;
     700    }
     701    LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
     702    RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd);
     703    return ERROR_PATH_NOT_FOUND;
     704}
    41705
    42706
     
    44708FS32_EXIT(ULONG uid, ULONG pid, ULONG pdb)
    45709{
     710    LogFlow(("FS32_EXIT: uid=%u pid=%u pdb=%#x\n", uid, pid, pdb));
    46711    NOREF(uid); NOREF(pid); NOREF(pdb);
    47712}
    48713
    49714
    50 DECLASM(int)
    51 FS32_SHUTDOWN(ULONG type, ULONG reserved)
    52 {
    53     NOREF(type); NOREF(reserved);
     715DECLASM(APIRET)
     716FS32_SHUTDOWN(ULONG uType, ULONG uReserved)
     717{
     718    LogFlow(("FS32_SHUTDOWN: type=%u uReserved=%u\n", uType, uReserved));
     719    NOREF(uType); NOREF(uReserved);
    54720    return NO_ERROR;
    55721}
    56722
    57723
    58 DECLASM(int)
    59 FS32_ATTACH(ULONG fFlags, PCSZ pszDev, PVBOXSFVP pvpfsd, PVBOXSFCD pcdfsd, PBYTE pszParm, PUSHORT pcbParm)
    60 {
    61     NOREF(fFlags); NOREF(pszDev); NOREF(pvpfsd); NOREF(pcdfsd); NOREF(pszParm); NOREF(pcbParm);
     724/**
     725 * FS32_ATTACH worker: FS_ATTACH
     726 */
     727static APIRET vboxSfOs2Attach(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam,
     728                              PSHFLSTRING *ppCleanup)
     729{
     730    /*
     731     * Check out the parameters, copying the pszParam into a suitable string buffer.
     732     */
     733    if (pszDev == NULL || !*pszDev || !RT_C_IS_ALPHA(pszDev[0]) || pszDev[1] != ':' || pszDev[2] != '\0')
     734    {
     735        LogRel(("vboxSfOs2Attach: Invalid pszDev value:%p:{%s}\n", pszDev, pszDev));
     736        return ERROR_INVALID_PARAMETER;
     737    }
     738    unsigned const iDrive = (pszDev[0] & ~0x20) - 'A';
     739
     740    if (pszParam == NULL || pcbParam == NULL)
     741    {
     742        LogRel(("vboxSfOs2Attach: NULL parameter buffer or buffer length\n"));
     743        return ERROR_INVALID_PARAMETER;
     744    }
     745
     746    PSHFLSTRING pStrName = *ppCleanup = vboxSfOs2StrAlloc(VBOXSFOS2_MAX_FOLDER_NAME - 1);
     747    pStrName->u16Length = *pcbParam;
     748    if (pStrName->u16Length < 1 || pStrName->u16Length > VBOXSFOS2_MAX_FOLDER_NAME)
     749    {
     750        LogRel(("vboxSfOs2Attach: Parameter buffer length is out of bounds: %u (min: 1, max " RT_XSTR(VBOXSFOS2_MAX_FOLDER_NAME) ")\n",
     751                pStrName->u16Length));
     752        return ERROR_INVALID_PARAMETER;
     753    }
     754
     755    int rc = KernCopyIn(pStrName->String.utf8, pszParam, pStrName->u16Length);
     756    if (rc != NO_ERROR)
     757        return rc;
     758
     759    pStrName->u16Length -= 1;
     760    if (pStrName->String.utf8[pStrName->u16Length] != '\0')
     761    {
     762        LogRel(("vboxSfOs2Attach: Parameter not null terminated\n"));
     763        return ERROR_INVALID_PARAMETER;
     764    }
     765
     766    /* Make sure it's only ascii and contains not weird stuff. */
     767    unsigned off = pStrName->u16Length;
     768    while (off-- > 0)
     769    {
     770        char const ch = pStrName->String.utf8[off];
     771        if (ch < 0x20 || ch >= 0x7f || ch == ':' || ch == '\\' || ch == '/')
     772        {
     773            LogRel(("vboxSfOs2Attach: Malformed folder name: %.*Rhxs (off %#x)\n", pStrName->u16Length, pStrName->String.utf8, off));
     774            return ERROR_INVALID_PARAMETER;
     775        }
     776    }
     777
     778    if (!pVpFsd)
     779    {
     780        LogRel(("vboxSfOs2Attach: pVpFsd is NULL\n"));
     781        return ERROR_INVALID_PARAMETER;
     782    }
     783
     784    /*
     785     * Look for the folder to see if we're already using it.  Map it if needed.
     786     */
     787    KernRequestExclusiveMutex(&g_MtxFolders);
     788    if (g_apDriveFolders[iDrive] == NULL)
     789    {
     790
     791        PVBOXSFFOLDER pFolder = vboxSfOs2FindAndRetainFolder(pStrName->String.ach, pStrName->u16Length);
     792        if (!pFolder)
     793        {
     794            rc = vboxSfOs2EnsureConnected();
     795            if (RT_SUCCESS(rc))
     796                rc = vboxSfOs2MapFolder(pStrName, &pFolder);
     797        }
     798        if (pFolder && RT_SUCCESS(rc))
     799        {
     800            pFolder->cDrives += 1;
     801            g_apDriveFolders[iDrive] = pFolder;
     802
     803            pVpFsd->u32Magic = VBOXSFVP_MAGIC;
     804            pVpFsd->pFolder  = pFolder;
     805
     806            KernReleaseExclusiveMutex(&g_MtxFolders);
     807
     808            LogRel(("vboxSfOs2Attach: Successfully attached '%s' to '%s'.\n", pFolder->szName, pszDev));
     809            return NO_ERROR;
     810        }
     811
     812        KernReleaseExclusiveMutex(&g_MtxFolders);
     813        return ERROR_FILE_NOT_FOUND;
     814    }
     815    KernReleaseExclusiveMutex(&g_MtxFolders);
     816
     817    LogRel(("vboxSfOs2Attach: Already got a folder on '%s'!\n", pszDev));
     818    RT_NOREF(pCdFsd);
     819    return ERROR_BUSY_DRIVE;
     820}
     821
     822
     823/**
     824 * FS32_ATTACH worker: FS_DETACH
     825 */
     826static APIRET vboxSfOs2Detach(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam)
     827{
     828    /*
     829     * Validate the volume data and assocated folder.
     830     */
     831    AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
     832    AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
     833    PVBOXSFFOLDER pFolder = pVpFsd->pFolder;
     834    AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
     835    AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
     836
     837    uint8_t idxDrive = UINT8_MAX;
     838    if (   pszDev
     839        && RT_C_IS_ALPHA(*pszDev))
     840        idxDrive = (*pszDev & ~0x20) - 'A';
     841
     842    /*
     843     * Can we detach it?
     844     */
     845    APIRET rc;
     846    KernRequestExclusiveMutex(&g_MtxFolders);
     847    if (   pFolder->cOpenFiles == 0
     848        && pFolder->cOpenSearches == 0)
     849    {
     850        /*
     851         * Check that we've got the right folder/drive combo.
     852         */
     853        if (   idxDrive < RT_ELEMENTS(g_apDriveFolders)
     854            && g_apDriveFolders[idxDrive] == pFolder)
     855        {
     856            g_apDriveFolders[idxDrive] = NULL;
     857            uint8_t cDrives = --pFolder->cDrives;
     858            AssertMsg(cDrives < 30, ("%#x\n", cDrives));
     859
     860            uint32_t cRefs = ASMAtomicDecU32(&pFolder->cRefs);
     861            AssertMsg(cRefs < _32K, ("%#x\n", cRefs));
     862            if (cRefs)
     863            {
     864                /* If there are no zero drives, unlink it from the list and release
     865                   the list reference.  This should almost always drop end up with us
     866                   destroying the folder.*/
     867                if (cDrives == 0)
     868                {
     869                    RTListNodeRemove(&pFolder->ListEntry);
     870                    cRefs = ASMAtomicDecU32(&pFolder->cRefs);
     871                    AssertMsg(cRefs < _32K, ("%#x\n", cRefs));
     872                    if (!cRefs)
     873                        vboxSfOs2DestroyFolder(pFolder);
     874                }
     875            }
     876            else
     877            {
     878                LogRel(("vboxSfOs2Detach: cRefs=0?!?\n"));
     879                vboxSfOs2DestroyFolder(pFolder);
     880            }
     881        }
     882        else
     883        {
     884            LogRel(("vboxSfOs2Detach: g_apDriveFolders[%#x]=%p pFolder=%p\n",
     885                    idxDrive, idxDrive < RT_ELEMENTS(g_apDriveFolders) ? g_apDriveFolders[idxDrive] : NULL, pFolder));
     886            rc = ERROR_NOT_SUPPORTED;
     887        }
     888    }
     889    else
     890        rc = ERROR_BUSY_DRIVE;
     891    KernReleaseExclusiveMutex(&g_MtxFolders);
     892
     893    RT_NOREF(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
     894    return rc;
     895}
     896
     897
     898/**
     899 * FS32_ATTACH worker: FSA_ATTACH_INFO
     900 */
     901static APIRET vboxSfOs2QueryAttachInfo(PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pbData, PUSHORT pcbParam)
     902{
     903    /*
     904     * Userland calls the kernel with a FSQBUFFER buffer, the kernel
     905     * fills in the first part of us and hands us &FSQBUFFER::cbFSAData
     906     * to do the rest.  We could return the share name here, for instance.
     907     */
     908    APIRET rc;
     909    USHORT cbParam = *pcbParam;
     910    if (   pszDev == NULL
     911        || (pszDev[0] != '\\' && pszDev[0] != '/'))
     912    {
     913        /* Validate the volume data and assocated folder. */
     914        AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
     915        AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
     916        PVBOXSFFOLDER pFolder = pVpFsd->pFolder;
     917        AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
     918        AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
     919
     920        /* Try copy out the data. */
     921        if (cbParam >= sizeof(USHORT) + pFolder->cchName + 1)
     922        {
     923            *pcbParam = (uint16_t)sizeof(USHORT) + pFolder->cchName + 1;
     924            cbParam = pFolder->cchName + 1;
     925            rc = KernCopyOut(pbData, &cbParam, sizeof(cbParam));
     926            if (rc != NO_ERROR)
     927                rc = KernCopyOut(pbData + sizeof(USHORT), pFolder->szName, pFolder->cchName + 1);
     928        }
     929        else
     930            rc = ERROR_BUFFER_OVERFLOW;
     931    }
     932    else
     933    {
     934        /* Looks like a device query, so return zero bytes. */
     935        if (cbParam >= sizeof(USHORT))
     936        {
     937            *pcbParam = sizeof(USHORT);
     938            cbParam   = 0;
     939            rc = KernCopyOut(pbData, &cbParam, sizeof(cbParam));
     940        }
     941        else
     942            rc = ERROR_BUFFER_OVERFLOW;
     943    }
     944
     945    RT_NOREF(pCdFsd);
     946    return rc;
     947}
     948
     949
     950DECLASM(APIRET)
     951FS32_ATTACH(ULONG fFlags, PCSZ pszDev, PVBOXSFVP pVpFsd, PVBOXSFCD pCdFsd, PBYTE pszParam, PUSHORT pcbParam)
     952{
     953    LogFlow(("FS32_ATTACH: fFlags=%#x  pszDev=%p:{%s} pVpFsd=%p pCdFsd=%p pszParam=%p pcbParam=%p\n",
     954             fFlags, pszDev, pszDev, pVpFsd, pCdFsd, pszParam, pcbParam));
     955    APIRET rc;
     956    if (pVpFsd)
     957    {
     958        PSHFLSTRING pCleanup = NULL;
     959
     960        if (fFlags == FS_ATTACH)
     961            rc = vboxSfOs2Attach(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam, &pCleanup);
     962        else if (fFlags == FSA_DETACH)
     963            rc = vboxSfOs2Detach(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
     964        else if (fFlags == FSA_ATTACH_INFO)
     965            rc = vboxSfOs2QueryAttachInfo(pszDev, pVpFsd, pCdFsd, pszParam, pcbParam);
     966        else
     967        {
     968            LogRel(("FS32_ATTACH: Unsupported fFlags value: %#x\n", fFlags));
     969            rc = ERROR_NOT_SUPPORTED;
     970        }
     971
     972        if (pCleanup)
     973            vboxSfOs2StrFree(pCleanup);
     974    }
     975    else
     976        rc = ERROR_NOT_SUPPORTED; /* We don't support device attaching. */
     977    LogFlow(("FS32_ATTACH: returns %u\n", rc));
     978    return rc;
     979}
     980
     981
     982DECLASM(APIRET)
     983FS32_VERIFYUNCNAME(ULONG uType, PCSZ pszName)
     984{
     985    LogFlow(("FS32_VERIFYUNCNAME: uType=%#x pszName=%p:{%s}\n", uType, pszName, pszName));
     986    RT_NOREF(uType); /* pass 1 or pass 2 doesn't matter to us, we've only got one 'server'. */
     987
     988    if (vboxSfOs2UncPrefixLength(pszName) > 0 )
     989        return NO_ERROR;
    62990    return ERROR_NOT_SUPPORTED;
    63991}
    64992
    65993
    66 DECLASM(int)
     994DECLASM(APIRET)
    67995FS32_FLUSHBUF(USHORT hVPB, ULONG fFlags)
    68996{
     
    721000
    731001
    74 DECLASM(int)
    75 FS32_FSINFO(ULONG fFlags, USHORT hVPB, PBYTE pbData, USHORT cbData, ULONG uLevel)
    76 {
    77     NOREF(fFlags); NOREF(hVPB); NOREF(pbData); NOREF(cbData); NOREF(uLevel);
    78     return ERROR_NOT_SUPPORTED;
    79 }
    80 
    81 
    82 DECLASM(int)
    83 FS32_FSCTL(union argdat *pArgdat, ULONG iArgType, ULONG uFunction,
     1002DECLASM(APIRET)
     1003FS32_FSINFO(ULONG fFlags, USHORT hVpb, PBYTE pbData, ULONG cbData, ULONG uLevel)
     1004{
     1005    LogFlow(("FS32_FSINFO: fFlags=%#x hVpb=%#x pbData=%p cbData=%#x uLevel=%p\n", fFlags, hVpb, pbData, cbData, uLevel));
     1006
     1007    /*
     1008     * Resolve hVpb and do parameter validation.
     1009     */
     1010    PVPFSI pVpFsi = NULL;
     1011    PVBOXSFVP pVpFsd = Fsh32GetVolParams(hVpb, &pVpFsi);
     1012    Log(("FS32_FSINFO: hVpb=%#x -> pVpFsd=%p pVpFsi=%p\n", hVpb, pVpFsd, pVpFsi));
     1013
     1014    AssertPtrReturn(pVpFsd, ERROR_SYS_INTERNAL);
     1015    AssertReturn(pVpFsd->u32Magic == VBOXSFVP_MAGIC, ERROR_SYS_INTERNAL);
     1016    PVBOXSFFOLDER pFolder = pVpFsd->pFolder;      /** @todo need to retain it behind locks. */
     1017    AssertPtrReturn(pFolder, ERROR_SYS_INTERNAL);
     1018    AssertReturn(pFolder->u32Magic == VBOXSFFOLDER_MAGIC, ERROR_SYS_INTERNAL);
     1019
     1020    APIRET rc;
     1021
     1022    /*
     1023     * Queries.
     1024     */
     1025    if (fFlags == INFO_RETREIVE)
     1026    {
     1027        /* Check that buffer/level matches up. */
     1028        switch (uLevel)
     1029        {
     1030            case FSIL_ALLOC:
     1031                if (cbData >= sizeof(FSALLOCATE))
     1032                    break;
     1033                LogFlow(("FS32_FSINOF: cbData=%u < sizeof(FSALLOCATE) -> ERROR_BUFFER_OVERFLOW\n", cbData));
     1034                return ERROR_BUFFER_OVERFLOW;
     1035
     1036            case FSIL_VOLSER:
     1037                if (cbData >= sizeof(FSINFO))
     1038                    break;
     1039                LogFlow(("FS32_FSINOF: cbData=%u < sizeof(FSINFO) -> ERROR_BUFFER_OVERFLOW\n", cbData));
     1040                return ERROR_BUFFER_OVERFLOW;
     1041
     1042            default:
     1043                LogRel(("FS32_FSINFO: Unsupported info level %u!\n", uLevel));
     1044                return ERROR_INVALID_LEVEL;
     1045        }
     1046
     1047        /* Work buffer union to keep it to a single allocation and no stack. */
     1048        union FsInfoBufs
     1049        {
     1050            struct
     1051            {
     1052                SHFLCREATEPARMS Params;
     1053                union
     1054                {
     1055                    SHFLSTRING Path;
     1056                    uint8_t    abPadding[SHFLSTRING_HEADER_SIZE + 4];
     1057                };
     1058            } Open;
     1059            struct
     1060            {
     1061                SHFLVOLINFO VolInfo;
     1062                union
     1063                {
     1064                    FSALLOCATE  Alloc;
     1065                    FSINFO      FsInfo;
     1066                };
     1067            } Info;
     1068        } *pu = (union FsInfoBufs *)VbglR0PhysHeapAlloc(sizeof(*pu));
     1069        if (!pu)
     1070            return ERROR_NOT_ENOUGH_MEMORY;
     1071
     1072        /*
     1073         * To get the info we need to open the root of the folder.
     1074         */
     1075        RT_ZERO(pu->Open.Params);
     1076        pu->Open.Params.CreateFlags = SHFL_CF_DIRECTORY   | SHFL_CF_ACT_FAIL_IF_NEW  | SHFL_CF_ACT_OPEN_IF_EXISTS
     1077                                    | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
     1078        pu->Open.Path.u16Size   = 3;
     1079        pu->Open.Path.u16Length = 2;
     1080        pu->Open.Path.String.utf8[0] = '\\';
     1081        pu->Open.Path.String.utf8[1] = '.';
     1082        pu->Open.Path.String.utf8[2] = '\0';
     1083
     1084        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, &pu->Open.Path, &pu->Open.Params);
     1085        LogFlow(("FS32_FSINFO: VbglR0SfCreate -> %Rrc Result=%d Handle=%#RX64\n", vrc, pu->Open.Params.Result, pu->Open.Params.Handle));
     1086        if (   RT_SUCCESS(vrc)
     1087            && pu->Open.Params.Handle != SHFL_HANDLE_NIL)
     1088        {
     1089            SHFLHANDLE hHandle = pu->Open.Params.Handle;
     1090
     1091            RT_ZERO(pu->Info.VolInfo);
     1092            uint32_t cbBuf = sizeof(pu->Info.VolInfo);
     1093            vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, hHandle, SHFL_INFO_VOLUME | SHFL_INFO_GET,
     1094                                 &cbBuf, (PSHFLDIRINFO)&pu->Info.VolInfo);
     1095            if (RT_SUCCESS(vrc))
     1096            {
     1097                /*
     1098                 * Construct and copy out the requested info.
     1099                 */
     1100                if (uLevel == FSIL_ALLOC)
     1101                {
     1102                    pu->Info.Alloc.idFileSystem = 0; /* unknown */
     1103                    pu->Info.Alloc.cSectorUnit  = pu->Info.VolInfo.ulBytesPerAllocationUnit / RT_MAX(pu->Info.VolInfo.ulBytesPerSector, 1);
     1104                    pu->Info.Alloc.cUnit        = (uint32_t)(pu->Info.VolInfo.ullTotalAllocationBytes  / RT_MAX(pu->Info.VolInfo.ulBytesPerAllocationUnit, 1));
     1105                    pu->Info.Alloc.cUnitAvail   = (uint32_t)(pu->Info.VolInfo.ullAvailableAllocationBytes  / RT_MAX(pu->Info.VolInfo.ulBytesPerAllocationUnit, 1));
     1106                    pu->Info.Alloc.cbSector     = (uint16_t)(pu->Info.VolInfo.ulBytesPerSector);
     1107                    rc = KernCopyOut(pbData, &pu->Info.Alloc, sizeof(pu->Info.Alloc));
     1108                }
     1109                else
     1110                {
     1111                    RT_ZERO(pu->Info.FsInfo);
     1112                    pu->Info.FsInfo.vol.cch = (uint8_t)RT_MIN(pFolder->cchName, sizeof(pu->Info.FsInfo.vol.szVolLabel) - 1);
     1113                    memcpy(pu->Info.FsInfo.vol.szVolLabel, pFolder->szName, pu->Info.FsInfo.vol.cch);
     1114                    *(uint32_t *)&pu->Info.FsInfo.fdateCreation = pu->Info.VolInfo.ulSerial;
     1115                    rc = KernCopyOut(pbData, &pu->Info.FsInfo, sizeof(pu->Info.FsInfo));
     1116                }
     1117            }
     1118            else
     1119            {
     1120                LogRel(("FS32_FSINFO: VbglR0SfFsInfo/SHFL_INFO_VOLUME failed: %Rrc\n", rc));
     1121                rc = ERROR_GEN_FAILURE;
     1122            }
     1123
     1124            vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, hHandle);
     1125            AssertRC(vrc);
     1126        }
     1127        else
     1128            rc = ERROR_GEN_FAILURE;
     1129
     1130        VbglR0PhysHeapFree(pu);
     1131    }
     1132    /*
     1133     * We don't allow setting anything.
     1134     */
     1135    else if (fFlags == INFO_SET)
     1136    {
     1137        LogRel(("FS32_FSINFO: Attempting to set volume info (uLevel=%u, cbData=%#x) -> ERROR_ACCESS_DENIED\n", uLevel, cbData));
     1138        rc = ERROR_ACCESS_DENIED;
     1139    }
     1140    else
     1141    {
     1142        LogRel(("FS32_FSINFO: Unknown flags: %#x\n", fFlags));
     1143        rc = ERROR_SYS_INTERNAL;
     1144    }
     1145
     1146    LogFlow(("FS32_FSINFO: returns %#x\n", rc));
     1147    return rc;
     1148}
     1149
     1150
     1151DECLASM(APIRET)
     1152FS32_FSCTL(union argdat *pArgData, ULONG iArgType, ULONG uFunction,
    841153           PVOID pvParm, USHORT cbParm, PUSHORT pcbParmIO,
    851154           PVOID pvData, USHORT cbData, PUSHORT pcbDataIO)
    861155{
    87     NOREF(pArgdat); NOREF(iArgType); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
     1156    LogFlow(("FS32_FSCTL: pArgData=%p iArgType=%#x uFunction=%#x pvParam=%p cbParam=%#x pcbParmIO=%p pvData=%p cbData=%#x pcbDataIO=%p\n",
     1157             pArgData, iArgType, uFunction, pvParm, cbParm, pcbParmIO, pvData, cbData, pcbDataIO));
     1158    NOREF(pArgData); NOREF(iArgType); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
    881159    NOREF(pvData); NOREF(cbData); NOREF(pcbDataIO);
    891160    return ERROR_NOT_SUPPORTED;
     
    911162
    921163
    93 DECLASM(int)
     1164DECLASM(APIRET)
    941165FS32_PROCESSNAME(PSZ pszName)
    951166{
     1167    LogFlow(("FS32_PROCESSNAME: '%s'\n", pszName));
    961168    NOREF(pszName);
    971169    return NO_ERROR;
     
    991171
    1001172
    101 DECLASM(int)
    102 FS32_CHDIR(ULONG fFlags, PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszDir, USHORT iCurDirEnd)
    103 {
    104     NOREF(fFlags); NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszDir); NOREF(iCurDirEnd);
     1173DECLASM(APIRET)
     1174FS32_CHDIR(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd)
     1175{
     1176    LogFlow(("FS32_CHDIR: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszDir=%p:{%s} offCurDirEnd=%d\n",
     1177             fFlags, pCdFsi, pCdFsi ? pCdFsi->cdi_hVPB : 0xffff, pCdFsi ? pCdFsi->cdi_curdir : "", pCdFsd, pszDir, pszDir, offCurDirEnd));
     1178
     1179    /*
     1180     * We do not keep any information about open directory, just verify
     1181     * them before they are CD'ed into and when asked to revalidate them.
     1182     * If there were any path walking benefits, we could consider opening the
     1183     * directory and keeping it open, but there isn't, so we don't do that.
     1184     */
     1185    APIRET rc = NO_ERROR;
     1186    if (   fFlags == CD_EXPLICIT
     1187        || fFlags == CD_VERIFY)
     1188    {
     1189        if (fFlags == CD_VERIFY)
     1190            pszDir = pCdFsi->cdi_curdir;
     1191
     1192        PVBOXSFFOLDER pFolder;
     1193        PSHFLSTRING   pStrFolderPath;
     1194        rc = vboxSfOs2ResolvePath(pszDir, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     1195        if (rc == NO_ERROR)
     1196        {
     1197            SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     1198            if (pParams)
     1199            {
     1200                RT_ZERO(*pParams);
     1201                pParams->CreateFlags = SHFL_CF_LOOKUP;
     1202
     1203                int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     1204                LogFlow(("FS32_CHDIR: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
     1205                if (RT_SUCCESS(vrc))
     1206                {
     1207                    switch (pParams->Result)
     1208                    {
     1209                        case SHFL_FILE_EXISTS:
     1210                            if (RTFS_IS_DIRECTORY(pParams->Info.Attr.fMode))
     1211                                rc = NO_ERROR;
     1212                            else
     1213                                rc = ERROR_ACCESS_DENIED;
     1214                            break;
     1215
     1216                        case SHFL_PATH_NOT_FOUND:
     1217                            rc = ERROR_PATH_NOT_FOUND;
     1218                            break;
     1219
     1220                        default:
     1221                        case SHFL_FILE_NOT_FOUND:
     1222                            rc = ERROR_FILE_NOT_FOUND;
     1223                            break;
     1224                    }
     1225                }
     1226                else
     1227                    rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
     1228                VbglR0PhysHeapFree(pParams);
     1229            }
     1230            else
     1231                rc = ERROR_NOT_ENOUGH_MEMORY;
     1232            vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     1233        }
     1234    }
     1235    else if (fFlags == CD_FREE)
     1236    {
     1237        /* nothing to do here. */
     1238    }
     1239    else
     1240    {
     1241        LogRel(("FS32_CHDIR: Unexpected fFlags value: %#x\n", fFlags));
     1242        rc = ERROR_NOT_SUPPORTED;
     1243    }
     1244
     1245    LogFlow(("FS32_CHDIR: returns %u\n", rc));
     1246    return rc;
     1247}
     1248
     1249
     1250DECLASM(APIRET)
     1251FS32_MKDIR(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd, PEAOP pEaOp, ULONG fFlags)
     1252{
     1253    LogFlow(("FS32_MKDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} pEAOp=%p fFlags=%#x\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd, pEaOp, fFlags));
     1254
     1255    /*
     1256     * We don't do EAs.
     1257     */
     1258    APIRET rc;
     1259    if (pEaOp == NULL)
     1260    {
     1261        /*
     1262         * Resolve the path.
     1263         */
     1264        PVBOXSFFOLDER pFolder;
     1265        PSHFLSTRING   pStrFolderPath;
     1266        rc = vboxSfOs2ResolvePath(pszDir, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     1267        if (rc == NO_ERROR)
     1268        {
     1269            /*
     1270             * The silly interface for creating directories amounts an open call that
     1271             * fails if it exists and we get a file handle back that needs closing.  Sigh.
     1272             */
     1273            SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     1274            if (pParams != NULL)
     1275            {
     1276                RT_ZERO(*pParams);
     1277                pParams->CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW | SHFL_CF_ACT_FAIL_IF_EXISTS
     1278                                     | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_DENYNONE;
     1279
     1280                int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     1281                LogFlow(("FS32_MKDIR: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
     1282                if (RT_SUCCESS(vrc))
     1283                {
     1284                    switch (pParams->Result)
     1285                    {
     1286                        case SHFL_FILE_CREATED:
     1287                            if (pParams->Handle != SHFL_HANDLE_NIL)
     1288                            {
     1289                                vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pParams->Handle);
     1290                                AssertRC(vrc);
     1291                            }
     1292                            rc = NO_ERROR;
     1293                            break;
     1294
     1295                        case SHFL_FILE_EXISTS:
     1296                            rc = ERROR_ACCESS_DENIED;
     1297                            break;
     1298
     1299                        case SHFL_PATH_NOT_FOUND:
     1300                            rc = ERROR_PATH_NOT_FOUND;
     1301                            break;
     1302
     1303                        default:
     1304                        case SHFL_FILE_NOT_FOUND:
     1305                            rc = ERROR_FILE_NOT_FOUND;
     1306                            break;
     1307                    }
     1308                }
     1309                else if (vrc == VERR_ALREADY_EXISTS)
     1310                    rc = ERROR_ACCESS_DENIED;
     1311                else
     1312                    rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
     1313                VbglR0PhysHeapFree(pParams);
     1314            }
     1315            else
     1316                rc = ERROR_NOT_ENOUGH_MEMORY;
     1317            vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     1318        }
     1319    }
     1320    else
     1321    {
     1322        Log(("FS32_MKDIR: EAs not supported\n"));
     1323        rc = ERROR_EAS_NOT_SUPPORTED;
     1324    }
     1325
     1326    RT_NOREF_PV(pCdFsi);
     1327    LogFlow(("FS32_RMDIR: returns %u\n", rc));
     1328    return rc;
     1329}
     1330
     1331
     1332DECLASM(APIRET)
     1333FS32_RMDIR(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszDir, LONG offCurDirEnd)
     1334{
     1335    LogFlow(("FS32_RMDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} offCurDirEnd=%d\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd));
     1336
     1337    /*
     1338     * Resolve the path.
     1339     */
     1340    PVBOXSFFOLDER pFolder;
     1341    PSHFLSTRING   pStrFolderPath;
     1342    APIRET rc = vboxSfOs2ResolvePath(pszDir, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     1343    if (rc == NO_ERROR)
     1344    {
     1345        int vrc = VbglR0SfRemove(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, SHFL_REMOVE_DIR);
     1346        LogFlow(("FS32_RMDIR: VbglR0SfRemove -> %Rrc\n", rc));
     1347        if (RT_SUCCESS(vrc))
     1348            rc = NO_ERROR;
     1349        else
     1350            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
     1351
     1352        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     1353    }
     1354
     1355    RT_NOREF_PV(pCdFsi);
     1356    LogFlow(("FS32_RMDIR: returns %u\n", rc));
     1357    return rc;
     1358}
     1359
     1360
     1361DECLASM(APIRET)
     1362FS32_COPY(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszSrc, LONG offSrcCurDirEnd,
     1363          PCSZ pszDst, LONG offDstCurDirEnd, ULONG uNameType)
     1364{
     1365    LogFlow(("FS32_COPY: fFlags=%#x pCdFsi=%p pCdFsd=%p pszSrc=%p:{%s} offSrcCurDirEnd=%d pszDst=%p:{%s} offDstCurDirEnd=%d uNameType=%#x\n",
     1366             fFlags, pCdFsi, pCdFsd, pszSrc, pszSrc, offSrcCurDirEnd, pszDst, pszDst, offDstCurDirEnd, uNameType));
     1367    NOREF(fFlags); NOREF(pCdFsi); NOREF(pCdFsd); NOREF(pszSrc); NOREF(offSrcCurDirEnd);
     1368    NOREF(pszDst); NOREF(offDstCurDirEnd); NOREF(uNameType);
     1369
     1370    /* Let DOSCALL1.DLL do the work for us till we get a host side function for doing this. */
     1371    return ERROR_CANNOT_COPY;
     1372}
     1373
     1374
     1375DECLASM(APIRET)
     1376FS32_MOVE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszSrc, LONG offSrcCurDirEnd, PCSZ pszDst, LONG offDstCurDirEnd, ULONG uNameType)
     1377{
     1378    LogFlow(("FS32_MOVE: pCdFsi=%p pCdFsd=%p pszSrc=%p:{%s} offSrcCurDirEnd=%d pszDst=%p:{%s} offDstcurDirEnd=%d uNameType=%#x\n",
     1379             pCdFsi, pCdFsd, pszSrc, pszSrc, offSrcCurDirEnd, pszDst, pszDst, offDstCurDirEnd, uNameType));
     1380
     1381    /*
     1382     * Resolve the source and destination paths and check that they
     1383     * refer to the same folder.
     1384     */
     1385    PVBOXSFFOLDER pSrcFolder;
     1386    PSHFLSTRING   pSrcFolderPath;
     1387    APIRET rc = vboxSfOs2ResolvePath(pszSrc, pCdFsd, offSrcCurDirEnd, &pSrcFolder, &pSrcFolderPath);
     1388    if (rc == NO_ERROR)
     1389    {
     1390        PVBOXSFFOLDER pDstFolder;
     1391        PSHFLSTRING   pDstFolderPath;
     1392        rc = vboxSfOs2ResolvePath(pszDst, pCdFsd, offDstCurDirEnd, &pDstFolder, &pDstFolderPath);
     1393        if (rc == NO_ERROR)
     1394        {
     1395            if (pSrcFolder == pDstFolder)
     1396            {
     1397                /*
     1398                 * Do the renaming.
     1399                 * Note! Requires 6.0.0beta2+ or 5.2.24+ host for renaming files.
     1400                 */
     1401                int vrc = VbglR0SfRename(&g_SfClient, &pSrcFolder->hHostFolder, pSrcFolderPath, pDstFolderPath,
     1402                                         SHFL_RENAME_FILE | SHFL_RENAME_DIR);
     1403                if (RT_SUCCESS(vrc))
     1404                    rc = NO_ERROR;
     1405                else
     1406                {
     1407                    Log(("FS32_MOVE: VbglR0SfRename failed: %Rrc\n", rc));
     1408                    rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
     1409                }
     1410            }
     1411            else
     1412            {
     1413                Log(("FS32_MOVE: source folder '%s' != destiation folder '%s'\n", pSrcFolder->szName, pDstFolder->szName));
     1414                rc = ERROR_NOT_SAME_DEVICE;
     1415            }
     1416            vboxSfOs2ReleasePathAndFolder(pDstFolderPath, pDstFolder);
     1417        }
     1418        vboxSfOs2ReleasePathAndFolder(pSrcFolderPath, pSrcFolder);
     1419    }
     1420
     1421    RT_NOREF_PV(pCdFsi); RT_NOREF_PV(uNameType);
     1422    return rc;
     1423}
     1424
     1425
     1426DECLASM(APIRET)
     1427FS32_DELETE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszFile, LONG offCurDirEnd)
     1428{
     1429    LogFlow(("FS32_DELETE: pCdFsi=%p pCdFsd=%p pszFile=%p:{%s} offCurDirEnd=%d\n", pCdFsi, pCdFsd, pszFile, pszFile, offCurDirEnd));
     1430
     1431    /*
     1432     * Resolve the path.
     1433     */
     1434    PVBOXSFFOLDER pFolder;
     1435    PSHFLSTRING   pStrFolderPath;
     1436    APIRET rc = vboxSfOs2ResolvePath(pszFile, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     1437    if (rc == NO_ERROR)
     1438    {
     1439        int vrc = VbglR0SfRemove(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, SHFL_REMOVE_FILE);
     1440        LogFlow(("FS32_DELETE: VbglR0SfRemove -> %Rrc\n", rc));
     1441        if (RT_SUCCESS(vrc))
     1442            rc = NO_ERROR;
     1443        else if (rc == VERR_FILE_NOT_FOUND)
     1444            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
     1445
     1446        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     1447    }
     1448
     1449    RT_NOREF_PV(pCdFsi);
     1450    LogFlow(("FS32_DELETE: returns %u\n", rc));
     1451    return rc;
     1452}
     1453
     1454
     1455
     1456/**
     1457 * Worker for FS32_PATHINFO that handles file stat setting.
     1458 *
     1459 * @returns OS/2 status code
     1460 * @param   pFolder         The folder.
     1461 * @param   hHostFile       The host file handle.
     1462 * @param   fAttribs        The attributes to set.
     1463 * @param   pTimestamps     Pointer to the timestamps.  NULL if none should be
     1464 *                          modified.
     1465 * @param   pObjInfoBuf     Buffer to use when setting the attributes (host will
     1466 *                          return current info upon successful return).
     1467 */
     1468APIRET vboxSfOs2SetInfoCommonWorker(PVBOXSFFOLDER pFolder, SHFLHANDLE hHostFile, ULONG fAttribs,
     1469                                    PFILESTATUS pTimestamps, PSHFLFSOBJINFO pObjInfoBuf)
     1470{
     1471    /*
     1472     * Validate the data a little and convert it to host speak.
     1473     * When the date part is zero, the timestamp should not be updated.
     1474     */
     1475    RT_ZERO(*pObjInfoBuf);
     1476    uint16_t cDelta = vboxSfOs2GetLocalTimeDelta();
     1477
     1478    /** @todo should we validate attributes?   */
     1479    pObjInfoBuf->Attr.fMode = (fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
     1480
     1481    if (pTimestamps)
     1482    {
     1483        if (   *(uint16_t *)&pTimestamps->fdateCreation   != 0
     1484            && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateCreation,   pTimestamps->ftimeCreation,   cDelta, &pObjInfoBuf->BirthTime))
     1485        {
     1486            LogRel(("vboxSfOs2SetInfoCommonWorker: Bad creation timestamp: %u-%u-%u %u:%u:%u\n",
     1487                    pTimestamps->fdateCreation.year + 1980, pTimestamps->fdateCreation.month, pTimestamps->fdateCreation.day,
     1488                    pTimestamps->ftimeCreation.hours, pTimestamps->ftimeCreation.minutes, pTimestamps->ftimeCreation.twosecs * 2));
     1489            return ERROR_INVALID_PARAMETER;
     1490        }
     1491        if (   *(uint16_t *)&pTimestamps->fdateLastAccess != 0
     1492            && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateLastAccess, pTimestamps->ftimeLastAccess, cDelta, &pObjInfoBuf->AccessTime))
     1493        {
     1494            LogRel(("vboxSfOs2SetInfoCommonWorker: Bad last access timestamp: %u-%u-%u %u:%u:%u\n",
     1495                    pTimestamps->fdateLastAccess.year + 1980, pTimestamps->fdateLastAccess.month, pTimestamps->fdateLastAccess.day,
     1496                    pTimestamps->ftimeLastAccess.hours, pTimestamps->ftimeLastAccess.minutes, pTimestamps->ftimeLastAccess.twosecs * 2));
     1497            return ERROR_INVALID_PARAMETER;
     1498        }
     1499        if (   *(uint16_t *)&pTimestamps->fdateLastWrite  != 0
     1500            && !vboxSfOs2DateTimeToTimeSpec(pTimestamps->fdateLastWrite,  pTimestamps->ftimeLastWrite,  cDelta, &pObjInfoBuf->ModificationTime))
     1501        {
     1502            LogRel(("vboxSfOs2SetInfoCommonWorker: Bad last access timestamp: %u-%u-%u %u:%u:%u\n",
     1503                    pTimestamps->fdateLastWrite.year + 1980, pTimestamps->fdateLastWrite.month, pTimestamps->fdateLastWrite.day,
     1504                    pTimestamps->ftimeLastWrite.hours, pTimestamps->ftimeLastWrite.minutes, pTimestamps->ftimeLastWrite.twosecs * 2));
     1505            return ERROR_INVALID_PARAMETER;
     1506        }
     1507    }
     1508
     1509    /*
     1510     * Call the host to do the updating.
     1511     */
     1512    uint32_t cbBuf = sizeof(*pObjInfoBuf);
     1513    int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, hHostFile, SHFL_INFO_SET | SHFL_INFO_FILE,
     1514                             &cbBuf, (SHFLDIRINFO *)pObjInfoBuf);
     1515    LogFlow(("vboxSfOs2SetFileInfo: VbglR0SfFsInfo -> %Rrc\n", vrc));
     1516
     1517    if (RT_SUCCESS(vrc))
     1518        return NO_ERROR;
     1519    return vboxSfOs2ConvertStatusToOs2(vrc, ERROR_ACCESS_DENIED);
     1520}
     1521
     1522
     1523/**
     1524 * Worker for FS32_FILEATTRIBUTE and FS32_PATHINFO that handles setting stuff.
     1525 *
     1526 * @returns OS/2 status code.
     1527 * @param   pFolder             The folder.
     1528 * @param   pFolderPath         The path within the folder.
     1529 * @param   fAttribs            New file attributes.
     1530 * @param   pTimestamps         New timestamps.  May be NULL.
     1531 */
     1532static APIRET vboxSfOs2SetPathInfoWorker(PVBOXSFFOLDER pFolder, PSHFLSTRING pFolderPath, ULONG fAttribs, PFILESTATUS pTimestamps)
     1533
     1534{
     1535    /*
     1536     * In order to do anything we need to open the object.
     1537     */
     1538    APIRET rc;
     1539    SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     1540    if (pParams)
     1541    {
     1542        RT_ZERO(*pParams);
     1543        pParams->CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW
     1544                             | SHFL_CF_ACCESS_ATTR_READWRITE | SHFL_CF_ACCESS_DENYNONE | SHFL_CF_ACCESS_NONE;
     1545
     1546        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pFolderPath, pParams);
     1547        LogFlow(("vboxSfOs2SetPathInfoWorker: VbglR0SfCreate -> %Rrc Result=%d Handle=%#RX64 fMode=%#x\n",
     1548                 vrc, pParams->Result, pParams->Handle, pParams->Info.Attr.fMode));
     1549        if (   vrc == VERR_IS_A_DIRECTORY
     1550            || (   RT_SUCCESS(vrc)
     1551                && pParams->Handle == SHFL_HANDLE_NIL
     1552                && RTFS_IS_DIRECTORY(pParams->Info.Attr.fMode)))
     1553        {
     1554            RT_ZERO(*pParams);
     1555            pParams->CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW
     1556                                 | SHFL_CF_ACCESS_ATTR_READWRITE | SHFL_CF_ACCESS_DENYNONE | SHFL_CF_ACCESS_NONE;
     1557            vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pFolderPath, pParams);
     1558            LogFlow(("vboxSfOs2SetPathInfoWorker: VbglR0SfCreate#2 -> %Rrc Result=%d Handle=%#RX64 fMode=%#x\n",
     1559                     vrc, pParams->Result, pParams->Handle, pParams->Info.Attr.fMode));
     1560        }
     1561        if (RT_SUCCESS(vrc))
     1562        {
     1563            switch (pParams->Result)
     1564            {
     1565                case SHFL_FILE_EXISTS:
     1566                    if (pParams->Handle != SHFL_HANDLE_NIL)
     1567                    {
     1568                        /*
     1569                         * Join up with FS32_FILEINFO to do the actual setting.
     1570                         */
     1571                        rc = vboxSfOs2SetInfoCommonWorker(pFolder, pParams->Handle, fAttribs, pTimestamps, &pParams->Info);
     1572
     1573                        vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pParams->Handle);
     1574                        AssertRC(vrc);
     1575                    }
     1576                    else
     1577                    {
     1578                        LogRel(("vboxSfOs2SetPathInfoWorker: No handle! fMode=%#x\n", pParams->Info.Attr.fMode));
     1579                        rc = ERROR_SYS_INTERNAL;
     1580                    }
     1581                    break;
     1582
     1583                case SHFL_PATH_NOT_FOUND:
     1584                    rc = ERROR_PATH_NOT_FOUND;
     1585                    break;
     1586
     1587                default:
     1588                case SHFL_FILE_NOT_FOUND:
     1589                    rc = ERROR_FILE_NOT_FOUND;
     1590                    break;
     1591            }
     1592        }
     1593        else
     1594            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
     1595        VbglR0PhysHeapFree(pParams);
     1596    }
     1597    else
     1598        rc = ERROR_NOT_ENOUGH_MEMORY;
     1599    return rc;
     1600}
     1601
     1602
     1603DECLASM(APIRET)
     1604FS32_FILEATTRIBUTE(ULONG fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszName, LONG offCurDirEnd, PUSHORT pfAttr)
     1605{
     1606    LogFlow(("FS32_FILEATTRIBUTE: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pfAttr=%p\n",
     1607             fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszName, pszName, offCurDirEnd, pfAttr));
     1608    RT_NOREF(offCurDirEnd);
     1609
     1610    APIRET rc;
     1611    if (   fFlags == FA_RETRIEVE
     1612        || fFlags == FA_SET)
     1613    {
     1614        PVBOXSFFOLDER pFolder;
     1615        PSHFLSTRING   pStrFolderPath;
     1616        rc = vboxSfOs2ResolvePath(pszName, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     1617        LogRel(("FS32_FILEATTRIBUTE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
     1618        if (rc == NO_ERROR)
     1619        {
     1620            if (fFlags == FA_RETRIEVE)
     1621            {
     1622                /*
     1623                 * Query it.
     1624                 */
     1625                SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     1626                if (pParams)
     1627                {
     1628                    RT_ZERO(*pParams);
     1629                    pParams->CreateFlags = SHFL_CF_LOOKUP;
     1630
     1631                    int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     1632                    LogFlow(("FS32_FILEATTRIBUTE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
     1633                    if (RT_SUCCESS(vrc))
     1634                    {
     1635                        switch (pParams->Result)
     1636                        {
     1637                            case SHFL_FILE_EXISTS:
     1638                                *pfAttr = (uint16_t)((pParams->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
     1639                                rc = NO_ERROR;
     1640                                break;
     1641
     1642                            case SHFL_PATH_NOT_FOUND:
     1643                                rc = ERROR_PATH_NOT_FOUND;
     1644                                break;
     1645
     1646                            default:
     1647                            case SHFL_FILE_NOT_FOUND:
     1648                                rc = ERROR_FILE_NOT_FOUND;
     1649                                break;
     1650                        }
     1651                    }
     1652                    else
     1653                        rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_FILE_NOT_FOUND);
     1654                    VbglR0PhysHeapFree(pParams);
     1655                }
     1656                else
     1657                    rc = ERROR_NOT_ENOUGH_MEMORY;
     1658            }
     1659            else
     1660            {
     1661                /*
     1662                 * Set the info.  Join paths with FS32_PATHINFO.
     1663                 */
     1664                rc = vboxSfOs2SetPathInfoWorker(pFolder, pStrFolderPath, *pfAttr, NULL);
     1665            }
     1666            vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     1667        }
     1668    }
     1669    else
     1670    {
     1671        LogRel(("FS32_FILEATTRIBUTE: Unknwon flag value: %#x\n", fFlags));
     1672        rc = ERROR_NOT_SUPPORTED;
     1673    }
     1674    LogFlow(("FS32_FILEATTRIBUTE: returns %u\n", rc));
     1675    return rc;
     1676}
     1677
     1678
     1679/**
     1680 * Creates an empty full EA list given a GEALIST and info level.
     1681 *
     1682 * @returns OS/2 status code.
     1683 * @param   pEaOp           Kernel copy of the EA request with flattened pointers.
     1684 * @param   uLevel          The info level being queried.
     1685 * @param   pcbWritten      Where to return the length of the resulting list.  Optional.
     1686 * @param   poffError       User buffer address of EAOP.oError for reporting GEALIST issues.
     1687 */
     1688APIRET vboxSfOs2MakeEmptyEaListEx(PEAOP pEaOp, ULONG uLevel, uint32_t *pcbWritten, ULONG *poffError)
     1689{
     1690    ULONG  cbDstList;
     1691    APIRET rc;
     1692
     1693    /*
     1694     * Levels 8 and 5 are simple.
     1695     */
     1696    if (   pEaOp->fpGEAList == NULL
     1697        || uLevel == FI_LVL_EAS_FULL_8
     1698        || uLevel == FI_LVL_EAS_FULL_5)
     1699    {
     1700        Log2(("vboxSfOs2MakeEmptyEaList: #1\n"));
     1701        cbDstList = RT_UOFFSET_AFTER(FEALIST, cbList);
     1702        rc = NO_ERROR;
     1703    }
     1704    /*
     1705     * For levels 3 and 4 we have to do work when a request list is present.
     1706     */
     1707    else
     1708    {
     1709        ULONG cbGetEasLeft = 0;
     1710        rc = KernCopyIn(&cbGetEasLeft, &pEaOp->fpGEAList->cbList, sizeof(pEaOp->fpGEAList->cbList));
     1711        ULONG cbFullEasLeft = 0;
     1712        if (rc == NO_ERROR)
     1713            rc = KernCopyIn(&cbFullEasLeft, &pEaOp->fpFEAList->cbList, sizeof(cbFullEasLeft));
     1714        if (   rc == NO_ERROR
     1715            && cbGetEasLeft  >= sizeof(pEaOp->fpGEAList->cbList)
     1716            && cbFullEasLeft >= sizeof(pEaOp->fpFEAList->cbList))
     1717        {
     1718            cbGetEasLeft  -= sizeof(pEaOp->fpGEAList->cbList);
     1719            cbFullEasLeft -= sizeof(pEaOp->fpFEAList->cbList);
     1720
     1721            char *pszNameBuf = (char *)RTMemAlloc(256 + 1);
     1722            if (!pszNameBuf)
     1723                return ERROR_NOT_ENOUGH_MEMORY;
     1724            /* Start of no-return zone. */
     1725
     1726            uint8_t const *pbSrc = (uint8_t const *)&pEaOp->fpGEAList->list[0]; /* user buffer! */
     1727            uint8_t       *pbDst = (uint8_t       *)&pEaOp->fpFEAList->list[0]; /* user buffer! */
     1728            Log2(("vboxSfOs2MakeEmptyEaList: %p LB %#x -> %p LB %#x...\n", pbSrc, cbGetEasLeft, pbDst, cbFullEasLeft));
     1729            while (cbGetEasLeft > 0)
     1730            {
     1731                /*
     1732                 * pbSrc: GEA: BYTE cbName; char szName[];
     1733                 */
     1734                /* Get name length. */
     1735                uint8_t cbName = 0;
     1736                rc = KernCopyIn(&cbName, pbSrc, sizeof(cbName));
     1737                Log3(("vboxSfOs2MakeEmptyEaList: cbName=%#x rc=%u\n", cbName, rc));
     1738                if (rc != NO_ERROR)
     1739                    break;
     1740                pbSrc++;
     1741                cbGetEasLeft--;
     1742                if (cbName + 1 > cbGetEasLeft)
     1743                {
     1744                    cbDstList = pbSrc - 1 - (uint8_t *)pEaOp->fpGEAList;
     1745                    rc = KernCopyOut(poffError, &cbDstList, sizeof(pEaOp->oError));
     1746                    if (rc == NO_ERROR)
     1747                        rc = ERROR_EA_LIST_INCONSISTENT;
     1748                    Log(("vboxSfOs2MakeEmptyEaList: ERROR_EA_LIST_INCONSISTENT\n"));
     1749                    break;
     1750                }
     1751
     1752                /* Copy in name. */
     1753                rc = KernCopyIn(pszNameBuf, pbSrc, cbName + 1);
     1754                if (rc != NO_ERROR)
     1755                    break;
     1756                Log3(("vboxSfOs2MakeEmptyEaList: szName: %.*Rhxs\n", cbName + 1, pszNameBuf));
     1757                if ((char *)memchr(pszNameBuf, '\0', cbName) != &pszNameBuf[cbName])
     1758                {
     1759                    cbDstList = pbSrc - 1 - (uint8_t *)pEaOp->fpGEAList;
     1760                    rc = KernCopyOut(poffError, &cbDstList, sizeof(pEaOp->oError));
     1761                    if (rc == NO_ERROR)
     1762                        rc = ERROR_INVALID_EA_NAME;
     1763                    Log(("vboxSfOs2MakeEmptyEaList: ERROR_INVALID_EA_NAME\n"));
     1764                    break;
     1765                }
     1766
     1767                /* Skip input. */
     1768                cbGetEasLeft -= cbName + 1;
     1769                pbSrc        += cbName + 1;
     1770
     1771                /*
     1772                 * Construct and emit output.
     1773                 * Note! We should technically skip duplicates here, but who cares...
     1774                 */
     1775                if (cbName > 0)
     1776                {
     1777                    FEA Result;
     1778                    if (sizeof(Result) + cbName + 1 > cbFullEasLeft)
     1779                    {
     1780                        Log(("vboxSfOs2MakeEmptyEaList: ERROR_BUFFER_OVERFLOW (%#x vs %#x)\n", sizeof(Result) + cbName + 1, cbFullEasLeft));
     1781                        rc = ERROR_BUFFER_OVERFLOW;
     1782                        break;
     1783                    }
     1784                    cbFullEasLeft -= sizeof(Result) + cbName + 1;
     1785
     1786                    Result.fEA     = 0;
     1787                    Result.cbName  = cbName;
     1788                    Result.cbValue = 0;
     1789                    rc = KernCopyOut(pbDst, &Result, sizeof(Result));
     1790                    if (rc != NO_ERROR)
     1791                        break;
     1792                    pbDst += sizeof(Result);
     1793
     1794                    rc = KernCopyOut(pbDst, pszNameBuf, cbName + 1);
     1795                    if (rc != NO_ERROR)
     1796                        break;
     1797                    pbDst += cbName + 1;
     1798                }
     1799            } /* (while more GEAs) */
     1800
     1801            /* End of no-return zone. */
     1802            RTMemFree(pszNameBuf);
     1803
     1804            cbDstList = (uintptr_t)pbDst - (uintptr_t)pEaOp->fpFEAList;
     1805        }
     1806        else
     1807        {
     1808            if (rc == NO_ERROR)
     1809                rc = ERROR_BUFFER_OVERFLOW;
     1810            cbDstList = 0; /* oh, shut up. */
     1811        }
     1812
     1813    }
     1814
     1815    /* Set the list length. */
     1816    if (rc == NO_ERROR)
     1817        rc = KernCopyOut(&pEaOp->fpFEAList->cbList, &cbDstList, sizeof(pEaOp->fpFEAList->cbList));
     1818
     1819    if (pcbWritten)
     1820        *pcbWritten = cbDstList;
     1821
     1822    Log(("vboxSfOs2MakeEmptyEaList: return %u (cbDstList=%#x)\n", rc, cbDstList));
     1823    return rc;
     1824}
     1825
     1826
     1827
     1828/**
     1829 * Creates an empty full EA list given a GEALIST and info level.
     1830 *
     1831 * @returns OS/2 status code.
     1832 * @param   pEaOp           The EA request.  User buffer.
     1833 * @param   uLevel          The info level being queried.
     1834 */
     1835DECL_NO_INLINE(RT_NOTHING, APIRET)
     1836vboxSfOs2MakeEmptyEaList(PEAOP pEaOp, ULONG uLevel)
     1837{
     1838    /*
     1839     * Copy the user request into memory, do pointer conversion, and
     1840     * join extended function version.
     1841     */
     1842    EAOP EaOp = { NULL, NULL, 0 };
     1843    APIRET rc = KernCopyIn(&EaOp, pEaOp, sizeof(EaOp));
     1844    if (rc == NO_ERROR)
     1845    {
     1846        Log2(("vboxSfOs2MakeEmptyEaList: #0: %p %p %#x\n", EaOp.fpGEAList, EaOp.fpFEAList, EaOp.oError));
     1847        EaOp.fpFEAList = (PFEALIST)KernSelToFlat((uintptr_t)EaOp.fpFEAList);
     1848        EaOp.fpGEAList = (PGEALIST)KernSelToFlat((uintptr_t)EaOp.fpGEAList);
     1849        Log2(("vboxSfOs2MakeEmptyEaList: #0b: %p %p\n", EaOp.fpGEAList, EaOp.fpFEAList));
     1850
     1851        rc = vboxSfOs2MakeEmptyEaListEx(&EaOp, uLevel, NULL, &pEaOp->oError);
     1852    }
     1853    return rc;
     1854}
     1855
     1856
     1857/**
     1858 * Corrects the case of the given path.
     1859 *
     1860 * @returns OS/2 status code
     1861 * @param   pFolder         The folder.
     1862 * @param   pStrFolderPath  The path within the folder.
     1863 * @param   pszPath         The original path for figuring the drive letter or
     1864 *                          UNC part of the path.
     1865 * @param   pbData          Where to return the data (user address).
     1866 * @param   cbData          The maximum amount of data we can return.
     1867 */
     1868static int vboxSfOs2QueryCorrectCase(PVBOXSFFOLDER pFolder, PSHFLSTRING pStrFolderPath, const char *pszPath,
     1869                                     PBYTE pbData, ULONG cbData)
     1870{
     1871/** @todo do case correction.  Can do step-by-step dir info... but slow */
     1872    RT_NOREF(pFolder, pStrFolderPath, pszPath, pbData, cbData);
    1051873    return ERROR_NOT_SUPPORTED;
    1061874}
    1071875
    1081876
    109 DECLASM(int)
    110 FS32_MKDIR(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszDir, USHORT iCurDirEnd,
    111            PBYTE pbEABuf, ULONG fFlags)
    112 {
    113     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszDir); NOREF(iCurDirEnd); NOREF(pbEABuf); NOREF(fFlags);
     1877/**
     1878 * Copy out file status info.
     1879 *
     1880 * @returns OS/2 status code.
     1881 * @param   pbDst           User address to put the status info at.
     1882 * @param   cbDst           The size of the structure to produce.
     1883 * @param   uLevel          The info level of the structure to produce.
     1884 * @param   pSrc            The shared folder FS object info source structure.
     1885 * @note    Careful with stack, thus no-inlining.
     1886 */
     1887DECL_NO_INLINE(RT_NOTHING, APIRET)
     1888vboxSfOs2FileStatusFromObjInfo(PBYTE pbDst, ULONG cbDst, ULONG uLevel, SHFLFSOBJINFO const *pSrc)
     1889{
     1890    union
     1891    {
     1892        FILESTATUS      Fst;
     1893        FILESTATUS2     Fst2;
     1894        FILESTATUS3L    Fst3L;
     1895        FILESTATUS4L    Fst4L;
     1896    } uTmp;
     1897
     1898    int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     1899    vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateCreation,   &uTmp.Fst.ftimeCreation,   pSrc->BirthTime, cMinLocalTimeDelta);
     1900    vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateLastAccess, &uTmp.Fst.ftimeLastAccess, pSrc->AccessTime, cMinLocalTimeDelta);
     1901    vboxSfOs2DateTimeFromTimeSpec(&uTmp.Fst.fdateLastWrite,  &uTmp.Fst.ftimeLastWrite,  pSrc->ModificationTime, cMinLocalTimeDelta);
     1902    if (uLevel < FI_LVL_STANDARD_64)
     1903    {
     1904        uTmp.Fst.cbFile       = (uint32_t)RT_MIN(pSrc->cbObject,    UINT32_MAX);
     1905        uTmp.Fst.cbFileAlloc  = (uint32_t)RT_MIN(pSrc->cbAllocated, UINT32_MAX);
     1906        uTmp.Fst.attrFile     = (uint16_t)((pSrc->Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
     1907        if (uLevel == FI_LVL_STANDARD_EASIZE)
     1908            uTmp.Fst2.cbList = 0;
     1909    }
     1910    else
     1911    {
     1912        uTmp.Fst3L.cbFile      = pSrc->cbObject;
     1913        uTmp.Fst3L.cbFileAlloc = pSrc->cbAllocated;
     1914        uTmp.Fst3L.attrFile    = (pSrc->Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT;
     1915        uTmp.Fst4L.cbList      = 0;
     1916    }
     1917
     1918    return KernCopyOut(pbDst, &uTmp, cbDst);
     1919}
     1920
     1921
     1922
     1923/**
     1924 * Worker for FS32_PATHINFO that handles file stat queries.
     1925 *
     1926 * @returns OS/2 status code
     1927 * @param   pFolder         The folder.
     1928 * @param   pStrFolderPath  The path within the folder.
     1929 * @param   uLevel          The information level.
     1930 * @param   pbData          Where to return the data (user address).
     1931 * @param   cbData          The amount of data to produce.
     1932 */
     1933static APIRET vboxSfOs2QueryPathInfo(PVBOXSFFOLDER pFolder, PSHFLSTRING pStrFolderPath, ULONG uLevel, PBYTE pbData, ULONG cbData)
     1934{
     1935    APIRET rc;
     1936    SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     1937    if (pParams)
     1938    {
     1939        RT_ZERO(*pParams);
     1940        pParams->CreateFlags = SHFL_CF_LOOKUP;
     1941
     1942        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     1943        LogFlow(("FS32_PATHINFO: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
     1944        if (RT_SUCCESS(vrc))
     1945        {
     1946            switch (pParams->Result)
     1947            {
     1948                case SHFL_FILE_EXISTS:
     1949                    switch (uLevel)
     1950                    {
     1951                        /*
     1952                         * Produce the desired file stat data.
     1953                         */
     1954                        case FI_LVL_STANDARD:
     1955                        case FI_LVL_STANDARD_EASIZE:
     1956                        case FI_LVL_STANDARD_64:
     1957                        case FI_LVL_STANDARD_EASIZE_64:
     1958                            rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, &pParams->Info);
     1959                            break;
     1960
     1961                        /*
     1962                         * We don't do EAs and we "just" need to return no-EAs.
     1963                         * However, that's not as easy as you might think.
     1964                         */
     1965                        case FI_LVL_EAS_FROM_LIST:
     1966                        case FI_LVL_EAS_FULL:
     1967                        case FI_LVL_EAS_FULL_5:
     1968                        case FI_LVL_EAS_FULL_8:
     1969                            rc = vboxSfOs2MakeEmptyEaList((PEAOP)pbData, uLevel);
     1970                            break;
     1971
     1972                        default:
     1973                            AssertFailed();
     1974                            rc = ERROR_GEN_FAILURE;
     1975                            break;
     1976                    }
     1977                    break;
     1978
     1979                case SHFL_PATH_NOT_FOUND:
     1980                    rc = ERROR_PATH_NOT_FOUND;
     1981                    break;
     1982
     1983                default:
     1984                case SHFL_FILE_NOT_FOUND:
     1985                    rc = ERROR_FILE_NOT_FOUND;
     1986                    break;
     1987            }
     1988        }
     1989        else
     1990            rc = vboxSfOs2ConvertStatusToOs2(rc, ERROR_FILE_NOT_FOUND);
     1991        VbglR0PhysHeapFree(pParams);
     1992    }
     1993    else
     1994        rc = ERROR_NOT_ENOUGH_MEMORY;
     1995    return rc;
     1996}
     1997
     1998
     1999DECLASM(APIRET)
     2000FS32_PATHINFO(USHORT fFlags, PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszPath, LONG offCurDirEnd,
     2001              ULONG uLevel, PBYTE pbData, ULONG cbData)
     2002{
     2003    LogFlow(("FS32_PATHINFO: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszPath=%p:{%s} offCurDirEnd=%d uLevel=%u pbData=%p cbData=%#x\n",
     2004             fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszPath, pszPath, offCurDirEnd, uLevel, pbData, cbData));
     2005
     2006    /*
     2007     * Check the level.
     2008     *
     2009     * Note! You would think this is FIL_STANDARD, FIL_QUERYEASIZE,
     2010     *       FIL_QUERYEASFROMLISTL and such.  However, there are several levels
     2011     *       (4/14, 6/16, 7/17, 8/18) that are not defined in os2.h and then
     2012     *       there and FIL_QUERYFULLNAME that is used very between the kernel
     2013     *       and the FSD so the kernel can implement DosEnumAttributes.
     2014     *
     2015     * Note! DOSCALL1.DLL has code for converting FILESTATUS to FILESTATUS3
     2016     *       and FILESTATUS2 to FILESTATUS4 as needed.  We don't need to do this.
     2017     *       It also has weird code for doubling the FILESTATUS2.cbList value
     2018     *       for no apparent reason.
     2019     */
     2020    ULONG cbMinData;
     2021    switch (uLevel)
     2022    {
     2023        case FI_LVL_STANDARD:
     2024            cbMinData = sizeof(FILESTATUS);
     2025            AssertCompileSize(FILESTATUS,  0x16);
     2026            break;
     2027        case FI_LVL_STANDARD_64:
     2028            cbMinData = sizeof(FILESTATUS3L);
     2029            AssertCompileSize(FILESTATUS3L, 0x20); /* cbFile and cbFileAlloc are misaligned. */
     2030            break;
     2031        case FI_LVL_STANDARD_EASIZE:
     2032            cbMinData = sizeof(FILESTATUS2);
     2033            AssertCompileSize(FILESTATUS2, 0x1a);
     2034            break;
     2035        case FI_LVL_STANDARD_EASIZE_64:
     2036            cbMinData = sizeof(FILESTATUS4L);
     2037            AssertCompileSize(FILESTATUS4L, 0x24); /* cbFile and cbFileAlloc are misaligned. */
     2038            break;
     2039        case FI_LVL_EAS_FROM_LIST:
     2040        case FI_LVL_EAS_FULL:
     2041        case FI_LVL_EAS_FULL_5:
     2042        case FI_LVL_EAS_FULL_8:
     2043            cbMinData = sizeof(EAOP);
     2044            break;
     2045        case FI_LVL_VERIFY_PATH:
     2046        case FI_LVL_CASE_CORRECT_PATH:
     2047            cbMinData = 1;
     2048            break;
     2049        default:
     2050            LogRel(("FS32_PATHINFO: Unsupported info level %u!\n", uLevel));
     2051            return ERROR_INVALID_LEVEL;
     2052    }
     2053    if (cbData < cbMinData || pbData == NULL)
     2054    {
     2055        Log(("FS32_PATHINFO: ERROR_BUFFER_OVERFLOW (cbMinData=%#x, cbData=%#x, pszPath=%s)\n", cbMinData, cbData, pszPath));
     2056        return ERROR_BUFFER_OVERFLOW;
     2057    }
     2058
     2059    /*
     2060     * Resolve the path to a folder and folder path.
     2061     */
     2062    PVBOXSFFOLDER pFolder;
     2063    PSHFLSTRING   pStrFolderPath;
     2064    APIRET rc = vboxSfOs2ResolvePath(pszPath, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     2065    LogFlow(("FS32_PATHINFO: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
     2066    if (rc == NO_ERROR)
     2067    {
     2068        /*
     2069         * Query information.
     2070         */
     2071        if (fFlags == PI_RETRIEVE)
     2072        {
     2073            if (   uLevel != FI_LVL_VERIFY_PATH
     2074                && uLevel != FI_LVL_CASE_CORRECT_PATH)
     2075                rc = vboxSfOs2QueryPathInfo(pFolder, pStrFolderPath, uLevel, pbData, cbMinData);
     2076            else if (uLevel == FI_LVL_VERIFY_PATH)
     2077                rc = NO_ERROR; /* vboxSfOs2ResolvePath should've taken care of this already */
     2078            else
     2079                rc = vboxSfOs2QueryCorrectCase(pFolder, pStrFolderPath, pszPath, pbData, cbData);
     2080        }
     2081        /*
     2082         * Update information.
     2083         */
     2084        else if (   fFlags == PI_SET
     2085                 || fFlags == (PI_SET | PI_WRITE_THRU))
     2086        {
     2087            if (   uLevel == FI_LVL_STANDARD
     2088                || uLevel == FI_LVL_STANDARD_64)
     2089            {
     2090                /* Read in the data and join paths with FS32_FILEATTRIBUTE: */
     2091                PFILESTATUS pDataCopy = (PFILESTATUS)VbglR0PhysHeapAlloc(cbMinData);
     2092                if (pDataCopy)
     2093                {
     2094                    rc = KernCopyIn(pDataCopy, pbData, cbMinData);
     2095                    if (rc == NO_ERROR)
     2096                        rc = vboxSfOs2SetPathInfoWorker(pFolder, pStrFolderPath,
     2097                                                        uLevel == FI_LVL_STANDARD
     2098                                                        ? (ULONG)pDataCopy->attrFile
     2099                                                        : ((PFILESTATUS3L)pDataCopy)->attrFile,
     2100                                                        (PFILESTATUS)pDataCopy);
     2101                    VbglR0PhysHeapFree(pDataCopy);
     2102                }
     2103                else
     2104                    rc = ERROR_NOT_ENOUGH_MEMORY;
     2105            }
     2106            else if (uLevel == FI_LVL_STANDARD_EASIZE)
     2107                rc = ERROR_EAS_NOT_SUPPORTED;
     2108            else
     2109                rc = ERROR_INVALID_LEVEL;
     2110        }
     2111        else
     2112        {
     2113            LogRel(("FS32_PATHINFO: Unknown flags value: %#x (path: %s)\n", fFlags, pszPath));
     2114            rc = ERROR_INVALID_PARAMETER;
     2115        }
     2116        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     2117    }
     2118    RT_NOREF_PV(pCdFsi);
     2119    return rc;
     2120}
     2121
     2122
     2123DECLASM(APIRET)
     2124FS32_MOUNT(USHORT fFlags, PVPFSI pvpfsi, PVBOXSFVP pVpFsd, USHORT hVPB, PCSZ pszBoot)
     2125{
     2126    NOREF(fFlags); NOREF(pvpfsi); NOREF(pVpFsd); NOREF(hVPB); NOREF(pszBoot);
    1142127    return ERROR_NOT_SUPPORTED;
    1152128}
    1162129
    117 
    118 DECLASM(int)
    119 FS32_RMDIR(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszDir, USHORT iCurDirEnd)
    120 {
    121     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszDir); NOREF(iCurDirEnd);
    122     return ERROR_NOT_SUPPORTED;
    123 }
    124 
    125 
    126 DECLASM(int)
    127 FS32_COPY(USHORT fFlags, PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszSrc, USHORT iSrcCurDirEnd,
    128           PCSZ pszDst, USHORT iDstCurDirEnd, USHORT uNameType)
    129 {
    130     NOREF(fFlags); NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszSrc); NOREF(iSrcCurDirEnd);
    131     NOREF(pszDst); NOREF(iDstCurDirEnd); NOREF(uNameType);
    132     return ERROR_NOT_SUPPORTED;
    133 }
    134 
    135 
    136 DECLASM(int)
    137 FS32_MOVE(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszSrc, USHORT iSrcCurDirEnd,
    138           PCSZ pszDst, USHORT iDstCurDirEnd, USHORT uNameType)
    139 {
    140     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszSrc); NOREF(iSrcCurDirEnd); NOREF(pszDst); NOREF(iDstCurDirEnd); NOREF(uNameType);
    141     return ERROR_NOT_SUPPORTED;
    142 }
    143 
    144 
    145 DECLASM(int)
    146 FS32_DELETE(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszFile, USHORT iCurDirEnd)
    147 {
    148     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszFile); NOREF(iCurDirEnd);
    149     return ERROR_NOT_SUPPORTED;
    150 }
    151 
    152 
    153 DECLASM(int)
    154 FS32_FILEATTRIBUTE(ULONG fFlags, PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszName, USHORT iCurDirEnd, PUSHORT pfAttr)
    155 {
    156     NOREF(fFlags); NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszName); NOREF(iCurDirEnd); NOREF(pfAttr);
    157     return ERROR_NOT_SUPPORTED;
    158 }
    159 
    160 
    161 DECLASM(int)
    162 FS32_PATHINFO(USHORT fFlags, PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszName, USHORT iCurDirEnd,
    163               USHORT uLevel, PBYTE pbData, USHORT cbData)
    164 {
    165     NOREF(fFlags); NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszName); NOREF(iCurDirEnd); NOREF(uLevel); NOREF(pbData); NOREF(cbData);
    166     return ERROR_NOT_SUPPORTED;
    167 }
    168 
    169 
    170 DECLASM(int)
    171 FS32_MOUNT(USHORT fFlags, PVPFSI pvpfsi, PVBOXSFVP pvpfsd, USHORT hVPB, PCSZ pszBoot)
    172 {
    173     NOREF(fFlags); NOREF(pvpfsi); NOREF(pvpfsd); NOREF(hVPB); NOREF(pszBoot);
    174     return ERROR_NOT_SUPPORTED;
    175 }
    176 
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.def

    r69339 r75337  
    8585    FS_SETSWAP
    8686    FS_SHUTDOWN
     87    FS_VERIFYUNCNAME
    8788    FS_WRITE
    8889
    8990    ; 32-bit entry points.
    90     FS32_CHGFILEPTR
    9191    FS32_CHGFILEPTRL
    9292    FS32_READ
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFA.asm

    r69339 r75337  
    3030
    3131
    32 ;*******************************************************************************
    33 ;* Header Files                                                                *
    34 ;*******************************************************************************
     32;*********************************************************************************************************************************
     33;*  Header Files                                                                                                                 *
     34;*********************************************************************************************************************************
    3535%define RT_INCL_16BIT_SEGMENTS
    3636%include "iprt/asmdefs.mac"
    3737%include "iprt/err.mac"
     38%include "iprt/x86.mac"
     39%include "iprt/formats/dwarf.mac"
    3840%include "VBox/VBoxGuest.mac"
    3941
    4042
    41 ;*******************************************************************************
    42 ;*  Defined Constants And Macros                                               *
    43 ;*******************************************************************************
     43;*********************************************************************************************************************************
     44;*  Dwarf constants and macros                                                                                                   *
     45;*********************************************************************************************************************************
     46;; enable dwarf debug info
     47%define WITH_DWARF 1
     48
     49;; Emits a LEB128 (signed) constant (%1) - limited range.
     50%macro DWARF_LEB128 1
     51%if %1 >= 0
     52 %if %1 < 64
     53        db  %1
     54 %else
     55        db  (%1 & 0x7f) | 0x80
     56        db  (%1 >> 7)   & 0x7f
     57 %endif
     58%else
     59 %if %1 > -64
     60        db  (%1 & 0x3f) | 0x40
     61 %else
     62        db  (%1 & 0x7f) | 0x80
     63        db  ((%1 >> 7)  & 0x7f) | 0x40
     64 %endif
     65%endif
     66%endmacro
     67
     68;; Emits a ULEB128 (unsigned) constant (%1) - limited range.
     69%macro DWARF_ULEB128 1
     70%if %1 < 0x80
     71        db  %1
     72%elif %1 < 0x4000
     73        db  (%1 & 0x7f) | 0x80
     74        db  (%1 >> 7)
     75%elif %1 < 0x200000
     76        db  ((%1)       & 0x7f) | 0x80
     77        db  ((%1 >> 7)  & 0x7f) | 0x80
     78        db  ((%1 >> 14))
     79%else
     80 %error out of range: %1
     81%endif
     82%endmacro
     83
     84;; Emits a pair of ULEB128 constants.  Useful for .debug_abbrev.
     85%macro DWARF_ULEB128_PAIR 2
     86        DWARF_ULEB128 %1
     87        DWARF_ULEB128 %2
     88%endmacro
     89
     90
     91;; defines a CFA offset by register (%1) + unsigned offset (%2).
     92%macro CFA_DEF_CFA 2
     93        db      DW_CFA_def_cfa
     94        DWARF_ULEB128 %1
     95        DWARF_ULEB128 %2
     96%endmacro
     97
     98;; defines the register (%1) value as CFA + unsigned offset (%2) * data_alignment_factor.
     99%macro CFA_VAL_OFFSET 2
     100        db      DW_CFA_val_offset
     101        DWARF_ULEB128 %1
     102        DWARF_ULEB128 %2
     103%endmacro
     104
     105;; defines the register (%1) save location as CFA + unsigned offset (%2) * data_alignment_factor.
     106%macro CFA_OFFSET 2
     107%if %1 < 0x40
     108        db      DW_CFA_offset | %1
     109%else
     110        db      DW_CFA_offset_extended
     111        DWARF_ULEB128 %1
     112%endif
     113        DWARF_ULEB128 %2
     114%endmacro
     115
     116%define MY_ABBREV_CODE_CU       2
     117%define MY_ABBREV_CODE_LABEL    3
     118
     119
     120;; Emits a debug info for a label in CODE16.
     121;; @param %1    symbol
     122%macro DWARF_LABEL_CODE16 1
     123%ifdef WITH_DWARF
     124segment _debug_info
     125        DWARF_ULEB128       MY_ABBREV_CODE_LABEL
     126        dd                  %1 wrt CODE16
     127        db                  2 ; Hardcoded CODE16 number.
     128%defstr tmp_str_conversion %1
     129        db                  tmp_str_conversion, 0
     130%endif
     131segment CODE16
     132%endmacro
     133
     134
     135;; Emits a debug info for a label in CODE32.
     136;; @param %1    symbol
     137%macro DWARF_LABEL_TEXT32 1
     138%ifdef WITH_DWARF
     139segment _debug_info
     140        DWARF_ULEB128       MY_ABBREV_CODE_LABEL
     141        dd                  %1 wrt TEXT32
     142        db                  3 ; Hardcoded TEXT32 number.
     143%defstr tmp_str_conversion %1
     144        db                  tmp_str_conversion, 0
     145%endif
     146segment TEXT32
     147%endmacro
     148
     149
     150
     151;*********************************************************************************************************************************
     152;*  Additional Segment definitions.                                                                                                         *
     153;*********************************************************************************************************************************
     154%ifdef WITH_DWARF       ; We need to use '_debug_xxx' + dotseg.exe here rather than '.debug_xxx' because some nasm crap.
     155segment _debug_frame       public CLASS=DWARF align=4 use32
     156g_cie_thunk_back:
     157        dd      (g_cie_thunk_end - g_cie_thunk_back - 4)    ; Length
     158        dd      0xffffffff                      ; I'm a CIE.
     159        db      4                               ; DwARF v4
     160        db      0                               ; Augmentation.
     161        db      4                               ; Address size.
     162        db      4                               ; Segment size.
     163        DWARF_LEB128  1                         ; Code alignment factor.
     164        DWARF_LEB128 -1                         ; Data alignment factor.
     165        DWARF_ULEB128   DWREG_X86_RA            ; Return register column.
     166        CFA_DEF_CFA     DWREG_X86_EBP, 8        ; cfa = EBP + 8
     167        CFA_OFFSET      DWREG_X86_EBP, 8        ; EBP = [CFA - 8]
     168        CFA_OFFSET      DWREG_X86_ESP, 8+10     ; SS  = [CFA - 8 - 10]
     169        CFA_OFFSET      DWREG_X86_SS,  8+6      ; SS  = [CFA - 8 - 6]
     170        CFA_OFFSET      DWREG_X86_ES,  8+4      ; ES  = [CFA - 8 - 4]
     171        CFA_OFFSET      DWREG_X86_DS,  8+2      ; DS  = [CFA - 8 - 2]
     172        CFA_OFFSET      DWREG_X86_CS,  2        ; CS  = [CFA - 2]
     173;        CFA_OFFSET      DWREG_X86_RA,  4        ; RetAddr = [CFA - 4]
     174        align   4, db DW_CFA_nop
     175g_cie_thunk_end:
     176
     177
     178segment _debug_abbrev       public CLASS=DWARF align=1 use32
     179g_abbrev_compile_unit:
     180        DWARF_ULEB128       MY_ABBREV_CODE_CU
     181        DWARF_ULEB128_PAIR  DW_TAG_compile_unit, DW_CHILDREN_yes
     182        DWARF_ULEB128_PAIR  DW_AT_name, DW_FORM_string
     183        db                  0, 0 ; the end.
     184g_abbrev_label:
     185        db                  MY_ABBREV_CODE_LABEL
     186        DWARF_ULEB128_PAIR  DW_TAG_label, DW_CHILDREN_no
     187        DWARF_ULEB128_PAIR  DW_AT_low_pc, DW_FORM_addr
     188        DWARF_ULEB128_PAIR  DW_AT_segment, DW_FORM_data1
     189        DWARF_ULEB128_PAIR  DW_AT_name, DW_FORM_string
     190        db                  0, 0 ; the end.
     191
     192
     193segment _debug_info         public CLASS=DWARF align=1 use32
     194g_dwarf_compile_unit_header:
     195        dd                  g_dwarf_compile_unit_end - g_dwarf_compile_unit_header - 4
     196        dw                  2           ; DWARF v2
     197        dd                  g_abbrev_compile_unit wrt _debug_abbrev
     198        db                  4           ; address_size
     199.compile_unit_die:
     200        db                  MY_ABBREV_CODE_CU
     201        db                  __FILE__, 0
     202
     203segment TEXT32
     204%endif ; WITH_DWARF
     205
     206
     207
     208;*********************************************************************************************************************************
     209;*  Defined Constants And Macros                                                                                                 *
     210;*********************************************************************************************************************************
    44211%define ERROR_NOT_SUPPORTED         50
    45212%define ERROR_INVALID_PARAMETER     87
    46213%define DevHlp_AttachDD             2ah
     214
    47215
    48216;;
     
    53221%%my_dbg_str: db %1, 0ah, 0
    54222segment CODE16
    55     push    ax
    56     mov     ax, %%my_dbg_str
    57     call    NAME(dbgstr16)
    58     pop     ax
     223        push    ax
     224        mov     ax, %%my_dbg_str
     225        call    NAME(dbgstr16)
     226        pop     ax
    59227%endif
    60228%endmacro
    61229
     230;%define RT_STR_QUOTE    "
     231;%define RT_STR(a_Label)       RT_STR_QUOTE a_Label RT_STR_QUOTE
    62232
    63233%macro VBOXSF_EP16_BEGIN 2
     234DWARF_LABEL_CODE16 %1
    64235global %1
    65236%1:
    66     DEBUG_STR16 {'VBoxSF: ', %2}
     237        ;DEBUG_STR16 {'VBoxSF: ', %2}
    67238
    68239%endmacro
     
    74245
    75246;;
    76 ; Used to taking us to 32-bit and reserving a parameter frame.
     247; Used in a 16-bit entrypoint for taking us to 32-bit and reserving a parameter frame.
    77248;
    78249; @param    %1      The function name
     
    80251;
    81252%macro VBOXSF_TO_32 2
    82     ; prologue
    83     push    ebp
    84     mov     ebp, esp                    ; bp
    85     push    ds                          ; bp - 2
    86     push    es                          ; bp - 4
    87 
    88     ; Reserve the 32-bit parameter and align the stack on a 16 byte
    89     ; boundary to make GCC really happy.
    90     sub     sp, %2
    91     and     sp, 0fff0h
    92 
    93     ;jmp far dword NAME(%i %+ _32) wrt FLAT
    94     db      066h
    95     db      0eah
    96     dd      NAME(%1 %+ _32) ;wrt FLAT
    97     dw      TEXT32 wrt FLAT
     253        ; prologue
     254%ifdef DEBUG
     255 %ifndef WITH_DWARF
     256        inc     ebp
     257 %endif
     258%endif
     259        push    ebp
     260        mov     ebp, esp                    ; bp
     261        push    ds                          ; bp - 2
     262        push    es                          ; bp - 4
     263%ifdef WITH_DWARF
     264        push    ss                          ; bp - 6
     265        lea     eax, [esp + 3*2 + 4 + 4]    ; bp - 10: return esp (16-bit)
     266        push    eax
     267%endif
     268
     269        ; Reserve the 32-bit parameter and align the stack on a 16 byte
     270        ; boundary to make GCC really happy.
     271        sub     sp, %2
     272        and     sp, 0fff0h
     273
     274        ;jmp far dword NAME(%i %+ _32) wrt FLAT
     275        db      066h
     276        db      0eah
     277        dd      NAME(%1 %+ _32) ;wrt FLAT
     278        dw      TEXT32 wrt FLAT
    98279segment TEXT32
    99280GLOBALNAME %1 %+ _32
    100     mov     ax, DATA32 wrt FLAT
    101     mov     ds, ax
    102     mov     es, ax
    103 
    104     call    KernThunkStackTo32
    105 
    106 %endmacro VBOXSF_TO_32 1
     281DWARF_LABEL_TEXT32 NAME(%1 %+ _32)
     282        mov     ax, DATA32 wrt FLAT
     283        mov     ds, ax
     284        mov     es, ax
     285
     286        call    KernThunkStackTo32
     287.vboxsf_to_32_end:
     288
     289%endmacro ; VBOXSF_TO_32
    107290
    108291;;
     
    112295;
    113296%macro VBOXSF_TO_16 1
    114     push    eax
    115     call    KernThunkStackTo16
    116     pop     eax
    117 
    118     ;jmp far dword NAME(%1 %+ _16) wrt CODE16
    119     db      066h
    120     db      0eah
    121     dw      NAME(%1 %+ _16) wrt CODE16
    122     dw      CODE16
     297.vboxsf_to_16_start:
     298        push    eax
     299        call    KernThunkStackTo16
     300        pop     eax
     301
     302        ;jmp far dword NAME(%1 %+ _16) wrt CODE16
     303        db      066h
     304        db      0eah
     305        dw      NAME(%1 %+ _16) wrt CODE16
     306        dw      CODE16
     307.vboxsf_to_16_done_32:
     308%ifdef WITH_DWARF
     309segment _debug_frame
     310.fde_start:
     311        dd      (.fde_end - .fde_start) - 4
     312        dd      g_cie_thunk_back wrt _debug_frame
     313        dd      2 ; TEXT32 idx
     314        dd      NAME(%1 %+ _32) wrt TEXT32
     315        dd      .vboxsf_to_16_done_32 - NAME(%1 %+ _32)
     316        db      DW_CFA_advance_loc | 4
     317        db      DW_CFA_advance_loc | 2
     318        db      DW_CFA_advance_loc | 2
     319        db      DW_CFA_advance_loc | 5
     320        db      DW_CFA_advance_loc2                         ; Hack to easily cover the parameter conversion code.
     321        dw      .vboxsf_to_16_start - .vboxsf_to_32_end
     322        db      DW_CFA_advance_loc | 1
     323        db      DW_CFA_advance_loc | 5
     324        db      DW_CFA_advance_loc | 1
     325        db      DW_CFA_advance_loc | 6
     326        align 4, db DW_CFA_nop
     327.fde_end:
     328 %endif ; WITH_DWARF
    123329segment CODE16
    124330GLOBALNAME %1 %+ _16
    125 
    126     ; Epilogue
    127     lea     sp, [bp - 4h]
    128     pop     es
    129     pop     ds
    130     mov     esp, ebp
    131     pop     ebp
     331DWARF_LABEL_CODE16 NAME(%1 %+ _16)
     332
     333        ; Epilogue
     334        lea     sp, [bp - 4h]
     335        pop     es
     336        pop     ds
     337        mov     esp, ebp
     338        pop     ebp
     339%ifdef DEBUG
     340 %ifndef WITH_DWARF
     341        dec     ebp
     342 %endif
     343%endif
    132344%endmacro
    133345
    134346;;
    135 ; Thunks the given 16:16 pointer to a flat pointer.
    136 ;
    137 ; @param    %1      The negated ebp offset of the input.
     347; Thunks the given 16:16 pointer to a flat pointer, NULL is returned as NULL.
     348;
     349; @param    %1      The ebp offset of the input.
    138350; @param    %2      The esp offset of the output.
    139351; @users    eax, edx, ecx
    140352;
    141353%macro VBOXSF_FARPTR_2_FLAT 2
    142     movzx   eax, word [ebp - (%1) + 2]
    143     push    eax
    144     call    KernSelToFlat
    145     movzx   edx, word [ebp - (%1)]
    146     add     eax, edx
    147     mov     [esp + (%2)], eax
     354        push    dword [ebp + (%1)]
     355        call    KernSelToFlat
     356        add     esp, 4h
     357        mov     [esp + (%2)], eax
    148358%endmacro
    149359
     
    151361; Thunks the given 16:16 struct sffsd pointer to a flat pointer.
    152362;
    153 ; @param    %1      The negated ebp offset of the input.
     363; @param    %1      The ebp offset of the input.
    154364; @param    %2      The esp offset of the output.
    155365; @users    eax, ecx
    156366;
    157367%macro VBOXSF_PSFFSD_2_FLAT 2
    158     lds     cx, [ebp - (%1)]
    159     and     ecx, 0ffffh
    160     mov     eax, dword [ecx]
    161     mov     cx, DATA32 wrt FLAT
    162     mov     [esp + (%2)], eax
    163     mov     ds, cx
     368%if 1 ; optimize later if we can.
     369        VBOXSF_FARPTR_2_FLAT %1, %2
     370%else
     371        lds     cx, [ebp + (%1)]
     372        and     ecx, 0ffffh
     373        mov     eax, dword [ecx]
     374        mov     cx, DATA32 wrt FLAT
     375        mov     [esp + (%2)], eax
     376        mov     ds, cx
     377%endif
    164378%endmacro
    165379
     
    168382; Thunks the given 16:16 struct cdfsd pointer to a flat pointer.
    169383;
    170 ; @param    %1      The negated ebp offset of the input.
     384; @param    %1      The ebp offset of the input.
    171385; @param    %2      The esp offset of the output.
    172386; @users    eax, ecx
    173387;
    174388%macro VBOXSF_PCDFSD_2_FLAT 2
    175     lds     cx, [ebp - (%1)]
    176     and     ecx, 0ffffh
    177     mov     eax, dword [ecx]
    178     mov     cx, DATA32 wrt FLAT
    179     mov     [esp + (%2)], eax
    180     mov     ds, cx
     389%if 1 ; optimize later if possible.
     390        VBOXSF_FARPTR_2_FLAT %1, %2
     391%else
     392        lds     cx, [ebp + (%1)]
     393        and     ecx, 0ffffh
     394        mov     eax, dword [ecx]
     395        mov     cx, DATA32 wrt FLAT
     396        mov     [esp + (%2)], eax
     397        mov     ds, cx
     398%endif
    181399%endmacro
    182400
     
    184402; Thunks the given 16:16 struct fsfsd pointer to a flat pointer.
    185403;
    186 ; @param    %1      The negated ebp offset of the input.
     404; @param    %1      The ebp offset of the input.
    187405; @param    %2      The esp offset of the output.
    188406; @users    eax, ecx
    189407;
    190408%macro VBOXSF_PFSFSD_2_FLAT 2
    191     lds     cx, [ebp - (%1)]
    192     and     ecx, 0ffffh
    193     mov     eax, dword [ecx]
    194     mov     cx, DATA32 wrt FLAT
    195     mov     [esp + (%2)], eax
    196     mov     ds, cx
     409%if 1 ; optimize later if possible.
     410        VBOXSF_FARPTR_2_FLAT %1, %2
     411%else
     412        lds     cx, [ebp + (%1)]
     413        and     ecx, 0ffffh
     414        mov     eax, dword [ecx]
     415        mov     cx, DATA32 wrt FLAT
     416        mov     [esp + (%2)], eax
     417        mov     ds, cx
     418%endif
    197419%endmacro
    198420
    199421
    200 
    201 ;*******************************************************************************
    202 ;* External Symbols                                                            *
    203 ;*******************************************************************************
     422;;
     423; Used for taking us from 32-bit and reserving a parameter frame.
     424;
     425; @param    %1      The function name
     426; @param    %2      The number of bytes to reserve
     427;
     428%macro VBOXSF_FROM_32 2
     429        ; prologue
     430        push    ebp
     431        mov     ebp, esp                    ; ebp
     432        push    ds                          ; ebp - 4
     433        push    es                          ; ebp - 8
     434        push    ebx                         ; ebp - 0ch
     435        push    esi                         ; ebp - 10h
     436        push    edi                         ; ebp - 14h
     437
     438        ; Reserve the 32-bit parameter
     439        sub     esp, %2
     440
     441        call    KernThunkStackTo16
     442
     443        ;jmp far dword NAME(%1 %+ _16) wrt CODE16
     444        db      066h
     445        db      0eah
     446        dw      NAME(%1 %+ _16) wrt CODE16
     447        dw      CODE16
     448.vboxsf_from_32_end:
     449
     450segment CODE16
     451GLOBALNAME %1 %+ _16
     452DWARF_LABEL_CODE16 NAME(%1 %+ _16)
     453
     454%endmacro
     455
     456
     457;;
     458; Partially countering VBOXSF_FROM_32:
     459; Take us back to 32-bit mode, but don't do the epilogue stuff.
     460;
     461; @param    %1      The function name
     462;
     463%macro VBOXSF_FROM_16_SWITCH 1
     464.vboxsf_from_16_start:
     465        ;jmp far dword NAME(%i %+ _32) wrt FLAT
     466        db      066h
     467        db      0eah
     468        dd      NAME(%1 %+ _32) ;wrt FLAT
     469        dw      TEXT32 wrt FLAT
     470.vboxsf_from_16_done_16:
     471
     472segment TEXT32
     473GLOBALNAME %1 %+ _32
     474DWARF_LABEL_TEXT32 NAME(%1 %+ _32)
     475
     476        push    eax
     477        call    KernThunkStackTo32
     478        mov     ax, DATA32 wrt FLAT
     479        mov     ds, eax
     480        mov     es, eax
     481        pop     eax
     482%endmacro
     483
     484
     485;;
     486; Does the remaining recovery after VBOXSF_FROM_32.
     487;
     488%macro VBOXSF_FROM_16_EPILOGUE 0
     489        ; Epilogue
     490        lea     esp, [ebp - 14h]
     491        pop     edi
     492        pop     esi
     493        pop     ebx
     494        pop     es
     495        pop     ds
     496        cld
     497        mov     esp, ebp
     498        pop     ebp
     499%endmacro
     500
     501
     502
     503
     504;*********************************************************************************************************************************
     505;*  External Symbols                                                                                                             *
     506;*********************************************************************************************************************************
    204507segment CODE32
    205508extern KernThunkStackTo32
     
    208511segment CODE16
    209512extern FSH_FORCENOSWAP
     513extern FSH_GETVOLPARM
    210514extern DOS16WRITE
    211515
     
    252556extern NAME(FS32_SETSWAP)
    253557extern NAME(FS32_SHUTDOWN)
     558extern NAME(FS32_VERIFYUNCNAME)
    254559extern FS32_WRITE
    255560
     
    267572global FS_NAME
    268573FS_NAME:
    269     db 'VBOXSF',0
     574        db 'VBOXSF',0
    270575
    271576;;
     
    284589FS_ATTRIBUTE:
    285590FS32_ATTRIBUTE:
    286     dd FSA_REMOTE + FSA_LARGEFILE ;+ FSA_LVL7 + FSA_LOCK
     591        dd FSA_REMOTE + FSA_LARGEFILE + FSA_UNC + FSA_LVL7 ;+ FSA_LOCK
    287592
    288593;; 64-bit mask.
     
    291596global FS_MPSAFEFLAGS2
    292597FS_MPSAFEFLAGS2:
    293     dd  0
    294     dd  0
     598        dd  1 | (1<<6)
     599        dd  0
    295600
    296601;;
    297602; Set after VBoxSFR0Init16Bit has been called.
    298603GLOBALNAME g_fDoneRing0
    299     db 0
     604        db 0
    300605
    301606align 4
     
    304609; (This is set by FS_INIT.)
    305610GLOBALNAME g_fpfnDevHlp
    306     dd 0
     611        dd 0
    307612
    308613;;
    309614; Whether initialization should be verbose or quiet.
    310615GLOBALNAME g_fVerbose
    311     db 1
     616        db 1
    312617
    313618;; DEBUGGING DEBUGGING
    314619GLOBALNAME g_u32Info
    315     dd 0
     620        dd 0
    316621
    317622;; Far pointer to DOS16WRITE (corrected set before called).
    318623; Just a 'temporary' hack to work around a wlink/nasm issue.
    319624GLOBALNAME g_fpfnDos16Write
    320     dw  DOS16WRITE
    321     dw  seg DOS16WRITE
     625        dw  DOS16WRITE
     626        dw  seg DOS16WRITE
    322627
    323628;;
    324629; The attach dd data.
    325630GLOBALNAME g_VBoxGuestAttachDD
    326     dd 0
    327     dw 0
    328     dd 0
    329     dw 0
     631        dd 0
     632        dw 0
     633        dd 0
     634        dw 0
    330635;;
    331636; The AttachDD name of the VBoxGuest.sys driver.
    332637GLOBALNAME g_szVBoxGuestName
    333     db VBOXGUEST_DEVICE_NAME_SHORT, 0
     638        db VBOXGUEST_DEVICE_NAME_SHORT, 0
    334639;;
    335640; The VBoxGuest IDC connection data.
    336641GLOBALNAME g_VBoxGuestIDC
    337     times VBGLOS2ATTACHDD_size db 0
     642        times VBGLOS2ATTACHDD_size db 0
    338643
    339644;;
     
    341646segment DATA32
    342647g_pfnDos16Write:
    343     dd  DOS16WRITE  ; flat
     648        dd  DOS16WRITE  ; flat
    344649
    345650
     
    363668VBOXSF_EP16_BEGIN   FS_ALLOCATEPAGESPACE, 'FS_ALLOCATEPAGESPACE'
    364669VBOXSF_TO_32        FS_ALLOCATEPAGESPACE, 4*4
    365     movzx   ecx, word [ebp + 08h]       ; cbWantContig
    366     mov     [esp + 3*4], ecx
    367     mov     edx, [ebp + 0ah]            ; cb
    368     mov     [esp + 2*4], edx
    369     VBOXSF_PSFFSD_2_FLAT  0eh, 1*4      ; psffsd
    370     VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; psffsi
    371     call    NAME(FS32_ALLOCATEPAGESPACE)
     670        movzx   ecx, word [ebp + 08h]       ; cbWantContig
     671        mov     [esp + 3*4], ecx
     672        mov     edx, [ebp + 0ah]            ; cb
     673        mov     [esp + 2*4], edx
     674        VBOXSF_PSFFSD_2_FLAT  0eh, 1*4      ; psffsd
     675        VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; psffsi
     676        call    NAME(FS32_ALLOCATEPAGESPACE)
    372677VBOXSF_TO_16        FS_ALLOCATEPAGESPACE
    373     retf    0eh
     678        retf    0eh
    374679VBOXSF_EP16_END     FS_ALLOCATEPAGESPACE
    375680
     
    378683;
    379684VBOXSF_EP16_BEGIN   FS_ATTACH, 'FS_ATTACH'
    380     ;
    381     ; Initialized ring-0 yet? (this is a likely first entry point)
    382     ;
    383     push    ds
    384     mov     ax, DATA16
    385     mov     ds, ax
    386     test    byte [NAME(g_fDoneRing0)], 1
    387     jnz     .DoneRing0
    388     call    NAME(VBoxSFR0Init16Bit)
     685        ;
     686        ; Initialized ring-0 yet? (this is a likely first entry point)
     687        ;
     688        push    ds
     689        mov     ax, DATA16
     690        mov     ds, ax
     691        test    byte [NAME(g_fDoneRing0)], 1
     692        jnz     .DoneRing0
     693        call    NAME(VBoxSFR0Init16Bit)
    389694.DoneRing0:
    390     pop     ds
     695        pop     ds
    391696
    392697VBOXSF_TO_32        FS_ATTACH, 6*4
    393     VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pcbParm
    394     VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pszParm
    395     VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pcdfsd
    396     VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pvpfsd
    397     VBOXSF_FARPTR_2_FLAT  18h, 1*4      ; pszDev
    398     movzx   ecx, word [ebp + 1ch]       ; fFlag
    399     mov     [esp], ecx
    400     call    NAME(FS32_ATTACH)
     698        VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pcbParm
     699        VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pszParm
     700        VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pcdfsd
     701        VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pvpfsd
     702        VBOXSF_FARPTR_2_FLAT  18h, 1*4      ; pszDev
     703        movzx   ecx, word [ebp + 1ch]       ; fFlag
     704        mov     [esp], ecx
     705        call    NAME(FS32_ATTACH)
    401706VBOXSF_TO_16        FS_ATTACH
    402     retf    16h
     707        retf    16h
    403708VBOXSF_EP16_END     FS_ATTACH
    404709
     
    408713VBOXSF_EP16_BEGIN   FS_CANCELLOCKREQUEST, 'FS_CANCELLOCKREQUEST'
    409714VBOXSF_TO_32        FS_CANCELLOCKREQUEST, 3*4
    410     VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pLockRange
    411     VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
    412     VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
    413     call    NAME(FS32_CANCELLOCKREQUEST)
     715        VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pLockRange
     716        VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
     717        VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
     718        call    NAME(FS32_CANCELLOCKREQUEST)
    414719VBOXSF_TO_16        FS_CANCELLOCKREQUEST
    415     retf    0ch
     720        retf    0ch
    416721VBOXSF_EP16_END     FS_CANCELLOCKREQUEST
    417722
     
    421726VBOXSF_EP16_BEGIN   FS_CANCELLOCKREQUESTL, 'FS_CANCELLOCKREQUESTL'
    422727VBOXSF_TO_32        FS_CANCELLOCKREQUESTL, 3*4
    423     VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pLockRange
    424     VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
    425     VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
    426     call    NAME(FS32_CANCELLOCKREQUESTL)
     728        VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pLockRange
     729        VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
     730        VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
     731        call    NAME(FS32_CANCELLOCKREQUESTL)
    427732VBOXSF_TO_16        FS_CANCELLOCKREQUESTL
    428     retf    0ch
     733        retf    0ch
    429734VBOXSF_EP16_END     FS_CANCELLOCKREQUESTL
    430735
     
    434739VBOXSF_EP16_BEGIN   FS_CHDIR, 'FS_CHDIR'
    435740VBOXSF_TO_32        FS_CHDIR, 5*4
    436     movzx   ecx, word [ebp + 08h]       ; iCurDirEnd
    437     mov     [esp + 4*4], ecx
    438     VBOXSF_FARPTR_2_FLAT  0ah, 3*4      ; pszDir
    439     VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pcdfsd (use slow thunk here, see flag)
    440     VBOXSF_FARPTR_2_FLAT  12h, 1*4      ; pcdfsi
    441     movzx   eax, word [ebp + 16h]       ; flag
    442     mov     [esp], eax
    443     call    NAME(FS32_CHDIR)
     741        movsx   ecx, word [ebp + 08h]       ; iCurDirEnd
     742        mov     [esp + 4*4], ecx
     743        VBOXSF_FARPTR_2_FLAT  0ah, 3*4      ; pszDir
     744        VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pcdfsd (use slow thunk here, see flag)
     745        VBOXSF_FARPTR_2_FLAT  12h, 1*4      ; pcdfsi
     746        movzx   eax, word [ebp + 16h]       ; flag
     747        mov     [esp], eax
     748        call    NAME(FS32_CHDIR)
    444749VBOXSF_TO_16        FS_CHDIR
    445     retf    10h
     750        retf    10h
    446751VBOXSF_EP16_END     FS_CHDIR
    447752
     
    450755VBOXSF_EP16_BEGIN   FS_CHGFILEPTR, 'FS_CHGFILEPTR'
    451756VBOXSF_TO_32        FS_CHGFILEPTR, 6*4
    452     movzx   ecx, word [ebp + 08h]       ; IOflag
    453     mov     [esp + 5*4], ecx
    454     movzx   edx, word [ebp + 0ah]       ; usMethod
    455     mov     [esp + 4*4], edx
    456     mov     eax, [ebp + 0ch]            ; off
    457     mov     [esp + 2*4], eax
    458     rol     eax, 1                      ; high dword - is there a better way than this?
    459     and     eax, 1
    460     mov     edx, 0ffffffffh
    461     mul     edx
    462     mov     [esp + 3*4], eax
    463     VBOXSF_PSFFSD_2_FLAT  10h, 1*4      ; psffsd
    464     VBOXSF_FARPTR_2_FLAT  14h, 0*4      ; psffsi
    465     call    FS32_CHGFILEPTRL
     757        movzx   ecx, word [ebp + 08h]       ; IOflag
     758        mov     [esp + 5*4], ecx
     759        movzx   edx, word [ebp + 0ah]       ; usMethod
     760        mov     [esp + 4*4], edx
     761        mov     eax, [ebp + 0ch]            ; off
     762        mov     [esp + 2*4], eax
     763        rol     eax, 1                      ; high dword - is there a better way than this?
     764        and     eax, 1
     765        mov     edx, 0ffffffffh
     766        mul     edx
     767        mov     [esp + 3*4], eax
     768        VBOXSF_PSFFSD_2_FLAT  10h, 1*4      ; psffsd
     769        VBOXSF_FARPTR_2_FLAT  14h, 0*4      ; psffsi
     770        call    FS32_CHGFILEPTRL
    466771VBOXSF_TO_16        FS_CHGFILEPTR
    467     retf    10h
     772        retf    10h
    468773VBOXSF_EP16_END     FS_CHGFILEPTR
    469774
     
    474779VBOXSF_EP16_BEGIN   FS_CLOSE, 'FS_CLOSE'
    475780VBOXSF_TO_32        FS_CLOSE, 4*4
    476     VBOXSF_PSFFSD_2_FLAT  08h, 3*4      ; psffsd
    477     VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; psffsi
    478     movzx   ecx, word [ebp + 10h]       ; IOflag
    479     mov     [esp + 1*4], ecx
    480     movzx   edx, word [ebp + 12h]       ; type
    481     mov     [esp], edx
    482     call    NAME(FS32_CLOSE)
     781        VBOXSF_PSFFSD_2_FLAT  08h, 3*4      ; psffsd
     782        VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; psffsi
     783        movzx   ecx, word [ebp + 10h]       ; IOflag
     784        mov     [esp + 1*4], ecx
     785        movzx   edx, word [ebp + 12h]       ; type
     786        mov     [esp], edx
     787        call    NAME(FS32_CLOSE)
    483788VBOXSF_TO_16        FS_CLOSE
    484     retf    0ch
     789        retf    0ch
    485790VBOXSF_EP16_END     FS_CLOSE
    486791
     
    491796VBOXSF_EP16_BEGIN   FS_COMMIT, 'FS_COMMIT'
    492797VBOXSF_TO_32        FS_COMMIT, 4*4
    493     VBOXSF_PSFFSD_2_FLAT  08h, 3*4      ; psffsd
    494     VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; psffsi
    495     movzx   ecx, word [ebp + 10h]       ; IOflag
    496     mov     [esp + 1*4], ecx
    497     movzx   edx, word [ebp + 12h]       ; type
    498     mov     [esp], edx
    499     call    NAME(FS32_COMMIT)
     798        VBOXSF_PSFFSD_2_FLAT  08h, 3*4      ; psffsd
     799        VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; psffsi
     800        movzx   ecx, word [ebp + 10h]       ; IOflag
     801        mov     [esp + 1*4], ecx
     802        movzx   edx, word [ebp + 12h]       ; type
     803        mov     [esp], edx
     804        call    NAME(FS32_COMMIT)
    500805VBOXSF_TO_16        FS_COMMIT
    501     retf    0ch
     806        retf    0ch
    502807VBOXSF_EP16_END     FS_COMMIT
    503808
     
    507812VBOXSF_EP16_BEGIN   FS_COPY, 'FS_COPY'
    508813VBOXSF_TO_32        FS_COPY, 8*4
    509     movzx   ecx, word [ebp + 08h]       ; flag
    510     mov     [esp + 7*4], ecx
    511     movzx   edx, word [ebp + 0ah]       ; iDstCurDirEnd
    512     mov     [esp + 6*4], edx
    513     VBOXSF_FARPTR_2_FLAT  0ch, 5*4      ; pszDst
    514     movzx   eax, word [ebp + 10h]       ; iSrcCurDirEnd
    515     mov     [esp + 4*4], eax
    516     VBOXSF_FARPTR_2_FLAT  12h, 3*4      ; pszSrc
    517     VBOXSF_PCDFSD_2_FLAT  16h, 2*4      ; psffsd
    518     VBOXSF_FARPTR_2_FLAT  1ah, 1*4      ; psffsi
    519     movzx   ecx, word [ebp + 1eh]       ; flag
    520     mov     [esp], ecx
    521     call    NAME(FS32_COPY)
     814        movzx   ecx, word [ebp + 08h]       ; flag
     815        mov     [esp + 7*4], ecx
     816        movsx   edx, word [ebp + 0ah]       ; iDstCurDirEnd
     817        mov     [esp + 6*4], edx
     818        VBOXSF_FARPTR_2_FLAT  0ch, 5*4      ; pszDst
     819        movsx   eax, word [ebp + 10h]       ; iSrcCurDirEnd
     820        mov     [esp + 4*4], eax
     821        VBOXSF_FARPTR_2_FLAT  12h, 3*4      ; pszSrc
     822        VBOXSF_PCDFSD_2_FLAT  16h, 2*4      ; psffsd
     823        VBOXSF_FARPTR_2_FLAT  1ah, 1*4      ; psffsi
     824        movzx   ecx, word [ebp + 1eh]       ; flag
     825        mov     [esp], ecx
     826        call    NAME(FS32_COPY)
    522827VBOXSF_TO_16        FS_COPY
    523     retf    18h
     828        retf    18h
    524829VBOXSF_EP16_END     FS_COPY
    525830
     
    529834VBOXSF_EP16_BEGIN   FS_DELETE, 'FS_DELETE'
    530835VBOXSF_TO_32        FS_DELETE, 4*4
    531     movzx   ecx, word [ebp + 08h]       ; iCurDirEnd
    532     mov     [esp + 3*4], ecx
    533     VBOXSF_FARPTR_2_FLAT  0ah, 2*4      ; pszFile
    534     VBOXSF_PCDFSD_2_FLAT  0eh, 1*4      ; pcdfsd
    535     VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; pcdfsi
    536     call    NAME(FS32_DELETE)
     836        movsx   ecx, word [ebp + 08h]       ; iCurDirEnd
     837        mov     [esp + 3*4], ecx
     838        VBOXSF_FARPTR_2_FLAT  0ah, 2*4      ; pszFile
     839        VBOXSF_PCDFSD_2_FLAT  0eh, 1*4      ; pcdfsd
     840        VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; pcdfsi
     841        call    NAME(FS32_DELETE)
    537842VBOXSF_TO_16        FS_DELETE
    538     retf    0eh
     843        retf    0eh
    539844VBOXSF_EP16_END FS_DELETE
    540845
     
    544849VBOXSF_EP16_BEGIN   FS_DOPAGEIO, 'FS_DOPAGEIO'
    545850VBOXSF_TO_32        FS_DOPAGEIO, 3*4
    546     VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pList
    547     VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
    548     VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
    549     call    NAME(FS32_DOPAGEIO)
     851        VBOXSF_FARPTR_2_FLAT  08h, 2*4      ; pList
     852        VBOXSF_PSFFSD_2_FLAT  0ch, 1*4      ; psffsd
     853        VBOXSF_FARPTR_2_FLAT  10h, 0*4      ; psffsi
     854        call    NAME(FS32_DOPAGEIO)
    550855VBOXSF_TO_16        FS_DOPAGEIO
    551     retf    0ch
     856        retf    0ch
    552857VBOXSF_EP16_END     FS_DOPAGEIO
    553858
     
    555860; @cproto void FS_EXIT(USHORT uid, USHORT pid, USHORT pdb)
    556861VBOXSF_EP16_BEGIN   FS_EXIT, 'FS_EXIT'
    557     ;
    558     ; Initialized ring-0 yet? (this is a likely first entry point)
    559     ;
    560     push    ds
    561     mov     ax, DATA16
    562     mov     ds, ax
    563     test    byte [NAME(g_fDoneRing0)], 1
    564     jnz     .DoneRing0
    565     call    NAME(VBoxSFR0Init16Bit)
     862        ;
     863        ; Initialized ring-0 yet? (this is a likely first entry point)
     864        ;
     865        push    ds
     866        mov     ax, DATA16
     867        mov     ds, ax
     868        test    byte [NAME(g_fDoneRing0)], 1
     869        jnz     .DoneRing0
     870        call    NAME(VBoxSFR0Init16Bit)
    566871.DoneRing0:
    567     pop     ds
     872        pop     ds
    568873
    569874VBOXSF_TO_32        FS_EXIT, 3*4
    570     movzx   ecx, word [ebp + 08h]       ; pdb
    571     mov     [esp + 2*4], ecx
    572     movzx   edx, word [ebp + 0ah]       ; pib
    573     mov     [esp + 1*4], edx
    574     movzx   eax, word [ebp + 0ch]       ; uid
    575     mov     [esp], eax
    576     call    NAME(FS32_EXIT)
     875        movzx   ecx, word [ebp + 08h]       ; pdb
     876        mov     [esp + 2*4], ecx
     877        movzx   edx, word [ebp + 0ah]       ; pib
     878        mov     [esp + 1*4], edx
     879        movzx   eax, word [ebp + 0ch]       ; uid
     880        mov     [esp], eax
     881        call    NAME(FS32_EXIT)
    577882VBOXSF_TO_16        FS_EXIT
    578     retf    6h
     883        retf    6h
    579884VBOXSF_EP16_END     FS_EXIT
    580885
     
    585890VBOXSF_EP16_BEGIN   FS_FILEATTRIBUTE, 'FS_FILEATTRIBUTE'
    586891VBOXSF_TO_32        FS_FILEATTRIBUTE, 6*4
    587     VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pAttr
    588     movzx   ecx, word [ebp + 0ch]       ; iCurDirEnd
    589     mov     [esp + 4*4], ecx
    590     VBOXSF_FARPTR_2_FLAT  0eh, 3*4      ; pszName
    591     VBOXSF_PCDFSD_2_FLAT  12h, 2*4      ; pcdfsd
    592     VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; pcdfsi
    593     movzx   edx, word [ebp + 1ah]       ; flag
    594     mov     [esp], edx
    595     call    NAME(FS32_FILEATTRIBUTE)
     892        VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pAttr
     893        movsx   ecx, word [ebp + 0ch]       ; iCurDirEnd - caller may pass 0xffff, so sign extend.
     894        mov     [esp + 4*4], ecx
     895        VBOXSF_FARPTR_2_FLAT  0eh, 3*4      ; pszName
     896        VBOXSF_PCDFSD_2_FLAT  12h, 2*4      ; pcdfsd
     897        VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; pcdfsi
     898        movzx   edx, word [ebp + 1ah]       ; flag
     899        mov     [esp], edx
     900        call    NAME(FS32_FILEATTRIBUTE)
    596901VBOXSF_TO_16        FS_FILEATTRIBUTE
    597     retf    14h
     902        retf    14h
    598903VBOXSF_EP16_END     FS_FILEATTRIBUTE
    599904
     
    604909VBOXSF_EP16_BEGIN   FS_FILEINFO, 'FS_FILEINFO'
    605910VBOXSF_TO_32        FS_FILEINFO, 7*4
    606     movzx   ecx, word [ebp + 08h]       ; IOflag
    607     mov     [esp + 6*4], ecx
    608     movzx   edx, word [ebp + 0ah]       ; cbData
    609     mov     [esp + 5*4], edx
    610     VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pData
    611     movzx   eax, word [ebp + 10h]       ; level
    612     mov     [esp + 3*4], eax
    613     VBOXSF_PSFFSD_2_FLAT  12h, 2*4      ; psffsd
    614     VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; psffsi
    615     movzx   ecx, word [ebp + 1ah]       ; flag
    616     mov     [esp], ecx
    617     call    NAME(FS32_FILEINFO)
     911        movzx   ecx, word [ebp + 08h]       ; IOflag
     912        mov     [esp + 6*4], ecx
     913        movzx   edx, word [ebp + 0ah]       ; cbData
     914        mov     [esp + 5*4], edx
     915        VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pData
     916        movzx   eax, word [ebp + 10h]       ; level
     917        mov     [esp + 3*4], eax
     918        VBOXSF_PSFFSD_2_FLAT  12h, 2*4      ; psffsd
     919        VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; psffsi
     920        movzx   ecx, word [ebp + 1ah]       ; flag
     921        mov     [esp], ecx
     922        call    NAME(FS32_FILEINFO)
    618923VBOXSF_TO_16        FS_FILEINFO
    619     retf    14h
     924        retf    14h
    620925VBOXSF_EP16_END     FS_FILEINFO
    621926
     
    626931VBOXSF_EP16_BEGIN   FS_FILEIO, 'FS_FILEIO'
    627932VBOXSF_TO_32        FS_FILEIO, 6*4
    628     movzx   ecx, word [ebp + 08h]       ; IOFlag
    629     mov     [esp + 5*4], ecx
    630     VBOXSF_FARPTR_2_FLAT  0ah, 4*4      ; poError
    631     movzx   edx, word [ebp + 0eh]       ; cbCmdList
    632     mov     [esp + 3*4], edx
    633     VBOXSF_FARPTR_2_FLAT  10h, 2*4      ; pCmdList
    634     VBOXSF_PSFFSD_2_FLAT  14h, 1*4      ; psffsd
    635     VBOXSF_FARPTR_2_FLAT  18h, 0*4      ; psffsi
    636     call    NAME(FS32_FILEIO)
     933        movzx   ecx, word [ebp + 08h]       ; IOFlag
     934        mov     [esp + 5*4], ecx
     935        VBOXSF_FARPTR_2_FLAT  0ah, 4*4      ; poError
     936        movzx   edx, word [ebp + 0eh]       ; cbCmdList
     937        mov     [esp + 3*4], edx
     938        VBOXSF_FARPTR_2_FLAT  10h, 2*4      ; pCmdList
     939        VBOXSF_PSFFSD_2_FLAT  14h, 1*4      ; psffsd
     940        VBOXSF_FARPTR_2_FLAT  18h, 0*4      ; psffsi
     941        call    NAME(FS32_FILEIO)
    637942VBOXSF_TO_16        FS_FILEIO
    638     retf    14h
     943        retf    14h
    639944VBOXSF_EP16_END     FS_FILEIO
    640945
     
    645950VBOXSF_EP16_BEGIN   FS_FILELOCKS, 'FS_FILELOCKS'
    646951VBOXSF_TO_32        FS_FILELOCKS, 6*4
    647     mov     ecx, [ebp + 08h]            ; flags
    648     mov     [esp + 5*4], ecx
    649     mov     edx, [ebp + 0ch]            ; timeout
    650     mov     [esp + 4*4], edx
    651     VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pLockRange
    652     VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pUnLockRange
    653     VBOXSF_PSFFSD_2_FLAT  18h, 1*4      ; psffsd
    654     VBOXSF_FARPTR_2_FLAT  1ch, 0*4      ; psffsi
    655     call    NAME(FS32_FILELOCKS)
     952        mov     ecx, [ebp + 08h]            ; flags
     953        mov     [esp + 5*4], ecx
     954        mov     edx, [ebp + 0ch]            ; timeout
     955        mov     [esp + 4*4], edx
     956        VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pLockRange
     957        VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pUnLockRange
     958        VBOXSF_PSFFSD_2_FLAT  18h, 1*4      ; psffsd
     959        VBOXSF_FARPTR_2_FLAT  1ch, 0*4      ; psffsi
     960        call    NAME(FS32_FILELOCKS)
    656961VBOXSF_TO_16        FS_FILELOCKS
    657     retf    18h
     962        retf    18h
    658963VBOXSF_EP16_END     FS_FILELOCKS
    659964
     
    664969VBOXSF_EP16_BEGIN   FS_FILELOCKSL, 'FS_FILELOCKSL'
    665970VBOXSF_TO_32        FS_FILELOCKSL, 6*4
    666     mov     ecx, [ebp + 08h]            ; flags
    667     mov     [esp + 5*4], ecx
    668     mov     edx, [ebp + 0ch]            ; timeout
    669     mov     [esp + 4*4], edx
    670     VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pLockRange
    671     VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pUnLockRange
    672     VBOXSF_PSFFSD_2_FLAT  18h, 1*4      ; psffsd
    673     VBOXSF_FARPTR_2_FLAT  1ch, 0*4      ; psffsi
    674     call    NAME(FS32_FILELOCKS)
     971        mov     ecx, [ebp + 08h]            ; flags
     972        mov     [esp + 5*4], ecx
     973        mov     edx, [ebp + 0ch]            ; timeout
     974        mov     [esp + 4*4], edx
     975        VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pLockRange
     976        VBOXSF_FARPTR_2_FLAT  14h, 2*4      ; pUnLockRange
     977        VBOXSF_PSFFSD_2_FLAT  18h, 1*4      ; psffsd
     978        VBOXSF_FARPTR_2_FLAT  1ch, 0*4      ; psffsi
     979        call    NAME(FS32_FILELOCKS)
    675980VBOXSF_TO_16        FS_FILELOCKSL
    676     retf    18h
     981        retf    18h
    677982VBOXSF_EP16_END     FS_FILELOCKSL
    678983
     
    683988VBOXSF_EP16_BEGIN   FS_FINDCLOSE, 'FS_FINDCLOSE'
    684989VBOXSF_TO_32        FS_FINDCLOSE, 2*4
    685     VBOXSF_PFSFSD_2_FLAT  08h, 1*4      ; pfsfsd
    686     VBOXSF_FARPTR_2_FLAT  0ch, 0*4      ; pfsfsi
    687     call    NAME(FS32_FINDCLOSE)
     990        VBOXSF_PFSFSD_2_FLAT  08h, 1*4      ; pfsfsd
     991        VBOXSF_FARPTR_2_FLAT  0ch, 0*4      ; pfsfsi
     992        call    NAME(FS32_FINDCLOSE)
    688993VBOXSF_TO_16        FS_FINDCLOSE
    689     retf    8h
     994        retf    8h
    690995VBOXSF_EP16_END     FS_FINDCLOSE
    691996
     
    6981003VBOXSF_EP16_BEGIN   FS_FINDFIRST, 'FS_FINDFIRST'
    6991004VBOXSF_TO_32        FS_FINDFIRST, 12*4
    700     movzx   ecx, word [ebp + 08h]       ; flags
    701     mov     [esp + 11*4], ecx
    702     movzx   edx, word [ebp + 0ah]       ; level
    703     mov     [esp + 10*4], edx
    704     VBOXSF_FARPTR_2_FLAT  0ch, 9*4      ; pcMatch
    705     movzx   eax, word [ebp + 10h]       ; cbData
    706     mov     [esp + 8*4], eax
    707     VBOXSF_FARPTR_2_FLAT  12h, 7*4      ; pbData
    708     VBOXSF_FARPTR_2_FLAT  16h, 6*4      ; pfsfsd
    709     VBOXSF_FARPTR_2_FLAT  1ah, 5*4      ; pfsfsi
    710     movzx   ecx, word [ebp + 1eh]       ; attr
    711     mov     [esp + 4*4], ecx
    712     movzx   edx, word [ebp + 20h]       ; iCurDirEnd
    713     mov     [esp + 3*4], edx
    714     VBOXSF_FARPTR_2_FLAT  22h, 2*4      ; pszName
    715     VBOXSF_PCDFSD_2_FLAT  26h, 1*4      ; pcdfsd
    716     VBOXSF_FARPTR_2_FLAT  2ah, 0*4      ; pcdfsi
    717     call    NAME(FS32_FINDFIRST)
     1005        movzx   ecx, word [ebp + 08h]       ; flags
     1006        mov     [esp + 11*4], ecx
     1007        movzx   edx, word [ebp + 0ah]       ; level
     1008        mov     [esp + 10*4], edx
     1009        VBOXSF_FARPTR_2_FLAT  0ch, 9*4      ; pcMatch
     1010        movzx   eax, word [ebp + 10h]       ; cbData
     1011        mov     [esp + 8*4], eax
     1012        VBOXSF_FARPTR_2_FLAT  12h, 7*4      ; pbData
     1013        VBOXSF_FARPTR_2_FLAT  16h, 6*4      ; pfsfsd
     1014        VBOXSF_FARPTR_2_FLAT  1ah, 5*4      ; pfsfsi
     1015        movzx   ecx, word [ebp + 1eh]       ; attr
     1016        mov     [esp + 4*4], ecx
     1017        movsx   edx, word [ebp + 20h]       ; iCurDirEnd
     1018        mov     [esp + 3*4], edx
     1019        VBOXSF_FARPTR_2_FLAT  22h, 2*4      ; pszName
     1020        VBOXSF_PCDFSD_2_FLAT  26h, 1*4      ; pcdfsd
     1021        VBOXSF_FARPTR_2_FLAT  2ah, 0*4      ; pcdfsi
     1022        call    NAME(FS32_FINDFIRST)
    7181023VBOXSF_TO_16        FS_FINDFIRST
    719     retf    26h
     1024        retf    26h
    7201025VBOXSF_EP16_END FS_FINDFIRST
    7211026
     
    7271032VBOXSF_EP16_BEGIN   FS_FINDFROMNAME, 'FS_FINDFROMNAME'
    7281033VBOXSF_TO_32        FS_FINDFROMNAME, 9*4
    729     movzx   ecx, word [ebp + 08h]       ; flags
    730     mov     [esp + 8*4], ecx
    731     VBOXSF_FARPTR_2_FLAT  0ah, 7*4      ; pszName
    732     mov     edx, [ebp + 0eh]            ; position
    733     mov     [esp + 6*4], edx
    734     movzx   eax, word [ebp + 12h]       ; level
    735     mov     [esp + 5*4], eax
    736     VBOXSF_FARPTR_2_FLAT  14h, 4*4      ; pcMatch
    737     movzx   eax, word [ebp + 18h]       ; cbData
    738     mov     [esp + 3*4], eax
    739     VBOXSF_FARPTR_2_FLAT  1ah, 2*4      ; pbData
    740     VBOXSF_PFSFSD_2_FLAT  1eh, 1*4      ; pfsfsd
    741     VBOXSF_FARPTR_2_FLAT  22h, 0*4      ; pfsfsi
    742     call    NAME(FS32_FINDFROMNAME)
     1034        movzx   ecx, word [ebp + 08h]       ; flags
     1035        mov     [esp + 8*4], ecx
     1036        VBOXSF_FARPTR_2_FLAT  0ah, 7*4      ; pszName
     1037        mov     edx, [ebp + 0eh]            ; position
     1038        mov     [esp + 6*4], edx
     1039        movzx   eax, word [ebp + 12h]       ; level
     1040        mov     [esp + 5*4], eax
     1041        VBOXSF_FARPTR_2_FLAT  14h, 4*4      ; pcMatch
     1042        movzx   eax, word [ebp + 18h]       ; cbData
     1043        mov     [esp + 3*4], eax
     1044        VBOXSF_FARPTR_2_FLAT  1ah, 2*4      ; pbData
     1045        VBOXSF_PFSFSD_2_FLAT  1eh, 1*4      ; pfsfsd
     1046        VBOXSF_FARPTR_2_FLAT  22h, 0*4      ; pfsfsi
     1047        call    NAME(FS32_FINDFROMNAME)
    7431048VBOXSF_TO_16        FS_FINDFROMNAME
    744     retf    1eh
     1049        retf    1eh
    7451050VBOXSF_EP16_END     FS_FINDFROMNAME
    7461051
     
    7521057VBOXSF_EP16_BEGIN   FS_FINDNEXT, 'FS_FINDNEXT'
    7531058VBOXSF_TO_32        FS_FINDNEXT, 7*4
    754     movzx   ecx, word [ebp + 08h]       ; flags
    755     mov     [esp + 6*4], ecx
    756     movzx   eax, word [ebp + 0ah]       ; level
    757     mov     [esp + 5*4], eax
    758     VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pcMatch
    759     movzx   eax, word [ebp + 10h]       ; cbData
    760     mov     [esp + 3*4], eax
    761     VBOXSF_FARPTR_2_FLAT  12h, 2*4      ; pbData
    762     VBOXSF_PFSFSD_2_FLAT  16h, 1*4      ; pfsfsd
    763     VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; pfsfsi
    764     call    NAME(FS32_FINDNEXT)
     1059        movzx   ecx, word [ebp + 08h]       ; flags
     1060        mov     [esp + 6*4], ecx
     1061        movzx   eax, word [ebp + 0ah]       ; level
     1062        mov     [esp + 5*4], eax
     1063        VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pcMatch
     1064        movzx   eax, word [ebp + 10h]       ; cbData
     1065        mov     [esp + 3*4], eax
     1066        VBOXSF_FARPTR_2_FLAT  12h, 2*4      ; pbData
     1067        VBOXSF_PFSFSD_2_FLAT  16h, 1*4      ; pfsfsd
     1068        VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; pfsfsi
     1069        call    NAME(FS32_FINDNEXT)
    7651070VBOXSF_TO_16        FS_FINDNEXT
    766     retf    16h
     1071        retf    16h
    7671072VBOXSF_EP16_END     FS_FINDNEXT
    7681073
     
    7731078VBOXSF_EP16_BEGIN   FS_FINDNOTIFYCLOSE, 'FS_FINDNOTIFYCLOSE'
    7741079VBOXSF_TO_32        FS_FINDNOTIFYCLOSE, 1*4
    775     movzx   ecx, word [ebp + 08h]       ; handle
    776     mov     [esp], ecx
    777     call    NAME(FS32_FINDNOTIFYCLOSE)
     1080        movzx   ecx, word [ebp + 08h]       ; handle
     1081        mov     [esp], ecx
     1082        call    NAME(FS32_FINDNOTIFYCLOSE)
    7781083VBOXSF_TO_16        FS_FINDNOTIFYCLOSE
    779     retf    2h
     1084        retf    2h
    7801085VBOXSF_EP16_END     FS_FINDNOTIFYCLOSE
    7811086
     
    7881093VBOXSF_EP16_BEGIN   FS_FINDNOTIFYFIRST, 'FS_FINDNOTIFYFIRST'
    7891094VBOXSF_TO_32        FS_FINDNOTIFYFIRST, 11*4
    790     movzx   ecx, word [ebp + 08h]       ; flags
    791     mov     [esp + 10*4], ecx
    792     movzx   edx, word [ebp + 0ah]       ; level
    793     mov     [esp + 9*4], edx
    794     VBOXSF_FARPTR_2_FLAT  0ch, 8*4      ; pcMatch
    795     movzx   eax, word [ebp + 10h]       ; cbData
    796     mov     [esp + 7*4], eax
    797     VBOXSF_FARPTR_2_FLAT  12h, 6*4      ; pbData
    798     VBOXSF_FARPTR_2_FLAT  16h, 5*4      ; pHandle
    799     movzx   ecx, word [ebp + 1ah]       ; attr
    800     mov     [esp + 4*4], ecx
    801     movzx   edx, word [ebp + 1ch]       ; iCurDirEnd
    802     mov     [esp + 3*4], edx
    803     VBOXSF_FARPTR_2_FLAT  1eh, 2*4      ; pszName
    804     VBOXSF_PCDFSD_2_FLAT  22h, 1*4      ; pcdfsd
    805     VBOXSF_FARPTR_2_FLAT  26h, 0*4      ; pcdfsi
    806     call    NAME(FS32_FINDNOTIFYFIRST)
     1095        movzx   ecx, word [ebp + 08h]       ; flags
     1096        mov     [esp + 10*4], ecx
     1097        movzx   edx, word [ebp + 0ah]       ; level
     1098        mov     [esp + 9*4], edx
     1099        VBOXSF_FARPTR_2_FLAT  0ch, 8*4      ; pcMatch
     1100        movzx   eax, word [ebp + 10h]       ; cbData
     1101        mov     [esp + 7*4], eax
     1102        VBOXSF_FARPTR_2_FLAT  12h, 6*4      ; pbData
     1103        VBOXSF_FARPTR_2_FLAT  16h, 5*4      ; pHandle
     1104        movzx   ecx, word [ebp + 1ah]       ; attr
     1105        mov     [esp + 4*4], ecx
     1106        movsx   edx, word [ebp + 1ch]       ; iCurDirEnd
     1107        mov     [esp + 3*4], edx
     1108        VBOXSF_FARPTR_2_FLAT  1eh, 2*4      ; pszName
     1109        VBOXSF_PCDFSD_2_FLAT  22h, 1*4      ; pcdfsd
     1110        VBOXSF_FARPTR_2_FLAT  26h, 0*4      ; pcdfsi
     1111        call    NAME(FS32_FINDNOTIFYFIRST)
    8071112VBOXSF_TO_16        FS_FINDNOTIFYFIRST
    808     retf    22h
     1113        retf    22h
    8091114VBOXSF_EP16_END     FS_FINDNOTIFYFIRST
    8101115
     
    8161121VBOXSF_EP16_BEGIN FS_FINDNOTIFYNEXT, 'FS_FINDNOTIFYNEXT'
    8171122VBOXSF_TO_32        FS_FINDNOTIFYNEXT, 6*4
    818     mov     ecx, [ebp + 08h]            ; timeout
    819     mov     [esp + 5*4], ecx
    820     movzx   edx, word [ebp + 0ch]       ; level
    821     mov     [esp + 4*4], edx
    822     VBOXSF_FARPTR_2_FLAT  0eh, 3*4      ; pcMatch
    823     movzx   eax, word [ebp + 12h]       ; cbData
    824     mov     [esp + 2*4], eax
    825     VBOXSF_FARPTR_2_FLAT  14h, 1*4      ; pbData
    826     movzx   ecx, word [ebp + 18h]       ; handle
    827     mov     [esp], ecx
    828     call    NAME(FS32_FINDNOTIFYNEXT)
     1123        mov     ecx, [ebp + 08h]            ; timeout
     1124        mov     [esp + 5*4], ecx
     1125        movzx   edx, word [ebp + 0ch]       ; level
     1126        mov     [esp + 4*4], edx
     1127        VBOXSF_FARPTR_2_FLAT  0eh, 3*4      ; pcMatch
     1128        movzx   eax, word [ebp + 12h]       ; cbData
     1129        mov     [esp + 2*4], eax
     1130        VBOXSF_FARPTR_2_FLAT  14h, 1*4      ; pbData
     1131        movzx   ecx, word [ebp + 18h]       ; handle
     1132        mov     [esp], ecx
     1133        call    NAME(FS32_FINDNOTIFYNEXT)
    8291134VBOXSF_TO_16        FS_FINDNOTIFYNEXT
    830     retf    12h
     1135        retf    12h
    8311136VBOXSF_EP16_END     FS_FINDNOTIFYNEXT
    8321137
     
    8351140VBOXSF_EP16_BEGIN FS_FLUSHBUF, 'FS_FLUSHBUF'
    8361141VBOXSF_TO_32        FS_FLUSHBUF, 2*4
    837     movzx   edx, word [ebp + 08h]       ; flag
    838     mov     [esp + 1*4], edx
    839     movzx   eax, word [ebp + 0ch]       ; hVPB
    840     mov     [esp + 0*4], eax
    841     call    NAME(FS32_FLUSHBUF)
     1142        movzx   edx, word [ebp + 08h]       ; flag
     1143        mov     [esp + 1*4], edx
     1144        movzx   eax, word [ebp + 0ch]       ; hVPB
     1145        mov     [esp + 0*4], eax
     1146        call    NAME(FS32_FLUSHBUF)
    8421147VBOXSF_TO_16        FS_FLUSHBUF
    843     retf    4h
     1148        retf    4h
    8441149VBOXSF_EP16_END FS_FLUSHBUF
    8451150
     
    8491154;                       PVOID pData, USHORT lenData, PUSHORT plenDataIO);
    8501155VBOXSF_EP16_BEGIN FS_FSCTL, 'FS_FSCTL'
    851     ;
    852     ; Initialized ring-0 yet? (this is a likely first entry point)
    853     ;
    854     push    ds
    855     mov     ax, DATA16
    856     mov     ds, ax
    857     test    byte [NAME(g_fDoneRing0)], 1
    858     jnz     .DoneRing0
    859     call    NAME(VBoxSFR0Init16Bit)
     1156        ;
     1157        ; Initialized ring-0 yet? (this is a likely first entry point)
     1158        ;
     1159        push    ds
     1160        mov     ax, DATA16
     1161        mov     ds, ax
     1162        test    byte [NAME(g_fDoneRing0)], 1
     1163        jnz     .DoneRing0
     1164        call    NAME(VBoxSFR0Init16Bit)
    8601165.DoneRing0:
    861     pop     ds
     1166        pop     ds
    8621167
    8631168VBOXSF_TO_32        FS_FSCTL, 9*4
    864     VBOXSF_FARPTR_2_FLAT  08h, 8*4      ; plenDataIO
    865     movzx   ecx, word [ebp + 0ch]       ; lenData
    866     mov     [esp + 7*4], ecx
    867     VBOXSF_FARPTR_2_FLAT  0eh, 6*4      ; pData
    868     VBOXSF_FARPTR_2_FLAT  12h, 5*4      ; plenDataIO
    869     movzx   ecx, word [ebp + 16h]       ; lenData
    870     mov     [esp + 4*4], ecx
    871     VBOXSF_FARPTR_2_FLAT  18h, 3*4      ; pData
    872     movzx   edx, word [ebp + 1ch]       ; func
    873     mov     [esp + 2*4], edx
    874     movzx   eax, word [ebp + 1eh]       ; iArgType
    875     mov     [esp + 1*4], eax
    876     VBOXSF_FARPTR_2_FLAT  20h, 0*4      ; pArgdat
    877     call    NAME(FS32_FSCTL)
     1169        VBOXSF_FARPTR_2_FLAT  08h, 8*4      ; plenDataIO
     1170        movzx   ecx, word [ebp + 0ch]       ; lenData
     1171        mov     [esp + 7*4], ecx
     1172        VBOXSF_FARPTR_2_FLAT  0eh, 6*4      ; pData
     1173        VBOXSF_FARPTR_2_FLAT  12h, 5*4      ; plenDataIO
     1174        movzx   ecx, word [ebp + 16h]       ; lenData
     1175        mov     [esp + 4*4], ecx
     1176        VBOXSF_FARPTR_2_FLAT  18h, 3*4      ; pData
     1177        movzx   edx, word [ebp + 1ch]       ; func
     1178        mov     [esp + 2*4], edx
     1179        movzx   eax, word [ebp + 1eh]       ; iArgType
     1180        mov     [esp + 1*4], eax
     1181        VBOXSF_FARPTR_2_FLAT  20h, 0*4      ; pArgdat
     1182        call    NAME(FS32_FSCTL)
    8781183VBOXSF_TO_16        FS_FSCTL
    879     retf    1ch
     1184        retf    1ch
    8801185VBOXSF_EP16_END FS_FSCTL
    8811186
     
    8841189VBOXSF_EP16_BEGIN FS_FSINFO, 'FS_FSINFO'
    8851190VBOXSF_TO_32        FS_FSINFO, 5*4
    886     movzx   ecx, word [ebp + 08h]       ; level
    887     mov     [esp + 10h], ecx
    888     movzx   edx, word [ebp + 0ah]       ; cbData
    889     mov     [esp + 0ch], edx
    890     VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; pbData
    891     movzx   edx, word [ebp + 10h]       ; hVPB
    892     mov     [esp], edx
    893     movzx   eax, word [ebp + 12h]       ; flag
    894     mov     [esp], eax
    895     call    NAME(FS32_FSINFO)
     1191        movzx   ecx, word [ebp + 08h]       ; level
     1192        mov     [esp + 10h], ecx
     1193        movzx   edx, word [ebp + 0ah]       ; cbData
     1194        mov     [esp + 0ch], edx
     1195        VBOXSF_FARPTR_2_FLAT  0ch, 2*4      ; pbData
     1196        movzx   edx, word [ebp + 10h]       ; hVPB
     1197        mov     [esp + 4], edx
     1198        movzx   eax, word [ebp + 12h]       ; flag
     1199        mov     [esp], eax
     1200        call    NAME(FS32_FSINFO)
    8961201VBOXSF_TO_16        FS_FSINFO
    897     retf    14h
     1202        retf    14h
    8981203VBOXSF_EP16_END     FS_FSINFO
    8991204
     
    9051210VBOXSF_EP16_BEGIN   FS_IOCTL, 'FS_IOCTL'
    9061211VBOXSF_TO_32        FS_IOCTL, 10*4
    907     VBOXSF_FARPTR_2_FLAT  08h, 9*4      ; plenDataIO
    908     movzx   ecx, word [ebp + 0ch]       ; lenData
    909     mov     [esp + 8*4], ecx
    910     VBOXSF_FARPTR_2_FLAT  0eh, 7*4      ; pData
    911     VBOXSF_FARPTR_2_FLAT  12h, 6*4      ; plenDataIO
    912     movzx   ecx, word [ebp + 16h]       ; lenData
    913     mov     [esp + 5*4], ecx
    914     VBOXSF_FARPTR_2_FLAT  18h, 4*4      ; pData
    915     movzx   edx, word [ebp + 1ch]       ; cat
    916     mov     [esp + 3*4], edx
    917     movzx   eax, word [ebp + 1eh]       ; func
    918     mov     [esp + 2*4], eax
    919     VBOXSF_PSFFSD_2_FLAT  20h, 1*4      ; psffsd
    920     VBOXSF_FARPTR_2_FLAT  24h, 0*4      ; pData
    921     call    NAME(FS32_IOCTL)
     1212        VBOXSF_FARPTR_2_FLAT  08h, 9*4      ; plenDataIO
     1213        movzx   ecx, word [ebp + 0ch]       ; lenData
     1214        mov     [esp + 8*4], ecx
     1215        VBOXSF_FARPTR_2_FLAT  0eh, 7*4      ; pData
     1216        VBOXSF_FARPTR_2_FLAT  12h, 6*4      ; plenDataIO
     1217        movzx   ecx, word [ebp + 16h]       ; lenData
     1218        mov     [esp + 5*4], ecx
     1219        VBOXSF_FARPTR_2_FLAT  18h, 4*4      ; pData
     1220        movzx   edx, word [ebp + 1ch]       ; cat
     1221        mov     [esp + 3*4], edx
     1222        movzx   eax, word [ebp + 1eh]       ; func
     1223        mov     [esp + 2*4], eax
     1224        VBOXSF_PSFFSD_2_FLAT  20h, 1*4      ; psffsd
     1225        VBOXSF_FARPTR_2_FLAT  24h, 0*4      ; pData
     1226        call    NAME(FS32_IOCTL)
    9221227VBOXSF_TO_16        FS_IOCTL
    923     retf    20h
     1228        retf    20h
    9241229VBOXSF_EP16_END     FS_IOCTL
    9251230
     
    9301235VBOXSF_EP16_BEGIN   FS_MKDIR, 'FS_MKDIR'
    9311236VBOXSF_TO_32        FS_MKDIR, 6*4
    932     movzx   ecx, word [ebp + 08h]       ; flag
    933     mov     [esp + 5*4], ecx
    934     VBOXSF_FARPTR_2_FLAT  0ah, 4*4      ; pEABuf
    935     movzx   edx, word [ebp + 0eh]       ; iCurDirEnd
    936     mov     [esp + 3*4], edx
    937     VBOXSF_FARPTR_2_FLAT  10h, 2*4      ; pszName
    938     VBOXSF_PCDFSD_2_FLAT  14h, 1*4      ; pcdfsd
    939     VBOXSF_FARPTR_2_FLAT  18h, 0*4      ; pcdfsi
    940     call    NAME(FS32_MKDIR)
     1237        movzx   ecx, word [ebp + 08h]       ; flag
     1238        mov     [esp + 5*4], ecx
     1239        VBOXSF_FARPTR_2_FLAT  0ah, 4*4      ; pEABuf
     1240        movsx   edx, word [ebp + 0eh]       ; iCurDirEnd
     1241        mov     [esp + 3*4], edx
     1242        VBOXSF_FARPTR_2_FLAT  10h, 2*4      ; pszName
     1243        VBOXSF_PCDFSD_2_FLAT  14h, 1*4      ; pcdfsd
     1244        VBOXSF_FARPTR_2_FLAT  18h, 0*4      ; pcdfsi
     1245        call    NAME(FS32_MKDIR)
    9411246VBOXSF_TO_16        FS_MKDIR
    942     retf    14h
     1247        retf    14h
    9431248VBOXSF_EP16_END     FS_MKDIR
    9441249
     
    9471252; @cproto int FS_MOUNT(USHORT flag, PVPFSI pvpfsi, PVBOXSFVP pvpfsd, USHORT hVPB, PCSZ pszBoot)
    9481253VBOXSF_EP16_BEGIN   FS_MOUNT, 'FS_MOUNT'
    949     ;
    950     ; Initialized ring-0 yet? (this is a likely first entry point)
    951     ;
    952     push    ds
    953     mov     ax, DATA16
    954     mov     ds, ax
    955     test    byte [NAME(g_fDoneRing0)], 1
    956     jnz     .DoneRing0
    957     call    NAME(VBoxSFR0Init16Bit)
     1254        ;
     1255        ; Initialized ring-0 yet? (this is a likely first entry point)
     1256        ;
     1257        push    ds
     1258        mov     ax, DATA16
     1259        mov     ds, ax
     1260        test    byte [NAME(g_fDoneRing0)], 1
     1261        jnz     .DoneRing0
     1262        call    NAME(VBoxSFR0Init16Bit)
    9581263.DoneRing0:
    959     pop     ds
     1264        pop     ds
    9601265
    9611266VBOXSF_TO_32        FS_MOUNT, 5*4
    962     VBOXSF_FARPTR_2_FLAT  08h, 4*4      ; pszBoot
    963     movzx   ecx, word [ebp + 0ch]       ; hVPB
    964     mov     [esp + 3*4], ecx
    965     VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pvpfsd
    966     VBOXSF_FARPTR_2_FLAT  12h, 1*4      ; pvpfsi
    967     movzx   ecx, word [ebp + 16h]       ; flag
    968     mov     [esp], ecx
    969     call    NAME(FS32_MOUNT)
     1267        VBOXSF_FARPTR_2_FLAT  08h, 4*4      ; pszBoot
     1268        movzx   ecx, word [ebp + 0ch]       ; hVPB
     1269        mov     [esp + 3*4], ecx
     1270        VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pvpfsd
     1271        VBOXSF_FARPTR_2_FLAT  12h, 1*4      ; pvpfsi
     1272        movzx   ecx, word [ebp + 16h]       ; flag
     1273        mov     [esp], ecx
     1274        call    NAME(FS32_MOUNT)
    9701275VBOXSF_TO_16        FS_MOUNT
    971     retf    10h
     1276        retf    10h
    9721277VBOXSF_EP16_END     FS_MOUNT
    9731278
     
    9781283VBOXSF_EP16_BEGIN   FS_MOVE, 'FS_MOVE'
    9791284VBOXSF_TO_32        FS_MOVE, 7*4
    980     movzx   ecx, word [ebp + 08h]       ; type
    981     mov     [esp + 6*4], ecx
    982     movzx   edx, word [ebp + 0ah]       ; iDstCurDirEnd
    983     mov     [esp + 5*4], edx
    984     VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pszDst
    985     movzx   eax, word [ebp + 10h]       ; iSrcCurDirEnd
    986     mov     [esp + 3*4], eax
    987     VBOXSF_FARPTR_2_FLAT  12h, 2*4      ; pszSrc
    988     VBOXSF_PCDFSD_2_FLAT  16h, 1*4      ; psffsd
    989     VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; psffsi
    990     call    NAME(FS32_MOVE)
     1285        movzx   ecx, word [ebp + 08h]       ; type
     1286        mov     [esp + 6*4], ecx
     1287        movzx   edx, word [ebp + 0ah]       ; iDstCurDirEnd
     1288        mov     [esp + 5*4], edx
     1289        VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pszDst
     1290        movzx   eax, word [ebp + 10h]       ; iSrcCurDirEnd
     1291        mov     [esp + 3*4], eax
     1292        VBOXSF_FARPTR_2_FLAT  12h, 2*4      ; pszSrc
     1293        VBOXSF_PCDFSD_2_FLAT  16h, 1*4      ; psffsd
     1294        VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; psffsi
     1295        call    NAME(FS32_MOVE)
    9911296VBOXSF_TO_16        FS_MOVE
    992     retf    16h
     1297        retf    16h
    9931298VBOXSF_EP16_END     FS_MOVE
    9941299
     
    9981303VBOXSF_EP16_BEGIN   FS_NEWSIZE, 'FS_NEWSIZE'
    9991304VBOXSF_TO_32        FS_NEWSIZE, 5*4     ; thunking to longlong edition.
    1000     movzx   ecx, word [ebp + 08h]       ; IOflag
    1001     mov     [esp + 4*4], ecx
    1002     mov     eax, [ebp + 0ah]            ; cbFile (ULONG -> LONGLONG)
    1003     mov     dword [esp + 3*4], 0
    1004     mov     [esp + 2*4], eax
    1005     VBOXSF_PSFFSD_2_FLAT  0eh, 1*4      ; psffsd
    1006     VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; psffsi
    1007     call            NAME(FS32_NEWSIZEL)
     1305        movzx   ecx, word [ebp + 08h]       ; IOflag
     1306        mov     [esp + 4*4], ecx
     1307        mov     eax, [ebp + 0ah]            ; cbFile (ULONG -> LONGLONG)
     1308        mov     dword [esp + 3*4], 0
     1309        mov     [esp + 2*4], eax
     1310        VBOXSF_PSFFSD_2_FLAT  0eh, 1*4      ; psffsd
     1311        VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; psffsi
     1312        call            NAME(FS32_NEWSIZEL)
    10081313VBOXSF_TO_16        FS_NEWSIZE
    1009     retf    0eh
     1314        retf    0eh
    10101315VBOXSF_EP16_END     FS_NEWSIZE
    10111316
     
    10151320VBOXSF_EP16_BEGIN FS_NEWSIZEL, 'FS_NEWSIZEL'
    10161321VBOXSF_TO_32        FS_NEWSIZEL, 5*4
    1017     movzx   ecx, word [ebp + 08h]       ; IOflag
    1018     mov     [esp + 4*4], ecx
    1019     mov     eax, [ebp + 0ah]            ; cbFile
    1020     mov     edx, [ebp + 0eh]
    1021     mov     [esp + 3*4], edx
    1022     mov     [esp + 2*4], eax
    1023     VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
    1024     VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
    1025     call            NAME(FS32_NEWSIZEL)
     1322        movzx   ecx, word [ebp + 08h]       ; IOflag
     1323        mov     [esp + 4*4], ecx
     1324        mov     eax, [ebp + 0ah]            ; cbFile
     1325        mov     edx, [ebp + 0eh]
     1326        mov     [esp + 3*4], edx
     1327        mov     [esp + 2*4], eax
     1328        VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
     1329        VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
     1330        call            NAME(FS32_NEWSIZEL)
    10261331VBOXSF_TO_16        FS_NEWSIZEL
    1027     retf    12h
     1332        retf    12h
    10281333VBOXSF_EP16_END FS_NEWSIZEL
    10291334
     
    10341339VBOXSF_EP16_BEGIN   FS_NMPIPE, 'FS_NMPIPE'
    10351340VBOXSF_TO_32        FS_NMPIPE, 6*4
    1036     VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pszName
    1037     VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pData
    1038     VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pOpRec
    1039     movzx   ecx, word [ebp + 14h]       ; OpType
    1040     mov     [esp + 2*4], ecx
    1041     VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; psffsd (take care...)
    1042     VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; psffsi
    1043     call            NAME(FS32_NMPIPE)
     1341        VBOXSF_FARPTR_2_FLAT  08h, 5*4      ; pszName
     1342        VBOXSF_FARPTR_2_FLAT  0ch, 4*4      ; pData
     1343        VBOXSF_FARPTR_2_FLAT  10h, 3*4      ; pOpRec
     1344        movzx   ecx, word [ebp + 14h]       ; OpType
     1345        mov     [esp + 2*4], ecx
     1346        VBOXSF_FARPTR_2_FLAT  16h, 1*4      ; psffsd (take care...)
     1347        VBOXSF_FARPTR_2_FLAT  1ah, 0*4      ; psffsi
     1348        call            NAME(FS32_NMPIPE)
    10441349VBOXSF_TO_16        FS_NMPIPE
    1045     retf    16h
     1350        retf    16h
    10461351VBOXSF_EP16_END     FS_NMPIPE
    10471352
     
    10531358VBOXSF_EP16_BEGIN   FS_OPENCREATE, 'FS_OPENCREATE'
    10541359VBOXSF_TO_32        FS_OPENCREATE, 12*4
    1055     VBOXSF_FARPTR_2_FLAT  08h, 11*4     ; pfgenflag
    1056     VBOXSF_FARPTR_2_FLAT  0ch, 10*4     ; pcEABuf
    1057     movzx   ecx, word [ebp + 10h]       ; usAttr
    1058     mov     [esp + 9*4], ecx
    1059     VBOXSF_FARPTR_2_FLAT  12h, 8*4      ; pusAction
    1060     movzx   edx, word [ebp + 16h]       ; usOpenFlag
    1061     mov     [esp + 7*4], edx
    1062     mov     eax, [ebp + 18h]            ; ulOpenMode
    1063     mov     [esp + 6*4], eax
    1064     VBOXSF_FARPTR_2_FLAT  1ch, 5*4      ; psffsd (new, no short cuts)
    1065     VBOXSF_FARPTR_2_FLAT  20h, 4*4      ; psffsi
    1066     movzx   ecx, word [ebp + 24h]       ; iCurDirEnd
    1067     mov     [esp + 3*4], ecx
    1068     VBOXSF_FARPTR_2_FLAT  26h, 2*4      ; pszName
    1069     VBOXSF_PCDFSD_2_FLAT  2ah, 1*4      ; pcdfsd
    1070     VBOXSF_FARPTR_2_FLAT  2eh, 0*4      ; pcdfsi
    1071     call    NAME(FS32_OPENCREATE)
     1360        VBOXSF_FARPTR_2_FLAT  08h, 11*4     ; pfgenflag
     1361        VBOXSF_FARPTR_2_FLAT  0ch, 10*4     ; pcEABuf
     1362        movzx   ecx, word [ebp + 10h]       ; usAttr
     1363        mov     [esp + 9*4], ecx
     1364        VBOXSF_FARPTR_2_FLAT  12h, 8*4      ; pusAction
     1365        movzx   edx, word [ebp + 16h]       ; usOpenFlag
     1366        mov     [esp + 7*4], edx
     1367        mov     eax, [ebp + 18h]            ; ulOpenMode
     1368        mov     [esp + 6*4], eax
     1369        VBOXSF_FARPTR_2_FLAT  1ch, 5*4      ; psffsd (new, no short cuts)
     1370        VBOXSF_FARPTR_2_FLAT  20h, 4*4      ; psffsi
     1371        movsx   ecx, word [ebp + 24h]       ; iCurDirEnd
     1372        mov     [esp + 3*4], ecx
     1373        VBOXSF_FARPTR_2_FLAT  26h, 2*4      ; pszName
     1374        VBOXSF_PCDFSD_2_FLAT  2ah, 1*4      ; pcdfsd
     1375        VBOXSF_FARPTR_2_FLAT  2eh, 0*4      ; pcdfsi
     1376        call    NAME(FS32_OPENCREATE)
    10721377VBOXSF_TO_16        FS_OPENCREATE
    1073     retf    42
     1378        retf    42
    10741379VBOXSF_EP16_END FS_OPENCREATE
    10751380
     
    10801385VBOXSF_EP16_BEGIN   FS_OPENPAGEFILE, 'FS_OPENPAGEFILE'
    10811386VBOXSF_TO_32        FS_OPENPAGEFILE, 9*4
    1082     mov     ecx, [ebp + 08h]            ; Reserved
    1083     mov     [esp + 8*4], ecx
    1084     movzx   edx, word [ebp + 0ch]       ; usAttr
    1085     mov     [esp + 7*4], edx
    1086     movzx   eax, word [ebp + 0eh]       ; usOpenFlag
    1087     mov     [esp + 6*4], eax
    1088     movzx   ecx, word [ebp + 10h]       ; usOpenMode
    1089     mov     [esp + 5*4], ecx
    1090     VBOXSF_FARPTR_2_FLAT  12h, 4*4      ; psffsd (new, no short cuts)
    1091     VBOXSF_FARPTR_2_FLAT  16h, 3*4      ; psffsi
    1092     VBOXSF_FARPTR_2_FLAT  1ah, 2*4      ; pszName
    1093     VBOXSF_FARPTR_2_FLAT  1eh, 1*4      ; pcMaxReq
    1094     VBOXSF_FARPTR_2_FLAT  22h, 0*4      ; pFlag
    1095     call    NAME(FS32_OPENPAGEFILE)
     1387        mov     ecx, [ebp + 08h]            ; Reserved
     1388        mov     [esp + 8*4], ecx
     1389        movzx   edx, word [ebp + 0ch]       ; usAttr
     1390        mov     [esp + 7*4], edx
     1391        movzx   eax, word [ebp + 0eh]       ; usOpenFlag
     1392        mov     [esp + 6*4], eax
     1393        movzx   ecx, word [ebp + 10h]       ; usOpenMode
     1394        mov     [esp + 5*4], ecx
     1395        VBOXSF_FARPTR_2_FLAT  12h, 4*4      ; psffsd (new, no short cuts)
     1396        VBOXSF_FARPTR_2_FLAT  16h, 3*4      ; psffsi
     1397        VBOXSF_FARPTR_2_FLAT  1ah, 2*4      ; pszName
     1398        VBOXSF_FARPTR_2_FLAT  1eh, 1*4      ; pcMaxReq
     1399        VBOXSF_FARPTR_2_FLAT  22h, 0*4      ; pFlag
     1400        call    NAME(FS32_OPENPAGEFILE)
    10961401VBOXSF_TO_16        FS_OPENPAGEFILE
    1097     retf    1eh
     1402        retf    1eh
    10981403VBOXSF_EP16_END     FS_OPENPAGEFILE
    10991404
     
    11041409VBOXSF_EP16_BEGIN   FS_PATHINFO, 'FS_PATHINFO'
    11051410VBOXSF_TO_32        FS_PATHINFO, 8*4
    1106     movzx   ecx, word [ebp + 08h]       ; cbData
    1107     mov     [esp + 7*4], ecx
    1108     VBOXSF_FARPTR_2_FLAT  0ah, 6*4      ; pData
    1109     movzx   edx, word [ebp + 0eh]       ; level
    1110     mov     [esp + 5*4], edx
    1111     movzx   eax, word [ebp + 10h]       ; iCurDirEnd
    1112     mov     [esp + 4*4], eax
    1113     VBOXSF_FARPTR_2_FLAT  12h, 3*4      ; pszName
    1114     VBOXSF_PCDFSD_2_FLAT  16h, 2*4      ; pcdfsd
    1115     VBOXSF_FARPTR_2_FLAT  1ah, 1*4      ; pcdfsi
    1116     movzx   edx, word [ebp + 1eh]       ; flag
    1117     mov     [esp], edx
    1118     call    NAME(FS32_PATHINFO)
     1411        movzx   ecx, word [ebp + 08h]       ; cbData
     1412        mov     [esp + 7*4], ecx
     1413        VBOXSF_FARPTR_2_FLAT  0ah, 6*4      ; pData
     1414        movzx   edx, word [ebp + 0eh]       ; level
     1415        mov     [esp + 5*4], edx
     1416        movsx   eax, word [ebp + 10h]       ; iCurDirEnd
     1417        mov     [esp + 4*4], eax
     1418        VBOXSF_FARPTR_2_FLAT  12h, 3*4      ; pszName
     1419        VBOXSF_PCDFSD_2_FLAT  16h, 2*4      ; pcdfsd
     1420        VBOXSF_FARPTR_2_FLAT  1ah, 1*4      ; pcdfsi
     1421        movzx   edx, word [ebp + 1eh]       ; flag
     1422        mov     [esp], edx
     1423        call    NAME(FS32_PATHINFO)
    11191424VBOXSF_TO_16        FS_PATHINFO
    1120     retf    18h
     1425        retf    18h
    11211426VBOXSF_EP16_END     FS_PATHINFO
    11221427
     
    11251430VBOXSF_EP16_BEGIN FS_PROCESSNAME, 'FS_PROCESSNAME'
    11261431VBOXSF_TO_32        FS_PROCESSNAME, 1*4
    1127     VBOXSF_FARPTR_2_FLAT  08h, 0*4      ; pszName
    1128     call    NAME(FS32_PROCESSNAME)
     1432        VBOXSF_FARPTR_2_FLAT  08h, 0*4      ; pszName
     1433        call    NAME(FS32_PROCESSNAME)
    11291434VBOXSF_TO_16        FS_PROCESSNAME
    1130     retf    4h
     1435        retf    4h
    11311436VBOXSF_EP16_END FS_PROCESSNAME
    11321437
     
    11361441VBOXSF_EP16_BEGIN   FS_READ, 'FS_READ'
    11371442VBOXSF_TO_32        FS_READ, 6*4        ; extra local for ULONG cbDataTmp.
    1138     movzx   ecx, word [ebp + 08h]       ; IOflag
    1139     mov     [esp + 4*4], ecx
    1140     les     dx, [ebp + 0ah]             ; cbDataTmp = *pcbData;
    1141     movzx   edx, dx
    1142     lea     ecx, [esp + 5*4]            ; pcbData = &cbDataTmp
    1143     movzx   eax, word [es:edx]
    1144     mov     [ecx], eax
    1145     mov     [esp + 3*4], ecx
    1146     mov     edx, DATA32
    1147     mov     es, edx
    1148     VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pbData
    1149     VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
    1150     VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
    1151     call    FS32_READ
    1152 
    1153     les     dx, [ebp + 0ah]             ; *pcbData = cbDataTmp;
    1154     movzx   edx, dx
    1155     mov     cx, [esp + 5*4]
    1156     mov     [es:edx], cx
    1157     mov     edx, DATA32
    1158     mov     es, edx
     1443        movzx   ecx, word [ebp + 08h]       ; IOflag
     1444        mov     [esp + 4*4], ecx
     1445        les     dx, [ebp + 0ah]             ; cbDataTmp = *pcbData;
     1446        movzx   edx, dx
     1447        lea     ecx, [esp + 5*4]            ; pcbData = &cbDataTmp
     1448        movzx   eax, word [es:edx]
     1449        mov     [ecx], eax
     1450        mov     [esp + 3*4], ecx
     1451        mov     edx, DATA32
     1452        mov     es, edx
     1453        VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pbData
     1454        VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
     1455        VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
     1456        call    FS32_READ
     1457
     1458        les     dx, [ebp + 0ah]             ; *pcbData = cbDataTmp;
     1459        movzx   edx, dx
     1460        mov     cx, [esp + 5*4]
     1461        mov     [es:edx], cx
     1462        mov     edx, DATA32
     1463        mov     es, edx
    11591464
    11601465VBOXSF_TO_16        FS_READ
    1161 
    1162     pop     es
    1163     retf    12h
     1466        retf    12h
    11641467VBOXSF_EP16_END     FS_READ
    11651468
     
    11701473VBOXSF_EP16_BEGIN   FS_RMDIR, 'FS_RMDIR'
    11711474VBOXSF_TO_32        FS_RMDIR, 4*4
    1172     movzx   edx, word [ebp + 08h]       ; iCurDirEnd
    1173     mov     [esp + 3*4], edx
    1174     VBOXSF_FARPTR_2_FLAT  0ah, 2*4      ; pszName
    1175     VBOXSF_PCDFSD_2_FLAT  0eh, 1*4      ; pcdfsd
    1176     VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; pcdfsi
    1177     call    NAME(FS32_RMDIR)
     1475        movsx   edx, word [ebp + 08h]       ; iCurDirEnd
     1476        mov     [esp + 3*4], edx
     1477        VBOXSF_FARPTR_2_FLAT  0ah, 2*4      ; pszName
     1478        VBOXSF_PCDFSD_2_FLAT  0eh, 1*4      ; pcdfsd
     1479        VBOXSF_FARPTR_2_FLAT  12h, 0*4      ; pcdfsi
     1480        call    NAME(FS32_RMDIR)
    11781481VBOXSF_TO_16        FS_RMDIR
    1179     retf    14h
     1482        retf    0eh
    11801483VBOXSF_EP16_END     FS_RMDIR
    11811484
     
    11861489VBOXSF_EP16_BEGIN FS_SETSWAP, 'FS_SETSWAP'
    11871490VBOXSF_TO_32        FS_SETSWAP, 2*4
    1188     VBOXSF_PSFFSD_2_FLAT  08h, 1*4      ; psffsd
    1189     VBOXSF_FARPTR_2_FLAT  0ch, 0*4      ; psffsi
    1190     call    NAME(FS32_SETSWAP)
     1491        VBOXSF_PSFFSD_2_FLAT  08h, 1*4      ; psffsd
     1492        VBOXSF_FARPTR_2_FLAT  0ch, 0*4      ; psffsi
     1493        call    NAME(FS32_SETSWAP)
    11911494VBOXSF_TO_16        FS_SETSWAP
    1192     retf    8h
     1495        retf    8h
    11931496VBOXSF_EP16_END     FS_SETSWAP
    11941497
     
    11991502VBOXSF_EP16_BEGIN   FS_SHUTDOWN, 'FS_SHUTDOWN'
    12001503VBOXSF_TO_32        FS_SHUTDOWN, 3*4
    1201     mov     ecx, [ebp + 08h]            ; type
    1202     mov     [esp + 1*4], edx
    1203     movzx   edx, word [ebp + 0ah]       ; reserved
    1204     mov     [esp], eax
    1205     call    NAME(FS32_SHUTDOWN)
     1504        mov     ecx, [ebp + 0ch]            ; type
     1505        mov     [esp + 1*4], edx
     1506        movzx   edx, word [ebp + 08h]       ; reserved
     1507        mov     [esp], eax
     1508        call    NAME(FS32_SHUTDOWN)
    12061509VBOXSF_TO_16        FS_SHUTDOWN
    1207     retf    6h
     1510        retf    6h
    12081511VBOXSF_EP16_END     FS_SHUTDOWN
     1512
     1513
     1514;;
     1515; @cproto int FS_VERIFYUNCNAME(USHORT type, PCSZ pszName);
     1516;
     1517VBOXSF_EP16_BEGIN   FS_VERIFYUNCNAME, 'FS_VERIFYUNCNAME'
     1518VBOXSF_TO_32        FS_VERIFYUNCNAME, 3*4
     1519        VBOXSF_FARPTR_2_FLAT  08h, 1*4      ; pszDev
     1520        movzx   ecx, word [ebp + 0ch]       ; fFlag
     1521        mov     [esp], ecx
     1522        call    NAME(FS32_VERIFYUNCNAME)
     1523VBOXSF_TO_16        FS_VERIFYUNCNAME
     1524        retf    6h
     1525VBOXSF_EP16_END     FS_VERIFYUNCNAME
    12091526
    12101527
     
    12131530VBOXSF_EP16_BEGIN   FS_WRITE, 'FS_WRITE'
    12141531VBOXSF_TO_32        FS_WRITE, 6*4       ; extra local for ULONG cbDataTmp.
    1215     movzx   ecx, word [ebp + 08h]       ; IOflag
    1216     mov     [esp + 4*4], ecx
    1217     les     dx, [ebp + 0ah]             ; cbDataTmp = *pcbData;
    1218     movzx   edx, dx
    1219     lea     ecx, [esp + 5*4]            ; pcbData = &cbDataTmp
    1220     movzx   eax, word [es:edx]
    1221     mov     [ecx], eax
    1222     mov     [esp + 3*4], ecx
    1223     mov     edx, DATA32
    1224     mov     es, edx
    1225     VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pbData
    1226     VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
    1227     VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
    1228     call    FS32_WRITE
    1229 
    1230     les     dx, [ebp + 0ah]             ; *pcbData = cbDataTmp;
    1231     movzx   edx, dx
    1232     mov     cx, [esp + 5*4]
    1233     mov     [es:edx], cx
    1234     mov     edx, DATA32
    1235     mov     es, edx
     1532        movzx   ecx, word [ebp + 08h]       ; IOflag
     1533        mov     [esp + 4*4], ecx
     1534        les     dx, [ebp + 0ah]             ; cbDataTmp = *pcbData;
     1535        movzx   edx, dx
     1536        lea     ecx, [esp + 5*4]            ; pcbData = &cbDataTmp
     1537        movzx   eax, word [es:edx]
     1538        mov     [ecx], eax
     1539        mov     [esp + 3*4], ecx
     1540        mov     edx, DATA32
     1541        mov     es, edx
     1542        VBOXSF_FARPTR_2_FLAT  0eh, 2*4      ; pbData
     1543        VBOXSF_PSFFSD_2_FLAT  12h, 1*4      ; psffsd
     1544        VBOXSF_FARPTR_2_FLAT  16h, 0*4      ; psffsi
     1545        call    FS32_WRITE
     1546
     1547        les     dx, [ebp + 0ah]             ; *pcbData = cbDataTmp;
     1548        movzx   edx, dx
     1549        mov     cx, [esp + 5*4]
     1550        mov     [es:edx], cx
     1551        mov     edx, DATA32
     1552        mov     es, edx
    12361553
    12371554VBOXSF_TO_16        FS_WRITE
    1238 
    1239     pop     es
    1240     retf    12h
     1555        retf    12h
    12411556VBOXSF_EP16_END     FS_WRITE
    12421557
     1558
     1559;
     1560;
     1561; Calling 16-bit kernel code.
     1562;
     1563;
     1564
     1565BEGINCODE
     1566
     1567;;
     1568; Wrapper around FSH_GETVOLPARM.
     1569;
     1570; @returns  VPBFSD.
     1571; @param    hVbp            The volume handle to resolve.
     1572; @param    ppVbpFsi
     1573;
     1574BEGINPROC       Fsh32GetVolParams
     1575VBOXSF_FROM_32  Fsh32GetVolParams, 2*4
     1576        mov     di, sp                  ; make the top of the stack addressable via di
     1577
     1578        mov     [ss:di], eax            ; clear the return variables
     1579        mov     [ss:di + 4], eax
     1580
     1581        mov     ax, [bp + 8]            ; hVbp
     1582        push    ax
     1583
     1584        lea     ax, [ss:di]             ; &hvfsi
     1585        push    ss
     1586        push    ax
     1587
     1588        lea     ax, [ss:di + 4]         ; &hvfsd
     1589        push    ss
     1590        push    ax
     1591
     1592        call far FSH_GETVOLPARM
     1593
     1594        mov     sp, di                  ; paranoia (pascal pops params)
     1595
     1596VBOXSF_FROM_16_SWITCH Fsh32GetVolParams
     1597
     1598        ; Convert vpfsi to flat and store it in return location.
     1599        mov     ebx, [ebp + 0ch]
     1600        test    ebx, ebx
     1601        jz      .no_vpfsi
     1602        call    KernSelToFlat
     1603        mov     [ebx], eax
     1604.no_vpfsi:
     1605        add     esp, 4
     1606
     1607        ; Convert vpfsd to flat and return it.
     1608        call    KernSelToFlat
     1609
     1610VBOXSF_FROM_16_EPILOGUE
     1611        ret
     1612ENDPROC     Fsh32GetVolParams
    12431613
    12441614
     
    12641634VBOXSF_EP16_BEGIN FS_INIT, 'FS_INIT'
    12651635;    DEBUG_STR16 'VBoxSF: FS_INIT - enter'
    1266     push    ebp
    1267     mov     ebp, esp
    1268     push    ds                          ; bp - 02h
    1269     push    es                          ; bp - 04h
    1270     push    esi                         ; bp - 08h
    1271     push    edi                         ; bp - 0ch
    1272 
    1273     mov     ax, DATA16
    1274     mov     ds, ax
    1275     mov     es, ax
    1276 
    1277     ;
    1278     ; Save the device help entry point.
    1279     ;
    1280     mov     eax, [bp + 0ch]
    1281     mov     [NAME(g_fpfnDevHlp)], eax
    1282 
    1283     ;
    1284     ; Parse the command line.
    1285     ; Doing this in assembly is kind of ugly...
    1286     ;
    1287     cmp     word [bp + 10h + 2], 3
    1288     jbe near .no_command_line
    1289     lds     si, [bp + 10h]              ; ds:si -> command line iterator.
     1636        push    ebp
     1637        mov     ebp, esp
     1638        push    ds                          ; bp - 02h
     1639        push    es                          ; bp - 04h
     1640        push    esi                         ; bp - 08h
     1641        push    edi                         ; bp - 0ch
     1642
     1643        mov     ax, DATA16
     1644        mov     ds, ax
     1645        mov     es, ax
     1646
     1647        ;
     1648        ; Save the device help entry point.
     1649        ;
     1650        mov     eax, [bp + 0ch]
     1651        mov     [NAME(g_fpfnDevHlp)], eax
     1652
     1653        ;
     1654        ; Parse the command line.
     1655        ; Doing this in assembly is kind of ugly...
     1656        ;
     1657        cmp     word [bp + 10h + 2], 3
     1658        jbe near .no_command_line
     1659        lds     si, [bp + 10h]              ; ds:si -> command line iterator.
    12901660.parse_next:
    12911661
    1292     ; skip leading blanks.
     1662        ; skip leading blanks.
    12931663.parse_next_char:
    1294     mov     di, si                      ; DI = start of argument.
    1295     lodsb
    1296     cmp     al, ' '
    1297     je      .parse_next_char
    1298     cmp     al, 9                       ; tab
    1299     je      .parse_next_char
    1300     cmp     al, 0
    1301     je near .parse_done
    1302 
    1303     ; check for '/' or '-'
    1304     cmp     al, '/'
    1305     je      .parse_switch
    1306     cmp     al, '-'
    1307     je      .parse_switch
    1308     jmp     .parse_error
    1309 
    1310     ; parse switches.
     1664        mov     di, si                      ; DI = start of argument.
     1665        lodsb
     1666        cmp     al, ' '
     1667        je      .parse_next_char
     1668        cmp     al, 9                       ; tab
     1669        je      .parse_next_char
     1670        cmp     al, 0
     1671        je near .parse_done
     1672
     1673        ; check for '/' or '-'
     1674        cmp     al, '/'
     1675        je      .parse_switch
     1676        cmp     al, '-'
     1677        je      .parse_switch
     1678        jmp     .parse_error
     1679
     1680        ; parse switches.
    13111681.parse_switch:
    1312     lodsb
    1313     cmp     al, 0
    1314     je      .parse_error
    1315     and     al, ~20h                    ; uppercase
    1316 
    1317     cmp     al, 'V'                     ; /V - verbose
    1318     je      .parse_verbose
    1319     cmp     al, 'Q'                     ; /Q - quiet.
    1320     je      .parse_quiet
    1321     jmp     .parse_error
     1682        lodsb
     1683        cmp     al, 0
     1684        je      .parse_error
     1685        and     al, ~20h                    ; uppercase
     1686
     1687        cmp     al, 'V'                     ; /V - verbose
     1688        je      .parse_verbose
     1689        cmp     al, 'Q'                     ; /Q - quiet.
     1690        je      .parse_quiet
     1691        jmp     .parse_error
    13221692
    13231693.parse_verbose:
    1324     mov     byte [es:NAME(g_fVerbose)], 1
    1325     jmp     .parse_next
     1694        mov     byte [es:NAME(g_fVerbose)], 1
     1695        jmp     .parse_next
    13261696
    13271697.parse_quiet:
    1328     mov     byte [es:NAME(g_fVerbose)], 0
    1329     jmp     .parse_next
     1698        mov     byte [es:NAME(g_fVerbose)], 0
     1699        jmp     .parse_next
    13301700
    13311701.parse_error:
    13321702segment DATA16
    13331703.szSyntaxError:
    1334     db 0dh, 0ah, 'VBoxSF.ifs: command line parse error at: ', 0
     1704        db 0dh, 0ah, 'VBoxSF.ifs: command line parse error at: ', 0
    13351705.szNewLine:
    1336     db 0dh, 0ah, 0dh, 0ah, 0
     1706        db 0dh, 0ah, 0dh, 0ah, 0
    13371707segment CODE16
    1338     mov     bx, .szSyntaxError
    1339     call    NAME(FS_INIT_FPUTS)
    1340 
    1341     push    es
    1342     push    ds
    1343     pop     es
    1344     mov     bx, di
    1345     call    NAME(FS_INIT_FPUTS)
    1346     pop     es
    1347 
    1348     mov     bx, .szNewLine
    1349     call    NAME(FS_INIT_FPUTS)
    1350 
    1351     mov     ax, ERROR_INVALID_PARAMETER
    1352     jmp     .done
     1708        mov     bx, .szSyntaxError
     1709        call    NAME(FS_INIT_FPUTS)
     1710
     1711        push    es
     1712        push    ds
     1713        pop     es
     1714        mov     bx, di
     1715        call    NAME(FS_INIT_FPUTS)
     1716        pop     es
     1717
     1718        mov     bx, .szNewLine
     1719        call    NAME(FS_INIT_FPUTS)
     1720
     1721        mov     ax, ERROR_INVALID_PARAMETER
     1722        jmp     .done
    13531723
    13541724.parse_done:
    1355     mov     ax, DATA16
    1356     mov     ds, ax
     1725        mov     ax, DATA16
     1726        mov     ds, ax
    13571727.no_command_line:
    13581728
    1359     ;
    1360     ; Write our greeting to STDOUT.
    1361     ; APIRET  _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
    1362     ;
    1363     cmp     byte [NAME(g_fVerbose)], 0
    1364     je near .quiet
     1729        ;
     1730        ; Write our greeting to STDOUT.
     1731        ; APIRET  _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
     1732        ;
     1733        cmp     byte [NAME(g_fVerbose)], 0
     1734        je near .quiet
    13651735segment DATA16
    13661736.szMessage:
    1367     db 'VirtualBox Guest Additions IFS for OS/2', 0dh, 0ah, 0
     1737        db 'VirtualBox Guest Additions IFS for OS/2', 0dh, 0ah, 0
    13681738segment CODE16
    1369     mov     bx, .szMessage
    1370     call    NAME(FS_INIT_FPUTS)
     1739        mov     bx, .szMessage
     1740        call    NAME(FS_INIT_FPUTS)
    13711741.quiet:
    13721742
    1373     ; return success.
    1374     xor     eax, eax
     1743        ; return success.
     1744        xor     eax, eax
    13751745.done:
    1376     lea     sp, [bp - 0ch]
    1377     pop     edi
    1378     pop     esi
    1379     pop     es
    1380     pop     ds
    1381     mov     esp, ebp
    1382     pop     ebp
    1383     DEBUG_STR16 'VBoxSF: FS_INIT - leave'
    1384     retf    0ch
     1746        lea     sp, [bp - 0ch]
     1747        pop     edi
     1748        pop     esi
     1749        pop     es
     1750        pop     ds
     1751        mov     esp, ebp
     1752        pop     ebp
     1753        DEBUG_STR16 'VBoxSF: FS_INIT - leave'
     1754        retf    0ch
    13851755VBOXSF_EP16_END FS_INIT
    13861756
     
    13921762; @uses     nothing.
    13931763GLOBALNAME FS_INIT_FPUTS
    1394     push    bp
    1395     mov     bp, sp
    1396     push    es                          ; bp - 02h
    1397     push    ds                          ; bp - 04h
    1398     push    ax                          ; bp - 06h
    1399     push    bx                          ; bp - 08h
    1400     push    cx                          ; bp - 0ah
    1401     push    dx                          ; bp - 0ch
    1402     push    si                          ; bp - 0eh
    1403     push    di                          ; bp - 10h
    1404 
    1405     ; cx = strlen(es:bx)
    1406     xor     al, al
    1407     mov     di, bx
    1408     mov     cx, 0ffffh
    1409     cld
    1410     repne scasb
    1411     not     cx
    1412     dec     cx
    1413 
    1414     ; APIRET  _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
    1415     push    cx
    1416     mov     ax, sp                      ; cbBytesWritten
    1417     push    1                           ; STDOUT
    1418     push    es                          ; pvBuf
    1419     push    bx
    1420     push    cx                          ; cbBuf
    1421     push    ss                          ; pcbBytesWritten
    1422     push    ax
     1764        push    bp
     1765        mov     bp, sp
     1766        push    es                          ; bp - 02h
     1767        push    ds                          ; bp - 04h
     1768        push    ax                          ; bp - 06h
     1769        push    bx                          ; bp - 08h
     1770        push    cx                          ; bp - 0ah
     1771        push    dx                          ; bp - 0ch
     1772        push    si                          ; bp - 0eh
     1773        push    di                          ; bp - 10h
     1774
     1775        ; cx = strlen(es:bx)
     1776        xor     al, al
     1777        mov     di, bx
     1778        mov     cx, 0ffffh
     1779        cld
     1780        repne scasb
     1781        not     cx
     1782        dec     cx
     1783
     1784        ; APIRET  _Pascal DosWrite(HFILE hf, PVOID pvBuf, USHORT cbBuf, PUSHORT pcbBytesWritten);
     1785        push    cx
     1786        mov     ax, sp                      ; cbBytesWritten
     1787        push    1                           ; STDOUT
     1788        push    es                          ; pvBuf
     1789        push    bx
     1790        push    cx                          ; cbBuf
     1791        push    ss                          ; pcbBytesWritten
     1792        push    ax
    14231793%if 0 ; wlink/nasm generates a non-aliased fixup here which results in 16-bit offset with the flat 32-bit selector.
    1424     call far DOS16WRITE
     1794        call far DOS16WRITE
    14251795%else
    1426     ; convert flat pointer to a far pointer using the tiled algorithm.
    1427     mov     ax, DATA32 wrt FLAT
    1428     mov     ds, ax
    1429     mov     eax, g_pfnDos16Write wrt FLAT
    1430     movzx   eax, word [eax + 2]                     ; High word of the flat address (in DATA32).
    1431     shl     ax, 3
    1432     or      ax, 0007h
    1433     mov     dx, DATA16
    1434     mov     ds, dx
    1435     mov     [NAME(g_fpfnDos16Write) + 2], ax        ; Update the selector (in DATA16).
    1436     ; do the call
    1437     call far [NAME(g_fpfnDos16Write)]
     1796        ; convert flat pointer to a far pointer using the tiled algorithm.
     1797        mov     ax, DATA32 wrt FLAT
     1798        mov     ds, ax
     1799        mov     eax, g_pfnDos16Write wrt FLAT
     1800        movzx   eax, word [eax + 2]                     ; High word of the flat address (in DATA32).
     1801        shl     ax, 3
     1802        or      ax, 0007h
     1803        mov     dx, DATA16
     1804        mov     ds, dx
     1805        mov     [NAME(g_fpfnDos16Write) + 2], ax        ; Update the selector (in DATA16).
     1806        ; do the call
     1807        call far [NAME(g_fpfnDos16Write)]
    14381808%endif
    14391809
    1440     lea     sp, [bp - 10h]
    1441     pop     di
    1442     pop     si
    1443     pop     dx
    1444     pop     cx
    1445     pop     bx
    1446     pop     ax
    1447     pop     ds
    1448     pop     es
    1449     pop     bp
    1450     ret
     1810        lea     sp, [bp - 10h]
     1811        pop     di
     1812        pop     si
     1813        pop     dx
     1814        pop     cx
     1815        pop     bx
     1816        pop     ax
     1817        pop     ds
     1818        pop     es
     1819        pop     bp
     1820        ret
    14511821ENDPROC FS_INIT_FPUTS
    14521822
     
    14591829;
    14601830GLOBALNAME VBoxSFR0Init16Bit
    1461     DEBUG_STR16 'VBoxSF: VBoxSFR0Init16Bit - enter'
    1462     push    ds
    1463     push    es
    1464     push    fs
    1465     push    gs
    1466     push    esi
    1467     push    edi
    1468     push    ebp
    1469     mov     ebp, esp
    1470     and     sp, 0fffch
    1471 
    1472     ;
    1473     ; Only try once.
    1474     ;
    1475     mov     ax, DATA16
    1476     mov     ds, ax
    1477     mov     byte [NAME(g_fDoneRing0)], 1
    1478 
    1479     ;
    1480     ; Try attach to the VBoxGuest driver.
    1481     ;
    1482     mov     bx, NAME(g_szVBoxGuestName)
    1483     mov     di, NAME(g_VBoxGuestAttachDD)
    1484     mov     dl, DevHlp_AttachDD
    1485     call far [NAME(g_fpfnDevHlp)]
    1486     jc      .attach_attempt_done
    1487 
    1488     push    seg NAME(g_VBoxGuestIDC)
    1489     push    NAME(g_VBoxGuestIDC)
    1490     call far [NAME(g_VBoxGuestAttachDD) + 6]
     1831        DEBUG_STR16 'VBoxSF: VBoxSFR0Init16Bit - enter'
     1832        push    ds
     1833        push    es
     1834        push    fs
     1835        push    gs
     1836        push    esi
     1837        push    edi
     1838        push    ebp
     1839        mov     ebp, esp
     1840        and     sp, 0fffch
     1841
     1842        ;
     1843        ; Only try once.
     1844        ;
     1845        mov     ax, DATA16
     1846        mov     ds, ax
     1847        mov     byte [NAME(g_fDoneRing0)], 1
     1848
     1849        ;
     1850        ; Try attach to the VBoxGuest driver.
     1851        ;
     1852        mov     bx, NAME(g_szVBoxGuestName)
     1853        mov     di, NAME(g_VBoxGuestAttachDD)
     1854        mov     dl, DevHlp_AttachDD
     1855        call far [NAME(g_fpfnDevHlp)]
     1856        jc      .attach_attempt_done
     1857
     1858        push    seg NAME(g_VBoxGuestIDC)
     1859        push    NAME(g_VBoxGuestIDC)
     1860        call far [NAME(g_VBoxGuestAttachDD) + 6]
    14911861.attach_attempt_done:
    14921862
    14931863%ifndef DONT_LOCK_SEGMENTS
    1494     ;
    1495     ; Lock the two 16-bit segments.
    1496     ;
    1497     push    DATA16
    1498     call far FSH_FORCENOSWAP
    1499     push    CODE16
    1500     call far FSH_FORCENOSWAP
    1501     ; Wonder if this'll work if wlink could mark the two segments as ALIASed...
    1502     ;push DATA32
    1503     ;call far FSH_FORCENOSWAP
    1504     ;push TEXT32
    1505     ;call far FSH_FORCENOSWAP
     1864        ;
     1865        ; Lock the two 16-bit segments.
     1866        ;
     1867        push    DATA16
     1868        call far FSH_FORCENOSWAP
     1869        push    CODE16
     1870        call far FSH_FORCENOSWAP
     1871        ; Wonder if this'll work if wlink could mark the two segments as ALIASed...
     1872        ;push DATA32
     1873        ;call far FSH_FORCENOSWAP
     1874        ;push TEXT32
     1875        ;call far FSH_FORCENOSWAP
    15061876%endif
    15071877
    1508     ;
    1509     ; Do 32-bit ring-0 init.
    1510     ;
    1511     ;jmp far dword NAME(VBoxSFR0Init16Bit_32) wrt FLAT
    1512     db      066h
    1513     db      0eah
    1514     dd      NAME(VBoxSFR0Init16Bit_32) ;wrt FLAT
    1515     dw      TEXT32 wrt FLAT
     1878        ;
     1879        ; Do 32-bit ring-0 init.
     1880        ;
     1881        ;jmp far dword NAME(VBoxSFR0Init16Bit_32) wrt FLAT
     1882        db      066h
     1883        db      0eah
     1884        dd      NAME(VBoxSFR0Init16Bit_32) ;wrt FLAT
     1885        dw      TEXT32 wrt FLAT
    15161886segment TEXT32
    15171887GLOBALNAME VBoxSFR0Init16Bit_32
    1518     mov     ax, DATA32 wrt FLAT
    1519     mov     ds, ax
    1520     mov     es, ax
    1521 
    1522     call    KernThunkStackTo32
    1523     call    NAME(VBoxSFR0Init)
    1524     call    KernThunkStackTo16
    1525 
    1526     ;jmp far dword NAME(VBoxSFR0Init16Bit_16) wrt CODE16
    1527     db      066h
    1528     db      0eah
    1529     dw      NAME(VBoxSFR0Init16Bit_16) wrt CODE16
    1530     dw      CODE16
     1888        mov     ax, DATA32 wrt FLAT
     1889        mov     ds, ax
     1890        mov     es, ax
     1891
     1892        call    KernThunkStackTo32
     1893        call    NAME(VBoxSFR0Init)
     1894        call    KernThunkStackTo16
     1895
     1896        ;jmp far dword NAME(VBoxSFR0Init16Bit_16) wrt CODE16
     1897        db      066h
     1898        db      0eah
     1899        dw      NAME(VBoxSFR0Init16Bit_16) wrt CODE16
     1900        dw      CODE16
    15311901segment CODE16
    15321902GLOBALNAME VBoxSFR0Init16Bit_16
    15331903
    1534     mov     esp, ebp
    1535     pop     ebp
    1536     pop     edi
    1537     pop     esi
    1538     pop     gs
    1539     pop     fs
    1540     pop     es
    1541     pop     ds
    1542     DEBUG_STR16 'VBoxSF: VBoxSFR0Init16Bit - leave'
    1543     ret
     1904        mov     esp, ebp
     1905        pop     ebp
     1906        pop     edi
     1907        pop     esi
     1908        pop     gs
     1909        pop     fs
     1910        pop     es
     1911        pop     ds
     1912        DEBUG_STR16 'VBoxSF: VBoxSFR0Init16Bit - leave'
     1913        ret
    15441914ENDPROC VBoxSFR0Init16Bit
    15451915
     
    15511921;
    15521922GLOBALNAME dbgstr16
    1553     push    ds
    1554     push    ebx
    1555     push    edx
    1556 
    1557     mov     bx, ax
    1558     mov     dx, 0504h                   ; RTLOG_DEBUG_PORT
    1559     mov     ax, DATA16
    1560     mov     ds, ax
     1923        push    ds
     1924        push    ebx
     1925        push    edx
     1926
     1927        mov     bx, ax
     1928        mov     dx, 0504h                   ; RTLOG_DEBUG_PORT
     1929        mov     ax, DATA16
     1930        mov     ds, ax
    15611931
    15621932.next:
    1563     mov     al, [bx]
    1564     or      al, al
    1565     jz      .done
    1566     inc     bx
    1567     out     dx, al
    1568     jmp     .next
     1933        mov     al, [bx]
     1934        or      al, al
     1935        jz      .done
     1936        inc     bx
     1937        out     dx, al
     1938        jmp     .next
    15691939
    15701940.done:
    1571     pop     edx
    1572     pop     ebx
    1573     pop     ds
    1574     ret
     1941        pop     edx
     1942        pop     ebx
     1943        pop     ds
     1944        ret
    15751945ENDPROC dbgstr16
    15761946%endif
    15771947
     1948
     1949%ifdef WITH_DWARF
     1950;
     1951; Close debug info
     1952;
     1953segment _debug_info
     1954        db  0
     1955g_dwarf_compile_unit_end:
     1956%endif
     1957
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp

    r68612 r75337  
    55
    66/*
    7  * Copyright (c) 2007 knut st. osmundsen <[email protected]>
     7 * Copyright (c) 2007-2018 knut st. osmundsen <[email protected]>
    88 *
    99 * Permission is hereby granted, free of charge, to any person
     
    3737
    3838#include <VBox/log.h>
     39#include <iprt/asm.h>
    3940#include <iprt/assert.h>
    40 
    41 
    42 
    43 DECLASM(int)
    44 FS32_OPENCREATE(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszName, USHORT iCurDirEnd,
    45                 PSFFSI psffsi, PVBOXSFFSD psffsd, ULONG uOpenMode, USHORT fOpenFlag,
    46                 PUSHORT puAction, USHORT fAttr, PBYTE pbEABuf, PUSHORT pfGenFlag)
    47 {
    48     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszName); NOREF(iCurDirEnd); NOREF(psffsi); NOREF(psffsd); NOREF(uOpenMode);
    49     NOREF(fOpenFlag); NOREF(puAction); NOREF(fAttr); NOREF(pbEABuf); NOREF(pfGenFlag);
    50     return ERROR_NOT_SUPPORTED;
    51 }
    52 
    53 
    54 DECLASM(int)
    55 FS32_CLOSE(ULONG uType, ULONG fIoFlags, PSFFSI psffsi, PVBOXSFFSD psffsd)
    56 {
    57     NOREF(uType); NOREF(fIoFlags); NOREF(psffsi); NOREF(psffsd);
    58     return ERROR_NOT_SUPPORTED;
    59 }
    60 
    61 
    62 DECLASM(int)
    63 FS32_COMMIT(ULONG uType, ULONG fIoFlags, PSFFSI psffsi, PVBOXSFFSD psffsd)
    64 {
    65     NOREF(uType); NOREF(fIoFlags); NOREF(psffsi); NOREF(psffsd);
    66     return ERROR_NOT_SUPPORTED;
     41#include <iprt/mem.h>
     42
     43
     44
     45DECLASM(APIRET)
     46FS32_OPENCREATE(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszName, LONG offCurDirEnd,
     47                PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fOpenMode, USHORT fOpenFlags,
     48                PUSHORT puAction, ULONG fAttribs, BYTE const *pbEaBuf, PUSHORT pfGenFlag)
     49{
     50    LogFlow(("FS32_OPENCREATE: pCdFsi=%p pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pSfFsi=%p pSfFsd=%p fOpenMode=%#x fOpenFlags=%#x puAction=%p fAttribs=%#x pbEaBuf=%p pfGenFlag=%p\n",
     51             pCdFsi, pCdFsd, pszName, pszName, offCurDirEnd, pSfFsi, pSfFsd, fOpenMode, fOpenFlags, puAction, fAttribs, pbEaBuf, pfGenFlag));
     52    RT_NOREF(pfGenFlag);
     53
     54    /*
     55     * Validate and convert parameters.
     56     */
     57    /* No EAs. */
     58    if (!pbEaBuf)
     59    { /* likely */ }
     60    else
     61    {
     62        LogRel(("FS32_OPENCREATE: Returns ERROR_EAS_NOT_SUPPORTED [%p];\n", pbEaBuf));
     63        return ERROR_EAS_NOT_SUPPORTED;
     64    }
     65
     66    /* No direct access. */
     67    if (!(fOpenMode & OPEN_FLAGS_DASD))
     68    { /* likely */ }
     69    else
     70    {
     71        LogRel(("FS32_OPENCREATE: Returns ERROR_ACCESS_DENIED [DASD];\n"));
     72        return ERROR_ACCESS_DENIED;
     73    }
     74
     75    SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
     76    if (!pParams)
     77        return ERROR_NOT_ENOUGH_MEMORY;
     78    RT_ZERO(*pParams);
     79
     80    /* access: */
     81    if (fOpenMode & OPEN_ACCESS_READWRITE)
     82        pParams->CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
     83    else if (fOpenMode & OPEN_ACCESS_WRITEONLY)
     84        pParams->CreateFlags = SHFL_CF_ACCESS_WRITE     | SHFL_CF_ACCESS_ATTR_WRITE;
     85    else
     86        pParams->CreateFlags = SHFL_CF_ACCESS_READ      | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
     87
     88    /* Sharing: */
     89    switch (fOpenMode & (OPEN_SHARE_DENYNONE | OPEN_SHARE_DENYREADWRITE | OPEN_SHARE_DENYREAD | OPEN_SHARE_DENYWRITE))
     90    {
     91        case OPEN_SHARE_DENYNONE:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
     92        case OPEN_SHARE_DENYWRITE:      pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
     93        case OPEN_SHARE_DENYREAD:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
     94        case OPEN_SHARE_DENYREADWRITE:  pParams->CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
     95        case 0:                         pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
     96        default:
     97            LogRel(("FS32_OPENCREATE: Invalid file sharing mode: %#x\n", fOpenMode));
     98            VbglR0PhysHeapFree(pParams);
     99            return VERR_INVALID_PARAMETER;
     100
     101    }
     102
     103    /* How to open the file: */
     104    switch (fOpenFlags & 0x13)
     105    {
     106        case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x00 */
     107            pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     108            break;
     109        case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x10 */
     110            pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     111            break;
     112        case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x01 */
     113            pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     114            break;
     115        case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x11 */
     116            pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     117            break;
     118        case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:   /* 0x02 */
     119            pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     120            break;
     121        case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
     122            pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     123            break;
     124        default:
     125            LogRel(("FS32_OPENCREATE: Invalid file open flags: %#x\n", fOpenFlags));
     126            VbglR0PhysHeapFree(pParams);
     127            return VERR_INVALID_PARAMETER;
     128    }
     129
     130    /* Misc: cache, etc? There seems to be no API for that. */
     131
     132    /* Attributes: */
     133    pParams->Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
     134
     135    /* Initial size: */
     136    if (pSfFsi->sfi_sizel > 0)
     137        pParams->Info.cbObject = pSfFsi->sfi_sizel;
     138
     139    /*
     140     * Resolve path to a folder and folder relative path.
     141     */
     142    PVBOXSFFOLDER pFolder;
     143    PSHFLSTRING   pStrFolderPath;
     144    RT_NOREF(pCdFsi);
     145    APIRET rc = vboxSfOs2ResolvePath(pszName, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     146    LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
     147    if (rc == NO_ERROR)
     148    {
     149        /*
     150         * Try open the file.
     151         */
     152        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     153        LogFlow(("FS32_OPENCREATE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
     154        if (RT_SUCCESS(vrc))
     155        {
     156            switch (pParams->Result)
     157            {
     158                case SHFL_FILE_EXISTS:
     159                    if (pParams->Handle == SHFL_HANDLE_NIL)
     160                    {
     161                        rc = ERROR_FILE_EXISTS;
     162                        break;
     163                    }
     164                    RT_FALL_THRU();
     165                case SHFL_FILE_CREATED:
     166                case SHFL_FILE_REPLACED:
     167                    if (   pParams->Info.cbObject < _2G
     168                        || (fOpenMode & OPEN_FLAGS_LARGEFILE))
     169                    {
     170                        pSfFsd->u32Magic    = VBOXSFSYFI_MAGIC;
     171                        pSfFsd->pSelf       = pSfFsd;
     172                        pSfFsd->hHostFile   = pParams->Handle;
     173                        pSfFsd->pFolder     = pFolder;
     174
     175                        uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
     176                        Assert(cOpenFiles < _32K);
     177                        pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
     178
     179                        pSfFsi->sfi_sizel   = pParams->Info.cbObject;
     180                        pSfFsi->sfi_type    = STYPE_FILE;
     181                        pSfFsi->sfi_DOSattr = (uint8_t)((pParams->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
     182                        int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     183                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pParams->Info.BirthTime,        cMinLocalTimeDelta);
     184                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pParams->Info.AccessTime,       cMinLocalTimeDelta);
     185                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pParams->Info.ModificationTime, cMinLocalTimeDelta);
     186                        if (pParams->Result == SHFL_FILE_CREATED)
     187                            pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
     188
     189                        *puAction = pParams->Result == SHFL_FILE_CREATED ? FILE_CREATED
     190                                  : pParams->Result == SHFL_FILE_EXISTS  ? FILE_EXISTED
     191                                  :                                        FILE_TRUNCATED;
     192
     193                        Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
     194                        rc = NO_ERROR;
     195                    }
     196                    else
     197                    {
     198                        LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pParams->Info.cbObject, pszName));
     199                        VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pParams->Handle);
     200                        rc = ERROR_ACCESS_DENIED;
     201                    }
     202                    break;
     203
     204                case SHFL_PATH_NOT_FOUND:
     205                    rc = ERROR_PATH_NOT_FOUND;
     206                    break;
     207
     208                default:
     209                case SHFL_FILE_NOT_FOUND:
     210                    rc = ERROR_FILE_NOT_FOUND;
     211                    break;
     212            }
     213        }
     214        else if (rc == VERR_ALREADY_EXISTS)
     215            rc = ERROR_ACCESS_DENIED;
     216        else
     217            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
     218        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     219    }
     220    VbglR0PhysHeapFree(pParams);
     221    LogFlow(("FS32_OPENCREATE: returns %u\n", rc));
     222    return rc;
     223}
     224
     225
     226DECLASM(APIRET)
     227FS32_CLOSE(ULONG uType, ULONG fIoFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
     228{
     229    LogFlow(("FS32_CLOSE: uType=%#x fIoFlags=%#x pSfFsi=%p pSfFsd=%p:{%#x}\n", uType, fIoFlags, pSfFsi, pSfFsd, pSfFsd->u32Magic));
     230
     231    /*
     232     * Validate input.
     233     */
     234    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     235    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     236    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     237    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     238    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     239    Assert(pFolder->cOpenFiles > 0);
     240
     241    /*
     242     * We only care for when the system is done truly with the file
     243     * and we can close it.
     244     */
     245    if (uType != FS_CL_FORSYS)
     246        return NO_ERROR;
     247
     248    /** @todo flush file if fIoFlags says so? */
     249    RT_NOREF(fIoFlags);
     250
     251    int vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile);
     252    AssertRC(vrc);
     253
     254    pSfFsd->hHostFile = SHFL_HANDLE_NIL;
     255    pSfFsd->pSelf     = NULL;
     256    pSfFsd->u32Magic  = ~VBOXSFSYFI_MAGIC;
     257    pSfFsd->pFolder   = NULL;
     258
     259    ASMAtomicDecU32(&pFolder->cOpenFiles);
     260    vboxSfOs2ReleaseFolder(pFolder);
     261
     262    RT_NOREF(pSfFsi);
     263    LogFlow(("FS32_CLOSE: returns NO_ERROR\n"));
     264    return NO_ERROR;
     265}
     266
     267
     268DECLASM(APIRET)
     269FS32_COMMIT(ULONG uType, ULONG fIoFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
     270{
     271    LogFlow(("FS32_COMMIT: uType=%#x fIoFlags=%#x pSfFsi=%p pSfFsd=%p:{%#x}\n", uType, fIoFlags, pSfFsi, pSfFsd, pSfFsd->u32Magic));
     272
     273    /*
     274     * Validate input.
     275     */
     276    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     277    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     278    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     279    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     280    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     281    Assert(pFolder->cOpenFiles > 0);
     282    RT_NOREF(pFolder);
     283
     284    /*
     285     * We only need to flush writable files.
     286     */
     287    if (   (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_WRITEONLY
     288        || (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_READWRITE)
     289    {
     290        int vrc = VbglR0SfFlush(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile);
     291        if (RT_FAILURE(vrc))
     292        {
     293            LogRel(("FS32_COMMIT: VbglR0SfFlush failed: %Rrc\n", vrc));
     294            return ERROR_FLUSHBUF_FAILED;
     295        }
     296    }
     297
     298    NOREF(uType); NOREF(fIoFlags); NOREF(pSfFsi);
     299    LogFlow(("FS32_COMMIT: returns NO_ERROR\n"));
     300    return NO_ERROR;
    67301}
    68302
    69303
    70304extern "C" APIRET APIENTRY
    71 FS32_CHGFILEPTRL(PSFFSI psffsi, PVBOXSFFSD psffsd, LONGLONG off, ULONG uMethod, ULONG fIoFlags)
    72 {
    73     NOREF(psffsi); NOREF(psffsd); NOREF(off); NOREF(uMethod); NOREF(fIoFlags);
    74     return ERROR_NOT_SUPPORTED;
     305FS32_CHGFILEPTRL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONGLONG off, ULONG uMethod, ULONG fIoFlags)
     306{
     307    LogFlow(("FS32_CHGFILEPTRL: pSfFsi=%p pSfFsd=%p off=%RI64 (%#RX64) uMethod=%u fIoFlags=%#x\n",
     308             pSfFsi, pSfFsd, off, off, uMethod, fIoFlags));
     309
     310    /*
     311     * Validate input.
     312     */
     313    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     314    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     315    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     316    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     317    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     318    Assert(pFolder->cOpenFiles > 0);
     319
     320    /*
     321     * Calc absolute offset.
     322     */
     323    int64_t offNew;
     324    switch (uMethod)
     325    {
     326        case CFP_RELBEGIN:
     327            if (off >= 0)
     328            {
     329                offNew = off;
     330                break;
     331            }
     332            Log(("FS32_CHGFILEPTRL: Negative seek (BEGIN): %RI64\n", off));
     333            return ERROR_NEGATIVE_SEEK;
     334
     335        case CFP_RELCUR:
     336            offNew = pSfFsi->sfi_positionl + off;
     337            if (offNew >= 0)
     338                break;
     339            Log(("FS32_CHGFILEPTRL: Negative seek (RELCUR): %RU64 + %RI64\n", pSfFsi->sfi_positionl, off));
     340            return ERROR_NEGATIVE_SEEK;
     341
     342        case CFP_RELEND:
     343        {
     344            /* Have to consult the host to get the current file size. */
     345
     346            PSHFLFSOBJINFO pObjInfo = (PSHFLFSOBJINFO)VbglR0PhysHeapAlloc(sizeof(*pObjInfo));
     347            if (!pObjInfo)
     348                return ERROR_NOT_ENOUGH_MEMORY;
     349            RT_ZERO(*pObjInfo);
     350            uint32_t cbObjInfo = sizeof(*pObjInfo);
     351
     352            int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     353                                     SHFL_INFO_FILE | SHFL_INFO_GET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
     354            if (RT_SUCCESS(vrc))
     355            {
     356                if (pSfFsi->sfi_mode & SFMODE_LARGE_FILE)
     357                    pSfFsi->sfi_sizel = pObjInfo->cbObject;
     358                else
     359                    pSfFsi->sfi_sizel = RT_MIN(pObjInfo->cbObject, _2G - 1);
     360            }
     361            else
     362                LogRel(("FS32_CHGFILEPTRL/CFP_RELEND: VbglR0SfFsInfo failed: %Rrc\n", vrc));
     363            VbglR0PhysHeapFree(pObjInfo);
     364
     365            offNew = pSfFsi->sfi_sizel + off;
     366            if (offNew >= 0)
     367                break;
     368            Log(("FS32_CHGFILEPTRL: Negative seek (CFP_RELEND): %RI64 + %RI64\n", pSfFsi->sfi_sizel, off));
     369            return ERROR_NEGATIVE_SEEK;
     370        }
     371
     372
     373        default:
     374            LogRel(("FS32_CHGFILEPTRL: Unknown seek method: %#x\n", uMethod));
     375            return ERROR_INVALID_FUNCTION;
     376    }
     377
     378    /*
     379     * Commit the seek.
     380     */
     381    pSfFsi->sfi_positionl = offNew;
     382    LogFlow(("FS32_CHGFILEPTRL: returns; sfi_positionl=%RI64\n", offNew));
     383    RT_NOREF_PV(fIoFlags);
     384    return NO_ERROR;
    75385}
    76386
    77387
    78388/** Forwards the call to FS32_CHGFILEPTRL. */
     389DECLASM(APIRET)
     390FS32_CHGFILEPTR(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONG off, ULONG uMethod, ULONG fIoFlags)
     391{
     392    return FS32_CHGFILEPTRL(pSfFsi, pSfFsd, off, uMethod, fIoFlags);
     393}
     394
     395
     396/**
     397 * Worker for FS32_PATHINFO that handles file stat setting.
     398 *
     399 * @returns OS/2 status code
     400 * @param   pFolder         The folder.
     401 * @param   pSfFsi          The file system independent file structure.  We'll
     402 *                          update the timestamps and size here.
     403 * @param   pSfFsd          Out file data.
     404 * @param   uLevel          The information level.
     405 * @param   pbData          The stat data to set.
     406 * @param   cbData          The uLevel specific input size.
     407 */
     408static APIRET
     409vboxSfOs2SetFileInfo(PVBOXSFFOLDER pFolder, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel, PBYTE pbData, ULONG cbData)
     410{
     411    APIRET rc;
     412
     413    /*
     414     * Data buffer both for caching user data and for issuing the
     415     * change request to the host.
     416     */
     417    struct SetFileInfoBuf
     418    {
     419        union
     420        {
     421            FILESTATUS      Lvl1;
     422            FILESTATUS3L    Lvl1L;
     423        };
     424        SHFLFSOBJINFO ObjInfo;
     425
     426    } *pBuf = (struct SetFileInfoBuf *)VbglR0PhysHeapAlloc(sizeof(*pBuf));
     427    if (pBuf)
     428    {
     429        /* Copy in the data. */
     430        rc = KernCopyIn(&pBuf->Lvl1, pbData, cbData);
     431        if (rc == NO_ERROR)
     432        {
     433            /*
     434             * Join paths with FS32_PATHINFO and FS32_FILEATTRIBUTE.
     435             */
     436            rc = vboxSfOs2SetInfoCommonWorker(pFolder, pSfFsd->hHostFile,
     437                                              uLevel == FI_LVL_STANDARD ? pBuf->Lvl1.attrFile : pBuf->Lvl1L.attrFile,
     438                                              &pBuf->Lvl1, &pBuf->ObjInfo);
     439            if (rc == NO_ERROR)
     440            {
     441                /*
     442                 * Update the timestamps in the independent file data with what
     443                 * the host returned:
     444                 */
     445                pSfFsi->sfi_tstamp |= ST_PCREAT | ST_PWRITE | ST_PREAD;
     446                pSfFsi->sfi_tstamp &= ~(ST_SCREAT | ST_SWRITE| ST_SREAD);
     447                uint16_t cDelta = vboxSfOs2GetLocalTimeDelta();
     448                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pBuf->ObjInfo.BirthTime,        cDelta);
     449                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pBuf->ObjInfo.AccessTime,       cDelta);
     450                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pBuf->ObjInfo.ModificationTime, cDelta);
     451
     452                /* And the size field as we're at it: */
     453                pSfFsi->sfi_sizel = pBuf->ObjInfo.cbObject;
     454            }
     455            else
     456                rc = ERROR_INVALID_PARAMETER;
     457        }
     458
     459        VbglR0PhysHeapFree(pBuf);
     460    }
     461    else
     462        rc = ERROR_NOT_ENOUGH_MEMORY;
     463    return rc;
     464}
     465
     466
     467/**
     468 * Worker for FS32_PATHINFO that handles file stat queries.
     469 *
     470 * @returns OS/2 status code
     471 * @param   pFolder         The folder.
     472 * @param   pSfFsi          The file system independent file structure.  We'll
     473 *                          update the timestamps and size here.
     474 * @param   pSfFsd          Out file data.
     475 * @param   uLevel          The information level.
     476 * @param   pbData          Where to return the data (user address).
     477 * @param   cbData          The amount of data to produce.
     478 */
     479static APIRET
     480vboxSfOs2QueryFileInfo(PVBOXSFFOLDER pFolder, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel, PBYTE pbData, ULONG cbData)
     481{
     482    APIRET rc;
     483    PSHFLFSOBJINFO pObjInfo = (PSHFLFSOBJINFO)VbglR0PhysHeapAlloc(sizeof(*pObjInfo));
     484    if (pObjInfo)
     485    {
     486        RT_ZERO(*pObjInfo);
     487        uint32_t cbObjInfo = sizeof(*pObjInfo);
     488
     489        int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     490                                SHFL_INFO_FILE | SHFL_INFO_GET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
     491        if (RT_SUCCESS(vrc))
     492        {
     493            rc = vboxSfOs2FileStatusFromObjInfo(pbData, cbData, uLevel, pObjInfo);
     494            if (rc == NO_ERROR)
     495            {
     496                /* Update the timestamps in the independent file data: */
     497                int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     498                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pObjInfo->BirthTime,        cMinLocalTimeDelta);
     499                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pObjInfo->AccessTime,       cMinLocalTimeDelta);
     500                vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pObjInfo->ModificationTime, cMinLocalTimeDelta);
     501
     502                /* And the size field as we're at it: */
     503                pSfFsi->sfi_sizel = pObjInfo->cbObject;
     504            }
     505        }
     506        else
     507        {
     508            Log(("vboxSfOs2QueryFileInfo: VbglR0SfFsInfo failed: %Rrc\n", vrc));
     509            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
     510        }
     511    }
     512    else
     513        rc = ERROR_NOT_ENOUGH_MEMORY;
     514    return rc;
     515}
     516
     517
     518DECLASM(APIRET)
     519FS32_FILEINFO(ULONG fFlags, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG uLevel,
     520              PBYTE pbData, ULONG cbData, ULONG fIoFlags)
     521{
     522    LogFlow(("FS32_FILEINFO: fFlags=%#x pSfFsi=%p pSfFsd=%p uLevel=%p pbData=%p cbData=%#x fIoFlags=%#x\n",
     523             fFlags, pSfFsi, pSfFsd, uLevel, pbData, cbData, fIoFlags));
     524
     525    /*
     526     * Validate input.
     527     */
     528    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     529    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     530    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     531    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     532    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     533    Assert(pFolder->cOpenFiles > 0);
     534
     535    /*
     536     * Check the level.
     537     * Note! See notes in FS32_PATHINFO.
     538     */
     539    ULONG cbMinData;
     540    switch (uLevel)
     541    {
     542        case FI_LVL_STANDARD:
     543            cbMinData = sizeof(FILESTATUS);
     544            AssertCompileSize(FILESTATUS,  0x16);
     545            break;
     546        case FI_LVL_STANDARD_64:
     547            cbMinData = sizeof(FILESTATUS3L);
     548            AssertCompileSize(FILESTATUS3L, 0x20); /* cbFile and cbFileAlloc are misaligned. */
     549            break;
     550        case FI_LVL_STANDARD_EASIZE:
     551            cbMinData = sizeof(FILESTATUS2);
     552            AssertCompileSize(FILESTATUS2, 0x1a);
     553            break;
     554        case FI_LVL_STANDARD_EASIZE_64:
     555            cbMinData = sizeof(FILESTATUS4L);
     556            AssertCompileSize(FILESTATUS4L, 0x24); /* cbFile and cbFileAlloc are misaligned. */
     557            break;
     558        case FI_LVL_EAS_FROM_LIST:
     559        case FI_LVL_EAS_FULL:
     560        case FI_LVL_EAS_FULL_5:
     561        case FI_LVL_EAS_FULL_8:
     562            cbMinData = sizeof(EAOP);
     563            break;
     564        default:
     565            LogRel(("FS32_PATHINFO: Unsupported info level %u!\n", uLevel));
     566            return ERROR_INVALID_LEVEL;
     567    }
     568    if (cbData < cbMinData || pbData == NULL)
     569    {
     570        Log(("FS32_FILEINFO: ERROR_BUFFER_OVERFLOW (cbMinData=%#x, cbData=%#x)\n", cbMinData, cbData));
     571        return ERROR_BUFFER_OVERFLOW;
     572    }
     573
     574    /*
     575     * Query information.
     576     */
     577    APIRET rc;
     578    if (fFlags == FI_RETRIEVE)
     579    {
     580        switch (uLevel)
     581        {
     582            case FI_LVL_STANDARD:
     583            case FI_LVL_STANDARD_EASIZE:
     584            case FI_LVL_STANDARD_64:
     585            case FI_LVL_STANDARD_EASIZE_64:
     586                rc = vboxSfOs2QueryFileInfo(pFolder, pSfFsi, pSfFsd, uLevel, pbData, cbMinData);
     587                break;
     588
     589            /*
     590             * We don't do EAs and we "just" need to return no-EAs.
     591             * However, that's not as easy as you might think.
     592             */
     593            case FI_LVL_EAS_FROM_LIST:
     594            case FI_LVL_EAS_FULL:
     595            case FI_LVL_EAS_FULL_5:
     596            case FI_LVL_EAS_FULL_8:
     597                rc = vboxSfOs2MakeEmptyEaList((PEAOP)pbData, uLevel);
     598                break;
     599
     600            default:
     601                AssertFailed();
     602                rc = ERROR_GEN_FAILURE;
     603                break;
     604        }
     605    }
     606    /*
     607     * Update information.
     608     */
     609    else if (fFlags == FI_SET)
     610    {
     611        switch (uLevel)
     612        {
     613            case FI_LVL_STANDARD:
     614            case FI_LVL_STANDARD_64:
     615                rc = vboxSfOs2SetFileInfo(pFolder, pSfFsi, pSfFsd, uLevel, pbData, cbMinData);
     616                break;
     617
     618            case FI_LVL_STANDARD_EASIZE:
     619                rc = ERROR_EAS_NOT_SUPPORTED;
     620                break;
     621
     622            case FI_LVL_STANDARD_EASIZE_64:
     623            case FI_LVL_EAS_FROM_LIST:
     624            case FI_LVL_EAS_FULL:
     625            case FI_LVL_EAS_FULL_5:
     626            case FI_LVL_EAS_FULL_8:
     627                rc = ERROR_INVALID_LEVEL;
     628                break;
     629
     630            default:
     631                AssertFailed();
     632                rc = ERROR_GEN_FAILURE;
     633                break;
     634        }
     635    }
     636    else
     637    {
     638        LogRel(("FS32_FILEINFO: Unknown flags value: %#x\n", fFlags));
     639        rc = ERROR_INVALID_PARAMETER;
     640    }
     641    RT_NOREF_PV(fIoFlags);
     642    return rc;
     643}
     644
     645
     646DECLASM(APIRET)
     647FS32_NEWSIZEL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, LONGLONG cbFile, ULONG fIoFlags)
     648{
     649    LogFlow(("FS32_NEWSIZEL: pSfFsi=%p pSfFsd=%p cbFile=%RI64 (%#RX64) fIoFlags=%#x\n", pSfFsi, pSfFsd, cbFile, cbFile, fIoFlags));
     650
     651    /*
     652     * Validate input.
     653     */
     654    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     655    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     656    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     657    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     658    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     659    Assert(pFolder->cOpenFiles > 0);
     660    if (cbFile < 0)
     661    {
     662        LogRel(("FS32_NEWSIZEL: Negative size: %RI64\n", cbFile));
     663        return ERROR_INVALID_PARAMETER;
     664    }
     665
     666    /*
     667     * This should only be possible on a file that is writable.
     668     */
     669    APIRET rc;
     670    if (   (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_WRITEONLY
     671        || (pSfFsi->sfi_mode & SFMODE_OPEN_ACCESS) == SFMODE_OPEN_READWRITE)
     672    {
     673        /*
     674         * Call the host.  We need a full object info structure here to pass
     675         * a 64-bit unsigned integer value.  Sigh.
     676         */
     677        /** @todo Shared folders: New SET_FILE_SIZE API. */
     678        PSHFLFSOBJINFO pObjInfo = (PSHFLFSOBJINFO)VbglR0PhysHeapAlloc(sizeof(*pObjInfo));
     679        if (pObjInfo)
     680        {
     681            RT_ZERO(*pObjInfo);
     682            pObjInfo->cbObject = cbFile;
     683            uint32_t cbObjInfo = sizeof(*pObjInfo);
     684            int vrc = VbglR0SfFsInfo(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     685                                     SHFL_INFO_SIZE | SHFL_INFO_SET, &cbObjInfo, (PSHFLDIRINFO)pObjInfo);
     686            if (RT_SUCCESS(vrc))
     687            {
     688                pSfFsi->sfi_sizel = cbFile;
     689                rc = NO_ERROR;
     690            }
     691            else
     692            {
     693                LogRel(("FS32_NEWSIZEL: VbglR0SfFsInfo failed: %Rrc\n", vrc));
     694                if (vrc == VERR_DISK_FULL)
     695                    rc = ERROR_DISK_FULL;
     696                else
     697                    rc = ERROR_GEN_FAILURE;
     698            }
     699            VbglR0PhysHeapFree(pObjInfo);
     700        }
     701        else
     702            rc = ERROR_NOT_ENOUGH_MEMORY;
     703    }
     704    else
     705        rc = ERROR_ACCESS_DENIED;
     706    LogFlow(("FS32_NEWSIZEL: returns %u\n", rc));
     707    return rc;
     708}
     709
     710
    79711extern "C" APIRET APIENTRY
    80 FS32_CHGFILEPTR(PSFFSI psffsi, PVBOXSFFSD psffsd, LONG off, ULONG uMethod, ULONG fIoFlags)
    81 {
    82     return FS32_CHGFILEPTRL(psffsi, psffsd, off, uMethod, fIoFlags);
    83 }
    84 
    85 DECLASM(int)
    86 FS32_FILEINFO(ULONG fFlag, PSFFSI psffsi, PVBOXSFFSD psffsd, ULONG uLevel,
    87               PBYTE pbData, ULONG cbData, ULONG fIoFlags)
    88 {
    89     NOREF(fFlag); NOREF(psffsi); NOREF(psffsd); NOREF(uLevel); NOREF(pbData); NOREF(cbData); NOREF(fIoFlags);
    90     return ERROR_NOT_SUPPORTED;
    91 }
    92 
    93 DECLASM(int)
    94 FS32_NEWSIZEL(PSFFSI psffsi, PVBOXSFFSD psffsd, LONGLONG cbFile, ULONG fIoFlags)
    95 {
    96     NOREF(psffsi); NOREF(psffsd); NOREF(cbFile); NOREF(fIoFlags);
    97     return ERROR_NOT_SUPPORTED;
     712FS32_READ(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, PVOID pvData, PULONG pcb, ULONG fIoFlags)
     713{
     714    LogFlow(("FS32_READ: pSfFsi=%p pSfFsd=%p pvData=%p pcb=%p:{%#x} fIoFlags=%#x\n", pSfFsi, pSfFsd, pvData, pcb, *pcb, fIoFlags));
     715
     716    /*
     717     * Validate input.
     718     */
     719    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     720    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     721    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     722    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     723    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     724    Assert(pFolder->cOpenFiles > 0);
     725    RT_NOREF(pFolder);
     726
     727    /*
     728     * If the read request is small enough, go thru a temporary buffer to
     729     * avoid locking/unlocking user memory.
     730     */
     731    uint64_t offRead  = pSfFsi->sfi_positionl;
     732    uint32_t cbRead   = *pcb;
     733    uint32_t cbActual = cbRead;
     734    if (cbRead <= _8K - ALLOC_HDR_SIZE)
     735    {
     736        void *pvBuf = VbglR0PhysHeapAlloc(cbRead);
     737        if (pvBuf != NULL)
     738        {
     739            APIRET rc;
     740            int vrc = VbglR0SfRead(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     741                                   offRead, &cbActual, (uint8_t *)pvBuf, true /*fLocked*/);
     742            if (RT_SUCCESS(vrc))
     743            {
     744                AssertStmt(cbActual <= cbRead, cbActual = cbRead);
     745                rc = KernCopyOut(pvData, pvBuf, cbActual);
     746                if (rc == NO_ERROR)
     747                {
     748                    *pcb = cbActual;
     749                    pSfFsi->sfi_positionl = offRead + cbActual;
     750                    if (pSfFsi->sfi_sizel < offRead + cbActual)
     751                        pSfFsi->sfi_sizel = offRead + cbActual;
     752                    pSfFsi->sfi_tstamp   |= ST_SREAD | ST_PREAD;
     753                    LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [copy]\n", cbActual, pSfFsi->sfi_positionl));
     754                }
     755            }
     756            else
     757            {
     758                Log(("FS32_READ: VbglR0SfRead(off=%#x,cb=%#x) -> %Rrc [copy]\n", offRead, cbRead, vrc));
     759                rc = ERROR_BAD_NET_RESP;
     760            }
     761            VbglR0PhysHeapFree(pvBuf);
     762            return rc;
     763        }
     764    }
     765
     766    /*
     767     * Do the read directly on the buffer, Vbgl will do the locking for us.
     768     */
     769    int vrc = VbglR0SfRead(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     770                           offRead, &cbActual, (uint8_t *)pvData, false /*fLocked*/);
     771    if (RT_SUCCESS(vrc))
     772    {
     773        AssertStmt(cbActual <= cbRead, cbActual = cbRead);
     774        *pcb = cbActual;
     775        pSfFsi->sfi_positionl = offRead + cbActual;
     776        if (pSfFsi->sfi_sizel < offRead + cbActual)
     777            pSfFsi->sfi_sizel = offRead + cbActual;
     778        pSfFsi->sfi_tstamp   |= ST_SREAD | ST_PREAD;
     779        LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [direct]\n", cbActual, pSfFsi->sfi_positionl));
     780        return NO_ERROR;
     781    }
     782    Log(("FS32_READ: VbglR0SfRead(off=%#x,cb=%#x) -> %Rrc [direct]\n", offRead, cbRead, vrc));
     783    RT_NOREF_PV(fIoFlags);
     784    return ERROR_BAD_NET_RESP;
    98785}
    99786
    100787
    101788extern "C" APIRET APIENTRY
    102 FS32_READ(PSFFSI psffsi, PVBOXSFFSD psffsd, PVOID pvData, PULONG pcb, ULONG fIoFlags)
    103 {
    104     NOREF(psffsi); NOREF(psffsd); NOREF(pvData); NOREF(pcb); NOREF(fIoFlags);
    105     return ERROR_NOT_SUPPORTED;
     789FS32_WRITE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, void const *pvData, PULONG pcb, ULONG fIoFlags)
     790{
     791    /*
     792     * Validate input.
     793     */
     794    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     795    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     796    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     797    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     798    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     799    Assert(pFolder->cOpenFiles > 0);
     800    RT_NOREF(pFolder);
     801
     802    /*
     803     * If the write request is small enough, go thru a temporary buffer to
     804     * avoid locking/unlocking user memory.
     805     */
     806    uint64_t offWrite = pSfFsi->sfi_positionl;
     807    uint32_t cbWrite  = *pcb;
     808    uint32_t cbActual = cbWrite;
     809    if (cbWrite <= _8K - ALLOC_HDR_SIZE)
     810    {
     811        void *pvBuf = VbglR0PhysHeapAlloc(cbWrite);
     812        if (pvBuf != NULL)
     813        {
     814            APIRET rc = KernCopyIn(pvBuf, pvData, cbWrite);
     815            if (rc == NO_ERROR)
     816            {
     817                int vrc = VbglR0SfWrite(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     818                                        offWrite, &cbActual, (uint8_t *)pvBuf, true /*fLocked*/);
     819                if (RT_SUCCESS(vrc))
     820                {
     821                    AssertStmt(cbActual <= cbWrite, cbActual = cbWrite);
     822                    *pcb = cbActual;
     823                    pSfFsi->sfi_positionl = offWrite + cbActual;
     824                    if (pSfFsi->sfi_sizel < offWrite + cbActual)
     825                        pSfFsi->sfi_sizel = offWrite + cbActual;
     826                    pSfFsi->sfi_tstamp   |= ST_SWRITE | ST_PWRITE;
     827                    LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [copy]\n", cbActual, pSfFsi->sfi_positionl));
     828                }
     829                else
     830                {
     831                    Log(("FS32_READ: VbglR0SfWrite(off=%#x,cb=%#x) -> %Rrc [copy]\n", offWrite, cbWrite, vrc));
     832                    rc = ERROR_BAD_NET_RESP;
     833                }
     834            }
     835            VbglR0PhysHeapFree(pvBuf);
     836            return rc;
     837        }
     838    }
     839
     840    /*
     841     * Do the write directly on the buffer, Vbgl will do the locking for us.
     842     */
     843    int vrc = VbglR0SfWrite(&g_SfClient, &pFolder->hHostFolder, pSfFsd->hHostFile,
     844                            offWrite, &cbActual, (uint8_t *)pvData, false /*fLocked*/);
     845    if (RT_SUCCESS(vrc))
     846    {
     847        AssertStmt(cbActual <= cbWrite, cbActual = cbWrite);
     848        *pcb = cbActual;
     849        pSfFsi->sfi_positionl = offWrite + cbActual;
     850        if (pSfFsi->sfi_sizel < offWrite + cbActual)
     851            pSfFsi->sfi_sizel = offWrite + cbActual;
     852        pSfFsi->sfi_tstamp   |= ST_SWRITE | ST_PWRITE;
     853        LogFlow(("FS32_READ: returns; cbActual=%#x sfi_positionl=%RI64 [direct]\n", cbActual, pSfFsi->sfi_positionl));
     854        return NO_ERROR;
     855    }
     856    Log(("FS32_READ: VbglR0SfWrite(off=%#x,cb=%#x) -> %Rrc [direct]\n", offWrite, cbWrite, vrc));
     857    RT_NOREF_PV(fIoFlags);
     858    return ERROR_BAD_NET_RESP;
    106859}
    107860
    108861
    109862extern "C" APIRET APIENTRY
    110 FS32_WRITE(PSFFSI psffsi, PVBOXSFFSD psffsd, PVOID pvData, PULONG pcb, ULONG fIoFlags)
    111 {
    112     NOREF(psffsi); NOREF(psffsd); NOREF(pvData); NOREF(pcb); NOREF(fIoFlags);
    113     return ERROR_NOT_SUPPORTED;
    114 }
    115 
    116 
    117 extern "C" APIRET APIENTRY
    118 FS32_READFILEATCACHE(PSFFSI psffsi, PVBOXSFFSD psffsd, ULONG fIoFlags, LONGLONG off, ULONG pcb, KernCacheList_t **ppCacheList)
    119 {
    120     NOREF(psffsi); NOREF(psffsd); NOREF(fIoFlags); NOREF(off); NOREF(pcb); NOREF(ppCacheList);
     863FS32_READFILEATCACHE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG fIoFlags, LONGLONG off, ULONG pcb, KernCacheList_t **ppCacheList)
     864{
     865    /*
     866     * Validate input.
     867     */
     868    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     869    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     870    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     871    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     872    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     873    Assert(pFolder->cOpenFiles > 0);
     874    RT_NOREF(pFolder);
     875
     876    /* I think this is used for sendfile(). */
     877
     878    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fIoFlags); NOREF(off); NOREF(pcb); NOREF(ppCacheList);
    121879    return ERROR_NOT_SUPPORTED;
    122880}
     
    133891/* oddments */
    134892
    135 DECLASM(int)
    136 FS32_CANCELLOCKREQUESTL(PSFFSI psffsi, PVBOXSFFSD psffsd, struct filelockl *pLockRange)
    137 {
    138     NOREF(psffsi); NOREF(psffsd); NOREF(pLockRange);
    139     return ERROR_NOT_SUPPORTED;
    140 }
    141 
    142 
    143 DECLASM(int)
    144 FS32_CANCELLOCKREQUEST(PSFFSI psffsi, PVBOXSFFSD psffsd, struct filelock *pLockRange)
    145 {
    146     NOREF(psffsi); NOREF(psffsd); NOREF(pLockRange);
    147     return ERROR_NOT_SUPPORTED;
    148 }
    149 
    150 
    151 DECLASM(int)
    152 FS32_FILELOCKSL(PSFFSI psffsi, PVBOXSFFSD psffsd, struct filelockl *pUnLockRange,
     893DECLASM(APIRET)
     894FS32_CANCELLOCKREQUESTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pLockRange)
     895{
     896    /*
     897     * Validate input.
     898     */
     899    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     900    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     901    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     902    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     903    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     904    Assert(pFolder->cOpenFiles > 0);
     905    RT_NOREF(pFolder);
     906
     907    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
     908    return ERROR_NOT_SUPPORTED;
     909}
     910
     911
     912DECLASM(APIRET)
     913FS32_CANCELLOCKREQUEST(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pLockRange)
     914{
     915    /*
     916     * Validate input.
     917     */
     918    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     919    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     920    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     921    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     922    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     923    Assert(pFolder->cOpenFiles > 0);
     924    RT_NOREF(pFolder);
     925
     926    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pLockRange);
     927    return ERROR_NOT_SUPPORTED;
     928}
     929
     930
     931DECLASM(APIRET)
     932FS32_FILELOCKSL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelockl *pUnLockRange,
    153933                struct filelockl *pLockRange, ULONG cMsTimeout, ULONG fFlags)
    154934{
    155     NOREF(psffsi); NOREF(psffsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
    156     return ERROR_NOT_SUPPORTED;
    157 }
    158 
    159 
    160 DECLASM(int)
    161 FS32_FILELOCKS(PSFFSI psffsi, PVBOXSFFSD psffsd, struct filelock *pUnLockRange,
     935    /*
     936     * Validate input.
     937     */
     938    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     939    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     940    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     941    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     942    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     943    Assert(pFolder->cOpenFiles > 0);
     944    RT_NOREF(pFolder);
     945
     946    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
     947    return ERROR_NOT_SUPPORTED;
     948}
     949
     950
     951DECLASM(APIRET)
     952FS32_FILELOCKS(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct filelock *pUnLockRange,
    162953               struct filelock *pLockRange, ULONG cMsTimeout, ULONG fFlags)
    163954{
    164     NOREF(psffsi); NOREF(psffsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
    165     return ERROR_NOT_SUPPORTED;
    166 }
    167 
    168 
    169 DECLASM(int)
    170 FS32_IOCTL(PSFFSI psffsi, PVBOXSFFSD psffsd, USHORT uCategory, USHORT uFunction,
     955    /*
     956     * Validate input.
     957     */
     958    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     959    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     960    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     961    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     962    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     963    Assert(pFolder->cOpenFiles > 0);
     964    RT_NOREF(pFolder);
     965
     966    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pUnLockRange); NOREF(pLockRange); NOREF(cMsTimeout); NOREF(fFlags);
     967    return ERROR_NOT_SUPPORTED;
     968}
     969
     970
     971DECLASM(APIRET)
     972FS32_IOCTL(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uCategory, USHORT uFunction,
    171973           PVOID pvParm, USHORT cbParm, PUSHORT pcbParmIO,
    172974           PVOID pvData, USHORT cbData, PUSHORT pcbDataIO)
    173975{
    174     NOREF(psffsi); NOREF(psffsd); NOREF(uCategory); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
     976    /*
     977     * Validate input.
     978     */
     979    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     980    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     981    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     982    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     983    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     984    Assert(pFolder->cOpenFiles > 0);
     985    RT_NOREF(pFolder);
     986
     987    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uCategory); NOREF(uFunction); NOREF(pvParm); NOREF(cbParm); NOREF(pcbParmIO);
    175988    NOREF(pvData); NOREF(cbData); NOREF(pcbDataIO);
    176989    return ERROR_NOT_SUPPORTED;
     
    178991
    179992
    180 DECLASM(int)
    181 FS32_FILEIO(PSFFSI psffsi, PVBOXSFFSD psffsd, PBYTE pbCmdList, USHORT cbCmdList,
     993DECLASM(APIRET)
     994FS32_FILEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, PBYTE pbCmdList, USHORT cbCmdList,
    182995            PUSHORT poffError, USHORT fIoFlag)
    183996{
    184     NOREF(psffsi); NOREF(psffsd); NOREF(pbCmdList); NOREF(cbCmdList); NOREF(poffError); NOREF(fIoFlag);
    185     return ERROR_NOT_SUPPORTED;
    186 }
    187 
    188 
    189 DECLASM(int)
    190 FS32_NMPIPE(PSFFSI psffsi, PVBOXSFFSD psffsd, USHORT uOpType, union npoper *pOpRec,
     997    /*
     998     * Validate input.
     999     */
     1000    AssertReturn(pSfFsd->u32Magic == VBOXSFSYFI_MAGIC, ERROR_SYS_INTERNAL);
     1001    AssertReturn(pSfFsd->pSelf    == pSfFsd, ERROR_SYS_INTERNAL);
     1002    PVBOXSFFOLDER pFolder = pSfFsd->pFolder;
     1003    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     1004    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     1005    Assert(pFolder->cOpenFiles > 0);
     1006    RT_NOREF(pFolder);
     1007
     1008    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pbCmdList); NOREF(cbCmdList); NOREF(poffError); NOREF(fIoFlag);
     1009    return ERROR_NOT_SUPPORTED;
     1010}
     1011
     1012
     1013DECLASM(APIRET)
     1014FS32_NMPIPE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, USHORT uOpType, union npoper *pOpRec,
    1911015            PBYTE pbData, PCSZ pszName)
    1921016{
    193     NOREF(psffsi); NOREF(psffsd); NOREF(uOpType); NOREF(pOpRec); NOREF(pbData); NOREF(pszName);
    194     return ERROR_NOT_SUPPORTED;
    195 }
    196 
    197 
    198 DECLASM(int)
    199 FS32_OPENPAGEFILE(PULONG pfFlags, PULONG pcMaxReq, PCSZ pszName, PSFFSI psffsi, PVBOXSFFSD psffsd,
    200                   USHORT uOpenMode, USHORT fOpenFlags, USHORT fAttr, ULONG uReserved)
    201 {
    202     NOREF(pfFlags); NOREF(pcMaxReq); NOREF(pszName); NOREF(psffsi); NOREF(psffsd); NOREF(uOpenMode); NOREF(fOpenFlags);
     1017    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(uOpType); NOREF(pOpRec); NOREF(pbData); NOREF(pszName);
     1018    return ERROR_NOT_SUPPORTED;
     1019}
     1020
     1021
     1022DECLASM(APIRET)
     1023FS32_OPENPAGEFILE(PULONG pfFlags, PULONG pcMaxReq, PCSZ pszName, PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd,
     1024                  USHORT fOpenMode, USHORT fOpenFlags, USHORT fAttr, ULONG uReserved)
     1025{
     1026    NOREF(pfFlags); NOREF(pcMaxReq); NOREF(pszName); NOREF(pSfFsi); NOREF(pSfFsd); NOREF(fOpenMode); NOREF(fOpenFlags);
    2031027    NOREF(fAttr); NOREF(uReserved);
    2041028    return ERROR_NOT_SUPPORTED;
     
    2061030
    2071031
    208 DECLASM(int)
    209 FS32_SETSWAP(PSFFSI psffsi, PVBOXSFFSD psffsd)
    210 {
    211     NOREF(psffsi); NOREF(psffsd);
    212     return ERROR_NOT_SUPPORTED;
    213 }
    214 
    215 
    216 DECLASM(int)
    217 FS32_ALLOCATEPAGESPACE(PSFFSI psffsi, PVBOXSFFSD psffsd, ULONG cb, USHORT cbWantContig)
    218 {
    219     NOREF(psffsi); NOREF(psffsd); NOREF(cb); NOREF(cbWantContig);
    220     return ERROR_NOT_SUPPORTED;
    221 }
    222 
    223 
    224 DECLASM(int)
    225 FS32_DOPAGEIO(PSFFSI psffsi, PVBOXSFFSD psffsd, struct PageCmdHeader *pList)
    226 {
    227     NOREF(psffsi); NOREF(psffsd); NOREF(pList);
    228     return ERROR_NOT_SUPPORTED;
    229 }
    230 
     1032DECLASM(APIRET)
     1033FS32_SETSWAP(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd)
     1034{
     1035    NOREF(pSfFsi); NOREF(pSfFsd);
     1036    return ERROR_NOT_SUPPORTED;
     1037}
     1038
     1039
     1040DECLASM(APIRET)
     1041FS32_ALLOCATEPAGESPACE(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, ULONG cb, USHORT cbWantContig)
     1042{
     1043    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(cb); NOREF(cbWantContig);
     1044    return ERROR_NOT_SUPPORTED;
     1045}
     1046
     1047
     1048DECLASM(APIRET)
     1049FS32_DOPAGEIO(PSFFSI pSfFsi, PVBOXSFSYFI pSfFsd, struct PageCmdHeader *pList)
     1050{
     1051    NOREF(pSfFsi); NOREF(pSfFsd); NOREF(pList);
     1052    return ERROR_NOT_SUPPORTED;
     1053}
     1054
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp

    r68612 r75337  
    55
    66/*
    7  * Copyright (c) 2007 knut st. osmundsen <[email protected]>
     7 * Copyright (c) 2007-2018 knut st. osmundsen <[email protected]>
    88 *
    99 * Permission is hereby granted, free of charge, to any person
     
    3737
    3838#include <VBox/log.h>
     39#include <iprt/asm.h>
    3940#include <iprt/assert.h>
    40 
    41 
    42 DECLASM(int)
    43 FS32_FINDFIRST(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszName, USHORT iCurDirEnd, USHORT fAttr,
    44                PFSFSI pfsfsi, PVBOXSFFS pfsfsd, PBYTE pbData, USHORT cbData, PUSHORT pcMatch,
    45                USHORT uLevel, USHORT fFlags)
    46 {
    47     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszName); NOREF(iCurDirEnd); NOREF(fAttr); NOREF(pfsfsi); NOREF(pfsfsd); NOREF(pbData);
    48     NOREF(cbData); NOREF(pcMatch); NOREF(uLevel); NOREF(fFlags);
     41#include <iprt/mem.h>
     42#include <iprt/path.h>
     43#include <iprt/err.h>
     44
     45
     46
     47/**
     48 * Checks if the given name is 8-dot-3 compatible.
     49 *
     50 * @returns true if compatible, false if not.
     51 * @param   pszName             The name to inspect (UTF-8).
     52 */
     53static bool vboxSfOs2IsUtf8Name8dot3(const char *pszName, size_t cchName, PRTUTF16 pwszTmp, size_t cwcTmp)
     54{
     55    /* Reject names that must be too long when using maximum UTF-8 encoding. */
     56    if (cchName > (8 + 1 + 3) * 4)
     57        return false;
     58
     59    /* First char cannot be a dot. */
     60    if (*pszName == '.' || !*pszName)
     61        return false;
     62
     63    /*
     64     * To basic checks on code point level before doing full conversion.
     65     */
     66    const char *pszCursor = pszName;
     67    for (uint32_t cuc = 0; ; cuc++)
     68    {
     69        RTUNICP uCp;
     70        RTStrGetCpEx(&pszCursor, &uCp);
     71        if (uCp == '.')
     72        {
     73            for (uint32_t cuc = 0; ; cuc++)
     74            {
     75                RTUNICP uCp;
     76                RTStrGetCpEx(&pszCursor, &uCp);
     77                if (!uCp)
     78                    break;
     79                if (uCp == '.')
     80                    return false;
     81                if (cuc >= 3)
     82                    return false;
     83            }
     84            break;
     85        }
     86        if (!uCp)
     87            break;
     88        if (cuc >= 8)
     89            return false;
     90    }
     91
     92    /*
     93     * Convert to UTF-16 and then to native codepage.
     94     */
     95    size_t cwcActual = cwcTmp;
     96    int rc = RTStrToUtf16Ex(pszName, cchName, &pwszTmp, cwcTmp, &cwcActual);
     97    if (RT_SUCCESS(rc))
     98    {
     99        char *pszTmp = (char *)&pwszTmp[cwcActual + 1];
     100        rc = KernStrFromUcs(NULL, pszTmp, pwszTmp, (cwcTmp - cwcActual - 1) * sizeof(RTUTF16), cwcActual);
     101        if (rc != NO_ERROR)
     102        {
     103            LogRel(("vboxSfOs2IsUtf8Name8dot3: KernStrFromUcs failed: %d\n", rc));
     104            return false;
     105        }
     106
     107        /*
     108         * Redo the check.
     109         * Note! This could be bogus if a DBCS leadin sequence collides with '.'.
     110         */
     111        for (uint32_t cch = 0; ; cch++)
     112        {
     113            char ch = *pszTmp++;
     114            if (ch == '.')
     115                break;
     116            if (ch == '\0')
     117                return true;
     118            if (cch >= 8)
     119                return false;
     120        }
     121        for (uint32_t cch = 0; ; cch++)
     122        {
     123            char ch = *pszTmp++;
     124            if (ch == '\0')
     125                return true;
     126            if (ch != '.')
     127                return false;
     128            if (cch >= 3)
     129                return false;
     130        }
     131    }
     132    else
     133        LogRel(("vboxSfOs2IsUtf8Name8dot3: RTStrToUtf16Ex failed: %Rrc\n", rc));
     134    return false;
     135}
     136
     137
     138/**
     139 * @returns Updated pbDst on success, NULL on failure.
     140 */
     141static uint8_t *vboxSfOs2CopyUtf8Name(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
     142{
     143    /* Convert UTF-8 to UTF-16: */
     144    int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
     145    if (RT_SUCCESS(rc))
     146    {
     147        char *pszDst = (char *)(pbDst + 1);
     148        rc = KernStrFromUcs(NULL, pszDst, pwszTmp, CCHMAXPATHCOMP, cwcTmp);
     149        if (rc == NO_ERROR)
     150        {
     151            size_t cchDst = strlen(pszDst);
     152            *pbDst++ = (uint8_t)cchDst;
     153            pbDst   += cchDst;
     154            *pbDst++ = '\0';
     155            return pbDst;
     156        }
     157        LogRel(("vboxSfOs2CopyUtf8Name: KernStrFromUcs failed: %d\n", rc));
     158    }
     159    else
     160        LogRel(("vboxSfOs2CopyUtf8Name: RTStrToUtf16Ex failed: %Rrc\n", rc));
     161    return NULL;
     162}
     163
     164
     165/**
     166 * @returns Updated pbDst on success, NULL on failure.
     167 */
     168static uint8_t *vboxSfOs2CopyUtf8NameAndUpperCase(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
     169{
     170    /* Convert UTF-8 to UTF-16: */
     171    int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
     172    if (RT_SUCCESS(rc))
     173    {
     174        char *pszDst = (char *)(pbDst + 1);
     175        rc = KernStrFromUcs(NULL, pszDst, RTUtf16ToUpper(pwszTmp), CCHMAXPATHCOMP, cwcTmp);
     176        if (rc == NO_ERROR)
     177        {
     178            size_t cchDst = strlen(pszDst);
     179            *pbDst++ = (uint8_t)cchDst;
     180            pbDst   += cchDst;
     181            *pbDst++ = '\0';
     182            return pbDst;
     183        }
     184        LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: KernStrFromUcs failed: %d\n", rc));
     185    }
     186    else
     187        LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: RTStrToUtf16Ex failed: %Rrc\n", rc));
     188    return NULL;
     189}
     190
     191
     192/**
     193 * @returns Updated pbDst on success, NULL on failure.
     194 */
     195static uint8_t *vboxSfOs2CopyUtf16NameAndUpperCase(uint8_t *pbDst, PRTUTF16 pwszSrc, size_t cwcSrc)
     196{
     197    char *pszDst = (char *)(pbDst + 1);
     198    APIRET rc = KernStrFromUcs(NULL, pszDst, RTUtf16ToUpper(pwszSrc), CCHMAXPATHCOMP, cwcSrc);
     199    if (rc == NO_ERROR)
     200    {
     201        size_t cchDst = strlen(pszDst);
     202        *pbDst++ = (uint8_t)cchDst;
     203        pbDst   += cchDst;
     204        *pbDst++ = '\0';
     205        return pbDst;
     206    }
     207    LogRel(("vboxSfOs2CopyUtf16NameAndUpperCase: KernStrFromUcs failed: %#x\n", rc));
     208    return NULL;
     209}
     210
     211
     212
     213/**
     214 * Worker for FS32_FINDFIRST, FS32_FINDNEXT and FS32_FINDFROMNAME.
     215 *
     216 * @returns OS/2 status code.
     217 * @param   pFolder     The folder we're working on.
     218 * @param   pFsFsd      The search handle data.
     219 * @param   pDataBuf    The search data buffer (some handle data there too).
     220 * @param   uLevel      The info level to return.
     221 * @param   fFlags      Position flag.
     222 * @param   pbData      The output buffer.
     223 * @param   cbData      The size of the output buffer.
     224 * @param   cMaxMatches The maximum number of matches to return.
     225 * @param   pcMatches   Where to set the number of returned matches.
     226 */
     227static APIRET vboxSfOs2ReadDirEntries(PVBOXSFFOLDER pFolder, PVBOXSFFS pFsFsd, PVBOXSFFSBUF pDataBuf, ULONG uLevel, ULONG fFlags,
     228                                      PBYTE pbData, ULONG cbData, USHORT cMaxMatches, PUSHORT pcMatches)
     229{
     230    APIRET rc = NO_ERROR;
     231
     232    /*
     233     * If we're doing EAs, the buffer starts with an EAOP structure.
     234     */
     235    EAOP    EaOp;
     236    PEAOP   pEaOpUser;
     237    switch (uLevel)
     238    {
     239        case FI_LVL_EAS_FROM_LIST:
     240        case FI_LVL_EAS_FROM_LIST_64:
     241        case FI_LVL_EAS_FULL:
     242        case FI_LVL_EAS_FULL_5:
     243        case FI_LVL_EAS_FULL_8:
     244            if (cbData >= sizeof(EaOp))
     245            {
     246                rc = KernCopyIn(&EaOp, pbData, sizeof(EaOp));
     247                if (rc == NO_ERROR)
     248                {
     249                    EaOp.fpGEAList = (PGEALIST)KernSelToFlat((uintptr_t)EaOp.fpGEAList);
     250                    EaOp.fpFEAList = NULL;
     251
     252                    pEaOpUser = (PEAOP)pbData;
     253                    pbData += sizeof(*pEaOpUser);
     254                    cbData -= sizeof(*pEaOpUser);
     255                    break;
     256                }
     257            }
     258            else
     259                rc = ERROR_BUFFER_OVERFLOW;
     260            Log(("vboxSfOs2ReadDirEntries: Failed to read EAOP: %u\n", rc));
     261            return rc;
     262    }
     263
     264    /*
     265     * Do the reading.
     266     */
     267    USHORT cMatches;
     268    for (cMatches = 0; cMatches < cMaxMatches;)
     269    {
     270        /*
     271         * Do we need to fetch more directory entries?
     272         */
     273        PSHFLDIRINFO pEntry = pDataBuf->pEntry;
     274        if (   pDataBuf->cEntriesLeft == 0
     275            || pEntry == NULL /* paranoia */)
     276        {
     277            pDataBuf->pEntry  = pEntry = (PSHFLDIRINFO)(pDataBuf + 1);
     278            pDataBuf->cbValid = pDataBuf->cbBuf - sizeof(*pDataBuf);
     279            int vrc = VbglR0SfDirInfo(&g_SfClient, &pFolder->hHostFolder, pFsFsd->hHostDir, pDataBuf->pFilter,
     280                                      cMaxMatches == 1 ? SHFL_LIST_RETURN_ONE : 0, 0 /*index*/, &pDataBuf->cbValid,
     281                                      pEntry, &pDataBuf->cEntriesLeft);
     282            if (RT_SUCCESS(vrc))
     283            {
     284                AssertReturn(pDataBuf->cbValid >= RT_UOFFSETOF(SHFLDIRINFO, name.String), ERROR_SYS_INTERNAL);
     285                AssertReturn(pDataBuf->cbValid >= RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size, ERROR_SYS_INTERNAL);
     286                Log4(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo returned %#x matches in %#x bytes\n", pDataBuf->cEntriesLeft, pDataBuf->cbValid));
     287            }
     288            else
     289            {
     290                if (vrc == VERR_NO_MORE_FILES)
     291                    Log(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo failed %Rrc (%d,%d)\n", vrc, pDataBuf->cEntriesLeft, pDataBuf->cbValid));
     292                else
     293                    Log4(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo returned VERR_NO_MORE_FILES (%d,%d)\n", pDataBuf->cEntriesLeft, pDataBuf->cbValid));
     294                pDataBuf->pEntry       = NULL;
     295                pDataBuf->cEntriesLeft = 0;
     296                if (cMatches == 0)
     297                {
     298                    if (vrc == VERR_NO_MORE_FILES)
     299                        rc = ERROR_NO_MORE_FILES;
     300                    else
     301                        rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
     302                }
     303                break;
     304            }
     305        }
     306
     307        /*
     308         * Do matching and stuff the return buffer.
     309         */
     310        if (   !((pEntry->Info.Attr.fMode >> RTFS_DOS_SHIFT) & pDataBuf->fExcludedAttribs)
     311            && ((pEntry->Info.Attr.fMode >> RTFS_DOS_SHIFT) & pDataBuf->fMustHaveAttribs) == pDataBuf->fMustHaveAttribs
     312            && (   pDataBuf->fLongFilenames
     313                || pEntry->cucShortName
     314                || vboxSfOs2IsUtf8Name8dot3((char *)pEntry->name.String.utf8, pEntry->name.u16Length,
     315                                            pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp))))
     316        {
     317            /*
     318             * We stages all but FEAs (level 3, 4, 13 and 14).
     319             */
     320            PBYTE const pbUserBufStart = pbData; /* In case we need to skip a bad name. */
     321            uint8_t    *pbToCopy       = pDataBuf->abStaging;
     322            uint8_t    *pbDst          = pbToCopy;
     323
     324            /* Position (originally used for FS32_FINDFROMNAME 'position', but since reused
     325               for FILEFINDBUF3::oNextEntryOffset and FILEFINDBUF4::oNextEntryOffset): */
     326            if (fFlags & FF_GETPOS)
     327            {
     328                *(uint32_t *)pbDst = pFsFsd->offLastFile + 1;
     329                pbDst += sizeof(uint32_t);
     330            }
     331
     332            /* Dates: Creation, Access, Write */
     333            vboxSfOs2DateTimeFromTimeSpec((FDATE *)pbDst, (FTIME *)(pbDst + 2), pEntry->Info.BirthTime, pDataBuf->cMinLocalTimeDelta);
     334            pbDst += sizeof(FDATE) + sizeof(FTIME);
     335            vboxSfOs2DateTimeFromTimeSpec((FDATE *)pbDst, (FTIME *)(pbDst + 2), pEntry->Info.AccessTime, pDataBuf->cMinLocalTimeDelta);
     336            pbDst += sizeof(FDATE) + sizeof(FTIME);
     337            vboxSfOs2DateTimeFromTimeSpec((FDATE *)pbDst, (FTIME *)(pbDst + 2), pEntry->Info.ModificationTime, pDataBuf->cMinLocalTimeDelta);
     338            pbDst += sizeof(FDATE) + sizeof(FTIME);
     339
     340            /* File size, allocation size, attributes: */
     341            if (uLevel >= FI_LVL_STANDARD_64)
     342            {
     343                *(uint64_t *)pbDst = pEntry->Info.cbObject;
     344                pbDst += sizeof(uint64_t);
     345                *(uint64_t *)pbDst = pEntry->Info.cbAllocated;
     346                pbDst += sizeof(uint64_t);
     347                *(uint32_t *)pbDst = (pEntry->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT;
     348                pbDst += sizeof(uint32_t);
     349            }
     350            else
     351            {
     352                *(uint32_t *)pbDst = (uint32_t)RT_MIN(pEntry->Info.cbObject, _2G - 1);
     353                pbDst += sizeof(uint32_t);
     354                *(uint32_t *)pbDst = (uint32_t)RT_MIN(pEntry->Info.cbAllocated, _2G - 1);
     355                pbDst += sizeof(uint32_t);
     356                *(uint16_t *)pbDst = (uint16_t)((pEntry->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
     357                pbDst += sizeof(uint16_t); /* (Curious: Who is expanding this to 32-bits for 32-bit callers? */
     358            }
     359
     360            /* Extra EA related fields: */
     361            if (   uLevel == FI_LVL_STANDARD
     362                || uLevel == FI_LVL_STANDARD_64)
     363            { /* nothing */ }
     364            else if (   uLevel == FI_LVL_STANDARD_EASIZE
     365                     || uLevel == FI_LVL_STANDARD_EASIZE_64)
     366            {
     367                /* EA size: */
     368                *(uint32_t *)pbDst = 0;
     369                pbDst += sizeof(uint32_t);
     370            }
     371            else
     372            {
     373                /* Empty FEALIST - flush pending data first: */
     374                uint32_t cbToCopy = pbDst - pbToCopy;
     375                if (cbToCopy < cbData)
     376                {
     377                    rc = KernCopyOut(pbData, pbToCopy, cbToCopy);
     378                    if (rc == NO_ERROR)
     379                    {
     380                        pbData += cbToCopy;
     381                        cbData -= cbToCopy;
     382                        pbDst   = pbToCopy;
     383
     384                        uint32_t cbWritten = 0;
     385                        EaOp.fpFEAList = (PFEALIST)pbData;
     386                        rc = vboxSfOs2MakeEmptyEaListEx(&EaOp, uLevel, &cbWritten, &pEaOpUser->oError);
     387                        if (rc == NO_ERROR)
     388                        {
     389                            cbData -= cbWritten;
     390                            pbData += cbWritten;
     391                        }
     392                    }
     393                }
     394                else
     395                    rc = ERROR_BUFFER_OVERFLOW;
     396                if (rc != NO_ERROR)
     397                    break;
     398            }
     399
     400            /* The length prefixed filename. */
     401            if (pDataBuf->fLongFilenames)
     402                pbDst = vboxSfOs2CopyUtf8Name(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
     403                                           (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
     404            else if (pEntry->cucShortName == 0)
     405                pbDst = vboxSfOs2CopyUtf8NameAndUpperCase(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
     406                                                       (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
     407            else
     408                pbDst = vboxSfOs2CopyUtf16NameAndUpperCase(pbDst, pEntry->uszShortName, pEntry->cucShortName);
     409            if (pbDst)
     410            {
     411                /*
     412                 * Copy out the staged data.
     413                 */
     414                uint32_t cbToCopy = pbDst - pbToCopy;
     415                if (cbToCopy <= cbData)
     416                {
     417                    rc = KernCopyOut(pbData, pbToCopy, cbToCopy);
     418                    if (rc == NO_ERROR)
     419                    {
     420                        Log4(("vboxSfOs2ReadDirEntries: match #%u LB %#x: '%s'\n", cMatches, cbToCopy, pEntry->name.String.utf8));
     421                        Log4(("%.*Rhxd\n", cbToCopy, pbToCopy));
     422
     423                        pbData += cbToCopy;
     424                        cbData -= cbToCopy;
     425                        pbDst   = pbToCopy;
     426
     427                        cMatches++;
     428                        pFsFsd->offLastFile++;
     429                    }
     430                    else
     431                        break;
     432                }
     433                else
     434                {
     435                    rc = ERROR_BUFFER_OVERFLOW;
     436                    break;
     437                }
     438            }
     439            else
     440            {
     441                /* Name conversion issue, just skip the entry. */
     442                Log3(("vboxSfOs2ReadDirEntries: Skipping '%s' due to name conversion issue.\n", pEntry->name.String.utf8));
     443                cbData -= pbUserBufStart - pbData;
     444                pbData  = pbUserBufStart;
     445            }
     446        }
     447        else
     448            Log3(("vboxSfOs2ReadDirEntries: fMode=%#x filter out by %#x/%#x; '%s'\n",
     449                  pEntry->Info.Attr.fMode, pDataBuf->fMustHaveAttribs, pDataBuf->fExcludedAttribs, pEntry->name.String.utf8));
     450
     451        /*
     452         * Advance to the next directory entry from the host.
     453         */
     454        if (pDataBuf->cEntriesLeft-- > 1)
     455        {
     456            pDataBuf->pEntry = pEntry = (PSHFLDIRINFO)&pEntry->name.String.utf8[pEntry->name.u16Size];
     457            uintptr_t offEntry = (uintptr_t)pEntry - (uintptr_t)(pDataBuf + 1);
     458            AssertMsgReturn(offEntry + RT_UOFFSETOF(SHFLDIRINFO, name.String) <= pDataBuf->cbValid,
     459                            ("offEntry=%#x cbValid=%#x\n", offEntry, pDataBuf->cbValid), ERROR_SYS_INTERNAL);
     460            AssertMsgReturn(offEntry + RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size <= pDataBuf->cbValid,
     461                            ("offEntry=%#x cbValid=%#x\n", offEntry, pDataBuf->cbValid), ERROR_SYS_INTERNAL);
     462        }
     463        else
     464            pDataBuf->pEntry = NULL;
     465    }
     466
     467    *pcMatches = cMatches;
     468
     469    /* Ignore buffer overflows if we've got matches to return. */
     470    if (rc == ERROR_BUFFER_OVERFLOW && cMatches > 0)
     471        rc = NO_ERROR;
     472    return rc;
     473}
     474
     475
     476DECLASM(APIRET)
     477FS32_FINDFIRST(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszPath, LONG offCurDirEnd, ULONG fAttribs,
     478               PFSFSI pFsFsi, PVBOXSFFS pFsFsd, PBYTE pbData, ULONG cbData, PUSHORT pcMatches, ULONG uLevel, ULONG fFlags)
     479{
     480    LogFlow(("pCdFsi=%p pCdFsd=%p pszPath=%p:{%s} offCurDirEnd=%d fAttribs=%#x pFsFsi=%p pFsFsd=%p pbData=%p cbData=%#x pcMatches=%p:{%#x} uLevel=%#x fFlags=%#x\n",
     481             pCdFsi, pCdFsd, pszPath, pszPath, offCurDirEnd, fAttribs, pFsFsi, pFsFsd, pbData, cbData, pcMatches, *pcMatches, uLevel, fFlags));
     482    USHORT const cMaxMatches = *pcMatches;
     483    *pcMatches = 0;
     484
     485    /*
     486     * Input validation.
     487     */
     488    switch (uLevel)
     489    {
     490        case FI_LVL_STANDARD:
     491        case FI_LVL_STANDARD_64:
     492        case FI_LVL_STANDARD_EASIZE:
     493        case FI_LVL_STANDARD_EASIZE_64:
     494            break;
     495
     496        case FI_LVL_EAS_FROM_LIST:
     497        case FI_LVL_EAS_FROM_LIST_64:
     498            if (cbData < sizeof(EAOP))
     499            {
     500                Log(("FS32_FINDFIRST: Buffer smaller than EAOP: %#x\n", cbData));
     501                return ERROR_BUFFER_OVERFLOW;
     502            }
     503            break;
     504
     505        default:
     506            LogRel(("FS32_FINDFIRST: Unsupported info level %u!\n", uLevel));
     507            return ERROR_INVALID_LEVEL;
     508    }
     509
     510    /*
     511     * Resolve path to a folder and folder relative path.
     512     */
     513    PVBOXSFFOLDER pFolder;
     514    PSHFLSTRING   pStrFolderPath;
     515    RT_NOREF(pCdFsi);
     516    APIRET rc = vboxSfOs2ResolvePath(pszPath, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
     517    LogFlow(("FS32_FINDFIRST: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
     518    if (rc == NO_ERROR)
     519    {
     520        /*
     521         * Look for a wildcard filter at the end of the path, saving it all for
     522         * later in NT filter speak if present.
     523         */
     524        PSHFLSTRING pFilter = NULL;
     525        char *pszFilter = RTPathFilename((char *)pStrFolderPath->String.utf8);
     526        if (   pszFilter
     527            && (   strchr(pszFilter, '*') != NULL
     528                || strchr(pszFilter, '?') != NULL))
     529        {
     530            if (strcmp(pszFilter, "*.*") == 0)
     531            {
     532                /* All files, no filtering needed. Just drop the filter expression from the directory path. */
     533                *pszFilter = '\0';
     534                pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
     535            }
     536            else
     537            {
     538                /* Duplicate the whole path. */
     539                pFilter = vboxSfOs2StrDup(pStrFolderPath->String.ach, pStrFolderPath->u16Length);
     540                if (pFilter)
     541                {
     542                    /* Drop filter from directory path. */
     543                    *pszFilter = '\0';
     544                    pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
     545
     546                    /* Convert filter part of the copy to NT speak. */
     547                    pszFilter = (char *)&pFilter->String.utf8[(uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]];
     548                    for (;;)
     549                    {
     550                        char ch = *pszFilter;
     551                        if (ch == '?')
     552                            *pszFilter = '>';       /* The DOS question mark: Matches one char, but dots and end-of-name eats them. */
     553                        else if (ch == '.')
     554                        {
     555                            char ch2 = pszFilter[1];
     556                            if (ch2 == '*' || ch2 == '?')
     557                                *pszFilter = '"';   /* The DOS dot: Matches a dot or end-of-name. */
     558                        }
     559                        else if (ch == '*')
     560                        {
     561                            if (pszFilter[1] == '.')
     562                                *pszFilter = '<';   /* The DOS star: Matches zero or more chars except the DOS dot.*/
     563                        }
     564                        else if (ch == '\0')
     565                            break;
     566                        pszFilter++;
     567                    }
     568                }
     569                else
     570                    rc = ERROR_NOT_ENOUGH_MEMORY;
     571            }
     572        }
     573        /*
     574         * When no wildcard is specified, we're supposed to return a single entry
     575         * with the name in the final component.  Exception is the root, where we
     576         * always list the whole thing.
     577         *
     578         * Not sure if we'll ever see a trailing slash here (pszFilter == NULL),
     579         * but if we do we should accept it only for the root.
     580         */
     581        else if (pszFilter)
     582        {
     583            pFilter = pStrFolderPath;
     584            pStrFolderPath = vboxSfOs2StrDup(pFilter->String.ach, pszFilter - pFilter->String.ach);
     585            if (!pStrFolderPath)
     586                rc = ERROR_NOT_ENOUGH_MEMORY;
     587        }
     588        else if (!pszFilter && pStrFolderPath->u16Length > 1)
     589        {
     590            LogFlow(("FS32_FINDFIRST: Trailing slash (%s)\n", pStrFolderPath->String.utf8));
     591            rc = ERROR_PATH_NOT_FOUND;
     592        }
     593        else
     594            LogFlow(("FS32_FINDFIRST: Root dir (%s)\n", pStrFolderPath->String.utf8));
     595
     596        /*
     597         * Make sure we've got a buffer for keeping unused search results.
     598         */
     599        PVBOXSFFSBUF pDataBuf = NULL;
     600        if (rc == NO_ERROR)
     601        {
     602            pDataBuf = (PVBOXSFFSBUF)RTMemAlloc(cMaxMatches == 1 ? VBOXSFFSBUF_MIN_SIZE : _16K - ALLOC_HDR_SIZE);
     603            if (pDataBuf)
     604                pDataBuf->cbBuf = cMaxMatches == 1 ? VBOXSFFSBUF_MIN_SIZE : _16K - ALLOC_HDR_SIZE;
     605            else
     606            {
     607                pDataBuf = (PVBOXSFFSBUF)RTMemAlloc(VBOXSFFSBUF_MIN_SIZE);
     608                if (pDataBuf)
     609                    pDataBuf->cbBuf = VBOXSFFSBUF_MIN_SIZE;
     610                else
     611                    rc = ERROR_NOT_ENOUGH_MEMORY;
     612            }
     613        }
     614        if (rc == NO_ERROR)
     615        {
     616            /*
     617             * Now, try open the directory for reading.
     618             * We pre-use the data buffer for parameter passin to avoid
     619             * wasting any stack space.
     620             */
     621            PSHFLCREATEPARMS pParams = (PSHFLCREATEPARMS)(pDataBuf + 1);
     622            RT_ZERO(*pParams);
     623            pParams->CreateFlags = SHFL_CF_DIRECTORY   | SHFL_CF_ACT_FAIL_IF_NEW  | SHFL_CF_ACT_OPEN_IF_EXISTS
     624                                 | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
     625            int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
     626            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate(%s) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
     627                     pStrFolderPath->String.ach, vrc, pParams->Result, pParams->Info.Attr.fMode, pParams->Handle));
     628            if (RT_SUCCESS(vrc))
     629            {
     630                switch (pParams->Result)
     631                {
     632                    case SHFL_FILE_EXISTS:
     633                        if (pParams->Handle != SHFL_HANDLE_NIL)
     634                        {
     635                            /*
     636                             * Initialize the structures.
     637                             */
     638                            pFsFsd->hHostDir        = pParams->Handle;
     639                            pFsFsd->u32Magic        = VBOXSFFS_MAGIC;
     640                            pFsFsd->pFolder         = pFolder;
     641                            pFsFsd->pBuf            = pDataBuf;
     642                            pFsFsd->offLastFile     = 0;
     643                            pDataBuf->u32Magic      = VBOXSFFSBUF_MAGIC;
     644                            pDataBuf->cbValid       = 0;
     645                            pDataBuf->cEntriesLeft  = 0;
     646                            pDataBuf->pEntry        = NULL;
     647                            pDataBuf->pFilter       = pFilter;
     648                            pDataBuf->fMustHaveAttribs   = (uint8_t)((fAttribs >> 8) & (RTFS_DOS_MASK_OS2 >> RTFS_DOS_SHIFT));
     649                            pDataBuf->fExcludedAttribs   = (uint8_t)(~fAttribs
     650                                                                     & (  (RTFS_DOS_MASK_OS2 & ~(RTFS_DOS_ARCHIVED | RTFS_DOS_READONLY)
     651                                                                        >> RTFS_DOS_SHIFT)));
     652                            pDataBuf->fLongFilenames     = RT_BOOL(fAttribs & FF_ATTR_LONG_FILENAME);
     653                            pDataBuf->cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     654
     655                            rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags,
     656                                                         pbData, cbData, cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
     657                            if (rc == NO_ERROR)
     658                            {
     659                                uint32_t cRefs = ASMAtomicIncU32(&pFolder->cOpenSearches);
     660                                Assert(cRefs < _4K); RT_NOREF(cRefs);
     661
     662                                /* We keep these on success: */
     663                                if (pFilter == pStrFolderPath)
     664                                    pStrFolderPath = NULL;
     665                                pFilter  = NULL;
     666                                pDataBuf = NULL;
     667                                pFolder  = NULL;
     668                            }
     669                            else
     670                            {
     671                                vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pFsFsd->hHostDir);
     672                                AssertRC(vrc);
     673                                pFsFsd->u32Magic = ~VBOXSFFS_MAGIC;
     674                                pDataBuf->u32Magic = ~VBOXSFFSBUF_MAGIC;
     675                                pFsFsd->pFolder  = NULL;
     676                                pFsFsd->hHostDir = NULL;
     677                            }
     678                        }
     679                        else
     680                        {
     681                            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate returns NIL handle for '%s'\n", pStrFolderPath->String.utf8));
     682                            rc = ERROR_PATH_NOT_FOUND;
     683                        }
     684                        break;
     685
     686                    case SHFL_PATH_NOT_FOUND:
     687                        rc = ERROR_PATH_NOT_FOUND;
     688                        break;
     689
     690                    default:
     691                    case SHFL_FILE_NOT_FOUND:
     692                        rc = ERROR_FILE_NOT_FOUND;
     693                        break;
     694                }
     695            }
     696            else
     697                rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
     698        }
     699
     700        RTMemFree(pDataBuf);
     701        if (pFilter != pStrFolderPath)
     702            vboxSfOs2StrFree(pFilter);
     703        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
     704    }
     705    LogFlow(("FS32_FINDFIRST: returns %u\n", rc));
     706    return rc;
     707}
     708
     709
     710DECLASM(APIRET)
     711FS32_FINDFROMNAME(PFSFSI pFsFsi, PVBOXSFFS pFsFsd, PBYTE pbData, ULONG cbData, PUSHORT pcMatches,
     712                  ULONG uLevel, ULONG uPosition, PCSZ pszName, ULONG fFlags)
     713{
     714    LogFlow(("FS32_FINDFROMNAME: pFsFsi=%p pFsFsd=%p pbData=%p cbData=%#x pcMatches=%p:{%#x} uLevel=%#x uPosition=%#x pszName=%p:{%s} fFlags=%#x\n",
     715             pFsFsi, pFsFsd, pbData, cbData, pcMatches, *pcMatches, uLevel, uPosition, pszName, pszName, fFlags));
     716
     717    /*
     718     * Input validation.
     719     */
     720    USHORT const cMaxMatches = *pcMatches;
     721    *pcMatches = 0;
     722    AssertReturn(pFsFsd->u32Magic == VBOXSFFS_MAGIC, ERROR_SYS_INTERNAL);
     723    PVBOXSFFOLDER pFolder = pFsFsd->pFolder;
     724    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     725    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     726    Assert(pFolder->cOpenSearches > 0);
     727    PVBOXSFFSBUF pDataBuf = pFsFsd->pBuf;
     728    AssertReturn(pDataBuf, ERROR_SYS_INTERNAL);
     729    Assert(pDataBuf->u32Magic == VBOXSFFSBUF_MAGIC);
     730
     731    switch (uLevel)
     732    {
     733        case FI_LVL_STANDARD:
     734        case FI_LVL_STANDARD_64:
     735        case FI_LVL_STANDARD_EASIZE:
     736        case FI_LVL_STANDARD_EASIZE_64:
     737            break;
     738
     739        case FI_LVL_EAS_FROM_LIST:
     740        case FI_LVL_EAS_FROM_LIST_64:
     741            Log(("FS32_FINDFIRST: FI_LVL_EAS_FROM_LIST[_64] -> ERROR_EAS_NOT_SUPPORTED\n"));
     742            return ERROR_EAS_NOT_SUPPORTED;
     743
     744        default:
     745            LogRel(("FS32_FINDFIRST: Unsupported info level %u!\n", uLevel));
     746            return ERROR_INVALID_LEVEL;
     747    }
     748
     749    /*
     750     * Check if we're just continuing.  This is usually the case.
     751     */
     752    APIRET rc;
     753    if (uPosition == pFsFsd->offLastFile)
     754        rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags, pbData, cbData,
     755                                     cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
     756    else
     757    {
     758        Log(("TODO: uPosition differs: %#x, expected %#x (%s)\n", uPosition, pFsFsd->offLastFile, pszName));
     759        rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags, pbData, cbData,
     760                                     cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
     761    }
     762
     763    RT_NOREF(pFsFsi, pszName);
     764    LogFlow(("FS32_FINDFROMNAME: returns %u (*pcMatches=%#x)\n", rc, *pcMatches));
     765    return rc;
     766}
     767
     768
     769DECLASM(APIRET)
     770FS32_FINDNEXT(PFSFSI pFsFsi, PVBOXSFFS pFsFsd, PBYTE pbData, ULONG cbData, PUSHORT pcMatches, ULONG uLevel, ULONG fFlags)
     771{
     772    LogFlow(("FS32_FINDNEXT: pFsFsi=%p pFsFsd=%p pbData=%p cbData=%#x pcMatches=%p:{%#x} uLevel=%#x fFlags=%#x\n",
     773             pFsFsi, pFsFsd, pbData, cbData, pcMatches, *pcMatches, uLevel, fFlags));
     774
     775    /*
     776     * Input validation.
     777     */
     778    USHORT const cMaxMatches = *pcMatches;
     779    *pcMatches = 0;
     780    AssertReturn(pFsFsd->u32Magic == VBOXSFFS_MAGIC, ERROR_SYS_INTERNAL);
     781    PVBOXSFFOLDER pFolder = pFsFsd->pFolder;
     782    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     783    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     784    Assert(pFolder->cOpenSearches > 0);
     785    PVBOXSFFSBUF pDataBuf = pFsFsd->pBuf;
     786    AssertReturn(pDataBuf, ERROR_SYS_INTERNAL);
     787    Assert(pDataBuf->u32Magic == VBOXSFFSBUF_MAGIC);
     788
     789    switch (uLevel)
     790    {
     791        case FI_LVL_STANDARD:
     792        case FI_LVL_STANDARD_64:
     793        case FI_LVL_STANDARD_EASIZE:
     794        case FI_LVL_STANDARD_EASIZE_64:
     795            break;
     796
     797        case FI_LVL_EAS_FROM_LIST:
     798        case FI_LVL_EAS_FROM_LIST_64:
     799            Log(("FS32_FINDFIRST: FI_LVL_EAS_FROM_LIST[_64] -> ERROR_EAS_NOT_SUPPORTED\n"));
     800            return ERROR_EAS_NOT_SUPPORTED;
     801
     802        default:
     803            LogRel(("FS32_FINDFIRST: Unsupported info level %u!\n", uLevel));
     804            return ERROR_INVALID_LEVEL;
     805    }
     806
     807    /*
     808     * Read more.
     809     */
     810    APIRET rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags, pbData, cbData,
     811                                        cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
     812
     813    NOREF(pFsFsi);
     814    LogFlow(("FS32_FINDNEXT: returns %u (*pcMatches=%#x)\n", rc, *pcMatches));
     815    return rc;
     816}
     817
     818
     819DECLASM(APIRET)
     820FS32_FINDCLOSE(PFSFSI pFsFsi, PVBOXSFFS pFsFsd)
     821{
     822    /*
     823     * Input validation.
     824     */
     825    AssertReturn(pFsFsd->u32Magic == VBOXSFFS_MAGIC, ERROR_SYS_INTERNAL);
     826    PVBOXSFFOLDER pFolder = pFsFsd->pFolder;
     827    AssertReturn(pFolder != NULL, ERROR_SYS_INTERNAL);
     828    Assert(pFolder->u32Magic == VBOXSFFOLDER_MAGIC);
     829    Assert(pFolder->cOpenSearches > 0);
     830    PVBOXSFFSBUF pDataBuf = pFsFsd->pBuf;
     831    AssertReturn(pDataBuf, ERROR_SYS_INTERNAL);
     832    Assert(pDataBuf->u32Magic == VBOXSFFSBUF_MAGIC);
     833
     834    /*
     835     * Close it.
     836     */
     837    if (pFsFsd->hHostDir != SHFL_HANDLE_NIL)
     838    {
     839        int vrc = VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pFsFsd->hHostDir);
     840        AssertRC(vrc);
     841    }
     842
     843    pFsFsd->u32Magic   = ~VBOXSFFS_MAGIC;
     844    pFsFsd->hHostDir   = SHFL_HANDLE_NIL;
     845    pFsFsd->pFolder    = NULL;
     846    pFsFsd->pBuf       = NULL;
     847    vboxSfOs2StrFree(pDataBuf->pFilter);
     848    pDataBuf->pFilter  = NULL;
     849    pDataBuf->u32Magic = ~VBOXSFFSBUF_MAGIC;
     850    pDataBuf->cbBuf    = 0;
     851    RTMemFree(pDataBuf);
     852
     853    uint32_t cRefs = ASMAtomicDecU32(&pFolder->cOpenSearches);
     854    Assert(cRefs < _4K); RT_NOREF(cRefs);
     855    vboxSfOs2ReleaseFolder(pFolder);
     856
     857    RT_NOREF(pFsFsi);
     858    LogFlow(("FS32_FINDCLOSE: returns NO_ERROR\n"));
     859    return NO_ERROR;
     860}
     861
     862
     863
     864
     865
     866DECLASM(APIRET)
     867FS32_FINDNOTIFYFIRST(PCDFSI pCdFsi, PVBOXSFCD pCdFsd, PCSZ pszPath, LONG offCurDirEnd, ULONG fAttribs,
     868                     PUSHORT phHandle, PBYTE pbData, ULONG cbData, PUSHORT pcMatches,
     869                     ULONG uLevel, ULONG fFlags)
     870{
     871    RT_NOREF(pCdFsi, pCdFsd, pszPath, offCurDirEnd, fAttribs, phHandle, pbData, cbData, pcMatches, uLevel, fFlags);
    49872    return ERROR_NOT_SUPPORTED;
    50873}
    51874
    52875
    53 DECLASM(int)
    54 FS32_FINDFROMNAME(PFSFSI pfsfsi, PVBOXSFFS pfsfsd, PBYTE pbData, USHORT cbData, PUSHORT pcMatch,
    55                   USHORT uLevel, ULONG position, PCSZ pszName, USHORT fFlags)
    56 {
    57     NOREF(pfsfsi); NOREF(pfsfsd); NOREF(pbData); NOREF(cbData); NOREF(pcMatch); NOREF(uLevel); NOREF(position); NOREF(pszName);
    58     NOREF(fFlags);
     876DECLASM(APIRET)
     877FS32_FINDNOTIFYNEXT(ULONG hHandle, PBYTE pbData, ULONG cbData, PUSHORT pcMatchs, ULONG uLevel, ULONG cMsTimeout)
     878{
     879    RT_NOREF(hHandle, pbData, cbData, pcMatchs, uLevel, cMsTimeout);
    59880    return ERROR_NOT_SUPPORTED;
    60881}
    61882
    62883
    63 DECLASM(int)
    64 FS32_FINDNEXT(PFSFSI pfsfsi, PVBOXSFFS pfsfsd, PBYTE pbData, USHORT cbData, PUSHORT pcMatch,
    65               USHORT uLevel, USHORT fFlags)
    66 {
    67     NOREF(pfsfsi); NOREF(pfsfsd); NOREF(pbData); NOREF(cbData); NOREF(pcMatch); NOREF(uLevel); NOREF(fFlags);
    68     return ERROR_NOT_SUPPORTED;
    69 }
    70 
    71 
    72 DECLASM(int)
    73 FS32_FINDCLOSE(PFSFSI pfsfsi, PVBOXSFFS pfsfsd)
    74 {
    75     NOREF(pfsfsi); NOREF(pfsfsd);
    76     return ERROR_NOT_SUPPORTED;
    77 }
    78 
    79 
    80 
    81 
    82 
    83 DECLASM(int)
    84 FS32_FINDNOTIFYFIRST(PCDFSI pcdfsi, PVBOXSFCD pcdfsd, PCSZ pszName, USHORT iCurDirEnd, USHORT fAtt,
    85                      PUSHORT phHandle, PBYTE pbData, USHORT cbData, PUSHORT pcMatch,
    86                      USHORT uLevel, USHORT fFlags)
    87 {
    88     NOREF(pcdfsi); NOREF(pcdfsd); NOREF(pszName); NOREF(iCurDirEnd); NOREF(fAtt); NOREF(phHandle); NOREF(pbData); NOREF(cbData);
    89     NOREF(pcMatch); NOREF(uLevel); NOREF(fFlags);
    90     return ERROR_NOT_SUPPORTED;
    91 }
    92 
    93 
    94 DECLASM(int)
    95 FS32_FINDNOTIFYNEXT(USHORT hHandle, PBYTE pbData, USHORT cbData, PUSHORT pcMatch,
    96                     USHORT uLevel, ULONG cMsTimeout)
    97 {
    98     NOREF(hHandle); NOREF(pbData); NOREF(cbData); NOREF(pcMatch); NOREF(uLevel); NOREF(cMsTimeout);
    99     return ERROR_NOT_SUPPORTED;
    100 }
    101 
    102 
    103 DECLASM(int)
    104 FS32_FINDNOTIFYCLOSE(USHORT hHandle)
     884DECLASM(APIRET)
     885FS32_FINDNOTIFYCLOSE(ULONG hHandle)
    105886{
    106887    NOREF(hHandle);
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInit.cpp

    r68577 r75337  
    55
    66/*
    7  * Copyright (c) 2007 knut st. osmundsen <[email protected]>
     7 * Copyright (c) 2007-2018 knut st. osmundsen <[email protected]>
    88 *
    99 * Permission is hereby granted, free of charge, to any person
     
    3737
    3838#include <VBox/VBoxGuestLib.h>
     39#include <VBox/VBoxGuest.h>
    3940#include <VBox/log.h>
    4041#include <iprt/assert.h>
     
    7071DECLASM(void) VBoxSFR0Init(void)
    7172{
    72     Log(("VBoxSFR0Init: g_fpfnDevHlp=%lx u32Version=%RX32 u32Session=%RX32 pfnServiceEP=%p g_u32Info=%u (%#x)\n",
    73          g_fpfnDevHlp, g_VBoxGuestIDC.u32Version, g_VBoxGuestIDC.u32Session, g_VBoxGuestIDC.pfnServiceEP, g_u32Info, g_u32Info));
     73    RTLogBackdoorPrintf("VBoxSFR0Init: g_fpfnDevHlp=%lx u32Version=%RX32 u32Session=%RX32 pfnServiceEP=%p g_u32Info=%u (%#x)\n",
     74                        g_fpfnDevHlp, g_VBoxGuestIDC.u32Version, g_VBoxGuestIDC.u32Session, g_VBoxGuestIDC.pfnServiceEP, g_u32Info, g_u32Info);
     75    RTLogBackdoorPrintf("&KernSISData=%p\n",        &KernSISData);
     76    RTLogBackdoorPrintf("&KernLISData=%p\n",        &KernLISData);
     77    RTLogBackdoorPrintf("KernInterruptLevel=%#x\n", KernInterruptLevel);
     78    RTLogBackdoorPrintf("KernTKSSBase=%p\n",        KernTKSSBase);
     79
     80    KernAllocMutexLock(&g_MtxFolders);
     81    RTListInit(&g_FolderHead);
    7482
    7583    /*
     
    101109#endif
    102110
    103                 Log(("VBoxSFR0Init: completed successfully\n"));
     111                RTLogBackdoorPrintf("VBoxSFR0Init: completed successfully\n");
    104112                return;
    105113            }
    106114        }
    107115
    108         LogRel(("VBoxSF: RTR0Init failed, rc=%Rrc\n", rc));
     116        RTLogBackdoorPrintf("VBoxSF: RTR0Init failed, rc=%Rrc\n", rc);
    109117    }
    110118    else
    111         LogRel(("VBoxSF: Failed to connect to VBoxGuest.sys.\n"));
     119        RTLogBackdoorPrintf("VBoxSF: Failed to connect to VBoxGuest.sys.\n");
    112120}
    113121
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h

    r69474 r75337  
    3636#define INCL_ERROR
    3737#define INCL_LONGLONG
    38 #include <os2.h>
     38#define OS2EMX_PLAIN_CHAR
    3939#include <os2ddk/bsekee.h>
    4040#include <os2ddk/devhlp.h>
     
    4545#include <iprt/types.h>
    4646#include <iprt/assert.h>
     47#include <iprt/list.h>
     48#include <VBox/VBoxGuestLibSharedFolders.h>
     49
     50
     51/** Allocation header used by RTMemAlloc.
     52 * This should be subtracted from round numbers. */
     53#define ALLOC_HDR_SIZE  (0x10 + 4)
     54
     55
     56/**
     57 * A shared folder
     58 */
     59typedef struct VBOXSFFOLDER
     60{
     61    /** For the shared folder list. */
     62    RTLISTNODE          ListEntry;
     63    /** Magic number (VBOXSFFOLDER_MAGIC). */
     64    uint32_t            u32Magic;
     65    /** Number of active references to this folder. */
     66    uint32_t volatile   cRefs;
     67    /** Number of open files referencing this folder.   */
     68    uint32_t volatile   cOpenFiles;
     69    /** Number of open searches referencing this folder.   */
     70    uint32_t volatile   cOpenSearches;
     71    /** Number of drives this is attached to. */
     72    uint8_t volatile    cDrives;
     73
     74    /** The host folder handle. */
     75    VBGLSFMAP           hHostFolder;
     76
     77    /** OS/2 volume handle. */
     78    USHORT              hVpb;
     79
     80    /** The length of the folder name. */
     81    uint8_t             cchName;
     82    /** The shared folder name. */
     83    char                szName[RT_FLEXIBLE_ARRAY];
     84} VBOXSFFOLDER;
     85/** Pointer to a shared folder. */
     86typedef VBOXSFFOLDER *PVBOXSFFOLDER;
     87/** Magic value for VBOXSFVP (Neal Town Stephenson). */
     88#define VBOXSFFOLDER_MAGIC      UINT32_C(0x19591031)
     89
     90/** The shared mutex protecting folders list, drives and the connection. */
     91extern MutexLock_t      g_MtxFolders;
     92/** List of active folder (PVBOXSFFOLDER). */
     93extern RTLISTANCHOR     g_FolderHead;
    4794
    4895
     
    5097 * VBoxSF Volume Parameter Structure.
    5198 *
    52  * @remark  Overlays the 36 byte VPFSD structure (fsd.h).
     99 * @remarks Overlays the 36 byte VPFSD structure (fsd.h).
     100 * @note    No self pointer as the kernel may reallocate these.
    53101 */
    54102typedef struct VBOXSFVP
    55103{
    56     uint32_t u32Dummy;
     104    /** Magic value (VBOXSFVP_MAGIC). */
     105    uint32_t         u32Magic;
     106    /** The folder. */
     107    PVBOXSFFOLDER    pFolder;
    57108} VBOXSFVP;
    58109AssertCompile(sizeof(VBOXSFVP) <= sizeof(VPFSD));
    59110/** Pointer to a VBOXSFVP struct. */
    60111typedef VBOXSFVP *PVBOXSFVP;
     112/** Magic value for VBOXSFVP (Laurence van Cott Niven). */
     113#define VBOXSFVP_MAGIC          UINT32_C(0x19380430)
    61114
    62115
     
    80133 * @remark  Overlays the 30 byte SFFSD structure (fsd.h).
    81134 */
    82 typedef struct VBOXSFFSD
    83 {
     135typedef struct VBOXSFSYFI
     136{
     137    /** Magic value (VBOXSFSYFI_MAGIC). */
     138    uint32_t            u32Magic;
    84139    /** Self pointer for quick 16:16 to flat translation. */
    85     struct VBOXSFFSD *pSelf;
    86 } VBOXSFFSD;
    87 AssertCompile(sizeof(VBOXSFFSD) <= sizeof(SFFSD));
    88 /** Pointer to a VBOXSFFSD struct. */
    89 typedef VBOXSFFSD *PVBOXSFFSD;
     140    struct VBOXSFSYFI  *pSelf;
     141    /** The host file handle. */
     142    SHFLHANDLE          hHostFile;
     143    /** The shared folder (referenced). */
     144    PVBOXSFFOLDER       pFolder;
     145} VBOXSFSYFI;
     146AssertCompile(sizeof(VBOXSFSYFI) <= sizeof(SFFSD));
     147/** Pointer to a VBOXSFSYFI struct. */
     148typedef VBOXSFSYFI *PVBOXSFSYFI;
     149/** Magic value for VBOXSFSYFI (Jon Ellis Meacham). */
     150#define VBOXSFSYFI_MAGIC         UINT32_C(0x19690520)
     151
     152
     153/**
     154 * VBoxSF File Search Buffer (header).
     155 */
     156typedef struct VBOXSFFSBUF
     157{
     158    /** A magic number (VBOXSFFSBUF_MAGIC). */
     159    uint32_t            u32Magic;
     160    /** Amount of buffer space allocated after this header. */
     161    uint32_t            cbBuf;
     162    /** The filter string (full path), NULL if all files are request. */
     163    PSHFLSTRING         pFilter;
     164    /** Must have attributes (shifted down DOS attributes).  */
     165    uint8_t             fMustHaveAttribs;
     166    /** Non-matching attributes (shifted down DOS attributes).  */
     167    uint8_t             fExcludedAttribs;
     168    /** Set if FF_ATTR_LONG_FILENAME. */
     169    bool                fLongFilenames : 1;
     170    uint8_t             bPadding1;
     171    /** The local time offset to use for this search. */
     172    int16_t             cMinLocalTimeDelta;
     173    uint8_t             abPadding2[2];
     174    /** Number of valid bytes in the buffer. */
     175    uint32_t            cbValid;
     176    /** Number of entries left in the buffer.   */
     177    uint32_t            cEntriesLeft;
     178    /** The next entry. */
     179    PSHFLDIRINFO        pEntry;
     180    /** Staging area for staging a full FILEFINDBUF4L (+ 32 safe bytes). */
     181    uint8_t             abStaging[RT_ALIGN_32(sizeof(FILEFINDBUF4L) + 32, 8)];
     182    /** For temporary convertion to UTF-8 so we can use KernStrFromUcs to get
     183     *  string encoded according to the process codepage. */
     184    RTUTF16             wszTmp[260];
     185} VBOXSFFSBUF;
     186AssertCompileSizeAlignment(VBOXSFFSBUF, 8);
     187/** Pointer to a file search buffer. */
     188typedef VBOXSFFSBUF *PVBOXSFFSBUF;
     189/** Magic number for VBOXSFFSBUF (Robert Anson Heinlein). */
     190#define VBOXSFFSBUF_MAGIC       UINT32_C(0x19070707)
     191/** Minimum buffer size. */
     192#define VBOXSFFSBUF_MIN_SIZE (  RT_ALIGN_32(sizeof(VBOXSFFSBUF) + sizeof(SHFLDIRINFO) + CCHMAXPATHCOMP * 4 + ALLOC_HDR_SIZE, 64) \
     193                              - ALLOC_HDR_SIZE)
    90194
    91195
     
    94198 *
    95199 * @remark  Overlays the 24 byte FSFSD structure (fsd.h).
     200 * @note    No self pointer as the kernel may reallocate these.
    96201 */
    97202typedef struct VBOXSFFS
    98203{
    99     /** Self pointer for quick 16:16 to flat translation. */
    100     struct VBOXSFFS *pSelf;
     204    /** Magic value (VBOXSFFS_MAGIC). */
     205    uint32_t            u32Magic;
     206    /** The last file position position. */
     207    uint32_t            offLastFile;
     208    /** The host directory handle. */
     209    SHFLHANDLE          hHostDir;
     210    /** The shared folder (referenced). */
     211    PVBOXSFFOLDER       pFolder;
     212    /** Search data buffer. */
     213    PVBOXSFFSBUF        pBuf;
    101214} VBOXSFFS;
    102215AssertCompile(sizeof(VBOXSFFS) <= sizeof(FSFSD));
    103216/** Pointer to a VBOXSFFS struct. */
    104217typedef VBOXSFFS *PVBOXSFFS;
    105 
     218/** Magic number for VBOXSFFS (Isaak Azimov). */
     219#define VBOXSFFS_MAGIC          UINT32_C(0x19200102)
     220
     221
     222extern VBGLSFCLIENT g_SfClient;
     223
     224PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength);
     225PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc);
     226void        vboxSfOs2StrFree(PSHFLSTRING pStr);
     227
     228APIRET      vboxSfOs2ResolvePath(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd,
     229                                 PVBOXSFFOLDER *ppFolder, PSHFLSTRING *ppStrFolderPath);
     230void        vboxSfOs2ReleasePathAndFolder(PSHFLSTRING pStrPath, PVBOXSFFOLDER pFolder);
     231void        vboxSfOs2ReleaseFolder(PVBOXSFFOLDER pFolder);
     232APIRET      vboxSfOs2ConvertStatusToOs2(int vrc, APIRET rcDefault);
     233int16_t     vboxSfOs2GetLocalTimeDelta(void);
     234void        vboxSfOs2DateTimeFromTimeSpec(FDATE *pDosDate, FTIME *pDosTime, RTTIMESPEC SrcTimeSpec, int16_t cMinLocalTimeDelta);
     235PRTTIMESPEC vboxSfOs2DateTimeToTimeSpec(FDATE DosDate, FTIME DosTime, int16_t cMinLocalTimeDelta, PRTTIMESPEC pDstTimeSpec);
     236APIRET      vboxSfOs2FileStatusFromObjInfo(PBYTE pbDst, ULONG cbDst, ULONG uLevel, SHFLFSOBJINFO const *pSrc);
     237APIRET      vboxSfOs2SetInfoCommonWorker(PVBOXSFFOLDER pFolder, SHFLHANDLE hHostFile, ULONG fAttribs,
     238                                         PFILESTATUS pTimestamps, PSHFLFSOBJINFO pObjInfoBuf);
     239APIRET      vboxSfOs2MakeEmptyEaList(PEAOP pEaOp, ULONG uLevel);
     240APIRET      vboxSfOs2MakeEmptyEaListEx(PEAOP pEaOp, ULONG uLevel, uint32_t *pcbWritten, ULONG *poffError);
     241
     242DECLASM(PVBOXSFVP) Fsh32GetVolParams(USHORT hVbp, PVPFSI *ppVpFsi /*optional*/);
    106243
    107244#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette