mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3968 lines
99 KiB
3968 lines
99 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mpransi.cxx
|
|
|
|
Abstract:
|
|
|
|
Contains Ansi Entry pointes for the MPR api.
|
|
|
|
Author:
|
|
|
|
Dan Lafferty (danl) 20-Dec-1991
|
|
|
|
Environment:
|
|
|
|
User Mode -Win32
|
|
|
|
Notes:
|
|
|
|
I may want to add a buffer size parameter to ConvertToAnsi
|
|
|
|
Revision History:
|
|
|
|
16-Feb-1996 anirudhs
|
|
Added InputParmsToUnicode, OutputBufferToAnsi and helper functions.
|
|
These form a smaller, faster, interpreted scheme for writing the
|
|
Ansi APIs. This scheme is smaller chiefly because it eliminates
|
|
a very large amount of code duplication present in the previous
|
|
scheme. This also makes the Ansi APIs less bug-prone. It is
|
|
faster chiefly because intermediate storage is allocated with a
|
|
single heap allocation per API, rather than several. Also, the
|
|
number of passes to scan and copy data is minimized.
|
|
06-Oct-1995 anirudhs
|
|
MprMakeUnicodeNetRes and related functions: Removed duplicated
|
|
code for the string fields of the net resource; added code to
|
|
iterate over the string fields instead. Fixed access violation
|
|
and memory leaks.
|
|
24-Aug-1992 danl
|
|
For WNetGetConnection & WNetGetUser, we allocate a buffer twice
|
|
the size of the user buffer. The data is placed in this buffer.
|
|
Then we check to see if the data will fit in the user buffer
|
|
after it is translated to Ansi. The presence of DBSC characters
|
|
may make it not fit. In which case, we return the required number
|
|
of bytes. This number assumes worse-case where all characters are
|
|
DBCS characters.
|
|
20-Dec-1991 danl
|
|
created
|
|
|
|
--*/
|
|
|
|
//
|
|
// INCLUDES
|
|
//
|
|
|
|
#include "precomp.hxx"
|
|
#include <string.h> // strlen
|
|
#include <tstring.h> // STRLEN
|
|
|
|
|
|
//
|
|
// CONSTANTS
|
|
//
|
|
|
|
#define MAX_STRINGS_PER_API 6
|
|
|
|
//
|
|
// The following masks are used to indicate which fields in the NetResource
|
|
// structure are used by an API.
|
|
// The values must match the NRFieldOffset array.
|
|
//
|
|
#define NETRESFIELD_LOCALNAME 0x00000001
|
|
#define NETRESFIELD_REMOTENAME 0x00000002
|
|
#define NETRESFIELD_COMMENT 0x00000004
|
|
#define NETRESFIELD_PROVIDER 0x00000008
|
|
|
|
#define NUMBER_OF_NETRESFIELD 4
|
|
|
|
//
|
|
// Combinations of the NETRESFIELD_ constants, for passing to InputParmsToUnicode.
|
|
//
|
|
#define NETRES_LRP "\xB" // local name, remote name, provider
|
|
#define NETRES_RP "\xA" // remote name, provider
|
|
|
|
//
|
|
// Alignment macros
|
|
// These macros assume that sizeof(WCHAR) and sizeof(DWORD) are powers of 2
|
|
//
|
|
#define ROUND_UP_TO_WCHAR(x) (((DWORD)(x) + sizeof(WCHAR) - 1) & ~(sizeof(WCHAR) - 1))
|
|
#define ROUND_UP_TO_DWORD(x) (((DWORD)(x) + sizeof(DWORD) - 1) & ~(sizeof(DWORD) - 1))
|
|
#define IS_WCHAR_ALIGNED(x) (((DWORD)(x) & (sizeof(WCHAR) - 1)) == 0)
|
|
#define IS_DWORD_ALIGNED(x) (((DWORD)(x) & (sizeof(DWORD) - 1)) == 0)
|
|
|
|
//
|
|
// STRUCTURES
|
|
//
|
|
|
|
typedef union
|
|
{
|
|
DWORD dword;
|
|
LPCSTR lpcstr;
|
|
LPNETRESOURCEA lpNetResA;
|
|
LPVOID lpvoid;
|
|
LPDWORD lpdword;
|
|
} ANSI_PARM;
|
|
|
|
typedef union
|
|
{
|
|
DWORD dword;
|
|
LPBYTE lpbyte;
|
|
LPWSTR lpwstr;
|
|
LPNETRESOURCEW lpNetResW;
|
|
} UNICODE_PARM;
|
|
|
|
|
|
class ANSI_OUT_BUFFER
|
|
{
|
|
private:
|
|
const LPBYTE _Start; // Pointer to start of buffer
|
|
const DWORD _Size; // Total number of bytes in buffer
|
|
DWORD _Used; // Number of bytes used (may exceed Size)
|
|
|
|
public:
|
|
|
|
ANSI_OUT_BUFFER(LPBYTE Start, DWORD Size) :
|
|
_Start(Start),
|
|
_Size (Size),
|
|
_Used (0)
|
|
{ }
|
|
|
|
BYTE * Next() const
|
|
{ return _Start + _Used; }
|
|
|
|
BOOL Overflow() const
|
|
{ return (_Used > _Size); }
|
|
|
|
DWORD FreeSpace() const
|
|
{ return (Overflow() ? 0 : _Size - _Used); }
|
|
|
|
BOOL HasRoomFor(DWORD Request) const
|
|
{ return (_Used + Request <= _Size); }
|
|
|
|
void AddUsed(DWORD Request)
|
|
{ _Used += Request; }
|
|
|
|
DWORD GetUsage() const
|
|
{ return _Used; }
|
|
};
|
|
|
|
//
|
|
// STATIC DATA
|
|
//
|
|
|
|
//
|
|
// This array of field offsets is used to iterate through the string fields
|
|
// of a net resource.
|
|
// The order must match the NETRESFIELD_ definitions.
|
|
// Note, we assume the offsets are the same for NETRESOURCEA and NETRESOURCEW.
|
|
// CODEWORK: Use the member selection operator, etc.
|
|
//
|
|
const UINT NRFieldOffset[] =
|
|
{
|
|
FIELD_OFFSET(NETRESOURCEA, lpLocalName),
|
|
FIELD_OFFSET(NETRESOURCEA, lpRemoteName),
|
|
FIELD_OFFSET(NETRESOURCEA, lpComment),
|
|
FIELD_OFFSET(NETRESOURCEA, lpProvider)
|
|
};
|
|
|
|
//
|
|
// These functions evaluate to the equivalent of (&(pNetRes->field))
|
|
//
|
|
inline LPWSTR * pSTRING_FIELDW(const NETRESOURCEW * pNetRes, ULONG iField)
|
|
{
|
|
return ((LPWSTR *) ((BYTE *)(pNetRes) + NRFieldOffset[iField]));
|
|
}
|
|
|
|
inline LPSTR * pSTRING_FIELDA(const NETRESOURCEA * pNetRes, ULONG iField)
|
|
{
|
|
return ((LPSTR *) ((BYTE *)(pNetRes) + NRFieldOffset[iField]));
|
|
}
|
|
|
|
|
|
//
|
|
// Local Functions
|
|
//
|
|
|
|
DWORD
|
|
InputParmsToUnicode (
|
|
IN LPCSTR Instructions,
|
|
IN const ANSI_PARM InputParms[],
|
|
OUT UNICODE_PARM OutputParms[],
|
|
OUT LPBYTE * ppBuffer
|
|
);
|
|
|
|
DWORD
|
|
StringParmToUnicodePass1 (
|
|
IN LPCSTR StringParm,
|
|
OUT PANSI_STRING AnsiString,
|
|
OUT PUNICODE_STRING UnicodeString,
|
|
IN OUT PULONG BufferOffset
|
|
);
|
|
|
|
DWORD
|
|
StringParmToUnicodePass2 (
|
|
IN OUT PANSI_STRING AnsiString,
|
|
OUT PUNICODE_STRING UnicodeString,
|
|
IN const BYTE * BufferStart,
|
|
OUT LPWSTR * Result
|
|
);
|
|
|
|
DWORD
|
|
OutputBufferToAnsi(
|
|
IN char BufferFormat,
|
|
IN LPBYTE SourceBuffer,
|
|
OUT LPVOID AnsiBuffer,
|
|
IN OUT LPDWORD pcbBufferSize
|
|
);
|
|
|
|
DWORD
|
|
OutputStringToAnsi(
|
|
IN LPCWSTR UnicodeIn,
|
|
IN OUT ANSI_OUT_BUFFER * Buf
|
|
);
|
|
|
|
DWORD
|
|
OutputNetResourceToAnsi(
|
|
IN NETRESOURCEW * lpNetResW,
|
|
IN OUT ANSI_OUT_BUFFER * Buf
|
|
);
|
|
|
|
DWORD
|
|
MprMakeUnicodeNetRes(
|
|
IN LPNETRESOURCEA lpNetResourceA,
|
|
OUT LPNETRESOURCEW lpNetResourceW,
|
|
IN DWORD dwUsedNetResFields
|
|
);
|
|
|
|
DWORD
|
|
MprMakeAnsiNetRes(
|
|
IN LPNETRESOURCEW lpNetResourceW,
|
|
OUT LPNETRESOURCEA lpNetResourceA
|
|
);
|
|
|
|
VOID
|
|
MprFreeNetResW(
|
|
IN LPNETRESOURCEW lpNetResourceW
|
|
);
|
|
|
|
DWORD
|
|
MprAnsiNetResSize(
|
|
IN LPNETRESOURCEA lpNetResourceA
|
|
);
|
|
|
|
VOID
|
|
MprCopyAnsiNetRes(
|
|
OUT LPVOID lpBuffer,
|
|
IN LPNETRESOURCEA lpNetResourceA
|
|
);
|
|
|
|
DWORD
|
|
ConvertToUnicode(
|
|
OUT LPTSTR *UnicodeOut,
|
|
IN LPCSTR AnsiIn
|
|
);
|
|
|
|
DWORD
|
|
ConvertToAnsi(
|
|
OUT LPSTR AnsiOut,
|
|
IN LPTSTR UnicodeIn
|
|
);
|
|
|
|
DWORD
|
|
ResourceArrayToAnsi(
|
|
IN DWORD NumElements,
|
|
IN OUT LPVOID NetResourceArray
|
|
);
|
|
|
|
|
|
|
|
DWORD
|
|
InputParmsToUnicode (
|
|
IN LPCSTR Instructions,
|
|
IN const ANSI_PARM InputParms[],
|
|
OUT UNICODE_PARM OutputParms[],
|
|
OUT LPBYTE * ppBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts the caller's input parameters to Unicode.
|
|
If necessary, it allocates one temporary buffer in which it stores
|
|
the intermediate Unicode parameters. This minimizes the cost of
|
|
calls to LocalAlloc.
|
|
|
|
Arguments:
|
|
|
|
Instructions - A string of characters, roughly one for each member
|
|
of the InputParms array, describing the action to be taken on each
|
|
InputParms member. Recognized values for the characters are:
|
|
|
|
'S' (String) - InputParms member is an LPSTR to be converted to
|
|
Unicode. Store a pointer to the Unicode string in the
|
|
corresponding OutputParms member.
|
|
|
|
'N' (NetResource) - InputParms member is a LPNETRESOURCEA to be
|
|
converted to a NETRESOURCEW. The next character in Instructions
|
|
is a bitmask of the NETRESFIELD_ constants, indicating which
|
|
fields of the NETRESOURCEA to convert. Store a pointer to the
|
|
NETRESOURCEW in the corresponding OutputParms member.
|
|
|
|
'B' (Buffer) - InputParms member (say InputParms[i]) is a pointer to
|
|
an output buffer. InputParms[i+1] is a pointer to a DWORD
|
|
indicating the buffer size in bytes. Probe the buffer for write.
|
|
Allocate an area of double the size (i.e. of size
|
|
(*InputParms[i+1])*sizeof(WCHAR)) in the intermediate buffer.
|
|
Store a pointer to this area of the buffer in OutputParms[i].
|
|
Store the size of this area in OutputParms[i+1].
|
|
|
|
If InputParms[i] is NULL, store NULL in OutputParms[i], and
|
|
ignore InputParms[i+1]. (In other words, the buffer pointer
|
|
is optional; the size pointer is optional only if the buffer
|
|
pointer is present.)
|
|
|
|
InputParms - An array of parameters to the Ansi API, described by the
|
|
Instructions parameter.
|
|
|
|
OutputParms - An array of the same size as InputParms, to hold the
|
|
converted Unicode parameters.
|
|
|
|
ppBuffer - A pointer to the intermediate buffer allocated by this
|
|
function will be stored here. It must be freed by a single call
|
|
to LocalFree, regardless of the return value from this function.
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS
|
|
|
|
WN_OUT_OF_MEMORY
|
|
|
|
WN_BAD_POINTER
|
|
|
|
History:
|
|
|
|
16-Feb-1996 anirudhs Created.
|
|
|
|
Notes:
|
|
|
|
The function works by making two passes through the Instructions string.
|
|
In the first pass the string lengths are determined and saved, and the
|
|
required size of the temporary buffer is calculated. In the second
|
|
pass the parameters are actually converted to Unicode.
|
|
|
|
--*/
|
|
{
|
|
ANSI_STRING AnsiStrings [MAX_STRINGS_PER_API];
|
|
UNICODE_STRING UnicodeStrings[MAX_STRINGS_PER_API];
|
|
ULONG Bytes = 0; // Size of buffer to allocate
|
|
DWORD status = WN_SUCCESS;
|
|
|
|
//
|
|
// The caller must have initialized the buffer pointer to NULL, so
|
|
// he can free the buffer even if this function fails.
|
|
//
|
|
ASSERT(*ppBuffer == NULL);
|
|
|
|
__try
|
|
{
|
|
//
|
|
// For two passes through Instructions
|
|
//
|
|
#define FIRST_PASS (iPass == 0)
|
|
for (ULONG iPass = 0; iPass <= 1; iPass++)
|
|
{
|
|
ULONG iString = 0; // Index into AnsiStrings and UnicodeStrings
|
|
|
|
//
|
|
// For each character in Instructions
|
|
//
|
|
const CHAR * pInstruction; // Pointer into Instructions
|
|
ULONG iParm; // Index into InputParms and OutputParms
|
|
for (pInstruction = Instructions, iParm = 0;
|
|
*pInstruction;
|
|
pInstruction++, iParm++)
|
|
{
|
|
MPR_LOG(ANSI, "Processing instruction '%hc'\n", *pInstruction);
|
|
|
|
switch (*pInstruction)
|
|
{
|
|
case 'B':
|
|
//
|
|
// The next 2 InputParms are a buffer pointer and size.
|
|
// Note that this code could cause an exception.
|
|
//
|
|
if (InputParms[iParm].lpvoid == NULL)
|
|
{
|
|
OutputParms[iParm].lpbyte = NULL;
|
|
iParm++;
|
|
break;
|
|
}
|
|
|
|
if (FIRST_PASS)
|
|
{
|
|
// Probe the original buffer
|
|
if (IS_BAD_BYTE_BUFFER(InputParms[iParm].lpvoid,
|
|
InputParms[iParm+1].lpdword))
|
|
{
|
|
status = WN_BAD_POINTER;
|
|
__leave;
|
|
}
|
|
|
|
// Reserve the intermediate buffer area
|
|
Bytes = ROUND_UP_TO_DWORD(Bytes);
|
|
OutputParms[iParm].dword = Bytes;
|
|
OutputParms[iParm+1].dword =
|
|
(*InputParms[iParm+1].lpdword) * sizeof(WCHAR);
|
|
Bytes += OutputParms[iParm+1].dword;
|
|
}
|
|
else
|
|
{
|
|
// Convert the offset to a pointer
|
|
OutputParms[iParm].lpbyte =
|
|
*ppBuffer + OutputParms[iParm].dword;
|
|
ASSERT(IS_DWORD_ALIGNED(OutputParms[iParm].lpbyte));
|
|
}
|
|
|
|
iParm++;
|
|
break;
|
|
|
|
case 'S':
|
|
//
|
|
// InputParm is a string to be converted.
|
|
// A NULL string stays NULL.
|
|
//
|
|
if (FIRST_PASS)
|
|
{
|
|
ASSERT(iString < MAX_STRINGS_PER_API);
|
|
Bytes = ROUND_UP_TO_WCHAR(Bytes);
|
|
status = StringParmToUnicodePass1(
|
|
InputParms[iParm].lpcstr,
|
|
&AnsiStrings[iString],
|
|
&UnicodeStrings[iString],
|
|
&Bytes);
|
|
}
|
|
else
|
|
{
|
|
status = StringParmToUnicodePass2(
|
|
&AnsiStrings[iString],
|
|
&UnicodeStrings[iString],
|
|
*ppBuffer,
|
|
&OutputParms[iParm].lpwstr);
|
|
}
|
|
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
iString++;
|
|
break;
|
|
|
|
case 'N':
|
|
//
|
|
// InputParm is a NETRESOURCEA to be converted, and the
|
|
// next character in Instructions tells which of its string
|
|
// fields are to be converted.
|
|
// NULL strings remain NULL; ignored fields are copied
|
|
// unchanged.
|
|
//
|
|
|
|
pInstruction++;
|
|
|
|
if (InputParms[iParm].lpNetResA == NULL)
|
|
{
|
|
// A null netresource stays null
|
|
OutputParms[iParm].lpNetResW = NULL;
|
|
break;
|
|
}
|
|
|
|
{
|
|
// First deal with the fixed-size part of the structure.
|
|
const NETRESOURCEA *pNetResA =
|
|
InputParms[iParm].lpNetResA;
|
|
NETRESOURCEW *pNetResW;
|
|
|
|
if (FIRST_PASS)
|
|
{
|
|
// Reserve space for the NETRESOURCEW
|
|
Bytes = ROUND_UP_TO_DWORD(Bytes);
|
|
OutputParms[iParm].dword = Bytes;
|
|
Bytes += sizeof(NETRESOURCEW);
|
|
ASSERT(IS_WCHAR_ALIGNED(Bytes));
|
|
}
|
|
else
|
|
{
|
|
// Copy fixed-size fields and NULL pointers
|
|
pNetResW = (NETRESOURCEW *)
|
|
(*ppBuffer + OutputParms[iParm].dword);
|
|
ASSERT(IS_DWORD_ALIGNED(pNetResW));
|
|
RtlCopyMemory(pNetResW, pNetResA, sizeof(NETRESOURCEA));
|
|
|
|
OutputParms[iParm].lpNetResW = pNetResW;
|
|
}
|
|
|
|
// Next add each non-null string specified in the
|
|
// field mask.
|
|
CHAR FieldMask = *pInstruction;
|
|
ASSERT(FieldMask != 0);
|
|
|
|
for (ULONG iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if ((FieldMask >> iField) & 1)
|
|
{
|
|
if (FIRST_PASS)
|
|
{
|
|
ASSERT(iString < MAX_STRINGS_PER_API);
|
|
status = StringParmToUnicodePass1(
|
|
* pSTRING_FIELDA(pNetResA, iField),
|
|
&AnsiStrings[iString],
|
|
&UnicodeStrings[iString],
|
|
&Bytes);
|
|
}
|
|
else
|
|
{
|
|
status = StringParmToUnicodePass2(
|
|
&AnsiStrings[iString],
|
|
&UnicodeStrings[iString],
|
|
*ppBuffer,
|
|
pSTRING_FIELDW(pNetResW, iField));
|
|
}
|
|
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
__leave;
|
|
}
|
|
|
|
iString++;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
if (FIRST_PASS)
|
|
{
|
|
//
|
|
// Actually allocate the space for the Unicode parameters
|
|
//
|
|
*ppBuffer = (LPBYTE) LocalAlloc(0, Bytes);
|
|
if (*ppBuffer == NULL)
|
|
{
|
|
status = GetLastError();
|
|
MPR_LOG2(ERROR,
|
|
"InputParmsToUnicode: LocalAlloc for %lu bytes failed, %lu\n",
|
|
Bytes, status);
|
|
__leave;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
#if DBG == 1
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION)
|
|
{
|
|
MPR_LOG(ERROR,"InputParmsToUnicode: Unexpected Exception %#lx\n",status);
|
|
}
|
|
#endif
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
StringParmToUnicodePass1 (
|
|
IN LPCSTR StringParm,
|
|
OUT PANSI_STRING AnsiString,
|
|
OUT PUNICODE_STRING UnicodeString,
|
|
IN OUT PULONG BufferOffset
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function for InputParmsToUnicode.
|
|
|
|
--*/
|
|
{
|
|
RtlInitAnsiString( AnsiString, StringParm );
|
|
|
|
if (StringParm == NULL)
|
|
{
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
// Save the offset to the memory for this Unicode string, to be converted
|
|
// to a pointer after the memory is allocated
|
|
ULONG UnicodeLength = RtlAnsiStringToUnicodeSize( AnsiString );
|
|
if (UnicodeLength > MAXUSHORT)
|
|
{
|
|
MPR_LOG(ERROR,
|
|
"Unicode size of Ansi string parm is %lu, exceeds MAXUSHORT\n",
|
|
UnicodeLength);
|
|
return WN_BAD_VALUE;
|
|
}
|
|
UnicodeString->Buffer = (LPWSTR) (*BufferOffset);
|
|
UnicodeString->MaximumLength = (USHORT) UnicodeLength;
|
|
|
|
*BufferOffset = ROUND_UP_TO_DWORD(*BufferOffset + UnicodeLength);
|
|
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
|
|
DWORD
|
|
StringParmToUnicodePass2 (
|
|
IN OUT PANSI_STRING AnsiString,
|
|
OUT PUNICODE_STRING UnicodeString,
|
|
IN const BYTE * BufferStart,
|
|
OUT LPWSTR * Result
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function for InputParmsToUnicode.
|
|
|
|
--*/
|
|
{
|
|
if (AnsiString->Buffer == NULL)
|
|
{
|
|
*Result = NULL;
|
|
// NOTE: the UnicodeString is not initialized in this case
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
// Convert the previously stored buffer offset into a pointer
|
|
UnicodeString->Buffer = (LPWSTR)
|
|
(BufferStart + (ULONG) UnicodeString->Buffer);
|
|
ASSERT(IS_WCHAR_ALIGNED(UnicodeString->Buffer));
|
|
|
|
// Convert the string to Unicode
|
|
NTSTATUS ntstatus =
|
|
RtlAnsiStringToUnicodeString(UnicodeString, AnsiString, FALSE);
|
|
if (!NT_SUCCESS(ntstatus))
|
|
{
|
|
MPR_LOG(ERROR, "RtlAnsiStringToUnicodeString failed %#lx\n", ntstatus);
|
|
return RtlNtStatusToDosError(ntstatus);
|
|
}
|
|
*Result = UnicodeString->Buffer;
|
|
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
OutputBufferToAnsi(
|
|
IN char BufferFormat,
|
|
IN LPBYTE SourceBuffer,
|
|
OUT LPVOID AnsiBuffer,
|
|
IN OUT LPDWORD pcbBufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts the data in the result buffer that was returned
|
|
from a Unicode API into Ansi and stores it in the Ansi caller's result
|
|
buffer. If the caller's buffer isn't large enough it saves the required
|
|
size in *pcbBufferSize and returns WN_MORE_DATA.
|
|
|
|
Nearly all the WNet APIs that have output buffers have only a single
|
|
field in the output buffer, so this API takes only a single character,
|
|
rather than a string, for the buffer format. APIs with more complicated
|
|
output buffers should handle the complexity themselves, by directly
|
|
calling the functions that this function calls.
|
|
|
|
Arguments:
|
|
|
|
BufferFormat - A character indicating the format of the SourceBuffer
|
|
field. Recognized values are:
|
|
|
|
'S' - SourceBuffer contains a Unicode string. Convert it to Ansi
|
|
and store the Ansi version in AnsiBuffer.
|
|
|
|
'N' - SourceBuffer contains a NETRESOURCEW with its associated
|
|
strings. Convert it to Ansi and store the Ansi version in
|
|
AnsiBuffer.
|
|
|
|
SourceBuffer - The output buffer returned from a Unicode API.
|
|
This must not be NULL.
|
|
|
|
AnsiBuffer - The output buffer that the caller of the Ansi API supplied.
|
|
This must not be NULL.
|
|
|
|
pcbBufferSize - On entry, the size of AnsiBuffer in bytes. If the
|
|
function returns WN_MORE_DATA, the required size is stored here;
|
|
otherwise this is unmodified.
|
|
This must not be NULL (must be a writeable DWORD pointer).
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS - successful.
|
|
|
|
WN_MORE_DATA - The buffer specified by AnsiBuffer and pcbBufferSize was
|
|
not large enough to hold the converted data from SourceBuffer. In
|
|
this case the required buffer size (in bytes) is written to
|
|
*pcbBufferSize. The contents of AnsiBuffer are undefined (it will
|
|
be partially filled).
|
|
|
|
History:
|
|
|
|
16-Feb-1996 anirudhs Created.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
// Doesn't handle optional parameters for now
|
|
ASSERT(SourceBuffer != NULL &&
|
|
AnsiBuffer != NULL &&
|
|
pcbBufferSize != NULL);
|
|
|
|
ANSI_OUT_BUFFER Buf((LPBYTE) AnsiBuffer, *pcbBufferSize);
|
|
DWORD status;
|
|
|
|
switch (BufferFormat)
|
|
{
|
|
case 'S':
|
|
status = OutputStringToAnsi((LPCWSTR) SourceBuffer, &Buf);
|
|
break;
|
|
|
|
case 'N':
|
|
status = OutputNetResourceToAnsi((NETRESOURCEW *) SourceBuffer, &Buf);
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
|
|
//
|
|
// Map the results to the conventions followed by the WNet APIs
|
|
//
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
if (Buf.Overflow())
|
|
{
|
|
*pcbBufferSize = Buf.GetUsage();
|
|
status = WN_MORE_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(status != WN_MORE_DATA);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
OutputStringToAnsi(
|
|
IN LPCWSTR UnicodeIn,
|
|
IN OUT ANSI_OUT_BUFFER * Buf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts a Unicode string to Ansi and calculates the number
|
|
of bytes required to store it. If the caller passes a buffer that has
|
|
enough remaining free space, it stores the Ansi data in the buffer.
|
|
Otherwise it just increments the buffer's space usage by the number of
|
|
bytes required.
|
|
|
|
Arguments:
|
|
|
|
UnicodeIn - A Unicode string to be converted to Ansi.
|
|
This must not be NULL.
|
|
|
|
Buf - A structure whose elements are interpreted as follows:
|
|
|
|
_Start - Start address of a buffer to contain the Ansi data.
|
|
This buffer must be writeable, or an exception will occur.
|
|
|
|
_Size - The total size of the buffer for the Ansi data.
|
|
|
|
_Used - On entry, the number of bytes in the buffer that have
|
|
already been used. The function will begin writing data at
|
|
_Start + _Used and will never write past the total size
|
|
specified by _Size. If there is not enough room left
|
|
in the buffer it will be partially filled or unmodified.
|
|
On a successful return, _Used is incremented by the number
|
|
of bytes that would be required to store the converted Ansi
|
|
data, whether or not it was actually stored in the buffer.
|
|
(This is done because the WNet APIs need to return the
|
|
required buffer size if the caller's buffer was too small.)
|
|
|
|
The use of this structure simplifies the writing of routines that
|
|
use this function and need to convert multiple fields of Unicode
|
|
data. Callers that need to convert only a single field can use
|
|
OutputBufferToAnsi.
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS - successful. The Ansi data was written to the buffer if
|
|
Buf->_Used <= Buf->_Size. Otherwise, Buf->_Used was incremented
|
|
without completely writing the data.
|
|
|
|
Note that WN_MORE_DATA is never returned.
|
|
|
|
History:
|
|
|
|
16-Feb-1996 anirudhs Created.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS ntStatus;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
|
|
ASSERT(UnicodeIn != NULL); // Doesn't handle optional parameters for now
|
|
|
|
//
|
|
// Initialize the string structures
|
|
//
|
|
RtlInitUnicodeString(&unicodeString, UnicodeIn);
|
|
|
|
ansiString.Buffer = (PCHAR) Buf->Next();
|
|
ansiString.MaximumLength = (Buf->FreeSpace() > MAXUSHORT ?
|
|
MAXUSHORT :
|
|
(USHORT) Buf->FreeSpace()
|
|
);
|
|
|
|
//
|
|
// Call the conversion function
|
|
//
|
|
ntStatus = RtlUnicodeStringToAnsiString (
|
|
&ansiString, // Destination
|
|
&unicodeString, // Source
|
|
(BOOLEAN)FALSE); // Don't allocate the destination
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
// Add on the buffer space we used
|
|
Buf->AddUsed(ansiString.Length + 1);
|
|
ASSERT(! Buf->Overflow());
|
|
return WN_SUCCESS;
|
|
}
|
|
else if (ntStatus == STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
// We couldn't fit the string in the buffer, but still figure out
|
|
// how much buffer space we would have used if we could
|
|
Buf->AddUsed(RtlUnicodeStringToAnsiSize(&unicodeString));
|
|
ASSERT(Buf->Overflow());
|
|
return WN_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
MPR_LOG(ERROR, "RtlUnicodeStringToAnsiString failed %#lx\n", ntStatus);
|
|
DWORD status = RtlNtStatusToDosError(ntStatus);
|
|
ASSERT(status != WN_MORE_DATA);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
OutputNetResourceToAnsi(
|
|
IN NETRESOURCEW * lpNetResW,
|
|
IN OUT ANSI_OUT_BUFFER * Buf
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts a NETRESOURCEW and its associated Unicode strings
|
|
to Ansi and returns the number of bytes required to store them. If the
|
|
caller passes a buffer that has enough remaining free space, it stores
|
|
the Ansi data in the buffer.
|
|
|
|
Arguments:
|
|
|
|
lpNetResW - A Unicode net resource to be converted to Ansi.
|
|
This must not be NULL.
|
|
|
|
Buf - same as OutputStringToAnsi.
|
|
|
|
Return Value:
|
|
|
|
Same as OutputStringToAnsi.
|
|
|
|
History:
|
|
|
|
16-Feb-1996 anirudhs Created.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Copy the fixed-size part of the structure, including NULL pointers,
|
|
// and/or add on the buffer space it would take
|
|
//
|
|
LPNETRESOURCEA lpNetResA = (LPNETRESOURCEA) Buf->Next();
|
|
if (Buf->HasRoomFor(sizeof(NETRESOURCEA)))
|
|
{
|
|
RtlCopyMemory(lpNetResA, lpNetResW, sizeof(NETRESOURCEA));
|
|
}
|
|
Buf->AddUsed(sizeof(NETRESOURCEA));
|
|
|
|
//
|
|
// Copy each non-NULL string field,
|
|
// and/or add on the buffer space it would take
|
|
//
|
|
for (DWORD iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if (* pSTRING_FIELDW(lpNetResW, iField) != NULL)
|
|
{
|
|
// Save a pointer to the Ansi string we are about to create
|
|
// in the Ansi net resource
|
|
* pSTRING_FIELDA(lpNetResA, iField) = (LPSTR) Buf->Next();
|
|
|
|
// Convert the string
|
|
DWORD status = OutputStringToAnsi(
|
|
* pSTRING_FIELDW(lpNetResW, iField),
|
|
Buf);
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
ASSERT(status != WN_MORE_DATA);
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetNetworkInformationA(
|
|
IN LPCSTR lpProvider,
|
|
IN OUT LPNETINFOSTRUCT lpNetInfoStruct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[1];
|
|
UNICODE_PARM UParm[1];
|
|
|
|
AParm[0].lpcstr = lpProvider;
|
|
|
|
status = InputParmsToUnicode("S", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetGetNetworkInformationW(UParm[0].lpwstr, lpNetInfoStruct);
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetProviderNameA(
|
|
IN DWORD dwNetType,
|
|
OUT LPSTR lpProviderName,
|
|
IN OUT LPDWORD lpBufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[2];
|
|
UNICODE_PARM UParm[2];
|
|
|
|
AParm[0].lpvoid = lpProviderName;
|
|
AParm[1].lpdword = lpBufferSize;
|
|
|
|
status = InputParmsToUnicode("B", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetGetProviderNameW(
|
|
dwNetType,
|
|
UParm[0].lpwstr,
|
|
lpBufferSize
|
|
);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = OutputBufferToAnsi(
|
|
'S', UParm[0].lpbyte, lpProviderName, lpBufferSize);
|
|
}
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WNetGetProviderTypeA(
|
|
IN LPCSTR lpProvider,
|
|
OUT LPDWORD lpdwNetType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[1];
|
|
UNICODE_PARM UParm[1];
|
|
|
|
AParm[0].lpcstr = lpProvider;
|
|
|
|
status = InputParmsToUnicode("S", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetGetProviderTypeW(
|
|
UParm[0].lpwstr,
|
|
lpdwNetType
|
|
);
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetAddConnectionA (
|
|
IN LPCSTR lpRemoteName,
|
|
IN LPCSTR lpPassword,
|
|
IN LPCSTR lpLocalName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpRemoteNameW = NULL;
|
|
LPTSTR lpPasswordW = NULL;
|
|
LPTSTR lpLocalNameW = NULL;
|
|
|
|
__try {
|
|
|
|
if(ARGUMENT_PRESENT(lpRemoteName)) {
|
|
status = ConvertToUnicode(&lpRemoteNameW, lpRemoteName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetAddConnectionA:ConvertToUnicodeFailed %d\n",status);
|
|
__leave;
|
|
}
|
|
}
|
|
if(ARGUMENT_PRESENT(lpPassword)) {
|
|
status = ConvertToUnicode(&lpPasswordW, lpPassword);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetAddConnectionA:ConvertToUnicodeFailed %d\n",status);
|
|
__leave;
|
|
}
|
|
}
|
|
if(ARGUMENT_PRESENT(lpLocalName)) {
|
|
status = ConvertToUnicode(&lpLocalNameW, lpLocalName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetAddConnectionA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetAddConnectionA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
status = WNetAddConnectionW(
|
|
lpRemoteNameW,
|
|
lpPasswordW,
|
|
lpLocalNameW);
|
|
|
|
CleanExit:
|
|
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
if(lpRemoteNameW != NULL) {
|
|
LocalFree(lpRemoteNameW);
|
|
}
|
|
if(lpPasswordW != NULL) {
|
|
MprClearString(lpPasswordW) ;
|
|
LocalFree(lpPasswordW);
|
|
}
|
|
if(lpLocalNameW != NULL) {
|
|
LocalFree(lpLocalNameW);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetAddConnection2A (
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
IN LPCSTR lpPassword,
|
|
IN LPCSTR lpUserName,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
return(WNetAddConnection3A(
|
|
NULL,
|
|
lpNetResource,
|
|
lpPassword,
|
|
lpUserName,
|
|
dwFlags));
|
|
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetAddConnection3A (
|
|
IN HWND hwndOwner,
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
IN LPCSTR lpPassword,
|
|
IN LPCSTR lpUserName,
|
|
IN DWORD dwFlags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
NETRESOURCEW netResourceW;
|
|
LPTSTR lpPasswordW = NULL;
|
|
LPTSTR lpUserNameW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Make a unicode version of the NetResource structure
|
|
//
|
|
status = MprMakeUnicodeNetRes(
|
|
lpNetResource,
|
|
&netResourceW,
|
|
NETRESFIELD_LOCALNAME |
|
|
NETRESFIELD_REMOTENAME |
|
|
NETRESFIELD_PROVIDER);
|
|
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG0(ERROR,"WNetAddConnection3A:MprMakeUnicodeNetRes Failed\n");
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if (ARGUMENT_PRESENT(lpPassword)) {
|
|
status = ConvertToUnicode(&lpPasswordW, lpPassword);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetAddConnection3A:ConvertToUnicodeFailed %d\n",status);
|
|
__leave;
|
|
}
|
|
}
|
|
if (ARGUMENT_PRESENT(lpUserName)) {
|
|
status = ConvertToUnicode(&lpUserNameW, lpUserName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetAddConnection3A:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetAddConnection3A:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetAddConnection3W(
|
|
hwndOwner,
|
|
&netResourceW,
|
|
lpPasswordW,
|
|
lpUserNameW,
|
|
dwFlags);
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
MprFreeNetResW(&netResourceW);
|
|
|
|
if(lpPasswordW != NULL) {
|
|
MprClearString(lpPasswordW) ;
|
|
LocalFree(lpPasswordW);
|
|
}
|
|
if(lpUserNameW != NULL) {
|
|
LocalFree(lpUserNameW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetUseConnectionA(
|
|
IN HWND hwndOwner,
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
IN LPCSTR lpUserID,
|
|
IN LPCSTR lpPassword,
|
|
IN DWORD dwFlags,
|
|
OUT LPSTR lpAccessName OPTIONAL,
|
|
IN OUT LPDWORD lpBufferSize OPTIONAL, // Optional only if lpAccessName absent
|
|
OUT LPDWORD lpResult
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[5];
|
|
UNICODE_PARM UParm[5];
|
|
|
|
AParm[0].lpNetResA = lpNetResource;
|
|
AParm[1].lpcstr = lpUserID;
|
|
AParm[2].lpcstr = lpPassword;
|
|
AParm[3].lpvoid = lpAccessName;
|
|
AParm[4].lpdword = lpBufferSize;
|
|
|
|
UParm[2].lpwstr = NULL;
|
|
|
|
status = InputParmsToUnicode("N" NETRES_LRP "SSB", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetUseConnectionW(
|
|
hwndOwner,
|
|
UParm[0].lpNetResW,
|
|
UParm[1].lpwstr,
|
|
UParm[2].lpwstr,
|
|
dwFlags,
|
|
UParm[3].lpwstr,
|
|
lpBufferSize,
|
|
lpResult
|
|
);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
if (ARGUMENT_PRESENT(lpAccessName))
|
|
{
|
|
//
|
|
// Note: At this point, we know that lpBufferSize is writeable.
|
|
//
|
|
status = OutputBufferToAnsi(
|
|
'S', UParm[3].lpbyte, lpAccessName, lpBufferSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
MprClearString(UParm[2].lpwstr);
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetCancelConnection2A (
|
|
IN LPCSTR lpName,
|
|
IN DWORD dwFlags,
|
|
IN BOOL fForce
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpNameW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpName)) {
|
|
status = ConvertToUnicode(&lpNameW, lpName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetCancelConnectionA:ConvertToUnicodeFailed %d\n",1);
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetCancelConnectionA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetCancelConnection2W( lpNameW, dwFlags, fForce );
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpNameW != NULL) {
|
|
LocalFree(lpNameW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetCancelConnectionA (
|
|
IN LPCSTR lpName,
|
|
IN BOOL fForce
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is provided for Win 3.1 compatability.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
return WNetCancelConnection2A( lpName, CONNECT_UPDATE_PROFILE, fForce ) ;
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetGetConnectionA (
|
|
IN LPCSTR lpLocalName,
|
|
OUT LPSTR lpRemoteName,
|
|
IN OUT LPDWORD lpnLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the RemoteName that is associated with a
|
|
LocalName (or driver letter).
|
|
|
|
Arguments:
|
|
|
|
lpLocalName - This is a pointer to the string that contains the LocalName.
|
|
|
|
lpRemoteName - This is a pointer to the buffer that will contain the
|
|
RemoteName string upon exit.
|
|
|
|
lpnLength - This is a pointer to the size (in characters) of the buffer
|
|
that is to be filled in with the RemoteName string. It is assumed
|
|
upon entry, that characters are all single byte characters.
|
|
If the buffer is too small and WN_MORE_DATA is returned, the data
|
|
at this location contains buffer size information - in number of
|
|
characters (bytes). This information indicates how large the buffer
|
|
should be (in bytes) to obtain the remote name. It is assumed that
|
|
all Unicode characteres translate into DBCS characters.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
DWORD tempStatus = WN_SUCCESS;
|
|
LPTSTR lpLocalNameW = NULL;
|
|
DWORD numChars = 0;
|
|
LPSTR tempBuffer=NULL;
|
|
DWORD numBytes = 0;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpLocalName)) {
|
|
status = ConvertToUnicode(&lpLocalNameW, lpLocalName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetConnectionA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
//
|
|
// Probe the return buffer
|
|
//
|
|
if (*lpnLength > 0){
|
|
*lpRemoteName = 0;
|
|
*(lpRemoteName + ((*lpnLength)-1)) = 0;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetConnectionA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Because of DBCS, we can't predict what the proper buffer size should
|
|
// be. So we allocate a temporary buffer that will hold as many
|
|
// unicode characters as the original buffer would hold single byte
|
|
// characters.
|
|
//
|
|
numChars = *lpnLength;
|
|
|
|
numBytes = (*lpnLength) * sizeof(TCHAR);
|
|
|
|
tempBuffer = (LPSTR)LocalAlloc(LMEM_FIXED, numBytes);
|
|
if (tempBuffer == NULL) {
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetGetConnectionW(
|
|
lpLocalNameW,
|
|
(LPWSTR)tempBuffer,
|
|
&numChars);
|
|
|
|
if (status == WN_SUCCESS || status == WN_CONNECTION_CLOSED) {
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
tempStatus = ConvertToAnsi(tempBuffer, (LPWSTR)tempBuffer);
|
|
if (tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetConnectionA: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
}
|
|
else {
|
|
numBytes = strlen(tempBuffer)+1;
|
|
if (numBytes > *lpnLength) {
|
|
status = WN_MORE_DATA;
|
|
*lpnLength = numBytes;
|
|
}
|
|
else {
|
|
strcpy (lpRemoteName, tempBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
else if (status == WN_MORE_DATA) {
|
|
//
|
|
// Adjust the required buffer size for ansi/DBCS.
|
|
//
|
|
// We don't know how many characters will be required so we have to
|
|
// assume the worst case (all characters are DBCS characters).
|
|
//
|
|
*lpnLength = numChars * sizeof(TCHAR);
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpLocalNameW != NULL) {
|
|
LocalFree(lpLocalNameW);
|
|
}
|
|
if (tempBuffer != NULL) {
|
|
LocalFree(tempBuffer);
|
|
}
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetGetConnection2A (
|
|
IN LPSTR lpLocalName,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpnLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns the RemoteName that is associated with a
|
|
LocalName (or driver letter) and the provider name that made the
|
|
connection.
|
|
|
|
Arguments:
|
|
|
|
lpLocalName - This is a pointer to the string that contains the LocalName.
|
|
|
|
lpBuffer - This is a pointer to the buffer that will contain the
|
|
WNET_CONNECTIONINFO structure upon exit.
|
|
|
|
lpnLength - This is a pointer to the size (in characters) of the buffer
|
|
that is to be filled in with the RemoteName string. It is assumed
|
|
upon entry, that characters are all single byte characters.
|
|
If the buffer is too small and WN_MORE_DATA is returned, the data
|
|
at this location contains buffer size information - in number of
|
|
characters (bytes). This information indicates how large the buffer
|
|
should be (in bytes) to obtain the remote name. It is assumed that
|
|
all Unicode characteres translate into DBCS characters.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
DWORD tempStatus = WN_SUCCESS;
|
|
LPTSTR lpLocalNameW = NULL;
|
|
LPSTR tempBuffer=NULL;
|
|
DWORD numBytes = 0;
|
|
WNET_CONNECTIONINFOA * pconninfoa ;
|
|
WNET_CONNECTIONINFOW * pconninfow ;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpLocalName)) {
|
|
status = ConvertToUnicode(&lpLocalNameW, lpLocalName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetConnection2A:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
//
|
|
// Probe the return buffer
|
|
//
|
|
if (*lpnLength > 0){
|
|
*((BYTE*)lpBuffer) = 0;
|
|
*((BYTE*)lpBuffer + ((*lpnLength)-1)) = 0;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetConnection2A:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
numBytes = (*lpnLength) * sizeof(TCHAR);
|
|
|
|
tempBuffer = (LPSTR)LocalAlloc(LMEM_FIXED, numBytes);
|
|
if (tempBuffer == NULL) {
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetGetConnection2W(
|
|
lpLocalNameW,
|
|
(LPVOID)tempBuffer,
|
|
&numBytes );
|
|
|
|
if (status == WN_SUCCESS || status == WN_CONNECTION_CLOSED) {
|
|
pconninfow = (WNET_CONNECTIONINFOW*) tempBuffer ;
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pconninfow->lpRemoteName,
|
|
pconninfow->lpRemoteName);
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetConnection2A: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pconninfow->lpProvider,
|
|
pconninfow->lpProvider);
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetConnection2A: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
|
|
numBytes = strlen((LPSTR)pconninfow->lpRemoteName ) +
|
|
strlen((LPSTR)pconninfow->lpProvider ) + 2 +
|
|
sizeof(WNET_CONNECTIONINFOA);
|
|
|
|
if (numBytes > *lpnLength) {
|
|
status = WN_MORE_DATA;
|
|
*lpnLength = numBytes;
|
|
}
|
|
else {
|
|
pconninfoa = (WNET_CONNECTIONINFOA*) lpBuffer ;
|
|
|
|
pconninfoa->lpRemoteName = strcpy((LPSTR) ((BYTE*) lpBuffer +
|
|
sizeof(WNET_CONNECTIONINFO)),
|
|
(LPSTR)pconninfow->lpRemoteName ) ;
|
|
pconninfoa->lpProvider = strcpy( (LPSTR) ((BYTE*) lpBuffer +
|
|
sizeof(WNET_CONNECTIONINFO) +
|
|
strlen( pconninfoa->lpRemoteName) +
|
|
sizeof( CHAR )),
|
|
(LPSTR)pconninfow->lpProvider ) ;
|
|
}
|
|
}
|
|
else if (status == WN_MORE_DATA) {
|
|
//
|
|
// Adjust the required buffer size for ansi/DBCS.
|
|
//
|
|
// We don't know how many characters will be required so we have to
|
|
// assume the worst case (all characters are DBCS characters).
|
|
//
|
|
*lpnLength = numBytes ;
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpLocalNameW != NULL) {
|
|
LocalFree(lpLocalNameW);
|
|
}
|
|
if (tempBuffer != NULL) {
|
|
LocalFree(tempBuffer);
|
|
}
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetConnection3A(
|
|
IN LPCSTR lpLocalName,
|
|
IN LPCSTR lpProviderName OPTIONAL,
|
|
IN DWORD dwLevel,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpBufferSize // in bytes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[2];
|
|
UNICODE_PARM UParm[2];
|
|
|
|
// For level 1, the output buffer is a DWORD, so no conversion is necessary
|
|
AParm[0].lpcstr = lpLocalName;
|
|
AParm[1].lpcstr = lpProviderName;
|
|
|
|
status = InputParmsToUnicode("SS", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetGetConnection3W(
|
|
UParm[0].lpwstr,
|
|
UParm[1].lpwstr,
|
|
dwLevel,
|
|
lpBuffer,
|
|
lpBufferSize
|
|
);
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
WNetGetUniversalNameA (
|
|
IN LPCSTR lpLocalPath,
|
|
IN DWORD dwInfoLevel,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpBufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
DWORD tempStatus = WN_SUCCESS;
|
|
LPTSTR lpLocalPathW = NULL;
|
|
LPSTR tempBuffer=NULL;
|
|
DWORD numBytes = 0;
|
|
LPSTR pTempPtr;
|
|
|
|
LPREMOTE_NAME_INFOW pRemoteNameInfoW;
|
|
LPREMOTE_NAME_INFOA pRemoteNameInfoA;
|
|
LPUNIVERSAL_NAME_INFOW pUniNameInfoW;
|
|
LPUNIVERSAL_NAME_INFOA pUniNameInfoA;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpLocalPath)) {
|
|
status = ConvertToUnicode(&lpLocalPathW, lpLocalPath);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUniversalNameA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
//
|
|
// Probe the return buffer
|
|
//
|
|
if (*lpBufferSize > 0){
|
|
*((BYTE*)lpBuffer) = 0;
|
|
*((BYTE*)lpBuffer + ((*lpBufferSize)-1)) = 0;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetUniversalNameA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
numBytes = (*lpBufferSize) * sizeof(TCHAR);
|
|
|
|
tempBuffer = (LPSTR)LocalAlloc(LMEM_FIXED, numBytes);
|
|
if (tempBuffer == NULL) {
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
|
|
//--------------------------------------------
|
|
// Call the Unicode version of the function.
|
|
//--------------------------------------------
|
|
|
|
status = WNetGetUniversalNameW(
|
|
(LPCTSTR)lpLocalPathW,
|
|
dwInfoLevel,
|
|
(LPVOID)tempBuffer,
|
|
&numBytes );
|
|
|
|
if (status == WN_SUCCESS || status == WN_CONNECTION_CLOSED) {
|
|
|
|
if (dwInfoLevel == REMOTE_NAME_INFO_LEVEL) {
|
|
// -----------------------------------
|
|
// REMOTE_NAME_INFO_LEVEL
|
|
// -----------------------------------
|
|
|
|
pRemoteNameInfoW = (LPREMOTE_NAME_INFOW) tempBuffer ;
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
if (pRemoteNameInfoW->lpUniversalName != NULL) {
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pRemoteNameInfoW->lpUniversalName,
|
|
pRemoteNameInfoW->lpUniversalName);
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUniversalNameA: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
}
|
|
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pRemoteNameInfoW->lpConnectionName,
|
|
pRemoteNameInfoW->lpConnectionName);
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUniversalNameA: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pRemoteNameInfoW->lpRemainingPath,
|
|
pRemoteNameInfoW->lpRemainingPath);
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUniversalNameA: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
|
|
numBytes = strlen((LPSTR)pRemoteNameInfoW->lpConnectionName ) +
|
|
strlen((LPSTR)pRemoteNameInfoW->lpRemainingPath ) +
|
|
(3*sizeof(CHAR)) +
|
|
sizeof(REMOTE_NAME_INFOA);
|
|
|
|
if (pRemoteNameInfoW->lpUniversalName != NULL) {
|
|
numBytes += strlen((LPSTR)pRemoteNameInfoW->lpUniversalName);
|
|
}
|
|
|
|
if (numBytes > *lpBufferSize) {
|
|
status = WN_MORE_DATA;
|
|
*lpBufferSize = numBytes;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Copy the strings from the temp buffer into the caller's buffer
|
|
// and update the structure in the caller's buffer.
|
|
//
|
|
|
|
pRemoteNameInfoA = (LPREMOTE_NAME_INFOA) lpBuffer;
|
|
|
|
pTempPtr = (LPSTR) ((LPBYTE) lpBuffer + sizeof(REMOTE_NAME_INFOA));
|
|
|
|
if (pRemoteNameInfoW->lpUniversalName != NULL) {
|
|
pRemoteNameInfoA->lpUniversalName = strcpy(pTempPtr,
|
|
(LPSTR)pRemoteNameInfoW->lpUniversalName ) ;
|
|
|
|
pTempPtr = pTempPtr + strlen(pRemoteNameInfoA->lpUniversalName) +
|
|
sizeof(CHAR);
|
|
}
|
|
else {
|
|
pRemoteNameInfoA->lpUniversalName = NULL;
|
|
}
|
|
|
|
pRemoteNameInfoA->lpConnectionName = strcpy( pTempPtr,
|
|
(LPSTR)pRemoteNameInfoW->lpConnectionName ) ;
|
|
|
|
pTempPtr = pTempPtr + strlen(pRemoteNameInfoA->lpConnectionName) +
|
|
sizeof(CHAR);
|
|
|
|
pRemoteNameInfoA->lpRemainingPath = strcpy( pTempPtr,
|
|
(LPSTR)pRemoteNameInfoW->lpRemainingPath ) ;
|
|
}
|
|
}
|
|
else {
|
|
// -----------------------------------
|
|
// Must be UNIVERSAL_NAME_INFO_LEVEL
|
|
// -----------------------------------
|
|
|
|
pUniNameInfoW = (LPUNIVERSAL_NAME_INFOW) tempBuffer ;
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
tempStatus = ConvertToAnsi(
|
|
(LPSTR)pUniNameInfoW->lpUniversalName,
|
|
pUniNameInfoW->lpUniversalName);
|
|
|
|
if(tempStatus != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUniversalNameA: ConvertToAnsi Failed %d\n",tempStatus);
|
|
status = tempStatus;
|
|
goto CleanExit;
|
|
}
|
|
|
|
numBytes = strlen((LPSTR)pUniNameInfoW->lpUniversalName ) + sizeof(CHAR) +
|
|
sizeof(UNIVERSAL_NAME_INFOA);
|
|
|
|
if (numBytes > *lpBufferSize) {
|
|
status = WN_MORE_DATA;
|
|
*lpBufferSize = numBytes;
|
|
}
|
|
else {
|
|
//
|
|
// Copy the strings from the temp buffer into the caller's buffer
|
|
// and update the structure in the caller's buffer.
|
|
//
|
|
pUniNameInfoA = (LPUNIVERSAL_NAME_INFOA) lpBuffer ;
|
|
|
|
pTempPtr = (LPSTR) ((LPBYTE) lpBuffer + sizeof(UNIVERSAL_NAME_INFOA));
|
|
|
|
pUniNameInfoA->lpUniversalName = strcpy(pTempPtr,
|
|
(LPSTR)pUniNameInfoW->lpUniversalName ) ;
|
|
}
|
|
}
|
|
}
|
|
else if (status == WN_MORE_DATA) {
|
|
//
|
|
// Adjust the required buffer size for ansi/DBCS.
|
|
//
|
|
// We don't know how many characters will be required so we have to
|
|
// assume the worst case (all characters are DBCS characters).
|
|
//
|
|
*lpBufferSize = numBytes ;
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpLocalPathW != NULL) {
|
|
LocalFree(lpLocalPathW);
|
|
}
|
|
if (tempBuffer != NULL) {
|
|
LocalFree(tempBuffer);
|
|
}
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetSetConnectionA(
|
|
IN LPCSTR lpName,
|
|
IN DWORD dwProperties,
|
|
IN LPVOID pvValues
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[1];
|
|
UNICODE_PARM UParm[1];
|
|
|
|
//
|
|
// pvValues points to various types of structures depending on the value
|
|
// of dwProperties.
|
|
// Currently there is only one valid value for dwProperties, and its
|
|
// corresponding pvValues points to a DWORD, so we don't need to worry
|
|
// about converting pvValues to Unicode.
|
|
//
|
|
AParm[0].lpcstr = lpName;
|
|
|
|
status = InputParmsToUnicode("S", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetSetConnectionW(UParm[0].lpwstr, dwProperties, pvValues);
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
MultinetGetConnectionPerformanceA(
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
OUT LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[1];
|
|
UNICODE_PARM UParm[1];
|
|
|
|
AParm[0].lpNetResA = lpNetResource;
|
|
|
|
status = InputParmsToUnicode("N" NETRES_LRP, AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = MultinetGetConnectionPerformanceW(
|
|
UParm[0].lpNetResW,
|
|
lpNetConnectInfoStruct);
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetOpenEnumA (
|
|
IN DWORD dwScope,
|
|
IN DWORD dwType,
|
|
IN DWORD dwUsage,
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
OUT LPHANDLE lphEnum
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPNETRESOURCEW lpNetResourceW = NULL;
|
|
NETRESOURCEW netResourceW;
|
|
|
|
__try {
|
|
|
|
if (lpNetResource != NULL) {
|
|
//
|
|
// Make a unicode version of the NetResource structure
|
|
//
|
|
status = MprMakeUnicodeNetRes(
|
|
lpNetResource,
|
|
&netResourceW,
|
|
NETRESFIELD_PROVIDER | NETRESFIELD_REMOTENAME);
|
|
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG(ERROR,"WNetOpenEnumA:MprMakeUnicodeNetRes Failed\n",0);
|
|
status = WN_OUT_OF_MEMORY;
|
|
}
|
|
else {
|
|
lpNetResourceW = &netResourceW;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Probe the handle location
|
|
//
|
|
*lphEnum = 0;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetOpenEnumA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetOpenEnumW(
|
|
dwScope,
|
|
dwType,
|
|
dwUsage,
|
|
lpNetResourceW,
|
|
lphEnum);
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
if (lpNetResource != NULL) {
|
|
MprFreeNetResW(lpNetResourceW);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetEnumResourceA (
|
|
IN HANDLE hEnum,
|
|
IN OUT LPDWORD lpcCount,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpBufferSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calls the unicode version of WNetEnumResource and
|
|
then converts the strings that are returned into ansi strings.
|
|
Since the user provided buffer is used to contain the unicode strings,
|
|
that buffer should be allocated with the size of unicode strings
|
|
in mind.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
DWORD status = WN_SUCCESS;
|
|
DWORD numConverted;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Probe the return buffer
|
|
//
|
|
if(*lpBufferSize > 0) {
|
|
*(LPBYTE)lpBuffer = 0;
|
|
*((LPBYTE)lpBuffer + (*lpBufferSize-1)) = 0;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetEnumResourceA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
return(status);
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetEnumResourceW(
|
|
hEnum,
|
|
lpcCount,
|
|
lpBuffer,
|
|
lpBufferSize);
|
|
|
|
if (status == WN_SUCCESS) {
|
|
|
|
numConverted = ResourceArrayToAnsi(
|
|
*lpcCount,
|
|
(LPNETRESOURCE)lpBuffer);
|
|
|
|
//
|
|
// If we weren't able to convert all the structures to ansi,
|
|
// then only return the count for those that were converted.
|
|
//
|
|
if(numConverted < *lpcCount) {
|
|
MPR_LOG0(ERROR,"WNetEnumResourceA: Couldn't convert all structs\n");
|
|
*lpcCount = numConverted;
|
|
}
|
|
}
|
|
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetResourceInformationA(
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpBufferSize,
|
|
OUT LPSTR * lplpSystem
|
|
)
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[3];
|
|
UNICODE_PARM UParm[3];
|
|
|
|
AParm[0].lpNetResA = lpNetResource;
|
|
AParm[1].lpvoid = lpBuffer;
|
|
AParm[2].lpdword = lpBufferSize;
|
|
|
|
status = InputParmsToUnicode("N" NETRES_RP "B", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
//
|
|
// The output buffer will contain a netresource followed by strings.
|
|
// We want to double the output buffer space for strings, but not for
|
|
// the netresource, since sizeof(NETRESOURCEW) == sizeof(NETRESOURCEA).
|
|
//
|
|
if (UParm[2].dword < sizeof(NETRESOURCE) * 2)
|
|
{
|
|
UParm[2].dword /= 2;
|
|
}
|
|
else
|
|
{
|
|
UParm[2].dword -= sizeof(NETRESOURCE);
|
|
}
|
|
|
|
status = WNetGetResourceInformationW(
|
|
UParm[0].lpNetResW,
|
|
UParm[1].lpbyte,
|
|
&UParm[2].dword,
|
|
(LPWSTR *) lplpSystem
|
|
);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
ANSI_OUT_BUFFER Buf((LPBYTE) lpBuffer, *lpBufferSize);
|
|
|
|
//
|
|
// Convert the Unicode netresource returned to Ansi
|
|
//
|
|
status = OutputNetResourceToAnsi(UParm[1].lpNetResW, &Buf);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
//
|
|
// Convert the Unicode string (*lplpSystem) returned to Ansi
|
|
//
|
|
LPWSTR lpSystemW = * (LPWSTR *) lplpSystem;
|
|
if (lpSystemW != NULL)
|
|
{
|
|
*lplpSystem = (LPSTR) Buf.Next();
|
|
status = OutputStringToAnsi(lpSystemW, &Buf);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Map the results to WNet API conventions
|
|
//
|
|
if (status == WN_SUCCESS && Buf.Overflow())
|
|
{
|
|
*lpBufferSize = Buf.GetUsage();
|
|
status = WN_MORE_DATA;
|
|
}
|
|
}
|
|
else if (status == WN_MORE_DATA)
|
|
{
|
|
//
|
|
// Adjust the required buffer size for ansi/DBCS.
|
|
//
|
|
// We don't know how many characters will be required so we have to
|
|
// assume the worst case (all characters are DBCS characters).
|
|
//
|
|
*lpBufferSize = UParm[2].dword;
|
|
}
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetResourceParentA(
|
|
IN LPNETRESOURCEA lpNetResource,
|
|
OUT LPVOID lpBuffer,
|
|
IN OUT LPDWORD lpBufferSize
|
|
)
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[3];
|
|
UNICODE_PARM UParm[3];
|
|
|
|
AParm[0].lpNetResA = lpNetResource;
|
|
AParm[1].lpvoid = lpBuffer;
|
|
AParm[2].lpdword = lpBufferSize;
|
|
|
|
status = InputParmsToUnicode("N" NETRES_RP "B", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
//
|
|
// The output buffer will contain a netresource followed by strings.
|
|
// We want to double the output buffer space for strings, but not for
|
|
// the netresource, since sizeof(NETRESOURCEW) == sizeof(NETRESOURCEA).
|
|
//
|
|
if (UParm[2].dword < sizeof(NETRESOURCE) * 2)
|
|
{
|
|
UParm[2].dword /= 2;
|
|
}
|
|
else
|
|
{
|
|
UParm[2].dword -= sizeof(NETRESOURCE);
|
|
}
|
|
|
|
status = WNetGetResourceParentW(
|
|
UParm[0].lpNetResW,
|
|
UParm[1].lpbyte,
|
|
&UParm[2].dword
|
|
);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
//
|
|
// Convert the Unicode netresource returned to Ansi
|
|
//
|
|
status = OutputBufferToAnsi('N', UParm[1].lpbyte, lpBuffer, lpBufferSize);
|
|
}
|
|
else if (status == WN_MORE_DATA)
|
|
{
|
|
//
|
|
// Adjust the required buffer size for ansi/DBCS.
|
|
//
|
|
// We don't know how many characters will be required so we have to
|
|
// assume the worst case (all characters are DBCS characters).
|
|
//
|
|
*lpBufferSize = UParm[2].dword;
|
|
}
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetGetUserA (
|
|
IN LPCSTR lpName,
|
|
OUT LPSTR lpUserName,
|
|
IN OUT LPDWORD lpnLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function retreives the current default user name or the username
|
|
used to establish a network connection.
|
|
|
|
Arguments:
|
|
|
|
lpName - Points to a null-terminated string that specifies either the
|
|
name or the local device to return the user name for, or a network
|
|
name that the user has made a connection to. If the pointer is
|
|
NULL, the name of the current user is returned.
|
|
|
|
lpUserName - Points to a buffer to receive the null-terminated
|
|
user name.
|
|
|
|
lpnLength - Specifies the size (in characters) of the buffer pointed
|
|
to by the lpUserName parameter. If the call fails because the
|
|
buffer is not big enough, this location is used to return the
|
|
required buffer size.
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpNameW = NULL;
|
|
DWORD numChars = 0;
|
|
LPSTR tempBuffer=NULL;
|
|
DWORD numBytes = 0;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpName)) {
|
|
status = ConvertToUnicode(&lpNameW, lpName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUserA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
//
|
|
// Probe the return buffer
|
|
//
|
|
if(*lpnLength > 0) {
|
|
*lpUserName = 0;
|
|
*(lpUserName + ((*lpnLength)-1)) = 0;
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetUserA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Because of DBCS, we can't predict what the proper buffer size should
|
|
// be. So we allocate a temporary buffer that will hold as many
|
|
// unicode characters as the original buffer would hold single byte
|
|
// characters.
|
|
//
|
|
numChars = *lpnLength;
|
|
|
|
numBytes = (*lpnLength) * sizeof(TCHAR);
|
|
|
|
tempBuffer = (LPSTR)LocalAlloc(LMEM_FIXED, numBytes);
|
|
if (tempBuffer == NULL) {
|
|
status = GetLastError();
|
|
goto CleanExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetGetUserW(
|
|
lpNameW,
|
|
(LPWSTR)tempBuffer,
|
|
&numChars);
|
|
|
|
if (status == WN_SUCCESS) {
|
|
//
|
|
// Convert the returned Unicode string and string size back to
|
|
// ansi.
|
|
//
|
|
status = ConvertToAnsi(tempBuffer, (LPWSTR)tempBuffer);
|
|
if(status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetUserA: ConvertToAnsi Failed %d\n",status);
|
|
}
|
|
else {
|
|
numBytes = strlen(tempBuffer)+1;
|
|
if (numBytes > *lpnLength) {
|
|
status = WN_MORE_DATA;
|
|
*lpnLength = numBytes;
|
|
}
|
|
else {
|
|
strcpy (lpUserName, tempBuffer);
|
|
}
|
|
}
|
|
}
|
|
else if (status == WN_MORE_DATA) {
|
|
//
|
|
// Adjust the required buffer size for ansi.
|
|
//
|
|
*lpnLength = numChars * sizeof(TCHAR);
|
|
}
|
|
|
|
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpNameW != NULL) {
|
|
LocalFree(lpNameW);
|
|
}
|
|
if (tempBuffer != NULL) {
|
|
LocalFree(tempBuffer);
|
|
}
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
RestoreConnectionA0 (
|
|
IN HWND hwnd,
|
|
IN LPSTR lpDevice
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpDeviceW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpDevice)) {
|
|
if(!ConvertToUnicode(&lpDeviceW, lpDevice)) {
|
|
MPR_LOG0(ERROR,"RestoreConnectionA0:ConvertToUnicodeFailed\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"RestoreConnectionA0:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetRestoreConnectionW(
|
|
hwnd,
|
|
lpDeviceW) ;
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpDeviceW != NULL) {
|
|
LocalFree(lpDeviceW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
WNetGetDirectoryTypeA (
|
|
IN LPSTR lpName,
|
|
OUT LPDWORD lpType,
|
|
IN BOOL bFlushCache
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpNameW = NULL;
|
|
INT iType; // WNetGetDirectoryTypeW wants an LPINT. BUGBUG -
|
|
// we should fix it to take an LPDWORD - this means
|
|
// fixing all users of mpr.h.
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpName)) {
|
|
status = ConvertToUnicode(&lpNameW, lpName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetDirectoryTypeA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Probe the OUT parameter
|
|
//
|
|
DWORD dwType = * (volatile LPDWORD) lpType;
|
|
* (volatile LPDWORD) lpType = dwType;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetDirectoryTypeA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetGetDirectoryTypeW(
|
|
lpNameW,
|
|
&iType,
|
|
bFlushCache);
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
*lpType = iType;
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpNameW != NULL) {
|
|
LocalFree(lpNameW);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
DWORD
|
|
WNetDirectoryNotifyA (
|
|
IN HWND hwnd,
|
|
IN LPSTR lpDir,
|
|
IN DWORD dwOper
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpDirW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpDir)) {
|
|
status = ConvertToUnicode(&lpDirW, lpDir);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetDirectoryNotifyA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetDirectoryNotifyA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetDirectoryNotifyW(
|
|
hwnd,
|
|
lpDirW,
|
|
dwOper);
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpDirW != NULL) {
|
|
LocalFree(lpDirW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
WNetGetLastErrorA (
|
|
OUT LPDWORD lpError,
|
|
OUT LPSTR lpErrorBuf,
|
|
IN DWORD nErrorBufSize,
|
|
OUT LPSTR lpNameBuf,
|
|
IN DWORD nNameBufSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Probe the return buffers
|
|
//
|
|
if (nErrorBufSize > 0) {
|
|
*lpErrorBuf = '\0';
|
|
*(lpErrorBuf + (nErrorBufSize-1)) = '\0';
|
|
}
|
|
|
|
if (nNameBufSize > 0) {
|
|
*lpNameBuf = '\0';
|
|
*(lpNameBuf + (nNameBufSize-1)) = '\0';
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetLastErrorA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
// Note: The sizes for the buffers that are passed in assume that
|
|
// the returned unicode strings will return DBCS characters.
|
|
//
|
|
status = WNetGetLastErrorW(
|
|
lpError,
|
|
(LPWSTR)lpErrorBuf,
|
|
(nErrorBufSize / sizeof(TCHAR)),
|
|
(LPWSTR)lpNameBuf,
|
|
(nNameBufSize / sizeof(TCHAR)));
|
|
|
|
if (status == WN_SUCCESS) {
|
|
//
|
|
// Convert the returned Unicode strings back to ansi.
|
|
//
|
|
if (nErrorBufSize > 0) {
|
|
status = ConvertToAnsi(lpErrorBuf, (LPWSTR)lpErrorBuf);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetLastErrorA: ConvertToAnsi Failed %d\n",status);
|
|
}
|
|
}
|
|
if (status == WN_SUCCESS) {
|
|
if (nNameBufSize > 0) {
|
|
status = ConvertToAnsi(lpNameBuf, (LPWSTR)lpNameBuf);
|
|
if(status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetLastErrorA: ConvertToAnsi Failed %d\n",status);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
WNetSetLastErrorA(
|
|
IN DWORD err,
|
|
IN LPSTR lpError,
|
|
IN LPSTR lpProviders
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status=WN_SUCCESS;
|
|
LPTSTR lpErrorW = NULL;
|
|
LPTSTR lpProvidersW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpError)) {
|
|
status = ConvertToUnicode(&lpErrorW, lpError);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetSetLastErrorA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
__leave;
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(lpProviders)) {
|
|
status = ConvertToUnicode(&lpProvidersW, lpProviders);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetSetLastProvidersA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetSetLastErrorA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
WNetSetLastErrorW (err, lpErrorW, lpProvidersW);
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpErrorW != NULL) {
|
|
LocalFree(lpErrorW);
|
|
}
|
|
if(lpProvidersW != NULL) {
|
|
LocalFree(lpProvidersW);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
MultinetGetErrorTextA(
|
|
OUT LPSTR lpErrorTextBuf OPTIONAL,
|
|
IN OUT LPDWORD lpnErrorBufSize OPTIONAL,
|
|
OUT LPSTR lpProviderNameBuf OPTIONAL,
|
|
IN OUT LPDWORD lpnNameBufSize OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[4];
|
|
UNICODE_PARM UParm[4];
|
|
|
|
AParm[0].lpvoid = lpErrorTextBuf;
|
|
AParm[1].lpdword = lpnErrorBufSize;
|
|
AParm[2].lpvoid = lpProviderNameBuf;
|
|
AParm[3].lpdword = lpnNameBufSize;
|
|
|
|
status = InputParmsToUnicode("BB", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
// Remember the sizes before calling the function
|
|
DWORD nErrorBufSize;
|
|
DWORD nNameBufSize;
|
|
if (ARGUMENT_PRESENT(lpErrorTextBuf))
|
|
{
|
|
nErrorBufSize = *lpnErrorBufSize;
|
|
}
|
|
if (ARGUMENT_PRESENT(lpProviderNameBuf))
|
|
{
|
|
nNameBufSize = *lpnNameBufSize;
|
|
}
|
|
|
|
status = MultinetGetErrorTextW(
|
|
UParm[0].lpwstr,
|
|
lpnErrorBufSize,
|
|
UParm[2].lpwstr,
|
|
lpnNameBufSize
|
|
);
|
|
|
|
if (status == WN_SUCCESS || status == WN_MORE_DATA)
|
|
{
|
|
if (ARGUMENT_PRESENT(lpErrorTextBuf) &&
|
|
nErrorBufSize == *lpnErrorBufSize)
|
|
{
|
|
// The Unicode API must have written the error text buffer
|
|
DWORD status2 = OutputBufferToAnsi(
|
|
'S',
|
|
UParm[0].lpbyte,
|
|
lpErrorTextBuf,
|
|
lpnErrorBufSize);
|
|
|
|
if (status2 != WN_SUCCESS)
|
|
{
|
|
status = status2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (status == WN_SUCCESS || status == WN_MORE_DATA)
|
|
{
|
|
if (ARGUMENT_PRESENT(lpProviderNameBuf) &&
|
|
nNameBufSize == *lpnNameBufSize)
|
|
{
|
|
// The Unicode API must have written the provider name buffer
|
|
DWORD status2 = OutputBufferToAnsi(
|
|
'S',
|
|
UParm[2].lpbyte,
|
|
lpProviderNameBuf,
|
|
lpnNameBufSize);
|
|
|
|
if (status2 != WN_SUCCESS)
|
|
{
|
|
status = status2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
WNetPropertyDialogA (
|
|
HWND hwndParent,
|
|
DWORD iButton,
|
|
DWORD nPropSel,
|
|
LPSTR lpszName,
|
|
DWORD nType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpNameW = NULL;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpszName)) {
|
|
status = ConvertToUnicode(&lpNameW, lpszName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetPropertyDialogA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetPropertyDialogA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
SetLastError(status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetPropertyDialogW(
|
|
hwndParent,
|
|
iButton,
|
|
nPropSel,
|
|
lpNameW,
|
|
nType ) ;
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpNameW != NULL) {
|
|
LocalFree(lpNameW);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WNetGetPropertyTextA (
|
|
DWORD iButton,
|
|
DWORD nPropSel,
|
|
LPSTR lpszName,
|
|
LPSTR lpszButtonName,
|
|
DWORD nButtonNameLen,
|
|
DWORD nType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD status = WN_SUCCESS;
|
|
LPTSTR lpNameW = NULL;
|
|
LPTSTR lpButtonNameW = NULL ;
|
|
DWORD buttonnameBufSizeW = 0 ;
|
|
|
|
__try {
|
|
|
|
//
|
|
// Probe the return buffers
|
|
//
|
|
|
|
if (nButtonNameLen > 0){
|
|
*lpszButtonName = 0;
|
|
*(lpszButtonName + (nButtonNameLen-1)) = 0;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetPropteryTextA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// If there is a return buffer, allocate a comparable size Unicode
|
|
// String Buffer. Otherwise, use the initialized lpButtonNameW - - NULL
|
|
// pointer.
|
|
//
|
|
if (nButtonNameLen > 0) {
|
|
|
|
buttonnameBufSizeW= (nButtonNameLen) * sizeof(TCHAR);
|
|
|
|
lpButtonNameW = (TCHAR *) LocalAlloc(LMEM_FIXED, buttonnameBufSizeW);
|
|
|
|
if(lpButtonNameW == NULL) {
|
|
status = GetLastError();
|
|
MPR_LOG1(ERROR,"WNetGetPropertyTextA: LocalAlloc Failed %d\n",status);
|
|
goto CleanExit;
|
|
}
|
|
|
|
}
|
|
__try {
|
|
|
|
//
|
|
// Create unicode versions of the strings
|
|
//
|
|
if(ARGUMENT_PRESENT(lpszName)) {
|
|
status = ConvertToUnicode(&lpNameW, lpszName);
|
|
if (status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetPropertyTextA:ConvertToUnicodeFailed %d\n",status);
|
|
}
|
|
}
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
status = GetExceptionCode();
|
|
if (status != EXCEPTION_ACCESS_VIOLATION) {
|
|
MPR_LOG(ERROR,"WNetGetPropertyTextA:Unexpected Exception 0x%lx\n",status);
|
|
}
|
|
status = WN_BAD_POINTER;
|
|
}
|
|
|
|
if (status != WN_SUCCESS) {
|
|
goto CleanExit;
|
|
}
|
|
|
|
//
|
|
// Call the Unicode version of the function.
|
|
//
|
|
status = WNetGetPropertyTextW(
|
|
iButton,
|
|
nPropSel,
|
|
lpNameW,
|
|
lpButtonNameW,
|
|
buttonnameBufSizeW,
|
|
nType ) ;
|
|
|
|
if (status == WN_SUCCESS) {
|
|
//
|
|
// Convert the returned Unicode strings back to ansi.
|
|
//
|
|
status = ConvertToAnsi(lpszButtonName, lpButtonNameW);
|
|
if(status != WN_SUCCESS) {
|
|
MPR_LOG1(ERROR,"WNetGetProprtyTextA: ConvertToAnsi Failed %d\n",status);
|
|
}
|
|
}
|
|
|
|
CleanExit:
|
|
//
|
|
// Free up any resources that were allocated by this function.
|
|
//
|
|
|
|
if(lpNameW != NULL) {
|
|
LocalFree(lpNameW);
|
|
}
|
|
if(lpButtonNameW != NULL) {
|
|
LocalFree(lpButtonNameW);
|
|
}
|
|
|
|
if (status != NO_ERROR) {
|
|
SetLastError(status);
|
|
}
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
DWORD APIENTRY
|
|
WNetFormatNetworkNameA(
|
|
IN LPCSTR lpProvider,
|
|
IN LPCSTR lpRemoteName,
|
|
OUT LPSTR lpFormattedName,
|
|
IN OUT LPDWORD lpnLength, // In characters!
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwAveCharPerLine
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
LPBYTE tempBuffer = NULL;
|
|
ANSI_PARM AParm[4];
|
|
UNICODE_PARM UParm[4];
|
|
|
|
AParm[0].lpcstr = lpProvider;
|
|
AParm[1].lpcstr = lpRemoteName;
|
|
AParm[2].lpvoid = lpFormattedName;
|
|
AParm[3].lpdword = lpnLength;
|
|
|
|
status = InputParmsToUnicode("SSB", AParm, UParm, &tempBuffer);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = WNetFormatNetworkNameW(
|
|
UParm[0].lpwstr,
|
|
UParm[1].lpwstr,
|
|
UParm[2].lpwstr,
|
|
lpnLength,
|
|
dwFlags,
|
|
dwAveCharPerLine
|
|
);
|
|
|
|
if (status == WN_SUCCESS)
|
|
{
|
|
status = OutputBufferToAnsi(
|
|
'S', UParm[2].lpbyte, lpFormattedName, lpnLength);
|
|
}
|
|
}
|
|
|
|
LocalFree(tempBuffer);
|
|
|
|
if (status != NO_ERROR)
|
|
{
|
|
SetLastError(status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
DWORD
|
|
MprMakeUnicodeNetRes(
|
|
IN LPNETRESOURCEA lpNetResourceA,
|
|
OUT LPNETRESOURCEW lpNetResourceW,
|
|
IN DWORD dwUsedNetResFields
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts and copies data from an ansi NetResource
|
|
structure to a unicode NetResource structure.
|
|
|
|
Since we don't want to modify a NetResource structure that the
|
|
user passes in, we need to have a separate one for unicode.
|
|
It is not acceptable to simply modify the pointers in the ansi
|
|
structure to point to unicode strings.
|
|
|
|
Any pointers in the lpNetResourceA structure that are NULL will have
|
|
their counterpart in lpNetResourceW set to NULL.
|
|
|
|
Arguments:
|
|
|
|
dwUsedFields - A bitmask indicating which fields are used in the
|
|
net resource structure. All unused fields will be set to
|
|
NULL in the lpNetResourceW structure. All used fields will
|
|
be converted to Unicode.
|
|
The lpNetResourceW structure must be freed by calling MprFreeNetResW
|
|
even if an error is returned or an AV occurs.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
UINT iField;
|
|
|
|
//
|
|
// Initialize the string fields of the unicode structure to NULL
|
|
// so that it can be freed by MprFreeNetResW even if an AV occurs
|
|
// while accessing the ansi structure.
|
|
//
|
|
lpNetResourceW->lpLocalName = NULL;
|
|
lpNetResourceW->lpRemoteName = NULL;
|
|
lpNetResourceW->lpComment = NULL;
|
|
lpNetResourceW->lpProvider = NULL;
|
|
|
|
//
|
|
// Copy the DWORD sized objects to the unicode structure.
|
|
//
|
|
lpNetResourceW->dwScope = lpNetResourceA->dwScope;
|
|
lpNetResourceW->dwType = lpNetResourceA->dwType ;
|
|
lpNetResourceW->dwDisplayType = lpNetResourceA->dwDisplayType ;
|
|
lpNetResourceW->dwUsage = lpNetResourceA->dwUsage;
|
|
|
|
//
|
|
// Convert the Strings and place pointers in the unicode structure.
|
|
//
|
|
for (iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if ( (dwUsedNetResFields & (1 << iField)) &&
|
|
(* pSTRING_FIELDA(lpNetResourceA, iField) != NULL) )
|
|
{
|
|
status = ConvertToUnicode(
|
|
pSTRING_FIELDW(lpNetResourceW, iField),
|
|
*pSTRING_FIELDA(lpNetResourceA, iField) );
|
|
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
MPR_LOG1(ERROR,"MprMakeUnicodeNetRes:ConvertToUnicodeFailed %d\n",status);
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
return WN_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
MprMakeAnsiNetRes(
|
|
IN LPNETRESOURCEW lpNetResourceW,
|
|
OUT LPNETRESOURCEA lpNetResourceA
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts a unicode NETRESOURCEW structure to an ansi
|
|
NETRESOURCEA structure. If lpNetResourceW and lpNetResourceA point
|
|
to the same location, the structure is simply translated "in place".
|
|
|
|
NOTE: The buffers for the strings are NOT allocated. Instead, the
|
|
unicode string buffers are re-used.
|
|
|
|
Therefore, either the unicode buffers must stay around so that the
|
|
ansi structure can point to them, or the ansi and unicode NetResource
|
|
pointers should point to the same buffer.
|
|
|
|
Arguments:
|
|
|
|
lpNetResourceW - A pointer to a NETRESOURCEW structure that contains
|
|
unicode strings.
|
|
|
|
lpNetResourceA - A pointer to a NETRESOURCEA structure that is to be
|
|
filled in. This can be a pointer to the same location as
|
|
lpNetResourceW so that the unicode structure gets replaced by
|
|
the ansi version.
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS - Successful.
|
|
|
|
Otherwise - The conversion failed.
|
|
|
|
--*/
|
|
{
|
|
DWORD status;
|
|
UINT iField;
|
|
|
|
//
|
|
// Copy the DWORD sized objects to the ansi structure.
|
|
//
|
|
lpNetResourceA->dwScope = lpNetResourceW->dwScope;
|
|
lpNetResourceA->dwType = lpNetResourceW->dwType ;
|
|
lpNetResourceA->dwDisplayType = lpNetResourceW->dwDisplayType ;
|
|
lpNetResourceA->dwUsage = lpNetResourceW->dwUsage;
|
|
|
|
|
|
//
|
|
// Convert the Strings and put the pointers in the unicode structure.
|
|
//
|
|
for (iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if (* pSTRING_FIELDW(lpNetResourceW, iField) != NULL)
|
|
{
|
|
status = ConvertToAnsi(
|
|
(LPSTR) *pSTRING_FIELDW(lpNetResourceW, iField),
|
|
*pSTRING_FIELDW(lpNetResourceW, iField) );
|
|
|
|
if (status != WN_SUCCESS)
|
|
{
|
|
MPR_LOG1(ERROR,"MprMakeAnsiNetRes:ConvertToAnsi failed %d\n",status);
|
|
return status;
|
|
}
|
|
|
|
*pSTRING_FIELDA(lpNetResourceA, iField) =
|
|
(LPSTR) *pSTRING_FIELDW(lpNetResourceW, iField);
|
|
}
|
|
}
|
|
|
|
return(WN_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
MprFreeNetResW(
|
|
IN LPNETRESOURCEW lpNetResourceW
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function frees memory that was allocated for the unicode strings
|
|
in a unicode NetResource structure.
|
|
|
|
Arguments:
|
|
|
|
lpNetResourceW - A pointer to a unicode NetResource structure.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
LocalFree(lpNetResourceW->lpLocalName);
|
|
LocalFree(lpNetResourceW->lpRemoteName);
|
|
LocalFree(lpNetResourceW->lpProvider);
|
|
LocalFree(lpNetResourceW->lpComment);
|
|
}
|
|
|
|
|
|
DWORD
|
|
MprAnsiNetResSize(
|
|
IN LPNETRESOURCEA lpNetResA
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calculates the minimum required size, in bytes, of a
|
|
buffer to hold a copy of the specified ansi NetResource structure
|
|
along with copies of its strings.
|
|
|
|
Arguments:
|
|
|
|
lpNetResA - A pointer to an ansi NetResource structure.
|
|
|
|
Return Value:
|
|
|
|
Required size in bytes.
|
|
|
|
--*/
|
|
{
|
|
DWORD cbSize = sizeof(NETRESOURCEA);
|
|
|
|
for (ULONG iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if (* pSTRING_FIELDA(lpNetResA, iField) != NULL)
|
|
{
|
|
cbSize += strlen(* pSTRING_FIELDA(lpNetResA, iField)) + 1;
|
|
}
|
|
}
|
|
|
|
return cbSize;
|
|
}
|
|
|
|
|
|
VOID
|
|
MprCopyAnsiNetRes(
|
|
OUT LPVOID lpBuffer,
|
|
IN LPNETRESOURCEA lpNetResIn
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function copies a supplied ansi NetResource structure and its
|
|
associated strings to a supplied buffer.
|
|
|
|
Arguments:
|
|
|
|
lpBuffer - A pointer to an output buffer that is assumed to be
|
|
large enough for the copy.
|
|
|
|
lpNetResIn - Pointer to the source ansi NetResource structure.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
LPNETRESOURCEA lpNetResOut = (LPNETRESOURCEA) lpBuffer;
|
|
LPSTR pNextString = (LPSTR) (lpNetResOut + 1);
|
|
|
|
//
|
|
// Copy fixed-size data and NULL pointers
|
|
//
|
|
RtlCopyMemory(lpNetResOut, lpNetResIn, sizeof(NETRESOURCEA));
|
|
|
|
//
|
|
// Copy string data
|
|
//
|
|
|
|
for (ULONG iField = 0;
|
|
iField < NUMBER_OF_NETRESFIELD;
|
|
iField++)
|
|
{
|
|
if (* pSTRING_FIELDA(lpNetResIn, iField) != NULL)
|
|
{
|
|
* pSTRING_FIELDA(lpNetResOut, iField) = pNextString;
|
|
strcpy(pNextString, * pSTRING_FIELDA(lpNetResIn, iField));
|
|
pNextString += strlen(pNextString) + 1;
|
|
// CODEWORK: The last strlen is unnecessary
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
ConvertToUnicode(
|
|
OUT LPWSTR *UnicodeOut,
|
|
IN LPCSTR AnsiIn
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates an AnsiString into a Unicode string.
|
|
A new string buffer is created by this function. If the call to
|
|
this function is successful, the caller must take responsibility for
|
|
the unicode string buffer that was allocated by this function.
|
|
The allocated buffer should be free'd with a call to LocalFree.
|
|
|
|
Arguments:
|
|
|
|
AnsiIn - This is a pointer to an ansi string that is to be converted.
|
|
|
|
UnicodeOut - This is a pointer to a location where the pointer to the
|
|
unicode string is to be placed.
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS - The conversion was successful.
|
|
|
|
Otherwise - The conversion was unsuccessful. In this case a buffer for
|
|
the unicode string was not allocated.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS ntStatus;
|
|
DWORD bufSize;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
LPWSTR buffer;
|
|
|
|
//
|
|
// Allocate a buffer for the unicode string.
|
|
//
|
|
|
|
bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
|
|
|
|
*UnicodeOut = buffer = (LPWSTR) LocalAlloc( LMEM_FIXED, bufSize);
|
|
|
|
if (buffer == NULL) {
|
|
|
|
KdPrint(("[ConvertToUnicode]LocalAlloc Failure %ld\n",GetLastError()));
|
|
|
|
return(GetLastError());
|
|
}
|
|
|
|
//
|
|
// Initialize the string structures
|
|
//
|
|
RtlInitAnsiString( &ansiString, AnsiIn );
|
|
|
|
unicodeString.Buffer = buffer;
|
|
unicodeString.MaximumLength = (USHORT)bufSize;
|
|
unicodeString.Length = 0;
|
|
|
|
//
|
|
// Call the conversion function.
|
|
//
|
|
ntStatus = RtlAnsiStringToUnicodeString (
|
|
&unicodeString, // Destination
|
|
&ansiString, // Source
|
|
(BOOLEAN)FALSE); // Allocate the destination
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
|
|
KdPrint(("[ConvertToUnicode]RtlAnsiStringToUnicodeString Failure %lx\n",
|
|
ntStatus));
|
|
|
|
return(RtlNtStatusToDosError(ntStatus));
|
|
}
|
|
|
|
//
|
|
// Note that string as returned by Rtl isn't yet terminated "properly."
|
|
// (unicodeString.Buffer is *UnicodeOut - see above)
|
|
//
|
|
unicodeString.Buffer[unicodeString.Length/sizeof(TCHAR)] = 0;
|
|
|
|
return(WN_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
ConvertToAnsi(
|
|
OUT LPSTR AnsiOut,
|
|
IN LPTSTR UnicodeIn
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates a UnicodeString into an Ansi string.
|
|
|
|
BEWARE!
|
|
It is assumed that the buffer pointed to by AnsiOut is large
|
|
enough to hold the Unicode String. Check sizes first.
|
|
|
|
If it is desired, UnicodeIn and AnsiIn can point to the same
|
|
location. Since the ansi string will always be smaller than the
|
|
unicode string, translation can take place in the same buffer.
|
|
|
|
Arguments:
|
|
|
|
UnicodeIn - This is a pointer to a unicode that is to be converted.
|
|
|
|
AnsiOut - This is a pointer to a buffer that will contain the
|
|
ansi string on return from this function call.
|
|
|
|
Return Value:
|
|
|
|
WN_SUCCESS - If the conversion was successful.
|
|
|
|
Otherwise - The conversion was unsuccessful.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS ntStatus;
|
|
UNICODE_STRING unicodeString;
|
|
ANSI_STRING ansiString;
|
|
|
|
//
|
|
// Initialize the string structures
|
|
//
|
|
RtlInitUnicodeString( &unicodeString, UnicodeIn);
|
|
|
|
ansiString.Buffer = AnsiOut;
|
|
ansiString.MaximumLength = unicodeString.MaximumLength;
|
|
ansiString.Length = 0;
|
|
|
|
//
|
|
// Call the conversion function.
|
|
//
|
|
ntStatus = RtlUnicodeStringToAnsiString (
|
|
&ansiString, // Destination
|
|
&unicodeString, // Source
|
|
(BOOLEAN)FALSE); // Don't allocate the destination
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
|
|
|
|
KdPrint(("[ConvertToAnsi]RtlUnicodeStringToAnsiString Failure %lx\n",
|
|
ntStatus));
|
|
|
|
return(RtlNtStatusToDosError(ntStatus));
|
|
}
|
|
|
|
ansiString.Buffer[ansiString.Length] = 0;
|
|
|
|
return(WN_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
ResourceArrayToAnsi(
|
|
IN DWORD NumElements,
|
|
IN OUT LPVOID NetResourceArray
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts an array of NETRESOURCEW structures to an array of
|
|
NETRESOURCEA structures. The conversion takes place "in place".
|
|
The unicode structures are written over to contain ansi elements.
|
|
The strings are written over to contain ansi strings.
|
|
|
|
Arguments:
|
|
|
|
NumElements - Indicates the number of elements in the NetResourceArray.
|
|
|
|
NetResourceArray - A pointer to a buffer that contains an array
|
|
of unicode NETRESOURCE structures on entry and an array of
|
|
ansi NETRESOURCE structures on exit. The buffer also contains
|
|
the strings associated with these structures.
|
|
|
|
Return Value:
|
|
|
|
Indicates the number of elements that are successfully converted.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
DWORD status;
|
|
LPNETRESOURCEA netResourceAPtr;
|
|
LPNETRESOURCEW netResourceWPtr;
|
|
|
|
//
|
|
// Initialize the pointers to be used in the conversion.
|
|
//
|
|
netResourceWPtr = (LPNETRESOURCEW)NetResourceArray;
|
|
netResourceAPtr = (LPNETRESOURCEA)NetResourceArray;
|
|
|
|
//
|
|
// Loop through and convert each structure.
|
|
//
|
|
for (i=0; i<NumElements; i++) {
|
|
|
|
status = MprMakeAnsiNetRes(&(netResourceWPtr[i]),&(netResourceAPtr[i]));
|
|
if (status != WN_SUCCESS) {
|
|
//
|
|
// If the conversion fails for any reason, return the
|
|
// number of successful conversions so far.
|
|
//
|
|
return(i);
|
|
}
|
|
}
|
|
return(NumElements);
|
|
}
|