fresh git tree for public release

we regretfully had to remove our git history for licensing reasons

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2010-10-11 14:59:26 -04:00
commit 0ad4db4fad
271 changed files with 71255 additions and 0 deletions

106
mount/enum.c Normal file
View file

@ -0,0 +1,106 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include "nfs41_driver.h" /* NFS41_PROVIDER_NAME_A */
void PrintErrorMessage(
IN DWORD dwError);
static __inline
void PrintMountLine(
LPCTSTR local,
LPCTSTR remote)
{
_tprintf(TEXT("%-11s %s\n"), local, remote);
}
/* ENUM_RESOURCE_BUFFER_SIZE
* from msdn re: WNetEnumResource
* "An application cannot set the lpBuffer parameter to NULL and
* retrieve the required buffer size from the lpBufferSize parameter.
* Instead, the application should allocate a buffer of a reasonable
* size16 kilobytes is typicaland use the value of lpBufferSize for
* error detection." */
#define ENUM_RESOURCE_BUFFER_SIZE (16*1024)
DWORD EnumMounts(
IN LPNETRESOURCE pContainer)
{
DWORD result = NO_ERROR;
LPNETRESOURCE pResources;
DWORD i, dwCount, dwTotal = 0;
DWORD dwBufferSize = ENUM_RESOURCE_BUFFER_SIZE;
HANDLE hEnum;
pResources = (LPNETRESOURCE)GlobalAlloc(0, ENUM_RESOURCE_BUFFER_SIZE);
if (pResources == NULL) {
result = WN_OUT_OF_MEMORY;
goto out;
}
result = WNetOpenEnum(RESOURCE_CONNECTED,
RESOURCETYPE_DISK, 0, pContainer, &hEnum);
if (result)
goto out_free;
_tprintf(TEXT("Listing %s mounts:\n\n"), TEXT(NFS41_PROVIDER_NAME_A));
PrintMountLine(TEXT("Volume"), TEXT("Remote path"));
do
{
dwCount = (DWORD)-1;
result = WNetEnumResource(hEnum,
&dwCount, pResources, &dwBufferSize);
if (result == NO_ERROR)
{
for (i = 0; i < dwCount; i++)
{
if (_tcscmp(pResources[i].lpProvider,
TEXT(NFS41_PROVIDER_NAME_A)) == 0)
{
PrintMountLine(pResources[i].lpLocalName,
pResources[i].lpRemoteName);
dwTotal++;
}
}
}
else if (result != WN_NO_MORE_ENTRIES)
break;
}
while (result != WN_NO_MORE_ENTRIES);
result = WNetCloseEnum(hEnum);
_tprintf(TEXT("\nFound %d share%s.\n"), dwTotal,
dwTotal == 1 ? TEXT("") : TEXT("s"));
out_free:
GlobalFree((HGLOBAL)pResources);
out:
return result;
}

369
mount/mount.c Normal file
View file

@ -0,0 +1,369 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <Winnetwk.h> /* for WNet*Connection */
#include <stdlib.h>
#include <stdio.h>
#include "nfs41_driver.h" /* NFS41_PROVIDER_NAME_A */
#include "options.h"
DWORD EnumMounts(
IN LPNETRESOURCE pContainer);
static DWORD DoMount(
IN LPTSTR pLocalName,
IN LPTSTR pRemoteName,
IN PMOUNT_OPTION_LIST pOptions);
static DWORD DoUnmount(
IN LPTSTR pLocalName,
IN BOOL bForce);
static void RecursivePrintEaInformation(
IN PFILE_FULL_EA_INFORMATION EA);
static BOOL ParseDriveLetter(
IN LPTSTR pArg,
OUT PTCH pDriveLetter);
void PrintErrorMessage(
IN DWORD dwError);
static VOID PrintUsage(LPTSTR pProcess)
{
_tprintf(TEXT("Usage: %s [options] <drive letter|*> <hostname>:<path>\n")
TEXT("Options:\n")
TEXT("\t-h\thelp\n")
TEXT("\t-d\tunmount\n")
TEXT("\t-f\tforce unmount if the drive is in use\n")
TEXT("\t-o <comma-separated mount options>\n")
TEXT("Mount options:\n")
TEXT("\tro\tmount as read-only\n")
TEXT("\trsize=#\tread buffer size in bytes\n")
TEXT("\twsize=#\twrite buffer size in bytes\n"),
pProcess, pProcess, pProcess);
}
DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
{
DWORD i, result = NO_ERROR;
TCHAR szLocalName[] = TEXT("C:\0");
LPTSTR pLocalName = NULL;
LPTSTR pRemoteName = NULL;
BOOL bUnmount = FALSE;
BOOL bForceUnmount = FALSE;
MOUNT_OPTION_LIST Options;
if (argc == 1) {
/* list open nfs shares */
result = EnumMounts(NULL);
if (result)
PrintErrorMessage(GetLastError());
goto out;
}
result = InitializeMountOptions(&Options, MAX_OPTION_BUFFER_SIZE);
if (result) {
PrintErrorMessage(GetLastError());
goto out;
}
/* parse command line */
for (i = 1; i < argc; i++)
{
if (argv[i][0] == TEXT('-'))
{
if (_tcscmp(argv[i], TEXT("-h")) == 0) /* help */
{
PrintUsage(argv[0]);
goto out;
}
else if (_tcscmp(argv[i], TEXT("-d")) == 0) /* unmount */
{
bUnmount = TRUE;
}
else if (_tcscmp(argv[i], TEXT("-f")) == 0) /* force unmount */
{
bForceUnmount = TRUE;
}
else if (_tcscmp(argv[i], TEXT("-o")) == 0) /* mount option */
{
++i;
if (i >= argc)
{
result = ERROR_BAD_ARGUMENTS;
_ftprintf(stderr, TEXT("Mount options missing ")
TEXT("after '-o'.\n\n"));
PrintUsage(argv[0]);
goto out_free;
}
if (!ParseMountOptions(argv[i], &Options))
{
result = ERROR_BAD_ARGUMENTS;
goto out_free;
}
}
else
_ftprintf(stderr, TEXT("Unrecognized option ")
TEXT("'%s', disregarding.\n"), argv[i]);
}
else if (pLocalName == NULL) /* drive letter */
{
pLocalName = argv[i];
}
else if (pRemoteName == NULL) /* remote path */
{
pRemoteName = argv[i];
}
else
_ftprintf(stderr, TEXT("Unrecognized argument ")
TEXT("'%s', disregarding.\n"), argv[i]);
}
/* validate local drive letter */
if (pLocalName == NULL)
{
result = ERROR_BAD_ARGUMENTS;
_ftprintf(stderr, TEXT("Missing argument for drive letter.\n\n"));
PrintUsage(argv[0]);
goto out_free;
}
if (FALSE == ParseDriveLetter(pLocalName, szLocalName))
{
result = ERROR_BAD_ARGUMENTS;
_ftprintf(stderr, TEXT("Invalid drive letter '%s'. ")
TEXT("Expected 'C' or 'C:'.\n\n"), pLocalName);
PrintUsage(argv[0]);
goto out_free;
}
if (bUnmount == TRUE) /* unmount */
{
result = DoUnmount(szLocalName, bForceUnmount);
if (result)
PrintErrorMessage(result);
}
else /* mount */
{
if (pRemoteName == NULL)
{
result = ERROR_BAD_NET_NAME;
_ftprintf(stderr, TEXT("Missing argument for remote path.\n\n"));
PrintUsage(argv[0]);
goto out_free;
}
result = DoMount(szLocalName, pRemoteName, &Options);
if (result)
PrintErrorMessage(result);
}
out_free:
FreeMountOptions(&Options);
out:
return result;
}
static void ConvertUnixSlashes(
IN OUT LPTSTR pRemoteName)
{
LPTSTR pos = pRemoteName;
for (pos = pRemoteName; *pos; pos++)
if (*pos == TEXT('/'))
*pos = TEXT('\\');
}
static LPTSTR FindEndOfServer(
IN LPTSTR pRemoteName)
{
LPTSTR pos = pRemoteName;
while (*pos && *pos != TEXT(':'))
pos++;
return pos;
}
static DWORD ParseRemoteName(
IN LPTSTR pRemoteName,
IN OUT PMOUNT_OPTION_LIST pOptions,
OUT LPTSTR pConnectionName,
IN size_t cchConnectionLen)
{
DWORD result = NO_ERROR;
LPTSTR pEnd;
ConvertUnixSlashes(pRemoteName);
pEnd = FindEndOfServer(pRemoteName);
/* fail if the server name doesn't end with :\ */
if (*pEnd == 0 || pEnd[0] != TEXT(':') || pEnd[1] != TEXT('\\')) {
_ftprintf(stderr, TEXT("Failed to parse the remote path. ")
TEXT("Expected 'hostname:\\path'.\n"));
result = ERROR_BAD_ARGUMENTS;
goto out;
}
*pEnd = TEXT('\0');
++pEnd;
if (!InsertOption(TEXT("srvname"), pRemoteName, pOptions) ||
!InsertOption(TEXT("mntpt"), *pEnd ? pEnd : TEXT("\\"), pOptions)) {
result = ERROR_BAD_ARGUMENTS;
goto out;
}
result = StringCchCopy(pConnectionName, cchConnectionLen, TEXT("\\\\"));
if (FAILED(result))
goto out;
result = StringCbCat(pConnectionName, cchConnectionLen, pRemoteName);
if (FAILED(result))
goto out;
if (*pEnd)
result = StringCchCat(pConnectionName, cchConnectionLen, pEnd);
out:
return result;
}
static DWORD DoMount(
IN LPTSTR pLocalName,
IN LPTSTR pRemoteName,
IN PMOUNT_OPTION_LIST pOptions)
{
DWORD result = NO_ERROR;
TCHAR szExisting[MAX_PATH];
TCHAR szRemoteName[MAX_PATH];
DWORD dwLength;
*szRemoteName = TEXT('\0');
result = ParseRemoteName(pRemoteName, pOptions, szRemoteName, MAX_PATH);
if (result)
goto out;
/* fail if the connection already exists */
result = WNetGetConnection(pLocalName, (LPTSTR)szExisting, &dwLength);
if (result == NO_ERROR)
{
result = ERROR_ALREADY_ASSIGNED;
_ftprintf(stderr, TEXT("Mount failed, drive %s is ")
TEXT("already assigned to '%s'.\n"),
pLocalName, szExisting);
}
else
{
NETRESOURCE NetResource;
TCHAR szConnection[MAX_PATH];
DWORD ConnectSize = MAX_PATH, ConnectResult;
ZeroMemory(&NetResource, sizeof(NETRESOURCE));
NetResource.dwType = RESOURCETYPE_DISK;
/* drive letter is chosen automatically if lpLocalName == NULL */
NetResource.lpLocalName = *pLocalName == TEXT('*') ? NULL : pLocalName;
NetResource.lpRemoteName = szRemoteName;
/* ignore other network providers */
NetResource.lpProvider = TEXT(NFS41_PROVIDER_NAME_A);
/* pass mount options via lpComment */
if (pOptions->Buffer->Length)
{
if (pOptions->Current)
pOptions->Current->NextEntryOffset = 0;
NetResource.lpComment = (LPTSTR)pOptions->Buffer;
}
result = WNetUseConnection(NULL,
&NetResource, NULL, NULL, 0,
szConnection, &ConnectSize, &ConnectResult);
if (result == NO_ERROR)
_tprintf(TEXT("Successfully mounted %s to drive %s\n"),
pRemoteName, szConnection);
else
_ftprintf(stderr, TEXT("WNetUseConnection(%s, %s) ")
TEXT("failed with error code %u.\n"),
pLocalName, szRemoteName, result);
}
out:
return result;
}
static DWORD DoUnmount(
IN LPTSTR pLocalName,
IN BOOL bForce)
{
DWORD result;
/* disconnect the specified local drive */
result = WNetCancelConnection2(pLocalName, 0, bForce);
/* TODO: verify that this connection uses the nfs41 provider -cbodley */
switch (result)
{
case NO_ERROR:
_tprintf(TEXT("Drive %s unmounted successfully.\n"), pLocalName);
break;
case ERROR_NOT_CONNECTED:
_ftprintf(stderr, TEXT("Drive %s is not currently ")
TEXT("connected.\n"), pLocalName);
break;
default:
_ftprintf(stderr, TEXT("WNetCancelConnection2(%s) failed ")
TEXT("with error code %u.\n"), pLocalName, result);
break;
}
return result;
}
static BOOL ParseDriveLetter(
IN LPTSTR pArg,
OUT PTCH pDriveLetter)
{
/* accept 'C' or 'C:' */
switch (_tcslen(pArg))
{
case 2:
if (pArg[1] != TEXT(':'))
return FALSE;
/* break intentionally missing */
case 1:
if (_istlower(*pArg))
*pArg = (TCHAR)_totupper(*pArg);
else if (!_istupper(*pArg) && *pArg != TEXT('*'))
return FALSE;
*pDriveLetter = *pArg;
return TRUE;
}
return FALSE;
}
void PrintErrorMessage(
IN DWORD dwError)
{
LPTSTR lpMsgBuf = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf, 0, NULL);
_fputts(lpMsgBuf, stderr);
LocalFree(lpMsgBuf);
}

230
mount/options.c Normal file
View file

@ -0,0 +1,230 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <stdio.h>
#include "options.h"
DWORD InitializeMountOptions(
IN OUT PMOUNT_OPTION_LIST Options,
IN ULONG BufferSize)
{
Options->Current = NULL;
Options->Remaining = BufferSize;
Options->Buffer = LocalAlloc(LMEM_ZEROINIT, BufferSize);
if (Options->Buffer == NULL)
return ERROR_OUTOFMEMORY;
Options->Buffer->Secret = MOUNT_OPTION_BUFFER_SECRET;
return NO_ERROR;
}
void FreeMountOptions(
IN OUT PMOUNT_OPTION_LIST Options)
{
Options->Current = NULL;
Options->Remaining = 0;
if (Options->Buffer)
{
LocalFree(Options->Buffer);
Options->Buffer = NULL;
}
}
static BOOL FindOptionByName(
IN LPCTSTR Name,
IN PMOUNT_OPTION_LIST Options,
OUT PFILE_FULL_EA_INFORMATION* ppOption)
{
PFILE_FULL_EA_INFORMATION Current =
(PFILE_FULL_EA_INFORMATION)Options->Buffer->Buffer;
ULONG NameLength = (ULONG)_tcslen(Name) * sizeof(TCHAR);
for (;;)
{
if (Current->EaNameLength == NameLength &&
_tcscmp((LPTSTR)Current->EaName, Name) == 0)
{
*ppOption = Current;
return TRUE;
}
if (Current->NextEntryOffset == 0)
break;
Current = (PFILE_FULL_EA_INFORMATION)
((PBYTE)Current + Current->NextEntryOffset);
}
return FALSE;
}
static FORCEINLINE ULONG EaBufferSize(
IN UCHAR NameSize,
IN USHORT ValueSize)
{
ULONG Size = sizeof(ULONG) + 2 * sizeof(UCHAR) + sizeof(USHORT)
+ NameSize + ValueSize + sizeof(TCHAR);
/* extended attributes require ULONG alignment;
* see documentation for IoCheckEaBufferValidity() */
return ( (Size + 3) / sizeof(ULONG) ) * sizeof(ULONG);
}
static FORCEINLINE ULONG EaBufferNextOffset(
IN PFILE_FULL_EA_INFORMATION EaBuffer)
{
return EaBufferSize(
EaBuffer->EaNameLength,
EaBuffer->EaValueLength);
}
BOOL InsertOption(
IN LPCTSTR Name,
IN LPCTSTR Value,
IN OUT PMOUNT_OPTION_LIST Options)
{
PFILE_FULL_EA_INFORMATION Current;
UCHAR NameLen = (UCHAR)_tcslen(Name) * sizeof(TCHAR);
USHORT ValueLen = (USHORT)_tcslen(Value) * sizeof(TCHAR);
ULONG SpaceRequired = EaBufferSize(NameLen, ValueLen);
/* don't allow duplicate options */
if (FindOptionByName(Name, Options, &Current)) {
_ftprintf(stderr, TEXT("Found a duplicate option ")
TEXT("'%s%s%s' while parsing '%s%s%s'.\n"),
(PTCH)Current->EaName,
Current->EaValueLength ? TEXT("=") : TEXT(""),
(PTCH)(Current->EaName + Current->EaNameLength + sizeof(TCHAR)),
Name, ValueLen ? TEXT("=") : Value, Value);
return FALSE;
}
/* fail if we're out of space */
if (SpaceRequired > Options->Remaining) {
_ftprintf(stderr, TEXT("Out of space for options!\n"));
return FALSE;
}
if (Options->Current == NULL)
Current = Options->Current = (PFILE_FULL_EA_INFORMATION)
Options->Buffer->Buffer;
else
Current = Options->Current = (PFILE_FULL_EA_INFORMATION)
((PBYTE)Options->Current + Options->Current->NextEntryOffset);
Current->EaNameLength = NameLen;
if (NameLen) /* copy attribute name */
StringCbCopy((LPTSTR)Current->EaName,
NameLen + sizeof(TCHAR), Name);
Current->EaValueLength = ValueLen;
if (ValueLen) /* copy attribute value */
StringCbCopy((LPTSTR)(Current->EaName + NameLen + sizeof(TCHAR)),
ValueLen + sizeof(TCHAR), Value);
Current->Flags = 0;
Current->NextEntryOffset = EaBufferNextOffset(Options->Current);
Options->Buffer->Length = (ULONG)(
(Current->EaName + NameLen + ValueLen + 2 * sizeof(TCHAR))
- Options->Buffer->Buffer );
Options->Remaining -= SpaceRequired;
return TRUE;
}
static void RecursivePrintEaInformation(
IN PFILE_FULL_EA_INFORMATION EA)
{
_tprintf(
TEXT("----------------------\n")
TEXT("Alignment: %5lu\n")
TEXT("NextEntryOffset: %5lu\n")
TEXT("Flags: %5u\n")
TEXT("EaNameLength: %5u\n")
TEXT("EaValueLength: %5u\n")
TEXT("EaName: %16ls\n")
TEXT("EaValue: %16ls\n\n"),
(ULONG_PTR)EA % sizeof(ULONG),
EA->NextEntryOffset,
EA->Flags,
EA->EaNameLength,
EA->EaValueLength,
(LPTSTR)EA->EaName,
(LPTSTR)(EA->EaName + EA->EaNameLength + sizeof(TCHAR)));
if (EA->NextEntryOffset)
RecursivePrintEaInformation((PFILE_FULL_EA_INFORMATION)
((PBYTE)EA + EA->NextEntryOffset));
}
static const TCHAR COMMA_T = TEXT(',');
static const TCHAR EQUAL_T = TEXT('=');
BOOL ParseMountOptions(
IN LPTSTR Arg,
IN OUT PMOUNT_OPTION_LIST Options)
{
PTCH pos, comma, equals;
pos = Arg;
for (;;)
{
comma = _tcschr(pos, COMMA_T);
if (comma)
{
if (comma == pos)
goto out_empty_option;
*comma = 0;
}
else if (_tcslen(pos) == 0)
goto out_empty_option;
/* accept 'option=value' or 'option' */
equals = _tcschr(pos, EQUAL_T);
if (equals)
{
if (equals == pos)
goto out_empty_option;
*equals = 0;
if (!InsertOption(pos, equals + 1, Options))
return FALSE;
}
else if (!InsertOption(pos, TEXT(""), Options))
return FALSE;
if (comma == NULL)
break;
pos = comma + 1;
}
/* RecursivePrintEaInformation(
(PFILE_FULL_EA_INFORMATION)Options->Buffer->Buffer); */
return TRUE;
out_empty_option:
_ftprintf(stderr, TEXT("Found an empty option while ")
TEXT("reading mount options at '%s'.\n"), pos);
return FALSE;
}

89
mount/options.h Normal file
View file

@ -0,0 +1,89 @@
/* Copyright (c) 2010
* The Regents of the University of Michigan
* All Rights Reserved
*
* Permission is granted to use, copy and redistribute this software
* for noncommercial education and research purposes, so long as no
* fee is charged, and so long as the name of the University of Michigan
* is not used in any advertising or publicity pertaining to the use
* or distribution of this software without specific, written prior
* authorization. Permission to modify or otherwise create derivative
* works of this software is not granted.
*
* This software is provided as is, without representation or warranty
* of any kind either express or implied, including without limitation
* the implied warranties of merchantability, fitness for a particular
* purpose, or noninfringement. The Regents of the University of
* Michigan shall not be liable for any damages, including special,
* indirect, incidental, or consequential damages, with respect to any
* claim arising out of or in connection with the use of the software,
* even if it has been or is hereafter advised of the possibility of
* such damages.
*/
#ifndef __NFS41_MOUNT_OPTIONS_H__
#define __NFS41_MOUNT_OPTIONS_H__
#define MOUNT_OPTION_BUFFER_SECRET ('n4')
/* MOUNT_OPTION_BUFFER
* Buffer passed to the network provider via NETRESOURCE.lpComment.
* To avoid interpreting a normal comment string as mount options, a
* NULL and secret number are expected at the front. */
typedef struct _MOUNT_OPTION_BUFFER {
USHORT Zero; /* = 0 */
USHORT Secret; /* = 'n4' */
ULONG Length;
CHAR Buffer[1];
} MOUNT_OPTION_BUFFER, *PMOUNT_OPTION_BUFFER;
#ifndef FILE_FULL_EA_INFORMATION
/* from wdm.h
* couldn't find a definition outside of the ddk -cbodley */
typedef struct _FILE_FULL_EA_INFORMATION {
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
#endif
/* MOUNT_OPTION_LIST
* Used internally to encapsulate the formation of the
* extended attribute buffer for mount options. */
typedef struct _MOUNT_OPTION_LIST {
PMOUNT_OPTION_BUFFER Buffer;
ULONG Remaining;
PFILE_FULL_EA_INFORMATION Current;
} MOUNT_OPTION_LIST, *PMOUNT_OPTION_LIST;
/* allocate space for 8 full attributes, but limit options by
* space rather than count. */
#define MAX_OPTION_EA_SIZE ( 8 * \
(sizeof(FILE_FULL_EA_INFORMATION) + MAX_PATH) )
#define MAX_OPTION_BUFFER_SIZE ( sizeof(MOUNT_OPTION_BUFFER) + \
MAX_OPTION_EA_SIZE - 1 )
/* options.c */
DWORD InitializeMountOptions(
IN OUT PMOUNT_OPTION_LIST Options,
IN ULONG BufferSize);
void FreeMountOptions(
IN OUT PMOUNT_OPTION_LIST Options);
BOOL ParseMountOptions(
IN LPTSTR Arg,
IN OUT PMOUNT_OPTION_LIST Options);
BOOL InsertOption(
IN LPCTSTR Name,
IN LPCTSTR Value,
IN OUT PMOUNT_OPTION_LIST Options);
#endif /* !__NFS41_MOUNT_OPTIONS_H__ */

17
mount/sources Normal file
View file

@ -0,0 +1,17 @@
TARGETTYPE=PROGRAM
TARGETNAME=nfs_mount
SOURCES=mount.c options.c enum.c
UMTYPE=console
USE_MSVCRT=1
TARGETLIBS=$(DDK_LIB_PATH)\mpr.lib
INCLUDES=..\sys
UMENTRY=wmain
UNICODE=1
C_DEFINES=$(C_DEFINES) -DUNICODE -D_UNICODE
!IF 0
/W3 is default level
bump to /Wall, but suppress warnings generated by system includes
!ENDIF
MSC_WARNING_LEVEL=/Wall /wd4668 /wd4619 /wd4820 /wd4255 /wd4711